From 7f42caa6c0f9c139b8a8f1b3acd61422834609ba Mon Sep 17 00:00:00 2001 From: Philip Barclay Date: Mon, 18 Nov 2019 19:10:45 +1300 Subject: [PATCH 001/559] Added YPR to web interface --- sonoff/xsns_32_mpu6050.ino | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index 58915efc9..d212a45e2 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -56,6 +56,7 @@ int16_t MPU_6050_temperature = 0; VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements VectorFloat gravity; // [x, y, z] gravity vector float euler[3]; // [psi, theta, phi] Euler angle container + float yawPitchRoll[3]; // [yaw, pitch roll] Yaw-pitch-roll container } MPU6050_DMP; MPU6050_DMP MPU6050_dmp; @@ -78,6 +79,7 @@ void MPU_6050PerformReading(void) mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); + mpu6050.dmpGetYawPitchRoll(MPU6050_dmp.yawPitchRoll, &MPU6050_dmp.q, &MPU6050_dmp.gravity); MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; @@ -161,7 +163,13 @@ const char HTTP_SNS_AXIS[] PROGMEM = "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = - "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = +#ifdef USE_MPU6050_DMP + "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}" // {s} = , {m} = , {e} = +#endif // USE_MPU_DMP + ; #endif // USE_WEBSERVER #define D_JSON_AXIS_AX "AccelXAxis" From dac6ce1e54b73eda46da6d22b8058550184a393d Mon Sep 17 00:00:00 2001 From: Philip Barclay Date: Mon, 18 Nov 2019 21:33:34 +1300 Subject: [PATCH 002/559] Added YPR results to webserver and JSON output if DMP enabled. --- tasmota/xsns_32_mpu6050.ino | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/tasmota/xsns_32_mpu6050.ino b/tasmota/xsns_32_mpu6050.ino index 7b26101a1..6f3cff5e8 100644 --- a/tasmota/xsns_32_mpu6050.ino +++ b/tasmota/xsns_32_mpu6050.ino @@ -69,7 +69,7 @@ MPU6050 mpu6050; void MPU_6050PerformReading(void) { #ifdef USE_MPU6050_DMP - mpu6050.resetFIFO(); // with a default dampling rate of 200Hz, we create a delay of approx. 5ms with a complete read cycle + mpu6050.resetFIFO(); // with a default sampling rate of 200Hz, we create a delay of approx. 5ms with a complete read cycle MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); @@ -147,6 +147,10 @@ void MPU_6050Detect(void) } } +#define D_YAW "Yaw" +#define D_PITCH "Pitch" +#define D_ROLL "Roll" + #ifdef USE_WEBSERVER const char HTTP_SNS_AXIS[] PROGMEM = "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = @@ -154,13 +158,13 @@ const char HTTP_SNS_AXIS[] PROGMEM = "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = - "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; // {s} = , {m} = , {e} = #ifdef USE_MPU6050_DMP +const char HTTP_SNS_YPR[] PROGMEM = "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" // {s} = , {m} = , {e} = - "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" // {s} = , {m} = , {e} = - "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}" // {s} = , {m} = , {e} = -#endif // USE_MPU_DMP - ; + "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" // {s} = , {m} = , {e} = + "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}"; // {s} = , {m} = , {e} = +#endif // USE_MPU6050_DMP #endif // USE_WEBSERVER #define D_JSON_AXIS_AX "AccelXAxis" @@ -169,6 +173,9 @@ const char HTTP_SNS_AXIS[] PROGMEM = #define D_JSON_AXIS_GX "GyroXAxis" #define D_JSON_AXIS_GY "GyroYAxis" #define D_JSON_AXIS_GZ "GyroZAxis" +#define D_JSON_YAW "Yaw" +#define D_JSON_PITCH "Pitch" +#define D_JSON_ROLL "Roll" void MPU_6050Show(bool json) { @@ -203,8 +210,20 @@ void MPU_6050Show(bool json) snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); char json_axis_gz[25]; snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); +#ifdef USE_MPU6050_DMP + char json_ypr_y[25]; + snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), MPU6050_dmp.yawPitchRoll[0]); + char json_ypr_p[25]; + snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), MPU6050_dmp.yawPitchRoll[1]); + char json_ypr_r[25]; + snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), MPU6050_dmp.yawPitchRoll[2]); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz, + json_ypr_y, json_ypr_p, json_ypr_r); +#else ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); +#endif // USE_MPU6050_DMP #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ @@ -212,6 +231,7 @@ void MPU_6050Show(bool json) } else { WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); + WSContentSend_PD(HTTP_SNS_YPR, MPU6050_dmp.yawPitchRoll[0], MPU6050_dmp.yawPitchRoll[1], MPU6050_dmp.yawPitchRoll[2]); #endif // USE_WEBSERVER } } From fe63e5cca2fcae187e7d6c3e3211db0414667821 Mon Sep 17 00:00:00 2001 From: Philip Barclay Date: Fri, 29 Nov 2019 21:07:39 +1300 Subject: [PATCH 003/559] Stringification and conversion from radians to degrees. --- tasmota/xsns_32_mpu6050.ino | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tasmota/xsns_32_mpu6050.ino b/tasmota/xsns_32_mpu6050.ino index 6f3cff5e8..bcec100b0 100644 --- a/tasmota/xsns_32_mpu6050.ino +++ b/tasmota/xsns_32_mpu6050.ino @@ -196,6 +196,14 @@ void MPU_6050Show(bool json) dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); char axis_gz[33]; dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); +#ifdef USE_MPU6050_DMP + char axis_yaw[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[0] / PI * 180.0, Settings.flag2.axis_resolution, axis_yaw); + char axis_pitch[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[1] / PI * 180.0, Settings.flag2.axis_resolution, axis_pitch); + char axis_roll[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[2] / PI * 180.0, Settings.flag2.axis_resolution, axis_roll); +#endif // USE_MPU6050_DMP if (json) { char json_axis_ax[25]; @@ -212,11 +220,11 @@ void MPU_6050Show(bool json) snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); #ifdef USE_MPU6050_DMP char json_ypr_y[25]; - snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), MPU6050_dmp.yawPitchRoll[0]); + snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), axis_yaw); char json_ypr_p[25]; - snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), MPU6050_dmp.yawPitchRoll[1]); + snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), axis_pitch); char json_ypr_r[25]; - snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), MPU6050_dmp.yawPitchRoll[2]); + snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), axis_roll); ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s%s%s%s}"), D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz, json_ypr_y, json_ypr_p, json_ypr_r); @@ -231,7 +239,9 @@ void MPU_6050Show(bool json) } else { WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); - WSContentSend_PD(HTTP_SNS_YPR, MPU6050_dmp.yawPitchRoll[0], MPU6050_dmp.yawPitchRoll[1], MPU6050_dmp.yawPitchRoll[2]); +#ifdef USE_MPU6050_DMP + WSContentSend_PD(HTTP_SNS_YPR, axis_yaw, axis_pitch, axis_roll); +#endif // USE_MPU6050_DMP #endif // USE_WEBSERVER } } From 8ed7257c9b8952e2e0d542461096ad0ad72db2a5 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 5 Dec 2019 15:16:57 +0100 Subject: [PATCH 004/559] Update platformio_override_sample.ini --- platformio_override_sample.ini | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index ad669b0a7..6cbd749c4 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -28,6 +28,7 @@ default_envs = [common] platform = ${core_active.platform} +platform_packages = ${core_active.platform_packages} build_flags = ${core_active.build_flags} ; *** Use settings from file user_config_override.h -DUSE_CONFIG_OVERRIDE @@ -72,6 +73,7 @@ build_flags = ${core_2_6_1.build_flags} ;platform = ${core_2_6_2.platform} ;build_flags = ${core_2_6_2.build_flags} ;platform = ${core_stage.platform} +;platform_packages = ${core_stage.platform_packages} ;build_flags = ${core_stage.build_flags} @@ -165,7 +167,8 @@ build_flags = ${esp82xx_defaults.build_flags} [core_stage] ; *** Esp8266 core for Arduino version latest beta -platform = https://github.com/platformio/platform-espressif8266.git#feature/stage +platform = espressif8266@2.3.1 +platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC From 246663dd9dd5759e64a6ceec1be3ae4abdab1485 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Thu, 5 Dec 2019 15:18:24 +0100 Subject: [PATCH 005/559] Update platformio_tasmota_env.ini --- platformio_tasmota_env.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 46e71d7af..38aaf2223 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -1,5 +1,6 @@ [env] platform = ${common.platform} +platform_packages = ${common.platform_packages} framework = ${common.framework} board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} From 3b4b549e61fafa8e9b2ed912fe7f196a6c7fe219 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Thu, 5 Dec 2019 16:34:30 +0100 Subject: [PATCH 006/559] sml mbus decoder syntax update support for byte order --- tasmota/xsns_53_sml.ino | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino index ddc3f8db0..7aa0fd22d 100755 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/xsns_53_sml.ino @@ -499,7 +499,10 @@ const uint8_t meter[]= #define USE_SML_MEDIAN_FILTER // max number of vars , may be adjusted +#ifndef MAX_VARS #define MAX_VARS 20 +#endif + // max number of meters , may be adjusted #define MAX_METERS 5 double meter_vars[MAX_VARS]; @@ -1427,14 +1430,25 @@ void SML_Decode(uint8_t index) { //ignore mp+=2; cp++; - } else if (!strncmp(mp,"uuuuuuuu",8)) { + } else if (!strncmp(mp,"UUuuUUuu",8)) { uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); ebus_dval=val; mbus_dval=val; mp+=8; cp+=4; - } - else if (*mp=='u' && *(mp+1)=='u' && *(mp+2)=='u' && *(mp+3)=='u'){ + } else if (*mp=='U' && *(mp+1)=='U' && *(mp+2)=='u' && *(mp+3)=='u'){ + uint16_t val = cp[1]|(cp[0]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (!strncmp(mp,"SSssSSss",8)) { + int32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + ebus_dval=val; + mbus_dval=val; + mp+=8; + cp+=4; + } else if (*mp=='u' && *(mp+1)=='u' && *(mp+2)=='U' && *(mp+3)=='U'){ uint16_t val = cp[0]|(cp[1]<<8); mbus_dval=val; ebus_dval=val; @@ -1442,17 +1456,25 @@ void SML_Decode(uint8_t index) { cp+=2; } else if (*mp=='u' && *(mp+1)=='u') { uint8_t val = *cp++; + mbus_dval=val; ebus_dval=val; mp+=2; - } - else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='s' && *(mp+3)=='s') { + } else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='S' && *(mp+3)=='S') { int16_t val = *cp|(*(cp+1)<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (*mp=='S' && *(mp+1)=='S' && *(mp+2)=='s' && *(mp+3)=='s') { + int16_t val = cp[1]|(cp[0]<<8); + mbus_dval=val; ebus_dval=val; mp+=4; cp+=2; } else if (*mp=='s' && *(mp+1)=='s') { int8_t val = *cp++; + mbus_dval=val; ebus_dval=val; mp+=2; } From 726883b16884fa03e893cdf0d3d6864c44b04efa Mon Sep 17 00:00:00 2001 From: Bohdan Kmit Date: Thu, 5 Dec 2019 20:54:30 +0200 Subject: [PATCH 007/559] Allow to build Minimal firmware with TLS support --- tasmota/tasmota_post.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index be3b503f0..cc47e3fc1 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -512,7 +512,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_ARDUINO_OTA // Disable support for Arduino OTA #undef USE_DOMOTICZ // Disable Domoticz #undef USE_HOME_ASSISTANT // Disable Home Assistant -#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set +//#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver #undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code) From b347c53846c84f17f246ab25cb373c87a0c747b6 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Thu, 5 Dec 2019 18:06:17 -0300 Subject: [PATCH 008/559] Fix markdown of Problem Issue Report --- .github/ISSUE_TEMPLATE/Bug_report.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index f9622222f..4b4027bf8 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -38,31 +38,31 @@ _Make sure your have performed every step and checked the applicable boxes befor - [ ] Self-compiled - [ ] IDE / Compiler used: _____ - [ ] Flashing tools used: _____ -- [ ] Provide the output of command: ``Backlog Template; Module; GPIO 255``: - ``` +- [ ] Provide the output of command: `Backlog Template; Module; GPIO 255`: +``` Configuration output here: - ``` -- [ ] If using rules, provide the output of this command: ``Backlog Rule1; Rule2; Rule3``: - ``` +``` +- [ ] If using rules, provide the output of this command: `Backlog Rule1; Rule2; Rule3`: +``` Rules output here: - ``` -- [ ] Provide the output of this command: ``Status 0``: - ``` +``` +- [ ] Provide the output of this command: `Status 0`: +``` STATUS 0 output here: - ``` +``` - [ ] Provide the output of the Console log output when you experience your issue; if applicable: - _(Please use_ ``weblog 4`` _for more debug information)_ - ``` + _(Please use_ `weblog 4` _for more debug information)_ +``` Console output here: - ``` +``` ### TO REPRODUCE _Steps to reproduce the behavior:_ From 9d9f3b0ca7b4b6ee7db5e8f8afaa44f1d7ca88fd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 6 Dec 2019 11:10:15 +0100 Subject: [PATCH 009/559] Change log buffer size from 520 to 700 Change log buffer size from 520 to 700 characters accomodating full rule text (#7110) --- tasmota/CHANGELOG.md | 7 ++++++- tasmota/tasmota.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 1706dbbb3..e92cfd27a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,7 +5,12 @@ - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) - Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) - Fix WS2812 power control (#7090) -- Change light color schemes 2, 3 and 4 from color wheel to Hue driven +- Change light color schemes 2, 3 and 4 from color wheel to Hue driven with user Saturation control +- Change log buffer size from 520 to 700 characters accomodating full rule text (#7110) +- Add rule var ``%topic%`` (#5522) +- Add rule triggers ``tele_power1#state`` and multiple ``tele-wifi1#xxx`` (#7093) +- Add experimental support for stepper motor shutter control +- Add optional USE_MQTT_TLS to tasmota-minimal.bin (#7115) ## Released diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index d9e55bd15..cefef3a06 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -119,7 +119,7 @@ const uint16_t INPUT_BUFFER_SIZE = 520; // Max number of characters in (seri const uint16_t FLOATSZ = 16; // Max number of characters in float result from dtostrfd (max 32) const uint16_t CMDSZ = 24; // Max number of characters in command const uint16_t TOPSZ = 100; // Max number of characters in topic string -const uint16_t LOGSZ = 520; // Max number of characters in log +const uint16_t LOGSZ = 700; // Max number of characters in log const uint16_t MIN_MESSZ = 893; // Min number of characters in MQTT message const uint8_t SENSOR_MAX_MISS = 5; // Max number of missed sensor reads before deciding it's offline From 8c5c95747c4344522c4dc343f311e1123026dcbd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 6 Dec 2019 12:18:46 +0100 Subject: [PATCH 010/559] Bump version 7.1.2.1 --- README.md | 2 +- RELEASENOTES.md | 4 +++- tasmota/CHANGELOG.md | 19 +++++++++++++------ tasmota/tasmota_version.h | 2 +- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7b101df63..acb6430d5 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v7.1.1.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v7.1.2.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 51d078352..0baecb42a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -51,4 +51,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) - Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) -- Change light color schemes 2, 3 and 4 from color wheel to Hue driven +- Fix WS2812 power control (#7090) +- Change light color schemes 2, 3 and 4 from color wheel to Hue driven with user Saturation control +- Change log buffer size from 520 to 700 characters accomodating full rule text (#7110) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e92cfd27a..2fe8fac75 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,18 @@ ## Unreleased (development) +### 7.1.2.1 20191206 + +- Add rule var ``%topic%`` (#5522) +- Add rule triggers ``tele_power1#state`` and multiple ``tele-wifi1#xxx`` (#7093) +- Add experimental support for stepper motor shutter control +- Add optional USE_MQTT_TLS to tasmota-minimal.bin (#7115) + +## Released + +### 7.1.2 20191206 + +- Maintenance Release + ### 7.1.1.1 20191201 - Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) @@ -7,12 +20,6 @@ - Fix WS2812 power control (#7090) - Change light color schemes 2, 3 and 4 from color wheel to Hue driven with user Saturation control - Change log buffer size from 520 to 700 characters accomodating full rule text (#7110) -- Add rule var ``%topic%`` (#5522) -- Add rule triggers ``tele_power1#state`` and multiple ``tele-wifi1#xxx`` (#7093) -- Add experimental support for stepper motor shutter control -- Add optional USE_MQTT_TLS to tasmota-minimal.bin (#7115) - -## Released ### 7.1.1 20191201 diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 54e4c165f..7b2207950 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010101; +const uint32_t VERSION = 0x07010201; #endif // _TASMOTA_VERSION_H_ From 00fd7f2f7c62765a95fcde751cf297f1bd37d2d3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 6 Dec 2019 15:02:05 +0100 Subject: [PATCH 011/559] Bump version to 7.1.2.2 Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) --- tasmota/CHANGELOG.md | 4 +++ tasmota/i18n.h | 1 + tasmota/settings.h | 4 +-- tasmota/settings.ino | 21 +++++++++++++++ tasmota/support.ino | 51 +++++++++++++++++++++++++++++-------- tasmota/support_command.ino | 46 +++++++++++++++++++++++++++++++-- tasmota/support_rtc.ino | 4 ++- tasmota/tasmota.ino | 2 -- tasmota/tasmota_version.h | 2 +- tasmota/xnrg_02_cse7766.ino | 2 +- 10 files changed, 117 insertions(+), 20 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 2fe8fac75..4bb5447ad 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 7.1.2.2 20191206 + +- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) + ### 7.1.2.1 20191206 - Add rule var ``%topic%`` (#5522) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 5de4b7a1d..dfa998474 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -285,6 +285,7 @@ #define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALDELIMITER "SerialDelimiter" #define D_CMND_BAUDRATE "Baudrate" +#define D_CMND_SERIALCONFIG "SerialConfig" #define D_CMND_TEMPLATE "Template" #define D_JSON_NAME "NAME" #define D_JSON_GPIO "GPIO" diff --git a/tasmota/settings.h b/tasmota/settings.h index 554711cad..f464a24cb 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -269,9 +269,7 @@ struct SYSCFG { uint8_t free_1d6[10]; // 1D6 SysBitfield4 flag4; // 1E0 - - uint8_t free_1e4; // 1E4 - + uint8_t serial_config; // 1E4 uint8_t wifi_output_power; // 1E5 uint8_t shutter_accuracy; // 1E6 uint8_t mqttlog_level; // 1E7 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 9ca979b45..f6113be46 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -156,6 +156,23 @@ const char kWebColors[] PROGMEM = COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|" COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT; +enum TasmotaSerialConfig { + TS_SERIAL_5N1, TS_SERIAL_6N1, TS_SERIAL_7N1, TS_SERIAL_8N1, + TS_SERIAL_5N2, TS_SERIAL_6N2, TS_SERIAL_7N2, TS_SERIAL_8N2, + TS_SERIAL_5E1, TS_SERIAL_6E1, TS_SERIAL_7E1, TS_SERIAL_8E1, + TS_SERIAL_5E2, TS_SERIAL_6E2, TS_SERIAL_7E2, TS_SERIAL_8E2, + TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1, + TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 }; + +const uint8_t kTasmotaSerialConfig[] PROGMEM = { + SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1, + SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2, + SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1, + SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2, + SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1, + SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2 +}; + /*********************************************************************************************\ * RTC memory \*********************************************************************************************/ @@ -670,6 +687,7 @@ void SettingsDefaultSet2(void) // for (uint32_t i = 1; i < MAX_PULSETIMERS; i++) { Settings.pulse_timer[i] = 0; } // Serial + Settings.serial_config = TS_SERIAL_8N1; Settings.baudrate = APP_BAUDRATE / 300; Settings.sbaudrate = SOFT_BAUDRATE / 300; Settings.serial_delimiter = 0xff; @@ -1155,6 +1173,9 @@ void SettingsDelta(void) if (Settings.version < 0x07000004) { Settings.wifi_output_power = 170; } + if (Settings.version < 0x07010202) { + Settings.serial_config = TS_SERIAL_8N1; + } Settings.version = VERSION; SettingsSave(1); diff --git a/tasmota/support.ino b/tasmota/support.ino index 8ce7f2840..f44d14eb7 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -737,19 +737,50 @@ int GetStateNumber(char *state_text) return state_number; } +String GetSerialConfig(void) +{ + // Settings.serial_config layout + // b000000xx - 5, 6, 7 or 8 data bits + // b00000x00 - 1 or 2 stop bits + // b000xx000 - None, Even or Odd parity + + const char kParity[] = "NEOI"; + + char config[4]; + config[0] = '5' + (Settings.serial_config & 0x3); + config[1] = kParity[(Settings.serial_config >> 3) & 0x3]; + config[2] = '1' + ((Settings.serial_config >> 2) & 0x1); + config[3] = '\0'; + return String(config); +} + +void SetSerialBegin(uint32_t baudrate) +{ + if (seriallog_level) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Set Serial to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); + delay(100); + } + Serial.flush(); + Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); + delay(10); + Serial.println(); +} + +void SetSerialConfig(uint32_t serial_config) +{ + if (serial_config == Settings.serial_config) { return; } + if (serial_config > TS_SERIAL_8O2) { return; } + + Settings.serial_config = serial_config; + SetSerialBegin(Serial.baudRate()); +} + void SetSerialBaudrate(int baudrate) { Settings.baudrate = baudrate / 300; - if (Serial.baudRate() != baudrate) { - if (seriallog_level) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), baudrate); - } - delay(100); - Serial.flush(); - Serial.begin(baudrate, serial_config); - delay(10); - Serial.println(); - } + if (Serial.baudRate() == baudrate) { return; } + + SetSerialBegin(baudrate); } void ClaimSerial(void) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index fe8640045..070409566 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -23,7 +23,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" - D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" + D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|" D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" @@ -38,7 +38,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, &CmndModule, &CmndModules, &CmndGpio, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange, - &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, + &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig, &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, @@ -1082,6 +1082,48 @@ void CmndBaudrate(void) ResponseCmndNumber(Settings.baudrate * 300); } +void CmndSerialConfig(void) +{ + // See TasmotaSerialConfig for possible options + // SerialConfig 0..23 where 3 equals 8N1 + // SerialConfig 8N1 + + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.data_len < 3) { // Use 0..23 as serial config option + if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) { + SetSerialConfig(XdrvMailbox.payload); + } + } + else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { + uint8_t serial_config = XdrvMailbox.payload -5; // Data bits 5, 6, 7 or 8, No parity and 1 stop bit + + bool valid = true; + char parity = (XdrvMailbox.data[1] & 0xdf); + if ('E' == parity) { + serial_config += 0x08; // Even parity + } + else if ('O' == parity) { + serial_config += 0x10; // Odd parity + } + else if ('N' != parity) { + valid = false; + } + + if ('2' == XdrvMailbox.data[2]) { + serial_config += 0x04; // Stop bits 2 + } + else if ('1' != XdrvMailbox.data[2]) { + valid = false; + } + + if (valid) { + SetSerialConfig(serial_config); + } + } + } + ResponseCmndChar(GetSerialConfig().c_str()); +} + void CmndSerialSend(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index ffb7239a6..27ef66ec7 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -379,7 +379,9 @@ void RtcSecond(void) Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle } uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id - if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || (Rtc.ntp_sync_minute == uptime_minute))) || ntp_force_sync ) ) { + if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || // Never synced + (Rtc.ntp_sync_minute == uptime_minute))) || // Re-sync every hour + ntp_force_sync ) ) { // Forced sync Rtc.ntp_time = sntp_get_current_timestamp(); if (Rtc.ntp_time > START_VALID_TIME) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) ntp_force_sync = false; diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index e10dfdb63..5cf0a430f 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -74,8 +74,6 @@ const char kCodeImage[] PROGMEM = "tasmota|minimal|sensors|knx|basic|display|ir" * Global variables \*********************************************************************************************/ -SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit - WiFiUDP PortUdp; // UDP Syslog and Alexa unsigned long feature_drv1; // Compiled driver feature map diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 7b2207950..929924840 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010201; +const uint32_t VERSION = 0x07010202; #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino index 339d4fee2..d52ee9ca3 100644 --- a/tasmota/xnrg_02_cse7766.ino +++ b/tasmota/xnrg_02_cse7766.ino @@ -211,7 +211,7 @@ void CseDrvInit(void) { if ((3 == pin[GPIO_CSE7766_RX]) && (1 == pin[GPIO_CSE7766_TX])) { // As it uses 8E1 currently only hardware serial is supported baudrate = 4800; - serial_config = SERIAL_8E1; + Settings.serial_config = TS_SERIAL_8E1; if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255 } From ee37c258e64c397225090c082686e2a471a7836e Mon Sep 17 00:00:00 2001 From: Laurent Dong Date: Fri, 6 Dec 2019 10:12:13 -0500 Subject: [PATCH 012/559] Embeded IF statement in backlog did not been processed The backlog_mutex blocked the execution of IF statement during call ExecuteCommand(), because all IF statement need to use backlog to perform commands. --- tasmota/tasmota.ino | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 5cf0a430f..306250549 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -349,15 +349,18 @@ void BacklogLoop(void) { if (TimeReached(backlog_delay)) { if (!BACKLOG_EMPTY && !backlog_mutex) { - backlog_mutex = true; #ifdef SUPPORT_IF_STATEMENT - ExecuteCommand((char*)backlog.shift().c_str(), SRC_BACKLOG); + backlog_mutex = true; + String cmd = backlog.shift(); + backlog_mutex = false; + ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); #else + backlog_mutex = true; ExecuteCommand((char*)backlog[backlog_pointer].c_str(), SRC_BACKLOG); backlog_pointer++; if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } -#endif backlog_mutex = false; +#endif } } } From 5f290f8b64cb215d4bc2d4f2f69397e43e9c1d2b Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Fri, 6 Dec 2019 20:10:04 -0300 Subject: [PATCH 013/559] Reverting changes in tele message due to backwards compatibility --- tasmota/support_tasmota.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 2f54cec7d..96cec9c5a 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -565,7 +565,7 @@ void MqttShowState(void) if (i == LightDevice()) { LightState(1); } // call it only once } else { #endif - ResponseAppend_P(PSTR(",\"%s\":{\"STATE\":\"%s\"}"), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 + ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1 GetStateText(bitRead(power, i-1))); #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { @@ -609,7 +609,7 @@ bool MqttShowSensor(void) if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":{\"STATE\":\"%s\"}"), i +1, GetStateText(swm ^ SwitchLastState(i))); + ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); } } XsnsCall(FUNC_JSON_APPEND); From 5a0febc64ef515fd3873b3f6b842ac4d669fda55 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 7 Dec 2019 10:41:29 +0100 Subject: [PATCH 014/559] Add save call stack in RTC memory in case of crash --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 3 ++ tasmota/my_user_config.h | 3 ++ tasmota/support_command.ino | 15 +++++- tasmota/support_crash_recorder.ino | 80 ++++++++++++++++++++++++++++++ tasmota/support_wifi.ino | 1 + tasmota/tasmota.h | 2 +- 7 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 tasmota/support_crash_recorder.ino diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 4bb5447ad..10c3c6941 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 7.1.2.2 20191206 - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) +- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack ### 7.1.2.1 20191206 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index dfa998474..30fcf173e 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -208,6 +208,7 @@ #define D_STATUS9_MARGIN "PTH" #define D_STATUS10_SENSOR "SNS" #define D_STATUS11_STATUS "STS" + #define D_STATUS12_STATUS "STK" #define D_CMND_STATE "State" #define D_CMND_POWER "Power" #define D_CMND_FANSPEED "FanSpeed" @@ -292,6 +293,8 @@ #define D_JSON_FLAG "FLAG" #define D_JSON_BASE "BASE" #define D_CMND_TEMPOFFSET "TempOffset" +#define D_CMND_CRASH "Crash" + #define D_JSON_ONE_TO_CRASH "1 to crash" // Commands xdrv_01_mqtt.ino #define D_CMND_MQTTLOG "MqttLog" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 7ef154d53..46fe15def 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -268,6 +268,9 @@ //#define MY_LANGUAGE zh-CN // Chinese (Simplified) in China //#define MY_LANGUAGE zh-TW // Chinese (Traditional) in Taiwan +// -- Crash generator --------------------------- +//#define USE_CRASH // add a `Crash` command to test the crash recorder (+48 bytes) + // -- Wifi Config tools --------------------------- #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 070409566..020e57b9d 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -30,7 +30,10 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif - D_CMND_SENSOR "|" D_CMND_DRIVER; +#ifdef USE_CRASH + D_CMND_CRASH "|" +#endif + D_CMND_SENSOR "|" D_CMND_DRIVER ; void (* const TasmotaCommand[])(void) PROGMEM = { &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, @@ -44,6 +47,9 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, +#endif +#ifdef USE_CRASH + &CmndCrash, #endif &CmndSensor, &CmndDriver }; @@ -483,6 +489,13 @@ void CmndStatus(void) MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } + if ((0 == payload) || (12 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); + CrashDump(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); + } + #ifdef USE_SCRIPT_STATUS if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); #endif diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino new file mode 100644 index 000000000..be0cde11b --- /dev/null +++ b/tasmota/support_crash_recorder.ino @@ -0,0 +1,80 @@ +/* + support_crash_recorder.ino - record the call stack in RTC in cas of crash + + Copyright (C) 2019 Stephan Hadinger, Theo Arends, + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +const uint32_t dump_max_len = 64; // dump only 64 call addresses + +/** + * Save crash information in RTC memory + * This function is called automatically if ESP8266 suffers an exception + * It should be kept quick / consise to be able to execute before hardware wdt may kick in + */ +extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) { + uint32_t addr_written = 0; // how many addresses have we already written in RTC + uint32_t value; // 4 bytes buffer to write to RTC + + for (uint32_t i = stack; i < stack_end; i += 4) { + value = *((uint32_t*) i); // load value from stack + if ((value >= 0x40000000) && (value < 0x40300000)) { // keep only addresses in code area + ESP.rtcUserMemoryWrite(addr_written, (uint32_t*)&value, sizeof(value)); + addr_written++; + if (addr_written >= dump_max_len) { break; } // we store only 64 addresses + } + } + // fill the rest of RTC with zeros + value = 0; + while (addr_written < dump_max_len) { + ESP.rtcUserMemoryWrite(addr_written++, (uint32_t*)&value, sizeof(value)); + } +} + +// Generate a crash to test the crash recorder +void CmndCrash(void) +{ + if (1 == XdrvMailbox.payload) { + volatile uint32_t dummy; + dummy = *((uint32_t*) 0x00000000); // invalid address + } else { + ResponseCmndChar(D_JSON_ONE_TO_CRASH); + } +} + +// Clear the RTC dump area when we do a normal reboot, this avoids garbage data to stay in RTC +void CrashDumpClear(void) { + uint32_t value = 0; + for (uint32_t i = 0; i < dump_max_len; i++) { + ESP.rtcUserMemoryWrite(i, (uint32_t*)&value, sizeof(value)); + } +} + +/*********************************************************************************************\ + * CmndCrashDump - dump the crash history - called by `Status 12` +\*********************************************************************************************/ +void CrashDump(void) +{ + ResponseAppend_P(PSTR("{\"call_chain\":[")); + for (uint32_t i = 0; i < dump_max_len; i++) { + uint32_t value; + ESP.rtcUserMemoryRead(i, (uint32_t*)&value, sizeof(value)); + if ((value >= 0x40000000) && (value < 0x40300000)) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"%08x\""), value); + } + } + ResponseAppend_P(PSTR("]}")); +} diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 49faa0663..06d922b26 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -617,6 +617,7 @@ void WifiShutdown(void) void EspRestart(void) { WifiShutdown(); + CrashDumpClear(); // Clear the stack dump in RTC // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 ESP.reset(); } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index cefef3a06..c31bfad83 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -131,7 +131,7 @@ const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate const uint32_t SERIAL_POLLING = 100; // Serial receive polling in ms const uint32_t ZIGBEE_POLLING = 100; // Serial receive polling in ms -const uint8_t MAX_STATUS = 11; // Max number of status lines +const uint8_t MAX_STATUS = 12; // Max number of status lines const uint32_t START_VALID_TIME = 1451602800; // Time is synced and after 2016-01-01 From 7796714ba08347122994b8033f9fb26a6b165643 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 7 Dec 2019 11:00:32 +0100 Subject: [PATCH 015/559] Change from `Crash` to `Restart -1` --- tasmota/i18n.h | 2 -- tasmota/my_user_config.h | 3 --- tasmota/support_command.ino | 9 +++------ tasmota/support_crash_recorder.ino | 8 ++------ 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 30fcf173e..f913c14d2 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -293,8 +293,6 @@ #define D_JSON_FLAG "FLAG" #define D_JSON_BASE "BASE" #define D_CMND_TEMPOFFSET "TempOffset" -#define D_CMND_CRASH "Crash" - #define D_JSON_ONE_TO_CRASH "1 to crash" // Commands xdrv_01_mqtt.ino #define D_CMND_MQTTLOG "MqttLog" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 46fe15def..7ef154d53 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -268,9 +268,6 @@ //#define MY_LANGUAGE zh-CN // Chinese (Simplified) in China //#define MY_LANGUAGE zh-TW // Chinese (Traditional) in Taiwan -// -- Crash generator --------------------------- -//#define USE_CRASH // add a `Crash` command to test the crash recorder (+48 bytes) - // -- Wifi Config tools --------------------------- #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 020e57b9d..23ce1f22e 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -29,9 +29,6 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" -#endif -#ifdef USE_CRASH - D_CMND_CRASH "|" #endif D_CMND_SENSOR "|" D_CMND_DRIVER ; @@ -47,9 +44,6 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, -#endif -#ifdef USE_CRASH - &CmndCrash, #endif &CmndSensor, &CmndDriver }; @@ -577,6 +571,9 @@ void CmndRestart(void) restart_flag = 2; ResponseCmndChar(D_JSON_RESTARTING); break; + case -1: + CmndCrash(); // force a crash + break; case 99: AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); EspRestart(); diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino index be0cde11b..abd948c39 100644 --- a/tasmota/support_crash_recorder.ino +++ b/tasmota/support_crash_recorder.ino @@ -46,12 +46,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack // Generate a crash to test the crash recorder void CmndCrash(void) { - if (1 == XdrvMailbox.payload) { - volatile uint32_t dummy; - dummy = *((uint32_t*) 0x00000000); // invalid address - } else { - ResponseCmndChar(D_JSON_ONE_TO_CRASH); - } + volatile uint32_t dummy; + dummy = *((uint32_t*) 0x00000000); } // Clear the RTC dump area when we do a normal reboot, this avoids garbage data to stay in RTC From 7e1e85eba95355fd814f393be8739b3f6a4008d4 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 7 Dec 2019 11:01:48 +0100 Subject: [PATCH 016/559] Add save call stack in RTC memory in case of crash --- tasmota/support_command.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 23ce1f22e..2ba09629e 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -45,7 +45,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif - &CmndSensor, &CmndDriver }; + &CmndSensor, &CmndDriver}; const char kWifiConfig[] PROGMEM = D_WCFG_0_RESTART "||" D_WCFG_2_WIFIMANAGER "||" D_WCFG_4_RETRY "|" D_WCFG_5_WAIT "|" D_WCFG_6_SERIAL "|" D_WCFG_7_WIFIMANAGER_RESET_ONLY; From edc2dc5c7947fedf80e2f55c34d875ef2d5d294a Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 7 Dec 2019 11:02:37 +0100 Subject: [PATCH 017/559] Add save call stack in RTC memory in case of crash --- tasmota/support_command.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 2ba09629e..f6baeef4e 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -30,7 +30,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif - D_CMND_SENSOR "|" D_CMND_DRIVER ; + D_CMND_SENSOR "|" D_CMND_DRIVER; void (* const TasmotaCommand[])(void) PROGMEM = { &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, @@ -45,7 +45,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif - &CmndSensor, &CmndDriver}; + &CmndSensor, &CmndDriver }; const char kWifiConfig[] PROGMEM = D_WCFG_0_RESTART "||" D_WCFG_2_WIFIMANAGER "||" D_WCFG_4_RETRY "|" D_WCFG_5_WAIT "|" D_WCFG_6_SERIAL "|" D_WCFG_7_WIFIMANAGER_RESET_ONLY; From a8c0c4e312015ba96e3d07b3b8effa24638a972d Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 7 Dec 2019 15:01:39 +0100 Subject: [PATCH 018/559] Remove any whitespace in TlsKey base64 --- tasmota/xdrv_02_mqtt.ino | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 49f35d579..a6994ebfb 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1071,6 +1071,19 @@ void CmndTlsKey(void) { } memcpy_P(spi_buffer, tls_spi_start, tls_spi_len); + // remove any white space from the base64 + char *cursor = XdrvMailbox.data; + uint32_t offset = 0; + while (1) { + *cursor = *(cursor + offset); + if ((' ' == *cursor) || ('\t' == *cursor) || ('\n' == *cursor)) { // if space found, remove this char until end of string + offset++; + } else { + if (0 == *cursor) { break; } + cursor++; + } + } + // allocate buffer for decoded base64 uint32_t bin_len = decode_base64_length((unsigned char*)XdrvMailbox.data); uint8_t *bin_buf = nullptr; From 2686ccb117e55462ae9d02c87732b48d5373bccb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 7 Dec 2019 16:50:10 +0100 Subject: [PATCH 019/559] Revert "Merge pull request #7134 from s-hadinger/crashrecorder_rtc" This reverts commit 758b25507822ad3c862216feb4c1af4fd5d53e78, reversing changes made to f4993736a500ffada2a110236dab04a93220d7e0. --- tasmota/CHANGELOG.md | 1 - tasmota/i18n.h | 1 - tasmota/support_command.ino | 10 ---- tasmota/support_crash_recorder.ino | 76 ------------------------------ tasmota/support_wifi.ino | 1 - tasmota/tasmota.h | 2 +- 6 files changed, 1 insertion(+), 90 deletions(-) delete mode 100644 tasmota/support_crash_recorder.ino diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 10c3c6941..4bb5447ad 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,7 +3,6 @@ ### 7.1.2.2 20191206 - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) -- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack ### 7.1.2.1 20191206 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index f913c14d2..dfa998474 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -208,7 +208,6 @@ #define D_STATUS9_MARGIN "PTH" #define D_STATUS10_SENSOR "SNS" #define D_STATUS11_STATUS "STS" - #define D_STATUS12_STATUS "STK" #define D_CMND_STATE "State" #define D_CMND_POWER "Power" #define D_CMND_FANSPEED "FanSpeed" diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index f6baeef4e..070409566 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -483,13 +483,6 @@ void CmndStatus(void) MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } - if ((0 == payload) || (12 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); - CrashDump(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); - } - #ifdef USE_SCRIPT_STATUS if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); #endif @@ -571,9 +564,6 @@ void CmndRestart(void) restart_flag = 2; ResponseCmndChar(D_JSON_RESTARTING); break; - case -1: - CmndCrash(); // force a crash - break; case 99: AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); EspRestart(); diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino deleted file mode 100644 index abd948c39..000000000 --- a/tasmota/support_crash_recorder.ino +++ /dev/null @@ -1,76 +0,0 @@ -/* - support_crash_recorder.ino - record the call stack in RTC in cas of crash - - Copyright (C) 2019 Stephan Hadinger, Theo Arends, - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -const uint32_t dump_max_len = 64; // dump only 64 call addresses - -/** - * Save crash information in RTC memory - * This function is called automatically if ESP8266 suffers an exception - * It should be kept quick / consise to be able to execute before hardware wdt may kick in - */ -extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) { - uint32_t addr_written = 0; // how many addresses have we already written in RTC - uint32_t value; // 4 bytes buffer to write to RTC - - for (uint32_t i = stack; i < stack_end; i += 4) { - value = *((uint32_t*) i); // load value from stack - if ((value >= 0x40000000) && (value < 0x40300000)) { // keep only addresses in code area - ESP.rtcUserMemoryWrite(addr_written, (uint32_t*)&value, sizeof(value)); - addr_written++; - if (addr_written >= dump_max_len) { break; } // we store only 64 addresses - } - } - // fill the rest of RTC with zeros - value = 0; - while (addr_written < dump_max_len) { - ESP.rtcUserMemoryWrite(addr_written++, (uint32_t*)&value, sizeof(value)); - } -} - -// Generate a crash to test the crash recorder -void CmndCrash(void) -{ - volatile uint32_t dummy; - dummy = *((uint32_t*) 0x00000000); -} - -// Clear the RTC dump area when we do a normal reboot, this avoids garbage data to stay in RTC -void CrashDumpClear(void) { - uint32_t value = 0; - for (uint32_t i = 0; i < dump_max_len; i++) { - ESP.rtcUserMemoryWrite(i, (uint32_t*)&value, sizeof(value)); - } -} - -/*********************************************************************************************\ - * CmndCrashDump - dump the crash history - called by `Status 12` -\*********************************************************************************************/ -void CrashDump(void) -{ - ResponseAppend_P(PSTR("{\"call_chain\":[")); - for (uint32_t i = 0; i < dump_max_len; i++) { - uint32_t value; - ESP.rtcUserMemoryRead(i, (uint32_t*)&value, sizeof(value)); - if ((value >= 0x40000000) && (value < 0x40300000)) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"%08x\""), value); - } - } - ResponseAppend_P(PSTR("]}")); -} diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 06d922b26..49faa0663 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -617,7 +617,6 @@ void WifiShutdown(void) void EspRestart(void) { WifiShutdown(); - CrashDumpClear(); // Clear the stack dump in RTC // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 ESP.reset(); } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index c31bfad83..cefef3a06 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -131,7 +131,7 @@ const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate const uint32_t SERIAL_POLLING = 100; // Serial receive polling in ms const uint32_t ZIGBEE_POLLING = 100; // Serial receive polling in ms -const uint8_t MAX_STATUS = 12; // Max number of status lines +const uint8_t MAX_STATUS = 11; // Max number of status lines const uint32_t START_VALID_TIME = 1451602800; // Time is synced and after 2016-01-01 From f3a5b033c8ca527da001dc34121a45f269f98f78 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 7 Dec 2019 18:32:39 +0100 Subject: [PATCH 020/559] Add save call stack in RTC memory in case of crash Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack (#7114, #5883) --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 1 + tasmota/support_command.ino | 10 ++++ tasmota/support_crash_recorder.ino | 78 ++++++++++++++++++++++++++++++ tasmota/support_wifi.ino | 1 + tasmota/tasmota.h | 2 +- 6 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 tasmota/support_crash_recorder.ino diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 4bb5447ad..10c3c6941 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 7.1.2.2 20191206 - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) +- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack ### 7.1.2.1 20191206 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index dfa998474..f913c14d2 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -208,6 +208,7 @@ #define D_STATUS9_MARGIN "PTH" #define D_STATUS10_SENSOR "SNS" #define D_STATUS11_STATUS "STS" + #define D_STATUS12_STATUS "STK" #define D_CMND_STATE "State" #define D_CMND_POWER "Power" #define D_CMND_FANSPEED "FanSpeed" diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 070409566..f6baeef4e 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -483,6 +483,13 @@ void CmndStatus(void) MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } + if ((0 == payload) || (12 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); + CrashDump(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); + } + #ifdef USE_SCRIPT_STATUS if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); #endif @@ -564,6 +571,9 @@ void CmndRestart(void) restart_flag = 2; ResponseCmndChar(D_JSON_RESTARTING); break; + case -1: + CmndCrash(); // force a crash + break; case 99: AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); EspRestart(); diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino new file mode 100644 index 000000000..2c217e2ba --- /dev/null +++ b/tasmota/support_crash_recorder.ino @@ -0,0 +1,78 @@ +/* + support_crash_recorder.ino - record the call stack in RTC in cas of crash + + Copyright (C) 2019 Stephan Hadinger, Theo Arends, + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +const uint32_t dump_max_len = 63; // dump only 64 call addresses + +/** + * Save crash information in RTC memory + * This function is called automatically if ESP8266 suffers an exception + * It should be kept quick / consise to be able to execute before hardware wdt may kick in + */ +extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) { + uint32_t addr_written = 0; // how many addresses have we already written in RTC + uint32_t value; // 4 bytes buffer to write to RTC + + for (uint32_t i = stack; i < stack_end; i += 4) { + value = *((uint32_t*) i); // load value from stack + if ((value >= 0x40000000) && (value < 0x40300000)) { // keep only addresses in code area + ESP.rtcUserMemoryWrite(addr_written, (uint32_t*)&value, sizeof(value)); + addr_written++; + if (addr_written >= dump_max_len) { break; } // we store only 63 addresses + } + } + // fill the rest of RTC with the amount of addresses + value = addr_written; + while (addr_written < dump_max_len +1) { + ESP.rtcUserMemoryWrite(addr_written++, (uint32_t*)&value, sizeof(value)); + } +} + +// Generate a crash to test the crash recorder +void CmndCrash(void) +{ + volatile uint32_t dummy; + dummy = *((uint32_t*) 0x00000000); +} + +// Clear the RTC dump counter when we do a normal reboot, this avoids garbage data to stay in RTC +void CrashDumpClear(void) { + uint32_t value = 0; + ESP.rtcUserMemoryWrite(dump_max_len, (uint32_t*)&value, sizeof(value)); +} + +/*********************************************************************************************\ + * CmndCrashDump - dump the crash history - called by `Status 12` +\*********************************************************************************************/ +void CrashDump(void) +{ + ResponseAppend_P(PSTR("{\"call_chain\":[")); + + uint32_t value; + ESP.rtcUserMemoryRead(dump_max_len, (uint32_t*)&value, sizeof(value)); + uint32_t count = value & 0x3F; + + for (uint32_t i = 0; i < count; i++) { + ESP.rtcUserMemoryRead(i, (uint32_t*)&value, sizeof(value)); + if ((value >= 0x40000000) && (value < 0x40300000)) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"%08x\""), value); + } + } + ResponseAppend_P(PSTR("]}")); +} diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 49faa0663..06d922b26 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -617,6 +617,7 @@ void WifiShutdown(void) void EspRestart(void) { WifiShutdown(); + CrashDumpClear(); // Clear the stack dump in RTC // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 ESP.reset(); } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index cefef3a06..c31bfad83 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -131,7 +131,7 @@ const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate const uint32_t SERIAL_POLLING = 100; // Serial receive polling in ms const uint32_t ZIGBEE_POLLING = 100; // Serial receive polling in ms -const uint8_t MAX_STATUS = 11; // Max number of status lines +const uint8_t MAX_STATUS = 12; // Max number of status lines const uint32_t START_VALID_TIME = 1451602800; // Time is synced and after 2016-01-01 From 368e9cc34028500725734e0cc050f28ef06fbe0d Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Sat, 7 Dec 2019 15:20:47 -0300 Subject: [PATCH 021/559] Update xdrv_12_home_assistant.ino --- tasmota/xdrv_12_home_assistant.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 38c36ead1..22c0e370e 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -86,6 +86,7 @@ const char HASS_DISCOVER_SENSOR[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") "\"avty_t\":\"%s\"," // tele/dualr2/LWT + "\"frc_upd\":true," // force update for better graph representation "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline From dae622b2cb2aa0e2e0ecf3cfc770b3cd87f24c24 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Sat, 7 Dec 2019 15:44:33 -0300 Subject: [PATCH 022/559] Update my_user_config.h --- tasmota/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 7ef154d53..d780f3d35 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -284,7 +284,7 @@ #define DOMOTICZ_OUT_TOPIC "domoticz/out" // Domoticz Output Topic // -- MQTT - Home Assistant Discovery ------------- -#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+7k code) +#define USE_HOME_ASSISTANT // Enable Home Assistant Discovery Support (+4.1k code, +6 bytes mem) #define HOME_ASSISTANT_DISCOVERY_PREFIX "homeassistant" // Home Assistant discovery prefix // -- MQTT - TLS - AWS IoT ------------------------ From fd079c57a3fd3861e6540f2e975b0e3a8796d333 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 7 Dec 2019 23:25:56 +0100 Subject: [PATCH 023/559] Fix crashdump bad JSON --- tasmota/support_crash_recorder.ino | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino index 2c217e2ba..c89fa681b 100644 --- a/tasmota/support_crash_recorder.ino +++ b/tasmota/support_crash_recorder.ino @@ -69,10 +69,8 @@ void CrashDump(void) for (uint32_t i = 0; i < count; i++) { ESP.rtcUserMemoryRead(i, (uint32_t*)&value, sizeof(value)); - if ((value >= 0x40000000) && (value < 0x40300000)) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"%08x\""), value); - } + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"%08x\""), value); } ResponseAppend_P(PSTR("]}")); } From 29d5d68ca05c807d987cb744d0673f438219552e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 8 Dec 2019 13:18:15 +0100 Subject: [PATCH 024/559] Redesign Exception reporting Redesign Exception reporting removing exception details from both MQTT info and Status 1. Now consolidated in Status 12 if available. --- tasmota/support.ino | 6 ---- tasmota/support_command.ino | 17 +++++---- tasmota/support_crash_recorder.ino | 55 ++++++++++++++++++------------ tasmota/xdrv_02_mqtt.ino | 2 +- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index f44d14eb7..14f21db01 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -107,12 +107,6 @@ String GetResetReason(void) } } -String GetResetReasonInfo(void) -{ - // "Fatal exception:0 flag:2 (EXCEPTION) epc1:0x704022a7 epc2:0x00000000 epc3:0x00000000 excvaddr:0x00000000 depc:0x00000000" - return (ResetReason() == REASON_EXCEPTION_RST) ? ESP.getResetInfo() : GetResetReason(); -} - /*********************************************************************************************\ * Miscellaneous \*********************************************************************************************/ diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index f6baeef4e..09495f55a 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -334,6 +334,9 @@ void CmndStatus(void) if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } // SetOption3 - Enable MQTT if (!energy_flg && (9 == payload)) { payload = 99; } + bool exception_flg = (ResetReason() == REASON_EXCEPTION_RST); + if (!exception_flg && (12 == payload)) { payload = 99; } + if ((0 == payload) || (99 == payload)) { uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; #ifdef USE_SONOFF_IFAN @@ -369,7 +372,7 @@ void CmndStatus(void) D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), baudrate, Settings.mqtt_grptopic, Settings.ota_url, - GetResetReasonInfo().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, + GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); } @@ -483,11 +486,13 @@ void CmndStatus(void) MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } - if ((0 == payload) || (12 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); - CrashDump(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); + if (exception_flg) { + if ((0 == payload) || (12 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); + CrashDump(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); + } } #ifdef USE_SCRIPT_STATUS diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino index c89fa681b..87009bbc5 100644 --- a/tasmota/support_crash_recorder.ino +++ b/tasmota/support_crash_recorder.ino @@ -1,5 +1,5 @@ /* - support_crash_recorder.ino - record the call stack in RTC in cas of crash + support_crash_recorder.ino - record the call stack in RTC in case of crash Copyright (C) 2019 Stephan Hadinger, Theo Arends, @@ -17,30 +17,30 @@ along with this program. If not, see . */ -const uint32_t dump_max_len = 63; // dump only 64 call addresses +const uint32_t crash_magic = 0x53415400; // Stack trace magic number (TASx) +const uint32_t crash_rtc_offset = 32; // Offset in RTC memory skipping OTA used block +const uint32_t crash_dump_max_len = 31; // Dump only 31 call addresses to satisfy max JSON length of about 600 characters /** * Save crash information in RTC memory * This function is called automatically if ESP8266 suffers an exception * It should be kept quick / consise to be able to execute before hardware wdt may kick in */ -extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) { +extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) +{ uint32_t addr_written = 0; // how many addresses have we already written in RTC uint32_t value; // 4 bytes buffer to write to RTC for (uint32_t i = stack; i < stack_end; i += 4) { value = *((uint32_t*) i); // load value from stack if ((value >= 0x40000000) && (value < 0x40300000)) { // keep only addresses in code area - ESP.rtcUserMemoryWrite(addr_written, (uint32_t*)&value, sizeof(value)); + ESP.rtcUserMemoryWrite(crash_rtc_offset + addr_written, (uint32_t*)&value, sizeof(value)); addr_written++; - if (addr_written >= dump_max_len) { break; } // we store only 63 addresses + if (addr_written >= crash_dump_max_len) { break; } // we store only 31 addresses } } - // fill the rest of RTC with the amount of addresses - value = addr_written; - while (addr_written < dump_max_len +1) { - ESP.rtcUserMemoryWrite(addr_written++, (uint32_t*)&value, sizeof(value)); - } + value = crash_magic + addr_written; + ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); } // Generate a crash to test the crash recorder @@ -51,26 +51,39 @@ void CmndCrash(void) } // Clear the RTC dump counter when we do a normal reboot, this avoids garbage data to stay in RTC -void CrashDumpClear(void) { +void CrashDumpClear(void) +{ uint32_t value = 0; - ESP.rtcUserMemoryWrite(dump_max_len, (uint32_t*)&value, sizeof(value)); + ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); } /*********************************************************************************************\ * CmndCrashDump - dump the crash history - called by `Status 12` \*********************************************************************************************/ + void CrashDump(void) { - ResponseAppend_P(PSTR("{\"call_chain\":[")); + ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""), + resetInfo.exccause, // Exception Cause + GetResetReason().c_str(), // Reset Reason + resetInfo.epc1, // Exception Progam Counter + resetInfo.epc2, // Exception Progam Counter - High-Priority Interrupt 1 + resetInfo.epc3, // Exception Progam Counter - High-Priority Interrupt 2 + resetInfo.excvaddr, // Exception Virtual Address Register - Virtual address that caused last fetch, load, or store exception + resetInfo.depc); // Double Exception Program Counter uint32_t value; - ESP.rtcUserMemoryRead(dump_max_len, (uint32_t*)&value, sizeof(value)); - uint32_t count = value & 0x3F; - - for (uint32_t i = 0; i < count; i++) { - ESP.rtcUserMemoryRead(i, (uint32_t*)&value, sizeof(value)); - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"%08x\""), value); + ESP.rtcUserMemoryRead(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); + if (crash_magic == (value & 0xFFFFFF00)) { + ResponseAppend_P(PSTR(",\"CallChain\":[")); + uint32_t count = value & 0x3F; + for (uint32_t i = 0; i < count; i++) { + ESP.rtcUserMemoryRead(crash_rtc_offset +i, (uint32_t*)&value, sizeof(value)); + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"%08x\""), value); + } + ResponseAppend_P(PSTR("]")); } - ResponseAppend_P(PSTR("]}")); + + ResponseJsonEnd(); } diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index a6994ebfb..d31d0a860 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -555,7 +555,7 @@ void MqttConnected(void) MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); } #endif // USE_WEBSERVER - Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), GetResetReasonInfo().c_str()); + Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), GetResetReason().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); MqttPublishAllPowerState(); if (Settings.tele_period) { From c06008935878a84676c8df9eb95d8aabb7acab27 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 8 Dec 2019 13:37:18 +0100 Subject: [PATCH 025/559] Bump version to 7.1.2.3 Redesign Exception reporting removing exception details from both MQTT info and Status 1. Now consolidated in Status 12 if available. --- tasmota/CHANGELOG.md | 4 ++++ tasmota/tasmota_version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 10c3c6941..240bca728 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 7.1.2.3 20191208 + +- Redesign Exception reporting removing exception details from both MQTT info and Status 1. Now consolidated in Status 12 if available. + ### 7.1.2.2 20191206 - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 929924840..9b94a31f5 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010202; +const uint32_t VERSION = 0x07010203; #endif // _TASMOTA_VERSION_H_ From 46566952a052b1a4a08f4f86547373160c0c7f20 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Sun, 8 Dec 2019 19:42:08 +0100 Subject: [PATCH 026/559] report Signal Strength in dBm over MQTT Also include dBm in debug log and in WebIf information display. --- tasmota/i18n.h | 1 + tasmota/support.ino | 2 +- tasmota/support_tasmota.ino | 5 +++-- tasmota/xdrv_01_webserver.ino | 6 +++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index f913c14d2..9b0457e19 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -134,6 +134,7 @@ #define D_JSON_SELECTED "selected" #define D_JSON_SERIALRECEIVED "SerialReceived" #define D_JSON_SET "Set" +#define D_JSON_SIGNAL "Signal" #define D_JSON_SSID "SSId" #define D_JSON_STARTDST "StartDST" // Start Daylight Savings Time #define D_JSON_STARTED "Started" diff --git a/tasmota/support.ino b/tasmota/support.ino index 14f21db01..ef3b8d9ee 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -51,7 +51,7 @@ void OsWatchTicker(void) uint32_t last_run = abs(t - oswatch_last_loop_time); #ifdef DEBUG_THEO - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d, last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), last_run); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), last_run); #endif // DEBUG_THEO if (last_run >= (OSWATCH_RESET_TIME * 1000)) { // AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_OSWATCH " " D_BLOCKED_LOOP ". " D_RESTARTING)); // Save iram space diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 96cec9c5a..2ab8fa0d7 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -583,8 +583,9 @@ void MqttShowState(void) MqttShowPWMState(); } - ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), - Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); + ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), + Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), + WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str()); } void MqttPublishTeleState(void) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 48e2cd26a..15707d224 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1638,11 +1638,11 @@ void HandleWifiConfiguration(void) int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); int auth = WiFi.encryptionType(indices[i]); char encryption[20]; - WSContentSend_P(PSTR("
%s (%d) %s %d%%
"), + WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), HtmlEscape(WiFi.SSID(indices[i])).c_str(), WiFi.channel(indices[i]), GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality + quality, WiFi.RSSI() ); delay(0); @@ -1970,7 +1970,7 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, Settings.friendlyname[i]); } WSContentSend_P(PSTR("}1}2 ")); // Empty line - WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI())); + WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI()); WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : ""); if (static_cast(WiFi.localIP()) != 0) { WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str()); From 6c3d02928617fa34291088df1d87ee2d75098e60 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Fri, 29 Nov 2019 17:28:25 +0000 Subject: [PATCH 027/559] Implement capability for setting CORS to a specific website instead of just enable for all websites --- tasmota/i18n.h | 1 + tasmota/language/bg-BG.h | 1 + tasmota/language/cs-CZ.h | 1 + tasmota/language/de-DE.h | 1 + tasmota/language/el-GR.h | 1 + tasmota/language/en-GB.h | 1 + tasmota/language/es-ES.h | 1 + tasmota/language/fr-FR.h | 1 + tasmota/language/he-HE.h | 1 + tasmota/language/hu-HU.h | 1 + tasmota/language/it-IT.h | 1 + tasmota/language/ko-KO.h | 1 + tasmota/language/nl-NL.h | 1 + tasmota/language/pl-PL.h | 1 + tasmota/language/pt-BR.h | 1 + tasmota/language/pt-PT.h | 1 + tasmota/language/ru-RU.h | 1 + tasmota/language/sk-SK.h | 1 + tasmota/language/sv-SE.h | 1 + tasmota/language/tr-TR.h | 1 + tasmota/language/uk-UK.h | 1 + tasmota/language/zh-CN.h | 1 + tasmota/language/zh-TW.h | 1 + tasmota/my_user_config.h | 6 +++--- tasmota/settings.h | 5 +++-- tasmota/settings.ino | 13 +++++++++++++ tasmota/tasmota_version.h | 2 +- tasmota/xdrv_01_webserver.ino | 25 ++++++++++++++++++------- 28 files changed, 61 insertions(+), 13 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 9b0457e19..f4fde64b3 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -335,6 +335,7 @@ #define D_CMND_WEBSENSOR "WebSensor" #define D_CMND_EMULATION "Emulation" #define D_CMND_SENDMAIL "Sendmail" +#define D_CMND_CORS "CORS" // Commands xdrv_03_energy.ino #define D_CMND_POWERLOW "PowerLow" diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 4bc5feebd..d39aba5f6 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Хладна" #define D_COMMAND "Команда" #define D_CONNECTED "Свързан" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Брой" #define D_COUNTER "Брояч" #define D_CURRENT "Ток" // As in Voltage and Current diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 8800368a3..1d7c6f381 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Studené světlo" #define D_COMMAND "Příkaz" #define D_CONNECTED "...připojeno" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Počítej" #define D_COUNTER "Počítadlo" #define D_CURRENT "Proud" // As in Voltage and Current diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index c50de823f..6569dd232 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "kalt" #define D_COMMAND "Befehl" #define D_CONNECTED "verbunden" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "zählen" #define D_COUNTER "Zähler" #define D_CURRENT "Strom" // As in Voltage and Current diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index 4fe47ae6d..f8b9c9614 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -72,6 +72,7 @@ #define D_COMMAND "Εντολή" #define D_CONNECTED "Συνδεδεμένο" #define D_COUNT "Μέτρηση" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNTER "Μετρητής" #define D_CURRENT "Ένταση" // As in Voltage and Current #define D_DATA "Δεδομένα" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index a98087a18..257a34c86 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Cold" #define D_COMMAND "Command" #define D_CONNECTED "Connected" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Count" #define D_COUNTER "Counter" #define D_CURRENT "Current" // As in Voltage and Current diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 014d822a9..7527bb77a 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Fría" #define D_COMMAND "Comando" #define D_CONNECTED "Conectado" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Conteo" #define D_COUNTER "Contador" #define D_CURRENT "Corriente" // As in Voltage and Current diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 4704c49e7..236df351b 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Froid" #define D_COMMAND "Commande" #define D_CONNECTED "Connecté" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Compte" #define D_COUNTER "Compteur" #define D_CURRENT "Courant" // As in Voltage and Current diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index 69387ceca..ac4dadb8e 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "אור קר" #define D_COMMAND "פקודה" #define D_CONNECTED "מחובר" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "סופר" #define D_COUNTER "מונה" #define D_CURRENT "נוכחי" // As in Voltage and Current diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 58f85eb22..62806fa46 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Hideg fény" #define D_COMMAND "Parancs" #define D_CONNECTED "Csatlakoztatva" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Szám" #define D_COUNTER "Számláló" #define D_CURRENT "Áramerősség" // As in Voltage and Current diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 3029f37da..0585c12d8 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Fredda" #define D_COMMAND "Comando" #define D_CONNECTED "Connesso" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Conteggio" #define D_COUNTER "Contatore" #define D_CURRENT "Corrente" // As in Voltage and Current diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index c6236a05f..bff508474 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -72,6 +72,7 @@ #define D_COMMAND "커맨드" #define D_CONNECTED "연결됨" #define D_COUNT "횟수" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNTER "Counter" #define D_CURRENT "전류" // As in Voltage and Current #define D_DATA "Data" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index da20ff1d7..75d841ddc 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -72,6 +72,7 @@ #define D_COMMAND "Opdracht" #define D_CONNECTED "Verbonden" #define D_COUNT "Aantal" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNTER "Teller" #define D_CURRENT "Stroom" // As in Voltage and Current #define D_DATA "Data" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 7a631f95f..8f5af6813 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Zimny" #define D_COMMAND "Komenda" #define D_CONNECTED "Połączony" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Licz" #define D_COUNTER "Licznik" #define D_CURRENT "Prąd" // As in Voltage and Current diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 2eb81f294..0efa57789 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Luz fria" #define D_COMMAND "Comando" #define D_CONNECTED "Ligado" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Contagem" #define D_COUNTER "Contador" #define D_CURRENT "Corrente" // As in Voltage and Current diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 46bafdef6..a6299c0c8 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Luz Fria" #define D_COMMAND "Comando" #define D_CONNECTED "Ligado" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Contagem" #define D_COUNTER "Contador" #define D_CURRENT "Corrente" // As in Voltage and Current diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 5ff9bff50..3bd788ede 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Холодный" #define D_COMMAND "Команда" #define D_CONNECTED "Соединен" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Подсчет" #define D_COUNTER "Счетчик" #define D_CURRENT "Ток" // As in Voltage and Current diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index 57ec74f8a..a64e49e01 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Studené svetlo" #define D_COMMAND "Príkaz" #define D_CONNECTED "...pripojené" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Počítaj" #define D_COUNTER "Počítadlo" #define D_CURRENT "Prúd" // As in Voltage and Current diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index aee8fd25d..51ffc2ae3 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Kallt" #define D_COMMAND "Kommando" #define D_CONNECTED "Ansluten" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Räkna" #define D_COUNTER "Räknare" #define D_CURRENT "Ström" // As in Voltage and Current diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 78612dace..6bc48c40f 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Soğuk" #define D_COMMAND "Komut" #define D_CONNECTED "Bağlandı" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Sayı" #define D_COUNTER "Sayaç" #define D_CURRENT "Current" // As in Voltage and Current diff --git a/tasmota/language/uk-UK.h b/tasmota/language/uk-UK.h index f16d66648..b4a314630 100644 --- a/tasmota/language/uk-UK.h +++ b/tasmota/language/uk-UK.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "Холодний" #define D_COMMAND "Команда" #define D_CONNECTED "Під'єднано" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "Розмір" #define D_COUNTER "Лічильник" #define D_CURRENT "Струм" // As in Voltage and Current diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 2c8610400..21aa63be3 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "冷" #define D_COMMAND "命令:" #define D_CONNECTED "已连接" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "数量:" #define D_COUNTER "计数器" #define D_CURRENT "电流" // As in Voltage and Current diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index e5ef8926a..1d78f181e 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -71,6 +71,7 @@ #define D_COLDLIGHT "冷" #define D_COMMAND "命令:" #define D_CONNECTED "已連接" +#define D_CORS_DOMAIN "CORS Domain" #define D_COUNT "數量:" #define D_COUNTER "Counter" #define D_CURRENT "電流" // As in Voltage and Current diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index d780f3d35..c643f0a6d 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -132,7 +132,7 @@ #define WEB_PASSWORD "" // [WebPassword] Web server Admin mode Password for WEB_USERNAME (empty string = Disable) #define FRIENDLY_NAME "Tasmota" // [FriendlyName] Friendlyname up to 32 characters used by webpages and Alexa #define EMULATION EMUL_NONE // [Emulation] Select Belkin WeMo (single relay/light) or Hue Bridge emulation (multi relay/light) (EMUL_NONE, EMUL_WEMO or EMUL_HUE) - +#define CORS_DOMAIN "" // [CorsDomain] CORS Domain for preflight requests // -- HTTP GUI Colors ----------------------------- // HTML hex color codes. Only 3 and 6 digit hex string values are supported!! See https://www.w3schools.com/colors/colors_hex.asp // Light theme - pre v7 @@ -219,7 +219,7 @@ #define APP_BLINKTIME 10 // [BlinkTime] Time in 0.1 Sec to blink/toggle power for relay 1 #define APP_BLINKCOUNT 10 // [BlinkCount] Number of blinks (0 = 32000) #define APP_SLEEP 0 // [Sleep] Sleep time to lower energy consumption (0 = Off, 1 - 250 mSec), -#define PWM_MAX_SLEEP 10 // Sleep will be lowered to this value when light is on, to avoid flickering +#define PWM_MAX_SLEEP 10 // Sleep will be lowered to this value when light is on, to avoid flickering #define KEY_DEBOUNCE_TIME 50 // [ButtonDebounce] Number of mSeconds button press debounce time #define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message @@ -291,7 +291,7 @@ // Using TLS starting with version v6.5.0.16 compilation will only work using Core 2.4.2 and 2.5.2. No longer supported: 2.3.0 //#define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake) // #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use. (+2.2k code, +1.9k mem during connection handshake) - // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates + // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates // #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) // #define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+11.9k code, +0.4k mem) // Note: you need to generate a private key + certificate per device and update 'tasmota/tasmota_aws_iot.cpp' diff --git a/tasmota/settings.h b/tasmota/settings.h index f464a24cb..6da25a36b 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -86,7 +86,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531) uint32_t hardware_energy_total : 1; // bit 22 (v6.6.0.15) - SetOption72 - Enable hardware energy total counter as reference (#6561) - uint32_t cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS + uint32_t ex_cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS uint32_t ds18x20_internal_pullup : 1; // bit 24 (v7.0.0.1) - SetOption74 - Enable internal pullup for single DS18x20 sensor uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled @@ -438,7 +438,8 @@ struct SYSCFG { uint8_t web_color2[2][3]; // EA0 - Needs to be on integer / 3 distance from web_color - uint8_t free_ea4[326]; // EA6 + char cors_domain[33]; // EC1 + uint8_t free_ea4[293]; // EA6 uint32_t i2c_drivers[3]; // FEC I2cDriver uint32_t cfg_timestamp; // FF8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index f6113be46..50f4fe4a6 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -140,6 +140,10 @@ #ifndef DEFAULT_LIGHT_COMPONENT #define DEFAULT_LIGHT_COMPONENT 255 #endif +#ifndef CORS_ENABLED_ALL +#define CORS_ENABLED_ALL "*" +#endif + enum WebColors { COL_TEXT, COL_BACKGROUND, COL_FORM, @@ -718,6 +722,7 @@ void SettingsDefaultSet2(void) Settings.weblog_level = WEB_LOG_LEVEL; strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password)); Settings.flag3.mdns_enabled = MDNS_ENABLED; + strlcpy(Settings.cors_domain, CORS_DOMAIN, sizeof(Settings.cors_domain)); // Button // Settings.flag.button_restrict = 0; @@ -1177,6 +1182,14 @@ void SettingsDelta(void) Settings.serial_config = TS_SERIAL_8N1; } + if (Settings.version < 0x07010204) { + if (Settings.flag3.ex_cors_enabled == 1) { + strlcpy(Settings.cors_domain, CORS_ENABLED_ALL, sizeof(Settings.cors_domain)); + } else { + Settings.cors_domain[0] = 0; + } + } + Settings.version = VERSION; SettingsSave(1); } diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 9b94a31f5..a0cbe1e41 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010203; +const uint32_t VERSION = 0x07010204; #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 15707d224..28620e21f 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -414,7 +414,8 @@ const char HTTP_FORM_WIFI[] PROGMEM = "

" D_AP1_PASSWORD "

" "

" D_AP2_SSID " (" STA_SSID2 ")

" "

" D_AP2_PASSWORD "

" - "

" D_HOSTNAME " (%s)

"; + "

" D_HOSTNAME " (%s)

" + "

" D_CORS_DOMAIN "

"; const char HTTP_FORM_LOG1[] PROGMEM = "
 " D_LOGGING_PARAMETERS " " @@ -673,8 +674,8 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true) void HttpHeaderCors(void) { - if (Settings.flag3.cors_enabled) { // SetOption73 - Enable HTTP CORS - WebServer->sendHeader(F("Access-Control-Allow-Origin"), F("*")); + if (Settings.cors_domain[0] != 0) { + WebServer->sendHeader(F("Access-Control-Allow-Origin"), Settings.cors_domain); } } @@ -1654,7 +1655,7 @@ void HandleWifiConfiguration(void) } // As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception - WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname); + WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname, Settings.cors_domain); WSContentSend_P(HTTP_FORM_END); } @@ -1678,6 +1679,8 @@ void WifiSaveSettings(void) if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); } + WebGetArg("c", tmp, sizeof(tmp)); + strlcpy(Settings.cors_domain, (!strlen(tmp)) ? CORS_DOMAIN : tmp, sizeof(Settings.cors_domain)); WebGetArg("s1", tmp, sizeof(tmp)); strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); WebGetArg("s2", tmp, sizeof(tmp)); @@ -1686,7 +1689,7 @@ void WifiSaveSettings(void) strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); WebGetArg("p2", tmp, sizeof(tmp)); strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1]); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.cors_domain); } /*-------------------------------------------------------------------------------------------*/ @@ -2698,7 +2701,7 @@ const char kWebCommands[] PROGMEM = "|" // No prefix #ifdef USE_SENDMAIL D_CMND_SENDMAIL "|" #endif - D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR; + D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR "|" D_CMND_CORS; void (* const WebCommand[])(void) PROGMEM = { #ifdef USE_EMULATION @@ -2707,7 +2710,7 @@ void (* const WebCommand[])(void) PROGMEM = { #ifdef USE_SENDMAIL &CmndSendmail, #endif - &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor }; + &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor, &CmndCors }; /*********************************************************************************************\ * Commands @@ -2828,6 +2831,14 @@ void CmndWebSensor(void) ResponseJsonEnd(); } +void CmndCors(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.cors_domain))) { + strlcpy(Settings.cors_domain, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.cors_domain)); + } + ResponseCmndChar(Settings.cors_domain); +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ From 531d36e012d69ff06dc8ebf89463c24e0cfdf820 Mon Sep 17 00:00:00 2001 From: Christian Tacke <8560110+ChristianTacke@users.noreply.github.com> Date: Sun, 8 Dec 2019 21:15:45 +0100 Subject: [PATCH 028/559] Timers: Use visibility instead of disabled The "+/-" chooser is only needed for sunrise/sunset. Otherwise it's disabled currently. This works. But it's a little confusing. Especially, if you first had "-" there (for sunset) and then switched to normal "time", then the "-" is still there, but you can't change it, because it's disabled. It looks better, if one uses .style.visibility to hide the element. It doesn't change the layout, just the element isn't shown. --- tasmota/xdrv_09_timers.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index a71960695..b00b5ba24 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -554,10 +554,10 @@ const char HTTP_TIMER_SCRIPT2[] PROGMEM = "o=qs('#ho');" "e=o.childElementCount;" "if(b==1){" - "qs('#dr').disabled='';" + "qs('#dr').style.visibility='';" "if(e>12){for(i=12;i<=23;i++){o.removeChild(o.lastElementChild);}}" // Create offset hours select options "}else{" - "qs('#dr').disabled='disabled';" + "qs('#dr').style.visibility='hidden';" "if(e<23){for(i=12;i<=23;i++){ce(i,o);}}" // Create hours select options "}" "}"; From 7cc7c2cc98bdb103def842807b44f6605802afb4 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 9 Dec 2019 10:14:13 +0100 Subject: [PATCH 029/559] Update xdrv_27_shutter.ino fix #7006 support for multiple shutters with steppers + add ShutterOpen/Close/Stop can get shutter index as parameter. e.g. shutteropen 3 to open shutter 3 --- tasmota/xdrv_27_shutter.ino | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index f47b53376..c97318c5f 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -194,10 +194,10 @@ void ShutterInit(void) } } else { Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; - if (pin[GPIO_PWM1 ]+i < 99) { + if (pin[GPIO_PWM1+i] < 99) { Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1]+i, 50); + analogWrite(pin[GPIO_PWM1+i], 50); } } @@ -257,11 +257,11 @@ void ShutterUpdatePosition(void) // Counter should be initiated to 0 to count movement. // 0..1000 in step 100 = 10 steps with 0.05 sec = 0.5sec total ramp time from start to // full speed. - if (pin[GPIO_PWM1]+i < 99 && Shutter.pwm_frequency != Shutter.max_pwm_frequency) { + if (pin[GPIO_PWM1+i] < 99 && Shutter.pwm_frequency != Shutter.max_pwm_frequency) { Shutter.pwm_frequency += Shutter.max_pwm_frequency/20; Shutter.pwm_frequency = (Shutter.pwm_frequency > Shutter.max_pwm_frequency ? Shutter.max_pwm_frequency : Shutter.pwm_frequency); analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1]+i, 50); + analogWrite(pin[GPIO_PWM1+i], 50); } Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); @@ -287,21 +287,21 @@ void ShutterUpdatePosition(void) // This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction // Only allow PWM microstepping if PWM and COUNTER are defined. // see wiki to connect PWM and COUNTER - if (pin[GPIO_PWM1 ]+i < 99 && pin[GPIO_CNTR1 ]+i < 99 ) { + if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { int16_t missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; Shutter.pwm_frequency = 0; //slow down for acurate position analogWriteFreq(500); - analogWrite(pin[GPIO_PWM1]+i, 50); + analogWrite(pin[GPIO_PWM1+i], 50); //prepare for stop PWM Shutter.motordelay[i] = -2 + Shutter.motordelay[i] + missing_steps/(Shutter.max_pwm_frequency/20); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Missing steps %d, adjust motordelay %d, counter %d, temp realpos %d"), missing_steps, Shutter.motordelay[i],RtcSettings.pulse_counter[i] ,Shutter.real_position[i]); - Settings.shutter_motordelay[i]=Shutter.motordelay[i]; + Settings.shutter_motordelay[i]=(missing_steps > 0 ? Shutter.motordelay[i] : 0); analogWriteFreq(0); while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { delay(1); } - analogWrite(pin[GPIO_PWM1]+i, 0); + analogWrite(pin[GPIO_PWM1+i], 0); Shutter.real_position[i] = ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Realpos %d, pulsecount %d, startpos %d, int32 %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i], ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)); @@ -357,12 +357,12 @@ void ShutterStartInit(uint8_t index, uint8_t direction, int32_t target_pos) Shutter.target_position[index] = target_pos; Shutter.start_position[index] = Shutter.real_position[index]; Shutter.time[index] = 0; - if (pin[GPIO_PWM1]+index < 99) { + if (pin[GPIO_PWM1+index] < 99) { Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1]+index, 0); + analogWrite(pin[GPIO_PWM1+index], 0); // can be operated without counter, but then not that acurate. - if (pin[GPIO_CNTR1]+index < 99) { + if (pin[GPIO_CNTR1+index] < 99) { RtcSettings.pulse_counter[index] = 0; } } @@ -459,6 +459,10 @@ void ShutterSetPosition(uint8_t device, uint8_t position) void CmndShutterOpen(void) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index); + if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { + XdrvMailbox.index = XdrvMailbox.payload; + } XdrvMailbox.payload = 100; last_source = SRC_WEBGUI; CmndShutterPosition(); @@ -466,6 +470,10 @@ void CmndShutterOpen(void) void CmndShutterClose(void) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index); + if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { + XdrvMailbox.index = XdrvMailbox.payload; + } XdrvMailbox.payload = 0; XdrvMailbox.data_len = 0; last_source = SRC_WEBGUI; @@ -475,6 +483,9 @@ void CmndShutterClose(void) void CmndShutterStop(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { + XdrvMailbox.index = XdrvMailbox.payload; + } uint32_t index = XdrvMailbox.index -1; if (Shutter.direction[index] != 0) { From dfee90bd61c70a96c8c28583258e07b85a23cf4c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 9 Dec 2019 15:15:16 +0100 Subject: [PATCH 030/559] Changelog update --- tasmota/CHANGELOG.md | 21 +++++++++++++++------ tasmota/my_user_config.h | 3 ++- tasmota/settings.h | 6 +++--- tasmota/settings.ino | 1 - 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 240bca728..826aad3b6 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,20 +1,29 @@ ## Unreleased (development) +### 7.1.2.4 20191209 + +- Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) +- Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) +- Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) + ### 7.1.2.3 20191208 - Redesign Exception reporting removing exception details from both MQTT info and Status 1. Now consolidated in Status 12 if available. ### 7.1.2.2 20191206 -- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) -- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack +- Remove rule trigger ``tele_power1#state`` due to compatibility +- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) +- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack by Stefan Hadinger +- Add Home Assistant force update by Frederico Leoni (#7140, #7074) ### 7.1.2.1 20191206 -- Add rule var ``%topic%`` (#5522) -- Add rule triggers ``tele_power1#state`` and multiple ``tele-wifi1#xxx`` (#7093) -- Add experimental support for stepper motor shutter control -- Add optional USE_MQTT_TLS to tasmota-minimal.bin (#7115) +- Add SML bus decoder syntax support for byte order by Gerhard Mutz (#7112) +- Add rule var ``%topic%`` by Adrian Scillato (#5522) +- Add rule triggers ``tele_power1#state`` and multiple ``tele-wifi1#xxx`` by Adrian Scillato (#7093) +- Add experimental support for stepper motor shutter control by Stefan Bode +- Add optional USE_MQTT_TLS to tasmota-minimal.bin by Bohdan Kmit (#7115) ## Released diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index c643f0a6d..5ff6bb6a2 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -132,7 +132,8 @@ #define WEB_PASSWORD "" // [WebPassword] Web server Admin mode Password for WEB_USERNAME (empty string = Disable) #define FRIENDLY_NAME "Tasmota" // [FriendlyName] Friendlyname up to 32 characters used by webpages and Alexa #define EMULATION EMUL_NONE // [Emulation] Select Belkin WeMo (single relay/light) or Hue Bridge emulation (multi relay/light) (EMUL_NONE, EMUL_WEMO or EMUL_HUE) -#define CORS_DOMAIN "" // [CorsDomain] CORS Domain for preflight requests +#define CORS_DOMAIN "" // [Cors] CORS Domain for preflight requests + // -- HTTP GUI Colors ----------------------------- // HTML hex color codes. Only 3 and 6 digit hex string values are supported!! See https://www.w3schools.com/colors/colors_hex.asp // Light theme - pre v7 diff --git a/tasmota/settings.h b/tasmota/settings.h index 6da25a36b..1c5206242 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -86,7 +86,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531) uint32_t hardware_energy_total : 1; // bit 22 (v6.6.0.15) - SetOption72 - Enable hardware energy total counter as reference (#6561) - uint32_t ex_cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS + uint32_t ex_cors_enabled : 1; // bit 23 (v7.0.0.1) - SetOption73 - Enable HTTP CORS uint32_t ds18x20_internal_pullup : 1; // bit 24 (v7.0.0.1) - SetOption74 - Enable internal pullup for single DS18x20 sensor uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled @@ -437,9 +437,9 @@ struct SYSCFG { uint8_t free_e9f[1]; // E9F uint8_t web_color2[2][3]; // EA0 - Needs to be on integer / 3 distance from web_color + char cors_domain[33]; // EA6 - char cors_domain[33]; // EC1 - uint8_t free_ea4[293]; // EA6 + uint8_t free_ec1[293]; // EC1 uint32_t i2c_drivers[3]; // FEC I2cDriver uint32_t cfg_timestamp; // FF8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 50f4fe4a6..cc6066c5a 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1181,7 +1181,6 @@ void SettingsDelta(void) if (Settings.version < 0x07010202) { Settings.serial_config = TS_SERIAL_8N1; } - if (Settings.version < 0x07010204) { if (Settings.flag3.ex_cors_enabled == 1) { strlcpy(Settings.cors_domain, CORS_ENABLED_ALL, sizeof(Settings.cors_domain)); From e9f8792649053c8d617cc4b63965aa1fc281b6bd Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 9 Dec 2019 15:29:22 +0100 Subject: [PATCH 031/559] Revert removal of exception details from MQTT info on restart Revert removal of exception details from MQTT info on restart --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_02_mqtt.ino | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 826aad3b6..00211f84b 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 7.1.2.4 20191209 - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) +- Revert removal of exception details from MQTT info on restart - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index d31d0a860..b38607ad7 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -555,7 +555,13 @@ void MqttConnected(void) MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); } #endif // USE_WEBSERVER - Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), GetResetReason().c_str()); + Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":")); + if (ResetReason() == REASON_EXCEPTION_RST) { + CrashDump(); + } else { + ResponseAppend_P(PSTR("\"%s\""), GetResetReason().c_str()); + } + ResponseJsonEnd(); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); MqttPublishAllPowerState(); if (Settings.tele_period) { From d3673963a2e77968b0775b397cc268640d99f9d6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 9 Dec 2019 16:16:21 +0100 Subject: [PATCH 032/559] Add Char Usage Ratio Add Char Usage Ratio for future Settings char redesign --- tasmota/settings.ino | 41 +++++++++++++++++++++++++++++++++++++ tasmota/support_command.ino | 7 +++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index cc6066c5a..4768ca24b 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -630,6 +630,47 @@ void SettingsSdkErase(void) delay(1000); } +String SettingsCharUsage(void) +{ + uint32_t str_len = 0; + uint32_t str_size = 0; + + for (uint32_t i = 0; i < 2; i++) { + str_len += strlen(Settings.sta_ssid[i]); str_size += sizeof(Settings.sta_ssid[i]); + str_len += strlen(Settings.sta_pwd[i]); str_size += sizeof(Settings.sta_pwd[i]); + } + for (uint32_t i = 0; i < 3; i++) { + str_len += strlen(Settings.mqtt_prefix[i]); str_size += sizeof(Settings.mqtt_prefix[i]); + str_len += strlen(Settings.ntp_server[i]); str_size += sizeof(Settings.ntp_server[i]); + } + for (uint32_t i = 0; i < 4; i++) { + str_len += strlen(Settings.state_text[i]); str_size += sizeof(Settings.state_text[i]); + str_len += strlen(Settings.friendlyname[i]); str_size += sizeof(Settings.friendlyname[i]); + } + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + str_len += strlen(Settings.mems[i]); str_size += sizeof(Settings.mems[i]); + } + + str_len += strlen(Settings.ota_url); str_size += sizeof(Settings.ota_url); + str_len += strlen(Settings.hostname); str_size += sizeof(Settings.hostname); + str_len += strlen(Settings.syslog_host); str_size += sizeof(Settings.syslog_host); + str_len += strlen(Settings.mqtt_host); str_size += sizeof(Settings.mqtt_host); + str_len += strlen(Settings.mqtt_client); str_size += sizeof(Settings.mqtt_client); + str_len += strlen(Settings.mqtt_user); str_size += sizeof(Settings.mqtt_user); + str_len += strlen(Settings.mqtt_pwd); str_size += sizeof(Settings.mqtt_pwd); + str_len += strlen(Settings.mqtt_topic); str_size += sizeof(Settings.mqtt_topic); + str_len += strlen(Settings.button_topic); str_size += sizeof(Settings.button_topic); + str_len += strlen(Settings.switch_topic); str_size += sizeof(Settings.switch_topic); + str_len += strlen(Settings.mqtt_grptopic); str_size += sizeof(Settings.mqtt_grptopic); + str_len += strlen(Settings.web_password); str_size += sizeof(Settings.web_password); + str_len += strlen(Settings.mqtt_fulltopic); str_size += sizeof(Settings.mqtt_fulltopic); + str_len += strlen(Settings.cors_domain); str_size += sizeof(Settings.cors_domain); + + char data[30]; + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), str_len, str_size); // Char Usage Ratio + return String(data); +} + /********************************************************************************************/ void SettingsDefault(void) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 09495f55a..b1c8512a4 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -380,9 +380,12 @@ void CmndStatus(void) if ((0 == payload) || (2 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," - "\"Hardware\":\"%s\"}}"), + "\"Hardware\":\"%s\"" + "%s}}"), my_version, my_image, GetBuildDateAndTime().c_str(), - ESP.getBootVersion(), ESP.getSdkVersion(), GetDeviceHardware().c_str()); + ESP.getBootVersion(), ESP.getSdkVersion(), + GetDeviceHardware().c_str(), + SettingsCharUsage().c_str()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); } From 53cfabdbca993ed59d8cb8ac1a3b7d45ff62d6c0 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Mon, 9 Dec 2019 21:43:30 +0100 Subject: [PATCH 033/559] Add RemoveAllSpaces() --- tasmota/support.ino | 17 +++++++++++++++++ tasmota/xdrv_02_mqtt.ino | 12 +----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index ef3b8d9ee..3ecc9b179 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -377,6 +377,23 @@ char* Trim(char* p) return p; } +char* RemoveAllSpaces(char* p) +{ + // remove any white space from the base64 + char *cursor = p; + uint32_t offset = 0; + while (1) { + *cursor = *(cursor + offset); + if ((' ' == *cursor) || ('\t' == *cursor) || ('\n' == *cursor)) { // if space found, remove this char until end of string + offset++; + } else { + if (0 == *cursor) { break; } + cursor++; + } + } + return p; +} + char* NoAlNumToUnderscore(char* dest, const char* source) { char* write = dest; diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index b38607ad7..6d68a346e 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1078,17 +1078,7 @@ void CmndTlsKey(void) { memcpy_P(spi_buffer, tls_spi_start, tls_spi_len); // remove any white space from the base64 - char *cursor = XdrvMailbox.data; - uint32_t offset = 0; - while (1) { - *cursor = *(cursor + offset); - if ((' ' == *cursor) || ('\t' == *cursor) || ('\n' == *cursor)) { // if space found, remove this char until end of string - offset++; - } else { - if (0 == *cursor) { break; } - cursor++; - } - } + RemoveAllSpaces(XdrvMailbox.data); // allocate buffer for decoded base64 uint32_t bin_len = decode_base64_length((unsigned char*)XdrvMailbox.data); From b2ac6c8ed7e3ddb47f809db66609ab23b8fa65cc Mon Sep 17 00:00:00 2001 From: localhost61 <33861984+localhost61@users.noreply.github.com> Date: Tue, 10 Dec 2019 00:51:08 +0100 Subject: [PATCH 034/559] Allow 4 DHT sensors --- tasmota/xsns_06_dht.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xsns_06_dht.ino b/tasmota/xsns_06_dht.ino index c4e877de9..6ef7055ac 100644 --- a/tasmota/xsns_06_dht.ino +++ b/tasmota/xsns_06_dht.ino @@ -28,7 +28,7 @@ #define XSNS_06 6 -#define DHT_MAX_SENSORS 3 +#define DHT_MAX_SENSORS 4 #define DHT_MAX_RETRY 8 uint32_t dht_max_cycles; From b9545f5194b66b325928945304a93076af1cde41 Mon Sep 17 00:00:00 2001 From: Thomas Herrmann Date: Tue, 10 Dec 2019 10:55:46 +0100 Subject: [PATCH 035/559] Report raw value from HX711 to overcome auto-tare functionality. Currently, when the device is switched off (intentionally or due to power cut), Tasmota only supports starting with the last known weight (Sensor34 7) or starting with 0 kg. In either case, this is sometimes not the desired functionality. For off-site logging of weights, it is more useful to report the raw, absolute value from the HX711 and to do calibration/tare in upper layers. Note: although it is called "Raw" value, the value is both averaged and scaled! It is just the offset compensation that is missing. --- tasmota/xsns_34_hx711.ino | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino index d9076f61d..469a5bb68 100644 --- a/tasmota/xsns_34_hx711.ino +++ b/tasmota/xsns_34_hx711.ino @@ -57,6 +57,7 @@ #define D_JSON_WEIGHT_MAX "WeightMax" #define D_JSON_WEIGHT_ITEM "WeightItem" #define D_JSON_WEIGHT_CHANGE "WeightChange" +#define D_JSON_WEIGHT_RAW "WeightRaw" enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; @@ -64,8 +65,10 @@ const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" struct HX { long weight = 0; + long raw = 0; long last_weight = 0; long sum_weight = 0; + long sum_raw = 0; long offset = 0; long scale = 1; long weight_diff = 0; @@ -272,13 +275,17 @@ void HxInit(void) void HxEvery100mSecond(void) { - Hx.sum_weight += HxRead(); + long raw = HxRead(); + Hx.sum_raw += raw; + Hx.sum_weight += raw; Hx.sample_count++; if (HX_SAMPLES == Hx.sample_count) { long average = Hx.sum_weight / Hx.sample_count; // grams + long raw_average = Hx.sum_raw / Hx.sample_count; // grams long value = average - Hx.offset; // grams Hx.weight = value / Hx.scale; // grams + Hx.raw = raw_average / Hx.scale; if (Hx.weight < 0) { if (Settings.energy_frequency_calibration) { long difference = Settings.energy_frequency_calibration + Hx.weight; @@ -367,6 +374,7 @@ void HxEvery100mSecond(void) } Hx.sum_weight = 0; + Hx.sum_raw = 0; Hx.sample_count = 0; } } @@ -405,7 +413,7 @@ void HxShow(bool json) dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); if (json) { - ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), weight_chr, scount); + ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s, \"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); @@ -565,4 +573,4 @@ bool Xsns34(uint8_t function) return result; } -#endif // USE_HX711 \ No newline at end of file +#endif // USE_HX711 From 407935efc422940098f3a57621a5f86156725b73 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 10 Dec 2019 12:33:45 +0100 Subject: [PATCH 036/559] Change GUI Shutter button text Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) --- RELEASENOTES.md | 20 ++++++++++++++------ tasmota/CHANGELOG.md | 3 ++- tasmota/xdrv_01_webserver.ino | 15 +++++++++++++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0baecb42a..468e8e5d5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,10 +47,18 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 7.1.2 Betty +### Version 7.1.2.4 -- Fix lost functionality of GPIO9 and GPIO10 on some devices (#7080) -- Fix Zigbee uses Hardware Serial if GPIO 1/3 or GPIO 13/15 and SerialLog 0 (#7071) -- Fix WS2812 power control (#7090) -- Change light color schemes 2, 3 and 4 from color wheel to Hue driven with user Saturation control -- Change log buffer size from 520 to 700 characters accomodating full rule text (#7110) +- Change Exception reporting removing exception details from ``Status 1`` and consolidated in ``Status 12`` if available +- Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) +- Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) +- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) +- Add rule var ``%topic%`` by Adrian Scillato (#5522) +- Add rule triggers ``tele-wifi1#xxx`` by Adrian Scillato (#7093) +- Add SML bus decoder syntax support for byte order by Gerhard Mutz (#7112) +- Add experimental support for stepper motor shutter control by Stefan Bode +- Add optional USE_MQTT_TLS to tasmota-minimal.bin by Bohdan Kmit (#7115) +- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack by Stefan Hadinger +- Add Home Assistant force update by Frederico Leoni (#7140, #7074) +- Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) +- Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 00211f84b..51148e814 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,13 +3,14 @@ ### 7.1.2.4 20191209 - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) +- Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) - Revert removal of exception details from MQTT info on restart - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) ### 7.1.2.3 20191208 -- Redesign Exception reporting removing exception details from both MQTT info and Status 1. Now consolidated in Status 12 if available. +- Change Exception reporting removing exception details from both MQTT info and ``Status 1``. Now consolidated in ``Status 12`` if available. ### 7.1.2.2 20191206 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 28620e21f..0a72da399 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1107,6 +1107,21 @@ void HandleRoot(void) } else { #endif // USE_SONOFF_IFAN for (uint32_t idx = 1; idx <= devices_present; idx++) { +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support + bool shutter_used = false; + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + if (Settings.shutter_startrelay[i] == (((idx -1) & 0xFFFFFFFE) +1)) { + shutter_used = true; + break; + } + } + if (shutter_used) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (idx % 2) ? "▲" : "▼" , ""); + continue; + } + } +#endif // USE_SHUTTER snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); } From f878eba66d37434ddf56bc84d22fb2014dab2132 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 10 Dec 2019 12:40:18 +0100 Subject: [PATCH 037/559] Change amount of supported DHT sensors Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 468e8e5d5..9003da11e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,6 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Exception reporting removing exception details from ``Status 1`` and consolidated in ``Status 12`` if available - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) - Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) +- Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167) - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) - Add rule var ``%topic%`` by Adrian Scillato (#5522) - Add rule triggers ``tele-wifi1#xxx`` by Adrian Scillato (#7093) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 51148e814..ba26dd7e6 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) - Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) +- Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167) - Revert removal of exception details from MQTT info on restart - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) From f03156849d18923f166ce618f99a5f885ce2bbf8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 10 Dec 2019 12:58:34 +0100 Subject: [PATCH 038/559] Add reporting of raw weight to HX711 Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9003da11e..cfb5f714d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -63,3 +63,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add Home Assistant force update by Frederico Leoni (#7140, #7074) - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) +- Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index ba26dd7e6..9eab486f8 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Revert removal of exception details from MQTT info on restart - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) +- Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) ### 7.1.2.3 20191208 From 5f9350831dbb18f2dcaa7e66faa486ebe63d9cf7 Mon Sep 17 00:00:00 2001 From: PtrO Date: Tue, 10 Dec 2019 18:09:59 +0100 Subject: [PATCH 039/559] 7.1.2.4 20191209 xdrv_09_timers.ino fix 12hr early Sunset/Sunrise due negative zero time. --- tasmota/xdrv_09_timers.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index b00b5ba24..db1cde97e 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -583,7 +583,7 @@ const char HTTP_TIMER_SCRIPT3[] PROGMEM = "if(m==0){s|=l;}" // Get time #ifdef USE_SUNRISE "if((m==1)||(m==2)){" - "if(qs('#dr').selectedIndex>0){l+=720;}" // If negative offset, add 12h to given offset time + "if(qs('#dr').selectedIndex>0){if(l>0){l+=720;}}" // If negative offset and delta-time > 0, add 12h to given offset time "s|=l&0x7FF;" // Save offset instead of time "}" #endif From 1761dee63e90eb61a6213d57ff9a62c7566e1f3a Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 10 Dec 2019 15:42:44 -0300 Subject: [PATCH 040/559] KNX: Added Key for using custom settings for KNX --- lib/esp-knx-ip-0.5.2/esp-knx-ip.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/esp-knx-ip-0.5.2/esp-knx-ip.h b/lib/esp-knx-ip-0.5.2/esp-knx-ip.h index eb5ecf7b0..7c6377bec 100644 --- a/lib/esp-knx-ip-0.5.2/esp-knx-ip.h +++ b/lib/esp-knx-ip-0.5.2/esp-knx-ip.h @@ -32,8 +32,18 @@ #define DISABLE_RESTORE_BUTTON 1 // [Default 0] Set to 1 to disable the "restore defaults" button in the web ui. // These values normally don't need adjustment -#define MULTICAST_PORT 3671 // [Default 3671] +#ifndef MULTICAST_IP #define MULTICAST_IP IPAddress(224, 0, 23, 12) // [Default IPAddress(224, 0, 23, 12)] +#else +#warning USING CUSTOM MULTICAST_IP +#endif + +#ifndef MULTICAST_PORT +#define MULTICAST_PORT 3671 // [Default 3671] +#else +#warning USING CUSTOM MULTICAST_PORT +#endif + #define SEND_CHECKSUM 0 // Uncomment to enable printing out debug messages. From 96cc933094a6f1f9ef1acca3ecf3248226aaca89 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Tue, 10 Dec 2019 22:00:38 +0100 Subject: [PATCH 041/559] Fix flashing H801 led at boot (#7165, #649) --- tasmota/CHANGELOG.md | 1 + tasmota/support_tasmota.ino | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 9eab486f8..51277e62b 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -9,6 +9,7 @@ - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) - Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) +- Fix flashing H801 led at boot (#7165, #649) ### 7.1.2.3 20191208 diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 2ab8fa0d7..34ce9f5dc 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1286,15 +1286,19 @@ void GpioInit(void) } #endif // USE_SONOFF_SC - if (!light_type) { - for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only - if (pin[GPIO_PWM1 +i] < 99) { + for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + if (light_type) { + // force PWM GPIOs to low or high mode, see #7165 + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); + } else { pwm_present = true; - pinMode(pin[GPIO_PWM1 +i], OUTPUT); analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); } } } + for (uint32_t i = 0; i < MAX_RELAYS; i++) { if (pin[GPIO_REL1 +i] < 99) { pinMode(pin[GPIO_REL1 +i], OUTPUT); From b1d26b9b3a5378092137ee25959ea3f6d82f1824 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 10 Dec 2019 22:36:23 -0300 Subject: [PATCH 042/559] RULES: Fix duplicated BACKLOG when using EVENT inside a BACKLOG --- tasmota/xdrv_10_rules.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 441722662..ac771f0d7 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -438,7 +438,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) String ucommand = commands; ucommand.toUpperCase(); // if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race exception - if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception + if ((ucommand.indexOf("EVENT ") != -1) && (ucommand.indexOf("BACKLOG ") == -1)) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception RulesVarReplace(commands, F("%VALUE%"), Rules.event_value); for (uint32_t i = 0; i < MAX_RULE_VARS; i++) { From 28c8761be21fc02d9addaf18f9a81023d4402602 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 11 Dec 2019 10:10:02 +0100 Subject: [PATCH 043/559] Update change log and release notes --- RELEASENOTES.md | 3 +++ tasmota/CHANGELOG.md | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cfb5f714d..2ce866863 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -53,6 +53,9 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) - Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) - Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167) +- Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649) +- Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) +- Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) - Add rule var ``%topic%`` by Adrian Scillato (#5522) - Add rule triggers ``tele-wifi1#xxx`` by Adrian Scillato (#7093) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 51277e62b..8f5954e66 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -9,7 +9,9 @@ - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) - Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) -- Fix flashing H801 led at boot (#7165, #649) +- Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649) +- Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) +- Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) ### 7.1.2.3 20191208 From 72aa161dddab0b9a293fe921b7f8e526e02ab73f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 11 Dec 2019 10:49:57 +0100 Subject: [PATCH 044/559] Extent statistics --- tasmota/settings.ino | 41 ---------------- tasmota/support_command.ino | 2 +- tasmota/support_statistics.ino | 88 ++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 42 deletions(-) create mode 100644 tasmota/support_statistics.ino diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 4768ca24b..cc6066c5a 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -630,47 +630,6 @@ void SettingsSdkErase(void) delay(1000); } -String SettingsCharUsage(void) -{ - uint32_t str_len = 0; - uint32_t str_size = 0; - - for (uint32_t i = 0; i < 2; i++) { - str_len += strlen(Settings.sta_ssid[i]); str_size += sizeof(Settings.sta_ssid[i]); - str_len += strlen(Settings.sta_pwd[i]); str_size += sizeof(Settings.sta_pwd[i]); - } - for (uint32_t i = 0; i < 3; i++) { - str_len += strlen(Settings.mqtt_prefix[i]); str_size += sizeof(Settings.mqtt_prefix[i]); - str_len += strlen(Settings.ntp_server[i]); str_size += sizeof(Settings.ntp_server[i]); - } - for (uint32_t i = 0; i < 4; i++) { - str_len += strlen(Settings.state_text[i]); str_size += sizeof(Settings.state_text[i]); - str_len += strlen(Settings.friendlyname[i]); str_size += sizeof(Settings.friendlyname[i]); - } - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - str_len += strlen(Settings.mems[i]); str_size += sizeof(Settings.mems[i]); - } - - str_len += strlen(Settings.ota_url); str_size += sizeof(Settings.ota_url); - str_len += strlen(Settings.hostname); str_size += sizeof(Settings.hostname); - str_len += strlen(Settings.syslog_host); str_size += sizeof(Settings.syslog_host); - str_len += strlen(Settings.mqtt_host); str_size += sizeof(Settings.mqtt_host); - str_len += strlen(Settings.mqtt_client); str_size += sizeof(Settings.mqtt_client); - str_len += strlen(Settings.mqtt_user); str_size += sizeof(Settings.mqtt_user); - str_len += strlen(Settings.mqtt_pwd); str_size += sizeof(Settings.mqtt_pwd); - str_len += strlen(Settings.mqtt_topic); str_size += sizeof(Settings.mqtt_topic); - str_len += strlen(Settings.button_topic); str_size += sizeof(Settings.button_topic); - str_len += strlen(Settings.switch_topic); str_size += sizeof(Settings.switch_topic); - str_len += strlen(Settings.mqtt_grptopic); str_size += sizeof(Settings.mqtt_grptopic); - str_len += strlen(Settings.web_password); str_size += sizeof(Settings.web_password); - str_len += strlen(Settings.mqtt_fulltopic); str_size += sizeof(Settings.mqtt_fulltopic); - str_len += strlen(Settings.cors_domain); str_size += sizeof(Settings.cors_domain); - - char data[30]; - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), str_len, str_size); // Char Usage Ratio - return String(data); -} - /********************************************************************************************/ void SettingsDefault(void) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index b1c8512a4..ec8de9126 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -385,7 +385,7 @@ void CmndStatus(void) my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getBootVersion(), ESP.getSdkVersion(), GetDeviceHardware().c_str(), - SettingsCharUsage().c_str()); + GetStatistics().c_str()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); } diff --git a/tasmota/support_statistics.ino b/tasmota/support_statistics.ino new file mode 100644 index 000000000..3239c5b93 --- /dev/null +++ b/tasmota/support_statistics.ino @@ -0,0 +1,88 @@ +/* + support_statistics.ino - gather statistics for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define USE_STATS_CODE + +#ifdef USE_STATS_CODE +/*********************************************************************************************\ + * Gather statistics +\*********************************************************************************************/ + +struct STATS { +// uint32_t str_size = 1151; // Total number of characters reserved as char array in Settings + uint32_t str_len = 0; // Total number of characters used within char array + uint32_t str_char = 0; // Total number of character '|' within all char arrays +} Stats; + +void StatisticsChar(const char* text) +{ + uint32_t len = strlen(text); + Stats.str_len += len; + for (uint32_t i = 0; i < len; i++) { + if ('|' == text[i]) { // Text string separator as currently used in GetTextIndexed() + Stats.str_char++; + } + } +} + +String GetStatistics(void) +{ + for (uint32_t i = 0; i < 2; i++) { + StatisticsChar(Settings.sta_ssid[i]); + StatisticsChar(Settings.sta_pwd[i]); + } + for (uint32_t i = 0; i < 3; i++) { + StatisticsChar(Settings.mqtt_prefix[i]); + StatisticsChar(Settings.ntp_server[i]); + } + for (uint32_t i = 0; i < 4; i++) { + StatisticsChar(Settings.state_text[i]); + StatisticsChar(Settings.friendlyname[i]); + } + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + StatisticsChar(Settings.mems[i]); + } + StatisticsChar(Settings.ota_url); + StatisticsChar(Settings.hostname); + StatisticsChar(Settings.syslog_host); + StatisticsChar(Settings.mqtt_host); + StatisticsChar(Settings.mqtt_client); + StatisticsChar(Settings.mqtt_user); + StatisticsChar(Settings.mqtt_pwd); + StatisticsChar(Settings.mqtt_topic); + StatisticsChar(Settings.button_topic); + StatisticsChar(Settings.switch_topic); + StatisticsChar(Settings.mqtt_grptopic); + StatisticsChar(Settings.web_password); + StatisticsChar(Settings.mqtt_fulltopic); + StatisticsChar(Settings.cors_domain); + + char data[40]; + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151/%d\""), Stats.str_len, Stats.str_char); // Char Usage Ratio + return String(data); +} + +#else + +String GetStatistics(void) +{ + return String(""); +} + +#endif // USE_STATS_CODE \ No newline at end of file From eccc9f20f5544c4b7b12813dda62a013b8259981 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 11 Dec 2019 11:54:27 +0100 Subject: [PATCH 045/559] Add weight_change for #7170 Add weight_change for #7170 --- tasmota/settings.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 1c5206242..524a6ac19 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -433,9 +433,7 @@ struct SYSCFG { uint16_t energy_power_delta; // E98 uint8_t shutter_motordelay[MAX_SHUTTERS]; // E9A int8_t temp_comp; // E9E - - uint8_t free_e9f[1]; // E9F - + uint8_t weight_change; // E9F uint8_t web_color2[2][3]; // EA0 - Needs to be on integer / 3 distance from web_color char cors_domain[33]; // EA6 From 27dd251fc341b506e3a11331d6c7ae4a3a5c19cd Mon Sep 17 00:00:00 2001 From: Bastian Urschel Date: Wed, 11 Dec 2019 15:53:19 +0100 Subject: [PATCH 046/559] IPv6 global unique address is now displayed at webinterface "information" above IPv4 address and also mentioned in the initial MQTT message if WebServer is active. --- tasmota/support_wifi.ino | 8 ++++++++ tasmota/xdrv_01_webserver.ino | 12 ++++++++++++ tasmota/xdrv_02_mqtt.ino | 5 +++++ 3 files changed, 25 insertions(+) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 06d922b26..3f9e7795b 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -352,6 +352,14 @@ bool WifiCheckIPv6(void) return ipv6_global; } +String WifiGetIPv6(void) +{ + for (auto a : addrList) { + if(!a.isLocal() && a.isV6()) return a.toString(); + } + return ""; +} + bool WifiCheckIPAddrStatus(void) // Return false for 169.254.x.x or fe80::/64 { bool ip_global=false; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 0a72da399..5dbec658a 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -598,7 +598,13 @@ void StartWebserver(int type, IPAddress ipweb) WebServer->begin(); // Web server start } if (Web.state != type) { +#if LWIP_IPV6 + String ipv6_addr = WifiGetIPv6(); + if(ipv6_addr!="") AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s and IPv6 global address %s "), my_hostname, (Wifi.mdns_begun) ? ".local" : "", ipweb.toString().c_str(),ipv6_addr.c_str()); + else AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "", ipweb.toString().c_str()); +#else AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %s"), my_hostname, (Wifi.mdns_begun) ? ".local" : "", ipweb.toString().c_str()); +#endif // LWIP_IPV6 = 1 rules_flag.http_init = 1; } if (type) { Web.state = type; } @@ -1990,6 +1996,12 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1}2 ")); // Empty line WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI()); WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : ""); +#if LWIP_IPV6 + String ipv6_addr = WifiGetIPv6(); + if(ipv6_addr != ""){ + WSContentSend_P(PSTR("}1 IPv6 Address }2%s"), ipv6_addr.c_str()); + } +#endif if (static_cast(WiFi.localIP()) != 0) { WSContentSend_P(PSTR("}1" D_IP_ADDRESS "}2%s"), WiFi.localIP().toString().c_str()); WSContentSend_P(PSTR("}1" D_GATEWAY "}2%s"), IPAddress(Settings.ip_address[1]).toString().c_str()); diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 6d68a346e..7a9b1bf43 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -550,8 +550,13 @@ void MqttConnected(void) MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { +#if LWIP_IPV6 + Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}"), + (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str(),WifiGetIPv6().c_str()); +#else Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); +#endif // LWIP_IPV6 = 1 MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); } #endif // USE_WEBSERVER From bfe2dc68cba880961ac4c18cb6512d0903c08172 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 11 Dec 2019 19:30:52 +0100 Subject: [PATCH 047/559] Fix statistics --- tasmota/settings.h | 2 +- tasmota/support_statistics.ino | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 524a6ac19..c938f0b39 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -437,7 +437,7 @@ struct SYSCFG { uint8_t web_color2[2][3]; // EA0 - Needs to be on integer / 3 distance from web_color char cors_domain[33]; // EA6 - uint8_t free_ec1[293]; // EC1 + uint8_t free_ec7[293]; // EC7 uint32_t i2c_drivers[3]; // FEC I2cDriver uint32_t cfg_timestamp; // FF8 diff --git a/tasmota/support_statistics.ino b/tasmota/support_statistics.ino index 3239c5b93..efd94f307 100644 --- a/tasmota/support_statistics.ino +++ b/tasmota/support_statistics.ino @@ -43,6 +43,9 @@ void StatisticsChar(const char* text) String GetStatistics(void) { + Stats.str_len = 0; + Stats.str_char = 0; + for (uint32_t i = 0; i < 2; i++) { StatisticsChar(Settings.sta_ssid[i]); StatisticsChar(Settings.sta_pwd[i]); From 2ecb1b18474d1efd57daef614f6489043ce87163 Mon Sep 17 00:00:00 2001 From: Thomas Herrmann Date: Wed, 11 Dec 2019 22:03:13 +0100 Subject: [PATCH 048/559] Make WeightDelta for JSON message configurable. --- tasmota/xsns_34_hx711.ino | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino index 469a5bb68..ecb8da493 100644 --- a/tasmota/xsns_34_hx711.ino +++ b/tasmota/xsns_34_hx711.ino @@ -58,6 +58,7 @@ #define D_JSON_WEIGHT_ITEM "WeightItem" #define D_JSON_WEIGHT_CHANGE "WeightChange" #define D_JSON_WEIGHT_RAW "WeightRaw" +#define D_JSON_WEIGHT_DELTA "WeightDelta" enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; @@ -81,6 +82,7 @@ struct HX { uint8_t pin_dout; bool tare_flg = false; bool weight_changed = false; + uint16_t weight_delta = 4; } Hx; /*********************************************************************************************/ @@ -149,6 +151,24 @@ void HxCalibrationStateTextJson(uint8_t msg_id) if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } } +void SetWeightDelta() +{ + // backwards compatible: restore old default value of 4 grams + if (Settings.weight_change == 0) { + Hx.weight_delta = 4; + return; + } + + // map upper values 101-255 to + if (Settings.weight_change > 100) { + Hx.weight_delta = (Settings.weight_change - 100) * 10 + 100; + return; + } + + // map 1..100 to 0..99 grams + Hx.weight_delta = Settings.weight_change - 1; +} + /*********************************************************************************************\ * Supported commands for Sensor34: * @@ -166,6 +186,7 @@ void HxCalibrationStateTextJson(uint8_t msg_id) * Sensor34 7 - Save current weight to be used as start weight on restart * Sensor34 8 0 - Disable JSON weight change message * Sensor34 8 1 - Enable JSON weight change message + * Sensor34 9 - Set minimum delta to trigger JSON message \*********************************************************************************************/ bool HxCommand(void) @@ -228,6 +249,13 @@ bool HxCommand(void) } show_parms = true; break; + case 9: // WeightDelta + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + SetWeightDelta(); + } + show_parms = true; + break; default: show_parms = true; } @@ -235,8 +263,10 @@ bool HxCommand(void) if (show_parms) { char item[33]; dtostrfd((float)Settings.weight_item / 10, 1, item); - Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":\"%s\"}}"), - Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item, GetStateText(Settings.SensorBits1.hx711_json_weight_change)); + Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" + D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":%s,\"" D_JSON_WEIGHT_DELTA "\":\"%d\"}}"), + Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, + item, GetStateText(Settings.SensorBits1.hx711_json_weight_change), Settings.weight_change); } return serviced; @@ -261,6 +291,8 @@ void HxInit(void) digitalWrite(Hx.pin_sck, LOW); + SetWeightDelta(); + if (HxIsReady(8 * HX_TIMEOUT)) { // Can take 600 milliseconds after power on if (!Settings.weight_max) { Settings.weight_max = HX_MAX_WEIGHT / 1000; } if (!Settings.weight_calibration) { Settings.weight_calibration = HX_SCALE; } @@ -358,7 +390,7 @@ void HxEvery100mSecond(void) Hx.weight += Hx.last_weight; // grams if (Settings.SensorBits1.hx711_json_weight_change) { - if (abs(Hx.weight - Hx.weight_diff) > 4) { // Use 4 gram threshold to decrease "ghost" weights + if (abs(Hx.weight - Hx.weight_diff) > Hx.weight_delta) { // Use weight_delta threshold to decrease "ghost" weights Hx.weight_diff = Hx.weight; Hx.weight_changed = true; } From abf1d2b27c7813f51b81500b27ddf0769bc0e828 Mon Sep 17 00:00:00 2001 From: localhost61 <33861984+localhost61@users.noreply.github.com> Date: Thu, 12 Dec 2019 08:39:44 +0100 Subject: [PATCH 049/559] Cosmetic typo in shutter log --- tasmota/xdrv_27_shutter.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index c97318c5f..8bc13dfa4 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -230,8 +230,8 @@ void ShutterInit(void) dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); char shutter_close_chr[10]; dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d,motordelay %d"), - i, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d,motordelay %d"), + i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], Shutter.mask, Settings.shutter_invert[i], Shutter.mode, Shutter.motordelay[i]); @@ -322,7 +322,7 @@ void ShutterUpdatePosition(void) Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, motordelay %d, rtcshutter: %s [s]"), i, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], Shutter.motordelay[i],stemp2); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, motordelay %d, rtcshutter: %s [s]"), i+1, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], Shutter.motordelay[i],stemp2); Shutter.start_position[i] = Shutter.real_position[i]; // sending MQTT result to broker @@ -385,7 +385,7 @@ void ShutterReportPosition(void) dtostrfd((float)Shutter.time[i] / 20, 2, stemp2); shutter_moving = 1; //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, motordelay %d, rtcshutter: %s [s]"), i,Shutter.real_position[i], Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2 ); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, motordelay %d, rtcshutter: %s [s]"), i+1,Shutter.real_position[i], Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2 ); } } if (rules_flag.shutter_moving > shutter_moving) { @@ -427,7 +427,7 @@ void ShutterRelayChanged(void) } else { if (Shutter.direction[i] != 0 && (!powerstate_local || (powerstate_local && Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE))) { Shutter.target_position[i] = Shutter.real_position[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i, Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); } else { last_source = SRC_SHUTTER; // avoid switch off in the next loop if (powerstate_local == 2) { // testing on CLOSE relay, if ON @@ -440,7 +440,7 @@ void ShutterRelayChanged(void) ShutterStartInit(i, 1, Shutter.open_max[i]); } } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i, Shutter.target_position[i], powerstate_local); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter.target_position[i], powerstate_local); } } } From f0a2563b87fac4056524b4c7d5f385198f771217 Mon Sep 17 00:00:00 2001 From: localhost61 <33861984+localhost61@users.noreply.github.com> Date: Thu, 12 Dec 2019 09:32:34 +0100 Subject: [PATCH 050/559] Update French language --- tasmota/language/fr-FR.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 236df351b..e107409e3 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.6.0.15 + * Updated until v7.1.2.4 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -71,7 +71,7 @@ #define D_COLDLIGHT "Froid" #define D_COMMAND "Commande" #define D_CONNECTED "Connecté" -#define D_CORS_DOMAIN "CORS Domain" +#define D_CORS_DOMAIN "Domaine CORS" #define D_COUNT "Compte" #define D_COUNTER "Compteur" #define D_CURRENT "Courant" // As in Voltage and Current @@ -281,7 +281,7 @@ #define D_MQTT_PARAMETERS "Paramètres MQTT" #define D_CLIENT "Client" -#define D_FULL_TOPIC "topic complet" +#define D_FULL_TOPIC "Topic complet" #define D_LOGGING_PARAMETERS "Paramètres du journal" #define D_SERIAL_LOG_LEVEL "Niveau de journalisation série" @@ -688,7 +688,7 @@ #define D_CHECKING "En test" #define D_WORKING "En marche" #define D_FAILURE "Défault" -#define D_SOLAX_ERROR_0 "Aucun Code d'erreur" +#define D_SOLAX_ERROR_0 "Aucun code d'erreur" #define D_SOLAX_ERROR_1 "Défaut Perte de réseau" #define D_SOLAX_ERROR_2 "Défaut Tension réseau" #define D_SOLAX_ERROR_3 "Défaut Fréquence réseau" From 424f8c86f4ba72d009405bf318cc16649ba36c0b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 12 Dec 2019 14:40:03 +0100 Subject: [PATCH 051/559] Update xsns_34_hx711.ino --- tasmota/xsns_34_hx711.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino index ecb8da493..d64712a86 100644 --- a/tasmota/xsns_34_hx711.ino +++ b/tasmota/xsns_34_hx711.ino @@ -264,7 +264,7 @@ bool HxCommand(void) char item[33]; dtostrfd((float)Settings.weight_item / 10, 1, item); Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" - D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":%s,\"" D_JSON_WEIGHT_DELTA "\":\"%d\"}}"), + D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":%s,\"" D_JSON_WEIGHT_DELTA "\":%d}}"), Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item, GetStateText(Settings.SensorBits1.hx711_json_weight_change), Settings.weight_change); } From c32d2088b0d617a0ab92107b110d19725f4de768 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 12 Dec 2019 14:51:41 +0100 Subject: [PATCH 052/559] Single Settings Char Array Phase 1 Single Settings Char Array Phase 1 - Does nothing yet --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/settings.ino | 148 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2ce866863..d269109e8 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -57,6 +57,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) - Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) +- Add command ``Sensor34 9 `` to set minimum delta to trigger JSON message by @tobox (#7188) - Add rule var ``%topic%`` by Adrian Scillato (#5522) - Add rule triggers ``tele-wifi1#xxx`` by Adrian Scillato (#7093) - Add SML bus decoder syntax support for byte order by Gerhard Mutz (#7112) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 8f5954e66..4bbeccb26 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -9,6 +9,7 @@ - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) - Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) +- Add command ``Sensor34 9 `` to set minimum delta to trigger JSON message by @tobox (#7188) - Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649) - Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) - Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index cc6066c5a..d616d4cfc 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -442,6 +442,152 @@ void UpdateQuickPowerCycle(bool update) } } +/*********************************************************************************************\ + * Config single char array support +\*********************************************************************************************/ + +enum CharsIndex { SET_OTAURL, + SET_MQTTPREFIX1, SET_MQTTPREFIX2, SET_MQTTPREFIX3, +// SET_STASSID1, SET_STASSID2, +// SET_STAPWD1, SET_STAPWD2, SET_WEBPWD, +// SET_HOSTNAME, SET_SYSLOG_HOST, +// SET_MQTT_HOST, SET_MQTT_CLIENT, +// SET_MQTT_USER, SET_MQTT_PWD, +// SET_MQTT_FULLTOPIC, SET_MQTT_TOPIC, +// SET_MQTT_BUTTON_TOPIC, SET_MQTT_SWITCH_TOPIC, SET_MQTT_GRP_TOPIC, +// SET_STATE_TXT1, SET_STATE_TXT2, SET_STATE_TXT3, SET_STATE_TXT4, +// SET_FRIENDLYNAME1, SET_FRIENDLYNAME2, SET_FRIENDLYNAME3, SET_FRIENDLYNAME4, + +// SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, // Future extension + +// SET_NTPSERVER1, SET_NTPSERVER2, SET_NTPSERVER3, +// SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5, +// SET_CORS, + +// SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, // Future extension +// SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, // Future extension +// SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, // Future extension +// SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, // Future extension + + SET_MAX }; + +const uint32_t settings_loc_num = 1; // First phase only ota_url and mqtt_prefix +const uint32_t settings_max_size = 134; + +char settings_fullstr[settings_max_size] = { 0 }; + +struct LOCATIONS { + char* address; + uint32_t size = 0; +} Location[settings_loc_num]; + +void SettingsInitText(void) +{ + for (uint32_t i = 0; i < settings_loc_num; i++) { + if (0 == i) { + Location[i].address = Settings.ota_url; + Location[i].size = sizeof(Settings.ota_url) + (3 * sizeof(Settings.mqtt_prefix[0])); +// Location[i].address = Settings.char_chunk1; +// Location[i].size = sizeof(Settings.char_chunk1); // 134 + } + else if (1 == i) { + Location[i].address = Settings.sta_ssid[0]; + Location[i].size = (2 * sizeof(Settings.sta_ssid[0])) + (2 * sizeof(Settings.sta_pwd[0])) + sizeof(Settings.hostname) + sizeof(Settings.syslog_host); +// Location[i].address = Settings.char_chunk2; +// Location[i].size = sizeof(Settings.char_chunk2); // 262 + } + else if (2 == i) { + // Need to move Settings.mqtt_port first! + Location[i].address = Settings.mqtt_host; + Location[i].size = sizeof(Settings.mqtt_host) + 2 + sizeof(Settings.mqtt_client) + sizeof(Settings.mqtt_user) + sizeof(Settings.mqtt_pwd) + sizeof(Settings.mqtt_topic) + sizeof(Settings.button_topic) + sizeof(Settings.mqtt_grptopic); +// Location[i].address = Settings.char_chunk3; +// Location[i].size = sizeof(Settings.char_chunk3); // 233 + } + } + + SettingsCopyText(0); // Load +} + +void SettingsCopyText(uint32_t direction) +{ + char* fullstr = settings_fullstr; + uint32_t size = 0; + for (uint32_t i = 0; i < settings_loc_num; i++) { + size = Location[i].size; + if (1 == direction) { + memcpy(Location[i].address, fullstr, size); // Save to Settings + } else { + memcpy(fullstr, Location[i].address, size); // Load from Settings + } + fullstr += size; + } +} + +bool SettingsUpdateText(uint32_t index, char* replace) +{ + if (index >= SET_MAX) { + return false; // Setting not supported - internal error + } + +// SettingsCopyText(0); // Load + + uint32_t start_pos = 0; + uint32_t end_pos = 0; + char* position = settings_fullstr; + for (uint32_t size = 0; size < SET_MAX; size++) { + while (*position++ != '\0') { } + if (1 == index) { + start_pos = position - settings_fullstr; + } + else if (0 == index) { + end_pos = position - settings_fullstr -1; + } + index--; + } + uint32_t len_pos = position - settings_fullstr; + + uint32_t current_len = end_pos - start_pos; + uint32_t replace_len = strlen(replace); + int diff = replace_len - current_len; + +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"), +// start_pos, end_pos, len_pos, current_len, replace_len, diff); + + int too_long = (len_pos + diff) - sizeof(settings_fullstr); + if (too_long > 0) { +// AddLog_P2(LOG_LEVEL_INFO, PSTR("CFG: Text too long by %d char(s)"), too_long); + return false; // Replace text too long + } + + if (diff != 0) { + // Shift full text string up or down + memmove_P(settings_fullstr + start_pos + replace_len, settings_fullstr + end_pos, len_pos - end_pos); + } + // Replace text + memmove_P(settings_fullstr + start_pos, replace, replace_len); + // Fill for future use + memset(settings_fullstr + len_pos + diff, 0x00, settings_max_size - len_pos - diff); + +// SettingsCopyText(1); // Save - Hold of for now + + return true; +} + +char* SettingsGetText(uint32_t index) +{ + if (index >= SET_MAX) { + return nullptr; // Setting not supported - internal error + } + +// SettingsCopyText(0); // Load + + char* position = settings_fullstr; + for (;index > 0; index--) { + while (*position++ != '\0') { } + } + return position; +} + /*********************************************************************************************\ * Config Save - Save parameters to Flash ONLY if any parameter has changed \*********************************************************************************************/ @@ -561,6 +707,8 @@ void SettingsLoad(void) settings_crc32 = GetSettingsCrc32(); #endif // FIRMWARE_MINIMAL + SettingsInitText(); + RtcSettingsLoad(); } From e09735dbaed91f8600d3b64b03ad1961b0a60a47 Mon Sep 17 00:00:00 2001 From: znanev <20048364+znanev@users.noreply.github.com> Date: Thu, 12 Dec 2019 14:18:12 +0000 Subject: [PATCH 053/559] Update bg-BG.h Update Bulgarian translation up to v7.1.2.4 --- tasmota/language/bg-BG.h | 76 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index d39aba5f6..d91db2dee 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.5.0.8 + * Updated until v7.1.2.4 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -71,7 +71,7 @@ #define D_COLDLIGHT "Хладна" #define D_COMMAND "Команда" #define D_CONNECTED "Свързан" -#define D_CORS_DOMAIN "CORS Domain" +#define D_CORS_DOMAIN "CORS домейн" #define D_COUNT "Брой" #define D_COUNTER "Брояч" #define D_CURRENT "Ток" // As in Voltage and Current @@ -83,7 +83,7 @@ #define D_DNS_SERVER "DNS Сървър" #define D_DONE "Изпълнено" #define D_DST_TIME "Лятно време" -#define D_ECO2 "eCO₂" +#define D_ECO2 "eCO2" #define D_EMULATION "Емулация" #define D_ENABLED "Разрешен" #define D_ERASE "Изтриване" @@ -114,7 +114,7 @@ #define D_LWT "LWT" #define D_MODULE "Модул" #define D_MQTT "MQTT" -#define D_MULTI_PRESS "множествено натискане" +#define D_MULTI_PRESS "неколкократно натискане" #define D_NOISE "Шум" #define D_NONE "Няма" #define D_OFF "Изкл." @@ -285,10 +285,10 @@ #define D_LOGGING_PARAMETERS "Параметри на лога" #define D_SERIAL_LOG_LEVEL "Степен на серийния лог" -#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_MQTT_LOG_LEVEL "Степен на MQTT лога" #define D_WEB_LOG_LEVEL "Степен на уеб лога" #define D_SYS_LOG_LEVEL "Степен на системния лог" -#define D_MORE_DEBUG "Още дебъгване" +#define D_MORE_DEBUG "Допълнителна debug информация" #define D_SYSLOG_HOST "Хост на системния лог" #define D_SYSLOG_PORT "Порт на системния лог" #define D_TELEMETRY_PERIOD "Период на телеметрия" @@ -382,7 +382,7 @@ #define D_HUE "Hue" #define D_HUE_BRIDGE_SETUP "Настройка на Hue bridge" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API не е внедрено" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API не е внедрен" #define D_HUE_API "Hue API" #define D_HUE_POST_ARGS "Hue POST аргументи" #define D_3_RESPONSE_PACKETS_SENT "Изпратени са 3 пакета за отговор" @@ -444,17 +444,17 @@ #define D_ENERGY_TOTAL "Използвана енергия общо" // xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" +#define D_OPEN "Отворена" +#define D_CLOSE "Затворена" +#define D_DOMOTICZ_SHUTTER "Щора" // xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" +#define D_CONFIGURE_PCF8574 "Конфигуриране на PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 параметри" +#define D_INVERT_PORTS "Обърни портовете" +#define D_DEVICE "Устройство" +#define D_DEVICE_INPUT "Вход" +#define D_DEVICE_OUTPUT "Изход" // xsns_05_ds18b20.ino #define D_SENSOR_BUSY "Датчикът DS18x20 е зает" @@ -675,27 +675,27 @@ #define D_UNIT_ANGLE "°" //SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" +#define D_PV1_VOLTAGE "Напрежение на PV1" +#define D_PV1_CURRENT "Ток на PV1" +#define D_PV1_POWER "Мощност на PV1" +#define D_PV2_VOLTAGE "Напрежение на PV2" +#define D_PV2_CURRENT "Ток на PV2" +#define D_PV2_POWER "Мощност на PV2" +#define D_SOLAR_POWER "Слънчева мощност" +#define D_INVERTER_POWER "Мощност на инвертера" +#define D_STATUS "Състояние" +#define D_WAITING "Очакване" +#define D_CHECKING "Проверка" +#define D_WORKING "Работи" +#define D_FAILURE "Грешка" +#define D_SOLAX_ERROR_0 "Грешка - няма код" +#define D_SOLAX_ERROR_1 "Грешка - загуба на мрежата" +#define D_SOLAX_ERROR_2 "Грешка - мрежово напрежение" +#define D_SOLAX_ERROR_3 "Грешка - мрежова честота" +#define D_SOLAX_ERROR_4 "Грешка - напрежение на Pv" +#define D_SOLAX_ERROR_5 "Грешка - проблем с изолацията" +#define D_SOLAX_ERROR_6 "Грешка - прегряване" +#define D_SOLAX_ERROR_7 "Грешка - вентилатор" +#define D_SOLAX_ERROR_8 "Грешка - друго оборудване" #endif // _LANGUAGE_BG_BG_H_ From e53f637bb6b94b81ca2b3f335f1fabea6a6882c6 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Thu, 12 Dec 2019 16:05:58 +0100 Subject: [PATCH 054/559] Mode definitions to i18 to enable other modules to use shutters --- tasmota/i18n.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index f4fde64b3..fed6930d7 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -494,6 +494,24 @@ #define D_JSON_MOTOR_MIS "setMIS" #endif + // Commands xdrv_27_Shutter.ino + #ifdef USE_SHUTTER + #define D_PRFX_SHUTTER "Shutter" + #define D_CMND_SHUTTER_OPEN "Open" + #define D_CMND_SHUTTER_CLOSE "Close" + #define D_CMND_SHUTTER_STOP "Stop" + #define D_CMND_SHUTTER_POSITION "Position" + #define D_CMND_SHUTTER_OPENTIME "OpenDuration" + #define D_CMND_SHUTTER_CLOSETIME "CloseDuration" + #define D_CMND_SHUTTER_RELAY "Relay" + #define D_CMND_SHUTTER_SETHALFWAY "SetHalfway" + #define D_CMND_SHUTTER_SETCLOSE "SetClose" + #define D_CMND_SHUTTER_INVERT "Invert" + #define D_CMND_SHUTTER_CLIBRATION "Calibration" + #define D_CMND_SHUTTER_MOTORDELAY "MotorDelay" + #define D_CMND_SHUTTER_FREQUENCY "Frequency" + #endif + /********************************************************************************************/ // Log message prefix From c9703c5584db4f19b237c0b35003fe91ad31fc0c Mon Sep 17 00:00:00 2001 From: znanev <20048364+znanev@users.noreply.github.com> Date: Thu, 12 Dec 2019 15:11:21 +0000 Subject: [PATCH 055/559] Update bg-BG.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change eCO2 to eCO₂ --- tasmota/language/bg-BG.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index d91db2dee..1f18d8efb 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -83,7 +83,7 @@ #define D_DNS_SERVER "DNS Сървър" #define D_DONE "Изпълнено" #define D_DST_TIME "Лятно време" -#define D_ECO2 "eCO2" +#define D_ECO2 "eCO₂" #define D_EMULATION "Емулация" #define D_ENABLED "Разрешен" #define D_ERASE "Изтриване" From 29de8b9dce5607326d8d42a6f5b28128cd93388e Mon Sep 17 00:00:00 2001 From: stefanbode Date: Thu, 12 Dec 2019 16:14:06 +0100 Subject: [PATCH 056/559] Update several functions - finally, secure pressing DOWN/UP button when shutter already in end-position will not turn ON the relay - remove shutter commands to main to allow other modules to interact - fix some overrun and underrun issues to end-positions --- tasmota/xdrv_27_shutter.ino | 104 +++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 44 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 8bc13dfa4..b3c02c80f 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -24,27 +24,10 @@ #define XDRV_27 27 -#define D_PRFX_SHUTTER "Shutter" -#define D_CMND_SHUTTER_OPEN "Open" -#define D_CMND_SHUTTER_CLOSE "Close" -#define D_CMND_SHUTTER_STOP "Stop" -#define D_CMND_SHUTTER_POSITION "Position" -#define D_CMND_SHUTTER_OPENTIME "OpenDuration" -#define D_CMND_SHUTTER_CLOSETIME "CloseDuration" -#define D_CMND_SHUTTER_RELAY "Relay" -#define D_CMND_SHUTTER_SETHALFWAY "SetHalfway" -#define D_CMND_SHUTTER_SETCLOSE "SetClose" -#define D_CMND_SHUTTER_INVERT "Invert" -#define D_CMND_SHUTTER_CLIBRATION "Calibration" -#define D_CMND_SHUTTER_MOTORDELAY "MotorDelay" -#define D_CMND_SHUTTER_FREQUENCY "Frequency" - #define D_SHUTTER "SHUTTER" const uint16_t MOTOR_STOP_TIME = 500; // in mS - - uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; uint16_t messwerte[5] = {30,50,70,90,100}; @@ -82,9 +65,10 @@ struct SHUTTER { uint16_t close_velocity[MAX_SHUTTERS]; // in relation to open velocity. higher value = faster int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE - uint8_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. + int16_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. uint16_t pwm_frequency; // frequency of PWN for stepper motors - uint16_t max_pwm_frequency = 1000; + uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency that can be used. depend on the motor and drivers + uint8_t skip_relay_change; // avoid overrun at endstops } Shutter; void ShutterRtc50mS(void) @@ -99,7 +83,7 @@ int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index) if (Settings.shutter_set50percent[index] != 50) { return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; } else { - uint32_t realpos; + int32_t realpos; // check against DIV 0 for (uint8_t j=0 ; j < 5 ; j++) { if (Settings.shuttercoeff[j][index] == 0) { @@ -133,7 +117,7 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t index) if (Settings.shutter_set50percent[index] != 50) { return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; } else { - uint16_t realpercent; + int16_t realpercent; for (uint8_t i=0 ; i < 5 ; i++) { if (realpos > Shutter.open_max[index] * calibrate_pos[i+1] / 100) { @@ -151,7 +135,7 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t index) break; } } - return realpercent; + return (realpercent < 0 ? 0 : (realpercent > 100 ? 0 : realpercent)); } } @@ -230,7 +214,7 @@ void ShutterInit(void) dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); char shutter_close_chr[10]; dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d,motordelay %d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d,motordelay %d"), i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], Shutter.mask, Settings.shutter_invert[i], Shutter.mode, Shutter.motordelay[i]); @@ -257,7 +241,7 @@ void ShutterUpdatePosition(void) // Counter should be initiated to 0 to count movement. // 0..1000 in step 100 = 10 steps with 0.05 sec = 0.5sec total ramp time from start to // full speed. - if (pin[GPIO_PWM1+i] < 99 && Shutter.pwm_frequency != Shutter.max_pwm_frequency) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99 && Shutter.pwm_frequency != Shutter.max_pwm_frequency) { Shutter.pwm_frequency += Shutter.max_pwm_frequency/20; Shutter.pwm_frequency = (Shutter.pwm_frequency > Shutter.max_pwm_frequency ? Shutter.max_pwm_frequency : Shutter.pwm_frequency); analogWriteFreq(Shutter.pwm_frequency); @@ -266,7 +250,7 @@ void ShutterUpdatePosition(void) Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); // avoid real position leaving the boundaries. - Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ; + // Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ; if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) { @@ -295,8 +279,9 @@ void ShutterUpdatePosition(void) analogWrite(pin[GPIO_PWM1+i], 50); //prepare for stop PWM Shutter.motordelay[i] = -2 + Shutter.motordelay[i] + missing_steps/(Shutter.max_pwm_frequency/20); + Shutter.motordelay[i] = Shutter.motordelay[i] > 0 ? Shutter.motordelay[i] : 0; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Missing steps %d, adjust motordelay %d, counter %d, temp realpos %d"), missing_steps, Shutter.motordelay[i],RtcSettings.pulse_counter[i] ,Shutter.real_position[i]); - Settings.shutter_motordelay[i]=(missing_steps > 0 ? Shutter.motordelay[i] : 0); + Settings.shutter_motordelay[i]=Shutter.motordelay[i]; analogWriteFreq(0); while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { delay(1); @@ -351,19 +336,35 @@ bool ShutterState(uint8_t device) (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) ); } -void ShutterStartInit(uint8_t index, uint8_t direction, int32_t target_pos) +void ShutterStartInit(uint8_t index, int8_t direction, int32_t target_pos) { - Shutter.direction[index] = direction; - Shutter.target_position[index] = target_pos; - Shutter.start_position[index] = Shutter.real_position[index]; - Shutter.time[index] = 0; - if (pin[GPIO_PWM1+index] < 99) { - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+index], 0); - // can be operated without counter, but then not that acurate. - if (pin[GPIO_CNTR1+index] < 99) { - RtcSettings.pulse_counter[index] = 0; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter.open_max[index] - Shutter.real_position[index]) / Shutter.close_velocity[index], Shutter.real_position[index] / Shutter.close_velocity[index], 2+Shutter.motordelay[index]); + if (direction == 1 && (Shutter.open_max[index] - Shutter.real_position[index]) / Shutter.close_velocity[index] <= 2+Shutter.motordelay[index]) { + // shutter alread 100% cannot move further + // store relay number variable + Shutter.skip_relay_change = 1 ; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: 100%% endstop already reached: Relay %d"),Shutter.skip_relay_change); + + } else if (direction == -1 && Shutter.real_position[index] / Shutter.close_velocity[index] <= 2+Shutter.motordelay[index]) { + // shutter already at 0% connot move into minus + // store relay number variable + Shutter.skip_relay_change = 1; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: 0%% endstop already reached: Relay %d"),Shutter.skip_relay_change); + + } else { + Shutter.direction[index] = direction; + Shutter.target_position[index] = target_pos; + Shutter.start_position[index] = Shutter.real_position[index]; + Shutter.time[index] = 0; + Shutter.skip_relay_change = 0; + if (pin[GPIO_PWM1+index] < 99) { + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+index], 0); + // can be operated without counter, but then not that acurate. + if (pin[GPIO_CNTR1+index] < 99) { + RtcSettings.pulse_counter[index] = 0; + } } } //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]); @@ -378,7 +379,7 @@ void ShutterDelayForMotorStop(void) void ShutterReportPosition(void) { uint16_t shutter_moving = 0; - for (uint32_t i = 0; i < shutters_present; i++) { + for (uint8_t i = 0; i < shutters_present; i++) { if (Shutter.direction[i] != 0) { char stemp1[20]; char stemp2[10]; @@ -414,7 +415,7 @@ void ShutterRelayChanged(void) switch (powerstate_local) { case 1: ShutterDelayForMotorStop(); - ShutterStartInit(i, 1, Shutter.open_max[i]); + ShutterStartInit(i, 1, Shutter.open_max[i]); break; case 3: ShutterDelayForMotorStop(); @@ -652,7 +653,7 @@ void CmndShutterSetClose(void) Shutter.real_position[XdrvMailbox.index -1] = 0; ShutterStartInit(XdrvMailbox.index -1, 0, 0); Settings.shutter_position[XdrvMailbox.index -1] = 0; - ResponseCmndChar(D_CONFIGURATION_RESET); + ResponseCmndIdxChar(D_CONFIGURATION_RESET); } } @@ -717,7 +718,7 @@ bool Xdrv27(uint8_t function) result = DecodeCommand(kShutterCommands, ShutterCommand); break; case FUNC_JSON_APPEND: - for (uint32_t i = 0; i < shutters_present; i++) { + for (uint8_t i = 0; i < shutters_present; i++) { uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; ResponseAppend_P(","); ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); @@ -731,10 +732,25 @@ bool Xdrv27(uint8_t function) case FUNC_SET_POWER: char stemp1[10]; // extract the number of the relay that was switched and save for later in Update Position. - Shutter.switched_relay = power ^ Shutter.old_power; - Shutter.old_power = power; + Shutter.switched_relay = XdrvMailbox.index ^ Shutter.old_power; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), Shutter.switched_relay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); ShutterRelayChanged(); + Shutter.old_power = XdrvMailbox.index; + break; + case FUNC_SET_DEVICE_POWER: + if (Shutter.skip_relay_change ) { + uint8_t i; + for (i = 0; i < devices_present; i++) { + if (Shutter.switched_relay &1) { + break; + } + Shutter.switched_relay >>= 1; + } + //AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: skip relay change: %d"),i+1); + result = true; + Shutter.skip_relay_change = 0; + ExecuteCommandPower(i+1, 0, SRC_SHUTTER); + } break; } } From bfeaabfc7f5a3dc3ac26e87935f1cd5c25e560a9 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Thu, 12 Dec 2019 17:03:25 +0100 Subject: [PATCH 057/559] typo --- tasmota/xdrv_27_shutter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index b3c02c80f..2338639a1 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -214,7 +214,7 @@ void ShutterInit(void) dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); char shutter_close_chr[10]; dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d,motordelay %d"), + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d,motordelay %d"), i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], Shutter.mask, Settings.shutter_invert[i], Shutter.mode, Shutter.motordelay[i]); From 666cc86c9eed2dd827af9667b924c49aa1c03980 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Thu, 12 Dec 2019 16:32:54 -0300 Subject: [PATCH 058/559] Allow to disable SNTP when using TIME --- tasmota/support_rtc.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 27ef66ec7..890604ee0 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -460,7 +460,9 @@ void RtcSetTime(uint32_t epoch) if (epoch < START_VALID_TIME) { // 2016-01-01 Rtc.user_time_entry = false; ntp_force_sync = true; + sntp_init(); } else { + sntp_stop(); Rtc.user_time_entry = true; Rtc.utc_time = epoch -1; // Will be corrected by RtcSecond } From 7d8a4f5077ed51c513c51fbb02240b4fa59c0a18 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Thu, 12 Dec 2019 22:22:34 +0100 Subject: [PATCH 059/559] Fix Zigbee crash #7187 --- tasmota/xdrv_23_zigbee_9_impl.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index cb08eeaee..9a08c3585 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -235,13 +235,14 @@ void ZigbeeInit(void) * Commands \*********************************************************************************************/ -uint32_t strToUInt(const JsonVariant val) { +uint32_t strToUInt(const JsonVariant &val) { // if the string starts with 0x, it is considered Hex, otherwise it is an int if (val.is()) { return val.as(); } else { - if (val.is()) { - return strtoull(val.as(), nullptr, 0); + if (val.is()) { + String sval = val.as(); + return strtoull(sval.c_str(), nullptr, 0); } } return 0; // couldn't parse anything @@ -593,6 +594,7 @@ void CmndZigbeeRead(void) { const JsonVariant &val_attr = getCaseInsensitive(json, PSTR("Read")); if (nullptr != &val_attr) { + uint16_t val = strToUInt(val_attr); if (val_attr.is()) { JsonArray& attr_arr = val_attr; attrs_len = attr_arr.size() * 2; @@ -604,11 +606,9 @@ void CmndZigbeeRead(void) { attrs[i++] = val & 0xFF; attrs[i++] = val >> 8; } - } else { attrs_len = 2; attrs = new uint8_t[attrs_len]; - uint16_t val = strToUInt(val_attr); attrs[0] = val & 0xFF; // little endian attrs[1] = val >> 8; } From 0c717ddbac4d08da681da09f69addcb583e9bdf6 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Thu, 12 Dec 2019 22:32:00 +0100 Subject: [PATCH 060/559] Added ResponseCmndDone() to ZigbeeRead --- tasmota/xdrv_23_zigbee_9_impl.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 9a08c3585..4e2ba5499 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -614,9 +614,10 @@ void CmndZigbeeRead(void) { } } - ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); - if (attrs) { delete[] attrs; } + if (attrs) { delete[] attrs; } + ResponseCmndDone(); } // Allow or Deny pairing of new Zigbee devices From 21fa1fa04e2bd8872be15b42889afc687badf754 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 13 Dec 2019 12:05:07 +0100 Subject: [PATCH 061/559] Bump version to 7.1.2.5 Change some Settings locations freeing up space for future single char allowing variable length text --- RELEASENOTES.md | 3 ++- tasmota/CHANGELOG.md | 4 +++ tasmota/settings.h | 49 +++++++++++++++++++++++++--------- tasmota/settings.ino | 10 +++++-- tasmota/support_statistics.ino | 9 +------ tasmota/tasmota_version.h | 2 +- 6 files changed, 52 insertions(+), 25 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d269109e8..0f5e1e33b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,12 +47,13 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 7.1.2.4 +### Version 7.1.2.5 - Change Exception reporting removing exception details from ``Status 1`` and consolidated in ``Status 12`` if available - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) - Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) - Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167) +- Change some Settings locations freeing up space for future single char allowing variable length text - Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649) - Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) - Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 4bbeccb26..970d22ca7 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 7.1.2.5 20191213 + +- Change some Settings locations freeing up space for future single char allowing variable length text + ### 7.1.2.4 20191209 - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) diff --git a/tasmota/settings.h b/tasmota/settings.h index c938f0b39..d05777d17 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -248,26 +248,34 @@ struct SYSCFG { SysBitfield flag; // 010 int16_t save_data; // 014 int8_t timezone; // 016 + + // Start of single char array + char ota_url[101]; // 017 char mqtt_prefix[3][11]; // 07C + uint8_t ex_baudrate; // 09D - Free since 6.6.0.9 - uint8_t seriallog_level; // 09E - uint8_t sta_config; // 09F - uint8_t sta_active; // 0A0 + uint8_t ex_seriallog_level; // 09E + uint8_t ex_sta_config; // 09F + uint8_t ex_sta_active; // 0A0 + char sta_ssid[2][33]; // 0A1 - Keep together with sta_pwd as being copied as one chunck with reset 5 char sta_pwd[2][65]; // 0E3 - Keep together with sta_ssid as being copied as one chunck with reset 5 char hostname[33]; // 165 char syslog_host[33]; // 186 - uint8_t rule_stop; // 1A7 - uint16_t syslog_port; // 1A8 - uint8_t syslog_level; // 1AA - uint8_t webserver; // 1AB - uint8_t weblog_level; // 1AC - uint8_t mqtt_fingerprint[2][20]; // 1AD - uint8_t adc_param_type; // 1D5 + + uint8_t ex_rule_stop; // 1A7 + uint16_t ex_syslog_port; // 1A8 + uint8_t ex_syslog_level; // 1AA + uint8_t ex_webserver; // 1AB + uint8_t ex_weblog_level; // 1AC + uint8_t ex_mqtt_fingerprint[2][20]; // 1AD + uint8_t ex_adc_param_type; // 1D5 uint8_t free_1d6[10]; // 1D6 + // End of single char array of 446 chars max (phase 3) + SysBitfield4 flag4; // 1E0 uint8_t serial_config; // 1E4 uint8_t wifi_output_power; // 1E5 @@ -282,6 +290,9 @@ struct SYSCFG { char mqtt_topic[33]; // 26F - Keep together with above items as being copied as one chunck with reset 6 char button_topic[33]; // 290 char mqtt_grptopic[33]; // 2B1 + + // Optional end of single char array of 698 chars max (phase 5) + uint8_t display_model; // 2D2 uint8_t display_mode; // 2D3 uint8_t display_refresh; // 2D4 @@ -302,7 +313,9 @@ struct SYSCFG { int16_t toffset[2]; // 30E uint8_t display_font; // 312 char state_text[4][11]; // 313 + uint8_t ex_energy_power_delta; // 33F - Free since 6.6.0.20 + uint16_t domoticz_update_timer; // 340 uint16_t pwm_range; // 342 unsigned long domoticz_relay_idx[MAX_DOMOTICZ_IDX]; // 344 @@ -338,7 +351,7 @@ struct SYSCFG { char friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC char switch_topic[33]; // 430 char serial_delimiter; // 451 - uint8_t ex_sbaudrate; // 452 - Free since 6.6.0.9 + uint8_t seriallog_level; // 452 uint8_t sleep; // 453 uint16_t domoticz_switch_idx[MAX_DOMOTICZ_IDX]; // 454 uint16_t domoticz_sensor_idx[MAX_DOMOTICZ_SNS_IDX]; // 45C @@ -398,7 +411,6 @@ struct SYSCFG { uint16_t baudrate; // 778 uint16_t sbaudrate; // 77A EnergyUsage energy_usage; // 77C -// uint32_t drivers[3]; // 794 - 6.5.0.12 replaced by below three entries uint32_t adc_param1; // 794 uint32_t adc_param2; // 798 int adc_param3; // 79C @@ -414,7 +426,9 @@ struct SYSCFG { unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight uint16_t web_refresh; // 7CC char mems[MAX_RULE_MEMS][10]; // 7CE + char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b + TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes uint16_t ina226_r_shunt[4]; // E20 uint16_t ina226_i_fs[4]; // E28 @@ -436,8 +450,17 @@ struct SYSCFG { uint8_t weight_change; // E9F uint8_t web_color2[2][3]; // EA0 - Needs to be on integer / 3 distance from web_color char cors_domain[33]; // EA6 + uint8_t sta_config; // EC7 + uint8_t sta_active; // EC8 + uint8_t rule_stop; // EC9 + uint16_t syslog_port; // ECA + uint8_t syslog_level; // ECC + uint8_t webserver; // ECD + uint8_t weblog_level; // ECE + uint8_t mqtt_fingerprint[2][20]; // ECF + uint8_t adc_param_type; // EF7 - uint8_t free_ec7[293]; // EC7 + uint8_t free_ef8[244]; // EF8 uint32_t i2c_drivers[3]; // FEC I2cDriver uint32_t cfg_timestamp; // FF8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index d616d4cfc..866e72f99 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1230,8 +1230,8 @@ void SettingsDelta(void) } } if (Settings.version < 0x06060009) { - Settings.baudrate = Settings.ex_baudrate * 4; - Settings.sbaudrate = Settings.ex_sbaudrate * 4; + Settings.baudrate = APP_BAUDRATE / 300; + Settings.sbaudrate = SOFT_BAUDRATE / 300; } if (Settings.version < 0x0606000A) { uint8_t tuyaindex = 0; @@ -1336,6 +1336,12 @@ void SettingsDelta(void) Settings.cors_domain[0] = 0; } } + if (Settings.version < 0x07010205) { + Settings.seriallog_level = Settings.ex_seriallog_level; // 09E -> 452 + Settings.sta_config = Settings.ex_sta_config; // 09F -> EC7 + Settings.sta_active = Settings.ex_sta_active; // 0A0 -> EC8 + memcpy((char*)&Settings.rule_stop, (char*)&Settings.ex_rule_stop, 47); // 1A7 -> EC9 + } Settings.version = VERSION; SettingsSave(1); diff --git a/tasmota/support_statistics.ino b/tasmota/support_statistics.ino index efd94f307..a34c7250a 100644 --- a/tasmota/support_statistics.ino +++ b/tasmota/support_statistics.ino @@ -27,24 +27,17 @@ struct STATS { // uint32_t str_size = 1151; // Total number of characters reserved as char array in Settings uint32_t str_len = 0; // Total number of characters used within char array - uint32_t str_char = 0; // Total number of character '|' within all char arrays } Stats; void StatisticsChar(const char* text) { uint32_t len = strlen(text); Stats.str_len += len; - for (uint32_t i = 0; i < len; i++) { - if ('|' == text[i]) { // Text string separator as currently used in GetTextIndexed() - Stats.str_char++; - } - } } String GetStatistics(void) { Stats.str_len = 0; - Stats.str_char = 0; for (uint32_t i = 0; i < 2; i++) { StatisticsChar(Settings.sta_ssid[i]); @@ -77,7 +70,7 @@ String GetStatistics(void) StatisticsChar(Settings.cors_domain); char data[40]; - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151/%d\""), Stats.str_len, Stats.str_char); // Char Usage Ratio + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151\""), Stats.str_len); // Char Usage Ratio return String(data); } diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index a0cbe1e41..ccc8dcbaf 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010204; +const uint32_t VERSION = 0x07010205; #endif // _TASMOTA_VERSION_H_ From 25c9666f2dfc6e0e90e551603089ab04ba288f2b Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 14 Dec 2019 12:06:59 +0100 Subject: [PATCH 062/559] Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor --- tasmota/CHANGELOG.md | 1 + tasmota/support_float.ino | 1 + tasmota/xdrv_23_zigbee_5_converters.ino | 287 ++++++++---------------- tasmota/xdrv_23_zigbee_8_parsers.ino | 2 +- tasmota/xdrv_23_zigbee_9_impl.ino | 4 +- 5 files changed, 99 insertions(+), 196 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 970d22ca7..8ffde8562 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 7.1.2.5 20191213 - Change some Settings locations freeing up space for future single char allowing variable length text +- Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor ### 7.1.2.4 20191209 diff --git a/tasmota/support_float.ino b/tasmota/support_float.ino index 21ec2f47d..d08fc13f9 100644 --- a/tasmota/support_float.ino +++ b/tasmota/support_float.ino @@ -172,6 +172,7 @@ double const f_sixthpi = f_pi / 6.0; // f_pi/6.0, used in double const f_tansixthpi = tan(f_sixthpi); // tan(f_pi/6), used in atan routines double const f_twelfthpi = f_pi / 12.0; // f_pi/12.0, used in atan routines double const f_tantwelfthpi = tan(f_twelfthpi); // tan(f_pi/12), used in atan routines +float const f_180pi = 180 / f_pi; // 180 / pi for angles in degrees // ******************************************************************* // *** diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index bf58a80b9..4defbf043 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -49,31 +49,26 @@ public: }; - void publishMQTTReceived(uint16_t groupid, uint16_t clusterid, Z_ShortAddress srcaddr, + void publishMQTTReceived(uint16_t groupid, uint16_t clusterid, uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, uint32_t timestamp) { #ifdef ZIGBEE_VERBOSE char hex_char[_payload.len()*2+2]; ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," "\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," "\"timestamp\":%d," "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," - "\"cmdid\":\"0x%02X\",\"payload\":\"%s\""), + "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), groupid, clusterid, srcaddr, srcendpoint, dstendpoint, wasbroadcast, linkquality, securityuse, seqnumber, timestamp, _frame_control, _manuf_code, _transact_seq, _cmd_id, hex_char); - - ResponseJsonEnd(); // append '}' - ResponseJsonEnd(); // append '}' - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); #endif } @@ -126,6 +121,10 @@ public: return _payload; } + uint16_t getManufCode(void) const { + return _manuf_code; + } + private: ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; uint16_t _manuf_code = 0; // optional @@ -456,7 +455,7 @@ void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { // return value: // 0 = keep initial value // 1 = remove initial value -typedef int32_t (*Z_AttrConverter)(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper* new_name); +typedef int32_t (*Z_AttrConverter)(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper* new_name, uint16_t cluster, uint16_t attr); typedef struct Z_AttributeConverter { uint16_t cluster; uint16_t attribute; @@ -625,6 +624,11 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0101, 0x0004, "DoorOpenEvents", &Z_Copy }, { 0x0101, 0x0005, "DoorClosedEvents", &Z_Copy }, { 0x0101, 0x0006, "OpenPeriod", &Z_Copy }, + // Aqara Lumi Vibration Sensor + { 0x0101, 0x0055, "AqaraVibrationMode", &Z_AqaraVibration }, + { 0x0101, 0x0503, "AqaraVibrationsOrAngle", &Z_Copy }, + { 0x0101, 0x0505, "AqaraVibration505", &Z_Copy }, + { 0x0101, 0x0508, "AqaraAccelerometer", &Z_AqaraVibration }, // Window Covering cluster { 0x0102, 0x0000, "WindowCoveringType", &Z_Copy }, { 0x0102, 0x0001, "PhysicalClosedLimitLift",&Z_Copy }, @@ -753,13 +757,13 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { // ====================================================================== // Record Manuf -int32_t Z_ManufKeep(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { +int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { json[new_name] = value; zigbee_devices.setManufId(shortaddr, value.as()); return 1; } // -int32_t Z_ModelKeep(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { +int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { json[new_name] = value; zigbee_devices.setModelId(shortaddr, value.as()); return 1; @@ -767,34 +771,89 @@ int32_t Z_ModelKeep(uint16_t shortaddr, JsonObject& json, const char *name, Json // ====================================================================== // Remove attribute -int32_t Z_Remove(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { +int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { return 1; // remove original key } // Copy value as-is -int32_t Z_Copy(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { +int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { json[new_name] = value; return 1; // remove original key } // Add pressure unit -int32_t Z_AddPressureUnit(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { +int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { json[new_name] = F(D_UNIT_PRESSURE); return 0; // keep original key } // Convert int to float and divide by 100 -int32_t Z_FloatDiv100(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { +int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { json[new_name] = ((float)value) / 100.0f; return 1; // remove original key } // Convert int to float and divide by 10 -int32_t Z_FloatDiv10(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { +int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { json[new_name] = ((float)value) / 10.0f; return 1; // remove original key } -int32_t Z_AqaraSensor(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name) { +// Aqara Vibration Sensor - special proprietary attributes +int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { + //json[new_name] = value; + switch (attr) { + case 0x0055: + { + int32_t ivalue = value; + const __FlashStringHelper * svalue; + switch (ivalue) { + case 1: svalue = F("vibrate"); break; + case 2: svalue = F("tilt"); break; + case 3: svalue = F("drop"); break; + default: svalue = F("unknown"); break; + } + json[new_name] = svalue; + } + break; + // case 0x0503: + // break; + // case 0x0505: + // break; + case 0x0508: + { + // see https://github.com/Koenkk/zigbee2mqtt/issues/295 and http://faire-ca-soi-meme.fr/domotique/2018/09/03/test-xiaomi-aqara-vibration-sensor/ + // report accelerometer measures + String hex = value; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + int16_t x, y, z; + z = buf2.get16(0); + y = buf2.get16(2); + x = buf2.get16(4); + JsonArray& xyz = json.createNestedArray(new_name); + xyz.add(x); + xyz.add(y); + xyz.add(z); + // calculate angles + float X = x; + float Y = y; + float Z = z; + int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; + int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; + int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; + // int32_t Angle_X = 0.5f + atanf(X/sqrtf(Z*Z+Y*Y)) * f_180pi; + // int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(X*X+Z*Z)) * f_180pi; + // int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(X*X+Y*Y)) * f_180pi; + JsonArray& angles = json.createNestedArray(F("AqaraAngles")); + angles.add(Angle_X); + angles.add(Angle_Y); + angles.add(Angle_Z); + } + break; + } + return 1; // remove original key +} + +int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { String hex = value; SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); uint32_t i = 0; @@ -809,36 +868,31 @@ int32_t Z_AqaraSensor(uint16_t shortaddr, JsonObject& json, const char *name, Js i += parseSingleAttribute(json, tmp, buf2, i, len); float val = json[tmp]; json.remove(tmp); - if (0x64 == attrid) { - json[F(D_JSON_TEMPERATURE)] = val / 100.0f; - } else if (0x65 == attrid) { - json[F(D_JSON_HUMIDITY)] = val / 100.0f; - } else if (0x66 == attrid) { - json[F(D_JSON_PRESSURE)] = val / 100.0f; - json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa - } else if (0x01 == attrid) { + if (0x01 == attrid) { json[F(D_JSON_VOLTAGE)] = val / 1000.0f; json[F("Battery")] = toPercentageCR2032(val); + } else if (0 == zcl->getManufCode()) { + // onla Aqara Temp/Humidity has manuf_code of zero. If non-zero we skip the parameters + if (0x64 == attrid) { + json[F(D_JSON_TEMPERATURE)] = val / 100.0f; + } else if (0x65 == attrid) { + json[F(D_JSON_HUMIDITY)] = val / 100.0f; + } else if (0x66 == attrid) { + json[F(D_JSON_PRESSURE)] = val / 100.0f; + json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa + } else if (0x01 == attrid) { + json[F(D_JSON_VOLTAGE)] = val / 1000.0f; + json[F("Battery")] = toPercentageCR2032(val); + } + } else if (0x115F == zcl->getManufCode()) { + // Aqara Motion Sensor, still unknown field + json[F("AqaraUnknown")] = val; } } return 1; // remove original key } // ====================================================================== -// Cluster Specific commands -// #define ZCL_OO_OFF "s_0006_00" // Cluster 0x0006, cmd 0x00 - On/Off - Off -// #define ZCL_OO_ON "s_0006_01" // Cluster 0x0006, cmd 0x01 - On/Off - On -// #define ZCL_COLORTEMP_MOVE "s_0300_0A" // Cluster 0x0300, cmd 0x0A, Move to Color Temp -// #define ZCL_LC_MOVE "s_0008_00" // Cluster 0x0008, cmd 0x00, Level Control Move to Level -// #define ZCL_LC_MOVE_1 "s_0008_01" // Cluster 0x0008, cmd 0x01, Level Control Move -// #define ZCL_LC_STEP "s_0008_02" // Cluster 0x0008, cmd 0x02, Level Control Step -// #define ZCL_LC_STOP "s_0008_03" // Cluster 0x0008, cmd 0x03, Level Control Stop -// #define ZCL_LC_MOVE_WOO "s_0008_04" // Cluster 0x0008, cmd 0x04, Level Control Move to Level, with On/Off -// #define ZCL_LC_MOVE_1_WOO "s_0008_05" // Cluster 0x0008, cmd 0x05, Level Control Move, with On/Off -// #define ZCL_LC_STEP_WOO "s_0008_06" // Cluster 0x0008, cmd 0x05, Level Control Step, with On/Off -// #define ZCL_LC_STOP_WOO "s_0008_07" // Cluster 0x0008, cmd 0x07, Level Control Stop - - void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { // iterate on json elements for (auto kv : json) { @@ -859,7 +913,7 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { if ((conv_cluster == cluster) && ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { - int32_t drop = (*converter->func)(shortaddr, json, key, value, (const __FlashStringHelper*) converter->name); + int32_t drop = (*converter->func)(this, shortaddr, json, key, value, (const __FlashStringHelper*) converter->name, conv_cluster, conv_attribute); if (drop) { json.remove(key); } @@ -870,157 +924,4 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { } } -//void ZCLFrame::postProcessAttributes2(JsonObject& json) { -// void postProcessAttributes2(JsonObject& json) { -// const __FlashStringHelper *key; -// -// // Osram Mini Switch -// key = F(ZCL_OO_OFF); -// if (json.containsKey(key)) { -// json.remove(key); -// json[F(D_CMND_POWER)] = F("Off"); -// } -// key = F(ZCL_OO_ON); -// if (json.containsKey(key)) { -// json.remove(key); -// json[F(D_CMND_POWER)] = F("On"); -// } -// key = F(ZCL_COLORTEMP_MOVE); -// if (json.containsKey(key)) { -// String hex = json[key]; -// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); -// uint16_t color_temp = buf2.get16(0); -// uint16_t transition_time = buf2.get16(2); -// json.remove(key); -// json[F("ColorTemp")] = color_temp; -// json[F("TransitionTime")] = transition_time / 10.0f; -// } -// key = F(ZCL_LC_MOVE_WOO); -// if (json.containsKey(key)) { -// String hex = json[key]; -// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); -// uint8_t level = buf2.get8(0); -// uint16_t transition_time = buf2.get16(1); -// json.remove(key); -// json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); // change to percentage -// json[F("TransitionTime")] = transition_time / 10.0f; -// if (0 == level) { -// json[F(D_CMND_POWER)] = F("Off"); -// } else { -// json[F(D_CMND_POWER)] = F("On"); -// } -// } -// key = F(ZCL_LC_MOVE); -// if (json.containsKey(key)) { -// String hex = json[key]; -// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); -// uint8_t level = buf2.get8(0); -// uint16_t transition_time = buf2.get16(1); -// json.remove(key); -// json[F("Dimmer")] = changeUIntScale(level, 0, 255, 0, 100); // change to percentage -// json[F("TransitionTime")] = transition_time / 10.0f; -// } -// key = F(ZCL_LC_MOVE_1); -// if (json.containsKey(key)) { -// String hex = json[key]; -// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); -// uint8_t move_mode = buf2.get8(0); -// uint8_t move_rate = buf2.get8(1); -// json.remove(key); -// json[F("Move")] = move_mode ? F("Down") : F("Up"); -// json[F("Rate")] = move_rate; -// } -// key = F(ZCL_LC_MOVE_1_WOO); -// if (json.containsKey(key)) { -// String hex = json[key]; -// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); -// uint8_t move_mode = buf2.get8(0); -// uint8_t move_rate = buf2.get8(1); -// json.remove(key); -// json[F("Move")] = move_mode ? F("Down") : F("Up"); -// json[F("Rate")] = move_rate; -// if (0 == move_mode) { -// json[F(D_CMND_POWER)] = F("On"); -// } -// } -// key = F(ZCL_LC_STEP); -// if (json.containsKey(key)) { -// String hex = json[key]; -// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); -// uint8_t step_mode = buf2.get8(0); -// uint8_t step_size = buf2.get8(1); -// uint16_t transition_time = buf2.get16(2); -// json.remove(key); -// json[F("Step")] = step_mode ? F("Down") : F("Up"); -// json[F("StepSize")] = step_size; -// json[F("TransitionTime")] = transition_time / 10.0f; -// } -// key = F(ZCL_LC_STEP_WOO); -// if (json.containsKey(key)) { -// String hex = json[key]; -// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); -// uint8_t step_mode = buf2.get8(0); -// uint8_t step_size = buf2.get8(1); -// uint16_t transition_time = buf2.get16(2); -// json.remove(key); -// json[F("Step")] = step_mode ? F("Down") : F("Up"); -// json[F("StepSize")] = step_size; -// json[F("TransitionTime")] = transition_time / 10.0f; -// if (0 == step_mode) { -// json[F(D_CMND_POWER)] = F("On"); -// } -// } -// key = F(ZCL_LC_STOP); -// if (json.containsKey(key)) { -// json.remove(key); -// json[F("Stop")] = 1; -// } -// key = F(ZCL_LC_STOP_WOO); -// if (json.containsKey(key)) { -// json.remove(key); -// json[F("Stop")] = 1; -// } -// -// // Lumi.weather proprietary field -// key = F(ZCL_LUMI_WEATHER); -// if (json.containsKey(key)) { -// String hex = json[key]; -// SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); -// DynamicJsonBuffer jsonBuffer; -// JsonObject& json_lumi = jsonBuffer.createObject(); -// uint32_t i = 0; -// uint32_t len = buf2.len(); -// char shortaddr[8]; -// -// while (len - i >= 2) { -// uint8_t attrid = buf2.get8(i++); -// -// snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%02X"), attrid); -// -// //json[shortaddr] = parseSingleAttribute(json_lumi, buf2, i, len, nullptr, 0); -// } -// // parse output -// if (json_lumi.containsKey("0x64")) { // Temperature -// int32_t temperature = json_lumi["0x64"]; -// json[F(D_JSON_TEMPERATURE)] = temperature / 100.0f; -// } -// if (json_lumi.containsKey("0x65")) { // Humidity -// uint32_t humidity = json_lumi["0x65"]; -// json[F(D_JSON_HUMIDITY)] = humidity / 100.0f; -// } -// if (json_lumi.containsKey("0x66")) { // Pressure -// int32_t pressure = json_lumi["0x66"]; -// json[F(D_JSON_PRESSURE)] = pressure / 100.0f; -// json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa -// } -// if (json_lumi.containsKey("0x01")) { // Battery Voltage -// uint32_t voltage = json_lumi["0x01"]; -// json[F(D_JSON_VOLTAGE)] = voltage / 1000.0f; -// json[F("Battery")] = toPercentageCR2032(voltage); -// } -// json.remove(key); -// } -// -// } - #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index a610bb882..acd7e5d26 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -398,7 +398,7 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { String msg(""); msg.reserve(100); json_root.printTo(msg); - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeZCLRawReceived: %s"), msg.c_str()); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeZCLRawReceived: %s"), msg.c_str()); zcl_received.postProcessAttributes(srcaddr, json); // Add linkquality diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 4e2ba5499..3bfd6c4e3 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -269,7 +269,7 @@ void CmndZigbeeReset(void) { void CmndZigbeeStatus(void) { if (ZigbeeSerial) { String dump = zigbee_devices.dump(XdrvMailbox.index, XdrvMailbox.payload); - Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.payload, dump.c_str()); + Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); } } @@ -540,7 +540,7 @@ void CmndZigbeeSend(void) { // we have an unsupported command type, just ignore it and fallback to missing command } - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZigbeeCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%s\"}"), + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZigbeeCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%s\"}"), device, endpoint, cmd_str.c_str()); zigbeeZCLSendStr(device, endpoint, cmd_str.c_str()); } else { From 40da54a0ecaf28fee697830d7d6732b3cc9d6ccb Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sat, 14 Dec 2019 12:09:35 +0100 Subject: [PATCH 063/559] New functions shutter: ramp up/down, MQTT reporting - code optimization - shuttermotordelay now defines ramp up and ramp down duration - shutterposition reported through MQTT during movement (HASS support) - improved stop (no underrun anymore) --- tasmota/xdrv_27_shutter.ino | 107 ++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 2338639a1..7194788b7 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -46,6 +46,7 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterFrequency}; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"direction\":%d}"; +const char MSG_SHUTTER_POS[] PROGMEM = "SHT: " D_PRFX_SHUTTER " %d: Real. %d, Stop: %d, dir %d, pulsetimer: %d, motordelay %d, rtc: %s [s], freq %d"; #include @@ -147,8 +148,6 @@ void ShutterInit(void) Shutter.old_power = power; bool relay_in_interlock = false; - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Accuracy digits: %d"), Settings.shutter_accuracy); - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { // upgrade to 0.1sec calculation base. if ( Settings.shutter_accuracy == 0) { @@ -223,6 +222,9 @@ void ShutterInit(void) // terminate loop at first INVALID shutter. break; } + if (shutters_present < 4) { + Shutter.max_pwm_frequency = Settings.shuttercoeff[4][4]; + } Settings.shutter_accuracy = 1; } } @@ -237,22 +239,25 @@ void ShutterUpdatePosition(void) if (Shutter.direction[i] != 0) { //char stemp1[20]; - // frequency start at 0. Stepper will start moving with first change of the Speed - // Counter should be initiated to 0 to count movement. - // 0..1000 in step 100 = 10 steps with 0.05 sec = 0.5sec total ramp time from start to - // full speed. - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99 && Shutter.pwm_frequency != Shutter.max_pwm_frequency) { - Shutter.pwm_frequency += Shutter.max_pwm_frequency/20; - Shutter.pwm_frequency = (Shutter.pwm_frequency > Shutter.max_pwm_frequency ? Shutter.max_pwm_frequency : Shutter.pwm_frequency); + + if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { + // Calculate position with counter. Much more accurate and no need for motordelay workaround + // aading some counters to stop early + Shutter.real_position[i] = Shutter.start_position[i] + ( ((int32_t)RtcSettings.pulse_counter[i]+Shutter.max_pwm_frequency/100) * Shutter.direction[i] * 2000 / Shutter.max_pwm_frequency ); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); + } else { + Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + } + + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99) { + uint16_t freq_change = Shutter.max_pwm_frequency/(Shutter.motordelay[i]+1); + // ramp up phase. calculate frequency + Shutter.pwm_frequency = tmin(freq_change * Shutter.time[i],Shutter.max_pwm_frequency); + // ramp down at the end of the movement time will not be exactly motordelay + Shutter.pwm_frequency = tmax(tmin(freq_change * (Shutter.target_position[i]-Shutter.real_position[i])*Shutter.direction[i]/30, Shutter.pwm_frequency),10); analogWriteFreq(Shutter.pwm_frequency); analogWrite(pin[GPIO_PWM1+i], 50); } - - Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); - // avoid real position leaving the boundaries. - // Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ; - - if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) { // calculate relay number responsible for current movement. //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter.real_position[i], Shutter.target_position[i],Shutter.direction[i]); @@ -273,22 +278,16 @@ void ShutterUpdatePosition(void) // see wiki to connect PWM and COUNTER if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { int16_t missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; - Shutter.pwm_frequency = 0; - //slow down for acurate position - analogWriteFreq(500); - analogWrite(pin[GPIO_PWM1+i], 50); //prepare for stop PWM - Shutter.motordelay[i] = -2 + Shutter.motordelay[i] + missing_steps/(Shutter.max_pwm_frequency/20); - Shutter.motordelay[i] = Shutter.motordelay[i] > 0 ? Shutter.motordelay[i] : 0; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Missing steps %d, adjust motordelay %d, counter %d, temp realpos %d"), missing_steps, Shutter.motordelay[i],RtcSettings.pulse_counter[i] ,Shutter.real_position[i]); - Settings.shutter_motordelay[i]=Shutter.motordelay[i]; - analogWriteFreq(0); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { delay(1); } analogWrite(pin[GPIO_PWM1+i], 0); Shutter.real_position[i] = ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Realpos %d, pulsecount %d, startpos %d, int32 %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i], ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); } if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { @@ -307,7 +306,7 @@ void ShutterUpdatePosition(void) Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, motordelay %d, rtcshutter: %s [s]"), i+1, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], Shutter.motordelay[i],stemp2); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MSG_SHUTTER_POS), i+1, Shutter.real_position[i], Settings.shutter_position[i], Shutter.direction[i], Settings.pulse_timer[cur_relay -1], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); Shutter.start_position[i] = Shutter.real_position[i]; // sending MQTT result to broker @@ -339,24 +338,10 @@ bool ShutterState(uint8_t device) void ShutterStartInit(uint8_t index, int8_t direction, int32_t target_pos) { //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter.open_max[index] - Shutter.real_position[index]) / Shutter.close_velocity[index], Shutter.real_position[index] / Shutter.close_velocity[index], 2+Shutter.motordelay[index]); - if (direction == 1 && (Shutter.open_max[index] - Shutter.real_position[index]) / Shutter.close_velocity[index] <= 2+Shutter.motordelay[index]) { - // shutter alread 100% cannot move further - // store relay number variable + if ( ( direction == 1 && (Shutter.open_max[index] - Shutter.real_position[index]) / 100 <= 2 ) + || ( direction == -1 && Shutter.real_position[index] / Shutter.close_velocity[index] <= 2)) { Shutter.skip_relay_change = 1 ; - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: 100%% endstop already reached: Relay %d"),Shutter.skip_relay_change); - - } else if (direction == -1 && Shutter.real_position[index] / Shutter.close_velocity[index] <= 2+Shutter.motordelay[index]) { - // shutter already at 0% connot move into minus - // store relay number variable - Shutter.skip_relay_change = 1; - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: 0%% endstop already reached: Relay %d"),Shutter.skip_relay_change); - } else { - Shutter.direction[index] = direction; - Shutter.target_position[index] = target_pos; - Shutter.start_position[index] = Shutter.real_position[index]; - Shutter.time[index] = 0; - Shutter.skip_relay_change = 0; if (pin[GPIO_PWM1+index] < 99) { Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); @@ -366,6 +351,12 @@ void ShutterStartInit(uint8_t index, int8_t direction, int32_t target_pos) RtcSettings.pulse_counter[index] = 0; } } + Shutter.target_position[index] = target_pos; + Shutter.start_position[index] = Shutter.real_position[index]; + Shutter.time[index] = 0; + Shutter.skip_relay_change = 0; + Shutter.direction[index] = direction; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[index], Shutter.start_position[index] ,RtcSettings.pulse_counter[index],Shutter.max_pwm_frequency , Shutter.direction[index] ,Shutter.max_pwm_frequency ); } //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]); } @@ -380,13 +371,19 @@ void ShutterReportPosition(void) { uint16_t shutter_moving = 0; for (uint8_t i = 0; i < shutters_present; i++) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d"), i+1,Shutter.real_position[i]); if (Shutter.direction[i] != 0) { char stemp1[20]; char stemp2[10]; + uint8_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); dtostrfd((float)Shutter.time[i] / 20, 2, stemp2); shutter_moving = 1; //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, motordelay %d, rtcshutter: %s [s]"), i+1,Shutter.real_position[i], Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2 ); + AddLog_P2(LOG_LEVEL_INFO, PSTR(MSG_SHUTTER_POS), i+1, Shutter.real_position[i], Settings.shutter_position[i], Shutter.direction[i], Settings.pulse_timer[cur_relay -1], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); + Response_P(PSTR("{")); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); } } if (rules_flag.shutter_moving > shutter_moving) { @@ -490,7 +487,7 @@ void CmndShutterStop(void) uint32_t index = XdrvMailbox.index -1; if (Shutter.direction[index] != 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction: %d"), XdrvMailbox.index, Shutter.direction[index]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[index]); // set stop position 10 steps ahead (0.5sec to allow normal stop) int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index])); XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, index); @@ -508,7 +505,7 @@ void CmndShutterPosition(void) if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { uint32_t index = XdrvMailbox.index -1; //limit the payload - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Position in: payload %s (%d), payload %d, index %d, source %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); if (XdrvMailbox.data_len > 1 && XdrvMailbox.payload <=0) { UpperCase(XdrvMailbox.data, XdrvMailbox.data); @@ -525,7 +522,7 @@ void CmndShutterPosition(void) //target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent; Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, realpos %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); } if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; @@ -541,18 +538,20 @@ void CmndShutterPosition(void) } } if (Shutter.direction[index] != new_shutterdirection ) { - ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); ShutterDelayForMotorStop(); + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); // Code for shutters with circuit safe configuration, switch the direction Relay ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); // power on ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); } else { // now start the motor for the right direction, work for momentary and normal shutters. - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter in direction %d"), Shutter.direction[index]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start in dir %d"), Shutter.direction[index]); + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay6 5s, xdrv %d"), XdrvMailbox.payload); } @@ -615,7 +614,6 @@ void CmndShutterRelay(void) } else { Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1); } - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay %d is %d"), XdrvMailbox.index, XdrvMailbox.payload); Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; ShutterInit(); // if payload is 0 to disable the relay there must be a reboot. Otherwhise does not work @@ -630,10 +628,8 @@ void CmndShutterSetHalfway(void) if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { Settings.shutter_set50percent[XdrvMailbox.index -1] = Settings.shutter_invert[XdrvMailbox.index -1] ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; ShutterInit(); - ResponseCmndIdxNumber(XdrvMailbox.payload); // ???? - } else { - ResponseCmndIdxNumber(Settings.shutter_set50percent[XdrvMailbox.index -1]); } + ResponseCmndIdxNumber(Settings.shutter_invert[XdrvMailbox.index -1] ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); } } @@ -641,6 +637,9 @@ void CmndShutterFrequency(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10000)) { Shutter.max_pwm_frequency = XdrvMailbox.payload; + if (shutters_present < 4) { + Settings.shuttercoeff[4][4] = Shutter.max_pwm_frequency; + } ResponseCmndNumber(XdrvMailbox.payload); // ???? } else { ResponseCmndNumber(Shutter.max_pwm_frequency); @@ -669,7 +668,7 @@ void CmndShutterInvert(void) void CmndShutterCalibration(void) // ???? { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if (XdrvMailbox.data_len > 0) { uint32_t i = 0; char *str_ptr; @@ -712,8 +711,10 @@ bool Xdrv27(uint8_t function) ShutterUpdatePosition(); break; case FUNC_EVERY_SECOND: + //case FUNC_EVERY_250_MSECOND: ShutterReportPosition(); break; + case FUNC_COMMAND: result = DecodeCommand(kShutterCommands, ShutterCommand); break; From de749b5b63a5144116f6eecb92e8bce227d5cb70 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sat, 14 Dec 2019 12:44:05 +0100 Subject: [PATCH 064/559] Update xdrv_27_shutter.ino Sorry you were to fast for me. I uploaded a buggy version. Now fixed --- tasmota/xdrv_27_shutter.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 7194788b7..2d143f415 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -46,7 +46,7 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterFrequency}; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"direction\":%d}"; -const char MSG_SHUTTER_POS[] PROGMEM = "SHT: " D_PRFX_SHUTTER " %d: Real. %d, Stop: %d, dir %d, pulsetimer: %d, motordelay %d, rtc: %s [s], freq %d"; +const char MSG_SHUTTER_POS[] PROGMEM = "SHT: " D_PRFX_SHUTTER " %d: Real. %d, Start: %d, Stop: %d, dir %d, motordelay %d, rtc: %s [s], freq %d"; #include @@ -306,7 +306,7 @@ void ShutterUpdatePosition(void) Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(MSG_SHUTTER_POS), i+1, Shutter.real_position[i], Settings.shutter_position[i], Shutter.direction[i], Settings.pulse_timer[cur_relay -1], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); + AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); Shutter.start_position[i] = Shutter.real_position[i]; // sending MQTT result to broker @@ -379,7 +379,7 @@ void ShutterReportPosition(void) dtostrfd((float)Shutter.time[i] / 20, 2, stemp2); shutter_moving = 1; //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; - AddLog_P2(LOG_LEVEL_INFO, PSTR(MSG_SHUTTER_POS), i+1, Shutter.real_position[i], Settings.shutter_position[i], Shutter.direction[i], Settings.pulse_timer[cur_relay -1], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); + AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); Response_P(PSTR("{")); ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); ResponseJsonEnd(); From 3d59de5d1d8345cc63c9776791f20e7fe8accf86 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 14 Dec 2019 13:16:55 +0100 Subject: [PATCH 065/559] Bump version to 7.1.2.6 - Change some more Settings locations freeing up space for future single char allowing variable length text - Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger - Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode --- RELEASENOTES.md | 4 +- tasmota/CHANGELOG.md | 7 ++- tasmota/settings.h | 32 ++++++---- tasmota/settings.ino | 121 +++++++++--------------------------- tasmota/support_tasmota.ino | 4 ++ tasmota/tasmota.h | 24 +++++++ tasmota/tasmota_version.h | 2 +- 7 files changed, 87 insertions(+), 107 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0f5e1e33b..4341ec587 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -47,7 +47,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 7.1.2.5 +### Version 7.1.2.6 - Change Exception reporting removing exception details from ``Status 1`` and consolidated in ``Status 12`` if available - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) @@ -69,3 +69,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) - Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) - Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) +- Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger +- Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 8ffde8562..e45d2efce 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,9 +1,14 @@ ## Unreleased (development) +### 7.1.2.6 20191214 + +- Change some more Settings locations freeing up space for future single char allowing variable length text + ### 7.1.2.5 20191213 - Change some Settings locations freeing up space for future single char allowing variable length text -- Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor +- Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger +- Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode ### 7.1.2.4 20191209 diff --git a/tasmota/settings.h b/tasmota/settings.h index d05777d17..af74422df 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -249,7 +249,7 @@ struct SYSCFG { int16_t save_data; // 014 int8_t timezone; // 016 - // Start of single char array + // Start of single char array Settings.text char ota_url[101]; // 017 char mqtt_prefix[3][11]; // 07C @@ -272,18 +272,21 @@ struct SYSCFG { uint8_t ex_mqtt_fingerprint[2][20]; // 1AD uint8_t ex_adc_param_type; // 1D5 - uint8_t free_1d6[10]; // 1D6 + uint8_t ex_free_1d6[10]; // 1D6 - // End of single char array of 446 chars max (phase 3) + // End of single char array of 456 chars max (phase 3) + + SysBitfield4 ex_flag4; // 1E0 + uint8_t ex_serial_config; // 1E4 + uint8_t ex_wifi_output_power; // 1E5 + uint8_t ex_shutter_accuracy; // 1E6 + uint8_t ex_mqttlog_level; // 1E7 + uint8_t ex_sps30_inuse_hours; // 1E8 - SysBitfield4 flag4; // 1E0 - uint8_t serial_config; // 1E4 - uint8_t wifi_output_power; // 1E5 - uint8_t shutter_accuracy; // 1E6 - uint8_t mqttlog_level; // 1E7 - uint8_t sps30_inuse_hours; // 1E8 char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6 - uint16_t mqtt_port; // 20A - Keep together + + uint16_t ex_mqtt_port; // 20A - Keep together + char mqtt_client[33]; // 20C - Keep together char mqtt_user[33]; // 22D - Keep together char mqtt_pwd[33]; // 24E - Keep together @@ -459,8 +462,15 @@ struct SYSCFG { uint8_t weblog_level; // ECE uint8_t mqtt_fingerprint[2][20]; // ECF uint8_t adc_param_type; // EF7 + SysBitfield4 flag4; // EF8 + uint16_t mqtt_port; // EFC + uint8_t serial_config; // EFE + uint8_t wifi_output_power; // EFF + uint8_t shutter_accuracy; // F00 + uint8_t mqttlog_level; // F01 + uint8_t sps30_inuse_hours; // F02 - uint8_t free_ef8[244]; // EF8 + uint8_t free_f03[233]; // F03 uint32_t i2c_drivers[3]; // FEC I2cDriver uint32_t cfg_timestamp; // FF8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 866e72f99..c1faa559e 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -443,132 +443,66 @@ void UpdateQuickPowerCycle(bool update) } /*********************************************************************************************\ - * Config single char array support + * Config Settings.text char array support \*********************************************************************************************/ -enum CharsIndex { SET_OTAURL, - SET_MQTTPREFIX1, SET_MQTTPREFIX2, SET_MQTTPREFIX3, -// SET_STASSID1, SET_STASSID2, -// SET_STAPWD1, SET_STAPWD2, SET_WEBPWD, -// SET_HOSTNAME, SET_SYSLOG_HOST, -// SET_MQTT_HOST, SET_MQTT_CLIENT, -// SET_MQTT_USER, SET_MQTT_PWD, -// SET_MQTT_FULLTOPIC, SET_MQTT_TOPIC, -// SET_MQTT_BUTTON_TOPIC, SET_MQTT_SWITCH_TOPIC, SET_MQTT_GRP_TOPIC, -// SET_STATE_TXT1, SET_STATE_TXT2, SET_STATE_TXT3, SET_STATE_TXT4, -// SET_FRIENDLYNAME1, SET_FRIENDLYNAME2, SET_FRIENDLYNAME3, SET_FRIENDLYNAME4, +const uint32_t settings_text_size = 457; // Settings.flag4 (1E0) - Settings.ota_url (017) -// SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, // Future extension - -// SET_NTPSERVER1, SET_NTPSERVER2, SET_NTPSERVER3, -// SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5, -// SET_CORS, - -// SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, // Future extension -// SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, // Future extension -// SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, // Future extension -// SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, // Future extension - - SET_MAX }; - -const uint32_t settings_loc_num = 1; // First phase only ota_url and mqtt_prefix -const uint32_t settings_max_size = 134; - -char settings_fullstr[settings_max_size] = { 0 }; - -struct LOCATIONS { - char* address; - uint32_t size = 0; -} Location[settings_loc_num]; - -void SettingsInitText(void) +uint32_t GetSettingsTextLen(void) { - for (uint32_t i = 0; i < settings_loc_num; i++) { - if (0 == i) { - Location[i].address = Settings.ota_url; - Location[i].size = sizeof(Settings.ota_url) + (3 * sizeof(Settings.mqtt_prefix[0])); -// Location[i].address = Settings.char_chunk1; -// Location[i].size = sizeof(Settings.char_chunk1); // 134 - } - else if (1 == i) { - Location[i].address = Settings.sta_ssid[0]; - Location[i].size = (2 * sizeof(Settings.sta_ssid[0])) + (2 * sizeof(Settings.sta_pwd[0])) + sizeof(Settings.hostname) + sizeof(Settings.syslog_host); -// Location[i].address = Settings.char_chunk2; -// Location[i].size = sizeof(Settings.char_chunk2); // 262 - } - else if (2 == i) { - // Need to move Settings.mqtt_port first! - Location[i].address = Settings.mqtt_host; - Location[i].size = sizeof(Settings.mqtt_host) + 2 + sizeof(Settings.mqtt_client) + sizeof(Settings.mqtt_user) + sizeof(Settings.mqtt_pwd) + sizeof(Settings.mqtt_topic) + sizeof(Settings.button_topic) + sizeof(Settings.mqtt_grptopic); -// Location[i].address = Settings.char_chunk3; -// Location[i].size = sizeof(Settings.char_chunk3); // 233 - } + char* position = Settings.ota_url; + for (uint32_t size = 0; size < SET_MAX; size++) { + while (*position++ != '\0') { } } - - SettingsCopyText(0); // Load + return position - Settings.ota_url; } -void SettingsCopyText(uint32_t direction) -{ - char* fullstr = settings_fullstr; - uint32_t size = 0; - for (uint32_t i = 0; i < settings_loc_num; i++) { - size = Location[i].size; - if (1 == direction) { - memcpy(Location[i].address, fullstr, size); // Save to Settings - } else { - memcpy(fullstr, Location[i].address, size); // Load from Settings - } - fullstr += size; - } -} - -bool SettingsUpdateText(uint32_t index, char* replace) +bool SettingsUpdateText(uint32_t index, char* replace_me) { if (index >= SET_MAX) { return false; // Setting not supported - internal error } -// SettingsCopyText(0); // Load + // Make a copy first in case we use source from Settings.text + uint32_t replace_len = strlen(replace_me); + char replace[replace_len +1]; + memcpy(replace, replace_me, sizeof(replace)); uint32_t start_pos = 0; uint32_t end_pos = 0; - char* position = settings_fullstr; + char* position = Settings.ota_url; for (uint32_t size = 0; size < SET_MAX; size++) { while (*position++ != '\0') { } if (1 == index) { - start_pos = position - settings_fullstr; + start_pos = position - Settings.ota_url; } else if (0 == index) { - end_pos = position - settings_fullstr -1; + end_pos = position - Settings.ota_url -1; } index--; } - uint32_t len_pos = position - settings_fullstr; + uint32_t char_len = position - Settings.ota_url; uint32_t current_len = end_pos - start_pos; - uint32_t replace_len = strlen(replace); int diff = replace_len - current_len; // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"), -// start_pos, end_pos, len_pos, current_len, replace_len, diff); +// start_pos, end_pos, char_len, current_len, replace_len, diff); - int too_long = (len_pos + diff) - sizeof(settings_fullstr); + int too_long = (char_len + diff) - settings_text_size; if (too_long > 0) { // AddLog_P2(LOG_LEVEL_INFO, PSTR("CFG: Text too long by %d char(s)"), too_long); return false; // Replace text too long } if (diff != 0) { - // Shift full text string up or down - memmove_P(settings_fullstr + start_pos + replace_len, settings_fullstr + end_pos, len_pos - end_pos); + // Shift Settings.text up or down + memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos); } // Replace text - memmove_P(settings_fullstr + start_pos, replace, replace_len); + memmove_P(Settings.ota_url + start_pos, replace, replace_len); // Fill for future use - memset(settings_fullstr + len_pos + diff, 0x00, settings_max_size - len_pos - diff); - -// SettingsCopyText(1); // Save - Hold of for now + memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff); return true; } @@ -579,9 +513,7 @@ char* SettingsGetText(uint32_t index) return nullptr; // Setting not supported - internal error } -// SettingsCopyText(0); // Load - - char* position = settings_fullstr; + char* position = Settings.ota_url; for (;index > 0; index--) { while (*position++ != '\0') { } } @@ -707,8 +639,6 @@ void SettingsLoad(void) settings_crc32 = GetSettingsCrc32(); #endif // FIRMWARE_MINIMAL - SettingsInitText(); - RtcSettingsLoad(); } @@ -1342,6 +1272,11 @@ void SettingsDelta(void) Settings.sta_active = Settings.ex_sta_active; // 0A0 -> EC8 memcpy((char*)&Settings.rule_stop, (char*)&Settings.ex_rule_stop, 47); // 1A7 -> EC9 } + if (Settings.version < 0x07010206) { + Settings.flag4 = Settings.ex_flag4; // 1E0 -> EF8 + Settings.mqtt_port = Settings.ex_mqtt_port; // 20A -> EFC + memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); // 1E4 -> EFE + } Settings.version = VERSION; SettingsSave(1); diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 34ce9f5dc..0f930e06e 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -905,12 +905,15 @@ void Every250mSeconds(void) if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { char storage_wifi[sizeof(Settings.sta_ssid) + sizeof(Settings.sta_pwd)]; + char storage_mqtt[sizeof(Settings.mqtt_host) + sizeof(Settings.mqtt_port) + sizeof(Settings.mqtt_client) + sizeof(Settings.mqtt_user) + sizeof(Settings.mqtt_pwd) + sizeof(Settings.mqtt_topic)]; + uint16_t mqtt_port = Settings.mqtt_port; // Workaround 7.1.2.6 Settings shuffle + memcpy(storage_wifi, Settings.sta_ssid, sizeof(storage_wifi)); // Backup current SSIDs and Passwords if (216 == restart_flag) { memcpy(storage_mqtt, Settings.mqtt_host, sizeof(storage_mqtt)); // Backup mqtt host, port, client, username and password @@ -923,6 +926,7 @@ void Every250mSeconds(void) if (216 == restart_flag) { memcpy(Settings.mqtt_host, storage_mqtt, sizeof(storage_mqtt)); // Restore the mqtt host, port, client, username and password strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); // Set client to default + Settings.mqtt_port = mqtt_port; // Workaround 7.1.2.6 Settings shuffle } restart_flag = 2; } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index c31bfad83..1f676acd4 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -272,6 +272,30 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FU enum AddressConfigSteps { ADDR_IDLE, ADDR_RECEIVE, ADDR_SEND }; +enum SettingsTextIndex { SET_OTAURL, + SET_MQTTPREFIX1, SET_MQTTPREFIX2, SET_MQTTPREFIX3, + SET_STASSID1, SET_STASSID2, + SET_STAPWD1, SET_STAPWD2, + SET_HOSTNAME, SET_SYSLOG_HOST, + SET_WEBPWD, + SET_MQTT_HOST, SET_MQTT_CLIENT, + SET_MQTT_USER, SET_MQTT_PWD, + SET_MQTT_FULLTOPIC, SET_MQTT_TOPIC, + SET_MQTT_BUTTON_TOPIC, SET_MQTT_SWITCH_TOPIC, SET_MQTT_GRP_TOPIC, + SET_STATE_TXT1, SET_STATE_TXT2, SET_STATE_TXT3, SET_STATE_TXT4, + SET_NTPSERVER1, SET_NTPSERVER2, SET_NTPSERVER3, + SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5, + SET_CORS, + SET_FRIENDLYNAME1, SET_FRIENDLYNAME2, SET_FRIENDLYNAME3, SET_FRIENDLYNAME4, + +// SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, // Future extension +// SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, // Future extension +// SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, // Future extension +// SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, // Future extension +// SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, // Future extension + + SET_MAX }; + enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER, SRC_MAX }; diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index ccc8dcbaf..a083dad4b 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010205; +const uint32_t VERSION = 0x07010206; #endif // _TASMOTA_VERSION_H_ From 4aa66b8032c0a95253ab04b45417fcd8bedcf7ec Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sun, 15 Dec 2019 14:21:41 +0100 Subject: [PATCH 066/559] Update xdrv_27_shutter.ino - bugfix inverted shutter - improved stepper soft start/stop now in all situations - --- tasmota/xdrv_27_shutter.ino | 73 ++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 2d143f415..e13bba771 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -67,7 +67,7 @@ struct SHUTTER { int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE int16_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. - uint16_t pwm_frequency; // frequency of PWN for stepper motors + int16_t pwm_frequency; // frequency of PWN for stepper motors uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency that can be used. depend on the motor and drivers uint8_t skip_relay_change; // avoid overrun at endstops } Shutter; @@ -223,7 +223,7 @@ void ShutterInit(void) break; } if (shutters_present < 4) { - Shutter.max_pwm_frequency = Settings.shuttercoeff[4][4]; + Shutter.max_pwm_frequency = Settings.shuttercoeff[4][4] > 0 ? Settings.shuttercoeff[4][4] : Shutter.max_pwm_frequency; } Settings.shutter_accuracy = 1; } @@ -237,13 +237,10 @@ void ShutterUpdatePosition(void) for (uint32_t i = 0; i < shutters_present; i++) { if (Shutter.direction[i] != 0) { - //char stemp1[20]; - - - if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { // Calculate position with counter. Much more accurate and no need for motordelay workaround - // aading some counters to stop early - Shutter.real_position[i] = Shutter.start_position[i] + ( ((int32_t)RtcSettings.pulse_counter[i]+Shutter.max_pwm_frequency/100) * Shutter.direction[i] * 2000 / Shutter.max_pwm_frequency ); + // adding some steps to stop early + Shutter.real_position[i] = Shutter.direction[i] * 20 + ShutterCounterBasedPosition(i);; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); } else { Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); @@ -286,7 +283,7 @@ void ShutterUpdatePosition(void) delay(1); } analogWrite(pin[GPIO_PWM1+i], 0); - Shutter.real_position[i] = ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; + Shutter.real_position[i] = ShutterCounterBasedPosition(i); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); } @@ -361,10 +358,29 @@ void ShutterStartInit(uint8_t index, int8_t direction, int32_t target_pos) //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]); } -void ShutterDelayForMotorStop(void) +void ShutterWaitForMotorStop(uint8_t index) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop %d"), MOTOR_STOP_TIME); - delay(MOTOR_STOP_TIME); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { + if (pin[GPIO_PWM1+index] < 99 && pin[GPIO_CNTR1+index] < 99 ) { + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Frequency change %d"), Shutter.pwm_frequency); + while (Shutter.pwm_frequency > 100) { + Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-(Shutter.max_pwm_frequency/(Shutter.motordelay[index]+1)) , 0); + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+index], 50); + delay(50); + } + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+index], 0); + Shutter.real_position[index] = ShutterCounterBasedPosition(index); + } else { + ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); + delay(MOTOR_STOP_TIME); + } + } else { + delay(MOTOR_STOP_TIME); + } } void ShutterReportPosition(void) @@ -373,7 +389,6 @@ void ShutterReportPosition(void) for (uint8_t i = 0; i < shutters_present; i++) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d"), i+1,Shutter.real_position[i]); if (Shutter.direction[i] != 0) { - char stemp1[20]; char stemp2[10]; uint8_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); dtostrfd((float)Shutter.time[i] / 20, 2, stemp2); @@ -381,7 +396,7 @@ void ShutterReportPosition(void) //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); Response_P(PSTR("{")); - ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, Settings.shutter_invert[i] ? 100-position : position, Shutter.direction[i]); ResponseJsonEnd(); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); } @@ -395,6 +410,11 @@ void ShutterReportPosition(void) //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); } +int32_t ShutterCounterBasedPosition(uint8 i) +{ + return ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; +} + void ShutterRelayChanged(void) { @@ -407,19 +427,20 @@ void ShutterRelayChanged(void) power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; //uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != last_source && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); if (manual_relays_changed) { + //Shutter.skip_relay_change = true; if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { + ShutterWaitForMotorStop(i); switch (powerstate_local) { case 1: - ShutterDelayForMotorStop(); ShutterStartInit(i, 1, Shutter.open_max[i]); break; case 3: - ShutterDelayForMotorStop(); ShutterStartInit(i, -1, 0); break; default: - Shutter.direction[i] = 0; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor."),i); Shutter.target_position[i] = Shutter.real_position[i]; } } else { @@ -430,11 +451,11 @@ void ShutterRelayChanged(void) last_source = SRC_SHUTTER; // avoid switch off in the next loop if (powerstate_local == 2) { // testing on CLOSE relay, if ON // close with relay two - ShutterDelayForMotorStop(); + ShutterWaitForMotorStop(i); ShutterStartInit(i, -1, 0); } else { // opens with relay one - ShutterDelayForMotorStop(); + ShutterWaitForMotorStop(i); ShutterStartInit(i, 1, Shutter.open_max[i]); } } @@ -533,16 +554,17 @@ void CmndShutterPosition(void) ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); delay(100); } else { - ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), 0, SRC_SHUTTER); - ShutterDelayForMotorStop(); + if (Shutter.mode == SHT_OFF_OPEN__OFF_CLOSE) { + ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), 0, SRC_SHUTTER); + ShutterWaitForMotorStop(index); + } } } if (Shutter.direction[index] != new_shutterdirection ) { - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { - ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); - ShutterDelayForMotorStop(); + ShutterWaitForMotorStop(index); + ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); // Code for shutters with circuit safe configuration, switch the direction Relay ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); @@ -635,7 +657,7 @@ void CmndShutterSetHalfway(void) void CmndShutterFrequency(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10000)) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { Shutter.max_pwm_frequency = XdrvMailbox.payload; if (shutters_present < 4) { Settings.shuttercoeff[4][4] = Shutter.max_pwm_frequency; @@ -750,6 +772,7 @@ bool Xdrv27(uint8_t function) //AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: skip relay change: %d"),i+1); result = true; Shutter.skip_relay_change = 0; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"),i); ExecuteCommandPower(i+1, 0, SRC_SHUTTER); } break; From 6985fcecaf012e9dc4798df7fbf7c0f68b7d0445 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 15 Dec 2019 16:02:41 +0100 Subject: [PATCH 067/559] Add Zigbee send automatic ZigbeeRead after sending a command --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_23_zigbee_0_constants.ino | 2 - tasmota/xdrv_23_zigbee_1_headers.ino | 26 +++++++++++ tasmota/xdrv_23_zigbee_3_devices.ino | 59 ++++++++++++++++++++++++- tasmota/xdrv_23_zigbee_5_converters.ino | 14 +++--- tasmota/xdrv_23_zigbee_6_commands.ino | 59 +++++++++++++++++++++++++ tasmota/xdrv_23_zigbee_8_parsers.ino | 2 - tasmota/xdrv_23_zigbee_9_impl.ino | 18 ++++---- 8 files changed, 160 insertions(+), 21 deletions(-) create mode 100644 tasmota/xdrv_23_zigbee_1_headers.ino diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e45d2efce..828b5d515 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 7.1.2.6 20191214 - Change some more Settings locations freeing up space for future single char allowing variable length text +- Add Zigbee send automatic ZigbeeRead after sending a command ### 7.1.2.5 20191213 diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index 996d877f8..0c74c9d8a 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -19,8 +19,6 @@ #ifdef USE_ZIGBEE -#define ZIGBEE_VERBOSE // output versbose MQTT Zigbee logs. Will remain active for now - typedef uint64_t Z_IEEEAddress; typedef uint16_t Z_ShortAddress; diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino new file mode 100644 index 000000000..b017d8e2e --- /dev/null +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -0,0 +1,26 @@ +/* + xdrv_23_zigbee_1_headers.ino - zigbee support for Tasmota + + Copyright (C) 2019 Theo Arends and Stephan Hadinger + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_ZIGBEE + +// contains some definitions for functions used before their declarations + +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1); + +#endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index f76c882c7..de13990c2 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -22,6 +22,9 @@ #include #include + +typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); + typedef struct Z_Device { uint16_t shortaddr; // unique key if not null, or unspecified if null uint64_t longaddr; // 0x00 means unspecified @@ -33,6 +36,12 @@ typedef struct Z_Device { std::vector endpoints; // encoded as high 16 bits is endpoint, low 16 bits is ProfileId std::vector clusters_in; // encoded as high 16 bits is endpoint, low 16 bits is cluster number std::vector clusters_out; // encoded as high 16 bits is endpoint, low 16 bits is cluster number + // below are per device timers, used for example to query the new state of the device + uint32_t timer; // millis() when to fire the timer, 0 if no timer + uint16_t cluster; // cluster to use for the timer + uint16_t endpoint; // endpoint to use for timer + uint32_t value; // any raw value to use for the timer + Z_DeviceTimer func; // function to call when timer occurs } Z_Device; // All devices are stored in a Vector @@ -70,6 +79,11 @@ public: // Dump json String dump(uint32_t dump_mode, int32_t device_num = 0) const; + // Timers + void resetTimer(uint32_t shortaddr); + void setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func); + void runTimer(void); + private: std::vector _devices = {}; @@ -157,7 +171,9 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { String(), // FriendlyName std::vector(), std::vector(), - std::vector() }; + std::vector(), + 0,0,0,0, + nullptr }; _devices.push_back(device); return _devices.back(); } @@ -346,6 +362,47 @@ void Z_Devices::updateLastSeen(uint16_t shortaddr) { _updateLastSeen(device); } +// Per device timers +// +// Reset the timer for a specific device +void Z_Devices::resetTimer(uint32_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + device.timer = 0; + device.func = nullptr; +} + +// Set timer for a specific device +void Z_Devices::setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + + device.cluster = cluster; + device.endpoint = endpoint; + device.value = value; + device.func = func; + device.timer = wait_ms + millis(); +} + +// Run timer at each tick +void Z_Devices::runTimer(void) { + uint32_t now = millis(); + + for (std::vector::iterator it = _devices.begin(); it != _devices.end(); ++it) { + Z_Device &device = *it; + uint16_t shortaddr = device.shortaddr; + + uint32_t timer = device.timer; + if ((timer) && (timer <= now)) { + // trigger the timer + (*device.func)(device.shortaddr, device.cluster, device.endpoint, device.value); + + device.timer = 0; // cancel the timer + } + } +} + + // Dump the internal memory of Zigbee devices // Mode = 1: simple dump of devices addresses and names // Mode = 2: Mode 1 + also dump the endpoints, profiles and clusters diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 4defbf043..a56ada927 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -53,7 +53,6 @@ public: uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, uint32_t timestamp) { -#ifdef ZIGBEE_VERBOSE char hex_char[_payload.len()*2+2]; ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" @@ -69,7 +68,6 @@ public: timestamp, _frame_control, _manuf_code, _transact_seq, _cmd_id, hex_char); -#endif } static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid) { // parse a raw frame and build the ZCL frame object @@ -497,7 +495,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0007, 0x0000, "SwitchType", &Z_Copy }, // Level Control cluster - { 0x0008, 0x0000, "CurrentLevel", &Z_Copy }, + { 0x0008, 0x0000, "Dimmer", &Z_Copy }, // { 0x0008, 0x0001, "RemainingTime", &Z_Copy }, // { 0x0008, 0x0010, "OnOffTransitionTime", &Z_Copy }, // { 0x0008, 0x0011, "OnLevel", &Z_Copy }, @@ -652,14 +650,14 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0102, 0x0019, "IntermediateSetpointsTilt",&Z_Copy }, // Color Control cluster - { 0x0300, 0x0000, "CurrentHue", &Z_Copy }, - { 0x0300, 0x0001, "CurrentSaturation", &Z_Copy }, + { 0x0300, 0x0000, "Hue", &Z_Copy }, + { 0x0300, 0x0001, "Sat", &Z_Copy }, { 0x0300, 0x0002, "RemainingTime", &Z_Copy }, - { 0x0300, 0x0003, "CurrentX", &Z_Copy }, - { 0x0300, 0x0004, "CurrentY", &Z_Copy }, + { 0x0300, 0x0003, "X", &Z_Copy }, + { 0x0300, 0x0004, "Y", &Z_Copy }, { 0x0300, 0x0005, "DriftCompensation", &Z_Copy }, { 0x0300, 0x0006, "CompensationText", &Z_Copy }, - { 0x0300, 0x0007, "ColorTemperatureMireds",&Z_Copy }, + { 0x0300, 0x0007, "CT", &Z_Copy }, { 0x0300, 0x0008, "ColorMode", &Z_Copy }, { 0x0300, 0x0010, "NumberOfPrimaries", &Z_Copy }, { 0x0300, 0x0011, "Primary1X", &Z_Copy }, diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index c877bd3a3..70a8f0788 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -47,6 +47,64 @@ const Z_CommandConverter Z_Commands[] = { { "ShutterTilt", "0102!08xx"}, // Tilt percentage }; +#define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian + +// Below are the attributes we wand to read from each cluster +const uint8_t CLUSTER_0006[] = { ZLE(0x0000) }; // Power +const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; // CurrentLevel +const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; // AlarmCount +const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007) }; // Hue, Sat, X, Y, CT + +int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + size_t attrs_len = 0; + const uint8_t* attrs = nullptr; + + switch (cluster) { + case 0x0006: // for On/Off + attrs = CLUSTER_0006; + attrs_len = sizeof(CLUSTER_0006); + break; + case 0x0008: // for Dimmer + attrs = CLUSTER_0008; + attrs_len = sizeof(CLUSTER_0008); + break; + case 0x0009: // for Alarms + attrs = CLUSTER_0009; + attrs_len = sizeof(CLUSTER_0009); + break; + case 0x0300: // for Lights + attrs = CLUSTER_0300; + attrs_len = sizeof(CLUSTER_0300); + break; + } + if (attrs) { + ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + } +} + + +// set a timer to read back the value in the future +void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint) { + uint32_t wait_ms = 0; + + switch (cluster) { + case 0x0006: // for On/Off + case 0x0009: // for Alamrs + wait_ms = 200; // wait 0.2 s + break; + case 0x0008: // for Dimmer + case 0x0300: // for Color + wait_ms = 1050; // wait 1.0 s + break; + case 0x0102: // for Shutters + wait_ms = 10000; // wait 10.0 s + break; + } + if (wait_ms) { + zigbee_devices.setTimer(shortaddr, wait_ms, cluster, endpoint, 0 /* value */, &Z_ReadAttrCallback); + } +} + const __FlashStringHelper* zigbeeFindCommand(const char *command) { char parm_uc[16]; // used to convert JSON keys to uppercase for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { @@ -114,6 +172,7 @@ const uint8_t kZ_Numbers[] PROGMEM = { 0,0,0,0,0, 2,2, 255 }; +// Convert an alias like "On" to the corresponding number uint32_t ZigbeeAliasOrNumber(const char *state_text) { char command[16]; int state_number = GetCommandCode(command, sizeof(command), state_text, kZ_Alias); diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index acd7e5d26..f88bf15e2 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -372,12 +372,10 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { zigbee_devices.updateLastSeen(srcaddr); ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid); -#ifdef ZIGBEE_VERBOSE zcl_received.publishMQTTReceived(groupid, clusterid, srcaddr, srcendpoint, dstendpoint, wasbroadcast, linkquality, securityuse, seqnumber, timestamp); -#endif char shortaddr[8]; snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 3bfd6c4e3..461b3af32 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -191,14 +191,9 @@ void ZigbeeInput(void) SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); // remove SOF, LEN and FCS -#ifdef ZIGBEE_VERBOSE ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char)); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPRECEIVED " %s"), hex_char); - // Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); - // MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZNPRECEIVED)); - // XdrvRulesProcess(); -#endif // now process the message ZigbeeProcessInput(znp_buffer); @@ -320,15 +315,13 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { ZigbeeSerial->write(fcs); // finally send fcs checksum byte AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend FCS %02X"), fcs); } -#ifdef ZIGBEE_VERBOSE // Now send a MQTT message to report the sent message char hex_char[(len * 2) + 2]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"), ToHex_P(msg, len, hex_char, sizeof(hex_char))); -#endif } -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1) { +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp, uint8_t transacId) { SBuffer buf(25+len); buf.add8(Z_SREQ | Z_AF); // 24 buf.add8(AF_DATA_REQUEST); // 01 @@ -423,6 +416,10 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { // everything is good, we can send the command ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len()); + // now set the timer, if any, to read back the state later + if (clusterSpecific) { + zigbeeSetCommandTimer(dstAddr, cluster, endpoint); + } ResponseCmndDone(); } @@ -648,6 +645,11 @@ bool Xdrv23(uint8_t function) if (zigbee.active) { switch (function) { + case FUNC_EVERY_50_MSECOND: + if (!zigbee.init_phase) { + zigbee_devices.runTimer(); + } + break; case FUNC_LOOP: if (ZigbeeSerial) { ZigbeeInput(); } if (zigbee.state_machine) { From d802b2dd6828aa79ee62d91127670ad489da0697 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 15 Dec 2019 19:39:27 +0100 Subject: [PATCH 068/559] Add Zigbee improving Occupancy:false detection for Aqara sensor --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_23_zigbee_5_converters.ino | 69 ++++++++++++++++++++----- tasmota/xdrv_23_zigbee_8_parsers.ino | 13 +++-- 3 files changed, 64 insertions(+), 19 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 828b5d515..cb90c5af5 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Change some more Settings locations freeing up space for future single char allowing variable length text - Add Zigbee send automatic ZigbeeRead after sending a command +- Add Zigbee improving Occupancy:false detection for Aqara sensor ### 7.1.2.5 20191213 diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index a56ada927..687ac2483 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -39,20 +39,23 @@ class ZCLFrame { public: ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id, - const char *buf, size_t buf_len, uint16_t clusterid = 0, uint16_t groupid = 0): + const char *buf, size_t buf_len, uint16_t clusterid = 0, uint16_t groupid = 0, + uint16_t srcaddr = 0, uint8_t srcendpoint = 0, uint8_t dstendpoint = 0, uint8_t wasbroadcast = 0, + uint8_t linkquality = 0, uint8_t securityuse = 0, uint8_t seqnumber = 0, + uint32_t timestamp = 0): _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), _payload(buf_len ? buf_len : 250), // allocate the data frame from source or preallocate big enough - _cluster_id(clusterid), _group_id(groupid) + _cluster_id(clusterid), _group_id(groupid), + _srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast), + _linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber), + _timestamp(timestamp) { _frame_control.d8 = frame_control; _payload.addBuffer(buf, buf_len); }; - void publishMQTTReceived(uint16_t groupid, uint16_t clusterid, uint16_t srcaddr, - uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, - uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, - uint32_t timestamp) { + void log(void) { char hex_char[_payload.len()*2+2]; ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" @@ -62,15 +65,18 @@ public: "\"timestamp\":%d," "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), - groupid, clusterid, srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp, + _group_id, _cluster_id, _srcaddr, + _srcendpoint, _dstendpoint, _wasbroadcast, + _linkquality, _securityuse, _seqnumber, + _timestamp, _frame_control, _manuf_code, _transact_seq, _cmd_id, hex_char); } - static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid) { // parse a raw frame and build the ZCL frame object + static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid, + uint16_t srcaddr = 0, uint8_t srcendpoint = 0, uint8_t dstendpoint = 0, uint8_t wasbroadcast = 0, + uint8_t linkquality = 0, uint8_t securityuse = 0, uint8_t seqnumber = 0, + uint32_t timestamp = 0) { // parse a raw frame and build the ZCL frame object uint32_t i = offset; ZCLHeaderFrameControl_t frame_control; uint16_t manuf_code = 0; @@ -115,6 +121,10 @@ public: return _cluster_id; } + inline uint16_t getSrcEndpoint(void) const { + return _srcendpoint; + } + const SBuffer &getPayload(void) const { return _payload; } @@ -131,6 +141,15 @@ private: uint16_t _cluster_id = 0; uint16_t _group_id = 0; SBuffer _payload; + // information from decoded ZCL frame + uint16_t _srcaddr; + uint8_t _srcendpoint; + uint8_t _dstendpoint; + uint8_t _wasbroadcast; + uint8_t _linkquality; + uint8_t _securityuse; + uint8_t _seqnumber; + uint32_t _timestamp; }; // Zigbee ZCL converters @@ -461,6 +480,8 @@ typedef struct Z_AttributeConverter { Z_AttrConverter func; } Z_AttributeConverter; +#define OCCUPANCY "Occupancy" // global define for Aqara + // list of post-processing directives const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0000, 0x0000, "ZCLVersion", &Z_Copy }, @@ -729,7 +750,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Occupancy Sensing cluster - { 0x0406, 0x0000, "Occupancy", &Z_Copy }, // Occupancy (map8) + { 0x0406, 0x0000, OCCUPANCY, &Z_AqaraOccupancy }, // Occupancy (map8) { 0x0406, 0x0001, "OccupancySensorType", &Z_Copy }, // OccupancySensorType { 0x0406, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values @@ -796,6 +817,30 @@ int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& return 1; // remove original key } + +// Aqara Occupancy behavior: the Aqara device only sends Occupancy: true events every 60 seconds. +// Here we add a timer so if we don't receive a Occupancy event for 90 seconds, we send Occupancy:false +const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s + +int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + // send Occupancy:false message + Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":{\"" OCCUPANCY "\":0}}}"), shortaddr); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); +} + +int32_t Z_AqaraOccupancy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + uint32_t occupancy = value; + + if (occupancy) { + zigbee_devices.setTimer(shortaddr, OCCUPANCY_TIMEOUT, cluster, zcl->getSrcEndpoint(), 0, &Z_OccupancyCallback); + } else { + zigbee_devices.resetTimer(shortaddr); + } + return 1; // remove original key +} + // Aqara Vibration Sensor - special proprietary attributes int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { //json[new_name] = value; diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index f88bf15e2..2f30080fa 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -370,13 +370,12 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { uint8_t seqnumber = buf.get8(17); zigbee_devices.updateLastSeen(srcaddr); - ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid); - - zcl_received.publishMQTTReceived(groupid, clusterid, srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp); - + ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, + srcaddr, + srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp); + zcl_received.log(); char shortaddr[8]; snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); From 946f6fd74f6569d2bcdbbc1e006ad6638d2ac223 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sun, 15 Dec 2019 16:40:02 -0300 Subject: [PATCH 069/559] PubSubClient: Add disconnect type option --- lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp b/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp index 68cc2dafa..0748fdc4a 100644 --- a/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp +++ b/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.cpp @@ -610,11 +610,13 @@ boolean PubSubClient::unsubscribe(const char* topic) { return false; } -void PubSubClient::disconnect() { +void PubSubClient::disconnect(bool disconnect_package) { buffer[0] = MQTTDISCONNECT; buffer[1] = 0; if (_client != nullptr) { - _client->write(buffer,2); + if (disconnect_package) { + _client->write(buffer,2); + } _client->flush(); _client->stop(); } From 08032944b2d596d0020fe23b0506b9583038b89f Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sun, 15 Dec 2019 16:45:03 -0300 Subject: [PATCH 070/559] PubSubClient: Add disconnect type option Allow clean disconnect as optional. This avoid the automatic deletion of LWT message in the broker for clean disconnections, in order to let LWT work also on all cases (Restart, Config Changes, etc) See https://github.com/arendst/Tasmota/issues/7189 --- lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h b/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h index aa2080ed1..593077e8c 100644 --- a/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h +++ b/lib/PubSubClient-EspEasy-2.7.12/src/PubSubClient.h @@ -141,7 +141,7 @@ public: boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage); boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage, boolean cleanSession); - void disconnect(); + void disconnect(bool disconnect_package = false); boolean publish(const char* topic, const char* payload); boolean publish(const char* topic, const char* payload, boolean retained); boolean publish(const char* topic, const uint8_t * payload, unsigned int plength); From d4c2e92fd560c3bad87fb1e168c19707dbbd6b4b Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Mon, 16 Dec 2019 06:52:25 +0100 Subject: [PATCH 071/559] scripter FUNC_SET_POWER into separate section >P --- tasmota/xdrv_10_scripter.ino | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 0bab141d7..5badb88ea 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1030,8 +1030,10 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso if ((*jo).is(vn)) { if (!strncmp(str_value,"ON",2)) { if (fp) *fp=1; + goto nexit; } else if (!strncmp(str_value,"OFF",3)) { if (fp) *fp=0; + goto nexit; } else { *vtype=STR_RES; tind->bits.constant=1; @@ -1039,6 +1041,7 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso if (sp) strlcpy(sp,str_value,SCRIPT_MAXSSIZE); return lp+len; } + } else { if (fp) { if (!strncmp(vn.c_str(),"Epoch",5)) { @@ -1047,6 +1050,7 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso *fp=CharToFloat((char*)str_value); } } + nexit: *vtype=NUM_RES; tind->bits.constant=1; tind->bits.is_string=0; @@ -4843,6 +4847,12 @@ bool Xdrv10(uint8_t function) result = ScriptCommand(); break; case FUNC_SET_POWER: +#ifdef SCRIPT_POWER_SECTION + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P",2,0); +#else + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,0); +#endif + break; case FUNC_RULES_PROCESS: if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data); break; From aae86a6718d6db43271581a5900c83ff84b58acf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 16 Dec 2019 15:13:57 +0100 Subject: [PATCH 072/559] Add fallback functionality Add fallback functionality from next version 7.1.2.7 --- tasmota/CHANGELOG.md | 1 + tasmota/settings.ino | 284 +++++++++++++++++++++-------- tasmota/support.ino | 20 +- tasmota/support_command.ino | 89 ++++----- tasmota/support_rtc.ino | 6 +- tasmota/support_statistics.ino | 45 +---- tasmota/support_tasmota.ino | 87 +++++---- tasmota/support_wifi.ino | 22 ++- tasmota/tasmota.ino | 15 +- tasmota/xdrv_01_webserver.ino | 106 ++++++----- tasmota/xdrv_02_mqtt.ino | 192 ++++++++----------- tasmota/xdrv_10_rules.ino | 20 +- tasmota/xdrv_10_scripter.ino | 12 +- tasmota/xdrv_12_home_assistant.ino | 42 ++--- tasmota/xdrv_13_display.ino | 8 +- tasmota/xdrv_20_hue.ino | 7 +- tasmota/xdrv_21_wemo.ino | 2 +- tasmota/xdrv_99_debug.ino | 46 ----- 18 files changed, 517 insertions(+), 487 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index cb90c5af5..a466a3212 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Change some more Settings locations freeing up space for future single char allowing variable length text - Add Zigbee send automatic ZigbeeRead after sending a command - Add Zigbee improving Occupancy:false detection for Aqara sensor +- Add fallback functionality from next version 7.1.2.7 ### 7.1.2.5 20191213 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index c1faa559e..d1d3fc1e8 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -446,6 +446,9 @@ void UpdateQuickPowerCycle(bool update) * Config Settings.text char array support \*********************************************************************************************/ +char aws_mqtt_host[66]; +char aws_mqtt_user[1] { 0 }; + const uint32_t settings_text_size = 457; // Settings.flag4 (1E0) - Settings.ota_url (017) uint32_t GetSettingsTextLen(void) @@ -457,7 +460,7 @@ uint32_t GetSettingsTextLen(void) return position - Settings.ota_url; } -bool SettingsUpdateText(uint32_t index, char* replace_me) +bool SettingsUpdateText(uint32_t index, const char* replace_me) { if (index >= SET_MAX) { return false; // Setting not supported - internal error @@ -468,55 +471,165 @@ bool SettingsUpdateText(uint32_t index, char* replace_me) char replace[replace_len +1]; memcpy(replace, replace_me, sizeof(replace)); - uint32_t start_pos = 0; - uint32_t end_pos = 0; - char* position = Settings.ota_url; - for (uint32_t size = 0; size < SET_MAX; size++) { - while (*position++ != '\0') { } - if (1 == index) { - start_pos = position - Settings.ota_url; + if (Settings.version < 0x07010207) { + uint32_t idx = 0; + switch (index) { + case SET_OTAURL: strlcpy(Settings.ota_url, replace, sizeof(Settings.ota_url)); break; + case SET_MQTTPREFIX3: idx++; + case SET_MQTTPREFIX2: idx++; + case SET_MQTTPREFIX1: strlcpy(Settings.mqtt_prefix[idx], replace, sizeof(Settings.mqtt_prefix[idx])); break; + case SET_STASSID2: idx++; + case SET_STASSID1: strlcpy(Settings.sta_ssid[idx], replace, sizeof(Settings.sta_ssid[idx])); break; + case SET_STAPWD2: idx++; + case SET_STAPWD1: strlcpy(Settings.sta_pwd[idx], replace, sizeof(Settings.sta_pwd[idx])); break; + case SET_HOSTNAME: strlcpy(Settings.hostname, replace, sizeof(Settings.hostname)); break; + case SET_SYSLOG_HOST: strlcpy(Settings.syslog_host, replace, sizeof(Settings.syslog_host)); break; + case SET_WEBPWD: strlcpy(Settings.web_password, replace, sizeof(Settings.web_password)); break; +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + case SET_MQTT_HOST: + if (strlen(replace) <= sizeof(Settings.mqtt_host)) { + strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); + Settings.mqtt_user[0] = 0; + } else { + // need to split in mqtt_user first then mqtt_host + strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); + strlcpy(Settings.mqtt_host, &replace[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); + } + break; + case SET_MQTT_USER: break; +#else + case SET_MQTT_HOST: strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); break; + case SET_MQTT_USER: strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); break; +#endif + case SET_MQTT_CLIENT: strlcpy(Settings.mqtt_client, replace, sizeof(Settings.mqtt_client)); break; + case SET_MQTT_PWD: strlcpy(Settings.mqtt_pwd, replace, sizeof(Settings.mqtt_pwd)); break; + case SET_MQTT_FULLTOPIC: strlcpy(Settings.mqtt_fulltopic, replace, sizeof(Settings.mqtt_fulltopic)); break; + case SET_MQTT_TOPIC: strlcpy(Settings.mqtt_topic, replace, sizeof(Settings.mqtt_topic)); break; + case SET_MQTT_BUTTON_TOPIC: strlcpy(Settings.button_topic, replace, sizeof(Settings.button_topic)); break; + case SET_MQTT_SWITCH_TOPIC: strlcpy(Settings.switch_topic, replace, sizeof(Settings.switch_topic)); break; + case SET_MQTT_GRP_TOPIC: strlcpy(Settings.mqtt_grptopic, replace, sizeof(Settings.mqtt_grptopic)); break; + case SET_STATE_TXT4: idx++; + case SET_STATE_TXT3: idx++; + case SET_STATE_TXT2: idx++; + case SET_STATE_TXT1: strlcpy(Settings.state_text[idx], replace, sizeof(Settings.state_text[idx])); break; + case SET_NTPSERVER3: idx++; + case SET_NTPSERVER2: idx++; + case SET_NTPSERVER1: strlcpy(Settings.ntp_server[idx], replace, sizeof(Settings.ntp_server[idx])); break; + case SET_MEM5: idx++; + case SET_MEM4: idx++; + case SET_MEM3: idx++; + case SET_MEM2: idx++; + case SET_MEM1: strlcpy(Settings.mems[idx], replace, sizeof(Settings.mems[idx])); break; + case SET_CORS: strlcpy(Settings.cors_domain, replace, sizeof(Settings.cors_domain)); break; + case SET_FRIENDLYNAME4: idx++; + case SET_FRIENDLYNAME3: idx++; + case SET_FRIENDLYNAME2: idx++; + case SET_FRIENDLYNAME1: strlcpy(Settings.friendlyname[idx], replace, sizeof(Settings.friendlyname[idx])); break; } - else if (0 == index) { - end_pos = position - Settings.ota_url -1; + } else { + uint32_t start_pos = 0; + uint32_t end_pos = 0; + char* position = Settings.ota_url; + for (uint32_t size = 0; size < SET_MAX; size++) { + while (*position++ != '\0') { } + if (1 == index) { + start_pos = position - Settings.ota_url; + } + else if (0 == index) { + end_pos = position - Settings.ota_url -1; + } + index--; } - index--; + uint32_t char_len = position - Settings.ota_url; + + uint32_t current_len = end_pos - start_pos; + int diff = replace_len - current_len; + + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"), + // start_pos, end_pos, char_len, current_len, replace_len, diff); + + int too_long = (char_len + diff) - settings_text_size; + if (too_long > 0) { + // AddLog_P2(LOG_LEVEL_INFO, PSTR("CFG: Text too long by %d char(s)"), too_long); + return false; // Replace text too long + } + + if (diff != 0) { + // Shift Settings.text up or down + memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos); + } + // Replace text + memmove_P(Settings.ota_url + start_pos, replace, replace_len); + // Fill for future use + memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff); } - uint32_t char_len = position - Settings.ota_url; - - uint32_t current_len = end_pos - start_pos; - int diff = replace_len - current_len; - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"), -// start_pos, end_pos, char_len, current_len, replace_len, diff); - - int too_long = (char_len + diff) - settings_text_size; - if (too_long > 0) { -// AddLog_P2(LOG_LEVEL_INFO, PSTR("CFG: Text too long by %d char(s)"), too_long); - return false; // Replace text too long - } - - if (diff != 0) { - // Shift Settings.text up or down - memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos); - } - // Replace text - memmove_P(Settings.ota_url + start_pos, replace, replace_len); - // Fill for future use - memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff); return true; } -char* SettingsGetText(uint32_t index) +char* SettingsText(uint32_t index) { if (index >= SET_MAX) { return nullptr; // Setting not supported - internal error } char* position = Settings.ota_url; - for (;index > 0; index--) { - while (*position++ != '\0') { } + + if (Settings.version < 0x07010207) { + uint32_t idx = 0; + switch (index) { + case SET_MQTTPREFIX3: idx++; + case SET_MQTTPREFIX2: idx++; + case SET_MQTTPREFIX1: position = Settings.mqtt_prefix[idx]; break; + case SET_STASSID2: idx++; + case SET_STASSID1: position = Settings.sta_ssid[idx]; break; + case SET_STAPWD2: idx++; + case SET_STAPWD1: position = Settings.sta_pwd[idx]; break; + case SET_HOSTNAME: position = Settings.hostname; break; + case SET_SYSLOG_HOST: position = Settings.syslog_host; break; + case SET_WEBPWD: position = Settings.web_password; break; +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + case SET_MQTT_HOST: + strlcpy(aws_mqtt_host, Settings.mqtt_user, strlen(Settings.mqtt_user)); + strlcpy(&aws_mqtt_host[strlen(Settings.mqtt_user)], Settings.mqtt_host, sizeof(Settings.mqtt_host)); + position = aws_mqtt_host; break; + case SET_MQTT_USER: position = aws_mqtt_user; break; +#else + case SET_MQTT_HOST: position = Settings.mqtt_host; break; + case SET_MQTT_USER: position = Settings.mqtt_user; break; +#endif + case SET_MQTT_CLIENT: position = Settings.mqtt_client; break; + case SET_MQTT_PWD: position = Settings.mqtt_pwd; break; + case SET_MQTT_FULLTOPIC: position = Settings.mqtt_fulltopic; break; + case SET_MQTT_TOPIC: position = Settings.mqtt_topic; break; + case SET_MQTT_BUTTON_TOPIC: position = Settings.button_topic; break; + case SET_MQTT_SWITCH_TOPIC: position = Settings.switch_topic; break; + case SET_MQTT_GRP_TOPIC: position = Settings.mqtt_grptopic; break; + case SET_STATE_TXT4: idx++; + case SET_STATE_TXT3: idx++; + case SET_STATE_TXT2: idx++; + case SET_STATE_TXT1: position = Settings.state_text[idx]; break; + case SET_NTPSERVER3: idx++; + case SET_NTPSERVER2: idx++; + case SET_NTPSERVER1: position = Settings.ntp_server[idx]; break; + case SET_MEM5: idx++; + case SET_MEM4: idx++; + case SET_MEM3: idx++; + case SET_MEM2: idx++; + case SET_MEM1: position = Settings.mems[idx]; break; + case SET_CORS: position = Settings.cors_domain; break; + case SET_FRIENDLYNAME4: idx++; + case SET_FRIENDLYNAME3: idx++; + case SET_FRIENDLYNAME2: idx++; + case SET_FRIENDLYNAME1: position = Settings.friendlyname[idx]; break; + } + + } else { + for (;index > 0; index--) { + while (*position++ != '\0') { } + } } + return position; } @@ -751,11 +864,11 @@ void SettingsDefaultSet2(void) Settings.module = MODULE; ModuleDefault(WEMOS); // for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { Settings.my_gp.io[i] = GPIO_NONE; } - strlcpy(Settings.friendlyname[0], FRIENDLY_NAME, sizeof(Settings.friendlyname[0])); - strlcpy(Settings.friendlyname[1], FRIENDLY_NAME"2", sizeof(Settings.friendlyname[1])); - strlcpy(Settings.friendlyname[2], FRIENDLY_NAME"3", sizeof(Settings.friendlyname[2])); - strlcpy(Settings.friendlyname[3], FRIENDLY_NAME"4", sizeof(Settings.friendlyname[3])); - strlcpy(Settings.ota_url, OTA_URL, sizeof(Settings.ota_url)); + SettingsUpdateText(SET_FRIENDLYNAME1, FRIENDLY_NAME); + SettingsUpdateText(SET_FRIENDLYNAME2, FRIENDLY_NAME"2"); + SettingsUpdateText(SET_FRIENDLYNAME3, FRIENDLY_NAME"3"); + SettingsUpdateText(SET_FRIENDLYNAME4, FRIENDLY_NAME"4"); + SettingsUpdateText(SET_OTAURL, OTA_URL); // Power Settings.flag.save_state = SAVE_STATE; @@ -783,14 +896,14 @@ void SettingsDefaultSet2(void) ParseIp(&Settings.ip_address[3], WIFI_DNS); Settings.sta_config = WIFI_CONFIG_TOOL; // Settings.sta_active = 0; - strlcpy(Settings.sta_ssid[0], STA_SSID1, sizeof(Settings.sta_ssid[0])); - strlcpy(Settings.sta_pwd[0], STA_PASS1, sizeof(Settings.sta_pwd[0])); - strlcpy(Settings.sta_ssid[1], STA_SSID2, sizeof(Settings.sta_ssid[1])); - strlcpy(Settings.sta_pwd[1], STA_PASS2, sizeof(Settings.sta_pwd[1])); - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); + SettingsUpdateText(SET_STASSID1, STA_SSID1); + SettingsUpdateText(SET_STASSID2, STA_SSID2); + SettingsUpdateText(SET_STAPWD1, STA_PASS1); + SettingsUpdateText(SET_STAPWD2, STA_PASS2); + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); // Syslog - strlcpy(Settings.syslog_host, SYS_LOG_HOST, sizeof(Settings.syslog_host)); + SettingsUpdateText(SET_SYSLOG_HOST, SYS_LOG_HOST); Settings.syslog_port = SYS_LOG_PORT; Settings.syslog_level = SYS_LOG_LEVEL; @@ -798,9 +911,9 @@ void SettingsDefaultSet2(void) Settings.flag2.emulation = EMULATION; Settings.webserver = WEB_SERVER; Settings.weblog_level = WEB_LOG_LEVEL; - strlcpy(Settings.web_password, WEB_PASSWORD, sizeof(Settings.web_password)); + SettingsUpdateText(SET_WEBPWD, WEB_PASSWORD); Settings.flag3.mdns_enabled = MDNS_ENABLED; - strlcpy(Settings.cors_domain, CORS_DOMAIN, sizeof(Settings.cors_domain)); + SettingsUpdateText(SET_CORS, CORS_DOMAIN); // Button // Settings.flag.button_restrict = 0; @@ -823,24 +936,24 @@ void SettingsDefaultSet2(void) // Settings.flag.mqtt_offline = 0; // Settings.flag.mqtt_serial = 0; // Settings.flag.device_index_enable = 0; - strlcpy(Settings.mqtt_host, MQTT_HOST, sizeof(Settings.mqtt_host)); + SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST); Settings.mqtt_port = MQTT_PORT; - strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); - strlcpy(Settings.mqtt_user, MQTT_USER, sizeof(Settings.mqtt_user)); - strlcpy(Settings.mqtt_pwd, MQTT_PASS, sizeof(Settings.mqtt_pwd)); - strlcpy(Settings.mqtt_topic, MQTT_TOPIC, sizeof(Settings.mqtt_topic)); - strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); - strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); - strlcpy(Settings.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(Settings.mqtt_grptopic)); - strlcpy(Settings.mqtt_fulltopic, MQTT_FULLTOPIC, sizeof(Settings.mqtt_fulltopic)); + SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID); + SettingsUpdateText(SET_MQTT_USER, MQTT_USER); + SettingsUpdateText(SET_MQTT_PWD, MQTT_PASS); + SettingsUpdateText(SET_MQTT_TOPIC, MQTT_TOPIC); + SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); + SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); + SettingsUpdateText(SET_MQTT_FULLTOPIC, MQTT_FULLTOPIC); Settings.mqtt_retry = MQTT_RETRY_SECS; - strlcpy(Settings.mqtt_prefix[0], SUB_PREFIX, sizeof(Settings.mqtt_prefix[0])); - strlcpy(Settings.mqtt_prefix[1], PUB_PREFIX, sizeof(Settings.mqtt_prefix[1])); - strlcpy(Settings.mqtt_prefix[2], PUB_PREFIX2, sizeof(Settings.mqtt_prefix[2])); - strlcpy(Settings.state_text[0], MQTT_STATUS_OFF, sizeof(Settings.state_text[0])); - strlcpy(Settings.state_text[1], MQTT_STATUS_ON, sizeof(Settings.state_text[1])); - strlcpy(Settings.state_text[2], MQTT_CMND_TOGGLE, sizeof(Settings.state_text[2])); - strlcpy(Settings.state_text[3], MQTT_CMND_HOLD, sizeof(Settings.state_text[3])); + SettingsUpdateText(SET_MQTTPREFIX1, SUB_PREFIX); + SettingsUpdateText(SET_MQTTPREFIX2, PUB_PREFIX); + SettingsUpdateText(SET_MQTTPREFIX3, PUB_PREFIX2); + SettingsUpdateText(SET_STATE_TXT1, MQTT_STATUS_OFF); + SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON); + SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE); + SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD); char fingerprint[60]; strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint)); char *p = fingerprint; @@ -992,15 +1105,11 @@ void SettingsDefaultSet2(void) Settings.timezone = APP_TIMEZONE / 60; Settings.timezone_minutes = abs(APP_TIMEZONE % 60); } - strlcpy(Settings.ntp_server[0], NTP_SERVER1, sizeof(Settings.ntp_server[0])); - strlcpy(Settings.ntp_server[1], NTP_SERVER2, sizeof(Settings.ntp_server[1])); - strlcpy(Settings.ntp_server[2], NTP_SERVER3, sizeof(Settings.ntp_server[2])); - for (uint32_t j = 0; j < 3; j++) { - for (uint32_t i = 0; i < strlen(Settings.ntp_server[j]); i++) { - if (Settings.ntp_server[j][i] == ',') { - Settings.ntp_server[j][i] = '.'; - } - } + SettingsUpdateText(SET_NTPSERVER1, NTP_SERVER1); + SettingsUpdateText(SET_NTPSERVER2, NTP_SERVER2); + SettingsUpdateText(SET_NTPSERVER3, NTP_SERVER3); + for (uint32_t i = 0; i < 3; i++) { + SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i))); } Settings.latitude = (int)((double)LATITUDE * 1000000); Settings.longitude = (int)((double)LONGITUDE * 1000000); @@ -1278,6 +1387,33 @@ void SettingsDelta(void) memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); // 1E4 -> EFE } + if ((VERSION < 0x7010207) && (Settings.version > VERSION)) { + char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp)); + char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21)); + char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22)); + char temp23[strlen(SettingsText(SET_MQTTPREFIX3)) +1]; strncpy(temp23, SettingsText(SET_MQTTPREFIX3), sizeof(temp23)); + char temp31[strlen(SettingsText(SET_STASSID1)) +1]; strncpy(temp31, SettingsText(SET_STASSID1), sizeof(temp31)); + char temp32[strlen(SettingsText(SET_STASSID2)) +1]; strncpy(temp32, SettingsText(SET_STASSID2), sizeof(temp32)); + char temp41[strlen(SettingsText(SET_STAPWD1)) +1]; strncpy(temp41, SettingsText(SET_STAPWD1), sizeof(temp41)); + char temp42[strlen(SettingsText(SET_STAPWD2)) +1]; strncpy(temp42, SettingsText(SET_STAPWD2), sizeof(temp42)); + char temp5[strlen(SettingsText(SET_HOSTNAME)) +1]; strncpy(temp5, SettingsText(SET_HOSTNAME), sizeof(temp5)); + char temp6[strlen(SettingsText(SET_SYSLOG_HOST)) +1]; strncpy(temp6, SettingsText(SET_SYSLOG_HOST), sizeof(temp5)); + + uint32_t version = Settings.version; + Settings.version = VERSION; + SettingsUpdateText(SET_OTAURL, temp); + SettingsUpdateText(SET_MQTTPREFIX1, temp21); + SettingsUpdateText(SET_MQTTPREFIX2, temp22); + SettingsUpdateText(SET_MQTTPREFIX3, temp23); + SettingsUpdateText(SET_STASSID1, temp31); + SettingsUpdateText(SET_STASSID2, temp32); + SettingsUpdateText(SET_STAPWD1, temp41); + SettingsUpdateText(SET_STAPWD2, temp42); + SettingsUpdateText(SET_HOSTNAME, temp5); + SettingsUpdateText(SET_SYSLOG_HOST, temp6); + Settings.version = version; + } + Settings.version = VERSION; SettingsSave(1); } diff --git a/tasmota/support.ino b/tasmota/support.ino index 3ecc9b179..87f05ad27 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -328,6 +328,22 @@ char* RemoveSpace(char* p) return p; } +char* ReplaceCommaWithDot(char* p) +{ + char* write = (char*)p; + char* read = (char*)p; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + if (ch == ',') { + ch = '.'; + } + *write++ = ch; + } + return p; +} + char* LowerCase(char* dest, const char* source) { char* write = dest; @@ -1571,10 +1587,10 @@ void Syslog(void) { // Destroys log_data - uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); if (syslog_host_hash != current_hash) { syslog_host_hash = current_hash; - WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash + WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { char syslog_preamble[64]; // Hostname + Id diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index ec8de9126..b8fbd4a7a 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -147,7 +147,7 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) data_len--; } - bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr); + bool grpflg = (strstr(topicBuf, SettingsText(SET_MQTT_GRP_TOPIC)) != nullptr); char stemp1[TOPSZ]; GetFallbackTopic_P(stemp1, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/ @@ -325,11 +325,11 @@ void CmndStatus(void) uint32_t payload = ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > MAX_STATUS)) ? 99 : XdrvMailbox.payload; uint32_t option = STAT; - char stemp[MAX_FRIENDLYNAMES * (sizeof(Settings.friendlyname[0]) +MAX_FRIENDLYNAMES)]; + char stemp[200]; char stemp2[100]; // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX - if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) { option++; } // TELE + if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2)) && (!payload)) { option++; } // TELE if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } // SetOption3 - Enable MQTT if (!energy_flg && (9 == payload)) { payload = 99; } @@ -344,7 +344,7 @@ void CmndStatus(void) #endif // USE_SONOFF_IFAN stemp[0] = '\0'; for (uint32_t i = 0; i < maxfn; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), Settings.friendlyname[i]); + snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), SettingsText(SET_FRIENDLYNAME1 +i)); } stemp2[0] = '\0'; for (uint32_t i = 0; i < MAX_SWITCHES; i++) { @@ -355,10 +355,10 @@ void CmndStatus(void) D_CMND_LEDMASK "\":\"%04X\",\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), ModuleNr(), stemp, mqtt_topic, - Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, + SettingsText(SET_MQTT_BUTTON_TOPIC), power, Settings.poweronstate, Settings.ledstate, Settings.ledmask, Settings.save_data, Settings.flag.save_state, // SetOption0 - Save power state and use after restart - Settings.switch_topic, + SettingsText(SET_MQTT_SWITCH_TOPIC), stemp2, Settings.flag.mqtt_button_retain, // CMND_BUTTONRETAIN Settings.flag.mqtt_switch_retain, // CMND_SWITCHRETAIN @@ -371,7 +371,7 @@ void CmndStatus(void) Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), - baudrate, Settings.mqtt_grptopic, Settings.ota_url, + baudrate, SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); @@ -394,7 +394,7 @@ void CmndStatus(void) D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\"]}}"), Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, - Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period, + SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), Settings.tele_period, Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), Settings.flag3.data, Settings.flag4.data); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3")); @@ -425,17 +425,10 @@ void CmndStatus(void) } if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT -#ifdef USE_MQTT_AWS_IOT - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" - D_CMND_MQTTCLIENT "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), - Settings.mqtt_user, Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, - mqtt_client, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); -#else Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, - mqtt_client, Settings.mqtt_user, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); -#endif + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), + mqtt_client, SettingsText(SET_MQTT_USER), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); } @@ -557,10 +550,10 @@ void CmndUpgrade(void) void CmndOtaUrl(void) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.ota_url))) { - strlcpy(Settings.ota_url, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data, sizeof(Settings.ota_url)); + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data); } - ResponseCmndChar(Settings.ota_url); + ResponseCmndChar(SettingsText(SET_OTAURL)); } void CmndSeriallog(void) @@ -1193,10 +1186,10 @@ void CmndSyslog(void) void CmndLoghost(void) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.syslog_host))) { - strlcpy(Settings.syslog_host, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data, sizeof(Settings.syslog_host)); + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_SYSLOG_HOST, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data); } - ResponseCmndChar(Settings.syslog_host); + ResponseCmndChar(SettingsText(SET_SYSLOG_HOST)); } void CmndLogport(void) @@ -1224,17 +1217,15 @@ void CmndIpAddress(void) void CmndNtpServer(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.ntp_server[0]))) { - strlcpy(Settings.ntp_server[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?NTP_SERVER1:(2==XdrvMailbox.index)?NTP_SERVER2:NTP_SERVER3 : XdrvMailbox.data, - sizeof(Settings.ntp_server[0])); - for (uint32_t i = 0; i < strlen(Settings.ntp_server[XdrvMailbox.index -1]); i++) { - if (Settings.ntp_server[XdrvMailbox.index -1][i] == ',') Settings.ntp_server[XdrvMailbox.index -1][i] = '.'; - } + uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1; + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(ntp_server, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? NTP_SERVER1 : (2 == XdrvMailbox.index) ? NTP_SERVER2 : NTP_SERVER3 : XdrvMailbox.data); + SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); // restart_flag = 2; // Issue #3890 ntp_force_sync = true; } - ResponseCmndIdxChar(Settings.ntp_server[XdrvMailbox.index -1]); + ResponseCmndIdxChar(SettingsText(ntp_server)); } } @@ -1251,33 +1242,31 @@ void CmndAp(void) } restart_flag = 2; } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active]); + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active)); } void CmndSsid(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.sta_ssid[0]))) { - strlcpy(Settings.sta_ssid[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data, - sizeof(Settings.sta_ssid[0])); + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); Settings.sta_active = XdrvMailbox.index -1; restart_flag = 2; } - ResponseCmndIdxChar(Settings.sta_ssid[XdrvMailbox.index -1]); + ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); } } void CmndPassword(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.data_len > 4 || SC_CLEAR == Shortcut() || SC_DEFAULT == Shortcut()) && (XdrvMailbox.data_len < sizeof(Settings.sta_pwd[0]))) { - strlcpy(Settings.sta_pwd[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data, - sizeof(Settings.sta_pwd[0])); + if ((XdrvMailbox.data_len > 4) || (SC_CLEAR == Shortcut()) || (SC_DEFAULT == Shortcut())) { + SettingsUpdateText(SET_STAPWD1 + XdrvMailbox.index -1, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data); Settings.sta_active = XdrvMailbox.index -1; restart_flag = 2; - ResponseCmndIdxChar(Settings.sta_pwd[XdrvMailbox.index -1]); + ResponseCmndIdxChar(SettingsText(SET_STAPWD1 + XdrvMailbox.index -1)); } else { Response_P(S_JSON_COMMAND_INDEX_ASTERISK, XdrvMailbox.command, XdrvMailbox.index); } @@ -1286,14 +1275,14 @@ void CmndPassword(void) void CmndHostname(void) { - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.hostname))) { - strlcpy(Settings.hostname, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data, sizeof(Settings.hostname)); - if (strstr(Settings.hostname, "%") != nullptr) { - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { + SettingsUpdateText(SET_HOSTNAME, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); } restart_flag = 2; } - ResponseCmndChar(Settings.hostname); + ResponseCmndChar(SettingsText(SET_HOSTNAME)); } void CmndWifiConfig(void) @@ -1315,16 +1304,16 @@ void CmndWifiConfig(void) void CmndFriendlyname(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.friendlyname[0]))) { + if (XdrvMailbox.data_len > 0) { char stemp1[TOPSZ]; if (1 == XdrvMailbox.index) { snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME)); } else { snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); } - strlcpy(Settings.friendlyname[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data, sizeof(Settings.friendlyname[XdrvMailbox.index -1])); + SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); } - ResponseCmndIdxChar(Settings.friendlyname[XdrvMailbox.index -1]); + ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1)); } } diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 27ef66ec7..ffaf171a3 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -469,9 +469,9 @@ void RtcSetTime(uint32_t epoch) void RtcInit(void) { - sntp_setservername(0, Settings.ntp_server[0]); - sntp_setservername(1, Settings.ntp_server[1]); - sntp_setservername(2, Settings.ntp_server[2]); + sntp_setservername(0, SettingsText(SET_NTPSERVER1)); + sntp_setservername(1, SettingsText(SET_NTPSERVER2)); + sntp_setservername(2, SettingsText(SET_NTPSERVER3)); sntp_stop(); sntp_set_timezone(0); // UTC time sntp_init(); diff --git a/tasmota/support_statistics.ino b/tasmota/support_statistics.ino index a34c7250a..1907b1edc 100644 --- a/tasmota/support_statistics.ino +++ b/tasmota/support_statistics.ino @@ -24,53 +24,10 @@ * Gather statistics \*********************************************************************************************/ -struct STATS { -// uint32_t str_size = 1151; // Total number of characters reserved as char array in Settings - uint32_t str_len = 0; // Total number of characters used within char array -} Stats; - -void StatisticsChar(const char* text) -{ - uint32_t len = strlen(text); - Stats.str_len += len; -} - String GetStatistics(void) { - Stats.str_len = 0; - - for (uint32_t i = 0; i < 2; i++) { - StatisticsChar(Settings.sta_ssid[i]); - StatisticsChar(Settings.sta_pwd[i]); - } - for (uint32_t i = 0; i < 3; i++) { - StatisticsChar(Settings.mqtt_prefix[i]); - StatisticsChar(Settings.ntp_server[i]); - } - for (uint32_t i = 0; i < 4; i++) { - StatisticsChar(Settings.state_text[i]); - StatisticsChar(Settings.friendlyname[i]); - } - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - StatisticsChar(Settings.mems[i]); - } - StatisticsChar(Settings.ota_url); - StatisticsChar(Settings.hostname); - StatisticsChar(Settings.syslog_host); - StatisticsChar(Settings.mqtt_host); - StatisticsChar(Settings.mqtt_client); - StatisticsChar(Settings.mqtt_user); - StatisticsChar(Settings.mqtt_pwd); - StatisticsChar(Settings.mqtt_topic); - StatisticsChar(Settings.button_topic); - StatisticsChar(Settings.switch_topic); - StatisticsChar(Settings.mqtt_grptopic); - StatisticsChar(Settings.web_password); - StatisticsChar(Settings.mqtt_fulltopic); - StatisticsChar(Settings.cors_domain); - char data[40]; - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151\""), Stats.str_len); // Char Usage Ratio + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); // Char Usage Ratio return String(data); } diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 0f930e06e..ff2b6f40a 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -60,15 +60,16 @@ char* Format(char* output, const char* input, int size) char* GetOtaUrl(char *otaurl, size_t otaurl_size) { - if (strstr(Settings.ota_url, "%04d") != nullptr) { // OTA url contains placeholder for chip ID - snprintf(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId() & 0x1fff); + if (strstr(SettingsText(SET_OTAURL), "%04d") != nullptr) { // OTA url contains placeholder for chip ID + snprintf(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId() & 0x1fff); } - else if (strstr(Settings.ota_url, "%d") != nullptr) { // OTA url contains placeholder for chip ID - snprintf_P(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId()); + else if (strstr(SettingsText(SET_OTAURL), "%d") != nullptr) { // OTA url contains placeholder for chip ID + snprintf_P(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId()); } else { - strlcpy(otaurl, Settings.ota_url, otaurl_size); + strlcpy(otaurl, SettingsText(SET_OTAURL), otaurl_size); } + return otaurl; } @@ -101,17 +102,19 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi fulltopic += topic; // cmnd/ } } else { - fulltopic = Settings.mqtt_fulltopic; + fulltopic = SettingsText(SET_MQTT_FULLTOPIC); if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { fulltopic += F("/"); fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops } for (uint32_t i = 0; i < 3; i++) { - if ('\0' == Settings.mqtt_prefix[i][0]) { - GetTextIndexed(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), i, kPrefixes); + if ('\0' == SettingsText(SET_MQTTPREFIX1 + i)) { + char temp[TOPSZ]; + SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes)); } } - fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); + fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + prefix)); + fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); fulltopic.replace(F("%hostname%"), my_hostname); String token_id = WiFi.macAddress(); @@ -131,7 +134,7 @@ char* GetGroupTopic_P(char *stopic, const char* subtopic) { // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# // SetOption75 1: cmnd/ - return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, Settings.mqtt_grptopic, subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) + return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(SET_MQTT_GRP_TOPIC), subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) } char* GetFallbackTopic_P(char *stopic, const char* subtopic) @@ -144,7 +147,7 @@ char* GetStateText(uint32_t state) if (state > 3) { state = 1; } - return Settings.state_text[state]; + return SettingsText(SET_STATE_TXT1 + state); } /********************************************************************************************/ @@ -358,10 +361,10 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) char stopic[TOPSZ]; char scommand[CMDSZ]; - char key_topic[sizeof(Settings.button_topic)]; + char key_topic[TOPSZ]; bool result = false; - char *tmp = (key) ? Settings.switch_topic : Settings.button_topic; + char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_BUTTON_TOPIC); Format(key_topic, tmp, sizeof(key_topic)); if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { // SetOption3 - Enable MQTT if (!key && (device > devices_present)) { @@ -374,7 +377,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) } else { if ((Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set !strcmp(mqtt_topic, key_topic) || - !strcmp(Settings.mqtt_grptopic, key_topic)) && + !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) && (POWER_TOGGLE == state)) { state = ~(power >> (device -1)) &1; // POWER_OFF or POWER_ON } @@ -584,7 +587,7 @@ void MqttShowState(void) } ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), - Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str()); } @@ -813,7 +816,6 @@ void Every250mSeconds(void) if (ota_state_flag && BACKLOG_EMPTY) { ota_state_flag--; if (2 == ota_state_flag) { - ota_url = Settings.ota_url; RtcSettings.ota_loader = 0; // Try requested image first ota_retry_counter = OTA_ATTEMPTS; ESPhttpUpdate.rebootOnUpdate(false); @@ -839,7 +841,7 @@ void Every250mSeconds(void) if (!pch) { pch = ech; } if (pch) { mqtt_data[pch - mqtt_data] = '\0'; - char *ech = strrchr(Settings.ota_url, '.'); // Change from filename.bin into filename-minimal.bin + char *ech = strrchr(SettingsText(SET_OTAURL), '.'); // Change from filename.bin into filename-minimal.bin snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); // Minimal filename must be filename-minimal } } @@ -903,30 +905,45 @@ void Every250mSeconds(void) } if (restart_flag && BACKLOG_EMPTY) { if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { - char storage_wifi[sizeof(Settings.sta_ssid) + - sizeof(Settings.sta_pwd)]; + // Backup current SSIDs and Passwords + char storage_ssid1[strlen(SettingsText(SET_STASSID1)) +1]; + strncpy(storage_ssid1, SettingsText(SET_STASSID1), sizeof(storage_ssid1)); + char storage_ssid2[strlen(SettingsText(SET_STASSID2)) +1]; + strncpy(storage_ssid2, SettingsText(SET_STASSID2), sizeof(storage_ssid2)); + char storage_pass1[strlen(SettingsText(SET_STAPWD1)) +1]; + strncpy(storage_pass1, SettingsText(SET_STAPWD1), sizeof(storage_pass1)); + char storage_pass2[strlen(SettingsText(SET_STAPWD2)) +1]; + strncpy(storage_pass2, SettingsText(SET_STAPWD2), sizeof(storage_pass2)); - char storage_mqtt[sizeof(Settings.mqtt_host) + - sizeof(Settings.mqtt_port) + - sizeof(Settings.mqtt_client) + - sizeof(Settings.mqtt_user) + - sizeof(Settings.mqtt_pwd) + - sizeof(Settings.mqtt_topic)]; - uint16_t mqtt_port = Settings.mqtt_port; // Workaround 7.1.2.6 Settings shuffle + char storage_mqtthost[strlen(SettingsText(SET_MQTT_HOST)) +1]; + strncpy(storage_mqtthost, SettingsText(SET_MQTT_HOST), sizeof(storage_mqtthost)); + char storage_mqttuser[strlen(SettingsText(SET_MQTT_USER)) +1]; + strncpy(storage_mqttuser, SettingsText(SET_MQTT_USER), sizeof(storage_mqttuser)); + char storage_mqttpwd[strlen(SettingsText(SET_MQTT_PWD)) +1]; + strncpy(storage_mqttpwd, SettingsText(SET_MQTT_PWD), sizeof(storage_mqttpwd)); + char storage_mqtttopic[strlen(SettingsText(SET_MQTT_TOPIC)) +1]; + strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic)); + uint16_t mqtt_port = Settings.mqtt_port; - memcpy(storage_wifi, Settings.sta_ssid, sizeof(storage_wifi)); // Backup current SSIDs and Passwords - if (216 == restart_flag) { - memcpy(storage_mqtt, Settings.mqtt_host, sizeof(storage_mqtt)); // Backup mqtt host, port, client, username and password - } +// if (216 == restart_flag) { + // Backup mqtt host, port, client, username and password +// } if ((215 == restart_flag) || (216 == restart_flag)) { SettingsErase(0); // Erase all flash from program end to end of physical flash } SettingsDefault(); - memcpy(Settings.sta_ssid, storage_wifi, sizeof(storage_wifi)); // Restore current SSIDs and Passwords + // Restore current SSIDs and Passwords + SettingsUpdateText(SET_STASSID1, storage_ssid1); + SettingsUpdateText(SET_STASSID2, storage_ssid2); + SettingsUpdateText(SET_STAPWD1, storage_pass1); + SettingsUpdateText(SET_STAPWD2, storage_pass2); if (216 == restart_flag) { - memcpy(Settings.mqtt_host, storage_mqtt, sizeof(storage_mqtt)); // Restore the mqtt host, port, client, username and password - strlcpy(Settings.mqtt_client, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)); // Set client to default - Settings.mqtt_port = mqtt_port; // Workaround 7.1.2.6 Settings shuffle + // Restore the mqtt host, port, client, username and password + SettingsUpdateText(SET_MQTT_HOST, storage_mqtthost); + SettingsUpdateText(SET_MQTT_USER, storage_mqttuser); + SettingsUpdateText(SET_MQTT_PWD, storage_mqttpwd); + SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic); + Settings.mqtt_port = mqtt_port; } restart_flag = 2; } @@ -977,7 +994,7 @@ void ArduinoOTAInit(void) { ArduinoOTA.setPort(8266); ArduinoOTA.setHostname(my_hostname); - if (Settings.web_password[0] !=0) { ArduinoOTA.setPassword(Settings.web_password); } + if (strlen(SettingsText(SET_WEBPWD))) { ArduinoOTA.setPassword(SettingsText(SET_WEBPWD)); } ArduinoOTA.onStart([]() { diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 3f9e7795b..86cc81dd8 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -191,18 +191,20 @@ void WifiBegin(uint8_t flag, uint8_t channel) case 2: // Toggle Settings.sta_active ^= 1; } // 3: Current AP - if ('\0' == Settings.sta_ssid[Settings.sta_active][0]) { Settings.sta_active ^= 1; } // Skip empty SSID + if ('\0' == SettingsText(SET_STASSID1 + Settings.sta_active)) { + Settings.sta_active ^= 1; // Skip empty SSID + } if (Settings.ip_address[0]) { WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); // Set static IP } WiFi.hostname(my_hostname); if (channel) { - WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active], channel, Wifi.bssid); + WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); } else { - WiFi.begin(Settings.sta_ssid[Settings.sta_active], Settings.sta_pwd[Settings.sta_active]); + WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); } AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); #if LWIP_IPV6 for (bool configured = false; !configured;) { @@ -278,10 +280,10 @@ void WifiBeginAfterScan(void) bool known = false; uint32_t j; for (j = 0; j < 2; j++) { - if (ssid_scan == Settings.sta_ssid[j]) { // SSID match + if (ssid_scan == SettingsText(SET_STASSID1 + j)) { // SSID match known = true; if (rssi_scan > best_network_db) { // Best network - if (sec_scan == ENC_TYPE_NONE || Settings.sta_pwd[j]) { // Check for passphrase if not open wlan + if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { // Check for passphrase if not open wlan best_network_db = (int8_t)rssi_scan; channel = chan_scan; ap = j; // AP1 or AP2 @@ -434,7 +436,7 @@ void WifiCheckIp(void) if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); } else { - if (('\0' == Settings.sta_ssid[0][0]) && ('\0' == Settings.sta_ssid[1][0])) { + if (('\0' == SettingsText(SET_STASSID1)) && ('\0' == SettingsText(SET_STASSID2))) { wifi_config_tool = WIFI_MANAGER; // Skip empty SSIDs and start Wifi config tool Wifi.retry = 0; } else { @@ -480,13 +482,13 @@ void WifiCheck(uint8_t param) if (Wifi.config_counter) { if (!Wifi.config_counter) { if (strlen(WiFi.SSID().c_str())) { - strlcpy(Settings.sta_ssid[0], WiFi.SSID().c_str(), sizeof(Settings.sta_ssid[0])); + SettingsUpdateText(SET_STASSID1, WiFi.SSID().c_str()); } if (strlen(WiFi.psk().c_str())) { - strlcpy(Settings.sta_pwd[0], WiFi.psk().c_str(), sizeof(Settings.sta_pwd[0])); + SettingsUpdateText(SET_STAPWD1, WiFi.psk().c_str()); } Settings.sta_active = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), Settings.sta_ssid[0]); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), SettingsText(SET_STASSID1)); } } if (!Wifi.config_counter) { diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 306250549..3b9e64a25 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -110,7 +110,6 @@ uint32_t web_log_index = 1; // Index in Web log buffer (should n float global_temperature = 9999; // Provide a global temperature to be used by some sensors float global_humidity = 0; // Provide a global humidity to be used by some sensors float global_pressure = 0; // Provide a global pressure to be used by some sensors -char *ota_url; // OTA url string pointer uint16_t tele_period = 9999; // Tele period timer uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command uint16_t blink_counter = 0; // Number of blink cycles @@ -265,13 +264,13 @@ void setup(void) } } - Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); - Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); - if (strstr(Settings.hostname, "%") != nullptr) { - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); - snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname, mqtt_topic, ESP.getChipId() & 0x1FFF); + Format(mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(mqtt_client)); + Format(mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(mqtt_topic)); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME), mqtt_topic, ESP.getChipId() & 0x1FFF); } else { - snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname); + snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME)); } GetEspHardwareType(); @@ -330,7 +329,7 @@ void setup(void) } blink_powersave = power; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, Settings.friendlyname[0], my_version, my_image); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, SettingsText(SET_FRIENDLYNAME1), my_version, my_image); #ifdef FIRMWARE_MINIMAL AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); #endif // FIRMWARE_MINIMAL diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 5dbec658a..9c8131ad3 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -658,8 +658,8 @@ void PollDnsWebserver(void) bool WebAuthenticate(void) { - if (Settings.web_password[0] != 0 && HTTP_MANAGER_RESET_ONLY != Web.state) { - return WebServer->authenticate(WEB_USERNAME, Settings.web_password); + if (strlen(SettingsText(SET_WEBPWD)) && (HTTP_MANAGER_RESET_ONLY != Web.state)) { + return WebServer->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD)); } else { return true; } @@ -680,8 +680,8 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true) void HttpHeaderCors(void) { - if (Settings.cors_domain[0] != 0) { - WebServer->sendHeader(F("Access-Control-Allow-Origin"), Settings.cors_domain); + if (strlen(SettingsText(SET_CORS))) { + WebServer->sendHeader(F("Access-Control-Allow-Origin"), SettingsText(SET_CORS)); } } @@ -816,7 +816,7 @@ void WSContentSend_PD(const char* formatP, ...) // Content send snprintf_P ch void WSContentStart_P(const char* title, bool auth) { - if (auth && (Settings.web_password[0] != 0) && !WebServer->authenticate(WEB_USERNAME, Settings.web_password)) { + if (auth && strlen(SettingsText(SET_WEBPWD)) && !WebServer->authenticate(WEB_USERNAME, SettingsText(SET_WEBPWD))) { return WebServer->requestAuthentication(); } @@ -825,7 +825,7 @@ void WSContentStart_P(const char* title, bool auth) if (title != nullptr) { char ctitle[strlen_P(title) +1]; strcpy_P(ctitle, title); // Get title from flash to RAM - WSContentSend_P(HTTP_HEADER, Settings.friendlyname[0], ctitle); + WSContentSend_P(HTTP_HEADER, SettingsText(SET_FRIENDLYNAME1), ctitle); } } @@ -869,7 +869,7 @@ void WSContentSendStyle_P(const char* formatP, ...) WebColor(COL_TEXT_WARNING), #endif WebColor(COL_TITLE), - ModuleName().c_str(), Settings.friendlyname[0]); + ModuleName().c_str(), SettingsText(SET_FRIENDLYNAME1)); if (Settings.flag3.gui_hostname_ip) { // SetOption53 - Show hostanme and IP address in GUI main menu bool lip = (static_cast(WiFi.localIP()) != 0); bool sip = (static_cast(WiFi.softAPIP()) != 0); @@ -993,10 +993,10 @@ void HandleRoot(void) if (WifiIsInManagerMode()) { #ifndef FIRMWARE_MINIMAL - if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { + if (strlen(SettingsText(SET_WEBPWD)) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { HandleWifiLogin(); } else { - if (!(Settings.web_password[0] != 0) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == Settings.web_password )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { + if (!strlen(SettingsText(SET_WEBPWD)) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { HandleWifiConfiguration(); } else { // wrong user and pass @@ -1676,7 +1676,7 @@ void HandleWifiConfiguration(void) } // As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception - WSContentSend_P(HTTP_FORM_WIFI, Settings.sta_ssid[0], Settings.sta_ssid[1], WIFI_HOSTNAME, WIFI_HOSTNAME, Settings.hostname, Settings.cors_domain); + WSContentSend_P(HTTP_FORM_WIFI, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS)); WSContentSend_P(HTTP_FORM_END); } @@ -1693,24 +1693,25 @@ void HandleWifiConfiguration(void) void WifiSaveSettings(void) { - char tmp[sizeof(Settings.sta_pwd[0])]; // Max length is currently 65 + char tmp[100]; // Max length is currently 65 WebGetArg("h", tmp, sizeof(tmp)); - strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); - if (strstr(Settings.hostname, "%") != nullptr) { - strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); + SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); } WebGetArg("c", tmp, sizeof(tmp)); - strlcpy(Settings.cors_domain, (!strlen(tmp)) ? CORS_DOMAIN : tmp, sizeof(Settings.cors_domain)); + SettingsUpdateText(SET_CORS, (!strlen(tmp)) ? CORS_DOMAIN : tmp); WebGetArg("s1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_ssid[0], (!strlen(tmp)) ? STA_SSID1 : tmp, sizeof(Settings.sta_ssid[0])); + SettingsUpdateText(SET_STASSID1, (!strlen(tmp)) ? STA_SSID1 : tmp); WebGetArg("s2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_ssid[1], (!strlen(tmp)) ? STA_SSID2 : tmp, sizeof(Settings.sta_ssid[1])); + SettingsUpdateText(SET_STASSID2, (!strlen(tmp)) ? STA_SSID2 : tmp); WebGetArg("p1", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[0], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[0] : tmp, sizeof(Settings.sta_pwd[0])); + SettingsUpdateText(SET_STAPWD1, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD1) : tmp); WebGetArg("p2", tmp, sizeof(tmp)); - strlcpy(Settings.sta_pwd[1], (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? Settings.sta_pwd[1] : tmp, sizeof(Settings.sta_pwd[1])); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), Settings.hostname, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.cors_domain); + SettingsUpdateText(SET_STAPWD2, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD2) : tmp); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), + SettingsText(SET_HOSTNAME), SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), SettingsText(SET_CORS)); } /*-------------------------------------------------------------------------------------------*/ @@ -1747,7 +1748,7 @@ void HandleLoggingConfiguration(void) } WSContentSend_P(PSTR("

")); } - WSContentSend_P(HTTP_FORM_LOG2, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); + WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, Settings.tele_period); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); @@ -1755,7 +1756,7 @@ void HandleLoggingConfiguration(void) void LoggingSaveSettings(void) { - char tmp[sizeof(Settings.syslog_host)]; // Max length is currently 33 + char tmp[100]; // Max length is currently 33 WebGetArg("l0", tmp, sizeof(tmp)); SetSeriallog((!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp)); @@ -1766,7 +1767,7 @@ void LoggingSaveSettings(void) WebGetArg("l3", tmp, sizeof(tmp)); SetSyslog((!strlen(tmp)) ? SYS_LOG_LEVEL : atoi(tmp)); WebGetArg("lh", tmp, sizeof(tmp)); - strlcpy(Settings.syslog_host, (!strlen(tmp)) ? SYS_LOG_HOST : tmp, sizeof(Settings.syslog_host)); + SettingsUpdateText(SET_SYSLOG_HOST, (!strlen(tmp)) ? SYS_LOG_HOST : tmp); WebGetArg("lp", tmp, sizeof(tmp)); Settings.syslog_port = (!strlen(tmp)) ? SYS_LOG_PORT : atoi(tmp); WebGetArg("lt", tmp, sizeof(tmp)); @@ -1775,7 +1776,7 @@ void LoggingSaveSettings(void) Settings.tele_period = 10; // Do not allow periods < 10 seconds } AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_LOG D_CMND_SERIALLOG " %d, " D_CMND_WEBLOG " %d, " D_CMND_MQTTLOG " %d, " D_CMND_SYSLOG " %d, " D_CMND_LOGHOST " %s, " D_CMND_LOGPORT " %d, " D_CMND_TELEPERIOD " %d"), - Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.tele_period); + Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, Settings.tele_period); } /*-------------------------------------------------------------------------------------------*/ @@ -1811,7 +1812,7 @@ void HandleOtherConfiguration(void) (i) ? stemp : "", i, (i) ? stemp : "", - Settings.friendlyname[i]); + SettingsText(SET_FRIENDLYNAME1 + i)); } #ifdef USE_EMULATION @@ -1843,10 +1844,10 @@ void OtherSaveSettings(void) { char tmp[128]; char webindex[5]; - char friendlyname[sizeof(Settings.friendlyname[0])]; + char friendlyname[TOPSZ]; WebGetArg("wp", tmp, sizeof(tmp)); - strlcpy(Settings.web_password, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? Settings.web_password : tmp, sizeof(Settings.web_password)); + SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp); Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); // SetOption3 - Enable MQTT #ifdef USE_EMULATION WebGetArg("b2", tmp, sizeof(tmp)); @@ -1857,8 +1858,8 @@ void OtherSaveSettings(void) snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i); WebGetArg(webindex, tmp, sizeof(tmp)); snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1); - strlcpy(Settings.friendlyname[i], (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp, sizeof(Settings.friendlyname[i])); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", Settings.friendlyname[i]); + SettingsUpdateText(SET_FRIENDLYNAME1 +i, (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp); + snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", SettingsText(SET_FRIENDLYNAME1 +i)); } AddLog(LOG_LEVEL_INFO); WebGetArg("t1", tmp, sizeof(tmp)); @@ -1890,8 +1891,8 @@ void HandleBackupConfiguration(void) char attachment[100]; -// char friendlyname[sizeof(Settings.friendlyname[0])]; -// snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, Settings.friendlyname[0]), my_version); +// char friendlyname[TOPSZ]; +// snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, SettingsText(SET_FRIENDLYNAME1)), my_version); char hostname[sizeof(my_hostname)]; snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(hostname, my_hostname), my_version); @@ -1991,10 +1992,10 @@ void HandleInformation(void) if (IsModuleIfan()) { maxfn = 1; } #endif // USE_SONOFF_IFAN for (uint32_t i = 0; i < maxfn; i++) { - WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, Settings.friendlyname[i]); + WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsText(SET_FRIENDLYNAME1 +i)); } WSContentSend_P(PSTR("}1}2 ")); // Empty line - WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI()); + WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI()); WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : ""); #if LWIP_IPV6 String ipv6_addr = WifiGetIPv6(); @@ -2016,17 +2017,12 @@ void HandleInformation(void) } WSContentSend_P(PSTR("}1}2 ")); // Empty line if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT -#ifdef USE_MQTT_AWS_IOT - WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s%s"), Settings.mqtt_user, Settings.mqtt_host); + WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsText(SET_MQTT_HOST)); WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); -#else - WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), Settings.mqtt_host); - WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port); - WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), Settings.mqtt_user); -#endif + WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER)); WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), mqtt_client); - WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), Settings.mqtt_topic); -// WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), Settings.mqtt_grptopic); + WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC)); +// WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), SettingsText(SET_MQTT_GRP_TOPIC)); WSContentSend_P(PSTR("}1" D_MQTT_GROUP_TOPIC "}2%s"), GetGroupTopic_P(stopic, "")); WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, mqtt_topic, "")); WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, "")); @@ -2085,7 +2081,7 @@ void HandleUpgradeFirmware(void) WSContentStart_P(S_FIRMWARE_UPGRADE); WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_UPG, Settings.ota_url); + WSContentSend_P(HTTP_FORM_UPG, SettingsText(SET_OTAURL)); WSContentSend_P(HTTP_FORM_RST_UPG, D_UPGRADE); WSContentSpaceButton(BUTTON_MAIN); WSContentStop(); @@ -2098,12 +2094,12 @@ void HandleUpgradeFirmwareStart(void) { if (!HttpCheckPriviledgedAccess()) { return; } - char command[sizeof(Settings.ota_url) + 10]; // OtaUrl + char command[128]; // OtaUrl AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); WifiConfigCounter(); - char otaurl[sizeof(Settings.ota_url)]; + char otaurl[101]; WebGetArg("o", otaurl, sizeof(otaurl)); if (strlen(otaurl)) { snprintf_P(command, sizeof(command), PSTR(D_CMND_OTAURL " %s"), otaurl); @@ -2412,12 +2408,12 @@ void HandleHttpCommand(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND)); bool valid = true; - if (Settings.web_password[0] != 0) { - char tmp1[sizeof(Settings.web_password)]; + if (strlen(SettingsText(SET_WEBPWD))) { + char tmp1[33]; WebGetArg("user", tmp1, sizeof(tmp1)); - char tmp2[sizeof(Settings.web_password)]; + char tmp2[strlen(SettingsText(SET_WEBPWD)) +1]; WebGetArg("password", tmp2, sizeof(tmp2)); - if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, Settings.web_password))) { valid = false; } + if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { valid = false; } } WSContentBegin(200, CT_JSON); @@ -2790,9 +2786,9 @@ void CmndWebServer(void) void CmndWebPassword(void) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.web_password))) { - strlcpy(Settings.web_password, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.web_password)); - ResponseCmndChar(Settings.web_password); + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_WEBPWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data); + ResponseCmndChar(SettingsText(SET_WEBPWD)); } else { Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); } @@ -2860,10 +2856,10 @@ void CmndWebSensor(void) void CmndCors(void) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.cors_domain))) { - strlcpy(Settings.cors_domain, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.cors_domain)); + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_CORS, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data); } - ResponseCmndChar(Settings.cors_domain); + ResponseCmndChar(SettingsText(SET_CORS)); } /*********************************************************************************************\ diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 7a9b1bf43..47838e223 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -91,10 +91,6 @@ tls_dir_t tls_dir; // memory copy of tls_dir from flash #endif // USE_MQTT_AWS_IOT -// A typical AWS IoT endpoint is 50 characters long, it does not fit -// in MqttHost field (32 chars). We need to concatenate both MqttUser and MqttHost -char AWS_endpoint[65]; // aWS IOT endpoint, concatenation of user and host - // check whether the fingerprint is filled with a single value // Filled with 0x00 = accept any fingerprint and learn it for next time // Filled with 0xFF = accept any fingerpring forever @@ -106,21 +102,6 @@ bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value) { } return true; } - -#ifdef USE_MQTT_AWS_IOT -void setLongMqttHost(const char *mqtt_host) { - if (strlen(mqtt_host) <= sizeof(Settings.mqtt_host)) { - strlcpy(Settings.mqtt_host, mqtt_host, sizeof(Settings.mqtt_host)); - Settings.mqtt_user[0] = 0; - } else { - // need to split in mqtt_user first then mqtt_host - strlcpy(Settings.mqtt_user, mqtt_host, sizeof(Settings.mqtt_user)); - strlcpy(Settings.mqtt_host, &mqtt_host[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); - } - strlcpy(AWS_endpoint, mqtt_host, sizeof(AWS_endpoint)); -} -#endif // USE_MQTT_AWS_IOT - #endif // USE_MQTT_TLS void MakeValidMqtt(uint32_t option, char* str) @@ -165,10 +146,10 @@ void MqttDiscoverServer(void) } } #endif // MDNS_HOSTNAME - snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); + SettingsUpdateText(SET_MQTT_HOST, MDNS.IP(i).toString().c_str()); Settings.mqtt_port = MDNS.port(i); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), Settings.mqtt_host, Settings.mqtt_port); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), SettingsText(SET_MQTT_HOST), Settings.mqtt_port); } } #endif // MQTT_HOST_DISCOVERY @@ -202,8 +183,6 @@ void MqttInit(void) tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); #ifdef USE_MQTT_AWS_IOT - snprintf_P(AWS_endpoint, sizeof(AWS_endpoint), PSTR("%s%s"), Settings.mqtt_user, Settings.mqtt_host); - loadTlsDir(); // load key and certificate data from Flash tlsClient->setClientECCert(AWS_IoT_Client_Certificate, AWS_IoT_Private_Key, @@ -261,8 +240,8 @@ void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len if (data_len >= MQTT_MAX_PACKET_SIZE) { return; } // Do not execute multiple times if Prefix1 equals Prefix2 - if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) { - char *str = strstr(mqtt_topic, Settings.mqtt_prefix[0]); + if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { + char *str = strstr(mqtt_topic, SettingsText(SET_MQTTPREFIX1)); if ((str == mqtt_topic) && mqtt_cmnd_publish) { if (mqtt_cmnd_publish > 3) { mqtt_cmnd_publish -= 3; @@ -330,8 +309,8 @@ void MqttPublishLogging(const char *mxtime) GetTopic_P(stopic, STAT, mqtt_topic, romram); char *me; - if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) { - me = strstr(stopic, Settings.mqtt_prefix[0]); + if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { + me = strstr(stopic, SettingsText(SET_MQTTPREFIX1)); if (me == stopic) { mqtt_cmnd_publish += 3; } @@ -389,8 +368,8 @@ void MqttPublish(const char* topic, bool retained) retained = false; // AWS IoT does not support retained, it will disconnect if received #endif - if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1])) { - me = strstr(topic,Settings.mqtt_prefix[0]); + if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2))) { + me = strstr(topic, SettingsText(SET_MQTTPREFIX1)); if (me == topic) { mqtt_cmnd_publish += 3; } @@ -505,11 +484,7 @@ void MqttDisconnected(int state) MqttClient.disconnect(); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), AWS_endpoint, Settings.mqtt_port, state, Mqtt.retry_counter); -#else - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), Settings.mqtt_host, Settings.mqtt_port, state, Mqtt.retry_counter); -#endif + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, state, Mqtt.retry_counter); rules_flag.mqtt_disconnected = 1; } @@ -533,7 +508,7 @@ void MqttConnected(void) GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); - if (strstr_P(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { + if (strstr_P(SettingsText(SET_MQTT_FULLTOPIC), MQTT_TOKEN_TOPIC) != nullptr) { GetGroupTopic_P(stopic, PSTR("#")); // SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing//# or SetOption75 1: cmnd/ MqttSubscribe(stopic); GetFallbackTopic_P(stopic, PSTR("#")); @@ -594,7 +569,7 @@ void MqttReconnect(void) MqttDiscoverServer(); #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY - if (!strlen(Settings.mqtt_host) || !Settings.mqtt_port) { + if (!strlen(SettingsText(SET_MQTT_HOST)) || !Settings.mqtt_port) { Mqtt.allowed = false; } #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) @@ -621,8 +596,12 @@ void MqttReconnect(void) char *mqtt_user = nullptr; char *mqtt_pwd = nullptr; - if (strlen(Settings.mqtt_user) > 0) mqtt_user = Settings.mqtt_user; - if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd; + if (strlen(SettingsText(SET_MQTT_USER))) { + mqtt_user = SettingsText(SET_MQTT_USER); + } + if (strlen(SettingsText(SET_MQTT_PWD))) { + mqtt_pwd = SettingsText(SET_MQTT_PWD); + } GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); Response_P(S_OFFLINE); @@ -645,10 +624,8 @@ void MqttReconnect(void) tlsClient->setClientECCert(AWS_IoT_Client_Certificate, AWS_IoT_Private_Key, 0xFFFF /* all usages, don't care */, 0); - MqttClient.setServer(AWS_endpoint, Settings.mqtt_port); -#else - MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); #endif + MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings.mqtt_port); uint32_t mqtt_connect_time = millis(); #if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) @@ -662,7 +639,7 @@ void MqttReconnect(void) tlsClient->setPubKeyFingerprint(Settings.mqtt_fingerprint[0], Settings.mqtt_fingerprint[1], allow_all_fingerprints); #endif #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT endpoint: %s"), AWS_endpoint); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT endpoint: %s"), SettingsText(SET_MQTT_HOST)); //if (MqttClient.connect(mqtt_client, nullptr, nullptr, nullptr, 0, false, nullptr)) { if (MqttClient.connect(mqtt_client, nullptr, nullptr, stopic, 1, false, mqtt_data, MQTT_CLEAN_SESSION)) { #else @@ -722,7 +699,7 @@ void MqttCheck(void) if (!Mqtt.retry_counter) { #ifdef USE_DISCOVERY #ifdef MQTT_HOST_DISCOVERY - if (!strlen(Settings.mqtt_host) && !Wifi.mdns_begun) { return; } + if (!strlen(SettingsText(SET_MQTT_HOST)) && !Wifi.mdns_begun) { return; } #endif // MQTT_HOST_DISCOVERY #endif // USE_DISCOVERY MqttReconnect(); @@ -763,18 +740,18 @@ void CmndMqttFingerprint(void) #if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT void CmndMqttUser(void) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_user))) { - strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data, sizeof(Settings.mqtt_user)); + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_MQTT_USER, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data); restart_flag = 2; } - ResponseCmndChar(Settings.mqtt_user); + ResponseCmndChar(SettingsText(SET_MQTT_USER)); } void CmndMqttPassword(void) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_pwd))) { - strlcpy(Settings.mqtt_pwd, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data, sizeof(Settings.mqtt_pwd)); - ResponseCmndChar(Settings.mqtt_pwd); + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_MQTT_PWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data); + ResponseCmndChar(SettingsText(SET_MQTT_PWD)); restart_flag = 2; } else { Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); @@ -792,19 +769,11 @@ void CmndMqttlog(void) void CmndMqttHost(void) { -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len <= sizeof(Settings.mqtt_host) + sizeof(Settings.mqtt_user) - 2)) { - setLongMqttHost((SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_MQTT_HOST, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); restart_flag = 2; } - ResponseCmndChar(AWS_endpoint); -#else - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_host))) { - strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data, sizeof(Settings.mqtt_host)); - restart_flag = 2; - } - ResponseCmndChar(Settings.mqtt_host); -#endif + ResponseCmndChar(SettingsText(SET_MQTT_HOST)); } void CmndMqttPort(void) @@ -828,11 +797,11 @@ void CmndMqttRetry(void) void CmndStateText(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.state_text[0]))) { + if (XdrvMailbox.data_len > 0) { for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) { if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_'; } - strlcpy(Settings.state_text[XdrvMailbox.index -1], XdrvMailbox.data, sizeof(Settings.state_text[0])); + SettingsUpdateText(SET_STATE_TXT1 + XdrvMailbox.index -1, XdrvMailbox.data); } ResponseCmndIdxChar(GetStateText(XdrvMailbox.index -1)); } @@ -840,40 +809,41 @@ void CmndStateText(void) void CmndMqttClient(void) { - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_client))) { - strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data, sizeof(Settings.mqtt_client)); + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { + SettingsUpdateText(SET_MQTT_CLIENT, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data); restart_flag = 2; } - ResponseCmndChar(Settings.mqtt_client); + ResponseCmndChar(SettingsText(SET_MQTT_CLIENT)); } void CmndFullTopic(void) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_fulltopic))) { + if (XdrvMailbox.data_len > 0) { MakeValidMqtt(1, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } char stemp1[TOPSZ]; strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_FULLTOPIC : XdrvMailbox.data, sizeof(stemp1)); - if (strcmp(stemp1, Settings.mqtt_fulltopic)) { + if (strcmp(stemp1, SettingsText(SET_MQTT_FULLTOPIC))) { Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic - strlcpy(Settings.mqtt_fulltopic, stemp1, sizeof(Settings.mqtt_fulltopic)); + SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp1); restart_flag = 2; } } - ResponseCmndChar(Settings.mqtt_fulltopic); + ResponseCmndChar(SettingsText(SET_MQTT_FULLTOPIC)); } void CmndPrefix(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_prefix[0]))) { + + if (XdrvMailbox.data_len > 0) { MakeValidMqtt(0, XdrvMailbox.data); - strlcpy(Settings.mqtt_prefix[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?SUB_PREFIX:(2==XdrvMailbox.index)?PUB_PREFIX:PUB_PREFIX2 : XdrvMailbox.data, sizeof(Settings.mqtt_prefix[0])); -// if (Settings.mqtt_prefix[XdrvMailbox.index -1][strlen(Settings.mqtt_prefix[XdrvMailbox.index -1])] == '/') Settings.mqtt_prefix[XdrvMailbox.index -1][strlen(Settings.mqtt_prefix[XdrvMailbox.index -1])] = 0; + SettingsUpdateText(SET_MQTTPREFIX1 + XdrvMailbox.index -1, + (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index) ? SUB_PREFIX : (2==XdrvMailbox.index) ? PUB_PREFIX : PUB_PREFIX2 : XdrvMailbox.data); restart_flag = 2; } - ResponseCmndIdxChar(Settings.mqtt_prefix[XdrvMailbox.index -1]); + ResponseCmndIdxChar(SettingsText(SET_MQTTPREFIX1 + XdrvMailbox.index -1)); } } @@ -899,60 +869,60 @@ void CmndPublish(void) void CmndGroupTopic(void) { - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_grptopic))) { + if (XdrvMailbox.data_len > 0) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } - strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data, sizeof(Settings.mqtt_grptopic)); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); restart_flag = 2; } - ResponseCmndChar(Settings.mqtt_grptopic); + ResponseCmndChar(SettingsText(SET_MQTT_GRP_TOPIC)); } void CmndTopic(void) { - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_topic))) { + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } char stemp1[TOPSZ]; strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_TOPIC : XdrvMailbox.data, sizeof(stemp1)); - if (strcmp(stemp1, Settings.mqtt_topic)) { + if (strcmp(stemp1, SettingsText(SET_MQTT_TOPIC))) { Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic - strlcpy(Settings.mqtt_topic, stemp1, sizeof(Settings.mqtt_topic)); + SettingsUpdateText(SET_MQTT_TOPIC, stemp1); restart_flag = 2; } } - ResponseCmndChar(Settings.mqtt_topic); + ResponseCmndChar(SettingsText(SET_MQTT_TOPIC)); } void CmndButtonTopic(void) { - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.button_topic))) { + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } switch (Shortcut()) { - case SC_CLEAR: strlcpy(Settings.button_topic, "", sizeof(Settings.button_topic)); break; - case SC_DEFAULT: strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); break; - case SC_USER: strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); break; - default: strlcpy(Settings.button_topic, XdrvMailbox.data, sizeof(Settings.button_topic)); + case SC_CLEAR: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, ""); break; + case SC_DEFAULT: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, mqtt_topic); break; + case SC_USER: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); break; + default: SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, XdrvMailbox.data); } } - ResponseCmndChar(Settings.button_topic); + ResponseCmndChar(SettingsText(SET_MQTT_BUTTON_TOPIC)); } void CmndSwitchTopic(void) { - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.switch_topic))) { + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } switch (Shortcut()) { - case SC_CLEAR: strlcpy(Settings.switch_topic, "", sizeof(Settings.switch_topic)); break; - case SC_DEFAULT: strlcpy(Settings.switch_topic, mqtt_topic, sizeof(Settings.switch_topic)); break; - case SC_USER: strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); break; - default: strlcpy(Settings.switch_topic, XdrvMailbox.data, sizeof(Settings.switch_topic)); + case SC_CLEAR: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, ""); break; + case SC_DEFAULT: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, mqtt_topic); break; + case SC_USER: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); break; + default: SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, XdrvMailbox.data); } } - ResponseCmndChar(Settings.switch_topic); + ResponseCmndChar(SettingsText(SET_MQTT_SWITCH_TOPIC)); } void CmndButtonRetain(void) @@ -1220,22 +1190,18 @@ void HandleMqttConfiguration(void) return; } - char str[sizeof(Settings.mqtt_client)]; + char str[33]; WSContentStart_P(S_CONFIGURE_MQTT); WSContentSendStyle(); WSContentSend_P(HTTP_FORM_MQTT1, -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AWS_endpoint, -#else - Settings.mqtt_host, -#endif + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, - Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, Settings.mqtt_client); + Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); WSContentSend_P(HTTP_FORM_MQTT2, - (Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user, - Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, Settings.mqtt_topic, - MQTT_FULLTOPIC, MQTT_FULLTOPIC, Settings.mqtt_fulltopic); + (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), + Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC), + MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); @@ -1253,32 +1219,28 @@ void MqttSaveSettings(void) WebGetArg("mf", tmp, sizeof(tmp)); strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); MakeValidMqtt(1, stemp2); - if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { + if ((strcmp(stemp, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) { Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic } - strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); - strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic)); + SettingsUpdateText(SET_MQTT_TOPIC, stemp); + SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2); WebGetArg("mh", tmp, sizeof(tmp)); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - setLongMqttHost((!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); -#else - strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host)); -#endif + SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); WebGetArg("ml", tmp, sizeof(tmp)); Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); WebGetArg("mc", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client)); + SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - AWS_endpoint, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_topic, Settings.mqtt_fulltopic); + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); #else // USE_MQTT_AWS_IOT WebGetArg("mu", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user)); + SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp); WebGetArg("mp", tmp, sizeof(tmp)); - strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? Settings.mqtt_pwd : tmp, sizeof(Settings.mqtt_pwd)); + SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_topic, Settings.mqtt_fulltopic); + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); #endif } #endif // USE_WEBSERVER diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index ac771f0d7..6e1636518 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -217,7 +217,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); if (rule_param.startsWith(stemp)) { - rule_param = Settings.mems[i]; + rule_param = SettingsText(SET_MEM1 + i); break; } } @@ -447,12 +447,12 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) } for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1); - RulesVarReplace(commands, stemp, Settings.mems[i]); + RulesVarReplace(commands, stemp, SettingsText(SET_MEM1 +i)); } RulesVarReplace(commands, F("%TIME%"), String(MinutesPastMidnight())); RulesVarReplace(commands, F("%UPTIME%"), String(MinutesUptime())); RulesVarReplace(commands, F("%TIMESTAMP%"), GetDateAndTime(DT_LOCAL)); - RulesVarReplace(commands, F("%TOPIC%"), Settings.mqtt_topic); + RulesVarReplace(commands, F("%TOPIC%"), SettingsText(SET_MQTT_TOPIC)); #if defined(USE_TIMERS) && defined(USE_SUNRISE) RulesVarReplace(commands, F("%SUNRISE%"), String(SunMinutes(0))); RulesVarReplace(commands, F("%SUNSET%"), String(SunMinutes(1))); @@ -608,7 +608,7 @@ void RulesEvery50ms(void) for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { if (bitRead(Rules.mems_event, i)) { bitClear(Rules.mems_event, i); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, SettingsText(SET_MEM1 +i)); RulesProcessEvent(json_event); break; } @@ -1002,7 +1002,7 @@ bool findNextVariableValue(char * &pVarname, float &value) } else if (sVarName.startsWith(F("MEM"))) { int index = sVarName.substring(3).toInt(); if (index > 0 && index <= MAX_RULE_MEMS) { - value = CharToFloat(Settings.mems[index -1]); + value = CharToFloat(SettingsText(SET_MEM1 + index -1)); } } else if (sVarName.equals(F("TIME"))) { value = MinutesPastMidnight(); @@ -1810,23 +1810,23 @@ void CmndMemory(void) if (!XdrvMailbox.usridx) { mqtt_data[0] = '\0'; for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - ResponseAppend_P(PSTR("%c\"Mem%d\":\"%s\""), (i) ? ',' : '{', i +1, Settings.mems[i]); + ResponseAppend_P(PSTR("%c\"Mem%d\":\"%s\""), (i) ? ',' : '{', i +1, SettingsText(SET_MEM1 +i)); } ResponseJsonEnd(); } else { if (XdrvMailbox.data_len > 0) { #ifdef USE_EXPRESSION if (XdrvMailbox.data[0] == '=') { // Spaces already been skipped in data - dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, Settings.mems[XdrvMailbox.index -1]); + dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, SettingsText(SET_MEM1 + XdrvMailbox.index -1)); } else { - strlcpy(Settings.mems[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[XdrvMailbox.index -1])); + SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); } #else - strlcpy(Settings.mems[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[XdrvMailbox.index -1])); + SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); #endif // USE_EXPRESSION bitSet(Rules.mems_event, XdrvMailbox.index -1); } - ResponseCmndIdxChar(Settings.mems[XdrvMailbox.index -1]); + ResponseCmndIdxChar(SettingsText(SET_MEM1 + XdrvMailbox.index -1)); } } } diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 5badb88ea..68df13984 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1041,7 +1041,7 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso if (sp) strlcpy(sp,str_value,SCRIPT_MAXSSIZE); return lp+len; } - + } else { if (fp) { if (!strncmp(vn.c_str(),"Epoch",5)) { @@ -1370,7 +1370,7 @@ chknext: goto exit; } if (!strncmp(vname,"gtopic",6)) { - if (sp) strlcpy(sp,Settings.mqtt_grptopic,glob_script_mem.max_ssize); + if (sp) strlcpy(sp,SettingsText(SET_MQTT_GRP_TOPIC),glob_script_mem.max_ssize); goto strexit; } break; @@ -1527,15 +1527,15 @@ chknext: goto exit; } if (!strncmp(vname,"prefix1",7)) { - if (sp) strlcpy(sp,Settings.mqtt_prefix[0],glob_script_mem.max_ssize); + if (sp) strlcpy(sp,SettingsText(SET_MQTTPREFIX1),glob_script_mem.max_ssize); goto strexit; } if (!strncmp(vname,"prefix2",7)) { - if (sp) strlcpy(sp,Settings.mqtt_prefix[1],glob_script_mem.max_ssize); + if (sp) strlcpy(sp,SettingsText(SET_MQTTPREFIX2),glob_script_mem.max_ssize); goto strexit; } if (!strncmp(vname,"prefix3",7)) { - if (sp) strlcpy(sp,Settings.mqtt_prefix[2],glob_script_mem.max_ssize); + if (sp) strlcpy(sp,SettingsText(SET_MQTTPREFIX3),glob_script_mem.max_ssize); goto strexit; } if (!strncmp(vname,"pow(",4)) { @@ -1744,7 +1744,7 @@ chknext: goto strexit; } if (!strncmp(vname,"topic",5)) { - if (sp) strlcpy(sp,Settings.mqtt_topic,glob_script_mem.max_ssize); + if (sp) strlcpy(sp,SettingsText(SET_MQTT_TOPIC),glob_script_mem.max_ssize); goto strexit; } #ifdef USE_DISPLAY diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 22c0e370e..58c266c61 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -46,7 +46,7 @@ const char HASS_DISCOVER_BUTTON_TOGGLE[] PROGMEM = const char HASS_DISCOVER_SWITCH_TOGGLE[] PROGMEM = ",\"value_template\":\"{%%if is_state(entity_id,\\\"on\\\")-%%}OFF{%%-else-%%}ON{%%-endif%%}\""; // A switch must maintain his state until the next update - + const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = ",\"value_template\":\"{{value_json.%s}}\"," // STATE "\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work @@ -86,7 +86,7 @@ const char HASS_DISCOVER_SENSOR[] PROGMEM = "{\"name\":\"%s\"," // dualr2 1 BTN "\"stat_t\":\"%s\"," // cmnd/dualr2/POWER (implies "\"optimistic\":\"false\",") "\"avty_t\":\"%s\"," // tele/dualr2/LWT - "\"frc_upd\":true," // force update for better graph representation + "\"frc_upd\":true," // force update for better graph representation "\"pl_avail\":\"" D_ONLINE "\"," // Online "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline @@ -239,9 +239,9 @@ void HAssAnnounceRelayLight(void) char *availability_topic = stemp3; if (i > MAX_FRIENDLYNAMES) { - snprintf_P(name, sizeof(name), PSTR("%s %d"), Settings.friendlyname[0], i); + snprintf_P(name, sizeof(name), PSTR("%s %d"), SettingsText(SET_FRIENDLYNAME1), i); } else { - snprintf_P(name, sizeof(name), Settings.friendlyname[i -1]); + snprintf_P(name, sizeof(name), SettingsText(SET_FRIENDLYNAME1 +i -1)); } GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1 GetTopic_P(command_topic, CMND, mqtt_topic, value_template); @@ -253,7 +253,7 @@ void HAssAnnounceRelayLight(void) Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); + Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2), availability_topic); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); @@ -324,7 +324,7 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint char *availability_topic = stemp2; char jsoname[8]; - snprintf_P(name, sizeof(name), PSTR("%s %s%d"), Settings.friendlyname[0], key?"Switch":"Button", device+1); + snprintf_P(name, sizeof(name), PSTR("%s %s%d"), SettingsText(SET_FRIENDLYNAME1), key?"Switch":"Button", device+1); snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key?"SWITCH":"BUTTON", device+1); GetPowerDevice(value_template, device+1, sizeof(value_template), key + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1 @@ -339,11 +339,11 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); if (toggle) { - if (!key) { - TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE, PSTR(D_RSLT_STATE), Settings.state_text[toggle?2:1]); + if (!key) { + TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT1 + toggle?2:1)); } else {TryResponseAppend_P(HASS_DISCOVER_SWITCH_TOGGLE);} } - else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), Settings.state_text[toggle?2:1], Settings.state_text[0]); + else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT1 + toggle?2:1), SettingsText(SET_STATE_TXT1)); TryResponseAppend_P(PSTR("}")); } @@ -352,10 +352,10 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint void HAssAnnounceSwitches(void) { - char sw_topic[sizeof(Settings.switch_topic)]; + char sw_topic[TOPSZ]; // Send info about buttons - char *tmp = Settings.switch_topic; + char *tmp = SettingsText(SET_MQTT_SWITCH_TOPIC); Format(sw_topic, tmp, sizeof(sw_topic)); if (!strcmp_P(sw_topic, "0") || strlen(sw_topic) == 0 ) { for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) { @@ -369,7 +369,7 @@ void HAssAnnounceSwitches(void) // Check if MQTT message will be ON/OFF or TOGGLE if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set - !strcmp(mqtt_topic, sw_topic) || !strcmp(Settings.mqtt_grptopic, sw_topic)) + !strcmp(mqtt_topic, sw_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), sw_topic)) { toggle = 0; // MQTT message will be ON/OFF } @@ -381,10 +381,10 @@ void HAssAnnounceSwitches(void) void HAssAnnounceButtons(void) { - char key_topic[sizeof(Settings.button_topic)]; + char key_topic[TOPSZ]; // Send info about buttons - char *tmp = Settings.button_topic; + char *tmp = SettingsText(SET_MQTT_BUTTON_TOPIC); Format(key_topic, tmp, sizeof(key_topic)); if (!strcmp_P(key_topic, "0") || strlen(key_topic) == 0 ) { for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { @@ -401,7 +401,7 @@ void HAssAnnounceButtons(void) // Check if MQTT message will be ON/OFF or TOGGLE if (Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set - !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) + !strcmp(mqtt_topic, key_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) { toggle = 0; // MQTT message will be ON/OFF } @@ -445,7 +445,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); } - snprintf_P(name, sizeof(name), PSTR("%s %s %s"), Settings.friendlyname[0], sensorname, subsensortype); + snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_FRIENDLYNAME1), sensorname, subsensortype); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); Shorten(&state_topic, prefix); @@ -458,7 +458,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) TryResponseAppend_P(HASS_DISCOVER_SENSOR_TEMP, TempUnit(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { TryResponseAppend_P(HASS_DISCOVER_SENSOR_HUM, sensorname); - } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE)) + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE)) || !strcmp_P(subsensortype, PSTR(D_JSON_PRESSUREATSEALEVEL))){ TryResponseAppend_P(HASS_DISCOVER_SENSOR_PRESS, PressureUnit().c_str(), sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) @@ -548,7 +548,7 @@ void HAssAnnounceStatusSensor(void) char *state_topic = stemp1; char *availability_topic = stemp2; - snprintf_P(name, sizeof(name), PSTR("%s status"), Settings.friendlyname[0]); + snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_FRIENDLYNAME1)); GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); @@ -558,7 +558,7 @@ void HAssAnnounceStatusSensor(void) Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(), - Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); + SettingsText(SET_FRIENDLYNAME1), ModuleName().c_str(), my_version, my_image); TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); TryResponseAppend_P(PSTR("}")); } @@ -588,8 +588,8 @@ void HAssDiscovery(void) Settings.flag.decimal_text = 1; // SetOption17 - Switch between decimal or hexadecimal output - Respond with decimal color values Settings.flag3.hass_tele_on_power = 1; // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT - send tele/STATE message as stat/RESULT // Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 - if (strcmp_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"))) { - strncpy_P(Settings.mqtt_fulltopic, PSTR("%topic%/%prefix%/"), sizeof(Settings.mqtt_fulltopic)); + if (strcmp_P(SettingsText(SET_MQTT_FULLTOPIC), PSTR("%topic%/%prefix%/"))) { + SettingsUpdateText(SET_MQTT_FULLTOPIC, "%topic%/%prefix%/"); restart_flag = 2; return; // As full topic has changed do restart first before sending discovery data } diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index 42bb9858b..b34b8ed27 100644 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -1008,7 +1008,7 @@ void DisplayLogBufferInit(void) snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname); DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), Settings.sta_ssid[Settings.sta_active]); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active)); DisplayLogBufferAdd(buffer); snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str()); DisplayLogBufferAdd(buffer); @@ -1196,7 +1196,7 @@ void DisplayMqttSubscribe(void) char ntopic[TOPSZ]; ntopic[0] = '\0'; - strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic)); + strlcpy(stopic, SettingsText(SET_MQTT_FULLTOPIC), sizeof(stopic)); char *tp = strtok(stopic, "/"); while (tp != nullptr) { if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { @@ -1205,7 +1205,7 @@ void DisplayMqttSubscribe(void) strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); // Add single-level wildcards tp = strtok(nullptr, "/"); } - strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic) - strlen(ntopic) -1); // Subscribe to tele messages + strncat(ntopic, SettingsText(SET_MQTTPREFIX3), sizeof(ntopic) - strlen(ntopic) -1); // Subscribe to tele messages strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); // Add multi-level wildcard MqttSubscribe(ntopic); disp_subscribed = true; @@ -1219,7 +1219,7 @@ bool DisplayMqttData(void) if (disp_subscribed) { char stopic[TOPSZ]; - snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), Settings.mqtt_prefix[2]); // tele/ + snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), SettingsText(SET_MQTTPREFIX3)); // tele/ char *tp = strstr(XdrvMailbox.topic, stopic); if (tp) { // tele/tasmota/SENSOR if (Settings.display_mode &0x04) { diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 254fa4d99..973499a1f 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -365,17 +365,18 @@ void HueLightStatus1(uint8_t device, String *response) // Any device whose friendly name start with "$" is considered hidden bool HueActive(uint8_t device) { if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } - return '$' != Settings.friendlyname[device-1][0]; +// return '$' != Settings.friendlyname[device-1][0]; + return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1]; } void HueLightStatus2(uint8_t device, String *response) { *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); if (device <= MAX_FRIENDLYNAMES) { - response->replace("{j1", Settings.friendlyname[device-1]); + response->replace("{j1", SettingsText(SET_FRIENDLYNAME1 +device -1)); } else { char fname[33]; - strcpy(fname, Settings.friendlyname[MAX_FRIENDLYNAMES-1]); + strcpy(fname, SettingsText(SET_FRIENDLYNAME1 + MAX_FRIENDLYNAMES -1)); uint32_t fname_len = strlen(fname); if (fname_len > 30) { fname_len = 30; } fname[fname_len++] = '-'; diff --git a/tasmota/xdrv_21_wemo.ino b/tasmota/xdrv_21_wemo.ino index 4a50560e2..13e867ae6 100644 --- a/tasmota/xdrv_21_wemo.ino +++ b/tasmota/xdrv_21_wemo.ino @@ -241,7 +241,7 @@ void HandleUpnpSetupWemo(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_SETUP)); String setup_xml = FPSTR(WEMO_SETUP_XML); - setup_xml.replace("{x1", Settings.friendlyname[0]); + setup_xml.replace("{x1", SettingsText(SET_FRIENDLYNAME1)); setup_xml.replace("{x2", WemoUuid()); setup_xml.replace("{x3", WemoSerialnumber()); WSSend(200, CT_XML, setup_xml); diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino index b347035e1..22bc5e162 100644 --- a/tasmota/xdrv_99_debug.ino +++ b/tasmota/xdrv_99_debug.ino @@ -25,8 +25,6 @@ #endif // USE_DEBUG_DRIVER #endif // DEBUG_THEO -//#define USE_DEBUG_SETTING_NAMES - #ifdef USE_DEBUG_DRIVER /*********************************************************************************************\ * Virtual debugging support - Part1 @@ -64,9 +62,6 @@ const char kDebugCommands[] PROGMEM = "|" // No prefix D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" -#ifdef USE_DEBUG_SETTING_NAMES - D_CMND_CFGSHOW "|" -#endif #ifdef USE_WEBSERVER D_CMND_CFGXOR "|" #endif @@ -82,9 +77,6 @@ const char kDebugCommands[] PROGMEM = "|" // No prefix void (* const DebugCommand[])(void) PROGMEM = { &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, -#ifdef USE_DEBUG_SETTING_NAMES - &CmndCfgShow, -#endif #ifdef USE_WEBSERVER &CmndCfgXor, #endif @@ -391,36 +383,6 @@ void DebugCfgPoke(char* parms) AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); } -#ifdef USE_DEBUG_SETTING_NAMES -void DebugCfgShow(uint8_t more) -{ - uint8_t *SetAddr; - SetAddr = (uint8_t *)&Settings; - - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Hostname (%d) [%s]"), (uint8_t *)&Settings.hostname - SetAddr, sizeof(Settings.hostname)-1, Settings.hostname); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: SSids (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_ssid - SetAddr, sizeof(Settings.sta_ssid[0])-1, Settings.sta_ssid[0], Settings.sta_ssid[1]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Friendlynames (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.friendlyname - SetAddr, sizeof(Settings.friendlyname[0])-1, Settings.friendlyname[0], Settings.friendlyname[1], Settings.friendlyname[2], Settings.friendlyname[3]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: OTA Url (%d) [%s]"), (uint8_t *)&Settings.ota_url - SetAddr, sizeof(Settings.ota_url)-1, Settings.ota_url); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: StateText (%d) [%s], [%s], [%s], [%s]"), (uint8_t *)&Settings.state_text - SetAddr, sizeof(Settings.state_text[0])-1, Settings.state_text[0], Settings.state_text[1], Settings.state_text[2], Settings.state_text[3]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Syslog Host (%d) [%s]"), (uint8_t *)&Settings.syslog_host - SetAddr, sizeof(Settings.syslog_host)-1, Settings.syslog_host); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: NTP Servers (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.ntp_server - SetAddr, sizeof(Settings.ntp_server[0])-1, Settings.ntp_server[0], Settings.ntp_server[1], Settings.ntp_server[2]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Host (%d) [%s]"), (uint8_t *)&Settings.mqtt_host - SetAddr, sizeof(Settings.mqtt_host)-1, Settings.mqtt_host); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Client (%d) [%s]"), (uint8_t *)&Settings.mqtt_client - SetAddr, sizeof(Settings.mqtt_client)-1, Settings.mqtt_client); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT User (%d) [%s]"), (uint8_t *)&Settings.mqtt_user - SetAddr, sizeof(Settings.mqtt_user)-1, Settings.mqtt_user); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT FullTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_fulltopic - SetAddr, sizeof(Settings.mqtt_fulltopic)-1, Settings.mqtt_fulltopic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Topic (%d) [%s]"), (uint8_t *)&Settings.mqtt_topic - SetAddr, sizeof(Settings.mqtt_topic)-1, Settings.mqtt_topic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT GroupTopic (%d) [%s]"), (uint8_t *)&Settings.mqtt_grptopic - SetAddr, sizeof(Settings.mqtt_grptopic)-1, Settings.mqtt_grptopic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT ButtonTopic (%d) [%s]"), (uint8_t *)&Settings.button_topic - SetAddr, sizeof(Settings.button_topic)-1, Settings.button_topic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT SwitchTopic (%d) [%s]"), (uint8_t *)&Settings.switch_topic - SetAddr, sizeof(Settings.switch_topic)-1, Settings.switch_topic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Prefixes (%d) [%s], [%s], [%s]"), (uint8_t *)&Settings.mqtt_prefix - SetAddr, sizeof(Settings.mqtt_prefix[0])-1, Settings.mqtt_prefix[0], Settings.mqtt_prefix[1], Settings.mqtt_prefix[2]); - if (17 == more) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: AP Passwords (%d) [%s], [%s]"), (uint8_t *)&Settings.sta_pwd - SetAddr, sizeof(Settings.sta_pwd[0])-1, Settings.sta_pwd[0], Settings.sta_pwd[1]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: MQTT Password (%d) [%s]"), (uint8_t *)&Settings.mqtt_pwd - SetAddr, sizeof(Settings.mqtt_pwd)-1, Settings.mqtt_pwd); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: Web Password (%d) [%s]"), (uint8_t *)&Settings.web_password - SetAddr, sizeof(Settings.web_password)-1, Settings.web_password); - } -} -#endif // USE_DEBUG_SETTING_NAMES - void SetFlashMode(uint8_t mode) { uint8_t *_buffer; @@ -474,14 +436,6 @@ void CmndCfgPoke(void) ResponseCmndDone(); } -#ifdef USE_DEBUG_SETTING_NAMES -void CmndCfgShow(void) -{ - DebugCfgShow(XdrvMailbox.payload); - ResponseCmndDone(); -} -#endif // USE_DEBUG_SETTING_NAMES - #ifdef USE_WEBSERVER void CmndCfgXor(void) { From e47c8710fe428b6077b72b32781ac1f5f3079f4a Mon Sep 17 00:00:00 2001 From: bjeram Date: Mon, 16 Dec 2019 16:55:52 +0100 Subject: [PATCH 073/559] setting pinMode for the pin used by RFRecv to INPUT --- tasmota/xdrv_17_rcswitch.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_17_rcswitch.ino b/tasmota/xdrv_17_rcswitch.ino index dfe5dc66a..156535876 100644 --- a/tasmota/xdrv_17_rcswitch.ino +++ b/tasmota/xdrv_17_rcswitch.ino @@ -85,6 +85,7 @@ void RfInit(void) mySwitch.enableTransmit(pin[GPIO_RFSEND]); } if (pin[GPIO_RFRECV] < 99) { + pinMode( pin[GPIO_RFRECV], INPUT); mySwitch.enableReceive(pin[GPIO_RFRECV]); } } From c1bb875abd7fd89e44d6ab21bf9137401fad02d8 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Mon, 16 Dec 2019 14:37:18 -0300 Subject: [PATCH 074/559] Fix typo --- tasmota/xdrv_20_hue.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 973499a1f..1d13ee263 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -366,7 +366,7 @@ void HueLightStatus1(uint8_t device, String *response) bool HueActive(uint8_t device) { if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } // return '$' != Settings.friendlyname[device-1][0]; - return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1]; + return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1); } void HueLightStatus2(uint8_t device, String *response) From 98579fba0f0662cb7a8277740bfaa24cc7a9f89f Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 16 Dec 2019 21:23:25 -0300 Subject: [PATCH 075/559] KNX: Fix compilation issue when using KNX on Tasmota-IR firmware type --- tasmota/xdrv_11_knx.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/xdrv_11_knx.ino b/tasmota/xdrv_11_knx.ino index c848bddfe..b52c37e4d 100644 --- a/tasmota/xdrv_11_knx.ino +++ b/tasmota/xdrv_11_knx.ino @@ -499,6 +499,7 @@ void KNX_INIT(void) if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } +#if defined(USE_ENERGY_SENSOR) // Any device with a Power Monitoring if ( energy_flg != ENERGY_NONE ) { device_param[KNX_ENERGY_POWER-1].show = true; @@ -509,6 +510,7 @@ void KNX_INIT(void) device_param[KNX_ENERGY_CURRENT-1].show = true; device_param[KNX_ENERGY_POWERFACTOR-1].show = true; } +#endif #ifdef USE_RULES device_param[KNX_SLOT1-1].show = true; From 6ea1cff2674d8f6ce6f7f56802b37e4c615a7574 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 16 Dec 2019 22:13:24 -0300 Subject: [PATCH 076/559] Add GPS Support --- tasmota/tasmota_template.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 5556629f9..793c93626 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -214,6 +214,8 @@ enum UserSelectablePins { GPIO_TASMOTASLAVE_RST_INV, // Slave Reset Inverted GPIO_HPMA_RX, // Honeywell HPMA115S0 Serial interface GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface + GPIO_GPS_RX, // GPS serial interface + GPIO_GPS_TX, // GPS serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -293,7 +295,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|" - D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|" + D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|" D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX ; const char kSensorNamesFixed[] PROGMEM = @@ -756,6 +758,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_DEEPSLEEP GPIO_DEEPSLEEP #endif +#ifdef USE_GPS + GPIO_GPS_RX, // GPS serial interface + GPIO_GPS_TX // GPS serial interface +#endif + }; const uint8_t kModuleNiceList[] PROGMEM = { From 0dd20a4c2b16b1360d3da241dc7b755510d7cc1d Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 16 Dec 2019 22:50:19 -0300 Subject: [PATCH 077/559] Add GPS Support --- tasmota/my_user_config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 5ff6bb6a2..7f1954690 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -470,6 +470,8 @@ // #define USE_PN532_DATA_RAW // Allow DATA block to be used by non-alpha-numberic data (+ 80 bytes code, 48 bytes ram) //#define USE_RDM6300 // Add support for RDM6300 125kHz RFID Reader (+0k8) //#define USE_IBEACON // Add support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +//#define USE_GPS // Add support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) +// #define USE_FLOG // Add support for GPS logging in OTA's Flash (Experimental) (+ 2.9kb flash, +8 bytes RAM) // -- Power monitoring sensors -------------------- #define USE_ENERGY_MARGIN_DETECTION // Add support for Energy Margin detection (+1k6 code) From f065ccaf0824ead2d600e4738c545d99be7492df Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 16 Dec 2019 23:01:07 -0300 Subject: [PATCH 078/559] Add GPS Support --- tasmota/support_flash_log.ino | 432 +++++++++++++++++ tasmota/xsns_58_GPS.ino | 858 ++++++++++++++++++++++++++++++++++ 2 files changed, 1290 insertions(+) create mode 100644 tasmota/support_flash_log.ino create mode 100644 tasmota/xsns_58_GPS.ino diff --git a/tasmota/support_flash_log.ino b/tasmota/support_flash_log.ino new file mode 100644 index 000000000..8d02ec2e8 --- /dev/null +++ b/tasmota/support_flash_log.ino @@ -0,0 +1,432 @@ +/* + support_flash_log.ino - log to flash support for Sonoff-Tasmota + + Copyright (C) 2019 Theo Arends & Christian Baars + + 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 . + + -------------------------------------------------------------------------------------------- + Version Date Action Description + -------------------------------------------------------------------------------------------- + + + --- + 1.0.0.0 20190923 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + base - code base from arendst and - written from scratch + +*/ + +/********************************************************************************************\ +| * Generic helper class to log arbitrary data to the OTA-partition +| * Working principle: Add preferrable small chunks of data to the sector buffer, which will +| * be written to FLASH when full automatically. The next sector will be +| * erased and is the anchor point for downloading and state configuration +| * after reboot. +\*********************************************************************************************/ + +#ifdef USE_FLOG + +class FLOG + +#define MAGIC_WORD_FL 0x464c //F, L + +{ + +struct header_t{ + uint16_t magic_word; // FL + uint16_t padding; // leave something for the future + uint32_t physical_start_sector:10; //first used sector of the current FLOG + uint32_t number:10; // number of this sector, starting with 0 for the first sector + uint32_t buf_pointer:12; //internal pointer to the next free position in the buffer = first empty byte when reading + }; // should be 4-byte-aligned + +private: +void _readSector(uint8_t one_sector); +void _eraseSector(uint8_t one_sector); +void _writeSector(uint8_t one_sector); +void _clearBuffer(void); +void _searchSaves(void); +void _findFirstErasedSector(void); +void _showBuffer(void); +void _initBuffer(void); +void _saveBufferToSector(void); +header_t _saved_header; + +public: + uint32_t size; // size of OTA-partition + uint32_t start; // start position of OTA-partition in bytes + uint32_t end; // end position of OTA-partition in bytes + uint16_t num_sectors; // calculated number of sectors with a size of 4096 bytes + + uint16_t first_erased_sector; // this will be our new start + uint16_t current_sector; // always point to next sector, where data from the buffer will be written to + + uint16_t bytes_left; // byte per buffer (of sector size 4096 bytes - 8 byte header size) + uint16_t sectors_left; // number of saved sectors for download + + uint8_t mode = 0; // 0 - write once on all sectors, then stop, 1 - write infinitely through the sectors + bool found_saved_data = false; // possible saved data has been found + bool ready = false; // the FLOG is initialized + bool running_download = false; // a download operation is running + bool recording = false; // ready for recording + + union sector_t{ + uint32_t dword_buffer[FLASH_SECTOR_SIZE/4]; + uint8_t byte_buffer[FLASH_SECTOR_SIZE]; + header_t header; // should be 4-byte-aligned + } sector; // the global buffer of 4096 bytes, used for reading and writing + + void init(void); + void addToBuffer(uint8_t src[], uint32_t size); + void startRecording(bool append); + void stopRecording(void); + + typedef void (*CallbackNoArgs) (); // simple typedef for a callback + typedef void (*CallbackWithArgs) (uint8_t *_record); // typedef for a callback with one argument + + void startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter); +}; + +extern "C" uint32_t _SPIFFS_start; // we make shure later, that only one of the two is really used ... +extern "C" uint32_t _FS_start; // ... depending on core-sdk-version + +/** + * @brief Will examine the start and end of the OTA-partition. Then the sector size will be computed, saved data should be found and the initial state will be configured. + */ +void FLOG::init(void) +{ +DEBUG_SENSOR_LOG(PSTR("FLOG: init ...")); +size = ESP.getSketchSize(); +// round one sector up +start = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) +end = (uint32_t)&_SPIFFS_start - 0x40200000; +#else // Core > 2.5.2 and STAGE +end = (uint32_t)&_FS_start - 0x40200000; +#endif +num_sectors = (end - start)/FLASH_SECTOR_SIZE; +DEBUG_SENSOR_LOG(PSTR("FLOG: size: 0x%lx, start: 0x%lx, end: 0x%lx, num_sectors(dec): %lu"), size, start, end, num_sectors ); +_findFirstErasedSector(); +if(first_erased_sector == 0xffff){ + _eraseSector(0); + first_erased_sector = 0; // start with sector 0, could be first run or after crash +} +_searchSaves(); +_initBuffer(); +ready = true; +} + +/********************************************************************************************\ +| * +| * private helper functions +| * +\*********************************************************************************************/ + +/** + * @brief Read a sector into the global buffer + * + * @param one_sector as an uint8_t + */ +void FLOG::_readSector(uint8_t one_sector){ + DEBUG_SENSOR_LOG(PSTR("FLOG: read sector number: %u" ), one_sector); + ESP.flashRead(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); +} +/** + * @brief Erase the given sector og the OTA-partition + * + * @param one_sector as an uint8_t + */ +void FLOG::_eraseSector(uint8_t one_sector){ // Erase sector of FLOG/OTA + DEBUG_SENSOR_LOG(PSTR("FLOG: erasing sector number: %u" ), one_sector); + ESP.flashEraseSector((start/FLASH_SECTOR_SIZE)+one_sector); +} +/** + * @brief Write the global buffer to the given sector + * + * @param one_sector as an uint8_t + */ +void FLOG::_writeSector(uint8_t one_sector){ // Write sector of FLOG/OTA + DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to sector number: %u" ), one_sector); + ESP.flashWrite(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); +} +/** + * @brief Clear the global buffer, but leave the header intact + * + */ +void FLOG::_clearBuffer(){ //not the header + for (uint32_t i = sizeof(sector.header)/4; i<(sizeof(sector.dword_buffer)/4); i++){ + sector.dword_buffer[i] = 0; + } + sector.header.buf_pointer = sizeof(sector.header); + // _showBuffer(); +} +/** + * @brief Write global buffer to FLASH and set the current sector to the next valid position, maybe to 0 + * + */ +void FLOG::_saveBufferToSector(){ // save buffer to already erased(!) sector, erase next sector, clear buffer, increment number + DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to current sector: %u" ),current_sector); + _writeSector(current_sector); + if(current_sector == num_sectors){ // 1 MB means ~110 sectors in OTA-partition, if we reach this, start a again + current_sector = 0; + } + else{ + current_sector++; + } + _eraseSector(current_sector); // we always erase the next sector, to find out were we are after restart + _clearBuffer(); + sector.header.number++; + DEBUG_SENSOR_LOG(PSTR("FLOG: new sector header number: %u" ),sector.header.number); +} + +/** + * @brief Typically after restart find the first erased sector as a starting point for further operations + * + */ +void FLOG::_findFirstErasedSector(){ + for (uint32_t i = 0; i3){ + break; + } + } +} + +/** + * @brief pass a data entry/record as uint8_t array with its size + * + * @param src uint8_t array + * @param size uint32_t size of the array + */ +void FLOG::addToBuffer(uint8_t src[], uint32_t size){ + if(mode == 0){ + if(sector.header.number == num_sectors && !ready){ + return; // we ignore additional calls and are done, TODO: maybe use meaningful return values + } + } + if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ + // DEBUG_SENSOR_LOG(PSTR("FLOG: enough space left in buffer: %u"), FLASH_SECTOR_SIZE - sector.header.buf_pointer - sizeof(sector.header)); + // DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u, size of added: %u"), sector.header.buf_pointer, size); + + memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); + sector.header.buf_pointer+=size; // this is the next free spot + // DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); + } + else{ + DEBUG_SENSOR_LOG(PSTR("FLOG: save buffer to flash sector: %u"), current_sector); + DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); + _saveBufferToSector(); + sectors_left++; + // but now save the data to the fresh buffer + if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ + memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); + sector.header.buf_pointer+=size; // this is the next free spot + } + } +} + +/** + * @brief shows that it is ready to accept recording + * + * @param append - if true append to current log, else start a new log + */ +void FLOG::startRecording(bool append){ + if(recording){ + DEBUG_SENSOR_LOG(PSTR("FLOG: already recording")); + return; + } + recording = true; + DEBUG_SENSOR_LOG(PSTR("FLOG: start recording")); + _initBuffer(); + if(!found_saved_data) { + append = false; // nothing to append to, we silently start a new log + } + if(append){ + sector.header.number = _saved_header.number+1; // continue with the next number + sector.header.physical_start_sector = _saved_header.physical_start_sector; // keep the old start sector + } + else{ //new log, old data is lost + sector.header.physical_start_sector = (uint16_t)first_erased_sector; + found_saved_data = false; + sectors_left = 0; + } + } + +/** + * @brief stop recording including saving current buffer to FLASH + * + */ +void FLOG::stopRecording(void){ + _saveBufferToSector(); + _findFirstErasedSector(); + _searchSaves(); + _initBuffer(); + recording = false; + found_saved_data = true; + } + +/** + * @brief Will start a downloads, needs the correct implementation of 3 callback functions + * + * @param size: size of the data entry/record in bytes, i.e. sizeof(myStruct) + * @param sendHeader: should implement at least something like: + * @example WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); // This is very likely unknown!! + * WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=myfile.txt")); + * @param sendRecord: will receive the memory address as "uint8_t* addr" and should consume the current entry/record + * @example myStruct_t *entry = (myStruct_t*)addr; + * Then make useful Strings and send it, i.e.: WebServer->sendContent_P(myString); + * @param sendFooter: finish the download, should implement at least: + * @example WebServer->sendContent(""); + */ + void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ + + _readSector(sector.header.physical_start_sector); + uint32_t next_sector = sector.header.physical_start_sector; + bytes_left = sector.header.buf_pointer - sizeof(sector.header); + DEBUG_SENSOR_LOG(PSTR("FLOG: create file for download, will process %u bytes"), bytes_left); + running_download = true; + // Callback 1: Create the header incl. file name, content length (probably unknown!!) and additional header stuff + sendHeader(); + + while(sectors_left){ + DEBUG_SENSOR_LOG(PSTR("FLOG: next sector: %u"), next_sector); + //initially we have the first sector already loaded, so we do it at the bottom + uint32_t k = sizeof(sector.header); + while(bytes_left){ + // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.byte_buffer[k],Flog->sector.byte_buffer[k+1]); + uint8_t *_record_start = (uint8_t*)§or.byte_buffer[k]; // this is basically the start address of the current record/entry of the Log + // Callback 2: send the pointer for consuming the next record/entry and doing something useful to create a file + sendRecord(_record_start); + if(k%128 == 0){ // give control to the system every x iteration, TODO: This will fail, when record/entry-size is not 8 + // DEBUG_SENSOR_LOG(PSTR("FLOG: now loop(), %u bytes left"), Flog->bytes_left); + OsWatchLoop(); + delay(sleep); + } + k+=size; + if(bytes_left>7){ + bytes_left-=size; + } + else{ + bytes_left = 0; + DEBUG_SENSOR_LOG(PSTR("FLOG: Flog->bytes_left not dividable by 8 ??????")); + } + } + next_sector++; + if(next_sector>num_sectors){ + next_sector = 0; + } + sectors_left--; + _readSector(next_sector); + bytes_left = sector.header.buf_pointer - sizeof(sector.header); + OsWatchLoop(); + delay(sleep); + } + running_download = false; + // Callback 3: create a footer or simply finish the download with an empty payload + sendFooter(); + // refresh settings for another download + _searchSaves(); + _initBuffer(); + } + + #endif // USE_FLOG \ No newline at end of file diff --git a/tasmota/xsns_58_GPS.ino b/tasmota/xsns_58_GPS.ino new file mode 100644 index 000000000..f2808f8fd --- /dev/null +++ b/tasmota/xsns_58_GPS.ino @@ -0,0 +1,858 @@ +/* + xsns_92_GPS_UBX.ino - GPS UBLOX support for Sonoff-Tasmota + + Copyright (C) 2019 Theo Arends, Christian Baars and Adrian Scillato + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + 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 . + + -------------------------------------------------------------------------------------------- + Version Date Action Description + -------------------------------------------------------------------------------------------- + + 0.9.1.0 20191216 integrate - Added pin specifications from Tasmota WEB UI + --- + 0.9.0.0 20190817 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota + forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota + base - code base from arendst and - https://www.youtube.com/watch?v=TwhCX0c8Xe0 + +## GPS-driver for the Ublox-series 6-8 +Driver is tested on a NEO-6m and a Beitian-220. Series 7 should work too. This adds only about 6kb to the program size, because the efficient UBX-protocol is used. These modules are quite cheap, starting at about 3.50€ for the NEO-6m. + +## Features: +- get position and time data +- sets system time automatically and Settings.latitude and Settings.longitude via command +- can log postion data with timestamp to flash with a small memory footprint of only 12 Bytes per record +- constructs a GPX-file for download of this data +- Web-UI +- simplified NTP-server +- command interface + +## Usage: +The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To get more debug information compile it with option "DEBUG_TASMOTA_SENSOR". + + +## Commands: + ++ sensor92 0 + write to all available sectors, then restart and overwrite the older ones + ++ sensor92 1 + write to all available sectors, then restart and overwrite the older ones + ++ sensor92 2 + filter out horizontal drift noise + ++ sensor92 3 + turn off noise filter + ++ sensor92 4 + start recording, new data will be appended + ++ sensor92 5 + start new recording, old data will lost + ++ sensor92 6 + stop recording, download link will be visible in Web-UI + ++ sensor92 7 + send mqtt on new postion + TELE -> consider to set TELE to a very high value + ++ sensor92 8 + only TELE message + ++ sensor92 9 + start NTP-server + ++ sensor92 10 + deactivate NTP-server + ++ sensor92 11 + force update of Tasmota-system-UTC with every new GPS-time-message + ++ sensor92 12 + do not update of Tasmota-system-UTC with every new GPS-time-message + ++ sensor92 13 + set latitude and longitude in settings + + + +## Rules examples for SSD1306 32x128 + + +rule1 on tele-GPS#lat do DisplayText [s1p21c1l01f1]LAT: %value% endon on tele-GPS#lon do DisplayText [s1p21c1l2]LON: %value% endon on switch1#state==3 do sensor92 4 endon on switch1#state==2 do sensor92 6 endon + +rule2 on tele-GPS#int>9 do DisplayText [f0c9l4]I%value% endon on tele-GPS#int<10 do DisplayText [f0c9l4]I0%value% endon on tele-GPS#fil==1 do DisplayText [f0c18l4]F endon on tele-GPS#fil==0 do DisplayText [f0c18l4]N endon + +rule3 on tele-FLOG#sec do DisplayText [f0c1l4]SAV:%value% endon on tele-FLOG#rec==1 do DisplayText [f0c1l4]REC: endon on tele-FLOG#mode do DisplayText [f0c14l4]M%value% endon + +*/ + +#ifdef USE_GPS + +#include "NTPServer.h" +#include "NTPPacket.h" + + +/*********************************************************************************************\ + * constants +\*********************************************************************************************/ + +#define D_CMND_UBX "UBX" + +const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; + +const char kUBXTypes[] PROGMEM = "UBX"; + +#define UBX_LAT_LON_THRESHOLD 1000 // filter out some noise of local drift + + +/********************************************************************************************\ +| *globals +\*********************************************************************************************/ + +const char UBLOX_INIT[] PROGMEM = { + // Disable NMEA + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, // GxGGA off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, // GxGLL off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, // GxGSA off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, // GxGSV off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, // GxRMC off + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, // GxVTG off + + // Disable UBX + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, //NAV-PVT off + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, //NAV-POSLLH off + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, //NAV-STATUS off + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, //NAV-TIMEUTC off + + // Enable UBX + // 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x01,0x00,0x00,0x00,0x00,0x18,0xE1, //NAV-PVT on + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, //NAV-POSLLH on + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, //NAV-STATUS on + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, //NAV-TIMEUTC on + + // Rate - we will not reset it for the moment after restart + // 0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz) + // 0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz) + // 0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39 //(1Hz) + // 0xB5,0x62,0x06,0x08,0x06,0x00,0xD0,0x07,0x01,0x00,0x01,0x00,0xED,0xBD //(0.5Hz) +}; + +char UBX_name[4]; + +struct UBX_t{ + const char UBX_HEADER[2] = { 0xB5, 0x62 }; // TODO: Check if we really save space here inside the struct + const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; + const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; + const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; + + struct entry_t{ + int32_t lat; //raw sensor value + int32_t lon; //raw sensor value + uint32_t time; //local time from system (maybe provided by the sensor) + }; + + union { + entry_t values; + uint8_t bytes[sizeof(entry_t)]; + } rec_buffer; + + struct POLL_MSG { + uint8_t cls; + uint8_t id; + uint16_t zero; + }; + + struct NAV_POSLLH { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + int32_t lon; + int32_t lat; + int32_t height; + int32_t hMSL; + uint32_t hAcc; + uint32_t vAcc; + }; + + struct NAV_STATUS { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint8_t gpsFix; + uint8_t flags; //bit 0 - gpsfix valid + uint8_t fixStat; + uint8_t flags2; + uint32_t ttff; + uint32_t msss; + }; + + struct NAV_TIME_UTC { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint32_t tAcc; + int32_t nano; // Nanoseconds of second, range -1e9 .. 1e9 (UTC) + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + struct { + uint8_t UTC:1; + uint8_t WKN:1; // week number + uint8_t TOW:1; // time of week + uint8_t padding:5; + } valid; + }; + + struct CFG_RATE { + uint8_t cls; //0x06 + uint8_t id; //0x08 + uint16_t len; // 6 bytes + uint16_t measRate; // in every ms -> 1 Hz = 1000 ms; 10 Hz = 100 ms -> x = 1000 ms / Hz + uint16_t navRate; // x measurements for 1 navigation event + uint16_t timeRef; // align to time system: 0= UTC, 1 = GPS, 2 = GLONASS, ... + char CK[2]; // checksum + }; + + struct { + uint32_t last_iTOW; + int32_t last_lat; + int32_t last_lon; + int32_t last_height; + uint32_t last_hAcc; + uint32_t last_vAcc; + uint8_t gpsFix; + uint8_t non_empty_loops; // in case of an unintended reset of the GPS, the serial interface will get flooded with NMEA + uint16_t log_interval; // in tenth of seconds + } state; + + struct { + uint32_t filter_noise:1; + uint32_t send_when_new:1; // no teleinterval + uint32_t send_UI_only:1; + uint32_t runningNTP:1; + uint32_t forceUTCupdate:1; + // TODO: more to come + } mode; + + union { + NAV_POSLLH navPosllh; + NAV_STATUS navStatus; + NAV_TIME_UTC navTime; + POLL_MSG pollMsg; + CFG_RATE cfgRate; + } Message; + +} UBX; + +enum UBXMsgType { + MT_NONE, + MT_NAV_POSLLH, + MT_NAV_STATUS, + MT_NAV_TIME, + MT_POLL +}; + +#ifdef USE_FLOG +FLOG *Flog = nullptr; +#endif //USE_FLOG +TasmotaSerial *UBXSerial; + +NtpServer timeServer(PortUdp); + +/*********************************************************************************************\ + * helper function +\*********************************************************************************************/ +void UBXcalcChecksum(char* CK, size_t msgSize) { + memset(CK, 0, 2); + for (int i = 0; i < msgSize; i++) { + CK[0] += ((char*)(&UBX.Message))[i]; + CK[1] += CK[0]; + } +} + +boolean UBXcompareMsgHeader(const char* msgHeader) { + char* ptr = (char*)(&UBX.Message); + return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; +} + +void UBXinitCFG(void){ + for(uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { + UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); + } + DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); + +/* + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), + Settings.knx_GA_registered, + device_param_ga[GAop-1], + GA_FNUM, GA_AREA, GA_FDEF ); +*/ + + + + +} + +void UBXTriggerTele(void){ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +#ifdef USE_RULES + RulesTeleperiod(); // Allow rule based HA messages +#endif // USE_RULES + } +} + +/********************************************************************************************/ + + +void UBXDetect(void) +{ + if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { + UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, 96); // 64 byte buffer is NOT enough + if (UBXSerial->begin(9600)) { + DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); + if (UBXSerial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); + } + } + } + + UBXinitCFG(); // turn of NMEA, only use "our" UBX-messages +#ifdef USE_FLOG + if(!Flog){ + Flog = new FLOG; // init Flash Log + Flog->init(); + } +#endif // USE_FLOG + + UBX.state.log_interval = 10; // 1 second + UBX.mode.send_UI_only = true; // send UI data ... + UBXTriggerTele(); // ... once at after start +} + +uint32_t UBXprocessGPS() { + static uint32_t fpos = 0; + static char checksum[2]; + static uint8_t currentMsgType = MT_NONE; + static size_t payloadSize = sizeof(UBX.Message); + + // DEBUG_SENSOR_LOG(PSTR("UBX: check for serial data")); + uint32_t data_bytes = 0; + while ( UBXSerial->available() ) { + data_bytes++; + byte c = UBXSerial->read(); + if ( fpos < 2 ) { + // For the first two bytes we are simply looking for a match with the UBX header bytes (0xB5,0x62) + if ( c == UBX.UBX_HEADER[fpos] ) + fpos++; + else + fpos = 0; // Reset to beginning state. + } + else { + // If we come here then fpos >= 2, which means we have found a match with the UBX_HEADER + // and we are now reading in the bytes that make up the payload. + + // Place the incoming byte into the ubxMessage struct. The position is fpos-2 because + // the struct does not include the initial two-byte header (UBX_HEADER). + if ( (fpos-2) < payloadSize ) + ((char*)(&UBX.Message))[fpos-2] = c; + + fpos++; + + if ( fpos == 4 ) { + // We have just received the second byte of the message type header, + // so now we can check to see what kind of message it is. + if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { + currentMsgType = MT_NAV_POSLLH; + payloadSize = sizeof(UBX_t::NAV_POSLLH); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { + currentMsgType = MT_NAV_STATUS; + payloadSize = sizeof(UBX_t::NAV_STATUS); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { + currentMsgType = MT_NAV_TIME; + payloadSize = sizeof(UBX_t::NAV_TIME_UTC); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); + } + else { + // unknown message type, bail + fpos = 0; + continue; + } + } + + if ( fpos == (payloadSize+2) ) { + // All payload bytes have now been received, so we can calculate the + // expected checksum value to compare with the next two incoming bytes. + UBXcalcChecksum(checksum, payloadSize); + } + else if ( fpos == (payloadSize+3) ) { + // First byte after the payload, ie. first byte of the checksum. + // Does it match the first byte of the checksum we calculated? + if ( c != checksum[0] ) { + // Checksum doesn't match, reset to beginning state and try again. + fpos = 0; + } + } + else if ( fpos == (payloadSize+4) ) { + // Second byte after the payload, ie. second byte of the checksum. + // Does it match the second byte of the checksum we calculated? + fpos = 0; // We will reset the state regardless of whether the checksum matches. + if ( c == checksum[1] ) { + // Checksum matches, we have a valid message. + return currentMsgType; + } + } + else if ( fpos > (payloadSize+4) ) { + // We have now read more bytes than both the expected payload and checksum + // together, so something went wrong. Reset to beginning state and try again. + fpos = 0; + } + } + } + // DEBUG_SENSOR_LOG(PSTR("UBX: got none or unknown Message")); + if(data_bytes!=0){ + UBX.state.non_empty_loops++; + DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); + } + else{ + UBX.state.non_empty_loops = 0; // now a hidden GPS-device reset is unlikely + } + return MT_NONE; +} + +/********************************************************************************************\ +| * callback functions for the download +\*********************************************************************************************/ +#ifdef USE_FLOG +void UBXsendHeader(void){ + WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); + WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); + WSSend(200, CT_STREAM, F( + "\r\n" + "\r\n" + "\r\n\r\n")); +} + +void UBXsendRecord(uint8_t *buf){ + char record[100]; + char stime[32]; + UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; + snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); + char lat[12]; + char lon[12]; + dtostrfd((double)entry->lat/10000000.0f,7,lat); + dtostrfd((double)entry->lon/10000000.0f,7,lon); + snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); + // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.dword_buffer[k+j],Flog->sector.dword_buffer[k+j+1]); + WebServer->sendContent_P(record); +} + +void UBXsendFooter(void){ + WebServer->sendContent(F("\n\n")); + WebServer->sendContent(""); + Rtc.user_time_entry = false; // we have blocked the main loop and want a new valid time +} + +/********************************************************************************************/ +void UBXsendFile(void){ + if (!HttpCheckPriviledgedAccess()) { return; } + Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); +} +#endif //USE_FLOG +/********************************************************************************************/ + +void UBXSetRate(uint16_t interval){ + UBX.Message.cfgRate.cls = 0x06; + UBX.Message.cfgRate.id = 0x08; + UBX.Message.cfgRate.len = 6; + uint32_t measRate = (1000*(uint32_t)interval); //seconds to milliseconds + if (measRate > 0xffff) { + measRate = 0xffff; // max. 65535 ms interval + } + UBX.Message.cfgRate.measRate = (uint16_t)measRate; + UBX.Message.cfgRate.navRate = 1; + UBX.Message.cfgRate.timeRef = 1; + UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); + DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); + UBXSerial->write(UBX.UBX_HEADER[0]); + UBXSerial->write(UBX.UBX_HEADER[1]); + for(uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); + DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); + } + UBX.state.log_interval = 10*interval; +} + + +void UBXSelectMode(uint16_t mode){ + DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); + switch(mode){ +#ifdef USE_FLOG + case 0: + Flog->mode = 0; // write once to all available sectors, then stop + break; + case 1: + Flog->mode = 1; // write to all available sectors, then restart and overwrite the older ones + break; + case 2: + UBX.mode.filter_noise = true; // filter out horizontal drift noise, TODO: find useful values + break; + case 3: + UBX.mode.filter_noise = false; + break; + case 4: + Flog->startRecording(true); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); + break; + case 5: + Flog->startRecording(false); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); + break; + case 6: + if(Flog->recording == true){ + Flog->stopRecording(); + } + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); + break; + case 7: + UBX.mode.send_when_new = 1; // send mqtt on new postion + TELE -> consider to set TELE to a very high value + break; + case 8: + UBX.mode.send_when_new = 0; // only TELE + break; + case 9: + if (timeServer.beginListening()){ + UBX.mode.runningNTP = true; + } + break; + case 10: + UBX.mode.runningNTP = false; + break; + case 11: + UBX.mode.forceUTCupdate = true; + break; + case 12: + UBX.mode.forceUTCupdate = false; + break; + case 13: + Settings.latitude = UBX.state.last_lat; + Settings.longitude = UBX.state.last_lon; + break; + + +#endif //USE_FLOG + default: + if(mode>1000 && mode <1066) { + // UBXSetRate(mode-1000); // min. 1001 = 0.001 Hz, but will be converted to 1/65535 anyway ~0.015 Hz, max. 2000 = 1.000 Hz + UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65 + } + break; + } + UBX.mode.send_UI_only = true; + UBXTriggerTele(); +} +/********************************************************************************************/ + +bool UBXHandlePOSLLH(){ + DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); + if(UBX.state.gpsFix>1){ + if(UBX.mode.filter_noise){ + if((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat6){ // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz) + UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!! + AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); + UBXSerial->flush(); + UBX.state.non_empty_loops = 0; + } +} + +/********************************************************************************************/ + +void UBXTimeServer(){ + if(UBX.mode.runningNTP){ + timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000); + } +} + +void UBXLoop(void) +{ + static uint16_t counter; //count up every 100 msec + static bool new_position; + + uint32_t msgType = UBXprocessGPS(); + + switch(msgType){ + case MT_NAV_POSLLH: + new_position = UBXHandlePOSLLH(); + break; + case MT_NAV_STATUS: + UBXHandleSTATUS(); + break; + case MT_NAV_TIME: + UBXHandleTIME(); + break; + default: + UBXHandleOther(); + break; + } + +#ifdef USE_FLOG + if(counter>UBX.state.log_interval){ + if(Flog->recording && new_position){ + UBX.rec_buffer.values.time = Rtc.local_time; + Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); + counter = 0; + } + } +#endif // USE_FLOG + +counter++; +} + +/********************************************************************************************/ +// normaly in i18n.h + +#ifdef USE_WEBSERVER + // {s} = , {m} = , {e} = + +#ifdef USE_FLOG +#ifdef DEBUG_TASMOTA_SENSOR + const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" + "{s} FLOG next sector for REC: {m} %u {e}" + "{s} %u sector(s) with data at sector: {m} %u {e}"; + const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; +#endif // DEBUG_TASMOTA_SENSOR + + const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; + const char kFLOG_STATE0[] PROGMEM = "ready"; + const char kFLOG_STATE1[] PROGMEM = "recording"; + const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; + + const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; + +#endif //USE_FLOG + const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; + + const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" + "{s} GPS longitude {m}%s{e}" + "{s} GPS height {m}%s m{e}" + "{s} GPS hor. Accuracy {m}%s m{e}" + "{s} GPS vert. Accuracy {m}%s m{e}" + "{s} GPS sat-fix status {m}%s{e}"; + + const char kGPSFix0[] PROGMEM = "no fix"; + const char kGPSFix1[] PROGMEM = "dead reckoning only"; + const char kGPSFix2[] PROGMEM = "2D-fix"; + const char kGPSFix3[] PROGMEM = "3D-fix"; + const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; + const char kGPSFix5[] PROGMEM = "Time only fix"; + const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; + +// const char UBX_GOOGLE_MAPS[] =""; + + +#endif // USE_WEBSERVER + +/********************************************************************************************/ + +void UBXShow(bool json) +{ + char lat[12]; + char lon[12]; + char height[12]; + char hAcc[12]; + char vAcc[12]; + dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); + dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); + dtostrfd((double)UBX.state.last_height/1000.0f,3,height); + dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); + dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); + + if (json) { + ResponseAppend_P(PSTR(",\"GPS\":{")); + if(UBX.mode.send_UI_only){ + uint32_t i = UBX.state.log_interval / 10; + ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"),UBX.mode.filter_noise, i); + } + else{ + ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"height\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, height, hAcc, vAcc); + } +#ifdef USE_FLOG + ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); +#endif //USE_FLOG + UBX.mode.send_UI_only = false; +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_GPS, lat, lon, height, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); + // WSContentSend_PD(UBX_GOOGLE_MAPS, lat, lon); +#ifdef DEBUG_TASMOTA_SENSOR +#ifdef USE_FLOG + WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); + if(Flog->recording){ + WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); + } +#endif //USE_FLOG +#endif // DEBUG_TASMOTA_SENSOR +#ifdef USE_FLOG + if(Flog->ready){ + WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); + } + if(!Flog->recording && Flog->found_saved_data){ + WSContentSend_P(HTTP_BTN_FLOG_DL); + } +#endif //USE_FLOG + if(UBX.mode.runningNTP){ + WSContentSend_P(HTTP_SNS_NTPSERVER); + } +#endif // USE_WEBSERVER + } +} + + +/*********************************************************************************************\ + * check the UBX commands +\*********************************************************************************************/ + +bool UBXCmd(void) { + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + UBXSelectMode(XdrvMailbox.payload); + Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_58 58 + +bool Xsns58(uint8_t function) +{ + bool result = false; + + if (true) { + switch (function) { + case FUNC_INIT: + UBXDetect(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_92 == XdrvMailbox.index){ + result = UBXCmd(); + } + break; + case FUNC_EVERY_50_MSECOND: + UBXTimeServer(); + break; + case FUNC_EVERY_100_MSECOND: +#ifdef USE_FLOG + if(!Flog->running_download) +#endif //USE_FLOG + { + UBXLoop(); + } + break; +#ifdef USE_FLOG + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/UBX", UBXsendFile); + break; +#endif //USE_FLOG + case FUNC_JSON_APPEND: + UBXShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: +#ifdef USE_FLOG + if(!Flog->running_download) +#endif //USE_FLOG + { + UBXShow(0); + } + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_GPS_UBX From b1e24bb9c37f94a6168c06ddf58eee6e54239e15 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Mon, 16 Dec 2019 23:03:49 -0300 Subject: [PATCH 079/559] Add GPS Support - Language Files --- tasmota/language/bg-BG.h | 1404 +++++++++++++++++++------------------- tasmota/language/cs-CZ.h | 1404 +++++++++++++++++++------------------- tasmota/language/de-DE.h | 1404 +++++++++++++++++++------------------- tasmota/language/el-GR.h | 1404 +++++++++++++++++++------------------- tasmota/language/en-GB.h | 1404 +++++++++++++++++++------------------- tasmota/language/es-ES.h | 1404 +++++++++++++++++++------------------- tasmota/language/fr-FR.h | 1404 +++++++++++++++++++------------------- tasmota/language/he-HE.h | 1404 +++++++++++++++++++------------------- tasmota/language/hu-HU.h | 1404 +++++++++++++++++++------------------- tasmota/language/it-IT.h | 1404 +++++++++++++++++++------------------- tasmota/language/ko-KO.h | 1404 +++++++++++++++++++------------------- tasmota/language/nl-NL.h | 1404 +++++++++++++++++++------------------- tasmota/language/pl-PL.h | 1404 +++++++++++++++++++------------------- tasmota/language/pt-BR.h | 1404 +++++++++++++++++++------------------- tasmota/language/pt-PT.h | 1404 +++++++++++++++++++------------------- tasmota/language/ru-RU.h | 1404 +++++++++++++++++++------------------- tasmota/language/sk-SK.h | 1404 +++++++++++++++++++------------------- tasmota/language/sv-SE.h | 1404 +++++++++++++++++++------------------- tasmota/language/tr-TR.h | 1404 +++++++++++++++++++------------------- tasmota/language/uk-UK.h | 1404 +++++++++++++++++++------------------- tasmota/language/zh-CN.h | 1404 +++++++++++++++++++------------------- tasmota/language/zh-TW.h | 1404 +++++++++++++++++++------------------- 22 files changed, 15466 insertions(+), 15422 deletions(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 1f18d8efb..ffb5bc3ec 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -1,701 +1,703 @@ -/* - bg-BG.h - localization for Bulgaria - Bulgarian for Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_BG_BG_H_ -#define _LANGUAGE_BG_BG_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.1.2.4 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1026 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "bg" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "НедПонВтрСрдЧетПетСъб" -#define D_MONTH3LIST "ЯнуФевМарАпрМайЮниЮлиАвгСепОктНоеДек" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Качество на въздуха" -#define D_AP "Точка за достъп" // Access Point -#define D_AS "като" -#define D_AUTO "АВТОМАТИЧНО" -#define D_BLINK "Мигане вкл." -#define D_BLINKOFF "Мигане изкл." -#define D_BOOT_COUNT "Брой на стартиранията" -#define D_BRIGHTLIGHT "Яркост" -#define D_BSSID "BSSId" -#define D_BUTTON "Бутон" -#define D_BY "от" // Written by me -#define D_BYTES "Байта" -#define D_CELSIUS "Целзий" -#define D_CHANNEL "Канал" -#define D_CO2 "Въглероден диоксид" -#define D_CODE "код" // Button code -#define D_COLDLIGHT "Хладна" -#define D_COMMAND "Команда" -#define D_CONNECTED "Свързан" -#define D_CORS_DOMAIN "CORS домейн" -#define D_COUNT "Брой" -#define D_COUNTER "Брояч" -#define D_CURRENT "Ток" // As in Voltage and Current -#define D_DATA "Данни" -#define D_DARKLIGHT "Тъмна" -#define D_DEBUG "Дебъгване" -#define D_DISABLED "Забранен" -#define D_DISTANCE "Разстояние" -#define D_DNS_SERVER "DNS Сървър" -#define D_DONE "Изпълнено" -#define D_DST_TIME "Лятно време" -#define D_ECO2 "eCO₂" -#define D_EMULATION "Емулация" -#define D_ENABLED "Разрешен" -#define D_ERASE "Изтриване" -#define D_ERROR "Грешка" -#define D_FAHRENHEIT "Фаренхайт" -#define D_FAILED "Неуспешно" -#define D_FALLBACK "Помощен" -#define D_FALLBACK_TOPIC "Помощен топик" -#define D_FALSE "Невярно" -#define D_FILE "Файл" -#define D_FLOW_RATE "Дебит" -#define D_FREE_MEMORY "Свободна памет" -#define D_FREQUENCY "Честота" -#define D_GAS "Газ" -#define D_GATEWAY "Шлюз" -#define D_GROUP "Група" -#define D_HOST "Хост" -#define D_HOSTNAME "Име на хоста" -#define D_HUMIDITY "Влажност" -#define D_ILLUMINANCE "Осветеност" -#define D_IMMEDIATE "Моментен" // Button immediate -#define D_INDEX "Индекс" -#define D_INFO "Информация" -#define D_INFRARED "Инфрачервен" -#define D_INITIALIZED "Инициализирано" -#define D_IP_ADDRESS "IP адрес" -#define D_LIGHT "Светлина" -#define D_LWT "LWT" -#define D_MODULE "Модул" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "неколкократно натискане" -#define D_NOISE "Шум" -#define D_NONE "Няма" -#define D_OFF "Изкл." -#define D_OFFLINE "Офлайн" -#define D_OK "Ок" -#define D_ON "Вкл." -#define D_ONLINE "Онлайн" -#define D_PASSWORD "Парола" -#define D_PORT "Порт" -#define D_POWER_FACTOR "Фактор на мощността" -#define D_POWERUSAGE "Мощност" -#define D_POWERUSAGE_ACTIVE "Активна мощност" -#define D_POWERUSAGE_APPARENT "Пълна мощност" -#define D_POWERUSAGE_REACTIVE "Реактивна мощност" -#define D_PRESSURE "Налягане" -#define D_PRESSUREATSEALEVEL "Налягане при морското ниво" -#define D_PROGRAM_FLASH_SIZE "Размер на флаш паметта за програми" -#define D_PROGRAM_SIZE "Размер на програмата" -#define D_PROJECT "Проект" -#define D_RAIN "Дъжд" -#define D_RECEIVED "Получено" -#define D_RESTART "Рестарт" -#define D_RESTARTING "Рестартиране" -#define D_RESTART_REASON "Причина за рестарта" -#define D_RESTORE "възстановяване" -#define D_RETAINED "запазено" -#define D_RULE "Правило" -#define D_SAVE "Запис" -#define D_SENSOR "Датчик" -#define D_SSID "SSId" -#define D_START "Старт" -#define D_STD_TIME "STD" -#define D_STOP "Стоп" -#define D_SUBNET_MASK "Маска на подмрежата" -#define D_SUBSCRIBE_TO "Записване за" -#define D_UNSUBSCRIBE_FROM "Отписване от" -#define D_SUCCESSFUL "Успешно" -#define D_SUNRISE "Изгрев" -#define D_SUNSET "Залез" -#define D_TEMPERATURE "Температура" -#define D_TO "към" -#define D_TOGGLE "Превключване" -#define D_TOPIC "Топик" -#define D_TOTAL_USAGE "Използвана вода" -#define D_TRANSMIT "Предаване" -#define D_TRUE "Вярно" -#define D_TVOC "TVOC" -#define D_UPGRADE "Обновяване" -#define D_UPLOAD "Зареждане" -#define D_UPTIME "Време от стартирането" -#define D_USER "Потребител" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV индекс" -#define D_UV_INDEX_1 "Нисък" -#define D_UV_INDEX_2 "Среден" -#define D_UV_INDEX_3 "Висок" -#define D_UV_INDEX_4 "Много висок" -#define D_UV_INDEX_5 "Изгаряне 1/2 степен" -#define D_UV_INDEX_6 "Изгаряне 3-та степен" -#define D_UV_INDEX_7 "Извън обхват" -#define D_UV_LEVEL "UV ниво" -#define D_UV_POWER "UV мощност" -#define D_VERSION "Версия" -#define D_VOLTAGE "Напрежение" -#define D_WEIGHT "Тегло" -#define D_WARMLIGHT "Топла" -#define D_WEB_SERVER "Уеб сървър" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Тази версия не поддържа постоянни настройки" -#define D_LEVEL_10 "ниво 1-0" -#define D_LEVEL_01 "ниво 0-1" -#define D_SERIAL_LOGGING_DISABLED "Серийният лог изключен" -#define D_SYSLOG_LOGGING_REENABLED "Системният лог активиран" - -#define D_SET_BAUDRATE_TO "Задаване скорост на предаване (Baudrate)" -#define D_RECEIVED_TOPIC "Получен топик" -#define D_DATA_SIZE "Размер на данните" -#define D_ANALOG_INPUT "Аналогов вход" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Блокиран цикъл" -#define D_WPS_FAILED_WITH_STATUS "WPS конфигурацията е НЕУСПЕШНА със статус" -#define D_ACTIVE_FOR_3_MINUTES "активно в течение на 3 минути" -#define D_FAILED_TO_START "Неуспешно стартиране" -#define D_PATCH_ISSUE_2186 "Проблем с патч 2186" -#define D_CONNECTING_TO_AP "Свързване към точка за достъп" -#define D_IN_MODE "в режим" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Грешка при свързването, не е получен IP адрес" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Грешка при свързването, точката за достъп е недостижима" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Грешка при свързването, грешна парола към точката за достъп" -#define D_CONNECT_FAILED_AP_TIMEOUT "Грешка при свързването, превишено време за изчакване" -#define D_ATTEMPTING_CONNECTION "Опитва свързване..." -#define D_CHECKING_CONNECTION "Проверка на свързването..." -#define D_QUERY_DONE "Запитването е изпълнено. Намерена е услуга MQTT" -#define D_MQTT_SERVICE_FOUND "MQTT услуга е намерена на" -#define D_FOUND_AT "намерена в" -#define D_SYSLOG_HOST_NOT_FOUND "Хостът на системния лог не е намерен" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Запазено във флаш паметта на" -#define D_LOADED_FROM_FLASH_AT "Заредено от флаш паметта от" -#define D_USE_DEFAULTS "Използване на параметри по подразбиране" -#define D_ERASED_SECTOR "Изтрит сектор" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуер
моля надградете го" -#define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на" -#define D_WITH_IP_ADDRESS "с IP адрес" -#define D_WEBSERVER_STOPPED "Уеб сървърът е спрян" -#define D_FILE_NOT_FOUND "Файлът не е намерен" -#define D_REDIRECTED "Пренасочено към адаптивния портал" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi мениджърът настройва точка за достъп и запомня станцията" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi мениджърът настрои точката за достъп" -#define D_TRYING_TO_CONNECT "Опит за свързване на устройството към мрежата" - -#define D_RESTART_IN "Рестарт след" -#define D_SECONDS "секунди" -#define D_DEVICE_WILL_RESTART "Устройството ще се рестартира след няколко секунди" -#define D_BUTTON_TOGGLE "Превключване" -#define D_CONFIGURATION "Конфигурация" -#define D_INFORMATION "Информация" -#define D_FIRMWARE_UPGRADE "Обновяване на фърмуера" -#define D_CONSOLE "Конзола" -#define D_CONFIRM_RESTART "Потвърдете рестартирането" - -#define D_CONFIGURE_MODULE "Конфигурация на модула" -#define D_CONFIGURE_WIFI "Конфигурация на WiFi" -#define D_CONFIGURE_MQTT "Конфигурация на MQTT" -#define D_CONFIGURE_DOMOTICZ "Конфигурация на Domoticz" -#define D_CONFIGURE_LOGGING "Конфигурация на лога" -#define D_CONFIGURE_OTHER "Други конфигурации" -#define D_CONFIRM_RESET_CONFIGURATION "Потвърдете изчистването" -#define D_RESET_CONFIGURATION "Изчистване на конфигурацията" -#define D_BACKUP_CONFIGURATION "Запазване на конфигурацията" -#define D_RESTORE_CONFIGURATION "Възстановяване на конфигурацията" -#define D_MAIN_MENU "Основно меню" - -#define D_MODULE_PARAMETERS "Параметри на модула" -#define D_MODULE_TYPE "Тип на модула" -#define D_PULLUP_ENABLE "Без pull-up за бутон/ключ" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Сериен вход" -#define D_SERIAL_OUT "Сериен изход" - -#define D_WIFI_PARAMETERS "Wifi параметри" -#define D_SCAN_FOR_WIFI_NETWORKS "Сканиране за безжични мрежи" -#define D_SCAN_DONE "Сканирането приключи" -#define D_NO_NETWORKS_FOUND "Не бяха открити мрежи" -#define D_REFRESH_TO_SCAN_AGAIN "Обновяване за повторно сканиране" -#define D_DUPLICATE_ACCESSPOINT "Дублиране на точката за достъп (AP)" -#define D_SKIPPING_LOW_QUALITY "Пропускане поради лошо качество" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Парола" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Парола" - -#define D_MQTT_PARAMETERS "Параметри на MQTT" -#define D_CLIENT "Клиент" -#define D_FULL_TOPIC "Пълен топик" - -#define D_LOGGING_PARAMETERS "Параметри на лога" -#define D_SERIAL_LOG_LEVEL "Степен на серийния лог" -#define D_MQTT_LOG_LEVEL "Степен на MQTT лога" -#define D_WEB_LOG_LEVEL "Степен на уеб лога" -#define D_SYS_LOG_LEVEL "Степен на системния лог" -#define D_MORE_DEBUG "Допълнителна debug информация" -#define D_SYSLOG_HOST "Хост на системния лог" -#define D_SYSLOG_PORT "Порт на системния лог" -#define D_TELEMETRY_PERIOD "Период на телеметрия" - -#define D_OTHER_PARAMETERS "Други параметри" -#define D_TEMPLATE "Модел" -#define D_ACTIVATE "Активирай" -#define D_WEB_ADMIN_PASSWORD "Парола на уеб администратора" -#define D_MQTT_ENABLE "Активиране на MQTT" -#define D_FRIENDLY_NAME "Приятелско име" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "Единично" -#define D_MULTI_DEVICE "Мулти" - -#define D_CONFIGURE_TEMPLATE "Конфигуриране на шаблон" -#define D_TEMPLATE_PARAMETERS "Параметри на шаблона" -#define D_TEMPLATE_NAME "Име" -#define D_BASE_TYPE "Базиран на" -#define D_TEMPLATE_FLAGS "Опции" - -#define D_SAVE_CONFIGURATION "Запазване на конфигурацията" -#define D_CONFIGURATION_SAVED "Конфигурацията е запазена" -#define D_CONFIGURATION_RESET "Конфигурацията е изчистена" - -#define D_PROGRAM_VERSION "Версия на програмата" -#define D_BUILD_DATE_AND_TIME "Дата и час на компилацията" -#define D_CORE_AND_SDK_VERSION "Версия на Core/SDK" -#define D_FLASH_WRITE_COUNT "Брой на записите във флаш паметта" -#define D_MAC_ADDRESS "MAC адрес" -#define D_MQTT_HOST "MQTT хост" -#define D_MQTT_PORT "MQTT порт" -#define D_MQTT_CLIENT "MQTT ID на клиент" -#define D_MQTT_USER "MQTT потребител" -#define D_MQTT_TOPIC "MQTT топик" -#define D_MQTT_GROUP_TOPIC "MQTT групов топик" -#define D_MQTT_FULL_TOPIC "MQTT пълен топик" -#define D_MDNS_DISCOVERY "mDNS откриване" -#define D_MDNS_ADVERTISE "mDNS известяване" -#define D_ESP_CHIP_ID "ID на ESP чипа" -#define D_FLASH_CHIP_ID "ID на чипа на флаш паметта" -#define D_FLASH_CHIP_SIZE "Размер на флаш паметта" -#define D_FREE_PROGRAM_SPACE "Свободно пространство за програми" - -#define D_UPGRADE_BY_WEBSERVER "Обновяване чрез уеб сървър" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Започване на обновяване" -#define D_UPGRADE_BY_FILE_UPLOAD "Обновяване чрез зареждане на файл" -#define D_UPLOAD_STARTED "Зареждането започна" -#define D_UPGRADE_STARTED "Обновяването започна" -#define D_UPLOAD_DONE "Зареждането завърши" -#define D_UPLOAD_ERR_1 "Не е избран файл" -#define D_UPLOAD_ERR_2 "Недостатъчно свободно място" -#define D_UPLOAD_ERR_3 "Magic байтът не е 0xE9" -#define D_UPLOAD_ERR_4 "Размерът на програмата е по-голям от реалния размер на флаш паметта" -#define D_UPLOAD_ERR_5 "Грешка при зареждането в буфера" -#define D_UPLOAD_ERR_6 "Грешка при зареждането. Включено е ниво 3 на лога" -#define D_UPLOAD_ERR_7 "Зареждането е прекъснато" -#define D_UPLOAD_ERR_8 "Файлът е невалиден" -#define D_UPLOAD_ERR_9 "Файлът е прекалено голям" -#define D_UPLOAD_ERR_10 "Грешка при инициализация на RF чипа" -#define D_UPLOAD_ERR_11 "Грешка при изтриване на RF чипа" -#define D_UPLOAD_ERR_12 "Грешка при записване в RF чипа" -#define D_UPLOAD_ERR_13 "Грешка при декодиране на RF фърмуера" -#define D_UPLOAD_ERROR_CODE "Код на грешка при зареждането" - -#define D_ENTER_COMMAND "Въвеждане на команда" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Включете ниво 2 на лога, ако очаквате отговор" -#define D_NEED_USER_AND_PASSWORD "Очаква user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Проверка на TLS отпечатък..." -#define D_TLS_CONNECT_FAILED_TO "Неуспешно TLS свързване към" -#define D_RETRY_IN "Повтори след" -#define D_VERIFIED "Проверен отпечтък" -#define D_INSECURE "Нешифрована връзка, недействителен отпечатък" -#define D_CONNECT_FAILED_TO "Грешка при свързването към" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast е изключен" -#define D_MULTICAST_REJOINED "Multicast е повторно съединен" -#define D_MULTICAST_JOIN_FAILED "Multicast грешка при присъединяването" -#define D_FAILED_TO_SEND_RESPONSE "Неуспех при изпращането на отговор" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo главно събитие" -#define D_WEMO_EVENT_SERVICE "WeMo услуга за събитията" -#define D_WEMO_META_SERVICE "WeMo мета-услуга" -#define D_WEMO_SETUP "WeMo настройка" -#define D_RESPONSE_SENT "Отговорът е изпратен" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Настройка на Hue bridge" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API не е внедрен" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST аргументи" -#define D_3_RESPONSE_PACKETS_SENT "Изпратени са 3 пакета за отговор" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz параметри" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Мощност,Енергия" - #define D_DOMOTICZ_ILLUMINANCE "Осветеност" - #define D_DOMOTICZ_COUNT "Брояч/PM1" - #define D_DOMOTICZ_VOLTAGE "Напрежение/PM2,5" - #define D_DOMOTICZ_CURRENT "Ток/PM10" - #define D_DOMOTICZ_AIRQUALITY "Качество на въздуха" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Период на опресняване" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Конфигуриране на таймер" -#define D_TIMER_PARAMETERS "Параметри на таймера" -#define D_TIMER_ENABLE "Активиране на таймера" -#define D_TIMER_ARM "Активиран" -#define D_TIMER_TIME "Време" -#define D_TIMER_DAYS "Дни" -#define D_TIMER_REPEAT "Повтори" -#define D_TIMER_OUTPUT "Изход" -#define D_TIMER_ACTION "Действие" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Конфигуриране на KNX" -#define D_KNX_PARAMETERS "KNX параметри" -#define D_KNX_GENERAL_CONFIG "Основни" -#define D_KNX_PHYSICAL_ADDRESS "Физически адрес" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Трябва да е уникален в KNX мрежата )" -#define D_KNX_ENABLE "Активиране на KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Групови адреси за изпращане на данни" -#define D_ADD "Добаване" -#define D_DELETE "Изтриване" -#define D_REPLY "Отговор" -#define D_KNX_GROUP_ADDRESS_TO_READ "Групови адреси за получаване на данни" -#define D_RECEIVED_FROM "Получен от" -#define D_KNX_COMMAND_WRITE "Писане" -#define D_KNX_COMMAND_READ "Четене" -#define D_KNX_COMMAND_OTHER "Друго" -#define D_SENT_TO "изпратен до" -#define D_KNX_WARNING "Груповият адрес (0/0/0) е резервиран и не може да бъде използван." -#define D_KNX_ENHANCEMENT "Подобрена комуникация" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Използвана енергия днес" -#define D_ENERGY_YESTERDAY "Използвана енергия вчера" -#define D_ENERGY_TOTAL "Използвана енергия общо" - -// xdrv_27_shutter.ino -#define D_OPEN "Отворена" -#define D_CLOSE "Затворена" -#define D_DOMOTICZ_SHUTTER "Щора" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Конфигуриране на PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 параметри" -#define D_INVERT_PORTS "Обърни портовете" -#define D_DEVICE "Устройство" -#define D_DEVICE_INPUT "Вход" -#define D_DEVICE_OUTPUT "Изход" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Датчикът DS18x20 е зает" -#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - грешка CRC" -#define D_SENSORS_FOUND "Намерен е датчик DS18x20" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Изтекло време за очакване на" -#define D_START_SIGNAL_LOW "Нисък стартов сигнал" -#define D_START_SIGNAL_HIGH "Висок стартов сигнал" -#define D_PULSE "Импулс" -#define D_CHECKSUM_FAILURE "Грешка в контролната сума" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчикът не прие команда ACK" -#define D_SHT1X_FOUND "Намерен е SHT1X" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Частици" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Ускорение - ос X" -#define D_AY_AXIS "Ускорение - ос Y" -#define D_AZ_AXIS "Ускорение - ос Z" -#define D_GX_AXIS "Жироскоп - ос X" -#define D_GY_AXIS "Жироскоп - ос Y" -#define D_GZ_AXIS "Жироскоп - ос Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Премахване на тегло" -#define D_HX_CAL_REFERENCE "Зареждане на референтно тегло" -#define D_HX_CAL_DONE "Калибриран" -#define D_HX_CAL_FAIL "Неуспешно калибриране" -#define D_RESET_HX711 "Нулиране на кантара" -#define D_CONFIGURE_HX711 "Конфигуриране на кантара" -#define D_HX711_PARAMETERS "Параметри на кантара" -#define D_ITEM_WEIGHT "Тегло" -#define D_REFERENCE_WEIGHT "Референтно тегло" -#define D_CALIBRATE "Калибриране" -#define D_CALIBRATION "Калибровка" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Посока на вятъра" -#define D_TX20_WIND_SPEED "Скорост на вятъра" -#define D_TX20_WIND_SPEED_AVG "Средна скорост на вятъра" -#define D_TX20_WIND_SPEED_MAX "Макс. скорост на вятъра" -#define D_TX20_NORTH "С" -#define D_TX20_EAST "И" -#define D_TX20_SOUTH "Ю" -#define D_TX20_WEST "З" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Няма" -#define D_SENSOR_USER "Потребит." -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 плейър" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Ключ" // Suffix "1" -#define D_SENSOR_BUTTON "Бутон" // Suffix "1" -#define D_SENSOR_RELAY "Реле" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Брояч" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Подсветка" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF датчик" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "gal/min" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" -#define D_UNIT_KILOOHM "kΩ" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "сектори" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Фазов ъгъл" -#define D_IMPORT_ACTIVE "Входна активна мощност" -#define D_EXPORT_ACTIVE "Изходна активна мощност" -#define D_IMPORT_REACTIVE "Входна реактивна мощност" -#define D_EXPORT_REACTIVE "Изходна реактивна мощност" -#define D_TOTAL_REACTIVE "Общо реактивна мощност" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "°" - -//SOLAXX1 -#define D_PV1_VOLTAGE "Напрежение на PV1" -#define D_PV1_CURRENT "Ток на PV1" -#define D_PV1_POWER "Мощност на PV1" -#define D_PV2_VOLTAGE "Напрежение на PV2" -#define D_PV2_CURRENT "Ток на PV2" -#define D_PV2_POWER "Мощност на PV2" -#define D_SOLAR_POWER "Слънчева мощност" -#define D_INVERTER_POWER "Мощност на инвертера" -#define D_STATUS "Състояние" -#define D_WAITING "Очакване" -#define D_CHECKING "Проверка" -#define D_WORKING "Работи" -#define D_FAILURE "Грешка" -#define D_SOLAX_ERROR_0 "Грешка - няма код" -#define D_SOLAX_ERROR_1 "Грешка - загуба на мрежата" -#define D_SOLAX_ERROR_2 "Грешка - мрежово напрежение" -#define D_SOLAX_ERROR_3 "Грешка - мрежова честота" -#define D_SOLAX_ERROR_4 "Грешка - напрежение на Pv" -#define D_SOLAX_ERROR_5 "Грешка - проблем с изолацията" -#define D_SOLAX_ERROR_6 "Грешка - прегряване" -#define D_SOLAX_ERROR_7 "Грешка - вентилатор" -#define D_SOLAX_ERROR_8 "Грешка - друго оборудване" - -#endif // _LANGUAGE_BG_BG_H_ +/* + bg-BG.h - localization for Bulgaria - Bulgarian for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_BG_BG_H_ +#define _LANGUAGE_BG_BG_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.1.2.4 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1026 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "bg" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "НедПонВтрСрдЧетПетСъб" +#define D_MONTH3LIST "ЯнуФевМарАпрМайЮниЮлиАвгСепОктНоеДек" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Качество на въздуха" +#define D_AP "Точка за достъп" // Access Point +#define D_AS "като" +#define D_AUTO "АВТОМАТИЧНО" +#define D_BLINK "Мигане вкл." +#define D_BLINKOFF "Мигане изкл." +#define D_BOOT_COUNT "Брой на стартиранията" +#define D_BRIGHTLIGHT "Яркост" +#define D_BSSID "BSSId" +#define D_BUTTON "Бутон" +#define D_BY "от" // Written by me +#define D_BYTES "Байта" +#define D_CELSIUS "Целзий" +#define D_CHANNEL "Канал" +#define D_CO2 "Въглероден диоксид" +#define D_CODE "код" // Button code +#define D_COLDLIGHT "Хладна" +#define D_COMMAND "Команда" +#define D_CONNECTED "Свързан" +#define D_CORS_DOMAIN "CORS домейн" +#define D_COUNT "Брой" +#define D_COUNTER "Брояч" +#define D_CURRENT "Ток" // As in Voltage and Current +#define D_DATA "Данни" +#define D_DARKLIGHT "Тъмна" +#define D_DEBUG "Дебъгване" +#define D_DISABLED "Забранен" +#define D_DISTANCE "Разстояние" +#define D_DNS_SERVER "DNS Сървър" +#define D_DONE "Изпълнено" +#define D_DST_TIME "Лятно време" +#define D_ECO2 "eCO₂" +#define D_EMULATION "Емулация" +#define D_ENABLED "Разрешен" +#define D_ERASE "Изтриване" +#define D_ERROR "Грешка" +#define D_FAHRENHEIT "Фаренхайт" +#define D_FAILED "Неуспешно" +#define D_FALLBACK "Помощен" +#define D_FALLBACK_TOPIC "Помощен топик" +#define D_FALSE "Невярно" +#define D_FILE "Файл" +#define D_FLOW_RATE "Дебит" +#define D_FREE_MEMORY "Свободна памет" +#define D_FREQUENCY "Честота" +#define D_GAS "Газ" +#define D_GATEWAY "Шлюз" +#define D_GROUP "Група" +#define D_HOST "Хост" +#define D_HOSTNAME "Име на хоста" +#define D_HUMIDITY "Влажност" +#define D_ILLUMINANCE "Осветеност" +#define D_IMMEDIATE "Моментен" // Button immediate +#define D_INDEX "Индекс" +#define D_INFO "Информация" +#define D_INFRARED "Инфрачервен" +#define D_INITIALIZED "Инициализирано" +#define D_IP_ADDRESS "IP адрес" +#define D_LIGHT "Светлина" +#define D_LWT "LWT" +#define D_MODULE "Модул" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "неколкократно натискане" +#define D_NOISE "Шум" +#define D_NONE "Няма" +#define D_OFF "Изкл." +#define D_OFFLINE "Офлайн" +#define D_OK "Ок" +#define D_ON "Вкл." +#define D_ONLINE "Онлайн" +#define D_PASSWORD "Парола" +#define D_PORT "Порт" +#define D_POWER_FACTOR "Фактор на мощността" +#define D_POWERUSAGE "Мощност" +#define D_POWERUSAGE_ACTIVE "Активна мощност" +#define D_POWERUSAGE_APPARENT "Пълна мощност" +#define D_POWERUSAGE_REACTIVE "Реактивна мощност" +#define D_PRESSURE "Налягане" +#define D_PRESSUREATSEALEVEL "Налягане при морското ниво" +#define D_PROGRAM_FLASH_SIZE "Размер на флаш паметта за програми" +#define D_PROGRAM_SIZE "Размер на програмата" +#define D_PROJECT "Проект" +#define D_RAIN "Дъжд" +#define D_RECEIVED "Получено" +#define D_RESTART "Рестарт" +#define D_RESTARTING "Рестартиране" +#define D_RESTART_REASON "Причина за рестарта" +#define D_RESTORE "възстановяване" +#define D_RETAINED "запазено" +#define D_RULE "Правило" +#define D_SAVE "Запис" +#define D_SENSOR "Датчик" +#define D_SSID "SSId" +#define D_START "Старт" +#define D_STD_TIME "STD" +#define D_STOP "Стоп" +#define D_SUBNET_MASK "Маска на подмрежата" +#define D_SUBSCRIBE_TO "Записване за" +#define D_UNSUBSCRIBE_FROM "Отписване от" +#define D_SUCCESSFUL "Успешно" +#define D_SUNRISE "Изгрев" +#define D_SUNSET "Залез" +#define D_TEMPERATURE "Температура" +#define D_TO "към" +#define D_TOGGLE "Превключване" +#define D_TOPIC "Топик" +#define D_TOTAL_USAGE "Използвана вода" +#define D_TRANSMIT "Предаване" +#define D_TRUE "Вярно" +#define D_TVOC "TVOC" +#define D_UPGRADE "Обновяване" +#define D_UPLOAD "Зареждане" +#define D_UPTIME "Време от стартирането" +#define D_USER "Потребител" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV индекс" +#define D_UV_INDEX_1 "Нисък" +#define D_UV_INDEX_2 "Среден" +#define D_UV_INDEX_3 "Висок" +#define D_UV_INDEX_4 "Много висок" +#define D_UV_INDEX_5 "Изгаряне 1/2 степен" +#define D_UV_INDEX_6 "Изгаряне 3-та степен" +#define D_UV_INDEX_7 "Извън обхват" +#define D_UV_LEVEL "UV ниво" +#define D_UV_POWER "UV мощност" +#define D_VERSION "Версия" +#define D_VOLTAGE "Напрежение" +#define D_WEIGHT "Тегло" +#define D_WARMLIGHT "Топла" +#define D_WEB_SERVER "Уеб сървър" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Тази версия не поддържа постоянни настройки" +#define D_LEVEL_10 "ниво 1-0" +#define D_LEVEL_01 "ниво 0-1" +#define D_SERIAL_LOGGING_DISABLED "Серийният лог изключен" +#define D_SYSLOG_LOGGING_REENABLED "Системният лог активиран" + +#define D_SET_BAUDRATE_TO "Задаване скорост на предаване (Baudrate)" +#define D_RECEIVED_TOPIC "Получен топик" +#define D_DATA_SIZE "Размер на данните" +#define D_ANALOG_INPUT "Аналогов вход" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Блокиран цикъл" +#define D_WPS_FAILED_WITH_STATUS "WPS конфигурацията е НЕУСПЕШНА със статус" +#define D_ACTIVE_FOR_3_MINUTES "активно в течение на 3 минути" +#define D_FAILED_TO_START "Неуспешно стартиране" +#define D_PATCH_ISSUE_2186 "Проблем с патч 2186" +#define D_CONNECTING_TO_AP "Свързване към точка за достъп" +#define D_IN_MODE "в режим" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Грешка при свързването, не е получен IP адрес" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Грешка при свързването, точката за достъп е недостижима" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Грешка при свързването, грешна парола към точката за достъп" +#define D_CONNECT_FAILED_AP_TIMEOUT "Грешка при свързването, превишено време за изчакване" +#define D_ATTEMPTING_CONNECTION "Опитва свързване..." +#define D_CHECKING_CONNECTION "Проверка на свързването..." +#define D_QUERY_DONE "Запитването е изпълнено. Намерена е услуга MQTT" +#define D_MQTT_SERVICE_FOUND "MQTT услуга е намерена на" +#define D_FOUND_AT "намерена в" +#define D_SYSLOG_HOST_NOT_FOUND "Хостът на системния лог не е намерен" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Запазено във флаш паметта на" +#define D_LOADED_FROM_FLASH_AT "Заредено от флаш паметта от" +#define D_USE_DEFAULTS "Използване на параметри по подразбиране" +#define D_ERASED_SECTOR "Изтрит сектор" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуер
моля надградете го" +#define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на" +#define D_WITH_IP_ADDRESS "с IP адрес" +#define D_WEBSERVER_STOPPED "Уеб сървърът е спрян" +#define D_FILE_NOT_FOUND "Файлът не е намерен" +#define D_REDIRECTED "Пренасочено към адаптивния портал" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi мениджърът настройва точка за достъп и запомня станцията" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi мениджърът настрои точката за достъп" +#define D_TRYING_TO_CONNECT "Опит за свързване на устройството към мрежата" + +#define D_RESTART_IN "Рестарт след" +#define D_SECONDS "секунди" +#define D_DEVICE_WILL_RESTART "Устройството ще се рестартира след няколко секунди" +#define D_BUTTON_TOGGLE "Превключване" +#define D_CONFIGURATION "Конфигурация" +#define D_INFORMATION "Информация" +#define D_FIRMWARE_UPGRADE "Обновяване на фърмуера" +#define D_CONSOLE "Конзола" +#define D_CONFIRM_RESTART "Потвърдете рестартирането" + +#define D_CONFIGURE_MODULE "Конфигурация на модула" +#define D_CONFIGURE_WIFI "Конфигурация на WiFi" +#define D_CONFIGURE_MQTT "Конфигурация на MQTT" +#define D_CONFIGURE_DOMOTICZ "Конфигурация на Domoticz" +#define D_CONFIGURE_LOGGING "Конфигурация на лога" +#define D_CONFIGURE_OTHER "Други конфигурации" +#define D_CONFIRM_RESET_CONFIGURATION "Потвърдете изчистването" +#define D_RESET_CONFIGURATION "Изчистване на конфигурацията" +#define D_BACKUP_CONFIGURATION "Запазване на конфигурацията" +#define D_RESTORE_CONFIGURATION "Възстановяване на конфигурацията" +#define D_MAIN_MENU "Основно меню" + +#define D_MODULE_PARAMETERS "Параметри на модула" +#define D_MODULE_TYPE "Тип на модула" +#define D_PULLUP_ENABLE "Без pull-up за бутон/ключ" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Сериен вход" +#define D_SERIAL_OUT "Сериен изход" + +#define D_WIFI_PARAMETERS "Wifi параметри" +#define D_SCAN_FOR_WIFI_NETWORKS "Сканиране за безжични мрежи" +#define D_SCAN_DONE "Сканирането приключи" +#define D_NO_NETWORKS_FOUND "Не бяха открити мрежи" +#define D_REFRESH_TO_SCAN_AGAIN "Обновяване за повторно сканиране" +#define D_DUPLICATE_ACCESSPOINT "Дублиране на точката за достъп (AP)" +#define D_SKIPPING_LOW_QUALITY "Пропускане поради лошо качество" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Парола" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Парола" + +#define D_MQTT_PARAMETERS "Параметри на MQTT" +#define D_CLIENT "Клиент" +#define D_FULL_TOPIC "Пълен топик" + +#define D_LOGGING_PARAMETERS "Параметри на лога" +#define D_SERIAL_LOG_LEVEL "Степен на серийния лог" +#define D_MQTT_LOG_LEVEL "Степен на MQTT лога" +#define D_WEB_LOG_LEVEL "Степен на уеб лога" +#define D_SYS_LOG_LEVEL "Степен на системния лог" +#define D_MORE_DEBUG "Допълнителна debug информация" +#define D_SYSLOG_HOST "Хост на системния лог" +#define D_SYSLOG_PORT "Порт на системния лог" +#define D_TELEMETRY_PERIOD "Период на телеметрия" + +#define D_OTHER_PARAMETERS "Други параметри" +#define D_TEMPLATE "Модел" +#define D_ACTIVATE "Активирай" +#define D_WEB_ADMIN_PASSWORD "Парола на уеб администратора" +#define D_MQTT_ENABLE "Активиране на MQTT" +#define D_FRIENDLY_NAME "Приятелско име" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "Единично" +#define D_MULTI_DEVICE "Мулти" + +#define D_CONFIGURE_TEMPLATE "Конфигуриране на шаблон" +#define D_TEMPLATE_PARAMETERS "Параметри на шаблона" +#define D_TEMPLATE_NAME "Име" +#define D_BASE_TYPE "Базиран на" +#define D_TEMPLATE_FLAGS "Опции" + +#define D_SAVE_CONFIGURATION "Запазване на конфигурацията" +#define D_CONFIGURATION_SAVED "Конфигурацията е запазена" +#define D_CONFIGURATION_RESET "Конфигурацията е изчистена" + +#define D_PROGRAM_VERSION "Версия на програмата" +#define D_BUILD_DATE_AND_TIME "Дата и час на компилацията" +#define D_CORE_AND_SDK_VERSION "Версия на Core/SDK" +#define D_FLASH_WRITE_COUNT "Брой на записите във флаш паметта" +#define D_MAC_ADDRESS "MAC адрес" +#define D_MQTT_HOST "MQTT хост" +#define D_MQTT_PORT "MQTT порт" +#define D_MQTT_CLIENT "MQTT ID на клиент" +#define D_MQTT_USER "MQTT потребител" +#define D_MQTT_TOPIC "MQTT топик" +#define D_MQTT_GROUP_TOPIC "MQTT групов топик" +#define D_MQTT_FULL_TOPIC "MQTT пълен топик" +#define D_MDNS_DISCOVERY "mDNS откриване" +#define D_MDNS_ADVERTISE "mDNS известяване" +#define D_ESP_CHIP_ID "ID на ESP чипа" +#define D_FLASH_CHIP_ID "ID на чипа на флаш паметта" +#define D_FLASH_CHIP_SIZE "Размер на флаш паметта" +#define D_FREE_PROGRAM_SPACE "Свободно пространство за програми" + +#define D_UPGRADE_BY_WEBSERVER "Обновяване чрез уеб сървър" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Започване на обновяване" +#define D_UPGRADE_BY_FILE_UPLOAD "Обновяване чрез зареждане на файл" +#define D_UPLOAD_STARTED "Зареждането започна" +#define D_UPGRADE_STARTED "Обновяването започна" +#define D_UPLOAD_DONE "Зареждането завърши" +#define D_UPLOAD_ERR_1 "Не е избран файл" +#define D_UPLOAD_ERR_2 "Недостатъчно свободно място" +#define D_UPLOAD_ERR_3 "Magic байтът не е 0xE9" +#define D_UPLOAD_ERR_4 "Размерът на програмата е по-голям от реалния размер на флаш паметта" +#define D_UPLOAD_ERR_5 "Грешка при зареждането в буфера" +#define D_UPLOAD_ERR_6 "Грешка при зареждането. Включено е ниво 3 на лога" +#define D_UPLOAD_ERR_7 "Зареждането е прекъснато" +#define D_UPLOAD_ERR_8 "Файлът е невалиден" +#define D_UPLOAD_ERR_9 "Файлът е прекалено голям" +#define D_UPLOAD_ERR_10 "Грешка при инициализация на RF чипа" +#define D_UPLOAD_ERR_11 "Грешка при изтриване на RF чипа" +#define D_UPLOAD_ERR_12 "Грешка при записване в RF чипа" +#define D_UPLOAD_ERR_13 "Грешка при декодиране на RF фърмуера" +#define D_UPLOAD_ERROR_CODE "Код на грешка при зареждането" + +#define D_ENTER_COMMAND "Въвеждане на команда" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Включете ниво 2 на лога, ако очаквате отговор" +#define D_NEED_USER_AND_PASSWORD "Очаква user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Проверка на TLS отпечатък..." +#define D_TLS_CONNECT_FAILED_TO "Неуспешно TLS свързване към" +#define D_RETRY_IN "Повтори след" +#define D_VERIFIED "Проверен отпечтък" +#define D_INSECURE "Нешифрована връзка, недействителен отпечатък" +#define D_CONNECT_FAILED_TO "Грешка при свързването към" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast е изключен" +#define D_MULTICAST_REJOINED "Multicast е повторно съединен" +#define D_MULTICAST_JOIN_FAILED "Multicast грешка при присъединяването" +#define D_FAILED_TO_SEND_RESPONSE "Неуспех при изпращането на отговор" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo главно събитие" +#define D_WEMO_EVENT_SERVICE "WeMo услуга за събитията" +#define D_WEMO_META_SERVICE "WeMo мета-услуга" +#define D_WEMO_SETUP "WeMo настройка" +#define D_RESPONSE_SENT "Отговорът е изпратен" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Настройка на Hue bridge" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API не е внедрен" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST аргументи" +#define D_3_RESPONSE_PACKETS_SENT "Изпратени са 3 пакета за отговор" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz параметри" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Мощност,Енергия" + #define D_DOMOTICZ_ILLUMINANCE "Осветеност" + #define D_DOMOTICZ_COUNT "Брояч/PM1" + #define D_DOMOTICZ_VOLTAGE "Напрежение/PM2,5" + #define D_DOMOTICZ_CURRENT "Ток/PM10" + #define D_DOMOTICZ_AIRQUALITY "Качество на въздуха" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Период на опресняване" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Конфигуриране на таймер" +#define D_TIMER_PARAMETERS "Параметри на таймера" +#define D_TIMER_ENABLE "Активиране на таймера" +#define D_TIMER_ARM "Активиран" +#define D_TIMER_TIME "Време" +#define D_TIMER_DAYS "Дни" +#define D_TIMER_REPEAT "Повтори" +#define D_TIMER_OUTPUT "Изход" +#define D_TIMER_ACTION "Действие" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Конфигуриране на KNX" +#define D_KNX_PARAMETERS "KNX параметри" +#define D_KNX_GENERAL_CONFIG "Основни" +#define D_KNX_PHYSICAL_ADDRESS "Физически адрес" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Трябва да е уникален в KNX мрежата )" +#define D_KNX_ENABLE "Активиране на KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Групови адреси за изпращане на данни" +#define D_ADD "Добаване" +#define D_DELETE "Изтриване" +#define D_REPLY "Отговор" +#define D_KNX_GROUP_ADDRESS_TO_READ "Групови адреси за получаване на данни" +#define D_RECEIVED_FROM "Получен от" +#define D_KNX_COMMAND_WRITE "Писане" +#define D_KNX_COMMAND_READ "Четене" +#define D_KNX_COMMAND_OTHER "Друго" +#define D_SENT_TO "изпратен до" +#define D_KNX_WARNING "Груповият адрес (0/0/0) е резервиран и не може да бъде използван." +#define D_KNX_ENHANCEMENT "Подобрена комуникация" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Използвана енергия днес" +#define D_ENERGY_YESTERDAY "Използвана енергия вчера" +#define D_ENERGY_TOTAL "Използвана енергия общо" + +// xdrv_27_shutter.ino +#define D_OPEN "Отворена" +#define D_CLOSE "Затворена" +#define D_DOMOTICZ_SHUTTER "Щора" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Конфигуриране на PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 параметри" +#define D_INVERT_PORTS "Обърни портовете" +#define D_DEVICE "Устройство" +#define D_DEVICE_INPUT "Вход" +#define D_DEVICE_OUTPUT "Изход" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Датчикът DS18x20 е зает" +#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - грешка CRC" +#define D_SENSORS_FOUND "Намерен е датчик DS18x20" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Изтекло време за очакване на" +#define D_START_SIGNAL_LOW "Нисък стартов сигнал" +#define D_START_SIGNAL_HIGH "Висок стартов сигнал" +#define D_PULSE "Импулс" +#define D_CHECKSUM_FAILURE "Грешка в контролната сума" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчикът не прие команда ACK" +#define D_SHT1X_FOUND "Намерен е SHT1X" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Частици" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Ускорение - ос X" +#define D_AY_AXIS "Ускорение - ос Y" +#define D_AZ_AXIS "Ускорение - ос Z" +#define D_GX_AXIS "Жироскоп - ос X" +#define D_GY_AXIS "Жироскоп - ос Y" +#define D_GZ_AXIS "Жироскоп - ос Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Премахване на тегло" +#define D_HX_CAL_REFERENCE "Зареждане на референтно тегло" +#define D_HX_CAL_DONE "Калибриран" +#define D_HX_CAL_FAIL "Неуспешно калибриране" +#define D_RESET_HX711 "Нулиране на кантара" +#define D_CONFIGURE_HX711 "Конфигуриране на кантара" +#define D_HX711_PARAMETERS "Параметри на кантара" +#define D_ITEM_WEIGHT "Тегло" +#define D_REFERENCE_WEIGHT "Референтно тегло" +#define D_CALIBRATE "Калибриране" +#define D_CALIBRATION "Калибровка" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Посока на вятъра" +#define D_TX20_WIND_SPEED "Скорост на вятъра" +#define D_TX20_WIND_SPEED_AVG "Средна скорост на вятъра" +#define D_TX20_WIND_SPEED_MAX "Макс. скорост на вятъра" +#define D_TX20_NORTH "С" +#define D_TX20_EAST "И" +#define D_TX20_SOUTH "Ю" +#define D_TX20_WEST "З" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Няма" +#define D_SENSOR_USER "Потребит." +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 плейър" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Ключ" // Suffix "1" +#define D_SENSOR_BUTTON "Бутон" // Suffix "1" +#define D_SENSOR_RELAY "Реле" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Брояч" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Подсветка" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF датчик" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "gal/min" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "сектори" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Фазов ъгъл" +#define D_IMPORT_ACTIVE "Входна активна мощност" +#define D_EXPORT_ACTIVE "Изходна активна мощност" +#define D_IMPORT_REACTIVE "Входна реактивна мощност" +#define D_EXPORT_REACTIVE "Изходна реактивна мощност" +#define D_TOTAL_REACTIVE "Общо реактивна мощност" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "°" + +//SOLAXX1 +#define D_PV1_VOLTAGE "Напрежение на PV1" +#define D_PV1_CURRENT "Ток на PV1" +#define D_PV1_POWER "Мощност на PV1" +#define D_PV2_VOLTAGE "Напрежение на PV2" +#define D_PV2_CURRENT "Ток на PV2" +#define D_PV2_POWER "Мощност на PV2" +#define D_SOLAR_POWER "Слънчева мощност" +#define D_INVERTER_POWER "Мощност на инвертера" +#define D_STATUS "Състояние" +#define D_WAITING "Очакване" +#define D_CHECKING "Проверка" +#define D_WORKING "Работи" +#define D_FAILURE "Грешка" +#define D_SOLAX_ERROR_0 "Грешка - няма код" +#define D_SOLAX_ERROR_1 "Грешка - загуба на мрежата" +#define D_SOLAX_ERROR_2 "Грешка - мрежово напрежение" +#define D_SOLAX_ERROR_3 "Грешка - мрежова честота" +#define D_SOLAX_ERROR_4 "Грешка - напрежение на Pv" +#define D_SOLAX_ERROR_5 "Грешка - проблем с изолацията" +#define D_SOLAX_ERROR_6 "Грешка - прегряване" +#define D_SOLAX_ERROR_7 "Грешка - вентилатор" +#define D_SOLAX_ERROR_8 "Грешка - друго оборудване" + +#endif // _LANGUAGE_BG_BG_H_ diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 1d7c6f381..7579e1922 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -1,701 +1,703 @@ -/* - cs-CZ.h - localization for Czech with diacritics - Czech for Tasmota - - Copyright (C) 2019 Vladimír Synek - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_CS_CZ_H_ -#define _LANGUAGE_CS_CZ_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.5.0.9 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1029 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "cs" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "Ne Po Út St Čt Pá So " -#define D_MONTH3LIST "LedÚnoBřeDubKvěČvnČvcSrpZářŘíjLisPro" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Kvalita vzduchu" -#define D_AP "AP" // Access Point -#define D_AS "jako" -#define D_AUTO "AUTO" -#define D_BLINK "Blikání" -#define D_BLINKOFF "BlikáníVyp" -#define D_BOOT_COUNT "Počítadlo spuštění" -#define D_BRIGHTLIGHT "Světlý" -#define D_BSSID "BSSId" -#define D_BUTTON "Tlačítko" -#define D_BY "by" // Written by me -#define D_BYTES "Bytů" -#define D_CELSIUS "°C" -#define D_CHANNEL "Channel" -#define D_CO2 "CO2" -#define D_CODE "kód" // Button code -#define D_COLDLIGHT "Studené světlo" -#define D_COMMAND "Příkaz" -#define D_CONNECTED "...připojeno" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Počítej" -#define D_COUNTER "Počítadlo" -#define D_CURRENT "Proud" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Tmavý" -#define D_DEBUG "Debug" -#define D_DISABLED "Zablokováno" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "Server DNS" -#define D_DONE "Provedeno" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulace" -#define D_ENABLED "Otevřený" -#define D_ERASE "Smaž" -#define D_ERROR "Chyba" -#define D_FAHRENHEIT "Fahrenheita" -#define D_FAILED "chyba" -#define D_FALLBACK "Záložní" -#define D_FALLBACK_TOPIC "Záložní topic" -#define D_FALSE "Nepravda" -#define D_FILE "Soubor" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Volná paměť" -#define D_FREQUENCY "Kmitočet" -#define D_GAS "Plyn" -#define D_GATEWAY "Výchozí brána" -#define D_GROUP "Skupina" -#define D_HOST "Server" -#define D_HOSTNAME "Název serveru" -#define D_HUMIDITY "Vlhkost" -#define D_ILLUMINANCE "Osvětlení" -#define D_IMMEDIATE "Okamžité" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Informace" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "Inicializovaný" -#define D_IP_ADDRESS "Adresa IP" -#define D_LIGHT "Světlo" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "několikeré-stisknutí" -#define D_NOISE "Hluk" -#define D_NONE "Žádný" -#define D_OFF "Vyp." -#define D_OFFLINE "Neaktivní" -#define D_OK "OK" -#define D_ON "Zap." -#define D_ONLINE "Aktivní" -#define D_PASSWORD "Heslo" -#define D_PORT "Port" -#define D_POWER_FACTOR "Účiník" -#define D_POWERUSAGE "Příkon" -#define D_POWERUSAGE_ACTIVE "Činný příkon" -#define D_POWERUSAGE_APPARENT "Zdánlivý příkon" -#define D_POWERUSAGE_REACTIVE "Jalový příkon" -#define D_PRESSURE "Tlak" -#define D_PRESSUREATSEALEVEL "Tlak na hladině moře" -#define D_PROGRAM_FLASH_SIZE "Velikost paměti flash" -#define D_PROGRAM_SIZE "Velikost programu" -#define D_PROJECT "Projekt" -#define D_RAIN "Rain" -#define D_RECEIVED "Přijatý" -#define D_RESTART "Restart" -#define D_RESTARTING "Restartování" -#define D_RESTART_REASON "Příčina restartu" -#define D_RESTORE "Obnovit" -#define D_RETAINED "Zachováno" -#define D_RULE "Rule" -#define D_SAVE "Ulož" -#define D_SENSOR "Sensor" -#define D_SSID "SSID" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Maska podsítě" -#define D_SUBSCRIBE_TO "Přihlaš se do" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "úspěšné." -#define D_SUNRISE "Svítání" -#define D_SUNSET "Soumrak" -#define D_TEMPERATURE "Teplota" -#define D_TO "do" -#define D_TOGGLE "Přepni" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Odešli" -#define D_TRUE "Pravda" -#define D_TVOC "TVOC" -#define D_UPGRADE "aktualizace" -#define D_UPLOAD "Nahrání..." -#define D_UPTIME "Uptime" -#define D_USER "Uživatel" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Nízký" -#define D_UV_INDEX_2 "Střední" -#define D_UV_INDEX_3 "Vysoký" -#define D_UV_INDEX_4 "Nebezpečný" -#define D_UV_INDEX_5 "Popál1/2" -#define D_UV_INDEX_6 "Popál3" -#define D_UV_INDEX_7 "MimoRozsah" -#define D_UV_LEVEL "úroveň UV" -#define D_UV_POWER "UV Power" -#define D_VERSION "Verze" -#define D_VOLTAGE "Napětí" -#define D_WEIGHT "Hmotnost" -#define D_WARMLIGHT "Teplé světlo" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "UPOZORNĚNÍ Tato verze nepodporuje trvalé nastavení" -#define D_LEVEL_10 "úroveň 1-0" -#define D_LEVEL_01 "úroveň 0-1" -#define D_SERIAL_LOGGING_DISABLED "Logování na sériovém portu ukončeno" -#define D_SYSLOG_LOGGING_REENABLED "Obnoven zápis do Syslog" - -#define D_SET_BAUDRATE_TO "Nastavení rychlosti přenosu na" -#define D_RECEIVED_TOPIC "Přijatý topic" -#define D_DATA_SIZE "Velikost dat" -#define D_ANALOG_INPUT "Analogový vstup" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Zablokování smyčky" -#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig se statusem" -#define D_ACTIVE_FOR_3_MINUTES "aktivní 3 minuty" -#define D_FAILED_TO_START "nepodařilo se spustit" -#define D_PATCH_ISSUE_2186 "Chyba 2186" -#define D_CONNECTING_TO_AP "Připojování k AP" -#define D_IN_MODE "v módu" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba připojení, nebyla obdržena IP adresa" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba připojení, nedostupný AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba připojení, nesprávné heslo pro AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba připojení, uplynul AP timeout" -#define D_ATTEMPTING_CONNECTION "Připojování..." -#define D_CHECKING_CONNECTION "Zkouška spojení..." -#define D_QUERY_DONE "Vyslání dotazu. Nalezena služba MQTT" -#define D_MQTT_SERVICE_FOUND "Služba MQTT byla nalezena" -#define D_FOUND_AT "znalezeno v" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebyl nalezen" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Uloženo do paměti flash v" -#define D_LOADED_FROM_FLASH_AT "Staženo z paměti flash z" -#define D_USE_DEFAULTS "Použij defaultní hodnoty" -#define D_ERASED_SECTOR "Smazaný sektor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" -#define D_WEBSERVER_ACTIVE_ON "Aktivní Web server" -#define D_WITH_IP_ADDRESS "na IP adrese" -#define D_WEBSERVER_STOPPED "Web server zastaven" -#define D_FILE_NOT_FOUND "Soubor nebyl nalezen" -#define D_REDIRECTED "Přesměrování na vlastní portál" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manager nastaví AP a zachová STA" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manager nastaví Access Point" -#define D_TRYING_TO_CONNECT "Zkouším připojit zařízení k síti" - -#define D_RESTART_IN "Restart" -#define D_SECONDS "sekund" -#define D_DEVICE_WILL_RESTART "Zařízení bude zrestartováno během několika sekund" -#define D_BUTTON_TOGGLE "Přepínač" -#define D_CONFIGURATION "Nastavení" -#define D_INFORMATION "Informace" -#define D_FIRMWARE_UPGRADE "Aktualizace firmware" -#define D_CONSOLE "Konzole" -#define D_CONFIRM_RESTART "Potvrzení restartu" - -#define D_CONFIGURE_MODULE "Nastavení modulu" -#define D_CONFIGURE_WIFI "Nastavení WiFi" -#define D_CONFIGURE_MQTT "Nastavení MQTT" -#define D_CONFIGURE_DOMOTICZ "Nastavení Domoticz" -#define D_CONFIGURE_LOGGING "Nastavení logování" -#define D_CONFIGURE_OTHER "Jiná nastavení" -#define D_CONFIRM_RESET_CONFIGURATION "Potvrzení resetu nastavení" -#define D_RESET_CONFIGURATION "Reset nastavení" -#define D_BACKUP_CONFIGURATION "Záloha nastavení" -#define D_RESTORE_CONFIGURATION "Obnovení nastavení" -#define D_MAIN_MENU "Hlavní menu" - -#define D_MODULE_PARAMETERS "Nastavení modulu" -#define D_MODULE_TYPE "Typ modulu" -#define D_PULLUP_ENABLE "Tlačítko/Spínač bez pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Nastavení WiFi" -#define D_SCAN_FOR_WIFI_NETWORKS "Scan sítí WiFi" -#define D_SCAN_DONE "Scan dokončen" -#define D_NO_NETWORKS_FOUND "Síť nebyla nalezena" -#define D_REFRESH_TO_SCAN_AGAIN "Zopakovat scan" -#define D_DUPLICATE_ACCESSPOINT "Kopie AP" -#define D_SKIPPING_LOW_QUALITY "Přeskočení z důvodu kvality signálu" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "Heslo AP1" -#define D_AP2_SSID "AP2 SSID" -#define D_AP2_PASSWORD "Heslo AP2" - -#define D_MQTT_PARAMETERS "Nastavení MQTT" -#define D_CLIENT "Klient" -#define D_FULL_TOPIC "Celý topic" - -#define D_LOGGING_PARAMETERS "Volba logování" -#define D_SERIAL_LOG_LEVEL "Seriová úroveň logu" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Webová úroveň logu" -#define D_SYS_LOG_LEVEL "Systemová úroveň logu" -#define D_MORE_DEBUG "Více debug informací" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Interval telemetrie" - -#define D_OTHER_PARAMETERS "Další nastavení" -#define D_TEMPLATE "Šablona" -#define D_ACTIVATE "Aktivovat" -#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" -#define D_MQTT_ENABLE "MQTT aktivní" -#define D_FRIENDLY_NAME "Friendly Name" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "Nastavení šablony" -#define D_TEMPLATE_PARAMETERS "Parametry šablony" -#define D_TEMPLATE_NAME "Název" -#define D_BASE_TYPE "Vzor z" -#define D_TEMPLATE_FLAGS "Volby" - -#define D_SAVE_CONFIGURATION "Ulož nastavení" -#define D_CONFIGURATION_SAVED "Nastavení uloženo" -#define D_CONFIGURATION_RESET "Nastavení resetováno" - -#define D_PROGRAM_VERSION "Verze programu" -#define D_BUILD_DATE_AND_TIME "Datum a čas kompilace" -#define D_CORE_AND_SDK_VERSION "Verze Core/SDK" -#define D_FLASH_WRITE_COUNT "Počet zápisů do paměti" -#define D_MAC_ADDRESS "Adresa MAC" -#define D_MQTT_HOST "Host MQTT" -#define D_MQTT_PORT "Port MQTT" -#define D_MQTT_CLIENT "Klient MQTT" -#define D_MQTT_USER "Uživatel MQTT" -#define D_MQTT_TOPIC "Topic MQTT" -#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT" -#define D_MQTT_FULL_TOPIC "Celý topic MQTT" -#define D_MDNS_DISCOVERY "Získávání mDNS" -#define D_MDNS_ADVERTISE "Rozesílání mDNS" -#define D_ESP_CHIP_ID "ID systému ESP" -#define D_FLASH_CHIP_ID "ID systému paměti flash" -#define D_FLASH_CHIP_SIZE "Velikost flash" -#define D_FREE_PROGRAM_SPACE "Volné místo pro program" - -#define D_UPGRADE_BY_WEBSERVER "Aktualizace z Web serveru" -#define D_OTA_URL "URL OTA" -#define D_START_UPGRADE "Start aktualizace" -#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizace nahráním souboru" -#define D_UPLOAD_STARTED "Nahrávání zahájeno" -#define D_UPGRADE_STARTED "Zahájení aktualizace" -#define D_UPLOAD_DONE "Nahrávání ukončeno" -#define D_UPLOAD_ERR_1 "Soubor nebyl vybrán" -#define D_UPLOAD_ERR_2 "Málo místa" -#define D_UPLOAD_ERR_3 "Magický byte má hodnotu jinou než 0xE9" -#define D_UPLOAD_ERR_4 "Velikost programu je větší než skutečná velikost paměti flash" -#define D_UPLOAD_ERR_5 "Chyba nahrávání, nesouhlasí porovnávané bity" -#define D_UPLOAD_ERR_6 "Chyba nahrávání. Spuštěn zápis do logu na úrovni 3" -#define D_UPLOAD_ERR_7 "Nahrávání přerušeno" -#define D_UPLOAD_ERR_8 "Špatný soubor" -#define D_UPLOAD_ERR_9 "Soubor je příliš velký" -#define D_UPLOAD_ERR_10 "Chyba inicializace RF chipu" -#define D_UPLOAD_ERR_11 "Chyba smazání RF chipu" -#define D_UPLOAD_ERR_12 "Chyba při zápisu do RF chipu" -#define D_UPLOAD_ERR_13 "Chyba dekódování RF firmwaru" -#define D_UPLOAD_ERROR_CODE "Chyba nahrávání" - -#define D_ENTER_COMMAND "Vlož příkaz" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni úroveň 2 zápisu Weblog, pokud je očekávána odpověď" -#define D_NEED_USER_AND_PASSWORD "Vyžadován uživatel=&heslo=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifikuj otisk TLS..." -#define D_TLS_CONNECT_FAILED_TO "Nepřipojeno TLS do" -#define D_RETRY_IN "Zopakuji za" -#define D_VERIFIED "Ověřeno otisk " -#define D_INSECURE "Nesprávné připojení z důvodu chybného otisku TLS" -#define D_CONNECT_FAILED_TO "Spojení se nepodařilo navázat" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast je vypnutý" -#define D_MULTICAST_REJOINED "Multicast opět připojený" -#define D_MULTICAST_JOIN_FAILED "Multicast neúspěšný" -#define D_FAILED_TO_SEND_RESPONSE "Nepodařilo se odeslat odpověď" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo základní událost" -#define D_WEMO_EVENT_SERVICE "WeMo servisní událost" -#define D_WEMO_META_SERVICE "WeMo meta událost" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Odpověď odeslána" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API není implementováno" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovědi odeslány" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Nastavení Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Spinac idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak" - #define D_DOMOTICZ_POWER_ENERGY "Příkon,Energie" - #define D_DOMOTICZ_ILLUMINANCE "Osvětlení" - #define D_DOMOTICZ_COUNT "Počítadlo/PM1" - #define D_DOMOTICZ_VOLTAGE "Napětí/PM2,5" - #define D_DOMOTICZ_CURRENT "Proud/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Aktualizace stopek" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Nastavení Časovače" -#define D_TIMER_PARAMETERS "Časovač" -#define D_TIMER_ENABLE "Povol časovače" -#define D_TIMER_ARM "Aktivní" -#define D_TIMER_TIME "Čas" -#define D_TIMER_DAYS "Dny" -#define D_TIMER_REPEAT "Opakovat" -#define D_TIMER_OUTPUT "Výstup" -#define D_TIMER_ACTION "Napájení" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Nastavení KNX" -#define D_KNX_PARAMETERS "KNX parametry" -#define D_KNX_GENERAL_CONFIG "Obecné" -#define D_KNX_PHYSICAL_ADDRESS "Fyzická adresa" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musí být jedinečná v síti KNX )" -#define D_KNX_ENABLE "Povol KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data k odeslání na skupinové adresy" -#define D_ADD "Přidej" -#define D_DELETE "Smaž" -#define D_REPLY "Odpověď" -#define D_KNX_GROUP_ADDRESS_TO_READ "Skupinové adresy pro příjem dat z" -#define D_RECEIVED_FROM "Přijato z" -#define D_KNX_COMMAND_WRITE "Zapiš" -#define D_KNX_COMMAND_READ "Čti" -#define D_KNX_COMMAND_OTHER "Jiné" -#define D_SENT_TO "pošli" -#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervována a nemůže být použita." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Spotřeba Dnes" -#define D_ENERGY_YESTERDAY "Spotřeba Včera" -#define D_ENERGY_TOTAL "Celková spotřeba" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor DS18x20 obsazen" -#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" -#define D_SENSORS_FOUND "Nalezen sensor DS18x20" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Čekání na" -#define D_START_SIGNAL_LOW "nízký startovní signál" -#define D_START_SIGNAL_HIGH "vysoký startovní signál" -#define D_PULSE "impuls" -#define D_CHECKSUM_FAILURE "Chybný kontrolní součet" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor neobdržel příkaz ACK" -#define D_SHT1X_FOUND "SHT1X nalezen" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "částic" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. osa-X" -#define D_AY_AXIS "Accel. osa-Y" -#define D_AZ_AXIS "Accel. osa-Z" -#define D_GX_AXIS "Gyro osa-X" -#define D_GY_AXIS "Gyro osa-Y" -#define D_GZ_AXIS "Gyro osa-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Odstraňte zátěž" -#define D_HX_CAL_REFERENCE "Vložte referenční zátěž" -#define D_HX_CAL_DONE "Zkalibrováno" -#define D_HX_CAL_FAIL "Chyba kalibrace" -#define D_RESET_HX711 "Reset váhy" -#define D_CONFIGURE_HX711 "Konfigurace váhy" -#define D_HX711_PARAMETERS "Parametry váhy" -#define D_ITEM_WEIGHT "Vlastní hmotnost" -#define D_REFERENCE_WEIGHT "Referenční hmotnost" -#define D_CALIBRATE "Kalibruj" -#define D_CALIBRATION "Kalibrace" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Směr větru" -#define D_TX20_WIND_SPEED "Rychlost větru" -#define D_TX20_WIND_SPEED_AVG "Průměrná rychlost větru" -#define D_TX20_WIND_SPEED_MAX "Maximální rychlost větru" -#define D_TX20_NORTH "S" -#define D_TX20_EAST "V" -#define D_TX20_SOUTH "J" -#define D_TX20_WEST "Z" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Není" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Spínač" // Suffix "1" -#define D_SENSOR_BUTTON "Tlačítko" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1", -#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "hod" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sektory" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_CS_CZ_H_ +/* + cs-CZ.h - localization for Czech with diacritics - Czech for Tasmota + + Copyright (C) 2019 Vladimír Synek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_CS_CZ_H_ +#define _LANGUAGE_CS_CZ_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.5.0.9 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1029 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "cs" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "Ne Po Út St Čt Pá So " +#define D_MONTH3LIST "LedÚnoBřeDubKvěČvnČvcSrpZářŘíjLisPro" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Kvalita vzduchu" +#define D_AP "AP" // Access Point +#define D_AS "jako" +#define D_AUTO "AUTO" +#define D_BLINK "Blikání" +#define D_BLINKOFF "BlikáníVyp" +#define D_BOOT_COUNT "Počítadlo spuštění" +#define D_BRIGHTLIGHT "Světlý" +#define D_BSSID "BSSId" +#define D_BUTTON "Tlačítko" +#define D_BY "by" // Written by me +#define D_BYTES "Bytů" +#define D_CELSIUS "°C" +#define D_CHANNEL "Channel" +#define D_CO2 "CO2" +#define D_CODE "kód" // Button code +#define D_COLDLIGHT "Studené světlo" +#define D_COMMAND "Příkaz" +#define D_CONNECTED "...připojeno" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Počítej" +#define D_COUNTER "Počítadlo" +#define D_CURRENT "Proud" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Tmavý" +#define D_DEBUG "Debug" +#define D_DISABLED "Zablokováno" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "Server DNS" +#define D_DONE "Provedeno" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulace" +#define D_ENABLED "Otevřený" +#define D_ERASE "Smaž" +#define D_ERROR "Chyba" +#define D_FAHRENHEIT "Fahrenheita" +#define D_FAILED "chyba" +#define D_FALLBACK "Záložní" +#define D_FALLBACK_TOPIC "Záložní topic" +#define D_FALSE "Nepravda" +#define D_FILE "Soubor" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Volná paměť" +#define D_FREQUENCY "Kmitočet" +#define D_GAS "Plyn" +#define D_GATEWAY "Výchozí brána" +#define D_GROUP "Skupina" +#define D_HOST "Server" +#define D_HOSTNAME "Název serveru" +#define D_HUMIDITY "Vlhkost" +#define D_ILLUMINANCE "Osvětlení" +#define D_IMMEDIATE "Okamžité" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Informace" +#define D_INFRARED "Infrared" +#define D_INITIALIZED "Inicializovaný" +#define D_IP_ADDRESS "Adresa IP" +#define D_LIGHT "Světlo" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "několikeré-stisknutí" +#define D_NOISE "Hluk" +#define D_NONE "Žádný" +#define D_OFF "Vyp." +#define D_OFFLINE "Neaktivní" +#define D_OK "OK" +#define D_ON "Zap." +#define D_ONLINE "Aktivní" +#define D_PASSWORD "Heslo" +#define D_PORT "Port" +#define D_POWER_FACTOR "Účiník" +#define D_POWERUSAGE "Příkon" +#define D_POWERUSAGE_ACTIVE "Činný příkon" +#define D_POWERUSAGE_APPARENT "Zdánlivý příkon" +#define D_POWERUSAGE_REACTIVE "Jalový příkon" +#define D_PRESSURE "Tlak" +#define D_PRESSUREATSEALEVEL "Tlak na hladině moře" +#define D_PROGRAM_FLASH_SIZE "Velikost paměti flash" +#define D_PROGRAM_SIZE "Velikost programu" +#define D_PROJECT "Projekt" +#define D_RAIN "Rain" +#define D_RECEIVED "Přijatý" +#define D_RESTART "Restart" +#define D_RESTARTING "Restartování" +#define D_RESTART_REASON "Příčina restartu" +#define D_RESTORE "Obnovit" +#define D_RETAINED "Zachováno" +#define D_RULE "Rule" +#define D_SAVE "Ulož" +#define D_SENSOR "Sensor" +#define D_SSID "SSID" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maska podsítě" +#define D_SUBSCRIBE_TO "Přihlaš se do" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "úspěšné." +#define D_SUNRISE "Svítání" +#define D_SUNSET "Soumrak" +#define D_TEMPERATURE "Teplota" +#define D_TO "do" +#define D_TOGGLE "Přepni" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Odešli" +#define D_TRUE "Pravda" +#define D_TVOC "TVOC" +#define D_UPGRADE "aktualizace" +#define D_UPLOAD "Nahrání..." +#define D_UPTIME "Uptime" +#define D_USER "Uživatel" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Nízký" +#define D_UV_INDEX_2 "Střední" +#define D_UV_INDEX_3 "Vysoký" +#define D_UV_INDEX_4 "Nebezpečný" +#define D_UV_INDEX_5 "Popál1/2" +#define D_UV_INDEX_6 "Popál3" +#define D_UV_INDEX_7 "MimoRozsah" +#define D_UV_LEVEL "úroveň UV" +#define D_UV_POWER "UV Power" +#define D_VERSION "Verze" +#define D_VOLTAGE "Napětí" +#define D_WEIGHT "Hmotnost" +#define D_WARMLIGHT "Teplé světlo" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "UPOZORNĚNÍ Tato verze nepodporuje trvalé nastavení" +#define D_LEVEL_10 "úroveň 1-0" +#define D_LEVEL_01 "úroveň 0-1" +#define D_SERIAL_LOGGING_DISABLED "Logování na sériovém portu ukončeno" +#define D_SYSLOG_LOGGING_REENABLED "Obnoven zápis do Syslog" + +#define D_SET_BAUDRATE_TO "Nastavení rychlosti přenosu na" +#define D_RECEIVED_TOPIC "Přijatý topic" +#define D_DATA_SIZE "Velikost dat" +#define D_ANALOG_INPUT "Analogový vstup" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Zablokování smyčky" +#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig se statusem" +#define D_ACTIVE_FOR_3_MINUTES "aktivní 3 minuty" +#define D_FAILED_TO_START "nepodařilo se spustit" +#define D_PATCH_ISSUE_2186 "Chyba 2186" +#define D_CONNECTING_TO_AP "Připojování k AP" +#define D_IN_MODE "v módu" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba připojení, nebyla obdržena IP adresa" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba připojení, nedostupný AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba připojení, nesprávné heslo pro AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba připojení, uplynul AP timeout" +#define D_ATTEMPTING_CONNECTION "Připojování..." +#define D_CHECKING_CONNECTION "Zkouška spojení..." +#define D_QUERY_DONE "Vyslání dotazu. Nalezena služba MQTT" +#define D_MQTT_SERVICE_FOUND "Služba MQTT byla nalezena" +#define D_FOUND_AT "znalezeno v" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebyl nalezen" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Uloženo do paměti flash v" +#define D_LOADED_FROM_FLASH_AT "Staženo z paměti flash z" +#define D_USE_DEFAULTS "Použij defaultní hodnoty" +#define D_ERASED_SECTOR "Smazaný sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" +#define D_WEBSERVER_ACTIVE_ON "Aktivní Web server" +#define D_WITH_IP_ADDRESS "na IP adrese" +#define D_WEBSERVER_STOPPED "Web server zastaven" +#define D_FILE_NOT_FOUND "Soubor nebyl nalezen" +#define D_REDIRECTED "Přesměrování na vlastní portál" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manager nastaví AP a zachová STA" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manager nastaví Access Point" +#define D_TRYING_TO_CONNECT "Zkouším připojit zařízení k síti" + +#define D_RESTART_IN "Restart" +#define D_SECONDS "sekund" +#define D_DEVICE_WILL_RESTART "Zařízení bude zrestartováno během několika sekund" +#define D_BUTTON_TOGGLE "Přepínač" +#define D_CONFIGURATION "Nastavení" +#define D_INFORMATION "Informace" +#define D_FIRMWARE_UPGRADE "Aktualizace firmware" +#define D_CONSOLE "Konzole" +#define D_CONFIRM_RESTART "Potvrzení restartu" + +#define D_CONFIGURE_MODULE "Nastavení modulu" +#define D_CONFIGURE_WIFI "Nastavení WiFi" +#define D_CONFIGURE_MQTT "Nastavení MQTT" +#define D_CONFIGURE_DOMOTICZ "Nastavení Domoticz" +#define D_CONFIGURE_LOGGING "Nastavení logování" +#define D_CONFIGURE_OTHER "Jiná nastavení" +#define D_CONFIRM_RESET_CONFIGURATION "Potvrzení resetu nastavení" +#define D_RESET_CONFIGURATION "Reset nastavení" +#define D_BACKUP_CONFIGURATION "Záloha nastavení" +#define D_RESTORE_CONFIGURATION "Obnovení nastavení" +#define D_MAIN_MENU "Hlavní menu" + +#define D_MODULE_PARAMETERS "Nastavení modulu" +#define D_MODULE_TYPE "Typ modulu" +#define D_PULLUP_ENABLE "Tlačítko/Spínač bez pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Nastavení WiFi" +#define D_SCAN_FOR_WIFI_NETWORKS "Scan sítí WiFi" +#define D_SCAN_DONE "Scan dokončen" +#define D_NO_NETWORKS_FOUND "Síť nebyla nalezena" +#define D_REFRESH_TO_SCAN_AGAIN "Zopakovat scan" +#define D_DUPLICATE_ACCESSPOINT "Kopie AP" +#define D_SKIPPING_LOW_QUALITY "Přeskočení z důvodu kvality signálu" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "Heslo AP1" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "Heslo AP2" + +#define D_MQTT_PARAMETERS "Nastavení MQTT" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Celý topic" + +#define D_LOGGING_PARAMETERS "Volba logování" +#define D_SERIAL_LOG_LEVEL "Seriová úroveň logu" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Webová úroveň logu" +#define D_SYS_LOG_LEVEL "Systemová úroveň logu" +#define D_MORE_DEBUG "Více debug informací" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Interval telemetrie" + +#define D_OTHER_PARAMETERS "Další nastavení" +#define D_TEMPLATE "Šablona" +#define D_ACTIVATE "Aktivovat" +#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" +#define D_MQTT_ENABLE "MQTT aktivní" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "Nastavení šablony" +#define D_TEMPLATE_PARAMETERS "Parametry šablony" +#define D_TEMPLATE_NAME "Název" +#define D_BASE_TYPE "Vzor z" +#define D_TEMPLATE_FLAGS "Volby" + +#define D_SAVE_CONFIGURATION "Ulož nastavení" +#define D_CONFIGURATION_SAVED "Nastavení uloženo" +#define D_CONFIGURATION_RESET "Nastavení resetováno" + +#define D_PROGRAM_VERSION "Verze programu" +#define D_BUILD_DATE_AND_TIME "Datum a čas kompilace" +#define D_CORE_AND_SDK_VERSION "Verze Core/SDK" +#define D_FLASH_WRITE_COUNT "Počet zápisů do paměti" +#define D_MAC_ADDRESS "Adresa MAC" +#define D_MQTT_HOST "Host MQTT" +#define D_MQTT_PORT "Port MQTT" +#define D_MQTT_CLIENT "Klient MQTT" +#define D_MQTT_USER "Uživatel MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT" +#define D_MQTT_FULL_TOPIC "Celý topic MQTT" +#define D_MDNS_DISCOVERY "Získávání mDNS" +#define D_MDNS_ADVERTISE "Rozesílání mDNS" +#define D_ESP_CHIP_ID "ID systému ESP" +#define D_FLASH_CHIP_ID "ID systému paměti flash" +#define D_FLASH_CHIP_SIZE "Velikost flash" +#define D_FREE_PROGRAM_SPACE "Volné místo pro program" + +#define D_UPGRADE_BY_WEBSERVER "Aktualizace z Web serveru" +#define D_OTA_URL "URL OTA" +#define D_START_UPGRADE "Start aktualizace" +#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizace nahráním souboru" +#define D_UPLOAD_STARTED "Nahrávání zahájeno" +#define D_UPGRADE_STARTED "Zahájení aktualizace" +#define D_UPLOAD_DONE "Nahrávání ukončeno" +#define D_UPLOAD_ERR_1 "Soubor nebyl vybrán" +#define D_UPLOAD_ERR_2 "Málo místa" +#define D_UPLOAD_ERR_3 "Magický byte má hodnotu jinou než 0xE9" +#define D_UPLOAD_ERR_4 "Velikost programu je větší než skutečná velikost paměti flash" +#define D_UPLOAD_ERR_5 "Chyba nahrávání, nesouhlasí porovnávané bity" +#define D_UPLOAD_ERR_6 "Chyba nahrávání. Spuštěn zápis do logu na úrovni 3" +#define D_UPLOAD_ERR_7 "Nahrávání přerušeno" +#define D_UPLOAD_ERR_8 "Špatný soubor" +#define D_UPLOAD_ERR_9 "Soubor je příliš velký" +#define D_UPLOAD_ERR_10 "Chyba inicializace RF chipu" +#define D_UPLOAD_ERR_11 "Chyba smazání RF chipu" +#define D_UPLOAD_ERR_12 "Chyba při zápisu do RF chipu" +#define D_UPLOAD_ERR_13 "Chyba dekódování RF firmwaru" +#define D_UPLOAD_ERROR_CODE "Chyba nahrávání" + +#define D_ENTER_COMMAND "Vlož příkaz" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni úroveň 2 zápisu Weblog, pokud je očekávána odpověď" +#define D_NEED_USER_AND_PASSWORD "Vyžadován uživatel=&heslo=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifikuj otisk TLS..." +#define D_TLS_CONNECT_FAILED_TO "Nepřipojeno TLS do" +#define D_RETRY_IN "Zopakuji za" +#define D_VERIFIED "Ověřeno otisk " +#define D_INSECURE "Nesprávné připojení z důvodu chybného otisku TLS" +#define D_CONNECT_FAILED_TO "Spojení se nepodařilo navázat" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast je vypnutý" +#define D_MULTICAST_REJOINED "Multicast opět připojený" +#define D_MULTICAST_JOIN_FAILED "Multicast neúspěšný" +#define D_FAILED_TO_SEND_RESPONSE "Nepodařilo se odeslat odpověď" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo základní událost" +#define D_WEMO_EVENT_SERVICE "WeMo servisní událost" +#define D_WEMO_META_SERVICE "WeMo meta událost" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Odpověď odeslána" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API není implementováno" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovědi odeslány" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Nastavení Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Spinac idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak" + #define D_DOMOTICZ_POWER_ENERGY "Příkon,Energie" + #define D_DOMOTICZ_ILLUMINANCE "Osvětlení" + #define D_DOMOTICZ_COUNT "Počítadlo/PM1" + #define D_DOMOTICZ_VOLTAGE "Napětí/PM2,5" + #define D_DOMOTICZ_CURRENT "Proud/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Aktualizace stopek" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Nastavení Časovače" +#define D_TIMER_PARAMETERS "Časovač" +#define D_TIMER_ENABLE "Povol časovače" +#define D_TIMER_ARM "Aktivní" +#define D_TIMER_TIME "Čas" +#define D_TIMER_DAYS "Dny" +#define D_TIMER_REPEAT "Opakovat" +#define D_TIMER_OUTPUT "Výstup" +#define D_TIMER_ACTION "Napájení" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Nastavení KNX" +#define D_KNX_PARAMETERS "KNX parametry" +#define D_KNX_GENERAL_CONFIG "Obecné" +#define D_KNX_PHYSICAL_ADDRESS "Fyzická adresa" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musí být jedinečná v síti KNX )" +#define D_KNX_ENABLE "Povol KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data k odeslání na skupinové adresy" +#define D_ADD "Přidej" +#define D_DELETE "Smaž" +#define D_REPLY "Odpověď" +#define D_KNX_GROUP_ADDRESS_TO_READ "Skupinové adresy pro příjem dat z" +#define D_RECEIVED_FROM "Přijato z" +#define D_KNX_COMMAND_WRITE "Zapiš" +#define D_KNX_COMMAND_READ "Čti" +#define D_KNX_COMMAND_OTHER "Jiné" +#define D_SENT_TO "pošli" +#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervována a nemůže být použita." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Spotřeba Dnes" +#define D_ENERGY_YESTERDAY "Spotřeba Včera" +#define D_ENERGY_TOTAL "Celková spotřeba" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor DS18x20 obsazen" +#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" +#define D_SENSORS_FOUND "Nalezen sensor DS18x20" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Čekání na" +#define D_START_SIGNAL_LOW "nízký startovní signál" +#define D_START_SIGNAL_HIGH "vysoký startovní signál" +#define D_PULSE "impuls" +#define D_CHECKSUM_FAILURE "Chybný kontrolní součet" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor neobdržel příkaz ACK" +#define D_SHT1X_FOUND "SHT1X nalezen" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "částic" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. osa-X" +#define D_AY_AXIS "Accel. osa-Y" +#define D_AZ_AXIS "Accel. osa-Z" +#define D_GX_AXIS "Gyro osa-X" +#define D_GY_AXIS "Gyro osa-Y" +#define D_GZ_AXIS "Gyro osa-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Odstraňte zátěž" +#define D_HX_CAL_REFERENCE "Vložte referenční zátěž" +#define D_HX_CAL_DONE "Zkalibrováno" +#define D_HX_CAL_FAIL "Chyba kalibrace" +#define D_RESET_HX711 "Reset váhy" +#define D_CONFIGURE_HX711 "Konfigurace váhy" +#define D_HX711_PARAMETERS "Parametry váhy" +#define D_ITEM_WEIGHT "Vlastní hmotnost" +#define D_REFERENCE_WEIGHT "Referenční hmotnost" +#define D_CALIBRATE "Kalibruj" +#define D_CALIBRATION "Kalibrace" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Směr větru" +#define D_TX20_WIND_SPEED "Rychlost větru" +#define D_TX20_WIND_SPEED_AVG "Průměrná rychlost větru" +#define D_TX20_WIND_SPEED_MAX "Maximální rychlost větru" +#define D_TX20_NORTH "S" +#define D_TX20_EAST "V" +#define D_TX20_SOUTH "J" +#define D_TX20_WEST "Z" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Není" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Spínač" // Suffix "1" +#define D_SENSOR_BUTTON "Tlačítko" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1", +#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "hod" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sektory" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_CS_CZ_H_ diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 6569dd232..d4e434e0c 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -1,701 +1,703 @@ -/* - de-DE.h - localization for German - Germany for Tasmota - - Copyright (C) 2019 VinceMasuka - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_DE_DE_H_ -#define _LANGUAGE_DE_DE_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.6.0.21 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1031 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "de" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "." -#define D_MONTH_DAY_SEPARATOR "." -#define D_DATE_TIME_SEPARATOR " " -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "So Mo Di Mi Do Fr Sa " -#define D_MONTH3LIST "JanFebMärAprMaiJunJulAugSepOktNovDez" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Luftqualität" -#define D_AP "AP" // Access Point -#define D_AS "als" -#define D_AUTO "AUTO" -#define D_BLINK "Blinken" -#define D_BLINKOFF "BlinkenAus" -#define D_BOOT_COUNT "Anzahl Startvorgänge" -#define D_BRIGHTLIGHT "hell" -#define D_BSSID "BSSId" -#define D_BUTTON "Knopf" -#define D_BY "von" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Kanal" -#define D_CO2 "CO²" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "kalt" -#define D_COMMAND "Befehl" -#define D_CONNECTED "verbunden" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "zählen" -#define D_COUNTER "Zähler" -#define D_CURRENT "Strom" // As in Voltage and Current -#define D_DATA "Daten" -#define D_DARKLIGHT "dunkel" -#define D_DEBUG "debug" -#define D_DISABLED "deaktiviert" -#define D_DISTANCE "Abstand" -#define D_DNS_SERVER "DNS-Server" -#define D_DONE "erledigt" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulation" -#define D_ENABLED "aktiviert" -#define D_ERASE "löschen" -#define D_ERROR "Fehler" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "fehlgeschlagen" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback-Topic" -#define D_FALSE "falsch" -#define D_FILE "Datei" -#define D_FLOW_RATE "Durchflussmenge" -#define D_FREE_MEMORY "Freier Arbeitsspeicher" -#define D_FREQUENCY "Frequenz" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Gruppe" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" -#define D_HUMIDITY "Feuchtigkeit" -#define D_ILLUMINANCE "Beleuchtungsintensität" -#define D_IMMEDIATE "direkt" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infrarot" -#define D_INITIALIZED "initialisiert" -#define D_IP_ADDRESS "IP-Adresse" -#define D_LIGHT "Licht" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "Mehrfachdruck" -#define D_NOISE "Lautstärke" -#define D_NONE "keine" -#define D_OFF "aus" -#define D_OFFLINE "Offline" -#define D_OK "OK" -#define D_ON "an" -#define D_ONLINE "Online" -#define D_PASSWORD "Passwort" -#define D_PORT "Port" -#define D_POWER_FACTOR "Leistungsfaktor" -#define D_POWERUSAGE "Leistung" -#define D_POWERUSAGE_ACTIVE "Wirkleistung" -#define D_POWERUSAGE_APPARENT "Scheinleistung" -#define D_POWERUSAGE_REACTIVE "Blindleistung" -#define D_PRESSURE "Luftdruck" -#define D_PRESSUREATSEALEVEL "Luftdruck auf Meereshöhe" -#define D_PROGRAM_FLASH_SIZE "Ges. Flash Speicher" -#define D_PROGRAM_SIZE "Ben. Flash Speicher" -#define D_PROJECT "Projekt" -#define D_RAIN "Regen" -#define D_RECEIVED "erhalten" -#define D_RESTART "Neustart" -#define D_RESTARTING "starte neu" -#define D_RESTART_REASON "Grund für Neustart" -#define D_RESTORE "Wiederherstellung" -#define D_RETAINED "beibehalten" -#define D_RULE "Regel" -#define D_SAVE "Speichern" -#define D_SENSOR "Sensor" -#define D_SSID "SSID" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Subnetzmaske" -#define D_SUBSCRIBE_TO "abonniere" -#define D_UNSUBSCRIBE_FROM "löse abo. von" -#define D_SUCCESSFUL "erfolgreich" -#define D_SUNRISE "Sonnenaufgang" -#define D_SUNSET "Sonnenuntergang" -#define D_TEMPERATURE "Temperatur" -#define D_TO "zu" -#define D_TOGGLE "An/Aus" -#define D_TOPIC "topic" -#define D_TOTAL_USAGE "Gesamtverbrauch" -#define D_TRANSMIT "Übertragen" -#define D_TRUE "wahr" -#define D_TVOC "TVOC" -#define D_UPGRADE "update" -#define D_UPLOAD "Upload" -#define D_UPTIME "Laufzeit" -#define D_USER "Benutzer" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV-Index" -#define D_UV_INDEX_1 "Niedrig" -#define D_UV_INDEX_2 "Mittel" -#define D_UV_INDEX_3 "Hoch" -#define D_UV_INDEX_4 "Intensiv" -#define D_UV_INDEX_5 "Gefährlich" -#define D_UV_INDEX_6 "Schädlich" -#define D_UV_INDEX_7 "Messwert!" -#define D_UV_LEVEL "UV-Level" -#define D_UV_POWER "UV Intensität" -#define D_VERSION "Version" -#define D_VOLTAGE "Spannung" -#define D_WEIGHT "Gewicht" -#define D_WARMLIGHT "warm" -#define D_WEB_SERVER "Web-Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ACHTUNG: Diese Version unterstützt keine persistenten Einstellungen" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serielles Logging deaktiviert" -#define D_SYSLOG_LOGGING_REENABLED "Syslog-Logging aktiviert" - -#define D_SET_BAUDRATE_TO "Setze Baudrate auf" -#define D_RECEIVED_TOPIC "empfangenes topic" -#define D_DATA_SIZE "Datengröße" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Schleife blockiert." -#define D_WPS_FAILED_WITH_STATUS "WPS fehlgeschlagen mit Status" -#define D_ACTIVE_FOR_3_MINUTES "aktiv für 3 Minuten" -#define D_FAILED_TO_START "Starten fehlgeschlagen" -#define D_PATCH_ISSUE_2186 "Repariere Problem #2186" -#define D_CONNECTING_TO_AP "verbinden mit AP" -#define D_IN_MODE "in Modus" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbindung fehlgeschlagen, da keine IP-Adresse zugeteilt wurde" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbindung fehlgeschlagen, da AP nicht erreicht werden konnte" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbindung fehlgeschlagen, da das Passwort falsch ist" -#define D_CONNECT_FAILED_AP_TIMEOUT "Verbindung fehlgeschlagen, da der AP nicht antwortet (timeout)" -#define D_ATTEMPTING_CONNECTION "Verbindungsversuch..." -#define D_CHECKING_CONNECTION "Prüfe Verbindung..." -#define D_QUERY_DONE "Suchanfrage abgeschlossen. MQTT-Services gefunden" -#define D_MQTT_SERVICE_FOUND "MQTT-Service gefunden bei" -#define D_FOUND_AT "gefunden bei" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog-Host nicht gefunden" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "in Flash gespeichert am" -#define D_LOADED_FROM_FLASH_AT "aus Flash geladen am" -#define D_USE_DEFAULTS "Standard verwenden" -#define D_ERASED_SECTOR "gelöschter Sektor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware
bitte upgraden" -#define D_WEBSERVER_ACTIVE_ON "Web-Server aktiv bei" -#define D_WITH_IP_ADDRESS "mit IP-Adresse" -#define D_WEBSERVER_STOPPED "Web-Server angehalten" -#define D_FILE_NOT_FOUND "Datei nicht gefunden" -#define D_REDIRECTED "umgeleitet zu captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WLAN-Manager AccessPoint gesetzt und behält Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "WLAN-Manager AccessPoint gesetzt" -#define D_TRYING_TO_CONNECT "Versuche Gerät mit Netzwerk zu verbinden" - -#define D_RESTART_IN "Neustart in" -#define D_SECONDS "Sekunden" -#define D_DEVICE_WILL_RESTART "Gerät wird jetzt neu gestartet" -#define D_BUTTON_TOGGLE "An/Aus" -#define D_CONFIGURATION "Einstellungen" -#define D_INFORMATION "Informationen" -#define D_FIRMWARE_UPGRADE "Firmware Update" -#define D_CONSOLE "Konsole" -#define D_CONFIRM_RESTART "Wirklich neustarten?" - -#define D_CONFIGURE_MODULE "Gerät konfigurieren" -#define D_CONFIGURE_WIFI "WLAN konfigurieren" -#define D_CONFIGURE_MQTT "MQTT konfigurieren" -#define D_CONFIGURE_DOMOTICZ "Domoticz konfigurieren" -#define D_CONFIGURE_LOGGING "Logging konfigurieren" -#define D_CONFIGURE_OTHER "Sonstige Konfiguration" -#define D_CONFIRM_RESET_CONFIGURATION "Zurücksetzen der Konfiguration bestätigen" -#define D_RESET_CONFIGURATION "Konfiguration zurücksetzen" -#define D_BACKUP_CONFIGURATION "Konfiguration sichern" -#define D_RESTORE_CONFIGURATION "Konfiguration wiederherstellen" -#define D_MAIN_MENU "Hauptmenü" - -#define D_MODULE_PARAMETERS "Geräte-Einstellungen" -#define D_MODULE_TYPE "Gerätetyp" -#define D_PULLUP_ENABLE "Kein Taster/Schalter Pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "serieller Eingang [serial in]" -#define D_SERIAL_OUT "serieller Ausgang [serial out]" - -#define D_WIFI_PARAMETERS "WLAN-Einstellungen" -#define D_SCAN_FOR_WIFI_NETWORKS "WLAN-Netzwerk suchen und auswählen" -#define D_SCAN_DONE "Suche abgeschlossen" -#define D_NO_NETWORKS_FOUND "Keine Netzwerke gefunden" -#define D_REFRESH_TO_SCAN_AGAIN "Aktualisieren, um erneut zu suchen" -#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplizieren" -#define D_SKIPPING_LOW_QUALITY "überspringe wegen niedriger Qualität" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA-PSK" -#define D_WPA2_PSK "WPA2-PSK" -#define D_AP1_SSID "WLAN 1 - SSID" -#define D_AP1_PASSWORD "WLAN 1 - Passwort" -#define D_AP2_SSID "WLAN 2 - SSID" -#define D_AP2_PASSWORD "WLAN 2 - Passwort" - -#define D_MQTT_PARAMETERS "MQTT-Einstellungen" -#define D_CLIENT "client" -#define D_FULL_TOPIC "full topic" - -#define D_LOGGING_PARAMETERS "Logging-Einstellungen" -#define D_SERIAL_LOG_LEVEL "Seriell-Log Level" -#define D_MQTT_LOG_LEVEL "Mqtt-Log Level" -#define D_WEB_LOG_LEVEL "Web-Log Level" -#define D_SYS_LOG_LEVEL "Sys-Log Level" -#define D_MORE_DEBUG "Mehr Details" -#define D_SYSLOG_HOST "Sys-Log Host" -#define D_SYSLOG_PORT "Sys-Log Port" -#define D_TELEMETRY_PERIOD "Telemetrieperiode" - -#define D_OTHER_PARAMETERS "Sonstige Einstellungen" -#define D_TEMPLATE "Vorlage" -#define D_ACTIVATE "Aktivieren" -#define D_WEB_ADMIN_PASSWORD "Passwort für Web Oberfläche" -#define D_MQTT_ENABLE "MQTT aktivieren" -#define D_FRIENDLY_NAME "Name [friendly name]" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "Einzelnes Gerät" -#define D_MULTI_DEVICE "Mehrfachgerät" - -#define D_CONFIGURE_TEMPLATE "Vorlage konfigurieren" -#define D_TEMPLATE_PARAMETERS "Vorlage Parameter" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "basiert auf" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Konfiguration speichern" -#define D_CONFIGURATION_SAVED "Konfiguration gespeichert" -#define D_CONFIGURATION_RESET "Konfiguration zurücksetzen" - -#define D_PROGRAM_VERSION "Tasmota Version" -#define D_BUILD_DATE_AND_TIME "Build-Datum & -Uhrzeit" -#define D_CORE_AND_SDK_VERSION "Core-/SDK-Version" -#define D_FLASH_WRITE_COUNT "Anz. Flash Schreibzugriffe" -#define D_MAC_ADDRESS "MAC-Adresse" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Port" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT Benutzer" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS-Ermittlung" -#define D_MDNS_ADVERTISE "mDNS-Bekanntmachung" -#define D_ESP_CHIP_ID "ESP Chip ID" -#define D_FLASH_CHIP_ID "Flash Chip ID" -#define D_FLASH_CHIP_SIZE "Realer Flash Speicher" -#define D_FREE_PROGRAM_SPACE "Verf. Flash Speicher" - -#define D_UPGRADE_BY_WEBSERVER "Update über Web-Server" -#define D_OTA_URL "OTA-URL" -#define D_START_UPGRADE "Update starten" -#define D_UPGRADE_BY_FILE_UPLOAD "Update Datei hochladen" -#define D_UPLOAD_STARTED "Upload gestartet" -#define D_UPGRADE_STARTED "Update gestartet" -#define D_UPLOAD_DONE "Upload abgeschlossen" -#define D_UPLOAD_ERR_1 "Keine Datei ausgewählt" -#define D_UPLOAD_ERR_2 "Ungenügend Speicherplatz" -#define D_UPLOAD_ERR_3 "Magic Byte ist nicht 0xE9" -#define D_UPLOAD_ERR_4 "Datei überschreitet vorhdn. Flashspeicher" -#define D_UPLOAD_ERR_5 "Upload Buffer Vergleich weicht ab" -#define D_UPLOAD_ERR_6 "Upload fehlgeschlagen. Aktiviere logging 3" -#define D_UPLOAD_ERR_7 "Upload abgebrochen" -#define D_UPLOAD_ERR_8 "Datei ungültig" -#define D_UPLOAD_ERR_9 "Datei zu groß" -#define D_UPLOAD_ERR_10 "RF Chip init fehlgeschlagen" -#define D_UPLOAD_ERR_11 "RF Chip löschen fehlgeschlagen" -#define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen" -#define D_UPLOAD_ERR_13 "RF Firmware ungültig" -#define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" - -#define D_ENTER_COMMAND "Befehl eingeben" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivere Web Log Level 2 falls Reaktion erwartet" -#define D_NEED_USER_AND_PASSWORD "Benötige user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "TLS-Fingerabdruck wird verifiziert..." -#define D_TLS_CONNECT_FAILED_TO "TLS-Verbindung fehlgeschlagen an" -#define D_RETRY_IN "Wiederversuch in" -#define D_VERIFIED "verifiziert mit Fingerabdruck" -#define D_INSECURE "unsichere Verbindung aufgrund ungültigen Fingerabdrucks" -#define D_CONNECT_FAILED_TO "Verbindung fehlgeschlagen aufgrund von" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast deaktiviert" -#define D_MULTICAST_REJOINED "Multicast (wieder-)verbunden" -#define D_MULTICAST_JOIN_FAILED "Multicast Verbindung fehlgeschlagen" -#define D_FAILED_TO_SEND_RESPONSE "Antwort senden fehlgeschlagen" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo-Setup" -#define D_RESPONSE_SENT "Antwort gesendet" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue-Setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue-API nicht implementiert" -#define D_HUE_API "Hue-API" -#define D_HUE_POST_ARGS "Hue POST-Argumente" -#define D_3_RESPONSE_PACKETS_SENT "3 Antwortpakete gesendet" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz-Parameter" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update Zeitplan" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Zeitplan konfigurieren" -#define D_TIMER_PARAMETERS "Zeitplan-Einstellungen" -#define D_TIMER_ENABLE "Zeitpläne aktivieren" -#define D_TIMER_ARM "Aktiv" -#define D_TIMER_TIME "Uhrzeit" -#define D_TIMER_DAYS "Wochentage" -#define D_TIMER_REPEAT "Wiederholen" -#define D_TIMER_OUTPUT "Ausgang" -#define D_TIMER_ACTION "Aktion" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX konfigurieren" -#define D_KNX_PARAMETERS "KNX-Parameter" -#define D_KNX_GENERAL_CONFIG "Allgemein" -#define D_KNX_PHYSICAL_ADDRESS "Physikalische Adresse" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Muss einmalig im KNX-Netzwerk sein )" -#define D_KNX_ENABLE "KNX aktivieren" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Daten zum Senden an Gruppenadresse" -#define D_ADD "Hinzufügen" -#define D_DELETE "Löschen" -#define D_REPLY "Antworten" -#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppenadresse zum Emfang von Daten" -#define D_RECEIVED_FROM "Empfangen von" -#define D_KNX_COMMAND_WRITE "Schreiben" -#define D_KNX_COMMAND_READ "Lesen" -#define D_KNX_COMMAND_OTHER "Andere" -#define D_SENT_TO "gesendet an" -#define D_KNX_WARNING "Die Gruppenadresse (0/0/0) ist reserviert und kann nicht verwendet werden." -#define D_KNX_ENHANCEMENT "Erweiterte Kommunikation" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energie heute" -#define D_ENERGY_YESTERDAY "Energie gestern" -#define D_ENERGY_TOTAL "Energie insgesamt" - -// xdrv_27_shutter.ino -#define D_OPEN "Öffnen" -#define D_CLOSE "Schliessen" -#define D_DOMOTICZ_SHUTTER "Rollo" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Konfiguriere PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 Parameter" -#define D_INVERT_PORTS "Invertiere Ports" -#define D_DEVICE "Gerät" -#define D_DEVICE_INPUT "Eingang" -#define D_DEVICE_OUTPUT "Ausgang" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor beschäftigt" -#define D_SENSOR_CRC_ERROR "Sensor CRC-Fehler" -#define D_SENSORS_FOUND "Sensor gefunden" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout während Warten auf" -#define D_START_SIGNAL_LOW "Startausschlag niedrig" -#define D_START_SIGNAL_HIGH "Startausschlag hoch" -#define D_PULSE "Puls" -#define D_CHECKSUM_FAILURE "Checksum-Fehler" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor hat ACK-Befehl nicht ausgeführt" -#define D_SHT1X_FOUND "SHT1X gefunden" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partikel" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Beschl. X-Achse" -#define D_AY_AXIS "Beschl. Y-Achse" -#define D_AZ_AXIS "Beschl. Z-Achse" -#define D_GX_AXIS "Gyroskop X-Achse" -#define D_GY_AXIS "Gyroskop Y-Achse" -#define D_GZ_AXIS "Gyroskop Z-Achse" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Wägegut entfernen" -#define D_HX_CAL_REFERENCE "Referenzgewicht auflegen" -#define D_HX_CAL_DONE "kalibriert" -#define D_HX_CAL_FAIL "Kalibrierung fehlgeschlagen" -#define D_RESET_HX711 "Tara" -#define D_CONFIGURE_HX711 "Tara Wert?" -#define D_HX711_PARAMETERS "Skala Parameter" -#define D_ITEM_WEIGHT "Wägegut Gewicht" -#define D_REFERENCE_WEIGHT "Referenz Gewicht" -#define D_CALIBRATE "kalibriert" -#define D_CALIBRATION "Kalibrierung" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Richtung" -#define D_TX20_WIND_SPEED "Windgeschwindigkeit" -#define D_TX20_WIND_SPEED_AVG "Ø Windgeschwindigkeit" -#define D_TX20_WIND_SPEED_MAX "max Windgeschwindigkeit" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "O" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" -#define D_UNIT_KILOOHM "kΩ" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "Sektoren" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phasenwinkel" -#define D_IMPORT_ACTIVE "Importiere Wirk" -#define D_EXPORT_ACTIVE "Exportiere Wirk" -#define D_IMPORT_REACTIVE "Importiere Blind" -#define D_EXPORT_REACTIVE "Exportiere Blind" -#define D_TOTAL_REACTIVE "Total Blind" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Grad" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Spannung" -#define D_PV1_CURRENT "PV1 Strom" -#define D_PV1_POWER "PV1 Leistung" -#define D_PV2_VOLTAGE "PV2 Spannung" -#define D_PV2_CURRENT "PV2 Strom" -#define D_PV2_POWER "PV2 Leistung" -#define D_SOLAR_POWER "solare Leistung" -#define D_INVERTER_POWER "Inverter Leistung" -#define D_STATUS "Status" -#define D_WAITING "warten" -#define D_CHECKING "prüfen" -#define D_WORKING "arbeitet" -#define D_FAILURE "Fehler" -#define D_SOLAX_ERROR_0 "Kein Fehler Code" -#define D_SOLAX_ERROR_1 "Fehler im Solarstromnetz" -#define D_SOLAX_ERROR_2 "Spannungsfehler im Solarstromnetz" -#define D_SOLAX_ERROR_3 "Frequenzfehler im Solarstromnetz" -#define D_SOLAX_ERROR_4 "Pv Spannungsfehler" -#define D_SOLAX_ERROR_5 "Isolationsfehler" -#define D_SOLAX_ERROR_6 "Übertemperatur" -#define D_SOLAX_ERROR_7 "Lüfterfehler" -#define D_SOLAX_ERROR_8 "sonstiger Fehler" - -#endif // _LANGUAGE_DE_DE_H_ +/* + de-DE.h - localization for German - Germany for Tasmota + + Copyright (C) 2019 VinceMasuka + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_DE_DE_H_ +#define _LANGUAGE_DE_DE_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.6.0.21 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1031 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "de" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "." +#define D_MONTH_DAY_SEPARATOR "." +#define D_DATE_TIME_SEPARATOR " " +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "So Mo Di Mi Do Fr Sa " +#define D_MONTH3LIST "JanFebMärAprMaiJunJulAugSepOktNovDez" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Luftqualität" +#define D_AP "AP" // Access Point +#define D_AS "als" +#define D_AUTO "AUTO" +#define D_BLINK "Blinken" +#define D_BLINKOFF "BlinkenAus" +#define D_BOOT_COUNT "Anzahl Startvorgänge" +#define D_BRIGHTLIGHT "hell" +#define D_BSSID "BSSId" +#define D_BUTTON "Knopf" +#define D_BY "von" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanal" +#define D_CO2 "CO²" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "kalt" +#define D_COMMAND "Befehl" +#define D_CONNECTED "verbunden" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "zählen" +#define D_COUNTER "Zähler" +#define D_CURRENT "Strom" // As in Voltage and Current +#define D_DATA "Daten" +#define D_DARKLIGHT "dunkel" +#define D_DEBUG "debug" +#define D_DISABLED "deaktiviert" +#define D_DISTANCE "Abstand" +#define D_DNS_SERVER "DNS-Server" +#define D_DONE "erledigt" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulation" +#define D_ENABLED "aktiviert" +#define D_ERASE "löschen" +#define D_ERROR "Fehler" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "fehlgeschlagen" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback-Topic" +#define D_FALSE "falsch" +#define D_FILE "Datei" +#define D_FLOW_RATE "Durchflussmenge" +#define D_FREE_MEMORY "Freier Arbeitsspeicher" +#define D_FREQUENCY "Frequenz" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Gruppe" +#define D_HOST "Host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Feuchtigkeit" +#define D_ILLUMINANCE "Beleuchtungsintensität" +#define D_IMMEDIATE "direkt" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infrarot" +#define D_INITIALIZED "initialisiert" +#define D_IP_ADDRESS "IP-Adresse" +#define D_LIGHT "Licht" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "Mehrfachdruck" +#define D_NOISE "Lautstärke" +#define D_NONE "keine" +#define D_OFF "aus" +#define D_OFFLINE "Offline" +#define D_OK "OK" +#define D_ON "an" +#define D_ONLINE "Online" +#define D_PASSWORD "Passwort" +#define D_PORT "Port" +#define D_POWER_FACTOR "Leistungsfaktor" +#define D_POWERUSAGE "Leistung" +#define D_POWERUSAGE_ACTIVE "Wirkleistung" +#define D_POWERUSAGE_APPARENT "Scheinleistung" +#define D_POWERUSAGE_REACTIVE "Blindleistung" +#define D_PRESSURE "Luftdruck" +#define D_PRESSUREATSEALEVEL "Luftdruck auf Meereshöhe" +#define D_PROGRAM_FLASH_SIZE "Ges. Flash Speicher" +#define D_PROGRAM_SIZE "Ben. Flash Speicher" +#define D_PROJECT "Projekt" +#define D_RAIN "Regen" +#define D_RECEIVED "erhalten" +#define D_RESTART "Neustart" +#define D_RESTARTING "starte neu" +#define D_RESTART_REASON "Grund für Neustart" +#define D_RESTORE "Wiederherstellung" +#define D_RETAINED "beibehalten" +#define D_RULE "Regel" +#define D_SAVE "Speichern" +#define D_SENSOR "Sensor" +#define D_SSID "SSID" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Subnetzmaske" +#define D_SUBSCRIBE_TO "abonniere" +#define D_UNSUBSCRIBE_FROM "löse abo. von" +#define D_SUCCESSFUL "erfolgreich" +#define D_SUNRISE "Sonnenaufgang" +#define D_SUNSET "Sonnenuntergang" +#define D_TEMPERATURE "Temperatur" +#define D_TO "zu" +#define D_TOGGLE "An/Aus" +#define D_TOPIC "topic" +#define D_TOTAL_USAGE "Gesamtverbrauch" +#define D_TRANSMIT "Übertragen" +#define D_TRUE "wahr" +#define D_TVOC "TVOC" +#define D_UPGRADE "update" +#define D_UPLOAD "Upload" +#define D_UPTIME "Laufzeit" +#define D_USER "Benutzer" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV-Index" +#define D_UV_INDEX_1 "Niedrig" +#define D_UV_INDEX_2 "Mittel" +#define D_UV_INDEX_3 "Hoch" +#define D_UV_INDEX_4 "Intensiv" +#define D_UV_INDEX_5 "Gefährlich" +#define D_UV_INDEX_6 "Schädlich" +#define D_UV_INDEX_7 "Messwert!" +#define D_UV_LEVEL "UV-Level" +#define D_UV_POWER "UV Intensität" +#define D_VERSION "Version" +#define D_VOLTAGE "Spannung" +#define D_WEIGHT "Gewicht" +#define D_WARMLIGHT "warm" +#define D_WEB_SERVER "Web-Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ACHTUNG: Diese Version unterstützt keine persistenten Einstellungen" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serielles Logging deaktiviert" +#define D_SYSLOG_LOGGING_REENABLED "Syslog-Logging aktiviert" + +#define D_SET_BAUDRATE_TO "Setze Baudrate auf" +#define D_RECEIVED_TOPIC "empfangenes topic" +#define D_DATA_SIZE "Datengröße" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Schleife blockiert." +#define D_WPS_FAILED_WITH_STATUS "WPS fehlgeschlagen mit Status" +#define D_ACTIVE_FOR_3_MINUTES "aktiv für 3 Minuten" +#define D_FAILED_TO_START "Starten fehlgeschlagen" +#define D_PATCH_ISSUE_2186 "Repariere Problem #2186" +#define D_CONNECTING_TO_AP "verbinden mit AP" +#define D_IN_MODE "in Modus" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbindung fehlgeschlagen, da keine IP-Adresse zugeteilt wurde" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbindung fehlgeschlagen, da AP nicht erreicht werden konnte" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbindung fehlgeschlagen, da das Passwort falsch ist" +#define D_CONNECT_FAILED_AP_TIMEOUT "Verbindung fehlgeschlagen, da der AP nicht antwortet (timeout)" +#define D_ATTEMPTING_CONNECTION "Verbindungsversuch..." +#define D_CHECKING_CONNECTION "Prüfe Verbindung..." +#define D_QUERY_DONE "Suchanfrage abgeschlossen. MQTT-Services gefunden" +#define D_MQTT_SERVICE_FOUND "MQTT-Service gefunden bei" +#define D_FOUND_AT "gefunden bei" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog-Host nicht gefunden" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "in Flash gespeichert am" +#define D_LOADED_FROM_FLASH_AT "aus Flash geladen am" +#define D_USE_DEFAULTS "Standard verwenden" +#define D_ERASED_SECTOR "gelöschter Sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware
bitte upgraden" +#define D_WEBSERVER_ACTIVE_ON "Web-Server aktiv bei" +#define D_WITH_IP_ADDRESS "mit IP-Adresse" +#define D_WEBSERVER_STOPPED "Web-Server angehalten" +#define D_FILE_NOT_FOUND "Datei nicht gefunden" +#define D_REDIRECTED "umgeleitet zu captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WLAN-Manager AccessPoint gesetzt und behält Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "WLAN-Manager AccessPoint gesetzt" +#define D_TRYING_TO_CONNECT "Versuche Gerät mit Netzwerk zu verbinden" + +#define D_RESTART_IN "Neustart in" +#define D_SECONDS "Sekunden" +#define D_DEVICE_WILL_RESTART "Gerät wird jetzt neu gestartet" +#define D_BUTTON_TOGGLE "An/Aus" +#define D_CONFIGURATION "Einstellungen" +#define D_INFORMATION "Informationen" +#define D_FIRMWARE_UPGRADE "Firmware Update" +#define D_CONSOLE "Konsole" +#define D_CONFIRM_RESTART "Wirklich neustarten?" + +#define D_CONFIGURE_MODULE "Gerät konfigurieren" +#define D_CONFIGURE_WIFI "WLAN konfigurieren" +#define D_CONFIGURE_MQTT "MQTT konfigurieren" +#define D_CONFIGURE_DOMOTICZ "Domoticz konfigurieren" +#define D_CONFIGURE_LOGGING "Logging konfigurieren" +#define D_CONFIGURE_OTHER "Sonstige Konfiguration" +#define D_CONFIRM_RESET_CONFIGURATION "Zurücksetzen der Konfiguration bestätigen" +#define D_RESET_CONFIGURATION "Konfiguration zurücksetzen" +#define D_BACKUP_CONFIGURATION "Konfiguration sichern" +#define D_RESTORE_CONFIGURATION "Konfiguration wiederherstellen" +#define D_MAIN_MENU "Hauptmenü" + +#define D_MODULE_PARAMETERS "Geräte-Einstellungen" +#define D_MODULE_TYPE "Gerätetyp" +#define D_PULLUP_ENABLE "Kein Taster/Schalter Pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "serieller Eingang [serial in]" +#define D_SERIAL_OUT "serieller Ausgang [serial out]" + +#define D_WIFI_PARAMETERS "WLAN-Einstellungen" +#define D_SCAN_FOR_WIFI_NETWORKS "WLAN-Netzwerk suchen und auswählen" +#define D_SCAN_DONE "Suche abgeschlossen" +#define D_NO_NETWORKS_FOUND "Keine Netzwerke gefunden" +#define D_REFRESH_TO_SCAN_AGAIN "Aktualisieren, um erneut zu suchen" +#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplizieren" +#define D_SKIPPING_LOW_QUALITY "überspringe wegen niedriger Qualität" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA-PSK" +#define D_WPA2_PSK "WPA2-PSK" +#define D_AP1_SSID "WLAN 1 - SSID" +#define D_AP1_PASSWORD "WLAN 1 - Passwort" +#define D_AP2_SSID "WLAN 2 - SSID" +#define D_AP2_PASSWORD "WLAN 2 - Passwort" + +#define D_MQTT_PARAMETERS "MQTT-Einstellungen" +#define D_CLIENT "client" +#define D_FULL_TOPIC "full topic" + +#define D_LOGGING_PARAMETERS "Logging-Einstellungen" +#define D_SERIAL_LOG_LEVEL "Seriell-Log Level" +#define D_MQTT_LOG_LEVEL "Mqtt-Log Level" +#define D_WEB_LOG_LEVEL "Web-Log Level" +#define D_SYS_LOG_LEVEL "Sys-Log Level" +#define D_MORE_DEBUG "Mehr Details" +#define D_SYSLOG_HOST "Sys-Log Host" +#define D_SYSLOG_PORT "Sys-Log Port" +#define D_TELEMETRY_PERIOD "Telemetrieperiode" + +#define D_OTHER_PARAMETERS "Sonstige Einstellungen" +#define D_TEMPLATE "Vorlage" +#define D_ACTIVATE "Aktivieren" +#define D_WEB_ADMIN_PASSWORD "Passwort für Web Oberfläche" +#define D_MQTT_ENABLE "MQTT aktivieren" +#define D_FRIENDLY_NAME "Name [friendly name]" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "Einzelnes Gerät" +#define D_MULTI_DEVICE "Mehrfachgerät" + +#define D_CONFIGURE_TEMPLATE "Vorlage konfigurieren" +#define D_TEMPLATE_PARAMETERS "Vorlage Parameter" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "basiert auf" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Konfiguration speichern" +#define D_CONFIGURATION_SAVED "Konfiguration gespeichert" +#define D_CONFIGURATION_RESET "Konfiguration zurücksetzen" + +#define D_PROGRAM_VERSION "Tasmota Version" +#define D_BUILD_DATE_AND_TIME "Build-Datum & -Uhrzeit" +#define D_CORE_AND_SDK_VERSION "Core-/SDK-Version" +#define D_FLASH_WRITE_COUNT "Anz. Flash Schreibzugriffe" +#define D_MAC_ADDRESS "MAC-Adresse" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Port" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT Benutzer" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS-Ermittlung" +#define D_MDNS_ADVERTISE "mDNS-Bekanntmachung" +#define D_ESP_CHIP_ID "ESP Chip ID" +#define D_FLASH_CHIP_ID "Flash Chip ID" +#define D_FLASH_CHIP_SIZE "Realer Flash Speicher" +#define D_FREE_PROGRAM_SPACE "Verf. Flash Speicher" + +#define D_UPGRADE_BY_WEBSERVER "Update über Web-Server" +#define D_OTA_URL "OTA-URL" +#define D_START_UPGRADE "Update starten" +#define D_UPGRADE_BY_FILE_UPLOAD "Update Datei hochladen" +#define D_UPLOAD_STARTED "Upload gestartet" +#define D_UPGRADE_STARTED "Update gestartet" +#define D_UPLOAD_DONE "Upload abgeschlossen" +#define D_UPLOAD_ERR_1 "Keine Datei ausgewählt" +#define D_UPLOAD_ERR_2 "Ungenügend Speicherplatz" +#define D_UPLOAD_ERR_3 "Magic Byte ist nicht 0xE9" +#define D_UPLOAD_ERR_4 "Datei überschreitet vorhdn. Flashspeicher" +#define D_UPLOAD_ERR_5 "Upload Buffer Vergleich weicht ab" +#define D_UPLOAD_ERR_6 "Upload fehlgeschlagen. Aktiviere logging 3" +#define D_UPLOAD_ERR_7 "Upload abgebrochen" +#define D_UPLOAD_ERR_8 "Datei ungültig" +#define D_UPLOAD_ERR_9 "Datei zu groß" +#define D_UPLOAD_ERR_10 "RF Chip init fehlgeschlagen" +#define D_UPLOAD_ERR_11 "RF Chip löschen fehlgeschlagen" +#define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen" +#define D_UPLOAD_ERR_13 "RF Firmware ungültig" +#define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" + +#define D_ENTER_COMMAND "Befehl eingeben" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivere Web Log Level 2 falls Reaktion erwartet" +#define D_NEED_USER_AND_PASSWORD "Benötige user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "TLS-Fingerabdruck wird verifiziert..." +#define D_TLS_CONNECT_FAILED_TO "TLS-Verbindung fehlgeschlagen an" +#define D_RETRY_IN "Wiederversuch in" +#define D_VERIFIED "verifiziert mit Fingerabdruck" +#define D_INSECURE "unsichere Verbindung aufgrund ungültigen Fingerabdrucks" +#define D_CONNECT_FAILED_TO "Verbindung fehlgeschlagen aufgrund von" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast deaktiviert" +#define D_MULTICAST_REJOINED "Multicast (wieder-)verbunden" +#define D_MULTICAST_JOIN_FAILED "Multicast Verbindung fehlgeschlagen" +#define D_FAILED_TO_SEND_RESPONSE "Antwort senden fehlgeschlagen" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo-Setup" +#define D_RESPONSE_SENT "Antwort gesendet" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue-Setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue-API nicht implementiert" +#define D_HUE_API "Hue-API" +#define D_HUE_POST_ARGS "Hue POST-Argumente" +#define D_3_RESPONSE_PACKETS_SENT "3 Antwortpakete gesendet" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz-Parameter" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Update Zeitplan" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Zeitplan konfigurieren" +#define D_TIMER_PARAMETERS "Zeitplan-Einstellungen" +#define D_TIMER_ENABLE "Zeitpläne aktivieren" +#define D_TIMER_ARM "Aktiv" +#define D_TIMER_TIME "Uhrzeit" +#define D_TIMER_DAYS "Wochentage" +#define D_TIMER_REPEAT "Wiederholen" +#define D_TIMER_OUTPUT "Ausgang" +#define D_TIMER_ACTION "Aktion" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX konfigurieren" +#define D_KNX_PARAMETERS "KNX-Parameter" +#define D_KNX_GENERAL_CONFIG "Allgemein" +#define D_KNX_PHYSICAL_ADDRESS "Physikalische Adresse" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Muss einmalig im KNX-Netzwerk sein )" +#define D_KNX_ENABLE "KNX aktivieren" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Daten zum Senden an Gruppenadresse" +#define D_ADD "Hinzufügen" +#define D_DELETE "Löschen" +#define D_REPLY "Antworten" +#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppenadresse zum Emfang von Daten" +#define D_RECEIVED_FROM "Empfangen von" +#define D_KNX_COMMAND_WRITE "Schreiben" +#define D_KNX_COMMAND_READ "Lesen" +#define D_KNX_COMMAND_OTHER "Andere" +#define D_SENT_TO "gesendet an" +#define D_KNX_WARNING "Die Gruppenadresse (0/0/0) ist reserviert und kann nicht verwendet werden." +#define D_KNX_ENHANCEMENT "Erweiterte Kommunikation" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energie heute" +#define D_ENERGY_YESTERDAY "Energie gestern" +#define D_ENERGY_TOTAL "Energie insgesamt" + +// xdrv_27_shutter.ino +#define D_OPEN "Öffnen" +#define D_CLOSE "Schliessen" +#define D_DOMOTICZ_SHUTTER "Rollo" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Konfiguriere PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 Parameter" +#define D_INVERT_PORTS "Invertiere Ports" +#define D_DEVICE "Gerät" +#define D_DEVICE_INPUT "Eingang" +#define D_DEVICE_OUTPUT "Ausgang" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor beschäftigt" +#define D_SENSOR_CRC_ERROR "Sensor CRC-Fehler" +#define D_SENSORS_FOUND "Sensor gefunden" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout während Warten auf" +#define D_START_SIGNAL_LOW "Startausschlag niedrig" +#define D_START_SIGNAL_HIGH "Startausschlag hoch" +#define D_PULSE "Puls" +#define D_CHECKSUM_FAILURE "Checksum-Fehler" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor hat ACK-Befehl nicht ausgeführt" +#define D_SHT1X_FOUND "SHT1X gefunden" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partikel" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Beschl. X-Achse" +#define D_AY_AXIS "Beschl. Y-Achse" +#define D_AZ_AXIS "Beschl. Z-Achse" +#define D_GX_AXIS "Gyroskop X-Achse" +#define D_GY_AXIS "Gyroskop Y-Achse" +#define D_GZ_AXIS "Gyroskop Z-Achse" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Wägegut entfernen" +#define D_HX_CAL_REFERENCE "Referenzgewicht auflegen" +#define D_HX_CAL_DONE "kalibriert" +#define D_HX_CAL_FAIL "Kalibrierung fehlgeschlagen" +#define D_RESET_HX711 "Tara" +#define D_CONFIGURE_HX711 "Tara Wert?" +#define D_HX711_PARAMETERS "Skala Parameter" +#define D_ITEM_WEIGHT "Wägegut Gewicht" +#define D_REFERENCE_WEIGHT "Referenz Gewicht" +#define D_CALIBRATE "kalibriert" +#define D_CALIBRATION "Kalibrierung" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Richtung" +#define D_TX20_WIND_SPEED "Windgeschwindigkeit" +#define D_TX20_WIND_SPEED_AVG "Ø Windgeschwindigkeit" +#define D_TX20_WIND_SPEED_MAX "max Windgeschwindigkeit" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "O" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "Sektoren" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phasenwinkel" +#define D_IMPORT_ACTIVE "Importiere Wirk" +#define D_EXPORT_ACTIVE "Exportiere Wirk" +#define D_IMPORT_REACTIVE "Importiere Blind" +#define D_EXPORT_REACTIVE "Exportiere Blind" +#define D_TOTAL_REACTIVE "Total Blind" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Grad" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Spannung" +#define D_PV1_CURRENT "PV1 Strom" +#define D_PV1_POWER "PV1 Leistung" +#define D_PV2_VOLTAGE "PV2 Spannung" +#define D_PV2_CURRENT "PV2 Strom" +#define D_PV2_POWER "PV2 Leistung" +#define D_SOLAR_POWER "solare Leistung" +#define D_INVERTER_POWER "Inverter Leistung" +#define D_STATUS "Status" +#define D_WAITING "warten" +#define D_CHECKING "prüfen" +#define D_WORKING "arbeitet" +#define D_FAILURE "Fehler" +#define D_SOLAX_ERROR_0 "Kein Fehler Code" +#define D_SOLAX_ERROR_1 "Fehler im Solarstromnetz" +#define D_SOLAX_ERROR_2 "Spannungsfehler im Solarstromnetz" +#define D_SOLAX_ERROR_3 "Frequenzfehler im Solarstromnetz" +#define D_SOLAX_ERROR_4 "Pv Spannungsfehler" +#define D_SOLAX_ERROR_5 "Isolationsfehler" +#define D_SOLAX_ERROR_6 "Übertemperatur" +#define D_SOLAX_ERROR_7 "Lüfterfehler" +#define D_SOLAX_ERROR_8 "sonstiger Fehler" + +#endif // _LANGUAGE_DE_DE_H_ diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index f8b9c9614..2ae0bef38 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -1,701 +1,703 @@ -/* - el-GR.h - localization for Greek - Greece for Tasmota - - Copyright (C) 2019 Theo Arends, translated by Nick Galfas - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_EL_GR_H_ -#define _LANGUAGE_EL_GR_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.5.0 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1032 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "el" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "ΚυρΔευΤριΤετΠεμΠαρΣαβ" -#define D_MONTH3LIST "ΙανΦεβΜαρΑπρΜαϊΙονΙολΑυγΣεπΟκτΝοεΔεκ" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Διαχειριστής" -#define D_AIR_QUALITY "Ποιότητα αέρα" -#define D_AP "AP" // Access Point -#define D_AS "ως" -#define D_AUTO "ΑΥΤΟΜΑΤΟ" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Καταμέτρηση εκκινήσεων" -#define D_BRIGHTLIGHT "Φωτεινό" -#define D_BSSID "BSSId" -#define D_BUTTON "Πλήκτρο" -#define D_BY "από" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Κελσίου" -#define D_CHANNEL "Κανάλι" -#define D_CO2 "Διοξείδιο του άνθρακα" -#define D_CODE "κώδικας" // Button code -#define D_COLDLIGHT "Ψυχρό" -#define D_COMMAND "Εντολή" -#define D_CONNECTED "Συνδεδεμένο" -#define D_COUNT "Μέτρηση" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNTER "Μετρητής" -#define D_CURRENT "Ένταση" // As in Voltage and Current -#define D_DATA "Δεδομένα" -#define D_DARKLIGHT "Σκοτεινό" -#define D_DEBUG "Debug" -#define D_DISABLED "Ανενεργό" -#define D_DISTANCE "Απόσταση" -#define D_DNS_SERVER "Διακομιστής DNS" -#define D_DONE "Ολοκληρώθηκε" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Εξομoίωση" -#define D_ENABLED "Ενεργό" -#define D_ERASE "Διαγραφή" -#define D_ERROR "Σφάλμα" -#define D_FAHRENHEIT "Φαρενάιτ" -#define D_FAILED "Απέτυχε" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "Ψευδές" -#define D_FILE "Αρχείο" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Ελεύθερη μνήμη" -#define D_FREQUENCY "Συχνότητα" -#define D_GAS "Αέριο" -#define D_GATEWAY "Πύλη" -#define D_GROUP "Ομάδα" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" -#define D_HUMIDITY "Υγρασία" -#define D_ILLUMINANCE "Φωτεινότητα" -#define D_IMMEDIATE "άμεσο" // Button immediate -#define D_INDEX "Κατάλογος" -#define D_INFO "Πληροφορίες" -#define D_INFRARED "Υπέρυθρο" -#define D_INITIALIZED "Αρχικοποιήθηκε" -#define D_IP_ADDRESS "Διεύθυνση IP" -#define D_LIGHT "Φως" -#define D_LWT "LWT" -#define D_MODULE "Μονάδα" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "ανίχνευση για πολλαπλά πατήματα" -#define D_NOISE "Θόρυβος" -#define D_NONE "Κανένα" -#define D_OFF "Off" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "On" -#define D_ONLINE "Online" -#define D_PASSWORD "Κωδικός" -#define D_PORT "Θύρα" -#define D_POWER_FACTOR "Συντελεστής Ισχύος" -#define D_POWERUSAGE "Ισχύς" -#define D_POWERUSAGE_ACTIVE "Ενεργός ισχύς" -#define D_POWERUSAGE_APPARENT "Φαινόμενη ισχύς" -#define D_POWERUSAGE_REACTIVE "Άεργη ισχύς" -#define D_PRESSURE "Πίεση" -#define D_PRESSUREATSEALEVEL "Πίεση στo επίπεδο θάλασσας" -#define D_PROGRAM_FLASH_SIZE "Μέγεθος προγράμματος στη Flash" -#define D_PROGRAM_SIZE "Μέγεθος προγράμματος" -#define D_PROJECT "Έργο" -#define D_RAIN "Rain" -#define D_RECEIVED "Ελήφθη" -#define D_RESTART "Επανεκκίνηση" -#define D_RESTARTING "Επανεκκινεί" -#define D_RESTART_REASON "Αιτία επανεκκίνησης" -#define D_RESTORE "επαναφορά" -#define D_RETAINED "διακράτηση" -#define D_RULE "Κανόνας" -#define D_SAVE "Αποθήκευση" -#define D_SENSOR "Αισθητήρας" -#define D_SSID "SSId" -#define D_START "Εκκίνηση" -#define D_STD_TIME "STD" -#define D_STOP "Τερματισμός" -#define D_SUBNET_MASK "Μάσκα υποδικτύου" -#define D_SUBSCRIBE_TO "Εγγραφή στο" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Επιτυχές" -#define D_SUNRISE "Σούρουπο" -#define D_SUNSET "Ηλιοβασίλεμα" -#define D_TEMPERATURE "Θερμοκρασία" -#define D_TO "έως" -#define D_TOGGLE "Εναλλαγή" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Μετάδοση" -#define D_TRUE "Αληθές" -#define D_TVOC "TVOC" -#define D_UPGRADE "αναβάθμιση" -#define D_UPLOAD "Ανέβασμα" -#define D_UPTIME "Χρόνος λειτουργίας" -#define D_USER "Χρήστης" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Δείκτης UV" -#define D_UV_INDEX_1 "Χαμηλό" -#define D_UV_INDEX_2 "Μέτριο" -#define D_UV_INDEX_3 "Υψηλό" -#define D_UV_INDEX_4 "Κίνδυνος" -#define D_UV_INDEX_5 "Έγκαυμα L1/2" -#define D_UV_INDEX_6 "Έγκαυμα L3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Επίπεδο UV" -#define D_UV_POWER "Ένταση UV" -#define D_VERSION "Έκδοση" -#define D_VOLTAGE "Τάση" -#define D_WEIGHT "Βάρος" -#define D_WARMLIGHT "Θερμό" -#define D_WEB_SERVER "Διακομιστής Web" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ΠΡΟΕΙΔΟΠΟΙΗΣΗ Αυτή η έκδοση δεν αποθηκεύει τις ρυθμίσεις" -#define D_LEVEL_10 "επίπεδο 1-0" -#define D_LEVEL_01 "επίπεδο 0-1" -#define D_SERIAL_LOGGING_DISABLED "Η καταγραφή σειριακής θύρας είναι απενεργοποιημένη" -#define D_SYSLOG_LOGGING_REENABLED "Η καταγραφή Syslog επαναενεργοποιήθηκε" - -#define D_SET_BAUDRATE_TO "Ορισμός Baudrate σε" -#define D_RECEIVED_TOPIC "Received Topic" -#define D_DATA_SIZE "Μέγεθος δεδομένων" -#define D_ANALOG_INPUT "Αναλογικό" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "Το WPSconfig ΑΠΕΤΥΧΕ με status" -#define D_ACTIVE_FOR_3_MINUTES "ενεργό για 3 λεπτά" -#define D_FAILED_TO_START "απέτυχε να εκκινήσει" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Συνδέεται στο AP" -#define D_IN_MODE "σε mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Αποτυχία σύνδεσης, δεν απονεμήθηκε διεύθυνση IP" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Αποτυχία σύνδεσης, δεν ανταποκρίνεται το AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Αποτυχία σύνδεσης, λάθος κωδικός για το AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Αποτυχία σύνδεσης, λήξη ορίου απόκρισης από το AP" -#define D_ATTEMPTING_CONNECTION "Προσπάθεια για σύνδεση..." -#define D_CHECKING_CONNECTION "Έλεγχος σύνδεσης..." -#define D_QUERY_DONE "Ολοκλήρωση ερωτήματος. Βρέθηκε υπηρεσία MQTT" -#define D_MQTT_SERVICE_FOUND "Βρέθηκε υπηρεσία MQTT στο" -#define D_FOUND_AT "βρέθηκε στο" -#define D_SYSLOG_HOST_NOT_FOUND "Δε βρέθηκε Syslog Host" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Αποθηκεύτηκε από τη Flash στο" -#define D_LOADED_FROM_FLASH_AT "Φορτώθηκε από τη Flash στο" -#define D_USE_DEFAULTS "Χρήση προεπιλογών" -#define D_ERASED_SECTOR "Διαγραφή τομέα" - -// webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" -#define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" -#define D_WITH_IP_ADDRESS "με διεύθυνση IP" -#define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" -#define D_FILE_NOT_FOUND "Δε βρέθηκε το αρχείο" -#define D_REDIRECTED "Ανακατεύθυνση στο captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" -#define D_TRYING_TO_CONNECT "Προσπάθεια σύνδεσης της συσκευής σε ασύρματο δίκτυο" - -#define D_RESTART_IN "Επανεκκίνηση σε" -#define D_SECONDS "δευτερόλεπτα" -#define D_DEVICE_WILL_RESTART "Η συσκευή θα επανεκκινήσει σε λίγα δευτερόλεπτα" -#define D_BUTTON_TOGGLE "Εναλλαγή" -#define D_CONFIGURATION "Ρυθμίσεις" -#define D_INFORMATION "Πληροφορίες" -#define D_FIRMWARE_UPGRADE "Αναβάθμιση" -#define D_CONSOLE "Κονσόλα" -#define D_CONFIRM_RESTART "Επιβεβαίωση επανεκκίνησης" - -#define D_CONFIGURE_MODULE "Μονάδα" -#define D_CONFIGURE_WIFI "WiFi" -#define D_CONFIGURE_MQTT "MQTT" -#define D_CONFIGURE_DOMOTICZ "Domoticz" -#define D_CONFIGURE_LOGGING "Καταγραφή" -#define D_CONFIGURE_OTHER "Άλλες ρυθμίσεις" -#define D_CONFIRM_RESET_CONFIGURATION "Επιβεβαίωση αρχικοποίησης στις προεπιλεγμένες ρυθμίσεις" -#define D_RESET_CONFIGURATION "Reset" -#define D_BACKUP_CONFIGURATION "Εξαγωγή" -#define D_RESTORE_CONFIGURATION "Επαναφορά" -#define D_MAIN_MENU "Κεντρικό μενού" - -#define D_MODULE_PARAMETERS "Παράμετροι μονάδας" -#define D_MODULE_TYPE "Τύπος μονάδας" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Παράμετροι Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Σάρωση για δίκτυα Wifi" -#define D_SCAN_DONE "Η σάρωση ολοκληρώθηκε" -#define D_NO_NETWORKS_FOUND "Δε βρέθηκαν δίκτυα" -#define D_REFRESH_TO_SCAN_AGAIN "Πατήστε ανανέωση για μια νέα σάρωση" -#define D_DUPLICATE_ACCESSPOINT "Διπλότυπο AccessPoint" -#define D_SKIPPING_LOW_QUALITY "Παράκαμψη λόγω χαμηλής ποιότητας" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Κωδικός" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Κωδικός" - -#define D_MQTT_PARAMETERS "Παράμετροι MQTT" -#define D_CLIENT "Πελάτης" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "Παράμετροι καταγραφής" -#define D_SERIAL_LOG_LEVEL "Επίπεδο Σειριακής" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Επίπεδο Web" -#define D_SYS_LOG_LEVEL "Επίπεδο Syslog" -#define D_MORE_DEBUG "More debug" -#define D_SYSLOG_HOST "Εξυπηρετητής Syslog" -#define D_SYSLOG_PORT "Θύρα Syslog" -#define D_TELEMETRY_PERIOD "Περίοδος τηλεμετρίας" - -#define D_OTHER_PARAMETERS "Άλλες παράμετροι" -#define D_TEMPLATE "Πρότυπο" -#define D_ACTIVATE "Ενεργοποίηση" -#define D_WEB_ADMIN_PASSWORD "Κωδικός διαχειριστή" -#define D_MQTT_ENABLE "Ενεργοποίηση MQTT" -#define D_FRIENDLY_NAME "Φιλική ονομασία" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "μονή συσκευή" -#define D_MULTI_DEVICE "πολλαπλές συσκευές" - -#define D_CONFIGURE_TEMPLATE "Πρότυπα" -#define D_TEMPLATE_PARAMETERS "Παράμετροι Πρότυπου" -#define D_TEMPLATE_NAME "Όνομα" -#define D_BASE_TYPE "Βασίζεται στο" -#define D_TEMPLATE_FLAGS "Επιλογές" - -#define D_SAVE_CONFIGURATION "Αποθήκευση ρυθμίσεων" -#define D_CONFIGURATION_SAVED "Οι ρυθμίσεις αποθηκεύτηκαν" -#define D_CONFIGURATION_RESET "Επαναφορά ρυθμίσεων" - -#define D_PROGRAM_VERSION "Έκδοση προγράμματος" -#define D_BUILD_DATE_AND_TIME "Ημερομηνία έκδοσης" -#define D_CORE_AND_SDK_VERSION "Έκδοση Core/SDK" -#define D_FLASH_WRITE_COUNT "Καταμέτρηση εγγραφών στη Flash" -#define D_MAC_ADDRESS "MAC Address" -#define D_MQTT_HOST "MQTT Διακομιστής" -#define D_MQTT_PORT "MQTT Θύρα" -#define D_MQTT_CLIENT "MQTT Πελάτης" -#define D_MQTT_USER "MQTT Χρήστης" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Μέγεθος Flash" -#define D_FREE_PROGRAM_SPACE "Ελεύθερος χώρος προγράμματος" - -#define D_UPGRADE_BY_WEBSERVER "Αναβάθμιση μέσω web server" -#define D_OTA_URL "OTA URL" -#define D_START_UPGRADE "Εκκίνηση αναβάθμισης" -#define D_UPGRADE_BY_FILE_UPLOAD "Αναβάθμιση με μεταφόρτωση αρχείου" -#define D_UPLOAD_STARTED "Η μεταφόρτωση ξεκίνησε" -#define D_UPGRADE_STARTED "Η αναβάθμιση ξεκίνησε" -#define D_UPLOAD_DONE "Η μεταφόρτωση ολοκληρώθηκε" -#define D_UPLOAD_ERR_1 "Δεν έχει επιλεγεί αρχείο" -#define D_UPLOAD_ERR_2 "Δεν υπάρχει επαρκής χώρος" -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" -#define D_UPLOAD_ERR_4 "Το μέγεθος προγράμματος είναι μεγαλύτερο από την πραγματική μνήμη Flash" -#define D_UPLOAD_ERR_5 "Upload buffer miscompare" -#define D_UPLOAD_ERR_6 "Η μεταφόρτωση απέτυχε. Επιλέξτε επίπεδο καταγραφής 3" -#define D_UPLOAD_ERR_7 "Η μεταφόρτωση ματαιώθηκε" -#define D_UPLOAD_ERR_8 "Μη έγκυρο αρχείο" -#define D_UPLOAD_ERR_9 "Πολύ μεγάλο αρχείο" -#define D_UPLOAD_ERR_10 "Αποτυχία αρχικοποίησης RF chip" -#define D_UPLOAD_ERR_11 "Αποτυχία σβησίματος στο RF chip" -#define D_UPLOAD_ERR_12 "Αποτυχία εγγραφής στο RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Κωδικός λάθους στη μεταφόρτωση" - -#define D_ENTER_COMMAND "Εισαγωγή εντολής" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Ενεργοποιήστε το weblog 2 εαν περιμένετε απόκριση" -#define D_NEED_USER_AND_PASSWORD "Χρειάζεται user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Επιβεβαίωση αποτυπώματος TLS..." -#define D_TLS_CONNECT_FAILED_TO "Αποτυχία σύνδεσης TLS στο" -#define D_RETRY_IN "Νέα προσπάθεια σε" -#define D_VERIFIED "Επιβεβαιώθηκε με χρήση αποτυπώματος TLS" -#define D_INSECURE "Επισφαλής σύνδεση λόγω άκυρου αποτυπώματος TLS" -#define D_CONNECT_FAILED_TO "Αποτυχία σύνδεσης στο" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Απενεργοποιημένο Multicast" -#define D_MULTICAST_REJOINED "Επανασύνδεση Multicast" -#define D_MULTICAST_JOIN_FAILED "Αποτυχία σύνδεσης Multicast" -#define D_FAILED_TO_SEND_RESPONSE "Αποτυχία αποστολής απόκρισης" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo βασικό event" -#define D_WEMO_EVENT_SERVICE "WeMo υπηρεσία event" -#define D_WEMO_META_SERVICE "WeMo υπηρεσία meta" -#define D_WEMO_SETUP "WeMo ρυθμίσεις" -#define D_RESPONSE_SENT "Αποστολή απάντησης" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue ρυθμίσεις" -#define D_HUE_API_NOT_IMPLEMENTED "Δε βρέθηκε εφαρμογή Hue API" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "Στάλθηκαν 3 πακέτα απόκρισης" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Παράμετροι Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Χρονικά" -#define D_TIMER_PARAMETERS "Παράμετροι χρονικών" -#define D_TIMER_ENABLE "Ενεργοποίηση χρονικών" -#define D_TIMER_ARM "Οπλισμένο" -#define D_TIMER_TIME "Ώρα" -#define D_TIMER_DAYS "Μέρες" -#define D_TIMER_REPEAT "Επανάληψη" -#define D_TIMER_OUTPUT "Έξοδος" -#define D_TIMER_ACTION "Λειτουργία" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Ρυθμίσεις KNX" -#define D_KNX_PARAMETERS "Παράμετροι KNX" -#define D_KNX_GENERAL_CONFIG "Γενικά" -#define D_KNX_PHYSICAL_ADDRESS "Διεύθυνση Μνήμης" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Πρέπει να είναι μοναδική στο KNX δίκτυο )" -#define D_KNX_ENABLE "Ενεργοποίηση KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Αποστολή δεδομένων σε Ομάδα Διευθύνσεων" -#define D_ADD "Προσθήκη" -#define D_DELETE "Διαγραφή" -#define D_REPLY "Επανάληψη" -#define D_KNX_GROUP_ADDRESS_TO_READ "Ομάδα Διευθύνσεων που θα λάβει τα Δεδομένα" -#define D_RECEIVED_FROM "Στάλθηκε από" -#define D_KNX_COMMAND_WRITE "Εγγραφή" -#define D_KNX_COMMAND_READ "Ανάγνωση" -#define D_KNX_COMMAND_OTHER "Άλλο" -#define D_SENT_TO "αποστολή σε" -#define D_KNX_WARNING "Η Ομάδα Διευθύνσεων ( 0 / 0 / 0 ) είναι δεσμευμένη και δεν μπορεί να χρησιμοποιηθεί." -#define D_KNX_ENHANCEMENT "Βελτίωση επικοινωνίας" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Ενέργεια σήμερα" -#define D_ENERGY_YESTERDAY "Ενέργεια χθες" -#define D_ENERGY_TOTAL "Ενέργεια συνολικά" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Ο αισθητήρας είναι απασχολημένος" -#define D_SENSOR_CRC_ERROR "Σφάλμα CRC αισθητήρα" -#define D_SENSORS_FOUND "Βρέθηκαν αισθητήρες" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Αναμονή Timeout για" -#define D_START_SIGNAL_LOW "χαμηλό αρχικό σήμα" -#define D_START_SIGNAL_HIGH "υψηλό αρχικό σήμα" -#define D_PULSE "παλμός" -#define D_CHECKSUM_FAILURE "Αποτυχία Checksum" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Ο αισθητήρας δεν έστειλε εντολή ACK" -#define D_SHT1X_FOUND "Βρέθηκε SHT1X" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Απομακρύνετε το βαρίδιο" -#define D_HX_CAL_REFERENCE "Τοποθετήστε το βαρίδιο αναφοράς" -#define D_HX_CAL_DONE "Βαθμονομήθηκε" -#define D_HX_CAL_FAIL "Αποτυχία βαθμονόμησης" -#define D_RESET_HX711 "Αρχικοποίηση ζυγαριάς" -#define D_CONFIGURE_HX711 "Ρύθμιση ζυγαριάς" -#define D_HX711_PARAMETERS "Παράμετροι ζυγαριάς" -#define D_ITEM_WEIGHT "Βάρος αντικειμένου" -#define D_REFERENCE_WEIGHT "Βάρος αναφοράς" -#define D_CALIBRATE "Βαθμονόμησε" -#define D_CALIBRATION "Βαθμονόμηση" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Κατεύθυνση ανέμου" -#define D_TX20_WIND_SPEED "Ταχύτητα ανέμου" -#define D_TX20_WIND_SPEED_AVG "Μέση ταχύτητα ανέμου" -#define D_TX20_WIND_SPEED_MAX "Μέγιστη ταχύτητα ανέμου" -#define D_TX20_NORTH "Β" -#define D_TX20_EAST "Α" -#define D_TX20_SOUTH "Ν" -#define D_TX20_WEST "Δ" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Κανένα" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_EL_GR_H_ +/* + el-GR.h - localization for Greek - Greece for Tasmota + + Copyright (C) 2019 Theo Arends, translated by Nick Galfas + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_EL_GR_H_ +#define _LANGUAGE_EL_GR_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.5.0 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1032 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "el" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "ΚυρΔευΤριΤετΠεμΠαρΣαβ" +#define D_MONTH3LIST "ΙανΦεβΜαρΑπρΜαϊΙονΙολΑυγΣεπΟκτΝοεΔεκ" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Διαχειριστής" +#define D_AIR_QUALITY "Ποιότητα αέρα" +#define D_AP "AP" // Access Point +#define D_AS "ως" +#define D_AUTO "ΑΥΤΟΜΑΤΟ" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Καταμέτρηση εκκινήσεων" +#define D_BRIGHTLIGHT "Φωτεινό" +#define D_BSSID "BSSId" +#define D_BUTTON "Πλήκτρο" +#define D_BY "από" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Κελσίου" +#define D_CHANNEL "Κανάλι" +#define D_CO2 "Διοξείδιο του άνθρακα" +#define D_CODE "κώδικας" // Button code +#define D_COLDLIGHT "Ψυχρό" +#define D_COMMAND "Εντολή" +#define D_CONNECTED "Συνδεδεμένο" +#define D_COUNT "Μέτρηση" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNTER "Μετρητής" +#define D_CURRENT "Ένταση" // As in Voltage and Current +#define D_DATA "Δεδομένα" +#define D_DARKLIGHT "Σκοτεινό" +#define D_DEBUG "Debug" +#define D_DISABLED "Ανενεργό" +#define D_DISTANCE "Απόσταση" +#define D_DNS_SERVER "Διακομιστής DNS" +#define D_DONE "Ολοκληρώθηκε" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Εξομoίωση" +#define D_ENABLED "Ενεργό" +#define D_ERASE "Διαγραφή" +#define D_ERROR "Σφάλμα" +#define D_FAHRENHEIT "Φαρενάιτ" +#define D_FAILED "Απέτυχε" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "Ψευδές" +#define D_FILE "Αρχείο" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Ελεύθερη μνήμη" +#define D_FREQUENCY "Συχνότητα" +#define D_GAS "Αέριο" +#define D_GATEWAY "Πύλη" +#define D_GROUP "Ομάδα" +#define D_HOST "Host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Υγρασία" +#define D_ILLUMINANCE "Φωτεινότητα" +#define D_IMMEDIATE "άμεσο" // Button immediate +#define D_INDEX "Κατάλογος" +#define D_INFO "Πληροφορίες" +#define D_INFRARED "Υπέρυθρο" +#define D_INITIALIZED "Αρχικοποιήθηκε" +#define D_IP_ADDRESS "Διεύθυνση IP" +#define D_LIGHT "Φως" +#define D_LWT "LWT" +#define D_MODULE "Μονάδα" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "ανίχνευση για πολλαπλά πατήματα" +#define D_NOISE "Θόρυβος" +#define D_NONE "Κανένα" +#define D_OFF "Off" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "On" +#define D_ONLINE "Online" +#define D_PASSWORD "Κωδικός" +#define D_PORT "Θύρα" +#define D_POWER_FACTOR "Συντελεστής Ισχύος" +#define D_POWERUSAGE "Ισχύς" +#define D_POWERUSAGE_ACTIVE "Ενεργός ισχύς" +#define D_POWERUSAGE_APPARENT "Φαινόμενη ισχύς" +#define D_POWERUSAGE_REACTIVE "Άεργη ισχύς" +#define D_PRESSURE "Πίεση" +#define D_PRESSUREATSEALEVEL "Πίεση στo επίπεδο θάλασσας" +#define D_PROGRAM_FLASH_SIZE "Μέγεθος προγράμματος στη Flash" +#define D_PROGRAM_SIZE "Μέγεθος προγράμματος" +#define D_PROJECT "Έργο" +#define D_RAIN "Rain" +#define D_RECEIVED "Ελήφθη" +#define D_RESTART "Επανεκκίνηση" +#define D_RESTARTING "Επανεκκινεί" +#define D_RESTART_REASON "Αιτία επανεκκίνησης" +#define D_RESTORE "επαναφορά" +#define D_RETAINED "διακράτηση" +#define D_RULE "Κανόνας" +#define D_SAVE "Αποθήκευση" +#define D_SENSOR "Αισθητήρας" +#define D_SSID "SSId" +#define D_START "Εκκίνηση" +#define D_STD_TIME "STD" +#define D_STOP "Τερματισμός" +#define D_SUBNET_MASK "Μάσκα υποδικτύου" +#define D_SUBSCRIBE_TO "Εγγραφή στο" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Επιτυχές" +#define D_SUNRISE "Σούρουπο" +#define D_SUNSET "Ηλιοβασίλεμα" +#define D_TEMPERATURE "Θερμοκρασία" +#define D_TO "έως" +#define D_TOGGLE "Εναλλαγή" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Μετάδοση" +#define D_TRUE "Αληθές" +#define D_TVOC "TVOC" +#define D_UPGRADE "αναβάθμιση" +#define D_UPLOAD "Ανέβασμα" +#define D_UPTIME "Χρόνος λειτουργίας" +#define D_USER "Χρήστης" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Δείκτης UV" +#define D_UV_INDEX_1 "Χαμηλό" +#define D_UV_INDEX_2 "Μέτριο" +#define D_UV_INDEX_3 "Υψηλό" +#define D_UV_INDEX_4 "Κίνδυνος" +#define D_UV_INDEX_5 "Έγκαυμα L1/2" +#define D_UV_INDEX_6 "Έγκαυμα L3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Επίπεδο UV" +#define D_UV_POWER "Ένταση UV" +#define D_VERSION "Έκδοση" +#define D_VOLTAGE "Τάση" +#define D_WEIGHT "Βάρος" +#define D_WARMLIGHT "Θερμό" +#define D_WEB_SERVER "Διακομιστής Web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ΠΡΟΕΙΔΟΠΟΙΗΣΗ Αυτή η έκδοση δεν αποθηκεύει τις ρυθμίσεις" +#define D_LEVEL_10 "επίπεδο 1-0" +#define D_LEVEL_01 "επίπεδο 0-1" +#define D_SERIAL_LOGGING_DISABLED "Η καταγραφή σειριακής θύρας είναι απενεργοποιημένη" +#define D_SYSLOG_LOGGING_REENABLED "Η καταγραφή Syslog επαναενεργοποιήθηκε" + +#define D_SET_BAUDRATE_TO "Ορισμός Baudrate σε" +#define D_RECEIVED_TOPIC "Received Topic" +#define D_DATA_SIZE "Μέγεθος δεδομένων" +#define D_ANALOG_INPUT "Αναλογικό" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "Το WPSconfig ΑΠΕΤΥΧΕ με status" +#define D_ACTIVE_FOR_3_MINUTES "ενεργό για 3 λεπτά" +#define D_FAILED_TO_START "απέτυχε να εκκινήσει" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Συνδέεται στο AP" +#define D_IN_MODE "σε mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Αποτυχία σύνδεσης, δεν απονεμήθηκε διεύθυνση IP" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Αποτυχία σύνδεσης, δεν ανταποκρίνεται το AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Αποτυχία σύνδεσης, λάθος κωδικός για το AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Αποτυχία σύνδεσης, λήξη ορίου απόκρισης από το AP" +#define D_ATTEMPTING_CONNECTION "Προσπάθεια για σύνδεση..." +#define D_CHECKING_CONNECTION "Έλεγχος σύνδεσης..." +#define D_QUERY_DONE "Ολοκλήρωση ερωτήματος. Βρέθηκε υπηρεσία MQTT" +#define D_MQTT_SERVICE_FOUND "Βρέθηκε υπηρεσία MQTT στο" +#define D_FOUND_AT "βρέθηκε στο" +#define D_SYSLOG_HOST_NOT_FOUND "Δε βρέθηκε Syslog Host" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Αποθηκεύτηκε από τη Flash στο" +#define D_LOADED_FROM_FLASH_AT "Φορτώθηκε από τη Flash στο" +#define D_USE_DEFAULTS "Χρήση προεπιλογών" +#define D_ERASED_SECTOR "Διαγραφή τομέα" + +// webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" +#define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" +#define D_WITH_IP_ADDRESS "με διεύθυνση IP" +#define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" +#define D_FILE_NOT_FOUND "Δε βρέθηκε το αρχείο" +#define D_REDIRECTED "Ανακατεύθυνση στο captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" +#define D_TRYING_TO_CONNECT "Προσπάθεια σύνδεσης της συσκευής σε ασύρματο δίκτυο" + +#define D_RESTART_IN "Επανεκκίνηση σε" +#define D_SECONDS "δευτερόλεπτα" +#define D_DEVICE_WILL_RESTART "Η συσκευή θα επανεκκινήσει σε λίγα δευτερόλεπτα" +#define D_BUTTON_TOGGLE "Εναλλαγή" +#define D_CONFIGURATION "Ρυθμίσεις" +#define D_INFORMATION "Πληροφορίες" +#define D_FIRMWARE_UPGRADE "Αναβάθμιση" +#define D_CONSOLE "Κονσόλα" +#define D_CONFIRM_RESTART "Επιβεβαίωση επανεκκίνησης" + +#define D_CONFIGURE_MODULE "Μονάδα" +#define D_CONFIGURE_WIFI "WiFi" +#define D_CONFIGURE_MQTT "MQTT" +#define D_CONFIGURE_DOMOTICZ "Domoticz" +#define D_CONFIGURE_LOGGING "Καταγραφή" +#define D_CONFIGURE_OTHER "Άλλες ρυθμίσεις" +#define D_CONFIRM_RESET_CONFIGURATION "Επιβεβαίωση αρχικοποίησης στις προεπιλεγμένες ρυθμίσεις" +#define D_RESET_CONFIGURATION "Reset" +#define D_BACKUP_CONFIGURATION "Εξαγωγή" +#define D_RESTORE_CONFIGURATION "Επαναφορά" +#define D_MAIN_MENU "Κεντρικό μενού" + +#define D_MODULE_PARAMETERS "Παράμετροι μονάδας" +#define D_MODULE_TYPE "Τύπος μονάδας" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Παράμετροι Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Σάρωση για δίκτυα Wifi" +#define D_SCAN_DONE "Η σάρωση ολοκληρώθηκε" +#define D_NO_NETWORKS_FOUND "Δε βρέθηκαν δίκτυα" +#define D_REFRESH_TO_SCAN_AGAIN "Πατήστε ανανέωση για μια νέα σάρωση" +#define D_DUPLICATE_ACCESSPOINT "Διπλότυπο AccessPoint" +#define D_SKIPPING_LOW_QUALITY "Παράκαμψη λόγω χαμηλής ποιότητας" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Κωδικός" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Κωδικός" + +#define D_MQTT_PARAMETERS "Παράμετροι MQTT" +#define D_CLIENT "Πελάτης" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "Παράμετροι καταγραφής" +#define D_SERIAL_LOG_LEVEL "Επίπεδο Σειριακής" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Επίπεδο Web" +#define D_SYS_LOG_LEVEL "Επίπεδο Syslog" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "Εξυπηρετητής Syslog" +#define D_SYSLOG_PORT "Θύρα Syslog" +#define D_TELEMETRY_PERIOD "Περίοδος τηλεμετρίας" + +#define D_OTHER_PARAMETERS "Άλλες παράμετροι" +#define D_TEMPLATE "Πρότυπο" +#define D_ACTIVATE "Ενεργοποίηση" +#define D_WEB_ADMIN_PASSWORD "Κωδικός διαχειριστή" +#define D_MQTT_ENABLE "Ενεργοποίηση MQTT" +#define D_FRIENDLY_NAME "Φιλική ονομασία" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "μονή συσκευή" +#define D_MULTI_DEVICE "πολλαπλές συσκευές" + +#define D_CONFIGURE_TEMPLATE "Πρότυπα" +#define D_TEMPLATE_PARAMETERS "Παράμετροι Πρότυπου" +#define D_TEMPLATE_NAME "Όνομα" +#define D_BASE_TYPE "Βασίζεται στο" +#define D_TEMPLATE_FLAGS "Επιλογές" + +#define D_SAVE_CONFIGURATION "Αποθήκευση ρυθμίσεων" +#define D_CONFIGURATION_SAVED "Οι ρυθμίσεις αποθηκεύτηκαν" +#define D_CONFIGURATION_RESET "Επαναφορά ρυθμίσεων" + +#define D_PROGRAM_VERSION "Έκδοση προγράμματος" +#define D_BUILD_DATE_AND_TIME "Ημερομηνία έκδοσης" +#define D_CORE_AND_SDK_VERSION "Έκδοση Core/SDK" +#define D_FLASH_WRITE_COUNT "Καταμέτρηση εγγραφών στη Flash" +#define D_MAC_ADDRESS "MAC Address" +#define D_MQTT_HOST "MQTT Διακομιστής" +#define D_MQTT_PORT "MQTT Θύρα" +#define D_MQTT_CLIENT "MQTT Πελάτης" +#define D_MQTT_USER "MQTT Χρήστης" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Μέγεθος Flash" +#define D_FREE_PROGRAM_SPACE "Ελεύθερος χώρος προγράμματος" + +#define D_UPGRADE_BY_WEBSERVER "Αναβάθμιση μέσω web server" +#define D_OTA_URL "OTA URL" +#define D_START_UPGRADE "Εκκίνηση αναβάθμισης" +#define D_UPGRADE_BY_FILE_UPLOAD "Αναβάθμιση με μεταφόρτωση αρχείου" +#define D_UPLOAD_STARTED "Η μεταφόρτωση ξεκίνησε" +#define D_UPGRADE_STARTED "Η αναβάθμιση ξεκίνησε" +#define D_UPLOAD_DONE "Η μεταφόρτωση ολοκληρώθηκε" +#define D_UPLOAD_ERR_1 "Δεν έχει επιλεγεί αρχείο" +#define D_UPLOAD_ERR_2 "Δεν υπάρχει επαρκής χώρος" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "Το μέγεθος προγράμματος είναι μεγαλύτερο από την πραγματική μνήμη Flash" +#define D_UPLOAD_ERR_5 "Upload buffer miscompare" +#define D_UPLOAD_ERR_6 "Η μεταφόρτωση απέτυχε. Επιλέξτε επίπεδο καταγραφής 3" +#define D_UPLOAD_ERR_7 "Η μεταφόρτωση ματαιώθηκε" +#define D_UPLOAD_ERR_8 "Μη έγκυρο αρχείο" +#define D_UPLOAD_ERR_9 "Πολύ μεγάλο αρχείο" +#define D_UPLOAD_ERR_10 "Αποτυχία αρχικοποίησης RF chip" +#define D_UPLOAD_ERR_11 "Αποτυχία σβησίματος στο RF chip" +#define D_UPLOAD_ERR_12 "Αποτυχία εγγραφής στο RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "Κωδικός λάθους στη μεταφόρτωση" + +#define D_ENTER_COMMAND "Εισαγωγή εντολής" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Ενεργοποιήστε το weblog 2 εαν περιμένετε απόκριση" +#define D_NEED_USER_AND_PASSWORD "Χρειάζεται user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Επιβεβαίωση αποτυπώματος TLS..." +#define D_TLS_CONNECT_FAILED_TO "Αποτυχία σύνδεσης TLS στο" +#define D_RETRY_IN "Νέα προσπάθεια σε" +#define D_VERIFIED "Επιβεβαιώθηκε με χρήση αποτυπώματος TLS" +#define D_INSECURE "Επισφαλής σύνδεση λόγω άκυρου αποτυπώματος TLS" +#define D_CONNECT_FAILED_TO "Αποτυχία σύνδεσης στο" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Απενεργοποιημένο Multicast" +#define D_MULTICAST_REJOINED "Επανασύνδεση Multicast" +#define D_MULTICAST_JOIN_FAILED "Αποτυχία σύνδεσης Multicast" +#define D_FAILED_TO_SEND_RESPONSE "Αποτυχία αποστολής απόκρισης" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo βασικό event" +#define D_WEMO_EVENT_SERVICE "WeMo υπηρεσία event" +#define D_WEMO_META_SERVICE "WeMo υπηρεσία meta" +#define D_WEMO_SETUP "WeMo ρυθμίσεις" +#define D_RESPONSE_SENT "Αποστολή απάντησης" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue ρυθμίσεις" +#define D_HUE_API_NOT_IMPLEMENTED "Δε βρέθηκε εφαρμογή Hue API" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "Στάλθηκαν 3 πακέτα απόκρισης" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Παράμετροι Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Χρονικά" +#define D_TIMER_PARAMETERS "Παράμετροι χρονικών" +#define D_TIMER_ENABLE "Ενεργοποίηση χρονικών" +#define D_TIMER_ARM "Οπλισμένο" +#define D_TIMER_TIME "Ώρα" +#define D_TIMER_DAYS "Μέρες" +#define D_TIMER_REPEAT "Επανάληψη" +#define D_TIMER_OUTPUT "Έξοδος" +#define D_TIMER_ACTION "Λειτουργία" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Ρυθμίσεις KNX" +#define D_KNX_PARAMETERS "Παράμετροι KNX" +#define D_KNX_GENERAL_CONFIG "Γενικά" +#define D_KNX_PHYSICAL_ADDRESS "Διεύθυνση Μνήμης" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Πρέπει να είναι μοναδική στο KNX δίκτυο )" +#define D_KNX_ENABLE "Ενεργοποίηση KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Αποστολή δεδομένων σε Ομάδα Διευθύνσεων" +#define D_ADD "Προσθήκη" +#define D_DELETE "Διαγραφή" +#define D_REPLY "Επανάληψη" +#define D_KNX_GROUP_ADDRESS_TO_READ "Ομάδα Διευθύνσεων που θα λάβει τα Δεδομένα" +#define D_RECEIVED_FROM "Στάλθηκε από" +#define D_KNX_COMMAND_WRITE "Εγγραφή" +#define D_KNX_COMMAND_READ "Ανάγνωση" +#define D_KNX_COMMAND_OTHER "Άλλο" +#define D_SENT_TO "αποστολή σε" +#define D_KNX_WARNING "Η Ομάδα Διευθύνσεων ( 0 / 0 / 0 ) είναι δεσμευμένη και δεν μπορεί να χρησιμοποιηθεί." +#define D_KNX_ENHANCEMENT "Βελτίωση επικοινωνίας" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Ενέργεια σήμερα" +#define D_ENERGY_YESTERDAY "Ενέργεια χθες" +#define D_ENERGY_TOTAL "Ενέργεια συνολικά" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Ο αισθητήρας είναι απασχολημένος" +#define D_SENSOR_CRC_ERROR "Σφάλμα CRC αισθητήρα" +#define D_SENSORS_FOUND "Βρέθηκαν αισθητήρες" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Αναμονή Timeout για" +#define D_START_SIGNAL_LOW "χαμηλό αρχικό σήμα" +#define D_START_SIGNAL_HIGH "υψηλό αρχικό σήμα" +#define D_PULSE "παλμός" +#define D_CHECKSUM_FAILURE "Αποτυχία Checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Ο αισθητήρας δεν έστειλε εντολή ACK" +#define D_SHT1X_FOUND "Βρέθηκε SHT1X" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Απομακρύνετε το βαρίδιο" +#define D_HX_CAL_REFERENCE "Τοποθετήστε το βαρίδιο αναφοράς" +#define D_HX_CAL_DONE "Βαθμονομήθηκε" +#define D_HX_CAL_FAIL "Αποτυχία βαθμονόμησης" +#define D_RESET_HX711 "Αρχικοποίηση ζυγαριάς" +#define D_CONFIGURE_HX711 "Ρύθμιση ζυγαριάς" +#define D_HX711_PARAMETERS "Παράμετροι ζυγαριάς" +#define D_ITEM_WEIGHT "Βάρος αντικειμένου" +#define D_REFERENCE_WEIGHT "Βάρος αναφοράς" +#define D_CALIBRATE "Βαθμονόμησε" +#define D_CALIBRATION "Βαθμονόμηση" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Κατεύθυνση ανέμου" +#define D_TX20_WIND_SPEED "Ταχύτητα ανέμου" +#define D_TX20_WIND_SPEED_AVG "Μέση ταχύτητα ανέμου" +#define D_TX20_WIND_SPEED_MAX "Μέγιστη ταχύτητα ανέμου" +#define D_TX20_NORTH "Β" +#define D_TX20_EAST "Α" +#define D_TX20_SOUTH "Ν" +#define D_TX20_WEST "Δ" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Κανένα" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_EL_GR_H_ diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 257a34c86..42d9d6100 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -1,701 +1,703 @@ -/* - en-GB.h - localization for English - United Kingdom for Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_EN_GB_H_ -#define _LANGUAGE_EN_GB_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.11 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -// https://www.science.co.il/language/Locale-codes.php -#define LANGUAGE_LCID 2057 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "en" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "SunMonTueWedThuFriSat" -#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Air quality" -#define D_AP "AP" // Access Point -#define D_AS "as" -#define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Boot Count" -#define D_BRIGHTLIGHT "Bright" -#define D_BSSID "BSSId" -#define D_BUTTON "Button" -#define D_BY "by" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Channel" -#define D_CO2 "Carbon dioxide" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "Cold" -#define D_COMMAND "Command" -#define D_CONNECTED "Connected" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Count" -#define D_COUNTER "Counter" -#define D_CURRENT "Current" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Dark" -#define D_DEBUG "Debug" -#define D_DISABLED "Disabled" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Done" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulation" -#define D_ENABLED "Enabled" -#define D_ERASE "Erase" -#define D_ERROR "Error" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Failed" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "False" -#define D_FILE "File" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Free Memory" -#define D_FREQUENCY "Frequency" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Group" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" -#define D_HUMIDITY "Humidity" -#define D_ILLUMINANCE "Illuminance" -#define D_IMMEDIATE "immediate" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "Initialized" -#define D_IP_ADDRESS "IP Address" -#define D_LIGHT "Light" -#define D_LWT "LWT" -#define D_MODULE "Module" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "Noise" -#define D_NONE "None" -#define D_OFF "Off" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "On" -#define D_ONLINE "Online" -#define D_PASSWORD "Password" -#define D_PORT "Port" -#define D_POWER_FACTOR "Power Factor" -#define D_POWERUSAGE "Power" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "Pressure" -#define D_PRESSUREATSEALEVEL "SeaPressure" -#define D_PROGRAM_FLASH_SIZE "Program Flash Size" -#define D_PROGRAM_SIZE "Program Size" -#define D_PROJECT "Project" -#define D_RAIN "Rain" -#define D_RECEIVED "Received" -#define D_RESTART "Restart" -#define D_RESTARTING "Restarting" -#define D_RESTART_REASON "Restart Reason" -#define D_RESTORE "restore" -#define D_RETAINED "retained" -#define D_RULE "Rule" -#define D_SAVE "Save" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Subnet Mask" -#define D_SUBSCRIBE_TO "Subscribe to" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Successful" -#define D_SUNRISE "Sunrise" -#define D_SUNSET "Sunset" -#define D_TEMPERATURE "Temperature" -#define D_TO "to" -#define D_TOGGLE "Toggle" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Transmit" -#define D_TRUE "True" -#define D_TVOC "TVOC" -#define D_UPGRADE "upgrade" -#define D_UPLOAD "Upload" -#define D_UPTIME "Uptime" -#define D_USER "User" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" // Out of Range -#define D_UV_LEVEL "UV Level" -#define D_UV_POWER "UV Power" -#define D_VERSION "Version" -#define D_VOLTAGE "Voltage" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "Warm" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial logging disabled" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logging re-enabled" - -#define D_SET_BAUDRATE_TO "Set Baudrate to" -#define D_RECEIVED_TOPIC "Received Topic" -#define D_DATA_SIZE "Data Size" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" -#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" -#define D_FAILED_TO_START "failed to start" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Connecting to AP" -#define D_IN_MODE "in mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connect failed as no IP address received" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Connect failed as AP cannot be reached" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password" -#define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout" -#define D_ATTEMPTING_CONNECTION "Attempting connection..." -#define D_CHECKING_CONNECTION "Checking connection..." -#define D_QUERY_DONE "Query done. MQTT services found" -#define D_MQTT_SERVICE_FOUND "MQTT service found on" -#define D_FOUND_AT "found at" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Saved to flash at" -#define D_LOADED_FROM_FLASH_AT "Loaded from flash at" -#define D_USE_DEFAULTS "Use defaults" -#define D_ERASED_SECTOR "Erased sector" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
please upgrade" -#define D_WEBSERVER_ACTIVE_ON "Web server active on" -#define D_WITH_IP_ADDRESS "with IP address" -#define D_WEBSERVER_STOPPED "Web server stopped" -#define D_FILE_NOT_FOUND "File Not Found" -#define D_REDIRECTED "Redirected to captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" -#define D_TRYING_TO_CONNECT "Trying to connect device to network" - -#define D_RESTART_IN "Restart in" -#define D_SECONDS "seconds" -#define D_DEVICE_WILL_RESTART "Device will restart in a few seconds" -#define D_BUTTON_TOGGLE "Toggle" -#define D_CONFIGURATION "Configuration" -#define D_INFORMATION "Information" -#define D_FIRMWARE_UPGRADE "Firmware Upgrade" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Confirm Restart" - -#define D_CONFIGURE_MODULE "Configure Module" -#define D_CONFIGURE_WIFI "Configure WiFi" -#define D_CONFIGURE_MQTT "Configure MQTT" -#define D_CONFIGURE_DOMOTICZ "Configure Domoticz" -#define D_CONFIGURE_LOGGING "Configure Logging" -#define D_CONFIGURE_OTHER "Configure Other" -#define D_CONFIRM_RESET_CONFIGURATION "Confirm Reset Configuration" -#define D_RESET_CONFIGURATION "Reset Configuration" -#define D_BACKUP_CONFIGURATION "Backup Configuration" -#define D_RESTORE_CONFIGURATION "Restore Configuration" -#define D_MAIN_MENU "Main Menu" - -#define D_MODULE_PARAMETERS "Module parameters" -#define D_MODULE_TYPE "Module type" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Wifi parameters" -#define D_SCAN_FOR_WIFI_NETWORKS "Scan for wifi networks" -#define D_SCAN_DONE "Scan done" -#define D_NO_NETWORKS_FOUND "No networks found" -#define D_REFRESH_TO_SCAN_AGAIN "Refresh to scan again" -#define D_DUPLICATE_ACCESSPOINT "Duplicate AccessPoint" -#define D_SKIPPING_LOW_QUALITY "Skipping due to low quality" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Password" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Password" - -#define D_MQTT_PARAMETERS "MQTT parameters" -#define D_CLIENT "Client" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "Logging parameters" -#define D_SERIAL_LOG_LEVEL "Serial log level" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web log level" -#define D_SYS_LOG_LEVEL "Syslog level" -#define D_MORE_DEBUG "More debug" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Telemetry period" - -#define D_OTHER_PARAMETERS "Other parameters" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Web Admin Password" -#define D_MQTT_ENABLE "MQTT enable" -#define D_FRIENDLY_NAME "Friendly Name" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Save configuration" -#define D_CONFIGURATION_SAVED "Configuration saved" -#define D_CONFIGURATION_RESET "Configuration reset" - -#define D_PROGRAM_VERSION "Program Version" -#define D_BUILD_DATE_AND_TIME "Build Date & Time" -#define D_CORE_AND_SDK_VERSION "Core/SDK Version" -#define D_FLASH_WRITE_COUNT "Flash write Count" -#define D_MAC_ADDRESS "MAC Address" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Port" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT User" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Size" -#define D_FREE_PROGRAM_SPACE "Free Program Space" - -#define D_UPGRADE_BY_WEBSERVER "Upgrade by web server" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Start upgrade" -#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade by file upload" -#define D_UPLOAD_STARTED "Upload started" -#define D_UPGRADE_STARTED "Upgrade started" -#define D_UPLOAD_DONE "Upload done" -#define D_UPLOAD_ERR_1 "No file selected" -#define D_UPLOAD_ERR_2 "Not enough space" -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" -#define D_UPLOAD_ERR_4 "Program flash size is larger than real flash size" -#define D_UPLOAD_ERR_5 "Upload buffer miscompare" -#define D_UPLOAD_ERR_6 "Upload failed. Enable logging 3" -#define D_UPLOAD_ERR_7 "Upload aborted" -#define D_UPLOAD_ERR_8 "File invalid" -#define D_UPLOAD_ERR_9 "File too large" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Upload error code" - -#define D_ENTER_COMMAND "Enter command" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" -#define D_NEED_USER_AND_PASSWORD "Need user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verify TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" -#define D_RETRY_IN "Retry in" -#define D_VERIFIED "Verified using Fingerprint" -#define D_INSECURE "Insecure connection due to invalid Fingerprint" -#define D_CONNECT_FAILED_TO "Connect failed to" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast disabled" -#define D_MULTICAST_REJOINED "Multicast (re)joined" -#define D_MULTICAST_JOIN_FAILED "Multicast join failed" -#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Response sent" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configure Timer" -#define D_TIMER_PARAMETERS "Timer parameters" -#define D_TIMER_ENABLE "Enable Timers" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configure KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energy Today" -#define D_ENERGY_YESTERDAY "Energy Yesterday" -#define D_ENERGY_TOTAL "Energy Total" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor busy" -#define D_SENSOR_CRC_ERROR "Sensor CRC error" -#define D_SENSORS_FOUND "Sensors found" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" -#define D_START_SIGNAL_LOW "start signal low" -#define D_START_SIGNAL_HIGH "start signal high" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "Checksum failure" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" -#define D_SHT1X_FOUND "SHT1X found" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_EN_GB_H_ +/* + en-GB.h - localization for English - United Kingdom for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_EN_GB_H_ +#define _LANGUAGE_EN_GB_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.11 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 2057 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "en" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "SunMonTueWedThuFriSat" +#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Air quality" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Boot Count" +#define D_BRIGHTLIGHT "Bright" +#define D_BSSID "BSSId" +#define D_BUTTON "Button" +#define D_BY "by" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" +#define D_CO2 "Carbon dioxide" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "Cold" +#define D_COMMAND "Command" +#define D_CONNECTED "Connected" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Count" +#define D_COUNTER "Counter" +#define D_CURRENT "Current" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Dark" +#define D_DEBUG "Debug" +#define D_DISABLED "Disabled" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "DNS Server" +#define D_DONE "Done" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulation" +#define D_ENABLED "Enabled" +#define D_ERASE "Erase" +#define D_ERROR "Error" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Failed" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "False" +#define D_FILE "File" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Free Memory" +#define D_FREQUENCY "Frequency" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Group" +#define D_HOST "Host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Humidity" +#define D_ILLUMINANCE "Illuminance" +#define D_IMMEDIATE "immediate" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infrared" +#define D_INITIALIZED "Initialized" +#define D_IP_ADDRESS "IP Address" +#define D_LIGHT "Light" +#define D_LWT "LWT" +#define D_MODULE "Module" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "Noise" +#define D_NONE "None" +#define D_OFF "Off" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "On" +#define D_ONLINE "Online" +#define D_PASSWORD "Password" +#define D_PORT "Port" +#define D_POWER_FACTOR "Power Factor" +#define D_POWERUSAGE "Power" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "Pressure" +#define D_PRESSUREATSEALEVEL "SeaPressure" +#define D_PROGRAM_FLASH_SIZE "Program Flash Size" +#define D_PROGRAM_SIZE "Program Size" +#define D_PROJECT "Project" +#define D_RAIN "Rain" +#define D_RECEIVED "Received" +#define D_RESTART "Restart" +#define D_RESTARTING "Restarting" +#define D_RESTART_REASON "Restart Reason" +#define D_RESTORE "restore" +#define D_RETAINED "retained" +#define D_RULE "Rule" +#define D_SAVE "Save" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Subnet Mask" +#define D_SUBSCRIBE_TO "Subscribe to" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Successful" +#define D_SUNRISE "Sunrise" +#define D_SUNSET "Sunset" +#define D_TEMPERATURE "Temperature" +#define D_TO "to" +#define D_TOGGLE "Toggle" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Transmit" +#define D_TRUE "True" +#define D_TVOC "TVOC" +#define D_UPGRADE "upgrade" +#define D_UPLOAD "Upload" +#define D_UPTIME "Uptime" +#define D_USER "User" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range +#define D_UV_LEVEL "UV Level" +#define D_UV_POWER "UV Power" +#define D_VERSION "Version" +#define D_VOLTAGE "Voltage" +#define D_WEIGHT "Weight" +#define D_WARMLIGHT "Warm" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial logging disabled" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logging re-enabled" + +#define D_SET_BAUDRATE_TO "Set Baudrate to" +#define D_RECEIVED_TOPIC "Received Topic" +#define D_DATA_SIZE "Data Size" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" +#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" +#define D_FAILED_TO_START "failed to start" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Connecting to AP" +#define D_IN_MODE "in mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connect failed as no IP address received" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Connect failed as AP cannot be reached" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password" +#define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout" +#define D_ATTEMPTING_CONNECTION "Attempting connection..." +#define D_CHECKING_CONNECTION "Checking connection..." +#define D_QUERY_DONE "Query done. MQTT services found" +#define D_MQTT_SERVICE_FOUND "MQTT service found on" +#define D_FOUND_AT "found at" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Saved to flash at" +#define D_LOADED_FROM_FLASH_AT "Loaded from flash at" +#define D_USE_DEFAULTS "Use defaults" +#define D_ERASED_SECTOR "Erased sector" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
please upgrade" +#define D_WEBSERVER_ACTIVE_ON "Web server active on" +#define D_WITH_IP_ADDRESS "with IP address" +#define D_WEBSERVER_STOPPED "Web server stopped" +#define D_FILE_NOT_FOUND "File Not Found" +#define D_REDIRECTED "Redirected to captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" +#define D_TRYING_TO_CONNECT "Trying to connect device to network" + +#define D_RESTART_IN "Restart in" +#define D_SECONDS "seconds" +#define D_DEVICE_WILL_RESTART "Device will restart in a few seconds" +#define D_BUTTON_TOGGLE "Toggle" +#define D_CONFIGURATION "Configuration" +#define D_INFORMATION "Information" +#define D_FIRMWARE_UPGRADE "Firmware Upgrade" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Confirm Restart" + +#define D_CONFIGURE_MODULE "Configure Module" +#define D_CONFIGURE_WIFI "Configure WiFi" +#define D_CONFIGURE_MQTT "Configure MQTT" +#define D_CONFIGURE_DOMOTICZ "Configure Domoticz" +#define D_CONFIGURE_LOGGING "Configure Logging" +#define D_CONFIGURE_OTHER "Configure Other" +#define D_CONFIRM_RESET_CONFIGURATION "Confirm Reset Configuration" +#define D_RESET_CONFIGURATION "Reset Configuration" +#define D_BACKUP_CONFIGURATION "Backup Configuration" +#define D_RESTORE_CONFIGURATION "Restore Configuration" +#define D_MAIN_MENU "Main Menu" + +#define D_MODULE_PARAMETERS "Module parameters" +#define D_MODULE_TYPE "Module type" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Wifi parameters" +#define D_SCAN_FOR_WIFI_NETWORKS "Scan for wifi networks" +#define D_SCAN_DONE "Scan done" +#define D_NO_NETWORKS_FOUND "No networks found" +#define D_REFRESH_TO_SCAN_AGAIN "Refresh to scan again" +#define D_DUPLICATE_ACCESSPOINT "Duplicate AccessPoint" +#define D_SKIPPING_LOW_QUALITY "Skipping due to low quality" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Password" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Password" + +#define D_MQTT_PARAMETERS "MQTT parameters" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "Logging parameters" +#define D_SERIAL_LOG_LEVEL "Serial log level" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web log level" +#define D_SYS_LOG_LEVEL "Syslog level" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Telemetry period" + +#define D_OTHER_PARAMETERS "Other parameters" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Web Admin Password" +#define D_MQTT_ENABLE "MQTT enable" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Save configuration" +#define D_CONFIGURATION_SAVED "Configuration saved" +#define D_CONFIGURATION_RESET "Configuration reset" + +#define D_PROGRAM_VERSION "Program Version" +#define D_BUILD_DATE_AND_TIME "Build Date & Time" +#define D_CORE_AND_SDK_VERSION "Core/SDK Version" +#define D_FLASH_WRITE_COUNT "Flash write Count" +#define D_MAC_ADDRESS "MAC Address" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Port" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT User" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash Size" +#define D_FREE_PROGRAM_SPACE "Free Program Space" + +#define D_UPGRADE_BY_WEBSERVER "Upgrade by web server" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Start upgrade" +#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade by file upload" +#define D_UPLOAD_STARTED "Upload started" +#define D_UPGRADE_STARTED "Upgrade started" +#define D_UPLOAD_DONE "Upload done" +#define D_UPLOAD_ERR_1 "No file selected" +#define D_UPLOAD_ERR_2 "Not enough space" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "Program flash size is larger than real flash size" +#define D_UPLOAD_ERR_5 "Upload buffer miscompare" +#define D_UPLOAD_ERR_6 "Upload failed. Enable logging 3" +#define D_UPLOAD_ERR_7 "Upload aborted" +#define D_UPLOAD_ERR_8 "File invalid" +#define D_UPLOAD_ERR_9 "File too large" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "Upload error code" + +#define D_ENTER_COMMAND "Enter command" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" +#define D_NEED_USER_AND_PASSWORD "Need user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verify TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" +#define D_RETRY_IN "Retry in" +#define D_VERIFIED "Verified using Fingerprint" +#define D_INSECURE "Insecure connection due to invalid Fingerprint" +#define D_CONNECT_FAILED_TO "Connect failed to" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast disabled" +#define D_MULTICAST_REJOINED "Multicast (re)joined" +#define D_MULTICAST_JOIN_FAILED "Multicast join failed" +#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Response sent" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configure Timer" +#define D_TIMER_PARAMETERS "Timer parameters" +#define D_TIMER_ENABLE "Enable Timers" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Time" +#define D_TIMER_DAYS "Days" +#define D_TIMER_REPEAT "Repeat" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configure KNX" +#define D_KNX_PARAMETERS "KNX Parameters" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Physical Address" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "Enable KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Add" +#define D_DELETE "Delete" +#define D_REPLY "Reply" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Write" +#define D_KNX_COMMAND_READ "Read" +#define D_KNX_COMMAND_OTHER "Other" +#define D_SENT_TO "sent to" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energy Today" +#define D_ENERGY_YESTERDAY "Energy Yesterday" +#define D_ENERGY_TOTAL "Energy Total" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor busy" +#define D_SENSOR_CRC_ERROR "Sensor CRC error" +#define D_SENSORS_FOUND "Sensors found" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" +#define D_START_SIGNAL_LOW "start signal low" +#define D_START_SIGNAL_HIGH "start signal high" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "Checksum failure" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_EN_GB_H_ diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 7527bb77a..4c98d8ebe 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -1,701 +1,703 @@ -/* - es-ES.h - localization for Spanish - Spain for Tasmota - - Copyright (C) 2019 Adrian Scillato - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_ES_ES_H_ -#define _LANGUAGE_ES_ES_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.0.0.5 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1034 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "es" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DomLunMarMieJueVieSab" -#define D_MONTH3LIST "EneFebMarAbrMayJunJulAgoSepOctNovDic" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Calidad del Aire" -#define D_AP "AP" // Access Point -#define D_AS "como" -#define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Conteo Reinicios" -#define D_BRIGHTLIGHT "Brillante" -#define D_BSSID "BSSId" -#define D_BUTTON "Botón" -#define D_BY "por" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canal" -#define D_CO2 "CO2" -#define D_CODE "código" // Button code -#define D_COLDLIGHT "Fría" -#define D_COMMAND "Comando" -#define D_CONNECTED "Conectado" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Conteo" -#define D_COUNTER "Contador" -#define D_CURRENT "Corriente" // As in Voltage and Current -#define D_DATA "Datos" -#define D_DARKLIGHT "Oscuro" -#define D_DEBUG "Debug" -#define D_DISABLED "Deshabilitado" -#define D_DISTANCE "Distancia" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Listo" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulación" -#define D_ENABLED "Habilitado" -#define D_ERASE "Borrar" -#define D_ERROR "Error" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Falló" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "FallbackTopic" -#define D_FALSE "Falso" -#define D_FILE "Archivo" -#define D_FLOW_RATE "Caudal" -#define D_FREE_MEMORY "Memoria Libre" -#define D_FREQUENCY "Frecuencia" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Grupo" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" -#define D_HUMIDITY "Humedad" -#define D_ILLUMINANCE "Luminancia" -#define D_IMMEDIATE "inmediato" // Button immediate -#define D_INDEX "Índice" -#define D_INFO "Información" -#define D_INFRARED "Infrarrojo" -#define D_INITIALIZED "Inicializado" -#define D_IP_ADDRESS "Dirección IP" -#define D_LIGHT "Luz" -#define D_LWT "LWT" -#define D_MODULE "Módulo" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "Ruido" -#define D_NONE "Ninguno" -#define D_OFF "Apagado" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "Encendido" -#define D_ONLINE "Online" -#define D_PASSWORD "Clave" -#define D_PORT "Puerto" -#define D_POWER_FACTOR "Factor de Potencia" -#define D_POWERUSAGE "Potencia" -#define D_POWERUSAGE_ACTIVE "Potencia Activa" -#define D_POWERUSAGE_APPARENT "Potencia Aparente" -#define D_POWERUSAGE_REACTIVE "Potencia Reactiva" -#define D_PRESSURE "Presión" -#define D_PRESSUREATSEALEVEL "Presión al nivel del mar" -#define D_PROGRAM_FLASH_SIZE "Tamaño de Flash de Programa" -#define D_PROGRAM_SIZE "Tamaño Programa" -#define D_PROJECT "Proyecto" -#define D_RAIN "Lluvia" -#define D_RECEIVED "Recibido" -#define D_RESTART "Reiniciar" -#define D_RESTARTING "Reiniciando" -#define D_RESTART_REASON "Causa Reinicio" -#define D_RESTORE "Restauración" -#define D_RETAINED "Grabado" -#define D_RULE "Regla" -#define D_SAVE "Grabar" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Iniciar" -#define D_STD_TIME "STD" -#define D_STOP "Detener" -#define D_SUBNET_MASK "Máscara Subred" -#define D_SUBSCRIBE_TO "Suscribir a" -#define D_UNSUBSCRIBE_FROM "Desuscribirse de" -#define D_SUCCESSFUL "Exitosa" -#define D_SUNRISE "Salida del Sol" -#define D_SUNSET "Puesta del Sol" -#define D_TEMPERATURE "Temperatura" -#define D_TO "a" -#define D_TOGGLE "Conmutar" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usado" -#define D_TRANSMIT "Transmitir" -#define D_TRUE "Verdadero" -#define D_TVOC "TVOC" -#define D_UPGRADE "Actualización" -#define D_UPLOAD "Carga" -#define D_UPTIME "Tiempo Encendido" -#define D_USER "Usuario" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Índice UV" -#define D_UV_INDEX_1 "Bajo" -#define D_UV_INDEX_2 "Medio" -#define D_UV_INDEX_3 "Alto" -#define D_UV_INDEX_4 "Peligroso" -#define D_UV_INDEX_5 "Quemaduras 1 a 2 grad" -#define D_UV_INDEX_6 "Quemaduras 3 grad" -#define D_UV_INDEX_7 "Fuera de Rango" -#define D_UV_LEVEL "Nivel UV" -#define D_UV_POWER "UV Power" -#define D_VERSION "Versión" -#define D_VOLTAGE "Tensión" -#define D_WEIGHT "Peso" -#define D_WARMLIGHT "Cálida" -#define D_WEB_SERVER "Servidor Web" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "Cuidado, esta versión no guarda los cambios" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Log serial deshabilitado" -#define D_SYSLOG_LOGGING_REENABLED "Syslog re-habilitado" - -#define D_SET_BAUDRATE_TO "Baudrate a" -#define D_RECEIVED_TOPIC "Topic Recibido" -#define D_DATA_SIZE "Tamaño de Datos" -#define D_ANALOG_INPUT "Entrada Analógica" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Ciclo Bloqueado" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALLÓ con estado" -#define D_ACTIVE_FOR_3_MINUTES "activo por 3 minutos" -#define D_FAILED_TO_START "falló inicio" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Connectando a AP" -#define D_IN_MODE "en modo" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Falló Conexión, Dirección IP no recibida" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Falló Conexión, AP no pudo ser contactado" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Falló Conexión, clave de AP incorrecta" -#define D_CONNECT_FAILED_AP_TIMEOUT "Falló Conexión, timeout de AP" -#define D_ATTEMPTING_CONNECTION "Intentando conectar..." -#define D_CHECKING_CONNECTION "Probando conexión..." -#define D_QUERY_DONE "Consulta lista. Servicio MQTT encontrado" -#define D_MQTT_SERVICE_FOUND "Servicio MQTT encontrado en" -#define D_FOUND_AT "encontrado en" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host no encontrado" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Grabado a la flash en" -#define D_LOADED_FROM_FLASH_AT "Cargado desde flash en" -#define D_USE_DEFAULTS "Usar valores por defecto" -#define D_ERASED_SECTOR "Sector borrado" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" -#define D_WEBSERVER_ACTIVE_ON "Servidor web activo en" -#define D_WITH_IP_ADDRESS "con dirección IP" -#define D_WEBSERVER_STOPPED "Servidor web detenido" -#define D_FILE_NOT_FOUND "Archivo No Encontrado" -#define D_REDIRECTED "Redireccionado al portal captivo" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager como AccessPoint y Estación" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager como AccessPoint" -#define D_TRYING_TO_CONNECT "Intentado conectar dispositivo a la red" - -#define D_RESTART_IN "Reinicio en" -#define D_SECONDS "segundos" -#define D_DEVICE_WILL_RESTART "El dispositivo se reiniciará en unos segundos" -#define D_BUTTON_TOGGLE "Alternar ON/OFF" -#define D_CONFIGURATION "Configuración" -#define D_INFORMATION "Información" -#define D_FIRMWARE_UPGRADE "Actualizar Firmware" -#define D_CONSOLE "Consola" -#define D_CONFIRM_RESTART "Confirmar Reinicio" - -#define D_CONFIGURE_MODULE "Configuración del Módulo" -#define D_CONFIGURE_WIFI "Configuración WiFi" -#define D_CONFIGURE_MQTT "Configuración MQTT" -#define D_CONFIGURE_DOMOTICZ "Configuración Domoticz" -#define D_CONFIGURE_LOGGING "Configuración Logging" -#define D_CONFIGURE_OTHER "Configuración Extra" -#define D_CONFIRM_RESET_CONFIGURATION "Confirmar Reset Configuración" -#define D_RESET_CONFIGURATION "Reset de Configuración" -#define D_BACKUP_CONFIGURATION "Backup de Configuración" -#define D_RESTORE_CONFIGURATION "Restaurar Configuración" -#define D_MAIN_MENU "Menú Principal" - -#define D_MODULE_PARAMETERS "Parámetros del módulo" -#define D_MODULE_TYPE "Tipo de módulo" -#define D_PULLUP_ENABLE "Botón/Llave sin pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Parámetros Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Buscar redes wifi" -#define D_SCAN_DONE "Busqueda finalizada" -#define D_NO_NETWORKS_FOUND "Ninguna red encontrada" -#define D_REFRESH_TO_SCAN_AGAIN "Recargar página para buscar nuevamente" -#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicado" -#define D_SKIPPING_LOW_QUALITY "Ignorado por baja calidad" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "SSId AP1" -#define D_AP1_PASSWORD "Clave AP1" -#define D_AP2_SSID "SSId AP2" -#define D_AP2_PASSWORD "Clave AP2" - -#define D_MQTT_PARAMETERS "Parámetros MQTT" -#define D_CLIENT "Cliente" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "Parámetros Logging" -#define D_SERIAL_LOG_LEVEL "Nivel de log por Serial" -#define D_MQTT_LOG_LEVEL "Nivel de log por Mqtt" -#define D_WEB_LOG_LEVEL "Nivel de log por Web" -#define D_SYS_LOG_LEVEL "Nivel de log por Syslog" -#define D_MORE_DEBUG "Más Debug" -#define D_SYSLOG_HOST "Host del Syslog" -#define D_SYSLOG_PORT "Puerto del Syslog" -#define D_TELEMETRY_PERIOD "Período de Telemetría" - -#define D_OTHER_PARAMETERS "Otros parámetros" -#define D_TEMPLATE "Plantilla" -#define D_ACTIVATE "Activar" -#define D_WEB_ADMIN_PASSWORD "Clave Administrador Web" -#define D_MQTT_ENABLE "Habilitar MQTT" -#define D_FRIENDLY_NAME "Nombre Amigable" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "dispositivo simple" -#define D_MULTI_DEVICE "dispositivo múltiple" - -#define D_CONFIGURE_TEMPLATE "Configurar Plantilla" -#define D_TEMPLATE_PARAMETERS "Parámetros de Plantilla" -#define D_TEMPLATE_NAME "Nombre" -#define D_BASE_TYPE "Basada en" -#define D_TEMPLATE_FLAGS "Opciones" - -#define D_SAVE_CONFIGURATION "Grabar configuración" -#define D_CONFIGURATION_SAVED "Configuración grabada" -#define D_CONFIGURATION_RESET "Configuración restablecida" - -#define D_PROGRAM_VERSION "Versión del Programa" -#define D_BUILD_DATE_AND_TIME "Fecha y Hora de Compilación" -#define D_CORE_AND_SDK_VERSION "Versión Core/SDK" -#define D_FLASH_WRITE_COUNT "Contador de escritura en Flash" -#define D_MAC_ADDRESS "Dirección MAC" -#define D_MQTT_HOST "Host MQTT" -#define D_MQTT_PORT "Puerto MQTT" -#define D_MQTT_CLIENT "Cliente MQTT" -#define D_MQTT_USER "Usuario MQTT" -#define D_MQTT_TOPIC "Topic MQTT" -#define D_MQTT_GROUP_TOPIC "Group Topic MQTT" -#define D_MQTT_FULL_TOPIC "Full Topic MQTT" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Tamaño Flash" -#define D_FREE_PROGRAM_SPACE "Memoria de Programa Libre" - -#define D_UPGRADE_BY_WEBSERVER "Actualizar por servidor web" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Comenzar actualización" -#define D_UPGRADE_BY_FILE_UPLOAD "Actualizar cargando archivo bin" -#define D_UPLOAD_STARTED "Cargando archivo" -#define D_UPGRADE_STARTED "Actualización iniciada" -#define D_UPLOAD_DONE "Carga finalizada" -#define D_UPLOAD_ERR_1 "Ningún archivo seleccionado" -#define D_UPLOAD_ERR_2 "Espacio insuficiente" -#define D_UPLOAD_ERR_3 "Magic byte no corresponde a 0xE9" -#define D_UPLOAD_ERR_4 "El tamaño de la memoria de programa es mayor que la de la flash" -#define D_UPLOAD_ERR_5 "Error de comparación del buffer de carga" -#define D_UPLOAD_ERR_6 "Carga fallida. Habilitar logging 3" -#define D_UPLOAD_ERR_7 "Carga cancelada" -#define D_UPLOAD_ERR_8 "Archivo no válido" -#define D_UPLOAD_ERR_9 "Archivo muy grande" -#define D_UPLOAD_ERR_10 "No inició chip RF" -#define D_UPLOAD_ERR_11 "No se pudo borrar en el chip RF" -#define D_UPLOAD_ERR_12 "No se puedo escribir en el chip RF" -#define D_UPLOAD_ERR_13 "No se pudo decodificar firmware RF" -#define D_UPLOAD_ERROR_CODE "Código de error de carga" - -#define D_ENTER_COMMAND "Ingresar comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 si desea respuesta" -#define D_NEED_USER_AND_PASSWORD "Se necesita user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verificar TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "Falló Conexión TLS a" -#define D_RETRY_IN "Reintentando" -#define D_VERIFIED "Verificado Fingerprint" -#define D_INSECURE "Conexión insegura por Fingerprint inválido" -#define D_CONNECT_FAILED_TO "Falló Conexión a" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast deshabilitado" -#define D_MULTICAST_REJOINED "Multicast (re)conectado" -#define D_MULTICAST_JOIN_FAILED "Conexión Multicast fallida" -#define D_FAILED_TO_SEND_RESPONSE "Falla al enviar respuesta" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "Evento base de WeMo" -#define D_WEMO_EVENT_SERVICE "Evento de servicio de WeMo" -#define D_WEMO_META_SERVICE "Meta Servicio de WeMo" -#define D_WEMO_SETUP "Configuración de WeMo" -#define D_RESPONSE_SENT "Respuesta enviada" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Configuración Hue" -#define D_HUE_API_NOT_IMPLEMENTED "API de Hue no implementada" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 paquetes de respuesta enviados" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parámetros Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Potencia,Energía" - #define D_DOMOTICZ_ILLUMINANCE "Luminancia" - #define D_DOMOTICZ_COUNT "Contador/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltaje/PM2,5" - #define D_DOMOTICZ_CURRENT "Corriente/PM10" - #define D_DOMOTICZ_AIRQUALITY "Calidad del Aire" - #define D_DOMOTICZ_P1_SMART_METER "Medidor Inteligente P1" -#define D_DOMOTICZ_UPDATE_TIMER "Intervalo de refresco" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configuración Temporizadores" -#define D_TIMER_PARAMETERS "Parámetros de Temporizadores" -#define D_TIMER_ENABLE "Habilitar Temporizadores" -#define D_TIMER_ARM "Activo" -#define D_TIMER_TIME "Hora" -#define D_TIMER_DAYS "Días" -#define D_TIMER_REPEAT "Repetir" -#define D_TIMER_OUTPUT "Salida" -#define D_TIMER_ACTION "Estado" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configuración de KNX" -#define D_KNX_PARAMETERS "Parámetros de KNX" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Dirección Física" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Debe ser única en la red KNX )" -#define D_KNX_ENABLE "Habilitar KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Datos a Enviar a las Direcciones de Grupo" -#define D_ADD "Agregar" -#define D_DELETE "Eliminar" -#define D_REPLY "Responder" -#define D_KNX_GROUP_ADDRESS_TO_READ "Direcciones de Grupo para Recibir Datos" -#define D_RECEIVED_FROM "Recibido desde" -#define D_KNX_COMMAND_WRITE "Escribir" -#define D_KNX_COMMAND_READ "Leer" -#define D_KNX_COMMAND_OTHER "Otro" -#define D_SENT_TO "enviada a" -#define D_KNX_WARNING "La dirección de grupo ( 0 / 0 / 0 ) está reservada y no puede ser utilizada." -#define D_KNX_ENHANCEMENT "Mejora de Comunicación" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energía Hoy" -#define D_ENERGY_YESTERDAY "Energía Ayer" -#define D_ENERGY_TOTAL "Energía Total" - -// xdrv_27_shutter.ino -#define D_OPEN "Abrir" -#define D_CLOSE "Cerrar" -#define D_DOMOTICZ_SHUTTER "Cortina" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configurar PCF8574" -#define D_PCF8574_PARAMETERS "Parámetros de PCF8574" -#define D_INVERT_PORTS "Invertir Puertos" -#define D_DEVICE "Dispositivo" -#define D_DEVICE_INPUT "Entrada" -#define D_DEVICE_OUTPUT "Salida" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor ocupado" -#define D_SENSOR_CRC_ERROR "Error CRC del Sensor" -#define D_SENSORS_FOUND "Sensores encontrados" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Espera de timeout por" -#define D_START_SIGNAL_LOW "iniciar señal baja" -#define D_START_SIGNAL_HIGH "iniciar señal alta" -#define D_PULSE "pulso" -#define D_CHECKSUM_FAILURE "Falló Checksum" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor no ha enviado el comando ACK" -#define D_SHT1X_FOUND "SHT1X encontrado" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partículas" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remover Peso" -#define D_HX_CAL_REFERENCE "Poner Peso de Referencia" -#define D_HX_CAL_DONE "Calibrado" -#define D_HX_CAL_FAIL "Falló Calibración" -#define D_RESET_HX711 "Restablecer Escala" -#define D_CONFIGURE_HX711 "Configurar Escala" -#define D_HX711_PARAMETERS "Parámetros de Escala" -#define D_ITEM_WEIGHT "Peso" -#define D_REFERENCE_WEIGHT "Peso de Referencia" -#define D_CALIBRATE "Calibrar" -#define D_CALIBRATION "Calibración" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Dirección del Viento" -#define D_TX20_WIND_SPEED "Vel. del Viento" -#define D_TX20_WIND_SPEED_AVG "Vel. Prom. del Viento" -#define D_TX20_WIND_SPEED_MAX "Vel. Max. del Viento" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Ninguno" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IR Tx" -#define D_SENSOR_SWITCH "Llave" // Suffix "1" -#define D_SENSOR_BUTTON "Botón" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Contador" // Suffix "1" -#define D_SENSOR_IRRECV "IR Rx" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "seg" -#define D_UNIT_SECTORS "sectores" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Ángulo de Fase" -#define D_IMPORT_ACTIVE "P. Activa Entrante" -#define D_EXPORT_ACTIVE "P. Activa Saliente" -#define D_IMPORT_REACTIVE "P. Reactiva Entrante" -#define D_EXPORT_REACTIVE "P. Reactiva Saliente" -#define D_TOTAL_REACTIVE "P. Reactiva Total" -#define D_UNIT_KWARH "kVArH" -#define D_UNIT_ANGLE "Grados" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltaje" -#define D_PV1_CURRENT "PV1 Corriente" -#define D_PV1_POWER "PV1 Potencia" -#define D_PV2_VOLTAGE "PV2 Voltaee" -#define D_PV2_CURRENT "PV2 Corriente" -#define D_PV2_POWER "PV2 Potencia" -#define D_SOLAR_POWER "Potencia Solar" -#define D_INVERTER_POWER "Potencia del Inversor" -#define D_STATUS "Estado" -#define D_WAITING "En Espera" -#define D_CHECKING "Revisando" -#define D_WORKING "Funcionando" -#define D_FAILURE "Falla" -#define D_SOLAX_ERROR_0 "Sin código de Error" -#define D_SOLAX_ERROR_1 "Falla por Pérdida de Red" -#define D_SOLAX_ERROR_2 "Falla por Voltaje de Red" -#define D_SOLAX_ERROR_3 "Falla por Frecuencia de Red" -#define D_SOLAX_ERROR_4 "Falla por Voltaje en PV" -#define D_SOLAX_ERROR_5 "Falla de Aislación" -#define D_SOLAX_ERROR_6 "Falla por sobretemperatura" -#define D_SOLAX_ERROR_7 "Falla de Ventilador" -#define D_SOLAX_ERROR_8 "Falla del Dispositivo" - -#endif // _LANGUAGE_ES_ES_H_ +/* + es-ES.h - localization for Spanish - Spain for Tasmota + + Copyright (C) 2019 Adrian Scillato + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_ES_ES_H_ +#define _LANGUAGE_ES_ES_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.0.0.5 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1034 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "es" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DomLunMarMieJueVieSab" +#define D_MONTH3LIST "EneFebMarAbrMayJunJulAgoSepOctNovDic" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Calidad del Aire" +#define D_AP "AP" // Access Point +#define D_AS "como" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Conteo Reinicios" +#define D_BRIGHTLIGHT "Brillante" +#define D_BSSID "BSSId" +#define D_BUTTON "Botón" +#define D_BY "por" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "CO2" +#define D_CODE "código" // Button code +#define D_COLDLIGHT "Fría" +#define D_COMMAND "Comando" +#define D_CONNECTED "Conectado" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Conteo" +#define D_COUNTER "Contador" +#define D_CURRENT "Corriente" // As in Voltage and Current +#define D_DATA "Datos" +#define D_DARKLIGHT "Oscuro" +#define D_DEBUG "Debug" +#define D_DISABLED "Deshabilitado" +#define D_DISTANCE "Distancia" +#define D_DNS_SERVER "DNS Server" +#define D_DONE "Listo" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulación" +#define D_ENABLED "Habilitado" +#define D_ERASE "Borrar" +#define D_ERROR "Error" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Falló" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "FallbackTopic" +#define D_FALSE "Falso" +#define D_FILE "Archivo" +#define D_FLOW_RATE "Caudal" +#define D_FREE_MEMORY "Memoria Libre" +#define D_FREQUENCY "Frecuencia" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupo" +#define D_HOST "Host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Humedad" +#define D_ILLUMINANCE "Luminancia" +#define D_IMMEDIATE "inmediato" // Button immediate +#define D_INDEX "Índice" +#define D_INFO "Información" +#define D_INFRARED "Infrarrojo" +#define D_INITIALIZED "Inicializado" +#define D_IP_ADDRESS "Dirección IP" +#define D_LIGHT "Luz" +#define D_LWT "LWT" +#define D_MODULE "Módulo" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "Ruido" +#define D_NONE "Ninguno" +#define D_OFF "Apagado" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "Encendido" +#define D_ONLINE "Online" +#define D_PASSWORD "Clave" +#define D_PORT "Puerto" +#define D_POWER_FACTOR "Factor de Potencia" +#define D_POWERUSAGE "Potencia" +#define D_POWERUSAGE_ACTIVE "Potencia Activa" +#define D_POWERUSAGE_APPARENT "Potencia Aparente" +#define D_POWERUSAGE_REACTIVE "Potencia Reactiva" +#define D_PRESSURE "Presión" +#define D_PRESSUREATSEALEVEL "Presión al nivel del mar" +#define D_PROGRAM_FLASH_SIZE "Tamaño de Flash de Programa" +#define D_PROGRAM_SIZE "Tamaño Programa" +#define D_PROJECT "Proyecto" +#define D_RAIN "Lluvia" +#define D_RECEIVED "Recibido" +#define D_RESTART "Reiniciar" +#define D_RESTARTING "Reiniciando" +#define D_RESTART_REASON "Causa Reinicio" +#define D_RESTORE "Restauración" +#define D_RETAINED "Grabado" +#define D_RULE "Regla" +#define D_SAVE "Grabar" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Iniciar" +#define D_STD_TIME "STD" +#define D_STOP "Detener" +#define D_SUBNET_MASK "Máscara Subred" +#define D_SUBSCRIBE_TO "Suscribir a" +#define D_UNSUBSCRIBE_FROM "Desuscribirse de" +#define D_SUCCESSFUL "Exitosa" +#define D_SUNRISE "Salida del Sol" +#define D_SUNSET "Puesta del Sol" +#define D_TEMPERATURE "Temperatura" +#define D_TO "a" +#define D_TOGGLE "Conmutar" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usado" +#define D_TRANSMIT "Transmitir" +#define D_TRUE "Verdadero" +#define D_TVOC "TVOC" +#define D_UPGRADE "Actualización" +#define D_UPLOAD "Carga" +#define D_UPTIME "Tiempo Encendido" +#define D_USER "Usuario" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Índice UV" +#define D_UV_INDEX_1 "Bajo" +#define D_UV_INDEX_2 "Medio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Peligroso" +#define D_UV_INDEX_5 "Quemaduras 1 a 2 grad" +#define D_UV_INDEX_6 "Quemaduras 3 grad" +#define D_UV_INDEX_7 "Fuera de Rango" +#define D_UV_LEVEL "Nivel UV" +#define D_UV_POWER "UV Power" +#define D_VERSION "Versión" +#define D_VOLTAGE "Tensión" +#define D_WEIGHT "Peso" +#define D_WARMLIGHT "Cálida" +#define D_WEB_SERVER "Servidor Web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "Cuidado, esta versión no guarda los cambios" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Log serial deshabilitado" +#define D_SYSLOG_LOGGING_REENABLED "Syslog re-habilitado" + +#define D_SET_BAUDRATE_TO "Baudrate a" +#define D_RECEIVED_TOPIC "Topic Recibido" +#define D_DATA_SIZE "Tamaño de Datos" +#define D_ANALOG_INPUT "Entrada Analógica" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Ciclo Bloqueado" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALLÓ con estado" +#define D_ACTIVE_FOR_3_MINUTES "activo por 3 minutos" +#define D_FAILED_TO_START "falló inicio" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Connectando a AP" +#define D_IN_MODE "en modo" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Falló Conexión, Dirección IP no recibida" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Falló Conexión, AP no pudo ser contactado" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Falló Conexión, clave de AP incorrecta" +#define D_CONNECT_FAILED_AP_TIMEOUT "Falló Conexión, timeout de AP" +#define D_ATTEMPTING_CONNECTION "Intentando conectar..." +#define D_CHECKING_CONNECTION "Probando conexión..." +#define D_QUERY_DONE "Consulta lista. Servicio MQTT encontrado" +#define D_MQTT_SERVICE_FOUND "Servicio MQTT encontrado en" +#define D_FOUND_AT "encontrado en" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host no encontrado" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Grabado a la flash en" +#define D_LOADED_FROM_FLASH_AT "Cargado desde flash en" +#define D_USE_DEFAULTS "Usar valores por defecto" +#define D_ERASED_SECTOR "Sector borrado" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" +#define D_WEBSERVER_ACTIVE_ON "Servidor web activo en" +#define D_WITH_IP_ADDRESS "con dirección IP" +#define D_WEBSERVER_STOPPED "Servidor web detenido" +#define D_FILE_NOT_FOUND "Archivo No Encontrado" +#define D_REDIRECTED "Redireccionado al portal captivo" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager como AccessPoint y Estación" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager como AccessPoint" +#define D_TRYING_TO_CONNECT "Intentado conectar dispositivo a la red" + +#define D_RESTART_IN "Reinicio en" +#define D_SECONDS "segundos" +#define D_DEVICE_WILL_RESTART "El dispositivo se reiniciará en unos segundos" +#define D_BUTTON_TOGGLE "Alternar ON/OFF" +#define D_CONFIGURATION "Configuración" +#define D_INFORMATION "Información" +#define D_FIRMWARE_UPGRADE "Actualizar Firmware" +#define D_CONSOLE "Consola" +#define D_CONFIRM_RESTART "Confirmar Reinicio" + +#define D_CONFIGURE_MODULE "Configuración del Módulo" +#define D_CONFIGURE_WIFI "Configuración WiFi" +#define D_CONFIGURE_MQTT "Configuración MQTT" +#define D_CONFIGURE_DOMOTICZ "Configuración Domoticz" +#define D_CONFIGURE_LOGGING "Configuración Logging" +#define D_CONFIGURE_OTHER "Configuración Extra" +#define D_CONFIRM_RESET_CONFIGURATION "Confirmar Reset Configuración" +#define D_RESET_CONFIGURATION "Reset de Configuración" +#define D_BACKUP_CONFIGURATION "Backup de Configuración" +#define D_RESTORE_CONFIGURATION "Restaurar Configuración" +#define D_MAIN_MENU "Menú Principal" + +#define D_MODULE_PARAMETERS "Parámetros del módulo" +#define D_MODULE_TYPE "Tipo de módulo" +#define D_PULLUP_ENABLE "Botón/Llave sin pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Parámetros Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Buscar redes wifi" +#define D_SCAN_DONE "Busqueda finalizada" +#define D_NO_NETWORKS_FOUND "Ninguna red encontrada" +#define D_REFRESH_TO_SCAN_AGAIN "Recargar página para buscar nuevamente" +#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicado" +#define D_SKIPPING_LOW_QUALITY "Ignorado por baja calidad" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "SSId AP1" +#define D_AP1_PASSWORD "Clave AP1" +#define D_AP2_SSID "SSId AP2" +#define D_AP2_PASSWORD "Clave AP2" + +#define D_MQTT_PARAMETERS "Parámetros MQTT" +#define D_CLIENT "Cliente" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "Parámetros Logging" +#define D_SERIAL_LOG_LEVEL "Nivel de log por Serial" +#define D_MQTT_LOG_LEVEL "Nivel de log por Mqtt" +#define D_WEB_LOG_LEVEL "Nivel de log por Web" +#define D_SYS_LOG_LEVEL "Nivel de log por Syslog" +#define D_MORE_DEBUG "Más Debug" +#define D_SYSLOG_HOST "Host del Syslog" +#define D_SYSLOG_PORT "Puerto del Syslog" +#define D_TELEMETRY_PERIOD "Período de Telemetría" + +#define D_OTHER_PARAMETERS "Otros parámetros" +#define D_TEMPLATE "Plantilla" +#define D_ACTIVATE "Activar" +#define D_WEB_ADMIN_PASSWORD "Clave Administrador Web" +#define D_MQTT_ENABLE "Habilitar MQTT" +#define D_FRIENDLY_NAME "Nombre Amigable" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "dispositivo simple" +#define D_MULTI_DEVICE "dispositivo múltiple" + +#define D_CONFIGURE_TEMPLATE "Configurar Plantilla" +#define D_TEMPLATE_PARAMETERS "Parámetros de Plantilla" +#define D_TEMPLATE_NAME "Nombre" +#define D_BASE_TYPE "Basada en" +#define D_TEMPLATE_FLAGS "Opciones" + +#define D_SAVE_CONFIGURATION "Grabar configuración" +#define D_CONFIGURATION_SAVED "Configuración grabada" +#define D_CONFIGURATION_RESET "Configuración restablecida" + +#define D_PROGRAM_VERSION "Versión del Programa" +#define D_BUILD_DATE_AND_TIME "Fecha y Hora de Compilación" +#define D_CORE_AND_SDK_VERSION "Versión Core/SDK" +#define D_FLASH_WRITE_COUNT "Contador de escritura en Flash" +#define D_MAC_ADDRESS "Dirección MAC" +#define D_MQTT_HOST "Host MQTT" +#define D_MQTT_PORT "Puerto MQTT" +#define D_MQTT_CLIENT "Cliente MQTT" +#define D_MQTT_USER "Usuario MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Group Topic MQTT" +#define D_MQTT_FULL_TOPIC "Full Topic MQTT" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Tamaño Flash" +#define D_FREE_PROGRAM_SPACE "Memoria de Programa Libre" + +#define D_UPGRADE_BY_WEBSERVER "Actualizar por servidor web" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Comenzar actualización" +#define D_UPGRADE_BY_FILE_UPLOAD "Actualizar cargando archivo bin" +#define D_UPLOAD_STARTED "Cargando archivo" +#define D_UPGRADE_STARTED "Actualización iniciada" +#define D_UPLOAD_DONE "Carga finalizada" +#define D_UPLOAD_ERR_1 "Ningún archivo seleccionado" +#define D_UPLOAD_ERR_2 "Espacio insuficiente" +#define D_UPLOAD_ERR_3 "Magic byte no corresponde a 0xE9" +#define D_UPLOAD_ERR_4 "El tamaño de la memoria de programa es mayor que la de la flash" +#define D_UPLOAD_ERR_5 "Error de comparación del buffer de carga" +#define D_UPLOAD_ERR_6 "Carga fallida. Habilitar logging 3" +#define D_UPLOAD_ERR_7 "Carga cancelada" +#define D_UPLOAD_ERR_8 "Archivo no válido" +#define D_UPLOAD_ERR_9 "Archivo muy grande" +#define D_UPLOAD_ERR_10 "No inició chip RF" +#define D_UPLOAD_ERR_11 "No se pudo borrar en el chip RF" +#define D_UPLOAD_ERR_12 "No se puedo escribir en el chip RF" +#define D_UPLOAD_ERR_13 "No se pudo decodificar firmware RF" +#define D_UPLOAD_ERROR_CODE "Código de error de carga" + +#define D_ENTER_COMMAND "Ingresar comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 si desea respuesta" +#define D_NEED_USER_AND_PASSWORD "Se necesita user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verificar TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "Falló Conexión TLS a" +#define D_RETRY_IN "Reintentando" +#define D_VERIFIED "Verificado Fingerprint" +#define D_INSECURE "Conexión insegura por Fingerprint inválido" +#define D_CONNECT_FAILED_TO "Falló Conexión a" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast deshabilitado" +#define D_MULTICAST_REJOINED "Multicast (re)conectado" +#define D_MULTICAST_JOIN_FAILED "Conexión Multicast fallida" +#define D_FAILED_TO_SEND_RESPONSE "Falla al enviar respuesta" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "Evento base de WeMo" +#define D_WEMO_EVENT_SERVICE "Evento de servicio de WeMo" +#define D_WEMO_META_SERVICE "Meta Servicio de WeMo" +#define D_WEMO_SETUP "Configuración de WeMo" +#define D_RESPONSE_SENT "Respuesta enviada" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Configuración Hue" +#define D_HUE_API_NOT_IMPLEMENTED "API de Hue no implementada" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 paquetes de respuesta enviados" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parámetros Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Potencia,Energía" + #define D_DOMOTICZ_ILLUMINANCE "Luminancia" + #define D_DOMOTICZ_COUNT "Contador/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltaje/PM2,5" + #define D_DOMOTICZ_CURRENT "Corriente/PM10" + #define D_DOMOTICZ_AIRQUALITY "Calidad del Aire" + #define D_DOMOTICZ_P1_SMART_METER "Medidor Inteligente P1" +#define D_DOMOTICZ_UPDATE_TIMER "Intervalo de refresco" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configuración Temporizadores" +#define D_TIMER_PARAMETERS "Parámetros de Temporizadores" +#define D_TIMER_ENABLE "Habilitar Temporizadores" +#define D_TIMER_ARM "Activo" +#define D_TIMER_TIME "Hora" +#define D_TIMER_DAYS "Días" +#define D_TIMER_REPEAT "Repetir" +#define D_TIMER_OUTPUT "Salida" +#define D_TIMER_ACTION "Estado" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configuración de KNX" +#define D_KNX_PARAMETERS "Parámetros de KNX" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Dirección Física" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Debe ser única en la red KNX )" +#define D_KNX_ENABLE "Habilitar KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Datos a Enviar a las Direcciones de Grupo" +#define D_ADD "Agregar" +#define D_DELETE "Eliminar" +#define D_REPLY "Responder" +#define D_KNX_GROUP_ADDRESS_TO_READ "Direcciones de Grupo para Recibir Datos" +#define D_RECEIVED_FROM "Recibido desde" +#define D_KNX_COMMAND_WRITE "Escribir" +#define D_KNX_COMMAND_READ "Leer" +#define D_KNX_COMMAND_OTHER "Otro" +#define D_SENT_TO "enviada a" +#define D_KNX_WARNING "La dirección de grupo ( 0 / 0 / 0 ) está reservada y no puede ser utilizada." +#define D_KNX_ENHANCEMENT "Mejora de Comunicación" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energía Hoy" +#define D_ENERGY_YESTERDAY "Energía Ayer" +#define D_ENERGY_TOTAL "Energía Total" + +// xdrv_27_shutter.ino +#define D_OPEN "Abrir" +#define D_CLOSE "Cerrar" +#define D_DOMOTICZ_SHUTTER "Cortina" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configurar PCF8574" +#define D_PCF8574_PARAMETERS "Parámetros de PCF8574" +#define D_INVERT_PORTS "Invertir Puertos" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Entrada" +#define D_DEVICE_OUTPUT "Salida" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor ocupado" +#define D_SENSOR_CRC_ERROR "Error CRC del Sensor" +#define D_SENSORS_FOUND "Sensores encontrados" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Espera de timeout por" +#define D_START_SIGNAL_LOW "iniciar señal baja" +#define D_START_SIGNAL_HIGH "iniciar señal alta" +#define D_PULSE "pulso" +#define D_CHECKSUM_FAILURE "Falló Checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor no ha enviado el comando ACK" +#define D_SHT1X_FOUND "SHT1X encontrado" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partículas" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remover Peso" +#define D_HX_CAL_REFERENCE "Poner Peso de Referencia" +#define D_HX_CAL_DONE "Calibrado" +#define D_HX_CAL_FAIL "Falló Calibración" +#define D_RESET_HX711 "Restablecer Escala" +#define D_CONFIGURE_HX711 "Configurar Escala" +#define D_HX711_PARAMETERS "Parámetros de Escala" +#define D_ITEM_WEIGHT "Peso" +#define D_REFERENCE_WEIGHT "Peso de Referencia" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibración" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Dirección del Viento" +#define D_TX20_WIND_SPEED "Vel. del Viento" +#define D_TX20_WIND_SPEED_AVG "Vel. Prom. del Viento" +#define D_TX20_WIND_SPEED_MAX "Vel. Max. del Viento" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Ninguno" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IR Tx" +#define D_SENSOR_SWITCH "Llave" // Suffix "1" +#define D_SENSOR_BUTTON "Botón" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Contador" // Suffix "1" +#define D_SENSOR_IRRECV "IR Rx" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "seg" +#define D_UNIT_SECTORS "sectores" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Ángulo de Fase" +#define D_IMPORT_ACTIVE "P. Activa Entrante" +#define D_EXPORT_ACTIVE "P. Activa Saliente" +#define D_IMPORT_REACTIVE "P. Reactiva Entrante" +#define D_EXPORT_REACTIVE "P. Reactiva Saliente" +#define D_TOTAL_REACTIVE "P. Reactiva Total" +#define D_UNIT_KWARH "kVArH" +#define D_UNIT_ANGLE "Grados" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltaje" +#define D_PV1_CURRENT "PV1 Corriente" +#define D_PV1_POWER "PV1 Potencia" +#define D_PV2_VOLTAGE "PV2 Voltaee" +#define D_PV2_CURRENT "PV2 Corriente" +#define D_PV2_POWER "PV2 Potencia" +#define D_SOLAR_POWER "Potencia Solar" +#define D_INVERTER_POWER "Potencia del Inversor" +#define D_STATUS "Estado" +#define D_WAITING "En Espera" +#define D_CHECKING "Revisando" +#define D_WORKING "Funcionando" +#define D_FAILURE "Falla" +#define D_SOLAX_ERROR_0 "Sin código de Error" +#define D_SOLAX_ERROR_1 "Falla por Pérdida de Red" +#define D_SOLAX_ERROR_2 "Falla por Voltaje de Red" +#define D_SOLAX_ERROR_3 "Falla por Frecuencia de Red" +#define D_SOLAX_ERROR_4 "Falla por Voltaje en PV" +#define D_SOLAX_ERROR_5 "Falla de Aislación" +#define D_SOLAX_ERROR_6 "Falla por sobretemperatura" +#define D_SOLAX_ERROR_7 "Falla de Ventilador" +#define D_SOLAX_ERROR_8 "Falla del Dispositivo" + +#endif // _LANGUAGE_ES_ES_H_ diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index e107409e3..7b8d291b8 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -1,701 +1,703 @@ -/* - fr-FR.h - localization for French - France for Tasmota - - Copyright (C) 2019 Olivier Francais - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_FR_FR_H_ -#define _LANGUAGE_FR_FR_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.1.2.4 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1036 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "fr" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DimLunMarMerJeuVenSam" -#define D_MONTH3LIST "JanFevMarAvrMaiJunJulAutSepOctNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Qualité de l'Air" -#define D_AP "AP" // Access Point -#define D_AS "comme" -#define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Nombre de boot" -#define D_BRIGHTLIGHT "Luminosité" -#define D_BSSID "BSSId" -#define D_BUTTON "Bouton" -#define D_BY "par" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canal" -#define D_CO2 "Dioxyde de carbone" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "Froid" -#define D_COMMAND "Commande" -#define D_CONNECTED "Connecté" -#define D_CORS_DOMAIN "Domaine CORS" -#define D_COUNT "Compte" -#define D_COUNTER "Compteur" -#define D_CURRENT "Courant" // As in Voltage and Current -#define D_DATA "Donnée" -#define D_DARKLIGHT "Sombre" -#define D_DEBUG "Debug" -#define D_DISABLED "Désactivé" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "Serveur DNS" -#define D_DONE "Fait" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Émulation" -#define D_ENABLED "Activé" -#define D_ERASE "Effacer" -#define D_ERROR "Erreur" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Échoué" -#define D_FALLBACK "Secours" -#define D_FALLBACK_TOPIC "Topic de secours" -#define D_FALSE "Faux" -#define D_FILE "Fichier" -#define D_FLOW_RATE "Débit" -#define D_FREE_MEMORY "Mémoire libre" -#define D_FREQUENCY "Fréquence" -#define D_GAS "Gaz" -#define D_GATEWAY "Passerelle" -#define D_GROUP "Groupe" -#define D_HOST "Hôte" -#define D_HOSTNAME "Nom d'Hôte" -#define D_HUMIDITY "Humidité" -#define D_ILLUMINANCE "Éclairement" -#define D_IMMEDIATE "immédiat" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infra-rouge" -#define D_INITIALIZED "Initialisé" -#define D_IP_ADDRESS "Adresse IP" -#define D_LIGHT "Lumière" -#define D_LWT "LWT" -#define D_MODULE "Module" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-pression" -#define D_NOISE "Bruit" -#define D_NONE "Aucun" -#define D_OFF "Arrêt" -#define D_OFFLINE "Déconnecté" -#define D_OK "Ok" -#define D_ON "Marche" -#define D_ONLINE "Connecté" -#define D_PASSWORD "Mot de passe" -#define D_PORT "Port" -#define D_POWER_FACTOR "Fact de puiss" -#define D_POWERUSAGE "Puissance" -#define D_POWERUSAGE_ACTIVE "Puiss active" -#define D_POWERUSAGE_APPARENT "Puiss apparente" -#define D_POWERUSAGE_REACTIVE "Puiss réactive" -#define D_PRESSURE "Pression" -#define D_PRESSUREATSEALEVEL "PressionMer" -#define D_PROGRAM_FLASH_SIZE "Taille Flash Programme" -#define D_PROGRAM_SIZE "Taille programme" -#define D_PROJECT "Projet" -#define D_RAIN "Pluie" -#define D_RECEIVED "Reçu" -#define D_RESTART "Redémarrage" -#define D_RESTARTING "Redémarre" -#define D_RESTART_REASON "Raison du redémarrage" -#define D_RESTORE "restaurer" -#define D_RETAINED "persistant" // MQTT -#define D_RULE "Règle" -#define D_SAVE "Enregistrer" -#define D_SENSOR "Capteur" -#define D_SSID "SSID" -#define D_START "Lancer" // "Lancer la mise à jour" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Masque sous-réseau" -#define D_SUBSCRIBE_TO "S'abonner à" -#define D_UNSUBSCRIBE_FROM "Se désabonner de" -#define D_SUCCESSFUL "Réussi" -#define D_SUNRISE "Lever du jour" -#define D_SUNSET "Tombée de la nuit" -#define D_TEMPERATURE "Température" -#define D_TO "à" -#define D_TOGGLE "Inverser" -#define D_TOPIC "Topic" // Keep MQTT keyword -#define D_TOTAL_USAGE "Eau totale" -#define D_TRANSMIT "Transmettre" -#define D_TRUE "Vrai" -#define D_TVOC "TVOC" -#define D_UPGRADE "la mise à jour" // "Lancer la mise à jour" -#define D_UPLOAD "Upload" // Not better in french -#define D_UPTIME "Durée d'activité" -#define D_USER "Utilisateur" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Indice UV" -#define D_UV_INDEX_1 "Faible" -#define D_UV_INDEX_2 "Modéré" -#define D_UV_INDEX_3 "Élevé" -#define D_UV_INDEX_4 "Très élevé" -#define D_UV_INDEX_5 "Brûlure niv.1/2" -#define D_UV_INDEX_6 "Brûlure niv.3" -#define D_UV_INDEX_7 "Hors échelle" -#define D_UV_LEVEL "Niveau UV" -#define D_UV_POWER "Puissance UV" -#define D_VERSION "Version" -#define D_VOLTAGE "Tension" -#define D_WEIGHT "Poids" -#define D_WARMLIGHT "Chaud" -#define D_WEB_SERVER "Serveur web" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ATTENTION Cette version ne supporte pas les réglages persistants" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivée" -#define D_SYSLOG_LOGGING_REENABLED "Jounalisation SysLog réactivée" - -#define D_SET_BAUDRATE_TO "Définir le débit à" -#define D_RECEIVED_TOPIC "Topic reçu" // Terme MQTT -#define D_DATA_SIZE "Taille données" -#define D_ANALOG_INPUT "Analogique" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Boucle bloquée" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig ÉCHOUÉ avec status" -#define D_ACTIVE_FOR_3_MINUTES "actif pour 3 minutes" -#define D_FAILED_TO_START "Échec de démarrage" -#define D_PATCH_ISSUE_2186 "Correction 2186" -#define D_CONNECTING_TO_AP "Connexion à l'AP" -#define D_IN_MODE "en mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Échec de connexion car aucune adresse IP n'a été reçue" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Échec de connexion car l'AP ne peut-être contacté" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Échec de connexion car le mot de passe de l'AP est incorrect" -#define D_CONNECT_FAILED_AP_TIMEOUT "Échec de connexion avec l'AP, expiré" -#define D_ATTEMPTING_CONNECTION "Tentative de connexion..." -#define D_CHECKING_CONNECTION "Vérification connexion..." -#define D_QUERY_DONE "Requête terminée. Services MQTT trouvés" -#define D_MQTT_SERVICE_FOUND "Service MQTT trouvé sur" -#define D_FOUND_AT "trouvé à" -#define D_SYSLOG_HOST_NOT_FOUND "Hôte SysLog introuvable" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Enregistré en flash à" -#define D_LOADED_FROM_FLASH_AT "Chargé de la flash à" -#define D_USE_DEFAULTS "Utiliser par défaut" -#define D_ERASED_SECTOR "Secteur effacé" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" -#define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur" -#define D_WITH_IP_ADDRESS "avec l'adresse IP" -#define D_WEBSERVER_STOPPED "Serveur web éteint" -#define D_FILE_NOT_FOUND "Fichier introuvable" -#define D_REDIRECTED "Redirection sur le portail captif" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager en mode Point d'Accès et Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager en mode Point d'Accès" -#define D_TRYING_TO_CONNECT "Tentative de connexion du module au réseau" - -#define D_RESTART_IN "Redémarrage dans" -#define D_SECONDS "secondes" -#define D_DEVICE_WILL_RESTART "Le module va redémarrer dans quelques secondes" -#define D_BUTTON_TOGGLE "on/off" -#define D_CONFIGURATION "Configuration" -#define D_INFORMATION "Informations" -#define D_FIRMWARE_UPGRADE "Mise à jour du Firmware" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Confirmer redémarrage" - -#define D_CONFIGURE_MODULE "Configuration du Module" -#define D_CONFIGURE_WIFI "Configuration WiFi" -#define D_CONFIGURE_MQTT "Configuration MQTT" -#define D_CONFIGURE_DOMOTICZ "Configuration Domoticz" -#define D_CONFIGURE_LOGGING "Configuration du journal" -#define D_CONFIGURE_OTHER "Autre configuration" -#define D_CONFIRM_RESET_CONFIGURATION "Confirmer la réinit. de la config." -#define D_RESET_CONFIGURATION "Configuration par défaut" -#define D_BACKUP_CONFIGURATION "Sauvegarde de la config." -#define D_RESTORE_CONFIGURATION "Restauration de la config." -#define D_MAIN_MENU "Menu principal" - -#define D_MODULE_PARAMETERS "Paramètres module" -#define D_MODULE_TYPE "Type de module" -#define D_PULLUP_ENABLE "Inter. sans pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Entrée série" -#define D_SERIAL_OUT "Sortie série" - -#define D_WIFI_PARAMETERS "Paramètres Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Scan des réseaux wifi" -#define D_SCAN_DONE "Scan terminé" -#define D_NO_NETWORKS_FOUND "Aucun réseau trouvé" -#define D_REFRESH_TO_SCAN_AGAIN "Rafraîchir pour scanner à nouveau" -#define D_DUPLICATE_ACCESSPOINT "Point d'Accès dupliqué" -#define D_SKIPPING_LOW_QUALITY "Évité car de mauvaise qualité" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "Mot de passe AP1" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "Mot de passe AP2" - -#define D_MQTT_PARAMETERS "Paramètres MQTT" -#define D_CLIENT "Client" -#define D_FULL_TOPIC "Topic complet" - -#define D_LOGGING_PARAMETERS "Paramètres du journal" -#define D_SERIAL_LOG_LEVEL "Niveau de journalisation série" -#define D_MQTT_LOG_LEVEL "Niveau de journalisation MQTT" -#define D_WEB_LOG_LEVEL "Niveau de journalisation web" -#define D_SYS_LOG_LEVEL "Niveau SysLog" -#define D_MORE_DEBUG "Plus de debug" -#define D_SYSLOG_HOST "Hôte SysLog" -#define D_SYSLOG_PORT "Port SysLog" -#define D_TELEMETRY_PERIOD "Période télémétrie" - -#define D_OTHER_PARAMETERS "Autres paramètres" -#define D_TEMPLATE "Modèle" -#define D_ACTIVATE "Activer" -#define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin" -#define D_MQTT_ENABLE "MQTT activé" -#define D_FRIENDLY_NAME "Surnom" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "module unique" -#define D_MULTI_DEVICE "multi module" - -#define D_CONFIGURE_TEMPLATE "Configuration du modèle" -#define D_TEMPLATE_PARAMETERS "Paramètres du modèle" -#define D_TEMPLATE_NAME "Nom" -#define D_BASE_TYPE "Basé sur" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Enregistrer la configuration" -#define D_CONFIGURATION_SAVED "Configuration enregistrée" -#define D_CONFIGURATION_RESET "Configuration réinitialisée" - -#define D_PROGRAM_VERSION "Version du programme" -#define D_BUILD_DATE_AND_TIME "Date & Heure de build" -#define D_CORE_AND_SDK_VERSION "Version Core/SDK" -#define D_FLASH_WRITE_COUNT "Compteur écriture flash" -#define D_MAC_ADDRESS "Adresse MAC" -#define D_MQTT_HOST "Hôte MQTT" -#define D_MQTT_PORT "Port MQTT" -#define D_MQTT_CLIENT "Client MQTT" -#define D_MQTT_USER "Utilisateur MQTT" -#define D_MQTT_TOPIC "Topic MQTT" -#define D_MQTT_GROUP_TOPIC "Groupe topic MQTT" -#define D_MQTT_FULL_TOPIC "Topic complet MQTT" -#define D_MDNS_DISCOVERY "Découverte mDNS" -#define D_MDNS_ADVERTISE "Annonce mDNS" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Taille flash" -#define D_FREE_PROGRAM_SPACE "Espace programme libre" - -#define D_UPGRADE_BY_WEBSERVER "Mise à jour par serveur web" -#define D_OTA_URL "URL OTA" -#define D_START_UPGRADE "Lancer la mise à jour" -#define D_UPGRADE_BY_FILE_UPLOAD "Mise à jour par téléchargement fichier" -#define D_UPLOAD_STARTED "Téléchargement lancé" -#define D_UPGRADE_STARTED "Mise à jour lancée" -#define D_UPLOAD_DONE "Téléchargement terminé" -#define D_UPLOAD_ERR_1 "Aucun fichier sélectionné" -#define D_UPLOAD_ERR_2 "Espace insuffisant" -#define D_UPLOAD_ERR_3 "L'octet magique n'est pas 0xE9" -#define D_UPLOAD_ERR_4 "La taille du programme à flasher est plus grande que la taille réelle de la mémoire flash" -#define D_UPLOAD_ERR_5 "Erreur de comparaison du buffer de téléchargement" -#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer WebLog 3" -#define D_UPLOAD_ERR_7 "Téléchargement annulé" -#define D_UPLOAD_ERR_8 "Fichier invalide" -#define D_UPLOAD_ERR_9 "Fichier trop grand" -#define D_UPLOAD_ERR_10 "Erreur d'initialisation du chip RF" -#define D_UPLOAD_ERR_11 "Erreur d'effacement du chip RF" -#define D_UPLOAD_ERR_12 "Erreur d'accès en écriture au chip RF" -#define D_UPLOAD_ERR_13 "Erreur de décodage du firmware RF" -#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement" - -#define D_ENTER_COMMAND "Saisir une commande" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer WebLog 2 si une réponse est attendue" -#define D_NEED_USER_AND_PASSWORD "Nécessite utilisateur=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Vérification d'empreinte TLS ..." -#define D_TLS_CONNECT_FAILED_TO "Échec de connexion TLS à" -#define D_RETRY_IN "Nouvelle tentative dans" -#define D_VERIFIED "Vérifié par empreinte " -#define D_INSECURE "Connexion non sécurisée car empreinte non vérifiée" -#define D_CONNECT_FAILED_TO "Échec de connexion à" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast désactivé" -#define D_MULTICAST_REJOINED "Multicast (re)joint" -#define D_MULTICAST_JOIN_FAILED "Multicast échec abonnement" -#define D_FAILED_TO_SEND_RESPONSE "Échec d'envoi réponse" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "Réglage WeMo" -#define D_RESPONSE_SENT "Réponse envoyée" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Réglage Hue" -#define D_HUE_API_NOT_IMPLEMENTED "API Hue non implémentée" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 paquets de réponse envoyés" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Paramètres Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Puissance,Énergie" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Compteur/PM1" - #define D_DOMOTICZ_VOLTAGE "Tension/PM2,5" - #define D_DOMOTICZ_CURRENT "Courant/PM10" - #define D_DOMOTICZ_AIRQUALITY "Qualité de l'air" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Durée de rafraichissement" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configuration des Timers" -#define D_TIMER_PARAMETERS "Paramètres Timer" -#define D_TIMER_ENABLE "Activer les Timers" -#define D_TIMER_ARM "Armer" -#define D_TIMER_TIME "Temps" -#define D_TIMER_DAYS "Jours" -#define D_TIMER_REPEAT "Répéter" -#define D_TIMER_OUTPUT "Sortie" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configuration de KNX" -#define D_KNX_PARAMETERS "Paramètres KNX" -#define D_KNX_GENERAL_CONFIG "Général" -#define D_KNX_PHYSICAL_ADDRESS "Adresse individuelle" // Backbone/Line/Device -> Zone/Ligne/Participant -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Doit être unique sur le réseau KNX)" -#define D_KNX_ENABLE "Activer KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Données à envoyer aux Adresses de Groupe" -#define D_ADD "Ajoûter" -#define D_DELETE "Supprimer" -#define D_REPLY "Répondre" -#define D_KNX_GROUP_ADDRESS_TO_READ "Données à recevoir des Adresses de Groupe" -#define D_RECEIVED_FROM "Reçu de" -#define D_KNX_COMMAND_WRITE "Écrire" -#define D_KNX_COMMAND_READ "Lire" -#define D_KNX_COMMAND_OTHER "Autre" -#define D_SENT_TO "envoyé à" -#define D_KNX_WARNING "L'Adresse de Groupe (0/0/0) est réservée et ne peut être utilisée." -#define D_KNX_ENHANCEMENT "Amélioration de la communication" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xsns_03_energy.ino -#define D_ENERGY_TODAY "Énergie aujourd'hui" -#define D_ENERGY_YESTERDAY "Énergie hier" -#define D_ENERGY_TOTAL "Énergie totale" - -// xdrv_27_shutter.ino -#define D_OPEN "Ouvert" -#define D_CLOSE "Fermé" -#define D_DOMOTICZ_SHUTTER "Volet" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configurer PCF8574" -#define D_PCF8574_PARAMETERS "Paramètres PCF8574" -#define D_INVERT_PORTS "Inverser les Ports" -#define D_DEVICE "Module" -#define D_DEVICE_INPUT "Entrée" -#define D_DEVICE_OUTPUT "Sortie" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Capteur occupé" -#define D_SENSOR_CRC_ERROR "Erreur CRC capteur" -#define D_SENSORS_FOUND "Capteur trouvé" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Expiration du délai" -#define D_START_SIGNAL_LOW "Signal Start bas" -#define D_START_SIGNAL_HIGH "Signal Start haut" -#define D_PULSE "Impulsion" -#define D_CHECKSUM_FAILURE "Erreur checksum" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Le capteur n'a pas acquitté la commande" -#define D_SHT1X_FOUND "SHT1X found" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particules" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accél. Axe-X" -#define D_AY_AXIS "Accél. Axe-Y" -#define D_AZ_AXIS "Accél. Axe-Z" -#define D_GX_AXIS "Gyro Axe-X" -#define D_GY_AXIS "Gyro Axe-Y" -#define D_GZ_AXIS "Gyro Axe-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Retirer la charge" -#define D_HX_CAL_REFERENCE "Charger l'étalon de poids" -#define D_HX_CAL_DONE "Étalonné" -#define D_HX_CAL_FAIL "L'étalonnage a échoué" -#define D_RESET_HX711 "Réinitialiser le capteur" -#define D_CONFIGURE_HX711 "Configurer le capteur" -#define D_HX711_PARAMETERS "Paramètres capteur" -#define D_ITEM_WEIGHT "Poids de l'objet" -#define D_REFERENCE_WEIGHT "Poids de référence" -#define D_CALIBRATE "Étalonner" -#define D_CALIBRATION "Étalonnage" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direction du vent" -#define D_TX20_WIND_SPEED "Vitesse du vent" -#define D_TX20_WIND_SPEED_AVG "Vitesse Moy." -#define D_TX20_WIND_SPEED_MAX "Vitesse Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Aucun" -#define D_SENSOR_USER "Utilisateur" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "ÉmetIR" -#define D_SENSOR_SWITCH "Inter." // Suffix "1" -#define D_SENSOR_BUTTON "Bouton" // Suffix "1" -#define D_SENSOR_RELAY "Relais" // Suffix "1i" -#define D_SENSOR_LED "LED" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Compteur" // Suffix "1" -#define D_SENSOR_IRRECV "RécptIR" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "RétroÉcl" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "gal/mn" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" -#define D_UNIT_KILOOHM "kΩ" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "mn" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "secteurs" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Angle de phase" -#define D_IMPORT_ACTIVE "Énergie act conso" -#define D_EXPORT_ACTIVE "Énergie act fournie" -#define D_IMPORT_REACTIVE "Énergie réa conso" -#define D_EXPORT_REACTIVE "Énergie réa fournie" -#define D_TOTAL_REACTIVE "Énergie réa totale" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "°" - -//SOLAXX1 -#define D_PV1_VOLTAGE "Tension PV1" -#define D_PV1_CURRENT "Courant PV1" -#define D_PV1_POWER "Puissance PV1" -#define D_PV2_VOLTAGE "Tension PV2" -#define D_PV2_CURRENT "Courant PV2" -#define D_PV2_POWER "Puissance PV2" -#define D_SOLAR_POWER "Puissance solaire" -#define D_INVERTER_POWER "Puissance onduleur" -#define D_STATUS "Statut" -#define D_WAITING "En attente" -#define D_CHECKING "En test" -#define D_WORKING "En marche" -#define D_FAILURE "Défault" -#define D_SOLAX_ERROR_0 "Aucun code d'erreur" -#define D_SOLAX_ERROR_1 "Défaut Perte de réseau" -#define D_SOLAX_ERROR_2 "Défaut Tension réseau" -#define D_SOLAX_ERROR_3 "Défaut Fréquence réseau" -#define D_SOLAX_ERROR_4 "Défaut Tension PV" -#define D_SOLAX_ERROR_5 "Défaut Isolation" -#define D_SOLAX_ERROR_6 "Défaut Surchauffe" -#define D_SOLAX_ERROR_7 "Défaut Ventilateur" -#define D_SOLAX_ERROR_8 "Défaut Autre équipement" - -#endif // _LANGUAGE_FR_FR_H_ +/* + fr-FR.h - localization for French - France for Tasmota + + Copyright (C) 2019 Olivier Francais + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_FR_FR_H_ +#define _LANGUAGE_FR_FR_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.1.2.4 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1036 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "fr" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DimLunMarMerJeuVenSam" +#define D_MONTH3LIST "JanFevMarAvrMaiJunJulAutSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Qualité de l'Air" +#define D_AP "AP" // Access Point +#define D_AS "comme" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Nombre de boot" +#define D_BRIGHTLIGHT "Luminosité" +#define D_BSSID "BSSId" +#define D_BUTTON "Bouton" +#define D_BY "par" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "Dioxyde de carbone" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "Froid" +#define D_COMMAND "Commande" +#define D_CONNECTED "Connecté" +#define D_CORS_DOMAIN "Domaine CORS" +#define D_COUNT "Compte" +#define D_COUNTER "Compteur" +#define D_CURRENT "Courant" // As in Voltage and Current +#define D_DATA "Donnée" +#define D_DARKLIGHT "Sombre" +#define D_DEBUG "Debug" +#define D_DISABLED "Désactivé" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "Serveur DNS" +#define D_DONE "Fait" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Émulation" +#define D_ENABLED "Activé" +#define D_ERASE "Effacer" +#define D_ERROR "Erreur" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Échoué" +#define D_FALLBACK "Secours" +#define D_FALLBACK_TOPIC "Topic de secours" +#define D_FALSE "Faux" +#define D_FILE "Fichier" +#define D_FLOW_RATE "Débit" +#define D_FREE_MEMORY "Mémoire libre" +#define D_FREQUENCY "Fréquence" +#define D_GAS "Gaz" +#define D_GATEWAY "Passerelle" +#define D_GROUP "Groupe" +#define D_HOST "Hôte" +#define D_HOSTNAME "Nom d'Hôte" +#define D_HUMIDITY "Humidité" +#define D_ILLUMINANCE "Éclairement" +#define D_IMMEDIATE "immédiat" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infra-rouge" +#define D_INITIALIZED "Initialisé" +#define D_IP_ADDRESS "Adresse IP" +#define D_LIGHT "Lumière" +#define D_LWT "LWT" +#define D_MODULE "Module" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-pression" +#define D_NOISE "Bruit" +#define D_NONE "Aucun" +#define D_OFF "Arrêt" +#define D_OFFLINE "Déconnecté" +#define D_OK "Ok" +#define D_ON "Marche" +#define D_ONLINE "Connecté" +#define D_PASSWORD "Mot de passe" +#define D_PORT "Port" +#define D_POWER_FACTOR "Fact de puiss" +#define D_POWERUSAGE "Puissance" +#define D_POWERUSAGE_ACTIVE "Puiss active" +#define D_POWERUSAGE_APPARENT "Puiss apparente" +#define D_POWERUSAGE_REACTIVE "Puiss réactive" +#define D_PRESSURE "Pression" +#define D_PRESSUREATSEALEVEL "PressionMer" +#define D_PROGRAM_FLASH_SIZE "Taille Flash Programme" +#define D_PROGRAM_SIZE "Taille programme" +#define D_PROJECT "Projet" +#define D_RAIN "Pluie" +#define D_RECEIVED "Reçu" +#define D_RESTART "Redémarrage" +#define D_RESTARTING "Redémarre" +#define D_RESTART_REASON "Raison du redémarrage" +#define D_RESTORE "restaurer" +#define D_RETAINED "persistant" // MQTT +#define D_RULE "Règle" +#define D_SAVE "Enregistrer" +#define D_SENSOR "Capteur" +#define D_SSID "SSID" +#define D_START "Lancer" // "Lancer la mise à jour" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Masque sous-réseau" +#define D_SUBSCRIBE_TO "S'abonner à" +#define D_UNSUBSCRIBE_FROM "Se désabonner de" +#define D_SUCCESSFUL "Réussi" +#define D_SUNRISE "Lever du jour" +#define D_SUNSET "Tombée de la nuit" +#define D_TEMPERATURE "Température" +#define D_TO "à" +#define D_TOGGLE "Inverser" +#define D_TOPIC "Topic" // Keep MQTT keyword +#define D_TOTAL_USAGE "Eau totale" +#define D_TRANSMIT "Transmettre" +#define D_TRUE "Vrai" +#define D_TVOC "TVOC" +#define D_UPGRADE "la mise à jour" // "Lancer la mise à jour" +#define D_UPLOAD "Upload" // Not better in french +#define D_UPTIME "Durée d'activité" +#define D_USER "Utilisateur" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Indice UV" +#define D_UV_INDEX_1 "Faible" +#define D_UV_INDEX_2 "Modéré" +#define D_UV_INDEX_3 "Élevé" +#define D_UV_INDEX_4 "Très élevé" +#define D_UV_INDEX_5 "Brûlure niv.1/2" +#define D_UV_INDEX_6 "Brûlure niv.3" +#define D_UV_INDEX_7 "Hors échelle" +#define D_UV_LEVEL "Niveau UV" +#define D_UV_POWER "Puissance UV" +#define D_VERSION "Version" +#define D_VOLTAGE "Tension" +#define D_WEIGHT "Poids" +#define D_WARMLIGHT "Chaud" +#define D_WEB_SERVER "Serveur web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ATTENTION Cette version ne supporte pas les réglages persistants" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivée" +#define D_SYSLOG_LOGGING_REENABLED "Jounalisation SysLog réactivée" + +#define D_SET_BAUDRATE_TO "Définir le débit à" +#define D_RECEIVED_TOPIC "Topic reçu" // Terme MQTT +#define D_DATA_SIZE "Taille données" +#define D_ANALOG_INPUT "Analogique" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Boucle bloquée" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig ÉCHOUÉ avec status" +#define D_ACTIVE_FOR_3_MINUTES "actif pour 3 minutes" +#define D_FAILED_TO_START "Échec de démarrage" +#define D_PATCH_ISSUE_2186 "Correction 2186" +#define D_CONNECTING_TO_AP "Connexion à l'AP" +#define D_IN_MODE "en mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Échec de connexion car aucune adresse IP n'a été reçue" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Échec de connexion car l'AP ne peut-être contacté" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Échec de connexion car le mot de passe de l'AP est incorrect" +#define D_CONNECT_FAILED_AP_TIMEOUT "Échec de connexion avec l'AP, expiré" +#define D_ATTEMPTING_CONNECTION "Tentative de connexion..." +#define D_CHECKING_CONNECTION "Vérification connexion..." +#define D_QUERY_DONE "Requête terminée. Services MQTT trouvés" +#define D_MQTT_SERVICE_FOUND "Service MQTT trouvé sur" +#define D_FOUND_AT "trouvé à" +#define D_SYSLOG_HOST_NOT_FOUND "Hôte SysLog introuvable" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Enregistré en flash à" +#define D_LOADED_FROM_FLASH_AT "Chargé de la flash à" +#define D_USE_DEFAULTS "Utiliser par défaut" +#define D_ERASED_SECTOR "Secteur effacé" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" +#define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur" +#define D_WITH_IP_ADDRESS "avec l'adresse IP" +#define D_WEBSERVER_STOPPED "Serveur web éteint" +#define D_FILE_NOT_FOUND "Fichier introuvable" +#define D_REDIRECTED "Redirection sur le portail captif" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager en mode Point d'Accès et Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager en mode Point d'Accès" +#define D_TRYING_TO_CONNECT "Tentative de connexion du module au réseau" + +#define D_RESTART_IN "Redémarrage dans" +#define D_SECONDS "secondes" +#define D_DEVICE_WILL_RESTART "Le module va redémarrer dans quelques secondes" +#define D_BUTTON_TOGGLE "on/off" +#define D_CONFIGURATION "Configuration" +#define D_INFORMATION "Informations" +#define D_FIRMWARE_UPGRADE "Mise à jour du Firmware" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Confirmer redémarrage" + +#define D_CONFIGURE_MODULE "Configuration du Module" +#define D_CONFIGURE_WIFI "Configuration WiFi" +#define D_CONFIGURE_MQTT "Configuration MQTT" +#define D_CONFIGURE_DOMOTICZ "Configuration Domoticz" +#define D_CONFIGURE_LOGGING "Configuration du journal" +#define D_CONFIGURE_OTHER "Autre configuration" +#define D_CONFIRM_RESET_CONFIGURATION "Confirmer la réinit. de la config." +#define D_RESET_CONFIGURATION "Configuration par défaut" +#define D_BACKUP_CONFIGURATION "Sauvegarde de la config." +#define D_RESTORE_CONFIGURATION "Restauration de la config." +#define D_MAIN_MENU "Menu principal" + +#define D_MODULE_PARAMETERS "Paramètres module" +#define D_MODULE_TYPE "Type de module" +#define D_PULLUP_ENABLE "Inter. sans pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Entrée série" +#define D_SERIAL_OUT "Sortie série" + +#define D_WIFI_PARAMETERS "Paramètres Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Scan des réseaux wifi" +#define D_SCAN_DONE "Scan terminé" +#define D_NO_NETWORKS_FOUND "Aucun réseau trouvé" +#define D_REFRESH_TO_SCAN_AGAIN "Rafraîchir pour scanner à nouveau" +#define D_DUPLICATE_ACCESSPOINT "Point d'Accès dupliqué" +#define D_SKIPPING_LOW_QUALITY "Évité car de mauvaise qualité" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "Mot de passe AP1" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "Mot de passe AP2" + +#define D_MQTT_PARAMETERS "Paramètres MQTT" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Topic complet" + +#define D_LOGGING_PARAMETERS "Paramètres du journal" +#define D_SERIAL_LOG_LEVEL "Niveau de journalisation série" +#define D_MQTT_LOG_LEVEL "Niveau de journalisation MQTT" +#define D_WEB_LOG_LEVEL "Niveau de journalisation web" +#define D_SYS_LOG_LEVEL "Niveau SysLog" +#define D_MORE_DEBUG "Plus de debug" +#define D_SYSLOG_HOST "Hôte SysLog" +#define D_SYSLOG_PORT "Port SysLog" +#define D_TELEMETRY_PERIOD "Période télémétrie" + +#define D_OTHER_PARAMETERS "Autres paramètres" +#define D_TEMPLATE "Modèle" +#define D_ACTIVATE "Activer" +#define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin" +#define D_MQTT_ENABLE "MQTT activé" +#define D_FRIENDLY_NAME "Surnom" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "module unique" +#define D_MULTI_DEVICE "multi module" + +#define D_CONFIGURE_TEMPLATE "Configuration du modèle" +#define D_TEMPLATE_PARAMETERS "Paramètres du modèle" +#define D_TEMPLATE_NAME "Nom" +#define D_BASE_TYPE "Basé sur" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Enregistrer la configuration" +#define D_CONFIGURATION_SAVED "Configuration enregistrée" +#define D_CONFIGURATION_RESET "Configuration réinitialisée" + +#define D_PROGRAM_VERSION "Version du programme" +#define D_BUILD_DATE_AND_TIME "Date & Heure de build" +#define D_CORE_AND_SDK_VERSION "Version Core/SDK" +#define D_FLASH_WRITE_COUNT "Compteur écriture flash" +#define D_MAC_ADDRESS "Adresse MAC" +#define D_MQTT_HOST "Hôte MQTT" +#define D_MQTT_PORT "Port MQTT" +#define D_MQTT_CLIENT "Client MQTT" +#define D_MQTT_USER "Utilisateur MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Groupe topic MQTT" +#define D_MQTT_FULL_TOPIC "Topic complet MQTT" +#define D_MDNS_DISCOVERY "Découverte mDNS" +#define D_MDNS_ADVERTISE "Annonce mDNS" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Taille flash" +#define D_FREE_PROGRAM_SPACE "Espace programme libre" + +#define D_UPGRADE_BY_WEBSERVER "Mise à jour par serveur web" +#define D_OTA_URL "URL OTA" +#define D_START_UPGRADE "Lancer la mise à jour" +#define D_UPGRADE_BY_FILE_UPLOAD "Mise à jour par téléchargement fichier" +#define D_UPLOAD_STARTED "Téléchargement lancé" +#define D_UPGRADE_STARTED "Mise à jour lancée" +#define D_UPLOAD_DONE "Téléchargement terminé" +#define D_UPLOAD_ERR_1 "Aucun fichier sélectionné" +#define D_UPLOAD_ERR_2 "Espace insuffisant" +#define D_UPLOAD_ERR_3 "L'octet magique n'est pas 0xE9" +#define D_UPLOAD_ERR_4 "La taille du programme à flasher est plus grande que la taille réelle de la mémoire flash" +#define D_UPLOAD_ERR_5 "Erreur de comparaison du buffer de téléchargement" +#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer WebLog 3" +#define D_UPLOAD_ERR_7 "Téléchargement annulé" +#define D_UPLOAD_ERR_8 "Fichier invalide" +#define D_UPLOAD_ERR_9 "Fichier trop grand" +#define D_UPLOAD_ERR_10 "Erreur d'initialisation du chip RF" +#define D_UPLOAD_ERR_11 "Erreur d'effacement du chip RF" +#define D_UPLOAD_ERR_12 "Erreur d'accès en écriture au chip RF" +#define D_UPLOAD_ERR_13 "Erreur de décodage du firmware RF" +#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement" + +#define D_ENTER_COMMAND "Saisir une commande" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer WebLog 2 si une réponse est attendue" +#define D_NEED_USER_AND_PASSWORD "Nécessite utilisateur=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Vérification d'empreinte TLS ..." +#define D_TLS_CONNECT_FAILED_TO "Échec de connexion TLS à" +#define D_RETRY_IN "Nouvelle tentative dans" +#define D_VERIFIED "Vérifié par empreinte " +#define D_INSECURE "Connexion non sécurisée car empreinte non vérifiée" +#define D_CONNECT_FAILED_TO "Échec de connexion à" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast désactivé" +#define D_MULTICAST_REJOINED "Multicast (re)joint" +#define D_MULTICAST_JOIN_FAILED "Multicast échec abonnement" +#define D_FAILED_TO_SEND_RESPONSE "Échec d'envoi réponse" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "Réglage WeMo" +#define D_RESPONSE_SENT "Réponse envoyée" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Réglage Hue" +#define D_HUE_API_NOT_IMPLEMENTED "API Hue non implémentée" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 paquets de réponse envoyés" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Paramètres Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Puissance,Énergie" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Compteur/PM1" + #define D_DOMOTICZ_VOLTAGE "Tension/PM2,5" + #define D_DOMOTICZ_CURRENT "Courant/PM10" + #define D_DOMOTICZ_AIRQUALITY "Qualité de l'air" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Durée de rafraichissement" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configuration des Timers" +#define D_TIMER_PARAMETERS "Paramètres Timer" +#define D_TIMER_ENABLE "Activer les Timers" +#define D_TIMER_ARM "Armer" +#define D_TIMER_TIME "Temps" +#define D_TIMER_DAYS "Jours" +#define D_TIMER_REPEAT "Répéter" +#define D_TIMER_OUTPUT "Sortie" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configuration de KNX" +#define D_KNX_PARAMETERS "Paramètres KNX" +#define D_KNX_GENERAL_CONFIG "Général" +#define D_KNX_PHYSICAL_ADDRESS "Adresse individuelle" // Backbone/Line/Device -> Zone/Ligne/Participant +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Doit être unique sur le réseau KNX)" +#define D_KNX_ENABLE "Activer KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Données à envoyer aux Adresses de Groupe" +#define D_ADD "Ajoûter" +#define D_DELETE "Supprimer" +#define D_REPLY "Répondre" +#define D_KNX_GROUP_ADDRESS_TO_READ "Données à recevoir des Adresses de Groupe" +#define D_RECEIVED_FROM "Reçu de" +#define D_KNX_COMMAND_WRITE "Écrire" +#define D_KNX_COMMAND_READ "Lire" +#define D_KNX_COMMAND_OTHER "Autre" +#define D_SENT_TO "envoyé à" +#define D_KNX_WARNING "L'Adresse de Groupe (0/0/0) est réservée et ne peut être utilisée." +#define D_KNX_ENHANCEMENT "Amélioration de la communication" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xsns_03_energy.ino +#define D_ENERGY_TODAY "Énergie aujourd'hui" +#define D_ENERGY_YESTERDAY "Énergie hier" +#define D_ENERGY_TOTAL "Énergie totale" + +// xdrv_27_shutter.ino +#define D_OPEN "Ouvert" +#define D_CLOSE "Fermé" +#define D_DOMOTICZ_SHUTTER "Volet" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configurer PCF8574" +#define D_PCF8574_PARAMETERS "Paramètres PCF8574" +#define D_INVERT_PORTS "Inverser les Ports" +#define D_DEVICE "Module" +#define D_DEVICE_INPUT "Entrée" +#define D_DEVICE_OUTPUT "Sortie" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Capteur occupé" +#define D_SENSOR_CRC_ERROR "Erreur CRC capteur" +#define D_SENSORS_FOUND "Capteur trouvé" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Expiration du délai" +#define D_START_SIGNAL_LOW "Signal Start bas" +#define D_START_SIGNAL_HIGH "Signal Start haut" +#define D_PULSE "Impulsion" +#define D_CHECKSUM_FAILURE "Erreur checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Le capteur n'a pas acquitté la commande" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particules" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accél. Axe-X" +#define D_AY_AXIS "Accél. Axe-Y" +#define D_AZ_AXIS "Accél. Axe-Z" +#define D_GX_AXIS "Gyro Axe-X" +#define D_GY_AXIS "Gyro Axe-Y" +#define D_GZ_AXIS "Gyro Axe-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Retirer la charge" +#define D_HX_CAL_REFERENCE "Charger l'étalon de poids" +#define D_HX_CAL_DONE "Étalonné" +#define D_HX_CAL_FAIL "L'étalonnage a échoué" +#define D_RESET_HX711 "Réinitialiser le capteur" +#define D_CONFIGURE_HX711 "Configurer le capteur" +#define D_HX711_PARAMETERS "Paramètres capteur" +#define D_ITEM_WEIGHT "Poids de l'objet" +#define D_REFERENCE_WEIGHT "Poids de référence" +#define D_CALIBRATE "Étalonner" +#define D_CALIBRATION "Étalonnage" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direction du vent" +#define D_TX20_WIND_SPEED "Vitesse du vent" +#define D_TX20_WIND_SPEED_AVG "Vitesse Moy." +#define D_TX20_WIND_SPEED_MAX "Vitesse Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Aucun" +#define D_SENSOR_USER "Utilisateur" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "ÉmetIR" +#define D_SENSOR_SWITCH "Inter." // Suffix "1" +#define D_SENSOR_BUTTON "Bouton" // Suffix "1" +#define D_SENSOR_RELAY "Relais" // Suffix "1i" +#define D_SENSOR_LED "LED" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Compteur" // Suffix "1" +#define D_SENSOR_IRRECV "RécptIR" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "RétroÉcl" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "gal/mn" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "mn" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "secteurs" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Angle de phase" +#define D_IMPORT_ACTIVE "Énergie act conso" +#define D_EXPORT_ACTIVE "Énergie act fournie" +#define D_IMPORT_REACTIVE "Énergie réa conso" +#define D_EXPORT_REACTIVE "Énergie réa fournie" +#define D_TOTAL_REACTIVE "Énergie réa totale" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "°" + +//SOLAXX1 +#define D_PV1_VOLTAGE "Tension PV1" +#define D_PV1_CURRENT "Courant PV1" +#define D_PV1_POWER "Puissance PV1" +#define D_PV2_VOLTAGE "Tension PV2" +#define D_PV2_CURRENT "Courant PV2" +#define D_PV2_POWER "Puissance PV2" +#define D_SOLAR_POWER "Puissance solaire" +#define D_INVERTER_POWER "Puissance onduleur" +#define D_STATUS "Statut" +#define D_WAITING "En attente" +#define D_CHECKING "En test" +#define D_WORKING "En marche" +#define D_FAILURE "Défault" +#define D_SOLAX_ERROR_0 "Aucun code d'erreur" +#define D_SOLAX_ERROR_1 "Défaut Perte de réseau" +#define D_SOLAX_ERROR_2 "Défaut Tension réseau" +#define D_SOLAX_ERROR_3 "Défaut Fréquence réseau" +#define D_SOLAX_ERROR_4 "Défaut Tension PV" +#define D_SOLAX_ERROR_5 "Défaut Isolation" +#define D_SOLAX_ERROR_6 "Défaut Surchauffe" +#define D_SOLAX_ERROR_7 "Défaut Ventilateur" +#define D_SOLAX_ERROR_8 "Défaut Autre équipement" + +#endif // _LANGUAGE_FR_FR_H_ diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index ac4dadb8e..869c31fb7 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -1,701 +1,703 @@ -/* - he-HE.h - localization for Hebrew - Israel for Tasmota - - Copyright (C) 2019 Yuval Mejahez - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_HE_HE_H_ -#define _LANGUAGE_HE_HE_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.14.0b -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1037 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "he" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "SunMonTueWedThuFriSat" -#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "מנהל" -#define D_AIR_QUALITY "איכות אוויר" -#define D_AP "AP" // Access Point -#define D_AS "-כ" -#define D_AUTO "אוטומטי" -#define D_BLINK "מהבהב" -#define D_BLINKOFF "כיבוי היבהוב" -#define D_BOOT_COUNT "מונה הפעלה מחדש" -#define D_BRIGHTLIGHT "בהירות" -#define D_BSSID "BSSId" -#define D_BUTTON "לחצן" -#define D_BY "על ידי" // Written by me -#define D_BYTES "בייט" -#define D_CELSIUS "צלזיוס" -#define D_CHANNEL "ערוץ" -#define D_CO2 "פחמן דו חמצני" -#define D_CODE "קוד" // Button code -#define D_COLDLIGHT "אור קר" -#define D_COMMAND "פקודה" -#define D_CONNECTED "מחובר" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "סופר" -#define D_COUNTER "מונה" -#define D_CURRENT "נוכחי" // As in Voltage and Current -#define D_DATA "נתונים" -#define D_DARKLIGHT "חושך" -#define D_DEBUG "באגים" -#define D_DISABLED "מבוטל" -#define D_DISTANCE "מרחק" -#define D_DNS_SERVER "DNS שרת" -#define D_DONE "סיים" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "הדמיה" -#define D_ENABLED "מאופשר" -#define D_ERASE "מחיקה" -#define D_ERROR "שגיאה" -#define D_FAHRENHEIT "פרנהייט" -#define D_FAILED "נכשל" -#define D_FALLBACK "חזרה" -#define D_FALLBACK_TOPIC "נושא לחזרה" -#define D_FALSE "שגוי" -#define D_FILE "קובץ" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "זכרון פנוי" -#define D_FREQUENCY "תדר" -#define D_GAS "גז" -#define D_GATEWAY "שער" -#define D_GROUP "קבוצה" -#define D_HOST "מארח" -#define D_HOSTNAME "שם מארח" -#define D_HUMIDITY "לחות" -#define D_ILLUMINANCE "רמת חשיפה" -#define D_IMMEDIATE "מידי" // Button immediate -#define D_INDEX "אינדקס" -#define D_INFO "מידע" -#define D_INFRARED "אינפרא" -#define D_INITIALIZED "מאותחל" -#define D_IP_ADDRESS "IP כתובת" -#define D_LIGHT "אור" -#define D_LWT "LWT" -#define D_MODULE "מודול" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "לחיצה מרובה" -#define D_NOISE "רעש" -#define D_NONE "כלום" -#define D_OFF "כבוי" -#define D_OFFLINE "מנותק" -#define D_OK "אוקיי" -#define D_ON "פועל" -#define D_ONLINE "מחובר" -#define D_PASSWORD "סיסמא" -#define D_PORT "פורט" -#define D_POWER_FACTOR "גורם כוח" -#define D_POWERUSAGE "כוח" -#define D_POWERUSAGE_ACTIVE "כוח פעיל" -#define D_POWERUSAGE_APPARENT "כוח לכאורה" -#define D_POWERUSAGE_REACTIVE "כוח תגובתי" -#define D_PRESSURE "לחץ" -#define D_PRESSUREATSEALEVEL "לחץ ימי" -#define D_PROGRAM_FLASH_SIZE "גודל תוכנית פלאש" -#define D_PROGRAM_SIZE "גודל תוכנית" -#define D_PROJECT "פרויקט" -#define D_RAIN "גשם" -#define D_RECEIVED "התקבל" -#define D_RESTART "איתחול" -#define D_RESTARTING "הפעלה מחדש" -#define D_RESTART_REASON "סיבת הפעלה מחדש" -#define D_RESTORE "שחזור" -#define D_RETAINED "שמור" -#define D_RULE "חוק" -#define D_SAVE "שמירה" -#define D_SENSOR "חיישן" -#define D_SSID "SSId" -#define D_START "התחלה" -#define D_STD_TIME "STD" -#define D_STOP "עצירה" -#define D_SUBNET_MASK "רשת מסכת משנה" -#define D_SUBSCRIBE_TO "הרשם ל" -#define D_UNSUBSCRIBE_FROM "בטל רישום" -#define D_SUCCESSFUL "הצליח" -#define D_SUNRISE "זריחה" -#define D_SUNSET "שקיעה" -#define D_TEMPERATURE "טמפרטורה" -#define D_TO "ל" -#define D_TOGGLE "מתג" -#define D_TOPIC "נושא" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "עבר" -#define D_TRUE "נכון" -#define D_TVOC "TVOC" -#define D_UPGRADE "שדרוג" -#define D_UPLOAD "העלאה" -#define D_UPTIME "זמן עליה" -#define D_USER "משתמש" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV אינדקס" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" // Out of Range -#define D_UV_LEVEL "UV רמת" -#define D_UV_POWER "UV Power" -#define D_VERSION "גרסה" -#define D_VOLTAGE "מתח" -#define D_WEIGHT "משקל" -#define D_WARMLIGHT "חום" -#define D_WEB_SERVER "Web שרת" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "אזהרה גרסה זו אינה תומכת בהגדרות קבועות" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "רישום טורי מושבת" -#define D_SYSLOG_LOGGING_REENABLED "הופעל מחדש Syslog רישום" - -#define D_SET_BAUDRATE_TO "הגדר קצב שידור ל" -#define D_RECEIVED_TOPIC "Topic התקבל" -#define D_DATA_SIZE "גודל נתונים" -#define D_ANALOG_INPUT "אנלוגי" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "לולאות חסומות" -#define D_WPS_FAILED_WITH_STATUS "נכשל עם הסטטוס WPSconfig" -#define D_ACTIVE_FOR_3_MINUTES "פעיל במשך 3 דקות" -#define D_FAILED_TO_START "נכשל בנסיון להתחיל" -#define D_PATCH_ISSUE_2186 "בעית תיקון 2186" -#define D_CONNECTING_TO_AP "AP -מתחבר ל" -#define D_IN_MODE "במצב" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP החיבור נכשל מכיוון שלא התקבלה כתובת" -#define D_CONNECT_FAILED_AP_NOT_REACHED "זמין AP החיבור נכשל כיוון שאין" -#define D_CONNECT_FAILED_WRONG_PASSWORD "סיסמא שגויה , AP חיבור נכשל ל" -#define D_CONNECT_FAILED_AP_TIMEOUT "פג זמן המתנה , AP חיבור נכשל ל" -#define D_ATTEMPTING_CONNECTION "...מנסה להתחבר" -#define D_CHECKING_CONNECTION "...בודק חיבור" -#define D_QUERY_DONE "MQTT השאילתה נעשתה. נמצאו שירותי" -#define D_MQTT_SERVICE_FOUND "MQTT נמצאו שירותי" -#define D_FOUND_AT "נמצא ב" -#define D_SYSLOG_HOST_NOT_FOUND "לא נמצא Syslog מארח" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "נשמר לפלאש ב" -#define D_LOADED_FROM_FLASH_AT "נטען מהפלאש מ" -#define D_USE_DEFAULTS "השתמש בהגדרות ברירת המחדל" -#define D_ERASED_SECTOR "סקטור מחוק" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "JavaScript - כדי להשתמש בקושחת אסמוטה אנא הפעל" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "קושחה מינימלית
בבקשה אנא שדרג" -#define D_WEBSERVER_ACTIVE_ON "שרת ווב פעיל" -#define D_WITH_IP_ADDRESS "IP עם כתובת" -#define D_WEBSERVER_STOPPED "שרת ווב הופסק" -#define D_FILE_NOT_FOUND "קובץ לא נמצא" -#define D_REDIRECTED "הופנה מחדש לפורטל" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" -#define D_TRYING_TO_CONNECT "מנסה לחבר את ההתקן לרשת" - -#define D_RESTART_IN "הפעלה מחדש תוך" -#define D_SECONDS "שניות" -#define D_DEVICE_WILL_RESTART "ההתקן יופעל מחדש בעוד מס' שניות" -#define D_BUTTON_TOGGLE "מצב" -#define D_CONFIGURATION "הגדרות" -#define D_INFORMATION "מידע" -#define D_FIRMWARE_UPGRADE "שדרוג קושחה" -#define D_CONSOLE "קונסול" -#define D_CONFIRM_RESTART "אישור הפעלה מחדש" - -#define D_CONFIGURE_MODULE "הגדרות מודול" -#define D_CONFIGURE_WIFI "WIFI הגדרות" -#define D_CONFIGURE_MQTT "MQTT הגדרות" -#define D_CONFIGURE_DOMOTICZ "Domoticz הגדרות" -#define D_CONFIGURE_LOGGING "הגדרת לוגים" -#define D_CONFIGURE_OTHER "הגדרות שונות" -#define D_CONFIRM_RESET_CONFIGURATION "אישור שינוי הגדרות" -#define D_RESET_CONFIGURATION "אתחול הגדרות" -#define D_BACKUP_CONFIGURATION "גיבוי הגדרות" -#define D_RESTORE_CONFIGURATION "שחזור הגדרות" -#define D_MAIN_MENU "תפריט ראשי" - -#define D_MODULE_PARAMETERS "מודול פרמטרים" -#define D_MODULE_TYPE "סוג מודול" -#define D_PULLUP_ENABLE "pull-up אין לחצן/מתג" -#define D_ADC "ADC" -#define D_GPIO " רגל " -#define D_SERIAL_IN "כניסת סריאל" -#define D_SERIAL_OUT "יציאת סריאל" - -#define D_WIFI_PARAMETERS "Wifi פרמטרים" -#define D_SCAN_FOR_WIFI_NETWORKS "סורק עבור רשתות אלחוטיות" -#define D_SCAN_DONE "סריקה הושלמה" -#define D_NO_NETWORKS_FOUND "לא נמצאו רשתות אלחוטיות" -#define D_REFRESH_TO_SCAN_AGAIN "רענן כדי לסרוק שוב" -#define D_DUPLICATE_ACCESSPOINT "נקודות גישה משוכפלות" -#define D_SKIPPING_LOW_QUALITY "מדלג עקב איכות רשת נמוכה" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Password" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Password" - -#define D_MQTT_PARAMETERS "MQTT פרמטרים" -#define D_CLIENT "לקוח" -#define D_FULL_TOPIC "זיהוי מלא" - -#define D_LOGGING_PARAMETERS "פרמטרי לוגים" -#define D_SERIAL_LOG_LEVEL "רמת לוג עבור סריאל" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "רמת לוג עבור אתר" -#define D_SYS_LOG_LEVEL "Syslog רמת לוג עבור שרת" -#define D_MORE_DEBUG "מיפוי נוסף" -#define D_SYSLOG_HOST "Syslog מארח" -#define D_SYSLOG_PORT "Syslog פורט" -#define D_TELEMETRY_PERIOD "זמן שידור" - -#define D_OTHER_PARAMETERS "פרמטרים שונים" -#define D_TEMPLATE "תבנית" -#define D_ACTIVATE "הפעל" -#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל" -#define D_MQTT_ENABLE "MQTT אפשר" -#define D_FRIENDLY_NAME "שם ידידותי" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "התקן בודד" -#define D_MULTI_DEVICE "התקנים" - -#define D_CONFIGURE_TEMPLATE "הגדר תבנית" -#define D_TEMPLATE_PARAMETERS "פרמטרים של תבנית" -#define D_TEMPLATE_NAME "שם" -#define D_BASE_TYPE "מבוסס על" -#define D_TEMPLATE_FLAGS "אפשריות" - -#define D_SAVE_CONFIGURATION "שמירת הגדרות" -#define D_CONFIGURATION_SAVED "הגדרות נשמרו" -#define D_CONFIGURATION_RESET "איפוס הגדרות" - -#define D_PROGRAM_VERSION "גירסת תוכנה" -#define D_BUILD_DATE_AND_TIME "Build Date & Time" -#define D_CORE_AND_SDK_VERSION "Core/SDK Version" -#define D_FLASH_WRITE_COUNT "מונה צריבות" -#define D_MAC_ADDRESS "MAC כתובת" -#define D_MQTT_HOST "MQTT מארח" -#define D_MQTT_PORT "MQTT פורט" -#define D_MQTT_CLIENT "MQTT לקוח" -#define D_MQTT_USER "MQTT שם משתמש" -#define D_MQTT_TOPIC "MQTT נושא" -#define D_MQTT_GROUP_TOPIC "MQTT נושא קבוצת" -#define D_MQTT_FULL_TOPIC "MQTT נושא מלא" -#define D_MDNS_DISCOVERY "mDNS זיהוי" -#define D_MDNS_ADVERTISE "mDNS פרסום" -#define D_ESP_CHIP_ID "ESP מס' רכיב" -#define D_FLASH_CHIP_ID "מס' רכיב פלאש" -#define D_FLASH_CHIP_SIZE "גודל זיכרון פלאש" -#define D_FREE_PROGRAM_SPACE "מקום פנוי - תוכנה" - -#define D_UPGRADE_BY_WEBSERVER "שדרוג קושחה" -#define D_OTA_URL "OTA כתובת" -#define D_START_UPGRADE "התחל בשדרוג" -#define D_UPGRADE_BY_FILE_UPLOAD "שדרוג דרך קובץ נכשל" -#define D_UPLOAD_STARTED "העלאה מתחילה" -#define D_UPGRADE_STARTED "שדרוג מתחיל" -#define D_UPLOAD_DONE "העלאה הסתיימה" -#define D_UPLOAD_ERR_1 "לא נבחר קובץ" -#define D_UPLOAD_ERR_2 "אין מספיק מקום" -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" -#define D_UPLOAD_ERR_4 "גודל קובץ השדרוג גדול מנפח האחסון של הפלאש" -#define D_UPLOAD_ERR_5 "מאגר העלאה לא תקין" -#define D_UPLOAD_ERR_6 "העלאה נכשלה. אפשר רישום 3" -#define D_UPLOAD_ERR_7 "ההעלאה בוטלה" -#define D_UPLOAD_ERR_8 "קובץ שגוי" -#define D_UPLOAD_ERR_9 "קובץ גדול מדי" -#define D_UPLOAD_ERR_10 "נכשלה RF הפעלת שבב" -#define D_UPLOAD_ERR_11 "נכשלה RF מחיקת שבב" -#define D_UPLOAD_ERR_12 "נכשלה RF כתיבת שבב" -#define D_UPLOAD_ERR_13 "נכשלה RF קידוד קושחת שבב" -#define D_UPLOAD_ERROR_CODE "שגיאת קוד העלאה" - -#define D_ENTER_COMMAND "הקש פקודה" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" -#define D_NEED_USER_AND_PASSWORD "Need user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "...TLS אמת טביעת אצבע של" -#define D_TLS_CONNECT_FAILED_TO "נכשל TLS חיבור" -#define D_RETRY_IN "נסה שוב תוך" -#define D_VERIFIED "מאומת באמצעות טביעת אצבע" -#define D_INSECURE "חיבור לא מאובטח עקב טביעת אצבע לא חוקית" -#define D_CONNECT_FAILED_TO "חיבור נכשל ל" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast disabled" -#define D_MULTICAST_REJOINED "Multicast (re)joined" -#define D_MULTICAST_JOIN_FAILED "Multicast join failed" -#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo הגדרת" -#define D_RESPONSE_SENT "תגובה נשלחה" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue הגדרת" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz פרמטרי" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "טמפרטורה" - #define D_DOMOTICZ_TEMP_HUM "טמפרטורה,לחות" - #define D_DOMOTICZ_TEMP_HUM_BARO "טמפרטורה,לחות,ברומטר" - #define D_DOMOTICZ_POWER_ENERGY "הספק,צריכה" - #define D_DOMOTICZ_ILLUMINANCE "עוצמת אור" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "איכות אוויר" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "עדכן טיימר" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "הגדרות תזמון" -#define D_TIMER_PARAMETERS "פרמטרים עבור תזמון" -#define D_TIMER_ENABLE "אפשר תזמון" -#define D_TIMER_ARM "טען" -#define D_TIMER_TIME "זמן" -#define D_TIMER_DAYS "ימים" -#define D_TIMER_REPEAT "חזרות" -#define D_TIMER_OUTPUT "פלט" -#define D_TIMER_ACTION "פעולה" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX הגדר" -#define D_KNX_PARAMETERS "KNX פרמטרי" -#define D_KNX_GENERAL_CONFIG "כללי" -#define D_KNX_PHYSICAL_ADDRESS "כתובת פיזית" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "KNX אפשר" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "נתונים לשליחה אל כתובות קבוצתיות" -#define D_ADD "הוסף" -#define D_DELETE "מחק" -#define D_REPLY "השב" -#define D_KNX_GROUP_ADDRESS_TO_READ "כתובות קבוצתיות לקבלת נתונים מ" -#define D_RECEIVED_FROM "התקבל מאת" -#define D_KNX_COMMAND_WRITE "כתיבה" -#define D_KNX_COMMAND_READ "קריאה" -#define D_KNX_COMMAND_OTHER "אחר" -#define D_SENT_TO "נשלח ל" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "שיפור התקשורת" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "צריכה יומית" -#define D_ENERGY_YESTERDAY "צריכה בעבר" -#define D_ENERGY_TOTAL "צריכה כללית" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "שרת עסוק" -#define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת" -#define D_SENSORS_FOUND "חיישנים לא נמצאו" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "הזמן הקצוב להמתנה" -#define D_START_SIGNAL_LOW "להתחיל אות נמוך" -#define D_START_SIGNAL_HIGH "להתחיל אות גבוה" -#define D_PULSE "פעימה" -#define D_CHECKSUM_FAILURE "בדיקת כשל נכשלה" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" -#define D_SHT1X_FOUND "SHT1X found" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "חלקיקים" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "הסר משקל" -#define D_HX_CAL_REFERENCE "טען משקל התייחסות" -#define D_HX_CAL_DONE "מכויל" -#define D_HX_CAL_FAIL "כיול נכשל" -#define D_RESET_HX711 "אפס את קנה המידה" -#define D_CONFIGURE_HX711 "הגדר קנה מידה" -#define D_HX711_PARAMETERS "פרמטרים של קנה מידה" -#define D_ITEM_WEIGHT "משקל פריט" -#define D_REFERENCE_WEIGHT "משקל הפניה" -#define D_CALIBRATE "כייל" -#define D_CALIBRATION "כיול" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "כיוון הרוח" -#define D_TX20_WIND_SPEED "מהירות הרוח" -#define D_TX20_WIND_SPEED_AVG "מהירות הרוח ממוצעת" -#define D_TX20_WIND_SPEED_MAX "מהירות הרוח מקסימלית" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "משתמש" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "נגן מוזיקה" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "מתג" // Suffix "1" -#define D_SENSOR_BUTTON "לחצן" // Suffix "1" -#define D_SENSOR_RELAY "ממסר" // Suffix "1i" -#define D_SENSOR_LED "לד" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "מונה" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_HE_HE_H_ +/* + he-HE.h - localization for Hebrew - Israel for Tasmota + + Copyright (C) 2019 Yuval Mejahez + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_HE_HE_H_ +#define _LANGUAGE_HE_HE_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.14.0b +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1037 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "he" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "SunMonTueWedThuFriSat" +#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "מנהל" +#define D_AIR_QUALITY "איכות אוויר" +#define D_AP "AP" // Access Point +#define D_AS "-כ" +#define D_AUTO "אוטומטי" +#define D_BLINK "מהבהב" +#define D_BLINKOFF "כיבוי היבהוב" +#define D_BOOT_COUNT "מונה הפעלה מחדש" +#define D_BRIGHTLIGHT "בהירות" +#define D_BSSID "BSSId" +#define D_BUTTON "לחצן" +#define D_BY "על ידי" // Written by me +#define D_BYTES "בייט" +#define D_CELSIUS "צלזיוס" +#define D_CHANNEL "ערוץ" +#define D_CO2 "פחמן דו חמצני" +#define D_CODE "קוד" // Button code +#define D_COLDLIGHT "אור קר" +#define D_COMMAND "פקודה" +#define D_CONNECTED "מחובר" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "סופר" +#define D_COUNTER "מונה" +#define D_CURRENT "נוכחי" // As in Voltage and Current +#define D_DATA "נתונים" +#define D_DARKLIGHT "חושך" +#define D_DEBUG "באגים" +#define D_DISABLED "מבוטל" +#define D_DISTANCE "מרחק" +#define D_DNS_SERVER "DNS שרת" +#define D_DONE "סיים" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "הדמיה" +#define D_ENABLED "מאופשר" +#define D_ERASE "מחיקה" +#define D_ERROR "שגיאה" +#define D_FAHRENHEIT "פרנהייט" +#define D_FAILED "נכשל" +#define D_FALLBACK "חזרה" +#define D_FALLBACK_TOPIC "נושא לחזרה" +#define D_FALSE "שגוי" +#define D_FILE "קובץ" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "זכרון פנוי" +#define D_FREQUENCY "תדר" +#define D_GAS "גז" +#define D_GATEWAY "שער" +#define D_GROUP "קבוצה" +#define D_HOST "מארח" +#define D_HOSTNAME "שם מארח" +#define D_HUMIDITY "לחות" +#define D_ILLUMINANCE "רמת חשיפה" +#define D_IMMEDIATE "מידי" // Button immediate +#define D_INDEX "אינדקס" +#define D_INFO "מידע" +#define D_INFRARED "אינפרא" +#define D_INITIALIZED "מאותחל" +#define D_IP_ADDRESS "IP כתובת" +#define D_LIGHT "אור" +#define D_LWT "LWT" +#define D_MODULE "מודול" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "לחיצה מרובה" +#define D_NOISE "רעש" +#define D_NONE "כלום" +#define D_OFF "כבוי" +#define D_OFFLINE "מנותק" +#define D_OK "אוקיי" +#define D_ON "פועל" +#define D_ONLINE "מחובר" +#define D_PASSWORD "סיסמא" +#define D_PORT "פורט" +#define D_POWER_FACTOR "גורם כוח" +#define D_POWERUSAGE "כוח" +#define D_POWERUSAGE_ACTIVE "כוח פעיל" +#define D_POWERUSAGE_APPARENT "כוח לכאורה" +#define D_POWERUSAGE_REACTIVE "כוח תגובתי" +#define D_PRESSURE "לחץ" +#define D_PRESSUREATSEALEVEL "לחץ ימי" +#define D_PROGRAM_FLASH_SIZE "גודל תוכנית פלאש" +#define D_PROGRAM_SIZE "גודל תוכנית" +#define D_PROJECT "פרויקט" +#define D_RAIN "גשם" +#define D_RECEIVED "התקבל" +#define D_RESTART "איתחול" +#define D_RESTARTING "הפעלה מחדש" +#define D_RESTART_REASON "סיבת הפעלה מחדש" +#define D_RESTORE "שחזור" +#define D_RETAINED "שמור" +#define D_RULE "חוק" +#define D_SAVE "שמירה" +#define D_SENSOR "חיישן" +#define D_SSID "SSId" +#define D_START "התחלה" +#define D_STD_TIME "STD" +#define D_STOP "עצירה" +#define D_SUBNET_MASK "רשת מסכת משנה" +#define D_SUBSCRIBE_TO "הרשם ל" +#define D_UNSUBSCRIBE_FROM "בטל רישום" +#define D_SUCCESSFUL "הצליח" +#define D_SUNRISE "זריחה" +#define D_SUNSET "שקיעה" +#define D_TEMPERATURE "טמפרטורה" +#define D_TO "ל" +#define D_TOGGLE "מתג" +#define D_TOPIC "נושא" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "עבר" +#define D_TRUE "נכון" +#define D_TVOC "TVOC" +#define D_UPGRADE "שדרוג" +#define D_UPLOAD "העלאה" +#define D_UPTIME "זמן עליה" +#define D_USER "משתמש" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV אינדקס" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range +#define D_UV_LEVEL "UV רמת" +#define D_UV_POWER "UV Power" +#define D_VERSION "גרסה" +#define D_VOLTAGE "מתח" +#define D_WEIGHT "משקל" +#define D_WARMLIGHT "חום" +#define D_WEB_SERVER "Web שרת" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "אזהרה גרסה זו אינה תומכת בהגדרות קבועות" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "רישום טורי מושבת" +#define D_SYSLOG_LOGGING_REENABLED "הופעל מחדש Syslog רישום" + +#define D_SET_BAUDRATE_TO "הגדר קצב שידור ל" +#define D_RECEIVED_TOPIC "Topic התקבל" +#define D_DATA_SIZE "גודל נתונים" +#define D_ANALOG_INPUT "אנלוגי" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "לולאות חסומות" +#define D_WPS_FAILED_WITH_STATUS "נכשל עם הסטטוס WPSconfig" +#define D_ACTIVE_FOR_3_MINUTES "פעיל במשך 3 דקות" +#define D_FAILED_TO_START "נכשל בנסיון להתחיל" +#define D_PATCH_ISSUE_2186 "בעית תיקון 2186" +#define D_CONNECTING_TO_AP "AP -מתחבר ל" +#define D_IN_MODE "במצב" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP החיבור נכשל מכיוון שלא התקבלה כתובת" +#define D_CONNECT_FAILED_AP_NOT_REACHED "זמין AP החיבור נכשל כיוון שאין" +#define D_CONNECT_FAILED_WRONG_PASSWORD "סיסמא שגויה , AP חיבור נכשל ל" +#define D_CONNECT_FAILED_AP_TIMEOUT "פג זמן המתנה , AP חיבור נכשל ל" +#define D_ATTEMPTING_CONNECTION "...מנסה להתחבר" +#define D_CHECKING_CONNECTION "...בודק חיבור" +#define D_QUERY_DONE "MQTT השאילתה נעשתה. נמצאו שירותי" +#define D_MQTT_SERVICE_FOUND "MQTT נמצאו שירותי" +#define D_FOUND_AT "נמצא ב" +#define D_SYSLOG_HOST_NOT_FOUND "לא נמצא Syslog מארח" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "נשמר לפלאש ב" +#define D_LOADED_FROM_FLASH_AT "נטען מהפלאש מ" +#define D_USE_DEFAULTS "השתמש בהגדרות ברירת המחדל" +#define D_ERASED_SECTOR "סקטור מחוק" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "JavaScript - כדי להשתמש בקושחת אסמוטה אנא הפעל" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "קושחה מינימלית
בבקשה אנא שדרג" +#define D_WEBSERVER_ACTIVE_ON "שרת ווב פעיל" +#define D_WITH_IP_ADDRESS "IP עם כתובת" +#define D_WEBSERVER_STOPPED "שרת ווב הופסק" +#define D_FILE_NOT_FOUND "קובץ לא נמצא" +#define D_REDIRECTED "הופנה מחדש לפורטל" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" +#define D_TRYING_TO_CONNECT "מנסה לחבר את ההתקן לרשת" + +#define D_RESTART_IN "הפעלה מחדש תוך" +#define D_SECONDS "שניות" +#define D_DEVICE_WILL_RESTART "ההתקן יופעל מחדש בעוד מס' שניות" +#define D_BUTTON_TOGGLE "מצב" +#define D_CONFIGURATION "הגדרות" +#define D_INFORMATION "מידע" +#define D_FIRMWARE_UPGRADE "שדרוג קושחה" +#define D_CONSOLE "קונסול" +#define D_CONFIRM_RESTART "אישור הפעלה מחדש" + +#define D_CONFIGURE_MODULE "הגדרות מודול" +#define D_CONFIGURE_WIFI "WIFI הגדרות" +#define D_CONFIGURE_MQTT "MQTT הגדרות" +#define D_CONFIGURE_DOMOTICZ "Domoticz הגדרות" +#define D_CONFIGURE_LOGGING "הגדרת לוגים" +#define D_CONFIGURE_OTHER "הגדרות שונות" +#define D_CONFIRM_RESET_CONFIGURATION "אישור שינוי הגדרות" +#define D_RESET_CONFIGURATION "אתחול הגדרות" +#define D_BACKUP_CONFIGURATION "גיבוי הגדרות" +#define D_RESTORE_CONFIGURATION "שחזור הגדרות" +#define D_MAIN_MENU "תפריט ראשי" + +#define D_MODULE_PARAMETERS "מודול פרמטרים" +#define D_MODULE_TYPE "סוג מודול" +#define D_PULLUP_ENABLE "pull-up אין לחצן/מתג" +#define D_ADC "ADC" +#define D_GPIO " רגל " +#define D_SERIAL_IN "כניסת סריאל" +#define D_SERIAL_OUT "יציאת סריאל" + +#define D_WIFI_PARAMETERS "Wifi פרמטרים" +#define D_SCAN_FOR_WIFI_NETWORKS "סורק עבור רשתות אלחוטיות" +#define D_SCAN_DONE "סריקה הושלמה" +#define D_NO_NETWORKS_FOUND "לא נמצאו רשתות אלחוטיות" +#define D_REFRESH_TO_SCAN_AGAIN "רענן כדי לסרוק שוב" +#define D_DUPLICATE_ACCESSPOINT "נקודות גישה משוכפלות" +#define D_SKIPPING_LOW_QUALITY "מדלג עקב איכות רשת נמוכה" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Password" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Password" + +#define D_MQTT_PARAMETERS "MQTT פרמטרים" +#define D_CLIENT "לקוח" +#define D_FULL_TOPIC "זיהוי מלא" + +#define D_LOGGING_PARAMETERS "פרמטרי לוגים" +#define D_SERIAL_LOG_LEVEL "רמת לוג עבור סריאל" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "רמת לוג עבור אתר" +#define D_SYS_LOG_LEVEL "Syslog רמת לוג עבור שרת" +#define D_MORE_DEBUG "מיפוי נוסף" +#define D_SYSLOG_HOST "Syslog מארח" +#define D_SYSLOG_PORT "Syslog פורט" +#define D_TELEMETRY_PERIOD "זמן שידור" + +#define D_OTHER_PARAMETERS "פרמטרים שונים" +#define D_TEMPLATE "תבנית" +#define D_ACTIVATE "הפעל" +#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל" +#define D_MQTT_ENABLE "MQTT אפשר" +#define D_FRIENDLY_NAME "שם ידידותי" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "התקן בודד" +#define D_MULTI_DEVICE "התקנים" + +#define D_CONFIGURE_TEMPLATE "הגדר תבנית" +#define D_TEMPLATE_PARAMETERS "פרמטרים של תבנית" +#define D_TEMPLATE_NAME "שם" +#define D_BASE_TYPE "מבוסס על" +#define D_TEMPLATE_FLAGS "אפשריות" + +#define D_SAVE_CONFIGURATION "שמירת הגדרות" +#define D_CONFIGURATION_SAVED "הגדרות נשמרו" +#define D_CONFIGURATION_RESET "איפוס הגדרות" + +#define D_PROGRAM_VERSION "גירסת תוכנה" +#define D_BUILD_DATE_AND_TIME "Build Date & Time" +#define D_CORE_AND_SDK_VERSION "Core/SDK Version" +#define D_FLASH_WRITE_COUNT "מונה צריבות" +#define D_MAC_ADDRESS "MAC כתובת" +#define D_MQTT_HOST "MQTT מארח" +#define D_MQTT_PORT "MQTT פורט" +#define D_MQTT_CLIENT "MQTT לקוח" +#define D_MQTT_USER "MQTT שם משתמש" +#define D_MQTT_TOPIC "MQTT נושא" +#define D_MQTT_GROUP_TOPIC "MQTT נושא קבוצת" +#define D_MQTT_FULL_TOPIC "MQTT נושא מלא" +#define D_MDNS_DISCOVERY "mDNS זיהוי" +#define D_MDNS_ADVERTISE "mDNS פרסום" +#define D_ESP_CHIP_ID "ESP מס' רכיב" +#define D_FLASH_CHIP_ID "מס' רכיב פלאש" +#define D_FLASH_CHIP_SIZE "גודל זיכרון פלאש" +#define D_FREE_PROGRAM_SPACE "מקום פנוי - תוכנה" + +#define D_UPGRADE_BY_WEBSERVER "שדרוג קושחה" +#define D_OTA_URL "OTA כתובת" +#define D_START_UPGRADE "התחל בשדרוג" +#define D_UPGRADE_BY_FILE_UPLOAD "שדרוג דרך קובץ נכשל" +#define D_UPLOAD_STARTED "העלאה מתחילה" +#define D_UPGRADE_STARTED "שדרוג מתחיל" +#define D_UPLOAD_DONE "העלאה הסתיימה" +#define D_UPLOAD_ERR_1 "לא נבחר קובץ" +#define D_UPLOAD_ERR_2 "אין מספיק מקום" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "גודל קובץ השדרוג גדול מנפח האחסון של הפלאש" +#define D_UPLOAD_ERR_5 "מאגר העלאה לא תקין" +#define D_UPLOAD_ERR_6 "העלאה נכשלה. אפשר רישום 3" +#define D_UPLOAD_ERR_7 "ההעלאה בוטלה" +#define D_UPLOAD_ERR_8 "קובץ שגוי" +#define D_UPLOAD_ERR_9 "קובץ גדול מדי" +#define D_UPLOAD_ERR_10 "נכשלה RF הפעלת שבב" +#define D_UPLOAD_ERR_11 "נכשלה RF מחיקת שבב" +#define D_UPLOAD_ERR_12 "נכשלה RF כתיבת שבב" +#define D_UPLOAD_ERR_13 "נכשלה RF קידוד קושחת שבב" +#define D_UPLOAD_ERROR_CODE "שגיאת קוד העלאה" + +#define D_ENTER_COMMAND "הקש פקודה" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" +#define D_NEED_USER_AND_PASSWORD "Need user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "...TLS אמת טביעת אצבע של" +#define D_TLS_CONNECT_FAILED_TO "נכשל TLS חיבור" +#define D_RETRY_IN "נסה שוב תוך" +#define D_VERIFIED "מאומת באמצעות טביעת אצבע" +#define D_INSECURE "חיבור לא מאובטח עקב טביעת אצבע לא חוקית" +#define D_CONNECT_FAILED_TO "חיבור נכשל ל" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast disabled" +#define D_MULTICAST_REJOINED "Multicast (re)joined" +#define D_MULTICAST_JOIN_FAILED "Multicast join failed" +#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo הגדרת" +#define D_RESPONSE_SENT "תגובה נשלחה" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue הגדרת" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz פרמטרי" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "טמפרטורה" + #define D_DOMOTICZ_TEMP_HUM "טמפרטורה,לחות" + #define D_DOMOTICZ_TEMP_HUM_BARO "טמפרטורה,לחות,ברומטר" + #define D_DOMOTICZ_POWER_ENERGY "הספק,צריכה" + #define D_DOMOTICZ_ILLUMINANCE "עוצמת אור" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "איכות אוויר" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "עדכן טיימר" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "הגדרות תזמון" +#define D_TIMER_PARAMETERS "פרמטרים עבור תזמון" +#define D_TIMER_ENABLE "אפשר תזמון" +#define D_TIMER_ARM "טען" +#define D_TIMER_TIME "זמן" +#define D_TIMER_DAYS "ימים" +#define D_TIMER_REPEAT "חזרות" +#define D_TIMER_OUTPUT "פלט" +#define D_TIMER_ACTION "פעולה" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX הגדר" +#define D_KNX_PARAMETERS "KNX פרמטרי" +#define D_KNX_GENERAL_CONFIG "כללי" +#define D_KNX_PHYSICAL_ADDRESS "כתובת פיזית" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "KNX אפשר" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "נתונים לשליחה אל כתובות קבוצתיות" +#define D_ADD "הוסף" +#define D_DELETE "מחק" +#define D_REPLY "השב" +#define D_KNX_GROUP_ADDRESS_TO_READ "כתובות קבוצתיות לקבלת נתונים מ" +#define D_RECEIVED_FROM "התקבל מאת" +#define D_KNX_COMMAND_WRITE "כתיבה" +#define D_KNX_COMMAND_READ "קריאה" +#define D_KNX_COMMAND_OTHER "אחר" +#define D_SENT_TO "נשלח ל" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "שיפור התקשורת" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "צריכה יומית" +#define D_ENERGY_YESTERDAY "צריכה בעבר" +#define D_ENERGY_TOTAL "צריכה כללית" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "שרת עסוק" +#define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת" +#define D_SENSORS_FOUND "חיישנים לא נמצאו" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "הזמן הקצוב להמתנה" +#define D_START_SIGNAL_LOW "להתחיל אות נמוך" +#define D_START_SIGNAL_HIGH "להתחיל אות גבוה" +#define D_PULSE "פעימה" +#define D_CHECKSUM_FAILURE "בדיקת כשל נכשלה" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "חלקיקים" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "הסר משקל" +#define D_HX_CAL_REFERENCE "טען משקל התייחסות" +#define D_HX_CAL_DONE "מכויל" +#define D_HX_CAL_FAIL "כיול נכשל" +#define D_RESET_HX711 "אפס את קנה המידה" +#define D_CONFIGURE_HX711 "הגדר קנה מידה" +#define D_HX711_PARAMETERS "פרמטרים של קנה מידה" +#define D_ITEM_WEIGHT "משקל פריט" +#define D_REFERENCE_WEIGHT "משקל הפניה" +#define D_CALIBRATE "כייל" +#define D_CALIBRATION "כיול" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "כיוון הרוח" +#define D_TX20_WIND_SPEED "מהירות הרוח" +#define D_TX20_WIND_SPEED_AVG "מהירות הרוח ממוצעת" +#define D_TX20_WIND_SPEED_MAX "מהירות הרוח מקסימלית" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "משתמש" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "נגן מוזיקה" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "מתג" // Suffix "1" +#define D_SENSOR_BUTTON "לחצן" // Suffix "1" +#define D_SENSOR_RELAY "ממסר" // Suffix "1i" +#define D_SENSOR_LED "לד" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "מונה" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_HE_HE_H_ diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 62806fa46..9533b355b 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -1,701 +1,703 @@ -/* - hu-HU.h - localization for Hungarian in Hungary for Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_HU_HU_H_ -#define _LANGUAGE_HU_HU_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.12.0e -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1038 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "hu" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "." -#define D_MONTH_DAY_SEPARATOR "." -#define D_DATE_TIME_SEPARATOR " " -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "VasHétKedSzeCsüPénSzo" -#define D_MONTH3LIST "JanFebMárÁprMájJúnJúlAugSzeOktNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Levegőminőség" -#define D_AP "AP" // Access Point -#define D_AS "mint" -#define D_AUTO "AUTO" -#define D_BLINK "Villogás" -#define D_BLINKOFF "Villogás ki" -#define D_BOOT_COUNT "Újraindulások száma" -#define D_BRIGHTLIGHT "Max. fényerő" -#define D_BSSID "BSSID" -#define D_BUTTON "Gomb" -#define D_BY "by" // Written by me -#define D_BYTES "Byte-ok" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Csatorna" -#define D_CO2 "Szén-dioxid" -#define D_CODE "kód" // Button code -#define D_COLDLIGHT "Hideg fény" -#define D_COMMAND "Parancs" -#define D_CONNECTED "Csatlakoztatva" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Szám" -#define D_COUNTER "Számláló" -#define D_CURRENT "Áramerősség" // As in Voltage and Current -#define D_DATA "Adat" -#define D_DARKLIGHT "Min. fényerő" -#define D_DEBUG "Debug" -#define D_DISABLED "Letiltva" -#define D_DISTANCE "Távolság" -#define D_DNS_SERVER "DNS szerver" -#define D_DONE "Kész" -#define D_DST_TIME "nyári idő" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emuláció" -#define D_ENABLED "Engedélyezve" -#define D_ERASE "Törlés" -#define D_ERROR "Hiba" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Sikertelen" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "fallback topik" -#define D_FALSE "Hamis" -#define D_FILE "Fájl" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Szabad memória" -#define D_FREQUENCY "Frekvencia" -#define D_GAS "Gáz" -#define D_GATEWAY "Átjáró" -#define D_GROUP "Csoport" -#define D_HOST "Hoszt" -#define D_HOSTNAME "Hosztnév" -#define D_HUMIDITY "Páratartalom" -#define D_ILLUMINANCE "Megvilágítás" -#define D_IMMEDIATE "azonnali" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infravörös" -#define D_INITIALIZED "Inicializálva" -#define D_IP_ADDRESS "IP cím" -#define D_LIGHT "Fény" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "több lenyomás" -#define D_NOISE "Zaj" -#define D_NONE "nincs" -#define D_OFF "Ki" -#define D_OFFLINE "Offline" -#define D_OK "OK" -#define D_ON "Be" -#define D_ONLINE "Online" -#define D_PASSWORD "Jelszó" -#define D_PORT "Port" -#define D_POWER_FACTOR "Teljesítménytényező" -#define D_POWERUSAGE "Energiafelhasználás" -#define D_POWERUSAGE_ACTIVE "Aktív teljesítmény" -#define D_POWERUSAGE_APPARENT "Látszólagos teljesítmény" -#define D_POWERUSAGE_REACTIVE "Reaktív teljesítmény" -#define D_PRESSURE "Nyomás" -#define D_PRESSUREATSEALEVEL "Tengerszinti nyomás" -#define D_PROGRAM_FLASH_SIZE "Program flash méret" -#define D_PROGRAM_SIZE "Program méret" -#define D_PROJECT "Projekt" -#define D_RAIN "Eső" -#define D_RECEIVED "Érkezett" -#define D_RESTART "Újraindítás" -#define D_RESTARTING "Újraindítás" -#define D_RESTART_REASON "Utolsó újraindulás oka" -#define D_RESTORE "Visszaállítás" -#define D_RETAINED "retained" -#define D_RULE "Szabály" -#define D_SAVE "Mentés" -#define D_SENSOR "Szenzor" -#define D_SSID "SSID" -#define D_START "" -#define D_STD_TIME "STD" -#define D_STOP "Leállítás" -#define D_SUBNET_MASK "Alhálózati maszk" -#define D_SUBSCRIBE_TO "Feliratkozás a(z)" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Sikeres" -#define D_SUNRISE "Napkelte" -#define D_SUNSET "Napnyugta" -#define D_TEMPERATURE "Hőmérséklet" -#define D_TO "-nak" -#define D_TOGGLE "Megfordítás" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Továbbít" -#define D_TRUE "Igaz" -#define D_TVOC "TVOC" -#define D_UPGRADE "Frissítés" -#define D_UPLOAD "Feltöltés" -#define D_UPTIME "Üzemidő" -#define D_USER "Felhasználó" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV index" -#define D_UV_INDEX_1 "alacsony" -#define D_UV_INDEX_2 "közepes" -#define D_UV_INDEX_3 "magas" -#define D_UV_INDEX_4 "veszélyes" -#define D_UV_INDEX_5 "égés L1/2" -#define D_UV_INDEX_6 "égés L3" -#define D_UV_INDEX_7 "tartományon kívül" -#define D_UV_LEVEL "UV szint" -#define D_UV_POWER "UV teljesítmény" -#define D_VERSION "Verzió" -#define D_VOLTAGE "Feszültség" -#define D_WEIGHT "Tömeg" -#define D_WARMLIGHT "Meleg fény" -#define D_WEB_SERVER "Webszerver" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "VIGYÁZZ! Ez a verzió nem támogat tartós beállításokat" -#define D_LEVEL_10 "szint 1-0" -#define D_LEVEL_01 "szint 0-1" -#define D_SERIAL_LOGGING_DISABLED "Soros naplózás kikapcsolva" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logolás újraengedélyezve" - -#define D_SET_BAUDRATE_TO "Baudrate beállítása" -#define D_RECEIVED_TOPIC "Érkezett topic" -#define D_DATA_SIZE "Adatméret" -#define D_ANALOG_INPUT "Analóg" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Tiltott hurok" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig SIKERTELEN státusz:" -#define D_ACTIVE_FOR_3_MINUTES "aktválás 3 percre" -#define D_FAILED_TO_START "sikertelen indítás" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "AP-hoz csatlakozás:" -#define D_IN_MODE "mód:" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Sikertelen csatlakozás, nincs kiosztott IP cím" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Sikertelen csatlakozás, AP nem elérhető" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Sikertelen csatlakozás, hibás AP jelszó" -#define D_CONNECT_FAILED_AP_TIMEOUT "Sikertelen csatlakozás AP időtúllépés miatt" -#define D_ATTEMPTING_CONNECTION "Csatlakozás..." -#define D_CHECKING_CONNECTION "Kapcsolat ellenőrzése..." -#define D_QUERY_DONE "Lekérés kész. MQTT szolgáltatás aktív" -#define D_MQTT_SERVICE_FOUND "élő MQTT szolgáltatás a(z)" -#define D_FOUND_AT "a(z)" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog hoszt nem található" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Flash-re mentve a(z)" -#define D_LOADED_FROM_FLASH_AT "Flash-ről betöltve a(z)" -#define D_USE_DEFAULTS "Alapértelmezett beáll. használata" -#define D_ERASED_SECTOR "Szektor törlése" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" -#define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:" -#define D_WITH_IP_ADDRESS "IP cím:" -#define D_WEBSERVER_STOPPED "Webszerver leállítva" -#define D_FILE_NOT_FOUND "Fájl nem található" -#define D_REDIRECTED "Átírányítás captive portálra" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WifiManager AccessPoint(AP) és Station(ST) beállítása" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager AccessPoint(AP) beállítása" -#define D_TRYING_TO_CONNECT "Csatlakozás a hálózatra..." - -#define D_RESTART_IN "Újraindítás..." -#define D_SECONDS "másodperc" -#define D_DEVICE_WILL_RESTART "Az eszköz hamarosan újraindul..." -#define D_BUTTON_TOGGLE "Megfordítás" -#define D_CONFIGURATION "Beállítások" -#define D_INFORMATION "Információ" -#define D_FIRMWARE_UPGRADE "Firmware frissítés" -#define D_CONSOLE "Konzol" -#define D_CONFIRM_RESTART "Biztosan újraindítsam a modult?" - -#define D_CONFIGURE_MODULE "Eszközbeállítások" -#define D_CONFIGURE_WIFI "WiFi konfiguráció" -#define D_CONFIGURE_MQTT "MQTT konfiguráció" -#define D_CONFIGURE_DOMOTICZ "Domoticz konfiguráció" -#define D_CONFIGURE_LOGGING "Naplózás beállításai" -#define D_CONFIGURE_OTHER "Egyéb beállítások" -#define D_CONFIRM_RESET_CONFIGURATION "Biztosan töröljem a beállításokat?" -#define D_RESET_CONFIGURATION "Beállítások törlése" -#define D_BACKUP_CONFIGURATION "Beállítások mentése" -#define D_RESTORE_CONFIGURATION "Beállítások visszatöltése" -#define D_MAIN_MENU "Menü" - -#define D_MODULE_PARAMETERS "Modul paraméterek" -#define D_MODULE_TYPE "Alkalmazott modul" -#define D_PULLUP_ENABLE "Nincs felhúzó ellenállás" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Soros BE" -#define D_SERIAL_OUT "Soros KI" - -#define D_WIFI_PARAMETERS "WiFi paraméterek" -#define D_SCAN_FOR_WIFI_NETWORKS "WiFi hálózat keresése" -#define D_SCAN_DONE "Keresés kész" -#define D_NO_NETWORKS_FOUND "Nincs elérhető hálózat" -#define D_REFRESH_TO_SCAN_AGAIN "Frissíts az újrakereséshez" -#define D_DUPLICATE_ACCESSPOINT "Duplikált access point" -#define D_SKIPPING_LOW_QUALITY "Rossz, alacsony jelminőség" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "AP1 megosztott kulcs" -#define D_AP2_SSID "AP2 SSID" -#define D_AP2_PASSWORD "AP2 megosztott kulcs" - -#define D_MQTT_PARAMETERS "MQTT paraméterek" -#define D_CLIENT "Kliens" -#define D_FULL_TOPIC "Teljes topic" - -#define D_LOGGING_PARAMETERS "Naplózási paraméterek" -#define D_SERIAL_LOG_LEVEL "Soros naplózási szint" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web naplózási szint" -#define D_SYS_LOG_LEVEL "Syslog szint" -#define D_MORE_DEBUG "Részletes hibakeresés" -#define D_SYSLOG_HOST "Syslog hoszt" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Telemetria (mp.)" - -#define D_OTHER_PARAMETERS "Egyéb beállítások" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Web admin jelszó" -#define D_MQTT_ENABLE "MQTT engedélyezése" -#define D_FRIENDLY_NAME "Név" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Beállítások mentése" -#define D_CONFIGURATION_SAVED "Beállítások elmentve" -#define D_CONFIGURATION_RESET "Beállítások visszaállítása" - -#define D_PROGRAM_VERSION "Program verzió" -#define D_BUILD_DATE_AND_TIME "Build ideje" -#define D_CORE_AND_SDK_VERSION "Core/SDK verzió" -#define D_FLASH_WRITE_COUNT "Flash írások száma" -#define D_MAC_ADDRESS "MAC cím" -#define D_MQTT_HOST "MQTT hoszt" -#define D_MQTT_PORT "MQTT port" -#define D_MQTT_CLIENT "MQTT kliens" -#define D_MQTT_USER "MQTT felhasználó" -#define D_MQTT_TOPIC "MQTT topic" -#define D_MQTT_GROUP_TOPIC "MQTT csoport topic" -#define D_MQTT_FULL_TOPIC "MQTT teljes topic" -#define D_MDNS_DISCOVERY "mDNS láthatóság" -#define D_MDNS_ADVERTISE "mDNS hirdetés" -#define D_ESP_CHIP_ID "ESP chip ID" -#define D_FLASH_CHIP_ID "Flash chip ID" -#define D_FLASH_CHIP_SIZE "Flash mérete" -#define D_FREE_PROGRAM_SPACE "Szabad programhely" - -#define D_UPGRADE_BY_WEBSERVER "Frissítés távoli szerverről" -#define D_OTA_URL "OTA URL" -#define D_START_UPGRADE "Frissítés" -#define D_UPGRADE_BY_FILE_UPLOAD "Frissítés helyi fájllal" -#define D_UPLOAD_STARTED "Feltöltés elindítva" -#define D_UPGRADE_STARTED "Frissítés elindítva" -#define D_UPLOAD_DONE "Feltöltés kész" -#define D_UPLOAD_ERR_1 "Nincs fájl kijelölve" -#define D_UPLOAD_ERR_2 "Nincs elég memória" -#define D_UPLOAD_ERR_3 "A \"magic byte\" nem 0xE9" -#define D_UPLOAD_ERR_4 "A program flashméret nagyobb a valós flashméretnél" -#define D_UPLOAD_ERR_5 "Feltöltési buffer hiba" -#define D_UPLOAD_ERR_6 "Feltöltés sikertelen. Endegélyezd a 3. szintű naplózást" -#define D_UPLOAD_ERR_7 "Feltöltés megszakítva" -#define D_UPLOAD_ERR_8 "Érvénytelen fájl" -#define D_UPLOAD_ERR_9 "A fájl túl nagy" -#define D_UPLOAD_ERR_10 "Az RF chip inicializálása sikertelen" -#define D_UPLOAD_ERR_11 "Az RF chip törlése sikertelen" -#define D_UPLOAD_ERR_12 "Az RF chip írása sikertelen" -#define D_UPLOAD_ERR_13 "Az RF firmware dekódolása sikertelen" -#define D_UPLOAD_ERROR_CODE "Feltöltési hibakód" - -#define D_ENTER_COMMAND "Kérem a parancsot..." -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Engedélyezz 2-es szintű webnaplózást több információért" -#define D_NEED_USER_AND_PASSWORD "Szükséges a user=&password= paraméter" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "TLS fingerprint hitelesítése..." -#define D_TLS_CONNECT_FAILED_TO "TLS csatlakozás sikertelen a(z)" -#define D_RETRY_IN "Újrapróbálás" -#define D_VERIFIED "Fingerprint hitelesítve" -#define D_INSECURE "Nem biztonságos kapcsolat érvénytelen fingerprint miatt" -#define D_CONNECT_FAILED_TO "Sikertelen csatlakozás a(z)" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast kikapcsolva" -#define D_MULTICAST_REJOINED "Multicast (újra)csatlakozás" -#define D_MULTICAST_JOIN_FAILED "Multicast csatlakozás sikertelen" -#define D_FAILED_TO_SEND_RESPONSE "Nem sikerült választ küldeni" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo beállítás" -#define D_RESPONSE_SENT "Válasz elküldve" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue beállítás" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API nincs implementálva" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argumentumok" -#define D_3_RESPONSE_PACKETS_SENT "3 válaszcsomag elküldve" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz paraméterek" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Kapcsoló idx" -#define D_DOMOTICZ_SENSOR_IDX "Szenzor idx" - #define D_DOMOTICZ_TEMP "Hőmérséklet" - #define D_DOMOTICZ_TEMP_HUM "Hőmérséklet, páratartalom" - #define D_DOMOTICZ_TEMP_HUM_BARO "Hőmérséklet, páratartalom, légnyomás" - #define D_DOMOTICZ_POWER_ENERGY "Teljesítmény, energia" - #define D_DOMOTICZ_ILLUMINANCE "Fényerő" - #define D_DOMOTICZ_COUNT "Szám/PM1" - #define D_DOMOTICZ_VOLTAGE "Feszültség/PM2.5" - #define D_DOMOTICZ_CURRENT "Áram/PM10" - #define D_DOMOTICZ_AIRQUALITY "Légminőség" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Frissítési időzítő" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Időzítő beállításai" -#define D_TIMER_PARAMETERS "Időzítő paraméterei" -#define D_TIMER_ENABLE "Időzítők engedélyezve" -#define D_TIMER_ARM "Be" -#define D_TIMER_TIME "Idő" -#define D_TIMER_DAYS "Napok" -#define D_TIMER_REPEAT "Ismétlés" -#define D_TIMER_OUTPUT "Kimenet" -#define D_TIMER_ACTION "Művelet" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX beállításai" -#define D_KNX_PARAMETERS "KNX paraméterei" -#define D_KNX_GENERAL_CONFIG "Általános" -#define D_KNX_PHYSICAL_ADDRESS "Fizikai cím" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(egyedinek kell lennie a KNX hálózaton)" -#define D_KNX_ENABLE "KNX engedélyezése" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Íráshoz használt csoportcímek" -#define D_ADD "Hozzáadás" -#define D_DELETE "Törlés" -#define D_REPLY "Válasz" -#define D_KNX_GROUP_ADDRESS_TO_READ "Fogadáshoz használt csoportcímek" -#define D_RECEIVED_FROM "Fogadva tőle:" -#define D_KNX_COMMAND_WRITE "Írás" -#define D_KNX_COMMAND_READ "Olvasás" -#define D_KNX_COMMAND_OTHER "Egyáb" -#define D_SENT_TO "küldve neki:" -#define D_KNX_WARNING "A csoportcím ( 0 / 0 / 0 ) fenntartott és nem használható." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Mai energia" -#define D_ENERGY_YESTERDAY "Tegnapi energia" -#define D_ENERGY_TOTAL "Összes energia" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Szenzor foglalt" -#define D_SENSOR_CRC_ERROR "Szenzor CRC hiba" -#define D_SENSORS_FOUND "Szenzorok megtalálva" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Időtúllépés, várakozás" -#define D_START_SIGNAL_LOW "startjel alacsony" -#define D_START_SIGNAL_HIGH "startjel magas" -#define D_PULSE "impulzus" -#define D_CHECKSUM_FAILURE "Checksum hiba" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "A szenzor nem nyugtázta a parancsot" -#define D_SHT1X_FOUND "SHT1X megtalálva" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Részecskék" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Gyorsulásm. X-tengely" -#define D_AY_AXIS "Gyorsulásm. Y-tengely" -#define D_AZ_AXIS "Gyorsulásm. Z-tengely" -#define D_GX_AXIS "Giroszkóp X-tengely" -#define D_GY_AXIS "Giroszkóp Y-tengely" -#define D_GZ_AXIS "Giroszkóp Z-tengely" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Távolítsa el a súlyt" -#define D_HX_CAL_REFERENCE "Helyezze fel a referenciasúlyt" -#define D_HX_CAL_DONE "Kalibrálva" -#define D_HX_CAL_FAIL "Kalibrálási hiba" -#define D_RESET_HX711 "Skála újrabeállítása" -#define D_CONFIGURE_HX711 "Skála konfigurálása" -#define D_HX711_PARAMETERS "Skálaparaméterek" -#define D_ITEM_WEIGHT "Tárgy tömege" -#define D_REFERENCE_WEIGHT "Referenciatömeg" -#define D_CALIBRATE "Kalibrálás" -#define D_CALIBRATION "Kalibrálás" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Szélirány" -#define D_TX20_WIND_SPEED "Szélsebesség" -#define D_TX20_WIND_SPEED_AVG "Átlag szélsebesség" -#define D_TX20_WIND_SPEED_MAX "Max. szélsebesség" -#define D_TX20_NORTH "É" -#define D_TX20_EAST "K" -#define D_TX20_SOUTH "D" -#define D_TX20_WEST "NY" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Nincs" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 lejátszó" -#define D_SENSOR_IRSEND "IR adó" -#define D_SENSOR_SWITCH "Kapcsoló" // Suffix "1" -#define D_SENSOR_BUTTON "Gomb" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "LED" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Számláló" // Suffix "1" -#define D_SENSOR_IRRECV "IR vevő" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Háttérfény" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "szektorok" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Fázisszög" -#define D_IMPORT_ACTIVE "Bejövő aktív" -#define D_EXPORT_ACTIVE "Kimenő aktív" -#define D_IMPORT_REACTIVE "Bejövő reaktív" -#define D_EXPORT_REACTIVE "Kimenő reaktív" -#define D_TOTAL_REACTIVE "Összes reaktív" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "fok" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_HU_HU_H_ +/* + hu-HU.h - localization for Hungarian in Hungary for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_HU_HU_H_ +#define _LANGUAGE_HU_HU_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.12.0e +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1038 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "hu" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "." +#define D_MONTH_DAY_SEPARATOR "." +#define D_DATE_TIME_SEPARATOR " " +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "VasHétKedSzeCsüPénSzo" +#define D_MONTH3LIST "JanFebMárÁprMájJúnJúlAugSzeOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Levegőminőség" +#define D_AP "AP" // Access Point +#define D_AS "mint" +#define D_AUTO "AUTO" +#define D_BLINK "Villogás" +#define D_BLINKOFF "Villogás ki" +#define D_BOOT_COUNT "Újraindulások száma" +#define D_BRIGHTLIGHT "Max. fényerő" +#define D_BSSID "BSSID" +#define D_BUTTON "Gomb" +#define D_BY "by" // Written by me +#define D_BYTES "Byte-ok" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Csatorna" +#define D_CO2 "Szén-dioxid" +#define D_CODE "kód" // Button code +#define D_COLDLIGHT "Hideg fény" +#define D_COMMAND "Parancs" +#define D_CONNECTED "Csatlakoztatva" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Szám" +#define D_COUNTER "Számláló" +#define D_CURRENT "Áramerősség" // As in Voltage and Current +#define D_DATA "Adat" +#define D_DARKLIGHT "Min. fényerő" +#define D_DEBUG "Debug" +#define D_DISABLED "Letiltva" +#define D_DISTANCE "Távolság" +#define D_DNS_SERVER "DNS szerver" +#define D_DONE "Kész" +#define D_DST_TIME "nyári idő" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emuláció" +#define D_ENABLED "Engedélyezve" +#define D_ERASE "Törlés" +#define D_ERROR "Hiba" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Sikertelen" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "fallback topik" +#define D_FALSE "Hamis" +#define D_FILE "Fájl" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Szabad memória" +#define D_FREQUENCY "Frekvencia" +#define D_GAS "Gáz" +#define D_GATEWAY "Átjáró" +#define D_GROUP "Csoport" +#define D_HOST "Hoszt" +#define D_HOSTNAME "Hosztnév" +#define D_HUMIDITY "Páratartalom" +#define D_ILLUMINANCE "Megvilágítás" +#define D_IMMEDIATE "azonnali" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infravörös" +#define D_INITIALIZED "Inicializálva" +#define D_IP_ADDRESS "IP cím" +#define D_LIGHT "Fény" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "több lenyomás" +#define D_NOISE "Zaj" +#define D_NONE "nincs" +#define D_OFF "Ki" +#define D_OFFLINE "Offline" +#define D_OK "OK" +#define D_ON "Be" +#define D_ONLINE "Online" +#define D_PASSWORD "Jelszó" +#define D_PORT "Port" +#define D_POWER_FACTOR "Teljesítménytényező" +#define D_POWERUSAGE "Energiafelhasználás" +#define D_POWERUSAGE_ACTIVE "Aktív teljesítmény" +#define D_POWERUSAGE_APPARENT "Látszólagos teljesítmény" +#define D_POWERUSAGE_REACTIVE "Reaktív teljesítmény" +#define D_PRESSURE "Nyomás" +#define D_PRESSUREATSEALEVEL "Tengerszinti nyomás" +#define D_PROGRAM_FLASH_SIZE "Program flash méret" +#define D_PROGRAM_SIZE "Program méret" +#define D_PROJECT "Projekt" +#define D_RAIN "Eső" +#define D_RECEIVED "Érkezett" +#define D_RESTART "Újraindítás" +#define D_RESTARTING "Újraindítás" +#define D_RESTART_REASON "Utolsó újraindulás oka" +#define D_RESTORE "Visszaállítás" +#define D_RETAINED "retained" +#define D_RULE "Szabály" +#define D_SAVE "Mentés" +#define D_SENSOR "Szenzor" +#define D_SSID "SSID" +#define D_START "" +#define D_STD_TIME "STD" +#define D_STOP "Leállítás" +#define D_SUBNET_MASK "Alhálózati maszk" +#define D_SUBSCRIBE_TO "Feliratkozás a(z)" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Sikeres" +#define D_SUNRISE "Napkelte" +#define D_SUNSET "Napnyugta" +#define D_TEMPERATURE "Hőmérséklet" +#define D_TO "-nak" +#define D_TOGGLE "Megfordítás" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Továbbít" +#define D_TRUE "Igaz" +#define D_TVOC "TVOC" +#define D_UPGRADE "Frissítés" +#define D_UPLOAD "Feltöltés" +#define D_UPTIME "Üzemidő" +#define D_USER "Felhasználó" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV index" +#define D_UV_INDEX_1 "alacsony" +#define D_UV_INDEX_2 "közepes" +#define D_UV_INDEX_3 "magas" +#define D_UV_INDEX_4 "veszélyes" +#define D_UV_INDEX_5 "égés L1/2" +#define D_UV_INDEX_6 "égés L3" +#define D_UV_INDEX_7 "tartományon kívül" +#define D_UV_LEVEL "UV szint" +#define D_UV_POWER "UV teljesítmény" +#define D_VERSION "Verzió" +#define D_VOLTAGE "Feszültség" +#define D_WEIGHT "Tömeg" +#define D_WARMLIGHT "Meleg fény" +#define D_WEB_SERVER "Webszerver" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "VIGYÁZZ! Ez a verzió nem támogat tartós beállításokat" +#define D_LEVEL_10 "szint 1-0" +#define D_LEVEL_01 "szint 0-1" +#define D_SERIAL_LOGGING_DISABLED "Soros naplózás kikapcsolva" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logolás újraengedélyezve" + +#define D_SET_BAUDRATE_TO "Baudrate beállítása" +#define D_RECEIVED_TOPIC "Érkezett topic" +#define D_DATA_SIZE "Adatméret" +#define D_ANALOG_INPUT "Analóg" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Tiltott hurok" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig SIKERTELEN státusz:" +#define D_ACTIVE_FOR_3_MINUTES "aktválás 3 percre" +#define D_FAILED_TO_START "sikertelen indítás" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "AP-hoz csatlakozás:" +#define D_IN_MODE "mód:" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Sikertelen csatlakozás, nincs kiosztott IP cím" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Sikertelen csatlakozás, AP nem elérhető" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Sikertelen csatlakozás, hibás AP jelszó" +#define D_CONNECT_FAILED_AP_TIMEOUT "Sikertelen csatlakozás AP időtúllépés miatt" +#define D_ATTEMPTING_CONNECTION "Csatlakozás..." +#define D_CHECKING_CONNECTION "Kapcsolat ellenőrzése..." +#define D_QUERY_DONE "Lekérés kész. MQTT szolgáltatás aktív" +#define D_MQTT_SERVICE_FOUND "élő MQTT szolgáltatás a(z)" +#define D_FOUND_AT "a(z)" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog hoszt nem található" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Flash-re mentve a(z)" +#define D_LOADED_FROM_FLASH_AT "Flash-ről betöltve a(z)" +#define D_USE_DEFAULTS "Alapértelmezett beáll. használata" +#define D_ERASED_SECTOR "Szektor törlése" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" +#define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:" +#define D_WITH_IP_ADDRESS "IP cím:" +#define D_WEBSERVER_STOPPED "Webszerver leállítva" +#define D_FILE_NOT_FOUND "Fájl nem található" +#define D_REDIRECTED "Átírányítás captive portálra" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WifiManager AccessPoint(AP) és Station(ST) beállítása" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager AccessPoint(AP) beállítása" +#define D_TRYING_TO_CONNECT "Csatlakozás a hálózatra..." + +#define D_RESTART_IN "Újraindítás..." +#define D_SECONDS "másodperc" +#define D_DEVICE_WILL_RESTART "Az eszköz hamarosan újraindul..." +#define D_BUTTON_TOGGLE "Megfordítás" +#define D_CONFIGURATION "Beállítások" +#define D_INFORMATION "Információ" +#define D_FIRMWARE_UPGRADE "Firmware frissítés" +#define D_CONSOLE "Konzol" +#define D_CONFIRM_RESTART "Biztosan újraindítsam a modult?" + +#define D_CONFIGURE_MODULE "Eszközbeállítások" +#define D_CONFIGURE_WIFI "WiFi konfiguráció" +#define D_CONFIGURE_MQTT "MQTT konfiguráció" +#define D_CONFIGURE_DOMOTICZ "Domoticz konfiguráció" +#define D_CONFIGURE_LOGGING "Naplózás beállításai" +#define D_CONFIGURE_OTHER "Egyéb beállítások" +#define D_CONFIRM_RESET_CONFIGURATION "Biztosan töröljem a beállításokat?" +#define D_RESET_CONFIGURATION "Beállítások törlése" +#define D_BACKUP_CONFIGURATION "Beállítások mentése" +#define D_RESTORE_CONFIGURATION "Beállítások visszatöltése" +#define D_MAIN_MENU "Menü" + +#define D_MODULE_PARAMETERS "Modul paraméterek" +#define D_MODULE_TYPE "Alkalmazott modul" +#define D_PULLUP_ENABLE "Nincs felhúzó ellenállás" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Soros BE" +#define D_SERIAL_OUT "Soros KI" + +#define D_WIFI_PARAMETERS "WiFi paraméterek" +#define D_SCAN_FOR_WIFI_NETWORKS "WiFi hálózat keresése" +#define D_SCAN_DONE "Keresés kész" +#define D_NO_NETWORKS_FOUND "Nincs elérhető hálózat" +#define D_REFRESH_TO_SCAN_AGAIN "Frissíts az újrakereséshez" +#define D_DUPLICATE_ACCESSPOINT "Duplikált access point" +#define D_SKIPPING_LOW_QUALITY "Rossz, alacsony jelminőség" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "AP1 megosztott kulcs" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "AP2 megosztott kulcs" + +#define D_MQTT_PARAMETERS "MQTT paraméterek" +#define D_CLIENT "Kliens" +#define D_FULL_TOPIC "Teljes topic" + +#define D_LOGGING_PARAMETERS "Naplózási paraméterek" +#define D_SERIAL_LOG_LEVEL "Soros naplózási szint" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web naplózási szint" +#define D_SYS_LOG_LEVEL "Syslog szint" +#define D_MORE_DEBUG "Részletes hibakeresés" +#define D_SYSLOG_HOST "Syslog hoszt" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Telemetria (mp.)" + +#define D_OTHER_PARAMETERS "Egyéb beállítások" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Web admin jelszó" +#define D_MQTT_ENABLE "MQTT engedélyezése" +#define D_FRIENDLY_NAME "Név" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Beállítások mentése" +#define D_CONFIGURATION_SAVED "Beállítások elmentve" +#define D_CONFIGURATION_RESET "Beállítások visszaállítása" + +#define D_PROGRAM_VERSION "Program verzió" +#define D_BUILD_DATE_AND_TIME "Build ideje" +#define D_CORE_AND_SDK_VERSION "Core/SDK verzió" +#define D_FLASH_WRITE_COUNT "Flash írások száma" +#define D_MAC_ADDRESS "MAC cím" +#define D_MQTT_HOST "MQTT hoszt" +#define D_MQTT_PORT "MQTT port" +#define D_MQTT_CLIENT "MQTT kliens" +#define D_MQTT_USER "MQTT felhasználó" +#define D_MQTT_TOPIC "MQTT topic" +#define D_MQTT_GROUP_TOPIC "MQTT csoport topic" +#define D_MQTT_FULL_TOPIC "MQTT teljes topic" +#define D_MDNS_DISCOVERY "mDNS láthatóság" +#define D_MDNS_ADVERTISE "mDNS hirdetés" +#define D_ESP_CHIP_ID "ESP chip ID" +#define D_FLASH_CHIP_ID "Flash chip ID" +#define D_FLASH_CHIP_SIZE "Flash mérete" +#define D_FREE_PROGRAM_SPACE "Szabad programhely" + +#define D_UPGRADE_BY_WEBSERVER "Frissítés távoli szerverről" +#define D_OTA_URL "OTA URL" +#define D_START_UPGRADE "Frissítés" +#define D_UPGRADE_BY_FILE_UPLOAD "Frissítés helyi fájllal" +#define D_UPLOAD_STARTED "Feltöltés elindítva" +#define D_UPGRADE_STARTED "Frissítés elindítva" +#define D_UPLOAD_DONE "Feltöltés kész" +#define D_UPLOAD_ERR_1 "Nincs fájl kijelölve" +#define D_UPLOAD_ERR_2 "Nincs elég memória" +#define D_UPLOAD_ERR_3 "A \"magic byte\" nem 0xE9" +#define D_UPLOAD_ERR_4 "A program flashméret nagyobb a valós flashméretnél" +#define D_UPLOAD_ERR_5 "Feltöltési buffer hiba" +#define D_UPLOAD_ERR_6 "Feltöltés sikertelen. Endegélyezd a 3. szintű naplózást" +#define D_UPLOAD_ERR_7 "Feltöltés megszakítva" +#define D_UPLOAD_ERR_8 "Érvénytelen fájl" +#define D_UPLOAD_ERR_9 "A fájl túl nagy" +#define D_UPLOAD_ERR_10 "Az RF chip inicializálása sikertelen" +#define D_UPLOAD_ERR_11 "Az RF chip törlése sikertelen" +#define D_UPLOAD_ERR_12 "Az RF chip írása sikertelen" +#define D_UPLOAD_ERR_13 "Az RF firmware dekódolása sikertelen" +#define D_UPLOAD_ERROR_CODE "Feltöltési hibakód" + +#define D_ENTER_COMMAND "Kérem a parancsot..." +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Engedélyezz 2-es szintű webnaplózást több információért" +#define D_NEED_USER_AND_PASSWORD "Szükséges a user=&password= paraméter" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "TLS fingerprint hitelesítése..." +#define D_TLS_CONNECT_FAILED_TO "TLS csatlakozás sikertelen a(z)" +#define D_RETRY_IN "Újrapróbálás" +#define D_VERIFIED "Fingerprint hitelesítve" +#define D_INSECURE "Nem biztonságos kapcsolat érvénytelen fingerprint miatt" +#define D_CONNECT_FAILED_TO "Sikertelen csatlakozás a(z)" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast kikapcsolva" +#define D_MULTICAST_REJOINED "Multicast (újra)csatlakozás" +#define D_MULTICAST_JOIN_FAILED "Multicast csatlakozás sikertelen" +#define D_FAILED_TO_SEND_RESPONSE "Nem sikerült választ küldeni" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo beállítás" +#define D_RESPONSE_SENT "Válasz elküldve" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue beállítás" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API nincs implementálva" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST argumentumok" +#define D_3_RESPONSE_PACKETS_SENT "3 válaszcsomag elküldve" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz paraméterek" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Kapcsoló idx" +#define D_DOMOTICZ_SENSOR_IDX "Szenzor idx" + #define D_DOMOTICZ_TEMP "Hőmérséklet" + #define D_DOMOTICZ_TEMP_HUM "Hőmérséklet, páratartalom" + #define D_DOMOTICZ_TEMP_HUM_BARO "Hőmérséklet, páratartalom, légnyomás" + #define D_DOMOTICZ_POWER_ENERGY "Teljesítmény, energia" + #define D_DOMOTICZ_ILLUMINANCE "Fényerő" + #define D_DOMOTICZ_COUNT "Szám/PM1" + #define D_DOMOTICZ_VOLTAGE "Feszültség/PM2.5" + #define D_DOMOTICZ_CURRENT "Áram/PM10" + #define D_DOMOTICZ_AIRQUALITY "Légminőség" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Frissítési időzítő" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Időzítő beállításai" +#define D_TIMER_PARAMETERS "Időzítő paraméterei" +#define D_TIMER_ENABLE "Időzítők engedélyezve" +#define D_TIMER_ARM "Be" +#define D_TIMER_TIME "Idő" +#define D_TIMER_DAYS "Napok" +#define D_TIMER_REPEAT "Ismétlés" +#define D_TIMER_OUTPUT "Kimenet" +#define D_TIMER_ACTION "Művelet" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX beállításai" +#define D_KNX_PARAMETERS "KNX paraméterei" +#define D_KNX_GENERAL_CONFIG "Általános" +#define D_KNX_PHYSICAL_ADDRESS "Fizikai cím" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(egyedinek kell lennie a KNX hálózaton)" +#define D_KNX_ENABLE "KNX engedélyezése" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Íráshoz használt csoportcímek" +#define D_ADD "Hozzáadás" +#define D_DELETE "Törlés" +#define D_REPLY "Válasz" +#define D_KNX_GROUP_ADDRESS_TO_READ "Fogadáshoz használt csoportcímek" +#define D_RECEIVED_FROM "Fogadva tőle:" +#define D_KNX_COMMAND_WRITE "Írás" +#define D_KNX_COMMAND_READ "Olvasás" +#define D_KNX_COMMAND_OTHER "Egyáb" +#define D_SENT_TO "küldve neki:" +#define D_KNX_WARNING "A csoportcím ( 0 / 0 / 0 ) fenntartott és nem használható." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Mai energia" +#define D_ENERGY_YESTERDAY "Tegnapi energia" +#define D_ENERGY_TOTAL "Összes energia" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Szenzor foglalt" +#define D_SENSOR_CRC_ERROR "Szenzor CRC hiba" +#define D_SENSORS_FOUND "Szenzorok megtalálva" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Időtúllépés, várakozás" +#define D_START_SIGNAL_LOW "startjel alacsony" +#define D_START_SIGNAL_HIGH "startjel magas" +#define D_PULSE "impulzus" +#define D_CHECKSUM_FAILURE "Checksum hiba" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "A szenzor nem nyugtázta a parancsot" +#define D_SHT1X_FOUND "SHT1X megtalálva" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Részecskék" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Gyorsulásm. X-tengely" +#define D_AY_AXIS "Gyorsulásm. Y-tengely" +#define D_AZ_AXIS "Gyorsulásm. Z-tengely" +#define D_GX_AXIS "Giroszkóp X-tengely" +#define D_GY_AXIS "Giroszkóp Y-tengely" +#define D_GZ_AXIS "Giroszkóp Z-tengely" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Távolítsa el a súlyt" +#define D_HX_CAL_REFERENCE "Helyezze fel a referenciasúlyt" +#define D_HX_CAL_DONE "Kalibrálva" +#define D_HX_CAL_FAIL "Kalibrálási hiba" +#define D_RESET_HX711 "Skála újrabeállítása" +#define D_CONFIGURE_HX711 "Skála konfigurálása" +#define D_HX711_PARAMETERS "Skálaparaméterek" +#define D_ITEM_WEIGHT "Tárgy tömege" +#define D_REFERENCE_WEIGHT "Referenciatömeg" +#define D_CALIBRATE "Kalibrálás" +#define D_CALIBRATION "Kalibrálás" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Szélirány" +#define D_TX20_WIND_SPEED "Szélsebesség" +#define D_TX20_WIND_SPEED_AVG "Átlag szélsebesség" +#define D_TX20_WIND_SPEED_MAX "Max. szélsebesség" +#define D_TX20_NORTH "É" +#define D_TX20_EAST "K" +#define D_TX20_SOUTH "D" +#define D_TX20_WEST "NY" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Nincs" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 lejátszó" +#define D_SENSOR_IRSEND "IR adó" +#define D_SENSOR_SWITCH "Kapcsoló" // Suffix "1" +#define D_SENSOR_BUTTON "Gomb" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "LED" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Számláló" // Suffix "1" +#define D_SENSOR_IRRECV "IR vevő" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Háttérfény" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "szektorok" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Fázisszög" +#define D_IMPORT_ACTIVE "Bejövő aktív" +#define D_EXPORT_ACTIVE "Kimenő aktív" +#define D_IMPORT_REACTIVE "Bejövő reaktív" +#define D_EXPORT_REACTIVE "Kimenő reaktív" +#define D_TOTAL_REACTIVE "Összes reaktív" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "fok" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_HU_HU_H_ diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 0585c12d8..a716988de 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -1,701 +1,703 @@ -/* - it-IT.h - localization for Italian - Italy for Tasmota - - Copyright (C) 2019 Gennaro Tortone - some mods by Antonio Fragola - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_IT_IT_H_ -#define _LANGUAGE_IT_IT_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.0.0a -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1040 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "it" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DomLunMarMerGioVenSab" -#define D_MONTH3LIST "GenFebMarAprMagGiuLugAgoSetOttNovDic" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Qualità dell'aria" -#define D_AP "AP" // Access Point -#define D_AS "come" -#define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Numero di boot" -#define D_BRIGHTLIGHT "Luminoso" -#define D_BSSID "BSSId" -#define D_BUTTON "Pulsante" -#define D_BY "da" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canale" -#define D_CO2 "CO2" -#define D_CODE "codice" // Button code -#define D_COLDLIGHT "Fredda" -#define D_COMMAND "Comando" -#define D_CONNECTED "Connesso" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Conteggio" -#define D_COUNTER "Contatore" -#define D_CURRENT "Corrente" // As in Voltage and Current -#define D_DATA "Dati" -#define D_DARKLIGHT "Scuro" -#define D_DEBUG "Debug" -#define D_DISABLED "Disabilitato" -#define D_DISTANCE "Distanza" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Fatto" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulazione" -#define D_ENABLED "Abilitato" -#define D_ERASE "Cancellare" -#define D_ERROR "Errore" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Fallito" -#define D_FALLBACK "Riserva" -#define D_FALLBACK_TOPIC "Topic Riserva" -#define D_FALSE "Falso" -#define D_FILE "File" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Memoria Libera" -#define D_FREQUENCY "Frequenza" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Gruppo" -#define D_HOST "Host" -#define D_HOSTNAME "Nome Host" -#define D_HUMIDITY "Umidità" -#define D_ILLUMINANCE "Illuminazione" -#define D_IMMEDIATE "immediato" // Button immediate -#define D_INDEX "Indice" -#define D_INFO "Info" -#define D_INFRARED "Infrarosso" -#define D_INITIALIZED "Inizializzato" -#define D_IP_ADDRESS "Indirizzo IP" -#define D_LIGHT "Luce" -#define D_LWT "LWT" -#define D_MODULE "Modulo" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-pressione" -#define D_NOISE "Rumore" -#define D_NONE "Nessuno" -#define D_OFF "Off" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "On" -#define D_ONLINE "Online" -#define D_PASSWORD "Password" -#define D_PORT "Porta" -#define D_POWER_FACTOR "Fattore di potenza" -#define D_POWERUSAGE "Potenza" -#define D_POWERUSAGE_ACTIVE "Potenza Attiva" -#define D_POWERUSAGE_APPARENT "Potenza Apparente" -#define D_POWERUSAGE_REACTIVE "Potenza Reattiva" -#define D_PRESSURE "Pressione" -#define D_PRESSUREATSEALEVEL "Pressione al livello del mare" -#define D_PROGRAM_FLASH_SIZE "Dimensione Flash Programma" -#define D_PROGRAM_SIZE "Dimensione Programma" -#define D_PROJECT "Progetto" -#define D_RAIN "Rain" -#define D_RECEIVED "Ricevuto" -#define D_RESTART "Riavvio" -#define D_RESTARTING "Riavviando" -#define D_RESTART_REASON "Causa Riavvio" -#define D_RESTORE "ripristino" -#define D_RETAINED "salvato" -#define D_RULE "Rule" -#define D_SAVE "Salva" -#define D_SENSOR "Sensore" -#define D_SSID "SSId" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Maschera Subnet" -#define D_SUBSCRIBE_TO "Sottoscrivi a" -#define D_UNSUBSCRIBE_FROM "Cancella da" -#define D_SUCCESSFUL "Riuscito" -#define D_SUNRISE "Alba" -#define D_SUNSET "Tramonto" -#define D_TEMPERATURE "Temperatura" -#define D_TO "a" -#define D_TOGGLE "Toggle" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Trasmesso" -#define D_TRUE "Vero" -#define D_TVOC "TVOC" -#define D_UPGRADE "Aggiornamento" -#define D_UPLOAD "Invio" -#define D_UPTIME "Uptime" -#define D_USER "Utente" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Indice UV" -#define D_UV_INDEX_1 "Basso" -#define D_UV_INDEX_2 "Medio" -#define D_UV_INDEX_3 "Alto" -#define D_UV_INDEX_4 "Pericolo" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Livello UV" -#define D_UV_POWER "Intensità UV" -#define D_VERSION "Versione" -#define D_VOLTAGE "Tensione" -#define D_WEIGHT "Peso" -#define D_WARMLIGHT "Calda" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Log Seriale disabilitato" -#define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato" - -#define D_SET_BAUDRATE_TO "Baudrate impostato a" -#define D_RECEIVED_TOPIC "Topic Ricevuto" -#define D_DATA_SIZE "Dimensione Dati" -#define D_ANALOG_INPUT "Ingresso Analogico" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Ciclo Bloccato" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato" -#define D_ACTIVE_FOR_3_MINUTES "Attivo per 3 minuti" -#define D_FAILED_TO_START "Partenza fallita" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Connessione ad AP" -#define D_IN_MODE "In modalità" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta" -#define D_CONNECT_FAILED_AP_TIMEOUT "Connessione fallita, timeout AP" -#define D_ATTEMPTING_CONNECTION "Tentativo di connessione..." -#define D_CHECKING_CONNECTION "Controllo connessione..." -#define D_QUERY_DONE "Query eseguita. Servizio MQTT trovato" -#define D_MQTT_SERVICE_FOUND "Servizio MQTT trovato su" -#define D_FOUND_AT "trovato a" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host non trovato" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Salvato nella flash in" -#define D_LOADED_FROM_FLASH_AT "Caricato dalla flash da" -#define D_USE_DEFAULTS "Utilizzo valori default" -#define D_ERASED_SECTOR "Settore cancellato" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" -#define D_WEBSERVER_ACTIVE_ON "Web server attivo su" -#define D_WITH_IP_ADDRESS "con indirizzo IP" -#define D_WEBSERVER_STOPPED "Web server arrestato" -#define D_FILE_NOT_FOUND "File Non Trovato" -#define D_REDIRECTED "Redirezione al captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Impostazione Wifimanager come AccessPoint e Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Impostazione Wifimanager come AccessPoint" -#define D_TRYING_TO_CONNECT "Tentativo di connessione del dispositivo alla rete" - -#define D_RESTART_IN "Riavvio in" -#define D_SECONDS "secondi" -#define D_DEVICE_WILL_RESTART "Il dispositivo verrà riavviato tra pochi secondi" -#define D_BUTTON_TOGGLE "On/Off" -#define D_CONFIGURATION "Configurazione" -#define D_INFORMATION "Informazioni" -#define D_FIRMWARE_UPGRADE "Aggiornamento Firmware" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Conferma Riavvio" - -#define D_CONFIGURE_MODULE "Configurazione Modulo" -#define D_CONFIGURE_WIFI "Configurazione WiFi" -#define D_CONFIGURE_MQTT "Configurazione MQTT" -#define D_CONFIGURE_DOMOTICZ "Configurazione Domoticz" -#define D_CONFIGURE_LOGGING "Configurazione Logging" -#define D_CONFIGURE_OTHER "Configurazione Extra" -#define D_CONFIRM_RESET_CONFIGURATION "Conferma Reset Configurazione" -#define D_RESET_CONFIGURATION "Reset Configurazione" -#define D_BACKUP_CONFIGURATION "Backup Configurazione" -#define D_RESTORE_CONFIGURATION "Ripristino Configurazione" -#define D_MAIN_MENU "Menu Principale" - -#define D_MODULE_PARAMETERS "Parametri del modulo" -#define D_MODULE_TYPE "Tipo modulo" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Seriale In" -#define D_SERIAL_OUT "Seriale Out" - -#define D_WIFI_PARAMETERS "Parametri Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi" -#define D_SCAN_DONE "Scansione effettuata" -#define D_NO_NETWORKS_FOUND "Nessuna rete trovata" -#define D_REFRESH_TO_SCAN_AGAIN "Ricarica per nuova scansione" -#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicato" -#define D_SKIPPING_LOW_QUALITY "Ignorato a causa di bassa qualità" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Password" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Password" - -#define D_MQTT_PARAMETERS "Parametri MQTT" -#define D_CLIENT "Client" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "Parametri Logging" -#define D_SERIAL_LOG_LEVEL "Livello di log Seriale" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "livello di log Web" -#define D_SYS_LOG_LEVEL "livello di log Sys" -#define D_MORE_DEBUG "Debug aggiuntivo" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog porta" -#define D_TELEMETRY_PERIOD "Periodo Telemetria" - -#define D_OTHER_PARAMETERS "Altri parametri" -#define D_TEMPLATE "Modello" -#define D_ACTIVATE "Attivare" -#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web" -#define D_MQTT_ENABLE "Abilita MQTT" -#define D_FRIENDLY_NAME "Nome amichevole" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "dispositivo singolo" -#define D_MULTI_DEVICE "dispositivo multiplo" - -#define D_CONFIGURE_TEMPLATE "Configurare Modello" -#define D_TEMPLATE_PARAMETERS "Parametri Modello" -#define D_TEMPLATE_NAME "Nome" -#define D_BASE_TYPE "Basato nel" -#define D_TEMPLATE_FLAGS "Opzioni" - -#define D_SAVE_CONFIGURATION "Salva configurazione" -#define D_CONFIGURATION_SAVED "Configurazione salvata" -#define D_CONFIGURATION_RESET "Configurazione azzerata" - -#define D_PROGRAM_VERSION "Versione del programma" -#define D_BUILD_DATE_AND_TIME "Data e ora compilazione" -#define D_CORE_AND_SDK_VERSION "Versione Core/SDK" -#define D_FLASH_WRITE_COUNT "Contatore scrittura Flash" -#define D_MAC_ADDRESS "Indirizzo MAC" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Porta" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT Utente" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Dimensione Flash" -#define D_FREE_PROGRAM_SPACE "Spazio Libero Memoria Programma" - -#define D_UPGRADE_BY_WEBSERVER "Aggiornamento da web server" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Avvio aggiornamento" -#define D_UPGRADE_BY_FILE_UPLOAD "Aggiornamento tramite invio file" -#define D_UPLOAD_STARTED "Invio iniziato" -#define D_UPGRADE_STARTED "Aggiornamento avviato" -#define D_UPLOAD_DONE "Invio effettuato" -#define D_UPLOAD_ERR_1 "Nessun file selezionato" -#define D_UPLOAD_ERR_2 "Spazio insufficiente" -#define D_UPLOAD_ERR_3 "Magic byte non corrispondente a 0xE9" -#define D_UPLOAD_ERR_4 "Dimensione della memoria programma maggiore della dimensione reale della flash" -#define D_UPLOAD_ERR_5 "Errore di comparazione del buffer di invio" -#define D_UPLOAD_ERR_6 "Invio fallito. Abilitare logging 3" -#define D_UPLOAD_ERR_7 "Invio annullato" -#define D_UPLOAD_ERR_8 "File non valido" -#define D_UPLOAD_ERR_9 "File troppo grande" -#define D_UPLOAD_ERR_10 "Inizializzazione fallita del chip RF" -#define D_UPLOAD_ERR_11 "Cancellazione fallita del chip RF" -#define D_UPLOAD_ERR_12 "Scrittura fallita del chip RF" -#define D_UPLOAD_ERR_13 "Decodifica fallita del firmware RF" -#define D_UPLOAD_ERROR_CODE "Codice errore invio" - -#define D_ENTER_COMMAND "Inserire comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Abilitare weblog 2 se è attesa una risposta" -#define D_NEED_USER_AND_PASSWORD "Richiesto user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifica TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "Connessione TLS fallita a" -#define D_RETRY_IN "Nuovo tentativo in" -#define D_VERIFIED "Verificato Fingerprint" -#define D_INSECURE "Connessione insicura a causa di Fingerprint non valido" -#define D_CONNECT_FAILED_TO "Connessione Fallita a" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast disabilitato" -#define D_MULTICAST_REJOINED "Multicast (ri)associato" -#define D_MULTICAST_JOIN_FAILED "Associazione Multicast fallita" -#define D_FAILED_TO_SEND_RESPONSE "Invio risposta fallito" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo evento base" -#define D_WEMO_EVENT_SERVICE "WeMo servizio eventi" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "Impostazione WeMo" -#define D_RESPONSE_SENT "Risposta inviata" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Impostazione Hue" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API non implementata" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argomenti" -#define D_3_RESPONSE_PACKETS_SENT "3 pacchetti di risposta inviati" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parametri Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Intervallo di aggiornamento" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configura Timer" -#define D_TIMER_PARAMETERS "Parametri Timer" -#define D_TIMER_ENABLE "Abilita Timer" -#define D_TIMER_ARM "Attiva" -#define D_TIMER_TIME "Ora" -#define D_TIMER_DAYS "Giorni" -#define D_TIMER_REPEAT "Ripeti" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Azione" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configura KNX" -#define D_KNX_PARAMETERS "Parametri KNX" -#define D_KNX_GENERAL_CONFIG "Generale" -#define D_KNX_PHYSICAL_ADDRESS "Indirizzo Fisico" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve essere univoco nella rete KNX )" -#define D_KNX_ENABLE "Abilita KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dati da Inviare al Gruppo di Indirizzi" -#define D_ADD "Aggiungi" -#define D_DELETE "Elimina" -#define D_REPLY "Rispondi" -#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppo di Indirizzi da cui Ricevere Dati" -#define D_RECEIVED_FROM "Ricevuto Da" -#define D_KNX_COMMAND_WRITE "Scrivi" -#define D_KNX_COMMAND_READ "Leggi" -#define D_KNX_COMMAND_OTHER "Altro" -#define D_SENT_TO "invia a" -#define D_KNX_WARNING "L'indirizzo del gruppo ( 0 / 0 / 0 ) è riservato e non può essere usato." -#define D_KNX_ENHANCEMENT "Miglioramento Comunicazione" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energia Oggi" -#define D_ENERGY_YESTERDAY "Energia Ieri" -#define D_ENERGY_TOTAL "Energia Totale" - -// xdrv_27_shutter.ino -#define D_OPEN "Aperta" -#define D_CLOSE "Chiusa" -#define D_DOMOTICZ_SHUTTER "Serranda" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configura PCF8574" -#define D_PCF8574_PARAMETERS "Parametri PCF8574" -#define D_INVERT_PORTS "Porte Invertite" -#define D_DEVICE "Dispositivo" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensore occupato" -#define D_SENSOR_CRC_ERROR "Sensore errore CRC" -#define D_SENSORS_FOUND "Sensori trovati" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Attesa timeout per" -#define D_START_SIGNAL_LOW "inizio segnale basso" -#define D_START_SIGNAL_HIGH "inizio segnale alto" -#define D_PULSE "impulso" -#define D_CHECKSUM_FAILURE "Checksum fallito" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensore non ha eseguito il comando ACK" -#define D_SHT1X_FOUND "SHT1X trovato" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particelle" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. Asse-X" -#define D_AY_AXIS "Accel. Asse-Y" -#define D_AZ_AXIS "Accel. Asse-Z" -#define D_GX_AXIS "Gyro Asse-X" -#define D_GY_AXIS "Gyro Asse-Y" -#define D_GZ_AXIS "Gyro Asse-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Rimuovere peso" -#define D_HX_CAL_REFERENCE "Caricare peso di riferimento" -#define D_HX_CAL_DONE "Calibrato" -#define D_HX_CAL_FAIL "Calibrazione fallita" -#define D_RESET_HX711 "Reset Scala" -#define D_CONFIGURE_HX711 "Configura Scala" -#define D_HX711_PARAMETERS "Parametri Scala" -#define D_ITEM_WEIGHT "Peso oggetto" -#define D_REFERENCE_WEIGHT "Peso di riferimento" -#define D_CALIBRATE "Calibrato" -#define D_CALIBRATION "Calibrazione" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direzione Vento" -#define D_TX20_WIND_SPEED "Velocità Vento" -#define D_TX20_WIND_SPEED_AVG "Velocità Media Vento" -#define D_TX20_WIND_SPEED_MAX "Velocità Massima Vento" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Nessuno" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "settori" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Angolo Fase" -#define D_IMPORT_ACTIVE "Potenza Attiva Importata" -#define D_EXPORT_ACTIVE "Potenza Attiva Esportata" -#define D_IMPORT_REACTIVE "Potenza Reattiva Importata" -#define D_EXPORT_REACTIVE "Potenza Reattiva Esportata" -#define D_TOTAL_REACTIVE "Potenza Reattiva Totale" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "°" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltaggio" -#define D_PV1_CURRENT "PV1 Corrente" -#define D_PV1_POWER "PV1 Eergia" -#define D_PV2_VOLTAGE "PV2 Voltaggio" -#define D_PV2_CURRENT "PV2 Corrente" -#define D_PV2_POWER "PV2 Energia" -#define D_SOLAR_POWER "Energia Solar" -#define D_INVERTER_POWER "Energia Inverter" -#define D_STATUS "Stato" -#define D_WAITING "In attesa" -#define D_CHECKING "Controllando" -#define D_WORKING "Lavorando" -#define D_FAILURE "Errore" -#define D_SOLAX_ERROR_0 "No Codice Errore" -#define D_SOLAX_ERROR_1 "Errore Grid Persa" -#define D_SOLAX_ERROR_2 "Errore Voltaggio Grid" -#define D_SOLAX_ERROR_3 "Errore Frequenza Grid" -#define D_SOLAX_ERROR_4 "Errore Voltaggio Pv" -#define D_SOLAX_ERROR_5 "Errore Isolamento" -#define D_SOLAX_ERROR_6 "Errore Temperatura Eccessiva" -#define D_SOLAX_ERROR_7 "Errore Ventilatore" -#define D_SOLAX_ERROR_8 "Altro Errore del Dispositivo" - -#endif // _LANGUAGE_IT_IT_H_ +/* + it-IT.h - localization for Italian - Italy for Tasmota + + Copyright (C) 2019 Gennaro Tortone - some mods by Antonio Fragola + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_IT_IT_H_ +#define _LANGUAGE_IT_IT_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.0.0a +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1040 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "it" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DomLunMarMerGioVenSab" +#define D_MONTH3LIST "GenFebMarAprMagGiuLugAgoSetOttNovDic" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Qualità dell'aria" +#define D_AP "AP" // Access Point +#define D_AS "come" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Numero di boot" +#define D_BRIGHTLIGHT "Luminoso" +#define D_BSSID "BSSId" +#define D_BUTTON "Pulsante" +#define D_BY "da" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canale" +#define D_CO2 "CO2" +#define D_CODE "codice" // Button code +#define D_COLDLIGHT "Fredda" +#define D_COMMAND "Comando" +#define D_CONNECTED "Connesso" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Conteggio" +#define D_COUNTER "Contatore" +#define D_CURRENT "Corrente" // As in Voltage and Current +#define D_DATA "Dati" +#define D_DARKLIGHT "Scuro" +#define D_DEBUG "Debug" +#define D_DISABLED "Disabilitato" +#define D_DISTANCE "Distanza" +#define D_DNS_SERVER "DNS Server" +#define D_DONE "Fatto" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulazione" +#define D_ENABLED "Abilitato" +#define D_ERASE "Cancellare" +#define D_ERROR "Errore" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Fallito" +#define D_FALLBACK "Riserva" +#define D_FALLBACK_TOPIC "Topic Riserva" +#define D_FALSE "Falso" +#define D_FILE "File" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Memoria Libera" +#define D_FREQUENCY "Frequenza" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Gruppo" +#define D_HOST "Host" +#define D_HOSTNAME "Nome Host" +#define D_HUMIDITY "Umidità" +#define D_ILLUMINANCE "Illuminazione" +#define D_IMMEDIATE "immediato" // Button immediate +#define D_INDEX "Indice" +#define D_INFO "Info" +#define D_INFRARED "Infrarosso" +#define D_INITIALIZED "Inizializzato" +#define D_IP_ADDRESS "Indirizzo IP" +#define D_LIGHT "Luce" +#define D_LWT "LWT" +#define D_MODULE "Modulo" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-pressione" +#define D_NOISE "Rumore" +#define D_NONE "Nessuno" +#define D_OFF "Off" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "On" +#define D_ONLINE "Online" +#define D_PASSWORD "Password" +#define D_PORT "Porta" +#define D_POWER_FACTOR "Fattore di potenza" +#define D_POWERUSAGE "Potenza" +#define D_POWERUSAGE_ACTIVE "Potenza Attiva" +#define D_POWERUSAGE_APPARENT "Potenza Apparente" +#define D_POWERUSAGE_REACTIVE "Potenza Reattiva" +#define D_PRESSURE "Pressione" +#define D_PRESSUREATSEALEVEL "Pressione al livello del mare" +#define D_PROGRAM_FLASH_SIZE "Dimensione Flash Programma" +#define D_PROGRAM_SIZE "Dimensione Programma" +#define D_PROJECT "Progetto" +#define D_RAIN "Rain" +#define D_RECEIVED "Ricevuto" +#define D_RESTART "Riavvio" +#define D_RESTARTING "Riavviando" +#define D_RESTART_REASON "Causa Riavvio" +#define D_RESTORE "ripristino" +#define D_RETAINED "salvato" +#define D_RULE "Rule" +#define D_SAVE "Salva" +#define D_SENSOR "Sensore" +#define D_SSID "SSId" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maschera Subnet" +#define D_SUBSCRIBE_TO "Sottoscrivi a" +#define D_UNSUBSCRIBE_FROM "Cancella da" +#define D_SUCCESSFUL "Riuscito" +#define D_SUNRISE "Alba" +#define D_SUNSET "Tramonto" +#define D_TEMPERATURE "Temperatura" +#define D_TO "a" +#define D_TOGGLE "Toggle" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Trasmesso" +#define D_TRUE "Vero" +#define D_TVOC "TVOC" +#define D_UPGRADE "Aggiornamento" +#define D_UPLOAD "Invio" +#define D_UPTIME "Uptime" +#define D_USER "Utente" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Indice UV" +#define D_UV_INDEX_1 "Basso" +#define D_UV_INDEX_2 "Medio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Pericolo" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Livello UV" +#define D_UV_POWER "Intensità UV" +#define D_VERSION "Versione" +#define D_VOLTAGE "Tensione" +#define D_WEIGHT "Peso" +#define D_WARMLIGHT "Calda" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Log Seriale disabilitato" +#define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato" + +#define D_SET_BAUDRATE_TO "Baudrate impostato a" +#define D_RECEIVED_TOPIC "Topic Ricevuto" +#define D_DATA_SIZE "Dimensione Dati" +#define D_ANALOG_INPUT "Ingresso Analogico" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Ciclo Bloccato" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato" +#define D_ACTIVE_FOR_3_MINUTES "Attivo per 3 minuti" +#define D_FAILED_TO_START "Partenza fallita" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Connessione ad AP" +#define D_IN_MODE "In modalità" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta" +#define D_CONNECT_FAILED_AP_TIMEOUT "Connessione fallita, timeout AP" +#define D_ATTEMPTING_CONNECTION "Tentativo di connessione..." +#define D_CHECKING_CONNECTION "Controllo connessione..." +#define D_QUERY_DONE "Query eseguita. Servizio MQTT trovato" +#define D_MQTT_SERVICE_FOUND "Servizio MQTT trovato su" +#define D_FOUND_AT "trovato a" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host non trovato" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Salvato nella flash in" +#define D_LOADED_FROM_FLASH_AT "Caricato dalla flash da" +#define D_USE_DEFAULTS "Utilizzo valori default" +#define D_ERASED_SECTOR "Settore cancellato" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" +#define D_WEBSERVER_ACTIVE_ON "Web server attivo su" +#define D_WITH_IP_ADDRESS "con indirizzo IP" +#define D_WEBSERVER_STOPPED "Web server arrestato" +#define D_FILE_NOT_FOUND "File Non Trovato" +#define D_REDIRECTED "Redirezione al captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Impostazione Wifimanager come AccessPoint e Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Impostazione Wifimanager come AccessPoint" +#define D_TRYING_TO_CONNECT "Tentativo di connessione del dispositivo alla rete" + +#define D_RESTART_IN "Riavvio in" +#define D_SECONDS "secondi" +#define D_DEVICE_WILL_RESTART "Il dispositivo verrà riavviato tra pochi secondi" +#define D_BUTTON_TOGGLE "On/Off" +#define D_CONFIGURATION "Configurazione" +#define D_INFORMATION "Informazioni" +#define D_FIRMWARE_UPGRADE "Aggiornamento Firmware" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Conferma Riavvio" + +#define D_CONFIGURE_MODULE "Configurazione Modulo" +#define D_CONFIGURE_WIFI "Configurazione WiFi" +#define D_CONFIGURE_MQTT "Configurazione MQTT" +#define D_CONFIGURE_DOMOTICZ "Configurazione Domoticz" +#define D_CONFIGURE_LOGGING "Configurazione Logging" +#define D_CONFIGURE_OTHER "Configurazione Extra" +#define D_CONFIRM_RESET_CONFIGURATION "Conferma Reset Configurazione" +#define D_RESET_CONFIGURATION "Reset Configurazione" +#define D_BACKUP_CONFIGURATION "Backup Configurazione" +#define D_RESTORE_CONFIGURATION "Ripristino Configurazione" +#define D_MAIN_MENU "Menu Principale" + +#define D_MODULE_PARAMETERS "Parametri del modulo" +#define D_MODULE_TYPE "Tipo modulo" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Seriale In" +#define D_SERIAL_OUT "Seriale Out" + +#define D_WIFI_PARAMETERS "Parametri Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi" +#define D_SCAN_DONE "Scansione effettuata" +#define D_NO_NETWORKS_FOUND "Nessuna rete trovata" +#define D_REFRESH_TO_SCAN_AGAIN "Ricarica per nuova scansione" +#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicato" +#define D_SKIPPING_LOW_QUALITY "Ignorato a causa di bassa qualità" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Password" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Password" + +#define D_MQTT_PARAMETERS "Parametri MQTT" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "Parametri Logging" +#define D_SERIAL_LOG_LEVEL "Livello di log Seriale" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "livello di log Web" +#define D_SYS_LOG_LEVEL "livello di log Sys" +#define D_MORE_DEBUG "Debug aggiuntivo" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog porta" +#define D_TELEMETRY_PERIOD "Periodo Telemetria" + +#define D_OTHER_PARAMETERS "Altri parametri" +#define D_TEMPLATE "Modello" +#define D_ACTIVATE "Attivare" +#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web" +#define D_MQTT_ENABLE "Abilita MQTT" +#define D_FRIENDLY_NAME "Nome amichevole" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "dispositivo singolo" +#define D_MULTI_DEVICE "dispositivo multiplo" + +#define D_CONFIGURE_TEMPLATE "Configurare Modello" +#define D_TEMPLATE_PARAMETERS "Parametri Modello" +#define D_TEMPLATE_NAME "Nome" +#define D_BASE_TYPE "Basato nel" +#define D_TEMPLATE_FLAGS "Opzioni" + +#define D_SAVE_CONFIGURATION "Salva configurazione" +#define D_CONFIGURATION_SAVED "Configurazione salvata" +#define D_CONFIGURATION_RESET "Configurazione azzerata" + +#define D_PROGRAM_VERSION "Versione del programma" +#define D_BUILD_DATE_AND_TIME "Data e ora compilazione" +#define D_CORE_AND_SDK_VERSION "Versione Core/SDK" +#define D_FLASH_WRITE_COUNT "Contatore scrittura Flash" +#define D_MAC_ADDRESS "Indirizzo MAC" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Porta" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT Utente" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Dimensione Flash" +#define D_FREE_PROGRAM_SPACE "Spazio Libero Memoria Programma" + +#define D_UPGRADE_BY_WEBSERVER "Aggiornamento da web server" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Avvio aggiornamento" +#define D_UPGRADE_BY_FILE_UPLOAD "Aggiornamento tramite invio file" +#define D_UPLOAD_STARTED "Invio iniziato" +#define D_UPGRADE_STARTED "Aggiornamento avviato" +#define D_UPLOAD_DONE "Invio effettuato" +#define D_UPLOAD_ERR_1 "Nessun file selezionato" +#define D_UPLOAD_ERR_2 "Spazio insufficiente" +#define D_UPLOAD_ERR_3 "Magic byte non corrispondente a 0xE9" +#define D_UPLOAD_ERR_4 "Dimensione della memoria programma maggiore della dimensione reale della flash" +#define D_UPLOAD_ERR_5 "Errore di comparazione del buffer di invio" +#define D_UPLOAD_ERR_6 "Invio fallito. Abilitare logging 3" +#define D_UPLOAD_ERR_7 "Invio annullato" +#define D_UPLOAD_ERR_8 "File non valido" +#define D_UPLOAD_ERR_9 "File troppo grande" +#define D_UPLOAD_ERR_10 "Inizializzazione fallita del chip RF" +#define D_UPLOAD_ERR_11 "Cancellazione fallita del chip RF" +#define D_UPLOAD_ERR_12 "Scrittura fallita del chip RF" +#define D_UPLOAD_ERR_13 "Decodifica fallita del firmware RF" +#define D_UPLOAD_ERROR_CODE "Codice errore invio" + +#define D_ENTER_COMMAND "Inserire comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Abilitare weblog 2 se è attesa una risposta" +#define D_NEED_USER_AND_PASSWORD "Richiesto user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifica TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "Connessione TLS fallita a" +#define D_RETRY_IN "Nuovo tentativo in" +#define D_VERIFIED "Verificato Fingerprint" +#define D_INSECURE "Connessione insicura a causa di Fingerprint non valido" +#define D_CONNECT_FAILED_TO "Connessione Fallita a" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast disabilitato" +#define D_MULTICAST_REJOINED "Multicast (ri)associato" +#define D_MULTICAST_JOIN_FAILED "Associazione Multicast fallita" +#define D_FAILED_TO_SEND_RESPONSE "Invio risposta fallito" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo evento base" +#define D_WEMO_EVENT_SERVICE "WeMo servizio eventi" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "Impostazione WeMo" +#define D_RESPONSE_SENT "Risposta inviata" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Impostazione Hue" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API non implementata" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST argomenti" +#define D_3_RESPONSE_PACKETS_SENT "3 pacchetti di risposta inviati" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parametri Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Intervallo di aggiornamento" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configura Timer" +#define D_TIMER_PARAMETERS "Parametri Timer" +#define D_TIMER_ENABLE "Abilita Timer" +#define D_TIMER_ARM "Attiva" +#define D_TIMER_TIME "Ora" +#define D_TIMER_DAYS "Giorni" +#define D_TIMER_REPEAT "Ripeti" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Azione" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configura KNX" +#define D_KNX_PARAMETERS "Parametri KNX" +#define D_KNX_GENERAL_CONFIG "Generale" +#define D_KNX_PHYSICAL_ADDRESS "Indirizzo Fisico" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve essere univoco nella rete KNX )" +#define D_KNX_ENABLE "Abilita KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dati da Inviare al Gruppo di Indirizzi" +#define D_ADD "Aggiungi" +#define D_DELETE "Elimina" +#define D_REPLY "Rispondi" +#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppo di Indirizzi da cui Ricevere Dati" +#define D_RECEIVED_FROM "Ricevuto Da" +#define D_KNX_COMMAND_WRITE "Scrivi" +#define D_KNX_COMMAND_READ "Leggi" +#define D_KNX_COMMAND_OTHER "Altro" +#define D_SENT_TO "invia a" +#define D_KNX_WARNING "L'indirizzo del gruppo ( 0 / 0 / 0 ) è riservato e non può essere usato." +#define D_KNX_ENHANCEMENT "Miglioramento Comunicazione" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energia Oggi" +#define D_ENERGY_YESTERDAY "Energia Ieri" +#define D_ENERGY_TOTAL "Energia Totale" + +// xdrv_27_shutter.ino +#define D_OPEN "Aperta" +#define D_CLOSE "Chiusa" +#define D_DOMOTICZ_SHUTTER "Serranda" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configura PCF8574" +#define D_PCF8574_PARAMETERS "Parametri PCF8574" +#define D_INVERT_PORTS "Porte Invertite" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensore occupato" +#define D_SENSOR_CRC_ERROR "Sensore errore CRC" +#define D_SENSORS_FOUND "Sensori trovati" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Attesa timeout per" +#define D_START_SIGNAL_LOW "inizio segnale basso" +#define D_START_SIGNAL_HIGH "inizio segnale alto" +#define D_PULSE "impulso" +#define D_CHECKSUM_FAILURE "Checksum fallito" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensore non ha eseguito il comando ACK" +#define D_SHT1X_FOUND "SHT1X trovato" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particelle" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. Asse-X" +#define D_AY_AXIS "Accel. Asse-Y" +#define D_AZ_AXIS "Accel. Asse-Z" +#define D_GX_AXIS "Gyro Asse-X" +#define D_GY_AXIS "Gyro Asse-Y" +#define D_GZ_AXIS "Gyro Asse-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Rimuovere peso" +#define D_HX_CAL_REFERENCE "Caricare peso di riferimento" +#define D_HX_CAL_DONE "Calibrato" +#define D_HX_CAL_FAIL "Calibrazione fallita" +#define D_RESET_HX711 "Reset Scala" +#define D_CONFIGURE_HX711 "Configura Scala" +#define D_HX711_PARAMETERS "Parametri Scala" +#define D_ITEM_WEIGHT "Peso oggetto" +#define D_REFERENCE_WEIGHT "Peso di riferimento" +#define D_CALIBRATE "Calibrato" +#define D_CALIBRATION "Calibrazione" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direzione Vento" +#define D_TX20_WIND_SPEED "Velocità Vento" +#define D_TX20_WIND_SPEED_AVG "Velocità Media Vento" +#define D_TX20_WIND_SPEED_MAX "Velocità Massima Vento" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Nessuno" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "settori" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Angolo Fase" +#define D_IMPORT_ACTIVE "Potenza Attiva Importata" +#define D_EXPORT_ACTIVE "Potenza Attiva Esportata" +#define D_IMPORT_REACTIVE "Potenza Reattiva Importata" +#define D_EXPORT_REACTIVE "Potenza Reattiva Esportata" +#define D_TOTAL_REACTIVE "Potenza Reattiva Totale" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "°" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltaggio" +#define D_PV1_CURRENT "PV1 Corrente" +#define D_PV1_POWER "PV1 Eergia" +#define D_PV2_VOLTAGE "PV2 Voltaggio" +#define D_PV2_CURRENT "PV2 Corrente" +#define D_PV2_POWER "PV2 Energia" +#define D_SOLAR_POWER "Energia Solar" +#define D_INVERTER_POWER "Energia Inverter" +#define D_STATUS "Stato" +#define D_WAITING "In attesa" +#define D_CHECKING "Controllando" +#define D_WORKING "Lavorando" +#define D_FAILURE "Errore" +#define D_SOLAX_ERROR_0 "No Codice Errore" +#define D_SOLAX_ERROR_1 "Errore Grid Persa" +#define D_SOLAX_ERROR_2 "Errore Voltaggio Grid" +#define D_SOLAX_ERROR_3 "Errore Frequenza Grid" +#define D_SOLAX_ERROR_4 "Errore Voltaggio Pv" +#define D_SOLAX_ERROR_5 "Errore Isolamento" +#define D_SOLAX_ERROR_6 "Errore Temperatura Eccessiva" +#define D_SOLAX_ERROR_7 "Errore Ventilatore" +#define D_SOLAX_ERROR_8 "Altro Errore del Dispositivo" + +#endif // _LANGUAGE_IT_IT_H_ diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index bff508474..4da467267 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -1,701 +1,703 @@ -/* - ko-KO.h - localization for Korean - Korean for Tasmota - - Copyright (C) 2019 Theo Arends (translated by NyaamZ) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_KO_KO_H_ -#define _LANGUAGE_KO_KO_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.11 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -// https://www.science.co.il/language/Locale-codes.php -#define LANGUAGE_LCID 1042 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "ko" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "일 월 화 수 목 금 토 " -#define D_MONTH3LIST "1월 2월 3월 4월 5월 6월 7월 8월 9월 10월11월12월" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "공기질" -#define D_AP "AP" // Access Point -#define D_AS "as" -#define D_AUTO "자동" -#define D_BLINK "깜박임" -#define D_BLINKOFF "깜박임 끄기" -#define D_BOOT_COUNT "부팅 횟수" -#define D_BRIGHTLIGHT "밝게" -#define D_BSSID "BSSId" -#define D_BUTTON "버튼" -#define D_BY "by" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "섭씨" -#define D_CHANNEL "채널" -#define D_CO2 "이산화탄소" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "차갑게" -#define D_COMMAND "커맨드" -#define D_CONNECTED "연결됨" -#define D_COUNT "횟수" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNTER "Counter" -#define D_CURRENT "전류" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "어둡게" -#define D_DEBUG "디버그" -#define D_DISABLED "사용안함" -#define D_DISTANCE "거리" -#define D_DNS_SERVER "DNS 서버" -#define D_DONE "완료" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "에뮬레이션" -#define D_ENABLED "사용" -#define D_ERASE "삭제" -#define D_ERROR "에러" -#define D_FAHRENHEIT "화씨" -#define D_FAILED "실패" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "거짓" -#define D_FILE "파일" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "남은 메모리" -#define D_FREQUENCY "Frequency" -#define D_GAS "가스" -#define D_GATEWAY "게이트웨이" -#define D_GROUP "그룹" -#define D_HOST "호스트" -#define D_HOSTNAME "호스트이름" -#define D_HUMIDITY "습도" -#define D_ILLUMINANCE "조도" -#define D_IMMEDIATE "immediate" // Button immediate -#define D_INDEX "인덱스" -#define D_INFO "정보" -#define D_INFRARED "적외선" -#define D_INITIALIZED "초기화됨" -#define D_IP_ADDRESS "IP 주소" -#define D_LIGHT "밝게" -#define D_LWT "LWT" -#define D_MODULE "모듈" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "소음" -#define D_NONE "없음" -#define D_OFF "꺼짐" -#define D_OFFLINE "오프라인" -#define D_OK "Ok" -#define D_ON "켜짐" -#define D_ONLINE "온라인" -#define D_PASSWORD "비밀번호" -#define D_PORT "포트" -#define D_POWER_FACTOR "Power Factor" -#define D_POWERUSAGE "전원" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "기압" -#define D_PRESSUREATSEALEVEL "해수면기압" -#define D_PROGRAM_FLASH_SIZE "플래시 용량" -#define D_PROGRAM_SIZE "프로그램 용량" -#define D_PROJECT "프로젝트" -#define D_RAIN "비" -#define D_RECEIVED "받음" -#define D_RESTART "재시작" -#define D_RESTARTING "재시작 중.." -#define D_RESTART_REASON "재시작 사유" -#define D_RESTORE "복구" -#define D_RETAINED "보류" -#define D_RULE "규칙" -#define D_SAVE "저장" -#define D_SENSOR "센서" -#define D_SSID "SSId" -#define D_START "시작" -#define D_STD_TIME "STD" -#define D_STOP "정지" -#define D_SUBNET_MASK "서브넷 마스크" -#define D_SUBSCRIBE_TO "구독" -#define D_UNSUBSCRIBE_FROM "구독 해제" -#define D_SUCCESSFUL "성공" -#define D_SUNRISE "일출" -#define D_SUNSET "일몰" -#define D_TEMPERATURE "온도" -#define D_TO "to" -#define D_TOGGLE "켜기/끄기" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "전체 사용량" -#define D_TRANSMIT "전송" -#define D_TRUE "참" -#define D_TVOC "TVOC" -#define D_UPGRADE "업그레이드" -#define D_UPLOAD "업로드" -#define D_UPTIME "가동시간" -#define D_USER "User" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV 색인" -#define D_UV_INDEX_1 "낮음" -#define D_UV_INDEX_2 "보통" -#define D_UV_INDEX_3 "높음" -#define D_UV_INDEX_4 "위험" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" // Out of Range -#define D_UV_LEVEL "UV 레벨" -#define D_UV_POWER "UV 파워" -#define D_VERSION "버전" -#define D_VOLTAGE "전압" -#define D_WEIGHT "무게" -#define D_WARMLIGHT "따뜻하게" -#define D_WEB_SERVER "웹 서버" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "경고: 이 버전은 영구 설정을 지원하지 않습니다" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial log 사용 안함" -#define D_SYSLOG_LOGGING_REENABLED "Syslog log 다시 사용" - -#define D_SET_BAUDRATE_TO "Set Baudrate to" -#define D_RECEIVED_TOPIC "Received Topic" -#define D_DATA_SIZE "데이터 용량" -#define D_ANALOG_INPUT "아날로그" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPS설정 실패" -#define D_ACTIVE_FOR_3_MINUTES "3분동안 활성화" -#define D_FAILED_TO_START "시작 실패" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "AP에 연결 중" -#define D_IN_MODE "in mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP 주소가 수신되지 않아 연결이 실패했습니다" -#define D_CONNECT_FAILED_AP_NOT_REACHED "연결이 닿지 않아 AP에 연결할 수 없습니다" -#define D_CONNECT_FAILED_WRONG_PASSWORD "비밀번호가 틀려 AP에 연결할 수 없습니다" -#define D_CONNECT_FAILED_AP_TIMEOUT "시간초과로 AP에 연결할 수 없습니다" -#define D_ATTEMPTING_CONNECTION "연결 시도 중..." -#define D_CHECKING_CONNECTION "연결 체크 중..." -#define D_QUERY_DONE "쿼리 완료. MQTT 서비스 발견" -#define D_MQTT_SERVICE_FOUND "MQTT 서비스 발견" -#define D_FOUND_AT "다음을 발견" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog 호스트가 발견되지 않았습니다" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "플래시에 저장" -#define D_LOADED_FROM_FLASH_AT "플래시에서 로드" -#define D_USE_DEFAULTS "디폴트 사용" -#define D_ERASED_SECTOR "삭제된 섹터" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" -#define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" -#define D_WITH_IP_ADDRESS "IP 주소" -#define D_WEBSERVER_STOPPED "Web 서버 멈춤" -#define D_FILE_NOT_FOUND "파일을 찾을 수 없습니다" -#define D_REDIRECTED "인증 페이지로 리디렉션" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "와이파이 매니저가 AccessPoint와 keep Station을 설정" -#define D_WIFIMANAGER_SET_ACCESSPOINT "와이파이 매니저가 AccessPoint를 설정" -#define D_TRYING_TO_CONNECT "장치를 네트워크에 연결하려고 시도 중" - -#define D_RESTART_IN "재시작" -#define D_SECONDS "초" -#define D_DEVICE_WILL_RESTART "이 장치는 몇 초 후 재시작됩니다" -#define D_BUTTON_TOGGLE "켜기/끄기" -#define D_CONFIGURATION "설정 메뉴" -#define D_INFORMATION "정보" -#define D_FIRMWARE_UPGRADE "펌웨어 업그레이드" -#define D_CONSOLE "콘솔" -#define D_CONFIRM_RESTART "재시작" - -#define D_CONFIGURE_MODULE "모듈 설정" -#define D_CONFIGURE_WIFI "WiFi 설정" -#define D_CONFIGURE_MQTT "MQTT 설정" -#define D_CONFIGURE_DOMOTICZ "Domoticz 설정" -#define D_CONFIGURE_LOGGING "로그 설정" -#define D_CONFIGURE_OTHER "기타 설정" -#define D_CONFIRM_RESET_CONFIGURATION "설정 초기화 확인" -#define D_RESET_CONFIGURATION "설정 초기화" -#define D_BACKUP_CONFIGURATION "설정 백업" -#define D_RESTORE_CONFIGURATION "설정 복구" -#define D_MAIN_MENU "메인 메뉴" - -#define D_MODULE_PARAMETERS "모듈 설정" -#define D_MODULE_TYPE "모듈 타입" -#define D_PULLUP_ENABLE "버튼 없음/스위치 당김" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Wifi 설정" -#define D_SCAN_FOR_WIFI_NETWORKS "Wifi 네트워크를 검색.." -#define D_SCAN_DONE "검색 완료" -#define D_NO_NETWORKS_FOUND "발견된 네트워크가 없습니다" -#define D_REFRESH_TO_SCAN_AGAIN "검색 재시도" -#define D_DUPLICATE_ACCESSPOINT "중복된 AccessPoint" -#define D_SKIPPING_LOW_QUALITY "약한 네트워크 신호 무시" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 비밀번호" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 비밀번호" - -#define D_MQTT_PARAMETERS "MQTT 설정" -#define D_CLIENT "클라이언트" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "로그 설정" -#define D_SERIAL_LOG_LEVEL "Serial 로그 레벨" -#define D_MQTT_LOG_LEVEL "Mqtt 로그 레벨" -#define D_WEB_LOG_LEVEL "Web 로그 레벨" -#define D_SYS_LOG_LEVEL "시스템로그 레벨" -#define D_MORE_DEBUG "More debug" -#define D_SYSLOG_HOST "시스템로그 호스트" -#define D_SYSLOG_PORT "시스템로그 포트" -#define D_TELEMETRY_PERIOD "보고 주기" - -#define D_OTHER_PARAMETERS "기타 설정" -#define D_TEMPLATE "템플릿" -#define D_ACTIVATE "활성화" -#define D_WEB_ADMIN_PASSWORD "Web Admin 비밀번호" -#define D_MQTT_ENABLE "MQTT 사용" -#define D_FRIENDLY_NAME "Friendly Name" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "단일 장치" -#define D_MULTI_DEVICE "다수 장치" - -#define D_CONFIGURE_TEMPLATE "템플릿 설정" -#define D_TEMPLATE_PARAMETERS "템플릿 설정" -#define D_TEMPLATE_NAME "이름" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "옵션" - -#define D_SAVE_CONFIGURATION "설정 저장" -#define D_CONFIGURATION_SAVED "설정 저장 완료" -#define D_CONFIGURATION_RESET "설정 초기화" - -#define D_PROGRAM_VERSION "프로그램 버전" -#define D_BUILD_DATE_AND_TIME "빌드 날짜" -#define D_CORE_AND_SDK_VERSION "Core/SDK 버전" -#define D_FLASH_WRITE_COUNT "플래시 쓰기 횟수" -#define D_MAC_ADDRESS "MAC 주소" -#define D_MQTT_HOST "MQTT 호스트" -#define D_MQTT_PORT "MQTT 포트" -#define D_MQTT_CLIENT "MQTT 클라이언트" -#define D_MQTT_USER "MQTT 아이디" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP 칩 Id" -#define D_FLASH_CHIP_ID "플래시 칩 Id" -#define D_FLASH_CHIP_SIZE "플래시 용량" -#define D_FREE_PROGRAM_SPACE "여유 프로그램 공간" - -#define D_UPGRADE_BY_WEBSERVER "웹 서버에서 업그레이드" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "업그레이드 시작" -#define D_UPGRADE_BY_FILE_UPLOAD "파일에서 업로드해 업그레이드" -#define D_UPLOAD_STARTED "업로드 시작됨" -#define D_UPGRADE_STARTED "업그레이드 시작됨" -#define D_UPLOAD_DONE "업그레이드 완료" -#define D_UPLOAD_ERR_1 "파일이 선택되지 않았습니다" -#define D_UPLOAD_ERR_2 "용량이 충분하지 않습니다" -#define D_UPLOAD_ERR_3 "Magic 바이트가 0xE9가 아닙니다" -#define D_UPLOAD_ERR_4 "플래시 프로그램이 실제 플래시 용량보다 큽니다" -#define D_UPLOAD_ERR_5 "업로드 버퍼가 일치하지 않습니다" -#define D_UPLOAD_ERR_6 "업로드 실패. 로그 3 사용" -#define D_UPLOAD_ERR_7 "업로드 중단" -#define D_UPLOAD_ERR_8 "파일이 유효하지 않습니다" -#define D_UPLOAD_ERR_9 "용량이 초과되었습니다" -#define D_UPLOAD_ERR_10 "RF 칩 초기화 실패" -#define D_UPLOAD_ERR_11 "RF 칩 삭제 실패" -#define D_UPLOAD_ERR_12 "RF 칩 쓰기 실패" -#define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패" -#define D_UPLOAD_ERROR_CODE "업로드 에러 코드" - -#define D_ENTER_COMMAND "커맨드 입력" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "응답이 있다면 Weblog 2를 사용" -#define D_NEED_USER_AND_PASSWORD "user=<아이디>&password=<비밀번호> 필요" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "TLS 지문 확인..." -#define D_TLS_CONNECT_FAILED_TO "TLS 연결 실패" -#define D_RETRY_IN "재시도 중" -#define D_VERIFIED "지문 확인 완료" -#define D_INSECURE "유효하지 않은 지문으로 연결이 되지 않았습니다" -#define D_CONNECT_FAILED_TO "연결 실패" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast 사용 불가" -#define D_MULTICAST_REJOINED "Multicast (다시)가입됨" -#define D_MULTICAST_JOIN_FAILED "Multicast 가입 실패" -#define D_FAILED_TO_SEND_RESPONSE "요청 전송 실패" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo 기본 이벤트" -#define D_WEMO_EVENT_SERVICE "WeMo 이벤트 서비스" -#define D_WEMO_META_SERVICE "WeMo meta 서비스" -#define D_WEMO_SETUP "WeMo 설정" -#define D_RESPONSE_SENT "요청 전송됨" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue 설정" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API가 포함되지 않음" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 요청 패킷이 전송됨" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz 설정" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "스위치 idx" -#define D_DOMOTICZ_SENSOR_IDX "센서 idx" - #define D_DOMOTICZ_TEMP "온도" - #define D_DOMOTICZ_TEMP_HUM "온도,습도" - #define D_DOMOTICZ_TEMP_HUM_BARO "온도,습도,기압" - #define D_DOMOTICZ_POWER_ENERGY "전력,전력량" - #define D_DOMOTICZ_ILLUMINANCE "조도" - #define D_DOMOTICZ_COUNT "횟수/PM1" - #define D_DOMOTICZ_VOLTAGE "전압/PM2.5" - #define D_DOMOTICZ_CURRENT "전류/PM10" - #define D_DOMOTICZ_AIRQUALITY "공기질" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "타이머 갱신" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "타이머 설정" -#define D_TIMER_PARAMETERS "타이머 설정" -#define D_TIMER_ENABLE "타이머 사용" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "시간" -#define D_TIMER_DAYS "일" -#define D_TIMER_REPEAT "반복" -#define D_TIMER_OUTPUT "출력" -#define D_TIMER_ACTION "행동" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX 설정" -#define D_KNX_PARAMETERS "KNX 설정" -#define D_KNX_GENERAL_CONFIG "일반" -#define D_KNX_PHYSICAL_ADDRESS "물리적 주소" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( KNX 네트워크 상에서 반드시 고유한 이름이어야 합니다 )" -#define D_KNX_ENABLE "KNX 사용" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "그룹 주소로 데이타를 보냅니다" -#define D_ADD "추가" -#define D_DELETE "삭제" -#define D_REPLY "응답" -#define D_KNX_GROUP_ADDRESS_TO_READ "받은 데이터의 그룹 주소" -#define D_RECEIVED_FROM "다음에서 받음" -#define D_KNX_COMMAND_WRITE "쓰기" -#define D_KNX_COMMAND_READ "읽기" -#define D_KNX_COMMAND_OTHER "기타" -#define D_SENT_TO "다음으로 보내기" -#define D_KNX_WARNING "그룹 주소 ( 0 / 0 / 0 )은 예약되어 사용할 수 없습니다" -#define D_KNX_ENHANCEMENT "커뮤니케이션 강화" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "금일 전력 사용량" -#define D_ENERGY_YESTERDAY "어제 전력 사용량" -#define D_ENERGY_TOTAL "총 전력 사용량" - -// xdrv_27_shutter.ino -#define D_OPEN "열기" -#define D_CLOSE "닫기" -#define D_DOMOTICZ_SHUTTER "셔터" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "PCF8574 설정" -#define D_PCF8574_PARAMETERS "PCF8574 파라미터" -#define D_INVERT_PORTS "포트 반전" -#define D_DEVICE "장치" -#define D_DEVICE_INPUT "입력" -#define D_DEVICE_OUTPUT "출력" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "센서가 사용 중" -#define D_SENSOR_CRC_ERROR "센서 CRC 에러" -#define D_SENSORS_FOUND "센서 발견" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "대기 시간 초과" -#define D_START_SIGNAL_LOW "시작 신호 낮음" -#define D_START_SIGNAL_HIGH "시작 신호 높음" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "체크섬 실패" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "센서가 ACK 명령을 수행하지 않음" -#define D_SHT1X_FOUND "SHT1X 발견" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "입자" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "중량 제거" -#define D_HX_CAL_REFERENCE "참조 중량 로드" -#define D_HX_CAL_DONE "교정됨" -#define D_HX_CAL_FAIL "교정 실패" -#define D_RESET_HX711 "스케일 초기화" -#define D_CONFIGURE_HX711 "스케일 설정" -#define D_HX711_PARAMETERS "스케일 상세" -#define D_ITEM_WEIGHT "아이템 중량" -#define D_REFERENCE_WEIGHT "참조 중량" -#define D_CALIBRATE "교정" -#define D_CALIBRATION "교정" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "풍향" -#define D_TX20_WIND_SPEED "풍속" -#define D_TX20_WIND_SPEED_AVG "평균 풍속" -#define D_TX20_WIND_SPEED_MAX "최대 풍속" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "없음" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "시" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "마이크로미터" -#define D_UNIT_MICROSECOND "마이크로초" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "밀리초" -#define D_UNIT_MINUTE "분" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "초" -#define D_UNIT_SECTORS "섹터" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_KO_KO_H_ +/* + ko-KO.h - localization for Korean - Korean for Tasmota + + Copyright (C) 2019 Theo Arends (translated by NyaamZ) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_KO_KO_H_ +#define _LANGUAGE_KO_KO_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.11 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 1042 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "ko" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "일 월 화 수 목 금 토 " +#define D_MONTH3LIST "1월 2월 3월 4월 5월 6월 7월 8월 9월 10월11월12월" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "공기질" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "자동" +#define D_BLINK "깜박임" +#define D_BLINKOFF "깜박임 끄기" +#define D_BOOT_COUNT "부팅 횟수" +#define D_BRIGHTLIGHT "밝게" +#define D_BSSID "BSSId" +#define D_BUTTON "버튼" +#define D_BY "by" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "섭씨" +#define D_CHANNEL "채널" +#define D_CO2 "이산화탄소" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "차갑게" +#define D_COMMAND "커맨드" +#define D_CONNECTED "연결됨" +#define D_COUNT "횟수" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNTER "Counter" +#define D_CURRENT "전류" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "어둡게" +#define D_DEBUG "디버그" +#define D_DISABLED "사용안함" +#define D_DISTANCE "거리" +#define D_DNS_SERVER "DNS 서버" +#define D_DONE "완료" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "에뮬레이션" +#define D_ENABLED "사용" +#define D_ERASE "삭제" +#define D_ERROR "에러" +#define D_FAHRENHEIT "화씨" +#define D_FAILED "실패" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "거짓" +#define D_FILE "파일" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "남은 메모리" +#define D_FREQUENCY "Frequency" +#define D_GAS "가스" +#define D_GATEWAY "게이트웨이" +#define D_GROUP "그룹" +#define D_HOST "호스트" +#define D_HOSTNAME "호스트이름" +#define D_HUMIDITY "습도" +#define D_ILLUMINANCE "조도" +#define D_IMMEDIATE "immediate" // Button immediate +#define D_INDEX "인덱스" +#define D_INFO "정보" +#define D_INFRARED "적외선" +#define D_INITIALIZED "초기화됨" +#define D_IP_ADDRESS "IP 주소" +#define D_LIGHT "밝게" +#define D_LWT "LWT" +#define D_MODULE "모듈" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "소음" +#define D_NONE "없음" +#define D_OFF "꺼짐" +#define D_OFFLINE "오프라인" +#define D_OK "Ok" +#define D_ON "켜짐" +#define D_ONLINE "온라인" +#define D_PASSWORD "비밀번호" +#define D_PORT "포트" +#define D_POWER_FACTOR "Power Factor" +#define D_POWERUSAGE "전원" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "기압" +#define D_PRESSUREATSEALEVEL "해수면기압" +#define D_PROGRAM_FLASH_SIZE "플래시 용량" +#define D_PROGRAM_SIZE "프로그램 용량" +#define D_PROJECT "프로젝트" +#define D_RAIN "비" +#define D_RECEIVED "받음" +#define D_RESTART "재시작" +#define D_RESTARTING "재시작 중.." +#define D_RESTART_REASON "재시작 사유" +#define D_RESTORE "복구" +#define D_RETAINED "보류" +#define D_RULE "규칙" +#define D_SAVE "저장" +#define D_SENSOR "센서" +#define D_SSID "SSId" +#define D_START "시작" +#define D_STD_TIME "STD" +#define D_STOP "정지" +#define D_SUBNET_MASK "서브넷 마스크" +#define D_SUBSCRIBE_TO "구독" +#define D_UNSUBSCRIBE_FROM "구독 해제" +#define D_SUCCESSFUL "성공" +#define D_SUNRISE "일출" +#define D_SUNSET "일몰" +#define D_TEMPERATURE "온도" +#define D_TO "to" +#define D_TOGGLE "켜기/끄기" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "전체 사용량" +#define D_TRANSMIT "전송" +#define D_TRUE "참" +#define D_TVOC "TVOC" +#define D_UPGRADE "업그레이드" +#define D_UPLOAD "업로드" +#define D_UPTIME "가동시간" +#define D_USER "User" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV 색인" +#define D_UV_INDEX_1 "낮음" +#define D_UV_INDEX_2 "보통" +#define D_UV_INDEX_3 "높음" +#define D_UV_INDEX_4 "위험" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range +#define D_UV_LEVEL "UV 레벨" +#define D_UV_POWER "UV 파워" +#define D_VERSION "버전" +#define D_VOLTAGE "전압" +#define D_WEIGHT "무게" +#define D_WARMLIGHT "따뜻하게" +#define D_WEB_SERVER "웹 서버" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "경고: 이 버전은 영구 설정을 지원하지 않습니다" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial log 사용 안함" +#define D_SYSLOG_LOGGING_REENABLED "Syslog log 다시 사용" + +#define D_SET_BAUDRATE_TO "Set Baudrate to" +#define D_RECEIVED_TOPIC "Received Topic" +#define D_DATA_SIZE "데이터 용량" +#define D_ANALOG_INPUT "아날로그" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPS설정 실패" +#define D_ACTIVE_FOR_3_MINUTES "3분동안 활성화" +#define D_FAILED_TO_START "시작 실패" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "AP에 연결 중" +#define D_IN_MODE "in mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP 주소가 수신되지 않아 연결이 실패했습니다" +#define D_CONNECT_FAILED_AP_NOT_REACHED "연결이 닿지 않아 AP에 연결할 수 없습니다" +#define D_CONNECT_FAILED_WRONG_PASSWORD "비밀번호가 틀려 AP에 연결할 수 없습니다" +#define D_CONNECT_FAILED_AP_TIMEOUT "시간초과로 AP에 연결할 수 없습니다" +#define D_ATTEMPTING_CONNECTION "연결 시도 중..." +#define D_CHECKING_CONNECTION "연결 체크 중..." +#define D_QUERY_DONE "쿼리 완료. MQTT 서비스 발견" +#define D_MQTT_SERVICE_FOUND "MQTT 서비스 발견" +#define D_FOUND_AT "다음을 발견" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog 호스트가 발견되지 않았습니다" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "플래시에 저장" +#define D_LOADED_FROM_FLASH_AT "플래시에서 로드" +#define D_USE_DEFAULTS "디폴트 사용" +#define D_ERASED_SECTOR "삭제된 섹터" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" +#define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" +#define D_WITH_IP_ADDRESS "IP 주소" +#define D_WEBSERVER_STOPPED "Web 서버 멈춤" +#define D_FILE_NOT_FOUND "파일을 찾을 수 없습니다" +#define D_REDIRECTED "인증 페이지로 리디렉션" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "와이파이 매니저가 AccessPoint와 keep Station을 설정" +#define D_WIFIMANAGER_SET_ACCESSPOINT "와이파이 매니저가 AccessPoint를 설정" +#define D_TRYING_TO_CONNECT "장치를 네트워크에 연결하려고 시도 중" + +#define D_RESTART_IN "재시작" +#define D_SECONDS "초" +#define D_DEVICE_WILL_RESTART "이 장치는 몇 초 후 재시작됩니다" +#define D_BUTTON_TOGGLE "켜기/끄기" +#define D_CONFIGURATION "설정 메뉴" +#define D_INFORMATION "정보" +#define D_FIRMWARE_UPGRADE "펌웨어 업그레이드" +#define D_CONSOLE "콘솔" +#define D_CONFIRM_RESTART "재시작" + +#define D_CONFIGURE_MODULE "모듈 설정" +#define D_CONFIGURE_WIFI "WiFi 설정" +#define D_CONFIGURE_MQTT "MQTT 설정" +#define D_CONFIGURE_DOMOTICZ "Domoticz 설정" +#define D_CONFIGURE_LOGGING "로그 설정" +#define D_CONFIGURE_OTHER "기타 설정" +#define D_CONFIRM_RESET_CONFIGURATION "설정 초기화 확인" +#define D_RESET_CONFIGURATION "설정 초기화" +#define D_BACKUP_CONFIGURATION "설정 백업" +#define D_RESTORE_CONFIGURATION "설정 복구" +#define D_MAIN_MENU "메인 메뉴" + +#define D_MODULE_PARAMETERS "모듈 설정" +#define D_MODULE_TYPE "모듈 타입" +#define D_PULLUP_ENABLE "버튼 없음/스위치 당김" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Wifi 설정" +#define D_SCAN_FOR_WIFI_NETWORKS "Wifi 네트워크를 검색.." +#define D_SCAN_DONE "검색 완료" +#define D_NO_NETWORKS_FOUND "발견된 네트워크가 없습니다" +#define D_REFRESH_TO_SCAN_AGAIN "검색 재시도" +#define D_DUPLICATE_ACCESSPOINT "중복된 AccessPoint" +#define D_SKIPPING_LOW_QUALITY "약한 네트워크 신호 무시" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 비밀번호" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 비밀번호" + +#define D_MQTT_PARAMETERS "MQTT 설정" +#define D_CLIENT "클라이언트" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "로그 설정" +#define D_SERIAL_LOG_LEVEL "Serial 로그 레벨" +#define D_MQTT_LOG_LEVEL "Mqtt 로그 레벨" +#define D_WEB_LOG_LEVEL "Web 로그 레벨" +#define D_SYS_LOG_LEVEL "시스템로그 레벨" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "시스템로그 호스트" +#define D_SYSLOG_PORT "시스템로그 포트" +#define D_TELEMETRY_PERIOD "보고 주기" + +#define D_OTHER_PARAMETERS "기타 설정" +#define D_TEMPLATE "템플릿" +#define D_ACTIVATE "활성화" +#define D_WEB_ADMIN_PASSWORD "Web Admin 비밀번호" +#define D_MQTT_ENABLE "MQTT 사용" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "단일 장치" +#define D_MULTI_DEVICE "다수 장치" + +#define D_CONFIGURE_TEMPLATE "템플릿 설정" +#define D_TEMPLATE_PARAMETERS "템플릿 설정" +#define D_TEMPLATE_NAME "이름" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "옵션" + +#define D_SAVE_CONFIGURATION "설정 저장" +#define D_CONFIGURATION_SAVED "설정 저장 완료" +#define D_CONFIGURATION_RESET "설정 초기화" + +#define D_PROGRAM_VERSION "프로그램 버전" +#define D_BUILD_DATE_AND_TIME "빌드 날짜" +#define D_CORE_AND_SDK_VERSION "Core/SDK 버전" +#define D_FLASH_WRITE_COUNT "플래시 쓰기 횟수" +#define D_MAC_ADDRESS "MAC 주소" +#define D_MQTT_HOST "MQTT 호스트" +#define D_MQTT_PORT "MQTT 포트" +#define D_MQTT_CLIENT "MQTT 클라이언트" +#define D_MQTT_USER "MQTT 아이디" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP 칩 Id" +#define D_FLASH_CHIP_ID "플래시 칩 Id" +#define D_FLASH_CHIP_SIZE "플래시 용량" +#define D_FREE_PROGRAM_SPACE "여유 프로그램 공간" + +#define D_UPGRADE_BY_WEBSERVER "웹 서버에서 업그레이드" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "업그레이드 시작" +#define D_UPGRADE_BY_FILE_UPLOAD "파일에서 업로드해 업그레이드" +#define D_UPLOAD_STARTED "업로드 시작됨" +#define D_UPGRADE_STARTED "업그레이드 시작됨" +#define D_UPLOAD_DONE "업그레이드 완료" +#define D_UPLOAD_ERR_1 "파일이 선택되지 않았습니다" +#define D_UPLOAD_ERR_2 "용량이 충분하지 않습니다" +#define D_UPLOAD_ERR_3 "Magic 바이트가 0xE9가 아닙니다" +#define D_UPLOAD_ERR_4 "플래시 프로그램이 실제 플래시 용량보다 큽니다" +#define D_UPLOAD_ERR_5 "업로드 버퍼가 일치하지 않습니다" +#define D_UPLOAD_ERR_6 "업로드 실패. 로그 3 사용" +#define D_UPLOAD_ERR_7 "업로드 중단" +#define D_UPLOAD_ERR_8 "파일이 유효하지 않습니다" +#define D_UPLOAD_ERR_9 "용량이 초과되었습니다" +#define D_UPLOAD_ERR_10 "RF 칩 초기화 실패" +#define D_UPLOAD_ERR_11 "RF 칩 삭제 실패" +#define D_UPLOAD_ERR_12 "RF 칩 쓰기 실패" +#define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패" +#define D_UPLOAD_ERROR_CODE "업로드 에러 코드" + +#define D_ENTER_COMMAND "커맨드 입력" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "응답이 있다면 Weblog 2를 사용" +#define D_NEED_USER_AND_PASSWORD "user=<아이디>&password=<비밀번호> 필요" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "TLS 지문 확인..." +#define D_TLS_CONNECT_FAILED_TO "TLS 연결 실패" +#define D_RETRY_IN "재시도 중" +#define D_VERIFIED "지문 확인 완료" +#define D_INSECURE "유효하지 않은 지문으로 연결이 되지 않았습니다" +#define D_CONNECT_FAILED_TO "연결 실패" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast 사용 불가" +#define D_MULTICAST_REJOINED "Multicast (다시)가입됨" +#define D_MULTICAST_JOIN_FAILED "Multicast 가입 실패" +#define D_FAILED_TO_SEND_RESPONSE "요청 전송 실패" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo 기본 이벤트" +#define D_WEMO_EVENT_SERVICE "WeMo 이벤트 서비스" +#define D_WEMO_META_SERVICE "WeMo meta 서비스" +#define D_WEMO_SETUP "WeMo 설정" +#define D_RESPONSE_SENT "요청 전송됨" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue 설정" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API가 포함되지 않음" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 요청 패킷이 전송됨" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz 설정" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "스위치 idx" +#define D_DOMOTICZ_SENSOR_IDX "센서 idx" + #define D_DOMOTICZ_TEMP "온도" + #define D_DOMOTICZ_TEMP_HUM "온도,습도" + #define D_DOMOTICZ_TEMP_HUM_BARO "온도,습도,기압" + #define D_DOMOTICZ_POWER_ENERGY "전력,전력량" + #define D_DOMOTICZ_ILLUMINANCE "조도" + #define D_DOMOTICZ_COUNT "횟수/PM1" + #define D_DOMOTICZ_VOLTAGE "전압/PM2.5" + #define D_DOMOTICZ_CURRENT "전류/PM10" + #define D_DOMOTICZ_AIRQUALITY "공기질" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "타이머 갱신" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "타이머 설정" +#define D_TIMER_PARAMETERS "타이머 설정" +#define D_TIMER_ENABLE "타이머 사용" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "시간" +#define D_TIMER_DAYS "일" +#define D_TIMER_REPEAT "반복" +#define D_TIMER_OUTPUT "출력" +#define D_TIMER_ACTION "행동" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX 설정" +#define D_KNX_PARAMETERS "KNX 설정" +#define D_KNX_GENERAL_CONFIG "일반" +#define D_KNX_PHYSICAL_ADDRESS "물리적 주소" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( KNX 네트워크 상에서 반드시 고유한 이름이어야 합니다 )" +#define D_KNX_ENABLE "KNX 사용" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "그룹 주소로 데이타를 보냅니다" +#define D_ADD "추가" +#define D_DELETE "삭제" +#define D_REPLY "응답" +#define D_KNX_GROUP_ADDRESS_TO_READ "받은 데이터의 그룹 주소" +#define D_RECEIVED_FROM "다음에서 받음" +#define D_KNX_COMMAND_WRITE "쓰기" +#define D_KNX_COMMAND_READ "읽기" +#define D_KNX_COMMAND_OTHER "기타" +#define D_SENT_TO "다음으로 보내기" +#define D_KNX_WARNING "그룹 주소 ( 0 / 0 / 0 )은 예약되어 사용할 수 없습니다" +#define D_KNX_ENHANCEMENT "커뮤니케이션 강화" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "금일 전력 사용량" +#define D_ENERGY_YESTERDAY "어제 전력 사용량" +#define D_ENERGY_TOTAL "총 전력 사용량" + +// xdrv_27_shutter.ino +#define D_OPEN "열기" +#define D_CLOSE "닫기" +#define D_DOMOTICZ_SHUTTER "셔터" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "PCF8574 설정" +#define D_PCF8574_PARAMETERS "PCF8574 파라미터" +#define D_INVERT_PORTS "포트 반전" +#define D_DEVICE "장치" +#define D_DEVICE_INPUT "입력" +#define D_DEVICE_OUTPUT "출력" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "센서가 사용 중" +#define D_SENSOR_CRC_ERROR "센서 CRC 에러" +#define D_SENSORS_FOUND "센서 발견" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "대기 시간 초과" +#define D_START_SIGNAL_LOW "시작 신호 낮음" +#define D_START_SIGNAL_HIGH "시작 신호 높음" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "체크섬 실패" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "센서가 ACK 명령을 수행하지 않음" +#define D_SHT1X_FOUND "SHT1X 발견" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "입자" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "중량 제거" +#define D_HX_CAL_REFERENCE "참조 중량 로드" +#define D_HX_CAL_DONE "교정됨" +#define D_HX_CAL_FAIL "교정 실패" +#define D_RESET_HX711 "스케일 초기화" +#define D_CONFIGURE_HX711 "스케일 설정" +#define D_HX711_PARAMETERS "스케일 상세" +#define D_ITEM_WEIGHT "아이템 중량" +#define D_REFERENCE_WEIGHT "참조 중량" +#define D_CALIBRATE "교정" +#define D_CALIBRATION "교정" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "풍향" +#define D_TX20_WIND_SPEED "풍속" +#define D_TX20_WIND_SPEED_AVG "평균 풍속" +#define D_TX20_WIND_SPEED_MAX "최대 풍속" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "없음" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "시" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "마이크로미터" +#define D_UNIT_MICROSECOND "마이크로초" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "밀리초" +#define D_UNIT_MINUTE "분" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "초" +#define D_UNIT_SECTORS "섹터" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_KO_KO_H_ diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 75d841ddc..cd1414f8f 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -1,701 +1,703 @@ -/* - nl-NL.h - localization for Dutch - Nederland for Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_NL_NL_H_ -#define _LANGUAGE_NL_NL_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.7.0 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1043 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "nl" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "Zo Ma Di Wo Do Vr Za " -#define D_MONTH3LIST "JanFebMarAprMeiJunJulAugSepOktNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Lucht kwaliteit" -#define D_AP "AP" // Access Point -#define D_AS "als" -#define D_AUTO "AUTO" -#define D_BLINK "Knipper" -#define D_BLINKOFF "KnipperUit" -#define D_BOOT_COUNT "Herstarts" -#define D_BRIGHTLIGHT "Fel" -#define D_BSSID "BSSId" -#define D_BUTTON "DrukKnop" -#define D_BY "door" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Kanaal" -#define D_CO2 "Koolstofdioxide" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "Koud" -#define D_COMMAND "Opdracht" -#define D_CONNECTED "Verbonden" -#define D_COUNT "Aantal" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNTER "Teller" -#define D_CURRENT "Stroom" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Donker" -#define D_DEBUG "Debug" -#define D_DISABLED "Uitgeschakeld" -#define D_DISTANCE "Afstand" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Klaar" -#define D_DST_TIME "ZT" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulatie" -#define D_ENABLED "Geactiveerd" -#define D_ERASE "Wissen" -#define D_ERROR "Fout" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Mislukt" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "Onwaar" -#define D_FILE "Bestand" -#define D_FLOW_RATE "Debiet" -#define D_FREE_MEMORY "Vrij geheugen" -#define D_FREQUENCY "Frequentie" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Groep" -#define D_HOST "Host" -#define D_HOSTNAME "Hostnaam" -#define D_HUMIDITY "Luchtvochtigheid" -#define D_ILLUMINANCE "Verlichtingssterkte" -#define D_IMMEDIATE "onmiddelijk" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infrarood" -#define D_INITIALIZED "Geinitialiseerd" -#define D_IP_ADDRESS "IP Adres" -#define D_LIGHT "Licht" -#define D_LWT "LWT" -#define D_MODULE "Module" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "meervoudig" -#define D_NOISE "Lawaai" -#define D_NONE "Geen" -#define D_OFF "Uit" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "Aan" -#define D_ONLINE "Online" -#define D_PASSWORD "Wachtwoord" -#define D_PORT "Poort" -#define D_POWER_FACTOR "Arbeidsfactor" -#define D_POWERUSAGE "Vermogen" -#define D_POWERUSAGE_ACTIVE "Werkelijk vermogen" -#define D_POWERUSAGE_APPARENT "Schijnbaar vermogen" -#define D_POWERUSAGE_REACTIVE "Blindvermogen" -#define D_PRESSURE "Luchtdruk" -#define D_PRESSUREATSEALEVEL "ZeeLuchtdruk" -#define D_PROGRAM_FLASH_SIZE "Programma Flash Grootte" -#define D_PROGRAM_SIZE "Programma Grootte" -#define D_PROJECT "Project" -#define D_RAIN "Regen" -#define D_RECEIVED "Ontvangen" -#define D_RESTART "Herstart" -#define D_RESTARTING "Herstarten" -#define D_RESTART_REASON "Reden herstart" -#define D_RESTORE "herstellen" -#define D_RETAINED "retained" -#define D_RULE "Regel" -#define D_SAVE "Opslaan" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Start" -#define D_STD_TIME "WT" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Subnet Masker" -#define D_SUBSCRIBE_TO "Abonneer op" -#define D_UNSUBSCRIBE_FROM "Uitschrijven van" -#define D_SUCCESSFUL "Gelukt" -#define D_SUNRISE "Zonsopgang" -#define D_SUNSET "Zonsondergang" -#define D_TEMPERATURE "Temperatuur" -#define D_TO "naar" -#define D_TOGGLE "Toggle" // Wissel, Tuimel -#define D_TOPIC "Topic" // Onderwerp -#define D_TOTAL_USAGE "Totaal verbruik" -#define D_TRANSMIT "Verzend" -#define D_TRUE "Waar" -#define D_TVOC "TVOC" -#define D_UPGRADE "opwaarderen" -#define D_UPLOAD "Verzenden" -#define D_UPTIME "Bedrijfstijd" -#define D_USER "Gebruiker" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV-index" -#define D_UV_INDEX_1 "Laag" -#define D_UV_INDEX_2 "Gemiddeld" -#define D_UV_INDEX_3 "Hoog" -#define D_UV_INDEX_4 "Intens" -#define D_UV_INDEX_5 "Gevaarlijk" -#define D_UV_INDEX_6 "Schadelijk" -#define D_UV_INDEX_7 "Uitzonderlijk" -#define D_UV_LEVEL "UV niveau" -#define D_UV_POWER "UV intensiteit" -#define D_VERSION "Versie" -#define D_VOLTAGE "Spanning" -#define D_WEIGHT "Gewicht" -#define D_WARMLIGHT "Warm" -#define D_WEB_SERVER "Webserver" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "WAARSCHUWING Deze versie bewaart geen instellingen" -#define D_LEVEL_10 "niveau 1-0" -#define D_LEVEL_01 "niveau 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serieel logging uitgeschakeld" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logging weer ingeschakeld" - -#define D_SET_BAUDRATE_TO "Zet baudrate op" -#define D_RECEIVED_TOPIC "Ontvangen topic" -#define D_DATA_SIZE "Data lengte" -#define D_ANALOG_INPUT "Analoog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig mislukt met status" -#define D_ACTIVE_FOR_3_MINUTES "3 minuten actief" -#define D_FAILED_TO_START "mislukt" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Verbinden met AP" -#define D_IN_MODE "in stand" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbinding mislukt omdat geen IP adres werd ontvangen" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbinding mislukt omdat AP onbereikbaar is" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbinding mislukt door fout wachtwoord" -#define D_CONNECT_FAILED_AP_TIMEOUT "Verbinding mislukt door AP time-out" -#define D_ATTEMPTING_CONNECTION "Verbinden..." -#define D_CHECKING_CONNECTION "Controleer verbinding..." -#define D_QUERY_DONE "Aanvraag klaar. Aantal MQTT diensten gevonden" -#define D_MQTT_SERVICE_FOUND "MQTT dienst gevonden op" -#define D_FOUND_AT "gevonden op" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host niet gevonden" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Opgeslagen in flash op" -#define D_LOADED_FROM_FLASH_AT "Geladen vanuit flash op" -#define D_USE_DEFAULTS "Gebruik standaardwaarden" -#define D_ERASED_SECTOR "Wis sector" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Zet JavaScript aan voor Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
opwaarderen" -#define D_WEBSERVER_ACTIVE_ON "Webserver actief op" -#define D_WITH_IP_ADDRESS "met IP adres" -#define D_WEBSERVER_STOPPED "Webserver gestopt" -#define D_FILE_NOT_FOUND "Bestand niet gevonden" -#define D_REDIRECTED "Omleiding naar captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager start AccessPoint en hou Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager start AccessPoint" -#define D_TRYING_TO_CONNECT "Apparaat probeert te verbinden met netwerk" - -#define D_RESTART_IN "Herstart over" -#define D_SECONDS "seconden" -#define D_DEVICE_WILL_RESTART "Herstart over enkele seconden" -#define D_BUTTON_TOGGLE "Toggle" // Wissel, Tuimel -#define D_CONFIGURATION "Configuratie" -#define D_INFORMATION "Informatie" -#define D_FIRMWARE_UPGRADE "Opwaarderen" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Bevestig herstart" - -#define D_CONFIGURE_MODULE "Configureer Module" -#define D_CONFIGURE_WIFI "Configureer WiFi" -#define D_CONFIGURE_MQTT "Configureer MQTT" -#define D_CONFIGURE_DOMOTICZ "Configureer Domoticz" -#define D_CONFIGURE_LOGGING "Configureer Logging" -#define D_CONFIGURE_OTHER "Configureer Overige" -#define D_CONFIRM_RESET_CONFIGURATION "Bevestig reset configuratie" -#define D_RESET_CONFIGURATION "Reset Configuratie" -#define D_BACKUP_CONFIGURATION "Bewaar Configuratie" -#define D_RESTORE_CONFIGURATION "Herstel Configuration" -#define D_MAIN_MENU "Hoofdmenu" - -#define D_MODULE_PARAMETERS "Module parameters" -#define D_MODULE_TYPE "Module soort" -#define D_PULLUP_ENABLE "Geen schakelaar pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serieel In" -#define D_SERIAL_OUT "Serieel Uit" - -#define D_WIFI_PARAMETERS "Wifi parameters" -#define D_SCAN_FOR_WIFI_NETWORKS "Zoek wifi netwerken" -#define D_SCAN_DONE "Scan klaar" -#define D_NO_NETWORKS_FOUND "Geen netwerken gevonden" -#define D_REFRESH_TO_SCAN_AGAIN "Vernieuw om opnieuw te zoeken" -#define D_DUPLICATE_ACCESSPOINT "Dubbel AccessPoint" -#define D_SKIPPING_LOW_QUALITY "Overslaan agv lage ontvangskwaliteit" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Wachtwoord" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Wachtwoord" - -#define D_MQTT_PARAMETERS "MQTT parameters" -#define D_CLIENT "Client" -#define D_FULL_TOPIC "Volledig Topic" - -#define D_LOGGING_PARAMETERS "Logging parameters" -#define D_SERIAL_LOG_LEVEL "Serieel log niveau" -#define D_MQTT_LOG_LEVEL "Mqtt log niveau" -#define D_WEB_LOG_LEVEL "Web log niveau" -#define D_SYS_LOG_LEVEL "Syslog niveau" -#define D_MORE_DEBUG "Meer debug" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog poort" -#define D_TELEMETRY_PERIOD "Telemetry periode" - -#define D_OTHER_PARAMETERS "Overige parameters" -#define D_TEMPLATE "Sjabloon" -#define D_ACTIVATE "Activeer" -#define D_WEB_ADMIN_PASSWORD "Web Admin Wachtwoord" -#define D_MQTT_ENABLE "MQTT ingeschakeld" -#define D_FRIENDLY_NAME "Beschrijvende naam" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "een apparaat" -#define D_MULTI_DEVICE "meer apparaten" - -#define D_CONFIGURE_TEMPLATE "Configureer Sjabloon" -#define D_TEMPLATE_PARAMETERS "Sjabloon parameters" -#define D_TEMPLATE_NAME "Naam" -#define D_BASE_TYPE "Op basis van" -#define D_TEMPLATE_FLAGS "Opties" - -#define D_SAVE_CONFIGURATION "Bewaar configuratie" -#define D_CONFIGURATION_SAVED "Configuratie opgeslagen" -#define D_CONFIGURATION_RESET "Configuratie ge-reset" - -#define D_PROGRAM_VERSION "Programma Versie" -#define D_BUILD_DATE_AND_TIME "Compileer Datum & Tijd" -#define D_CORE_AND_SDK_VERSION "Core/SDK Versie" -#define D_FLASH_WRITE_COUNT "Aantal Flash opslagen" -#define D_MAC_ADDRESS "MAC Adres" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Poort" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT Gebruiker" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Groep Topic" -#define D_MQTT_FULL_TOPIC "MQTT Volledig Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Grootte" -#define D_FREE_PROGRAM_SPACE "Programma ruimte over" - -#define D_UPGRADE_BY_WEBSERVER "Opwaarderen dmv webserver" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Start opwaarderen" -#define D_UPGRADE_BY_FILE_UPLOAD "Opwaarderen dmv verzenden bestand" -#define D_UPLOAD_STARTED "Verzending gestart" -#define D_UPGRADE_STARTED "Opwaarderen gestart" -#define D_UPLOAD_DONE "Opwaarderen klaar" -#define D_UPLOAD_ERR_1 "Geen bestand gekozen" -#define D_UPLOAD_ERR_2 "Onvoldoende geheugen ruimte" -#define D_UPLOAD_ERR_3 "Magische byte is niet 0xE9" -#define D_UPLOAD_ERR_4 "Programma flash grootte is groter dan werkelijke flash grootte" -#define D_UPLOAD_ERR_5 "Opwaardeer buffer verschil" -#define D_UPLOAD_ERR_6 "Opwaarderen mislukt. Schakel logging 3 in" -#define D_UPLOAD_ERR_7 "Opwaarderen afgebroken" -#define D_UPLOAD_ERR_8 "Ongeldig bestand" -#define D_UPLOAD_ERR_9 "Bestand is te groot" -#define D_UPLOAD_ERR_10 "Init RF chip mislukt" -#define D_UPLOAD_ERR_11 "Wissen RF chip mislukt" -#define D_UPLOAD_ERR_12 "Opwaarderen RF chip mislukt" -#define D_UPLOAD_ERR_13 "Decoderen RF bestand mislukt" -#define D_UPLOAD_ERROR_CODE "Opwaardeer foutcode" - -#define D_ENTER_COMMAND "Geef opdracht" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Schakel weblog 2 in indien antwoord verwacht" -#define D_NEED_USER_AND_PASSWORD "Benodig user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Controleer TLS vingerafdruk..." -#define D_TLS_CONNECT_FAILED_TO "TLS Verbinding mislukt naar" -#define D_RETRY_IN "Opnieuw proberen over" -#define D_VERIFIED "Gecontroleerd met vingerafdruk" -#define D_INSECURE "Door ongeldige vingerafdruk een onveilige verbinding" -#define D_CONNECT_FAILED_TO "Verbinding mislukt naar" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast uitgeschakeld" -#define D_MULTICAST_REJOINED "Multicast verbonden" -#define D_MULTICAST_JOIN_FAILED "Multicast verbinding mislukt" -#define D_FAILED_TO_SEND_RESPONSE "Antwoord versturen mislukt" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basis gebeurtenis" -#define D_WEMO_EVENT_SERVICE "WeMo gebeurtenis dienst" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo installatie" -#define D_RESPONSE_SENT "Antwoord verstuurd" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue installatie" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API niet beschikbaar" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argumenten" -#define D_3_RESPONSE_PACKETS_SENT "3 antwoord paketten verstuurd" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Toets idx" -#define D_DOMOTICZ_SWITCH_IDX "Schakelaar idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Spanning/PM2,5" - #define D_DOMOTICZ_CURRENT "Stroom/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Bijwerk timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configureer Tijdschakelaar" -#define D_TIMER_PARAMETERS "Tijdschakelaar parameters" -#define D_TIMER_ENABLE "Tijdschakelaars inschakelen" -#define D_TIMER_ARM "Actief" -#define D_TIMER_TIME "Tijd" -#define D_TIMER_DAYS "Dagen" -#define D_TIMER_REPEAT "Herhaal" -#define D_TIMER_OUTPUT "Uitgang" -#define D_TIMER_ACTION "Actie" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configureer KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "Algemeen" -#define D_KNX_PHYSICAL_ADDRESS "Eigen adres" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Moet uniek zijn op het KNX netwerk)" -#define D_KNX_ENABLE "KNX inschakelen" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Stuur gegevens naar groep adressen" -#define D_ADD "Toevoegen" -#define D_DELETE "Verwijder" -#define D_REPLY "Antwoord" -#define D_KNX_GROUP_ADDRESS_TO_READ "Ontvang gegevens van groep adressen" -#define D_RECEIVED_FROM "Ontvangen van" -#define D_KNX_COMMAND_WRITE "Schrijven" -#define D_KNX_COMMAND_READ "Lezen" -#define D_KNX_COMMAND_OTHER "Overige" -#define D_SENT_TO "verzend naar" -#define D_KNX_WARNING "Groep adres (0/0/0) is gereserveerd en mag niet worden gebruikt." -#define D_KNX_ENHANCEMENT "Verbeter verbinding" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Verbruik vandaag" -#define D_ENERGY_YESTERDAY "Verbruik gisteren" -#define D_ENERGY_TOTAL "Verbruik totaal" - -// xdrv_27_shutter.ino -#define D_OPEN "Openen" -#define D_CLOSE "Sluiten" -#define D_DOMOTICZ_SHUTTER "Rolluik" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configureer PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 Parameters" -#define D_INVERT_PORTS "Inverteer Poorten" -#define D_DEVICE "Apparaat" -#define D_DEVICE_INPUT "Ingang" -#define D_DEVICE_OUTPUT "Uitgang" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor bezet" -#define D_SENSOR_CRC_ERROR "Sensor CRC fout" -#define D_SENSORS_FOUND "Aantal sensoren" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Te lang wachten op" -#define D_START_SIGNAL_LOW "laag start signaal" -#define D_START_SIGNAL_HIGH "hoog start signaal" -#define D_PULSE "signaal" -#define D_CHECKSUM_FAILURE "Controle mislukt" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Geen opdracht ACK van sensor" -#define D_SHT1X_FOUND "SHT1X gevonden" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Stofdeeltjes" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Verwijder gewicht" -#define D_HX_CAL_REFERENCE "Plaats ijkgewicht" -#define D_HX_CAL_DONE "Ge-ijkt" -#define D_HX_CAL_FAIL "Ijken is mislukt" -#define D_RESET_HX711 "Nulstelling weegschaal" -#define D_CONFIGURE_HX711 "Configureer Weegschaal" -#define D_HX711_PARAMETERS "Weegschaal parameters" -#define D_ITEM_WEIGHT "Gewicht van onderdeel" -#define D_REFERENCE_WEIGHT "Ijkgewicht" -#define D_CALIBRATE "Ijken" -#define D_CALIBRATION "Ijken" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Windrichting" -#define D_TX20_WIND_SPEED "Windsnelheid" -#define D_TX20_WIND_SPEED_AVG "Windsnelheid gemiddeld" -#define D_TX20_WIND_SPEED_MAX "Windsnelhied maximaal" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Geen" -#define D_SENSOR_USER "Gebruiker" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Speler" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relais" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Teller" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Zoemer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kΩ" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectoren" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Fase hoek" -#define D_IMPORT_ACTIVE "Import werkelijk" -#define D_EXPORT_ACTIVE "Export werkelijk" -#define D_IMPORT_REACTIVE "Import blind" -#define D_EXPORT_REACTIVE "Export blind" -#define D_TOTAL_REACTIVE "Totaal blind" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 spanning" -#define D_PV1_CURRENT "PV1 stroom" -#define D_PV1_POWER "PV1 vermogen" -#define D_PV2_VOLTAGE "PV2 spanning" -#define D_PV2_CURRENT "PV2 stroom" -#define D_PV2_POWER "PV2 vermogen" -#define D_SOLAR_POWER "Zon vermogen" -#define D_INVERTER_POWER "Omvormer vermogen" -#define D_STATUS "Status" -#define D_WAITING "Wacht" -#define D_CHECKING "Controle" -#define D_WORKING "Actief" -#define D_FAILURE "Fout" -#define D_SOLAX_ERROR_0 "Geen" -#define D_SOLAX_ERROR_1 "Netverbinding" -#define D_SOLAX_ERROR_2 "Netspanning" -#define D_SOLAX_ERROR_3 "Netfrequentie" -#define D_SOLAX_ERROR_4 "Pv spanning" -#define D_SOLAX_ERROR_5 "Isolatie" -#define D_SOLAX_ERROR_6 "Overtemperatuur" -#define D_SOLAX_ERROR_7 "Ventilator" -#define D_SOLAX_ERROR_8 "Overige" - -#endif // _LANGUAGE_NL_NL_H_ +/* + nl-NL.h - localization for Dutch - Nederland for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_NL_NL_H_ +#define _LANGUAGE_NL_NL_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.7.0 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1043 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "nl" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "Zo Ma Di Wo Do Vr Za " +#define D_MONTH3LIST "JanFebMarAprMeiJunJulAugSepOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Lucht kwaliteit" +#define D_AP "AP" // Access Point +#define D_AS "als" +#define D_AUTO "AUTO" +#define D_BLINK "Knipper" +#define D_BLINKOFF "KnipperUit" +#define D_BOOT_COUNT "Herstarts" +#define D_BRIGHTLIGHT "Fel" +#define D_BSSID "BSSId" +#define D_BUTTON "DrukKnop" +#define D_BY "door" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanaal" +#define D_CO2 "Koolstofdioxide" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "Koud" +#define D_COMMAND "Opdracht" +#define D_CONNECTED "Verbonden" +#define D_COUNT "Aantal" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNTER "Teller" +#define D_CURRENT "Stroom" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Donker" +#define D_DEBUG "Debug" +#define D_DISABLED "Uitgeschakeld" +#define D_DISTANCE "Afstand" +#define D_DNS_SERVER "DNS Server" +#define D_DONE "Klaar" +#define D_DST_TIME "ZT" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulatie" +#define D_ENABLED "Geactiveerd" +#define D_ERASE "Wissen" +#define D_ERROR "Fout" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Mislukt" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "Onwaar" +#define D_FILE "Bestand" +#define D_FLOW_RATE "Debiet" +#define D_FREE_MEMORY "Vrij geheugen" +#define D_FREQUENCY "Frequentie" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Groep" +#define D_HOST "Host" +#define D_HOSTNAME "Hostnaam" +#define D_HUMIDITY "Luchtvochtigheid" +#define D_ILLUMINANCE "Verlichtingssterkte" +#define D_IMMEDIATE "onmiddelijk" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infrarood" +#define D_INITIALIZED "Geinitialiseerd" +#define D_IP_ADDRESS "IP Adres" +#define D_LIGHT "Licht" +#define D_LWT "LWT" +#define D_MODULE "Module" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "meervoudig" +#define D_NOISE "Lawaai" +#define D_NONE "Geen" +#define D_OFF "Uit" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "Aan" +#define D_ONLINE "Online" +#define D_PASSWORD "Wachtwoord" +#define D_PORT "Poort" +#define D_POWER_FACTOR "Arbeidsfactor" +#define D_POWERUSAGE "Vermogen" +#define D_POWERUSAGE_ACTIVE "Werkelijk vermogen" +#define D_POWERUSAGE_APPARENT "Schijnbaar vermogen" +#define D_POWERUSAGE_REACTIVE "Blindvermogen" +#define D_PRESSURE "Luchtdruk" +#define D_PRESSUREATSEALEVEL "ZeeLuchtdruk" +#define D_PROGRAM_FLASH_SIZE "Programma Flash Grootte" +#define D_PROGRAM_SIZE "Programma Grootte" +#define D_PROJECT "Project" +#define D_RAIN "Regen" +#define D_RECEIVED "Ontvangen" +#define D_RESTART "Herstart" +#define D_RESTARTING "Herstarten" +#define D_RESTART_REASON "Reden herstart" +#define D_RESTORE "herstellen" +#define D_RETAINED "retained" +#define D_RULE "Regel" +#define D_SAVE "Opslaan" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Start" +#define D_STD_TIME "WT" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Subnet Masker" +#define D_SUBSCRIBE_TO "Abonneer op" +#define D_UNSUBSCRIBE_FROM "Uitschrijven van" +#define D_SUCCESSFUL "Gelukt" +#define D_SUNRISE "Zonsopgang" +#define D_SUNSET "Zonsondergang" +#define D_TEMPERATURE "Temperatuur" +#define D_TO "naar" +#define D_TOGGLE "Toggle" // Wissel, Tuimel +#define D_TOPIC "Topic" // Onderwerp +#define D_TOTAL_USAGE "Totaal verbruik" +#define D_TRANSMIT "Verzend" +#define D_TRUE "Waar" +#define D_TVOC "TVOC" +#define D_UPGRADE "opwaarderen" +#define D_UPLOAD "Verzenden" +#define D_UPTIME "Bedrijfstijd" +#define D_USER "Gebruiker" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV-index" +#define D_UV_INDEX_1 "Laag" +#define D_UV_INDEX_2 "Gemiddeld" +#define D_UV_INDEX_3 "Hoog" +#define D_UV_INDEX_4 "Intens" +#define D_UV_INDEX_5 "Gevaarlijk" +#define D_UV_INDEX_6 "Schadelijk" +#define D_UV_INDEX_7 "Uitzonderlijk" +#define D_UV_LEVEL "UV niveau" +#define D_UV_POWER "UV intensiteit" +#define D_VERSION "Versie" +#define D_VOLTAGE "Spanning" +#define D_WEIGHT "Gewicht" +#define D_WARMLIGHT "Warm" +#define D_WEB_SERVER "Webserver" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "WAARSCHUWING Deze versie bewaart geen instellingen" +#define D_LEVEL_10 "niveau 1-0" +#define D_LEVEL_01 "niveau 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serieel logging uitgeschakeld" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logging weer ingeschakeld" + +#define D_SET_BAUDRATE_TO "Zet baudrate op" +#define D_RECEIVED_TOPIC "Ontvangen topic" +#define D_DATA_SIZE "Data lengte" +#define D_ANALOG_INPUT "Analoog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig mislukt met status" +#define D_ACTIVE_FOR_3_MINUTES "3 minuten actief" +#define D_FAILED_TO_START "mislukt" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Verbinden met AP" +#define D_IN_MODE "in stand" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbinding mislukt omdat geen IP adres werd ontvangen" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbinding mislukt omdat AP onbereikbaar is" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbinding mislukt door fout wachtwoord" +#define D_CONNECT_FAILED_AP_TIMEOUT "Verbinding mislukt door AP time-out" +#define D_ATTEMPTING_CONNECTION "Verbinden..." +#define D_CHECKING_CONNECTION "Controleer verbinding..." +#define D_QUERY_DONE "Aanvraag klaar. Aantal MQTT diensten gevonden" +#define D_MQTT_SERVICE_FOUND "MQTT dienst gevonden op" +#define D_FOUND_AT "gevonden op" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host niet gevonden" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Opgeslagen in flash op" +#define D_LOADED_FROM_FLASH_AT "Geladen vanuit flash op" +#define D_USE_DEFAULTS "Gebruik standaardwaarden" +#define D_ERASED_SECTOR "Wis sector" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Zet JavaScript aan voor Tasmota" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
opwaarderen" +#define D_WEBSERVER_ACTIVE_ON "Webserver actief op" +#define D_WITH_IP_ADDRESS "met IP adres" +#define D_WEBSERVER_STOPPED "Webserver gestopt" +#define D_FILE_NOT_FOUND "Bestand niet gevonden" +#define D_REDIRECTED "Omleiding naar captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager start AccessPoint en hou Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager start AccessPoint" +#define D_TRYING_TO_CONNECT "Apparaat probeert te verbinden met netwerk" + +#define D_RESTART_IN "Herstart over" +#define D_SECONDS "seconden" +#define D_DEVICE_WILL_RESTART "Herstart over enkele seconden" +#define D_BUTTON_TOGGLE "Toggle" // Wissel, Tuimel +#define D_CONFIGURATION "Configuratie" +#define D_INFORMATION "Informatie" +#define D_FIRMWARE_UPGRADE "Opwaarderen" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Bevestig herstart" + +#define D_CONFIGURE_MODULE "Configureer Module" +#define D_CONFIGURE_WIFI "Configureer WiFi" +#define D_CONFIGURE_MQTT "Configureer MQTT" +#define D_CONFIGURE_DOMOTICZ "Configureer Domoticz" +#define D_CONFIGURE_LOGGING "Configureer Logging" +#define D_CONFIGURE_OTHER "Configureer Overige" +#define D_CONFIRM_RESET_CONFIGURATION "Bevestig reset configuratie" +#define D_RESET_CONFIGURATION "Reset Configuratie" +#define D_BACKUP_CONFIGURATION "Bewaar Configuratie" +#define D_RESTORE_CONFIGURATION "Herstel Configuration" +#define D_MAIN_MENU "Hoofdmenu" + +#define D_MODULE_PARAMETERS "Module parameters" +#define D_MODULE_TYPE "Module soort" +#define D_PULLUP_ENABLE "Geen schakelaar pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serieel In" +#define D_SERIAL_OUT "Serieel Uit" + +#define D_WIFI_PARAMETERS "Wifi parameters" +#define D_SCAN_FOR_WIFI_NETWORKS "Zoek wifi netwerken" +#define D_SCAN_DONE "Scan klaar" +#define D_NO_NETWORKS_FOUND "Geen netwerken gevonden" +#define D_REFRESH_TO_SCAN_AGAIN "Vernieuw om opnieuw te zoeken" +#define D_DUPLICATE_ACCESSPOINT "Dubbel AccessPoint" +#define D_SKIPPING_LOW_QUALITY "Overslaan agv lage ontvangskwaliteit" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Wachtwoord" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Wachtwoord" + +#define D_MQTT_PARAMETERS "MQTT parameters" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Volledig Topic" + +#define D_LOGGING_PARAMETERS "Logging parameters" +#define D_SERIAL_LOG_LEVEL "Serieel log niveau" +#define D_MQTT_LOG_LEVEL "Mqtt log niveau" +#define D_WEB_LOG_LEVEL "Web log niveau" +#define D_SYS_LOG_LEVEL "Syslog niveau" +#define D_MORE_DEBUG "Meer debug" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog poort" +#define D_TELEMETRY_PERIOD "Telemetry periode" + +#define D_OTHER_PARAMETERS "Overige parameters" +#define D_TEMPLATE "Sjabloon" +#define D_ACTIVATE "Activeer" +#define D_WEB_ADMIN_PASSWORD "Web Admin Wachtwoord" +#define D_MQTT_ENABLE "MQTT ingeschakeld" +#define D_FRIENDLY_NAME "Beschrijvende naam" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "een apparaat" +#define D_MULTI_DEVICE "meer apparaten" + +#define D_CONFIGURE_TEMPLATE "Configureer Sjabloon" +#define D_TEMPLATE_PARAMETERS "Sjabloon parameters" +#define D_TEMPLATE_NAME "Naam" +#define D_BASE_TYPE "Op basis van" +#define D_TEMPLATE_FLAGS "Opties" + +#define D_SAVE_CONFIGURATION "Bewaar configuratie" +#define D_CONFIGURATION_SAVED "Configuratie opgeslagen" +#define D_CONFIGURATION_RESET "Configuratie ge-reset" + +#define D_PROGRAM_VERSION "Programma Versie" +#define D_BUILD_DATE_AND_TIME "Compileer Datum & Tijd" +#define D_CORE_AND_SDK_VERSION "Core/SDK Versie" +#define D_FLASH_WRITE_COUNT "Aantal Flash opslagen" +#define D_MAC_ADDRESS "MAC Adres" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Poort" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT Gebruiker" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Groep Topic" +#define D_MQTT_FULL_TOPIC "MQTT Volledig Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash Grootte" +#define D_FREE_PROGRAM_SPACE "Programma ruimte over" + +#define D_UPGRADE_BY_WEBSERVER "Opwaarderen dmv webserver" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Start opwaarderen" +#define D_UPGRADE_BY_FILE_UPLOAD "Opwaarderen dmv verzenden bestand" +#define D_UPLOAD_STARTED "Verzending gestart" +#define D_UPGRADE_STARTED "Opwaarderen gestart" +#define D_UPLOAD_DONE "Opwaarderen klaar" +#define D_UPLOAD_ERR_1 "Geen bestand gekozen" +#define D_UPLOAD_ERR_2 "Onvoldoende geheugen ruimte" +#define D_UPLOAD_ERR_3 "Magische byte is niet 0xE9" +#define D_UPLOAD_ERR_4 "Programma flash grootte is groter dan werkelijke flash grootte" +#define D_UPLOAD_ERR_5 "Opwaardeer buffer verschil" +#define D_UPLOAD_ERR_6 "Opwaarderen mislukt. Schakel logging 3 in" +#define D_UPLOAD_ERR_7 "Opwaarderen afgebroken" +#define D_UPLOAD_ERR_8 "Ongeldig bestand" +#define D_UPLOAD_ERR_9 "Bestand is te groot" +#define D_UPLOAD_ERR_10 "Init RF chip mislukt" +#define D_UPLOAD_ERR_11 "Wissen RF chip mislukt" +#define D_UPLOAD_ERR_12 "Opwaarderen RF chip mislukt" +#define D_UPLOAD_ERR_13 "Decoderen RF bestand mislukt" +#define D_UPLOAD_ERROR_CODE "Opwaardeer foutcode" + +#define D_ENTER_COMMAND "Geef opdracht" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Schakel weblog 2 in indien antwoord verwacht" +#define D_NEED_USER_AND_PASSWORD "Benodig user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Controleer TLS vingerafdruk..." +#define D_TLS_CONNECT_FAILED_TO "TLS Verbinding mislukt naar" +#define D_RETRY_IN "Opnieuw proberen over" +#define D_VERIFIED "Gecontroleerd met vingerafdruk" +#define D_INSECURE "Door ongeldige vingerafdruk een onveilige verbinding" +#define D_CONNECT_FAILED_TO "Verbinding mislukt naar" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast uitgeschakeld" +#define D_MULTICAST_REJOINED "Multicast verbonden" +#define D_MULTICAST_JOIN_FAILED "Multicast verbinding mislukt" +#define D_FAILED_TO_SEND_RESPONSE "Antwoord versturen mislukt" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basis gebeurtenis" +#define D_WEMO_EVENT_SERVICE "WeMo gebeurtenis dienst" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo installatie" +#define D_RESPONSE_SENT "Antwoord verstuurd" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue installatie" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API niet beschikbaar" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST argumenten" +#define D_3_RESPONSE_PACKETS_SENT "3 antwoord paketten verstuurd" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Toets idx" +#define D_DOMOTICZ_SWITCH_IDX "Schakelaar idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Spanning/PM2,5" + #define D_DOMOTICZ_CURRENT "Stroom/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Bijwerk timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configureer Tijdschakelaar" +#define D_TIMER_PARAMETERS "Tijdschakelaar parameters" +#define D_TIMER_ENABLE "Tijdschakelaars inschakelen" +#define D_TIMER_ARM "Actief" +#define D_TIMER_TIME "Tijd" +#define D_TIMER_DAYS "Dagen" +#define D_TIMER_REPEAT "Herhaal" +#define D_TIMER_OUTPUT "Uitgang" +#define D_TIMER_ACTION "Actie" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configureer KNX" +#define D_KNX_PARAMETERS "KNX Parameters" +#define D_KNX_GENERAL_CONFIG "Algemeen" +#define D_KNX_PHYSICAL_ADDRESS "Eigen adres" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Moet uniek zijn op het KNX netwerk)" +#define D_KNX_ENABLE "KNX inschakelen" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Stuur gegevens naar groep adressen" +#define D_ADD "Toevoegen" +#define D_DELETE "Verwijder" +#define D_REPLY "Antwoord" +#define D_KNX_GROUP_ADDRESS_TO_READ "Ontvang gegevens van groep adressen" +#define D_RECEIVED_FROM "Ontvangen van" +#define D_KNX_COMMAND_WRITE "Schrijven" +#define D_KNX_COMMAND_READ "Lezen" +#define D_KNX_COMMAND_OTHER "Overige" +#define D_SENT_TO "verzend naar" +#define D_KNX_WARNING "Groep adres (0/0/0) is gereserveerd en mag niet worden gebruikt." +#define D_KNX_ENHANCEMENT "Verbeter verbinding" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Verbruik vandaag" +#define D_ENERGY_YESTERDAY "Verbruik gisteren" +#define D_ENERGY_TOTAL "Verbruik totaal" + +// xdrv_27_shutter.ino +#define D_OPEN "Openen" +#define D_CLOSE "Sluiten" +#define D_DOMOTICZ_SHUTTER "Rolluik" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configureer PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 Parameters" +#define D_INVERT_PORTS "Inverteer Poorten" +#define D_DEVICE "Apparaat" +#define D_DEVICE_INPUT "Ingang" +#define D_DEVICE_OUTPUT "Uitgang" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor bezet" +#define D_SENSOR_CRC_ERROR "Sensor CRC fout" +#define D_SENSORS_FOUND "Aantal sensoren" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Te lang wachten op" +#define D_START_SIGNAL_LOW "laag start signaal" +#define D_START_SIGNAL_HIGH "hoog start signaal" +#define D_PULSE "signaal" +#define D_CHECKSUM_FAILURE "Controle mislukt" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Geen opdracht ACK van sensor" +#define D_SHT1X_FOUND "SHT1X gevonden" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Stofdeeltjes" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Verwijder gewicht" +#define D_HX_CAL_REFERENCE "Plaats ijkgewicht" +#define D_HX_CAL_DONE "Ge-ijkt" +#define D_HX_CAL_FAIL "Ijken is mislukt" +#define D_RESET_HX711 "Nulstelling weegschaal" +#define D_CONFIGURE_HX711 "Configureer Weegschaal" +#define D_HX711_PARAMETERS "Weegschaal parameters" +#define D_ITEM_WEIGHT "Gewicht van onderdeel" +#define D_REFERENCE_WEIGHT "Ijkgewicht" +#define D_CALIBRATE "Ijken" +#define D_CALIBRATION "Ijken" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Windrichting" +#define D_TX20_WIND_SPEED "Windsnelheid" +#define D_TX20_WIND_SPEED_AVG "Windsnelheid gemiddeld" +#define D_TX20_WIND_SPEED_MAX "Windsnelhied maximaal" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Geen" +#define D_SENSOR_USER "Gebruiker" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Speler" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relais" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Teller" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Zoemer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectoren" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Fase hoek" +#define D_IMPORT_ACTIVE "Import werkelijk" +#define D_EXPORT_ACTIVE "Export werkelijk" +#define D_IMPORT_REACTIVE "Import blind" +#define D_EXPORT_REACTIVE "Export blind" +#define D_TOTAL_REACTIVE "Totaal blind" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 spanning" +#define D_PV1_CURRENT "PV1 stroom" +#define D_PV1_POWER "PV1 vermogen" +#define D_PV2_VOLTAGE "PV2 spanning" +#define D_PV2_CURRENT "PV2 stroom" +#define D_PV2_POWER "PV2 vermogen" +#define D_SOLAR_POWER "Zon vermogen" +#define D_INVERTER_POWER "Omvormer vermogen" +#define D_STATUS "Status" +#define D_WAITING "Wacht" +#define D_CHECKING "Controle" +#define D_WORKING "Actief" +#define D_FAILURE "Fout" +#define D_SOLAX_ERROR_0 "Geen" +#define D_SOLAX_ERROR_1 "Netverbinding" +#define D_SOLAX_ERROR_2 "Netspanning" +#define D_SOLAX_ERROR_3 "Netfrequentie" +#define D_SOLAX_ERROR_4 "Pv spanning" +#define D_SOLAX_ERROR_5 "Isolatie" +#define D_SOLAX_ERROR_6 "Overtemperatuur" +#define D_SOLAX_ERROR_7 "Ventilator" +#define D_SOLAX_ERROR_8 "Overige" + +#endif // _LANGUAGE_NL_NL_H_ diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 8f5af6813..1b83f8697 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -1,701 +1,703 @@ -/* - pl-PL-d.h - localization for Polish with diacritics - Poland for Tasmota - - Copyright (C) 2019 Theo Arends (translated by roblad - Robert L., upgraded by R. Turala) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_PL_PL_D_H_ -#define _LANGUAGE_PL_PL_D_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.12.0d -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1045 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "pl" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "NiePonWtoŚroCzwPiąSob" -#define D_MONTH3LIST "StyLutMarKwiMajCzeLipSieWrzPaźLisGru" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Jakość powietrza" -#define D_AP "AP" // Access Point -#define D_AS "jak" -#define D_AUTO "AUTO" -#define D_BLINK "Miganie" -#define D_BLINKOFF "Miganie - Wył." -#define D_BOOT_COUNT "Licznik restartów" -#define D_BRIGHTLIGHT "Jasny" -#define D_BSSID "BSSId" -#define D_BUTTON "Przycisk" -#define D_BY "by" // Written by me -#define D_BYTES "Bajtów" -#define D_CELSIUS "Celsiusz" -#define D_CHANNEL "Kanał" -#define D_CO2 "Dwutlenek węgla" -#define D_CODE "Kod" // Button code -#define D_COLDLIGHT "Zimny" -#define D_COMMAND "Komenda" -#define D_CONNECTED "Połączony" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Licz" -#define D_COUNTER "Licznik" -#define D_CURRENT "Prąd" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Ciemny" -#define D_DEBUG "Debug" -#define D_DISABLED "Wyłączony" -#define D_DISTANCE "Odległość" -#define D_DNS_SERVER "Serwer DNS" -#define D_DONE "Wykonane" -#define D_DST_TIME "Czas DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulacja" -#define D_ENABLED "Załączony" -#define D_ERASE "Wyczyść" -#define D_ERROR "Błąd" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Błędny" -#define D_FALLBACK "Awaryjny" -#define D_FALLBACK_TOPIC "Temat zastępczy" -#define D_FALSE "Fałsz" -#define D_FILE "Plik" -#define D_FLOW_RATE "Przepływ" -#define D_FREE_MEMORY "Wolna pamięć" -#define D_FREQUENCY "Częstotliwość" -#define D_GAS "Gas" -#define D_GATEWAY "Brama" -#define D_GROUP "Grupa" -#define D_HOST "Serwer" -#define D_HOSTNAME "Nazwa serwera" -#define D_HUMIDITY "Wilgotność" -#define D_ILLUMINANCE "Podświetlanie" -#define D_IMMEDIATE "Natychmiastowy" // Button immediate -#define D_INDEX "Indeks" -#define D_INFO "Informacja" -#define D_INFRARED "Podczerwień" -#define D_INITIALIZED "Zainicjowany" -#define D_IP_ADDRESS "Adres IP" -#define D_LIGHT "Światło" -#define D_LWT "LWT" -#define D_MODULE "Moduł" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "Wielokrotne naciśnięcie" -#define D_NOISE "Szum" -#define D_NONE "Brak" -#define D_OFF "Wyłączony" -#define D_OFFLINE "Nieaktywny" -#define D_OK "Ok" -#define D_ON "Załączony" -#define D_ONLINE "Aktywny" -#define D_PASSWORD "Hasło" -#define D_PORT "Port" -#define D_POWER_FACTOR "Cosinus fi" -#define D_POWERUSAGE "Moc" -#define D_POWERUSAGE_ACTIVE "Moc czynna" -#define D_POWERUSAGE_APPARENT "Moc pozorna" -#define D_POWERUSAGE_REACTIVE "Moc bierna" -#define D_PRESSURE "Ciśnienie" -#define D_PRESSUREATSEALEVEL "Ciśnienie na poziomie morza" -#define D_PROGRAM_FLASH_SIZE "Rozmiar programu flash" -#define D_PROGRAM_SIZE "Rozmiar programu" -#define D_PROJECT "Projekt" -#define D_RAIN "Deszcz" -#define D_RECEIVED "Otrzymany" -#define D_RESTART "Restart" -#define D_RESTARTING "Restartowanie" -#define D_RESTART_REASON "Przyczyna restartu" -#define D_RESTORE "Przywracanie" -#define D_RETAINED "Zachowane" -#define D_RULE "Reguła" -#define D_SAVE "Zapisz" -#define D_SENSOR "Czujnik" -#define D_SSID "SSID" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Maska podsieci" -#define D_SUBSCRIBE_TO "Subskrybuj" -#define D_UNSUBSCRIBE_FROM "Nie subskrybuj" -#define D_SUCCESSFUL "Powodzenie" -#define D_SUNRISE "Wschód słońca" -#define D_SUNSET "Zachód słońca" -#define D_TEMPERATURE "Temperatura" -#define D_TO "do" -#define D_TOGGLE "Przełącz" -#define D_TOPIC "Temat" -#define D_TOTAL_USAGE "Całkowite użycie" -#define D_TRANSMIT "Wyślij" -#define D_TRUE "Prawda" -#define D_TVOC "TVOC" -#define D_UPGRADE "aktualizacji" -#define D_UPLOAD "Wgraj" -#define D_UPTIME "Czas pracy" -#define D_USER "Użytkownik" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Index UV" -#define D_UV_INDEX_1 "Niski" -#define D_UV_INDEX_2 "Średni" -#define D_UV_INDEX_3 "Wysoki" -#define D_UV_INDEX_4 "Niebezpieczny" -#define D_UV_INDEX_5 "Burn L1/2" -#define D_UV_INDEX_6 "Burn L3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Poziom UV" -#define D_UV_POWER "Moc UV" -#define D_VERSION "Wersja" -#define D_VOLTAGE "Napięcie" -#define D_WEIGHT "Waga" -#define D_WARMLIGHT "Temperatura światła" -#define D_WEB_SERVER "Serwer Web" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "UWAGA Ta wersja nie obsługuje zapisu ustawień" -#define D_LEVEL_10 "poziom 1-0" -#define D_LEVEL_01 "poziom 0-1" -#define D_SERIAL_LOGGING_DISABLED "Wyłączony dziennik na porcie szeregowym" -#define D_SYSLOG_LOGGING_REENABLED "Wznowiono zapis do Syslog" - -#define D_SET_BAUDRATE_TO "Ustaw szybkość transmisji na" -#define D_RECEIVED_TOPIC "Otrzymany temat" -#define D_DATA_SIZE "Wielkość danych" -#define D_ANALOG_INPUT "Wejście analogowe" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Pętla zablokowana" -#define D_WPS_FAILED_WITH_STATUS "Błąd konfiguracji WPS ze statusem" -#define D_ACTIVE_FOR_3_MINUTES "aktywny 3 minuty" -#define D_FAILED_TO_START "nie udało się uruchomić" -#define D_PATCH_ISSUE_2186 "Błąd poprawki 2186" -#define D_CONNECTING_TO_AP "Łączenie z AP" -#define D_IN_MODE "w trybie" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Połączenie nie powiodło się, ponieważ nie otrzymano adresu IP" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Połączenie nie powiodło się, AP nie osiągalny" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Połączenie nie powiodło się, nieprawidlowe hasło" -#define D_CONNECT_FAILED_AP_TIMEOUT "Nie udało się nawiązac połączenia, limit czasu przekroczony" -#define D_ATTEMPTING_CONNECTION "Próba połączenia..." -#define D_CHECKING_CONNECTION "Sprawdzanie połączenia..." -#define D_QUERY_DONE "Zapytanie wykonane" -#define D_MQTT_SERVICE_FOUND "Usługa MQTT została znaleziona" -#define D_FOUND_AT "znaleziono w" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nie znaleziony" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Zapisano do pamięci flash w" -#define D_LOADED_FROM_FLASH_AT "Wczytano z pamięci flash w" -#define D_USE_DEFAULTS "Użyj domyślnych" -#define D_ERASED_SECTOR "Sektor wymazany" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" -#define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" -#define D_WITH_IP_ADDRESS "z adresem IP" -#define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" -#define D_FILE_NOT_FOUND "Plik nie odnaleziony" -#define D_REDIRECTED "Przekierowano do własnego portalu" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Menedżer Wifi ustawia punkt dostępowy i zachowuje stacje" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Menedżer sieci Wi-Fi Access Point" -#define D_TRYING_TO_CONNECT "Próbuję połączyć urzadzenie z siecią" - -#define D_RESTART_IN "Zrestartuj" -#define D_SECONDS "Sekund" -#define D_DEVICE_WILL_RESTART "Urządzenie zrestartuje sie za kilka sekund" -#define D_BUTTON_TOGGLE "Załącz/Wyłącz" -#define D_CONFIGURATION "Konfiguracja" -#define D_INFORMATION "Informacje" -#define D_FIRMWARE_UPGRADE "Aktualizacja oprogramowania" -#define D_CONSOLE "Konsola" -#define D_CONFIRM_RESTART "Potwierdź restart" - -#define D_CONFIGURE_MODULE "Konfiguracja modułu" -#define D_CONFIGURE_WIFI "Konfiguracja WiFi" -#define D_CONFIGURE_MQTT "Konfiguracja MQTT" -#define D_CONFIGURE_DOMOTICZ "Konfiguracja Domoticza" -#define D_CONFIGURE_LOGGING "Konfiguracja dziennika" -#define D_CONFIGURE_OTHER "Inne konfiguracje" -#define D_CONFIRM_RESET_CONFIGURATION "Potwierdź reset ustawień" -#define D_RESET_CONFIGURATION "Reset ustawień" -#define D_BACKUP_CONFIGURATION "Kopia ustawień" -#define D_RESTORE_CONFIGURATION "Przywracanie ustawień" -#define D_MAIN_MENU "Menu główne" - -#define D_MODULE_PARAMETERS "Parametry modułu" -#define D_MODULE_TYPE "Typ" -#define D_PULLUP_ENABLE "Przełącznik pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Wejście rs" -#define D_SERIAL_OUT "Wyjście rs" - -#define D_WIFI_PARAMETERS "Parametry sieci WiFi" -#define D_SCAN_FOR_WIFI_NETWORKS "Skanuj sieci" -#define D_SCAN_DONE "Skanowanie wykonane" -#define D_NO_NETWORKS_FOUND "Nie znaleziono sieci" -#define D_REFRESH_TO_SCAN_AGAIN "Odśwież aby ponownie wyszukać sieci" -#define D_DUPLICATE_ACCESSPOINT "Duplikuj" -#define D_SKIPPING_LOW_QUALITY "Pominięto z powodu niskiej jakości sygnału" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "Nazwa 1" -#define D_AP1_PASSWORD "Hasło 1" -#define D_AP2_SSID "Nazwa 2" -#define D_AP2_PASSWORD "Hasło 2" - -#define D_MQTT_PARAMETERS "Parametry MQTT" -#define D_CLIENT "Klient" -#define D_FULL_TOPIC "Pełny temat" - -#define D_LOGGING_PARAMETERS "Opcje dziennika" -#define D_SERIAL_LOG_LEVEL "Serial - poziom" -#define D_MQTT_LOG_LEVEL "Mqtt - poziom" -#define D_WEB_LOG_LEVEL "Web - poziom" -#define D_SYS_LOG_LEVEL "System - poziom" -#define D_MORE_DEBUG "Więcej informacji dziennika" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Okres telemetrii" - -#define D_OTHER_PARAMETERS "Inne parametry" -#define D_TEMPLATE "Szablon" -#define D_ACTIVATE "Aktywuj" -#define D_WEB_ADMIN_PASSWORD "Hasło administratora" -#define D_MQTT_ENABLE "Załącz MQTT" -#define D_FRIENDLY_NAME "Nazwa" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Mostek Hue" -#define D_SINGLE_DEVICE "pojedyńcze urządzenie" -#define D_MULTI_DEVICE "multi urządzenie" - -#define D_CONFIGURE_TEMPLATE "Konfiguracja szablonu" -#define D_TEMPLATE_PARAMETERS "Parametry szablonu" -#define D_TEMPLATE_NAME "Nazwa" -#define D_BASE_TYPE "Na bazie" -#define D_TEMPLATE_FLAGS "Opcje" - -#define D_SAVE_CONFIGURATION "Zapisz ustawienia" -#define D_CONFIGURATION_SAVED "Ustawienia zapisane" -#define D_CONFIGURATION_RESET "Ustawienia zresetowane" - -#define D_PROGRAM_VERSION "Wersja oprogramowania" -#define D_BUILD_DATE_AND_TIME "Data kompilacji" -#define D_CORE_AND_SDK_VERSION "Wersja Core/SDK" -#define D_FLASH_WRITE_COUNT "Liczba zapisów do pamięci" -#define D_MAC_ADDRESS "Adres MAC" -#define D_MQTT_HOST "Host" -#define D_MQTT_PORT "Port" -#define D_MQTT_CLIENT "Klient" -#define D_MQTT_USER "Użytkownik" -#define D_MQTT_TOPIC "Temat" -#define D_MQTT_GROUP_TOPIC "Temat grupy" -#define D_MQTT_FULL_TOPIC "Pełny temat" -#define D_MDNS_DISCOVERY "Wykrywanie mDNS" -#define D_MDNS_ADVERTISE "Rozgłaszanie mDNS" -#define D_ESP_CHIP_ID "ID ukladu ESP" -#define D_FLASH_CHIP_ID "ID pamięci flash" -#define D_FLASH_CHIP_SIZE "Rozmiar pamięci flash" -#define D_FREE_PROGRAM_SPACE "Wolna pamięć programu" - -#define D_UPGRADE_BY_WEBSERVER "Aktualizacja z serwera Web" -#define D_OTA_URL "Adres serwera" -#define D_START_UPGRADE "Aktualizuj" -#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja z pliku" -#define D_UPLOAD_STARTED "Wgrywanie rozpoczęte" -#define D_UPGRADE_STARTED "Aktualizacja rozpoczęta" -#define D_UPLOAD_DONE "Wgrywanie zakończone" -#define D_UPLOAD_ERR_1 "Nie wybrano pliku" -#define D_UPLOAD_ERR_2 "Niewystarczająca ilość miejsca" -#define D_UPLOAD_ERR_3 "Magiczny bajt jest inny niz 0xE9" -#define D_UPLOAD_ERR_4 "Rozmiar programu jest większy niż rzeczywisty rozmiar pamięci flash" -#define D_UPLOAD_ERR_5 "Wgrywanie, bufor niezgodności stanu porównywanych bitow" -#define D_UPLOAD_ERR_6 "Błąd wgrywania. Uruchomiono zapis do dziennika na poziomie 3" -#define D_UPLOAD_ERR_7 "Wgrywanie przerwane" -#define D_UPLOAD_ERR_8 "Błędny plik" -#define D_UPLOAD_ERR_9 "Plik jest za duży" -#define D_UPLOAD_ERR_10 "Błąd inicjacji układu RF" -#define D_UPLOAD_ERR_11 "Błąd kasowania układu RF" -#define D_UPLOAD_ERR_12 "Błąd zapisu układu RF" -#define D_UPLOAD_ERR_13 "Błąd dekodowania oprrogramowania układu RF" -#define D_UPLOAD_ERROR_CODE "Błąd wgrywania" - -#define D_ENTER_COMMAND "Wprowadź polecenie" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Włącz poziom 2 zapisu dziennika, jeśli oczekiwana jest odpowiedź" -#define D_NEED_USER_AND_PASSWORD "Wymagany użytkownik=&hasło=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Weryfikuj odcisk TLS..." -#define D_TLS_CONNECT_FAILED_TO "Nieudane połączenie TLS do" -#define D_RETRY_IN "Spróbuj ponownie" -#define D_VERIFIED "Zweryfikowano odcisk" -#define D_INSECURE "Nieprawidłowe połączenie z powodu błędnego odcisku TLS" -#define D_CONNECT_FAILED_TO "Nie udało się nawiązać połączenia" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast wyłączony" -#define D_MULTICAST_REJOINED "Multicast dołączony" -#define D_MULTICAST_JOIN_FAILED "Podłączenie Multicast nie powiodło się" -#define D_FAILED_TO_SEND_RESPONSE "Nie udało się wysłać odpowiedzi" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "Zdarzenie podstawowe" -#define D_WEMO_EVENT_SERVICE "Zdarzenie serwisowe" -#define D_WEMO_META_SERVICE "Meta dane serwisowe" -#define D_WEMO_SETUP "Ustawienia WeMo" -#define D_RESPONSE_SENT "Wyślij odpowiedź" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Ustawienia Hue" -#define D_HUE_API_NOT_IMPLEMENTED "Api nie zaimplementowane" -#define D_HUE_API "API" -#define D_HUE_POST_ARGS "POST argument" -#define D_3_RESPONSE_PACKETS_SENT "3 pakiety odpowiedzi wysyłane" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Klucz Idx" -#define D_DOMOTICZ_SWITCH_IDX "Przełącznik Idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor Idx" - #define D_DOMOTICZ_TEMP "Temperatura" - #define D_DOMOTICZ_TEMP_HUM "Temperatura, Wilgotność" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temperatura, Wilgotność, Ciśnienie" - #define D_DOMOTICZ_POWER_ENERGY "Moc, Energia" - #define D_DOMOTICZ_ILLUMINANCE "Oświetlenie" - #define D_DOMOTICZ_COUNT "Licznik" - #define D_DOMOTICZ_VOLTAGE "Napięcie" - #define D_DOMOTICZ_CURRENT "Prąd" - #define D_DOMOTICZ_AIRQUALITY "Jakość powietrza" - #define D_DOMOTICZ_P1_SMART_METER "Miernik P1" -#define D_DOMOTICZ_UPDATE_TIMER "Aktualizacja zegara" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Konfiguracja harmonogramu" -#define D_TIMER_PARAMETERS "Parametry harmonogramu" -#define D_TIMER_ENABLE "Załącz harmonogram" -#define D_TIMER_ARM "Załącz" -#define D_TIMER_TIME "Czas" -#define D_TIMER_DAYS "Dni" -#define D_TIMER_REPEAT "Powtarzaj" -#define D_TIMER_OUTPUT "Wyjście" -#define D_TIMER_ACTION "Akcja" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Konfiguracja KNX" -#define D_KNX_PARAMETERS "Parametry KNX" -#define D_KNX_GENERAL_CONFIG "Konfiguracja ogólna" -#define D_KNX_PHYSICAL_ADDRESS "Adres fizyczny" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Musi być unikalny w sieci KNX)" -#define D_KNX_ENABLE "Załącz" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Adresy grupowe do zapisu" -#define D_ADD "Dodaj" -#define D_DELETE "Usuń" -#define D_REPLY "Odpowiedz" -#define D_KNX_GROUP_ADDRESS_TO_READ "Adresy grupowe do odbioru" -#define D_RECEIVED_FROM "Odebrane od" -#define D_KNX_COMMAND_WRITE "Zapisz" -#define D_KNX_COMMAND_READ "Czytaj" -#define D_KNX_COMMAND_OTHER "Inna komenda" -#define D_SENT_TO "Wyślij do" -#define D_KNX_WARNING "Adres grupy (0/0/0) jest zarezerwowany i nie można go użyć." -#define D_KNX_ENHANCEMENT "Rozszerzenia" -#define D_KNX_TX_SLOT "Gniazdo TX" -#define D_KNX_RX_SLOT "Gniazdo RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energia dzisiaj" -#define D_ENERGY_YESTERDAY "Energia wczoraj" -#define D_ENERGY_TOTAL "Energia całkowita" - -// xdrv_27_shutter.ino -#define D_OPEN "Otwórz" -#define D_CLOSE "Zamknij" -#define D_DOMOTICZ_SHUTTER "Roleta" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Konfiguracja PCF8574" -#define D_PCF8574_PARAMETERS "Parametry PCF8574" -#define D_INVERT_PORTS "Porty odwrócone" -#define D_DEVICE "Urządzenie" -#define D_DEVICE_INPUT "Wejście" -#define D_DEVICE_OUTPUT "Wyjście" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Czujnik zajęty" -#define D_SENSOR_CRC_ERROR "Błąd CRC czujnika" -#define D_SENSORS_FOUND "Znaleziono czujnik" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Trwa oczekiwanie" -#define D_START_SIGNAL_LOW "Sygnał startowy niski" -#define D_START_SIGNAL_HIGH "Sygnał startowy wysoki" -#define D_PULSE "Impuls" -#define D_CHECKSUM_FAILURE "Błędna suma kontrolna" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Czujnik nie otrzymał komendy ACK" -#define D_SHT1X_FOUND "SHT1X znaleziony" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Cząstki" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Usuń wagę" -#define D_HX_CAL_REFERENCE "Załaduj wagę referencyjną" -#define D_HX_CAL_DONE "Skalibrowany" -#define D_HX_CAL_FAIL "Błąd kalibracji" -#define D_RESET_HX711 "Zresetuj skalę" -#define D_CONFIGURE_HX711 "Skonfiguruj skalę" -#define D_HX711_PARAMETERS "Parametry skali" -#define D_ITEM_WEIGHT "Waga przedmiotu" -#define D_REFERENCE_WEIGHT "Waga referencyjna" -#define D_CALIBRATE "Skalibruj" -#define D_CALIBRATION "Kalibrowanie" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Kierunek" -#define D_TX20_WIND_SPEED "Prędkość" -#define D_TX20_WIND_SPEED_AVG "Średnia prędkość" -#define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Brak" -#define D_SENSOR_USER "Użytkownik" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "Odtearzacz MP3" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Przełącznik" // Suffix "1" -#define D_SENSOR_BUTTON "Przycisk" // Suffix "1" -#define D_SENSOR_RELAY "Przekaźnik" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "Led link" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Licznik" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Podświetlanie" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "Głęboko uśpiony" -#define D_SENSOR_EXS_ENABLE "Załącz EXS" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Godz" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sektory" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Przesunięcie faz" -#define D_IMPORT_ACTIVE "Czynna pobrana" -#define D_EXPORT_ACTIVE "Czynna oddana" -#define D_IMPORT_REACTIVE "Bierna pobrana" -#define D_EXPORT_REACTIVE "Bierna oddana" -#define D_TOTAL_REACTIVE "Bierna całkowita" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "Napięcie PV1" -#define D_PV1_CURRENT "Prąd PV1" -#define D_PV1_POWER "Moc PV1 " -#define D_PV2_VOLTAGE "Napięcie PV2" -#define D_PV2_CURRENT "Prąd PV2" -#define D_PV2_POWER "Moc PV2" -#define D_SOLAR_POWER "Moc PV" -#define D_INVERTER_POWER "Moc invertera" -#define D_STATUS "Status" -#define D_WAITING "Oczekiwanie" -#define D_CHECKING "Sprawdzanie" -#define D_WORKING "Praca" -#define D_FAILURE "Błąd" -#define D_SOLAX_ERROR_0 "Błąd - brak kodu" -#define D_SOLAX_ERROR_1 "Błąd - utrata sieci" -#define D_SOLAX_ERROR_2 "Błąd - napięcie sieci" -#define D_SOLAX_ERROR_3 "Błąd - częstotliwość sieci" -#define D_SOLAX_ERROR_4 "Błąd - napięcie PV" -#define D_SOLAX_ERROR_5 "Błąd - usterka izolacji" -#define D_SOLAX_ERROR_6 "Błąd - przegrzanie" -#define D_SOLAX_ERROR_7 "Błąd - wentylator" -#define D_SOLAX_ERROR_8 "Błąd - inne urządzenie" - -#endif // _LANGUAGE_PL_PL_D_H_ +/* + pl-PL-d.h - localization for Polish with diacritics - Poland for Tasmota + + Copyright (C) 2019 Theo Arends (translated by roblad - Robert L., upgraded by R. Turala) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_PL_PL_D_H_ +#define _LANGUAGE_PL_PL_D_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.12.0d +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1045 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "pl" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "NiePonWtoŚroCzwPiąSob" +#define D_MONTH3LIST "StyLutMarKwiMajCzeLipSieWrzPaźLisGru" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Jakość powietrza" +#define D_AP "AP" // Access Point +#define D_AS "jak" +#define D_AUTO "AUTO" +#define D_BLINK "Miganie" +#define D_BLINKOFF "Miganie - Wył." +#define D_BOOT_COUNT "Licznik restartów" +#define D_BRIGHTLIGHT "Jasny" +#define D_BSSID "BSSId" +#define D_BUTTON "Przycisk" +#define D_BY "by" // Written by me +#define D_BYTES "Bajtów" +#define D_CELSIUS "Celsiusz" +#define D_CHANNEL "Kanał" +#define D_CO2 "Dwutlenek węgla" +#define D_CODE "Kod" // Button code +#define D_COLDLIGHT "Zimny" +#define D_COMMAND "Komenda" +#define D_CONNECTED "Połączony" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Licz" +#define D_COUNTER "Licznik" +#define D_CURRENT "Prąd" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Ciemny" +#define D_DEBUG "Debug" +#define D_DISABLED "Wyłączony" +#define D_DISTANCE "Odległość" +#define D_DNS_SERVER "Serwer DNS" +#define D_DONE "Wykonane" +#define D_DST_TIME "Czas DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulacja" +#define D_ENABLED "Załączony" +#define D_ERASE "Wyczyść" +#define D_ERROR "Błąd" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Błędny" +#define D_FALLBACK "Awaryjny" +#define D_FALLBACK_TOPIC "Temat zastępczy" +#define D_FALSE "Fałsz" +#define D_FILE "Plik" +#define D_FLOW_RATE "Przepływ" +#define D_FREE_MEMORY "Wolna pamięć" +#define D_FREQUENCY "Częstotliwość" +#define D_GAS "Gas" +#define D_GATEWAY "Brama" +#define D_GROUP "Grupa" +#define D_HOST "Serwer" +#define D_HOSTNAME "Nazwa serwera" +#define D_HUMIDITY "Wilgotność" +#define D_ILLUMINANCE "Podświetlanie" +#define D_IMMEDIATE "Natychmiastowy" // Button immediate +#define D_INDEX "Indeks" +#define D_INFO "Informacja" +#define D_INFRARED "Podczerwień" +#define D_INITIALIZED "Zainicjowany" +#define D_IP_ADDRESS "Adres IP" +#define D_LIGHT "Światło" +#define D_LWT "LWT" +#define D_MODULE "Moduł" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "Wielokrotne naciśnięcie" +#define D_NOISE "Szum" +#define D_NONE "Brak" +#define D_OFF "Wyłączony" +#define D_OFFLINE "Nieaktywny" +#define D_OK "Ok" +#define D_ON "Załączony" +#define D_ONLINE "Aktywny" +#define D_PASSWORD "Hasło" +#define D_PORT "Port" +#define D_POWER_FACTOR "Cosinus fi" +#define D_POWERUSAGE "Moc" +#define D_POWERUSAGE_ACTIVE "Moc czynna" +#define D_POWERUSAGE_APPARENT "Moc pozorna" +#define D_POWERUSAGE_REACTIVE "Moc bierna" +#define D_PRESSURE "Ciśnienie" +#define D_PRESSUREATSEALEVEL "Ciśnienie na poziomie morza" +#define D_PROGRAM_FLASH_SIZE "Rozmiar programu flash" +#define D_PROGRAM_SIZE "Rozmiar programu" +#define D_PROJECT "Projekt" +#define D_RAIN "Deszcz" +#define D_RECEIVED "Otrzymany" +#define D_RESTART "Restart" +#define D_RESTARTING "Restartowanie" +#define D_RESTART_REASON "Przyczyna restartu" +#define D_RESTORE "Przywracanie" +#define D_RETAINED "Zachowane" +#define D_RULE "Reguła" +#define D_SAVE "Zapisz" +#define D_SENSOR "Czujnik" +#define D_SSID "SSID" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maska podsieci" +#define D_SUBSCRIBE_TO "Subskrybuj" +#define D_UNSUBSCRIBE_FROM "Nie subskrybuj" +#define D_SUCCESSFUL "Powodzenie" +#define D_SUNRISE "Wschód słońca" +#define D_SUNSET "Zachód słońca" +#define D_TEMPERATURE "Temperatura" +#define D_TO "do" +#define D_TOGGLE "Przełącz" +#define D_TOPIC "Temat" +#define D_TOTAL_USAGE "Całkowite użycie" +#define D_TRANSMIT "Wyślij" +#define D_TRUE "Prawda" +#define D_TVOC "TVOC" +#define D_UPGRADE "aktualizacji" +#define D_UPLOAD "Wgraj" +#define D_UPTIME "Czas pracy" +#define D_USER "Użytkownik" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Index UV" +#define D_UV_INDEX_1 "Niski" +#define D_UV_INDEX_2 "Średni" +#define D_UV_INDEX_3 "Wysoki" +#define D_UV_INDEX_4 "Niebezpieczny" +#define D_UV_INDEX_5 "Burn L1/2" +#define D_UV_INDEX_6 "Burn L3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Poziom UV" +#define D_UV_POWER "Moc UV" +#define D_VERSION "Wersja" +#define D_VOLTAGE "Napięcie" +#define D_WEIGHT "Waga" +#define D_WARMLIGHT "Temperatura światła" +#define D_WEB_SERVER "Serwer Web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "UWAGA Ta wersja nie obsługuje zapisu ustawień" +#define D_LEVEL_10 "poziom 1-0" +#define D_LEVEL_01 "poziom 0-1" +#define D_SERIAL_LOGGING_DISABLED "Wyłączony dziennik na porcie szeregowym" +#define D_SYSLOG_LOGGING_REENABLED "Wznowiono zapis do Syslog" + +#define D_SET_BAUDRATE_TO "Ustaw szybkość transmisji na" +#define D_RECEIVED_TOPIC "Otrzymany temat" +#define D_DATA_SIZE "Wielkość danych" +#define D_ANALOG_INPUT "Wejście analogowe" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Pętla zablokowana" +#define D_WPS_FAILED_WITH_STATUS "Błąd konfiguracji WPS ze statusem" +#define D_ACTIVE_FOR_3_MINUTES "aktywny 3 minuty" +#define D_FAILED_TO_START "nie udało się uruchomić" +#define D_PATCH_ISSUE_2186 "Błąd poprawki 2186" +#define D_CONNECTING_TO_AP "Łączenie z AP" +#define D_IN_MODE "w trybie" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Połączenie nie powiodło się, ponieważ nie otrzymano adresu IP" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Połączenie nie powiodło się, AP nie osiągalny" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Połączenie nie powiodło się, nieprawidlowe hasło" +#define D_CONNECT_FAILED_AP_TIMEOUT "Nie udało się nawiązac połączenia, limit czasu przekroczony" +#define D_ATTEMPTING_CONNECTION "Próba połączenia..." +#define D_CHECKING_CONNECTION "Sprawdzanie połączenia..." +#define D_QUERY_DONE "Zapytanie wykonane" +#define D_MQTT_SERVICE_FOUND "Usługa MQTT została znaleziona" +#define D_FOUND_AT "znaleziono w" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nie znaleziony" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Zapisano do pamięci flash w" +#define D_LOADED_FROM_FLASH_AT "Wczytano z pamięci flash w" +#define D_USE_DEFAULTS "Użyj domyślnych" +#define D_ERASED_SECTOR "Sektor wymazany" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" +#define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" +#define D_WITH_IP_ADDRESS "z adresem IP" +#define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" +#define D_FILE_NOT_FOUND "Plik nie odnaleziony" +#define D_REDIRECTED "Przekierowano do własnego portalu" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Menedżer Wifi ustawia punkt dostępowy i zachowuje stacje" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Menedżer sieci Wi-Fi Access Point" +#define D_TRYING_TO_CONNECT "Próbuję połączyć urzadzenie z siecią" + +#define D_RESTART_IN "Zrestartuj" +#define D_SECONDS "Sekund" +#define D_DEVICE_WILL_RESTART "Urządzenie zrestartuje sie za kilka sekund" +#define D_BUTTON_TOGGLE "Załącz/Wyłącz" +#define D_CONFIGURATION "Konfiguracja" +#define D_INFORMATION "Informacje" +#define D_FIRMWARE_UPGRADE "Aktualizacja oprogramowania" +#define D_CONSOLE "Konsola" +#define D_CONFIRM_RESTART "Potwierdź restart" + +#define D_CONFIGURE_MODULE "Konfiguracja modułu" +#define D_CONFIGURE_WIFI "Konfiguracja WiFi" +#define D_CONFIGURE_MQTT "Konfiguracja MQTT" +#define D_CONFIGURE_DOMOTICZ "Konfiguracja Domoticza" +#define D_CONFIGURE_LOGGING "Konfiguracja dziennika" +#define D_CONFIGURE_OTHER "Inne konfiguracje" +#define D_CONFIRM_RESET_CONFIGURATION "Potwierdź reset ustawień" +#define D_RESET_CONFIGURATION "Reset ustawień" +#define D_BACKUP_CONFIGURATION "Kopia ustawień" +#define D_RESTORE_CONFIGURATION "Przywracanie ustawień" +#define D_MAIN_MENU "Menu główne" + +#define D_MODULE_PARAMETERS "Parametry modułu" +#define D_MODULE_TYPE "Typ" +#define D_PULLUP_ENABLE "Przełącznik pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Wejście rs" +#define D_SERIAL_OUT "Wyjście rs" + +#define D_WIFI_PARAMETERS "Parametry sieci WiFi" +#define D_SCAN_FOR_WIFI_NETWORKS "Skanuj sieci" +#define D_SCAN_DONE "Skanowanie wykonane" +#define D_NO_NETWORKS_FOUND "Nie znaleziono sieci" +#define D_REFRESH_TO_SCAN_AGAIN "Odśwież aby ponownie wyszukać sieci" +#define D_DUPLICATE_ACCESSPOINT "Duplikuj" +#define D_SKIPPING_LOW_QUALITY "Pominięto z powodu niskiej jakości sygnału" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "Nazwa 1" +#define D_AP1_PASSWORD "Hasło 1" +#define D_AP2_SSID "Nazwa 2" +#define D_AP2_PASSWORD "Hasło 2" + +#define D_MQTT_PARAMETERS "Parametry MQTT" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Pełny temat" + +#define D_LOGGING_PARAMETERS "Opcje dziennika" +#define D_SERIAL_LOG_LEVEL "Serial - poziom" +#define D_MQTT_LOG_LEVEL "Mqtt - poziom" +#define D_WEB_LOG_LEVEL "Web - poziom" +#define D_SYS_LOG_LEVEL "System - poziom" +#define D_MORE_DEBUG "Więcej informacji dziennika" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Okres telemetrii" + +#define D_OTHER_PARAMETERS "Inne parametry" +#define D_TEMPLATE "Szablon" +#define D_ACTIVATE "Aktywuj" +#define D_WEB_ADMIN_PASSWORD "Hasło administratora" +#define D_MQTT_ENABLE "Załącz MQTT" +#define D_FRIENDLY_NAME "Nazwa" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Mostek Hue" +#define D_SINGLE_DEVICE "pojedyńcze urządzenie" +#define D_MULTI_DEVICE "multi urządzenie" + +#define D_CONFIGURE_TEMPLATE "Konfiguracja szablonu" +#define D_TEMPLATE_PARAMETERS "Parametry szablonu" +#define D_TEMPLATE_NAME "Nazwa" +#define D_BASE_TYPE "Na bazie" +#define D_TEMPLATE_FLAGS "Opcje" + +#define D_SAVE_CONFIGURATION "Zapisz ustawienia" +#define D_CONFIGURATION_SAVED "Ustawienia zapisane" +#define D_CONFIGURATION_RESET "Ustawienia zresetowane" + +#define D_PROGRAM_VERSION "Wersja oprogramowania" +#define D_BUILD_DATE_AND_TIME "Data kompilacji" +#define D_CORE_AND_SDK_VERSION "Wersja Core/SDK" +#define D_FLASH_WRITE_COUNT "Liczba zapisów do pamięci" +#define D_MAC_ADDRESS "Adres MAC" +#define D_MQTT_HOST "Host" +#define D_MQTT_PORT "Port" +#define D_MQTT_CLIENT "Klient" +#define D_MQTT_USER "Użytkownik" +#define D_MQTT_TOPIC "Temat" +#define D_MQTT_GROUP_TOPIC "Temat grupy" +#define D_MQTT_FULL_TOPIC "Pełny temat" +#define D_MDNS_DISCOVERY "Wykrywanie mDNS" +#define D_MDNS_ADVERTISE "Rozgłaszanie mDNS" +#define D_ESP_CHIP_ID "ID ukladu ESP" +#define D_FLASH_CHIP_ID "ID pamięci flash" +#define D_FLASH_CHIP_SIZE "Rozmiar pamięci flash" +#define D_FREE_PROGRAM_SPACE "Wolna pamięć programu" + +#define D_UPGRADE_BY_WEBSERVER "Aktualizacja z serwera Web" +#define D_OTA_URL "Adres serwera" +#define D_START_UPGRADE "Aktualizuj" +#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja z pliku" +#define D_UPLOAD_STARTED "Wgrywanie rozpoczęte" +#define D_UPGRADE_STARTED "Aktualizacja rozpoczęta" +#define D_UPLOAD_DONE "Wgrywanie zakończone" +#define D_UPLOAD_ERR_1 "Nie wybrano pliku" +#define D_UPLOAD_ERR_2 "Niewystarczająca ilość miejsca" +#define D_UPLOAD_ERR_3 "Magiczny bajt jest inny niz 0xE9" +#define D_UPLOAD_ERR_4 "Rozmiar programu jest większy niż rzeczywisty rozmiar pamięci flash" +#define D_UPLOAD_ERR_5 "Wgrywanie, bufor niezgodności stanu porównywanych bitow" +#define D_UPLOAD_ERR_6 "Błąd wgrywania. Uruchomiono zapis do dziennika na poziomie 3" +#define D_UPLOAD_ERR_7 "Wgrywanie przerwane" +#define D_UPLOAD_ERR_8 "Błędny plik" +#define D_UPLOAD_ERR_9 "Plik jest za duży" +#define D_UPLOAD_ERR_10 "Błąd inicjacji układu RF" +#define D_UPLOAD_ERR_11 "Błąd kasowania układu RF" +#define D_UPLOAD_ERR_12 "Błąd zapisu układu RF" +#define D_UPLOAD_ERR_13 "Błąd dekodowania oprrogramowania układu RF" +#define D_UPLOAD_ERROR_CODE "Błąd wgrywania" + +#define D_ENTER_COMMAND "Wprowadź polecenie" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Włącz poziom 2 zapisu dziennika, jeśli oczekiwana jest odpowiedź" +#define D_NEED_USER_AND_PASSWORD "Wymagany użytkownik=&hasło=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Weryfikuj odcisk TLS..." +#define D_TLS_CONNECT_FAILED_TO "Nieudane połączenie TLS do" +#define D_RETRY_IN "Spróbuj ponownie" +#define D_VERIFIED "Zweryfikowano odcisk" +#define D_INSECURE "Nieprawidłowe połączenie z powodu błędnego odcisku TLS" +#define D_CONNECT_FAILED_TO "Nie udało się nawiązać połączenia" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast wyłączony" +#define D_MULTICAST_REJOINED "Multicast dołączony" +#define D_MULTICAST_JOIN_FAILED "Podłączenie Multicast nie powiodło się" +#define D_FAILED_TO_SEND_RESPONSE "Nie udało się wysłać odpowiedzi" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "Zdarzenie podstawowe" +#define D_WEMO_EVENT_SERVICE "Zdarzenie serwisowe" +#define D_WEMO_META_SERVICE "Meta dane serwisowe" +#define D_WEMO_SETUP "Ustawienia WeMo" +#define D_RESPONSE_SENT "Wyślij odpowiedź" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Ustawienia Hue" +#define D_HUE_API_NOT_IMPLEMENTED "Api nie zaimplementowane" +#define D_HUE_API "API" +#define D_HUE_POST_ARGS "POST argument" +#define D_3_RESPONSE_PACKETS_SENT "3 pakiety odpowiedzi wysyłane" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Klucz Idx" +#define D_DOMOTICZ_SWITCH_IDX "Przełącznik Idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor Idx" + #define D_DOMOTICZ_TEMP "Temperatura" + #define D_DOMOTICZ_TEMP_HUM "Temperatura, Wilgotność" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temperatura, Wilgotność, Ciśnienie" + #define D_DOMOTICZ_POWER_ENERGY "Moc, Energia" + #define D_DOMOTICZ_ILLUMINANCE "Oświetlenie" + #define D_DOMOTICZ_COUNT "Licznik" + #define D_DOMOTICZ_VOLTAGE "Napięcie" + #define D_DOMOTICZ_CURRENT "Prąd" + #define D_DOMOTICZ_AIRQUALITY "Jakość powietrza" + #define D_DOMOTICZ_P1_SMART_METER "Miernik P1" +#define D_DOMOTICZ_UPDATE_TIMER "Aktualizacja zegara" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Konfiguracja harmonogramu" +#define D_TIMER_PARAMETERS "Parametry harmonogramu" +#define D_TIMER_ENABLE "Załącz harmonogram" +#define D_TIMER_ARM "Załącz" +#define D_TIMER_TIME "Czas" +#define D_TIMER_DAYS "Dni" +#define D_TIMER_REPEAT "Powtarzaj" +#define D_TIMER_OUTPUT "Wyjście" +#define D_TIMER_ACTION "Akcja" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Konfiguracja KNX" +#define D_KNX_PARAMETERS "Parametry KNX" +#define D_KNX_GENERAL_CONFIG "Konfiguracja ogólna" +#define D_KNX_PHYSICAL_ADDRESS "Adres fizyczny" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Musi być unikalny w sieci KNX)" +#define D_KNX_ENABLE "Załącz" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Adresy grupowe do zapisu" +#define D_ADD "Dodaj" +#define D_DELETE "Usuń" +#define D_REPLY "Odpowiedz" +#define D_KNX_GROUP_ADDRESS_TO_READ "Adresy grupowe do odbioru" +#define D_RECEIVED_FROM "Odebrane od" +#define D_KNX_COMMAND_WRITE "Zapisz" +#define D_KNX_COMMAND_READ "Czytaj" +#define D_KNX_COMMAND_OTHER "Inna komenda" +#define D_SENT_TO "Wyślij do" +#define D_KNX_WARNING "Adres grupy (0/0/0) jest zarezerwowany i nie można go użyć." +#define D_KNX_ENHANCEMENT "Rozszerzenia" +#define D_KNX_TX_SLOT "Gniazdo TX" +#define D_KNX_RX_SLOT "Gniazdo RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energia dzisiaj" +#define D_ENERGY_YESTERDAY "Energia wczoraj" +#define D_ENERGY_TOTAL "Energia całkowita" + +// xdrv_27_shutter.ino +#define D_OPEN "Otwórz" +#define D_CLOSE "Zamknij" +#define D_DOMOTICZ_SHUTTER "Roleta" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Konfiguracja PCF8574" +#define D_PCF8574_PARAMETERS "Parametry PCF8574" +#define D_INVERT_PORTS "Porty odwrócone" +#define D_DEVICE "Urządzenie" +#define D_DEVICE_INPUT "Wejście" +#define D_DEVICE_OUTPUT "Wyjście" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Czujnik zajęty" +#define D_SENSOR_CRC_ERROR "Błąd CRC czujnika" +#define D_SENSORS_FOUND "Znaleziono czujnik" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Trwa oczekiwanie" +#define D_START_SIGNAL_LOW "Sygnał startowy niski" +#define D_START_SIGNAL_HIGH "Sygnał startowy wysoki" +#define D_PULSE "Impuls" +#define D_CHECKSUM_FAILURE "Błędna suma kontrolna" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Czujnik nie otrzymał komendy ACK" +#define D_SHT1X_FOUND "SHT1X znaleziony" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Cząstki" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Usuń wagę" +#define D_HX_CAL_REFERENCE "Załaduj wagę referencyjną" +#define D_HX_CAL_DONE "Skalibrowany" +#define D_HX_CAL_FAIL "Błąd kalibracji" +#define D_RESET_HX711 "Zresetuj skalę" +#define D_CONFIGURE_HX711 "Skonfiguruj skalę" +#define D_HX711_PARAMETERS "Parametry skali" +#define D_ITEM_WEIGHT "Waga przedmiotu" +#define D_REFERENCE_WEIGHT "Waga referencyjna" +#define D_CALIBRATE "Skalibruj" +#define D_CALIBRATION "Kalibrowanie" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Kierunek" +#define D_TX20_WIND_SPEED "Prędkość" +#define D_TX20_WIND_SPEED_AVG "Średnia prędkość" +#define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Brak" +#define D_SENSOR_USER "Użytkownik" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "Odtearzacz MP3" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Przełącznik" // Suffix "1" +#define D_SENSOR_BUTTON "Przycisk" // Suffix "1" +#define D_SENSOR_RELAY "Przekaźnik" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "Led link" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Licznik" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Podświetlanie" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "Głęboko uśpiony" +#define D_SENSOR_EXS_ENABLE "Załącz EXS" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Godz" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sektory" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Przesunięcie faz" +#define D_IMPORT_ACTIVE "Czynna pobrana" +#define D_EXPORT_ACTIVE "Czynna oddana" +#define D_IMPORT_REACTIVE "Bierna pobrana" +#define D_EXPORT_REACTIVE "Bierna oddana" +#define D_TOTAL_REACTIVE "Bierna całkowita" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "Napięcie PV1" +#define D_PV1_CURRENT "Prąd PV1" +#define D_PV1_POWER "Moc PV1 " +#define D_PV2_VOLTAGE "Napięcie PV2" +#define D_PV2_CURRENT "Prąd PV2" +#define D_PV2_POWER "Moc PV2" +#define D_SOLAR_POWER "Moc PV" +#define D_INVERTER_POWER "Moc invertera" +#define D_STATUS "Status" +#define D_WAITING "Oczekiwanie" +#define D_CHECKING "Sprawdzanie" +#define D_WORKING "Praca" +#define D_FAILURE "Błąd" +#define D_SOLAX_ERROR_0 "Błąd - brak kodu" +#define D_SOLAX_ERROR_1 "Błąd - utrata sieci" +#define D_SOLAX_ERROR_2 "Błąd - napięcie sieci" +#define D_SOLAX_ERROR_3 "Błąd - częstotliwość sieci" +#define D_SOLAX_ERROR_4 "Błąd - napięcie PV" +#define D_SOLAX_ERROR_5 "Błąd - usterka izolacji" +#define D_SOLAX_ERROR_6 "Błąd - przegrzanie" +#define D_SOLAX_ERROR_7 "Błąd - wentylator" +#define D_SOLAX_ERROR_8 "Błąd - inne urządzenie" + +#endif // _LANGUAGE_PL_PL_D_H_ diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 0efa57789..43dc9581b 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -1,701 +1,703 @@ -/* - pt-BR.h - localization for Portuguese - Brazil for Tasmota - - Copyright (C) 2019 Fabiano Bovo - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_PT_BR_H_ -#define _LANGUAGE_PT_BR_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.0.0.1 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1046 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "pt" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DomSegTerQuaQuiSexSab" -#define D_MONTH3LIST "JanFevMarAbrMaiJunJulAgoSepOutNovDez" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Qualidade do ar" -#define D_AP "Ponto de acesso" // Ponto de Acesso -#define D_AS "como" -#define D_AUTO "Auto" -#define D_BLINK "Pulsar" -#define D_BLINKOFF "Pulsar desligado" -#define D_BOOT_COUNT "Contagem de inicialização" -#define D_BRIGHTLIGHT "Brilho" -#define D_BSSID "BSSId" -#define D_BUTTON "Botão" -#define D_BY "por" // Write by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canal" -#define D_CO2 "CO2" -#define D_CODE "Código" // Button code -#define D_COLDLIGHT "Luz fria" -#define D_COMMAND "Comando" -#define D_CONNECTED "Ligado" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Contagem" -#define D_COUNTER "Contador" -#define D_CURRENT "Corrente" // As in Voltage and Current -#define D_DATA "Dados" -#define D_DARKLIGHT "Luz escura" -#define D_DEBUG "Depurar" -#define D_DISABLED "Desabilitado" -#define D_DISTANCE "Distância" -#define D_DNS_SERVER "Servidor DNS" -#define D_DONE "Concluído" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulação" -#define D_ENABLED "Habilitado" -#define D_ERASE "Apagar" -#define D_ERROR "Erro" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Falha" -#define D_FALLBACK "Retornar" -#define D_FALLBACK_TOPIC "Tópico para retornar" -#define D_FALSE "Falso" -#define D_FILE "Arquivo" -#define D_FLOW_RATE "Quociente de vazão" -#define D_FREE_MEMORY "Memória livre" -#define D_FREQUENCY "Frequência" -#define D_GAS "Gás" -#define D_GATEWAY "Gateway" -#define D_GROUP "Grupo" -#define D_HOST "Host" -#define D_HOSTNAME "Nome do Host" -#define D_HUMIDITY "Umidade" -#define D_ILLUMINANCE "Luminância" -#define D_IMMEDIATE "Imediato" // Button immediate -#define D_INDEX "Índice" -#define D_INFO "Informação" -#define D_INFRARED "Infravermelho" -#define D_INITIALIZED "Inicializado" -#define D_IP_ADDRESS "Endereço IP" -#define D_LIGHT "Luz" -#define D_LWT "LWT" -#define D_MODULE "Módulo" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-pressão" -#define D_NOISE "Ruído" -#define D_NONE "Nenhum" -#define D_OFF "Desligado" -#define D_OFFLINE "Desconectado" -#define D_OK "Ok" -#define D_ON "Ligado" -#define D_ONLINE "Conectado" -#define D_PASSWORD "Senha" -#define D_PORT "Porta" -#define D_POWER_FACTOR "Fator de potência" -#define D_POWERUSAGE "Potência" -#define D_POWERUSAGE_ACTIVE "Potência ativa" -#define D_POWERUSAGE_APPARENT "Potência aparente" -#define D_POWERUSAGE_REACTIVE "Potência reativa" -#define D_PRESSURE "Pressão" -#define D_PRESSUREATSEALEVEL "Pressão ao nível do mar" -#define D_PROGRAM_FLASH_SIZE "Tamanho do programa na memória" -#define D_PROGRAM_SIZE "Tamanho do programa" -#define D_PROJECT "Projeto" -#define D_RAIN "Rain" -#define D_RECEIVED "Recebido" -#define D_RESTART "Reiniciar" -#define D_RESTARTING "Reiniciando" -#define D_RESTART_REASON "Motivo do reinício" -#define D_RESTORE "Restauração" -#define D_RETAINED "Manter" -#define D_RULE "Regra" -#define D_SAVE "Salvar" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Iniciar" -#define D_STD_TIME "STD" -#define D_STOP "Parar" -#define D_SUBNET_MASK "Máscara sub rede" -#define D_SUBSCRIBE_TO "Subescrever para" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Successo" -#define D_SUNRISE "Nascer do sol" -#define D_SUNSET "Por do sol" -#define D_TEMPERATURE "Temperatura" -#define D_TO "Para" -#define D_TOGGLE "Inverter" -#define D_TOPIC "Tópico" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Transmitir" -#define D_TRUE "Verdadeiro" -#define D_TVOC "TVOC" -#define D_UPGRADE "atualização" -#define D_UPLOAD "Enviar" -#define D_UPTIME "Tempo de atividade" -#define D_USER "Usuário" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Índice UV" -#define D_UV_INDEX_1 "Baixo" -#define D_UV_INDEX_2 "Médio" -#define D_UV_INDEX_3 "Alto" -#define D_UV_INDEX_4 "Perigro" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Nível UV" -#define D_UV_POWER "UV Power" -#define D_VERSION "Versão" -#define D_VOLTAGE "Voltagem" -#define D_WEIGHT "Peso" -#define D_WARMLIGHT "Luz quente" -#define D_WEB_SERVER "Servidor WEB" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes" -#define D_LEVEL_10 "nível 1-0" -#define D_LEVEL_01 "nível 0-1" -#define D_SERIAL_LOGGING_DISABLED "Registro Serial desabilitado" -#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" - -#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" -#define D_RECEIVED_TOPIC "Tópico recebido" -#define D_DATA_SIZE "Tamanho de dados" -#define D_ANALOG_INPUT "Entrada analógica" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Loop bloqueado" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig falha de estado" -#define D_ACTIVE_FOR_3_MINUTES "Ativo por 3 minutos" -#define D_FAILED_TO_START "Falha ao iníciar" -#define D_PATCH_ISSUE_2186 "Questão 2186" -#define D_CONNECTING_TO_AP "Ligando ao PA" -#define D_IN_MODE "em modo" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "A ligação falhou porque nenhum endereço IP foi recebido" -#define D_CONNECT_FAILED_AP_NOT_REACHED "A ligação falhou porque o PA não pôde ser alcançado" -#define D_CONNECT_FAILED_WRONG_PASSWORD "A ligação falhou porque a senha está incorreta" -#define D_CONNECT_FAILED_AP_TIMEOUT "A ligação falhou porque o tempo foi excedido" -#define D_ATTEMPTING_CONNECTION "Ligando..." -#define D_CHECKING_CONNECTION "Verificando ligação..." -#define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" -#define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" -#define D_FOUND_AT "encontrado em" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog anfitrião não encontrado" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Guardado na flash em" -#define D_LOADED_FROM_FLASH_AT "Lido da flash em" -#define D_USE_DEFAULTS "Usar predefinições" -#define D_ERASED_SECTOR "Apagar setores" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" -#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" -#define D_WITH_IP_ADDRESS "com o endereço IP" -#define D_WEBSERVER_STOPPED "Servidor WEB parou" -#define D_FILE_NOT_FOUND "Arquivo não encontrado" -#define D_REDIRECTED "Redirecionado para o portal ativo" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager: configura o Ponto de Acesso e a Estação" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager: configura o Ponto de Acesso" -#define D_TRYING_TO_CONNECT "Conectar o dispositivo à rede" - -#define D_RESTART_IN "Reinicia em" -#define D_SECONDS "segundos" -#define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" -#define D_BUTTON_TOGGLE "Comandar" -#define D_CONFIGURATION "Configuração" -#define D_INFORMATION "Informação" -#define D_FIRMWARE_UPGRADE "Atualização de Firmware" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Confirmar o reinicio" - -#define D_CONFIGURE_MODULE "Configurar Módulo" -#define D_CONFIGURE_WIFI "Configurar WiFi" -#define D_CONFIGURE_MQTT "Configurar MQTT" -#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" -#define D_CONFIGURE_LOGGING "Configurar Logging" -#define D_CONFIGURE_OTHER "Configurar outras opções" -#define D_CONFIRM_RESET_CONFIGURATION "Confirmar limpeza de configuração" -#define D_RESET_CONFIGURATION "Apagar configuração" -#define D_BACKUP_CONFIGURATION "Salvar configuração" -#define D_RESTORE_CONFIGURATION "Repor configuração" -#define D_MAIN_MENU "Menu principal" - -#define D_MODULE_PARAMETERS "Parâmetros do módulo" -#define D_MODULE_TYPE "Tipo de módulo" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Entrada serial" -#define D_SERIAL_OUT "Saída serial" - -#define D_WIFI_PARAMETERS "Parâmetros do wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Encontrar redes wifi" -#define D_SCAN_DONE "Busca finalizada" -#define D_NO_NETWORKS_FOUND "Sem redes" -#define D_REFRESH_TO_SCAN_AGAIN "Nova busca" -#define D_DUPLICATE_ACCESSPOINT "Ponto de Acesso duplicado" -#define D_SKIPPING_LOW_QUALITY "Ignorado devido à baixa qualidade do sinal" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "Senha AP1" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "Senha AP2" - -#define D_MQTT_PARAMETERS "Parâmetros MQTT" -#define D_CLIENT "Cliente" -#define D_FULL_TOPIC "Tópico completo" - -#define D_LOGGING_PARAMETERS "Parâmetros Logging" -#define D_SERIAL_LOG_LEVEL "Nível de registro serial" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Nível de registro WEB" -#define D_SYS_LOG_LEVEL "Nível de registro Syslog" -#define D_MORE_DEBUG "Depurar mais" -#define D_SYSLOG_HOST "Syslog anfitrião" -#define D_SYSLOG_PORT "Porta Syslog" -#define D_TELEMETRY_PERIOD "Período de telemetria" - -#define D_OTHER_PARAMETERS "Outros parâmetros" -#define D_TEMPLATE "Modelo" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin" -#define D_MQTT_ENABLE "MQTT habilitado" -#define D_FRIENDLY_NAME "Nome amigável" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "Dispositivo único" -#define D_MULTI_DEVICE "Múltiplos dispositivos" - -#define D_CONFIGURE_TEMPLATE "Configurar Modelo" -#define D_TEMPLATE_PARAMETERS "Parâmetros Modelo" -#define D_TEMPLATE_NAME "Nome" -#define D_BASE_TYPE "Baseado em" -#define D_TEMPLATE_FLAGS "Opções" - -#define D_SAVE_CONFIGURATION "Gravar configuração" -#define D_CONFIGURATION_SAVED "Configuração gravada" -#define D_CONFIGURATION_RESET "Reinicialização da configuração" - -#define D_PROGRAM_VERSION "Versão do programa" -#define D_BUILD_DATE_AND_TIME "Data e Hora da compilação" -#define D_CORE_AND_SDK_VERSION "Versão Core/SDK" -#define D_FLASH_WRITE_COUNT "Contagem de gravação flash" -#define D_MAC_ADDRESS "Endereço MAC" -#define D_MQTT_HOST "MQTT Servidor" -#define D_MQTT_PORT "MQTT Porta" -#define D_MQTT_CLIENT "MQTT Cliente" -#define D_MQTT_USER "MQTT Usuário" -#define D_MQTT_TOPIC "MQTT Tópico" -#define D_MQTT_GROUP_TOPIC "MQTT Tópico Grupo" -#define D_MQTT_FULL_TOPIC "MQTT Tópico Completo" -#define D_MDNS_DISCOVERY "Descobrir mDNS" -#define D_MDNS_ADVERTISE "Anunciar mDNS" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Size" -#define D_FREE_PROGRAM_SPACE "Espaço Livre Programa" - -#define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Iniciar atualização" -#define D_UPGRADE_BY_FILE_UPLOAD "Atualização por arquivo local" -#define D_UPLOAD_STARTED "Início do envio" -#define D_UPGRADE_STARTED "Atualização iniciada" -#define D_UPLOAD_DONE "Atualização finalizada" -#define D_UPLOAD_ERR_1 "Nenhum arquivo selecionado" -#define D_UPLOAD_ERR_2 "Não existe memória disponível" -#define D_UPLOAD_ERR_3 "Byte mágico não é 0xE9" -#define D_UPLOAD_ERR_4 "O tamanho do programa é maior do que o tamanho da memória" -#define D_UPLOAD_ERR_5 "Envio buffer miscompare" -#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar logging 3" -#define D_UPLOAD_ERR_7 "Envio cancelado" -#define D_UPLOAD_ERR_8 "Arquivo inválido" -#define D_UPLOAD_ERR_9 "Arquivo muito grande" -#define D_UPLOAD_ERR_10 "Falha ao iniciar chip RF" -#define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF" -#define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF" -#define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF" -#define D_UPLOAD_ERROR_CODE "Código de erro do envio" - -#define D_ENTER_COMMAND "Inserir comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 se resposta esperada" -#define D_NEED_USER_AND_PASSWORD "Necessário user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifique a impressão digital TLS..." -#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" -#define D_RETRY_IN "Tentativa em" -#define D_VERIFIED "Verificado impressão digital " -#define D_INSECURE "Ligação insegura devido à impressão digital inválida" -#define D_CONNECT_FAILED_TO "A ligação falhou ao" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast desabilitado" -#define D_MULTICAST_REJOINED "Multicast (re)ingressou" -#define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" -#define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo evento básico" -#define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" -#define D_WEMO_META_SERVICE "WeMo serviço meta" -#define D_WEMO_SETUP "WeMo configuração" -#define D_RESPONSE_SENT "Resposta enviada" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API nao implementada" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parâmetros Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Chave idx" -#define D_DOMOTICZ_SWITCH_IDX "Interruptor idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Umi" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Umi,Pres" - #define D_DOMOTICZ_POWER_ENERGY "Potência,Energia" - #define D_DOMOTICZ_ILLUMINANCE "Luminância" - #define D_DOMOTICZ_COUNT "Contagem/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltagem/PM2.5" - #define D_DOMOTICZ_CURRENT "Corrente/PM10" - #define D_DOMOTICZ_AIRQUALITY "Qualidade do ar" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Tempo de atualização" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configurar temporizador" -#define D_TIMER_PARAMETERS "Parâmetros" -#define D_TIMER_ENABLE "Habilitar temporizadores" -#define D_TIMER_ARM "Habilitar" -#define D_TIMER_TIME "Horário" -#define D_TIMER_DAYS "Dias" -#define D_TIMER_REPEAT "Repetir" -#define D_TIMER_OUTPUT "Saída" -#define D_TIMER_ACTION "Ação" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configurar KNX" -#define D_KNX_PARAMETERS "Parâmetros KNX" -#define D_KNX_GENERAL_CONFIG "Geral" -#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Deve ser único na rede KNX)" -#define D_KNX_ENABLE "Habilitar KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Endereço do grupo para enviar" -#define D_ADD "Adicionar" -#define D_DELETE "Remover" -#define D_REPLY "Responder" -#define D_KNX_GROUP_ADDRESS_TO_READ "Endereço do grupo para receber" -#define D_RECEIVED_FROM "Recebido de" -#define D_KNX_COMMAND_WRITE "Escrever" -#define D_KNX_COMMAND_READ "Ler" -#define D_KNX_COMMAND_OTHER "Outros" -#define D_SENT_TO "Enviar para" -#define D_KNX_WARNING "O endereço ( 0 / 0 / 0 ) é reservado e não pode ser usado." -#define D_KNX_ENHANCEMENT "Melhoria da comunicação" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Consumo energético de hoje" -#define D_ENERGY_YESTERDAY "Consumo energético de ontem" -#define D_ENERGY_TOTAL "Consumo total de energia" - -// xdrv_27_shutter.ino -#define D_OPEN "Aberta" -#define D_CLOSE "Fechada" -#define D_DOMOTICZ_SHUTTER "Persiana" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configura PCF8574" -#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" -#define D_INVERT_PORTS "Portas Invertidas" -#define D_DEVICE "Dispositivo" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor ocupado" -#define D_SENSOR_CRC_ERROR "Erro sensor CRC" -#define D_SENSORS_FOUND "Sensores encontrados" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" -#define D_START_SIGNAL_LOW "Sinal de início baixo" -#define D_START_SIGNAL_HIGH "Sinal de início elevado" -#define D_PULSE "pulso" -#define D_CHECKSUM_FAILURE "Falha checksum" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" -#define D_SHT1X_FOUND "SHT1X encontrado" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partículas" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remover peso" -#define D_HX_CAL_REFERENCE "Peso de referência de carga" -#define D_HX_CAL_DONE "Calibrado" -#define D_HX_CAL_FAIL "Falha na calibração" -#define D_RESET_HX711 "Redefinir escala" -#define D_CONFIGURE_HX711 "Configurar escala" -#define D_HX711_PARAMETERS "Parâmetros de escala" -#define D_ITEM_WEIGHT "Peso do Item" -#define D_REFERENCE_WEIGHT "Peso de referência" -#define D_CALIBRATE "Calibrar" -#define D_CALIBRATION "Calibração" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direção do vento" -#define D_TX20_WIND_SPEED "Velocidade do vento" -#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" -#define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "L" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Nenhum" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Interruptor" // Suffix "1" -#define D_SENSOR_BUTTON "Botão" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Contador" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Luz de fundo" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "H" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "M" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "setores" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "W/h" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Ângulo de Fase" -#define D_IMPORT_ACTIVE "Importar Ativo" -#define D_EXPORT_ACTIVE "Exportar Ativo" -#define D_IMPORT_REACTIVE "Importar Reativo" -#define D_EXPORT_REACTIVE "Exportar Reativo" -#define D_TOTAL_REACTIVE "Reativo total" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltagem" -#define D_PV1_CURRENT "PV1 Corrente" -#define D_PV1_POWER "PV1 Energia" -#define D_PV2_VOLTAGE "PV2 Voltagem" -#define D_PV2_CURRENT "PV2 Corrente" -#define D_PV2_POWER "PV2 Energia" -#define D_SOLAR_POWER "Energia Solar" -#define D_INVERTER_POWER "Potência do Inversor" -#define D_STATUS "Status" -#define D_WAITING "Esperando" -#define D_CHECKING "Verificando" -#define D_WORKING "Trabalhando" -#define D_FAILURE "Falha" -#define D_SOLAX_ERROR_0 "Nenhum código de erro" -#define D_SOLAX_ERROR_1 "Erro Grid Perdida" -#define D_SOLAX_ERROR_2 "Falha na Tensão da rede" -#define D_SOLAX_ERROR_3 "Falha na Frequência do Grid" -#define D_SOLAX_ERROR_4 "Pv Falha de Tensão" -#define D_SOLAX_ERROR_5 "Falha de Isolamento" -#define D_SOLAX_ERROR_6 "Falha de Temperatura excessiva" -#define D_SOLAX_ERROR_7 "Falha no Ventilador" -#define D_SOLAX_ERROR_8 "Outra falha do dispositivo" - -#endif // _LANGUAGE_PT_BR_H_ +/* + pt-BR.h - localization for Portuguese - Brazil for Tasmota + + Copyright (C) 2019 Fabiano Bovo + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_PT_BR_H_ +#define _LANGUAGE_PT_BR_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.0.0.1 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1046 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "pt" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DomSegTerQuaQuiSexSab" +#define D_MONTH3LIST "JanFevMarAbrMaiJunJulAgoSepOutNovDez" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Qualidade do ar" +#define D_AP "Ponto de acesso" // Ponto de Acesso +#define D_AS "como" +#define D_AUTO "Auto" +#define D_BLINK "Pulsar" +#define D_BLINKOFF "Pulsar desligado" +#define D_BOOT_COUNT "Contagem de inicialização" +#define D_BRIGHTLIGHT "Brilho" +#define D_BSSID "BSSId" +#define D_BUTTON "Botão" +#define D_BY "por" // Write by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "CO2" +#define D_CODE "Código" // Button code +#define D_COLDLIGHT "Luz fria" +#define D_COMMAND "Comando" +#define D_CONNECTED "Ligado" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Contagem" +#define D_COUNTER "Contador" +#define D_CURRENT "Corrente" // As in Voltage and Current +#define D_DATA "Dados" +#define D_DARKLIGHT "Luz escura" +#define D_DEBUG "Depurar" +#define D_DISABLED "Desabilitado" +#define D_DISTANCE "Distância" +#define D_DNS_SERVER "Servidor DNS" +#define D_DONE "Concluído" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulação" +#define D_ENABLED "Habilitado" +#define D_ERASE "Apagar" +#define D_ERROR "Erro" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Falha" +#define D_FALLBACK "Retornar" +#define D_FALLBACK_TOPIC "Tópico para retornar" +#define D_FALSE "Falso" +#define D_FILE "Arquivo" +#define D_FLOW_RATE "Quociente de vazão" +#define D_FREE_MEMORY "Memória livre" +#define D_FREQUENCY "Frequência" +#define D_GAS "Gás" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupo" +#define D_HOST "Host" +#define D_HOSTNAME "Nome do Host" +#define D_HUMIDITY "Umidade" +#define D_ILLUMINANCE "Luminância" +#define D_IMMEDIATE "Imediato" // Button immediate +#define D_INDEX "Índice" +#define D_INFO "Informação" +#define D_INFRARED "Infravermelho" +#define D_INITIALIZED "Inicializado" +#define D_IP_ADDRESS "Endereço IP" +#define D_LIGHT "Luz" +#define D_LWT "LWT" +#define D_MODULE "Módulo" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-pressão" +#define D_NOISE "Ruído" +#define D_NONE "Nenhum" +#define D_OFF "Desligado" +#define D_OFFLINE "Desconectado" +#define D_OK "Ok" +#define D_ON "Ligado" +#define D_ONLINE "Conectado" +#define D_PASSWORD "Senha" +#define D_PORT "Porta" +#define D_POWER_FACTOR "Fator de potência" +#define D_POWERUSAGE "Potência" +#define D_POWERUSAGE_ACTIVE "Potência ativa" +#define D_POWERUSAGE_APPARENT "Potência aparente" +#define D_POWERUSAGE_REACTIVE "Potência reativa" +#define D_PRESSURE "Pressão" +#define D_PRESSUREATSEALEVEL "Pressão ao nível do mar" +#define D_PROGRAM_FLASH_SIZE "Tamanho do programa na memória" +#define D_PROGRAM_SIZE "Tamanho do programa" +#define D_PROJECT "Projeto" +#define D_RAIN "Rain" +#define D_RECEIVED "Recebido" +#define D_RESTART "Reiniciar" +#define D_RESTARTING "Reiniciando" +#define D_RESTART_REASON "Motivo do reinício" +#define D_RESTORE "Restauração" +#define D_RETAINED "Manter" +#define D_RULE "Regra" +#define D_SAVE "Salvar" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Iniciar" +#define D_STD_TIME "STD" +#define D_STOP "Parar" +#define D_SUBNET_MASK "Máscara sub rede" +#define D_SUBSCRIBE_TO "Subescrever para" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Successo" +#define D_SUNRISE "Nascer do sol" +#define D_SUNSET "Por do sol" +#define D_TEMPERATURE "Temperatura" +#define D_TO "Para" +#define D_TOGGLE "Inverter" +#define D_TOPIC "Tópico" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Transmitir" +#define D_TRUE "Verdadeiro" +#define D_TVOC "TVOC" +#define D_UPGRADE "atualização" +#define D_UPLOAD "Enviar" +#define D_UPTIME "Tempo de atividade" +#define D_USER "Usuário" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Índice UV" +#define D_UV_INDEX_1 "Baixo" +#define D_UV_INDEX_2 "Médio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Perigro" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Nível UV" +#define D_UV_POWER "UV Power" +#define D_VERSION "Versão" +#define D_VOLTAGE "Voltagem" +#define D_WEIGHT "Peso" +#define D_WARMLIGHT "Luz quente" +#define D_WEB_SERVER "Servidor WEB" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes" +#define D_LEVEL_10 "nível 1-0" +#define D_LEVEL_01 "nível 0-1" +#define D_SERIAL_LOGGING_DISABLED "Registro Serial desabilitado" +#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" + +#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" +#define D_RECEIVED_TOPIC "Tópico recebido" +#define D_DATA_SIZE "Tamanho de dados" +#define D_ANALOG_INPUT "Entrada analógica" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Loop bloqueado" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig falha de estado" +#define D_ACTIVE_FOR_3_MINUTES "Ativo por 3 minutos" +#define D_FAILED_TO_START "Falha ao iníciar" +#define D_PATCH_ISSUE_2186 "Questão 2186" +#define D_CONNECTING_TO_AP "Ligando ao PA" +#define D_IN_MODE "em modo" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "A ligação falhou porque nenhum endereço IP foi recebido" +#define D_CONNECT_FAILED_AP_NOT_REACHED "A ligação falhou porque o PA não pôde ser alcançado" +#define D_CONNECT_FAILED_WRONG_PASSWORD "A ligação falhou porque a senha está incorreta" +#define D_CONNECT_FAILED_AP_TIMEOUT "A ligação falhou porque o tempo foi excedido" +#define D_ATTEMPTING_CONNECTION "Ligando..." +#define D_CHECKING_CONNECTION "Verificando ligação..." +#define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" +#define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" +#define D_FOUND_AT "encontrado em" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog anfitrião não encontrado" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Guardado na flash em" +#define D_LOADED_FROM_FLASH_AT "Lido da flash em" +#define D_USE_DEFAULTS "Usar predefinições" +#define D_ERASED_SECTOR "Apagar setores" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" +#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" +#define D_WITH_IP_ADDRESS "com o endereço IP" +#define D_WEBSERVER_STOPPED "Servidor WEB parou" +#define D_FILE_NOT_FOUND "Arquivo não encontrado" +#define D_REDIRECTED "Redirecionado para o portal ativo" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager: configura o Ponto de Acesso e a Estação" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager: configura o Ponto de Acesso" +#define D_TRYING_TO_CONNECT "Conectar o dispositivo à rede" + +#define D_RESTART_IN "Reinicia em" +#define D_SECONDS "segundos" +#define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" +#define D_BUTTON_TOGGLE "Comandar" +#define D_CONFIGURATION "Configuração" +#define D_INFORMATION "Informação" +#define D_FIRMWARE_UPGRADE "Atualização de Firmware" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Confirmar o reinicio" + +#define D_CONFIGURE_MODULE "Configurar Módulo" +#define D_CONFIGURE_WIFI "Configurar WiFi" +#define D_CONFIGURE_MQTT "Configurar MQTT" +#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" +#define D_CONFIGURE_LOGGING "Configurar Logging" +#define D_CONFIGURE_OTHER "Configurar outras opções" +#define D_CONFIRM_RESET_CONFIGURATION "Confirmar limpeza de configuração" +#define D_RESET_CONFIGURATION "Apagar configuração" +#define D_BACKUP_CONFIGURATION "Salvar configuração" +#define D_RESTORE_CONFIGURATION "Repor configuração" +#define D_MAIN_MENU "Menu principal" + +#define D_MODULE_PARAMETERS "Parâmetros do módulo" +#define D_MODULE_TYPE "Tipo de módulo" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Entrada serial" +#define D_SERIAL_OUT "Saída serial" + +#define D_WIFI_PARAMETERS "Parâmetros do wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Encontrar redes wifi" +#define D_SCAN_DONE "Busca finalizada" +#define D_NO_NETWORKS_FOUND "Sem redes" +#define D_REFRESH_TO_SCAN_AGAIN "Nova busca" +#define D_DUPLICATE_ACCESSPOINT "Ponto de Acesso duplicado" +#define D_SKIPPING_LOW_QUALITY "Ignorado devido à baixa qualidade do sinal" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "Senha AP1" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "Senha AP2" + +#define D_MQTT_PARAMETERS "Parâmetros MQTT" +#define D_CLIENT "Cliente" +#define D_FULL_TOPIC "Tópico completo" + +#define D_LOGGING_PARAMETERS "Parâmetros Logging" +#define D_SERIAL_LOG_LEVEL "Nível de registro serial" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Nível de registro WEB" +#define D_SYS_LOG_LEVEL "Nível de registro Syslog" +#define D_MORE_DEBUG "Depurar mais" +#define D_SYSLOG_HOST "Syslog anfitrião" +#define D_SYSLOG_PORT "Porta Syslog" +#define D_TELEMETRY_PERIOD "Período de telemetria" + +#define D_OTHER_PARAMETERS "Outros parâmetros" +#define D_TEMPLATE "Modelo" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin" +#define D_MQTT_ENABLE "MQTT habilitado" +#define D_FRIENDLY_NAME "Nome amigável" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "Dispositivo único" +#define D_MULTI_DEVICE "Múltiplos dispositivos" + +#define D_CONFIGURE_TEMPLATE "Configurar Modelo" +#define D_TEMPLATE_PARAMETERS "Parâmetros Modelo" +#define D_TEMPLATE_NAME "Nome" +#define D_BASE_TYPE "Baseado em" +#define D_TEMPLATE_FLAGS "Opções" + +#define D_SAVE_CONFIGURATION "Gravar configuração" +#define D_CONFIGURATION_SAVED "Configuração gravada" +#define D_CONFIGURATION_RESET "Reinicialização da configuração" + +#define D_PROGRAM_VERSION "Versão do programa" +#define D_BUILD_DATE_AND_TIME "Data e Hora da compilação" +#define D_CORE_AND_SDK_VERSION "Versão Core/SDK" +#define D_FLASH_WRITE_COUNT "Contagem de gravação flash" +#define D_MAC_ADDRESS "Endereço MAC" +#define D_MQTT_HOST "MQTT Servidor" +#define D_MQTT_PORT "MQTT Porta" +#define D_MQTT_CLIENT "MQTT Cliente" +#define D_MQTT_USER "MQTT Usuário" +#define D_MQTT_TOPIC "MQTT Tópico" +#define D_MQTT_GROUP_TOPIC "MQTT Tópico Grupo" +#define D_MQTT_FULL_TOPIC "MQTT Tópico Completo" +#define D_MDNS_DISCOVERY "Descobrir mDNS" +#define D_MDNS_ADVERTISE "Anunciar mDNS" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash Size" +#define D_FREE_PROGRAM_SPACE "Espaço Livre Programa" + +#define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Iniciar atualização" +#define D_UPGRADE_BY_FILE_UPLOAD "Atualização por arquivo local" +#define D_UPLOAD_STARTED "Início do envio" +#define D_UPGRADE_STARTED "Atualização iniciada" +#define D_UPLOAD_DONE "Atualização finalizada" +#define D_UPLOAD_ERR_1 "Nenhum arquivo selecionado" +#define D_UPLOAD_ERR_2 "Não existe memória disponível" +#define D_UPLOAD_ERR_3 "Byte mágico não é 0xE9" +#define D_UPLOAD_ERR_4 "O tamanho do programa é maior do que o tamanho da memória" +#define D_UPLOAD_ERR_5 "Envio buffer miscompare" +#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar logging 3" +#define D_UPLOAD_ERR_7 "Envio cancelado" +#define D_UPLOAD_ERR_8 "Arquivo inválido" +#define D_UPLOAD_ERR_9 "Arquivo muito grande" +#define D_UPLOAD_ERR_10 "Falha ao iniciar chip RF" +#define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF" +#define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF" +#define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF" +#define D_UPLOAD_ERROR_CODE "Código de erro do envio" + +#define D_ENTER_COMMAND "Inserir comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 se resposta esperada" +#define D_NEED_USER_AND_PASSWORD "Necessário user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifique a impressão digital TLS..." +#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" +#define D_RETRY_IN "Tentativa em" +#define D_VERIFIED "Verificado impressão digital " +#define D_INSECURE "Ligação insegura devido à impressão digital inválida" +#define D_CONNECT_FAILED_TO "A ligação falhou ao" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast desabilitado" +#define D_MULTICAST_REJOINED "Multicast (re)ingressou" +#define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" +#define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo evento básico" +#define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" +#define D_WEMO_META_SERVICE "WeMo serviço meta" +#define D_WEMO_SETUP "WeMo configuração" +#define D_RESPONSE_SENT "Resposta enviada" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API nao implementada" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parâmetros Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Chave idx" +#define D_DOMOTICZ_SWITCH_IDX "Interruptor idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Umi" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Umi,Pres" + #define D_DOMOTICZ_POWER_ENERGY "Potência,Energia" + #define D_DOMOTICZ_ILLUMINANCE "Luminância" + #define D_DOMOTICZ_COUNT "Contagem/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltagem/PM2.5" + #define D_DOMOTICZ_CURRENT "Corrente/PM10" + #define D_DOMOTICZ_AIRQUALITY "Qualidade do ar" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Tempo de atualização" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configurar temporizador" +#define D_TIMER_PARAMETERS "Parâmetros" +#define D_TIMER_ENABLE "Habilitar temporizadores" +#define D_TIMER_ARM "Habilitar" +#define D_TIMER_TIME "Horário" +#define D_TIMER_DAYS "Dias" +#define D_TIMER_REPEAT "Repetir" +#define D_TIMER_OUTPUT "Saída" +#define D_TIMER_ACTION "Ação" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configurar KNX" +#define D_KNX_PARAMETERS "Parâmetros KNX" +#define D_KNX_GENERAL_CONFIG "Geral" +#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Deve ser único na rede KNX)" +#define D_KNX_ENABLE "Habilitar KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Endereço do grupo para enviar" +#define D_ADD "Adicionar" +#define D_DELETE "Remover" +#define D_REPLY "Responder" +#define D_KNX_GROUP_ADDRESS_TO_READ "Endereço do grupo para receber" +#define D_RECEIVED_FROM "Recebido de" +#define D_KNX_COMMAND_WRITE "Escrever" +#define D_KNX_COMMAND_READ "Ler" +#define D_KNX_COMMAND_OTHER "Outros" +#define D_SENT_TO "Enviar para" +#define D_KNX_WARNING "O endereço ( 0 / 0 / 0 ) é reservado e não pode ser usado." +#define D_KNX_ENHANCEMENT "Melhoria da comunicação" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Consumo energético de hoje" +#define D_ENERGY_YESTERDAY "Consumo energético de ontem" +#define D_ENERGY_TOTAL "Consumo total de energia" + +// xdrv_27_shutter.ino +#define D_OPEN "Aberta" +#define D_CLOSE "Fechada" +#define D_DOMOTICZ_SHUTTER "Persiana" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configura PCF8574" +#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" +#define D_INVERT_PORTS "Portas Invertidas" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor ocupado" +#define D_SENSOR_CRC_ERROR "Erro sensor CRC" +#define D_SENSORS_FOUND "Sensores encontrados" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" +#define D_START_SIGNAL_LOW "Sinal de início baixo" +#define D_START_SIGNAL_HIGH "Sinal de início elevado" +#define D_PULSE "pulso" +#define D_CHECKSUM_FAILURE "Falha checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" +#define D_SHT1X_FOUND "SHT1X encontrado" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partículas" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remover peso" +#define D_HX_CAL_REFERENCE "Peso de referência de carga" +#define D_HX_CAL_DONE "Calibrado" +#define D_HX_CAL_FAIL "Falha na calibração" +#define D_RESET_HX711 "Redefinir escala" +#define D_CONFIGURE_HX711 "Configurar escala" +#define D_HX711_PARAMETERS "Parâmetros de escala" +#define D_ITEM_WEIGHT "Peso do Item" +#define D_REFERENCE_WEIGHT "Peso de referência" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibração" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direção do vento" +#define D_TX20_WIND_SPEED "Velocidade do vento" +#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" +#define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "L" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Nenhum" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Interruptor" // Suffix "1" +#define D_SENSOR_BUTTON "Botão" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Contador" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Luz de fundo" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "H" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "M" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "setores" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "W/h" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Ângulo de Fase" +#define D_IMPORT_ACTIVE "Importar Ativo" +#define D_EXPORT_ACTIVE "Exportar Ativo" +#define D_IMPORT_REACTIVE "Importar Reativo" +#define D_EXPORT_REACTIVE "Exportar Reativo" +#define D_TOTAL_REACTIVE "Reativo total" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltagem" +#define D_PV1_CURRENT "PV1 Corrente" +#define D_PV1_POWER "PV1 Energia" +#define D_PV2_VOLTAGE "PV2 Voltagem" +#define D_PV2_CURRENT "PV2 Corrente" +#define D_PV2_POWER "PV2 Energia" +#define D_SOLAR_POWER "Energia Solar" +#define D_INVERTER_POWER "Potência do Inversor" +#define D_STATUS "Status" +#define D_WAITING "Esperando" +#define D_CHECKING "Verificando" +#define D_WORKING "Trabalhando" +#define D_FAILURE "Falha" +#define D_SOLAX_ERROR_0 "Nenhum código de erro" +#define D_SOLAX_ERROR_1 "Erro Grid Perdida" +#define D_SOLAX_ERROR_2 "Falha na Tensão da rede" +#define D_SOLAX_ERROR_3 "Falha na Frequência do Grid" +#define D_SOLAX_ERROR_4 "Pv Falha de Tensão" +#define D_SOLAX_ERROR_5 "Falha de Isolamento" +#define D_SOLAX_ERROR_6 "Falha de Temperatura excessiva" +#define D_SOLAX_ERROR_7 "Falha no Ventilador" +#define D_SOLAX_ERROR_8 "Outra falha do dispositivo" + +#endif // _LANGUAGE_PT_BR_H_ diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index a6299c0c8..e9a08c753 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -1,701 +1,703 @@ -/* - pt-PT.h - localization for Portuguese - Portugal for Tasmota - - Copyright (C) 2019 Paulo Paiva - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_PT_PT_H_ -#define _LANGUAGE_PT_PT_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.0.0.1 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 2070 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "pt" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DomSegTerQuaQuiSexSab" -#define D_MONTH3LIST "JanFevMarAbrMaiJunJulAgoSepOutNovDez" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Qualidade do Ar" -#define D_AP "AP" // Ponto de Acesso -#define D_AS "como" -#define D_AUTO "AUTO" -#define D_BLINK "Piscar" -#define D_BLINKOFF "Piscar Desligado" -#define D_BOOT_COUNT "Contagem de Inicialização" -#define D_BRIGHTLIGHT "Brilho" -#define D_BSSID "BSSId" -#define D_BUTTON "Botão" -#define D_BY "por" // Write by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canal" -#define D_CO2 "Dioxido de Carbono" -#define D_CODE "Código" // Button code -#define D_COLDLIGHT "Luz Fria" -#define D_COMMAND "Comando" -#define D_CONNECTED "Ligado" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Contagem" -#define D_COUNTER "Contador" -#define D_CURRENT "Corrente" // As in Voltage and Current -#define D_DATA "Dados" -#define D_DARKLIGHT "Luz Escura" -#define D_DEBUG "Depurar" -#define D_DISABLED "Disabilitado" -#define D_DISTANCE "Distância" -#define D_DNS_SERVER "Servidor DNS" -#define D_DONE "Concluído" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulação" -#define D_ENABLED "Habilitado" -#define D_ERASE "Apagar" -#define D_ERROR "Erro" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Falha" -#define D_FALLBACK "Retornar" -#define D_FALLBACK_TOPIC "Tópico para retornar" -#define D_FALSE "Falso" -#define D_FILE "Ficheiro" -#define D_FLOW_RATE "Taxa de Fluxo" -#define D_FREE_MEMORY "Memoria Livre" -#define D_FREQUENCY "Frequência" -#define D_GAS "Gás" -#define D_GATEWAY "Gateway" -#define D_GROUP "Grupo" -#define D_HOST "Anfitrião" -#define D_HOSTNAME "Nome Anfitrião" -#define D_HUMIDITY "Humidade" -#define D_ILLUMINANCE "Luminâcia" -#define D_IMMEDIATE "Immediato" // Button immediate -#define D_INDEX "Indíce" -#define D_INFO "Info" -#define D_INFRARED "Infravermelho" -#define D_INITIALIZED "Inicializado" -#define D_IP_ADDRESS "Endereço IP" -#define D_LIGHT "Luz" -#define D_LWT "LWT" -#define D_MODULE "Módulo" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-pressão" -#define D_NOISE "Ruído" -#define D_NONE "Nenhum" -#define D_OFF "Off" -#define D_OFFLINE "Desconetado" -#define D_OK "Ok" -#define D_ON "On" -#define D_ONLINE "Conetado" -#define D_PASSWORD "Palavra Chave" -#define D_PORT "Porta" -#define D_POWER_FACTOR "Factor de Potência" -#define D_POWERUSAGE "Potência" -#define D_POWERUSAGE_ACTIVE "Potência Ativa" -#define D_POWERUSAGE_APPARENT "Potência Aparente" -#define D_POWERUSAGE_REACTIVE "Potência Reativa" -#define D_PRESSURE "Pressão" -#define D_PRESSUREATSEALEVEL "Pressão ao nível do Mar" -#define D_PROGRAM_FLASH_SIZE "Tamanho do Programa na Flash" -#define D_PROGRAM_SIZE "Tamanho do Programa" -#define D_PROJECT "Projeto" -#define D_RAIN "Chuva" -#define D_RECEIVED "Recebido" -#define D_RESTART "Reiniciar" -#define D_RESTARTING "A reiniciar" -#define D_RESTART_REASON "Razão do reinicio" -#define D_RESTORE "Restauro" -#define D_RETAINED "Manter" -#define D_RULE "Regra" -#define D_SAVE "Guardar" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Início" -#define D_STD_TIME "STD" -#define D_STOP "Parar" -#define D_SUBNET_MASK "Mascara sub rede" -#define D_SUBSCRIBE_TO "Subscrever" -#define D_UNSUBSCRIBE_FROM "Cancelar subscrição de" -#define D_SUCCESSFUL "Successo" -#define D_SUNRISE "Nascer do Sol" -#define D_SUNSET "Pôr do Sol" -#define D_TEMPERATURE "Temperatura" -#define D_TO "para" -#define D_TOGGLE "Pressionar" -#define D_TOPIC "Tópico" -#define D_TOTAL_USAGE "Uso total" -#define D_TRANSMIT "Transmitir" -#define D_TRUE "Verdadeiro" -#define D_TVOC "TVOC" -#define D_UPGRADE "Atualizar" -#define D_UPLOAD "Enviar" -#define D_UPTIME "Tempo de Atividade" -#define D_USER "Utilizador" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Indíce UV" -#define D_UV_INDEX_1 "Baixo" -#define D_UV_INDEX_2 "Médio" -#define D_UV_INDEX_3 "Elevado" -#define D_UV_INDEX_4 "Perigoso" -#define D_UV_INDEX_5 "QueimaduraL1/2" -#define D_UV_INDEX_6 "QueimaduraL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Nível UV" -#define D_UV_POWER "Poder UV" -#define D_VERSION "Versão" -#define D_VOLTAGE "Voltagem" -#define D_WEIGHT "Peso" -#define D_WARMLIGHT "Luz Quente" -#define D_WEB_SERVER "Servidor WEB" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "AVISO esta versão não supporta configurações persistentes" -#define D_LEVEL_10 "nível 1-0" -#define D_LEVEL_01 "nível 0-1" -#define D_SERIAL_LOGGING_DISABLED "Registro de porta série desabilitado" -#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" - -#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" -#define D_RECEIVED_TOPIC "Topico Recebido" -#define D_DATA_SIZE "Tamanho de Dados" -#define D_ANALOG_INPUT "Entrada Analógica" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Loop Bloqueado" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALHOU com estado" -#define D_ACTIVE_FOR_3_MINUTES "ativo por 3 minutos" -#define D_FAILED_TO_START "Falha ao iníciar" -#define D_PATCH_ISSUE_2186 "Questão 2186" -#define D_CONNECTING_TO_AP "Ligando ao AP" -#define D_IN_MODE "em modo" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "A ligação falhou porque nenhum endereço IP foi recebido" -#define D_CONNECT_FAILED_AP_NOT_REACHED "A ligação falhou porque o AP não pode ser alcançado" -#define D_CONNECT_FAILED_WRONG_PASSWORD "A ligação falhou porque a palavra chave está incorreta" -#define D_CONNECT_FAILED_AP_TIMEOUT "A ligação falhou porque o tempo excedeu" -#define D_ATTEMPTING_CONNECTION "A ligar..." -#define D_CHECKING_CONNECTION "A verificar ligação..." -#define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" -#define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" -#define D_FOUND_AT "encontrado em" -#define D_SYSLOG_HOST_NOT_FOUND "Anfitrião Syslog não encontrado" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Guardado na flash em" -#define D_LOADED_FROM_FLASH_AT "Lido da flash em" -#define D_USE_DEFAULTS "Usar predefinições" -#define D_ERASED_SECTOR "Apagado setor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Para utilizar o Tasmota, por favor ative o JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
Por favor atualize" -#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" -#define D_WITH_IP_ADDRESS "com o endereço IP" -#define D_WEBSERVER_STOPPED "Servitor WEB parou" -#define D_FILE_NOT_FOUND "Ficheiro não encontrado" -#define D_REDIRECTED "Redirecionado para o portal ativo" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager configura o Ponto de Acesso e mantem a Estação" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager configura o Ponto de Acesso" -#define D_TRYING_TO_CONNECT "A tentar ligar o dispositivo à rede" - -#define D_RESTART_IN "Reinicia em" -#define D_SECONDS "segundos" -#define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" -#define D_BUTTON_TOGGLE "Alternar" -#define D_CONFIGURATION "Configuração" -#define D_INFORMATION "Informação" -#define D_FIRMWARE_UPGRADE "Atualização de Firmware" -#define D_CONSOLE "Consola" -#define D_CONFIRM_RESTART "Confirmar o reinício" - -#define D_CONFIGURE_MODULE "Configurar Módulo" -#define D_CONFIGURE_WIFI "Configurar WiFi" -#define D_CONFIGURE_MQTT "Configurar MQTT" -#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" -#define D_CONFIGURE_LOGGING "Configurar registro" -#define D_CONFIGURE_OTHER "Configurar outras opções" -#define D_CONFIRM_RESET_CONFIGURATION "Confirme o reinício da configuração" -#define D_RESET_CONFIGURATION "Apagar configuração" -#define D_BACKUP_CONFIGURATION "Guardar configuração" -#define D_RESTORE_CONFIGURATION "Repor configuração" -#define D_MAIN_MENU "Menu Principal" - -#define D_MODULE_PARAMETERS "Parametros do Módulo" -#define D_MODULE_TYPE "Tipo de Módulo" -#define D_PULLUP_ENABLE "Sem pull-up de Botão/Interruptor" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Entrada de porta série" -#define D_SERIAL_OUT "Saída de porta série" - -#define D_WIFI_PARAMETERS "Parametros Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Procurar redes Wifi" -#define D_SCAN_DONE "Pesquisa terminada" -#define D_NO_NETWORKS_FOUND "Sem redes encontradas" -#define D_REFRESH_TO_SCAN_AGAIN "Atualize para realizar nova pesquisa" -#define D_DUPLICATE_ACCESSPOINT "Duplicar ponto de Acesso" -#define D_SKIPPING_LOW_QUALITY "Ignorado devido a baixa qualidade do sinal" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "SSId do AP1" -#define D_AP1_PASSWORD "Palavra Chave do AP1" -#define D_AP2_SSID "SSId do AP2" -#define D_AP2_PASSWORD "Palavra Chave do AP2" - -#define D_MQTT_PARAMETERS "Parametros MQTT" -#define D_CLIENT "Cliente" -#define D_FULL_TOPIC "Tópico completo" - -#define D_LOGGING_PARAMETERS "Parametros para registro" -#define D_SERIAL_LOG_LEVEL "Nível de registro na porta série" -#define D_MQTT_LOG_LEVEL "Nível de registro MQTT" -#define D_WEB_LOG_LEVEL "Nível de registro WEB" -#define D_SYS_LOG_LEVEL "Nível de registro do Syslog" -#define D_MORE_DEBUG "Depurar mais" -#define D_SYSLOG_HOST "Anfitrião Syslog" -#define D_SYSLOG_PORT "Porta Syslog" -#define D_TELEMETRY_PERIOD "Período de Telemetria" - -#define D_OTHER_PARAMETERS "Outros parametros" -#define D_TEMPLATE "Modelo" -#define D_ACTIVATE "Ativar" -#define D_WEB_ADMIN_PASSWORD "Palavra Chave do Admin WEB" -#define D_MQTT_ENABLE "MQTT habilitado" -#define D_FRIENDLY_NAME "Nome amigável" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "dispositivo único" -#define D_MULTI_DEVICE "dispositivo múltiplo" - -#define D_CONFIGURE_TEMPLATE "Configurar Modelo" -#define D_TEMPLATE_PARAMETERS "Parametros do Modelo" -#define D_TEMPLATE_NAME "Nome do Modelo" -#define D_BASE_TYPE "Baseado em" -#define D_TEMPLATE_FLAGS "Opções" - -#define D_SAVE_CONFIGURATION "Guardar configuração" -#define D_CONFIGURATION_SAVED "Configuração guardada" -#define D_CONFIGURATION_RESET "Reinicializar a configuração" - -#define D_PROGRAM_VERSION "Versão do Programa" -#define D_BUILD_DATE_AND_TIME "Data e Hora de criação" -#define D_CORE_AND_SDK_VERSION "Versão Core/SDK" -#define D_FLASH_WRITE_COUNT "Contagem de gravação da flash" -#define D_MAC_ADDRESS "Endereço MAC" -#define D_MQTT_HOST "Servidor MQTT" -#define D_MQTT_PORT "Porta MQTT" -#define D_MQTT_CLIENT "Cliente MQTT" -#define D_MQTT_USER "Utilizador MQTT" -#define D_MQTT_TOPIC "Tópico MQTT" -#define D_MQTT_GROUP_TOPIC "Tópico MQTT de Grupo" -#define D_MQTT_FULL_TOPIC "Tópico MQTT Completo" -#define D_MDNS_DISCOVERY "Descobrir mDNS" -#define D_MDNS_ADVERTISE "Anunciar mDNS" -#define D_ESP_CHIP_ID "ID do chip ESP" -#define D_FLASH_CHIP_ID "ID do chip da Flash" -#define D_FLASH_CHIP_SIZE "Tamanho da Flash" -#define D_FREE_PROGRAM_SPACE "Espaço de Programa Livre" - -#define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" -#define D_OTA_URL "Url OTA" -#define D_START_UPGRADE "Iniciar atualização" -#define D_UPGRADE_BY_FILE_UPLOAD "Atualizar por envio de ficheiro" -#define D_UPLOAD_STARTED "Envio Iniciado" -#define D_UPGRADE_STARTED "Atualização Iniciada" -#define D_UPLOAD_DONE "Atualização Finalizada" -#define D_UPLOAD_ERR_1 "Nenhum ficheiro selecionado" -#define D_UPLOAD_ERR_2 "Não existe espaço disponível" -#define D_UPLOAD_ERR_3 "O Byte mágico não é 0xE9" -#define D_UPLOAD_ERR_4 "O tamanho do programa e maior do que o tamanho real da flash" -#define D_UPLOAD_ERR_5 "Comparação incorreta do buffer de upload" -#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar registro 3" -#define D_UPLOAD_ERR_7 "Envio cancelado" -#define D_UPLOAD_ERR_8 "Ficheiro inválido" -#define D_UPLOAD_ERR_9 "Ficheiro demasiado grande" -#define D_UPLOAD_ERR_10 "Falha ao iniciar o chip de RF" -#define D_UPLOAD_ERR_11 "Falha ao apagar o chip de RF" -#define D_UPLOAD_ERR_12 "Falha ao escrever no chip de RF" -#define D_UPLOAD_ERR_13 "Falha ao descodificar o firmware RF" -#define D_UPLOAD_ERROR_CODE "Código de erro do envio" - -#define D_ENTER_COMMAND "Inserir comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 se resposta esperada" -#define D_NEED_USER_AND_PASSWORD "Necessário user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifique a impressão digital TLS..." -#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" -#define D_RETRY_IN "Nova tentativa em" -#define D_VERIFIED "Verificado usando impressão digital" -#define D_INSECURE "Ligação insegura devido à impressão digital inválida" -#define D_CONNECT_FAILED_TO "A ligação falhou ao" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast desabilitado" -#define D_MULTICAST_REJOINED "Multicast (re)ingressado" -#define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" -#define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo evento básico" -#define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" -#define D_WEMO_META_SERVICE "WeMo serviço meta" -#define D_WEMO_SETUP "WeMo configuração" -#define D_RESPONSE_SENT "Resposta enviada" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Configuração do Hue" -#define D_HUE_API_NOT_IMPLEMENTED "API Hue nao implementada" -#define D_HUE_API "API Hue" -#define D_HUE_POST_ARGS "Argumentos de POST HUE" -#define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parametros Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Chave idx" -#define D_DOMOTICZ_SWITCH_IDX "Interruptor idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Potência,Energia" - #define D_DOMOTICZ_ILLUMINANCE "Luminâcia" - #define D_DOMOTICZ_COUNT "Contagem/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltagem/PM2.5" - #define D_DOMOTICZ_CURRENT "Corrente/PM10" - #define D_DOMOTICZ_AIRQUALITY "Qualidade do Ar" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Temporizador de atualização" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configurar temporizador" -#define D_TIMER_PARAMETERS "Parâmetros do temporizador" -#define D_TIMER_ENABLE "Habilitar Temporizadores" -#define D_TIMER_ARM "Armar" -#define D_TIMER_TIME "Tempo" -#define D_TIMER_DAYS "Dias" -#define D_TIMER_REPEAT "Repetir" -#define D_TIMER_OUTPUT "Aaída" -#define D_TIMER_ACTION "Açao" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configurar KNX" -#define D_KNX_PARAMETERS "Parâmetros KNX" -#define D_KNX_GENERAL_CONFIG "Geral" -#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve ser exclusivo na rede KNX )" -#define D_KNX_ENABLE "Habilitar KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dados para enviar para Endereços de Grupo" -#define D_ADD "Adicionar" -#define D_DELETE "Remover" -#define D_REPLY "Responder" -#define D_KNX_GROUP_ADDRESS_TO_READ "Endereços de Grupo de onde receber dados" -#define D_RECEIVED_FROM "Recebido de" -#define D_KNX_COMMAND_WRITE "Escrever" -#define D_KNX_COMMAND_READ "Ler" -#define D_KNX_COMMAND_OTHER "Outro" -#define D_SENT_TO "enviar para" -#define D_KNX_WARNING "O Endereço de Grupo ( 0 / 0 / 0 ) está reservado e não pode ser usado." -#define D_KNX_ENHANCEMENT "Melhoria de Comunicação" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Consumo energético de hoje" -#define D_ENERGY_YESTERDAY "Consumo energético de ontem" -#define D_ENERGY_TOTAL "Consumo energético total" - -// xdrv_27_shutter.ino -#define D_OPEN "Abrir" -#define D_CLOSE "Fechar" -#define D_DOMOTICZ_SHUTTER "Estore" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configurar PCF8574" -#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" -#define D_INVERT_PORTS "Inverter Portas" -#define D_DEVICE "Dispositivo" -#define D_DEVICE_INPUT "Entrada" -#define D_DEVICE_OUTPUT "Saída" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor ocupado" -#define D_SENSOR_CRC_ERROR "Erro no CRC do sensor" -#define D_SENSORS_FOUND "Sensores encontrados" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" -#define D_START_SIGNAL_LOW "Sinal de início baixo" -#define D_START_SIGNAL_HIGH "Sinal de início elevado" -#define D_PULSE "pulso" -#define D_CHECKSUM_FAILURE "Falha na soma de verificação" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" -#define D_SHT1X_FOUND "SHT1X encontrado" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partículas" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remover peso" -#define D_HX_CAL_REFERENCE "Carregar peso de referência" -#define D_HX_CAL_DONE "Calibrado" -#define D_HX_CAL_FAIL "Falha na calibração" -#define D_RESET_HX711 "Reiniciar balança" -#define D_CONFIGURE_HX711 "Configurar balança" -#define D_HX711_PARAMETERS "Parâmetros da balança" -#define D_ITEM_WEIGHT "Peso do item" -#define D_REFERENCE_WEIGHT "Peso de referência" -#define D_CALIBRATE "Calibrar" -#define D_CALIBRATION "Calibração" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direção do vento" -#define D_TX20_WIND_SPEED "Velocidade do vento" -#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" -#define D_TX20_WIND_SPEED_MAX "Velocidade máxima do vento" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Nenhum" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Interruptor" // Suffix "1" -#define D_SENSOR_BUTTON "Botão" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Contador" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Luz fundo" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "Sensor RF" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotativo" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "setores" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Ângulo de fase" -#define D_IMPORT_ACTIVE "Ativo importado" -#define D_EXPORT_ACTIVE "Ativo exportado" -#define D_IMPORT_REACTIVE "Reativo importado" -#define D_EXPORT_REACTIVE "Reativo exportado" -#define D_TOTAL_REACTIVE "Reactivo total" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "Voltagem PV1" -#define D_PV1_CURRENT "Corrente PV1" -#define D_PV1_POWER "Potência PV1" -#define D_PV2_VOLTAGE "Voltagem PV2" -#define D_PV2_CURRENT "Corrente PV2" -#define D_PV2_POWER "Potência PV2" -#define D_SOLAR_POWER "Potência Solar" -#define D_INVERTER_POWER "Potência do Inversor" -#define D_STATUS "Estado" -#define D_WAITING "Esperando" -#define D_CHECKING "Verificando" -#define D_WORKING "Trabalhando" -#define D_FAILURE "Falha" -#define D_SOLAX_ERROR_0 "Nenhum código de erro" -#define D_SOLAX_ERROR_1 "Falha devido a perda de rede" -#define D_SOLAX_ERROR_2 "Falha devido a perda de tensão" -#define D_SOLAX_ERROR_3 "Falha devido a perda de frequência" -#define D_SOLAX_ERROR_4 "Falha de tensão de Pv" -#define D_SOLAX_ERROR_5 "Falha de isolamento" -#define D_SOLAX_ERROR_6 "Falha de temperatura excessiva" -#define D_SOLAX_ERROR_7 "Falha no ventilador" -#define D_SOLAX_ERROR_8 "Outra falha no dispositivo" - -#endif // _LANGUAGE_PT_PT_H_ +/* + pt-PT.h - localization for Portuguese - Portugal for Tasmota + + Copyright (C) 2019 Paulo Paiva + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_PT_PT_H_ +#define _LANGUAGE_PT_PT_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.0.0.1 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 2070 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "pt" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DomSegTerQuaQuiSexSab" +#define D_MONTH3LIST "JanFevMarAbrMaiJunJulAgoSepOutNovDez" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Qualidade do Ar" +#define D_AP "AP" // Ponto de Acesso +#define D_AS "como" +#define D_AUTO "AUTO" +#define D_BLINK "Piscar" +#define D_BLINKOFF "Piscar Desligado" +#define D_BOOT_COUNT "Contagem de Inicialização" +#define D_BRIGHTLIGHT "Brilho" +#define D_BSSID "BSSId" +#define D_BUTTON "Botão" +#define D_BY "por" // Write by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "Dioxido de Carbono" +#define D_CODE "Código" // Button code +#define D_COLDLIGHT "Luz Fria" +#define D_COMMAND "Comando" +#define D_CONNECTED "Ligado" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Contagem" +#define D_COUNTER "Contador" +#define D_CURRENT "Corrente" // As in Voltage and Current +#define D_DATA "Dados" +#define D_DARKLIGHT "Luz Escura" +#define D_DEBUG "Depurar" +#define D_DISABLED "Disabilitado" +#define D_DISTANCE "Distância" +#define D_DNS_SERVER "Servidor DNS" +#define D_DONE "Concluído" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulação" +#define D_ENABLED "Habilitado" +#define D_ERASE "Apagar" +#define D_ERROR "Erro" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Falha" +#define D_FALLBACK "Retornar" +#define D_FALLBACK_TOPIC "Tópico para retornar" +#define D_FALSE "Falso" +#define D_FILE "Ficheiro" +#define D_FLOW_RATE "Taxa de Fluxo" +#define D_FREE_MEMORY "Memoria Livre" +#define D_FREQUENCY "Frequência" +#define D_GAS "Gás" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupo" +#define D_HOST "Anfitrião" +#define D_HOSTNAME "Nome Anfitrião" +#define D_HUMIDITY "Humidade" +#define D_ILLUMINANCE "Luminâcia" +#define D_IMMEDIATE "Immediato" // Button immediate +#define D_INDEX "Indíce" +#define D_INFO "Info" +#define D_INFRARED "Infravermelho" +#define D_INITIALIZED "Inicializado" +#define D_IP_ADDRESS "Endereço IP" +#define D_LIGHT "Luz" +#define D_LWT "LWT" +#define D_MODULE "Módulo" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-pressão" +#define D_NOISE "Ruído" +#define D_NONE "Nenhum" +#define D_OFF "Off" +#define D_OFFLINE "Desconetado" +#define D_OK "Ok" +#define D_ON "On" +#define D_ONLINE "Conetado" +#define D_PASSWORD "Palavra Chave" +#define D_PORT "Porta" +#define D_POWER_FACTOR "Factor de Potência" +#define D_POWERUSAGE "Potência" +#define D_POWERUSAGE_ACTIVE "Potência Ativa" +#define D_POWERUSAGE_APPARENT "Potência Aparente" +#define D_POWERUSAGE_REACTIVE "Potência Reativa" +#define D_PRESSURE "Pressão" +#define D_PRESSUREATSEALEVEL "Pressão ao nível do Mar" +#define D_PROGRAM_FLASH_SIZE "Tamanho do Programa na Flash" +#define D_PROGRAM_SIZE "Tamanho do Programa" +#define D_PROJECT "Projeto" +#define D_RAIN "Chuva" +#define D_RECEIVED "Recebido" +#define D_RESTART "Reiniciar" +#define D_RESTARTING "A reiniciar" +#define D_RESTART_REASON "Razão do reinicio" +#define D_RESTORE "Restauro" +#define D_RETAINED "Manter" +#define D_RULE "Regra" +#define D_SAVE "Guardar" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Início" +#define D_STD_TIME "STD" +#define D_STOP "Parar" +#define D_SUBNET_MASK "Mascara sub rede" +#define D_SUBSCRIBE_TO "Subscrever" +#define D_UNSUBSCRIBE_FROM "Cancelar subscrição de" +#define D_SUCCESSFUL "Successo" +#define D_SUNRISE "Nascer do Sol" +#define D_SUNSET "Pôr do Sol" +#define D_TEMPERATURE "Temperatura" +#define D_TO "para" +#define D_TOGGLE "Pressionar" +#define D_TOPIC "Tópico" +#define D_TOTAL_USAGE "Uso total" +#define D_TRANSMIT "Transmitir" +#define D_TRUE "Verdadeiro" +#define D_TVOC "TVOC" +#define D_UPGRADE "Atualizar" +#define D_UPLOAD "Enviar" +#define D_UPTIME "Tempo de Atividade" +#define D_USER "Utilizador" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Indíce UV" +#define D_UV_INDEX_1 "Baixo" +#define D_UV_INDEX_2 "Médio" +#define D_UV_INDEX_3 "Elevado" +#define D_UV_INDEX_4 "Perigoso" +#define D_UV_INDEX_5 "QueimaduraL1/2" +#define D_UV_INDEX_6 "QueimaduraL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Nível UV" +#define D_UV_POWER "Poder UV" +#define D_VERSION "Versão" +#define D_VOLTAGE "Voltagem" +#define D_WEIGHT "Peso" +#define D_WARMLIGHT "Luz Quente" +#define D_WEB_SERVER "Servidor WEB" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "AVISO esta versão não supporta configurações persistentes" +#define D_LEVEL_10 "nível 1-0" +#define D_LEVEL_01 "nível 0-1" +#define D_SERIAL_LOGGING_DISABLED "Registro de porta série desabilitado" +#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" + +#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" +#define D_RECEIVED_TOPIC "Topico Recebido" +#define D_DATA_SIZE "Tamanho de Dados" +#define D_ANALOG_INPUT "Entrada Analógica" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Loop Bloqueado" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALHOU com estado" +#define D_ACTIVE_FOR_3_MINUTES "ativo por 3 minutos" +#define D_FAILED_TO_START "Falha ao iníciar" +#define D_PATCH_ISSUE_2186 "Questão 2186" +#define D_CONNECTING_TO_AP "Ligando ao AP" +#define D_IN_MODE "em modo" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "A ligação falhou porque nenhum endereço IP foi recebido" +#define D_CONNECT_FAILED_AP_NOT_REACHED "A ligação falhou porque o AP não pode ser alcançado" +#define D_CONNECT_FAILED_WRONG_PASSWORD "A ligação falhou porque a palavra chave está incorreta" +#define D_CONNECT_FAILED_AP_TIMEOUT "A ligação falhou porque o tempo excedeu" +#define D_ATTEMPTING_CONNECTION "A ligar..." +#define D_CHECKING_CONNECTION "A verificar ligação..." +#define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" +#define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" +#define D_FOUND_AT "encontrado em" +#define D_SYSLOG_HOST_NOT_FOUND "Anfitrião Syslog não encontrado" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Guardado na flash em" +#define D_LOADED_FROM_FLASH_AT "Lido da flash em" +#define D_USE_DEFAULTS "Usar predefinições" +#define D_ERASED_SECTOR "Apagado setor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Para utilizar o Tasmota, por favor ative o JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
Por favor atualize" +#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" +#define D_WITH_IP_ADDRESS "com o endereço IP" +#define D_WEBSERVER_STOPPED "Servitor WEB parou" +#define D_FILE_NOT_FOUND "Ficheiro não encontrado" +#define D_REDIRECTED "Redirecionado para o portal ativo" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager configura o Ponto de Acesso e mantem a Estação" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager configura o Ponto de Acesso" +#define D_TRYING_TO_CONNECT "A tentar ligar o dispositivo à rede" + +#define D_RESTART_IN "Reinicia em" +#define D_SECONDS "segundos" +#define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" +#define D_BUTTON_TOGGLE "Alternar" +#define D_CONFIGURATION "Configuração" +#define D_INFORMATION "Informação" +#define D_FIRMWARE_UPGRADE "Atualização de Firmware" +#define D_CONSOLE "Consola" +#define D_CONFIRM_RESTART "Confirmar o reinício" + +#define D_CONFIGURE_MODULE "Configurar Módulo" +#define D_CONFIGURE_WIFI "Configurar WiFi" +#define D_CONFIGURE_MQTT "Configurar MQTT" +#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" +#define D_CONFIGURE_LOGGING "Configurar registro" +#define D_CONFIGURE_OTHER "Configurar outras opções" +#define D_CONFIRM_RESET_CONFIGURATION "Confirme o reinício da configuração" +#define D_RESET_CONFIGURATION "Apagar configuração" +#define D_BACKUP_CONFIGURATION "Guardar configuração" +#define D_RESTORE_CONFIGURATION "Repor configuração" +#define D_MAIN_MENU "Menu Principal" + +#define D_MODULE_PARAMETERS "Parametros do Módulo" +#define D_MODULE_TYPE "Tipo de Módulo" +#define D_PULLUP_ENABLE "Sem pull-up de Botão/Interruptor" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Entrada de porta série" +#define D_SERIAL_OUT "Saída de porta série" + +#define D_WIFI_PARAMETERS "Parametros Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Procurar redes Wifi" +#define D_SCAN_DONE "Pesquisa terminada" +#define D_NO_NETWORKS_FOUND "Sem redes encontradas" +#define D_REFRESH_TO_SCAN_AGAIN "Atualize para realizar nova pesquisa" +#define D_DUPLICATE_ACCESSPOINT "Duplicar ponto de Acesso" +#define D_SKIPPING_LOW_QUALITY "Ignorado devido a baixa qualidade do sinal" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "SSId do AP1" +#define D_AP1_PASSWORD "Palavra Chave do AP1" +#define D_AP2_SSID "SSId do AP2" +#define D_AP2_PASSWORD "Palavra Chave do AP2" + +#define D_MQTT_PARAMETERS "Parametros MQTT" +#define D_CLIENT "Cliente" +#define D_FULL_TOPIC "Tópico completo" + +#define D_LOGGING_PARAMETERS "Parametros para registro" +#define D_SERIAL_LOG_LEVEL "Nível de registro na porta série" +#define D_MQTT_LOG_LEVEL "Nível de registro MQTT" +#define D_WEB_LOG_LEVEL "Nível de registro WEB" +#define D_SYS_LOG_LEVEL "Nível de registro do Syslog" +#define D_MORE_DEBUG "Depurar mais" +#define D_SYSLOG_HOST "Anfitrião Syslog" +#define D_SYSLOG_PORT "Porta Syslog" +#define D_TELEMETRY_PERIOD "Período de Telemetria" + +#define D_OTHER_PARAMETERS "Outros parametros" +#define D_TEMPLATE "Modelo" +#define D_ACTIVATE "Ativar" +#define D_WEB_ADMIN_PASSWORD "Palavra Chave do Admin WEB" +#define D_MQTT_ENABLE "MQTT habilitado" +#define D_FRIENDLY_NAME "Nome amigável" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "dispositivo único" +#define D_MULTI_DEVICE "dispositivo múltiplo" + +#define D_CONFIGURE_TEMPLATE "Configurar Modelo" +#define D_TEMPLATE_PARAMETERS "Parametros do Modelo" +#define D_TEMPLATE_NAME "Nome do Modelo" +#define D_BASE_TYPE "Baseado em" +#define D_TEMPLATE_FLAGS "Opções" + +#define D_SAVE_CONFIGURATION "Guardar configuração" +#define D_CONFIGURATION_SAVED "Configuração guardada" +#define D_CONFIGURATION_RESET "Reinicializar a configuração" + +#define D_PROGRAM_VERSION "Versão do Programa" +#define D_BUILD_DATE_AND_TIME "Data e Hora de criação" +#define D_CORE_AND_SDK_VERSION "Versão Core/SDK" +#define D_FLASH_WRITE_COUNT "Contagem de gravação da flash" +#define D_MAC_ADDRESS "Endereço MAC" +#define D_MQTT_HOST "Servidor MQTT" +#define D_MQTT_PORT "Porta MQTT" +#define D_MQTT_CLIENT "Cliente MQTT" +#define D_MQTT_USER "Utilizador MQTT" +#define D_MQTT_TOPIC "Tópico MQTT" +#define D_MQTT_GROUP_TOPIC "Tópico MQTT de Grupo" +#define D_MQTT_FULL_TOPIC "Tópico MQTT Completo" +#define D_MDNS_DISCOVERY "Descobrir mDNS" +#define D_MDNS_ADVERTISE "Anunciar mDNS" +#define D_ESP_CHIP_ID "ID do chip ESP" +#define D_FLASH_CHIP_ID "ID do chip da Flash" +#define D_FLASH_CHIP_SIZE "Tamanho da Flash" +#define D_FREE_PROGRAM_SPACE "Espaço de Programa Livre" + +#define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" +#define D_OTA_URL "Url OTA" +#define D_START_UPGRADE "Iniciar atualização" +#define D_UPGRADE_BY_FILE_UPLOAD "Atualizar por envio de ficheiro" +#define D_UPLOAD_STARTED "Envio Iniciado" +#define D_UPGRADE_STARTED "Atualização Iniciada" +#define D_UPLOAD_DONE "Atualização Finalizada" +#define D_UPLOAD_ERR_1 "Nenhum ficheiro selecionado" +#define D_UPLOAD_ERR_2 "Não existe espaço disponível" +#define D_UPLOAD_ERR_3 "O Byte mágico não é 0xE9" +#define D_UPLOAD_ERR_4 "O tamanho do programa e maior do que o tamanho real da flash" +#define D_UPLOAD_ERR_5 "Comparação incorreta do buffer de upload" +#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar registro 3" +#define D_UPLOAD_ERR_7 "Envio cancelado" +#define D_UPLOAD_ERR_8 "Ficheiro inválido" +#define D_UPLOAD_ERR_9 "Ficheiro demasiado grande" +#define D_UPLOAD_ERR_10 "Falha ao iniciar o chip de RF" +#define D_UPLOAD_ERR_11 "Falha ao apagar o chip de RF" +#define D_UPLOAD_ERR_12 "Falha ao escrever no chip de RF" +#define D_UPLOAD_ERR_13 "Falha ao descodificar o firmware RF" +#define D_UPLOAD_ERROR_CODE "Código de erro do envio" + +#define D_ENTER_COMMAND "Inserir comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 se resposta esperada" +#define D_NEED_USER_AND_PASSWORD "Necessário user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifique a impressão digital TLS..." +#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" +#define D_RETRY_IN "Nova tentativa em" +#define D_VERIFIED "Verificado usando impressão digital" +#define D_INSECURE "Ligação insegura devido à impressão digital inválida" +#define D_CONNECT_FAILED_TO "A ligação falhou ao" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast desabilitado" +#define D_MULTICAST_REJOINED "Multicast (re)ingressado" +#define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" +#define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo evento básico" +#define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" +#define D_WEMO_META_SERVICE "WeMo serviço meta" +#define D_WEMO_SETUP "WeMo configuração" +#define D_RESPONSE_SENT "Resposta enviada" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Configuração do Hue" +#define D_HUE_API_NOT_IMPLEMENTED "API Hue nao implementada" +#define D_HUE_API "API Hue" +#define D_HUE_POST_ARGS "Argumentos de POST HUE" +#define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parametros Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Chave idx" +#define D_DOMOTICZ_SWITCH_IDX "Interruptor idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Potência,Energia" + #define D_DOMOTICZ_ILLUMINANCE "Luminâcia" + #define D_DOMOTICZ_COUNT "Contagem/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltagem/PM2.5" + #define D_DOMOTICZ_CURRENT "Corrente/PM10" + #define D_DOMOTICZ_AIRQUALITY "Qualidade do Ar" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Temporizador de atualização" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configurar temporizador" +#define D_TIMER_PARAMETERS "Parâmetros do temporizador" +#define D_TIMER_ENABLE "Habilitar Temporizadores" +#define D_TIMER_ARM "Armar" +#define D_TIMER_TIME "Tempo" +#define D_TIMER_DAYS "Dias" +#define D_TIMER_REPEAT "Repetir" +#define D_TIMER_OUTPUT "Aaída" +#define D_TIMER_ACTION "Açao" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configurar KNX" +#define D_KNX_PARAMETERS "Parâmetros KNX" +#define D_KNX_GENERAL_CONFIG "Geral" +#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve ser exclusivo na rede KNX )" +#define D_KNX_ENABLE "Habilitar KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dados para enviar para Endereços de Grupo" +#define D_ADD "Adicionar" +#define D_DELETE "Remover" +#define D_REPLY "Responder" +#define D_KNX_GROUP_ADDRESS_TO_READ "Endereços de Grupo de onde receber dados" +#define D_RECEIVED_FROM "Recebido de" +#define D_KNX_COMMAND_WRITE "Escrever" +#define D_KNX_COMMAND_READ "Ler" +#define D_KNX_COMMAND_OTHER "Outro" +#define D_SENT_TO "enviar para" +#define D_KNX_WARNING "O Endereço de Grupo ( 0 / 0 / 0 ) está reservado e não pode ser usado." +#define D_KNX_ENHANCEMENT "Melhoria de Comunicação" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Consumo energético de hoje" +#define D_ENERGY_YESTERDAY "Consumo energético de ontem" +#define D_ENERGY_TOTAL "Consumo energético total" + +// xdrv_27_shutter.ino +#define D_OPEN "Abrir" +#define D_CLOSE "Fechar" +#define D_DOMOTICZ_SHUTTER "Estore" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configurar PCF8574" +#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" +#define D_INVERT_PORTS "Inverter Portas" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Entrada" +#define D_DEVICE_OUTPUT "Saída" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor ocupado" +#define D_SENSOR_CRC_ERROR "Erro no CRC do sensor" +#define D_SENSORS_FOUND "Sensores encontrados" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" +#define D_START_SIGNAL_LOW "Sinal de início baixo" +#define D_START_SIGNAL_HIGH "Sinal de início elevado" +#define D_PULSE "pulso" +#define D_CHECKSUM_FAILURE "Falha na soma de verificação" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" +#define D_SHT1X_FOUND "SHT1X encontrado" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partículas" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remover peso" +#define D_HX_CAL_REFERENCE "Carregar peso de referência" +#define D_HX_CAL_DONE "Calibrado" +#define D_HX_CAL_FAIL "Falha na calibração" +#define D_RESET_HX711 "Reiniciar balança" +#define D_CONFIGURE_HX711 "Configurar balança" +#define D_HX711_PARAMETERS "Parâmetros da balança" +#define D_ITEM_WEIGHT "Peso do item" +#define D_REFERENCE_WEIGHT "Peso de referência" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibração" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direção do vento" +#define D_TX20_WIND_SPEED "Velocidade do vento" +#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" +#define D_TX20_WIND_SPEED_MAX "Velocidade máxima do vento" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Nenhum" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Interruptor" // Suffix "1" +#define D_SENSOR_BUTTON "Botão" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Contador" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Luz fundo" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "Sensor RF" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotativo" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "setores" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Ângulo de fase" +#define D_IMPORT_ACTIVE "Ativo importado" +#define D_EXPORT_ACTIVE "Ativo exportado" +#define D_IMPORT_REACTIVE "Reativo importado" +#define D_EXPORT_REACTIVE "Reativo exportado" +#define D_TOTAL_REACTIVE "Reactivo total" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "Voltagem PV1" +#define D_PV1_CURRENT "Corrente PV1" +#define D_PV1_POWER "Potência PV1" +#define D_PV2_VOLTAGE "Voltagem PV2" +#define D_PV2_CURRENT "Corrente PV2" +#define D_PV2_POWER "Potência PV2" +#define D_SOLAR_POWER "Potência Solar" +#define D_INVERTER_POWER "Potência do Inversor" +#define D_STATUS "Estado" +#define D_WAITING "Esperando" +#define D_CHECKING "Verificando" +#define D_WORKING "Trabalhando" +#define D_FAILURE "Falha" +#define D_SOLAX_ERROR_0 "Nenhum código de erro" +#define D_SOLAX_ERROR_1 "Falha devido a perda de rede" +#define D_SOLAX_ERROR_2 "Falha devido a perda de tensão" +#define D_SOLAX_ERROR_3 "Falha devido a perda de frequência" +#define D_SOLAX_ERROR_4 "Falha de tensão de Pv" +#define D_SOLAX_ERROR_5 "Falha de isolamento" +#define D_SOLAX_ERROR_6 "Falha de temperatura excessiva" +#define D_SOLAX_ERROR_7 "Falha no ventilador" +#define D_SOLAX_ERROR_8 "Outra falha no dispositivo" + +#endif // _LANGUAGE_PT_PT_H_ diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 3bd788ede..a603216a9 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -1,701 +1,703 @@ -/* - ru-RU.h - localization for Russian - Rissia for Tasmota - - Copyright (C) 2019 Theo Arends / roman-vn - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_RU_RU_H_ -#define _LANGUAGE_RU_RU_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.12.0b -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1049 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "ru" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "ВскПонВтрСрдЧетПятСуб" -#define D_MONTH3LIST "ЯнвФевМарАпрМайИюнИюлАвгСенОктНояДек" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Качество воздуха" -#define D_AP "AP" // Access Point -#define D_AS "как" -#define D_AUTO "АВТО" -#define D_BLINK "Мигать" -#define D_BLINKOFF "Не Мигать" -#define D_BOOT_COUNT "Количество загрузок" -#define D_BRIGHTLIGHT "Яркость" -#define D_BSSID "BSSId" -#define D_BUTTON "Кнопка" -#define D_BY "by" // Written by me -#define D_BYTES "Байт" -#define D_CELSIUS "Цельсия" -#define D_CHANNEL "Channel" -#define D_CO2 "Углекислый газ" -#define D_CODE "код" // Button code -#define D_COLDLIGHT "Холодный" -#define D_COMMAND "Команда" -#define D_CONNECTED "Соединен" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Подсчет" -#define D_COUNTER "Счетчик" -#define D_CURRENT "Ток" // As in Voltage and Current -#define D_DATA "Данные" -#define D_DARKLIGHT "Темный" -#define D_DEBUG "Отладка" -#define D_DISABLED "Блокирован" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "DNS Сервер" -#define D_DONE "Выполнено" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Эмуляция" -#define D_ENABLED "Активно" -#define D_ERASE "Стирать" -#define D_ERROR "Ошибка" -#define D_FAHRENHEIT "Фаренгейт" -#define D_FAILED "Неудачно" -#define D_FALLBACK "Обратная связь" -#define D_FALLBACK_TOPIC "Топик обратной связи" -#define D_FALSE "Ложно" -#define D_FILE "Файл" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Свободная память" -#define D_FREQUENCY "Frequency" -#define D_GAS "Газ" -#define D_GATEWAY "Шлюз" -#define D_GROUP "Группа" -#define D_HOST "Хост" -#define D_HOSTNAME "Имя Хоста" -#define D_HUMIDITY "Влажность" -#define D_ILLUMINANCE "Освещенность" -#define D_IMMEDIATE "немедленно" // Button immediate -#define D_INDEX "Индекс" -#define D_INFO "Инфо" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "Инициализировано" -#define D_IP_ADDRESS "IP Адрес" -#define D_LIGHT "Свет" -#define D_LWT "LWT" -#define D_MODULE "Модуль" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "многократное нажатие" -#define D_NOISE "Шум" -#define D_NONE "Нет" -#define D_OFF "Выкл" -#define D_OFFLINE "Офф-лайн" -#define D_OK "Ок" -#define D_ON "Вкл" -#define D_ONLINE "Он-лайн" -#define D_PASSWORD "Пароль" -#define D_PORT "Порт" -#define D_POWER_FACTOR "Коэффициент Мощности" -#define D_POWERUSAGE "Мощность" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "Давление" -#define D_PRESSUREATSEALEVEL "Давление на уровне моря" -#define D_PROGRAM_FLASH_SIZE "Размер Flash для программ" -#define D_PROGRAM_SIZE "Размер программы " -#define D_PROJECT "Проект" -#define D_RAIN "Rain" -#define D_RECEIVED "Получено" -#define D_RESTART "Перезапуск" -#define D_RESTARTING "Перезапуск" -#define D_RESTART_REASON "Причина перезагрузки" -#define D_RESTORE "восстановление" -#define D_RETAINED "нераспред." -#define D_RULE "Rule" -#define D_SAVE "Сохранить" -#define D_SENSOR "Датчик" -#define D_SSID "SSId" -#define D_START "Старт" -#define D_STD_TIME "STD" -#define D_STOP "Стоп" -#define D_SUBNET_MASK "Маска Подсети" -#define D_SUBSCRIBE_TO "Подписаться на" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Успешно" -#define D_SUNRISE "Sunrise" -#define D_SUNSET "Sunset" -#define D_TEMPERATURE "Температура" -#define D_TO "до" -#define D_TOGGLE "Переключить" -#define D_TOPIC "Топик" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Передать" -#define D_TRUE "Истина" -#define D_TVOC "TVOC" -#define D_UPGRADE "обновление" -#define D_UPLOAD "Загрузить" -#define D_UPTIME "Uptime" -#define D_USER "Пользователь" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "УФ уровень" -#define D_UV_POWER "UV Power" -#define D_VERSION "Версия" -#define D_VOLTAGE "Напряжение" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "Тепло" -#define D_WEB_SERVER "Web сервер" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Эта версия не поддерживает персистентные настройки" -#define D_LEVEL_10 "уровень 1-0" -#define D_LEVEL_01 "уровень 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial logging отключен" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logging включен" - -#define D_SET_BAUDRATE_TO "Установить скорость передачи (Baudrate)" -#define D_RECEIVED_TOPIC "Полученный Топик" -#define D_DATA_SIZE "Размер данных" -#define D_ANALOG_INPUT "Аналоговый вход" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Блокирующий цикл" -#define D_WPS_FAILED_WITH_STATUS "WPS конфигурация НЕУДАЧНА со статусом" -#define D_ACTIVE_FOR_3_MINUTES "активен в течение 3 минут" -#define D_FAILED_TO_START "не удалось запустить" -#define D_PATCH_ISSUE_2186 "Проблема с исправлением 2186" -#define D_CONNECTING_TO_AP "Подключение к AP" -#define D_IN_MODE "в режиме" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Ошибка подключения, IP-адрес не получен" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Ошибка соединения, AP не может быть достигнута" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Ошибка соединения, неверный пароль к AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Ошибка соединения с AP по тайм-ауту" -#define D_ATTEMPTING_CONNECTION "Попытка подключения..." -#define D_CHECKING_CONNECTION "Проверка соединения..." -#define D_QUERY_DONE "Запрос выполнен. Обнаружены службы MQTT" -#define D_MQTT_SERVICE_FOUND "MQTT сервис service найдено" -#define D_FOUND_AT "найдено в" -#define D_SYSLOG_HOST_NOT_FOUND "System лог хост не найден" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Сохранено во флэш-память" -#define D_LOADED_FROM_FLASH_AT "Загружено из флэш-памяти" -#define D_USE_DEFAULTS "Использовать значение по умолчанию" -#define D_ERASED_SECTOR "Стереть сектор" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" -#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен" -#define D_WITH_IP_ADDRESS "с IP-адресом" -#define D_WEBSERVER_STOPPED "Веб-сервер остановлен" -#define D_FILE_NOT_FOUND "Файл не найден" -#define D_REDIRECTED "Перенаправлено на адаптивный портал" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер устанавливает Точку Доступа и сохраняет станцию" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер установил Точку Доступа" -#define D_TRYING_TO_CONNECT "Попытка подключения устройства к сети" - -#define D_RESTART_IN "Перезапуск" -#define D_SECONDS "секунд" -#define D_DEVICE_WILL_RESTART "Устройство будет перезапущено через несколько секунд" -#define D_BUTTON_TOGGLE "Переключить" -#define D_CONFIGURATION "Конфигурация" -#define D_INFORMATION "Информация" -#define D_FIRMWARE_UPGRADE "Обновление прошивки" -#define D_CONSOLE "Консоль" -#define D_CONFIRM_RESTART "Подтвердить перезагрузку" - -#define D_CONFIGURE_MODULE "Конфигурация Модуля" -#define D_CONFIGURE_WIFI "Конфигурация WiFi" -#define D_CONFIGURE_MQTT "Конфигурация MQTT" -#define D_CONFIGURE_DOMOTICZ "Конфигурация Domoticz" -#define D_CONFIGURE_LOGGING "Конфигурация Logging" -#define D_CONFIGURE_OTHER "Конфигурация прочее" -#define D_CONFIRM_RESET_CONFIGURATION "Подтвердить Сброс Конфигурации" -#define D_RESET_CONFIGURATION "Сброс Конфигурации" -#define D_BACKUP_CONFIGURATION "Резервное копирование Конфигурации" -#define D_RESTORE_CONFIGURATION "Восстановление Конфигурации" -#define D_MAIN_MENU "Главное Меню" - -#define D_MODULE_PARAMETERS "Параметры модуля" -#define D_MODULE_TYPE "Тип модуля" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial вход" -#define D_SERIAL_OUT "Serial выход" - -#define D_WIFI_PARAMETERS "Параметры Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Сканирование беспроводных сетей Wifi" -#define D_SCAN_DONE "Сканирование завершено" -#define D_NO_NETWORKS_FOUND "Не найдено сетей" -#define D_REFRESH_TO_SCAN_AGAIN "Обновить для повторного сканирования" -#define D_DUPLICATE_ACCESSPOINT "Дублировать Точку Доступа (AP)" -#define D_SKIPPING_LOW_QUALITY "Пропущено из-за низкого качества" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Пароль" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Пароль" - -#define D_MQTT_PARAMETERS "Параметры MQTT" -#define D_CLIENT "Клиент" -#define D_FULL_TOPIC "Полный Топик" - -#define D_LOGGING_PARAMETERS "Параметры Logging" -#define D_SERIAL_LOG_LEVEL "Serial лог уровень" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web лог уровень" -#define D_SYS_LOG_LEVEL "System лог уровень" -#define D_MORE_DEBUG "Дополнительная информация для отладки" -#define D_SYSLOG_HOST "System лог хост" -#define D_SYSLOG_PORT "System лог порт" -#define D_TELEMETRY_PERIOD "Период телеметрии" - -#define D_OTHER_PARAMETERS "Параметры Прочие" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Пароль Web администратора" -#define D_MQTT_ENABLE "MQTT активен" -#define D_FRIENDLY_NAME "Дружественное Имя" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "одиночное" -#define D_MULTI_DEVICE "мульти" - -#define D_CONFIGURE_TEMPLATE "Конфигурация Template" -#define D_TEMPLATE_PARAMETERS "Параметры Template" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Сохранить конфигурацию" -#define D_CONFIGURATION_SAVED "Конфигурация сохранена " -#define D_CONFIGURATION_RESET "Конфигурация сброшена" - -#define D_PROGRAM_VERSION "Версия программы" -#define D_BUILD_DATE_AND_TIME "Дата & Время сборки" -#define D_CORE_AND_SDK_VERSION "Версия Core/SDK" -#define D_FLASH_WRITE_COUNT "Кол-во записей Flash" -#define D_MAC_ADDRESS "MAC Адрес" -#define D_MQTT_HOST "MQTT Хост" -#define D_MQTT_PORT "MQTT Порт" -#define D_MQTT_CLIENT "MQTT Клиент ID" -#define D_MQTT_USER "MQTT Пользователь" -#define D_MQTT_TOPIC "MQTT Топик" -#define D_MQTT_GROUP_TOPIC "MQTT Топик группы" -#define D_MQTT_FULL_TOPIC "MQTT Топик полный" -#define D_MDNS_DISCOVERY "mDNS Обнаружение" -#define D_MDNS_ADVERTISE "mDNS Транcляция" -#define D_ESP_CHIP_ID "ID чипа ESP" -#define D_FLASH_CHIP_ID "ID чипа Flash памяти" -#define D_FLASH_CHIP_SIZE "Размер Flash памяти" -#define D_FREE_PROGRAM_SPACE "Свободное пространство программ" - -#define D_UPGRADE_BY_WEBSERVER "Обновление через Веб-сервер" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Начать обновление" -#define D_UPGRADE_BY_FILE_UPLOAD "Обновление путем загрузки файлов" -#define D_UPLOAD_STARTED "Загрузка началась" -#define D_UPGRADE_STARTED "Обновление началось" -#define D_UPLOAD_DONE "Загрузка завершена" -#define D_UPLOAD_ERR_1 "Файл не выбран" -#define D_UPLOAD_ERR_2 "Недостаточно места" -#define D_UPLOAD_ERR_3 "Magic байт не 0xE9" -#define D_UPLOAD_ERR_4 "Размер прошивки больше, чем реальный размер флеш памяти" -#define D_UPLOAD_ERR_5 "Ошибка загрузки буфера" -#define D_UPLOAD_ERR_6 "Ошибка загрузки. Включено лог уровня 3" -#define D_UPLOAD_ERR_7 "Загрузка прервана" -#define D_UPLOAD_ERR_8 "Файл неверный" -#define D_UPLOAD_ERR_9 "Слишком большой файл" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Код ошибки загрузки" - -#define D_ENTER_COMMAND "Введите команду" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Включить Веб лог уровня 2 если ожидается ответ" -#define D_NEED_USER_AND_PASSWORD "Ожидается user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Проверка TLS Fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "Сбой подключения TLS к" -#define D_RETRY_IN "Повторить" -#define D_VERIFIED "Проверено Fingerprint" -#define D_INSECURE "Небезопасное соединение, недействительный Fingerprint" -#define D_CONNECT_FAILED_TO "Ошибка подключения к" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast отключен" -#define D_MULTICAST_REJOINED "Multicast (ре)соединился" -#define D_MULTICAST_JOIN_FAILED "Multicast ошибка соединения" -#define D_FAILED_TO_SEND_RESPONSE "Не удалось отправить ответ" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo основное событие" -#define D_WEMO_EVENT_SERVICE "WeMo служба событий" -#define D_WEMO_META_SERVICE "WeMo мета-сервис" -#define D_WEMO_SETUP "WeMo настройка" -#define D_RESPONSE_SENT "Ответ отправлен" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue настройка" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API не реализовано" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 ответных пакета получено" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Параметры Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2,5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Конфигурация Timer" -#define D_TIMER_PARAMETERS "Параметры Timer" -#define D_TIMER_ENABLE "Enable Timers" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Конфигурация KNX" -#define D_KNX_PARAMETERS "Параметры KNX" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Энергия Сегодня" -#define D_ENERGY_YESTERDAY "Энергия Вчера" -#define D_ENERGY_TOTAL "Энергия Всего" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Датчик DS18x20 занят" -#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - ошибка CRC" -#define D_SENSORS_FOUND "Датчик DS18x20 найден" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Тайм-аут, в ожидании" -#define D_START_SIGNAL_LOW "сигнал старт низкий" -#define D_START_SIGNAL_HIGH "сигнал старт высокий" -#define D_PULSE "пульс" -#define D_CHECKSUM_FAILURE "Ошибка контрольной суммы" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не получил команду ACK" -#define D_SHT1X_FOUND "SHT1X найден" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "-нет-" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Свич" // Suffix "1" -#define D_SENSOR_BUTTON "Кнопка" // Suffix "1" -#define D_SENSOR_RELAY "Реле" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Счетчик" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "А" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Ч" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "кОм" -#define D_UNIT_KILOWATTHOUR "кВт" -#define D_UNIT_LUX "лк" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" -#define D_UNIT_MICROMETER "мкм" -#define D_UNIT_MICROSECOND "мкс" -#define D_UNIT_MILLIAMPERE "мА" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "мм рт.ст." -#define D_UNIT_MILLISECOND "мс" -#define D_UNIT_MINUTE "мин" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "гПа" -#define D_UNIT_SECOND "сек" -#define D_UNIT_SECTORS "секторов" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "В" -#define D_UNIT_WATT "Вт" -#define D_UNIT_WATTHOUR "ВтЧ" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Угол фазы" -#define D_IMPORT_ACTIVE "Импорт активной мощности" -#define D_EXPORT_ACTIVE "Экспорт активной мощности" -#define D_IMPORT_REACTIVE "Импорт реактивной мощности" -#define D_EXPORT_REACTIVE "Экспорт реактивной мощности" -#define D_TOTAL_REACTIVE "Итого реактивная мощность" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Град" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_RU_RU_H_ +/* + ru-RU.h - localization for Russian - Rissia for Tasmota + + Copyright (C) 2019 Theo Arends / roman-vn + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_RU_RU_H_ +#define _LANGUAGE_RU_RU_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.12.0b +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1049 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "ru" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "ВскПонВтрСрдЧетПятСуб" +#define D_MONTH3LIST "ЯнвФевМарАпрМайИюнИюлАвгСенОктНояДек" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Качество воздуха" +#define D_AP "AP" // Access Point +#define D_AS "как" +#define D_AUTO "АВТО" +#define D_BLINK "Мигать" +#define D_BLINKOFF "Не Мигать" +#define D_BOOT_COUNT "Количество загрузок" +#define D_BRIGHTLIGHT "Яркость" +#define D_BSSID "BSSId" +#define D_BUTTON "Кнопка" +#define D_BY "by" // Written by me +#define D_BYTES "Байт" +#define D_CELSIUS "Цельсия" +#define D_CHANNEL "Channel" +#define D_CO2 "Углекислый газ" +#define D_CODE "код" // Button code +#define D_COLDLIGHT "Холодный" +#define D_COMMAND "Команда" +#define D_CONNECTED "Соединен" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Подсчет" +#define D_COUNTER "Счетчик" +#define D_CURRENT "Ток" // As in Voltage and Current +#define D_DATA "Данные" +#define D_DARKLIGHT "Темный" +#define D_DEBUG "Отладка" +#define D_DISABLED "Блокирован" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "DNS Сервер" +#define D_DONE "Выполнено" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Эмуляция" +#define D_ENABLED "Активно" +#define D_ERASE "Стирать" +#define D_ERROR "Ошибка" +#define D_FAHRENHEIT "Фаренгейт" +#define D_FAILED "Неудачно" +#define D_FALLBACK "Обратная связь" +#define D_FALLBACK_TOPIC "Топик обратной связи" +#define D_FALSE "Ложно" +#define D_FILE "Файл" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Свободная память" +#define D_FREQUENCY "Frequency" +#define D_GAS "Газ" +#define D_GATEWAY "Шлюз" +#define D_GROUP "Группа" +#define D_HOST "Хост" +#define D_HOSTNAME "Имя Хоста" +#define D_HUMIDITY "Влажность" +#define D_ILLUMINANCE "Освещенность" +#define D_IMMEDIATE "немедленно" // Button immediate +#define D_INDEX "Индекс" +#define D_INFO "Инфо" +#define D_INFRARED "Infrared" +#define D_INITIALIZED "Инициализировано" +#define D_IP_ADDRESS "IP Адрес" +#define D_LIGHT "Свет" +#define D_LWT "LWT" +#define D_MODULE "Модуль" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "многократное нажатие" +#define D_NOISE "Шум" +#define D_NONE "Нет" +#define D_OFF "Выкл" +#define D_OFFLINE "Офф-лайн" +#define D_OK "Ок" +#define D_ON "Вкл" +#define D_ONLINE "Он-лайн" +#define D_PASSWORD "Пароль" +#define D_PORT "Порт" +#define D_POWER_FACTOR "Коэффициент Мощности" +#define D_POWERUSAGE "Мощность" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "Давление" +#define D_PRESSUREATSEALEVEL "Давление на уровне моря" +#define D_PROGRAM_FLASH_SIZE "Размер Flash для программ" +#define D_PROGRAM_SIZE "Размер программы " +#define D_PROJECT "Проект" +#define D_RAIN "Rain" +#define D_RECEIVED "Получено" +#define D_RESTART "Перезапуск" +#define D_RESTARTING "Перезапуск" +#define D_RESTART_REASON "Причина перезагрузки" +#define D_RESTORE "восстановление" +#define D_RETAINED "нераспред." +#define D_RULE "Rule" +#define D_SAVE "Сохранить" +#define D_SENSOR "Датчик" +#define D_SSID "SSId" +#define D_START "Старт" +#define D_STD_TIME "STD" +#define D_STOP "Стоп" +#define D_SUBNET_MASK "Маска Подсети" +#define D_SUBSCRIBE_TO "Подписаться на" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Успешно" +#define D_SUNRISE "Sunrise" +#define D_SUNSET "Sunset" +#define D_TEMPERATURE "Температура" +#define D_TO "до" +#define D_TOGGLE "Переключить" +#define D_TOPIC "Топик" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Передать" +#define D_TRUE "Истина" +#define D_TVOC "TVOC" +#define D_UPGRADE "обновление" +#define D_UPLOAD "Загрузить" +#define D_UPTIME "Uptime" +#define D_USER "Пользователь" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "УФ уровень" +#define D_UV_POWER "UV Power" +#define D_VERSION "Версия" +#define D_VOLTAGE "Напряжение" +#define D_WEIGHT "Weight" +#define D_WARMLIGHT "Тепло" +#define D_WEB_SERVER "Web сервер" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Эта версия не поддерживает персистентные настройки" +#define D_LEVEL_10 "уровень 1-0" +#define D_LEVEL_01 "уровень 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial logging отключен" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logging включен" + +#define D_SET_BAUDRATE_TO "Установить скорость передачи (Baudrate)" +#define D_RECEIVED_TOPIC "Полученный Топик" +#define D_DATA_SIZE "Размер данных" +#define D_ANALOG_INPUT "Аналоговый вход" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Блокирующий цикл" +#define D_WPS_FAILED_WITH_STATUS "WPS конфигурация НЕУДАЧНА со статусом" +#define D_ACTIVE_FOR_3_MINUTES "активен в течение 3 минут" +#define D_FAILED_TO_START "не удалось запустить" +#define D_PATCH_ISSUE_2186 "Проблема с исправлением 2186" +#define D_CONNECTING_TO_AP "Подключение к AP" +#define D_IN_MODE "в режиме" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Ошибка подключения, IP-адрес не получен" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Ошибка соединения, AP не может быть достигнута" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Ошибка соединения, неверный пароль к AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Ошибка соединения с AP по тайм-ауту" +#define D_ATTEMPTING_CONNECTION "Попытка подключения..." +#define D_CHECKING_CONNECTION "Проверка соединения..." +#define D_QUERY_DONE "Запрос выполнен. Обнаружены службы MQTT" +#define D_MQTT_SERVICE_FOUND "MQTT сервис service найдено" +#define D_FOUND_AT "найдено в" +#define D_SYSLOG_HOST_NOT_FOUND "System лог хост не найден" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Сохранено во флэш-память" +#define D_LOADED_FROM_FLASH_AT "Загружено из флэш-памяти" +#define D_USE_DEFAULTS "Использовать значение по умолчанию" +#define D_ERASED_SECTOR "Стереть сектор" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" +#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен" +#define D_WITH_IP_ADDRESS "с IP-адресом" +#define D_WEBSERVER_STOPPED "Веб-сервер остановлен" +#define D_FILE_NOT_FOUND "Файл не найден" +#define D_REDIRECTED "Перенаправлено на адаптивный портал" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер устанавливает Точку Доступа и сохраняет станцию" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер установил Точку Доступа" +#define D_TRYING_TO_CONNECT "Попытка подключения устройства к сети" + +#define D_RESTART_IN "Перезапуск" +#define D_SECONDS "секунд" +#define D_DEVICE_WILL_RESTART "Устройство будет перезапущено через несколько секунд" +#define D_BUTTON_TOGGLE "Переключить" +#define D_CONFIGURATION "Конфигурация" +#define D_INFORMATION "Информация" +#define D_FIRMWARE_UPGRADE "Обновление прошивки" +#define D_CONSOLE "Консоль" +#define D_CONFIRM_RESTART "Подтвердить перезагрузку" + +#define D_CONFIGURE_MODULE "Конфигурация Модуля" +#define D_CONFIGURE_WIFI "Конфигурация WiFi" +#define D_CONFIGURE_MQTT "Конфигурация MQTT" +#define D_CONFIGURE_DOMOTICZ "Конфигурация Domoticz" +#define D_CONFIGURE_LOGGING "Конфигурация Logging" +#define D_CONFIGURE_OTHER "Конфигурация прочее" +#define D_CONFIRM_RESET_CONFIGURATION "Подтвердить Сброс Конфигурации" +#define D_RESET_CONFIGURATION "Сброс Конфигурации" +#define D_BACKUP_CONFIGURATION "Резервное копирование Конфигурации" +#define D_RESTORE_CONFIGURATION "Восстановление Конфигурации" +#define D_MAIN_MENU "Главное Меню" + +#define D_MODULE_PARAMETERS "Параметры модуля" +#define D_MODULE_TYPE "Тип модуля" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial вход" +#define D_SERIAL_OUT "Serial выход" + +#define D_WIFI_PARAMETERS "Параметры Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Сканирование беспроводных сетей Wifi" +#define D_SCAN_DONE "Сканирование завершено" +#define D_NO_NETWORKS_FOUND "Не найдено сетей" +#define D_REFRESH_TO_SCAN_AGAIN "Обновить для повторного сканирования" +#define D_DUPLICATE_ACCESSPOINT "Дублировать Точку Доступа (AP)" +#define D_SKIPPING_LOW_QUALITY "Пропущено из-за низкого качества" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Пароль" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Пароль" + +#define D_MQTT_PARAMETERS "Параметры MQTT" +#define D_CLIENT "Клиент" +#define D_FULL_TOPIC "Полный Топик" + +#define D_LOGGING_PARAMETERS "Параметры Logging" +#define D_SERIAL_LOG_LEVEL "Serial лог уровень" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web лог уровень" +#define D_SYS_LOG_LEVEL "System лог уровень" +#define D_MORE_DEBUG "Дополнительная информация для отладки" +#define D_SYSLOG_HOST "System лог хост" +#define D_SYSLOG_PORT "System лог порт" +#define D_TELEMETRY_PERIOD "Период телеметрии" + +#define D_OTHER_PARAMETERS "Параметры Прочие" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Пароль Web администратора" +#define D_MQTT_ENABLE "MQTT активен" +#define D_FRIENDLY_NAME "Дружественное Имя" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "одиночное" +#define D_MULTI_DEVICE "мульти" + +#define D_CONFIGURE_TEMPLATE "Конфигурация Template" +#define D_TEMPLATE_PARAMETERS "Параметры Template" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Сохранить конфигурацию" +#define D_CONFIGURATION_SAVED "Конфигурация сохранена " +#define D_CONFIGURATION_RESET "Конфигурация сброшена" + +#define D_PROGRAM_VERSION "Версия программы" +#define D_BUILD_DATE_AND_TIME "Дата & Время сборки" +#define D_CORE_AND_SDK_VERSION "Версия Core/SDK" +#define D_FLASH_WRITE_COUNT "Кол-во записей Flash" +#define D_MAC_ADDRESS "MAC Адрес" +#define D_MQTT_HOST "MQTT Хост" +#define D_MQTT_PORT "MQTT Порт" +#define D_MQTT_CLIENT "MQTT Клиент ID" +#define D_MQTT_USER "MQTT Пользователь" +#define D_MQTT_TOPIC "MQTT Топик" +#define D_MQTT_GROUP_TOPIC "MQTT Топик группы" +#define D_MQTT_FULL_TOPIC "MQTT Топик полный" +#define D_MDNS_DISCOVERY "mDNS Обнаружение" +#define D_MDNS_ADVERTISE "mDNS Транcляция" +#define D_ESP_CHIP_ID "ID чипа ESP" +#define D_FLASH_CHIP_ID "ID чипа Flash памяти" +#define D_FLASH_CHIP_SIZE "Размер Flash памяти" +#define D_FREE_PROGRAM_SPACE "Свободное пространство программ" + +#define D_UPGRADE_BY_WEBSERVER "Обновление через Веб-сервер" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Начать обновление" +#define D_UPGRADE_BY_FILE_UPLOAD "Обновление путем загрузки файлов" +#define D_UPLOAD_STARTED "Загрузка началась" +#define D_UPGRADE_STARTED "Обновление началось" +#define D_UPLOAD_DONE "Загрузка завершена" +#define D_UPLOAD_ERR_1 "Файл не выбран" +#define D_UPLOAD_ERR_2 "Недостаточно места" +#define D_UPLOAD_ERR_3 "Magic байт не 0xE9" +#define D_UPLOAD_ERR_4 "Размер прошивки больше, чем реальный размер флеш памяти" +#define D_UPLOAD_ERR_5 "Ошибка загрузки буфера" +#define D_UPLOAD_ERR_6 "Ошибка загрузки. Включено лог уровня 3" +#define D_UPLOAD_ERR_7 "Загрузка прервана" +#define D_UPLOAD_ERR_8 "Файл неверный" +#define D_UPLOAD_ERR_9 "Слишком большой файл" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "Код ошибки загрузки" + +#define D_ENTER_COMMAND "Введите команду" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Включить Веб лог уровня 2 если ожидается ответ" +#define D_NEED_USER_AND_PASSWORD "Ожидается user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Проверка TLS Fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "Сбой подключения TLS к" +#define D_RETRY_IN "Повторить" +#define D_VERIFIED "Проверено Fingerprint" +#define D_INSECURE "Небезопасное соединение, недействительный Fingerprint" +#define D_CONNECT_FAILED_TO "Ошибка подключения к" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast отключен" +#define D_MULTICAST_REJOINED "Multicast (ре)соединился" +#define D_MULTICAST_JOIN_FAILED "Multicast ошибка соединения" +#define D_FAILED_TO_SEND_RESPONSE "Не удалось отправить ответ" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo основное событие" +#define D_WEMO_EVENT_SERVICE "WeMo служба событий" +#define D_WEMO_META_SERVICE "WeMo мета-сервис" +#define D_WEMO_SETUP "WeMo настройка" +#define D_RESPONSE_SENT "Ответ отправлен" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue настройка" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API не реализовано" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 ответных пакета получено" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Параметры Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2,5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Конфигурация Timer" +#define D_TIMER_PARAMETERS "Параметры Timer" +#define D_TIMER_ENABLE "Enable Timers" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Time" +#define D_TIMER_DAYS "Days" +#define D_TIMER_REPEAT "Repeat" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Конфигурация KNX" +#define D_KNX_PARAMETERS "Параметры KNX" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Physical Address" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "Enable KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Add" +#define D_DELETE "Delete" +#define D_REPLY "Reply" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Write" +#define D_KNX_COMMAND_READ "Read" +#define D_KNX_COMMAND_OTHER "Other" +#define D_SENT_TO "sent to" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Энергия Сегодня" +#define D_ENERGY_YESTERDAY "Энергия Вчера" +#define D_ENERGY_TOTAL "Энергия Всего" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Датчик DS18x20 занят" +#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - ошибка CRC" +#define D_SENSORS_FOUND "Датчик DS18x20 найден" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Тайм-аут, в ожидании" +#define D_START_SIGNAL_LOW "сигнал старт низкий" +#define D_START_SIGNAL_HIGH "сигнал старт высокий" +#define D_PULSE "пульс" +#define D_CHECKSUM_FAILURE "Ошибка контрольной суммы" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не получил команду ACK" +#define D_SHT1X_FOUND "SHT1X найден" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "-нет-" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Свич" // Suffix "1" +#define D_SENSOR_BUTTON "Кнопка" // Suffix "1" +#define D_SENSOR_RELAY "Реле" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Счетчик" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "А" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Ч" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "кОм" +#define D_UNIT_KILOWATTHOUR "кВт" +#define D_UNIT_LUX "лк" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" +#define D_UNIT_MICROMETER "мкм" +#define D_UNIT_MICROSECOND "мкс" +#define D_UNIT_MILLIAMPERE "мА" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "мм рт.ст." +#define D_UNIT_MILLISECOND "мс" +#define D_UNIT_MINUTE "мин" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "гПа" +#define D_UNIT_SECOND "сек" +#define D_UNIT_SECTORS "секторов" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "В" +#define D_UNIT_WATT "Вт" +#define D_UNIT_WATTHOUR "ВтЧ" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Угол фазы" +#define D_IMPORT_ACTIVE "Импорт активной мощности" +#define D_EXPORT_ACTIVE "Экспорт активной мощности" +#define D_IMPORT_REACTIVE "Импорт реактивной мощности" +#define D_EXPORT_REACTIVE "Экспорт реактивной мощности" +#define D_TOTAL_REACTIVE "Итого реактивная мощность" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Град" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_RU_RU_H_ diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index a64e49e01..52540be9c 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -1,701 +1,703 @@ -/* - sk-SK.h - localization for Slovak with diacritics - Slovak for Tasmota - - Copyright (C) 2019 Vladimír Jendroľ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_SK_SK_H_ -#define _LANGUAGE_SK_SK_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.14 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1029 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "sk" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "Ne Po Ut St Št Pi So" -#define D_MONTH3LIST "JanFebMarAprMájJúnJúlAugSepOktNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Kvalita vzduchu" -#define D_AP "AP" // Access Point -#define D_AS "ako" -#define D_AUTO "AUTO" -#define D_BLINK "Blikanie" -#define D_BLINKOFF "BlikanieVyp" -#define D_BOOT_COUNT "Počítadlo spustení" -#define D_BRIGHTLIGHT "Svetlý" -#define D_BSSID "BSSId" -#define D_BUTTON "Tlačídlo" -#define D_BY "by" // Written by me -#define D_BYTES "Bytov" -#define D_CELSIUS "°C" -#define D_CHANNEL "Kanál" -#define D_CO2 "CO2" -#define D_CODE "kód" // Button code -#define D_COLDLIGHT "Studené svetlo" -#define D_COMMAND "Príkaz" -#define D_CONNECTED "...pripojené" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Počítaj" -#define D_COUNTER "Počítadlo" -#define D_CURRENT "Prúd" // As in Voltage and Current -#define D_DATA "Dáta" -#define D_FLOW_RATE "Flow rate" -#define D_DARKLIGHT "Tmavý" -#define D_DEBUG "Debug" -#define D_DISABLED "Zablokované" -#define D_DISTANCE "Vzdialenosť" -#define D_DNS_SERVER "Server DNS" -#define D_DONE "Hotovo" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulácia" -#define D_ENABLED "Otvorený" -#define D_ERASE "Zmaž" -#define D_ERROR "Chyba" -#define D_FAHRENHEIT "Fahrenheita" -#define D_FAILED "chyba" -#define D_FALLBACK "Záložný" -#define D_FALLBACK_TOPIC "Záložný topic" -#define D_FALSE "Nepravda" -#define D_FILE "Súbor" -#define D_FREE_MEMORY "Voľná pamäť" -#define D_FREQUENCY "Frekvencia" -#define D_GAS "Plyn" -#define D_GATEWAY "Predvolená brána" -#define D_GROUP "Skupina" -#define D_HOST "Server" -#define D_HOSTNAME "Názov servera" -#define D_HUMIDITY "Vlhkosť" -#define D_ILLUMINANCE "Osvetlenie" -#define D_IMMEDIATE "Okamžité" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Informácie" -#define D_INFRARED "Infračervené" -#define D_INITIALIZED "Inicializovaný" -#define D_IP_ADDRESS "Adresa IP" -#define D_LIGHT "Svetlo" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-stlačenie" -#define D_NOISE "Hluk" -#define D_NONE "Žiadny" -#define D_OFF "Vyp." -#define D_OFFLINE "Neaktívny" -#define D_OK "OK" -#define D_ON "Zap." -#define D_ONLINE "Aktívny" -#define D_PASSWORD "Heslo" -#define D_PORT "Port" -#define D_POWER_FACTOR "Účinník" -#define D_POWERUSAGE "Príkon" -#define D_POWERUSAGE_ACTIVE "Činný príkon" -#define D_POWERUSAGE_APPARENT "Zdanlivý príkon" -#define D_POWERUSAGE_REACTIVE "Jalový príkon" -#define D_PRESSURE "Tlak" -#define D_PRESSUREATSEALEVEL "Tlak na hladine mora" -#define D_PROGRAM_FLASH_SIZE "Veľkosť flash pamäte" -#define D_PROGRAM_SIZE "Veľkosť programu" -#define D_PROJECT "Projekt" -#define D_RAIN "Dážď" -#define D_RECEIVED "Prijatý" -#define D_RESTART "Reštart" -#define D_RESTARTING "Reštartuje sa" -#define D_RESTART_REASON "Príčina reštartu" -#define D_RESTORE "Obnoviť" -#define D_RETAINED "Zachované" -#define D_RULE "Pravidlo" -#define D_SAVE "Ulož" -#define D_SENSOR "Senzor" -#define D_SSID "SSID" -#define D_START "Spustiť" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Maska podsiete" -#define D_SUBSCRIBE_TO "Prihlásiť do" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "úspešné." -#define D_SUNRISE "Svitanie" -#define D_SUNSET "Súmrak" -#define D_TEMPERATURE "Teplota" -#define D_TO "do" -#define D_TOGGLE "Prepni" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Odošli" -#define D_TRUE "Pravda" -#define D_TVOC "TVOC" -#define D_UPGRADE "aktualizáciu" -#define D_UPLOAD "Nahrávanie..." -#define D_UPTIME "Uptime" -#define D_USER "Používateľ" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Nízky" -#define D_UV_INDEX_2 "Stredný" -#define D_UV_INDEX_3 "Vysoký" -#define D_UV_INDEX_4 "Nebezpečný" -#define D_UV_INDEX_5 "Popál1/2" -#define D_UV_INDEX_6 "Popál3" -#define D_UV_INDEX_7 "MimoRozsah" -#define D_UV_LEVEL "úroveň UV" -#define D_UV_POWER "UV Power" -#define D_VERSION "Verzia" -#define D_VOLTAGE "Napätie" -#define D_WEIGHT "Hmotnosť" -#define D_WARMLIGHT "Teplé svetlo" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "UPOZORNENIE Táto verzia nepodporuje trvalé nastavenia" -#define D_LEVEL_10 "úroveň 1-0" -#define D_LEVEL_01 "úroveň 0-1" -#define D_SERIAL_LOGGING_DISABLED "Logovanie na sériovom porte ukončené" -#define D_SYSLOG_LOGGING_REENABLED "Obnovený zápis do Syslog" - -#define D_SET_BAUDRATE_TO "Nastaviť rýchlosti prenosu na" -#define D_RECEIVED_TOPIC "Prijatý topic" -#define D_DATA_SIZE "Veľkosť dát" -#define D_ANALOG_INPUT "Analógový vstup" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Zablokovanie slučky" -#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig so statusom" -#define D_ACTIVE_FOR_3_MINUTES "aktívny 3 minúty" -#define D_FAILED_TO_START "nepodarilo sa spustiť" -#define D_PATCH_ISSUE_2186 "Chyba 2186" -#define D_CONNECTING_TO_AP "Pripájanie k AP" -#define D_IN_MODE "v režime" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba pripojenia, nebola obdržaná IP adresa" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba pripojenia, nedostupný AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba pripojenia, nesprávne heslo pre AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba pripojenia, uplynul AP timeout" -#define D_ATTEMPTING_CONNECTION "Pripájanie..." -#define D_CHECKING_CONNECTION "Skúška spojenia..." -#define D_QUERY_DONE "Vyslanie požiadavky. Nájdená služba MQTT" -#define D_MQTT_SERVICE_FOUND "Služba MQTT bola nájdená" -#define D_FOUND_AT "nájdené v" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebol nájdený" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Uložené do flash pamäte v" -#define D_LOADED_FROM_FLASH_AT "Stiahnuté z flash pamäte z" -#define D_USE_DEFAULTS "Použi prednastavené hodnoty" -#define D_ERASED_SECTOR "Zmazaný sektor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" -#define D_WEBSERVER_ACTIVE_ON "Aktívny Web server" -#define D_WITH_IP_ADDRESS "na IP adrese" -#define D_WEBSERVER_STOPPED "Web server zastavený" -#define D_FILE_NOT_FOUND "Súbor nebol nájdený" -#define D_REDIRECTED "Presmerovanie na vlastný portál" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manažér nastaví AP a zachová STA" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manažér nastaví Access Point" -#define D_TRYING_TO_CONNECT "Skúšam pripojiť zariadenie k sieti" - -#define D_RESTART_IN "Reštart" -#define D_SECONDS "sekúnd" -#define D_DEVICE_WILL_RESTART "Zariadenie bude reštartované behom niekoľkých sekúnd" -#define D_BUTTON_TOGGLE "Prepínač" -#define D_CONFIGURATION "Nastavenia" -#define D_INFORMATION "Informácie" -#define D_FIRMWARE_UPGRADE "Aktualizácia firmware" -#define D_CONSOLE "Konzola" -#define D_CONFIRM_RESTART "Potvrdenie reštartu" - -#define D_CONFIGURE_MODULE "Nastavenia modulu" -#define D_CONFIGURE_WIFI "Nastavenia WiFi" -#define D_CONFIGURE_MQTT "Nastavenia MQTT" -#define D_CONFIGURE_DOMOTICZ "Nastavenia Domoticz" -#define D_CONFIGURE_LOGGING "Nastavenia logovania" -#define D_CONFIGURE_OTHER "Ostatné nastavenia" -#define D_CONFIRM_RESET_CONFIGURATION "Potvrdenie resetu nastavení" -#define D_RESET_CONFIGURATION "Reset nastavení" -#define D_BACKUP_CONFIGURATION "Záloha nastavení" -#define D_RESTORE_CONFIGURATION "Obnovenie nastavení" -#define D_MAIN_MENU "Hlavné menu" - -#define D_MODULE_PARAMETERS "Nastavenia modulu" -#define D_MODULE_TYPE "Typ modulu" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Nastavenia WiFi" -#define D_SCAN_FOR_WIFI_NETWORKS "Sken WiFi sietí" -#define D_SCAN_DONE "Sken dokončený" -#define D_NO_NETWORKS_FOUND "Sieť nebola nájdená" -#define D_REFRESH_TO_SCAN_AGAIN "Zopakovať sken" -#define D_DUPLICATE_ACCESSPOINT "Kópia AP" -#define D_SKIPPING_LOW_QUALITY "Preskočenie z dôvodu kvality signálu" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "Heslo AP1" -#define D_AP2_SSID "AP2 SSID" -#define D_AP2_PASSWORD "Heslo AP2" - -#define D_MQTT_PARAMETERS "Nastavenia MQTT" -#define D_CLIENT "Klient" -#define D_FULL_TOPIC "Celý topic" - -#define D_LOGGING_PARAMETERS "Voľba logovania" -#define D_SERIAL_LOG_LEVEL "Sériová úroveň logu" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Webová úroveň logu" -#define D_SYS_LOG_LEVEL "Systemová úroveň logu" -#define D_MORE_DEBUG "Viac debug informácí" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Interval telemetrie" - -#define D_OTHER_PARAMETERS "Ostatné nastavenia" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" -#define D_MQTT_ENABLE "MQTT aktívne" -#define D_FRIENDLY_NAME "Friendly Name" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Ulož nastavenia" -#define D_CONFIGURATION_SAVED "Nastavenia uložené" -#define D_CONFIGURATION_RESET "Nastavenia resetované" - -#define D_PROGRAM_VERSION "Verzia programu" -#define D_BUILD_DATE_AND_TIME "Datum a čas kompilácie" -#define D_CORE_AND_SDK_VERSION "Verzia Core/SDK" -#define D_FLASH_WRITE_COUNT "Počet zápisov do pamäte" -#define D_MAC_ADDRESS "Adresa MAC" -#define D_MQTT_HOST "Host MQTT" -#define D_MQTT_PORT "Port MQTT" -#define D_MQTT_CLIENT "Klient MQTT" -#define D_MQTT_USER "Používateľ MQTT" -#define D_MQTT_TOPIC "Topic MQTT" -#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT" -#define D_MQTT_FULL_TOPIC "Celý topic MQTT" -#define D_MDNS_DISCOVERY "Získavanie mDNS" -#define D_MDNS_ADVERTISE "Rozosielanie mDNS" -#define D_ESP_CHIP_ID "ID systému ESP" -#define D_FLASH_CHIP_ID "ID systému flash pamäte" -#define D_FLASH_CHIP_SIZE "Veľkosť flash" -#define D_FREE_PROGRAM_SPACE "Voľné místo pre program" - -#define D_UPGRADE_BY_WEBSERVER "Aktualizácia z Web serveru" -#define D_OTA_URL "URL OTA" -#define D_START_UPGRADE "Spustiť aktualizáciu" -#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizácia nahraním súboru" -#define D_UPLOAD_STARTED "Nahrávanie spustené" -#define D_UPGRADE_STARTED "Aktualizácia spustená" -#define D_UPLOAD_DONE "Nahrávanie ukončené" -#define D_UPLOAD_ERR_1 "Súbor nebol vybraný" -#define D_UPLOAD_ERR_2 "Málo miesta" -#define D_UPLOAD_ERR_3 "Magický byte má hodnotu inú než 0xE9" -#define D_UPLOAD_ERR_4 "Veľkosť programu je väčšia než skutočná veľkosť flash pamäte" -#define D_UPLOAD_ERR_5 "Chyba nahrávania, nesúhlasia porovnávané bity" -#define D_UPLOAD_ERR_6 "Chyba nahrávania. Spustený zápis do logu na úrovni 3" -#define D_UPLOAD_ERR_7 "Nahrávanie prerušené" -#define D_UPLOAD_ERR_8 "Nesprávny súbor" -#define D_UPLOAD_ERR_9 "Súbor je príliš veľký" -#define D_UPLOAD_ERR_10 "Chyba inicializácie RF chipu" -#define D_UPLOAD_ERR_11 "Chyba zmazania RF chipu" -#define D_UPLOAD_ERR_12 "Chyba pri zápise do RF chipu" -#define D_UPLOAD_ERR_13 "Chyba dekódovania RF firmwaru" -#define D_UPLOAD_ERROR_CODE "Chyba nahrávania" - -#define D_ENTER_COMMAND "Vlož príkaz" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni úroveň 2 zápisu Weblog, ak je očekávaná odpoveď" -#define D_NEED_USER_AND_PASSWORD "Vyžadovaný používateľ=&heslo=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifikuj odtlačok TLS..." -#define D_TLS_CONNECT_FAILED_TO "Nepripojené TLS do" -#define D_RETRY_IN "Zopakujem o" -#define D_VERIFIED "Overený odtlačok " -#define D_INSECURE "Nesprávne pripojenie z dôvodu chybného odtlačku TLS" -#define D_CONNECT_FAILED_TO "Nepodarilo sa nadviazať spojenie" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast je vypnutý" -#define D_MULTICAST_REJOINED "Multicast opäť pripojený" -#define D_MULTICAST_JOIN_FAILED "Multicast neúspešný" -#define D_FAILED_TO_SEND_RESPONSE "Nepodarilo sa odoslať odpoveď" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo základná udalosť" -#define D_WEMO_EVENT_SERVICE "WeMo servisná udalosť" -#define D_WEMO_META_SERVICE "WeMo meta udalosť" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Odpoveď odoslaná" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API nie je implementované" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovede odoslané" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Nastavenia Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Spinac idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak" - #define D_DOMOTICZ_POWER_ENERGY "Príkon,Energia" - #define D_DOMOTICZ_ILLUMINANCE "Osvetlenie" - #define D_DOMOTICZ_COUNT "Počítadlo/PM1" - #define D_DOMOTICZ_VOLTAGE "Napätie/PM2,5" - #define D_DOMOTICZ_CURRENT "Prúd/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Aktualizácia časovača" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Nastavenia časovača" -#define D_TIMER_PARAMETERS "Časovač" -#define D_TIMER_ENABLE "Povoľ časovače" -#define D_TIMER_ARM "Aktívne" -#define D_TIMER_TIME "Čas" -#define D_TIMER_DAYS "Dni" -#define D_TIMER_REPEAT "Opakovať" -#define D_TIMER_OUTPUT "Výstup" -#define D_TIMER_ACTION "Napájanie" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Nastavenie KNX" -#define D_KNX_PARAMETERS "KNX parametre" -#define D_KNX_GENERAL_CONFIG "Všeobecné" -#define D_KNX_PHYSICAL_ADDRESS "Fyzická adresa" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musí být jedinečná v sieti KNX )" -#define D_KNX_ENABLE "Povoľ KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dáta na odoslanie na skupinové adresy" -#define D_ADD "Pridať" -#define D_DELETE "Zmazať" -#define D_REPLY "Odpoveď" -#define D_KNX_GROUP_ADDRESS_TO_READ "Skupinové adresy pre príjem dát z" -#define D_RECEIVED_FROM "Prijaté z" -#define D_KNX_COMMAND_WRITE "Zapíš" -#define D_KNX_COMMAND_READ "Čítaj" -#define D_KNX_COMMAND_OTHER "Iné" -#define D_SENT_TO "pošli" -#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervovaná a nemôže byť použitá." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Spotreba dnes" -#define D_ENERGY_YESTERDAY "Spotreba včera" -#define D_ENERGY_TOTAL "Celková spotreba" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor DS18x20 obsadený" -#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" -#define D_SENSORS_FOUND "Nanájdený senzor DS18x20" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Čakanie na" -#define D_START_SIGNAL_LOW "nízký štartovací signál" -#define D_START_SIGNAL_HIGH "vysoký štartovací signál" -#define D_PULSE "impulz" -#define D_CHECKSUM_FAILURE "Chybný kontrolný súčet" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Senzor neobdržal príkaz ACK" -#define D_SHT1X_FOUND "SHT1X nanájdený" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "častíc" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. os-X" -#define D_AY_AXIS "Accel. os-Y" -#define D_AZ_AXIS "Accel. os-Z" -#define D_GX_AXIS "Gyro os-X" -#define D_GY_AXIS "Gyro os-Y" -#define D_GZ_AXIS "Gyro os-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Odstráňte záťaž" -#define D_HX_CAL_REFERENCE "Vložte referenčnú záťaž" -#define D_HX_CAL_DONE "Skalibrováné" -#define D_HX_CAL_FAIL "Chyba kalibráce" -#define D_RESET_HX711 "Reset váhy" -#define D_CONFIGURE_HX711 "Konfiguráce váhy" -#define D_HX711_PARAMETERS "Parametre váhy" -#define D_ITEM_WEIGHT "Vlastná hmotnosť" -#define D_REFERENCE_WEIGHT "Referenčná hmotnosť" -#define D_CALIBRATE "Kalibruj" -#define D_CALIBRATION "Kalibrácia" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Smer vetra" -#define D_TX20_WIND_SPEED "Rýchlosť vetra" -#define D_TX20_WIND_SPEED_AVG "Priemerná rýchlosť vetra" -#define D_TX20_WIND_SPEED_MAX "Maximálna rýchlosť vetra" -#define D_TX20_NORTH "S" -#define D_TX20_EAST "V" -#define D_TX20_SOUTH "J" -#define D_TX20_WEST "Z" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Žiaden" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Spínač" // Suffix "1" -#define D_SENSOR_BUTTON "Tlačidlo" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1", -#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Senzor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "hod" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sek" -#define D_UNIT_SECTORS "sektory" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_SK_SK_H_ +/* + sk-SK.h - localization for Slovak with diacritics - Slovak for Tasmota + + Copyright (C) 2019 Vladimír Jendroľ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_SK_SK_H_ +#define _LANGUAGE_SK_SK_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.14 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1029 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "sk" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "Ne Po Ut St Št Pi So" +#define D_MONTH3LIST "JanFebMarAprMájJúnJúlAugSepOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Kvalita vzduchu" +#define D_AP "AP" // Access Point +#define D_AS "ako" +#define D_AUTO "AUTO" +#define D_BLINK "Blikanie" +#define D_BLINKOFF "BlikanieVyp" +#define D_BOOT_COUNT "Počítadlo spustení" +#define D_BRIGHTLIGHT "Svetlý" +#define D_BSSID "BSSId" +#define D_BUTTON "Tlačídlo" +#define D_BY "by" // Written by me +#define D_BYTES "Bytov" +#define D_CELSIUS "°C" +#define D_CHANNEL "Kanál" +#define D_CO2 "CO2" +#define D_CODE "kód" // Button code +#define D_COLDLIGHT "Studené svetlo" +#define D_COMMAND "Príkaz" +#define D_CONNECTED "...pripojené" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Počítaj" +#define D_COUNTER "Počítadlo" +#define D_CURRENT "Prúd" // As in Voltage and Current +#define D_DATA "Dáta" +#define D_FLOW_RATE "Flow rate" +#define D_DARKLIGHT "Tmavý" +#define D_DEBUG "Debug" +#define D_DISABLED "Zablokované" +#define D_DISTANCE "Vzdialenosť" +#define D_DNS_SERVER "Server DNS" +#define D_DONE "Hotovo" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulácia" +#define D_ENABLED "Otvorený" +#define D_ERASE "Zmaž" +#define D_ERROR "Chyba" +#define D_FAHRENHEIT "Fahrenheita" +#define D_FAILED "chyba" +#define D_FALLBACK "Záložný" +#define D_FALLBACK_TOPIC "Záložný topic" +#define D_FALSE "Nepravda" +#define D_FILE "Súbor" +#define D_FREE_MEMORY "Voľná pamäť" +#define D_FREQUENCY "Frekvencia" +#define D_GAS "Plyn" +#define D_GATEWAY "Predvolená brána" +#define D_GROUP "Skupina" +#define D_HOST "Server" +#define D_HOSTNAME "Názov servera" +#define D_HUMIDITY "Vlhkosť" +#define D_ILLUMINANCE "Osvetlenie" +#define D_IMMEDIATE "Okamžité" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Informácie" +#define D_INFRARED "Infračervené" +#define D_INITIALIZED "Inicializovaný" +#define D_IP_ADDRESS "Adresa IP" +#define D_LIGHT "Svetlo" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-stlačenie" +#define D_NOISE "Hluk" +#define D_NONE "Žiadny" +#define D_OFF "Vyp." +#define D_OFFLINE "Neaktívny" +#define D_OK "OK" +#define D_ON "Zap." +#define D_ONLINE "Aktívny" +#define D_PASSWORD "Heslo" +#define D_PORT "Port" +#define D_POWER_FACTOR "Účinník" +#define D_POWERUSAGE "Príkon" +#define D_POWERUSAGE_ACTIVE "Činný príkon" +#define D_POWERUSAGE_APPARENT "Zdanlivý príkon" +#define D_POWERUSAGE_REACTIVE "Jalový príkon" +#define D_PRESSURE "Tlak" +#define D_PRESSUREATSEALEVEL "Tlak na hladine mora" +#define D_PROGRAM_FLASH_SIZE "Veľkosť flash pamäte" +#define D_PROGRAM_SIZE "Veľkosť programu" +#define D_PROJECT "Projekt" +#define D_RAIN "Dážď" +#define D_RECEIVED "Prijatý" +#define D_RESTART "Reštart" +#define D_RESTARTING "Reštartuje sa" +#define D_RESTART_REASON "Príčina reštartu" +#define D_RESTORE "Obnoviť" +#define D_RETAINED "Zachované" +#define D_RULE "Pravidlo" +#define D_SAVE "Ulož" +#define D_SENSOR "Senzor" +#define D_SSID "SSID" +#define D_START "Spustiť" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maska podsiete" +#define D_SUBSCRIBE_TO "Prihlásiť do" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "úspešné." +#define D_SUNRISE "Svitanie" +#define D_SUNSET "Súmrak" +#define D_TEMPERATURE "Teplota" +#define D_TO "do" +#define D_TOGGLE "Prepni" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Odošli" +#define D_TRUE "Pravda" +#define D_TVOC "TVOC" +#define D_UPGRADE "aktualizáciu" +#define D_UPLOAD "Nahrávanie..." +#define D_UPTIME "Uptime" +#define D_USER "Používateľ" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Nízky" +#define D_UV_INDEX_2 "Stredný" +#define D_UV_INDEX_3 "Vysoký" +#define D_UV_INDEX_4 "Nebezpečný" +#define D_UV_INDEX_5 "Popál1/2" +#define D_UV_INDEX_6 "Popál3" +#define D_UV_INDEX_7 "MimoRozsah" +#define D_UV_LEVEL "úroveň UV" +#define D_UV_POWER "UV Power" +#define D_VERSION "Verzia" +#define D_VOLTAGE "Napätie" +#define D_WEIGHT "Hmotnosť" +#define D_WARMLIGHT "Teplé svetlo" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "UPOZORNENIE Táto verzia nepodporuje trvalé nastavenia" +#define D_LEVEL_10 "úroveň 1-0" +#define D_LEVEL_01 "úroveň 0-1" +#define D_SERIAL_LOGGING_DISABLED "Logovanie na sériovom porte ukončené" +#define D_SYSLOG_LOGGING_REENABLED "Obnovený zápis do Syslog" + +#define D_SET_BAUDRATE_TO "Nastaviť rýchlosti prenosu na" +#define D_RECEIVED_TOPIC "Prijatý topic" +#define D_DATA_SIZE "Veľkosť dát" +#define D_ANALOG_INPUT "Analógový vstup" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Zablokovanie slučky" +#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig so statusom" +#define D_ACTIVE_FOR_3_MINUTES "aktívny 3 minúty" +#define D_FAILED_TO_START "nepodarilo sa spustiť" +#define D_PATCH_ISSUE_2186 "Chyba 2186" +#define D_CONNECTING_TO_AP "Pripájanie k AP" +#define D_IN_MODE "v režime" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba pripojenia, nebola obdržaná IP adresa" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba pripojenia, nedostupný AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba pripojenia, nesprávne heslo pre AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba pripojenia, uplynul AP timeout" +#define D_ATTEMPTING_CONNECTION "Pripájanie..." +#define D_CHECKING_CONNECTION "Skúška spojenia..." +#define D_QUERY_DONE "Vyslanie požiadavky. Nájdená služba MQTT" +#define D_MQTT_SERVICE_FOUND "Služba MQTT bola nájdená" +#define D_FOUND_AT "nájdené v" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebol nájdený" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Uložené do flash pamäte v" +#define D_LOADED_FROM_FLASH_AT "Stiahnuté z flash pamäte z" +#define D_USE_DEFAULTS "Použi prednastavené hodnoty" +#define D_ERASED_SECTOR "Zmazaný sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" +#define D_WEBSERVER_ACTIVE_ON "Aktívny Web server" +#define D_WITH_IP_ADDRESS "na IP adrese" +#define D_WEBSERVER_STOPPED "Web server zastavený" +#define D_FILE_NOT_FOUND "Súbor nebol nájdený" +#define D_REDIRECTED "Presmerovanie na vlastný portál" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manažér nastaví AP a zachová STA" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manažér nastaví Access Point" +#define D_TRYING_TO_CONNECT "Skúšam pripojiť zariadenie k sieti" + +#define D_RESTART_IN "Reštart" +#define D_SECONDS "sekúnd" +#define D_DEVICE_WILL_RESTART "Zariadenie bude reštartované behom niekoľkých sekúnd" +#define D_BUTTON_TOGGLE "Prepínač" +#define D_CONFIGURATION "Nastavenia" +#define D_INFORMATION "Informácie" +#define D_FIRMWARE_UPGRADE "Aktualizácia firmware" +#define D_CONSOLE "Konzola" +#define D_CONFIRM_RESTART "Potvrdenie reštartu" + +#define D_CONFIGURE_MODULE "Nastavenia modulu" +#define D_CONFIGURE_WIFI "Nastavenia WiFi" +#define D_CONFIGURE_MQTT "Nastavenia MQTT" +#define D_CONFIGURE_DOMOTICZ "Nastavenia Domoticz" +#define D_CONFIGURE_LOGGING "Nastavenia logovania" +#define D_CONFIGURE_OTHER "Ostatné nastavenia" +#define D_CONFIRM_RESET_CONFIGURATION "Potvrdenie resetu nastavení" +#define D_RESET_CONFIGURATION "Reset nastavení" +#define D_BACKUP_CONFIGURATION "Záloha nastavení" +#define D_RESTORE_CONFIGURATION "Obnovenie nastavení" +#define D_MAIN_MENU "Hlavné menu" + +#define D_MODULE_PARAMETERS "Nastavenia modulu" +#define D_MODULE_TYPE "Typ modulu" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Nastavenia WiFi" +#define D_SCAN_FOR_WIFI_NETWORKS "Sken WiFi sietí" +#define D_SCAN_DONE "Sken dokončený" +#define D_NO_NETWORKS_FOUND "Sieť nebola nájdená" +#define D_REFRESH_TO_SCAN_AGAIN "Zopakovať sken" +#define D_DUPLICATE_ACCESSPOINT "Kópia AP" +#define D_SKIPPING_LOW_QUALITY "Preskočenie z dôvodu kvality signálu" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "Heslo AP1" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "Heslo AP2" + +#define D_MQTT_PARAMETERS "Nastavenia MQTT" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Celý topic" + +#define D_LOGGING_PARAMETERS "Voľba logovania" +#define D_SERIAL_LOG_LEVEL "Sériová úroveň logu" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Webová úroveň logu" +#define D_SYS_LOG_LEVEL "Systemová úroveň logu" +#define D_MORE_DEBUG "Viac debug informácí" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Interval telemetrie" + +#define D_OTHER_PARAMETERS "Ostatné nastavenia" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" +#define D_MQTT_ENABLE "MQTT aktívne" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Ulož nastavenia" +#define D_CONFIGURATION_SAVED "Nastavenia uložené" +#define D_CONFIGURATION_RESET "Nastavenia resetované" + +#define D_PROGRAM_VERSION "Verzia programu" +#define D_BUILD_DATE_AND_TIME "Datum a čas kompilácie" +#define D_CORE_AND_SDK_VERSION "Verzia Core/SDK" +#define D_FLASH_WRITE_COUNT "Počet zápisov do pamäte" +#define D_MAC_ADDRESS "Adresa MAC" +#define D_MQTT_HOST "Host MQTT" +#define D_MQTT_PORT "Port MQTT" +#define D_MQTT_CLIENT "Klient MQTT" +#define D_MQTT_USER "Používateľ MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT" +#define D_MQTT_FULL_TOPIC "Celý topic MQTT" +#define D_MDNS_DISCOVERY "Získavanie mDNS" +#define D_MDNS_ADVERTISE "Rozosielanie mDNS" +#define D_ESP_CHIP_ID "ID systému ESP" +#define D_FLASH_CHIP_ID "ID systému flash pamäte" +#define D_FLASH_CHIP_SIZE "Veľkosť flash" +#define D_FREE_PROGRAM_SPACE "Voľné místo pre program" + +#define D_UPGRADE_BY_WEBSERVER "Aktualizácia z Web serveru" +#define D_OTA_URL "URL OTA" +#define D_START_UPGRADE "Spustiť aktualizáciu" +#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizácia nahraním súboru" +#define D_UPLOAD_STARTED "Nahrávanie spustené" +#define D_UPGRADE_STARTED "Aktualizácia spustená" +#define D_UPLOAD_DONE "Nahrávanie ukončené" +#define D_UPLOAD_ERR_1 "Súbor nebol vybraný" +#define D_UPLOAD_ERR_2 "Málo miesta" +#define D_UPLOAD_ERR_3 "Magický byte má hodnotu inú než 0xE9" +#define D_UPLOAD_ERR_4 "Veľkosť programu je väčšia než skutočná veľkosť flash pamäte" +#define D_UPLOAD_ERR_5 "Chyba nahrávania, nesúhlasia porovnávané bity" +#define D_UPLOAD_ERR_6 "Chyba nahrávania. Spustený zápis do logu na úrovni 3" +#define D_UPLOAD_ERR_7 "Nahrávanie prerušené" +#define D_UPLOAD_ERR_8 "Nesprávny súbor" +#define D_UPLOAD_ERR_9 "Súbor je príliš veľký" +#define D_UPLOAD_ERR_10 "Chyba inicializácie RF chipu" +#define D_UPLOAD_ERR_11 "Chyba zmazania RF chipu" +#define D_UPLOAD_ERR_12 "Chyba pri zápise do RF chipu" +#define D_UPLOAD_ERR_13 "Chyba dekódovania RF firmwaru" +#define D_UPLOAD_ERROR_CODE "Chyba nahrávania" + +#define D_ENTER_COMMAND "Vlož príkaz" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni úroveň 2 zápisu Weblog, ak je očekávaná odpoveď" +#define D_NEED_USER_AND_PASSWORD "Vyžadovaný používateľ=&heslo=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifikuj odtlačok TLS..." +#define D_TLS_CONNECT_FAILED_TO "Nepripojené TLS do" +#define D_RETRY_IN "Zopakujem o" +#define D_VERIFIED "Overený odtlačok " +#define D_INSECURE "Nesprávne pripojenie z dôvodu chybného odtlačku TLS" +#define D_CONNECT_FAILED_TO "Nepodarilo sa nadviazať spojenie" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast je vypnutý" +#define D_MULTICAST_REJOINED "Multicast opäť pripojený" +#define D_MULTICAST_JOIN_FAILED "Multicast neúspešný" +#define D_FAILED_TO_SEND_RESPONSE "Nepodarilo sa odoslať odpoveď" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo základná udalosť" +#define D_WEMO_EVENT_SERVICE "WeMo servisná udalosť" +#define D_WEMO_META_SERVICE "WeMo meta udalosť" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Odpoveď odoslaná" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API nie je implementované" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovede odoslané" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Nastavenia Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Spinac idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak" + #define D_DOMOTICZ_POWER_ENERGY "Príkon,Energia" + #define D_DOMOTICZ_ILLUMINANCE "Osvetlenie" + #define D_DOMOTICZ_COUNT "Počítadlo/PM1" + #define D_DOMOTICZ_VOLTAGE "Napätie/PM2,5" + #define D_DOMOTICZ_CURRENT "Prúd/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Aktualizácia časovača" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Nastavenia časovača" +#define D_TIMER_PARAMETERS "Časovač" +#define D_TIMER_ENABLE "Povoľ časovače" +#define D_TIMER_ARM "Aktívne" +#define D_TIMER_TIME "Čas" +#define D_TIMER_DAYS "Dni" +#define D_TIMER_REPEAT "Opakovať" +#define D_TIMER_OUTPUT "Výstup" +#define D_TIMER_ACTION "Napájanie" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Nastavenie KNX" +#define D_KNX_PARAMETERS "KNX parametre" +#define D_KNX_GENERAL_CONFIG "Všeobecné" +#define D_KNX_PHYSICAL_ADDRESS "Fyzická adresa" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musí být jedinečná v sieti KNX )" +#define D_KNX_ENABLE "Povoľ KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dáta na odoslanie na skupinové adresy" +#define D_ADD "Pridať" +#define D_DELETE "Zmazať" +#define D_REPLY "Odpoveď" +#define D_KNX_GROUP_ADDRESS_TO_READ "Skupinové adresy pre príjem dát z" +#define D_RECEIVED_FROM "Prijaté z" +#define D_KNX_COMMAND_WRITE "Zapíš" +#define D_KNX_COMMAND_READ "Čítaj" +#define D_KNX_COMMAND_OTHER "Iné" +#define D_SENT_TO "pošli" +#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervovaná a nemôže byť použitá." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Spotreba dnes" +#define D_ENERGY_YESTERDAY "Spotreba včera" +#define D_ENERGY_TOTAL "Celková spotreba" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor DS18x20 obsadený" +#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" +#define D_SENSORS_FOUND "Nanájdený senzor DS18x20" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Čakanie na" +#define D_START_SIGNAL_LOW "nízký štartovací signál" +#define D_START_SIGNAL_HIGH "vysoký štartovací signál" +#define D_PULSE "impulz" +#define D_CHECKSUM_FAILURE "Chybný kontrolný súčet" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Senzor neobdržal príkaz ACK" +#define D_SHT1X_FOUND "SHT1X nanájdený" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "častíc" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. os-X" +#define D_AY_AXIS "Accel. os-Y" +#define D_AZ_AXIS "Accel. os-Z" +#define D_GX_AXIS "Gyro os-X" +#define D_GY_AXIS "Gyro os-Y" +#define D_GZ_AXIS "Gyro os-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Odstráňte záťaž" +#define D_HX_CAL_REFERENCE "Vložte referenčnú záťaž" +#define D_HX_CAL_DONE "Skalibrováné" +#define D_HX_CAL_FAIL "Chyba kalibráce" +#define D_RESET_HX711 "Reset váhy" +#define D_CONFIGURE_HX711 "Konfiguráce váhy" +#define D_HX711_PARAMETERS "Parametre váhy" +#define D_ITEM_WEIGHT "Vlastná hmotnosť" +#define D_REFERENCE_WEIGHT "Referenčná hmotnosť" +#define D_CALIBRATE "Kalibruj" +#define D_CALIBRATION "Kalibrácia" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Smer vetra" +#define D_TX20_WIND_SPEED "Rýchlosť vetra" +#define D_TX20_WIND_SPEED_AVG "Priemerná rýchlosť vetra" +#define D_TX20_WIND_SPEED_MAX "Maximálna rýchlosť vetra" +#define D_TX20_NORTH "S" +#define D_TX20_EAST "V" +#define D_TX20_SOUTH "J" +#define D_TX20_WEST "Z" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Žiaden" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Spínač" // Suffix "1" +#define D_SENSOR_BUTTON "Tlačidlo" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1", +#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Senzor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "hod" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sek" +#define D_UNIT_SECTORS "sektory" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_SK_SK_H_ diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index 51ffc2ae3..3edeaf193 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -1,701 +1,703 @@ -/* - sv-SE.h - localization for Swedish - Svenska for Tasmota - - Copyright (C) 2019 Gunnar Norin - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_SV_SE_H_ -#define _LANGUAGE_SV_SE_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.11 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -// https://www.science.co.il/language/Locale-codes.php -#define LANGUAGE_LCID 1053 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "sv" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "SönMånTisOnsTorFreLör" -#define D_MONTH3LIST "JanFebMarAprMajJunJulAugSepOktNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Luftkvalitet" -#define D_AP "AP" // Access Point -#define D_AS "som" -#define D_AUTO "AUTO" -#define D_BLINK "Blinka" -#define D_BLINKOFF "BlinkaAv" -#define D_BOOT_COUNT "Uppstartsräknare" -#define D_BRIGHTLIGHT "Ljust" -#define D_BSSID "BSSId" -#define D_BUTTON "Knapp" -#define D_BY "av" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Kanal" -#define D_CO2 "Koldioxid" -#define D_CODE "kod" // Button code -#define D_COLDLIGHT "Kallt" -#define D_COMMAND "Kommando" -#define D_CONNECTED "Ansluten" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Räkna" -#define D_COUNTER "Räknare" -#define D_CURRENT "Ström" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Mörkt" -#define D_DEBUG "Debug" -#define D_DISABLED "Inaktiverad" -#define D_DISTANCE "Distans" -#define D_DNS_SERVER "DNS-server" -#define D_DONE "Gjort" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulation" -#define D_ENABLED "Aktiverad" -#define D_ERASE "Ta bort" -#define D_ERROR "Fel" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Misslyckades" -#define D_FALLBACK "Reserv" -#define D_FALLBACK_TOPIC "Reservämne" -#define D_FALSE "Falskt" -#define D_FILE "Fil" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Ledigt minne" -#define D_FREQUENCY "Frekvens" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Grupp" -#define D_HOST "Värd" -#define D_HOSTNAME "Värdnamn" -#define D_HUMIDITY "Fuktighet" -#define D_ILLUMINANCE "Belysnings" -#define D_IMMEDIATE "Omedelbar" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infraröd" -#define D_INITIALIZED "Initialiserad" -#define D_IP_ADDRESS "IP-adress" -#define D_LIGHT "Ljus" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "fler tryck" -#define D_NOISE "Oväsen" -#define D_NONE "Ingen" -#define D_OFF "Av" -#define D_OFFLINE "Off-line" -#define D_OK "Ok" -#define D_ON "På" -#define D_ONLINE "Ansluten" -#define D_PASSWORD "Lösenord" -#define D_PORT "Port" -#define D_POWER_FACTOR "Spänningsfaktor" -#define D_POWERUSAGE "Spänning" -#define D_POWERUSAGE_ACTIVE "Aktiv spänning" -#define D_POWERUSAGE_APPARENT "Skenbar spänning" -#define D_POWERUSAGE_REACTIVE "Responsiv spänning" -#define D_PRESSURE "Tryck" -#define D_PRESSUREATSEALEVEL "Havstryck" -#define D_PROGRAM_FLASH_SIZE "Program-flashstorlek" -#define D_PROGRAM_SIZE "Programstorlek" -#define D_PROJECT "Projekt" -#define D_RAIN "Regn" -#define D_RECEIVED "Mottagen" -#define D_RESTART "Omstart" -#define D_RESTARTING "Startar om" -#define D_RESTART_REASON "Omstartsorsak" -#define D_RESTORE "återställ" -#define D_RETAINED "bevarad" -#define D_RULE "Regel" -#define D_SAVE "Spara" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Starta" -#define D_STD_TIME "STD" -#define D_STOP "Stoppa" -#define D_SUBNET_MASK "Nätmask" -#define D_SUBSCRIBE_TO "Prenumera på" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Lyckat" -#define D_SUNRISE "Soluppgång" -#define D_SUNSET "Solnedgång" -#define D_TEMPERATURE "Temperatur" -#define D_TO "till" -#define D_TOGGLE "Växla" -#define D_TOPIC "Ämne" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Sänd" -#define D_TRUE "Sant" -#define D_TVOC "TVOC" -#define D_UPGRADE "uppgradera" -#define D_UPLOAD "Ladda upp" -#define D_UPTIME "Upptid" -#define D_USER "Användare" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Låg" -#define D_UV_INDEX_2 "Med" -#define D_UV_INDEX_3 "Hög" -#define D_UV_INDEX_4 "Farligt" -#define D_UV_INDEX_5 "Skadligt" -#define D_UV_INDEX_6 "Extremt" -#define D_UV_INDEX_7 "UO" // Out of Range -#define D_UV_LEVEL "UV nivå" -#define D_UV_POWER "UV kraft" -#define D_VERSION "Version" -#define D_VOLTAGE "Volttal" -#define D_WEIGHT "Vikt" -#define D_WARMLIGHT "Varm" -#define D_WEB_SERVER "Webbserver" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "VARNING Denna version supporterar inte beständiga inställningar" -#define D_LEVEL_10 "nivå 1-0" -#define D_LEVEL_01 "nivå 0-1" -#define D_SERIAL_LOGGING_DISABLED "Seriell loggning inaktiverad" -#define D_SYSLOG_LOGGING_REENABLED "Syslog återaktiverad" - -#define D_SET_BAUDRATE_TO "Ange Baudrate till" -#define D_RECEIVED_TOPIC "Mottaget ämne" -#define D_DATA_SIZE "Datastorlek" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blockerad loop" -#define D_WPS_FAILED_WITH_STATUS "WPS-konfigurering MISSLYCKADES med status" -#define D_ACTIVE_FOR_3_MINUTES "aktiv för 3 minuter" -#define D_FAILED_TO_START "misslyckades att starta" -#define D_PATCH_ISSUE_2186 "Laga problem 2186" -#define D_CONNECTING_TO_AP "Ansluter till AP" -#define D_IN_MODE "i läge" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Anslutning misslyckades mottog ingen IP-adress" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Anslutning misslyckades, kunde inte nå AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Anslutning misslyckades, fel lösenord för AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Anslutning misslyckadess med AP, timeout" -#define D_ATTEMPTING_CONNECTION "Försöker ansluta..." -#define D_CHECKING_CONNECTION "Kontrollerar anslutning..." -#define D_QUERY_DONE "Fråga utförd. MQTT-tjänster hittades" -#define D_MQTT_SERVICE_FOUND "MQTT-tjänst hittades på" -#define D_FOUND_AT "hittades vid" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog-värd hittades inte" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Sparade till flash vid" -#define D_LOADED_FROM_FLASH_AT "Laddade från flash vid" -#define D_USE_DEFAULTS "Använd standard" -#define D_ERASED_SECTOR "Rensade sektor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" -#define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" -#define D_WITH_IP_ADDRESS "med IP-adress" -#define D_WEBSERVER_STOPPED "Webbserver stoppad" -#define D_FILE_NOT_FOUND "Filen hittades inte" -#define D_REDIRECTED "Omdirigerad till fångstportal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifihanterare ange accesspunkt och behåll station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifihanterare ange accesspunkt" -#define D_TRYING_TO_CONNECT "Försöker att ansluta enheten till nätverk" - -#define D_RESTART_IN "Omstart om" -#define D_SECONDS "sekunder" -#define D_DEVICE_WILL_RESTART "Enheten kommer att starta om inom ett antal sekunder" -#define D_BUTTON_TOGGLE "Växla" -#define D_CONFIGURATION "Konfigurering" -#define D_INFORMATION "Information" -#define D_FIRMWARE_UPGRADE "Uppgradera firmware" -#define D_CONSOLE "Konsol" -#define D_CONFIRM_RESTART "Bekräfta omstart" - -#define D_CONFIGURE_MODULE "Konfigurera modul" -#define D_CONFIGURE_WIFI "Konfigurera WiFi" -#define D_CONFIGURE_MQTT "Konfigurera MQTT" -#define D_CONFIGURE_DOMOTICZ "Konfigurera Domoticz" -#define D_CONFIGURE_LOGGING "Konfigurera loggning" -#define D_CONFIGURE_OTHER "Konfigurera annat" -#define D_CONFIRM_RESET_CONFIGURATION "Bekräfta nollställning av konfiguration" -#define D_RESET_CONFIGURATION "Nollställ konfiguration" -#define D_BACKUP_CONFIGURATION "Säkerhetskopiera konfiguration" -#define D_RESTORE_CONFIGURATION "Återställ konfiguration" -#define D_MAIN_MENU "Huvudmeny" - -#define D_MODULE_PARAMETERS "Modulparameterar" -#define D_MODULE_TYPE "Modultyp" -#define D_PULLUP_ENABLE "Ingen knapp/brytare pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Seriell in" -#define D_SERIAL_OUT "Seriell ut" - -#define D_WIFI_PARAMETERS "Wifi-parameterar" -#define D_SCAN_FOR_WIFI_NETWORKS "Skanna efter wifi-nätverk" -#define D_SCAN_DONE "Skanning slutförd" -#define D_NO_NETWORKS_FOUND "Inga nätverk hittades" -#define D_REFRESH_TO_SCAN_AGAIN "Uppdatera för att skanna igen" -#define D_DUPLICATE_ACCESSPOINT "Dubblett accesspunkt" -#define D_SKIPPING_LOW_QUALITY "Hoppa över pga dålig kvalitet" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 lösenord" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 lösenord" - -#define D_MQTT_PARAMETERS "MQTT-parameterar" -#define D_CLIENT "Klient" -#define D_FULL_TOPIC "Fullt ämne" - -#define D_LOGGING_PARAMETERS "Loggningsparametrar" -#define D_SERIAL_LOG_LEVEL "Seriell loggnivå" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Webb loggnivå" -#define D_SYS_LOG_LEVEL "Syslog-nivå" -#define D_MORE_DEBUG "Mer debugging" -#define D_SYSLOG_HOST "Syslog-värd" -#define D_SYSLOG_PORT "Syslog-port" -#define D_TELEMETRY_PERIOD "Telemetriperiod" - -#define D_OTHER_PARAMETERS "Andra parametrar" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Webbadmin-lösenord" -#define D_MQTT_ENABLE "MQTT aktivera" -#define D_FRIENDLY_NAME "Läsbart namn" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "soloenhet" -#define D_MULTI_DEVICE "multienhet" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Spara konfiguration" -#define D_CONFIGURATION_SAVED "Konfiguration sparad" -#define D_CONFIGURATION_RESET "Konfiguration nollställd" - -#define D_PROGRAM_VERSION "Programversion" -#define D_BUILD_DATE_AND_TIME "Kompilerings datum & tid" -#define D_CORE_AND_SDK_VERSION "Core/SDK version" -#define D_FLASH_WRITE_COUNT "Flash-skrivningsräknare" -#define D_MAC_ADDRESS "MAC-adress" -#define D_MQTT_HOST "MQTT-värd" -#define D_MQTT_PORT "MQTT-port" -#define D_MQTT_CLIENT "MQTT-klient" -#define D_MQTT_USER "MQTT-användare" -#define D_MQTT_TOPIC "MQTT-ämne" -#define D_MQTT_GROUP_TOPIC "MQTT gruppämne" -#define D_MQTT_FULL_TOPIC "MQTT fullt ämne" -#define D_MDNS_DISCOVERY "mDNS upptäckning" -#define D_MDNS_ADVERTISE "mDNS annonsering" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash-storlek" -#define D_FREE_PROGRAM_SPACE "Ledigt programutrymme" - -#define D_UPGRADE_BY_WEBSERVER "Uppgradering via webbserver" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Starta uppdatering" -#define D_UPGRADE_BY_FILE_UPLOAD "Uppgradering via filuppladdning" -#define D_UPLOAD_STARTED "Uppladdning startad" -#define D_UPGRADE_STARTED "Uppgradeing startad" -#define D_UPLOAD_DONE "Uppladdning klar" -#define D_UPLOAD_ERR_1 "Ingen fil vald" -#define D_UPLOAD_ERR_2 "Inte tillräckligt med ledigt utrymme" -#define D_UPLOAD_ERR_3 "Magisk byte är inte 0xE9" -#define D_UPLOAD_ERR_4 "Programmets flashstorlek är större än den verkliga flashstorleken" -#define D_UPLOAD_ERR_5 "Uppladdningbuffert stämmer inte överens" -#define D_UPLOAD_ERR_6 "Uppladdning misslyckad. Aktivera loggning 3" -#define D_UPLOAD_ERR_7 "Uppladdning avbruten" -#define D_UPLOAD_ERR_8 "Ogiltig fil" -#define D_UPLOAD_ERR_9 "För stor fil" -#define D_UPLOAD_ERR_10 "Misslyckades initera RF chip" -#define D_UPLOAD_ERR_11 "Misslyckades rensa RF chip" -#define D_UPLOAD_ERR_12 "Misslyckades skriva till RF chip" -#define D_UPLOAD_ERR_13 "Misslyckades avkoda RF firmware" -#define D_UPLOAD_ERROR_CODE "Uppladdningsfelkod" - -#define D_ENTER_COMMAND "Ange kommando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivera webblogg 2 om svar förväntas" -#define D_NEED_USER_AND_PASSWORD "Behöver user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifierar TLS fingeravtryck..." -#define D_TLS_CONNECT_FAILED_TO "TLS-anslutning misslyckades" -#define D_RETRY_IN "Försöker igen om" -#define D_VERIFIED "Verifierad med fingeravtryck" -#define D_INSECURE "Osäker anslutning pga ogiltigt fingeravtryck" -#define D_CONNECT_FAILED_TO "Anslutning misslyckades" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast inaktiverad" -#define D_MULTICAST_REJOINED "Multicast (åter)anslöt" -#define D_MULTICAST_JOIN_FAILED "Multicast anslutning misslyckades" -#define D_FAILED_TO_SEND_RESPONSE "Misslyckades skicka svar" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo standardhändelse" -#define D_WEMO_EVENT_SERVICE "WeMo händelsetjänst" -#define D_WEMO_META_SERVICE "WeMo metatjänst" -#define D_WEMO_SETUP "WeMo installation" -#define D_RESPONSE_SENT "Svar skickat" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue installation" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API inte implementerat" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 svarspaket skickade" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parametetrar" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Nyckel idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Fuk" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Fuk,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Spänning,Energi" - #define D_DOMOTICZ_ILLUMINANCE "Belysningsstyrka" - #define D_DOMOTICZ_COUNT "Antal/PM1" - #define D_DOMOTICZ_VOLTAGE "Volt/PM2.5" - #define D_DOMOTICZ_CURRENT "Ström/PM10" - #define D_DOMOTICZ_AIRQUALITY "Luftkvalitet" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Uppdatera timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Konfigurera timer" -#define D_TIMER_PARAMETERS "Timerparametrar" -#define D_TIMER_ENABLE "Aktivera timer" -#define D_TIMER_ARM "Aktivera" -#define D_TIMER_TIME "Tid" -#define D_TIMER_DAYS "Dagar" -#define D_TIMER_REPEAT "Repetera" -#define D_TIMER_OUTPUT "Utgång" -#define D_TIMER_ACTION "Åtgärd" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Konfigurera KNX" -#define D_KNX_PARAMETERS "KNX Parametrar" -#define D_KNX_GENERAL_CONFIG "Allmänt" -#define D_KNX_PHYSICAL_ADDRESS "Fysisk adress" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Måste vara unik på KNX-nätverket )" -#define D_KNX_ENABLE "Aktivera KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data att skicka till gruppadresser" -#define D_ADD "Lägg till" -#define D_DELETE "Ta bort" -#define D_REPLY "Svara" -#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppadresser att ta emot data från" -#define D_RECEIVED_FROM "Mottagen från" -#define D_KNX_COMMAND_WRITE "Skriv" -#define D_KNX_COMMAND_READ "Läs" -#define D_KNX_COMMAND_OTHER "Andra" -#define D_SENT_TO "skickad till" -#define D_KNX_WARNING "Gruppadressen ( 0 / 0 / 0 ) är reserverad och kan inte användas." -#define D_KNX_ENHANCEMENT "Kommuniceringsförbättring" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energi idag" -#define D_ENERGY_YESTERDAY "Energi igår" -#define D_ENERGY_TOTAL "Energi totalt" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor upptagen" -#define D_SENSOR_CRC_ERROR "Sensor CRC-fel" -#define D_SENSORS_FOUND "Sensorer hittades" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout under väntan" -#define D_START_SIGNAL_LOW "startsignal låg" -#define D_START_SIGNAL_HIGH "startsignal hög" -#define D_PULSE "puls" -#define D_CHECKSUM_FAILURE "Fel kontrollsumma" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor besvarade inte med ACK kommando" -#define D_SHT1X_FOUND "SHT1X hittades" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partiklar" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axel" -#define D_AY_AXIS "Accel. Y-Axel" -#define D_AZ_AXIS "Accel. Z-Axel" -#define D_GX_AXIS "Gyro X-Axel" -#define D_GY_AXIS "Gyro Y-Axel" -#define D_GZ_AXIS "Gyro Z-Axel" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Ta bort vikter" -#define D_HX_CAL_REFERENCE "Ladda referensvikt" -#define D_HX_CAL_DONE "Kalibrerad" -#define D_HX_CAL_FAIL "Kalibrering misslyckad" -#define D_RESET_HX711 "Återställ våg" -#define D_CONFIGURE_HX711 "Konfigurera våg" -#define D_HX711_PARAMETERS "Vågparametrar" -#define D_ITEM_WEIGHT "Objektsvikt" -#define D_REFERENCE_WEIGHT "Referensvikt" -#define D_CALIBRATE "Kalibrera" -#define D_CALIBRATION "Kalibrering" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Vindriktning" -#define D_TX20_WIND_SPEED "Vindstyrka" -#define D_TX20_WIND_SPEED_AVG "Vindstyrka medel" -#define D_TX20_WIND_SPEED_MAX "Vindstyrka max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "Ö" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "V" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Ingen" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3-spelare" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Omkopplare" // Suffix "1" -#define D_SENSOR_BUTTON "Knapp" // Suffix "1" -#define D_SENSOR_RELAY "Relä" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Räknare" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Tim" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "ink" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sek" -#define D_UNIT_SECTORS "sektorer" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Fasvinkel" -#define D_IMPORT_ACTIVE "Import aktiv" -#define D_EXPORT_ACTIVE "Export aktiv" -#define D_IMPORT_REACTIVE "Import reaktiv" -#define D_EXPORT_REACTIVE "Export reaktiv" -#define D_TOTAL_REACTIVE "Total reaktiv" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_SV_SE_H_ +/* + sv-SE.h - localization for Swedish - Svenska for Tasmota + + Copyright (C) 2019 Gunnar Norin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_SV_SE_H_ +#define _LANGUAGE_SV_SE_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.11 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 1053 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "sv" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "SönMånTisOnsTorFreLör" +#define D_MONTH3LIST "JanFebMarAprMajJunJulAugSepOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Luftkvalitet" +#define D_AP "AP" // Access Point +#define D_AS "som" +#define D_AUTO "AUTO" +#define D_BLINK "Blinka" +#define D_BLINKOFF "BlinkaAv" +#define D_BOOT_COUNT "Uppstartsräknare" +#define D_BRIGHTLIGHT "Ljust" +#define D_BSSID "BSSId" +#define D_BUTTON "Knapp" +#define D_BY "av" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanal" +#define D_CO2 "Koldioxid" +#define D_CODE "kod" // Button code +#define D_COLDLIGHT "Kallt" +#define D_COMMAND "Kommando" +#define D_CONNECTED "Ansluten" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Räkna" +#define D_COUNTER "Räknare" +#define D_CURRENT "Ström" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Mörkt" +#define D_DEBUG "Debug" +#define D_DISABLED "Inaktiverad" +#define D_DISTANCE "Distans" +#define D_DNS_SERVER "DNS-server" +#define D_DONE "Gjort" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulation" +#define D_ENABLED "Aktiverad" +#define D_ERASE "Ta bort" +#define D_ERROR "Fel" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Misslyckades" +#define D_FALLBACK "Reserv" +#define D_FALLBACK_TOPIC "Reservämne" +#define D_FALSE "Falskt" +#define D_FILE "Fil" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Ledigt minne" +#define D_FREQUENCY "Frekvens" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupp" +#define D_HOST "Värd" +#define D_HOSTNAME "Värdnamn" +#define D_HUMIDITY "Fuktighet" +#define D_ILLUMINANCE "Belysnings" +#define D_IMMEDIATE "Omedelbar" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infraröd" +#define D_INITIALIZED "Initialiserad" +#define D_IP_ADDRESS "IP-adress" +#define D_LIGHT "Ljus" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "fler tryck" +#define D_NOISE "Oväsen" +#define D_NONE "Ingen" +#define D_OFF "Av" +#define D_OFFLINE "Off-line" +#define D_OK "Ok" +#define D_ON "På" +#define D_ONLINE "Ansluten" +#define D_PASSWORD "Lösenord" +#define D_PORT "Port" +#define D_POWER_FACTOR "Spänningsfaktor" +#define D_POWERUSAGE "Spänning" +#define D_POWERUSAGE_ACTIVE "Aktiv spänning" +#define D_POWERUSAGE_APPARENT "Skenbar spänning" +#define D_POWERUSAGE_REACTIVE "Responsiv spänning" +#define D_PRESSURE "Tryck" +#define D_PRESSUREATSEALEVEL "Havstryck" +#define D_PROGRAM_FLASH_SIZE "Program-flashstorlek" +#define D_PROGRAM_SIZE "Programstorlek" +#define D_PROJECT "Projekt" +#define D_RAIN "Regn" +#define D_RECEIVED "Mottagen" +#define D_RESTART "Omstart" +#define D_RESTARTING "Startar om" +#define D_RESTART_REASON "Omstartsorsak" +#define D_RESTORE "återställ" +#define D_RETAINED "bevarad" +#define D_RULE "Regel" +#define D_SAVE "Spara" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Starta" +#define D_STD_TIME "STD" +#define D_STOP "Stoppa" +#define D_SUBNET_MASK "Nätmask" +#define D_SUBSCRIBE_TO "Prenumera på" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Lyckat" +#define D_SUNRISE "Soluppgång" +#define D_SUNSET "Solnedgång" +#define D_TEMPERATURE "Temperatur" +#define D_TO "till" +#define D_TOGGLE "Växla" +#define D_TOPIC "Ämne" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Sänd" +#define D_TRUE "Sant" +#define D_TVOC "TVOC" +#define D_UPGRADE "uppgradera" +#define D_UPLOAD "Ladda upp" +#define D_UPTIME "Upptid" +#define D_USER "Användare" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Låg" +#define D_UV_INDEX_2 "Med" +#define D_UV_INDEX_3 "Hög" +#define D_UV_INDEX_4 "Farligt" +#define D_UV_INDEX_5 "Skadligt" +#define D_UV_INDEX_6 "Extremt" +#define D_UV_INDEX_7 "UO" // Out of Range +#define D_UV_LEVEL "UV nivå" +#define D_UV_POWER "UV kraft" +#define D_VERSION "Version" +#define D_VOLTAGE "Volttal" +#define D_WEIGHT "Vikt" +#define D_WARMLIGHT "Varm" +#define D_WEB_SERVER "Webbserver" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "VARNING Denna version supporterar inte beständiga inställningar" +#define D_LEVEL_10 "nivå 1-0" +#define D_LEVEL_01 "nivå 0-1" +#define D_SERIAL_LOGGING_DISABLED "Seriell loggning inaktiverad" +#define D_SYSLOG_LOGGING_REENABLED "Syslog återaktiverad" + +#define D_SET_BAUDRATE_TO "Ange Baudrate till" +#define D_RECEIVED_TOPIC "Mottaget ämne" +#define D_DATA_SIZE "Datastorlek" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blockerad loop" +#define D_WPS_FAILED_WITH_STATUS "WPS-konfigurering MISSLYCKADES med status" +#define D_ACTIVE_FOR_3_MINUTES "aktiv för 3 minuter" +#define D_FAILED_TO_START "misslyckades att starta" +#define D_PATCH_ISSUE_2186 "Laga problem 2186" +#define D_CONNECTING_TO_AP "Ansluter till AP" +#define D_IN_MODE "i läge" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Anslutning misslyckades mottog ingen IP-adress" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Anslutning misslyckades, kunde inte nå AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Anslutning misslyckades, fel lösenord för AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Anslutning misslyckadess med AP, timeout" +#define D_ATTEMPTING_CONNECTION "Försöker ansluta..." +#define D_CHECKING_CONNECTION "Kontrollerar anslutning..." +#define D_QUERY_DONE "Fråga utförd. MQTT-tjänster hittades" +#define D_MQTT_SERVICE_FOUND "MQTT-tjänst hittades på" +#define D_FOUND_AT "hittades vid" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog-värd hittades inte" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Sparade till flash vid" +#define D_LOADED_FROM_FLASH_AT "Laddade från flash vid" +#define D_USE_DEFAULTS "Använd standard" +#define D_ERASED_SECTOR "Rensade sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" +#define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" +#define D_WITH_IP_ADDRESS "med IP-adress" +#define D_WEBSERVER_STOPPED "Webbserver stoppad" +#define D_FILE_NOT_FOUND "Filen hittades inte" +#define D_REDIRECTED "Omdirigerad till fångstportal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifihanterare ange accesspunkt och behåll station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifihanterare ange accesspunkt" +#define D_TRYING_TO_CONNECT "Försöker att ansluta enheten till nätverk" + +#define D_RESTART_IN "Omstart om" +#define D_SECONDS "sekunder" +#define D_DEVICE_WILL_RESTART "Enheten kommer att starta om inom ett antal sekunder" +#define D_BUTTON_TOGGLE "Växla" +#define D_CONFIGURATION "Konfigurering" +#define D_INFORMATION "Information" +#define D_FIRMWARE_UPGRADE "Uppgradera firmware" +#define D_CONSOLE "Konsol" +#define D_CONFIRM_RESTART "Bekräfta omstart" + +#define D_CONFIGURE_MODULE "Konfigurera modul" +#define D_CONFIGURE_WIFI "Konfigurera WiFi" +#define D_CONFIGURE_MQTT "Konfigurera MQTT" +#define D_CONFIGURE_DOMOTICZ "Konfigurera Domoticz" +#define D_CONFIGURE_LOGGING "Konfigurera loggning" +#define D_CONFIGURE_OTHER "Konfigurera annat" +#define D_CONFIRM_RESET_CONFIGURATION "Bekräfta nollställning av konfiguration" +#define D_RESET_CONFIGURATION "Nollställ konfiguration" +#define D_BACKUP_CONFIGURATION "Säkerhetskopiera konfiguration" +#define D_RESTORE_CONFIGURATION "Återställ konfiguration" +#define D_MAIN_MENU "Huvudmeny" + +#define D_MODULE_PARAMETERS "Modulparameterar" +#define D_MODULE_TYPE "Modultyp" +#define D_PULLUP_ENABLE "Ingen knapp/brytare pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Seriell in" +#define D_SERIAL_OUT "Seriell ut" + +#define D_WIFI_PARAMETERS "Wifi-parameterar" +#define D_SCAN_FOR_WIFI_NETWORKS "Skanna efter wifi-nätverk" +#define D_SCAN_DONE "Skanning slutförd" +#define D_NO_NETWORKS_FOUND "Inga nätverk hittades" +#define D_REFRESH_TO_SCAN_AGAIN "Uppdatera för att skanna igen" +#define D_DUPLICATE_ACCESSPOINT "Dubblett accesspunkt" +#define D_SKIPPING_LOW_QUALITY "Hoppa över pga dålig kvalitet" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 lösenord" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 lösenord" + +#define D_MQTT_PARAMETERS "MQTT-parameterar" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Fullt ämne" + +#define D_LOGGING_PARAMETERS "Loggningsparametrar" +#define D_SERIAL_LOG_LEVEL "Seriell loggnivå" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Webb loggnivå" +#define D_SYS_LOG_LEVEL "Syslog-nivå" +#define D_MORE_DEBUG "Mer debugging" +#define D_SYSLOG_HOST "Syslog-värd" +#define D_SYSLOG_PORT "Syslog-port" +#define D_TELEMETRY_PERIOD "Telemetriperiod" + +#define D_OTHER_PARAMETERS "Andra parametrar" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Webbadmin-lösenord" +#define D_MQTT_ENABLE "MQTT aktivera" +#define D_FRIENDLY_NAME "Läsbart namn" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "soloenhet" +#define D_MULTI_DEVICE "multienhet" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Spara konfiguration" +#define D_CONFIGURATION_SAVED "Konfiguration sparad" +#define D_CONFIGURATION_RESET "Konfiguration nollställd" + +#define D_PROGRAM_VERSION "Programversion" +#define D_BUILD_DATE_AND_TIME "Kompilerings datum & tid" +#define D_CORE_AND_SDK_VERSION "Core/SDK version" +#define D_FLASH_WRITE_COUNT "Flash-skrivningsräknare" +#define D_MAC_ADDRESS "MAC-adress" +#define D_MQTT_HOST "MQTT-värd" +#define D_MQTT_PORT "MQTT-port" +#define D_MQTT_CLIENT "MQTT-klient" +#define D_MQTT_USER "MQTT-användare" +#define D_MQTT_TOPIC "MQTT-ämne" +#define D_MQTT_GROUP_TOPIC "MQTT gruppämne" +#define D_MQTT_FULL_TOPIC "MQTT fullt ämne" +#define D_MDNS_DISCOVERY "mDNS upptäckning" +#define D_MDNS_ADVERTISE "mDNS annonsering" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash-storlek" +#define D_FREE_PROGRAM_SPACE "Ledigt programutrymme" + +#define D_UPGRADE_BY_WEBSERVER "Uppgradering via webbserver" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Starta uppdatering" +#define D_UPGRADE_BY_FILE_UPLOAD "Uppgradering via filuppladdning" +#define D_UPLOAD_STARTED "Uppladdning startad" +#define D_UPGRADE_STARTED "Uppgradeing startad" +#define D_UPLOAD_DONE "Uppladdning klar" +#define D_UPLOAD_ERR_1 "Ingen fil vald" +#define D_UPLOAD_ERR_2 "Inte tillräckligt med ledigt utrymme" +#define D_UPLOAD_ERR_3 "Magisk byte är inte 0xE9" +#define D_UPLOAD_ERR_4 "Programmets flashstorlek är större än den verkliga flashstorleken" +#define D_UPLOAD_ERR_5 "Uppladdningbuffert stämmer inte överens" +#define D_UPLOAD_ERR_6 "Uppladdning misslyckad. Aktivera loggning 3" +#define D_UPLOAD_ERR_7 "Uppladdning avbruten" +#define D_UPLOAD_ERR_8 "Ogiltig fil" +#define D_UPLOAD_ERR_9 "För stor fil" +#define D_UPLOAD_ERR_10 "Misslyckades initera RF chip" +#define D_UPLOAD_ERR_11 "Misslyckades rensa RF chip" +#define D_UPLOAD_ERR_12 "Misslyckades skriva till RF chip" +#define D_UPLOAD_ERR_13 "Misslyckades avkoda RF firmware" +#define D_UPLOAD_ERROR_CODE "Uppladdningsfelkod" + +#define D_ENTER_COMMAND "Ange kommando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivera webblogg 2 om svar förväntas" +#define D_NEED_USER_AND_PASSWORD "Behöver user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifierar TLS fingeravtryck..." +#define D_TLS_CONNECT_FAILED_TO "TLS-anslutning misslyckades" +#define D_RETRY_IN "Försöker igen om" +#define D_VERIFIED "Verifierad med fingeravtryck" +#define D_INSECURE "Osäker anslutning pga ogiltigt fingeravtryck" +#define D_CONNECT_FAILED_TO "Anslutning misslyckades" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast inaktiverad" +#define D_MULTICAST_REJOINED "Multicast (åter)anslöt" +#define D_MULTICAST_JOIN_FAILED "Multicast anslutning misslyckades" +#define D_FAILED_TO_SEND_RESPONSE "Misslyckades skicka svar" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo standardhändelse" +#define D_WEMO_EVENT_SERVICE "WeMo händelsetjänst" +#define D_WEMO_META_SERVICE "WeMo metatjänst" +#define D_WEMO_SETUP "WeMo installation" +#define D_RESPONSE_SENT "Svar skickat" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue installation" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API inte implementerat" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 svarspaket skickade" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parametetrar" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Nyckel idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Fuk" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Fuk,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Spänning,Energi" + #define D_DOMOTICZ_ILLUMINANCE "Belysningsstyrka" + #define D_DOMOTICZ_COUNT "Antal/PM1" + #define D_DOMOTICZ_VOLTAGE "Volt/PM2.5" + #define D_DOMOTICZ_CURRENT "Ström/PM10" + #define D_DOMOTICZ_AIRQUALITY "Luftkvalitet" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Uppdatera timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Konfigurera timer" +#define D_TIMER_PARAMETERS "Timerparametrar" +#define D_TIMER_ENABLE "Aktivera timer" +#define D_TIMER_ARM "Aktivera" +#define D_TIMER_TIME "Tid" +#define D_TIMER_DAYS "Dagar" +#define D_TIMER_REPEAT "Repetera" +#define D_TIMER_OUTPUT "Utgång" +#define D_TIMER_ACTION "Åtgärd" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Konfigurera KNX" +#define D_KNX_PARAMETERS "KNX Parametrar" +#define D_KNX_GENERAL_CONFIG "Allmänt" +#define D_KNX_PHYSICAL_ADDRESS "Fysisk adress" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Måste vara unik på KNX-nätverket )" +#define D_KNX_ENABLE "Aktivera KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data att skicka till gruppadresser" +#define D_ADD "Lägg till" +#define D_DELETE "Ta bort" +#define D_REPLY "Svara" +#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppadresser att ta emot data från" +#define D_RECEIVED_FROM "Mottagen från" +#define D_KNX_COMMAND_WRITE "Skriv" +#define D_KNX_COMMAND_READ "Läs" +#define D_KNX_COMMAND_OTHER "Andra" +#define D_SENT_TO "skickad till" +#define D_KNX_WARNING "Gruppadressen ( 0 / 0 / 0 ) är reserverad och kan inte användas." +#define D_KNX_ENHANCEMENT "Kommuniceringsförbättring" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energi idag" +#define D_ENERGY_YESTERDAY "Energi igår" +#define D_ENERGY_TOTAL "Energi totalt" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor upptagen" +#define D_SENSOR_CRC_ERROR "Sensor CRC-fel" +#define D_SENSORS_FOUND "Sensorer hittades" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout under väntan" +#define D_START_SIGNAL_LOW "startsignal låg" +#define D_START_SIGNAL_HIGH "startsignal hög" +#define D_PULSE "puls" +#define D_CHECKSUM_FAILURE "Fel kontrollsumma" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor besvarade inte med ACK kommando" +#define D_SHT1X_FOUND "SHT1X hittades" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partiklar" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axel" +#define D_AY_AXIS "Accel. Y-Axel" +#define D_AZ_AXIS "Accel. Z-Axel" +#define D_GX_AXIS "Gyro X-Axel" +#define D_GY_AXIS "Gyro Y-Axel" +#define D_GZ_AXIS "Gyro Z-Axel" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Ta bort vikter" +#define D_HX_CAL_REFERENCE "Ladda referensvikt" +#define D_HX_CAL_DONE "Kalibrerad" +#define D_HX_CAL_FAIL "Kalibrering misslyckad" +#define D_RESET_HX711 "Återställ våg" +#define D_CONFIGURE_HX711 "Konfigurera våg" +#define D_HX711_PARAMETERS "Vågparametrar" +#define D_ITEM_WEIGHT "Objektsvikt" +#define D_REFERENCE_WEIGHT "Referensvikt" +#define D_CALIBRATE "Kalibrera" +#define D_CALIBRATION "Kalibrering" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Vindriktning" +#define D_TX20_WIND_SPEED "Vindstyrka" +#define D_TX20_WIND_SPEED_AVG "Vindstyrka medel" +#define D_TX20_WIND_SPEED_MAX "Vindstyrka max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "Ö" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "V" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Ingen" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3-spelare" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Omkopplare" // Suffix "1" +#define D_SENSOR_BUTTON "Knapp" // Suffix "1" +#define D_SENSOR_RELAY "Relä" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Räknare" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Tim" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "ink" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sek" +#define D_UNIT_SECTORS "sektorer" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Fasvinkel" +#define D_IMPORT_ACTIVE "Import aktiv" +#define D_EXPORT_ACTIVE "Export aktiv" +#define D_IMPORT_REACTIVE "Import reaktiv" +#define D_EXPORT_REACTIVE "Export reaktiv" +#define D_TOTAL_REACTIVE "Total reaktiv" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_SV_SE_H_ diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 6bc48c40f..02f89c833 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -1,701 +1,703 @@ -/* - tr-TR.h - localization for Turkish - Turkey for Tasmota - - Copyright (C) 2019 Ali Sait Teke and Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_TR_TR_H_ -#define _LANGUAGE_TR_TR_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.1.1 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1055 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "tr" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "." -#define D_MONTH_DAY_SEPARATOR "." -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "PazPztSalCarPerCumCmt" -#define D_MONTH3LIST "OckSubMarNisMayHazTemAguEylEkmKasAra" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Hava Kalitesi" -#define D_AP "AP" // Access Point -#define D_AS "as" -#define D_AUTO "OTOMATIK" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Yeniden başlama sayısı" -#define D_BRIGHTLIGHT "Işık" -#define D_BSSID "BSSId" -#define D_BUTTON "Buton" -#define D_BY "by" // Written by me -#define D_BYTES "Bayt" -#define D_CELSIUS "Derece" -#define D_CHANNEL "Channel" -#define D_CO2 "Karbon dioksit" -#define D_CODE "kod" // Button code -#define D_COLDLIGHT "Soğuk" -#define D_COMMAND "Komut" -#define D_CONNECTED "Bağlandı" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Sayı" -#define D_COUNTER "Sayaç" -#define D_CURRENT "Current" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Karanlık" -#define D_DEBUG "Hata Ayıklama" -#define D_DISABLED "Etkin Değil" -#define D_DISTANCE "Mesage" -#define D_DNS_SERVER "DNS Sunucu" -#define D_DONE "Tamam" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emülasyon" -#define D_ENABLED "Etkin" -#define D_ERASE "Temizle" -#define D_ERROR "Hata" -#define D_FAHRENHEIT "Fahrenayt" -#define D_FAILED "Başlarısız" -#define D_FALLBACK "Geri iletim" -#define D_FALLBACK_TOPIC "Geri İletim Topiği" -#define D_FALSE "False" -#define D_FILE "Dosya" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Boş Hafıza" -#define D_FREQUENCY "Frekans" -#define D_GAS "Gas" -#define D_GATEWAY "Geçit" -#define D_GROUP "Grup" -#define D_HOST "Host" -#define D_HOSTNAME "Host Adresi" -#define D_HUMIDITY "Nem" -#define D_ILLUMINANCE "Aydınlık" -#define D_IMMEDIATE "derhal" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Bilgi" -#define D_INFRARED "Kızılötesi" -#define D_INITIALIZED "Başlatıldı" -#define D_IP_ADDRESS "IP Adresi" -#define D_LIGHT "Işık" -#define D_LWT "LWT" -#define D_MODULE "Modül" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "Noise" -#define D_NONE "None" -#define D_OFF "Off" -#define D_OFFLINE "Çevirimdışı" -#define D_OK "Tamam" -#define D_ON "On" -#define D_ONLINE "Çevirimiçi" -#define D_PASSWORD "Şifre" -#define D_PORT "Port" -#define D_POWER_FACTOR "Güç Faktörü" -#define D_POWERUSAGE "Güç" -#define D_POWERUSAGE_ACTIVE "Aktif Güç" -#define D_POWERUSAGE_APPARENT "Görünen Güç" -#define D_POWERUSAGE_REACTIVE "Reaktif Güç" -#define D_PRESSURE "Basınç" -#define D_PRESSUREATSEALEVEL "Deniz Seviyesi Basıncı" -#define D_PROGRAM_FLASH_SIZE "Yazılım Flash Boyutu" -#define D_PROGRAM_SIZE "Yazılım Boyutu" -#define D_PROJECT "Proje" -#define D_RAIN "Rain" -#define D_RECEIVED "Alınan" -#define D_RESTART "Yeniden Başlat" -#define D_RESTARTING "Yeniden Başlatılıyor" -#define D_RESTART_REASON "Yeniden Başlatma Sebebi" -#define D_RESTORE "restore" -#define D_RETAINED "tutulan" -#define D_RULE "Kural" -#define D_SAVE "Kaydet" -#define D_SENSOR "Sensör" -#define D_SSID "SSId" -#define D_START "Başlat" -#define D_STD_TIME "STD" -#define D_STOP "Durdur" -#define D_SUBNET_MASK "Altağ Geçidi Maskesi" -#define D_SUBSCRIBE_TO "Abone olunan" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Başarıyla Tamamlandı" -#define D_SUNRISE "Gün doğumu" -#define D_SUNSET "Gün batımı" -#define D_TEMPERATURE "Sıcaklık" -#define D_TO "den" -#define D_TOGGLE "Geçiş Tuşu" -#define D_TOPIC "Başlık" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "İletim" -#define D_TRUE "True" -#define D_TVOC "TVOC" -#define D_UPGRADE "yükseltme" -#define D_UPLOAD "Yükleme" -#define D_UPTIME "Açık Kalma Süresi" -#define D_USER "Kullanıcı" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Indeksi" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "UV Seviyesi" -#define D_UV_POWER "UV Power" -#define D_VERSION "Versiyon" -#define D_VOLTAGE "Voltaj" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "Sıcak" -#define D_WEB_SERVER "Web Sunucusu" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "UYARI Bu versiyon ayarların kalıcı olarak kaydedilmesine olanak sağlamıyor" -#define D_LEVEL_10 "seviye 1-0" -#define D_LEVEL_01 "seviye 0-1" -#define D_SERIAL_LOGGING_DISABLED "Seri port loglaması kapalı" -#define D_SYSLOG_LOGGING_REENABLED "Sistem loglaması tekrar aktif" - -#define D_SET_BAUDRATE_TO "Baud hızını şu şekilde değiştir" -#define D_RECEIVED_TOPIC "Alınan Başlık" -#define D_DATA_SIZE "Veri Büyüklüğü" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Döngü bloke edildi" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" -#define D_ACTIVE_FOR_3_MINUTES "3 dakika aktif" -#define D_FAILED_TO_START "başlatma başarılı olamadı" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "AP'ye bağlan" -#define D_IN_MODE "modunda" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP adresi alınamadığı için bağlantı kurulamadı" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Ap'ye ulaşılamadı" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Girilen parolayı AP kabul etmedi" -#define D_CONNECT_FAILED_AP_TIMEOUT "AP'ye bağlanılırken süre aşımı oluştu" -#define D_ATTEMPTING_CONNECTION "Yeniden bağlanılıyor..." -#define D_CHECKING_CONNECTION "Bağlantı kontrol ediliyor..." -#define D_QUERY_DONE "Soru tamamlandı. MQTT servisleri bulundu" -#define D_MQTT_SERVICE_FOUND "Üzerinden MQTT serivisi tespit edildi" -#define D_FOUND_AT "(bulundu)" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog hostu bulunamadı" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Bellekten (Flash) kaydedidi:" -#define D_LOADED_FROM_FLASH_AT "Bellekten (Flash) okundu" -#define D_USE_DEFAULTS "Varsayılanları Kullan" -#define D_ERASED_SECTOR "Sektör temizlendi" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" -#define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif" -#define D_WITH_IP_ADDRESS "IP adres ile" -#define D_WEBSERVER_STOPPED "Web sunucusu durdu" -#define D_FILE_NOT_FOUND "Dosya Bulunamadı" -#define D_REDIRECTED "Portala yönlendirildiniz" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi yöneticisi AP olarak ayarlandı ve istasyon olarak bekletiliyor" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi yöneticisi AP olarak ayarlandı" -#define D_TRYING_TO_CONNECT "Cihaz ağa bağlanmaya çalışıyor" - -#define D_RESTART_IN "Burada tekrar başlat" -#define D_SECONDS "saniye" -#define D_DEVICE_WILL_RESTART "Birkaç saniye içerisinde cihaz tekrar başlatılacak" -#define D_BUTTON_TOGGLE "Toggle" -#define D_CONFIGURATION "Konfigürasyon" -#define D_INFORMATION "Bilgi" -#define D_FIRMWARE_UPGRADE "Cihaz yazılımını Güncelle" -#define D_CONSOLE "Konsol" -#define D_CONFIRM_RESTART "Yeniden Başlatmayı Onayla" - -#define D_CONFIGURE_MODULE "Modül Ayarlarını Değiştir" -#define D_CONFIGURE_WIFI "WiFi'i Ayarlarını Değiştir" -#define D_CONFIGURE_MQTT "MQTT'yi Ayarlarını Değiştir" -#define D_CONFIGURE_DOMOTICZ "Domoticz Ayarlarını Değiştir" -#define D_CONFIGURE_LOGGING "Loglama Ayarlarını Değiştir" -#define D_CONFIGURE_OTHER "Diğer Ayarları Değiştir" -#define D_CONFIRM_RESET_CONFIGURATION "Resetleme Ayarlarını Onayla" -#define D_RESET_CONFIGURATION "Tüm Ayarları Resetle" -#define D_BACKUP_CONFIGURATION "Ayarları Yedekle" -#define D_RESTORE_CONFIGURATION "Ayarları Geri Yükle" -#define D_MAIN_MENU "Ana Menü" - -#define D_MODULE_PARAMETERS "Modül parametreleri" -#define D_MODULE_TYPE "Modul türü" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Wifi parametreleri" -#define D_SCAN_FOR_WIFI_NETWORKS "Çevredeki Wifi Networklerini Tara" -#define D_SCAN_DONE "Tarama tamamladı" -#define D_NO_NETWORKS_FOUND "Herhangi wifi ağı bulunamadı" -#define D_REFRESH_TO_SCAN_AGAIN "Tekrar tarama - yenile" -#define D_DUPLICATE_ACCESSPOINT "AP'yi çoğalt" -#define D_SKIPPING_LOW_QUALITY "Düşük kalitedekileri dikkate alma" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 Adı (SSId)" -#define D_AP1_PASSWORD "AP1 Parolası" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Parolası" - -#define D_MQTT_PARAMETERS "MQTT parametreleri" -#define D_CLIENT "İstemci" -#define D_FULL_TOPIC "Tüm Başlık" - -#define D_LOGGING_PARAMETERS "Loglama parametreleri" -#define D_SERIAL_LOG_LEVEL "Serial log seviyesi" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web log seviyesi" -#define D_SYS_LOG_LEVEL "Syslog seviyesi" -#define D_MORE_DEBUG "Hata ayıklama devamı" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Telemetri peryodu" - -#define D_OTHER_PARAMETERS "Diğer parametreler" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Web Yönetici Şifresi" -#define D_MQTT_ENABLE "MQTT aktif" -#define D_FRIENDLY_NAME "Kullanıcı Dostu İsim" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "tekli cihaz" -#define D_MULTI_DEVICE "çoklu cihaz" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Ayarları Kaydet" -#define D_CONFIGURATION_SAVED "Ayarlar kaydedildi" -#define D_CONFIGURATION_RESET "Ayarlar resetlendi" - -#define D_PROGRAM_VERSION "Yazılım versiyonu" -#define D_BUILD_DATE_AND_TIME "Derleme Tarihi ve Saati" -#define D_CORE_AND_SDK_VERSION "Core/SDK Versiyonu" -#define D_FLASH_WRITE_COUNT "Belleğe (flash) Yazma Sayısı" -#define D_MAC_ADDRESS "MAC Adresi" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Port" -#define D_MQTT_CLIENT "MQTT İstemcisi" -#define D_MQTT_USER "MQTT Kullanıcısı" -#define D_MQTT_TOPIC "MQTT Topiği" -#define D_MQTT_GROUP_TOPIC "MQTT Grup Topiği" -#define D_MQTT_FULL_TOPIC "MQTT Full Topik" -#define D_MDNS_DISCOVERY "mDNS Keşfi" -#define D_MDNS_ADVERTISE "mDNS Yayını" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Boyutu" -#define D_FREE_PROGRAM_SPACE "Boşta Yazılım Alanı Boyutu" - -#define D_UPGRADE_BY_WEBSERVER "Web server kullanarak yükselt" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Yükseltmeyi başlat" -#define D_UPGRADE_BY_FILE_UPLOAD "Dosya kullanrak yükset" -#define D_UPLOAD_STARTED "Yükleme başlatıldı" -#define D_UPGRADE_STARTED "YÜkestlme başlatıldı" -#define D_UPLOAD_DONE "Yükleme Tamamlandı" -#define D_UPLOAD_ERR_1 "Dosya seçilmedi" -#define D_UPLOAD_ERR_2 "Boş yer yok" -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" -#define D_UPLOAD_ERR_4 "Yazılımın boyutu gerçek boyutundan fazla" -#define D_UPLOAD_ERR_5 "Upload buffer miscompare" -#define D_UPLOAD_ERR_6 "Yükleme başarısız. Enable logging 3" -#define D_UPLOAD_ERR_7 "Yükleme iptal edildi" -#define D_UPLOAD_ERR_8 "Geçersiz dosya" -#define D_UPLOAD_ERR_9 "File too large" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Upload error code" - -#define D_ENTER_COMMAND "Komut girişi" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" -#define D_NEED_USER_AND_PASSWORD "Need user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verify TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" -#define D_RETRY_IN "Retry in" -#define D_VERIFIED "Verified using Fingerprint" -#define D_INSECURE "Insecure connection due to invalid Fingerprint" -#define D_CONNECT_FAILED_TO "Connect failed to" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast kapalı" -#define D_MULTICAST_REJOINED "Multicast (tekrar)bağlanıldı" -#define D_MULTICAST_JOIN_FAILED "Multicast bağlantısı başarısız" -#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Response sent" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue kurulumu" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API'si entegre edilmedi" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argümanları" -#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Zamanlayıcıyı güncelle" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Zamanlayıcı Ayarları" -#define D_TIMER_PARAMETERS "Zamanlayıcı Parametreleri" -#define D_TIMER_ENABLE "Zamanlayıcı Aktif" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Zaman" -#define D_TIMER_DAYS "Gün" -#define D_TIMER_REPEAT "Tekrar" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX Ayarları" -#define D_KNX_PARAMETERS "KNX Parametreleri" -#define D_KNX_GENERAL_CONFIG "Genel Ayarlar" -#define D_KNX_PHYSICAL_ADDRESS "Fiziksel Addres" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "KNX Aktif" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Ekle" -#define D_DELETE "Sil" -#define D_REPLY "Cevapla" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Yaz" -#define D_KNX_COMMAND_READ "Oku" -#define D_KNX_COMMAND_OTHER "Diğer" -#define D_SENT_TO "gönder" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energy Today" -#define D_ENERGY_YESTERDAY "Energy Yesterday" -#define D_ENERGY_TOTAL "Energy Total" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensör başgül" -#define D_SENSOR_CRC_ERROR "Sensor CRC hatası" -#define D_SENSORS_FOUND "Sensörler bulundu" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" -#define D_START_SIGNAL_LOW "düşük sinyal başlat" -#define D_START_SIGNAL_HIGH "yüksek sinyal başlat" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "Checksum failure" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" -#define D_SHT1X_FOUND "SHT1X found" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_TR_TR_H_ +/* + tr-TR.h - localization for Turkish - Turkey for Tasmota + + Copyright (C) 2019 Ali Sait Teke and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_TR_TR_H_ +#define _LANGUAGE_TR_TR_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.1.1 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1055 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "tr" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "." +#define D_MONTH_DAY_SEPARATOR "." +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "PazPztSalCarPerCumCmt" +#define D_MONTH3LIST "OckSubMarNisMayHazTemAguEylEkmKasAra" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Hava Kalitesi" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "OTOMATIK" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Yeniden başlama sayısı" +#define D_BRIGHTLIGHT "Işık" +#define D_BSSID "BSSId" +#define D_BUTTON "Buton" +#define D_BY "by" // Written by me +#define D_BYTES "Bayt" +#define D_CELSIUS "Derece" +#define D_CHANNEL "Channel" +#define D_CO2 "Karbon dioksit" +#define D_CODE "kod" // Button code +#define D_COLDLIGHT "Soğuk" +#define D_COMMAND "Komut" +#define D_CONNECTED "Bağlandı" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Sayı" +#define D_COUNTER "Sayaç" +#define D_CURRENT "Current" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Karanlık" +#define D_DEBUG "Hata Ayıklama" +#define D_DISABLED "Etkin Değil" +#define D_DISTANCE "Mesage" +#define D_DNS_SERVER "DNS Sunucu" +#define D_DONE "Tamam" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emülasyon" +#define D_ENABLED "Etkin" +#define D_ERASE "Temizle" +#define D_ERROR "Hata" +#define D_FAHRENHEIT "Fahrenayt" +#define D_FAILED "Başlarısız" +#define D_FALLBACK "Geri iletim" +#define D_FALLBACK_TOPIC "Geri İletim Topiği" +#define D_FALSE "False" +#define D_FILE "Dosya" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Boş Hafıza" +#define D_FREQUENCY "Frekans" +#define D_GAS "Gas" +#define D_GATEWAY "Geçit" +#define D_GROUP "Grup" +#define D_HOST "Host" +#define D_HOSTNAME "Host Adresi" +#define D_HUMIDITY "Nem" +#define D_ILLUMINANCE "Aydınlık" +#define D_IMMEDIATE "derhal" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Bilgi" +#define D_INFRARED "Kızılötesi" +#define D_INITIALIZED "Başlatıldı" +#define D_IP_ADDRESS "IP Adresi" +#define D_LIGHT "Işık" +#define D_LWT "LWT" +#define D_MODULE "Modül" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "Noise" +#define D_NONE "None" +#define D_OFF "Off" +#define D_OFFLINE "Çevirimdışı" +#define D_OK "Tamam" +#define D_ON "On" +#define D_ONLINE "Çevirimiçi" +#define D_PASSWORD "Şifre" +#define D_PORT "Port" +#define D_POWER_FACTOR "Güç Faktörü" +#define D_POWERUSAGE "Güç" +#define D_POWERUSAGE_ACTIVE "Aktif Güç" +#define D_POWERUSAGE_APPARENT "Görünen Güç" +#define D_POWERUSAGE_REACTIVE "Reaktif Güç" +#define D_PRESSURE "Basınç" +#define D_PRESSUREATSEALEVEL "Deniz Seviyesi Basıncı" +#define D_PROGRAM_FLASH_SIZE "Yazılım Flash Boyutu" +#define D_PROGRAM_SIZE "Yazılım Boyutu" +#define D_PROJECT "Proje" +#define D_RAIN "Rain" +#define D_RECEIVED "Alınan" +#define D_RESTART "Yeniden Başlat" +#define D_RESTARTING "Yeniden Başlatılıyor" +#define D_RESTART_REASON "Yeniden Başlatma Sebebi" +#define D_RESTORE "restore" +#define D_RETAINED "tutulan" +#define D_RULE "Kural" +#define D_SAVE "Kaydet" +#define D_SENSOR "Sensör" +#define D_SSID "SSId" +#define D_START "Başlat" +#define D_STD_TIME "STD" +#define D_STOP "Durdur" +#define D_SUBNET_MASK "Altağ Geçidi Maskesi" +#define D_SUBSCRIBE_TO "Abone olunan" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Başarıyla Tamamlandı" +#define D_SUNRISE "Gün doğumu" +#define D_SUNSET "Gün batımı" +#define D_TEMPERATURE "Sıcaklık" +#define D_TO "den" +#define D_TOGGLE "Geçiş Tuşu" +#define D_TOPIC "Başlık" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "İletim" +#define D_TRUE "True" +#define D_TVOC "TVOC" +#define D_UPGRADE "yükseltme" +#define D_UPLOAD "Yükleme" +#define D_UPTIME "Açık Kalma Süresi" +#define D_USER "Kullanıcı" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Indeksi" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "UV Seviyesi" +#define D_UV_POWER "UV Power" +#define D_VERSION "Versiyon" +#define D_VOLTAGE "Voltaj" +#define D_WEIGHT "Weight" +#define D_WARMLIGHT "Sıcak" +#define D_WEB_SERVER "Web Sunucusu" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "UYARI Bu versiyon ayarların kalıcı olarak kaydedilmesine olanak sağlamıyor" +#define D_LEVEL_10 "seviye 1-0" +#define D_LEVEL_01 "seviye 0-1" +#define D_SERIAL_LOGGING_DISABLED "Seri port loglaması kapalı" +#define D_SYSLOG_LOGGING_REENABLED "Sistem loglaması tekrar aktif" + +#define D_SET_BAUDRATE_TO "Baud hızını şu şekilde değiştir" +#define D_RECEIVED_TOPIC "Alınan Başlık" +#define D_DATA_SIZE "Veri Büyüklüğü" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Döngü bloke edildi" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" +#define D_ACTIVE_FOR_3_MINUTES "3 dakika aktif" +#define D_FAILED_TO_START "başlatma başarılı olamadı" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "AP'ye bağlan" +#define D_IN_MODE "modunda" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP adresi alınamadığı için bağlantı kurulamadı" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Ap'ye ulaşılamadı" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Girilen parolayı AP kabul etmedi" +#define D_CONNECT_FAILED_AP_TIMEOUT "AP'ye bağlanılırken süre aşımı oluştu" +#define D_ATTEMPTING_CONNECTION "Yeniden bağlanılıyor..." +#define D_CHECKING_CONNECTION "Bağlantı kontrol ediliyor..." +#define D_QUERY_DONE "Soru tamamlandı. MQTT servisleri bulundu" +#define D_MQTT_SERVICE_FOUND "Üzerinden MQTT serivisi tespit edildi" +#define D_FOUND_AT "(bulundu)" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog hostu bulunamadı" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Bellekten (Flash) kaydedidi:" +#define D_LOADED_FROM_FLASH_AT "Bellekten (Flash) okundu" +#define D_USE_DEFAULTS "Varsayılanları Kullan" +#define D_ERASED_SECTOR "Sektör temizlendi" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" +#define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif" +#define D_WITH_IP_ADDRESS "IP adres ile" +#define D_WEBSERVER_STOPPED "Web sunucusu durdu" +#define D_FILE_NOT_FOUND "Dosya Bulunamadı" +#define D_REDIRECTED "Portala yönlendirildiniz" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi yöneticisi AP olarak ayarlandı ve istasyon olarak bekletiliyor" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi yöneticisi AP olarak ayarlandı" +#define D_TRYING_TO_CONNECT "Cihaz ağa bağlanmaya çalışıyor" + +#define D_RESTART_IN "Burada tekrar başlat" +#define D_SECONDS "saniye" +#define D_DEVICE_WILL_RESTART "Birkaç saniye içerisinde cihaz tekrar başlatılacak" +#define D_BUTTON_TOGGLE "Toggle" +#define D_CONFIGURATION "Konfigürasyon" +#define D_INFORMATION "Bilgi" +#define D_FIRMWARE_UPGRADE "Cihaz yazılımını Güncelle" +#define D_CONSOLE "Konsol" +#define D_CONFIRM_RESTART "Yeniden Başlatmayı Onayla" + +#define D_CONFIGURE_MODULE "Modül Ayarlarını Değiştir" +#define D_CONFIGURE_WIFI "WiFi'i Ayarlarını Değiştir" +#define D_CONFIGURE_MQTT "MQTT'yi Ayarlarını Değiştir" +#define D_CONFIGURE_DOMOTICZ "Domoticz Ayarlarını Değiştir" +#define D_CONFIGURE_LOGGING "Loglama Ayarlarını Değiştir" +#define D_CONFIGURE_OTHER "Diğer Ayarları Değiştir" +#define D_CONFIRM_RESET_CONFIGURATION "Resetleme Ayarlarını Onayla" +#define D_RESET_CONFIGURATION "Tüm Ayarları Resetle" +#define D_BACKUP_CONFIGURATION "Ayarları Yedekle" +#define D_RESTORE_CONFIGURATION "Ayarları Geri Yükle" +#define D_MAIN_MENU "Ana Menü" + +#define D_MODULE_PARAMETERS "Modül parametreleri" +#define D_MODULE_TYPE "Modul türü" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Wifi parametreleri" +#define D_SCAN_FOR_WIFI_NETWORKS "Çevredeki Wifi Networklerini Tara" +#define D_SCAN_DONE "Tarama tamamladı" +#define D_NO_NETWORKS_FOUND "Herhangi wifi ağı bulunamadı" +#define D_REFRESH_TO_SCAN_AGAIN "Tekrar tarama - yenile" +#define D_DUPLICATE_ACCESSPOINT "AP'yi çoğalt" +#define D_SKIPPING_LOW_QUALITY "Düşük kalitedekileri dikkate alma" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 Adı (SSId)" +#define D_AP1_PASSWORD "AP1 Parolası" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Parolası" + +#define D_MQTT_PARAMETERS "MQTT parametreleri" +#define D_CLIENT "İstemci" +#define D_FULL_TOPIC "Tüm Başlık" + +#define D_LOGGING_PARAMETERS "Loglama parametreleri" +#define D_SERIAL_LOG_LEVEL "Serial log seviyesi" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web log seviyesi" +#define D_SYS_LOG_LEVEL "Syslog seviyesi" +#define D_MORE_DEBUG "Hata ayıklama devamı" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Telemetri peryodu" + +#define D_OTHER_PARAMETERS "Diğer parametreler" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Web Yönetici Şifresi" +#define D_MQTT_ENABLE "MQTT aktif" +#define D_FRIENDLY_NAME "Kullanıcı Dostu İsim" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "tekli cihaz" +#define D_MULTI_DEVICE "çoklu cihaz" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Ayarları Kaydet" +#define D_CONFIGURATION_SAVED "Ayarlar kaydedildi" +#define D_CONFIGURATION_RESET "Ayarlar resetlendi" + +#define D_PROGRAM_VERSION "Yazılım versiyonu" +#define D_BUILD_DATE_AND_TIME "Derleme Tarihi ve Saati" +#define D_CORE_AND_SDK_VERSION "Core/SDK Versiyonu" +#define D_FLASH_WRITE_COUNT "Belleğe (flash) Yazma Sayısı" +#define D_MAC_ADDRESS "MAC Adresi" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Port" +#define D_MQTT_CLIENT "MQTT İstemcisi" +#define D_MQTT_USER "MQTT Kullanıcısı" +#define D_MQTT_TOPIC "MQTT Topiği" +#define D_MQTT_GROUP_TOPIC "MQTT Grup Topiği" +#define D_MQTT_FULL_TOPIC "MQTT Full Topik" +#define D_MDNS_DISCOVERY "mDNS Keşfi" +#define D_MDNS_ADVERTISE "mDNS Yayını" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash Boyutu" +#define D_FREE_PROGRAM_SPACE "Boşta Yazılım Alanı Boyutu" + +#define D_UPGRADE_BY_WEBSERVER "Web server kullanarak yükselt" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Yükseltmeyi başlat" +#define D_UPGRADE_BY_FILE_UPLOAD "Dosya kullanrak yükset" +#define D_UPLOAD_STARTED "Yükleme başlatıldı" +#define D_UPGRADE_STARTED "YÜkestlme başlatıldı" +#define D_UPLOAD_DONE "Yükleme Tamamlandı" +#define D_UPLOAD_ERR_1 "Dosya seçilmedi" +#define D_UPLOAD_ERR_2 "Boş yer yok" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "Yazılımın boyutu gerçek boyutundan fazla" +#define D_UPLOAD_ERR_5 "Upload buffer miscompare" +#define D_UPLOAD_ERR_6 "Yükleme başarısız. Enable logging 3" +#define D_UPLOAD_ERR_7 "Yükleme iptal edildi" +#define D_UPLOAD_ERR_8 "Geçersiz dosya" +#define D_UPLOAD_ERR_9 "File too large" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "Upload error code" + +#define D_ENTER_COMMAND "Komut girişi" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" +#define D_NEED_USER_AND_PASSWORD "Need user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verify TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" +#define D_RETRY_IN "Retry in" +#define D_VERIFIED "Verified using Fingerprint" +#define D_INSECURE "Insecure connection due to invalid Fingerprint" +#define D_CONNECT_FAILED_TO "Connect failed to" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast kapalı" +#define D_MULTICAST_REJOINED "Multicast (tekrar)bağlanıldı" +#define D_MULTICAST_JOIN_FAILED "Multicast bağlantısı başarısız" +#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Response sent" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue kurulumu" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API'si entegre edilmedi" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST argümanları" +#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Zamanlayıcıyı güncelle" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Zamanlayıcı Ayarları" +#define D_TIMER_PARAMETERS "Zamanlayıcı Parametreleri" +#define D_TIMER_ENABLE "Zamanlayıcı Aktif" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Zaman" +#define D_TIMER_DAYS "Gün" +#define D_TIMER_REPEAT "Tekrar" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX Ayarları" +#define D_KNX_PARAMETERS "KNX Parametreleri" +#define D_KNX_GENERAL_CONFIG "Genel Ayarlar" +#define D_KNX_PHYSICAL_ADDRESS "Fiziksel Addres" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "KNX Aktif" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Ekle" +#define D_DELETE "Sil" +#define D_REPLY "Cevapla" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Yaz" +#define D_KNX_COMMAND_READ "Oku" +#define D_KNX_COMMAND_OTHER "Diğer" +#define D_SENT_TO "gönder" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energy Today" +#define D_ENERGY_YESTERDAY "Energy Yesterday" +#define D_ENERGY_TOTAL "Energy Total" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensör başgül" +#define D_SENSOR_CRC_ERROR "Sensor CRC hatası" +#define D_SENSORS_FOUND "Sensörler bulundu" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" +#define D_START_SIGNAL_LOW "düşük sinyal başlat" +#define D_START_SIGNAL_HIGH "yüksek sinyal başlat" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "Checksum failure" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_TR_TR_H_ diff --git a/tasmota/language/uk-UK.h b/tasmota/language/uk-UK.h index b4a314630..98f87e932 100644 --- a/tasmota/language/uk-UK.h +++ b/tasmota/language/uk-UK.h @@ -1,701 +1,703 @@ -/* - uk-UK.h - localization for Ukrainian - Ukraine for Tasmota - - Copyright (C) 2019 Theo Arends / vadym-adik - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_UK_UK_H_ -#define _LANGUAGE_UK_UK_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.14.0a -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1058 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "uk" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "НедПонВівСерЧетПятСуб" -#define D_MONTH3LIST "СічЛютБерКвіТраЧерЛипСерВерЖовЛисГру" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Якість повітря" -#define D_AP "Точка доступу" // Access Point -#define D_AS "як" -#define D_AUTO "АВТО" -#define D_BLINK "Блимати" -#define D_BLINKOFF "Не блимати" -#define D_BOOT_COUNT "К-сть завант." -#define D_BRIGHTLIGHT "Яскравість" -#define D_BSSID "BSSId" -#define D_BUTTON "Кнопка" -#define D_BY " " // Written by me -#define D_BYTES "Байт" -#define D_CELSIUS "Цельсія" -#define D_CHANNEL "Канал" -#define D_CO2 "Вуглек. газ" -#define D_CODE "код" // Button code -#define D_COLDLIGHT "Холодний" -#define D_COMMAND "Команда" -#define D_CONNECTED "Під'єднано" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Розмір" -#define D_COUNTER "Лічильник" -#define D_CURRENT "Струм" // As in Voltage and Current -#define D_DATA "Дані" -#define D_DARKLIGHT "Темний" -#define D_DEBUG "Налагодження" -#define D_DISABLED "Заблоковано" -#define D_DISTANCE "Відстань" -#define D_DNS_SERVER "Сервер DNS" -#define D_DONE "Виконано" -#define D_DST_TIME "Літній час" -#define D_ECO2 "eCO2" -#define D_EMULATION "Емуляція" -#define D_ENABLED "Активно" -#define D_ERASE "Стирати" -#define D_ERROR "Помилка" -#define D_FAHRENHEIT "Фаренгейт" -#define D_FAILED "Невдало" -#define D_FALLBACK "Зворотній зв'язок" -#define D_FALLBACK_TOPIC "Топік зворотнього зв'язку" -#define D_FALSE "Ні" -#define D_FILE "Файл" -#define D_FLOW_RATE "Потік" -#define D_FREE_MEMORY "Вільна память" -#define D_FREQUENCY "Частота" -#define D_GAS "Газ" -#define D_GATEWAY "Шлюз" -#define D_GROUP "Група" -#define D_HOST "Хост" -#define D_HOSTNAME "Назва хосту" -#define D_HUMIDITY "Вологість" -#define D_ILLUMINANCE "Освітленність" -#define D_IMMEDIATE "Негайно" // Button immediate -#define D_INDEX "Індекс" -#define D_INFO "Інфо" -#define D_INFRARED "Інфрачервоний" -#define D_INITIALIZED "Ініціалізовано" -#define D_IP_ADDRESS "IP адреса" -#define D_LIGHT "Світло" -#define D_LWT "LWT" -#define D_MODULE "Модуль" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "Багаторазове натискання" -#define D_NOISE "Шум" -#define D_NONE "Нічого" -#define D_OFF "Вимк." -#define D_OFFLINE "Офф-лайн" -#define D_OK "Ок" -#define D_ON "Увімк." -#define D_ONLINE "Он-лайн" -#define D_PASSWORD "Гасло" -#define D_PORT "Порт" -#define D_POWER_FACTOR "Коефіцієнт потужності" -#define D_POWERUSAGE "Потужність" -#define D_POWERUSAGE_ACTIVE "Активна потужність" -#define D_POWERUSAGE_APPARENT "Дійсна потужність" -#define D_POWERUSAGE_REACTIVE "Реактивна потужність" -#define D_PRESSURE "Тиск" -#define D_PRESSUREATSEALEVEL "Тиск на рівні моря" -#define D_PROGRAM_FLASH_SIZE "Розмір Flash для програм" -#define D_PROGRAM_SIZE "Розмір програм" -#define D_PROJECT "Проект" -#define D_RAIN "Дощ" -#define D_RECEIVED "Отримано" -#define D_RESTART "Перезавантаження" -#define D_RESTARTING "Перезавантаження" -#define D_RESTART_REASON "Причина перезавантаження" -#define D_RESTORE "відновлення" -#define D_RETAINED "зберігати" -#define D_RULE "Правило" -#define D_SAVE "Зберегти" -#define D_SENSOR "Давач" -#define D_SSID "SSID" -#define D_START "Старт" -#define D_STD_TIME "Стандартний час" -#define D_STOP "Стоп" -#define D_SUBNET_MASK "Маска підмережі" -#define D_SUBSCRIBE_TO "Підписатись на" -#define D_UNSUBSCRIBE_FROM "Відписатися від" -#define D_SUCCESSFUL "Успішно" -#define D_SUNRISE "Схід сонця" -#define D_SUNSET "Захід сонця" -#define D_TEMPERATURE "Температура" -#define D_TO "до" -#define D_TOGGLE "Перекл." -#define D_TOPIC "Топік" -#define D_TOTAL_USAGE "Загальне споживання" -#define D_TRANSMIT "Передати" -#define D_TRUE "Так" -#define D_TVOC "TVOC" -#define D_UPGRADE "оновлення" -#define D_UPLOAD "Завантажити" -#define D_UPTIME "Час роботи" -#define D_USER "Користувач" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Індекс УФ" -#define D_UV_INDEX_1 "Низький" -#define D_UV_INDEX_2 "Середній" -#define D_UV_INDEX_3 "Високий" -#define D_UV_INDEX_4 "Небезпечний" -#define D_UV_INDEX_5 "Опіки 1/2 ступеня" -#define D_UV_INDEX_6 "Опіки 3 ступеня" -#define D_UV_INDEX_7 "Невідомий" -#define D_UV_LEVEL "Рівень УФ" -#define D_UV_POWER "Потужність УФ" -#define D_VERSION "Версія" -#define D_VOLTAGE "Напруга" -#define D_WEIGHT "Вага" -#define D_WARMLIGHT "Тепло" -#define D_WEB_SERVER "Web сервер" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ПОПЕРЕДЖЕННЯ! Ця версія не підтримує збереження налаштувань" -#define D_LEVEL_10 "рівень 1-0" -#define D_LEVEL_01 "рівень 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial журнал вимкнений" -#define D_SYSLOG_LOGGING_REENABLED "Syslog журнал увімкнений" - -#define D_SET_BAUDRATE_TO "Встановити швидкість передачі (Baudrate)" -#define D_RECEIVED_TOPIC "Отриманий Топік" -#define D_DATA_SIZE "Розмір даних" -#define D_ANALOG_INPUT "Напруга" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Цикл заблокований" -#define D_WPS_FAILED_WITH_STATUS "WPS конфігурація з статусом НЕВДАЛА" -#define D_ACTIVE_FOR_3_MINUTES "активний протягом 3 хвилин" -#define D_FAILED_TO_START "не вдалось запустити" -#define D_PATCH_ISSUE_2186 "Проблема з виправленням 2186" -#define D_CONNECTING_TO_AP "Підключення до AP" -#define D_IN_MODE "в режимі" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Помилка підключення, IP-адреса не отримана" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Помилка з'єднання, AP не знайдено" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Помилка з'єднання, невірне гасло до AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Помилка з'єднання з AP по тайм-ауту" -#define D_ATTEMPTING_CONNECTION "Спроба підключення..." -#define D_CHECKING_CONNECTION "Перевірка з'єднання..." -#define D_QUERY_DONE "Запит виконаний. Виявлено сервер MQTT" -#define D_MQTT_SERVICE_FOUND "MQTT сервер знайдено" -#define D_FOUND_AT "знайдено в" -#define D_SYSLOG_HOST_NOT_FOUND "Сервер журналу не знайдено" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Збережено в флэш-пам'ять" -#define D_LOADED_FROM_FLASH_AT "Завантажено з флэш-пам'яті" -#define D_USE_DEFAULTS "Використовувати значення за замовчуванням" -#define D_ERASED_SECTOR "Стерто сектор" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Для використання Tasmota треба увімкнути JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" -#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активний" -#define D_WITH_IP_ADDRESS "з IP-адресою" -#define D_WEBSERVER_STOPPED "Веб-сервер зупинений" -#define D_FILE_NOT_FOUND "Файл не знайдений" -#define D_REDIRECTED "Перенаправлено на адаптивний портал" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер встановлює Точку Доступу і зберігає параметри" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер встановив Точку Доступу" -#define D_TRYING_TO_CONNECT "Спроба підключення пристрою до мережі" - -#define D_RESTART_IN "Перезавантаження" -#define D_SECONDS "секунд" -#define D_DEVICE_WILL_RESTART "Пристрій буде перезавантажено через декілька секунд" -#define D_BUTTON_TOGGLE "Переключити" -#define D_CONFIGURATION "Конфігурація" -#define D_INFORMATION "Інформація" -#define D_FIRMWARE_UPGRADE "Оновлення прошивки" -#define D_CONSOLE "Консоль" -#define D_CONFIRM_RESTART "Підтвердити перезавантаження" - -#define D_CONFIGURE_MODULE "Конфігурація модуля" -#define D_CONFIGURE_WIFI "Конфігурація WiFi" -#define D_CONFIGURE_MQTT "Конфігурація MQTT" -#define D_CONFIGURE_DOMOTICZ "Конфігурація Domoticz" -#define D_CONFIGURE_LOGGING "Конфігурація журналів" -#define D_CONFIGURE_OTHER "Конфігурація інше" -#define D_CONFIRM_RESET_CONFIGURATION "Підтвердити скидання конфігурації" -#define D_RESET_CONFIGURATION "Скидання конфігурації" -#define D_BACKUP_CONFIGURATION "Резервне копіювання конфігурації" -#define D_RESTORE_CONFIGURATION "Відновлення конфігурації" -#define D_MAIN_MENU "Головне меню" - -#define D_MODULE_PARAMETERS "Параметри модуля" -#define D_MODULE_TYPE "Тип модуля" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "АЦП" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial вхід" -#define D_SERIAL_OUT "Serial вихід" - -#define D_WIFI_PARAMETERS "Параметри Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Сканування бездротовихих мереж Wifi" -#define D_SCAN_DONE "Сканування завершене" -#define D_NO_NETWORKS_FOUND "Не знайдено мереж" -#define D_REFRESH_TO_SCAN_AGAIN "Оновити для повторного сканування" -#define D_DUPLICATE_ACCESSPOINT "Дублювати Точку Доступу (AP)" -#define D_SKIPPING_LOW_QUALITY "Пропущено через низьку якість" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "AP1 гасло" -#define D_AP2_SSID "AP2 SSID" -#define D_AP2_PASSWORD "AP2 гасло" - -#define D_MQTT_PARAMETERS "Параметри MQTT" -#define D_CLIENT "Клієнт" -#define D_FULL_TOPIC "Повний Топік" - -#define D_LOGGING_PARAMETERS "Параметри журналу" -#define D_SERIAL_LOG_LEVEL "Serial рівень" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web рівень" -#define D_SYS_LOG_LEVEL "System рівень" -#define D_MORE_DEBUG "Додаткова інформація для налагодження" -#define D_SYSLOG_HOST "System хост" -#define D_SYSLOG_PORT "System порт" -#define D_TELEMETRY_PERIOD "Період телеметрії" - -#define D_OTHER_PARAMETERS "Параметри Інше" -#define D_TEMPLATE "Шаблони" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Гасло Web адміністратора" -#define D_MQTT_ENABLE "MQTT активний" -#define D_FRIENDLY_NAME "Дружнє Ім'я" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "одиночне" -#define D_MULTI_DEVICE "мульти" - -#define D_CONFIGURE_TEMPLATE "Конфігурація шаблона" -#define D_TEMPLATE_PARAMETERS "Параметри шаблона" -#define D_TEMPLATE_NAME "Назва" -#define D_BASE_TYPE "На основі" -#define D_TEMPLATE_FLAGS "Опції" - -#define D_SAVE_CONFIGURATION "Зберегти конфігурацію" -#define D_CONFIGURATION_SAVED "Конфігурація збережена " -#define D_CONFIGURATION_RESET "Конфігурація скинута" - -#define D_PROGRAM_VERSION "Версія програми" -#define D_BUILD_DATE_AND_TIME "Дата і час збірки" -#define D_CORE_AND_SDK_VERSION "Версія Core/SDK" -#define D_FLASH_WRITE_COUNT "Кількість записів Flash" -#define D_MAC_ADDRESS "MAC Адреса" -#define D_MQTT_HOST "MQTT Хост" -#define D_MQTT_PORT "MQTT Порт" -#define D_MQTT_CLIENT "MQTT ID Клієнта" -#define D_MQTT_USER "MQTT Користувач" -#define D_MQTT_TOPIC "MQTT Топік" -#define D_MQTT_GROUP_TOPIC "MQTT Топік групи" -#define D_MQTT_FULL_TOPIC "MQTT Топік повний" -#define D_MDNS_DISCOVERY "mDNS Виявлення" -#define D_MDNS_ADVERTISE "mDNS Транcляція" -#define D_ESP_CHIP_ID "ID чипу ESP" -#define D_FLASH_CHIP_ID "ID чипу Flash пам'яті" -#define D_FLASH_CHIP_SIZE "Розмір Flash пам'яті" -#define D_FREE_PROGRAM_SPACE "Вільний простір для програм" - -#define D_UPGRADE_BY_WEBSERVER "Оновлення через Веб-сервер" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Почати оновлення" -#define D_UPGRADE_BY_FILE_UPLOAD "Оновлення шляхом завантаження файлів" -#define D_UPLOAD_STARTED "Завантаження почалось" -#define D_UPGRADE_STARTED "Оновлення почалось" -#define D_UPLOAD_DONE "Завантаження завершено" -#define D_UPLOAD_ERR_1 "Файл не вибраний" -#define D_UPLOAD_ERR_2 "Недостатньо місця" -#define D_UPLOAD_ERR_3 "Магічний байт не 0xE9" -#define D_UPLOAD_ERR_4 "Размір прошивки більший, ніж размір Flash пам'яті" -#define D_UPLOAD_ERR_5 "Помилка завантаження буферу" -#define D_UPLOAD_ERR_6 "Помилка завантаження. Увімкнено лог рівень 3" -#define D_UPLOAD_ERR_7 "Завантаження перервано" -#define D_UPLOAD_ERR_8 "Файл невірний" -#define D_UPLOAD_ERR_9 "Занадто великий файл" -#define D_UPLOAD_ERR_10 "Помилка ініціалізаціції чипу FR" -#define D_UPLOAD_ERR_11 "Помилка стирання чипу RF" -#define D_UPLOAD_ERR_12 "Помилка запису чипу RF" -#define D_UPLOAD_ERR_13 "Помилка розкодування прошивки RF" -#define D_UPLOAD_ERROR_CODE "Код помилки завантаження" - -#define D_ENTER_COMMAND "Уведіть команду" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Увімкніть Веб лог рівня 2 якщо очікуєте відповідь" -#define D_NEED_USER_AND_PASSWORD "Очікується user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Перевірка відбитка TLS..." -#define D_TLS_CONNECT_FAILED_TO "Збій підключення TLS до" -#define D_RETRY_IN "Повторити" -#define D_VERIFIED "Перевірено відбиток" -#define D_INSECURE "Небезпечне з'єднання, недійсний відбиток" -#define D_CONNECT_FAILED_TO "Помилка підключення до" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast вимкнений" -#define D_MULTICAST_REJOINED "Multicast (пере)під'єднався" -#define D_MULTICAST_JOIN_FAILED "Multicast помилка з'єднання" -#define D_FAILED_TO_SEND_RESPONSE "Не вдалось надіслати відповідь" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo основна подія" -#define D_WEMO_EVENT_SERVICE "WeMo служба подій" -#define D_WEMO_META_SERVICE "WeMo мета-сервіс" -#define D_WEMO_SETUP "WeMo налаштування" -#define D_RESPONSE_SENT "Відповідь відіслана" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue налаштування" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API не реалізовано" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 пакету відповіді отримано" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz налаштування" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Ключ idx" -#define D_DOMOTICZ_SWITCH_IDX "Перемикач idx" -#define D_DOMOTICZ_SENSOR_IDX "Давач idx" - #define D_DOMOTICZ_TEMP "Температура" - #define D_DOMOTICZ_TEMP_HUM "Темп,Волог" - #define D_DOMOTICZ_TEMP_HUM_BARO "Темп,Волог,Тиск" - #define D_DOMOTICZ_POWER_ENERGY "Потуж,Енергія" - #define D_DOMOTICZ_ILLUMINANCE "Освітлення" - #define D_DOMOTICZ_COUNT "Лічильник/PM1" - #define D_DOMOTICZ_VOLTAGE "Напруга/PM2,5" - #define D_DOMOTICZ_CURRENT "Струм/PM10" - #define D_DOMOTICZ_AIRQUALITY "Якість повітря" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Оновлення таймерів" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Конфігурація таймерів" -#define D_TIMER_PARAMETERS "Налаштування таймерів" -#define D_TIMER_ENABLE "Таймери увімкнені" -#define D_TIMER_ARM "Увімкнений" -#define D_TIMER_TIME "Час" -#define D_TIMER_DAYS "Дні" -#define D_TIMER_REPEAT "Повтор" -#define D_TIMER_OUTPUT "Вихід" -#define D_TIMER_ACTION "Дія" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Конфігурація KNX" -#define D_KNX_PARAMETERS "Налаштування KNX" -#define D_KNX_GENERAL_CONFIG "Основні" -#define D_KNX_PHYSICAL_ADDRESS "Фізична адреса" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Має бути унікальною у мережі KNX)" -#define D_KNX_ENABLE "KNX Увімкнений" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Дані для запису групових адрес" -#define D_ADD "Додати" -#define D_DELETE "Видалити" -#define D_REPLY "Повторити" -#define D_KNX_GROUP_ADDRESS_TO_READ "Дані для читання групових адрес" -#define D_RECEIVED_FROM "Отримати з" -#define D_KNX_COMMAND_WRITE "Записати" -#define D_KNX_COMMAND_READ "Читати" -#define D_KNX_COMMAND_OTHER "Інше" -#define D_SENT_TO "надіслати до" -#define D_KNX_WARNING "Адреса групи (0/0/0) зарезервована і не може бути використана." -#define D_KNX_ENHANCEMENT "Підвищення зв'язку" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Енергія Сьогодні" -#define D_ENERGY_YESTERDAY "Енергія Вчора" -#define D_ENERGY_TOTAL "Енергія Всього" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Датчик DS18x20 зайнятий" -#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - помилка CRC" -#define D_SENSORS_FOUND "Датчик DS18x20 знайдено" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Тайм-аут, в очікуванні" -#define D_START_SIGNAL_LOW "стартовий сигнал низький" -#define D_START_SIGNAL_HIGH "стартовий сигнал високий" -#define D_PULSE "імпульс" -#define D_CHECKSUM_FAILURE "Помилка контрольної суми" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не підтвердив отримання команди" -#define D_SHT1X_FOUND "SHT1X знайдено" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Частинки понад" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Приск. Вісь-X" -#define D_AY_AXIS "Приск. Вісь-Y" -#define D_AZ_AXIS "Приск. Вісь-Z" -#define D_GX_AXIS "Орієнт Вісь-X" -#define D_GY_AXIS "Орієнт Вісь-Y" -#define D_GZ_AXIS "Орієнт Вісь-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Напрям вітру" -#define D_TX20_WIND_SPEED "Швидкість вітру" -#define D_TX20_WIND_SPEED_AVG "Середня швидкість вітру" -#define D_TX20_WIND_SPEED_MAX "Максимальна швидкість вітру" -#define D_TX20_NORTH "Пн" -#define D_TX20_EAST "Сх" -#define D_TX20_SOUTH "Пд" -#define D_TX20_WEST "Зх" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Немає" -#define D_SENSOR_USER "Користувач" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Перемикач" // Suffix "1" -#define D_SENSOR_BUTTON "Кнопка" // Suffix "1" -#define D_SENSOR_RELAY "Реле" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "ШІМ" // Suffix "1" -#define D_SENSOR_COUNTER "Лічильник" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Регулятор" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Зуммер" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "А" -#define D_UNIT_CENTIMETER "cм" -#define D_UNIT_HERTZ "Гц" -#define D_UNIT_HOUR "Г" -#define D_UNIT_GALLONS "гал" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "кг" -#define D_UNIT_KILOMETER_PER_HOUR "км/г" // or "km/h" -#define D_UNIT_KILOOHM "кОм" -#define D_UNIT_KILOWATTHOUR "кВт" -#define D_UNIT_LUX "лк" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" -#define D_UNIT_MICROMETER "мкм" -#define D_UNIT_MICROSECOND "мкс" -#define D_UNIT_MILLIAMPERE "мА" -#define D_UNIT_MILLIMETER "мм" -#define D_UNIT_MILLIMETER_MERCURY "ммHg" -#define D_UNIT_MILLISECOND "мс" -#define D_UNIT_MINUTE "хв" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "гПа" -#define D_UNIT_SECOND "сек" -#define D_UNIT_SECTORS "секторів" -#define D_UNIT_VA "ВА" -#define D_UNIT_VAR "ВАр" -#define D_UNIT_VOLT "В" -#define D_UNIT_WATT "Вт" -#define D_UNIT_WATTHOUR "Вт/Год" -#define D_UNIT_WATT_METER_QUADRAT "Вт/m²" - -//SDM220 -#define D_PHASE_ANGLE "Кут фази" -#define D_IMPORT_ACTIVE "Активна вхід" -#define D_EXPORT_ACTIVE "Активна вихід" -#define D_IMPORT_REACTIVE "Рекативна вхід" -#define D_EXPORT_REACTIVE "Реактивна вихід" -#define D_TOTAL_REACTIVE "Всього реактивна" -#define D_UNIT_KWARH "кВАр/г" -#define D_UNIT_ANGLE "Град" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_UK_UK_H_ +/* + uk-UK.h - localization for Ukrainian - Ukraine for Tasmota + + Copyright (C) 2019 Theo Arends / vadym-adik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_UK_UK_H_ +#define _LANGUAGE_UK_UK_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.14.0a +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1058 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "uk" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "НедПонВівСерЧетПятСуб" +#define D_MONTH3LIST "СічЛютБерКвіТраЧерЛипСерВерЖовЛисГру" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Якість повітря" +#define D_AP "Точка доступу" // Access Point +#define D_AS "як" +#define D_AUTO "АВТО" +#define D_BLINK "Блимати" +#define D_BLINKOFF "Не блимати" +#define D_BOOT_COUNT "К-сть завант." +#define D_BRIGHTLIGHT "Яскравість" +#define D_BSSID "BSSId" +#define D_BUTTON "Кнопка" +#define D_BY " " // Written by me +#define D_BYTES "Байт" +#define D_CELSIUS "Цельсія" +#define D_CHANNEL "Канал" +#define D_CO2 "Вуглек. газ" +#define D_CODE "код" // Button code +#define D_COLDLIGHT "Холодний" +#define D_COMMAND "Команда" +#define D_CONNECTED "Під'єднано" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Розмір" +#define D_COUNTER "Лічильник" +#define D_CURRENT "Струм" // As in Voltage and Current +#define D_DATA "Дані" +#define D_DARKLIGHT "Темний" +#define D_DEBUG "Налагодження" +#define D_DISABLED "Заблоковано" +#define D_DISTANCE "Відстань" +#define D_DNS_SERVER "Сервер DNS" +#define D_DONE "Виконано" +#define D_DST_TIME "Літній час" +#define D_ECO2 "eCO2" +#define D_EMULATION "Емуляція" +#define D_ENABLED "Активно" +#define D_ERASE "Стирати" +#define D_ERROR "Помилка" +#define D_FAHRENHEIT "Фаренгейт" +#define D_FAILED "Невдало" +#define D_FALLBACK "Зворотній зв'язок" +#define D_FALLBACK_TOPIC "Топік зворотнього зв'язку" +#define D_FALSE "Ні" +#define D_FILE "Файл" +#define D_FLOW_RATE "Потік" +#define D_FREE_MEMORY "Вільна память" +#define D_FREQUENCY "Частота" +#define D_GAS "Газ" +#define D_GATEWAY "Шлюз" +#define D_GROUP "Група" +#define D_HOST "Хост" +#define D_HOSTNAME "Назва хосту" +#define D_HUMIDITY "Вологість" +#define D_ILLUMINANCE "Освітленність" +#define D_IMMEDIATE "Негайно" // Button immediate +#define D_INDEX "Індекс" +#define D_INFO "Інфо" +#define D_INFRARED "Інфрачервоний" +#define D_INITIALIZED "Ініціалізовано" +#define D_IP_ADDRESS "IP адреса" +#define D_LIGHT "Світло" +#define D_LWT "LWT" +#define D_MODULE "Модуль" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "Багаторазове натискання" +#define D_NOISE "Шум" +#define D_NONE "Нічого" +#define D_OFF "Вимк." +#define D_OFFLINE "Офф-лайн" +#define D_OK "Ок" +#define D_ON "Увімк." +#define D_ONLINE "Он-лайн" +#define D_PASSWORD "Гасло" +#define D_PORT "Порт" +#define D_POWER_FACTOR "Коефіцієнт потужності" +#define D_POWERUSAGE "Потужність" +#define D_POWERUSAGE_ACTIVE "Активна потужність" +#define D_POWERUSAGE_APPARENT "Дійсна потужність" +#define D_POWERUSAGE_REACTIVE "Реактивна потужність" +#define D_PRESSURE "Тиск" +#define D_PRESSUREATSEALEVEL "Тиск на рівні моря" +#define D_PROGRAM_FLASH_SIZE "Розмір Flash для програм" +#define D_PROGRAM_SIZE "Розмір програм" +#define D_PROJECT "Проект" +#define D_RAIN "Дощ" +#define D_RECEIVED "Отримано" +#define D_RESTART "Перезавантаження" +#define D_RESTARTING "Перезавантаження" +#define D_RESTART_REASON "Причина перезавантаження" +#define D_RESTORE "відновлення" +#define D_RETAINED "зберігати" +#define D_RULE "Правило" +#define D_SAVE "Зберегти" +#define D_SENSOR "Давач" +#define D_SSID "SSID" +#define D_START "Старт" +#define D_STD_TIME "Стандартний час" +#define D_STOP "Стоп" +#define D_SUBNET_MASK "Маска підмережі" +#define D_SUBSCRIBE_TO "Підписатись на" +#define D_UNSUBSCRIBE_FROM "Відписатися від" +#define D_SUCCESSFUL "Успішно" +#define D_SUNRISE "Схід сонця" +#define D_SUNSET "Захід сонця" +#define D_TEMPERATURE "Температура" +#define D_TO "до" +#define D_TOGGLE "Перекл." +#define D_TOPIC "Топік" +#define D_TOTAL_USAGE "Загальне споживання" +#define D_TRANSMIT "Передати" +#define D_TRUE "Так" +#define D_TVOC "TVOC" +#define D_UPGRADE "оновлення" +#define D_UPLOAD "Завантажити" +#define D_UPTIME "Час роботи" +#define D_USER "Користувач" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Індекс УФ" +#define D_UV_INDEX_1 "Низький" +#define D_UV_INDEX_2 "Середній" +#define D_UV_INDEX_3 "Високий" +#define D_UV_INDEX_4 "Небезпечний" +#define D_UV_INDEX_5 "Опіки 1/2 ступеня" +#define D_UV_INDEX_6 "Опіки 3 ступеня" +#define D_UV_INDEX_7 "Невідомий" +#define D_UV_LEVEL "Рівень УФ" +#define D_UV_POWER "Потужність УФ" +#define D_VERSION "Версія" +#define D_VOLTAGE "Напруга" +#define D_WEIGHT "Вага" +#define D_WARMLIGHT "Тепло" +#define D_WEB_SERVER "Web сервер" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ПОПЕРЕДЖЕННЯ! Ця версія не підтримує збереження налаштувань" +#define D_LEVEL_10 "рівень 1-0" +#define D_LEVEL_01 "рівень 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial журнал вимкнений" +#define D_SYSLOG_LOGGING_REENABLED "Syslog журнал увімкнений" + +#define D_SET_BAUDRATE_TO "Встановити швидкість передачі (Baudrate)" +#define D_RECEIVED_TOPIC "Отриманий Топік" +#define D_DATA_SIZE "Розмір даних" +#define D_ANALOG_INPUT "Напруга" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Цикл заблокований" +#define D_WPS_FAILED_WITH_STATUS "WPS конфігурація з статусом НЕВДАЛА" +#define D_ACTIVE_FOR_3_MINUTES "активний протягом 3 хвилин" +#define D_FAILED_TO_START "не вдалось запустити" +#define D_PATCH_ISSUE_2186 "Проблема з виправленням 2186" +#define D_CONNECTING_TO_AP "Підключення до AP" +#define D_IN_MODE "в режимі" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Помилка підключення, IP-адреса не отримана" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Помилка з'єднання, AP не знайдено" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Помилка з'єднання, невірне гасло до AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Помилка з'єднання з AP по тайм-ауту" +#define D_ATTEMPTING_CONNECTION "Спроба підключення..." +#define D_CHECKING_CONNECTION "Перевірка з'єднання..." +#define D_QUERY_DONE "Запит виконаний. Виявлено сервер MQTT" +#define D_MQTT_SERVICE_FOUND "MQTT сервер знайдено" +#define D_FOUND_AT "знайдено в" +#define D_SYSLOG_HOST_NOT_FOUND "Сервер журналу не знайдено" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Збережено в флэш-пам'ять" +#define D_LOADED_FROM_FLASH_AT "Завантажено з флэш-пам'яті" +#define D_USE_DEFAULTS "Використовувати значення за замовчуванням" +#define D_ERASED_SECTOR "Стерто сектор" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Для використання Tasmota треба увімкнути JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" +#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активний" +#define D_WITH_IP_ADDRESS "з IP-адресою" +#define D_WEBSERVER_STOPPED "Веб-сервер зупинений" +#define D_FILE_NOT_FOUND "Файл не знайдений" +#define D_REDIRECTED "Перенаправлено на адаптивний портал" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер встановлює Точку Доступу і зберігає параметри" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер встановив Точку Доступу" +#define D_TRYING_TO_CONNECT "Спроба підключення пристрою до мережі" + +#define D_RESTART_IN "Перезавантаження" +#define D_SECONDS "секунд" +#define D_DEVICE_WILL_RESTART "Пристрій буде перезавантажено через декілька секунд" +#define D_BUTTON_TOGGLE "Переключити" +#define D_CONFIGURATION "Конфігурація" +#define D_INFORMATION "Інформація" +#define D_FIRMWARE_UPGRADE "Оновлення прошивки" +#define D_CONSOLE "Консоль" +#define D_CONFIRM_RESTART "Підтвердити перезавантаження" + +#define D_CONFIGURE_MODULE "Конфігурація модуля" +#define D_CONFIGURE_WIFI "Конфігурація WiFi" +#define D_CONFIGURE_MQTT "Конфігурація MQTT" +#define D_CONFIGURE_DOMOTICZ "Конфігурація Domoticz" +#define D_CONFIGURE_LOGGING "Конфігурація журналів" +#define D_CONFIGURE_OTHER "Конфігурація інше" +#define D_CONFIRM_RESET_CONFIGURATION "Підтвердити скидання конфігурації" +#define D_RESET_CONFIGURATION "Скидання конфігурації" +#define D_BACKUP_CONFIGURATION "Резервне копіювання конфігурації" +#define D_RESTORE_CONFIGURATION "Відновлення конфігурації" +#define D_MAIN_MENU "Головне меню" + +#define D_MODULE_PARAMETERS "Параметри модуля" +#define D_MODULE_TYPE "Тип модуля" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "АЦП" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial вхід" +#define D_SERIAL_OUT "Serial вихід" + +#define D_WIFI_PARAMETERS "Параметри Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Сканування бездротовихих мереж Wifi" +#define D_SCAN_DONE "Сканування завершене" +#define D_NO_NETWORKS_FOUND "Не знайдено мереж" +#define D_REFRESH_TO_SCAN_AGAIN "Оновити для повторного сканування" +#define D_DUPLICATE_ACCESSPOINT "Дублювати Точку Доступу (AP)" +#define D_SKIPPING_LOW_QUALITY "Пропущено через низьку якість" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "AP1 гасло" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "AP2 гасло" + +#define D_MQTT_PARAMETERS "Параметри MQTT" +#define D_CLIENT "Клієнт" +#define D_FULL_TOPIC "Повний Топік" + +#define D_LOGGING_PARAMETERS "Параметри журналу" +#define D_SERIAL_LOG_LEVEL "Serial рівень" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web рівень" +#define D_SYS_LOG_LEVEL "System рівень" +#define D_MORE_DEBUG "Додаткова інформація для налагодження" +#define D_SYSLOG_HOST "System хост" +#define D_SYSLOG_PORT "System порт" +#define D_TELEMETRY_PERIOD "Період телеметрії" + +#define D_OTHER_PARAMETERS "Параметри Інше" +#define D_TEMPLATE "Шаблони" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Гасло Web адміністратора" +#define D_MQTT_ENABLE "MQTT активний" +#define D_FRIENDLY_NAME "Дружнє Ім'я" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "одиночне" +#define D_MULTI_DEVICE "мульти" + +#define D_CONFIGURE_TEMPLATE "Конфігурація шаблона" +#define D_TEMPLATE_PARAMETERS "Параметри шаблона" +#define D_TEMPLATE_NAME "Назва" +#define D_BASE_TYPE "На основі" +#define D_TEMPLATE_FLAGS "Опції" + +#define D_SAVE_CONFIGURATION "Зберегти конфігурацію" +#define D_CONFIGURATION_SAVED "Конфігурація збережена " +#define D_CONFIGURATION_RESET "Конфігурація скинута" + +#define D_PROGRAM_VERSION "Версія програми" +#define D_BUILD_DATE_AND_TIME "Дата і час збірки" +#define D_CORE_AND_SDK_VERSION "Версія Core/SDK" +#define D_FLASH_WRITE_COUNT "Кількість записів Flash" +#define D_MAC_ADDRESS "MAC Адреса" +#define D_MQTT_HOST "MQTT Хост" +#define D_MQTT_PORT "MQTT Порт" +#define D_MQTT_CLIENT "MQTT ID Клієнта" +#define D_MQTT_USER "MQTT Користувач" +#define D_MQTT_TOPIC "MQTT Топік" +#define D_MQTT_GROUP_TOPIC "MQTT Топік групи" +#define D_MQTT_FULL_TOPIC "MQTT Топік повний" +#define D_MDNS_DISCOVERY "mDNS Виявлення" +#define D_MDNS_ADVERTISE "mDNS Транcляція" +#define D_ESP_CHIP_ID "ID чипу ESP" +#define D_FLASH_CHIP_ID "ID чипу Flash пам'яті" +#define D_FLASH_CHIP_SIZE "Розмір Flash пам'яті" +#define D_FREE_PROGRAM_SPACE "Вільний простір для програм" + +#define D_UPGRADE_BY_WEBSERVER "Оновлення через Веб-сервер" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Почати оновлення" +#define D_UPGRADE_BY_FILE_UPLOAD "Оновлення шляхом завантаження файлів" +#define D_UPLOAD_STARTED "Завантаження почалось" +#define D_UPGRADE_STARTED "Оновлення почалось" +#define D_UPLOAD_DONE "Завантаження завершено" +#define D_UPLOAD_ERR_1 "Файл не вибраний" +#define D_UPLOAD_ERR_2 "Недостатньо місця" +#define D_UPLOAD_ERR_3 "Магічний байт не 0xE9" +#define D_UPLOAD_ERR_4 "Размір прошивки більший, ніж размір Flash пам'яті" +#define D_UPLOAD_ERR_5 "Помилка завантаження буферу" +#define D_UPLOAD_ERR_6 "Помилка завантаження. Увімкнено лог рівень 3" +#define D_UPLOAD_ERR_7 "Завантаження перервано" +#define D_UPLOAD_ERR_8 "Файл невірний" +#define D_UPLOAD_ERR_9 "Занадто великий файл" +#define D_UPLOAD_ERR_10 "Помилка ініціалізаціції чипу FR" +#define D_UPLOAD_ERR_11 "Помилка стирання чипу RF" +#define D_UPLOAD_ERR_12 "Помилка запису чипу RF" +#define D_UPLOAD_ERR_13 "Помилка розкодування прошивки RF" +#define D_UPLOAD_ERROR_CODE "Код помилки завантаження" + +#define D_ENTER_COMMAND "Уведіть команду" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Увімкніть Веб лог рівня 2 якщо очікуєте відповідь" +#define D_NEED_USER_AND_PASSWORD "Очікується user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Перевірка відбитка TLS..." +#define D_TLS_CONNECT_FAILED_TO "Збій підключення TLS до" +#define D_RETRY_IN "Повторити" +#define D_VERIFIED "Перевірено відбиток" +#define D_INSECURE "Небезпечне з'єднання, недійсний відбиток" +#define D_CONNECT_FAILED_TO "Помилка підключення до" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast вимкнений" +#define D_MULTICAST_REJOINED "Multicast (пере)під'єднався" +#define D_MULTICAST_JOIN_FAILED "Multicast помилка з'єднання" +#define D_FAILED_TO_SEND_RESPONSE "Не вдалось надіслати відповідь" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo основна подія" +#define D_WEMO_EVENT_SERVICE "WeMo служба подій" +#define D_WEMO_META_SERVICE "WeMo мета-сервіс" +#define D_WEMO_SETUP "WeMo налаштування" +#define D_RESPONSE_SENT "Відповідь відіслана" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue налаштування" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API не реалізовано" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 пакету відповіді отримано" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz налаштування" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Ключ idx" +#define D_DOMOTICZ_SWITCH_IDX "Перемикач idx" +#define D_DOMOTICZ_SENSOR_IDX "Давач idx" + #define D_DOMOTICZ_TEMP "Температура" + #define D_DOMOTICZ_TEMP_HUM "Темп,Волог" + #define D_DOMOTICZ_TEMP_HUM_BARO "Темп,Волог,Тиск" + #define D_DOMOTICZ_POWER_ENERGY "Потуж,Енергія" + #define D_DOMOTICZ_ILLUMINANCE "Освітлення" + #define D_DOMOTICZ_COUNT "Лічильник/PM1" + #define D_DOMOTICZ_VOLTAGE "Напруга/PM2,5" + #define D_DOMOTICZ_CURRENT "Струм/PM10" + #define D_DOMOTICZ_AIRQUALITY "Якість повітря" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Оновлення таймерів" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Конфігурація таймерів" +#define D_TIMER_PARAMETERS "Налаштування таймерів" +#define D_TIMER_ENABLE "Таймери увімкнені" +#define D_TIMER_ARM "Увімкнений" +#define D_TIMER_TIME "Час" +#define D_TIMER_DAYS "Дні" +#define D_TIMER_REPEAT "Повтор" +#define D_TIMER_OUTPUT "Вихід" +#define D_TIMER_ACTION "Дія" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Конфігурація KNX" +#define D_KNX_PARAMETERS "Налаштування KNX" +#define D_KNX_GENERAL_CONFIG "Основні" +#define D_KNX_PHYSICAL_ADDRESS "Фізична адреса" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Має бути унікальною у мережі KNX)" +#define D_KNX_ENABLE "KNX Увімкнений" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Дані для запису групових адрес" +#define D_ADD "Додати" +#define D_DELETE "Видалити" +#define D_REPLY "Повторити" +#define D_KNX_GROUP_ADDRESS_TO_READ "Дані для читання групових адрес" +#define D_RECEIVED_FROM "Отримати з" +#define D_KNX_COMMAND_WRITE "Записати" +#define D_KNX_COMMAND_READ "Читати" +#define D_KNX_COMMAND_OTHER "Інше" +#define D_SENT_TO "надіслати до" +#define D_KNX_WARNING "Адреса групи (0/0/0) зарезервована і не може бути використана." +#define D_KNX_ENHANCEMENT "Підвищення зв'язку" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Енергія Сьогодні" +#define D_ENERGY_YESTERDAY "Енергія Вчора" +#define D_ENERGY_TOTAL "Енергія Всього" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Датчик DS18x20 зайнятий" +#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - помилка CRC" +#define D_SENSORS_FOUND "Датчик DS18x20 знайдено" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Тайм-аут, в очікуванні" +#define D_START_SIGNAL_LOW "стартовий сигнал низький" +#define D_START_SIGNAL_HIGH "стартовий сигнал високий" +#define D_PULSE "імпульс" +#define D_CHECKSUM_FAILURE "Помилка контрольної суми" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не підтвердив отримання команди" +#define D_SHT1X_FOUND "SHT1X знайдено" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Частинки понад" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Приск. Вісь-X" +#define D_AY_AXIS "Приск. Вісь-Y" +#define D_AZ_AXIS "Приск. Вісь-Z" +#define D_GX_AXIS "Орієнт Вісь-X" +#define D_GY_AXIS "Орієнт Вісь-Y" +#define D_GZ_AXIS "Орієнт Вісь-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Напрям вітру" +#define D_TX20_WIND_SPEED "Швидкість вітру" +#define D_TX20_WIND_SPEED_AVG "Середня швидкість вітру" +#define D_TX20_WIND_SPEED_MAX "Максимальна швидкість вітру" +#define D_TX20_NORTH "Пн" +#define D_TX20_EAST "Сх" +#define D_TX20_SOUTH "Пд" +#define D_TX20_WEST "Зх" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Немає" +#define D_SENSOR_USER "Користувач" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Перемикач" // Suffix "1" +#define D_SENSOR_BUTTON "Кнопка" // Suffix "1" +#define D_SENSOR_RELAY "Реле" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "ШІМ" // Suffix "1" +#define D_SENSOR_COUNTER "Лічильник" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Регулятор" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Зуммер" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "А" +#define D_UNIT_CENTIMETER "cм" +#define D_UNIT_HERTZ "Гц" +#define D_UNIT_HOUR "Г" +#define D_UNIT_GALLONS "гал" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "кг" +#define D_UNIT_KILOMETER_PER_HOUR "км/г" // or "km/h" +#define D_UNIT_KILOOHM "кОм" +#define D_UNIT_KILOWATTHOUR "кВт" +#define D_UNIT_LUX "лк" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" +#define D_UNIT_MICROMETER "мкм" +#define D_UNIT_MICROSECOND "мкс" +#define D_UNIT_MILLIAMPERE "мА" +#define D_UNIT_MILLIMETER "мм" +#define D_UNIT_MILLIMETER_MERCURY "ммHg" +#define D_UNIT_MILLISECOND "мс" +#define D_UNIT_MINUTE "хв" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "гПа" +#define D_UNIT_SECOND "сек" +#define D_UNIT_SECTORS "секторів" +#define D_UNIT_VA "ВА" +#define D_UNIT_VAR "ВАр" +#define D_UNIT_VOLT "В" +#define D_UNIT_WATT "Вт" +#define D_UNIT_WATTHOUR "Вт/Год" +#define D_UNIT_WATT_METER_QUADRAT "Вт/m²" + +//SDM220 +#define D_PHASE_ANGLE "Кут фази" +#define D_IMPORT_ACTIVE "Активна вхід" +#define D_EXPORT_ACTIVE "Активна вихід" +#define D_IMPORT_REACTIVE "Рекативна вхід" +#define D_EXPORT_REACTIVE "Реактивна вихід" +#define D_TOTAL_REACTIVE "Всього реактивна" +#define D_UNIT_KWARH "кВАр/г" +#define D_UNIT_ANGLE "Град" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_UK_UK_H_ diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 21aa63be3..275216007 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -1,701 +1,703 @@ -/* - zh-CN.h - localization for Chinese (Simplified) - China for Tasmota - - Copyright (C) 2019 Theo Arends (translated by killadm) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_ZH_CN_H_ -#define _LANGUAGE_ZH_CN_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.14.0b -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 2052 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "zh" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "日 一 二 三 四 五 六 " -#define D_MONTH3LIST "1月 2月 3月 4月 5月 6月 7月 8月 9月 10月11月12月" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "空气质量" -#define D_AP "AP" // Access Point -#define D_AS "名称:" -#define D_AUTO "自动" -#define D_BLINK "闪烁" -#define D_BLINKOFF "闪烁关" -#define D_BOOT_COUNT "启动次数" -#define D_BRIGHTLIGHT "亮" -#define D_BSSID "BSSId" -#define D_BUTTON "按钮" -#define D_BY "汉化: killadm 作者:" // Written by me -#define D_BYTES "大小:" -#define D_CELSIUS "摄氏" -#define D_CHANNEL "频道" -#define D_CO2 "二氧化碳" -#define D_CODE "代码" // Button code -#define D_COLDLIGHT "冷" -#define D_COMMAND "命令:" -#define D_CONNECTED "已连接" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "数量:" -#define D_COUNTER "计数器" -#define D_CURRENT "电流" // As in Voltage and Current -#define D_DATA "数据:" -#define D_DARKLIGHT "暗" -#define D_DEBUG "调试" -#define D_DISABLED "禁用" -#define D_DISTANCE "距离" -#define D_DNS_SERVER "DNS服务器" -#define D_DONE "完成" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "设备模拟" -#define D_ENABLED "启用" -#define D_ERASE "擦除" -#define D_ERROR "错误" -#define D_FAHRENHEIT "华氏" -#define D_FAILED "失败" -#define D_FALLBACK "回退" -#define D_FALLBACK_TOPIC "回退主题" -#define D_FALSE "False" -#define D_FILE "文件:" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "空闲内存" -#define D_FREQUENCY "频率" -#define D_GAS "气体" -#define D_GATEWAY "网关" -#define D_GROUP "组:" -#define D_HOST "主机" -#define D_HOSTNAME "主机名" -#define D_HUMIDITY "湿度" -#define D_ILLUMINANCE "照度" -#define D_IMMEDIATE "单次按键" // Button immediate -#define D_INDEX "索引:" -#define D_INFO "信息" -#define D_INFRARED "红外线" -#define D_INITIALIZED "初始化完成" -#define D_IP_ADDRESS "IP地址" -#define D_LIGHT "灯" -#define D_LWT "LWT" -#define D_MODULE "模块" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "多次按键" -#define D_NOISE "嘈杂" -#define D_NONE "无" -#define D_OFF "关" -#define D_OFFLINE "离线" -#define D_OK "好" -#define D_ON "开" -#define D_ONLINE "在线" -#define D_PASSWORD "密码" -#define D_PORT "端口" -#define D_POWER_FACTOR "功率因数" -#define D_POWERUSAGE "功率" -#define D_POWERUSAGE_ACTIVE "有功功率" -#define D_POWERUSAGE_APPARENT "视在功率" -#define D_POWERUSAGE_REACTIVE "无功功率" -#define D_PRESSURE "气压" -#define D_PRESSUREATSEALEVEL "海平面气压" -#define D_PROGRAM_FLASH_SIZE "固件 Flash 大小" -#define D_PROGRAM_SIZE "固件大小" -#define D_PROJECT "项目:" -#define D_RAIN "降水量" -#define D_RECEIVED "已接收" -#define D_RESTART "重启" -#define D_RESTARTING "正在重启" -#define D_RESTART_REASON "重启原因" -#define D_RESTORE "恢复" -#define D_RETAINED "已保留" -#define D_RULE "规则" -#define D_SAVE "保存" -#define D_SENSOR "传感器" -#define D_SSID "名称" -#define D_START "开始" -#define D_STD_TIME "STD" -#define D_STOP "停止" -#define D_SUBNET_MASK "子网掩码" -#define D_SUBSCRIBE_TO "订阅" -#define D_UNSUBSCRIBE_FROM "退订" -#define D_SUCCESSFUL "成功" -#define D_SUNRISE "日出" -#define D_SUNSET "日落" -#define D_TEMPERATURE "温度" -#define D_TO "to" -#define D_TOGGLE "切换" -#define D_TOPIC "主题" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "发送" -#define D_TRUE "True" -#define D_TVOC "TVOC" -#define D_UPGRADE "升级" -#define D_UPLOAD "上传" -#define D_UPTIME "运行时间" -#define D_USER "用户名" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "紫外线指数" -#define D_UV_INDEX_1 "低" -#define D_UV_INDEX_2 "中" -#define D_UV_INDEX_3 "高" -#define D_UV_INDEX_4 "危险" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "紫外线水平" -#define D_UV_POWER "紫外线功率 " -#define D_VERSION "版本" -#define D_VOLTAGE "电压" -#define D_WEIGHT "重量" -#define D_WARMLIGHT "暖" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "警告:精简固件不支持配置持久化保存" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "串口日志已禁用" -#define D_SYSLOG_LOGGING_REENABLED "Syslog 日志已开启" - -#define D_SET_BAUDRATE_TO "设置波特率为:" -#define D_RECEIVED_TOPIC "接收到的主题:" -#define D_DATA_SIZE "数据大小:" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPS 配置失败,状态:" -#define D_ACTIVE_FOR_3_MINUTES "激活 3 分钟" -#define D_FAILED_TO_START "未能启动" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "连接到 AP" -#define D_IN_MODE "模式:" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "连接失败,因为没有获取到 IP 地址" -#define D_CONNECT_FAILED_AP_NOT_REACHED "连接失败,无法连接 AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "连接失败,AP 密码不正确" -#define D_CONNECT_FAILED_AP_TIMEOUT "连接失败,AP 超时" -#define D_ATTEMPTING_CONNECTION "尝试连接..." -#define D_CHECKING_CONNECTION "检查连接..." -#define D_QUERY_DONE "查询完成。 发现 MQTT 服务" -#define D_MQTT_SERVICE_FOUND "发现 MQTT 服务:" -#define D_FOUND_AT "发现:" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog 主机未找到" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "保存到 flash:" -#define D_LOADED_FROM_FLASH_AT "从 flash 载入:" -#define D_USE_DEFAULTS "使用默认设置" -#define D_ERASED_SECTOR "擦除扇区" - -// webserver.ino -#define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" -#define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" -#define D_WITH_IP_ADDRESS "IP 地址:" -#define D_WEBSERVER_STOPPED "Web 服务已停止" -#define D_FILE_NOT_FOUND "文件未找到" -#define D_REDIRECTED "重定向到认证页面" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager 设置无线操作模式" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 设置接入点" -#define D_TRYING_TO_CONNECT "尝试将设备连接到网络" - -#define D_RESTART_IN "重启需要" -#define D_SECONDS "秒" -#define D_DEVICE_WILL_RESTART "设备将在几秒钟内重启" -#define D_BUTTON_TOGGLE "状态切换" -#define D_CONFIGURATION "设置" -#define D_INFORMATION "信息" -#define D_FIRMWARE_UPGRADE "固件升级" -#define D_CONSOLE "控制台" -#define D_CONFIRM_RESTART "确认重启" - -#define D_CONFIGURE_MODULE "模块设置" -#define D_CONFIGURE_WIFI "WiFi设置" -#define D_CONFIGURE_MQTT "MQTT设置" -#define D_CONFIGURE_DOMOTICZ "Domoticz设置" -#define D_CONFIGURE_LOGGING "日志设置" -#define D_CONFIGURE_OTHER "其他设置" -#define D_CONFIRM_RESET_CONFIGURATION "确认重置配置" -#define D_RESET_CONFIGURATION "重置配置" -#define D_BACKUP_CONFIGURATION "备份配置" -#define D_RESTORE_CONFIGURATION "还原配置" -#define D_MAIN_MENU "主菜单" - -#define D_MODULE_PARAMETERS "模块设置" -#define D_MODULE_TYPE "模块类型" -#define D_PULLUP_ENABLE "没有按钮/开关上拉" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "串口输入(RX)" -#define D_SERIAL_OUT "串口输出(TX)" - -#define D_WIFI_PARAMETERS "Wifi设置" -#define D_SCAN_FOR_WIFI_NETWORKS "扫描无线网络" -#define D_SCAN_DONE "扫描完毕" -#define D_NO_NETWORKS_FOUND "未找到任何网络" -#define D_REFRESH_TO_SCAN_AGAIN "刷新并重试" -#define D_DUPLICATE_ACCESSPOINT "重复AP" -#define D_SKIPPING_LOW_QUALITY "忽略弱信号网络" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 名称" -#define D_AP1_PASSWORD "AP1 密码" -#define D_AP2_SSID "AP2 名称" -#define D_AP2_PASSWORD "AP2 密码" - -#define D_MQTT_PARAMETERS "MQTT 设置" -#define D_CLIENT "客户端" -#define D_FULL_TOPIC "完整主题" - -#define D_LOGGING_PARAMETERS "日志设置" -#define D_SERIAL_LOG_LEVEL "串口日志级别" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web 日志级别" -#define D_SYS_LOG_LEVEL "Syslog 日志级别" -#define D_MORE_DEBUG "全部调试" -#define D_SYSLOG_HOST "Syslog 主机地址" -#define D_SYSLOG_PORT "Syslog 端口" -#define D_TELEMETRY_PERIOD "上报周期" - -#define D_OTHER_PARAMETERS "其他设置" -#define D_TEMPLATE "模板" -#define D_ACTIVATE "启用" -#define D_WEB_ADMIN_PASSWORD "WEB 管理密码" -#define D_MQTT_ENABLE "启用MQTT" -#define D_FRIENDLY_NAME "昵称" -#define D_BELKIN_WEMO "贝尔金 WeMo" -#define D_HUE_BRIDGE "飞利浦 Hue 网桥" -#define D_SINGLE_DEVICE "单设备" -#define D_MULTI_DEVICE "多设备" - -#define D_CONFIGURE_TEMPLATE "模板配置" -#define D_TEMPLATE_PARAMETERS "模板参数" -#define D_TEMPLATE_NAME "名称" -#define D_BASE_TYPE "基于" -#define D_TEMPLATE_FLAGS "选项" - -#define D_SAVE_CONFIGURATION "保存设置" -#define D_CONFIGURATION_SAVED "设置已保存" -#define D_CONFIGURATION_RESET "设置已重置" - -#define D_PROGRAM_VERSION "固件版本" -#define D_BUILD_DATE_AND_TIME "编译时间" -#define D_CORE_AND_SDK_VERSION "内核和 SDK 版本" -#define D_FLASH_WRITE_COUNT "Flash 写入次数" -#define D_MAC_ADDRESS "MAC 地址" -#define D_MQTT_HOST "MQTT 主机" -#define D_MQTT_PORT "MQTT 端口" -#define D_MQTT_CLIENT "MQTT 客户端" -#define D_MQTT_USER "MQTT 用户名" -#define D_MQTT_TOPIC "MQTT 主题" -#define D_MQTT_GROUP_TOPIC "MQTT 主题组" -#define D_MQTT_FULL_TOPIC "MQTT 完整主题" -#define D_MDNS_DISCOVERY "mDNS 发现" -#define D_MDNS_ADVERTISE "mDNS 广播" -#define D_ESP_CHIP_ID "ESP 芯片 ID" -#define D_FLASH_CHIP_ID "Flash 芯片 ID" -#define D_FLASH_CHIP_SIZE "Flash 大小" -#define D_FREE_PROGRAM_SPACE "空闲程序空间" - -#define D_UPGRADE_BY_WEBSERVER "通过 Web 升级" -#define D_OTA_URL "OTA 地址" -#define D_START_UPGRADE "开始升级" -#define D_UPGRADE_BY_FILE_UPLOAD "通过文件升级" -#define D_UPLOAD_STARTED "开始上传" -#define D_UPGRADE_STARTED "开始升级" -#define D_UPLOAD_DONE "上传完成" -#define D_UPLOAD_ERR_1 "没有选择任何文件" -#define D_UPLOAD_ERR_2 "没有足够空间" -#define D_UPLOAD_ERR_3 "固件头不是 0xE9" -#define D_UPLOAD_ERR_4 "固件大小超过 flash 容量" -#define D_UPLOAD_ERR_5 "上传缓冲区不足,请先刷入精简固件再升级" -#define D_UPLOAD_ERR_6 "上传失败。 启用日志级别 3 调试" -#define D_UPLOAD_ERR_7 "上传取消" -#define D_UPLOAD_ERR_8 "错误的固件" -#define D_UPLOAD_ERR_9 "固件太大" -#define D_UPLOAD_ERR_10 "初始化 RF 芯片失败" -#define D_UPLOAD_ERR_11 "擦除 RF 芯片失败" -#define D_UPLOAD_ERR_12 "写入 RF 芯片失败" -#define D_UPLOAD_ERR_13 "解码 RF 固件失败" -#define D_UPLOAD_ERROR_CODE "上传错误代码" - -#define D_ENTER_COMMAND "输入命令" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果想得到预期响应,请调整日志级别至: 2 信息" -#define D_NEED_USER_AND_PASSWORD "需要 user=<用户名>&password=<密码>" - -// xdrv_00_mqtt.ino -#define D_FINGERPRINT "验证 TLS 指纹..." -#define D_TLS_CONNECT_FAILED_TO "TLS 连接失败" -#define D_RETRY_IN "重试倒计时:" -#define D_VERIFIED "验证成功" -#define D_INSECURE "指纹无效导致连接不安全" -#define D_CONNECT_FAILED_TO "连接失败:" - -// xdrv_wemohue.ino -#define D_MULTICAST_DISABLED "组播已禁用" -#define D_MULTICAST_REJOINED "组播已(重新)加入" -#define D_MULTICAST_JOIN_FAILED "组播加入失败" -#define D_FAILED_TO_SEND_RESPONSE "请求发送失败" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo 基础事件" -#define D_WEMO_EVENT_SERVICE "WeMo 事件服务" -#define D_WEMO_META_SERVICE "WeMo meta 服务" -#define D_WEMO_SETUP "WeMo 设置" -#define D_RESPONSE_SENT "发送请求" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue 设置" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未实现" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST 参数" -#define D_3_RESPONSE_PACKETS_SENT "3 请求包发送" - -// xdrv_05_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz 设置" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "开关 idx" -#define D_DOMOTICZ_SENSOR_IDX "传感器 idx" - #define D_DOMOTICZ_TEMP "温度" - #define D_DOMOTICZ_TEMP_HUM "温度,湿度" - #define D_DOMOTICZ_TEMP_HUM_BARO "温度,湿度,气压" - #define D_DOMOTICZ_POWER_ENERGY "功率,电量" - #define D_DOMOTICZ_ILLUMINANCE "照度" - #define D_DOMOTICZ_COUNT "数值/PM1" - #define D_DOMOTICZ_VOLTAGE "电压/PM2.5" - #define D_DOMOTICZ_CURRENT "电流/PM10" - #define D_DOMOTICZ_AIRQUALITY "空气质量" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "更新计时器" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "定时器设置" -#define D_TIMER_PARAMETERS "定时器参数" -#define D_TIMER_ENABLE "启用定时器" -#define D_TIMER_ARM "启用" -#define D_TIMER_TIME "时间" -#define D_TIMER_DAYS "天" -#define D_TIMER_REPEAT "重复" -#define D_TIMER_OUTPUT "输出" -#define D_TIMER_ACTION "动作" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX 配置" -#define D_KNX_PARAMETERS "KNX 参数" -#define D_KNX_GENERAL_CONFIG "同用" -#define D_KNX_PHYSICAL_ADDRESS "物理地址" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( 在 KNX 网络上必须是唯一的 )" -#define D_KNX_ENABLE "启用 KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "要发送到组地址的数据" -#define D_ADD "添加" -#define D_DELETE "删除" -#define D_REPLY "回复" -#define D_KNX_GROUP_ADDRESS_TO_READ "用来接收数据的组地址" -#define D_RECEIVED_FROM "接收自" -#define D_KNX_COMMAND_WRITE "写" -#define D_KNX_COMMAND_READ "读" -#define D_KNX_COMMAND_OTHER "其他" -#define D_SENT_TO "发送到" -#define D_KNX_WARNING "组地址(0/0/0)被保留,不能使用。" -#define D_KNX_ENHANCEMENT "通讯增强" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "今日用电量" -#define D_ENERGY_YESTERDAY "昨日用电量" -#define D_ENERGY_TOTAL "总用电量" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "传感器正忙" -#define D_SENSOR_CRC_ERROR "传感器 CRC 校验错误" -#define D_SENSORS_FOUND "发现传感器" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "等待超时" -#define D_START_SIGNAL_LOW "开始低电平" -#define D_START_SIGNAL_HIGH "开始高电平" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "校验失败" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "传感器没有确认命令" -#define D_SHT1X_FOUND "发现 SHT1X 传感器" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "颗粒物直径大于" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "加速度计X轴分量" -#define D_AY_AXIS "加速度计Y轴分量" -#define D_AZ_AXIS "加速度计Z轴分量" -#define D_GX_AXIS "绕X轴旋转的角速度" -#define D_GY_AXIS "绕Y轴旋转的角速度" -#define D_GZ_AXIS "绕Z轴旋转的角速度" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "去除重量" -#define D_HX_CAL_REFERENCE "加载参考重量" -#define D_HX_CAL_DONE "已校准" -#define D_HX_CAL_FAIL "校准失败" -#define D_RESET_HX711 "秤重置" -#define D_CONFIGURE_HX711 "秤配置" -#define D_HX711_PARAMETERS "秤参数" -#define D_ITEM_WEIGHT "物品中粮" -#define D_REFERENCE_WEIGHT "参考重量" -#define D_CALIBRATE "校准" -#define D_CALIBRATION "校准" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "风向" -#define D_TX20_WIND_SPEED "风速" -#define D_TX20_WIND_SPEED_AVG "平均风速" -#define D_TX20_WIND_SPEED_MAX "最高风速" -#define D_TX20_NORTH "北" -#define D_TX20_EAST "东" -#define D_TX20_SOUTH "南" -#define D_TX20_WEST "西" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "无" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "安" -#define D_UNIT_CENTIMETER "厘米" -#define D_UNIT_HERTZ "赫兹" -#define D_UNIT_HOUR "时" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "千克" -#define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h" -#define D_UNIT_KILOOHM "千欧" -#define D_UNIT_KILOWATTHOUR "千瓦时" -#define D_UNIT_LUX "勒克斯" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" -#define D_UNIT_MICROMETER "微米" -#define D_UNIT_MICROSECOND "微秒" -#define D_UNIT_MILLIAMPERE "毫安" -#define D_UNIT_MILLIMETER "毫米" -#define D_UNIT_MILLIMETER_MERCURY "毫米汞柱" -#define D_UNIT_MILLISECOND "毫秒" -#define D_UNIT_MINUTE "分" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "每分升" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "百帕" -#define D_UNIT_SECOND "秒" -#define D_UNIT_SECTORS "扇区" -#define D_UNIT_VA "伏安" -#define D_UNIT_VAR "无功伏安" -#define D_UNIT_VOLT "伏" -#define D_UNIT_WATT "瓦" -#define D_UNIT_WATTHOUR "瓦时" -#define D_UNIT_WATT_METER_QUADRAT "瓦/平米" - -//SDM220 -#define D_PHASE_ANGLE "相位角" -#define D_IMPORT_ACTIVE "有功输入" -#define D_EXPORT_ACTIVE "有功输出" -#define D_IMPORT_REACTIVE "无功输入" -#define D_EXPORT_REACTIVE "无功输出" -#define D_TOTAL_REACTIVE "总无功功率" -#define D_UNIT_KWARH "千乏时" -#define D_UNIT_ANGLE "度" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_ZH_CN_H_ +/* + zh-CN.h - localization for Chinese (Simplified) - China for Tasmota + + Copyright (C) 2019 Theo Arends (translated by killadm) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_ZH_CN_H_ +#define _LANGUAGE_ZH_CN_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.14.0b +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 2052 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "zh" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "日 一 二 三 四 五 六 " +#define D_MONTH3LIST "1月 2月 3月 4月 5月 6月 7月 8月 9月 10月11月12月" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "空气质量" +#define D_AP "AP" // Access Point +#define D_AS "名称:" +#define D_AUTO "自动" +#define D_BLINK "闪烁" +#define D_BLINKOFF "闪烁关" +#define D_BOOT_COUNT "启动次数" +#define D_BRIGHTLIGHT "亮" +#define D_BSSID "BSSId" +#define D_BUTTON "按钮" +#define D_BY "汉化: killadm 作者:" // Written by me +#define D_BYTES "大小:" +#define D_CELSIUS "摄氏" +#define D_CHANNEL "频道" +#define D_CO2 "二氧化碳" +#define D_CODE "代码" // Button code +#define D_COLDLIGHT "冷" +#define D_COMMAND "命令:" +#define D_CONNECTED "已连接" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "数量:" +#define D_COUNTER "计数器" +#define D_CURRENT "电流" // As in Voltage and Current +#define D_DATA "数据:" +#define D_DARKLIGHT "暗" +#define D_DEBUG "调试" +#define D_DISABLED "禁用" +#define D_DISTANCE "距离" +#define D_DNS_SERVER "DNS服务器" +#define D_DONE "完成" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "设备模拟" +#define D_ENABLED "启用" +#define D_ERASE "擦除" +#define D_ERROR "错误" +#define D_FAHRENHEIT "华氏" +#define D_FAILED "失败" +#define D_FALLBACK "回退" +#define D_FALLBACK_TOPIC "回退主题" +#define D_FALSE "False" +#define D_FILE "文件:" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "空闲内存" +#define D_FREQUENCY "频率" +#define D_GAS "气体" +#define D_GATEWAY "网关" +#define D_GROUP "组:" +#define D_HOST "主机" +#define D_HOSTNAME "主机名" +#define D_HUMIDITY "湿度" +#define D_ILLUMINANCE "照度" +#define D_IMMEDIATE "单次按键" // Button immediate +#define D_INDEX "索引:" +#define D_INFO "信息" +#define D_INFRARED "红外线" +#define D_INITIALIZED "初始化完成" +#define D_IP_ADDRESS "IP地址" +#define D_LIGHT "灯" +#define D_LWT "LWT" +#define D_MODULE "模块" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "多次按键" +#define D_NOISE "嘈杂" +#define D_NONE "无" +#define D_OFF "关" +#define D_OFFLINE "离线" +#define D_OK "好" +#define D_ON "开" +#define D_ONLINE "在线" +#define D_PASSWORD "密码" +#define D_PORT "端口" +#define D_POWER_FACTOR "功率因数" +#define D_POWERUSAGE "功率" +#define D_POWERUSAGE_ACTIVE "有功功率" +#define D_POWERUSAGE_APPARENT "视在功率" +#define D_POWERUSAGE_REACTIVE "无功功率" +#define D_PRESSURE "气压" +#define D_PRESSUREATSEALEVEL "海平面气压" +#define D_PROGRAM_FLASH_SIZE "固件 Flash 大小" +#define D_PROGRAM_SIZE "固件大小" +#define D_PROJECT "项目:" +#define D_RAIN "降水量" +#define D_RECEIVED "已接收" +#define D_RESTART "重启" +#define D_RESTARTING "正在重启" +#define D_RESTART_REASON "重启原因" +#define D_RESTORE "恢复" +#define D_RETAINED "已保留" +#define D_RULE "规则" +#define D_SAVE "保存" +#define D_SENSOR "传感器" +#define D_SSID "名称" +#define D_START "开始" +#define D_STD_TIME "STD" +#define D_STOP "停止" +#define D_SUBNET_MASK "子网掩码" +#define D_SUBSCRIBE_TO "订阅" +#define D_UNSUBSCRIBE_FROM "退订" +#define D_SUCCESSFUL "成功" +#define D_SUNRISE "日出" +#define D_SUNSET "日落" +#define D_TEMPERATURE "温度" +#define D_TO "to" +#define D_TOGGLE "切换" +#define D_TOPIC "主题" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "发送" +#define D_TRUE "True" +#define D_TVOC "TVOC" +#define D_UPGRADE "升级" +#define D_UPLOAD "上传" +#define D_UPTIME "运行时间" +#define D_USER "用户名" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "紫外线指数" +#define D_UV_INDEX_1 "低" +#define D_UV_INDEX_2 "中" +#define D_UV_INDEX_3 "高" +#define D_UV_INDEX_4 "危险" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "紫外线水平" +#define D_UV_POWER "紫外线功率 " +#define D_VERSION "版本" +#define D_VOLTAGE "电压" +#define D_WEIGHT "重量" +#define D_WARMLIGHT "暖" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "警告:精简固件不支持配置持久化保存" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "串口日志已禁用" +#define D_SYSLOG_LOGGING_REENABLED "Syslog 日志已开启" + +#define D_SET_BAUDRATE_TO "设置波特率为:" +#define D_RECEIVED_TOPIC "接收到的主题:" +#define D_DATA_SIZE "数据大小:" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPS 配置失败,状态:" +#define D_ACTIVE_FOR_3_MINUTES "激活 3 分钟" +#define D_FAILED_TO_START "未能启动" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "连接到 AP" +#define D_IN_MODE "模式:" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "连接失败,因为没有获取到 IP 地址" +#define D_CONNECT_FAILED_AP_NOT_REACHED "连接失败,无法连接 AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "连接失败,AP 密码不正确" +#define D_CONNECT_FAILED_AP_TIMEOUT "连接失败,AP 超时" +#define D_ATTEMPTING_CONNECTION "尝试连接..." +#define D_CHECKING_CONNECTION "检查连接..." +#define D_QUERY_DONE "查询完成。 发现 MQTT 服务" +#define D_MQTT_SERVICE_FOUND "发现 MQTT 服务:" +#define D_FOUND_AT "发现:" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog 主机未找到" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "保存到 flash:" +#define D_LOADED_FROM_FLASH_AT "从 flash 载入:" +#define D_USE_DEFAULTS "使用默认设置" +#define D_ERASED_SECTOR "擦除扇区" + +// webserver.ino +#define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" +#define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" +#define D_WITH_IP_ADDRESS "IP 地址:" +#define D_WEBSERVER_STOPPED "Web 服务已停止" +#define D_FILE_NOT_FOUND "文件未找到" +#define D_REDIRECTED "重定向到认证页面" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager 设置无线操作模式" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 设置接入点" +#define D_TRYING_TO_CONNECT "尝试将设备连接到网络" + +#define D_RESTART_IN "重启需要" +#define D_SECONDS "秒" +#define D_DEVICE_WILL_RESTART "设备将在几秒钟内重启" +#define D_BUTTON_TOGGLE "状态切换" +#define D_CONFIGURATION "设置" +#define D_INFORMATION "信息" +#define D_FIRMWARE_UPGRADE "固件升级" +#define D_CONSOLE "控制台" +#define D_CONFIRM_RESTART "确认重启" + +#define D_CONFIGURE_MODULE "模块设置" +#define D_CONFIGURE_WIFI "WiFi设置" +#define D_CONFIGURE_MQTT "MQTT设置" +#define D_CONFIGURE_DOMOTICZ "Domoticz设置" +#define D_CONFIGURE_LOGGING "日志设置" +#define D_CONFIGURE_OTHER "其他设置" +#define D_CONFIRM_RESET_CONFIGURATION "确认重置配置" +#define D_RESET_CONFIGURATION "重置配置" +#define D_BACKUP_CONFIGURATION "备份配置" +#define D_RESTORE_CONFIGURATION "还原配置" +#define D_MAIN_MENU "主菜单" + +#define D_MODULE_PARAMETERS "模块设置" +#define D_MODULE_TYPE "模块类型" +#define D_PULLUP_ENABLE "没有按钮/开关上拉" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "串口输入(RX)" +#define D_SERIAL_OUT "串口输出(TX)" + +#define D_WIFI_PARAMETERS "Wifi设置" +#define D_SCAN_FOR_WIFI_NETWORKS "扫描无线网络" +#define D_SCAN_DONE "扫描完毕" +#define D_NO_NETWORKS_FOUND "未找到任何网络" +#define D_REFRESH_TO_SCAN_AGAIN "刷新并重试" +#define D_DUPLICATE_ACCESSPOINT "重复AP" +#define D_SKIPPING_LOW_QUALITY "忽略弱信号网络" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 名称" +#define D_AP1_PASSWORD "AP1 密码" +#define D_AP2_SSID "AP2 名称" +#define D_AP2_PASSWORD "AP2 密码" + +#define D_MQTT_PARAMETERS "MQTT 设置" +#define D_CLIENT "客户端" +#define D_FULL_TOPIC "完整主题" + +#define D_LOGGING_PARAMETERS "日志设置" +#define D_SERIAL_LOG_LEVEL "串口日志级别" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web 日志级别" +#define D_SYS_LOG_LEVEL "Syslog 日志级别" +#define D_MORE_DEBUG "全部调试" +#define D_SYSLOG_HOST "Syslog 主机地址" +#define D_SYSLOG_PORT "Syslog 端口" +#define D_TELEMETRY_PERIOD "上报周期" + +#define D_OTHER_PARAMETERS "其他设置" +#define D_TEMPLATE "模板" +#define D_ACTIVATE "启用" +#define D_WEB_ADMIN_PASSWORD "WEB 管理密码" +#define D_MQTT_ENABLE "启用MQTT" +#define D_FRIENDLY_NAME "昵称" +#define D_BELKIN_WEMO "贝尔金 WeMo" +#define D_HUE_BRIDGE "飞利浦 Hue 网桥" +#define D_SINGLE_DEVICE "单设备" +#define D_MULTI_DEVICE "多设备" + +#define D_CONFIGURE_TEMPLATE "模板配置" +#define D_TEMPLATE_PARAMETERS "模板参数" +#define D_TEMPLATE_NAME "名称" +#define D_BASE_TYPE "基于" +#define D_TEMPLATE_FLAGS "选项" + +#define D_SAVE_CONFIGURATION "保存设置" +#define D_CONFIGURATION_SAVED "设置已保存" +#define D_CONFIGURATION_RESET "设置已重置" + +#define D_PROGRAM_VERSION "固件版本" +#define D_BUILD_DATE_AND_TIME "编译时间" +#define D_CORE_AND_SDK_VERSION "内核和 SDK 版本" +#define D_FLASH_WRITE_COUNT "Flash 写入次数" +#define D_MAC_ADDRESS "MAC 地址" +#define D_MQTT_HOST "MQTT 主机" +#define D_MQTT_PORT "MQTT 端口" +#define D_MQTT_CLIENT "MQTT 客户端" +#define D_MQTT_USER "MQTT 用户名" +#define D_MQTT_TOPIC "MQTT 主题" +#define D_MQTT_GROUP_TOPIC "MQTT 主题组" +#define D_MQTT_FULL_TOPIC "MQTT 完整主题" +#define D_MDNS_DISCOVERY "mDNS 发现" +#define D_MDNS_ADVERTISE "mDNS 广播" +#define D_ESP_CHIP_ID "ESP 芯片 ID" +#define D_FLASH_CHIP_ID "Flash 芯片 ID" +#define D_FLASH_CHIP_SIZE "Flash 大小" +#define D_FREE_PROGRAM_SPACE "空闲程序空间" + +#define D_UPGRADE_BY_WEBSERVER "通过 Web 升级" +#define D_OTA_URL "OTA 地址" +#define D_START_UPGRADE "开始升级" +#define D_UPGRADE_BY_FILE_UPLOAD "通过文件升级" +#define D_UPLOAD_STARTED "开始上传" +#define D_UPGRADE_STARTED "开始升级" +#define D_UPLOAD_DONE "上传完成" +#define D_UPLOAD_ERR_1 "没有选择任何文件" +#define D_UPLOAD_ERR_2 "没有足够空间" +#define D_UPLOAD_ERR_3 "固件头不是 0xE9" +#define D_UPLOAD_ERR_4 "固件大小超过 flash 容量" +#define D_UPLOAD_ERR_5 "上传缓冲区不足,请先刷入精简固件再升级" +#define D_UPLOAD_ERR_6 "上传失败。 启用日志级别 3 调试" +#define D_UPLOAD_ERR_7 "上传取消" +#define D_UPLOAD_ERR_8 "错误的固件" +#define D_UPLOAD_ERR_9 "固件太大" +#define D_UPLOAD_ERR_10 "初始化 RF 芯片失败" +#define D_UPLOAD_ERR_11 "擦除 RF 芯片失败" +#define D_UPLOAD_ERR_12 "写入 RF 芯片失败" +#define D_UPLOAD_ERR_13 "解码 RF 固件失败" +#define D_UPLOAD_ERROR_CODE "上传错误代码" + +#define D_ENTER_COMMAND "输入命令" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果想得到预期响应,请调整日志级别至: 2 信息" +#define D_NEED_USER_AND_PASSWORD "需要 user=<用户名>&password=<密码>" + +// xdrv_00_mqtt.ino +#define D_FINGERPRINT "验证 TLS 指纹..." +#define D_TLS_CONNECT_FAILED_TO "TLS 连接失败" +#define D_RETRY_IN "重试倒计时:" +#define D_VERIFIED "验证成功" +#define D_INSECURE "指纹无效导致连接不安全" +#define D_CONNECT_FAILED_TO "连接失败:" + +// xdrv_wemohue.ino +#define D_MULTICAST_DISABLED "组播已禁用" +#define D_MULTICAST_REJOINED "组播已(重新)加入" +#define D_MULTICAST_JOIN_FAILED "组播加入失败" +#define D_FAILED_TO_SEND_RESPONSE "请求发送失败" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo 基础事件" +#define D_WEMO_EVENT_SERVICE "WeMo 事件服务" +#define D_WEMO_META_SERVICE "WeMo meta 服务" +#define D_WEMO_SETUP "WeMo 设置" +#define D_RESPONSE_SENT "发送请求" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue 设置" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未实现" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST 参数" +#define D_3_RESPONSE_PACKETS_SENT "3 请求包发送" + +// xdrv_05_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz 设置" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "开关 idx" +#define D_DOMOTICZ_SENSOR_IDX "传感器 idx" + #define D_DOMOTICZ_TEMP "温度" + #define D_DOMOTICZ_TEMP_HUM "温度,湿度" + #define D_DOMOTICZ_TEMP_HUM_BARO "温度,湿度,气压" + #define D_DOMOTICZ_POWER_ENERGY "功率,电量" + #define D_DOMOTICZ_ILLUMINANCE "照度" + #define D_DOMOTICZ_COUNT "数值/PM1" + #define D_DOMOTICZ_VOLTAGE "电压/PM2.5" + #define D_DOMOTICZ_CURRENT "电流/PM10" + #define D_DOMOTICZ_AIRQUALITY "空气质量" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "更新计时器" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "定时器设置" +#define D_TIMER_PARAMETERS "定时器参数" +#define D_TIMER_ENABLE "启用定时器" +#define D_TIMER_ARM "启用" +#define D_TIMER_TIME "时间" +#define D_TIMER_DAYS "天" +#define D_TIMER_REPEAT "重复" +#define D_TIMER_OUTPUT "输出" +#define D_TIMER_ACTION "动作" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX 配置" +#define D_KNX_PARAMETERS "KNX 参数" +#define D_KNX_GENERAL_CONFIG "同用" +#define D_KNX_PHYSICAL_ADDRESS "物理地址" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( 在 KNX 网络上必须是唯一的 )" +#define D_KNX_ENABLE "启用 KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "要发送到组地址的数据" +#define D_ADD "添加" +#define D_DELETE "删除" +#define D_REPLY "回复" +#define D_KNX_GROUP_ADDRESS_TO_READ "用来接收数据的组地址" +#define D_RECEIVED_FROM "接收自" +#define D_KNX_COMMAND_WRITE "写" +#define D_KNX_COMMAND_READ "读" +#define D_KNX_COMMAND_OTHER "其他" +#define D_SENT_TO "发送到" +#define D_KNX_WARNING "组地址(0/0/0)被保留,不能使用。" +#define D_KNX_ENHANCEMENT "通讯增强" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "今日用电量" +#define D_ENERGY_YESTERDAY "昨日用电量" +#define D_ENERGY_TOTAL "总用电量" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "传感器正忙" +#define D_SENSOR_CRC_ERROR "传感器 CRC 校验错误" +#define D_SENSORS_FOUND "发现传感器" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "等待超时" +#define D_START_SIGNAL_LOW "开始低电平" +#define D_START_SIGNAL_HIGH "开始高电平" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "校验失败" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "传感器没有确认命令" +#define D_SHT1X_FOUND "发现 SHT1X 传感器" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "颗粒物直径大于" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "加速度计X轴分量" +#define D_AY_AXIS "加速度计Y轴分量" +#define D_AZ_AXIS "加速度计Z轴分量" +#define D_GX_AXIS "绕X轴旋转的角速度" +#define D_GY_AXIS "绕Y轴旋转的角速度" +#define D_GZ_AXIS "绕Z轴旋转的角速度" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "去除重量" +#define D_HX_CAL_REFERENCE "加载参考重量" +#define D_HX_CAL_DONE "已校准" +#define D_HX_CAL_FAIL "校准失败" +#define D_RESET_HX711 "秤重置" +#define D_CONFIGURE_HX711 "秤配置" +#define D_HX711_PARAMETERS "秤参数" +#define D_ITEM_WEIGHT "物品中粮" +#define D_REFERENCE_WEIGHT "参考重量" +#define D_CALIBRATE "校准" +#define D_CALIBRATION "校准" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "风向" +#define D_TX20_WIND_SPEED "风速" +#define D_TX20_WIND_SPEED_AVG "平均风速" +#define D_TX20_WIND_SPEED_MAX "最高风速" +#define D_TX20_NORTH "北" +#define D_TX20_EAST "东" +#define D_TX20_SOUTH "南" +#define D_TX20_WEST "西" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "无" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "安" +#define D_UNIT_CENTIMETER "厘米" +#define D_UNIT_HERTZ "赫兹" +#define D_UNIT_HOUR "时" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "千克" +#define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h" +#define D_UNIT_KILOOHM "千欧" +#define D_UNIT_KILOWATTHOUR "千瓦时" +#define D_UNIT_LUX "勒克斯" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" +#define D_UNIT_MICROMETER "微米" +#define D_UNIT_MICROSECOND "微秒" +#define D_UNIT_MILLIAMPERE "毫安" +#define D_UNIT_MILLIMETER "毫米" +#define D_UNIT_MILLIMETER_MERCURY "毫米汞柱" +#define D_UNIT_MILLISECOND "毫秒" +#define D_UNIT_MINUTE "分" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "每分升" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "百帕" +#define D_UNIT_SECOND "秒" +#define D_UNIT_SECTORS "扇区" +#define D_UNIT_VA "伏安" +#define D_UNIT_VAR "无功伏安" +#define D_UNIT_VOLT "伏" +#define D_UNIT_WATT "瓦" +#define D_UNIT_WATTHOUR "瓦时" +#define D_UNIT_WATT_METER_QUADRAT "瓦/平米" + +//SDM220 +#define D_PHASE_ANGLE "相位角" +#define D_IMPORT_ACTIVE "有功输入" +#define D_EXPORT_ACTIVE "有功输出" +#define D_IMPORT_REACTIVE "无功输入" +#define D_EXPORT_REACTIVE "无功输出" +#define D_TOTAL_REACTIVE "总无功功率" +#define D_UNIT_KWARH "千乏时" +#define D_UNIT_ANGLE "度" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_ZH_CN_H_ diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 1d78f181e..ed67b2931 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -1,701 +1,703 @@ -/* - zh-TW.h - localization for Chinese (Traditional) - Taiwan for Tasmota - - Copyright (C) 2019 Theo Arends (translated by dannydu) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_ZH_TW_H_ -#define _LANGUAGE_ZH_TW_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.12.0d -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1028 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "zh" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "SunMonTueWedThuFriSat" -#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "空氣品質" -#define D_AP "AP" // Access Point -#define D_AS "名稱:" -#define D_AUTO "自動" -#define D_BLINK "閃爍" -#define D_BLINKOFF "閃爍關" -#define D_BOOT_COUNT "啟動次數" -#define D_BRIGHTLIGHT "亮度" -#define D_BSSID "BSSId" -#define D_BUTTON "按鈕" -#define D_BY "by" // Written by me -#define D_BYTES "大小:" -#define D_CELSIUS "攝氏" -#define D_CHANNEL "Channel" -#define D_CO2 "二氧化碳" -#define D_CODE "代碼" // Button code -#define D_COLDLIGHT "冷" -#define D_COMMAND "命令:" -#define D_CONNECTED "已連接" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "數量:" -#define D_COUNTER "Counter" -#define D_CURRENT "電流" // As in Voltage and Current -#define D_DATA "數據:" -#define D_DARKLIGHT "Dark" -#define D_DEBUG "除錯" -#define D_DISABLED "停用" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "DNS伺服器" -#define D_DONE "完成" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "設備模擬" -#define D_ENABLED "啟用" -#define D_ERASE "刪除" -#define D_ERROR "錯誤" -#define D_FAHRENHEIT "華氏" -#define D_FAILED "失敗" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "False" -#define D_FILE "文件:" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "可用記憶體" -#define D_FREQUENCY "Frequency" -#define D_GAS "氣體" -#define D_GATEWAY "網關" -#define D_GROUP "組:" -#define D_HOST "主機" -#define D_HOSTNAME "主機名" -#define D_HUMIDITY "濕度" -#define D_ILLUMINANCE "照度" -#define D_IMMEDIATE "immediate" // Button immediate -#define D_INDEX "索引:" -#define D_INFO "信息" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "初始化完成" -#define D_IP_ADDRESS "IP地址" -#define D_LIGHT "燈" -#define D_LWT "LWT" -#define D_MODULE "模組" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "多次按鍵" -#define D_NOISE "雜訊" -#define D_NONE "無" -#define D_OFF "關" -#define D_OFFLINE "離線" -#define D_OK "好" -#define D_ON "開" -#define D_ONLINE "在線" -#define D_PASSWORD "密碼" -#define D_PORT "端口" -#define D_POWER_FACTOR "功率因數" -#define D_POWERUSAGE "功率" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "氣壓" -#define D_PRESSUREATSEALEVEL "海平面氣壓" -#define D_PROGRAM_FLASH_SIZE "韌體 Flash 大小" -#define D_PROGRAM_SIZE "韌體大小" -#define D_PROJECT "項目:" -#define D_RAIN "Rain" -#define D_RECEIVED "已接收" -#define D_RESTART "重啟" -#define D_RESTARTING "正在重啟" -#define D_RESTART_REASON "重啟原因" -#define D_RESTORE "恢覆" -#define D_RETAINED "已保留" -#define D_RULE "Rule" -#define D_SAVE "存檔" -#define D_SENSOR "感測器" -#define D_SSID "名稱" -#define D_START "開始" -#define D_STD_TIME "STD" -#define D_STOP "停止" -#define D_SUBNET_MASK "子網遮罩" -#define D_SUBSCRIBE_TO "訂閱" -#define D_UNSUBSCRIBE_FROM "退訂" -#define D_SUCCESSFUL "成功" -#define D_SUNRISE "Sunrise" -#define D_SUNSET "Sunset" -#define D_TEMPERATURE "溫度" -#define D_TO "to" -#define D_TOGGLE "切換" -#define D_TOPIC "主題" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "發送" -#define D_TRUE "True" -#define D_TVOC "TVOC" -#define D_UPGRADE "升級" -#define D_UPLOAD "上傳" -#define D_UPTIME "運行時間" -#define D_USER "用戶名" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "紫外線等級" -#define D_UV_POWER "UV Power" -#define D_VERSION "版本" -#define D_VOLTAGE "電壓" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "暖" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "警告:精簡產品不支持配置寫入保存" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "串口日誌已禁用" -#define D_SYSLOG_LOGGING_REENABLED "Syslog 日誌已開啟" - -#define D_SET_BAUDRATE_TO "設置波特率為:" -#define D_RECEIVED_TOPIC "接收到的主題:" -#define D_DATA_SIZE "數據大小:" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" -#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" -#define D_FAILED_TO_START "未能啟動" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "連接到 AP" -#define D_IN_MODE "模式:" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "連接失敗,因為沒有獲取到IP地址" -#define D_CONNECT_FAILED_AP_NOT_REACHED "連接失敗,無法連接AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "連接失敗,AP密碼不正確" -#define D_CONNECT_FAILED_AP_TIMEOUT "連接失敗,AP超時" -#define D_ATTEMPTING_CONNECTION "嘗試連接..." -#define D_CHECKING_CONNECTION "檢查連接..." -#define D_QUERY_DONE "查詢完成。 發現MQTT服務" -#define D_MQTT_SERVICE_FOUND "發現MQTT服務:" -#define D_FOUND_AT "found at" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog主機未找到" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "保存到 flash:" -#define D_LOADED_FROM_FLASH_AT "從 flash 載入" -#define D_USE_DEFAULTS "使用默認設置" -#define D_ERASED_SECTOR "擦除刪除" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" -#define D_WEBSERVER_ACTIVE_ON "Web服務器:" -#define D_WITH_IP_ADDRESS "IP地址:" -#define D_WEBSERVER_STOPPED "Web 服務器已停止" -#define D_FILE_NOT_FOUND "文件未找到" -#define D_REDIRECTED "重定向到認證頁面" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 設置接入點" -#define D_TRYING_TO_CONNECT "嘗試將設備連接到網絡" - -#define D_RESTART_IN "重啟需要" -#define D_SECONDS "秒" -#define D_DEVICE_WILL_RESTART "設備將在幾分鐘內重啟" -#define D_BUTTON_TOGGLE "狀態切換" -#define D_CONFIGURATION "設置" -#define D_INFORMATION "信息" -#define D_FIRMWARE_UPGRADE "固件升級" -#define D_CONSOLE "控制台" -#define D_CONFIRM_RESTART "確認重啟" - -#define D_CONFIGURE_MODULE "模塊設置" -#define D_CONFIGURE_WIFI "WiFi設置" -#define D_CONFIGURE_MQTT "MQTT設置" -#define D_CONFIGURE_DOMOTICZ "Domoticz設置" -#define D_CONFIGURE_LOGGING "日志設置" -#define D_CONFIGURE_OTHER "其他設置" -#define D_CONFIRM_RESET_CONFIGURATION "確認重置配置" -#define D_RESET_CONFIGURATION "重置配置" -#define D_BACKUP_CONFIGURATION "備份配置" -#define D_RESTORE_CONFIGURATION "還原配置" -#define D_MAIN_MENU "主菜單" - -#define D_MODULE_PARAMETERS "模塊設置" -#define D_MODULE_TYPE "模塊類型" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "串口輸入(RX)" -#define D_SERIAL_OUT "串口輸出(TX)" - -#define D_WIFI_PARAMETERS "Wifi設置" -#define D_SCAN_FOR_WIFI_NETWORKS "掃描無線網絡" -#define D_SCAN_DONE "掃描完畢" -#define D_NO_NETWORKS_FOUND "未找到任何網絡" -#define D_REFRESH_TO_SCAN_AGAIN "刷新並重試" -#define D_DUPLICATE_ACCESSPOINT "重覆AP" -#define D_SKIPPING_LOW_QUALITY "忽略弱信號網絡" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 名稱" -#define D_AP1_PASSWORD "AP1 密碼" -#define D_AP2_SSID "AP2 名稱" -#define D_AP2_PASSWORD "AP2 密碼" - -#define D_MQTT_PARAMETERS "MQTT設置" -#define D_CLIENT "客戶端" -#define D_FULL_TOPIC "完整主題" - -#define D_LOGGING_PARAMETERS "日志設置" -#define D_SERIAL_LOG_LEVEL "串口日志級別" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web 日志級別" -#define D_SYS_LOG_LEVEL "Syslog 日志級別" -#define D_MORE_DEBUG "全部調試" -#define D_SYSLOG_HOST "Syslog 主機地址" -#define D_SYSLOG_PORT "Syslog 端口" -#define D_TELEMETRY_PERIOD "上報周期" - -#define D_OTHER_PARAMETERS "其他設置" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "WEB管理密碼" -#define D_MQTT_ENABLE "啟用MQTT" -#define D_FRIENDLY_NAME "昵稱" -#define D_BELKIN_WEMO "貝爾金 WeMo" -#define D_HUE_BRIDGE "飛利浦 Hue 網橋" -#define D_SINGLE_DEVICE "單設備" -#define D_MULTI_DEVICE "多設備" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "保存設置" -#define D_CONFIGURATION_SAVED "設置已保存" -#define D_CONFIGURATION_RESET "設置已重置" - -#define D_PROGRAM_VERSION "固件版本" -#define D_BUILD_DATE_AND_TIME "編譯時間" -#define D_CORE_AND_SDK_VERSION "內核版本" -#define D_FLASH_WRITE_COUNT "刷機次數" -#define D_MAC_ADDRESS "MAC地址" -#define D_MQTT_HOST "MQTT主機" -#define D_MQTT_PORT "MQTT端口" -#define D_MQTT_CLIENT "MQTT客戶端" -#define D_MQTT_USER "MQTT用戶名" -#define D_MQTT_TOPIC "MQTT 主題(Topic)" -#define D_MQTT_GROUP_TOPIC "MQTT 主題組(Group Topic)" -#define D_MQTT_FULL_TOPIC "MQTT 完整主題(Full Topic)" -#define D_MDNS_DISCOVERY "mDNS 發現" -#define D_MDNS_ADVERTISE "mDNS 廣播" -#define D_ESP_CHIP_ID "ESP芯片ID" -#define D_FLASH_CHIP_ID "Flash芯片ID" -#define D_FLASH_CHIP_SIZE "Flash大小" -#define D_FREE_PROGRAM_SPACE "空閑程序空間" - -#define D_UPGRADE_BY_WEBSERVER "通過Web升級" -#define D_OTA_URL "OTA地址" -#define D_START_UPGRADE "開始升級" -#define D_UPGRADE_BY_FILE_UPLOAD "通過文件升級" -#define D_UPLOAD_STARTED "開始上傳" -#define D_UPGRADE_STARTED "開始升級" -#define D_UPLOAD_DONE "上傳完成" -#define D_UPLOAD_ERR_1 "沒有選擇文件" -#define D_UPLOAD_ERR_2 "沒有足夠空間" -#define D_UPLOAD_ERR_3 "固件頭不是 0xE9" -#define D_UPLOAD_ERR_4 "固件太大" -#define D_UPLOAD_ERR_5 "上傳緩沖區不匹配" -#define D_UPLOAD_ERR_6 "上傳失敗。 啟用日志記錄 3" -#define D_UPLOAD_ERR_7 "上傳取消" -#define D_UPLOAD_ERR_8 "錯誤的固件" -#define D_UPLOAD_ERR_9 "固件太大" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "上傳錯誤代碼" - -#define D_ENTER_COMMAND "輸入命令" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果預期響應,則啟用Weblog 2" -#define D_NEED_USER_AND_PASSWORD "需要 user=<用戶名>&password=<密碼>" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "驗證 TLS 指紋..." -#define D_TLS_CONNECT_FAILED_TO "TLS 連接失敗" -#define D_RETRY_IN "重試倒計時:" -#define D_VERIFIED "驗證成功" -#define D_INSECURE "指紋無效導致連接不安全" -#define D_CONNECT_FAILED_TO "連接失敗:" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "組播已禁用" -#define D_MULTICAST_REJOINED "組播已(重新)加入" -#define D_MULTICAST_JOIN_FAILED "組播加入失敗" -#define D_FAILED_TO_SEND_RESPONSE "請求發送失敗" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo 基礎事件" -#define D_WEMO_EVENT_SERVICE "WeMo 事件服務" -#define D_WEMO_META_SERVICE "WeMo meta 服務" -#define D_WEMO_SETUP "WeMo 設置" -#define D_RESPONSE_SENT "發送請求" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue 設置" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未實現" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST 參數" -#define D_3_RESPONSE_PACKETS_SENT "3 請求包發送" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz 設置" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "開關 idx" -#define D_DOMOTICZ_SENSOR_IDX "傳感器 idx" - #define D_DOMOTICZ_TEMP "溫度" - #define D_DOMOTICZ_TEMP_HUM "溫度,濕度" - #define D_DOMOTICZ_TEMP_HUM_BARO "溫度,濕度,氣壓" - #define D_DOMOTICZ_POWER_ENERGY "功率,電量" - #define D_DOMOTICZ_ILLUMINANCE "照度" - #define D_DOMOTICZ_COUNT "數值/PM1" - #define D_DOMOTICZ_VOLTAGE "電壓/PM2.5" - #define D_DOMOTICZ_CURRENT "電流/PM10" - #define D_DOMOTICZ_AIRQUALITY "空氣品質" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "更新計時器" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configure Timer" -#define D_TIMER_PARAMETERS "Timer parameters" -#define D_TIMER_ENABLE "Enable Timers" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configure KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "今日用電量" -#define D_ENERGY_YESTERDAY "昨日用電量" -#define D_ENERGY_TOTAL "總用電量" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "傳感器正忙" -#define D_SENSOR_CRC_ERROR "傳感器 CRC 校驗錯誤" -#define D_SENSORS_FOUND "發現傳感器" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "等待超時" -#define D_START_SIGNAL_LOW "開始低電平" -#define D_START_SIGNAL_HIGH "開始高電平" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "校驗失敗" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "傳感器沒有確認命令" -#define D_SHT1X_FOUND "發現 SHT1X 傳感器" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "顆粒物直徑大於" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" - -// Units -#define D_UNIT_AMPERE "安" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "時" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "千歐" -#define D_UNIT_KILOWATTHOUR "千瓦時" -#define D_UNIT_LUX "勒克斯" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" -#define D_UNIT_MICROMETER "微米" -#define D_UNIT_MICROSECOND "微秒" -#define D_UNIT_MILLIAMPERE "毫安" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "毫秒" -#define D_UNIT_MINUTE "分" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "每分升" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "百帕" -#define D_UNIT_SECOND "秒" -#define D_UNIT_SECTORS "扇區" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "伏" -#define D_UNIT_WATT "瓦" -#define D_UNIT_WATTHOUR "瓦時" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_ZH_TW_H_ +/* + zh-TW.h - localization for Chinese (Traditional) - Taiwan for Tasmota + + Copyright (C) 2019 Theo Arends (translated by dannydu) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_ZH_TW_H_ +#define _LANGUAGE_ZH_TW_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.12.0d +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1028 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "zh" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "SunMonTueWedThuFriSat" +#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "空氣品質" +#define D_AP "AP" // Access Point +#define D_AS "名稱:" +#define D_AUTO "自動" +#define D_BLINK "閃爍" +#define D_BLINKOFF "閃爍關" +#define D_BOOT_COUNT "啟動次數" +#define D_BRIGHTLIGHT "亮度" +#define D_BSSID "BSSId" +#define D_BUTTON "按鈕" +#define D_BY "by" // Written by me +#define D_BYTES "大小:" +#define D_CELSIUS "攝氏" +#define D_CHANNEL "Channel" +#define D_CO2 "二氧化碳" +#define D_CODE "代碼" // Button code +#define D_COLDLIGHT "冷" +#define D_COMMAND "命令:" +#define D_CONNECTED "已連接" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "數量:" +#define D_COUNTER "Counter" +#define D_CURRENT "電流" // As in Voltage and Current +#define D_DATA "數據:" +#define D_DARKLIGHT "Dark" +#define D_DEBUG "除錯" +#define D_DISABLED "停用" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "DNS伺服器" +#define D_DONE "完成" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "設備模擬" +#define D_ENABLED "啟用" +#define D_ERASE "刪除" +#define D_ERROR "錯誤" +#define D_FAHRENHEIT "華氏" +#define D_FAILED "失敗" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "False" +#define D_FILE "文件:" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "可用記憶體" +#define D_FREQUENCY "Frequency" +#define D_GAS "氣體" +#define D_GATEWAY "網關" +#define D_GROUP "組:" +#define D_HOST "主機" +#define D_HOSTNAME "主機名" +#define D_HUMIDITY "濕度" +#define D_ILLUMINANCE "照度" +#define D_IMMEDIATE "immediate" // Button immediate +#define D_INDEX "索引:" +#define D_INFO "信息" +#define D_INFRARED "Infrared" +#define D_INITIALIZED "初始化完成" +#define D_IP_ADDRESS "IP地址" +#define D_LIGHT "燈" +#define D_LWT "LWT" +#define D_MODULE "模組" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "多次按鍵" +#define D_NOISE "雜訊" +#define D_NONE "無" +#define D_OFF "關" +#define D_OFFLINE "離線" +#define D_OK "好" +#define D_ON "開" +#define D_ONLINE "在線" +#define D_PASSWORD "密碼" +#define D_PORT "端口" +#define D_POWER_FACTOR "功率因數" +#define D_POWERUSAGE "功率" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "氣壓" +#define D_PRESSUREATSEALEVEL "海平面氣壓" +#define D_PROGRAM_FLASH_SIZE "韌體 Flash 大小" +#define D_PROGRAM_SIZE "韌體大小" +#define D_PROJECT "項目:" +#define D_RAIN "Rain" +#define D_RECEIVED "已接收" +#define D_RESTART "重啟" +#define D_RESTARTING "正在重啟" +#define D_RESTART_REASON "重啟原因" +#define D_RESTORE "恢覆" +#define D_RETAINED "已保留" +#define D_RULE "Rule" +#define D_SAVE "存檔" +#define D_SENSOR "感測器" +#define D_SSID "名稱" +#define D_START "開始" +#define D_STD_TIME "STD" +#define D_STOP "停止" +#define D_SUBNET_MASK "子網遮罩" +#define D_SUBSCRIBE_TO "訂閱" +#define D_UNSUBSCRIBE_FROM "退訂" +#define D_SUCCESSFUL "成功" +#define D_SUNRISE "Sunrise" +#define D_SUNSET "Sunset" +#define D_TEMPERATURE "溫度" +#define D_TO "to" +#define D_TOGGLE "切換" +#define D_TOPIC "主題" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "發送" +#define D_TRUE "True" +#define D_TVOC "TVOC" +#define D_UPGRADE "升級" +#define D_UPLOAD "上傳" +#define D_UPTIME "運行時間" +#define D_USER "用戶名" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "紫外線等級" +#define D_UV_POWER "UV Power" +#define D_VERSION "版本" +#define D_VOLTAGE "電壓" +#define D_WEIGHT "Weight" +#define D_WARMLIGHT "暖" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "警告:精簡產品不支持配置寫入保存" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "串口日誌已禁用" +#define D_SYSLOG_LOGGING_REENABLED "Syslog 日誌已開啟" + +#define D_SET_BAUDRATE_TO "設置波特率為:" +#define D_RECEIVED_TOPIC "接收到的主題:" +#define D_DATA_SIZE "數據大小:" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" +#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" +#define D_FAILED_TO_START "未能啟動" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "連接到 AP" +#define D_IN_MODE "模式:" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "連接失敗,因為沒有獲取到IP地址" +#define D_CONNECT_FAILED_AP_NOT_REACHED "連接失敗,無法連接AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "連接失敗,AP密碼不正確" +#define D_CONNECT_FAILED_AP_TIMEOUT "連接失敗,AP超時" +#define D_ATTEMPTING_CONNECTION "嘗試連接..." +#define D_CHECKING_CONNECTION "檢查連接..." +#define D_QUERY_DONE "查詢完成。 發現MQTT服務" +#define D_MQTT_SERVICE_FOUND "發現MQTT服務:" +#define D_FOUND_AT "found at" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog主機未找到" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "保存到 flash:" +#define D_LOADED_FROM_FLASH_AT "從 flash 載入" +#define D_USE_DEFAULTS "使用默認設置" +#define D_ERASED_SECTOR "擦除刪除" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" +#define D_WEBSERVER_ACTIVE_ON "Web服務器:" +#define D_WITH_IP_ADDRESS "IP地址:" +#define D_WEBSERVER_STOPPED "Web 服務器已停止" +#define D_FILE_NOT_FOUND "文件未找到" +#define D_REDIRECTED "重定向到認證頁面" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 設置接入點" +#define D_TRYING_TO_CONNECT "嘗試將設備連接到網絡" + +#define D_RESTART_IN "重啟需要" +#define D_SECONDS "秒" +#define D_DEVICE_WILL_RESTART "設備將在幾分鐘內重啟" +#define D_BUTTON_TOGGLE "狀態切換" +#define D_CONFIGURATION "設置" +#define D_INFORMATION "信息" +#define D_FIRMWARE_UPGRADE "固件升級" +#define D_CONSOLE "控制台" +#define D_CONFIRM_RESTART "確認重啟" + +#define D_CONFIGURE_MODULE "模塊設置" +#define D_CONFIGURE_WIFI "WiFi設置" +#define D_CONFIGURE_MQTT "MQTT設置" +#define D_CONFIGURE_DOMOTICZ "Domoticz設置" +#define D_CONFIGURE_LOGGING "日志設置" +#define D_CONFIGURE_OTHER "其他設置" +#define D_CONFIRM_RESET_CONFIGURATION "確認重置配置" +#define D_RESET_CONFIGURATION "重置配置" +#define D_BACKUP_CONFIGURATION "備份配置" +#define D_RESTORE_CONFIGURATION "還原配置" +#define D_MAIN_MENU "主菜單" + +#define D_MODULE_PARAMETERS "模塊設置" +#define D_MODULE_TYPE "模塊類型" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "串口輸入(RX)" +#define D_SERIAL_OUT "串口輸出(TX)" + +#define D_WIFI_PARAMETERS "Wifi設置" +#define D_SCAN_FOR_WIFI_NETWORKS "掃描無線網絡" +#define D_SCAN_DONE "掃描完畢" +#define D_NO_NETWORKS_FOUND "未找到任何網絡" +#define D_REFRESH_TO_SCAN_AGAIN "刷新並重試" +#define D_DUPLICATE_ACCESSPOINT "重覆AP" +#define D_SKIPPING_LOW_QUALITY "忽略弱信號網絡" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 名稱" +#define D_AP1_PASSWORD "AP1 密碼" +#define D_AP2_SSID "AP2 名稱" +#define D_AP2_PASSWORD "AP2 密碼" + +#define D_MQTT_PARAMETERS "MQTT設置" +#define D_CLIENT "客戶端" +#define D_FULL_TOPIC "完整主題" + +#define D_LOGGING_PARAMETERS "日志設置" +#define D_SERIAL_LOG_LEVEL "串口日志級別" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web 日志級別" +#define D_SYS_LOG_LEVEL "Syslog 日志級別" +#define D_MORE_DEBUG "全部調試" +#define D_SYSLOG_HOST "Syslog 主機地址" +#define D_SYSLOG_PORT "Syslog 端口" +#define D_TELEMETRY_PERIOD "上報周期" + +#define D_OTHER_PARAMETERS "其他設置" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "WEB管理密碼" +#define D_MQTT_ENABLE "啟用MQTT" +#define D_FRIENDLY_NAME "昵稱" +#define D_BELKIN_WEMO "貝爾金 WeMo" +#define D_HUE_BRIDGE "飛利浦 Hue 網橋" +#define D_SINGLE_DEVICE "單設備" +#define D_MULTI_DEVICE "多設備" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "保存設置" +#define D_CONFIGURATION_SAVED "設置已保存" +#define D_CONFIGURATION_RESET "設置已重置" + +#define D_PROGRAM_VERSION "固件版本" +#define D_BUILD_DATE_AND_TIME "編譯時間" +#define D_CORE_AND_SDK_VERSION "內核版本" +#define D_FLASH_WRITE_COUNT "刷機次數" +#define D_MAC_ADDRESS "MAC地址" +#define D_MQTT_HOST "MQTT主機" +#define D_MQTT_PORT "MQTT端口" +#define D_MQTT_CLIENT "MQTT客戶端" +#define D_MQTT_USER "MQTT用戶名" +#define D_MQTT_TOPIC "MQTT 主題(Topic)" +#define D_MQTT_GROUP_TOPIC "MQTT 主題組(Group Topic)" +#define D_MQTT_FULL_TOPIC "MQTT 完整主題(Full Topic)" +#define D_MDNS_DISCOVERY "mDNS 發現" +#define D_MDNS_ADVERTISE "mDNS 廣播" +#define D_ESP_CHIP_ID "ESP芯片ID" +#define D_FLASH_CHIP_ID "Flash芯片ID" +#define D_FLASH_CHIP_SIZE "Flash大小" +#define D_FREE_PROGRAM_SPACE "空閑程序空間" + +#define D_UPGRADE_BY_WEBSERVER "通過Web升級" +#define D_OTA_URL "OTA地址" +#define D_START_UPGRADE "開始升級" +#define D_UPGRADE_BY_FILE_UPLOAD "通過文件升級" +#define D_UPLOAD_STARTED "開始上傳" +#define D_UPGRADE_STARTED "開始升級" +#define D_UPLOAD_DONE "上傳完成" +#define D_UPLOAD_ERR_1 "沒有選擇文件" +#define D_UPLOAD_ERR_2 "沒有足夠空間" +#define D_UPLOAD_ERR_3 "固件頭不是 0xE9" +#define D_UPLOAD_ERR_4 "固件太大" +#define D_UPLOAD_ERR_5 "上傳緩沖區不匹配" +#define D_UPLOAD_ERR_6 "上傳失敗。 啟用日志記錄 3" +#define D_UPLOAD_ERR_7 "上傳取消" +#define D_UPLOAD_ERR_8 "錯誤的固件" +#define D_UPLOAD_ERR_9 "固件太大" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "上傳錯誤代碼" + +#define D_ENTER_COMMAND "輸入命令" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果預期響應,則啟用Weblog 2" +#define D_NEED_USER_AND_PASSWORD "需要 user=<用戶名>&password=<密碼>" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "驗證 TLS 指紋..." +#define D_TLS_CONNECT_FAILED_TO "TLS 連接失敗" +#define D_RETRY_IN "重試倒計時:" +#define D_VERIFIED "驗證成功" +#define D_INSECURE "指紋無效導致連接不安全" +#define D_CONNECT_FAILED_TO "連接失敗:" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "組播已禁用" +#define D_MULTICAST_REJOINED "組播已(重新)加入" +#define D_MULTICAST_JOIN_FAILED "組播加入失敗" +#define D_FAILED_TO_SEND_RESPONSE "請求發送失敗" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo 基礎事件" +#define D_WEMO_EVENT_SERVICE "WeMo 事件服務" +#define D_WEMO_META_SERVICE "WeMo meta 服務" +#define D_WEMO_SETUP "WeMo 設置" +#define D_RESPONSE_SENT "發送請求" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue 設置" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未實現" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST 參數" +#define D_3_RESPONSE_PACKETS_SENT "3 請求包發送" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz 設置" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "開關 idx" +#define D_DOMOTICZ_SENSOR_IDX "傳感器 idx" + #define D_DOMOTICZ_TEMP "溫度" + #define D_DOMOTICZ_TEMP_HUM "溫度,濕度" + #define D_DOMOTICZ_TEMP_HUM_BARO "溫度,濕度,氣壓" + #define D_DOMOTICZ_POWER_ENERGY "功率,電量" + #define D_DOMOTICZ_ILLUMINANCE "照度" + #define D_DOMOTICZ_COUNT "數值/PM1" + #define D_DOMOTICZ_VOLTAGE "電壓/PM2.5" + #define D_DOMOTICZ_CURRENT "電流/PM10" + #define D_DOMOTICZ_AIRQUALITY "空氣品質" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "更新計時器" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configure Timer" +#define D_TIMER_PARAMETERS "Timer parameters" +#define D_TIMER_ENABLE "Enable Timers" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Time" +#define D_TIMER_DAYS "Days" +#define D_TIMER_REPEAT "Repeat" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configure KNX" +#define D_KNX_PARAMETERS "KNX Parameters" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Physical Address" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "Enable KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Add" +#define D_DELETE "Delete" +#define D_REPLY "Reply" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Write" +#define D_KNX_COMMAND_READ "Read" +#define D_KNX_COMMAND_OTHER "Other" +#define D_SENT_TO "sent to" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "今日用電量" +#define D_ENERGY_YESTERDAY "昨日用電量" +#define D_ENERGY_TOTAL "總用電量" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "傳感器正忙" +#define D_SENSOR_CRC_ERROR "傳感器 CRC 校驗錯誤" +#define D_SENSORS_FOUND "發現傳感器" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "等待超時" +#define D_START_SIGNAL_LOW "開始低電平" +#define D_START_SIGNAL_HIGH "開始高電平" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "校驗失敗" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "傳感器沒有確認命令" +#define D_SHT1X_FOUND "發現 SHT1X 傳感器" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "顆粒物直徑大於" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" + +// Units +#define D_UNIT_AMPERE "安" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "時" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "千歐" +#define D_UNIT_KILOWATTHOUR "千瓦時" +#define D_UNIT_LUX "勒克斯" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" +#define D_UNIT_MICROMETER "微米" +#define D_UNIT_MICROSECOND "微秒" +#define D_UNIT_MILLIAMPERE "毫安" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "毫秒" +#define D_UNIT_MINUTE "分" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "每分升" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "百帕" +#define D_UNIT_SECOND "秒" +#define D_UNIT_SECTORS "扇區" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "伏" +#define D_UNIT_WATT "瓦" +#define D_UNIT_WATTHOUR "瓦時" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_ZH_TW_H_ From 4cb4aee86b95554eb53b6a659c93548205160779 Mon Sep 17 00:00:00 2001 From: ascillato Date: Mon, 16 Dec 2019 23:09:34 -0300 Subject: [PATCH 080/559] Revert "Add GPS Support - Language Files" This reverts commit b1e24bb9c37f94a6168c06ddf58eee6e54239e15. --- tasmota/language/bg-BG.h | 1404 +++++++++++++++++++------------------- tasmota/language/cs-CZ.h | 1404 +++++++++++++++++++------------------- tasmota/language/de-DE.h | 1404 +++++++++++++++++++------------------- tasmota/language/el-GR.h | 1404 +++++++++++++++++++------------------- tasmota/language/en-GB.h | 1404 +++++++++++++++++++------------------- tasmota/language/es-ES.h | 1404 +++++++++++++++++++------------------- tasmota/language/fr-FR.h | 1404 +++++++++++++++++++------------------- tasmota/language/he-HE.h | 1404 +++++++++++++++++++------------------- tasmota/language/hu-HU.h | 1404 +++++++++++++++++++------------------- tasmota/language/it-IT.h | 1404 +++++++++++++++++++------------------- tasmota/language/ko-KO.h | 1404 +++++++++++++++++++------------------- tasmota/language/nl-NL.h | 1404 +++++++++++++++++++------------------- tasmota/language/pl-PL.h | 1404 +++++++++++++++++++------------------- tasmota/language/pt-BR.h | 1404 +++++++++++++++++++------------------- tasmota/language/pt-PT.h | 1404 +++++++++++++++++++------------------- tasmota/language/ru-RU.h | 1404 +++++++++++++++++++------------------- tasmota/language/sk-SK.h | 1404 +++++++++++++++++++------------------- tasmota/language/sv-SE.h | 1404 +++++++++++++++++++------------------- tasmota/language/tr-TR.h | 1404 +++++++++++++++++++------------------- tasmota/language/uk-UK.h | 1404 +++++++++++++++++++------------------- tasmota/language/zh-CN.h | 1404 +++++++++++++++++++------------------- tasmota/language/zh-TW.h | 1404 +++++++++++++++++++------------------- 22 files changed, 15422 insertions(+), 15466 deletions(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index ffb5bc3ec..1f18d8efb 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -1,703 +1,701 @@ -/* - bg-BG.h - localization for Bulgaria - Bulgarian for Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_BG_BG_H_ -#define _LANGUAGE_BG_BG_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.1.2.4 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1026 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "bg" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "НедПонВтрСрдЧетПетСъб" -#define D_MONTH3LIST "ЯнуФевМарАпрМайЮниЮлиАвгСепОктНоеДек" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Качество на въздуха" -#define D_AP "Точка за достъп" // Access Point -#define D_AS "като" -#define D_AUTO "АВТОМАТИЧНО" -#define D_BLINK "Мигане вкл." -#define D_BLINKOFF "Мигане изкл." -#define D_BOOT_COUNT "Брой на стартиранията" -#define D_BRIGHTLIGHT "Яркост" -#define D_BSSID "BSSId" -#define D_BUTTON "Бутон" -#define D_BY "от" // Written by me -#define D_BYTES "Байта" -#define D_CELSIUS "Целзий" -#define D_CHANNEL "Канал" -#define D_CO2 "Въглероден диоксид" -#define D_CODE "код" // Button code -#define D_COLDLIGHT "Хладна" -#define D_COMMAND "Команда" -#define D_CONNECTED "Свързан" -#define D_CORS_DOMAIN "CORS домейн" -#define D_COUNT "Брой" -#define D_COUNTER "Брояч" -#define D_CURRENT "Ток" // As in Voltage and Current -#define D_DATA "Данни" -#define D_DARKLIGHT "Тъмна" -#define D_DEBUG "Дебъгване" -#define D_DISABLED "Забранен" -#define D_DISTANCE "Разстояние" -#define D_DNS_SERVER "DNS Сървър" -#define D_DONE "Изпълнено" -#define D_DST_TIME "Лятно време" -#define D_ECO2 "eCO₂" -#define D_EMULATION "Емулация" -#define D_ENABLED "Разрешен" -#define D_ERASE "Изтриване" -#define D_ERROR "Грешка" -#define D_FAHRENHEIT "Фаренхайт" -#define D_FAILED "Неуспешно" -#define D_FALLBACK "Помощен" -#define D_FALLBACK_TOPIC "Помощен топик" -#define D_FALSE "Невярно" -#define D_FILE "Файл" -#define D_FLOW_RATE "Дебит" -#define D_FREE_MEMORY "Свободна памет" -#define D_FREQUENCY "Честота" -#define D_GAS "Газ" -#define D_GATEWAY "Шлюз" -#define D_GROUP "Група" -#define D_HOST "Хост" -#define D_HOSTNAME "Име на хоста" -#define D_HUMIDITY "Влажност" -#define D_ILLUMINANCE "Осветеност" -#define D_IMMEDIATE "Моментен" // Button immediate -#define D_INDEX "Индекс" -#define D_INFO "Информация" -#define D_INFRARED "Инфрачервен" -#define D_INITIALIZED "Инициализирано" -#define D_IP_ADDRESS "IP адрес" -#define D_LIGHT "Светлина" -#define D_LWT "LWT" -#define D_MODULE "Модул" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "неколкократно натискане" -#define D_NOISE "Шум" -#define D_NONE "Няма" -#define D_OFF "Изкл." -#define D_OFFLINE "Офлайн" -#define D_OK "Ок" -#define D_ON "Вкл." -#define D_ONLINE "Онлайн" -#define D_PASSWORD "Парола" -#define D_PORT "Порт" -#define D_POWER_FACTOR "Фактор на мощността" -#define D_POWERUSAGE "Мощност" -#define D_POWERUSAGE_ACTIVE "Активна мощност" -#define D_POWERUSAGE_APPARENT "Пълна мощност" -#define D_POWERUSAGE_REACTIVE "Реактивна мощност" -#define D_PRESSURE "Налягане" -#define D_PRESSUREATSEALEVEL "Налягане при морското ниво" -#define D_PROGRAM_FLASH_SIZE "Размер на флаш паметта за програми" -#define D_PROGRAM_SIZE "Размер на програмата" -#define D_PROJECT "Проект" -#define D_RAIN "Дъжд" -#define D_RECEIVED "Получено" -#define D_RESTART "Рестарт" -#define D_RESTARTING "Рестартиране" -#define D_RESTART_REASON "Причина за рестарта" -#define D_RESTORE "възстановяване" -#define D_RETAINED "запазено" -#define D_RULE "Правило" -#define D_SAVE "Запис" -#define D_SENSOR "Датчик" -#define D_SSID "SSId" -#define D_START "Старт" -#define D_STD_TIME "STD" -#define D_STOP "Стоп" -#define D_SUBNET_MASK "Маска на подмрежата" -#define D_SUBSCRIBE_TO "Записване за" -#define D_UNSUBSCRIBE_FROM "Отписване от" -#define D_SUCCESSFUL "Успешно" -#define D_SUNRISE "Изгрев" -#define D_SUNSET "Залез" -#define D_TEMPERATURE "Температура" -#define D_TO "към" -#define D_TOGGLE "Превключване" -#define D_TOPIC "Топик" -#define D_TOTAL_USAGE "Използвана вода" -#define D_TRANSMIT "Предаване" -#define D_TRUE "Вярно" -#define D_TVOC "TVOC" -#define D_UPGRADE "Обновяване" -#define D_UPLOAD "Зареждане" -#define D_UPTIME "Време от стартирането" -#define D_USER "Потребител" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV индекс" -#define D_UV_INDEX_1 "Нисък" -#define D_UV_INDEX_2 "Среден" -#define D_UV_INDEX_3 "Висок" -#define D_UV_INDEX_4 "Много висок" -#define D_UV_INDEX_5 "Изгаряне 1/2 степен" -#define D_UV_INDEX_6 "Изгаряне 3-та степен" -#define D_UV_INDEX_7 "Извън обхват" -#define D_UV_LEVEL "UV ниво" -#define D_UV_POWER "UV мощност" -#define D_VERSION "Версия" -#define D_VOLTAGE "Напрежение" -#define D_WEIGHT "Тегло" -#define D_WARMLIGHT "Топла" -#define D_WEB_SERVER "Уеб сървър" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Тази версия не поддържа постоянни настройки" -#define D_LEVEL_10 "ниво 1-0" -#define D_LEVEL_01 "ниво 0-1" -#define D_SERIAL_LOGGING_DISABLED "Серийният лог изключен" -#define D_SYSLOG_LOGGING_REENABLED "Системният лог активиран" - -#define D_SET_BAUDRATE_TO "Задаване скорост на предаване (Baudrate)" -#define D_RECEIVED_TOPIC "Получен топик" -#define D_DATA_SIZE "Размер на данните" -#define D_ANALOG_INPUT "Аналогов вход" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Блокиран цикъл" -#define D_WPS_FAILED_WITH_STATUS "WPS конфигурацията е НЕУСПЕШНА със статус" -#define D_ACTIVE_FOR_3_MINUTES "активно в течение на 3 минути" -#define D_FAILED_TO_START "Неуспешно стартиране" -#define D_PATCH_ISSUE_2186 "Проблем с патч 2186" -#define D_CONNECTING_TO_AP "Свързване към точка за достъп" -#define D_IN_MODE "в режим" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Грешка при свързването, не е получен IP адрес" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Грешка при свързването, точката за достъп е недостижима" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Грешка при свързването, грешна парола към точката за достъп" -#define D_CONNECT_FAILED_AP_TIMEOUT "Грешка при свързването, превишено време за изчакване" -#define D_ATTEMPTING_CONNECTION "Опитва свързване..." -#define D_CHECKING_CONNECTION "Проверка на свързването..." -#define D_QUERY_DONE "Запитването е изпълнено. Намерена е услуга MQTT" -#define D_MQTT_SERVICE_FOUND "MQTT услуга е намерена на" -#define D_FOUND_AT "намерена в" -#define D_SYSLOG_HOST_NOT_FOUND "Хостът на системния лог не е намерен" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Запазено във флаш паметта на" -#define D_LOADED_FROM_FLASH_AT "Заредено от флаш паметта от" -#define D_USE_DEFAULTS "Използване на параметри по подразбиране" -#define D_ERASED_SECTOR "Изтрит сектор" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуер
моля надградете го" -#define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на" -#define D_WITH_IP_ADDRESS "с IP адрес" -#define D_WEBSERVER_STOPPED "Уеб сървърът е спрян" -#define D_FILE_NOT_FOUND "Файлът не е намерен" -#define D_REDIRECTED "Пренасочено към адаптивния портал" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi мениджърът настройва точка за достъп и запомня станцията" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi мениджърът настрои точката за достъп" -#define D_TRYING_TO_CONNECT "Опит за свързване на устройството към мрежата" - -#define D_RESTART_IN "Рестарт след" -#define D_SECONDS "секунди" -#define D_DEVICE_WILL_RESTART "Устройството ще се рестартира след няколко секунди" -#define D_BUTTON_TOGGLE "Превключване" -#define D_CONFIGURATION "Конфигурация" -#define D_INFORMATION "Информация" -#define D_FIRMWARE_UPGRADE "Обновяване на фърмуера" -#define D_CONSOLE "Конзола" -#define D_CONFIRM_RESTART "Потвърдете рестартирането" - -#define D_CONFIGURE_MODULE "Конфигурация на модула" -#define D_CONFIGURE_WIFI "Конфигурация на WiFi" -#define D_CONFIGURE_MQTT "Конфигурация на MQTT" -#define D_CONFIGURE_DOMOTICZ "Конфигурация на Domoticz" -#define D_CONFIGURE_LOGGING "Конфигурация на лога" -#define D_CONFIGURE_OTHER "Други конфигурации" -#define D_CONFIRM_RESET_CONFIGURATION "Потвърдете изчистването" -#define D_RESET_CONFIGURATION "Изчистване на конфигурацията" -#define D_BACKUP_CONFIGURATION "Запазване на конфигурацията" -#define D_RESTORE_CONFIGURATION "Възстановяване на конфигурацията" -#define D_MAIN_MENU "Основно меню" - -#define D_MODULE_PARAMETERS "Параметри на модула" -#define D_MODULE_TYPE "Тип на модула" -#define D_PULLUP_ENABLE "Без pull-up за бутон/ключ" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Сериен вход" -#define D_SERIAL_OUT "Сериен изход" - -#define D_WIFI_PARAMETERS "Wifi параметри" -#define D_SCAN_FOR_WIFI_NETWORKS "Сканиране за безжични мрежи" -#define D_SCAN_DONE "Сканирането приключи" -#define D_NO_NETWORKS_FOUND "Не бяха открити мрежи" -#define D_REFRESH_TO_SCAN_AGAIN "Обновяване за повторно сканиране" -#define D_DUPLICATE_ACCESSPOINT "Дублиране на точката за достъп (AP)" -#define D_SKIPPING_LOW_QUALITY "Пропускане поради лошо качество" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Парола" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Парола" - -#define D_MQTT_PARAMETERS "Параметри на MQTT" -#define D_CLIENT "Клиент" -#define D_FULL_TOPIC "Пълен топик" - -#define D_LOGGING_PARAMETERS "Параметри на лога" -#define D_SERIAL_LOG_LEVEL "Степен на серийния лог" -#define D_MQTT_LOG_LEVEL "Степен на MQTT лога" -#define D_WEB_LOG_LEVEL "Степен на уеб лога" -#define D_SYS_LOG_LEVEL "Степен на системния лог" -#define D_MORE_DEBUG "Допълнителна debug информация" -#define D_SYSLOG_HOST "Хост на системния лог" -#define D_SYSLOG_PORT "Порт на системния лог" -#define D_TELEMETRY_PERIOD "Период на телеметрия" - -#define D_OTHER_PARAMETERS "Други параметри" -#define D_TEMPLATE "Модел" -#define D_ACTIVATE "Активирай" -#define D_WEB_ADMIN_PASSWORD "Парола на уеб администратора" -#define D_MQTT_ENABLE "Активиране на MQTT" -#define D_FRIENDLY_NAME "Приятелско име" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "Единично" -#define D_MULTI_DEVICE "Мулти" - -#define D_CONFIGURE_TEMPLATE "Конфигуриране на шаблон" -#define D_TEMPLATE_PARAMETERS "Параметри на шаблона" -#define D_TEMPLATE_NAME "Име" -#define D_BASE_TYPE "Базиран на" -#define D_TEMPLATE_FLAGS "Опции" - -#define D_SAVE_CONFIGURATION "Запазване на конфигурацията" -#define D_CONFIGURATION_SAVED "Конфигурацията е запазена" -#define D_CONFIGURATION_RESET "Конфигурацията е изчистена" - -#define D_PROGRAM_VERSION "Версия на програмата" -#define D_BUILD_DATE_AND_TIME "Дата и час на компилацията" -#define D_CORE_AND_SDK_VERSION "Версия на Core/SDK" -#define D_FLASH_WRITE_COUNT "Брой на записите във флаш паметта" -#define D_MAC_ADDRESS "MAC адрес" -#define D_MQTT_HOST "MQTT хост" -#define D_MQTT_PORT "MQTT порт" -#define D_MQTT_CLIENT "MQTT ID на клиент" -#define D_MQTT_USER "MQTT потребител" -#define D_MQTT_TOPIC "MQTT топик" -#define D_MQTT_GROUP_TOPIC "MQTT групов топик" -#define D_MQTT_FULL_TOPIC "MQTT пълен топик" -#define D_MDNS_DISCOVERY "mDNS откриване" -#define D_MDNS_ADVERTISE "mDNS известяване" -#define D_ESP_CHIP_ID "ID на ESP чипа" -#define D_FLASH_CHIP_ID "ID на чипа на флаш паметта" -#define D_FLASH_CHIP_SIZE "Размер на флаш паметта" -#define D_FREE_PROGRAM_SPACE "Свободно пространство за програми" - -#define D_UPGRADE_BY_WEBSERVER "Обновяване чрез уеб сървър" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Започване на обновяване" -#define D_UPGRADE_BY_FILE_UPLOAD "Обновяване чрез зареждане на файл" -#define D_UPLOAD_STARTED "Зареждането започна" -#define D_UPGRADE_STARTED "Обновяването започна" -#define D_UPLOAD_DONE "Зареждането завърши" -#define D_UPLOAD_ERR_1 "Не е избран файл" -#define D_UPLOAD_ERR_2 "Недостатъчно свободно място" -#define D_UPLOAD_ERR_3 "Magic байтът не е 0xE9" -#define D_UPLOAD_ERR_4 "Размерът на програмата е по-голям от реалния размер на флаш паметта" -#define D_UPLOAD_ERR_5 "Грешка при зареждането в буфера" -#define D_UPLOAD_ERR_6 "Грешка при зареждането. Включено е ниво 3 на лога" -#define D_UPLOAD_ERR_7 "Зареждането е прекъснато" -#define D_UPLOAD_ERR_8 "Файлът е невалиден" -#define D_UPLOAD_ERR_9 "Файлът е прекалено голям" -#define D_UPLOAD_ERR_10 "Грешка при инициализация на RF чипа" -#define D_UPLOAD_ERR_11 "Грешка при изтриване на RF чипа" -#define D_UPLOAD_ERR_12 "Грешка при записване в RF чипа" -#define D_UPLOAD_ERR_13 "Грешка при декодиране на RF фърмуера" -#define D_UPLOAD_ERROR_CODE "Код на грешка при зареждането" - -#define D_ENTER_COMMAND "Въвеждане на команда" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Включете ниво 2 на лога, ако очаквате отговор" -#define D_NEED_USER_AND_PASSWORD "Очаква user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Проверка на TLS отпечатък..." -#define D_TLS_CONNECT_FAILED_TO "Неуспешно TLS свързване към" -#define D_RETRY_IN "Повтори след" -#define D_VERIFIED "Проверен отпечтък" -#define D_INSECURE "Нешифрована връзка, недействителен отпечатък" -#define D_CONNECT_FAILED_TO "Грешка при свързването към" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast е изключен" -#define D_MULTICAST_REJOINED "Multicast е повторно съединен" -#define D_MULTICAST_JOIN_FAILED "Multicast грешка при присъединяването" -#define D_FAILED_TO_SEND_RESPONSE "Неуспех при изпращането на отговор" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo главно събитие" -#define D_WEMO_EVENT_SERVICE "WeMo услуга за събитията" -#define D_WEMO_META_SERVICE "WeMo мета-услуга" -#define D_WEMO_SETUP "WeMo настройка" -#define D_RESPONSE_SENT "Отговорът е изпратен" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Настройка на Hue bridge" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API не е внедрен" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST аргументи" -#define D_3_RESPONSE_PACKETS_SENT "Изпратени са 3 пакета за отговор" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz параметри" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Мощност,Енергия" - #define D_DOMOTICZ_ILLUMINANCE "Осветеност" - #define D_DOMOTICZ_COUNT "Брояч/PM1" - #define D_DOMOTICZ_VOLTAGE "Напрежение/PM2,5" - #define D_DOMOTICZ_CURRENT "Ток/PM10" - #define D_DOMOTICZ_AIRQUALITY "Качество на въздуха" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Период на опресняване" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Конфигуриране на таймер" -#define D_TIMER_PARAMETERS "Параметри на таймера" -#define D_TIMER_ENABLE "Активиране на таймера" -#define D_TIMER_ARM "Активиран" -#define D_TIMER_TIME "Време" -#define D_TIMER_DAYS "Дни" -#define D_TIMER_REPEAT "Повтори" -#define D_TIMER_OUTPUT "Изход" -#define D_TIMER_ACTION "Действие" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Конфигуриране на KNX" -#define D_KNX_PARAMETERS "KNX параметри" -#define D_KNX_GENERAL_CONFIG "Основни" -#define D_KNX_PHYSICAL_ADDRESS "Физически адрес" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Трябва да е уникален в KNX мрежата )" -#define D_KNX_ENABLE "Активиране на KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Групови адреси за изпращане на данни" -#define D_ADD "Добаване" -#define D_DELETE "Изтриване" -#define D_REPLY "Отговор" -#define D_KNX_GROUP_ADDRESS_TO_READ "Групови адреси за получаване на данни" -#define D_RECEIVED_FROM "Получен от" -#define D_KNX_COMMAND_WRITE "Писане" -#define D_KNX_COMMAND_READ "Четене" -#define D_KNX_COMMAND_OTHER "Друго" -#define D_SENT_TO "изпратен до" -#define D_KNX_WARNING "Груповият адрес (0/0/0) е резервиран и не може да бъде използван." -#define D_KNX_ENHANCEMENT "Подобрена комуникация" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Използвана енергия днес" -#define D_ENERGY_YESTERDAY "Използвана енергия вчера" -#define D_ENERGY_TOTAL "Използвана енергия общо" - -// xdrv_27_shutter.ino -#define D_OPEN "Отворена" -#define D_CLOSE "Затворена" -#define D_DOMOTICZ_SHUTTER "Щора" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Конфигуриране на PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 параметри" -#define D_INVERT_PORTS "Обърни портовете" -#define D_DEVICE "Устройство" -#define D_DEVICE_INPUT "Вход" -#define D_DEVICE_OUTPUT "Изход" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Датчикът DS18x20 е зает" -#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - грешка CRC" -#define D_SENSORS_FOUND "Намерен е датчик DS18x20" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Изтекло време за очакване на" -#define D_START_SIGNAL_LOW "Нисък стартов сигнал" -#define D_START_SIGNAL_HIGH "Висок стартов сигнал" -#define D_PULSE "Импулс" -#define D_CHECKSUM_FAILURE "Грешка в контролната сума" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчикът не прие команда ACK" -#define D_SHT1X_FOUND "Намерен е SHT1X" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Частици" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Ускорение - ос X" -#define D_AY_AXIS "Ускорение - ос Y" -#define D_AZ_AXIS "Ускорение - ос Z" -#define D_GX_AXIS "Жироскоп - ос X" -#define D_GY_AXIS "Жироскоп - ос Y" -#define D_GZ_AXIS "Жироскоп - ос Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Премахване на тегло" -#define D_HX_CAL_REFERENCE "Зареждане на референтно тегло" -#define D_HX_CAL_DONE "Калибриран" -#define D_HX_CAL_FAIL "Неуспешно калибриране" -#define D_RESET_HX711 "Нулиране на кантара" -#define D_CONFIGURE_HX711 "Конфигуриране на кантара" -#define D_HX711_PARAMETERS "Параметри на кантара" -#define D_ITEM_WEIGHT "Тегло" -#define D_REFERENCE_WEIGHT "Референтно тегло" -#define D_CALIBRATE "Калибриране" -#define D_CALIBRATION "Калибровка" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Посока на вятъра" -#define D_TX20_WIND_SPEED "Скорост на вятъра" -#define D_TX20_WIND_SPEED_AVG "Средна скорост на вятъра" -#define D_TX20_WIND_SPEED_MAX "Макс. скорост на вятъра" -#define D_TX20_NORTH "С" -#define D_TX20_EAST "И" -#define D_TX20_SOUTH "Ю" -#define D_TX20_WEST "З" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Няма" -#define D_SENSOR_USER "Потребит." -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 плейър" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Ключ" // Suffix "1" -#define D_SENSOR_BUTTON "Бутон" // Suffix "1" -#define D_SENSOR_RELAY "Реле" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Брояч" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Подсветка" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF датчик" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "gal/min" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" -#define D_UNIT_KILOOHM "kΩ" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "сектори" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Фазов ъгъл" -#define D_IMPORT_ACTIVE "Входна активна мощност" -#define D_EXPORT_ACTIVE "Изходна активна мощност" -#define D_IMPORT_REACTIVE "Входна реактивна мощност" -#define D_EXPORT_REACTIVE "Изходна реактивна мощност" -#define D_TOTAL_REACTIVE "Общо реактивна мощност" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "°" - -//SOLAXX1 -#define D_PV1_VOLTAGE "Напрежение на PV1" -#define D_PV1_CURRENT "Ток на PV1" -#define D_PV1_POWER "Мощност на PV1" -#define D_PV2_VOLTAGE "Напрежение на PV2" -#define D_PV2_CURRENT "Ток на PV2" -#define D_PV2_POWER "Мощност на PV2" -#define D_SOLAR_POWER "Слънчева мощност" -#define D_INVERTER_POWER "Мощност на инвертера" -#define D_STATUS "Състояние" -#define D_WAITING "Очакване" -#define D_CHECKING "Проверка" -#define D_WORKING "Работи" -#define D_FAILURE "Грешка" -#define D_SOLAX_ERROR_0 "Грешка - няма код" -#define D_SOLAX_ERROR_1 "Грешка - загуба на мрежата" -#define D_SOLAX_ERROR_2 "Грешка - мрежово напрежение" -#define D_SOLAX_ERROR_3 "Грешка - мрежова честота" -#define D_SOLAX_ERROR_4 "Грешка - напрежение на Pv" -#define D_SOLAX_ERROR_5 "Грешка - проблем с изолацията" -#define D_SOLAX_ERROR_6 "Грешка - прегряване" -#define D_SOLAX_ERROR_7 "Грешка - вентилатор" -#define D_SOLAX_ERROR_8 "Грешка - друго оборудване" - -#endif // _LANGUAGE_BG_BG_H_ +/* + bg-BG.h - localization for Bulgaria - Bulgarian for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_BG_BG_H_ +#define _LANGUAGE_BG_BG_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.1.2.4 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1026 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "bg" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "НедПонВтрСрдЧетПетСъб" +#define D_MONTH3LIST "ЯнуФевМарАпрМайЮниЮлиАвгСепОктНоеДек" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Качество на въздуха" +#define D_AP "Точка за достъп" // Access Point +#define D_AS "като" +#define D_AUTO "АВТОМАТИЧНО" +#define D_BLINK "Мигане вкл." +#define D_BLINKOFF "Мигане изкл." +#define D_BOOT_COUNT "Брой на стартиранията" +#define D_BRIGHTLIGHT "Яркост" +#define D_BSSID "BSSId" +#define D_BUTTON "Бутон" +#define D_BY "от" // Written by me +#define D_BYTES "Байта" +#define D_CELSIUS "Целзий" +#define D_CHANNEL "Канал" +#define D_CO2 "Въглероден диоксид" +#define D_CODE "код" // Button code +#define D_COLDLIGHT "Хладна" +#define D_COMMAND "Команда" +#define D_CONNECTED "Свързан" +#define D_CORS_DOMAIN "CORS домейн" +#define D_COUNT "Брой" +#define D_COUNTER "Брояч" +#define D_CURRENT "Ток" // As in Voltage and Current +#define D_DATA "Данни" +#define D_DARKLIGHT "Тъмна" +#define D_DEBUG "Дебъгване" +#define D_DISABLED "Забранен" +#define D_DISTANCE "Разстояние" +#define D_DNS_SERVER "DNS Сървър" +#define D_DONE "Изпълнено" +#define D_DST_TIME "Лятно време" +#define D_ECO2 "eCO₂" +#define D_EMULATION "Емулация" +#define D_ENABLED "Разрешен" +#define D_ERASE "Изтриване" +#define D_ERROR "Грешка" +#define D_FAHRENHEIT "Фаренхайт" +#define D_FAILED "Неуспешно" +#define D_FALLBACK "Помощен" +#define D_FALLBACK_TOPIC "Помощен топик" +#define D_FALSE "Невярно" +#define D_FILE "Файл" +#define D_FLOW_RATE "Дебит" +#define D_FREE_MEMORY "Свободна памет" +#define D_FREQUENCY "Честота" +#define D_GAS "Газ" +#define D_GATEWAY "Шлюз" +#define D_GROUP "Група" +#define D_HOST "Хост" +#define D_HOSTNAME "Име на хоста" +#define D_HUMIDITY "Влажност" +#define D_ILLUMINANCE "Осветеност" +#define D_IMMEDIATE "Моментен" // Button immediate +#define D_INDEX "Индекс" +#define D_INFO "Информация" +#define D_INFRARED "Инфрачервен" +#define D_INITIALIZED "Инициализирано" +#define D_IP_ADDRESS "IP адрес" +#define D_LIGHT "Светлина" +#define D_LWT "LWT" +#define D_MODULE "Модул" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "неколкократно натискане" +#define D_NOISE "Шум" +#define D_NONE "Няма" +#define D_OFF "Изкл." +#define D_OFFLINE "Офлайн" +#define D_OK "Ок" +#define D_ON "Вкл." +#define D_ONLINE "Онлайн" +#define D_PASSWORD "Парола" +#define D_PORT "Порт" +#define D_POWER_FACTOR "Фактор на мощността" +#define D_POWERUSAGE "Мощност" +#define D_POWERUSAGE_ACTIVE "Активна мощност" +#define D_POWERUSAGE_APPARENT "Пълна мощност" +#define D_POWERUSAGE_REACTIVE "Реактивна мощност" +#define D_PRESSURE "Налягане" +#define D_PRESSUREATSEALEVEL "Налягане при морското ниво" +#define D_PROGRAM_FLASH_SIZE "Размер на флаш паметта за програми" +#define D_PROGRAM_SIZE "Размер на програмата" +#define D_PROJECT "Проект" +#define D_RAIN "Дъжд" +#define D_RECEIVED "Получено" +#define D_RESTART "Рестарт" +#define D_RESTARTING "Рестартиране" +#define D_RESTART_REASON "Причина за рестарта" +#define D_RESTORE "възстановяване" +#define D_RETAINED "запазено" +#define D_RULE "Правило" +#define D_SAVE "Запис" +#define D_SENSOR "Датчик" +#define D_SSID "SSId" +#define D_START "Старт" +#define D_STD_TIME "STD" +#define D_STOP "Стоп" +#define D_SUBNET_MASK "Маска на подмрежата" +#define D_SUBSCRIBE_TO "Записване за" +#define D_UNSUBSCRIBE_FROM "Отписване от" +#define D_SUCCESSFUL "Успешно" +#define D_SUNRISE "Изгрев" +#define D_SUNSET "Залез" +#define D_TEMPERATURE "Температура" +#define D_TO "към" +#define D_TOGGLE "Превключване" +#define D_TOPIC "Топик" +#define D_TOTAL_USAGE "Използвана вода" +#define D_TRANSMIT "Предаване" +#define D_TRUE "Вярно" +#define D_TVOC "TVOC" +#define D_UPGRADE "Обновяване" +#define D_UPLOAD "Зареждане" +#define D_UPTIME "Време от стартирането" +#define D_USER "Потребител" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV индекс" +#define D_UV_INDEX_1 "Нисък" +#define D_UV_INDEX_2 "Среден" +#define D_UV_INDEX_3 "Висок" +#define D_UV_INDEX_4 "Много висок" +#define D_UV_INDEX_5 "Изгаряне 1/2 степен" +#define D_UV_INDEX_6 "Изгаряне 3-та степен" +#define D_UV_INDEX_7 "Извън обхват" +#define D_UV_LEVEL "UV ниво" +#define D_UV_POWER "UV мощност" +#define D_VERSION "Версия" +#define D_VOLTAGE "Напрежение" +#define D_WEIGHT "Тегло" +#define D_WARMLIGHT "Топла" +#define D_WEB_SERVER "Уеб сървър" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Тази версия не поддържа постоянни настройки" +#define D_LEVEL_10 "ниво 1-0" +#define D_LEVEL_01 "ниво 0-1" +#define D_SERIAL_LOGGING_DISABLED "Серийният лог изключен" +#define D_SYSLOG_LOGGING_REENABLED "Системният лог активиран" + +#define D_SET_BAUDRATE_TO "Задаване скорост на предаване (Baudrate)" +#define D_RECEIVED_TOPIC "Получен топик" +#define D_DATA_SIZE "Размер на данните" +#define D_ANALOG_INPUT "Аналогов вход" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Блокиран цикъл" +#define D_WPS_FAILED_WITH_STATUS "WPS конфигурацията е НЕУСПЕШНА със статус" +#define D_ACTIVE_FOR_3_MINUTES "активно в течение на 3 минути" +#define D_FAILED_TO_START "Неуспешно стартиране" +#define D_PATCH_ISSUE_2186 "Проблем с патч 2186" +#define D_CONNECTING_TO_AP "Свързване към точка за достъп" +#define D_IN_MODE "в режим" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Грешка при свързването, не е получен IP адрес" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Грешка при свързването, точката за достъп е недостижима" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Грешка при свързването, грешна парола към точката за достъп" +#define D_CONNECT_FAILED_AP_TIMEOUT "Грешка при свързването, превишено време за изчакване" +#define D_ATTEMPTING_CONNECTION "Опитва свързване..." +#define D_CHECKING_CONNECTION "Проверка на свързването..." +#define D_QUERY_DONE "Запитването е изпълнено. Намерена е услуга MQTT" +#define D_MQTT_SERVICE_FOUND "MQTT услуга е намерена на" +#define D_FOUND_AT "намерена в" +#define D_SYSLOG_HOST_NOT_FOUND "Хостът на системния лог не е намерен" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Запазено във флаш паметта на" +#define D_LOADED_FROM_FLASH_AT "Заредено от флаш паметта от" +#define D_USE_DEFAULTS "Използване на параметри по подразбиране" +#define D_ERASED_SECTOR "Изтрит сектор" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуер
моля надградете го" +#define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на" +#define D_WITH_IP_ADDRESS "с IP адрес" +#define D_WEBSERVER_STOPPED "Уеб сървърът е спрян" +#define D_FILE_NOT_FOUND "Файлът не е намерен" +#define D_REDIRECTED "Пренасочено към адаптивния портал" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi мениджърът настройва точка за достъп и запомня станцията" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi мениджърът настрои точката за достъп" +#define D_TRYING_TO_CONNECT "Опит за свързване на устройството към мрежата" + +#define D_RESTART_IN "Рестарт след" +#define D_SECONDS "секунди" +#define D_DEVICE_WILL_RESTART "Устройството ще се рестартира след няколко секунди" +#define D_BUTTON_TOGGLE "Превключване" +#define D_CONFIGURATION "Конфигурация" +#define D_INFORMATION "Информация" +#define D_FIRMWARE_UPGRADE "Обновяване на фърмуера" +#define D_CONSOLE "Конзола" +#define D_CONFIRM_RESTART "Потвърдете рестартирането" + +#define D_CONFIGURE_MODULE "Конфигурация на модула" +#define D_CONFIGURE_WIFI "Конфигурация на WiFi" +#define D_CONFIGURE_MQTT "Конфигурация на MQTT" +#define D_CONFIGURE_DOMOTICZ "Конфигурация на Domoticz" +#define D_CONFIGURE_LOGGING "Конфигурация на лога" +#define D_CONFIGURE_OTHER "Други конфигурации" +#define D_CONFIRM_RESET_CONFIGURATION "Потвърдете изчистването" +#define D_RESET_CONFIGURATION "Изчистване на конфигурацията" +#define D_BACKUP_CONFIGURATION "Запазване на конфигурацията" +#define D_RESTORE_CONFIGURATION "Възстановяване на конфигурацията" +#define D_MAIN_MENU "Основно меню" + +#define D_MODULE_PARAMETERS "Параметри на модула" +#define D_MODULE_TYPE "Тип на модула" +#define D_PULLUP_ENABLE "Без pull-up за бутон/ключ" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Сериен вход" +#define D_SERIAL_OUT "Сериен изход" + +#define D_WIFI_PARAMETERS "Wifi параметри" +#define D_SCAN_FOR_WIFI_NETWORKS "Сканиране за безжични мрежи" +#define D_SCAN_DONE "Сканирането приключи" +#define D_NO_NETWORKS_FOUND "Не бяха открити мрежи" +#define D_REFRESH_TO_SCAN_AGAIN "Обновяване за повторно сканиране" +#define D_DUPLICATE_ACCESSPOINT "Дублиране на точката за достъп (AP)" +#define D_SKIPPING_LOW_QUALITY "Пропускане поради лошо качество" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Парола" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Парола" + +#define D_MQTT_PARAMETERS "Параметри на MQTT" +#define D_CLIENT "Клиент" +#define D_FULL_TOPIC "Пълен топик" + +#define D_LOGGING_PARAMETERS "Параметри на лога" +#define D_SERIAL_LOG_LEVEL "Степен на серийния лог" +#define D_MQTT_LOG_LEVEL "Степен на MQTT лога" +#define D_WEB_LOG_LEVEL "Степен на уеб лога" +#define D_SYS_LOG_LEVEL "Степен на системния лог" +#define D_MORE_DEBUG "Допълнителна debug информация" +#define D_SYSLOG_HOST "Хост на системния лог" +#define D_SYSLOG_PORT "Порт на системния лог" +#define D_TELEMETRY_PERIOD "Период на телеметрия" + +#define D_OTHER_PARAMETERS "Други параметри" +#define D_TEMPLATE "Модел" +#define D_ACTIVATE "Активирай" +#define D_WEB_ADMIN_PASSWORD "Парола на уеб администратора" +#define D_MQTT_ENABLE "Активиране на MQTT" +#define D_FRIENDLY_NAME "Приятелско име" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "Единично" +#define D_MULTI_DEVICE "Мулти" + +#define D_CONFIGURE_TEMPLATE "Конфигуриране на шаблон" +#define D_TEMPLATE_PARAMETERS "Параметри на шаблона" +#define D_TEMPLATE_NAME "Име" +#define D_BASE_TYPE "Базиран на" +#define D_TEMPLATE_FLAGS "Опции" + +#define D_SAVE_CONFIGURATION "Запазване на конфигурацията" +#define D_CONFIGURATION_SAVED "Конфигурацията е запазена" +#define D_CONFIGURATION_RESET "Конфигурацията е изчистена" + +#define D_PROGRAM_VERSION "Версия на програмата" +#define D_BUILD_DATE_AND_TIME "Дата и час на компилацията" +#define D_CORE_AND_SDK_VERSION "Версия на Core/SDK" +#define D_FLASH_WRITE_COUNT "Брой на записите във флаш паметта" +#define D_MAC_ADDRESS "MAC адрес" +#define D_MQTT_HOST "MQTT хост" +#define D_MQTT_PORT "MQTT порт" +#define D_MQTT_CLIENT "MQTT ID на клиент" +#define D_MQTT_USER "MQTT потребител" +#define D_MQTT_TOPIC "MQTT топик" +#define D_MQTT_GROUP_TOPIC "MQTT групов топик" +#define D_MQTT_FULL_TOPIC "MQTT пълен топик" +#define D_MDNS_DISCOVERY "mDNS откриване" +#define D_MDNS_ADVERTISE "mDNS известяване" +#define D_ESP_CHIP_ID "ID на ESP чипа" +#define D_FLASH_CHIP_ID "ID на чипа на флаш паметта" +#define D_FLASH_CHIP_SIZE "Размер на флаш паметта" +#define D_FREE_PROGRAM_SPACE "Свободно пространство за програми" + +#define D_UPGRADE_BY_WEBSERVER "Обновяване чрез уеб сървър" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Започване на обновяване" +#define D_UPGRADE_BY_FILE_UPLOAD "Обновяване чрез зареждане на файл" +#define D_UPLOAD_STARTED "Зареждането започна" +#define D_UPGRADE_STARTED "Обновяването започна" +#define D_UPLOAD_DONE "Зареждането завърши" +#define D_UPLOAD_ERR_1 "Не е избран файл" +#define D_UPLOAD_ERR_2 "Недостатъчно свободно място" +#define D_UPLOAD_ERR_3 "Magic байтът не е 0xE9" +#define D_UPLOAD_ERR_4 "Размерът на програмата е по-голям от реалния размер на флаш паметта" +#define D_UPLOAD_ERR_5 "Грешка при зареждането в буфера" +#define D_UPLOAD_ERR_6 "Грешка при зареждането. Включено е ниво 3 на лога" +#define D_UPLOAD_ERR_7 "Зареждането е прекъснато" +#define D_UPLOAD_ERR_8 "Файлът е невалиден" +#define D_UPLOAD_ERR_9 "Файлът е прекалено голям" +#define D_UPLOAD_ERR_10 "Грешка при инициализация на RF чипа" +#define D_UPLOAD_ERR_11 "Грешка при изтриване на RF чипа" +#define D_UPLOAD_ERR_12 "Грешка при записване в RF чипа" +#define D_UPLOAD_ERR_13 "Грешка при декодиране на RF фърмуера" +#define D_UPLOAD_ERROR_CODE "Код на грешка при зареждането" + +#define D_ENTER_COMMAND "Въвеждане на команда" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Включете ниво 2 на лога, ако очаквате отговор" +#define D_NEED_USER_AND_PASSWORD "Очаква user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Проверка на TLS отпечатък..." +#define D_TLS_CONNECT_FAILED_TO "Неуспешно TLS свързване към" +#define D_RETRY_IN "Повтори след" +#define D_VERIFIED "Проверен отпечтък" +#define D_INSECURE "Нешифрована връзка, недействителен отпечатък" +#define D_CONNECT_FAILED_TO "Грешка при свързването към" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast е изключен" +#define D_MULTICAST_REJOINED "Multicast е повторно съединен" +#define D_MULTICAST_JOIN_FAILED "Multicast грешка при присъединяването" +#define D_FAILED_TO_SEND_RESPONSE "Неуспех при изпращането на отговор" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo главно събитие" +#define D_WEMO_EVENT_SERVICE "WeMo услуга за събитията" +#define D_WEMO_META_SERVICE "WeMo мета-услуга" +#define D_WEMO_SETUP "WeMo настройка" +#define D_RESPONSE_SENT "Отговорът е изпратен" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Настройка на Hue bridge" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API не е внедрен" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST аргументи" +#define D_3_RESPONSE_PACKETS_SENT "Изпратени са 3 пакета за отговор" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz параметри" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Мощност,Енергия" + #define D_DOMOTICZ_ILLUMINANCE "Осветеност" + #define D_DOMOTICZ_COUNT "Брояч/PM1" + #define D_DOMOTICZ_VOLTAGE "Напрежение/PM2,5" + #define D_DOMOTICZ_CURRENT "Ток/PM10" + #define D_DOMOTICZ_AIRQUALITY "Качество на въздуха" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Период на опресняване" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Конфигуриране на таймер" +#define D_TIMER_PARAMETERS "Параметри на таймера" +#define D_TIMER_ENABLE "Активиране на таймера" +#define D_TIMER_ARM "Активиран" +#define D_TIMER_TIME "Време" +#define D_TIMER_DAYS "Дни" +#define D_TIMER_REPEAT "Повтори" +#define D_TIMER_OUTPUT "Изход" +#define D_TIMER_ACTION "Действие" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Конфигуриране на KNX" +#define D_KNX_PARAMETERS "KNX параметри" +#define D_KNX_GENERAL_CONFIG "Основни" +#define D_KNX_PHYSICAL_ADDRESS "Физически адрес" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Трябва да е уникален в KNX мрежата )" +#define D_KNX_ENABLE "Активиране на KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Групови адреси за изпращане на данни" +#define D_ADD "Добаване" +#define D_DELETE "Изтриване" +#define D_REPLY "Отговор" +#define D_KNX_GROUP_ADDRESS_TO_READ "Групови адреси за получаване на данни" +#define D_RECEIVED_FROM "Получен от" +#define D_KNX_COMMAND_WRITE "Писане" +#define D_KNX_COMMAND_READ "Четене" +#define D_KNX_COMMAND_OTHER "Друго" +#define D_SENT_TO "изпратен до" +#define D_KNX_WARNING "Груповият адрес (0/0/0) е резервиран и не може да бъде използван." +#define D_KNX_ENHANCEMENT "Подобрена комуникация" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Използвана енергия днес" +#define D_ENERGY_YESTERDAY "Използвана енергия вчера" +#define D_ENERGY_TOTAL "Използвана енергия общо" + +// xdrv_27_shutter.ino +#define D_OPEN "Отворена" +#define D_CLOSE "Затворена" +#define D_DOMOTICZ_SHUTTER "Щора" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Конфигуриране на PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 параметри" +#define D_INVERT_PORTS "Обърни портовете" +#define D_DEVICE "Устройство" +#define D_DEVICE_INPUT "Вход" +#define D_DEVICE_OUTPUT "Изход" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Датчикът DS18x20 е зает" +#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - грешка CRC" +#define D_SENSORS_FOUND "Намерен е датчик DS18x20" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Изтекло време за очакване на" +#define D_START_SIGNAL_LOW "Нисък стартов сигнал" +#define D_START_SIGNAL_HIGH "Висок стартов сигнал" +#define D_PULSE "Импулс" +#define D_CHECKSUM_FAILURE "Грешка в контролната сума" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчикът не прие команда ACK" +#define D_SHT1X_FOUND "Намерен е SHT1X" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Частици" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Ускорение - ос X" +#define D_AY_AXIS "Ускорение - ос Y" +#define D_AZ_AXIS "Ускорение - ос Z" +#define D_GX_AXIS "Жироскоп - ос X" +#define D_GY_AXIS "Жироскоп - ос Y" +#define D_GZ_AXIS "Жироскоп - ос Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Премахване на тегло" +#define D_HX_CAL_REFERENCE "Зареждане на референтно тегло" +#define D_HX_CAL_DONE "Калибриран" +#define D_HX_CAL_FAIL "Неуспешно калибриране" +#define D_RESET_HX711 "Нулиране на кантара" +#define D_CONFIGURE_HX711 "Конфигуриране на кантара" +#define D_HX711_PARAMETERS "Параметри на кантара" +#define D_ITEM_WEIGHT "Тегло" +#define D_REFERENCE_WEIGHT "Референтно тегло" +#define D_CALIBRATE "Калибриране" +#define D_CALIBRATION "Калибровка" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Посока на вятъра" +#define D_TX20_WIND_SPEED "Скорост на вятъра" +#define D_TX20_WIND_SPEED_AVG "Средна скорост на вятъра" +#define D_TX20_WIND_SPEED_MAX "Макс. скорост на вятъра" +#define D_TX20_NORTH "С" +#define D_TX20_EAST "И" +#define D_TX20_SOUTH "Ю" +#define D_TX20_WEST "З" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Няма" +#define D_SENSOR_USER "Потребит." +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 плейър" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Ключ" // Suffix "1" +#define D_SENSOR_BUTTON "Бутон" // Suffix "1" +#define D_SENSOR_RELAY "Реле" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Брояч" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Подсветка" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF датчик" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "gal/min" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "сектори" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Фазов ъгъл" +#define D_IMPORT_ACTIVE "Входна активна мощност" +#define D_EXPORT_ACTIVE "Изходна активна мощност" +#define D_IMPORT_REACTIVE "Входна реактивна мощност" +#define D_EXPORT_REACTIVE "Изходна реактивна мощност" +#define D_TOTAL_REACTIVE "Общо реактивна мощност" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "°" + +//SOLAXX1 +#define D_PV1_VOLTAGE "Напрежение на PV1" +#define D_PV1_CURRENT "Ток на PV1" +#define D_PV1_POWER "Мощност на PV1" +#define D_PV2_VOLTAGE "Напрежение на PV2" +#define D_PV2_CURRENT "Ток на PV2" +#define D_PV2_POWER "Мощност на PV2" +#define D_SOLAR_POWER "Слънчева мощност" +#define D_INVERTER_POWER "Мощност на инвертера" +#define D_STATUS "Състояние" +#define D_WAITING "Очакване" +#define D_CHECKING "Проверка" +#define D_WORKING "Работи" +#define D_FAILURE "Грешка" +#define D_SOLAX_ERROR_0 "Грешка - няма код" +#define D_SOLAX_ERROR_1 "Грешка - загуба на мрежата" +#define D_SOLAX_ERROR_2 "Грешка - мрежово напрежение" +#define D_SOLAX_ERROR_3 "Грешка - мрежова честота" +#define D_SOLAX_ERROR_4 "Грешка - напрежение на Pv" +#define D_SOLAX_ERROR_5 "Грешка - проблем с изолацията" +#define D_SOLAX_ERROR_6 "Грешка - прегряване" +#define D_SOLAX_ERROR_7 "Грешка - вентилатор" +#define D_SOLAX_ERROR_8 "Грешка - друго оборудване" + +#endif // _LANGUAGE_BG_BG_H_ diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 7579e1922..1d7c6f381 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -1,703 +1,701 @@ -/* - cs-CZ.h - localization for Czech with diacritics - Czech for Tasmota - - Copyright (C) 2019 Vladimír Synek - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_CS_CZ_H_ -#define _LANGUAGE_CS_CZ_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.5.0.9 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1029 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "cs" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "Ne Po Út St Čt Pá So " -#define D_MONTH3LIST "LedÚnoBřeDubKvěČvnČvcSrpZářŘíjLisPro" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Kvalita vzduchu" -#define D_AP "AP" // Access Point -#define D_AS "jako" -#define D_AUTO "AUTO" -#define D_BLINK "Blikání" -#define D_BLINKOFF "BlikáníVyp" -#define D_BOOT_COUNT "Počítadlo spuštění" -#define D_BRIGHTLIGHT "Světlý" -#define D_BSSID "BSSId" -#define D_BUTTON "Tlačítko" -#define D_BY "by" // Written by me -#define D_BYTES "Bytů" -#define D_CELSIUS "°C" -#define D_CHANNEL "Channel" -#define D_CO2 "CO2" -#define D_CODE "kód" // Button code -#define D_COLDLIGHT "Studené světlo" -#define D_COMMAND "Příkaz" -#define D_CONNECTED "...připojeno" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Počítej" -#define D_COUNTER "Počítadlo" -#define D_CURRENT "Proud" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Tmavý" -#define D_DEBUG "Debug" -#define D_DISABLED "Zablokováno" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "Server DNS" -#define D_DONE "Provedeno" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulace" -#define D_ENABLED "Otevřený" -#define D_ERASE "Smaž" -#define D_ERROR "Chyba" -#define D_FAHRENHEIT "Fahrenheita" -#define D_FAILED "chyba" -#define D_FALLBACK "Záložní" -#define D_FALLBACK_TOPIC "Záložní topic" -#define D_FALSE "Nepravda" -#define D_FILE "Soubor" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Volná paměť" -#define D_FREQUENCY "Kmitočet" -#define D_GAS "Plyn" -#define D_GATEWAY "Výchozí brána" -#define D_GROUP "Skupina" -#define D_HOST "Server" -#define D_HOSTNAME "Název serveru" -#define D_HUMIDITY "Vlhkost" -#define D_ILLUMINANCE "Osvětlení" -#define D_IMMEDIATE "Okamžité" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Informace" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "Inicializovaný" -#define D_IP_ADDRESS "Adresa IP" -#define D_LIGHT "Světlo" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "několikeré-stisknutí" -#define D_NOISE "Hluk" -#define D_NONE "Žádný" -#define D_OFF "Vyp." -#define D_OFFLINE "Neaktivní" -#define D_OK "OK" -#define D_ON "Zap." -#define D_ONLINE "Aktivní" -#define D_PASSWORD "Heslo" -#define D_PORT "Port" -#define D_POWER_FACTOR "Účiník" -#define D_POWERUSAGE "Příkon" -#define D_POWERUSAGE_ACTIVE "Činný příkon" -#define D_POWERUSAGE_APPARENT "Zdánlivý příkon" -#define D_POWERUSAGE_REACTIVE "Jalový příkon" -#define D_PRESSURE "Tlak" -#define D_PRESSUREATSEALEVEL "Tlak na hladině moře" -#define D_PROGRAM_FLASH_SIZE "Velikost paměti flash" -#define D_PROGRAM_SIZE "Velikost programu" -#define D_PROJECT "Projekt" -#define D_RAIN "Rain" -#define D_RECEIVED "Přijatý" -#define D_RESTART "Restart" -#define D_RESTARTING "Restartování" -#define D_RESTART_REASON "Příčina restartu" -#define D_RESTORE "Obnovit" -#define D_RETAINED "Zachováno" -#define D_RULE "Rule" -#define D_SAVE "Ulož" -#define D_SENSOR "Sensor" -#define D_SSID "SSID" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Maska podsítě" -#define D_SUBSCRIBE_TO "Přihlaš se do" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "úspěšné." -#define D_SUNRISE "Svítání" -#define D_SUNSET "Soumrak" -#define D_TEMPERATURE "Teplota" -#define D_TO "do" -#define D_TOGGLE "Přepni" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Odešli" -#define D_TRUE "Pravda" -#define D_TVOC "TVOC" -#define D_UPGRADE "aktualizace" -#define D_UPLOAD "Nahrání..." -#define D_UPTIME "Uptime" -#define D_USER "Uživatel" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Nízký" -#define D_UV_INDEX_2 "Střední" -#define D_UV_INDEX_3 "Vysoký" -#define D_UV_INDEX_4 "Nebezpečný" -#define D_UV_INDEX_5 "Popál1/2" -#define D_UV_INDEX_6 "Popál3" -#define D_UV_INDEX_7 "MimoRozsah" -#define D_UV_LEVEL "úroveň UV" -#define D_UV_POWER "UV Power" -#define D_VERSION "Verze" -#define D_VOLTAGE "Napětí" -#define D_WEIGHT "Hmotnost" -#define D_WARMLIGHT "Teplé světlo" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "UPOZORNĚNÍ Tato verze nepodporuje trvalé nastavení" -#define D_LEVEL_10 "úroveň 1-0" -#define D_LEVEL_01 "úroveň 0-1" -#define D_SERIAL_LOGGING_DISABLED "Logování na sériovém portu ukončeno" -#define D_SYSLOG_LOGGING_REENABLED "Obnoven zápis do Syslog" - -#define D_SET_BAUDRATE_TO "Nastavení rychlosti přenosu na" -#define D_RECEIVED_TOPIC "Přijatý topic" -#define D_DATA_SIZE "Velikost dat" -#define D_ANALOG_INPUT "Analogový vstup" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Zablokování smyčky" -#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig se statusem" -#define D_ACTIVE_FOR_3_MINUTES "aktivní 3 minuty" -#define D_FAILED_TO_START "nepodařilo se spustit" -#define D_PATCH_ISSUE_2186 "Chyba 2186" -#define D_CONNECTING_TO_AP "Připojování k AP" -#define D_IN_MODE "v módu" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba připojení, nebyla obdržena IP adresa" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba připojení, nedostupný AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba připojení, nesprávné heslo pro AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba připojení, uplynul AP timeout" -#define D_ATTEMPTING_CONNECTION "Připojování..." -#define D_CHECKING_CONNECTION "Zkouška spojení..." -#define D_QUERY_DONE "Vyslání dotazu. Nalezena služba MQTT" -#define D_MQTT_SERVICE_FOUND "Služba MQTT byla nalezena" -#define D_FOUND_AT "znalezeno v" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebyl nalezen" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Uloženo do paměti flash v" -#define D_LOADED_FROM_FLASH_AT "Staženo z paměti flash z" -#define D_USE_DEFAULTS "Použij defaultní hodnoty" -#define D_ERASED_SECTOR "Smazaný sektor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" -#define D_WEBSERVER_ACTIVE_ON "Aktivní Web server" -#define D_WITH_IP_ADDRESS "na IP adrese" -#define D_WEBSERVER_STOPPED "Web server zastaven" -#define D_FILE_NOT_FOUND "Soubor nebyl nalezen" -#define D_REDIRECTED "Přesměrování na vlastní portál" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manager nastaví AP a zachová STA" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manager nastaví Access Point" -#define D_TRYING_TO_CONNECT "Zkouším připojit zařízení k síti" - -#define D_RESTART_IN "Restart" -#define D_SECONDS "sekund" -#define D_DEVICE_WILL_RESTART "Zařízení bude zrestartováno během několika sekund" -#define D_BUTTON_TOGGLE "Přepínač" -#define D_CONFIGURATION "Nastavení" -#define D_INFORMATION "Informace" -#define D_FIRMWARE_UPGRADE "Aktualizace firmware" -#define D_CONSOLE "Konzole" -#define D_CONFIRM_RESTART "Potvrzení restartu" - -#define D_CONFIGURE_MODULE "Nastavení modulu" -#define D_CONFIGURE_WIFI "Nastavení WiFi" -#define D_CONFIGURE_MQTT "Nastavení MQTT" -#define D_CONFIGURE_DOMOTICZ "Nastavení Domoticz" -#define D_CONFIGURE_LOGGING "Nastavení logování" -#define D_CONFIGURE_OTHER "Jiná nastavení" -#define D_CONFIRM_RESET_CONFIGURATION "Potvrzení resetu nastavení" -#define D_RESET_CONFIGURATION "Reset nastavení" -#define D_BACKUP_CONFIGURATION "Záloha nastavení" -#define D_RESTORE_CONFIGURATION "Obnovení nastavení" -#define D_MAIN_MENU "Hlavní menu" - -#define D_MODULE_PARAMETERS "Nastavení modulu" -#define D_MODULE_TYPE "Typ modulu" -#define D_PULLUP_ENABLE "Tlačítko/Spínač bez pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Nastavení WiFi" -#define D_SCAN_FOR_WIFI_NETWORKS "Scan sítí WiFi" -#define D_SCAN_DONE "Scan dokončen" -#define D_NO_NETWORKS_FOUND "Síť nebyla nalezena" -#define D_REFRESH_TO_SCAN_AGAIN "Zopakovat scan" -#define D_DUPLICATE_ACCESSPOINT "Kopie AP" -#define D_SKIPPING_LOW_QUALITY "Přeskočení z důvodu kvality signálu" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "Heslo AP1" -#define D_AP2_SSID "AP2 SSID" -#define D_AP2_PASSWORD "Heslo AP2" - -#define D_MQTT_PARAMETERS "Nastavení MQTT" -#define D_CLIENT "Klient" -#define D_FULL_TOPIC "Celý topic" - -#define D_LOGGING_PARAMETERS "Volba logování" -#define D_SERIAL_LOG_LEVEL "Seriová úroveň logu" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Webová úroveň logu" -#define D_SYS_LOG_LEVEL "Systemová úroveň logu" -#define D_MORE_DEBUG "Více debug informací" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Interval telemetrie" - -#define D_OTHER_PARAMETERS "Další nastavení" -#define D_TEMPLATE "Šablona" -#define D_ACTIVATE "Aktivovat" -#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" -#define D_MQTT_ENABLE "MQTT aktivní" -#define D_FRIENDLY_NAME "Friendly Name" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "Nastavení šablony" -#define D_TEMPLATE_PARAMETERS "Parametry šablony" -#define D_TEMPLATE_NAME "Název" -#define D_BASE_TYPE "Vzor z" -#define D_TEMPLATE_FLAGS "Volby" - -#define D_SAVE_CONFIGURATION "Ulož nastavení" -#define D_CONFIGURATION_SAVED "Nastavení uloženo" -#define D_CONFIGURATION_RESET "Nastavení resetováno" - -#define D_PROGRAM_VERSION "Verze programu" -#define D_BUILD_DATE_AND_TIME "Datum a čas kompilace" -#define D_CORE_AND_SDK_VERSION "Verze Core/SDK" -#define D_FLASH_WRITE_COUNT "Počet zápisů do paměti" -#define D_MAC_ADDRESS "Adresa MAC" -#define D_MQTT_HOST "Host MQTT" -#define D_MQTT_PORT "Port MQTT" -#define D_MQTT_CLIENT "Klient MQTT" -#define D_MQTT_USER "Uživatel MQTT" -#define D_MQTT_TOPIC "Topic MQTT" -#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT" -#define D_MQTT_FULL_TOPIC "Celý topic MQTT" -#define D_MDNS_DISCOVERY "Získávání mDNS" -#define D_MDNS_ADVERTISE "Rozesílání mDNS" -#define D_ESP_CHIP_ID "ID systému ESP" -#define D_FLASH_CHIP_ID "ID systému paměti flash" -#define D_FLASH_CHIP_SIZE "Velikost flash" -#define D_FREE_PROGRAM_SPACE "Volné místo pro program" - -#define D_UPGRADE_BY_WEBSERVER "Aktualizace z Web serveru" -#define D_OTA_URL "URL OTA" -#define D_START_UPGRADE "Start aktualizace" -#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizace nahráním souboru" -#define D_UPLOAD_STARTED "Nahrávání zahájeno" -#define D_UPGRADE_STARTED "Zahájení aktualizace" -#define D_UPLOAD_DONE "Nahrávání ukončeno" -#define D_UPLOAD_ERR_1 "Soubor nebyl vybrán" -#define D_UPLOAD_ERR_2 "Málo místa" -#define D_UPLOAD_ERR_3 "Magický byte má hodnotu jinou než 0xE9" -#define D_UPLOAD_ERR_4 "Velikost programu je větší než skutečná velikost paměti flash" -#define D_UPLOAD_ERR_5 "Chyba nahrávání, nesouhlasí porovnávané bity" -#define D_UPLOAD_ERR_6 "Chyba nahrávání. Spuštěn zápis do logu na úrovni 3" -#define D_UPLOAD_ERR_7 "Nahrávání přerušeno" -#define D_UPLOAD_ERR_8 "Špatný soubor" -#define D_UPLOAD_ERR_9 "Soubor je příliš velký" -#define D_UPLOAD_ERR_10 "Chyba inicializace RF chipu" -#define D_UPLOAD_ERR_11 "Chyba smazání RF chipu" -#define D_UPLOAD_ERR_12 "Chyba při zápisu do RF chipu" -#define D_UPLOAD_ERR_13 "Chyba dekódování RF firmwaru" -#define D_UPLOAD_ERROR_CODE "Chyba nahrávání" - -#define D_ENTER_COMMAND "Vlož příkaz" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni úroveň 2 zápisu Weblog, pokud je očekávána odpověď" -#define D_NEED_USER_AND_PASSWORD "Vyžadován uživatel=&heslo=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifikuj otisk TLS..." -#define D_TLS_CONNECT_FAILED_TO "Nepřipojeno TLS do" -#define D_RETRY_IN "Zopakuji za" -#define D_VERIFIED "Ověřeno otisk " -#define D_INSECURE "Nesprávné připojení z důvodu chybného otisku TLS" -#define D_CONNECT_FAILED_TO "Spojení se nepodařilo navázat" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast je vypnutý" -#define D_MULTICAST_REJOINED "Multicast opět připojený" -#define D_MULTICAST_JOIN_FAILED "Multicast neúspěšný" -#define D_FAILED_TO_SEND_RESPONSE "Nepodařilo se odeslat odpověď" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo základní událost" -#define D_WEMO_EVENT_SERVICE "WeMo servisní událost" -#define D_WEMO_META_SERVICE "WeMo meta událost" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Odpověď odeslána" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API není implementováno" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovědi odeslány" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Nastavení Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Spinac idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak" - #define D_DOMOTICZ_POWER_ENERGY "Příkon,Energie" - #define D_DOMOTICZ_ILLUMINANCE "Osvětlení" - #define D_DOMOTICZ_COUNT "Počítadlo/PM1" - #define D_DOMOTICZ_VOLTAGE "Napětí/PM2,5" - #define D_DOMOTICZ_CURRENT "Proud/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Aktualizace stopek" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Nastavení Časovače" -#define D_TIMER_PARAMETERS "Časovač" -#define D_TIMER_ENABLE "Povol časovače" -#define D_TIMER_ARM "Aktivní" -#define D_TIMER_TIME "Čas" -#define D_TIMER_DAYS "Dny" -#define D_TIMER_REPEAT "Opakovat" -#define D_TIMER_OUTPUT "Výstup" -#define D_TIMER_ACTION "Napájení" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Nastavení KNX" -#define D_KNX_PARAMETERS "KNX parametry" -#define D_KNX_GENERAL_CONFIG "Obecné" -#define D_KNX_PHYSICAL_ADDRESS "Fyzická adresa" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musí být jedinečná v síti KNX )" -#define D_KNX_ENABLE "Povol KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data k odeslání na skupinové adresy" -#define D_ADD "Přidej" -#define D_DELETE "Smaž" -#define D_REPLY "Odpověď" -#define D_KNX_GROUP_ADDRESS_TO_READ "Skupinové adresy pro příjem dat z" -#define D_RECEIVED_FROM "Přijato z" -#define D_KNX_COMMAND_WRITE "Zapiš" -#define D_KNX_COMMAND_READ "Čti" -#define D_KNX_COMMAND_OTHER "Jiné" -#define D_SENT_TO "pošli" -#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervována a nemůže být použita." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Spotřeba Dnes" -#define D_ENERGY_YESTERDAY "Spotřeba Včera" -#define D_ENERGY_TOTAL "Celková spotřeba" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor DS18x20 obsazen" -#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" -#define D_SENSORS_FOUND "Nalezen sensor DS18x20" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Čekání na" -#define D_START_SIGNAL_LOW "nízký startovní signál" -#define D_START_SIGNAL_HIGH "vysoký startovní signál" -#define D_PULSE "impuls" -#define D_CHECKSUM_FAILURE "Chybný kontrolní součet" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor neobdržel příkaz ACK" -#define D_SHT1X_FOUND "SHT1X nalezen" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "částic" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. osa-X" -#define D_AY_AXIS "Accel. osa-Y" -#define D_AZ_AXIS "Accel. osa-Z" -#define D_GX_AXIS "Gyro osa-X" -#define D_GY_AXIS "Gyro osa-Y" -#define D_GZ_AXIS "Gyro osa-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Odstraňte zátěž" -#define D_HX_CAL_REFERENCE "Vložte referenční zátěž" -#define D_HX_CAL_DONE "Zkalibrováno" -#define D_HX_CAL_FAIL "Chyba kalibrace" -#define D_RESET_HX711 "Reset váhy" -#define D_CONFIGURE_HX711 "Konfigurace váhy" -#define D_HX711_PARAMETERS "Parametry váhy" -#define D_ITEM_WEIGHT "Vlastní hmotnost" -#define D_REFERENCE_WEIGHT "Referenční hmotnost" -#define D_CALIBRATE "Kalibruj" -#define D_CALIBRATION "Kalibrace" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Směr větru" -#define D_TX20_WIND_SPEED "Rychlost větru" -#define D_TX20_WIND_SPEED_AVG "Průměrná rychlost větru" -#define D_TX20_WIND_SPEED_MAX "Maximální rychlost větru" -#define D_TX20_NORTH "S" -#define D_TX20_EAST "V" -#define D_TX20_SOUTH "J" -#define D_TX20_WEST "Z" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Není" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Spínač" // Suffix "1" -#define D_SENSOR_BUTTON "Tlačítko" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1", -#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "hod" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sektory" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_CS_CZ_H_ +/* + cs-CZ.h - localization for Czech with diacritics - Czech for Tasmota + + Copyright (C) 2019 Vladimír Synek + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_CS_CZ_H_ +#define _LANGUAGE_CS_CZ_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.5.0.9 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1029 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "cs" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "Ne Po Út St Čt Pá So " +#define D_MONTH3LIST "LedÚnoBřeDubKvěČvnČvcSrpZářŘíjLisPro" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Kvalita vzduchu" +#define D_AP "AP" // Access Point +#define D_AS "jako" +#define D_AUTO "AUTO" +#define D_BLINK "Blikání" +#define D_BLINKOFF "BlikáníVyp" +#define D_BOOT_COUNT "Počítadlo spuštění" +#define D_BRIGHTLIGHT "Světlý" +#define D_BSSID "BSSId" +#define D_BUTTON "Tlačítko" +#define D_BY "by" // Written by me +#define D_BYTES "Bytů" +#define D_CELSIUS "°C" +#define D_CHANNEL "Channel" +#define D_CO2 "CO2" +#define D_CODE "kód" // Button code +#define D_COLDLIGHT "Studené světlo" +#define D_COMMAND "Příkaz" +#define D_CONNECTED "...připojeno" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Počítej" +#define D_COUNTER "Počítadlo" +#define D_CURRENT "Proud" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Tmavý" +#define D_DEBUG "Debug" +#define D_DISABLED "Zablokováno" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "Server DNS" +#define D_DONE "Provedeno" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulace" +#define D_ENABLED "Otevřený" +#define D_ERASE "Smaž" +#define D_ERROR "Chyba" +#define D_FAHRENHEIT "Fahrenheita" +#define D_FAILED "chyba" +#define D_FALLBACK "Záložní" +#define D_FALLBACK_TOPIC "Záložní topic" +#define D_FALSE "Nepravda" +#define D_FILE "Soubor" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Volná paměť" +#define D_FREQUENCY "Kmitočet" +#define D_GAS "Plyn" +#define D_GATEWAY "Výchozí brána" +#define D_GROUP "Skupina" +#define D_HOST "Server" +#define D_HOSTNAME "Název serveru" +#define D_HUMIDITY "Vlhkost" +#define D_ILLUMINANCE "Osvětlení" +#define D_IMMEDIATE "Okamžité" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Informace" +#define D_INFRARED "Infrared" +#define D_INITIALIZED "Inicializovaný" +#define D_IP_ADDRESS "Adresa IP" +#define D_LIGHT "Světlo" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "několikeré-stisknutí" +#define D_NOISE "Hluk" +#define D_NONE "Žádný" +#define D_OFF "Vyp." +#define D_OFFLINE "Neaktivní" +#define D_OK "OK" +#define D_ON "Zap." +#define D_ONLINE "Aktivní" +#define D_PASSWORD "Heslo" +#define D_PORT "Port" +#define D_POWER_FACTOR "Účiník" +#define D_POWERUSAGE "Příkon" +#define D_POWERUSAGE_ACTIVE "Činný příkon" +#define D_POWERUSAGE_APPARENT "Zdánlivý příkon" +#define D_POWERUSAGE_REACTIVE "Jalový příkon" +#define D_PRESSURE "Tlak" +#define D_PRESSUREATSEALEVEL "Tlak na hladině moře" +#define D_PROGRAM_FLASH_SIZE "Velikost paměti flash" +#define D_PROGRAM_SIZE "Velikost programu" +#define D_PROJECT "Projekt" +#define D_RAIN "Rain" +#define D_RECEIVED "Přijatý" +#define D_RESTART "Restart" +#define D_RESTARTING "Restartování" +#define D_RESTART_REASON "Příčina restartu" +#define D_RESTORE "Obnovit" +#define D_RETAINED "Zachováno" +#define D_RULE "Rule" +#define D_SAVE "Ulož" +#define D_SENSOR "Sensor" +#define D_SSID "SSID" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maska podsítě" +#define D_SUBSCRIBE_TO "Přihlaš se do" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "úspěšné." +#define D_SUNRISE "Svítání" +#define D_SUNSET "Soumrak" +#define D_TEMPERATURE "Teplota" +#define D_TO "do" +#define D_TOGGLE "Přepni" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Odešli" +#define D_TRUE "Pravda" +#define D_TVOC "TVOC" +#define D_UPGRADE "aktualizace" +#define D_UPLOAD "Nahrání..." +#define D_UPTIME "Uptime" +#define D_USER "Uživatel" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Nízký" +#define D_UV_INDEX_2 "Střední" +#define D_UV_INDEX_3 "Vysoký" +#define D_UV_INDEX_4 "Nebezpečný" +#define D_UV_INDEX_5 "Popál1/2" +#define D_UV_INDEX_6 "Popál3" +#define D_UV_INDEX_7 "MimoRozsah" +#define D_UV_LEVEL "úroveň UV" +#define D_UV_POWER "UV Power" +#define D_VERSION "Verze" +#define D_VOLTAGE "Napětí" +#define D_WEIGHT "Hmotnost" +#define D_WARMLIGHT "Teplé světlo" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "UPOZORNĚNÍ Tato verze nepodporuje trvalé nastavení" +#define D_LEVEL_10 "úroveň 1-0" +#define D_LEVEL_01 "úroveň 0-1" +#define D_SERIAL_LOGGING_DISABLED "Logování na sériovém portu ukončeno" +#define D_SYSLOG_LOGGING_REENABLED "Obnoven zápis do Syslog" + +#define D_SET_BAUDRATE_TO "Nastavení rychlosti přenosu na" +#define D_RECEIVED_TOPIC "Přijatý topic" +#define D_DATA_SIZE "Velikost dat" +#define D_ANALOG_INPUT "Analogový vstup" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Zablokování smyčky" +#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig se statusem" +#define D_ACTIVE_FOR_3_MINUTES "aktivní 3 minuty" +#define D_FAILED_TO_START "nepodařilo se spustit" +#define D_PATCH_ISSUE_2186 "Chyba 2186" +#define D_CONNECTING_TO_AP "Připojování k AP" +#define D_IN_MODE "v módu" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba připojení, nebyla obdržena IP adresa" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba připojení, nedostupný AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba připojení, nesprávné heslo pro AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba připojení, uplynul AP timeout" +#define D_ATTEMPTING_CONNECTION "Připojování..." +#define D_CHECKING_CONNECTION "Zkouška spojení..." +#define D_QUERY_DONE "Vyslání dotazu. Nalezena služba MQTT" +#define D_MQTT_SERVICE_FOUND "Služba MQTT byla nalezena" +#define D_FOUND_AT "znalezeno v" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebyl nalezen" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Uloženo do paměti flash v" +#define D_LOADED_FROM_FLASH_AT "Staženo z paměti flash z" +#define D_USE_DEFAULTS "Použij defaultní hodnoty" +#define D_ERASED_SECTOR "Smazaný sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ
prosím zaktualizujte" +#define D_WEBSERVER_ACTIVE_ON "Aktivní Web server" +#define D_WITH_IP_ADDRESS "na IP adrese" +#define D_WEBSERVER_STOPPED "Web server zastaven" +#define D_FILE_NOT_FOUND "Soubor nebyl nalezen" +#define D_REDIRECTED "Přesměrování na vlastní portál" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manager nastaví AP a zachová STA" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manager nastaví Access Point" +#define D_TRYING_TO_CONNECT "Zkouším připojit zařízení k síti" + +#define D_RESTART_IN "Restart" +#define D_SECONDS "sekund" +#define D_DEVICE_WILL_RESTART "Zařízení bude zrestartováno během několika sekund" +#define D_BUTTON_TOGGLE "Přepínač" +#define D_CONFIGURATION "Nastavení" +#define D_INFORMATION "Informace" +#define D_FIRMWARE_UPGRADE "Aktualizace firmware" +#define D_CONSOLE "Konzole" +#define D_CONFIRM_RESTART "Potvrzení restartu" + +#define D_CONFIGURE_MODULE "Nastavení modulu" +#define D_CONFIGURE_WIFI "Nastavení WiFi" +#define D_CONFIGURE_MQTT "Nastavení MQTT" +#define D_CONFIGURE_DOMOTICZ "Nastavení Domoticz" +#define D_CONFIGURE_LOGGING "Nastavení logování" +#define D_CONFIGURE_OTHER "Jiná nastavení" +#define D_CONFIRM_RESET_CONFIGURATION "Potvrzení resetu nastavení" +#define D_RESET_CONFIGURATION "Reset nastavení" +#define D_BACKUP_CONFIGURATION "Záloha nastavení" +#define D_RESTORE_CONFIGURATION "Obnovení nastavení" +#define D_MAIN_MENU "Hlavní menu" + +#define D_MODULE_PARAMETERS "Nastavení modulu" +#define D_MODULE_TYPE "Typ modulu" +#define D_PULLUP_ENABLE "Tlačítko/Spínač bez pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Nastavení WiFi" +#define D_SCAN_FOR_WIFI_NETWORKS "Scan sítí WiFi" +#define D_SCAN_DONE "Scan dokončen" +#define D_NO_NETWORKS_FOUND "Síť nebyla nalezena" +#define D_REFRESH_TO_SCAN_AGAIN "Zopakovat scan" +#define D_DUPLICATE_ACCESSPOINT "Kopie AP" +#define D_SKIPPING_LOW_QUALITY "Přeskočení z důvodu kvality signálu" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "Heslo AP1" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "Heslo AP2" + +#define D_MQTT_PARAMETERS "Nastavení MQTT" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Celý topic" + +#define D_LOGGING_PARAMETERS "Volba logování" +#define D_SERIAL_LOG_LEVEL "Seriová úroveň logu" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Webová úroveň logu" +#define D_SYS_LOG_LEVEL "Systemová úroveň logu" +#define D_MORE_DEBUG "Více debug informací" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Interval telemetrie" + +#define D_OTHER_PARAMETERS "Další nastavení" +#define D_TEMPLATE "Šablona" +#define D_ACTIVATE "Aktivovat" +#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" +#define D_MQTT_ENABLE "MQTT aktivní" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "Nastavení šablony" +#define D_TEMPLATE_PARAMETERS "Parametry šablony" +#define D_TEMPLATE_NAME "Název" +#define D_BASE_TYPE "Vzor z" +#define D_TEMPLATE_FLAGS "Volby" + +#define D_SAVE_CONFIGURATION "Ulož nastavení" +#define D_CONFIGURATION_SAVED "Nastavení uloženo" +#define D_CONFIGURATION_RESET "Nastavení resetováno" + +#define D_PROGRAM_VERSION "Verze programu" +#define D_BUILD_DATE_AND_TIME "Datum a čas kompilace" +#define D_CORE_AND_SDK_VERSION "Verze Core/SDK" +#define D_FLASH_WRITE_COUNT "Počet zápisů do paměti" +#define D_MAC_ADDRESS "Adresa MAC" +#define D_MQTT_HOST "Host MQTT" +#define D_MQTT_PORT "Port MQTT" +#define D_MQTT_CLIENT "Klient MQTT" +#define D_MQTT_USER "Uživatel MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT" +#define D_MQTT_FULL_TOPIC "Celý topic MQTT" +#define D_MDNS_DISCOVERY "Získávání mDNS" +#define D_MDNS_ADVERTISE "Rozesílání mDNS" +#define D_ESP_CHIP_ID "ID systému ESP" +#define D_FLASH_CHIP_ID "ID systému paměti flash" +#define D_FLASH_CHIP_SIZE "Velikost flash" +#define D_FREE_PROGRAM_SPACE "Volné místo pro program" + +#define D_UPGRADE_BY_WEBSERVER "Aktualizace z Web serveru" +#define D_OTA_URL "URL OTA" +#define D_START_UPGRADE "Start aktualizace" +#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizace nahráním souboru" +#define D_UPLOAD_STARTED "Nahrávání zahájeno" +#define D_UPGRADE_STARTED "Zahájení aktualizace" +#define D_UPLOAD_DONE "Nahrávání ukončeno" +#define D_UPLOAD_ERR_1 "Soubor nebyl vybrán" +#define D_UPLOAD_ERR_2 "Málo místa" +#define D_UPLOAD_ERR_3 "Magický byte má hodnotu jinou než 0xE9" +#define D_UPLOAD_ERR_4 "Velikost programu je větší než skutečná velikost paměti flash" +#define D_UPLOAD_ERR_5 "Chyba nahrávání, nesouhlasí porovnávané bity" +#define D_UPLOAD_ERR_6 "Chyba nahrávání. Spuštěn zápis do logu na úrovni 3" +#define D_UPLOAD_ERR_7 "Nahrávání přerušeno" +#define D_UPLOAD_ERR_8 "Špatný soubor" +#define D_UPLOAD_ERR_9 "Soubor je příliš velký" +#define D_UPLOAD_ERR_10 "Chyba inicializace RF chipu" +#define D_UPLOAD_ERR_11 "Chyba smazání RF chipu" +#define D_UPLOAD_ERR_12 "Chyba při zápisu do RF chipu" +#define D_UPLOAD_ERR_13 "Chyba dekódování RF firmwaru" +#define D_UPLOAD_ERROR_CODE "Chyba nahrávání" + +#define D_ENTER_COMMAND "Vlož příkaz" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni úroveň 2 zápisu Weblog, pokud je očekávána odpověď" +#define D_NEED_USER_AND_PASSWORD "Vyžadován uživatel=&heslo=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifikuj otisk TLS..." +#define D_TLS_CONNECT_FAILED_TO "Nepřipojeno TLS do" +#define D_RETRY_IN "Zopakuji za" +#define D_VERIFIED "Ověřeno otisk " +#define D_INSECURE "Nesprávné připojení z důvodu chybného otisku TLS" +#define D_CONNECT_FAILED_TO "Spojení se nepodařilo navázat" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast je vypnutý" +#define D_MULTICAST_REJOINED "Multicast opět připojený" +#define D_MULTICAST_JOIN_FAILED "Multicast neúspěšný" +#define D_FAILED_TO_SEND_RESPONSE "Nepodařilo se odeslat odpověď" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo základní událost" +#define D_WEMO_EVENT_SERVICE "WeMo servisní událost" +#define D_WEMO_META_SERVICE "WeMo meta událost" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Odpověď odeslána" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API není implementováno" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovědi odeslány" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Nastavení Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Spinac idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak" + #define D_DOMOTICZ_POWER_ENERGY "Příkon,Energie" + #define D_DOMOTICZ_ILLUMINANCE "Osvětlení" + #define D_DOMOTICZ_COUNT "Počítadlo/PM1" + #define D_DOMOTICZ_VOLTAGE "Napětí/PM2,5" + #define D_DOMOTICZ_CURRENT "Proud/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Aktualizace stopek" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Nastavení Časovače" +#define D_TIMER_PARAMETERS "Časovač" +#define D_TIMER_ENABLE "Povol časovače" +#define D_TIMER_ARM "Aktivní" +#define D_TIMER_TIME "Čas" +#define D_TIMER_DAYS "Dny" +#define D_TIMER_REPEAT "Opakovat" +#define D_TIMER_OUTPUT "Výstup" +#define D_TIMER_ACTION "Napájení" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Nastavení KNX" +#define D_KNX_PARAMETERS "KNX parametry" +#define D_KNX_GENERAL_CONFIG "Obecné" +#define D_KNX_PHYSICAL_ADDRESS "Fyzická adresa" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musí být jedinečná v síti KNX )" +#define D_KNX_ENABLE "Povol KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data k odeslání na skupinové adresy" +#define D_ADD "Přidej" +#define D_DELETE "Smaž" +#define D_REPLY "Odpověď" +#define D_KNX_GROUP_ADDRESS_TO_READ "Skupinové adresy pro příjem dat z" +#define D_RECEIVED_FROM "Přijato z" +#define D_KNX_COMMAND_WRITE "Zapiš" +#define D_KNX_COMMAND_READ "Čti" +#define D_KNX_COMMAND_OTHER "Jiné" +#define D_SENT_TO "pošli" +#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervována a nemůže být použita." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Spotřeba Dnes" +#define D_ENERGY_YESTERDAY "Spotřeba Včera" +#define D_ENERGY_TOTAL "Celková spotřeba" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor DS18x20 obsazen" +#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" +#define D_SENSORS_FOUND "Nalezen sensor DS18x20" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Čekání na" +#define D_START_SIGNAL_LOW "nízký startovní signál" +#define D_START_SIGNAL_HIGH "vysoký startovní signál" +#define D_PULSE "impuls" +#define D_CHECKSUM_FAILURE "Chybný kontrolní součet" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor neobdržel příkaz ACK" +#define D_SHT1X_FOUND "SHT1X nalezen" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "částic" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. osa-X" +#define D_AY_AXIS "Accel. osa-Y" +#define D_AZ_AXIS "Accel. osa-Z" +#define D_GX_AXIS "Gyro osa-X" +#define D_GY_AXIS "Gyro osa-Y" +#define D_GZ_AXIS "Gyro osa-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Odstraňte zátěž" +#define D_HX_CAL_REFERENCE "Vložte referenční zátěž" +#define D_HX_CAL_DONE "Zkalibrováno" +#define D_HX_CAL_FAIL "Chyba kalibrace" +#define D_RESET_HX711 "Reset váhy" +#define D_CONFIGURE_HX711 "Konfigurace váhy" +#define D_HX711_PARAMETERS "Parametry váhy" +#define D_ITEM_WEIGHT "Vlastní hmotnost" +#define D_REFERENCE_WEIGHT "Referenční hmotnost" +#define D_CALIBRATE "Kalibruj" +#define D_CALIBRATION "Kalibrace" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Směr větru" +#define D_TX20_WIND_SPEED "Rychlost větru" +#define D_TX20_WIND_SPEED_AVG "Průměrná rychlost větru" +#define D_TX20_WIND_SPEED_MAX "Maximální rychlost větru" +#define D_TX20_NORTH "S" +#define D_TX20_EAST "V" +#define D_TX20_SOUTH "J" +#define D_TX20_WEST "Z" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Není" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Spínač" // Suffix "1" +#define D_SENSOR_BUTTON "Tlačítko" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1", +#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "hod" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sektory" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_CS_CZ_H_ diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index d4e434e0c..6569dd232 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -1,703 +1,701 @@ -/* - de-DE.h - localization for German - Germany for Tasmota - - Copyright (C) 2019 VinceMasuka - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_DE_DE_H_ -#define _LANGUAGE_DE_DE_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.6.0.21 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1031 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "de" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "." -#define D_MONTH_DAY_SEPARATOR "." -#define D_DATE_TIME_SEPARATOR " " -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "So Mo Di Mi Do Fr Sa " -#define D_MONTH3LIST "JanFebMärAprMaiJunJulAugSepOktNovDez" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Luftqualität" -#define D_AP "AP" // Access Point -#define D_AS "als" -#define D_AUTO "AUTO" -#define D_BLINK "Blinken" -#define D_BLINKOFF "BlinkenAus" -#define D_BOOT_COUNT "Anzahl Startvorgänge" -#define D_BRIGHTLIGHT "hell" -#define D_BSSID "BSSId" -#define D_BUTTON "Knopf" -#define D_BY "von" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Kanal" -#define D_CO2 "CO²" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "kalt" -#define D_COMMAND "Befehl" -#define D_CONNECTED "verbunden" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "zählen" -#define D_COUNTER "Zähler" -#define D_CURRENT "Strom" // As in Voltage and Current -#define D_DATA "Daten" -#define D_DARKLIGHT "dunkel" -#define D_DEBUG "debug" -#define D_DISABLED "deaktiviert" -#define D_DISTANCE "Abstand" -#define D_DNS_SERVER "DNS-Server" -#define D_DONE "erledigt" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulation" -#define D_ENABLED "aktiviert" -#define D_ERASE "löschen" -#define D_ERROR "Fehler" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "fehlgeschlagen" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback-Topic" -#define D_FALSE "falsch" -#define D_FILE "Datei" -#define D_FLOW_RATE "Durchflussmenge" -#define D_FREE_MEMORY "Freier Arbeitsspeicher" -#define D_FREQUENCY "Frequenz" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Gruppe" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" -#define D_HUMIDITY "Feuchtigkeit" -#define D_ILLUMINANCE "Beleuchtungsintensität" -#define D_IMMEDIATE "direkt" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infrarot" -#define D_INITIALIZED "initialisiert" -#define D_IP_ADDRESS "IP-Adresse" -#define D_LIGHT "Licht" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "Mehrfachdruck" -#define D_NOISE "Lautstärke" -#define D_NONE "keine" -#define D_OFF "aus" -#define D_OFFLINE "Offline" -#define D_OK "OK" -#define D_ON "an" -#define D_ONLINE "Online" -#define D_PASSWORD "Passwort" -#define D_PORT "Port" -#define D_POWER_FACTOR "Leistungsfaktor" -#define D_POWERUSAGE "Leistung" -#define D_POWERUSAGE_ACTIVE "Wirkleistung" -#define D_POWERUSAGE_APPARENT "Scheinleistung" -#define D_POWERUSAGE_REACTIVE "Blindleistung" -#define D_PRESSURE "Luftdruck" -#define D_PRESSUREATSEALEVEL "Luftdruck auf Meereshöhe" -#define D_PROGRAM_FLASH_SIZE "Ges. Flash Speicher" -#define D_PROGRAM_SIZE "Ben. Flash Speicher" -#define D_PROJECT "Projekt" -#define D_RAIN "Regen" -#define D_RECEIVED "erhalten" -#define D_RESTART "Neustart" -#define D_RESTARTING "starte neu" -#define D_RESTART_REASON "Grund für Neustart" -#define D_RESTORE "Wiederherstellung" -#define D_RETAINED "beibehalten" -#define D_RULE "Regel" -#define D_SAVE "Speichern" -#define D_SENSOR "Sensor" -#define D_SSID "SSID" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Subnetzmaske" -#define D_SUBSCRIBE_TO "abonniere" -#define D_UNSUBSCRIBE_FROM "löse abo. von" -#define D_SUCCESSFUL "erfolgreich" -#define D_SUNRISE "Sonnenaufgang" -#define D_SUNSET "Sonnenuntergang" -#define D_TEMPERATURE "Temperatur" -#define D_TO "zu" -#define D_TOGGLE "An/Aus" -#define D_TOPIC "topic" -#define D_TOTAL_USAGE "Gesamtverbrauch" -#define D_TRANSMIT "Übertragen" -#define D_TRUE "wahr" -#define D_TVOC "TVOC" -#define D_UPGRADE "update" -#define D_UPLOAD "Upload" -#define D_UPTIME "Laufzeit" -#define D_USER "Benutzer" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV-Index" -#define D_UV_INDEX_1 "Niedrig" -#define D_UV_INDEX_2 "Mittel" -#define D_UV_INDEX_3 "Hoch" -#define D_UV_INDEX_4 "Intensiv" -#define D_UV_INDEX_5 "Gefährlich" -#define D_UV_INDEX_6 "Schädlich" -#define D_UV_INDEX_7 "Messwert!" -#define D_UV_LEVEL "UV-Level" -#define D_UV_POWER "UV Intensität" -#define D_VERSION "Version" -#define D_VOLTAGE "Spannung" -#define D_WEIGHT "Gewicht" -#define D_WARMLIGHT "warm" -#define D_WEB_SERVER "Web-Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ACHTUNG: Diese Version unterstützt keine persistenten Einstellungen" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serielles Logging deaktiviert" -#define D_SYSLOG_LOGGING_REENABLED "Syslog-Logging aktiviert" - -#define D_SET_BAUDRATE_TO "Setze Baudrate auf" -#define D_RECEIVED_TOPIC "empfangenes topic" -#define D_DATA_SIZE "Datengröße" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Schleife blockiert." -#define D_WPS_FAILED_WITH_STATUS "WPS fehlgeschlagen mit Status" -#define D_ACTIVE_FOR_3_MINUTES "aktiv für 3 Minuten" -#define D_FAILED_TO_START "Starten fehlgeschlagen" -#define D_PATCH_ISSUE_2186 "Repariere Problem #2186" -#define D_CONNECTING_TO_AP "verbinden mit AP" -#define D_IN_MODE "in Modus" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbindung fehlgeschlagen, da keine IP-Adresse zugeteilt wurde" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbindung fehlgeschlagen, da AP nicht erreicht werden konnte" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbindung fehlgeschlagen, da das Passwort falsch ist" -#define D_CONNECT_FAILED_AP_TIMEOUT "Verbindung fehlgeschlagen, da der AP nicht antwortet (timeout)" -#define D_ATTEMPTING_CONNECTION "Verbindungsversuch..." -#define D_CHECKING_CONNECTION "Prüfe Verbindung..." -#define D_QUERY_DONE "Suchanfrage abgeschlossen. MQTT-Services gefunden" -#define D_MQTT_SERVICE_FOUND "MQTT-Service gefunden bei" -#define D_FOUND_AT "gefunden bei" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog-Host nicht gefunden" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "in Flash gespeichert am" -#define D_LOADED_FROM_FLASH_AT "aus Flash geladen am" -#define D_USE_DEFAULTS "Standard verwenden" -#define D_ERASED_SECTOR "gelöschter Sektor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware
bitte upgraden" -#define D_WEBSERVER_ACTIVE_ON "Web-Server aktiv bei" -#define D_WITH_IP_ADDRESS "mit IP-Adresse" -#define D_WEBSERVER_STOPPED "Web-Server angehalten" -#define D_FILE_NOT_FOUND "Datei nicht gefunden" -#define D_REDIRECTED "umgeleitet zu captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WLAN-Manager AccessPoint gesetzt und behält Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "WLAN-Manager AccessPoint gesetzt" -#define D_TRYING_TO_CONNECT "Versuche Gerät mit Netzwerk zu verbinden" - -#define D_RESTART_IN "Neustart in" -#define D_SECONDS "Sekunden" -#define D_DEVICE_WILL_RESTART "Gerät wird jetzt neu gestartet" -#define D_BUTTON_TOGGLE "An/Aus" -#define D_CONFIGURATION "Einstellungen" -#define D_INFORMATION "Informationen" -#define D_FIRMWARE_UPGRADE "Firmware Update" -#define D_CONSOLE "Konsole" -#define D_CONFIRM_RESTART "Wirklich neustarten?" - -#define D_CONFIGURE_MODULE "Gerät konfigurieren" -#define D_CONFIGURE_WIFI "WLAN konfigurieren" -#define D_CONFIGURE_MQTT "MQTT konfigurieren" -#define D_CONFIGURE_DOMOTICZ "Domoticz konfigurieren" -#define D_CONFIGURE_LOGGING "Logging konfigurieren" -#define D_CONFIGURE_OTHER "Sonstige Konfiguration" -#define D_CONFIRM_RESET_CONFIGURATION "Zurücksetzen der Konfiguration bestätigen" -#define D_RESET_CONFIGURATION "Konfiguration zurücksetzen" -#define D_BACKUP_CONFIGURATION "Konfiguration sichern" -#define D_RESTORE_CONFIGURATION "Konfiguration wiederherstellen" -#define D_MAIN_MENU "Hauptmenü" - -#define D_MODULE_PARAMETERS "Geräte-Einstellungen" -#define D_MODULE_TYPE "Gerätetyp" -#define D_PULLUP_ENABLE "Kein Taster/Schalter Pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "serieller Eingang [serial in]" -#define D_SERIAL_OUT "serieller Ausgang [serial out]" - -#define D_WIFI_PARAMETERS "WLAN-Einstellungen" -#define D_SCAN_FOR_WIFI_NETWORKS "WLAN-Netzwerk suchen und auswählen" -#define D_SCAN_DONE "Suche abgeschlossen" -#define D_NO_NETWORKS_FOUND "Keine Netzwerke gefunden" -#define D_REFRESH_TO_SCAN_AGAIN "Aktualisieren, um erneut zu suchen" -#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplizieren" -#define D_SKIPPING_LOW_QUALITY "überspringe wegen niedriger Qualität" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA-PSK" -#define D_WPA2_PSK "WPA2-PSK" -#define D_AP1_SSID "WLAN 1 - SSID" -#define D_AP1_PASSWORD "WLAN 1 - Passwort" -#define D_AP2_SSID "WLAN 2 - SSID" -#define D_AP2_PASSWORD "WLAN 2 - Passwort" - -#define D_MQTT_PARAMETERS "MQTT-Einstellungen" -#define D_CLIENT "client" -#define D_FULL_TOPIC "full topic" - -#define D_LOGGING_PARAMETERS "Logging-Einstellungen" -#define D_SERIAL_LOG_LEVEL "Seriell-Log Level" -#define D_MQTT_LOG_LEVEL "Mqtt-Log Level" -#define D_WEB_LOG_LEVEL "Web-Log Level" -#define D_SYS_LOG_LEVEL "Sys-Log Level" -#define D_MORE_DEBUG "Mehr Details" -#define D_SYSLOG_HOST "Sys-Log Host" -#define D_SYSLOG_PORT "Sys-Log Port" -#define D_TELEMETRY_PERIOD "Telemetrieperiode" - -#define D_OTHER_PARAMETERS "Sonstige Einstellungen" -#define D_TEMPLATE "Vorlage" -#define D_ACTIVATE "Aktivieren" -#define D_WEB_ADMIN_PASSWORD "Passwort für Web Oberfläche" -#define D_MQTT_ENABLE "MQTT aktivieren" -#define D_FRIENDLY_NAME "Name [friendly name]" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "Einzelnes Gerät" -#define D_MULTI_DEVICE "Mehrfachgerät" - -#define D_CONFIGURE_TEMPLATE "Vorlage konfigurieren" -#define D_TEMPLATE_PARAMETERS "Vorlage Parameter" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "basiert auf" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Konfiguration speichern" -#define D_CONFIGURATION_SAVED "Konfiguration gespeichert" -#define D_CONFIGURATION_RESET "Konfiguration zurücksetzen" - -#define D_PROGRAM_VERSION "Tasmota Version" -#define D_BUILD_DATE_AND_TIME "Build-Datum & -Uhrzeit" -#define D_CORE_AND_SDK_VERSION "Core-/SDK-Version" -#define D_FLASH_WRITE_COUNT "Anz. Flash Schreibzugriffe" -#define D_MAC_ADDRESS "MAC-Adresse" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Port" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT Benutzer" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS-Ermittlung" -#define D_MDNS_ADVERTISE "mDNS-Bekanntmachung" -#define D_ESP_CHIP_ID "ESP Chip ID" -#define D_FLASH_CHIP_ID "Flash Chip ID" -#define D_FLASH_CHIP_SIZE "Realer Flash Speicher" -#define D_FREE_PROGRAM_SPACE "Verf. Flash Speicher" - -#define D_UPGRADE_BY_WEBSERVER "Update über Web-Server" -#define D_OTA_URL "OTA-URL" -#define D_START_UPGRADE "Update starten" -#define D_UPGRADE_BY_FILE_UPLOAD "Update Datei hochladen" -#define D_UPLOAD_STARTED "Upload gestartet" -#define D_UPGRADE_STARTED "Update gestartet" -#define D_UPLOAD_DONE "Upload abgeschlossen" -#define D_UPLOAD_ERR_1 "Keine Datei ausgewählt" -#define D_UPLOAD_ERR_2 "Ungenügend Speicherplatz" -#define D_UPLOAD_ERR_3 "Magic Byte ist nicht 0xE9" -#define D_UPLOAD_ERR_4 "Datei überschreitet vorhdn. Flashspeicher" -#define D_UPLOAD_ERR_5 "Upload Buffer Vergleich weicht ab" -#define D_UPLOAD_ERR_6 "Upload fehlgeschlagen. Aktiviere logging 3" -#define D_UPLOAD_ERR_7 "Upload abgebrochen" -#define D_UPLOAD_ERR_8 "Datei ungültig" -#define D_UPLOAD_ERR_9 "Datei zu groß" -#define D_UPLOAD_ERR_10 "RF Chip init fehlgeschlagen" -#define D_UPLOAD_ERR_11 "RF Chip löschen fehlgeschlagen" -#define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen" -#define D_UPLOAD_ERR_13 "RF Firmware ungültig" -#define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" - -#define D_ENTER_COMMAND "Befehl eingeben" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivere Web Log Level 2 falls Reaktion erwartet" -#define D_NEED_USER_AND_PASSWORD "Benötige user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "TLS-Fingerabdruck wird verifiziert..." -#define D_TLS_CONNECT_FAILED_TO "TLS-Verbindung fehlgeschlagen an" -#define D_RETRY_IN "Wiederversuch in" -#define D_VERIFIED "verifiziert mit Fingerabdruck" -#define D_INSECURE "unsichere Verbindung aufgrund ungültigen Fingerabdrucks" -#define D_CONNECT_FAILED_TO "Verbindung fehlgeschlagen aufgrund von" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast deaktiviert" -#define D_MULTICAST_REJOINED "Multicast (wieder-)verbunden" -#define D_MULTICAST_JOIN_FAILED "Multicast Verbindung fehlgeschlagen" -#define D_FAILED_TO_SEND_RESPONSE "Antwort senden fehlgeschlagen" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo-Setup" -#define D_RESPONSE_SENT "Antwort gesendet" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue-Setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue-API nicht implementiert" -#define D_HUE_API "Hue-API" -#define D_HUE_POST_ARGS "Hue POST-Argumente" -#define D_3_RESPONSE_PACKETS_SENT "3 Antwortpakete gesendet" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz-Parameter" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update Zeitplan" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Zeitplan konfigurieren" -#define D_TIMER_PARAMETERS "Zeitplan-Einstellungen" -#define D_TIMER_ENABLE "Zeitpläne aktivieren" -#define D_TIMER_ARM "Aktiv" -#define D_TIMER_TIME "Uhrzeit" -#define D_TIMER_DAYS "Wochentage" -#define D_TIMER_REPEAT "Wiederholen" -#define D_TIMER_OUTPUT "Ausgang" -#define D_TIMER_ACTION "Aktion" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX konfigurieren" -#define D_KNX_PARAMETERS "KNX-Parameter" -#define D_KNX_GENERAL_CONFIG "Allgemein" -#define D_KNX_PHYSICAL_ADDRESS "Physikalische Adresse" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Muss einmalig im KNX-Netzwerk sein )" -#define D_KNX_ENABLE "KNX aktivieren" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Daten zum Senden an Gruppenadresse" -#define D_ADD "Hinzufügen" -#define D_DELETE "Löschen" -#define D_REPLY "Antworten" -#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppenadresse zum Emfang von Daten" -#define D_RECEIVED_FROM "Empfangen von" -#define D_KNX_COMMAND_WRITE "Schreiben" -#define D_KNX_COMMAND_READ "Lesen" -#define D_KNX_COMMAND_OTHER "Andere" -#define D_SENT_TO "gesendet an" -#define D_KNX_WARNING "Die Gruppenadresse (0/0/0) ist reserviert und kann nicht verwendet werden." -#define D_KNX_ENHANCEMENT "Erweiterte Kommunikation" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energie heute" -#define D_ENERGY_YESTERDAY "Energie gestern" -#define D_ENERGY_TOTAL "Energie insgesamt" - -// xdrv_27_shutter.ino -#define D_OPEN "Öffnen" -#define D_CLOSE "Schliessen" -#define D_DOMOTICZ_SHUTTER "Rollo" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Konfiguriere PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 Parameter" -#define D_INVERT_PORTS "Invertiere Ports" -#define D_DEVICE "Gerät" -#define D_DEVICE_INPUT "Eingang" -#define D_DEVICE_OUTPUT "Ausgang" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor beschäftigt" -#define D_SENSOR_CRC_ERROR "Sensor CRC-Fehler" -#define D_SENSORS_FOUND "Sensor gefunden" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout während Warten auf" -#define D_START_SIGNAL_LOW "Startausschlag niedrig" -#define D_START_SIGNAL_HIGH "Startausschlag hoch" -#define D_PULSE "Puls" -#define D_CHECKSUM_FAILURE "Checksum-Fehler" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor hat ACK-Befehl nicht ausgeführt" -#define D_SHT1X_FOUND "SHT1X gefunden" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partikel" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Beschl. X-Achse" -#define D_AY_AXIS "Beschl. Y-Achse" -#define D_AZ_AXIS "Beschl. Z-Achse" -#define D_GX_AXIS "Gyroskop X-Achse" -#define D_GY_AXIS "Gyroskop Y-Achse" -#define D_GZ_AXIS "Gyroskop Z-Achse" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Wägegut entfernen" -#define D_HX_CAL_REFERENCE "Referenzgewicht auflegen" -#define D_HX_CAL_DONE "kalibriert" -#define D_HX_CAL_FAIL "Kalibrierung fehlgeschlagen" -#define D_RESET_HX711 "Tara" -#define D_CONFIGURE_HX711 "Tara Wert?" -#define D_HX711_PARAMETERS "Skala Parameter" -#define D_ITEM_WEIGHT "Wägegut Gewicht" -#define D_REFERENCE_WEIGHT "Referenz Gewicht" -#define D_CALIBRATE "kalibriert" -#define D_CALIBRATION "Kalibrierung" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Richtung" -#define D_TX20_WIND_SPEED "Windgeschwindigkeit" -#define D_TX20_WIND_SPEED_AVG "Ø Windgeschwindigkeit" -#define D_TX20_WIND_SPEED_MAX "max Windgeschwindigkeit" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "O" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" -#define D_UNIT_KILOOHM "kΩ" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "Sektoren" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phasenwinkel" -#define D_IMPORT_ACTIVE "Importiere Wirk" -#define D_EXPORT_ACTIVE "Exportiere Wirk" -#define D_IMPORT_REACTIVE "Importiere Blind" -#define D_EXPORT_REACTIVE "Exportiere Blind" -#define D_TOTAL_REACTIVE "Total Blind" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Grad" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Spannung" -#define D_PV1_CURRENT "PV1 Strom" -#define D_PV1_POWER "PV1 Leistung" -#define D_PV2_VOLTAGE "PV2 Spannung" -#define D_PV2_CURRENT "PV2 Strom" -#define D_PV2_POWER "PV2 Leistung" -#define D_SOLAR_POWER "solare Leistung" -#define D_INVERTER_POWER "Inverter Leistung" -#define D_STATUS "Status" -#define D_WAITING "warten" -#define D_CHECKING "prüfen" -#define D_WORKING "arbeitet" -#define D_FAILURE "Fehler" -#define D_SOLAX_ERROR_0 "Kein Fehler Code" -#define D_SOLAX_ERROR_1 "Fehler im Solarstromnetz" -#define D_SOLAX_ERROR_2 "Spannungsfehler im Solarstromnetz" -#define D_SOLAX_ERROR_3 "Frequenzfehler im Solarstromnetz" -#define D_SOLAX_ERROR_4 "Pv Spannungsfehler" -#define D_SOLAX_ERROR_5 "Isolationsfehler" -#define D_SOLAX_ERROR_6 "Übertemperatur" -#define D_SOLAX_ERROR_7 "Lüfterfehler" -#define D_SOLAX_ERROR_8 "sonstiger Fehler" - -#endif // _LANGUAGE_DE_DE_H_ +/* + de-DE.h - localization for German - Germany for Tasmota + + Copyright (C) 2019 VinceMasuka + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_DE_DE_H_ +#define _LANGUAGE_DE_DE_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.6.0.21 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1031 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "de" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "." +#define D_MONTH_DAY_SEPARATOR "." +#define D_DATE_TIME_SEPARATOR " " +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "So Mo Di Mi Do Fr Sa " +#define D_MONTH3LIST "JanFebMärAprMaiJunJulAugSepOktNovDez" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Luftqualität" +#define D_AP "AP" // Access Point +#define D_AS "als" +#define D_AUTO "AUTO" +#define D_BLINK "Blinken" +#define D_BLINKOFF "BlinkenAus" +#define D_BOOT_COUNT "Anzahl Startvorgänge" +#define D_BRIGHTLIGHT "hell" +#define D_BSSID "BSSId" +#define D_BUTTON "Knopf" +#define D_BY "von" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanal" +#define D_CO2 "CO²" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "kalt" +#define D_COMMAND "Befehl" +#define D_CONNECTED "verbunden" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "zählen" +#define D_COUNTER "Zähler" +#define D_CURRENT "Strom" // As in Voltage and Current +#define D_DATA "Daten" +#define D_DARKLIGHT "dunkel" +#define D_DEBUG "debug" +#define D_DISABLED "deaktiviert" +#define D_DISTANCE "Abstand" +#define D_DNS_SERVER "DNS-Server" +#define D_DONE "erledigt" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulation" +#define D_ENABLED "aktiviert" +#define D_ERASE "löschen" +#define D_ERROR "Fehler" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "fehlgeschlagen" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback-Topic" +#define D_FALSE "falsch" +#define D_FILE "Datei" +#define D_FLOW_RATE "Durchflussmenge" +#define D_FREE_MEMORY "Freier Arbeitsspeicher" +#define D_FREQUENCY "Frequenz" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Gruppe" +#define D_HOST "Host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Feuchtigkeit" +#define D_ILLUMINANCE "Beleuchtungsintensität" +#define D_IMMEDIATE "direkt" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infrarot" +#define D_INITIALIZED "initialisiert" +#define D_IP_ADDRESS "IP-Adresse" +#define D_LIGHT "Licht" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "Mehrfachdruck" +#define D_NOISE "Lautstärke" +#define D_NONE "keine" +#define D_OFF "aus" +#define D_OFFLINE "Offline" +#define D_OK "OK" +#define D_ON "an" +#define D_ONLINE "Online" +#define D_PASSWORD "Passwort" +#define D_PORT "Port" +#define D_POWER_FACTOR "Leistungsfaktor" +#define D_POWERUSAGE "Leistung" +#define D_POWERUSAGE_ACTIVE "Wirkleistung" +#define D_POWERUSAGE_APPARENT "Scheinleistung" +#define D_POWERUSAGE_REACTIVE "Blindleistung" +#define D_PRESSURE "Luftdruck" +#define D_PRESSUREATSEALEVEL "Luftdruck auf Meereshöhe" +#define D_PROGRAM_FLASH_SIZE "Ges. Flash Speicher" +#define D_PROGRAM_SIZE "Ben. Flash Speicher" +#define D_PROJECT "Projekt" +#define D_RAIN "Regen" +#define D_RECEIVED "erhalten" +#define D_RESTART "Neustart" +#define D_RESTARTING "starte neu" +#define D_RESTART_REASON "Grund für Neustart" +#define D_RESTORE "Wiederherstellung" +#define D_RETAINED "beibehalten" +#define D_RULE "Regel" +#define D_SAVE "Speichern" +#define D_SENSOR "Sensor" +#define D_SSID "SSID" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Subnetzmaske" +#define D_SUBSCRIBE_TO "abonniere" +#define D_UNSUBSCRIBE_FROM "löse abo. von" +#define D_SUCCESSFUL "erfolgreich" +#define D_SUNRISE "Sonnenaufgang" +#define D_SUNSET "Sonnenuntergang" +#define D_TEMPERATURE "Temperatur" +#define D_TO "zu" +#define D_TOGGLE "An/Aus" +#define D_TOPIC "topic" +#define D_TOTAL_USAGE "Gesamtverbrauch" +#define D_TRANSMIT "Übertragen" +#define D_TRUE "wahr" +#define D_TVOC "TVOC" +#define D_UPGRADE "update" +#define D_UPLOAD "Upload" +#define D_UPTIME "Laufzeit" +#define D_USER "Benutzer" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV-Index" +#define D_UV_INDEX_1 "Niedrig" +#define D_UV_INDEX_2 "Mittel" +#define D_UV_INDEX_3 "Hoch" +#define D_UV_INDEX_4 "Intensiv" +#define D_UV_INDEX_5 "Gefährlich" +#define D_UV_INDEX_6 "Schädlich" +#define D_UV_INDEX_7 "Messwert!" +#define D_UV_LEVEL "UV-Level" +#define D_UV_POWER "UV Intensität" +#define D_VERSION "Version" +#define D_VOLTAGE "Spannung" +#define D_WEIGHT "Gewicht" +#define D_WARMLIGHT "warm" +#define D_WEB_SERVER "Web-Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ACHTUNG: Diese Version unterstützt keine persistenten Einstellungen" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serielles Logging deaktiviert" +#define D_SYSLOG_LOGGING_REENABLED "Syslog-Logging aktiviert" + +#define D_SET_BAUDRATE_TO "Setze Baudrate auf" +#define D_RECEIVED_TOPIC "empfangenes topic" +#define D_DATA_SIZE "Datengröße" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Schleife blockiert." +#define D_WPS_FAILED_WITH_STATUS "WPS fehlgeschlagen mit Status" +#define D_ACTIVE_FOR_3_MINUTES "aktiv für 3 Minuten" +#define D_FAILED_TO_START "Starten fehlgeschlagen" +#define D_PATCH_ISSUE_2186 "Repariere Problem #2186" +#define D_CONNECTING_TO_AP "verbinden mit AP" +#define D_IN_MODE "in Modus" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbindung fehlgeschlagen, da keine IP-Adresse zugeteilt wurde" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbindung fehlgeschlagen, da AP nicht erreicht werden konnte" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbindung fehlgeschlagen, da das Passwort falsch ist" +#define D_CONNECT_FAILED_AP_TIMEOUT "Verbindung fehlgeschlagen, da der AP nicht antwortet (timeout)" +#define D_ATTEMPTING_CONNECTION "Verbindungsversuch..." +#define D_CHECKING_CONNECTION "Prüfe Verbindung..." +#define D_QUERY_DONE "Suchanfrage abgeschlossen. MQTT-Services gefunden" +#define D_MQTT_SERVICE_FOUND "MQTT-Service gefunden bei" +#define D_FOUND_AT "gefunden bei" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog-Host nicht gefunden" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "in Flash gespeichert am" +#define D_LOADED_FROM_FLASH_AT "aus Flash geladen am" +#define D_USE_DEFAULTS "Standard verwenden" +#define D_ERASED_SECTOR "gelöschter Sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware
bitte upgraden" +#define D_WEBSERVER_ACTIVE_ON "Web-Server aktiv bei" +#define D_WITH_IP_ADDRESS "mit IP-Adresse" +#define D_WEBSERVER_STOPPED "Web-Server angehalten" +#define D_FILE_NOT_FOUND "Datei nicht gefunden" +#define D_REDIRECTED "umgeleitet zu captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WLAN-Manager AccessPoint gesetzt und behält Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "WLAN-Manager AccessPoint gesetzt" +#define D_TRYING_TO_CONNECT "Versuche Gerät mit Netzwerk zu verbinden" + +#define D_RESTART_IN "Neustart in" +#define D_SECONDS "Sekunden" +#define D_DEVICE_WILL_RESTART "Gerät wird jetzt neu gestartet" +#define D_BUTTON_TOGGLE "An/Aus" +#define D_CONFIGURATION "Einstellungen" +#define D_INFORMATION "Informationen" +#define D_FIRMWARE_UPGRADE "Firmware Update" +#define D_CONSOLE "Konsole" +#define D_CONFIRM_RESTART "Wirklich neustarten?" + +#define D_CONFIGURE_MODULE "Gerät konfigurieren" +#define D_CONFIGURE_WIFI "WLAN konfigurieren" +#define D_CONFIGURE_MQTT "MQTT konfigurieren" +#define D_CONFIGURE_DOMOTICZ "Domoticz konfigurieren" +#define D_CONFIGURE_LOGGING "Logging konfigurieren" +#define D_CONFIGURE_OTHER "Sonstige Konfiguration" +#define D_CONFIRM_RESET_CONFIGURATION "Zurücksetzen der Konfiguration bestätigen" +#define D_RESET_CONFIGURATION "Konfiguration zurücksetzen" +#define D_BACKUP_CONFIGURATION "Konfiguration sichern" +#define D_RESTORE_CONFIGURATION "Konfiguration wiederherstellen" +#define D_MAIN_MENU "Hauptmenü" + +#define D_MODULE_PARAMETERS "Geräte-Einstellungen" +#define D_MODULE_TYPE "Gerätetyp" +#define D_PULLUP_ENABLE "Kein Taster/Schalter Pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "serieller Eingang [serial in]" +#define D_SERIAL_OUT "serieller Ausgang [serial out]" + +#define D_WIFI_PARAMETERS "WLAN-Einstellungen" +#define D_SCAN_FOR_WIFI_NETWORKS "WLAN-Netzwerk suchen und auswählen" +#define D_SCAN_DONE "Suche abgeschlossen" +#define D_NO_NETWORKS_FOUND "Keine Netzwerke gefunden" +#define D_REFRESH_TO_SCAN_AGAIN "Aktualisieren, um erneut zu suchen" +#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplizieren" +#define D_SKIPPING_LOW_QUALITY "überspringe wegen niedriger Qualität" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA-PSK" +#define D_WPA2_PSK "WPA2-PSK" +#define D_AP1_SSID "WLAN 1 - SSID" +#define D_AP1_PASSWORD "WLAN 1 - Passwort" +#define D_AP2_SSID "WLAN 2 - SSID" +#define D_AP2_PASSWORD "WLAN 2 - Passwort" + +#define D_MQTT_PARAMETERS "MQTT-Einstellungen" +#define D_CLIENT "client" +#define D_FULL_TOPIC "full topic" + +#define D_LOGGING_PARAMETERS "Logging-Einstellungen" +#define D_SERIAL_LOG_LEVEL "Seriell-Log Level" +#define D_MQTT_LOG_LEVEL "Mqtt-Log Level" +#define D_WEB_LOG_LEVEL "Web-Log Level" +#define D_SYS_LOG_LEVEL "Sys-Log Level" +#define D_MORE_DEBUG "Mehr Details" +#define D_SYSLOG_HOST "Sys-Log Host" +#define D_SYSLOG_PORT "Sys-Log Port" +#define D_TELEMETRY_PERIOD "Telemetrieperiode" + +#define D_OTHER_PARAMETERS "Sonstige Einstellungen" +#define D_TEMPLATE "Vorlage" +#define D_ACTIVATE "Aktivieren" +#define D_WEB_ADMIN_PASSWORD "Passwort für Web Oberfläche" +#define D_MQTT_ENABLE "MQTT aktivieren" +#define D_FRIENDLY_NAME "Name [friendly name]" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "Einzelnes Gerät" +#define D_MULTI_DEVICE "Mehrfachgerät" + +#define D_CONFIGURE_TEMPLATE "Vorlage konfigurieren" +#define D_TEMPLATE_PARAMETERS "Vorlage Parameter" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "basiert auf" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Konfiguration speichern" +#define D_CONFIGURATION_SAVED "Konfiguration gespeichert" +#define D_CONFIGURATION_RESET "Konfiguration zurücksetzen" + +#define D_PROGRAM_VERSION "Tasmota Version" +#define D_BUILD_DATE_AND_TIME "Build-Datum & -Uhrzeit" +#define D_CORE_AND_SDK_VERSION "Core-/SDK-Version" +#define D_FLASH_WRITE_COUNT "Anz. Flash Schreibzugriffe" +#define D_MAC_ADDRESS "MAC-Adresse" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Port" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT Benutzer" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS-Ermittlung" +#define D_MDNS_ADVERTISE "mDNS-Bekanntmachung" +#define D_ESP_CHIP_ID "ESP Chip ID" +#define D_FLASH_CHIP_ID "Flash Chip ID" +#define D_FLASH_CHIP_SIZE "Realer Flash Speicher" +#define D_FREE_PROGRAM_SPACE "Verf. Flash Speicher" + +#define D_UPGRADE_BY_WEBSERVER "Update über Web-Server" +#define D_OTA_URL "OTA-URL" +#define D_START_UPGRADE "Update starten" +#define D_UPGRADE_BY_FILE_UPLOAD "Update Datei hochladen" +#define D_UPLOAD_STARTED "Upload gestartet" +#define D_UPGRADE_STARTED "Update gestartet" +#define D_UPLOAD_DONE "Upload abgeschlossen" +#define D_UPLOAD_ERR_1 "Keine Datei ausgewählt" +#define D_UPLOAD_ERR_2 "Ungenügend Speicherplatz" +#define D_UPLOAD_ERR_3 "Magic Byte ist nicht 0xE9" +#define D_UPLOAD_ERR_4 "Datei überschreitet vorhdn. Flashspeicher" +#define D_UPLOAD_ERR_5 "Upload Buffer Vergleich weicht ab" +#define D_UPLOAD_ERR_6 "Upload fehlgeschlagen. Aktiviere logging 3" +#define D_UPLOAD_ERR_7 "Upload abgebrochen" +#define D_UPLOAD_ERR_8 "Datei ungültig" +#define D_UPLOAD_ERR_9 "Datei zu groß" +#define D_UPLOAD_ERR_10 "RF Chip init fehlgeschlagen" +#define D_UPLOAD_ERR_11 "RF Chip löschen fehlgeschlagen" +#define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen" +#define D_UPLOAD_ERR_13 "RF Firmware ungültig" +#define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" + +#define D_ENTER_COMMAND "Befehl eingeben" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivere Web Log Level 2 falls Reaktion erwartet" +#define D_NEED_USER_AND_PASSWORD "Benötige user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "TLS-Fingerabdruck wird verifiziert..." +#define D_TLS_CONNECT_FAILED_TO "TLS-Verbindung fehlgeschlagen an" +#define D_RETRY_IN "Wiederversuch in" +#define D_VERIFIED "verifiziert mit Fingerabdruck" +#define D_INSECURE "unsichere Verbindung aufgrund ungültigen Fingerabdrucks" +#define D_CONNECT_FAILED_TO "Verbindung fehlgeschlagen aufgrund von" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast deaktiviert" +#define D_MULTICAST_REJOINED "Multicast (wieder-)verbunden" +#define D_MULTICAST_JOIN_FAILED "Multicast Verbindung fehlgeschlagen" +#define D_FAILED_TO_SEND_RESPONSE "Antwort senden fehlgeschlagen" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo-Setup" +#define D_RESPONSE_SENT "Antwort gesendet" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue-Setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue-API nicht implementiert" +#define D_HUE_API "Hue-API" +#define D_HUE_POST_ARGS "Hue POST-Argumente" +#define D_3_RESPONSE_PACKETS_SENT "3 Antwortpakete gesendet" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz-Parameter" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Update Zeitplan" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Zeitplan konfigurieren" +#define D_TIMER_PARAMETERS "Zeitplan-Einstellungen" +#define D_TIMER_ENABLE "Zeitpläne aktivieren" +#define D_TIMER_ARM "Aktiv" +#define D_TIMER_TIME "Uhrzeit" +#define D_TIMER_DAYS "Wochentage" +#define D_TIMER_REPEAT "Wiederholen" +#define D_TIMER_OUTPUT "Ausgang" +#define D_TIMER_ACTION "Aktion" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX konfigurieren" +#define D_KNX_PARAMETERS "KNX-Parameter" +#define D_KNX_GENERAL_CONFIG "Allgemein" +#define D_KNX_PHYSICAL_ADDRESS "Physikalische Adresse" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Muss einmalig im KNX-Netzwerk sein )" +#define D_KNX_ENABLE "KNX aktivieren" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Daten zum Senden an Gruppenadresse" +#define D_ADD "Hinzufügen" +#define D_DELETE "Löschen" +#define D_REPLY "Antworten" +#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppenadresse zum Emfang von Daten" +#define D_RECEIVED_FROM "Empfangen von" +#define D_KNX_COMMAND_WRITE "Schreiben" +#define D_KNX_COMMAND_READ "Lesen" +#define D_KNX_COMMAND_OTHER "Andere" +#define D_SENT_TO "gesendet an" +#define D_KNX_WARNING "Die Gruppenadresse (0/0/0) ist reserviert und kann nicht verwendet werden." +#define D_KNX_ENHANCEMENT "Erweiterte Kommunikation" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energie heute" +#define D_ENERGY_YESTERDAY "Energie gestern" +#define D_ENERGY_TOTAL "Energie insgesamt" + +// xdrv_27_shutter.ino +#define D_OPEN "Öffnen" +#define D_CLOSE "Schliessen" +#define D_DOMOTICZ_SHUTTER "Rollo" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Konfiguriere PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 Parameter" +#define D_INVERT_PORTS "Invertiere Ports" +#define D_DEVICE "Gerät" +#define D_DEVICE_INPUT "Eingang" +#define D_DEVICE_OUTPUT "Ausgang" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor beschäftigt" +#define D_SENSOR_CRC_ERROR "Sensor CRC-Fehler" +#define D_SENSORS_FOUND "Sensor gefunden" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout während Warten auf" +#define D_START_SIGNAL_LOW "Startausschlag niedrig" +#define D_START_SIGNAL_HIGH "Startausschlag hoch" +#define D_PULSE "Puls" +#define D_CHECKSUM_FAILURE "Checksum-Fehler" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor hat ACK-Befehl nicht ausgeführt" +#define D_SHT1X_FOUND "SHT1X gefunden" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partikel" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Beschl. X-Achse" +#define D_AY_AXIS "Beschl. Y-Achse" +#define D_AZ_AXIS "Beschl. Z-Achse" +#define D_GX_AXIS "Gyroskop X-Achse" +#define D_GY_AXIS "Gyroskop Y-Achse" +#define D_GZ_AXIS "Gyroskop Z-Achse" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Wägegut entfernen" +#define D_HX_CAL_REFERENCE "Referenzgewicht auflegen" +#define D_HX_CAL_DONE "kalibriert" +#define D_HX_CAL_FAIL "Kalibrierung fehlgeschlagen" +#define D_RESET_HX711 "Tara" +#define D_CONFIGURE_HX711 "Tara Wert?" +#define D_HX711_PARAMETERS "Skala Parameter" +#define D_ITEM_WEIGHT "Wägegut Gewicht" +#define D_REFERENCE_WEIGHT "Referenz Gewicht" +#define D_CALIBRATE "kalibriert" +#define D_CALIBRATION "Kalibrierung" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Richtung" +#define D_TX20_WIND_SPEED "Windgeschwindigkeit" +#define D_TX20_WIND_SPEED_AVG "Ø Windgeschwindigkeit" +#define D_TX20_WIND_SPEED_MAX "max Windgeschwindigkeit" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "O" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "Sektoren" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phasenwinkel" +#define D_IMPORT_ACTIVE "Importiere Wirk" +#define D_EXPORT_ACTIVE "Exportiere Wirk" +#define D_IMPORT_REACTIVE "Importiere Blind" +#define D_EXPORT_REACTIVE "Exportiere Blind" +#define D_TOTAL_REACTIVE "Total Blind" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Grad" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Spannung" +#define D_PV1_CURRENT "PV1 Strom" +#define D_PV1_POWER "PV1 Leistung" +#define D_PV2_VOLTAGE "PV2 Spannung" +#define D_PV2_CURRENT "PV2 Strom" +#define D_PV2_POWER "PV2 Leistung" +#define D_SOLAR_POWER "solare Leistung" +#define D_INVERTER_POWER "Inverter Leistung" +#define D_STATUS "Status" +#define D_WAITING "warten" +#define D_CHECKING "prüfen" +#define D_WORKING "arbeitet" +#define D_FAILURE "Fehler" +#define D_SOLAX_ERROR_0 "Kein Fehler Code" +#define D_SOLAX_ERROR_1 "Fehler im Solarstromnetz" +#define D_SOLAX_ERROR_2 "Spannungsfehler im Solarstromnetz" +#define D_SOLAX_ERROR_3 "Frequenzfehler im Solarstromnetz" +#define D_SOLAX_ERROR_4 "Pv Spannungsfehler" +#define D_SOLAX_ERROR_5 "Isolationsfehler" +#define D_SOLAX_ERROR_6 "Übertemperatur" +#define D_SOLAX_ERROR_7 "Lüfterfehler" +#define D_SOLAX_ERROR_8 "sonstiger Fehler" + +#endif // _LANGUAGE_DE_DE_H_ diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index 2ae0bef38..f8b9c9614 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -1,703 +1,701 @@ -/* - el-GR.h - localization for Greek - Greece for Tasmota - - Copyright (C) 2019 Theo Arends, translated by Nick Galfas - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_EL_GR_H_ -#define _LANGUAGE_EL_GR_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.5.0 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1032 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "el" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "ΚυρΔευΤριΤετΠεμΠαρΣαβ" -#define D_MONTH3LIST "ΙανΦεβΜαρΑπρΜαϊΙονΙολΑυγΣεπΟκτΝοεΔεκ" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Διαχειριστής" -#define D_AIR_QUALITY "Ποιότητα αέρα" -#define D_AP "AP" // Access Point -#define D_AS "ως" -#define D_AUTO "ΑΥΤΟΜΑΤΟ" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Καταμέτρηση εκκινήσεων" -#define D_BRIGHTLIGHT "Φωτεινό" -#define D_BSSID "BSSId" -#define D_BUTTON "Πλήκτρο" -#define D_BY "από" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Κελσίου" -#define D_CHANNEL "Κανάλι" -#define D_CO2 "Διοξείδιο του άνθρακα" -#define D_CODE "κώδικας" // Button code -#define D_COLDLIGHT "Ψυχρό" -#define D_COMMAND "Εντολή" -#define D_CONNECTED "Συνδεδεμένο" -#define D_COUNT "Μέτρηση" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNTER "Μετρητής" -#define D_CURRENT "Ένταση" // As in Voltage and Current -#define D_DATA "Δεδομένα" -#define D_DARKLIGHT "Σκοτεινό" -#define D_DEBUG "Debug" -#define D_DISABLED "Ανενεργό" -#define D_DISTANCE "Απόσταση" -#define D_DNS_SERVER "Διακομιστής DNS" -#define D_DONE "Ολοκληρώθηκε" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Εξομoίωση" -#define D_ENABLED "Ενεργό" -#define D_ERASE "Διαγραφή" -#define D_ERROR "Σφάλμα" -#define D_FAHRENHEIT "Φαρενάιτ" -#define D_FAILED "Απέτυχε" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "Ψευδές" -#define D_FILE "Αρχείο" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Ελεύθερη μνήμη" -#define D_FREQUENCY "Συχνότητα" -#define D_GAS "Αέριο" -#define D_GATEWAY "Πύλη" -#define D_GROUP "Ομάδα" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" -#define D_HUMIDITY "Υγρασία" -#define D_ILLUMINANCE "Φωτεινότητα" -#define D_IMMEDIATE "άμεσο" // Button immediate -#define D_INDEX "Κατάλογος" -#define D_INFO "Πληροφορίες" -#define D_INFRARED "Υπέρυθρο" -#define D_INITIALIZED "Αρχικοποιήθηκε" -#define D_IP_ADDRESS "Διεύθυνση IP" -#define D_LIGHT "Φως" -#define D_LWT "LWT" -#define D_MODULE "Μονάδα" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "ανίχνευση για πολλαπλά πατήματα" -#define D_NOISE "Θόρυβος" -#define D_NONE "Κανένα" -#define D_OFF "Off" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "On" -#define D_ONLINE "Online" -#define D_PASSWORD "Κωδικός" -#define D_PORT "Θύρα" -#define D_POWER_FACTOR "Συντελεστής Ισχύος" -#define D_POWERUSAGE "Ισχύς" -#define D_POWERUSAGE_ACTIVE "Ενεργός ισχύς" -#define D_POWERUSAGE_APPARENT "Φαινόμενη ισχύς" -#define D_POWERUSAGE_REACTIVE "Άεργη ισχύς" -#define D_PRESSURE "Πίεση" -#define D_PRESSUREATSEALEVEL "Πίεση στo επίπεδο θάλασσας" -#define D_PROGRAM_FLASH_SIZE "Μέγεθος προγράμματος στη Flash" -#define D_PROGRAM_SIZE "Μέγεθος προγράμματος" -#define D_PROJECT "Έργο" -#define D_RAIN "Rain" -#define D_RECEIVED "Ελήφθη" -#define D_RESTART "Επανεκκίνηση" -#define D_RESTARTING "Επανεκκινεί" -#define D_RESTART_REASON "Αιτία επανεκκίνησης" -#define D_RESTORE "επαναφορά" -#define D_RETAINED "διακράτηση" -#define D_RULE "Κανόνας" -#define D_SAVE "Αποθήκευση" -#define D_SENSOR "Αισθητήρας" -#define D_SSID "SSId" -#define D_START "Εκκίνηση" -#define D_STD_TIME "STD" -#define D_STOP "Τερματισμός" -#define D_SUBNET_MASK "Μάσκα υποδικτύου" -#define D_SUBSCRIBE_TO "Εγγραφή στο" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Επιτυχές" -#define D_SUNRISE "Σούρουπο" -#define D_SUNSET "Ηλιοβασίλεμα" -#define D_TEMPERATURE "Θερμοκρασία" -#define D_TO "έως" -#define D_TOGGLE "Εναλλαγή" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Μετάδοση" -#define D_TRUE "Αληθές" -#define D_TVOC "TVOC" -#define D_UPGRADE "αναβάθμιση" -#define D_UPLOAD "Ανέβασμα" -#define D_UPTIME "Χρόνος λειτουργίας" -#define D_USER "Χρήστης" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Δείκτης UV" -#define D_UV_INDEX_1 "Χαμηλό" -#define D_UV_INDEX_2 "Μέτριο" -#define D_UV_INDEX_3 "Υψηλό" -#define D_UV_INDEX_4 "Κίνδυνος" -#define D_UV_INDEX_5 "Έγκαυμα L1/2" -#define D_UV_INDEX_6 "Έγκαυμα L3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Επίπεδο UV" -#define D_UV_POWER "Ένταση UV" -#define D_VERSION "Έκδοση" -#define D_VOLTAGE "Τάση" -#define D_WEIGHT "Βάρος" -#define D_WARMLIGHT "Θερμό" -#define D_WEB_SERVER "Διακομιστής Web" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ΠΡΟΕΙΔΟΠΟΙΗΣΗ Αυτή η έκδοση δεν αποθηκεύει τις ρυθμίσεις" -#define D_LEVEL_10 "επίπεδο 1-0" -#define D_LEVEL_01 "επίπεδο 0-1" -#define D_SERIAL_LOGGING_DISABLED "Η καταγραφή σειριακής θύρας είναι απενεργοποιημένη" -#define D_SYSLOG_LOGGING_REENABLED "Η καταγραφή Syslog επαναενεργοποιήθηκε" - -#define D_SET_BAUDRATE_TO "Ορισμός Baudrate σε" -#define D_RECEIVED_TOPIC "Received Topic" -#define D_DATA_SIZE "Μέγεθος δεδομένων" -#define D_ANALOG_INPUT "Αναλογικό" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "Το WPSconfig ΑΠΕΤΥΧΕ με status" -#define D_ACTIVE_FOR_3_MINUTES "ενεργό για 3 λεπτά" -#define D_FAILED_TO_START "απέτυχε να εκκινήσει" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Συνδέεται στο AP" -#define D_IN_MODE "σε mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Αποτυχία σύνδεσης, δεν απονεμήθηκε διεύθυνση IP" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Αποτυχία σύνδεσης, δεν ανταποκρίνεται το AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Αποτυχία σύνδεσης, λάθος κωδικός για το AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Αποτυχία σύνδεσης, λήξη ορίου απόκρισης από το AP" -#define D_ATTEMPTING_CONNECTION "Προσπάθεια για σύνδεση..." -#define D_CHECKING_CONNECTION "Έλεγχος σύνδεσης..." -#define D_QUERY_DONE "Ολοκλήρωση ερωτήματος. Βρέθηκε υπηρεσία MQTT" -#define D_MQTT_SERVICE_FOUND "Βρέθηκε υπηρεσία MQTT στο" -#define D_FOUND_AT "βρέθηκε στο" -#define D_SYSLOG_HOST_NOT_FOUND "Δε βρέθηκε Syslog Host" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Αποθηκεύτηκε από τη Flash στο" -#define D_LOADED_FROM_FLASH_AT "Φορτώθηκε από τη Flash στο" -#define D_USE_DEFAULTS "Χρήση προεπιλογών" -#define D_ERASED_SECTOR "Διαγραφή τομέα" - -// webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" -#define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" -#define D_WITH_IP_ADDRESS "με διεύθυνση IP" -#define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" -#define D_FILE_NOT_FOUND "Δε βρέθηκε το αρχείο" -#define D_REDIRECTED "Ανακατεύθυνση στο captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" -#define D_TRYING_TO_CONNECT "Προσπάθεια σύνδεσης της συσκευής σε ασύρματο δίκτυο" - -#define D_RESTART_IN "Επανεκκίνηση σε" -#define D_SECONDS "δευτερόλεπτα" -#define D_DEVICE_WILL_RESTART "Η συσκευή θα επανεκκινήσει σε λίγα δευτερόλεπτα" -#define D_BUTTON_TOGGLE "Εναλλαγή" -#define D_CONFIGURATION "Ρυθμίσεις" -#define D_INFORMATION "Πληροφορίες" -#define D_FIRMWARE_UPGRADE "Αναβάθμιση" -#define D_CONSOLE "Κονσόλα" -#define D_CONFIRM_RESTART "Επιβεβαίωση επανεκκίνησης" - -#define D_CONFIGURE_MODULE "Μονάδα" -#define D_CONFIGURE_WIFI "WiFi" -#define D_CONFIGURE_MQTT "MQTT" -#define D_CONFIGURE_DOMOTICZ "Domoticz" -#define D_CONFIGURE_LOGGING "Καταγραφή" -#define D_CONFIGURE_OTHER "Άλλες ρυθμίσεις" -#define D_CONFIRM_RESET_CONFIGURATION "Επιβεβαίωση αρχικοποίησης στις προεπιλεγμένες ρυθμίσεις" -#define D_RESET_CONFIGURATION "Reset" -#define D_BACKUP_CONFIGURATION "Εξαγωγή" -#define D_RESTORE_CONFIGURATION "Επαναφορά" -#define D_MAIN_MENU "Κεντρικό μενού" - -#define D_MODULE_PARAMETERS "Παράμετροι μονάδας" -#define D_MODULE_TYPE "Τύπος μονάδας" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Παράμετροι Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Σάρωση για δίκτυα Wifi" -#define D_SCAN_DONE "Η σάρωση ολοκληρώθηκε" -#define D_NO_NETWORKS_FOUND "Δε βρέθηκαν δίκτυα" -#define D_REFRESH_TO_SCAN_AGAIN "Πατήστε ανανέωση για μια νέα σάρωση" -#define D_DUPLICATE_ACCESSPOINT "Διπλότυπο AccessPoint" -#define D_SKIPPING_LOW_QUALITY "Παράκαμψη λόγω χαμηλής ποιότητας" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Κωδικός" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Κωδικός" - -#define D_MQTT_PARAMETERS "Παράμετροι MQTT" -#define D_CLIENT "Πελάτης" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "Παράμετροι καταγραφής" -#define D_SERIAL_LOG_LEVEL "Επίπεδο Σειριακής" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Επίπεδο Web" -#define D_SYS_LOG_LEVEL "Επίπεδο Syslog" -#define D_MORE_DEBUG "More debug" -#define D_SYSLOG_HOST "Εξυπηρετητής Syslog" -#define D_SYSLOG_PORT "Θύρα Syslog" -#define D_TELEMETRY_PERIOD "Περίοδος τηλεμετρίας" - -#define D_OTHER_PARAMETERS "Άλλες παράμετροι" -#define D_TEMPLATE "Πρότυπο" -#define D_ACTIVATE "Ενεργοποίηση" -#define D_WEB_ADMIN_PASSWORD "Κωδικός διαχειριστή" -#define D_MQTT_ENABLE "Ενεργοποίηση MQTT" -#define D_FRIENDLY_NAME "Φιλική ονομασία" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "μονή συσκευή" -#define D_MULTI_DEVICE "πολλαπλές συσκευές" - -#define D_CONFIGURE_TEMPLATE "Πρότυπα" -#define D_TEMPLATE_PARAMETERS "Παράμετροι Πρότυπου" -#define D_TEMPLATE_NAME "Όνομα" -#define D_BASE_TYPE "Βασίζεται στο" -#define D_TEMPLATE_FLAGS "Επιλογές" - -#define D_SAVE_CONFIGURATION "Αποθήκευση ρυθμίσεων" -#define D_CONFIGURATION_SAVED "Οι ρυθμίσεις αποθηκεύτηκαν" -#define D_CONFIGURATION_RESET "Επαναφορά ρυθμίσεων" - -#define D_PROGRAM_VERSION "Έκδοση προγράμματος" -#define D_BUILD_DATE_AND_TIME "Ημερομηνία έκδοσης" -#define D_CORE_AND_SDK_VERSION "Έκδοση Core/SDK" -#define D_FLASH_WRITE_COUNT "Καταμέτρηση εγγραφών στη Flash" -#define D_MAC_ADDRESS "MAC Address" -#define D_MQTT_HOST "MQTT Διακομιστής" -#define D_MQTT_PORT "MQTT Θύρα" -#define D_MQTT_CLIENT "MQTT Πελάτης" -#define D_MQTT_USER "MQTT Χρήστης" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Μέγεθος Flash" -#define D_FREE_PROGRAM_SPACE "Ελεύθερος χώρος προγράμματος" - -#define D_UPGRADE_BY_WEBSERVER "Αναβάθμιση μέσω web server" -#define D_OTA_URL "OTA URL" -#define D_START_UPGRADE "Εκκίνηση αναβάθμισης" -#define D_UPGRADE_BY_FILE_UPLOAD "Αναβάθμιση με μεταφόρτωση αρχείου" -#define D_UPLOAD_STARTED "Η μεταφόρτωση ξεκίνησε" -#define D_UPGRADE_STARTED "Η αναβάθμιση ξεκίνησε" -#define D_UPLOAD_DONE "Η μεταφόρτωση ολοκληρώθηκε" -#define D_UPLOAD_ERR_1 "Δεν έχει επιλεγεί αρχείο" -#define D_UPLOAD_ERR_2 "Δεν υπάρχει επαρκής χώρος" -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" -#define D_UPLOAD_ERR_4 "Το μέγεθος προγράμματος είναι μεγαλύτερο από την πραγματική μνήμη Flash" -#define D_UPLOAD_ERR_5 "Upload buffer miscompare" -#define D_UPLOAD_ERR_6 "Η μεταφόρτωση απέτυχε. Επιλέξτε επίπεδο καταγραφής 3" -#define D_UPLOAD_ERR_7 "Η μεταφόρτωση ματαιώθηκε" -#define D_UPLOAD_ERR_8 "Μη έγκυρο αρχείο" -#define D_UPLOAD_ERR_9 "Πολύ μεγάλο αρχείο" -#define D_UPLOAD_ERR_10 "Αποτυχία αρχικοποίησης RF chip" -#define D_UPLOAD_ERR_11 "Αποτυχία σβησίματος στο RF chip" -#define D_UPLOAD_ERR_12 "Αποτυχία εγγραφής στο RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Κωδικός λάθους στη μεταφόρτωση" - -#define D_ENTER_COMMAND "Εισαγωγή εντολής" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Ενεργοποιήστε το weblog 2 εαν περιμένετε απόκριση" -#define D_NEED_USER_AND_PASSWORD "Χρειάζεται user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Επιβεβαίωση αποτυπώματος TLS..." -#define D_TLS_CONNECT_FAILED_TO "Αποτυχία σύνδεσης TLS στο" -#define D_RETRY_IN "Νέα προσπάθεια σε" -#define D_VERIFIED "Επιβεβαιώθηκε με χρήση αποτυπώματος TLS" -#define D_INSECURE "Επισφαλής σύνδεση λόγω άκυρου αποτυπώματος TLS" -#define D_CONNECT_FAILED_TO "Αποτυχία σύνδεσης στο" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Απενεργοποιημένο Multicast" -#define D_MULTICAST_REJOINED "Επανασύνδεση Multicast" -#define D_MULTICAST_JOIN_FAILED "Αποτυχία σύνδεσης Multicast" -#define D_FAILED_TO_SEND_RESPONSE "Αποτυχία αποστολής απόκρισης" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo βασικό event" -#define D_WEMO_EVENT_SERVICE "WeMo υπηρεσία event" -#define D_WEMO_META_SERVICE "WeMo υπηρεσία meta" -#define D_WEMO_SETUP "WeMo ρυθμίσεις" -#define D_RESPONSE_SENT "Αποστολή απάντησης" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue ρυθμίσεις" -#define D_HUE_API_NOT_IMPLEMENTED "Δε βρέθηκε εφαρμογή Hue API" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "Στάλθηκαν 3 πακέτα απόκρισης" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Παράμετροι Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Χρονικά" -#define D_TIMER_PARAMETERS "Παράμετροι χρονικών" -#define D_TIMER_ENABLE "Ενεργοποίηση χρονικών" -#define D_TIMER_ARM "Οπλισμένο" -#define D_TIMER_TIME "Ώρα" -#define D_TIMER_DAYS "Μέρες" -#define D_TIMER_REPEAT "Επανάληψη" -#define D_TIMER_OUTPUT "Έξοδος" -#define D_TIMER_ACTION "Λειτουργία" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Ρυθμίσεις KNX" -#define D_KNX_PARAMETERS "Παράμετροι KNX" -#define D_KNX_GENERAL_CONFIG "Γενικά" -#define D_KNX_PHYSICAL_ADDRESS "Διεύθυνση Μνήμης" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Πρέπει να είναι μοναδική στο KNX δίκτυο )" -#define D_KNX_ENABLE "Ενεργοποίηση KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Αποστολή δεδομένων σε Ομάδα Διευθύνσεων" -#define D_ADD "Προσθήκη" -#define D_DELETE "Διαγραφή" -#define D_REPLY "Επανάληψη" -#define D_KNX_GROUP_ADDRESS_TO_READ "Ομάδα Διευθύνσεων που θα λάβει τα Δεδομένα" -#define D_RECEIVED_FROM "Στάλθηκε από" -#define D_KNX_COMMAND_WRITE "Εγγραφή" -#define D_KNX_COMMAND_READ "Ανάγνωση" -#define D_KNX_COMMAND_OTHER "Άλλο" -#define D_SENT_TO "αποστολή σε" -#define D_KNX_WARNING "Η Ομάδα Διευθύνσεων ( 0 / 0 / 0 ) είναι δεσμευμένη και δεν μπορεί να χρησιμοποιηθεί." -#define D_KNX_ENHANCEMENT "Βελτίωση επικοινωνίας" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Ενέργεια σήμερα" -#define D_ENERGY_YESTERDAY "Ενέργεια χθες" -#define D_ENERGY_TOTAL "Ενέργεια συνολικά" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Ο αισθητήρας είναι απασχολημένος" -#define D_SENSOR_CRC_ERROR "Σφάλμα CRC αισθητήρα" -#define D_SENSORS_FOUND "Βρέθηκαν αισθητήρες" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Αναμονή Timeout για" -#define D_START_SIGNAL_LOW "χαμηλό αρχικό σήμα" -#define D_START_SIGNAL_HIGH "υψηλό αρχικό σήμα" -#define D_PULSE "παλμός" -#define D_CHECKSUM_FAILURE "Αποτυχία Checksum" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Ο αισθητήρας δεν έστειλε εντολή ACK" -#define D_SHT1X_FOUND "Βρέθηκε SHT1X" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Απομακρύνετε το βαρίδιο" -#define D_HX_CAL_REFERENCE "Τοποθετήστε το βαρίδιο αναφοράς" -#define D_HX_CAL_DONE "Βαθμονομήθηκε" -#define D_HX_CAL_FAIL "Αποτυχία βαθμονόμησης" -#define D_RESET_HX711 "Αρχικοποίηση ζυγαριάς" -#define D_CONFIGURE_HX711 "Ρύθμιση ζυγαριάς" -#define D_HX711_PARAMETERS "Παράμετροι ζυγαριάς" -#define D_ITEM_WEIGHT "Βάρος αντικειμένου" -#define D_REFERENCE_WEIGHT "Βάρος αναφοράς" -#define D_CALIBRATE "Βαθμονόμησε" -#define D_CALIBRATION "Βαθμονόμηση" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Κατεύθυνση ανέμου" -#define D_TX20_WIND_SPEED "Ταχύτητα ανέμου" -#define D_TX20_WIND_SPEED_AVG "Μέση ταχύτητα ανέμου" -#define D_TX20_WIND_SPEED_MAX "Μέγιστη ταχύτητα ανέμου" -#define D_TX20_NORTH "Β" -#define D_TX20_EAST "Α" -#define D_TX20_SOUTH "Ν" -#define D_TX20_WEST "Δ" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Κανένα" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_EL_GR_H_ +/* + el-GR.h - localization for Greek - Greece for Tasmota + + Copyright (C) 2019 Theo Arends, translated by Nick Galfas + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_EL_GR_H_ +#define _LANGUAGE_EL_GR_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.5.0 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1032 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "el" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "ΚυρΔευΤριΤετΠεμΠαρΣαβ" +#define D_MONTH3LIST "ΙανΦεβΜαρΑπρΜαϊΙονΙολΑυγΣεπΟκτΝοεΔεκ" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Διαχειριστής" +#define D_AIR_QUALITY "Ποιότητα αέρα" +#define D_AP "AP" // Access Point +#define D_AS "ως" +#define D_AUTO "ΑΥΤΟΜΑΤΟ" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Καταμέτρηση εκκινήσεων" +#define D_BRIGHTLIGHT "Φωτεινό" +#define D_BSSID "BSSId" +#define D_BUTTON "Πλήκτρο" +#define D_BY "από" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Κελσίου" +#define D_CHANNEL "Κανάλι" +#define D_CO2 "Διοξείδιο του άνθρακα" +#define D_CODE "κώδικας" // Button code +#define D_COLDLIGHT "Ψυχρό" +#define D_COMMAND "Εντολή" +#define D_CONNECTED "Συνδεδεμένο" +#define D_COUNT "Μέτρηση" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNTER "Μετρητής" +#define D_CURRENT "Ένταση" // As in Voltage and Current +#define D_DATA "Δεδομένα" +#define D_DARKLIGHT "Σκοτεινό" +#define D_DEBUG "Debug" +#define D_DISABLED "Ανενεργό" +#define D_DISTANCE "Απόσταση" +#define D_DNS_SERVER "Διακομιστής DNS" +#define D_DONE "Ολοκληρώθηκε" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Εξομoίωση" +#define D_ENABLED "Ενεργό" +#define D_ERASE "Διαγραφή" +#define D_ERROR "Σφάλμα" +#define D_FAHRENHEIT "Φαρενάιτ" +#define D_FAILED "Απέτυχε" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "Ψευδές" +#define D_FILE "Αρχείο" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Ελεύθερη μνήμη" +#define D_FREQUENCY "Συχνότητα" +#define D_GAS "Αέριο" +#define D_GATEWAY "Πύλη" +#define D_GROUP "Ομάδα" +#define D_HOST "Host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Υγρασία" +#define D_ILLUMINANCE "Φωτεινότητα" +#define D_IMMEDIATE "άμεσο" // Button immediate +#define D_INDEX "Κατάλογος" +#define D_INFO "Πληροφορίες" +#define D_INFRARED "Υπέρυθρο" +#define D_INITIALIZED "Αρχικοποιήθηκε" +#define D_IP_ADDRESS "Διεύθυνση IP" +#define D_LIGHT "Φως" +#define D_LWT "LWT" +#define D_MODULE "Μονάδα" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "ανίχνευση για πολλαπλά πατήματα" +#define D_NOISE "Θόρυβος" +#define D_NONE "Κανένα" +#define D_OFF "Off" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "On" +#define D_ONLINE "Online" +#define D_PASSWORD "Κωδικός" +#define D_PORT "Θύρα" +#define D_POWER_FACTOR "Συντελεστής Ισχύος" +#define D_POWERUSAGE "Ισχύς" +#define D_POWERUSAGE_ACTIVE "Ενεργός ισχύς" +#define D_POWERUSAGE_APPARENT "Φαινόμενη ισχύς" +#define D_POWERUSAGE_REACTIVE "Άεργη ισχύς" +#define D_PRESSURE "Πίεση" +#define D_PRESSUREATSEALEVEL "Πίεση στo επίπεδο θάλασσας" +#define D_PROGRAM_FLASH_SIZE "Μέγεθος προγράμματος στη Flash" +#define D_PROGRAM_SIZE "Μέγεθος προγράμματος" +#define D_PROJECT "Έργο" +#define D_RAIN "Rain" +#define D_RECEIVED "Ελήφθη" +#define D_RESTART "Επανεκκίνηση" +#define D_RESTARTING "Επανεκκινεί" +#define D_RESTART_REASON "Αιτία επανεκκίνησης" +#define D_RESTORE "επαναφορά" +#define D_RETAINED "διακράτηση" +#define D_RULE "Κανόνας" +#define D_SAVE "Αποθήκευση" +#define D_SENSOR "Αισθητήρας" +#define D_SSID "SSId" +#define D_START "Εκκίνηση" +#define D_STD_TIME "STD" +#define D_STOP "Τερματισμός" +#define D_SUBNET_MASK "Μάσκα υποδικτύου" +#define D_SUBSCRIBE_TO "Εγγραφή στο" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Επιτυχές" +#define D_SUNRISE "Σούρουπο" +#define D_SUNSET "Ηλιοβασίλεμα" +#define D_TEMPERATURE "Θερμοκρασία" +#define D_TO "έως" +#define D_TOGGLE "Εναλλαγή" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Μετάδοση" +#define D_TRUE "Αληθές" +#define D_TVOC "TVOC" +#define D_UPGRADE "αναβάθμιση" +#define D_UPLOAD "Ανέβασμα" +#define D_UPTIME "Χρόνος λειτουργίας" +#define D_USER "Χρήστης" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Δείκτης UV" +#define D_UV_INDEX_1 "Χαμηλό" +#define D_UV_INDEX_2 "Μέτριο" +#define D_UV_INDEX_3 "Υψηλό" +#define D_UV_INDEX_4 "Κίνδυνος" +#define D_UV_INDEX_5 "Έγκαυμα L1/2" +#define D_UV_INDEX_6 "Έγκαυμα L3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Επίπεδο UV" +#define D_UV_POWER "Ένταση UV" +#define D_VERSION "Έκδοση" +#define D_VOLTAGE "Τάση" +#define D_WEIGHT "Βάρος" +#define D_WARMLIGHT "Θερμό" +#define D_WEB_SERVER "Διακομιστής Web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ΠΡΟΕΙΔΟΠΟΙΗΣΗ Αυτή η έκδοση δεν αποθηκεύει τις ρυθμίσεις" +#define D_LEVEL_10 "επίπεδο 1-0" +#define D_LEVEL_01 "επίπεδο 0-1" +#define D_SERIAL_LOGGING_DISABLED "Η καταγραφή σειριακής θύρας είναι απενεργοποιημένη" +#define D_SYSLOG_LOGGING_REENABLED "Η καταγραφή Syslog επαναενεργοποιήθηκε" + +#define D_SET_BAUDRATE_TO "Ορισμός Baudrate σε" +#define D_RECEIVED_TOPIC "Received Topic" +#define D_DATA_SIZE "Μέγεθος δεδομένων" +#define D_ANALOG_INPUT "Αναλογικό" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "Το WPSconfig ΑΠΕΤΥΧΕ με status" +#define D_ACTIVE_FOR_3_MINUTES "ενεργό για 3 λεπτά" +#define D_FAILED_TO_START "απέτυχε να εκκινήσει" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Συνδέεται στο AP" +#define D_IN_MODE "σε mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Αποτυχία σύνδεσης, δεν απονεμήθηκε διεύθυνση IP" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Αποτυχία σύνδεσης, δεν ανταποκρίνεται το AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Αποτυχία σύνδεσης, λάθος κωδικός για το AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Αποτυχία σύνδεσης, λήξη ορίου απόκρισης από το AP" +#define D_ATTEMPTING_CONNECTION "Προσπάθεια για σύνδεση..." +#define D_CHECKING_CONNECTION "Έλεγχος σύνδεσης..." +#define D_QUERY_DONE "Ολοκλήρωση ερωτήματος. Βρέθηκε υπηρεσία MQTT" +#define D_MQTT_SERVICE_FOUND "Βρέθηκε υπηρεσία MQTT στο" +#define D_FOUND_AT "βρέθηκε στο" +#define D_SYSLOG_HOST_NOT_FOUND "Δε βρέθηκε Syslog Host" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Αποθηκεύτηκε από τη Flash στο" +#define D_LOADED_FROM_FLASH_AT "Φορτώθηκε από τη Flash στο" +#define D_USE_DEFAULTS "Χρήση προεπιλογών" +#define D_ERASED_SECTOR "Διαγραφή τομέα" + +// webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
παρακαλώ αναβαθμίστε" +#define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο" +#define D_WITH_IP_ADDRESS "με διεύθυνση IP" +#define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε" +#define D_FILE_NOT_FOUND "Δε βρέθηκε το αρχείο" +#define D_REDIRECTED "Ανακατεύθυνση στο captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" +#define D_TRYING_TO_CONNECT "Προσπάθεια σύνδεσης της συσκευής σε ασύρματο δίκτυο" + +#define D_RESTART_IN "Επανεκκίνηση σε" +#define D_SECONDS "δευτερόλεπτα" +#define D_DEVICE_WILL_RESTART "Η συσκευή θα επανεκκινήσει σε λίγα δευτερόλεπτα" +#define D_BUTTON_TOGGLE "Εναλλαγή" +#define D_CONFIGURATION "Ρυθμίσεις" +#define D_INFORMATION "Πληροφορίες" +#define D_FIRMWARE_UPGRADE "Αναβάθμιση" +#define D_CONSOLE "Κονσόλα" +#define D_CONFIRM_RESTART "Επιβεβαίωση επανεκκίνησης" + +#define D_CONFIGURE_MODULE "Μονάδα" +#define D_CONFIGURE_WIFI "WiFi" +#define D_CONFIGURE_MQTT "MQTT" +#define D_CONFIGURE_DOMOTICZ "Domoticz" +#define D_CONFIGURE_LOGGING "Καταγραφή" +#define D_CONFIGURE_OTHER "Άλλες ρυθμίσεις" +#define D_CONFIRM_RESET_CONFIGURATION "Επιβεβαίωση αρχικοποίησης στις προεπιλεγμένες ρυθμίσεις" +#define D_RESET_CONFIGURATION "Reset" +#define D_BACKUP_CONFIGURATION "Εξαγωγή" +#define D_RESTORE_CONFIGURATION "Επαναφορά" +#define D_MAIN_MENU "Κεντρικό μενού" + +#define D_MODULE_PARAMETERS "Παράμετροι μονάδας" +#define D_MODULE_TYPE "Τύπος μονάδας" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Παράμετροι Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Σάρωση για δίκτυα Wifi" +#define D_SCAN_DONE "Η σάρωση ολοκληρώθηκε" +#define D_NO_NETWORKS_FOUND "Δε βρέθηκαν δίκτυα" +#define D_REFRESH_TO_SCAN_AGAIN "Πατήστε ανανέωση για μια νέα σάρωση" +#define D_DUPLICATE_ACCESSPOINT "Διπλότυπο AccessPoint" +#define D_SKIPPING_LOW_QUALITY "Παράκαμψη λόγω χαμηλής ποιότητας" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Κωδικός" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Κωδικός" + +#define D_MQTT_PARAMETERS "Παράμετροι MQTT" +#define D_CLIENT "Πελάτης" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "Παράμετροι καταγραφής" +#define D_SERIAL_LOG_LEVEL "Επίπεδο Σειριακής" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Επίπεδο Web" +#define D_SYS_LOG_LEVEL "Επίπεδο Syslog" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "Εξυπηρετητής Syslog" +#define D_SYSLOG_PORT "Θύρα Syslog" +#define D_TELEMETRY_PERIOD "Περίοδος τηλεμετρίας" + +#define D_OTHER_PARAMETERS "Άλλες παράμετροι" +#define D_TEMPLATE "Πρότυπο" +#define D_ACTIVATE "Ενεργοποίηση" +#define D_WEB_ADMIN_PASSWORD "Κωδικός διαχειριστή" +#define D_MQTT_ENABLE "Ενεργοποίηση MQTT" +#define D_FRIENDLY_NAME "Φιλική ονομασία" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "μονή συσκευή" +#define D_MULTI_DEVICE "πολλαπλές συσκευές" + +#define D_CONFIGURE_TEMPLATE "Πρότυπα" +#define D_TEMPLATE_PARAMETERS "Παράμετροι Πρότυπου" +#define D_TEMPLATE_NAME "Όνομα" +#define D_BASE_TYPE "Βασίζεται στο" +#define D_TEMPLATE_FLAGS "Επιλογές" + +#define D_SAVE_CONFIGURATION "Αποθήκευση ρυθμίσεων" +#define D_CONFIGURATION_SAVED "Οι ρυθμίσεις αποθηκεύτηκαν" +#define D_CONFIGURATION_RESET "Επαναφορά ρυθμίσεων" + +#define D_PROGRAM_VERSION "Έκδοση προγράμματος" +#define D_BUILD_DATE_AND_TIME "Ημερομηνία έκδοσης" +#define D_CORE_AND_SDK_VERSION "Έκδοση Core/SDK" +#define D_FLASH_WRITE_COUNT "Καταμέτρηση εγγραφών στη Flash" +#define D_MAC_ADDRESS "MAC Address" +#define D_MQTT_HOST "MQTT Διακομιστής" +#define D_MQTT_PORT "MQTT Θύρα" +#define D_MQTT_CLIENT "MQTT Πελάτης" +#define D_MQTT_USER "MQTT Χρήστης" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Μέγεθος Flash" +#define D_FREE_PROGRAM_SPACE "Ελεύθερος χώρος προγράμματος" + +#define D_UPGRADE_BY_WEBSERVER "Αναβάθμιση μέσω web server" +#define D_OTA_URL "OTA URL" +#define D_START_UPGRADE "Εκκίνηση αναβάθμισης" +#define D_UPGRADE_BY_FILE_UPLOAD "Αναβάθμιση με μεταφόρτωση αρχείου" +#define D_UPLOAD_STARTED "Η μεταφόρτωση ξεκίνησε" +#define D_UPGRADE_STARTED "Η αναβάθμιση ξεκίνησε" +#define D_UPLOAD_DONE "Η μεταφόρτωση ολοκληρώθηκε" +#define D_UPLOAD_ERR_1 "Δεν έχει επιλεγεί αρχείο" +#define D_UPLOAD_ERR_2 "Δεν υπάρχει επαρκής χώρος" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "Το μέγεθος προγράμματος είναι μεγαλύτερο από την πραγματική μνήμη Flash" +#define D_UPLOAD_ERR_5 "Upload buffer miscompare" +#define D_UPLOAD_ERR_6 "Η μεταφόρτωση απέτυχε. Επιλέξτε επίπεδο καταγραφής 3" +#define D_UPLOAD_ERR_7 "Η μεταφόρτωση ματαιώθηκε" +#define D_UPLOAD_ERR_8 "Μη έγκυρο αρχείο" +#define D_UPLOAD_ERR_9 "Πολύ μεγάλο αρχείο" +#define D_UPLOAD_ERR_10 "Αποτυχία αρχικοποίησης RF chip" +#define D_UPLOAD_ERR_11 "Αποτυχία σβησίματος στο RF chip" +#define D_UPLOAD_ERR_12 "Αποτυχία εγγραφής στο RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "Κωδικός λάθους στη μεταφόρτωση" + +#define D_ENTER_COMMAND "Εισαγωγή εντολής" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Ενεργοποιήστε το weblog 2 εαν περιμένετε απόκριση" +#define D_NEED_USER_AND_PASSWORD "Χρειάζεται user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Επιβεβαίωση αποτυπώματος TLS..." +#define D_TLS_CONNECT_FAILED_TO "Αποτυχία σύνδεσης TLS στο" +#define D_RETRY_IN "Νέα προσπάθεια σε" +#define D_VERIFIED "Επιβεβαιώθηκε με χρήση αποτυπώματος TLS" +#define D_INSECURE "Επισφαλής σύνδεση λόγω άκυρου αποτυπώματος TLS" +#define D_CONNECT_FAILED_TO "Αποτυχία σύνδεσης στο" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Απενεργοποιημένο Multicast" +#define D_MULTICAST_REJOINED "Επανασύνδεση Multicast" +#define D_MULTICAST_JOIN_FAILED "Αποτυχία σύνδεσης Multicast" +#define D_FAILED_TO_SEND_RESPONSE "Αποτυχία αποστολής απόκρισης" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo βασικό event" +#define D_WEMO_EVENT_SERVICE "WeMo υπηρεσία event" +#define D_WEMO_META_SERVICE "WeMo υπηρεσία meta" +#define D_WEMO_SETUP "WeMo ρυθμίσεις" +#define D_RESPONSE_SENT "Αποστολή απάντησης" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue ρυθμίσεις" +#define D_HUE_API_NOT_IMPLEMENTED "Δε βρέθηκε εφαρμογή Hue API" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "Στάλθηκαν 3 πακέτα απόκρισης" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Παράμετροι Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Χρονικά" +#define D_TIMER_PARAMETERS "Παράμετροι χρονικών" +#define D_TIMER_ENABLE "Ενεργοποίηση χρονικών" +#define D_TIMER_ARM "Οπλισμένο" +#define D_TIMER_TIME "Ώρα" +#define D_TIMER_DAYS "Μέρες" +#define D_TIMER_REPEAT "Επανάληψη" +#define D_TIMER_OUTPUT "Έξοδος" +#define D_TIMER_ACTION "Λειτουργία" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Ρυθμίσεις KNX" +#define D_KNX_PARAMETERS "Παράμετροι KNX" +#define D_KNX_GENERAL_CONFIG "Γενικά" +#define D_KNX_PHYSICAL_ADDRESS "Διεύθυνση Μνήμης" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Πρέπει να είναι μοναδική στο KNX δίκτυο )" +#define D_KNX_ENABLE "Ενεργοποίηση KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Αποστολή δεδομένων σε Ομάδα Διευθύνσεων" +#define D_ADD "Προσθήκη" +#define D_DELETE "Διαγραφή" +#define D_REPLY "Επανάληψη" +#define D_KNX_GROUP_ADDRESS_TO_READ "Ομάδα Διευθύνσεων που θα λάβει τα Δεδομένα" +#define D_RECEIVED_FROM "Στάλθηκε από" +#define D_KNX_COMMAND_WRITE "Εγγραφή" +#define D_KNX_COMMAND_READ "Ανάγνωση" +#define D_KNX_COMMAND_OTHER "Άλλο" +#define D_SENT_TO "αποστολή σε" +#define D_KNX_WARNING "Η Ομάδα Διευθύνσεων ( 0 / 0 / 0 ) είναι δεσμευμένη και δεν μπορεί να χρησιμοποιηθεί." +#define D_KNX_ENHANCEMENT "Βελτίωση επικοινωνίας" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Ενέργεια σήμερα" +#define D_ENERGY_YESTERDAY "Ενέργεια χθες" +#define D_ENERGY_TOTAL "Ενέργεια συνολικά" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Ο αισθητήρας είναι απασχολημένος" +#define D_SENSOR_CRC_ERROR "Σφάλμα CRC αισθητήρα" +#define D_SENSORS_FOUND "Βρέθηκαν αισθητήρες" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Αναμονή Timeout για" +#define D_START_SIGNAL_LOW "χαμηλό αρχικό σήμα" +#define D_START_SIGNAL_HIGH "υψηλό αρχικό σήμα" +#define D_PULSE "παλμός" +#define D_CHECKSUM_FAILURE "Αποτυχία Checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Ο αισθητήρας δεν έστειλε εντολή ACK" +#define D_SHT1X_FOUND "Βρέθηκε SHT1X" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Απομακρύνετε το βαρίδιο" +#define D_HX_CAL_REFERENCE "Τοποθετήστε το βαρίδιο αναφοράς" +#define D_HX_CAL_DONE "Βαθμονομήθηκε" +#define D_HX_CAL_FAIL "Αποτυχία βαθμονόμησης" +#define D_RESET_HX711 "Αρχικοποίηση ζυγαριάς" +#define D_CONFIGURE_HX711 "Ρύθμιση ζυγαριάς" +#define D_HX711_PARAMETERS "Παράμετροι ζυγαριάς" +#define D_ITEM_WEIGHT "Βάρος αντικειμένου" +#define D_REFERENCE_WEIGHT "Βάρος αναφοράς" +#define D_CALIBRATE "Βαθμονόμησε" +#define D_CALIBRATION "Βαθμονόμηση" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Κατεύθυνση ανέμου" +#define D_TX20_WIND_SPEED "Ταχύτητα ανέμου" +#define D_TX20_WIND_SPEED_AVG "Μέση ταχύτητα ανέμου" +#define D_TX20_WIND_SPEED_MAX "Μέγιστη ταχύτητα ανέμου" +#define D_TX20_NORTH "Β" +#define D_TX20_EAST "Α" +#define D_TX20_SOUTH "Ν" +#define D_TX20_WEST "Δ" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Κανένα" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_EL_GR_H_ diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 42d9d6100..257a34c86 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -1,703 +1,701 @@ -/* - en-GB.h - localization for English - United Kingdom for Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_EN_GB_H_ -#define _LANGUAGE_EN_GB_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.11 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -// https://www.science.co.il/language/Locale-codes.php -#define LANGUAGE_LCID 2057 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "en" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "SunMonTueWedThuFriSat" -#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Air quality" -#define D_AP "AP" // Access Point -#define D_AS "as" -#define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Boot Count" -#define D_BRIGHTLIGHT "Bright" -#define D_BSSID "BSSId" -#define D_BUTTON "Button" -#define D_BY "by" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Channel" -#define D_CO2 "Carbon dioxide" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "Cold" -#define D_COMMAND "Command" -#define D_CONNECTED "Connected" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Count" -#define D_COUNTER "Counter" -#define D_CURRENT "Current" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Dark" -#define D_DEBUG "Debug" -#define D_DISABLED "Disabled" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Done" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulation" -#define D_ENABLED "Enabled" -#define D_ERASE "Erase" -#define D_ERROR "Error" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Failed" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "False" -#define D_FILE "File" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Free Memory" -#define D_FREQUENCY "Frequency" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Group" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" -#define D_HUMIDITY "Humidity" -#define D_ILLUMINANCE "Illuminance" -#define D_IMMEDIATE "immediate" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "Initialized" -#define D_IP_ADDRESS "IP Address" -#define D_LIGHT "Light" -#define D_LWT "LWT" -#define D_MODULE "Module" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "Noise" -#define D_NONE "None" -#define D_OFF "Off" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "On" -#define D_ONLINE "Online" -#define D_PASSWORD "Password" -#define D_PORT "Port" -#define D_POWER_FACTOR "Power Factor" -#define D_POWERUSAGE "Power" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "Pressure" -#define D_PRESSUREATSEALEVEL "SeaPressure" -#define D_PROGRAM_FLASH_SIZE "Program Flash Size" -#define D_PROGRAM_SIZE "Program Size" -#define D_PROJECT "Project" -#define D_RAIN "Rain" -#define D_RECEIVED "Received" -#define D_RESTART "Restart" -#define D_RESTARTING "Restarting" -#define D_RESTART_REASON "Restart Reason" -#define D_RESTORE "restore" -#define D_RETAINED "retained" -#define D_RULE "Rule" -#define D_SAVE "Save" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Subnet Mask" -#define D_SUBSCRIBE_TO "Subscribe to" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Successful" -#define D_SUNRISE "Sunrise" -#define D_SUNSET "Sunset" -#define D_TEMPERATURE "Temperature" -#define D_TO "to" -#define D_TOGGLE "Toggle" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Transmit" -#define D_TRUE "True" -#define D_TVOC "TVOC" -#define D_UPGRADE "upgrade" -#define D_UPLOAD "Upload" -#define D_UPTIME "Uptime" -#define D_USER "User" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" // Out of Range -#define D_UV_LEVEL "UV Level" -#define D_UV_POWER "UV Power" -#define D_VERSION "Version" -#define D_VOLTAGE "Voltage" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "Warm" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial logging disabled" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logging re-enabled" - -#define D_SET_BAUDRATE_TO "Set Baudrate to" -#define D_RECEIVED_TOPIC "Received Topic" -#define D_DATA_SIZE "Data Size" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" -#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" -#define D_FAILED_TO_START "failed to start" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Connecting to AP" -#define D_IN_MODE "in mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connect failed as no IP address received" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Connect failed as AP cannot be reached" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password" -#define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout" -#define D_ATTEMPTING_CONNECTION "Attempting connection..." -#define D_CHECKING_CONNECTION "Checking connection..." -#define D_QUERY_DONE "Query done. MQTT services found" -#define D_MQTT_SERVICE_FOUND "MQTT service found on" -#define D_FOUND_AT "found at" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Saved to flash at" -#define D_LOADED_FROM_FLASH_AT "Loaded from flash at" -#define D_USE_DEFAULTS "Use defaults" -#define D_ERASED_SECTOR "Erased sector" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
please upgrade" -#define D_WEBSERVER_ACTIVE_ON "Web server active on" -#define D_WITH_IP_ADDRESS "with IP address" -#define D_WEBSERVER_STOPPED "Web server stopped" -#define D_FILE_NOT_FOUND "File Not Found" -#define D_REDIRECTED "Redirected to captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" -#define D_TRYING_TO_CONNECT "Trying to connect device to network" - -#define D_RESTART_IN "Restart in" -#define D_SECONDS "seconds" -#define D_DEVICE_WILL_RESTART "Device will restart in a few seconds" -#define D_BUTTON_TOGGLE "Toggle" -#define D_CONFIGURATION "Configuration" -#define D_INFORMATION "Information" -#define D_FIRMWARE_UPGRADE "Firmware Upgrade" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Confirm Restart" - -#define D_CONFIGURE_MODULE "Configure Module" -#define D_CONFIGURE_WIFI "Configure WiFi" -#define D_CONFIGURE_MQTT "Configure MQTT" -#define D_CONFIGURE_DOMOTICZ "Configure Domoticz" -#define D_CONFIGURE_LOGGING "Configure Logging" -#define D_CONFIGURE_OTHER "Configure Other" -#define D_CONFIRM_RESET_CONFIGURATION "Confirm Reset Configuration" -#define D_RESET_CONFIGURATION "Reset Configuration" -#define D_BACKUP_CONFIGURATION "Backup Configuration" -#define D_RESTORE_CONFIGURATION "Restore Configuration" -#define D_MAIN_MENU "Main Menu" - -#define D_MODULE_PARAMETERS "Module parameters" -#define D_MODULE_TYPE "Module type" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Wifi parameters" -#define D_SCAN_FOR_WIFI_NETWORKS "Scan for wifi networks" -#define D_SCAN_DONE "Scan done" -#define D_NO_NETWORKS_FOUND "No networks found" -#define D_REFRESH_TO_SCAN_AGAIN "Refresh to scan again" -#define D_DUPLICATE_ACCESSPOINT "Duplicate AccessPoint" -#define D_SKIPPING_LOW_QUALITY "Skipping due to low quality" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Password" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Password" - -#define D_MQTT_PARAMETERS "MQTT parameters" -#define D_CLIENT "Client" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "Logging parameters" -#define D_SERIAL_LOG_LEVEL "Serial log level" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web log level" -#define D_SYS_LOG_LEVEL "Syslog level" -#define D_MORE_DEBUG "More debug" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Telemetry period" - -#define D_OTHER_PARAMETERS "Other parameters" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Web Admin Password" -#define D_MQTT_ENABLE "MQTT enable" -#define D_FRIENDLY_NAME "Friendly Name" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Save configuration" -#define D_CONFIGURATION_SAVED "Configuration saved" -#define D_CONFIGURATION_RESET "Configuration reset" - -#define D_PROGRAM_VERSION "Program Version" -#define D_BUILD_DATE_AND_TIME "Build Date & Time" -#define D_CORE_AND_SDK_VERSION "Core/SDK Version" -#define D_FLASH_WRITE_COUNT "Flash write Count" -#define D_MAC_ADDRESS "MAC Address" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Port" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT User" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Size" -#define D_FREE_PROGRAM_SPACE "Free Program Space" - -#define D_UPGRADE_BY_WEBSERVER "Upgrade by web server" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Start upgrade" -#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade by file upload" -#define D_UPLOAD_STARTED "Upload started" -#define D_UPGRADE_STARTED "Upgrade started" -#define D_UPLOAD_DONE "Upload done" -#define D_UPLOAD_ERR_1 "No file selected" -#define D_UPLOAD_ERR_2 "Not enough space" -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" -#define D_UPLOAD_ERR_4 "Program flash size is larger than real flash size" -#define D_UPLOAD_ERR_5 "Upload buffer miscompare" -#define D_UPLOAD_ERR_6 "Upload failed. Enable logging 3" -#define D_UPLOAD_ERR_7 "Upload aborted" -#define D_UPLOAD_ERR_8 "File invalid" -#define D_UPLOAD_ERR_9 "File too large" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Upload error code" - -#define D_ENTER_COMMAND "Enter command" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" -#define D_NEED_USER_AND_PASSWORD "Need user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verify TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" -#define D_RETRY_IN "Retry in" -#define D_VERIFIED "Verified using Fingerprint" -#define D_INSECURE "Insecure connection due to invalid Fingerprint" -#define D_CONNECT_FAILED_TO "Connect failed to" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast disabled" -#define D_MULTICAST_REJOINED "Multicast (re)joined" -#define D_MULTICAST_JOIN_FAILED "Multicast join failed" -#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Response sent" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configure Timer" -#define D_TIMER_PARAMETERS "Timer parameters" -#define D_TIMER_ENABLE "Enable Timers" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configure KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energy Today" -#define D_ENERGY_YESTERDAY "Energy Yesterday" -#define D_ENERGY_TOTAL "Energy Total" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor busy" -#define D_SENSOR_CRC_ERROR "Sensor CRC error" -#define D_SENSORS_FOUND "Sensors found" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" -#define D_START_SIGNAL_LOW "start signal low" -#define D_START_SIGNAL_HIGH "start signal high" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "Checksum failure" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" -#define D_SHT1X_FOUND "SHT1X found" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_EN_GB_H_ +/* + en-GB.h - localization for English - United Kingdom for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_EN_GB_H_ +#define _LANGUAGE_EN_GB_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.11 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 2057 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "en" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "SunMonTueWedThuFriSat" +#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Air quality" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Boot Count" +#define D_BRIGHTLIGHT "Bright" +#define D_BSSID "BSSId" +#define D_BUTTON "Button" +#define D_BY "by" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Channel" +#define D_CO2 "Carbon dioxide" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "Cold" +#define D_COMMAND "Command" +#define D_CONNECTED "Connected" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Count" +#define D_COUNTER "Counter" +#define D_CURRENT "Current" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Dark" +#define D_DEBUG "Debug" +#define D_DISABLED "Disabled" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "DNS Server" +#define D_DONE "Done" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulation" +#define D_ENABLED "Enabled" +#define D_ERASE "Erase" +#define D_ERROR "Error" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Failed" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "False" +#define D_FILE "File" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Free Memory" +#define D_FREQUENCY "Frequency" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Group" +#define D_HOST "Host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Humidity" +#define D_ILLUMINANCE "Illuminance" +#define D_IMMEDIATE "immediate" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infrared" +#define D_INITIALIZED "Initialized" +#define D_IP_ADDRESS "IP Address" +#define D_LIGHT "Light" +#define D_LWT "LWT" +#define D_MODULE "Module" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "Noise" +#define D_NONE "None" +#define D_OFF "Off" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "On" +#define D_ONLINE "Online" +#define D_PASSWORD "Password" +#define D_PORT "Port" +#define D_POWER_FACTOR "Power Factor" +#define D_POWERUSAGE "Power" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "Pressure" +#define D_PRESSUREATSEALEVEL "SeaPressure" +#define D_PROGRAM_FLASH_SIZE "Program Flash Size" +#define D_PROGRAM_SIZE "Program Size" +#define D_PROJECT "Project" +#define D_RAIN "Rain" +#define D_RECEIVED "Received" +#define D_RESTART "Restart" +#define D_RESTARTING "Restarting" +#define D_RESTART_REASON "Restart Reason" +#define D_RESTORE "restore" +#define D_RETAINED "retained" +#define D_RULE "Rule" +#define D_SAVE "Save" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Subnet Mask" +#define D_SUBSCRIBE_TO "Subscribe to" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Successful" +#define D_SUNRISE "Sunrise" +#define D_SUNSET "Sunset" +#define D_TEMPERATURE "Temperature" +#define D_TO "to" +#define D_TOGGLE "Toggle" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Transmit" +#define D_TRUE "True" +#define D_TVOC "TVOC" +#define D_UPGRADE "upgrade" +#define D_UPLOAD "Upload" +#define D_UPTIME "Uptime" +#define D_USER "User" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range +#define D_UV_LEVEL "UV Level" +#define D_UV_POWER "UV Power" +#define D_VERSION "Version" +#define D_VOLTAGE "Voltage" +#define D_WEIGHT "Weight" +#define D_WARMLIGHT "Warm" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial logging disabled" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logging re-enabled" + +#define D_SET_BAUDRATE_TO "Set Baudrate to" +#define D_RECEIVED_TOPIC "Received Topic" +#define D_DATA_SIZE "Data Size" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" +#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" +#define D_FAILED_TO_START "failed to start" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Connecting to AP" +#define D_IN_MODE "in mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connect failed as no IP address received" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Connect failed as AP cannot be reached" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password" +#define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout" +#define D_ATTEMPTING_CONNECTION "Attempting connection..." +#define D_CHECKING_CONNECTION "Checking connection..." +#define D_QUERY_DONE "Query done. MQTT services found" +#define D_MQTT_SERVICE_FOUND "MQTT service found on" +#define D_FOUND_AT "found at" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Saved to flash at" +#define D_LOADED_FROM_FLASH_AT "Loaded from flash at" +#define D_USE_DEFAULTS "Use defaults" +#define D_ERASED_SECTOR "Erased sector" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
please upgrade" +#define D_WEBSERVER_ACTIVE_ON "Web server active on" +#define D_WITH_IP_ADDRESS "with IP address" +#define D_WEBSERVER_STOPPED "Web server stopped" +#define D_FILE_NOT_FOUND "File Not Found" +#define D_REDIRECTED "Redirected to captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" +#define D_TRYING_TO_CONNECT "Trying to connect device to network" + +#define D_RESTART_IN "Restart in" +#define D_SECONDS "seconds" +#define D_DEVICE_WILL_RESTART "Device will restart in a few seconds" +#define D_BUTTON_TOGGLE "Toggle" +#define D_CONFIGURATION "Configuration" +#define D_INFORMATION "Information" +#define D_FIRMWARE_UPGRADE "Firmware Upgrade" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Confirm Restart" + +#define D_CONFIGURE_MODULE "Configure Module" +#define D_CONFIGURE_WIFI "Configure WiFi" +#define D_CONFIGURE_MQTT "Configure MQTT" +#define D_CONFIGURE_DOMOTICZ "Configure Domoticz" +#define D_CONFIGURE_LOGGING "Configure Logging" +#define D_CONFIGURE_OTHER "Configure Other" +#define D_CONFIRM_RESET_CONFIGURATION "Confirm Reset Configuration" +#define D_RESET_CONFIGURATION "Reset Configuration" +#define D_BACKUP_CONFIGURATION "Backup Configuration" +#define D_RESTORE_CONFIGURATION "Restore Configuration" +#define D_MAIN_MENU "Main Menu" + +#define D_MODULE_PARAMETERS "Module parameters" +#define D_MODULE_TYPE "Module type" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Wifi parameters" +#define D_SCAN_FOR_WIFI_NETWORKS "Scan for wifi networks" +#define D_SCAN_DONE "Scan done" +#define D_NO_NETWORKS_FOUND "No networks found" +#define D_REFRESH_TO_SCAN_AGAIN "Refresh to scan again" +#define D_DUPLICATE_ACCESSPOINT "Duplicate AccessPoint" +#define D_SKIPPING_LOW_QUALITY "Skipping due to low quality" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Password" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Password" + +#define D_MQTT_PARAMETERS "MQTT parameters" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "Logging parameters" +#define D_SERIAL_LOG_LEVEL "Serial log level" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web log level" +#define D_SYS_LOG_LEVEL "Syslog level" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Telemetry period" + +#define D_OTHER_PARAMETERS "Other parameters" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Web Admin Password" +#define D_MQTT_ENABLE "MQTT enable" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Save configuration" +#define D_CONFIGURATION_SAVED "Configuration saved" +#define D_CONFIGURATION_RESET "Configuration reset" + +#define D_PROGRAM_VERSION "Program Version" +#define D_BUILD_DATE_AND_TIME "Build Date & Time" +#define D_CORE_AND_SDK_VERSION "Core/SDK Version" +#define D_FLASH_WRITE_COUNT "Flash write Count" +#define D_MAC_ADDRESS "MAC Address" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Port" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT User" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash Size" +#define D_FREE_PROGRAM_SPACE "Free Program Space" + +#define D_UPGRADE_BY_WEBSERVER "Upgrade by web server" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Start upgrade" +#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade by file upload" +#define D_UPLOAD_STARTED "Upload started" +#define D_UPGRADE_STARTED "Upgrade started" +#define D_UPLOAD_DONE "Upload done" +#define D_UPLOAD_ERR_1 "No file selected" +#define D_UPLOAD_ERR_2 "Not enough space" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "Program flash size is larger than real flash size" +#define D_UPLOAD_ERR_5 "Upload buffer miscompare" +#define D_UPLOAD_ERR_6 "Upload failed. Enable logging 3" +#define D_UPLOAD_ERR_7 "Upload aborted" +#define D_UPLOAD_ERR_8 "File invalid" +#define D_UPLOAD_ERR_9 "File too large" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "Upload error code" + +#define D_ENTER_COMMAND "Enter command" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" +#define D_NEED_USER_AND_PASSWORD "Need user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verify TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" +#define D_RETRY_IN "Retry in" +#define D_VERIFIED "Verified using Fingerprint" +#define D_INSECURE "Insecure connection due to invalid Fingerprint" +#define D_CONNECT_FAILED_TO "Connect failed to" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast disabled" +#define D_MULTICAST_REJOINED "Multicast (re)joined" +#define D_MULTICAST_JOIN_FAILED "Multicast join failed" +#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Response sent" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configure Timer" +#define D_TIMER_PARAMETERS "Timer parameters" +#define D_TIMER_ENABLE "Enable Timers" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Time" +#define D_TIMER_DAYS "Days" +#define D_TIMER_REPEAT "Repeat" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configure KNX" +#define D_KNX_PARAMETERS "KNX Parameters" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Physical Address" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "Enable KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Add" +#define D_DELETE "Delete" +#define D_REPLY "Reply" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Write" +#define D_KNX_COMMAND_READ "Read" +#define D_KNX_COMMAND_OTHER "Other" +#define D_SENT_TO "sent to" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energy Today" +#define D_ENERGY_YESTERDAY "Energy Yesterday" +#define D_ENERGY_TOTAL "Energy Total" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor busy" +#define D_SENSOR_CRC_ERROR "Sensor CRC error" +#define D_SENSORS_FOUND "Sensors found" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" +#define D_START_SIGNAL_LOW "start signal low" +#define D_START_SIGNAL_HIGH "start signal high" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "Checksum failure" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_EN_GB_H_ diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 4c98d8ebe..7527bb77a 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -1,703 +1,701 @@ -/* - es-ES.h - localization for Spanish - Spain for Tasmota - - Copyright (C) 2019 Adrian Scillato - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_ES_ES_H_ -#define _LANGUAGE_ES_ES_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.0.0.5 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1034 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "es" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DomLunMarMieJueVieSab" -#define D_MONTH3LIST "EneFebMarAbrMayJunJulAgoSepOctNovDic" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Calidad del Aire" -#define D_AP "AP" // Access Point -#define D_AS "como" -#define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Conteo Reinicios" -#define D_BRIGHTLIGHT "Brillante" -#define D_BSSID "BSSId" -#define D_BUTTON "Botón" -#define D_BY "por" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canal" -#define D_CO2 "CO2" -#define D_CODE "código" // Button code -#define D_COLDLIGHT "Fría" -#define D_COMMAND "Comando" -#define D_CONNECTED "Conectado" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Conteo" -#define D_COUNTER "Contador" -#define D_CURRENT "Corriente" // As in Voltage and Current -#define D_DATA "Datos" -#define D_DARKLIGHT "Oscuro" -#define D_DEBUG "Debug" -#define D_DISABLED "Deshabilitado" -#define D_DISTANCE "Distancia" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Listo" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulación" -#define D_ENABLED "Habilitado" -#define D_ERASE "Borrar" -#define D_ERROR "Error" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Falló" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "FallbackTopic" -#define D_FALSE "Falso" -#define D_FILE "Archivo" -#define D_FLOW_RATE "Caudal" -#define D_FREE_MEMORY "Memoria Libre" -#define D_FREQUENCY "Frecuencia" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Grupo" -#define D_HOST "Host" -#define D_HOSTNAME "Hostname" -#define D_HUMIDITY "Humedad" -#define D_ILLUMINANCE "Luminancia" -#define D_IMMEDIATE "inmediato" // Button immediate -#define D_INDEX "Índice" -#define D_INFO "Información" -#define D_INFRARED "Infrarrojo" -#define D_INITIALIZED "Inicializado" -#define D_IP_ADDRESS "Dirección IP" -#define D_LIGHT "Luz" -#define D_LWT "LWT" -#define D_MODULE "Módulo" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "Ruido" -#define D_NONE "Ninguno" -#define D_OFF "Apagado" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "Encendido" -#define D_ONLINE "Online" -#define D_PASSWORD "Clave" -#define D_PORT "Puerto" -#define D_POWER_FACTOR "Factor de Potencia" -#define D_POWERUSAGE "Potencia" -#define D_POWERUSAGE_ACTIVE "Potencia Activa" -#define D_POWERUSAGE_APPARENT "Potencia Aparente" -#define D_POWERUSAGE_REACTIVE "Potencia Reactiva" -#define D_PRESSURE "Presión" -#define D_PRESSUREATSEALEVEL "Presión al nivel del mar" -#define D_PROGRAM_FLASH_SIZE "Tamaño de Flash de Programa" -#define D_PROGRAM_SIZE "Tamaño Programa" -#define D_PROJECT "Proyecto" -#define D_RAIN "Lluvia" -#define D_RECEIVED "Recibido" -#define D_RESTART "Reiniciar" -#define D_RESTARTING "Reiniciando" -#define D_RESTART_REASON "Causa Reinicio" -#define D_RESTORE "Restauración" -#define D_RETAINED "Grabado" -#define D_RULE "Regla" -#define D_SAVE "Grabar" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Iniciar" -#define D_STD_TIME "STD" -#define D_STOP "Detener" -#define D_SUBNET_MASK "Máscara Subred" -#define D_SUBSCRIBE_TO "Suscribir a" -#define D_UNSUBSCRIBE_FROM "Desuscribirse de" -#define D_SUCCESSFUL "Exitosa" -#define D_SUNRISE "Salida del Sol" -#define D_SUNSET "Puesta del Sol" -#define D_TEMPERATURE "Temperatura" -#define D_TO "a" -#define D_TOGGLE "Conmutar" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usado" -#define D_TRANSMIT "Transmitir" -#define D_TRUE "Verdadero" -#define D_TVOC "TVOC" -#define D_UPGRADE "Actualización" -#define D_UPLOAD "Carga" -#define D_UPTIME "Tiempo Encendido" -#define D_USER "Usuario" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Índice UV" -#define D_UV_INDEX_1 "Bajo" -#define D_UV_INDEX_2 "Medio" -#define D_UV_INDEX_3 "Alto" -#define D_UV_INDEX_4 "Peligroso" -#define D_UV_INDEX_5 "Quemaduras 1 a 2 grad" -#define D_UV_INDEX_6 "Quemaduras 3 grad" -#define D_UV_INDEX_7 "Fuera de Rango" -#define D_UV_LEVEL "Nivel UV" -#define D_UV_POWER "UV Power" -#define D_VERSION "Versión" -#define D_VOLTAGE "Tensión" -#define D_WEIGHT "Peso" -#define D_WARMLIGHT "Cálida" -#define D_WEB_SERVER "Servidor Web" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "Cuidado, esta versión no guarda los cambios" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Log serial deshabilitado" -#define D_SYSLOG_LOGGING_REENABLED "Syslog re-habilitado" - -#define D_SET_BAUDRATE_TO "Baudrate a" -#define D_RECEIVED_TOPIC "Topic Recibido" -#define D_DATA_SIZE "Tamaño de Datos" -#define D_ANALOG_INPUT "Entrada Analógica" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Ciclo Bloqueado" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALLÓ con estado" -#define D_ACTIVE_FOR_3_MINUTES "activo por 3 minutos" -#define D_FAILED_TO_START "falló inicio" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Connectando a AP" -#define D_IN_MODE "en modo" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Falló Conexión, Dirección IP no recibida" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Falló Conexión, AP no pudo ser contactado" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Falló Conexión, clave de AP incorrecta" -#define D_CONNECT_FAILED_AP_TIMEOUT "Falló Conexión, timeout de AP" -#define D_ATTEMPTING_CONNECTION "Intentando conectar..." -#define D_CHECKING_CONNECTION "Probando conexión..." -#define D_QUERY_DONE "Consulta lista. Servicio MQTT encontrado" -#define D_MQTT_SERVICE_FOUND "Servicio MQTT encontrado en" -#define D_FOUND_AT "encontrado en" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host no encontrado" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Grabado a la flash en" -#define D_LOADED_FROM_FLASH_AT "Cargado desde flash en" -#define D_USE_DEFAULTS "Usar valores por defecto" -#define D_ERASED_SECTOR "Sector borrado" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" -#define D_WEBSERVER_ACTIVE_ON "Servidor web activo en" -#define D_WITH_IP_ADDRESS "con dirección IP" -#define D_WEBSERVER_STOPPED "Servidor web detenido" -#define D_FILE_NOT_FOUND "Archivo No Encontrado" -#define D_REDIRECTED "Redireccionado al portal captivo" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager como AccessPoint y Estación" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager como AccessPoint" -#define D_TRYING_TO_CONNECT "Intentado conectar dispositivo a la red" - -#define D_RESTART_IN "Reinicio en" -#define D_SECONDS "segundos" -#define D_DEVICE_WILL_RESTART "El dispositivo se reiniciará en unos segundos" -#define D_BUTTON_TOGGLE "Alternar ON/OFF" -#define D_CONFIGURATION "Configuración" -#define D_INFORMATION "Información" -#define D_FIRMWARE_UPGRADE "Actualizar Firmware" -#define D_CONSOLE "Consola" -#define D_CONFIRM_RESTART "Confirmar Reinicio" - -#define D_CONFIGURE_MODULE "Configuración del Módulo" -#define D_CONFIGURE_WIFI "Configuración WiFi" -#define D_CONFIGURE_MQTT "Configuración MQTT" -#define D_CONFIGURE_DOMOTICZ "Configuración Domoticz" -#define D_CONFIGURE_LOGGING "Configuración Logging" -#define D_CONFIGURE_OTHER "Configuración Extra" -#define D_CONFIRM_RESET_CONFIGURATION "Confirmar Reset Configuración" -#define D_RESET_CONFIGURATION "Reset de Configuración" -#define D_BACKUP_CONFIGURATION "Backup de Configuración" -#define D_RESTORE_CONFIGURATION "Restaurar Configuración" -#define D_MAIN_MENU "Menú Principal" - -#define D_MODULE_PARAMETERS "Parámetros del módulo" -#define D_MODULE_TYPE "Tipo de módulo" -#define D_PULLUP_ENABLE "Botón/Llave sin pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Parámetros Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Buscar redes wifi" -#define D_SCAN_DONE "Busqueda finalizada" -#define D_NO_NETWORKS_FOUND "Ninguna red encontrada" -#define D_REFRESH_TO_SCAN_AGAIN "Recargar página para buscar nuevamente" -#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicado" -#define D_SKIPPING_LOW_QUALITY "Ignorado por baja calidad" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "SSId AP1" -#define D_AP1_PASSWORD "Clave AP1" -#define D_AP2_SSID "SSId AP2" -#define D_AP2_PASSWORD "Clave AP2" - -#define D_MQTT_PARAMETERS "Parámetros MQTT" -#define D_CLIENT "Cliente" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "Parámetros Logging" -#define D_SERIAL_LOG_LEVEL "Nivel de log por Serial" -#define D_MQTT_LOG_LEVEL "Nivel de log por Mqtt" -#define D_WEB_LOG_LEVEL "Nivel de log por Web" -#define D_SYS_LOG_LEVEL "Nivel de log por Syslog" -#define D_MORE_DEBUG "Más Debug" -#define D_SYSLOG_HOST "Host del Syslog" -#define D_SYSLOG_PORT "Puerto del Syslog" -#define D_TELEMETRY_PERIOD "Período de Telemetría" - -#define D_OTHER_PARAMETERS "Otros parámetros" -#define D_TEMPLATE "Plantilla" -#define D_ACTIVATE "Activar" -#define D_WEB_ADMIN_PASSWORD "Clave Administrador Web" -#define D_MQTT_ENABLE "Habilitar MQTT" -#define D_FRIENDLY_NAME "Nombre Amigable" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "dispositivo simple" -#define D_MULTI_DEVICE "dispositivo múltiple" - -#define D_CONFIGURE_TEMPLATE "Configurar Plantilla" -#define D_TEMPLATE_PARAMETERS "Parámetros de Plantilla" -#define D_TEMPLATE_NAME "Nombre" -#define D_BASE_TYPE "Basada en" -#define D_TEMPLATE_FLAGS "Opciones" - -#define D_SAVE_CONFIGURATION "Grabar configuración" -#define D_CONFIGURATION_SAVED "Configuración grabada" -#define D_CONFIGURATION_RESET "Configuración restablecida" - -#define D_PROGRAM_VERSION "Versión del Programa" -#define D_BUILD_DATE_AND_TIME "Fecha y Hora de Compilación" -#define D_CORE_AND_SDK_VERSION "Versión Core/SDK" -#define D_FLASH_WRITE_COUNT "Contador de escritura en Flash" -#define D_MAC_ADDRESS "Dirección MAC" -#define D_MQTT_HOST "Host MQTT" -#define D_MQTT_PORT "Puerto MQTT" -#define D_MQTT_CLIENT "Cliente MQTT" -#define D_MQTT_USER "Usuario MQTT" -#define D_MQTT_TOPIC "Topic MQTT" -#define D_MQTT_GROUP_TOPIC "Group Topic MQTT" -#define D_MQTT_FULL_TOPIC "Full Topic MQTT" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Tamaño Flash" -#define D_FREE_PROGRAM_SPACE "Memoria de Programa Libre" - -#define D_UPGRADE_BY_WEBSERVER "Actualizar por servidor web" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Comenzar actualización" -#define D_UPGRADE_BY_FILE_UPLOAD "Actualizar cargando archivo bin" -#define D_UPLOAD_STARTED "Cargando archivo" -#define D_UPGRADE_STARTED "Actualización iniciada" -#define D_UPLOAD_DONE "Carga finalizada" -#define D_UPLOAD_ERR_1 "Ningún archivo seleccionado" -#define D_UPLOAD_ERR_2 "Espacio insuficiente" -#define D_UPLOAD_ERR_3 "Magic byte no corresponde a 0xE9" -#define D_UPLOAD_ERR_4 "El tamaño de la memoria de programa es mayor que la de la flash" -#define D_UPLOAD_ERR_5 "Error de comparación del buffer de carga" -#define D_UPLOAD_ERR_6 "Carga fallida. Habilitar logging 3" -#define D_UPLOAD_ERR_7 "Carga cancelada" -#define D_UPLOAD_ERR_8 "Archivo no válido" -#define D_UPLOAD_ERR_9 "Archivo muy grande" -#define D_UPLOAD_ERR_10 "No inició chip RF" -#define D_UPLOAD_ERR_11 "No se pudo borrar en el chip RF" -#define D_UPLOAD_ERR_12 "No se puedo escribir en el chip RF" -#define D_UPLOAD_ERR_13 "No se pudo decodificar firmware RF" -#define D_UPLOAD_ERROR_CODE "Código de error de carga" - -#define D_ENTER_COMMAND "Ingresar comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 si desea respuesta" -#define D_NEED_USER_AND_PASSWORD "Se necesita user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verificar TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "Falló Conexión TLS a" -#define D_RETRY_IN "Reintentando" -#define D_VERIFIED "Verificado Fingerprint" -#define D_INSECURE "Conexión insegura por Fingerprint inválido" -#define D_CONNECT_FAILED_TO "Falló Conexión a" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast deshabilitado" -#define D_MULTICAST_REJOINED "Multicast (re)conectado" -#define D_MULTICAST_JOIN_FAILED "Conexión Multicast fallida" -#define D_FAILED_TO_SEND_RESPONSE "Falla al enviar respuesta" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "Evento base de WeMo" -#define D_WEMO_EVENT_SERVICE "Evento de servicio de WeMo" -#define D_WEMO_META_SERVICE "Meta Servicio de WeMo" -#define D_WEMO_SETUP "Configuración de WeMo" -#define D_RESPONSE_SENT "Respuesta enviada" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Configuración Hue" -#define D_HUE_API_NOT_IMPLEMENTED "API de Hue no implementada" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 paquetes de respuesta enviados" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parámetros Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Potencia,Energía" - #define D_DOMOTICZ_ILLUMINANCE "Luminancia" - #define D_DOMOTICZ_COUNT "Contador/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltaje/PM2,5" - #define D_DOMOTICZ_CURRENT "Corriente/PM10" - #define D_DOMOTICZ_AIRQUALITY "Calidad del Aire" - #define D_DOMOTICZ_P1_SMART_METER "Medidor Inteligente P1" -#define D_DOMOTICZ_UPDATE_TIMER "Intervalo de refresco" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configuración Temporizadores" -#define D_TIMER_PARAMETERS "Parámetros de Temporizadores" -#define D_TIMER_ENABLE "Habilitar Temporizadores" -#define D_TIMER_ARM "Activo" -#define D_TIMER_TIME "Hora" -#define D_TIMER_DAYS "Días" -#define D_TIMER_REPEAT "Repetir" -#define D_TIMER_OUTPUT "Salida" -#define D_TIMER_ACTION "Estado" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configuración de KNX" -#define D_KNX_PARAMETERS "Parámetros de KNX" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Dirección Física" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Debe ser única en la red KNX )" -#define D_KNX_ENABLE "Habilitar KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Datos a Enviar a las Direcciones de Grupo" -#define D_ADD "Agregar" -#define D_DELETE "Eliminar" -#define D_REPLY "Responder" -#define D_KNX_GROUP_ADDRESS_TO_READ "Direcciones de Grupo para Recibir Datos" -#define D_RECEIVED_FROM "Recibido desde" -#define D_KNX_COMMAND_WRITE "Escribir" -#define D_KNX_COMMAND_READ "Leer" -#define D_KNX_COMMAND_OTHER "Otro" -#define D_SENT_TO "enviada a" -#define D_KNX_WARNING "La dirección de grupo ( 0 / 0 / 0 ) está reservada y no puede ser utilizada." -#define D_KNX_ENHANCEMENT "Mejora de Comunicación" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energía Hoy" -#define D_ENERGY_YESTERDAY "Energía Ayer" -#define D_ENERGY_TOTAL "Energía Total" - -// xdrv_27_shutter.ino -#define D_OPEN "Abrir" -#define D_CLOSE "Cerrar" -#define D_DOMOTICZ_SHUTTER "Cortina" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configurar PCF8574" -#define D_PCF8574_PARAMETERS "Parámetros de PCF8574" -#define D_INVERT_PORTS "Invertir Puertos" -#define D_DEVICE "Dispositivo" -#define D_DEVICE_INPUT "Entrada" -#define D_DEVICE_OUTPUT "Salida" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor ocupado" -#define D_SENSOR_CRC_ERROR "Error CRC del Sensor" -#define D_SENSORS_FOUND "Sensores encontrados" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Espera de timeout por" -#define D_START_SIGNAL_LOW "iniciar señal baja" -#define D_START_SIGNAL_HIGH "iniciar señal alta" -#define D_PULSE "pulso" -#define D_CHECKSUM_FAILURE "Falló Checksum" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor no ha enviado el comando ACK" -#define D_SHT1X_FOUND "SHT1X encontrado" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partículas" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remover Peso" -#define D_HX_CAL_REFERENCE "Poner Peso de Referencia" -#define D_HX_CAL_DONE "Calibrado" -#define D_HX_CAL_FAIL "Falló Calibración" -#define D_RESET_HX711 "Restablecer Escala" -#define D_CONFIGURE_HX711 "Configurar Escala" -#define D_HX711_PARAMETERS "Parámetros de Escala" -#define D_ITEM_WEIGHT "Peso" -#define D_REFERENCE_WEIGHT "Peso de Referencia" -#define D_CALIBRATE "Calibrar" -#define D_CALIBRATION "Calibración" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Dirección del Viento" -#define D_TX20_WIND_SPEED "Vel. del Viento" -#define D_TX20_WIND_SPEED_AVG "Vel. Prom. del Viento" -#define D_TX20_WIND_SPEED_MAX "Vel. Max. del Viento" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Ninguno" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IR Tx" -#define D_SENSOR_SWITCH "Llave" // Suffix "1" -#define D_SENSOR_BUTTON "Botón" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Contador" // Suffix "1" -#define D_SENSOR_IRRECV "IR Rx" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "seg" -#define D_UNIT_SECTORS "sectores" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Ángulo de Fase" -#define D_IMPORT_ACTIVE "P. Activa Entrante" -#define D_EXPORT_ACTIVE "P. Activa Saliente" -#define D_IMPORT_REACTIVE "P. Reactiva Entrante" -#define D_EXPORT_REACTIVE "P. Reactiva Saliente" -#define D_TOTAL_REACTIVE "P. Reactiva Total" -#define D_UNIT_KWARH "kVArH" -#define D_UNIT_ANGLE "Grados" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltaje" -#define D_PV1_CURRENT "PV1 Corriente" -#define D_PV1_POWER "PV1 Potencia" -#define D_PV2_VOLTAGE "PV2 Voltaee" -#define D_PV2_CURRENT "PV2 Corriente" -#define D_PV2_POWER "PV2 Potencia" -#define D_SOLAR_POWER "Potencia Solar" -#define D_INVERTER_POWER "Potencia del Inversor" -#define D_STATUS "Estado" -#define D_WAITING "En Espera" -#define D_CHECKING "Revisando" -#define D_WORKING "Funcionando" -#define D_FAILURE "Falla" -#define D_SOLAX_ERROR_0 "Sin código de Error" -#define D_SOLAX_ERROR_1 "Falla por Pérdida de Red" -#define D_SOLAX_ERROR_2 "Falla por Voltaje de Red" -#define D_SOLAX_ERROR_3 "Falla por Frecuencia de Red" -#define D_SOLAX_ERROR_4 "Falla por Voltaje en PV" -#define D_SOLAX_ERROR_5 "Falla de Aislación" -#define D_SOLAX_ERROR_6 "Falla por sobretemperatura" -#define D_SOLAX_ERROR_7 "Falla de Ventilador" -#define D_SOLAX_ERROR_8 "Falla del Dispositivo" - -#endif // _LANGUAGE_ES_ES_H_ +/* + es-ES.h - localization for Spanish - Spain for Tasmota + + Copyright (C) 2019 Adrian Scillato + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_ES_ES_H_ +#define _LANGUAGE_ES_ES_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.0.0.5 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1034 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "es" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DomLunMarMieJueVieSab" +#define D_MONTH3LIST "EneFebMarAbrMayJunJulAgoSepOctNovDic" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Calidad del Aire" +#define D_AP "AP" // Access Point +#define D_AS "como" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Conteo Reinicios" +#define D_BRIGHTLIGHT "Brillante" +#define D_BSSID "BSSId" +#define D_BUTTON "Botón" +#define D_BY "por" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "CO2" +#define D_CODE "código" // Button code +#define D_COLDLIGHT "Fría" +#define D_COMMAND "Comando" +#define D_CONNECTED "Conectado" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Conteo" +#define D_COUNTER "Contador" +#define D_CURRENT "Corriente" // As in Voltage and Current +#define D_DATA "Datos" +#define D_DARKLIGHT "Oscuro" +#define D_DEBUG "Debug" +#define D_DISABLED "Deshabilitado" +#define D_DISTANCE "Distancia" +#define D_DNS_SERVER "DNS Server" +#define D_DONE "Listo" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulación" +#define D_ENABLED "Habilitado" +#define D_ERASE "Borrar" +#define D_ERROR "Error" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Falló" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "FallbackTopic" +#define D_FALSE "Falso" +#define D_FILE "Archivo" +#define D_FLOW_RATE "Caudal" +#define D_FREE_MEMORY "Memoria Libre" +#define D_FREQUENCY "Frecuencia" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupo" +#define D_HOST "Host" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Humedad" +#define D_ILLUMINANCE "Luminancia" +#define D_IMMEDIATE "inmediato" // Button immediate +#define D_INDEX "Índice" +#define D_INFO "Información" +#define D_INFRARED "Infrarrojo" +#define D_INITIALIZED "Inicializado" +#define D_IP_ADDRESS "Dirección IP" +#define D_LIGHT "Luz" +#define D_LWT "LWT" +#define D_MODULE "Módulo" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "Ruido" +#define D_NONE "Ninguno" +#define D_OFF "Apagado" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "Encendido" +#define D_ONLINE "Online" +#define D_PASSWORD "Clave" +#define D_PORT "Puerto" +#define D_POWER_FACTOR "Factor de Potencia" +#define D_POWERUSAGE "Potencia" +#define D_POWERUSAGE_ACTIVE "Potencia Activa" +#define D_POWERUSAGE_APPARENT "Potencia Aparente" +#define D_POWERUSAGE_REACTIVE "Potencia Reactiva" +#define D_PRESSURE "Presión" +#define D_PRESSUREATSEALEVEL "Presión al nivel del mar" +#define D_PROGRAM_FLASH_SIZE "Tamaño de Flash de Programa" +#define D_PROGRAM_SIZE "Tamaño Programa" +#define D_PROJECT "Proyecto" +#define D_RAIN "Lluvia" +#define D_RECEIVED "Recibido" +#define D_RESTART "Reiniciar" +#define D_RESTARTING "Reiniciando" +#define D_RESTART_REASON "Causa Reinicio" +#define D_RESTORE "Restauración" +#define D_RETAINED "Grabado" +#define D_RULE "Regla" +#define D_SAVE "Grabar" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Iniciar" +#define D_STD_TIME "STD" +#define D_STOP "Detener" +#define D_SUBNET_MASK "Máscara Subred" +#define D_SUBSCRIBE_TO "Suscribir a" +#define D_UNSUBSCRIBE_FROM "Desuscribirse de" +#define D_SUCCESSFUL "Exitosa" +#define D_SUNRISE "Salida del Sol" +#define D_SUNSET "Puesta del Sol" +#define D_TEMPERATURE "Temperatura" +#define D_TO "a" +#define D_TOGGLE "Conmutar" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usado" +#define D_TRANSMIT "Transmitir" +#define D_TRUE "Verdadero" +#define D_TVOC "TVOC" +#define D_UPGRADE "Actualización" +#define D_UPLOAD "Carga" +#define D_UPTIME "Tiempo Encendido" +#define D_USER "Usuario" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Índice UV" +#define D_UV_INDEX_1 "Bajo" +#define D_UV_INDEX_2 "Medio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Peligroso" +#define D_UV_INDEX_5 "Quemaduras 1 a 2 grad" +#define D_UV_INDEX_6 "Quemaduras 3 grad" +#define D_UV_INDEX_7 "Fuera de Rango" +#define D_UV_LEVEL "Nivel UV" +#define D_UV_POWER "UV Power" +#define D_VERSION "Versión" +#define D_VOLTAGE "Tensión" +#define D_WEIGHT "Peso" +#define D_WARMLIGHT "Cálida" +#define D_WEB_SERVER "Servidor Web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "Cuidado, esta versión no guarda los cambios" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Log serial deshabilitado" +#define D_SYSLOG_LOGGING_REENABLED "Syslog re-habilitado" + +#define D_SET_BAUDRATE_TO "Baudrate a" +#define D_RECEIVED_TOPIC "Topic Recibido" +#define D_DATA_SIZE "Tamaño de Datos" +#define D_ANALOG_INPUT "Entrada Analógica" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Ciclo Bloqueado" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALLÓ con estado" +#define D_ACTIVE_FOR_3_MINUTES "activo por 3 minutos" +#define D_FAILED_TO_START "falló inicio" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Connectando a AP" +#define D_IN_MODE "en modo" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Falló Conexión, Dirección IP no recibida" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Falló Conexión, AP no pudo ser contactado" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Falló Conexión, clave de AP incorrecta" +#define D_CONNECT_FAILED_AP_TIMEOUT "Falló Conexión, timeout de AP" +#define D_ATTEMPTING_CONNECTION "Intentando conectar..." +#define D_CHECKING_CONNECTION "Probando conexión..." +#define D_QUERY_DONE "Consulta lista. Servicio MQTT encontrado" +#define D_MQTT_SERVICE_FOUND "Servicio MQTT encontrado en" +#define D_FOUND_AT "encontrado en" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host no encontrado" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Grabado a la flash en" +#define D_LOADED_FROM_FLASH_AT "Cargado desde flash en" +#define D_USE_DEFAULTS "Usar valores por defecto" +#define D_ERASED_SECTOR "Sector borrado" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
actualice por favor" +#define D_WEBSERVER_ACTIVE_ON "Servidor web activo en" +#define D_WITH_IP_ADDRESS "con dirección IP" +#define D_WEBSERVER_STOPPED "Servidor web detenido" +#define D_FILE_NOT_FOUND "Archivo No Encontrado" +#define D_REDIRECTED "Redireccionado al portal captivo" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager como AccessPoint y Estación" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager como AccessPoint" +#define D_TRYING_TO_CONNECT "Intentado conectar dispositivo a la red" + +#define D_RESTART_IN "Reinicio en" +#define D_SECONDS "segundos" +#define D_DEVICE_WILL_RESTART "El dispositivo se reiniciará en unos segundos" +#define D_BUTTON_TOGGLE "Alternar ON/OFF" +#define D_CONFIGURATION "Configuración" +#define D_INFORMATION "Información" +#define D_FIRMWARE_UPGRADE "Actualizar Firmware" +#define D_CONSOLE "Consola" +#define D_CONFIRM_RESTART "Confirmar Reinicio" + +#define D_CONFIGURE_MODULE "Configuración del Módulo" +#define D_CONFIGURE_WIFI "Configuración WiFi" +#define D_CONFIGURE_MQTT "Configuración MQTT" +#define D_CONFIGURE_DOMOTICZ "Configuración Domoticz" +#define D_CONFIGURE_LOGGING "Configuración Logging" +#define D_CONFIGURE_OTHER "Configuración Extra" +#define D_CONFIRM_RESET_CONFIGURATION "Confirmar Reset Configuración" +#define D_RESET_CONFIGURATION "Reset de Configuración" +#define D_BACKUP_CONFIGURATION "Backup de Configuración" +#define D_RESTORE_CONFIGURATION "Restaurar Configuración" +#define D_MAIN_MENU "Menú Principal" + +#define D_MODULE_PARAMETERS "Parámetros del módulo" +#define D_MODULE_TYPE "Tipo de módulo" +#define D_PULLUP_ENABLE "Botón/Llave sin pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Parámetros Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Buscar redes wifi" +#define D_SCAN_DONE "Busqueda finalizada" +#define D_NO_NETWORKS_FOUND "Ninguna red encontrada" +#define D_REFRESH_TO_SCAN_AGAIN "Recargar página para buscar nuevamente" +#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicado" +#define D_SKIPPING_LOW_QUALITY "Ignorado por baja calidad" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "SSId AP1" +#define D_AP1_PASSWORD "Clave AP1" +#define D_AP2_SSID "SSId AP2" +#define D_AP2_PASSWORD "Clave AP2" + +#define D_MQTT_PARAMETERS "Parámetros MQTT" +#define D_CLIENT "Cliente" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "Parámetros Logging" +#define D_SERIAL_LOG_LEVEL "Nivel de log por Serial" +#define D_MQTT_LOG_LEVEL "Nivel de log por Mqtt" +#define D_WEB_LOG_LEVEL "Nivel de log por Web" +#define D_SYS_LOG_LEVEL "Nivel de log por Syslog" +#define D_MORE_DEBUG "Más Debug" +#define D_SYSLOG_HOST "Host del Syslog" +#define D_SYSLOG_PORT "Puerto del Syslog" +#define D_TELEMETRY_PERIOD "Período de Telemetría" + +#define D_OTHER_PARAMETERS "Otros parámetros" +#define D_TEMPLATE "Plantilla" +#define D_ACTIVATE "Activar" +#define D_WEB_ADMIN_PASSWORD "Clave Administrador Web" +#define D_MQTT_ENABLE "Habilitar MQTT" +#define D_FRIENDLY_NAME "Nombre Amigable" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "dispositivo simple" +#define D_MULTI_DEVICE "dispositivo múltiple" + +#define D_CONFIGURE_TEMPLATE "Configurar Plantilla" +#define D_TEMPLATE_PARAMETERS "Parámetros de Plantilla" +#define D_TEMPLATE_NAME "Nombre" +#define D_BASE_TYPE "Basada en" +#define D_TEMPLATE_FLAGS "Opciones" + +#define D_SAVE_CONFIGURATION "Grabar configuración" +#define D_CONFIGURATION_SAVED "Configuración grabada" +#define D_CONFIGURATION_RESET "Configuración restablecida" + +#define D_PROGRAM_VERSION "Versión del Programa" +#define D_BUILD_DATE_AND_TIME "Fecha y Hora de Compilación" +#define D_CORE_AND_SDK_VERSION "Versión Core/SDK" +#define D_FLASH_WRITE_COUNT "Contador de escritura en Flash" +#define D_MAC_ADDRESS "Dirección MAC" +#define D_MQTT_HOST "Host MQTT" +#define D_MQTT_PORT "Puerto MQTT" +#define D_MQTT_CLIENT "Cliente MQTT" +#define D_MQTT_USER "Usuario MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Group Topic MQTT" +#define D_MQTT_FULL_TOPIC "Full Topic MQTT" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Tamaño Flash" +#define D_FREE_PROGRAM_SPACE "Memoria de Programa Libre" + +#define D_UPGRADE_BY_WEBSERVER "Actualizar por servidor web" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Comenzar actualización" +#define D_UPGRADE_BY_FILE_UPLOAD "Actualizar cargando archivo bin" +#define D_UPLOAD_STARTED "Cargando archivo" +#define D_UPGRADE_STARTED "Actualización iniciada" +#define D_UPLOAD_DONE "Carga finalizada" +#define D_UPLOAD_ERR_1 "Ningún archivo seleccionado" +#define D_UPLOAD_ERR_2 "Espacio insuficiente" +#define D_UPLOAD_ERR_3 "Magic byte no corresponde a 0xE9" +#define D_UPLOAD_ERR_4 "El tamaño de la memoria de programa es mayor que la de la flash" +#define D_UPLOAD_ERR_5 "Error de comparación del buffer de carga" +#define D_UPLOAD_ERR_6 "Carga fallida. Habilitar logging 3" +#define D_UPLOAD_ERR_7 "Carga cancelada" +#define D_UPLOAD_ERR_8 "Archivo no válido" +#define D_UPLOAD_ERR_9 "Archivo muy grande" +#define D_UPLOAD_ERR_10 "No inició chip RF" +#define D_UPLOAD_ERR_11 "No se pudo borrar en el chip RF" +#define D_UPLOAD_ERR_12 "No se puedo escribir en el chip RF" +#define D_UPLOAD_ERR_13 "No se pudo decodificar firmware RF" +#define D_UPLOAD_ERROR_CODE "Código de error de carga" + +#define D_ENTER_COMMAND "Ingresar comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 si desea respuesta" +#define D_NEED_USER_AND_PASSWORD "Se necesita user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verificar TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "Falló Conexión TLS a" +#define D_RETRY_IN "Reintentando" +#define D_VERIFIED "Verificado Fingerprint" +#define D_INSECURE "Conexión insegura por Fingerprint inválido" +#define D_CONNECT_FAILED_TO "Falló Conexión a" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast deshabilitado" +#define D_MULTICAST_REJOINED "Multicast (re)conectado" +#define D_MULTICAST_JOIN_FAILED "Conexión Multicast fallida" +#define D_FAILED_TO_SEND_RESPONSE "Falla al enviar respuesta" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "Evento base de WeMo" +#define D_WEMO_EVENT_SERVICE "Evento de servicio de WeMo" +#define D_WEMO_META_SERVICE "Meta Servicio de WeMo" +#define D_WEMO_SETUP "Configuración de WeMo" +#define D_RESPONSE_SENT "Respuesta enviada" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Configuración Hue" +#define D_HUE_API_NOT_IMPLEMENTED "API de Hue no implementada" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 paquetes de respuesta enviados" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parámetros Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Potencia,Energía" + #define D_DOMOTICZ_ILLUMINANCE "Luminancia" + #define D_DOMOTICZ_COUNT "Contador/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltaje/PM2,5" + #define D_DOMOTICZ_CURRENT "Corriente/PM10" + #define D_DOMOTICZ_AIRQUALITY "Calidad del Aire" + #define D_DOMOTICZ_P1_SMART_METER "Medidor Inteligente P1" +#define D_DOMOTICZ_UPDATE_TIMER "Intervalo de refresco" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configuración Temporizadores" +#define D_TIMER_PARAMETERS "Parámetros de Temporizadores" +#define D_TIMER_ENABLE "Habilitar Temporizadores" +#define D_TIMER_ARM "Activo" +#define D_TIMER_TIME "Hora" +#define D_TIMER_DAYS "Días" +#define D_TIMER_REPEAT "Repetir" +#define D_TIMER_OUTPUT "Salida" +#define D_TIMER_ACTION "Estado" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configuración de KNX" +#define D_KNX_PARAMETERS "Parámetros de KNX" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Dirección Física" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Debe ser única en la red KNX )" +#define D_KNX_ENABLE "Habilitar KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Datos a Enviar a las Direcciones de Grupo" +#define D_ADD "Agregar" +#define D_DELETE "Eliminar" +#define D_REPLY "Responder" +#define D_KNX_GROUP_ADDRESS_TO_READ "Direcciones de Grupo para Recibir Datos" +#define D_RECEIVED_FROM "Recibido desde" +#define D_KNX_COMMAND_WRITE "Escribir" +#define D_KNX_COMMAND_READ "Leer" +#define D_KNX_COMMAND_OTHER "Otro" +#define D_SENT_TO "enviada a" +#define D_KNX_WARNING "La dirección de grupo ( 0 / 0 / 0 ) está reservada y no puede ser utilizada." +#define D_KNX_ENHANCEMENT "Mejora de Comunicación" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energía Hoy" +#define D_ENERGY_YESTERDAY "Energía Ayer" +#define D_ENERGY_TOTAL "Energía Total" + +// xdrv_27_shutter.ino +#define D_OPEN "Abrir" +#define D_CLOSE "Cerrar" +#define D_DOMOTICZ_SHUTTER "Cortina" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configurar PCF8574" +#define D_PCF8574_PARAMETERS "Parámetros de PCF8574" +#define D_INVERT_PORTS "Invertir Puertos" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Entrada" +#define D_DEVICE_OUTPUT "Salida" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor ocupado" +#define D_SENSOR_CRC_ERROR "Error CRC del Sensor" +#define D_SENSORS_FOUND "Sensores encontrados" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Espera de timeout por" +#define D_START_SIGNAL_LOW "iniciar señal baja" +#define D_START_SIGNAL_HIGH "iniciar señal alta" +#define D_PULSE "pulso" +#define D_CHECKSUM_FAILURE "Falló Checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor no ha enviado el comando ACK" +#define D_SHT1X_FOUND "SHT1X encontrado" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partículas" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remover Peso" +#define D_HX_CAL_REFERENCE "Poner Peso de Referencia" +#define D_HX_CAL_DONE "Calibrado" +#define D_HX_CAL_FAIL "Falló Calibración" +#define D_RESET_HX711 "Restablecer Escala" +#define D_CONFIGURE_HX711 "Configurar Escala" +#define D_HX711_PARAMETERS "Parámetros de Escala" +#define D_ITEM_WEIGHT "Peso" +#define D_REFERENCE_WEIGHT "Peso de Referencia" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibración" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Dirección del Viento" +#define D_TX20_WIND_SPEED "Vel. del Viento" +#define D_TX20_WIND_SPEED_AVG "Vel. Prom. del Viento" +#define D_TX20_WIND_SPEED_MAX "Vel. Max. del Viento" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Ninguno" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IR Tx" +#define D_SENSOR_SWITCH "Llave" // Suffix "1" +#define D_SENSOR_BUTTON "Botón" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Contador" // Suffix "1" +#define D_SENSOR_IRRECV "IR Rx" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "seg" +#define D_UNIT_SECTORS "sectores" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Ángulo de Fase" +#define D_IMPORT_ACTIVE "P. Activa Entrante" +#define D_EXPORT_ACTIVE "P. Activa Saliente" +#define D_IMPORT_REACTIVE "P. Reactiva Entrante" +#define D_EXPORT_REACTIVE "P. Reactiva Saliente" +#define D_TOTAL_REACTIVE "P. Reactiva Total" +#define D_UNIT_KWARH "kVArH" +#define D_UNIT_ANGLE "Grados" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltaje" +#define D_PV1_CURRENT "PV1 Corriente" +#define D_PV1_POWER "PV1 Potencia" +#define D_PV2_VOLTAGE "PV2 Voltaee" +#define D_PV2_CURRENT "PV2 Corriente" +#define D_PV2_POWER "PV2 Potencia" +#define D_SOLAR_POWER "Potencia Solar" +#define D_INVERTER_POWER "Potencia del Inversor" +#define D_STATUS "Estado" +#define D_WAITING "En Espera" +#define D_CHECKING "Revisando" +#define D_WORKING "Funcionando" +#define D_FAILURE "Falla" +#define D_SOLAX_ERROR_0 "Sin código de Error" +#define D_SOLAX_ERROR_1 "Falla por Pérdida de Red" +#define D_SOLAX_ERROR_2 "Falla por Voltaje de Red" +#define D_SOLAX_ERROR_3 "Falla por Frecuencia de Red" +#define D_SOLAX_ERROR_4 "Falla por Voltaje en PV" +#define D_SOLAX_ERROR_5 "Falla de Aislación" +#define D_SOLAX_ERROR_6 "Falla por sobretemperatura" +#define D_SOLAX_ERROR_7 "Falla de Ventilador" +#define D_SOLAX_ERROR_8 "Falla del Dispositivo" + +#endif // _LANGUAGE_ES_ES_H_ diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 7b8d291b8..e107409e3 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -1,703 +1,701 @@ -/* - fr-FR.h - localization for French - France for Tasmota - - Copyright (C) 2019 Olivier Francais - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_FR_FR_H_ -#define _LANGUAGE_FR_FR_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.1.2.4 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1036 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "fr" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DimLunMarMerJeuVenSam" -#define D_MONTH3LIST "JanFevMarAvrMaiJunJulAutSepOctNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Qualité de l'Air" -#define D_AP "AP" // Access Point -#define D_AS "comme" -#define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Nombre de boot" -#define D_BRIGHTLIGHT "Luminosité" -#define D_BSSID "BSSId" -#define D_BUTTON "Bouton" -#define D_BY "par" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canal" -#define D_CO2 "Dioxyde de carbone" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "Froid" -#define D_COMMAND "Commande" -#define D_CONNECTED "Connecté" -#define D_CORS_DOMAIN "Domaine CORS" -#define D_COUNT "Compte" -#define D_COUNTER "Compteur" -#define D_CURRENT "Courant" // As in Voltage and Current -#define D_DATA "Donnée" -#define D_DARKLIGHT "Sombre" -#define D_DEBUG "Debug" -#define D_DISABLED "Désactivé" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "Serveur DNS" -#define D_DONE "Fait" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Émulation" -#define D_ENABLED "Activé" -#define D_ERASE "Effacer" -#define D_ERROR "Erreur" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Échoué" -#define D_FALLBACK "Secours" -#define D_FALLBACK_TOPIC "Topic de secours" -#define D_FALSE "Faux" -#define D_FILE "Fichier" -#define D_FLOW_RATE "Débit" -#define D_FREE_MEMORY "Mémoire libre" -#define D_FREQUENCY "Fréquence" -#define D_GAS "Gaz" -#define D_GATEWAY "Passerelle" -#define D_GROUP "Groupe" -#define D_HOST "Hôte" -#define D_HOSTNAME "Nom d'Hôte" -#define D_HUMIDITY "Humidité" -#define D_ILLUMINANCE "Éclairement" -#define D_IMMEDIATE "immédiat" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infra-rouge" -#define D_INITIALIZED "Initialisé" -#define D_IP_ADDRESS "Adresse IP" -#define D_LIGHT "Lumière" -#define D_LWT "LWT" -#define D_MODULE "Module" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-pression" -#define D_NOISE "Bruit" -#define D_NONE "Aucun" -#define D_OFF "Arrêt" -#define D_OFFLINE "Déconnecté" -#define D_OK "Ok" -#define D_ON "Marche" -#define D_ONLINE "Connecté" -#define D_PASSWORD "Mot de passe" -#define D_PORT "Port" -#define D_POWER_FACTOR "Fact de puiss" -#define D_POWERUSAGE "Puissance" -#define D_POWERUSAGE_ACTIVE "Puiss active" -#define D_POWERUSAGE_APPARENT "Puiss apparente" -#define D_POWERUSAGE_REACTIVE "Puiss réactive" -#define D_PRESSURE "Pression" -#define D_PRESSUREATSEALEVEL "PressionMer" -#define D_PROGRAM_FLASH_SIZE "Taille Flash Programme" -#define D_PROGRAM_SIZE "Taille programme" -#define D_PROJECT "Projet" -#define D_RAIN "Pluie" -#define D_RECEIVED "Reçu" -#define D_RESTART "Redémarrage" -#define D_RESTARTING "Redémarre" -#define D_RESTART_REASON "Raison du redémarrage" -#define D_RESTORE "restaurer" -#define D_RETAINED "persistant" // MQTT -#define D_RULE "Règle" -#define D_SAVE "Enregistrer" -#define D_SENSOR "Capteur" -#define D_SSID "SSID" -#define D_START "Lancer" // "Lancer la mise à jour" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Masque sous-réseau" -#define D_SUBSCRIBE_TO "S'abonner à" -#define D_UNSUBSCRIBE_FROM "Se désabonner de" -#define D_SUCCESSFUL "Réussi" -#define D_SUNRISE "Lever du jour" -#define D_SUNSET "Tombée de la nuit" -#define D_TEMPERATURE "Température" -#define D_TO "à" -#define D_TOGGLE "Inverser" -#define D_TOPIC "Topic" // Keep MQTT keyword -#define D_TOTAL_USAGE "Eau totale" -#define D_TRANSMIT "Transmettre" -#define D_TRUE "Vrai" -#define D_TVOC "TVOC" -#define D_UPGRADE "la mise à jour" // "Lancer la mise à jour" -#define D_UPLOAD "Upload" // Not better in french -#define D_UPTIME "Durée d'activité" -#define D_USER "Utilisateur" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Indice UV" -#define D_UV_INDEX_1 "Faible" -#define D_UV_INDEX_2 "Modéré" -#define D_UV_INDEX_3 "Élevé" -#define D_UV_INDEX_4 "Très élevé" -#define D_UV_INDEX_5 "Brûlure niv.1/2" -#define D_UV_INDEX_6 "Brûlure niv.3" -#define D_UV_INDEX_7 "Hors échelle" -#define D_UV_LEVEL "Niveau UV" -#define D_UV_POWER "Puissance UV" -#define D_VERSION "Version" -#define D_VOLTAGE "Tension" -#define D_WEIGHT "Poids" -#define D_WARMLIGHT "Chaud" -#define D_WEB_SERVER "Serveur web" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ATTENTION Cette version ne supporte pas les réglages persistants" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivée" -#define D_SYSLOG_LOGGING_REENABLED "Jounalisation SysLog réactivée" - -#define D_SET_BAUDRATE_TO "Définir le débit à" -#define D_RECEIVED_TOPIC "Topic reçu" // Terme MQTT -#define D_DATA_SIZE "Taille données" -#define D_ANALOG_INPUT "Analogique" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Boucle bloquée" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig ÉCHOUÉ avec status" -#define D_ACTIVE_FOR_3_MINUTES "actif pour 3 minutes" -#define D_FAILED_TO_START "Échec de démarrage" -#define D_PATCH_ISSUE_2186 "Correction 2186" -#define D_CONNECTING_TO_AP "Connexion à l'AP" -#define D_IN_MODE "en mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Échec de connexion car aucune adresse IP n'a été reçue" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Échec de connexion car l'AP ne peut-être contacté" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Échec de connexion car le mot de passe de l'AP est incorrect" -#define D_CONNECT_FAILED_AP_TIMEOUT "Échec de connexion avec l'AP, expiré" -#define D_ATTEMPTING_CONNECTION "Tentative de connexion..." -#define D_CHECKING_CONNECTION "Vérification connexion..." -#define D_QUERY_DONE "Requête terminée. Services MQTT trouvés" -#define D_MQTT_SERVICE_FOUND "Service MQTT trouvé sur" -#define D_FOUND_AT "trouvé à" -#define D_SYSLOG_HOST_NOT_FOUND "Hôte SysLog introuvable" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Enregistré en flash à" -#define D_LOADED_FROM_FLASH_AT "Chargé de la flash à" -#define D_USE_DEFAULTS "Utiliser par défaut" -#define D_ERASED_SECTOR "Secteur effacé" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" -#define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur" -#define D_WITH_IP_ADDRESS "avec l'adresse IP" -#define D_WEBSERVER_STOPPED "Serveur web éteint" -#define D_FILE_NOT_FOUND "Fichier introuvable" -#define D_REDIRECTED "Redirection sur le portail captif" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager en mode Point d'Accès et Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager en mode Point d'Accès" -#define D_TRYING_TO_CONNECT "Tentative de connexion du module au réseau" - -#define D_RESTART_IN "Redémarrage dans" -#define D_SECONDS "secondes" -#define D_DEVICE_WILL_RESTART "Le module va redémarrer dans quelques secondes" -#define D_BUTTON_TOGGLE "on/off" -#define D_CONFIGURATION "Configuration" -#define D_INFORMATION "Informations" -#define D_FIRMWARE_UPGRADE "Mise à jour du Firmware" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Confirmer redémarrage" - -#define D_CONFIGURE_MODULE "Configuration du Module" -#define D_CONFIGURE_WIFI "Configuration WiFi" -#define D_CONFIGURE_MQTT "Configuration MQTT" -#define D_CONFIGURE_DOMOTICZ "Configuration Domoticz" -#define D_CONFIGURE_LOGGING "Configuration du journal" -#define D_CONFIGURE_OTHER "Autre configuration" -#define D_CONFIRM_RESET_CONFIGURATION "Confirmer la réinit. de la config." -#define D_RESET_CONFIGURATION "Configuration par défaut" -#define D_BACKUP_CONFIGURATION "Sauvegarde de la config." -#define D_RESTORE_CONFIGURATION "Restauration de la config." -#define D_MAIN_MENU "Menu principal" - -#define D_MODULE_PARAMETERS "Paramètres module" -#define D_MODULE_TYPE "Type de module" -#define D_PULLUP_ENABLE "Inter. sans pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Entrée série" -#define D_SERIAL_OUT "Sortie série" - -#define D_WIFI_PARAMETERS "Paramètres Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Scan des réseaux wifi" -#define D_SCAN_DONE "Scan terminé" -#define D_NO_NETWORKS_FOUND "Aucun réseau trouvé" -#define D_REFRESH_TO_SCAN_AGAIN "Rafraîchir pour scanner à nouveau" -#define D_DUPLICATE_ACCESSPOINT "Point d'Accès dupliqué" -#define D_SKIPPING_LOW_QUALITY "Évité car de mauvaise qualité" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "Mot de passe AP1" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "Mot de passe AP2" - -#define D_MQTT_PARAMETERS "Paramètres MQTT" -#define D_CLIENT "Client" -#define D_FULL_TOPIC "Topic complet" - -#define D_LOGGING_PARAMETERS "Paramètres du journal" -#define D_SERIAL_LOG_LEVEL "Niveau de journalisation série" -#define D_MQTT_LOG_LEVEL "Niveau de journalisation MQTT" -#define D_WEB_LOG_LEVEL "Niveau de journalisation web" -#define D_SYS_LOG_LEVEL "Niveau SysLog" -#define D_MORE_DEBUG "Plus de debug" -#define D_SYSLOG_HOST "Hôte SysLog" -#define D_SYSLOG_PORT "Port SysLog" -#define D_TELEMETRY_PERIOD "Période télémétrie" - -#define D_OTHER_PARAMETERS "Autres paramètres" -#define D_TEMPLATE "Modèle" -#define D_ACTIVATE "Activer" -#define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin" -#define D_MQTT_ENABLE "MQTT activé" -#define D_FRIENDLY_NAME "Surnom" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "module unique" -#define D_MULTI_DEVICE "multi module" - -#define D_CONFIGURE_TEMPLATE "Configuration du modèle" -#define D_TEMPLATE_PARAMETERS "Paramètres du modèle" -#define D_TEMPLATE_NAME "Nom" -#define D_BASE_TYPE "Basé sur" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Enregistrer la configuration" -#define D_CONFIGURATION_SAVED "Configuration enregistrée" -#define D_CONFIGURATION_RESET "Configuration réinitialisée" - -#define D_PROGRAM_VERSION "Version du programme" -#define D_BUILD_DATE_AND_TIME "Date & Heure de build" -#define D_CORE_AND_SDK_VERSION "Version Core/SDK" -#define D_FLASH_WRITE_COUNT "Compteur écriture flash" -#define D_MAC_ADDRESS "Adresse MAC" -#define D_MQTT_HOST "Hôte MQTT" -#define D_MQTT_PORT "Port MQTT" -#define D_MQTT_CLIENT "Client MQTT" -#define D_MQTT_USER "Utilisateur MQTT" -#define D_MQTT_TOPIC "Topic MQTT" -#define D_MQTT_GROUP_TOPIC "Groupe topic MQTT" -#define D_MQTT_FULL_TOPIC "Topic complet MQTT" -#define D_MDNS_DISCOVERY "Découverte mDNS" -#define D_MDNS_ADVERTISE "Annonce mDNS" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Taille flash" -#define D_FREE_PROGRAM_SPACE "Espace programme libre" - -#define D_UPGRADE_BY_WEBSERVER "Mise à jour par serveur web" -#define D_OTA_URL "URL OTA" -#define D_START_UPGRADE "Lancer la mise à jour" -#define D_UPGRADE_BY_FILE_UPLOAD "Mise à jour par téléchargement fichier" -#define D_UPLOAD_STARTED "Téléchargement lancé" -#define D_UPGRADE_STARTED "Mise à jour lancée" -#define D_UPLOAD_DONE "Téléchargement terminé" -#define D_UPLOAD_ERR_1 "Aucun fichier sélectionné" -#define D_UPLOAD_ERR_2 "Espace insuffisant" -#define D_UPLOAD_ERR_3 "L'octet magique n'est pas 0xE9" -#define D_UPLOAD_ERR_4 "La taille du programme à flasher est plus grande que la taille réelle de la mémoire flash" -#define D_UPLOAD_ERR_5 "Erreur de comparaison du buffer de téléchargement" -#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer WebLog 3" -#define D_UPLOAD_ERR_7 "Téléchargement annulé" -#define D_UPLOAD_ERR_8 "Fichier invalide" -#define D_UPLOAD_ERR_9 "Fichier trop grand" -#define D_UPLOAD_ERR_10 "Erreur d'initialisation du chip RF" -#define D_UPLOAD_ERR_11 "Erreur d'effacement du chip RF" -#define D_UPLOAD_ERR_12 "Erreur d'accès en écriture au chip RF" -#define D_UPLOAD_ERR_13 "Erreur de décodage du firmware RF" -#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement" - -#define D_ENTER_COMMAND "Saisir une commande" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer WebLog 2 si une réponse est attendue" -#define D_NEED_USER_AND_PASSWORD "Nécessite utilisateur=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Vérification d'empreinte TLS ..." -#define D_TLS_CONNECT_FAILED_TO "Échec de connexion TLS à" -#define D_RETRY_IN "Nouvelle tentative dans" -#define D_VERIFIED "Vérifié par empreinte " -#define D_INSECURE "Connexion non sécurisée car empreinte non vérifiée" -#define D_CONNECT_FAILED_TO "Échec de connexion à" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast désactivé" -#define D_MULTICAST_REJOINED "Multicast (re)joint" -#define D_MULTICAST_JOIN_FAILED "Multicast échec abonnement" -#define D_FAILED_TO_SEND_RESPONSE "Échec d'envoi réponse" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "Réglage WeMo" -#define D_RESPONSE_SENT "Réponse envoyée" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Réglage Hue" -#define D_HUE_API_NOT_IMPLEMENTED "API Hue non implémentée" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 paquets de réponse envoyés" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Paramètres Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Puissance,Énergie" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Compteur/PM1" - #define D_DOMOTICZ_VOLTAGE "Tension/PM2,5" - #define D_DOMOTICZ_CURRENT "Courant/PM10" - #define D_DOMOTICZ_AIRQUALITY "Qualité de l'air" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Durée de rafraichissement" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configuration des Timers" -#define D_TIMER_PARAMETERS "Paramètres Timer" -#define D_TIMER_ENABLE "Activer les Timers" -#define D_TIMER_ARM "Armer" -#define D_TIMER_TIME "Temps" -#define D_TIMER_DAYS "Jours" -#define D_TIMER_REPEAT "Répéter" -#define D_TIMER_OUTPUT "Sortie" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configuration de KNX" -#define D_KNX_PARAMETERS "Paramètres KNX" -#define D_KNX_GENERAL_CONFIG "Général" -#define D_KNX_PHYSICAL_ADDRESS "Adresse individuelle" // Backbone/Line/Device -> Zone/Ligne/Participant -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Doit être unique sur le réseau KNX)" -#define D_KNX_ENABLE "Activer KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Données à envoyer aux Adresses de Groupe" -#define D_ADD "Ajoûter" -#define D_DELETE "Supprimer" -#define D_REPLY "Répondre" -#define D_KNX_GROUP_ADDRESS_TO_READ "Données à recevoir des Adresses de Groupe" -#define D_RECEIVED_FROM "Reçu de" -#define D_KNX_COMMAND_WRITE "Écrire" -#define D_KNX_COMMAND_READ "Lire" -#define D_KNX_COMMAND_OTHER "Autre" -#define D_SENT_TO "envoyé à" -#define D_KNX_WARNING "L'Adresse de Groupe (0/0/0) est réservée et ne peut être utilisée." -#define D_KNX_ENHANCEMENT "Amélioration de la communication" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xsns_03_energy.ino -#define D_ENERGY_TODAY "Énergie aujourd'hui" -#define D_ENERGY_YESTERDAY "Énergie hier" -#define D_ENERGY_TOTAL "Énergie totale" - -// xdrv_27_shutter.ino -#define D_OPEN "Ouvert" -#define D_CLOSE "Fermé" -#define D_DOMOTICZ_SHUTTER "Volet" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configurer PCF8574" -#define D_PCF8574_PARAMETERS "Paramètres PCF8574" -#define D_INVERT_PORTS "Inverser les Ports" -#define D_DEVICE "Module" -#define D_DEVICE_INPUT "Entrée" -#define D_DEVICE_OUTPUT "Sortie" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Capteur occupé" -#define D_SENSOR_CRC_ERROR "Erreur CRC capteur" -#define D_SENSORS_FOUND "Capteur trouvé" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Expiration du délai" -#define D_START_SIGNAL_LOW "Signal Start bas" -#define D_START_SIGNAL_HIGH "Signal Start haut" -#define D_PULSE "Impulsion" -#define D_CHECKSUM_FAILURE "Erreur checksum" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Le capteur n'a pas acquitté la commande" -#define D_SHT1X_FOUND "SHT1X found" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particules" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accél. Axe-X" -#define D_AY_AXIS "Accél. Axe-Y" -#define D_AZ_AXIS "Accél. Axe-Z" -#define D_GX_AXIS "Gyro Axe-X" -#define D_GY_AXIS "Gyro Axe-Y" -#define D_GZ_AXIS "Gyro Axe-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Retirer la charge" -#define D_HX_CAL_REFERENCE "Charger l'étalon de poids" -#define D_HX_CAL_DONE "Étalonné" -#define D_HX_CAL_FAIL "L'étalonnage a échoué" -#define D_RESET_HX711 "Réinitialiser le capteur" -#define D_CONFIGURE_HX711 "Configurer le capteur" -#define D_HX711_PARAMETERS "Paramètres capteur" -#define D_ITEM_WEIGHT "Poids de l'objet" -#define D_REFERENCE_WEIGHT "Poids de référence" -#define D_CALIBRATE "Étalonner" -#define D_CALIBRATION "Étalonnage" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direction du vent" -#define D_TX20_WIND_SPEED "Vitesse du vent" -#define D_TX20_WIND_SPEED_AVG "Vitesse Moy." -#define D_TX20_WIND_SPEED_MAX "Vitesse Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Aucun" -#define D_SENSOR_USER "Utilisateur" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "ÉmetIR" -#define D_SENSOR_SWITCH "Inter." // Suffix "1" -#define D_SENSOR_BUTTON "Bouton" // Suffix "1" -#define D_SENSOR_RELAY "Relais" // Suffix "1i" -#define D_SENSOR_LED "LED" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Compteur" // Suffix "1" -#define D_SENSOR_IRRECV "RécptIR" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "RétroÉcl" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "gal/mn" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" -#define D_UNIT_KILOOHM "kΩ" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "mn" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "secteurs" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Angle de phase" -#define D_IMPORT_ACTIVE "Énergie act conso" -#define D_EXPORT_ACTIVE "Énergie act fournie" -#define D_IMPORT_REACTIVE "Énergie réa conso" -#define D_EXPORT_REACTIVE "Énergie réa fournie" -#define D_TOTAL_REACTIVE "Énergie réa totale" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "°" - -//SOLAXX1 -#define D_PV1_VOLTAGE "Tension PV1" -#define D_PV1_CURRENT "Courant PV1" -#define D_PV1_POWER "Puissance PV1" -#define D_PV2_VOLTAGE "Tension PV2" -#define D_PV2_CURRENT "Courant PV2" -#define D_PV2_POWER "Puissance PV2" -#define D_SOLAR_POWER "Puissance solaire" -#define D_INVERTER_POWER "Puissance onduleur" -#define D_STATUS "Statut" -#define D_WAITING "En attente" -#define D_CHECKING "En test" -#define D_WORKING "En marche" -#define D_FAILURE "Défault" -#define D_SOLAX_ERROR_0 "Aucun code d'erreur" -#define D_SOLAX_ERROR_1 "Défaut Perte de réseau" -#define D_SOLAX_ERROR_2 "Défaut Tension réseau" -#define D_SOLAX_ERROR_3 "Défaut Fréquence réseau" -#define D_SOLAX_ERROR_4 "Défaut Tension PV" -#define D_SOLAX_ERROR_5 "Défaut Isolation" -#define D_SOLAX_ERROR_6 "Défaut Surchauffe" -#define D_SOLAX_ERROR_7 "Défaut Ventilateur" -#define D_SOLAX_ERROR_8 "Défaut Autre équipement" - -#endif // _LANGUAGE_FR_FR_H_ +/* + fr-FR.h - localization for French - France for Tasmota + + Copyright (C) 2019 Olivier Francais + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_FR_FR_H_ +#define _LANGUAGE_FR_FR_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.1.2.4 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1036 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "fr" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DimLunMarMerJeuVenSam" +#define D_MONTH3LIST "JanFevMarAvrMaiJunJulAutSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Qualité de l'Air" +#define D_AP "AP" // Access Point +#define D_AS "comme" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Nombre de boot" +#define D_BRIGHTLIGHT "Luminosité" +#define D_BSSID "BSSId" +#define D_BUTTON "Bouton" +#define D_BY "par" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "Dioxyde de carbone" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "Froid" +#define D_COMMAND "Commande" +#define D_CONNECTED "Connecté" +#define D_CORS_DOMAIN "Domaine CORS" +#define D_COUNT "Compte" +#define D_COUNTER "Compteur" +#define D_CURRENT "Courant" // As in Voltage and Current +#define D_DATA "Donnée" +#define D_DARKLIGHT "Sombre" +#define D_DEBUG "Debug" +#define D_DISABLED "Désactivé" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "Serveur DNS" +#define D_DONE "Fait" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Émulation" +#define D_ENABLED "Activé" +#define D_ERASE "Effacer" +#define D_ERROR "Erreur" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Échoué" +#define D_FALLBACK "Secours" +#define D_FALLBACK_TOPIC "Topic de secours" +#define D_FALSE "Faux" +#define D_FILE "Fichier" +#define D_FLOW_RATE "Débit" +#define D_FREE_MEMORY "Mémoire libre" +#define D_FREQUENCY "Fréquence" +#define D_GAS "Gaz" +#define D_GATEWAY "Passerelle" +#define D_GROUP "Groupe" +#define D_HOST "Hôte" +#define D_HOSTNAME "Nom d'Hôte" +#define D_HUMIDITY "Humidité" +#define D_ILLUMINANCE "Éclairement" +#define D_IMMEDIATE "immédiat" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infra-rouge" +#define D_INITIALIZED "Initialisé" +#define D_IP_ADDRESS "Adresse IP" +#define D_LIGHT "Lumière" +#define D_LWT "LWT" +#define D_MODULE "Module" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-pression" +#define D_NOISE "Bruit" +#define D_NONE "Aucun" +#define D_OFF "Arrêt" +#define D_OFFLINE "Déconnecté" +#define D_OK "Ok" +#define D_ON "Marche" +#define D_ONLINE "Connecté" +#define D_PASSWORD "Mot de passe" +#define D_PORT "Port" +#define D_POWER_FACTOR "Fact de puiss" +#define D_POWERUSAGE "Puissance" +#define D_POWERUSAGE_ACTIVE "Puiss active" +#define D_POWERUSAGE_APPARENT "Puiss apparente" +#define D_POWERUSAGE_REACTIVE "Puiss réactive" +#define D_PRESSURE "Pression" +#define D_PRESSUREATSEALEVEL "PressionMer" +#define D_PROGRAM_FLASH_SIZE "Taille Flash Programme" +#define D_PROGRAM_SIZE "Taille programme" +#define D_PROJECT "Projet" +#define D_RAIN "Pluie" +#define D_RECEIVED "Reçu" +#define D_RESTART "Redémarrage" +#define D_RESTARTING "Redémarre" +#define D_RESTART_REASON "Raison du redémarrage" +#define D_RESTORE "restaurer" +#define D_RETAINED "persistant" // MQTT +#define D_RULE "Règle" +#define D_SAVE "Enregistrer" +#define D_SENSOR "Capteur" +#define D_SSID "SSID" +#define D_START "Lancer" // "Lancer la mise à jour" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Masque sous-réseau" +#define D_SUBSCRIBE_TO "S'abonner à" +#define D_UNSUBSCRIBE_FROM "Se désabonner de" +#define D_SUCCESSFUL "Réussi" +#define D_SUNRISE "Lever du jour" +#define D_SUNSET "Tombée de la nuit" +#define D_TEMPERATURE "Température" +#define D_TO "à" +#define D_TOGGLE "Inverser" +#define D_TOPIC "Topic" // Keep MQTT keyword +#define D_TOTAL_USAGE "Eau totale" +#define D_TRANSMIT "Transmettre" +#define D_TRUE "Vrai" +#define D_TVOC "TVOC" +#define D_UPGRADE "la mise à jour" // "Lancer la mise à jour" +#define D_UPLOAD "Upload" // Not better in french +#define D_UPTIME "Durée d'activité" +#define D_USER "Utilisateur" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Indice UV" +#define D_UV_INDEX_1 "Faible" +#define D_UV_INDEX_2 "Modéré" +#define D_UV_INDEX_3 "Élevé" +#define D_UV_INDEX_4 "Très élevé" +#define D_UV_INDEX_5 "Brûlure niv.1/2" +#define D_UV_INDEX_6 "Brûlure niv.3" +#define D_UV_INDEX_7 "Hors échelle" +#define D_UV_LEVEL "Niveau UV" +#define D_UV_POWER "Puissance UV" +#define D_VERSION "Version" +#define D_VOLTAGE "Tension" +#define D_WEIGHT "Poids" +#define D_WARMLIGHT "Chaud" +#define D_WEB_SERVER "Serveur web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ATTENTION Cette version ne supporte pas les réglages persistants" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivée" +#define D_SYSLOG_LOGGING_REENABLED "Jounalisation SysLog réactivée" + +#define D_SET_BAUDRATE_TO "Définir le débit à" +#define D_RECEIVED_TOPIC "Topic reçu" // Terme MQTT +#define D_DATA_SIZE "Taille données" +#define D_ANALOG_INPUT "Analogique" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Boucle bloquée" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig ÉCHOUÉ avec status" +#define D_ACTIVE_FOR_3_MINUTES "actif pour 3 minutes" +#define D_FAILED_TO_START "Échec de démarrage" +#define D_PATCH_ISSUE_2186 "Correction 2186" +#define D_CONNECTING_TO_AP "Connexion à l'AP" +#define D_IN_MODE "en mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Échec de connexion car aucune adresse IP n'a été reçue" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Échec de connexion car l'AP ne peut-être contacté" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Échec de connexion car le mot de passe de l'AP est incorrect" +#define D_CONNECT_FAILED_AP_TIMEOUT "Échec de connexion avec l'AP, expiré" +#define D_ATTEMPTING_CONNECTION "Tentative de connexion..." +#define D_CHECKING_CONNECTION "Vérification connexion..." +#define D_QUERY_DONE "Requête terminée. Services MQTT trouvés" +#define D_MQTT_SERVICE_FOUND "Service MQTT trouvé sur" +#define D_FOUND_AT "trouvé à" +#define D_SYSLOG_HOST_NOT_FOUND "Hôte SysLog introuvable" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Enregistré en flash à" +#define D_LOADED_FROM_FLASH_AT "Chargé de la flash à" +#define D_USE_DEFAULTS "Utiliser par défaut" +#define D_ERASED_SECTOR "Secteur effacé" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL
merci de mettre à jour" +#define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur" +#define D_WITH_IP_ADDRESS "avec l'adresse IP" +#define D_WEBSERVER_STOPPED "Serveur web éteint" +#define D_FILE_NOT_FOUND "Fichier introuvable" +#define D_REDIRECTED "Redirection sur le portail captif" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager en mode Point d'Accès et Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager en mode Point d'Accès" +#define D_TRYING_TO_CONNECT "Tentative de connexion du module au réseau" + +#define D_RESTART_IN "Redémarrage dans" +#define D_SECONDS "secondes" +#define D_DEVICE_WILL_RESTART "Le module va redémarrer dans quelques secondes" +#define D_BUTTON_TOGGLE "on/off" +#define D_CONFIGURATION "Configuration" +#define D_INFORMATION "Informations" +#define D_FIRMWARE_UPGRADE "Mise à jour du Firmware" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Confirmer redémarrage" + +#define D_CONFIGURE_MODULE "Configuration du Module" +#define D_CONFIGURE_WIFI "Configuration WiFi" +#define D_CONFIGURE_MQTT "Configuration MQTT" +#define D_CONFIGURE_DOMOTICZ "Configuration Domoticz" +#define D_CONFIGURE_LOGGING "Configuration du journal" +#define D_CONFIGURE_OTHER "Autre configuration" +#define D_CONFIRM_RESET_CONFIGURATION "Confirmer la réinit. de la config." +#define D_RESET_CONFIGURATION "Configuration par défaut" +#define D_BACKUP_CONFIGURATION "Sauvegarde de la config." +#define D_RESTORE_CONFIGURATION "Restauration de la config." +#define D_MAIN_MENU "Menu principal" + +#define D_MODULE_PARAMETERS "Paramètres module" +#define D_MODULE_TYPE "Type de module" +#define D_PULLUP_ENABLE "Inter. sans pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Entrée série" +#define D_SERIAL_OUT "Sortie série" + +#define D_WIFI_PARAMETERS "Paramètres Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Scan des réseaux wifi" +#define D_SCAN_DONE "Scan terminé" +#define D_NO_NETWORKS_FOUND "Aucun réseau trouvé" +#define D_REFRESH_TO_SCAN_AGAIN "Rafraîchir pour scanner à nouveau" +#define D_DUPLICATE_ACCESSPOINT "Point d'Accès dupliqué" +#define D_SKIPPING_LOW_QUALITY "Évité car de mauvaise qualité" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "Mot de passe AP1" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "Mot de passe AP2" + +#define D_MQTT_PARAMETERS "Paramètres MQTT" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Topic complet" + +#define D_LOGGING_PARAMETERS "Paramètres du journal" +#define D_SERIAL_LOG_LEVEL "Niveau de journalisation série" +#define D_MQTT_LOG_LEVEL "Niveau de journalisation MQTT" +#define D_WEB_LOG_LEVEL "Niveau de journalisation web" +#define D_SYS_LOG_LEVEL "Niveau SysLog" +#define D_MORE_DEBUG "Plus de debug" +#define D_SYSLOG_HOST "Hôte SysLog" +#define D_SYSLOG_PORT "Port SysLog" +#define D_TELEMETRY_PERIOD "Période télémétrie" + +#define D_OTHER_PARAMETERS "Autres paramètres" +#define D_TEMPLATE "Modèle" +#define D_ACTIVATE "Activer" +#define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin" +#define D_MQTT_ENABLE "MQTT activé" +#define D_FRIENDLY_NAME "Surnom" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "module unique" +#define D_MULTI_DEVICE "multi module" + +#define D_CONFIGURE_TEMPLATE "Configuration du modèle" +#define D_TEMPLATE_PARAMETERS "Paramètres du modèle" +#define D_TEMPLATE_NAME "Nom" +#define D_BASE_TYPE "Basé sur" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Enregistrer la configuration" +#define D_CONFIGURATION_SAVED "Configuration enregistrée" +#define D_CONFIGURATION_RESET "Configuration réinitialisée" + +#define D_PROGRAM_VERSION "Version du programme" +#define D_BUILD_DATE_AND_TIME "Date & Heure de build" +#define D_CORE_AND_SDK_VERSION "Version Core/SDK" +#define D_FLASH_WRITE_COUNT "Compteur écriture flash" +#define D_MAC_ADDRESS "Adresse MAC" +#define D_MQTT_HOST "Hôte MQTT" +#define D_MQTT_PORT "Port MQTT" +#define D_MQTT_CLIENT "Client MQTT" +#define D_MQTT_USER "Utilisateur MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Groupe topic MQTT" +#define D_MQTT_FULL_TOPIC "Topic complet MQTT" +#define D_MDNS_DISCOVERY "Découverte mDNS" +#define D_MDNS_ADVERTISE "Annonce mDNS" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Taille flash" +#define D_FREE_PROGRAM_SPACE "Espace programme libre" + +#define D_UPGRADE_BY_WEBSERVER "Mise à jour par serveur web" +#define D_OTA_URL "URL OTA" +#define D_START_UPGRADE "Lancer la mise à jour" +#define D_UPGRADE_BY_FILE_UPLOAD "Mise à jour par téléchargement fichier" +#define D_UPLOAD_STARTED "Téléchargement lancé" +#define D_UPGRADE_STARTED "Mise à jour lancée" +#define D_UPLOAD_DONE "Téléchargement terminé" +#define D_UPLOAD_ERR_1 "Aucun fichier sélectionné" +#define D_UPLOAD_ERR_2 "Espace insuffisant" +#define D_UPLOAD_ERR_3 "L'octet magique n'est pas 0xE9" +#define D_UPLOAD_ERR_4 "La taille du programme à flasher est plus grande que la taille réelle de la mémoire flash" +#define D_UPLOAD_ERR_5 "Erreur de comparaison du buffer de téléchargement" +#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer WebLog 3" +#define D_UPLOAD_ERR_7 "Téléchargement annulé" +#define D_UPLOAD_ERR_8 "Fichier invalide" +#define D_UPLOAD_ERR_9 "Fichier trop grand" +#define D_UPLOAD_ERR_10 "Erreur d'initialisation du chip RF" +#define D_UPLOAD_ERR_11 "Erreur d'effacement du chip RF" +#define D_UPLOAD_ERR_12 "Erreur d'accès en écriture au chip RF" +#define D_UPLOAD_ERR_13 "Erreur de décodage du firmware RF" +#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement" + +#define D_ENTER_COMMAND "Saisir une commande" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer WebLog 2 si une réponse est attendue" +#define D_NEED_USER_AND_PASSWORD "Nécessite utilisateur=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Vérification d'empreinte TLS ..." +#define D_TLS_CONNECT_FAILED_TO "Échec de connexion TLS à" +#define D_RETRY_IN "Nouvelle tentative dans" +#define D_VERIFIED "Vérifié par empreinte " +#define D_INSECURE "Connexion non sécurisée car empreinte non vérifiée" +#define D_CONNECT_FAILED_TO "Échec de connexion à" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast désactivé" +#define D_MULTICAST_REJOINED "Multicast (re)joint" +#define D_MULTICAST_JOIN_FAILED "Multicast échec abonnement" +#define D_FAILED_TO_SEND_RESPONSE "Échec d'envoi réponse" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "Réglage WeMo" +#define D_RESPONSE_SENT "Réponse envoyée" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Réglage Hue" +#define D_HUE_API_NOT_IMPLEMENTED "API Hue non implémentée" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 paquets de réponse envoyés" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Paramètres Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Puissance,Énergie" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Compteur/PM1" + #define D_DOMOTICZ_VOLTAGE "Tension/PM2,5" + #define D_DOMOTICZ_CURRENT "Courant/PM10" + #define D_DOMOTICZ_AIRQUALITY "Qualité de l'air" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Durée de rafraichissement" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configuration des Timers" +#define D_TIMER_PARAMETERS "Paramètres Timer" +#define D_TIMER_ENABLE "Activer les Timers" +#define D_TIMER_ARM "Armer" +#define D_TIMER_TIME "Temps" +#define D_TIMER_DAYS "Jours" +#define D_TIMER_REPEAT "Répéter" +#define D_TIMER_OUTPUT "Sortie" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configuration de KNX" +#define D_KNX_PARAMETERS "Paramètres KNX" +#define D_KNX_GENERAL_CONFIG "Général" +#define D_KNX_PHYSICAL_ADDRESS "Adresse individuelle" // Backbone/Line/Device -> Zone/Ligne/Participant +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Doit être unique sur le réseau KNX)" +#define D_KNX_ENABLE "Activer KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Données à envoyer aux Adresses de Groupe" +#define D_ADD "Ajoûter" +#define D_DELETE "Supprimer" +#define D_REPLY "Répondre" +#define D_KNX_GROUP_ADDRESS_TO_READ "Données à recevoir des Adresses de Groupe" +#define D_RECEIVED_FROM "Reçu de" +#define D_KNX_COMMAND_WRITE "Écrire" +#define D_KNX_COMMAND_READ "Lire" +#define D_KNX_COMMAND_OTHER "Autre" +#define D_SENT_TO "envoyé à" +#define D_KNX_WARNING "L'Adresse de Groupe (0/0/0) est réservée et ne peut être utilisée." +#define D_KNX_ENHANCEMENT "Amélioration de la communication" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xsns_03_energy.ino +#define D_ENERGY_TODAY "Énergie aujourd'hui" +#define D_ENERGY_YESTERDAY "Énergie hier" +#define D_ENERGY_TOTAL "Énergie totale" + +// xdrv_27_shutter.ino +#define D_OPEN "Ouvert" +#define D_CLOSE "Fermé" +#define D_DOMOTICZ_SHUTTER "Volet" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configurer PCF8574" +#define D_PCF8574_PARAMETERS "Paramètres PCF8574" +#define D_INVERT_PORTS "Inverser les Ports" +#define D_DEVICE "Module" +#define D_DEVICE_INPUT "Entrée" +#define D_DEVICE_OUTPUT "Sortie" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Capteur occupé" +#define D_SENSOR_CRC_ERROR "Erreur CRC capteur" +#define D_SENSORS_FOUND "Capteur trouvé" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Expiration du délai" +#define D_START_SIGNAL_LOW "Signal Start bas" +#define D_START_SIGNAL_HIGH "Signal Start haut" +#define D_PULSE "Impulsion" +#define D_CHECKSUM_FAILURE "Erreur checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Le capteur n'a pas acquitté la commande" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particules" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accél. Axe-X" +#define D_AY_AXIS "Accél. Axe-Y" +#define D_AZ_AXIS "Accél. Axe-Z" +#define D_GX_AXIS "Gyro Axe-X" +#define D_GY_AXIS "Gyro Axe-Y" +#define D_GZ_AXIS "Gyro Axe-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Retirer la charge" +#define D_HX_CAL_REFERENCE "Charger l'étalon de poids" +#define D_HX_CAL_DONE "Étalonné" +#define D_HX_CAL_FAIL "L'étalonnage a échoué" +#define D_RESET_HX711 "Réinitialiser le capteur" +#define D_CONFIGURE_HX711 "Configurer le capteur" +#define D_HX711_PARAMETERS "Paramètres capteur" +#define D_ITEM_WEIGHT "Poids de l'objet" +#define D_REFERENCE_WEIGHT "Poids de référence" +#define D_CALIBRATE "Étalonner" +#define D_CALIBRATION "Étalonnage" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direction du vent" +#define D_TX20_WIND_SPEED "Vitesse du vent" +#define D_TX20_WIND_SPEED_AVG "Vitesse Moy." +#define D_TX20_WIND_SPEED_MAX "Vitesse Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Aucun" +#define D_SENSOR_USER "Utilisateur" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "ÉmetIR" +#define D_SENSOR_SWITCH "Inter." // Suffix "1" +#define D_SENSOR_BUTTON "Bouton" // Suffix "1" +#define D_SENSOR_RELAY "Relais" // Suffix "1i" +#define D_SENSOR_LED "LED" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Compteur" // Suffix "1" +#define D_SENSOR_IRRECV "RécptIR" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "RétroÉcl" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "gal/mn" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "mn" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "secteurs" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Angle de phase" +#define D_IMPORT_ACTIVE "Énergie act conso" +#define D_EXPORT_ACTIVE "Énergie act fournie" +#define D_IMPORT_REACTIVE "Énergie réa conso" +#define D_EXPORT_REACTIVE "Énergie réa fournie" +#define D_TOTAL_REACTIVE "Énergie réa totale" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "°" + +//SOLAXX1 +#define D_PV1_VOLTAGE "Tension PV1" +#define D_PV1_CURRENT "Courant PV1" +#define D_PV1_POWER "Puissance PV1" +#define D_PV2_VOLTAGE "Tension PV2" +#define D_PV2_CURRENT "Courant PV2" +#define D_PV2_POWER "Puissance PV2" +#define D_SOLAR_POWER "Puissance solaire" +#define D_INVERTER_POWER "Puissance onduleur" +#define D_STATUS "Statut" +#define D_WAITING "En attente" +#define D_CHECKING "En test" +#define D_WORKING "En marche" +#define D_FAILURE "Défault" +#define D_SOLAX_ERROR_0 "Aucun code d'erreur" +#define D_SOLAX_ERROR_1 "Défaut Perte de réseau" +#define D_SOLAX_ERROR_2 "Défaut Tension réseau" +#define D_SOLAX_ERROR_3 "Défaut Fréquence réseau" +#define D_SOLAX_ERROR_4 "Défaut Tension PV" +#define D_SOLAX_ERROR_5 "Défaut Isolation" +#define D_SOLAX_ERROR_6 "Défaut Surchauffe" +#define D_SOLAX_ERROR_7 "Défaut Ventilateur" +#define D_SOLAX_ERROR_8 "Défaut Autre équipement" + +#endif // _LANGUAGE_FR_FR_H_ diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index 869c31fb7..ac4dadb8e 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -1,703 +1,701 @@ -/* - he-HE.h - localization for Hebrew - Israel for Tasmota - - Copyright (C) 2019 Yuval Mejahez - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_HE_HE_H_ -#define _LANGUAGE_HE_HE_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.14.0b -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1037 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "he" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "SunMonTueWedThuFriSat" -#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "מנהל" -#define D_AIR_QUALITY "איכות אוויר" -#define D_AP "AP" // Access Point -#define D_AS "-כ" -#define D_AUTO "אוטומטי" -#define D_BLINK "מהבהב" -#define D_BLINKOFF "כיבוי היבהוב" -#define D_BOOT_COUNT "מונה הפעלה מחדש" -#define D_BRIGHTLIGHT "בהירות" -#define D_BSSID "BSSId" -#define D_BUTTON "לחצן" -#define D_BY "על ידי" // Written by me -#define D_BYTES "בייט" -#define D_CELSIUS "צלזיוס" -#define D_CHANNEL "ערוץ" -#define D_CO2 "פחמן דו חמצני" -#define D_CODE "קוד" // Button code -#define D_COLDLIGHT "אור קר" -#define D_COMMAND "פקודה" -#define D_CONNECTED "מחובר" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "סופר" -#define D_COUNTER "מונה" -#define D_CURRENT "נוכחי" // As in Voltage and Current -#define D_DATA "נתונים" -#define D_DARKLIGHT "חושך" -#define D_DEBUG "באגים" -#define D_DISABLED "מבוטל" -#define D_DISTANCE "מרחק" -#define D_DNS_SERVER "DNS שרת" -#define D_DONE "סיים" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "הדמיה" -#define D_ENABLED "מאופשר" -#define D_ERASE "מחיקה" -#define D_ERROR "שגיאה" -#define D_FAHRENHEIT "פרנהייט" -#define D_FAILED "נכשל" -#define D_FALLBACK "חזרה" -#define D_FALLBACK_TOPIC "נושא לחזרה" -#define D_FALSE "שגוי" -#define D_FILE "קובץ" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "זכרון פנוי" -#define D_FREQUENCY "תדר" -#define D_GAS "גז" -#define D_GATEWAY "שער" -#define D_GROUP "קבוצה" -#define D_HOST "מארח" -#define D_HOSTNAME "שם מארח" -#define D_HUMIDITY "לחות" -#define D_ILLUMINANCE "רמת חשיפה" -#define D_IMMEDIATE "מידי" // Button immediate -#define D_INDEX "אינדקס" -#define D_INFO "מידע" -#define D_INFRARED "אינפרא" -#define D_INITIALIZED "מאותחל" -#define D_IP_ADDRESS "IP כתובת" -#define D_LIGHT "אור" -#define D_LWT "LWT" -#define D_MODULE "מודול" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "לחיצה מרובה" -#define D_NOISE "רעש" -#define D_NONE "כלום" -#define D_OFF "כבוי" -#define D_OFFLINE "מנותק" -#define D_OK "אוקיי" -#define D_ON "פועל" -#define D_ONLINE "מחובר" -#define D_PASSWORD "סיסמא" -#define D_PORT "פורט" -#define D_POWER_FACTOR "גורם כוח" -#define D_POWERUSAGE "כוח" -#define D_POWERUSAGE_ACTIVE "כוח פעיל" -#define D_POWERUSAGE_APPARENT "כוח לכאורה" -#define D_POWERUSAGE_REACTIVE "כוח תגובתי" -#define D_PRESSURE "לחץ" -#define D_PRESSUREATSEALEVEL "לחץ ימי" -#define D_PROGRAM_FLASH_SIZE "גודל תוכנית פלאש" -#define D_PROGRAM_SIZE "גודל תוכנית" -#define D_PROJECT "פרויקט" -#define D_RAIN "גשם" -#define D_RECEIVED "התקבל" -#define D_RESTART "איתחול" -#define D_RESTARTING "הפעלה מחדש" -#define D_RESTART_REASON "סיבת הפעלה מחדש" -#define D_RESTORE "שחזור" -#define D_RETAINED "שמור" -#define D_RULE "חוק" -#define D_SAVE "שמירה" -#define D_SENSOR "חיישן" -#define D_SSID "SSId" -#define D_START "התחלה" -#define D_STD_TIME "STD" -#define D_STOP "עצירה" -#define D_SUBNET_MASK "רשת מסכת משנה" -#define D_SUBSCRIBE_TO "הרשם ל" -#define D_UNSUBSCRIBE_FROM "בטל רישום" -#define D_SUCCESSFUL "הצליח" -#define D_SUNRISE "זריחה" -#define D_SUNSET "שקיעה" -#define D_TEMPERATURE "טמפרטורה" -#define D_TO "ל" -#define D_TOGGLE "מתג" -#define D_TOPIC "נושא" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "עבר" -#define D_TRUE "נכון" -#define D_TVOC "TVOC" -#define D_UPGRADE "שדרוג" -#define D_UPLOAD "העלאה" -#define D_UPTIME "זמן עליה" -#define D_USER "משתמש" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV אינדקס" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" // Out of Range -#define D_UV_LEVEL "UV רמת" -#define D_UV_POWER "UV Power" -#define D_VERSION "גרסה" -#define D_VOLTAGE "מתח" -#define D_WEIGHT "משקל" -#define D_WARMLIGHT "חום" -#define D_WEB_SERVER "Web שרת" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "אזהרה גרסה זו אינה תומכת בהגדרות קבועות" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "רישום טורי מושבת" -#define D_SYSLOG_LOGGING_REENABLED "הופעל מחדש Syslog רישום" - -#define D_SET_BAUDRATE_TO "הגדר קצב שידור ל" -#define D_RECEIVED_TOPIC "Topic התקבל" -#define D_DATA_SIZE "גודל נתונים" -#define D_ANALOG_INPUT "אנלוגי" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "לולאות חסומות" -#define D_WPS_FAILED_WITH_STATUS "נכשל עם הסטטוס WPSconfig" -#define D_ACTIVE_FOR_3_MINUTES "פעיל במשך 3 דקות" -#define D_FAILED_TO_START "נכשל בנסיון להתחיל" -#define D_PATCH_ISSUE_2186 "בעית תיקון 2186" -#define D_CONNECTING_TO_AP "AP -מתחבר ל" -#define D_IN_MODE "במצב" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP החיבור נכשל מכיוון שלא התקבלה כתובת" -#define D_CONNECT_FAILED_AP_NOT_REACHED "זמין AP החיבור נכשל כיוון שאין" -#define D_CONNECT_FAILED_WRONG_PASSWORD "סיסמא שגויה , AP חיבור נכשל ל" -#define D_CONNECT_FAILED_AP_TIMEOUT "פג זמן המתנה , AP חיבור נכשל ל" -#define D_ATTEMPTING_CONNECTION "...מנסה להתחבר" -#define D_CHECKING_CONNECTION "...בודק חיבור" -#define D_QUERY_DONE "MQTT השאילתה נעשתה. נמצאו שירותי" -#define D_MQTT_SERVICE_FOUND "MQTT נמצאו שירותי" -#define D_FOUND_AT "נמצא ב" -#define D_SYSLOG_HOST_NOT_FOUND "לא נמצא Syslog מארח" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "נשמר לפלאש ב" -#define D_LOADED_FROM_FLASH_AT "נטען מהפלאש מ" -#define D_USE_DEFAULTS "השתמש בהגדרות ברירת המחדל" -#define D_ERASED_SECTOR "סקטור מחוק" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "JavaScript - כדי להשתמש בקושחת אסמוטה אנא הפעל" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "קושחה מינימלית
בבקשה אנא שדרג" -#define D_WEBSERVER_ACTIVE_ON "שרת ווב פעיל" -#define D_WITH_IP_ADDRESS "IP עם כתובת" -#define D_WEBSERVER_STOPPED "שרת ווב הופסק" -#define D_FILE_NOT_FOUND "קובץ לא נמצא" -#define D_REDIRECTED "הופנה מחדש לפורטל" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" -#define D_TRYING_TO_CONNECT "מנסה לחבר את ההתקן לרשת" - -#define D_RESTART_IN "הפעלה מחדש תוך" -#define D_SECONDS "שניות" -#define D_DEVICE_WILL_RESTART "ההתקן יופעל מחדש בעוד מס' שניות" -#define D_BUTTON_TOGGLE "מצב" -#define D_CONFIGURATION "הגדרות" -#define D_INFORMATION "מידע" -#define D_FIRMWARE_UPGRADE "שדרוג קושחה" -#define D_CONSOLE "קונסול" -#define D_CONFIRM_RESTART "אישור הפעלה מחדש" - -#define D_CONFIGURE_MODULE "הגדרות מודול" -#define D_CONFIGURE_WIFI "WIFI הגדרות" -#define D_CONFIGURE_MQTT "MQTT הגדרות" -#define D_CONFIGURE_DOMOTICZ "Domoticz הגדרות" -#define D_CONFIGURE_LOGGING "הגדרת לוגים" -#define D_CONFIGURE_OTHER "הגדרות שונות" -#define D_CONFIRM_RESET_CONFIGURATION "אישור שינוי הגדרות" -#define D_RESET_CONFIGURATION "אתחול הגדרות" -#define D_BACKUP_CONFIGURATION "גיבוי הגדרות" -#define D_RESTORE_CONFIGURATION "שחזור הגדרות" -#define D_MAIN_MENU "תפריט ראשי" - -#define D_MODULE_PARAMETERS "מודול פרמטרים" -#define D_MODULE_TYPE "סוג מודול" -#define D_PULLUP_ENABLE "pull-up אין לחצן/מתג" -#define D_ADC "ADC" -#define D_GPIO " רגל " -#define D_SERIAL_IN "כניסת סריאל" -#define D_SERIAL_OUT "יציאת סריאל" - -#define D_WIFI_PARAMETERS "Wifi פרמטרים" -#define D_SCAN_FOR_WIFI_NETWORKS "סורק עבור רשתות אלחוטיות" -#define D_SCAN_DONE "סריקה הושלמה" -#define D_NO_NETWORKS_FOUND "לא נמצאו רשתות אלחוטיות" -#define D_REFRESH_TO_SCAN_AGAIN "רענן כדי לסרוק שוב" -#define D_DUPLICATE_ACCESSPOINT "נקודות גישה משוכפלות" -#define D_SKIPPING_LOW_QUALITY "מדלג עקב איכות רשת נמוכה" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Password" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Password" - -#define D_MQTT_PARAMETERS "MQTT פרמטרים" -#define D_CLIENT "לקוח" -#define D_FULL_TOPIC "זיהוי מלא" - -#define D_LOGGING_PARAMETERS "פרמטרי לוגים" -#define D_SERIAL_LOG_LEVEL "רמת לוג עבור סריאל" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "רמת לוג עבור אתר" -#define D_SYS_LOG_LEVEL "Syslog רמת לוג עבור שרת" -#define D_MORE_DEBUG "מיפוי נוסף" -#define D_SYSLOG_HOST "Syslog מארח" -#define D_SYSLOG_PORT "Syslog פורט" -#define D_TELEMETRY_PERIOD "זמן שידור" - -#define D_OTHER_PARAMETERS "פרמטרים שונים" -#define D_TEMPLATE "תבנית" -#define D_ACTIVATE "הפעל" -#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל" -#define D_MQTT_ENABLE "MQTT אפשר" -#define D_FRIENDLY_NAME "שם ידידותי" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "התקן בודד" -#define D_MULTI_DEVICE "התקנים" - -#define D_CONFIGURE_TEMPLATE "הגדר תבנית" -#define D_TEMPLATE_PARAMETERS "פרמטרים של תבנית" -#define D_TEMPLATE_NAME "שם" -#define D_BASE_TYPE "מבוסס על" -#define D_TEMPLATE_FLAGS "אפשריות" - -#define D_SAVE_CONFIGURATION "שמירת הגדרות" -#define D_CONFIGURATION_SAVED "הגדרות נשמרו" -#define D_CONFIGURATION_RESET "איפוס הגדרות" - -#define D_PROGRAM_VERSION "גירסת תוכנה" -#define D_BUILD_DATE_AND_TIME "Build Date & Time" -#define D_CORE_AND_SDK_VERSION "Core/SDK Version" -#define D_FLASH_WRITE_COUNT "מונה צריבות" -#define D_MAC_ADDRESS "MAC כתובת" -#define D_MQTT_HOST "MQTT מארח" -#define D_MQTT_PORT "MQTT פורט" -#define D_MQTT_CLIENT "MQTT לקוח" -#define D_MQTT_USER "MQTT שם משתמש" -#define D_MQTT_TOPIC "MQTT נושא" -#define D_MQTT_GROUP_TOPIC "MQTT נושא קבוצת" -#define D_MQTT_FULL_TOPIC "MQTT נושא מלא" -#define D_MDNS_DISCOVERY "mDNS זיהוי" -#define D_MDNS_ADVERTISE "mDNS פרסום" -#define D_ESP_CHIP_ID "ESP מס' רכיב" -#define D_FLASH_CHIP_ID "מס' רכיב פלאש" -#define D_FLASH_CHIP_SIZE "גודל זיכרון פלאש" -#define D_FREE_PROGRAM_SPACE "מקום פנוי - תוכנה" - -#define D_UPGRADE_BY_WEBSERVER "שדרוג קושחה" -#define D_OTA_URL "OTA כתובת" -#define D_START_UPGRADE "התחל בשדרוג" -#define D_UPGRADE_BY_FILE_UPLOAD "שדרוג דרך קובץ נכשל" -#define D_UPLOAD_STARTED "העלאה מתחילה" -#define D_UPGRADE_STARTED "שדרוג מתחיל" -#define D_UPLOAD_DONE "העלאה הסתיימה" -#define D_UPLOAD_ERR_1 "לא נבחר קובץ" -#define D_UPLOAD_ERR_2 "אין מספיק מקום" -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" -#define D_UPLOAD_ERR_4 "גודל קובץ השדרוג גדול מנפח האחסון של הפלאש" -#define D_UPLOAD_ERR_5 "מאגר העלאה לא תקין" -#define D_UPLOAD_ERR_6 "העלאה נכשלה. אפשר רישום 3" -#define D_UPLOAD_ERR_7 "ההעלאה בוטלה" -#define D_UPLOAD_ERR_8 "קובץ שגוי" -#define D_UPLOAD_ERR_9 "קובץ גדול מדי" -#define D_UPLOAD_ERR_10 "נכשלה RF הפעלת שבב" -#define D_UPLOAD_ERR_11 "נכשלה RF מחיקת שבב" -#define D_UPLOAD_ERR_12 "נכשלה RF כתיבת שבב" -#define D_UPLOAD_ERR_13 "נכשלה RF קידוד קושחת שבב" -#define D_UPLOAD_ERROR_CODE "שגיאת קוד העלאה" - -#define D_ENTER_COMMAND "הקש פקודה" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" -#define D_NEED_USER_AND_PASSWORD "Need user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "...TLS אמת טביעת אצבע של" -#define D_TLS_CONNECT_FAILED_TO "נכשל TLS חיבור" -#define D_RETRY_IN "נסה שוב תוך" -#define D_VERIFIED "מאומת באמצעות טביעת אצבע" -#define D_INSECURE "חיבור לא מאובטח עקב טביעת אצבע לא חוקית" -#define D_CONNECT_FAILED_TO "חיבור נכשל ל" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast disabled" -#define D_MULTICAST_REJOINED "Multicast (re)joined" -#define D_MULTICAST_JOIN_FAILED "Multicast join failed" -#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo הגדרת" -#define D_RESPONSE_SENT "תגובה נשלחה" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue הגדרת" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz פרמטרי" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "טמפרטורה" - #define D_DOMOTICZ_TEMP_HUM "טמפרטורה,לחות" - #define D_DOMOTICZ_TEMP_HUM_BARO "טמפרטורה,לחות,ברומטר" - #define D_DOMOTICZ_POWER_ENERGY "הספק,צריכה" - #define D_DOMOTICZ_ILLUMINANCE "עוצמת אור" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "איכות אוויר" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "עדכן טיימר" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "הגדרות תזמון" -#define D_TIMER_PARAMETERS "פרמטרים עבור תזמון" -#define D_TIMER_ENABLE "אפשר תזמון" -#define D_TIMER_ARM "טען" -#define D_TIMER_TIME "זמן" -#define D_TIMER_DAYS "ימים" -#define D_TIMER_REPEAT "חזרות" -#define D_TIMER_OUTPUT "פלט" -#define D_TIMER_ACTION "פעולה" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX הגדר" -#define D_KNX_PARAMETERS "KNX פרמטרי" -#define D_KNX_GENERAL_CONFIG "כללי" -#define D_KNX_PHYSICAL_ADDRESS "כתובת פיזית" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "KNX אפשר" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "נתונים לשליחה אל כתובות קבוצתיות" -#define D_ADD "הוסף" -#define D_DELETE "מחק" -#define D_REPLY "השב" -#define D_KNX_GROUP_ADDRESS_TO_READ "כתובות קבוצתיות לקבלת נתונים מ" -#define D_RECEIVED_FROM "התקבל מאת" -#define D_KNX_COMMAND_WRITE "כתיבה" -#define D_KNX_COMMAND_READ "קריאה" -#define D_KNX_COMMAND_OTHER "אחר" -#define D_SENT_TO "נשלח ל" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "שיפור התקשורת" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "צריכה יומית" -#define D_ENERGY_YESTERDAY "צריכה בעבר" -#define D_ENERGY_TOTAL "צריכה כללית" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "שרת עסוק" -#define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת" -#define D_SENSORS_FOUND "חיישנים לא נמצאו" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "הזמן הקצוב להמתנה" -#define D_START_SIGNAL_LOW "להתחיל אות נמוך" -#define D_START_SIGNAL_HIGH "להתחיל אות גבוה" -#define D_PULSE "פעימה" -#define D_CHECKSUM_FAILURE "בדיקת כשל נכשלה" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" -#define D_SHT1X_FOUND "SHT1X found" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "חלקיקים" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "הסר משקל" -#define D_HX_CAL_REFERENCE "טען משקל התייחסות" -#define D_HX_CAL_DONE "מכויל" -#define D_HX_CAL_FAIL "כיול נכשל" -#define D_RESET_HX711 "אפס את קנה המידה" -#define D_CONFIGURE_HX711 "הגדר קנה מידה" -#define D_HX711_PARAMETERS "פרמטרים של קנה מידה" -#define D_ITEM_WEIGHT "משקל פריט" -#define D_REFERENCE_WEIGHT "משקל הפניה" -#define D_CALIBRATE "כייל" -#define D_CALIBRATION "כיול" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "כיוון הרוח" -#define D_TX20_WIND_SPEED "מהירות הרוח" -#define D_TX20_WIND_SPEED_AVG "מהירות הרוח ממוצעת" -#define D_TX20_WIND_SPEED_MAX "מהירות הרוח מקסימלית" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "משתמש" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "נגן מוזיקה" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "מתג" // Suffix "1" -#define D_SENSOR_BUTTON "לחצן" // Suffix "1" -#define D_SENSOR_RELAY "ממסר" // Suffix "1i" -#define D_SENSOR_LED "לד" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "מונה" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_HE_HE_H_ +/* + he-HE.h - localization for Hebrew - Israel for Tasmota + + Copyright (C) 2019 Yuval Mejahez + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_HE_HE_H_ +#define _LANGUAGE_HE_HE_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.14.0b +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1037 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "he" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "SunMonTueWedThuFriSat" +#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "מנהל" +#define D_AIR_QUALITY "איכות אוויר" +#define D_AP "AP" // Access Point +#define D_AS "-כ" +#define D_AUTO "אוטומטי" +#define D_BLINK "מהבהב" +#define D_BLINKOFF "כיבוי היבהוב" +#define D_BOOT_COUNT "מונה הפעלה מחדש" +#define D_BRIGHTLIGHT "בהירות" +#define D_BSSID "BSSId" +#define D_BUTTON "לחצן" +#define D_BY "על ידי" // Written by me +#define D_BYTES "בייט" +#define D_CELSIUS "צלזיוס" +#define D_CHANNEL "ערוץ" +#define D_CO2 "פחמן דו חמצני" +#define D_CODE "קוד" // Button code +#define D_COLDLIGHT "אור קר" +#define D_COMMAND "פקודה" +#define D_CONNECTED "מחובר" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "סופר" +#define D_COUNTER "מונה" +#define D_CURRENT "נוכחי" // As in Voltage and Current +#define D_DATA "נתונים" +#define D_DARKLIGHT "חושך" +#define D_DEBUG "באגים" +#define D_DISABLED "מבוטל" +#define D_DISTANCE "מרחק" +#define D_DNS_SERVER "DNS שרת" +#define D_DONE "סיים" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "הדמיה" +#define D_ENABLED "מאופשר" +#define D_ERASE "מחיקה" +#define D_ERROR "שגיאה" +#define D_FAHRENHEIT "פרנהייט" +#define D_FAILED "נכשל" +#define D_FALLBACK "חזרה" +#define D_FALLBACK_TOPIC "נושא לחזרה" +#define D_FALSE "שגוי" +#define D_FILE "קובץ" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "זכרון פנוי" +#define D_FREQUENCY "תדר" +#define D_GAS "גז" +#define D_GATEWAY "שער" +#define D_GROUP "קבוצה" +#define D_HOST "מארח" +#define D_HOSTNAME "שם מארח" +#define D_HUMIDITY "לחות" +#define D_ILLUMINANCE "רמת חשיפה" +#define D_IMMEDIATE "מידי" // Button immediate +#define D_INDEX "אינדקס" +#define D_INFO "מידע" +#define D_INFRARED "אינפרא" +#define D_INITIALIZED "מאותחל" +#define D_IP_ADDRESS "IP כתובת" +#define D_LIGHT "אור" +#define D_LWT "LWT" +#define D_MODULE "מודול" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "לחיצה מרובה" +#define D_NOISE "רעש" +#define D_NONE "כלום" +#define D_OFF "כבוי" +#define D_OFFLINE "מנותק" +#define D_OK "אוקיי" +#define D_ON "פועל" +#define D_ONLINE "מחובר" +#define D_PASSWORD "סיסמא" +#define D_PORT "פורט" +#define D_POWER_FACTOR "גורם כוח" +#define D_POWERUSAGE "כוח" +#define D_POWERUSAGE_ACTIVE "כוח פעיל" +#define D_POWERUSAGE_APPARENT "כוח לכאורה" +#define D_POWERUSAGE_REACTIVE "כוח תגובתי" +#define D_PRESSURE "לחץ" +#define D_PRESSUREATSEALEVEL "לחץ ימי" +#define D_PROGRAM_FLASH_SIZE "גודל תוכנית פלאש" +#define D_PROGRAM_SIZE "גודל תוכנית" +#define D_PROJECT "פרויקט" +#define D_RAIN "גשם" +#define D_RECEIVED "התקבל" +#define D_RESTART "איתחול" +#define D_RESTARTING "הפעלה מחדש" +#define D_RESTART_REASON "סיבת הפעלה מחדש" +#define D_RESTORE "שחזור" +#define D_RETAINED "שמור" +#define D_RULE "חוק" +#define D_SAVE "שמירה" +#define D_SENSOR "חיישן" +#define D_SSID "SSId" +#define D_START "התחלה" +#define D_STD_TIME "STD" +#define D_STOP "עצירה" +#define D_SUBNET_MASK "רשת מסכת משנה" +#define D_SUBSCRIBE_TO "הרשם ל" +#define D_UNSUBSCRIBE_FROM "בטל רישום" +#define D_SUCCESSFUL "הצליח" +#define D_SUNRISE "זריחה" +#define D_SUNSET "שקיעה" +#define D_TEMPERATURE "טמפרטורה" +#define D_TO "ל" +#define D_TOGGLE "מתג" +#define D_TOPIC "נושא" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "עבר" +#define D_TRUE "נכון" +#define D_TVOC "TVOC" +#define D_UPGRADE "שדרוג" +#define D_UPLOAD "העלאה" +#define D_UPTIME "זמן עליה" +#define D_USER "משתמש" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV אינדקס" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range +#define D_UV_LEVEL "UV רמת" +#define D_UV_POWER "UV Power" +#define D_VERSION "גרסה" +#define D_VOLTAGE "מתח" +#define D_WEIGHT "משקל" +#define D_WARMLIGHT "חום" +#define D_WEB_SERVER "Web שרת" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "אזהרה גרסה זו אינה תומכת בהגדרות קבועות" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "רישום טורי מושבת" +#define D_SYSLOG_LOGGING_REENABLED "הופעל מחדש Syslog רישום" + +#define D_SET_BAUDRATE_TO "הגדר קצב שידור ל" +#define D_RECEIVED_TOPIC "Topic התקבל" +#define D_DATA_SIZE "גודל נתונים" +#define D_ANALOG_INPUT "אנלוגי" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "לולאות חסומות" +#define D_WPS_FAILED_WITH_STATUS "נכשל עם הסטטוס WPSconfig" +#define D_ACTIVE_FOR_3_MINUTES "פעיל במשך 3 דקות" +#define D_FAILED_TO_START "נכשל בנסיון להתחיל" +#define D_PATCH_ISSUE_2186 "בעית תיקון 2186" +#define D_CONNECTING_TO_AP "AP -מתחבר ל" +#define D_IN_MODE "במצב" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP החיבור נכשל מכיוון שלא התקבלה כתובת" +#define D_CONNECT_FAILED_AP_NOT_REACHED "זמין AP החיבור נכשל כיוון שאין" +#define D_CONNECT_FAILED_WRONG_PASSWORD "סיסמא שגויה , AP חיבור נכשל ל" +#define D_CONNECT_FAILED_AP_TIMEOUT "פג זמן המתנה , AP חיבור נכשל ל" +#define D_ATTEMPTING_CONNECTION "...מנסה להתחבר" +#define D_CHECKING_CONNECTION "...בודק חיבור" +#define D_QUERY_DONE "MQTT השאילתה נעשתה. נמצאו שירותי" +#define D_MQTT_SERVICE_FOUND "MQTT נמצאו שירותי" +#define D_FOUND_AT "נמצא ב" +#define D_SYSLOG_HOST_NOT_FOUND "לא נמצא Syslog מארח" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "נשמר לפלאש ב" +#define D_LOADED_FROM_FLASH_AT "נטען מהפלאש מ" +#define D_USE_DEFAULTS "השתמש בהגדרות ברירת המחדל" +#define D_ERASED_SECTOR "סקטור מחוק" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "JavaScript - כדי להשתמש בקושחת אסמוטה אנא הפעל" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "קושחה מינימלית
בבקשה אנא שדרג" +#define D_WEBSERVER_ACTIVE_ON "שרת ווב פעיל" +#define D_WITH_IP_ADDRESS "IP עם כתובת" +#define D_WEBSERVER_STOPPED "שרת ווב הופסק" +#define D_FILE_NOT_FOUND "קובץ לא נמצא" +#define D_REDIRECTED "הופנה מחדש לפורטל" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" +#define D_TRYING_TO_CONNECT "מנסה לחבר את ההתקן לרשת" + +#define D_RESTART_IN "הפעלה מחדש תוך" +#define D_SECONDS "שניות" +#define D_DEVICE_WILL_RESTART "ההתקן יופעל מחדש בעוד מס' שניות" +#define D_BUTTON_TOGGLE "מצב" +#define D_CONFIGURATION "הגדרות" +#define D_INFORMATION "מידע" +#define D_FIRMWARE_UPGRADE "שדרוג קושחה" +#define D_CONSOLE "קונסול" +#define D_CONFIRM_RESTART "אישור הפעלה מחדש" + +#define D_CONFIGURE_MODULE "הגדרות מודול" +#define D_CONFIGURE_WIFI "WIFI הגדרות" +#define D_CONFIGURE_MQTT "MQTT הגדרות" +#define D_CONFIGURE_DOMOTICZ "Domoticz הגדרות" +#define D_CONFIGURE_LOGGING "הגדרת לוגים" +#define D_CONFIGURE_OTHER "הגדרות שונות" +#define D_CONFIRM_RESET_CONFIGURATION "אישור שינוי הגדרות" +#define D_RESET_CONFIGURATION "אתחול הגדרות" +#define D_BACKUP_CONFIGURATION "גיבוי הגדרות" +#define D_RESTORE_CONFIGURATION "שחזור הגדרות" +#define D_MAIN_MENU "תפריט ראשי" + +#define D_MODULE_PARAMETERS "מודול פרמטרים" +#define D_MODULE_TYPE "סוג מודול" +#define D_PULLUP_ENABLE "pull-up אין לחצן/מתג" +#define D_ADC "ADC" +#define D_GPIO " רגל " +#define D_SERIAL_IN "כניסת סריאל" +#define D_SERIAL_OUT "יציאת סריאל" + +#define D_WIFI_PARAMETERS "Wifi פרמטרים" +#define D_SCAN_FOR_WIFI_NETWORKS "סורק עבור רשתות אלחוטיות" +#define D_SCAN_DONE "סריקה הושלמה" +#define D_NO_NETWORKS_FOUND "לא נמצאו רשתות אלחוטיות" +#define D_REFRESH_TO_SCAN_AGAIN "רענן כדי לסרוק שוב" +#define D_DUPLICATE_ACCESSPOINT "נקודות גישה משוכפלות" +#define D_SKIPPING_LOW_QUALITY "מדלג עקב איכות רשת נמוכה" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Password" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Password" + +#define D_MQTT_PARAMETERS "MQTT פרמטרים" +#define D_CLIENT "לקוח" +#define D_FULL_TOPIC "זיהוי מלא" + +#define D_LOGGING_PARAMETERS "פרמטרי לוגים" +#define D_SERIAL_LOG_LEVEL "רמת לוג עבור סריאל" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "רמת לוג עבור אתר" +#define D_SYS_LOG_LEVEL "Syslog רמת לוג עבור שרת" +#define D_MORE_DEBUG "מיפוי נוסף" +#define D_SYSLOG_HOST "Syslog מארח" +#define D_SYSLOG_PORT "Syslog פורט" +#define D_TELEMETRY_PERIOD "זמן שידור" + +#define D_OTHER_PARAMETERS "פרמטרים שונים" +#define D_TEMPLATE "תבנית" +#define D_ACTIVATE "הפעל" +#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל" +#define D_MQTT_ENABLE "MQTT אפשר" +#define D_FRIENDLY_NAME "שם ידידותי" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "התקן בודד" +#define D_MULTI_DEVICE "התקנים" + +#define D_CONFIGURE_TEMPLATE "הגדר תבנית" +#define D_TEMPLATE_PARAMETERS "פרמטרים של תבנית" +#define D_TEMPLATE_NAME "שם" +#define D_BASE_TYPE "מבוסס על" +#define D_TEMPLATE_FLAGS "אפשריות" + +#define D_SAVE_CONFIGURATION "שמירת הגדרות" +#define D_CONFIGURATION_SAVED "הגדרות נשמרו" +#define D_CONFIGURATION_RESET "איפוס הגדרות" + +#define D_PROGRAM_VERSION "גירסת תוכנה" +#define D_BUILD_DATE_AND_TIME "Build Date & Time" +#define D_CORE_AND_SDK_VERSION "Core/SDK Version" +#define D_FLASH_WRITE_COUNT "מונה צריבות" +#define D_MAC_ADDRESS "MAC כתובת" +#define D_MQTT_HOST "MQTT מארח" +#define D_MQTT_PORT "MQTT פורט" +#define D_MQTT_CLIENT "MQTT לקוח" +#define D_MQTT_USER "MQTT שם משתמש" +#define D_MQTT_TOPIC "MQTT נושא" +#define D_MQTT_GROUP_TOPIC "MQTT נושא קבוצת" +#define D_MQTT_FULL_TOPIC "MQTT נושא מלא" +#define D_MDNS_DISCOVERY "mDNS זיהוי" +#define D_MDNS_ADVERTISE "mDNS פרסום" +#define D_ESP_CHIP_ID "ESP מס' רכיב" +#define D_FLASH_CHIP_ID "מס' רכיב פלאש" +#define D_FLASH_CHIP_SIZE "גודל זיכרון פלאש" +#define D_FREE_PROGRAM_SPACE "מקום פנוי - תוכנה" + +#define D_UPGRADE_BY_WEBSERVER "שדרוג קושחה" +#define D_OTA_URL "OTA כתובת" +#define D_START_UPGRADE "התחל בשדרוג" +#define D_UPGRADE_BY_FILE_UPLOAD "שדרוג דרך קובץ נכשל" +#define D_UPLOAD_STARTED "העלאה מתחילה" +#define D_UPGRADE_STARTED "שדרוג מתחיל" +#define D_UPLOAD_DONE "העלאה הסתיימה" +#define D_UPLOAD_ERR_1 "לא נבחר קובץ" +#define D_UPLOAD_ERR_2 "אין מספיק מקום" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "גודל קובץ השדרוג גדול מנפח האחסון של הפלאש" +#define D_UPLOAD_ERR_5 "מאגר העלאה לא תקין" +#define D_UPLOAD_ERR_6 "העלאה נכשלה. אפשר רישום 3" +#define D_UPLOAD_ERR_7 "ההעלאה בוטלה" +#define D_UPLOAD_ERR_8 "קובץ שגוי" +#define D_UPLOAD_ERR_9 "קובץ גדול מדי" +#define D_UPLOAD_ERR_10 "נכשלה RF הפעלת שבב" +#define D_UPLOAD_ERR_11 "נכשלה RF מחיקת שבב" +#define D_UPLOAD_ERR_12 "נכשלה RF כתיבת שבב" +#define D_UPLOAD_ERR_13 "נכשלה RF קידוד קושחת שבב" +#define D_UPLOAD_ERROR_CODE "שגיאת קוד העלאה" + +#define D_ENTER_COMMAND "הקש פקודה" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" +#define D_NEED_USER_AND_PASSWORD "Need user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "...TLS אמת טביעת אצבע של" +#define D_TLS_CONNECT_FAILED_TO "נכשל TLS חיבור" +#define D_RETRY_IN "נסה שוב תוך" +#define D_VERIFIED "מאומת באמצעות טביעת אצבע" +#define D_INSECURE "חיבור לא מאובטח עקב טביעת אצבע לא חוקית" +#define D_CONNECT_FAILED_TO "חיבור נכשל ל" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast disabled" +#define D_MULTICAST_REJOINED "Multicast (re)joined" +#define D_MULTICAST_JOIN_FAILED "Multicast join failed" +#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo הגדרת" +#define D_RESPONSE_SENT "תגובה נשלחה" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue הגדרת" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz פרמטרי" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "טמפרטורה" + #define D_DOMOTICZ_TEMP_HUM "טמפרטורה,לחות" + #define D_DOMOTICZ_TEMP_HUM_BARO "טמפרטורה,לחות,ברומטר" + #define D_DOMOTICZ_POWER_ENERGY "הספק,צריכה" + #define D_DOMOTICZ_ILLUMINANCE "עוצמת אור" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "איכות אוויר" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "עדכן טיימר" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "הגדרות תזמון" +#define D_TIMER_PARAMETERS "פרמטרים עבור תזמון" +#define D_TIMER_ENABLE "אפשר תזמון" +#define D_TIMER_ARM "טען" +#define D_TIMER_TIME "זמן" +#define D_TIMER_DAYS "ימים" +#define D_TIMER_REPEAT "חזרות" +#define D_TIMER_OUTPUT "פלט" +#define D_TIMER_ACTION "פעולה" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX הגדר" +#define D_KNX_PARAMETERS "KNX פרמטרי" +#define D_KNX_GENERAL_CONFIG "כללי" +#define D_KNX_PHYSICAL_ADDRESS "כתובת פיזית" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "KNX אפשר" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "נתונים לשליחה אל כתובות קבוצתיות" +#define D_ADD "הוסף" +#define D_DELETE "מחק" +#define D_REPLY "השב" +#define D_KNX_GROUP_ADDRESS_TO_READ "כתובות קבוצתיות לקבלת נתונים מ" +#define D_RECEIVED_FROM "התקבל מאת" +#define D_KNX_COMMAND_WRITE "כתיבה" +#define D_KNX_COMMAND_READ "קריאה" +#define D_KNX_COMMAND_OTHER "אחר" +#define D_SENT_TO "נשלח ל" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "שיפור התקשורת" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "צריכה יומית" +#define D_ENERGY_YESTERDAY "צריכה בעבר" +#define D_ENERGY_TOTAL "צריכה כללית" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "שרת עסוק" +#define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת" +#define D_SENSORS_FOUND "חיישנים לא נמצאו" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "הזמן הקצוב להמתנה" +#define D_START_SIGNAL_LOW "להתחיל אות נמוך" +#define D_START_SIGNAL_HIGH "להתחיל אות גבוה" +#define D_PULSE "פעימה" +#define D_CHECKSUM_FAILURE "בדיקת כשל נכשלה" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "חלקיקים" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "הסר משקל" +#define D_HX_CAL_REFERENCE "טען משקל התייחסות" +#define D_HX_CAL_DONE "מכויל" +#define D_HX_CAL_FAIL "כיול נכשל" +#define D_RESET_HX711 "אפס את קנה המידה" +#define D_CONFIGURE_HX711 "הגדר קנה מידה" +#define D_HX711_PARAMETERS "פרמטרים של קנה מידה" +#define D_ITEM_WEIGHT "משקל פריט" +#define D_REFERENCE_WEIGHT "משקל הפניה" +#define D_CALIBRATE "כייל" +#define D_CALIBRATION "כיול" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "כיוון הרוח" +#define D_TX20_WIND_SPEED "מהירות הרוח" +#define D_TX20_WIND_SPEED_AVG "מהירות הרוח ממוצעת" +#define D_TX20_WIND_SPEED_MAX "מהירות הרוח מקסימלית" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "משתמש" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "נגן מוזיקה" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "מתג" // Suffix "1" +#define D_SENSOR_BUTTON "לחצן" // Suffix "1" +#define D_SENSOR_RELAY "ממסר" // Suffix "1i" +#define D_SENSOR_LED "לד" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "מונה" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_HE_HE_H_ diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 9533b355b..62806fa46 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -1,703 +1,701 @@ -/* - hu-HU.h - localization for Hungarian in Hungary for Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_HU_HU_H_ -#define _LANGUAGE_HU_HU_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.12.0e -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1038 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "hu" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "." -#define D_MONTH_DAY_SEPARATOR "." -#define D_DATE_TIME_SEPARATOR " " -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "VasHétKedSzeCsüPénSzo" -#define D_MONTH3LIST "JanFebMárÁprMájJúnJúlAugSzeOktNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Levegőminőség" -#define D_AP "AP" // Access Point -#define D_AS "mint" -#define D_AUTO "AUTO" -#define D_BLINK "Villogás" -#define D_BLINKOFF "Villogás ki" -#define D_BOOT_COUNT "Újraindulások száma" -#define D_BRIGHTLIGHT "Max. fényerő" -#define D_BSSID "BSSID" -#define D_BUTTON "Gomb" -#define D_BY "by" // Written by me -#define D_BYTES "Byte-ok" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Csatorna" -#define D_CO2 "Szén-dioxid" -#define D_CODE "kód" // Button code -#define D_COLDLIGHT "Hideg fény" -#define D_COMMAND "Parancs" -#define D_CONNECTED "Csatlakoztatva" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Szám" -#define D_COUNTER "Számláló" -#define D_CURRENT "Áramerősség" // As in Voltage and Current -#define D_DATA "Adat" -#define D_DARKLIGHT "Min. fényerő" -#define D_DEBUG "Debug" -#define D_DISABLED "Letiltva" -#define D_DISTANCE "Távolság" -#define D_DNS_SERVER "DNS szerver" -#define D_DONE "Kész" -#define D_DST_TIME "nyári idő" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emuláció" -#define D_ENABLED "Engedélyezve" -#define D_ERASE "Törlés" -#define D_ERROR "Hiba" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Sikertelen" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "fallback topik" -#define D_FALSE "Hamis" -#define D_FILE "Fájl" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Szabad memória" -#define D_FREQUENCY "Frekvencia" -#define D_GAS "Gáz" -#define D_GATEWAY "Átjáró" -#define D_GROUP "Csoport" -#define D_HOST "Hoszt" -#define D_HOSTNAME "Hosztnév" -#define D_HUMIDITY "Páratartalom" -#define D_ILLUMINANCE "Megvilágítás" -#define D_IMMEDIATE "azonnali" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infravörös" -#define D_INITIALIZED "Inicializálva" -#define D_IP_ADDRESS "IP cím" -#define D_LIGHT "Fény" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "több lenyomás" -#define D_NOISE "Zaj" -#define D_NONE "nincs" -#define D_OFF "Ki" -#define D_OFFLINE "Offline" -#define D_OK "OK" -#define D_ON "Be" -#define D_ONLINE "Online" -#define D_PASSWORD "Jelszó" -#define D_PORT "Port" -#define D_POWER_FACTOR "Teljesítménytényező" -#define D_POWERUSAGE "Energiafelhasználás" -#define D_POWERUSAGE_ACTIVE "Aktív teljesítmény" -#define D_POWERUSAGE_APPARENT "Látszólagos teljesítmény" -#define D_POWERUSAGE_REACTIVE "Reaktív teljesítmény" -#define D_PRESSURE "Nyomás" -#define D_PRESSUREATSEALEVEL "Tengerszinti nyomás" -#define D_PROGRAM_FLASH_SIZE "Program flash méret" -#define D_PROGRAM_SIZE "Program méret" -#define D_PROJECT "Projekt" -#define D_RAIN "Eső" -#define D_RECEIVED "Érkezett" -#define D_RESTART "Újraindítás" -#define D_RESTARTING "Újraindítás" -#define D_RESTART_REASON "Utolsó újraindulás oka" -#define D_RESTORE "Visszaállítás" -#define D_RETAINED "retained" -#define D_RULE "Szabály" -#define D_SAVE "Mentés" -#define D_SENSOR "Szenzor" -#define D_SSID "SSID" -#define D_START "" -#define D_STD_TIME "STD" -#define D_STOP "Leállítás" -#define D_SUBNET_MASK "Alhálózati maszk" -#define D_SUBSCRIBE_TO "Feliratkozás a(z)" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Sikeres" -#define D_SUNRISE "Napkelte" -#define D_SUNSET "Napnyugta" -#define D_TEMPERATURE "Hőmérséklet" -#define D_TO "-nak" -#define D_TOGGLE "Megfordítás" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Továbbít" -#define D_TRUE "Igaz" -#define D_TVOC "TVOC" -#define D_UPGRADE "Frissítés" -#define D_UPLOAD "Feltöltés" -#define D_UPTIME "Üzemidő" -#define D_USER "Felhasználó" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV index" -#define D_UV_INDEX_1 "alacsony" -#define D_UV_INDEX_2 "közepes" -#define D_UV_INDEX_3 "magas" -#define D_UV_INDEX_4 "veszélyes" -#define D_UV_INDEX_5 "égés L1/2" -#define D_UV_INDEX_6 "égés L3" -#define D_UV_INDEX_7 "tartományon kívül" -#define D_UV_LEVEL "UV szint" -#define D_UV_POWER "UV teljesítmény" -#define D_VERSION "Verzió" -#define D_VOLTAGE "Feszültség" -#define D_WEIGHT "Tömeg" -#define D_WARMLIGHT "Meleg fény" -#define D_WEB_SERVER "Webszerver" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "VIGYÁZZ! Ez a verzió nem támogat tartós beállításokat" -#define D_LEVEL_10 "szint 1-0" -#define D_LEVEL_01 "szint 0-1" -#define D_SERIAL_LOGGING_DISABLED "Soros naplózás kikapcsolva" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logolás újraengedélyezve" - -#define D_SET_BAUDRATE_TO "Baudrate beállítása" -#define D_RECEIVED_TOPIC "Érkezett topic" -#define D_DATA_SIZE "Adatméret" -#define D_ANALOG_INPUT "Analóg" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Tiltott hurok" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig SIKERTELEN státusz:" -#define D_ACTIVE_FOR_3_MINUTES "aktválás 3 percre" -#define D_FAILED_TO_START "sikertelen indítás" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "AP-hoz csatlakozás:" -#define D_IN_MODE "mód:" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Sikertelen csatlakozás, nincs kiosztott IP cím" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Sikertelen csatlakozás, AP nem elérhető" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Sikertelen csatlakozás, hibás AP jelszó" -#define D_CONNECT_FAILED_AP_TIMEOUT "Sikertelen csatlakozás AP időtúllépés miatt" -#define D_ATTEMPTING_CONNECTION "Csatlakozás..." -#define D_CHECKING_CONNECTION "Kapcsolat ellenőrzése..." -#define D_QUERY_DONE "Lekérés kész. MQTT szolgáltatás aktív" -#define D_MQTT_SERVICE_FOUND "élő MQTT szolgáltatás a(z)" -#define D_FOUND_AT "a(z)" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog hoszt nem található" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Flash-re mentve a(z)" -#define D_LOADED_FROM_FLASH_AT "Flash-ről betöltve a(z)" -#define D_USE_DEFAULTS "Alapértelmezett beáll. használata" -#define D_ERASED_SECTOR "Szektor törlése" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" -#define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:" -#define D_WITH_IP_ADDRESS "IP cím:" -#define D_WEBSERVER_STOPPED "Webszerver leállítva" -#define D_FILE_NOT_FOUND "Fájl nem található" -#define D_REDIRECTED "Átírányítás captive portálra" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WifiManager AccessPoint(AP) és Station(ST) beállítása" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager AccessPoint(AP) beállítása" -#define D_TRYING_TO_CONNECT "Csatlakozás a hálózatra..." - -#define D_RESTART_IN "Újraindítás..." -#define D_SECONDS "másodperc" -#define D_DEVICE_WILL_RESTART "Az eszköz hamarosan újraindul..." -#define D_BUTTON_TOGGLE "Megfordítás" -#define D_CONFIGURATION "Beállítások" -#define D_INFORMATION "Információ" -#define D_FIRMWARE_UPGRADE "Firmware frissítés" -#define D_CONSOLE "Konzol" -#define D_CONFIRM_RESTART "Biztosan újraindítsam a modult?" - -#define D_CONFIGURE_MODULE "Eszközbeállítások" -#define D_CONFIGURE_WIFI "WiFi konfiguráció" -#define D_CONFIGURE_MQTT "MQTT konfiguráció" -#define D_CONFIGURE_DOMOTICZ "Domoticz konfiguráció" -#define D_CONFIGURE_LOGGING "Naplózás beállításai" -#define D_CONFIGURE_OTHER "Egyéb beállítások" -#define D_CONFIRM_RESET_CONFIGURATION "Biztosan töröljem a beállításokat?" -#define D_RESET_CONFIGURATION "Beállítások törlése" -#define D_BACKUP_CONFIGURATION "Beállítások mentése" -#define D_RESTORE_CONFIGURATION "Beállítások visszatöltése" -#define D_MAIN_MENU "Menü" - -#define D_MODULE_PARAMETERS "Modul paraméterek" -#define D_MODULE_TYPE "Alkalmazott modul" -#define D_PULLUP_ENABLE "Nincs felhúzó ellenállás" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Soros BE" -#define D_SERIAL_OUT "Soros KI" - -#define D_WIFI_PARAMETERS "WiFi paraméterek" -#define D_SCAN_FOR_WIFI_NETWORKS "WiFi hálózat keresése" -#define D_SCAN_DONE "Keresés kész" -#define D_NO_NETWORKS_FOUND "Nincs elérhető hálózat" -#define D_REFRESH_TO_SCAN_AGAIN "Frissíts az újrakereséshez" -#define D_DUPLICATE_ACCESSPOINT "Duplikált access point" -#define D_SKIPPING_LOW_QUALITY "Rossz, alacsony jelminőség" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "AP1 megosztott kulcs" -#define D_AP2_SSID "AP2 SSID" -#define D_AP2_PASSWORD "AP2 megosztott kulcs" - -#define D_MQTT_PARAMETERS "MQTT paraméterek" -#define D_CLIENT "Kliens" -#define D_FULL_TOPIC "Teljes topic" - -#define D_LOGGING_PARAMETERS "Naplózási paraméterek" -#define D_SERIAL_LOG_LEVEL "Soros naplózási szint" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web naplózási szint" -#define D_SYS_LOG_LEVEL "Syslog szint" -#define D_MORE_DEBUG "Részletes hibakeresés" -#define D_SYSLOG_HOST "Syslog hoszt" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Telemetria (mp.)" - -#define D_OTHER_PARAMETERS "Egyéb beállítások" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Web admin jelszó" -#define D_MQTT_ENABLE "MQTT engedélyezése" -#define D_FRIENDLY_NAME "Név" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Beállítások mentése" -#define D_CONFIGURATION_SAVED "Beállítások elmentve" -#define D_CONFIGURATION_RESET "Beállítások visszaállítása" - -#define D_PROGRAM_VERSION "Program verzió" -#define D_BUILD_DATE_AND_TIME "Build ideje" -#define D_CORE_AND_SDK_VERSION "Core/SDK verzió" -#define D_FLASH_WRITE_COUNT "Flash írások száma" -#define D_MAC_ADDRESS "MAC cím" -#define D_MQTT_HOST "MQTT hoszt" -#define D_MQTT_PORT "MQTT port" -#define D_MQTT_CLIENT "MQTT kliens" -#define D_MQTT_USER "MQTT felhasználó" -#define D_MQTT_TOPIC "MQTT topic" -#define D_MQTT_GROUP_TOPIC "MQTT csoport topic" -#define D_MQTT_FULL_TOPIC "MQTT teljes topic" -#define D_MDNS_DISCOVERY "mDNS láthatóság" -#define D_MDNS_ADVERTISE "mDNS hirdetés" -#define D_ESP_CHIP_ID "ESP chip ID" -#define D_FLASH_CHIP_ID "Flash chip ID" -#define D_FLASH_CHIP_SIZE "Flash mérete" -#define D_FREE_PROGRAM_SPACE "Szabad programhely" - -#define D_UPGRADE_BY_WEBSERVER "Frissítés távoli szerverről" -#define D_OTA_URL "OTA URL" -#define D_START_UPGRADE "Frissítés" -#define D_UPGRADE_BY_FILE_UPLOAD "Frissítés helyi fájllal" -#define D_UPLOAD_STARTED "Feltöltés elindítva" -#define D_UPGRADE_STARTED "Frissítés elindítva" -#define D_UPLOAD_DONE "Feltöltés kész" -#define D_UPLOAD_ERR_1 "Nincs fájl kijelölve" -#define D_UPLOAD_ERR_2 "Nincs elég memória" -#define D_UPLOAD_ERR_3 "A \"magic byte\" nem 0xE9" -#define D_UPLOAD_ERR_4 "A program flashméret nagyobb a valós flashméretnél" -#define D_UPLOAD_ERR_5 "Feltöltési buffer hiba" -#define D_UPLOAD_ERR_6 "Feltöltés sikertelen. Endegélyezd a 3. szintű naplózást" -#define D_UPLOAD_ERR_7 "Feltöltés megszakítva" -#define D_UPLOAD_ERR_8 "Érvénytelen fájl" -#define D_UPLOAD_ERR_9 "A fájl túl nagy" -#define D_UPLOAD_ERR_10 "Az RF chip inicializálása sikertelen" -#define D_UPLOAD_ERR_11 "Az RF chip törlése sikertelen" -#define D_UPLOAD_ERR_12 "Az RF chip írása sikertelen" -#define D_UPLOAD_ERR_13 "Az RF firmware dekódolása sikertelen" -#define D_UPLOAD_ERROR_CODE "Feltöltési hibakód" - -#define D_ENTER_COMMAND "Kérem a parancsot..." -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Engedélyezz 2-es szintű webnaplózást több információért" -#define D_NEED_USER_AND_PASSWORD "Szükséges a user=&password= paraméter" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "TLS fingerprint hitelesítése..." -#define D_TLS_CONNECT_FAILED_TO "TLS csatlakozás sikertelen a(z)" -#define D_RETRY_IN "Újrapróbálás" -#define D_VERIFIED "Fingerprint hitelesítve" -#define D_INSECURE "Nem biztonságos kapcsolat érvénytelen fingerprint miatt" -#define D_CONNECT_FAILED_TO "Sikertelen csatlakozás a(z)" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast kikapcsolva" -#define D_MULTICAST_REJOINED "Multicast (újra)csatlakozás" -#define D_MULTICAST_JOIN_FAILED "Multicast csatlakozás sikertelen" -#define D_FAILED_TO_SEND_RESPONSE "Nem sikerült választ küldeni" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo beállítás" -#define D_RESPONSE_SENT "Válasz elküldve" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue beállítás" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API nincs implementálva" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argumentumok" -#define D_3_RESPONSE_PACKETS_SENT "3 válaszcsomag elküldve" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz paraméterek" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Kapcsoló idx" -#define D_DOMOTICZ_SENSOR_IDX "Szenzor idx" - #define D_DOMOTICZ_TEMP "Hőmérséklet" - #define D_DOMOTICZ_TEMP_HUM "Hőmérséklet, páratartalom" - #define D_DOMOTICZ_TEMP_HUM_BARO "Hőmérséklet, páratartalom, légnyomás" - #define D_DOMOTICZ_POWER_ENERGY "Teljesítmény, energia" - #define D_DOMOTICZ_ILLUMINANCE "Fényerő" - #define D_DOMOTICZ_COUNT "Szám/PM1" - #define D_DOMOTICZ_VOLTAGE "Feszültség/PM2.5" - #define D_DOMOTICZ_CURRENT "Áram/PM10" - #define D_DOMOTICZ_AIRQUALITY "Légminőség" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Frissítési időzítő" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Időzítő beállításai" -#define D_TIMER_PARAMETERS "Időzítő paraméterei" -#define D_TIMER_ENABLE "Időzítők engedélyezve" -#define D_TIMER_ARM "Be" -#define D_TIMER_TIME "Idő" -#define D_TIMER_DAYS "Napok" -#define D_TIMER_REPEAT "Ismétlés" -#define D_TIMER_OUTPUT "Kimenet" -#define D_TIMER_ACTION "Művelet" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX beállításai" -#define D_KNX_PARAMETERS "KNX paraméterei" -#define D_KNX_GENERAL_CONFIG "Általános" -#define D_KNX_PHYSICAL_ADDRESS "Fizikai cím" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(egyedinek kell lennie a KNX hálózaton)" -#define D_KNX_ENABLE "KNX engedélyezése" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Íráshoz használt csoportcímek" -#define D_ADD "Hozzáadás" -#define D_DELETE "Törlés" -#define D_REPLY "Válasz" -#define D_KNX_GROUP_ADDRESS_TO_READ "Fogadáshoz használt csoportcímek" -#define D_RECEIVED_FROM "Fogadva tőle:" -#define D_KNX_COMMAND_WRITE "Írás" -#define D_KNX_COMMAND_READ "Olvasás" -#define D_KNX_COMMAND_OTHER "Egyáb" -#define D_SENT_TO "küldve neki:" -#define D_KNX_WARNING "A csoportcím ( 0 / 0 / 0 ) fenntartott és nem használható." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Mai energia" -#define D_ENERGY_YESTERDAY "Tegnapi energia" -#define D_ENERGY_TOTAL "Összes energia" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Szenzor foglalt" -#define D_SENSOR_CRC_ERROR "Szenzor CRC hiba" -#define D_SENSORS_FOUND "Szenzorok megtalálva" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Időtúllépés, várakozás" -#define D_START_SIGNAL_LOW "startjel alacsony" -#define D_START_SIGNAL_HIGH "startjel magas" -#define D_PULSE "impulzus" -#define D_CHECKSUM_FAILURE "Checksum hiba" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "A szenzor nem nyugtázta a parancsot" -#define D_SHT1X_FOUND "SHT1X megtalálva" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Részecskék" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Gyorsulásm. X-tengely" -#define D_AY_AXIS "Gyorsulásm. Y-tengely" -#define D_AZ_AXIS "Gyorsulásm. Z-tengely" -#define D_GX_AXIS "Giroszkóp X-tengely" -#define D_GY_AXIS "Giroszkóp Y-tengely" -#define D_GZ_AXIS "Giroszkóp Z-tengely" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Távolítsa el a súlyt" -#define D_HX_CAL_REFERENCE "Helyezze fel a referenciasúlyt" -#define D_HX_CAL_DONE "Kalibrálva" -#define D_HX_CAL_FAIL "Kalibrálási hiba" -#define D_RESET_HX711 "Skála újrabeállítása" -#define D_CONFIGURE_HX711 "Skála konfigurálása" -#define D_HX711_PARAMETERS "Skálaparaméterek" -#define D_ITEM_WEIGHT "Tárgy tömege" -#define D_REFERENCE_WEIGHT "Referenciatömeg" -#define D_CALIBRATE "Kalibrálás" -#define D_CALIBRATION "Kalibrálás" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Szélirány" -#define D_TX20_WIND_SPEED "Szélsebesség" -#define D_TX20_WIND_SPEED_AVG "Átlag szélsebesség" -#define D_TX20_WIND_SPEED_MAX "Max. szélsebesség" -#define D_TX20_NORTH "É" -#define D_TX20_EAST "K" -#define D_TX20_SOUTH "D" -#define D_TX20_WEST "NY" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Nincs" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 lejátszó" -#define D_SENSOR_IRSEND "IR adó" -#define D_SENSOR_SWITCH "Kapcsoló" // Suffix "1" -#define D_SENSOR_BUTTON "Gomb" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "LED" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Számláló" // Suffix "1" -#define D_SENSOR_IRRECV "IR vevő" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Háttérfény" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "szektorok" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Fázisszög" -#define D_IMPORT_ACTIVE "Bejövő aktív" -#define D_EXPORT_ACTIVE "Kimenő aktív" -#define D_IMPORT_REACTIVE "Bejövő reaktív" -#define D_EXPORT_REACTIVE "Kimenő reaktív" -#define D_TOTAL_REACTIVE "Összes reaktív" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "fok" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_HU_HU_H_ +/* + hu-HU.h - localization for Hungarian in Hungary for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_HU_HU_H_ +#define _LANGUAGE_HU_HU_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.12.0e +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1038 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "hu" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "." +#define D_MONTH_DAY_SEPARATOR "." +#define D_DATE_TIME_SEPARATOR " " +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "VasHétKedSzeCsüPénSzo" +#define D_MONTH3LIST "JanFebMárÁprMájJúnJúlAugSzeOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Levegőminőség" +#define D_AP "AP" // Access Point +#define D_AS "mint" +#define D_AUTO "AUTO" +#define D_BLINK "Villogás" +#define D_BLINKOFF "Villogás ki" +#define D_BOOT_COUNT "Újraindulások száma" +#define D_BRIGHTLIGHT "Max. fényerő" +#define D_BSSID "BSSID" +#define D_BUTTON "Gomb" +#define D_BY "by" // Written by me +#define D_BYTES "Byte-ok" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Csatorna" +#define D_CO2 "Szén-dioxid" +#define D_CODE "kód" // Button code +#define D_COLDLIGHT "Hideg fény" +#define D_COMMAND "Parancs" +#define D_CONNECTED "Csatlakoztatva" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Szám" +#define D_COUNTER "Számláló" +#define D_CURRENT "Áramerősség" // As in Voltage and Current +#define D_DATA "Adat" +#define D_DARKLIGHT "Min. fényerő" +#define D_DEBUG "Debug" +#define D_DISABLED "Letiltva" +#define D_DISTANCE "Távolság" +#define D_DNS_SERVER "DNS szerver" +#define D_DONE "Kész" +#define D_DST_TIME "nyári idő" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emuláció" +#define D_ENABLED "Engedélyezve" +#define D_ERASE "Törlés" +#define D_ERROR "Hiba" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Sikertelen" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "fallback topik" +#define D_FALSE "Hamis" +#define D_FILE "Fájl" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Szabad memória" +#define D_FREQUENCY "Frekvencia" +#define D_GAS "Gáz" +#define D_GATEWAY "Átjáró" +#define D_GROUP "Csoport" +#define D_HOST "Hoszt" +#define D_HOSTNAME "Hosztnév" +#define D_HUMIDITY "Páratartalom" +#define D_ILLUMINANCE "Megvilágítás" +#define D_IMMEDIATE "azonnali" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infravörös" +#define D_INITIALIZED "Inicializálva" +#define D_IP_ADDRESS "IP cím" +#define D_LIGHT "Fény" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "több lenyomás" +#define D_NOISE "Zaj" +#define D_NONE "nincs" +#define D_OFF "Ki" +#define D_OFFLINE "Offline" +#define D_OK "OK" +#define D_ON "Be" +#define D_ONLINE "Online" +#define D_PASSWORD "Jelszó" +#define D_PORT "Port" +#define D_POWER_FACTOR "Teljesítménytényező" +#define D_POWERUSAGE "Energiafelhasználás" +#define D_POWERUSAGE_ACTIVE "Aktív teljesítmény" +#define D_POWERUSAGE_APPARENT "Látszólagos teljesítmény" +#define D_POWERUSAGE_REACTIVE "Reaktív teljesítmény" +#define D_PRESSURE "Nyomás" +#define D_PRESSUREATSEALEVEL "Tengerszinti nyomás" +#define D_PROGRAM_FLASH_SIZE "Program flash méret" +#define D_PROGRAM_SIZE "Program méret" +#define D_PROJECT "Projekt" +#define D_RAIN "Eső" +#define D_RECEIVED "Érkezett" +#define D_RESTART "Újraindítás" +#define D_RESTARTING "Újraindítás" +#define D_RESTART_REASON "Utolsó újraindulás oka" +#define D_RESTORE "Visszaállítás" +#define D_RETAINED "retained" +#define D_RULE "Szabály" +#define D_SAVE "Mentés" +#define D_SENSOR "Szenzor" +#define D_SSID "SSID" +#define D_START "" +#define D_STD_TIME "STD" +#define D_STOP "Leállítás" +#define D_SUBNET_MASK "Alhálózati maszk" +#define D_SUBSCRIBE_TO "Feliratkozás a(z)" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Sikeres" +#define D_SUNRISE "Napkelte" +#define D_SUNSET "Napnyugta" +#define D_TEMPERATURE "Hőmérséklet" +#define D_TO "-nak" +#define D_TOGGLE "Megfordítás" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Továbbít" +#define D_TRUE "Igaz" +#define D_TVOC "TVOC" +#define D_UPGRADE "Frissítés" +#define D_UPLOAD "Feltöltés" +#define D_UPTIME "Üzemidő" +#define D_USER "Felhasználó" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV index" +#define D_UV_INDEX_1 "alacsony" +#define D_UV_INDEX_2 "közepes" +#define D_UV_INDEX_3 "magas" +#define D_UV_INDEX_4 "veszélyes" +#define D_UV_INDEX_5 "égés L1/2" +#define D_UV_INDEX_6 "égés L3" +#define D_UV_INDEX_7 "tartományon kívül" +#define D_UV_LEVEL "UV szint" +#define D_UV_POWER "UV teljesítmény" +#define D_VERSION "Verzió" +#define D_VOLTAGE "Feszültség" +#define D_WEIGHT "Tömeg" +#define D_WARMLIGHT "Meleg fény" +#define D_WEB_SERVER "Webszerver" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "VIGYÁZZ! Ez a verzió nem támogat tartós beállításokat" +#define D_LEVEL_10 "szint 1-0" +#define D_LEVEL_01 "szint 0-1" +#define D_SERIAL_LOGGING_DISABLED "Soros naplózás kikapcsolva" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logolás újraengedélyezve" + +#define D_SET_BAUDRATE_TO "Baudrate beállítása" +#define D_RECEIVED_TOPIC "Érkezett topic" +#define D_DATA_SIZE "Adatméret" +#define D_ANALOG_INPUT "Analóg" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Tiltott hurok" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig SIKERTELEN státusz:" +#define D_ACTIVE_FOR_3_MINUTES "aktválás 3 percre" +#define D_FAILED_TO_START "sikertelen indítás" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "AP-hoz csatlakozás:" +#define D_IN_MODE "mód:" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Sikertelen csatlakozás, nincs kiosztott IP cím" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Sikertelen csatlakozás, AP nem elérhető" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Sikertelen csatlakozás, hibás AP jelszó" +#define D_CONNECT_FAILED_AP_TIMEOUT "Sikertelen csatlakozás AP időtúllépés miatt" +#define D_ATTEMPTING_CONNECTION "Csatlakozás..." +#define D_CHECKING_CONNECTION "Kapcsolat ellenőrzése..." +#define D_QUERY_DONE "Lekérés kész. MQTT szolgáltatás aktív" +#define D_MQTT_SERVICE_FOUND "élő MQTT szolgáltatás a(z)" +#define D_FOUND_AT "a(z)" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog hoszt nem található" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Flash-re mentve a(z)" +#define D_LOADED_FROM_FLASH_AT "Flash-ről betöltve a(z)" +#define D_USE_DEFAULTS "Alapértelmezett beáll. használata" +#define D_ERASED_SECTOR "Szektor törlése" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware
frissítsd!" +#define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:" +#define D_WITH_IP_ADDRESS "IP cím:" +#define D_WEBSERVER_STOPPED "Webszerver leállítva" +#define D_FILE_NOT_FOUND "Fájl nem található" +#define D_REDIRECTED "Átírányítás captive portálra" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "WifiManager AccessPoint(AP) és Station(ST) beállítása" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager AccessPoint(AP) beállítása" +#define D_TRYING_TO_CONNECT "Csatlakozás a hálózatra..." + +#define D_RESTART_IN "Újraindítás..." +#define D_SECONDS "másodperc" +#define D_DEVICE_WILL_RESTART "Az eszköz hamarosan újraindul..." +#define D_BUTTON_TOGGLE "Megfordítás" +#define D_CONFIGURATION "Beállítások" +#define D_INFORMATION "Információ" +#define D_FIRMWARE_UPGRADE "Firmware frissítés" +#define D_CONSOLE "Konzol" +#define D_CONFIRM_RESTART "Biztosan újraindítsam a modult?" + +#define D_CONFIGURE_MODULE "Eszközbeállítások" +#define D_CONFIGURE_WIFI "WiFi konfiguráció" +#define D_CONFIGURE_MQTT "MQTT konfiguráció" +#define D_CONFIGURE_DOMOTICZ "Domoticz konfiguráció" +#define D_CONFIGURE_LOGGING "Naplózás beállításai" +#define D_CONFIGURE_OTHER "Egyéb beállítások" +#define D_CONFIRM_RESET_CONFIGURATION "Biztosan töröljem a beállításokat?" +#define D_RESET_CONFIGURATION "Beállítások törlése" +#define D_BACKUP_CONFIGURATION "Beállítások mentése" +#define D_RESTORE_CONFIGURATION "Beállítások visszatöltése" +#define D_MAIN_MENU "Menü" + +#define D_MODULE_PARAMETERS "Modul paraméterek" +#define D_MODULE_TYPE "Alkalmazott modul" +#define D_PULLUP_ENABLE "Nincs felhúzó ellenállás" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Soros BE" +#define D_SERIAL_OUT "Soros KI" + +#define D_WIFI_PARAMETERS "WiFi paraméterek" +#define D_SCAN_FOR_WIFI_NETWORKS "WiFi hálózat keresése" +#define D_SCAN_DONE "Keresés kész" +#define D_NO_NETWORKS_FOUND "Nincs elérhető hálózat" +#define D_REFRESH_TO_SCAN_AGAIN "Frissíts az újrakereséshez" +#define D_DUPLICATE_ACCESSPOINT "Duplikált access point" +#define D_SKIPPING_LOW_QUALITY "Rossz, alacsony jelminőség" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "AP1 megosztott kulcs" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "AP2 megosztott kulcs" + +#define D_MQTT_PARAMETERS "MQTT paraméterek" +#define D_CLIENT "Kliens" +#define D_FULL_TOPIC "Teljes topic" + +#define D_LOGGING_PARAMETERS "Naplózási paraméterek" +#define D_SERIAL_LOG_LEVEL "Soros naplózási szint" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web naplózási szint" +#define D_SYS_LOG_LEVEL "Syslog szint" +#define D_MORE_DEBUG "Részletes hibakeresés" +#define D_SYSLOG_HOST "Syslog hoszt" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Telemetria (mp.)" + +#define D_OTHER_PARAMETERS "Egyéb beállítások" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Web admin jelszó" +#define D_MQTT_ENABLE "MQTT engedélyezése" +#define D_FRIENDLY_NAME "Név" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Beállítások mentése" +#define D_CONFIGURATION_SAVED "Beállítások elmentve" +#define D_CONFIGURATION_RESET "Beállítások visszaállítása" + +#define D_PROGRAM_VERSION "Program verzió" +#define D_BUILD_DATE_AND_TIME "Build ideje" +#define D_CORE_AND_SDK_VERSION "Core/SDK verzió" +#define D_FLASH_WRITE_COUNT "Flash írások száma" +#define D_MAC_ADDRESS "MAC cím" +#define D_MQTT_HOST "MQTT hoszt" +#define D_MQTT_PORT "MQTT port" +#define D_MQTT_CLIENT "MQTT kliens" +#define D_MQTT_USER "MQTT felhasználó" +#define D_MQTT_TOPIC "MQTT topic" +#define D_MQTT_GROUP_TOPIC "MQTT csoport topic" +#define D_MQTT_FULL_TOPIC "MQTT teljes topic" +#define D_MDNS_DISCOVERY "mDNS láthatóság" +#define D_MDNS_ADVERTISE "mDNS hirdetés" +#define D_ESP_CHIP_ID "ESP chip ID" +#define D_FLASH_CHIP_ID "Flash chip ID" +#define D_FLASH_CHIP_SIZE "Flash mérete" +#define D_FREE_PROGRAM_SPACE "Szabad programhely" + +#define D_UPGRADE_BY_WEBSERVER "Frissítés távoli szerverről" +#define D_OTA_URL "OTA URL" +#define D_START_UPGRADE "Frissítés" +#define D_UPGRADE_BY_FILE_UPLOAD "Frissítés helyi fájllal" +#define D_UPLOAD_STARTED "Feltöltés elindítva" +#define D_UPGRADE_STARTED "Frissítés elindítva" +#define D_UPLOAD_DONE "Feltöltés kész" +#define D_UPLOAD_ERR_1 "Nincs fájl kijelölve" +#define D_UPLOAD_ERR_2 "Nincs elég memória" +#define D_UPLOAD_ERR_3 "A \"magic byte\" nem 0xE9" +#define D_UPLOAD_ERR_4 "A program flashméret nagyobb a valós flashméretnél" +#define D_UPLOAD_ERR_5 "Feltöltési buffer hiba" +#define D_UPLOAD_ERR_6 "Feltöltés sikertelen. Endegélyezd a 3. szintű naplózást" +#define D_UPLOAD_ERR_7 "Feltöltés megszakítva" +#define D_UPLOAD_ERR_8 "Érvénytelen fájl" +#define D_UPLOAD_ERR_9 "A fájl túl nagy" +#define D_UPLOAD_ERR_10 "Az RF chip inicializálása sikertelen" +#define D_UPLOAD_ERR_11 "Az RF chip törlése sikertelen" +#define D_UPLOAD_ERR_12 "Az RF chip írása sikertelen" +#define D_UPLOAD_ERR_13 "Az RF firmware dekódolása sikertelen" +#define D_UPLOAD_ERROR_CODE "Feltöltési hibakód" + +#define D_ENTER_COMMAND "Kérem a parancsot..." +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Engedélyezz 2-es szintű webnaplózást több információért" +#define D_NEED_USER_AND_PASSWORD "Szükséges a user=&password= paraméter" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "TLS fingerprint hitelesítése..." +#define D_TLS_CONNECT_FAILED_TO "TLS csatlakozás sikertelen a(z)" +#define D_RETRY_IN "Újrapróbálás" +#define D_VERIFIED "Fingerprint hitelesítve" +#define D_INSECURE "Nem biztonságos kapcsolat érvénytelen fingerprint miatt" +#define D_CONNECT_FAILED_TO "Sikertelen csatlakozás a(z)" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast kikapcsolva" +#define D_MULTICAST_REJOINED "Multicast (újra)csatlakozás" +#define D_MULTICAST_JOIN_FAILED "Multicast csatlakozás sikertelen" +#define D_FAILED_TO_SEND_RESPONSE "Nem sikerült választ küldeni" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo beállítás" +#define D_RESPONSE_SENT "Válasz elküldve" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue beállítás" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API nincs implementálva" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST argumentumok" +#define D_3_RESPONSE_PACKETS_SENT "3 válaszcsomag elküldve" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz paraméterek" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Kapcsoló idx" +#define D_DOMOTICZ_SENSOR_IDX "Szenzor idx" + #define D_DOMOTICZ_TEMP "Hőmérséklet" + #define D_DOMOTICZ_TEMP_HUM "Hőmérséklet, páratartalom" + #define D_DOMOTICZ_TEMP_HUM_BARO "Hőmérséklet, páratartalom, légnyomás" + #define D_DOMOTICZ_POWER_ENERGY "Teljesítmény, energia" + #define D_DOMOTICZ_ILLUMINANCE "Fényerő" + #define D_DOMOTICZ_COUNT "Szám/PM1" + #define D_DOMOTICZ_VOLTAGE "Feszültség/PM2.5" + #define D_DOMOTICZ_CURRENT "Áram/PM10" + #define D_DOMOTICZ_AIRQUALITY "Légminőség" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Frissítési időzítő" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Időzítő beállításai" +#define D_TIMER_PARAMETERS "Időzítő paraméterei" +#define D_TIMER_ENABLE "Időzítők engedélyezve" +#define D_TIMER_ARM "Be" +#define D_TIMER_TIME "Idő" +#define D_TIMER_DAYS "Napok" +#define D_TIMER_REPEAT "Ismétlés" +#define D_TIMER_OUTPUT "Kimenet" +#define D_TIMER_ACTION "Művelet" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX beállításai" +#define D_KNX_PARAMETERS "KNX paraméterei" +#define D_KNX_GENERAL_CONFIG "Általános" +#define D_KNX_PHYSICAL_ADDRESS "Fizikai cím" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(egyedinek kell lennie a KNX hálózaton)" +#define D_KNX_ENABLE "KNX engedélyezése" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Íráshoz használt csoportcímek" +#define D_ADD "Hozzáadás" +#define D_DELETE "Törlés" +#define D_REPLY "Válasz" +#define D_KNX_GROUP_ADDRESS_TO_READ "Fogadáshoz használt csoportcímek" +#define D_RECEIVED_FROM "Fogadva tőle:" +#define D_KNX_COMMAND_WRITE "Írás" +#define D_KNX_COMMAND_READ "Olvasás" +#define D_KNX_COMMAND_OTHER "Egyáb" +#define D_SENT_TO "küldve neki:" +#define D_KNX_WARNING "A csoportcím ( 0 / 0 / 0 ) fenntartott és nem használható." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Mai energia" +#define D_ENERGY_YESTERDAY "Tegnapi energia" +#define D_ENERGY_TOTAL "Összes energia" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Szenzor foglalt" +#define D_SENSOR_CRC_ERROR "Szenzor CRC hiba" +#define D_SENSORS_FOUND "Szenzorok megtalálva" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Időtúllépés, várakozás" +#define D_START_SIGNAL_LOW "startjel alacsony" +#define D_START_SIGNAL_HIGH "startjel magas" +#define D_PULSE "impulzus" +#define D_CHECKSUM_FAILURE "Checksum hiba" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "A szenzor nem nyugtázta a parancsot" +#define D_SHT1X_FOUND "SHT1X megtalálva" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Részecskék" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Gyorsulásm. X-tengely" +#define D_AY_AXIS "Gyorsulásm. Y-tengely" +#define D_AZ_AXIS "Gyorsulásm. Z-tengely" +#define D_GX_AXIS "Giroszkóp X-tengely" +#define D_GY_AXIS "Giroszkóp Y-tengely" +#define D_GZ_AXIS "Giroszkóp Z-tengely" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Távolítsa el a súlyt" +#define D_HX_CAL_REFERENCE "Helyezze fel a referenciasúlyt" +#define D_HX_CAL_DONE "Kalibrálva" +#define D_HX_CAL_FAIL "Kalibrálási hiba" +#define D_RESET_HX711 "Skála újrabeállítása" +#define D_CONFIGURE_HX711 "Skála konfigurálása" +#define D_HX711_PARAMETERS "Skálaparaméterek" +#define D_ITEM_WEIGHT "Tárgy tömege" +#define D_REFERENCE_WEIGHT "Referenciatömeg" +#define D_CALIBRATE "Kalibrálás" +#define D_CALIBRATION "Kalibrálás" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Szélirány" +#define D_TX20_WIND_SPEED "Szélsebesség" +#define D_TX20_WIND_SPEED_AVG "Átlag szélsebesség" +#define D_TX20_WIND_SPEED_MAX "Max. szélsebesség" +#define D_TX20_NORTH "É" +#define D_TX20_EAST "K" +#define D_TX20_SOUTH "D" +#define D_TX20_WEST "NY" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Nincs" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 lejátszó" +#define D_SENSOR_IRSEND "IR adó" +#define D_SENSOR_SWITCH "Kapcsoló" // Suffix "1" +#define D_SENSOR_BUTTON "Gomb" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "LED" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Számláló" // Suffix "1" +#define D_SENSOR_IRRECV "IR vevő" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Háttérfény" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "szektorok" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Fázisszög" +#define D_IMPORT_ACTIVE "Bejövő aktív" +#define D_EXPORT_ACTIVE "Kimenő aktív" +#define D_IMPORT_REACTIVE "Bejövő reaktív" +#define D_EXPORT_REACTIVE "Kimenő reaktív" +#define D_TOTAL_REACTIVE "Összes reaktív" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "fok" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_HU_HU_H_ diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index a716988de..0585c12d8 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -1,703 +1,701 @@ -/* - it-IT.h - localization for Italian - Italy for Tasmota - - Copyright (C) 2019 Gennaro Tortone - some mods by Antonio Fragola - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_IT_IT_H_ -#define _LANGUAGE_IT_IT_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.0.0a -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1040 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "it" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DomLunMarMerGioVenSab" -#define D_MONTH3LIST "GenFebMarAprMagGiuLugAgoSetOttNovDic" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Qualità dell'aria" -#define D_AP "AP" // Access Point -#define D_AS "come" -#define D_AUTO "AUTO" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Numero di boot" -#define D_BRIGHTLIGHT "Luminoso" -#define D_BSSID "BSSId" -#define D_BUTTON "Pulsante" -#define D_BY "da" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canale" -#define D_CO2 "CO2" -#define D_CODE "codice" // Button code -#define D_COLDLIGHT "Fredda" -#define D_COMMAND "Comando" -#define D_CONNECTED "Connesso" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Conteggio" -#define D_COUNTER "Contatore" -#define D_CURRENT "Corrente" // As in Voltage and Current -#define D_DATA "Dati" -#define D_DARKLIGHT "Scuro" -#define D_DEBUG "Debug" -#define D_DISABLED "Disabilitato" -#define D_DISTANCE "Distanza" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Fatto" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulazione" -#define D_ENABLED "Abilitato" -#define D_ERASE "Cancellare" -#define D_ERROR "Errore" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Fallito" -#define D_FALLBACK "Riserva" -#define D_FALLBACK_TOPIC "Topic Riserva" -#define D_FALSE "Falso" -#define D_FILE "File" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Memoria Libera" -#define D_FREQUENCY "Frequenza" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Gruppo" -#define D_HOST "Host" -#define D_HOSTNAME "Nome Host" -#define D_HUMIDITY "Umidità" -#define D_ILLUMINANCE "Illuminazione" -#define D_IMMEDIATE "immediato" // Button immediate -#define D_INDEX "Indice" -#define D_INFO "Info" -#define D_INFRARED "Infrarosso" -#define D_INITIALIZED "Inizializzato" -#define D_IP_ADDRESS "Indirizzo IP" -#define D_LIGHT "Luce" -#define D_LWT "LWT" -#define D_MODULE "Modulo" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-pressione" -#define D_NOISE "Rumore" -#define D_NONE "Nessuno" -#define D_OFF "Off" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "On" -#define D_ONLINE "Online" -#define D_PASSWORD "Password" -#define D_PORT "Porta" -#define D_POWER_FACTOR "Fattore di potenza" -#define D_POWERUSAGE "Potenza" -#define D_POWERUSAGE_ACTIVE "Potenza Attiva" -#define D_POWERUSAGE_APPARENT "Potenza Apparente" -#define D_POWERUSAGE_REACTIVE "Potenza Reattiva" -#define D_PRESSURE "Pressione" -#define D_PRESSUREATSEALEVEL "Pressione al livello del mare" -#define D_PROGRAM_FLASH_SIZE "Dimensione Flash Programma" -#define D_PROGRAM_SIZE "Dimensione Programma" -#define D_PROJECT "Progetto" -#define D_RAIN "Rain" -#define D_RECEIVED "Ricevuto" -#define D_RESTART "Riavvio" -#define D_RESTARTING "Riavviando" -#define D_RESTART_REASON "Causa Riavvio" -#define D_RESTORE "ripristino" -#define D_RETAINED "salvato" -#define D_RULE "Rule" -#define D_SAVE "Salva" -#define D_SENSOR "Sensore" -#define D_SSID "SSId" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Maschera Subnet" -#define D_SUBSCRIBE_TO "Sottoscrivi a" -#define D_UNSUBSCRIBE_FROM "Cancella da" -#define D_SUCCESSFUL "Riuscito" -#define D_SUNRISE "Alba" -#define D_SUNSET "Tramonto" -#define D_TEMPERATURE "Temperatura" -#define D_TO "a" -#define D_TOGGLE "Toggle" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Trasmesso" -#define D_TRUE "Vero" -#define D_TVOC "TVOC" -#define D_UPGRADE "Aggiornamento" -#define D_UPLOAD "Invio" -#define D_UPTIME "Uptime" -#define D_USER "Utente" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Indice UV" -#define D_UV_INDEX_1 "Basso" -#define D_UV_INDEX_2 "Medio" -#define D_UV_INDEX_3 "Alto" -#define D_UV_INDEX_4 "Pericolo" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Livello UV" -#define D_UV_POWER "Intensità UV" -#define D_VERSION "Versione" -#define D_VOLTAGE "Tensione" -#define D_WEIGHT "Peso" -#define D_WARMLIGHT "Calda" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Log Seriale disabilitato" -#define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato" - -#define D_SET_BAUDRATE_TO "Baudrate impostato a" -#define D_RECEIVED_TOPIC "Topic Ricevuto" -#define D_DATA_SIZE "Dimensione Dati" -#define D_ANALOG_INPUT "Ingresso Analogico" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Ciclo Bloccato" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato" -#define D_ACTIVE_FOR_3_MINUTES "Attivo per 3 minuti" -#define D_FAILED_TO_START "Partenza fallita" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Connessione ad AP" -#define D_IN_MODE "In modalità" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta" -#define D_CONNECT_FAILED_AP_TIMEOUT "Connessione fallita, timeout AP" -#define D_ATTEMPTING_CONNECTION "Tentativo di connessione..." -#define D_CHECKING_CONNECTION "Controllo connessione..." -#define D_QUERY_DONE "Query eseguita. Servizio MQTT trovato" -#define D_MQTT_SERVICE_FOUND "Servizio MQTT trovato su" -#define D_FOUND_AT "trovato a" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host non trovato" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Salvato nella flash in" -#define D_LOADED_FROM_FLASH_AT "Caricato dalla flash da" -#define D_USE_DEFAULTS "Utilizzo valori default" -#define D_ERASED_SECTOR "Settore cancellato" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" -#define D_WEBSERVER_ACTIVE_ON "Web server attivo su" -#define D_WITH_IP_ADDRESS "con indirizzo IP" -#define D_WEBSERVER_STOPPED "Web server arrestato" -#define D_FILE_NOT_FOUND "File Non Trovato" -#define D_REDIRECTED "Redirezione al captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Impostazione Wifimanager come AccessPoint e Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Impostazione Wifimanager come AccessPoint" -#define D_TRYING_TO_CONNECT "Tentativo di connessione del dispositivo alla rete" - -#define D_RESTART_IN "Riavvio in" -#define D_SECONDS "secondi" -#define D_DEVICE_WILL_RESTART "Il dispositivo verrà riavviato tra pochi secondi" -#define D_BUTTON_TOGGLE "On/Off" -#define D_CONFIGURATION "Configurazione" -#define D_INFORMATION "Informazioni" -#define D_FIRMWARE_UPGRADE "Aggiornamento Firmware" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Conferma Riavvio" - -#define D_CONFIGURE_MODULE "Configurazione Modulo" -#define D_CONFIGURE_WIFI "Configurazione WiFi" -#define D_CONFIGURE_MQTT "Configurazione MQTT" -#define D_CONFIGURE_DOMOTICZ "Configurazione Domoticz" -#define D_CONFIGURE_LOGGING "Configurazione Logging" -#define D_CONFIGURE_OTHER "Configurazione Extra" -#define D_CONFIRM_RESET_CONFIGURATION "Conferma Reset Configurazione" -#define D_RESET_CONFIGURATION "Reset Configurazione" -#define D_BACKUP_CONFIGURATION "Backup Configurazione" -#define D_RESTORE_CONFIGURATION "Ripristino Configurazione" -#define D_MAIN_MENU "Menu Principale" - -#define D_MODULE_PARAMETERS "Parametri del modulo" -#define D_MODULE_TYPE "Tipo modulo" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Seriale In" -#define D_SERIAL_OUT "Seriale Out" - -#define D_WIFI_PARAMETERS "Parametri Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi" -#define D_SCAN_DONE "Scansione effettuata" -#define D_NO_NETWORKS_FOUND "Nessuna rete trovata" -#define D_REFRESH_TO_SCAN_AGAIN "Ricarica per nuova scansione" -#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicato" -#define D_SKIPPING_LOW_QUALITY "Ignorato a causa di bassa qualità" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Password" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Password" - -#define D_MQTT_PARAMETERS "Parametri MQTT" -#define D_CLIENT "Client" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "Parametri Logging" -#define D_SERIAL_LOG_LEVEL "Livello di log Seriale" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "livello di log Web" -#define D_SYS_LOG_LEVEL "livello di log Sys" -#define D_MORE_DEBUG "Debug aggiuntivo" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog porta" -#define D_TELEMETRY_PERIOD "Periodo Telemetria" - -#define D_OTHER_PARAMETERS "Altri parametri" -#define D_TEMPLATE "Modello" -#define D_ACTIVATE "Attivare" -#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web" -#define D_MQTT_ENABLE "Abilita MQTT" -#define D_FRIENDLY_NAME "Nome amichevole" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "dispositivo singolo" -#define D_MULTI_DEVICE "dispositivo multiplo" - -#define D_CONFIGURE_TEMPLATE "Configurare Modello" -#define D_TEMPLATE_PARAMETERS "Parametri Modello" -#define D_TEMPLATE_NAME "Nome" -#define D_BASE_TYPE "Basato nel" -#define D_TEMPLATE_FLAGS "Opzioni" - -#define D_SAVE_CONFIGURATION "Salva configurazione" -#define D_CONFIGURATION_SAVED "Configurazione salvata" -#define D_CONFIGURATION_RESET "Configurazione azzerata" - -#define D_PROGRAM_VERSION "Versione del programma" -#define D_BUILD_DATE_AND_TIME "Data e ora compilazione" -#define D_CORE_AND_SDK_VERSION "Versione Core/SDK" -#define D_FLASH_WRITE_COUNT "Contatore scrittura Flash" -#define D_MAC_ADDRESS "Indirizzo MAC" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Porta" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT Utente" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Dimensione Flash" -#define D_FREE_PROGRAM_SPACE "Spazio Libero Memoria Programma" - -#define D_UPGRADE_BY_WEBSERVER "Aggiornamento da web server" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Avvio aggiornamento" -#define D_UPGRADE_BY_FILE_UPLOAD "Aggiornamento tramite invio file" -#define D_UPLOAD_STARTED "Invio iniziato" -#define D_UPGRADE_STARTED "Aggiornamento avviato" -#define D_UPLOAD_DONE "Invio effettuato" -#define D_UPLOAD_ERR_1 "Nessun file selezionato" -#define D_UPLOAD_ERR_2 "Spazio insufficiente" -#define D_UPLOAD_ERR_3 "Magic byte non corrispondente a 0xE9" -#define D_UPLOAD_ERR_4 "Dimensione della memoria programma maggiore della dimensione reale della flash" -#define D_UPLOAD_ERR_5 "Errore di comparazione del buffer di invio" -#define D_UPLOAD_ERR_6 "Invio fallito. Abilitare logging 3" -#define D_UPLOAD_ERR_7 "Invio annullato" -#define D_UPLOAD_ERR_8 "File non valido" -#define D_UPLOAD_ERR_9 "File troppo grande" -#define D_UPLOAD_ERR_10 "Inizializzazione fallita del chip RF" -#define D_UPLOAD_ERR_11 "Cancellazione fallita del chip RF" -#define D_UPLOAD_ERR_12 "Scrittura fallita del chip RF" -#define D_UPLOAD_ERR_13 "Decodifica fallita del firmware RF" -#define D_UPLOAD_ERROR_CODE "Codice errore invio" - -#define D_ENTER_COMMAND "Inserire comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Abilitare weblog 2 se è attesa una risposta" -#define D_NEED_USER_AND_PASSWORD "Richiesto user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifica TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "Connessione TLS fallita a" -#define D_RETRY_IN "Nuovo tentativo in" -#define D_VERIFIED "Verificato Fingerprint" -#define D_INSECURE "Connessione insicura a causa di Fingerprint non valido" -#define D_CONNECT_FAILED_TO "Connessione Fallita a" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast disabilitato" -#define D_MULTICAST_REJOINED "Multicast (ri)associato" -#define D_MULTICAST_JOIN_FAILED "Associazione Multicast fallita" -#define D_FAILED_TO_SEND_RESPONSE "Invio risposta fallito" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo evento base" -#define D_WEMO_EVENT_SERVICE "WeMo servizio eventi" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "Impostazione WeMo" -#define D_RESPONSE_SENT "Risposta inviata" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Impostazione Hue" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API non implementata" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argomenti" -#define D_3_RESPONSE_PACKETS_SENT "3 pacchetti di risposta inviati" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parametri Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Intervallo di aggiornamento" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configura Timer" -#define D_TIMER_PARAMETERS "Parametri Timer" -#define D_TIMER_ENABLE "Abilita Timer" -#define D_TIMER_ARM "Attiva" -#define D_TIMER_TIME "Ora" -#define D_TIMER_DAYS "Giorni" -#define D_TIMER_REPEAT "Ripeti" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Azione" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configura KNX" -#define D_KNX_PARAMETERS "Parametri KNX" -#define D_KNX_GENERAL_CONFIG "Generale" -#define D_KNX_PHYSICAL_ADDRESS "Indirizzo Fisico" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve essere univoco nella rete KNX )" -#define D_KNX_ENABLE "Abilita KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dati da Inviare al Gruppo di Indirizzi" -#define D_ADD "Aggiungi" -#define D_DELETE "Elimina" -#define D_REPLY "Rispondi" -#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppo di Indirizzi da cui Ricevere Dati" -#define D_RECEIVED_FROM "Ricevuto Da" -#define D_KNX_COMMAND_WRITE "Scrivi" -#define D_KNX_COMMAND_READ "Leggi" -#define D_KNX_COMMAND_OTHER "Altro" -#define D_SENT_TO "invia a" -#define D_KNX_WARNING "L'indirizzo del gruppo ( 0 / 0 / 0 ) è riservato e non può essere usato." -#define D_KNX_ENHANCEMENT "Miglioramento Comunicazione" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energia Oggi" -#define D_ENERGY_YESTERDAY "Energia Ieri" -#define D_ENERGY_TOTAL "Energia Totale" - -// xdrv_27_shutter.ino -#define D_OPEN "Aperta" -#define D_CLOSE "Chiusa" -#define D_DOMOTICZ_SHUTTER "Serranda" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configura PCF8574" -#define D_PCF8574_PARAMETERS "Parametri PCF8574" -#define D_INVERT_PORTS "Porte Invertite" -#define D_DEVICE "Dispositivo" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensore occupato" -#define D_SENSOR_CRC_ERROR "Sensore errore CRC" -#define D_SENSORS_FOUND "Sensori trovati" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Attesa timeout per" -#define D_START_SIGNAL_LOW "inizio segnale basso" -#define D_START_SIGNAL_HIGH "inizio segnale alto" -#define D_PULSE "impulso" -#define D_CHECKSUM_FAILURE "Checksum fallito" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensore non ha eseguito il comando ACK" -#define D_SHT1X_FOUND "SHT1X trovato" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particelle" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. Asse-X" -#define D_AY_AXIS "Accel. Asse-Y" -#define D_AZ_AXIS "Accel. Asse-Z" -#define D_GX_AXIS "Gyro Asse-X" -#define D_GY_AXIS "Gyro Asse-Y" -#define D_GZ_AXIS "Gyro Asse-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Rimuovere peso" -#define D_HX_CAL_REFERENCE "Caricare peso di riferimento" -#define D_HX_CAL_DONE "Calibrato" -#define D_HX_CAL_FAIL "Calibrazione fallita" -#define D_RESET_HX711 "Reset Scala" -#define D_CONFIGURE_HX711 "Configura Scala" -#define D_HX711_PARAMETERS "Parametri Scala" -#define D_ITEM_WEIGHT "Peso oggetto" -#define D_REFERENCE_WEIGHT "Peso di riferimento" -#define D_CALIBRATE "Calibrato" -#define D_CALIBRATION "Calibrazione" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direzione Vento" -#define D_TX20_WIND_SPEED "Velocità Vento" -#define D_TX20_WIND_SPEED_AVG "Velocità Media Vento" -#define D_TX20_WIND_SPEED_MAX "Velocità Massima Vento" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Nessuno" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "settori" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Angolo Fase" -#define D_IMPORT_ACTIVE "Potenza Attiva Importata" -#define D_EXPORT_ACTIVE "Potenza Attiva Esportata" -#define D_IMPORT_REACTIVE "Potenza Reattiva Importata" -#define D_EXPORT_REACTIVE "Potenza Reattiva Esportata" -#define D_TOTAL_REACTIVE "Potenza Reattiva Totale" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "°" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltaggio" -#define D_PV1_CURRENT "PV1 Corrente" -#define D_PV1_POWER "PV1 Eergia" -#define D_PV2_VOLTAGE "PV2 Voltaggio" -#define D_PV2_CURRENT "PV2 Corrente" -#define D_PV2_POWER "PV2 Energia" -#define D_SOLAR_POWER "Energia Solar" -#define D_INVERTER_POWER "Energia Inverter" -#define D_STATUS "Stato" -#define D_WAITING "In attesa" -#define D_CHECKING "Controllando" -#define D_WORKING "Lavorando" -#define D_FAILURE "Errore" -#define D_SOLAX_ERROR_0 "No Codice Errore" -#define D_SOLAX_ERROR_1 "Errore Grid Persa" -#define D_SOLAX_ERROR_2 "Errore Voltaggio Grid" -#define D_SOLAX_ERROR_3 "Errore Frequenza Grid" -#define D_SOLAX_ERROR_4 "Errore Voltaggio Pv" -#define D_SOLAX_ERROR_5 "Errore Isolamento" -#define D_SOLAX_ERROR_6 "Errore Temperatura Eccessiva" -#define D_SOLAX_ERROR_7 "Errore Ventilatore" -#define D_SOLAX_ERROR_8 "Altro Errore del Dispositivo" - -#endif // _LANGUAGE_IT_IT_H_ +/* + it-IT.h - localization for Italian - Italy for Tasmota + + Copyright (C) 2019 Gennaro Tortone - some mods by Antonio Fragola + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_IT_IT_H_ +#define _LANGUAGE_IT_IT_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.0.0a +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1040 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "it" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DomLunMarMerGioVenSab" +#define D_MONTH3LIST "GenFebMarAprMagGiuLugAgoSetOttNovDic" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Qualità dell'aria" +#define D_AP "AP" // Access Point +#define D_AS "come" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Numero di boot" +#define D_BRIGHTLIGHT "Luminoso" +#define D_BSSID "BSSId" +#define D_BUTTON "Pulsante" +#define D_BY "da" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canale" +#define D_CO2 "CO2" +#define D_CODE "codice" // Button code +#define D_COLDLIGHT "Fredda" +#define D_COMMAND "Comando" +#define D_CONNECTED "Connesso" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Conteggio" +#define D_COUNTER "Contatore" +#define D_CURRENT "Corrente" // As in Voltage and Current +#define D_DATA "Dati" +#define D_DARKLIGHT "Scuro" +#define D_DEBUG "Debug" +#define D_DISABLED "Disabilitato" +#define D_DISTANCE "Distanza" +#define D_DNS_SERVER "DNS Server" +#define D_DONE "Fatto" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulazione" +#define D_ENABLED "Abilitato" +#define D_ERASE "Cancellare" +#define D_ERROR "Errore" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Fallito" +#define D_FALLBACK "Riserva" +#define D_FALLBACK_TOPIC "Topic Riserva" +#define D_FALSE "Falso" +#define D_FILE "File" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Memoria Libera" +#define D_FREQUENCY "Frequenza" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Gruppo" +#define D_HOST "Host" +#define D_HOSTNAME "Nome Host" +#define D_HUMIDITY "Umidità" +#define D_ILLUMINANCE "Illuminazione" +#define D_IMMEDIATE "immediato" // Button immediate +#define D_INDEX "Indice" +#define D_INFO "Info" +#define D_INFRARED "Infrarosso" +#define D_INITIALIZED "Inizializzato" +#define D_IP_ADDRESS "Indirizzo IP" +#define D_LIGHT "Luce" +#define D_LWT "LWT" +#define D_MODULE "Modulo" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-pressione" +#define D_NOISE "Rumore" +#define D_NONE "Nessuno" +#define D_OFF "Off" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "On" +#define D_ONLINE "Online" +#define D_PASSWORD "Password" +#define D_PORT "Porta" +#define D_POWER_FACTOR "Fattore di potenza" +#define D_POWERUSAGE "Potenza" +#define D_POWERUSAGE_ACTIVE "Potenza Attiva" +#define D_POWERUSAGE_APPARENT "Potenza Apparente" +#define D_POWERUSAGE_REACTIVE "Potenza Reattiva" +#define D_PRESSURE "Pressione" +#define D_PRESSUREATSEALEVEL "Pressione al livello del mare" +#define D_PROGRAM_FLASH_SIZE "Dimensione Flash Programma" +#define D_PROGRAM_SIZE "Dimensione Programma" +#define D_PROJECT "Progetto" +#define D_RAIN "Rain" +#define D_RECEIVED "Ricevuto" +#define D_RESTART "Riavvio" +#define D_RESTARTING "Riavviando" +#define D_RESTART_REASON "Causa Riavvio" +#define D_RESTORE "ripristino" +#define D_RETAINED "salvato" +#define D_RULE "Rule" +#define D_SAVE "Salva" +#define D_SENSOR "Sensore" +#define D_SSID "SSId" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maschera Subnet" +#define D_SUBSCRIBE_TO "Sottoscrivi a" +#define D_UNSUBSCRIBE_FROM "Cancella da" +#define D_SUCCESSFUL "Riuscito" +#define D_SUNRISE "Alba" +#define D_SUNSET "Tramonto" +#define D_TEMPERATURE "Temperatura" +#define D_TO "a" +#define D_TOGGLE "Toggle" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Trasmesso" +#define D_TRUE "Vero" +#define D_TVOC "TVOC" +#define D_UPGRADE "Aggiornamento" +#define D_UPLOAD "Invio" +#define D_UPTIME "Uptime" +#define D_USER "Utente" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Indice UV" +#define D_UV_INDEX_1 "Basso" +#define D_UV_INDEX_2 "Medio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Pericolo" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Livello UV" +#define D_UV_POWER "Intensità UV" +#define D_VERSION "Versione" +#define D_VOLTAGE "Tensione" +#define D_WEIGHT "Peso" +#define D_WARMLIGHT "Calda" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Log Seriale disabilitato" +#define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato" + +#define D_SET_BAUDRATE_TO "Baudrate impostato a" +#define D_RECEIVED_TOPIC "Topic Ricevuto" +#define D_DATA_SIZE "Dimensione Dati" +#define D_ANALOG_INPUT "Ingresso Analogico" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Ciclo Bloccato" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato" +#define D_ACTIVE_FOR_3_MINUTES "Attivo per 3 minuti" +#define D_FAILED_TO_START "Partenza fallita" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Connessione ad AP" +#define D_IN_MODE "In modalità" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta" +#define D_CONNECT_FAILED_AP_TIMEOUT "Connessione fallita, timeout AP" +#define D_ATTEMPTING_CONNECTION "Tentativo di connessione..." +#define D_CHECKING_CONNECTION "Controllo connessione..." +#define D_QUERY_DONE "Query eseguita. Servizio MQTT trovato" +#define D_MQTT_SERVICE_FOUND "Servizio MQTT trovato su" +#define D_FOUND_AT "trovato a" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host non trovato" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Salvato nella flash in" +#define D_LOADED_FROM_FLASH_AT "Caricato dalla flash da" +#define D_USE_DEFAULTS "Utilizzo valori default" +#define D_ERASED_SECTOR "Settore cancellato" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
effettuare aggiornamento" +#define D_WEBSERVER_ACTIVE_ON "Web server attivo su" +#define D_WITH_IP_ADDRESS "con indirizzo IP" +#define D_WEBSERVER_STOPPED "Web server arrestato" +#define D_FILE_NOT_FOUND "File Non Trovato" +#define D_REDIRECTED "Redirezione al captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Impostazione Wifimanager come AccessPoint e Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Impostazione Wifimanager come AccessPoint" +#define D_TRYING_TO_CONNECT "Tentativo di connessione del dispositivo alla rete" + +#define D_RESTART_IN "Riavvio in" +#define D_SECONDS "secondi" +#define D_DEVICE_WILL_RESTART "Il dispositivo verrà riavviato tra pochi secondi" +#define D_BUTTON_TOGGLE "On/Off" +#define D_CONFIGURATION "Configurazione" +#define D_INFORMATION "Informazioni" +#define D_FIRMWARE_UPGRADE "Aggiornamento Firmware" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Conferma Riavvio" + +#define D_CONFIGURE_MODULE "Configurazione Modulo" +#define D_CONFIGURE_WIFI "Configurazione WiFi" +#define D_CONFIGURE_MQTT "Configurazione MQTT" +#define D_CONFIGURE_DOMOTICZ "Configurazione Domoticz" +#define D_CONFIGURE_LOGGING "Configurazione Logging" +#define D_CONFIGURE_OTHER "Configurazione Extra" +#define D_CONFIRM_RESET_CONFIGURATION "Conferma Reset Configurazione" +#define D_RESET_CONFIGURATION "Reset Configurazione" +#define D_BACKUP_CONFIGURATION "Backup Configurazione" +#define D_RESTORE_CONFIGURATION "Ripristino Configurazione" +#define D_MAIN_MENU "Menu Principale" + +#define D_MODULE_PARAMETERS "Parametri del modulo" +#define D_MODULE_TYPE "Tipo modulo" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Seriale In" +#define D_SERIAL_OUT "Seriale Out" + +#define D_WIFI_PARAMETERS "Parametri Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi" +#define D_SCAN_DONE "Scansione effettuata" +#define D_NO_NETWORKS_FOUND "Nessuna rete trovata" +#define D_REFRESH_TO_SCAN_AGAIN "Ricarica per nuova scansione" +#define D_DUPLICATE_ACCESSPOINT "AccessPoint duplicato" +#define D_SKIPPING_LOW_QUALITY "Ignorato a causa di bassa qualità" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Password" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Password" + +#define D_MQTT_PARAMETERS "Parametri MQTT" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "Parametri Logging" +#define D_SERIAL_LOG_LEVEL "Livello di log Seriale" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "livello di log Web" +#define D_SYS_LOG_LEVEL "livello di log Sys" +#define D_MORE_DEBUG "Debug aggiuntivo" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog porta" +#define D_TELEMETRY_PERIOD "Periodo Telemetria" + +#define D_OTHER_PARAMETERS "Altri parametri" +#define D_TEMPLATE "Modello" +#define D_ACTIVATE "Attivare" +#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web" +#define D_MQTT_ENABLE "Abilita MQTT" +#define D_FRIENDLY_NAME "Nome amichevole" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "dispositivo singolo" +#define D_MULTI_DEVICE "dispositivo multiplo" + +#define D_CONFIGURE_TEMPLATE "Configurare Modello" +#define D_TEMPLATE_PARAMETERS "Parametri Modello" +#define D_TEMPLATE_NAME "Nome" +#define D_BASE_TYPE "Basato nel" +#define D_TEMPLATE_FLAGS "Opzioni" + +#define D_SAVE_CONFIGURATION "Salva configurazione" +#define D_CONFIGURATION_SAVED "Configurazione salvata" +#define D_CONFIGURATION_RESET "Configurazione azzerata" + +#define D_PROGRAM_VERSION "Versione del programma" +#define D_BUILD_DATE_AND_TIME "Data e ora compilazione" +#define D_CORE_AND_SDK_VERSION "Versione Core/SDK" +#define D_FLASH_WRITE_COUNT "Contatore scrittura Flash" +#define D_MAC_ADDRESS "Indirizzo MAC" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Porta" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT Utente" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Dimensione Flash" +#define D_FREE_PROGRAM_SPACE "Spazio Libero Memoria Programma" + +#define D_UPGRADE_BY_WEBSERVER "Aggiornamento da web server" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Avvio aggiornamento" +#define D_UPGRADE_BY_FILE_UPLOAD "Aggiornamento tramite invio file" +#define D_UPLOAD_STARTED "Invio iniziato" +#define D_UPGRADE_STARTED "Aggiornamento avviato" +#define D_UPLOAD_DONE "Invio effettuato" +#define D_UPLOAD_ERR_1 "Nessun file selezionato" +#define D_UPLOAD_ERR_2 "Spazio insufficiente" +#define D_UPLOAD_ERR_3 "Magic byte non corrispondente a 0xE9" +#define D_UPLOAD_ERR_4 "Dimensione della memoria programma maggiore della dimensione reale della flash" +#define D_UPLOAD_ERR_5 "Errore di comparazione del buffer di invio" +#define D_UPLOAD_ERR_6 "Invio fallito. Abilitare logging 3" +#define D_UPLOAD_ERR_7 "Invio annullato" +#define D_UPLOAD_ERR_8 "File non valido" +#define D_UPLOAD_ERR_9 "File troppo grande" +#define D_UPLOAD_ERR_10 "Inizializzazione fallita del chip RF" +#define D_UPLOAD_ERR_11 "Cancellazione fallita del chip RF" +#define D_UPLOAD_ERR_12 "Scrittura fallita del chip RF" +#define D_UPLOAD_ERR_13 "Decodifica fallita del firmware RF" +#define D_UPLOAD_ERROR_CODE "Codice errore invio" + +#define D_ENTER_COMMAND "Inserire comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Abilitare weblog 2 se è attesa una risposta" +#define D_NEED_USER_AND_PASSWORD "Richiesto user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifica TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "Connessione TLS fallita a" +#define D_RETRY_IN "Nuovo tentativo in" +#define D_VERIFIED "Verificato Fingerprint" +#define D_INSECURE "Connessione insicura a causa di Fingerprint non valido" +#define D_CONNECT_FAILED_TO "Connessione Fallita a" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast disabilitato" +#define D_MULTICAST_REJOINED "Multicast (ri)associato" +#define D_MULTICAST_JOIN_FAILED "Associazione Multicast fallita" +#define D_FAILED_TO_SEND_RESPONSE "Invio risposta fallito" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo evento base" +#define D_WEMO_EVENT_SERVICE "WeMo servizio eventi" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "Impostazione WeMo" +#define D_RESPONSE_SENT "Risposta inviata" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Impostazione Hue" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API non implementata" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST argomenti" +#define D_3_RESPONSE_PACKETS_SENT "3 pacchetti di risposta inviati" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parametri Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Intervallo di aggiornamento" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configura Timer" +#define D_TIMER_PARAMETERS "Parametri Timer" +#define D_TIMER_ENABLE "Abilita Timer" +#define D_TIMER_ARM "Attiva" +#define D_TIMER_TIME "Ora" +#define D_TIMER_DAYS "Giorni" +#define D_TIMER_REPEAT "Ripeti" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Azione" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configura KNX" +#define D_KNX_PARAMETERS "Parametri KNX" +#define D_KNX_GENERAL_CONFIG "Generale" +#define D_KNX_PHYSICAL_ADDRESS "Indirizzo Fisico" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve essere univoco nella rete KNX )" +#define D_KNX_ENABLE "Abilita KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dati da Inviare al Gruppo di Indirizzi" +#define D_ADD "Aggiungi" +#define D_DELETE "Elimina" +#define D_REPLY "Rispondi" +#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppo di Indirizzi da cui Ricevere Dati" +#define D_RECEIVED_FROM "Ricevuto Da" +#define D_KNX_COMMAND_WRITE "Scrivi" +#define D_KNX_COMMAND_READ "Leggi" +#define D_KNX_COMMAND_OTHER "Altro" +#define D_SENT_TO "invia a" +#define D_KNX_WARNING "L'indirizzo del gruppo ( 0 / 0 / 0 ) è riservato e non può essere usato." +#define D_KNX_ENHANCEMENT "Miglioramento Comunicazione" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energia Oggi" +#define D_ENERGY_YESTERDAY "Energia Ieri" +#define D_ENERGY_TOTAL "Energia Totale" + +// xdrv_27_shutter.ino +#define D_OPEN "Aperta" +#define D_CLOSE "Chiusa" +#define D_DOMOTICZ_SHUTTER "Serranda" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configura PCF8574" +#define D_PCF8574_PARAMETERS "Parametri PCF8574" +#define D_INVERT_PORTS "Porte Invertite" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensore occupato" +#define D_SENSOR_CRC_ERROR "Sensore errore CRC" +#define D_SENSORS_FOUND "Sensori trovati" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Attesa timeout per" +#define D_START_SIGNAL_LOW "inizio segnale basso" +#define D_START_SIGNAL_HIGH "inizio segnale alto" +#define D_PULSE "impulso" +#define D_CHECKSUM_FAILURE "Checksum fallito" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensore non ha eseguito il comando ACK" +#define D_SHT1X_FOUND "SHT1X trovato" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particelle" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. Asse-X" +#define D_AY_AXIS "Accel. Asse-Y" +#define D_AZ_AXIS "Accel. Asse-Z" +#define D_GX_AXIS "Gyro Asse-X" +#define D_GY_AXIS "Gyro Asse-Y" +#define D_GZ_AXIS "Gyro Asse-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Rimuovere peso" +#define D_HX_CAL_REFERENCE "Caricare peso di riferimento" +#define D_HX_CAL_DONE "Calibrato" +#define D_HX_CAL_FAIL "Calibrazione fallita" +#define D_RESET_HX711 "Reset Scala" +#define D_CONFIGURE_HX711 "Configura Scala" +#define D_HX711_PARAMETERS "Parametri Scala" +#define D_ITEM_WEIGHT "Peso oggetto" +#define D_REFERENCE_WEIGHT "Peso di riferimento" +#define D_CALIBRATE "Calibrato" +#define D_CALIBRATION "Calibrazione" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direzione Vento" +#define D_TX20_WIND_SPEED "Velocità Vento" +#define D_TX20_WIND_SPEED_AVG "Velocità Media Vento" +#define D_TX20_WIND_SPEED_MAX "Velocità Massima Vento" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Nessuno" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "settori" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Angolo Fase" +#define D_IMPORT_ACTIVE "Potenza Attiva Importata" +#define D_EXPORT_ACTIVE "Potenza Attiva Esportata" +#define D_IMPORT_REACTIVE "Potenza Reattiva Importata" +#define D_EXPORT_REACTIVE "Potenza Reattiva Esportata" +#define D_TOTAL_REACTIVE "Potenza Reattiva Totale" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "°" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltaggio" +#define D_PV1_CURRENT "PV1 Corrente" +#define D_PV1_POWER "PV1 Eergia" +#define D_PV2_VOLTAGE "PV2 Voltaggio" +#define D_PV2_CURRENT "PV2 Corrente" +#define D_PV2_POWER "PV2 Energia" +#define D_SOLAR_POWER "Energia Solar" +#define D_INVERTER_POWER "Energia Inverter" +#define D_STATUS "Stato" +#define D_WAITING "In attesa" +#define D_CHECKING "Controllando" +#define D_WORKING "Lavorando" +#define D_FAILURE "Errore" +#define D_SOLAX_ERROR_0 "No Codice Errore" +#define D_SOLAX_ERROR_1 "Errore Grid Persa" +#define D_SOLAX_ERROR_2 "Errore Voltaggio Grid" +#define D_SOLAX_ERROR_3 "Errore Frequenza Grid" +#define D_SOLAX_ERROR_4 "Errore Voltaggio Pv" +#define D_SOLAX_ERROR_5 "Errore Isolamento" +#define D_SOLAX_ERROR_6 "Errore Temperatura Eccessiva" +#define D_SOLAX_ERROR_7 "Errore Ventilatore" +#define D_SOLAX_ERROR_8 "Altro Errore del Dispositivo" + +#endif // _LANGUAGE_IT_IT_H_ diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 4da467267..bff508474 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -1,703 +1,701 @@ -/* - ko-KO.h - localization for Korean - Korean for Tasmota - - Copyright (C) 2019 Theo Arends (translated by NyaamZ) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_KO_KO_H_ -#define _LANGUAGE_KO_KO_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.11 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -// https://www.science.co.il/language/Locale-codes.php -#define LANGUAGE_LCID 1042 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "ko" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "일 월 화 수 목 금 토 " -#define D_MONTH3LIST "1월 2월 3월 4월 5월 6월 7월 8월 9월 10월11월12월" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "공기질" -#define D_AP "AP" // Access Point -#define D_AS "as" -#define D_AUTO "자동" -#define D_BLINK "깜박임" -#define D_BLINKOFF "깜박임 끄기" -#define D_BOOT_COUNT "부팅 횟수" -#define D_BRIGHTLIGHT "밝게" -#define D_BSSID "BSSId" -#define D_BUTTON "버튼" -#define D_BY "by" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "섭씨" -#define D_CHANNEL "채널" -#define D_CO2 "이산화탄소" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "차갑게" -#define D_COMMAND "커맨드" -#define D_CONNECTED "연결됨" -#define D_COUNT "횟수" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNTER "Counter" -#define D_CURRENT "전류" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "어둡게" -#define D_DEBUG "디버그" -#define D_DISABLED "사용안함" -#define D_DISTANCE "거리" -#define D_DNS_SERVER "DNS 서버" -#define D_DONE "완료" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "에뮬레이션" -#define D_ENABLED "사용" -#define D_ERASE "삭제" -#define D_ERROR "에러" -#define D_FAHRENHEIT "화씨" -#define D_FAILED "실패" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "거짓" -#define D_FILE "파일" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "남은 메모리" -#define D_FREQUENCY "Frequency" -#define D_GAS "가스" -#define D_GATEWAY "게이트웨이" -#define D_GROUP "그룹" -#define D_HOST "호스트" -#define D_HOSTNAME "호스트이름" -#define D_HUMIDITY "습도" -#define D_ILLUMINANCE "조도" -#define D_IMMEDIATE "immediate" // Button immediate -#define D_INDEX "인덱스" -#define D_INFO "정보" -#define D_INFRARED "적외선" -#define D_INITIALIZED "초기화됨" -#define D_IP_ADDRESS "IP 주소" -#define D_LIGHT "밝게" -#define D_LWT "LWT" -#define D_MODULE "모듈" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "소음" -#define D_NONE "없음" -#define D_OFF "꺼짐" -#define D_OFFLINE "오프라인" -#define D_OK "Ok" -#define D_ON "켜짐" -#define D_ONLINE "온라인" -#define D_PASSWORD "비밀번호" -#define D_PORT "포트" -#define D_POWER_FACTOR "Power Factor" -#define D_POWERUSAGE "전원" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "기압" -#define D_PRESSUREATSEALEVEL "해수면기압" -#define D_PROGRAM_FLASH_SIZE "플래시 용량" -#define D_PROGRAM_SIZE "프로그램 용량" -#define D_PROJECT "프로젝트" -#define D_RAIN "비" -#define D_RECEIVED "받음" -#define D_RESTART "재시작" -#define D_RESTARTING "재시작 중.." -#define D_RESTART_REASON "재시작 사유" -#define D_RESTORE "복구" -#define D_RETAINED "보류" -#define D_RULE "규칙" -#define D_SAVE "저장" -#define D_SENSOR "센서" -#define D_SSID "SSId" -#define D_START "시작" -#define D_STD_TIME "STD" -#define D_STOP "정지" -#define D_SUBNET_MASK "서브넷 마스크" -#define D_SUBSCRIBE_TO "구독" -#define D_UNSUBSCRIBE_FROM "구독 해제" -#define D_SUCCESSFUL "성공" -#define D_SUNRISE "일출" -#define D_SUNSET "일몰" -#define D_TEMPERATURE "온도" -#define D_TO "to" -#define D_TOGGLE "켜기/끄기" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "전체 사용량" -#define D_TRANSMIT "전송" -#define D_TRUE "참" -#define D_TVOC "TVOC" -#define D_UPGRADE "업그레이드" -#define D_UPLOAD "업로드" -#define D_UPTIME "가동시간" -#define D_USER "User" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV 색인" -#define D_UV_INDEX_1 "낮음" -#define D_UV_INDEX_2 "보통" -#define D_UV_INDEX_3 "높음" -#define D_UV_INDEX_4 "위험" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" // Out of Range -#define D_UV_LEVEL "UV 레벨" -#define D_UV_POWER "UV 파워" -#define D_VERSION "버전" -#define D_VOLTAGE "전압" -#define D_WEIGHT "무게" -#define D_WARMLIGHT "따뜻하게" -#define D_WEB_SERVER "웹 서버" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "경고: 이 버전은 영구 설정을 지원하지 않습니다" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial log 사용 안함" -#define D_SYSLOG_LOGGING_REENABLED "Syslog log 다시 사용" - -#define D_SET_BAUDRATE_TO "Set Baudrate to" -#define D_RECEIVED_TOPIC "Received Topic" -#define D_DATA_SIZE "데이터 용량" -#define D_ANALOG_INPUT "아날로그" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPS설정 실패" -#define D_ACTIVE_FOR_3_MINUTES "3분동안 활성화" -#define D_FAILED_TO_START "시작 실패" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "AP에 연결 중" -#define D_IN_MODE "in mode" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP 주소가 수신되지 않아 연결이 실패했습니다" -#define D_CONNECT_FAILED_AP_NOT_REACHED "연결이 닿지 않아 AP에 연결할 수 없습니다" -#define D_CONNECT_FAILED_WRONG_PASSWORD "비밀번호가 틀려 AP에 연결할 수 없습니다" -#define D_CONNECT_FAILED_AP_TIMEOUT "시간초과로 AP에 연결할 수 없습니다" -#define D_ATTEMPTING_CONNECTION "연결 시도 중..." -#define D_CHECKING_CONNECTION "연결 체크 중..." -#define D_QUERY_DONE "쿼리 완료. MQTT 서비스 발견" -#define D_MQTT_SERVICE_FOUND "MQTT 서비스 발견" -#define D_FOUND_AT "다음을 발견" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog 호스트가 발견되지 않았습니다" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "플래시에 저장" -#define D_LOADED_FROM_FLASH_AT "플래시에서 로드" -#define D_USE_DEFAULTS "디폴트 사용" -#define D_ERASED_SECTOR "삭제된 섹터" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" -#define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" -#define D_WITH_IP_ADDRESS "IP 주소" -#define D_WEBSERVER_STOPPED "Web 서버 멈춤" -#define D_FILE_NOT_FOUND "파일을 찾을 수 없습니다" -#define D_REDIRECTED "인증 페이지로 리디렉션" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "와이파이 매니저가 AccessPoint와 keep Station을 설정" -#define D_WIFIMANAGER_SET_ACCESSPOINT "와이파이 매니저가 AccessPoint를 설정" -#define D_TRYING_TO_CONNECT "장치를 네트워크에 연결하려고 시도 중" - -#define D_RESTART_IN "재시작" -#define D_SECONDS "초" -#define D_DEVICE_WILL_RESTART "이 장치는 몇 초 후 재시작됩니다" -#define D_BUTTON_TOGGLE "켜기/끄기" -#define D_CONFIGURATION "설정 메뉴" -#define D_INFORMATION "정보" -#define D_FIRMWARE_UPGRADE "펌웨어 업그레이드" -#define D_CONSOLE "콘솔" -#define D_CONFIRM_RESTART "재시작" - -#define D_CONFIGURE_MODULE "모듈 설정" -#define D_CONFIGURE_WIFI "WiFi 설정" -#define D_CONFIGURE_MQTT "MQTT 설정" -#define D_CONFIGURE_DOMOTICZ "Domoticz 설정" -#define D_CONFIGURE_LOGGING "로그 설정" -#define D_CONFIGURE_OTHER "기타 설정" -#define D_CONFIRM_RESET_CONFIGURATION "설정 초기화 확인" -#define D_RESET_CONFIGURATION "설정 초기화" -#define D_BACKUP_CONFIGURATION "설정 백업" -#define D_RESTORE_CONFIGURATION "설정 복구" -#define D_MAIN_MENU "메인 메뉴" - -#define D_MODULE_PARAMETERS "모듈 설정" -#define D_MODULE_TYPE "모듈 타입" -#define D_PULLUP_ENABLE "버튼 없음/스위치 당김" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Wifi 설정" -#define D_SCAN_FOR_WIFI_NETWORKS "Wifi 네트워크를 검색.." -#define D_SCAN_DONE "검색 완료" -#define D_NO_NETWORKS_FOUND "발견된 네트워크가 없습니다" -#define D_REFRESH_TO_SCAN_AGAIN "검색 재시도" -#define D_DUPLICATE_ACCESSPOINT "중복된 AccessPoint" -#define D_SKIPPING_LOW_QUALITY "약한 네트워크 신호 무시" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 비밀번호" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 비밀번호" - -#define D_MQTT_PARAMETERS "MQTT 설정" -#define D_CLIENT "클라이언트" -#define D_FULL_TOPIC "Full Topic" - -#define D_LOGGING_PARAMETERS "로그 설정" -#define D_SERIAL_LOG_LEVEL "Serial 로그 레벨" -#define D_MQTT_LOG_LEVEL "Mqtt 로그 레벨" -#define D_WEB_LOG_LEVEL "Web 로그 레벨" -#define D_SYS_LOG_LEVEL "시스템로그 레벨" -#define D_MORE_DEBUG "More debug" -#define D_SYSLOG_HOST "시스템로그 호스트" -#define D_SYSLOG_PORT "시스템로그 포트" -#define D_TELEMETRY_PERIOD "보고 주기" - -#define D_OTHER_PARAMETERS "기타 설정" -#define D_TEMPLATE "템플릿" -#define D_ACTIVATE "활성화" -#define D_WEB_ADMIN_PASSWORD "Web Admin 비밀번호" -#define D_MQTT_ENABLE "MQTT 사용" -#define D_FRIENDLY_NAME "Friendly Name" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "단일 장치" -#define D_MULTI_DEVICE "다수 장치" - -#define D_CONFIGURE_TEMPLATE "템플릿 설정" -#define D_TEMPLATE_PARAMETERS "템플릿 설정" -#define D_TEMPLATE_NAME "이름" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "옵션" - -#define D_SAVE_CONFIGURATION "설정 저장" -#define D_CONFIGURATION_SAVED "설정 저장 완료" -#define D_CONFIGURATION_RESET "설정 초기화" - -#define D_PROGRAM_VERSION "프로그램 버전" -#define D_BUILD_DATE_AND_TIME "빌드 날짜" -#define D_CORE_AND_SDK_VERSION "Core/SDK 버전" -#define D_FLASH_WRITE_COUNT "플래시 쓰기 횟수" -#define D_MAC_ADDRESS "MAC 주소" -#define D_MQTT_HOST "MQTT 호스트" -#define D_MQTT_PORT "MQTT 포트" -#define D_MQTT_CLIENT "MQTT 클라이언트" -#define D_MQTT_USER "MQTT 아이디" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" -#define D_MQTT_FULL_TOPIC "MQTT Full Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP 칩 Id" -#define D_FLASH_CHIP_ID "플래시 칩 Id" -#define D_FLASH_CHIP_SIZE "플래시 용량" -#define D_FREE_PROGRAM_SPACE "여유 프로그램 공간" - -#define D_UPGRADE_BY_WEBSERVER "웹 서버에서 업그레이드" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "업그레이드 시작" -#define D_UPGRADE_BY_FILE_UPLOAD "파일에서 업로드해 업그레이드" -#define D_UPLOAD_STARTED "업로드 시작됨" -#define D_UPGRADE_STARTED "업그레이드 시작됨" -#define D_UPLOAD_DONE "업그레이드 완료" -#define D_UPLOAD_ERR_1 "파일이 선택되지 않았습니다" -#define D_UPLOAD_ERR_2 "용량이 충분하지 않습니다" -#define D_UPLOAD_ERR_3 "Magic 바이트가 0xE9가 아닙니다" -#define D_UPLOAD_ERR_4 "플래시 프로그램이 실제 플래시 용량보다 큽니다" -#define D_UPLOAD_ERR_5 "업로드 버퍼가 일치하지 않습니다" -#define D_UPLOAD_ERR_6 "업로드 실패. 로그 3 사용" -#define D_UPLOAD_ERR_7 "업로드 중단" -#define D_UPLOAD_ERR_8 "파일이 유효하지 않습니다" -#define D_UPLOAD_ERR_9 "용량이 초과되었습니다" -#define D_UPLOAD_ERR_10 "RF 칩 초기화 실패" -#define D_UPLOAD_ERR_11 "RF 칩 삭제 실패" -#define D_UPLOAD_ERR_12 "RF 칩 쓰기 실패" -#define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패" -#define D_UPLOAD_ERROR_CODE "업로드 에러 코드" - -#define D_ENTER_COMMAND "커맨드 입력" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "응답이 있다면 Weblog 2를 사용" -#define D_NEED_USER_AND_PASSWORD "user=<아이디>&password=<비밀번호> 필요" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "TLS 지문 확인..." -#define D_TLS_CONNECT_FAILED_TO "TLS 연결 실패" -#define D_RETRY_IN "재시도 중" -#define D_VERIFIED "지문 확인 완료" -#define D_INSECURE "유효하지 않은 지문으로 연결이 되지 않았습니다" -#define D_CONNECT_FAILED_TO "연결 실패" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast 사용 불가" -#define D_MULTICAST_REJOINED "Multicast (다시)가입됨" -#define D_MULTICAST_JOIN_FAILED "Multicast 가입 실패" -#define D_FAILED_TO_SEND_RESPONSE "요청 전송 실패" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo 기본 이벤트" -#define D_WEMO_EVENT_SERVICE "WeMo 이벤트 서비스" -#define D_WEMO_META_SERVICE "WeMo meta 서비스" -#define D_WEMO_SETUP "WeMo 설정" -#define D_RESPONSE_SENT "요청 전송됨" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue 설정" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API가 포함되지 않음" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 요청 패킷이 전송됨" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz 설정" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "스위치 idx" -#define D_DOMOTICZ_SENSOR_IDX "센서 idx" - #define D_DOMOTICZ_TEMP "온도" - #define D_DOMOTICZ_TEMP_HUM "온도,습도" - #define D_DOMOTICZ_TEMP_HUM_BARO "온도,습도,기압" - #define D_DOMOTICZ_POWER_ENERGY "전력,전력량" - #define D_DOMOTICZ_ILLUMINANCE "조도" - #define D_DOMOTICZ_COUNT "횟수/PM1" - #define D_DOMOTICZ_VOLTAGE "전압/PM2.5" - #define D_DOMOTICZ_CURRENT "전류/PM10" - #define D_DOMOTICZ_AIRQUALITY "공기질" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "타이머 갱신" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "타이머 설정" -#define D_TIMER_PARAMETERS "타이머 설정" -#define D_TIMER_ENABLE "타이머 사용" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "시간" -#define D_TIMER_DAYS "일" -#define D_TIMER_REPEAT "반복" -#define D_TIMER_OUTPUT "출력" -#define D_TIMER_ACTION "행동" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX 설정" -#define D_KNX_PARAMETERS "KNX 설정" -#define D_KNX_GENERAL_CONFIG "일반" -#define D_KNX_PHYSICAL_ADDRESS "물리적 주소" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( KNX 네트워크 상에서 반드시 고유한 이름이어야 합니다 )" -#define D_KNX_ENABLE "KNX 사용" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "그룹 주소로 데이타를 보냅니다" -#define D_ADD "추가" -#define D_DELETE "삭제" -#define D_REPLY "응답" -#define D_KNX_GROUP_ADDRESS_TO_READ "받은 데이터의 그룹 주소" -#define D_RECEIVED_FROM "다음에서 받음" -#define D_KNX_COMMAND_WRITE "쓰기" -#define D_KNX_COMMAND_READ "읽기" -#define D_KNX_COMMAND_OTHER "기타" -#define D_SENT_TO "다음으로 보내기" -#define D_KNX_WARNING "그룹 주소 ( 0 / 0 / 0 )은 예약되어 사용할 수 없습니다" -#define D_KNX_ENHANCEMENT "커뮤니케이션 강화" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "금일 전력 사용량" -#define D_ENERGY_YESTERDAY "어제 전력 사용량" -#define D_ENERGY_TOTAL "총 전력 사용량" - -// xdrv_27_shutter.ino -#define D_OPEN "열기" -#define D_CLOSE "닫기" -#define D_DOMOTICZ_SHUTTER "셔터" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "PCF8574 설정" -#define D_PCF8574_PARAMETERS "PCF8574 파라미터" -#define D_INVERT_PORTS "포트 반전" -#define D_DEVICE "장치" -#define D_DEVICE_INPUT "입력" -#define D_DEVICE_OUTPUT "출력" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "센서가 사용 중" -#define D_SENSOR_CRC_ERROR "센서 CRC 에러" -#define D_SENSORS_FOUND "센서 발견" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "대기 시간 초과" -#define D_START_SIGNAL_LOW "시작 신호 낮음" -#define D_START_SIGNAL_HIGH "시작 신호 높음" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "체크섬 실패" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "센서가 ACK 명령을 수행하지 않음" -#define D_SHT1X_FOUND "SHT1X 발견" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "입자" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "중량 제거" -#define D_HX_CAL_REFERENCE "참조 중량 로드" -#define D_HX_CAL_DONE "교정됨" -#define D_HX_CAL_FAIL "교정 실패" -#define D_RESET_HX711 "스케일 초기화" -#define D_CONFIGURE_HX711 "스케일 설정" -#define D_HX711_PARAMETERS "스케일 상세" -#define D_ITEM_WEIGHT "아이템 중량" -#define D_REFERENCE_WEIGHT "참조 중량" -#define D_CALIBRATE "교정" -#define D_CALIBRATION "교정" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "풍향" -#define D_TX20_WIND_SPEED "풍속" -#define D_TX20_WIND_SPEED_AVG "평균 풍속" -#define D_TX20_WIND_SPEED_MAX "최대 풍속" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "없음" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "시" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "마이크로미터" -#define D_UNIT_MICROSECOND "마이크로초" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "밀리초" -#define D_UNIT_MINUTE "분" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "초" -#define D_UNIT_SECTORS "섹터" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_KO_KO_H_ +/* + ko-KO.h - localization for Korean - Korean for Tasmota + + Copyright (C) 2019 Theo Arends (translated by NyaamZ) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_KO_KO_H_ +#define _LANGUAGE_KO_KO_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.11 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 1042 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "ko" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "일 월 화 수 목 금 토 " +#define D_MONTH3LIST "1월 2월 3월 4월 5월 6월 7월 8월 9월 10월11월12월" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "공기질" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "자동" +#define D_BLINK "깜박임" +#define D_BLINKOFF "깜박임 끄기" +#define D_BOOT_COUNT "부팅 횟수" +#define D_BRIGHTLIGHT "밝게" +#define D_BSSID "BSSId" +#define D_BUTTON "버튼" +#define D_BY "by" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "섭씨" +#define D_CHANNEL "채널" +#define D_CO2 "이산화탄소" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "차갑게" +#define D_COMMAND "커맨드" +#define D_CONNECTED "연결됨" +#define D_COUNT "횟수" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNTER "Counter" +#define D_CURRENT "전류" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "어둡게" +#define D_DEBUG "디버그" +#define D_DISABLED "사용안함" +#define D_DISTANCE "거리" +#define D_DNS_SERVER "DNS 서버" +#define D_DONE "완료" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "에뮬레이션" +#define D_ENABLED "사용" +#define D_ERASE "삭제" +#define D_ERROR "에러" +#define D_FAHRENHEIT "화씨" +#define D_FAILED "실패" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "거짓" +#define D_FILE "파일" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "남은 메모리" +#define D_FREQUENCY "Frequency" +#define D_GAS "가스" +#define D_GATEWAY "게이트웨이" +#define D_GROUP "그룹" +#define D_HOST "호스트" +#define D_HOSTNAME "호스트이름" +#define D_HUMIDITY "습도" +#define D_ILLUMINANCE "조도" +#define D_IMMEDIATE "immediate" // Button immediate +#define D_INDEX "인덱스" +#define D_INFO "정보" +#define D_INFRARED "적외선" +#define D_INITIALIZED "초기화됨" +#define D_IP_ADDRESS "IP 주소" +#define D_LIGHT "밝게" +#define D_LWT "LWT" +#define D_MODULE "모듈" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "소음" +#define D_NONE "없음" +#define D_OFF "꺼짐" +#define D_OFFLINE "오프라인" +#define D_OK "Ok" +#define D_ON "켜짐" +#define D_ONLINE "온라인" +#define D_PASSWORD "비밀번호" +#define D_PORT "포트" +#define D_POWER_FACTOR "Power Factor" +#define D_POWERUSAGE "전원" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "기압" +#define D_PRESSUREATSEALEVEL "해수면기압" +#define D_PROGRAM_FLASH_SIZE "플래시 용량" +#define D_PROGRAM_SIZE "프로그램 용량" +#define D_PROJECT "프로젝트" +#define D_RAIN "비" +#define D_RECEIVED "받음" +#define D_RESTART "재시작" +#define D_RESTARTING "재시작 중.." +#define D_RESTART_REASON "재시작 사유" +#define D_RESTORE "복구" +#define D_RETAINED "보류" +#define D_RULE "규칙" +#define D_SAVE "저장" +#define D_SENSOR "센서" +#define D_SSID "SSId" +#define D_START "시작" +#define D_STD_TIME "STD" +#define D_STOP "정지" +#define D_SUBNET_MASK "서브넷 마스크" +#define D_SUBSCRIBE_TO "구독" +#define D_UNSUBSCRIBE_FROM "구독 해제" +#define D_SUCCESSFUL "성공" +#define D_SUNRISE "일출" +#define D_SUNSET "일몰" +#define D_TEMPERATURE "온도" +#define D_TO "to" +#define D_TOGGLE "켜기/끄기" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "전체 사용량" +#define D_TRANSMIT "전송" +#define D_TRUE "참" +#define D_TVOC "TVOC" +#define D_UPGRADE "업그레이드" +#define D_UPLOAD "업로드" +#define D_UPTIME "가동시간" +#define D_USER "User" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV 색인" +#define D_UV_INDEX_1 "낮음" +#define D_UV_INDEX_2 "보통" +#define D_UV_INDEX_3 "높음" +#define D_UV_INDEX_4 "위험" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" // Out of Range +#define D_UV_LEVEL "UV 레벨" +#define D_UV_POWER "UV 파워" +#define D_VERSION "버전" +#define D_VOLTAGE "전압" +#define D_WEIGHT "무게" +#define D_WARMLIGHT "따뜻하게" +#define D_WEB_SERVER "웹 서버" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "경고: 이 버전은 영구 설정을 지원하지 않습니다" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial log 사용 안함" +#define D_SYSLOG_LOGGING_REENABLED "Syslog log 다시 사용" + +#define D_SET_BAUDRATE_TO "Set Baudrate to" +#define D_RECEIVED_TOPIC "Received Topic" +#define D_DATA_SIZE "데이터 용량" +#define D_ANALOG_INPUT "아날로그" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPS설정 실패" +#define D_ACTIVE_FOR_3_MINUTES "3분동안 활성화" +#define D_FAILED_TO_START "시작 실패" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "AP에 연결 중" +#define D_IN_MODE "in mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP 주소가 수신되지 않아 연결이 실패했습니다" +#define D_CONNECT_FAILED_AP_NOT_REACHED "연결이 닿지 않아 AP에 연결할 수 없습니다" +#define D_CONNECT_FAILED_WRONG_PASSWORD "비밀번호가 틀려 AP에 연결할 수 없습니다" +#define D_CONNECT_FAILED_AP_TIMEOUT "시간초과로 AP에 연결할 수 없습니다" +#define D_ATTEMPTING_CONNECTION "연결 시도 중..." +#define D_CHECKING_CONNECTION "연결 체크 중..." +#define D_QUERY_DONE "쿼리 완료. MQTT 서비스 발견" +#define D_MQTT_SERVICE_FOUND "MQTT 서비스 발견" +#define D_FOUND_AT "다음을 발견" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog 호스트가 발견되지 않았습니다" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "플래시에 저장" +#define D_LOADED_FROM_FLASH_AT "플래시에서 로드" +#define D_USE_DEFAULTS "디폴트 사용" +#define D_ERASED_SECTOR "삭제된 섹터" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오." +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
업그레이드가 필요합니다" +#define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중" +#define D_WITH_IP_ADDRESS "IP 주소" +#define D_WEBSERVER_STOPPED "Web 서버 멈춤" +#define D_FILE_NOT_FOUND "파일을 찾을 수 없습니다" +#define D_REDIRECTED "인증 페이지로 리디렉션" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "와이파이 매니저가 AccessPoint와 keep Station을 설정" +#define D_WIFIMANAGER_SET_ACCESSPOINT "와이파이 매니저가 AccessPoint를 설정" +#define D_TRYING_TO_CONNECT "장치를 네트워크에 연결하려고 시도 중" + +#define D_RESTART_IN "재시작" +#define D_SECONDS "초" +#define D_DEVICE_WILL_RESTART "이 장치는 몇 초 후 재시작됩니다" +#define D_BUTTON_TOGGLE "켜기/끄기" +#define D_CONFIGURATION "설정 메뉴" +#define D_INFORMATION "정보" +#define D_FIRMWARE_UPGRADE "펌웨어 업그레이드" +#define D_CONSOLE "콘솔" +#define D_CONFIRM_RESTART "재시작" + +#define D_CONFIGURE_MODULE "모듈 설정" +#define D_CONFIGURE_WIFI "WiFi 설정" +#define D_CONFIGURE_MQTT "MQTT 설정" +#define D_CONFIGURE_DOMOTICZ "Domoticz 설정" +#define D_CONFIGURE_LOGGING "로그 설정" +#define D_CONFIGURE_OTHER "기타 설정" +#define D_CONFIRM_RESET_CONFIGURATION "설정 초기화 확인" +#define D_RESET_CONFIGURATION "설정 초기화" +#define D_BACKUP_CONFIGURATION "설정 백업" +#define D_RESTORE_CONFIGURATION "설정 복구" +#define D_MAIN_MENU "메인 메뉴" + +#define D_MODULE_PARAMETERS "모듈 설정" +#define D_MODULE_TYPE "모듈 타입" +#define D_PULLUP_ENABLE "버튼 없음/스위치 당김" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Wifi 설정" +#define D_SCAN_FOR_WIFI_NETWORKS "Wifi 네트워크를 검색.." +#define D_SCAN_DONE "검색 완료" +#define D_NO_NETWORKS_FOUND "발견된 네트워크가 없습니다" +#define D_REFRESH_TO_SCAN_AGAIN "검색 재시도" +#define D_DUPLICATE_ACCESSPOINT "중복된 AccessPoint" +#define D_SKIPPING_LOW_QUALITY "약한 네트워크 신호 무시" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 비밀번호" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 비밀번호" + +#define D_MQTT_PARAMETERS "MQTT 설정" +#define D_CLIENT "클라이언트" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "로그 설정" +#define D_SERIAL_LOG_LEVEL "Serial 로그 레벨" +#define D_MQTT_LOG_LEVEL "Mqtt 로그 레벨" +#define D_WEB_LOG_LEVEL "Web 로그 레벨" +#define D_SYS_LOG_LEVEL "시스템로그 레벨" +#define D_MORE_DEBUG "More debug" +#define D_SYSLOG_HOST "시스템로그 호스트" +#define D_SYSLOG_PORT "시스템로그 포트" +#define D_TELEMETRY_PERIOD "보고 주기" + +#define D_OTHER_PARAMETERS "기타 설정" +#define D_TEMPLATE "템플릿" +#define D_ACTIVATE "활성화" +#define D_WEB_ADMIN_PASSWORD "Web Admin 비밀번호" +#define D_MQTT_ENABLE "MQTT 사용" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "단일 장치" +#define D_MULTI_DEVICE "다수 장치" + +#define D_CONFIGURE_TEMPLATE "템플릿 설정" +#define D_TEMPLATE_PARAMETERS "템플릿 설정" +#define D_TEMPLATE_NAME "이름" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "옵션" + +#define D_SAVE_CONFIGURATION "설정 저장" +#define D_CONFIGURATION_SAVED "설정 저장 완료" +#define D_CONFIGURATION_RESET "설정 초기화" + +#define D_PROGRAM_VERSION "프로그램 버전" +#define D_BUILD_DATE_AND_TIME "빌드 날짜" +#define D_CORE_AND_SDK_VERSION "Core/SDK 버전" +#define D_FLASH_WRITE_COUNT "플래시 쓰기 횟수" +#define D_MAC_ADDRESS "MAC 주소" +#define D_MQTT_HOST "MQTT 호스트" +#define D_MQTT_PORT "MQTT 포트" +#define D_MQTT_CLIENT "MQTT 클라이언트" +#define D_MQTT_USER "MQTT 아이디" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Group Topic" +#define D_MQTT_FULL_TOPIC "MQTT Full Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP 칩 Id" +#define D_FLASH_CHIP_ID "플래시 칩 Id" +#define D_FLASH_CHIP_SIZE "플래시 용량" +#define D_FREE_PROGRAM_SPACE "여유 프로그램 공간" + +#define D_UPGRADE_BY_WEBSERVER "웹 서버에서 업그레이드" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "업그레이드 시작" +#define D_UPGRADE_BY_FILE_UPLOAD "파일에서 업로드해 업그레이드" +#define D_UPLOAD_STARTED "업로드 시작됨" +#define D_UPGRADE_STARTED "업그레이드 시작됨" +#define D_UPLOAD_DONE "업그레이드 완료" +#define D_UPLOAD_ERR_1 "파일이 선택되지 않았습니다" +#define D_UPLOAD_ERR_2 "용량이 충분하지 않습니다" +#define D_UPLOAD_ERR_3 "Magic 바이트가 0xE9가 아닙니다" +#define D_UPLOAD_ERR_4 "플래시 프로그램이 실제 플래시 용량보다 큽니다" +#define D_UPLOAD_ERR_5 "업로드 버퍼가 일치하지 않습니다" +#define D_UPLOAD_ERR_6 "업로드 실패. 로그 3 사용" +#define D_UPLOAD_ERR_7 "업로드 중단" +#define D_UPLOAD_ERR_8 "파일이 유효하지 않습니다" +#define D_UPLOAD_ERR_9 "용량이 초과되었습니다" +#define D_UPLOAD_ERR_10 "RF 칩 초기화 실패" +#define D_UPLOAD_ERR_11 "RF 칩 삭제 실패" +#define D_UPLOAD_ERR_12 "RF 칩 쓰기 실패" +#define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패" +#define D_UPLOAD_ERROR_CODE "업로드 에러 코드" + +#define D_ENTER_COMMAND "커맨드 입력" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "응답이 있다면 Weblog 2를 사용" +#define D_NEED_USER_AND_PASSWORD "user=<아이디>&password=<비밀번호> 필요" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "TLS 지문 확인..." +#define D_TLS_CONNECT_FAILED_TO "TLS 연결 실패" +#define D_RETRY_IN "재시도 중" +#define D_VERIFIED "지문 확인 완료" +#define D_INSECURE "유효하지 않은 지문으로 연결이 되지 않았습니다" +#define D_CONNECT_FAILED_TO "연결 실패" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast 사용 불가" +#define D_MULTICAST_REJOINED "Multicast (다시)가입됨" +#define D_MULTICAST_JOIN_FAILED "Multicast 가입 실패" +#define D_FAILED_TO_SEND_RESPONSE "요청 전송 실패" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo 기본 이벤트" +#define D_WEMO_EVENT_SERVICE "WeMo 이벤트 서비스" +#define D_WEMO_META_SERVICE "WeMo meta 서비스" +#define D_WEMO_SETUP "WeMo 설정" +#define D_RESPONSE_SENT "요청 전송됨" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue 설정" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API가 포함되지 않음" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 요청 패킷이 전송됨" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz 설정" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "스위치 idx" +#define D_DOMOTICZ_SENSOR_IDX "센서 idx" + #define D_DOMOTICZ_TEMP "온도" + #define D_DOMOTICZ_TEMP_HUM "온도,습도" + #define D_DOMOTICZ_TEMP_HUM_BARO "온도,습도,기압" + #define D_DOMOTICZ_POWER_ENERGY "전력,전력량" + #define D_DOMOTICZ_ILLUMINANCE "조도" + #define D_DOMOTICZ_COUNT "횟수/PM1" + #define D_DOMOTICZ_VOLTAGE "전압/PM2.5" + #define D_DOMOTICZ_CURRENT "전류/PM10" + #define D_DOMOTICZ_AIRQUALITY "공기질" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "타이머 갱신" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "타이머 설정" +#define D_TIMER_PARAMETERS "타이머 설정" +#define D_TIMER_ENABLE "타이머 사용" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "시간" +#define D_TIMER_DAYS "일" +#define D_TIMER_REPEAT "반복" +#define D_TIMER_OUTPUT "출력" +#define D_TIMER_ACTION "행동" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX 설정" +#define D_KNX_PARAMETERS "KNX 설정" +#define D_KNX_GENERAL_CONFIG "일반" +#define D_KNX_PHYSICAL_ADDRESS "물리적 주소" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( KNX 네트워크 상에서 반드시 고유한 이름이어야 합니다 )" +#define D_KNX_ENABLE "KNX 사용" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "그룹 주소로 데이타를 보냅니다" +#define D_ADD "추가" +#define D_DELETE "삭제" +#define D_REPLY "응답" +#define D_KNX_GROUP_ADDRESS_TO_READ "받은 데이터의 그룹 주소" +#define D_RECEIVED_FROM "다음에서 받음" +#define D_KNX_COMMAND_WRITE "쓰기" +#define D_KNX_COMMAND_READ "읽기" +#define D_KNX_COMMAND_OTHER "기타" +#define D_SENT_TO "다음으로 보내기" +#define D_KNX_WARNING "그룹 주소 ( 0 / 0 / 0 )은 예약되어 사용할 수 없습니다" +#define D_KNX_ENHANCEMENT "커뮤니케이션 강화" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "금일 전력 사용량" +#define D_ENERGY_YESTERDAY "어제 전력 사용량" +#define D_ENERGY_TOTAL "총 전력 사용량" + +// xdrv_27_shutter.ino +#define D_OPEN "열기" +#define D_CLOSE "닫기" +#define D_DOMOTICZ_SHUTTER "셔터" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "PCF8574 설정" +#define D_PCF8574_PARAMETERS "PCF8574 파라미터" +#define D_INVERT_PORTS "포트 반전" +#define D_DEVICE "장치" +#define D_DEVICE_INPUT "입력" +#define D_DEVICE_OUTPUT "출력" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "센서가 사용 중" +#define D_SENSOR_CRC_ERROR "센서 CRC 에러" +#define D_SENSORS_FOUND "센서 발견" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "대기 시간 초과" +#define D_START_SIGNAL_LOW "시작 신호 낮음" +#define D_START_SIGNAL_HIGH "시작 신호 높음" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "체크섬 실패" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "센서가 ACK 명령을 수행하지 않음" +#define D_SHT1X_FOUND "SHT1X 발견" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "입자" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "중량 제거" +#define D_HX_CAL_REFERENCE "참조 중량 로드" +#define D_HX_CAL_DONE "교정됨" +#define D_HX_CAL_FAIL "교정 실패" +#define D_RESET_HX711 "스케일 초기화" +#define D_CONFIGURE_HX711 "스케일 설정" +#define D_HX711_PARAMETERS "스케일 상세" +#define D_ITEM_WEIGHT "아이템 중량" +#define D_REFERENCE_WEIGHT "참조 중량" +#define D_CALIBRATE "교정" +#define D_CALIBRATION "교정" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "풍향" +#define D_TX20_WIND_SPEED "풍속" +#define D_TX20_WIND_SPEED_AVG "평균 풍속" +#define D_TX20_WIND_SPEED_MAX "최대 풍속" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "없음" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "시" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "마이크로미터" +#define D_UNIT_MICROSECOND "마이크로초" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "밀리초" +#define D_UNIT_MINUTE "분" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "초" +#define D_UNIT_SECTORS "섹터" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_KO_KO_H_ diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index cd1414f8f..75d841ddc 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -1,703 +1,701 @@ -/* - nl-NL.h - localization for Dutch - Nederland for Tasmota - - Copyright (C) 2019 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_NL_NL_H_ -#define _LANGUAGE_NL_NL_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.7.0 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1043 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "nl" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "Zo Ma Di Wo Do Vr Za " -#define D_MONTH3LIST "JanFebMarAprMeiJunJulAugSepOktNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Lucht kwaliteit" -#define D_AP "AP" // Access Point -#define D_AS "als" -#define D_AUTO "AUTO" -#define D_BLINK "Knipper" -#define D_BLINKOFF "KnipperUit" -#define D_BOOT_COUNT "Herstarts" -#define D_BRIGHTLIGHT "Fel" -#define D_BSSID "BSSId" -#define D_BUTTON "DrukKnop" -#define D_BY "door" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Kanaal" -#define D_CO2 "Koolstofdioxide" -#define D_CODE "code" // Button code -#define D_COLDLIGHT "Koud" -#define D_COMMAND "Opdracht" -#define D_CONNECTED "Verbonden" -#define D_COUNT "Aantal" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNTER "Teller" -#define D_CURRENT "Stroom" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Donker" -#define D_DEBUG "Debug" -#define D_DISABLED "Uitgeschakeld" -#define D_DISTANCE "Afstand" -#define D_DNS_SERVER "DNS Server" -#define D_DONE "Klaar" -#define D_DST_TIME "ZT" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulatie" -#define D_ENABLED "Geactiveerd" -#define D_ERASE "Wissen" -#define D_ERROR "Fout" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Mislukt" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "Onwaar" -#define D_FILE "Bestand" -#define D_FLOW_RATE "Debiet" -#define D_FREE_MEMORY "Vrij geheugen" -#define D_FREQUENCY "Frequentie" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Groep" -#define D_HOST "Host" -#define D_HOSTNAME "Hostnaam" -#define D_HUMIDITY "Luchtvochtigheid" -#define D_ILLUMINANCE "Verlichtingssterkte" -#define D_IMMEDIATE "onmiddelijk" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infrarood" -#define D_INITIALIZED "Geinitialiseerd" -#define D_IP_ADDRESS "IP Adres" -#define D_LIGHT "Licht" -#define D_LWT "LWT" -#define D_MODULE "Module" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "meervoudig" -#define D_NOISE "Lawaai" -#define D_NONE "Geen" -#define D_OFF "Uit" -#define D_OFFLINE "Offline" -#define D_OK "Ok" -#define D_ON "Aan" -#define D_ONLINE "Online" -#define D_PASSWORD "Wachtwoord" -#define D_PORT "Poort" -#define D_POWER_FACTOR "Arbeidsfactor" -#define D_POWERUSAGE "Vermogen" -#define D_POWERUSAGE_ACTIVE "Werkelijk vermogen" -#define D_POWERUSAGE_APPARENT "Schijnbaar vermogen" -#define D_POWERUSAGE_REACTIVE "Blindvermogen" -#define D_PRESSURE "Luchtdruk" -#define D_PRESSUREATSEALEVEL "ZeeLuchtdruk" -#define D_PROGRAM_FLASH_SIZE "Programma Flash Grootte" -#define D_PROGRAM_SIZE "Programma Grootte" -#define D_PROJECT "Project" -#define D_RAIN "Regen" -#define D_RECEIVED "Ontvangen" -#define D_RESTART "Herstart" -#define D_RESTARTING "Herstarten" -#define D_RESTART_REASON "Reden herstart" -#define D_RESTORE "herstellen" -#define D_RETAINED "retained" -#define D_RULE "Regel" -#define D_SAVE "Opslaan" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Start" -#define D_STD_TIME "WT" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Subnet Masker" -#define D_SUBSCRIBE_TO "Abonneer op" -#define D_UNSUBSCRIBE_FROM "Uitschrijven van" -#define D_SUCCESSFUL "Gelukt" -#define D_SUNRISE "Zonsopgang" -#define D_SUNSET "Zonsondergang" -#define D_TEMPERATURE "Temperatuur" -#define D_TO "naar" -#define D_TOGGLE "Toggle" // Wissel, Tuimel -#define D_TOPIC "Topic" // Onderwerp -#define D_TOTAL_USAGE "Totaal verbruik" -#define D_TRANSMIT "Verzend" -#define D_TRUE "Waar" -#define D_TVOC "TVOC" -#define D_UPGRADE "opwaarderen" -#define D_UPLOAD "Verzenden" -#define D_UPTIME "Bedrijfstijd" -#define D_USER "Gebruiker" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV-index" -#define D_UV_INDEX_1 "Laag" -#define D_UV_INDEX_2 "Gemiddeld" -#define D_UV_INDEX_3 "Hoog" -#define D_UV_INDEX_4 "Intens" -#define D_UV_INDEX_5 "Gevaarlijk" -#define D_UV_INDEX_6 "Schadelijk" -#define D_UV_INDEX_7 "Uitzonderlijk" -#define D_UV_LEVEL "UV niveau" -#define D_UV_POWER "UV intensiteit" -#define D_VERSION "Versie" -#define D_VOLTAGE "Spanning" -#define D_WEIGHT "Gewicht" -#define D_WARMLIGHT "Warm" -#define D_WEB_SERVER "Webserver" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "WAARSCHUWING Deze versie bewaart geen instellingen" -#define D_LEVEL_10 "niveau 1-0" -#define D_LEVEL_01 "niveau 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serieel logging uitgeschakeld" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logging weer ingeschakeld" - -#define D_SET_BAUDRATE_TO "Zet baudrate op" -#define D_RECEIVED_TOPIC "Ontvangen topic" -#define D_DATA_SIZE "Data lengte" -#define D_ANALOG_INPUT "Analoog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig mislukt met status" -#define D_ACTIVE_FOR_3_MINUTES "3 minuten actief" -#define D_FAILED_TO_START "mislukt" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "Verbinden met AP" -#define D_IN_MODE "in stand" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbinding mislukt omdat geen IP adres werd ontvangen" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbinding mislukt omdat AP onbereikbaar is" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbinding mislukt door fout wachtwoord" -#define D_CONNECT_FAILED_AP_TIMEOUT "Verbinding mislukt door AP time-out" -#define D_ATTEMPTING_CONNECTION "Verbinden..." -#define D_CHECKING_CONNECTION "Controleer verbinding..." -#define D_QUERY_DONE "Aanvraag klaar. Aantal MQTT diensten gevonden" -#define D_MQTT_SERVICE_FOUND "MQTT dienst gevonden op" -#define D_FOUND_AT "gevonden op" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host niet gevonden" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Opgeslagen in flash op" -#define D_LOADED_FROM_FLASH_AT "Geladen vanuit flash op" -#define D_USE_DEFAULTS "Gebruik standaardwaarden" -#define D_ERASED_SECTOR "Wis sector" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Zet JavaScript aan voor Tasmota" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
opwaarderen" -#define D_WEBSERVER_ACTIVE_ON "Webserver actief op" -#define D_WITH_IP_ADDRESS "met IP adres" -#define D_WEBSERVER_STOPPED "Webserver gestopt" -#define D_FILE_NOT_FOUND "Bestand niet gevonden" -#define D_REDIRECTED "Omleiding naar captive portal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager start AccessPoint en hou Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager start AccessPoint" -#define D_TRYING_TO_CONNECT "Apparaat probeert te verbinden met netwerk" - -#define D_RESTART_IN "Herstart over" -#define D_SECONDS "seconden" -#define D_DEVICE_WILL_RESTART "Herstart over enkele seconden" -#define D_BUTTON_TOGGLE "Toggle" // Wissel, Tuimel -#define D_CONFIGURATION "Configuratie" -#define D_INFORMATION "Informatie" -#define D_FIRMWARE_UPGRADE "Opwaarderen" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Bevestig herstart" - -#define D_CONFIGURE_MODULE "Configureer Module" -#define D_CONFIGURE_WIFI "Configureer WiFi" -#define D_CONFIGURE_MQTT "Configureer MQTT" -#define D_CONFIGURE_DOMOTICZ "Configureer Domoticz" -#define D_CONFIGURE_LOGGING "Configureer Logging" -#define D_CONFIGURE_OTHER "Configureer Overige" -#define D_CONFIRM_RESET_CONFIGURATION "Bevestig reset configuratie" -#define D_RESET_CONFIGURATION "Reset Configuratie" -#define D_BACKUP_CONFIGURATION "Bewaar Configuratie" -#define D_RESTORE_CONFIGURATION "Herstel Configuration" -#define D_MAIN_MENU "Hoofdmenu" - -#define D_MODULE_PARAMETERS "Module parameters" -#define D_MODULE_TYPE "Module soort" -#define D_PULLUP_ENABLE "Geen schakelaar pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serieel In" -#define D_SERIAL_OUT "Serieel Uit" - -#define D_WIFI_PARAMETERS "Wifi parameters" -#define D_SCAN_FOR_WIFI_NETWORKS "Zoek wifi netwerken" -#define D_SCAN_DONE "Scan klaar" -#define D_NO_NETWORKS_FOUND "Geen netwerken gevonden" -#define D_REFRESH_TO_SCAN_AGAIN "Vernieuw om opnieuw te zoeken" -#define D_DUPLICATE_ACCESSPOINT "Dubbel AccessPoint" -#define D_SKIPPING_LOW_QUALITY "Overslaan agv lage ontvangskwaliteit" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Wachtwoord" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Wachtwoord" - -#define D_MQTT_PARAMETERS "MQTT parameters" -#define D_CLIENT "Client" -#define D_FULL_TOPIC "Volledig Topic" - -#define D_LOGGING_PARAMETERS "Logging parameters" -#define D_SERIAL_LOG_LEVEL "Serieel log niveau" -#define D_MQTT_LOG_LEVEL "Mqtt log niveau" -#define D_WEB_LOG_LEVEL "Web log niveau" -#define D_SYS_LOG_LEVEL "Syslog niveau" -#define D_MORE_DEBUG "Meer debug" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog poort" -#define D_TELEMETRY_PERIOD "Telemetry periode" - -#define D_OTHER_PARAMETERS "Overige parameters" -#define D_TEMPLATE "Sjabloon" -#define D_ACTIVATE "Activeer" -#define D_WEB_ADMIN_PASSWORD "Web Admin Wachtwoord" -#define D_MQTT_ENABLE "MQTT ingeschakeld" -#define D_FRIENDLY_NAME "Beschrijvende naam" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "een apparaat" -#define D_MULTI_DEVICE "meer apparaten" - -#define D_CONFIGURE_TEMPLATE "Configureer Sjabloon" -#define D_TEMPLATE_PARAMETERS "Sjabloon parameters" -#define D_TEMPLATE_NAME "Naam" -#define D_BASE_TYPE "Op basis van" -#define D_TEMPLATE_FLAGS "Opties" - -#define D_SAVE_CONFIGURATION "Bewaar configuratie" -#define D_CONFIGURATION_SAVED "Configuratie opgeslagen" -#define D_CONFIGURATION_RESET "Configuratie ge-reset" - -#define D_PROGRAM_VERSION "Programma Versie" -#define D_BUILD_DATE_AND_TIME "Compileer Datum & Tijd" -#define D_CORE_AND_SDK_VERSION "Core/SDK Versie" -#define D_FLASH_WRITE_COUNT "Aantal Flash opslagen" -#define D_MAC_ADDRESS "MAC Adres" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Poort" -#define D_MQTT_CLIENT "MQTT Client" -#define D_MQTT_USER "MQTT Gebruiker" -#define D_MQTT_TOPIC "MQTT Topic" -#define D_MQTT_GROUP_TOPIC "MQTT Groep Topic" -#define D_MQTT_FULL_TOPIC "MQTT Volledig Topic" -#define D_MDNS_DISCOVERY "mDNS Discovery" -#define D_MDNS_ADVERTISE "mDNS Advertise" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Grootte" -#define D_FREE_PROGRAM_SPACE "Programma ruimte over" - -#define D_UPGRADE_BY_WEBSERVER "Opwaarderen dmv webserver" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Start opwaarderen" -#define D_UPGRADE_BY_FILE_UPLOAD "Opwaarderen dmv verzenden bestand" -#define D_UPLOAD_STARTED "Verzending gestart" -#define D_UPGRADE_STARTED "Opwaarderen gestart" -#define D_UPLOAD_DONE "Opwaarderen klaar" -#define D_UPLOAD_ERR_1 "Geen bestand gekozen" -#define D_UPLOAD_ERR_2 "Onvoldoende geheugen ruimte" -#define D_UPLOAD_ERR_3 "Magische byte is niet 0xE9" -#define D_UPLOAD_ERR_4 "Programma flash grootte is groter dan werkelijke flash grootte" -#define D_UPLOAD_ERR_5 "Opwaardeer buffer verschil" -#define D_UPLOAD_ERR_6 "Opwaarderen mislukt. Schakel logging 3 in" -#define D_UPLOAD_ERR_7 "Opwaarderen afgebroken" -#define D_UPLOAD_ERR_8 "Ongeldig bestand" -#define D_UPLOAD_ERR_9 "Bestand is te groot" -#define D_UPLOAD_ERR_10 "Init RF chip mislukt" -#define D_UPLOAD_ERR_11 "Wissen RF chip mislukt" -#define D_UPLOAD_ERR_12 "Opwaarderen RF chip mislukt" -#define D_UPLOAD_ERR_13 "Decoderen RF bestand mislukt" -#define D_UPLOAD_ERROR_CODE "Opwaardeer foutcode" - -#define D_ENTER_COMMAND "Geef opdracht" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Schakel weblog 2 in indien antwoord verwacht" -#define D_NEED_USER_AND_PASSWORD "Benodig user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Controleer TLS vingerafdruk..." -#define D_TLS_CONNECT_FAILED_TO "TLS Verbinding mislukt naar" -#define D_RETRY_IN "Opnieuw proberen over" -#define D_VERIFIED "Gecontroleerd met vingerafdruk" -#define D_INSECURE "Door ongeldige vingerafdruk een onveilige verbinding" -#define D_CONNECT_FAILED_TO "Verbinding mislukt naar" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast uitgeschakeld" -#define D_MULTICAST_REJOINED "Multicast verbonden" -#define D_MULTICAST_JOIN_FAILED "Multicast verbinding mislukt" -#define D_FAILED_TO_SEND_RESPONSE "Antwoord versturen mislukt" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basis gebeurtenis" -#define D_WEMO_EVENT_SERVICE "WeMo gebeurtenis dienst" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo installatie" -#define D_RESPONSE_SENT "Antwoord verstuurd" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue installatie" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API niet beschikbaar" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argumenten" -#define D_3_RESPONSE_PACKETS_SENT "3 antwoord paketten verstuurd" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Toets idx" -#define D_DOMOTICZ_SWITCH_IDX "Schakelaar idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Spanning/PM2,5" - #define D_DOMOTICZ_CURRENT "Stroom/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Bijwerk timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configureer Tijdschakelaar" -#define D_TIMER_PARAMETERS "Tijdschakelaar parameters" -#define D_TIMER_ENABLE "Tijdschakelaars inschakelen" -#define D_TIMER_ARM "Actief" -#define D_TIMER_TIME "Tijd" -#define D_TIMER_DAYS "Dagen" -#define D_TIMER_REPEAT "Herhaal" -#define D_TIMER_OUTPUT "Uitgang" -#define D_TIMER_ACTION "Actie" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configureer KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "Algemeen" -#define D_KNX_PHYSICAL_ADDRESS "Eigen adres" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Moet uniek zijn op het KNX netwerk)" -#define D_KNX_ENABLE "KNX inschakelen" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Stuur gegevens naar groep adressen" -#define D_ADD "Toevoegen" -#define D_DELETE "Verwijder" -#define D_REPLY "Antwoord" -#define D_KNX_GROUP_ADDRESS_TO_READ "Ontvang gegevens van groep adressen" -#define D_RECEIVED_FROM "Ontvangen van" -#define D_KNX_COMMAND_WRITE "Schrijven" -#define D_KNX_COMMAND_READ "Lezen" -#define D_KNX_COMMAND_OTHER "Overige" -#define D_SENT_TO "verzend naar" -#define D_KNX_WARNING "Groep adres (0/0/0) is gereserveerd en mag niet worden gebruikt." -#define D_KNX_ENHANCEMENT "Verbeter verbinding" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Verbruik vandaag" -#define D_ENERGY_YESTERDAY "Verbruik gisteren" -#define D_ENERGY_TOTAL "Verbruik totaal" - -// xdrv_27_shutter.ino -#define D_OPEN "Openen" -#define D_CLOSE "Sluiten" -#define D_DOMOTICZ_SHUTTER "Rolluik" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configureer PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 Parameters" -#define D_INVERT_PORTS "Inverteer Poorten" -#define D_DEVICE "Apparaat" -#define D_DEVICE_INPUT "Ingang" -#define D_DEVICE_OUTPUT "Uitgang" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor bezet" -#define D_SENSOR_CRC_ERROR "Sensor CRC fout" -#define D_SENSORS_FOUND "Aantal sensoren" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Te lang wachten op" -#define D_START_SIGNAL_LOW "laag start signaal" -#define D_START_SIGNAL_HIGH "hoog start signaal" -#define D_PULSE "signaal" -#define D_CHECKSUM_FAILURE "Controle mislukt" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Geen opdracht ACK van sensor" -#define D_SHT1X_FOUND "SHT1X gevonden" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Stofdeeltjes" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Verwijder gewicht" -#define D_HX_CAL_REFERENCE "Plaats ijkgewicht" -#define D_HX_CAL_DONE "Ge-ijkt" -#define D_HX_CAL_FAIL "Ijken is mislukt" -#define D_RESET_HX711 "Nulstelling weegschaal" -#define D_CONFIGURE_HX711 "Configureer Weegschaal" -#define D_HX711_PARAMETERS "Weegschaal parameters" -#define D_ITEM_WEIGHT "Gewicht van onderdeel" -#define D_REFERENCE_WEIGHT "Ijkgewicht" -#define D_CALIBRATE "Ijken" -#define D_CALIBRATION "Ijken" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Windrichting" -#define D_TX20_WIND_SPEED "Windsnelheid" -#define D_TX20_WIND_SPEED_AVG "Windsnelheid gemiddeld" -#define D_TX20_WIND_SPEED_MAX "Windsnelhied maximaal" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Geen" -#define D_SENSOR_USER "Gebruiker" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Speler" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relais" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Teller" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Zoemer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "h" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kΩ" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" -#define D_UNIT_MICROMETER "µm" -#define D_UNIT_MICROSECOND "µs" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectoren" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Fase hoek" -#define D_IMPORT_ACTIVE "Import werkelijk" -#define D_EXPORT_ACTIVE "Export werkelijk" -#define D_IMPORT_REACTIVE "Import blind" -#define D_EXPORT_REACTIVE "Export blind" -#define D_TOTAL_REACTIVE "Totaal blind" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 spanning" -#define D_PV1_CURRENT "PV1 stroom" -#define D_PV1_POWER "PV1 vermogen" -#define D_PV2_VOLTAGE "PV2 spanning" -#define D_PV2_CURRENT "PV2 stroom" -#define D_PV2_POWER "PV2 vermogen" -#define D_SOLAR_POWER "Zon vermogen" -#define D_INVERTER_POWER "Omvormer vermogen" -#define D_STATUS "Status" -#define D_WAITING "Wacht" -#define D_CHECKING "Controle" -#define D_WORKING "Actief" -#define D_FAILURE "Fout" -#define D_SOLAX_ERROR_0 "Geen" -#define D_SOLAX_ERROR_1 "Netverbinding" -#define D_SOLAX_ERROR_2 "Netspanning" -#define D_SOLAX_ERROR_3 "Netfrequentie" -#define D_SOLAX_ERROR_4 "Pv spanning" -#define D_SOLAX_ERROR_5 "Isolatie" -#define D_SOLAX_ERROR_6 "Overtemperatuur" -#define D_SOLAX_ERROR_7 "Ventilator" -#define D_SOLAX_ERROR_8 "Overige" - -#endif // _LANGUAGE_NL_NL_H_ +/* + nl-NL.h - localization for Dutch - Nederland for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_NL_NL_H_ +#define _LANGUAGE_NL_NL_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.7.0 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1043 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "nl" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "Zo Ma Di Wo Do Vr Za " +#define D_MONTH3LIST "JanFebMarAprMeiJunJulAugSepOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Lucht kwaliteit" +#define D_AP "AP" // Access Point +#define D_AS "als" +#define D_AUTO "AUTO" +#define D_BLINK "Knipper" +#define D_BLINKOFF "KnipperUit" +#define D_BOOT_COUNT "Herstarts" +#define D_BRIGHTLIGHT "Fel" +#define D_BSSID "BSSId" +#define D_BUTTON "DrukKnop" +#define D_BY "door" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanaal" +#define D_CO2 "Koolstofdioxide" +#define D_CODE "code" // Button code +#define D_COLDLIGHT "Koud" +#define D_COMMAND "Opdracht" +#define D_CONNECTED "Verbonden" +#define D_COUNT "Aantal" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNTER "Teller" +#define D_CURRENT "Stroom" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Donker" +#define D_DEBUG "Debug" +#define D_DISABLED "Uitgeschakeld" +#define D_DISTANCE "Afstand" +#define D_DNS_SERVER "DNS Server" +#define D_DONE "Klaar" +#define D_DST_TIME "ZT" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulatie" +#define D_ENABLED "Geactiveerd" +#define D_ERASE "Wissen" +#define D_ERROR "Fout" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Mislukt" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "Onwaar" +#define D_FILE "Bestand" +#define D_FLOW_RATE "Debiet" +#define D_FREE_MEMORY "Vrij geheugen" +#define D_FREQUENCY "Frequentie" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Groep" +#define D_HOST "Host" +#define D_HOSTNAME "Hostnaam" +#define D_HUMIDITY "Luchtvochtigheid" +#define D_ILLUMINANCE "Verlichtingssterkte" +#define D_IMMEDIATE "onmiddelijk" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infrarood" +#define D_INITIALIZED "Geinitialiseerd" +#define D_IP_ADDRESS "IP Adres" +#define D_LIGHT "Licht" +#define D_LWT "LWT" +#define D_MODULE "Module" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "meervoudig" +#define D_NOISE "Lawaai" +#define D_NONE "Geen" +#define D_OFF "Uit" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "Aan" +#define D_ONLINE "Online" +#define D_PASSWORD "Wachtwoord" +#define D_PORT "Poort" +#define D_POWER_FACTOR "Arbeidsfactor" +#define D_POWERUSAGE "Vermogen" +#define D_POWERUSAGE_ACTIVE "Werkelijk vermogen" +#define D_POWERUSAGE_APPARENT "Schijnbaar vermogen" +#define D_POWERUSAGE_REACTIVE "Blindvermogen" +#define D_PRESSURE "Luchtdruk" +#define D_PRESSUREATSEALEVEL "ZeeLuchtdruk" +#define D_PROGRAM_FLASH_SIZE "Programma Flash Grootte" +#define D_PROGRAM_SIZE "Programma Grootte" +#define D_PROJECT "Project" +#define D_RAIN "Regen" +#define D_RECEIVED "Ontvangen" +#define D_RESTART "Herstart" +#define D_RESTARTING "Herstarten" +#define D_RESTART_REASON "Reden herstart" +#define D_RESTORE "herstellen" +#define D_RETAINED "retained" +#define D_RULE "Regel" +#define D_SAVE "Opslaan" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Start" +#define D_STD_TIME "WT" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Subnet Masker" +#define D_SUBSCRIBE_TO "Abonneer op" +#define D_UNSUBSCRIBE_FROM "Uitschrijven van" +#define D_SUCCESSFUL "Gelukt" +#define D_SUNRISE "Zonsopgang" +#define D_SUNSET "Zonsondergang" +#define D_TEMPERATURE "Temperatuur" +#define D_TO "naar" +#define D_TOGGLE "Toggle" // Wissel, Tuimel +#define D_TOPIC "Topic" // Onderwerp +#define D_TOTAL_USAGE "Totaal verbruik" +#define D_TRANSMIT "Verzend" +#define D_TRUE "Waar" +#define D_TVOC "TVOC" +#define D_UPGRADE "opwaarderen" +#define D_UPLOAD "Verzenden" +#define D_UPTIME "Bedrijfstijd" +#define D_USER "Gebruiker" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV-index" +#define D_UV_INDEX_1 "Laag" +#define D_UV_INDEX_2 "Gemiddeld" +#define D_UV_INDEX_3 "Hoog" +#define D_UV_INDEX_4 "Intens" +#define D_UV_INDEX_5 "Gevaarlijk" +#define D_UV_INDEX_6 "Schadelijk" +#define D_UV_INDEX_7 "Uitzonderlijk" +#define D_UV_LEVEL "UV niveau" +#define D_UV_POWER "UV intensiteit" +#define D_VERSION "Versie" +#define D_VOLTAGE "Spanning" +#define D_WEIGHT "Gewicht" +#define D_WARMLIGHT "Warm" +#define D_WEB_SERVER "Webserver" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "WAARSCHUWING Deze versie bewaart geen instellingen" +#define D_LEVEL_10 "niveau 1-0" +#define D_LEVEL_01 "niveau 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serieel logging uitgeschakeld" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logging weer ingeschakeld" + +#define D_SET_BAUDRATE_TO "Zet baudrate op" +#define D_RECEIVED_TOPIC "Ontvangen topic" +#define D_DATA_SIZE "Data lengte" +#define D_ANALOG_INPUT "Analoog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig mislukt met status" +#define D_ACTIVE_FOR_3_MINUTES "3 minuten actief" +#define D_FAILED_TO_START "mislukt" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "Verbinden met AP" +#define D_IN_MODE "in stand" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Verbinding mislukt omdat geen IP adres werd ontvangen" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Verbinding mislukt omdat AP onbereikbaar is" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Verbinding mislukt door fout wachtwoord" +#define D_CONNECT_FAILED_AP_TIMEOUT "Verbinding mislukt door AP time-out" +#define D_ATTEMPTING_CONNECTION "Verbinden..." +#define D_CHECKING_CONNECTION "Controleer verbinding..." +#define D_QUERY_DONE "Aanvraag klaar. Aantal MQTT diensten gevonden" +#define D_MQTT_SERVICE_FOUND "MQTT dienst gevonden op" +#define D_FOUND_AT "gevonden op" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host niet gevonden" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Opgeslagen in flash op" +#define D_LOADED_FROM_FLASH_AT "Geladen vanuit flash op" +#define D_USE_DEFAULTS "Gebruik standaardwaarden" +#define D_ERASED_SECTOR "Wis sector" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Zet JavaScript aan voor Tasmota" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
opwaarderen" +#define D_WEBSERVER_ACTIVE_ON "Webserver actief op" +#define D_WITH_IP_ADDRESS "met IP adres" +#define D_WEBSERVER_STOPPED "Webserver gestopt" +#define D_FILE_NOT_FOUND "Bestand niet gevonden" +#define D_REDIRECTED "Omleiding naar captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager start AccessPoint en hou Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager start AccessPoint" +#define D_TRYING_TO_CONNECT "Apparaat probeert te verbinden met netwerk" + +#define D_RESTART_IN "Herstart over" +#define D_SECONDS "seconden" +#define D_DEVICE_WILL_RESTART "Herstart over enkele seconden" +#define D_BUTTON_TOGGLE "Toggle" // Wissel, Tuimel +#define D_CONFIGURATION "Configuratie" +#define D_INFORMATION "Informatie" +#define D_FIRMWARE_UPGRADE "Opwaarderen" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Bevestig herstart" + +#define D_CONFIGURE_MODULE "Configureer Module" +#define D_CONFIGURE_WIFI "Configureer WiFi" +#define D_CONFIGURE_MQTT "Configureer MQTT" +#define D_CONFIGURE_DOMOTICZ "Configureer Domoticz" +#define D_CONFIGURE_LOGGING "Configureer Logging" +#define D_CONFIGURE_OTHER "Configureer Overige" +#define D_CONFIRM_RESET_CONFIGURATION "Bevestig reset configuratie" +#define D_RESET_CONFIGURATION "Reset Configuratie" +#define D_BACKUP_CONFIGURATION "Bewaar Configuratie" +#define D_RESTORE_CONFIGURATION "Herstel Configuration" +#define D_MAIN_MENU "Hoofdmenu" + +#define D_MODULE_PARAMETERS "Module parameters" +#define D_MODULE_TYPE "Module soort" +#define D_PULLUP_ENABLE "Geen schakelaar pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serieel In" +#define D_SERIAL_OUT "Serieel Uit" + +#define D_WIFI_PARAMETERS "Wifi parameters" +#define D_SCAN_FOR_WIFI_NETWORKS "Zoek wifi netwerken" +#define D_SCAN_DONE "Scan klaar" +#define D_NO_NETWORKS_FOUND "Geen netwerken gevonden" +#define D_REFRESH_TO_SCAN_AGAIN "Vernieuw om opnieuw te zoeken" +#define D_DUPLICATE_ACCESSPOINT "Dubbel AccessPoint" +#define D_SKIPPING_LOW_QUALITY "Overslaan agv lage ontvangskwaliteit" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Wachtwoord" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Wachtwoord" + +#define D_MQTT_PARAMETERS "MQTT parameters" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Volledig Topic" + +#define D_LOGGING_PARAMETERS "Logging parameters" +#define D_SERIAL_LOG_LEVEL "Serieel log niveau" +#define D_MQTT_LOG_LEVEL "Mqtt log niveau" +#define D_WEB_LOG_LEVEL "Web log niveau" +#define D_SYS_LOG_LEVEL "Syslog niveau" +#define D_MORE_DEBUG "Meer debug" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog poort" +#define D_TELEMETRY_PERIOD "Telemetry periode" + +#define D_OTHER_PARAMETERS "Overige parameters" +#define D_TEMPLATE "Sjabloon" +#define D_ACTIVATE "Activeer" +#define D_WEB_ADMIN_PASSWORD "Web Admin Wachtwoord" +#define D_MQTT_ENABLE "MQTT ingeschakeld" +#define D_FRIENDLY_NAME "Beschrijvende naam" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "een apparaat" +#define D_MULTI_DEVICE "meer apparaten" + +#define D_CONFIGURE_TEMPLATE "Configureer Sjabloon" +#define D_TEMPLATE_PARAMETERS "Sjabloon parameters" +#define D_TEMPLATE_NAME "Naam" +#define D_BASE_TYPE "Op basis van" +#define D_TEMPLATE_FLAGS "Opties" + +#define D_SAVE_CONFIGURATION "Bewaar configuratie" +#define D_CONFIGURATION_SAVED "Configuratie opgeslagen" +#define D_CONFIGURATION_RESET "Configuratie ge-reset" + +#define D_PROGRAM_VERSION "Programma Versie" +#define D_BUILD_DATE_AND_TIME "Compileer Datum & Tijd" +#define D_CORE_AND_SDK_VERSION "Core/SDK Versie" +#define D_FLASH_WRITE_COUNT "Aantal Flash opslagen" +#define D_MAC_ADDRESS "MAC Adres" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Poort" +#define D_MQTT_CLIENT "MQTT Client" +#define D_MQTT_USER "MQTT Gebruiker" +#define D_MQTT_TOPIC "MQTT Topic" +#define D_MQTT_GROUP_TOPIC "MQTT Groep Topic" +#define D_MQTT_FULL_TOPIC "MQTT Volledig Topic" +#define D_MDNS_DISCOVERY "mDNS Discovery" +#define D_MDNS_ADVERTISE "mDNS Advertise" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash Grootte" +#define D_FREE_PROGRAM_SPACE "Programma ruimte over" + +#define D_UPGRADE_BY_WEBSERVER "Opwaarderen dmv webserver" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Start opwaarderen" +#define D_UPGRADE_BY_FILE_UPLOAD "Opwaarderen dmv verzenden bestand" +#define D_UPLOAD_STARTED "Verzending gestart" +#define D_UPGRADE_STARTED "Opwaarderen gestart" +#define D_UPLOAD_DONE "Opwaarderen klaar" +#define D_UPLOAD_ERR_1 "Geen bestand gekozen" +#define D_UPLOAD_ERR_2 "Onvoldoende geheugen ruimte" +#define D_UPLOAD_ERR_3 "Magische byte is niet 0xE9" +#define D_UPLOAD_ERR_4 "Programma flash grootte is groter dan werkelijke flash grootte" +#define D_UPLOAD_ERR_5 "Opwaardeer buffer verschil" +#define D_UPLOAD_ERR_6 "Opwaarderen mislukt. Schakel logging 3 in" +#define D_UPLOAD_ERR_7 "Opwaarderen afgebroken" +#define D_UPLOAD_ERR_8 "Ongeldig bestand" +#define D_UPLOAD_ERR_9 "Bestand is te groot" +#define D_UPLOAD_ERR_10 "Init RF chip mislukt" +#define D_UPLOAD_ERR_11 "Wissen RF chip mislukt" +#define D_UPLOAD_ERR_12 "Opwaarderen RF chip mislukt" +#define D_UPLOAD_ERR_13 "Decoderen RF bestand mislukt" +#define D_UPLOAD_ERROR_CODE "Opwaardeer foutcode" + +#define D_ENTER_COMMAND "Geef opdracht" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Schakel weblog 2 in indien antwoord verwacht" +#define D_NEED_USER_AND_PASSWORD "Benodig user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Controleer TLS vingerafdruk..." +#define D_TLS_CONNECT_FAILED_TO "TLS Verbinding mislukt naar" +#define D_RETRY_IN "Opnieuw proberen over" +#define D_VERIFIED "Gecontroleerd met vingerafdruk" +#define D_INSECURE "Door ongeldige vingerafdruk een onveilige verbinding" +#define D_CONNECT_FAILED_TO "Verbinding mislukt naar" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast uitgeschakeld" +#define D_MULTICAST_REJOINED "Multicast verbonden" +#define D_MULTICAST_JOIN_FAILED "Multicast verbinding mislukt" +#define D_FAILED_TO_SEND_RESPONSE "Antwoord versturen mislukt" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basis gebeurtenis" +#define D_WEMO_EVENT_SERVICE "WeMo gebeurtenis dienst" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo installatie" +#define D_RESPONSE_SENT "Antwoord verstuurd" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue installatie" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API niet beschikbaar" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST argumenten" +#define D_3_RESPONSE_PACKETS_SENT "3 antwoord paketten verstuurd" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Toets idx" +#define D_DOMOTICZ_SWITCH_IDX "Schakelaar idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Spanning/PM2,5" + #define D_DOMOTICZ_CURRENT "Stroom/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Bijwerk timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configureer Tijdschakelaar" +#define D_TIMER_PARAMETERS "Tijdschakelaar parameters" +#define D_TIMER_ENABLE "Tijdschakelaars inschakelen" +#define D_TIMER_ARM "Actief" +#define D_TIMER_TIME "Tijd" +#define D_TIMER_DAYS "Dagen" +#define D_TIMER_REPEAT "Herhaal" +#define D_TIMER_OUTPUT "Uitgang" +#define D_TIMER_ACTION "Actie" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configureer KNX" +#define D_KNX_PARAMETERS "KNX Parameters" +#define D_KNX_GENERAL_CONFIG "Algemeen" +#define D_KNX_PHYSICAL_ADDRESS "Eigen adres" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Moet uniek zijn op het KNX netwerk)" +#define D_KNX_ENABLE "KNX inschakelen" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Stuur gegevens naar groep adressen" +#define D_ADD "Toevoegen" +#define D_DELETE "Verwijder" +#define D_REPLY "Antwoord" +#define D_KNX_GROUP_ADDRESS_TO_READ "Ontvang gegevens van groep adressen" +#define D_RECEIVED_FROM "Ontvangen van" +#define D_KNX_COMMAND_WRITE "Schrijven" +#define D_KNX_COMMAND_READ "Lezen" +#define D_KNX_COMMAND_OTHER "Overige" +#define D_SENT_TO "verzend naar" +#define D_KNX_WARNING "Groep adres (0/0/0) is gereserveerd en mag niet worden gebruikt." +#define D_KNX_ENHANCEMENT "Verbeter verbinding" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Verbruik vandaag" +#define D_ENERGY_YESTERDAY "Verbruik gisteren" +#define D_ENERGY_TOTAL "Verbruik totaal" + +// xdrv_27_shutter.ino +#define D_OPEN "Openen" +#define D_CLOSE "Sluiten" +#define D_DOMOTICZ_SHUTTER "Rolluik" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configureer PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 Parameters" +#define D_INVERT_PORTS "Inverteer Poorten" +#define D_DEVICE "Apparaat" +#define D_DEVICE_INPUT "Ingang" +#define D_DEVICE_OUTPUT "Uitgang" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor bezet" +#define D_SENSOR_CRC_ERROR "Sensor CRC fout" +#define D_SENSORS_FOUND "Aantal sensoren" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Te lang wachten op" +#define D_START_SIGNAL_LOW "laag start signaal" +#define D_START_SIGNAL_HIGH "hoog start signaal" +#define D_PULSE "signaal" +#define D_CHECKSUM_FAILURE "Controle mislukt" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Geen opdracht ACK van sensor" +#define D_SHT1X_FOUND "SHT1X gevonden" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Stofdeeltjes" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Verwijder gewicht" +#define D_HX_CAL_REFERENCE "Plaats ijkgewicht" +#define D_HX_CAL_DONE "Ge-ijkt" +#define D_HX_CAL_FAIL "Ijken is mislukt" +#define D_RESET_HX711 "Nulstelling weegschaal" +#define D_CONFIGURE_HX711 "Configureer Weegschaal" +#define D_HX711_PARAMETERS "Weegschaal parameters" +#define D_ITEM_WEIGHT "Gewicht van onderdeel" +#define D_REFERENCE_WEIGHT "Ijkgewicht" +#define D_CALIBRATE "Ijken" +#define D_CALIBRATION "Ijken" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Windrichting" +#define D_TX20_WIND_SPEED "Windsnelheid" +#define D_TX20_WIND_SPEED_AVG "Windsnelheid gemiddeld" +#define D_TX20_WIND_SPEED_MAX "Windsnelhied maximaal" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Geen" +#define D_SENSOR_USER "Gebruiker" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Speler" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relais" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Teller" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Zoemer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectoren" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Fase hoek" +#define D_IMPORT_ACTIVE "Import werkelijk" +#define D_EXPORT_ACTIVE "Export werkelijk" +#define D_IMPORT_REACTIVE "Import blind" +#define D_EXPORT_REACTIVE "Export blind" +#define D_TOTAL_REACTIVE "Totaal blind" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 spanning" +#define D_PV1_CURRENT "PV1 stroom" +#define D_PV1_POWER "PV1 vermogen" +#define D_PV2_VOLTAGE "PV2 spanning" +#define D_PV2_CURRENT "PV2 stroom" +#define D_PV2_POWER "PV2 vermogen" +#define D_SOLAR_POWER "Zon vermogen" +#define D_INVERTER_POWER "Omvormer vermogen" +#define D_STATUS "Status" +#define D_WAITING "Wacht" +#define D_CHECKING "Controle" +#define D_WORKING "Actief" +#define D_FAILURE "Fout" +#define D_SOLAX_ERROR_0 "Geen" +#define D_SOLAX_ERROR_1 "Netverbinding" +#define D_SOLAX_ERROR_2 "Netspanning" +#define D_SOLAX_ERROR_3 "Netfrequentie" +#define D_SOLAX_ERROR_4 "Pv spanning" +#define D_SOLAX_ERROR_5 "Isolatie" +#define D_SOLAX_ERROR_6 "Overtemperatuur" +#define D_SOLAX_ERROR_7 "Ventilator" +#define D_SOLAX_ERROR_8 "Overige" + +#endif // _LANGUAGE_NL_NL_H_ diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 1b83f8697..8f5af6813 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -1,703 +1,701 @@ -/* - pl-PL-d.h - localization for Polish with diacritics - Poland for Tasmota - - Copyright (C) 2019 Theo Arends (translated by roblad - Robert L., upgraded by R. Turala) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_PL_PL_D_H_ -#define _LANGUAGE_PL_PL_D_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.12.0d -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1045 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "pl" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "NiePonWtoŚroCzwPiąSob" -#define D_MONTH3LIST "StyLutMarKwiMajCzeLipSieWrzPaźLisGru" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Jakość powietrza" -#define D_AP "AP" // Access Point -#define D_AS "jak" -#define D_AUTO "AUTO" -#define D_BLINK "Miganie" -#define D_BLINKOFF "Miganie - Wył." -#define D_BOOT_COUNT "Licznik restartów" -#define D_BRIGHTLIGHT "Jasny" -#define D_BSSID "BSSId" -#define D_BUTTON "Przycisk" -#define D_BY "by" // Written by me -#define D_BYTES "Bajtów" -#define D_CELSIUS "Celsiusz" -#define D_CHANNEL "Kanał" -#define D_CO2 "Dwutlenek węgla" -#define D_CODE "Kod" // Button code -#define D_COLDLIGHT "Zimny" -#define D_COMMAND "Komenda" -#define D_CONNECTED "Połączony" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Licz" -#define D_COUNTER "Licznik" -#define D_CURRENT "Prąd" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Ciemny" -#define D_DEBUG "Debug" -#define D_DISABLED "Wyłączony" -#define D_DISTANCE "Odległość" -#define D_DNS_SERVER "Serwer DNS" -#define D_DONE "Wykonane" -#define D_DST_TIME "Czas DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulacja" -#define D_ENABLED "Załączony" -#define D_ERASE "Wyczyść" -#define D_ERROR "Błąd" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Błędny" -#define D_FALLBACK "Awaryjny" -#define D_FALLBACK_TOPIC "Temat zastępczy" -#define D_FALSE "Fałsz" -#define D_FILE "Plik" -#define D_FLOW_RATE "Przepływ" -#define D_FREE_MEMORY "Wolna pamięć" -#define D_FREQUENCY "Częstotliwość" -#define D_GAS "Gas" -#define D_GATEWAY "Brama" -#define D_GROUP "Grupa" -#define D_HOST "Serwer" -#define D_HOSTNAME "Nazwa serwera" -#define D_HUMIDITY "Wilgotność" -#define D_ILLUMINANCE "Podświetlanie" -#define D_IMMEDIATE "Natychmiastowy" // Button immediate -#define D_INDEX "Indeks" -#define D_INFO "Informacja" -#define D_INFRARED "Podczerwień" -#define D_INITIALIZED "Zainicjowany" -#define D_IP_ADDRESS "Adres IP" -#define D_LIGHT "Światło" -#define D_LWT "LWT" -#define D_MODULE "Moduł" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "Wielokrotne naciśnięcie" -#define D_NOISE "Szum" -#define D_NONE "Brak" -#define D_OFF "Wyłączony" -#define D_OFFLINE "Nieaktywny" -#define D_OK "Ok" -#define D_ON "Załączony" -#define D_ONLINE "Aktywny" -#define D_PASSWORD "Hasło" -#define D_PORT "Port" -#define D_POWER_FACTOR "Cosinus fi" -#define D_POWERUSAGE "Moc" -#define D_POWERUSAGE_ACTIVE "Moc czynna" -#define D_POWERUSAGE_APPARENT "Moc pozorna" -#define D_POWERUSAGE_REACTIVE "Moc bierna" -#define D_PRESSURE "Ciśnienie" -#define D_PRESSUREATSEALEVEL "Ciśnienie na poziomie morza" -#define D_PROGRAM_FLASH_SIZE "Rozmiar programu flash" -#define D_PROGRAM_SIZE "Rozmiar programu" -#define D_PROJECT "Projekt" -#define D_RAIN "Deszcz" -#define D_RECEIVED "Otrzymany" -#define D_RESTART "Restart" -#define D_RESTARTING "Restartowanie" -#define D_RESTART_REASON "Przyczyna restartu" -#define D_RESTORE "Przywracanie" -#define D_RETAINED "Zachowane" -#define D_RULE "Reguła" -#define D_SAVE "Zapisz" -#define D_SENSOR "Czujnik" -#define D_SSID "SSID" -#define D_START "Start" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Maska podsieci" -#define D_SUBSCRIBE_TO "Subskrybuj" -#define D_UNSUBSCRIBE_FROM "Nie subskrybuj" -#define D_SUCCESSFUL "Powodzenie" -#define D_SUNRISE "Wschód słońca" -#define D_SUNSET "Zachód słońca" -#define D_TEMPERATURE "Temperatura" -#define D_TO "do" -#define D_TOGGLE "Przełącz" -#define D_TOPIC "Temat" -#define D_TOTAL_USAGE "Całkowite użycie" -#define D_TRANSMIT "Wyślij" -#define D_TRUE "Prawda" -#define D_TVOC "TVOC" -#define D_UPGRADE "aktualizacji" -#define D_UPLOAD "Wgraj" -#define D_UPTIME "Czas pracy" -#define D_USER "Użytkownik" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Index UV" -#define D_UV_INDEX_1 "Niski" -#define D_UV_INDEX_2 "Średni" -#define D_UV_INDEX_3 "Wysoki" -#define D_UV_INDEX_4 "Niebezpieczny" -#define D_UV_INDEX_5 "Burn L1/2" -#define D_UV_INDEX_6 "Burn L3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Poziom UV" -#define D_UV_POWER "Moc UV" -#define D_VERSION "Wersja" -#define D_VOLTAGE "Napięcie" -#define D_WEIGHT "Waga" -#define D_WARMLIGHT "Temperatura światła" -#define D_WEB_SERVER "Serwer Web" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "UWAGA Ta wersja nie obsługuje zapisu ustawień" -#define D_LEVEL_10 "poziom 1-0" -#define D_LEVEL_01 "poziom 0-1" -#define D_SERIAL_LOGGING_DISABLED "Wyłączony dziennik na porcie szeregowym" -#define D_SYSLOG_LOGGING_REENABLED "Wznowiono zapis do Syslog" - -#define D_SET_BAUDRATE_TO "Ustaw szybkość transmisji na" -#define D_RECEIVED_TOPIC "Otrzymany temat" -#define D_DATA_SIZE "Wielkość danych" -#define D_ANALOG_INPUT "Wejście analogowe" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Pętla zablokowana" -#define D_WPS_FAILED_WITH_STATUS "Błąd konfiguracji WPS ze statusem" -#define D_ACTIVE_FOR_3_MINUTES "aktywny 3 minuty" -#define D_FAILED_TO_START "nie udało się uruchomić" -#define D_PATCH_ISSUE_2186 "Błąd poprawki 2186" -#define D_CONNECTING_TO_AP "Łączenie z AP" -#define D_IN_MODE "w trybie" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Połączenie nie powiodło się, ponieważ nie otrzymano adresu IP" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Połączenie nie powiodło się, AP nie osiągalny" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Połączenie nie powiodło się, nieprawidlowe hasło" -#define D_CONNECT_FAILED_AP_TIMEOUT "Nie udało się nawiązac połączenia, limit czasu przekroczony" -#define D_ATTEMPTING_CONNECTION "Próba połączenia..." -#define D_CHECKING_CONNECTION "Sprawdzanie połączenia..." -#define D_QUERY_DONE "Zapytanie wykonane" -#define D_MQTT_SERVICE_FOUND "Usługa MQTT została znaleziona" -#define D_FOUND_AT "znaleziono w" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nie znaleziony" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Zapisano do pamięci flash w" -#define D_LOADED_FROM_FLASH_AT "Wczytano z pamięci flash w" -#define D_USE_DEFAULTS "Użyj domyślnych" -#define D_ERASED_SECTOR "Sektor wymazany" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" -#define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" -#define D_WITH_IP_ADDRESS "z adresem IP" -#define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" -#define D_FILE_NOT_FOUND "Plik nie odnaleziony" -#define D_REDIRECTED "Przekierowano do własnego portalu" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Menedżer Wifi ustawia punkt dostępowy i zachowuje stacje" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Menedżer sieci Wi-Fi Access Point" -#define D_TRYING_TO_CONNECT "Próbuję połączyć urzadzenie z siecią" - -#define D_RESTART_IN "Zrestartuj" -#define D_SECONDS "Sekund" -#define D_DEVICE_WILL_RESTART "Urządzenie zrestartuje sie za kilka sekund" -#define D_BUTTON_TOGGLE "Załącz/Wyłącz" -#define D_CONFIGURATION "Konfiguracja" -#define D_INFORMATION "Informacje" -#define D_FIRMWARE_UPGRADE "Aktualizacja oprogramowania" -#define D_CONSOLE "Konsola" -#define D_CONFIRM_RESTART "Potwierdź restart" - -#define D_CONFIGURE_MODULE "Konfiguracja modułu" -#define D_CONFIGURE_WIFI "Konfiguracja WiFi" -#define D_CONFIGURE_MQTT "Konfiguracja MQTT" -#define D_CONFIGURE_DOMOTICZ "Konfiguracja Domoticza" -#define D_CONFIGURE_LOGGING "Konfiguracja dziennika" -#define D_CONFIGURE_OTHER "Inne konfiguracje" -#define D_CONFIRM_RESET_CONFIGURATION "Potwierdź reset ustawień" -#define D_RESET_CONFIGURATION "Reset ustawień" -#define D_BACKUP_CONFIGURATION "Kopia ustawień" -#define D_RESTORE_CONFIGURATION "Przywracanie ustawień" -#define D_MAIN_MENU "Menu główne" - -#define D_MODULE_PARAMETERS "Parametry modułu" -#define D_MODULE_TYPE "Typ" -#define D_PULLUP_ENABLE "Przełącznik pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Wejście rs" -#define D_SERIAL_OUT "Wyjście rs" - -#define D_WIFI_PARAMETERS "Parametry sieci WiFi" -#define D_SCAN_FOR_WIFI_NETWORKS "Skanuj sieci" -#define D_SCAN_DONE "Skanowanie wykonane" -#define D_NO_NETWORKS_FOUND "Nie znaleziono sieci" -#define D_REFRESH_TO_SCAN_AGAIN "Odśwież aby ponownie wyszukać sieci" -#define D_DUPLICATE_ACCESSPOINT "Duplikuj" -#define D_SKIPPING_LOW_QUALITY "Pominięto z powodu niskiej jakości sygnału" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "Nazwa 1" -#define D_AP1_PASSWORD "Hasło 1" -#define D_AP2_SSID "Nazwa 2" -#define D_AP2_PASSWORD "Hasło 2" - -#define D_MQTT_PARAMETERS "Parametry MQTT" -#define D_CLIENT "Klient" -#define D_FULL_TOPIC "Pełny temat" - -#define D_LOGGING_PARAMETERS "Opcje dziennika" -#define D_SERIAL_LOG_LEVEL "Serial - poziom" -#define D_MQTT_LOG_LEVEL "Mqtt - poziom" -#define D_WEB_LOG_LEVEL "Web - poziom" -#define D_SYS_LOG_LEVEL "System - poziom" -#define D_MORE_DEBUG "Więcej informacji dziennika" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Okres telemetrii" - -#define D_OTHER_PARAMETERS "Inne parametry" -#define D_TEMPLATE "Szablon" -#define D_ACTIVATE "Aktywuj" -#define D_WEB_ADMIN_PASSWORD "Hasło administratora" -#define D_MQTT_ENABLE "Załącz MQTT" -#define D_FRIENDLY_NAME "Nazwa" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Mostek Hue" -#define D_SINGLE_DEVICE "pojedyńcze urządzenie" -#define D_MULTI_DEVICE "multi urządzenie" - -#define D_CONFIGURE_TEMPLATE "Konfiguracja szablonu" -#define D_TEMPLATE_PARAMETERS "Parametry szablonu" -#define D_TEMPLATE_NAME "Nazwa" -#define D_BASE_TYPE "Na bazie" -#define D_TEMPLATE_FLAGS "Opcje" - -#define D_SAVE_CONFIGURATION "Zapisz ustawienia" -#define D_CONFIGURATION_SAVED "Ustawienia zapisane" -#define D_CONFIGURATION_RESET "Ustawienia zresetowane" - -#define D_PROGRAM_VERSION "Wersja oprogramowania" -#define D_BUILD_DATE_AND_TIME "Data kompilacji" -#define D_CORE_AND_SDK_VERSION "Wersja Core/SDK" -#define D_FLASH_WRITE_COUNT "Liczba zapisów do pamięci" -#define D_MAC_ADDRESS "Adres MAC" -#define D_MQTT_HOST "Host" -#define D_MQTT_PORT "Port" -#define D_MQTT_CLIENT "Klient" -#define D_MQTT_USER "Użytkownik" -#define D_MQTT_TOPIC "Temat" -#define D_MQTT_GROUP_TOPIC "Temat grupy" -#define D_MQTT_FULL_TOPIC "Pełny temat" -#define D_MDNS_DISCOVERY "Wykrywanie mDNS" -#define D_MDNS_ADVERTISE "Rozgłaszanie mDNS" -#define D_ESP_CHIP_ID "ID ukladu ESP" -#define D_FLASH_CHIP_ID "ID pamięci flash" -#define D_FLASH_CHIP_SIZE "Rozmiar pamięci flash" -#define D_FREE_PROGRAM_SPACE "Wolna pamięć programu" - -#define D_UPGRADE_BY_WEBSERVER "Aktualizacja z serwera Web" -#define D_OTA_URL "Adres serwera" -#define D_START_UPGRADE "Aktualizuj" -#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja z pliku" -#define D_UPLOAD_STARTED "Wgrywanie rozpoczęte" -#define D_UPGRADE_STARTED "Aktualizacja rozpoczęta" -#define D_UPLOAD_DONE "Wgrywanie zakończone" -#define D_UPLOAD_ERR_1 "Nie wybrano pliku" -#define D_UPLOAD_ERR_2 "Niewystarczająca ilość miejsca" -#define D_UPLOAD_ERR_3 "Magiczny bajt jest inny niz 0xE9" -#define D_UPLOAD_ERR_4 "Rozmiar programu jest większy niż rzeczywisty rozmiar pamięci flash" -#define D_UPLOAD_ERR_5 "Wgrywanie, bufor niezgodności stanu porównywanych bitow" -#define D_UPLOAD_ERR_6 "Błąd wgrywania. Uruchomiono zapis do dziennika na poziomie 3" -#define D_UPLOAD_ERR_7 "Wgrywanie przerwane" -#define D_UPLOAD_ERR_8 "Błędny plik" -#define D_UPLOAD_ERR_9 "Plik jest za duży" -#define D_UPLOAD_ERR_10 "Błąd inicjacji układu RF" -#define D_UPLOAD_ERR_11 "Błąd kasowania układu RF" -#define D_UPLOAD_ERR_12 "Błąd zapisu układu RF" -#define D_UPLOAD_ERR_13 "Błąd dekodowania oprrogramowania układu RF" -#define D_UPLOAD_ERROR_CODE "Błąd wgrywania" - -#define D_ENTER_COMMAND "Wprowadź polecenie" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Włącz poziom 2 zapisu dziennika, jeśli oczekiwana jest odpowiedź" -#define D_NEED_USER_AND_PASSWORD "Wymagany użytkownik=&hasło=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Weryfikuj odcisk TLS..." -#define D_TLS_CONNECT_FAILED_TO "Nieudane połączenie TLS do" -#define D_RETRY_IN "Spróbuj ponownie" -#define D_VERIFIED "Zweryfikowano odcisk" -#define D_INSECURE "Nieprawidłowe połączenie z powodu błędnego odcisku TLS" -#define D_CONNECT_FAILED_TO "Nie udało się nawiązać połączenia" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast wyłączony" -#define D_MULTICAST_REJOINED "Multicast dołączony" -#define D_MULTICAST_JOIN_FAILED "Podłączenie Multicast nie powiodło się" -#define D_FAILED_TO_SEND_RESPONSE "Nie udało się wysłać odpowiedzi" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "Zdarzenie podstawowe" -#define D_WEMO_EVENT_SERVICE "Zdarzenie serwisowe" -#define D_WEMO_META_SERVICE "Meta dane serwisowe" -#define D_WEMO_SETUP "Ustawienia WeMo" -#define D_RESPONSE_SENT "Wyślij odpowiedź" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Ustawienia Hue" -#define D_HUE_API_NOT_IMPLEMENTED "Api nie zaimplementowane" -#define D_HUE_API "API" -#define D_HUE_POST_ARGS "POST argument" -#define D_3_RESPONSE_PACKETS_SENT "3 pakiety odpowiedzi wysyłane" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Klucz Idx" -#define D_DOMOTICZ_SWITCH_IDX "Przełącznik Idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor Idx" - #define D_DOMOTICZ_TEMP "Temperatura" - #define D_DOMOTICZ_TEMP_HUM "Temperatura, Wilgotność" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temperatura, Wilgotność, Ciśnienie" - #define D_DOMOTICZ_POWER_ENERGY "Moc, Energia" - #define D_DOMOTICZ_ILLUMINANCE "Oświetlenie" - #define D_DOMOTICZ_COUNT "Licznik" - #define D_DOMOTICZ_VOLTAGE "Napięcie" - #define D_DOMOTICZ_CURRENT "Prąd" - #define D_DOMOTICZ_AIRQUALITY "Jakość powietrza" - #define D_DOMOTICZ_P1_SMART_METER "Miernik P1" -#define D_DOMOTICZ_UPDATE_TIMER "Aktualizacja zegara" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Konfiguracja harmonogramu" -#define D_TIMER_PARAMETERS "Parametry harmonogramu" -#define D_TIMER_ENABLE "Załącz harmonogram" -#define D_TIMER_ARM "Załącz" -#define D_TIMER_TIME "Czas" -#define D_TIMER_DAYS "Dni" -#define D_TIMER_REPEAT "Powtarzaj" -#define D_TIMER_OUTPUT "Wyjście" -#define D_TIMER_ACTION "Akcja" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Konfiguracja KNX" -#define D_KNX_PARAMETERS "Parametry KNX" -#define D_KNX_GENERAL_CONFIG "Konfiguracja ogólna" -#define D_KNX_PHYSICAL_ADDRESS "Adres fizyczny" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Musi być unikalny w sieci KNX)" -#define D_KNX_ENABLE "Załącz" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Adresy grupowe do zapisu" -#define D_ADD "Dodaj" -#define D_DELETE "Usuń" -#define D_REPLY "Odpowiedz" -#define D_KNX_GROUP_ADDRESS_TO_READ "Adresy grupowe do odbioru" -#define D_RECEIVED_FROM "Odebrane od" -#define D_KNX_COMMAND_WRITE "Zapisz" -#define D_KNX_COMMAND_READ "Czytaj" -#define D_KNX_COMMAND_OTHER "Inna komenda" -#define D_SENT_TO "Wyślij do" -#define D_KNX_WARNING "Adres grupy (0/0/0) jest zarezerwowany i nie można go użyć." -#define D_KNX_ENHANCEMENT "Rozszerzenia" -#define D_KNX_TX_SLOT "Gniazdo TX" -#define D_KNX_RX_SLOT "Gniazdo RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energia dzisiaj" -#define D_ENERGY_YESTERDAY "Energia wczoraj" -#define D_ENERGY_TOTAL "Energia całkowita" - -// xdrv_27_shutter.ino -#define D_OPEN "Otwórz" -#define D_CLOSE "Zamknij" -#define D_DOMOTICZ_SHUTTER "Roleta" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Konfiguracja PCF8574" -#define D_PCF8574_PARAMETERS "Parametry PCF8574" -#define D_INVERT_PORTS "Porty odwrócone" -#define D_DEVICE "Urządzenie" -#define D_DEVICE_INPUT "Wejście" -#define D_DEVICE_OUTPUT "Wyjście" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Czujnik zajęty" -#define D_SENSOR_CRC_ERROR "Błąd CRC czujnika" -#define D_SENSORS_FOUND "Znaleziono czujnik" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Trwa oczekiwanie" -#define D_START_SIGNAL_LOW "Sygnał startowy niski" -#define D_START_SIGNAL_HIGH "Sygnał startowy wysoki" -#define D_PULSE "Impuls" -#define D_CHECKSUM_FAILURE "Błędna suma kontrolna" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Czujnik nie otrzymał komendy ACK" -#define D_SHT1X_FOUND "SHT1X znaleziony" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Cząstki" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Usuń wagę" -#define D_HX_CAL_REFERENCE "Załaduj wagę referencyjną" -#define D_HX_CAL_DONE "Skalibrowany" -#define D_HX_CAL_FAIL "Błąd kalibracji" -#define D_RESET_HX711 "Zresetuj skalę" -#define D_CONFIGURE_HX711 "Skonfiguruj skalę" -#define D_HX711_PARAMETERS "Parametry skali" -#define D_ITEM_WEIGHT "Waga przedmiotu" -#define D_REFERENCE_WEIGHT "Waga referencyjna" -#define D_CALIBRATE "Skalibruj" -#define D_CALIBRATION "Kalibrowanie" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Kierunek" -#define D_TX20_WIND_SPEED "Prędkość" -#define D_TX20_WIND_SPEED_AVG "Średnia prędkość" -#define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Brak" -#define D_SENSOR_USER "Użytkownik" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "Odtearzacz MP3" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Przełącznik" // Suffix "1" -#define D_SENSOR_BUTTON "Przycisk" // Suffix "1" -#define D_SENSOR_RELAY "Przekaźnik" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "Led link" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Licznik" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Podświetlanie" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "Głęboko uśpiony" -#define D_SENSOR_EXS_ENABLE "Załącz EXS" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Godz" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sektory" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Przesunięcie faz" -#define D_IMPORT_ACTIVE "Czynna pobrana" -#define D_EXPORT_ACTIVE "Czynna oddana" -#define D_IMPORT_REACTIVE "Bierna pobrana" -#define D_EXPORT_REACTIVE "Bierna oddana" -#define D_TOTAL_REACTIVE "Bierna całkowita" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "Napięcie PV1" -#define D_PV1_CURRENT "Prąd PV1" -#define D_PV1_POWER "Moc PV1 " -#define D_PV2_VOLTAGE "Napięcie PV2" -#define D_PV2_CURRENT "Prąd PV2" -#define D_PV2_POWER "Moc PV2" -#define D_SOLAR_POWER "Moc PV" -#define D_INVERTER_POWER "Moc invertera" -#define D_STATUS "Status" -#define D_WAITING "Oczekiwanie" -#define D_CHECKING "Sprawdzanie" -#define D_WORKING "Praca" -#define D_FAILURE "Błąd" -#define D_SOLAX_ERROR_0 "Błąd - brak kodu" -#define D_SOLAX_ERROR_1 "Błąd - utrata sieci" -#define D_SOLAX_ERROR_2 "Błąd - napięcie sieci" -#define D_SOLAX_ERROR_3 "Błąd - częstotliwość sieci" -#define D_SOLAX_ERROR_4 "Błąd - napięcie PV" -#define D_SOLAX_ERROR_5 "Błąd - usterka izolacji" -#define D_SOLAX_ERROR_6 "Błąd - przegrzanie" -#define D_SOLAX_ERROR_7 "Błąd - wentylator" -#define D_SOLAX_ERROR_8 "Błąd - inne urządzenie" - -#endif // _LANGUAGE_PL_PL_D_H_ +/* + pl-PL-d.h - localization for Polish with diacritics - Poland for Tasmota + + Copyright (C) 2019 Theo Arends (translated by roblad - Robert L., upgraded by R. Turala) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_PL_PL_D_H_ +#define _LANGUAGE_PL_PL_D_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.12.0d +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1045 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "pl" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "NiePonWtoŚroCzwPiąSob" +#define D_MONTH3LIST "StyLutMarKwiMajCzeLipSieWrzPaźLisGru" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Jakość powietrza" +#define D_AP "AP" // Access Point +#define D_AS "jak" +#define D_AUTO "AUTO" +#define D_BLINK "Miganie" +#define D_BLINKOFF "Miganie - Wył." +#define D_BOOT_COUNT "Licznik restartów" +#define D_BRIGHTLIGHT "Jasny" +#define D_BSSID "BSSId" +#define D_BUTTON "Przycisk" +#define D_BY "by" // Written by me +#define D_BYTES "Bajtów" +#define D_CELSIUS "Celsiusz" +#define D_CHANNEL "Kanał" +#define D_CO2 "Dwutlenek węgla" +#define D_CODE "Kod" // Button code +#define D_COLDLIGHT "Zimny" +#define D_COMMAND "Komenda" +#define D_CONNECTED "Połączony" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Licz" +#define D_COUNTER "Licznik" +#define D_CURRENT "Prąd" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Ciemny" +#define D_DEBUG "Debug" +#define D_DISABLED "Wyłączony" +#define D_DISTANCE "Odległość" +#define D_DNS_SERVER "Serwer DNS" +#define D_DONE "Wykonane" +#define D_DST_TIME "Czas DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulacja" +#define D_ENABLED "Załączony" +#define D_ERASE "Wyczyść" +#define D_ERROR "Błąd" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Błędny" +#define D_FALLBACK "Awaryjny" +#define D_FALLBACK_TOPIC "Temat zastępczy" +#define D_FALSE "Fałsz" +#define D_FILE "Plik" +#define D_FLOW_RATE "Przepływ" +#define D_FREE_MEMORY "Wolna pamięć" +#define D_FREQUENCY "Częstotliwość" +#define D_GAS "Gas" +#define D_GATEWAY "Brama" +#define D_GROUP "Grupa" +#define D_HOST "Serwer" +#define D_HOSTNAME "Nazwa serwera" +#define D_HUMIDITY "Wilgotność" +#define D_ILLUMINANCE "Podświetlanie" +#define D_IMMEDIATE "Natychmiastowy" // Button immediate +#define D_INDEX "Indeks" +#define D_INFO "Informacja" +#define D_INFRARED "Podczerwień" +#define D_INITIALIZED "Zainicjowany" +#define D_IP_ADDRESS "Adres IP" +#define D_LIGHT "Światło" +#define D_LWT "LWT" +#define D_MODULE "Moduł" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "Wielokrotne naciśnięcie" +#define D_NOISE "Szum" +#define D_NONE "Brak" +#define D_OFF "Wyłączony" +#define D_OFFLINE "Nieaktywny" +#define D_OK "Ok" +#define D_ON "Załączony" +#define D_ONLINE "Aktywny" +#define D_PASSWORD "Hasło" +#define D_PORT "Port" +#define D_POWER_FACTOR "Cosinus fi" +#define D_POWERUSAGE "Moc" +#define D_POWERUSAGE_ACTIVE "Moc czynna" +#define D_POWERUSAGE_APPARENT "Moc pozorna" +#define D_POWERUSAGE_REACTIVE "Moc bierna" +#define D_PRESSURE "Ciśnienie" +#define D_PRESSUREATSEALEVEL "Ciśnienie na poziomie morza" +#define D_PROGRAM_FLASH_SIZE "Rozmiar programu flash" +#define D_PROGRAM_SIZE "Rozmiar programu" +#define D_PROJECT "Projekt" +#define D_RAIN "Deszcz" +#define D_RECEIVED "Otrzymany" +#define D_RESTART "Restart" +#define D_RESTARTING "Restartowanie" +#define D_RESTART_REASON "Przyczyna restartu" +#define D_RESTORE "Przywracanie" +#define D_RETAINED "Zachowane" +#define D_RULE "Reguła" +#define D_SAVE "Zapisz" +#define D_SENSOR "Czujnik" +#define D_SSID "SSID" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maska podsieci" +#define D_SUBSCRIBE_TO "Subskrybuj" +#define D_UNSUBSCRIBE_FROM "Nie subskrybuj" +#define D_SUCCESSFUL "Powodzenie" +#define D_SUNRISE "Wschód słońca" +#define D_SUNSET "Zachód słońca" +#define D_TEMPERATURE "Temperatura" +#define D_TO "do" +#define D_TOGGLE "Przełącz" +#define D_TOPIC "Temat" +#define D_TOTAL_USAGE "Całkowite użycie" +#define D_TRANSMIT "Wyślij" +#define D_TRUE "Prawda" +#define D_TVOC "TVOC" +#define D_UPGRADE "aktualizacji" +#define D_UPLOAD "Wgraj" +#define D_UPTIME "Czas pracy" +#define D_USER "Użytkownik" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Index UV" +#define D_UV_INDEX_1 "Niski" +#define D_UV_INDEX_2 "Średni" +#define D_UV_INDEX_3 "Wysoki" +#define D_UV_INDEX_4 "Niebezpieczny" +#define D_UV_INDEX_5 "Burn L1/2" +#define D_UV_INDEX_6 "Burn L3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Poziom UV" +#define D_UV_POWER "Moc UV" +#define D_VERSION "Wersja" +#define D_VOLTAGE "Napięcie" +#define D_WEIGHT "Waga" +#define D_WARMLIGHT "Temperatura światła" +#define D_WEB_SERVER "Serwer Web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "UWAGA Ta wersja nie obsługuje zapisu ustawień" +#define D_LEVEL_10 "poziom 1-0" +#define D_LEVEL_01 "poziom 0-1" +#define D_SERIAL_LOGGING_DISABLED "Wyłączony dziennik na porcie szeregowym" +#define D_SYSLOG_LOGGING_REENABLED "Wznowiono zapis do Syslog" + +#define D_SET_BAUDRATE_TO "Ustaw szybkość transmisji na" +#define D_RECEIVED_TOPIC "Otrzymany temat" +#define D_DATA_SIZE "Wielkość danych" +#define D_ANALOG_INPUT "Wejście analogowe" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Pętla zablokowana" +#define D_WPS_FAILED_WITH_STATUS "Błąd konfiguracji WPS ze statusem" +#define D_ACTIVE_FOR_3_MINUTES "aktywny 3 minuty" +#define D_FAILED_TO_START "nie udało się uruchomić" +#define D_PATCH_ISSUE_2186 "Błąd poprawki 2186" +#define D_CONNECTING_TO_AP "Łączenie z AP" +#define D_IN_MODE "w trybie" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Połączenie nie powiodło się, ponieważ nie otrzymano adresu IP" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Połączenie nie powiodło się, AP nie osiągalny" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Połączenie nie powiodło się, nieprawidlowe hasło" +#define D_CONNECT_FAILED_AP_TIMEOUT "Nie udało się nawiązac połączenia, limit czasu przekroczony" +#define D_ATTEMPTING_CONNECTION "Próba połączenia..." +#define D_CHECKING_CONNECTION "Sprawdzanie połączenia..." +#define D_QUERY_DONE "Zapytanie wykonane" +#define D_MQTT_SERVICE_FOUND "Usługa MQTT została znaleziona" +#define D_FOUND_AT "znaleziono w" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nie znaleziony" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Zapisano do pamięci flash w" +#define D_LOADED_FROM_FLASH_AT "Wczytano z pamięci flash w" +#define D_USE_DEFAULTS "Użyj domyślnych" +#define D_ERASED_SECTOR "Sektor wymazany" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL
proszę uaktualnić" +#define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web" +#define D_WITH_IP_ADDRESS "z adresem IP" +#define D_WEBSERVER_STOPPED "Serwer Web zatrzymany" +#define D_FILE_NOT_FOUND "Plik nie odnaleziony" +#define D_REDIRECTED "Przekierowano do własnego portalu" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Menedżer Wifi ustawia punkt dostępowy i zachowuje stacje" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Menedżer sieci Wi-Fi Access Point" +#define D_TRYING_TO_CONNECT "Próbuję połączyć urzadzenie z siecią" + +#define D_RESTART_IN "Zrestartuj" +#define D_SECONDS "Sekund" +#define D_DEVICE_WILL_RESTART "Urządzenie zrestartuje sie za kilka sekund" +#define D_BUTTON_TOGGLE "Załącz/Wyłącz" +#define D_CONFIGURATION "Konfiguracja" +#define D_INFORMATION "Informacje" +#define D_FIRMWARE_UPGRADE "Aktualizacja oprogramowania" +#define D_CONSOLE "Konsola" +#define D_CONFIRM_RESTART "Potwierdź restart" + +#define D_CONFIGURE_MODULE "Konfiguracja modułu" +#define D_CONFIGURE_WIFI "Konfiguracja WiFi" +#define D_CONFIGURE_MQTT "Konfiguracja MQTT" +#define D_CONFIGURE_DOMOTICZ "Konfiguracja Domoticza" +#define D_CONFIGURE_LOGGING "Konfiguracja dziennika" +#define D_CONFIGURE_OTHER "Inne konfiguracje" +#define D_CONFIRM_RESET_CONFIGURATION "Potwierdź reset ustawień" +#define D_RESET_CONFIGURATION "Reset ustawień" +#define D_BACKUP_CONFIGURATION "Kopia ustawień" +#define D_RESTORE_CONFIGURATION "Przywracanie ustawień" +#define D_MAIN_MENU "Menu główne" + +#define D_MODULE_PARAMETERS "Parametry modułu" +#define D_MODULE_TYPE "Typ" +#define D_PULLUP_ENABLE "Przełącznik pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Wejście rs" +#define D_SERIAL_OUT "Wyjście rs" + +#define D_WIFI_PARAMETERS "Parametry sieci WiFi" +#define D_SCAN_FOR_WIFI_NETWORKS "Skanuj sieci" +#define D_SCAN_DONE "Skanowanie wykonane" +#define D_NO_NETWORKS_FOUND "Nie znaleziono sieci" +#define D_REFRESH_TO_SCAN_AGAIN "Odśwież aby ponownie wyszukać sieci" +#define D_DUPLICATE_ACCESSPOINT "Duplikuj" +#define D_SKIPPING_LOW_QUALITY "Pominięto z powodu niskiej jakości sygnału" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "Nazwa 1" +#define D_AP1_PASSWORD "Hasło 1" +#define D_AP2_SSID "Nazwa 2" +#define D_AP2_PASSWORD "Hasło 2" + +#define D_MQTT_PARAMETERS "Parametry MQTT" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Pełny temat" + +#define D_LOGGING_PARAMETERS "Opcje dziennika" +#define D_SERIAL_LOG_LEVEL "Serial - poziom" +#define D_MQTT_LOG_LEVEL "Mqtt - poziom" +#define D_WEB_LOG_LEVEL "Web - poziom" +#define D_SYS_LOG_LEVEL "System - poziom" +#define D_MORE_DEBUG "Więcej informacji dziennika" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Okres telemetrii" + +#define D_OTHER_PARAMETERS "Inne parametry" +#define D_TEMPLATE "Szablon" +#define D_ACTIVATE "Aktywuj" +#define D_WEB_ADMIN_PASSWORD "Hasło administratora" +#define D_MQTT_ENABLE "Załącz MQTT" +#define D_FRIENDLY_NAME "Nazwa" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Mostek Hue" +#define D_SINGLE_DEVICE "pojedyńcze urządzenie" +#define D_MULTI_DEVICE "multi urządzenie" + +#define D_CONFIGURE_TEMPLATE "Konfiguracja szablonu" +#define D_TEMPLATE_PARAMETERS "Parametry szablonu" +#define D_TEMPLATE_NAME "Nazwa" +#define D_BASE_TYPE "Na bazie" +#define D_TEMPLATE_FLAGS "Opcje" + +#define D_SAVE_CONFIGURATION "Zapisz ustawienia" +#define D_CONFIGURATION_SAVED "Ustawienia zapisane" +#define D_CONFIGURATION_RESET "Ustawienia zresetowane" + +#define D_PROGRAM_VERSION "Wersja oprogramowania" +#define D_BUILD_DATE_AND_TIME "Data kompilacji" +#define D_CORE_AND_SDK_VERSION "Wersja Core/SDK" +#define D_FLASH_WRITE_COUNT "Liczba zapisów do pamięci" +#define D_MAC_ADDRESS "Adres MAC" +#define D_MQTT_HOST "Host" +#define D_MQTT_PORT "Port" +#define D_MQTT_CLIENT "Klient" +#define D_MQTT_USER "Użytkownik" +#define D_MQTT_TOPIC "Temat" +#define D_MQTT_GROUP_TOPIC "Temat grupy" +#define D_MQTT_FULL_TOPIC "Pełny temat" +#define D_MDNS_DISCOVERY "Wykrywanie mDNS" +#define D_MDNS_ADVERTISE "Rozgłaszanie mDNS" +#define D_ESP_CHIP_ID "ID ukladu ESP" +#define D_FLASH_CHIP_ID "ID pamięci flash" +#define D_FLASH_CHIP_SIZE "Rozmiar pamięci flash" +#define D_FREE_PROGRAM_SPACE "Wolna pamięć programu" + +#define D_UPGRADE_BY_WEBSERVER "Aktualizacja z serwera Web" +#define D_OTA_URL "Adres serwera" +#define D_START_UPGRADE "Aktualizuj" +#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja z pliku" +#define D_UPLOAD_STARTED "Wgrywanie rozpoczęte" +#define D_UPGRADE_STARTED "Aktualizacja rozpoczęta" +#define D_UPLOAD_DONE "Wgrywanie zakończone" +#define D_UPLOAD_ERR_1 "Nie wybrano pliku" +#define D_UPLOAD_ERR_2 "Niewystarczająca ilość miejsca" +#define D_UPLOAD_ERR_3 "Magiczny bajt jest inny niz 0xE9" +#define D_UPLOAD_ERR_4 "Rozmiar programu jest większy niż rzeczywisty rozmiar pamięci flash" +#define D_UPLOAD_ERR_5 "Wgrywanie, bufor niezgodności stanu porównywanych bitow" +#define D_UPLOAD_ERR_6 "Błąd wgrywania. Uruchomiono zapis do dziennika na poziomie 3" +#define D_UPLOAD_ERR_7 "Wgrywanie przerwane" +#define D_UPLOAD_ERR_8 "Błędny plik" +#define D_UPLOAD_ERR_9 "Plik jest za duży" +#define D_UPLOAD_ERR_10 "Błąd inicjacji układu RF" +#define D_UPLOAD_ERR_11 "Błąd kasowania układu RF" +#define D_UPLOAD_ERR_12 "Błąd zapisu układu RF" +#define D_UPLOAD_ERR_13 "Błąd dekodowania oprrogramowania układu RF" +#define D_UPLOAD_ERROR_CODE "Błąd wgrywania" + +#define D_ENTER_COMMAND "Wprowadź polecenie" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Włącz poziom 2 zapisu dziennika, jeśli oczekiwana jest odpowiedź" +#define D_NEED_USER_AND_PASSWORD "Wymagany użytkownik=&hasło=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Weryfikuj odcisk TLS..." +#define D_TLS_CONNECT_FAILED_TO "Nieudane połączenie TLS do" +#define D_RETRY_IN "Spróbuj ponownie" +#define D_VERIFIED "Zweryfikowano odcisk" +#define D_INSECURE "Nieprawidłowe połączenie z powodu błędnego odcisku TLS" +#define D_CONNECT_FAILED_TO "Nie udało się nawiązać połączenia" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast wyłączony" +#define D_MULTICAST_REJOINED "Multicast dołączony" +#define D_MULTICAST_JOIN_FAILED "Podłączenie Multicast nie powiodło się" +#define D_FAILED_TO_SEND_RESPONSE "Nie udało się wysłać odpowiedzi" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "Zdarzenie podstawowe" +#define D_WEMO_EVENT_SERVICE "Zdarzenie serwisowe" +#define D_WEMO_META_SERVICE "Meta dane serwisowe" +#define D_WEMO_SETUP "Ustawienia WeMo" +#define D_RESPONSE_SENT "Wyślij odpowiedź" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Ustawienia Hue" +#define D_HUE_API_NOT_IMPLEMENTED "Api nie zaimplementowane" +#define D_HUE_API "API" +#define D_HUE_POST_ARGS "POST argument" +#define D_3_RESPONSE_PACKETS_SENT "3 pakiety odpowiedzi wysyłane" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Klucz Idx" +#define D_DOMOTICZ_SWITCH_IDX "Przełącznik Idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor Idx" + #define D_DOMOTICZ_TEMP "Temperatura" + #define D_DOMOTICZ_TEMP_HUM "Temperatura, Wilgotność" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temperatura, Wilgotność, Ciśnienie" + #define D_DOMOTICZ_POWER_ENERGY "Moc, Energia" + #define D_DOMOTICZ_ILLUMINANCE "Oświetlenie" + #define D_DOMOTICZ_COUNT "Licznik" + #define D_DOMOTICZ_VOLTAGE "Napięcie" + #define D_DOMOTICZ_CURRENT "Prąd" + #define D_DOMOTICZ_AIRQUALITY "Jakość powietrza" + #define D_DOMOTICZ_P1_SMART_METER "Miernik P1" +#define D_DOMOTICZ_UPDATE_TIMER "Aktualizacja zegara" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Konfiguracja harmonogramu" +#define D_TIMER_PARAMETERS "Parametry harmonogramu" +#define D_TIMER_ENABLE "Załącz harmonogram" +#define D_TIMER_ARM "Załącz" +#define D_TIMER_TIME "Czas" +#define D_TIMER_DAYS "Dni" +#define D_TIMER_REPEAT "Powtarzaj" +#define D_TIMER_OUTPUT "Wyjście" +#define D_TIMER_ACTION "Akcja" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Konfiguracja KNX" +#define D_KNX_PARAMETERS "Parametry KNX" +#define D_KNX_GENERAL_CONFIG "Konfiguracja ogólna" +#define D_KNX_PHYSICAL_ADDRESS "Adres fizyczny" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Musi być unikalny w sieci KNX)" +#define D_KNX_ENABLE "Załącz" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Adresy grupowe do zapisu" +#define D_ADD "Dodaj" +#define D_DELETE "Usuń" +#define D_REPLY "Odpowiedz" +#define D_KNX_GROUP_ADDRESS_TO_READ "Adresy grupowe do odbioru" +#define D_RECEIVED_FROM "Odebrane od" +#define D_KNX_COMMAND_WRITE "Zapisz" +#define D_KNX_COMMAND_READ "Czytaj" +#define D_KNX_COMMAND_OTHER "Inna komenda" +#define D_SENT_TO "Wyślij do" +#define D_KNX_WARNING "Adres grupy (0/0/0) jest zarezerwowany i nie można go użyć." +#define D_KNX_ENHANCEMENT "Rozszerzenia" +#define D_KNX_TX_SLOT "Gniazdo TX" +#define D_KNX_RX_SLOT "Gniazdo RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energia dzisiaj" +#define D_ENERGY_YESTERDAY "Energia wczoraj" +#define D_ENERGY_TOTAL "Energia całkowita" + +// xdrv_27_shutter.ino +#define D_OPEN "Otwórz" +#define D_CLOSE "Zamknij" +#define D_DOMOTICZ_SHUTTER "Roleta" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Konfiguracja PCF8574" +#define D_PCF8574_PARAMETERS "Parametry PCF8574" +#define D_INVERT_PORTS "Porty odwrócone" +#define D_DEVICE "Urządzenie" +#define D_DEVICE_INPUT "Wejście" +#define D_DEVICE_OUTPUT "Wyjście" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Czujnik zajęty" +#define D_SENSOR_CRC_ERROR "Błąd CRC czujnika" +#define D_SENSORS_FOUND "Znaleziono czujnik" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Trwa oczekiwanie" +#define D_START_SIGNAL_LOW "Sygnał startowy niski" +#define D_START_SIGNAL_HIGH "Sygnał startowy wysoki" +#define D_PULSE "Impuls" +#define D_CHECKSUM_FAILURE "Błędna suma kontrolna" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Czujnik nie otrzymał komendy ACK" +#define D_SHT1X_FOUND "SHT1X znaleziony" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Cząstki" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Usuń wagę" +#define D_HX_CAL_REFERENCE "Załaduj wagę referencyjną" +#define D_HX_CAL_DONE "Skalibrowany" +#define D_HX_CAL_FAIL "Błąd kalibracji" +#define D_RESET_HX711 "Zresetuj skalę" +#define D_CONFIGURE_HX711 "Skonfiguruj skalę" +#define D_HX711_PARAMETERS "Parametry skali" +#define D_ITEM_WEIGHT "Waga przedmiotu" +#define D_REFERENCE_WEIGHT "Waga referencyjna" +#define D_CALIBRATE "Skalibruj" +#define D_CALIBRATION "Kalibrowanie" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Kierunek" +#define D_TX20_WIND_SPEED "Prędkość" +#define D_TX20_WIND_SPEED_AVG "Średnia prędkość" +#define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Brak" +#define D_SENSOR_USER "Użytkownik" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "Odtearzacz MP3" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Przełącznik" // Suffix "1" +#define D_SENSOR_BUTTON "Przycisk" // Suffix "1" +#define D_SENSOR_RELAY "Przekaźnik" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "Led link" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Licznik" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Podświetlanie" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "Głęboko uśpiony" +#define D_SENSOR_EXS_ENABLE "Załącz EXS" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Godz" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sektory" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Przesunięcie faz" +#define D_IMPORT_ACTIVE "Czynna pobrana" +#define D_EXPORT_ACTIVE "Czynna oddana" +#define D_IMPORT_REACTIVE "Bierna pobrana" +#define D_EXPORT_REACTIVE "Bierna oddana" +#define D_TOTAL_REACTIVE "Bierna całkowita" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "Napięcie PV1" +#define D_PV1_CURRENT "Prąd PV1" +#define D_PV1_POWER "Moc PV1 " +#define D_PV2_VOLTAGE "Napięcie PV2" +#define D_PV2_CURRENT "Prąd PV2" +#define D_PV2_POWER "Moc PV2" +#define D_SOLAR_POWER "Moc PV" +#define D_INVERTER_POWER "Moc invertera" +#define D_STATUS "Status" +#define D_WAITING "Oczekiwanie" +#define D_CHECKING "Sprawdzanie" +#define D_WORKING "Praca" +#define D_FAILURE "Błąd" +#define D_SOLAX_ERROR_0 "Błąd - brak kodu" +#define D_SOLAX_ERROR_1 "Błąd - utrata sieci" +#define D_SOLAX_ERROR_2 "Błąd - napięcie sieci" +#define D_SOLAX_ERROR_3 "Błąd - częstotliwość sieci" +#define D_SOLAX_ERROR_4 "Błąd - napięcie PV" +#define D_SOLAX_ERROR_5 "Błąd - usterka izolacji" +#define D_SOLAX_ERROR_6 "Błąd - przegrzanie" +#define D_SOLAX_ERROR_7 "Błąd - wentylator" +#define D_SOLAX_ERROR_8 "Błąd - inne urządzenie" + +#endif // _LANGUAGE_PL_PL_D_H_ diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 43dc9581b..0efa57789 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -1,703 +1,701 @@ -/* - pt-BR.h - localization for Portuguese - Brazil for Tasmota - - Copyright (C) 2019 Fabiano Bovo - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_PT_BR_H_ -#define _LANGUAGE_PT_BR_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.0.0.1 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1046 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "pt" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DomSegTerQuaQuiSexSab" -#define D_MONTH3LIST "JanFevMarAbrMaiJunJulAgoSepOutNovDez" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Qualidade do ar" -#define D_AP "Ponto de acesso" // Ponto de Acesso -#define D_AS "como" -#define D_AUTO "Auto" -#define D_BLINK "Pulsar" -#define D_BLINKOFF "Pulsar desligado" -#define D_BOOT_COUNT "Contagem de inicialização" -#define D_BRIGHTLIGHT "Brilho" -#define D_BSSID "BSSId" -#define D_BUTTON "Botão" -#define D_BY "por" // Write by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canal" -#define D_CO2 "CO2" -#define D_CODE "Código" // Button code -#define D_COLDLIGHT "Luz fria" -#define D_COMMAND "Comando" -#define D_CONNECTED "Ligado" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Contagem" -#define D_COUNTER "Contador" -#define D_CURRENT "Corrente" // As in Voltage and Current -#define D_DATA "Dados" -#define D_DARKLIGHT "Luz escura" -#define D_DEBUG "Depurar" -#define D_DISABLED "Desabilitado" -#define D_DISTANCE "Distância" -#define D_DNS_SERVER "Servidor DNS" -#define D_DONE "Concluído" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulação" -#define D_ENABLED "Habilitado" -#define D_ERASE "Apagar" -#define D_ERROR "Erro" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Falha" -#define D_FALLBACK "Retornar" -#define D_FALLBACK_TOPIC "Tópico para retornar" -#define D_FALSE "Falso" -#define D_FILE "Arquivo" -#define D_FLOW_RATE "Quociente de vazão" -#define D_FREE_MEMORY "Memória livre" -#define D_FREQUENCY "Frequência" -#define D_GAS "Gás" -#define D_GATEWAY "Gateway" -#define D_GROUP "Grupo" -#define D_HOST "Host" -#define D_HOSTNAME "Nome do Host" -#define D_HUMIDITY "Umidade" -#define D_ILLUMINANCE "Luminância" -#define D_IMMEDIATE "Imediato" // Button immediate -#define D_INDEX "Índice" -#define D_INFO "Informação" -#define D_INFRARED "Infravermelho" -#define D_INITIALIZED "Inicializado" -#define D_IP_ADDRESS "Endereço IP" -#define D_LIGHT "Luz" -#define D_LWT "LWT" -#define D_MODULE "Módulo" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-pressão" -#define D_NOISE "Ruído" -#define D_NONE "Nenhum" -#define D_OFF "Desligado" -#define D_OFFLINE "Desconectado" -#define D_OK "Ok" -#define D_ON "Ligado" -#define D_ONLINE "Conectado" -#define D_PASSWORD "Senha" -#define D_PORT "Porta" -#define D_POWER_FACTOR "Fator de potência" -#define D_POWERUSAGE "Potência" -#define D_POWERUSAGE_ACTIVE "Potência ativa" -#define D_POWERUSAGE_APPARENT "Potência aparente" -#define D_POWERUSAGE_REACTIVE "Potência reativa" -#define D_PRESSURE "Pressão" -#define D_PRESSUREATSEALEVEL "Pressão ao nível do mar" -#define D_PROGRAM_FLASH_SIZE "Tamanho do programa na memória" -#define D_PROGRAM_SIZE "Tamanho do programa" -#define D_PROJECT "Projeto" -#define D_RAIN "Rain" -#define D_RECEIVED "Recebido" -#define D_RESTART "Reiniciar" -#define D_RESTARTING "Reiniciando" -#define D_RESTART_REASON "Motivo do reinício" -#define D_RESTORE "Restauração" -#define D_RETAINED "Manter" -#define D_RULE "Regra" -#define D_SAVE "Salvar" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Iniciar" -#define D_STD_TIME "STD" -#define D_STOP "Parar" -#define D_SUBNET_MASK "Máscara sub rede" -#define D_SUBSCRIBE_TO "Subescrever para" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Successo" -#define D_SUNRISE "Nascer do sol" -#define D_SUNSET "Por do sol" -#define D_TEMPERATURE "Temperatura" -#define D_TO "Para" -#define D_TOGGLE "Inverter" -#define D_TOPIC "Tópico" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Transmitir" -#define D_TRUE "Verdadeiro" -#define D_TVOC "TVOC" -#define D_UPGRADE "atualização" -#define D_UPLOAD "Enviar" -#define D_UPTIME "Tempo de atividade" -#define D_USER "Usuário" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Índice UV" -#define D_UV_INDEX_1 "Baixo" -#define D_UV_INDEX_2 "Médio" -#define D_UV_INDEX_3 "Alto" -#define D_UV_INDEX_4 "Perigro" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Nível UV" -#define D_UV_POWER "UV Power" -#define D_VERSION "Versão" -#define D_VOLTAGE "Voltagem" -#define D_WEIGHT "Peso" -#define D_WARMLIGHT "Luz quente" -#define D_WEB_SERVER "Servidor WEB" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes" -#define D_LEVEL_10 "nível 1-0" -#define D_LEVEL_01 "nível 0-1" -#define D_SERIAL_LOGGING_DISABLED "Registro Serial desabilitado" -#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" - -#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" -#define D_RECEIVED_TOPIC "Tópico recebido" -#define D_DATA_SIZE "Tamanho de dados" -#define D_ANALOG_INPUT "Entrada analógica" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Loop bloqueado" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig falha de estado" -#define D_ACTIVE_FOR_3_MINUTES "Ativo por 3 minutos" -#define D_FAILED_TO_START "Falha ao iníciar" -#define D_PATCH_ISSUE_2186 "Questão 2186" -#define D_CONNECTING_TO_AP "Ligando ao PA" -#define D_IN_MODE "em modo" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "A ligação falhou porque nenhum endereço IP foi recebido" -#define D_CONNECT_FAILED_AP_NOT_REACHED "A ligação falhou porque o PA não pôde ser alcançado" -#define D_CONNECT_FAILED_WRONG_PASSWORD "A ligação falhou porque a senha está incorreta" -#define D_CONNECT_FAILED_AP_TIMEOUT "A ligação falhou porque o tempo foi excedido" -#define D_ATTEMPTING_CONNECTION "Ligando..." -#define D_CHECKING_CONNECTION "Verificando ligação..." -#define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" -#define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" -#define D_FOUND_AT "encontrado em" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog anfitrião não encontrado" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Guardado na flash em" -#define D_LOADED_FROM_FLASH_AT "Lido da flash em" -#define D_USE_DEFAULTS "Usar predefinições" -#define D_ERASED_SECTOR "Apagar setores" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" -#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" -#define D_WITH_IP_ADDRESS "com o endereço IP" -#define D_WEBSERVER_STOPPED "Servidor WEB parou" -#define D_FILE_NOT_FOUND "Arquivo não encontrado" -#define D_REDIRECTED "Redirecionado para o portal ativo" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager: configura o Ponto de Acesso e a Estação" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager: configura o Ponto de Acesso" -#define D_TRYING_TO_CONNECT "Conectar o dispositivo à rede" - -#define D_RESTART_IN "Reinicia em" -#define D_SECONDS "segundos" -#define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" -#define D_BUTTON_TOGGLE "Comandar" -#define D_CONFIGURATION "Configuração" -#define D_INFORMATION "Informação" -#define D_FIRMWARE_UPGRADE "Atualização de Firmware" -#define D_CONSOLE "Console" -#define D_CONFIRM_RESTART "Confirmar o reinicio" - -#define D_CONFIGURE_MODULE "Configurar Módulo" -#define D_CONFIGURE_WIFI "Configurar WiFi" -#define D_CONFIGURE_MQTT "Configurar MQTT" -#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" -#define D_CONFIGURE_LOGGING "Configurar Logging" -#define D_CONFIGURE_OTHER "Configurar outras opções" -#define D_CONFIRM_RESET_CONFIGURATION "Confirmar limpeza de configuração" -#define D_RESET_CONFIGURATION "Apagar configuração" -#define D_BACKUP_CONFIGURATION "Salvar configuração" -#define D_RESTORE_CONFIGURATION "Repor configuração" -#define D_MAIN_MENU "Menu principal" - -#define D_MODULE_PARAMETERS "Parâmetros do módulo" -#define D_MODULE_TYPE "Tipo de módulo" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Entrada serial" -#define D_SERIAL_OUT "Saída serial" - -#define D_WIFI_PARAMETERS "Parâmetros do wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Encontrar redes wifi" -#define D_SCAN_DONE "Busca finalizada" -#define D_NO_NETWORKS_FOUND "Sem redes" -#define D_REFRESH_TO_SCAN_AGAIN "Nova busca" -#define D_DUPLICATE_ACCESSPOINT "Ponto de Acesso duplicado" -#define D_SKIPPING_LOW_QUALITY "Ignorado devido à baixa qualidade do sinal" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "Senha AP1" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "Senha AP2" - -#define D_MQTT_PARAMETERS "Parâmetros MQTT" -#define D_CLIENT "Cliente" -#define D_FULL_TOPIC "Tópico completo" - -#define D_LOGGING_PARAMETERS "Parâmetros Logging" -#define D_SERIAL_LOG_LEVEL "Nível de registro serial" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Nível de registro WEB" -#define D_SYS_LOG_LEVEL "Nível de registro Syslog" -#define D_MORE_DEBUG "Depurar mais" -#define D_SYSLOG_HOST "Syslog anfitrião" -#define D_SYSLOG_PORT "Porta Syslog" -#define D_TELEMETRY_PERIOD "Período de telemetria" - -#define D_OTHER_PARAMETERS "Outros parâmetros" -#define D_TEMPLATE "Modelo" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin" -#define D_MQTT_ENABLE "MQTT habilitado" -#define D_FRIENDLY_NAME "Nome amigável" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "Dispositivo único" -#define D_MULTI_DEVICE "Múltiplos dispositivos" - -#define D_CONFIGURE_TEMPLATE "Configurar Modelo" -#define D_TEMPLATE_PARAMETERS "Parâmetros Modelo" -#define D_TEMPLATE_NAME "Nome" -#define D_BASE_TYPE "Baseado em" -#define D_TEMPLATE_FLAGS "Opções" - -#define D_SAVE_CONFIGURATION "Gravar configuração" -#define D_CONFIGURATION_SAVED "Configuração gravada" -#define D_CONFIGURATION_RESET "Reinicialização da configuração" - -#define D_PROGRAM_VERSION "Versão do programa" -#define D_BUILD_DATE_AND_TIME "Data e Hora da compilação" -#define D_CORE_AND_SDK_VERSION "Versão Core/SDK" -#define D_FLASH_WRITE_COUNT "Contagem de gravação flash" -#define D_MAC_ADDRESS "Endereço MAC" -#define D_MQTT_HOST "MQTT Servidor" -#define D_MQTT_PORT "MQTT Porta" -#define D_MQTT_CLIENT "MQTT Cliente" -#define D_MQTT_USER "MQTT Usuário" -#define D_MQTT_TOPIC "MQTT Tópico" -#define D_MQTT_GROUP_TOPIC "MQTT Tópico Grupo" -#define D_MQTT_FULL_TOPIC "MQTT Tópico Completo" -#define D_MDNS_DISCOVERY "Descobrir mDNS" -#define D_MDNS_ADVERTISE "Anunciar mDNS" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Size" -#define D_FREE_PROGRAM_SPACE "Espaço Livre Programa" - -#define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Iniciar atualização" -#define D_UPGRADE_BY_FILE_UPLOAD "Atualização por arquivo local" -#define D_UPLOAD_STARTED "Início do envio" -#define D_UPGRADE_STARTED "Atualização iniciada" -#define D_UPLOAD_DONE "Atualização finalizada" -#define D_UPLOAD_ERR_1 "Nenhum arquivo selecionado" -#define D_UPLOAD_ERR_2 "Não existe memória disponível" -#define D_UPLOAD_ERR_3 "Byte mágico não é 0xE9" -#define D_UPLOAD_ERR_4 "O tamanho do programa é maior do que o tamanho da memória" -#define D_UPLOAD_ERR_5 "Envio buffer miscompare" -#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar logging 3" -#define D_UPLOAD_ERR_7 "Envio cancelado" -#define D_UPLOAD_ERR_8 "Arquivo inválido" -#define D_UPLOAD_ERR_9 "Arquivo muito grande" -#define D_UPLOAD_ERR_10 "Falha ao iniciar chip RF" -#define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF" -#define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF" -#define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF" -#define D_UPLOAD_ERROR_CODE "Código de erro do envio" - -#define D_ENTER_COMMAND "Inserir comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 se resposta esperada" -#define D_NEED_USER_AND_PASSWORD "Necessário user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifique a impressão digital TLS..." -#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" -#define D_RETRY_IN "Tentativa em" -#define D_VERIFIED "Verificado impressão digital " -#define D_INSECURE "Ligação insegura devido à impressão digital inválida" -#define D_CONNECT_FAILED_TO "A ligação falhou ao" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast desabilitado" -#define D_MULTICAST_REJOINED "Multicast (re)ingressou" -#define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" -#define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo evento básico" -#define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" -#define D_WEMO_META_SERVICE "WeMo serviço meta" -#define D_WEMO_SETUP "WeMo configuração" -#define D_RESPONSE_SENT "Resposta enviada" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API nao implementada" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parâmetros Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Chave idx" -#define D_DOMOTICZ_SWITCH_IDX "Interruptor idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Umi" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Umi,Pres" - #define D_DOMOTICZ_POWER_ENERGY "Potência,Energia" - #define D_DOMOTICZ_ILLUMINANCE "Luminância" - #define D_DOMOTICZ_COUNT "Contagem/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltagem/PM2.5" - #define D_DOMOTICZ_CURRENT "Corrente/PM10" - #define D_DOMOTICZ_AIRQUALITY "Qualidade do ar" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Tempo de atualização" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configurar temporizador" -#define D_TIMER_PARAMETERS "Parâmetros" -#define D_TIMER_ENABLE "Habilitar temporizadores" -#define D_TIMER_ARM "Habilitar" -#define D_TIMER_TIME "Horário" -#define D_TIMER_DAYS "Dias" -#define D_TIMER_REPEAT "Repetir" -#define D_TIMER_OUTPUT "Saída" -#define D_TIMER_ACTION "Ação" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configurar KNX" -#define D_KNX_PARAMETERS "Parâmetros KNX" -#define D_KNX_GENERAL_CONFIG "Geral" -#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Deve ser único na rede KNX)" -#define D_KNX_ENABLE "Habilitar KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Endereço do grupo para enviar" -#define D_ADD "Adicionar" -#define D_DELETE "Remover" -#define D_REPLY "Responder" -#define D_KNX_GROUP_ADDRESS_TO_READ "Endereço do grupo para receber" -#define D_RECEIVED_FROM "Recebido de" -#define D_KNX_COMMAND_WRITE "Escrever" -#define D_KNX_COMMAND_READ "Ler" -#define D_KNX_COMMAND_OTHER "Outros" -#define D_SENT_TO "Enviar para" -#define D_KNX_WARNING "O endereço ( 0 / 0 / 0 ) é reservado e não pode ser usado." -#define D_KNX_ENHANCEMENT "Melhoria da comunicação" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Consumo energético de hoje" -#define D_ENERGY_YESTERDAY "Consumo energético de ontem" -#define D_ENERGY_TOTAL "Consumo total de energia" - -// xdrv_27_shutter.ino -#define D_OPEN "Aberta" -#define D_CLOSE "Fechada" -#define D_DOMOTICZ_SHUTTER "Persiana" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configura PCF8574" -#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" -#define D_INVERT_PORTS "Portas Invertidas" -#define D_DEVICE "Dispositivo" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor ocupado" -#define D_SENSOR_CRC_ERROR "Erro sensor CRC" -#define D_SENSORS_FOUND "Sensores encontrados" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" -#define D_START_SIGNAL_LOW "Sinal de início baixo" -#define D_START_SIGNAL_HIGH "Sinal de início elevado" -#define D_PULSE "pulso" -#define D_CHECKSUM_FAILURE "Falha checksum" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" -#define D_SHT1X_FOUND "SHT1X encontrado" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partículas" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remover peso" -#define D_HX_CAL_REFERENCE "Peso de referência de carga" -#define D_HX_CAL_DONE "Calibrado" -#define D_HX_CAL_FAIL "Falha na calibração" -#define D_RESET_HX711 "Redefinir escala" -#define D_CONFIGURE_HX711 "Configurar escala" -#define D_HX711_PARAMETERS "Parâmetros de escala" -#define D_ITEM_WEIGHT "Peso do Item" -#define D_REFERENCE_WEIGHT "Peso de referência" -#define D_CALIBRATE "Calibrar" -#define D_CALIBRATION "Calibração" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direção do vento" -#define D_TX20_WIND_SPEED "Velocidade do vento" -#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" -#define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "L" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Nenhum" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Interruptor" // Suffix "1" -#define D_SENSOR_BUTTON "Botão" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Contador" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Luz de fundo" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "H" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "M" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "s" -#define D_UNIT_SECTORS "setores" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "W/h" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Ângulo de Fase" -#define D_IMPORT_ACTIVE "Importar Ativo" -#define D_EXPORT_ACTIVE "Exportar Ativo" -#define D_IMPORT_REACTIVE "Importar Reativo" -#define D_EXPORT_REACTIVE "Exportar Reativo" -#define D_TOTAL_REACTIVE "Reativo total" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltagem" -#define D_PV1_CURRENT "PV1 Corrente" -#define D_PV1_POWER "PV1 Energia" -#define D_PV2_VOLTAGE "PV2 Voltagem" -#define D_PV2_CURRENT "PV2 Corrente" -#define D_PV2_POWER "PV2 Energia" -#define D_SOLAR_POWER "Energia Solar" -#define D_INVERTER_POWER "Potência do Inversor" -#define D_STATUS "Status" -#define D_WAITING "Esperando" -#define D_CHECKING "Verificando" -#define D_WORKING "Trabalhando" -#define D_FAILURE "Falha" -#define D_SOLAX_ERROR_0 "Nenhum código de erro" -#define D_SOLAX_ERROR_1 "Erro Grid Perdida" -#define D_SOLAX_ERROR_2 "Falha na Tensão da rede" -#define D_SOLAX_ERROR_3 "Falha na Frequência do Grid" -#define D_SOLAX_ERROR_4 "Pv Falha de Tensão" -#define D_SOLAX_ERROR_5 "Falha de Isolamento" -#define D_SOLAX_ERROR_6 "Falha de Temperatura excessiva" -#define D_SOLAX_ERROR_7 "Falha no Ventilador" -#define D_SOLAX_ERROR_8 "Outra falha do dispositivo" - -#endif // _LANGUAGE_PT_BR_H_ +/* + pt-BR.h - localization for Portuguese - Brazil for Tasmota + + Copyright (C) 2019 Fabiano Bovo + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_PT_BR_H_ +#define _LANGUAGE_PT_BR_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.0.0.1 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1046 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "pt" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DomSegTerQuaQuiSexSab" +#define D_MONTH3LIST "JanFevMarAbrMaiJunJulAgoSepOutNovDez" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Qualidade do ar" +#define D_AP "Ponto de acesso" // Ponto de Acesso +#define D_AS "como" +#define D_AUTO "Auto" +#define D_BLINK "Pulsar" +#define D_BLINKOFF "Pulsar desligado" +#define D_BOOT_COUNT "Contagem de inicialização" +#define D_BRIGHTLIGHT "Brilho" +#define D_BSSID "BSSId" +#define D_BUTTON "Botão" +#define D_BY "por" // Write by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "CO2" +#define D_CODE "Código" // Button code +#define D_COLDLIGHT "Luz fria" +#define D_COMMAND "Comando" +#define D_CONNECTED "Ligado" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Contagem" +#define D_COUNTER "Contador" +#define D_CURRENT "Corrente" // As in Voltage and Current +#define D_DATA "Dados" +#define D_DARKLIGHT "Luz escura" +#define D_DEBUG "Depurar" +#define D_DISABLED "Desabilitado" +#define D_DISTANCE "Distância" +#define D_DNS_SERVER "Servidor DNS" +#define D_DONE "Concluído" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulação" +#define D_ENABLED "Habilitado" +#define D_ERASE "Apagar" +#define D_ERROR "Erro" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Falha" +#define D_FALLBACK "Retornar" +#define D_FALLBACK_TOPIC "Tópico para retornar" +#define D_FALSE "Falso" +#define D_FILE "Arquivo" +#define D_FLOW_RATE "Quociente de vazão" +#define D_FREE_MEMORY "Memória livre" +#define D_FREQUENCY "Frequência" +#define D_GAS "Gás" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupo" +#define D_HOST "Host" +#define D_HOSTNAME "Nome do Host" +#define D_HUMIDITY "Umidade" +#define D_ILLUMINANCE "Luminância" +#define D_IMMEDIATE "Imediato" // Button immediate +#define D_INDEX "Índice" +#define D_INFO "Informação" +#define D_INFRARED "Infravermelho" +#define D_INITIALIZED "Inicializado" +#define D_IP_ADDRESS "Endereço IP" +#define D_LIGHT "Luz" +#define D_LWT "LWT" +#define D_MODULE "Módulo" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-pressão" +#define D_NOISE "Ruído" +#define D_NONE "Nenhum" +#define D_OFF "Desligado" +#define D_OFFLINE "Desconectado" +#define D_OK "Ok" +#define D_ON "Ligado" +#define D_ONLINE "Conectado" +#define D_PASSWORD "Senha" +#define D_PORT "Porta" +#define D_POWER_FACTOR "Fator de potência" +#define D_POWERUSAGE "Potência" +#define D_POWERUSAGE_ACTIVE "Potência ativa" +#define D_POWERUSAGE_APPARENT "Potência aparente" +#define D_POWERUSAGE_REACTIVE "Potência reativa" +#define D_PRESSURE "Pressão" +#define D_PRESSUREATSEALEVEL "Pressão ao nível do mar" +#define D_PROGRAM_FLASH_SIZE "Tamanho do programa na memória" +#define D_PROGRAM_SIZE "Tamanho do programa" +#define D_PROJECT "Projeto" +#define D_RAIN "Rain" +#define D_RECEIVED "Recebido" +#define D_RESTART "Reiniciar" +#define D_RESTARTING "Reiniciando" +#define D_RESTART_REASON "Motivo do reinício" +#define D_RESTORE "Restauração" +#define D_RETAINED "Manter" +#define D_RULE "Regra" +#define D_SAVE "Salvar" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Iniciar" +#define D_STD_TIME "STD" +#define D_STOP "Parar" +#define D_SUBNET_MASK "Máscara sub rede" +#define D_SUBSCRIBE_TO "Subescrever para" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Successo" +#define D_SUNRISE "Nascer do sol" +#define D_SUNSET "Por do sol" +#define D_TEMPERATURE "Temperatura" +#define D_TO "Para" +#define D_TOGGLE "Inverter" +#define D_TOPIC "Tópico" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Transmitir" +#define D_TRUE "Verdadeiro" +#define D_TVOC "TVOC" +#define D_UPGRADE "atualização" +#define D_UPLOAD "Enviar" +#define D_UPTIME "Tempo de atividade" +#define D_USER "Usuário" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Índice UV" +#define D_UV_INDEX_1 "Baixo" +#define D_UV_INDEX_2 "Médio" +#define D_UV_INDEX_3 "Alto" +#define D_UV_INDEX_4 "Perigro" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Nível UV" +#define D_UV_POWER "UV Power" +#define D_VERSION "Versão" +#define D_VOLTAGE "Voltagem" +#define D_WEIGHT "Peso" +#define D_WARMLIGHT "Luz quente" +#define D_WEB_SERVER "Servidor WEB" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes" +#define D_LEVEL_10 "nível 1-0" +#define D_LEVEL_01 "nível 0-1" +#define D_SERIAL_LOGGING_DISABLED "Registro Serial desabilitado" +#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" + +#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" +#define D_RECEIVED_TOPIC "Tópico recebido" +#define D_DATA_SIZE "Tamanho de dados" +#define D_ANALOG_INPUT "Entrada analógica" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Loop bloqueado" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig falha de estado" +#define D_ACTIVE_FOR_3_MINUTES "Ativo por 3 minutos" +#define D_FAILED_TO_START "Falha ao iníciar" +#define D_PATCH_ISSUE_2186 "Questão 2186" +#define D_CONNECTING_TO_AP "Ligando ao PA" +#define D_IN_MODE "em modo" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "A ligação falhou porque nenhum endereço IP foi recebido" +#define D_CONNECT_FAILED_AP_NOT_REACHED "A ligação falhou porque o PA não pôde ser alcançado" +#define D_CONNECT_FAILED_WRONG_PASSWORD "A ligação falhou porque a senha está incorreta" +#define D_CONNECT_FAILED_AP_TIMEOUT "A ligação falhou porque o tempo foi excedido" +#define D_ATTEMPTING_CONNECTION "Ligando..." +#define D_CHECKING_CONNECTION "Verificando ligação..." +#define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" +#define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" +#define D_FOUND_AT "encontrado em" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog anfitrião não encontrado" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Guardado na flash em" +#define D_LOADED_FROM_FLASH_AT "Lido da flash em" +#define D_USE_DEFAULTS "Usar predefinições" +#define D_ERASED_SECTOR "Apagar setores" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo
Atualizar por favor" +#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" +#define D_WITH_IP_ADDRESS "com o endereço IP" +#define D_WEBSERVER_STOPPED "Servidor WEB parou" +#define D_FILE_NOT_FOUND "Arquivo não encontrado" +#define D_REDIRECTED "Redirecionado para o portal ativo" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager: configura o Ponto de Acesso e a Estação" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager: configura o Ponto de Acesso" +#define D_TRYING_TO_CONNECT "Conectar o dispositivo à rede" + +#define D_RESTART_IN "Reinicia em" +#define D_SECONDS "segundos" +#define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" +#define D_BUTTON_TOGGLE "Comandar" +#define D_CONFIGURATION "Configuração" +#define D_INFORMATION "Informação" +#define D_FIRMWARE_UPGRADE "Atualização de Firmware" +#define D_CONSOLE "Console" +#define D_CONFIRM_RESTART "Confirmar o reinicio" + +#define D_CONFIGURE_MODULE "Configurar Módulo" +#define D_CONFIGURE_WIFI "Configurar WiFi" +#define D_CONFIGURE_MQTT "Configurar MQTT" +#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" +#define D_CONFIGURE_LOGGING "Configurar Logging" +#define D_CONFIGURE_OTHER "Configurar outras opções" +#define D_CONFIRM_RESET_CONFIGURATION "Confirmar limpeza de configuração" +#define D_RESET_CONFIGURATION "Apagar configuração" +#define D_BACKUP_CONFIGURATION "Salvar configuração" +#define D_RESTORE_CONFIGURATION "Repor configuração" +#define D_MAIN_MENU "Menu principal" + +#define D_MODULE_PARAMETERS "Parâmetros do módulo" +#define D_MODULE_TYPE "Tipo de módulo" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Entrada serial" +#define D_SERIAL_OUT "Saída serial" + +#define D_WIFI_PARAMETERS "Parâmetros do wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Encontrar redes wifi" +#define D_SCAN_DONE "Busca finalizada" +#define D_NO_NETWORKS_FOUND "Sem redes" +#define D_REFRESH_TO_SCAN_AGAIN "Nova busca" +#define D_DUPLICATE_ACCESSPOINT "Ponto de Acesso duplicado" +#define D_SKIPPING_LOW_QUALITY "Ignorado devido à baixa qualidade do sinal" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "Senha AP1" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "Senha AP2" + +#define D_MQTT_PARAMETERS "Parâmetros MQTT" +#define D_CLIENT "Cliente" +#define D_FULL_TOPIC "Tópico completo" + +#define D_LOGGING_PARAMETERS "Parâmetros Logging" +#define D_SERIAL_LOG_LEVEL "Nível de registro serial" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Nível de registro WEB" +#define D_SYS_LOG_LEVEL "Nível de registro Syslog" +#define D_MORE_DEBUG "Depurar mais" +#define D_SYSLOG_HOST "Syslog anfitrião" +#define D_SYSLOG_PORT "Porta Syslog" +#define D_TELEMETRY_PERIOD "Período de telemetria" + +#define D_OTHER_PARAMETERS "Outros parâmetros" +#define D_TEMPLATE "Modelo" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin" +#define D_MQTT_ENABLE "MQTT habilitado" +#define D_FRIENDLY_NAME "Nome amigável" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "Dispositivo único" +#define D_MULTI_DEVICE "Múltiplos dispositivos" + +#define D_CONFIGURE_TEMPLATE "Configurar Modelo" +#define D_TEMPLATE_PARAMETERS "Parâmetros Modelo" +#define D_TEMPLATE_NAME "Nome" +#define D_BASE_TYPE "Baseado em" +#define D_TEMPLATE_FLAGS "Opções" + +#define D_SAVE_CONFIGURATION "Gravar configuração" +#define D_CONFIGURATION_SAVED "Configuração gravada" +#define D_CONFIGURATION_RESET "Reinicialização da configuração" + +#define D_PROGRAM_VERSION "Versão do programa" +#define D_BUILD_DATE_AND_TIME "Data e Hora da compilação" +#define D_CORE_AND_SDK_VERSION "Versão Core/SDK" +#define D_FLASH_WRITE_COUNT "Contagem de gravação flash" +#define D_MAC_ADDRESS "Endereço MAC" +#define D_MQTT_HOST "MQTT Servidor" +#define D_MQTT_PORT "MQTT Porta" +#define D_MQTT_CLIENT "MQTT Cliente" +#define D_MQTT_USER "MQTT Usuário" +#define D_MQTT_TOPIC "MQTT Tópico" +#define D_MQTT_GROUP_TOPIC "MQTT Tópico Grupo" +#define D_MQTT_FULL_TOPIC "MQTT Tópico Completo" +#define D_MDNS_DISCOVERY "Descobrir mDNS" +#define D_MDNS_ADVERTISE "Anunciar mDNS" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash Size" +#define D_FREE_PROGRAM_SPACE "Espaço Livre Programa" + +#define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Iniciar atualização" +#define D_UPGRADE_BY_FILE_UPLOAD "Atualização por arquivo local" +#define D_UPLOAD_STARTED "Início do envio" +#define D_UPGRADE_STARTED "Atualização iniciada" +#define D_UPLOAD_DONE "Atualização finalizada" +#define D_UPLOAD_ERR_1 "Nenhum arquivo selecionado" +#define D_UPLOAD_ERR_2 "Não existe memória disponível" +#define D_UPLOAD_ERR_3 "Byte mágico não é 0xE9" +#define D_UPLOAD_ERR_4 "O tamanho do programa é maior do que o tamanho da memória" +#define D_UPLOAD_ERR_5 "Envio buffer miscompare" +#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar logging 3" +#define D_UPLOAD_ERR_7 "Envio cancelado" +#define D_UPLOAD_ERR_8 "Arquivo inválido" +#define D_UPLOAD_ERR_9 "Arquivo muito grande" +#define D_UPLOAD_ERR_10 "Falha ao iniciar chip RF" +#define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF" +#define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF" +#define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF" +#define D_UPLOAD_ERROR_CODE "Código de erro do envio" + +#define D_ENTER_COMMAND "Inserir comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 se resposta esperada" +#define D_NEED_USER_AND_PASSWORD "Necessário user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifique a impressão digital TLS..." +#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" +#define D_RETRY_IN "Tentativa em" +#define D_VERIFIED "Verificado impressão digital " +#define D_INSECURE "Ligação insegura devido à impressão digital inválida" +#define D_CONNECT_FAILED_TO "A ligação falhou ao" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast desabilitado" +#define D_MULTICAST_REJOINED "Multicast (re)ingressou" +#define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" +#define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo evento básico" +#define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" +#define D_WEMO_META_SERVICE "WeMo serviço meta" +#define D_WEMO_SETUP "WeMo configuração" +#define D_RESPONSE_SENT "Resposta enviada" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API nao implementada" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parâmetros Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Chave idx" +#define D_DOMOTICZ_SWITCH_IDX "Interruptor idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Umi" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Umi,Pres" + #define D_DOMOTICZ_POWER_ENERGY "Potência,Energia" + #define D_DOMOTICZ_ILLUMINANCE "Luminância" + #define D_DOMOTICZ_COUNT "Contagem/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltagem/PM2.5" + #define D_DOMOTICZ_CURRENT "Corrente/PM10" + #define D_DOMOTICZ_AIRQUALITY "Qualidade do ar" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Tempo de atualização" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configurar temporizador" +#define D_TIMER_PARAMETERS "Parâmetros" +#define D_TIMER_ENABLE "Habilitar temporizadores" +#define D_TIMER_ARM "Habilitar" +#define D_TIMER_TIME "Horário" +#define D_TIMER_DAYS "Dias" +#define D_TIMER_REPEAT "Repetir" +#define D_TIMER_OUTPUT "Saída" +#define D_TIMER_ACTION "Ação" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configurar KNX" +#define D_KNX_PARAMETERS "Parâmetros KNX" +#define D_KNX_GENERAL_CONFIG "Geral" +#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Deve ser único na rede KNX)" +#define D_KNX_ENABLE "Habilitar KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Endereço do grupo para enviar" +#define D_ADD "Adicionar" +#define D_DELETE "Remover" +#define D_REPLY "Responder" +#define D_KNX_GROUP_ADDRESS_TO_READ "Endereço do grupo para receber" +#define D_RECEIVED_FROM "Recebido de" +#define D_KNX_COMMAND_WRITE "Escrever" +#define D_KNX_COMMAND_READ "Ler" +#define D_KNX_COMMAND_OTHER "Outros" +#define D_SENT_TO "Enviar para" +#define D_KNX_WARNING "O endereço ( 0 / 0 / 0 ) é reservado e não pode ser usado." +#define D_KNX_ENHANCEMENT "Melhoria da comunicação" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Consumo energético de hoje" +#define D_ENERGY_YESTERDAY "Consumo energético de ontem" +#define D_ENERGY_TOTAL "Consumo total de energia" + +// xdrv_27_shutter.ino +#define D_OPEN "Aberta" +#define D_CLOSE "Fechada" +#define D_DOMOTICZ_SHUTTER "Persiana" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configura PCF8574" +#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" +#define D_INVERT_PORTS "Portas Invertidas" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor ocupado" +#define D_SENSOR_CRC_ERROR "Erro sensor CRC" +#define D_SENSORS_FOUND "Sensores encontrados" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" +#define D_START_SIGNAL_LOW "Sinal de início baixo" +#define D_START_SIGNAL_HIGH "Sinal de início elevado" +#define D_PULSE "pulso" +#define D_CHECKSUM_FAILURE "Falha checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" +#define D_SHT1X_FOUND "SHT1X encontrado" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partículas" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remover peso" +#define D_HX_CAL_REFERENCE "Peso de referência de carga" +#define D_HX_CAL_DONE "Calibrado" +#define D_HX_CAL_FAIL "Falha na calibração" +#define D_RESET_HX711 "Redefinir escala" +#define D_CONFIGURE_HX711 "Configurar escala" +#define D_HX711_PARAMETERS "Parâmetros de escala" +#define D_ITEM_WEIGHT "Peso do Item" +#define D_REFERENCE_WEIGHT "Peso de referência" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibração" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direção do vento" +#define D_TX20_WIND_SPEED "Velocidade do vento" +#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" +#define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "L" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Nenhum" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Interruptor" // Suffix "1" +#define D_SENSOR_BUTTON "Botão" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Contador" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Luz de fundo" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "H" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "M" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "s" +#define D_UNIT_SECTORS "setores" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "W/h" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Ângulo de Fase" +#define D_IMPORT_ACTIVE "Importar Ativo" +#define D_EXPORT_ACTIVE "Exportar Ativo" +#define D_IMPORT_REACTIVE "Importar Reativo" +#define D_EXPORT_REACTIVE "Exportar Reativo" +#define D_TOTAL_REACTIVE "Reativo total" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltagem" +#define D_PV1_CURRENT "PV1 Corrente" +#define D_PV1_POWER "PV1 Energia" +#define D_PV2_VOLTAGE "PV2 Voltagem" +#define D_PV2_CURRENT "PV2 Corrente" +#define D_PV2_POWER "PV2 Energia" +#define D_SOLAR_POWER "Energia Solar" +#define D_INVERTER_POWER "Potência do Inversor" +#define D_STATUS "Status" +#define D_WAITING "Esperando" +#define D_CHECKING "Verificando" +#define D_WORKING "Trabalhando" +#define D_FAILURE "Falha" +#define D_SOLAX_ERROR_0 "Nenhum código de erro" +#define D_SOLAX_ERROR_1 "Erro Grid Perdida" +#define D_SOLAX_ERROR_2 "Falha na Tensão da rede" +#define D_SOLAX_ERROR_3 "Falha na Frequência do Grid" +#define D_SOLAX_ERROR_4 "Pv Falha de Tensão" +#define D_SOLAX_ERROR_5 "Falha de Isolamento" +#define D_SOLAX_ERROR_6 "Falha de Temperatura excessiva" +#define D_SOLAX_ERROR_7 "Falha no Ventilador" +#define D_SOLAX_ERROR_8 "Outra falha do dispositivo" + +#endif // _LANGUAGE_PT_BR_H_ diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index e9a08c753..a6299c0c8 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -1,703 +1,701 @@ -/* - pt-PT.h - localization for Portuguese - Portugal for Tasmota - - Copyright (C) 2019 Paulo Paiva - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_PT_PT_H_ -#define _LANGUAGE_PT_PT_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v7.0.0.1 -\*********************************************************************/ - -#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 2070 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "pt" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "DomSegTerQuaQuiSexSab" -#define D_MONTH3LIST "JanFevMarAbrMaiJunJulAgoSepOutNovDez" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Qualidade do Ar" -#define D_AP "AP" // Ponto de Acesso -#define D_AS "como" -#define D_AUTO "AUTO" -#define D_BLINK "Piscar" -#define D_BLINKOFF "Piscar Desligado" -#define D_BOOT_COUNT "Contagem de Inicialização" -#define D_BRIGHTLIGHT "Brilho" -#define D_BSSID "BSSId" -#define D_BUTTON "Botão" -#define D_BY "por" // Write by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Canal" -#define D_CO2 "Dioxido de Carbono" -#define D_CODE "Código" // Button code -#define D_COLDLIGHT "Luz Fria" -#define D_COMMAND "Comando" -#define D_CONNECTED "Ligado" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Contagem" -#define D_COUNTER "Contador" -#define D_CURRENT "Corrente" // As in Voltage and Current -#define D_DATA "Dados" -#define D_DARKLIGHT "Luz Escura" -#define D_DEBUG "Depurar" -#define D_DISABLED "Disabilitado" -#define D_DISTANCE "Distância" -#define D_DNS_SERVER "Servidor DNS" -#define D_DONE "Concluído" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulação" -#define D_ENABLED "Habilitado" -#define D_ERASE "Apagar" -#define D_ERROR "Erro" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Falha" -#define D_FALLBACK "Retornar" -#define D_FALLBACK_TOPIC "Tópico para retornar" -#define D_FALSE "Falso" -#define D_FILE "Ficheiro" -#define D_FLOW_RATE "Taxa de Fluxo" -#define D_FREE_MEMORY "Memoria Livre" -#define D_FREQUENCY "Frequência" -#define D_GAS "Gás" -#define D_GATEWAY "Gateway" -#define D_GROUP "Grupo" -#define D_HOST "Anfitrião" -#define D_HOSTNAME "Nome Anfitrião" -#define D_HUMIDITY "Humidade" -#define D_ILLUMINANCE "Luminâcia" -#define D_IMMEDIATE "Immediato" // Button immediate -#define D_INDEX "Indíce" -#define D_INFO "Info" -#define D_INFRARED "Infravermelho" -#define D_INITIALIZED "Inicializado" -#define D_IP_ADDRESS "Endereço IP" -#define D_LIGHT "Luz" -#define D_LWT "LWT" -#define D_MODULE "Módulo" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-pressão" -#define D_NOISE "Ruído" -#define D_NONE "Nenhum" -#define D_OFF "Off" -#define D_OFFLINE "Desconetado" -#define D_OK "Ok" -#define D_ON "On" -#define D_ONLINE "Conetado" -#define D_PASSWORD "Palavra Chave" -#define D_PORT "Porta" -#define D_POWER_FACTOR "Factor de Potência" -#define D_POWERUSAGE "Potência" -#define D_POWERUSAGE_ACTIVE "Potência Ativa" -#define D_POWERUSAGE_APPARENT "Potência Aparente" -#define D_POWERUSAGE_REACTIVE "Potência Reativa" -#define D_PRESSURE "Pressão" -#define D_PRESSUREATSEALEVEL "Pressão ao nível do Mar" -#define D_PROGRAM_FLASH_SIZE "Tamanho do Programa na Flash" -#define D_PROGRAM_SIZE "Tamanho do Programa" -#define D_PROJECT "Projeto" -#define D_RAIN "Chuva" -#define D_RECEIVED "Recebido" -#define D_RESTART "Reiniciar" -#define D_RESTARTING "A reiniciar" -#define D_RESTART_REASON "Razão do reinicio" -#define D_RESTORE "Restauro" -#define D_RETAINED "Manter" -#define D_RULE "Regra" -#define D_SAVE "Guardar" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Início" -#define D_STD_TIME "STD" -#define D_STOP "Parar" -#define D_SUBNET_MASK "Mascara sub rede" -#define D_SUBSCRIBE_TO "Subscrever" -#define D_UNSUBSCRIBE_FROM "Cancelar subscrição de" -#define D_SUCCESSFUL "Successo" -#define D_SUNRISE "Nascer do Sol" -#define D_SUNSET "Pôr do Sol" -#define D_TEMPERATURE "Temperatura" -#define D_TO "para" -#define D_TOGGLE "Pressionar" -#define D_TOPIC "Tópico" -#define D_TOTAL_USAGE "Uso total" -#define D_TRANSMIT "Transmitir" -#define D_TRUE "Verdadeiro" -#define D_TVOC "TVOC" -#define D_UPGRADE "Atualizar" -#define D_UPLOAD "Enviar" -#define D_UPTIME "Tempo de Atividade" -#define D_USER "Utilizador" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Indíce UV" -#define D_UV_INDEX_1 "Baixo" -#define D_UV_INDEX_2 "Médio" -#define D_UV_INDEX_3 "Elevado" -#define D_UV_INDEX_4 "Perigoso" -#define D_UV_INDEX_5 "QueimaduraL1/2" -#define D_UV_INDEX_6 "QueimaduraL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "Nível UV" -#define D_UV_POWER "Poder UV" -#define D_VERSION "Versão" -#define D_VOLTAGE "Voltagem" -#define D_WEIGHT "Peso" -#define D_WARMLIGHT "Luz Quente" -#define D_WEB_SERVER "Servidor WEB" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "AVISO esta versão não supporta configurações persistentes" -#define D_LEVEL_10 "nível 1-0" -#define D_LEVEL_01 "nível 0-1" -#define D_SERIAL_LOGGING_DISABLED "Registro de porta série desabilitado" -#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" - -#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" -#define D_RECEIVED_TOPIC "Topico Recebido" -#define D_DATA_SIZE "Tamanho de Dados" -#define D_ANALOG_INPUT "Entrada Analógica" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Loop Bloqueado" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALHOU com estado" -#define D_ACTIVE_FOR_3_MINUTES "ativo por 3 minutos" -#define D_FAILED_TO_START "Falha ao iníciar" -#define D_PATCH_ISSUE_2186 "Questão 2186" -#define D_CONNECTING_TO_AP "Ligando ao AP" -#define D_IN_MODE "em modo" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "A ligação falhou porque nenhum endereço IP foi recebido" -#define D_CONNECT_FAILED_AP_NOT_REACHED "A ligação falhou porque o AP não pode ser alcançado" -#define D_CONNECT_FAILED_WRONG_PASSWORD "A ligação falhou porque a palavra chave está incorreta" -#define D_CONNECT_FAILED_AP_TIMEOUT "A ligação falhou porque o tempo excedeu" -#define D_ATTEMPTING_CONNECTION "A ligar..." -#define D_CHECKING_CONNECTION "A verificar ligação..." -#define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" -#define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" -#define D_FOUND_AT "encontrado em" -#define D_SYSLOG_HOST_NOT_FOUND "Anfitrião Syslog não encontrado" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Guardado na flash em" -#define D_LOADED_FROM_FLASH_AT "Lido da flash em" -#define D_USE_DEFAULTS "Usar predefinições" -#define D_ERASED_SECTOR "Apagado setor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Para utilizar o Tasmota, por favor ative o JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
Por favor atualize" -#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" -#define D_WITH_IP_ADDRESS "com o endereço IP" -#define D_WEBSERVER_STOPPED "Servitor WEB parou" -#define D_FILE_NOT_FOUND "Ficheiro não encontrado" -#define D_REDIRECTED "Redirecionado para o portal ativo" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager configura o Ponto de Acesso e mantem a Estação" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager configura o Ponto de Acesso" -#define D_TRYING_TO_CONNECT "A tentar ligar o dispositivo à rede" - -#define D_RESTART_IN "Reinicia em" -#define D_SECONDS "segundos" -#define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" -#define D_BUTTON_TOGGLE "Alternar" -#define D_CONFIGURATION "Configuração" -#define D_INFORMATION "Informação" -#define D_FIRMWARE_UPGRADE "Atualização de Firmware" -#define D_CONSOLE "Consola" -#define D_CONFIRM_RESTART "Confirmar o reinício" - -#define D_CONFIGURE_MODULE "Configurar Módulo" -#define D_CONFIGURE_WIFI "Configurar WiFi" -#define D_CONFIGURE_MQTT "Configurar MQTT" -#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" -#define D_CONFIGURE_LOGGING "Configurar registro" -#define D_CONFIGURE_OTHER "Configurar outras opções" -#define D_CONFIRM_RESET_CONFIGURATION "Confirme o reinício da configuração" -#define D_RESET_CONFIGURATION "Apagar configuração" -#define D_BACKUP_CONFIGURATION "Guardar configuração" -#define D_RESTORE_CONFIGURATION "Repor configuração" -#define D_MAIN_MENU "Menu Principal" - -#define D_MODULE_PARAMETERS "Parametros do Módulo" -#define D_MODULE_TYPE "Tipo de Módulo" -#define D_PULLUP_ENABLE "Sem pull-up de Botão/Interruptor" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Entrada de porta série" -#define D_SERIAL_OUT "Saída de porta série" - -#define D_WIFI_PARAMETERS "Parametros Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Procurar redes Wifi" -#define D_SCAN_DONE "Pesquisa terminada" -#define D_NO_NETWORKS_FOUND "Sem redes encontradas" -#define D_REFRESH_TO_SCAN_AGAIN "Atualize para realizar nova pesquisa" -#define D_DUPLICATE_ACCESSPOINT "Duplicar ponto de Acesso" -#define D_SKIPPING_LOW_QUALITY "Ignorado devido a baixa qualidade do sinal" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "SSId do AP1" -#define D_AP1_PASSWORD "Palavra Chave do AP1" -#define D_AP2_SSID "SSId do AP2" -#define D_AP2_PASSWORD "Palavra Chave do AP2" - -#define D_MQTT_PARAMETERS "Parametros MQTT" -#define D_CLIENT "Cliente" -#define D_FULL_TOPIC "Tópico completo" - -#define D_LOGGING_PARAMETERS "Parametros para registro" -#define D_SERIAL_LOG_LEVEL "Nível de registro na porta série" -#define D_MQTT_LOG_LEVEL "Nível de registro MQTT" -#define D_WEB_LOG_LEVEL "Nível de registro WEB" -#define D_SYS_LOG_LEVEL "Nível de registro do Syslog" -#define D_MORE_DEBUG "Depurar mais" -#define D_SYSLOG_HOST "Anfitrião Syslog" -#define D_SYSLOG_PORT "Porta Syslog" -#define D_TELEMETRY_PERIOD "Período de Telemetria" - -#define D_OTHER_PARAMETERS "Outros parametros" -#define D_TEMPLATE "Modelo" -#define D_ACTIVATE "Ativar" -#define D_WEB_ADMIN_PASSWORD "Palavra Chave do Admin WEB" -#define D_MQTT_ENABLE "MQTT habilitado" -#define D_FRIENDLY_NAME "Nome amigável" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "dispositivo único" -#define D_MULTI_DEVICE "dispositivo múltiplo" - -#define D_CONFIGURE_TEMPLATE "Configurar Modelo" -#define D_TEMPLATE_PARAMETERS "Parametros do Modelo" -#define D_TEMPLATE_NAME "Nome do Modelo" -#define D_BASE_TYPE "Baseado em" -#define D_TEMPLATE_FLAGS "Opções" - -#define D_SAVE_CONFIGURATION "Guardar configuração" -#define D_CONFIGURATION_SAVED "Configuração guardada" -#define D_CONFIGURATION_RESET "Reinicializar a configuração" - -#define D_PROGRAM_VERSION "Versão do Programa" -#define D_BUILD_DATE_AND_TIME "Data e Hora de criação" -#define D_CORE_AND_SDK_VERSION "Versão Core/SDK" -#define D_FLASH_WRITE_COUNT "Contagem de gravação da flash" -#define D_MAC_ADDRESS "Endereço MAC" -#define D_MQTT_HOST "Servidor MQTT" -#define D_MQTT_PORT "Porta MQTT" -#define D_MQTT_CLIENT "Cliente MQTT" -#define D_MQTT_USER "Utilizador MQTT" -#define D_MQTT_TOPIC "Tópico MQTT" -#define D_MQTT_GROUP_TOPIC "Tópico MQTT de Grupo" -#define D_MQTT_FULL_TOPIC "Tópico MQTT Completo" -#define D_MDNS_DISCOVERY "Descobrir mDNS" -#define D_MDNS_ADVERTISE "Anunciar mDNS" -#define D_ESP_CHIP_ID "ID do chip ESP" -#define D_FLASH_CHIP_ID "ID do chip da Flash" -#define D_FLASH_CHIP_SIZE "Tamanho da Flash" -#define D_FREE_PROGRAM_SPACE "Espaço de Programa Livre" - -#define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" -#define D_OTA_URL "Url OTA" -#define D_START_UPGRADE "Iniciar atualização" -#define D_UPGRADE_BY_FILE_UPLOAD "Atualizar por envio de ficheiro" -#define D_UPLOAD_STARTED "Envio Iniciado" -#define D_UPGRADE_STARTED "Atualização Iniciada" -#define D_UPLOAD_DONE "Atualização Finalizada" -#define D_UPLOAD_ERR_1 "Nenhum ficheiro selecionado" -#define D_UPLOAD_ERR_2 "Não existe espaço disponível" -#define D_UPLOAD_ERR_3 "O Byte mágico não é 0xE9" -#define D_UPLOAD_ERR_4 "O tamanho do programa e maior do que o tamanho real da flash" -#define D_UPLOAD_ERR_5 "Comparação incorreta do buffer de upload" -#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar registro 3" -#define D_UPLOAD_ERR_7 "Envio cancelado" -#define D_UPLOAD_ERR_8 "Ficheiro inválido" -#define D_UPLOAD_ERR_9 "Ficheiro demasiado grande" -#define D_UPLOAD_ERR_10 "Falha ao iniciar o chip de RF" -#define D_UPLOAD_ERR_11 "Falha ao apagar o chip de RF" -#define D_UPLOAD_ERR_12 "Falha ao escrever no chip de RF" -#define D_UPLOAD_ERR_13 "Falha ao descodificar o firmware RF" -#define D_UPLOAD_ERROR_CODE "Código de erro do envio" - -#define D_ENTER_COMMAND "Inserir comando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 se resposta esperada" -#define D_NEED_USER_AND_PASSWORD "Necessário user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifique a impressão digital TLS..." -#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" -#define D_RETRY_IN "Nova tentativa em" -#define D_VERIFIED "Verificado usando impressão digital" -#define D_INSECURE "Ligação insegura devido à impressão digital inválida" -#define D_CONNECT_FAILED_TO "A ligação falhou ao" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast desabilitado" -#define D_MULTICAST_REJOINED "Multicast (re)ingressado" -#define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" -#define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo evento básico" -#define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" -#define D_WEMO_META_SERVICE "WeMo serviço meta" -#define D_WEMO_SETUP "WeMo configuração" -#define D_RESPONSE_SENT "Resposta enviada" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Configuração do Hue" -#define D_HUE_API_NOT_IMPLEMENTED "API Hue nao implementada" -#define D_HUE_API "API Hue" -#define D_HUE_POST_ARGS "Argumentos de POST HUE" -#define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Parametros Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Chave idx" -#define D_DOMOTICZ_SWITCH_IDX "Interruptor idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Potência,Energia" - #define D_DOMOTICZ_ILLUMINANCE "Luminâcia" - #define D_DOMOTICZ_COUNT "Contagem/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltagem/PM2.5" - #define D_DOMOTICZ_CURRENT "Corrente/PM10" - #define D_DOMOTICZ_AIRQUALITY "Qualidade do Ar" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Temporizador de atualização" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configurar temporizador" -#define D_TIMER_PARAMETERS "Parâmetros do temporizador" -#define D_TIMER_ENABLE "Habilitar Temporizadores" -#define D_TIMER_ARM "Armar" -#define D_TIMER_TIME "Tempo" -#define D_TIMER_DAYS "Dias" -#define D_TIMER_REPEAT "Repetir" -#define D_TIMER_OUTPUT "Aaída" -#define D_TIMER_ACTION "Açao" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configurar KNX" -#define D_KNX_PARAMETERS "Parâmetros KNX" -#define D_KNX_GENERAL_CONFIG "Geral" -#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve ser exclusivo na rede KNX )" -#define D_KNX_ENABLE "Habilitar KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dados para enviar para Endereços de Grupo" -#define D_ADD "Adicionar" -#define D_DELETE "Remover" -#define D_REPLY "Responder" -#define D_KNX_GROUP_ADDRESS_TO_READ "Endereços de Grupo de onde receber dados" -#define D_RECEIVED_FROM "Recebido de" -#define D_KNX_COMMAND_WRITE "Escrever" -#define D_KNX_COMMAND_READ "Ler" -#define D_KNX_COMMAND_OTHER "Outro" -#define D_SENT_TO "enviar para" -#define D_KNX_WARNING "O Endereço de Grupo ( 0 / 0 / 0 ) está reservado e não pode ser usado." -#define D_KNX_ENHANCEMENT "Melhoria de Comunicação" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Consumo energético de hoje" -#define D_ENERGY_YESTERDAY "Consumo energético de ontem" -#define D_ENERGY_TOTAL "Consumo energético total" - -// xdrv_27_shutter.ino -#define D_OPEN "Abrir" -#define D_CLOSE "Fechar" -#define D_DOMOTICZ_SHUTTER "Estore" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configurar PCF8574" -#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" -#define D_INVERT_PORTS "Inverter Portas" -#define D_DEVICE "Dispositivo" -#define D_DEVICE_INPUT "Entrada" -#define D_DEVICE_OUTPUT "Saída" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor ocupado" -#define D_SENSOR_CRC_ERROR "Erro no CRC do sensor" -#define D_SENSORS_FOUND "Sensores encontrados" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" -#define D_START_SIGNAL_LOW "Sinal de início baixo" -#define D_START_SIGNAL_HIGH "Sinal de início elevado" -#define D_PULSE "pulso" -#define D_CHECKSUM_FAILURE "Falha na soma de verificação" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" -#define D_SHT1X_FOUND "SHT1X encontrado" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partículas" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remover peso" -#define D_HX_CAL_REFERENCE "Carregar peso de referência" -#define D_HX_CAL_DONE "Calibrado" -#define D_HX_CAL_FAIL "Falha na calibração" -#define D_RESET_HX711 "Reiniciar balança" -#define D_CONFIGURE_HX711 "Configurar balança" -#define D_HX711_PARAMETERS "Parâmetros da balança" -#define D_ITEM_WEIGHT "Peso do item" -#define D_REFERENCE_WEIGHT "Peso de referência" -#define D_CALIBRATE "Calibrar" -#define D_CALIBRATION "Calibração" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Direção do vento" -#define D_TX20_WIND_SPEED "Velocidade do vento" -#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" -#define D_TX20_WIND_SPEED_MAX "Velocidade máxima do vento" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "O" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Nenhum" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Interruptor" // Suffix "1" -#define D_SENSOR_BUTTON "Botão" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Contador" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Luz fundo" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "Sensor RF" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotativo" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "setores" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Ângulo de fase" -#define D_IMPORT_ACTIVE "Ativo importado" -#define D_EXPORT_ACTIVE "Ativo exportado" -#define D_IMPORT_REACTIVE "Reativo importado" -#define D_EXPORT_REACTIVE "Reativo exportado" -#define D_TOTAL_REACTIVE "Reactivo total" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "Voltagem PV1" -#define D_PV1_CURRENT "Corrente PV1" -#define D_PV1_POWER "Potência PV1" -#define D_PV2_VOLTAGE "Voltagem PV2" -#define D_PV2_CURRENT "Corrente PV2" -#define D_PV2_POWER "Potência PV2" -#define D_SOLAR_POWER "Potência Solar" -#define D_INVERTER_POWER "Potência do Inversor" -#define D_STATUS "Estado" -#define D_WAITING "Esperando" -#define D_CHECKING "Verificando" -#define D_WORKING "Trabalhando" -#define D_FAILURE "Falha" -#define D_SOLAX_ERROR_0 "Nenhum código de erro" -#define D_SOLAX_ERROR_1 "Falha devido a perda de rede" -#define D_SOLAX_ERROR_2 "Falha devido a perda de tensão" -#define D_SOLAX_ERROR_3 "Falha devido a perda de frequência" -#define D_SOLAX_ERROR_4 "Falha de tensão de Pv" -#define D_SOLAX_ERROR_5 "Falha de isolamento" -#define D_SOLAX_ERROR_6 "Falha de temperatura excessiva" -#define D_SOLAX_ERROR_7 "Falha no ventilador" -#define D_SOLAX_ERROR_8 "Outra falha no dispositivo" - -#endif // _LANGUAGE_PT_PT_H_ +/* + pt-PT.h - localization for Portuguese - Portugal for Tasmota + + Copyright (C) 2019 Paulo Paiva + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_PT_PT_H_ +#define _LANGUAGE_PT_PT_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v7.0.0.1 +\*********************************************************************/ + +#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 2070 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "pt" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DomSegTerQuaQuiSexSab" +#define D_MONTH3LIST "JanFevMarAbrMaiJunJulAgoSepOutNovDez" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Qualidade do Ar" +#define D_AP "AP" // Ponto de Acesso +#define D_AS "como" +#define D_AUTO "AUTO" +#define D_BLINK "Piscar" +#define D_BLINKOFF "Piscar Desligado" +#define D_BOOT_COUNT "Contagem de Inicialização" +#define D_BRIGHTLIGHT "Brilho" +#define D_BSSID "BSSId" +#define D_BUTTON "Botão" +#define D_BY "por" // Write by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "Dioxido de Carbono" +#define D_CODE "Código" // Button code +#define D_COLDLIGHT "Luz Fria" +#define D_COMMAND "Comando" +#define D_CONNECTED "Ligado" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Contagem" +#define D_COUNTER "Contador" +#define D_CURRENT "Corrente" // As in Voltage and Current +#define D_DATA "Dados" +#define D_DARKLIGHT "Luz Escura" +#define D_DEBUG "Depurar" +#define D_DISABLED "Disabilitado" +#define D_DISTANCE "Distância" +#define D_DNS_SERVER "Servidor DNS" +#define D_DONE "Concluído" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulação" +#define D_ENABLED "Habilitado" +#define D_ERASE "Apagar" +#define D_ERROR "Erro" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Falha" +#define D_FALLBACK "Retornar" +#define D_FALLBACK_TOPIC "Tópico para retornar" +#define D_FALSE "Falso" +#define D_FILE "Ficheiro" +#define D_FLOW_RATE "Taxa de Fluxo" +#define D_FREE_MEMORY "Memoria Livre" +#define D_FREQUENCY "Frequência" +#define D_GAS "Gás" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupo" +#define D_HOST "Anfitrião" +#define D_HOSTNAME "Nome Anfitrião" +#define D_HUMIDITY "Humidade" +#define D_ILLUMINANCE "Luminâcia" +#define D_IMMEDIATE "Immediato" // Button immediate +#define D_INDEX "Indíce" +#define D_INFO "Info" +#define D_INFRARED "Infravermelho" +#define D_INITIALIZED "Inicializado" +#define D_IP_ADDRESS "Endereço IP" +#define D_LIGHT "Luz" +#define D_LWT "LWT" +#define D_MODULE "Módulo" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-pressão" +#define D_NOISE "Ruído" +#define D_NONE "Nenhum" +#define D_OFF "Off" +#define D_OFFLINE "Desconetado" +#define D_OK "Ok" +#define D_ON "On" +#define D_ONLINE "Conetado" +#define D_PASSWORD "Palavra Chave" +#define D_PORT "Porta" +#define D_POWER_FACTOR "Factor de Potência" +#define D_POWERUSAGE "Potência" +#define D_POWERUSAGE_ACTIVE "Potência Ativa" +#define D_POWERUSAGE_APPARENT "Potência Aparente" +#define D_POWERUSAGE_REACTIVE "Potência Reativa" +#define D_PRESSURE "Pressão" +#define D_PRESSUREATSEALEVEL "Pressão ao nível do Mar" +#define D_PROGRAM_FLASH_SIZE "Tamanho do Programa na Flash" +#define D_PROGRAM_SIZE "Tamanho do Programa" +#define D_PROJECT "Projeto" +#define D_RAIN "Chuva" +#define D_RECEIVED "Recebido" +#define D_RESTART "Reiniciar" +#define D_RESTARTING "A reiniciar" +#define D_RESTART_REASON "Razão do reinicio" +#define D_RESTORE "Restauro" +#define D_RETAINED "Manter" +#define D_RULE "Regra" +#define D_SAVE "Guardar" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Início" +#define D_STD_TIME "STD" +#define D_STOP "Parar" +#define D_SUBNET_MASK "Mascara sub rede" +#define D_SUBSCRIBE_TO "Subscrever" +#define D_UNSUBSCRIBE_FROM "Cancelar subscrição de" +#define D_SUCCESSFUL "Successo" +#define D_SUNRISE "Nascer do Sol" +#define D_SUNSET "Pôr do Sol" +#define D_TEMPERATURE "Temperatura" +#define D_TO "para" +#define D_TOGGLE "Pressionar" +#define D_TOPIC "Tópico" +#define D_TOTAL_USAGE "Uso total" +#define D_TRANSMIT "Transmitir" +#define D_TRUE "Verdadeiro" +#define D_TVOC "TVOC" +#define D_UPGRADE "Atualizar" +#define D_UPLOAD "Enviar" +#define D_UPTIME "Tempo de Atividade" +#define D_USER "Utilizador" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Indíce UV" +#define D_UV_INDEX_1 "Baixo" +#define D_UV_INDEX_2 "Médio" +#define D_UV_INDEX_3 "Elevado" +#define D_UV_INDEX_4 "Perigoso" +#define D_UV_INDEX_5 "QueimaduraL1/2" +#define D_UV_INDEX_6 "QueimaduraL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "Nível UV" +#define D_UV_POWER "Poder UV" +#define D_VERSION "Versão" +#define D_VOLTAGE "Voltagem" +#define D_WEIGHT "Peso" +#define D_WARMLIGHT "Luz Quente" +#define D_WEB_SERVER "Servidor WEB" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "AVISO esta versão não supporta configurações persistentes" +#define D_LEVEL_10 "nível 1-0" +#define D_LEVEL_01 "nível 0-1" +#define D_SERIAL_LOGGING_DISABLED "Registro de porta série desabilitado" +#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" + +#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" +#define D_RECEIVED_TOPIC "Topico Recebido" +#define D_DATA_SIZE "Tamanho de Dados" +#define D_ANALOG_INPUT "Entrada Analógica" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Loop Bloqueado" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FALHOU com estado" +#define D_ACTIVE_FOR_3_MINUTES "ativo por 3 minutos" +#define D_FAILED_TO_START "Falha ao iníciar" +#define D_PATCH_ISSUE_2186 "Questão 2186" +#define D_CONNECTING_TO_AP "Ligando ao AP" +#define D_IN_MODE "em modo" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "A ligação falhou porque nenhum endereço IP foi recebido" +#define D_CONNECT_FAILED_AP_NOT_REACHED "A ligação falhou porque o AP não pode ser alcançado" +#define D_CONNECT_FAILED_WRONG_PASSWORD "A ligação falhou porque a palavra chave está incorreta" +#define D_CONNECT_FAILED_AP_TIMEOUT "A ligação falhou porque o tempo excedeu" +#define D_ATTEMPTING_CONNECTION "A ligar..." +#define D_CHECKING_CONNECTION "A verificar ligação..." +#define D_QUERY_DONE "Consulta finalizada. Serviço MQTT não encontrado" +#define D_MQTT_SERVICE_FOUND "Serviço MQTT encontrado em" +#define D_FOUND_AT "encontrado em" +#define D_SYSLOG_HOST_NOT_FOUND "Anfitrião Syslog não encontrado" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Guardado na flash em" +#define D_LOADED_FROM_FLASH_AT "Lido da flash em" +#define D_USE_DEFAULTS "Usar predefinições" +#define D_ERASED_SECTOR "Apagado setor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Para utilizar o Tasmota, por favor ative o JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO
Por favor atualize" +#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em" +#define D_WITH_IP_ADDRESS "com o endereço IP" +#define D_WEBSERVER_STOPPED "Servitor WEB parou" +#define D_FILE_NOT_FOUND "Ficheiro não encontrado" +#define D_REDIRECTED "Redirecionado para o portal ativo" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager configura o Ponto de Acesso e mantem a Estação" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager configura o Ponto de Acesso" +#define D_TRYING_TO_CONNECT "A tentar ligar o dispositivo à rede" + +#define D_RESTART_IN "Reinicia em" +#define D_SECONDS "segundos" +#define D_DEVICE_WILL_RESTART "O dispositivo irá reiniciar dentro de alguns segundos" +#define D_BUTTON_TOGGLE "Alternar" +#define D_CONFIGURATION "Configuração" +#define D_INFORMATION "Informação" +#define D_FIRMWARE_UPGRADE "Atualização de Firmware" +#define D_CONSOLE "Consola" +#define D_CONFIRM_RESTART "Confirmar o reinício" + +#define D_CONFIGURE_MODULE "Configurar Módulo" +#define D_CONFIGURE_WIFI "Configurar WiFi" +#define D_CONFIGURE_MQTT "Configurar MQTT" +#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz" +#define D_CONFIGURE_LOGGING "Configurar registro" +#define D_CONFIGURE_OTHER "Configurar outras opções" +#define D_CONFIRM_RESET_CONFIGURATION "Confirme o reinício da configuração" +#define D_RESET_CONFIGURATION "Apagar configuração" +#define D_BACKUP_CONFIGURATION "Guardar configuração" +#define D_RESTORE_CONFIGURATION "Repor configuração" +#define D_MAIN_MENU "Menu Principal" + +#define D_MODULE_PARAMETERS "Parametros do Módulo" +#define D_MODULE_TYPE "Tipo de Módulo" +#define D_PULLUP_ENABLE "Sem pull-up de Botão/Interruptor" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Entrada de porta série" +#define D_SERIAL_OUT "Saída de porta série" + +#define D_WIFI_PARAMETERS "Parametros Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Procurar redes Wifi" +#define D_SCAN_DONE "Pesquisa terminada" +#define D_NO_NETWORKS_FOUND "Sem redes encontradas" +#define D_REFRESH_TO_SCAN_AGAIN "Atualize para realizar nova pesquisa" +#define D_DUPLICATE_ACCESSPOINT "Duplicar ponto de Acesso" +#define D_SKIPPING_LOW_QUALITY "Ignorado devido a baixa qualidade do sinal" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "SSId do AP1" +#define D_AP1_PASSWORD "Palavra Chave do AP1" +#define D_AP2_SSID "SSId do AP2" +#define D_AP2_PASSWORD "Palavra Chave do AP2" + +#define D_MQTT_PARAMETERS "Parametros MQTT" +#define D_CLIENT "Cliente" +#define D_FULL_TOPIC "Tópico completo" + +#define D_LOGGING_PARAMETERS "Parametros para registro" +#define D_SERIAL_LOG_LEVEL "Nível de registro na porta série" +#define D_MQTT_LOG_LEVEL "Nível de registro MQTT" +#define D_WEB_LOG_LEVEL "Nível de registro WEB" +#define D_SYS_LOG_LEVEL "Nível de registro do Syslog" +#define D_MORE_DEBUG "Depurar mais" +#define D_SYSLOG_HOST "Anfitrião Syslog" +#define D_SYSLOG_PORT "Porta Syslog" +#define D_TELEMETRY_PERIOD "Período de Telemetria" + +#define D_OTHER_PARAMETERS "Outros parametros" +#define D_TEMPLATE "Modelo" +#define D_ACTIVATE "Ativar" +#define D_WEB_ADMIN_PASSWORD "Palavra Chave do Admin WEB" +#define D_MQTT_ENABLE "MQTT habilitado" +#define D_FRIENDLY_NAME "Nome amigável" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "dispositivo único" +#define D_MULTI_DEVICE "dispositivo múltiplo" + +#define D_CONFIGURE_TEMPLATE "Configurar Modelo" +#define D_TEMPLATE_PARAMETERS "Parametros do Modelo" +#define D_TEMPLATE_NAME "Nome do Modelo" +#define D_BASE_TYPE "Baseado em" +#define D_TEMPLATE_FLAGS "Opções" + +#define D_SAVE_CONFIGURATION "Guardar configuração" +#define D_CONFIGURATION_SAVED "Configuração guardada" +#define D_CONFIGURATION_RESET "Reinicializar a configuração" + +#define D_PROGRAM_VERSION "Versão do Programa" +#define D_BUILD_DATE_AND_TIME "Data e Hora de criação" +#define D_CORE_AND_SDK_VERSION "Versão Core/SDK" +#define D_FLASH_WRITE_COUNT "Contagem de gravação da flash" +#define D_MAC_ADDRESS "Endereço MAC" +#define D_MQTT_HOST "Servidor MQTT" +#define D_MQTT_PORT "Porta MQTT" +#define D_MQTT_CLIENT "Cliente MQTT" +#define D_MQTT_USER "Utilizador MQTT" +#define D_MQTT_TOPIC "Tópico MQTT" +#define D_MQTT_GROUP_TOPIC "Tópico MQTT de Grupo" +#define D_MQTT_FULL_TOPIC "Tópico MQTT Completo" +#define D_MDNS_DISCOVERY "Descobrir mDNS" +#define D_MDNS_ADVERTISE "Anunciar mDNS" +#define D_ESP_CHIP_ID "ID do chip ESP" +#define D_FLASH_CHIP_ID "ID do chip da Flash" +#define D_FLASH_CHIP_SIZE "Tamanho da Flash" +#define D_FREE_PROGRAM_SPACE "Espaço de Programa Livre" + +#define D_UPGRADE_BY_WEBSERVER "Atualizar pelo servidor WEB" +#define D_OTA_URL "Url OTA" +#define D_START_UPGRADE "Iniciar atualização" +#define D_UPGRADE_BY_FILE_UPLOAD "Atualizar por envio de ficheiro" +#define D_UPLOAD_STARTED "Envio Iniciado" +#define D_UPGRADE_STARTED "Atualização Iniciada" +#define D_UPLOAD_DONE "Atualização Finalizada" +#define D_UPLOAD_ERR_1 "Nenhum ficheiro selecionado" +#define D_UPLOAD_ERR_2 "Não existe espaço disponível" +#define D_UPLOAD_ERR_3 "O Byte mágico não é 0xE9" +#define D_UPLOAD_ERR_4 "O tamanho do programa e maior do que o tamanho real da flash" +#define D_UPLOAD_ERR_5 "Comparação incorreta do buffer de upload" +#define D_UPLOAD_ERR_6 "Falha no envio. Habilitar registro 3" +#define D_UPLOAD_ERR_7 "Envio cancelado" +#define D_UPLOAD_ERR_8 "Ficheiro inválido" +#define D_UPLOAD_ERR_9 "Ficheiro demasiado grande" +#define D_UPLOAD_ERR_10 "Falha ao iniciar o chip de RF" +#define D_UPLOAD_ERR_11 "Falha ao apagar o chip de RF" +#define D_UPLOAD_ERR_12 "Falha ao escrever no chip de RF" +#define D_UPLOAD_ERR_13 "Falha ao descodificar o firmware RF" +#define D_UPLOAD_ERROR_CODE "Código de erro do envio" + +#define D_ENTER_COMMAND "Inserir comando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Habilitar weblog 2 se resposta esperada" +#define D_NEED_USER_AND_PASSWORD "Necessário user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifique a impressão digital TLS..." +#define D_TLS_CONNECT_FAILED_TO "TLS não conseguiu ligar" +#define D_RETRY_IN "Nova tentativa em" +#define D_VERIFIED "Verificado usando impressão digital" +#define D_INSECURE "Ligação insegura devido à impressão digital inválida" +#define D_CONNECT_FAILED_TO "A ligação falhou ao" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast desabilitado" +#define D_MULTICAST_REJOINED "Multicast (re)ingressado" +#define D_MULTICAST_JOIN_FAILED "Multicast falha no reingresso" +#define D_FAILED_TO_SEND_RESPONSE "Falha no envio de reposta" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo evento básico" +#define D_WEMO_EVENT_SERVICE "WeMo evento de serviço" +#define D_WEMO_META_SERVICE "WeMo serviço meta" +#define D_WEMO_SETUP "WeMo configuração" +#define D_RESPONSE_SENT "Resposta enviada" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Configuração do Hue" +#define D_HUE_API_NOT_IMPLEMENTED "API Hue nao implementada" +#define D_HUE_API "API Hue" +#define D_HUE_POST_ARGS "Argumentos de POST HUE" +#define D_3_RESPONSE_PACKETS_SENT "3 pacotes de resposta enviados" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parametros Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Chave idx" +#define D_DOMOTICZ_SWITCH_IDX "Interruptor idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Potência,Energia" + #define D_DOMOTICZ_ILLUMINANCE "Luminâcia" + #define D_DOMOTICZ_COUNT "Contagem/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltagem/PM2.5" + #define D_DOMOTICZ_CURRENT "Corrente/PM10" + #define D_DOMOTICZ_AIRQUALITY "Qualidade do Ar" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Temporizador de atualização" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configurar temporizador" +#define D_TIMER_PARAMETERS "Parâmetros do temporizador" +#define D_TIMER_ENABLE "Habilitar Temporizadores" +#define D_TIMER_ARM "Armar" +#define D_TIMER_TIME "Tempo" +#define D_TIMER_DAYS "Dias" +#define D_TIMER_REPEAT "Repetir" +#define D_TIMER_OUTPUT "Aaída" +#define D_TIMER_ACTION "Açao" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configurar KNX" +#define D_KNX_PARAMETERS "Parâmetros KNX" +#define D_KNX_GENERAL_CONFIG "Geral" +#define D_KNX_PHYSICAL_ADDRESS "Endereço físico" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Deve ser exclusivo na rede KNX )" +#define D_KNX_ENABLE "Habilitar KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dados para enviar para Endereços de Grupo" +#define D_ADD "Adicionar" +#define D_DELETE "Remover" +#define D_REPLY "Responder" +#define D_KNX_GROUP_ADDRESS_TO_READ "Endereços de Grupo de onde receber dados" +#define D_RECEIVED_FROM "Recebido de" +#define D_KNX_COMMAND_WRITE "Escrever" +#define D_KNX_COMMAND_READ "Ler" +#define D_KNX_COMMAND_OTHER "Outro" +#define D_SENT_TO "enviar para" +#define D_KNX_WARNING "O Endereço de Grupo ( 0 / 0 / 0 ) está reservado e não pode ser usado." +#define D_KNX_ENHANCEMENT "Melhoria de Comunicação" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Consumo energético de hoje" +#define D_ENERGY_YESTERDAY "Consumo energético de ontem" +#define D_ENERGY_TOTAL "Consumo energético total" + +// xdrv_27_shutter.ino +#define D_OPEN "Abrir" +#define D_CLOSE "Fechar" +#define D_DOMOTICZ_SHUTTER "Estore" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configurar PCF8574" +#define D_PCF8574_PARAMETERS "Parâmetros PCF8574" +#define D_INVERT_PORTS "Inverter Portas" +#define D_DEVICE "Dispositivo" +#define D_DEVICE_INPUT "Entrada" +#define D_DEVICE_OUTPUT "Saída" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor ocupado" +#define D_SENSOR_CRC_ERROR "Erro no CRC do sensor" +#define D_SENSORS_FOUND "Sensores encontrados" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Fim do tempo de espera" +#define D_START_SIGNAL_LOW "Sinal de início baixo" +#define D_START_SIGNAL_HIGH "Sinal de início elevado" +#define D_PULSE "pulso" +#define D_CHECKSUM_FAILURE "Falha na soma de verificação" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor não aceitou o comando ACK" +#define D_SHT1X_FOUND "SHT1X encontrado" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partículas" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remover peso" +#define D_HX_CAL_REFERENCE "Carregar peso de referência" +#define D_HX_CAL_DONE "Calibrado" +#define D_HX_CAL_FAIL "Falha na calibração" +#define D_RESET_HX711 "Reiniciar balança" +#define D_CONFIGURE_HX711 "Configurar balança" +#define D_HX711_PARAMETERS "Parâmetros da balança" +#define D_ITEM_WEIGHT "Peso do item" +#define D_REFERENCE_WEIGHT "Peso de referência" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibração" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direção do vento" +#define D_TX20_WIND_SPEED "Velocidade do vento" +#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" +#define D_TX20_WIND_SPEED_MAX "Velocidade máxima do vento" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Nenhum" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Interruptor" // Suffix "1" +#define D_SENSOR_BUTTON "Botão" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Contador" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Luz fundo" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "Sensor RF" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotativo" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "setores" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Ângulo de fase" +#define D_IMPORT_ACTIVE "Ativo importado" +#define D_EXPORT_ACTIVE "Ativo exportado" +#define D_IMPORT_REACTIVE "Reativo importado" +#define D_EXPORT_REACTIVE "Reativo exportado" +#define D_TOTAL_REACTIVE "Reactivo total" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "Voltagem PV1" +#define D_PV1_CURRENT "Corrente PV1" +#define D_PV1_POWER "Potência PV1" +#define D_PV2_VOLTAGE "Voltagem PV2" +#define D_PV2_CURRENT "Corrente PV2" +#define D_PV2_POWER "Potência PV2" +#define D_SOLAR_POWER "Potência Solar" +#define D_INVERTER_POWER "Potência do Inversor" +#define D_STATUS "Estado" +#define D_WAITING "Esperando" +#define D_CHECKING "Verificando" +#define D_WORKING "Trabalhando" +#define D_FAILURE "Falha" +#define D_SOLAX_ERROR_0 "Nenhum código de erro" +#define D_SOLAX_ERROR_1 "Falha devido a perda de rede" +#define D_SOLAX_ERROR_2 "Falha devido a perda de tensão" +#define D_SOLAX_ERROR_3 "Falha devido a perda de frequência" +#define D_SOLAX_ERROR_4 "Falha de tensão de Pv" +#define D_SOLAX_ERROR_5 "Falha de isolamento" +#define D_SOLAX_ERROR_6 "Falha de temperatura excessiva" +#define D_SOLAX_ERROR_7 "Falha no ventilador" +#define D_SOLAX_ERROR_8 "Outra falha no dispositivo" + +#endif // _LANGUAGE_PT_PT_H_ diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index a603216a9..3bd788ede 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -1,703 +1,701 @@ -/* - ru-RU.h - localization for Russian - Rissia for Tasmota - - Copyright (C) 2019 Theo Arends / roman-vn - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_RU_RU_H_ -#define _LANGUAGE_RU_RU_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.12.0b -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1049 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "ru" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "ВскПонВтрСрдЧетПятСуб" -#define D_MONTH3LIST "ЯнвФевМарАпрМайИюнИюлАвгСенОктНояДек" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Качество воздуха" -#define D_AP "AP" // Access Point -#define D_AS "как" -#define D_AUTO "АВТО" -#define D_BLINK "Мигать" -#define D_BLINKOFF "Не Мигать" -#define D_BOOT_COUNT "Количество загрузок" -#define D_BRIGHTLIGHT "Яркость" -#define D_BSSID "BSSId" -#define D_BUTTON "Кнопка" -#define D_BY "by" // Written by me -#define D_BYTES "Байт" -#define D_CELSIUS "Цельсия" -#define D_CHANNEL "Channel" -#define D_CO2 "Углекислый газ" -#define D_CODE "код" // Button code -#define D_COLDLIGHT "Холодный" -#define D_COMMAND "Команда" -#define D_CONNECTED "Соединен" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Подсчет" -#define D_COUNTER "Счетчик" -#define D_CURRENT "Ток" // As in Voltage and Current -#define D_DATA "Данные" -#define D_DARKLIGHT "Темный" -#define D_DEBUG "Отладка" -#define D_DISABLED "Блокирован" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "DNS Сервер" -#define D_DONE "Выполнено" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Эмуляция" -#define D_ENABLED "Активно" -#define D_ERASE "Стирать" -#define D_ERROR "Ошибка" -#define D_FAHRENHEIT "Фаренгейт" -#define D_FAILED "Неудачно" -#define D_FALLBACK "Обратная связь" -#define D_FALLBACK_TOPIC "Топик обратной связи" -#define D_FALSE "Ложно" -#define D_FILE "Файл" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Свободная память" -#define D_FREQUENCY "Frequency" -#define D_GAS "Газ" -#define D_GATEWAY "Шлюз" -#define D_GROUP "Группа" -#define D_HOST "Хост" -#define D_HOSTNAME "Имя Хоста" -#define D_HUMIDITY "Влажность" -#define D_ILLUMINANCE "Освещенность" -#define D_IMMEDIATE "немедленно" // Button immediate -#define D_INDEX "Индекс" -#define D_INFO "Инфо" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "Инициализировано" -#define D_IP_ADDRESS "IP Адрес" -#define D_LIGHT "Свет" -#define D_LWT "LWT" -#define D_MODULE "Модуль" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "многократное нажатие" -#define D_NOISE "Шум" -#define D_NONE "Нет" -#define D_OFF "Выкл" -#define D_OFFLINE "Офф-лайн" -#define D_OK "Ок" -#define D_ON "Вкл" -#define D_ONLINE "Он-лайн" -#define D_PASSWORD "Пароль" -#define D_PORT "Порт" -#define D_POWER_FACTOR "Коэффициент Мощности" -#define D_POWERUSAGE "Мощность" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "Давление" -#define D_PRESSUREATSEALEVEL "Давление на уровне моря" -#define D_PROGRAM_FLASH_SIZE "Размер Flash для программ" -#define D_PROGRAM_SIZE "Размер программы " -#define D_PROJECT "Проект" -#define D_RAIN "Rain" -#define D_RECEIVED "Получено" -#define D_RESTART "Перезапуск" -#define D_RESTARTING "Перезапуск" -#define D_RESTART_REASON "Причина перезагрузки" -#define D_RESTORE "восстановление" -#define D_RETAINED "нераспред." -#define D_RULE "Rule" -#define D_SAVE "Сохранить" -#define D_SENSOR "Датчик" -#define D_SSID "SSId" -#define D_START "Старт" -#define D_STD_TIME "STD" -#define D_STOP "Стоп" -#define D_SUBNET_MASK "Маска Подсети" -#define D_SUBSCRIBE_TO "Подписаться на" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Успешно" -#define D_SUNRISE "Sunrise" -#define D_SUNSET "Sunset" -#define D_TEMPERATURE "Температура" -#define D_TO "до" -#define D_TOGGLE "Переключить" -#define D_TOPIC "Топик" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Передать" -#define D_TRUE "Истина" -#define D_TVOC "TVOC" -#define D_UPGRADE "обновление" -#define D_UPLOAD "Загрузить" -#define D_UPTIME "Uptime" -#define D_USER "Пользователь" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "УФ уровень" -#define D_UV_POWER "UV Power" -#define D_VERSION "Версия" -#define D_VOLTAGE "Напряжение" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "Тепло" -#define D_WEB_SERVER "Web сервер" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Эта версия не поддерживает персистентные настройки" -#define D_LEVEL_10 "уровень 1-0" -#define D_LEVEL_01 "уровень 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial logging отключен" -#define D_SYSLOG_LOGGING_REENABLED "Syslog logging включен" - -#define D_SET_BAUDRATE_TO "Установить скорость передачи (Baudrate)" -#define D_RECEIVED_TOPIC "Полученный Топик" -#define D_DATA_SIZE "Размер данных" -#define D_ANALOG_INPUT "Аналоговый вход" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Блокирующий цикл" -#define D_WPS_FAILED_WITH_STATUS "WPS конфигурация НЕУДАЧНА со статусом" -#define D_ACTIVE_FOR_3_MINUTES "активен в течение 3 минут" -#define D_FAILED_TO_START "не удалось запустить" -#define D_PATCH_ISSUE_2186 "Проблема с исправлением 2186" -#define D_CONNECTING_TO_AP "Подключение к AP" -#define D_IN_MODE "в режиме" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Ошибка подключения, IP-адрес не получен" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Ошибка соединения, AP не может быть достигнута" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Ошибка соединения, неверный пароль к AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Ошибка соединения с AP по тайм-ауту" -#define D_ATTEMPTING_CONNECTION "Попытка подключения..." -#define D_CHECKING_CONNECTION "Проверка соединения..." -#define D_QUERY_DONE "Запрос выполнен. Обнаружены службы MQTT" -#define D_MQTT_SERVICE_FOUND "MQTT сервис service найдено" -#define D_FOUND_AT "найдено в" -#define D_SYSLOG_HOST_NOT_FOUND "System лог хост не найден" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Сохранено во флэш-память" -#define D_LOADED_FROM_FLASH_AT "Загружено из флэш-памяти" -#define D_USE_DEFAULTS "Использовать значение по умолчанию" -#define D_ERASED_SECTOR "Стереть сектор" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" -#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен" -#define D_WITH_IP_ADDRESS "с IP-адресом" -#define D_WEBSERVER_STOPPED "Веб-сервер остановлен" -#define D_FILE_NOT_FOUND "Файл не найден" -#define D_REDIRECTED "Перенаправлено на адаптивный портал" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер устанавливает Точку Доступа и сохраняет станцию" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер установил Точку Доступа" -#define D_TRYING_TO_CONNECT "Попытка подключения устройства к сети" - -#define D_RESTART_IN "Перезапуск" -#define D_SECONDS "секунд" -#define D_DEVICE_WILL_RESTART "Устройство будет перезапущено через несколько секунд" -#define D_BUTTON_TOGGLE "Переключить" -#define D_CONFIGURATION "Конфигурация" -#define D_INFORMATION "Информация" -#define D_FIRMWARE_UPGRADE "Обновление прошивки" -#define D_CONSOLE "Консоль" -#define D_CONFIRM_RESTART "Подтвердить перезагрузку" - -#define D_CONFIGURE_MODULE "Конфигурация Модуля" -#define D_CONFIGURE_WIFI "Конфигурация WiFi" -#define D_CONFIGURE_MQTT "Конфигурация MQTT" -#define D_CONFIGURE_DOMOTICZ "Конфигурация Domoticz" -#define D_CONFIGURE_LOGGING "Конфигурация Logging" -#define D_CONFIGURE_OTHER "Конфигурация прочее" -#define D_CONFIRM_RESET_CONFIGURATION "Подтвердить Сброс Конфигурации" -#define D_RESET_CONFIGURATION "Сброс Конфигурации" -#define D_BACKUP_CONFIGURATION "Резервное копирование Конфигурации" -#define D_RESTORE_CONFIGURATION "Восстановление Конфигурации" -#define D_MAIN_MENU "Главное Меню" - -#define D_MODULE_PARAMETERS "Параметры модуля" -#define D_MODULE_TYPE "Тип модуля" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial вход" -#define D_SERIAL_OUT "Serial выход" - -#define D_WIFI_PARAMETERS "Параметры Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Сканирование беспроводных сетей Wifi" -#define D_SCAN_DONE "Сканирование завершено" -#define D_NO_NETWORKS_FOUND "Не найдено сетей" -#define D_REFRESH_TO_SCAN_AGAIN "Обновить для повторного сканирования" -#define D_DUPLICATE_ACCESSPOINT "Дублировать Точку Доступа (AP)" -#define D_SKIPPING_LOW_QUALITY "Пропущено из-за низкого качества" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 Пароль" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Пароль" - -#define D_MQTT_PARAMETERS "Параметры MQTT" -#define D_CLIENT "Клиент" -#define D_FULL_TOPIC "Полный Топик" - -#define D_LOGGING_PARAMETERS "Параметры Logging" -#define D_SERIAL_LOG_LEVEL "Serial лог уровень" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web лог уровень" -#define D_SYS_LOG_LEVEL "System лог уровень" -#define D_MORE_DEBUG "Дополнительная информация для отладки" -#define D_SYSLOG_HOST "System лог хост" -#define D_SYSLOG_PORT "System лог порт" -#define D_TELEMETRY_PERIOD "Период телеметрии" - -#define D_OTHER_PARAMETERS "Параметры Прочие" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Пароль Web администратора" -#define D_MQTT_ENABLE "MQTT активен" -#define D_FRIENDLY_NAME "Дружественное Имя" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "одиночное" -#define D_MULTI_DEVICE "мульти" - -#define D_CONFIGURE_TEMPLATE "Конфигурация Template" -#define D_TEMPLATE_PARAMETERS "Параметры Template" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Сохранить конфигурацию" -#define D_CONFIGURATION_SAVED "Конфигурация сохранена " -#define D_CONFIGURATION_RESET "Конфигурация сброшена" - -#define D_PROGRAM_VERSION "Версия программы" -#define D_BUILD_DATE_AND_TIME "Дата & Время сборки" -#define D_CORE_AND_SDK_VERSION "Версия Core/SDK" -#define D_FLASH_WRITE_COUNT "Кол-во записей Flash" -#define D_MAC_ADDRESS "MAC Адрес" -#define D_MQTT_HOST "MQTT Хост" -#define D_MQTT_PORT "MQTT Порт" -#define D_MQTT_CLIENT "MQTT Клиент ID" -#define D_MQTT_USER "MQTT Пользователь" -#define D_MQTT_TOPIC "MQTT Топик" -#define D_MQTT_GROUP_TOPIC "MQTT Топик группы" -#define D_MQTT_FULL_TOPIC "MQTT Топик полный" -#define D_MDNS_DISCOVERY "mDNS Обнаружение" -#define D_MDNS_ADVERTISE "mDNS Транcляция" -#define D_ESP_CHIP_ID "ID чипа ESP" -#define D_FLASH_CHIP_ID "ID чипа Flash памяти" -#define D_FLASH_CHIP_SIZE "Размер Flash памяти" -#define D_FREE_PROGRAM_SPACE "Свободное пространство программ" - -#define D_UPGRADE_BY_WEBSERVER "Обновление через Веб-сервер" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Начать обновление" -#define D_UPGRADE_BY_FILE_UPLOAD "Обновление путем загрузки файлов" -#define D_UPLOAD_STARTED "Загрузка началась" -#define D_UPGRADE_STARTED "Обновление началось" -#define D_UPLOAD_DONE "Загрузка завершена" -#define D_UPLOAD_ERR_1 "Файл не выбран" -#define D_UPLOAD_ERR_2 "Недостаточно места" -#define D_UPLOAD_ERR_3 "Magic байт не 0xE9" -#define D_UPLOAD_ERR_4 "Размер прошивки больше, чем реальный размер флеш памяти" -#define D_UPLOAD_ERR_5 "Ошибка загрузки буфера" -#define D_UPLOAD_ERR_6 "Ошибка загрузки. Включено лог уровня 3" -#define D_UPLOAD_ERR_7 "Загрузка прервана" -#define D_UPLOAD_ERR_8 "Файл неверный" -#define D_UPLOAD_ERR_9 "Слишком большой файл" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Код ошибки загрузки" - -#define D_ENTER_COMMAND "Введите команду" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Включить Веб лог уровня 2 если ожидается ответ" -#define D_NEED_USER_AND_PASSWORD "Ожидается user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Проверка TLS Fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "Сбой подключения TLS к" -#define D_RETRY_IN "Повторить" -#define D_VERIFIED "Проверено Fingerprint" -#define D_INSECURE "Небезопасное соединение, недействительный Fingerprint" -#define D_CONNECT_FAILED_TO "Ошибка подключения к" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast отключен" -#define D_MULTICAST_REJOINED "Multicast (ре)соединился" -#define D_MULTICAST_JOIN_FAILED "Multicast ошибка соединения" -#define D_FAILED_TO_SEND_RESPONSE "Не удалось отправить ответ" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo основное событие" -#define D_WEMO_EVENT_SERVICE "WeMo служба событий" -#define D_WEMO_META_SERVICE "WeMo мета-сервис" -#define D_WEMO_SETUP "WeMo настройка" -#define D_RESPONSE_SENT "Ответ отправлен" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue настройка" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API не реализовано" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 ответных пакета получено" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Параметры Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2,5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Update timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Конфигурация Timer" -#define D_TIMER_PARAMETERS "Параметры Timer" -#define D_TIMER_ENABLE "Enable Timers" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Конфигурация KNX" -#define D_KNX_PARAMETERS "Параметры KNX" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Энергия Сегодня" -#define D_ENERGY_YESTERDAY "Энергия Вчера" -#define D_ENERGY_TOTAL "Энергия Всего" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Датчик DS18x20 занят" -#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - ошибка CRC" -#define D_SENSORS_FOUND "Датчик DS18x20 найден" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Тайм-аут, в ожидании" -#define D_START_SIGNAL_LOW "сигнал старт низкий" -#define D_START_SIGNAL_HIGH "сигнал старт высокий" -#define D_PULSE "пульс" -#define D_CHECKSUM_FAILURE "Ошибка контрольной суммы" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не получил команду ACK" -#define D_SHT1X_FOUND "SHT1X найден" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "-нет-" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Свич" // Suffix "1" -#define D_SENSOR_BUTTON "Кнопка" // Suffix "1" -#define D_SENSOR_RELAY "Реле" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Счетчик" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "А" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Ч" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "кОм" -#define D_UNIT_KILOWATTHOUR "кВт" -#define D_UNIT_LUX "лк" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" -#define D_UNIT_MICROMETER "мкм" -#define D_UNIT_MICROSECOND "мкс" -#define D_UNIT_MILLIAMPERE "мА" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "мм рт.ст." -#define D_UNIT_MILLISECOND "мс" -#define D_UNIT_MINUTE "мин" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "гПа" -#define D_UNIT_SECOND "сек" -#define D_UNIT_SECTORS "секторов" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "В" -#define D_UNIT_WATT "Вт" -#define D_UNIT_WATTHOUR "ВтЧ" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Угол фазы" -#define D_IMPORT_ACTIVE "Импорт активной мощности" -#define D_EXPORT_ACTIVE "Экспорт активной мощности" -#define D_IMPORT_REACTIVE "Импорт реактивной мощности" -#define D_EXPORT_REACTIVE "Экспорт реактивной мощности" -#define D_TOTAL_REACTIVE "Итого реактивная мощность" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Град" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_RU_RU_H_ +/* + ru-RU.h - localization for Russian - Rissia for Tasmota + + Copyright (C) 2019 Theo Arends / roman-vn + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_RU_RU_H_ +#define _LANGUAGE_RU_RU_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.12.0b +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1049 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "ru" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "ВскПонВтрСрдЧетПятСуб" +#define D_MONTH3LIST "ЯнвФевМарАпрМайИюнИюлАвгСенОктНояДек" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Качество воздуха" +#define D_AP "AP" // Access Point +#define D_AS "как" +#define D_AUTO "АВТО" +#define D_BLINK "Мигать" +#define D_BLINKOFF "Не Мигать" +#define D_BOOT_COUNT "Количество загрузок" +#define D_BRIGHTLIGHT "Яркость" +#define D_BSSID "BSSId" +#define D_BUTTON "Кнопка" +#define D_BY "by" // Written by me +#define D_BYTES "Байт" +#define D_CELSIUS "Цельсия" +#define D_CHANNEL "Channel" +#define D_CO2 "Углекислый газ" +#define D_CODE "код" // Button code +#define D_COLDLIGHT "Холодный" +#define D_COMMAND "Команда" +#define D_CONNECTED "Соединен" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Подсчет" +#define D_COUNTER "Счетчик" +#define D_CURRENT "Ток" // As in Voltage and Current +#define D_DATA "Данные" +#define D_DARKLIGHT "Темный" +#define D_DEBUG "Отладка" +#define D_DISABLED "Блокирован" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "DNS Сервер" +#define D_DONE "Выполнено" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Эмуляция" +#define D_ENABLED "Активно" +#define D_ERASE "Стирать" +#define D_ERROR "Ошибка" +#define D_FAHRENHEIT "Фаренгейт" +#define D_FAILED "Неудачно" +#define D_FALLBACK "Обратная связь" +#define D_FALLBACK_TOPIC "Топик обратной связи" +#define D_FALSE "Ложно" +#define D_FILE "Файл" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Свободная память" +#define D_FREQUENCY "Frequency" +#define D_GAS "Газ" +#define D_GATEWAY "Шлюз" +#define D_GROUP "Группа" +#define D_HOST "Хост" +#define D_HOSTNAME "Имя Хоста" +#define D_HUMIDITY "Влажность" +#define D_ILLUMINANCE "Освещенность" +#define D_IMMEDIATE "немедленно" // Button immediate +#define D_INDEX "Индекс" +#define D_INFO "Инфо" +#define D_INFRARED "Infrared" +#define D_INITIALIZED "Инициализировано" +#define D_IP_ADDRESS "IP Адрес" +#define D_LIGHT "Свет" +#define D_LWT "LWT" +#define D_MODULE "Модуль" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "многократное нажатие" +#define D_NOISE "Шум" +#define D_NONE "Нет" +#define D_OFF "Выкл" +#define D_OFFLINE "Офф-лайн" +#define D_OK "Ок" +#define D_ON "Вкл" +#define D_ONLINE "Он-лайн" +#define D_PASSWORD "Пароль" +#define D_PORT "Порт" +#define D_POWER_FACTOR "Коэффициент Мощности" +#define D_POWERUSAGE "Мощность" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "Давление" +#define D_PRESSUREATSEALEVEL "Давление на уровне моря" +#define D_PROGRAM_FLASH_SIZE "Размер Flash для программ" +#define D_PROGRAM_SIZE "Размер программы " +#define D_PROJECT "Проект" +#define D_RAIN "Rain" +#define D_RECEIVED "Получено" +#define D_RESTART "Перезапуск" +#define D_RESTARTING "Перезапуск" +#define D_RESTART_REASON "Причина перезагрузки" +#define D_RESTORE "восстановление" +#define D_RETAINED "нераспред." +#define D_RULE "Rule" +#define D_SAVE "Сохранить" +#define D_SENSOR "Датчик" +#define D_SSID "SSId" +#define D_START "Старт" +#define D_STD_TIME "STD" +#define D_STOP "Стоп" +#define D_SUBNET_MASK "Маска Подсети" +#define D_SUBSCRIBE_TO "Подписаться на" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Успешно" +#define D_SUNRISE "Sunrise" +#define D_SUNSET "Sunset" +#define D_TEMPERATURE "Температура" +#define D_TO "до" +#define D_TOGGLE "Переключить" +#define D_TOPIC "Топик" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Передать" +#define D_TRUE "Истина" +#define D_TVOC "TVOC" +#define D_UPGRADE "обновление" +#define D_UPLOAD "Загрузить" +#define D_UPTIME "Uptime" +#define D_USER "Пользователь" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "УФ уровень" +#define D_UV_POWER "UV Power" +#define D_VERSION "Версия" +#define D_VOLTAGE "Напряжение" +#define D_WEIGHT "Weight" +#define D_WARMLIGHT "Тепло" +#define D_WEB_SERVER "Web сервер" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ПРЕДУПРЕЖДЕНИЕ Эта версия не поддерживает персистентные настройки" +#define D_LEVEL_10 "уровень 1-0" +#define D_LEVEL_01 "уровень 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial logging отключен" +#define D_SYSLOG_LOGGING_REENABLED "Syslog logging включен" + +#define D_SET_BAUDRATE_TO "Установить скорость передачи (Baudrate)" +#define D_RECEIVED_TOPIC "Полученный Топик" +#define D_DATA_SIZE "Размер данных" +#define D_ANALOG_INPUT "Аналоговый вход" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Блокирующий цикл" +#define D_WPS_FAILED_WITH_STATUS "WPS конфигурация НЕУДАЧНА со статусом" +#define D_ACTIVE_FOR_3_MINUTES "активен в течение 3 минут" +#define D_FAILED_TO_START "не удалось запустить" +#define D_PATCH_ISSUE_2186 "Проблема с исправлением 2186" +#define D_CONNECTING_TO_AP "Подключение к AP" +#define D_IN_MODE "в режиме" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Ошибка подключения, IP-адрес не получен" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Ошибка соединения, AP не может быть достигнута" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Ошибка соединения, неверный пароль к AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Ошибка соединения с AP по тайм-ауту" +#define D_ATTEMPTING_CONNECTION "Попытка подключения..." +#define D_CHECKING_CONNECTION "Проверка соединения..." +#define D_QUERY_DONE "Запрос выполнен. Обнаружены службы MQTT" +#define D_MQTT_SERVICE_FOUND "MQTT сервис service найдено" +#define D_FOUND_AT "найдено в" +#define D_SYSLOG_HOST_NOT_FOUND "System лог хост не найден" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Сохранено во флэш-память" +#define D_LOADED_FROM_FLASH_AT "Загружено из флэш-памяти" +#define D_USE_DEFAULTS "Использовать значение по умолчанию" +#define D_ERASED_SECTOR "Стереть сектор" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
пожалуйста обновите" +#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен" +#define D_WITH_IP_ADDRESS "с IP-адресом" +#define D_WEBSERVER_STOPPED "Веб-сервер остановлен" +#define D_FILE_NOT_FOUND "Файл не найден" +#define D_REDIRECTED "Перенаправлено на адаптивный портал" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер устанавливает Точку Доступа и сохраняет станцию" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер установил Точку Доступа" +#define D_TRYING_TO_CONNECT "Попытка подключения устройства к сети" + +#define D_RESTART_IN "Перезапуск" +#define D_SECONDS "секунд" +#define D_DEVICE_WILL_RESTART "Устройство будет перезапущено через несколько секунд" +#define D_BUTTON_TOGGLE "Переключить" +#define D_CONFIGURATION "Конфигурация" +#define D_INFORMATION "Информация" +#define D_FIRMWARE_UPGRADE "Обновление прошивки" +#define D_CONSOLE "Консоль" +#define D_CONFIRM_RESTART "Подтвердить перезагрузку" + +#define D_CONFIGURE_MODULE "Конфигурация Модуля" +#define D_CONFIGURE_WIFI "Конфигурация WiFi" +#define D_CONFIGURE_MQTT "Конфигурация MQTT" +#define D_CONFIGURE_DOMOTICZ "Конфигурация Domoticz" +#define D_CONFIGURE_LOGGING "Конфигурация Logging" +#define D_CONFIGURE_OTHER "Конфигурация прочее" +#define D_CONFIRM_RESET_CONFIGURATION "Подтвердить Сброс Конфигурации" +#define D_RESET_CONFIGURATION "Сброс Конфигурации" +#define D_BACKUP_CONFIGURATION "Резервное копирование Конфигурации" +#define D_RESTORE_CONFIGURATION "Восстановление Конфигурации" +#define D_MAIN_MENU "Главное Меню" + +#define D_MODULE_PARAMETERS "Параметры модуля" +#define D_MODULE_TYPE "Тип модуля" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial вход" +#define D_SERIAL_OUT "Serial выход" + +#define D_WIFI_PARAMETERS "Параметры Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Сканирование беспроводных сетей Wifi" +#define D_SCAN_DONE "Сканирование завершено" +#define D_NO_NETWORKS_FOUND "Не найдено сетей" +#define D_REFRESH_TO_SCAN_AGAIN "Обновить для повторного сканирования" +#define D_DUPLICATE_ACCESSPOINT "Дублировать Точку Доступа (AP)" +#define D_SKIPPING_LOW_QUALITY "Пропущено из-за низкого качества" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 Пароль" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Пароль" + +#define D_MQTT_PARAMETERS "Параметры MQTT" +#define D_CLIENT "Клиент" +#define D_FULL_TOPIC "Полный Топик" + +#define D_LOGGING_PARAMETERS "Параметры Logging" +#define D_SERIAL_LOG_LEVEL "Serial лог уровень" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web лог уровень" +#define D_SYS_LOG_LEVEL "System лог уровень" +#define D_MORE_DEBUG "Дополнительная информация для отладки" +#define D_SYSLOG_HOST "System лог хост" +#define D_SYSLOG_PORT "System лог порт" +#define D_TELEMETRY_PERIOD "Период телеметрии" + +#define D_OTHER_PARAMETERS "Параметры Прочие" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Пароль Web администратора" +#define D_MQTT_ENABLE "MQTT активен" +#define D_FRIENDLY_NAME "Дружественное Имя" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "одиночное" +#define D_MULTI_DEVICE "мульти" + +#define D_CONFIGURE_TEMPLATE "Конфигурация Template" +#define D_TEMPLATE_PARAMETERS "Параметры Template" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Сохранить конфигурацию" +#define D_CONFIGURATION_SAVED "Конфигурация сохранена " +#define D_CONFIGURATION_RESET "Конфигурация сброшена" + +#define D_PROGRAM_VERSION "Версия программы" +#define D_BUILD_DATE_AND_TIME "Дата & Время сборки" +#define D_CORE_AND_SDK_VERSION "Версия Core/SDK" +#define D_FLASH_WRITE_COUNT "Кол-во записей Flash" +#define D_MAC_ADDRESS "MAC Адрес" +#define D_MQTT_HOST "MQTT Хост" +#define D_MQTT_PORT "MQTT Порт" +#define D_MQTT_CLIENT "MQTT Клиент ID" +#define D_MQTT_USER "MQTT Пользователь" +#define D_MQTT_TOPIC "MQTT Топик" +#define D_MQTT_GROUP_TOPIC "MQTT Топик группы" +#define D_MQTT_FULL_TOPIC "MQTT Топик полный" +#define D_MDNS_DISCOVERY "mDNS Обнаружение" +#define D_MDNS_ADVERTISE "mDNS Транcляция" +#define D_ESP_CHIP_ID "ID чипа ESP" +#define D_FLASH_CHIP_ID "ID чипа Flash памяти" +#define D_FLASH_CHIP_SIZE "Размер Flash памяти" +#define D_FREE_PROGRAM_SPACE "Свободное пространство программ" + +#define D_UPGRADE_BY_WEBSERVER "Обновление через Веб-сервер" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Начать обновление" +#define D_UPGRADE_BY_FILE_UPLOAD "Обновление путем загрузки файлов" +#define D_UPLOAD_STARTED "Загрузка началась" +#define D_UPGRADE_STARTED "Обновление началось" +#define D_UPLOAD_DONE "Загрузка завершена" +#define D_UPLOAD_ERR_1 "Файл не выбран" +#define D_UPLOAD_ERR_2 "Недостаточно места" +#define D_UPLOAD_ERR_3 "Magic байт не 0xE9" +#define D_UPLOAD_ERR_4 "Размер прошивки больше, чем реальный размер флеш памяти" +#define D_UPLOAD_ERR_5 "Ошибка загрузки буфера" +#define D_UPLOAD_ERR_6 "Ошибка загрузки. Включено лог уровня 3" +#define D_UPLOAD_ERR_7 "Загрузка прервана" +#define D_UPLOAD_ERR_8 "Файл неверный" +#define D_UPLOAD_ERR_9 "Слишком большой файл" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "Код ошибки загрузки" + +#define D_ENTER_COMMAND "Введите команду" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Включить Веб лог уровня 2 если ожидается ответ" +#define D_NEED_USER_AND_PASSWORD "Ожидается user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Проверка TLS Fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "Сбой подключения TLS к" +#define D_RETRY_IN "Повторить" +#define D_VERIFIED "Проверено Fingerprint" +#define D_INSECURE "Небезопасное соединение, недействительный Fingerprint" +#define D_CONNECT_FAILED_TO "Ошибка подключения к" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast отключен" +#define D_MULTICAST_REJOINED "Multicast (ре)соединился" +#define D_MULTICAST_JOIN_FAILED "Multicast ошибка соединения" +#define D_FAILED_TO_SEND_RESPONSE "Не удалось отправить ответ" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo основное событие" +#define D_WEMO_EVENT_SERVICE "WeMo служба событий" +#define D_WEMO_META_SERVICE "WeMo мета-сервис" +#define D_WEMO_SETUP "WeMo настройка" +#define D_RESPONSE_SENT "Ответ отправлен" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue настройка" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API не реализовано" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 ответных пакета получено" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Параметры Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2,5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Update timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Конфигурация Timer" +#define D_TIMER_PARAMETERS "Параметры Timer" +#define D_TIMER_ENABLE "Enable Timers" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Time" +#define D_TIMER_DAYS "Days" +#define D_TIMER_REPEAT "Repeat" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Конфигурация KNX" +#define D_KNX_PARAMETERS "Параметры KNX" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Physical Address" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "Enable KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Add" +#define D_DELETE "Delete" +#define D_REPLY "Reply" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Write" +#define D_KNX_COMMAND_READ "Read" +#define D_KNX_COMMAND_OTHER "Other" +#define D_SENT_TO "sent to" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Энергия Сегодня" +#define D_ENERGY_YESTERDAY "Энергия Вчера" +#define D_ENERGY_TOTAL "Энергия Всего" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Датчик DS18x20 занят" +#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - ошибка CRC" +#define D_SENSORS_FOUND "Датчик DS18x20 найден" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Тайм-аут, в ожидании" +#define D_START_SIGNAL_LOW "сигнал старт низкий" +#define D_START_SIGNAL_HIGH "сигнал старт высокий" +#define D_PULSE "пульс" +#define D_CHECKSUM_FAILURE "Ошибка контрольной суммы" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не получил команду ACK" +#define D_SHT1X_FOUND "SHT1X найден" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "-нет-" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Свич" // Suffix "1" +#define D_SENSOR_BUTTON "Кнопка" // Suffix "1" +#define D_SENSOR_RELAY "Реле" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Счетчик" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "А" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Ч" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "кОм" +#define D_UNIT_KILOWATTHOUR "кВт" +#define D_UNIT_LUX "лк" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" +#define D_UNIT_MICROMETER "мкм" +#define D_UNIT_MICROSECOND "мкс" +#define D_UNIT_MILLIAMPERE "мА" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "мм рт.ст." +#define D_UNIT_MILLISECOND "мс" +#define D_UNIT_MINUTE "мин" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "гПа" +#define D_UNIT_SECOND "сек" +#define D_UNIT_SECTORS "секторов" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "В" +#define D_UNIT_WATT "Вт" +#define D_UNIT_WATTHOUR "ВтЧ" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Угол фазы" +#define D_IMPORT_ACTIVE "Импорт активной мощности" +#define D_EXPORT_ACTIVE "Экспорт активной мощности" +#define D_IMPORT_REACTIVE "Импорт реактивной мощности" +#define D_EXPORT_REACTIVE "Экспорт реактивной мощности" +#define D_TOTAL_REACTIVE "Итого реактивная мощность" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Град" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_RU_RU_H_ diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index 52540be9c..a64e49e01 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -1,703 +1,701 @@ -/* - sk-SK.h - localization for Slovak with diacritics - Slovak for Tasmota - - Copyright (C) 2019 Vladimír Jendroľ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_SK_SK_H_ -#define _LANGUAGE_SK_SK_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.14 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1029 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "sk" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "Ne Po Ut St Št Pi So" -#define D_MONTH3LIST "JanFebMarAprMájJúnJúlAugSepOktNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Kvalita vzduchu" -#define D_AP "AP" // Access Point -#define D_AS "ako" -#define D_AUTO "AUTO" -#define D_BLINK "Blikanie" -#define D_BLINKOFF "BlikanieVyp" -#define D_BOOT_COUNT "Počítadlo spustení" -#define D_BRIGHTLIGHT "Svetlý" -#define D_BSSID "BSSId" -#define D_BUTTON "Tlačídlo" -#define D_BY "by" // Written by me -#define D_BYTES "Bytov" -#define D_CELSIUS "°C" -#define D_CHANNEL "Kanál" -#define D_CO2 "CO2" -#define D_CODE "kód" // Button code -#define D_COLDLIGHT "Studené svetlo" -#define D_COMMAND "Príkaz" -#define D_CONNECTED "...pripojené" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Počítaj" -#define D_COUNTER "Počítadlo" -#define D_CURRENT "Prúd" // As in Voltage and Current -#define D_DATA "Dáta" -#define D_FLOW_RATE "Flow rate" -#define D_DARKLIGHT "Tmavý" -#define D_DEBUG "Debug" -#define D_DISABLED "Zablokované" -#define D_DISTANCE "Vzdialenosť" -#define D_DNS_SERVER "Server DNS" -#define D_DONE "Hotovo" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulácia" -#define D_ENABLED "Otvorený" -#define D_ERASE "Zmaž" -#define D_ERROR "Chyba" -#define D_FAHRENHEIT "Fahrenheita" -#define D_FAILED "chyba" -#define D_FALLBACK "Záložný" -#define D_FALLBACK_TOPIC "Záložný topic" -#define D_FALSE "Nepravda" -#define D_FILE "Súbor" -#define D_FREE_MEMORY "Voľná pamäť" -#define D_FREQUENCY "Frekvencia" -#define D_GAS "Plyn" -#define D_GATEWAY "Predvolená brána" -#define D_GROUP "Skupina" -#define D_HOST "Server" -#define D_HOSTNAME "Názov servera" -#define D_HUMIDITY "Vlhkosť" -#define D_ILLUMINANCE "Osvetlenie" -#define D_IMMEDIATE "Okamžité" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Informácie" -#define D_INFRARED "Infračervené" -#define D_INITIALIZED "Inicializovaný" -#define D_IP_ADDRESS "Adresa IP" -#define D_LIGHT "Svetlo" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-stlačenie" -#define D_NOISE "Hluk" -#define D_NONE "Žiadny" -#define D_OFF "Vyp." -#define D_OFFLINE "Neaktívny" -#define D_OK "OK" -#define D_ON "Zap." -#define D_ONLINE "Aktívny" -#define D_PASSWORD "Heslo" -#define D_PORT "Port" -#define D_POWER_FACTOR "Účinník" -#define D_POWERUSAGE "Príkon" -#define D_POWERUSAGE_ACTIVE "Činný príkon" -#define D_POWERUSAGE_APPARENT "Zdanlivý príkon" -#define D_POWERUSAGE_REACTIVE "Jalový príkon" -#define D_PRESSURE "Tlak" -#define D_PRESSUREATSEALEVEL "Tlak na hladine mora" -#define D_PROGRAM_FLASH_SIZE "Veľkosť flash pamäte" -#define D_PROGRAM_SIZE "Veľkosť programu" -#define D_PROJECT "Projekt" -#define D_RAIN "Dážď" -#define D_RECEIVED "Prijatý" -#define D_RESTART "Reštart" -#define D_RESTARTING "Reštartuje sa" -#define D_RESTART_REASON "Príčina reštartu" -#define D_RESTORE "Obnoviť" -#define D_RETAINED "Zachované" -#define D_RULE "Pravidlo" -#define D_SAVE "Ulož" -#define D_SENSOR "Senzor" -#define D_SSID "SSID" -#define D_START "Spustiť" -#define D_STD_TIME "STD" -#define D_STOP "Stop" -#define D_SUBNET_MASK "Maska podsiete" -#define D_SUBSCRIBE_TO "Prihlásiť do" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "úspešné." -#define D_SUNRISE "Svitanie" -#define D_SUNSET "Súmrak" -#define D_TEMPERATURE "Teplota" -#define D_TO "do" -#define D_TOGGLE "Prepni" -#define D_TOPIC "Topic" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Odošli" -#define D_TRUE "Pravda" -#define D_TVOC "TVOC" -#define D_UPGRADE "aktualizáciu" -#define D_UPLOAD "Nahrávanie..." -#define D_UPTIME "Uptime" -#define D_USER "Používateľ" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Nízky" -#define D_UV_INDEX_2 "Stredný" -#define D_UV_INDEX_3 "Vysoký" -#define D_UV_INDEX_4 "Nebezpečný" -#define D_UV_INDEX_5 "Popál1/2" -#define D_UV_INDEX_6 "Popál3" -#define D_UV_INDEX_7 "MimoRozsah" -#define D_UV_LEVEL "úroveň UV" -#define D_UV_POWER "UV Power" -#define D_VERSION "Verzia" -#define D_VOLTAGE "Napätie" -#define D_WEIGHT "Hmotnosť" -#define D_WARMLIGHT "Teplé svetlo" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "UPOZORNENIE Táto verzia nepodporuje trvalé nastavenia" -#define D_LEVEL_10 "úroveň 1-0" -#define D_LEVEL_01 "úroveň 0-1" -#define D_SERIAL_LOGGING_DISABLED "Logovanie na sériovom porte ukončené" -#define D_SYSLOG_LOGGING_REENABLED "Obnovený zápis do Syslog" - -#define D_SET_BAUDRATE_TO "Nastaviť rýchlosti prenosu na" -#define D_RECEIVED_TOPIC "Prijatý topic" -#define D_DATA_SIZE "Veľkosť dát" -#define D_ANALOG_INPUT "Analógový vstup" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Zablokovanie slučky" -#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig so statusom" -#define D_ACTIVE_FOR_3_MINUTES "aktívny 3 minúty" -#define D_FAILED_TO_START "nepodarilo sa spustiť" -#define D_PATCH_ISSUE_2186 "Chyba 2186" -#define D_CONNECTING_TO_AP "Pripájanie k AP" -#define D_IN_MODE "v režime" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba pripojenia, nebola obdržaná IP adresa" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba pripojenia, nedostupný AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba pripojenia, nesprávne heslo pre AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba pripojenia, uplynul AP timeout" -#define D_ATTEMPTING_CONNECTION "Pripájanie..." -#define D_CHECKING_CONNECTION "Skúška spojenia..." -#define D_QUERY_DONE "Vyslanie požiadavky. Nájdená služba MQTT" -#define D_MQTT_SERVICE_FOUND "Služba MQTT bola nájdená" -#define D_FOUND_AT "nájdené v" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebol nájdený" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Uložené do flash pamäte v" -#define D_LOADED_FROM_FLASH_AT "Stiahnuté z flash pamäte z" -#define D_USE_DEFAULTS "Použi prednastavené hodnoty" -#define D_ERASED_SECTOR "Zmazaný sektor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" -#define D_WEBSERVER_ACTIVE_ON "Aktívny Web server" -#define D_WITH_IP_ADDRESS "na IP adrese" -#define D_WEBSERVER_STOPPED "Web server zastavený" -#define D_FILE_NOT_FOUND "Súbor nebol nájdený" -#define D_REDIRECTED "Presmerovanie na vlastný portál" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manažér nastaví AP a zachová STA" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manažér nastaví Access Point" -#define D_TRYING_TO_CONNECT "Skúšam pripojiť zariadenie k sieti" - -#define D_RESTART_IN "Reštart" -#define D_SECONDS "sekúnd" -#define D_DEVICE_WILL_RESTART "Zariadenie bude reštartované behom niekoľkých sekúnd" -#define D_BUTTON_TOGGLE "Prepínač" -#define D_CONFIGURATION "Nastavenia" -#define D_INFORMATION "Informácie" -#define D_FIRMWARE_UPGRADE "Aktualizácia firmware" -#define D_CONSOLE "Konzola" -#define D_CONFIRM_RESTART "Potvrdenie reštartu" - -#define D_CONFIGURE_MODULE "Nastavenia modulu" -#define D_CONFIGURE_WIFI "Nastavenia WiFi" -#define D_CONFIGURE_MQTT "Nastavenia MQTT" -#define D_CONFIGURE_DOMOTICZ "Nastavenia Domoticz" -#define D_CONFIGURE_LOGGING "Nastavenia logovania" -#define D_CONFIGURE_OTHER "Ostatné nastavenia" -#define D_CONFIRM_RESET_CONFIGURATION "Potvrdenie resetu nastavení" -#define D_RESET_CONFIGURATION "Reset nastavení" -#define D_BACKUP_CONFIGURATION "Záloha nastavení" -#define D_RESTORE_CONFIGURATION "Obnovenie nastavení" -#define D_MAIN_MENU "Hlavné menu" - -#define D_MODULE_PARAMETERS "Nastavenia modulu" -#define D_MODULE_TYPE "Typ modulu" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Nastavenia WiFi" -#define D_SCAN_FOR_WIFI_NETWORKS "Sken WiFi sietí" -#define D_SCAN_DONE "Sken dokončený" -#define D_NO_NETWORKS_FOUND "Sieť nebola nájdená" -#define D_REFRESH_TO_SCAN_AGAIN "Zopakovať sken" -#define D_DUPLICATE_ACCESSPOINT "Kópia AP" -#define D_SKIPPING_LOW_QUALITY "Preskočenie z dôvodu kvality signálu" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "Heslo AP1" -#define D_AP2_SSID "AP2 SSID" -#define D_AP2_PASSWORD "Heslo AP2" - -#define D_MQTT_PARAMETERS "Nastavenia MQTT" -#define D_CLIENT "Klient" -#define D_FULL_TOPIC "Celý topic" - -#define D_LOGGING_PARAMETERS "Voľba logovania" -#define D_SERIAL_LOG_LEVEL "Sériová úroveň logu" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Webová úroveň logu" -#define D_SYS_LOG_LEVEL "Systemová úroveň logu" -#define D_MORE_DEBUG "Viac debug informácí" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Interval telemetrie" - -#define D_OTHER_PARAMETERS "Ostatné nastavenia" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" -#define D_MQTT_ENABLE "MQTT aktívne" -#define D_FRIENDLY_NAME "Friendly Name" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "single device" -#define D_MULTI_DEVICE "multi device" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Ulož nastavenia" -#define D_CONFIGURATION_SAVED "Nastavenia uložené" -#define D_CONFIGURATION_RESET "Nastavenia resetované" - -#define D_PROGRAM_VERSION "Verzia programu" -#define D_BUILD_DATE_AND_TIME "Datum a čas kompilácie" -#define D_CORE_AND_SDK_VERSION "Verzia Core/SDK" -#define D_FLASH_WRITE_COUNT "Počet zápisov do pamäte" -#define D_MAC_ADDRESS "Adresa MAC" -#define D_MQTT_HOST "Host MQTT" -#define D_MQTT_PORT "Port MQTT" -#define D_MQTT_CLIENT "Klient MQTT" -#define D_MQTT_USER "Používateľ MQTT" -#define D_MQTT_TOPIC "Topic MQTT" -#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT" -#define D_MQTT_FULL_TOPIC "Celý topic MQTT" -#define D_MDNS_DISCOVERY "Získavanie mDNS" -#define D_MDNS_ADVERTISE "Rozosielanie mDNS" -#define D_ESP_CHIP_ID "ID systému ESP" -#define D_FLASH_CHIP_ID "ID systému flash pamäte" -#define D_FLASH_CHIP_SIZE "Veľkosť flash" -#define D_FREE_PROGRAM_SPACE "Voľné místo pre program" - -#define D_UPGRADE_BY_WEBSERVER "Aktualizácia z Web serveru" -#define D_OTA_URL "URL OTA" -#define D_START_UPGRADE "Spustiť aktualizáciu" -#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizácia nahraním súboru" -#define D_UPLOAD_STARTED "Nahrávanie spustené" -#define D_UPGRADE_STARTED "Aktualizácia spustená" -#define D_UPLOAD_DONE "Nahrávanie ukončené" -#define D_UPLOAD_ERR_1 "Súbor nebol vybraný" -#define D_UPLOAD_ERR_2 "Málo miesta" -#define D_UPLOAD_ERR_3 "Magický byte má hodnotu inú než 0xE9" -#define D_UPLOAD_ERR_4 "Veľkosť programu je väčšia než skutočná veľkosť flash pamäte" -#define D_UPLOAD_ERR_5 "Chyba nahrávania, nesúhlasia porovnávané bity" -#define D_UPLOAD_ERR_6 "Chyba nahrávania. Spustený zápis do logu na úrovni 3" -#define D_UPLOAD_ERR_7 "Nahrávanie prerušené" -#define D_UPLOAD_ERR_8 "Nesprávny súbor" -#define D_UPLOAD_ERR_9 "Súbor je príliš veľký" -#define D_UPLOAD_ERR_10 "Chyba inicializácie RF chipu" -#define D_UPLOAD_ERR_11 "Chyba zmazania RF chipu" -#define D_UPLOAD_ERR_12 "Chyba pri zápise do RF chipu" -#define D_UPLOAD_ERR_13 "Chyba dekódovania RF firmwaru" -#define D_UPLOAD_ERROR_CODE "Chyba nahrávania" - -#define D_ENTER_COMMAND "Vlož príkaz" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni úroveň 2 zápisu Weblog, ak je očekávaná odpoveď" -#define D_NEED_USER_AND_PASSWORD "Vyžadovaný používateľ=&heslo=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifikuj odtlačok TLS..." -#define D_TLS_CONNECT_FAILED_TO "Nepripojené TLS do" -#define D_RETRY_IN "Zopakujem o" -#define D_VERIFIED "Overený odtlačok " -#define D_INSECURE "Nesprávne pripojenie z dôvodu chybného odtlačku TLS" -#define D_CONNECT_FAILED_TO "Nepodarilo sa nadviazať spojenie" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast je vypnutý" -#define D_MULTICAST_REJOINED "Multicast opäť pripojený" -#define D_MULTICAST_JOIN_FAILED "Multicast neúspešný" -#define D_FAILED_TO_SEND_RESPONSE "Nepodarilo sa odoslať odpoveď" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo základná udalosť" -#define D_WEMO_EVENT_SERVICE "WeMo servisná udalosť" -#define D_WEMO_META_SERVICE "WeMo meta udalosť" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Odpoveď odoslaná" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue setup" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API nie je implementované" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovede odoslané" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Nastavenia Domoticz" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Spinac idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak" - #define D_DOMOTICZ_POWER_ENERGY "Príkon,Energia" - #define D_DOMOTICZ_ILLUMINANCE "Osvetlenie" - #define D_DOMOTICZ_COUNT "Počítadlo/PM1" - #define D_DOMOTICZ_VOLTAGE "Napätie/PM2,5" - #define D_DOMOTICZ_CURRENT "Prúd/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Aktualizácia časovača" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Nastavenia časovača" -#define D_TIMER_PARAMETERS "Časovač" -#define D_TIMER_ENABLE "Povoľ časovače" -#define D_TIMER_ARM "Aktívne" -#define D_TIMER_TIME "Čas" -#define D_TIMER_DAYS "Dni" -#define D_TIMER_REPEAT "Opakovať" -#define D_TIMER_OUTPUT "Výstup" -#define D_TIMER_ACTION "Napájanie" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Nastavenie KNX" -#define D_KNX_PARAMETERS "KNX parametre" -#define D_KNX_GENERAL_CONFIG "Všeobecné" -#define D_KNX_PHYSICAL_ADDRESS "Fyzická adresa" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musí být jedinečná v sieti KNX )" -#define D_KNX_ENABLE "Povoľ KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dáta na odoslanie na skupinové adresy" -#define D_ADD "Pridať" -#define D_DELETE "Zmazať" -#define D_REPLY "Odpoveď" -#define D_KNX_GROUP_ADDRESS_TO_READ "Skupinové adresy pre príjem dát z" -#define D_RECEIVED_FROM "Prijaté z" -#define D_KNX_COMMAND_WRITE "Zapíš" -#define D_KNX_COMMAND_READ "Čítaj" -#define D_KNX_COMMAND_OTHER "Iné" -#define D_SENT_TO "pošli" -#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervovaná a nemôže byť použitá." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Spotreba dnes" -#define D_ENERGY_YESTERDAY "Spotreba včera" -#define D_ENERGY_TOTAL "Celková spotreba" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor DS18x20 obsadený" -#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" -#define D_SENSORS_FOUND "Nanájdený senzor DS18x20" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Čakanie na" -#define D_START_SIGNAL_LOW "nízký štartovací signál" -#define D_START_SIGNAL_HIGH "vysoký štartovací signál" -#define D_PULSE "impulz" -#define D_CHECKSUM_FAILURE "Chybný kontrolný súčet" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Senzor neobdržal príkaz ACK" -#define D_SHT1X_FOUND "SHT1X nanájdený" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "častíc" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. os-X" -#define D_AY_AXIS "Accel. os-Y" -#define D_AZ_AXIS "Accel. os-Z" -#define D_GX_AXIS "Gyro os-X" -#define D_GY_AXIS "Gyro os-Y" -#define D_GZ_AXIS "Gyro os-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Odstráňte záťaž" -#define D_HX_CAL_REFERENCE "Vložte referenčnú záťaž" -#define D_HX_CAL_DONE "Skalibrováné" -#define D_HX_CAL_FAIL "Chyba kalibráce" -#define D_RESET_HX711 "Reset váhy" -#define D_CONFIGURE_HX711 "Konfiguráce váhy" -#define D_HX711_PARAMETERS "Parametre váhy" -#define D_ITEM_WEIGHT "Vlastná hmotnosť" -#define D_REFERENCE_WEIGHT "Referenčná hmotnosť" -#define D_CALIBRATE "Kalibruj" -#define D_CALIBRATION "Kalibrácia" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Smer vetra" -#define D_TX20_WIND_SPEED "Rýchlosť vetra" -#define D_TX20_WIND_SPEED_AVG "Priemerná rýchlosť vetra" -#define D_TX20_WIND_SPEED_MAX "Maximálna rýchlosť vetra" -#define D_TX20_NORTH "S" -#define D_TX20_EAST "V" -#define D_TX20_SOUTH "J" -#define D_TX20_WEST "Z" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Žiaden" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Spínač" // Suffix "1" -#define D_SENSOR_BUTTON "Tlačidlo" // Suffix "1" -#define D_SENSOR_RELAY "Relé" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1", -#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Senzor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "hod" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sek" -#define D_UNIT_SECTORS "sektory" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_SK_SK_H_ +/* + sk-SK.h - localization for Slovak with diacritics - Slovak for Tasmota + + Copyright (C) 2019 Vladimír Jendroľ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_SK_SK_H_ +#define _LANGUAGE_SK_SK_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.14 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1029 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "sk" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "Ne Po Ut St Št Pi So" +#define D_MONTH3LIST "JanFebMarAprMájJúnJúlAugSepOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Kvalita vzduchu" +#define D_AP "AP" // Access Point +#define D_AS "ako" +#define D_AUTO "AUTO" +#define D_BLINK "Blikanie" +#define D_BLINKOFF "BlikanieVyp" +#define D_BOOT_COUNT "Počítadlo spustení" +#define D_BRIGHTLIGHT "Svetlý" +#define D_BSSID "BSSId" +#define D_BUTTON "Tlačídlo" +#define D_BY "by" // Written by me +#define D_BYTES "Bytov" +#define D_CELSIUS "°C" +#define D_CHANNEL "Kanál" +#define D_CO2 "CO2" +#define D_CODE "kód" // Button code +#define D_COLDLIGHT "Studené svetlo" +#define D_COMMAND "Príkaz" +#define D_CONNECTED "...pripojené" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Počítaj" +#define D_COUNTER "Počítadlo" +#define D_CURRENT "Prúd" // As in Voltage and Current +#define D_DATA "Dáta" +#define D_FLOW_RATE "Flow rate" +#define D_DARKLIGHT "Tmavý" +#define D_DEBUG "Debug" +#define D_DISABLED "Zablokované" +#define D_DISTANCE "Vzdialenosť" +#define D_DNS_SERVER "Server DNS" +#define D_DONE "Hotovo" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulácia" +#define D_ENABLED "Otvorený" +#define D_ERASE "Zmaž" +#define D_ERROR "Chyba" +#define D_FAHRENHEIT "Fahrenheita" +#define D_FAILED "chyba" +#define D_FALLBACK "Záložný" +#define D_FALLBACK_TOPIC "Záložný topic" +#define D_FALSE "Nepravda" +#define D_FILE "Súbor" +#define D_FREE_MEMORY "Voľná pamäť" +#define D_FREQUENCY "Frekvencia" +#define D_GAS "Plyn" +#define D_GATEWAY "Predvolená brána" +#define D_GROUP "Skupina" +#define D_HOST "Server" +#define D_HOSTNAME "Názov servera" +#define D_HUMIDITY "Vlhkosť" +#define D_ILLUMINANCE "Osvetlenie" +#define D_IMMEDIATE "Okamžité" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Informácie" +#define D_INFRARED "Infračervené" +#define D_INITIALIZED "Inicializovaný" +#define D_IP_ADDRESS "Adresa IP" +#define D_LIGHT "Svetlo" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-stlačenie" +#define D_NOISE "Hluk" +#define D_NONE "Žiadny" +#define D_OFF "Vyp." +#define D_OFFLINE "Neaktívny" +#define D_OK "OK" +#define D_ON "Zap." +#define D_ONLINE "Aktívny" +#define D_PASSWORD "Heslo" +#define D_PORT "Port" +#define D_POWER_FACTOR "Účinník" +#define D_POWERUSAGE "Príkon" +#define D_POWERUSAGE_ACTIVE "Činný príkon" +#define D_POWERUSAGE_APPARENT "Zdanlivý príkon" +#define D_POWERUSAGE_REACTIVE "Jalový príkon" +#define D_PRESSURE "Tlak" +#define D_PRESSUREATSEALEVEL "Tlak na hladine mora" +#define D_PROGRAM_FLASH_SIZE "Veľkosť flash pamäte" +#define D_PROGRAM_SIZE "Veľkosť programu" +#define D_PROJECT "Projekt" +#define D_RAIN "Dážď" +#define D_RECEIVED "Prijatý" +#define D_RESTART "Reštart" +#define D_RESTARTING "Reštartuje sa" +#define D_RESTART_REASON "Príčina reštartu" +#define D_RESTORE "Obnoviť" +#define D_RETAINED "Zachované" +#define D_RULE "Pravidlo" +#define D_SAVE "Ulož" +#define D_SENSOR "Senzor" +#define D_SSID "SSID" +#define D_START "Spustiť" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Maska podsiete" +#define D_SUBSCRIBE_TO "Prihlásiť do" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "úspešné." +#define D_SUNRISE "Svitanie" +#define D_SUNSET "Súmrak" +#define D_TEMPERATURE "Teplota" +#define D_TO "do" +#define D_TOGGLE "Prepni" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Odošli" +#define D_TRUE "Pravda" +#define D_TVOC "TVOC" +#define D_UPGRADE "aktualizáciu" +#define D_UPLOAD "Nahrávanie..." +#define D_UPTIME "Uptime" +#define D_USER "Používateľ" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Nízky" +#define D_UV_INDEX_2 "Stredný" +#define D_UV_INDEX_3 "Vysoký" +#define D_UV_INDEX_4 "Nebezpečný" +#define D_UV_INDEX_5 "Popál1/2" +#define D_UV_INDEX_6 "Popál3" +#define D_UV_INDEX_7 "MimoRozsah" +#define D_UV_LEVEL "úroveň UV" +#define D_UV_POWER "UV Power" +#define D_VERSION "Verzia" +#define D_VOLTAGE "Napätie" +#define D_WEIGHT "Hmotnosť" +#define D_WARMLIGHT "Teplé svetlo" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "UPOZORNENIE Táto verzia nepodporuje trvalé nastavenia" +#define D_LEVEL_10 "úroveň 1-0" +#define D_LEVEL_01 "úroveň 0-1" +#define D_SERIAL_LOGGING_DISABLED "Logovanie na sériovom porte ukončené" +#define D_SYSLOG_LOGGING_REENABLED "Obnovený zápis do Syslog" + +#define D_SET_BAUDRATE_TO "Nastaviť rýchlosti prenosu na" +#define D_RECEIVED_TOPIC "Prijatý topic" +#define D_DATA_SIZE "Veľkosť dát" +#define D_ANALOG_INPUT "Analógový vstup" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Zablokovanie slučky" +#define D_WPS_FAILED_WITH_STATUS "Chyba WPSconfig so statusom" +#define D_ACTIVE_FOR_3_MINUTES "aktívny 3 minúty" +#define D_FAILED_TO_START "nepodarilo sa spustiť" +#define D_PATCH_ISSUE_2186 "Chyba 2186" +#define D_CONNECTING_TO_AP "Pripájanie k AP" +#define D_IN_MODE "v režime" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Chyba pripojenia, nebola obdržaná IP adresa" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Chyba pripojenia, nedostupný AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Chyba pripojenia, nesprávne heslo pre AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Chyba pripojenia, uplynul AP timeout" +#define D_ATTEMPTING_CONNECTION "Pripájanie..." +#define D_CHECKING_CONNECTION "Skúška spojenia..." +#define D_QUERY_DONE "Vyslanie požiadavky. Nájdená služba MQTT" +#define D_MQTT_SERVICE_FOUND "Služba MQTT bola nájdená" +#define D_FOUND_AT "nájdené v" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nebol nájdený" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Uložené do flash pamäte v" +#define D_LOADED_FROM_FLASH_AT "Stiahnuté z flash pamäte z" +#define D_USE_DEFAULTS "Použi prednastavené hodnoty" +#define D_ERASED_SECTOR "Zmazaný sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY
prosím aktualizujte" +#define D_WEBSERVER_ACTIVE_ON "Aktívny Web server" +#define D_WITH_IP_ADDRESS "na IP adrese" +#define D_WEBSERVER_STOPPED "Web server zastavený" +#define D_FILE_NOT_FOUND "Súbor nebol nájdený" +#define D_REDIRECTED "Presmerovanie na vlastný portál" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wi-Fi manažér nastaví AP a zachová STA" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wi-Fi manažér nastaví Access Point" +#define D_TRYING_TO_CONNECT "Skúšam pripojiť zariadenie k sieti" + +#define D_RESTART_IN "Reštart" +#define D_SECONDS "sekúnd" +#define D_DEVICE_WILL_RESTART "Zariadenie bude reštartované behom niekoľkých sekúnd" +#define D_BUTTON_TOGGLE "Prepínač" +#define D_CONFIGURATION "Nastavenia" +#define D_INFORMATION "Informácie" +#define D_FIRMWARE_UPGRADE "Aktualizácia firmware" +#define D_CONSOLE "Konzola" +#define D_CONFIRM_RESTART "Potvrdenie reštartu" + +#define D_CONFIGURE_MODULE "Nastavenia modulu" +#define D_CONFIGURE_WIFI "Nastavenia WiFi" +#define D_CONFIGURE_MQTT "Nastavenia MQTT" +#define D_CONFIGURE_DOMOTICZ "Nastavenia Domoticz" +#define D_CONFIGURE_LOGGING "Nastavenia logovania" +#define D_CONFIGURE_OTHER "Ostatné nastavenia" +#define D_CONFIRM_RESET_CONFIGURATION "Potvrdenie resetu nastavení" +#define D_RESET_CONFIGURATION "Reset nastavení" +#define D_BACKUP_CONFIGURATION "Záloha nastavení" +#define D_RESTORE_CONFIGURATION "Obnovenie nastavení" +#define D_MAIN_MENU "Hlavné menu" + +#define D_MODULE_PARAMETERS "Nastavenia modulu" +#define D_MODULE_TYPE "Typ modulu" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Nastavenia WiFi" +#define D_SCAN_FOR_WIFI_NETWORKS "Sken WiFi sietí" +#define D_SCAN_DONE "Sken dokončený" +#define D_NO_NETWORKS_FOUND "Sieť nebola nájdená" +#define D_REFRESH_TO_SCAN_AGAIN "Zopakovať sken" +#define D_DUPLICATE_ACCESSPOINT "Kópia AP" +#define D_SKIPPING_LOW_QUALITY "Preskočenie z dôvodu kvality signálu" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "Heslo AP1" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "Heslo AP2" + +#define D_MQTT_PARAMETERS "Nastavenia MQTT" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Celý topic" + +#define D_LOGGING_PARAMETERS "Voľba logovania" +#define D_SERIAL_LOG_LEVEL "Sériová úroveň logu" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Webová úroveň logu" +#define D_SYS_LOG_LEVEL "Systemová úroveň logu" +#define D_MORE_DEBUG "Viac debug informácí" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Interval telemetrie" + +#define D_OTHER_PARAMETERS "Ostatné nastavenia" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora" +#define D_MQTT_ENABLE "MQTT aktívne" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "single device" +#define D_MULTI_DEVICE "multi device" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Ulož nastavenia" +#define D_CONFIGURATION_SAVED "Nastavenia uložené" +#define D_CONFIGURATION_RESET "Nastavenia resetované" + +#define D_PROGRAM_VERSION "Verzia programu" +#define D_BUILD_DATE_AND_TIME "Datum a čas kompilácie" +#define D_CORE_AND_SDK_VERSION "Verzia Core/SDK" +#define D_FLASH_WRITE_COUNT "Počet zápisov do pamäte" +#define D_MAC_ADDRESS "Adresa MAC" +#define D_MQTT_HOST "Host MQTT" +#define D_MQTT_PORT "Port MQTT" +#define D_MQTT_CLIENT "Klient MQTT" +#define D_MQTT_USER "Používateľ MQTT" +#define D_MQTT_TOPIC "Topic MQTT" +#define D_MQTT_GROUP_TOPIC "Topic skupiny MQTT" +#define D_MQTT_FULL_TOPIC "Celý topic MQTT" +#define D_MDNS_DISCOVERY "Získavanie mDNS" +#define D_MDNS_ADVERTISE "Rozosielanie mDNS" +#define D_ESP_CHIP_ID "ID systému ESP" +#define D_FLASH_CHIP_ID "ID systému flash pamäte" +#define D_FLASH_CHIP_SIZE "Veľkosť flash" +#define D_FREE_PROGRAM_SPACE "Voľné místo pre program" + +#define D_UPGRADE_BY_WEBSERVER "Aktualizácia z Web serveru" +#define D_OTA_URL "URL OTA" +#define D_START_UPGRADE "Spustiť aktualizáciu" +#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizácia nahraním súboru" +#define D_UPLOAD_STARTED "Nahrávanie spustené" +#define D_UPGRADE_STARTED "Aktualizácia spustená" +#define D_UPLOAD_DONE "Nahrávanie ukončené" +#define D_UPLOAD_ERR_1 "Súbor nebol vybraný" +#define D_UPLOAD_ERR_2 "Málo miesta" +#define D_UPLOAD_ERR_3 "Magický byte má hodnotu inú než 0xE9" +#define D_UPLOAD_ERR_4 "Veľkosť programu je väčšia než skutočná veľkosť flash pamäte" +#define D_UPLOAD_ERR_5 "Chyba nahrávania, nesúhlasia porovnávané bity" +#define D_UPLOAD_ERR_6 "Chyba nahrávania. Spustený zápis do logu na úrovni 3" +#define D_UPLOAD_ERR_7 "Nahrávanie prerušené" +#define D_UPLOAD_ERR_8 "Nesprávny súbor" +#define D_UPLOAD_ERR_9 "Súbor je príliš veľký" +#define D_UPLOAD_ERR_10 "Chyba inicializácie RF chipu" +#define D_UPLOAD_ERR_11 "Chyba zmazania RF chipu" +#define D_UPLOAD_ERR_12 "Chyba pri zápise do RF chipu" +#define D_UPLOAD_ERR_13 "Chyba dekódovania RF firmwaru" +#define D_UPLOAD_ERROR_CODE "Chyba nahrávania" + +#define D_ENTER_COMMAND "Vlož príkaz" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Zapni úroveň 2 zápisu Weblog, ak je očekávaná odpoveď" +#define D_NEED_USER_AND_PASSWORD "Vyžadovaný používateľ=&heslo=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifikuj odtlačok TLS..." +#define D_TLS_CONNECT_FAILED_TO "Nepripojené TLS do" +#define D_RETRY_IN "Zopakujem o" +#define D_VERIFIED "Overený odtlačok " +#define D_INSECURE "Nesprávne pripojenie z dôvodu chybného odtlačku TLS" +#define D_CONNECT_FAILED_TO "Nepodarilo sa nadviazať spojenie" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast je vypnutý" +#define D_MULTICAST_REJOINED "Multicast opäť pripojený" +#define D_MULTICAST_JOIN_FAILED "Multicast neúspešný" +#define D_FAILED_TO_SEND_RESPONSE "Nepodarilo sa odoslať odpoveď" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo základná udalosť" +#define D_WEMO_EVENT_SERVICE "WeMo servisná udalosť" +#define D_WEMO_META_SERVICE "WeMo meta udalosť" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Odpoveď odoslaná" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue setup" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API nie je implementované" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 pakety odpovede odoslané" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Nastavenia Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Spinac idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Vlhk" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Vlhk,Tlak" + #define D_DOMOTICZ_POWER_ENERGY "Príkon,Energia" + #define D_DOMOTICZ_ILLUMINANCE "Osvetlenie" + #define D_DOMOTICZ_COUNT "Počítadlo/PM1" + #define D_DOMOTICZ_VOLTAGE "Napätie/PM2,5" + #define D_DOMOTICZ_CURRENT "Prúd/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Aktualizácia časovača" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Nastavenia časovača" +#define D_TIMER_PARAMETERS "Časovač" +#define D_TIMER_ENABLE "Povoľ časovače" +#define D_TIMER_ARM "Aktívne" +#define D_TIMER_TIME "Čas" +#define D_TIMER_DAYS "Dni" +#define D_TIMER_REPEAT "Opakovať" +#define D_TIMER_OUTPUT "Výstup" +#define D_TIMER_ACTION "Napájanie" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Nastavenie KNX" +#define D_KNX_PARAMETERS "KNX parametre" +#define D_KNX_GENERAL_CONFIG "Všeobecné" +#define D_KNX_PHYSICAL_ADDRESS "Fyzická adresa" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musí být jedinečná v sieti KNX )" +#define D_KNX_ENABLE "Povoľ KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dáta na odoslanie na skupinové adresy" +#define D_ADD "Pridať" +#define D_DELETE "Zmazať" +#define D_REPLY "Odpoveď" +#define D_KNX_GROUP_ADDRESS_TO_READ "Skupinové adresy pre príjem dát z" +#define D_RECEIVED_FROM "Prijaté z" +#define D_KNX_COMMAND_WRITE "Zapíš" +#define D_KNX_COMMAND_READ "Čítaj" +#define D_KNX_COMMAND_OTHER "Iné" +#define D_SENT_TO "pošli" +#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervovaná a nemôže byť použitá." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Spotreba dnes" +#define D_ENERGY_YESTERDAY "Spotreba včera" +#define D_ENERGY_TOTAL "Celková spotreba" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor DS18x20 obsadený" +#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC" +#define D_SENSORS_FOUND "Nanájdený senzor DS18x20" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Čakanie na" +#define D_START_SIGNAL_LOW "nízký štartovací signál" +#define D_START_SIGNAL_HIGH "vysoký štartovací signál" +#define D_PULSE "impulz" +#define D_CHECKSUM_FAILURE "Chybný kontrolný súčet" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Senzor neobdržal príkaz ACK" +#define D_SHT1X_FOUND "SHT1X nanájdený" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "častíc" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. os-X" +#define D_AY_AXIS "Accel. os-Y" +#define D_AZ_AXIS "Accel. os-Z" +#define D_GX_AXIS "Gyro os-X" +#define D_GY_AXIS "Gyro os-Y" +#define D_GZ_AXIS "Gyro os-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Odstráňte záťaž" +#define D_HX_CAL_REFERENCE "Vložte referenčnú záťaž" +#define D_HX_CAL_DONE "Skalibrováné" +#define D_HX_CAL_FAIL "Chyba kalibráce" +#define D_RESET_HX711 "Reset váhy" +#define D_CONFIGURE_HX711 "Konfiguráce váhy" +#define D_HX711_PARAMETERS "Parametre váhy" +#define D_ITEM_WEIGHT "Vlastná hmotnosť" +#define D_REFERENCE_WEIGHT "Referenčná hmotnosť" +#define D_CALIBRATE "Kalibruj" +#define D_CALIBRATION "Kalibrácia" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Smer vetra" +#define D_TX20_WIND_SPEED "Rýchlosť vetra" +#define D_TX20_WIND_SPEED_AVG "Priemerná rýchlosť vetra" +#define D_TX20_WIND_SPEED_MAX "Maximálna rýchlosť vetra" +#define D_TX20_NORTH "S" +#define D_TX20_EAST "V" +#define D_TX20_SOUTH "J" +#define D_TX20_WEST "Z" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Žiaden" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Spínač" // Suffix "1" +#define D_SENSOR_BUTTON "Tlačidlo" // Suffix "1" +#define D_SENSOR_RELAY "Relé" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1", +#define D_SENSOR_COUNTER "Počítadlo" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Senzor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "hod" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sek" +#define D_UNIT_SECTORS "sektory" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_SK_SK_H_ diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index 3edeaf193..51ffc2ae3 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -1,703 +1,701 @@ -/* - sv-SE.h - localization for Swedish - Svenska for Tasmota - - Copyright (C) 2019 Gunnar Norin - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_SV_SE_H_ -#define _LANGUAGE_SV_SE_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.2.1.11 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -// https://www.science.co.il/language/Locale-codes.php -#define LANGUAGE_LCID 1053 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "sv" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "SönMånTisOnsTorFreLör" -#define D_MONTH3LIST "JanFebMarAprMajJunJulAugSepOktNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Luftkvalitet" -#define D_AP "AP" // Access Point -#define D_AS "som" -#define D_AUTO "AUTO" -#define D_BLINK "Blinka" -#define D_BLINKOFF "BlinkaAv" -#define D_BOOT_COUNT "Uppstartsräknare" -#define D_BRIGHTLIGHT "Ljust" -#define D_BSSID "BSSId" -#define D_BUTTON "Knapp" -#define D_BY "av" // Written by me -#define D_BYTES "Bytes" -#define D_CELSIUS "Celsius" -#define D_CHANNEL "Kanal" -#define D_CO2 "Koldioxid" -#define D_CODE "kod" // Button code -#define D_COLDLIGHT "Kallt" -#define D_COMMAND "Kommando" -#define D_CONNECTED "Ansluten" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Räkna" -#define D_COUNTER "Räknare" -#define D_CURRENT "Ström" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Mörkt" -#define D_DEBUG "Debug" -#define D_DISABLED "Inaktiverad" -#define D_DISTANCE "Distans" -#define D_DNS_SERVER "DNS-server" -#define D_DONE "Gjort" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emulation" -#define D_ENABLED "Aktiverad" -#define D_ERASE "Ta bort" -#define D_ERROR "Fel" -#define D_FAHRENHEIT "Fahrenheit" -#define D_FAILED "Misslyckades" -#define D_FALLBACK "Reserv" -#define D_FALLBACK_TOPIC "Reservämne" -#define D_FALSE "Falskt" -#define D_FILE "Fil" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Ledigt minne" -#define D_FREQUENCY "Frekvens" -#define D_GAS "Gas" -#define D_GATEWAY "Gateway" -#define D_GROUP "Grupp" -#define D_HOST "Värd" -#define D_HOSTNAME "Värdnamn" -#define D_HUMIDITY "Fuktighet" -#define D_ILLUMINANCE "Belysnings" -#define D_IMMEDIATE "Omedelbar" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Info" -#define D_INFRARED "Infraröd" -#define D_INITIALIZED "Initialiserad" -#define D_IP_ADDRESS "IP-adress" -#define D_LIGHT "Ljus" -#define D_LWT "LWT" -#define D_MODULE "Modul" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "fler tryck" -#define D_NOISE "Oväsen" -#define D_NONE "Ingen" -#define D_OFF "Av" -#define D_OFFLINE "Off-line" -#define D_OK "Ok" -#define D_ON "På" -#define D_ONLINE "Ansluten" -#define D_PASSWORD "Lösenord" -#define D_PORT "Port" -#define D_POWER_FACTOR "Spänningsfaktor" -#define D_POWERUSAGE "Spänning" -#define D_POWERUSAGE_ACTIVE "Aktiv spänning" -#define D_POWERUSAGE_APPARENT "Skenbar spänning" -#define D_POWERUSAGE_REACTIVE "Responsiv spänning" -#define D_PRESSURE "Tryck" -#define D_PRESSUREATSEALEVEL "Havstryck" -#define D_PROGRAM_FLASH_SIZE "Program-flashstorlek" -#define D_PROGRAM_SIZE "Programstorlek" -#define D_PROJECT "Projekt" -#define D_RAIN "Regn" -#define D_RECEIVED "Mottagen" -#define D_RESTART "Omstart" -#define D_RESTARTING "Startar om" -#define D_RESTART_REASON "Omstartsorsak" -#define D_RESTORE "återställ" -#define D_RETAINED "bevarad" -#define D_RULE "Regel" -#define D_SAVE "Spara" -#define D_SENSOR "Sensor" -#define D_SSID "SSId" -#define D_START "Starta" -#define D_STD_TIME "STD" -#define D_STOP "Stoppa" -#define D_SUBNET_MASK "Nätmask" -#define D_SUBSCRIBE_TO "Prenumera på" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Lyckat" -#define D_SUNRISE "Soluppgång" -#define D_SUNSET "Solnedgång" -#define D_TEMPERATURE "Temperatur" -#define D_TO "till" -#define D_TOGGLE "Växla" -#define D_TOPIC "Ämne" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "Sänd" -#define D_TRUE "Sant" -#define D_TVOC "TVOC" -#define D_UPGRADE "uppgradera" -#define D_UPLOAD "Ladda upp" -#define D_UPTIME "Upptid" -#define D_USER "Användare" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Låg" -#define D_UV_INDEX_2 "Med" -#define D_UV_INDEX_3 "Hög" -#define D_UV_INDEX_4 "Farligt" -#define D_UV_INDEX_5 "Skadligt" -#define D_UV_INDEX_6 "Extremt" -#define D_UV_INDEX_7 "UO" // Out of Range -#define D_UV_LEVEL "UV nivå" -#define D_UV_POWER "UV kraft" -#define D_VERSION "Version" -#define D_VOLTAGE "Volttal" -#define D_WEIGHT "Vikt" -#define D_WARMLIGHT "Varm" -#define D_WEB_SERVER "Webbserver" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "VARNING Denna version supporterar inte beständiga inställningar" -#define D_LEVEL_10 "nivå 1-0" -#define D_LEVEL_01 "nivå 0-1" -#define D_SERIAL_LOGGING_DISABLED "Seriell loggning inaktiverad" -#define D_SYSLOG_LOGGING_REENABLED "Syslog återaktiverad" - -#define D_SET_BAUDRATE_TO "Ange Baudrate till" -#define D_RECEIVED_TOPIC "Mottaget ämne" -#define D_DATA_SIZE "Datastorlek" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blockerad loop" -#define D_WPS_FAILED_WITH_STATUS "WPS-konfigurering MISSLYCKADES med status" -#define D_ACTIVE_FOR_3_MINUTES "aktiv för 3 minuter" -#define D_FAILED_TO_START "misslyckades att starta" -#define D_PATCH_ISSUE_2186 "Laga problem 2186" -#define D_CONNECTING_TO_AP "Ansluter till AP" -#define D_IN_MODE "i läge" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Anslutning misslyckades mottog ingen IP-adress" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Anslutning misslyckades, kunde inte nå AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Anslutning misslyckades, fel lösenord för AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Anslutning misslyckadess med AP, timeout" -#define D_ATTEMPTING_CONNECTION "Försöker ansluta..." -#define D_CHECKING_CONNECTION "Kontrollerar anslutning..." -#define D_QUERY_DONE "Fråga utförd. MQTT-tjänster hittades" -#define D_MQTT_SERVICE_FOUND "MQTT-tjänst hittades på" -#define D_FOUND_AT "hittades vid" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog-värd hittades inte" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Sparade till flash vid" -#define D_LOADED_FROM_FLASH_AT "Laddade från flash vid" -#define D_USE_DEFAULTS "Använd standard" -#define D_ERASED_SECTOR "Rensade sektor" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" -#define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" -#define D_WITH_IP_ADDRESS "med IP-adress" -#define D_WEBSERVER_STOPPED "Webbserver stoppad" -#define D_FILE_NOT_FOUND "Filen hittades inte" -#define D_REDIRECTED "Omdirigerad till fångstportal" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifihanterare ange accesspunkt och behåll station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifihanterare ange accesspunkt" -#define D_TRYING_TO_CONNECT "Försöker att ansluta enheten till nätverk" - -#define D_RESTART_IN "Omstart om" -#define D_SECONDS "sekunder" -#define D_DEVICE_WILL_RESTART "Enheten kommer att starta om inom ett antal sekunder" -#define D_BUTTON_TOGGLE "Växla" -#define D_CONFIGURATION "Konfigurering" -#define D_INFORMATION "Information" -#define D_FIRMWARE_UPGRADE "Uppgradera firmware" -#define D_CONSOLE "Konsol" -#define D_CONFIRM_RESTART "Bekräfta omstart" - -#define D_CONFIGURE_MODULE "Konfigurera modul" -#define D_CONFIGURE_WIFI "Konfigurera WiFi" -#define D_CONFIGURE_MQTT "Konfigurera MQTT" -#define D_CONFIGURE_DOMOTICZ "Konfigurera Domoticz" -#define D_CONFIGURE_LOGGING "Konfigurera loggning" -#define D_CONFIGURE_OTHER "Konfigurera annat" -#define D_CONFIRM_RESET_CONFIGURATION "Bekräfta nollställning av konfiguration" -#define D_RESET_CONFIGURATION "Nollställ konfiguration" -#define D_BACKUP_CONFIGURATION "Säkerhetskopiera konfiguration" -#define D_RESTORE_CONFIGURATION "Återställ konfiguration" -#define D_MAIN_MENU "Huvudmeny" - -#define D_MODULE_PARAMETERS "Modulparameterar" -#define D_MODULE_TYPE "Modultyp" -#define D_PULLUP_ENABLE "Ingen knapp/brytare pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Seriell in" -#define D_SERIAL_OUT "Seriell ut" - -#define D_WIFI_PARAMETERS "Wifi-parameterar" -#define D_SCAN_FOR_WIFI_NETWORKS "Skanna efter wifi-nätverk" -#define D_SCAN_DONE "Skanning slutförd" -#define D_NO_NETWORKS_FOUND "Inga nätverk hittades" -#define D_REFRESH_TO_SCAN_AGAIN "Uppdatera för att skanna igen" -#define D_DUPLICATE_ACCESSPOINT "Dubblett accesspunkt" -#define D_SKIPPING_LOW_QUALITY "Hoppa över pga dålig kvalitet" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSId" -#define D_AP1_PASSWORD "AP1 lösenord" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 lösenord" - -#define D_MQTT_PARAMETERS "MQTT-parameterar" -#define D_CLIENT "Klient" -#define D_FULL_TOPIC "Fullt ämne" - -#define D_LOGGING_PARAMETERS "Loggningsparametrar" -#define D_SERIAL_LOG_LEVEL "Seriell loggnivå" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Webb loggnivå" -#define D_SYS_LOG_LEVEL "Syslog-nivå" -#define D_MORE_DEBUG "Mer debugging" -#define D_SYSLOG_HOST "Syslog-värd" -#define D_SYSLOG_PORT "Syslog-port" -#define D_TELEMETRY_PERIOD "Telemetriperiod" - -#define D_OTHER_PARAMETERS "Andra parametrar" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Webbadmin-lösenord" -#define D_MQTT_ENABLE "MQTT aktivera" -#define D_FRIENDLY_NAME "Läsbart namn" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "soloenhet" -#define D_MULTI_DEVICE "multienhet" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Spara konfiguration" -#define D_CONFIGURATION_SAVED "Konfiguration sparad" -#define D_CONFIGURATION_RESET "Konfiguration nollställd" - -#define D_PROGRAM_VERSION "Programversion" -#define D_BUILD_DATE_AND_TIME "Kompilerings datum & tid" -#define D_CORE_AND_SDK_VERSION "Core/SDK version" -#define D_FLASH_WRITE_COUNT "Flash-skrivningsräknare" -#define D_MAC_ADDRESS "MAC-adress" -#define D_MQTT_HOST "MQTT-värd" -#define D_MQTT_PORT "MQTT-port" -#define D_MQTT_CLIENT "MQTT-klient" -#define D_MQTT_USER "MQTT-användare" -#define D_MQTT_TOPIC "MQTT-ämne" -#define D_MQTT_GROUP_TOPIC "MQTT gruppämne" -#define D_MQTT_FULL_TOPIC "MQTT fullt ämne" -#define D_MDNS_DISCOVERY "mDNS upptäckning" -#define D_MDNS_ADVERTISE "mDNS annonsering" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash-storlek" -#define D_FREE_PROGRAM_SPACE "Ledigt programutrymme" - -#define D_UPGRADE_BY_WEBSERVER "Uppgradering via webbserver" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Starta uppdatering" -#define D_UPGRADE_BY_FILE_UPLOAD "Uppgradering via filuppladdning" -#define D_UPLOAD_STARTED "Uppladdning startad" -#define D_UPGRADE_STARTED "Uppgradeing startad" -#define D_UPLOAD_DONE "Uppladdning klar" -#define D_UPLOAD_ERR_1 "Ingen fil vald" -#define D_UPLOAD_ERR_2 "Inte tillräckligt med ledigt utrymme" -#define D_UPLOAD_ERR_3 "Magisk byte är inte 0xE9" -#define D_UPLOAD_ERR_4 "Programmets flashstorlek är större än den verkliga flashstorleken" -#define D_UPLOAD_ERR_5 "Uppladdningbuffert stämmer inte överens" -#define D_UPLOAD_ERR_6 "Uppladdning misslyckad. Aktivera loggning 3" -#define D_UPLOAD_ERR_7 "Uppladdning avbruten" -#define D_UPLOAD_ERR_8 "Ogiltig fil" -#define D_UPLOAD_ERR_9 "För stor fil" -#define D_UPLOAD_ERR_10 "Misslyckades initera RF chip" -#define D_UPLOAD_ERR_11 "Misslyckades rensa RF chip" -#define D_UPLOAD_ERR_12 "Misslyckades skriva till RF chip" -#define D_UPLOAD_ERR_13 "Misslyckades avkoda RF firmware" -#define D_UPLOAD_ERROR_CODE "Uppladdningsfelkod" - -#define D_ENTER_COMMAND "Ange kommando" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivera webblogg 2 om svar förväntas" -#define D_NEED_USER_AND_PASSWORD "Behöver user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verifierar TLS fingeravtryck..." -#define D_TLS_CONNECT_FAILED_TO "TLS-anslutning misslyckades" -#define D_RETRY_IN "Försöker igen om" -#define D_VERIFIED "Verifierad med fingeravtryck" -#define D_INSECURE "Osäker anslutning pga ogiltigt fingeravtryck" -#define D_CONNECT_FAILED_TO "Anslutning misslyckades" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast inaktiverad" -#define D_MULTICAST_REJOINED "Multicast (åter)anslöt" -#define D_MULTICAST_JOIN_FAILED "Multicast anslutning misslyckades" -#define D_FAILED_TO_SEND_RESPONSE "Misslyckades skicka svar" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo standardhändelse" -#define D_WEMO_EVENT_SERVICE "WeMo händelsetjänst" -#define D_WEMO_META_SERVICE "WeMo metatjänst" -#define D_WEMO_SETUP "WeMo installation" -#define D_RESPONSE_SENT "Svar skickat" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue installation" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API inte implementerat" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 svarspaket skickade" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parametetrar" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Nyckel idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Fuk" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Fuk,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Spänning,Energi" - #define D_DOMOTICZ_ILLUMINANCE "Belysningsstyrka" - #define D_DOMOTICZ_COUNT "Antal/PM1" - #define D_DOMOTICZ_VOLTAGE "Volt/PM2.5" - #define D_DOMOTICZ_CURRENT "Ström/PM10" - #define D_DOMOTICZ_AIRQUALITY "Luftkvalitet" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Uppdatera timer" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Konfigurera timer" -#define D_TIMER_PARAMETERS "Timerparametrar" -#define D_TIMER_ENABLE "Aktivera timer" -#define D_TIMER_ARM "Aktivera" -#define D_TIMER_TIME "Tid" -#define D_TIMER_DAYS "Dagar" -#define D_TIMER_REPEAT "Repetera" -#define D_TIMER_OUTPUT "Utgång" -#define D_TIMER_ACTION "Åtgärd" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Konfigurera KNX" -#define D_KNX_PARAMETERS "KNX Parametrar" -#define D_KNX_GENERAL_CONFIG "Allmänt" -#define D_KNX_PHYSICAL_ADDRESS "Fysisk adress" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Måste vara unik på KNX-nätverket )" -#define D_KNX_ENABLE "Aktivera KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data att skicka till gruppadresser" -#define D_ADD "Lägg till" -#define D_DELETE "Ta bort" -#define D_REPLY "Svara" -#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppadresser att ta emot data från" -#define D_RECEIVED_FROM "Mottagen från" -#define D_KNX_COMMAND_WRITE "Skriv" -#define D_KNX_COMMAND_READ "Läs" -#define D_KNX_COMMAND_OTHER "Andra" -#define D_SENT_TO "skickad till" -#define D_KNX_WARNING "Gruppadressen ( 0 / 0 / 0 ) är reserverad och kan inte användas." -#define D_KNX_ENHANCEMENT "Kommuniceringsförbättring" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energi idag" -#define D_ENERGY_YESTERDAY "Energi igår" -#define D_ENERGY_TOTAL "Energi totalt" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensor upptagen" -#define D_SENSOR_CRC_ERROR "Sensor CRC-fel" -#define D_SENSORS_FOUND "Sensorer hittades" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout under väntan" -#define D_START_SIGNAL_LOW "startsignal låg" -#define D_START_SIGNAL_HIGH "startsignal hög" -#define D_PULSE "puls" -#define D_CHECKSUM_FAILURE "Fel kontrollsumma" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor besvarade inte med ACK kommando" -#define D_SHT1X_FOUND "SHT1X hittades" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Partiklar" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axel" -#define D_AY_AXIS "Accel. Y-Axel" -#define D_AZ_AXIS "Accel. Z-Axel" -#define D_GX_AXIS "Gyro X-Axel" -#define D_GY_AXIS "Gyro Y-Axel" -#define D_GZ_AXIS "Gyro Z-Axel" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Ta bort vikter" -#define D_HX_CAL_REFERENCE "Ladda referensvikt" -#define D_HX_CAL_DONE "Kalibrerad" -#define D_HX_CAL_FAIL "Kalibrering misslyckad" -#define D_RESET_HX711 "Återställ våg" -#define D_CONFIGURE_HX711 "Konfigurera våg" -#define D_HX711_PARAMETERS "Vågparametrar" -#define D_ITEM_WEIGHT "Objektsvikt" -#define D_REFERENCE_WEIGHT "Referensvikt" -#define D_CALIBRATE "Kalibrera" -#define D_CALIBRATION "Kalibrering" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Vindriktning" -#define D_TX20_WIND_SPEED "Vindstyrka" -#define D_TX20_WIND_SPEED_AVG "Vindstyrka medel" -#define D_TX20_WIND_SPEED_MAX "Vindstyrka max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "Ö" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "V" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Ingen" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3-spelare" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Omkopplare" // Suffix "1" -#define D_SENSOR_BUTTON "Knapp" // Suffix "1" -#define D_SENSOR_RELAY "Relä" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Räknare" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Tim" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "ink" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sek" -#define D_UNIT_SECTORS "sektorer" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Fasvinkel" -#define D_IMPORT_ACTIVE "Import aktiv" -#define D_EXPORT_ACTIVE "Export aktiv" -#define D_IMPORT_REACTIVE "Import reaktiv" -#define D_EXPORT_REACTIVE "Export reaktiv" -#define D_TOTAL_REACTIVE "Total reaktiv" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_SV_SE_H_ +/* + sv-SE.h - localization for Swedish - Svenska for Tasmota + + Copyright (C) 2019 Gunnar Norin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_SV_SE_H_ +#define _LANGUAGE_SV_SE_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.2.1.11 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 1053 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "sv" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "SönMånTisOnsTorFreLör" +#define D_MONTH3LIST "JanFebMarAprMajJunJulAugSepOktNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Luftkvalitet" +#define D_AP "AP" // Access Point +#define D_AS "som" +#define D_AUTO "AUTO" +#define D_BLINK "Blinka" +#define D_BLINKOFF "BlinkaAv" +#define D_BOOT_COUNT "Uppstartsräknare" +#define D_BRIGHTLIGHT "Ljust" +#define D_BSSID "BSSId" +#define D_BUTTON "Knapp" +#define D_BY "av" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Kanal" +#define D_CO2 "Koldioxid" +#define D_CODE "kod" // Button code +#define D_COLDLIGHT "Kallt" +#define D_COMMAND "Kommando" +#define D_CONNECTED "Ansluten" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Räkna" +#define D_COUNTER "Räknare" +#define D_CURRENT "Ström" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Mörkt" +#define D_DEBUG "Debug" +#define D_DISABLED "Inaktiverad" +#define D_DISTANCE "Distans" +#define D_DNS_SERVER "DNS-server" +#define D_DONE "Gjort" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emulation" +#define D_ENABLED "Aktiverad" +#define D_ERASE "Ta bort" +#define D_ERROR "Fel" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Misslyckades" +#define D_FALLBACK "Reserv" +#define D_FALLBACK_TOPIC "Reservämne" +#define D_FALSE "Falskt" +#define D_FILE "Fil" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Ledigt minne" +#define D_FREQUENCY "Frekvens" +#define D_GAS "Gas" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grupp" +#define D_HOST "Värd" +#define D_HOSTNAME "Värdnamn" +#define D_HUMIDITY "Fuktighet" +#define D_ILLUMINANCE "Belysnings" +#define D_IMMEDIATE "Omedelbar" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infraröd" +#define D_INITIALIZED "Initialiserad" +#define D_IP_ADDRESS "IP-adress" +#define D_LIGHT "Ljus" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "fler tryck" +#define D_NOISE "Oväsen" +#define D_NONE "Ingen" +#define D_OFF "Av" +#define D_OFFLINE "Off-line" +#define D_OK "Ok" +#define D_ON "På" +#define D_ONLINE "Ansluten" +#define D_PASSWORD "Lösenord" +#define D_PORT "Port" +#define D_POWER_FACTOR "Spänningsfaktor" +#define D_POWERUSAGE "Spänning" +#define D_POWERUSAGE_ACTIVE "Aktiv spänning" +#define D_POWERUSAGE_APPARENT "Skenbar spänning" +#define D_POWERUSAGE_REACTIVE "Responsiv spänning" +#define D_PRESSURE "Tryck" +#define D_PRESSUREATSEALEVEL "Havstryck" +#define D_PROGRAM_FLASH_SIZE "Program-flashstorlek" +#define D_PROGRAM_SIZE "Programstorlek" +#define D_PROJECT "Projekt" +#define D_RAIN "Regn" +#define D_RECEIVED "Mottagen" +#define D_RESTART "Omstart" +#define D_RESTARTING "Startar om" +#define D_RESTART_REASON "Omstartsorsak" +#define D_RESTORE "återställ" +#define D_RETAINED "bevarad" +#define D_RULE "Regel" +#define D_SAVE "Spara" +#define D_SENSOR "Sensor" +#define D_SSID "SSId" +#define D_START "Starta" +#define D_STD_TIME "STD" +#define D_STOP "Stoppa" +#define D_SUBNET_MASK "Nätmask" +#define D_SUBSCRIBE_TO "Prenumera på" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Lyckat" +#define D_SUNRISE "Soluppgång" +#define D_SUNSET "Solnedgång" +#define D_TEMPERATURE "Temperatur" +#define D_TO "till" +#define D_TOGGLE "Växla" +#define D_TOPIC "Ämne" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "Sänd" +#define D_TRUE "Sant" +#define D_TVOC "TVOC" +#define D_UPGRADE "uppgradera" +#define D_UPLOAD "Ladda upp" +#define D_UPTIME "Upptid" +#define D_USER "Användare" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Låg" +#define D_UV_INDEX_2 "Med" +#define D_UV_INDEX_3 "Hög" +#define D_UV_INDEX_4 "Farligt" +#define D_UV_INDEX_5 "Skadligt" +#define D_UV_INDEX_6 "Extremt" +#define D_UV_INDEX_7 "UO" // Out of Range +#define D_UV_LEVEL "UV nivå" +#define D_UV_POWER "UV kraft" +#define D_VERSION "Version" +#define D_VOLTAGE "Volttal" +#define D_WEIGHT "Vikt" +#define D_WARMLIGHT "Varm" +#define D_WEB_SERVER "Webbserver" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "VARNING Denna version supporterar inte beständiga inställningar" +#define D_LEVEL_10 "nivå 1-0" +#define D_LEVEL_01 "nivå 0-1" +#define D_SERIAL_LOGGING_DISABLED "Seriell loggning inaktiverad" +#define D_SYSLOG_LOGGING_REENABLED "Syslog återaktiverad" + +#define D_SET_BAUDRATE_TO "Ange Baudrate till" +#define D_RECEIVED_TOPIC "Mottaget ämne" +#define D_DATA_SIZE "Datastorlek" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blockerad loop" +#define D_WPS_FAILED_WITH_STATUS "WPS-konfigurering MISSLYCKADES med status" +#define D_ACTIVE_FOR_3_MINUTES "aktiv för 3 minuter" +#define D_FAILED_TO_START "misslyckades att starta" +#define D_PATCH_ISSUE_2186 "Laga problem 2186" +#define D_CONNECTING_TO_AP "Ansluter till AP" +#define D_IN_MODE "i läge" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Anslutning misslyckades mottog ingen IP-adress" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Anslutning misslyckades, kunde inte nå AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Anslutning misslyckades, fel lösenord för AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Anslutning misslyckadess med AP, timeout" +#define D_ATTEMPTING_CONNECTION "Försöker ansluta..." +#define D_CHECKING_CONNECTION "Kontrollerar anslutning..." +#define D_QUERY_DONE "Fråga utförd. MQTT-tjänster hittades" +#define D_MQTT_SERVICE_FOUND "MQTT-tjänst hittades på" +#define D_FOUND_AT "hittades vid" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog-värd hittades inte" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Sparade till flash vid" +#define D_LOADED_FROM_FLASH_AT "Laddade från flash vid" +#define D_USE_DEFAULTS "Använd standard" +#define D_ERASED_SECTOR "Rensade sektor" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware
var god uppgradera" +#define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på" +#define D_WITH_IP_ADDRESS "med IP-adress" +#define D_WEBSERVER_STOPPED "Webbserver stoppad" +#define D_FILE_NOT_FOUND "Filen hittades inte" +#define D_REDIRECTED "Omdirigerad till fångstportal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifihanterare ange accesspunkt och behåll station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifihanterare ange accesspunkt" +#define D_TRYING_TO_CONNECT "Försöker att ansluta enheten till nätverk" + +#define D_RESTART_IN "Omstart om" +#define D_SECONDS "sekunder" +#define D_DEVICE_WILL_RESTART "Enheten kommer att starta om inom ett antal sekunder" +#define D_BUTTON_TOGGLE "Växla" +#define D_CONFIGURATION "Konfigurering" +#define D_INFORMATION "Information" +#define D_FIRMWARE_UPGRADE "Uppgradera firmware" +#define D_CONSOLE "Konsol" +#define D_CONFIRM_RESTART "Bekräfta omstart" + +#define D_CONFIGURE_MODULE "Konfigurera modul" +#define D_CONFIGURE_WIFI "Konfigurera WiFi" +#define D_CONFIGURE_MQTT "Konfigurera MQTT" +#define D_CONFIGURE_DOMOTICZ "Konfigurera Domoticz" +#define D_CONFIGURE_LOGGING "Konfigurera loggning" +#define D_CONFIGURE_OTHER "Konfigurera annat" +#define D_CONFIRM_RESET_CONFIGURATION "Bekräfta nollställning av konfiguration" +#define D_RESET_CONFIGURATION "Nollställ konfiguration" +#define D_BACKUP_CONFIGURATION "Säkerhetskopiera konfiguration" +#define D_RESTORE_CONFIGURATION "Återställ konfiguration" +#define D_MAIN_MENU "Huvudmeny" + +#define D_MODULE_PARAMETERS "Modulparameterar" +#define D_MODULE_TYPE "Modultyp" +#define D_PULLUP_ENABLE "Ingen knapp/brytare pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Seriell in" +#define D_SERIAL_OUT "Seriell ut" + +#define D_WIFI_PARAMETERS "Wifi-parameterar" +#define D_SCAN_FOR_WIFI_NETWORKS "Skanna efter wifi-nätverk" +#define D_SCAN_DONE "Skanning slutförd" +#define D_NO_NETWORKS_FOUND "Inga nätverk hittades" +#define D_REFRESH_TO_SCAN_AGAIN "Uppdatera för att skanna igen" +#define D_DUPLICATE_ACCESSPOINT "Dubblett accesspunkt" +#define D_SKIPPING_LOW_QUALITY "Hoppa över pga dålig kvalitet" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "AP1 lösenord" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 lösenord" + +#define D_MQTT_PARAMETERS "MQTT-parameterar" +#define D_CLIENT "Klient" +#define D_FULL_TOPIC "Fullt ämne" + +#define D_LOGGING_PARAMETERS "Loggningsparametrar" +#define D_SERIAL_LOG_LEVEL "Seriell loggnivå" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Webb loggnivå" +#define D_SYS_LOG_LEVEL "Syslog-nivå" +#define D_MORE_DEBUG "Mer debugging" +#define D_SYSLOG_HOST "Syslog-värd" +#define D_SYSLOG_PORT "Syslog-port" +#define D_TELEMETRY_PERIOD "Telemetriperiod" + +#define D_OTHER_PARAMETERS "Andra parametrar" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Webbadmin-lösenord" +#define D_MQTT_ENABLE "MQTT aktivera" +#define D_FRIENDLY_NAME "Läsbart namn" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "soloenhet" +#define D_MULTI_DEVICE "multienhet" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Spara konfiguration" +#define D_CONFIGURATION_SAVED "Konfiguration sparad" +#define D_CONFIGURATION_RESET "Konfiguration nollställd" + +#define D_PROGRAM_VERSION "Programversion" +#define D_BUILD_DATE_AND_TIME "Kompilerings datum & tid" +#define D_CORE_AND_SDK_VERSION "Core/SDK version" +#define D_FLASH_WRITE_COUNT "Flash-skrivningsräknare" +#define D_MAC_ADDRESS "MAC-adress" +#define D_MQTT_HOST "MQTT-värd" +#define D_MQTT_PORT "MQTT-port" +#define D_MQTT_CLIENT "MQTT-klient" +#define D_MQTT_USER "MQTT-användare" +#define D_MQTT_TOPIC "MQTT-ämne" +#define D_MQTT_GROUP_TOPIC "MQTT gruppämne" +#define D_MQTT_FULL_TOPIC "MQTT fullt ämne" +#define D_MDNS_DISCOVERY "mDNS upptäckning" +#define D_MDNS_ADVERTISE "mDNS annonsering" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash-storlek" +#define D_FREE_PROGRAM_SPACE "Ledigt programutrymme" + +#define D_UPGRADE_BY_WEBSERVER "Uppgradering via webbserver" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Starta uppdatering" +#define D_UPGRADE_BY_FILE_UPLOAD "Uppgradering via filuppladdning" +#define D_UPLOAD_STARTED "Uppladdning startad" +#define D_UPGRADE_STARTED "Uppgradeing startad" +#define D_UPLOAD_DONE "Uppladdning klar" +#define D_UPLOAD_ERR_1 "Ingen fil vald" +#define D_UPLOAD_ERR_2 "Inte tillräckligt med ledigt utrymme" +#define D_UPLOAD_ERR_3 "Magisk byte är inte 0xE9" +#define D_UPLOAD_ERR_4 "Programmets flashstorlek är större än den verkliga flashstorleken" +#define D_UPLOAD_ERR_5 "Uppladdningbuffert stämmer inte överens" +#define D_UPLOAD_ERR_6 "Uppladdning misslyckad. Aktivera loggning 3" +#define D_UPLOAD_ERR_7 "Uppladdning avbruten" +#define D_UPLOAD_ERR_8 "Ogiltig fil" +#define D_UPLOAD_ERR_9 "För stor fil" +#define D_UPLOAD_ERR_10 "Misslyckades initera RF chip" +#define D_UPLOAD_ERR_11 "Misslyckades rensa RF chip" +#define D_UPLOAD_ERR_12 "Misslyckades skriva till RF chip" +#define D_UPLOAD_ERR_13 "Misslyckades avkoda RF firmware" +#define D_UPLOAD_ERROR_CODE "Uppladdningsfelkod" + +#define D_ENTER_COMMAND "Ange kommando" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Aktivera webblogg 2 om svar förväntas" +#define D_NEED_USER_AND_PASSWORD "Behöver user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifierar TLS fingeravtryck..." +#define D_TLS_CONNECT_FAILED_TO "TLS-anslutning misslyckades" +#define D_RETRY_IN "Försöker igen om" +#define D_VERIFIED "Verifierad med fingeravtryck" +#define D_INSECURE "Osäker anslutning pga ogiltigt fingeravtryck" +#define D_CONNECT_FAILED_TO "Anslutning misslyckades" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast inaktiverad" +#define D_MULTICAST_REJOINED "Multicast (åter)anslöt" +#define D_MULTICAST_JOIN_FAILED "Multicast anslutning misslyckades" +#define D_FAILED_TO_SEND_RESPONSE "Misslyckades skicka svar" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo standardhändelse" +#define D_WEMO_EVENT_SERVICE "WeMo händelsetjänst" +#define D_WEMO_META_SERVICE "WeMo metatjänst" +#define D_WEMO_SETUP "WeMo installation" +#define D_RESPONSE_SENT "Svar skickat" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue installation" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API inte implementerat" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 svarspaket skickade" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parametetrar" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Nyckel idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Fuk" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Fuk,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Spänning,Energi" + #define D_DOMOTICZ_ILLUMINANCE "Belysningsstyrka" + #define D_DOMOTICZ_COUNT "Antal/PM1" + #define D_DOMOTICZ_VOLTAGE "Volt/PM2.5" + #define D_DOMOTICZ_CURRENT "Ström/PM10" + #define D_DOMOTICZ_AIRQUALITY "Luftkvalitet" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Uppdatera timer" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Konfigurera timer" +#define D_TIMER_PARAMETERS "Timerparametrar" +#define D_TIMER_ENABLE "Aktivera timer" +#define D_TIMER_ARM "Aktivera" +#define D_TIMER_TIME "Tid" +#define D_TIMER_DAYS "Dagar" +#define D_TIMER_REPEAT "Repetera" +#define D_TIMER_OUTPUT "Utgång" +#define D_TIMER_ACTION "Åtgärd" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Konfigurera KNX" +#define D_KNX_PARAMETERS "KNX Parametrar" +#define D_KNX_GENERAL_CONFIG "Allmänt" +#define D_KNX_PHYSICAL_ADDRESS "Fysisk adress" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Måste vara unik på KNX-nätverket )" +#define D_KNX_ENABLE "Aktivera KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data att skicka till gruppadresser" +#define D_ADD "Lägg till" +#define D_DELETE "Ta bort" +#define D_REPLY "Svara" +#define D_KNX_GROUP_ADDRESS_TO_READ "Gruppadresser att ta emot data från" +#define D_RECEIVED_FROM "Mottagen från" +#define D_KNX_COMMAND_WRITE "Skriv" +#define D_KNX_COMMAND_READ "Läs" +#define D_KNX_COMMAND_OTHER "Andra" +#define D_SENT_TO "skickad till" +#define D_KNX_WARNING "Gruppadressen ( 0 / 0 / 0 ) är reserverad och kan inte användas." +#define D_KNX_ENHANCEMENT "Kommuniceringsförbättring" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energi idag" +#define D_ENERGY_YESTERDAY "Energi igår" +#define D_ENERGY_TOTAL "Energi totalt" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensor upptagen" +#define D_SENSOR_CRC_ERROR "Sensor CRC-fel" +#define D_SENSORS_FOUND "Sensorer hittades" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout under väntan" +#define D_START_SIGNAL_LOW "startsignal låg" +#define D_START_SIGNAL_HIGH "startsignal hög" +#define D_PULSE "puls" +#define D_CHECKSUM_FAILURE "Fel kontrollsumma" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor besvarade inte med ACK kommando" +#define D_SHT1X_FOUND "SHT1X hittades" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Partiklar" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axel" +#define D_AY_AXIS "Accel. Y-Axel" +#define D_AZ_AXIS "Accel. Z-Axel" +#define D_GX_AXIS "Gyro X-Axel" +#define D_GY_AXIS "Gyro Y-Axel" +#define D_GZ_AXIS "Gyro Z-Axel" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Ta bort vikter" +#define D_HX_CAL_REFERENCE "Ladda referensvikt" +#define D_HX_CAL_DONE "Kalibrerad" +#define D_HX_CAL_FAIL "Kalibrering misslyckad" +#define D_RESET_HX711 "Återställ våg" +#define D_CONFIGURE_HX711 "Konfigurera våg" +#define D_HX711_PARAMETERS "Vågparametrar" +#define D_ITEM_WEIGHT "Objektsvikt" +#define D_REFERENCE_WEIGHT "Referensvikt" +#define D_CALIBRATE "Kalibrera" +#define D_CALIBRATION "Kalibrering" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Vindriktning" +#define D_TX20_WIND_SPEED "Vindstyrka" +#define D_TX20_WIND_SPEED_AVG "Vindstyrka medel" +#define D_TX20_WIND_SPEED_MAX "Vindstyrka max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "Ö" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "V" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Ingen" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3-spelare" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Omkopplare" // Suffix "1" +#define D_SENSOR_BUTTON "Knapp" // Suffix "1" +#define D_SENSOR_RELAY "Relä" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Räknare" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Tim" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "ink" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sek" +#define D_UNIT_SECTORS "sektorer" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Fasvinkel" +#define D_IMPORT_ACTIVE "Import aktiv" +#define D_EXPORT_ACTIVE "Export aktiv" +#define D_IMPORT_REACTIVE "Import reaktiv" +#define D_EXPORT_REACTIVE "Export reaktiv" +#define D_TOTAL_REACTIVE "Total reaktiv" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_SV_SE_H_ diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 02f89c833..6bc48c40f 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -1,703 +1,701 @@ -/* - tr-TR.h - localization for Turkish - Turkey for Tasmota - - Copyright (C) 2019 Ali Sait Teke and Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_TR_TR_H_ -#define _LANGUAGE_TR_TR_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v6.1.1 -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1055 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "tr" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "." -#define D_MONTH_DAY_SEPARATOR "." -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "PazPztSalCarPerCumCmt" -#define D_MONTH3LIST "OckSubMarNisMayHazTemAguEylEkmKasAra" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Hava Kalitesi" -#define D_AP "AP" // Access Point -#define D_AS "as" -#define D_AUTO "OTOMATIK" -#define D_BLINK "Blink" -#define D_BLINKOFF "BlinkOff" -#define D_BOOT_COUNT "Yeniden başlama sayısı" -#define D_BRIGHTLIGHT "Işık" -#define D_BSSID "BSSId" -#define D_BUTTON "Buton" -#define D_BY "by" // Written by me -#define D_BYTES "Bayt" -#define D_CELSIUS "Derece" -#define D_CHANNEL "Channel" -#define D_CO2 "Karbon dioksit" -#define D_CODE "kod" // Button code -#define D_COLDLIGHT "Soğuk" -#define D_COMMAND "Komut" -#define D_CONNECTED "Bağlandı" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Sayı" -#define D_COUNTER "Sayaç" -#define D_CURRENT "Current" // As in Voltage and Current -#define D_DATA "Data" -#define D_DARKLIGHT "Karanlık" -#define D_DEBUG "Hata Ayıklama" -#define D_DISABLED "Etkin Değil" -#define D_DISTANCE "Mesage" -#define D_DNS_SERVER "DNS Sunucu" -#define D_DONE "Tamam" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "Emülasyon" -#define D_ENABLED "Etkin" -#define D_ERASE "Temizle" -#define D_ERROR "Hata" -#define D_FAHRENHEIT "Fahrenayt" -#define D_FAILED "Başlarısız" -#define D_FALLBACK "Geri iletim" -#define D_FALLBACK_TOPIC "Geri İletim Topiği" -#define D_FALSE "False" -#define D_FILE "Dosya" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "Boş Hafıza" -#define D_FREQUENCY "Frekans" -#define D_GAS "Gas" -#define D_GATEWAY "Geçit" -#define D_GROUP "Grup" -#define D_HOST "Host" -#define D_HOSTNAME "Host Adresi" -#define D_HUMIDITY "Nem" -#define D_ILLUMINANCE "Aydınlık" -#define D_IMMEDIATE "derhal" // Button immediate -#define D_INDEX "Index" -#define D_INFO "Bilgi" -#define D_INFRARED "Kızılötesi" -#define D_INITIALIZED "Başlatıldı" -#define D_IP_ADDRESS "IP Adresi" -#define D_LIGHT "Işık" -#define D_LWT "LWT" -#define D_MODULE "Modül" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "multi-press" -#define D_NOISE "Noise" -#define D_NONE "None" -#define D_OFF "Off" -#define D_OFFLINE "Çevirimdışı" -#define D_OK "Tamam" -#define D_ON "On" -#define D_ONLINE "Çevirimiçi" -#define D_PASSWORD "Şifre" -#define D_PORT "Port" -#define D_POWER_FACTOR "Güç Faktörü" -#define D_POWERUSAGE "Güç" -#define D_POWERUSAGE_ACTIVE "Aktif Güç" -#define D_POWERUSAGE_APPARENT "Görünen Güç" -#define D_POWERUSAGE_REACTIVE "Reaktif Güç" -#define D_PRESSURE "Basınç" -#define D_PRESSUREATSEALEVEL "Deniz Seviyesi Basıncı" -#define D_PROGRAM_FLASH_SIZE "Yazılım Flash Boyutu" -#define D_PROGRAM_SIZE "Yazılım Boyutu" -#define D_PROJECT "Proje" -#define D_RAIN "Rain" -#define D_RECEIVED "Alınan" -#define D_RESTART "Yeniden Başlat" -#define D_RESTARTING "Yeniden Başlatılıyor" -#define D_RESTART_REASON "Yeniden Başlatma Sebebi" -#define D_RESTORE "restore" -#define D_RETAINED "tutulan" -#define D_RULE "Kural" -#define D_SAVE "Kaydet" -#define D_SENSOR "Sensör" -#define D_SSID "SSId" -#define D_START "Başlat" -#define D_STD_TIME "STD" -#define D_STOP "Durdur" -#define D_SUBNET_MASK "Altağ Geçidi Maskesi" -#define D_SUBSCRIBE_TO "Abone olunan" -#define D_UNSUBSCRIBE_FROM "Unsubscribe from" -#define D_SUCCESSFUL "Başarıyla Tamamlandı" -#define D_SUNRISE "Gün doğumu" -#define D_SUNSET "Gün batımı" -#define D_TEMPERATURE "Sıcaklık" -#define D_TO "den" -#define D_TOGGLE "Geçiş Tuşu" -#define D_TOPIC "Başlık" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "İletim" -#define D_TRUE "True" -#define D_TVOC "TVOC" -#define D_UPGRADE "yükseltme" -#define D_UPLOAD "Yükleme" -#define D_UPTIME "Açık Kalma Süresi" -#define D_USER "Kullanıcı" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Indeksi" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "UV Seviyesi" -#define D_UV_POWER "UV Power" -#define D_VERSION "Versiyon" -#define D_VOLTAGE "Voltaj" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "Sıcak" -#define D_WEB_SERVER "Web Sunucusu" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "UYARI Bu versiyon ayarların kalıcı olarak kaydedilmesine olanak sağlamıyor" -#define D_LEVEL_10 "seviye 1-0" -#define D_LEVEL_01 "seviye 0-1" -#define D_SERIAL_LOGGING_DISABLED "Seri port loglaması kapalı" -#define D_SYSLOG_LOGGING_REENABLED "Sistem loglaması tekrar aktif" - -#define D_SET_BAUDRATE_TO "Baud hızını şu şekilde değiştir" -#define D_RECEIVED_TOPIC "Alınan Başlık" -#define D_DATA_SIZE "Veri Büyüklüğü" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Döngü bloke edildi" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" -#define D_ACTIVE_FOR_3_MINUTES "3 dakika aktif" -#define D_FAILED_TO_START "başlatma başarılı olamadı" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "AP'ye bağlan" -#define D_IN_MODE "modunda" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP adresi alınamadığı için bağlantı kurulamadı" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Ap'ye ulaşılamadı" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Girilen parolayı AP kabul etmedi" -#define D_CONNECT_FAILED_AP_TIMEOUT "AP'ye bağlanılırken süre aşımı oluştu" -#define D_ATTEMPTING_CONNECTION "Yeniden bağlanılıyor..." -#define D_CHECKING_CONNECTION "Bağlantı kontrol ediliyor..." -#define D_QUERY_DONE "Soru tamamlandı. MQTT servisleri bulundu" -#define D_MQTT_SERVICE_FOUND "Üzerinden MQTT serivisi tespit edildi" -#define D_FOUND_AT "(bulundu)" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog hostu bulunamadı" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Bellekten (Flash) kaydedidi:" -#define D_LOADED_FROM_FLASH_AT "Bellekten (Flash) okundu" -#define D_USE_DEFAULTS "Varsayılanları Kullan" -#define D_ERASED_SECTOR "Sektör temizlendi" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" -#define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif" -#define D_WITH_IP_ADDRESS "IP adres ile" -#define D_WEBSERVER_STOPPED "Web sunucusu durdu" -#define D_FILE_NOT_FOUND "Dosya Bulunamadı" -#define D_REDIRECTED "Portala yönlendirildiniz" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi yöneticisi AP olarak ayarlandı ve istasyon olarak bekletiliyor" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi yöneticisi AP olarak ayarlandı" -#define D_TRYING_TO_CONNECT "Cihaz ağa bağlanmaya çalışıyor" - -#define D_RESTART_IN "Burada tekrar başlat" -#define D_SECONDS "saniye" -#define D_DEVICE_WILL_RESTART "Birkaç saniye içerisinde cihaz tekrar başlatılacak" -#define D_BUTTON_TOGGLE "Toggle" -#define D_CONFIGURATION "Konfigürasyon" -#define D_INFORMATION "Bilgi" -#define D_FIRMWARE_UPGRADE "Cihaz yazılımını Güncelle" -#define D_CONSOLE "Konsol" -#define D_CONFIRM_RESTART "Yeniden Başlatmayı Onayla" - -#define D_CONFIGURE_MODULE "Modül Ayarlarını Değiştir" -#define D_CONFIGURE_WIFI "WiFi'i Ayarlarını Değiştir" -#define D_CONFIGURE_MQTT "MQTT'yi Ayarlarını Değiştir" -#define D_CONFIGURE_DOMOTICZ "Domoticz Ayarlarını Değiştir" -#define D_CONFIGURE_LOGGING "Loglama Ayarlarını Değiştir" -#define D_CONFIGURE_OTHER "Diğer Ayarları Değiştir" -#define D_CONFIRM_RESET_CONFIGURATION "Resetleme Ayarlarını Onayla" -#define D_RESET_CONFIGURATION "Tüm Ayarları Resetle" -#define D_BACKUP_CONFIGURATION "Ayarları Yedekle" -#define D_RESTORE_CONFIGURATION "Ayarları Geri Yükle" -#define D_MAIN_MENU "Ana Menü" - -#define D_MODULE_PARAMETERS "Modül parametreleri" -#define D_MODULE_TYPE "Modul türü" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial In" -#define D_SERIAL_OUT "Serial Out" - -#define D_WIFI_PARAMETERS "Wifi parametreleri" -#define D_SCAN_FOR_WIFI_NETWORKS "Çevredeki Wifi Networklerini Tara" -#define D_SCAN_DONE "Tarama tamamladı" -#define D_NO_NETWORKS_FOUND "Herhangi wifi ağı bulunamadı" -#define D_REFRESH_TO_SCAN_AGAIN "Tekrar tarama - yenile" -#define D_DUPLICATE_ACCESSPOINT "AP'yi çoğalt" -#define D_SKIPPING_LOW_QUALITY "Düşük kalitedekileri dikkate alma" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 Adı (SSId)" -#define D_AP1_PASSWORD "AP1 Parolası" -#define D_AP2_SSID "AP2 SSId" -#define D_AP2_PASSWORD "AP2 Parolası" - -#define D_MQTT_PARAMETERS "MQTT parametreleri" -#define D_CLIENT "İstemci" -#define D_FULL_TOPIC "Tüm Başlık" - -#define D_LOGGING_PARAMETERS "Loglama parametreleri" -#define D_SERIAL_LOG_LEVEL "Serial log seviyesi" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web log seviyesi" -#define D_SYS_LOG_LEVEL "Syslog seviyesi" -#define D_MORE_DEBUG "Hata ayıklama devamı" -#define D_SYSLOG_HOST "Syslog host" -#define D_SYSLOG_PORT "Syslog port" -#define D_TELEMETRY_PERIOD "Telemetri peryodu" - -#define D_OTHER_PARAMETERS "Diğer parametreler" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Web Yönetici Şifresi" -#define D_MQTT_ENABLE "MQTT aktif" -#define D_FRIENDLY_NAME "Kullanıcı Dostu İsim" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "tekli cihaz" -#define D_MULTI_DEVICE "çoklu cihaz" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "Ayarları Kaydet" -#define D_CONFIGURATION_SAVED "Ayarlar kaydedildi" -#define D_CONFIGURATION_RESET "Ayarlar resetlendi" - -#define D_PROGRAM_VERSION "Yazılım versiyonu" -#define D_BUILD_DATE_AND_TIME "Derleme Tarihi ve Saati" -#define D_CORE_AND_SDK_VERSION "Core/SDK Versiyonu" -#define D_FLASH_WRITE_COUNT "Belleğe (flash) Yazma Sayısı" -#define D_MAC_ADDRESS "MAC Adresi" -#define D_MQTT_HOST "MQTT Host" -#define D_MQTT_PORT "MQTT Port" -#define D_MQTT_CLIENT "MQTT İstemcisi" -#define D_MQTT_USER "MQTT Kullanıcısı" -#define D_MQTT_TOPIC "MQTT Topiği" -#define D_MQTT_GROUP_TOPIC "MQTT Grup Topiği" -#define D_MQTT_FULL_TOPIC "MQTT Full Topik" -#define D_MDNS_DISCOVERY "mDNS Keşfi" -#define D_MDNS_ADVERTISE "mDNS Yayını" -#define D_ESP_CHIP_ID "ESP Chip Id" -#define D_FLASH_CHIP_ID "Flash Chip Id" -#define D_FLASH_CHIP_SIZE "Flash Boyutu" -#define D_FREE_PROGRAM_SPACE "Boşta Yazılım Alanı Boyutu" - -#define D_UPGRADE_BY_WEBSERVER "Web server kullanarak yükselt" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Yükseltmeyi başlat" -#define D_UPGRADE_BY_FILE_UPLOAD "Dosya kullanrak yükset" -#define D_UPLOAD_STARTED "Yükleme başlatıldı" -#define D_UPGRADE_STARTED "YÜkestlme başlatıldı" -#define D_UPLOAD_DONE "Yükleme Tamamlandı" -#define D_UPLOAD_ERR_1 "Dosya seçilmedi" -#define D_UPLOAD_ERR_2 "Boş yer yok" -#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" -#define D_UPLOAD_ERR_4 "Yazılımın boyutu gerçek boyutundan fazla" -#define D_UPLOAD_ERR_5 "Upload buffer miscompare" -#define D_UPLOAD_ERR_6 "Yükleme başarısız. Enable logging 3" -#define D_UPLOAD_ERR_7 "Yükleme iptal edildi" -#define D_UPLOAD_ERR_8 "Geçersiz dosya" -#define D_UPLOAD_ERR_9 "File too large" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "Upload error code" - -#define D_ENTER_COMMAND "Komut girişi" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" -#define D_NEED_USER_AND_PASSWORD "Need user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Verify TLS fingerprint..." -#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" -#define D_RETRY_IN "Retry in" -#define D_VERIFIED "Verified using Fingerprint" -#define D_INSECURE "Insecure connection due to invalid Fingerprint" -#define D_CONNECT_FAILED_TO "Connect failed to" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast kapalı" -#define D_MULTICAST_REJOINED "Multicast (tekrar)bağlanıldı" -#define D_MULTICAST_JOIN_FAILED "Multicast bağlantısı başarısız" -#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo basic event" -#define D_WEMO_EVENT_SERVICE "WeMo event service" -#define D_WEMO_META_SERVICE "WeMo meta service" -#define D_WEMO_SETUP "WeMo setup" -#define D_RESPONSE_SENT "Response sent" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue kurulumu" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API'si entegre edilmedi" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST argümanları" -#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "Switch idx" -#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" - #define D_DOMOTICZ_TEMP "Temp" - #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" - #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" - #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" - #define D_DOMOTICZ_ILLUMINANCE "Illuminance" - #define D_DOMOTICZ_COUNT "Count/PM1" - #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" - #define D_DOMOTICZ_CURRENT "Current/PM10" - #define D_DOMOTICZ_AIRQUALITY "AirQuality" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Zamanlayıcıyı güncelle" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Zamanlayıcı Ayarları" -#define D_TIMER_PARAMETERS "Zamanlayıcı Parametreleri" -#define D_TIMER_ENABLE "Zamanlayıcı Aktif" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Zaman" -#define D_TIMER_DAYS "Gün" -#define D_TIMER_REPEAT "Tekrar" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX Ayarları" -#define D_KNX_PARAMETERS "KNX Parametreleri" -#define D_KNX_GENERAL_CONFIG "Genel Ayarlar" -#define D_KNX_PHYSICAL_ADDRESS "Fiziksel Addres" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "KNX Aktif" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Ekle" -#define D_DELETE "Sil" -#define D_REPLY "Cevapla" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Yaz" -#define D_KNX_COMMAND_READ "Oku" -#define D_KNX_COMMAND_OTHER "Diğer" -#define D_SENT_TO "gönder" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Energy Today" -#define D_ENERGY_YESTERDAY "Energy Yesterday" -#define D_ENERGY_TOTAL "Energy Total" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Sensör başgül" -#define D_SENSOR_CRC_ERROR "Sensor CRC hatası" -#define D_SENSORS_FOUND "Sensörler bulundu" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" -#define D_START_SIGNAL_LOW "düşük sinyal başlat" -#define D_START_SIGNAL_HIGH "yüksek sinyal başlat" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "Checksum failure" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" -#define D_SHT1X_FOUND "SHT1X found" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Particals" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "A" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "Hr" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "kOhm" -#define D_UNIT_KILOWATTHOUR "kWh" -#define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" -#define D_UNIT_MICROMETER "um" -#define D_UNIT_MICROSECOND "us" -#define D_UNIT_MILLIAMPERE "mA" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "ms" -#define D_UNIT_MINUTE "Min" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "hPa" -#define D_UNIT_SECOND "sec" -#define D_UNIT_SECTORS "sectors" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "V" -#define D_UNIT_WATT "W" -#define D_UNIT_WATTHOUR "Wh" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_TR_TR_H_ +/* + tr-TR.h - localization for Turkish - Turkey for Tasmota + + Copyright (C) 2019 Ali Sait Teke and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_TR_TR_H_ +#define _LANGUAGE_TR_TR_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v6.1.1 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1055 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "tr" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "." +#define D_MONTH_DAY_SEPARATOR "." +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "PazPztSalCarPerCumCmt" +#define D_MONTH3LIST "OckSubMarNisMayHazTemAguEylEkmKasAra" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Hava Kalitesi" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "OTOMATIK" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Yeniden başlama sayısı" +#define D_BRIGHTLIGHT "Işık" +#define D_BSSID "BSSId" +#define D_BUTTON "Buton" +#define D_BY "by" // Written by me +#define D_BYTES "Bayt" +#define D_CELSIUS "Derece" +#define D_CHANNEL "Channel" +#define D_CO2 "Karbon dioksit" +#define D_CODE "kod" // Button code +#define D_COLDLIGHT "Soğuk" +#define D_COMMAND "Komut" +#define D_CONNECTED "Bağlandı" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Sayı" +#define D_COUNTER "Sayaç" +#define D_CURRENT "Current" // As in Voltage and Current +#define D_DATA "Data" +#define D_DARKLIGHT "Karanlık" +#define D_DEBUG "Hata Ayıklama" +#define D_DISABLED "Etkin Değil" +#define D_DISTANCE "Mesage" +#define D_DNS_SERVER "DNS Sunucu" +#define D_DONE "Tamam" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "Emülasyon" +#define D_ENABLED "Etkin" +#define D_ERASE "Temizle" +#define D_ERROR "Hata" +#define D_FAHRENHEIT "Fahrenayt" +#define D_FAILED "Başlarısız" +#define D_FALLBACK "Geri iletim" +#define D_FALLBACK_TOPIC "Geri İletim Topiği" +#define D_FALSE "False" +#define D_FILE "Dosya" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "Boş Hafıza" +#define D_FREQUENCY "Frekans" +#define D_GAS "Gas" +#define D_GATEWAY "Geçit" +#define D_GROUP "Grup" +#define D_HOST "Host" +#define D_HOSTNAME "Host Adresi" +#define D_HUMIDITY "Nem" +#define D_ILLUMINANCE "Aydınlık" +#define D_IMMEDIATE "derhal" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Bilgi" +#define D_INFRARED "Kızılötesi" +#define D_INITIALIZED "Başlatıldı" +#define D_IP_ADDRESS "IP Adresi" +#define D_LIGHT "Işık" +#define D_LWT "LWT" +#define D_MODULE "Modül" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "multi-press" +#define D_NOISE "Noise" +#define D_NONE "None" +#define D_OFF "Off" +#define D_OFFLINE "Çevirimdışı" +#define D_OK "Tamam" +#define D_ON "On" +#define D_ONLINE "Çevirimiçi" +#define D_PASSWORD "Şifre" +#define D_PORT "Port" +#define D_POWER_FACTOR "Güç Faktörü" +#define D_POWERUSAGE "Güç" +#define D_POWERUSAGE_ACTIVE "Aktif Güç" +#define D_POWERUSAGE_APPARENT "Görünen Güç" +#define D_POWERUSAGE_REACTIVE "Reaktif Güç" +#define D_PRESSURE "Basınç" +#define D_PRESSUREATSEALEVEL "Deniz Seviyesi Basıncı" +#define D_PROGRAM_FLASH_SIZE "Yazılım Flash Boyutu" +#define D_PROGRAM_SIZE "Yazılım Boyutu" +#define D_PROJECT "Proje" +#define D_RAIN "Rain" +#define D_RECEIVED "Alınan" +#define D_RESTART "Yeniden Başlat" +#define D_RESTARTING "Yeniden Başlatılıyor" +#define D_RESTART_REASON "Yeniden Başlatma Sebebi" +#define D_RESTORE "restore" +#define D_RETAINED "tutulan" +#define D_RULE "Kural" +#define D_SAVE "Kaydet" +#define D_SENSOR "Sensör" +#define D_SSID "SSId" +#define D_START "Başlat" +#define D_STD_TIME "STD" +#define D_STOP "Durdur" +#define D_SUBNET_MASK "Altağ Geçidi Maskesi" +#define D_SUBSCRIBE_TO "Abone olunan" +#define D_UNSUBSCRIBE_FROM "Unsubscribe from" +#define D_SUCCESSFUL "Başarıyla Tamamlandı" +#define D_SUNRISE "Gün doğumu" +#define D_SUNSET "Gün batımı" +#define D_TEMPERATURE "Sıcaklık" +#define D_TO "den" +#define D_TOGGLE "Geçiş Tuşu" +#define D_TOPIC "Başlık" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "İletim" +#define D_TRUE "True" +#define D_TVOC "TVOC" +#define D_UPGRADE "yükseltme" +#define D_UPLOAD "Yükleme" +#define D_UPTIME "Açık Kalma Süresi" +#define D_USER "Kullanıcı" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Indeksi" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "UV Seviyesi" +#define D_UV_POWER "UV Power" +#define D_VERSION "Versiyon" +#define D_VOLTAGE "Voltaj" +#define D_WEIGHT "Weight" +#define D_WARMLIGHT "Sıcak" +#define D_WEB_SERVER "Web Sunucusu" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "UYARI Bu versiyon ayarların kalıcı olarak kaydedilmesine olanak sağlamıyor" +#define D_LEVEL_10 "seviye 1-0" +#define D_LEVEL_01 "seviye 0-1" +#define D_SERIAL_LOGGING_DISABLED "Seri port loglaması kapalı" +#define D_SYSLOG_LOGGING_REENABLED "Sistem loglaması tekrar aktif" + +#define D_SET_BAUDRATE_TO "Baud hızını şu şekilde değiştir" +#define D_RECEIVED_TOPIC "Alınan Başlık" +#define D_DATA_SIZE "Veri Büyüklüğü" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Döngü bloke edildi" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" +#define D_ACTIVE_FOR_3_MINUTES "3 dakika aktif" +#define D_FAILED_TO_START "başlatma başarılı olamadı" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "AP'ye bağlan" +#define D_IN_MODE "modunda" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP adresi alınamadığı için bağlantı kurulamadı" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Ap'ye ulaşılamadı" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Girilen parolayı AP kabul etmedi" +#define D_CONNECT_FAILED_AP_TIMEOUT "AP'ye bağlanılırken süre aşımı oluştu" +#define D_ATTEMPTING_CONNECTION "Yeniden bağlanılıyor..." +#define D_CHECKING_CONNECTION "Bağlantı kontrol ediliyor..." +#define D_QUERY_DONE "Soru tamamlandı. MQTT servisleri bulundu" +#define D_MQTT_SERVICE_FOUND "Üzerinden MQTT serivisi tespit edildi" +#define D_FOUND_AT "(bulundu)" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog hostu bulunamadı" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Bellekten (Flash) kaydedidi:" +#define D_LOADED_FROM_FLASH_AT "Bellekten (Flash) okundu" +#define D_USE_DEFAULTS "Varsayılanları Kullan" +#define D_ERASED_SECTOR "Sektör temizlendi" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük
lütfen yükseltin" +#define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif" +#define D_WITH_IP_ADDRESS "IP adres ile" +#define D_WEBSERVER_STOPPED "Web sunucusu durdu" +#define D_FILE_NOT_FOUND "Dosya Bulunamadı" +#define D_REDIRECTED "Portala yönlendirildiniz" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi yöneticisi AP olarak ayarlandı ve istasyon olarak bekletiliyor" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi yöneticisi AP olarak ayarlandı" +#define D_TRYING_TO_CONNECT "Cihaz ağa bağlanmaya çalışıyor" + +#define D_RESTART_IN "Burada tekrar başlat" +#define D_SECONDS "saniye" +#define D_DEVICE_WILL_RESTART "Birkaç saniye içerisinde cihaz tekrar başlatılacak" +#define D_BUTTON_TOGGLE "Toggle" +#define D_CONFIGURATION "Konfigürasyon" +#define D_INFORMATION "Bilgi" +#define D_FIRMWARE_UPGRADE "Cihaz yazılımını Güncelle" +#define D_CONSOLE "Konsol" +#define D_CONFIRM_RESTART "Yeniden Başlatmayı Onayla" + +#define D_CONFIGURE_MODULE "Modül Ayarlarını Değiştir" +#define D_CONFIGURE_WIFI "WiFi'i Ayarlarını Değiştir" +#define D_CONFIGURE_MQTT "MQTT'yi Ayarlarını Değiştir" +#define D_CONFIGURE_DOMOTICZ "Domoticz Ayarlarını Değiştir" +#define D_CONFIGURE_LOGGING "Loglama Ayarlarını Değiştir" +#define D_CONFIGURE_OTHER "Diğer Ayarları Değiştir" +#define D_CONFIRM_RESET_CONFIGURATION "Resetleme Ayarlarını Onayla" +#define D_RESET_CONFIGURATION "Tüm Ayarları Resetle" +#define D_BACKUP_CONFIGURATION "Ayarları Yedekle" +#define D_RESTORE_CONFIGURATION "Ayarları Geri Yükle" +#define D_MAIN_MENU "Ana Menü" + +#define D_MODULE_PARAMETERS "Modül parametreleri" +#define D_MODULE_TYPE "Modul türü" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial In" +#define D_SERIAL_OUT "Serial Out" + +#define D_WIFI_PARAMETERS "Wifi parametreleri" +#define D_SCAN_FOR_WIFI_NETWORKS "Çevredeki Wifi Networklerini Tara" +#define D_SCAN_DONE "Tarama tamamladı" +#define D_NO_NETWORKS_FOUND "Herhangi wifi ağı bulunamadı" +#define D_REFRESH_TO_SCAN_AGAIN "Tekrar tarama - yenile" +#define D_DUPLICATE_ACCESSPOINT "AP'yi çoğalt" +#define D_SKIPPING_LOW_QUALITY "Düşük kalitedekileri dikkate alma" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 Adı (SSId)" +#define D_AP1_PASSWORD "AP1 Parolası" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "AP2 Parolası" + +#define D_MQTT_PARAMETERS "MQTT parametreleri" +#define D_CLIENT "İstemci" +#define D_FULL_TOPIC "Tüm Başlık" + +#define D_LOGGING_PARAMETERS "Loglama parametreleri" +#define D_SERIAL_LOG_LEVEL "Serial log seviyesi" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web log seviyesi" +#define D_SYS_LOG_LEVEL "Syslog seviyesi" +#define D_MORE_DEBUG "Hata ayıklama devamı" +#define D_SYSLOG_HOST "Syslog host" +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Telemetri peryodu" + +#define D_OTHER_PARAMETERS "Diğer parametreler" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Web Yönetici Şifresi" +#define D_MQTT_ENABLE "MQTT aktif" +#define D_FRIENDLY_NAME "Kullanıcı Dostu İsim" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "tekli cihaz" +#define D_MULTI_DEVICE "çoklu cihaz" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "Ayarları Kaydet" +#define D_CONFIGURATION_SAVED "Ayarlar kaydedildi" +#define D_CONFIGURATION_RESET "Ayarlar resetlendi" + +#define D_PROGRAM_VERSION "Yazılım versiyonu" +#define D_BUILD_DATE_AND_TIME "Derleme Tarihi ve Saati" +#define D_CORE_AND_SDK_VERSION "Core/SDK Versiyonu" +#define D_FLASH_WRITE_COUNT "Belleğe (flash) Yazma Sayısı" +#define D_MAC_ADDRESS "MAC Adresi" +#define D_MQTT_HOST "MQTT Host" +#define D_MQTT_PORT "MQTT Port" +#define D_MQTT_CLIENT "MQTT İstemcisi" +#define D_MQTT_USER "MQTT Kullanıcısı" +#define D_MQTT_TOPIC "MQTT Topiği" +#define D_MQTT_GROUP_TOPIC "MQTT Grup Topiği" +#define D_MQTT_FULL_TOPIC "MQTT Full Topik" +#define D_MDNS_DISCOVERY "mDNS Keşfi" +#define D_MDNS_ADVERTISE "mDNS Yayını" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Flash Boyutu" +#define D_FREE_PROGRAM_SPACE "Boşta Yazılım Alanı Boyutu" + +#define D_UPGRADE_BY_WEBSERVER "Web server kullanarak yükselt" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Yükseltmeyi başlat" +#define D_UPGRADE_BY_FILE_UPLOAD "Dosya kullanrak yükset" +#define D_UPLOAD_STARTED "Yükleme başlatıldı" +#define D_UPGRADE_STARTED "YÜkestlme başlatıldı" +#define D_UPLOAD_DONE "Yükleme Tamamlandı" +#define D_UPLOAD_ERR_1 "Dosya seçilmedi" +#define D_UPLOAD_ERR_2 "Boş yer yok" +#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9" +#define D_UPLOAD_ERR_4 "Yazılımın boyutu gerçek boyutundan fazla" +#define D_UPLOAD_ERR_5 "Upload buffer miscompare" +#define D_UPLOAD_ERR_6 "Yükleme başarısız. Enable logging 3" +#define D_UPLOAD_ERR_7 "Yükleme iptal edildi" +#define D_UPLOAD_ERR_8 "Geçersiz dosya" +#define D_UPLOAD_ERR_9 "File too large" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "Upload error code" + +#define D_ENTER_COMMAND "Komut girişi" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected" +#define D_NEED_USER_AND_PASSWORD "Need user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verify TLS fingerprint..." +#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to" +#define D_RETRY_IN "Retry in" +#define D_VERIFIED "Verified using Fingerprint" +#define D_INSECURE "Insecure connection due to invalid Fingerprint" +#define D_CONNECT_FAILED_TO "Connect failed to" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast kapalı" +#define D_MULTICAST_REJOINED "Multicast (tekrar)bağlanıldı" +#define D_MULTICAST_JOIN_FAILED "Multicast bağlantısı başarısız" +#define D_FAILED_TO_SEND_RESPONSE "Failed to send response" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo basic event" +#define D_WEMO_EVENT_SERVICE "WeMo event service" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "WeMo setup" +#define D_RESPONSE_SENT "Response sent" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue kurulumu" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API'si entegre edilmedi" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST argümanları" +#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz parameters" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Switch idx" +#define D_DOMOTICZ_SENSOR_IDX "Sensor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,Hum" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Power,Energy" + #define D_DOMOTICZ_ILLUMINANCE "Illuminance" + #define D_DOMOTICZ_COUNT "Count/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5" + #define D_DOMOTICZ_CURRENT "Current/PM10" + #define D_DOMOTICZ_AIRQUALITY "AirQuality" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Zamanlayıcıyı güncelle" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Zamanlayıcı Ayarları" +#define D_TIMER_PARAMETERS "Zamanlayıcı Parametreleri" +#define D_TIMER_ENABLE "Zamanlayıcı Aktif" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Zaman" +#define D_TIMER_DAYS "Gün" +#define D_TIMER_REPEAT "Tekrar" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX Ayarları" +#define D_KNX_PARAMETERS "KNX Parametreleri" +#define D_KNX_GENERAL_CONFIG "Genel Ayarlar" +#define D_KNX_PHYSICAL_ADDRESS "Fiziksel Addres" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "KNX Aktif" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Ekle" +#define D_DELETE "Sil" +#define D_REPLY "Cevapla" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Yaz" +#define D_KNX_COMMAND_READ "Oku" +#define D_KNX_COMMAND_OTHER "Diğer" +#define D_SENT_TO "gönder" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energy Today" +#define D_ENERGY_YESTERDAY "Energy Yesterday" +#define D_ENERGY_TOTAL "Energy Total" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Sensör başgül" +#define D_SENSOR_CRC_ERROR "Sensor CRC hatası" +#define D_SENSORS_FOUND "Sensörler bulundu" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timeout waiting for" +#define D_START_SIGNAL_LOW "düşük sinyal başlat" +#define D_START_SIGNAL_HIGH "yüksek sinyal başlat" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "Checksum failure" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command" +#define D_SHT1X_FOUND "SHT1X found" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particals" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kOhm" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3" +#define D_UNIT_MICROMETER "um" +#define D_UNIT_MICROSECOND "us" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_TR_TR_H_ diff --git a/tasmota/language/uk-UK.h b/tasmota/language/uk-UK.h index 98f87e932..b4a314630 100644 --- a/tasmota/language/uk-UK.h +++ b/tasmota/language/uk-UK.h @@ -1,703 +1,701 @@ -/* - uk-UK.h - localization for Ukrainian - Ukraine for Tasmota - - Copyright (C) 2019 Theo Arends / vadym-adik - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_UK_UK_H_ -#define _LANGUAGE_UK_UK_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.14.0a -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1058 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "uk" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "НедПонВівСерЧетПятСуб" -#define D_MONTH3LIST "СічЛютБерКвіТраЧерЛипСерВерЖовЛисГру" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "," - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "Якість повітря" -#define D_AP "Точка доступу" // Access Point -#define D_AS "як" -#define D_AUTO "АВТО" -#define D_BLINK "Блимати" -#define D_BLINKOFF "Не блимати" -#define D_BOOT_COUNT "К-сть завант." -#define D_BRIGHTLIGHT "Яскравість" -#define D_BSSID "BSSId" -#define D_BUTTON "Кнопка" -#define D_BY " " // Written by me -#define D_BYTES "Байт" -#define D_CELSIUS "Цельсія" -#define D_CHANNEL "Канал" -#define D_CO2 "Вуглек. газ" -#define D_CODE "код" // Button code -#define D_COLDLIGHT "Холодний" -#define D_COMMAND "Команда" -#define D_CONNECTED "Під'єднано" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Розмір" -#define D_COUNTER "Лічильник" -#define D_CURRENT "Струм" // As in Voltage and Current -#define D_DATA "Дані" -#define D_DARKLIGHT "Темний" -#define D_DEBUG "Налагодження" -#define D_DISABLED "Заблоковано" -#define D_DISTANCE "Відстань" -#define D_DNS_SERVER "Сервер DNS" -#define D_DONE "Виконано" -#define D_DST_TIME "Літній час" -#define D_ECO2 "eCO2" -#define D_EMULATION "Емуляція" -#define D_ENABLED "Активно" -#define D_ERASE "Стирати" -#define D_ERROR "Помилка" -#define D_FAHRENHEIT "Фаренгейт" -#define D_FAILED "Невдало" -#define D_FALLBACK "Зворотній зв'язок" -#define D_FALLBACK_TOPIC "Топік зворотнього зв'язку" -#define D_FALSE "Ні" -#define D_FILE "Файл" -#define D_FLOW_RATE "Потік" -#define D_FREE_MEMORY "Вільна память" -#define D_FREQUENCY "Частота" -#define D_GAS "Газ" -#define D_GATEWAY "Шлюз" -#define D_GROUP "Група" -#define D_HOST "Хост" -#define D_HOSTNAME "Назва хосту" -#define D_HUMIDITY "Вологість" -#define D_ILLUMINANCE "Освітленність" -#define D_IMMEDIATE "Негайно" // Button immediate -#define D_INDEX "Індекс" -#define D_INFO "Інфо" -#define D_INFRARED "Інфрачервоний" -#define D_INITIALIZED "Ініціалізовано" -#define D_IP_ADDRESS "IP адреса" -#define D_LIGHT "Світло" -#define D_LWT "LWT" -#define D_MODULE "Модуль" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "Багаторазове натискання" -#define D_NOISE "Шум" -#define D_NONE "Нічого" -#define D_OFF "Вимк." -#define D_OFFLINE "Офф-лайн" -#define D_OK "Ок" -#define D_ON "Увімк." -#define D_ONLINE "Он-лайн" -#define D_PASSWORD "Гасло" -#define D_PORT "Порт" -#define D_POWER_FACTOR "Коефіцієнт потужності" -#define D_POWERUSAGE "Потужність" -#define D_POWERUSAGE_ACTIVE "Активна потужність" -#define D_POWERUSAGE_APPARENT "Дійсна потужність" -#define D_POWERUSAGE_REACTIVE "Реактивна потужність" -#define D_PRESSURE "Тиск" -#define D_PRESSUREATSEALEVEL "Тиск на рівні моря" -#define D_PROGRAM_FLASH_SIZE "Розмір Flash для програм" -#define D_PROGRAM_SIZE "Розмір програм" -#define D_PROJECT "Проект" -#define D_RAIN "Дощ" -#define D_RECEIVED "Отримано" -#define D_RESTART "Перезавантаження" -#define D_RESTARTING "Перезавантаження" -#define D_RESTART_REASON "Причина перезавантаження" -#define D_RESTORE "відновлення" -#define D_RETAINED "зберігати" -#define D_RULE "Правило" -#define D_SAVE "Зберегти" -#define D_SENSOR "Давач" -#define D_SSID "SSID" -#define D_START "Старт" -#define D_STD_TIME "Стандартний час" -#define D_STOP "Стоп" -#define D_SUBNET_MASK "Маска підмережі" -#define D_SUBSCRIBE_TO "Підписатись на" -#define D_UNSUBSCRIBE_FROM "Відписатися від" -#define D_SUCCESSFUL "Успішно" -#define D_SUNRISE "Схід сонця" -#define D_SUNSET "Захід сонця" -#define D_TEMPERATURE "Температура" -#define D_TO "до" -#define D_TOGGLE "Перекл." -#define D_TOPIC "Топік" -#define D_TOTAL_USAGE "Загальне споживання" -#define D_TRANSMIT "Передати" -#define D_TRUE "Так" -#define D_TVOC "TVOC" -#define D_UPGRADE "оновлення" -#define D_UPLOAD "Завантажити" -#define D_UPTIME "Час роботи" -#define D_USER "Користувач" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "Індекс УФ" -#define D_UV_INDEX_1 "Низький" -#define D_UV_INDEX_2 "Середній" -#define D_UV_INDEX_3 "Високий" -#define D_UV_INDEX_4 "Небезпечний" -#define D_UV_INDEX_5 "Опіки 1/2 ступеня" -#define D_UV_INDEX_6 "Опіки 3 ступеня" -#define D_UV_INDEX_7 "Невідомий" -#define D_UV_LEVEL "Рівень УФ" -#define D_UV_POWER "Потужність УФ" -#define D_VERSION "Версія" -#define D_VOLTAGE "Напруга" -#define D_WEIGHT "Вага" -#define D_WARMLIGHT "Тепло" -#define D_WEB_SERVER "Web сервер" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "ПОПЕРЕДЖЕННЯ! Ця версія не підтримує збереження налаштувань" -#define D_LEVEL_10 "рівень 1-0" -#define D_LEVEL_01 "рівень 0-1" -#define D_SERIAL_LOGGING_DISABLED "Serial журнал вимкнений" -#define D_SYSLOG_LOGGING_REENABLED "Syslog журнал увімкнений" - -#define D_SET_BAUDRATE_TO "Встановити швидкість передачі (Baudrate)" -#define D_RECEIVED_TOPIC "Отриманий Топік" -#define D_DATA_SIZE "Розмір даних" -#define D_ANALOG_INPUT "Напруга" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Цикл заблокований" -#define D_WPS_FAILED_WITH_STATUS "WPS конфігурація з статусом НЕВДАЛА" -#define D_ACTIVE_FOR_3_MINUTES "активний протягом 3 хвилин" -#define D_FAILED_TO_START "не вдалось запустити" -#define D_PATCH_ISSUE_2186 "Проблема з виправленням 2186" -#define D_CONNECTING_TO_AP "Підключення до AP" -#define D_IN_MODE "в режимі" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "Помилка підключення, IP-адреса не отримана" -#define D_CONNECT_FAILED_AP_NOT_REACHED "Помилка з'єднання, AP не знайдено" -#define D_CONNECT_FAILED_WRONG_PASSWORD "Помилка з'єднання, невірне гасло до AP" -#define D_CONNECT_FAILED_AP_TIMEOUT "Помилка з'єднання з AP по тайм-ауту" -#define D_ATTEMPTING_CONNECTION "Спроба підключення..." -#define D_CHECKING_CONNECTION "Перевірка з'єднання..." -#define D_QUERY_DONE "Запит виконаний. Виявлено сервер MQTT" -#define D_MQTT_SERVICE_FOUND "MQTT сервер знайдено" -#define D_FOUND_AT "знайдено в" -#define D_SYSLOG_HOST_NOT_FOUND "Сервер журналу не знайдено" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "Збережено в флэш-пам'ять" -#define D_LOADED_FROM_FLASH_AT "Завантажено з флэш-пам'яті" -#define D_USE_DEFAULTS "Використовувати значення за замовчуванням" -#define D_ERASED_SECTOR "Стерто сектор" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "Для використання Tasmota треба увімкнути JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" -#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активний" -#define D_WITH_IP_ADDRESS "з IP-адресою" -#define D_WEBSERVER_STOPPED "Веб-сервер зупинений" -#define D_FILE_NOT_FOUND "Файл не знайдений" -#define D_REDIRECTED "Перенаправлено на адаптивний портал" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер встановлює Точку Доступу і зберігає параметри" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер встановив Точку Доступу" -#define D_TRYING_TO_CONNECT "Спроба підключення пристрою до мережі" - -#define D_RESTART_IN "Перезавантаження" -#define D_SECONDS "секунд" -#define D_DEVICE_WILL_RESTART "Пристрій буде перезавантажено через декілька секунд" -#define D_BUTTON_TOGGLE "Переключити" -#define D_CONFIGURATION "Конфігурація" -#define D_INFORMATION "Інформація" -#define D_FIRMWARE_UPGRADE "Оновлення прошивки" -#define D_CONSOLE "Консоль" -#define D_CONFIRM_RESTART "Підтвердити перезавантаження" - -#define D_CONFIGURE_MODULE "Конфігурація модуля" -#define D_CONFIGURE_WIFI "Конфігурація WiFi" -#define D_CONFIGURE_MQTT "Конфігурація MQTT" -#define D_CONFIGURE_DOMOTICZ "Конфігурація Domoticz" -#define D_CONFIGURE_LOGGING "Конфігурація журналів" -#define D_CONFIGURE_OTHER "Конфігурація інше" -#define D_CONFIRM_RESET_CONFIGURATION "Підтвердити скидання конфігурації" -#define D_RESET_CONFIGURATION "Скидання конфігурації" -#define D_BACKUP_CONFIGURATION "Резервне копіювання конфігурації" -#define D_RESTORE_CONFIGURATION "Відновлення конфігурації" -#define D_MAIN_MENU "Головне меню" - -#define D_MODULE_PARAMETERS "Параметри модуля" -#define D_MODULE_TYPE "Тип модуля" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "АЦП" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "Serial вхід" -#define D_SERIAL_OUT "Serial вихід" - -#define D_WIFI_PARAMETERS "Параметри Wifi" -#define D_SCAN_FOR_WIFI_NETWORKS "Сканування бездротовихих мереж Wifi" -#define D_SCAN_DONE "Сканування завершене" -#define D_NO_NETWORKS_FOUND "Не знайдено мереж" -#define D_REFRESH_TO_SCAN_AGAIN "Оновити для повторного сканування" -#define D_DUPLICATE_ACCESSPOINT "Дублювати Точку Доступу (AP)" -#define D_SKIPPING_LOW_QUALITY "Пропущено через низьку якість" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 SSID" -#define D_AP1_PASSWORD "AP1 гасло" -#define D_AP2_SSID "AP2 SSID" -#define D_AP2_PASSWORD "AP2 гасло" - -#define D_MQTT_PARAMETERS "Параметри MQTT" -#define D_CLIENT "Клієнт" -#define D_FULL_TOPIC "Повний Топік" - -#define D_LOGGING_PARAMETERS "Параметри журналу" -#define D_SERIAL_LOG_LEVEL "Serial рівень" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web рівень" -#define D_SYS_LOG_LEVEL "System рівень" -#define D_MORE_DEBUG "Додаткова інформація для налагодження" -#define D_SYSLOG_HOST "System хост" -#define D_SYSLOG_PORT "System порт" -#define D_TELEMETRY_PERIOD "Період телеметрії" - -#define D_OTHER_PARAMETERS "Параметри Інше" -#define D_TEMPLATE "Шаблони" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Гасло Web адміністратора" -#define D_MQTT_ENABLE "MQTT активний" -#define D_FRIENDLY_NAME "Дружнє Ім'я" -#define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "одиночне" -#define D_MULTI_DEVICE "мульти" - -#define D_CONFIGURE_TEMPLATE "Конфігурація шаблона" -#define D_TEMPLATE_PARAMETERS "Параметри шаблона" -#define D_TEMPLATE_NAME "Назва" -#define D_BASE_TYPE "На основі" -#define D_TEMPLATE_FLAGS "Опції" - -#define D_SAVE_CONFIGURATION "Зберегти конфігурацію" -#define D_CONFIGURATION_SAVED "Конфігурація збережена " -#define D_CONFIGURATION_RESET "Конфігурація скинута" - -#define D_PROGRAM_VERSION "Версія програми" -#define D_BUILD_DATE_AND_TIME "Дата і час збірки" -#define D_CORE_AND_SDK_VERSION "Версія Core/SDK" -#define D_FLASH_WRITE_COUNT "Кількість записів Flash" -#define D_MAC_ADDRESS "MAC Адреса" -#define D_MQTT_HOST "MQTT Хост" -#define D_MQTT_PORT "MQTT Порт" -#define D_MQTT_CLIENT "MQTT ID Клієнта" -#define D_MQTT_USER "MQTT Користувач" -#define D_MQTT_TOPIC "MQTT Топік" -#define D_MQTT_GROUP_TOPIC "MQTT Топік групи" -#define D_MQTT_FULL_TOPIC "MQTT Топік повний" -#define D_MDNS_DISCOVERY "mDNS Виявлення" -#define D_MDNS_ADVERTISE "mDNS Транcляція" -#define D_ESP_CHIP_ID "ID чипу ESP" -#define D_FLASH_CHIP_ID "ID чипу Flash пам'яті" -#define D_FLASH_CHIP_SIZE "Розмір Flash пам'яті" -#define D_FREE_PROGRAM_SPACE "Вільний простір для програм" - -#define D_UPGRADE_BY_WEBSERVER "Оновлення через Веб-сервер" -#define D_OTA_URL "OTA Url" -#define D_START_UPGRADE "Почати оновлення" -#define D_UPGRADE_BY_FILE_UPLOAD "Оновлення шляхом завантаження файлів" -#define D_UPLOAD_STARTED "Завантаження почалось" -#define D_UPGRADE_STARTED "Оновлення почалось" -#define D_UPLOAD_DONE "Завантаження завершено" -#define D_UPLOAD_ERR_1 "Файл не вибраний" -#define D_UPLOAD_ERR_2 "Недостатньо місця" -#define D_UPLOAD_ERR_3 "Магічний байт не 0xE9" -#define D_UPLOAD_ERR_4 "Размір прошивки більший, ніж размір Flash пам'яті" -#define D_UPLOAD_ERR_5 "Помилка завантаження буферу" -#define D_UPLOAD_ERR_6 "Помилка завантаження. Увімкнено лог рівень 3" -#define D_UPLOAD_ERR_7 "Завантаження перервано" -#define D_UPLOAD_ERR_8 "Файл невірний" -#define D_UPLOAD_ERR_9 "Занадто великий файл" -#define D_UPLOAD_ERR_10 "Помилка ініціалізаціції чипу FR" -#define D_UPLOAD_ERR_11 "Помилка стирання чипу RF" -#define D_UPLOAD_ERR_12 "Помилка запису чипу RF" -#define D_UPLOAD_ERR_13 "Помилка розкодування прошивки RF" -#define D_UPLOAD_ERROR_CODE "Код помилки завантаження" - -#define D_ENTER_COMMAND "Уведіть команду" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "Увімкніть Веб лог рівня 2 якщо очікуєте відповідь" -#define D_NEED_USER_AND_PASSWORD "Очікується user=&password=" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "Перевірка відбитка TLS..." -#define D_TLS_CONNECT_FAILED_TO "Збій підключення TLS до" -#define D_RETRY_IN "Повторити" -#define D_VERIFIED "Перевірено відбиток" -#define D_INSECURE "Небезпечне з'єднання, недійсний відбиток" -#define D_CONNECT_FAILED_TO "Помилка підключення до" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "Multicast вимкнений" -#define D_MULTICAST_REJOINED "Multicast (пере)під'єднався" -#define D_MULTICAST_JOIN_FAILED "Multicast помилка з'єднання" -#define D_FAILED_TO_SEND_RESPONSE "Не вдалось надіслати відповідь" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo основна подія" -#define D_WEMO_EVENT_SERVICE "WeMo служба подій" -#define D_WEMO_META_SERVICE "WeMo мета-сервіс" -#define D_WEMO_SETUP "WeMo налаштування" -#define D_RESPONSE_SENT "Відповідь відіслана" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue налаштування" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API не реалізовано" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST args" -#define D_3_RESPONSE_PACKETS_SENT "3 пакету відповіді отримано" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz налаштування" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Ключ idx" -#define D_DOMOTICZ_SWITCH_IDX "Перемикач idx" -#define D_DOMOTICZ_SENSOR_IDX "Давач idx" - #define D_DOMOTICZ_TEMP "Температура" - #define D_DOMOTICZ_TEMP_HUM "Темп,Волог" - #define D_DOMOTICZ_TEMP_HUM_BARO "Темп,Волог,Тиск" - #define D_DOMOTICZ_POWER_ENERGY "Потуж,Енергія" - #define D_DOMOTICZ_ILLUMINANCE "Освітлення" - #define D_DOMOTICZ_COUNT "Лічильник/PM1" - #define D_DOMOTICZ_VOLTAGE "Напруга/PM2,5" - #define D_DOMOTICZ_CURRENT "Струм/PM10" - #define D_DOMOTICZ_AIRQUALITY "Якість повітря" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "Оновлення таймерів" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Конфігурація таймерів" -#define D_TIMER_PARAMETERS "Налаштування таймерів" -#define D_TIMER_ENABLE "Таймери увімкнені" -#define D_TIMER_ARM "Увімкнений" -#define D_TIMER_TIME "Час" -#define D_TIMER_DAYS "Дні" -#define D_TIMER_REPEAT "Повтор" -#define D_TIMER_OUTPUT "Вихід" -#define D_TIMER_ACTION "Дія" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Конфігурація KNX" -#define D_KNX_PARAMETERS "Налаштування KNX" -#define D_KNX_GENERAL_CONFIG "Основні" -#define D_KNX_PHYSICAL_ADDRESS "Фізична адреса" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Має бути унікальною у мережі KNX)" -#define D_KNX_ENABLE "KNX Увімкнений" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Дані для запису групових адрес" -#define D_ADD "Додати" -#define D_DELETE "Видалити" -#define D_REPLY "Повторити" -#define D_KNX_GROUP_ADDRESS_TO_READ "Дані для читання групових адрес" -#define D_RECEIVED_FROM "Отримати з" -#define D_KNX_COMMAND_WRITE "Записати" -#define D_KNX_COMMAND_READ "Читати" -#define D_KNX_COMMAND_OTHER "Інше" -#define D_SENT_TO "надіслати до" -#define D_KNX_WARNING "Адреса групи (0/0/0) зарезервована і не може бути використана." -#define D_KNX_ENHANCEMENT "Підвищення зв'язку" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "Енергія Сьогодні" -#define D_ENERGY_YESTERDAY "Енергія Вчора" -#define D_ENERGY_TOTAL "Енергія Всього" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Датчик DS18x20 зайнятий" -#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - помилка CRC" -#define D_SENSORS_FOUND "Датчик DS18x20 знайдено" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "Тайм-аут, в очікуванні" -#define D_START_SIGNAL_LOW "стартовий сигнал низький" -#define D_START_SIGNAL_HIGH "стартовий сигнал високий" -#define D_PULSE "імпульс" -#define D_CHECKSUM_FAILURE "Помилка контрольної суми" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не підтвердив отримання команди" -#define D_SHT1X_FOUND "SHT1X знайдено" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "Частинки понад" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Приск. Вісь-X" -#define D_AY_AXIS "Приск. Вісь-Y" -#define D_AZ_AXIS "Приск. Вісь-Z" -#define D_GX_AXIS "Орієнт Вісь-X" -#define D_GY_AXIS "Орієнт Вісь-Y" -#define D_GZ_AXIS "Орієнт Вісь-Z" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Напрям вітру" -#define D_TX20_WIND_SPEED "Швидкість вітру" -#define D_TX20_WIND_SPEED_AVG "Середня швидкість вітру" -#define D_TX20_WIND_SPEED_MAX "Максимальна швидкість вітру" -#define D_TX20_NORTH "Пн" -#define D_TX20_EAST "Сх" -#define D_TX20_SOUTH "Пд" -#define D_TX20_WEST "Зх" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "Немає" -#define D_SENSOR_USER "Користувач" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Перемикач" // Suffix "1" -#define D_SENSOR_BUTTON "Кнопка" // Suffix "1" -#define D_SENSOR_RELAY "Реле" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "ШІМ" // Suffix "1" -#define D_SENSOR_COUNTER "Лічильник" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Регулятор" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Зуммер" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "А" -#define D_UNIT_CENTIMETER "cм" -#define D_UNIT_HERTZ "Гц" -#define D_UNIT_HOUR "Г" -#define D_UNIT_GALLONS "гал" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "кг" -#define D_UNIT_KILOMETER_PER_HOUR "км/г" // or "km/h" -#define D_UNIT_KILOOHM "кОм" -#define D_UNIT_KILOWATTHOUR "кВт" -#define D_UNIT_LUX "лк" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" -#define D_UNIT_MICROMETER "мкм" -#define D_UNIT_MICROSECOND "мкс" -#define D_UNIT_MILLIAMPERE "мА" -#define D_UNIT_MILLIMETER "мм" -#define D_UNIT_MILLIMETER_MERCURY "ммHg" -#define D_UNIT_MILLISECOND "мс" -#define D_UNIT_MINUTE "хв" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "ppd" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "гПа" -#define D_UNIT_SECOND "сек" -#define D_UNIT_SECTORS "секторів" -#define D_UNIT_VA "ВА" -#define D_UNIT_VAR "ВАр" -#define D_UNIT_VOLT "В" -#define D_UNIT_WATT "Вт" -#define D_UNIT_WATTHOUR "Вт/Год" -#define D_UNIT_WATT_METER_QUADRAT "Вт/m²" - -//SDM220 -#define D_PHASE_ANGLE "Кут фази" -#define D_IMPORT_ACTIVE "Активна вхід" -#define D_EXPORT_ACTIVE "Активна вихід" -#define D_IMPORT_REACTIVE "Рекативна вхід" -#define D_EXPORT_REACTIVE "Реактивна вихід" -#define D_TOTAL_REACTIVE "Всього реактивна" -#define D_UNIT_KWARH "кВАр/г" -#define D_UNIT_ANGLE "Град" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_UK_UK_H_ +/* + uk-UK.h - localization for Ukrainian - Ukraine for Tasmota + + Copyright (C) 2019 Theo Arends / vadym-adik + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_UK_UK_H_ +#define _LANGUAGE_UK_UK_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.14.0a +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1058 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "uk" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "НедПонВівСерЧетПятСуб" +#define D_MONTH3LIST "СічЛютБерКвіТраЧерЛипСерВерЖовЛисГру" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "," + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Якість повітря" +#define D_AP "Точка доступу" // Access Point +#define D_AS "як" +#define D_AUTO "АВТО" +#define D_BLINK "Блимати" +#define D_BLINKOFF "Не блимати" +#define D_BOOT_COUNT "К-сть завант." +#define D_BRIGHTLIGHT "Яскравість" +#define D_BSSID "BSSId" +#define D_BUTTON "Кнопка" +#define D_BY " " // Written by me +#define D_BYTES "Байт" +#define D_CELSIUS "Цельсія" +#define D_CHANNEL "Канал" +#define D_CO2 "Вуглек. газ" +#define D_CODE "код" // Button code +#define D_COLDLIGHT "Холодний" +#define D_COMMAND "Команда" +#define D_CONNECTED "Під'єднано" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "Розмір" +#define D_COUNTER "Лічильник" +#define D_CURRENT "Струм" // As in Voltage and Current +#define D_DATA "Дані" +#define D_DARKLIGHT "Темний" +#define D_DEBUG "Налагодження" +#define D_DISABLED "Заблоковано" +#define D_DISTANCE "Відстань" +#define D_DNS_SERVER "Сервер DNS" +#define D_DONE "Виконано" +#define D_DST_TIME "Літній час" +#define D_ECO2 "eCO2" +#define D_EMULATION "Емуляція" +#define D_ENABLED "Активно" +#define D_ERASE "Стирати" +#define D_ERROR "Помилка" +#define D_FAHRENHEIT "Фаренгейт" +#define D_FAILED "Невдало" +#define D_FALLBACK "Зворотній зв'язок" +#define D_FALLBACK_TOPIC "Топік зворотнього зв'язку" +#define D_FALSE "Ні" +#define D_FILE "Файл" +#define D_FLOW_RATE "Потік" +#define D_FREE_MEMORY "Вільна память" +#define D_FREQUENCY "Частота" +#define D_GAS "Газ" +#define D_GATEWAY "Шлюз" +#define D_GROUP "Група" +#define D_HOST "Хост" +#define D_HOSTNAME "Назва хосту" +#define D_HUMIDITY "Вологість" +#define D_ILLUMINANCE "Освітленність" +#define D_IMMEDIATE "Негайно" // Button immediate +#define D_INDEX "Індекс" +#define D_INFO "Інфо" +#define D_INFRARED "Інфрачервоний" +#define D_INITIALIZED "Ініціалізовано" +#define D_IP_ADDRESS "IP адреса" +#define D_LIGHT "Світло" +#define D_LWT "LWT" +#define D_MODULE "Модуль" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "Багаторазове натискання" +#define D_NOISE "Шум" +#define D_NONE "Нічого" +#define D_OFF "Вимк." +#define D_OFFLINE "Офф-лайн" +#define D_OK "Ок" +#define D_ON "Увімк." +#define D_ONLINE "Он-лайн" +#define D_PASSWORD "Гасло" +#define D_PORT "Порт" +#define D_POWER_FACTOR "Коефіцієнт потужності" +#define D_POWERUSAGE "Потужність" +#define D_POWERUSAGE_ACTIVE "Активна потужність" +#define D_POWERUSAGE_APPARENT "Дійсна потужність" +#define D_POWERUSAGE_REACTIVE "Реактивна потужність" +#define D_PRESSURE "Тиск" +#define D_PRESSUREATSEALEVEL "Тиск на рівні моря" +#define D_PROGRAM_FLASH_SIZE "Розмір Flash для програм" +#define D_PROGRAM_SIZE "Розмір програм" +#define D_PROJECT "Проект" +#define D_RAIN "Дощ" +#define D_RECEIVED "Отримано" +#define D_RESTART "Перезавантаження" +#define D_RESTARTING "Перезавантаження" +#define D_RESTART_REASON "Причина перезавантаження" +#define D_RESTORE "відновлення" +#define D_RETAINED "зберігати" +#define D_RULE "Правило" +#define D_SAVE "Зберегти" +#define D_SENSOR "Давач" +#define D_SSID "SSID" +#define D_START "Старт" +#define D_STD_TIME "Стандартний час" +#define D_STOP "Стоп" +#define D_SUBNET_MASK "Маска підмережі" +#define D_SUBSCRIBE_TO "Підписатись на" +#define D_UNSUBSCRIBE_FROM "Відписатися від" +#define D_SUCCESSFUL "Успішно" +#define D_SUNRISE "Схід сонця" +#define D_SUNSET "Захід сонця" +#define D_TEMPERATURE "Температура" +#define D_TO "до" +#define D_TOGGLE "Перекл." +#define D_TOPIC "Топік" +#define D_TOTAL_USAGE "Загальне споживання" +#define D_TRANSMIT "Передати" +#define D_TRUE "Так" +#define D_TVOC "TVOC" +#define D_UPGRADE "оновлення" +#define D_UPLOAD "Завантажити" +#define D_UPTIME "Час роботи" +#define D_USER "Користувач" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Індекс УФ" +#define D_UV_INDEX_1 "Низький" +#define D_UV_INDEX_2 "Середній" +#define D_UV_INDEX_3 "Високий" +#define D_UV_INDEX_4 "Небезпечний" +#define D_UV_INDEX_5 "Опіки 1/2 ступеня" +#define D_UV_INDEX_6 "Опіки 3 ступеня" +#define D_UV_INDEX_7 "Невідомий" +#define D_UV_LEVEL "Рівень УФ" +#define D_UV_POWER "Потужність УФ" +#define D_VERSION "Версія" +#define D_VOLTAGE "Напруга" +#define D_WEIGHT "Вага" +#define D_WARMLIGHT "Тепло" +#define D_WEB_SERVER "Web сервер" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ПОПЕРЕДЖЕННЯ! Ця версія не підтримує збереження налаштувань" +#define D_LEVEL_10 "рівень 1-0" +#define D_LEVEL_01 "рівень 0-1" +#define D_SERIAL_LOGGING_DISABLED "Serial журнал вимкнений" +#define D_SYSLOG_LOGGING_REENABLED "Syslog журнал увімкнений" + +#define D_SET_BAUDRATE_TO "Встановити швидкість передачі (Baudrate)" +#define D_RECEIVED_TOPIC "Отриманий Топік" +#define D_DATA_SIZE "Розмір даних" +#define D_ANALOG_INPUT "Напруга" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Цикл заблокований" +#define D_WPS_FAILED_WITH_STATUS "WPS конфігурація з статусом НЕВДАЛА" +#define D_ACTIVE_FOR_3_MINUTES "активний протягом 3 хвилин" +#define D_FAILED_TO_START "не вдалось запустити" +#define D_PATCH_ISSUE_2186 "Проблема з виправленням 2186" +#define D_CONNECTING_TO_AP "Підключення до AP" +#define D_IN_MODE "в режимі" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Помилка підключення, IP-адреса не отримана" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Помилка з'єднання, AP не знайдено" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Помилка з'єднання, невірне гасло до AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Помилка з'єднання з AP по тайм-ауту" +#define D_ATTEMPTING_CONNECTION "Спроба підключення..." +#define D_CHECKING_CONNECTION "Перевірка з'єднання..." +#define D_QUERY_DONE "Запит виконаний. Виявлено сервер MQTT" +#define D_MQTT_SERVICE_FOUND "MQTT сервер знайдено" +#define D_FOUND_AT "знайдено в" +#define D_SYSLOG_HOST_NOT_FOUND "Сервер журналу не знайдено" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Збережено в флэш-пам'ять" +#define D_LOADED_FROM_FLASH_AT "Завантажено з флэш-пам'яті" +#define D_USE_DEFAULTS "Використовувати значення за замовчуванням" +#define D_ERASED_SECTOR "Стерто сектор" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Для використання Tasmota треба увімкнути JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL
будь-ласка оновіть" +#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активний" +#define D_WITH_IP_ADDRESS "з IP-адресою" +#define D_WEBSERVER_STOPPED "Веб-сервер зупинений" +#define D_FILE_NOT_FOUND "Файл не знайдений" +#define D_REDIRECTED "Перенаправлено на адаптивний портал" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер встановлює Точку Доступу і зберігає параметри" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер встановив Точку Доступу" +#define D_TRYING_TO_CONNECT "Спроба підключення пристрою до мережі" + +#define D_RESTART_IN "Перезавантаження" +#define D_SECONDS "секунд" +#define D_DEVICE_WILL_RESTART "Пристрій буде перезавантажено через декілька секунд" +#define D_BUTTON_TOGGLE "Переключити" +#define D_CONFIGURATION "Конфігурація" +#define D_INFORMATION "Інформація" +#define D_FIRMWARE_UPGRADE "Оновлення прошивки" +#define D_CONSOLE "Консоль" +#define D_CONFIRM_RESTART "Підтвердити перезавантаження" + +#define D_CONFIGURE_MODULE "Конфігурація модуля" +#define D_CONFIGURE_WIFI "Конфігурація WiFi" +#define D_CONFIGURE_MQTT "Конфігурація MQTT" +#define D_CONFIGURE_DOMOTICZ "Конфігурація Domoticz" +#define D_CONFIGURE_LOGGING "Конфігурація журналів" +#define D_CONFIGURE_OTHER "Конфігурація інше" +#define D_CONFIRM_RESET_CONFIGURATION "Підтвердити скидання конфігурації" +#define D_RESET_CONFIGURATION "Скидання конфігурації" +#define D_BACKUP_CONFIGURATION "Резервне копіювання конфігурації" +#define D_RESTORE_CONFIGURATION "Відновлення конфігурації" +#define D_MAIN_MENU "Головне меню" + +#define D_MODULE_PARAMETERS "Параметри модуля" +#define D_MODULE_TYPE "Тип модуля" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "АЦП" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Serial вхід" +#define D_SERIAL_OUT "Serial вихід" + +#define D_WIFI_PARAMETERS "Параметри Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Сканування бездротовихих мереж Wifi" +#define D_SCAN_DONE "Сканування завершене" +#define D_NO_NETWORKS_FOUND "Не знайдено мереж" +#define D_REFRESH_TO_SCAN_AGAIN "Оновити для повторного сканування" +#define D_DUPLICATE_ACCESSPOINT "Дублювати Точку Доступу (AP)" +#define D_SKIPPING_LOW_QUALITY "Пропущено через низьку якість" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSID" +#define D_AP1_PASSWORD "AP1 гасло" +#define D_AP2_SSID "AP2 SSID" +#define D_AP2_PASSWORD "AP2 гасло" + +#define D_MQTT_PARAMETERS "Параметри MQTT" +#define D_CLIENT "Клієнт" +#define D_FULL_TOPIC "Повний Топік" + +#define D_LOGGING_PARAMETERS "Параметри журналу" +#define D_SERIAL_LOG_LEVEL "Serial рівень" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web рівень" +#define D_SYS_LOG_LEVEL "System рівень" +#define D_MORE_DEBUG "Додаткова інформація для налагодження" +#define D_SYSLOG_HOST "System хост" +#define D_SYSLOG_PORT "System порт" +#define D_TELEMETRY_PERIOD "Період телеметрії" + +#define D_OTHER_PARAMETERS "Параметри Інше" +#define D_TEMPLATE "Шаблони" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "Гасло Web адміністратора" +#define D_MQTT_ENABLE "MQTT активний" +#define D_FRIENDLY_NAME "Дружнє Ім'я" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "одиночне" +#define D_MULTI_DEVICE "мульти" + +#define D_CONFIGURE_TEMPLATE "Конфігурація шаблона" +#define D_TEMPLATE_PARAMETERS "Параметри шаблона" +#define D_TEMPLATE_NAME "Назва" +#define D_BASE_TYPE "На основі" +#define D_TEMPLATE_FLAGS "Опції" + +#define D_SAVE_CONFIGURATION "Зберегти конфігурацію" +#define D_CONFIGURATION_SAVED "Конфігурація збережена " +#define D_CONFIGURATION_RESET "Конфігурація скинута" + +#define D_PROGRAM_VERSION "Версія програми" +#define D_BUILD_DATE_AND_TIME "Дата і час збірки" +#define D_CORE_AND_SDK_VERSION "Версія Core/SDK" +#define D_FLASH_WRITE_COUNT "Кількість записів Flash" +#define D_MAC_ADDRESS "MAC Адреса" +#define D_MQTT_HOST "MQTT Хост" +#define D_MQTT_PORT "MQTT Порт" +#define D_MQTT_CLIENT "MQTT ID Клієнта" +#define D_MQTT_USER "MQTT Користувач" +#define D_MQTT_TOPIC "MQTT Топік" +#define D_MQTT_GROUP_TOPIC "MQTT Топік групи" +#define D_MQTT_FULL_TOPIC "MQTT Топік повний" +#define D_MDNS_DISCOVERY "mDNS Виявлення" +#define D_MDNS_ADVERTISE "mDNS Транcляція" +#define D_ESP_CHIP_ID "ID чипу ESP" +#define D_FLASH_CHIP_ID "ID чипу Flash пам'яті" +#define D_FLASH_CHIP_SIZE "Розмір Flash пам'яті" +#define D_FREE_PROGRAM_SPACE "Вільний простір для програм" + +#define D_UPGRADE_BY_WEBSERVER "Оновлення через Веб-сервер" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Почати оновлення" +#define D_UPGRADE_BY_FILE_UPLOAD "Оновлення шляхом завантаження файлів" +#define D_UPLOAD_STARTED "Завантаження почалось" +#define D_UPGRADE_STARTED "Оновлення почалось" +#define D_UPLOAD_DONE "Завантаження завершено" +#define D_UPLOAD_ERR_1 "Файл не вибраний" +#define D_UPLOAD_ERR_2 "Недостатньо місця" +#define D_UPLOAD_ERR_3 "Магічний байт не 0xE9" +#define D_UPLOAD_ERR_4 "Размір прошивки більший, ніж размір Flash пам'яті" +#define D_UPLOAD_ERR_5 "Помилка завантаження буферу" +#define D_UPLOAD_ERR_6 "Помилка завантаження. Увімкнено лог рівень 3" +#define D_UPLOAD_ERR_7 "Завантаження перервано" +#define D_UPLOAD_ERR_8 "Файл невірний" +#define D_UPLOAD_ERR_9 "Занадто великий файл" +#define D_UPLOAD_ERR_10 "Помилка ініціалізаціції чипу FR" +#define D_UPLOAD_ERR_11 "Помилка стирання чипу RF" +#define D_UPLOAD_ERR_12 "Помилка запису чипу RF" +#define D_UPLOAD_ERR_13 "Помилка розкодування прошивки RF" +#define D_UPLOAD_ERROR_CODE "Код помилки завантаження" + +#define D_ENTER_COMMAND "Уведіть команду" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Увімкніть Веб лог рівня 2 якщо очікуєте відповідь" +#define D_NEED_USER_AND_PASSWORD "Очікується user=&password=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Перевірка відбитка TLS..." +#define D_TLS_CONNECT_FAILED_TO "Збій підключення TLS до" +#define D_RETRY_IN "Повторити" +#define D_VERIFIED "Перевірено відбиток" +#define D_INSECURE "Небезпечне з'єднання, недійсний відбиток" +#define D_CONNECT_FAILED_TO "Помилка підключення до" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast вимкнений" +#define D_MULTICAST_REJOINED "Multicast (пере)під'єднався" +#define D_MULTICAST_JOIN_FAILED "Multicast помилка з'єднання" +#define D_FAILED_TO_SEND_RESPONSE "Не вдалось надіслати відповідь" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo основна подія" +#define D_WEMO_EVENT_SERVICE "WeMo служба подій" +#define D_WEMO_META_SERVICE "WeMo мета-сервіс" +#define D_WEMO_SETUP "WeMo налаштування" +#define D_RESPONSE_SENT "Відповідь відіслана" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue налаштування" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API не реалізовано" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 пакету відповіді отримано" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz налаштування" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Ключ idx" +#define D_DOMOTICZ_SWITCH_IDX "Перемикач idx" +#define D_DOMOTICZ_SENSOR_IDX "Давач idx" + #define D_DOMOTICZ_TEMP "Температура" + #define D_DOMOTICZ_TEMP_HUM "Темп,Волог" + #define D_DOMOTICZ_TEMP_HUM_BARO "Темп,Волог,Тиск" + #define D_DOMOTICZ_POWER_ENERGY "Потуж,Енергія" + #define D_DOMOTICZ_ILLUMINANCE "Освітлення" + #define D_DOMOTICZ_COUNT "Лічильник/PM1" + #define D_DOMOTICZ_VOLTAGE "Напруга/PM2,5" + #define D_DOMOTICZ_CURRENT "Струм/PM10" + #define D_DOMOTICZ_AIRQUALITY "Якість повітря" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Оновлення таймерів" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Конфігурація таймерів" +#define D_TIMER_PARAMETERS "Налаштування таймерів" +#define D_TIMER_ENABLE "Таймери увімкнені" +#define D_TIMER_ARM "Увімкнений" +#define D_TIMER_TIME "Час" +#define D_TIMER_DAYS "Дні" +#define D_TIMER_REPEAT "Повтор" +#define D_TIMER_OUTPUT "Вихід" +#define D_TIMER_ACTION "Дія" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Конфігурація KNX" +#define D_KNX_PARAMETERS "Налаштування KNX" +#define D_KNX_GENERAL_CONFIG "Основні" +#define D_KNX_PHYSICAL_ADDRESS "Фізична адреса" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Має бути унікальною у мережі KNX)" +#define D_KNX_ENABLE "KNX Увімкнений" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Дані для запису групових адрес" +#define D_ADD "Додати" +#define D_DELETE "Видалити" +#define D_REPLY "Повторити" +#define D_KNX_GROUP_ADDRESS_TO_READ "Дані для читання групових адрес" +#define D_RECEIVED_FROM "Отримати з" +#define D_KNX_COMMAND_WRITE "Записати" +#define D_KNX_COMMAND_READ "Читати" +#define D_KNX_COMMAND_OTHER "Інше" +#define D_SENT_TO "надіслати до" +#define D_KNX_WARNING "Адреса групи (0/0/0) зарезервована і не може бути використана." +#define D_KNX_ENHANCEMENT "Підвищення зв'язку" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Енергія Сьогодні" +#define D_ENERGY_YESTERDAY "Енергія Вчора" +#define D_ENERGY_TOTAL "Енергія Всього" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Датчик DS18x20 зайнятий" +#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - помилка CRC" +#define D_SENSORS_FOUND "Датчик DS18x20 знайдено" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Тайм-аут, в очікуванні" +#define D_START_SIGNAL_LOW "стартовий сигнал низький" +#define D_START_SIGNAL_HIGH "стартовий сигнал високий" +#define D_PULSE "імпульс" +#define D_CHECKSUM_FAILURE "Помилка контрольної суми" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не підтвердив отримання команди" +#define D_SHT1X_FOUND "SHT1X знайдено" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Частинки понад" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Приск. Вісь-X" +#define D_AY_AXIS "Приск. Вісь-Y" +#define D_AZ_AXIS "Приск. Вісь-Z" +#define D_GX_AXIS "Орієнт Вісь-X" +#define D_GY_AXIS "Орієнт Вісь-Y" +#define D_GZ_AXIS "Орієнт Вісь-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Напрям вітру" +#define D_TX20_WIND_SPEED "Швидкість вітру" +#define D_TX20_WIND_SPEED_AVG "Середня швидкість вітру" +#define D_TX20_WIND_SPEED_MAX "Максимальна швидкість вітру" +#define D_TX20_NORTH "Пн" +#define D_TX20_EAST "Сх" +#define D_TX20_SOUTH "Пд" +#define D_TX20_WEST "Зх" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Немає" +#define D_SENSOR_USER "Користувач" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Перемикач" // Suffix "1" +#define D_SENSOR_BUTTON "Кнопка" // Suffix "1" +#define D_SENSOR_RELAY "Реле" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "ШІМ" // Suffix "1" +#define D_SENSOR_COUNTER "Лічильник" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Регулятор" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Зуммер" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "А" +#define D_UNIT_CENTIMETER "cм" +#define D_UNIT_HERTZ "Гц" +#define D_UNIT_HOUR "Г" +#define D_UNIT_GALLONS "гал" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "кг" +#define D_UNIT_KILOMETER_PER_HOUR "км/г" // or "km/h" +#define D_UNIT_KILOOHM "кОм" +#define D_UNIT_KILOWATTHOUR "кВт" +#define D_UNIT_LUX "лк" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" +#define D_UNIT_MICROMETER "мкм" +#define D_UNIT_MICROSECOND "мкс" +#define D_UNIT_MILLIAMPERE "мА" +#define D_UNIT_MILLIMETER "мм" +#define D_UNIT_MILLIMETER_MERCURY "ммHg" +#define D_UNIT_MILLISECOND "мс" +#define D_UNIT_MINUTE "хв" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "гПа" +#define D_UNIT_SECOND "сек" +#define D_UNIT_SECTORS "секторів" +#define D_UNIT_VA "ВА" +#define D_UNIT_VAR "ВАр" +#define D_UNIT_VOLT "В" +#define D_UNIT_WATT "Вт" +#define D_UNIT_WATTHOUR "Вт/Год" +#define D_UNIT_WATT_METER_QUADRAT "Вт/m²" + +//SDM220 +#define D_PHASE_ANGLE "Кут фази" +#define D_IMPORT_ACTIVE "Активна вхід" +#define D_EXPORT_ACTIVE "Активна вихід" +#define D_IMPORT_REACTIVE "Рекативна вхід" +#define D_EXPORT_REACTIVE "Реактивна вихід" +#define D_TOTAL_REACTIVE "Всього реактивна" +#define D_UNIT_KWARH "кВАр/г" +#define D_UNIT_ANGLE "Град" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_UK_UK_H_ diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 275216007..21aa63be3 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -1,703 +1,701 @@ -/* - zh-CN.h - localization for Chinese (Simplified) - China for Tasmota - - Copyright (C) 2019 Theo Arends (translated by killadm) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_ZH_CN_H_ -#define _LANGUAGE_ZH_CN_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.14.0b -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 2052 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "zh" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "日 一 二 三 四 五 六 " -#define D_MONTH3LIST "1月 2月 3月 4月 5月 6月 7月 8月 9月 10月11月12月" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "空气质量" -#define D_AP "AP" // Access Point -#define D_AS "名称:" -#define D_AUTO "自动" -#define D_BLINK "闪烁" -#define D_BLINKOFF "闪烁关" -#define D_BOOT_COUNT "启动次数" -#define D_BRIGHTLIGHT "亮" -#define D_BSSID "BSSId" -#define D_BUTTON "按钮" -#define D_BY "汉化: killadm 作者:" // Written by me -#define D_BYTES "大小:" -#define D_CELSIUS "摄氏" -#define D_CHANNEL "频道" -#define D_CO2 "二氧化碳" -#define D_CODE "代码" // Button code -#define D_COLDLIGHT "冷" -#define D_COMMAND "命令:" -#define D_CONNECTED "已连接" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "数量:" -#define D_COUNTER "计数器" -#define D_CURRENT "电流" // As in Voltage and Current -#define D_DATA "数据:" -#define D_DARKLIGHT "暗" -#define D_DEBUG "调试" -#define D_DISABLED "禁用" -#define D_DISTANCE "距离" -#define D_DNS_SERVER "DNS服务器" -#define D_DONE "完成" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "设备模拟" -#define D_ENABLED "启用" -#define D_ERASE "擦除" -#define D_ERROR "错误" -#define D_FAHRENHEIT "华氏" -#define D_FAILED "失败" -#define D_FALLBACK "回退" -#define D_FALLBACK_TOPIC "回退主题" -#define D_FALSE "False" -#define D_FILE "文件:" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "空闲内存" -#define D_FREQUENCY "频率" -#define D_GAS "气体" -#define D_GATEWAY "网关" -#define D_GROUP "组:" -#define D_HOST "主机" -#define D_HOSTNAME "主机名" -#define D_HUMIDITY "湿度" -#define D_ILLUMINANCE "照度" -#define D_IMMEDIATE "单次按键" // Button immediate -#define D_INDEX "索引:" -#define D_INFO "信息" -#define D_INFRARED "红外线" -#define D_INITIALIZED "初始化完成" -#define D_IP_ADDRESS "IP地址" -#define D_LIGHT "灯" -#define D_LWT "LWT" -#define D_MODULE "模块" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "多次按键" -#define D_NOISE "嘈杂" -#define D_NONE "无" -#define D_OFF "关" -#define D_OFFLINE "离线" -#define D_OK "好" -#define D_ON "开" -#define D_ONLINE "在线" -#define D_PASSWORD "密码" -#define D_PORT "端口" -#define D_POWER_FACTOR "功率因数" -#define D_POWERUSAGE "功率" -#define D_POWERUSAGE_ACTIVE "有功功率" -#define D_POWERUSAGE_APPARENT "视在功率" -#define D_POWERUSAGE_REACTIVE "无功功率" -#define D_PRESSURE "气压" -#define D_PRESSUREATSEALEVEL "海平面气压" -#define D_PROGRAM_FLASH_SIZE "固件 Flash 大小" -#define D_PROGRAM_SIZE "固件大小" -#define D_PROJECT "项目:" -#define D_RAIN "降水量" -#define D_RECEIVED "已接收" -#define D_RESTART "重启" -#define D_RESTARTING "正在重启" -#define D_RESTART_REASON "重启原因" -#define D_RESTORE "恢复" -#define D_RETAINED "已保留" -#define D_RULE "规则" -#define D_SAVE "保存" -#define D_SENSOR "传感器" -#define D_SSID "名称" -#define D_START "开始" -#define D_STD_TIME "STD" -#define D_STOP "停止" -#define D_SUBNET_MASK "子网掩码" -#define D_SUBSCRIBE_TO "订阅" -#define D_UNSUBSCRIBE_FROM "退订" -#define D_SUCCESSFUL "成功" -#define D_SUNRISE "日出" -#define D_SUNSET "日落" -#define D_TEMPERATURE "温度" -#define D_TO "to" -#define D_TOGGLE "切换" -#define D_TOPIC "主题" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "发送" -#define D_TRUE "True" -#define D_TVOC "TVOC" -#define D_UPGRADE "升级" -#define D_UPLOAD "上传" -#define D_UPTIME "运行时间" -#define D_USER "用户名" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "紫外线指数" -#define D_UV_INDEX_1 "低" -#define D_UV_INDEX_2 "中" -#define D_UV_INDEX_3 "高" -#define D_UV_INDEX_4 "危险" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "紫外线水平" -#define D_UV_POWER "紫外线功率 " -#define D_VERSION "版本" -#define D_VOLTAGE "电压" -#define D_WEIGHT "重量" -#define D_WARMLIGHT "暖" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "警告:精简固件不支持配置持久化保存" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "串口日志已禁用" -#define D_SYSLOG_LOGGING_REENABLED "Syslog 日志已开启" - -#define D_SET_BAUDRATE_TO "设置波特率为:" -#define D_RECEIVED_TOPIC "接收到的主题:" -#define D_DATA_SIZE "数据大小:" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPS 配置失败,状态:" -#define D_ACTIVE_FOR_3_MINUTES "激活 3 分钟" -#define D_FAILED_TO_START "未能启动" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "连接到 AP" -#define D_IN_MODE "模式:" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "连接失败,因为没有获取到 IP 地址" -#define D_CONNECT_FAILED_AP_NOT_REACHED "连接失败,无法连接 AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "连接失败,AP 密码不正确" -#define D_CONNECT_FAILED_AP_TIMEOUT "连接失败,AP 超时" -#define D_ATTEMPTING_CONNECTION "尝试连接..." -#define D_CHECKING_CONNECTION "检查连接..." -#define D_QUERY_DONE "查询完成。 发现 MQTT 服务" -#define D_MQTT_SERVICE_FOUND "发现 MQTT 服务:" -#define D_FOUND_AT "发现:" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog 主机未找到" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "保存到 flash:" -#define D_LOADED_FROM_FLASH_AT "从 flash 载入:" -#define D_USE_DEFAULTS "使用默认设置" -#define D_ERASED_SECTOR "擦除扇区" - -// webserver.ino -#define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" -#define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" -#define D_WITH_IP_ADDRESS "IP 地址:" -#define D_WEBSERVER_STOPPED "Web 服务已停止" -#define D_FILE_NOT_FOUND "文件未找到" -#define D_REDIRECTED "重定向到认证页面" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager 设置无线操作模式" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 设置接入点" -#define D_TRYING_TO_CONNECT "尝试将设备连接到网络" - -#define D_RESTART_IN "重启需要" -#define D_SECONDS "秒" -#define D_DEVICE_WILL_RESTART "设备将在几秒钟内重启" -#define D_BUTTON_TOGGLE "状态切换" -#define D_CONFIGURATION "设置" -#define D_INFORMATION "信息" -#define D_FIRMWARE_UPGRADE "固件升级" -#define D_CONSOLE "控制台" -#define D_CONFIRM_RESTART "确认重启" - -#define D_CONFIGURE_MODULE "模块设置" -#define D_CONFIGURE_WIFI "WiFi设置" -#define D_CONFIGURE_MQTT "MQTT设置" -#define D_CONFIGURE_DOMOTICZ "Domoticz设置" -#define D_CONFIGURE_LOGGING "日志设置" -#define D_CONFIGURE_OTHER "其他设置" -#define D_CONFIRM_RESET_CONFIGURATION "确认重置配置" -#define D_RESET_CONFIGURATION "重置配置" -#define D_BACKUP_CONFIGURATION "备份配置" -#define D_RESTORE_CONFIGURATION "还原配置" -#define D_MAIN_MENU "主菜单" - -#define D_MODULE_PARAMETERS "模块设置" -#define D_MODULE_TYPE "模块类型" -#define D_PULLUP_ENABLE "没有按钮/开关上拉" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "串口输入(RX)" -#define D_SERIAL_OUT "串口输出(TX)" - -#define D_WIFI_PARAMETERS "Wifi设置" -#define D_SCAN_FOR_WIFI_NETWORKS "扫描无线网络" -#define D_SCAN_DONE "扫描完毕" -#define D_NO_NETWORKS_FOUND "未找到任何网络" -#define D_REFRESH_TO_SCAN_AGAIN "刷新并重试" -#define D_DUPLICATE_ACCESSPOINT "重复AP" -#define D_SKIPPING_LOW_QUALITY "忽略弱信号网络" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 名称" -#define D_AP1_PASSWORD "AP1 密码" -#define D_AP2_SSID "AP2 名称" -#define D_AP2_PASSWORD "AP2 密码" - -#define D_MQTT_PARAMETERS "MQTT 设置" -#define D_CLIENT "客户端" -#define D_FULL_TOPIC "完整主题" - -#define D_LOGGING_PARAMETERS "日志设置" -#define D_SERIAL_LOG_LEVEL "串口日志级别" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web 日志级别" -#define D_SYS_LOG_LEVEL "Syslog 日志级别" -#define D_MORE_DEBUG "全部调试" -#define D_SYSLOG_HOST "Syslog 主机地址" -#define D_SYSLOG_PORT "Syslog 端口" -#define D_TELEMETRY_PERIOD "上报周期" - -#define D_OTHER_PARAMETERS "其他设置" -#define D_TEMPLATE "模板" -#define D_ACTIVATE "启用" -#define D_WEB_ADMIN_PASSWORD "WEB 管理密码" -#define D_MQTT_ENABLE "启用MQTT" -#define D_FRIENDLY_NAME "昵称" -#define D_BELKIN_WEMO "贝尔金 WeMo" -#define D_HUE_BRIDGE "飞利浦 Hue 网桥" -#define D_SINGLE_DEVICE "单设备" -#define D_MULTI_DEVICE "多设备" - -#define D_CONFIGURE_TEMPLATE "模板配置" -#define D_TEMPLATE_PARAMETERS "模板参数" -#define D_TEMPLATE_NAME "名称" -#define D_BASE_TYPE "基于" -#define D_TEMPLATE_FLAGS "选项" - -#define D_SAVE_CONFIGURATION "保存设置" -#define D_CONFIGURATION_SAVED "设置已保存" -#define D_CONFIGURATION_RESET "设置已重置" - -#define D_PROGRAM_VERSION "固件版本" -#define D_BUILD_DATE_AND_TIME "编译时间" -#define D_CORE_AND_SDK_VERSION "内核和 SDK 版本" -#define D_FLASH_WRITE_COUNT "Flash 写入次数" -#define D_MAC_ADDRESS "MAC 地址" -#define D_MQTT_HOST "MQTT 主机" -#define D_MQTT_PORT "MQTT 端口" -#define D_MQTT_CLIENT "MQTT 客户端" -#define D_MQTT_USER "MQTT 用户名" -#define D_MQTT_TOPIC "MQTT 主题" -#define D_MQTT_GROUP_TOPIC "MQTT 主题组" -#define D_MQTT_FULL_TOPIC "MQTT 完整主题" -#define D_MDNS_DISCOVERY "mDNS 发现" -#define D_MDNS_ADVERTISE "mDNS 广播" -#define D_ESP_CHIP_ID "ESP 芯片 ID" -#define D_FLASH_CHIP_ID "Flash 芯片 ID" -#define D_FLASH_CHIP_SIZE "Flash 大小" -#define D_FREE_PROGRAM_SPACE "空闲程序空间" - -#define D_UPGRADE_BY_WEBSERVER "通过 Web 升级" -#define D_OTA_URL "OTA 地址" -#define D_START_UPGRADE "开始升级" -#define D_UPGRADE_BY_FILE_UPLOAD "通过文件升级" -#define D_UPLOAD_STARTED "开始上传" -#define D_UPGRADE_STARTED "开始升级" -#define D_UPLOAD_DONE "上传完成" -#define D_UPLOAD_ERR_1 "没有选择任何文件" -#define D_UPLOAD_ERR_2 "没有足够空间" -#define D_UPLOAD_ERR_3 "固件头不是 0xE9" -#define D_UPLOAD_ERR_4 "固件大小超过 flash 容量" -#define D_UPLOAD_ERR_5 "上传缓冲区不足,请先刷入精简固件再升级" -#define D_UPLOAD_ERR_6 "上传失败。 启用日志级别 3 调试" -#define D_UPLOAD_ERR_7 "上传取消" -#define D_UPLOAD_ERR_8 "错误的固件" -#define D_UPLOAD_ERR_9 "固件太大" -#define D_UPLOAD_ERR_10 "初始化 RF 芯片失败" -#define D_UPLOAD_ERR_11 "擦除 RF 芯片失败" -#define D_UPLOAD_ERR_12 "写入 RF 芯片失败" -#define D_UPLOAD_ERR_13 "解码 RF 固件失败" -#define D_UPLOAD_ERROR_CODE "上传错误代码" - -#define D_ENTER_COMMAND "输入命令" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果想得到预期响应,请调整日志级别至: 2 信息" -#define D_NEED_USER_AND_PASSWORD "需要 user=<用户名>&password=<密码>" - -// xdrv_00_mqtt.ino -#define D_FINGERPRINT "验证 TLS 指纹..." -#define D_TLS_CONNECT_FAILED_TO "TLS 连接失败" -#define D_RETRY_IN "重试倒计时:" -#define D_VERIFIED "验证成功" -#define D_INSECURE "指纹无效导致连接不安全" -#define D_CONNECT_FAILED_TO "连接失败:" - -// xdrv_wemohue.ino -#define D_MULTICAST_DISABLED "组播已禁用" -#define D_MULTICAST_REJOINED "组播已(重新)加入" -#define D_MULTICAST_JOIN_FAILED "组播加入失败" -#define D_FAILED_TO_SEND_RESPONSE "请求发送失败" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo 基础事件" -#define D_WEMO_EVENT_SERVICE "WeMo 事件服务" -#define D_WEMO_META_SERVICE "WeMo meta 服务" -#define D_WEMO_SETUP "WeMo 设置" -#define D_RESPONSE_SENT "发送请求" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue 设置" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未实现" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST 参数" -#define D_3_RESPONSE_PACKETS_SENT "3 请求包发送" - -// xdrv_05_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz 设置" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "开关 idx" -#define D_DOMOTICZ_SENSOR_IDX "传感器 idx" - #define D_DOMOTICZ_TEMP "温度" - #define D_DOMOTICZ_TEMP_HUM "温度,湿度" - #define D_DOMOTICZ_TEMP_HUM_BARO "温度,湿度,气压" - #define D_DOMOTICZ_POWER_ENERGY "功率,电量" - #define D_DOMOTICZ_ILLUMINANCE "照度" - #define D_DOMOTICZ_COUNT "数值/PM1" - #define D_DOMOTICZ_VOLTAGE "电压/PM2.5" - #define D_DOMOTICZ_CURRENT "电流/PM10" - #define D_DOMOTICZ_AIRQUALITY "空气质量" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "更新计时器" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "定时器设置" -#define D_TIMER_PARAMETERS "定时器参数" -#define D_TIMER_ENABLE "启用定时器" -#define D_TIMER_ARM "启用" -#define D_TIMER_TIME "时间" -#define D_TIMER_DAYS "天" -#define D_TIMER_REPEAT "重复" -#define D_TIMER_OUTPUT "输出" -#define D_TIMER_ACTION "动作" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "KNX 配置" -#define D_KNX_PARAMETERS "KNX 参数" -#define D_KNX_GENERAL_CONFIG "同用" -#define D_KNX_PHYSICAL_ADDRESS "物理地址" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( 在 KNX 网络上必须是唯一的 )" -#define D_KNX_ENABLE "启用 KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "要发送到组地址的数据" -#define D_ADD "添加" -#define D_DELETE "删除" -#define D_REPLY "回复" -#define D_KNX_GROUP_ADDRESS_TO_READ "用来接收数据的组地址" -#define D_RECEIVED_FROM "接收自" -#define D_KNX_COMMAND_WRITE "写" -#define D_KNX_COMMAND_READ "读" -#define D_KNX_COMMAND_OTHER "其他" -#define D_SENT_TO "发送到" -#define D_KNX_WARNING "组地址(0/0/0)被保留,不能使用。" -#define D_KNX_ENHANCEMENT "通讯增强" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "今日用电量" -#define D_ENERGY_YESTERDAY "昨日用电量" -#define D_ENERGY_TOTAL "总用电量" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "传感器正忙" -#define D_SENSOR_CRC_ERROR "传感器 CRC 校验错误" -#define D_SENSORS_FOUND "发现传感器" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "等待超时" -#define D_START_SIGNAL_LOW "开始低电平" -#define D_START_SIGNAL_HIGH "开始高电平" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "校验失败" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "传感器没有确认命令" -#define D_SHT1X_FOUND "发现 SHT1X 传感器" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "颗粒物直径大于" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "加速度计X轴分量" -#define D_AY_AXIS "加速度计Y轴分量" -#define D_AZ_AXIS "加速度计Z轴分量" -#define D_GX_AXIS "绕X轴旋转的角速度" -#define D_GY_AXIS "绕Y轴旋转的角速度" -#define D_GZ_AXIS "绕Z轴旋转的角速度" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "去除重量" -#define D_HX_CAL_REFERENCE "加载参考重量" -#define D_HX_CAL_DONE "已校准" -#define D_HX_CAL_FAIL "校准失败" -#define D_RESET_HX711 "秤重置" -#define D_CONFIGURE_HX711 "秤配置" -#define D_HX711_PARAMETERS "秤参数" -#define D_ITEM_WEIGHT "物品中粮" -#define D_REFERENCE_WEIGHT "参考重量" -#define D_CALIBRATE "校准" -#define D_CALIBRATION "校准" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "风向" -#define D_TX20_WIND_SPEED "风速" -#define D_TX20_WIND_SPEED_AVG "平均风速" -#define D_TX20_WIND_SPEED_MAX "最高风速" -#define D_TX20_NORTH "北" -#define D_TX20_EAST "东" -#define D_TX20_SOUTH "南" -#define D_TX20_WEST "西" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "无" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "安" -#define D_UNIT_CENTIMETER "厘米" -#define D_UNIT_HERTZ "赫兹" -#define D_UNIT_HOUR "时" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "千克" -#define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h" -#define D_UNIT_KILOOHM "千欧" -#define D_UNIT_KILOWATTHOUR "千瓦时" -#define D_UNIT_LUX "勒克斯" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" -#define D_UNIT_MICROMETER "微米" -#define D_UNIT_MICROSECOND "微秒" -#define D_UNIT_MILLIAMPERE "毫安" -#define D_UNIT_MILLIMETER "毫米" -#define D_UNIT_MILLIMETER_MERCURY "毫米汞柱" -#define D_UNIT_MILLISECOND "毫秒" -#define D_UNIT_MINUTE "分" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "每分升" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "百帕" -#define D_UNIT_SECOND "秒" -#define D_UNIT_SECTORS "扇区" -#define D_UNIT_VA "伏安" -#define D_UNIT_VAR "无功伏安" -#define D_UNIT_VOLT "伏" -#define D_UNIT_WATT "瓦" -#define D_UNIT_WATTHOUR "瓦时" -#define D_UNIT_WATT_METER_QUADRAT "瓦/平米" - -//SDM220 -#define D_PHASE_ANGLE "相位角" -#define D_IMPORT_ACTIVE "有功输入" -#define D_EXPORT_ACTIVE "有功输出" -#define D_IMPORT_REACTIVE "无功输入" -#define D_EXPORT_REACTIVE "无功输出" -#define D_TOTAL_REACTIVE "总无功功率" -#define D_UNIT_KWARH "千乏时" -#define D_UNIT_ANGLE "度" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_ZH_CN_H_ +/* + zh-CN.h - localization for Chinese (Simplified) - China for Tasmota + + Copyright (C) 2019 Theo Arends (translated by killadm) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_ZH_CN_H_ +#define _LANGUAGE_ZH_CN_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.14.0b +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 2052 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "zh" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "日 一 二 三 四 五 六 " +#define D_MONTH3LIST "1月 2月 3月 4月 5月 6月 7月 8月 9月 10月11月12月" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "空气质量" +#define D_AP "AP" // Access Point +#define D_AS "名称:" +#define D_AUTO "自动" +#define D_BLINK "闪烁" +#define D_BLINKOFF "闪烁关" +#define D_BOOT_COUNT "启动次数" +#define D_BRIGHTLIGHT "亮" +#define D_BSSID "BSSId" +#define D_BUTTON "按钮" +#define D_BY "汉化: killadm 作者:" // Written by me +#define D_BYTES "大小:" +#define D_CELSIUS "摄氏" +#define D_CHANNEL "频道" +#define D_CO2 "二氧化碳" +#define D_CODE "代码" // Button code +#define D_COLDLIGHT "冷" +#define D_COMMAND "命令:" +#define D_CONNECTED "已连接" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "数量:" +#define D_COUNTER "计数器" +#define D_CURRENT "电流" // As in Voltage and Current +#define D_DATA "数据:" +#define D_DARKLIGHT "暗" +#define D_DEBUG "调试" +#define D_DISABLED "禁用" +#define D_DISTANCE "距离" +#define D_DNS_SERVER "DNS服务器" +#define D_DONE "完成" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "设备模拟" +#define D_ENABLED "启用" +#define D_ERASE "擦除" +#define D_ERROR "错误" +#define D_FAHRENHEIT "华氏" +#define D_FAILED "失败" +#define D_FALLBACK "回退" +#define D_FALLBACK_TOPIC "回退主题" +#define D_FALSE "False" +#define D_FILE "文件:" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "空闲内存" +#define D_FREQUENCY "频率" +#define D_GAS "气体" +#define D_GATEWAY "网关" +#define D_GROUP "组:" +#define D_HOST "主机" +#define D_HOSTNAME "主机名" +#define D_HUMIDITY "湿度" +#define D_ILLUMINANCE "照度" +#define D_IMMEDIATE "单次按键" // Button immediate +#define D_INDEX "索引:" +#define D_INFO "信息" +#define D_INFRARED "红外线" +#define D_INITIALIZED "初始化完成" +#define D_IP_ADDRESS "IP地址" +#define D_LIGHT "灯" +#define D_LWT "LWT" +#define D_MODULE "模块" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "多次按键" +#define D_NOISE "嘈杂" +#define D_NONE "无" +#define D_OFF "关" +#define D_OFFLINE "离线" +#define D_OK "好" +#define D_ON "开" +#define D_ONLINE "在线" +#define D_PASSWORD "密码" +#define D_PORT "端口" +#define D_POWER_FACTOR "功率因数" +#define D_POWERUSAGE "功率" +#define D_POWERUSAGE_ACTIVE "有功功率" +#define D_POWERUSAGE_APPARENT "视在功率" +#define D_POWERUSAGE_REACTIVE "无功功率" +#define D_PRESSURE "气压" +#define D_PRESSUREATSEALEVEL "海平面气压" +#define D_PROGRAM_FLASH_SIZE "固件 Flash 大小" +#define D_PROGRAM_SIZE "固件大小" +#define D_PROJECT "项目:" +#define D_RAIN "降水量" +#define D_RECEIVED "已接收" +#define D_RESTART "重启" +#define D_RESTARTING "正在重启" +#define D_RESTART_REASON "重启原因" +#define D_RESTORE "恢复" +#define D_RETAINED "已保留" +#define D_RULE "规则" +#define D_SAVE "保存" +#define D_SENSOR "传感器" +#define D_SSID "名称" +#define D_START "开始" +#define D_STD_TIME "STD" +#define D_STOP "停止" +#define D_SUBNET_MASK "子网掩码" +#define D_SUBSCRIBE_TO "订阅" +#define D_UNSUBSCRIBE_FROM "退订" +#define D_SUCCESSFUL "成功" +#define D_SUNRISE "日出" +#define D_SUNSET "日落" +#define D_TEMPERATURE "温度" +#define D_TO "to" +#define D_TOGGLE "切换" +#define D_TOPIC "主题" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "发送" +#define D_TRUE "True" +#define D_TVOC "TVOC" +#define D_UPGRADE "升级" +#define D_UPLOAD "上传" +#define D_UPTIME "运行时间" +#define D_USER "用户名" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "紫外线指数" +#define D_UV_INDEX_1 "低" +#define D_UV_INDEX_2 "中" +#define D_UV_INDEX_3 "高" +#define D_UV_INDEX_4 "危险" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "紫外线水平" +#define D_UV_POWER "紫外线功率 " +#define D_VERSION "版本" +#define D_VOLTAGE "电压" +#define D_WEIGHT "重量" +#define D_WARMLIGHT "暖" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "警告:精简固件不支持配置持久化保存" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "串口日志已禁用" +#define D_SYSLOG_LOGGING_REENABLED "Syslog 日志已开启" + +#define D_SET_BAUDRATE_TO "设置波特率为:" +#define D_RECEIVED_TOPIC "接收到的主题:" +#define D_DATA_SIZE "数据大小:" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPS 配置失败,状态:" +#define D_ACTIVE_FOR_3_MINUTES "激活 3 分钟" +#define D_FAILED_TO_START "未能启动" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "连接到 AP" +#define D_IN_MODE "模式:" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "连接失败,因为没有获取到 IP 地址" +#define D_CONNECT_FAILED_AP_NOT_REACHED "连接失败,无法连接 AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "连接失败,AP 密码不正确" +#define D_CONNECT_FAILED_AP_TIMEOUT "连接失败,AP 超时" +#define D_ATTEMPTING_CONNECTION "尝试连接..." +#define D_CHECKING_CONNECTION "检查连接..." +#define D_QUERY_DONE "查询完成。 发现 MQTT 服务" +#define D_MQTT_SERVICE_FOUND "发现 MQTT 服务:" +#define D_FOUND_AT "发现:" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog 主机未找到" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "保存到 flash:" +#define D_LOADED_FROM_FLASH_AT "从 flash 载入:" +#define D_USE_DEFAULTS "使用默认设置" +#define D_ERASED_SECTOR "擦除扇区" + +// webserver.ino +#define D_NOSCRIPT "Tasmota要求浏览器支持 JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "当前是精简版固件
请升级" +#define D_WEBSERVER_ACTIVE_ON "Web 服务器地址:" +#define D_WITH_IP_ADDRESS "IP 地址:" +#define D_WEBSERVER_STOPPED "Web 服务已停止" +#define D_FILE_NOT_FOUND "文件未找到" +#define D_REDIRECTED "重定向到认证页面" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager 设置无线操作模式" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 设置接入点" +#define D_TRYING_TO_CONNECT "尝试将设备连接到网络" + +#define D_RESTART_IN "重启需要" +#define D_SECONDS "秒" +#define D_DEVICE_WILL_RESTART "设备将在几秒钟内重启" +#define D_BUTTON_TOGGLE "状态切换" +#define D_CONFIGURATION "设置" +#define D_INFORMATION "信息" +#define D_FIRMWARE_UPGRADE "固件升级" +#define D_CONSOLE "控制台" +#define D_CONFIRM_RESTART "确认重启" + +#define D_CONFIGURE_MODULE "模块设置" +#define D_CONFIGURE_WIFI "WiFi设置" +#define D_CONFIGURE_MQTT "MQTT设置" +#define D_CONFIGURE_DOMOTICZ "Domoticz设置" +#define D_CONFIGURE_LOGGING "日志设置" +#define D_CONFIGURE_OTHER "其他设置" +#define D_CONFIRM_RESET_CONFIGURATION "确认重置配置" +#define D_RESET_CONFIGURATION "重置配置" +#define D_BACKUP_CONFIGURATION "备份配置" +#define D_RESTORE_CONFIGURATION "还原配置" +#define D_MAIN_MENU "主菜单" + +#define D_MODULE_PARAMETERS "模块设置" +#define D_MODULE_TYPE "模块类型" +#define D_PULLUP_ENABLE "没有按钮/开关上拉" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "串口输入(RX)" +#define D_SERIAL_OUT "串口输出(TX)" + +#define D_WIFI_PARAMETERS "Wifi设置" +#define D_SCAN_FOR_WIFI_NETWORKS "扫描无线网络" +#define D_SCAN_DONE "扫描完毕" +#define D_NO_NETWORKS_FOUND "未找到任何网络" +#define D_REFRESH_TO_SCAN_AGAIN "刷新并重试" +#define D_DUPLICATE_ACCESSPOINT "重复AP" +#define D_SKIPPING_LOW_QUALITY "忽略弱信号网络" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 名称" +#define D_AP1_PASSWORD "AP1 密码" +#define D_AP2_SSID "AP2 名称" +#define D_AP2_PASSWORD "AP2 密码" + +#define D_MQTT_PARAMETERS "MQTT 设置" +#define D_CLIENT "客户端" +#define D_FULL_TOPIC "完整主题" + +#define D_LOGGING_PARAMETERS "日志设置" +#define D_SERIAL_LOG_LEVEL "串口日志级别" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web 日志级别" +#define D_SYS_LOG_LEVEL "Syslog 日志级别" +#define D_MORE_DEBUG "全部调试" +#define D_SYSLOG_HOST "Syslog 主机地址" +#define D_SYSLOG_PORT "Syslog 端口" +#define D_TELEMETRY_PERIOD "上报周期" + +#define D_OTHER_PARAMETERS "其他设置" +#define D_TEMPLATE "模板" +#define D_ACTIVATE "启用" +#define D_WEB_ADMIN_PASSWORD "WEB 管理密码" +#define D_MQTT_ENABLE "启用MQTT" +#define D_FRIENDLY_NAME "昵称" +#define D_BELKIN_WEMO "贝尔金 WeMo" +#define D_HUE_BRIDGE "飞利浦 Hue 网桥" +#define D_SINGLE_DEVICE "单设备" +#define D_MULTI_DEVICE "多设备" + +#define D_CONFIGURE_TEMPLATE "模板配置" +#define D_TEMPLATE_PARAMETERS "模板参数" +#define D_TEMPLATE_NAME "名称" +#define D_BASE_TYPE "基于" +#define D_TEMPLATE_FLAGS "选项" + +#define D_SAVE_CONFIGURATION "保存设置" +#define D_CONFIGURATION_SAVED "设置已保存" +#define D_CONFIGURATION_RESET "设置已重置" + +#define D_PROGRAM_VERSION "固件版本" +#define D_BUILD_DATE_AND_TIME "编译时间" +#define D_CORE_AND_SDK_VERSION "内核和 SDK 版本" +#define D_FLASH_WRITE_COUNT "Flash 写入次数" +#define D_MAC_ADDRESS "MAC 地址" +#define D_MQTT_HOST "MQTT 主机" +#define D_MQTT_PORT "MQTT 端口" +#define D_MQTT_CLIENT "MQTT 客户端" +#define D_MQTT_USER "MQTT 用户名" +#define D_MQTT_TOPIC "MQTT 主题" +#define D_MQTT_GROUP_TOPIC "MQTT 主题组" +#define D_MQTT_FULL_TOPIC "MQTT 完整主题" +#define D_MDNS_DISCOVERY "mDNS 发现" +#define D_MDNS_ADVERTISE "mDNS 广播" +#define D_ESP_CHIP_ID "ESP 芯片 ID" +#define D_FLASH_CHIP_ID "Flash 芯片 ID" +#define D_FLASH_CHIP_SIZE "Flash 大小" +#define D_FREE_PROGRAM_SPACE "空闲程序空间" + +#define D_UPGRADE_BY_WEBSERVER "通过 Web 升级" +#define D_OTA_URL "OTA 地址" +#define D_START_UPGRADE "开始升级" +#define D_UPGRADE_BY_FILE_UPLOAD "通过文件升级" +#define D_UPLOAD_STARTED "开始上传" +#define D_UPGRADE_STARTED "开始升级" +#define D_UPLOAD_DONE "上传完成" +#define D_UPLOAD_ERR_1 "没有选择任何文件" +#define D_UPLOAD_ERR_2 "没有足够空间" +#define D_UPLOAD_ERR_3 "固件头不是 0xE9" +#define D_UPLOAD_ERR_4 "固件大小超过 flash 容量" +#define D_UPLOAD_ERR_5 "上传缓冲区不足,请先刷入精简固件再升级" +#define D_UPLOAD_ERR_6 "上传失败。 启用日志级别 3 调试" +#define D_UPLOAD_ERR_7 "上传取消" +#define D_UPLOAD_ERR_8 "错误的固件" +#define D_UPLOAD_ERR_9 "固件太大" +#define D_UPLOAD_ERR_10 "初始化 RF 芯片失败" +#define D_UPLOAD_ERR_11 "擦除 RF 芯片失败" +#define D_UPLOAD_ERR_12 "写入 RF 芯片失败" +#define D_UPLOAD_ERR_13 "解码 RF 固件失败" +#define D_UPLOAD_ERROR_CODE "上传错误代码" + +#define D_ENTER_COMMAND "输入命令" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果想得到预期响应,请调整日志级别至: 2 信息" +#define D_NEED_USER_AND_PASSWORD "需要 user=<用户名>&password=<密码>" + +// xdrv_00_mqtt.ino +#define D_FINGERPRINT "验证 TLS 指纹..." +#define D_TLS_CONNECT_FAILED_TO "TLS 连接失败" +#define D_RETRY_IN "重试倒计时:" +#define D_VERIFIED "验证成功" +#define D_INSECURE "指纹无效导致连接不安全" +#define D_CONNECT_FAILED_TO "连接失败:" + +// xdrv_wemohue.ino +#define D_MULTICAST_DISABLED "组播已禁用" +#define D_MULTICAST_REJOINED "组播已(重新)加入" +#define D_MULTICAST_JOIN_FAILED "组播加入失败" +#define D_FAILED_TO_SEND_RESPONSE "请求发送失败" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo 基础事件" +#define D_WEMO_EVENT_SERVICE "WeMo 事件服务" +#define D_WEMO_META_SERVICE "WeMo meta 服务" +#define D_WEMO_SETUP "WeMo 设置" +#define D_RESPONSE_SENT "发送请求" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue 设置" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未实现" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST 参数" +#define D_3_RESPONSE_PACKETS_SENT "3 请求包发送" + +// xdrv_05_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz 设置" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "开关 idx" +#define D_DOMOTICZ_SENSOR_IDX "传感器 idx" + #define D_DOMOTICZ_TEMP "温度" + #define D_DOMOTICZ_TEMP_HUM "温度,湿度" + #define D_DOMOTICZ_TEMP_HUM_BARO "温度,湿度,气压" + #define D_DOMOTICZ_POWER_ENERGY "功率,电量" + #define D_DOMOTICZ_ILLUMINANCE "照度" + #define D_DOMOTICZ_COUNT "数值/PM1" + #define D_DOMOTICZ_VOLTAGE "电压/PM2.5" + #define D_DOMOTICZ_CURRENT "电流/PM10" + #define D_DOMOTICZ_AIRQUALITY "空气质量" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "更新计时器" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "定时器设置" +#define D_TIMER_PARAMETERS "定时器参数" +#define D_TIMER_ENABLE "启用定时器" +#define D_TIMER_ARM "启用" +#define D_TIMER_TIME "时间" +#define D_TIMER_DAYS "天" +#define D_TIMER_REPEAT "重复" +#define D_TIMER_OUTPUT "输出" +#define D_TIMER_ACTION "动作" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "KNX 配置" +#define D_KNX_PARAMETERS "KNX 参数" +#define D_KNX_GENERAL_CONFIG "同用" +#define D_KNX_PHYSICAL_ADDRESS "物理地址" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( 在 KNX 网络上必须是唯一的 )" +#define D_KNX_ENABLE "启用 KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "要发送到组地址的数据" +#define D_ADD "添加" +#define D_DELETE "删除" +#define D_REPLY "回复" +#define D_KNX_GROUP_ADDRESS_TO_READ "用来接收数据的组地址" +#define D_RECEIVED_FROM "接收自" +#define D_KNX_COMMAND_WRITE "写" +#define D_KNX_COMMAND_READ "读" +#define D_KNX_COMMAND_OTHER "其他" +#define D_SENT_TO "发送到" +#define D_KNX_WARNING "组地址(0/0/0)被保留,不能使用。" +#define D_KNX_ENHANCEMENT "通讯增强" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "今日用电量" +#define D_ENERGY_YESTERDAY "昨日用电量" +#define D_ENERGY_TOTAL "总用电量" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "传感器正忙" +#define D_SENSOR_CRC_ERROR "传感器 CRC 校验错误" +#define D_SENSORS_FOUND "发现传感器" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "等待超时" +#define D_START_SIGNAL_LOW "开始低电平" +#define D_START_SIGNAL_HIGH "开始高电平" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "校验失败" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "传感器没有确认命令" +#define D_SHT1X_FOUND "发现 SHT1X 传感器" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "颗粒物直径大于" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "加速度计X轴分量" +#define D_AY_AXIS "加速度计Y轴分量" +#define D_AZ_AXIS "加速度计Z轴分量" +#define D_GX_AXIS "绕X轴旋转的角速度" +#define D_GY_AXIS "绕Y轴旋转的角速度" +#define D_GZ_AXIS "绕Z轴旋转的角速度" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "去除重量" +#define D_HX_CAL_REFERENCE "加载参考重量" +#define D_HX_CAL_DONE "已校准" +#define D_HX_CAL_FAIL "校准失败" +#define D_RESET_HX711 "秤重置" +#define D_CONFIGURE_HX711 "秤配置" +#define D_HX711_PARAMETERS "秤参数" +#define D_ITEM_WEIGHT "物品中粮" +#define D_REFERENCE_WEIGHT "参考重量" +#define D_CALIBRATE "校准" +#define D_CALIBRATION "校准" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "风向" +#define D_TX20_WIND_SPEED "风速" +#define D_TX20_WIND_SPEED_AVG "平均风速" +#define D_TX20_WIND_SPEED_MAX "最高风速" +#define D_TX20_NORTH "北" +#define D_TX20_EAST "东" +#define D_TX20_SOUTH "南" +#define D_TX20_WEST "西" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "无" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "安" +#define D_UNIT_CENTIMETER "厘米" +#define D_UNIT_HERTZ "赫兹" +#define D_UNIT_HOUR "时" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "千克" +#define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h" +#define D_UNIT_KILOOHM "千欧" +#define D_UNIT_KILOWATTHOUR "千瓦时" +#define D_UNIT_LUX "勒克斯" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" +#define D_UNIT_MICROMETER "微米" +#define D_UNIT_MICROSECOND "微秒" +#define D_UNIT_MILLIAMPERE "毫安" +#define D_UNIT_MILLIMETER "毫米" +#define D_UNIT_MILLIMETER_MERCURY "毫米汞柱" +#define D_UNIT_MILLISECOND "毫秒" +#define D_UNIT_MINUTE "分" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "每分升" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "百帕" +#define D_UNIT_SECOND "秒" +#define D_UNIT_SECTORS "扇区" +#define D_UNIT_VA "伏安" +#define D_UNIT_VAR "无功伏安" +#define D_UNIT_VOLT "伏" +#define D_UNIT_WATT "瓦" +#define D_UNIT_WATTHOUR "瓦时" +#define D_UNIT_WATT_METER_QUADRAT "瓦/平米" + +//SDM220 +#define D_PHASE_ANGLE "相位角" +#define D_IMPORT_ACTIVE "有功输入" +#define D_EXPORT_ACTIVE "有功输出" +#define D_IMPORT_REACTIVE "无功输入" +#define D_EXPORT_REACTIVE "无功输出" +#define D_TOTAL_REACTIVE "总无功功率" +#define D_UNIT_KWARH "千乏时" +#define D_UNIT_ANGLE "度" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_ZH_CN_H_ diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index ed67b2931..1d78f181e 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -1,703 +1,701 @@ -/* - zh-TW.h - localization for Chinese (Traditional) - Taiwan for Tasmota - - Copyright (C) 2019 Theo Arends (translated by dannydu) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _LANGUAGE_ZH_TW_H_ -#define _LANGUAGE_ZH_TW_H_ - -/*************************** ATTENTION *******************************\ - * - * Due to memory constraints only UTF-8 is supported. - * To save code space keep text as short as possible. - * Time and Date provided by SDK can not be localized (yet). - * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. - * Use online command Prefix to translate cmnd, stat and tele. - * - * Updated until v5.12.0d -\*********************************************************************/ - -//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) - -#define LANGUAGE_LCID 1028 -// HTML (ISO 639-1) Language Code -#define D_HTML_LANGUAGE "zh" - -// "2017-03-07T11:08:02" - ISO8601:2004 -#define D_YEAR_MONTH_SEPARATOR "-" -#define D_MONTH_DAY_SEPARATOR "-" -#define D_DATE_TIME_SEPARATOR "T" -#define D_HOUR_MINUTE_SEPARATOR ":" -#define D_MINUTE_SECOND_SEPARATOR ":" - -#define D_DAY3LIST "SunMonTueWedThuFriSat" -#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" - -// Non JSON decimal separator -#define D_DECIMAL_SEPARATOR "." - -// Common -#define D_ADMIN "Admin" -#define D_AIR_QUALITY "空氣品質" -#define D_AP "AP" // Access Point -#define D_AS "名稱:" -#define D_AUTO "自動" -#define D_BLINK "閃爍" -#define D_BLINKOFF "閃爍關" -#define D_BOOT_COUNT "啟動次數" -#define D_BRIGHTLIGHT "亮度" -#define D_BSSID "BSSId" -#define D_BUTTON "按鈕" -#define D_BY "by" // Written by me -#define D_BYTES "大小:" -#define D_CELSIUS "攝氏" -#define D_CHANNEL "Channel" -#define D_CO2 "二氧化碳" -#define D_CODE "代碼" // Button code -#define D_COLDLIGHT "冷" -#define D_COMMAND "命令:" -#define D_CONNECTED "已連接" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "數量:" -#define D_COUNTER "Counter" -#define D_CURRENT "電流" // As in Voltage and Current -#define D_DATA "數據:" -#define D_DARKLIGHT "Dark" -#define D_DEBUG "除錯" -#define D_DISABLED "停用" -#define D_DISTANCE "Distance" -#define D_DNS_SERVER "DNS伺服器" -#define D_DONE "完成" -#define D_DST_TIME "DST" -#define D_ECO2 "eCO2" -#define D_EMULATION "設備模擬" -#define D_ENABLED "啟用" -#define D_ERASE "刪除" -#define D_ERROR "錯誤" -#define D_FAHRENHEIT "華氏" -#define D_FAILED "失敗" -#define D_FALLBACK "Fallback" -#define D_FALLBACK_TOPIC "Fallback Topic" -#define D_FALSE "False" -#define D_FILE "文件:" -#define D_FLOW_RATE "Flow rate" -#define D_FREE_MEMORY "可用記憶體" -#define D_FREQUENCY "Frequency" -#define D_GAS "氣體" -#define D_GATEWAY "網關" -#define D_GROUP "組:" -#define D_HOST "主機" -#define D_HOSTNAME "主機名" -#define D_HUMIDITY "濕度" -#define D_ILLUMINANCE "照度" -#define D_IMMEDIATE "immediate" // Button immediate -#define D_INDEX "索引:" -#define D_INFO "信息" -#define D_INFRARED "Infrared" -#define D_INITIALIZED "初始化完成" -#define D_IP_ADDRESS "IP地址" -#define D_LIGHT "燈" -#define D_LWT "LWT" -#define D_MODULE "模組" -#define D_MQTT "MQTT" -#define D_MULTI_PRESS "多次按鍵" -#define D_NOISE "雜訊" -#define D_NONE "無" -#define D_OFF "關" -#define D_OFFLINE "離線" -#define D_OK "好" -#define D_ON "開" -#define D_ONLINE "在線" -#define D_PASSWORD "密碼" -#define D_PORT "端口" -#define D_POWER_FACTOR "功率因數" -#define D_POWERUSAGE "功率" -#define D_POWERUSAGE_ACTIVE "Active Power" -#define D_POWERUSAGE_APPARENT "Apparent Power" -#define D_POWERUSAGE_REACTIVE "Reactive Power" -#define D_PRESSURE "氣壓" -#define D_PRESSUREATSEALEVEL "海平面氣壓" -#define D_PROGRAM_FLASH_SIZE "韌體 Flash 大小" -#define D_PROGRAM_SIZE "韌體大小" -#define D_PROJECT "項目:" -#define D_RAIN "Rain" -#define D_RECEIVED "已接收" -#define D_RESTART "重啟" -#define D_RESTARTING "正在重啟" -#define D_RESTART_REASON "重啟原因" -#define D_RESTORE "恢覆" -#define D_RETAINED "已保留" -#define D_RULE "Rule" -#define D_SAVE "存檔" -#define D_SENSOR "感測器" -#define D_SSID "名稱" -#define D_START "開始" -#define D_STD_TIME "STD" -#define D_STOP "停止" -#define D_SUBNET_MASK "子網遮罩" -#define D_SUBSCRIBE_TO "訂閱" -#define D_UNSUBSCRIBE_FROM "退訂" -#define D_SUCCESSFUL "成功" -#define D_SUNRISE "Sunrise" -#define D_SUNSET "Sunset" -#define D_TEMPERATURE "溫度" -#define D_TO "to" -#define D_TOGGLE "切換" -#define D_TOPIC "主題" -#define D_TOTAL_USAGE "Total Usage" -#define D_TRANSMIT "發送" -#define D_TRUE "True" -#define D_TVOC "TVOC" -#define D_UPGRADE "升級" -#define D_UPLOAD "上傳" -#define D_UPTIME "運行時間" -#define D_USER "用戶名" -#define D_UTC_TIME "UTC" -#define D_UV_INDEX "UV Index" -#define D_UV_INDEX_1 "Low" -#define D_UV_INDEX_2 "Mid" -#define D_UV_INDEX_3 "High" -#define D_UV_INDEX_4 "Danger" -#define D_UV_INDEX_5 "BurnL1/2" -#define D_UV_INDEX_6 "BurnL3" -#define D_UV_INDEX_7 "OoR" -#define D_UV_LEVEL "紫外線等級" -#define D_UV_POWER "UV Power" -#define D_VERSION "版本" -#define D_VOLTAGE "電壓" -#define D_WEIGHT "Weight" -#define D_WARMLIGHT "暖" -#define D_WEB_SERVER "Web Server" - -// tasmota.ino -#define D_WARNING_MINIMAL_VERSION "警告:精簡產品不支持配置寫入保存" -#define D_LEVEL_10 "level 1-0" -#define D_LEVEL_01 "level 0-1" -#define D_SERIAL_LOGGING_DISABLED "串口日誌已禁用" -#define D_SYSLOG_LOGGING_REENABLED "Syslog 日誌已開啟" - -#define D_SET_BAUDRATE_TO "設置波特率為:" -#define D_RECEIVED_TOPIC "接收到的主題:" -#define D_DATA_SIZE "數據大小:" -#define D_ANALOG_INPUT "Analog" - -// support.ino -#define D_OSWATCH "osWatch" -#define D_BLOCKED_LOOP "Blocked Loop" -#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" -#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" -#define D_FAILED_TO_START "未能啟動" -#define D_PATCH_ISSUE_2186 "Patch issue 2186" -#define D_CONNECTING_TO_AP "連接到 AP" -#define D_IN_MODE "模式:" -#define D_CONNECT_FAILED_NO_IP_ADDRESS "連接失敗,因為沒有獲取到IP地址" -#define D_CONNECT_FAILED_AP_NOT_REACHED "連接失敗,無法連接AP" -#define D_CONNECT_FAILED_WRONG_PASSWORD "連接失敗,AP密碼不正確" -#define D_CONNECT_FAILED_AP_TIMEOUT "連接失敗,AP超時" -#define D_ATTEMPTING_CONNECTION "嘗試連接..." -#define D_CHECKING_CONNECTION "檢查連接..." -#define D_QUERY_DONE "查詢完成。 發現MQTT服務" -#define D_MQTT_SERVICE_FOUND "發現MQTT服務:" -#define D_FOUND_AT "found at" -#define D_SYSLOG_HOST_NOT_FOUND "Syslog主機未找到" - -// settings.ino -#define D_SAVED_TO_FLASH_AT "保存到 flash:" -#define D_LOADED_FROM_FLASH_AT "從 flash 載入" -#define D_USE_DEFAULTS "使用默認設置" -#define D_ERASED_SECTOR "擦除刪除" - -// xdrv_02_webserver.ino -#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" -#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" -#define D_WEBSERVER_ACTIVE_ON "Web服務器:" -#define D_WITH_IP_ADDRESS "IP地址:" -#define D_WEBSERVER_STOPPED "Web 服務器已停止" -#define D_FILE_NOT_FOUND "文件未找到" -#define D_REDIRECTED "重定向到認證頁面" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" -#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 設置接入點" -#define D_TRYING_TO_CONNECT "嘗試將設備連接到網絡" - -#define D_RESTART_IN "重啟需要" -#define D_SECONDS "秒" -#define D_DEVICE_WILL_RESTART "設備將在幾分鐘內重啟" -#define D_BUTTON_TOGGLE "狀態切換" -#define D_CONFIGURATION "設置" -#define D_INFORMATION "信息" -#define D_FIRMWARE_UPGRADE "固件升級" -#define D_CONSOLE "控制台" -#define D_CONFIRM_RESTART "確認重啟" - -#define D_CONFIGURE_MODULE "模塊設置" -#define D_CONFIGURE_WIFI "WiFi設置" -#define D_CONFIGURE_MQTT "MQTT設置" -#define D_CONFIGURE_DOMOTICZ "Domoticz設置" -#define D_CONFIGURE_LOGGING "日志設置" -#define D_CONFIGURE_OTHER "其他設置" -#define D_CONFIRM_RESET_CONFIGURATION "確認重置配置" -#define D_RESET_CONFIGURATION "重置配置" -#define D_BACKUP_CONFIGURATION "備份配置" -#define D_RESTORE_CONFIGURATION "還原配置" -#define D_MAIN_MENU "主菜單" - -#define D_MODULE_PARAMETERS "模塊設置" -#define D_MODULE_TYPE "模塊類型" -#define D_PULLUP_ENABLE "No Button/Switch pull-up" -#define D_ADC "ADC" -#define D_GPIO "GPIO" -#define D_SERIAL_IN "串口輸入(RX)" -#define D_SERIAL_OUT "串口輸出(TX)" - -#define D_WIFI_PARAMETERS "Wifi設置" -#define D_SCAN_FOR_WIFI_NETWORKS "掃描無線網絡" -#define D_SCAN_DONE "掃描完畢" -#define D_NO_NETWORKS_FOUND "未找到任何網絡" -#define D_REFRESH_TO_SCAN_AGAIN "刷新並重試" -#define D_DUPLICATE_ACCESSPOINT "重覆AP" -#define D_SKIPPING_LOW_QUALITY "忽略弱信號網絡" -#define D_RSSI "RSSI" -#define D_WEP "WEP" -#define D_WPA_PSK "WPA PSK" -#define D_WPA2_PSK "WPA2 PSK" -#define D_AP1_SSID "AP1 名稱" -#define D_AP1_PASSWORD "AP1 密碼" -#define D_AP2_SSID "AP2 名稱" -#define D_AP2_PASSWORD "AP2 密碼" - -#define D_MQTT_PARAMETERS "MQTT設置" -#define D_CLIENT "客戶端" -#define D_FULL_TOPIC "完整主題" - -#define D_LOGGING_PARAMETERS "日志設置" -#define D_SERIAL_LOG_LEVEL "串口日志級別" -#define D_MQTT_LOG_LEVEL "Mqtt log level" -#define D_WEB_LOG_LEVEL "Web 日志級別" -#define D_SYS_LOG_LEVEL "Syslog 日志級別" -#define D_MORE_DEBUG "全部調試" -#define D_SYSLOG_HOST "Syslog 主機地址" -#define D_SYSLOG_PORT "Syslog 端口" -#define D_TELEMETRY_PERIOD "上報周期" - -#define D_OTHER_PARAMETERS "其他設置" -#define D_TEMPLATE "Template" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "WEB管理密碼" -#define D_MQTT_ENABLE "啟用MQTT" -#define D_FRIENDLY_NAME "昵稱" -#define D_BELKIN_WEMO "貝爾金 WeMo" -#define D_HUE_BRIDGE "飛利浦 Hue 網橋" -#define D_SINGLE_DEVICE "單設備" -#define D_MULTI_DEVICE "多設備" - -#define D_CONFIGURE_TEMPLATE "Configure Template" -#define D_TEMPLATE_PARAMETERS "Template parameters" -#define D_TEMPLATE_NAME "Name" -#define D_BASE_TYPE "Based on" -#define D_TEMPLATE_FLAGS "Options" - -#define D_SAVE_CONFIGURATION "保存設置" -#define D_CONFIGURATION_SAVED "設置已保存" -#define D_CONFIGURATION_RESET "設置已重置" - -#define D_PROGRAM_VERSION "固件版本" -#define D_BUILD_DATE_AND_TIME "編譯時間" -#define D_CORE_AND_SDK_VERSION "內核版本" -#define D_FLASH_WRITE_COUNT "刷機次數" -#define D_MAC_ADDRESS "MAC地址" -#define D_MQTT_HOST "MQTT主機" -#define D_MQTT_PORT "MQTT端口" -#define D_MQTT_CLIENT "MQTT客戶端" -#define D_MQTT_USER "MQTT用戶名" -#define D_MQTT_TOPIC "MQTT 主題(Topic)" -#define D_MQTT_GROUP_TOPIC "MQTT 主題組(Group Topic)" -#define D_MQTT_FULL_TOPIC "MQTT 完整主題(Full Topic)" -#define D_MDNS_DISCOVERY "mDNS 發現" -#define D_MDNS_ADVERTISE "mDNS 廣播" -#define D_ESP_CHIP_ID "ESP芯片ID" -#define D_FLASH_CHIP_ID "Flash芯片ID" -#define D_FLASH_CHIP_SIZE "Flash大小" -#define D_FREE_PROGRAM_SPACE "空閑程序空間" - -#define D_UPGRADE_BY_WEBSERVER "通過Web升級" -#define D_OTA_URL "OTA地址" -#define D_START_UPGRADE "開始升級" -#define D_UPGRADE_BY_FILE_UPLOAD "通過文件升級" -#define D_UPLOAD_STARTED "開始上傳" -#define D_UPGRADE_STARTED "開始升級" -#define D_UPLOAD_DONE "上傳完成" -#define D_UPLOAD_ERR_1 "沒有選擇文件" -#define D_UPLOAD_ERR_2 "沒有足夠空間" -#define D_UPLOAD_ERR_3 "固件頭不是 0xE9" -#define D_UPLOAD_ERR_4 "固件太大" -#define D_UPLOAD_ERR_5 "上傳緩沖區不匹配" -#define D_UPLOAD_ERR_6 "上傳失敗。 啟用日志記錄 3" -#define D_UPLOAD_ERR_7 "上傳取消" -#define D_UPLOAD_ERR_8 "錯誤的固件" -#define D_UPLOAD_ERR_9 "固件太大" -#define D_UPLOAD_ERR_10 "Failed to init RF chip" -#define D_UPLOAD_ERR_11 "Failed to erase RF chip" -#define D_UPLOAD_ERR_12 "Failed to write to RF chip" -#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" -#define D_UPLOAD_ERROR_CODE "上傳錯誤代碼" - -#define D_ENTER_COMMAND "輸入命令" -#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果預期響應,則啟用Weblog 2" -#define D_NEED_USER_AND_PASSWORD "需要 user=<用戶名>&password=<密碼>" - -// xdrv_01_mqtt.ino -#define D_FINGERPRINT "驗證 TLS 指紋..." -#define D_TLS_CONNECT_FAILED_TO "TLS 連接失敗" -#define D_RETRY_IN "重試倒計時:" -#define D_VERIFIED "驗證成功" -#define D_INSECURE "指紋無效導致連接不安全" -#define D_CONNECT_FAILED_TO "連接失敗:" - -// xplg_wemohue.ino -#define D_MULTICAST_DISABLED "組播已禁用" -#define D_MULTICAST_REJOINED "組播已(重新)加入" -#define D_MULTICAST_JOIN_FAILED "組播加入失敗" -#define D_FAILED_TO_SEND_RESPONSE "請求發送失敗" - -#define D_WEMO "WeMo" -#define D_WEMO_BASIC_EVENT "WeMo 基礎事件" -#define D_WEMO_EVENT_SERVICE "WeMo 事件服務" -#define D_WEMO_META_SERVICE "WeMo meta 服務" -#define D_WEMO_SETUP "WeMo 設置" -#define D_RESPONSE_SENT "發送請求" - -#define D_HUE "Hue" -#define D_HUE_BRIDGE_SETUP "Hue 設置" -#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未實現" -#define D_HUE_API "Hue API" -#define D_HUE_POST_ARGS "Hue POST 參數" -#define D_3_RESPONSE_PACKETS_SENT "3 請求包發送" - -// xdrv_07_domoticz.ino -#define D_DOMOTICZ_PARAMETERS "Domoticz 設置" -#define D_DOMOTICZ_IDX "Idx" -#define D_DOMOTICZ_KEY_IDX "Key idx" -#define D_DOMOTICZ_SWITCH_IDX "開關 idx" -#define D_DOMOTICZ_SENSOR_IDX "傳感器 idx" - #define D_DOMOTICZ_TEMP "溫度" - #define D_DOMOTICZ_TEMP_HUM "溫度,濕度" - #define D_DOMOTICZ_TEMP_HUM_BARO "溫度,濕度,氣壓" - #define D_DOMOTICZ_POWER_ENERGY "功率,電量" - #define D_DOMOTICZ_ILLUMINANCE "照度" - #define D_DOMOTICZ_COUNT "數值/PM1" - #define D_DOMOTICZ_VOLTAGE "電壓/PM2.5" - #define D_DOMOTICZ_CURRENT "電流/PM10" - #define D_DOMOTICZ_AIRQUALITY "空氣品質" - #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" -#define D_DOMOTICZ_UPDATE_TIMER "更新計時器" - -// xdrv_09_timers.ino -#define D_CONFIGURE_TIMER "Configure Timer" -#define D_TIMER_PARAMETERS "Timer parameters" -#define D_TIMER_ENABLE "Enable Timers" -#define D_TIMER_ARM "Arm" -#define D_TIMER_TIME "Time" -#define D_TIMER_DAYS "Days" -#define D_TIMER_REPEAT "Repeat" -#define D_TIMER_OUTPUT "Output" -#define D_TIMER_ACTION "Action" - -// xdrv_10_knx.ino -#define D_CONFIGURE_KNX "Configure KNX" -#define D_KNX_PARAMETERS "KNX Parameters" -#define D_KNX_GENERAL_CONFIG "General" -#define D_KNX_PHYSICAL_ADDRESS "Physical Address" -#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" -#define D_KNX_ENABLE "Enable KNX" -#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" -#define D_ADD "Add" -#define D_DELETE "Delete" -#define D_REPLY "Reply" -#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" -#define D_RECEIVED_FROM "Received from" -#define D_KNX_COMMAND_WRITE "Write" -#define D_KNX_COMMAND_READ "Read" -#define D_KNX_COMMAND_OTHER "Other" -#define D_SENT_TO "sent to" -#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." -#define D_KNX_ENHANCEMENT "Communication Enhancement" -#define D_KNX_TX_SLOT "KNX TX" -#define D_KNX_RX_SLOT "KNX RX" - -// xdrv_03_energy.ino -#define D_ENERGY_TODAY "今日用電量" -#define D_ENERGY_YESTERDAY "昨日用電量" -#define D_ENERGY_TOTAL "總用電量" - -// xdrv_27_shutter.ino -#define D_OPEN "Open" -#define D_CLOSE "Close" -#define D_DOMOTICZ_SHUTTER "Shutter" - -// xdrv_28_pcf8574.ino -#define D_CONFIGURE_PCF8574 "Configure PCF8574" -#define D_PCF8574_PARAMETERS "PCF8574 parameters" -#define D_INVERT_PORTS "Invert Ports" -#define D_DEVICE "Device" -#define D_DEVICE_INPUT "Input" -#define D_DEVICE_OUTPUT "Output" - -// xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "傳感器正忙" -#define D_SENSOR_CRC_ERROR "傳感器 CRC 校驗錯誤" -#define D_SENSORS_FOUND "發現傳感器" - -// xsns_06_dht.ino -#define D_TIMEOUT_WAITING_FOR "等待超時" -#define D_START_SIGNAL_LOW "開始低電平" -#define D_START_SIGNAL_HIGH "開始高電平" -#define D_PULSE "pulse" -#define D_CHECKSUM_FAILURE "校驗失敗" - -// xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "傳感器沒有確認命令" -#define D_SHT1X_FOUND "發現 SHT1X 傳感器" - -// xsns_18_pms5003.ino -#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter -#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter -#define D_PARTICALS_BEYOND "顆粒物直徑大於" - -// xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" - -// xsns_34_hx711.ino -#define D_HX_CAL_REMOVE "Remove weigth" -#define D_HX_CAL_REFERENCE "Load reference weigth" -#define D_HX_CAL_DONE "Calibrated" -#define D_HX_CAL_FAIL "Calibration failed" -#define D_RESET_HX711 "Reset Scale" -#define D_CONFIGURE_HX711 "Configure Scale" -#define D_HX711_PARAMETERS "Scale parameters" -#define D_ITEM_WEIGHT "Item weight" -#define D_REFERENCE_WEIGHT "Reference weigth" -#define D_CALIBRATE "Calibrate" -#define D_CALIBRATION "Calibration" - -//xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" -#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" -#define D_TX20_NORTH "N" -#define D_TX20_EAST "E" -#define D_TX20_SOUTH "S" -#define D_TX20_WEST "W" - -// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box -#define D_SENSOR_NONE "None" -#define D_SENSOR_USER "User" -#define D_SENSOR_DHT11 "DHT11" -#define D_SENSOR_AM2301 "AM2301" -#define D_SENSOR_SI7021 "SI7021" -#define D_SENSOR_DS18X20 "DS18x20" -#define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA "I2C SDA" -#define D_SENSOR_WS2812 "WS2812" -#define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "IRsend" -#define D_SENSOR_SWITCH "Switch" // Suffix "1" -#define D_SENSOR_BUTTON "Button" // Suffix "1" -#define D_SENSOR_RELAY "Relay" // Suffix "1i" -#define D_SENSOR_LED "Led" // Suffix "1i" -#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" -#define D_SENSOR_PWM "PWM" // Suffix "1" -#define D_SENSOR_COUNTER "Counter" // Suffix "1" -#define D_SENSOR_IRRECV "IRrecv" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" -#define D_SENSOR_SPI_CS "SPI CS" -#define D_SENSOR_SPI_DC "SPI DC" -#define D_SENSOR_SPI_MISO "SPI MISO" -#define D_SENSOR_SPI_MOSI "SPI MOSI" -#define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" -#define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" -#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" -#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" -#define D_SENSOR_TM1638_CLK "TM16 CLK" -#define D_SENSOR_TM1638_DIO "TM16 DIO" -#define D_SENSOR_TM1638_STB "TM16 STB" -#define D_SENSOR_HX711_SCK "HX711 SCK" -#define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" -#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" -#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" -#define D_SENSOR_SSPI_MISO "SSPI MISO" -#define D_SENSOR_SSPI_MOSI "SSPI MOSI" -#define D_SENSOR_SSPI_SCLK "SSPI SCLK" -#define D_SENSOR_SSPI_CS "SSPI CS" -#define D_SENSOR_SSPI_DC "SSPI DC" -#define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" -#define D_SENSOR_MAX31855_CS "MX31855 CS" -#define D_SENSOR_MAX31855_CLK "MX31855 CLK" -#define D_SENSOR_MAX31855_DO "MX31855 DO" -#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" -#define D_SENSOR_NRG_CF1 "HLWBL CF1" -#define D_SENSOR_HLW_CF "HLW8012 CF" -#define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" -#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" -#define D_SENSOR_SM16716_CLK "SM16716 CLK" -#define D_SENSOR_SM16716_DAT "SM16716 DAT" -#define D_SENSOR_SM16716_POWER "SM16716 PWR" -#define D_SENSOR_MY92X1_DI "MY92x1 DI" -#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" -#define D_SENSOR_ARIRFRCV "ALux IrRcv" -#define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" -#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" -#define D_SENSOR_HRE_CLOCK "HRE Clock" -#define D_SENSOR_HRE_DATA "HRE Data" -#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" -#define D_SENSOR_BUZZER "Buzzer" -#define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" -#define D_SENSOR_IBEACON_TX "iBeacon TX" -#define D_SENSOR_IBEACON_RX "iBeacon RX" -#define D_SENSOR_RDM6300_RX "RDM6300 RX" -#define D_SENSOR_CC1101_CS "CC1101 CS" -#define D_SENSOR_A4988_DIR "A4988 DIR" -#define D_SENSOR_A4988_STP "A4988 STP" -#define D_SENSOR_A4988_ENA "A4988 ENA" -#define D_SENSOR_A4988_MS1 "A4988 MS1" -#define D_SENSOR_A4988_MS2 "A4988 MS2" -#define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" -#define D_SENSOR_SM2135_CLK "SM2135 Clk" -#define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" -#define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" -#define D_SENSOR_GPS_TX "GPS TX" - -// Units -#define D_UNIT_AMPERE "安" -#define D_UNIT_CENTIMETER "cm" -#define D_UNIT_HERTZ "Hz" -#define D_UNIT_HOUR "時" -#define D_UNIT_GALLONS "gal" -#define D_UNIT_GALLONS_PER_MIN "g/m" -#define D_UNIT_INCREMENTS "inc" -#define D_UNIT_KILOGRAM "kg" -#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" -#define D_UNIT_KILOOHM "千歐" -#define D_UNIT_KILOWATTHOUR "千瓦時" -#define D_UNIT_LUX "勒克斯" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" -#define D_UNIT_MICROMETER "微米" -#define D_UNIT_MICROSECOND "微秒" -#define D_UNIT_MILLIAMPERE "毫安" -#define D_UNIT_MILLIMETER "mm" -#define D_UNIT_MILLIMETER_MERCURY "mmHg" -#define D_UNIT_MILLISECOND "毫秒" -#define D_UNIT_MINUTE "分" -#define D_UNIT_PARTS_PER_BILLION "ppb" -#define D_UNIT_PARTS_PER_DECILITER "每分升" -#define D_UNIT_PARTS_PER_MILLION "ppm" -#define D_UNIT_PRESSURE "百帕" -#define D_UNIT_SECOND "秒" -#define D_UNIT_SECTORS "扇區" -#define D_UNIT_VA "VA" -#define D_UNIT_VAR "VAr" -#define D_UNIT_VOLT "伏" -#define D_UNIT_WATT "瓦" -#define D_UNIT_WATTHOUR "瓦時" -#define D_UNIT_WATT_METER_QUADRAT "W/m²" - -//SDM220 -#define D_PHASE_ANGLE "Phase Angle" -#define D_IMPORT_ACTIVE "Import Active" -#define D_EXPORT_ACTIVE "Export Active" -#define D_IMPORT_REACTIVE "Import Reactive" -#define D_EXPORT_REACTIVE "Export Reactive" -#define D_TOTAL_REACTIVE "Total Reactive" -#define D_UNIT_KWARH "kVArh" -#define D_UNIT_ANGLE "Deg" - -//SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" - -#endif // _LANGUAGE_ZH_TW_H_ +/* + zh-TW.h - localization for Chinese (Traditional) - Taiwan for Tasmota + + Copyright (C) 2019 Theo Arends (translated by dannydu) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_ZH_TW_H_ +#define _LANGUAGE_ZH_TW_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v5.12.0d +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) + +#define LANGUAGE_LCID 1028 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "zh" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "SunMonTueWedThuFriSat" +#define D_MONTH3LIST "JanFebMarAprMayJunJulAugSepOctNovDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "空氣品質" +#define D_AP "AP" // Access Point +#define D_AS "名稱:" +#define D_AUTO "自動" +#define D_BLINK "閃爍" +#define D_BLINKOFF "閃爍關" +#define D_BOOT_COUNT "啟動次數" +#define D_BRIGHTLIGHT "亮度" +#define D_BSSID "BSSId" +#define D_BUTTON "按鈕" +#define D_BY "by" // Written by me +#define D_BYTES "大小:" +#define D_CELSIUS "攝氏" +#define D_CHANNEL "Channel" +#define D_CO2 "二氧化碳" +#define D_CODE "代碼" // Button code +#define D_COLDLIGHT "冷" +#define D_COMMAND "命令:" +#define D_CONNECTED "已連接" +#define D_CORS_DOMAIN "CORS Domain" +#define D_COUNT "數量:" +#define D_COUNTER "Counter" +#define D_CURRENT "電流" // As in Voltage and Current +#define D_DATA "數據:" +#define D_DARKLIGHT "Dark" +#define D_DEBUG "除錯" +#define D_DISABLED "停用" +#define D_DISTANCE "Distance" +#define D_DNS_SERVER "DNS伺服器" +#define D_DONE "完成" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO2" +#define D_EMULATION "設備模擬" +#define D_ENABLED "啟用" +#define D_ERASE "刪除" +#define D_ERROR "錯誤" +#define D_FAHRENHEIT "華氏" +#define D_FAILED "失敗" +#define D_FALLBACK "Fallback" +#define D_FALLBACK_TOPIC "Fallback Topic" +#define D_FALSE "False" +#define D_FILE "文件:" +#define D_FLOW_RATE "Flow rate" +#define D_FREE_MEMORY "可用記憶體" +#define D_FREQUENCY "Frequency" +#define D_GAS "氣體" +#define D_GATEWAY "網關" +#define D_GROUP "組:" +#define D_HOST "主機" +#define D_HOSTNAME "主機名" +#define D_HUMIDITY "濕度" +#define D_ILLUMINANCE "照度" +#define D_IMMEDIATE "immediate" // Button immediate +#define D_INDEX "索引:" +#define D_INFO "信息" +#define D_INFRARED "Infrared" +#define D_INITIALIZED "初始化完成" +#define D_IP_ADDRESS "IP地址" +#define D_LIGHT "燈" +#define D_LWT "LWT" +#define D_MODULE "模組" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "多次按鍵" +#define D_NOISE "雜訊" +#define D_NONE "無" +#define D_OFF "關" +#define D_OFFLINE "離線" +#define D_OK "好" +#define D_ON "開" +#define D_ONLINE "在線" +#define D_PASSWORD "密碼" +#define D_PORT "端口" +#define D_POWER_FACTOR "功率因數" +#define D_POWERUSAGE "功率" +#define D_POWERUSAGE_ACTIVE "Active Power" +#define D_POWERUSAGE_APPARENT "Apparent Power" +#define D_POWERUSAGE_REACTIVE "Reactive Power" +#define D_PRESSURE "氣壓" +#define D_PRESSUREATSEALEVEL "海平面氣壓" +#define D_PROGRAM_FLASH_SIZE "韌體 Flash 大小" +#define D_PROGRAM_SIZE "韌體大小" +#define D_PROJECT "項目:" +#define D_RAIN "Rain" +#define D_RECEIVED "已接收" +#define D_RESTART "重啟" +#define D_RESTARTING "正在重啟" +#define D_RESTART_REASON "重啟原因" +#define D_RESTORE "恢覆" +#define D_RETAINED "已保留" +#define D_RULE "Rule" +#define D_SAVE "存檔" +#define D_SENSOR "感測器" +#define D_SSID "名稱" +#define D_START "開始" +#define D_STD_TIME "STD" +#define D_STOP "停止" +#define D_SUBNET_MASK "子網遮罩" +#define D_SUBSCRIBE_TO "訂閱" +#define D_UNSUBSCRIBE_FROM "退訂" +#define D_SUCCESSFUL "成功" +#define D_SUNRISE "Sunrise" +#define D_SUNSET "Sunset" +#define D_TEMPERATURE "溫度" +#define D_TO "to" +#define D_TOGGLE "切換" +#define D_TOPIC "主題" +#define D_TOTAL_USAGE "Total Usage" +#define D_TRANSMIT "發送" +#define D_TRUE "True" +#define D_TVOC "TVOC" +#define D_UPGRADE "升級" +#define D_UPLOAD "上傳" +#define D_UPTIME "運行時間" +#define D_USER "用戶名" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "UV Index" +#define D_UV_INDEX_1 "Low" +#define D_UV_INDEX_2 "Mid" +#define D_UV_INDEX_3 "High" +#define D_UV_INDEX_4 "Danger" +#define D_UV_INDEX_5 "BurnL1/2" +#define D_UV_INDEX_6 "BurnL3" +#define D_UV_INDEX_7 "OoR" +#define D_UV_LEVEL "紫外線等級" +#define D_UV_POWER "UV Power" +#define D_VERSION "版本" +#define D_VOLTAGE "電壓" +#define D_WEIGHT "Weight" +#define D_WARMLIGHT "暖" +#define D_WEB_SERVER "Web Server" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "警告:精簡產品不支持配置寫入保存" +#define D_LEVEL_10 "level 1-0" +#define D_LEVEL_01 "level 0-1" +#define D_SERIAL_LOGGING_DISABLED "串口日誌已禁用" +#define D_SYSLOG_LOGGING_REENABLED "Syslog 日誌已開啟" + +#define D_SET_BAUDRATE_TO "設置波特率為:" +#define D_RECEIVED_TOPIC "接收到的主題:" +#define D_DATA_SIZE "數據大小:" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Blocked Loop" +#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status" +#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes" +#define D_FAILED_TO_START "未能啟動" +#define D_PATCH_ISSUE_2186 "Patch issue 2186" +#define D_CONNECTING_TO_AP "連接到 AP" +#define D_IN_MODE "模式:" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "連接失敗,因為沒有獲取到IP地址" +#define D_CONNECT_FAILED_AP_NOT_REACHED "連接失敗,無法連接AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "連接失敗,AP密碼不正確" +#define D_CONNECT_FAILED_AP_TIMEOUT "連接失敗,AP超時" +#define D_ATTEMPTING_CONNECTION "嘗試連接..." +#define D_CHECKING_CONNECTION "檢查連接..." +#define D_QUERY_DONE "查詢完成。 發現MQTT服務" +#define D_MQTT_SERVICE_FOUND "發現MQTT服務:" +#define D_FOUND_AT "found at" +#define D_SYSLOG_HOST_NOT_FOUND "Syslog主機未找到" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "保存到 flash:" +#define D_LOADED_FROM_FLASH_AT "從 flash 載入" +#define D_USE_DEFAULTS "使用默認設置" +#define D_ERASED_SECTOR "擦除刪除" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "To use Tasmota, please enable JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "固件版本過低
請升級" +#define D_WEBSERVER_ACTIVE_ON "Web服務器:" +#define D_WITH_IP_ADDRESS "IP地址:" +#define D_WEBSERVER_STOPPED "Web 服務器已停止" +#define D_FILE_NOT_FOUND "文件未找到" +#define D_REDIRECTED "重定向到認證頁面" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager 設置接入點" +#define D_TRYING_TO_CONNECT "嘗試將設備連接到網絡" + +#define D_RESTART_IN "重啟需要" +#define D_SECONDS "秒" +#define D_DEVICE_WILL_RESTART "設備將在幾分鐘內重啟" +#define D_BUTTON_TOGGLE "狀態切換" +#define D_CONFIGURATION "設置" +#define D_INFORMATION "信息" +#define D_FIRMWARE_UPGRADE "固件升級" +#define D_CONSOLE "控制台" +#define D_CONFIRM_RESTART "確認重啟" + +#define D_CONFIGURE_MODULE "模塊設置" +#define D_CONFIGURE_WIFI "WiFi設置" +#define D_CONFIGURE_MQTT "MQTT設置" +#define D_CONFIGURE_DOMOTICZ "Domoticz設置" +#define D_CONFIGURE_LOGGING "日志設置" +#define D_CONFIGURE_OTHER "其他設置" +#define D_CONFIRM_RESET_CONFIGURATION "確認重置配置" +#define D_RESET_CONFIGURATION "重置配置" +#define D_BACKUP_CONFIGURATION "備份配置" +#define D_RESTORE_CONFIGURATION "還原配置" +#define D_MAIN_MENU "主菜單" + +#define D_MODULE_PARAMETERS "模塊設置" +#define D_MODULE_TYPE "模塊類型" +#define D_PULLUP_ENABLE "No Button/Switch pull-up" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "串口輸入(RX)" +#define D_SERIAL_OUT "串口輸出(TX)" + +#define D_WIFI_PARAMETERS "Wifi設置" +#define D_SCAN_FOR_WIFI_NETWORKS "掃描無線網絡" +#define D_SCAN_DONE "掃描完畢" +#define D_NO_NETWORKS_FOUND "未找到任何網絡" +#define D_REFRESH_TO_SCAN_AGAIN "刷新並重試" +#define D_DUPLICATE_ACCESSPOINT "重覆AP" +#define D_SKIPPING_LOW_QUALITY "忽略弱信號網絡" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 名稱" +#define D_AP1_PASSWORD "AP1 密碼" +#define D_AP2_SSID "AP2 名稱" +#define D_AP2_PASSWORD "AP2 密碼" + +#define D_MQTT_PARAMETERS "MQTT設置" +#define D_CLIENT "客戶端" +#define D_FULL_TOPIC "完整主題" + +#define D_LOGGING_PARAMETERS "日志設置" +#define D_SERIAL_LOG_LEVEL "串口日志級別" +#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_WEB_LOG_LEVEL "Web 日志級別" +#define D_SYS_LOG_LEVEL "Syslog 日志級別" +#define D_MORE_DEBUG "全部調試" +#define D_SYSLOG_HOST "Syslog 主機地址" +#define D_SYSLOG_PORT "Syslog 端口" +#define D_TELEMETRY_PERIOD "上報周期" + +#define D_OTHER_PARAMETERS "其他設置" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activate" +#define D_WEB_ADMIN_PASSWORD "WEB管理密碼" +#define D_MQTT_ENABLE "啟用MQTT" +#define D_FRIENDLY_NAME "昵稱" +#define D_BELKIN_WEMO "貝爾金 WeMo" +#define D_HUE_BRIDGE "飛利浦 Hue 網橋" +#define D_SINGLE_DEVICE "單設備" +#define D_MULTI_DEVICE "多設備" + +#define D_CONFIGURE_TEMPLATE "Configure Template" +#define D_TEMPLATE_PARAMETERS "Template parameters" +#define D_TEMPLATE_NAME "Name" +#define D_BASE_TYPE "Based on" +#define D_TEMPLATE_FLAGS "Options" + +#define D_SAVE_CONFIGURATION "保存設置" +#define D_CONFIGURATION_SAVED "設置已保存" +#define D_CONFIGURATION_RESET "設置已重置" + +#define D_PROGRAM_VERSION "固件版本" +#define D_BUILD_DATE_AND_TIME "編譯時間" +#define D_CORE_AND_SDK_VERSION "內核版本" +#define D_FLASH_WRITE_COUNT "刷機次數" +#define D_MAC_ADDRESS "MAC地址" +#define D_MQTT_HOST "MQTT主機" +#define D_MQTT_PORT "MQTT端口" +#define D_MQTT_CLIENT "MQTT客戶端" +#define D_MQTT_USER "MQTT用戶名" +#define D_MQTT_TOPIC "MQTT 主題(Topic)" +#define D_MQTT_GROUP_TOPIC "MQTT 主題組(Group Topic)" +#define D_MQTT_FULL_TOPIC "MQTT 完整主題(Full Topic)" +#define D_MDNS_DISCOVERY "mDNS 發現" +#define D_MDNS_ADVERTISE "mDNS 廣播" +#define D_ESP_CHIP_ID "ESP芯片ID" +#define D_FLASH_CHIP_ID "Flash芯片ID" +#define D_FLASH_CHIP_SIZE "Flash大小" +#define D_FREE_PROGRAM_SPACE "空閑程序空間" + +#define D_UPGRADE_BY_WEBSERVER "通過Web升級" +#define D_OTA_URL "OTA地址" +#define D_START_UPGRADE "開始升級" +#define D_UPGRADE_BY_FILE_UPLOAD "通過文件升級" +#define D_UPLOAD_STARTED "開始上傳" +#define D_UPGRADE_STARTED "開始升級" +#define D_UPLOAD_DONE "上傳完成" +#define D_UPLOAD_ERR_1 "沒有選擇文件" +#define D_UPLOAD_ERR_2 "沒有足夠空間" +#define D_UPLOAD_ERR_3 "固件頭不是 0xE9" +#define D_UPLOAD_ERR_4 "固件太大" +#define D_UPLOAD_ERR_5 "上傳緩沖區不匹配" +#define D_UPLOAD_ERR_6 "上傳失敗。 啟用日志記錄 3" +#define D_UPLOAD_ERR_7 "上傳取消" +#define D_UPLOAD_ERR_8 "錯誤的固件" +#define D_UPLOAD_ERR_9 "固件太大" +#define D_UPLOAD_ERR_10 "Failed to init RF chip" +#define D_UPLOAD_ERR_11 "Failed to erase RF chip" +#define D_UPLOAD_ERR_12 "Failed to write to RF chip" +#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERROR_CODE "上傳錯誤代碼" + +#define D_ENTER_COMMAND "輸入命令" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "如果預期響應,則啟用Weblog 2" +#define D_NEED_USER_AND_PASSWORD "需要 user=<用戶名>&password=<密碼>" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "驗證 TLS 指紋..." +#define D_TLS_CONNECT_FAILED_TO "TLS 連接失敗" +#define D_RETRY_IN "重試倒計時:" +#define D_VERIFIED "驗證成功" +#define D_INSECURE "指紋無效導致連接不安全" +#define D_CONNECT_FAILED_TO "連接失敗:" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "組播已禁用" +#define D_MULTICAST_REJOINED "組播已(重新)加入" +#define D_MULTICAST_JOIN_FAILED "組播加入失敗" +#define D_FAILED_TO_SEND_RESPONSE "請求發送失敗" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo 基礎事件" +#define D_WEMO_EVENT_SERVICE "WeMo 事件服務" +#define D_WEMO_META_SERVICE "WeMo meta 服務" +#define D_WEMO_SETUP "WeMo 設置" +#define D_RESPONSE_SENT "發送請求" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Hue 設置" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API 未實現" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST 參數" +#define D_3_RESPONSE_PACKETS_SENT "3 請求包發送" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Domoticz 設置" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "開關 idx" +#define D_DOMOTICZ_SENSOR_IDX "傳感器 idx" + #define D_DOMOTICZ_TEMP "溫度" + #define D_DOMOTICZ_TEMP_HUM "溫度,濕度" + #define D_DOMOTICZ_TEMP_HUM_BARO "溫度,濕度,氣壓" + #define D_DOMOTICZ_POWER_ENERGY "功率,電量" + #define D_DOMOTICZ_ILLUMINANCE "照度" + #define D_DOMOTICZ_COUNT "數值/PM1" + #define D_DOMOTICZ_VOLTAGE "電壓/PM2.5" + #define D_DOMOTICZ_CURRENT "電流/PM10" + #define D_DOMOTICZ_AIRQUALITY "空氣品質" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "更新計時器" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configure Timer" +#define D_TIMER_PARAMETERS "Timer parameters" +#define D_TIMER_ENABLE "Enable Timers" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Time" +#define D_TIMER_DAYS "Days" +#define D_TIMER_REPEAT "Repeat" +#define D_TIMER_OUTPUT "Output" +#define D_TIMER_ACTION "Action" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configure KNX" +#define D_KNX_PARAMETERS "KNX Parameters" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Physical Address" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )" +#define D_KNX_ENABLE "Enable KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses" +#define D_ADD "Add" +#define D_DELETE "Delete" +#define D_REPLY "Reply" +#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from" +#define D_RECEIVED_FROM "Received from" +#define D_KNX_COMMAND_WRITE "Write" +#define D_KNX_COMMAND_READ "Read" +#define D_KNX_COMMAND_OTHER "Other" +#define D_SENT_TO "sent to" +#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used." +#define D_KNX_ENHANCEMENT "Communication Enhancement" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "今日用電量" +#define D_ENERGY_YESTERDAY "昨日用電量" +#define D_ENERGY_TOTAL "總用電量" + +// xdrv_27_shutter.ino +#define D_OPEN "Open" +#define D_CLOSE "Close" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configure PCF8574" +#define D_PCF8574_PARAMETERS "PCF8574 parameters" +#define D_INVERT_PORTS "Invert Ports" +#define D_DEVICE "Device" +#define D_DEVICE_INPUT "Input" +#define D_DEVICE_OUTPUT "Output" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "傳感器正忙" +#define D_SENSOR_CRC_ERROR "傳感器 CRC 校驗錯誤" +#define D_SENSORS_FOUND "發現傳感器" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "等待超時" +#define D_START_SIGNAL_LOW "開始低電平" +#define D_START_SIGNAL_HIGH "開始高電平" +#define D_PULSE "pulse" +#define D_CHECKSUM_FAILURE "校驗失敗" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "傳感器沒有確認命令" +#define D_SHT1X_FOUND "發現 SHT1X 傳感器" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "顆粒物直徑大於" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel. X-Axis" +#define D_AY_AXIS "Accel. Y-Axis" +#define D_AZ_AXIS "Accel. Z-Axis" +#define D_GX_AXIS "Gyro X-Axis" +#define D_GY_AXIS "Gyro Y-Axis" +#define D_GZ_AXIS "Gyro Z-Axis" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Remove weigth" +#define D_HX_CAL_REFERENCE "Load reference weigth" +#define D_HX_CAL_DONE "Calibrated" +#define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "None" +#define D_SENSOR_USER "User" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Switch" // Suffix "1" +#define D_SENSOR_BUTTON "Button" // Suffix "1" +#define D_SENSOR_RELAY "Relay" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Counter" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" + +// Units +#define D_UNIT_AMPERE "安" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "時" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "千歐" +#define D_UNIT_KILOWATTHOUR "千瓦時" +#define D_UNIT_LUX "勒克斯" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "微克/立方米" +#define D_UNIT_MICROMETER "微米" +#define D_UNIT_MICROSECOND "微秒" +#define D_UNIT_MILLIAMPERE "毫安" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "毫秒" +#define D_UNIT_MINUTE "分" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "每分升" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "百帕" +#define D_UNIT_SECOND "秒" +#define D_UNIT_SECTORS "扇區" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "伏" +#define D_UNIT_WATT "瓦" +#define D_UNIT_WATTHOUR "瓦時" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220 +#define D_PHASE_ANGLE "Phase Angle" +#define D_IMPORT_ACTIVE "Import Active" +#define D_EXPORT_ACTIVE "Export Active" +#define D_IMPORT_REACTIVE "Import Reactive" +#define D_EXPORT_REACTIVE "Export Reactive" +#define D_TOTAL_REACTIVE "Total Reactive" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltage" +#define D_PV1_CURRENT "PV1 Current" +#define D_PV1_POWER "PV1 Power" +#define D_PV2_VOLTAGE "PV2 Voltage" +#define D_PV2_CURRENT "PV2 Current" +#define D_PV2_POWER "PV2 Power" +#define D_SOLAR_POWER "Solar Power" +#define D_INVERTER_POWER "Inverter Power" +#define D_STATUS "Status" +#define D_WAITING "Waiting" +#define D_CHECKING "Checking" +#define D_WORKING "Working" +#define D_FAILURE "Failure" +#define D_SOLAX_ERROR_0 "No Error Code" +#define D_SOLAX_ERROR_1 "Grid Lost Fault" +#define D_SOLAX_ERROR_2 "Grid Voltage Fault" +#define D_SOLAX_ERROR_3 "Grid Frequency Fault" +#define D_SOLAX_ERROR_4 "Pv Voltage Fault" +#define D_SOLAX_ERROR_5 "Isolation Fault" +#define D_SOLAX_ERROR_6 "Over Temperature Fault" +#define D_SOLAX_ERROR_7 "Fan Fault" +#define D_SOLAX_ERROR_8 "Other Device Fault" + +#endif // _LANGUAGE_ZH_TW_H_ From 69a79c83a513c7b0c38468e9ed9210115f6487ea Mon Sep 17 00:00:00 2001 From: ascillato Date: Mon, 16 Dec 2019 23:16:25 -0300 Subject: [PATCH 081/559] Add GPS Support - Language Files --- tasmota/language/bg-BG.h | 2 ++ tasmota/language/cs-CZ.h | 2 ++ tasmota/language/de-DE.h | 2 ++ tasmota/language/el-GR.h | 2 ++ tasmota/language/en-GB.h | 2 ++ tasmota/language/es-ES.h | 8 +++++--- tasmota/language/fr-FR.h | 2 ++ tasmota/language/he-HE.h | 2 ++ tasmota/language/hu-HU.h | 2 ++ tasmota/language/it-IT.h | 2 ++ tasmota/language/ko-KO.h | 2 ++ tasmota/language/nl-NL.h | 2 ++ tasmota/language/pl-PL.h | 2 ++ tasmota/language/pt-BR.h | 2 ++ tasmota/language/pt-PT.h | 2 ++ tasmota/language/ru-RU.h | 2 ++ tasmota/language/sk-SK.h | 2 ++ tasmota/language/sv-SE.h | 2 ++ tasmota/language/tr-TR.h | 2 ++ tasmota/language/uk-UK.h | 2 ++ tasmota/language/zh-CN.h | 2 ++ tasmota/language/zh-TW.h | 2 ++ 22 files changed, 47 insertions(+), 3 deletions(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 1f18d8efb..4ef69b318 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 1d7c6f381..242cc3ab9 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 6569dd232..0ed4119aa 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index f8b9c9614..f694c53a6 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 257a34c86..14211c20d 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 7527bb77a..ddaf76aed 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -626,9 +626,11 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index e107409e3..a49acb3e1 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index ac4dadb8e..2a93b0b61 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 62806fa46..b27c12f87 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 0585c12d8..e59a71df2 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index bff508474..aafa93855 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 75d841ddc..977d0ae02 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 8f5af6813..47550d9e0 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 0efa57789..248955a92 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index a6299c0c8..7ccfa6c08 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 3bd788ede..cedad2664 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index a64e49e01..448dcd7b0 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index 51ffc2ae3..c87941b24 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 6bc48c40f..32b37edf9 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/uk-UK.h b/tasmota/language/uk-UK.h index b4a314630..31f420b8f 100644 --- a/tasmota/language/uk-UK.h +++ b/tasmota/language/uk-UK.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 21aa63be3..7d9ecfd46 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "安" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 1d78f181e..5b633920e 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -629,6 +629,8 @@ #define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" // Units #define D_UNIT_AMPERE "安" From 1a02f52de950bcafe707680488f59a9af549a18d Mon Sep 17 00:00:00 2001 From: ascillato Date: Mon, 16 Dec 2019 23:29:36 -0300 Subject: [PATCH 082/559] Add NTP Local Server Library --- lib/ArduinoNTPd/NTPPacket.cpp | 39 +++++++++++++++++ lib/ArduinoNTPd/NTPPacket.h | 75 +++++++++++++++++++++++++++++++++ lib/ArduinoNTPd/NTPServer.cpp | 79 +++++++++++++++++++++++++++++++++++ lib/ArduinoNTPd/NTPServer.h | 35 ++++++++++++++++ tasmota/xsns_58_GPS.ino | 2 +- 5 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 lib/ArduinoNTPd/NTPPacket.cpp create mode 100644 lib/ArduinoNTPd/NTPPacket.h create mode 100644 lib/ArduinoNTPd/NTPServer.cpp create mode 100644 lib/ArduinoNTPd/NTPServer.h diff --git a/lib/ArduinoNTPd/NTPPacket.cpp b/lib/ArduinoNTPd/NTPPacket.cpp new file mode 100644 index 000000000..e3cdf6b32 --- /dev/null +++ b/lib/ArduinoNTPd/NTPPacket.cpp @@ -0,0 +1,39 @@ +/* + * File: NTPPacket.cpp + * Description: + * NTP packet representation. + * Author: Mooneer Salem + * License: New BSD License + */ + +#include "NTPPacket.h" + +void NtpPacket::swapEndian() +{ + reverseBytes_(&rootDelay); + reverseBytes_(&rootDispersion); + reverseBytes_(&referenceTimestampSeconds); + reverseBytes_(&referenceTimestampFraction); + reverseBytes_(&originTimestampSeconds); + reverseBytes_(&originTimestampFraction); + reverseBytes_(&receiveTimestampSeconds); + reverseBytes_(&receiveTimestampFraction); + reverseBytes_(&transmitTimestampSeconds); + reverseBytes_(&transmitTimestampFraction); +} + +void NtpPacket::reverseBytes_(uint32_t *number) +{ + char buf[4]; + char *numberAsChar = (char*)number; + + buf[0] = numberAsChar[3]; + buf[1] = numberAsChar[2]; + buf[2] = numberAsChar[1]; + buf[3] = numberAsChar[0]; + + numberAsChar[0] = buf[0]; + numberAsChar[1] = buf[1]; + numberAsChar[2] = buf[2]; + numberAsChar[3] = buf[3]; +} diff --git a/lib/ArduinoNTPd/NTPPacket.h b/lib/ArduinoNTPd/NTPPacket.h new file mode 100644 index 000000000..80a1366f5 --- /dev/null +++ b/lib/ArduinoNTPd/NTPPacket.h @@ -0,0 +1,75 @@ +/* + * File: NTPPacket.h + * Description: + * NTP packet representation. + * Author: Mooneer Salem + * License: New BSD License + */ + +#ifndef NTP_PACKET_H +#define NTP_PACKET_H + +#include "Arduino.h" + + +/* + * Contains the data in a typical NTP packet. + */ +struct NtpPacket +{ + static const int PACKET_SIZE = 48; + + unsigned char leapVersionMode; + + unsigned int leapIndicator() const { return leapVersionMode >> 6; } + void leapIndicator(unsigned int newValue) { leapVersionMode = (0x3F & leapVersionMode) | ((newValue & 0x03) << 6); } + + unsigned int versionNumber() const { return (leapVersionMode >> 3) & 0x07; } + void versionNumber(unsigned int newValue) { leapVersionMode = (0xC7 & leapVersionMode) | ((newValue & 0x07) << 3); } + + unsigned int mode() const { return (leapVersionMode & 0x07); } + void mode(unsigned int newValue) { leapVersionMode = (leapVersionMode & 0xF8) | (newValue & 0x07); } + + char stratum; + char poll; + char precision; + uint32_t rootDelay; + uint32_t rootDispersion; + char referenceId[4]; + uint32_t referenceTimestampSeconds; + uint32_t referenceTimestampFraction; + uint32_t originTimestampSeconds; + uint32_t originTimestampFraction; + uint32_t receiveTimestampSeconds; + uint32_t receiveTimestampFraction; + uint32_t transmitTimestampSeconds; + uint32_t transmitTimestampFraction; + + /* + * Rearranges bytes in 32 bit values from big-endian (NTP protocol) + * to little-endian (Arduino/PC), or vice versa. Must be called before + * modifying the structure or sending the packet. + */ + void swapEndian(); + + /* + * Returns packet as a char array for transmission via network. + * WARNING: modifying the return value is unsafe. + */ + const char *packet() { return (const char*)this; } + + /* + * Copies packet buffer to packet object. + */ + void populatePacket(const char *buffer) + { + memcpy(this, buffer, PACKET_SIZE); + } +private: + /* + * Reverses bytes in a number. + */ + void reverseBytes_(uint32_t *number); +}; + +#endif // NTP_PACKET_H diff --git a/lib/ArduinoNTPd/NTPServer.cpp b/lib/ArduinoNTPd/NTPServer.cpp new file mode 100644 index 000000000..6ee82bd6c --- /dev/null +++ b/lib/ArduinoNTPd/NTPServer.cpp @@ -0,0 +1,79 @@ +/* + * File: NTPServer.cpp + * Description: + * NTP server implementation. + * Author: Mooneer Salem + * License: New BSD License + */ + + +#include + +#include "NTPPacket.h" +#include "NTPServer.h" + +#define NTP_PORT 123 +#define NTP_TIMESTAMP_DIFF (2208988800) // 1900 to 1970 in seconds + +bool NtpServer::beginListening() +{ + if (timeServerPort_.begin(NTP_PORT)){ + return true; + } + return false; +} + +bool NtpServer::processOneRequest(uint32_t utc, uint32_t millisecs) +{ + // We need the time we've received the packet in our response. + uint32_t recvSecs = utc + NTP_TIMESTAMP_DIFF; + double recvFractDouble = (double)millisecs/0.00023283064365386963; // millisec/((10^6)/(2^32)) + uint32_t recvFract = (double)recvFractDouble; //TODO: really handle this!!! + bool processed = false; + + int packetDataSize = timeServerPort_.parsePacket(); + if (packetDataSize && packetDataSize >= NtpPacket::PACKET_SIZE) + { + // Received what is probably an NTP packet. Read it in and verify + // that it's legit. + NtpPacket packet; + timeServerPort_.read((char*)&packet, NtpPacket::PACKET_SIZE); + // TODO: verify packet. + + // Populate response. + packet.swapEndian(); + packet.leapIndicator(0); + packet.versionNumber(4); + packet.mode(4); + packet.stratum = 2; // I guess stratum 1 is too optimistic + packet.poll = 10; // 6-10 per RFC 5905. + packet.precision = -21; // ~0.5 microsecond precision. + packet.rootDelay = 0; //60 * (0xFFFF / 1000); // ~60 milliseconds, TBD + packet.rootDispersion = 0; //10 * (0xFFFF / 1000); // ~10 millisecond dispersion, TBD + packet.referenceId[0] = 'G'; + packet.referenceId[1] = 'P'; + packet.referenceId[2] = 'S'; + packet.referenceId[3] = 0; + packet.referenceTimestampSeconds = utc; + packet.referenceTimestampFraction = recvFract; + packet.originTimestampSeconds = packet.transmitTimestampSeconds; + packet.originTimestampFraction = packet.transmitTimestampFraction; + packet.receiveTimestampSeconds = recvSecs; + packet.receiveTimestampFraction = recvFract; + + // ...and the transmit time. + // timeSource_.now(&packet.transmitTimestampSeconds, &packet.transmitTimestampFraction); + + // Now transmit the response to the client. + packet.swapEndian(); + timeServerPort_.beginPacket(timeServerPort_.remoteIP(), timeServerPort_.remotePort()); + for (int count = 0; count < NtpPacket::PACKET_SIZE; count++) + { + timeServerPort_.write(packet.packet()[count]); + } + timeServerPort_.endPacket(); + processed = true; + } + + return processed; +} \ No newline at end of file diff --git a/lib/ArduinoNTPd/NTPServer.h b/lib/ArduinoNTPd/NTPServer.h new file mode 100644 index 000000000..121d905ce --- /dev/null +++ b/lib/ArduinoNTPd/NTPServer.h @@ -0,0 +1,35 @@ +/* + * File: NTPServer.h + * Description: + * NTP server implementation. + * Author: Mooneer Salem + * License: New BSD License + */ + +#ifndef NTP_SERVER_H +#define NTP_SERVER_H + +class NtpServer +{ +public: + NtpServer(WiFiUDP Port) + { + timeServerPort_=Port; + } + + /* + * Begins listening for NTP requests. + */ + bool beginListening(void); + + + /* + * Processes a single NTP request. + */ + bool processOneRequest(uint32_t utc, uint32_t millisecs); + +private: + WiFiUDP timeServerPort_; +}; + +#endif // NTP_SERVER_H diff --git a/tasmota/xsns_58_GPS.ino b/tasmota/xsns_58_GPS.ino index f2808f8fd..1871ff85f 100644 --- a/tasmota/xsns_58_GPS.ino +++ b/tasmota/xsns_58_GPS.ino @@ -1,5 +1,5 @@ /* - xsns_92_GPS_UBX.ino - GPS UBLOX support for Sonoff-Tasmota + xsns_58_GPS_UBX.ino - GPS UBLOX support for Sonoff-Tasmota Copyright (C) 2019 Theo Arends, Christian Baars and Adrian Scillato From ed92cdc74c2f3b063986cad77d629c78fa1fa550 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 17 Dec 2019 01:40:56 -0300 Subject: [PATCH 083/559] Fix sensor number and identations --- tasmota/xsns_58_GPS.ino | 187 +++++++++++++++++++--------------------- 1 file changed, 87 insertions(+), 100 deletions(-) diff --git a/tasmota/xsns_58_GPS.ino b/tasmota/xsns_58_GPS.ino index 1871ff85f..5f0c2d46b 100644 --- a/tasmota/xsns_58_GPS.ino +++ b/tasmota/xsns_58_GPS.ino @@ -20,7 +20,7 @@ Version Date Action Description -------------------------------------------------------------------------------------------- - 0.9.1.0 20191216 integrate - Added pin specifications from Tasmota WEB UI + 0.9.1.0 20191216 integrate - Added pin specifications from Tasmota WEB UI. Minor tweaks. --- 0.9.0.0 20190817 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota @@ -299,17 +299,6 @@ void UBXinitCFG(void){ UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); } DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); - -/* - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), - Settings.knx_GA_registered, - device_param_ga[GAop-1], - GA_FNUM, GA_AREA, GA_FDEF ); -*/ - - - - } void UBXTriggerTele(void){ @@ -435,11 +424,10 @@ uint32_t UBXprocessGPS() { } } // DEBUG_SENSOR_LOG(PSTR("UBX: got none or unknown Message")); - if(data_bytes!=0){ + if(data_bytes!=0) { UBX.state.non_empty_loops++; DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); - } - else{ + } else { UBX.state.non_empty_loops = 0; // now a hidden GPS-device reset is unlikely } return MT_NONE; @@ -449,7 +437,7 @@ uint32_t UBXprocessGPS() { | * callback functions for the download \*********************************************************************************************/ #ifdef USE_FLOG -void UBXsendHeader(void){ +void UBXsendHeader(void) { WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); WSSend(200, CT_STREAM, F( @@ -461,17 +449,17 @@ void UBXsendHeader(void){ } void UBXsendRecord(uint8_t *buf){ - char record[100]; - char stime[32]; - UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; - snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); - char lat[12]; - char lon[12]; - dtostrfd((double)entry->lat/10000000.0f,7,lat); - dtostrfd((double)entry->lon/10000000.0f,7,lon); - snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); - // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.dword_buffer[k+j],Flog->sector.dword_buffer[k+j+1]); - WebServer->sendContent_P(record); + char record[100]; + char stime[32]; + UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; + snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); + char lat[12]; + char lon[12]; + dtostrfd((double)entry->lat/10000000.0f,7,lat); + dtostrfd((double)entry->lon/10000000.0f,7,lon); + snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); + // DEBUG_SENSOR_LOG(PSTR("FLOG: DL %u %u"), Flog->sector.dword_buffer[k+j],Flog->sector.dword_buffer[k+j+1]); + WebServer->sendContent_P(record); } void UBXsendFooter(void){ @@ -482,8 +470,8 @@ void UBXsendFooter(void){ /********************************************************************************************/ void UBXsendFile(void){ - if (!HttpCheckPriviledgedAccess()) { return; } - Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); + if (!HttpCheckPriviledgedAccess()) { return; } + Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); } #endif //USE_FLOG /********************************************************************************************/ @@ -512,69 +500,67 @@ void UBXSetRate(uint16_t interval){ void UBXSelectMode(uint16_t mode){ - DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); - switch(mode){ + DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); + switch(mode){ #ifdef USE_FLOG - case 0: - Flog->mode = 0; // write once to all available sectors, then stop - break; + case 0: + Flog->mode = 0; // write once to all available sectors, then stop + break; case 1: - Flog->mode = 1; // write to all available sectors, then restart and overwrite the older ones - break; + Flog->mode = 1; // write to all available sectors, then restart and overwrite the older ones + break; case 2: - UBX.mode.filter_noise = true; // filter out horizontal drift noise, TODO: find useful values - break; + UBX.mode.filter_noise = true; // filter out horizontal drift noise, TODO: find useful values + break; case 3: - UBX.mode.filter_noise = false; - break; + UBX.mode.filter_noise = false; + break; case 4: - Flog->startRecording(true); - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); - break; + Flog->startRecording(true); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); + break; case 5: - Flog->startRecording(false); - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); - break; + Flog->startRecording(false); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); + break; case 6: - if(Flog->recording == true){ - Flog->stopRecording(); - } - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); - break; + if(Flog->recording == true){ + Flog->stopRecording(); + } + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); + break; +#endif //USE_FLOG case 7: - UBX.mode.send_when_new = 1; // send mqtt on new postion + TELE -> consider to set TELE to a very high value - break; + UBX.mode.send_when_new = 1; // send mqtt on new postion + TELE -> consider to set TELE to a very high value + break; case 8: - UBX.mode.send_when_new = 0; // only TELE - break; + UBX.mode.send_when_new = 0; // only TELE + break; case 9: - if (timeServer.beginListening()){ - UBX.mode.runningNTP = true; - } - break; + if (timeServer.beginListening()){ + UBX.mode.runningNTP = true; + } + break; case 10: - UBX.mode.runningNTP = false; - break; + UBX.mode.runningNTP = false; + break; case 11: - UBX.mode.forceUTCupdate = true; - break; + UBX.mode.forceUTCupdate = true; + break; case 12: - UBX.mode.forceUTCupdate = false; - break; + UBX.mode.forceUTCupdate = false; + break; case 13: - Settings.latitude = UBX.state.last_lat; - Settings.longitude = UBX.state.last_lon; - break; - - -#endif //USE_FLOG + Settings.latitude = UBX.state.last_lat; + Settings.longitude = UBX.state.last_lon; + break; default: if(mode>1000 && mode <1066) { // UBXSetRate(mode-1000); // min. 1001 = 0.001 Hz, but will be converted to 1/65535 anyway ~0.015 Hz, max. 2000 = 1.000 Hz UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65 } - break; - } + break; + } UBX.mode.send_UI_only = true; UBXTriggerTele(); } @@ -601,8 +587,7 @@ bool UBXHandlePOSLLH(){ UBXTriggerTele(); } return true; // new position - } - else { + } else { DEBUG_SENSOR_LOG(PSTR("UBX: no valid position data")); } return false; // no GPS-fix @@ -611,12 +596,13 @@ bool UBXHandlePOSLLH(){ void UBXHandleSTATUS(){ DEBUG_SENSOR_LOG(PSTR("UBX: gpsFix: %u, valid: %u"),UBX.Message.navStatus.gpsFix, (UBX.Message.navStatus.flags)&1); if((UBX.Message.navStatus.flags)&1){ - UBX.state.gpsFix = UBX.Message.navStatus.gpsFix; //only store fixed status if flag is valid + UBX.state.gpsFix = UBX.Message.navStatus.gpsFix; //only store fixed status if flag is valid } else{ - UBX.state.gpsFix = 0; // without valid flag, everything is "no fix" + UBX.state.gpsFix = 0; // without valid flag, everything is "no fix" } } + void UBXHandleTIME(){ DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"),UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec); if(UBX.Message.navTime.valid.UTC){ @@ -636,7 +622,8 @@ void UBXHandleTIME(){ } } -void UBXHandleOther(void){ +void UBXHandleOther(void) +{ if(UBX.state.non_empty_loops>6){ // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz) UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!! AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); @@ -647,7 +634,8 @@ void UBXHandleOther(void){ /********************************************************************************************/ -void UBXTimeServer(){ +void UBXTimeServer() +{ if(UBX.mode.runningNTP){ timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000); } @@ -662,17 +650,17 @@ void UBXLoop(void) switch(msgType){ case MT_NAV_POSLLH: - new_position = UBXHandlePOSLLH(); - break; + new_position = UBXHandlePOSLLH(); + break; case MT_NAV_STATUS: - UBXHandleSTATUS(); - break; + UBXHandleSTATUS(); + break; case MT_NAV_TIME: - UBXHandleTIME(); - break; + UBXHandleTIME(); + break; default: - UBXHandleOther(); - break; + UBXHandleOther(); + break; } #ifdef USE_FLOG @@ -752,8 +740,7 @@ void UBXShow(bool json) if(UBX.mode.send_UI_only){ uint32_t i = UBX.state.log_interval / 10; ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"),UBX.mode.filter_noise, i); - } - else{ + } else { ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"height\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, height, hAcc, vAcc); } #ifdef USE_FLOG @@ -768,7 +755,7 @@ void UBXShow(bool json) #ifdef USE_FLOG WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); if(Flog->recording){ - WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); + WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); } #endif //USE_FLOG #endif // DEBUG_TASMOTA_SENSOR @@ -794,10 +781,10 @@ void UBXShow(bool json) bool UBXCmd(void) { bool serviced = true; - if (XdrvMailbox.data_len > 0) { - UBXSelectMode(XdrvMailbox.payload); - Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); - } + if (XdrvMailbox.data_len > 0) { + UBXSelectMode(XdrvMailbox.payload); + Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } return serviced; } @@ -805,7 +792,7 @@ bool UBXCmd(void) { * Interface \*********************************************************************************************/ -#define XSNS_58 58 +#define XSNS_58 58 bool Xsns58(uint8_t function) { @@ -816,12 +803,12 @@ bool Xsns58(uint8_t function) case FUNC_INIT: UBXDetect(); break; - case FUNC_COMMAND_SENSOR: - if (XSNS_92 == XdrvMailbox.index){ + case FUNC_COMMAND_SENSOR: + if (XSNS_58 == XdrvMailbox.index){ result = UBXCmd(); } break; - case FUNC_EVERY_50_MSECOND: + case FUNC_EVERY_50_MSECOND: UBXTimeServer(); break; case FUNC_EVERY_100_MSECOND: @@ -834,8 +821,8 @@ bool Xsns58(uint8_t function) break; #ifdef USE_FLOG case FUNC_WEB_ADD_HANDLER: - WebServer->on("/UBX", UBXsendFile); - break; + WebServer->on("/UBX", UBXsendFile); + break; #endif //USE_FLOG case FUNC_JSON_APPEND: UBXShow(1); From 2d75cb95763aa8da58d07b28e3f76a05c8c9b3ad Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 17 Dec 2019 02:43:35 -0300 Subject: [PATCH 084/559] Fix more identations --- tasmota/xsns_58_GPS.ino | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/tasmota/xsns_58_GPS.ino b/tasmota/xsns_58_GPS.ino index 5f0c2d46b..58178b976 100644 --- a/tasmota/xsns_58_GPS.ino +++ b/tasmota/xsns_58_GPS.ino @@ -44,46 +44,46 @@ The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To ## Commands: -+ sensor92 0 ++ sensor58 0 write to all available sectors, then restart and overwrite the older ones -+ sensor92 1 ++ sensor58 1 write to all available sectors, then restart and overwrite the older ones -+ sensor92 2 ++ sensor58 2 filter out horizontal drift noise -+ sensor92 3 ++ sensor58 3 turn off noise filter -+ sensor92 4 ++ sensor58 4 start recording, new data will be appended -+ sensor92 5 ++ sensor58 5 start new recording, old data will lost -+ sensor92 6 ++ sensor58 6 stop recording, download link will be visible in Web-UI -+ sensor92 7 ++ sensor58 7 send mqtt on new postion + TELE -> consider to set TELE to a very high value -+ sensor92 8 ++ sensor58 8 only TELE message -+ sensor92 9 ++ sensor58 9 start NTP-server -+ sensor92 10 ++ sensor58 10 deactivate NTP-server -+ sensor92 11 ++ sensor58 11 force update of Tasmota-system-UTC with every new GPS-time-message -+ sensor92 12 ++ sensor58 12 do not update of Tasmota-system-UTC with every new GPS-time-message -+ sensor92 13 ++ sensor58 13 set latitude and longitude in settings @@ -91,7 +91,7 @@ The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To ## Rules examples for SSD1306 32x128 -rule1 on tele-GPS#lat do DisplayText [s1p21c1l01f1]LAT: %value% endon on tele-GPS#lon do DisplayText [s1p21c1l2]LON: %value% endon on switch1#state==3 do sensor92 4 endon on switch1#state==2 do sensor92 6 endon +rule1 on tele-GPS#lat do DisplayText [s1p21c1l01f1]LAT: %value% endon on tele-GPS#lon do DisplayText [s1p21c1l2]LON: %value% endon on switch1#state==3 do sensor58 4 endon on switch1#state==2 do sensor58 6 endon rule2 on tele-GPS#int>9 do DisplayText [f0c9l4]I%value% endon on tele-GPS#int<10 do DisplayText [f0c9l4]I0%value% endon on tele-GPS#fil==1 do DisplayText [f0c18l4]F endon on tele-GPS#fil==0 do DisplayText [f0c18l4]N endon @@ -715,7 +715,7 @@ counter++; const char kGPSFix5[] PROGMEM = "Time only fix"; const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; -// const char UBX_GOOGLE_MAPS[] =""; +// const char UBX_GOOGLE_MAPS[] =""; #endif // USE_WEBSERVER @@ -735,7 +735,8 @@ void UBXShow(bool json) dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); - if (json) { + if (json) + { ResponseAppend_P(PSTR(",\"GPS\":{")); if(UBX.mode.send_UI_only){ uint32_t i = UBX.state.log_interval / 10; @@ -748,9 +749,9 @@ void UBXShow(bool json) #endif //USE_FLOG UBX.mode.send_UI_only = false; #ifdef USE_WEBSERVER - } else { + } else { WSContentSend_PD(HTTP_SNS_GPS, lat, lon, height, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); - // WSContentSend_PD(UBX_GOOGLE_MAPS, lat, lon); + //WSContentSend_P(UBX_GOOGLE_MAPS, lat, lon); #ifdef DEBUG_TASMOTA_SENSOR #ifdef USE_FLOG WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); @@ -771,7 +772,7 @@ void UBXShow(bool json) WSContentSend_P(HTTP_SNS_NTPSERVER); } #endif // USE_WEBSERVER - } + } } From fa56e958e07008d14529dd113dc993c39e7d3d0d Mon Sep 17 00:00:00 2001 From: root Date: Tue, 26 Nov 2019 16:51:53 +0100 Subject: [PATCH 085/559] domoticz -> tasmota support --- tasmota/i18n.h | 1 - tasmota/xdrv_07_domoticz.ino | 48 +++++++++++++++++++++++++++++++++++- tasmota/xdrv_27_shutter.ino | 8 +++--- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index fed6930d7..df7cff12b 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -494,7 +494,6 @@ #define D_JSON_MOTOR_MIS "setMIS" #endif - // Commands xdrv_27_Shutter.ino #ifdef USE_SHUTTER #define D_PRFX_SHUTTER "Shutter" #define D_CMND_SHUTTER_OPEN "Open" diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino index f5e8af19c..9d24d6edf 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/xdrv_07_domoticz.ino @@ -51,6 +51,10 @@ uint32_t domoticz_fan_debounce = 0; // iFan02 state debounce timer bool domoticz_subscribe = false; bool domoticz_update_flag = true; +#ifdef USE_SHUTTER +bool domoticz_is_shutter = false; +#endif // USE_SHUTTER + int DomoticzBatteryQuality(void) { // Battery 0%: ESP 2.6V (minimum operating voltage is 2.5) @@ -108,6 +112,11 @@ void MqttPublishDomoticzPowerState(uint8_t device) if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT if ((device < 1) || (device > devices_present)) { device = 1; } if (Settings.domoticz_relay_idx[device -1]) { +#ifdef USE_SHUTTER + if (domoticz_is_shutter) { + // Shutter is updated by sensor update - power state should not be sent + } else { +#endif // USE_SHUTTER #ifdef USE_SONOFF_IFAN if (IsModuleIfan() && (device > 1)) { // Fan handled by MqttPublishDomoticzFanState @@ -121,6 +130,9 @@ void MqttPublishDomoticzPowerState(uint8_t device) #ifdef USE_SONOFF_IFAN } #endif // USE_SONOFF_IFAN +#ifdef USE_SHUTTER + } +#endif //USE_SHUTTER } } } @@ -140,6 +152,13 @@ void DomoticzMqttUpdate(void) if (domoticz_update_timer <= 0) { domoticz_update_timer = Settings.domoticz_update_timer; for (uint32_t i = 1; i <= devices_present; i++) { +#ifdef USE_SHUTTER + if (domoticz_is_shutter) + { + // no power state updates for shutters + break; + } +#endif // USE_SHUTTER #ifdef USE_SONOFF_IFAN if (IsModuleIfan() && (i > 1)) { MqttPublishDomoticzFanState(); @@ -163,6 +182,7 @@ void DomoticzMqttSubscribe(void) domoticz_subscribe = true; } } + if (domoticz_subscribe) { char stopic[TOPSZ]; snprintf_P(stopic, sizeof(stopic), PSTR(DOMOTICZ_OUT_TOPIC "/#")); // domoticz topic @@ -230,6 +250,8 @@ bool DomoticzMqttData(void) for (uint32_t i = 0; i < maxdev; i++) { if (idx == Settings.domoticz_relay_idx[i]) { bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; + bool isShutter = strcmp_P(domoticz["dtype"],PSTR("Light/Switch")) == 0 & strncmp_P(domoticz["switchType"],PSTR("Blinds"), 6) == 0; + char stemp1[10]; snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); #ifdef USE_SONOFF_IFAN @@ -252,6 +274,28 @@ bool DomoticzMqttData(void) found = true; } else #endif // USE_SONOFF_IFAN +#ifdef USE_SHUTTER + if (isShutter) + { + if (domoticz.containsKey("nvalue")) { + nvalue = domoticz["nvalue"]; + } + + uint8_t position = 0; + if (domoticz.containsKey("svalue1")) { + position = domoticz["svalue1"]; + } + if (nvalue != 2) { + position = nvalue == 0 ? 0 : 100; + } + + snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); + XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); + + found = true; + } else +#endif // USE_SHUTTER if (iscolordimmer && 10 == nvalue) { // Color_SetColor JsonObject& color = domoticz["Color"]; uint16_t level = nvalue = domoticz["svalue1"]; @@ -573,7 +617,6 @@ void DomoticzSaveSettings(void) bool Xdrv07(uint8_t function) { bool result = false; - if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT switch (function) { case FUNC_EVERY_SECOND: @@ -592,6 +635,9 @@ bool Xdrv07(uint8_t function) #endif // USE_WEBSERVER case FUNC_MQTT_SUBSCRIBE: DomoticzMqttSubscribe(); +#ifdef USE_SHUTTER + if (Settings.domoticz_sensor_idx[DZ_SHUTTER]) { domoticz_is_shutter = true; } +#endif // USE_SHUTTER break; case FUNC_MQTT_INIT: domoticz_update_timer = 2; diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index e13bba771..97212ad6e 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -528,12 +528,12 @@ void CmndShutterPosition(void) //limit the payload AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); + // value 0 with data_len > 0 can mean Open if (XdrvMailbox.data_len > 1 && XdrvMailbox.payload <=0) { UpperCase(XdrvMailbox.data, XdrvMailbox.data); - if (!strcmp(XdrvMailbox.data,"UP")) { CmndShutterOpen(); } - if (!strcmp(XdrvMailbox.data,"DOWN")) { CmndShutterClose(); } - if (!strcmp(XdrvMailbox.data,"STOP")) { CmndShutterStop(); } - return; + if (!strcmp(XdrvMailbox.data,"UP")) { CmndShutterOpen(); return; } + if (!strcmp(XdrvMailbox.data,"DOWN")) { CmndShutterClose(); return; } + if (!strcmp(XdrvMailbox.data,"STOP")) { CmndShutterStop(); return; } } int8_t target_pos_percent = XdrvMailbox.payload < 0 ? 0 : (XdrvMailbox.payload > 100 ? 100 : XdrvMailbox.payload); From 082f5e40cefeda76ab458a93a03d4335840c2caa Mon Sep 17 00:00:00 2001 From: ahoiahoi <45395388+ahoiahoi@users.noreply.github.com> Date: Tue, 26 Nov 2019 16:58:05 +0100 Subject: [PATCH 086/559] accidentally deleted linefeed --- tasmota/i18n.h | 1 + tasmota/xdrv_07_domoticz.ino | 1 + 2 files changed, 2 insertions(+) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index df7cff12b..fed6930d7 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -494,6 +494,7 @@ #define D_JSON_MOTOR_MIS "setMIS" #endif + // Commands xdrv_27_Shutter.ino #ifdef USE_SHUTTER #define D_PRFX_SHUTTER "Shutter" #define D_CMND_SHUTTER_OPEN "Open" diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino index 9d24d6edf..b20e0335c 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/xdrv_07_domoticz.ino @@ -617,6 +617,7 @@ void DomoticzSaveSettings(void) bool Xdrv07(uint8_t function) { bool result = false; + if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT switch (function) { case FUNC_EVERY_SECOND: From efc7dc2388988c6233cbf97cb5b65f36ea30976b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 17 Dec 2019 10:54:38 +0100 Subject: [PATCH 087/559] Add fallback functionality from next version Add fallback functionality from next version 8.x --- tasmota/CHANGELOG.md | 2 +- tasmota/settings.ino | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index a466a3212..ad2ad30d4 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,7 +5,7 @@ - Change some more Settings locations freeing up space for future single char allowing variable length text - Add Zigbee send automatic ZigbeeRead after sending a command - Add Zigbee improving Occupancy:false detection for Aqara sensor -- Add fallback functionality from next version 7.1.2.7 +- Add fallback functionality from next version 8.x ### 7.1.2.5 20191213 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index d1d3fc1e8..d5c59246f 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -471,7 +471,7 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me) char replace[replace_len +1]; memcpy(replace, replace_me, sizeof(replace)); - if (Settings.version < 0x07010207) { + if (Settings.version < 0x08000000) { uint32_t idx = 0; switch (index) { case SET_OTAURL: strlcpy(Settings.ota_url, replace, sizeof(Settings.ota_url)); break; @@ -575,7 +575,7 @@ char* SettingsText(uint32_t index) char* position = Settings.ota_url; - if (Settings.version < 0x07010207) { + if (Settings.version < 0x08000000) { uint32_t idx = 0; switch (index) { case SET_MQTTPREFIX3: idx++; @@ -1387,7 +1387,7 @@ void SettingsDelta(void) memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); // 1E4 -> EFE } - if ((VERSION < 0x7010207) && (Settings.version > VERSION)) { + if ((VERSION < 0x08000000) && (Settings.version > VERSION)) { char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp)); char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21)); char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22)); From 359770c23eedf86f5c14ed098dde5cc12c7bb089 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 17 Dec 2019 11:43:22 +0100 Subject: [PATCH 088/559] Update support_statistics.ino --- tasmota/support_statistics.ino | 38 +++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/tasmota/support_statistics.ino b/tasmota/support_statistics.ino index 1907b1edc..78334e7eb 100644 --- a/tasmota/support_statistics.ino +++ b/tasmota/support_statistics.ino @@ -27,7 +27,43 @@ String GetStatistics(void) { char data[40]; - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); // Char Usage Ratio + + if (Settings.version < 0x08000000) { + uint32_t str_len = 0; + for (uint32_t i = 0; i < 2; i++) { + str_len += strlen(Settings.sta_ssid[i]); + str_len += strlen(Settings.sta_pwd[i]); + } + for (uint32_t i = 0; i < 3; i++) { + str_len += strlen(Settings.mqtt_prefix[i]); + str_len += strlen(Settings.ntp_server[i]); + } + for (uint32_t i = 0; i < 4; i++) { + str_len += strlen(Settings.state_text[i]); + str_len += strlen(Settings.friendlyname[i]); + } + for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { + str_len += strlen(Settings.mems[i]); + } + + str_len += strlen(Settings.ota_url); + str_len += strlen(Settings.hostname); + str_len += strlen(Settings.syslog_host); + str_len += strlen(Settings.mqtt_host); + str_len += strlen(Settings.mqtt_client); + str_len += strlen(Settings.mqtt_user); + str_len += strlen(Settings.mqtt_pwd); + str_len += strlen(Settings.mqtt_topic); + str_len += strlen(Settings.button_topic); + str_len += strlen(Settings.switch_topic); + str_len += strlen(Settings.mqtt_grptopic); + str_len += strlen(Settings.web_password); + str_len += strlen(Settings.mqtt_fulltopic); + str_len += strlen(Settings.cors_domain); + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151\""), str_len); // Char Usage Ratio + } else { + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); // Char Usage Ratio + } return String(data); } From 78b1363add7637e853a98f5ce417451cd36a1211 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 17 Dec 2019 12:08:32 +0100 Subject: [PATCH 089/559] Update support_statistics.ino --- tasmota/support_statistics.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/support_statistics.ino b/tasmota/support_statistics.ino index 78334e7eb..b8f65bd20 100644 --- a/tasmota/support_statistics.ino +++ b/tasmota/support_statistics.ino @@ -45,7 +45,6 @@ String GetStatistics(void) for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { str_len += strlen(Settings.mems[i]); } - str_len += strlen(Settings.ota_url); str_len += strlen(Settings.hostname); str_len += strlen(Settings.syslog_host); @@ -60,7 +59,7 @@ String GetStatistics(void) str_len += strlen(Settings.web_password); str_len += strlen(Settings.mqtt_fulltopic); str_len += strlen(Settings.cors_domain); - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151\""), str_len); // Char Usage Ratio + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151\""), 37 + str_len); // Char Usage Ratio } else { snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); // Char Usage Ratio } From 5968d2b28aa163e0ffde1a43261f1ad70bb7f06d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 17 Dec 2019 15:13:47 +0100 Subject: [PATCH 090/559] Change tasmota-basic to tasmota-lite Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE --- .travis.yml | 2 +- BUILDS.md | 12 ++++++------ RELEASENOTES.md | 2 +- platformio.ini | 2 +- platformio_override_sample.ini | 4 ++-- platformio_tasmota_env.ini | 4 ++-- tasmota/CHANGELOG.md | 1 + tasmota/my_user_config.h | 2 +- tasmota/tasmota_post.h | 8 ++++---- 9 files changed, 19 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 911f3423e..ffd47f546 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ cache: false env: - ENV=tasmota - ENV=tasmota-minimal - - ENV=tasmota-basic + - ENV=tasmota-lite - ENV=tasmota-knx - ENV=tasmota-sensors - ENV=tasmota-display diff --git a/BUILDS.md b/BUILDS.md index 74c0a7a35..d21fd9f15 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -1,6 +1,6 @@ ## Available Features and Sensors -| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks |-----------------------|---------|-------|--------|-----|---------|----|---------|-------- | MY_LANGUAGE en-GB | x | x | x | x | x | x | x | | USE_ARDUINO_OTA | - | - | - | - | - | - | - | @@ -27,7 +27,7 @@ | USE_EXPRESSION | - | - | - | - | - | - | - | | SUPPORT_IF_STATEMENT | - | - | - | - | - | - | - | | | | | | | | | | -| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | ROTARY_V1 | - | - | - | - | - | - | - | | USE_SONOFF_RF | - | - | x | x | x | - | - | | USE_RF_FLASH | - | - | x | x | x | - | - | @@ -42,7 +42,7 @@ | USE_DEEPSLEEP | - | - | x | - | x | - | - | | USE_EXS_DIMMER | - | - | x | x | - | - | - | | | | | | | | | | -| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_LIGHT | - | x | x | x | x | x | x | | USE_WS2812 | - | - | x | x | x | - | x | | USE_WS2812_DMA | - | - | - | - | - | - | - | @@ -69,7 +69,7 @@ | USE_MAX31855 | - | - | - | - | x | - | - | | USE_MAX31865 | - | - | - | - | - | - | - | | | | | | | | | | -| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_I2C | - | - | x | x | x | - | x | | USE_SHT | - | - | x | x | x | - | x | | USE_HTU | - | - | x | x | x | - | x | @@ -107,7 +107,7 @@ | USE_PCF8574 | - | - | - | - | - | - | - | | USE_HIH6 | - | - | - | - | x | - | - | | | | | | | | | | -| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | | USE_MHZ19 | - | - | x | x | x | - | x | | USE_SENSEAIR | - | - | x | x | x | - | x | @@ -133,7 +133,7 @@ | USE_A4988_STEPPER | - | - | - | - | - | - | - | | USE_TASMOTA_SLAVE | - | - | - | - | - | - | - | Experimental | | | | | | | | | -| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks +| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_DISPLAY | - | - | - | - | - | - | x | | USE_DISPLAY_LCD | - | - | - | - | - | - | x | | USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4341ec587..b8220e8d3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -34,7 +34,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - **tasmota.bin** = The Tasmota version with sensors. **RECOMMENDED RELEASE BINARY** - **tasmota-BG.bin** to **tasmota-TW.bin** = The Tasmota version in different languages. -- **tasmota-basic.bin** = The Basic version without most sensors. +- **tasmota-lite.bin** = The Lite version without most sensors. - **tasmota-knx.bin** = The Knx version without some features but adds KNX support. - **tasmota-sensors.bin** = The Sensors version adds more useful sensors. - **tasmota-ir** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features. diff --git a/platformio.ini b/platformio.ini index d47eadafb..6e73715d4 100755 --- a/platformio.ini +++ b/platformio.ini @@ -20,7 +20,7 @@ default_envs = ; tasmota ; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big ; tasmota-minimal -; tasmota-basic +; tasmota-lite ; tasmota-knx ; tasmota-sensors ; tasmota-display diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 6cbd749c4..9ac4084cd 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -19,7 +19,7 @@ default_envs = ; tasmota-debug ; tasmota-ircustom ; alternative to 'tasmota' with full IR protocols activated, you will need to disable some features to keep code not too big ; tasmota-minimal -; tasmota-basic +; tasmota-lite ; tasmota-knx ; tasmota-sensors ; tasmota-display @@ -36,7 +36,7 @@ build_flags = ${core_active.build_flags} ; *** Optional Firmware configurations ; -DFIRMWARE_MINIMAL ; -DFIRMWARE_SENSORS -; -DFIRMWARE_BASIC +; -DFIRMWARE_LITE ; -DFIRMWARE_KNX_NO_EMULATION ; -DFIRMWARE_DISPLAYS ; -DFIRMWARE_IR diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 38aaf2223..fd0571125 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -18,8 +18,8 @@ extra_scripts = ${common.extra_scripts} [env:tasmota-minimal] build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL -[env:tasmota-basic] -build_flags = ${common.build_flags} -DFIRMWARE_BASIC +[env:tasmota-lite] +build_flags = ${common.build_flags} -DFIRMWARE_LITE [env:tasmota-knx] build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index ad2ad30d4..90f29af2a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 7.1.2.6 20191214 - Change some more Settings locations freeing up space for future single char allowing variable length text +- Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE - Add Zigbee send automatic ZigbeeRead after sending a command - Add Zigbee improving Occupancy:false detection for Aqara sensor - Add fallback functionality from next version 8.x diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 5ff6bb6a2..04318d9c8 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -570,7 +570,7 @@ * See RELEASENOTES.md for selected features \*********************************************************************************************/ -//#define FIRMWARE_BASIC // Create tasmota-basic with no sensors +//#define FIRMWARE_LITE // Create tasmota-lite with no sensors //#define FIRMWARE_SENSORS // Create tasmota-sensors with useful sensors enabled //#define FIRMWARE_KNX_NO_EMULATION // Create tasmota-knx with KNX but without Emulation //#define FIRMWARE_DISPLAYS // Create tasmota-display with display drivers enabled diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index cc47e3fc1..75f35cd92 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -390,17 +390,17 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #endif // FIRMWARE_IR /*********************************************************************************************\ - * [tasmota-basic.bin] + * [tasmota-lite.bin] * Provide an image without sensors \*********************************************************************************************/ -#ifdef FIRMWARE_BASIC +#ifdef FIRMWARE_LITE #undef CODE_IMAGE #define CODE_IMAGE 4 #undef APP_SLEEP -#define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_BASIC +#define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_LITE #undef USE_ARDUINO_OTA // Disable support for Arduino OTA #undef USE_DOMOTICZ // Disable Domoticz @@ -502,7 +502,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef CODE_IMAGE #define CODE_IMAGE 1 -#undef FIRMWARE_BASIC // Disable tasmota-basic with no sensors +#undef FIRMWARE_LITE // Disable tasmota-lite with no sensors #undef FIRMWARE_SENSORS // Disable tasmota-sensors with useful sensors enabled #undef FIRMWARE_KNX_NO_EMULATION // Disable tasmota-knx with KNX but without Emulation #undef FIRMWARE_DISPLAYS // Disable tasmota-display with display drivers enabled From 5b80d82054d0adcf7a776621493af6ff1ea01abd Mon Sep 17 00:00:00 2001 From: Michael Ingraham <34340210+meingraham@users.noreply.github.com> Date: Tue, 17 Dec 2019 13:59:03 -0500 Subject: [PATCH 091/559] wiki link --- .github/ISSUE_TEMPLATE/Bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 4b4027bf8..a73024342 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -29,7 +29,7 @@ _Make sure your have performed every step and checked the applicable boxes befor - [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md) - [ ] Searched the problem in [issues](https://github.com/arendst/Tasmota/issues) -- [ ] Searched the problem in the [wiki](https://github.com/arendst/Tasmota/wiki/Troubleshooting) +- [ ] Searched the problem in the [wiki](https://tasmota.github.io/docs/#/help/FAQ) - [ ] Searched the problem in the [forum](https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the [chat](https://discord.gg/Ks2Kzd4) - [ ] Device used (e.g., Sonoff Basic): _____ From d199cfcc394618883740c01939fe09b056294d8c Mon Sep 17 00:00:00 2001 From: Stefan Oskamp <57906326+stefan-oskamp@users.noreply.github.com> Date: Tue, 17 Dec 2019 21:25:51 +0100 Subject: [PATCH 092/559] Added DHT12 Refer to issue #7229 --- I2CDEVICES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/I2CDEVICES.md b/I2CDEVICES.md index 73f4a9c6b..6d0de4e1a 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -61,4 +61,5 @@ Index | Define | Driver | Device | Address(es) | Description 38 | USE_DISPLAY_ILI9488 | xdsp_08 | FT6236 | 0x38 | Touch panel controller 39 | USE_DISPLAY_RA8876 | xdsp_10 | FT5316 | 0x38 | Touch panel controller 40 | USE_TSL2591 | xsns_57 | TLS2591 | 0x29 | Light intensity sensor + 41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor From 9a7dfe7178449caa21f00838ccb608047d198f5a Mon Sep 17 00:00:00 2001 From: Stefan Oskamp <57906326+stefan-oskamp@users.noreply.github.com> Date: Tue, 17 Dec 2019 21:31:01 +0100 Subject: [PATCH 093/559] Driver for I2C sensor DHT12 Refer to issue #7229 --- tasmota/xsns_58_dht12.ino | 140 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 tasmota/xsns_58_dht12.ino diff --git a/tasmota/xsns_58_dht12.ino b/tasmota/xsns_58_dht12.ino new file mode 100644 index 000000000..1c60329b8 --- /dev/null +++ b/tasmota/xsns_58_dht12.ino @@ -0,0 +1,140 @@ +/* + xsns_58_dht12.ino - DHT12 I2C temperature and humidity sensor support for Tasmota + + Copyright (C) 2019 Stefan Oskamp and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_I2C +#ifdef USE_DHT12 +/*********************************************************************************************\ + * DHT12 - Temperature and Humidity + * + * I2C Address: 0x5C +\*********************************************************************************************/ + +#define XSNS_58 58 +#define XI2C_41 41 // See I2CDEVICES.md + +#define DHT12_ADDR (uint8_t) 0x5C + +char dht12_name[] = "DHT12-0x00"; +uint8_t dht12_count = 0; +float dht12_temperature = NAN; +float dht12_humidity = NAN; + +bool Dht12Read(void) +{ + Wire.beginTransmission(DHT12_ADDR); + Wire.write(0); + if (Wire.endTransmission() != 0) { + return false; + } + delay(50); + Wire.requestFrom(DHT12_ADDR, (uint8_t) 5); + delay(5); + uint8_t humidity = Wire.read(); + uint8_t humidityTenth = Wire.read(); + uint8_t temp = Wire.read(); + uint8_t tempTenth = Wire.read(); + uint8_t checksum = Wire.read(); + dht12_humidity = (float) humidity + (float) humidityTenth/(float) 10.0; + dht12_temperature = (float) temp + (float) tempTenth/(float) 10.0; + return (!isnan(dht12_temperature) && !isnan(dht12_humidity)); +} + +void Dht12Detect(void) +{ + if (Dht12Read()) { + snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, dht12_name, DHT12_ADDR); + AddLog(LOG_LEVEL_DEBUG); + snprintf_P(dht12_name, sizeof(dht12_name), PSTR("%s%c0x%02X"), "DHT12", IndexSeparator(), DHT12_ADDR); + dht12_count = 1; + } +} + +void Dht12Show(bool json) +{ + if (dht12_count > 0) + { + char temperature[33]; + dtostrfd(dht12_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(dht12_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) + { + ResponseAppend_P(JSON_SNS_TEMPHUM, dht12_name, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period)) + { + DomoticzTempHumSensor(temperature, humidity); + } +#endif // USE_DOMOTICZ + +#ifdef USE_KNX + if (0 == tele_period) + { + KnxSensor(KNX_TEMPERATURE, dht12_temperature); + KnxSensor(KNX_HUMIDITY, dht12_humidity); + } +#endif // USE_KNX + +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_TEMP, dht12_name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, dht12_name, humidity); +#endif // USE_WEBSERVER + } + } +} + + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns58(uint8_t function) +{ + if (!I2cEnabled(XI2C_41)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Dht12Detect(); + } + else if (dht12_count > 0) { + switch (function) { + case FUNC_EVERY_SECOND: + Dht12Read(); + break; + case FUNC_JSON_APPEND: + Dht12Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Dht12Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_DHT12 +#endif // USE_I2C From 3c835f0ee71fd0365e98304c8d5edcc7ee751d19 Mon Sep 17 00:00:00 2001 From: Stefan Oskamp <57906326+stefan-oskamp@users.noreply.github.com> Date: Tue, 17 Dec 2019 21:32:55 +0100 Subject: [PATCH 094/559] Added USE_DHT12 Refer to issue #7229 --- tasmota/tasmota_post.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 75f35cd92..108726c77 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -135,6 +135,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code) //#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code) #define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code) +#define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0kx code) //#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code) //#define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) From 894b5050f7066283d3e76f8bb38c17d1778be780 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Tue, 17 Dec 2019 18:07:05 -0300 Subject: [PATCH 095/559] Changed wiki for docs on feature request template --- .github/ISSUE_TEMPLATE/Feature_request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md index 43fd36e7c..90d705ea0 100644 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -10,7 +10,7 @@ Please take a few minutes to complete the requested information below. Our abili DO NOT DELETE ANY TEXT from this template! Otherwise the issue will be auto-closed. --> -**Have you looked for this feature in other issues and in the wiki?** +**Have you looked for this feature in other issues and in the docs?** **Is your feature request related to a problem? Please describe.** _A clear and concise description of what the problem is._ From 377ff5e9ea614c7b77ea2ce9bef68f7a92d28eee Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Tue, 17 Dec 2019 18:08:34 -0300 Subject: [PATCH 096/559] Changed wiki for docs on problem report template --- .github/ISSUE_TEMPLATE/Bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index a73024342..19c9bd00d 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -29,7 +29,7 @@ _Make sure your have performed every step and checked the applicable boxes befor - [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md) - [ ] Searched the problem in [issues](https://github.com/arendst/Tasmota/issues) -- [ ] Searched the problem in the [wiki](https://tasmota.github.io/docs/#/help/FAQ) +- [ ] Searched the problem in the [docs](https://tasmota.github.io/docs/#/help/FAQ) - [ ] Searched the problem in the [forum](https://groups.google.com/d/forum/sonoffusers) - [ ] Searched the problem in the [chat](https://discord.gg/Ks2Kzd4) - [ ] Device used (e.g., Sonoff Basic): _____ From c2d60b2ab772f109cd2b606df7eef56e029afdc7 Mon Sep 17 00:00:00 2001 From: Stefan Oskamp <57906326+stefan-oskamp@users.noreply.github.com> Date: Tue, 17 Dec 2019 22:19:49 +0100 Subject: [PATCH 097/559] Added entry for I2C sensor DHT12 --- tasmota/my_user_config.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 04318d9c8..d5645a9af 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -418,6 +418,7 @@ // #define USE_PAJ7620 // [I2cDriver34] Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) // #define USE_PCF8574 // [I2cDriver2] Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code) // #define USE_HIH6 // [I2cDriver36] Enable Honeywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) +// #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 From 5e9f33a124cf83085422f287f0bc930e4c278b3d Mon Sep 17 00:00:00 2001 From: Adrian Scillato <39969427+ascillato2@users.noreply.github.com> Date: Tue, 17 Dec 2019 18:24:45 -0300 Subject: [PATCH 098/559] Changed wiki for docs on issue bot --- .github/issue-close-app.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/issue-close-app.yml b/.github/issue-close-app.yml index 8e981441b..d222d8980 100644 --- a/.github/issue-close-app.yml +++ b/.github/issue-close-app.yml @@ -39,7 +39,7 @@ issueConfigs: - "EXPECTED BEHAVIOUR" - content: # template 2: feature request - - "Have you looked for this feature in other issues and in the wiki" + - "Have you looked for this feature in other issues and in the docs" - "Describe the solution you'd like" # Optional configuration: From eb4b3d306b4dfe9ae56e94539c1e88dcb837b310 Mon Sep 17 00:00:00 2001 From: Stefan Oskamp <57906326+stefan-oskamp@users.noreply.github.com> Date: Tue, 17 Dec 2019 22:29:16 +0100 Subject: [PATCH 099/559] Added code size for USE_DHT12 --- tasmota/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index d5645a9af..73a965d30 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -418,7 +418,7 @@ // #define USE_PAJ7620 // [I2cDriver34] Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) // #define USE_PCF8574 // [I2cDriver2] Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code) // #define USE_HIH6 // [I2cDriver36] Enable Honeywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) -// #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) +// #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) (+0k7 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 From e853cc65e597bd47e164ee0a8bfef8061e0d5d8d Mon Sep 17 00:00:00 2001 From: Stefan Oskamp <57906326+stefan-oskamp@users.noreply.github.com> Date: Tue, 17 Dec 2019 22:31:08 +0100 Subject: [PATCH 100/559] Added code size for USE_DHT12 --- tasmota/tasmota_post.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 108726c77..b095fdbf2 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -135,7 +135,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code) //#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code) #define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code) -#define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0kx code) +#define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0k7 code) //#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code) //#define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) From 46aec3acf5d139fe505179c920f9428b393cc7d2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 18 Dec 2019 11:41:10 +0100 Subject: [PATCH 101/559] Fix AWS mqtt host length clipped to 32 --- tasmota/settings.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index d5c59246f..881ec2e7c 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -590,8 +590,8 @@ char* SettingsText(uint32_t index) case SET_WEBPWD: position = Settings.web_password; break; #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) case SET_MQTT_HOST: - strlcpy(aws_mqtt_host, Settings.mqtt_user, strlen(Settings.mqtt_user)); - strlcpy(&aws_mqtt_host[strlen(Settings.mqtt_user)], Settings.mqtt_host, sizeof(Settings.mqtt_host)); + strncpy(aws_mqtt_host, Settings.mqtt_user, strlen(Settings.mqtt_user)); + strncpy(&aws_mqtt_host[strlen(Settings.mqtt_user)], Settings.mqtt_host, strlen(Settings.mqtt_host)); position = aws_mqtt_host; break; case SET_MQTT_USER: position = aws_mqtt_user; break; #else From ac1e153ec04c0c316819e86dc4c42fa172dd2e2c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 18 Dec 2019 11:54:31 +0100 Subject: [PATCH 102/559] Better and smaller AWS fix --- tasmota/settings.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 881ec2e7c..bcc182de9 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -590,8 +590,7 @@ char* SettingsText(uint32_t index) case SET_WEBPWD: position = Settings.web_password; break; #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) case SET_MQTT_HOST: - strncpy(aws_mqtt_host, Settings.mqtt_user, strlen(Settings.mqtt_user)); - strncpy(&aws_mqtt_host[strlen(Settings.mqtt_user)], Settings.mqtt_host, strlen(Settings.mqtt_host)); + snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), Settings.mqtt_user, Settings.mqtt_host); position = aws_mqtt_host; break; case SET_MQTT_USER: position = aws_mqtt_user; break; #else From dd94df28afb08199180d8e9c7a46a6a46974116d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 18 Dec 2019 14:29:05 +0100 Subject: [PATCH 103/559] Update fallback preparation --- tasmota/settings.ino | 34 ++++++++++++++++++++++++---------- tasmota/tasmota.h | 6 +++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index bcc182de9..afb327725 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1387,16 +1387,23 @@ void SettingsDelta(void) } if ((VERSION < 0x08000000) && (Settings.version > VERSION)) { - char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp)); - char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21)); - char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22)); - char temp23[strlen(SettingsText(SET_MQTTPREFIX3)) +1]; strncpy(temp23, SettingsText(SET_MQTTPREFIX3), sizeof(temp23)); - char temp31[strlen(SettingsText(SET_STASSID1)) +1]; strncpy(temp31, SettingsText(SET_STASSID1), sizeof(temp31)); - char temp32[strlen(SettingsText(SET_STASSID2)) +1]; strncpy(temp32, SettingsText(SET_STASSID2), sizeof(temp32)); - char temp41[strlen(SettingsText(SET_STAPWD1)) +1]; strncpy(temp41, SettingsText(SET_STAPWD1), sizeof(temp41)); - char temp42[strlen(SettingsText(SET_STAPWD2)) +1]; strncpy(temp42, SettingsText(SET_STAPWD2), sizeof(temp42)); - char temp5[strlen(SettingsText(SET_HOSTNAME)) +1]; strncpy(temp5, SettingsText(SET_HOSTNAME), sizeof(temp5)); - char temp6[strlen(SettingsText(SET_SYSLOG_HOST)) +1]; strncpy(temp6, SettingsText(SET_SYSLOG_HOST), sizeof(temp5)); + char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp)); + char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21)); + char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22)); + char temp23[strlen(SettingsText(SET_MQTTPREFIX3)) +1]; strncpy(temp23, SettingsText(SET_MQTTPREFIX3), sizeof(temp23)); + char temp31[strlen(SettingsText(SET_STASSID1)) +1]; strncpy(temp31, SettingsText(SET_STASSID1), sizeof(temp31)); + char temp32[strlen(SettingsText(SET_STASSID2)) +1]; strncpy(temp32, SettingsText(SET_STASSID2), sizeof(temp32)); + char temp41[strlen(SettingsText(SET_STAPWD1)) +1]; strncpy(temp41, SettingsText(SET_STAPWD1), sizeof(temp41)); + char temp42[strlen(SettingsText(SET_STAPWD2)) +1]; strncpy(temp42, SettingsText(SET_STAPWD2), sizeof(temp42)); + char temp5[strlen(SettingsText(SET_HOSTNAME)) +1]; strncpy(temp5, SettingsText(SET_HOSTNAME), sizeof(temp5)); + char temp6[strlen(SettingsText(SET_SYSLOG_HOST)) +1]; strncpy(temp6, SettingsText(SET_SYSLOG_HOST), sizeof(temp6)); + char temp7[strlen(SettingsText(SET_MQTT_HOST)) +1]; strncpy(temp7, SettingsText(SET_MQTT_HOST), sizeof(temp7)); + char temp8[strlen(SettingsText(SET_MQTT_CLIENT)) +1]; strncpy(temp8, SettingsText(SET_MQTT_CLIENT), sizeof(temp8)); + char temp9[strlen(SettingsText(SET_MQTT_USER)) +1]; strncpy(temp9, SettingsText(SET_MQTT_USER), sizeof(temp9)); + char temp10[strlen(SettingsText(SET_MQTT_PWD)) +1]; strncpy(temp10, SettingsText(SET_MQTT_PWD), sizeof(temp10)); + char temp11[strlen(SettingsText(SET_MQTT_TOPIC)) +1]; strncpy(temp11, SettingsText(SET_MQTT_TOPIC), sizeof(temp11)); + char temp12[strlen(SettingsText(SET_MQTT_BUTTON_TOPIC)) +1]; strncpy(temp12, SettingsText(SET_MQTT_BUTTON_TOPIC), sizeof(temp12)); + char temp13[strlen(SettingsText(SET_MQTT_GRP_TOPIC)) +1]; strncpy(temp13, SettingsText(SET_MQTT_GRP_TOPIC), sizeof(temp13)); uint32_t version = Settings.version; Settings.version = VERSION; @@ -1410,6 +1417,13 @@ void SettingsDelta(void) SettingsUpdateText(SET_STAPWD2, temp42); SettingsUpdateText(SET_HOSTNAME, temp5); SettingsUpdateText(SET_SYSLOG_HOST, temp6); + SettingsUpdateText(SET_MQTT_HOST, temp7); + SettingsUpdateText(SET_MQTT_CLIENT, temp8); + SettingsUpdateText(SET_MQTT_USER, temp9); + SettingsUpdateText(SET_MQTT_PWD, temp10); + SettingsUpdateText(SET_MQTT_TOPIC, temp11); + SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); Settings.version = version; } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 1f676acd4..c93c3ea9e 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -277,15 +277,15 @@ enum SettingsTextIndex { SET_OTAURL, SET_STASSID1, SET_STASSID2, SET_STAPWD1, SET_STAPWD2, SET_HOSTNAME, SET_SYSLOG_HOST, - SET_WEBPWD, + SET_WEBPWD, SET_CORS, SET_MQTT_HOST, SET_MQTT_CLIENT, SET_MQTT_USER, SET_MQTT_PWD, SET_MQTT_FULLTOPIC, SET_MQTT_TOPIC, SET_MQTT_BUTTON_TOPIC, SET_MQTT_SWITCH_TOPIC, SET_MQTT_GRP_TOPIC, SET_STATE_TXT1, SET_STATE_TXT2, SET_STATE_TXT3, SET_STATE_TXT4, SET_NTPSERVER1, SET_NTPSERVER2, SET_NTPSERVER3, - SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5, - SET_CORS, + SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5, SET_MEM6, SET_MEM7, SET_MEM8, + SET_MEM9, SET_MEM10, SET_MEM11, SET_MEM12, SET_MEM13, SET_MEM14, SET_MEM15, SET_MEM16, SET_FRIENDLYNAME1, SET_FRIENDLYNAME2, SET_FRIENDLYNAME3, SET_FRIENDLYNAME4, // SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, // Future extension From 62f4419a595353fcf92643226d536751cbdc26f2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 18 Dec 2019 14:48:32 +0100 Subject: [PATCH 104/559] Update settings.ino --- tasmota/settings.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index afb327725..139fd3845 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1386,7 +1386,7 @@ void SettingsDelta(void) memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); // 1E4 -> EFE } - if ((VERSION < 0x08000000) && (Settings.version > VERSION)) { + if ((VERSION < 0x08000000) && (Settings.version >= 0x08000000)) { char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp)); char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21)); char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22)); From e574f7dd841a501406a2cd2632f2a07a17ac7b53 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 18 Dec 2019 14:54:14 +0100 Subject: [PATCH 105/559] Add fallback support from version 8.x --- RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b8220e8d3..4360e8ee3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -54,6 +54,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) - Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167) - Change some Settings locations freeing up space for future single char allowing variable length text +- Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE - Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649) - Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) - Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) @@ -71,3 +72,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) - Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger - Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode +- Add fallback support from version 8.x diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 90f29af2a..1bf38a0ec 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,7 +6,7 @@ - Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE - Add Zigbee send automatic ZigbeeRead after sending a command - Add Zigbee improving Occupancy:false detection for Aqara sensor -- Add fallback functionality from next version 8.x +- Add fallback support from version 8.x ### 7.1.2.5 20191213 From 5c282db649b6928b15701f393a147bbb6a1e7259 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 18 Dec 2019 18:21:10 +0100 Subject: [PATCH 106/559] Add some GPIO checks --- tasmota/support.ino | 7 +++++++ tasmota/support_tasmota.ino | 10 ++++------ tasmota/xdrv_24_buzzer.ino | 4 ++-- tasmota/xnrg_01_hlw8012.ino | 4 +--- tasmota/xnrg_04_mcp39f501.ino | 4 +--- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index 87f05ad27..4b2bc49fb 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -995,6 +995,13 @@ int ResponseJsonEndEnd(void) * GPIO Module and Template management \*********************************************************************************************/ +void DigitalWrite(uint32_t gpio_pin, uint32_t state) +{ + if (pin[gpio_pin] < 99) { + digitalWrite(pin[gpio_pin], state &1); + } +} + uint8_t ModuleNr(void) { // 0 = User module (255) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index ff2b6f40a..0935d9a28 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -166,9 +166,7 @@ void SetLatchingRelay(power_t lpower, uint32_t state) for (uint32_t i = 0; i < devices_present; i++) { uint32_t port = (i << 1) + ((latching_power >> i) &1); - if (pin[GPIO_REL1 +port] < 99) { - digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state); - } + DigitalWrite(GPIO_REL1 +port, bitRead(rel_inverted, port) ? !state : state); } } @@ -226,8 +224,8 @@ void SetDevicePower(power_t rpower, uint32_t source) else { for (uint32_t i = 0; i < devices_present; i++) { power_t state = rpower &1; - if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { - digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state); + if (i < MAX_RELAYS) { + DigitalWrite(GPIO_REL1 +i, bitRead(rel_inverted, i) ? !state : state); } rpower >>= 1; } @@ -293,7 +291,7 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) } else { led_power &= (0xFF ^ mask); } - digitalWrite(pin[GPIO_LED1 + led], bitRead(led_inverted, led) ? !state : state); + DigitalWrite(GPIO_LED1 + led, bitRead(led_inverted, led) ? !state : state); } } diff --git a/tasmota/xdrv_24_buzzer.ino b/tasmota/xdrv_24_buzzer.ino index 2266b1af7..968f91cad 100644 --- a/tasmota/xdrv_24_buzzer.ino +++ b/tasmota/xdrv_24_buzzer.ino @@ -39,7 +39,7 @@ struct BUZZER { void BuzzerOff(void) { - digitalWrite(pin[GPIO_BUZZER], Buzzer.inverted); // Buzzer Off + DigitalWrite(GPIO_BUZZER, Buzzer.inverted); // Buzzer Off } //void BuzzerBeep(uint32_t count = 1, uint32_t on = 1, uint32_t off = 1, uint32_t tune = 0); @@ -124,7 +124,7 @@ void BuzzerEvery100mSec(void) Buzzer.duration = Buzzer.set[Buzzer.state]; } } - digitalWrite(pin[GPIO_BUZZER], (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); + DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); } else { Buzzer.enable = false; } diff --git a/tasmota/xnrg_01_hlw8012.ino b/tasmota/xnrg_01_hlw8012.ino index 488da7059..3b01eaea7 100644 --- a/tasmota/xnrg_01_hlw8012.ino +++ b/tasmota/xnrg_01_hlw8012.ino @@ -143,9 +143,7 @@ void HlwEvery200ms(void) if (Hlw.cf1_timer >= 8) { Hlw.cf1_timer = 0; Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; - if (pin[GPIO_NRG_SEL] < 99) { - digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); - } + DigitalWrite(GPIO_NRG_SEL, Hlw.select_ui_flag); if (Hlw.cf1_pulse_counter) { cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter; diff --git a/tasmota/xnrg_04_mcp39f501.ino b/tasmota/xnrg_04_mcp39f501.ino index 2fa98276d..d5a5dde4a 100644 --- a/tasmota/xnrg_04_mcp39f501.ino +++ b/tasmota/xnrg_04_mcp39f501.ino @@ -570,9 +570,7 @@ void McpSnsInit(void) } else { mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); } - if (pin[GPIO_MCP39F5_RST] < 99) { - digitalWrite(pin[GPIO_MCP39F5_RST], 1); // MCP enable - } + DigitalWrite(GPIO_MCP39F5_RST, 1); // MCP enable } else { energy_flg = ENERGY_NONE; } From fdd65bbf8c031a025bb7b4da7fabe2b319096f65 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Wed, 18 Dec 2019 22:00:05 -0300 Subject: [PATCH 107/559] Update xdrv_12_home_assistant.ino --- tasmota/xdrv_12_home_assistant.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 58c266c61..274b5f42a 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -340,10 +340,10 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); if (toggle) { if (!key) { - TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT1 + toggle?2:1)); + TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT3)); } else {TryResponseAppend_P(HASS_DISCOVER_SWITCH_TOGGLE);} } - else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT1 + toggle?2:1), SettingsText(SET_STATE_TXT1)); + else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2), SettingsText(SET_STATE_TXT1)); TryResponseAppend_P(PSTR("}")); } From 6cae0f8f14fb92a275899e8d0af27e052fde464e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 19 Dec 2019 10:06:23 +0100 Subject: [PATCH 108/559] Add some more fallback code --- tasmota/settings.ino | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 139fd3845..8820967a4 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1128,6 +1128,10 @@ void SettingsDefaultSet2(void) memset(&Settings.monitors, 0xFF, 20); // Enable all possible monitors, displays and sensors SettingsEnableAllI2cDrivers(); + + if (VERSION < 0x08000000) { + SettingsBackwardCompat(); + } } /********************************************************************************************/ @@ -1167,6 +1171,17 @@ void SettingsEnableAllI2cDrivers(void) Settings.i2c_drivers[2] = 0xFFFFFFFF; } +void SettingsBackwardCompat(void) +{ + Settings.ex_seriallog_level = Settings.seriallog_level; // 09E <- 452 + Settings.ex_sta_config = Settings.sta_config; // 09F <- EC7 + Settings.ex_sta_active = Settings.sta_active; // 0A0 <- EC8 + memcpy((char*)&Settings.ex_rule_stop, (char*)&Settings.rule_stop, 47); // 1A7 <- EC9 + Settings.ex_flag4 = Settings.flag4; // 1E0 <- EF8 + Settings.ex_mqtt_port = Settings.mqtt_port; // 20A <- EFC + memcpy((char*)&Settings.ex_serial_config, (char*)&Settings.serial_config, 5); // 1E4 <- EFE +} + /********************************************************************************************/ void SettingsDelta(void) @@ -1425,6 +1440,8 @@ void SettingsDelta(void) SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); Settings.version = version; + + SettingsBackwardCompat(); } Settings.version = VERSION; From 1288cc20e0dfff4dd376060bb29019138bf11a13 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 19 Dec 2019 15:30:25 +0100 Subject: [PATCH 109/559] Fix fallback from 8.x after full erase --- tasmota/settings.ino | 162 +++++++++++++++++++------------------------ 1 file changed, 71 insertions(+), 91 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 8820967a4..d921e4957 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -471,97 +471,59 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me) char replace[replace_len +1]; memcpy(replace, replace_me, sizeof(replace)); - if (Settings.version < 0x08000000) { - uint32_t idx = 0; - switch (index) { - case SET_OTAURL: strlcpy(Settings.ota_url, replace, sizeof(Settings.ota_url)); break; - case SET_MQTTPREFIX3: idx++; - case SET_MQTTPREFIX2: idx++; - case SET_MQTTPREFIX1: strlcpy(Settings.mqtt_prefix[idx], replace, sizeof(Settings.mqtt_prefix[idx])); break; - case SET_STASSID2: idx++; - case SET_STASSID1: strlcpy(Settings.sta_ssid[idx], replace, sizeof(Settings.sta_ssid[idx])); break; - case SET_STAPWD2: idx++; - case SET_STAPWD1: strlcpy(Settings.sta_pwd[idx], replace, sizeof(Settings.sta_pwd[idx])); break; - case SET_HOSTNAME: strlcpy(Settings.hostname, replace, sizeof(Settings.hostname)); break; - case SET_SYSLOG_HOST: strlcpy(Settings.syslog_host, replace, sizeof(Settings.syslog_host)); break; - case SET_WEBPWD: strlcpy(Settings.web_password, replace, sizeof(Settings.web_password)); break; + uint32_t idx = 0; + switch (index) { + case SET_OTAURL: strlcpy(Settings.ota_url, replace, sizeof(Settings.ota_url)); break; + case SET_MQTTPREFIX3: idx++; + case SET_MQTTPREFIX2: idx++; + case SET_MQTTPREFIX1: strlcpy(Settings.mqtt_prefix[idx], replace, sizeof(Settings.mqtt_prefix[idx])); break; + case SET_STASSID2: idx++; + case SET_STASSID1: strlcpy(Settings.sta_ssid[idx], replace, sizeof(Settings.sta_ssid[idx])); break; + case SET_STAPWD2: idx++; + case SET_STAPWD1: strlcpy(Settings.sta_pwd[idx], replace, sizeof(Settings.sta_pwd[idx])); break; + case SET_HOSTNAME: strlcpy(Settings.hostname, replace, sizeof(Settings.hostname)); break; + case SET_SYSLOG_HOST: strlcpy(Settings.syslog_host, replace, sizeof(Settings.syslog_host)); break; + case SET_WEBPWD: strlcpy(Settings.web_password, replace, sizeof(Settings.web_password)); break; #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - case SET_MQTT_HOST: - if (strlen(replace) <= sizeof(Settings.mqtt_host)) { - strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); - Settings.mqtt_user[0] = 0; - } else { - // need to split in mqtt_user first then mqtt_host - strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); - strlcpy(Settings.mqtt_host, &replace[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); - } - break; - case SET_MQTT_USER: break; + case SET_MQTT_HOST: + if (strlen(replace) <= sizeof(Settings.mqtt_host)) { + strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); + Settings.mqtt_user[0] = 0; + } else { + // need to split in mqtt_user first then mqtt_host + strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); + strlcpy(Settings.mqtt_host, &replace[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); + } + break; + case SET_MQTT_USER: break; #else - case SET_MQTT_HOST: strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); break; - case SET_MQTT_USER: strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); break; + case SET_MQTT_HOST: strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); break; + case SET_MQTT_USER: strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); break; #endif - case SET_MQTT_CLIENT: strlcpy(Settings.mqtt_client, replace, sizeof(Settings.mqtt_client)); break; - case SET_MQTT_PWD: strlcpy(Settings.mqtt_pwd, replace, sizeof(Settings.mqtt_pwd)); break; - case SET_MQTT_FULLTOPIC: strlcpy(Settings.mqtt_fulltopic, replace, sizeof(Settings.mqtt_fulltopic)); break; - case SET_MQTT_TOPIC: strlcpy(Settings.mqtt_topic, replace, sizeof(Settings.mqtt_topic)); break; - case SET_MQTT_BUTTON_TOPIC: strlcpy(Settings.button_topic, replace, sizeof(Settings.button_topic)); break; - case SET_MQTT_SWITCH_TOPIC: strlcpy(Settings.switch_topic, replace, sizeof(Settings.switch_topic)); break; - case SET_MQTT_GRP_TOPIC: strlcpy(Settings.mqtt_grptopic, replace, sizeof(Settings.mqtt_grptopic)); break; - case SET_STATE_TXT4: idx++; - case SET_STATE_TXT3: idx++; - case SET_STATE_TXT2: idx++; - case SET_STATE_TXT1: strlcpy(Settings.state_text[idx], replace, sizeof(Settings.state_text[idx])); break; - case SET_NTPSERVER3: idx++; - case SET_NTPSERVER2: idx++; - case SET_NTPSERVER1: strlcpy(Settings.ntp_server[idx], replace, sizeof(Settings.ntp_server[idx])); break; - case SET_MEM5: idx++; - case SET_MEM4: idx++; - case SET_MEM3: idx++; - case SET_MEM2: idx++; - case SET_MEM1: strlcpy(Settings.mems[idx], replace, sizeof(Settings.mems[idx])); break; - case SET_CORS: strlcpy(Settings.cors_domain, replace, sizeof(Settings.cors_domain)); break; - case SET_FRIENDLYNAME4: idx++; - case SET_FRIENDLYNAME3: idx++; - case SET_FRIENDLYNAME2: idx++; - case SET_FRIENDLYNAME1: strlcpy(Settings.friendlyname[idx], replace, sizeof(Settings.friendlyname[idx])); break; - } - } else { - uint32_t start_pos = 0; - uint32_t end_pos = 0; - char* position = Settings.ota_url; - for (uint32_t size = 0; size < SET_MAX; size++) { - while (*position++ != '\0') { } - if (1 == index) { - start_pos = position - Settings.ota_url; - } - else if (0 == index) { - end_pos = position - Settings.ota_url -1; - } - index--; - } - uint32_t char_len = position - Settings.ota_url; - - uint32_t current_len = end_pos - start_pos; - int diff = replace_len - current_len; - - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"), - // start_pos, end_pos, char_len, current_len, replace_len, diff); - - int too_long = (char_len + diff) - settings_text_size; - if (too_long > 0) { - // AddLog_P2(LOG_LEVEL_INFO, PSTR("CFG: Text too long by %d char(s)"), too_long); - return false; // Replace text too long - } - - if (diff != 0) { - // Shift Settings.text up or down - memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos); - } - // Replace text - memmove_P(Settings.ota_url + start_pos, replace, replace_len); - // Fill for future use - memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff); + case SET_MQTT_CLIENT: strlcpy(Settings.mqtt_client, replace, sizeof(Settings.mqtt_client)); break; + case SET_MQTT_PWD: strlcpy(Settings.mqtt_pwd, replace, sizeof(Settings.mqtt_pwd)); break; + case SET_MQTT_FULLTOPIC: strlcpy(Settings.mqtt_fulltopic, replace, sizeof(Settings.mqtt_fulltopic)); break; + case SET_MQTT_TOPIC: strlcpy(Settings.mqtt_topic, replace, sizeof(Settings.mqtt_topic)); break; + case SET_MQTT_BUTTON_TOPIC: strlcpy(Settings.button_topic, replace, sizeof(Settings.button_topic)); break; + case SET_MQTT_SWITCH_TOPIC: strlcpy(Settings.switch_topic, replace, sizeof(Settings.switch_topic)); break; + case SET_MQTT_GRP_TOPIC: strlcpy(Settings.mqtt_grptopic, replace, sizeof(Settings.mqtt_grptopic)); break; + case SET_STATE_TXT4: idx++; + case SET_STATE_TXT3: idx++; + case SET_STATE_TXT2: idx++; + case SET_STATE_TXT1: strlcpy(Settings.state_text[idx], replace, sizeof(Settings.state_text[idx])); break; + case SET_NTPSERVER3: idx++; + case SET_NTPSERVER2: idx++; + case SET_NTPSERVER1: strlcpy(Settings.ntp_server[idx], replace, sizeof(Settings.ntp_server[idx])); break; + case SET_MEM5: idx++; + case SET_MEM4: idx++; + case SET_MEM3: idx++; + case SET_MEM2: idx++; + case SET_MEM1: strlcpy(Settings.mems[idx], replace, sizeof(Settings.mems[idx])); break; + case SET_CORS: strlcpy(Settings.cors_domain, replace, sizeof(Settings.cors_domain)); break; + case SET_FRIENDLYNAME4: idx++; + case SET_FRIENDLYNAME3: idx++; + case SET_FRIENDLYNAME2: idx++; + case SET_FRIENDLYNAME1: strlcpy(Settings.friendlyname[idx], replace, sizeof(Settings.friendlyname[idx])); break; } return true; @@ -1402,6 +1364,27 @@ void SettingsDelta(void) } if ((VERSION < 0x08000000) && (Settings.version >= 0x08000000)) { + SettingsUpdateText(SET_WEBPWD, SettingsText(SET_WEBPWD)); + SettingsUpdateText(SET_CORS, SettingsText(SET_CORS)); + SettingsUpdateText(SET_MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); + SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, SettingsText(SET_MQTT_SWITCH_TOPIC)); + SettingsUpdateText(SET_STATE_TXT1, SettingsText(SET_STATE_TXT1)); + SettingsUpdateText(SET_STATE_TXT2, SettingsText(SET_STATE_TXT2)); + SettingsUpdateText(SET_STATE_TXT3, SettingsText(SET_STATE_TXT3)); + SettingsUpdateText(SET_STATE_TXT4, SettingsText(SET_STATE_TXT4)); + SettingsUpdateText(SET_NTPSERVER1, SettingsText(SET_NTPSERVER1)); + SettingsUpdateText(SET_NTPSERVER2, SettingsText(SET_NTPSERVER2)); + SettingsUpdateText(SET_NTPSERVER3, SettingsText(SET_NTPSERVER3)); + SettingsUpdateText(SET_MEM1, SettingsText(SET_MEM1)); + SettingsUpdateText(SET_MEM2, SettingsText(SET_MEM2)); + SettingsUpdateText(SET_MEM3, SettingsText(SET_MEM3)); + SettingsUpdateText(SET_MEM4, SettingsText(SET_MEM4)); + SettingsUpdateText(SET_MEM5, SettingsText(SET_MEM5)); + SettingsUpdateText(SET_FRIENDLYNAME1, SettingsText(SET_FRIENDLYNAME1)); + SettingsUpdateText(SET_FRIENDLYNAME2, SettingsText(SET_FRIENDLYNAME2)); + SettingsUpdateText(SET_FRIENDLYNAME3, SettingsText(SET_FRIENDLYNAME3)); + SettingsUpdateText(SET_FRIENDLYNAME4, SettingsText(SET_FRIENDLYNAME4)); + char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp)); char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21)); char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22)); @@ -1420,8 +1403,6 @@ void SettingsDelta(void) char temp12[strlen(SettingsText(SET_MQTT_BUTTON_TOPIC)) +1]; strncpy(temp12, SettingsText(SET_MQTT_BUTTON_TOPIC), sizeof(temp12)); char temp13[strlen(SettingsText(SET_MQTT_GRP_TOPIC)) +1]; strncpy(temp13, SettingsText(SET_MQTT_GRP_TOPIC), sizeof(temp13)); - uint32_t version = Settings.version; - Settings.version = VERSION; SettingsUpdateText(SET_OTAURL, temp); SettingsUpdateText(SET_MQTTPREFIX1, temp21); SettingsUpdateText(SET_MQTTPREFIX2, temp22); @@ -1439,7 +1420,6 @@ void SettingsDelta(void) SettingsUpdateText(SET_MQTT_TOPIC, temp11); SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); - Settings.version = version; SettingsBackwardCompat(); } From a2b4b1b06d507a01b18f96cd03bae71e291eaf5a Mon Sep 17 00:00:00 2001 From: stefanbode Date: Fri, 20 Dec 2019 11:27:35 +0100 Subject: [PATCH 110/559] new features - new closeduration - new control how to accelerate an decellerate --- tasmota/xdrv_27_shutter.ino | 253 ++++++++++++++++++++---------------- 1 file changed, 142 insertions(+), 111 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index e13bba771..8392bebad 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -27,11 +27,13 @@ #define D_SHUTTER "SHUTTER" const uint16_t MOTOR_STOP_TIME = 500; // in mS +const uint8_t steps_per_second = 20; // FUNC_EVERY_50_MSECOND uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; uint16_t messwerte[5] = {30,50,70,90,100}; +uint16_t last_execute_step; -enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE }; +enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" @@ -68,43 +70,51 @@ struct SHUTTER { uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE int16_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. int16_t pwm_frequency; // frequency of PWN for stepper motors - uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency that can be used. depend on the motor and drivers + uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency for openig the shutter. depend on the motor and drivers + uint16_t max_close_pwm_frequency[MAX_SHUTTERS];// maximum of PWM frequency for closeing the shutter. depend on the motor and drivers uint8_t skip_relay_change; // avoid overrun at endstops + int32_t accelerator[MAX_SHUTTERS]; // speed of ramp-up, ramp down of shutter } Shutter; void ShutterRtc50mS(void) { for (uint32_t i = 0; i < shutters_present; i++) { Shutter.time[i]++; + if (Shutter.accelerator[i]) { + Shutter.pwm_frequency += Shutter.accelerator[i]; + Shutter.pwm_frequency = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency)); + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 50); + } } } -int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index) +int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t i) { - if (Settings.shutter_set50percent[index] != 50) { - return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; + if (Settings.shutter_set50percent[i] != 50) { + return percent <= 5 ? Settings.shuttercoeff[2][i] * percent : Settings.shuttercoeff[1][i] * percent + Settings.shuttercoeff[0][i]; } else { int32_t realpos; // check against DIV 0 for (uint8_t j=0 ; j < 5 ; j++) { - if (Settings.shuttercoeff[j][index] == 0) { + if (Settings.shuttercoeff[j][i] == 0) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); for (uint8_t k=0 ; k < 5 ; k++) { - Settings.shuttercoeff[k][index] = messwerte[k] * 1000 / messwerte[4]; + Settings.shuttercoeff[k][i] = messwerte[k] * 1000 / messwerte[4]; } } } - for (uint8_t i=0 ; i < 5 ; i++) { - if (percent*10 > Settings.shuttercoeff[i][index]) { - realpos = Shutter.open_max[index] * calibrate_pos[i+1] / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[i][index]); + for (uint8_t l=0 ; l < 5 ; l++) { + if (percent*10 > Settings.shuttercoeff[l][i]) { + realpos = Shutter.open_max[i] * calibrate_pos[l+1] / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[l][i]); } else { - if ( i == 0) { - realpos = percent * Shutter.open_max[index] * calibrate_pos[i+1] / Settings.shuttercoeff[i][index] / 10; + if ( l == 0) { + realpos = percent * Shutter.open_max[i] * calibrate_pos[l+1] / Settings.shuttercoeff[l][i] / 10; } else { - //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[i+1] - calibrate_pos[i]), (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index])); - realpos += ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; + //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][i] ) * Shutter_Open_Max[i] * (calibrate_pos[l+1] - calibrate_pos[l]) / (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][l]) / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[l+1] - calibrate_pos[l]), (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][l])); + realpos += ( percent*10 - Settings.shuttercoeff[l-1][i] ) * Shutter.open_max[i] * (calibrate_pos[l+1] - calibrate_pos[l]) / (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][i]) / 100; } break; } @@ -113,25 +123,25 @@ int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index) } } -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t index) +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t i) { - if (Settings.shutter_set50percent[index] != 50) { - return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; + if (Settings.shutter_set50percent[i] != 50) { + return Settings.shuttercoeff[2][i] * 5 > realpos ? realpos / Settings.shuttercoeff[2][i] : (realpos-Settings.shuttercoeff[0][i]) / Settings.shuttercoeff[1][i]; } else { int16_t realpercent; - for (uint8_t i=0 ; i < 5 ; i++) { - if (realpos > Shutter.open_max[index] * calibrate_pos[i+1] / 100) { - realpercent = Settings.shuttercoeff[i][index] /10; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[index] * calibrate_pos[i+1] / 100); + for (uint8_t j=0 ; j < 5 ; j++) { + if (realpos > Shutter.open_max[i] * calibrate_pos[j+1] / 100) { + realpercent = Settings.shuttercoeff[j][i] /10; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[i] * calibrate_pos[i+1] / 100); } else { if ( i == 0) { - realpercent = ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * Settings.shuttercoeff[i][index] / calibrate_pos[i+1] / Shutter.open_max[index]; + realpercent = ( realpos - (Shutter.open_max[i] * calibrate_pos[j] / 100) ) * 10 * Settings.shuttercoeff[j][i] / calibrate_pos[j+1] / Shutter.open_max[i]; } else { - //uint16_t addon = ( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[index]; - //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[index]/100, (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index])); - realpercent += ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i]) / Shutter.open_max[index] ; + //uint16_t addon = ( realpos - (Shutter_Open_Max[i] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][i] - Settings.shuttercoeff[i-1][i]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[i]; + //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][i] ) * Shutter_Open_Max[i] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][i] -Settings.shuttercoeff[i-1][i]) / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[i] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[i]/100, (Settings.shuttercoeff[i][i] -Settings.shuttercoeff[i-1][i])); + realpercent += ( realpos - (Shutter.open_max[i] * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][i] - Settings.shuttercoeff[j-1][i]) / (calibrate_pos[j+1] - calibrate_pos[j]) / Shutter.open_max[i] ; } break; } @@ -148,12 +158,11 @@ void ShutterInit(void) Shutter.old_power = power; bool relay_in_interlock = false; + // if shutter 4 is unused + if (Settings.shutter_startrelay[MAX_SHUTTERS] == 0) { + Shutter.max_pwm_frequency = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : Shutter.max_pwm_frequency; + } for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - // upgrade to 0.1sec calculation base. - if ( Settings.shutter_accuracy == 0) { - Settings.shutter_closetime[i] = Settings.shutter_closetime[i] * 10; - Settings.shutter_opentime[i] = Settings.shutter_opentime[i] * 10; - } // set startrelay to 1 on first init, but only to shutter 1. 90% usecase Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]); if (Settings.shutter_startrelay[i] && Settings.shutter_startrelay[i] <9) { @@ -177,7 +186,8 @@ void ShutterInit(void) } } else { Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; - if (pin[GPIO_PWM1+i] < 99) { + if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i]) { + Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER; Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); analogWrite(pin[GPIO_PWM1+i], 50); @@ -195,6 +205,8 @@ void ShutterInit(void) // Update Calculation 20 because time interval is 0.05 sec Shutter.open_max[i] = 200 * Shutter.open_time[i]; Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ; + Shutter.max_close_pwm_frequency[i] = Shutter.max_pwm_frequency*Shutter.open_time[i]/Shutter.close_time[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Closefreq: %d"),i, Shutter.max_close_pwm_frequency[i]); // calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part if (Settings.shutter_set50percent[i] != 50) { @@ -222,43 +234,54 @@ void ShutterInit(void) // terminate loop at first INVALID shutter. break; } - if (shutters_present < 4) { - Shutter.max_pwm_frequency = Settings.shuttercoeff[4][4] > 0 ? Settings.shuttercoeff[4][4] : Shutter.max_pwm_frequency; - } + Settings.shutter_accuracy = 1; } } void ShutterUpdatePosition(void) { + char scommand[CMDSZ]; char stopic[TOPSZ]; char stemp2[10]; for (uint32_t i = 0; i < shutters_present; i++) { if (Shutter.direction[i] != 0) { - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { + int32_t stop_position_delta = 20; + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { // Calculate position with counter. Much more accurate and no need for motordelay workaround // adding some steps to stop early - Shutter.real_position[i] = Shutter.direction[i] * 20 + ShutterCounterBasedPosition(i);; - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + + int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; + int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); + int32_t min_runtime_ms = Shutter.pwm_frequency*1000 / max_freq_change_per_sec; + int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; + int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency / max_frequency * Shutter.direction[i] ; + + int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; + stop_position_delta =200 * Shutter.pwm_frequency/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); + //Shutter.accelerator[i] = tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); + //int32_t act_freq_change = max_freq_change_per_sec/20; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, + Shutter.pwm_frequency,max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); + + if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { + + Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]); + } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency == max_frequency) { + Shutter.accelerator[i] = 0; + } } else { Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); } - - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE && pin[GPIO_PWM1+i] < 99) { - uint16_t freq_change = Shutter.max_pwm_frequency/(Shutter.motordelay[i]+1); - // ramp up phase. calculate frequency - Shutter.pwm_frequency = tmin(freq_change * Shutter.time[i],Shutter.max_pwm_frequency); - // ramp down at the end of the movement time will not be exactly motordelay - Shutter.pwm_frequency = tmax(tmin(freq_change * (Shutter.target_position[i]-Shutter.real_position[i])*Shutter.direction[i]/30, Shutter.pwm_frequency),10); - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+i], 50); - } - if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) { + if ( Shutter.real_position[i] * Shutter.direction[i] + stop_position_delta >= Shutter.target_position[i] * Shutter.direction[i] ) { // calculate relay number responsible for current movement. //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter.real_position[i], Shutter.target_position[i],Shutter.direction[i]); uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; + int16_t missing_steps; switch (Shutter.mode) { case SHT_PULSE_OPEN__PULSE_CLOSE: @@ -269,29 +292,34 @@ void ShutterUpdatePosition(void) last_source = SRC_SHUTTER; } break; - case SHT_OFF_ON__OPEN_CLOSE: - // This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction - // Only allow PWM microstepping if PWM and COUNTER are defined. - // see wiki to connect PWM and COUNTER - if (pin[GPIO_PWM1+i] < 99 && pin[GPIO_CNTR1+i] < 99 ) { - int16_t missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; - //prepare for stop PWM - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); - while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { - delay(1); - } - analogWrite(pin[GPIO_PWM1+i], 0); - Shutter.real_position[i] = ShutterCounterBasedPosition(i); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); - + case SHT_OFF_ON__OPEN_CLOSE_STEPPER: + missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; + //prepare for stop PWM + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); + Shutter.accelerator[i] = 0; + Shutter.pwm_frequency = Shutter.pwm_frequency > 250 ? 250 : Shutter.pwm_frequency; + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 50); + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); + while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { + delay(1); } + analogWrite(pin[GPIO_PWM1+i], 0); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); } break; + case SHT_OFF_ON__OPEN_CLOSE: + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); + } + break; case SHT_OFF_OPEN__OFF_CLOSE: // avoid switching OFF a relay already OFF if ((1 << (cur_relay-1)) & power) { @@ -302,7 +330,7 @@ void ShutterUpdatePosition(void) } Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); - dtostrfd((float)Shutter.time[i] / 20, 1, stemp2); + dtostrfd((float)Shutter.time[i] / steps_per_second, 1, stemp2); AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); Shutter.start_position[i] = Shutter.real_position[i]; @@ -332,50 +360,51 @@ bool ShutterState(uint8_t device) (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) ); } -void ShutterStartInit(uint8_t index, int8_t direction, int32_t target_pos) +void ShutterStartInit(uint8_t i, int8_t direction, int32_t target_pos) { - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter.open_max[index] - Shutter.real_position[index]) / Shutter.close_velocity[index], Shutter.real_position[index] / Shutter.close_velocity[index], 2+Shutter.motordelay[index]); - if ( ( direction == 1 && (Shutter.open_max[index] - Shutter.real_position[index]) / 100 <= 2 ) - || ( direction == -1 && Shutter.real_position[index] / Shutter.close_velocity[index] <= 2)) { + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: dir %d, delta1 %d, delta2 %d, grant %d"),direction, (Shutter.open_max[i] - Shutter.real_position[i]) / Shutter.close_velocity[i], Shutter.real_position[i] / Shutter.close_velocity[i], 2+Shutter.motordelay[i]); + if ( ( direction == 1 && (Shutter.open_max[i] - Shutter.real_position[i]) / 100 <= 2 ) + || ( direction == -1 && Shutter.real_position[i] / Shutter.close_velocity[i] <= 2)) { Shutter.skip_relay_change = 1 ; } else { - if (pin[GPIO_PWM1+index] < 99) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { Shutter.pwm_frequency = 0; analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+index], 0); + analogWrite(pin[GPIO_PWM1+i], 0); // can be operated without counter, but then not that acurate. - if (pin[GPIO_CNTR1+index] < 99) { - RtcSettings.pulse_counter[index] = 0; + if (pin[GPIO_CNTR1+i] < 99) { + RtcSettings.pulse_counter[i] = 0; } + Shutter.accelerator[i] = Shutter.max_pwm_frequency / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Ramp up: %d"), Shutter.accelerator[i]); } - Shutter.target_position[index] = target_pos; - Shutter.start_position[index] = Shutter.real_position[index]; - Shutter.time[index] = 0; + Shutter.target_position[i] = target_pos; + Shutter.start_position[i] = Shutter.real_position[i]; + Shutter.time[i] = 0; Shutter.skip_relay_change = 0; - Shutter.direction[index] = direction; - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[index], Shutter.start_position[index] ,RtcSettings.pulse_counter[index],Shutter.max_pwm_frequency , Shutter.direction[index] ,Shutter.max_pwm_frequency ); + Shutter.direction[i] = direction; + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); } - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]); + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), i, Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i]); } -void ShutterWaitForMotorStop(uint8_t index) +void ShutterWaitForMotorStop(uint8_t i) { AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { - if (pin[GPIO_PWM1+index] < 99 && pin[GPIO_CNTR1+index] < 99 ) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { + if ( Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Frequency change %d"), Shutter.pwm_frequency); - while (Shutter.pwm_frequency > 100) { - Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-(Shutter.max_pwm_frequency/(Shutter.motordelay[index]+1)) , 0); + while (Shutter.pwm_frequency > 0) { + Shutter.accelerator[i] = 0; + Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+index], 50); + analogWrite(pin[GPIO_PWM1+i], 50); delay(50); } - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+index], 0); - Shutter.real_position[index] = ShutterCounterBasedPosition(index); + analogWrite(pin[GPIO_PWM1+i], 0); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); } else { - ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); delay(MOTOR_STOP_TIME); } } else { @@ -391,7 +420,7 @@ void ShutterReportPosition(void) if (Shutter.direction[i] != 0) { char stemp2[10]; uint8_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); - dtostrfd((float)Shutter.time[i] / 20, 2, stemp2); + dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); shutter_moving = 1; //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; AddLog_P2(LOG_LEVEL_INFO, MSG_SHUTTER_POS, i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i],stemp2,Shutter.pwm_frequency); @@ -430,7 +459,7 @@ void ShutterRelayChanged(void) //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); if (manual_relays_changed) { //Shutter.skip_relay_change = true; - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { ShutterWaitForMotorStop(i); switch (powerstate_local) { case 1: @@ -478,7 +507,7 @@ void ShutterSetPosition(uint8_t device, uint8_t position) void CmndShutterOpen(void) { - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index); + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.i); if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { XdrvMailbox.index = XdrvMailbox.payload; } @@ -489,7 +518,7 @@ void CmndShutterOpen(void) void CmndShutterClose(void) { - //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, index %d"), XdrvMailbox.payload, XdrvMailbox.index); + //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.i); if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { XdrvMailbox.index = XdrvMailbox.payload; } @@ -505,14 +534,14 @@ void CmndShutterStop(void) if ( XdrvMailbox.index == 1 && XdrvMailbox.payload != -99) { XdrvMailbox.index = XdrvMailbox.payload; } - uint32_t index = XdrvMailbox.index -1; - if (Shutter.direction[index] != 0) { + uint32_t i = XdrvMailbox.index -1; + if (Shutter.direction[i] != 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[index]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]); // set stop position 10 steps ahead (0.5sec to allow normal stop) - int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index])); - XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, index); - //XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index]; + int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); + //XdrvMailbox.payload = Settings.shuttercoeff[2][i] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][i] : (temp_realpos-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; last_source = SRC_WEBGUI; CmndShutterPosition(); } else { @@ -524,7 +553,7 @@ void CmndShutterStop(void) void CmndShutterPosition(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - uint32_t index = XdrvMailbox.index -1; + uint32_t index = XdrvMailbox.index-1; //limit the payload AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); @@ -542,6 +571,7 @@ void CmndShutterPosition(void) if (XdrvMailbox.payload != -99) { //target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent; Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); + Shutter.accelerator[index] = Shutter.max_pwm_frequency / (Shutter.motordelay[index]>0 ? Shutter.motordelay[index] : 1); //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); } @@ -561,7 +591,7 @@ void CmndShutterPosition(void) } } if (Shutter.direction[index] != new_shutterdirection ) { - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); ShutterWaitForMotorStop(index); ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); @@ -617,11 +647,11 @@ void CmndShutterMotorDelay(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if (XdrvMailbox.data_len > 0) { - Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(20 * CharToFloat(XdrvMailbox.data)); + Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(steps_per_second * CharToFloat(XdrvMailbox.data)); ShutterInit(); } char time_chr[10]; - dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / 20, 2, time_chr); + dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / steps_per_second, 2, time_chr); ResponseCmndIdxChar(time_chr); } } @@ -660,8 +690,9 @@ void CmndShutterFrequency(void) if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { Shutter.max_pwm_frequency = XdrvMailbox.payload; if (shutters_present < 4) { - Settings.shuttercoeff[4][4] = Shutter.max_pwm_frequency; + Settings.shuttercoeff[4][3] = Shutter.max_pwm_frequency; } + ShutterInit(); ResponseCmndNumber(XdrvMailbox.payload); // ???? } else { ResponseCmndNumber(Shutter.max_pwm_frequency); @@ -707,8 +738,8 @@ void CmndShutterCalibration(void) // ???? messwerte[i] = field; } for (i=0 ; i < 5 ; i++) { - Settings.shuttercoeff[i][XdrvMailbox.index-1] = messwerte[i] * 1000 / messwerte[4]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index-1,Settings.shuttercoeff[i][XdrvMailbox.index-1], messwerte[i]); + Settings.shuttercoeff[i][XdrvMailbox.index -1] = messwerte[i] * 1000 / messwerte[4]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); } ShutterInit(); ResponseCmndIdxChar(XdrvMailbox.data); From f49b498c3902174e61580d88c3b777f84cf58f90 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Fri, 20 Dec 2019 12:40:40 +0100 Subject: [PATCH 111/559] fix #7213 DIV0 fix --- tasmota/xdrv_29_deepsleep.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_29_deepsleep.ino b/tasmota/xdrv_29_deepsleep.ino index c830a092e..78479bd5b 100644 --- a/tasmota/xdrv_29_deepsleep.ino +++ b/tasmota/xdrv_29_deepsleep.ino @@ -103,7 +103,7 @@ void DeepSleepPrepare(void) // if more then 10% timeslip = 0 == non valid wakeup; maybe manual timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; if (timeslip) { - RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / (Settings.deepsleep - (millis() / 1000)); + RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000),5)); // Avoid crazy numbers. Again maximum 10% deviation. RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); RtcSettings.nextwakeup += Settings.deepsleep; From f2209109e9e306c90b4b4a67df1e54e8ca9d481f Mon Sep 17 00:00:00 2001 From: stefanbode Date: Fri, 20 Dec 2019 12:45:29 +0100 Subject: [PATCH 112/559] Update xdrv_29_deepsleep.ino --- tasmota/xdrv_29_deepsleep.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_29_deepsleep.ino b/tasmota/xdrv_29_deepsleep.ino index 78479bd5b..f0a8de685 100644 --- a/tasmota/xdrv_29_deepsleep.ino +++ b/tasmota/xdrv_29_deepsleep.ino @@ -103,7 +103,7 @@ void DeepSleepPrepare(void) // if more then 10% timeslip = 0 == non valid wakeup; maybe manual timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; if (timeslip) { - RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000),5)); + RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5); // Avoid crazy numbers. Again maximum 10% deviation. RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); RtcSettings.nextwakeup += Settings.deepsleep; From 7459a8a4248c2991b6d39d066f1760d1dc66956c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 20 Dec 2019 15:12:44 +0100 Subject: [PATCH 113/559] Add restriction if fallback firmware is incompatible Add restriction if fallback firmware is incompatible with settings resulting in unreachable device --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 4 ++++ tasmota/language/bg-BG.h | 1 + tasmota/language/cs-CZ.h | 1 + tasmota/language/de-DE.h | 1 + tasmota/language/el-GR.h | 1 + tasmota/language/en-GB.h | 3 ++- tasmota/language/es-ES.h | 1 + tasmota/language/fr-FR.h | 1 + tasmota/language/he-HE.h | 1 + tasmota/language/hu-HU.h | 1 + tasmota/language/it-IT.h | 1 + tasmota/language/ko-KO.h | 1 + tasmota/language/nl-NL.h | 1 + tasmota/language/pl-PL.h | 1 + tasmota/language/pt-BR.h | 1 + tasmota/language/pt-PT.h | 1 + tasmota/language/ru-RU.h | 1 + tasmota/language/sk-SK.h | 1 + tasmota/language/sv-SE.h | 1 + tasmota/language/tr-TR.h | 1 + tasmota/language/uk-UK.h | 1 + tasmota/language/zh-CN.h | 1 + tasmota/language/zh-TW.h | 1 + tasmota/settings.ino | 38 +++++++++++++++++++++++++++++++++++ tasmota/support_tasmota.ino | 14 ++++++++++--- tasmota/tasmota.ino | 2 ++ tasmota/tasmota_version.h | 3 +++ tasmota/xdrv_01_webserver.ino | 10 +++++++-- 30 files changed, 91 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4360e8ee3..9224a1825 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -73,3 +73,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger - Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode - Add fallback support from version 8.x +- Add restriction if fallback firmware is incompatible with settings resulting in unreachable device diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 1bf38a0ec..2d5ae9077 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -7,6 +7,7 @@ - Add Zigbee send automatic ZigbeeRead after sending a command - Add Zigbee improving Occupancy:false detection for Aqara sensor - Add fallback support from version 8.x +- Add restriction if fallback firmware is incompatible with settings resulting in unreachable device ### 7.1.2.5 20191213 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index fed6930d7..1844dd44b 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -635,4 +635,8 @@ const char S_INFORMATION[] PROGMEM = D_INFORMATION; const char S_RESTART[] PROGMEM = D_RESTART; #endif // USE_WEBSERVER +const uint32_t MARKER_START = 0x5AA55AA5; +const uint32_t MARKER_END = 0xA55AA55A; +const uint32_t VERSION_MARKER[] PROGMEM = { MARKER_START, VERSION, MARKER_END }; + #endif // _I18N_H_ diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 1f18d8efb..251a840e8 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Грешка при изтриване на RF чипа" #define D_UPLOAD_ERR_12 "Грешка при записване в RF чипа" #define D_UPLOAD_ERR_13 "Грешка при декодиране на RF фърмуера" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Код на грешка при зареждането" #define D_ENTER_COMMAND "Въвеждане на команда" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 1d7c6f381..79ba068ab 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Chyba smazání RF chipu" #define D_UPLOAD_ERR_12 "Chyba při zápisu do RF chipu" #define D_UPLOAD_ERR_13 "Chyba dekódování RF firmwaru" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Chyba nahrávání" #define D_ENTER_COMMAND "Vlož příkaz" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 6569dd232..3cb7786af 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "RF Chip löschen fehlgeschlagen" #define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen" #define D_UPLOAD_ERR_13 "RF Firmware ungültig" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" #define D_ENTER_COMMAND "Befehl eingeben" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index f8b9c9614..3bea69d8f 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Αποτυχία σβησίματος στο RF chip" #define D_UPLOAD_ERR_12 "Αποτυχία εγγραφής στο RF chip" #define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Κωδικός λάθους στη μεταφόρτωση" #define D_ENTER_COMMAND "Εισαγωγή εντολής" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 257a34c86..d64632603 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.2.1.11 + * Updated until v8.0.0.0 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Failed to erase RF chip" #define D_UPLOAD_ERR_12 "Failed to write to RF chip" #define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Upload error code" #define D_ENTER_COMMAND "Enter command" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 7527bb77a..b0c9477de 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "No se pudo borrar en el chip RF" #define D_UPLOAD_ERR_12 "No se puedo escribir en el chip RF" #define D_UPLOAD_ERR_13 "No se pudo decodificar firmware RF" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Código de error de carga" #define D_ENTER_COMMAND "Ingresar comando" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index e107409e3..48576002e 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Erreur d'effacement du chip RF" #define D_UPLOAD_ERR_12 "Erreur d'accès en écriture au chip RF" #define D_UPLOAD_ERR_13 "Erreur de décodage du firmware RF" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement" #define D_ENTER_COMMAND "Saisir une commande" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index ac4dadb8e..1d4a1b549 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "נכשלה RF מחיקת שבב" #define D_UPLOAD_ERR_12 "נכשלה RF כתיבת שבב" #define D_UPLOAD_ERR_13 "נכשלה RF קידוד קושחת שבב" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "שגיאת קוד העלאה" #define D_ENTER_COMMAND "הקש פקודה" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 62806fa46..111558516 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Az RF chip törlése sikertelen" #define D_UPLOAD_ERR_12 "Az RF chip írása sikertelen" #define D_UPLOAD_ERR_13 "Az RF firmware dekódolása sikertelen" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Feltöltési hibakód" #define D_ENTER_COMMAND "Kérem a parancsot..." diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 0585c12d8..edf9b92c2 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Cancellazione fallita del chip RF" #define D_UPLOAD_ERR_12 "Scrittura fallita del chip RF" #define D_UPLOAD_ERR_13 "Decodifica fallita del firmware RF" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Codice errore invio" #define D_ENTER_COMMAND "Inserire comando" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index bff508474..4e20860f5 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "RF 칩 삭제 실패" #define D_UPLOAD_ERR_12 "RF 칩 쓰기 실패" #define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "업로드 에러 코드" #define D_ENTER_COMMAND "커맨드 입력" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 75d841ddc..e49b71ca1 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Wissen RF chip mislukt" #define D_UPLOAD_ERR_12 "Opwaarderen RF chip mislukt" #define D_UPLOAD_ERR_13 "Decoderen RF bestand mislukt" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Opwaardeer foutcode" #define D_ENTER_COMMAND "Geef opdracht" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 8f5af6813..a2aada42b 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Błąd kasowania układu RF" #define D_UPLOAD_ERR_12 "Błąd zapisu układu RF" #define D_UPLOAD_ERR_13 "Błąd dekodowania oprrogramowania układu RF" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Błąd wgrywania" #define D_ENTER_COMMAND "Wprowadź polecenie" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 0efa57789..ae808ef9e 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF" #define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF" #define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Código de erro do envio" #define D_ENTER_COMMAND "Inserir comando" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index a6299c0c8..e6684232c 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Falha ao apagar o chip de RF" #define D_UPLOAD_ERR_12 "Falha ao escrever no chip de RF" #define D_UPLOAD_ERR_13 "Falha ao descodificar o firmware RF" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Código de erro do envio" #define D_ENTER_COMMAND "Inserir comando" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 3bd788ede..cd5c072aa 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Failed to erase RF chip" #define D_UPLOAD_ERR_12 "Failed to write to RF chip" #define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Код ошибки загрузки" #define D_ENTER_COMMAND "Введите команду" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index a64e49e01..ef16212ca 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Chyba zmazania RF chipu" #define D_UPLOAD_ERR_12 "Chyba pri zápise do RF chipu" #define D_UPLOAD_ERR_13 "Chyba dekódovania RF firmwaru" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Chyba nahrávania" #define D_ENTER_COMMAND "Vlož príkaz" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index 51ffc2ae3..971ee42b1 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Misslyckades rensa RF chip" #define D_UPLOAD_ERR_12 "Misslyckades skriva till RF chip" #define D_UPLOAD_ERR_13 "Misslyckades avkoda RF firmware" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Uppladdningsfelkod" #define D_ENTER_COMMAND "Ange kommando" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 6bc48c40f..67400d1cc 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Failed to erase RF chip" #define D_UPLOAD_ERR_12 "Failed to write to RF chip" #define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Upload error code" #define D_ENTER_COMMAND "Komut girişi" diff --git a/tasmota/language/uk-UK.h b/tasmota/language/uk-UK.h index b4a314630..b81f30012 100644 --- a/tasmota/language/uk-UK.h +++ b/tasmota/language/uk-UK.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Помилка стирання чипу RF" #define D_UPLOAD_ERR_12 "Помилка запису чипу RF" #define D_UPLOAD_ERR_13 "Помилка розкодування прошивки RF" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "Код помилки завантаження" #define D_ENTER_COMMAND "Уведіть команду" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 21aa63be3..665f39fc3 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "擦除 RF 芯片失败" #define D_UPLOAD_ERR_12 "写入 RF 芯片失败" #define D_UPLOAD_ERR_13 "解码 RF 固件失败" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "上传错误代码" #define D_ENTER_COMMAND "输入命令" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 1d78f181e..6f56e03df 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -353,6 +353,7 @@ #define D_UPLOAD_ERR_11 "Failed to erase RF chip" #define D_UPLOAD_ERR_12 "Failed to write to RF chip" #define D_UPLOAD_ERR_13 "Failed to decode RF firmware" +#define D_UPLOAD_ERR_14 "Not compatible" #define D_UPLOAD_ERROR_CODE "上傳錯誤代碼" #define D_ENTER_COMMAND "輸入命令" diff --git a/tasmota/settings.ino b/tasmota/settings.ino index d921e4957..b572ca645 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -343,6 +343,44 @@ void SetFlashModeDout(void) delete[] _buffer; } +uint32_t OtaVersion(void) +{ + eboot_command ebcmd; + eboot_command_read(&ebcmd); + uint32_t start_address = ebcmd.args[0]; + uint32_t end_address = start_address + (ebcmd.args[2] & 0xFFFFF000) + FLASH_SECTOR_SIZE; + uint32_t* buffer = new uint32_t[FLASH_SECTOR_SIZE / 4]; + + uint32_t version[3] = { 0 }; + bool found = false; + for (uint32_t address = start_address; address < end_address; address = address + FLASH_SECTOR_SIZE) { + ESP.flashRead(address, (uint32_t*)buffer, FLASH_SECTOR_SIZE); + for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) { + version[0] = version[1]; + version[1] = version[2]; + version[2] = buffer[i]; + if ((version[0] == MARKER_START) && (version[2] == MARKER_END)) { + found = true; + break; + } + } + if (found) { break; } + } + delete[] buffer; + + if (!found) { version[1] = 0; } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: Version 0x%08X, Compatible 0x%08X"), version[1], VERSION_COMPATIBLE); + + return version[1]; +} + +void AbandonOta(void) +{ + uint32_t eboot_magic = 0; + ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic)); +} + void SettingsBufferFree(void) { if (settings_buffer != nullptr) { diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 0935d9a28..08b898efb 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -866,13 +866,21 @@ void Every250mSeconds(void) } if (90 == ota_state_flag) { // Allow MQTT to reconnect ota_state_flag = 0; + Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\"")); if (ota_result) { // SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 - Response_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); + if (OtaVersion() < VERSION_COMPATIBLE) { + AbandonOta(); + ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14)); + } else { + ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); + restart_flag = 2; + } } else { - Response_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); + ResponseAppend_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); } - restart_flag = 2; // Restart anyway to keep memory clean webserver + ResponseAppend_P(PSTR("\"}")); +// restart_flag = 2; // Restart anyway to keep memory clean webserver MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); } } diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 3b9e64a25..67be9d35f 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -334,6 +334,8 @@ void setup(void) AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); #endif // FIRMWARE_MINIMAL + memcpy_P(log_data, VERSION_MARKER, 1); // Dummy for compiler saving VERSION_MARKER + RtcInit(); #ifdef USE_ARDUINO_OTA diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index a083dad4b..84ff6d905 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -22,4 +22,7 @@ const uint32_t VERSION = 0x07010206; +// Lowest compatible version +const uint32_t VERSION_COMPATIBLE = 0x06000000; + #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 9c8131ad3..fe10e4cd3 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -511,6 +511,8 @@ const char kUploadErrors[] PROGMEM = D_UPLOAD_ERR_1 "|" D_UPLOAD_ERR_2 "|" D_UPLOAD_ERR_3 "|" D_UPLOAD_ERR_4 "|" D_UPLOAD_ERR_5 "|" D_UPLOAD_ERR_6 "|" D_UPLOAD_ERR_7 "|" D_UPLOAD_ERR_8 "|" D_UPLOAD_ERR_9 #ifdef USE_RF_FLASH "|" D_UPLOAD_ERR_10 "|" D_UPLOAD_ERR_11 "|" D_UPLOAD_ERR_12 "|" D_UPLOAD_ERR_13 +#else + "|" D_UPLOAD_ERR_14 #endif ; @@ -2137,12 +2139,11 @@ void HandleUploadDone(void) WSContentSendStyle(); WSContentSend_P(PSTR("
" D_UPLOAD " " D_FAILED "

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

"), WebColor(COL_TEXT_WARNING)); #ifdef USE_RF_FLASH if (Web.upload_error < 14) { #else - if (Web.upload_error < 10) { + if (Web.upload_error < 11) { #endif GetTextIndexed(error, sizeof(error), Web.upload_error -1, kUploadErrors); } else { @@ -2376,6 +2377,11 @@ void HandleUploadLoop(void) Web.upload_error = 6; // Upload failed. Enable logging 3 return; } + if (OtaVersion() < VERSION_COMPATIBLE) { + AbandonOta(); + Web.upload_error = 10; // Not compatible + return; + } } if (!Web.upload_error) { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD D_SUCCESSFUL " %u bytes. " D_RESTARTING), upload.totalSize); From 72849f672e907ca5ed43c697fb13cf57a065c1f5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 20 Dec 2019 15:48:40 +0100 Subject: [PATCH 114/559] Add support for DHT12 - Fix DeepSleep in case there is no wifi by Stefan Bode (#7213) - Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp --- BUILDS.md | 1 + RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 2 ++ tasmota/support_features.ino | 4 +++- tools/decode-status.py | 2 +- 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/BUILDS.md b/BUILDS.md index d21fd9f15..3b311a6eb 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -106,6 +106,7 @@ | USE_PAJ7620 | - | - | - | - | - | - | - | | USE_PCF8574 | - | - | - | - | - | - | - | | USE_HIH6 | - | - | - | - | x | - | - | +| USE_DHT12 | - | - | - | - | x | - | - | | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9224a1825..234258dab 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -58,6 +58,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649) - Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) - Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) +- Fix DeepSleep in case there is no wifi by Stefan Bode (#7213) - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) - Add command ``Sensor34 9 `` to set minimum delta to trigger JSON message by @tobox (#7188) - Add rule var ``%topic%`` by Adrian Scillato (#5522) @@ -74,3 +75,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode - Add fallback support from version 8.x - Add restriction if fallback firmware is incompatible with settings resulting in unreachable device +- Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 2d5ae9077..2b32857c2 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,10 +4,12 @@ - Change some more Settings locations freeing up space for future single char allowing variable length text - Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE +- Fix DeepSleep in case there is no wifi by Stefan Bode (#7213) - Add Zigbee send automatic ZigbeeRead after sending a command - Add Zigbee improving Occupancy:false detection for Aqara sensor - Add fallback support from version 8.x - Add restriction if fallback firmware is incompatible with settings resulting in unreachable device +- Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp ### 7.1.2.5 20191213 diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index be4c8f6a4..31428d03b 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -489,7 +489,9 @@ void GetFeatures(void) #ifdef USE_TSL2591 feature5 |= 0x00080000; #endif -// feature5 |= 0x00100000; +#ifdef USE_DHT12 + feature5 |= 0x00100000; +#endif // feature5 |= 0x00200000; // feature5 |= 0x00400000; // feature5 |= 0x00800000; diff --git a/tools/decode-status.py b/tools/decode-status.py index be79cf921..e6751ae92 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -187,7 +187,7 @@ a_features = [[ "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", - "","","","", + "USE_DHT12","","","", "","","","", "","","","" ]] From 18bc158bc84ca2d3c7c713e106dabf8329fa0920 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Fri, 20 Dec 2019 16:01:24 +0100 Subject: [PATCH 115/559] Fix Fade would ignore ``savedata 0`` and store to flash anyways (#7262) --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_04_light.ino | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 2b32857c2..f14c46658 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -10,6 +10,7 @@ - Add fallback support from version 8.x - Add restriction if fallback firmware is incompatible with settings resulting in unreachable device - Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp +- Fix Fade would ignore ``savedata 0`` and store to flash anyways (#7262) ### 7.1.2.5 20191213 diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 7f1e66fc6..6148a9aad 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1766,11 +1766,13 @@ void LightApplyFade(void) { // Note: Settings.light_speed is the number of half-seconds for a 100% fade, // i.e. light_speed=1 means 1024 steps in 10 ticks (500ms) Light.fade_duration = (distance * Settings.light_speed * 10) / 1024; - // Also postpone the save_data for the duration of the Fade (in seconds) - uint32_t delay_seconds = 1 + (Light.fade_duration + 19) / 20; // add one more second - // AddLog_P2(LOG_LEVEL_INFO, PSTR("delay_seconds %d, save_data_counter %d"), delay_seconds, save_data_counter); - if (save_data_counter < delay_seconds) { - save_data_counter = delay_seconds; // pospone + if (Settings.save_data) { + // Also postpone the save_data for the duration of the Fade (in seconds) + uint32_t delay_seconds = 1 + (Light.fade_duration + 19) / 20; // add one more second + // AddLog_P2(LOG_LEVEL_INFO, PSTR("delay_seconds %d, save_data_counter %d"), delay_seconds, save_data_counter); + if (save_data_counter < delay_seconds) { + save_data_counter = delay_seconds; // pospone + } } } else { // no fade needed, we keep the duration at zero, it will fallback directly to end of fade From 70a2c2cd20cb5a6003151f1cdf05a9232bd7a1da Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 20 Dec 2019 16:22:49 +0100 Subject: [PATCH 116/559] Fix Fade --- RELEASENOTES.md | 3 +++ tasmota/CHANGELOG.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 234258dab..56c4e2c07 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -14,6 +14,8 @@ See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-pat 4. Migrate to **Sonoff-Tasmota 6.x** 5. Migrate to **Tasmota 7.x** +Only this version will support fallback from version 8.x. + ## Supported Core versions This release will be supported from ESP8266/Arduino library Core version **2.6.1** due to reported security and stability issues on previous Core version. @@ -59,6 +61,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) - Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) - Fix DeepSleep in case there is no wifi by Stefan Bode (#7213) +- Fix Fade would ignore ``savedata 0`` and store to flash anyways (#7262) - Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) - Add command ``Sensor34 9 `` to set minimum delta to trigger JSON message by @tobox (#7188) - Add rule var ``%topic%`` by Adrian Scillato (#5522) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index f14c46658..d847aef5b 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,12 +5,12 @@ - Change some more Settings locations freeing up space for future single char allowing variable length text - Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE - Fix DeepSleep in case there is no wifi by Stefan Bode (#7213) +- Fix Fade would ignore ``savedata 0`` and store to flash anyways (#7262) - Add Zigbee send automatic ZigbeeRead after sending a command - Add Zigbee improving Occupancy:false detection for Aqara sensor - Add fallback support from version 8.x - Add restriction if fallback firmware is incompatible with settings resulting in unreachable device - Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp -- Fix Fade would ignore ``savedata 0`` and store to flash anyways (#7262) ### 7.1.2.5 20191213 From 74d0f55ce725f578de6ab27b0d0f4ff68eb9cb82 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 20 Dec 2019 16:36:08 +0100 Subject: [PATCH 117/559] Update languages --- tasmota/language/de-DE.h | 4 ++-- tasmota/language/nl-NL.h | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 3cb7786af..c61da0932 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.6.0.21 + * Updated until v8.0.0 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -353,7 +353,7 @@ #define D_UPLOAD_ERR_11 "RF Chip löschen fehlgeschlagen" #define D_UPLOAD_ERR_12 "RF Chip beschreiben fehlgeschlagen" #define D_UPLOAD_ERR_13 "RF Firmware ungültig" -#define D_UPLOAD_ERR_14 "Not compatible" +#define D_UPLOAD_ERR_14 "Nicht kompatibel" #define D_UPLOAD_ERROR_CODE "Upload Fehler Nummer" #define D_ENTER_COMMAND "Befehl eingeben" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index e49b71ca1..40222e65f 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v6.7.0 + * Updated until v8.0.0 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -353,7 +353,7 @@ #define D_UPLOAD_ERR_11 "Wissen RF chip mislukt" #define D_UPLOAD_ERR_12 "Opwaarderen RF chip mislukt" #define D_UPLOAD_ERR_13 "Decoderen RF bestand mislukt" -#define D_UPLOAD_ERR_14 "Not compatible" +#define D_UPLOAD_ERR_14 "Niet geschikt" #define D_UPLOAD_ERROR_CODE "Opwaardeer foutcode" #define D_ENTER_COMMAND "Geef opdracht" @@ -479,12 +479,12 @@ #define D_PARTICALS_BEYOND "Stofdeeltjes" // xsns_32_mpu6050.ino -#define D_AX_AXIS "Accel. X-Axis" -#define D_AY_AXIS "Accel. Y-Axis" -#define D_AZ_AXIS "Accel. Z-Axis" -#define D_GX_AXIS "Gyro X-Axis" -#define D_GY_AXIS "Gyro Y-Axis" -#define D_GZ_AXIS "Gyro Z-Axis" +#define D_AX_AXIS "Versn. X-as" +#define D_AY_AXIS "Versn. Y-as" +#define D_AZ_AXIS "Versn. Z-as" +#define D_GX_AXIS "Gyro X-as" +#define D_GY_AXIS "Gyro Y-as" +#define D_GZ_AXIS "Gyro Z-as" // xsns_34_hx711.ino #define D_HX_CAL_REMOVE "Verwijder gewicht" @@ -627,9 +627,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" // Units #define D_UNIT_AMPERE "A" From 7e24ed9c2cd6886c80dadb3a35b70faea849c73c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 20 Dec 2019 18:24:20 +0100 Subject: [PATCH 118/559] Fix error message --- tasmota/settings.h | 4 ++-- tasmota/settings.ino | 4 ++++ tasmota/xdrv_01_webserver.ino | 10 +++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index af74422df..8b7fe2822 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -91,7 +91,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t grouptopic_mode : 1; // bit 25 (v7.0.0.1) - SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1) uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled uint32_t slider_dimmer_stay_on : 1; // bit 27 (v7.0.0.6) - SetOption77 - Do not power off if slider moved to far left - uint32_t spare28 : 1; + uint32_t compatibility_check : 1; // bit 28 (v7.1.2.6) - SetOption78 - Disable OTA compatibility check uint32_t spare29 : 1; uint32_t shutter_mode : 1; // bit 30 (v6.6.0.14) - SetOption80 - Enable shutter support uint32_t pcf8574_ports_inverted : 1; // bit 31 (v6.6.0.14) - SetOption81 - Invert all ports on PCF8574 devices @@ -428,7 +428,7 @@ struct SYSCFG { unsigned long weight_calibration; // 7C4 unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight uint16_t web_refresh; // 7CC - char mems[MAX_RULE_MEMS][10]; // 7CE + char mems[MAX_RULE_MEMS][10]; // 7CE - Used by scripter as script_pram char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b diff --git a/tasmota/settings.ino b/tasmota/settings.ino index b572ca645..afbd7b223 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -345,6 +345,10 @@ void SetFlashModeDout(void) uint32_t OtaVersion(void) { + if (Settings.flag3.compatibility_check) { + return 0xFFFFFFFF; + } + eboot_command ebcmd; eboot_command_read(&ebcmd); uint32_t start_address = ebcmd.args[0]; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index fe10e4cd3..6b0edd8cb 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -511,9 +511,8 @@ const char kUploadErrors[] PROGMEM = D_UPLOAD_ERR_1 "|" D_UPLOAD_ERR_2 "|" D_UPLOAD_ERR_3 "|" D_UPLOAD_ERR_4 "|" D_UPLOAD_ERR_5 "|" D_UPLOAD_ERR_6 "|" D_UPLOAD_ERR_7 "|" D_UPLOAD_ERR_8 "|" D_UPLOAD_ERR_9 #ifdef USE_RF_FLASH "|" D_UPLOAD_ERR_10 "|" D_UPLOAD_ERR_11 "|" D_UPLOAD_ERR_12 "|" D_UPLOAD_ERR_13 -#else - "|" D_UPLOAD_ERR_14 #endif + "|" D_UPLOAD_ERR_14 ; const uint16_t DNS_PORT = 53; @@ -2141,9 +2140,10 @@ void HandleUploadDone(void) if (Web.upload_error) { WSContentSend_P(PSTR("%06x'>" D_FAILED "

"), WebColor(COL_TEXT_WARNING)); #ifdef USE_RF_FLASH - if (Web.upload_error < 14) { + if (Web.upload_error < 15) { #else - if (Web.upload_error < 11) { + if ((Web.upload_error < 10) || (14 == Web.upload_error)) { + if (14 == Web.upload_error) { Web.upload_error = 10; } #endif GetTextIndexed(error, sizeof(error), Web.upload_error -1, kUploadErrors); } else { @@ -2379,7 +2379,7 @@ void HandleUploadLoop(void) } if (OtaVersion() < VERSION_COMPATIBLE) { AbandonOta(); - Web.upload_error = 10; // Not compatible + Web.upload_error = 14; // Not compatible return; } } From 42f25b1cfb928671460d7dd3f4cd131c4521e516 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 20 Dec 2019 18:37:14 +0100 Subject: [PATCH 119/559] Update xdrv_01_webserver.ino --- tasmota/xdrv_01_webserver.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 6b0edd8cb..8aece2be8 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2238,7 +2238,7 @@ void HandleUploadLoop(void) Update.end(); // End esp8266 update session Web.upload_file_type = UPL_EFM8BB1; - Web.upload_error = SnfBrUpdateInit(); + Web.upload_error = SnfBrUpdateInit(); // 10, 11 if (Web.upload_error != 0) { return; } } else #endif // USE_RF_FLASH @@ -2246,7 +2246,7 @@ void HandleUploadLoop(void) if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO SLAVE hex file Update.end(); // End esp8266 update session Web.upload_file_type = UPL_TASMOTASLAVE; - Web.upload_error = TasmotaSlave_UpdateInit(); + Web.upload_error = TasmotaSlave_UpdateInit(); // 0 if (Web.upload_error != 0) { return; } } else #endif @@ -2281,13 +2281,13 @@ void HandleUploadLoop(void) free(efm8bb1_update); efm8bb1_update = nullptr; if (result != 0) { - Web.upload_error = abs(result); // 2 = Not enough space, 8 = File invalid + Web.upload_error = abs(result); // 2 = Not enough space, 8 = File invalid, 12, 13 return; } } ssize_t result = rf_search_and_write(upload.buf, upload.currentSize); if (result < 0) { - Web.upload_error = abs(result); + Web.upload_error = abs(result); // 8, 12, 13 return; } else if (result > 0) { if ((size_t)result > upload.currentSize) { From e85f1560a22c514ff945257891a4d7a7d642fed6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 21 Dec 2019 12:43:07 +0100 Subject: [PATCH 120/559] Refactor DHT12 sensor driver --- tasmota/xsns_58_dht12.ino | 136 +++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 62 deletions(-) diff --git a/tasmota/xsns_58_dht12.ino b/tasmota/xsns_58_dht12.ino index 1c60329b8..88dfd3598 100644 --- a/tasmota/xsns_58_dht12.ino +++ b/tasmota/xsns_58_dht12.ino @@ -28,82 +28,94 @@ #define XSNS_58 58 #define XI2C_41 41 // See I2CDEVICES.md -#define DHT12_ADDR (uint8_t) 0x5C +#define DHT12_ADDR 0x5C -char dht12_name[] = "DHT12-0x00"; -uint8_t dht12_count = 0; -float dht12_temperature = NAN; -float dht12_humidity = NAN; +struct DHT12 { + float temperature = NAN; + float humidity = NAN; + uint8_t valid = 0; + uint8_t count = 0; + char name[6] = "DHT12"; +} Dht12; bool Dht12Read(void) { - Wire.beginTransmission(DHT12_ADDR); - Wire.write(0); - if (Wire.endTransmission() != 0) { - return false; - } - delay(50); - Wire.requestFrom(DHT12_ADDR, (uint8_t) 5); - delay(5); - uint8_t humidity = Wire.read(); - uint8_t humidityTenth = Wire.read(); - uint8_t temp = Wire.read(); - uint8_t tempTenth = Wire.read(); - uint8_t checksum = Wire.read(); - dht12_humidity = (float) humidity + (float) humidityTenth/(float) 10.0; - dht12_temperature = (float) temp + (float) tempTenth/(float) 10.0; - return (!isnan(dht12_temperature) && !isnan(dht12_humidity)); + if (Dht12.valid) { Dht12.valid--; } + + Wire.beginTransmission(DHT12_ADDR); + Wire.write(0); + if (Wire.endTransmission() != 0) { return false; } + + delay(50); + + Wire.requestFrom(DHT12_ADDR, 5); + delay(5); + uint8_t humidity = Wire.read(); + uint8_t humidityTenth = Wire.read(); + uint8_t temp = Wire.read(); + uint8_t tempTenth = Wire.read(); + uint8_t checksum = Wire.read(); + + Dht12.humidity = ConvertHumidity( (float) humidity + (float) humidityTenth/(float) 10.0 ); + Dht12.temperature = ConvertTemp( (float) temp + (float) tempTenth/(float) 10.0 ); + + if (isnan(Dht12.temperature) || isnan(Dht12.humidity)) { return false; } + + Dht12.valid = SENSOR_MAX_MISS; + return true; } +/********************************************************************************************/ + void Dht12Detect(void) { - if (Dht12Read()) { - snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, dht12_name, DHT12_ADDR); - AddLog(LOG_LEVEL_DEBUG); - snprintf_P(dht12_name, sizeof(dht12_name), PSTR("%s%c0x%02X"), "DHT12", IndexSeparator(), DHT12_ADDR); - dht12_count = 1; - } + if (I2cActive(DHT12_ADDR)) { return; } + + if (Dht12Read()) { + I2cSetActiveFound(DHT12_ADDR, Dht12.name); + Dht12.count = 1; + } } -void Dht12Show(bool json) +void Dht12EverySecond(void) { - if (dht12_count > 0) - { - char temperature[33]; - dtostrfd(dht12_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(dht12_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) - { - ResponseAppend_P(JSON_SNS_TEMPHUM, dht12_name, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period)) - { - DomoticzTempHumSensor(temperature, humidity); - } -#endif // USE_DOMOTICZ - -#ifdef USE_KNX - if (0 == tele_period) - { - KnxSensor(KNX_TEMPERATURE, dht12_temperature); - KnxSensor(KNX_HUMIDITY, dht12_humidity); - } -#endif // USE_KNX - -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_TEMP, dht12_name, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, dht12_name, humidity); -#endif // USE_WEBSERVER + if (uptime &1) { + // DHT12: 55mS + if (!Dht12Read()) { + AddLogMissed(Dht12.name, Dht12.valid); } } } +void Dht12Show(bool json) +{ + if (Dht12.valid) { + char temperature[33]; + dtostrfd(Dht12.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht12.humidity, Settings.flag2.humidity_resolution, humidity); + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht12.name, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif // USE_DOMOTICZ +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, Dht12.temperature); + KnxSensor(KNX_HUMIDITY, Dht12.humidity); + } +#endif // USE_KNX +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht12.name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht12.name, humidity); +#endif // USE_WEBSERVER + } + } +} /*********************************************************************************************\ * Interface @@ -118,10 +130,10 @@ bool Xsns58(uint8_t function) if (FUNC_INIT == function) { Dht12Detect(); } - else if (dht12_count > 0) { + else if (Dht12.count) { switch (function) { case FUNC_EVERY_SECOND: - Dht12Read(); + Dht12EverySecond(); break; case FUNC_JSON_APPEND: Dht12Show(1); From d2ebefbb16405c53dd07b5a82ea27b81c8146ec2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 21 Dec 2019 13:45:26 +0100 Subject: [PATCH 121/559] Bump version to 7.2.0.1 --- README.md | 2 +- RELEASENOTES.md | 2 +- tasmota/CHANGELOG.md | 10 ++++++++-- tasmota/tasmota_version.h | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index acb6430d5..9a9ff0e1c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v7.1.2.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v7.2.x.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 56c4e2c07..f3fff8860 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -49,7 +49,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 7.1.2.6 +### Version 7.2.0 Constance - Change Exception reporting removing exception details from ``Status 1`` and consolidated in ``Status 12`` if available - Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index d847aef5b..e290e1909 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,13 @@ ## Unreleased (development) +### 7.2.0.1 20191221 + +## Released + +### 7.2.0 20191221 + +- Release + ### 7.1.2.6 20191214 - Change some more Settings locations freeing up space for future single char allowing variable length text @@ -51,8 +59,6 @@ - Add experimental support for stepper motor shutter control by Stefan Bode - Add optional USE_MQTT_TLS to tasmota-minimal.bin by Bohdan Kmit (#7115) -## Released - ### 7.1.2 20191206 - Maintenance Release diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 84ff6d905..27480159d 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010206; +const uint32_t VERSION = 0x07020001; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x06000000; From f55e02e80041e58159c6480dde62bfe0d5a77ace Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 21 Dec 2019 15:37:36 +0100 Subject: [PATCH 122/559] Bump version to 8.0.0.1 Change Settings text handling allowing variable length text within a total text pool of 699 characters --- RELEASENOTES.md | 36 +---- tasmota/CHANGELOG.md | 4 +- tasmota/settings.h | 9 -- tasmota/settings.ino | 258 ++++++++++++--------------------- tasmota/support_statistics.ino | 37 +---- tasmota/tasmota_version.h | 4 +- 6 files changed, 100 insertions(+), 248 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f3fff8860..bf21cf32b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,8 +2,6 @@ # RELEASE NOTES -### Sonoff-Tasmota is now Tasmota - ## Migration Information See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-path) for instructions how to migrate to a major version. Pay attention to the following version breaks due to dynamic settings updates: @@ -13,8 +11,7 @@ See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-pat 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** 5. Migrate to **Tasmota 7.x** - -Only this version will support fallback from version 8.x. +6. Migrate to **Tasmota 8.x** ## Supported Core versions @@ -49,33 +46,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 7.2.0 Constance +### Version 8.0.0.1 -- Change Exception reporting removing exception details from ``Status 1`` and consolidated in ``Status 12`` if available -- Change HTTP CORS from command ``SetOption73 0/1`` to ``Cors `` allowing user control of specific CORS domain by Shantur Rathore (#7066) -- Change GUI Shutter button text to Up and Down Arrows based on PR by Xavier Muller (#7166) -- Change amount of supported DHT sensors from 3 to 4 by Xavier Muller (#7167) -- Change some Settings locations freeing up space for future single char allowing variable length text -- Change tasmota-basic.bin and FIRMWARE_BASIC to tasmota-lite.bin and FIRMWARE_LITE -- Fix flashing H801 led at boot by Stefan Hadinger (#7165, #649) -- Fix duplicated ``Backlog`` when using Event inside a Backlog by Adrian Scillato (#7178, #7147) -- Fix Gui Timer when using a negative zero offset of -00:00 by Peter Ooms (#7174) -- Fix DeepSleep in case there is no wifi by Stefan Bode (#7213) -- Fix Fade would ignore ``savedata 0`` and store to flash anyways (#7262) -- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config based in PR by Luis Teixeira (#7108) -- Add command ``Sensor34 9 `` to set minimum delta to trigger JSON message by @tobox (#7188) -- Add rule var ``%topic%`` by Adrian Scillato (#5522) -- Add rule triggers ``tele-wifi1#xxx`` by Adrian Scillato (#7093) -- Add SML bus decoder syntax support for byte order by Gerhard Mutz (#7112) -- Add experimental support for stepper motor shutter control by Stefan Bode -- Add optional USE_MQTT_TLS to tasmota-minimal.bin by Bohdan Kmit (#7115) -- Add save call stack in RTC memory in case of crash, command ``Status 12`` to dump the stack by Stefan Hadinger -- Add Home Assistant force update by Frederico Leoni (#7140, #7074) -- Add Wifi Signal Strength in dBm in addition to RSSI Wifi Experience by Andreas Schultz (#7145) -- Add Yaw, Pitch and Roll support for MPU6050 by Philip Barclay (#7058) -- Add reporting of raw weight to JSON from HX711 to overcome auto-tare functionality by @tobox (#7171) -- Add Zigbee support for Xiaomi Aqara Vibration Sensor and Presence Sensor by Stefan Hadinger -- Add Shutter functions ramp up/down and MQTT reporting by Stefan Bode -- Add fallback support from version 8.x -- Add restriction if fallback firmware is incompatible with settings resulting in unreachable device -- Add support for DHT12 Temperature and Humidity sensor by Stefan Oskamp +- Change Settings text handling allowing variable length text within a total text pool of 699 characters diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e290e1909..e8b70c0cd 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,6 +1,8 @@ ## Unreleased (development) -### 7.2.0.1 20191221 +### 8.0.0.1 20191221 + +- Change Settings text handling allowing variable length text within a total text pool of 699 characters ## Released diff --git a/tasmota/settings.h b/tasmota/settings.h index 8b7fe2822..0b3990578 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -231,13 +231,6 @@ typedef struct { const uint8_t MAX_TUYA_FUNCTIONS = 16; -/* -struct SYSCFG { - unsigned long cfg_holder; // 000 Pre v6 header - unsigned long save_flag; // 004 - unsigned long version; // 008 - unsigned long bootcount; // 00C -*/ struct SYSCFG { uint16_t cfg_holder; // 000 v6 header uint16_t cfg_size; // 002 @@ -274,8 +267,6 @@ struct SYSCFG { uint8_t ex_free_1d6[10]; // 1D6 - // End of single char array of 456 chars max (phase 3) - SysBitfield4 ex_flag4; // 1E0 uint8_t ex_serial_config; // 1E4 uint8_t ex_wifi_output_power; // 1E5 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index afbd7b223..9a0ea44f1 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -488,10 +488,7 @@ void UpdateQuickPowerCycle(bool update) * Config Settings.text char array support \*********************************************************************************************/ -char aws_mqtt_host[66]; -char aws_mqtt_user[1] { 0 }; - -const uint32_t settings_text_size = 457; // Settings.flag4 (1E0) - Settings.ota_url (017) +const uint32_t settings_text_size = 699; // Settings.flag4 (2D2) - Settings.ota_url (017) uint32_t GetSettingsTextLen(void) { @@ -513,60 +510,43 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me) char replace[replace_len +1]; memcpy(replace, replace_me, sizeof(replace)); - uint32_t idx = 0; - switch (index) { - case SET_OTAURL: strlcpy(Settings.ota_url, replace, sizeof(Settings.ota_url)); break; - case SET_MQTTPREFIX3: idx++; - case SET_MQTTPREFIX2: idx++; - case SET_MQTTPREFIX1: strlcpy(Settings.mqtt_prefix[idx], replace, sizeof(Settings.mqtt_prefix[idx])); break; - case SET_STASSID2: idx++; - case SET_STASSID1: strlcpy(Settings.sta_ssid[idx], replace, sizeof(Settings.sta_ssid[idx])); break; - case SET_STAPWD2: idx++; - case SET_STAPWD1: strlcpy(Settings.sta_pwd[idx], replace, sizeof(Settings.sta_pwd[idx])); break; - case SET_HOSTNAME: strlcpy(Settings.hostname, replace, sizeof(Settings.hostname)); break; - case SET_SYSLOG_HOST: strlcpy(Settings.syslog_host, replace, sizeof(Settings.syslog_host)); break; - case SET_WEBPWD: strlcpy(Settings.web_password, replace, sizeof(Settings.web_password)); break; -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - case SET_MQTT_HOST: - if (strlen(replace) <= sizeof(Settings.mqtt_host)) { - strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); - Settings.mqtt_user[0] = 0; - } else { - // need to split in mqtt_user first then mqtt_host - strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); - strlcpy(Settings.mqtt_host, &replace[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); - } - break; - case SET_MQTT_USER: break; -#else - case SET_MQTT_HOST: strlcpy(Settings.mqtt_host, replace, sizeof(Settings.mqtt_host)); break; - case SET_MQTT_USER: strlcpy(Settings.mqtt_user, replace, sizeof(Settings.mqtt_user)); break; -#endif - case SET_MQTT_CLIENT: strlcpy(Settings.mqtt_client, replace, sizeof(Settings.mqtt_client)); break; - case SET_MQTT_PWD: strlcpy(Settings.mqtt_pwd, replace, sizeof(Settings.mqtt_pwd)); break; - case SET_MQTT_FULLTOPIC: strlcpy(Settings.mqtt_fulltopic, replace, sizeof(Settings.mqtt_fulltopic)); break; - case SET_MQTT_TOPIC: strlcpy(Settings.mqtt_topic, replace, sizeof(Settings.mqtt_topic)); break; - case SET_MQTT_BUTTON_TOPIC: strlcpy(Settings.button_topic, replace, sizeof(Settings.button_topic)); break; - case SET_MQTT_SWITCH_TOPIC: strlcpy(Settings.switch_topic, replace, sizeof(Settings.switch_topic)); break; - case SET_MQTT_GRP_TOPIC: strlcpy(Settings.mqtt_grptopic, replace, sizeof(Settings.mqtt_grptopic)); break; - case SET_STATE_TXT4: idx++; - case SET_STATE_TXT3: idx++; - case SET_STATE_TXT2: idx++; - case SET_STATE_TXT1: strlcpy(Settings.state_text[idx], replace, sizeof(Settings.state_text[idx])); break; - case SET_NTPSERVER3: idx++; - case SET_NTPSERVER2: idx++; - case SET_NTPSERVER1: strlcpy(Settings.ntp_server[idx], replace, sizeof(Settings.ntp_server[idx])); break; - case SET_MEM5: idx++; - case SET_MEM4: idx++; - case SET_MEM3: idx++; - case SET_MEM2: idx++; - case SET_MEM1: strlcpy(Settings.mems[idx], replace, sizeof(Settings.mems[idx])); break; - case SET_CORS: strlcpy(Settings.cors_domain, replace, sizeof(Settings.cors_domain)); break; - case SET_FRIENDLYNAME4: idx++; - case SET_FRIENDLYNAME3: idx++; - case SET_FRIENDLYNAME2: idx++; - case SET_FRIENDLYNAME1: strlcpy(Settings.friendlyname[idx], replace, sizeof(Settings.friendlyname[idx])); break; + uint32_t start_pos = 0; + uint32_t end_pos = 0; + char* position = Settings.ota_url; + for (uint32_t size = 0; size < SET_MAX; size++) { + while (*position++ != '\0') { } + if (1 == index) { + start_pos = position - Settings.ota_url; + } + else if (0 == index) { + end_pos = position - Settings.ota_url -1; + } + index--; } + uint32_t char_len = position - Settings.ota_url; + + uint32_t current_len = end_pos - start_pos; + int diff = replace_len - current_len; + +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TST: start %d, end %d, len %d, current %d, replace %d, diff %d"), +// start_pos, end_pos, char_len, current_len, replace_len, diff); + + int too_long = (char_len + diff) - settings_text_size; + if (too_long > 0) { +// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text too long by %d char(s)"), too_long); + return false; // Replace text too long + } + + if (diff != 0) { + // Shift Settings.text up or down + memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos); + } + // Replace text + memmove_P(Settings.ota_url + start_pos, replace, replace_len); + // Fill for future use + memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d"), GetSettingsTextLen(), settings_text_size); return true; } @@ -578,61 +558,9 @@ char* SettingsText(uint32_t index) } char* position = Settings.ota_url; - - if (Settings.version < 0x08000000) { - uint32_t idx = 0; - switch (index) { - case SET_MQTTPREFIX3: idx++; - case SET_MQTTPREFIX2: idx++; - case SET_MQTTPREFIX1: position = Settings.mqtt_prefix[idx]; break; - case SET_STASSID2: idx++; - case SET_STASSID1: position = Settings.sta_ssid[idx]; break; - case SET_STAPWD2: idx++; - case SET_STAPWD1: position = Settings.sta_pwd[idx]; break; - case SET_HOSTNAME: position = Settings.hostname; break; - case SET_SYSLOG_HOST: position = Settings.syslog_host; break; - case SET_WEBPWD: position = Settings.web_password; break; -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - case SET_MQTT_HOST: - snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), Settings.mqtt_user, Settings.mqtt_host); - position = aws_mqtt_host; break; - case SET_MQTT_USER: position = aws_mqtt_user; break; -#else - case SET_MQTT_HOST: position = Settings.mqtt_host; break; - case SET_MQTT_USER: position = Settings.mqtt_user; break; -#endif - case SET_MQTT_CLIENT: position = Settings.mqtt_client; break; - case SET_MQTT_PWD: position = Settings.mqtt_pwd; break; - case SET_MQTT_FULLTOPIC: position = Settings.mqtt_fulltopic; break; - case SET_MQTT_TOPIC: position = Settings.mqtt_topic; break; - case SET_MQTT_BUTTON_TOPIC: position = Settings.button_topic; break; - case SET_MQTT_SWITCH_TOPIC: position = Settings.switch_topic; break; - case SET_MQTT_GRP_TOPIC: position = Settings.mqtt_grptopic; break; - case SET_STATE_TXT4: idx++; - case SET_STATE_TXT3: idx++; - case SET_STATE_TXT2: idx++; - case SET_STATE_TXT1: position = Settings.state_text[idx]; break; - case SET_NTPSERVER3: idx++; - case SET_NTPSERVER2: idx++; - case SET_NTPSERVER1: position = Settings.ntp_server[idx]; break; - case SET_MEM5: idx++; - case SET_MEM4: idx++; - case SET_MEM3: idx++; - case SET_MEM2: idx++; - case SET_MEM1: position = Settings.mems[idx]; break; - case SET_CORS: position = Settings.cors_domain; break; - case SET_FRIENDLYNAME4: idx++; - case SET_FRIENDLYNAME3: idx++; - case SET_FRIENDLYNAME2: idx++; - case SET_FRIENDLYNAME1: position = Settings.friendlyname[idx]; break; - } - - } else { - for (;index > 0; index--) { - while (*position++ != '\0') { } - } + for (;index > 0; index--) { + while (*position++ != '\0') { } } - return position; } @@ -1132,10 +1060,6 @@ void SettingsDefaultSet2(void) memset(&Settings.monitors, 0xFF, 20); // Enable all possible monitors, displays and sensors SettingsEnableAllI2cDrivers(); - - if (VERSION < 0x08000000) { - SettingsBackwardCompat(); - } } /********************************************************************************************/ @@ -1175,17 +1099,6 @@ void SettingsEnableAllI2cDrivers(void) Settings.i2c_drivers[2] = 0xFFFFFFFF; } -void SettingsBackwardCompat(void) -{ - Settings.ex_seriallog_level = Settings.seriallog_level; // 09E <- 452 - Settings.ex_sta_config = Settings.sta_config; // 09F <- EC7 - Settings.ex_sta_active = Settings.sta_active; // 0A0 <- EC8 - memcpy((char*)&Settings.ex_rule_stop, (char*)&Settings.rule_stop, 47); // 1A7 <- EC9 - Settings.ex_flag4 = Settings.flag4; // 1E0 <- EF8 - Settings.ex_mqtt_port = Settings.mqtt_port; // 20A <- EFC - memcpy((char*)&Settings.ex_serial_config, (char*)&Settings.serial_config, 5); // 1E4 <- EFE -} - /********************************************************************************************/ void SettingsDelta(void) @@ -1405,46 +1318,26 @@ void SettingsDelta(void) memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); // 1E4 -> EFE } - if ((VERSION < 0x08000000) && (Settings.version >= 0x08000000)) { - SettingsUpdateText(SET_WEBPWD, SettingsText(SET_WEBPWD)); - SettingsUpdateText(SET_CORS, SettingsText(SET_CORS)); - SettingsUpdateText(SET_MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); - SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, SettingsText(SET_MQTT_SWITCH_TOPIC)); - SettingsUpdateText(SET_STATE_TXT1, SettingsText(SET_STATE_TXT1)); - SettingsUpdateText(SET_STATE_TXT2, SettingsText(SET_STATE_TXT2)); - SettingsUpdateText(SET_STATE_TXT3, SettingsText(SET_STATE_TXT3)); - SettingsUpdateText(SET_STATE_TXT4, SettingsText(SET_STATE_TXT4)); - SettingsUpdateText(SET_NTPSERVER1, SettingsText(SET_NTPSERVER1)); - SettingsUpdateText(SET_NTPSERVER2, SettingsText(SET_NTPSERVER2)); - SettingsUpdateText(SET_NTPSERVER3, SettingsText(SET_NTPSERVER3)); - SettingsUpdateText(SET_MEM1, SettingsText(SET_MEM1)); - SettingsUpdateText(SET_MEM2, SettingsText(SET_MEM2)); - SettingsUpdateText(SET_MEM3, SettingsText(SET_MEM3)); - SettingsUpdateText(SET_MEM4, SettingsText(SET_MEM4)); - SettingsUpdateText(SET_MEM5, SettingsText(SET_MEM5)); - SettingsUpdateText(SET_FRIENDLYNAME1, SettingsText(SET_FRIENDLYNAME1)); - SettingsUpdateText(SET_FRIENDLYNAME2, SettingsText(SET_FRIENDLYNAME2)); - SettingsUpdateText(SET_FRIENDLYNAME3, SettingsText(SET_FRIENDLYNAME3)); - SettingsUpdateText(SET_FRIENDLYNAME4, SettingsText(SET_FRIENDLYNAME4)); - - char temp[strlen(SettingsText(SET_OTAURL)) +1]; strncpy(temp, SettingsText(SET_OTAURL), sizeof(temp)); - char temp21[strlen(SettingsText(SET_MQTTPREFIX1)) +1]; strncpy(temp21, SettingsText(SET_MQTTPREFIX1), sizeof(temp21)); - char temp22[strlen(SettingsText(SET_MQTTPREFIX2)) +1]; strncpy(temp22, SettingsText(SET_MQTTPREFIX2), sizeof(temp22)); - char temp23[strlen(SettingsText(SET_MQTTPREFIX3)) +1]; strncpy(temp23, SettingsText(SET_MQTTPREFIX3), sizeof(temp23)); - char temp31[strlen(SettingsText(SET_STASSID1)) +1]; strncpy(temp31, SettingsText(SET_STASSID1), sizeof(temp31)); - char temp32[strlen(SettingsText(SET_STASSID2)) +1]; strncpy(temp32, SettingsText(SET_STASSID2), sizeof(temp32)); - char temp41[strlen(SettingsText(SET_STAPWD1)) +1]; strncpy(temp41, SettingsText(SET_STAPWD1), sizeof(temp41)); - char temp42[strlen(SettingsText(SET_STAPWD2)) +1]; strncpy(temp42, SettingsText(SET_STAPWD2), sizeof(temp42)); - char temp5[strlen(SettingsText(SET_HOSTNAME)) +1]; strncpy(temp5, SettingsText(SET_HOSTNAME), sizeof(temp5)); - char temp6[strlen(SettingsText(SET_SYSLOG_HOST)) +1]; strncpy(temp6, SettingsText(SET_SYSLOG_HOST), sizeof(temp6)); - char temp7[strlen(SettingsText(SET_MQTT_HOST)) +1]; strncpy(temp7, SettingsText(SET_MQTT_HOST), sizeof(temp7)); - char temp8[strlen(SettingsText(SET_MQTT_CLIENT)) +1]; strncpy(temp8, SettingsText(SET_MQTT_CLIENT), sizeof(temp8)); - char temp9[strlen(SettingsText(SET_MQTT_USER)) +1]; strncpy(temp9, SettingsText(SET_MQTT_USER), sizeof(temp9)); - char temp10[strlen(SettingsText(SET_MQTT_PWD)) +1]; strncpy(temp10, SettingsText(SET_MQTT_PWD), sizeof(temp10)); - char temp11[strlen(SettingsText(SET_MQTT_TOPIC)) +1]; strncpy(temp11, SettingsText(SET_MQTT_TOPIC), sizeof(temp11)); - char temp12[strlen(SettingsText(SET_MQTT_BUTTON_TOPIC)) +1]; strncpy(temp12, SettingsText(SET_MQTT_BUTTON_TOPIC), sizeof(temp12)); - char temp13[strlen(SettingsText(SET_MQTT_GRP_TOPIC)) +1]; strncpy(temp13, SettingsText(SET_MQTT_GRP_TOPIC), sizeof(temp13)); + if (Settings.version < 0x08000000) { + char temp[strlen(Settings.ota_url) +1]; strncpy(temp, Settings.ota_url, sizeof(temp)); + char temp21[strlen(Settings.mqtt_prefix[0]) +1]; strncpy(temp21, Settings.mqtt_prefix[0], sizeof(temp21)); + char temp22[strlen(Settings.mqtt_prefix[1]) +1]; strncpy(temp22, Settings.mqtt_prefix[1], sizeof(temp22)); + char temp23[strlen(Settings.mqtt_prefix[2]) +1]; strncpy(temp23, Settings.mqtt_prefix[2], sizeof(temp23)); + char temp31[strlen(Settings.sta_ssid[0]) +1]; strncpy(temp31, Settings.sta_ssid[0], sizeof(temp31)); + char temp32[strlen(Settings.sta_ssid[1]) +1]; strncpy(temp32, Settings.sta_ssid[1], sizeof(temp32)); + char temp41[strlen(Settings.sta_pwd[0]) +1]; strncpy(temp41, Settings.sta_pwd[0], sizeof(temp41)); + char temp42[strlen(Settings.sta_pwd[1]) +1]; strncpy(temp42, Settings.sta_pwd[1], sizeof(temp42)); + char temp5[strlen(Settings.hostname) +1]; strncpy(temp5, Settings.hostname, sizeof(temp5)); + char temp6[strlen(Settings.syslog_host) +1]; strncpy(temp6, Settings.syslog_host, sizeof(temp6)); + char temp7[strlen(Settings.mqtt_host) +1]; strncpy(temp7, Settings.mqtt_host, sizeof(temp7)); + char temp8[strlen(Settings.mqtt_client) +1]; strncpy(temp8, Settings.mqtt_client, sizeof(temp8)); + char temp9[strlen(Settings.mqtt_user) +1]; strncpy(temp9, Settings.mqtt_user, sizeof(temp9)); + char temp10[strlen(Settings.mqtt_pwd) +1]; strncpy(temp10, Settings.mqtt_pwd, sizeof(temp10)); + char temp11[strlen(Settings.mqtt_topic) +1]; strncpy(temp11, Settings.mqtt_topic, sizeof(temp11)); + char temp12[strlen(Settings.button_topic) +1]; strncpy(temp12, Settings.button_topic, sizeof(temp12)); + char temp13[strlen(Settings.mqtt_grptopic) +1]; strncpy(temp13, Settings.mqtt_grptopic, sizeof(temp13)); + memset(Settings.ota_url, 0x00, settings_text_size); SettingsUpdateText(SET_OTAURL, temp); SettingsUpdateText(SET_MQTTPREFIX1, temp21); SettingsUpdateText(SET_MQTTPREFIX2, temp22); @@ -1455,15 +1348,46 @@ void SettingsDelta(void) SettingsUpdateText(SET_STAPWD2, temp42); SettingsUpdateText(SET_HOSTNAME, temp5); SettingsUpdateText(SET_SYSLOG_HOST, temp6); +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + if (!strlen(Settings.mqtt_user)) { + SettingsUpdateText(SET_MQTT_HOST, temp7); + SettingsUpdateText(SET_MQTT_USER, temp9); + } else { + char aws_mqtt_host[66]; + snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), temp9, temp7); + SettingsUpdateText(SET_MQTT_HOST, mqtt_host); + SettingsUpdateText(SET_MQTT_USER, ""); + } +#else SettingsUpdateText(SET_MQTT_HOST, temp7); - SettingsUpdateText(SET_MQTT_CLIENT, temp8); SettingsUpdateText(SET_MQTT_USER, temp9); +#endif + SettingsUpdateText(SET_MQTT_CLIENT, temp8); SettingsUpdateText(SET_MQTT_PWD, temp10); SettingsUpdateText(SET_MQTT_TOPIC, temp11); SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); - SettingsBackwardCompat(); + SettingsUpdateText(SET_WEBPWD, Settings.web_password); + SettingsUpdateText(SET_CORS, Settings.cors_domain); + SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.mqtt_fulltopic); + SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.switch_topic); + SettingsUpdateText(SET_STATE_TXT1, Settings.state_text[0]); + SettingsUpdateText(SET_STATE_TXT2, Settings.state_text[1]); + SettingsUpdateText(SET_STATE_TXT3, Settings.state_text[2]); + SettingsUpdateText(SET_STATE_TXT4, Settings.state_text[3]); + SettingsUpdateText(SET_NTPSERVER1, Settings.ntp_server[0]); + SettingsUpdateText(SET_NTPSERVER2, Settings.ntp_server[1]); + SettingsUpdateText(SET_NTPSERVER3, Settings.ntp_server[2]); + SettingsUpdateText(SET_MEM1, Settings.mems[0]); + SettingsUpdateText(SET_MEM2, Settings.mems[1]); + SettingsUpdateText(SET_MEM3, Settings.mems[2]); + SettingsUpdateText(SET_MEM4, Settings.mems[3]); + SettingsUpdateText(SET_MEM5, Settings.mems[4]); + SettingsUpdateText(SET_FRIENDLYNAME1, Settings.friendlyname[0]); + SettingsUpdateText(SET_FRIENDLYNAME2, Settings.friendlyname[1]); + SettingsUpdateText(SET_FRIENDLYNAME3, Settings.friendlyname[2]); + SettingsUpdateText(SET_FRIENDLYNAME4, Settings.friendlyname[3]); } Settings.version = VERSION; diff --git a/tasmota/support_statistics.ino b/tasmota/support_statistics.ino index b8f65bd20..1907b1edc 100644 --- a/tasmota/support_statistics.ino +++ b/tasmota/support_statistics.ino @@ -27,42 +27,7 @@ String GetStatistics(void) { char data[40]; - - if (Settings.version < 0x08000000) { - uint32_t str_len = 0; - for (uint32_t i = 0; i < 2; i++) { - str_len += strlen(Settings.sta_ssid[i]); - str_len += strlen(Settings.sta_pwd[i]); - } - for (uint32_t i = 0; i < 3; i++) { - str_len += strlen(Settings.mqtt_prefix[i]); - str_len += strlen(Settings.ntp_server[i]); - } - for (uint32_t i = 0; i < 4; i++) { - str_len += strlen(Settings.state_text[i]); - str_len += strlen(Settings.friendlyname[i]); - } - for (uint32_t i = 0; i < MAX_RULE_MEMS; i++) { - str_len += strlen(Settings.mems[i]); - } - str_len += strlen(Settings.ota_url); - str_len += strlen(Settings.hostname); - str_len += strlen(Settings.syslog_host); - str_len += strlen(Settings.mqtt_host); - str_len += strlen(Settings.mqtt_client); - str_len += strlen(Settings.mqtt_user); - str_len += strlen(Settings.mqtt_pwd); - str_len += strlen(Settings.mqtt_topic); - str_len += strlen(Settings.button_topic); - str_len += strlen(Settings.switch_topic); - str_len += strlen(Settings.mqtt_grptopic); - str_len += strlen(Settings.web_password); - str_len += strlen(Settings.mqtt_fulltopic); - str_len += strlen(Settings.cors_domain); - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/1151\""), 37 + str_len); // Char Usage Ratio - } else { - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); // Char Usage Ratio - } + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); // Char Usage Ratio return String(data); } diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 27480159d..be2cfafe2 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,9 +20,9 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07020001; +const uint32_t VERSION = 0x08000001; // Lowest compatible version -const uint32_t VERSION_COMPATIBLE = 0x06000000; +const uint32_t VERSION_COMPATIBLE = 0x07010006; #endif // _TASMOTA_VERSION_H_ From 9fc11270bad712d5f34823ce721bc5db25ecd390 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 21 Dec 2019 17:09:24 +0100 Subject: [PATCH 123/559] Fix Arduino IDE compile error Fix Arduino IDE compile error (#7277) --- tasmota/tasmota_post.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index b095fdbf2..c54adfe82 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -21,7 +21,7 @@ #define _TASMOTA_POST_H_ /*********************************************************************************************\ - * Function declarations + * Function prototypes \*********************************************************************************************/ // Needed for core 2.3.0 compilation (#6721) @@ -39,6 +39,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); //#endif // USE_KNX char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0'); +extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end); /*********************************************************************************************\ * Default global defines From 281cef6763a26635ea872b8c860c07b463caa889 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 21 Dec 2019 17:57:54 +0100 Subject: [PATCH 124/559] Fix no AP on initial install Fix no AP on initial install (#7282) --- tasmota/support_tasmota.ino | 2 +- tasmota/support_wifi.ino | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 08b898efb..900ba3dd4 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -108,7 +108,7 @@ char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopi fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops } for (uint32_t i = 0; i < 3; i++) { - if ('\0' == SettingsText(SET_MQTTPREFIX1 + i)) { + if (!strlen(SettingsText(SET_MQTTPREFIX1 + i))) { char temp[TOPSZ]; SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes)); } diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 86cc81dd8..c283f1bb5 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -191,7 +191,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) case 2: // Toggle Settings.sta_active ^= 1; } // 3: Current AP - if ('\0' == SettingsText(SET_STASSID1 + Settings.sta_active)) { + if (!strlen(SettingsText(SET_STASSID1 + Settings.sta_active))) { Settings.sta_active ^= 1; // Skip empty SSID } if (Settings.ip_address[0]) { @@ -436,7 +436,7 @@ void WifiCheckIp(void) if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); } else { - if (('\0' == SettingsText(SET_STASSID1)) && ('\0' == SettingsText(SET_STASSID2))) { + if (!strlen(SettingsText(SET_STASSID1)) && !strlen(SettingsText(SET_STASSID2))) { wifi_config_tool = WIFI_MANAGER; // Skip empty SSIDs and start Wifi config tool Wifi.retry = 0; } else { From 9a7d5346c457c288ea564dcb33ca47a8f643e39d Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 21 Dec 2019 18:26:36 +0100 Subject: [PATCH 125/559] Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_04_light.ino | 78 +++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e8b70c0cd..8d7a06812 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.0.0.1 20191221 - Change Settings text handling allowing variable length text within a total text pool of 699 characters +- Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) ## Released diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index 6148a9aad..d6e71ab08 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -262,8 +262,8 @@ struct LIGHT { uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; uint16_t fade_cur_10[LST_MAX]; uint16_t fade_end_10[LST_MAX]; // 10 bits resolution target channel values - uint16_t fade_counter = 0; // fade timer in ticks (50ms) - uint16_t fade_duration = 0; // duration of fade in ticks (50ms) + uint16_t fade_duration = 0; // duration of fade in milliseconds + uint32_t fade_start = 0; // fade start time in milliseconds, compared to millis() } Light; power_t LightPower(void) @@ -1574,20 +1574,25 @@ void LightAnimate(void) bool power_off = false; Light.strip_timer_counter++; - if (!Light.power) { // All channels powered off - Light.strip_timer_counter = 0; - if (!Light.fade_running) { - sleep = Settings.sleep; - } - if (Settings.light_scheme >= LS_MAX) { - power_off = true; - } - } else { + + // set sleep parameter: either settings, + // or set a maximum of PWM_MAX_SLEEP if light is on or Fade is running + if (Light.power || Light.fade_running) { if (Settings.sleep > PWM_MAX_SLEEP) { sleep = PWM_MAX_SLEEP; // set a maxumum value of 50 milliseconds to ensure that animations are smooth } else { sleep = Settings.sleep; // or keep the current sleep if it's lower than 50 } + } else { + sleep = Settings.sleep; + } + + if (!Light.power) { // All channels powered off + Light.strip_timer_counter = 0; + if (Settings.light_scheme >= LS_MAX) { + power_off = true; + } + } else { switch (Settings.light_scheme) { case LS_POWER: light_controller.calcLevels(Light.new_color); @@ -1733,27 +1738,35 @@ void LightAnimate(void) memcpy(Light.fade_end_8, cur_col, sizeof(Light.fade_start_8)); memcpy(Light.fade_end_10, cur_col_10bits, sizeof(Light.fade_start_10)); Light.fade_running = true; - Light.fade_counter = 0; Light.fade_duration = 0; // set the value to zero to force a recompute + Light.fade_start = 0; // Fade will applied immediately below } } if (Light.fade_running) { - LightApplyFade(); - // AddLog_P2(LOG_LEVEL_INFO, PSTR("LightApplyFade %d %d %d %d %d - %d %d %d %d %d"), - // Light.fade_cur_8[0], Light.fade_cur_8[1], Light.fade_cur_8[2], Light.fade_cur_8[3], Light.fade_cur_8[4], - // Light.fade_cur_10[0], Light.fade_cur_10[1], Light.fade_cur_10[2], Light.fade_cur_10[3], Light.fade_cur_10[4]); + if (LightApplyFade()) { + // AddLog_P2(LOG_LEVEL_INFO, PSTR("LightApplyFade %d %d %d %d %d - %d %d %d %d %d"), + // Light.fade_cur_8[0], Light.fade_cur_8[1], Light.fade_cur_8[2], Light.fade_cur_8[3], Light.fade_cur_8[4], + // Light.fade_cur_10[0], Light.fade_cur_10[1], Light.fade_cur_10[2], Light.fade_cur_10[3], Light.fade_cur_10[4]); - LightSetOutputs(Light.fade_cur_8, Light.fade_cur_10); + LightSetOutputs(Light.fade_cur_8, Light.fade_cur_10); + } } } } -void LightApplyFade(void) { +bool LightApplyFade(void) { // did the value chanegd and needs to be applied + static uint32_t last_millis = 0; + uint32_t now = millis(); + + if ((now - last_millis) <= 5) { + return false; // the value was not changed in the last 5 milliseconds, ignore + } + last_millis = now; // Check if we need to calculate the duration if (0 == Light.fade_duration) { - Light.fade_counter = 0; + Light.fade_start = now; // compute the distance between start and and color (max of distance for each channel) uint32_t distance = 0; for (uint32_t i = 0; i < Light.subtype; i++) { @@ -1764,11 +1777,11 @@ void LightApplyFade(void) { if (distance > 0) { // compute the duration of the animation // Note: Settings.light_speed is the number of half-seconds for a 100% fade, - // i.e. light_speed=1 means 1024 steps in 10 ticks (500ms) - Light.fade_duration = (distance * Settings.light_speed * 10) / 1024; + // i.e. light_speed=1 means 1024 steps in 500ms + Light.fade_duration = (distance * Settings.light_speed * 500) / 1023; if (Settings.save_data) { // Also postpone the save_data for the duration of the Fade (in seconds) - uint32_t delay_seconds = 1 + (Light.fade_duration + 19) / 20; // add one more second + uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; // add one more second // AddLog_P2(LOG_LEVEL_INFO, PSTR("delay_seconds %d, save_data_counter %d"), delay_seconds, save_data_counter); if (save_data_counter < delay_seconds) { save_data_counter = delay_seconds; // pospone @@ -1776,16 +1789,18 @@ void LightApplyFade(void) { } } else { // no fade needed, we keep the duration at zero, it will fallback directly to end of fade + Light.fade_running = false; } } - Light.fade_counter++; - if (Light.fade_counter <= Light.fade_duration) { // fade not finished + uint16_t fade_current = now - Light.fade_start; // number of milliseconds since start of fade + if (fade_current <= Light.fade_duration) { // fade not finished + //Serial.printf("Fade: %d / %d - ", fade_current, Light.fade_duration); for (uint32_t i = 0; i < Light.subtype; i++) { - Light.fade_cur_8[i] = changeUIntScale(Light.fade_counter, + Light.fade_cur_8[i] = changeUIntScale(fade_current, 0, Light.fade_duration, Light.fade_start_8[i], Light.fade_end_8[i]); - Light.fade_cur_10[i] = changeUIntScale(Light.fade_counter, + Light.fade_cur_10[i] = changeUIntScale(fade_current, 0, Light.fade_duration, Light.fade_start_10[i], Light.fade_end_10[i]); } @@ -1793,7 +1808,7 @@ void LightApplyFade(void) { // stop fade //AddLop_P2(LOG_LEVEL_DEBUG, PSTR("Stop fade")); Light.fade_running = false; - Light.fade_counter = 0; + Light.fade_start = 0; Light.fade_duration = 0; // set light to target value memcpy(Light.fade_cur_8, Light.fade_end_8, sizeof(Light.fade_end_8)); @@ -1802,7 +1817,7 @@ void LightApplyFade(void) { memcpy(Light.fade_start_8, Light.fade_end_8, sizeof(Light.fade_start_8)); memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10)); } - + return true; } // On entry we take the 5 channels 8 bits entry, and we apply Power modifiers @@ -2428,6 +2443,13 @@ bool Xdrv04(uint8_t function) case FUNC_SERIAL: result = XlgtCall(FUNC_SERIAL); break; + case FUNC_LOOP: + if (Light.fade_running) { + if (LightApplyFade()) { + LightSetOutputs(Light.fade_cur_8, Light.fade_cur_10); + } + } + break; case FUNC_EVERY_50_MSECOND: LightAnimate(); break; From fbe29e485b4ea835b46320d85587e7b8f4285d0b Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 21 Dec 2019 18:39:47 +0100 Subject: [PATCH 126/559] Zigbee aqara switch, support for double/triple clicks --- tasmota/xdrv_23_zigbee_5_converters.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 687ac2483..a4ab9e9fc 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -511,6 +511,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { // On/off cluster { 0x0006, 0x0000, "Power", &Z_Copy }, + { 0x0006, 0x8000, "Power", &Z_Copy }, // See 7280 // On/Off Switch Configuration cluster { 0x0007, 0x0000, "SwitchType", &Z_Copy }, From d13553baefa9a53af18c1eeb031449fa80708916 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 21 Dec 2019 18:59:00 +0100 Subject: [PATCH 127/559] Fix restore Fix restore ShutterAccuracy, MqttLog, WifiConfig, WifiPower and SerialConfig (#7281) --- tasmota/CHANGELOG.md | 3 +++ tasmota/settings.ino | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index e8b70c0cd..bd8801376 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -9,6 +9,9 @@ ### 7.2.0 20191221 - Release +- Fix Arduino IDE compile error (#7277) +- Fix restore ShutterAccuracy, MqttLog, WifiConfig, WifiPower and SerialConfig (#7281) +- Fix no AP on initial install (#7282) ### 7.1.2.6 20191214 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 9a0ea44f1..2fd84bde0 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1240,8 +1240,8 @@ void SettingsDelta(void) memset((char*)&Settings +0x1D6, 0x00, 16); } if (Settings.version < 0x0606000F) { - Settings.shutter_accuracy = 0; - Settings.mqttlog_level = MQTT_LOG_LEVEL; + Settings.ex_shutter_accuracy = 0; + Settings.ex_mqttlog_level = MQTT_LOG_LEVEL; } if (Settings.version < 0x06060011) { Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; @@ -1281,7 +1281,7 @@ void SettingsDelta(void) } if (Settings.version < 0x06060015) { if ((EX_WIFI_SMARTCONFIG == Settings.sta_config) || (EX_WIFI_WPSCONFIG == Settings.sta_config)) { - Settings.sta_config = WIFI_MANAGER; + Settings.ex_sta_config = WIFI_MANAGER; } } @@ -1294,10 +1294,10 @@ void SettingsDelta(void) SettingsEnableAllI2cDrivers(); } if (Settings.version < 0x07000004) { - Settings.wifi_output_power = 170; + Settings.ex_wifi_output_power = 170; } if (Settings.version < 0x07010202) { - Settings.serial_config = TS_SERIAL_8N1; + Settings.ex_serial_config = TS_SERIAL_8N1; } if (Settings.version < 0x07010204) { if (Settings.flag3.ex_cors_enabled == 1) { From 486894781f775eb7cde2b971aa904d7f3d059a4e Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 21 Dec 2019 22:38:49 +0100 Subject: [PATCH 128/559] Fix AWS IoT --- tasmota/settings.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 2fd84bde0..8c378264b 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1355,7 +1355,7 @@ void SettingsDelta(void) } else { char aws_mqtt_host[66]; snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), temp9, temp7); - SettingsUpdateText(SET_MQTT_HOST, mqtt_host); + SettingsUpdateText(SET_MQTT_HOST, aws_mqtt_host); SettingsUpdateText(SET_MQTT_USER, ""); } #else From ca534c4a1bb9f7910219c15a33e340578c639053 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 21 Dec 2019 23:36:15 -0300 Subject: [PATCH 129/559] Changed sensor number to a new free one --- tasmota/{xsns_58_GPS.ino => xsns_60_GPS.ino} | 40 ++++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) rename tasmota/{xsns_58_GPS.ino => xsns_60_GPS.ino} (95%) diff --git a/tasmota/xsns_58_GPS.ino b/tasmota/xsns_60_GPS.ino similarity index 95% rename from tasmota/xsns_58_GPS.ino rename to tasmota/xsns_60_GPS.ino index 58178b976..db9343e2d 100644 --- a/tasmota/xsns_58_GPS.ino +++ b/tasmota/xsns_60_GPS.ino @@ -1,5 +1,5 @@ /* - xsns_58_GPS_UBX.ino - GPS UBLOX support for Sonoff-Tasmota + xsns_60_GPS.ino - GPS UBLOX support for Sonoff-Tasmota Copyright (C) 2019 Theo Arends, Christian Baars and Adrian Scillato @@ -44,46 +44,46 @@ The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To ## Commands: -+ sensor58 0 ++ sensor60 0 write to all available sectors, then restart and overwrite the older ones -+ sensor58 1 ++ sensor60 1 write to all available sectors, then restart and overwrite the older ones -+ sensor58 2 ++ sensor60 2 filter out horizontal drift noise -+ sensor58 3 ++ sensor60 3 turn off noise filter -+ sensor58 4 ++ sensor60 4 start recording, new data will be appended -+ sensor58 5 ++ sensor60 5 start new recording, old data will lost -+ sensor58 6 ++ sensor60 6 stop recording, download link will be visible in Web-UI -+ sensor58 7 ++ sensor60 7 send mqtt on new postion + TELE -> consider to set TELE to a very high value -+ sensor58 8 ++ sensor60 8 only TELE message -+ sensor58 9 ++ sensor60 9 start NTP-server -+ sensor58 10 ++ sensor60 10 deactivate NTP-server -+ sensor58 11 ++ sensor60 11 force update of Tasmota-system-UTC with every new GPS-time-message -+ sensor58 12 ++ sensor60 12 do not update of Tasmota-system-UTC with every new GPS-time-message -+ sensor58 13 ++ sensor60 13 set latitude and longitude in settings @@ -91,7 +91,7 @@ The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To ## Rules examples for SSD1306 32x128 -rule1 on tele-GPS#lat do DisplayText [s1p21c1l01f1]LAT: %value% endon on tele-GPS#lon do DisplayText [s1p21c1l2]LON: %value% endon on switch1#state==3 do sensor58 4 endon on switch1#state==2 do sensor58 6 endon +rule1 on tele-GPS#lat do DisplayText [s1p21c1l01f1]LAT: %value% endon on tele-GPS#lon do DisplayText [s1p21c1l2]LON: %value% endon on switch1#state==3 do sensor60 4 endon on switch1#state==2 do sensor60 6 endon rule2 on tele-GPS#int>9 do DisplayText [f0c9l4]I%value% endon on tele-GPS#int<10 do DisplayText [f0c9l4]I0%value% endon on tele-GPS#fil==1 do DisplayText [f0c18l4]F endon on tele-GPS#fil==0 do DisplayText [f0c18l4]N endon @@ -793,9 +793,9 @@ bool UBXCmd(void) { * Interface \*********************************************************************************************/ -#define XSNS_58 58 +#define XSNS_60 60 -bool Xsns58(uint8_t function) +bool Xsns60(uint8_t function) { bool result = false; @@ -805,7 +805,7 @@ bool Xsns58(uint8_t function) UBXDetect(); break; case FUNC_COMMAND_SENSOR: - if (XSNS_58 == XdrvMailbox.index){ + if (XSNS_60 == XdrvMailbox.index){ result = UBXCmd(); } break; @@ -843,4 +843,4 @@ bool Xsns58(uint8_t function) return result; } -#endif // USE_GPS_UBX +#endif // USE_GPS From f642f014b70959b41248f951a72d52c2dc96db7a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 22 Dec 2019 11:52:54 +0100 Subject: [PATCH 130/559] Fix WifiConfig error --- tasmota/CHANGELOG.md | 1 + tasmota/settings.ino | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 6d6c82853..c7d34cbea 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -13,6 +13,7 @@ - Fix Arduino IDE compile error (#7277) - Fix restore ShutterAccuracy, MqttLog, WifiConfig, WifiPower and SerialConfig (#7281) - Fix no AP on initial install (#7282) +- Fix failing downgrade (#7285) ### 7.1.2.6 20191214 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 8c378264b..a1da16764 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -488,7 +488,7 @@ void UpdateQuickPowerCycle(bool update) * Config Settings.text char array support \*********************************************************************************************/ -const uint32_t settings_text_size = 699; // Settings.flag4 (2D2) - Settings.ota_url (017) +const uint32_t settings_text_size = 699; // Settings.display_model (2D2) - Settings.ota_url (017) uint32_t GetSettingsTextLen(void) { @@ -1280,7 +1280,7 @@ void SettingsDelta(void) Settings.ex_energy_power_delta = 0; } if (Settings.version < 0x06060015) { - if ((EX_WIFI_SMARTCONFIG == Settings.sta_config) || (EX_WIFI_WPSCONFIG == Settings.sta_config)) { + if ((EX_WIFI_SMARTCONFIG == Settings.ex_sta_config) || (EX_WIFI_WPSCONFIG == Settings.ex_sta_config)) { Settings.ex_sta_config = WIFI_MANAGER; } } From ad4a7e91acd3e7eccce345b50269b4604a356fb9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 22 Dec 2019 15:23:52 +0100 Subject: [PATCH 131/559] Add support for max 150 characters Add support for max 150 characters in most command parameter strings (#3686, #4754) --- RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 2 ++ tasmota/settings.h | 2 +- tasmota/settings.ino | 2 +- tasmota/support_command.ino | 2 +- tasmota/support_tasmota.ino | 2 +- tasmota/tasmota.h | 4 ++-- tasmota/tasmota.ino | 6 +++--- tasmota/xdrv_01_webserver.ino | 14 +++++++------- tasmota/xdrv_02_mqtt.ino | 4 ++-- tasmota/xdrv_10_scripter.ino | 14 +++++++------- 11 files changed, 29 insertions(+), 25 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index bf21cf32b..7f07caaaa 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -49,3 +49,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ### Version 8.0.0.1 - Change Settings text handling allowing variable length text within a total text pool of 699 characters +- Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) +- Add support for max 150 characters in command parameter strings (#3686, #4754) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index c7d34cbea..6930b6ab4 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,12 +4,14 @@ - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) +- Add support for max 150 characters in most command parameter strings (#3686, #4754) ## Released ### 7.2.0 20191221 - Release +- Change basic version string to lite (#7291) - Fix Arduino IDE compile error (#7277) - Fix restore ShutterAccuracy, MqttLog, WifiConfig, WifiPower and SerialConfig (#7281) - Fix no AP on initial install (#7282) diff --git a/tasmota/settings.h b/tasmota/settings.h index 0b3990578..c55d85b34 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -419,7 +419,7 @@ struct SYSCFG { unsigned long weight_calibration; // 7C4 unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight uint16_t web_refresh; // 7CC - char mems[MAX_RULE_MEMS][10]; // 7CE - Used by scripter as script_pram + char mems[5][10]; // 7CE - Used by scripter as script_pram char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b diff --git a/tasmota/settings.ino b/tasmota/settings.ino index a1da16764..b0241f9fb 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -533,7 +533,7 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me) int too_long = (char_len + diff) - settings_text_size; if (too_long > 0) { -// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text too long by %d char(s)"), too_long); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text overflow by %d char(s)"), too_long); return false; // Replace text too long } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index b8fbd4a7a..265926b59 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -326,7 +326,7 @@ void CmndStatus(void) uint32_t option = STAT; char stemp[200]; - char stemp2[100]; + char stemp2[TOPSZ]; // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX if (!strcmp(SettingsText(SET_MQTTPREFIX1), SettingsText(SET_MQTTPREFIX2)) && (!payload)) { option++; } // TELE diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 900ba3dd4..c649d9379 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -546,7 +546,7 @@ void MqttShowPWMState(void) void MqttShowState(void) { - char stemp1[33]; + char stemp1[TOPSZ]; ResponseAppendTime(); ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index c93c3ea9e..d68907185 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -70,10 +70,10 @@ const uint8_t MAX_XSNS_DRIVERS = 96; // Max number of allowed sensor driv const uint8_t MAX_I2C_DRIVERS = 96; // Max number of allowed i2c drivers const uint8_t MAX_SHUTTERS = 4; // Max number of shutters const uint8_t MAX_PCF8574 = 8; // Max number of PCF8574 devices -const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules +const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation const char MQTT_TOKEN_PREFIX[] PROGMEM = "%prefix%"; // To be substituted by mqtt_prefix[x] @@ -118,7 +118,7 @@ const uint8_t OTA_ATTEMPTS = 5; // Number of times to try fetching t const uint16_t INPUT_BUFFER_SIZE = 520; // Max number of characters in (serial and http) command buffer const uint16_t FLOATSZ = 16; // Max number of characters in float result from dtostrfd (max 32) const uint16_t CMDSZ = 24; // Max number of characters in command -const uint16_t TOPSZ = 100; // Max number of characters in topic string +const uint16_t TOPSZ = 151; // Max number of characters in topic string const uint16_t LOGSZ = 700; // Max number of characters in log const uint16_t MIN_MESSZ = 893; // Min number of characters in MQTT message diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 67be9d35f..e80331366 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -68,7 +68,7 @@ // Structs #include "settings.h" -const char kCodeImage[] PROGMEM = "tasmota|minimal|sensors|knx|basic|display|ir"; +const char kCodeImage[] PROGMEM = "tasmota|minimal|sensors|knx|lite|display|ir"; /*********************************************************************************************\ * Global variables @@ -161,8 +161,8 @@ StateBitfield global_state; // Global states (currently Wifi and char my_version[33]; // Composed version string char my_image[33]; // Code image and/or commit char my_hostname[33]; // Composed Wifi hostname -char mqtt_client[33]; // Composed MQTT Clientname -char mqtt_topic[33]; // Composed MQTT topic +char mqtt_client[TOPSZ]; // Composed MQTT Clientname +char mqtt_topic[TOPSZ]; // Composed MQTT topic char serial_in_buffer[INPUT_BUFFER_SIZE]; // Receive buffer char mqtt_data[MESSZ]; // MQTT publish buffer and web page ajax buffer char log_data[LOGSZ]; // Logging diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 8aece2be8..104e71f67 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1694,7 +1694,7 @@ void HandleWifiConfiguration(void) void WifiSaveSettings(void) { - char tmp[100]; // Max length is currently 65 + char tmp[TOPSZ]; // Max length is currently 150 WebGetArg("h", tmp, sizeof(tmp)); SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); @@ -1757,7 +1757,7 @@ void HandleLoggingConfiguration(void) void LoggingSaveSettings(void) { - char tmp[100]; // Max length is currently 33 + char tmp[TOPSZ]; // Max length is currently 33 WebGetArg("l0", tmp, sizeof(tmp)); SetSeriallog((!strlen(tmp)) ? SERIAL_LOG_LEVEL : atoi(tmp)); @@ -1843,7 +1843,7 @@ void HandleOtherConfiguration(void) void OtherSaveSettings(void) { - char tmp[128]; + char tmp[TOPSZ]; char webindex[5]; char friendlyname[TOPSZ]; @@ -1890,7 +1890,7 @@ void HandleBackupConfiguration(void) WiFiClient myClient = WebServer->client(); WebServer->setContentLength(sizeof(Settings)); - char attachment[100]; + char attachment[TOPSZ]; // char friendlyname[TOPSZ]; // snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, SettingsText(SET_FRIENDLYNAME1)), my_version); @@ -2095,12 +2095,12 @@ void HandleUpgradeFirmwareStart(void) { if (!HttpCheckPriviledgedAccess()) { return; } - char command[128]; // OtaUrl + char command[TOPSZ + 10]; // OtaUrl AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); WifiConfigCounter(); - char otaurl[101]; + char otaurl[TOPSZ]; WebGetArg("o", otaurl, sizeof(otaurl)); if (strlen(otaurl)) { snprintf_P(command, sizeof(command), PSTR(D_CMND_OTAURL " %s"), otaurl); @@ -2637,7 +2637,7 @@ int WebSend(char *buffer) if (user) { user = strtok_r(user, ":", &password); // user = |admin|, password = |joker| if (user && password) { - char userpass[128]; + char userpass[200]; snprintf_P(userpass, sizeof(userpass), PSTR("user=%s&password=%s&"), user, password); url += userpass; // url = |http://192.168.178.86/cm?user=admin&password=joker&| } diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 47838e223..f9ff3e67d 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -1190,7 +1190,7 @@ void HandleMqttConfiguration(void) return; } - char str[33]; + char str[TOPSZ]; WSContentStart_P(S_CONFIGURE_MQTT); WSContentSendStyle(); @@ -1209,7 +1209,7 @@ void HandleMqttConfiguration(void) void MqttSaveSettings(void) { - char tmp[100]; + char tmp[TOPSZ]; char stemp[TOPSZ]; char stemp2[TOPSZ]; diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 68df13984..da63dbb22 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -56,7 +56,7 @@ keywords if then else endif, or, and are better readable for beginners (others m #define SCRIPT_MAXSSIZE 48 #define SCRIPT_EOL '\n' #define SCRIPT_FLOAT_PRECISION 2 -#define SCRIPT_MAXPERM (MAX_RULE_MEMS*10)-4/sizeof(float) +#define SCRIPT_MAXPERM (5*10)-4/sizeof(float) #define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution @@ -1041,7 +1041,7 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso if (sp) strlcpy(sp,str_value,SCRIPT_MAXSSIZE); return lp+len; } - + } else { if (fp) { if (!strncmp(vn.c_str(),"Epoch",5)) { @@ -1575,7 +1575,7 @@ chknext: case 'r': if (!strncmp(vname,"ram",3)) { - fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(MAX_RULE_MEMS*10); + fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(5*10); goto exit; } break; @@ -2995,7 +2995,7 @@ void ScripterEvery100ms(void) { if (fast_script==99) Run_Scripter(">F",2,0); } -//mems[MAX_RULE_MEMS] is 50 bytes in 6.5 +//mems[5] is 50 bytes in 6.5 // can hold 11 floats or floats + strings // should report overflow later void Scripter_save_pvars(void) { @@ -3007,7 +3007,7 @@ void Scripter_save_pvars(void) { if (vtp[count].bits.is_permanent && !vtp[count].bits.is_string) { uint8_t index=vtp[count].index; mlen+=sizeof(float); - if (mlen>MAX_RULE_MEMS*10) { + if (mlen>5*10) { vtp[count].bits.is_permanent=0; return; } @@ -3021,7 +3021,7 @@ void Scripter_save_pvars(void) { char *sp=glob_script_mem.glob_snp+(index*glob_script_mem.max_ssize); uint8_t slen=strlen(sp); mlen+=slen+1; - if (mlen>MAX_RULE_MEMS*10) { + if (mlen>5*10) { vtp[count].bits.is_permanent=0; return; } @@ -4755,7 +4755,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_size=MAX_SCRIPT_SIZE; glob_script_mem.flags=0; glob_script_mem.script_pram=(uint8_t*)Settings.mems[0]; - glob_script_mem.script_pram_size=MAX_RULE_MEMS*10; + glob_script_mem.script_pram_size=5*10; #ifdef USE_BUTTON_EVENT for (uint32_t cnt=0;cnt Date: Sun, 22 Dec 2019 15:36:20 +0100 Subject: [PATCH 132/559] Change max number of rule ``Mem``s to 16 Change max number of rule ``Mem``s from 5 to 16 (#4933) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/tasmota.h | 2 +- tasmota/xdrv_10_rules.ino | 4 ++-- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7f07caaaa..b2bff6a7a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -50,4 +50,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) +- Change max number of rule ``Mem``s from 5 to 16 (#4933) - Add support for max 150 characters in command parameter strings (#3686, #4754) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 6930b6ab4..1c99c7223 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) +- Change max number of rule ``Mem``s from 5 to 16 (#4933) - Add support for max 150 characters in most command parameter strings (#3686, #4754) ## Released diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index d68907185..bdbe5d177 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -73,7 +73,7 @@ const uint8_t MAX_PCF8574 = 8; // Max number of PCF8574 devices const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules -const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars +const uint8_t MAX_RULE_MEMS = 16; // Max number of saved vars const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation const char MQTT_TOKEN_PREFIX[] PROGMEM = "%prefix%"; // To be substituted by mqtt_prefix[x] diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 6e1636518..72276f94b 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -174,8 +174,8 @@ char rules_vars[MAX_RULE_VARS][33] = {{ 0 }}; #if (MAX_RULE_VARS>16) #error MAX_RULE_VARS is bigger than 16 #endif -#if (MAX_RULE_MEMS>5) -#error MAX_RULE_MEMS is bigger than 5 +#if (MAX_RULE_MEMS>16) +#error MAX_RULE_MEMS is bigger than 16 #endif /*******************************************************************************************/ From 35e51918e30c0d6d30cbc94524bec980bdf97aa1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 22 Dec 2019 16:53:51 +0100 Subject: [PATCH 133/559] Document Settings changes --- tasmota/settings.h | 68 ++++++++++++----------- tasmota/settings.ino | 104 +++++++++++++++++------------------ tasmota/xdrv_10_scripter.ino | 2 +- tasmota/xdrv_20_hue.ino | 1 - 4 files changed, 88 insertions(+), 87 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index c55d85b34..af774a4c2 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -229,6 +229,7 @@ typedef struct { uint8_t dpid = 0; } TuyaFnidDpidMap; +const uint32_t settings_text_size = 699; // Settings.text_pool[size] = Settings.display_model (2D2) - Settings.text_pool (017) const uint8_t MAX_TUYA_FUNCTIONS = 16; struct SYSCFG { @@ -242,21 +243,19 @@ struct SYSCFG { int16_t save_data; // 014 int8_t timezone; // 016 - // Start of single char array Settings.text + // Start of char array storing all parameter strings - char ota_url[101]; // 017 - char mqtt_prefix[3][11]; // 07C + char text_pool[101]; // 017 - was ota_url[101] - size is settings_text_size - uint8_t ex_baudrate; // 09D - Free since 6.6.0.9 + char ex_mqtt_prefix[3][11]; // 07C + uint8_t ex_baudrate; // 09D uint8_t ex_seriallog_level; // 09E uint8_t ex_sta_config; // 09F uint8_t ex_sta_active; // 0A0 - - char sta_ssid[2][33]; // 0A1 - Keep together with sta_pwd as being copied as one chunck with reset 5 - char sta_pwd[2][65]; // 0E3 - Keep together with sta_ssid as being copied as one chunck with reset 5 - char hostname[33]; // 165 - char syslog_host[33]; // 186 - + char ex_sta_ssid[2][33]; // 0A1 + char ex_sta_pwd[2][65]; // 0E3 + char ex_hostname[33]; // 165 + char ex_syslog_host[33]; // 186 uint8_t ex_rule_stop; // 1A7 uint16_t ex_syslog_port; // 1A8 uint8_t ex_syslog_level; // 1AA @@ -264,28 +263,23 @@ struct SYSCFG { uint8_t ex_weblog_level; // 1AC uint8_t ex_mqtt_fingerprint[2][20]; // 1AD uint8_t ex_adc_param_type; // 1D5 - uint8_t ex_free_1d6[10]; // 1D6 - SysBitfield4 ex_flag4; // 1E0 uint8_t ex_serial_config; // 1E4 uint8_t ex_wifi_output_power; // 1E5 uint8_t ex_shutter_accuracy; // 1E6 uint8_t ex_mqttlog_level; // 1E7 uint8_t ex_sps30_inuse_hours; // 1E8 + char ex_mqtt_host[33]; // 1E9 + uint16_t ex_mqtt_port; // 20A + char ex_mqtt_client[33]; // 20C + char ex_mqtt_user[33]; // 22D + char ex_mqtt_pwd[33]; // 24E + char ex_mqtt_topic[33]; // 26F + char ex_button_topic[33]; // 290 + char ex_mqtt_grptopic[33]; // 2B1 - char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6 - - uint16_t ex_mqtt_port; // 20A - Keep together - - char mqtt_client[33]; // 20C - Keep together - char mqtt_user[33]; // 22D - Keep together - char mqtt_pwd[33]; // 24E - Keep together - char mqtt_topic[33]; // 26F - Keep together with above items as being copied as one chunck with reset 6 - char button_topic[33]; // 290 - char mqtt_grptopic[33]; // 2B1 - - // Optional end of single char array of 698 chars max (phase 5) + // End of single char array of 698 chars max uint8_t display_model; // 2D2 uint8_t display_mode; // 2D3 @@ -306,8 +300,8 @@ struct SYSCFG { uint8_t param[PARAM8_SIZE]; // 2FC SetOption32 .. SetOption49 int16_t toffset[2]; // 30E uint8_t display_font; // 312 - char state_text[4][11]; // 313 + char ex_state_text[4][11]; // 313 uint8_t ex_energy_power_delta; // 33F - Free since 6.6.0.20 uint16_t domoticz_update_timer; // 340 @@ -342,8 +336,10 @@ struct SYSCFG { uint16_t light_rotation; // 39E SysBitfield3 flag3; // 3A0 uint8_t switchmode[MAX_SWITCHES]; // 3A4 (6.0.0b - moved from 0x4CA) - char friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC - char switch_topic[33]; // 430 + + char ex_friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC + char ex_switch_topic[33]; // 430 + char serial_delimiter; // 451 uint8_t seriallog_level; // 452 uint8_t sleep; // 453 @@ -367,15 +363,21 @@ struct SYSCFG { uint8_t knx_GA_registered; // 4A5 Number of Group Address to read uint16_t light_wakeup; // 4A6 uint8_t knx_CB_registered; // 4A8 Number of Group Address to write - char web_password[33]; // 4A9 + + char ex_web_password[33]; // 4A9 + uint8_t interlock[MAX_INTERLOCKS]; // 4CA - char ntp_server[3][33]; // 4CE + + char ex_ntp_server[3][33]; // 4CE + uint8_t ina219_mode; // 531 uint16_t pulse_timer[MAX_PULSETIMERS]; // 532 uint16_t button_debounce; // 542 uint32_t ip_address[4]; // 544 unsigned long energy_kWhtotal; // 554 - char mqtt_fulltopic[100]; // 558 + + char ex_mqtt_fulltopic[100]; // 558 + SysBitfield2 flag2; // 5BC unsigned long pulse_counter[MAX_COUNTERS]; // 5C0 uint16_t pulse_counter_type; // 5D0 @@ -419,7 +421,7 @@ struct SYSCFG { unsigned long weight_calibration; // 7C4 unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight uint16_t web_refresh; // 7CC - char mems[5][10]; // 7CE - Used by scripter as script_pram + char script_pram[5][10]; // 7CE char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b @@ -443,7 +445,9 @@ struct SYSCFG { int8_t temp_comp; // E9E uint8_t weight_change; // E9F uint8_t web_color2[2][3]; // EA0 - Needs to be on integer / 3 distance from web_color - char cors_domain[33]; // EA6 + + char ex_cors_domain[33]; // EA6 + uint8_t sta_config; // EC7 uint8_t sta_active; // EC8 uint8_t rule_stop; // EC9 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index b0241f9fb..ce6c33ff4 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -488,15 +488,13 @@ void UpdateQuickPowerCycle(bool update) * Config Settings.text char array support \*********************************************************************************************/ -const uint32_t settings_text_size = 699; // Settings.display_model (2D2) - Settings.ota_url (017) - uint32_t GetSettingsTextLen(void) { - char* position = Settings.ota_url; + char* position = Settings.text_pool; for (uint32_t size = 0; size < SET_MAX; size++) { while (*position++ != '\0') { } } - return position - Settings.ota_url; + return position - Settings.text_pool; } bool SettingsUpdateText(uint32_t index, const char* replace_me) @@ -512,18 +510,18 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me) uint32_t start_pos = 0; uint32_t end_pos = 0; - char* position = Settings.ota_url; + char* position = Settings.text_pool; for (uint32_t size = 0; size < SET_MAX; size++) { while (*position++ != '\0') { } if (1 == index) { - start_pos = position - Settings.ota_url; + start_pos = position - Settings.text_pool; } else if (0 == index) { - end_pos = position - Settings.ota_url -1; + end_pos = position - Settings.text_pool -1; } index--; } - uint32_t char_len = position - Settings.ota_url; + uint32_t char_len = position - Settings.text_pool; uint32_t current_len = end_pos - start_pos; int diff = replace_len - current_len; @@ -539,12 +537,12 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me) if (diff != 0) { // Shift Settings.text up or down - memmove_P(Settings.ota_url + start_pos + replace_len, Settings.ota_url + end_pos, char_len - end_pos); + memmove_P(Settings.text_pool + start_pos + replace_len, Settings.text_pool + end_pos, char_len - end_pos); } // Replace text - memmove_P(Settings.ota_url + start_pos, replace, replace_len); + memmove_P(Settings.text_pool + start_pos, replace, replace_len); // Fill for future use - memset(Settings.ota_url + char_len + diff, 0x00, settings_text_size - char_len - diff); + memset(Settings.text_pool + char_len + diff, 0x00, settings_text_size - char_len - diff); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d"), GetSettingsTextLen(), settings_text_size); @@ -557,7 +555,7 @@ char* SettingsText(uint32_t index) return nullptr; // Setting not supported - internal error } - char* position = Settings.ota_url; + char* position = Settings.text_pool; for (;index > 0; index--) { while (*position++ != '\0') { } } @@ -1301,9 +1299,9 @@ void SettingsDelta(void) } if (Settings.version < 0x07010204) { if (Settings.flag3.ex_cors_enabled == 1) { - strlcpy(Settings.cors_domain, CORS_ENABLED_ALL, sizeof(Settings.cors_domain)); + strlcpy(Settings.ex_cors_domain, CORS_ENABLED_ALL, sizeof(Settings.ex_cors_domain)); } else { - Settings.cors_domain[0] = 0; + Settings.ex_cors_domain[0] = 0; } } if (Settings.version < 0x07010205) { @@ -1319,25 +1317,25 @@ void SettingsDelta(void) } if (Settings.version < 0x08000000) { - char temp[strlen(Settings.ota_url) +1]; strncpy(temp, Settings.ota_url, sizeof(temp)); - char temp21[strlen(Settings.mqtt_prefix[0]) +1]; strncpy(temp21, Settings.mqtt_prefix[0], sizeof(temp21)); - char temp22[strlen(Settings.mqtt_prefix[1]) +1]; strncpy(temp22, Settings.mqtt_prefix[1], sizeof(temp22)); - char temp23[strlen(Settings.mqtt_prefix[2]) +1]; strncpy(temp23, Settings.mqtt_prefix[2], sizeof(temp23)); - char temp31[strlen(Settings.sta_ssid[0]) +1]; strncpy(temp31, Settings.sta_ssid[0], sizeof(temp31)); - char temp32[strlen(Settings.sta_ssid[1]) +1]; strncpy(temp32, Settings.sta_ssid[1], sizeof(temp32)); - char temp41[strlen(Settings.sta_pwd[0]) +1]; strncpy(temp41, Settings.sta_pwd[0], sizeof(temp41)); - char temp42[strlen(Settings.sta_pwd[1]) +1]; strncpy(temp42, Settings.sta_pwd[1], sizeof(temp42)); - char temp5[strlen(Settings.hostname) +1]; strncpy(temp5, Settings.hostname, sizeof(temp5)); - char temp6[strlen(Settings.syslog_host) +1]; strncpy(temp6, Settings.syslog_host, sizeof(temp6)); - char temp7[strlen(Settings.mqtt_host) +1]; strncpy(temp7, Settings.mqtt_host, sizeof(temp7)); - char temp8[strlen(Settings.mqtt_client) +1]; strncpy(temp8, Settings.mqtt_client, sizeof(temp8)); - char temp9[strlen(Settings.mqtt_user) +1]; strncpy(temp9, Settings.mqtt_user, sizeof(temp9)); - char temp10[strlen(Settings.mqtt_pwd) +1]; strncpy(temp10, Settings.mqtt_pwd, sizeof(temp10)); - char temp11[strlen(Settings.mqtt_topic) +1]; strncpy(temp11, Settings.mqtt_topic, sizeof(temp11)); - char temp12[strlen(Settings.button_topic) +1]; strncpy(temp12, Settings.button_topic, sizeof(temp12)); - char temp13[strlen(Settings.mqtt_grptopic) +1]; strncpy(temp13, Settings.mqtt_grptopic, sizeof(temp13)); + char temp[strlen(Settings.text_pool) +1]; strncpy(temp, Settings.text_pool, sizeof(temp)); // Was ota_url + char temp21[strlen(Settings.ex_mqtt_prefix[0]) +1]; strncpy(temp21, Settings.ex_mqtt_prefix[0], sizeof(temp21)); + char temp22[strlen(Settings.ex_mqtt_prefix[1]) +1]; strncpy(temp22, Settings.ex_mqtt_prefix[1], sizeof(temp22)); + char temp23[strlen(Settings.ex_mqtt_prefix[2]) +1]; strncpy(temp23, Settings.ex_mqtt_prefix[2], sizeof(temp23)); + char temp31[strlen(Settings.ex_sta_ssid[0]) +1]; strncpy(temp31, Settings.ex_sta_ssid[0], sizeof(temp31)); + char temp32[strlen(Settings.ex_sta_ssid[1]) +1]; strncpy(temp32, Settings.ex_sta_ssid[1], sizeof(temp32)); + char temp41[strlen(Settings.ex_sta_pwd[0]) +1]; strncpy(temp41, Settings.ex_sta_pwd[0], sizeof(temp41)); + char temp42[strlen(Settings.ex_sta_pwd[1]) +1]; strncpy(temp42, Settings.ex_sta_pwd[1], sizeof(temp42)); + char temp5[strlen(Settings.ex_hostname) +1]; strncpy(temp5, Settings.ex_hostname, sizeof(temp5)); + char temp6[strlen(Settings.ex_syslog_host) +1]; strncpy(temp6, Settings.ex_syslog_host, sizeof(temp6)); + char temp7[strlen(Settings.ex_mqtt_host) +1]; strncpy(temp7, Settings.ex_mqtt_host, sizeof(temp7)); + char temp8[strlen(Settings.ex_mqtt_client) +1]; strncpy(temp8, Settings.ex_mqtt_client, sizeof(temp8)); + char temp9[strlen(Settings.ex_mqtt_user) +1]; strncpy(temp9, Settings.ex_mqtt_user, sizeof(temp9)); + char temp10[strlen(Settings.ex_mqtt_pwd) +1]; strncpy(temp10, Settings.ex_mqtt_pwd, sizeof(temp10)); + char temp11[strlen(Settings.ex_mqtt_topic) +1]; strncpy(temp11, Settings.ex_mqtt_topic, sizeof(temp11)); + char temp12[strlen(Settings.ex_button_topic) +1]; strncpy(temp12, Settings.ex_button_topic, sizeof(temp12)); + char temp13[strlen(Settings.ex_mqtt_grptopic) +1]; strncpy(temp13, Settings.ex_mqtt_grptopic, sizeof(temp13)); - memset(Settings.ota_url, 0x00, settings_text_size); + memset(Settings.text_pool, 0x00, settings_text_size); SettingsUpdateText(SET_OTAURL, temp); SettingsUpdateText(SET_MQTTPREFIX1, temp21); SettingsUpdateText(SET_MQTTPREFIX2, temp22); @@ -1349,7 +1347,7 @@ void SettingsDelta(void) SettingsUpdateText(SET_HOSTNAME, temp5); SettingsUpdateText(SET_SYSLOG_HOST, temp6); #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (!strlen(Settings.mqtt_user)) { + if (!strlen(Settings.ex_mqtt_user)) { SettingsUpdateText(SET_MQTT_HOST, temp7); SettingsUpdateText(SET_MQTT_USER, temp9); } else { @@ -1368,26 +1366,26 @@ void SettingsDelta(void) SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); - SettingsUpdateText(SET_WEBPWD, Settings.web_password); - SettingsUpdateText(SET_CORS, Settings.cors_domain); - SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.mqtt_fulltopic); - SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.switch_topic); - SettingsUpdateText(SET_STATE_TXT1, Settings.state_text[0]); - SettingsUpdateText(SET_STATE_TXT2, Settings.state_text[1]); - SettingsUpdateText(SET_STATE_TXT3, Settings.state_text[2]); - SettingsUpdateText(SET_STATE_TXT4, Settings.state_text[3]); - SettingsUpdateText(SET_NTPSERVER1, Settings.ntp_server[0]); - SettingsUpdateText(SET_NTPSERVER2, Settings.ntp_server[1]); - SettingsUpdateText(SET_NTPSERVER3, Settings.ntp_server[2]); - SettingsUpdateText(SET_MEM1, Settings.mems[0]); - SettingsUpdateText(SET_MEM2, Settings.mems[1]); - SettingsUpdateText(SET_MEM3, Settings.mems[2]); - SettingsUpdateText(SET_MEM4, Settings.mems[3]); - SettingsUpdateText(SET_MEM5, Settings.mems[4]); - SettingsUpdateText(SET_FRIENDLYNAME1, Settings.friendlyname[0]); - SettingsUpdateText(SET_FRIENDLYNAME2, Settings.friendlyname[1]); - SettingsUpdateText(SET_FRIENDLYNAME3, Settings.friendlyname[2]); - SettingsUpdateText(SET_FRIENDLYNAME4, Settings.friendlyname[3]); + SettingsUpdateText(SET_WEBPWD, Settings.ex_web_password); + SettingsUpdateText(SET_CORS, Settings.ex_cors_domain); + SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.ex_mqtt_fulltopic); + SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.ex_switch_topic); + SettingsUpdateText(SET_STATE_TXT1, Settings.ex_state_text[0]); + SettingsUpdateText(SET_STATE_TXT2, Settings.ex_state_text[1]); + SettingsUpdateText(SET_STATE_TXT3, Settings.ex_state_text[2]); + SettingsUpdateText(SET_STATE_TXT4, Settings.ex_state_text[3]); + SettingsUpdateText(SET_NTPSERVER1, Settings.ex_ntp_server[0]); + SettingsUpdateText(SET_NTPSERVER2, Settings.ex_ntp_server[1]); + SettingsUpdateText(SET_NTPSERVER3, Settings.ex_ntp_server[2]); + SettingsUpdateText(SET_MEM1, Settings.script_pram[0]); + SettingsUpdateText(SET_MEM2, Settings.script_pram[1]); + SettingsUpdateText(SET_MEM3, Settings.script_pram[2]); + SettingsUpdateText(SET_MEM4, Settings.script_pram[3]); + SettingsUpdateText(SET_MEM5, Settings.script_pram[4]); + SettingsUpdateText(SET_FRIENDLYNAME1, Settings.ex_friendlyname[0]); + SettingsUpdateText(SET_FRIENDLYNAME2, Settings.ex_friendlyname[1]); + SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]); + SettingsUpdateText(SET_FRIENDLYNAME4, Settings.ex_friendlyname[3]); } Settings.version = VERSION; diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index da63dbb22..c6aedb80e 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -4754,7 +4754,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_ram=Settings.rules[0]; glob_script_mem.script_size=MAX_SCRIPT_SIZE; glob_script_mem.flags=0; - glob_script_mem.script_pram=(uint8_t*)Settings.mems[0]; + glob_script_mem.script_pram=(uint8_t*)Settings.script_pram[0]; glob_script_mem.script_pram_size=5*10; #ifdef USE_BUTTON_EVENT diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 1d13ee263..80e85d821 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -365,7 +365,6 @@ void HueLightStatus1(uint8_t device, String *response) // Any device whose friendly name start with "$" is considered hidden bool HueActive(uint8_t device) { if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } -// return '$' != Settings.friendlyname[device-1][0]; return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1); } From 7695a2c5bf457e719d6387e1b03e6798e528e8d3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 22 Dec 2019 17:15:47 +0100 Subject: [PATCH 134/559] Change max number of rule ``Var``s to 16 Change max number of rule ``Var``s from 5 to 16 (#4933) --- README.md | 3 ++- RELEASENOTES.md | 3 ++- tasmota/CHANGELOG.md | 1 + tasmota/tasmota.h | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9a9ff0e1c..43bf4604a 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v7.2.x.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v8.0.x.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) @@ -67,6 +67,7 @@ See [wiki migration path](https://tasmota.github.io/docs/#/Upgrading?id=migratio 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** 5. Migrate to **Tasmota 7.x** +6. Migrate to **Tasmota 8.x** ## Support Information diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b2bff6a7a..8ac156872 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -51,4 +51,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) - Change max number of rule ``Mem``s from 5 to 16 (#4933) -- Add support for max 150 characters in command parameter strings (#3686, #4754) +- Change max number of rule ``Var``s from 5 to 16 (#4933) +- Add support for max 150 characters in most command parameter strings (#3686, #4754) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 1c99c7223..653112388 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) - Change max number of rule ``Mem``s from 5 to 16 (#4933) +- Change max number of rule ``Var``s from 5 to 16 (#4933) - Add support for max 150 characters in most command parameter strings (#3686, #4754) ## Released diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index bdbe5d177..829a90871 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -143,7 +143,7 @@ const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to \*********************************************************************************************/ #define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer) -#define MAX_RULE_VARS 5 // Max number of rule variables (10 bytes / variable) +#define MAX_RULE_VARS 16 // Max number of rule variables (33 bytes / variable) /* // Removed from esp8266 core since 20171105 From cdcaaa325deb9f31f1292e5196a94a70e312f94f Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 22 Dec 2019 17:47:45 +0100 Subject: [PATCH 135/559] Add Zigbee coalesce sensor attributes into a single message --- tasmota/CHANGELOG.md | 1 + tasmota/my_user_config.h | 1 + tasmota/xdrv_23_zigbee_0_constants.ino | 2 + tasmota/xdrv_23_zigbee_1_headers.ino | 20 +++++++++ tasmota/xdrv_23_zigbee_3_devices.ino | 57 ++++++++++++++++++++++-- tasmota/xdrv_23_zigbee_5_converters.ino | 22 +--------- tasmota/xdrv_23_zigbee_8_parsers.ino | 58 +++++++++++++++++++++---- tasmota/xdrv_23_zigbee_9_impl.ino | 19 -------- 8 files changed, 130 insertions(+), 50 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 653112388..084388717 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -7,6 +7,7 @@ - Change max number of rule ``Mem``s from 5 to 16 (#4933) - Change max number of rule ``Var``s from 5 to 16 (#4933) - Add support for max 150 characters in most command parameter strings (#3686, #4754) +- Add Zigbee coalesce sensor attributes into a single message ## Released diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 73a965d30..89640ffcf 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -530,6 +530,7 @@ #define USE_ZIGBEE_PRECFGKEY_L 0x0F0D0B0907050301L // note: changing requires to re-pair all devices #define USE_ZIGBEE_PRECFGKEY_H 0x0D0C0A0806040200L // note: changing requires to re-pair all devices #define USE_ZIGBEE_PERMIT_JOIN false // don't allow joining by default + #define USE_ZIGBEE_COALESCE_ATTR_TIMER 350 // timer to coalesce attribute values (in ms) // -- Other sensors/drivers ----------------------- diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index 0c74c9d8a..f83acf21b 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -19,6 +19,8 @@ #ifdef USE_ZIGBEE +#define OCCUPANCY "Occupancy" // global define for Aqara + typedef uint64_t Z_IEEEAddress; typedef uint16_t Z_ShortAddress; diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index b017d8e2e..8bfc59b70 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -23,4 +23,24 @@ void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1); + +// Get an JSON attribute, with case insensitive key search +JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { + // key can be in PROGMEM + if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) { + return *(JsonVariant*)nullptr; + } + + for (auto kv : json) { + const char *key = kv.key; + JsonVariant &value = kv.value; + + if (0 == strcasecmp_P(key, needle)) { + return value; + } + } + // if not found + return *(JsonVariant*)nullptr; +} + #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index de13990c2..c42f4b603 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -42,6 +42,9 @@ typedef struct Z_Device { uint16_t endpoint; // endpoint to use for timer uint32_t value; // any raw value to use for the timer Z_DeviceTimer func; // function to call when timer occurs + // json buffer used for attribute reporting + DynamicJsonBuffer *json_buffer; + JsonObject *json; } Z_Device; // All devices are stored in a Vector @@ -84,6 +87,11 @@ public: void setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func); void runTimer(void); + // Append or clear attributes Json structure + void jsonClear(uint16_t shortaddr); + void jsonAppend(uint16_t shortaddr, JsonObject &values); + const JsonObject *jsonGet(uint16_t shortaddr); + private: std::vector _devices = {}; @@ -173,7 +181,9 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { std::vector(), std::vector(), 0,0,0,0, - nullptr }; + nullptr, + nullptr, nullptr }; + device.json_buffer = new DynamicJsonBuffer(); _devices.push_back(device); return _devices.back(); } @@ -394,14 +404,55 @@ void Z_Devices::runTimer(void) { uint32_t timer = device.timer; if ((timer) && (timer <= now)) { + device.timer = 0; // cancel the timer before calling, so the callback can set another timer // trigger the timer (*device.func)(device.shortaddr, device.cluster, device.endpoint, device.value); - - device.timer = 0; // cancel the timer } } } +void Z_Devices::jsonClear(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + + device.json = nullptr; + device.json_buffer->clear(); +} + +void Z_Devices::jsonAppend(uint16_t shortaddr, JsonObject &values) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } // don't crash if not found + if (&values == nullptr) { return; } + + if (nullptr == device.json) { + device.json = &(device.json_buffer->createObject()); + } + // copy all values from 'values' to 'json' + for (auto kv : values) { + String key_string = kv.key; + const char * key = key_string.c_str(); + JsonVariant &val = kv.value; + + device.json->remove(key_string); // force remove to have metadata like LinkQuality at the end + + if (val.is()) { + String sval = val.as(); // force a copy of the String value + device.json->set(key_string, sval); + } else if (val.is()) { + // todo + } else if (val.is()) { + // todo + } else { + device.json->set(key_string, kv.value); + } + } +} + +const JsonObject *Z_Devices::jsonGet(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return nullptr; } // don't crash if not found + return device.json; +} // Dump the internal memory of Zigbee devices // Mode = 1: simple dump of devices addresses and names diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index a4ab9e9fc..49d63808e 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -480,8 +480,6 @@ typedef struct Z_AttributeConverter { Z_AttrConverter func; } Z_AttributeConverter; -#define OCCUPANCY "Occupancy" // global define for Aqara - // list of post-processing directives const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0000, 0x0000, "ZCLVersion", &Z_Copy }, @@ -751,7 +749,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Occupancy Sensing cluster - { 0x0406, 0x0000, OCCUPANCY, &Z_AqaraOccupancy }, // Occupancy (map8) + { 0x0406, 0x0000, OCCUPANCY, &Z_Copy }, // Occupancy (map8) { 0x0406, 0x0001, "OccupancySensorType", &Z_Copy }, // OccupancySensorType { 0x0406, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values @@ -818,11 +816,7 @@ int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& return 1; // remove original key } - -// Aqara Occupancy behavior: the Aqara device only sends Occupancy: true events every 60 seconds. -// Here we add a timer so if we don't receive a Occupancy event for 90 seconds, we send Occupancy:false -const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s - +// Publish a message for `"Occupancy":0` when the timer expired int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { // send Occupancy:false message Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":{\"" OCCUPANCY "\":0}}}"), shortaddr); @@ -830,18 +824,6 @@ int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpo XdrvRulesProcess(); } -int32_t Z_AqaraOccupancy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - uint32_t occupancy = value; - - if (occupancy) { - zigbee_devices.setTimer(shortaddr, OCCUPANCY_TIMEOUT, cluster, zcl->getSrcEndpoint(), 0, &Z_OccupancyCallback); - } else { - zigbee_devices.resetTimer(shortaddr); - } - return 1; // remove original key -} - // Aqara Vibration Sensor - special proprietary attributes int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { //json[new_name] = value; diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 2f30080fa..89320b117 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -357,6 +357,39 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { return -1; } +// Aqara Occupancy behavior: the Aqara device only sends Occupancy: true events every 60 seconds. +// Here we add a timer so if we don't receive a Occupancy event for 90 seconds, we send Occupancy:false +const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s + +void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, const JsonObject *json) { + // Read OCCUPANCY value if any + const JsonVariant &val_endpoint = getCaseInsensitive(*json, PSTR(OCCUPANCY)); + if (nullptr != &val_endpoint) { + uint32_t occupancy = strToUInt(val_endpoint); + + if (occupancy) { + zigbee_devices.setTimer(shortaddr, OCCUPANCY_TIMEOUT, cluster, endpoint, 0, &Z_OccupancyCallback); + } + } +} + + +// Publish the received values once they have been coalesced +int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + const JsonObject *json = zigbee_devices.jsonGet(shortaddr); + if (json == nullptr) { return 0; } // don't crash if not found + + // Post-provess for Aqara Presence Senson + Z_AqaraOccupancy(shortaddr, cluster, endpoint, json); + + String msg = ""; + json->printTo(msg); + zigbee_devices.jsonClear(shortaddr); + Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); +} + int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { uint16_t groupid = buf.get16(2); uint16_t clusterid = buf.get16(4); @@ -369,6 +402,8 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { uint32_t timestamp = buf.get32(13); uint8_t seqnumber = buf.get8(17); + bool defer_attributes = false; // do we defer attributes reporting to coalesce + zigbee_devices.updateLastSeen(srcaddr); ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, srcaddr, @@ -384,13 +419,13 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { JsonObject& json1 = json_root.createNestedObject(F(D_CMND_ZIGBEE_RECEIVED)); JsonObject& json = json1.createNestedObject(shortaddr); - // TODO add name field if it is known if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { - zcl_received.parseRawAttributes(json); + zcl_received.parseRawAttributes(json); + if (clusterid) { defer_attributes = true; } // don't defer system Cluster=0 messages } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { zcl_received.parseReadAttributes(json); } else if (zcl_received.isClusterSpecificCommand()) { - zcl_received.parseClusterSpecificCommand(json); + zcl_received.parseClusterSpecificCommand(json); } String msg(""); msg.reserve(100); @@ -401,11 +436,18 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { // Add linkquality json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; - msg = ""; - json_root.printTo(msg); - Response_P(PSTR("%s"), msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); + if (defer_attributes) { + // Prepare for publish + zigbee_devices.jsonAppend(srcaddr, json); + zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); + } else { + // Publish immediately + msg = ""; + json_root.printTo(msg); + Response_P(PSTR("%s"), msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + } return -1; } diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 461b3af32..b3681f00e 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -423,25 +423,6 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { ResponseCmndDone(); } -// Get an JSON attribute, with case insensitive key search -JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { - // key can be in PROGMEM - if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) { - return *(JsonVariant*)nullptr; - } - - for (auto kv : json) { - const char *key = kv.key; - JsonVariant &value = kv.value; - - if (0 == strcasecmp_P(key, needle)) { - return value; - } - } - // if not found - return *(JsonVariant*)nullptr; -} - void CmndZigbeeSend(void) { // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":1} } // ZigbeeSend { "device":"0x1234", "endpoint":"0x03", "send":{"Power":"3"} } From 3fee364fd75286e1c0c95305ee76b71a7ef751d2 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sun, 22 Dec 2019 19:59:56 +0100 Subject: [PATCH 136/559] Allow deepsleep to wait for second TELEPERIOD intervall Compatible with old values teleperiod10 or 300 to start deepsleep immediately asap. All Other values (at least >15, because this is often min runtime) for teleperiod causes the device to wait for another teleperiod eventually fix for #7295 --- tasmota/xdrv_29_deepsleep.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_29_deepsleep.ino b/tasmota/xdrv_29_deepsleep.ino index f0a8de685..69eed78f1 100644 --- a/tasmota/xdrv_29_deepsleep.ino +++ b/tasmota/xdrv_29_deepsleep.ino @@ -192,7 +192,7 @@ bool Xdrv29(uint8_t function) DeepSleepEverySecond(); break; case FUNC_AFTER_TELEPERIOD: - if (DeepSleepEnabled() && !deepsleep_flag) { + if (DeepSleepEnabled() && !deepsleep_flag && (Settings.tele_period == 10 || Settings.tele_period == 300 || UpTime() > Settings.tele_period)) { deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; // Start deepsleep in 4 seconds } break; From bf1c48c67e6b8c9162ff091791e6d4c69fee2dd6 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 23 Dec 2019 14:05:26 +0100 Subject: [PATCH 137/559] Update migration path --- README.md | 4 +++- RELEASENOTES.md | 9 ++++++--- tasmota/CHANGELOG.md | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 43bf4604a..ea1d1c23c 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,9 @@ See [wiki migration path](https://tasmota.github.io/docs/#/Upgrading?id=migratio 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** 5. Migrate to **Tasmota 7.x** -6. Migrate to **Tasmota 8.x** +--- Major change in parameter storage layout --- +6. Migrate to **Tasmota 8.1** +7. Migrate to **Tasmota 8.x** ## Support Information diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8ac156872..79f653d8e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -11,7 +11,9 @@ See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-pat 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** 5. Migrate to **Tasmota 7.x** -6. Migrate to **Tasmota 8.x** +--- Major change in parameter storage layout --- +6. Migrate to **Tasmota 8.1** +7. Migrate to **Tasmota 8.x** ## Supported Core versions @@ -50,6 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) -- Change max number of rule ``Mem``s from 5 to 16 (#4933) -- Change max number of rule ``Var``s from 5 to 16 (#4933) +- Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) - Add support for max 150 characters in most command parameter strings (#3686, #4754) +- Add Zigbee coalesce sensor attributes into a single message +- Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 084388717..09b12eb9a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,10 +4,10 @@ - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) -- Change max number of rule ``Mem``s from 5 to 16 (#4933) -- Change max number of rule ``Var``s from 5 to 16 (#4933) +- Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) - Add support for max 150 characters in most command parameter strings (#3686, #4754) - Add Zigbee coalesce sensor attributes into a single message +- Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 ## Released From fb8bb1223aef674ca2f41a49189e2abbe5527200 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 23 Dec 2019 15:39:07 +0100 Subject: [PATCH 138/559] Add support for GPS as NTP server Add support for GPS as NTP server by Christian Baars and Adrian Scillato --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/support_features.ino | 4 +- tasmota/tasmota_template.h | 15 +- tasmota/xsns_60_GPS.ino | 384 ++++++++++++++++++----------------- tools/decode-status.py | 5 +- 6 files changed, 216 insertions(+), 194 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 79f653d8e..237568fc5 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -54,5 +54,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) - Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) - Add support for max 150 characters in most command parameter strings (#3686, #4754) +- Add support for GPS as NTP server by Christian Baars and Adrian Scillato - Add Zigbee coalesce sensor attributes into a single message - Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 09b12eb9a..33617755b 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,6 +6,7 @@ - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) - Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) - Add support for max 150 characters in most command parameter strings (#3686, #4754) +- Add support for GPS as NTP server by Christian Baars and Adrian Scillato - Add Zigbee coalesce sensor attributes into a single message - Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 31428d03b..dcc24de0b 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -493,7 +493,9 @@ void GetFeatures(void) feature5 |= 0x00100000; #endif // feature5 |= 0x00200000; -// feature5 |= 0x00400000; +#ifdef USE_GPS + feature5 |= 0x00400000; +#endif // feature5 |= 0x00800000; // feature5 |= 0x01000000; diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 793c93626..3985884ef 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -295,7 +295,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|" - D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|" D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX + D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|" + D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX ; const char kSensorNamesFixed[] PROGMEM = @@ -673,6 +674,7 @@ const uint8_t kGpioNiceList[] PROGMEM = { #endif // USE_SOLAX_X1 #endif // USE_ENERGY_SENSOR +// Serial #ifdef USE_SERIAL_BRIDGE GPIO_SBR_TX, // Serial Bridge Serial interface GPIO_SBR_RX, // Serial Bridge Serial interface @@ -727,6 +729,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_IBEACON_RX, GPIO_IBEACON_TX, #endif +#ifdef USE_GPS + GPIO_GPS_RX, // GPS serial interface + GPIO_GPS_TX, // GPS serial interface +#endif + #ifdef USE_MGC3130 GPIO_MGC3130_XFER, GPIO_MGC3130_RESET, @@ -756,11 +763,7 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_A4988_MS3, // A4988 microstep pin3 #endif #ifdef USE_DEEPSLEEP - GPIO_DEEPSLEEP -#endif -#ifdef USE_GPS - GPIO_GPS_RX, // GPS serial interface - GPIO_GPS_TX // GPS serial interface + GPIO_DEEPSLEEP, #endif }; diff --git a/tasmota/xsns_60_GPS.ino b/tasmota/xsns_60_GPS.ino index db9343e2d..519caac20 100644 --- a/tasmota/xsns_60_GPS.ino +++ b/tasmota/xsns_60_GPS.ino @@ -1,5 +1,5 @@ /* - xsns_60_GPS.ino - GPS UBLOX support for Sonoff-Tasmota + xsns_60_GPS.ino - GPS UBLOX support for Tasmota Copyright (C) 2019 Theo Arends, Christian Baars and Adrian Scillato @@ -15,7 +15,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . +*/ +#ifdef USE_GPS +/*********************************************************************************************\ -------------------------------------------------------------------------------------------- Version Date Action Description -------------------------------------------------------------------------------------------- @@ -25,86 +28,85 @@ 0.9.0.0 20190817 started - further development by Christian Baars - https://github.com/Staars/Sonoff-Tasmota forked - from arendst/tasmota - https://github.com/arendst/Sonoff-Tasmota base - code base from arendst and - https://www.youtube.com/watch?v=TwhCX0c8Xe0 - -## GPS-driver for the Ublox-series 6-8 + +## GPS-driver for the Ublox-series 6-8 Driver is tested on a NEO-6m and a Beitian-220. Series 7 should work too. This adds only about 6kb to the program size, because the efficient UBX-protocol is used. These modules are quite cheap, starting at about 3.50€ for the NEO-6m. -## Features: +## Features: - get position and time data -- sets system time automatically and Settings.latitude and Settings.longitude via command +- sets system time automatically and Settings.latitude and Settings.longitude via command - can log postion data with timestamp to flash with a small memory footprint of only 12 Bytes per record -- constructs a GPX-file for download of this data -- Web-UI +- constructs a GPX-file for download of this data +- Web-UI - simplified NTP-server -- command interface - -## Usage: -The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To get more debug information compile it with option "DEBUG_TASMOTA_SENSOR". +- command interface - -## Commands: - -+ sensor60 0 +## Usage: +The serial pins are GPX_RX and GPS_TX, no further installation steps needed. To get more debug information compile it with option "DEBUG_TASMOTA_SENSOR". + + +## Commands: + ++ sensor60 0 write to all available sectors, then restart and overwrite the older ones - -+ sensor60 1 + ++ sensor60 1 write to all available sectors, then restart and overwrite the older ones - -+ sensor60 2 + ++ sensor60 2 filter out horizontal drift noise - -+ sensor60 3 + ++ sensor60 3 turn off noise filter - -+ sensor60 4 + ++ sensor60 4 start recording, new data will be appended - -+ sensor60 5 + ++ sensor60 5 start new recording, old data will lost - -+ sensor60 6 + ++ sensor60 6 stop recording, download link will be visible in Web-UI - -+ sensor60 7 + ++ sensor60 7 send mqtt on new postion + TELE -> consider to set TELE to a very high value - -+ sensor60 8 + ++ sensor60 8 only TELE message - -+ sensor60 9 + ++ sensor60 9 start NTP-server - -+ sensor60 10 + ++ sensor60 10 deactivate NTP-server - -+ sensor60 11 + ++ sensor60 11 force update of Tasmota-system-UTC with every new GPS-time-message - -+ sensor60 12 + ++ sensor60 12 do not update of Tasmota-system-UTC with every new GPS-time-message - -+ sensor60 13 - set latitude and longitude in settings - - - -## Rules examples for SSD1306 32x128 - - + ++ sensor60 13 + set latitude and longitude in settings + + + +## Rules examples for SSD1306 32x128 + + rule1 on tele-GPS#lat do DisplayText [s1p21c1l01f1]LAT: %value% endon on tele-GPS#lon do DisplayText [s1p21c1l2]LON: %value% endon on switch1#state==3 do sensor60 4 endon on switch1#state==2 do sensor60 6 endon rule2 on tele-GPS#int>9 do DisplayText [f0c9l4]I%value% endon on tele-GPS#int<10 do DisplayText [f0c9l4]I0%value% endon on tele-GPS#fil==1 do DisplayText [f0c18l4]F endon on tele-GPS#fil==0 do DisplayText [f0c18l4]N endon rule3 on tele-FLOG#sec do DisplayText [f0c1l4]SAV:%value% endon on tele-FLOG#rec==1 do DisplayText [f0c1l4]REC: endon on tele-FLOG#mode do DisplayText [f0c14l4]M%value% endon -*/ +\*********************************************************************************************/ -#ifdef USE_GPS +#define XSNS_60 60 #include "NTPServer.h" #include "NTPPacket.h" - /*********************************************************************************************\ * constants \*********************************************************************************************/ @@ -117,7 +119,6 @@ const char kUBXTypes[] PROGMEM = "UBX"; #define UBX_LAT_LON_THRESHOLD 1000 // filter out some noise of local drift - /********************************************************************************************\ | *globals \*********************************************************************************************/ @@ -152,13 +153,13 @@ const char UBLOX_INIT[] PROGMEM = { char UBX_name[4]; -struct UBX_t{ +struct UBX_t { const char UBX_HEADER[2] = { 0xB5, 0x62 }; // TODO: Check if we really save space here inside the struct const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; - struct entry_t{ + struct entry_t { int32_t lat; //raw sensor value int32_t lon; //raw sensor value uint32_t time; //local time from system (maybe provided by the sensor) @@ -200,7 +201,7 @@ struct UBX_t{ uint32_t ttff; uint32_t msss; }; - + struct NAV_TIME_UTC { uint8_t cls; uint8_t id; @@ -281,7 +282,9 @@ NtpServer timeServer(PortUdp); /*********************************************************************************************\ * helper function \*********************************************************************************************/ -void UBXcalcChecksum(char* CK, size_t msgSize) { + +void UBXcalcChecksum(char* CK, size_t msgSize) +{ memset(CK, 0, 2); for (int i = 0; i < msgSize; i++) { CK[0] += ((char*)(&UBX.Message))[i]; @@ -289,19 +292,22 @@ void UBXcalcChecksum(char* CK, size_t msgSize) { } } -boolean UBXcompareMsgHeader(const char* msgHeader) { +bool UBXcompareMsgHeader(const char* msgHeader) +{ char* ptr = (char*)(&UBX.Message); return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; } -void UBXinitCFG(void){ - for(uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { +void UBXinitCFG(void) +{ + for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); } DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); } -void UBXTriggerTele(void){ +void UBXTriggerTele(void) +{ mqtt_data[0] = '\0'; if (MqttShowSensor()) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); @@ -313,23 +319,22 @@ void UBXTriggerTele(void){ /********************************************************************************************/ - void UBXDetect(void) { if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, 96); // 64 byte buffer is NOT enough if (UBXSerial->begin(9600)) { DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); - if (UBXSerial->hardwareSerial()) { - ClaimSerial(); + if (UBXSerial->hardwareSerial()) { + ClaimSerial(); DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); - } + } } } UBXinitCFG(); // turn of NMEA, only use "our" UBX-messages #ifdef USE_FLOG - if(!Flog){ + if (!Flog) { Flog = new FLOG; // init Flash Log Flog->init(); } @@ -340,7 +345,8 @@ void UBXDetect(void) UBXTriggerTele(); // ... once at after start } -uint32_t UBXprocessGPS() { +uint32_t UBXprocessGPS() +{ static uint32_t fpos = 0; static char checksum[2]; static uint8_t currentMsgType = MT_NONE; @@ -350,27 +356,27 @@ uint32_t UBXprocessGPS() { uint32_t data_bytes = 0; while ( UBXSerial->available() ) { data_bytes++; - byte c = UBXSerial->read(); + byte c = UBXSerial->read(); if ( fpos < 2 ) { // For the first two bytes we are simply looking for a match with the UBX header bytes (0xB5,0x62) - if ( c == UBX.UBX_HEADER[fpos] ) + if ( c == UBX.UBX_HEADER[fpos] ) { fpos++; - else + } else { fpos = 0; // Reset to beginning state. - } - else { + } + } else { // If we come here then fpos >= 2, which means we have found a match with the UBX_HEADER // and we are now reading in the bytes that make up the payload. - + // Place the incoming byte into the ubxMessage struct. The position is fpos-2 because // the struct does not include the initial two-byte header (UBX_HEADER). - if ( (fpos-2) < payloadSize ) + if ( (fpos-2) < payloadSize ) { ((char*)(&UBX.Message))[fpos-2] = c; - + } fpos++; - + if ( fpos == 4 ) { - // We have just received the second byte of the message type header, + // We have just received the second byte of the message type header, // so now we can check to see what kind of message it is. if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { currentMsgType = MT_NAV_POSLLH; @@ -395,7 +401,7 @@ uint32_t UBXprocessGPS() { } if ( fpos == (payloadSize+2) ) { - // All payload bytes have now been received, so we can calculate the + // All payload bytes have now been received, so we can calculate the // expected checksum value to compare with the next two incoming bytes. UBXcalcChecksum(checksum, payloadSize); } @@ -404,7 +410,7 @@ uint32_t UBXprocessGPS() { // Does it match the first byte of the checksum we calculated? if ( c != checksum[0] ) { // Checksum doesn't match, reset to beginning state and try again. - fpos = 0; + fpos = 0; } } else if ( fpos == (payloadSize+4) ) { @@ -417,18 +423,18 @@ uint32_t UBXprocessGPS() { } } else if ( fpos > (payloadSize+4) ) { - // We have now read more bytes than both the expected payload and checksum + // We have now read more bytes than both the expected payload and checksum // together, so something went wrong. Reset to beginning state and try again. fpos = 0; } } } // DEBUG_SENSOR_LOG(PSTR("UBX: got none or unknown Message")); - if(data_bytes!=0) { - UBX.state.non_empty_loops++; - DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); + if (data_bytes!=0) { + UBX.state.non_empty_loops++; + DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); } else { - UBX.state.non_empty_loops = 0; // now a hidden GPS-device reset is unlikely + UBX.state.non_empty_loops = 0; // now a hidden GPS-device reset is unlikely } return MT_NONE; } @@ -436,19 +442,22 @@ uint32_t UBXprocessGPS() { /********************************************************************************************\ | * callback functions for the download \*********************************************************************************************/ + #ifdef USE_FLOG -void UBXsendHeader(void) { +void UBXsendHeader(void) +{ WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); WSSend(200, CT_STREAM, F( - "\r\n" + "\r\n" "\r\n" "\r\n\r\n")); } -void UBXsendRecord(uint8_t *buf){ +void UBXsendRecord(uint8_t *buf) +{ char record[100]; char stime[32]; UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; @@ -462,27 +471,32 @@ void UBXsendRecord(uint8_t *buf){ WebServer->sendContent_P(record); } -void UBXsendFooter(void){ +void UBXsendFooter(void) +{ WebServer->sendContent(F("\n\n")); WebServer->sendContent(""); Rtc.user_time_entry = false; // we have blocked the main loop and want a new valid time } /********************************************************************************************/ -void UBXsendFile(void){ + +void UBXsendFile(void) +{ if (!HttpCheckPriviledgedAccess()) { return; } Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); } #endif //USE_FLOG + /********************************************************************************************/ -void UBXSetRate(uint16_t interval){ +void UBXSetRate(uint16_t interval) +{ UBX.Message.cfgRate.cls = 0x06; UBX.Message.cfgRate.id = 0x08; UBX.Message.cfgRate.len = 6; uint32_t measRate = (1000*(uint32_t)interval); //seconds to milliseconds if (measRate > 0xffff) { - measRate = 0xffff; // max. 65535 ms interval + measRate = 0xffff; // max. 65535 ms interval } UBX.Message.cfgRate.measRate = (uint16_t)measRate; UBX.Message.cfgRate.navRate = 1; @@ -491,15 +505,15 @@ void UBXSetRate(uint16_t interval){ DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); UBXSerial->write(UBX.UBX_HEADER[0]); UBXSerial->write(UBX.UBX_HEADER[1]); - for(uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); } - UBX.state.log_interval = 10*interval; + UBX.state.log_interval = 10*interval; } - -void UBXSelectMode(uint16_t mode){ +void UBXSelectMode(uint16_t mode) +{ DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); switch(mode){ #ifdef USE_FLOG @@ -513,7 +527,7 @@ void UBXSelectMode(uint16_t mode){ UBX.mode.filter_noise = true; // filter out horizontal drift noise, TODO: find useful values break; case 3: - UBX.mode.filter_noise = false; + UBX.mode.filter_noise = false; break; case 4: Flog->startRecording(true); @@ -529,7 +543,7 @@ void UBXSelectMode(uint16_t mode){ } AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); break; -#endif //USE_FLOG +#endif //USE_FLOG case 7: UBX.mode.send_when_new = 1; // send mqtt on new postion + TELE -> consider to set TELE to a very high value break; @@ -537,7 +551,7 @@ void UBXSelectMode(uint16_t mode){ UBX.mode.send_when_new = 0; // only TELE break; case 9: - if (timeServer.beginListening()){ + if (timeServer.beginListening()) { UBX.mode.runningNTP = true; } break; @@ -555,77 +569,80 @@ void UBXSelectMode(uint16_t mode){ Settings.longitude = UBX.state.last_lon; break; default: - if(mode>1000 && mode <1066) { + if (mode>1000 && mode <1066) { // UBXSetRate(mode-1000); // min. 1001 = 0.001 Hz, but will be converted to 1/65535 anyway ~0.015 Hz, max. 2000 = 1.000 Hz - UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65 + UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65 } break; } UBX.mode.send_UI_only = true; UBXTriggerTele(); } + /********************************************************************************************/ -bool UBXHandlePOSLLH(){ - DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); - if(UBX.state.gpsFix>1){ - if(UBX.mode.filter_noise){ - if((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat1) { + if (UBX.mode.filter_noise) { + if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat6){ // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz) - UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!! + if (UBX.state.non_empty_loops>6) { // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz) + UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!! AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); UBXSerial->flush(); UBX.state.non_empty_loops = 0; @@ -645,7 +662,7 @@ void UBXLoop(void) { static uint16_t counter; //count up every 100 msec static bool new_position; - + uint32_t msgType = UBXprocessGPS(); switch(msgType){ @@ -664,8 +681,8 @@ void UBXLoop(void) } #ifdef USE_FLOG - if(counter>UBX.state.log_interval){ - if(Flog->recording && new_position){ + if (counter>UBX.state.log_interval) { + if (Flog->recording && new_position) { UBX.rec_buffer.values.time = Rtc.local_time; Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); counter = 0; @@ -673,7 +690,7 @@ void UBXLoop(void) } #endif // USE_FLOG -counter++; + counter++; } /********************************************************************************************/ @@ -716,7 +733,7 @@ counter++; const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; // const char UBX_GOOGLE_MAPS[] =""; - + #endif // USE_WEBSERVER @@ -724,23 +741,22 @@ counter++; void UBXShow(bool json) { - char lat[12]; - char lon[12]; - char height[12]; - char hAcc[12]; - char vAcc[12]; - dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); - dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); - dtostrfd((double)UBX.state.last_height/1000.0f,3,height); - dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); - dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); + char lat[12]; + char lon[12]; + char height[12]; + char hAcc[12]; + char vAcc[12]; + dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); + dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); + dtostrfd((double)UBX.state.last_height/1000.0f,3,height); + dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); + dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); - if (json) - { + if (json) { ResponseAppend_P(PSTR(",\"GPS\":{")); - if(UBX.mode.send_UI_only){ + if (UBX.mode.send_UI_only) { uint32_t i = UBX.state.log_interval / 10; - ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"),UBX.mode.filter_noise, i); + ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); } else { ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"height\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, height, hAcc, vAcc); } @@ -755,37 +771,37 @@ void UBXShow(bool json) #ifdef DEBUG_TASMOTA_SENSOR #ifdef USE_FLOG WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); - if(Flog->recording){ + if (Flog->recording) { WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); } #endif //USE_FLOG #endif // DEBUG_TASMOTA_SENSOR #ifdef USE_FLOG - if(Flog->ready){ + if (Flog->ready) { WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); } - if(!Flog->recording && Flog->found_saved_data){ + if (!Flog->recording && Flog->found_saved_data) { WSContentSend_P(HTTP_BTN_FLOG_DL); } #endif //USE_FLOG - if(UBX.mode.runningNTP){ + if (UBX.mode.runningNTP) { WSContentSend_P(HTTP_SNS_NTPSERVER); } #endif // USE_WEBSERVER } } - /*********************************************************************************************\ * check the UBX commands \*********************************************************************************************/ -bool UBXCmd(void) { +bool UBXCmd(void) +{ bool serviced = true; - if (XdrvMailbox.data_len > 0) { - UBXSelectMode(XdrvMailbox.payload); - Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); - } + if (XdrvMailbox.data_len > 0) { + UBXSelectMode(XdrvMailbox.payload); + Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } return serviced; } @@ -793,28 +809,26 @@ bool UBXCmd(void) { * Interface \*********************************************************************************************/ -#define XSNS_60 60 - bool Xsns60(uint8_t function) { bool result = false; - if (true) { + if (true) { switch (function) { case FUNC_INIT: UBXDetect(); break; case FUNC_COMMAND_SENSOR: - if (XSNS_60 == XdrvMailbox.index){ + if (XSNS_60 == XdrvMailbox.index) { result = UBXCmd(); - } + } break; case FUNC_EVERY_50_MSECOND: UBXTimeServer(); break; case FUNC_EVERY_100_MSECOND: #ifdef USE_FLOG - if(!Flog->running_download) + if (!Flog->running_download) #endif //USE_FLOG { UBXLoop(); @@ -831,7 +845,7 @@ bool Xsns60(uint8_t function) #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: #ifdef USE_FLOG - if(!Flog->running_download) + if (!Flog->running_download) #endif //USE_FLOG { UBXShow(0); diff --git a/tools/decode-status.py b/tools/decode-status.py index e6751ae92..492c300fa 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -131,7 +131,8 @@ a_setoption = [[ "GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)", "Enable incrementing bootcount when deepsleep is enabled", "Do not power off if slider moved to far left", - "","", + "Bypass Compatibility check", + "", "Enable shutter support", "Invert PCF8574 ports" ],[ @@ -187,7 +188,7 @@ a_features = [[ "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", - "USE_DHT12","","","", + "USE_DHT12","","USE_GPS","", "","","","", "","","","" ]] From fd0155a5b1153cbb45f4579f0822a30927cf5f9f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 23 Dec 2019 15:53:43 +0100 Subject: [PATCH 139/559] Update supported sensor list --- BUILDS.md | 3 +++ tasmota/tasmota_post.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/BUILDS.md b/BUILDS.md index 3b311a6eb..5c897746a 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -119,6 +119,9 @@ | USE_MP3_PLAYER | - | - | - | - | x | - | - | | USE_AZ7798 | - | - | - | - | - | - | - | | USE_PN532_HSU | - | - | - | - | x | - | - | +| USE_RDM6300 | - | - | - | - | x | - | - | +| USE_IBEACON | - | - | - | - | x | - | - | +| USE_GPS | - | - | - | - | - | - | - | | USE_ZIGBEE | - | - | - | - | - | - | - | | | | | | | | | | | USE_IR_REMOTE | - | - | x | x | x | x | x | diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index c54adfe82..c9f8396fe 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -180,6 +180,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) #define USE_RDM6300 // Add support for RDM6300 125kHz RFID Reader (+0k8) #define USE_IBEACON // Add support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +//#define USE_GPS // Add support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) #define USE_ENERGY_SENSOR // Add energy sensors (-14k code) #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) @@ -374,6 +375,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) #undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) #undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +#undef USE_GPS // Disable support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) //#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -462,6 +464,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) #undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) #undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +#undef USE_GPS // Disable support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) //#undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_PZEM004T // Disable PZEM004T energy sensor @@ -571,6 +574,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) #undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8) #undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) +#undef USE_GPS // Disable support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) #undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_PZEM004T // Disable PZEM004T energy sensor From a10b1998085d340acc7fcc890bf1d197a9186702 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 23 Dec 2019 15:59:00 +0100 Subject: [PATCH 140/559] Version bump to 8.0.0.2 --- RELEASENOTES.md | 2 +- tasmota/CHANGELOG.md | 4 ++++ tasmota/tasmota_version.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 237568fc5..6033aa5df 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -48,7 +48,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.0.0.1 +### Version 8.0.0.2 - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 33617755b..73e035ff2 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 8.0.0.2 20191223 + +- Changed Settings variable namings + ### 8.0.0.1 20191221 - Change Settings text handling allowing variable length text within a total text pool of 699 characters diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index be2cfafe2..e69d4fd39 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08000001; +const uint32_t VERSION = 0x08000002; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; From 749960533f45056061e195c175b70eb7a9cd5d15 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Mon, 23 Dec 2019 16:53:54 +0100 Subject: [PATCH 141/559] Add Zigbee better support for Xiaomi Double Switch and Xiaomi Vibration sensor --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 1 + tasmota/xdrv_23_zigbee_3_devices.ino | 95 ++++++++++++++++++----- tasmota/xdrv_23_zigbee_5_converters.ino | 74 +++++++++++------- tasmota/xdrv_23_zigbee_7_statemachine.ino | 1 + tasmota/xdrv_23_zigbee_8_parsers.ino | 42 +++++++--- tasmota/xdrv_23_zigbee_9_impl.ino | 25 +++++- 7 files changed, 182 insertions(+), 57 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 73e035ff2..cb2bfe0c5 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.0.0.2 20191223 - Changed Settings variable namings +- Add Zigbee better support for Xiaomi Double Switch and Xiaomi Vibration sensor ### 8.0.0.1 20191221 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 1844dd44b..68a19f75e 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -468,6 +468,7 @@ #define D_CMND_ZIGBEE_STATUS "ZigbeeStatus" #define D_CMND_ZIGBEE_RESET "ZigbeeReset" #define D_JSON_ZIGBEE_CC2530 "CC2530" +#define D_CMND_ZIGBEEZNPRECEIVE "ZigbeeZNPReceive" // only for debug #define D_CMND_ZIGBEEZNPSEND "ZigbeeZNPSend" #define D_JSON_ZIGBEE_STATE "ZigbeeState" #define D_JSON_ZIGBEEZNPRECEIVED "ZigbeeZNPReceived" diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index c42f4b603..1ec18d3e1 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -91,6 +91,8 @@ public: void jsonClear(uint16_t shortaddr); void jsonAppend(uint16_t shortaddr, JsonObject &values); const JsonObject *jsonGet(uint16_t shortaddr); + const void jsonPublish(uint16_t shortaddr); // publish the json message and clear buffer + bool jsonIsConflict(uint16_t shortaddr, const JsonObject &values); private: std::vector _devices = {}; @@ -419,6 +421,67 @@ void Z_Devices::jsonClear(uint16_t shortaddr) { device.json_buffer->clear(); } +void CopyJsonVariant(JsonObject &to, const String &key, const JsonVariant &val) { + to.remove(key); // force remove to have metadata like LinkQuality at the end + + if (val.is()) { + String sval = val.as(); // force a copy of the String value + to.set(key, sval); + } else if (val.is()) { + JsonArray &nested_arr = to.createNestedArray(key); + CopyJsonArray(nested_arr, val.as()); + } else if (val.is()) { + JsonObject &nested_obj = to.createNestedObject(key); + CopyJsonObject(nested_obj, val.as()); + } else { + to.set(key, val); + } +} + +void CopyJsonArray(JsonArray &to, const JsonArray &arr) { + for (auto v : arr) { + if (v.is()) { + String sval = v.as(); // force a copy of the String value + to.add(sval); + } else if (v.is()) { + } else if (v.is()) { + } else { + to.add(v); + } + } +} + +void CopyJsonObject(JsonObject &to, const JsonObject &from) { + for (auto kv : from) { + String key_string = kv.key; + JsonVariant &val = kv.value; + + CopyJsonVariant(to, key_string, val); + } +} + +// does the new payload conflicts with the existing payload, i.e. values would be overwritten +bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const JsonObject &values) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return false; } // don't crash if not found + if (&values == nullptr) { return false; } + + if (nullptr == device.json) { + return false; // if no previous value, no conflict + } + + for (auto kv : values) { + String key_string = kv.key; + + if (strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_LINKQUALITY))) { // exception = ignore duplicates for LinkQuality + if (device.json->containsKey(kv.key)) { + return true; // conflict! + } + } + } + return false; +} + void Z_Devices::jsonAppend(uint16_t shortaddr, JsonObject &values) { Z_Device & device = getShortAddr(shortaddr); if (&device == nullptr) { return; } // don't crash if not found @@ -428,24 +491,7 @@ void Z_Devices::jsonAppend(uint16_t shortaddr, JsonObject &values) { device.json = &(device.json_buffer->createObject()); } // copy all values from 'values' to 'json' - for (auto kv : values) { - String key_string = kv.key; - const char * key = key_string.c_str(); - JsonVariant &val = kv.value; - - device.json->remove(key_string); // force remove to have metadata like LinkQuality at the end - - if (val.is()) { - String sval = val.as(); // force a copy of the String value - device.json->set(key_string, sval); - } else if (val.is()) { - // todo - } else if (val.is()) { - // todo - } else { - device.json->set(key_string, kv.value); - } - } + CopyJsonObject(*device.json, values); } const JsonObject *Z_Devices::jsonGet(uint16_t shortaddr) { @@ -454,6 +500,19 @@ const JsonObject *Z_Devices::jsonGet(uint16_t shortaddr) { return device.json; } +const void Z_Devices::jsonPublish(uint16_t shortaddr) { + const JsonObject *json = zigbee_devices.jsonGet(shortaddr); + if (json == nullptr) { return; } // don't crash if not found + + String msg = ""; + json->printTo(msg); + zigbee_devices.jsonClear(shortaddr); + Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); +} + + // Dump the internal memory of Zigbee devices // Mode = 1: simple dump of devices addresses and names // Mode = 2: Mode 1 + also dump the endpoints, profiles and clusters diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 49d63808e..1423c53f1 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -100,6 +100,7 @@ public: return _frame_control.b.frame_type & 1; } + static void generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len); void parseRawAttributes(JsonObject& json, uint8_t offset = 0); void parseReadAttributes(JsonObject& json, uint8_t offset = 0); void parseClusterSpecificCommand(JsonObject& json, uint8_t offset = 0); @@ -290,17 +291,20 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer bool parse_as_string = true; uint32_t len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); // len is 8 or 16 bits i += (attrtype <= 0x42) ? 1 : 2; // increment pointer + if (i + len > buf.len()) { // make sure we don't get past the buffer + len = buf.len() - i; + } // check if we can safely use a string if ((0x41 == attrtype) || (0x43 == attrtype)) { parse_as_string = false; } - else { - for (uint32_t j = 0; j < len; j++) { - if (0x00 == buf.get8(i+j)) { - parse_as_string = false; - break; - } - } - } + // else { + // for (uint32_t j = 0; j < len; j++) { + // if (0x00 == buf.get8(i+j)) { + // parse_as_string = false; + // break; + // } + // } + // } if (parse_as_string) { char str[len+1]; @@ -409,19 +413,28 @@ uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer return i - offset; // how much have we increased the index } +// Generate an attribute name based on cluster number, attribute, and suffix if duplicates +void ZCLFrame::generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len) { + uint32_t suffix = 1; + + snprintf_P(key, key_len, PSTR("%04X/%04X"), cluster, attr); + while (json.containsKey(key)) { + suffix++; + snprintf_P(key, key_len, PSTR("%04X/%04X+%d"), cluster, attr, suffix); // add "0008/0001+2" suffix if duplicate + } +} // First pass, parse all attributes in their native format void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { uint32_t i = offset; uint32_t len = _payload.len(); - while (len - i >= 3) { + while (len >= i + 3) { uint16_t attrid = _payload.get16(i); i += 2; char key[16]; - snprintf_P(key, sizeof(key), PSTR("%04X/%04X"), - _cluster_id, attrid); + generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); // exception for Xiaomi lumi.weather - specific field to be treated as octet and not char if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { @@ -445,8 +458,7 @@ void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { if (0 == status) { char key[16]; - snprintf_P(key, sizeof(key), PSTR("%04X/%04X"), - _cluster_id, attrid); + generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); i += parseSingleAttribute(json, key, _payload, i, len); } @@ -472,7 +484,7 @@ void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { // return value: // 0 = keep initial value // 1 = remove initial value -typedef int32_t (*Z_AttrConverter)(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper* new_name, uint16_t cluster, uint16_t attr); +typedef int32_t (*Z_AttrConverter)(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); typedef struct Z_AttributeConverter { uint16_t cluster; uint16_t attribute; @@ -775,13 +787,13 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { // ====================================================================== // Record Manuf -int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { json[new_name] = value; zigbee_devices.setManufId(shortaddr, value.as()); return 1; } // -int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { json[new_name] = value; zigbee_devices.setModelId(shortaddr, value.as()); return 1; @@ -789,29 +801,29 @@ int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& j // ====================================================================== // Remove attribute -int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { return 1; // remove original key } // Copy value as-is -int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { json[new_name] = value; return 1; // remove original key } // Add pressure unit -int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { json[new_name] = F(D_UNIT_PRESSURE); return 0; // keep original key } // Convert int to float and divide by 100 -int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { json[new_name] = ((float)value) / 100.0f; return 1; // remove original key } // Convert int to float and divide by 10 -int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { json[new_name] = ((float)value) / 10.0f; return 1; // remove original key } @@ -825,7 +837,7 @@ int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpo } // Aqara Vibration Sensor - special proprietary attributes -int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { //json[new_name] = value; switch (attr) { case 0x0055: @@ -879,7 +891,7 @@ int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObje return 1; // remove original key } -int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const __FlashStringHelper *new_name, uint16_t cluster, uint16_t attr) { +int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { String hex = value; SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); uint32_t i = 0; @@ -925,11 +937,19 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { String key_string = kv.key; const char * key = key_string.c_str(); JsonVariant& value = kv.value; - // Check that format looks like "CCCC/AAAA" + // Check that format looks like "CCCC/AAAA" or "CCCC/AAAA+d" char * delimiter = strchr(key, '/'); + char * delimiter2 = strchr(key, '+'); if (delimiter) { + uint16_t attribute; + uint16_t suffix = 1; uint16_t cluster = strtoul(key, &delimiter, 16); - uint16_t attribute = strtoul(delimiter+1, nullptr, 16); + if (!delimiter2) { + attribute = strtoul(delimiter+1, nullptr, 16); + } else { + attribute = strtoul(delimiter+1, &delimiter2, 16); + suffix = strtoul(delimiter2+1, nullptr, 10); + } // Iterate on filter for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { @@ -939,7 +959,9 @@ void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { if ((conv_cluster == cluster) && ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { - int32_t drop = (*converter->func)(this, shortaddr, json, key, value, (const __FlashStringHelper*) converter->name, conv_cluster, conv_attribute); + String new_name_str = converter->name; + if (suffix > 1) { new_name_str += suffix; } // append suffix number + int32_t drop = (*converter->func)(this, shortaddr, json, key, value, new_name_str, conv_cluster, conv_attribute); if (drop) { json.remove(key); } diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index d4f3e459f..261a4ac6a 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -32,6 +32,7 @@ const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; // Device announces its const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; // Node descriptor const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; // Endpoints descriptor const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; // Simple Descriptor (clusters) +const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; // Device announces its address const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 89320b117..fcfeb06a7 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -357,6 +357,28 @@ int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { return -1; } +// 45CA +int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { + Z_ShortAddress srcAddr = buf.get16(2); + Z_IEEEAddress ieeeAddr = buf.get64(4); + Z_ShortAddress parentNw = buf.get16(12); + + zigbee_devices.updateDevice(srcAddr, ieeeAddr); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"ParentNetwork\":\"0x%04X\"}}"), + ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + //Z_SendActiveEpReq(srcAddr); + return -1; +} + // Aqara Occupancy behavior: the Aqara device only sends Occupancy: true events every 60 seconds. // Here we add a timer so if we don't receive a Occupancy event for 90 seconds, we send Occupancy:false const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; // 90 s @@ -378,16 +400,11 @@ void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, c int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { const JsonObject *json = zigbee_devices.jsonGet(shortaddr); if (json == nullptr) { return 0; } // don't crash if not found - // Post-provess for Aqara Presence Senson Z_AqaraOccupancy(shortaddr, cluster, endpoint, json); - String msg = ""; - json->printTo(msg); - zigbee_devices.jsonClear(shortaddr); - Response_P(PSTR("{\"" D_CMND_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); + zigbee_devices.jsonPublish(shortaddr); + return 1; } int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { @@ -438,8 +455,13 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { if (defer_attributes) { // Prepare for publish - zigbee_devices.jsonAppend(srcaddr, json); - zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); + if (zigbee_devices.jsonIsConflict(srcaddr, json)) { + // there is conflicting values, force a publish of the previous message now and don't coalesce + zigbee_devices.jsonPublish(srcaddr); + } else { + zigbee_devices.jsonAppend(srcaddr, json); + zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); + } } else { // Publish immediately msg = ""; @@ -459,6 +481,7 @@ typedef struct Z_Dispatcher { // Filters for ZCL frames ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481 ZBM(AREQ_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) // 45C1 +ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) // 45CA ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) // 45CB ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4585 ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 @@ -466,6 +489,7 @@ ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, { AREQ_END_DEVICE_ANNCE_IND, &Z_ReceiveEndDeviceAnnonce }, + { AREQ_END_DEVICE_TC_DEV_IND, &Z_ReceiveTCDevInd }, { AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus }, { AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc }, { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index b3681f00e..59cf382b0 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -31,12 +31,14 @@ TasmotaSerial *ZigbeeSerial = nullptr; const char kZigbeeCommands[] PROGMEM = "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" - D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ ; + D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE + ; void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZigbeeZNPSend, &CmndZigbeePermitJoin, &CmndZigbeeStatus, &CmndZigbeeReset, &CmndZigbeeSend, - &CmndZigbeeProbe, &CmndZigbeeRead }; + &CmndZigbeeProbe, &CmndZigbeeRead, &CmndZigbeeZNPReceive + }; int32_t ZigbeeProcessInput(class SBuffer &buf) { if (!zigbee.state_machine) { return -1; } // if state machine is stopped, send 'ignore' message @@ -268,7 +270,7 @@ void CmndZigbeeStatus(void) { } } -void CmndZigbeeZNPSend(void) +void CmndZigbeeZNPSendOrReceive(bool send) { if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { uint8_t code; @@ -286,11 +288,26 @@ void CmndZigbeeZNPSend(void) size -= 2; codes += 2; } - ZigbeeZNPSend(buf.getBuffer(), buf.len()); + if (send) { + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + } else { + ZigbeeProcessInput(buf); + } } ResponseCmndDone(); } +// For debug purposes only, simulates a message received +void CmndZigbeeZNPReceive(void) +{ + CmndZigbeeZNPSendOrReceive(false); +} + +void CmndZigbeeZNPSend(void) +{ + CmndZigbeeZNPSendOrReceive(true); +} + void ZigbeeZNPSend(const uint8_t *msg, size_t len) { if ((len < 2) || (len > 252)) { // abort, message cannot be less than 2 bytes for CMD1 and CMD2 From 1f20c36ce44919c2f3d44c0f40eeaf7a326549e8 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 23 Dec 2019 17:41:36 +0100 Subject: [PATCH 142/559] Update migration info --- README.md | 2 ++ RELEASENOTES.md | 3 +++ 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index ea1d1c23c..f3412a9c7 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,9 @@ See [wiki migration path](https://tasmota.github.io/docs/#/Upgrading?id=migratio 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** 5. Migrate to **Tasmota 7.x** + --- Major change in parameter storage layout --- + 6. Migrate to **Tasmota 8.1** 7. Migrate to **Tasmota 8.x** diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6033aa5df..88442445a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -11,7 +11,9 @@ See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-pat 3. Migrate to **Sonoff-Tasmota 5.14** 4. Migrate to **Sonoff-Tasmota 6.x** 5. Migrate to **Tasmota 7.x** + --- Major change in parameter storage layout --- + 6. Migrate to **Tasmota 8.1** 7. Migrate to **Tasmota 8.x** @@ -56,4 +58,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for max 150 characters in most command parameter strings (#3686, #4754) - Add support for GPS as NTP server by Christian Baars and Adrian Scillato - Add Zigbee coalesce sensor attributes into a single message +- Add Zigbee better support for Xiaomi Double Switch and Xiaomi Vibration sensor - Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 From c1f30da81ee71fcfb9b293997fb4d4b1dc75fe7f Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Mon, 23 Dec 2019 22:22:29 -0300 Subject: [PATCH 143/559] Add Moisture Sensor --- tasmota/i18n.h | 4 +++ tasmota/language/bg-BG.h | 1 + tasmota/language/cs-CZ.h | 1 + tasmota/language/de-DE.h | 1 + tasmota/language/el-GR.h | 1 + tasmota/language/en-GB.h | 1 + tasmota/language/es-ES.h | 1 + tasmota/language/fr-FR.h | 1 + tasmota/language/he-HE.h | 1 + tasmota/language/hu-HU.h | 1 + tasmota/language/it-IT.h | 1 + tasmota/language/ko-KO.h | 1 + tasmota/language/nl-NL.h | 1 + tasmota/language/pl-PL.h | 1 + tasmota/language/pt-BR.h | 1 + tasmota/language/pt-PT.h | 1 + tasmota/language/ru-RU.h | 1 + tasmota/language/sk-SK.h | 1 + tasmota/language/sv-SE.h | 1 + tasmota/language/tr-TR.h | 1 + tasmota/language/uk-UK.h | 1 + tasmota/language/zh-CN.h | 1 + tasmota/language/zh-TW.h | 1 + tasmota/tasmota_template.h | 2 ++ tasmota/xsns_02_analog.ino | 51 +++++++++++++++++++++++++++++++++----- tasmota/xsns_48_chirp.ino | 2 +- 26 files changed, 74 insertions(+), 7 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 68a19f75e..24b0e1f19 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -99,6 +99,7 @@ #define D_JSON_MEMORY_ERROR "Memory error" #define D_JSON_MINIMAL "minimal" #define D_JSON_MODEL "Model" +#define D_JSON_MOISTURE "Moisture" #define D_JSON_MQTT_COUNT "MqttCount" #define D_JSON_NO "No" #define D_JSON_NOISE "Noise" @@ -589,6 +590,7 @@ const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; const char JSON_SNS_ILLUMINANCE[] PROGMEM = ",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}"; +const char JSON_SNS_MOISTURE[] PROGMEM = ",\"%s\":{\"" D_JSON_MOISTURE "\":%d}"; const char JSON_SNS_GNGPM[] PROGMEM = ",\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}"; @@ -618,6 +620,8 @@ const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MIL const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = const char HTTP_SNS_GALLONS[] PROGMEM = "{s}%s " D_TOTAL_USAGE "{m}%s " D_UNIT_GALLONS " {e}"; // {s} = , {m} = , {e} = const char HTTP_SNS_GPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_GALLONS_PER_MIN" {e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_MOISTURE[] PROGMEM = "{s}%s " D_MOISTURE "{m}%d %%{e}"; // {s} = , {m} = , {e} = + const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 12937ca6c..f2ac56402 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -113,6 +113,7 @@ #define D_LIGHT "Светлина" #define D_LWT "LWT" #define D_MODULE "Модул" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "неколкократно натискане" #define D_NOISE "Шум" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index a297d7063..272e2c5ca 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -113,6 +113,7 @@ #define D_LIGHT "Světlo" #define D_LWT "LWT" #define D_MODULE "Modul" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "několikeré-stisknutí" #define D_NOISE "Hluk" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 663628cd1..89d36103d 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -113,6 +113,7 @@ #define D_LIGHT "Licht" #define D_LWT "LWT" #define D_MODULE "Modul" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "Mehrfachdruck" #define D_NOISE "Lautstärke" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index d491d31a2..2b1e4748c 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -113,6 +113,7 @@ #define D_LIGHT "Φως" #define D_LWT "LWT" #define D_MODULE "Μονάδα" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "ανίχνευση για πολλαπλά πατήματα" #define D_NOISE "Θόρυβος" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 8ec56b16c..ab7f90cf8 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -113,6 +113,7 @@ #define D_LIGHT "Light" #define D_LWT "LWT" #define D_MODULE "Module" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-press" #define D_NOISE "Noise" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 42f0991a6..e41b4cb32 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -113,6 +113,7 @@ #define D_LIGHT "Luz" #define D_LWT "LWT" #define D_MODULE "Módulo" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-press" #define D_NOISE "Ruido" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index a0e34da3e..840421ff3 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -113,6 +113,7 @@ #define D_LIGHT "Lumière" #define D_LWT "LWT" #define D_MODULE "Module" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-pression" #define D_NOISE "Bruit" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index d31d5380c..9e26a6c5e 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -113,6 +113,7 @@ #define D_LIGHT "אור" #define D_LWT "LWT" #define D_MODULE "מודול" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "לחיצה מרובה" #define D_NOISE "רעש" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 7cde76cbb..b7f33a549 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -113,6 +113,7 @@ #define D_LIGHT "Fény" #define D_LWT "LWT" #define D_MODULE "Modul" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "több lenyomás" #define D_NOISE "Zaj" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 7b6d7eed0..d3c55579a 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -113,6 +113,7 @@ #define D_LIGHT "Luce" #define D_LWT "LWT" #define D_MODULE "Modulo" +#define D_MOISTURE "Umidità" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-pressione" #define D_NOISE "Rumore" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 5d15554de..a6c2088a1 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -113,6 +113,7 @@ #define D_LIGHT "밝게" #define D_LWT "LWT" #define D_MODULE "모듈" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-press" #define D_NOISE "소음" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index ec352f3e6..8fb492399 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -113,6 +113,7 @@ #define D_LIGHT "Licht" #define D_LWT "LWT" #define D_MODULE "Module" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "meervoudig" #define D_NOISE "Lawaai" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 9c547e29b..58168516d 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -113,6 +113,7 @@ #define D_LIGHT "Światło" #define D_LWT "LWT" #define D_MODULE "Moduł" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "Wielokrotne naciśnięcie" #define D_NOISE "Szum" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 7a8db0dca..0c9891323 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -113,6 +113,7 @@ #define D_LIGHT "Luz" #define D_LWT "LWT" #define D_MODULE "Módulo" +#define D_MOISTURE "Umidade" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-pressão" #define D_NOISE "Ruído" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 8b9868bd8..210ef8e29 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -113,6 +113,7 @@ #define D_LIGHT "Luz" #define D_LWT "LWT" #define D_MODULE "Módulo" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-pressão" #define D_NOISE "Ruído" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 610af6f3f..6696e0e48 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -113,6 +113,7 @@ #define D_LIGHT "Свет" #define D_LWT "LWT" #define D_MODULE "Модуль" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "многократное нажатие" #define D_NOISE "Шум" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index 9aa428b69..21120179a 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -113,6 +113,7 @@ #define D_LIGHT "Svetlo" #define D_LWT "LWT" #define D_MODULE "Modul" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-stlačenie" #define D_NOISE "Hluk" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index 1a70704ee..117fb40ed 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -113,6 +113,7 @@ #define D_LIGHT "Ljus" #define D_LWT "LWT" #define D_MODULE "Modul" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "fler tryck" #define D_NOISE "Oväsen" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 6e9d9b9bf..9874688da 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -113,6 +113,7 @@ #define D_LIGHT "Işık" #define D_LWT "LWT" #define D_MODULE "Modül" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-press" #define D_NOISE "Noise" diff --git a/tasmota/language/uk-UK.h b/tasmota/language/uk-UK.h index d4862c3c8..dbf58fe35 100644 --- a/tasmota/language/uk-UK.h +++ b/tasmota/language/uk-UK.h @@ -113,6 +113,7 @@ #define D_LIGHT "Світло" #define D_LWT "LWT" #define D_MODULE "Модуль" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "Багаторазове натискання" #define D_NOISE "Шум" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 886a7c918..7700e7e78 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -113,6 +113,7 @@ #define D_LIGHT "灯" #define D_LWT "LWT" #define D_MODULE "模块" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "多次按键" #define D_NOISE "嘈杂" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 61f82fb4c..34bb68e3d 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -113,6 +113,7 @@ #define D_LIGHT "燈" #define D_LWT "LWT" #define D_MODULE "模組" +#define D_MOISTURE "Moisture" #define D_MQTT "MQTT" #define D_MULTI_PRESS "多次按鍵" #define D_NOISE "雜訊" diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 3985884ef..6b936d14a 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -313,6 +313,7 @@ enum UserSelectableAdc0 { ADC0_BUTTON_INV, // ADC0_SWITCH, // Switch // ADC0_SWITCH_INV, + ADC0_MOIST, // Moisture ADC0_END }; // Programmer selectable ADC0 functionality @@ -326,6 +327,7 @@ const char kAdc0Names[] PROGMEM = D_SENSOR_NONE "|" D_ANALOG_INPUT "|" D_TEMPERATURE "|" D_LIGHT "|" D_SENSOR_BUTTON "|" D_SENSOR_BUTTON "i|" + D_MOISTURE "|" // D_SENSOR_SWITCH "|" D_SENSOR_SWITCH "i|" ; diff --git a/tasmota/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino index 1a4bc090b..4e75dbbe7 100644 --- a/tasmota/xsns_02_analog.ino +++ b/tasmota/xsns_02_analog.ino @@ -66,6 +66,12 @@ void AdcInit(void) Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; } + else if (ADC0_MOIST == my_adc0) { + Settings.adc_param_type = ADC0_MOIST; + Settings.adc_param1 = 0; + Settings.adc_param2 = 1023; + Settings.adc_param3 = 0; + } } } @@ -113,6 +119,20 @@ uint16_t AdcGetLux(void) return (uint16_t)ldrLux; } +uint16_t AdcGetMoist(void) +// formula for calibration: value, fromLow, fromHigh, toHigh, toLow +// Example: 632, 0, 1023, 100, 0 +// int( ( ( ( - ) / ( - ) ) * ( - ) ) + ) +// double amoist = ((Settings.adc_param2 - (double)adc) / (Settings.adc_param2 - Settings.adc_param1) * 100; +// int((((1023 - ) / ( 1023 - 0 )) * ( 100 - 0 )) + 0 ) + +{ + int adc = AdcRead(2); + double amoist = ((double)Settings.adc_param2 - (double)adc) / ((double)Settings.adc_param2 - (double)Settings.adc_param1) * 100; + //double amoist = ((1023 - (double)adc) / 1023) * 100; + return (uint16_t)amoist; +} + void AdcEverySecond(void) { if (ADC0_TEMP == my_adc0) { @@ -126,7 +146,7 @@ void AdcEverySecond(void) } void AdcShow(bool json) -{ +{ if (ADC0_INPUT == my_adc0) { uint16_t analog = AdcRead(5); @@ -173,9 +193,20 @@ void AdcShow(bool json) #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light); + #endif // USE_WEBSERVER } } + else if (ADC0_MOIST == my_adc0) { + uint16_t adc_moist = AdcGetMoist(); + if (json) { + ResponseAppend_P(JSON_SNS_MOISTURE, "ANALOG", adc_moist); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_MOISTURE, "", adc_moist); +#endif // USE_WEBSERVER + } + } } /*********************************************************************************************\ @@ -217,7 +248,7 @@ void CmndAdcs(void) void CmndAdcParam(void) { if (XdrvMailbox.data_len) { - if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload)) { + if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload) || (ADC0_MOIST == XdrvMailbox.payload)) { // if ((XdrvMailbox.payload == my_adc0) && ((ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0))) { if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len +1]; @@ -227,10 +258,13 @@ void CmndAdcParam(void) // Settings.adc_param_type = my_adc0; Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); - Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); + if (!ADC0_MOIST == XdrvMailbox.payload) { + Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); + } } else { // Set default values based on current adc type // AdcParam 2 // AdcParam 3 + // AdcParam 6 Settings.adc_param_type = 0; AdcInit(); } @@ -246,8 +280,13 @@ void CmndAdcParam(void) } char param3[33]; dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); - Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d,%s]}"), - Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2, param3); + if ((ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0)) { + Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d,%s]}"), + Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2, param3); + } else if (ADC0_MOIST == my_adc0) { + Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d]}"), + Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2); + } } /*********************************************************************************************\ @@ -263,7 +302,7 @@ bool Xsns02(uint8_t function) result = DecodeCommand(kAdcCommands, AdcCommand); break; default: - if ((ADC0_INPUT == my_adc0) || (ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0)) { + if ((ADC0_INPUT == my_adc0) || (ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0) || (ADC0_MOIST == my_adc0)) { switch (function) { #ifdef USE_RULES case FUNC_EVERY_250_MSECOND: diff --git a/tasmota/xsns_48_chirp.ino b/tasmota/xsns_48_chirp.ino index 84fcd4f66..131a0cc24 100644 --- a/tasmota/xsns_48_chirp.ino +++ b/tasmota/xsns_48_chirp.ino @@ -399,7 +399,7 @@ void ChirpEvery100MSecond(void) /********************************************************************************************/ // normaly in i18n.h -#define D_JSON_MOISTURE "Moisture" +// #define D_JSON_MOISTURE "Moisture" // on i18n.h #define D_JSON_DARKNESS "Darkness" #ifdef USE_WEBSERVER From def43784998c18f0821caef253326ced45455b36 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 24 Dec 2019 12:20:04 +0100 Subject: [PATCH 144/559] Add support for ADC0 Moisture Add support for ``AdcParam`` parameters to control ADC0 Moisture formula by Federico Leoni (#7309) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 55 +++++++++++++++++++------------------- tasmota/tasmota_template.h | 2 +- tasmota/xsns_02_analog.ino | 14 +++++----- tasmota/xsns_48_chirp.ino | 34 +++++++++++------------ 6 files changed, 52 insertions(+), 55 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 88442445a..3515a7433 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -57,6 +57,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) - Add support for max 150 characters in most command parameter strings (#3686, #4754) - Add support for GPS as NTP server by Christian Baars and Adrian Scillato +- Add support for ``AdcParam`` parameters to control ADC0 Moisture formula by Federico Leoni (#7309) - Add Zigbee coalesce sensor attributes into a single message - Add Zigbee better support for Xiaomi Double Switch and Xiaomi Vibration sensor - Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index cb2bfe0c5..372a2507f 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Changed Settings variable namings - Add Zigbee better support for Xiaomi Double Switch and Xiaomi Vibration sensor +- Add support for ``AdcParam`` parameters to control ADC0 Moisture formula by Federico Leoni (#7309) ### 8.0.0.1 20191221 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 24b0e1f19..1ae20dcde 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -50,6 +50,7 @@ #define D_JSON_COUNT "Count" #define D_JSON_COUNTER "Counter" #define D_JSON_CURRENT "Current" // As in Voltage and Current +#define D_JSON_DARKNESS "Darkness" #define D_JSON_DATA "Data" #define D_JSON_DISTANCE "Distance" #define D_JSON_DNSSERVER "DNSServer" @@ -458,7 +459,6 @@ #define D_CMND_LONGITUDE "Longitude" // Commands xdrv_16_tuyadimmer.ino - #define D_CMND_TUYA_MCU "TuyaMCU" #define D_CMND_TUYA_MCU_SEND_STATE "TuyaSend" #define D_JSON_TUYA_MCU_RECEIVED "TuyaReceived" @@ -485,34 +485,33 @@ #define D_CMND_ZIGBEE_SEND "ZigbeeSend" #define D_JSON_ZIGBEE_ZCL_SENT "ZigbeeZCLSent" - // Commands xdrv_25_A4988_Stepper.ino - #ifdef USE_A4988_STEPPER - #define D_CMND_MOTOR "MOTOR" - #define D_JSON_MOTOR_MOVE "doMove" - #define D_JSON_MOTOR_ROTATE "doRotate" - #define D_JSON_MOTOR_TURN "doTurn" - #define D_JSON_MOTOR_SPR "setSPR" - #define D_JSON_MOTOR_RPM "setRPM" - #define D_JSON_MOTOR_MIS "setMIS" - #endif +// Commands xdrv_25_A4988_Stepper.ino +#define D_CMND_MOTOR "MOTOR" +#define D_JSON_MOTOR_MOVE "doMove" +#define D_JSON_MOTOR_ROTATE "doRotate" +#define D_JSON_MOTOR_TURN "doTurn" +#define D_JSON_MOTOR_SPR "setSPR" +#define D_JSON_MOTOR_RPM "setRPM" +#define D_JSON_MOTOR_MIS "setMIS" - // Commands xdrv_27_Shutter.ino - #ifdef USE_SHUTTER - #define D_PRFX_SHUTTER "Shutter" - #define D_CMND_SHUTTER_OPEN "Open" - #define D_CMND_SHUTTER_CLOSE "Close" - #define D_CMND_SHUTTER_STOP "Stop" - #define D_CMND_SHUTTER_POSITION "Position" - #define D_CMND_SHUTTER_OPENTIME "OpenDuration" - #define D_CMND_SHUTTER_CLOSETIME "CloseDuration" - #define D_CMND_SHUTTER_RELAY "Relay" - #define D_CMND_SHUTTER_SETHALFWAY "SetHalfway" - #define D_CMND_SHUTTER_SETCLOSE "SetClose" - #define D_CMND_SHUTTER_INVERT "Invert" - #define D_CMND_SHUTTER_CLIBRATION "Calibration" - #define D_CMND_SHUTTER_MOTORDELAY "MotorDelay" - #define D_CMND_SHUTTER_FREQUENCY "Frequency" - #endif +// Commands xdrv_27_Shutter.ino +#define D_PRFX_SHUTTER "Shutter" +#define D_CMND_SHUTTER_OPEN "Open" +#define D_CMND_SHUTTER_CLOSE "Close" +#define D_CMND_SHUTTER_STOP "Stop" +#define D_CMND_SHUTTER_POSITION "Position" +#define D_CMND_SHUTTER_OPENTIME "OpenDuration" +#define D_CMND_SHUTTER_CLOSETIME "CloseDuration" +#define D_CMND_SHUTTER_RELAY "Relay" +#define D_CMND_SHUTTER_SETHALFWAY "SetHalfway" +#define D_CMND_SHUTTER_SETCLOSE "SetClose" +#define D_CMND_SHUTTER_INVERT "Invert" +#define D_CMND_SHUTTER_CLIBRATION "Calibration" +#define D_CMND_SHUTTER_MOTORDELAY "MotorDelay" +#define D_CMND_SHUTTER_FREQUENCY "Frequency" + +// Commands xsns_02_analog.ino +#define D_CMND_ADCPARAM "AdcParam" /********************************************************************************************/ diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 6b936d14a..685546b91 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -311,9 +311,9 @@ enum UserSelectableAdc0 { ADC0_LIGHT, // Light sensor ADC0_BUTTON, // Button ADC0_BUTTON_INV, + ADC0_MOIST, // Moisture // ADC0_SWITCH, // Switch // ADC0_SWITCH_INV, - ADC0_MOIST, // Moisture ADC0_END }; // Programmer selectable ADC0 functionality diff --git a/tasmota/xsns_02_analog.ino b/tasmota/xsns_02_analog.ino index 4e75dbbe7..3dd974918 100644 --- a/tasmota/xsns_02_analog.ino +++ b/tasmota/xsns_02_analog.ino @@ -146,7 +146,7 @@ void AdcEverySecond(void) } void AdcShow(bool json) -{ +{ if (ADC0_INPUT == my_adc0) { uint16_t analog = AdcRead(5); @@ -193,12 +193,12 @@ void AdcShow(bool json) #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light); - #endif // USE_WEBSERVER } } else if (ADC0_MOIST == my_adc0) { uint16_t adc_moist = AdcGetMoist(); + if (json) { ResponseAppend_P(JSON_SNS_MOISTURE, "ANALOG", adc_moist); #ifdef USE_WEBSERVER @@ -206,14 +206,13 @@ void AdcShow(bool json) WSContentSend_PD(HTTP_SNS_MOISTURE, "", adc_moist); #endif // USE_WEBSERVER } - } + } } /*********************************************************************************************\ * Commands \*********************************************************************************************/ -#define D_CMND_ADCPARAM "AdcParam" const char kAdcCommands[] PROGMEM = "|" // No prefix D_CMND_ADC "|" D_CMND_ADCS "|" D_CMND_ADCPARAM; @@ -248,7 +247,7 @@ void CmndAdcs(void) void CmndAdcParam(void) { if (XdrvMailbox.data_len) { - if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload) || (ADC0_MOIST == XdrvMailbox.payload)) { + if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload) || (ADC0_MOIST == XdrvMailbox.payload)) { // if ((XdrvMailbox.payload == my_adc0) && ((ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0))) { if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len +1]; @@ -283,10 +282,11 @@ void CmndAdcParam(void) if ((ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0)) { Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d,%s]}"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2, param3); - } else if (ADC0_MOIST == my_adc0) { + } + else if (ADC0_MOIST == my_adc0) { Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d]}"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2); - } + } } /*********************************************************************************************\ diff --git a/tasmota/xsns_48_chirp.ino b/tasmota/xsns_48_chirp.ino index 131a0cc24..f761e6afc 100644 --- a/tasmota/xsns_48_chirp.ino +++ b/tasmota/xsns_48_chirp.ino @@ -397,22 +397,17 @@ void ChirpEvery100MSecond(void) } /********************************************************************************************/ + // normaly in i18n.h - -// #define D_JSON_MOISTURE "Moisture" // on i18n.h -#define D_JSON_DARKNESS "Darkness" - #ifdef USE_WEBSERVER // {s} = , {m} = , {e} = - const char HTTP_SNS_MOISTURE[] PROGMEM = "{s} " D_JSON_MOISTURE "{m}%s %{e}"; - const char HTTP_SNS_DARKNESS[] PROGMEM = "{s} " D_JSON_DARKNESS "{m}%s %{e}"; - const char HTTP_SNS_CHIRPVER[] PROGMEM = "{s} CHIRP-sensor %u at address{m}0x%x{e}" - "{s} FW-version{m}%s {e}"; ; - const char HTTP_SNS_CHIRPSLEEP[] PROGMEM = "{s} {m} is sleeping ...{e}"; +const char HTTP_SNS_DARKNESS[] PROGMEM = "{s} " D_JSON_DARKNESS "{m}%s %%{e}"; +const char HTTP_SNS_CHIRPVER[] PROGMEM = "{s} CHIRP-sensor %u at address{m}0x%x{e}" + "{s} FW-version{m}%s {e}"; ; +const char HTTP_SNS_CHIRPSLEEP[] PROGMEM = "{s} {m} is sleeping ...{e}"; #endif // USE_WEBSERVER - /********************************************************************************************/ void ChirpShow(bool json) @@ -420,8 +415,6 @@ void ChirpShow(bool json) for (uint32_t i = 0; i < chirp_found_sensors; i++) { if (chirp_sensor[i].version) { // convert double values to string - char str_moisture[33]; - dtostrfd(chirp_sensor[i].moisture, 0, str_moisture); char str_temperature[33]; double t_temperature = ((double) chirp_sensor[i].temperature )/10.0; dtostrfd(t_temperature, Settings.flag2.temperature_resolution, str_temperature); @@ -434,9 +427,10 @@ void ChirpShow(bool json) else{ sprintf(str_version, "%x", chirp_sensor[i].version); } + if (json) { if(!chirp_sensor[i].explicitSleep) { - ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%s"),chirp_name, i, str_moisture); + ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%d"), chirp_name, i, chirp_sensor[i].moisture); if(chirp_sensor[i].temperature!=-1){ // this is the error code -> no temperature ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"),str_temperature); } @@ -447,9 +441,11 @@ void ChirpShow(bool json) } #ifdef USE_DOMOTICZ if (0 == tele_period) { - DomoticzTempHumSensor(str_temperature, str_moisture); - DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); // this is not LUX!! - } + char str_moisture[33]; + dtostrfd(chirp_sensor[i].moisture, 0, str_moisture); + DomoticzTempHumSensor(str_temperature, str_moisture); + DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); // this is not LUX!! + } #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { @@ -458,10 +454,10 @@ void ChirpShow(bool json) WSContentSend_PD(HTTP_SNS_CHIRPSLEEP); } else { - WSContentSend_PD(HTTP_SNS_MOISTURE, str_moisture); + WSContentSend_PD(HTTP_SNS_MOISTURE, "", chirp_sensor[i].moisture); WSContentSend_PD(HTTP_SNS_DARKNESS, str_light); - if(chirp_sensor[i].temperature!=-1){ // this is the error code -> no temperature - WSContentSend_PD(HTTP_SNS_TEMP, " ",str_temperature, TempUnit()); + if (chirp_sensor[i].temperature!=-1) { // this is the error code -> no temperature + WSContentSend_PD(HTTP_SNS_TEMP, "", str_temperature, TempUnit()); } } From a2478f9569a5411ad3660085c9ae5384c5e92358 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 24 Dec 2019 15:06:19 +0100 Subject: [PATCH 145/559] Change number of ``FriendlyName``s from 4 to 8 Change number of ``FriendlyName``s from 4 to 8 --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/settings.h | 2 +- tasmota/tasmota.h | 16 ++++++------- tasmota/xdrv_01_webserver.ino | 9 +++++--- tasmota/xdrv_09_timers.ino | 7 +++--- tasmota/xdrv_10_rules.ino | 6 ++--- tasmota/xdrv_10_scripter.ino | 12 ++++------ tasmota/xdsp_02_ssd1306.ino | 3 +-- tasmota/xdsp_07_sh1106.ino | 3 +-- tasmota/xdsp_09_SSD1351.ino | 3 +-- tasmota/xsns_41_max44009.ino | 3 +-- tasmota/xsns_42_scd30.ino | 43 ++++++++++++++++------------------- 13 files changed, 50 insertions(+), 59 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 3515a7433..c9293bb95 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -55,6 +55,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) - Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) +- Change number of ``FriendlyName``s from 4 to 8 - Add support for max 150 characters in most command parameter strings (#3686, #4754) - Add support for GPS as NTP server by Christian Baars and Adrian Scillato - Add support for ``AdcParam`` parameters to control ADC0 Moisture formula by Federico Leoni (#7309) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 372a2507f..d6b1d0ab7 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.0.0.2 20191223 - Changed Settings variable namings +- Change number of ``FriendlyName``s from 4 to 8 - Add Zigbee better support for Xiaomi Double Switch and Xiaomi Vibration sensor - Add support for ``AdcParam`` parameters to control ADC0 Moisture formula by Federico Leoni (#7309) diff --git a/tasmota/settings.h b/tasmota/settings.h index af774a4c2..eddc4f04b 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -337,7 +337,7 @@ struct SYSCFG { SysBitfield3 flag3; // 3A0 uint8_t switchmode[MAX_SWITCHES]; // 3A4 (6.0.0b - moved from 0x4CA) - char ex_friendlyname[MAX_FRIENDLYNAMES][33]; // 3AC + char ex_friendlyname[4][33]; // 3AC char ex_switch_topic[33]; // 430 char serial_delimiter; // 451 diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 829a90871..2e539bb49 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -58,7 +58,6 @@ const uint8_t MAX_PWMS = 5; // Max number of PWM channels const uint8_t MAX_COUNTERS = 4; // Max number of counter sensors const uint8_t MAX_TIMERS = 16; // Max number of Timers const uint8_t MAX_PULSETIMERS = 8; // Max number of supported pulse timers -const uint8_t MAX_FRIENDLYNAMES = 4; // Max number of Friendly names const uint8_t MAX_DOMOTICZ_IDX = 4; // Max number of Domoticz device, key and switch indices const uint8_t MAX_DOMOTICZ_SNS_IDX = 12; // Max number of Domoticz sensors indices const uint8_t MAX_KNX_GA = 10; // Max number of KNX Group Addresses to read that can be set @@ -73,7 +72,10 @@ const uint8_t MAX_PCF8574 = 8; // Max number of PCF8574 devices const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules +// Changes to the following MAX_ defines need to be in line with enum SettingsTextIndex +const uint8_t MAX_FRIENDLYNAMES = 8; // Max number of Friendly names const uint8_t MAX_RULE_MEMS = 16; // Max number of saved vars + const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation const char MQTT_TOKEN_PREFIX[] PROGMEM = "%prefix%"; // To be substituted by mqtt_prefix[x] @@ -287,13 +289,11 @@ enum SettingsTextIndex { SET_OTAURL, SET_MEM1, SET_MEM2, SET_MEM3, SET_MEM4, SET_MEM5, SET_MEM6, SET_MEM7, SET_MEM8, SET_MEM9, SET_MEM10, SET_MEM11, SET_MEM12, SET_MEM13, SET_MEM14, SET_MEM15, SET_MEM16, SET_FRIENDLYNAME1, SET_FRIENDLYNAME2, SET_FRIENDLYNAME3, SET_FRIENDLYNAME4, - -// SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, // Future extension -// SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, // Future extension -// SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, // Future extension -// SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, // Future extension -// SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, // Future extension - + SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, + SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, + SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, + SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, + SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, SET_MAX }; enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 104e71f67..c25cdc3f6 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1846,6 +1846,7 @@ void OtherSaveSettings(void) char tmp[TOPSZ]; char webindex[5]; char friendlyname[TOPSZ]; + char message[LOGSZ]; WebGetArg("wp", tmp, sizeof(tmp)); SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp); @@ -1854,15 +1855,17 @@ void OtherSaveSettings(void) WebGetArg("b2", tmp, sizeof(tmp)); Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); #endif // USE_EMULATION - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); + + snprintf_P(message, sizeof(message), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) { snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i); WebGetArg(webindex, tmp, sizeof(tmp)); snprintf_P(friendlyname, sizeof(friendlyname), PSTR(FRIENDLY_NAME"%d"), i +1); SettingsUpdateText(SET_FRIENDLYNAME1 +i, (!strlen(tmp)) ? (i) ? friendlyname : FRIENDLY_NAME : tmp); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%s %s"), log_data, (i) ? "," : "", SettingsText(SET_FRIENDLYNAME1 +i)); + snprintf_P(message, sizeof(message), PSTR("%s%s %s"), message, (i) ? "," : "", SettingsText(SET_FRIENDLYNAME1 +i)); } - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, message); + WebGetArg("t1", tmp, sizeof(tmp)); if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255} char svalue[128]; diff --git a/tasmota/xdrv_09_timers.ino b/tasmota/xdrv_09_timers.ino index db1cde97e..a6c7b23a9 100644 --- a/tasmota/xdrv_09_timers.ino +++ b/tasmota/xdrv_09_timers.ino @@ -733,12 +733,13 @@ void HandleTimerConfiguration(void) void TimerSaveSettings(void) { char tmp[MAX_TIMERS *12]; // Need space for MAX_TIMERS x 10 digit numbers separated by a comma + char message[LOGSZ]; Timer timer; Settings.flag3.timers_enable = WebServer->hasArg("e0"); // CMND_TIMERS WebGetArg("t0", tmp, sizeof(tmp)); char *p = tmp; - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable); // CMND_TIMERS + snprintf_P(message, sizeof(message), PSTR(D_LOG_MQTT D_CMND_TIMERS " %d"), Settings.flag3.timers_enable); // CMND_TIMERS for (uint32_t i = 0; i < MAX_TIMERS; i++) { timer.data = strtol(p, &p, 10); p++; // Skip comma @@ -747,9 +748,9 @@ void TimerSaveSettings(void) Settings.timer[i].data = timer.data; if (flag) TimerSetRandomWindow(i); } - snprintf_P(log_data, sizeof(log_data), PSTR("%s,0x%08X"), log_data, Settings.timer[i].data); + snprintf_P(message, sizeof(message), PSTR("%s,0x%08X"), message, Settings.timer[i].data); } - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, message); } #endif // USE_TIMERS_WEB #endif // USE_WEBSERVER diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 72276f94b..21c9de283 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -1400,8 +1400,7 @@ bool evaluateLogicalExpression(const char * expression, int len) memcpy(expbuff, expression, len); expbuff[len] = '\0'; - //snprintf_P(log_data, sizeof(log_data), PSTR("EvalLogic: |%s|"), expbuff); - //AddLog(LOG_LEVEL_DEBUG); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EvalLogic: |%s|"), expbuff); char * pointer = expbuff; LinkedList values; LinkedList logicOperators; @@ -1527,8 +1526,7 @@ void ExecuteCommandBlock(const char * commands, int len) memcpy(cmdbuff, commands, len); cmdbuff[len] = '\0'; - //snprintf_P(log_data, sizeof(log_data), PSTR("ExecCmd: |%s|"), cmdbuff); - //AddLog(LOG_LEVEL_DEBUG); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ExecCmd: |%s|"), cmdbuff); char oneCommand[len + 1]; //To put one command int insertPosition = 0; //When insert into backlog, we should do it by 0, 1, 2 ... char * pos = cmdbuff; diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index c6aedb80e..27d72c717 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -2203,8 +2203,7 @@ void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) { void toLog(const char *str) { if (!str) return; - snprintf_P(log_data, sizeof(log_data), PSTR("%s"),str); - AddLog(LOG_LEVEL_INFO); + AddLog_P(LOG_LEVEL_INFO, str); } @@ -2681,8 +2680,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { } cmd[count]=*lp++; } - //snprintf_P(log_data, sizeof(log_data), tmp); - //AddLog(LOG_LEVEL_INFO); + //AddLog_P(LOG_LEVEL_INFO, tmp); // replace vars in cmd char *tmp=cmdmem+SCRIPT_CMDMEM/2; Replace_Cmd_Vars(cmd,tmp,SCRIPT_CMDMEM/2); @@ -2694,8 +2692,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) { } else { if (!sflag) { tasm_cmd_activ=1; - snprintf_P(log_data, sizeof(log_data), PSTR("Script: performs \"%s\""), tmp); - AddLog(glob_script_mem.script_loglevel&0x7f); + AddLog_P2(glob_script_mem.script_loglevel&0x7f, PSTR("Script: performs \"%s\""), tmp); } else if (sflag==2) { // allow recursive call } else { @@ -3544,8 +3541,7 @@ void ScriptSaveSettings(void) { if (bitRead(Settings.rule_enabled, 0)) { int16_t res=Init_Scripter(); if (res) { - snprintf_P(log_data, sizeof(log_data), PSTR("script init error: %d"),res); - AddLog(LOG_LEVEL_INFO); + AddLog_P2(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); return; } Run_Scripter(">B",2,0); diff --git a/tasmota/xdsp_02_ssd1306.ino b/tasmota/xdsp_02_ssd1306.ino index e263901bc..0bee9d10d 100644 --- a/tasmota/xdsp_02_ssd1306.ino +++ b/tasmota/xdsp_02_ssd1306.ino @@ -124,8 +124,7 @@ void Ssd1306PrintLog(void) strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); DisplayFillScreen(last_row); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); renderer->println(disp_screen_buffer[last_row]); renderer->Updateframe(); diff --git a/tasmota/xdsp_07_sh1106.ino b/tasmota/xdsp_07_sh1106.ino index eba56a442..00babbdf9 100644 --- a/tasmota/xdsp_07_sh1106.ino +++ b/tasmota/xdsp_07_sh1106.ino @@ -119,8 +119,7 @@ void SH1106PrintLog(void) strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); DisplayFillScreen(last_row); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); renderer->println(disp_screen_buffer[last_row]); renderer->Updateframe(); diff --git a/tasmota/xdsp_09_SSD1351.ino b/tasmota/xdsp_09_SSD1351.ino index ad7e86f99..0391bf8f4 100644 --- a/tasmota/xdsp_09_SSD1351.ino +++ b/tasmota/xdsp_09_SSD1351.ino @@ -112,8 +112,7 @@ void SSD1351PrintLog(void) strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); DisplayFillScreen(last_row); - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); renderer->println(disp_screen_buffer[last_row]); renderer->Updateframe(); diff --git a/tasmota/xsns_41_max44009.ino b/tasmota/xsns_41_max44009.ino index 2cdf6b78d..e1ef99ee1 100644 --- a/tasmota/xsns_41_max44009.ino +++ b/tasmota/xsns_41_max44009.ino @@ -75,8 +75,7 @@ void Max4409Detect(void) if ((I2cValidRead8(&buffer1, max44009_address, REG_LOWER_THRESHOLD)) && (I2cValidRead8(&buffer2, max44009_address, REG_THRESHOLD_TIMER))) { - //snprintf(log_data, sizeof(log_data), "MAX44009 %x: %x, %x", max44009_address, (int)buffer1, (int)buffer2); - //AddLog(LOG_LEVEL_DEBUG_MORE); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("MAX44009 %x: %x, %x"), max44009_address, (int)buffer1, (int)buffer2); if ((0x00 == buffer1) && (0xFF == buffer2)) { diff --git a/tasmota/xsns_42_scd30.ino b/tasmota/xsns_42_scd30.ino index d3bb5cbef..12ac95cd2 100644 --- a/tasmota/xsns_42_scd30.ino +++ b/tasmota/xsns_42_scd30.ino @@ -23,6 +23,8 @@ #define XSNS_42 42 #define XI2C_29 29 // See I2CDEVICES.md +//#define SCD30_DEBUG + #define SCD30_ADDRESS 0x61 #define SCD30_MAX_MISSED_READS 3 @@ -118,24 +120,23 @@ void Scd30Update(void) scd30ErrorState = SCD30_STATE_ERROR_DATA_CRC; scd30CrcError_count++; #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld", scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), + scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); #endif break; case ERROR_SCD30_CO2_ZERO: scd30Co2Zero_count++; #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld", scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), + scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); #endif break; default: { scd30ErrorState = SCD30_STATE_ERROR_READ_MEAS; #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld", error, scd30Loop_count); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, scd30Loop_count); #endif return; } @@ -147,10 +148,9 @@ void Scd30Update(void) case SCD30_STATE_ERROR_DATA_CRC: { //scd30IsDataValid = false; #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); - snprintf_P(log_data, sizeof(log_data), "SCD30: got CRC error, try again, counter: %ld", scd30Loop_count); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: got CRC error, try again, counter: %ld"), scd30Loop_count); #endif scd30ErrorState = ERROR_SCD30_NO_ERROR; } @@ -159,17 +159,15 @@ void Scd30Update(void) case SCD30_STATE_ERROR_READ_MEAS: { //scd30IsDataValid = false; #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); - snprintf_P(log_data, sizeof(log_data), "SCD30: not answering, sending soft reset, counter: %ld", scd30Loop_count); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: not answering, sending soft reset, counter: %ld"), scd30Loop_count); #endif scd30Reset_count++; error = scd30.softReset(); if (error) { #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: resetting got error: 0x%lX", error); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: resetting got error: 0x%lX"), error); #endif error >>= 8; if (error == 4) { @@ -186,18 +184,16 @@ void Scd30Update(void) case SCD30_STATE_ERROR_SOFT_RESET: { //scd30IsDataValid = false; #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld", scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog(LOG_LEVEL_ERROR); - snprintf_P(log_data, sizeof(log_data), "SCD30: clearing i2c bus"); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P(LOG_LEVEL_ERROR, PSTR("SCD30: clearing i2c bus")); #endif i2cReset_count++; error = scd30.clearI2CBus(); if (error) { scd30ErrorState = SCD30_STATE_ERROR_I2C_RESET; #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: error clearing i2c bus: 0x%lX", error); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error clearing i2c bus: 0x%lX"), error); #endif } else { scd30ErrorState = ERROR_SCD30_NO_ERROR; @@ -342,8 +338,7 @@ bool Scd30CommandSensor() if (error) { #ifdef SCD30_DEBUG - snprintf_P(log_data, sizeof(log_data), "SCD30: error getting FW version: 0x%lX", error); - AddLog(LOG_LEVEL_ERROR); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error getting FW version: 0x%lX"), error); #endif serviced = false; } From 29366222a538283fb86b94eb1000e8fc6cb17bee Mon Sep 17 00:00:00 2001 From: Hadinger Date: Tue, 24 Dec 2019 16:42:47 +0100 Subject: [PATCH 146/559] Re-enable mqttuser/mqttpassword for AWS IoT --- tasmota/xdrv_02_mqtt.ino | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index f9ff3e67d..910a2ea6f 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -32,9 +32,7 @@ const char kMqttCommands[] PROGMEM = "|" // No prefix #if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) D_CMND_MQTTFINGERPRINT "|" #endif -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" -#endif #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) D_CMND_TLSKEY "|" #endif @@ -46,9 +44,7 @@ void (* const MqttCommand[])(void) PROGMEM = { #if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) &CmndMqttFingerprint, #endif -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT &CmndMqttUser, &CmndMqttPassword, -#endif #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) &CmndTlsKey, #endif @@ -640,7 +636,6 @@ void MqttReconnect(void) #endif #if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "AWS IoT endpoint: %s"), SettingsText(SET_MQTT_HOST)); - //if (MqttClient.connect(mqtt_client, nullptr, nullptr, nullptr, 0, false, nullptr)) { if (MqttClient.connect(mqtt_client, nullptr, nullptr, stopic, 1, false, mqtt_data, MQTT_CLEAN_SESSION)) { #else if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data, MQTT_CLEAN_SESSION)) { @@ -737,7 +732,6 @@ void CmndMqttFingerprint(void) } #endif -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT void CmndMqttUser(void) { if (XdrvMailbox.data_len > 0) { @@ -757,7 +751,6 @@ void CmndMqttPassword(void) Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); } } -#endif // USE_MQTT_AWS_IOT void CmndMqttlog(void) { @@ -1171,10 +1164,8 @@ const char HTTP_FORM_MQTT1[] PROGMEM = "

" D_PORT " (" STR(MQTT_PORT) ")

" "

" D_CLIENT " (%s)

"; const char HTTP_FORM_MQTT2[] PROGMEM = -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password disabled with AWS IoT "

" D_USER " (" MQTT_USER ")

" "

" D_PASSWORD "

" -#endif // USE_MQTT_AWS_IOT "

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

" "

" D_FULL_TOPIC " (%s)

"; From b66cc3479f363b61b53104aa40d841467062fe51 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 24 Dec 2019 17:10:50 +0100 Subject: [PATCH 147/559] Add support for user defined GUI button text Add commands ``WebButton1`` until ``WebButton16`` to support user defined GUI button text (#7166) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 1 + tasmota/settings.ino | 13 +++++----- tasmota/support_command.ino | 2 +- tasmota/tasmota.h | 9 +++---- tasmota/xdrv_01_webserver.ino | 47 +++++++++++++++++++++++++++++------ 7 files changed, 54 insertions(+), 20 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c9293bb95..6be1dfa9f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -56,6 +56,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) - Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) - Change number of ``FriendlyName``s from 4 to 8 +- Add commands ``WebButton1`` until ``WebButton16`` to support user defined GUI button text (#7166) - Add support for max 150 characters in most command parameter strings (#3686, #4754) - Add support for GPS as NTP server by Christian Baars and Adrian Scillato - Add support for ``AdcParam`` parameters to control ADC0 Moisture formula by Federico Leoni (#7309) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index d6b1d0ab7..0c12ed15c 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,6 +6,7 @@ - Change number of ``FriendlyName``s from 4 to 8 - Add Zigbee better support for Xiaomi Double Switch and Xiaomi Vibration sensor - Add support for ``AdcParam`` parameters to control ADC0 Moisture formula by Federico Leoni (#7309) +- Add commands ``WebButton1`` until ``WebButton16`` to support user defined GUI button text (#7166) ### 8.0.0.1 20191221 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 1ae20dcde..e726fdf5d 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -334,6 +334,7 @@ #define D_CMND_WEBREFRESH "WebRefresh" #define D_CMND_WEBSEND "WebSend" #define D_CMND_WEBCOLOR "WebColor" +#define D_CMND_WEBBUTTON "WebButton" #define D_CMND_WEBSENSOR "WebSensor" #define D_CMND_EMULATION "Emulation" #define D_CMND_SENDMAIL "Sendmail" diff --git a/tasmota/settings.ino b/tasmota/settings.ino index ce6c33ff4..6412d3fc9 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -551,13 +551,14 @@ bool SettingsUpdateText(uint32_t index, const char* replace_me) char* SettingsText(uint32_t index) { - if (index >= SET_MAX) { - return nullptr; // Setting not supported - internal error - } - char* position = Settings.text_pool; - for (;index > 0; index--) { - while (*position++ != '\0') { } + + if (index >= SET_MAX) { + position += settings_text_size -1; // Setting not supported - internal error - return empty string + } else { + for (;index > 0; index--) { + while (*position++ != '\0') { } + } } return position; } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 265926b59..f6413dd57 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1311,7 +1311,7 @@ void CmndFriendlyname(void) } else { snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); } - SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); + SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); } ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1)); } diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 2e539bb49..c0231d3c9 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -73,8 +73,9 @@ const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 5 const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules // Changes to the following MAX_ defines need to be in line with enum SettingsTextIndex -const uint8_t MAX_FRIENDLYNAMES = 8; // Max number of Friendly names const uint8_t MAX_RULE_MEMS = 16; // Max number of saved vars +const uint8_t MAX_FRIENDLYNAMES = 8; // Max number of Friendly names +const uint8_t MAX_BUTTON_TEXT = 16; // Max number of GUI button labels const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation @@ -290,10 +291,8 @@ enum SettingsTextIndex { SET_OTAURL, SET_MEM9, SET_MEM10, SET_MEM11, SET_MEM12, SET_MEM13, SET_MEM14, SET_MEM15, SET_MEM16, SET_FRIENDLYNAME1, SET_FRIENDLYNAME2, SET_FRIENDLYNAME3, SET_FRIENDLYNAME4, SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, - SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, - SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, - SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, - SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, + SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, + SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, SET_MAX }; enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index c25cdc3f6..d86562bb3 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1014,7 +1014,7 @@ void HandleRoot(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); - char stemp[10]; + char stemp[33]; WSContentStart_P(S_MAIN_MENU); #ifdef USE_SCRIPT_WEB_DISPLAY @@ -1106,14 +1106,19 @@ void HandleRoot(void) WSContentSend_P(PSTR("")); #ifdef USE_SONOFF_IFAN if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, D_BUTTON_TOGGLE, ""); + WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, + (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : D_BUTTON_TOGGLE, + ""); for (uint32_t i = 0; i < MaxFanspeed(); i++) { snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); - WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, stemp, ""); + WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, + (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp, + ""); } } else { #endif // USE_SONOFF_IFAN for (uint32_t idx = 1; idx <= devices_present; idx++) { + bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); #ifdef USE_SHUTTER if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support bool shutter_used = false; @@ -1124,13 +1129,17 @@ void HandleRoot(void) } } if (shutter_used) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (idx % 2) ? "▲" : "▼" , ""); + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (idx % 2) ? "▲" : "▼", + ""); continue; } } #endif // USE_SHUTTER snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, (devices_present < 5) ? D_BUTTON_TOGGLE : "", (devices_present > 1) ? stemp : ""); + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (devices_present < 5) ? D_BUTTON_TOGGLE : "", + (set_button) ? "" : (devices_present > 1) ? stemp : ""); } #ifdef USE_SONOFF_IFAN } @@ -1146,7 +1155,9 @@ void HandleRoot(void) if (idx > 0) { WSContentSend_P(PSTR("")); } for (uint32_t j = 0; j < 4; j++) { idx++; - WSContentSend_P(PSTR(""), idx, idx); // &k is related to WebGetArg("k", tmp, sizeof(tmp)); + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), idx); + WSContentSend_P(PSTR(""), idx, // &k is related to WebGetArg("k", tmp, sizeof(tmp)); + (strlen(SettingsText(SET_BUTTON1 + idx -1))) ? SettingsText(SET_BUTTON1 + idx -1) : stemp); } } WSContentSend_P(PSTR("")); @@ -2733,7 +2744,8 @@ const char kWebCommands[] PROGMEM = "|" // No prefix #ifdef USE_SENDMAIL D_CMND_SENDMAIL "|" #endif - D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR "|" D_CMND_CORS; + D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" + D_CMND_WEBSENSOR "|" D_CMND_WEBBUTTON "|" D_CMND_CORS; void (* const WebCommand[])(void) PROGMEM = { #ifdef USE_EMULATION @@ -2742,7 +2754,8 @@ void (* const WebCommand[])(void) PROGMEM = { #ifdef USE_SENDMAIL &CmndSendmail, #endif - &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor, &CmndCors }; + &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, + &CmndWebSensor, &CmndWebButton, &CmndCors }; /*********************************************************************************************\ * Commands @@ -2863,6 +2876,24 @@ void CmndWebSensor(void) ResponseJsonEnd(); } +void CmndWebButton(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_BUTTON_TEXT)) { + if (!XdrvMailbox.usridx) { + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < MAX_BUTTON_TEXT; i++) { + ResponseAppend_P(PSTR("%c\"WebButton%d\":\"%s\""), (i) ? ',' : '{', i +1, SettingsText(SET_BUTTON1 +i)); + } + ResponseJsonEnd(); + } else { + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_BUTTON1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data); + } + ResponseCmndIdxChar(SettingsText(SET_BUTTON1 + XdrvMailbox.index -1)); + } + } +} + void CmndCors(void) { if (XdrvMailbox.data_len > 0) { From ad312c04144d17e6d38de34f1b44503480852739 Mon Sep 17 00:00:00 2001 From: Federico Leoni Date: Tue, 24 Dec 2019 13:21:56 -0300 Subject: [PATCH 148/559] Update xdrv_12_home_assistant.ino --- tasmota/xdrv_12_home_assistant.ino | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 274b5f42a..50ac66761 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -100,6 +100,12 @@ const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} "\"dev_cla\":\"humidity\""; // humidity +const char HASS_DISCOVER_SENSOR_MOIST[] PROGMEM = + ",\"unit_of_meas\":\"%%\"," // % + "\"val_tpl\":\"{{value_json['%s'].Moisture}}\"," // "ANALOG":{"Moisture":78} -> {{ value_json['ANALOG'].Moisture }} + "\"dev_cla\":\"humidity\"," // humidity + "\"ic\":\"mdi:cup-water\""; // cup-water icon + const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = ",\"unit_of_meas\":\"%s\"," // PressureUnit() setting "\"val_tpl\":\"{{value_json['%s'].%s}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} @@ -473,6 +479,8 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) TryResponseAppend_P(HASS_DISCOVER_SENSOR_AMPERE, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_ILLUMINANCE))){ TryResponseAppend_P(HASS_DISCOVER_SENSOR_ILLUMINANCE, sensorname, subsensortype); + } else if (!strcmp_P(subsensortype, PSTR(D_JSON_MOISTURE))){ + TryResponseAppend_P(HASS_DISCOVER_SENSOR_MOIST, sensorname, subsensortype); } else { if (is_sensor){ TryResponseAppend_P(PSTR(",\"unit_of_meas\":\" \"")); // " " As unit of measurement to get a value graph (not available for binary sensors) From 8cf7c6fbc212929f397c202af0009369ebe6d249 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 24 Dec 2019 17:25:21 +0100 Subject: [PATCH 149/559] Bump version to 8.0.0.3 --- RELEASENOTES.md | 2 +- tasmota/CHANGELOG.md | 4 ++++ tasmota/tasmota_version.h | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6be1dfa9f..c7566764e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -50,7 +50,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.0.0.2 +### Version 8.0.0.3 - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 0c12ed15c..b351cb091 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 8.0.0.3 20191224 + +- Version bump due to internal Settings change + ### 8.0.0.2 20191223 - Changed Settings variable namings diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index e69d4fd39..57329bcd1 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08000002; +const uint32_t VERSION = 0x08000003; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; From 72f2e944d5070eeaffac8ecc89a373cc7c5e5353 Mon Sep 17 00:00:00 2001 From: gemu2015 Date: Wed, 25 Dec 2019 09:04:54 +0100 Subject: [PATCH 150/559] scripter pram update --- tasmota/settings.h | 2 +- tasmota/settings.ino | 5 ----- tasmota/xdrv_10_scripter.ino | 11 ++++++----- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index eddc4f04b..dfe35be60 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -421,7 +421,7 @@ struct SYSCFG { unsigned long weight_calibration; // 7C4 unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight uint16_t web_refresh; // 7CC - char script_pram[5][10]; // 7CE + uint8_t script_pram[50]; // 7CE char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 6412d3fc9..8181440d7 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1378,11 +1378,6 @@ void SettingsDelta(void) SettingsUpdateText(SET_NTPSERVER1, Settings.ex_ntp_server[0]); SettingsUpdateText(SET_NTPSERVER2, Settings.ex_ntp_server[1]); SettingsUpdateText(SET_NTPSERVER3, Settings.ex_ntp_server[2]); - SettingsUpdateText(SET_MEM1, Settings.script_pram[0]); - SettingsUpdateText(SET_MEM2, Settings.script_pram[1]); - SettingsUpdateText(SET_MEM3, Settings.script_pram[2]); - SettingsUpdateText(SET_MEM4, Settings.script_pram[3]); - SettingsUpdateText(SET_MEM5, Settings.script_pram[4]); SettingsUpdateText(SET_FRIENDLYNAME1, Settings.ex_friendlyname[0]); SettingsUpdateText(SET_FRIENDLYNAME2, Settings.ex_friendlyname[1]); SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]); diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 27d72c717..6b97fa68a 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -56,7 +56,8 @@ keywords if then else endif, or, and are better readable for beginners (others m #define SCRIPT_MAXSSIZE 48 #define SCRIPT_EOL '\n' #define SCRIPT_FLOAT_PRECISION 2 -#define SCRIPT_MAXPERM (5*10)-4/sizeof(float) +#define PMEM_SIZE sizeof(Settings.script_pram) +#define SCRIPT_MAXPERM (PMEM_SIZE)-4/sizeof(float) #define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS // offsets epoch readings by 1.1.2019 00:00:00 to fit into float with second resolution @@ -1575,7 +1576,7 @@ chknext: case 'r': if (!strncmp(vname,"ram",3)) { - fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(5*10); + fvar=glob_script_mem.script_mem_size+(glob_script_mem.script_size)+(PMEM_SIZE); goto exit; } break; @@ -3004,7 +3005,7 @@ void Scripter_save_pvars(void) { if (vtp[count].bits.is_permanent && !vtp[count].bits.is_string) { uint8_t index=vtp[count].index; mlen+=sizeof(float); - if (mlen>5*10) { + if (mlen>PMEM_SIZE) { vtp[count].bits.is_permanent=0; return; } @@ -3018,7 +3019,7 @@ void Scripter_save_pvars(void) { char *sp=glob_script_mem.glob_snp+(index*glob_script_mem.max_ssize); uint8_t slen=strlen(sp); mlen+=slen+1; - if (mlen>5*10) { + if (mlen>PMEM_SIZE) { vtp[count].bits.is_permanent=0; return; } @@ -4751,7 +4752,7 @@ bool Xdrv10(uint8_t function) glob_script_mem.script_size=MAX_SCRIPT_SIZE; glob_script_mem.flags=0; glob_script_mem.script_pram=(uint8_t*)Settings.script_pram[0]; - glob_script_mem.script_pram_size=5*10; + glob_script_mem.script_pram_size=PMEM_SIZE; #ifdef USE_BUTTON_EVENT for (uint32_t cnt=0;cnt Date: Wed, 25 Dec 2019 09:09:43 +0100 Subject: [PATCH 151/559] sml max vars for large meter definitions redefinable --- tasmota/xsns_53_sml.ino | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tasmota/xsns_53_sml.ino b/tasmota/xsns_53_sml.ino index 7aa0fd22d..672f7f826 100755 --- a/tasmota/xsns_53_sml.ino +++ b/tasmota/xsns_53_sml.ino @@ -493,19 +493,19 @@ const uint8_t meter[]= //===================================================== // median filter eliminates outliers, but uses much RAM and CPU cycles -// 672 bytes extra RAM with MAX_VARS = 16 +// 672 bytes extra RAM with SML_MAX_VARS = 16 // default compile on, but must be enabled by descriptor flag 16 // may be undefined if RAM must be saved #define USE_SML_MEDIAN_FILTER // max number of vars , may be adjusted -#ifndef MAX_VARS -#define MAX_VARS 20 +#ifndef SML_MAX_VARS +#define SML_MAX_VARS 20 #endif // max number of meters , may be adjusted #define MAX_METERS 5 -double meter_vars[MAX_VARS]; +double meter_vars[SML_MAX_VARS]; // calulate deltas #define MAX_DVARS MAX_METERS*2 double dvalues[MAX_DVARS]; @@ -540,7 +540,7 @@ uint8_t sml_desc_cnt; struct SML_MEDIAN_FILTER { double buffer[MEDIAN_SIZE]; int8_t index; -} sml_mf[MAX_VARS]; +} sml_mf[SML_MAX_VARS]; #ifndef FLT_MAX #define FLT_MAX 99999999 @@ -1326,7 +1326,7 @@ void SML_Decode(uint8_t index) { uint32_t ind; ind=atoi(mp); while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>MAX_VARS) ind=1; + if (ind<1 || ind>SML_MAX_VARS) ind=1; dvar=meter_vars[ind-1]; for (uint8_t p=0;p<5;p++) { if (*mp=='@') { @@ -1345,7 +1345,7 @@ void SML_Decode(uint8_t index) { } ind=atoi(mp); while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>MAX_VARS) ind=1; + if (ind<1 || ind>SML_MAX_VARS) ind=1; switch (opr) { case '+': if (iflg) dvar+=ind; @@ -1381,7 +1381,7 @@ void SML_Decode(uint8_t index) { while (*mp==' ') mp++; uint8_t ind=atoi(mp); while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>MAX_VARS) ind=1; + if (ind<1 || ind>SML_MAX_VARS) ind=1; uint32_t delay=atoi(mp)*1000; uint32_t dtime=millis()-dtimes[dindex]; if (dtime>delay) { @@ -1604,7 +1604,7 @@ void SML_Decode(uint8_t index) { } nextsect: // next section - if (vindex Date: Wed, 25 Dec 2019 09:57:37 +0100 Subject: [PATCH 152/559] revert --- tasmota/settings.h | 2 +- tasmota/settings.ino | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index dfe35be60..eddc4f04b 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -421,7 +421,7 @@ struct SYSCFG { unsigned long weight_calibration; // 7C4 unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight uint16_t web_refresh; // 7CC - uint8_t script_pram[50]; // 7CE + char script_pram[5][10]; // 7CE char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 8181440d7..6412d3fc9 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1378,6 +1378,11 @@ void SettingsDelta(void) SettingsUpdateText(SET_NTPSERVER1, Settings.ex_ntp_server[0]); SettingsUpdateText(SET_NTPSERVER2, Settings.ex_ntp_server[1]); SettingsUpdateText(SET_NTPSERVER3, Settings.ex_ntp_server[2]); + SettingsUpdateText(SET_MEM1, Settings.script_pram[0]); + SettingsUpdateText(SET_MEM2, Settings.script_pram[1]); + SettingsUpdateText(SET_MEM3, Settings.script_pram[2]); + SettingsUpdateText(SET_MEM4, Settings.script_pram[3]); + SettingsUpdateText(SET_MEM5, Settings.script_pram[4]); SettingsUpdateText(SET_FRIENDLYNAME1, Settings.ex_friendlyname[0]); SettingsUpdateText(SET_FRIENDLYNAME2, Settings.ex_friendlyname[1]); SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]); From 19dbcc777010db4aba0ba5e2be9067fe40bffbb7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Dec 2019 12:39:38 +0100 Subject: [PATCH 153/559] Release 8.1.0 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3412a9c7..35abdb7e6 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases ## Development -[![Dev Version](https://img.shields.io/badge/development%20version-v8.0.x.x-blue.svg)](https://github.com/arendst/Tasmota) +[![Dev Version](https://img.shields.io/badge/development%20version-v8.1.x.x-blue.svg)](https://github.com/arendst/Tasmota) [![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/) [![Build Status](https://img.shields.io/travis/arendst/Tasmota.svg)](https://travis-ci.org/arendst/Tasmota) From b07e6b5386a059a93a4dec118234962a0d8c67a0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Dec 2019 12:59:21 +0100 Subject: [PATCH 154/559] Add fallback information --- RELEASENOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c7566764e..1e048b2f6 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -17,6 +17,8 @@ See [migration path](https://tasmota.github.io/docs/#/Upgrading?id=migration-pat 6. Migrate to **Tasmota 8.1** 7. Migrate to **Tasmota 8.x** +While fallback or downgrading is common practice it was never supported due to Settings additions or changes in newer releases. Starting with release **v8.1.0 Doris** the Settings are re-allocated in such a way that fallback is only allowed and possible to release **v7.2.0 Constance**. Once at v7.2.0 you're on your own when downgrading even further. + ## Supported Core versions This release will be supported from ESP8266/Arduino library Core version **2.6.1** due to reported security and stability issues on previous Core version. From 15acf8487d980794f475804abcc51eb94f2895dc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 25 Dec 2019 13:28:29 +0100 Subject: [PATCH 155/559] Bump version to 8.1.0.1 --- RELEASENOTES.md | 2 +- tasmota/CHANGELOG.md | 10 ++++++++-- tasmota/tasmota_version.h | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1e048b2f6..578d145b9 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,7 +52,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.0.0.3 +### Version 8.1.0 Doris - Change Settings text handling allowing variable length text within a total text pool of 699 characters - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index b351cb091..80c6b480b 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,13 @@ ## Unreleased (development) +### 8.1.0.1 20191225 + +## Released + +### 8.1.0 20191225 + +- Release + ### 8.0.0.3 20191224 - Version bump due to internal Settings change @@ -22,8 +30,6 @@ - Add Zigbee coalesce sensor attributes into a single message - Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 -## Released - ### 7.2.0 20191221 - Release diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 57329bcd1..8bc0a50e1 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08000003; +const uint32_t VERSION = 0x08010001; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; From 4f6a74730016d780273b9a0be1314d5136b59ccf Mon Sep 17 00:00:00 2001 From: Ian Duffy Date: Wed, 25 Dec 2019 21:44:38 +0000 Subject: [PATCH 156/559] Add manufactureURL to the hue description.xml endpoint The netdisco library by HA looks for manufacture, modelNumber and manufactureURL for its auto discovery mechanism. https://github.com/home-assistant/netdisco/blob/master/netdisco/discoverables/philips_hue.py Currently, tasmota doesn't return this, and as a result home assistant doesn't discover the emulator. this commit adds a manufactureURL so discovery works --- tasmota/xdrv_20_hue.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/xdrv_20_hue.ino b/tasmota/xdrv_20_hue.ino index 80e85d821..c9f0031b0 100644 --- a/tasmota/xdrv_20_hue.ino +++ b/tasmota/xdrv_20_hue.ino @@ -124,6 +124,7 @@ const char HUE_DESCRIPTION_XML[] PROGMEM = "Amazon-Echo-HA-Bridge ({x1)" // "Philips hue ({x1)" "Royal Philips Electronics" + "http://www.philips.com" "Philips hue Personal Wireless Lighting" "Philips hue bridge 2012" "929000226503" From aa155f9a52a28421ecb17d9977034d663497ebca Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 25 Dec 2019 21:59:42 -0300 Subject: [PATCH 157/559] AP MODE: Added Restore Config Button --- tasmota/xdrv_01_webserver.ino | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index d86562bb3..b9bad2812 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1693,10 +1693,11 @@ void HandleWifiConfiguration(void) } if (WifiIsInManagerMode()) { - WSContentSpaceButton(BUTTON_RESTART); #ifndef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESTORE); WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); #endif // FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESTART); } else { WSContentSpaceButton(BUTTON_CONFIGURATION); } @@ -1970,7 +1971,11 @@ void HandleRestoreConfiguration(void) WSContentSendStyle(); WSContentSend_P(HTTP_FORM_RST); WSContentSend_P(HTTP_FORM_RST_UPG, D_RESTORE); - WSContentSpaceButton(BUTTON_CONFIGURATION); + if (WifiIsInManagerMode()) { + WSContentSpaceButton(BUTTON_MAIN); + } else { + WSContentSpaceButton(BUTTON_CONFIGURATION); + } WSContentStop(); Web.upload_error = 0; From 96842eed7343b2e782eb2dba7c5aadb5c5abbee0 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Wed, 25 Dec 2019 22:13:17 -0300 Subject: [PATCH 158/559] Better Button Spacing --- tasmota/xdrv_01_webserver.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index b9bad2812..d2b405437 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1695,7 +1695,7 @@ void HandleWifiConfiguration(void) if (WifiIsInManagerMode()) { #ifndef FIRMWARE_MINIMAL WSContentSpaceButton(BUTTON_RESTORE); - WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); + WSContentButton(BUTTON_RESET_CONFIGURATION); #endif // FIRMWARE_MINIMAL WSContentSpaceButton(BUTTON_RESTART); } else { From e8626e9cca73188ba4b07d9f910b2c71fb9fab98 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 26 Dec 2019 12:26:06 +0100 Subject: [PATCH 159/559] Fix command processing Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) --- RELEASENOTES.md | 14 ++------------ tasmota/CHANGELOG.md | 2 ++ tasmota/support.ino | 7 +++++++ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 578d145b9..e2a87362a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,16 +52,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.1.0 Doris +### Version 8.1.0.1 -- Change Settings text handling allowing variable length text within a total text pool of 699 characters -- Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) -- Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) -- Change number of ``FriendlyName``s from 4 to 8 -- Add commands ``WebButton1`` until ``WebButton16`` to support user defined GUI button text (#7166) -- Add support for max 150 characters in most command parameter strings (#3686, #4754) -- Add support for GPS as NTP server by Christian Baars and Adrian Scillato -- Add support for ``AdcParam`` parameters to control ADC0 Moisture formula by Federico Leoni (#7309) -- Add Zigbee coalesce sensor attributes into a single message -- Add Zigbee better support for Xiaomi Double Switch and Xiaomi Vibration sensor -- Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 +- Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 80c6b480b..c208e88b8 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,6 +2,8 @@ ### 8.1.0.1 20191225 +- Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) + ## Released ### 8.1.0 20191225 diff --git a/tasmota/support.ino b/tasmota/support.ino index 4b2bc49fb..9b66fbc2a 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -731,6 +731,13 @@ bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void)) { GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); // Get prefix if available int prefix_length = strlen(XdrvMailbox.command); + if (prefix_length) { + char prefix[prefix_length +1]; + snprintf_P(prefix, sizeof(prefix), XdrvMailbox.topic); // Copy prefix part only + if (strcasecmp(prefix, XdrvMailbox.command)) { + return false; // Prefix not in command + } + } int command_code = GetCommandCode(XdrvMailbox.command + prefix_length, CMDSZ, XdrvMailbox.topic + prefix_length, haystack); if (command_code > 0) { // Skip prefix XdrvMailbox.command_code = command_code -1; From 3fe685d2521b006490f9bd2ed7b1fc1033bf93da Mon Sep 17 00:00:00 2001 From: localhost61 <33861984+localhost61@users.noreply.github.com> Date: Thu, 26 Dec 2019 13:28:27 +0100 Subject: [PATCH 160/559] Update French language to v8.1.0.1 --- tasmota/language/fr-FR.h | 106 +++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 840421ff3..d9d7019f8 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v7.1.2.4 + * Updated until v8.1.0.1 \*********************************************************************/ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -83,7 +83,7 @@ #define D_DNS_SERVER "Serveur DNS" #define D_DONE "Fait" #define D_DST_TIME "DST" -#define D_ECO2 "eCO2" +#define D_ECO2 "eCO₂" #define D_EMULATION "Émulation" #define D_ENABLED "Activé" #define D_ERASE "Effacer" @@ -113,7 +113,7 @@ #define D_LIGHT "Lumière" #define D_LWT "LWT" #define D_MODULE "Module" -#define D_MOISTURE "Moisture" +#define D_MOISTURE "Humidité" #define D_MQTT "MQTT" #define D_MULTI_PRESS "multi-pression" #define D_NOISE "Bruit" @@ -354,7 +354,7 @@ #define D_UPLOAD_ERR_11 "Erreur d'effacement du chip RF" #define D_UPLOAD_ERR_12 "Erreur d'accès en écriture au chip RF" #define D_UPLOAD_ERR_13 "Erreur de décodage du firmware RF" -#define D_UPLOAD_ERR_14 "Not compatible" +#define D_UPLOAD_ERR_14 "Incompatible" #define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement" #define D_ENTER_COMMAND "Saisir une commande" @@ -500,7 +500,7 @@ #define D_CALIBRATE "Étalonner" #define D_CALIBRATION "Étalonnage" -//xsns_35_tx20.ino +//xsns_35_TX20.ino #define D_TX20_WIND_DIRECTION "Direction du vent" #define D_TX20_WIND_SPEED "Vitesse du vent" #define D_TX20_WIND_SPEED_AVG "Vitesse Moy." @@ -521,7 +521,7 @@ #define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" #define D_SENSOR_DFR562 "MP3 Player" -#define D_SENSOR_IRSEND "ÉmetIR" +#define D_SENSOR_IRSEND "IR TX" #define D_SENSOR_SWITCH "Inter." // Suffix "1" #define D_SENSOR_BUTTON "Bouton" // Suffix "1" #define D_SENSOR_RELAY "Relais" // Suffix "1i" @@ -529,15 +529,15 @@ #define D_SENSOR_LED_LINK "LedLink" // Suffix "i" #define D_SENSOR_PWM "PWM" // Suffix "1" #define D_SENSOR_COUNTER "Compteur" // Suffix "1" -#define D_SENSOR_IRRECV "RécptIR" -#define D_SENSOR_MHZ_RX "MHZ Rx" -#define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM004_RX "PZEM004 Rx" -#define D_SENSOR_PZEM016_RX "PZEM016 Rx" -#define D_SENSOR_PZEM017_RX "PZEM017 Rx" -#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" -#define D_SENSOR_SAIR_RX "SAir Rx" -#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_IRRECV "IR RX" +#define D_SENSOR_MHZ_RX "MHZ RX" +#define D_SENSOR_MHZ_TX "MHZ TX" +#define D_SENSOR_PZEM004_RX "PZEM004 RX" +#define D_SENSOR_PZEM016_RX "PZEM016 RX" +#define D_SENSOR_PZEM017_RX "PZEM017 RX" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX TX" +#define D_SENSOR_SAIR_RX "SAir RX" +#define D_SENSOR_SAIR_TX "SAir TX" #define D_SENSOR_SPI_CS "SPI CS" #define D_SENSOR_SPI_DC "SPI DC" #define D_SENSOR_SPI_MISO "SPI MISO" @@ -545,28 +545,28 @@ #define D_SENSOR_SPI_CLK "SPI CLK" #define D_SENSOR_BACKLIGHT "RétroÉcl" #define D_SENSOR_PMS5003 "PMS5003" -#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" -#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" -#define D_SENSOR_HPMA_RX "HPMA Rx" -#define D_SENSOR_HPMA_TX "HPMA Tx" -#define D_SENSOR_SBR_RX "SerBr Rx" -#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SDS0X1_RX "SDS0X1 RX" +#define D_SENSOR_SDS0X1_TX "SDS0X1 TX" +#define D_SENSOR_HPMA_RX "HPMA RX" +#define D_SENSOR_HPMA_TX "HPMA TX" +#define D_SENSOR_SBR_RX "SerBr RX" +#define D_SENSOR_SBR_TX "SerBr TX" #define D_SENSOR_SR04_TRIG "SR04 Tri/TX" #define D_SENSOR_SR04_ECHO "SR04 Ech/RX" -#define D_SENSOR_SDM120_TX "SDMx20 Tx" -#define D_SENSOR_SDM120_RX "SDMx20 Rx" -#define D_SENSOR_SDM630_TX "SDM630 Tx" -#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_SDM120_TX "SDMx20 TX" +#define D_SENSOR_SDM120_RX "SDMx20 RX" +#define D_SENSOR_SDM630_TX "SDM630 TX" +#define D_SENSOR_SDM630_RX "SDM630 RX" #define D_SENSOR_TM1638_CLK "TM16 CLK" #define D_SENSOR_TM1638_DIO "TM16 DIO" #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_TX20_TX "TX20" -#define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" -#define D_SENSOR_TUYA_TX "Tuya Tx" -#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_RFSEND "RF TX" +#define D_SENSOR_RFRECV "RF RX" +#define D_SENSOR_TUYA_TX "Tuya TX" +#define D_SENSOR_TUYA_RX "Tuya RX" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" #define D_SENSOR_MGC3130_RESET "MGC3130 Rst" #define D_SENSOR_SSPI_MISO "SSPI MISO" @@ -575,8 +575,8 @@ #define D_SENSOR_SSPI_CS "SSPI CS" #define D_SENSOR_SSPI_DC "SSPI DC" #define D_SENSOR_RF_SENSOR "RF Sensor" -#define D_SENSOR_AZ_RX "AZ Rx" -#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_AZ_RX "AZ RX" +#define D_SENSOR_AZ_TX "AZ TX" #define D_SENSOR_MAX31855_CS "MX31855 CS" #define D_SENSOR_MAX31855_CLK "MX31855 CLK" #define D_SENSOR_MAX31855_DO "MX31855 DO" @@ -584,13 +584,13 @@ #define D_SENSOR_NRG_CF1 "HLWBL CF1" #define D_SENSOR_HLW_CF "HLW8012 CF" #define D_SENSOR_HJL_CF "BL0937 CF" -#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" -#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_TX "MCP39F5 TX" +#define D_SENSOR_MCP39F5_RX "MCP39F5 RX" #define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" -#define D_SENSOR_CSE7766_TX "CSE7766 Tx" -#define D_SENSOR_CSE7766_RX "CSE7766 Rx" -#define D_SENSOR_PN532_TX "PN532 Tx" -#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_CSE7766_TX "CSE7766 TX" +#define D_SENSOR_CSE7766_RX "CSE7766 RX" +#define D_SENSOR_PN532_TX "PN532 TX" +#define D_SENSOR_PN532_RX "PN532 RX" #define D_SENSOR_SM16716_CLK "SM16716 CLK" #define D_SENSOR_SM16716_DAT "SM16716 DAT" #define D_SENSOR_SM16716_POWER "SM16716 PWR" @@ -598,18 +598,18 @@ #define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" #define D_SENSOR_ARIRFRCV "ALux IrRcv" #define D_SENSOR_ARIRFSEL "ALux IrSel" -#define D_SENSOR_TXD "Serial Tx" -#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_TXD "Série TX" +#define D_SENSOR_RXD "Série RX" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" #define D_SENSOR_HRE_CLOCK "HRE Clock" #define D_SENSOR_HRE_DATA "HRE Data" #define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" #define D_SENSOR_BUZZER "Buzzer" #define D_SENSOR_OLED_RESET "OLED Reset" -#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" -#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" -#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" -#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_ZIGBEE_TXD "Zigbee TX" +#define D_SENSOR_ZIGBEE_RXD "Zigbee RX" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 TX" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 RX" #define D_SENSOR_IBEACON_TX "iBeacon TX" #define D_SENSOR_IBEACON_RX "iBeacon RX" #define D_SENSOR_RDM6300_RX "RDM6300 RX" @@ -620,19 +620,19 @@ #define D_SENSOR_A4988_MS1 "A4988 MS1" #define D_SENSOR_A4988_MS2 "A4988 MS2" #define D_SENSOR_A4988_MS3 "A4988 MS3" -#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" -#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" -#define D_SENSOR_DDSU666_TX "DDSU666 Tx" -#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_DDS2382_TX "DDS238-2 TX" +#define D_SENSOR_DDS2382_RX "DDS238-2 RX" +#define D_SENSOR_DDSU666_TX "DDSU666 TX" +#define D_SENSOR_DDSU666_RX "DDSU666 RX" #define D_SENSOR_SM2135_CLK "SM2135 Clk" #define D_SENSOR_SM2135_DAT "SM2135 Dat" -#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_DEEPSLEEP "Hibernation" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" -#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_SLAVE_TX "Esclave TX" +#define D_SENSOR_SLAVE_RX "Esclave RX" +#define D_SENSOR_SLAVE_RESET "Esclave Rst" #define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_GPS_RX "GPS RX" // Units #define D_UNIT_AMPERE "A" @@ -647,7 +647,7 @@ #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" #define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" From baacd946252350eb429caf79cf1b78f43704d271 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 26 Dec 2019 17:23:10 +0100 Subject: [PATCH 161/559] Update de-DE.h --- tasmota/language/de-DE.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 89d36103d..9e30f42f8 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -28,7 +28,7 @@ * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. * Use online command Prefix to translate cmnd, stat and tele. * - * Updated until v8.0.0 + * Updated until v8.1.0.1 \*********************************************************************/ //#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) @@ -66,7 +66,7 @@ #define D_BYTES "Bytes" #define D_CELSIUS "Celsius" #define D_CHANNEL "Kanal" -#define D_CO2 "CO²" +#define D_CO2 "CO₂" #define D_CODE "code" // Button code #define D_COLDLIGHT "kalt" #define D_COMMAND "Befehl" @@ -83,7 +83,7 @@ #define D_DNS_SERVER "DNS-Server" #define D_DONE "erledigt" #define D_DST_TIME "DST" -#define D_ECO2 "eCO2" +#define D_ECO2 "eCO₂" #define D_EMULATION "Emulation" #define D_ENABLED "aktiviert" #define D_ERASE "löschen" @@ -647,7 +647,7 @@ #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" -#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m3" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" #define D_UNIT_MICROMETER "µm" #define D_UNIT_MICROSECOND "µs" #define D_UNIT_MILLIAMPERE "mA" From 35e306f41047c6c842add3b6742c312a8b3d9793 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Thu, 26 Dec 2019 19:11:51 +0100 Subject: [PATCH 162/559] Update pl-PL.h Update PL to last changes. --- tasmota/language/pl-PL.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 58168516d..4f2c9c069 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -62,7 +62,7 @@ #define D_BRIGHTLIGHT "Jasny" #define D_BSSID "BSSId" #define D_BUTTON "Przycisk" -#define D_BY "by" // Written by me +#define D_BY "przez" // Written by me #define D_BYTES "Bajtów" #define D_CELSIUS "Celsiusz" #define D_CHANNEL "Kanał" @@ -71,7 +71,7 @@ #define D_COLDLIGHT "Zimny" #define D_COMMAND "Komenda" #define D_CONNECTED "Połączony" -#define D_CORS_DOMAIN "CORS Domain" +#define D_CORS_DOMAIN "Domena CORS" #define D_COUNT "Licz" #define D_COUNTER "Licznik" #define D_CURRENT "Prąd" // As in Voltage and Current @@ -113,7 +113,7 @@ #define D_LIGHT "Światło" #define D_LWT "LWT" #define D_MODULE "Moduł" -#define D_MOISTURE "Moisture" +#define D_MOISTURE "Wilgotność" #define D_MQTT "MQTT" #define D_MULTI_PRESS "Wielokrotne naciśnięcie" #define D_NOISE "Szum" From 6ebe7b219b1cbef0d3834cd51f04fd6e8fc16275 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Thu, 26 Dec 2019 22:07:29 +0100 Subject: [PATCH 163/559] Fix White blend mode #7325 --- tasmota/xdrv_04_light.ino | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index d6e71ab08..a7f996914 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1682,8 +1682,10 @@ void LightAnimate(void) cur_col_10bits[i] = changeUIntScale(cur_col_10bits[i] - min_rgb_10, 0, 1023, 0, adjust10); cur_col[i] = changeUIntScale(cur_col[i] - min_rgb, 0, 255, 0, Settings.rgbwwTable[i]); } + // compute the adjusted white levels for 10 and 8 bits - uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 255, 0, Settings.rgbwwTable[3]); // set white power down corrected with rgbwwTable[3] + uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); + uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); // set white power down corrected with rgbwwTable[3] uint32_t white = changeUIntScale(min_rgb, 0, 255, 0, Settings.rgbwwTable[3]); // set white power down corrected with rgbwwTable[3] if (LST_RGBW == Light.subtype) { // we simply set the white channel @@ -1863,8 +1865,9 @@ void LightSetOutputs(const uint8_t *cur_col, const uint16_t *cur_col_10bits) { } } } - // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("LGT: R %02X(%d) G %02X(%d) B %02X(%d), CW %02X(%d) WW %02x(%d), D %d"), - // cur_col[0], cur_col_10bits[0], cur_col[1], cur_col_10bits[1], cur_col[2], cur_col_10bits[2], cur_col[3], cur_col_10bits[3], cur_col[4], cur_col_10bits[4], light_state.getDimmer()); + char msg[24]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Channels %s"), + ToHex_P((const unsigned char *)cur_col_10bits, 10, msg, sizeof(msg))); // Some devices need scaled RGB like Sonoff L1 // TODO, should be probably moved to the Sonoff L1 support code @@ -1873,8 +1876,6 @@ void LightSetOutputs(const uint8_t *cur_col, const uint16_t *cur_col_10bits) { for (uint32_t i = 0; i < 3; i++) { scale_col[i] = (0 == max) ? 255 : (255 > max) ? changeUIntScale(cur_col[i], 0, max, 0, 255) : cur_col[i]; } - // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("LGT: R%d(%d) G%d(%d) B%d(%d), C%d(%d) W%d(%d), D%d"), - // cur_col[0], scale_col[0], cur_col[1], scale_col[1], cur_col[2], scale_col[2], cur_col[3], scale_col[3], cur_col[4], scale_col[4], light_state.getDimmer()); char *tmp_data = XdrvMailbox.data; char *tmp_topic = XdrvMailbox.topic; From 24aff9b4156d82e4056cb6bb6106c4325ff9001f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:13:22 +0100 Subject: [PATCH 164/559] Add info to Status 0 - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` --- RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 2 ++ tasmota/support_command.ino | 12 ++++++------ tasmota/support_wifi.ino | 7 +++++++ 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e2a87362a..f7eabdb5b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -55,3 +55,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ### Version 8.1.0.1 - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) +- Add SerialConfig to ``Status 1`` +- Add WifiPower to ``Status 5`` diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index c208e88b8..a6bc376b6 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,8 @@ ### 8.1.0.1 20191225 - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) +- Add SerialConfig to ``Status 1`` +- Add WifiPower to ``Status 5`` ## Released diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index f6413dd57..53f4601a8 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -193,7 +193,7 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) // backlog_delay = millis() + (100 * MIN_BACKLOG_DELAY); backlog_delay = millis() + Settings.param[P_BACKLOG_DELAY]; - char command[CMDSZ]; + char command[CMDSZ] = { 0 }; XdrvMailbox.command = command; XdrvMailbox.index = index; XdrvMailbox.data_len = data_len; @@ -368,10 +368,10 @@ void CmndStatus(void) } if ((0 == payload) || (1 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_SERIALCONFIG "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), - baudrate, SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), + baudrate, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); @@ -417,10 +417,10 @@ void CmndStatus(void) if ((0 == payload) || (5 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\"" D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" - D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d}}"), + D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"), my_hostname, WiFi.localIP().toString().c_str(), IPAddress(Settings.ip_address[1]).toString().c_str(), IPAddress(Settings.ip_address[2]).toString().c_str(), IPAddress(Settings.ip_address[3]).toString().c_str(), WiFi.macAddress().c_str(), - Settings.webserver, Settings.sta_config); + Settings.webserver, Settings.sta_config, WifiGetOutputPower().c_str()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "5")); } @@ -1607,7 +1607,7 @@ void CmndWifiPower(void) } WifiSetOutputPower(); } - ResponseCmndFloat((float)(Settings.wifi_output_power) / 10, 1); + ResponseCmndChar(WifiGetOutputPower().c_str()); } #ifdef USE_I2C diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index c283f1bb5..0d54723ca 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -587,6 +587,13 @@ int WifiState(void) return state; } +String WifiGetOutputPower(void) +{ + char stemp1[TOPSZ]; + dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); + return String(stemp1); +} + void WifiSetOutputPower(void) { WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); From 5682675ac9faa14c6a80c80f3754015191d88900 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 27 Dec 2019 15:13:40 +0100 Subject: [PATCH 165/559] Fix some serial interface initializations Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/support.ino | 17 +++++++++-------- tasmota/support_tasmota.ino | 10 +++------- tasmota/tasmota.ino | 2 -- tasmota/xdrv_06_snfbridge.ino | 3 +-- tasmota/xdrv_22_sonoff_ifan.ino | 4 +--- tasmota/xlgt_05_sonoff_l1.ino | 3 +-- tasmota/xnrg_02_cse7766.ino | 3 +-- tasmota/xsns_04_snfsc.ino | 6 +++--- 10 files changed, 21 insertions(+), 29 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f7eabdb5b..b3b5c8c2d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -54,6 +54,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ### Version 8.1.0.1 +- Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index a6bc376b6..321d405c5 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,6 +2,7 @@ ### 8.1.0.1 20191225 +- Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` diff --git a/tasmota/support.ino b/tasmota/support.ino index 9b66fbc2a..32ef55731 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -790,14 +790,9 @@ String GetSerialConfig(void) void SetSerialBegin(uint32_t baudrate) { - if (seriallog_level) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Set Serial to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); - delay(100); - } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Set Serial to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); Serial.flush(); Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); - delay(10); - Serial.println(); } void SetSerialConfig(uint32_t serial_config) @@ -812,11 +807,17 @@ void SetSerialConfig(uint32_t serial_config) void SetSerialBaudrate(int baudrate) { Settings.baudrate = baudrate / 300; - if (Serial.baudRate() == baudrate) { return; } - SetSerialBegin(baudrate); } +void PrepSerial(int prep_baudrate, uint32_t serial_config) +{ + Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG + Settings.serial_config = serial_config; + baudrate = prep_baudrate; + SetSeriallog(LOG_LEVEL_NONE); +} + void ClaimSerial(void) { serial_local = true; diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index c649d9379..153d8a1fd 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1296,20 +1296,16 @@ void GpioInit(void) // devices_present = 1; } else if (SONOFF_DUAL == my_module_type) { - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG devices_present = 2; - baudrate = 19200; + PrepSerial(19200, TS_SERIAL_8N1); } else if (CH4 == my_module_type) { - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG devices_present = 4; - baudrate = 19200; + PrepSerial(19200, TS_SERIAL_8N1); } #ifdef USE_SONOFF_SC else if (SONOFF_SC == my_module_type) { - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG - devices_present = 0; - baudrate = 19200; + PrepSerial(19200, TS_SERIAL_8N1); } #endif // USE_SONOFF_SC diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index e80331366..e2866347e 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -194,8 +194,6 @@ void setup(void) RtcRebootSave(); Serial.begin(baudrate); - delay(10); - Serial.println(); seriallog_level = LOG_LEVEL_INFO; // Allow specific serial messages until config loaded snprintf_P(my_version, sizeof(my_version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); // Release version 6.3.0 diff --git a/tasmota/xdrv_06_snfbridge.ino b/tasmota/xdrv_06_snfbridge.ino index 9f8a852d5..56ba3dabc 100644 --- a/tasmota/xdrv_06_snfbridge.ino +++ b/tasmota/xdrv_06_snfbridge.ino @@ -578,8 +578,7 @@ bool Xdrv06(uint8_t function) SonoffBridgeSendCommand(0xA7); // Stop reading RF signals enabling iTead default RF handling break; case FUNC_PRE_INIT: - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG - baudrate = 19200; + PrepSerial(19200, TS_SERIAL_8N1); break; } } diff --git a/tasmota/xdrv_22_sonoff_ifan.ino b/tasmota/xdrv_22_sonoff_ifan.ino index b260952f4..125800367 100644 --- a/tasmota/xdrv_22_sonoff_ifan.ino +++ b/tasmota/xdrv_22_sonoff_ifan.ino @@ -217,9 +217,7 @@ void CmndFanspeed(void) bool SonoffIfanInit(void) { if (SONOFF_IFAN03 == my_module_type) { - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG - baudrate = 9600; - SetSeriallog(LOG_LEVEL_NONE); + PrepSerial(9600, TS_SERIAL_8N1); } return false; // Continue init chain } diff --git a/tasmota/xlgt_05_sonoff_l1.ino b/tasmota/xlgt_05_sonoff_l1.ino index 3fef84576..11059f6ff 100644 --- a/tasmota/xlgt_05_sonoff_l1.ino +++ b/tasmota/xlgt_05_sonoff_l1.ino @@ -222,8 +222,7 @@ void SnfL1ModuleSelected(void) { if (SONOFF_L1 == my_module_type) { if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { - Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG - baudrate = 19200; + PrepSerial(19200, TS_SERIAL_8N1); light_type = LT_RGB; light_flg = XLGT_05; diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino index d52ee9ca3..a10f6cc9d 100644 --- a/tasmota/xnrg_02_cse7766.ino +++ b/tasmota/xnrg_02_cse7766.ino @@ -210,8 +210,7 @@ void CseEverySecond(void) void CseDrvInit(void) { if ((3 == pin[GPIO_CSE7766_RX]) && (1 == pin[GPIO_CSE7766_TX])) { // As it uses 8E1 currently only hardware serial is supported - baudrate = 4800; - Settings.serial_config = TS_SERIAL_8E1; + PrepSerial(4800, TS_SERIAL_8E1); if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255 } diff --git a/tasmota/xsns_04_snfsc.ino b/tasmota/xsns_04_snfsc.ino index 060321349..7f83f4e06 100644 --- a/tasmota/xsns_04_snfsc.ino +++ b/tasmota/xsns_04_snfsc.ino @@ -159,9 +159,6 @@ bool Xsns04(uint8_t function) if (SONOFF_SC == my_module_type) { switch (function) { - case FUNC_INIT: - SonoffScInit(); - break; case FUNC_JSON_APPEND: SonoffScShow(1); break; @@ -170,6 +167,9 @@ bool Xsns04(uint8_t function) SonoffScShow(0); break; #endif // USE_WEBSERVER + case FUNC_INIT: + SonoffScInit(); + break; } } return result; From 782414c35d8eaa23d52518c3feafad5b6f15e246 Mon Sep 17 00:00:00 2001 From: Leonid Muravjev Date: Fri, 20 Dec 2019 22:29:54 +0300 Subject: [PATCH 166/559] ds1624: support for ds1621 and ds1624 [x] the I2C address reservation implemented. [x] multiple sensors any combination with 8 addresses [x] with and without HotPlug support --- BUILDS.md | 3 +- I2CDEVICES.md | 2 + RELEASENOTES.md | 2 + tasmota/tasmota_post.h | 1 + tasmota/xsns_59_ds1624.ino | 200 +++++++++++++++++++++++++++++++++++++ tools/decode-status.py | 2 +- 6 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 tasmota/xsns_59_ds1624.ino diff --git a/BUILDS.md b/BUILDS.md index 5c897746a..4318635ec 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -107,6 +107,7 @@ | USE_PCF8574 | - | - | - | - | - | - | - | | USE_HIH6 | - | - | - | - | x | - | - | | USE_DHT12 | - | - | - | - | x | - | - | +| USE_DS1624 | - | - | - | - | x | - | - | | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | @@ -148,4 +149,4 @@ | USE_DISPLAY_EPAPER_42 | - | - | - | - | - | - | x | | USE_DISPLAY_ILI9488 | - | - | - | - | - | - | - | | USE_DISPLAY_SSD1351 | - | - | - | - | - | - | - | -| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | \ No newline at end of file +| USE_DISPLAY_RA8876 | - | - | - | - | - | - | - | diff --git a/I2CDEVICES.md b/I2CDEVICES.md index 6d0de4e1a..c7b42108f 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -62,4 +62,6 @@ Index | Define | Driver | Device | Address(es) | Description 39 | USE_DISPLAY_RA8876 | xdsp_10 | FT5316 | 0x38 | Touch panel controller 40 | USE_TSL2591 | xsns_57 | TLS2591 | 0x29 | Light intensity sensor 41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor + 42 | USE_DS1624 | xsns_59 | DS1621 | 0x48 - 0x4F | Temperature sensor + 42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e2a87362a..fb7a2436c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -50,6 +50,8 @@ The following binary downloads have been compiled with ESP8266/Arduino library c [Complete list](BUILDS.md) of available feature and sensors. +For merge for Changelog: +- Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev ## Changelog ### Version 8.1.0.1 diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index c9f8396fe..5571da265 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -137,6 +137,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack //#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code) #define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code) #define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0k7 code) +#define USE_DS1624 // Add I2C code for DS1624, DS1621 sensor //#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code) //#define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) diff --git a/tasmota/xsns_59_ds1624.ino b/tasmota/xsns_59_ds1624.ino new file mode 100644 index 000000000..82ce7d8f6 --- /dev/null +++ b/tasmota/xsns_59_ds1624.ino @@ -0,0 +1,200 @@ +/* + xsns_59_ds1624.ino - Support for I2C DS1624 Temperature Sensor + + Copyright (C) 2019 Leonid Myravjev + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_I2C +#ifdef USE_DS1624 + +/*********************************************************************************************\ + * DS1624,DS1621 - Temperature + * + * I2C Address: 0x48 - 0x4F +\*********************************************************************************************/ + +#define XSNS_59 59 +#define XI2C_42 42 // See I2CDEVICES.md + +#define DS1624_MEM_REGISTER 0x17 //only for ds1624, don't exists on 1621 +#define DS1624_CONF_REGISTER 0xAC +#define DS1624_TEMP_REGISTER 0xAA +#define DS1624_START_REGISTER 0xEE +#define DS1624_STOP_REGISTER 0x22 + +#define DS1621_COUNTER_REGISTER 0xA8 //exists on 1621 and 1624(undocumented) +#define DS1621_SLOPE_REGISTER 0xA9 //exists on 1624 and 1624(undocumented) + +enum { + DS1624_TYPE_DS1624, + DS1624_TYPE_DS1621 +}; + +#define DS1624_MAX_SENSORS 8 +bool ds1624_init=false; +struct { + bool valid; + float value; + int type; + char name[9]; +} ds1624_sns[DS1624_MAX_SENSORS]; + +uint32_t DS1624_Idx2Addr(int idx) { + return 0x48 + idx; +} + +void DS1624_HotPlugUp(int idx) { + uint32_t addr; + uint8_t config,tmp; + + addr = DS1624_Idx2Addr(idx); + if (I2cActive(addr)) return; + if (!I2cSetDevice(addr)) return; + if (I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { + if (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) + ds1624_sns[idx].type=DS1624_TYPE_DS1624; + else ds1624_sns[idx].type=DS1624_TYPE_DS1621; + if (ds1624_sns[idx].type==DS1624_TYPE_DS1621) + snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS1621_%d"), idx); + else snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS1624_%d"), idx); + I2cSetActiveFound(addr, ds1624_sns[idx].name); + ds1624_sns[idx].valid=true; + if ((config & 1) == 1) { + config &= 0xfe; + I2cWrite8(addr, DS1624_CONF_REGISTER, config); //1show off + delay(10);// by spec after writing + } + I2cValidRead(addr, DS1624_START_REGISTER, 1); //FIXME 0 must read, but 0 isn't work for tasmota + AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); + } +} + +void DS1624_HotPlugDown(int idx) { + uint32_t addr=DS1624_Idx2Addr(idx); + if (I2cActive(addr)==false) return; + I2cResetActive(addr); + ds1624_sns[idx].valid=false; + AddLog_P2(LOG_LEVEL_INFO, "Hot UnPlug %s", ds1624_sns[idx].name); +} + +bool DS1624GetTemp(float *value, int idx) +{ + uint16_t t; + bool result; + uint32_t addr=DS1624_Idx2Addr(idx); + + if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) return false; + *value = ConvertTemp(((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625); + if (ds1624_sns[idx].type==DS1624_TYPE_DS1621) { // Higher resolution + uint8_t perc,remain; + if (I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)==false) return true; + if (I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)==false) return true; + *value += ((float)perc - (float)remain)/((float)perc) - 0.25; + } + return true; +} + +void DS1624HotPlugScan(void) +{ + uint16_t t; + + for (int idx = 0; idx < DS1624_MAX_SENSORS; idx++) { + uint32_t addr=DS1624_Idx2Addr(idx); + if ((I2cActive(addr)==true) && (ds1624_sns[idx].valid==false)) + continue; // is busy by another driver + if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { + DS1624_HotPlugDown(idx); + continue; } + DS1624_HotPlugUp(idx); + } +} + +void DS1624EverySecond(void) +{ + float t; + for (int i = 0; i < DS1624_MAX_SENSORS; i++) { + if (ds1624_sns[i].valid==false) continue; + if (!DS1624GetTemp(&t, i)) continue; + ds1624_sns[i].value=t; + } +} + +void DS1624Show(bool json) +{ + int i; + char temperature[33]; + + for (i = 0; i < DS1624_MAX_SENSORS; i++) { + if (ds1624_sns[i].valid==false) continue; + + dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds1624_sns[i].name, temperature); + if (0 == tele_period) { //FIXME 0==i WTF? + #ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); + #endif // USE_DOMOTICZ + #ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, temperature); + #endif // USE_KNX + } + #ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds1624_sns[i].name, temperature, TempUnit()); + #endif // USE_WEBSERVER + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define FUNC_HOTPLUG_SCAN 999 // FIXME remove it after HOTPLUG supported + +bool Xsns59(uint8_t function) +{ + if (!I2cEnabled(XI2C_20)) { return false; } + + bool result = false; + if (FUNC_INIT == function) { + if (ds1624_init==false) { + memset(ds1624_sns, 0, sizeof(ds1624_sns)); + ds1624_init=true; + DS1624HotPlugScan(); //If HotPlug is off + } + } + switch (function) { + case FUNC_HOTPLUG_SCAN: + DS1624HotPlugScan(); + break; + case FUNC_EVERY_SECOND: + DS1624EverySecond(); + break; + case FUNC_JSON_APPEND: + DS1624Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DS1624Show(0); + break; + #endif // USE_WEBSERVER + } + return result; +} + +#endif // USE_DS1624 +#endif // USE_I2C diff --git a/tools/decode-status.py b/tools/decode-status.py index 492c300fa..81c5c0fc1 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -188,7 +188,7 @@ a_features = [[ "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", - "USE_DHT12","","USE_GPS","", + "USE_DHT12","USE_DS1624","USE_GPS","", "","","","", "","","","" ]] From e48e5859cddeee636e43d01749482212aed3e491 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Fri, 27 Dec 2019 21:02:23 +0100 Subject: [PATCH 167/559] Change Lights: simplified gamma correction and 10 bits internal computation --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_04_light.ino | 341 ++++++++++++++++++-------------------- 2 files changed, 166 insertions(+), 176 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 321d405c5..077384325 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,6 +6,7 @@ - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` +- Change Lights: simplified gamma correction and 10 bits internal computation ## Released diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index a7f996914..ecb966053 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -112,12 +112,11 @@ * to adjust leds with different power * .g If rgbwwTable[4] is zero, blend RGB with White and adjust the level of * White channel according to rgbwwTable[3] - * .h Avoid PMW values between 1008 and 1022, issue #1146 - * .i Scale ranges from 10 bits to 0..PWMRange (by default 1023) so no change + * .h Scale ranges from 10 bits to 0..PWMRange (by default 1023) so no change * by default. - * .j Apply port remapping from Option37 - * .k Invert PWM value if port is of type PMWxi instead of PMWx - * .l Apply PWM value with analogWrite() - if pin is configured + * .i Apply port remapping from Option37 + * .j Invert PWM value if port is of type PMWxi instead of PMWx + * .k Apply PWM value with analogWrite() - if pin is configured * \*********************************************************************************************/ @@ -161,73 +160,82 @@ struct LCwColor { const uint8_t MAX_FIXED_COLD_WARM = 4; const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; -// New version of Gamma correction table, with adaptative resolution -// from 11 bits (lower values) to 8 bits (upper values). -// We're using the fact that lower values are small and can fit within 8 bits -// To save flash space, the array is only 8 bits uint -#ifdef XFUNC_PTR_IN_ROM -const uint8_t _ledTable[] PROGMEM = { -#else -const uint8_t _ledTable[] = { -#endif - // 11 bits resolution - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, // 11 bits, 0..2047 - 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, // 11 bits, 0..2047 - 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, // 11 bits, 0..2047 - 20, 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 35, 37, 38, 40, 42, // 11 bits, 0..2047 - // 10 bits resolution - 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 38, 39, // 10 bits, 0..1023 - 41, 42, 44, 45, 47, 48, 50, 51, 53, 55, 56, 58, 60, 62, 64, 65, // 10 bits, 0..1023 - 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 96, 98,101, // 10 bits, 0..1023 - 103,106,108,111,114,116,119,122,125,128,131,134,137,140,143,146, // 10 bits, 0..1023 - // 9 bits resolution - 75, 77, 78, 80, 82, 84, 85, 87, 89, 91, 93, 94, 96, 98,100,102, // 9 bits, 0..511 - 104,106,108,110,112,115,117,119,121,123,125,128,130,132,135,137, // 9 bits, 0..511 - 140,142,144,147,149,152,155,157,160,163,165,168,171,173,176,179, // 9 bits, 0..511 - 182,185,188,191,194,197,200,203,206,209,212,215,219,222,225,229, // 9 bits, 0..511 - // 8 bits resolution - 116,118,120,121,123,125,127,128,130,132,134,136,138,139,141,143, // 8 bits, 0..255 - 145,147,149,151,153,155,157,159,161,163,165,168,170,172,174,176, // 8 bits, 0..255 - 178,181,183,185,187,190,192,194,197,199,201,204,206,209,211,214, // 8 bits, 0..255 - 216,219,221,224,226,229,232,234,237,240,242,245,248,250,253,255 // 8 bits, 0..255 +// New version of Gamma correction compute +// Instead of a table, we do a multi-linear approximation, which is close enough +// At low levels, the slope is a bit higher than actual gamma, to make changes smoother +// Internal resolution is 10 bits. + +typedef struct gamma_table_t { + uint16_t to_src; + uint16_t to_gamma; +} gamma_table_t; + +const gamma_table_t gamma_table[] = { // don't put in PROGMEM for performance reasons + { 3, 0 }, + { 209, 13 }, + { 312, 41 }, + { 457, 106 }, + { 626, 261 }, + { 762, 450 }, + { 895, 703 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } // fail-safe if out of range +}; + +// simplified Gamma table for Fade, cheating a little at low brightness +const gamma_table_t gamma_table_fast[] = { + { 0, 0 }, + { 384, 67 }, + { 768, 467 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } // fail-safe if out of range }; // For reference, below are the computed gamma tables, via ledGamma() // for 8 bits output: -// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, -// 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, -// 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, -// 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, -// 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, -// 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, -// 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47, 48, 49, 50, 51, -// 52, 53, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, -// 70, 71, 72, 74, 75, 76, 78, 79, 80, 82, 83, 84, 86, 87, 88, 90, -// 91, 93, 94, 96, 97, 99,100,102,103,105,106,108,110,111,113,115, -//116,118,120,121,123,125,127,128,130,132,134,136,138,139,141,143, -//145,147,149,151,153,155,157,159,161,163,165,168,170,172,174,176, -//178,181,183,185,187,190,192,194,197,199,201,204,206,209,211,214, -//216,219,221,224,226,229,232,234,237,240,242,245,248,250,253,255 +// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +// 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, +// 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, +// 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, +// 6, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, +// 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, +// 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, +// 25, 26, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 37, 38, +// 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, +// 54, 55, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 66, 68, 69, +// 71, 72, 73, 75, 76, 78, 79, 80, 82, 83, 85, 86, 87, 88, 90, 91, +// 93, 94, 95, 97, 98,100,101,102,104,105,107,108,109,111,112,114, +// 116,118,120,121,123,125,127,129,131,133,135,137,139,141,142,144, +// 146,148,150,152,154,156,158,160,162,164,166,168,170,171,173,175, +// 177,180,182,185,187,190,192,195,197,200,202,205,207,210,212,215, +// 217,220,222,225,227,230,233,235,238,240,243,245,248,250,253,255 // // and for 10 bits output: -// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -// 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, -// 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, -// 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17, 18, 19, 19, 20, 21, -// 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 38, 39, -// 41, 42, 44, 45, 47, 48, 50, 51, 53, 55, 56, 58, 60, 62, 64, 65, -// 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 96, 98,101, -//103,106,108,111,114,116,119,122,125,128,131,134,137,140,143,146, -//151,155,157,161,165,169,171,175,179,183,187,189,193,197,201,205, -//209,213,217,221,225,231,235,239,243,247,251,257,261,265,271,275, -//281,285,289,295,299,305,311,315,321,327,331,337,343,347,353,359, -//365,371,377,383,389,395,401,407,413,419,425,431,439,445,451,459, -//467,475,483,487,495,503,511,515,523,531,539,547,555,559,567,575, -//583,591,599,607,615,623,631,639,647,655,663,675,683,691,699,707, -//715,727,735,743,751,763,771,779,791,799,807,819,827,839,847,859, -//867,879,887,899,907,919,931,939,951,963,971,983,995,1003,1015,1023 +// 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, +// 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, +// 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, +// 12, 12, 13, 13, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, +// 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42, 44, +// 46, 47, 49, 51, 53, 54, 56, 58, 60, 62, 63, 65, 67, 69, 70, 72, +// 74, 76, 78, 79, 81, 83, 85, 86, 88, 90, 92, 94, 95, 97, 99, 101, +// 102, 104, 106, 110, 113, 117, 121, 124, 128, 132, 135, 139, 143, 146, 150, 154, +// 158, 162, 166, 169, 173, 177, 180, 184, 188, 191, 195, 199, 202, 206, 210, 213, +// 217, 221, 224, 228, 232, 235, 239, 243, 246, 250, 254, 257, 261, 266, 272, 277, +// 283, 288, 294, 300, 305, 311, 316, 322, 327, 333, 339, 344, 350, 355, 361, 366, +// 372, 378, 383, 389, 394, 400, 405, 411, 417, 422, 428, 433, 439, 444, 450, 457, +// 464, 472, 480, 487, 495, 503, 510, 518, 525, 533, 541, 548, 556, 564, 571, 579, +// 587, 594, 602, 609, 617, 627, 634, 642, 650, 657, 665, 672, 680, 688, 695, 703, +// 712, 722, 732, 742, 752, 762, 772, 782, 792, 802, 812, 822, 832, 842, 852, 862, +// 872, 882, 892, 902, 912, 923, 933, 943, 953, 963, 973, 983, 993,1003,1013,1023 +// +// Output for Dimmer 0..100 values +// 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, +// 10, 10, 11, 12, 12, 13, 16, 18, 21, 23, 26, 29, 32, 34, 37, +// 40, 44, 49, 53, 58, 62, 67, 70, 76, 79, 85, 90, 94, 99,102, +// 110,117,128,135,146,158,166,177,184,195,202,213,221,232,239, +// 250,261,272,288,300,316,327,344,355,372,389,400,417,428,444, +// 457,480,495,518,533,556,579,594,617,634,657,672,695,712,742, +// 772,792,822,842,872,892,923,943,973,993,1023 struct LIGHT { uint32_t strip_timer_counter = 0; // Bars and Gradient @@ -256,9 +264,6 @@ struct LIGHT { bool pwm_multi_channels = false; // SetOption68, treat each PWM channel as an independant dimmer bool fade_running = false; - uint8_t fade_start_8[LST_MAX] = {0,0,0,0,0}; - uint8_t fade_cur_8[LST_MAX]; - uint8_t fade_end_8[LST_MAX]; // 8 bits resolution target channel values uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; uint16_t fade_cur_10[LST_MAX]; uint16_t fade_end_10[LST_MAX]; // 10 bits resolution target channel values @@ -1072,36 +1077,53 @@ public: LightStateClass light_state = LightStateClass(); LightControllerClass light_controller = LightControllerClass(light_state); +/*********************************************************************************************\ + * Change scales from 8 bits to 10 bits and vice versa +\*********************************************************************************************/ +// 8 to 10 to 8 is garanteed to give the same result +uint16_t change8to10(uint8_t v) { + return changeUIntScale(v, 0, 255, 0, 1023); +} +// change from 10 bits to 8 bits, but any non-zero input will be non-zero +uint8_t change10to8(uint16_t v) { + return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); +} + /*********************************************************************************************\ * Gamma correction \*********************************************************************************************/ // Calculate the gamma corrected value for LEDS -// You can request 11, 10, 9 or 8 bits resolution via 'bits_out' parameter -uint16_t ledGamma(uint8_t v, uint16_t bits_out = 8) { - uint16_t result; - // bits_resolution: the resolution of _ledTable[v], between 8 and 11 - uint32_t bits_resolution = 11 - (v / 64); // 8..11 - int32_t bits_correction = bits_out - bits_resolution; // -3..3 -#ifdef XFUNC_PTR_IN_ROM - uint32_t uncorrected_value = pgm_read_byte(_ledTable + v); // 0..255 -#else - uint32_t uncorrected_value = _ledTable[v]; // 0..255 -#endif - if (0 == bits_correction) { - // we already match the required resolution, no change - result = uncorrected_value; - } else if (bits_correction > 0) { - // the output resolution is higher than our value, we need to extrapolate - // we shift by bits_correction, and force last bits to 1 - uint32_t bits_mask = (1 << bits_correction) - 1; // 1, 3, 7 - result = (uncorrected_value << bits_correction) | bits_mask; - } else { // bits_correction < 0 - // our resolution is too high, we need to remove bits - // we add 1, 3 or 7 to force rouding to the nearest high value - uint32_t bits_mask = (1 << -bits_correction) - 1; // 1, 3, 7 - result = ((uncorrected_value + bits_mask) >> -bits_correction); +uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (v <= to_src) { + return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); + } + from_src = to_src + 1; + from_gamma = to_gamma + 1; } - return result; +} +// 10_10 bits, fast fade mode +uint16_t ledGamma10_10_fast(uint16_t v) { + return ledGamma_internal(v, gamma_table_fast); +} + +// 10 bits in, 10 bits out +uint16_t ledGamma10_10(uint16_t v) { + return ledGamma_internal(v, gamma_table); +} +// 10 bits resolution, 8 bits in +uint16_t ledGamma10(uint8_t v) { + return ledGamma10_10(change8to10(v)); +} + +// Legacy function +uint8_t ledGamma(uint8_t v) { + return change10to8(ledGamma10(v)); } /********************************************************************************************/ @@ -1569,7 +1591,6 @@ void LightSetPower(void) // Light.power tells which lights or channels (SetOption68) are on/off void LightAnimate(void) { - uint8_t cur_col[LST_MAX]; uint16_t light_still_on = 0; bool power_off = false; @@ -1653,92 +1674,73 @@ void LightAnimate(void) Light.update = true; } if (Light.update) { - uint16_t cur_col_10bits[LST_MAX]; // 10 bits version of cur_col for PWM + uint16_t cur_col_10[LST_MAX]; // 10 bits resolution Light.update = false; // first set 8 and 10 bits channels for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col[i] = Light.last_color[i] = Light.new_color[i]; + Light.last_color[i] = Light.new_color[i]; // Extend from 8 to 10 bits if no correction (in case no gamma correction is required) - cur_col_10bits[i] = changeUIntScale(cur_col[i], 0, 255, 0, 1023); + cur_col_10[i] = change8to10(Light.new_color[i]); } if (Light.pwm_multi_channels) { - calcGammaMultiChannels(cur_col, cur_col_10bits); + calcGammaMultiChannels(cur_col_10); } else { - calcGammaBulbs(cur_col, cur_col_10bits); + calcGammaBulbs(cur_col_10); if (PHILIPS == my_module_type) { - calcGammaCTPwm(cur_col, cur_col_10bits); + calcGammaCTPwm(cur_col_10); } // Now see if we need to mix RGB and True White // Valid only for LST_RGBW, LST_RGBWC, rgbwwTable[4] is zero, and white is zero (see doc) - if ((LST_RGBW <= Light.subtype) && (0 == Settings.rgbwwTable[4]) && (0 == cur_col[3]+cur_col[4])) { - uint32_t min_rgb_10 = min3(cur_col_10bits[0], cur_col_10bits[1], cur_col_10bits[2]); - uint8_t min_rgb = min3(cur_col[0], cur_col[1], cur_col[2]); + if ((LST_RGBW <= Light.subtype) && (0 == Settings.rgbwwTable[4]) && (0 == cur_col_10[3]+cur_col_10[4])) { + uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); for (uint32_t i=0; i<3; i++) { // substract white and adjust according to rgbwwTable - uint32_t adjust10 = changeUIntScale(Settings.rgbwwTable[i], 0, 255, 0, 1023); - cur_col_10bits[i] = changeUIntScale(cur_col_10bits[i] - min_rgb_10, 0, 1023, 0, adjust10); - cur_col[i] = changeUIntScale(cur_col[i] - min_rgb, 0, 255, 0, Settings.rgbwwTable[i]); + uint32_t adjust10 = change8to10(Settings.rgbwwTable[i]); + cur_col_10[i] = changeUIntScale(cur_col_10[i] - min_rgb_10, 0, 1023, 0, adjust10); } // compute the adjusted white levels for 10 and 8 bits uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); // set white power down corrected with rgbwwTable[3] - uint32_t white = changeUIntScale(min_rgb, 0, 255, 0, Settings.rgbwwTable[3]); // set white power down corrected with rgbwwTable[3] if (LST_RGBW == Light.subtype) { // we simply set the white channel - cur_col_10bits[3] = white_10; - cur_col[3] = white; + cur_col_10[3] = white_10; } else { // LST_RGBWC // we distribute white between cold and warm according to CT value uint32_t ct = light_state.getCT(); - cur_col_10bits[4] = changeUIntScale(ct, 153, 500, 0, white_10); - cur_col_10bits[3] = white_10 - cur_col_10bits[4]; - cur_col[4] = changeUIntScale(ct, 153, 500, 0, white); - cur_col[3] = white - cur_col[4]; + cur_col_10[4] = changeUIntScale(ct, 153, 500, 0, white_10); + cur_col_10[3] = white_10 - cur_col_10[4]; } } } // final adjusments for PMW, post-gamma correction for (uint32_t i = 0; i < LST_MAX; i++) { -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) - // Fix unwanted blinking and PWM watchdog errors for values close to pwm_range (H801, Arilux and BN-SZ01) - // but keep value 1023 if full range (PWM will be deactivated in this case) - if ((cur_col_10bits[i] > 1008) && (cur_col_10bits[i] < 1023)) { - cur_col_10bits[i] = 1008; - } -#endif // scale from 0..1023 to 0..pwm_range, but keep any non-zero value to at least 1 - cur_col_10bits[i] = (cur_col_10bits[i] > 0) ? changeUIntScale(cur_col_10bits[i], 1, 1023, 1, Settings.pwm_range) : 0; + cur_col_10[i] = (cur_col_10[i] > 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0; } // apply port remapping on both 8 bits and 10 bits versions - uint8_t orig_col[LST_MAX]; uint16_t orig_col_10bits[LST_MAX]; - memcpy(orig_col, cur_col, sizeof(orig_col)); - memcpy(orig_col_10bits, cur_col_10bits, sizeof(orig_col_10bits)); + memcpy(orig_col_10bits, cur_col_10, sizeof(orig_col_10bits)); for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col[i] = orig_col[Light.color_remap[i]]; - cur_col_10bits[i] = orig_col_10bits[Light.color_remap[i]]; + cur_col_10[i] = orig_col_10bits[Light.color_remap[i]]; } if (!Settings.light_fade || power_off) { // no fade // record the current value for a future Fade - memcpy(Light.fade_start_8, cur_col, sizeof(Light.fade_start_8)); - memcpy(Light.fade_start_10, cur_col_10bits, sizeof(Light.fade_start_10)); + memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10)); // push the final values at 8 and 10 bits resolution to the PWMs - LightSetOutputs(cur_col, cur_col_10bits); + LightSetOutputs(cur_col_10); } else { // fade on if (Light.fade_running) { // if fade is running, we take the curring value as the start for the next fade - memcpy(Light.fade_start_8, Light.fade_cur_8, sizeof(Light.fade_start_8)); memcpy(Light.fade_start_10, Light.fade_cur_10, sizeof(Light.fade_start_10)); } - memcpy(Light.fade_end_8, cur_col, sizeof(Light.fade_start_8)); - memcpy(Light.fade_end_10, cur_col_10bits, sizeof(Light.fade_start_10)); + memcpy(Light.fade_end_10, cur_col_10, sizeof(Light.fade_start_10)); Light.fade_running = true; Light.fade_duration = 0; // set the value to zero to force a recompute Light.fade_start = 0; @@ -1747,11 +1749,10 @@ void LightAnimate(void) } if (Light.fade_running) { if (LightApplyFade()) { - // AddLog_P2(LOG_LEVEL_INFO, PSTR("LightApplyFade %d %d %d %d %d - %d %d %d %d %d"), - // Light.fade_cur_8[0], Light.fade_cur_8[1], Light.fade_cur_8[2], Light.fade_cur_8[3], Light.fade_cur_8[4], + // AddLog_P2(LOG_LEVEL_INFO, PSTR("LightApplyFade %d %d %d %d %d"), // Light.fade_cur_10[0], Light.fade_cur_10[1], Light.fade_cur_10[2], Light.fade_cur_10[3], Light.fade_cur_10[4]); - LightSetOutputs(Light.fade_cur_8, Light.fade_cur_10); + LightSetOutputs(Light.fade_cur_10); } } } @@ -1799,9 +1800,6 @@ bool LightApplyFade(void) { // did the value chanegd and needs to be applied if (fade_current <= Light.fade_duration) { // fade not finished //Serial.printf("Fade: %d / %d - ", fade_current, Light.fade_duration); for (uint32_t i = 0; i < Light.subtype; i++) { - Light.fade_cur_8[i] = changeUIntScale(fade_current, - 0, Light.fade_duration, - Light.fade_start_8[i], Light.fade_end_8[i]); Light.fade_cur_10[i] = changeUIntScale(fade_current, 0, Light.fade_duration, Light.fade_start_10[i], Light.fade_end_10[i]); @@ -1813,10 +1811,8 @@ bool LightApplyFade(void) { // did the value chanegd and needs to be applied Light.fade_start = 0; Light.fade_duration = 0; // set light to target value - memcpy(Light.fade_cur_8, Light.fade_end_8, sizeof(Light.fade_end_8)); memcpy(Light.fade_cur_10, Light.fade_end_10, sizeof(Light.fade_end_10)); // record the last value for next start - memcpy(Light.fade_start_8, Light.fade_end_8, sizeof(Light.fade_start_8)); memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10)); } return true; @@ -1855,20 +1851,24 @@ void LightApplyPower(uint8_t new_color[LST_MAX], power_t power) { } } -void LightSetOutputs(const uint8_t *cur_col, const uint16_t *cur_col_10bits) { +void LightSetOutputs(const uint16_t *cur_col_10) { // now apply the actual PWM values, adjusted and remapped 10-bits range if (light_type < LT_PWM6) { // only for direct PWM lights, not for Tuya, Armtronix... for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { if (pin[GPIO_PWM1 +i] < 99) { - //AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d, Pwm%d %d"), i, cur_col_10bits[i], i+1, cur_col[i]); - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10bits[(i + Light.pwm_offset)] : cur_col_10bits[(i + Light.pwm_offset)]); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d"), i, cur_col_10[i]); + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10[(i + Light.pwm_offset)] : cur_col_10[(i + Light.pwm_offset)]); } } } char msg[24]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Channels %s"), - ToHex_P((const unsigned char *)cur_col_10bits, 10, msg, sizeof(msg))); - + ToHex_P((const unsigned char *)cur_col_10, 10, msg, sizeof(msg))); + + uint8_t cur_col[LST_MAX]; + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col[i] = change10to8(cur_col_10[i]); + } // Some devices need scaled RGB like Sonoff L1 // TODO, should be probably moved to the Sonoff L1 support code uint8_t scale_col[3]; @@ -1888,7 +1888,7 @@ void LightSetOutputs(const uint8_t *cur_col, const uint16_t *cur_col_10bits) { } // Do specific computation is SetOption73 is on, Color Temp is a separate PWM channel -void calcGammaCTPwm(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { +void calcGammaCTPwm(uint16_t cur_col_10[5]) { // Xiaomi Philips bulbs follow a different scheme: uint8_t cold, warm; // channel 1 is the color tone, mapped to cold channel (0..255) light_state.getCW(&cold, &warm); @@ -1896,32 +1896,28 @@ void calcGammaCTPwm(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { uint32_t cw1 = Light.subtype - 1; // address for the ColorTone PWM uint32_t cw0 = Light.subtype - 2; // address for the White Brightness PWM // overall brightness - uint16_t pxBri = cur_col[cw0] + cur_col[cw1]; - if (pxBri > 255) { pxBri = 255; } - cur_col[cw1] = changeUIntScale(cold, 0, cold + warm, 0, 255); // - cur_col_10bits[cw1] = changeUIntScale(cur_col[cw1], 0, 255, 0, 1023); + uint16_t pxBri10 = cur_col_10[cw0] + cur_col_10[cw1]; + if (pxBri10 > 1023) { pxBri10 = 1023; } + cur_col_10[cw1] = changeUIntScale(cold, 0, cold + warm, 0, 1023); // // channel 0=intensity, channel1=temperature if (Settings.light_correction) { // gamma correction - cur_col[cw0] = ledGamma(pxBri); - cur_col_10bits[cw0] = ledGamma(pxBri, 10); // 10 bits gamma correction + cur_col_10[cw0] = ledGamma10_10(pxBri10); // 10 bits gamma correction } else { - cur_col[cw0] = pxBri; - cur_col_10bits[cw0] = changeUIntScale(pxBri, 0, 255, 0, 1023); // no gamma, extend to 10 bits + cur_col_10[cw0] = pxBri10; // no gamma, extend to 10 bits } } // Just apply basic Gamma to each channel -void calcGammaMultiChannels(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { +void calcGammaMultiChannels(uint16_t cur_col_10[5]) { // Apply gamma correction for 8 and 10 bits resolutions, if needed if (Settings.light_correction) { for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col_10bits[i] = ledGamma(cur_col[i], 10); - cur_col[i] = ledGamma(cur_col[i]); + cur_col_10[i] = ledGamma10_10(cur_col_10[i]); } } } -void calcGammaBulbs(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { +void calcGammaBulbs(uint16_t cur_col_10[5]) { // Apply gamma correction for 8 and 10 bits resolutions, if needed if (Settings.light_correction) { // First apply combined correction to the overall white power @@ -1931,35 +1927,28 @@ void calcGammaBulbs(uint8_t cur_col[5], uint16_t cur_col_10bits[5]) { w_idx[0] = 3; w_idx[1] = 4; } - uint16_t white_bri = cur_col[w_idx[0]] + cur_col[w_idx[1]]; + uint16_t white_bri10 = cur_col_10[w_idx[0]] + cur_col_10[w_idx[1]]; // if sum of both channels is > 255, then channels are probablu uncorrelated - if (white_bri <= 255) { + if (white_bri10 <= 1023) { // we calculate the gamma corrected sum of CW + WW - uint16_t white_bri_10bits = ledGamma(white_bri, 10); - uint8_t white_bri_8bits = ledGamma(white_bri); + uint16_t white_bri_10bits = ledGamma10_10(white_bri10); // then we split the total energy among the cold and warm leds - cur_col_10bits[w_idx[0]] = changeUIntScale(cur_col[w_idx[0]], 0, white_bri, 0, white_bri_10bits); - cur_col_10bits[w_idx[1]] = changeUIntScale(cur_col[w_idx[1]], 0, white_bri, 0, white_bri_10bits); - cur_col[w_idx[0]] = changeUIntScale(cur_col[w_idx[0]], 0, white_bri, 0, white_bri_8bits); - cur_col[w_idx[1]] = changeUIntScale(cur_col[w_idx[1]], 0, white_bri, 0, white_bri_8bits); + cur_col_10[w_idx[0]] = changeUIntScale(cur_col_10[w_idx[0]], 0, white_bri10, 0, white_bri_10bits); + cur_col_10[w_idx[1]] = changeUIntScale(cur_col_10[w_idx[1]], 0, white_bri10, 0, white_bri_10bits); } else { - cur_col_10bits[w_idx[0]] = ledGamma(cur_col[w_idx[0]], 10); - cur_col_10bits[w_idx[1]] = ledGamma(cur_col[w_idx[1]], 10); - cur_col[w_idx[0]] = ledGamma(cur_col[w_idx[0]]); - cur_col[w_idx[1]] = ledGamma(cur_col[w_idx[1]]); + cur_col_10[w_idx[0]] = ledGamma10_10(cur_col_10[w_idx[0]]); + cur_col_10[w_idx[1]] = ledGamma10_10(cur_col_10[w_idx[1]]); } } // then apply gamma correction to RGB channels if (LST_RGB <= Light.subtype) { for (uint32_t i = 0; i < 3; i++) { - cur_col_10bits[i] = ledGamma(cur_col[i], 10); - cur_col[i] = ledGamma(cur_col[i]); + cur_col_10[i] = ledGamma10_10(cur_col_10[i]); } } // If RGBW or Single channel, also adjust White channel if ((LST_COLDWARM != Light.subtype) && (LST_RGBWC != Light.subtype)) { - cur_col_10bits[3] = ledGamma(cur_col[3], 10); - cur_col[3] = ledGamma(cur_col[3]); + cur_col_10[3] = ledGamma10_10(cur_col_10[3]); } } } @@ -2447,7 +2436,7 @@ bool Xdrv04(uint8_t function) case FUNC_LOOP: if (Light.fade_running) { if (LightApplyFade()) { - LightSetOutputs(Light.fade_cur_8, Light.fade_cur_10); + LightSetOutputs(Light.fade_cur_10); } } break; From 1ba2239804540267a5fb76354759c2f9d0b8424d Mon Sep 17 00:00:00 2001 From: Bohdan Kmit Date: Sat, 28 Dec 2019 00:29:25 +0200 Subject: [PATCH 168/559] Improved Ukrainian translation, renamed localization to proper uk-UA name --- platformio_tasmota_env.ini | 2 +- tasmota/language/{uk-UK.h => uk-UA.h} | 150 +++++++++++++------------- tasmota/my_user_config.h | 2 +- 3 files changed, 77 insertions(+), 77 deletions(-) rename tasmota/language/{uk-UK.h => uk-UA.h} (88%) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index fd0571125..f2b46c131 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -97,4 +97,4 @@ build_flags = ${common.build_flags} -DMY_LANGUAGE=tr-TR build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-TW [env:tasmota-UK] -build_flags = ${common.build_flags} -DMY_LANGUAGE=uk-UK +build_flags = ${common.build_flags} -DMY_LANGUAGE=uk-UA diff --git a/tasmota/language/uk-UK.h b/tasmota/language/uk-UA.h similarity index 88% rename from tasmota/language/uk-UK.h rename to tasmota/language/uk-UA.h index dbf58fe35..cd77adebd 100644 --- a/tasmota/language/uk-UK.h +++ b/tasmota/language/uk-UA.h @@ -1,5 +1,5 @@ /* - uk-UK.h - localization for Ukrainian - Ukraine for Tasmota + uk-UA.h - localization for Ukrainian - Ukraine for Tasmota Copyright (C) 2019 Theo Arends / vadym-adik @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef _LANGUAGE_UK_UK_H_ -#define _LANGUAGE_UK_UK_H_ +#ifndef _LANGUAGE_UK_UA_H_ +#define _LANGUAGE_UK_UA_H_ /*************************** ATTENTION *******************************\ * @@ -51,7 +51,7 @@ #define D_DECIMAL_SEPARATOR "," // Common -#define D_ADMIN "Admin" +#define D_ADMIN "Адміністратор" #define D_AIR_QUALITY "Якість повітря" #define D_AP "Точка доступу" // Access Point #define D_AS "як" @@ -63,7 +63,7 @@ #define D_BSSID "BSSId" #define D_BUTTON "Кнопка" #define D_BY " " // Written by me -#define D_BYTES "Байт" +#define D_BYTES "Байтів" #define D_CELSIUS "Цельсія" #define D_CHANNEL "Канал" #define D_CO2 "Вуглек. газ" @@ -71,27 +71,27 @@ #define D_COLDLIGHT "Холодний" #define D_COMMAND "Команда" #define D_CONNECTED "Під'єднано" -#define D_CORS_DOMAIN "CORS Domain" -#define D_COUNT "Розмір" +#define D_CORS_DOMAIN "Домен CORS" +#define D_COUNT "разів" #define D_COUNTER "Лічильник" #define D_CURRENT "Струм" // As in Voltage and Current #define D_DATA "Дані" #define D_DARKLIGHT "Темний" #define D_DEBUG "Налагодження" -#define D_DISABLED "Заблоковано" +#define D_DISABLED "Вимкнено" #define D_DISTANCE "Відстань" #define D_DNS_SERVER "Сервер DNS" #define D_DONE "Виконано" #define D_DST_TIME "Літній час" #define D_ECO2 "eCO2" #define D_EMULATION "Емуляція" -#define D_ENABLED "Активно" +#define D_ENABLED "Увімкнено" #define D_ERASE "Стирати" #define D_ERROR "Помилка" #define D_FAHRENHEIT "Фаренгейт" #define D_FAILED "Невдало" -#define D_FALLBACK "Зворотній зв'язок" -#define D_FALLBACK_TOPIC "Топік зворотнього зв'язку" +#define D_FALLBACK "Запасний" +#define D_FALLBACK_TOPIC "Запасний топік" #define D_FALSE "Ні" #define D_FILE "Файл" #define D_FLOW_RATE "Потік" @@ -106,34 +106,34 @@ #define D_ILLUMINANCE "Освітленність" #define D_IMMEDIATE "Негайно" // Button immediate #define D_INDEX "Індекс" -#define D_INFO "Інфо" +#define D_INFO "Інформація" #define D_INFRARED "Інфрачервоний" #define D_INITIALIZED "Ініціалізовано" #define D_IP_ADDRESS "IP адреса" #define D_LIGHT "Світло" #define D_LWT "LWT" #define D_MODULE "Модуль" -#define D_MOISTURE "Moisture" +#define D_MOISTURE "Волога" #define D_MQTT "MQTT" #define D_MULTI_PRESS "Багаторазове натискання" #define D_NOISE "Шум" #define D_NONE "Нічого" -#define D_OFF "Вимк." -#define D_OFFLINE "Офф-лайн" +#define D_OFF "Вимкнено" +#define D_OFFLINE "Неактивний" #define D_OK "Ок" -#define D_ON "Увімк." -#define D_ONLINE "Он-лайн" +#define D_ON "Увімкнено" +#define D_ONLINE "Активний" #define D_PASSWORD "Гасло" #define D_PORT "Порт" #define D_POWER_FACTOR "Коефіцієнт потужності" #define D_POWERUSAGE "Потужність" #define D_POWERUSAGE_ACTIVE "Активна потужність" -#define D_POWERUSAGE_APPARENT "Дійсна потужність" +#define D_POWERUSAGE_APPARENT "Загальна потужність" #define D_POWERUSAGE_REACTIVE "Реактивна потужність" #define D_PRESSURE "Тиск" #define D_PRESSUREATSEALEVEL "Тиск на рівні моря" #define D_PROGRAM_FLASH_SIZE "Розмір Flash для програм" -#define D_PROGRAM_SIZE "Розмір програм" +#define D_PROGRAM_SIZE "Розмір програми" #define D_PROJECT "Проект" #define D_RAIN "Дощ" #define D_RECEIVED "Отримано" @@ -194,7 +194,7 @@ #define D_SET_BAUDRATE_TO "Встановити швидкість передачі (Baudrate)" #define D_RECEIVED_TOPIC "Отриманий Топік" #define D_DATA_SIZE "Розмір даних" -#define D_ANALOG_INPUT "Напруга" +#define D_ANALOG_INPUT "Аналоговий вхід" // support.ino #define D_OSWATCH "osWatch" @@ -203,7 +203,7 @@ #define D_ACTIVE_FOR_3_MINUTES "активний протягом 3 хвилин" #define D_FAILED_TO_START "не вдалось запустити" #define D_PATCH_ISSUE_2186 "Проблема з виправленням 2186" -#define D_CONNECTING_TO_AP "Підключення до AP" +#define D_CONNECTING_TO_AP "Підключення до Точки Доступу" #define D_IN_MODE "в режимі" #define D_CONNECT_FAILED_NO_IP_ADDRESS "Помилка підключення, IP-адреса не отримана" #define D_CONNECT_FAILED_AP_NOT_REACHED "Помилка з'єднання, AP не знайдено" @@ -213,12 +213,12 @@ #define D_CHECKING_CONNECTION "Перевірка з'єднання..." #define D_QUERY_DONE "Запит виконаний. Виявлено сервер MQTT" #define D_MQTT_SERVICE_FOUND "MQTT сервер знайдено" -#define D_FOUND_AT "знайдено в" +#define D_FOUND_AT "знайдено за адресою" #define D_SYSLOG_HOST_NOT_FOUND "Сервер журналу не знайдено" // settings.ino -#define D_SAVED_TO_FLASH_AT "Збережено в флэш-пам'ять" -#define D_LOADED_FROM_FLASH_AT "Завантажено з флэш-пам'яті" +#define D_SAVED_TO_FLASH_AT "Збережено в Flash-пам'ять" +#define D_LOADED_FROM_FLASH_AT "Завантажено з Flash-пам'яті" #define D_USE_DEFAULTS "Використовувати значення за замовчуванням" #define D_ERASED_SECTOR "Стерто сектор" @@ -230,7 +230,7 @@ #define D_WEBSERVER_STOPPED "Веб-сервер зупинений" #define D_FILE_NOT_FOUND "Файл не знайдений" #define D_REDIRECTED "Перенаправлено на адаптивний портал" -#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер встановлює Точку Доступу і зберігає параметри" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi менеджер встановлює Точку Доступу і станцію" #define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi менеджер встановив Точку Доступу" #define D_TRYING_TO_CONNECT "Спроба підключення пристрою до мережі" @@ -286,18 +286,18 @@ #define D_LOGGING_PARAMETERS "Параметри журналу" #define D_SERIAL_LOG_LEVEL "Serial рівень" -#define D_MQTT_LOG_LEVEL "Mqtt log level" +#define D_MQTT_LOG_LEVEL "Mqtt рівень" #define D_WEB_LOG_LEVEL "Web рівень" -#define D_SYS_LOG_LEVEL "System рівень" +#define D_SYS_LOG_LEVEL "Syslog рівень" #define D_MORE_DEBUG "Додаткова інформація для налагодження" -#define D_SYSLOG_HOST "System хост" -#define D_SYSLOG_PORT "System порт" +#define D_SYSLOG_HOST "Syslog хост" +#define D_SYSLOG_PORT "Syslog порт" #define D_TELEMETRY_PERIOD "Період телеметрії" #define D_OTHER_PARAMETERS "Параметри Інше" #define D_TEMPLATE "Шаблони" -#define D_ACTIVATE "Activate" -#define D_WEB_ADMIN_PASSWORD "Гасло Web адміністратора" +#define D_ACTIVATE "Активувний" +#define D_WEB_ADMIN_PASSWORD "Гасло адміністратора Web" #define D_MQTT_ENABLE "MQTT активний" #define D_FRIENDLY_NAME "Дружнє Ім'я" #define D_BELKIN_WEMO "Belkin WeMo" @@ -328,14 +328,14 @@ #define D_MQTT_GROUP_TOPIC "MQTT Топік групи" #define D_MQTT_FULL_TOPIC "MQTT Топік повний" #define D_MDNS_DISCOVERY "mDNS Виявлення" -#define D_MDNS_ADVERTISE "mDNS Транcляція" +#define D_MDNS_ADVERTISE "mDNS Анонс" #define D_ESP_CHIP_ID "ID чипу ESP" #define D_FLASH_CHIP_ID "ID чипу Flash пам'яті" #define D_FLASH_CHIP_SIZE "Розмір Flash пам'яті" #define D_FREE_PROGRAM_SPACE "Вільний простір для програм" #define D_UPGRADE_BY_WEBSERVER "Оновлення через Веб-сервер" -#define D_OTA_URL "OTA Url" +#define D_OTA_URL "OTA URL" #define D_START_UPGRADE "Почати оновлення" #define D_UPGRADE_BY_FILE_UPLOAD "Оновлення шляхом завантаження файлів" #define D_UPLOAD_STARTED "Завантаження почалось" @@ -350,11 +350,11 @@ #define D_UPLOAD_ERR_7 "Завантаження перервано" #define D_UPLOAD_ERR_8 "Файл невірний" #define D_UPLOAD_ERR_9 "Занадто великий файл" -#define D_UPLOAD_ERR_10 "Помилка ініціалізаціції чипу FR" +#define D_UPLOAD_ERR_10 "Помилка ініціалізаціції чипу RF" #define D_UPLOAD_ERR_11 "Помилка стирання чипу RF" #define D_UPLOAD_ERR_12 "Помилка запису чипу RF" #define D_UPLOAD_ERR_13 "Помилка розкодування прошивки RF" -#define D_UPLOAD_ERR_14 "Not compatible" +#define D_UPLOAD_ERR_14 "Не сумісно" #define D_UPLOAD_ERROR_CODE "Код помилки завантаження" #define D_ENTER_COMMAND "Уведіть команду" @@ -363,7 +363,7 @@ // xdrv_01_mqtt.ino #define D_FINGERPRINT "Перевірка відбитка TLS..." -#define D_TLS_CONNECT_FAILED_TO "Збій підключення TLS до" +#define D_TLS_CONNECT_FAILED_TO "Збій TLS підключення до" #define D_RETRY_IN "Повторити" #define D_VERIFIED "Перевірено відбиток" #define D_INSECURE "Небезпечне з'єднання, недійсний відбиток" @@ -414,7 +414,7 @@ #define D_TIMER_ARM "Увімкнений" #define D_TIMER_TIME "Час" #define D_TIMER_DAYS "Дні" -#define D_TIMER_REPEAT "Повтор" +#define D_TIMER_REPEAT "Повторення" #define D_TIMER_OUTPUT "Вихід" #define D_TIMER_ACTION "Дія" @@ -459,9 +459,9 @@ #define D_DEVICE_OUTPUT "Output" // xsns_05_ds18b20.ino -#define D_SENSOR_BUSY "Датчик DS18x20 зайнятий" -#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - помилка CRC" -#define D_SENSORS_FOUND "Датчик DS18x20 знайдено" +#define D_SENSOR_BUSY "Давач DS18x20 зайнятий" +#define D_SENSOR_CRC_ERROR "Давач DS18x20 - помилка CRC" +#define D_SENSORS_FOUND "Давач DS18x20 знайдено" // xsns_06_dht.ino #define D_TIMEOUT_WAITING_FOR "Тайм-аут, в очікуванні" @@ -471,7 +471,7 @@ #define D_CHECKSUM_FAILURE "Помилка контрольної суми" // xsns_07_sht1x.ino -#define D_SENSOR_DID_NOT_ACK_COMMAND "Датчик не підтвердив отримання команди" +#define D_SENSOR_DID_NOT_ACK_COMMAND "Давач не підтвердив отримання команди" #define D_SHT1X_FOUND "SHT1X знайдено" // xsns_18_pms5003.ino @@ -543,7 +543,7 @@ #define D_SENSOR_SPI_MISO "SPI MISO" #define D_SENSOR_SPI_MOSI "SPI MOSI" #define D_SENSOR_SPI_CLK "SPI CLK" -#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_BACKLIGHT "OLED Light" #define D_SENSOR_PMS5003 "PMS5003" #define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" #define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" @@ -564,7 +564,7 @@ #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_TX20_TX "TX20" #define D_SENSOR_RFSEND "RFSend" -#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_RFRECV "RFRecv" #define D_SENSOR_TUYA_TX "Tuya Tx" #define D_SENSOR_TUYA_RX "Tuya Rx" #define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" @@ -628,9 +628,9 @@ #define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_EXS_ENABLE "EXS Enable" -#define D_SENSOR_SLAVE_TX "Slave TX" -#define D_SENSOR_SLAVE_RX "Slave RX" -#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_TX "GPS TX" @@ -640,20 +640,20 @@ #define D_UNIT_HERTZ "Гц" #define D_UNIT_HOUR "Г" #define D_UNIT_GALLONS "гал" -#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_GALLONS_PER_MIN "гал/хв" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "кг" #define D_UNIT_KILOMETER_PER_HOUR "км/г" // or "km/h" #define D_UNIT_KILOOHM "кОм" -#define D_UNIT_KILOWATTHOUR "кВт" +#define D_UNIT_KILOWATTHOUR "кВт/г" #define D_UNIT_LUX "лк" #define D_UNIT_MICROGRAM_PER_CUBIC_METER "мкг/м3" #define D_UNIT_MICROMETER "мкм" -#define D_UNIT_MICROSECOND "мкс" +#define D_UNIT_MICROSECOND "мкС" #define D_UNIT_MILLIAMPERE "мА" #define D_UNIT_MILLIMETER "мм" #define D_UNIT_MILLIMETER_MERCURY "ммHg" -#define D_UNIT_MILLISECOND "мс" +#define D_UNIT_MILLISECOND "мС" #define D_UNIT_MINUTE "хв" #define D_UNIT_PARTS_PER_BILLION "ppb" #define D_UNIT_PARTS_PER_DECILITER "ppd" @@ -665,8 +665,8 @@ #define D_UNIT_VAR "ВАр" #define D_UNIT_VOLT "В" #define D_UNIT_WATT "Вт" -#define D_UNIT_WATTHOUR "Вт/Год" -#define D_UNIT_WATT_METER_QUADRAT "Вт/m²" +#define D_UNIT_WATTHOUR "Вт/г" +#define D_UNIT_WATT_METER_QUADRAT "Вт/м²" //SDM220 #define D_PHASE_ANGLE "Кут фази" @@ -679,27 +679,27 @@ #define D_UNIT_ANGLE "Град" //SOLAXX1 -#define D_PV1_VOLTAGE "PV1 Voltage" -#define D_PV1_CURRENT "PV1 Current" -#define D_PV1_POWER "PV1 Power" -#define D_PV2_VOLTAGE "PV2 Voltage" -#define D_PV2_CURRENT "PV2 Current" -#define D_PV2_POWER "PV2 Power" -#define D_SOLAR_POWER "Solar Power" -#define D_INVERTER_POWER "Inverter Power" -#define D_STATUS "Status" -#define D_WAITING "Waiting" -#define D_CHECKING "Checking" -#define D_WORKING "Working" -#define D_FAILURE "Failure" -#define D_SOLAX_ERROR_0 "No Error Code" -#define D_SOLAX_ERROR_1 "Grid Lost Fault" -#define D_SOLAX_ERROR_2 "Grid Voltage Fault" -#define D_SOLAX_ERROR_3 "Grid Frequency Fault" -#define D_SOLAX_ERROR_4 "Pv Voltage Fault" -#define D_SOLAX_ERROR_5 "Isolation Fault" -#define D_SOLAX_ERROR_6 "Over Temperature Fault" -#define D_SOLAX_ERROR_7 "Fan Fault" -#define D_SOLAX_ERROR_8 "Other Device Fault" +#define D_PV1_VOLTAGE "PV1 Напруга" +#define D_PV1_CURRENT "PV1 Струм" +#define D_PV1_POWER "PV1 Потужність" +#define D_PV2_VOLTAGE "PV2 Напруга" +#define D_PV2_CURRENT "PV2 Струм" +#define D_PV2_POWER "PV2 Потужність" +#define D_SOLAR_POWER "Solar Потужність" +#define D_INVERTER_POWER "Inverter Потужність" +#define D_STATUS "Стан" +#define D_WAITING "Очікування" +#define D_CHECKING "Перевірка" +#define D_WORKING "Працює" +#define D_FAILURE "Помилка" +#define D_SOLAX_ERROR_0 "Немає помилки" +#define D_SOLAX_ERROR_1 "Втрата мережі" +#define D_SOLAX_ERROR_2 "Напруга мережі" +#define D_SOLAX_ERROR_3 "Частота мережі" +#define D_SOLAX_ERROR_4 "Напруга Pv" +#define D_SOLAX_ERROR_5 "Ізоляція" +#define D_SOLAX_ERROR_6 "Перегрів" +#define D_SOLAX_ERROR_7 "Вентилятор" +#define D_SOLAX_ERROR_8 "Інший пристрій" -#endif // _LANGUAGE_UK_UK_H_ +#endif // _LANGUAGE_UK_UA_H_ diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 13e7c6c64..b60651fec 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -265,7 +265,7 @@ //#define MY_LANGUAGE sk-SK // Slovak in Slovakia //#define MY_LANGUAGE sv-SE // Swedish in Sweden //#define MY_LANGUAGE tr-TR // Turkish in Turkey -//#define MY_LANGUAGE uk-UK // Ukrainian in Ukraine +//#define MY_LANGUAGE uk-UA // Ukrainian in Ukraine //#define MY_LANGUAGE zh-CN // Chinese (Simplified) in China //#define MY_LANGUAGE zh-TW // Chinese (Traditional) in Taiwan From 3f9018658c9ddee84326cef98f4e7c46eaaacc86 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 28 Dec 2019 09:58:30 +0100 Subject: [PATCH 169/559] Better gamma curve --- tasmota/xdrv_04_light.ino | 55 ++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index ecb966053..1310ff471 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -171,7 +171,8 @@ typedef struct gamma_table_t { } gamma_table_t; const gamma_table_t gamma_table[] = { // don't put in PROGMEM for performance reasons - { 3, 0 }, + { 1, 1 }, + { 4, 1 }, { 209, 13 }, { 312, 41 }, { 457, 106 }, @@ -196,46 +197,46 @@ const gamma_table_t gamma_table_fast[] = { // 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, // 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, -// 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, -// 6, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, -// 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, +// 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, +// 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, +// 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, // 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, // 25, 26, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 37, 38, // 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, -// 54, 55, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 66, 68, 69, -// 71, 72, 73, 75, 76, 78, 79, 80, 82, 83, 85, 86, 87, 88, 90, 91, +// 54, 55, 56, 57, 58, 59, 60, 61, 61, 62, 63, 64, 65, 67, 68, 69, +// 71, 72, 73, 75, 76, 78, 79, 80, 82, 83, 85, 86, 87, 89, 90, 91, // 93, 94, 95, 97, 98,100,101,102,104,105,107,108,109,111,112,114, -// 116,118,120,121,123,125,127,129,131,133,135,137,139,141,142,144, +// 116,118,120,122,124,125,127,129,131,133,135,137,139,141,143,144, // 146,148,150,152,154,156,158,160,162,164,166,168,170,171,173,175, -// 177,180,182,185,187,190,192,195,197,200,202,205,207,210,212,215, -// 217,220,222,225,227,230,233,235,238,240,243,245,248,250,253,255 +// 178,180,183,185,188,190,193,195,198,200,203,205,208,210,213,215, +// 218,220,223,225,228,230,233,235,238,240,243,245,248,250,253,255 // // and for 10 bits output: // 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, // 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, // 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, -// 12, 12, 13, 13, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -// 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 42, 44, -// 46, 47, 49, 51, 53, 54, 56, 58, 60, 62, 63, 65, 67, 69, 70, 72, -// 74, 76, 78, 79, 81, 83, 85, 86, 88, 90, 92, 94, 95, 97, 99, 101, +// 12, 12, 13, 13, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, +// 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, +// 45, 47, 49, 50, 52, 54, 56, 58, 59, 61, 63, 65, 67, 68, 70, 72, +// 74, 76, 77, 79, 81, 83, 84, 86, 88, 90, 92, 93, 95, 97, 99, 101, // 102, 104, 106, 110, 113, 117, 121, 124, 128, 132, 135, 139, 143, 146, 150, 154, // 158, 162, 166, 169, 173, 177, 180, 184, 188, 191, 195, 199, 202, 206, 210, 213, -// 217, 221, 224, 228, 232, 235, 239, 243, 246, 250, 254, 257, 261, 266, 272, 277, -// 283, 288, 294, 300, 305, 311, 316, 322, 327, 333, 339, 344, 350, 355, 361, 366, -// 372, 378, 383, 389, 394, 400, 405, 411, 417, 422, 428, 433, 439, 444, 450, 457, -// 464, 472, 480, 487, 495, 503, 510, 518, 525, 533, 541, 548, 556, 564, 571, 579, -// 587, 594, 602, 609, 617, 627, 634, 642, 650, 657, 665, 672, 680, 688, 695, 703, -// 712, 722, 732, 742, 752, 762, 772, 782, 792, 802, 812, 822, 832, 842, 852, 862, -// 872, 882, 892, 902, 912, 923, 933, 943, 953, 963, 973, 983, 993,1003,1013,1023 +// 217, 221, 224, 228, 232, 235, 239, 243, 246, 250, 254, 257, 261, 267, 272, 278, +// 283, 289, 294, 300, 305, 311, 317, 322, 328, 333, 339, 344, 350, 356, 361, 367, +// 372, 378, 383, 389, 394, 400, 406, 411, 417, 422, 428, 433, 439, 444, 450, 458, +// 465, 473, 480, 488, 496, 503, 511, 518, 526, 534, 541, 549, 557, 564, 572, 579, +// 587, 595, 602, 610, 617, 627, 635, 642, 650, 657, 665, 673, 680, 688, 695, 703, +// 713, 723, 733, 743, 753, 763, 773, 783, 793, 803, 813, 823, 833, 843, 853, 863, +// 873, 883, 893, 903, 913, 923, 933, 943, 953, 963, 973, 983, 993,1003,1013,1023 // // Output for Dimmer 0..100 values // 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, -// 10, 10, 11, 12, 12, 13, 16, 18, 21, 23, 26, 29, 32, 34, 37, -// 40, 44, 49, 53, 58, 62, 67, 70, 76, 79, 85, 90, 94, 99,102, +// 10, 10, 11, 12, 12, 13, 15, 17, 21, 23, 26, 28, 31, 34, 37, +// 40, 43, 49, 52, 58, 61, 67, 70, 76, 79, 84, 90, 93, 99,102, // 110,117,128,135,146,158,166,177,184,195,202,213,221,232,239, -// 250,261,272,288,300,316,327,344,355,372,389,400,417,428,444, -// 457,480,495,518,533,556,579,594,617,634,657,672,695,712,742, -// 772,792,822,842,872,892,923,943,973,993,1023 +// 250,261,272,289,300,317,328,344,356,372,389,400,417,428,444, +// 458,480,496,518,534,557,579,595,617,635,657,673,695,713,743, +// 773,793,823,843,873,893,923,943,973,993,1023 struct LIGHT { uint32_t strip_timer_counter = 0; // Bars and Gradient @@ -1103,8 +1104,8 @@ uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { if (v <= to_src) { return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); } - from_src = to_src + 1; - from_gamma = to_gamma + 1; + from_src = to_src; + from_gamma = to_gamma; } } // 10_10 bits, fast fade mode From 7295b6631021fc68443033665c12373499658cbf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 28 Dec 2019 10:42:00 +0100 Subject: [PATCH 170/559] Add DS1624 support --- RELEASENOTES.md | 4 ++-- tasmota/CHANGELOG.md | 3 ++- tasmota/support_features.ino | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 16e5d63c2..e3b1e0fb4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -50,13 +50,13 @@ The following binary downloads have been compiled with ESP8266/Arduino library c [Complete list](BUILDS.md) of available feature and sensors. -For merge for Changelog: -- Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev ## Changelog ### Version 8.1.0.1 +- Change Lights: simplified gamma correction and 10 bits internal computation - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` +- Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 077384325..530b8c198 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -2,11 +2,12 @@ ### 8.1.0.1 20191225 +- Change Lights: simplified gamma correction and 10 bits internal computation - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` -- Change Lights: simplified gamma correction and 10 bits internal computation +- Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev ## Released diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index dcc24de0b..696e5ee5d 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -492,7 +492,9 @@ void GetFeatures(void) #ifdef USE_DHT12 feature5 |= 0x00100000; #endif -// feature5 |= 0x00200000; +#ifdef USE_DS1624 + feature5 |= 0x00200000; +#endif #ifdef USE_GPS feature5 |= 0x00400000; #endif From 5f62b59f05d82b15792e0cfda81a451825d8942f Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 28 Dec 2019 11:35:44 +0100 Subject: [PATCH 171/559] Refactor DS1624 driver --- tasmota/my_user_config.h | 1 + tasmota/xsns_59_ds1624.ino | 134 ++++++++++++++++++++----------------- 2 files changed, 72 insertions(+), 63 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index b60651fec..538301695 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -419,6 +419,7 @@ // #define USE_PCF8574 // [I2cDriver2] Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code) // #define USE_HIH6 // [I2cDriver36] Enable Honeywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) // #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) (+0k7 code) +// #define USE_DS1624 // [I2cDriver42] Enable DS1624, DS1621 temperature sensor (I2C addresses 0x48 - 0x4F) (+1k2 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/xsns_59_ds1624.ino b/tasmota/xsns_59_ds1624.ino index 82ce7d8f6..06b21d39e 100644 --- a/tasmota/xsns_59_ds1624.ino +++ b/tasmota/xsns_59_ds1624.ino @@ -21,8 +21,8 @@ #ifdef USE_DS1624 /*********************************************************************************************\ - * DS1624,DS1621 - Temperature - * + * DS1624, DS1621 - Temperature + * * I2C Address: 0x48 - 0x4F \*********************************************************************************************/ @@ -44,64 +44,68 @@ enum { }; #define DS1624_MAX_SENSORS 8 -bool ds1624_init=false; + +bool ds1624_init = false; + struct { - bool valid; - float value; - int type; - char name[9]; + float value; + uint8_t type; + bool valid; + char name[9]; } ds1624_sns[DS1624_MAX_SENSORS]; -uint32_t DS1624_Idx2Addr(int idx) { +uint32_t DS1624_Idx2Addr(uint32_t idx) { return 0x48 + idx; } -void DS1624_HotPlugUp(int idx) { - uint32_t addr; - uint8_t config,tmp; +void DS1624_HotPlugUp(uint32_t idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); - addr = DS1624_Idx2Addr(idx); - if (I2cActive(addr)) return; - if (!I2cSetDevice(addr)) return; + if (I2cActive(addr)) { return; } + if (!I2cSetDevice(addr)) { return; } + + uint8_t config; if (I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { - if (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) - ds1624_sns[idx].type=DS1624_TYPE_DS1624; - else ds1624_sns[idx].type=DS1624_TYPE_DS1621; - if (ds1624_sns[idx].type==DS1624_TYPE_DS1621) - snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS1621_%d"), idx); - else snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS1624_%d"), idx); + uint8_t tmp; + ds1624_sns[idx].type = (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) ? DS1624_TYPE_DS1624 : DS1624_TYPE_DS1621; + + snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS162%c%c%d"), + (ds1624_sns[idx].type == DS1624_TYPE_DS1621) ? '1' : '4', IndexSeparator(), idx); I2cSetActiveFound(addr, ds1624_sns[idx].name); - ds1624_sns[idx].valid=true; + + ds1624_sns[idx].valid = true; if ((config & 1) == 1) { config &= 0xfe; - I2cWrite8(addr, DS1624_CONF_REGISTER, config); //1show off - delay(10);// by spec after writing + I2cWrite8(addr, DS1624_CONF_REGISTER, config); // 1show off + delay(10); // by spec after writing } - I2cValidRead(addr, DS1624_START_REGISTER, 1); //FIXME 0 must read, but 0 isn't work for tasmota + I2cValidRead(addr, DS1624_START_REGISTER, 1); // FIXME 0 must read, but 0 isn't work for tasmota AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); } } -void DS1624_HotPlugDown(int idx) { - uint32_t addr=DS1624_Idx2Addr(idx); - if (I2cActive(addr)==false) return; +void DS1624_HotPlugDown(int idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + if (!I2cActive(addr)) { return; } I2cResetActive(addr); - ds1624_sns[idx].valid=false; + ds1624_sns[idx].valid = false; AddLog_P2(LOG_LEVEL_INFO, "Hot UnPlug %s", ds1624_sns[idx].name); } bool DS1624GetTemp(float *value, int idx) { - uint16_t t; - bool result; - uint32_t addr=DS1624_Idx2Addr(idx); + uint32_t addr = DS1624_Idx2Addr(idx); - if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) return false; - *value = ConvertTemp(((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625); - if (ds1624_sns[idx].type==DS1624_TYPE_DS1621) { // Higher resolution - uint8_t perc,remain; - if (I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)==false) return true; - if (I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)==false) return true; + uint16_t t; + if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { return false; } + *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; + if (ds1624_sns[idx].type == DS1624_TYPE_DS1621) { // Higher resolution + uint8_t remain; + if (!I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)) { return true; } + uint8_t perc; + if (!I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)) { return true; } *value += ((float)perc - (float)remain)/((float)perc) - 0.25; } return true; @@ -111,13 +115,15 @@ void DS1624HotPlugScan(void) { uint16_t t; - for (int idx = 0; idx < DS1624_MAX_SENSORS; idx++) { - uint32_t addr=DS1624_Idx2Addr(idx); - if ((I2cActive(addr)==true) && (ds1624_sns[idx].valid==false)) - continue; // is busy by another driver + for (uint32_t idx = 0; idx < DS1624_MAX_SENSORS; idx++) { + uint32_t addr = DS1624_Idx2Addr(idx); + if (I2cActive(addr) && !ds1624_sns[idx].valid) { + continue; // is busy by another driver + } if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { DS1624_HotPlugDown(idx); - continue; } + continue; + } DS1624_HotPlugUp(idx); } } @@ -125,36 +131,37 @@ void DS1624HotPlugScan(void) void DS1624EverySecond(void) { float t; - for (int i = 0; i < DS1624_MAX_SENSORS; i++) { - if (ds1624_sns[i].valid==false) continue; - if (!DS1624GetTemp(&t, i)) continue; - ds1624_sns[i].value=t; + for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { + if (!ds1624_sns[i].valid) { continue; } + if (!DS1624GetTemp(&t, i)) { continue; } + ds1624_sns[i].value = ConvertTemp(t); } } void DS1624Show(bool json) { - int i; char temperature[33]; + bool once = true; - for (i = 0; i < DS1624_MAX_SENSORS; i++) { - if (ds1624_sns[i].valid==false) continue; + for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { + if (!ds1624_sns[i].valid) { continue; } dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); if (json) { ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds1624_sns[i].name, temperature); - if (0 == tele_period) { //FIXME 0==i WTF? - #ifdef USE_DOMOTICZ + if ((0 == tele_period) && once) { +#ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); - #endif // USE_DOMOTICZ - #ifdef USE_KNX +#endif // USE_DOMOTICZ +#ifdef USE_KNX KnxSensor(KNX_TEMPERATURE, temperature); - #endif // USE_KNX +#endif // USE_KNX + once = false; } - #ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_TEMP, ds1624_sns[i].name, temperature, TempUnit()); - #endif // USE_WEBSERVER +#endif // USE_WEBSERVER } } } @@ -163,18 +170,19 @@ void DS1624Show(bool json) * Interface \*********************************************************************************************/ -#define FUNC_HOTPLUG_SCAN 999 // FIXME remove it after HOTPLUG supported +#define FUNC_HOTPLUG_SCAN 255 // FIXME remove it after HOTPLUG supported bool Xsns59(uint8_t function) { - if (!I2cEnabled(XI2C_20)) { return false; } + if (!I2cEnabled(XI2C_42)) { return false; } bool result = false; + if (FUNC_INIT == function) { - if (ds1624_init==false) { + if (!ds1624_init) { memset(ds1624_sns, 0, sizeof(ds1624_sns)); - ds1624_init=true; - DS1624HotPlugScan(); //If HotPlug is off + ds1624_init = true; + DS1624HotPlugScan(); // If HotPlug is off } } switch (function) { @@ -187,11 +195,11 @@ bool Xsns59(uint8_t function) case FUNC_JSON_APPEND: DS1624Show(1); break; - #ifdef USE_WEBSERVER +#ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: DS1624Show(0); break; - #endif // USE_WEBSERVER +#endif // USE_WEBSERVER } return result; } From 4d9c55108314c789dc704ea758e74993ec490776 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 28 Dec 2019 13:14:51 +0100 Subject: [PATCH 172/559] Add WDT crash status --- tasmota/support_command.ino | 5 ++++- tasmota/support_crash_recorder.ino | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 53f4601a8..397d60f30 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -334,7 +334,7 @@ void CmndStatus(void) if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } // SetOption3 - Enable MQTT if (!energy_flg && (9 == payload)) { payload = 99; } - bool exception_flg = (ResetReason() == REASON_EXCEPTION_RST); + bool exception_flg = (ResetReason() == REASON_EXCEPTION_RST) || (ResetReason() == REASON_SOFT_WDT_RST); if (!exception_flg && (12 == payload)) { payload = 99; } if ((0 == payload) || (99 == payload)) { @@ -575,6 +575,9 @@ void CmndRestart(void) case -1: CmndCrash(); // force a crash break; + case -2: + CmndWDT(); + break; case 99: AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); EspRestart(); diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino index 87009bbc5..d354adb3b 100644 --- a/tasmota/support_crash_recorder.ino +++ b/tasmota/support_crash_recorder.ino @@ -50,6 +50,15 @@ void CmndCrash(void) dummy = *((uint32_t*) 0x00000000); } +// do an infinite loop to trigger WDT watchdog +void CmndWDT(void) +{ + volatile uint32_t dummy = 0; + while (1) { + dummy++; + } +} + // Clear the RTC dump counter when we do a normal reboot, this avoids garbage data to stay in RTC void CrashDumpClear(void) { From eabac5e466027f9df1e616a97419e6ffd6f75fd5 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 28 Dec 2019 13:59:01 +0100 Subject: [PATCH 173/559] Zigbee attribute decoder for Xiaomi Aqara Cube --- tasmota/CHANGELOG.md | 1 + tasmota/xdrv_23_zigbee_5_converters.ino | 61 ++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 530b8c198..3abb0db81 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` - Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev +- Add Zigbee attribute decoder for Xiaomi Aqara Cube ## Released diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 1423c53f1..94853d629 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -601,7 +601,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0012, 0x001C, "Description", &Z_Copy }, { 0x0012, 0x004A, "NumberOfStates", &Z_Copy }, { 0x0012, 0x0051, "OutOfService", &Z_Copy }, - { 0x0012, 0x0055, "PresentValue", &Z_Copy }, + { 0x0012, 0x0055, "PresentValue", &Z_AqaraCube }, { 0x0012, 0x0067, "Reliability", &Z_Copy }, { 0x0012, 0x006F, "StatusFlags", &Z_Copy }, { 0x0012, 0x0100, "ApplicationType", &Z_Copy }, @@ -836,6 +836,65 @@ int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpo XdrvRulesProcess(); } +// Aqara Cube +int32_t Z_AqaraCube(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; // copy the original value + int32_t val = value; + const __FlashStringHelper *aqara_cube = F("AqaraCube"); + const __FlashStringHelper *aqara_cube_side = F("AqaraCubeSide"); + const __FlashStringHelper *aqara_cube_from_side = F("AqaraCubeFromSide"); + + switch (val) { + case 0: + json[aqara_cube] = F("shake"); + break; + case 2: + json[aqara_cube] = F("wakeup"); + break; + case 3: + json[aqara_cube] = F("fall"); + break; + case 64 ... 127: + json[aqara_cube] = F("flip90"); + json[aqara_cube_side] = val % 8; + json[aqara_cube_from_side] = (val - 64) / 8; + break; + case 128 ... 132: + json[aqara_cube] = F("flip180"); + json[aqara_cube_side] = val - 128; + break; + case 256 ... 261: + json[aqara_cube] = F("slide"); + json[aqara_cube_side] = val - 256; + break; + case 512 ... 517: + json[aqara_cube] = F("tap"); + json[aqara_cube_side] = val - 512; + break; + } + + // Source: https://github.com/kirovilya/ioBroker.zigbee + // +---+ + // | 2 | + // +---+---+---+ + // | 4 | 0 | 1 | + // +---+---+---+ + // |M5I| + // +---+ + // | 3 | + // +---+ + // Side 5 is with the MI logo, side 3 contains the battery door. + // presentValue = 0 = shake + // presentValue = 2 = wakeup + // presentValue = 3 = fly/fall + // presentValue = y + x * 8 + 64 = 90º Flip from side x on top to side y on top + // presentValue = x + 128 = 180º flip to side x on top + // presentValue = x + 256 = push/slide cube while side x is on top + // presentValue = x + 512 = double tap while side x is on top + + return 1; +} + // Aqara Vibration Sensor - special proprietary attributes int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { //json[new_name] = value; From ab167b097477b0fd53857e784edf77bfe955cbb4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 28 Dec 2019 14:54:26 +0100 Subject: [PATCH 174/559] Add more crash dump information --- RELEASENOTES.md | 1 + tasmota/support.ino | 7 ++++++- tasmota/support_command.ino | 9 +++++---- tasmota/support_crash_recorder.ino | 15 ++++++++++++++- tasmota/xdrv_02_mqtt.ino | 2 +- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e3b1e0fb4..42788a5b9 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -60,3 +60,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` - Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev +- Add Zigbee attribute decoder for Xiaomi Aqara Cube diff --git a/tasmota/support.ino b/tasmota/support.ino index 32ef55731..8010f1e5c 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -57,8 +57,13 @@ void OsWatchTicker(void) // AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_OSWATCH " " D_BLOCKED_LOOP ". " D_RESTARTING)); // Save iram space RtcSettings.oswatch_blocked_loop = 1; RtcSettingsSave(); + // ESP.restart(); // normal reboot - ESP.reset(); // hard reset +// ESP.reset(); // hard reset + + // Force an exception to get a stackdump + volatile uint32_t dummy; + dummy = *((uint32_t*) 0x00000000); } } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 397d60f30..0762fa329 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -333,9 +333,7 @@ void CmndStatus(void) if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } // SetOption3 - Enable MQTT if (!energy_flg && (9 == payload)) { payload = 99; } - - bool exception_flg = (ResetReason() == REASON_EXCEPTION_RST) || (ResetReason() == REASON_SOFT_WDT_RST); - if (!exception_flg && (12 == payload)) { payload = 99; } + if (!CrashFlag() && (12 == payload)) { payload = 99; } if ((0 == payload) || (99 == payload)) { uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; @@ -482,7 +480,7 @@ void CmndStatus(void) MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } - if (exception_flg) { + if (CrashFlag()) { if ((0 == payload) || (12 == payload)) { Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); CrashDump(); @@ -578,6 +576,9 @@ void CmndRestart(void) case -2: CmndWDT(); break; + case -3: + CmndBlockedLoop(); + break; case 99: AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); EspRestart(); diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino index d354adb3b..a51cb5dd2 100644 --- a/tasmota/support_crash_recorder.ino +++ b/tasmota/support_crash_recorder.ino @@ -50,7 +50,7 @@ void CmndCrash(void) dummy = *((uint32_t*) 0x00000000); } -// do an infinite loop to trigger WDT watchdog +// Do an infinite loop to trigger WDT watchdog void CmndWDT(void) { volatile uint32_t dummy = 0; @@ -59,6 +59,14 @@ void CmndWDT(void) } } +// This will trigger the os watch after OSWATCH_RESET_TIME (=120) seconds +void CmndBlockedLoop(void) +{ + while (1) { + delay(1000); + } +} + // Clear the RTC dump counter when we do a normal reboot, this avoids garbage data to stay in RTC void CrashDumpClear(void) { @@ -70,6 +78,11 @@ void CrashDumpClear(void) * CmndCrashDump - dump the crash history - called by `Status 12` \*********************************************************************************************/ +bool CrashFlag(void) +{ + return ((ResetReason() == REASON_EXCEPTION_RST) || (ResetReason() == REASON_SOFT_WDT_RST) || oswatch_blocked_loop); +} + void CrashDump(void) { ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""), diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 910a2ea6f..3544ec070 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -532,7 +532,7 @@ void MqttConnected(void) } #endif // USE_WEBSERVER Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":")); - if (ResetReason() == REASON_EXCEPTION_RST) { + if (CrashFlag()) { CrashDump(); } else { ResponseAppend_P(PSTR("\"%s\""), GetResetReason().c_str()); From aefb3fb9de0e2f43afd54665006009a99d030eb8 Mon Sep 17 00:00:00 2001 From: Andre Thomas <470015+andrethomas@users.noreply.github.com> Date: Sat, 28 Dec 2019 16:47:30 +0200 Subject: [PATCH 175/559] Reserve SetOption79 Used to enable resetting of the counter values to zero after telemetry data was transmitted. --- tasmota/settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index eddc4f04b..0c47e5aca 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -92,7 +92,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t bootcount_update : 1; // bit 26 (v7.0.0.4) - SetOption76 - Enable incrementing bootcount when deepsleep is enabled uint32_t slider_dimmer_stay_on : 1; // bit 27 (v7.0.0.6) - SetOption77 - Do not power off if slider moved to far left uint32_t compatibility_check : 1; // bit 28 (v7.1.2.6) - SetOption78 - Disable OTA compatibility check - uint32_t spare29 : 1; + uint32_t counter_reset_on_tele : 1; // bit 29 (v8.1.0.1) - SetOption79 - Enable resetting of counters after telemetry was sent uint32_t shutter_mode : 1; // bit 30 (v6.6.0.14) - SetOption80 - Enable shutter support uint32_t pcf8574_ports_inverted : 1; // bit 31 (v6.6.0.14) - SetOption81 - Invert all ports on PCF8574 devices }; From 436cf830b9b5690d3f41a122160352c5106d87cf Mon Sep 17 00:00:00 2001 From: Andre Thomas <470015+andrethomas@users.noreply.github.com> Date: Sat, 28 Dec 2019 16:49:57 +0200 Subject: [PATCH 176/559] Add support for resetting counters on tele_period Add support for resetting counters on tele_period if SetOption78 is enabled. --- tasmota/xsns_01_counter.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tasmota/xsns_01_counter.ino b/tasmota/xsns_01_counter.ino index 8ed615c86..c664ff811 100644 --- a/tasmota/xsns_01_counter.ino +++ b/tasmota/xsns_01_counter.ino @@ -150,6 +150,9 @@ void CounterShow(bool json) ResponseAppend_P(PSTR(",\"COUNTER\":{")); } ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); + if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { + RtcSettings.pulse_counter[i] = 0; + } header = true; #ifdef USE_DOMOTICZ if ((0 == tele_period) && (1 == dsxflg)) { From 4a9271acedc8cb11829d45c1632723f9c35ec5c5 Mon Sep 17 00:00:00 2001 From: Andre Thomas <470015+andrethomas@users.noreply.github.com> Date: Sat, 28 Dec 2019 17:26:15 +0200 Subject: [PATCH 177/559] Update xsns_01_counter.ino --- tasmota/xsns_01_counter.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/xsns_01_counter.ino b/tasmota/xsns_01_counter.ino index c664ff811..985216392 100644 --- a/tasmota/xsns_01_counter.ino +++ b/tasmota/xsns_01_counter.ino @@ -150,9 +150,6 @@ void CounterShow(bool json) ResponseAppend_P(PSTR(",\"COUNTER\":{")); } ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); - if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { - RtcSettings.pulse_counter[i] = 0; - } header = true; #ifdef USE_DOMOTICZ if ((0 == tele_period) && (1 == dsxflg)) { @@ -160,6 +157,9 @@ void CounterShow(bool json) dsxflg++; } #endif // USE_DOMOTICZ + if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { + RtcSettings.pulse_counter[i] = 0; + } #ifdef USE_WEBSERVER } else { WSContentSend_PD(PSTR("{s}" D_COUNTER "%d{m}%s%s{e}"), From 6a06d356267b0291409f4f114cf7e1736d3a75ce Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 28 Dec 2019 16:33:51 +0100 Subject: [PATCH 178/559] Add command ``SetOption79 0/1`` Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 42788a5b9..c0524023e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -57,6 +57,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change Lights: simplified gamma correction and 10 bits internal computation - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) +- Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` - Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 3abb0db81..0cb300692 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Change Lights: simplified gamma correction and 10 bits internal computation - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) +- Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add SerialConfig to ``Status 1`` - Add WifiPower to ``Status 5`` - Add support for DS1624, DS1621 Temperature sensor by Leonid Myravjev From daf3d27c9afe0f89d8eeb8cd92609e146764c3e3 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Sat, 28 Dec 2019 23:24:52 +0700 Subject: [PATCH 179/559] Update xdrv_27_shutter.ino Try to bugfix --- tasmota/xdrv_27_shutter.ino | 60 +++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 8392bebad..4b3936533 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -89,32 +89,33 @@ void ShutterRtc50mS(void) } } -int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t i) + +int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index) { - if (Settings.shutter_set50percent[i] != 50) { - return percent <= 5 ? Settings.shuttercoeff[2][i] * percent : Settings.shuttercoeff[1][i] * percent + Settings.shuttercoeff[0][i]; + if (Settings.shutter_set50percent[index] != 50) { + return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; } else { - int32_t realpos; + uint32_t realpos; // check against DIV 0 for (uint8_t j=0 ; j < 5 ; j++) { - if (Settings.shuttercoeff[j][i] == 0) { + if (Settings.shuttercoeff[j][index] == 0) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); for (uint8_t k=0 ; k < 5 ; k++) { - Settings.shuttercoeff[k][i] = messwerte[k] * 1000 / messwerte[4]; + Settings.shuttercoeff[k][index] = messwerte[k] * 1000 / messwerte[4]; } } } - for (uint8_t l=0 ; l < 5 ; l++) { - if (percent*10 > Settings.shuttercoeff[l][i]) { - realpos = Shutter.open_max[i] * calibrate_pos[l+1] / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[l][i]); + for (uint8_t i=0 ; i < 5 ; i++) { + if (percent*10 > Settings.shuttercoeff[i][index]) { + realpos = Shutter.open_max[index] * calibrate_pos[i+1] / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[i][index]); } else { - if ( l == 0) { - realpos = percent * Shutter.open_max[i] * calibrate_pos[l+1] / Settings.shuttercoeff[l][i] / 10; + if ( i == 0) { + realpos = percent * Shutter.open_max[index] * calibrate_pos[i+1] / Settings.shuttercoeff[i][index] / 10; } else { - //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][i] ) * Shutter_Open_Max[i] * (calibrate_pos[l+1] - calibrate_pos[l]) / (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][l]) / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[l+1] - calibrate_pos[l]), (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][l])); - realpos += ( percent*10 - Settings.shuttercoeff[l-1][i] ) * Shutter.open_max[i] * (calibrate_pos[l+1] - calibrate_pos[l]) / (Settings.shuttercoeff[l][i] -Settings.shuttercoeff[l-1][i]) / 100; + //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[i+1] - calibrate_pos[i]), (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index])); + realpos += ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; } break; } @@ -123,33 +124,34 @@ int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t i) } } -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t i) +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint8_t index) { - if (Settings.shutter_set50percent[i] != 50) { - return Settings.shuttercoeff[2][i] * 5 > realpos ? realpos / Settings.shuttercoeff[2][i] : (realpos-Settings.shuttercoeff[0][i]) / Settings.shuttercoeff[1][i]; + if (Settings.shutter_set50percent[index] != 50) { + return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; } else { - int16_t realpercent; + uint16_t realpercent; - for (uint8_t j=0 ; j < 5 ; j++) { - if (realpos > Shutter.open_max[i] * calibrate_pos[j+1] / 100) { - realpercent = Settings.shuttercoeff[j][i] /10; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[i] * calibrate_pos[i+1] / 100); + for (uint8_t i=0 ; i < 5 ; i++) { + if (realpos > Shutter.open_max[index] * calibrate_pos[i+1] / 100) { + realpercent = Settings.shuttercoeff[i][index] /10; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[index] * calibrate_pos[i+1] / 100); } else { if ( i == 0) { - realpercent = ( realpos - (Shutter.open_max[i] * calibrate_pos[j] / 100) ) * 10 * Settings.shuttercoeff[j][i] / calibrate_pos[j+1] / Shutter.open_max[i]; + realpercent = ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * Settings.shuttercoeff[i][index] / calibrate_pos[i+1] / Shutter.open_max[index]; } else { - //uint16_t addon = ( realpos - (Shutter_Open_Max[i] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][i] - Settings.shuttercoeff[i-1][i]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[i]; - //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][i] ) * Shutter_Open_Max[i] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][i] -Settings.shuttercoeff[i-1][i]) / 100; - //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[i] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[i]/100, (Settings.shuttercoeff[i][i] -Settings.shuttercoeff[i-1][i])); - realpercent += ( realpos - (Shutter.open_max[i] * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][i] - Settings.shuttercoeff[j-1][i]) / (calibrate_pos[j+1] - calibrate_pos[j]) / Shutter.open_max[i] ; + //uint16_t addon = ( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[index]; + //uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100; + //AddLog_P2(LOG_LEVEL_INFO, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[index]/100, (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index])); + realpercent += ( realpos - (Shutter.open_max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i]) / Shutter.open_max[index] ; } break; } } - return (realpercent < 0 ? 0 : (realpercent > 100 ? 0 : realpercent)); + return realpercent; } } + void ShutterInit(void) { shutters_present = 0; From 7a49f523e7d3f296a3f1ae9ab2310be181cbc5b9 Mon Sep 17 00:00:00 2001 From: Bohdan Kmit Date: Sat, 28 Dec 2019 19:25:43 +0200 Subject: [PATCH 180/559] Make scripter configuration interface localizable Add tasmota-script build environment and travis entry --- tasmota/language/bg-BG.h | 13 +++++++++++++ tasmota/language/cs-CZ.h | 13 +++++++++++++ tasmota/language/de-DE.h | 13 +++++++++++++ tasmota/language/el-GR.h | 13 +++++++++++++ tasmota/language/en-GB.h | 13 +++++++++++++ tasmota/language/es-ES.h | 13 +++++++++++++ tasmota/language/fr-FR.h | 13 +++++++++++++ tasmota/language/he-HE.h | 13 +++++++++++++ tasmota/language/hu-HU.h | 13 +++++++++++++ tasmota/language/it-IT.h | 13 +++++++++++++ tasmota/language/ko-KO.h | 13 +++++++++++++ tasmota/language/nl-NL.h | 13 +++++++++++++ tasmota/language/pl-PL.h | 13 +++++++++++++ tasmota/language/pt-BR.h | 13 +++++++++++++ tasmota/language/pt-PT.h | 13 +++++++++++++ tasmota/language/ru-RU.h | 13 +++++++++++++ tasmota/language/sk-SK.h | 13 +++++++++++++ tasmota/language/sv-SE.h | 13 +++++++++++++ tasmota/language/tr-TR.h | 13 +++++++++++++ tasmota/language/uk-UA.h | 23 ++++++++++++++++++----- tasmota/language/zh-CN.h | 13 +++++++++++++ tasmota/language/zh-TW.h | 13 +++++++++++++ tasmota/xdrv_10_scripter.ino | 19 +++++++------------ 23 files changed, 298 insertions(+), 17 deletions(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index f2ac56402..22e99f9f9 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Грешка - вентилатор" #define D_SOLAX_ERROR_8 "Грешка - друго оборудване" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_BG_BG_H_ diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 272e2c5ca..92ba99b30 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_CS_CZ_H_ diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 9e30f42f8..eeddc5580 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Lüfterfehler" #define D_SOLAX_ERROR_8 "sonstiger Fehler" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_DE_DE_H_ diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index 2b1e4748c..15b78fea7 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_EL_GR_H_ diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index ab7f90cf8..72d30faac 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_EN_GB_H_ diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index e41b4cb32..cc8cc3166 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Falla de Ventilador" #define D_SOLAX_ERROR_8 "Falla del Dispositivo" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_ES_ES_H_ diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index d9d7019f8..c84610379 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Défaut Ventilateur" #define D_SOLAX_ERROR_8 "Défaut Autre équipement" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_FR_FR_H_ diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index 9e26a6c5e..d21750fba 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_HE_HE_H_ diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index b7f33a549..da61d1ffd 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_HU_HU_H_ diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index d3c55579a..ca584ec8e 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Errore Ventilatore" #define D_SOLAX_ERROR_8 "Altro Errore del Dispositivo" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_IT_IT_H_ diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index a6c2088a1..b85f60bce 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_KO_KO_H_ diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 8fb492399..1fde4786d 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Ventilator" #define D_SOLAX_ERROR_8 "Overige" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_NL_NL_H_ diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 4f2c9c069..f8250eda2 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Błąd - wentylator" #define D_SOLAX_ERROR_8 "Błąd - inne urządzenie" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_PL_PL_D_H_ diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 0c9891323..f5390be86 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Falha no Ventilador" #define D_SOLAX_ERROR_8 "Outra falha do dispositivo" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_PT_BR_H_ diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 210ef8e29..154bebd70 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Falha no ventilador" #define D_SOLAX_ERROR_8 "Outra falha no dispositivo" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_PT_PT_H_ diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 6696e0e48..89567f11f 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_RU_RU_H_ diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index 21120179a..c42130e11 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_SK_SK_H_ diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index 117fb40ed..074c81c8e 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_SV_SE_H_ diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 9874688da..04cc270ec 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_TR_TR_H_ diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index cd77adebd..af7672973 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -296,14 +296,14 @@ #define D_OTHER_PARAMETERS "Параметри Інше" #define D_TEMPLATE "Шаблони" -#define D_ACTIVATE "Активувний" +#define D_ACTIVATE "Активований" #define D_WEB_ADMIN_PASSWORD "Гасло адміністратора Web" #define D_MQTT_ENABLE "MQTT активний" -#define D_FRIENDLY_NAME "Дружнє Ім'я" +#define D_FRIENDLY_NAME "Дружня назва" #define D_BELKIN_WEMO "Belkin WeMo" -#define D_HUE_BRIDGE "Hue Bridge" -#define D_SINGLE_DEVICE "одиночне" -#define D_MULTI_DEVICE "мульти" +#define D_HUE_BRIDGE "Міст Hue" +#define D_SINGLE_DEVICE "один пристрій" +#define D_MULTI_DEVICE "декілька пристроїв" #define D_CONFIGURE_TEMPLATE "Конфігурація шаблона" #define D_TEMPLATE_PARAMETERS "Параметри шаблона" @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Вентилятор" #define D_SOLAX_ERROR_8 "Інший пристрій" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Конфігурація сценарія" +#define D_SCRIPT "Редагування сценарія" +#define D_SDCARD_UPLOAD "завантажити файл на карту SD" +#define D_SDCARD_DIR "завантажити файл в каталог на карту SD" +#define D_UPL_DONE "Готово" +#define D_SCRIPT_CHARS_LEFT "символів ще вільно" +#define D_SCRIPT_CHARS_NO_MORE "більше немає місця" +#define D_SCRIPT_DOWNLOAD "Звантажити" +#define D_SCRIPT_ENABLE "Сценарій увімкнено" +#define D_SCRIPT_UPLOAD "Завантажити" +#define D_SCRIPT_UPLOAD_FILES "Завантажити файли" + #endif // _LANGUAGE_UK_UA_H_ diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 7700e7e78..4c75b7bb7 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_ZH_CN_H_ diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 34bb68e3d..f17ba46b7 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -702,4 +702,17 @@ #define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_8 "Other Device Fault" +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Edit script" +#define D_SCRIPT "edit script" +#define D_SDCARD_UPLOAD "file upload" +#define D_SDCARD_DIR "sd card directory" +#define D_UPL_DONE "Done" +#define D_SCRIPT_CHARS_LEFT "chars left" +#define D_SCRIPT_CHARS_NO_MORE "no more chars" +#define D_SCRIPT_DOWNLOAD "Download" +#define D_SCRIPT_ENABLE "script enable" +#define D_SCRIPT_UPLOAD "Upload" +#define D_SCRIPT_UPLOAD_FILES "Upload files" + #endif // _LANGUAGE_ZH_TW_H_ diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 6b97fa68a..29177482a 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -3033,11 +3033,6 @@ void Scripter_save_pvars(void) { #ifdef USE_WEBSERVER #define WEB_HANDLE_SCRIPT "s10" -#define D_CONFIGURE_SCRIPT "Edit script" -#define D_SCRIPT "edit script" -#define D_SDCARD_UPLOAD "file upload" -#define D_SDCARD_DIR "sd card directory" -#define D_UPL_DONE "Done" const char S_CONFIGURE_SCRIPT[] PROGMEM = D_CONFIGURE_SCRIPT; @@ -3051,7 +3046,7 @@ const char HTTP_FORM_SCRIPT[] PROGMEM = const char HTTP_FORM_SCRIPT1[] PROGMEM = "
" - "script enable
" + "" D_SCRIPT_ENABLE "
" "


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

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

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

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

"), + GetTextIndexed(action, sizeof(action), title_index, kButtonAction), + GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); + } +} + +void WSContentSpaceButton(uint32_t title_index) +{ + WSContentSend_P(PSTR("
")); + WSContentButton(title_index); +} + +void WSContentEnd(void) +{ + WSContentFlush(); + _WSContentSend(""); + WebServer->client().stop(); +} + +void WSContentStop(void) +{ + if (WifiIsInManagerMode()) { + if (WifiConfigCounter()) { + WSContentSend_P(HTTP_COUNTER); + } + } + WSContentSend_P(HTTP_END, my_version); + WSContentEnd(); +} + + + +void WebRestart(uint32_t type) +{ + + + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); + + bool reset_only = (HTTP_MANAGER_RESET_ONLY == Web.state); + + WSContentStart_P((type) ? S_SAVE_CONFIGURATION : S_RESTART, !reset_only); + WSContentSend_P(HTTP_SCRIPT_RELOAD); + WSContentSendStyle(); + if (type) { + WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); + if (2 == type) { + WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); + } + WSContentSend_P(PSTR("
")); + } + WSContentSend_P(HTTP_MSG_RSTRT); + if (HTTP_MANAGER == Web.state || reset_only) { + Web.state = HTTP_ADMIN; + } else { + WSContentSpaceButton(BUTTON_MAIN); + } + WSContentStop(); + + ShowWebSource(SRC_WEBGUI); + restart_flag = 2; +} + + + +void HandleWifiLogin(void) +{ + WSContentStart_P(S_CONFIGURE_WIFI, false); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_LOGIN); + + if (HTTP_MANAGER_RESET_ONLY == Web.state) { + WSContentSpaceButton(BUTTON_RESTART); +#ifndef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); +#endif + } + + WSContentStop(); +} + +void WebSliderColdWarm(void) +{ + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "a", + "#fff", "#ff0", + 1, + 153, 500, + LightGetColorTemp(), + 't', 0); +} + +void HandleRoot(void) +{ + if (CaptivePortal()) { return; } + + if (WebServer->hasArg("rst")) { + WebRestart(0); + return; + } + + if (WifiIsInManagerMode()) { +#ifndef FIRMWARE_MINIMAL + if (strlen(SettingsText(SET_WEBPWD)) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { + HandleWifiLogin(); + } else { + if (!strlen(SettingsText(SET_WEBPWD)) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { + HandleWifiConfiguration(); + } else { + + HandleWifiLogin(); + } + } +#endif + return; + } + + if (HandleRootStatusRefresh()) { + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); + + char stemp[33]; + + WSContentStart_P(S_MAIN_MENU); +#ifdef USE_SCRIPT_WEB_DISPLAY + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh, Settings.web_refresh); +#else + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); +#endif + WSContentSend_P(HTTP_SCRIPT_ROOT_PART2); + + WSContentSendStyle(); + + WSContentSend_P(PSTR("
")); + if (devices_present) { +#ifdef USE_LIGHT + if (light_type) { + uint8_t light_subtype = light_type &7; + if (!Settings.flag3.pwm_multi_channels) { + bool split_white = ((LST_RGBW <= light_subtype) && (devices_present > 1)); + + if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) { + WebSliderColdWarm(); + } + + if (light_subtype > 2) { + uint16_t hue; + uint8_t sat; + LightGetHSB(&hue, &sat, nullptr); + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "b", + "#800", "#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800", + 2, + 1, 359, + hue, + 'h', 0); + + uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255); + char scolor[8]; + snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); + uint8_t red, green, blue; + LightHsToRgb(hue, 255, &red, &green, &blue); + snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "s", + scolor, stemp, + 3, + 0, 100, + changeUIntScale(sat, 0, 255, 0, 100), + 'n', 0); + } + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "c", + "#000", "#fff", + 4, + Settings.flag3.slider_dimmer_stay_on, 100, + Settings.light_dimmer, + 'd', 0); + + if (split_white) { + if (LST_RGBCW == light_subtype) { + WebSliderColdWarm(); + } + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "f", + "#000", "#fff", + 5, + Settings.flag3.slider_dimmer_stay_on, 100, + LightGetDimmer(2), + 'w', 0); + } + } else { + uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; + stemp[0] = 'e'; stemp[1] = '0'; stemp[2] = '\0'; + for (uint32_t i = 0; i < pwm_channels; i++) { + stemp[1]++; + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + stemp, + "#000", "#fff", + i+1, + 1, 100, + changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), + 'e', i+1); + } + } + } +#endif +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + for (uint32_t i = 0; i < shutters_present; i++) { + WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1); + } + } +#endif + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("
")); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, + (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : D_BUTTON_TOGGLE, + ""); + for (uint32_t i = 0; i < MaxFanspeed(); i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); + WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, + (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp, + ""); + } + } else { +#endif + for (uint32_t idx = 1; idx <= devices_present; idx++) { + bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); +#ifdef USE_SHUTTER + int32_t ShutterWebButton; + if (ShutterWebButton = IsShutterWebButton(idx)) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) ? "-" : ((ShutterWebButton>0) ? "▲" : "▼")), + ""); + continue; + } +#endif + snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (devices_present < 5) ? D_BUTTON_TOGGLE : "", + (set_button) ? "" : (devices_present > 1) ? stemp : ""); + } +#ifdef USE_SONOFF_IFAN + } +#endif + WSContentSend_P(PSTR("
%s
")); + } +#ifdef USE_SONOFF_RF + if (SONOFF_BRIDGE == my_module_type) { + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("")); + uint32_t idx = 0; + for (uint32_t i = 0; i < 4; i++) { + if (idx > 0) { WSContentSend_P(PSTR("")); } + for (uint32_t j = 0; j < 4; j++) { + idx++; + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), idx); + WSContentSend_P(PSTR(""), idx, + (strlen(SettingsText(SET_BUTTON1 + idx -1))) ? SettingsText(SET_BUTTON1 + idx -1) : stemp); + } + } + WSContentSend_P(PSTR("")); + } +#endif + +#ifndef FIRMWARE_MINIMAL + XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); + XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); +#endif + + if (HTTP_ADMIN == Web.state) { +#ifdef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE); +#else + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentButton(BUTTON_INFORMATION); + WSContentButton(BUTTON_FIRMWARE_UPGRADE); +#endif + WSContentButton(BUTTON_CONSOLE); + WSContentButton(BUTTON_RESTART); + } + WSContentStop(); +} + +bool HandleRootStatusRefresh(void) +{ + if (!WebAuthenticate()) { + WebServer->requestAuthentication(); + return true; + } + + if (!WebServer->hasArg("m")) { + return false; + } + + #ifdef USE_SCRIPT_WEB_DISPLAY + Script_Check_HTML_Setvars(); + #endif + + char tmp[8]; + char svalue[32]; + char webindex[5]; + + WebGetArg("o", tmp, sizeof(tmp)); + if (strlen(tmp)) { + ShowWebSource(SRC_WEBGUI); + uint32_t device = atoi(tmp); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + if (device < 2) { + ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE); + } else { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), device -2); + ExecuteCommand(svalue, SRC_WEBGUI); + } + } else { +#endif +#ifdef USE_SHUTTER + int32_t ShutterWebButton; + if (ShutterWebButton = IsShutterWebButton(device)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_TOGGLEUP) : PSTR(D_CMND_SHUTTER_TOGGLEDOWN)); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } else { +#endif + ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); +#ifdef USE_SHUTTER + } +#endif +#ifdef USE_SONOFF_IFAN + } +#endif + } + WebGetArg("d0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("w0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + for (uint32_t j = 1; j <= pwm_channels; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } + WebGetArg("t0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("h0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("n0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } +#ifdef USE_SHUTTER + for (uint32_t j = 1; j <= shutters_present; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } +#endif +#ifdef USE_SONOFF_RF + WebGetArg("k", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } +#endif + WSContentBegin(200, CT_HTML); + WSContentSend_P(PSTR("{t}")); + XsnsCall(FUNC_WEB_SENSOR); +#ifdef USE_SCRIPT_WEB_DISPLAY + XdrvCall(FUNC_WEB_SENSOR); +#endif + + WSContentSend_P(PSTR("")); + + if (devices_present) { + WSContentSend_P(PSTR("{t}")); + uint32_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); + uint32_t fanspeed = GetFanspeed(); + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); + WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); + } else { +#endif + for (uint32_t idx = 1; idx <= devices_present; idx++) { + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); + WSContentSend_P(HTTP_DEVICE_STATE, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); + } +#ifdef USE_SONOFF_IFAN + } +#endif + WSContentSend_P(PSTR("")); + } + WSContentEnd(); + + return true; +} + +#ifdef USE_SHUTTER +int32_t IsShutterWebButton(uint32_t idx) { + + int32_t ShutterWebButton = 0; + if (Settings.flag3.shutter_mode) { + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + if (Settings.shutter_startrelay[i] && ((Settings.shutter_startrelay[i] == idx) || (Settings.shutter_startrelay[i] == (idx-1)))) { + ShutterWebButton = (Settings.shutter_startrelay[i] == idx) ? (i+1): (-1-i); + break; + } + } + } + return ShutterWebButton; +} +#endif + + + +#ifndef FIRMWARE_MINIMAL + +void HandleConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); + + WSContentStart_P(S_CONFIGURATION); + WSContentSendStyle(); + + WSContentButton(BUTTON_MODULE); + WSContentButton(BUTTON_WIFI); + + XdrvCall(FUNC_WEB_ADD_BUTTON); + XsnsCall(FUNC_WEB_ADD_BUTTON); + + WSContentButton(BUTTON_LOGGING); + WSContentButton(BUTTON_OTHER); + WSContentButton(BUTTON_TEMPLATE); + + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); + WSContentButton(BUTTON_BACKUP); + WSContentButton(BUTTON_RESTORE); + + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + + + +void HandleTemplateConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + TemplateSaveSettings(); + WebRestart(1); + return; + } + + char stemp[30]; + + if (WebServer->hasArg("m")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { + uint32_t midx = pgm_read_byte(kModuleNiceList + i); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); + } + WSContentEnd(); + return; + } + + WebGetArg("t", stemp, sizeof(stemp)); + if (strlen(stemp)) { + uint32_t module = atoi(stemp); + uint32_t module_save = Settings.module; + Settings.module = module; + myio cmodule; + ModuleGpios(&cmodule); + gpio_flag flag = ModuleFlag(); + Settings.module = module_save; + + WSContentBegin(200, CT_PLAIN); + WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); + for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { + if (1 == i) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); + } + uint32_t midx = pgm_read_byte(kGpioNiceList + i); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); + } + WSContentSend_P(PSTR("}1")); + + for (uint32_t i = 0; i < ADC0_END; i++) { + if (1 == i) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ADC0_USER, D_SENSOR_USER, ADC0_USER); + } + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, i, GetTextIndexed(stemp, sizeof(stemp), i, kAdc0Names), i); + } + WSContentSend_P(PSTR("}1")); + + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if ((i < 6) || ((i > 8) && (i != 11))) { + WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", cmodule.io[i]); + } + } + WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings.user_template_base); + WSContentEnd(); + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); + + WSContentStart_P(S_CONFIGURE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_TEMPLATE); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_TEMPLATE); + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("" D_TEMPLATE_NAME "" + "" D_BASE_TYPE "" + "" + "
")); + WSContentSend_P(HTTP_TABLE100); + for (uint32_t i = 0; i < 17; i++) { + if ((i < 6) || ((i > 8) && (i != 11))) { + WSContentSend_P(PSTR("" D_GPIO "%d"), + ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i); + } + } + WSContentSend_P(PSTR("" D_ADC "0"), WebColor(COL_TEXT)); + WSContentSend_P(PSTR("")); + gpio_flag flag = ModuleFlag(); + if (flag.data > ADC0_USER) { + WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); + } + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void TemplateSaveSettings(void) +{ + char tmp[sizeof(Settings.user_template.name)]; + char webindex[5]; + char svalue[128]; + + WebGetArg("s1", tmp, sizeof(tmp)); + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); + + uint32_t j = 0; + for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); + uint8_t gpio = atoi(tmp); + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio); + j++; + } + + WebGetArg("g17", tmp, sizeof(tmp)); + uint32_t flag = atoi(tmp); + for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { + snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); + uint32_t state = WebServer->hasArg(webindex) << i +4; + flag += state; + } + WebGetArg("g99", tmp, sizeof(tmp)); + uint32_t base = atoi(tmp) +1; + + snprintf_P(svalue, sizeof(svalue), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), svalue, flag, base); + ExecuteWebCommand(svalue, SRC_WEBGUI); +} + + + +void HandleModuleConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + ModuleSaveSettings(); + WebRestart(1); + return; + } + + char stemp[30]; + uint32_t midx; + myio cmodule; + ModuleGpios(&cmodule); + + if (WebServer->hasArg("m")) { + WSContentBegin(200, CT_PLAIN); + uint32_t vidx = 0; + for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { + if (0 == i) { + midx = USER_MODULE; + vidx = 0; + } else { + midx = pgm_read_byte(kModuleNiceList + i -1); + vidx = midx +1; + } + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx); + } + WSContentEnd(); + return; + } + + if (WebServer->hasArg("g")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t j = 0; j < sizeof(kGpioNiceList); j++) { + midx = pgm_read_byte(kGpioNiceList + j); + if (!GetUsedInModule(midx, cmodule.io)) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); + } + } + WSContentEnd(); + return; + } + +#ifndef USE_ADC_VCC + if (WebServer->hasArg("a")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t j = 0; j < ADC0_END; j++) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j); + } + WSContentEnd(); + return; + } +#endif + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); + + WSContentStart_P(S_CONFIGURE_MODULE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (ValidGPIO(i, cmodule.io[i])) { + WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); + } + } + WSContentSend_P(HTTP_SCRIPT_MODULE2, Settings.my_adc0); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (ValidGPIO(i, cmodule.io[i])) { + snprintf_P(stemp, 3, PINS_WEMOS +i*2); + char sesp8285[40]; + snprintf_P(sesp8285, sizeof(sesp8285), PSTR("ESP8285"), WebColor(COL_TEXT_WARNING)); + WSContentSend_P(PSTR("%s " D_GPIO "%d %s"), + (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i); + } + } +#ifndef USE_ADC_VCC + if (ValidAdc()) { + WSContentSend_P(PSTR("%s " D_ADC "0"), (WEMOS==my_module_type)?"A0":""); + } +#endif + WSContentSend_P(PSTR("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void ModuleSaveSettings(void) +{ + char tmp[8]; + char webindex[5]; + + WebGetArg("g99", tmp, sizeof(tmp)); + uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); + Settings.last_module = Settings.module; + Settings.module = new_module; + SetModuleType(); + myio cmodule; + ModuleGpios(&cmodule); + String gpios = ""; + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (Settings.last_module != new_module) { + Settings.my_gp.io[i] = GPIO_NONE; + } else { + if (ValidGPIO(i, cmodule.io[i])) { + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); + WebGetArg(webindex, tmp, sizeof(tmp)); + Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); + } + } + } +#ifndef USE_ADC_VCC + WebGetArg("g17", tmp, sizeof(tmp)); + Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp); + gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0); +#endif + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); +} + + + +const char kUnescapeCode[] = "&><\"\'"; +const char kEscapeCode[] PROGMEM = "&|>|<|"|'"; + +String HtmlEscape(const String unescaped) { + char escaped[10]; + size_t ulen = unescaped.length(); + String result = ""; + for (size_t i = 0; i < ulen; i++) { + char c = unescaped[i]; + char *p = strchr(kUnescapeCode, c); + if (p != nullptr) { + result += GetTextIndexed(escaped, sizeof(escaped), p - kUnescapeCode, kEscapeCode); + } else { + result += c; + } + } + return result; +} + + +const char kEncryptionType[] PROGMEM = "|||" D_WPA_PSK "||" D_WPA2_PSK "|" D_WEP "||" D_NONE "|" D_AUTO; + +void HandleWifiConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); + + if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { + WifiSaveSettings(); + WebRestart(2); + return; + } + + WSContentStart_P(S_CONFIGURE_WIFI, !WifiIsInManagerMode()); + WSContentSend_P(HTTP_SCRIPT_WIFI); + WSContentSendStyle(); + + if (HTTP_MANAGER_RESET_ONLY != Web.state) { + if (WebServer->hasArg("scan")) { +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + int n = WiFi.scanNetworks(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); + + if (0 == n) { + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); + WSContentSend_P(S_NO_NETWORKS_FOUND); + WSContentSend_P(PSTR(". " D_REFRESH_TO_SCAN_AGAIN ".")); + } else { + + int indices[n]; + for (uint32_t i = 0; i < n; i++) { + indices[i] = i; + } + + + for (uint32_t i = 0; i < n; i++) { + for (uint32_t j = i + 1; j < n; j++) { + if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { + std::swap(indices[i], indices[j]); + } + } + } + + + String cssid; + for (uint32_t i = 0; i < n; i++) { + if (-1 == indices[i]) { continue; } + cssid = WiFi.SSID(indices[i]); + uint32_t cschn = WiFi.channel(indices[i]); + for (uint32_t j = i + 1; j < n; j++) { + if ((cssid == WiFi.SSID(indices[j])) && (cschn == WiFi.channel(indices[j]))) { + DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); + indices[j] = -1; + } + } + } + + + for (uint32_t i = 0; i < n; i++) { + if (-1 == indices[i]) { continue; } + DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), + WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); + int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); + int auth = WiFi.encryptionType(indices[i]); + char encryption[20]; + WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), + HtmlEscape(WiFi.SSID(indices[i])).c_str(), + WiFi.channel(indices[i]), + GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), + quality, WiFi.RSSI(indices[i]) + ); + delay(0); + + } + WSContentSend_P(PSTR("
")); + } + } else { + WSContentSend_P(PSTR("
")); + } + + + WSContentSend_P(HTTP_FORM_WIFI, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS)); + WSContentSend_P(HTTP_FORM_END); + } + + if (WifiIsInManagerMode()) { +#ifndef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESTORE); + WSContentButton(BUTTON_RESET_CONFIGURATION); +#endif + WSContentSpaceButton(BUTTON_RESTART); + } else { + WSContentSpaceButton(BUTTON_CONFIGURATION); + } + WSContentStop(); +} + +void WifiSaveSettings(void) +{ + char tmp[TOPSZ]; + + WebGetArg("h", tmp, sizeof(tmp)); + SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + } + WebGetArg("c", tmp, sizeof(tmp)); + SettingsUpdateText(SET_CORS, (!strlen(tmp)) ? CORS_DOMAIN : tmp); + WebGetArg("s1", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STASSID1, (!strlen(tmp)) ? STA_SSID1 : tmp); + WebGetArg("s2", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STASSID2, (!strlen(tmp)) ? STA_SSID2 : tmp); + WebGetArg("p1", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STAPWD1, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD1) : tmp); + WebGetArg("p2", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STAPWD2, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD2) : tmp); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), + SettingsText(SET_HOSTNAME), SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), SettingsText(SET_CORS)); +} + + + +void HandleLoggingConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); + + if (WebServer->hasArg("save")) { + LoggingSaveSettings(); + HandleConfiguration(); + return; + } + + WSContentStart_P(S_CONFIGURE_LOGGING); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_LOG1); + char stemp1[45]; + char stemp2[32]; + uint8_t dlevel[4] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE, LOG_LEVEL_NONE }; + for (uint32_t idx = 0; idx < 4; idx++) { + if ((2==idx) && !Settings.flag.mqtt_enabled) { continue; } + uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:(2==idx)?Settings.mqttlog_level:Settings.syslog_level; + WSContentSend_P(PSTR("

%s (%s)

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

"), + i +1, + (i) ? stemp : "", + i, + (i) ? stemp : "", + SettingsText(SET_FRIENDLYNAME1 + i)); + } + +#ifdef USE_EMULATION + WSContentSend_P(PSTR("

 " D_EMULATION " 

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

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

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

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

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

" D_HOST " (" MQTT_HOST ")

" + "

" D_PORT " (" STR(MQTT_PORT) ")

" + "

" D_CLIENT " (%s)

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

" D_USER " (" MQTT_USER ")

" + "

" D_PASSWORD "

" + "

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

" + "

" D_FULL_TOPIC " (%s)

"; + +void HandleMqttConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); + + if (WebServer->hasArg("save")) { + MqttSaveSettings(); + WebRestart(1); + return; + } + + char str[TOPSZ]; + + WSContentStart_P(S_CONFIGURE_MQTT); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MQTT1, + SettingsText(SET_MQTT_HOST), + Settings.mqtt_port, + Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); + WSContentSend_P(HTTP_FORM_MQTT2, + (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), + Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC), + MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void MqttSaveSettings(void) +{ + char tmp[TOPSZ]; + char stemp[TOPSZ]; + char stemp2[TOPSZ]; + + WebGetArg("mt", tmp, sizeof(tmp)); + strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); + MakeValidMqtt(0, stemp); + WebGetArg("mf", tmp, sizeof(tmp)); + strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); + MakeValidMqtt(1, stemp2); + if ((strcmp(stemp, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) { + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, S_LWT, true); + } + SettingsUpdateText(SET_MQTT_TOPIC, stemp); + SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2); + WebGetArg("mh", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); + WebGetArg("ml", tmp, sizeof(tmp)); + Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); + WebGetArg("mc", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); +#else + WebGetArg("mu", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp); + WebGetArg("mp", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); +#endif +} +#endif + + + + + +bool Xdrv02(uint8_t function) +{ + bool result = false; + + if (Settings.flag.mqtt_enabled) { + switch (function) { + case FUNC_PRE_INIT: + MqttInit(); + break; + case FUNC_EVERY_50_MSECOND: + MqttClient.loop(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_MQTT); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); + break; +#endif + case FUNC_COMMAND: + result = DecodeCommand(kMqttCommands, MqttCommand); + break; + } + } + return result; +} +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_03_energy.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_03_energy.ino" +#ifdef USE_ENERGY_SENSOR + + + + +#define XDRV_03 3 +#define XSNS_03 3 + + + + +#define ENERGY_NONE 0 +#define ENERGY_WATCHDOG 4 + +#include + +#define D_CMND_POWERCAL "PowerCal" +#define D_CMND_VOLTAGECAL "VoltageCal" +#define D_CMND_CURRENTCAL "CurrentCal" +#define D_CMND_TARIFF "Tariff" +#define D_CMND_MODULEADDRESS "ModuleAddress" + +enum EnergyCommands { + CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, + CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS }; + +const char kEnergyCommands[] PROGMEM = "|" + D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" + D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|" +#ifdef USE_ENERGY_MARGIN_DETECTION + D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" +#ifdef USE_ENERGY_POWER_LIMIT + D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|" + D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" + D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|" +#endif +#endif + D_CMND_ENERGYRESET "|" D_CMND_TARIFF ; + +void (* const EnergyCommand[])(void) PROGMEM = { + &CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, + &CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress, +#ifdef USE_ENERGY_MARGIN_DETECTION + &CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh, +#ifdef USE_ENERGY_POWER_LIMIT + &CmndMaxEnergy, &CmndMaxEnergyStart, + &CmndMaxPower, &CmndMaxPowerHold, &CmndMaxPowerWindow, + &CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow, +#endif +#endif + &CmndEnergyReset, &CmndTariff }; + +const char kEnergyPhases[] PROGMEM = "|%s / %s|%s / %s / %s||[%s,%s]|[%s,%s,%s]"; + +struct ENERGY { + float voltage[3] = { 0, 0, 0 }; + float current[3] = { 0, 0, 0 }; + float active_power[3] = { 0, 0, 0 }; + float apparent_power[3] = { NAN, NAN, NAN }; + float reactive_power[3] = { NAN, NAN, NAN }; + float power_factor[3] = { NAN, NAN, NAN }; + float frequency[3] = { NAN, NAN, NAN }; + + float start_energy = 0; + float daily = 0; + float total = 0; + float export_active = NAN; + + unsigned long kWhtoday_delta = 0; + unsigned long kWhtoday_offset = 0; + unsigned long kWhtoday; + unsigned long period = 0; + + uint8_t fifth_second = 0; + uint8_t command_code = 0; + uint8_t data_valid[3] = { 0, 0, 0 }; + + uint8_t phase_count = 1; + bool voltage_common = false; + + bool voltage_available = true; + bool current_available = true; + + bool type_dc = false; + bool power_on = true; + +#ifdef USE_ENERGY_MARGIN_DETECTION + uint16_t power_history[3] = { 0 }; + uint8_t power_steady_counter = 8; + bool power_delta = false; + bool min_power_flag = false; + bool max_power_flag = false; + bool min_voltage_flag = false; + bool max_voltage_flag = false; + bool min_current_flag = false; + bool max_current_flag = false; + +#ifdef USE_ENERGY_POWER_LIMIT + uint16_t mplh_counter = 0; + uint16_t mplw_counter = 0; + uint8_t mplr_counter = 0; + uint8_t max_energy_state = 0; +#endif +#endif +} Energy; + +Ticker ticker_energy; + + + +bool EnergyTariff1Active() +{ + uint8_t dst = 0; + if (IsDst() && (Settings.tariff[0][1] != Settings.tariff[1][1])) { + dst = 1; + } + if (Settings.tariff[0][dst] != Settings.tariff[1][dst]) { + if (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || + (RtcTime.day_of_week == 7))) { + return true; + } + uint32_t minutes = MinutesPastMidnight(); + if (Settings.tariff[0][dst] > Settings.tariff[1][dst]) { + + return ((minutes >= Settings.tariff[0][dst]) || (minutes < Settings.tariff[1][dst])); + } else { + + return ((minutes >= Settings.tariff[0][dst]) && (minutes < Settings.tariff[1][dst])); + } + } else { + return false; + } +} + +void EnergyUpdateToday(void) +{ + if (Energy.kWhtoday_delta > 1000) { + unsigned long delta = Energy.kWhtoday_delta / 1000; + Energy.kWhtoday_delta -= (delta * 1000); + Energy.kWhtoday += delta; + } + + RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday; + Energy.daily = (float)(RtcSettings.energy_kWhtoday) / 100000; + Energy.total = (float)(RtcSettings.energy_kWhtotal + RtcSettings.energy_kWhtoday) / 100000; + + if (RtcTime.valid){ + + uint32_t energy_diff = (uint32_t)(Energy.total * 100000) - RtcSettings.energy_usage.last_usage_kWhtotal; + RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 100000); + + uint32_t return_diff = 0; + if (!isnan(Energy.export_active)) { + return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; + RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000); + } + + if (EnergyTariff1Active()) { + RtcSettings.energy_usage.usage1_kWhtotal += energy_diff; + RtcSettings.energy_usage.return1_kWhtotal += return_diff; + } else { + RtcSettings.energy_usage.usage2_kWhtotal += energy_diff; + RtcSettings.energy_usage.return2_kWhtotal += return_diff; + } + } +} + +void EnergyUpdateTotal(float value, bool kwh) +{ + + + + + uint32_t multiplier = (kwh) ? 100000 : 100; + + if (0 == Energy.start_energy || (value < Energy.start_energy)) { + Energy.start_energy = value; + } + else if (value != Energy.start_energy) { + Energy.kWhtoday = (unsigned long)((value - Energy.start_energy) * multiplier); + } + + if ((Energy.total < (value - 0.01)) && + Settings.flag3.hardware_energy_total) { + RtcSettings.energy_kWhtotal = (unsigned long)((value * multiplier) - Energy.kWhtoday_offset - Energy.kWhtoday); + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; + Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); + + } + EnergyUpdateToday(); +} + + + +void Energy200ms(void) +{ + Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; + + Energy.fifth_second++; + if (5 == Energy.fifth_second) { + Energy.fifth_second = 0; + + XnrgCall(FUNC_ENERGY_EVERY_SECOND); + + if (RtcTime.valid) { + if (LocalTime() == Midnight()) { + Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; + + RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + Energy.kWhtoday = 0; + Energy.kWhtoday_offset = 0; + RtcSettings.energy_kWhtoday = 0; + Energy.start_energy = 0; + + Energy.kWhtoday_delta = 0; + Energy.period = Energy.kWhtoday; + EnergyUpdateToday(); +#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) + Energy.max_energy_state = 3; +#endif + } +#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) + if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == Energy.max_energy_state )) { + Energy.max_energy_state = 0; + } +#endif + + } + } + + XnrgCall(FUNC_EVERY_200_MSECOND); +} + +void EnergySaveState(void) +{ + Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; + + Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + + Settings.energy_usage = RtcSettings.energy_usage; +} + +#ifdef USE_ENERGY_MARGIN_DETECTION +bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) +{ + bool change; + + if (!margin) return false; + change = save_flag; + if (type) { + flag = (value > margin); + } else { + flag = (value < margin); + } + save_flag = flag; + return (change != save_flag); +} + +void EnergyMarginCheck(void) +{ + if (Energy.power_steady_counter) { + Energy.power_steady_counter--; + return; + } + + uint16_t energy_power_u = (uint16_t)(Energy.active_power[0]); + + if (Settings.energy_power_delta) { + uint16_t delta = abs(Energy.power_history[0] - energy_power_u); + if (delta > 0) { + if (Settings.energy_power_delta < 101) { + uint16_t min_power = (Energy.power_history[0] > energy_power_u) ? energy_power_u : Energy.power_history[0]; + if (0 == min_power) { min_power++; } + if (((delta * 100) / min_power) > Settings.energy_power_delta) { + Energy.power_delta = true; + } + } else { + if (delta > (Settings.energy_power_delta -100)) { + Energy.power_delta = true; + } + } + if (Energy.power_delta) { + Energy.power_history[1] = Energy.active_power[0]; + Energy.power_history[2] = Energy.active_power[0]; + } + } + } + Energy.power_history[0] = Energy.power_history[1]; + Energy.power_history[1] = Energy.power_history[2]; + Energy.power_history[2] = energy_power_u; + + if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { + uint16_t energy_voltage_u = (uint16_t)(Energy.voltage[0]); + uint16_t energy_current_u = (uint16_t)(Energy.current[0] * 1000); + + DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); + + Response_P(PSTR("{")); + bool flag; + bool jsonflg = false; + if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, Energy.max_power_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, Energy.min_current_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, Energy.max_current_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (jsonflg) { + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); + EnergyMqttShow(); + } + } + +#ifdef USE_ENERGY_POWER_LIMIT + + if (Settings.energy_max_power_limit) { + if (Energy.active_power[0] > Settings.energy_max_power_limit) { + if (!Energy.mplh_counter) { + Energy.mplh_counter = Settings.energy_max_power_limit_hold; + } else { + Energy.mplh_counter--; + if (!Energy.mplh_counter) { + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":%d}"), energy_power_u); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); + if (!Energy.mplr_counter) { + Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; + } + Energy.mplw_counter = Settings.energy_max_power_limit_window; + } + } + } + else if (power && (energy_power_u <= Settings.energy_max_power_limit)) { + Energy.mplh_counter = 0; + Energy.mplr_counter = 0; + Energy.mplw_counter = 0; + } + if (!power) { + if (Energy.mplw_counter) { + Energy.mplw_counter--; + } else { + if (Energy.mplr_counter) { + Energy.mplr_counter--; + if (Energy.mplr_counter) { + ResponseTime_P(PSTR(",\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); + RestorePower(true, SRC_MAXPOWER); + } else { + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); + } + } + } + } + } + + + if (Settings.energy_max_energy) { + uint16_t energy_daily_u = (uint16_t)(Energy.daily * 1000); + if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { + Energy.max_energy_state = 1; + ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); + RestorePower(true, SRC_MAXENERGY); + } + else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { + Energy.max_energy_state = 2; + char stemp[FLOATSZ]; + dtostrfd(Energy.daily, 3, stemp); + ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":%s}"), stemp); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); + } + } +#endif + + if (Energy.power_delta) { EnergyMqttShow(); } +} + +void EnergyMqttShow(void) +{ + + int tele_period_save = tele_period; + tele_period = 2; + mqtt_data[0] = '\0'; + ResponseAppendTime(); + EnergyShow(true); + tele_period = tele_period_save; + ResponseJsonEnd(); + MqttPublishTeleSensor(); + Energy.power_delta = false; +} +#endif + +void EnergyEverySecond(void) +{ + + if (global_update) { + if (power && (global_temperature != 9999) && (global_temperature > Settings.param[P_OVER_TEMP])) { + SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); + } + } + + + uint32_t data_valid = Energy.phase_count; + for (uint32_t i = 0; i < Energy.phase_count; i++) { + if (Energy.data_valid[i] <= ENERGY_WATCHDOG) { + Energy.data_valid[i]++; + if (Energy.data_valid[i] > ENERGY_WATCHDOG) { + + Energy.voltage[i] = 0; + Energy.current[i] = 0; + Energy.active_power[i] = 0; + if (!isnan(Energy.apparent_power[i])) { Energy.apparent_power[i] = 0; } + if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; } + if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; } + if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; } + + data_valid--; + } + } + } + if (!data_valid) { + if (!isnan(Energy.export_active)) { Energy.export_active = 0; } + Energy.start_energy = 0; + + XnrgCall(FUNC_ENERGY_RESET); + } + +#ifdef USE_ENERGY_MARGIN_DETECTION + EnergyMarginCheck(); +#endif +} + + + + + +void EnergyCommandCalResponse(uint32_t nvalue) +{ + snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); + ResponseCmndNumber(nvalue); +} + +void CmndEnergyReset(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { + char *p; + unsigned long lnum = strtoul(XdrvMailbox.data, &p, 10); + if (p != XdrvMailbox.data) { + switch (XdrvMailbox.index) { + case 1: + + Energy.kWhtoday_offset = lnum *100; + Energy.kWhtoday = 0; + Energy.kWhtoday_delta = 0; + Energy.start_energy = 0; + Energy.period = Energy.kWhtoday_offset; + Settings.energy_kWhtoday = Energy.kWhtoday_offset; + RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset; + Energy.daily = (float)Energy.kWhtoday_offset / 100000; + if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) { + Settings.energy_kWhtotal_time = LocalTime(); + } + break; + case 2: + + Settings.energy_kWhyesterday = lnum *100; + break; + case 3: + + RtcSettings.energy_kWhtotal = lnum *100; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + + Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); + RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); + break; + } + } + } + else if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { + uint32_t values[2] = { 0 }; + uint32_t position = ParseParameters(2, values); + values[0] *= 100; + values[1] *= 100; + + switch (XdrvMailbox.index) + { + case 4: + + if (position > 0) { + RtcSettings.energy_usage.usage1_kWhtotal = values[0]; + } + if (position > 1) { + RtcSettings.energy_usage.usage2_kWhtotal = values[1]; + } + Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; + Settings.energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal; + break; + case 5: + + if (position > 0) { + RtcSettings.energy_usage.return1_kWhtotal = values[0]; + } + if (position > 1) { + RtcSettings.energy_usage.return2_kWhtotal = values[1]; + } + Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal; + Settings.energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal; + break; + } + } + + Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; + + char energy_total_chr[FLOATSZ]; + dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); + char energy_daily_chr[FLOATSZ]; + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); + char energy_yesterday_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + + char energy_usage1_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage1_chr); + char energy_usage2_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage2_chr); + char energy_return1_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return1_chr); + char energy_return2_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return2_chr); + + Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s,\"" D_JSON_USAGE "\":[%s,%s],\"" D_JSON_EXPORT "\":[%s,%s]}}"), + XdrvMailbox.command, energy_total_chr, energy_yesterday_chr, energy_daily_chr, energy_usage1_chr, energy_usage2_chr, energy_return1_chr, energy_return2_chr); +} + +void CmndTariff(void) +{ + + + + + + + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + uint32_t tariff = XdrvMailbox.index -1; + uint32_t time_type = 0; + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + while ((str != nullptr) && (time_type < 2)) { + char *q; + uint32_t value = strtol(str, &q, 10); + Settings.tariff[tariff][time_type] = value; + if (value < 24) { + Settings.tariff[tariff][time_type] *= 60; + char *minute = strtok_r(nullptr, ":", &q); + if (minute) { + value = strtol(minute, nullptr, 10); + if (value > 59) { + value = 59; + } + Settings.tariff[tariff][time_type] += value; + } + } + if (Settings.tariff[tariff][time_type] > 1439) { + Settings.tariff[tariff][time_type] = 1439; + } + str = strtok_r(nullptr, ", ", &p); + time_type++; + } + } + else if (XdrvMailbox.index == 9) { + Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; + } + Response_P(PSTR("{\"%s\":{\"Off-Peak\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Standard\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Weekend\":\"%s\"}}"), + XdrvMailbox.command, + GetMinuteTime(Settings.tariff[0][0]).c_str(),GetMinuteTime(Settings.tariff[0][1]).c_str(), + GetMinuteTime(Settings.tariff[1][0]).c_str(),GetMinuteTime(Settings.tariff[1][1]).c_str(), + GetStateText(Settings.flag3.energy_weekend)); +} + +void CmndPowerCal(void) +{ + Energy.command_code = CMND_POWERCAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_power_calibration = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_power_calibration); + } +} + +void CmndVoltageCal(void) +{ + Energy.command_code = CMND_VOLTAGECAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_voltage_calibration = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_voltage_calibration); + } +} + +void CmndCurrentCal(void) +{ + Energy.command_code = CMND_CURRENTCAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_current_calibration = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_current_calibration); + } +} + +void CmndPowerSet(void) +{ + Energy.command_code = CMND_POWERSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_power_calibration); + } +} + +void CmndVoltageSet(void) +{ + Energy.command_code = CMND_VOLTAGESET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_voltage_calibration); + } +} + +void CmndCurrentSet(void) +{ + Energy.command_code = CMND_CURRENTSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_current_calibration); + } +} + +void CmndFrequencySet(void) +{ + Energy.command_code = CMND_FREQUENCYSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_frequency_calibration); + } +} + +void CmndModuleAddress(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) { + Energy.command_code = CMND_MODULEADDRESS; + if (XnrgCall(FUNC_COMMAND)) { + ResponseCmndDone(); + } + } +} + +#ifdef USE_ENERGY_MARGIN_DETECTION +void CmndPowerDelta(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { + Settings.energy_power_delta = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_power_delta); +} + +void CmndPowerLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_min_power = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_power); +} + +void CmndPowerHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power); +} + +void CmndVoltageLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { + Settings.energy_min_voltage = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_voltage); +} + +void CmndVoltageHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { + Settings.energy_max_voltage = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_voltage); +} + +void CmndCurrentLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { + Settings.energy_min_current = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_current); +} + +void CmndCurrentHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { + Settings.energy_max_current = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_current); +} + +#ifdef USE_ENERGY_POWER_LIMIT +void CmndMaxPower(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit); +} + +void CmndMaxPowerHold(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit_hold); +} + +void CmndMaxPowerWindow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit_window); +} + +void CmndSafePower(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_safe_limit = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit); +} + +void CmndSafePowerHold(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold); +} + +void CmndSafePowerWindow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) { + Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit_window); +} + +void CmndMaxEnergy(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_energy = XdrvMailbox.payload; + Energy.max_energy_state = 3; + } + ResponseCmndNumber(Settings.energy_max_energy); +} + +void CmndMaxEnergyStart(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { + Settings.energy_max_energy_start = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_energy_start); +} +#endif +#endif + +void EnergySnsInit(void) +{ + XnrgCall(FUNC_INIT); + + if (energy_flg) { + if (RtcSettingsValid()) { + Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; + } + else if (RtcTime.day_of_year == Settings.energy_kWhdoy) { + Energy.kWhtoday_offset = Settings.energy_kWhtoday; + } + else { + Energy.kWhtoday_offset = 0; + } + Energy.kWhtoday = 0; + Energy.kWhtoday_delta = 0; + Energy.period = Energy.kWhtoday_offset; + EnergyUpdateToday(); + ticker_energy.attach_ms(200, Energy200ms); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_SNS1[] PROGMEM = + "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" + "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" + "{s}" D_POWER_FACTOR "{m}%s{e}"; + +const char HTTP_ENERGY_SNS2[] PROGMEM = + "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; + +const char HTTP_ENERGY_SNS3[] PROGMEM = + "{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; +#endif + +char* EnergyFormatIndex(char* result, char* input, bool json, uint32_t index, bool single = false) +{ + char layout[16]; + GetTextIndexed(layout, sizeof(layout), (index -1) + (3 * json), kEnergyPhases); + switch (index) { + case 2: + snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ); + break; + case 3: + snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ, input + FLOATSZ + FLOATSZ); + break; + default: + snprintf_P(result, FLOATSZ *3, input); + } + return result; +} + +char* EnergyFormat(char* result, char* input, bool json, bool single = false) +{ + uint8_t index = (single) ? 1 : Energy.phase_count; + return EnergyFormatIndex(result, input, json, index, single); +} + +void EnergyShow(bool json) +{ + for (uint32_t i = 0; i < Energy.phase_count; i++) { + if (Energy.voltage_common) { + Energy.voltage[i] = Energy.voltage[0]; + } + } + + float power_factor_knx = Energy.power_factor[0]; + + char apparent_power_chr[Energy.phase_count][FLOATSZ]; + char reactive_power_chr[Energy.phase_count][FLOATSZ]; + char power_factor_chr[Energy.phase_count][FLOATSZ]; + char frequency_chr[Energy.phase_count][FLOATSZ]; + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + for (uint32_t i = 0; i < Energy.phase_count; i++) { + float apparent_power = Energy.apparent_power[i]; + if (isnan(apparent_power)) { + apparent_power = Energy.voltage[i] * Energy.current[i]; + } + if (apparent_power < Energy.active_power[i]) { + Energy.active_power[i] = apparent_power; + } + + float power_factor = Energy.power_factor[i]; + if (isnan(power_factor)) { + power_factor = (Energy.active_power[i] && apparent_power) ? Energy.active_power[i] / apparent_power : 0; + if (power_factor > 1) { + power_factor = 1; + } + } + if (0 == i) { power_factor_knx = power_factor; } + + float reactive_power = Energy.reactive_power[i]; + if (isnan(reactive_power)) { + reactive_power = 0; + uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(Energy.active_power[i] * 100)) / 10; + if ((Energy.current[i] > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { + + + reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(Energy.active_power[i] * Energy.active_power[i] * 100))) / 10; + } + } + + dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr[i]); + dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr[i]); + dtostrfd(power_factor, 2, power_factor_chr[i]); + } + } + for (uint32_t i = 0; i < Energy.phase_count; i++) { + float frequency = Energy.frequency[i]; + if (isnan(Energy.frequency[i])) { + frequency = 0; + } + dtostrfd(frequency, Settings.flag2.frequency_resolution, frequency_chr[i]); + } + } + + char voltage_chr[Energy.phase_count][FLOATSZ]; + char current_chr[Energy.phase_count][FLOATSZ]; + char active_power_chr[Energy.phase_count][FLOATSZ]; + for (uint32_t i = 0; i < Energy.phase_count; i++) { + dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]); + dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]); + dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]); + } + + char energy_daily_chr[FLOATSZ]; + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); + char energy_yesterday_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + + char energy_total_chr[3][FLOATSZ]; + dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr[0]); + char export_active_chr[3][FLOATSZ]; + dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]); + uint8_t energy_total_fields = 1; + + if (Settings.tariff[0][0] != Settings.tariff[1][0]) { + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[2]); + energy_total_fields = 3; + } + + char value_chr[FLOATSZ *3]; + char value2_chr[FLOATSZ *3]; + char value3_chr[FLOATSZ *3]; + + if (json) { + bool show_energy_period = (0 == tele_period); + + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), + GetDateAndTime(DT_ENERGY).c_str(), + EnergyFormatIndex(value_chr, energy_total_chr[0], json, energy_total_fields), + energy_yesterday_chr, + energy_daily_chr); + + if (!isnan(Energy.export_active)) { + ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), + EnergyFormatIndex(value_chr, export_active_chr[0], json, energy_total_fields)); + } + + if (show_energy_period) { + float energy = 0; + if (Energy.period) { + energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100; + } + Energy.period = RtcSettings.energy_kWhtoday; + char energy_period_chr[FLOATSZ]; + dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); + ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); + } + ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"), + EnergyFormat(value_chr, active_power_chr[0], json)); + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"), + EnergyFormat(value_chr, apparent_power_chr[0], json), + EnergyFormat(value2_chr, reactive_power_chr[0], json), + EnergyFormat(value3_chr, power_factor_chr[0], json)); + } + if (!isnan(Energy.frequency[0])) { + ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), + EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); + } + } + if (Energy.voltage_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), + EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); + } + if (Energy.current_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), + EnergyFormat(value_chr, current_chr[0], json)); + } + XnrgCall(FUNC_JSON_APPEND); + ResponseJsonEnd(); + +#ifdef USE_DOMOTICZ + if (show_energy_period) { + dtostrfd(Energy.total * 1000, 1, energy_total_chr[0]); + DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr[0]); + + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_total_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_total_chr[2]); + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, export_active_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, export_active_chr[2]); + DomoticzSensorP1SmartMeter(energy_total_chr[1], energy_total_chr[2], export_active_chr[1], export_active_chr[2], (int)Energy.active_power[0]); + + if (Energy.voltage_available) { + DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); + } + if (Energy.current_available) { + DomoticzSensor(DZ_CURRENT, current_chr[0]); + } + } +#endif +#ifdef USE_KNX + if (show_energy_period) { + if (Energy.voltage_available) { + KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage[0]); + } + if (Energy.current_available) { + KnxSensor(KNX_ENERGY_CURRENT, Energy.current[0]); + } + KnxSensor(KNX_ENERGY_POWER, Energy.active_power[0]); + if (!Energy.type_dc) { + KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor_knx); + } + KnxSensor(KNX_ENERGY_DAILY, Energy.daily); + KnxSensor(KNX_ENERGY_TOTAL, Energy.total); + KnxSensor(KNX_ENERGY_START, Energy.start_energy); + } +#endif +#ifdef USE_WEBSERVER + } else { + if (Energy.voltage_available) { + WSContentSend_PD(HTTP_SNS_VOLTAGE, EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); + } + if (Energy.current_available) { + WSContentSend_PD(HTTP_SNS_CURRENT, EnergyFormat(value_chr, current_chr[0], json)); + } + WSContentSend_PD(HTTP_SNS_POWER, EnergyFormat(value_chr, active_power_chr[0], json)); + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + WSContentSend_PD(HTTP_ENERGY_SNS1, EnergyFormat(value_chr, apparent_power_chr[0], json), + EnergyFormat(value2_chr, reactive_power_chr[0], json), + EnergyFormat(value3_chr, power_factor_chr[0], json)); + } + if (!isnan(Energy.frequency[0])) { + WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), + EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); + } + } + WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]); + if (!isnan(Energy.export_active)) { + WSContentSend_PD(HTTP_ENERGY_SNS3, export_active_chr[0]); + } + + XnrgCall(FUNC_WEB_SENSOR); +#endif + } +} + + + + + +bool Xdrv03(uint8_t function) +{ + bool result = false; + + if (FUNC_PRE_INIT == function) { + energy_flg = ENERGY_NONE; + XnrgCall(FUNC_PRE_INIT); + } + else if (energy_flg) { + switch (function) { + case FUNC_LOOP: + XnrgCall(FUNC_LOOP); + break; + case FUNC_EVERY_250_MSECOND: + XnrgCall(FUNC_EVERY_250_MSECOND); + break; + case FUNC_SERIAL: + result = XnrgCall(FUNC_SERIAL); + break; +#ifdef USE_ENERGY_MARGIN_DETECTION + case FUNC_SET_POWER: + Energy.power_steady_counter = 2; + break; +#endif + case FUNC_COMMAND: + result = DecodeCommand(kEnergyCommands, EnergyCommand); + break; + } + } + return result; +} + +bool Xsns03(uint8_t function) +{ + bool result = false; + + if (energy_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + EnergyEverySecond(); + break; + case FUNC_JSON_APPEND: + EnergyShow(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + EnergyShow(false); + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + EnergySaveState(); + break; + case FUNC_INIT: + EnergySnsInit(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" +#ifdef USE_LIGHT +# 124 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" +#define XDRV_04 4 + + +enum LightSchemes { LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX }; + +const uint8_t LIGHT_COLOR_SIZE = 25; + +const char kLightCommands[] PROGMEM = "|" + D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" + D_CMND_RGBWWTABLE "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" + D_CMND_WHITE "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; + +void (* const LightCommand[])(void) PROGMEM = { + &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndDimmerRange, &CmndLedTable, &CmndFade, + &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, + &CmndWhite, &CmndChannel, &CmndHsbColor, &CmndUndocA }; + + +enum LightColorModes { + LCM_RGB = 1, LCM_CT = 2, LCM_BOTH = 3 }; + +struct LRgbColor { + uint8_t R, G, B; +}; +const uint8_t MAX_FIXED_COLOR = 12; +const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = + { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; + +struct LWColor { + uint8_t W; +}; +const uint8_t MAX_FIXED_WHITE = 4; +const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; + +struct LCwColor { + uint8_t C, W; +}; +const uint8_t MAX_FIXED_COLD_WARM = 4; +const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; + + +const uint16_t CT_MIN = 153; +const uint16_t CT_MAX = 500; + +const uint16_t CT_MIN_ALEXA = 200; +const uint16_t CT_MAX_ALEXA = 380; + + + + + + +typedef struct gamma_table_t { + uint16_t to_src; + uint16_t to_gamma; +} gamma_table_t; + +const gamma_table_t gamma_table[] = { + { 1, 1 }, + { 4, 1 }, + { 209, 13 }, + { 312, 41 }, + { 457, 106 }, + { 626, 261 }, + { 762, 450 }, + { 895, 703 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } +}; + + +const gamma_table_t gamma_table_fast[] = { + { 384, 192 }, + { 768, 576 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } +}; +# 248 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" +struct LIGHT { + uint32_t strip_timer_counter = 0; + power_t power = 0; + + uint16_t wakeup_counter = 0; + + uint8_t entry_color[LST_MAX]; + uint8_t current_color[LST_MAX]; + uint8_t new_color[LST_MAX]; + uint8_t last_color[LST_MAX]; + uint8_t color_remap[LST_MAX]; + + uint8_t wheel = 0; + uint8_t random = 0; + uint8_t subtype = 0; + uint8_t device = 0; + uint8_t old_power = 1; + uint8_t wakeup_active = 0; + uint8_t wakeup_dimmer = 0; + uint8_t fixed_color_index = 1; + uint8_t pwm_offset = 0; + uint8_t max_scheme = LS_MAX -1; + + bool update = true; + bool pwm_multi_channels = false; + + bool fade_initialized = false; + bool fade_running = false; + uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; + uint16_t fade_cur_10[LST_MAX]; + uint16_t fade_end_10[LST_MAX]; + uint16_t fade_duration = 0; + uint32_t fade_start = 0; +} Light; + +power_t LightPower(void) +{ + return Light.power; +} + + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +power_t LightPowerIRAM(void) ICACHE_RAM_ATTR; +#endif + +power_t LightPowerIRAM(void) +{ + return Light.power; +} + +uint8_t LightDevice(void) +{ + return Light.device; +} + +static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) { + return (a < b && a < c) ? a : (b < c) ? b : c; +} +# 344 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" +class LightStateClass { + private: + uint16_t _hue = 0; + uint8_t _sat = 255; + uint8_t _briRGB = 255; + + uint8_t _r = 255; + uint8_t _g = 255; + uint8_t _b = 255; + + uint8_t _subtype = 0; + uint16_t _ct = CT_MIN; + uint8_t _wc = 255; + uint8_t _ww = 0; + uint8_t _briCT = 255; + + uint8_t _color_mode = LCM_RGB; + + + + + + uint16_t _ct_min_range = CT_MIN; + uint16_t _ct_max_range = CT_MAX; + + public: + LightStateClass() { + + } + + void setSubType(uint8_t sub_type) { + _subtype = sub_type; + } +# 386 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" + uint8_t setColorMode(uint8_t cm) { + uint8_t prev_cm = _color_mode; + if (cm < LCM_RGB) { cm = LCM_RGB; } + if (cm > LCM_BOTH) { cm = LCM_BOTH; } + uint8_t maxbri = (_briRGB >= _briCT) ? _briRGB : _briCT; + + switch (_subtype) { + case LST_COLDWARM: + _color_mode = LCM_CT; + break; + + case LST_NONE: + case LST_SINGLE: + case LST_RGB: + default: + _color_mode = LCM_RGB; + break; + + case LST_RGBW: + case LST_RGBCW: + _color_mode = cm; + break; + } + if (LCM_RGB == _color_mode) { + _briCT = 0; + if (0 == _briRGB) { _briRGB = maxbri; } + } + if (LCM_CT == _color_mode) { + _briRGB = 0; + if (0 == _briCT) { _briCT = maxbri; } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setColorMode prev_cm (%d) req_cm (%d) new_cm (%d)", prev_cm, cm, _color_mode); +#endif + return prev_cm; + } + + inline uint8_t getColorMode() { + return _color_mode; + } + + void addRGBMode() { + setColorMode(_color_mode | LCM_RGB); + } + void addCTMode() { + setColorMode(_color_mode | LCM_CT); + } + + + void getRGB(uint8_t *r, uint8_t *g, uint8_t *b) { + if (r) { *r = _r; } + if (g) { *g = _g; } + if (b) { *b = _b; } + } + + + + void getCW(uint8_t *rc, uint8_t *rw) { + if (rc) { *rc = _wc; } + if (rw) { *rw = _ww; } + } + + + void getActualRGBCW(uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *c, uint8_t *w) { + bool rgb_channels_on = _color_mode & LCM_RGB; + bool ct_channels_on = _color_mode & LCM_CT; + + if (r) { *r = rgb_channels_on ? changeUIntScale(_r, 0, 255, 0, _briRGB) : 0; } + if (g) { *g = rgb_channels_on ? changeUIntScale(_g, 0, 255, 0, _briRGB) : 0; } + if (b) { *b = rgb_channels_on ? changeUIntScale(_b, 0, 255, 0, _briRGB) : 0; } + + if (c) { *c = ct_channels_on ? changeUIntScale(_wc, 0, 255, 0, _briCT) : 0; } + if (w) { *w = ct_channels_on ? changeUIntScale(_ww, 0, 255, 0, _briCT) : 0; } + } + + uint8_t getChannels(uint8_t *channels) { + getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); + } + + void getChannelsRaw(uint8_t *channels) { + channels[0] = _r; + channels[1] = _g; + channels[2] = _b; + channels[3] = _wc; + channels[4] = _ww; + } + + void getHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { + if (hue) { *hue = _hue; } + if (sat) { *sat = _sat; } + if (bri) { *bri = _briRGB; } + } + + + uint8_t getBri(void) { + + return (_briRGB >= _briCT) ? _briRGB : _briCT; + } + + + inline uint8_t getBriCT() { + return _briCT; + } + + static inline uint8_t DimmerToBri(uint8_t dimmer) { + return changeUIntScale(dimmer, 0, 100, 0, 255); + } + static uint8_t BriToDimmer(uint8_t bri) { + uint8_t dimmer = changeUIntScale(bri, 0, 255, 0, 100); + + if ((dimmer == 0) && (bri > 0)) { dimmer = 1; } + return dimmer; + } + + uint8_t getDimmer(uint32_t mode = 0) { + uint8_t bri; + switch (mode) { + case 1: + bri = getBriRGB(); + break; + case 2: + bri = getBriCT(); + break; + default: + bri = getBri(); + break; + } + return BriToDimmer(bri); + } + + inline uint16_t getCT() const { + return _ct; + } + + + uint16_t getCT10bits() const { + return changeUIntScale(_ct, _ct_min_range, _ct_max_range, 0, 1023); + } + + inline void setCTRange(uint16_t ct_min_range, uint16_t ct_max_range) { + _ct_min_range = ct_min_range; + _ct_max_range = ct_max_range; + } + + inline void getCTRange(uint16_t *ct_min_range, uint16_t *ct_max_range) const { + if (ct_min_range) { *ct_min_range = _ct_min_range; } + if (ct_max_range) { *ct_max_range = _ct_max_range; } + } + + + void getXY(float *x, float *y) { + RgbToXy(_r, _g, _b, x, y); + } + + + + void setBri(uint8_t bri) { + setBriRGB(_color_mode & LCM_RGB ? bri : 0); + setBriCT(_color_mode & LCM_CT ? bri : 0); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setBri RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + } + + + uint8_t setBriRGB(uint8_t bri_rgb) { + uint8_t prev_bri = _briRGB; + _briRGB = bri_rgb; + if (bri_rgb > 0) { addRGBMode(); } + return prev_bri; + } + + + uint8_t setBriCT(uint8_t bri_ct) { + uint8_t prev_bri = _briCT; + _briCT = bri_ct; + if (bri_ct > 0) { addCTMode(); } + return prev_bri; + } + + inline uint8_t getBriRGB() { + return _briRGB; + } + + void setDimmer(uint8_t dimmer) { + setBri(DimmerToBri(dimmer)); + } + + void setCT(uint16_t ct) { + if (0 == ct) { + + setColorMode(LCM_RGB); + } else { + ct = (ct < CT_MIN ? CT_MIN : (ct > CT_MAX ? CT_MAX : ct)); + _ww = changeUIntScale(ct, _ct_min_range, _ct_max_range, 0, 255); + _wc = 255 - _ww; + _ct = ct; + addCTMode(); + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCT RGB raw (%d %d %d) HS (%d %d) briRGB (%d) briCT (%d) CT (%d)", _r, _g, _b, _hue, _sat, _briRGB, _briCT, _ct); +#endif + } +# 604 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" + void setCW(uint8_t c, uint8_t w, bool free_range = false) { + uint16_t max = (w > c) ? w : c; + uint16_t sum = c + w; + + if (0 == max) { + _briCT = 0; + setColorMode(LCM_RGB); + } else { + if (!free_range) { + + _ww = changeUIntScale(w, 0, sum, 0, 255); + _wc = 255 - _ww; + } else { + _ww = changeUIntScale(w, 0, max, 0, 255); + _wc = changeUIntScale(c, 0, max, 0, 255); + } + _ct = changeUIntScale(w, 0, sum, _ct_min_range, _ct_max_range); + addCTMode(); + if (_color_mode & LCM_CT) { _briCT = free_range ? max : (sum > 255 ? 255 : sum); } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCW CW (%d %d) CT (%d) briCT (%d)", c, w, _ct, _briCT); +#endif + } + + + uint8_t setRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { + uint16_t hue; + uint8_t sat; +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB input (%d %d %d)", r, g, b); +#endif + + uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; + + if (0 == max) { + r = g = b = 255; + setColorMode(LCM_CT); + } else { + if (255 > max) { + + r = changeUIntScale(r, 0, max, 0, 255); + g = changeUIntScale(g, 0, max, 0, 255); + b = changeUIntScale(b, 0, max, 0, 255); + } + addRGBMode(); + } + if (!keep_bri) { + _briRGB = (_color_mode & LCM_RGB) ? max : 0; + } + + RgbToHsb(r, g, b, &hue, &sat, nullptr); + _r = r; + _g = g; + _b = b; + _hue = hue; + _sat = sat; +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + return max; + } + + void setHS(uint16_t hue, uint8_t sat) { + uint8_t r, g, b; + HsToRgb(hue, sat, &r, &g, &b); + _r = r; + _g = g; + _b = b; + _hue = hue; + _sat = sat; + addRGBMode(); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS HS (%d %d) rgb (%d %d %d)", hue, sat, r, g, b); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + } + + + + void setChannelsRaw(uint8_t *channels) { + _r = channels[0]; + _g = channels[1]; + _b = channels[2]; + _wc = channels[3]; + _ww = channels[4]; +} + + + + + void setChannels(uint8_t *channels) { + setRGB(channels[0], channels[1], channels[2]); + setCW(channels[3], channels[4], true); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels (%d %d %d %d %d)", + channels[0], channels[1], channels[2], channels[3], channels[4]); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels CT (%d) briRGB (%d) briCT (%d)", _ct, _briRGB, _briCT); +#endif + } + + + static void RgbToHsb(uint8_t r, uint8_t g, uint8_t b, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri); + static void HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); + static void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y); + static void XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb); + +}; +# 720 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" +void LightStateClass::RgbToHsb(uint8_t ir, uint8_t ig, uint8_t ib, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri) { + uint32_t r = ir; + uint32_t g = ig; + uint32_t b = ib; + uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; + uint32_t min = (r < g && r < b) ? r : (g < b) ? g : b; + uint32_t d = max - min; + + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = max; + + if (d != 0) { + sat = changeUIntScale(d, 0, max, 0, 255); + if (r == max) { + hue = (g > b) ? changeUIntScale(g-b,0,d,0,60) : 360 - changeUIntScale(b-g,0,d,0,60); + } else if (g == max) { + hue = (b > r) ? 120 + changeUIntScale(b-r,0,d,0,60) : 120 - changeUIntScale(r-b,0,d,0,60); + } else { + hue = (r > g) ? 240 + changeUIntScale(r-g,0,d,0,60) : 240 - changeUIntScale(g-r,0,d,0,60); + } + hue = hue % 360; + } + + if (r_hue) *r_hue = hue; + if (r_sat) *r_sat = sat; + if (r_bri) *r_bri = bri; + +} + +void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { + uint32_t r = 255; + uint32_t g = 255; + uint32_t b = 255; + + hue = hue % 360; + + if (sat > 0) { + uint32_t i = hue / 60; + uint32_t f = hue % 60; + uint32_t q = 255 - changeUIntScale(f, 0, 60, 0, sat); + uint32_t p = 255 - sat; + uint32_t t = 255 - changeUIntScale(60 - f, 0, 60, 0, sat); + + switch (i) { + case 0: + + g = t; + b = p; + break; + case 1: + r = q; + + b = p; + break; + case 2: + r = p; + + b = t; + break; + case 3: + r = p; + g = q; + + break; + case 4: + r = t; + g = p; + + break; + default: + + g = p; + b = q; + break; + } + } + if (r_r) *r_r = r; + if (r_g) *r_g = g; + if (r_b) *r_b = b; +} + +#define POW FastPrecisePowf + +void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) { + float x = 0.31271f; + float y = 0.32902f; + + if (i_r + i_b + i_g > 0) { + float r = (float)i_r / 255.0f; + float g = (float)i_g / 255.0f; + float b = (float)i_b / 255.0f; + + + r = (r > 0.04045f) ? POW((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f); + g = (g > 0.04045f) ? POW((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f); + b = (b > 0.04045f) ? POW((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f); + + + + float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + float Z = r * 0.000000f + g * 0.053077f + b * 1.035763f; + + x = X / (X + Y + Z); + y = Y / (X + Y + Z); + + } + if (r_x) *r_x = x; + if (r_y) *r_y = y; +} + +void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb) +{ + x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x)); + y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y)); + float z = 1.0f - x - y; + + float X = x / y; + float Z = z / y; + + + + float r = X * 3.2406f - 1.5372f - Z * 0.4986f; + float g = -X * 0.9689f + 1.8758f + Z * 0.0415f; + float b = X * 0.0557f - 0.2040f + Z * 1.0570f; + float max = (r > g && r > b) ? r : (g > b) ? g : b; + r = r / max; + g = g / max; + b = b / max; + r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * POW(r, (1.0f / 2.4f)) - 0.055f; + g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * POW(g, (1.0f / 2.4f)) - 0.055f; + b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * POW(b, (1.0f / 2.4f)) - 0.055f; + + + + + + int32_t ir = r * 255.0f + 0.5f; + int32_t ig = g * 255.0f + 0.5f; + int32_t ib = b * 255.0f + 0.5f; + if (rr) { *rr = (ir > 255 ? 255: (ir < 0 ? 0 : ir)); } + if (rg) { *rg = (ig > 255 ? 255: (ig < 0 ? 0 : ig)); } + if (rb) { *rb = (ib > 255 ? 255: (ib < 0 ? 0 : ib)); } +} + +class LightControllerClass { +private: + LightStateClass *_state; + + + bool _ct_rgb_linked = true; + bool _pwm_multi_channels = false; + +public: + LightControllerClass(LightStateClass& state) { + _state = &state; + } + + void setSubType(uint8_t sub_type) { + _state->setSubType(sub_type); + } + + inline bool setCTRGBLinked(bool ct_rgb_linked) { + bool prev = _ct_rgb_linked; + if (_pwm_multi_channels) { + _ct_rgb_linked = false; + } else { + _ct_rgb_linked = ct_rgb_linked; + } + return prev; + } + + void setAlexaCTRange(bool alexa_ct_range) { + + if (alexa_ct_range) { + _state->setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA); + } else { + _state->setCTRange(CT_MIN, CT_MAX); + } + } + + inline bool isCTRGBLinked() { + return _ct_rgb_linked; + } + + inline bool setPWMMultiChannel(bool pwm_multi_channels) { + bool prev = _pwm_multi_channels; + _pwm_multi_channels = pwm_multi_channels; + if (pwm_multi_channels) setCTRGBLinked(false); + return prev; + } + + inline bool isPWMMultiChannel(void) { + return _pwm_multi_channels; + } + +#ifdef DEBUG_LIGHT + void debugLogs() { + uint8_t r,g,b,c,w; + _state->getActualRGBCW(&r,&g,&b,&c,&w); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs rgb (%d %d %d) cw (%d %d)", + r, g, b, c, w); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs lightCurrent (%d %d %d %d %d)", + Light.current_color[0], Light.current_color[1], Light.current_color[2], + Light.current_color[3], Light.current_color[4]); + } +#endif + + void loadSettings() { +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings Settings.light_color (%d %d %d %d %d - %d)", + Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], + Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", + light_type, Light.subtype); +#endif + if (_pwm_multi_channels) { + _state->setChannelsRaw(Settings.light_color); + } else { + + _state->setCW(Settings.light_color[3], Settings.light_color[4], true); + _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); + + + + uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); + if (Settings.light_color[0] + Settings.light_color[1] + Settings.light_color[2] > 0) { + + + if ( (DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) && + (DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) { + _state->setColorMode(LCM_RGB); + } + _state->setBriRGB(bri); + } else { + _state->setBriCT(bri); + } + } + } + + void changeCTB(uint16_t new_ct, uint8_t briCT) { + + + + + + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBW > Light.subtype)) { + return; + } + _state->setCT(new_ct); + _state->setBriCT(briCT); + if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } + saveSettings(); + calcLevels(); + + } + + void changeDimmer(uint8_t dimmer, uint32_t mode = 0) { + uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); + switch (mode) { + case 1: + changeBriRGB(bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + break; + case 2: + changeBriCT(bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } + break; + default: + changeBri(bri); + break; + } + } + + void changeBri(uint8_t bri) { + _state->setBri(bri); + saveSettings(); + calcLevels(); + } + + void changeBriRGB(uint8_t bri) { + _state->setBriRGB(bri); + saveSettings(); + calcLevels(); + } + + void changeBriCT(uint8_t bri) { + _state->setBriCT(bri); + saveSettings(); + calcLevels(); + } + + void changeRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { + _state->setRGB(r, g, b, keep_bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + saveSettings(); + calcLevels(); + } + + + + void calcLevels(uint8_t *current_color = nullptr) { + uint8_t r,g,b,c,w,briRGB,briCT; + if (current_color == nullptr) { current_color = Light.current_color; } + + if (_pwm_multi_channels) { + _state->getChannelsRaw(current_color); + return; + } + + _state->getActualRGBCW(&r,&g,&b,&c,&w); + briRGB = _state->getBriRGB(); + briCT = _state->getBriCT(); + + current_color[0] = current_color[1] = current_color[2] = 0; + current_color[3] = current_color[4] = 0; + switch (Light.subtype) { + case LST_NONE: + current_color[0] = 255; + break; + case LST_SINGLE: + current_color[0] = briRGB; + break; + case LST_COLDWARM: + current_color[0] = c; + current_color[1] = w; + break; + case LST_RGBW: + case LST_RGBCW: + if (LST_RGBCW == Light.subtype) { + current_color[3] = c; + current_color[4] = w; + } else { + current_color[3] = briCT; + } + + case LST_RGB: + current_color[0] = r; + current_color[1] = g; + current_color[2] = b; + break; + } + } + + void changeHSB(uint16_t hue, uint8_t sat, uint8_t briRGB) { + _state->setHS(hue, sat); + _state->setBriRGB(briRGB); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + saveSettings(); + calcLevels(); + } + + + void saveSettings() { + if (Light.pwm_multi_channels) { + + _state->getChannelsRaw(Settings.light_color); + Settings.light_dimmer = 100; + } else { + uint8_t cm = _state->getColorMode(); + + memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); + if (LCM_RGB & cm) { + _state->getRGB(&Settings.light_color[0], &Settings.light_color[1], &Settings.light_color[2]); + Settings.light_dimmer = _state->BriToDimmer(_state->getBriRGB()); + + if (LCM_BOTH == cm) { + + _state->getActualRGBCW(nullptr, nullptr, nullptr, &Settings.light_color[3], &Settings.light_color[4]); + } + } else if (LCM_CT == cm) { + _state->getCW(&Settings.light_color[3], &Settings.light_color[4]); + Settings.light_dimmer = _state->BriToDimmer(_state->getBriCT()); + } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::saveSettings Settings.light_color (%d %d %d %d %d - %d)", + Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], + Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); +#endif + } + + + + + void changeChannels(uint8_t *channels) { + if (Light.pwm_multi_channels) { + _state->setChannelsRaw(channels); + } else if (LST_COLDWARM == Light.subtype) { + + uint8_t remapped_channels[5] = {0,0,0,channels[0],channels[1]}; + _state->setChannels(remapped_channels); + } else { + _state->setChannels(channels); + } + + saveSettings(); + calcLevels(); + } +}; + + + +LightStateClass light_state = LightStateClass(); +LightControllerClass light_controller = LightControllerClass(light_state); + + + + + +uint16_t change8to10(uint8_t v) { + return changeUIntScale(v, 0, 255, 0, 1023); +} + +uint8_t change10to8(uint16_t v) { + return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); +} + + + + + +uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (v <= to_src) { + return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); + } + from_src = to_src; + from_gamma = to_gamma; + } +} + +uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (vg <= to_gamma) { + return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src); + } + from_src = to_src; + from_gamma = to_gamma; + } +} + + +uint16_t ledGamma10_10(uint16_t v) { + return ledGamma_internal(v, gamma_table); +} + +uint16_t ledGamma10(uint8_t v) { + return ledGamma10_10(change8to10(v)); +} + + +uint8_t ledGamma(uint8_t v) { + return change10to8(ledGamma10(v)); +} + + + +void LightPwmOffset(uint32_t offset) +{ + Light.pwm_offset = offset; +} + +bool LightModuleInit(void) +{ + light_type = LT_BASIC; + + if (Settings.flag.pwm_control) { + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 +i] < 99) { light_type++; } + } + } + + light_flg = 0; + if (XlgtCall(FUNC_MODULE_INIT)) { + + } + else if (SONOFF_BN == my_module_type) { + light_type = LT_PWM1; + } + else if (SONOFF_LED == my_module_type) { + if (!my_module.io[4]) { + pinMode(4, OUTPUT); + digitalWrite(4, LOW); + } + if (!my_module.io[5]) { + pinMode(5, OUTPUT); + digitalWrite(5, LOW); + } + if (!my_module.io[14]) { + pinMode(14, OUTPUT); + digitalWrite(14, LOW); + } + light_type = LT_PWM2; + } + + if (light_type > LT_BASIC) { + devices_present++; + } + + + if (Settings.flag3.pwm_multi_channels) { + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + if (0 == pwm_channels) { pwm_channels = 1; } + devices_present += pwm_channels - 1; + } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= (light_type & 7))) { + + devices_present++; + } + + return (light_type > LT_BASIC); +} + +void LightInit(void) +{ + Light.device = devices_present; + Light.subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; + + if (LST_RGBW <= Light.subtype) { + + + bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); + light_controller.setCTRGBLinked(ct_rgb_linked); + } + + if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) { + + light_controller.setPWMMultiChannel(true); + Light.device = devices_present - Light.subtype + 1; + } else if (!light_controller.isCTRGBLinked()) { + + Light.device--; + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", + Light.pwm_multi_channels, Light.subtype, Light.device, devices_present); +#endif + + light_controller.setSubType(Light.subtype); + light_controller.loadSettings(); + light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); + + if (LST_SINGLE == Light.subtype) { + Settings.light_color[0] = 255; + } + if (light_type < LT_PWM6) { + for (uint32_t i = 0; i < light_type; i++) { + Settings.pwm_value[i] = 0; + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + } + } + if (pin[GPIO_ARIRFRCV] < 99) { + if (pin[GPIO_ARIRFSEL] < 99) { + pinMode(pin[GPIO_ARIRFSEL], OUTPUT); + digitalWrite(pin[GPIO_ARIRFSEL], 1); + } + } + } + + uint32_t max_scheme = Light.max_scheme; + if (Light.subtype < LST_RGB) { + max_scheme = LS_POWER; + } + if ((LS_WAKEUP == Settings.light_scheme) || (Settings.light_scheme > max_scheme)) { + Settings.light_scheme = LS_POWER; + } + Light.power = 0; + Light.update = true; + Light.wakeup_active = 0; + + LightUpdateColorMapping(); +} + +void LightUpdateColorMapping(void) +{ + uint8_t param = Settings.param[P_RGB_REMAP] & 127; + if (param > 119){ param = 0; } + + uint8_t tmp[] = {0,1,2,3,4}; + Light.color_remap[0] = tmp[param / 24]; + for (uint32_t i = param / 24; i<4; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 24; + Light.color_remap[1] = tmp[(param / 6)]; + for (uint32_t i = param / 6; i<3; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 6; + Light.color_remap[2] = tmp[(param / 2)]; + for (uint32_t i = param / 2; i<2; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 2; + Light.color_remap[3] = tmp[param]; + Light.color_remap[4] = tmp[1-param]; + + Light.update = true; + +} + +uint8_t LightGetDimmer(uint8_t dimmer) { + return light_state.getDimmer(dimmer); +} + +void LightSetDimmer(uint8_t dimmer) { + light_controller.changeDimmer(dimmer); +} + +void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { + light_state.getHSB(hue, sat, bri); +} + +void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { + light_state.HsToRgb(hue, sat, r_r, r_g, r_b); +} + + +uint8_t LightGetBri(uint8_t device) { + uint8_t bri = 254; + if (Light.pwm_multi_channels) { + if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { + bri = Light.current_color[device - Light.device]; + } + } else if (light_controller.isCTRGBLinked()) { + if (device == Light.device) { + bri = light_state.getBri(); + } + } else { + if (device == Light.device) { + bri = light_state.getBriRGB(); + } else if (device == Light.device + 1) { + bri = light_state.getBriCT(); + } + } + return bri; +} + + +void LightSetBri(uint8_t device, uint8_t bri) { + if (Light.pwm_multi_channels) { + if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { + Light.current_color[device - Light.device] = bri; + light_controller.changeChannels(Light.current_color); + } + } else if (light_controller.isCTRGBLinked()) { + if (device == Light.device) { + light_controller.changeBri(bri); + } + } else { + if (device == Light.device) { + light_controller.changeBriRGB(bri); + } else if (device == Light.device + 1) { + light_controller.changeBriCT(bri); + } + } +} + +void LightSetColorTemp(uint16_t ct) +{ + + + + + + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { + return; + } + light_controller.changeCTB(ct, light_state.getBriCT()); +} + +uint16_t LightGetColorTemp(void) +{ + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { + return 0; + } + return (light_state.getColorMode() & LCM_CT) ? light_state.getCT() : 0; +} + +void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) +{ + + + + if (Settings.flag.light_signal) { + uint16_t signal = changeUIntScale(value, lo, hi, 0, 255); + + light_controller.changeRGB(signal, 255 - signal, 0, true); + Settings.light_scheme = 0; + if (0 == light_state.getBri()) { + light_controller.changeBri(50); + } + } +} + + +char* LightGetColor(char* scolor, boolean force_hex = false) +{ + light_controller.calcLevels(); + scolor[0] = '\0'; + for (uint32_t i = 0; i < Light.subtype; i++) { + if (!force_hex && Settings.flag.decimal_text) { + snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Light.current_color[i]); + } else { + snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%02X"), scolor, Light.current_color[i]); + } + } + return scolor; +} + +void LightPowerOn(void) +{ + if (light_state.getBri() && !(Light.power)) { + ExecuteCommandPower(Light.device, POWER_ON, SRC_LIGHT); + } +} + +void LightState(uint8_t append) +{ + char scolor[LIGHT_COLOR_SIZE]; + char scommand[33]; + bool unlinked = !light_controller.isCTRGBLinked() && (Light.subtype >= LST_RGBW); + + if (append) { + ResponseAppend_P(PSTR(",")); + } else { + Response_P(PSTR("{")); + } + if (!Light.pwm_multi_channels) { + if (unlinked) { + + ResponseAppend_P(PSTR("\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d" + ",\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d"), + Light.device, GetStateText(Light.power & 1), Light.device, light_state.getDimmer(1), + Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), Light.device + 1, light_state.getDimmer(2)); + } else { + GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1), + light_state.getDimmer()); + } + + + if (Light.subtype > LST_SINGLE) { + ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); + if (LST_RGB <= Light.subtype) { + uint16_t hue; + uint8_t sat, bri; + light_state.getHSB(&hue, &sat, &bri); + sat = changeUIntScale(sat, 0, 255, 0, 100); + bri = changeUIntScale(bri, 0, 255, 0, 100); + + ResponseAppend_P(PSTR(",\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), hue,sat,bri); + } + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { + ResponseAppend_P(PSTR(",\"" D_CMND_WHITE "\":%d"), light_state.getDimmer(2)); + } + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), light_state.getCT()); + } + + ResponseAppend_P(PSTR(",\"" D_CMND_CHANNEL "\":[" )); + for (uint32_t i = 0; i < Light.subtype; i++) { + uint8_t channel_raw = Light.current_color[i]; + uint8_t channel = changeUIntScale(channel_raw,0,255,0,100); + + if ((0 == channel) && (channel_raw > 0)) { channel = 1; } + ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), channel); + } + ResponseAppend_P(PSTR("]")); + } + + if (append) { + if (Light.subtype >= LST_RGB) { + ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); + } + if (Light.max_scheme > LS_MAX) { + ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width); + } + ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), + GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); + } + } else { + for (uint32_t i = 0; i < Light.subtype; i++) { + GetPowerDevice(scommand, Light.device + i, sizeof(scommand), 1); + uint32_t light_power_masked = Light.power & (1 << i); + light_power_masked = light_power_masked ? 1 : 0; + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_CHANNEL "%d\":%d,"), scommand, GetStateText(light_power_masked), Light.device + i, + changeUIntScale(Light.current_color[i], 0, 255, 0, 100)); + } + ResponseAppend_P(PSTR("\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); + } + + if (!append) { + ResponseJsonEnd(); + } +} + +void LightPreparePower(power_t channels = 0xFFFFFFFF) { +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); +#endif + + if (Light.pwm_multi_channels) { + for (uint32_t i = 0; i < Light.subtype; i++) { + if (bitRead(channels, i)) { + + if ((Light.current_color[i]) && (!bitRead(Light.power, i))) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device + i, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else { + + if ((0 == Light.current_color[i]) && bitRead(Light.power, i)) { + ExecuteCommandPower(Light.device + i, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } + #ifdef USE_DOMOTICZ + DomoticzUpdatePowerState(Light.device + i); + #endif + } + } + } else { + if (light_controller.isCTRGBLinked()) { + if (light_state.getBri() && !(Light.power)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBri() && Light.power) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } else { + + if (channels & 1) { + if (light_state.getBriRGB() && !(Light.power & 1)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBriRGB() && (Light.power & 1)) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } + + if (channels & 2) { + if (light_state.getBriCT() && !(Light.power & 2)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBriCT() && (Light.power & 2)) { + ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } + } +#ifdef USE_DOMOTICZ + DomoticzUpdatePowerState(Light.device); +#endif + } + + if (Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } + +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); +#endif + Light.power = power >> (Light.device - 1); + LightState(0); +} + +void LightCycleColor(int8_t direction) +{ + if (Light.strip_timer_counter % (Settings.light_speed * 2)) { + return; + } + + if (0 == direction) { + if (Light.random == Light.wheel) { + Light.random = random(255); + + uint8_t my_dir = (Light.random < Light.wheel -128) ? 1 : + (Light.random < Light.wheel ) ? 0 : + (Light.random > Light.wheel +128) ? 0 : 1; + Light.random = (Light.random & 0xFE) | my_dir; + + + } + + direction = (Light.random &0x01) ? 1 : -1; + } + Light.wheel += direction; + uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); + + + + uint8_t sat; + light_state.getHSB(nullptr, &sat, nullptr); + light_state.setHS(hue, sat); + light_controller.calcLevels(Light.new_color); +} + +void LightSetPower(void) +{ + + Light.old_power = Light.power; + + uint32_t mask = 1; + if (Light.pwm_multi_channels) { + mask = (1 << Light.subtype) - 1; + } else if (!light_controller.isCTRGBLinked()) { + mask = 3; + } + uint32_t shift = Light.device - 1; + + + + + + Light.power = (XdrvMailbox.index & (mask << shift)) >> shift; + if (Light.wakeup_active) { + Light.wakeup_active--; + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightSetPower XdrvMailbox.index=%d Light.old_power=%d Light.power=%d mask=%d shift=%d", + XdrvMailbox.index, Light.old_power, Light.power, mask, shift); +#endif + if (Light.power != Light.old_power) { + Light.update = true; + } + LightAnimate(); +} + + + + +void LightAnimate(void) +{ + uint16_t light_still_on = 0; + bool power_off = false; + + + light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); + Light.strip_timer_counter++; + + + + if (Light.power || Light.fade_running) { + if (Settings.sleep > PWM_MAX_SLEEP) { + sleep = PWM_MAX_SLEEP; + } else { + sleep = Settings.sleep; + } + } else { + sleep = Settings.sleep; + } + + if (!Light.power) { + Light.strip_timer_counter = 0; + if (Settings.light_scheme >= LS_MAX) { + power_off = true; + } + } else { + switch (Settings.light_scheme) { + case LS_POWER: + light_controller.calcLevels(Light.new_color); + break; + case LS_WAKEUP: + if (2 == Light.wakeup_active) { + Light.wakeup_active = 1; + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.new_color[i] = 0; + } + Light.wakeup_counter = 0; + Light.wakeup_dimmer = 0; + } + Light.wakeup_counter++; + if (Light.wakeup_counter > ((Settings.light_wakeup * STATES) / Settings.light_dimmer)) { + Light.wakeup_counter = 0; + Light.wakeup_dimmer++; + if (Light.wakeup_dimmer <= Settings.light_dimmer) { + light_state.setDimmer(Light.wakeup_dimmer); + light_controller.calcLevels(); + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.new_color[i] = Light.current_color[i]; + } + } else { + + + + + Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"")); + LightState(1); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); + XdrvRulesProcess(); + + Light.wakeup_active = 0; + Settings.light_scheme = LS_POWER; + } + } + break; + case LS_CYCLEUP: + LightCycleColor(1); + break; + case LS_CYCLEDN: + LightCycleColor(-1); + break; + case LS_RANDOM: + LightCycleColor(0); + break; + default: + XlgtCall(FUNC_SET_SCHEME); + } + } + + if ((Settings.light_scheme < LS_MAX) || power_off) { + + + LightApplyPower(Light.new_color, Light.power); + + + + + + + + if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { + Light.update = true; + } + if (Light.update) { + uint16_t cur_col_10[LST_MAX]; + Light.update = false; + + + for (uint32_t i = 0; i < LST_MAX; i++) { + Light.last_color[i] = Light.new_color[i]; + + cur_col_10[i] = change8to10(Light.new_color[i]); + } + + if (Light.pwm_multi_channels) { + calcGammaMultiChannels(cur_col_10); + } else { + calcGammaBulbs(cur_col_10); + + + + if ((LST_RGBW <= Light.subtype) && (0 == Settings.rgbwwTable[4]) && (0 == cur_col_10[3]+cur_col_10[4])) { + uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); + for (uint32_t i=0; i<3; i++) { + + uint32_t adjust10 = change8to10(Settings.rgbwwTable[i]); + cur_col_10[i] = changeUIntScale(cur_col_10[i] - min_rgb_10, 0, 1023, 0, adjust10); + } + + + uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); + uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); + if (LST_RGBW == Light.subtype) { + + cur_col_10[3] = white_10; + } else { + + uint32_t ct = light_state.getCT10bits(); + cur_col_10[4] = changeUIntScale(ct, 0, 1023, 0, white_10); + cur_col_10[3] = white_10 - cur_col_10[4]; + } + } + } + + + if (0 != Settings.rgbwwTable[4]) { + for (uint32_t i = 0; i 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0; + } + + + uint16_t orig_col_10bits[LST_MAX]; + memcpy(orig_col_10bits, cur_col_10, sizeof(orig_col_10bits)); + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col_10[i] = orig_col_10bits[Light.color_remap[i]]; + } + + if (!Settings.light_fade || power_off || (!Light.fade_initialized)) { + + memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10)); + + LightSetOutputs(cur_col_10); + Light.fade_initialized = true; + } else { + if (Light.fade_running) { + + memcpy(Light.fade_start_10, Light.fade_cur_10, sizeof(Light.fade_start_10)); + } + memcpy(Light.fade_end_10, cur_col_10, sizeof(Light.fade_start_10)); + Light.fade_running = true; + Light.fade_duration = 0; + Light.fade_start = 0; + + } + } + if (Light.fade_running) { + if (LightApplyFade()) { + + + + LightSetOutputs(Light.fade_cur_10); + } + } + } +} + +bool isChannelGammaCorrected(uint32_t channel) { + if (!Settings.light_correction) { return false; } + if (channel >= Light.subtype) { return false; } + + if (PHILIPS == my_module_type) { + if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } + if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } + } + return true; +} + + +uint16_t fadeGamma(uint32_t channel, uint16_t v) { + if (isChannelGammaCorrected(channel)) { + return ledGamma_internal(v, gamma_table_fast); + } else { + return v; + } +} +uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg) { + if (isChannelGammaCorrected(channel)) { + return ledGammaReverse_internal(vg, gamma_table_fast); + } else { + return vg; + } +} + +bool LightApplyFade(void) { + static uint32_t last_millis = 0; + uint32_t now = millis(); + + if ((now - last_millis) <= 5) { + return false; + } + last_millis = now; + + + if (0 == Light.fade_duration) { + Light.fade_start = now; + + uint32_t distance = 0; + for (uint32_t i = 0; i < Light.subtype; i++) { + int32_t channel_distance = fadeGammaReverse(i, Light.fade_end_10[i]) - fadeGammaReverse(i, Light.fade_start_10[i]); + if (channel_distance < 0) { channel_distance = - channel_distance; } + if (channel_distance > distance) { distance = channel_distance; } + } + if (distance > 0) { + + + + Light.fade_duration = (distance * Settings.light_speed * 500) / 1023; + if (Settings.save_data) { + + uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; + + if (save_data_counter < delay_seconds) { + save_data_counter = delay_seconds; + } + } + } else { + + Light.fade_running = false; + } + } + + uint16_t fade_current = now - Light.fade_start; + if (fade_current <= Light.fade_duration) { + + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.fade_cur_10[i] = fadeGamma(i, + changeUIntScale(fadeGammaReverse(i, fade_current), + 0, Light.fade_duration, + fadeGammaReverse(i, Light.fade_start_10[i]), + fadeGammaReverse(i, Light.fade_end_10[i]))); + + + + } + } else { + + + Light.fade_running = false; + Light.fade_start = 0; + Light.fade_duration = 0; + + memcpy(Light.fade_cur_10, Light.fade_end_10, sizeof(Light.fade_end_10)); + + memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10)); + } + return true; +} + + + +void LightApplyPower(uint8_t new_color[LST_MAX], power_t power) { + + if (Light.pwm_multi_channels) { + + for (uint32_t i = 0; i < LST_MAX; i++) { + if (0 == bitRead(power,i)) { + new_color[i] = 0; + } + } + + + + + + } else { + if (!light_controller.isCTRGBLinked()) { + + if (0 == (power & 1)) { + new_color[0] = new_color[1] = new_color[2] = 0; + } + if (0 == (power & 2)) { + new_color[3] = new_color[4] = 0; + } + } else if (!power) { + for (uint32_t i = 0; i < LST_MAX; i++) { + new_color[i] = 0; + } + } + } +} + +void LightSetOutputs(const uint16_t *cur_col_10) { + + if (light_type < LT_PWM6) { + for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { + if (pin[GPIO_PWM1 +i] < 99) { + + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10[(i + Light.pwm_offset)] : cur_col_10[(i + Light.pwm_offset)]); + } + } + } + + + + + uint8_t cur_col[LST_MAX]; + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col[i] = change10to8(cur_col_10[i]); + } + + + uint8_t scale_col[3]; + uint32_t max = (cur_col[0] > cur_col[1] && cur_col[0] > cur_col[2]) ? cur_col[0] : (cur_col[1] > cur_col[2]) ? cur_col[1] : cur_col[2]; + for (uint32_t i = 0; i < 3; i++) { + scale_col[i] = (0 == max) ? 255 : (255 > max) ? changeUIntScale(cur_col[i], 0, max, 0, 255) : cur_col[i]; + } + + char *tmp_data = XdrvMailbox.data; + char *tmp_topic = XdrvMailbox.topic; + XdrvMailbox.data = (char*)cur_col; + XdrvMailbox.topic = (char*)scale_col; + if (XlgtCall(FUNC_SET_CHANNELS)) { } + else if (XdrvCall(FUNC_SET_CHANNELS)) { } + XdrvMailbox.data = tmp_data; + XdrvMailbox.topic = tmp_topic; +} + + +void calcGammaMultiChannels(uint16_t cur_col_10[5]) { + + if (Settings.light_correction) { + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col_10[i] = ledGamma10_10(cur_col_10[i]); + } + } +} + +void calcGammaBulbs(uint16_t cur_col_10[5]) { + + + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + + uint32_t cw1 = Light.subtype - 1; + uint32_t cw0 = Light.subtype - 2; + uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; + uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; + + if (PHILIPS == my_module_type) { + + cur_col_10[cw1] = light_state.getCT10bits(); + + if (Settings.light_correction) { + cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); + } else { + cur_col_10[cw0] = white_bri10_1023; + } + } else if (Settings.light_correction) { + + if (white_bri10 <= 1031) { + + uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); + + cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); + cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); + } else { + cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); + cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); + } + } + } + + if (Settings.light_correction) { + + if (LST_RGB <= Light.subtype) { + for (uint32_t i = 0; i < 3; i++) { + cur_col_10[i] = ledGamma10_10(cur_col_10[i]); + } + } + + if ((LST_SINGLE == Light.subtype) || (LST_RGBW == Light.subtype)) { + cur_col_10[Light.subtype - 1] = ledGamma10_10(cur_col_10[Light.subtype - 1]); + } + } +} + + + + + +bool LightColorEntry(char *buffer, uint32_t buffer_length) +{ + char scolor[10]; + char *p; + char *str; + uint32_t entry_type = 0; + uint8_t value = Light.fixed_color_index; + + if (buffer[0] == '#') { + buffer++; + buffer_length--; + } + + if (Light.subtype >= LST_RGB) { + char option = (1 == buffer_length) ? buffer[0] : '\0'; + if (('+' == option) && (Light.fixed_color_index < MAX_FIXED_COLOR)) { + value++; + } + else if (('-' == option) && (Light.fixed_color_index > 1)) { + value--; + } else { + value = atoi(buffer); + } + } + + memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); + + while ((buffer_length > 0) && ('=' == buffer[buffer_length - 1])) { + buffer_length--; + memcpy(&Light.entry_color, &Light.current_color, sizeof(Light.entry_color)); + } + if (strstr(buffer, ",") != nullptr) { + int8_t i = 0; + for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) { + if (i < LST_MAX) { + Light.entry_color[i++] = atoi(str); + } + } + entry_type = 2; + } + else if (((2 * Light.subtype) == buffer_length) || (buffer_length > 3)) { + for (uint32_t i = 0; i < tmin((uint)(buffer_length / 2), sizeof(Light.entry_color)); i++) { + strlcpy(scolor, buffer + (i *2), 3); + Light.entry_color[i] = (uint8_t)strtol(scolor, &p, 16); + } + entry_type = 1; + } + else if ((Light.subtype >= LST_RGB) && (value > 0) && (value <= MAX_FIXED_COLOR)) { + Light.fixed_color_index = value; + memcpy_P(&Light.entry_color, &kFixedColor[value -1], 3); + entry_type = 1; + } + else if ((value > 199) && (value <= 199 + MAX_FIXED_COLD_WARM)) { + if (LST_RGBW == Light.subtype) { + memcpy_P(&Light.entry_color[3], &kFixedWhite[value -200], 1); + entry_type = 1; + } + else if (LST_COLDWARM == Light.subtype) { + memcpy_P(&Light.entry_color, &kFixedColdWarm[value -200], 2); + entry_type = 1; + } + else if (LST_RGBCW == Light.subtype) { + memcpy_P(&Light.entry_color[3], &kFixedColdWarm[value -200], 2); + entry_type = 1; + } + } + if (entry_type) { + Settings.flag.decimal_text = entry_type -1; + } + return (entry_type); +} + + + +void CmndSupportColor(void) +{ + bool valid_entry = false; + bool coldim = false; + + if (XdrvMailbox.data_len > 0) { + valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); + if (valid_entry) { + if (XdrvMailbox.index <= 2) { + uint32_t old_bri = light_state.getBri(); + + light_controller.changeChannels(Light.entry_color); + if (2 == XdrvMailbox.index) { + + light_controller.changeBri(old_bri); + } + + Settings.light_scheme = 0; + coldim = true; + } else { + for (uint32_t i = 0; i < LST_RGB; i++) { + Settings.ws_color[XdrvMailbox.index -3][i] = Light.entry_color[i]; + } + } + } + } + char scolor[LIGHT_COLOR_SIZE]; + if (!valid_entry && (XdrvMailbox.index <= 2)) { + ResponseCmndChar(LightGetColor(scolor)); + } + if (XdrvMailbox.index >= 3) { + scolor[0] = '\0'; + for (uint32_t i = 0; i < LST_RGB; i++) { + if (Settings.flag.decimal_text) { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.ws_color[XdrvMailbox.index -3][i]); + } else { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]); + } + } + ResponseCmndIdxChar(scolor); + } + if (coldim) { + LightPreparePower(); + } +} + +void CmndColor(void) +{ + + + + + + + + if ((Light.subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { + CmndSupportColor(); + } +} + +void CmndWhite(void) +{ + + + if (Light.pwm_multi_channels) { return; } + if ( ((Light.subtype >= LST_RGBW) || (LST_COLDWARM == Light.subtype)) && (XdrvMailbox.index == 1)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + light_controller.changeDimmer(XdrvMailbox.payload, 2); + LightPreparePower(2); + } else { + ResponseCmndNumber(light_state.getDimmer(2)); + } + } +} + +void CmndChannel(void) +{ + + + + + if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { + uint32_t light_index = XdrvMailbox.index - Light.device; + power_t coldim = 0; + + + if (1 == XdrvMailbox.data_len) { + uint8_t channel = changeUIntScale(Light.current_color[light_index],0,255,0,100); + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; + } else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (channel < 11) ? 1 : channel - 10; + } + } + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Light.current_color[light_index] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); + if (Light.pwm_multi_channels) { + coldim = 1 << light_index; + } else { + if (light_controller.isCTRGBLinked()) { + + if ((light_index < 3) && (light_controller.isCTRGBLinked())) { + Light.current_color[3] = Light.current_color[4] = 0; + } else { + Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; + } + coldim = 1; + } else { + if (light_index < 3) { coldim = 1; } + else { coldim = 2; } + } + } + light_controller.changeChannels(Light.current_color); + } + ResponseCmndIdxNumber(changeUIntScale(Light.current_color[light_index],0,255,0,100)); + if (coldim) { + LightPreparePower(coldim); + } + } +} + +void CmndHsbColor(void) +{ + + + + + + + + if (Light.subtype >= LST_RGB) { + if (XdrvMailbox.data_len > 0) { + uint16_t c_hue; + uint8_t c_sat; + light_state.getHSB(&c_hue, &c_sat, nullptr); + uint32_t HSB[3]; + HSB[0] = c_hue; + HSB[1] = c_sat; + HSB[2] = light_state.getBriRGB(); + if ((2 == XdrvMailbox.index) || (3 == XdrvMailbox.index)) { + if ((uint32_t)XdrvMailbox.payload > 100) { XdrvMailbox.payload = 100; } + HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); + } else { + uint32_t paramcount = ParseParameters(3, HSB); + if (HSB[0] > 360) { HSB[0] = 360; } + for (uint32_t i = 1; i < paramcount; i++) { + if (HSB[i] > 100) { HSB[i] == 100; } + HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); + } + } + light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); + LightPreparePower(1); + } else { + LightState(0); + } + } +} + +void CmndScheme(void) +{ + + + + + + if (Light.subtype >= LST_RGB) { + uint32_t max_scheme = Light.max_scheme; + + if (1 == XdrvMailbox.data_len) { + if (('+' == XdrvMailbox.data[0]) && (Settings.light_scheme < max_scheme)) { + XdrvMailbox.payload = Settings.light_scheme + ((0 == Settings.light_scheme) ? 2 : 1); + } + else if (('-' == XdrvMailbox.data[0]) && (Settings.light_scheme > 0)) { + XdrvMailbox.payload = Settings.light_scheme - ((2 == Settings.light_scheme) ? 2 : 1); + } + } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= max_scheme)) { + uint32_t parm[2]; + if (ParseParameters(2, parm) > 1) { + Light.wheel = parm[1]; + } + Settings.light_scheme = XdrvMailbox.payload; + if (LS_WAKEUP == Settings.light_scheme) { + Light.wakeup_active = 3; + } + LightPowerOn(); + Light.strip_timer_counter = 0; + + if (Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } + } + ResponseCmndNumber(Settings.light_scheme); + } +} + +void CmndWakeup(void) +{ + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + light_controller.changeDimmer(XdrvMailbox.payload); + } + Light.wakeup_active = 3; + Settings.light_scheme = LS_WAKEUP; + LightPowerOn(); + ResponseCmndChar(D_JSON_STARTED); +} + +void CmndColorTemperature(void) +{ + + + + + if (Light.pwm_multi_channels) { return; } + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + uint32_t ct = light_state.getCT(); + if (1 == XdrvMailbox.data_len) { + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (ct > (CT_MAX-34)) ? CT_MAX : ct + 34; + } + else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (ct < (CT_MIN+34)) ? CT_MIN : ct - 34; + } + } + if ((XdrvMailbox.payload >= CT_MIN) && (XdrvMailbox.payload <= CT_MAX)) { + light_controller.changeCTB(XdrvMailbox.payload, light_state.getBriCT()); + LightPreparePower(2); + } else { + ResponseCmndNumber(ct); + } + } +} + +void CmndDimmer(void) +{ + + + + + + + uint32_t dimmer; + if (XdrvMailbox.index > 2) { XdrvMailbox.index = 1; } + + if ((light_controller.isCTRGBLinked()) || (0 == XdrvMailbox.index)) { + dimmer = light_state.getDimmer(); + } else { + dimmer = light_state.getDimmer(XdrvMailbox.index); + } + + if (1 == XdrvMailbox.data_len) { + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (dimmer > 89) ? 100 : dimmer + 10; + } else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (dimmer < 11) ? 1 : dimmer - 10; + } + } + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + if (light_controller.isCTRGBLinked()) { + + light_controller.changeDimmer(XdrvMailbox.payload); + LightPreparePower(); + } else { + if (0 != XdrvMailbox.index) { + light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); + LightPreparePower(1 << (XdrvMailbox.index - 1)); + } else { + + light_controller.changeDimmer(XdrvMailbox.payload, 1); + light_controller.changeDimmer(XdrvMailbox.payload, 2); + LightPreparePower(); + } + } + Light.update = true; + } else { + ResponseCmndNumber(dimmer); + } +} + +void CmndDimmerRange(void) +{ + + + if (XdrvMailbox.data_len > 0) { + uint32_t parm[2]; + parm[0] = Settings.dimmer_hw_min; + parm[1] = Settings.dimmer_hw_max; + ParseParameters(2, parm); + if (parm[0] < parm[1]) { + Settings.dimmer_hw_min = parm[0]; + Settings.dimmer_hw_max = parm[1]; + } else { + Settings.dimmer_hw_min = parm[1]; + Settings.dimmer_hw_max = parm[0]; + } + restart_flag = 2; + } + Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); +} + +void CmndLedTable(void) +{ + + + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + Settings.light_correction = XdrvMailbox.payload; + break; + case 2: + Settings.light_correction ^= 1; + break; + } + Light.update = true; + } + ResponseCmndStateText(Settings.light_correction); +} + +void CmndRgbwwTable(void) +{ + + + if ((XdrvMailbox.data_len > 0)) { + uint32_t parm[LST_RGBCW -1]; + uint32_t parmcount = ParseParameters(LST_RGBCW, parm); + for (uint32_t i = 0; i < parmcount; i++) { + Settings.rgbwwTable[i] = parm[i]; + } + Light.update = true; + } + char scolor[LIGHT_COLOR_SIZE]; + scolor[0] = '\0'; + for (uint32_t i = 0; i < LST_RGBCW; i++) { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); + } + ResponseCmndChar(scolor); +} + +void CmndFade(void) +{ + + + + + switch (XdrvMailbox.payload) { + case 0: + case 1: + Settings.light_fade = XdrvMailbox.payload; + break; + case 2: + Settings.light_fade ^= 1; + break; + } + if (!Settings.light_fade) { Light.fade_running = false; } + ResponseCmndStateText(Settings.light_fade); +} + +void CmndSpeed(void) +{ + + + + + if (1 == XdrvMailbox.data_len) { + if (('+' == XdrvMailbox.data[0]) && (Settings.light_speed > 1)) { + XdrvMailbox.payload = Settings.light_speed - 1; + } + else if (('-' == XdrvMailbox.data[0]) && (Settings.light_speed < 40)) { + XdrvMailbox.payload = Settings.light_speed + 1; + } + } + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 40)) { + Settings.light_speed = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_speed); +} + +void CmndWakeupDuration(void) +{ + + + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { + Settings.light_wakeup = XdrvMailbox.payload; + Light.wakeup_active = 0; + } + ResponseCmndNumber(Settings.light_wakeup); +} + +void CmndUndocA(void) +{ + + char scolor[LIGHT_COLOR_SIZE]; + LightGetColor(scolor, true); + scolor[6] = '\0'; + Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); + MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); + mqtt_data[0] = '\0'; +} + + + + + +bool Xdrv04(uint8_t function) +{ + bool result = false; + + if (FUNC_MODULE_INIT == function) { + return LightModuleInit(); + } + else if (light_type) { + switch (function) { + case FUNC_SERIAL: + result = XlgtCall(FUNC_SERIAL); + break; + case FUNC_LOOP: + if (Light.fade_running) { + if (LightApplyFade()) { + LightSetOutputs(Light.fade_cur_10); + } + } + break; + case FUNC_EVERY_50_MSECOND: + LightAnimate(); + break; + case FUNC_SET_POWER: + LightSetPower(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kLightCommands, LightCommand); + if (!result) { + result = XlgtCall(FUNC_COMMAND); + } + break; + case FUNC_PRE_INIT: + LightInit(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_05_irremote.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_05_irremote.ino" +#if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) + + + + +#define XDRV_05 5 + +#include + +enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND }; + +const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; + + +void (* const IrRemoteCommand[])(void) PROGMEM = { + &CmndIrSend }; + + +static const uint8_t MAX_STANDARD_IR = NEC; +const char kIrRemoteProtocols[] PROGMEM = "UNKNOWN|RC5|RC6|NEC"; + + + + + +#include + +IRsend *irsend = nullptr; +bool irsend_active = false; + +void IrSendInit(void) +{ + irsend = new IRsend(pin[GPIO_IRSEND]); + irsend->begin(); +} + +#ifdef USE_IR_RECEIVE + + + + +const bool IR_RCV_SAVE_BUFFER = false; +const uint32_t IR_TIME_AVOID_DUPLICATE = 500; + +#include + +IRrecv *irrecv = nullptr; + +unsigned long ir_lasttime = 0; + +void IrReceiveUpdateThreshold(void) +{ + if (irrecv != nullptr) { + if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + } +} + +void IrReceiveInit(void) +{ + + irrecv = new IRrecv(pin[GPIO_IRRECV], IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER); + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + irrecv->enableIRIn(); + + +} + +void IrReceiveCheck(void) +{ + char sirtype[8]; + int8_t iridx = 0; + + decode_results results; + + if (irrecv->decode(&results)) { + char hvalue[65]; + + iridx = results.decode_type; + if ((iridx < 0) || (iridx > MAX_STANDARD_IR)) { iridx = 0; } + + if (iridx) { + if (results.bits > 64) { + + uint32_t digits2 = results.bits / 8; + if (results.bits % 8) { digits2++; } + ToHex_P((unsigned char*)results.state, digits2, hvalue, sizeof(hvalue)); + } else { + Uint64toHex(results.value, hvalue, results.bits); + } + } else { + Uint64toHex(results.value, hvalue, 32); + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%s, Decode %d"), + irsend_active, results.rawlen, results.overflow, results.bits, hvalue, results.decode_type); + + unsigned long now = millis(); + + if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { + ir_lasttime = now; + + char svalue[64]; + if (Settings.flag.ir_receive_decimal) { + ulltoa(results.value, svalue, 10); + } else { + snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue); + } + ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d"), + GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits); + if (iridx) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_DATA "\":%s"), svalue); + } else { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_HASH "\":%s"), svalue); + } + + if (Settings.flag3.receive_raw) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); + uint16_t i; + for (i = 1; i < results.rawlen; i++) { + if (i > 1) { ResponseAppend_P(PSTR(",")); } + uint32_t usecs; + for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { + ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); + } + ResponseAppend_P(PSTR("%d"), usecs); + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } + } + uint16_t extended_length = results.rawlen - 1; + for (uint32_t j = 0; j < results.rawlen - 1; j++) { + uint32_t usecs = results.rawbuf[j] * kRawTick; + + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + if (iridx) { + unsigned long value = results.value | (iridx << 28); + DomoticzSensor(DZ_COUNT, value); + } +#endif + } + + irrecv->resume(); + } +} +#endif + + + + + +uint32_t IrRemoteCmndIrSendJson(void) +{ + + + + + char dataBufUc[XdrvMailbox.data_len + 1]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { + return IE_INVALID_JSON; + } + + StaticJsonBuffer<140> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (!root.success()) { + return IE_INVALID_JSON; + } + + + + char parm_uc[10]; + const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; + uint16_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; + uint64_t data = strtoull(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); + uint16_t repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT))]; + + if (XdrvMailbox.index > repeat + 1) { + repeat = XdrvMailbox.index - 1; + } + if (!(protocol && bits)) { + return IE_SYNTAX_IRSEND; + } + + char protocol_text[20]; + int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); + + char dvalue[64]; + char hvalue[20]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %s (0x%s), repeat %d, protocol_code %d"), + protocol_text, protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat, protocol_code); + + irsend_active = true; + switch (protocol_code) { +#ifdef USE_IR_SEND_RC5 + case RC5: + irsend->sendRC5(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_RC6 + case RC6: + irsend->sendRC6(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_NEC + case NEC: + irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits, repeat); break; +#endif + default: + irsend_active = false; + ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); + } + + return IE_NO_ERROR; +} + +void CmndIrSend(void) +{ + uint8_t error = IE_SYNTAX_IRSEND; + + if (XdrvMailbox.data_len) { + + if (strstr(XdrvMailbox.data, "{") == nullptr) { + error = IE_INVALID_JSON; + } else { + error = IrRemoteCmndIrSendJson(); + } + } + IrRemoteCmndResponse(error); +} + +void IrRemoteCmndResponse(uint32_t error) +{ + switch (error) { + case IE_INVALID_RAWDATA: + ResponseCmndChar(D_JSON_INVALID_RAWDATA); + break; + case IE_INVALID_JSON: + ResponseCmndChar(D_JSON_INVALID_JSON); + break; + case IE_SYNTAX_IRSEND: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + break; + default: + ResponseCmndDone(); + } +} + + + + + +bool Xdrv05(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { + switch (function) { + case FUNC_PRE_INIT: + if (pin[GPIO_IRSEND] < 99) { + IrSendInit(); + } +#ifdef USE_IR_RECEIVE + if (pin[GPIO_IRRECV] < 99) { + IrReceiveInit(); + } +#endif + break; + case FUNC_EVERY_50_MSECOND: +#ifdef USE_IR_RECEIVE + if (pin[GPIO_IRRECV] < 99) { + IrReceiveCheck(); + } +#endif + irsend_active = false; + break; + case FUNC_COMMAND: + if (pin[GPIO_IRSEND] < 99) { + result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); + } + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_05_irremote_full.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_05_irremote_full.ino" +#ifdef USE_IR_REMOTE_FULL + + + + +#define XDRV_05 5 + +#include +#include +#include +#include +#include + +enum IrErrors { IE_RESPONSE_PROVIDED, IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC, + IE_UNSUPPORTED_HVAC, IE_UNSUPPORTED_PROTOCOL }; + +const char kIrRemoteCommands[] PROGMEM = "|" + D_CMND_IRHVAC "|" D_CMND_IRSEND ; + +void (* const IrRemoteCommand[])(void) PROGMEM = { + &CmndIrHvac, &CmndIrSend }; + + + + + +IRsend *irsend = nullptr; +bool irsend_active = false; + +void IrSendInit(void) +{ + irsend = new IRsend(pin[GPIO_IRSEND]); + irsend->begin(); +} + + + +uint8_t reverseBitsInByte(uint8_t b) { + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; +} + + +uint64_t reverseBitsInBytes64(uint64_t b) { + union { + uint8_t b[8]; + uint64_t i; + } a; + a.i = b; + for (uint32_t i=0; i<8; i++) { + a.b[i] = reverseBitsInByte(a.b[i]); + } + return a.i; +} + + + + + +const bool IR_FULL_RCV_SAVE_BUFFER = false; +const uint32_t IR_TIME_AVOID_DUPLICATE = 500; + + + + +const uint16_t IR_FULL_BUFFER_SIZE = 1024; + + + +const uint8_t IR__FULL_RCV_TIMEOUT = 50; + +IRrecv *irrecv = nullptr; + +unsigned long ir_lasttime = 0; + +void IrReceiveUpdateThreshold(void) +{ + if (irrecv != nullptr) { + if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + } +} + +void IrReceiveInit(void) +{ + + irrecv = new IRrecv(pin[GPIO_IRRECV], IR_FULL_BUFFER_SIZE, IR__FULL_RCV_TIMEOUT, IR_FULL_RCV_SAVE_BUFFER); + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + irrecv->enableIRIn(); +} + +String sendACJsonState(const stdAc::state_t &state) { + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + json[D_JSON_IRHVAC_VENDOR] = typeToString(state.protocol); + json[D_JSON_IRHVAC_MODEL] = state.model; + json[D_JSON_IRHVAC_POWER] = IRac::boolToString(state.power); + json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(state.mode); + + if (state.mode == stdAc::opmode_t::kOff || !state.power) { + json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff); + json[D_JSON_IRHVAC_POWER] = IRac::boolToString(false); + } + json[D_JSON_IRHVAC_CELSIUS] = IRac::boolToString(state.celsius); + if (floorf(state.degrees) == state.degrees) { + json[D_JSON_IRHVAC_TEMP] = floorf(state.degrees); + } else { + json[D_JSON_IRHVAC_TEMP] = RawJson(String(state.degrees, 1)); + } + json[D_JSON_IRHVAC_FANSPEED] = IRac::fanspeedToString(state.fanspeed); + json[D_JSON_IRHVAC_SWINGV] = IRac::swingvToString(state.swingv); + json[D_JSON_IRHVAC_SWINGH] = IRac::swinghToString(state.swingh); + json[D_JSON_IRHVAC_QUIET] = IRac::boolToString(state.quiet); + json[D_JSON_IRHVAC_TURBO] = IRac::boolToString(state.turbo); + json[D_JSON_IRHVAC_ECONO] = IRac::boolToString(state.econo); + json[D_JSON_IRHVAC_LIGHT] = IRac::boolToString(state.light); + json[D_JSON_IRHVAC_FILTER] = IRac::boolToString(state.filter); + json[D_JSON_IRHVAC_CLEAN] = IRac::boolToString(state.clean); + json[D_JSON_IRHVAC_BEEP] = IRac::boolToString(state.beep); + json[D_JSON_IRHVAC_SLEEP] = state.sleep; + + String payload = ""; + payload.reserve(200); + json.printTo(payload); + return payload; +} + +String sendIRJsonState(const struct decode_results &results) { + String json("{"); + json += "\"" D_JSON_IR_PROTOCOL "\":\""; + json += typeToString(results.decode_type); + json += "\",\"" D_JSON_IR_BITS "\":"; + json += results.bits; + + if (hasACState(results.decode_type)) { + json += ",\"" D_JSON_IR_DATA "\":\"0x"; + json += resultToHexidecimal(&results); + json += "\""; + } else { + if (UNKNOWN != results.decode_type) { + json += ",\"" D_JSON_IR_DATA "\":"; + } else { + json += ",\"" D_JSON_IR_HASH "\":"; + } + if (Settings.flag.ir_receive_decimal) { + char svalue[32]; + ulltoa(results.value, svalue, 10); + json += svalue; + } else { + char hvalue[64]; + if (UNKNOWN != results.decode_type) { + Uint64toHex(results.value, hvalue, results.bits); + json += "\"0x"; + json += hvalue; + json += "\",\"" D_JSON_IR_DATALSB "\":\"0x"; + Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); + json += hvalue; + json += "\""; + } else { + Uint64toHex(results.value, hvalue, 32); + json += "\"0x"; + json += hvalue; + json += "\""; + } + } + } + json += ",\"" D_JSON_IR_REPEAT "\":"; + json += results.repeat; + + stdAc::state_t ac_result; + if (IRAcUtils::decodeToState(&results, &ac_result, nullptr)) { + + json += ",\"" D_CMND_IRHVAC "\":"; + json += sendACJsonState(ac_result); + } + + return json; +} + +void IrReceiveCheck(void) +{ + decode_results results; + + if (irrecv->decode(&results)) { + uint32_t now = millis(); + + + if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { + ir_lasttime = now; + Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); + + if (Settings.flag3.receive_raw) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); + uint16_t i; + for (i = 1; i < results.rawlen; i++) { + if (i > 1) { ResponseAppend_P(PSTR(",")); } + uint32_t usecs; + for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { + ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); + } + ResponseAppend_P(PSTR("%d"), usecs); + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } + } + uint16_t extended_length = results.rawlen - 1; + for (uint32_t j = 0; j < results.rawlen - 1; j++) { + uint32_t usecs = results.rawbuf[j] * kRawTick; + + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + + XdrvRulesProcess(); + } + + irrecv->resume(); + } +} + + + + + + + +String listSupportedProtocols(bool hvac) { + String l(""); + bool first = true; + for (uint32_t i = UNUSED + 1; i <= kLastDecodeType; i++) { + bool found = false; + if (hvac) { + found = IRac::isProtocolSupported((decode_type_t)i); + } else { + found = (IRsend::defaultBits((decode_type_t)i) > 0) && (!IRac::isProtocolSupported((decode_type_t)i)); + } + if (found) { + if (first) { + first = false; + } else { + l += "|"; + } + l += typeToString((decode_type_t)i); + } + } + return l; +} + + +const stdAc::fanspeed_t IrHvacFanSpeed[] PROGMEM = { stdAc::fanspeed_t::kAuto, + stdAc::fanspeed_t::kMin, stdAc::fanspeed_t::kLow,stdAc::fanspeed_t::kMedium, + stdAc::fanspeed_t::kHigh, stdAc::fanspeed_t::kMax }; + +uint32_t IrRemoteCmndIrHvacJson(void) +{ + stdAc::state_t state, prev; + char parm_uc[12]; + + + char dataBufUc[XdrvMailbox.data_len + 1]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } + + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(dataBufUc); + if (!json.success()) { return IE_INVALID_JSON; } + + + state.protocol = decode_type_t::UNKNOWN; + state.model = 1; + state.mode = stdAc::opmode_t::kAuto; + state.power = false; + state.celsius = true; + state.degrees = 21.0f; + state.fanspeed = stdAc::fanspeed_t::kMedium; + state.swingv = stdAc::swingv_t::kOff; + state.swingh = stdAc::swingh_t::kOff; + state.light = false; + state.beep = false; + state.econo = false; + state.filter = false; + state.turbo = false; + state.quiet = false; + state.sleep = -1; + state.clean = false; + state.clock = -1; + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); + if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); + if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } + if (decode_type_t::UNKNOWN == state.protocol) { return IE_UNSUPPORTED_HVAC; } + if (!IRac::isProtocolSupported(state.protocol)) { return IE_UNSUPPORTED_HVAC; } + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED)); + if (json.containsKey(parm_uc)) { + uint32_t fan_speed = json[parm_uc]; + if ((fan_speed >= 1) && (fan_speed <= 5)) { + state.fanspeed = (stdAc::fanspeed_t) pgm_read_byte(&IrHvacFanSpeed[fan_speed]); + } else { + state.fanspeed = IRac::strToFanspeed(json[parm_uc]); + } + } + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODEL)); + if (json.containsKey(parm_uc)) { state.model = IRac::strToModel(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE)); + if (json.containsKey(parm_uc)) { state.mode = IRac::strToOpmode(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGV)); + if (json.containsKey(parm_uc)) { state.swingv = IRac::strToSwingV(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGH)); + if (json.containsKey(parm_uc)) { state.swingh = IRac::strToSwingH(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TEMP)); + if (json.containsKey(parm_uc)) { state.degrees = json[parm_uc]; } + + + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER)); + if (json.containsKey(parm_uc)) { state.power = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CELSIUS)); + if (json.containsKey(parm_uc)) { state.celsius = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_LIGHT)); + if (json.containsKey(parm_uc)) { state.light = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_BEEP)); + if (json.containsKey(parm_uc)) { state.beep = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_ECONO)); + if (json.containsKey(parm_uc)) { state.econo = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FILTER)); + if (json.containsKey(parm_uc)) { state.filter = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TURBO)); + if (json.containsKey(parm_uc)) { state.turbo = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_QUIET)); + if (json.containsKey(parm_uc)) { state.quiet = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CLEAN)); + if (json.containsKey(parm_uc)) { state.clean = IRac::strToBool(json[parm_uc]); } + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SLEEP)); + if (json[parm_uc]) { state.sleep = json[parm_uc]; } + + + IRac ac(pin[GPIO_IRSEND]); + bool success = ac.sendAc(state, &prev); + if (!success) { return IE_SYNTAX_IRHVAC; } + + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":%s}"), sendACJsonState(state).c_str()); + return IE_RESPONSE_PROVIDED; +} + +void CmndIrHvac(void) +{ + uint8_t error = IE_SYNTAX_IRHVAC; + + if (XdrvMailbox.data_len) { + error = IrRemoteCmndIrHvacJson(); + } + if (error != IE_RESPONSE_PROVIDED) { IrRemoteCmndResponse(error); } +} + + + + + +uint32_t IrRemoteCmndIrSendJson(void) +{ + char parm_uc[12]; + + + + char dataBufUc[XdrvMailbox.data_len + 1]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } + + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(dataBufUc); + if (!json.success()) { return IE_INVALID_JSON; } + + + + decode_type_t protocol = decode_type_t::UNKNOWN; + uint16_t bits = 0; + uint64_t data; + uint8_t repeat = 0; + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); + if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); + if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } + if (decode_type_t::UNKNOWN == protocol) { return IE_UNSUPPORTED_PROTOCOL; } + + UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS)); + if (json.containsKey(parm_uc)) { bits = json[parm_uc]; } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT)); + if (json.containsKey(parm_uc)) { repeat = json[parm_uc]; } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATALSB)); + if (json.containsKey(parm_uc)) { data = reverseBitsInBytes64(strtoull(json[parm_uc], nullptr, 0)); } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA)); + if (json.containsKey(parm_uc)) { data = strtoull(json[parm_uc], nullptr, 0); } + if (0 == bits) { return IE_SYNTAX_IRSEND; } + + + if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; } + + char dvalue[32]; + char hvalue[32]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data 0x%s (%s), repeat %d"), + protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat); + + irsend_active = true; + bool success = irsend->send(protocol, data, bits, repeat); + + if (!success) { + irsend_active = false; + ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); + } + return IE_NO_ERROR; +} + +uint32_t IrRemoteCmndIrSendRaw(void) +{ + + + + + + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + if (p == nullptr) { + return IE_INVALID_RAWDATA; + } + + + uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; + + uint16_t freq = atoi(str); + if (!freq && (*str != '0')) { + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (count < 2) { + return IE_INVALID_RAWDATA; + } + + uint16_t parm[count]; + for (uint32_t i = 0; i < count; i++) { + parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + if (!parm[i]) { + if (!i) { + parm[0] = 38000; + } else { + return IE_INVALID_RAWDATA; + } + } + } + + uint16_t i = 0; + if (count < 4) { + + uint16_t mark = parm[1] *2; + if (3 == count) { + if (parm[2] < parm[1]) { + + mark = parm[1] * parm[2]; + } else { + + mark = parm[2]; + } + } + uint16_t raw_array[strlen(p)]; + for (; *p; *p++) { + if (*p == '0') { + raw_array[i++] = parm[1]; + } + else if (*p == '1') { + raw_array[i++] = mark; + } + } + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, i, parm[0]); + if (r < repeat) { + irsend->space(40000); + } + } + } + else if (6 == count) { + + uint16_t raw_array[strlen(p)*2+3]; + raw_array[i++] = parm[1]; + raw_array[i++] = parm[2]; + uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; + uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; + for (; *p; *p++) { + if (*p == '0') { + raw_array[i++] = parm[3]; + raw_array[i++] = parm[4]; + } + else if (*p == '1') { + raw_array[i++] = parm[3]; + raw_array[i++] = parm[5]; + } + } + raw_array[i++] = parm[3]; + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, i, parm[0]); + if (r < repeat) { + irsend->space(inter_message); + } + } + } + else { + return IE_INVALID_RAWDATA; + } + } else { + if (!freq) { freq = 38000; } + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (0 == count) { + return IE_INVALID_RAWDATA; + } + + + count++; + if (count < 200) { + uint16_t raw_array[count]; + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + } + + + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + } else { + uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); + if (raw_array == nullptr) { + return IE_INVALID_RAWDATA; + } + + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + } + + + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + free(raw_array); + } + } + + return IE_NO_ERROR; +} + +void CmndIrSend(void) +{ + uint8_t error = IE_SYNTAX_IRSEND; + + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, "{") == nullptr) { + error = IrRemoteCmndIrSendRaw(); + } else { + error = IrRemoteCmndIrSendJson(); + } + } + IrRemoteCmndResponse(error); +} + +void IrRemoteCmndResponse(uint32_t error) +{ + switch (error) { + case IE_INVALID_RAWDATA: + ResponseCmndChar(D_JSON_INVALID_RAWDATA); + break; + case IE_INVALID_JSON: + ResponseCmndChar(D_JSON_INVALID_JSON); + break; + case IE_SYNTAX_IRSEND: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + break; + case IE_SYNTAX_IRHVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + break; + case IE_UNSUPPORTED_HVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR " (%s)\"}"), listSupportedProtocols(true).c_str()); + break; + case IE_UNSUPPORTED_PROTOCOL: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_PROTOCOL " (%s)\"}"), listSupportedProtocols(false).c_str()); + break; + default: + ResponseCmndDone(); + } +} + + + + + +bool Xdrv05(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { + switch (function) { + case FUNC_PRE_INIT: + if (pin[GPIO_IRSEND] < 99) { + IrSendInit(); + } + if (pin[GPIO_IRRECV] < 99) { + IrReceiveInit(); + } + break; + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_IRRECV] < 99) { + IrReceiveCheck(); + } + irsend_active = false; + break; + case FUNC_COMMAND: + if (pin[GPIO_IRSEND] < 99) { + result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); + } + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_06_snfbridge.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_06_snfbridge.ino" +#ifdef USE_SONOFF_RF + + + + +#define XDRV_06 6 + +const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; + +enum SonoffBridgeCommands { + CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE }; + +const char kSonoffBridgeCommands[] PROGMEM = "|" + D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY "|" D_CMND_RFRAW; + +void (* const SonoffBridgeCommand[])(void) PROGMEM = { + &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfKey, &CmndRfRaw }; + +struct SONOFFBRIDGE { + uint32_t last_received_id = 0; + uint32_t last_send_code = 0; + uint32_t last_time = 0; + uint32_t last_learn_time = 0; + uint8_t receive_flag = 0; + uint8_t receive_raw_flag = 0; + uint8_t learn_key = 1; + uint8_t learn_active = 0; + uint8_t expected_bytes = 0; +} SnfBridge; + +#ifdef USE_RF_FLASH + + + + + + + +#include "ihx.h" +#include "c2.h" + +const ssize_t RF_RECORD_NO_START_FOUND = -1; +const ssize_t RF_RECORD_NO_END_FOUND = -2; + +ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) +{ + for (size_t i = 0; i < size; i++) { + if (buf[i] == ':') { + return i; + } + } + return RF_RECORD_NO_START_FOUND; +} + +ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size) +{ + for (size_t i = 0; i < size; i++) { + if (buf[i] == '\n') { + return i; + } + } + return RF_RECORD_NO_END_FOUND; +} + +ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len) +{ + ssize_t record_start; + ssize_t record_end; + ssize_t glue_record_sz; + uint8_t *glue_buf; + ssize_t result; + + if (remnant_data[0] != ':') { return -8; } + + + record_end = rf_find_hex_record_end(new_data, new_data_len); + record_start = rf_find_hex_record_start(new_data, new_data_len); + + + + + if ((record_start != RF_RECORD_NO_START_FOUND) && (record_start < record_end)) { + return -8; + } + + glue_record_sz = strlen((const char *) remnant_data) + record_end; + + glue_buf = (uint8_t *) malloc(glue_record_sz); + if (glue_buf == nullptr) { return -2; } + + + memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); + memcpy(glue_buf + strlen((const char *) remnant_data), new_data, record_end); + + result = rf_decode_and_write(glue_buf, glue_record_sz); + free(glue_buf); + return result; +} + +ssize_t rf_decode_and_write(uint8_t *record, size_t size) +{ + uint8_t err = ihx_decode(record, size); + if (err != IHX_SUCCESS) { return -13; } + + ihx_t *h = (ihx_t *) record; + if (h->record_type == IHX_RT_DATA) { + int retries = 5; + uint16_t address = h->address_high * 0x100 + h->address_low; + + do { + err = c2_programming_init(); + err = c2_block_write(address, h->data, h->len); + } while (err != C2_SUCCESS && retries--); + } else if (h->record_type == IHX_RT_END_OF_FILE) { + + err = c2_reset(); + } + + if (err != C2_SUCCESS) { return -12; } + + return 0; +} + +ssize_t rf_search_and_write(uint8_t *buf, size_t size) +{ + + ssize_t rec_end; + ssize_t rec_start; + ssize_t err; + + for (size_t i = 0; i < size; i++) { + + rec_start = rf_find_hex_record_start(buf + i, size - i); + if (rec_start == RF_RECORD_NO_START_FOUND) { + + return -8; + } + + + rec_start += i; + rec_end = rf_find_hex_record_end(buf + rec_start, size - rec_start); + if (rec_end == RF_RECORD_NO_END_FOUND) { + + return rec_start; + } + + + rec_end += rec_start; + + err = rf_decode_and_write(buf + rec_start, rec_end - rec_start); + if (err < 0) { return err; } + i = rec_end; + } + + return 0; +} + +uint8_t rf_erase_flash(void) +{ + uint8_t err; + + for (uint32_t i = 0; i < 4; i++) { + err = c2_programming_init(); + if (err != C2_SUCCESS) { + return 10; + } + err = c2_device_erase(); + if (err != C2_SUCCESS) { + if (i < 3) { + c2_reset(); + } else { + return 11; + } + } else { + break; + } + } + return 0; +} + +uint8_t SnfBrUpdateInit(void) +{ + pinMode(PIN_C2CK, OUTPUT); + pinMode(PIN_C2D, INPUT); + + return rf_erase_flash(); +} +#endif + + + +void SonoffBridgeReceivedRaw(void) +{ + + uint8_t buckets = 0; + + if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } + + ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); + for (uint32_t i = 0; i < serial_in_byte_counter; i++) { + ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); + if (0xB1 == serial_in_buffer[1]) { + if ((i > 3) && buckets) { buckets--; } + if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { + ResponseAppend_P(PSTR(" ")); + } + } + } + ResponseAppend_P(PSTR("\"}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); + + XdrvRulesProcess(); +} + + + +void SonoffBridgeLearnFailed(void) +{ + SnfBridge.learn_active = 0; + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARN_FAILED); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); +} + +void SonoffBridgeReceived(void) +{ + uint16_t sync_time = 0; + uint16_t low_time = 0; + uint16_t high_time = 0; + uint32_t received_id = 0; + char rfkey[8]; + char stemp[16]; + + AddLogSerial(LOG_LEVEL_DEBUG); + + if (0xA2 == serial_in_buffer[0]) { + SonoffBridgeLearnFailed(); + } + else if (0xA3 == serial_in_buffer[0]) { + SnfBridge.learn_active = 0; + low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; + high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; + if (low_time && high_time) { + for (uint32_t i = 0; i < 9; i++) { + Settings.rf_code[SnfBridge.learn_key][i] = serial_in_buffer[i +1]; + } + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); + } else { + SonoffBridgeLearnFailed(); + } + } + else if (0xA4 == serial_in_buffer[0]) { + if (SnfBridge.learn_active) { + SonoffBridgeLearnFailed(); + } else { + sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; + low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; + high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; + received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9]; + + unsigned long now = millis(); + if (!((received_id == SnfBridge.last_received_id) && (now - SnfBridge.last_time < SFB_TIME_AVOID_DUPLICATE))) { + SnfBridge.last_received_id = received_id; + SnfBridge.last_time = now; + strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey)); + for (uint32_t i = 1; i <= 16; i++) { + if (Settings.rf_code[i][0]) { + uint32_t send_id = Settings.rf_code[i][6] << 16 | Settings.rf_code[i][7] << 8 | Settings.rf_code[i][8]; + if (send_id == received_id) { + snprintf_P(rfkey, sizeof(rfkey), PSTR("%d"), i); + break; + } + } + } + if (Settings.flag.rf_receive_decimal) { + snprintf_P(stemp, sizeof(stemp), PSTR("%u"), received_id); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); + } + ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), + sync_time, low_time, high_time, stemp, rfkey); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); + #ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, received_id); + #endif + } + } + } +} + +bool SonoffBridgeSerialInput(void) +{ + + static int8_t receive_len = 0; + + if (SnfBridge.receive_flag) { + if (SnfBridge.receive_raw_flag) { + if (!serial_in_byte_counter) { + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (serial_in_byte_counter == 3) { + if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { + receive_len = serial_in_buffer[2] + 4; + } + } + if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { + SonoffBridgeReceivedRaw(); + SnfBridge.receive_flag = 0; + return 1; + } + } + else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { + if (0 == serial_in_byte_counter) { + SnfBridge.expected_bytes = 2; + if (serial_in_byte >= 0xA3) { + SnfBridge.expected_bytes = 11; + } + if (serial_in_byte == 0xA6) { + SnfBridge.expected_bytes = 0; + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + SnfBridge.receive_raw_flag = 1; + } + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if ((SnfBridge.expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { + SonoffBridgeReceived(); + SnfBridge.receive_flag = 0; + return 1; + } + } + serial_in_byte = 0; + } + if (0xAA == serial_in_byte) { + serial_in_byte_counter = 0; + serial_in_byte = 0; + SnfBridge.receive_flag = 1; + receive_len = 0; + } + return 0; +} + +void SonoffBridgeSendCommand(uint8_t code) +{ + Serial.write(0xAA); + Serial.write(code); + Serial.write(0x55); +} + +void SonoffBridgeSendAck(void) +{ + Serial.write(0xAA); + Serial.write(0xA0); + Serial.write(0x55); +} + +void SonoffBridgeSendCode(uint32_t code) +{ + Serial.write(0xAA); + Serial.write(0xA5); + for (uint32_t i = 0; i < 6; i++) { + Serial.write(Settings.rf_code[0][i]); + } + Serial.write((code >> 16) & 0xff); + Serial.write((code >> 8) & 0xff); + Serial.write(code & 0xff); + Serial.write(0x55); + Serial.flush(); +} + +void SonoffBridgeSend(uint8_t idx, uint8_t key) +{ + uint8_t code; + + key--; + Serial.write(0xAA); + Serial.write(0xA5); + for (uint32_t i = 0; i < 8; i++) { + Serial.write(Settings.rf_code[idx][i]); + } + if (0 == idx) { + code = (0x10 << (key >> 2)) | (1 << (key & 3)); + } else { + code = Settings.rf_code[idx][8]; + } + Serial.write(code); + Serial.write(0x55); + Serial.flush(); +#ifdef USE_DOMOTICZ + + +#endif +} + +void SonoffBridgeLearn(uint8_t key) +{ + SnfBridge.learn_key = key; + SnfBridge.learn_active = 1; + SnfBridge.last_learn_time = millis(); + Serial.write(0xAA); + Serial.write(0xA1); + Serial.write(0x55); +} + + + + + +void CmndRfBridge(void) +{ + char *p; + char stemp [10]; + uint32_t code = 0; + uint8_t radix = 10; + + uint32_t set_index = XdrvMailbox.command_code *2; + + if (XdrvMailbox.data[0] == '#') { + XdrvMailbox.data++; + XdrvMailbox.data_len--; + radix = 16; + } + + if (XdrvMailbox.data_len) { + code = strtol(XdrvMailbox.data, &p, radix); + if (code) { + if (CMND_RFCODE == XdrvMailbox.command_code) { + SnfBridge.last_send_code = code; + SonoffBridgeSendCode(code); + } else { + if (1 == XdrvMailbox.payload) { + code = pgm_read_byte(kDefaultRfCode + set_index) << 8 | pgm_read_byte(kDefaultRfCode + set_index +1); + } + uint8_t msb = code >> 8; + uint8_t lsb = code & 0xFF; + if ((code > 0) && (code < 0x7FFF) && (msb != 0x55) && (lsb != 0x55)) { + Settings.rf_code[0][set_index] = msb; + Settings.rf_code[0][set_index +1] = lsb; + } + } + } + } + if (CMND_RFCODE == XdrvMailbox.command_code) { + code = SnfBridge.last_send_code; + } else { + code = Settings.rf_code[0][set_index] << 8 | Settings.rf_code[0][set_index +1]; + } + if (10 == radix) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), code); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"#%06X\""), code); + } + Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp); +} + +void CmndRfKey(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) { + unsigned long now = millis(); + if ((!SnfBridge.learn_active) || (now - SnfBridge.last_learn_time > 60100)) { + SnfBridge.learn_active = 0; + if (2 == XdrvMailbox.payload) { + SonoffBridgeLearn(XdrvMailbox.index); + ResponseCmndIdxChar(D_JSON_START_LEARNING); + } + else if (3 == XdrvMailbox.payload) { + Settings.rf_code[XdrvMailbox.index][0] = 0; + ResponseCmndIdxChar(D_JSON_SET_TO_DEFAULT); + } + else if (4 == XdrvMailbox.payload) { + for (uint32_t i = 0; i < 6; i++) { + Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i]; + } + Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff; + Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff; + Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff; + ResponseCmndIdxChar(D_JSON_SAVED); + } else if (5 == XdrvMailbox.payload) { + uint8_t key = XdrvMailbox.index; + uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; + uint16_t sync_time = (Settings.rf_code[index][0] << 8) | Settings.rf_code[index][1]; + uint16_t low_time = (Settings.rf_code[index][2] << 8) | Settings.rf_code[index][3]; + uint16_t high_time = (Settings.rf_code[index][4] << 8) | Settings.rf_code[index][5]; + uint32_t code = (Settings.rf_code[index][6] << 16) | (Settings.rf_code[index][7] << 8); + if (0 == index) { + key--; + code |= (uint8_t)((0x10 << (key >> 2)) | (1 << (key & 3))); + } else { + code |= Settings.rf_code[index][8]; + } + Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), + XdrvMailbox.command, XdrvMailbox.index, sync_time, low_time, high_time, code); + } else { + if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { + SonoffBridgeSend(0, XdrvMailbox.index); + ResponseCmndIdxChar(D_JSON_DEFAULT_SENT); + } else { + SonoffBridgeSend(XdrvMailbox.index, 0); + ResponseCmndIdxChar(D_JSON_LEARNED_SENT); + } + } + } else { + Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, SnfBridge.learn_key, D_JSON_LEARNING_ACTIVE); + } + } +} + +void CmndRfRaw(void) +{ + if (XdrvMailbox.data_len) { + if (XdrvMailbox.data_len < 6) { + switch (XdrvMailbox.payload) { + case 0: + SonoffBridgeSendCommand(0xA7); + case 1: + SnfBridge.receive_raw_flag = XdrvMailbox.payload; + break; + case 166: + case 167: + case 169: + case 176: + case 177: + case 255: + SonoffBridgeSendCommand(XdrvMailbox.payload); + SnfBridge.receive_raw_flag = 1; + break; + case 192: + char beep[] = "AAC000C055\0"; + SerialSendRaw(beep); + break; + } + } else { + SerialSendRaw(RemoveSpace(XdrvMailbox.data)); + SnfBridge.receive_raw_flag = 1; + } + } + ResponseCmndStateText(SnfBridge.receive_raw_flag); +} + + + + + +bool Xdrv06(uint8_t function) +{ + bool result = false; + + if (SONOFF_BRIDGE == my_module_type) { + switch (function) { + case FUNC_SERIAL: + result = SonoffBridgeSerialInput(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kSonoffBridgeCommands, SonoffBridgeCommand); + break; + case FUNC_INIT: + SnfBridge.receive_raw_flag = 0; + SonoffBridgeSendCommand(0xA7); + break; + case FUNC_PRE_INIT: + SetSerial(19200, TS_SERIAL_8N1); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_07_domoticz.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_07_domoticz.ino" +#ifdef USE_DOMOTICZ + +#define XDRV_07 7 + +#define D_PRFX_DOMOTICZ "Domoticz" +#define D_CMND_IDX "Idx" +#define D_CMND_KEYIDX "KeyIdx" +#define D_CMND_SWITCHIDX "SwitchIdx" +#define D_CMND_SENSORIDX "SensorIdx" +#define D_CMND_UPDATETIMER "UpdateTimer" + +const char kDomoticzCommands[] PROGMEM = D_PRFX_DOMOTICZ "|" + D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ; + +void (* const DomoticzCommand[])(void) PROGMEM = { + &CmndDomoticzIdx, &CmndDomoticzKeyIdx, &CmndDomoticzSwitchIdx, &CmndDomoticzSensorIdx, &CmndDomoticzUpdateTimer }; + +const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; + +#if MAX_DOMOTICZ_SNS_IDX < DZ_MAX_SENSORS + #error "Domoticz: Too many sensors or change settings.h layout" +#endif + +const char kDomoticzSensors[] PROGMEM = + D_DOMOTICZ_TEMP "|" D_DOMOTICZ_TEMP_HUM "|" D_DOMOTICZ_TEMP_HUM_BARO "|" D_DOMOTICZ_POWER_ENERGY "|" D_DOMOTICZ_ILLUMINANCE "|" + D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER "|" D_DOMOTICZ_SHUTTER ; + +char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; + +int domoticz_update_timer = 0; +uint32_t domoticz_fan_debounce = 0; +bool domoticz_subscribe = false; +bool domoticz_update_flag = true; + +#ifdef USE_SHUTTER +bool domoticz_is_shutter = false; +#endif + +int DomoticzBatteryQuality(void) +{ + + + + + int quality = 100; + +#ifdef USE_ADC_VCC + uint16_t voltage = ESP.getVcc(); + if (voltage <= 2600) { + quality = 0; + } else if (voltage >= 4600) { + quality = 200; + } else { + quality = (voltage - 2600) / 10; + } +#endif + return quality; +} + +int DomoticzRssiQuality(void) +{ + + + return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; +} + +#ifdef USE_SONOFF_IFAN +void MqttPublishDomoticzFanState(void) +{ + if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { + char svalue[8]; + + int fan_speed = GetFanspeed(); + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); + + domoticz_fan_debounce = millis(); + } +} + +void DomoticzUpdateFanState(void) +{ + if (domoticz_update_flag) { + MqttPublishDomoticzFanState(); + } + domoticz_update_flag = true; +} +#endif + +void MqttPublishDomoticzPowerState(uint8_t device) +{ + if (Settings.flag.mqtt_enabled) { + if ((device < 1) || (device > devices_present)) { device = 1; } + if (Settings.domoticz_relay_idx[device -1]) { +#ifdef USE_SHUTTER + if (domoticz_is_shutter) { + + } else { +#endif +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (device > 1)) { + + } else { +#endif + char svalue[8]; + + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); +#ifdef USE_SONOFF_IFAN + } +#endif +#ifdef USE_SHUTTER + } +#endif + } + } +} + +void DomoticzUpdatePowerState(uint8_t device) +{ + if (domoticz_update_flag) { + MqttPublishDomoticzPowerState(device); + } + domoticz_update_flag = true; +} + +void DomoticzMqttUpdate(void) +{ + if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) { + domoticz_update_timer--; + if (domoticz_update_timer <= 0) { + domoticz_update_timer = Settings.domoticz_update_timer; + for (uint32_t i = 1; i <= devices_present; i++) { +#ifdef USE_SHUTTER + if (domoticz_is_shutter) + { + + break; + } +#endif +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (i > 1)) { + MqttPublishDomoticzFanState(); + break; + } else { +#endif + MqttPublishDomoticzPowerState(i); +#ifdef USE_SONOFF_IFAN + } +#endif + } + } + } +} + +void DomoticzMqttSubscribe(void) +{ + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (uint32_t i = 0; i < maxdev; i++) { + if (Settings.domoticz_relay_idx[i]) { + domoticz_subscribe = true; + } + } + + if (domoticz_subscribe) { + char stopic[TOPSZ]; + snprintf_P(stopic, sizeof(stopic), PSTR(DOMOTICZ_OUT_TOPIC "/#")); + MqttSubscribe(stopic); + } +} +# 219 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_07_domoticz.ino" +bool DomoticzMqttData(void) +{ + domoticz_update_flag = true; + + if (strncasecmp_P(XdrvMailbox.topic, PSTR(DOMOTICZ_OUT_TOPIC), strlen(DOMOTICZ_OUT_TOPIC)) != 0) { + return false; + } + + + if (XdrvMailbox.data_len < 20) { + return true; + } + StaticJsonBuffer<400> jsonBuf; + JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data); + if (!domoticz.success()) { + return true; + } + + + + uint32_t idx = domoticz["idx"]; + int16_t nvalue = -1; + if (domoticz.containsKey("nvalue")) { + nvalue = domoticz["nvalue"]; + } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); + + bool found = false; + if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (uint32_t i = 0; i < maxdev; i++) { + if (idx == Settings.domoticz_relay_idx[i]) { + bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; + bool isShutter = strcmp_P(domoticz["dtype"],PSTR("Light/Switch")) == 0 & strncmp_P(domoticz["switchType"],PSTR("Blinds"), 6) == 0; + + char stemp1[10]; + snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (1 == i)) { + uint8_t svalue = 0; + if (domoticz.containsKey("svalue1")) { + svalue = domoticz["svalue1"]; + } else { + return true; + } + svalue = (nvalue == 2) ? svalue / 10 : 0; + if (GetFanspeed() == svalue) { + return true; + } + if (TimePassedSince(domoticz_fan_debounce) < 1000) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); + found = true; + } else +#endif +#ifdef USE_SHUTTER + if (isShutter) + { + if (domoticz.containsKey("nvalue")) { + nvalue = domoticz["nvalue"]; + } + + uint8_t position = 0; + if (domoticz.containsKey("svalue1")) { + position = domoticz["svalue1"]; + } + if (nvalue != 2) { + position = nvalue == 0 ? 0 : 100; + } + + snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); + XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); + + found = true; + } else +#endif + if (iscolordimmer && 10 == nvalue) { + + JsonObject& color = domoticz["Color"]; + uint16_t level = nvalue = domoticz["svalue1"]; + uint16_t r = color["r"]; r = r * level / 100; + uint16_t g = color["g"]; g = g * level / 100; + uint16_t b = color["b"]; b = b * level / 100; + uint16_t cw = color["cw"]; cw = cw * level / 100; + uint16_t ww = color["ww"]; ww = ww * level / 100; + uint16_t m = 0; + uint16_t t = 0; + if (color.containsKey("m")) { + m = color["m"]; + t = color["t"]; + } + if (2 == m) { + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_BACKLOG)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR(D_CMND_COLORTEMPERATURE " %d;" D_CMND_DIMMER " %d"), changeUIntScale(t, 0, 255, CT_MIN, CT_MAX), level); + } else { + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); + } + found = true; + } + else if ((!iscolordimmer && 2 == nvalue) || + (iscolordimmer && 15 == nvalue)) { + if (domoticz.containsKey("svalue1")) { + nvalue = domoticz["svalue1"]; + } else { + return true; + } + if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + found = true; + } + else if (1 == nvalue || 0 == nvalue) { + if (((power >> i) &1) == (power_t)nvalue) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + found = true; + } + break; + } + } + } + if (!found) { return true; } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); + + domoticz_update_flag = false; + return false; +} + + + +bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg) +{ + bool result = false; + + if (device <= MAX_DOMOTICZ_IDX) { + if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { + Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), + (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); + MqttPublish(domoticz_in_topic); + result = true; + } + } + return result; +} +# 391 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_07_domoticz.ino" +uint8_t DomoticzHumidityState(char *hum) +{ + uint8_t h = atoi(hum); + return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; +} + +void DomoticzSensor(uint8_t idx, char *data) +{ + if (Settings.domoticz_sensor_idx[idx]) { + char dmess[128]; + + memcpy(dmess, mqtt_data, sizeof(dmess)); + if (DZ_AIRQUALITY == idx) { + Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), + Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + } else { + uint8_t nvalue = 0; +#ifdef USE_SHUTTER + if (DZ_SHUTTER == idx) { + uint8_t position = atoi(data); + nvalue = position < 2 ? 0 : (position == 100 ? 1 : 2); + } +#endif + Response_P(DOMOTICZ_MESSAGE, + Settings.domoticz_sensor_idx[idx], nvalue, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + } + MqttPublish(domoticz_in_topic); + memcpy(mqtt_data, dmess, sizeof(dmess)); + } +} + +void DomoticzSensor(uint8_t idx, uint32_t value) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%d"), value); + DomoticzSensor(idx, data); +} + +void DomoticzTempHumSensor(char *temp, char *hum) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temp, hum, DomoticzHumidityState(hum)); + DomoticzSensor(DZ_TEMP_HUM, data); +} + +void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro) +{ + char data[32]; + snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temp, hum, DomoticzHumidityState(hum), baro); + DomoticzSensor(DZ_TEMP_HUM_BARO, data); +} + +void DomoticzSensorPowerEnergy(int power, char *energy) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%d;%s"), power, energy); + DomoticzSensor(DZ_POWER_ENERGY, data); +} + +void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power) +{ + + + + + + int consumed = power; + int produced = 0; + if (power < 0) { + consumed = 0; + produced = -power; + } + char data[64]; + snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced); + DomoticzSensor(DZ_P1_SMART_METER, data); +} + + + + + +void CmndDomoticzIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndIdxNumber(Settings.domoticz_relay_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzKeyIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_key_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzSwitchIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_switch_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzSensorIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzUpdateTimer(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.domoticz_update_timer = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.domoticz_update_timer); +} + + + + + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_DOMOTICZ "dm" + +const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; + +const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = + "

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

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


" + "



" + "

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

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

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

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

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

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

")); + WSContentSend_P(PSTR("

"),"/upl",D_UPL_DONE); + + WSContentStop(); +} + + + +void script_upload(void) { + + + + HTTPUpload& upload = WebServer->upload(); + if (upload.status == UPLOAD_FILE_START) { + char npath[48]; + sprintf(npath,"%s/%s",path,upload.filename.c_str()); + SD.remove(npath); + upload_file=SD.open(npath,FILE_WRITE); + if (!upload_file) Web.upload_error=1; + } else if(upload.status == UPLOAD_FILE_WRITE) { + if (upload_file) upload_file.write(upload.buf,upload.currentSize); + } else if(upload.status == UPLOAD_FILE_END) { + if (upload_file) upload_file.close(); + if (Web.upload_error) { + AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error")); + } + } else { + Web.upload_error=1; + WebServer->send(500, "text/plain", "500: couldn't create file"); + } +} + +uint8_t DownloadFile(char *file) { + File download_file; + WiFiClient download_Client; + + if (!SD.exists(file)) { + AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); + return 0; + } + + download_file=SD.open(file,FILE_READ); + if (!download_file) { + AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); + return 0; + } + + if (download_file.isDirectory()) { + download_file.close(); + return 1; + } + + uint32_t flen=download_file.size(); + + download_Client = WebServer->client(); + WebServer->setContentLength(flen); + + char attachment[100]; + char *cp; + for (uint8_t cnt=strlen(file); cnt>=0; cnt--) { + if (file[cnt]=='/') { + cp=&file[cnt+1]; + break; + } + } + snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp); + WebServer->sendHeader(F("Content-Disposition"), attachment); + WSSend(200, CT_STREAM, ""); + + uint8_t buff[512]; + uint16_t bread; + + + uint8_t cnt=0; + while (download_file.available()) { + bread=download_file.read(buff,sizeof(buff)); + uint16_t bw=download_Client.write((const char*)buff,bread); + if (!bw) break; + cnt++; + if (cnt>7) { + cnt=0; + if (glob_script_mem.script_loglevel&0x80) { + + loop(); + } + } + } + download_file.close(); + download_Client.stop(); + return 0; +} + +#endif + + +void HandleScriptTextareaConfiguration(void) { + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + ScriptSaveSettings(); + HandleConfiguration(); + return; + } +} + +void HandleScriptConfiguration(void) { + + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT); + +#ifdef USE_SCRIPT_FATFS + if (WebServer->hasArg("d1")) { + DownloadFile(glob_script_mem.flink[0]); + } + if (WebServer->hasArg("d2")) { + DownloadFile(glob_script_mem.flink[1]); + } + if (WebServer->hasArg("upl")) { + Script_FileUploadConfiguration(); + } +#endif + + WSContentStart_P(S_CONFIGURE_SCRIPT); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_SCRIPT); + + +#ifdef xSCRIPT_STRIP_COMMENTS + uint16_t ssize=glob_script_mem.script_size; + if (bitRead(Settings.rule_enabled, 1)) ssize*=2; + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",ssize); +#else + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); +#endif + + + if (glob_script_mem.script_ram[0]) { + _WSContentSend(glob_script_mem.script_ram); + } + WSContentSend_P(HTTP_FORM_SCRIPT1b); + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.script_sd_found) { + WSContentSend_P(HTTP_FORM_SCRIPT1d); + if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); + if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); + } +#endif + + WSContentSend_P(HTTP_SCRIPT_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); + } + + +void ScriptSaveSettings(void) { + + if (WebServer->hasArg("c1")) { + bitWrite(Settings.rule_enabled,0,1); + } else { + bitWrite(Settings.rule_enabled,0,0); + } + + + String str = WebServer->arg("t1"); + + if (*str.c_str()) { + + str.replace("\r\n","\n"); + str.replace("\r","\n"); + +#ifdef xSCRIPT_STRIP_COMMENTS + if (bitRead(Settings.rule_enabled, 1)) { + char *sp=(char*)str.c_str(); + char *sp1=sp; + char *dp=sp; + uint8_t flg=0; + while (*sp) { + while (*sp==' ') sp++; + sp1=sp; + sp=strchr(sp,'\n'); + if (!sp) { + flg=1; + } else { + *sp=0; + } + if (*sp1!=';') { + uint8_t slen=strlen(sp1); + if (slen) { + strcpy(dp,sp1); + dp+=slen; + *dp++='\n'; + } + } + if (flg) { + *dp=0; + break; + } + sp++; + } + } +#endif + + strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); + +#ifdef USE_24C256 +#ifndef USE_SCRIPT_FATFS + if (glob_script_mem.flags&1) { + EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); + } +#endif +#endif + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.flags&1) { + SD.remove(FAT_SCRIPT_NAME); + File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE); + file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE); + file.close(); + } +#endif + + } + + if (glob_script_mem.script_mem) { + Scripter_save_pvars(); + free(glob_script_mem.script_mem); + glob_script_mem.script_mem=0; + glob_script_mem.script_mem_size=0; + } + + if (bitRead(Settings.rule_enabled, 0)) { + int16_t res=Init_Scripter(); + if (res) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); + return; + } + Run_Scripter(">B",2,0); + fast_script=Run_Scripter(">F",-2,0); + } +} + +#endif + + +#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) + + +#define HUE_DEV_MVNUM 5 +#define HUE_DEV_NSIZE 16 +struct HUE_SCRIPT { + char name[HUE_DEV_NSIZE]; + uint8_t type; + uint8_t index[HUE_DEV_MVNUM]; + uint8_t vindex[HUE_DEV_MVNUM]; +} hue_script[32]; + + +const char SCRIPT_HUE_LIGHTS_STATUS_JSON1[] PROGMEM = + "{\"state\":" + "{\"on\":{state}," + "{light_status}" + "\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":true}" + ",\"type\":\"{type}\"," + "\"name\":\"{j1\"," + "\"modelid\":\"{m1}\"," + "\"uniqueid\":\"{j2\"," + "\"swversion\":\"5.50.1.19085\"}"; +# 3624 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" +const char SCRIPT_HUE_LIGHTS_STATUS_JSON2[] PROGMEM = +"{\"state\":{" +"\"presence\":{state}," +"\"lastupdated\":\"2017-10-01T12:37:30\"" +"}," +"\"swupdate\":{" +"\"state\":\"noupdates\"," +"\"lastinstall\": null" +"}," +"\"config\":{" +"\"on\":true," +"\"battery\":100," +"\"reachable\":true," +"\"alert\":\"none\"," +"\"ledindication\":false," +"\"usertest\":false," +"\"sensitivity\":2," +"\"sensitivitymax\":2," +"\"pending\":[]" +"}," +"\"name\":\"{j1\"," +"\"type\":\"ZLLPresence\"," +"\"modelid\":\"SML001\"," +"\"manufacturername\":\"Philips\"," +"\"swversion\":\"6.1.0.18912\"," +"\"uniqueid\":\"{j2\"" +"}"; +# 3705 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" +void Script_HueStatus(String *response, uint16_t hue_devs) { + + if (hue_script[hue_devs].type=='p') { + *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON2); + response->replace("{j1",hue_script[hue_devs].name); + response->replace("{j2", GetHueDeviceId(hue_devs)); + uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + response->replace("{state}", (pwr ? "true" : "false")); + return; + } + + *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1); + uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + response->replace("{state}", (pwr ? "true" : "false")); + String light_status = ""; + if (hue_script[hue_devs].index[1]>0) { + + light_status += "\"bri\":"; + uint32_t bri=glob_script_mem.fvars[hue_script[hue_devs].index[1]-1]; + if (bri > 254) bri = 254; + if (bri < 1) bri = 1; + light_status += String(bri); + light_status += ","; + } + if (hue_script[hue_devs].index[2]>0) { + + uint32_t hue=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1]; + + light_status += "\"hue\":"; + light_status += String(hue); + light_status += ","; + } + if (hue_script[hue_devs].index[3]>0) { + + uint32_t sat=glob_script_mem.fvars[hue_script[hue_devs].index[3]-1] ; + if (sat > 254) sat = 254; + if (sat < 1) sat = 1; + light_status += "\"sat\":"; + light_status += String(sat); + light_status += ","; + } + if (hue_script[hue_devs].index[4]>0) { + + uint32_t ct=glob_script_mem.fvars[hue_script[hue_devs].index[4]-1]; + light_status += "\"ct\":"; + light_status += String(ct); + light_status += ","; + } + + float temp; + switch (hue_script[hue_devs].type) { + case 'C': + response->replace("{type}","Color Ligh"); + response->replace("{m1","LST001"); + break; + case 'D': + response->replace("{type}","Dimmable Light"); + response->replace("{m1","LWB004"); + break; + case 'T': + response->replace("{type}","Color Temperature Light"); + response->replace("{m1","LTW011"); + break; + case 'E': + response->replace("{type}","Extended color light"); + response->replace("{m1","LCT007"); + break; + case 'S': + response->replace("{type}","On/Off light"); + response->replace("{m1","LCT007"); + break; + default: + response->replace("{type}","color light"); + response->replace("{m1","LST001"); + break; + } + + response->replace("{light_status}", light_status); + response->replace("{j1",hue_script[hue_devs].name); + response->replace("{j2", GetHueDeviceId(hue_devs)); + +} + +void Script_Check_Hue(String *response) { + if (!bitRead(Settings.rule_enabled, 0)) return; + + uint8_t hue_script_found=Run_Scripter(">H",-2,0); + if (hue_script_found!=99) return; + + char line[128]; + char tmp[128]; + uint8_t hue_devs=0; + uint8_t vindex=0; + char *cp; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + SCRIPT_SKIP_SPACES + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + cp=line; + for (uint32_t i=0; i0) *response+=",\""; + } + *response+=String(EncodeLightId(hue_devs+devices_present+1))+"\":"; + Script_HueStatus(response,hue_devs); + } + + hue_devs++; + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } +#if 0 + if (response) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs); + toLog(">>>>"); + toLog(response->c_str()); + toLog(response->c_str()+LOGSZ); + } +#endif +} + +const char sHUE_LIGHT_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; + +const char sHUE_SENSOR_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; + +const char sHUE_ERROR_JSON[] PROGMEM = + "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; + + + +void Script_Handle_Hue(String *path) { + String response; + int code = 200; + uint16_t tmp = 0; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint16_t ct = 0; + bool resp = false; + + uint8_t device = DecodeLightId(atoi(path->c_str())); + uint8_t index = device-devices_present-1; + + if (WebServer->args()) { + response = "["; + + StaticJsonBuffer<400> jsonBuffer; + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + if (hue_json.containsKey("on")) { + + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "on"); + + bool on = hue_json["on"]; + switch(on) + { + case false : glob_script_mem.fvars[hue_script[index].index[0]-1]=0; + response.replace("{re", "false"); + break; + case true : glob_script_mem.fvars[hue_script[index].index[0]-1]=1; + response.replace("{re", "true"); + break; + } + glob_script_mem.type[hue_script[index].vindex[0]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("bri")) { + tmp = hue_json["bri"]; + bri=tmp; + if (254 <= bri) { bri = 255; } + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "bri"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[1]-1]=bri; + glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("xy")) { + float x, y; + x = hue_json["xy"][0]; + y = hue_json["xy"][1]; + const String &x_str = hue_json["xy"][0]; + const String &y_str = hue_json["xy"][1]; + uint8_t rr,gg,bb; + LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); + LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "xy"); + response.replace("{re", "[" + x_str + "," + y_str + "]"); + glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; + glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; + glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; + glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; + resp = true; + } + + if (hue_json.containsKey("hue")) { + tmp = hue_json["hue"]; + + + hue=tmp; + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "hue"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; + glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("sat")) { + tmp = hue_json["sat"]; + sat=tmp; + if (254 <= sat) { sat = 255; } + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "sat"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; + glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("ct")) { + ct = hue_json["ct"]; + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "ct"); + response.replace("{re", String(ct)); + glob_script_mem.fvars[hue_script[index].index[4]-1]=ct; + glob_script_mem.type[hue_script[index].vindex[4]].bits.changed=1; + resp = true; + } + response += "]"; + + } else { + response = FPSTR(sHUE_ERROR_JSON); + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); + WSSend(code, CT_JSON, response); + if (resp) { + Run_Scripter(">E",2,0); + } +} +#endif + + +#ifdef USE_SCRIPT_SUB_COMMAND +bool Script_SubCmd(void) { + if (!bitRead(Settings.rule_enabled, 0)) return false; + + if (tasm_cmd_activ) return false; + + char command[CMDSZ]; + strlcpy(command,XdrvMailbox.topic,CMDSZ); + uint32_t pl=XdrvMailbox.payload; + char pld[64]; + strlcpy(pld,XdrvMailbox.data,sizeof(pld)); + + char cmdbuff[128]; + char *cp=cmdbuff; + *cp++='#'; + strcpy(cp,XdrvMailbox.topic); + uint8_t tlen=strlen(XdrvMailbox.topic); + cp+=tlen; + if (XdrvMailbox.index > 0) { + *cp++=XdrvMailbox.index|0x30; + tlen++; + } + if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) { + *cp++='('; + strncpy(cp,XdrvMailbox.data,XdrvMailbox.data_len); + cp+=XdrvMailbox.data_len; + *cp++=')'; + *cp=0; + } + + uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); + + if (res) return false; + else { + if (pl>=0) { + Response_P(S_JSON_COMMAND_NVALUE, command, pl); + } else { + Response_P(S_JSON_COMMAND_SVALUE, command, pld); + } + } + return true; +} +#endif + +void execute_script(char *script) { + char *svd_sp=glob_script_mem.scriptptr; + strcat(script,"\n#"); + glob_script_mem.scriptptr=script; + Run_Scripter(">",1,0); + glob_script_mem.scriptptr=svd_sp; +} +#define D_CMND_SCRIPT "Script" +#define D_CMND_SUBSCRIBE "Subscribe" +#define D_CMND_UNSUBSCRIBE "Unsubscribe" + +enum ScriptCommands { CMND_SCRIPT,CMND_SUBSCRIBE, CMND_UNSUBSCRIBE }; +const char kScriptCommands[] PROGMEM = D_CMND_SCRIPT "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE; + +bool ScriptCommand(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t index = XdrvMailbox.index; + + if (tasm_cmd_activ) return false; + + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); + if (-1 == command_code) { + serviced = false; + } + else if ((CMND_SCRIPT == command_code) && (index > 0)) { + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); + break; +#ifdef xSCRIPT_STRIP_COMMENTS + case 2: + bitWrite(Settings.rule_enabled, 1,0); + break; + case 3: + bitWrite(Settings.rule_enabled, 1,1); + break; +#endif + } + } else { + if ('>' == XdrvMailbox.data[0]) { + + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),command,XdrvMailbox.data); + if (bitRead(Settings.rule_enabled, 0)) { + for (uint8_t count=0; count> 1; +} + +void dateTime(uint16_t* date, uint16_t* time) { + + *date = xFAT_DATE(RtcTime.year,RtcTime.month, RtcTime.day_of_month); + + *time = xFAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second); +} + +#endif + + + +#ifdef SUPPORT_MQTT_EVENT +# 4199 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" +bool ScriptMqttData(void) +{ + bool serviced = false; + + toLog(XdrvMailbox.data); + if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { + return false; + } + String sTopic = XdrvMailbox.topic; + String sData = XdrvMailbox.data; + + MQTT_Subscription event_item; + + for (uint32_t index = 0; index < subscriptions.size(); index++) { + event_item = subscriptions.get(index); + + + if (sTopic.startsWith(event_item.Topic)) { + + serviced = true; + String value; + String lkey; + if (event_item.Key.length() == 0) { + value = sData; + } else { + StaticJsonBuffer<400> jsonBuf; + JsonObject& jsonData = jsonBuf.parseObject(sData); + String key1 = event_item.Key; + String key2; + if (!jsonData.success()) break; + int dot; + if ((dot = key1.indexOf('.')) > 0) { + key2 = key1.substring(dot+1); + key1 = key1.substring(0, dot); + lkey=key2; + if (!jsonData[key1][key2].success()) break; + value = (const char *)jsonData[key1][key2]; + } else { + if (!jsonData[key1].success()) break; + value = (const char *)jsonData[key1]; + lkey=key1; + } + } + value.trim(); + char sbuffer[128]; + + if (!strncmp(lkey.c_str(),"Epoch",5)) { + uint32_t ep=atoi(value.c_str())-(uint32_t)EPOCH_OFFSET; + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(),ep); + } else { + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); + } + + execute_script(sbuffer); + } + } + return serviced; +} +# 4274 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" +String ScriptSubscribe(const char *data, int data_len) +{ + MQTT_Subscription subscription_item; + String events; + if (data_len > 0) { + char parameters[data_len+1]; + memcpy(parameters, data, data_len); + parameters[data_len] = '\0'; + String event_name, topic, key; + + char * pos = strtok(parameters, ","); + if (pos) { + event_name = Trim(pos); + pos = strtok(nullptr, ","); + if (pos) { + topic = Trim(pos); + pos = strtok(nullptr, ","); + if (pos) { + key = Trim(pos); + } + } + } + + + if (event_name.length() > 0 && topic.length() > 0) { + + for (uint32_t index=0; index < subscriptions.size(); index++) { + if (subscriptions.get(index).Event.equals(event_name)) { + + String stopic = subscriptions.get(index).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(index); + break; + } + } + + if (!topic.endsWith("#")) { + if (topic.endsWith("/")) { + topic.concat("#"); + } else { + topic.concat("/#"); + } + } + + + subscription_item.Event = event_name; + subscription_item.Topic = topic.substring(0, topic.length() - 2); + subscription_item.Key = key; + subscriptions.add(subscription_item); + + MqttSubscribe(topic.c_str()); + events.concat(event_name + "," + topic + + (key.length()>0 ? "," : "") + + key); + } else { + events = D_JSON_WRONG_PARAMETERS; + } + } else { + + for (uint32_t index=0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + events.concat(subscription_item.Event + "," + subscription_item.Topic + + (subscription_item.Key.length()>0 ? "," : "") + + subscription_item.Key + "; "); + } + } + return events; +} +# 4354 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" +String ScriptUnsubscribe(const char * data, int data_len) +{ + MQTT_Subscription subscription_item; + String events; + if (data_len > 0) { + for (uint32_t index = 0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + if (subscription_item.Event.equalsIgnoreCase(data)) { + String stopic = subscription_item.Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + events = subscription_item.Event; + subscriptions.remove(index); + break; + } + } + } else { + + String stopic; + while (subscriptions.size() > 0) { + events.concat(subscriptions.get(0).Event + "; "); + stopic = subscriptions.get(0).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(0); + } + } + return events; +} +#endif + + + +#ifdef USE_SCRIPT_WEB_DISPLAY + +void Script_Check_HTML_Setvars(void) { + + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("sv")) { + String stmp = WebServer->arg("sv"); + char cmdbuf[64]; + memset(cmdbuf,0,sizeof(cmdbuf)); + char *cp=cmdbuf; + *cp++='>'; + strncpy(cp,stmp.c_str(),sizeof(cmdbuf)-1); + char *cp1=strchr(cp,'_'); + if (!cp1) return; + *cp1=0; + char vname[32]; + strncpy(vname,cp,sizeof(vname)); + *cp1='='; + cp1++; + + struct T_INDEX ind; + uint8_t vtype; + isvar(vname,&vtype,&ind,0,0,0); + if (vtype!=NUM_RES && vtype&STYPE) { + + uint8_t tlen=strlen(cp1); + memmove(cp1+1,cp1,tlen); + *cp1='\"'; + *(cp1+tlen+1)='\"'; + } + + + execute_script(cmdbuf); + Run_Scripter(">E",2,0); + } +} + + +const char SCRIPT_MSG_BUTTONa[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUTTONb[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUT_START[] PROGMEM = + "
"; +const char SCRIPT_MSG_BUT_START_TBL[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUT_STOP[] PROGMEM = + ""; +const char SCRIPT_MSG_BUT_STOP_TBL[] PROGMEM = + "
"; + +const char SCRIPT_MSG_SLIDER[] PROGMEM = + "
%s
%s%s
" + "
"; + +const char SCRIPT_MSG_CHKBOX[] PROGMEM = + "
"; + +const char SCRIPT_MSG_TEXTINP[] PROGMEM = + "
"; + +const char SCRIPT_MSG_NUMINP[] PROGMEM = + "
"; + + +void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { +uint32_t cnt; + for (cnt=0;cntW",-2,0); + if (web_script==99) { + char line[128]; + char tmp[128]; + uint8_t optflg=0; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; i0) { + cp="checked='checked'"; + uval=0; + } else { + cp=""; + uval=1; + } + WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); + + } else if (!strncmp(lin,"bu(",3)) { + char *lp=lin+3; + uint8_t bcnt=0; + char *found=lin; + while (bcnt<4) { + found=strstr(found,"bu("); + if (!found) break; + found+=3; + bcnt++; + } + uint8_t proz=100/bcnt; + if (!optflg && bcnt>1) proz-=2; + if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); + else WSContentSend_PD(SCRIPT_MSG_BUT_START); + for (uint32_t cnt=0;cnt0) { + cp=ontxt; + uval=0; + } else { + cp=offtxt; + uval=1; + } + if (bcnt>1 && cnt==bcnt-1) { + if (!optflg) proz+=2; + } + if (!optflg) { + WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); + } else { + WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); + } + if (bcnt>1 && cnt%s
"),tmp); + } else { + WSContentSend_PD(PSTR("{s}%s{e}"),tmp); + } + } + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } +} +#endif + + +#ifdef USE_SENDMAIL +void script_send_email_body(BearSSL::WiFiClientSecure_light *client) { +uint8_t msect=Run_Scripter(">m",-2,0); + if (msect==99) { + char line[128]; + char tmp[128]; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; iprintln(tmp); + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } else { + client->println("*"); + } +} +#endif + +#ifdef USE_SCRIPT_JSON_EXPORT +void ScriptJsonAppend(void) { + uint8_t web_script=Run_Scripter(">J",-2,0); + if (web_script==99) { + char line[128]; + char tmp[128]; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; iB",2,0); + fast_script=Run_Scripter(">F",-2,0); +#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) + Script_Check_Hue(0); +#endif + } + break; + case FUNC_EVERY_100_MSECOND: + ScripterEvery100ms(); + break; + case FUNC_EVERY_SECOND: + ScriptEverySecond(); + break; + case FUNC_COMMAND: + result = ScriptCommand(); + break; + case FUNC_SET_POWER: +#ifdef SCRIPT_POWER_SECTION + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P",2,0); +#else + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,0); +#endif + break; + case FUNC_RULES_PROCESS: + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_RULES); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); + WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); + +#ifdef USE_SCRIPT_FATFS + WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload); + WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess); + WebServer->on("/upl", HTTP_GET,Script_FileUploadConfiguration); +#endif + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + if (bitRead(Settings.rule_enabled, 0)) { + Run_Scripter(">R",2,0); + Scripter_save_pvars(); + } + break; +#ifdef SUPPORT_MQTT_EVENT + case FUNC_MQTT_DATA: + if (bitRead(Settings.rule_enabled, 0)) { + result = ScriptMqttData(); + } + break; +#endif +#ifdef USE_SCRIPT_WEB_DISPLAY + case FUNC_WEB_SENSOR: + if (bitRead(Settings.rule_enabled, 0)) { + ScriptWebShow(); + } + break; +#endif + +#ifdef USE_SCRIPT_JSON_EXPORT + case FUNC_JSON_APPEND: + if (bitRead(Settings.rule_enabled, 0)) { + ScriptJsonAppend(); + } + break; +#endif + +#ifdef USE_BUTTON_EVENT + case FUNC_BUTTON_PRESSED: + if (bitRead(Settings.rule_enabled, 0)) { + if ((script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) { + script_button[XdrvMailbox.index]=XdrvMailbox.payload; + Run_Scripter(">b",2,0); + } + } + break; +#endif + + } + return result; +} + + + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" +#ifdef USE_KNX +# 51 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" +#define XDRV_11 11 + +#include + +address_t KNX_physs_addr; +address_t KNX_addr; + +#define KNX_Empty 255 + +#define TOGGLE_INHIBIT_TIME 15 + +float last_temp; +float last_hum; +uint8_t toggle_inhibit; + +typedef struct __device_parameters +{ + uint8_t type; + + + + + bool show; + + bool last_state; + + callback_id_t CB_id; + + + + + +} device_parameters_t; + + +device_parameters_t device_param[] = { + { 1, false, false, KNX_Empty }, + { 2, false, false, KNX_Empty }, + { 3, false, false, KNX_Empty }, + { 4, false, false, KNX_Empty }, + { 5, false, false, KNX_Empty }, + { 6, false, false, KNX_Empty }, + { 7, false, false, KNX_Empty }, + { 8, false, false, KNX_Empty }, + { 9, false, false, KNX_Empty }, + { 10, false, false, KNX_Empty }, + { 11, false, false, KNX_Empty }, + { 12, false, false, KNX_Empty }, + { 13, false, false, KNX_Empty }, + { 14, false, false, KNX_Empty }, + { 15, false, false, KNX_Empty }, + { 16, false, false, KNX_Empty }, + { KNX_TEMPERATURE, false, false, KNX_Empty }, + { KNX_HUMIDITY , false, false, KNX_Empty }, + { KNX_ENERGY_VOLTAGE , false, false, KNX_Empty }, + { KNX_ENERGY_CURRENT , false, false, KNX_Empty }, + { KNX_ENERGY_POWER , false, false, KNX_Empty }, + { KNX_ENERGY_POWERFACTOR , false, false, KNX_Empty }, + { KNX_ENERGY_DAILY , false, false, KNX_Empty }, + { KNX_ENERGY_START , false, false, KNX_Empty }, + { KNX_ENERGY_TOTAL , false, false, KNX_Empty }, + { KNX_SLOT1 , false, false, KNX_Empty }, + { KNX_SLOT2 , false, false, KNX_Empty }, + { KNX_SLOT3 , false, false, KNX_Empty }, + { KNX_SLOT4 , false, false, KNX_Empty }, + { KNX_SLOT5 , false, false, KNX_Empty }, + { KNX_Empty, false, false, KNX_Empty} +}; + + +const char * device_param_ga[] = { + D_TIMER_OUTPUT " 1", + D_TIMER_OUTPUT " 2", + D_TIMER_OUTPUT " 3", + D_TIMER_OUTPUT " 4", + D_TIMER_OUTPUT " 5", + D_TIMER_OUTPUT " 6", + D_TIMER_OUTPUT " 7", + D_TIMER_OUTPUT " 8", + D_SENSOR_BUTTON " 1", + D_SENSOR_BUTTON " 2", + D_SENSOR_BUTTON " 3", + D_SENSOR_BUTTON " 4", + D_SENSOR_BUTTON " 5", + D_SENSOR_BUTTON " 6", + D_SENSOR_BUTTON " 7", + D_SENSOR_BUTTON " 8", + D_TEMPERATURE , + D_HUMIDITY , + D_VOLTAGE , + D_CURRENT , + D_POWERUSAGE , + D_POWER_FACTOR , + D_ENERGY_TODAY , + D_ENERGY_YESTERDAY , + D_ENERGY_TOTAL , + D_KNX_TX_SLOT " 1", + D_KNX_TX_SLOT " 2", + D_KNX_TX_SLOT " 3", + D_KNX_TX_SLOT " 4", + D_KNX_TX_SLOT " 5", + nullptr +}; + + +const char *device_param_cb[] = { + D_TIMER_OUTPUT " 1", + D_TIMER_OUTPUT " 2", + D_TIMER_OUTPUT " 3", + D_TIMER_OUTPUT " 4", + D_TIMER_OUTPUT " 5", + D_TIMER_OUTPUT " 6", + D_TIMER_OUTPUT " 7", + D_TIMER_OUTPUT " 8", + D_TIMER_OUTPUT " 1 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 2 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 3 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 4 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 5 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 6 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 7 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 8 " D_BUTTON_TOGGLE, + D_REPLY " " D_TEMPERATURE, + D_REPLY " " D_HUMIDITY, + D_REPLY " " D_VOLTAGE , + D_REPLY " " D_CURRENT , + D_REPLY " " D_POWERUSAGE , + D_REPLY " " D_POWER_FACTOR , + D_REPLY " " D_ENERGY_TODAY , + D_REPLY " " D_ENERGY_YESTERDAY , + D_REPLY " " D_ENERGY_TOTAL , + D_KNX_RX_SLOT " 1", + D_KNX_RX_SLOT " 2", + D_KNX_RX_SLOT " 3", + D_KNX_RX_SLOT " 4", + D_KNX_RX_SLOT " 5", + nullptr +}; + + +#define D_PRFX_KNX "Knx" +#define D_CMND_KNXTXCMND "Tx_Cmnd" +#define D_CMND_KNXTXVAL "Tx_Val" +#define D_CMND_KNX_ENABLED "_Enabled" +#define D_CMND_KNX_ENHANCED "_Enhanced" +#define D_CMND_KNX_PA "_PA" +#define D_CMND_KNX_GA "_GA" +#define D_CMND_KNX_CB "_CB" + +const char kKnxCommands[] PROGMEM = D_PRFX_KNX "|" + D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ; + +void (* const KnxCommand[])(void) PROGMEM = { + &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb }; + +uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 ) +{ + for (uint32_t i = start; i < Settings.knx_GA_registered; ++i) + { + if ( Settings.knx_GA_param[i] == param ) + { + if ( Settings.knx_GA_addr[i] != 0 ) + { + if ( i >= start ) { return i; } + } + } + } + return KNX_Empty; +} + + +uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 ) +{ + for (uint32_t i = start; i < Settings.knx_CB_registered; ++i) + { + if ( Settings.knx_CB_param[i] == param ) + { + if ( Settings.knx_CB_addr[i] != 0 ) + { + if ( i >= start ) { return i; } + } + } + } + return KNX_Empty; +} + + +void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ) +{ + + if ( Settings.knx_GA_registered >= MAX_KNX_GA ) { return; } + if ( GA_FNUM == 0 && GA_AREA == 0 && GA_FDEF == 0 ) { return; } + + + Settings.knx_GA_param[Settings.knx_GA_registered] = GAop; + KNX_addr.ga.area = GA_FNUM; + KNX_addr.ga.line = GA_AREA; + KNX_addr.ga.member = GA_FDEF; + Settings.knx_GA_addr[Settings.knx_GA_registered] = KNX_addr.value; + + Settings.knx_GA_registered++; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), + Settings.knx_GA_registered, + device_param_ga[GAop-1], + GA_FNUM, GA_AREA, GA_FDEF ); +} + + +void KNX_DEL_GA( uint8_t GAnum ) +{ + + uint8_t dest_offset = 0; + uint8_t src_offset = 0; + uint8_t len = 0; + + + Settings.knx_GA_param[GAnum-1] = 0; + + if (GAnum == 1) + { + + src_offset = 1; + + + + len = (Settings.knx_GA_registered - 1); + } + else if (GAnum == Settings.knx_GA_registered) + { + + } + else + { + + + + + dest_offset = GAnum -1 ; + src_offset = dest_offset + 1; + len = (Settings.knx_GA_registered - GAnum); + } + + if (len > 0) + { + memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(uint8_t)); + memmove(Settings.knx_GA_addr + dest_offset, Settings.knx_GA_addr + src_offset, len * sizeof(uint16_t)); + } + + Settings.knx_GA_registered--; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " GA #%d"), + GAnum ); +} + + +void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ) +{ + + if ( Settings.knx_CB_registered >= MAX_KNX_CB ) { return; } + if ( CB_FNUM == 0 && CB_AREA == 0 && CB_FDEF == 0 ) { return; } + + + if ( device_param[CBop-1].CB_id == KNX_Empty ) + { + + device_param[CBop-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[CBop-1]); + + + + + } + + Settings.knx_CB_param[Settings.knx_CB_registered] = CBop; + KNX_addr.ga.area = CB_FNUM; + KNX_addr.ga.line = CB_AREA; + KNX_addr.ga.member = CB_FDEF; + Settings.knx_CB_addr[Settings.knx_CB_registered] = KNX_addr.value; + + knx.callback_assign( device_param[CBop-1].CB_id, KNX_addr ); + + Settings.knx_CB_registered++; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"), + Settings.knx_CB_registered, + CB_FNUM, CB_AREA, CB_FDEF, + device_param_cb[CBop-1] ); +} + + +void KNX_DEL_CB( uint8_t CBnum ) +{ + uint8_t oldparam = Settings.knx_CB_param[CBnum-1]; + uint8_t dest_offset = 0; + uint8_t src_offset = 0; + uint8_t len = 0; + + + knx.callback_unassign(CBnum-1); + Settings.knx_CB_param[CBnum-1] = 0; + + if (CBnum == 1) + { + + src_offset = 1; + + + + len = (Settings.knx_CB_registered - 1); + } + else if (CBnum == Settings.knx_CB_registered) + { + + } + else + { + + + + + dest_offset = CBnum -1 ; + src_offset = dest_offset + 1; + len = (Settings.knx_CB_registered - CBnum); + } + + if (len > 0) + { + memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(uint8_t)); + memmove(Settings.knx_CB_addr + dest_offset, Settings.knx_CB_addr + src_offset, len * sizeof(uint16_t)); + } + + Settings.knx_CB_registered--; + + + if ( KNX_CB_Search( oldparam ) == KNX_Empty ) { + knx.callback_deregister( device_param[oldparam-1].CB_id ); + device_param[oldparam-1].CB_id = KNX_Empty; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " CB #%d"), CBnum ); +} + + +bool KNX_CONFIG_NOT_MATCH(void) +{ + + for (uint32_t i = 0; i < KNX_MAX_device_param; ++i) + { + if ( !device_param[i].show ) { + + + + if ( KNX_GA_Search(i+1) != KNX_Empty ) { return true; } + + if ( i < 8 ) + { + if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } + if ( KNX_CB_Search(i+9) != KNX_Empty ) { return true; } + } + + if ( i > 15 ) + { + if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } + } + } + } + + + for (uint32_t i = 0; i < Settings.knx_GA_registered; ++i) + { + if ( Settings.knx_GA_param[i] != 0 ) + { + if ( Settings.knx_GA_addr[i] == 0 ) + { + return true; + } + } + } + for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) + { + if ( Settings.knx_CB_param[i] != 0 ) + { + if ( Settings.knx_CB_addr[i] == 0 ) + { + return true; + } + } + } + + return false; +} + + +void KNXStart(void) +{ + knx.start(nullptr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_START)); +} + + +void KNX_INIT(void) +{ + + if (Settings.knx_GA_registered > MAX_KNX_GA) { Settings.knx_GA_registered = MAX_KNX_GA; } + if (Settings.knx_CB_registered > MAX_KNX_CB) { Settings.knx_CB_registered = MAX_KNX_CB; } + + + KNX_physs_addr.value = Settings.knx_physsical_addr; + knx.physical_address_set( KNX_physs_addr ); +# 472 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" + for (uint32_t i = 0; i < devices_present; ++i) + { + device_param[i].show = true; + } + for (uint32_t i = GPIO_SWT1; i < GPIO_SWT4 + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } + } + for (uint32_t i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } + } + for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } + } + for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } + } + if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } +#ifdef USE_DS18x20 + if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } +#endif + if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + +#if defined(USE_ENERGY_SENSOR) + + if ( energy_flg != ENERGY_NONE ) { + device_param[KNX_ENERGY_POWER-1].show = true; + device_param[KNX_ENERGY_DAILY-1].show = true; + device_param[KNX_ENERGY_START-1].show = true; + device_param[KNX_ENERGY_TOTAL-1].show = true; + device_param[KNX_ENERGY_VOLTAGE-1].show = true; + device_param[KNX_ENERGY_CURRENT-1].show = true; + device_param[KNX_ENERGY_POWERFACTOR-1].show = true; + } +#endif + +#ifdef USE_RULES + device_param[KNX_SLOT1-1].show = true; + device_param[KNX_SLOT2-1].show = true; + device_param[KNX_SLOT3-1].show = true; + device_param[KNX_SLOT4-1].show = true; + device_param[KNX_SLOT5-1].show = true; +#endif + + + if (KNX_CONFIG_NOT_MATCH()) { + Settings.knx_GA_registered = 0; + Settings.knx_CB_registered = 0; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS)); + } + + + + + uint8_t j; + for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) + { + j = Settings.knx_CB_param[i]; + if ( j > 0 ) + { + device_param[j-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[j-1]); + + + + KNX_addr.value = Settings.knx_CB_addr[i]; + knx.callback_assign( device_param[j-1].CB_id, KNX_addr ); + } + } +} + + +void KNX_CB_Action(message_t const &msg, void *arg) +{ + device_parameters_t *chan = (device_parameters_t *)arg; + if (!(Settings.flag.knx_enabled)) { return; } + + char tempchar[33]; + + if (msg.data_len == 1) { + + tempchar[0] = msg.data[0]; + tempchar[1] = '\0'; + } else { + + float tempvar = knx.data_to_2byte_float(msg.data); + dtostrfd(tempvar,2,tempchar); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"), + msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, + (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, + tempchar, + device_param_cb[(chan->type)-1]); + + switch (msg.ct) + { + case KNX_CT_WRITE: + if (chan->type < 9) + { + ExecuteCommandPower(chan->type, msg.data[0], SRC_KNX); + } + else if (chan->type < 17) + { + if (!toggle_inhibit) { + ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#ifdef USE_RULES + else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) + { + if (!toggle_inhibit) { + char command[25]; + if (msg.data_len == 1) { + + snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]); + } else { + + snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar); + } + ExecuteCommand(command, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#endif + break; + + case KNX_CT_READ: + if (chan->type < 9) + { + knx.answer_1bit(msg.received_on, chan->last_state); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_1bit(msg.received_on, chan->last_state); + knx.answer_1bit(msg.received_on, chan->last_state); + } + } + else if (chan->type == KNX_TEMPERATURE) + { + knx.answer_2byte_float(msg.received_on, last_temp); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_2byte_float(msg.received_on, last_temp); + knx.answer_2byte_float(msg.received_on, last_temp); + } + } + else if (chan->type == KNX_HUMIDITY) + { + knx.answer_2byte_float(msg.received_on, last_hum); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_2byte_float(msg.received_on, last_hum); + knx.answer_2byte_float(msg.received_on, last_hum); + } + } +#ifdef USE_RULES + else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) + { + if (!toggle_inhibit) { + char command[25]; + snprintf_P(command, sizeof(command), PSTR("event KNXRX_REQ%d"), ((chan->type) - KNX_SLOT1 + 1 ) ); + ExecuteCommand(command, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#endif + break; + } +} + + +void KnxUpdatePowerState(uint8_t device, power_t state) +{ + if (!(Settings.flag.knx_enabled)) { return; } + + device_param[device -1].last_state = bitRead(state, device -1); + + + uint8_t i = KNX_GA_Search(device); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[device -1], device_param[device -1].last_state, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(device, i + 1); + } +} + + +void KnxSendButtonPower(void) +{ + if (!(Settings.flag.knx_enabled)) { return; } + + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; + uint32_t device = XdrvMailbox.payload & 0xFF; + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; +# 693 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" + uint8_t i = KNX_GA_Search(device + 8); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, !(state == 0)); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, !(state == 0)); + knx.write_1bit(KNX_addr, !(state == 0)); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[device + 7], !(state == 0), + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(device + 8, i + 1); + } + +} + + +void KnxSensor(uint8_t sensor_type, float value) +{ + if (sensor_type == KNX_TEMPERATURE) + { + last_temp = value; + } else if (sensor_type == KNX_HUMIDITY) + { + last_hum = value; + } + + if (!(Settings.flag.knx_enabled)) { return; } + + uint8_t i = KNX_GA_Search(sensor_type); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_2byte_float(KNX_addr, value); + if (Settings.flag.knx_enable_enhancement) { + knx.write_2byte_float(KNX_addr, value); + knx.write_2byte_float(KNX_addr, value); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "), + device_param_ga[sensor_type -1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(sensor_type, i+1); + } +} + + + + + + +#ifdef USE_WEBSERVER +#ifdef USE_KNX_WEB_MENU +const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; + +const char HTTP_BTN_MENU_KNX[] PROGMEM = + "

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

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" + "" D_KNX_ENABLE "" D_KNX_ENHANCEMENT "

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

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

" + "
" + "" D_KNX_GROUP_ADDRESS_TO_READ "
"; + +const char HTTP_FORM_KNX4[] PROGMEM = + "-> -> ")); + WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_AREA", "GA_FDEF"); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); + for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) + { + if ( Settings.knx_GA_param[i] ) + { + KNX_addr.value = Settings.knx_GA_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1); + } + } + + WSContentSend_P(HTTP_FORM_KNX3); + WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_AREA", "CB_FDEF"); + WSContentSend_P(HTTP_FORM_KNX4); + + uint8_t j; + for (uint32_t i = 0; i < KNX_MAX_device_param ; i++) + { + + if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } + if ( i == 8 ) { j = 0; } + if ( device_param[j].show ) + { + WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); + } + } + WSContentSend_P(PSTR(" ")); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); + + for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) + { + if ( Settings.knx_CB_param[i] ) + { + KNX_addr.value = Settings.knx_CB_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); + } + } + WSContentSend_P(PSTR("
")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); + } + +} + + +void KNX_Save_Settings(void) +{ + String stmp; + address_t KNX_addr; + + Settings.flag.knx_enabled = WebServer->hasArg("b1"); + Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2"); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), + Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement ); + + stmp = WebServer->arg("area"); + KNX_addr.pa.area = stmp.toInt(); + stmp = WebServer->arg("line"); + KNX_addr.pa.line = stmp.toInt(); + stmp = WebServer->arg("member"); + KNX_addr.pa.member = stmp.toInt(); + Settings.knx_physsical_addr = KNX_addr.value; + knx.physical_address_set( KNX_addr ); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "), + KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA: %d"), + Settings.knx_GA_registered ); + for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) + { + KNX_addr.value = Settings.knx_GA_addr[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), + i+1, device_param_ga[Settings.knx_GA_param[i]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB: %d"), + Settings.knx_CB_registered ); + for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) + { + KNX_addr.value = Settings.knx_CB_addr[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), + i+1, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, + device_param_cb[Settings.knx_CB_param[i]-1] ); + } +} + +#endif +#endif + + + + + +void CmndKnxTxCmnd(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { + + + + uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], !(XdrvMailbox.payload == 0), + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); + } + ResponseCmndIdxChar (XdrvMailbox.data ); + } +} + +void CmndKnxTxVal(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { + + + + uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + + float tempvar = CharToFloat(XdrvMailbox.data); + dtostrfd(tempvar,2,XdrvMailbox.data); + + knx.write_2byte_float(KNX_addr, tempvar); + if (Settings.flag.knx_enable_enhancement) { + knx.write_2byte_float(KNX_addr, tempvar); + knx.write_2byte_float(KNX_addr, tempvar); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), + device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], XdrvMailbox.data, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); + } + ResponseCmndIdxChar (XdrvMailbox.data ); + } +} + +void CmndKnxEnabled(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag.knx_enabled = XdrvMailbox.payload; + } + ResponseCmndChar (GetStateText(Settings.flag.knx_enabled) ); +} + +void CmndKnxEnhanced(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag.knx_enable_enhancement = XdrvMailbox.payload; + } + ResponseCmndChar (GetStateText(Settings.flag.knx_enable_enhancement) ); +} + +void CmndKnxPa(void) +{ + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ".") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); + int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2)); + int pa_member = atoi(subStr(sub_string, XdrvMailbox.data, ".", 3)); + + if ( ((pa_area == 0) && (pa_line == 0) && (pa_member == 0)) + || (pa_area > 15) || (pa_line > 15) || (pa_member > 255) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.pa.area = pa_area; + KNX_addr.pa.line = pa_line; + KNX_addr.pa.member = pa_member; + Settings.knx_physsical_addr = KNX_addr.value; + } + } + KNX_addr.value = Settings.knx_physsical_addr; + Response_P (PSTR("{\"%s\":\"%d.%d.%d\"}"), + XdrvMailbox.command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); +} + +void CmndKnxGa(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_GA)) { + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + int ga_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + int ga_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + + if ( ((ga_area == 0) && (ga_line == 0) && (ga_member == 0)) + || (ga_area > 31) || (ga_line > 7) || (ga_member > 255) + || (ga_option < 0) || ((ga_option > KNX_MAX_device_param ) && (ga_option != KNX_Empty)) + || (!device_param[ga_option-1].show) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.ga.area = ga_area; + KNX_addr.ga.line = ga_line; + KNX_addr.ga.member = ga_member; + + if ( XdrvMailbox.index > Settings.knx_GA_registered ) { + Settings.knx_GA_registered ++; + XdrvMailbox.index = Settings.knx_GA_registered; + } + + Settings.knx_GA_addr[XdrvMailbox.index -1] = KNX_addr.value; + Settings.knx_GA_param[XdrvMailbox.index -1] = ga_option; + } else { + if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) { + XdrvMailbox.index = XdrvMailbox.payload; + } else { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + } + if ( XdrvMailbox.index <= Settings.knx_GA_registered ) { + KNX_addr.value = Settings.knx_GA_addr[XdrvMailbox.index -1]; + Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), + XdrvMailbox.command, XdrvMailbox.index, device_param_ga[Settings.knx_GA_param[XdrvMailbox.index-1]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + } + } else { + ResponseCmndNumber (Settings.knx_GA_registered ); + } + } +} + +void CmndKnxCb(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_CB)) { + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + int cb_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + int cb_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + + if ( ((cb_area == 0) && (cb_line == 0) && (cb_member == 0)) + || (cb_area > 31) || (cb_line > 7) || (cb_member > 255) + || (cb_option < 0) || ((cb_option > KNX_MAX_device_param ) && (cb_option != KNX_Empty)) + || (!device_param[cb_option-1].show) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.ga.area = cb_area; + KNX_addr.ga.line = cb_line; + KNX_addr.ga.member = cb_member; + + if ( XdrvMailbox.index > Settings.knx_CB_registered ) { + Settings.knx_CB_registered ++; + XdrvMailbox.index = Settings.knx_CB_registered; + } + + Settings.knx_CB_addr[XdrvMailbox.index -1] = KNX_addr.value; + Settings.knx_CB_param[XdrvMailbox.index -1] = cb_option; + } else { + if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) { + XdrvMailbox.index = XdrvMailbox.payload; + } else { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + } + if ( XdrvMailbox.index <= Settings.knx_CB_registered ) { + KNX_addr.value = Settings.knx_CB_addr[XdrvMailbox.index -1]; + Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), + XdrvMailbox.command, XdrvMailbox.index, device_param_cb[Settings.knx_CB_param[XdrvMailbox.index-1]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + } + } else { + ResponseCmndNumber (Settings.knx_CB_registered ); + } + } +} + + + + + +bool Xdrv11(uint8_t function) +{ + bool result = false; + switch (function) { + case FUNC_LOOP: + if (!global_state.wifi_down) { knx.loop(); } + break; + case FUNC_EVERY_50_MSECOND: + if (toggle_inhibit) { + toggle_inhibit--; + } + break; + case FUNC_ANY_KEY: + KnxSendButtonPower(); + break; +#ifdef USE_WEBSERVER +#ifdef USE_KNX_WEB_MENU + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_KNX); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/kn", HandleKNXConfiguration); + break; +#endif +#endif + case FUNC_COMMAND: + result = DecodeCommand(kKnxCommands, KnxCommand); + break; + case FUNC_PRE_INIT: + KNX_INIT(); + break; + + + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_12_home_assistant.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_12_home_assistant.ino" +#ifdef USE_HOME_ASSISTANT + +#define XDRV_12 12 + + +const char kHAssJsonSensorTypes[] PROGMEM = + D_JSON_TEMPERATURE "|" D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" + D_JSON_APPARENT_POWERUSAGE "|Battery|" D_JSON_CURRENT "|" D_JSON_DISTANCE "|" D_JSON_FREQUENCY "|" D_JSON_HUMIDITY "|" D_JSON_ILLUMINANCE "|" + D_JSON_MOISTURE "|PB0.3|PB0.5|PB1|PB2.5|PB5|PB10|PM1|PM2.5|PM10|" D_JSON_POWERFACTOR "|" D_JSON_POWERUSAGE "|" + D_JSON_REACTIVE_POWERUSAGE "|" D_JSON_TODAY "|" D_JSON_TOTAL "|" D_JSON_VOLTAGE "|" D_JSON_WEIGHT "|" D_JSON_YESTERDAY; +const char kHAssJsonSensorUnits[] PROGMEM = + "|||" + "W|%|A|Cm|Hz|%|LX|" + "%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³||W|" + "W|KWh|KWh|V|Kg|KWh"; +const char kHAssJsonSensorDevCla[] PROGMEM = + "dev_cla\":\"temperature|dev_cla\":\"pressure|dev_cla\":\"pressure|" + "dev_cla\":\"power|dev_cla\":\"battery|ic\":\"mdi:alpha-a-circle-outline|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" + "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" + "ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|" + "dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power"; + + +const char HASS_DISCOVER_SENSOR[] PROGMEM = + ",\"unit_of_meas\":\"%s\",\"%s\"," + "\"frc_upd\":true," + "\"val_tpl\":\"{{value_json['%s']['%s']"; + +const char HASS_DISCOVER_BASE[] PROGMEM = + "{\"name\":\"%s\"," + "\"stat_t\":\"%s\"," + "\"avty_t\":\"%s\"," + "\"pl_avail\":\"" D_ONLINE "\"," + "\"pl_not_avail\":\"" D_OFFLINE "\""; + +const char HASS_DISCOVER_RELAY[] PROGMEM = + ",\"cmd_t\":\"%s\"," + "\"val_tpl\":\"{{value_json.%s}}\"," + "\"pl_off\":\"%s\"," + "\"pl_on\":\"%s\""; + +const char HASS_DISCOVER_BUTTON_TOGGLE[] PROGMEM = + ",\"value_template\":\"{%%if is_state(entity_id,\\\"off\\\")-%%}ON{%%-endif%%}\"," + "\"off_delay\":1"; + +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = + ",\"value_template\":\"{{value_json.%s}}\"," + "\"frc_upd\":true," + "\"pl_on\":\"%s\"," + "\"pl_off\":\"%s\""; + +const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = + ",\"bri_cmd_t\":\"%s\"," + "\"bri_stat_t\":\"%s\"," + "\"bri_scl\":100," + "\"on_cmd_type\":\"%s\"," + "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; + +const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = + ",\"rgb_cmd_t\":\"%s2\"," + "\"rgb_stat_t\":\"%s\"," + "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; + +const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = + ",\"whit_val_cmd_t\":\"%s\"," + "\"whit_val_stat_t\":\"%s\"," + "\"white_value_scale\":100," + "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; + +const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = + ",\"clr_temp_cmd_t\":\"%s\"," + "\"clr_temp_stat_t\":\"%s\"," + "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; + +const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = + ",\"fx_cmd_t\":\"%s\"," + "\"fx_stat_t\":\"%s\"," + "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," + "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; + +const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = + ",\"json_attributes_topic\":\"%s\"," + "\"unit_of_meas\":\" \"," + "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"," + "\"ic\":\"mdi:information-outline\""; + +const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = + ",\"uniq_id\":\"%s\"," + "\"device\":{\"identifiers\":[\"%06X\"]," + "\"connections\":[[\"mac\",\"%s\"]]," + "\"name\":\"%s\"," + "\"model\":\"%s\"," + "\"sw_version\":\"%s%s\"," + "\"manufacturer\":\"Tasmota\"}"; + +const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = + ",\"uniq_id\":\"%s\"," + "\"device\":{\"identifiers\":[\"%06X\"]," + "\"connections\":[[\"mac\",\"%s\"]]}"; + +uint8_t hass_init_step = 0; +uint8_t hass_mode = 0; +int hass_tele_period = 0; + +void TryResponseAppend_P(const char *format, ...) +{ + va_list args; + va_start(args, format); + char dummy[2]; + int dlen = vsnprintf_P(dummy, 1, format, args); + + int mlen = strlen(mqtt_data); + int slen = sizeof(mqtt_data) - 1 - mlen; + if (dlen >= slen) + { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: MQTT discovery failed due to too long topic or friendly name. " + "Please shorten topic and friendly name. Failed to format(%u/%u):"), + dlen, slen); + va_start(args, format); + vsnprintf_P(log_data, sizeof(log_data), format, args); + AddLog(LOG_LEVEL_ERROR); + } + else + { + va_start(args, format); + vsnprintf_P(mqtt_data + mlen, slen, format, args); + } + va_end(args); +} + +void HAssAnnounceRelayLight(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char stemp3[TOPSZ]; + char unique_id[30]; + bool is_light = false; + bool is_topic_light = false; + + for (uint32_t i = 1; i <= MAX_RELAYS; i++) + { + is_light = ((i == devices_present) && (light_type)); + is_topic_light = Settings.flag.hass_light || is_light; + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), + (is_topic_light) ? "switch" : "light", unique_id); + MqttPublish(stopic, true); + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), + (is_topic_light) ? "light" : "switch", unique_id); + + if (Settings.flag.hass_discovery && (i <= devices_present)) + { + char name[33 + 2]; + char value_template[33]; + char prefix[TOPSZ]; + char *command_topic = stemp1; + char *state_topic = stemp2; + char *availability_topic = stemp3; + + if (i > MAX_FRIENDLYNAMES) + { + snprintf_P(name, sizeof(name), PSTR("%s %d"), SettingsText(SET_FRIENDLYNAME1), i); + } + else + { + snprintf_P(name, sizeof(name), SettingsText(SET_FRIENDLYNAME1 + i - 1)); + } + GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); + GetTopic_P(command_topic, CMND, mqtt_topic, value_template); + GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + +#ifdef USE_LIGHT + if (is_light) + { + char *brightness_command_topic = stemp1; + + GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); + strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic, stemp3); + + if (Light.subtype >= LST_RGB) + { + char *rgb_command_topic = stemp1; + + GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); + + char *effect_command_topic = stemp1; + GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); + } + if (LST_RGBW == Light.subtype) + { + char *white_temp_command_topic = stemp1; + + GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); + } + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) + { + char *color_temp_command_topic = stemp1; + + GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); + } + } +#endif + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); + } +} + +void HAssAnnounceButtonSwitch(uint8_t device, char *topic, uint8_t present, uint8_t key, uint8_t toggle) +{ + + + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), key ? "SW" : "BTN", device + 1); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); + + if (Settings.flag.hass_discovery && present) + { + char name[33 + 6]; + char value_template[33]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + char jsoname[8]; + + snprintf_P(name, sizeof(name), PSTR("%s %s%d"), SettingsText(SET_FRIENDLYNAME1), key ? "Switch" : "Button", device + 1); + snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key ? "SWITCH" : "BUTTON", device + 1); + GetPowerDevice(value_template, device + 1, sizeof(value_template), + key + Settings.flag.device_index_enable); + GetTopic_P(state_topic, STAT, mqtt_topic, (PSTR("/'%s'"), jsoname)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + + if (toggle) { + if (!key) { + TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE); + } else { + TryResponseAppend_P(",\"value_template\":\"{%%if is_state(entity_id,\\\"on\\\")-%%}OFF{%%-else-%%}ON{%%-endif%%}\""); + } + } else { + TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2), SettingsText(SET_STATE_TXT1)); + } + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSwitches(void) +{ + char sw_topic[TOPSZ]; + + + char *tmp = SettingsText(SET_MQTT_SWITCH_TOPIC); + Format(sw_topic, tmp, sizeof(sw_topic)); + if (!strcmp_P(sw_topic, "0") || strlen(sw_topic) == 0) + { + for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) + { + uint8_t switch_present = 0; + uint8_t toggle = 1; + + if (pin[GPIO_SWT1 + switch_index] < 99) + { + switch_present = 1; + } + + + if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || + Settings.flag3.button_switch_force_local || + !strcmp(mqtt_topic, sw_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), sw_topic)) + { + toggle = 0; + } + HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 1, toggle); + } + } +} + +void HAssAnnounceButtons(void) +{ + char key_topic[TOPSZ]; + + + char *tmp = SettingsText(SET_MQTT_BUTTON_TOPIC); + Format(key_topic, tmp, sizeof(key_topic)); + if (!strcmp_P(key_topic, "0") || strlen(key_topic) == 0) + { + for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) + { + uint8_t button_present = 0; + uint8_t toggle = 1; + + if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) + { + button_present = 1; + } + else + { + if (pin[GPIO_KEY1 + button_index] < 99) + { + button_present = 1; + } + } + + + if (Settings.flag3.button_switch_force_local || + !strcmp(mqtt_topic, key_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) + { + toggle = 0; + } + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 0, toggle); + } + } +} + +void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, uint8_t subidx) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + mqtt_data[0] = '\0'; + + char subname[20]; + NoAlNumToUnderscore(subname, MultiSubName); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subname); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);; + + if (Settings.flag.hass_discovery) + { + char name[33 + 42]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); + snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_FRIENDLYNAME1), sensorname, MultiSubName); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + + char jname[32]; + int sensor_index = GetCommandCode(jname, sizeof(jname), subsensortype, kHAssJsonSensorTypes); + if (sensor_index > -1) { + char param1[20]; + GetTextIndexed(param1, sizeof(param1), sensor_index, kHAssJsonSensorUnits); + switch (sensor_index) { + case 0: + snprintf_P(param1, sizeof(param1), PSTR("°%c"),TempUnit()); + break; + case 1: + case 2: + snprintf_P(param1, sizeof(param1), PSTR("%s"), PressureUnit().c_str()); + break; + } + char param2[50]; + GetTextIndexed(param2, sizeof(param2), sensor_index, kHAssJsonSensorDevCla); + TryResponseAppend_P(HASS_DISCOVER_SENSOR, param1, param2, sensorname, subsensortype); + if (subidx) { + TryResponseAppend_P(PSTR("[%d]"), subqty -1); + } + } else { + TryResponseAppend_P(HASS_DISCOVER_SENSOR, " ", "ic\":\"mdi:eye", sensorname, subsensortype); + } + TryResponseAppend_P(PSTR("}}\"}")); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSensors(void) +{ + uint8_t hass_xsns_index = 0; + bool is_sensor = true; + uint8_t subqty = 0; + do + { + mqtt_data[0] = '\0'; + int tele_period_save = tele_period; + tele_period = 2; + XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); + tele_period = tele_period_save; + + char sensordata[512]; + strlcpy(sensordata, mqtt_data, sizeof(sensordata)); + + if (strlen(sensordata)) + { + sensordata[0] = '{'; + snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); + + + + StaticJsonBuffer<500> jsonBuffer; + JsonObject &root = jsonBuffer.parseObject(sensordata); + if (!root.success()) + { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: jsonBuffer failed to parse '%s'"), sensordata); + continue; + } + for (auto sensor : root) + { + const char *sensorname = sensor.key; + JsonObject &sensors = sensor.value.as(); + if (!sensors.success()) + { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: JsonObject failed to parse '%s'"), sensordata); + continue; + } + for (auto subsensor : sensors) + { + + if (subsensor.value.is()) { + JsonArray& subsensors = subsensor.value.as(); + subqty = subsensors.size(); + char MultiSubName[20]; + for (int i = 1; i <= subqty; i++) { + snprintf_P(MultiSubName, sizeof(MultiSubName), PSTR("%s %d"), subsensor.key, i); + HAssAnnounceSensor(sensorname, subsensor.key, MultiSubName, i, 1); + } + } else { HAssAnnounceSensor(sensorname, subsensor.key, subsensor.key, 0, 0);} + } + } + } + yield(); + } while (hass_xsns_index != 0); +} + +void HAssAnnounceStatusSensor(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP.getChipId()); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + + if (Settings.flag.hass_discovery) + { + char name[33 + 7]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + + snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_FRIENDLYNAME1)); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(), + SettingsText(SET_FRIENDLYNAME1), ModuleName().c_str(), my_version, my_image); + + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); +} + +void HAssPublishStatus(void) +{ + Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," + "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," + "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," + "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," + "\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_CMND_IPADDRESS "\":\"%s\"," + "\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), + my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getSdkVersion(), ModuleName().c_str(), + GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), + Settings.bootcount, Settings.save_flag, WiFi.localIP().toString().c_str(), + WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); +} + +void HAssDiscovery(void) +{ + + if (Settings.flag.hass_discovery) + { + Settings.flag.mqtt_response = 0; + Settings.flag.decimal_text = 1; + Settings.flag3.hass_tele_on_power = 1; + Settings.light_scheme = 0; + } + + if (Settings.flag.hass_discovery || (1 == hass_mode)) + { + + HAssAnnounceRelayLight(); + + + HAssAnnounceButtons(); + + + HAssAnnounceSwitches(); + + + HAssAnnounceSensors(); + + + HAssAnnounceStatusSensor(); + } +} + +void HAssDiscover(void) +{ + hass_mode = 1; + hass_init_step = 1; +} + +void HAssAnyKey(void) +{ + if (!Settings.flag.hass_discovery) + { + return; + } + + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; + uint32_t device = XdrvMailbox.payload & 0xFF; + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; + + char scommand[CMDSZ]; + snprintf_P(scommand, sizeof(scommand), PSTR("%s%d"), (key) ? "SWITCH" : "BUTTON", device); + char stopic[TOPSZ]; + + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P(S_JSON_COMMAND_SVALUE, PSTR(D_RSLT_STATE), GetStateText(state)); + MqttPublish(stopic); +} + + + + + +bool Xdrv12(uint8_t function) +{ + bool result = false; + + if (Settings.flag.mqtt_enabled) + { + switch (function) + { + case FUNC_EVERY_SECOND: + if (hass_init_step) + { + hass_init_step--; + if (!hass_init_step) + { + HAssDiscovery(); + } + } + else if (Settings.flag.hass_discovery && Settings.tele_period) + { + hass_tele_period++; + if (hass_tele_period >= Settings.tele_period) + { + hass_tele_period = 0; + + mqtt_data[0] = '\0'; + HAssPublishStatus(); + } + } + break; + case FUNC_ANY_KEY: + HAssAnyKey(); + break; + case FUNC_MQTT_INIT: + hass_mode = 0; + hass_init_step = 2; + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_13_display.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_13_display.ino" +#if defined(USE_I2C) || defined(USE_SPI) +#ifdef USE_DISPLAY + +#define XDRV_13 13 + +#include +#include + +Renderer *renderer; + +enum ColorType { COLOR_BW, COLOR_COLOR }; + +#ifndef MAXBUTTONS +#define MAXBUTTONS 16 +#endif + +#ifdef USE_TOUCH_BUTTONS +VButton *buttons[MAXBUTTONS]; +#endif + + + +uint16_t fg_color = 1; +uint16_t bg_color = 0; +uint8_t color_type = COLOR_BW; +uint8_t auto_draw=1; + +const uint8_t DISPLAY_MAX_DRIVERS = 16; +const uint8_t DISPLAY_MAX_COLS = 44; +const uint8_t DISPLAY_MAX_ROWS = 32; + +const uint8_t DISPLAY_LOG_ROWS = 32; + +#define D_PRFX_DISPLAY "Display" +#define D_CMND_DISP_ADDRESS "Address" +#define D_CMND_DISP_COLS "Cols" +#define D_CMND_DISP_DIMMER "Dimmer" +#define D_CMND_DISP_MODE "Mode" +#define D_CMND_DISP_MODEL "Model" +#define D_CMND_DISP_REFRESH "Refresh" +#define D_CMND_DISP_ROWS "Rows" +#define D_CMND_DISP_SIZE "Size" +#define D_CMND_DISP_FONT "Font" +#define D_CMND_DISP_ROTATE "Rotate" +#define D_CMND_DISP_TEXT "Text" +#define D_CMND_DISP_WIDTH "Width" +#define D_CMND_DISP_HEIGHT "Height" + +enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND, + FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER, + FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_DRAW_FRAME, + FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_LINE, + FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE, + FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE, + FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING, FUNC_DISPLAY_ONOFF }; + +enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; + +const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" + "|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" + D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" + D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; + +void (* const DisplayCommand[])(void) PROGMEM = { + &CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh, + &CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont, + &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress }; + +char *dsp_str; + +uint16_t dsp_x; +uint16_t dsp_y; +uint16_t dsp_x2; +uint16_t dsp_y2; +uint16_t dsp_rad; +uint16_t dsp_color; +int16_t dsp_len; +int16_t disp_xpos = 0; +int16_t disp_ypos = 0; + +uint8_t disp_power = 0; +uint8_t disp_device = 0; +uint8_t disp_refresh = 1; +uint8_t disp_autodraw = 1; +uint8_t dsp_init; +uint8_t dsp_font; +uint8_t dsp_flag; +uint8_t dsp_on; + +#ifdef USE_DISPLAY_MODES1TO5 + +char **disp_log_buffer; +char **disp_screen_buffer; +char disp_temp[2]; +char disp_pres[5]; + +uint8_t disp_log_buffer_cols = 0; +uint8_t disp_log_buffer_idx = 0; +uint8_t disp_log_buffer_ptr = 0; +uint8_t disp_screen_buffer_cols = 0; +uint8_t disp_screen_buffer_rows = 0; +bool disp_subscribed = false; + +#endif + + + +void DisplayInit(uint8_t mode) +{ + if (renderer) { + renderer->DisplayInit(mode, Settings.display_size, Settings.display_rotate, Settings.display_font); + } + else { + dsp_init = mode; + XdspCall(FUNC_DISPLAY_INIT); + } +} + +void DisplayClear(void) +{ + XdspCall(FUNC_DISPLAY_CLEAR); +} + +void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_len = len; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_HLINE); +} + +void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_len = len; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_VLINE); +} + +void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_LINE); +} + +void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_rad = rad; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_CIRCLE); +} + +void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_rad = rad; + dsp_color = color; + XdspCall(FUNC_DISPLAY_FILL_CIRCLE); +} + +void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_RECTANGLE); +} + +void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_FILL_RECTANGLE); +} + +void DisplayDrawFrame(void) +{ + XdspCall(FUNC_DISPLAY_DRAW_FRAME); +} + +void DisplaySetSize(uint8_t size) +{ + Settings.display_size = size &3; + XdspCall(FUNC_DISPLAY_TEXT_SIZE); +} + +void DisplaySetFont(uint8_t font) +{ + Settings.display_font = font &3; + XdspCall(FUNC_DISPLAY_FONT_SIZE); +} + +void DisplaySetRotation(uint8_t rotation) +{ + Settings.display_rotate = rotation &3; + XdspCall(FUNC_DISPLAY_ROTATION); +} + +void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + dsp_x = x; + dsp_y = y; + dsp_str = str; + dsp_color = color; + dsp_flag = flag; + XdspCall(FUNC_DISPLAY_DRAW_STRING); +} + +void DisplayOnOff(uint8_t on) +{ + dsp_on = on; + XdspCall(FUNC_DISPLAY_ONOFF); +} + + + + +uint8_t fatoiv(char *cp,float *res) { + uint8_t index=0; + *res=CharToFloat(cp); + while (*cp) { + if ((*cp>='0' && *cp<='9') || (*cp=='-') || (*cp=='.')) { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +uint8_t atoiv(char *cp, int16_t *res) +{ + uint8_t index = 0; + *res = atoi(cp); + while (*cp) { + if ((*cp>='0' && *cp<='9') || (*cp=='-')) { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +uint8_t atoiV(char *cp, uint16_t *res) +{ + uint8_t index = 0; + *res = atoi(cp); + while (*cp) { + if (*cp>='0' && *cp<='9') { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +void alignright(char *string) { + uint16_t slen=strlen(string); + uint16_t len=slen; + while (len) { + + if (string[len-1]!=' ') { + break; + } + len--; + } + uint16_t diff=slen-len; + if (diff>0) { + + memmove(&string[diff],string,len); + memset(string,' ',diff); + } +} + +char *get_string(char *buff,uint8_t len,char *cp) { +uint8_t index=0; + while (*cp!=':') { + buff[index]=*cp++; + index++; + if (index>=len) break; + } + buff[index]=0; + cp++; + return cp; +} + +#define ESCAPE_CHAR '~' + + +uint32_t decode_te(char *line) { + uint32_t skip = 0; + char sbuf[3],*cp; + while (*line) { + if (*line==ESCAPE_CHAR) { + cp=line+1; + if (*cp!=0 && *cp==ESCAPE_CHAR) { + + memmove(cp,cp+1,strlen(cp)); + skip++; + } else { + + if (strlen(cp)<2) { + + return skip; + } + + sbuf[0]=*(cp); + sbuf[1]=*(cp+1); + sbuf[2]=0; + *line=strtol(sbuf,0,16); + + memmove(cp,cp+2,strlen(cp)-1); + skip += 2; + } + } + line++; + } + return skip; +} + + + +#define DISPLAY_BUFFER_COLS 128 + +void DisplayText(void) +{ + uint8_t lpos; + uint8_t escape = 0; + uint8_t var; + int16_t lin = 0; + int16_t col = 0; + int16_t fill = 0; + int16_t temp; + int16_t temp1; + float ftemp; + + char linebuf[DISPLAY_BUFFER_COLS]; + char *dp = linebuf; + char *cp = XdrvMailbox.data; + + memset(linebuf, ' ', sizeof(linebuf)); + linebuf[sizeof(linebuf)-1] = 0; + *dp = 0; + + while (*cp) { + if (!escape) { + + if (*cp == '[') { + escape = 1; + cp++; + + if ((uint32_t)dp - (uint32_t)linebuf) { + if (!fill) { *dp = 0; } + if (col > 0 && lin > 0) { + + if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); + else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); + } else { + + if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + } + memset(linebuf, ' ', sizeof(linebuf)); + linebuf[sizeof(linebuf)-1] = 0; + dp = linebuf; + } + } else { + + if (dp < (linebuf + DISPLAY_BUFFER_COLS)) { *dp++ = *cp++; } + } + } else { + + if (*cp == ']') { + escape = 0; + cp++; + } else { + + switch (*cp++) { + case 'z': + + if (!renderer) DisplayClear(); + else renderer->fillScreen(bg_color); + disp_xpos = 0; + disp_ypos = 0; + col = 0; + lin = 0; + break; + case 'i': + + DisplayInit(DISPLAY_INIT_PARTIAL); + break; + case 'I': + + DisplayInit(DISPLAY_INIT_FULL); + break; + case 'o': + if (!renderer) { + DisplayOnOff(0); + } else { + renderer->DisplayOnff(0); + } + break; + case 'O': + if (!renderer) { + DisplayOnOff(1); + } else { + renderer->DisplayOnff(1); + } + break; + case 'x': + + var = atoiv(cp, &disp_xpos); + cp += var; + break; + case 'y': + + var = atoiv(cp, &disp_ypos); + cp += var; + break; + case 'l': + + var = atoiv(cp, &lin); + cp += var; + + break; + case 'c': + + var = atoiv(cp, &col); + cp += var; + + break; + case 'C': + + if (*cp=='i') { + + cp++; + var = atoiv(cp, &temp); + if (renderer) ftemp=renderer->GetColorFromIndex(temp); + } else { + + var = fatoiv(cp,&ftemp); + } + fg_color=ftemp; + cp += var; + if (renderer) renderer->setTextColor(fg_color,bg_color); + break; + case 'B': + + if (*cp=='i') { + + cp++; + var = atoiv(cp, &temp); + if (renderer) ftemp=renderer->GetColorFromIndex(temp); + } else { + var = fatoiv(cp,&ftemp); + } + bg_color=ftemp; + cp += var; + if (renderer) renderer->setTextColor(fg_color,bg_color); + break; + case 'p': + + var = atoiv(cp, &fill); + cp += var; + linebuf[fill] = 0; + break; +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) + case 'P': + { char *ep=strchr(cp,':'); + if (ep) { + *ep=0; + ep++; + Draw_RGB_Bitmap(cp,disp_xpos,disp_ypos); + cp=ep; + } + } + break; +#endif + case 'h': + + var = atoiv(cp, &temp); + cp += var; + if (temp < 0) { + if (renderer) renderer->writeFastHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); + else DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); + } else { + if (renderer) renderer->writeFastHLine(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawHLine(disp_xpos, disp_ypos, temp, fg_color); + } + disp_xpos += temp; + break; + case 'v': + + var = atoiv(cp, &temp); + cp += var; + if (temp < 0) { + if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); + else DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); + } else { + if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawVLine(disp_xpos, disp_ypos, temp, fg_color); + } + disp_ypos += temp; + break; + case 'L': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->writeLine(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, fg_color); + disp_xpos += temp; + disp_ypos += temp1; + break; + case 'k': + + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->drawCircle(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawCircle(disp_xpos, disp_ypos, temp, fg_color); + break; + case 'K': + + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color); + break; + case 'r': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->drawRect(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); + break; + case 'R': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->fillRect(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); + break; + case 'u': + + { int16_t rad; + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + cp++; + var = atoiv(cp, &rad); + cp += var; + if (renderer) renderer->drawRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); + + } + break; + case 'U': + + { int16_t rad; + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + cp++; + var = atoiv(cp, &rad); + cp += var; + if (renderer) renderer->fillRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); + + } + break; + + case 't': + if (*cp=='S') { + cp++; + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { + snprintf_P(dp, 9, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + dp += 8; + } + } else { + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -5) { + snprintf_P(dp, 6, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute); + dp += 5; + } + } + break; + case 'T': + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { + snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year%2000); + dp += 8; + } + break; + case 'd': + + if (renderer) renderer->Updateframe(); + else DisplayDrawFrame(); + break; + case 'D': + + auto_draw=*cp&3; + if (renderer) renderer->setDrawMode(auto_draw>>1); + cp += 1; + break; + case 's': + + if (renderer) renderer->setTextSize(*cp&7); + else DisplaySetSize(*cp&3); + cp += 1; + break; + case 'f': + + if (renderer) renderer->setTextFont(*cp&7); + else DisplaySetFont(*cp&7); + cp += 1; + break; + case 'a': + + if (renderer) renderer->setRotation(*cp&3); + else DisplaySetRotation(*cp&3); + cp+=1; + break; + +#ifdef USE_GRAPH + case 'G': + + if (*cp=='d') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + var=atoiv(cp,&temp1); + cp+=var; + RedrawGraph(temp,temp1); + break; + } +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) + if (*cp=='s') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + + char bbuff[128]; + cp=get_string(bbuff,sizeof(bbuff),cp); + Save_graph(temp,bbuff); + break; + } + if (*cp=='r') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + + char bbuff[128]; + cp=get_string(bbuff,sizeof(bbuff),cp); + Restore_graph(temp,bbuff); + break; + } +#endif + { int16_t num,gxp,gyp,gxs,gys,dec,icol; + float ymin,ymax; + var=atoiv(cp,&num); + cp+=var; + cp++; + var=atoiv(cp,&gxp); + cp+=var; + cp++; + var=atoiv(cp,&gyp); + cp+=var; + cp++; + var=atoiv(cp,&gxs); + cp+=var; + cp++; + var=atoiv(cp,&gys); + cp+=var; + cp++; + var=atoiv(cp,&dec); + cp+=var; + cp++; + var=fatoiv(cp,&ymin); + cp+=var; + cp++; + var=fatoiv(cp,&ymax); + cp+=var; + if (color_type==COLOR_COLOR) { + + cp++; + var=atoiv(cp,&icol); + cp+=var; + } else { + icol=0; + } + DefineGraph(num,gxp,gyp,gxs,gys,dec,ymin,ymax,icol); + } + break; + case 'g': + { float temp; + int16_t num; + var=atoiv(cp,&num); + cp+=var; + cp++; + var=fatoiv(cp,&temp); + cp+=var; + AddValue(num,temp); + } + break; +#endif + +#ifdef USE_AWATCH + case 'w': + var = atoiv(cp, &temp); + cp += var; + DrawAClock(temp); + break; +#endif + +#ifdef USE_TOUCH_BUTTONS + case 'b': + { int16_t num,gxp,gyp,gxs,gys,outline,fill,textcolor,textsize; + var=atoiv(cp,&num); + cp+=var; + cp++; + uint8_t bflags=num>>8; + num=num%MAXBUTTONS; + var=atoiv(cp,&gxp); + cp+=var; + cp++; + var=atoiv(cp,&gyp); + cp+=var; + cp++; + var=atoiv(cp,&gxs); + cp+=var; + cp++; + var=atoiv(cp,&gys); + cp+=var; + cp++; + var=atoiv(cp,&outline); + cp+=var; + cp++; + var=atoiv(cp,&fill); + cp+=var; + cp++; + var=atoiv(cp,&textcolor); + cp+=var; + cp++; + var=atoiv(cp,&textsize); + cp+=var; + cp++; + + char bbuff[32]; + cp=get_string(bbuff,sizeof(bbuff),cp); + + if (buttons[num]) { + delete buttons[num]; + } + if (renderer) { + buttons[num]= new VButton(); + if (buttons[num]) { + buttons[num]->vpower=bflags; + buttons[num]->initButtonUL(renderer,gxp,gyp,gxs,gys,renderer->GetColorFromIndex(outline),\ + renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); + if (!bflags) { + + buttons[num]->xdrawButton(bitRead(power,num)); + } else { + + buttons[num]->vpower&=0x7f; + buttons[num]->xdrawButton(buttons[num]->vpower&0x80); + } + } + } + } + break; +#endif + default: + + Response_P(PSTR("Unknown Escape")); + goto exit; + break; + } + } + } + } + exit: + + dp -= decode_te(linebuf); + if ((uint32_t)dp - (uint32_t)linebuf) { + if (!fill) { + *dp = 0; + } else { + linebuf[abs(fill)] = 0; + } + if (fill<0) { + + alignright(linebuf); + } + if (col > 0 && lin > 0) { + + if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); + else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); + } else { + + if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + } + } + + if (auto_draw&1) { + if (renderer) renderer->Updateframe(); + else DisplayDrawFrame(); + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void DisplayClearScreenBuffer(void) +{ + if (disp_screen_buffer_cols) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + memset(disp_screen_buffer[i], 0, disp_screen_buffer_cols); + } + } +} + +void DisplayFreeScreenBuffer(void) +{ + if (disp_screen_buffer != nullptr) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + if (disp_screen_buffer[i] != nullptr) { free(disp_screen_buffer[i]); } + } + free(disp_screen_buffer); + disp_screen_buffer_cols = 0; + disp_screen_buffer_rows = 0; + } +} + +void DisplayAllocScreenBuffer(void) +{ + if (!disp_screen_buffer_cols) { + disp_screen_buffer_rows = Settings.display_rows; + disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); + if (disp_screen_buffer != nullptr) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); + if (disp_screen_buffer[i] == nullptr) { + DisplayFreeScreenBuffer(); + break; + } + } + } + if (disp_screen_buffer != nullptr) { + disp_screen_buffer_cols = Settings.display_cols[0] +1; + DisplayClearScreenBuffer(); + } + } +} + +void DisplayReAllocScreenBuffer(void) +{ + DisplayFreeScreenBuffer(); + DisplayAllocScreenBuffer(); +} + +void DisplayFillScreen(uint32_t line) +{ + uint32_t len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]); + if (len) { + memset(disp_screen_buffer[line] + strlen(disp_screen_buffer[line]), 0x20, len); + disp_screen_buffer[line][disp_screen_buffer_cols -1] = 0; + } +} + + + +void DisplayClearLogBuffer(void) +{ + if (disp_log_buffer_cols) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + memset(disp_log_buffer[i], 0, disp_log_buffer_cols); + } + } +} + +void DisplayFreeLogBuffer(void) +{ + if (disp_log_buffer != nullptr) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + if (disp_log_buffer[i] != nullptr) { free(disp_log_buffer[i]); } + } + free(disp_log_buffer); + disp_log_buffer_cols = 0; + } +} + +void DisplayAllocLogBuffer(void) +{ + if (!disp_log_buffer_cols) { + disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); + if (disp_log_buffer != nullptr) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); + if (disp_log_buffer[i] == nullptr) { + DisplayFreeLogBuffer(); + break; + } + } + } + if (disp_log_buffer != nullptr) { + disp_log_buffer_cols = Settings.display_cols[0] +1; + DisplayClearLogBuffer(); + } + } +} + +void DisplayReAllocLogBuffer(void) +{ + DisplayFreeLogBuffer(); + DisplayAllocLogBuffer(); +} + +void DisplayLogBufferAdd(char* txt) +{ + if (disp_log_buffer_cols) { + strlcpy(disp_log_buffer[disp_log_buffer_idx], txt, disp_log_buffer_cols); + disp_log_buffer_idx++; + if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) { disp_log_buffer_idx = 0; } + } +} + +char* DisplayLogBuffer(char temp_code) +{ + char* result = nullptr; + if (disp_log_buffer_cols) { + if (disp_log_buffer_idx != disp_log_buffer_ptr) { + result = disp_log_buffer[disp_log_buffer_ptr]; + disp_log_buffer_ptr++; + if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; } + + char *pch = strchr(result, '~'); + if (pch != nullptr) { result[pch - result] = temp_code; } + } + } + return result; +} + +void DisplayLogBufferInit(void) +{ + if (Settings.display_mode) { + disp_log_buffer_idx = 0; + disp_log_buffer_ptr = 0; + disp_refresh = Settings.display_refresh; + + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); + snprintf_P(disp_pres, sizeof(disp_pres), PressureUnit().c_str()); + + DisplayReAllocLogBuffer(); + + char buffer[40]; + snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), my_version, my_image); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); + DisplayLogBufferAdd(buffer); + + snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active)); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str()); + DisplayLogBufferAdd(buffer); + if (!global_state.wifi_down) { + snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), WiFi.localIP().toString().c_str()); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI())); + DisplayLogBufferAdd(buffer); + } + } +} + + + + + +enum SensorQuantity { + JSON_TEMPERATURE, + JSON_HUMIDITY, JSON_LIGHT, JSON_NOISE, JSON_AIRQUALITY, + JSON_PRESSURE, JSON_PRESSUREATSEALEVEL, + JSON_ILLUMINANCE, + JSON_GAS, + JSON_YESTERDAY, JSON_TOTAL, JSON_TODAY, + JSON_PERIOD, + JSON_POWERFACTOR, JSON_COUNTER, JSON_ANALOG_INPUT, JSON_UV_LEVEL, + JSON_CURRENT, + JSON_VOLTAGE, + JSON_POWERUSAGE, + JSON_CO2, + JSON_FREQUENCY }; +const char kSensorQuantity[] PROGMEM = + D_JSON_TEMPERATURE "|" + D_JSON_HUMIDITY "|" D_JSON_LIGHT "|" D_JSON_NOISE "|" D_JSON_AIRQUALITY "|" + D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" + D_JSON_ILLUMINANCE "|" + D_JSON_GAS "|" + D_JSON_YESTERDAY "|" D_JSON_TOTAL "|" D_JSON_TODAY "|" + D_JSON_PERIOD "|" + D_JSON_POWERFACTOR "|" D_JSON_COUNTER "|" D_JSON_ANALOG_INPUT "|" D_JSON_UV_LEVEL "|" + D_JSON_CURRENT "|" + D_JSON_VOLTAGE "|" + D_JSON_POWERUSAGE "|" + D_JSON_CO2 "|" + D_JSON_FREQUENCY ; + +void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value) +{ + char quantity[TOPSZ]; + char buffer[Settings.display_cols[0] +1]; + char spaces[Settings.display_cols[0]]; + char source[Settings.display_cols[0] - Settings.display_cols[1]]; + char svalue[Settings.display_cols[1] +1]; + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("DisplayJsonValue")); +#endif + + memset(spaces, 0x20, sizeof(spaces)); + spaces[sizeof(spaces) -1] = '\0'; + snprintf_P(source, sizeof(source), PSTR("%s%s%s%s"), topic, (strlen(topic))?"/":"", mkey, spaces); + + int quantity_code = GetCommandCode(quantity, sizeof(quantity), mkey, kSensorQuantity); + if ((-1 == quantity_code) || !strcmp_P(mkey, S_RSLT_POWER)) { + return; + } + if (JSON_TEMPERATURE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s~%s"), value, disp_temp); + } + else if ((quantity_code >= JSON_HUMIDITY) && (quantity_code <= JSON_AIRQUALITY)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s%%"), value); + } + else if ((quantity_code >= JSON_PRESSURE) && (quantity_code <= JSON_PRESSUREATSEALEVEL)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s"), value, disp_pres); + } + else if (JSON_ILLUMINANCE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_LUX), value); + } + else if (JSON_GAS == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOOHM), value); + } + else if ((quantity_code >= JSON_YESTERDAY) && (quantity_code <= JSON_TODAY)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOWATTHOUR), value); + } + else if (JSON_PERIOD == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATTHOUR), value); + } + else if ((quantity_code >= JSON_POWERFACTOR) && (quantity_code <= JSON_UV_LEVEL)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s"), value); + } + else if (JSON_CURRENT == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_AMPERE), value); + } + else if (JSON_VOLTAGE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_VOLT), value); + } + else if (JSON_POWERUSAGE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATT), value); + } + else if (JSON_CO2 == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value); + } + else if (JSON_FREQUENCY == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_HERTZ), value); + } + snprintf_P(buffer, sizeof(buffer), PSTR("%s %s"), source, svalue); + + + + DisplayLogBufferAdd(buffer); +} + +void DisplayAnalyzeJson(char *topic, char *json) +{ +# 1145 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_13_display.ino" + String jsonStr = json; + + StaticJsonBuffer<1024> jsonBuf; + JsonObject &root = jsonBuf.parseObject(jsonStr); + if (root.success()) { + + const char *unit; + unit = root[D_JSON_TEMPERATURE_UNIT]; + if (unit) { + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), unit); + } + unit = root[D_JSON_PRESSURE_UNIT]; + if (unit) { + snprintf_P(disp_pres, sizeof(disp_pres), PSTR("%s"), unit); + } + + for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) { + JsonVariant value = it->value; + if (value.is()) { + JsonObject& Object2 = value; + for (JsonObject::iterator it2 = Object2.begin(); it2 != Object2.end(); ++it2) { + JsonVariant value2 = it2->value; + if (value2.is()) { + JsonObject& Object3 = value2; + for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) { + const char* value = it3->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it3->key, value); + } + } + } else { + const char* value = it2->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it2->key, value); + } + } + } + } else { + const char* value = it->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it->key, value); + } + } + } + } +} + +void DisplayMqttSubscribe(void) +{ + + + + + + + if (Settings.display_model && (Settings.display_mode &0x04)) { + + char stopic[TOPSZ]; + char ntopic[TOPSZ]; + + ntopic[0] = '\0'; + strlcpy(stopic, SettingsText(SET_MQTT_FULLTOPIC), sizeof(stopic)); + char *tp = strtok(stopic, "/"); + while (tp != nullptr) { + if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { + break; + } + strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); + tp = strtok(nullptr, "/"); + } + strncat(ntopic, SettingsText(SET_MQTTPREFIX3), sizeof(ntopic) - strlen(ntopic) -1); + strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); + MqttSubscribe(ntopic); + disp_subscribed = true; + } else { + disp_subscribed = false; + } +} + +bool DisplayMqttData(void) +{ + if (disp_subscribed) { + char stopic[TOPSZ]; + + snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), SettingsText(SET_MQTTPREFIX3)); + char *tp = strstr(XdrvMailbox.topic, stopic); + if (tp) { + if (Settings.display_mode &0x04) { + tp = tp + strlen(stopic); + char *topic = strtok(tp, "/"); + DisplayAnalyzeJson(topic, XdrvMailbox.data); + } + return true; + } + } + return false; +} + +void DisplayLocalSensor(void) +{ + if ((Settings.display_mode &0x02) && (0 == tele_period)) { + char no_topic[1] = { 0 }; + + DisplayAnalyzeJson(no_topic, mqtt_data); + } +} + +#endif + + + + + +void DisplayInitDriver(void) +{ + XdspCall(FUNC_DISPLAY_INIT_DRIVER); + + if (renderer) { + renderer->setTextFont(Settings.display_font); + renderer->setTextSize(Settings.display_size); + } + + + + + if (Settings.display_model) { + devices_present++; + disp_device = devices_present; + +#ifndef USE_DISPLAY_MODES1TO5 + Settings.display_mode = 0; +#else + DisplayLogBufferInit(); +#endif + } +} + +void DisplaySetPower(void) +{ + disp_power = bitRead(XdrvMailbox.index, disp_device -1); + + + + if (Settings.display_model) { + if (!renderer) { + XdspCall(FUNC_DISPLAY_POWER); + } else { + renderer->DisplayOnff(disp_power); + } + } +} + + + + + +void CmndDisplay(void) +{ + Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\"" + D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" + D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), + Settings.display_model, Settings.display_width, Settings.display_height, + Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, + Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); +} + +void CmndDisplayModel(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) { + uint32_t last_display_model = Settings.display_model; + Settings.display_model = XdrvMailbox.payload; + if (XdspCall(FUNC_DISPLAY_MODEL)) { + restart_flag = 2; + } else { + Settings.display_model = last_display_model; + } + } + ResponseCmndNumber(Settings.display_model); +} + +void CmndDisplayWidth(void) +{ + if (XdrvMailbox.payload > 0) { + if (XdrvMailbox.payload != Settings.display_width) { + Settings.display_width = XdrvMailbox.payload; + restart_flag = 2; + } + } + ResponseCmndNumber(Settings.display_width); +} + +void CmndDisplayHeight(void) +{ + if (XdrvMailbox.payload > 0) { + if (XdrvMailbox.payload != Settings.display_height) { + Settings.display_height = XdrvMailbox.payload; + restart_flag = 2; + } + } + ResponseCmndNumber(Settings.display_height); +} + +void CmndDisplayMode(void) +{ +#ifdef USE_DISPLAY_MODES1TO5 + + + + + + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { + uint32_t last_display_mode = Settings.display_mode; + Settings.display_mode = XdrvMailbox.payload; + + if (disp_subscribed != (Settings.display_mode &0x04)) { + restart_flag = 2; + } else { + if (last_display_mode && !Settings.display_mode) { + DisplayInit(DISPLAY_INIT_MODE); + if (renderer) renderer->fillScreen(bg_color); + else DisplayClear(); + } else { + DisplayLogBufferInit(); + DisplayInit(DISPLAY_INIT_MODE); + } + } + } +#endif + ResponseCmndNumber(Settings.display_mode); +} + +void CmndDisplayDimmer(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; + if (Settings.display_dimmer && !(disp_power)) { + ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY); + } + else if (!Settings.display_dimmer && disp_power) { + ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); + } + if (renderer) renderer->dim(Settings.display_dimmer); + } + ResponseCmndNumber(Settings.display_dimmer); +} + +void CmndDisplaySize(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { + Settings.display_size = XdrvMailbox.payload; + if (renderer) renderer->setTextSize(Settings.display_size); + else DisplaySetSize(Settings.display_size); + } + ResponseCmndNumber(Settings.display_size); +} + +void CmndDisplayFont(void) +{ + if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) { + Settings.display_font = XdrvMailbox.payload; + if (renderer) renderer->setTextFont(Settings.display_font); + else DisplaySetFont(Settings.display_font); + } + ResponseCmndNumber(Settings.display_font); +} + +void CmndDisplayRotate(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { + if (Settings.display_rotate != XdrvMailbox.payload) { +# 1428 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_13_display.ino" + Settings.display_rotate = XdrvMailbox.payload; + DisplayInit(DISPLAY_INIT_MODE); +#ifdef USE_DISPLAY_MODES1TO5 + DisplayLogBufferInit(); +#endif + } + } + ResponseCmndNumber(Settings.display_rotate); +} + +void CmndDisplayText(void) +{ + if (disp_device && XdrvMailbox.data_len > 0) { +#ifndef USE_DISPLAY_MODES1TO5 + DisplayText(); +#else + if (!Settings.display_mode) { + DisplayText(); + } else { + DisplayLogBufferAdd(XdrvMailbox.data); + } +#endif + ResponseCmndChar(XdrvMailbox.data); + } +} + +void CmndDisplayAddress(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { + Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]); + } +} + +void CmndDisplayRefresh(void) +{ + if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { + Settings.display_refresh = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.display_refresh); +} + +void CmndDisplayColumns(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { + Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload; +#ifdef USE_DISPLAY_MODES1TO5 + if (1 == XdrvMailbox.index) { + DisplayLogBufferInit(); + DisplayReAllocScreenBuffer(); + } +#endif + } + ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]); + } +} + +void CmndDisplayRows(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { + Settings.display_rows = XdrvMailbox.payload; +#ifdef USE_DISPLAY_MODES1TO5 + DisplayLogBufferInit(); + DisplayReAllocScreenBuffer(); +#endif + } + ResponseCmndNumber(Settings.display_rows); +} + + + + + +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) +void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { + if (!renderer) return; + + + File fp; + fp=SD.open(file,FILE_READ); + if (!fp) return; + uint16_t xsize; + fp.read((uint8_t*)&xsize,2); + uint16_t ysize; + fp.read((uint8_t*)&ysize,2); + +#if 1 +#define XBUFF 128 + uint16_t xdiv=xsize/XBUFF; + renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); + for(int16_t j=0; j=2) renderer->pushColors(rgb,len/2,true); + } + OsWatchLoop(); + } + renderer->setAddrWindow(0,0,0,0); +#else + for(int16_t j=0; jwritePixel(xp+i,yp,rgb); + } + delay(0); + OsWatchLoop(); + yp++; + } +#endif + fp.close(); +} +#endif + +#ifdef USE_AWATCH +#define MINUTE_REDUCT 4 + +#ifndef pi +#define pi 3.14159265359 +#endif + + +void DrawAClock(uint16_t rad) { + if (!renderer) return; + float frad=rad; + uint16_t hred=frad/3.0; + renderer->fillCircle(disp_xpos, disp_ypos, rad, bg_color); + renderer->drawCircle(disp_xpos, disp_ypos, rad, fg_color); + renderer->fillCircle(disp_xpos, disp_ypos, 4, fg_color); + for (uint8_t count=0; count<60; count+=5) { + float p1=((float)count*(pi/30)-(pi/2)); + uint8_t len; + if ((count%15)==0) { + len=4; + } else { + len=2; + } + renderer->writeLine(disp_xpos+((float)(rad-len)*cosf(p1)), disp_ypos+((float)(rad-len)*sinf(p1)), disp_xpos+(frad*cosf(p1)), disp_ypos+(frad*sinf(p1)), fg_color); + } + + + float hour=((float)RtcTime.hour*60.0+(float)RtcTime.minute)/60.0; + float temp=(hour*(pi/6.0)-(pi/2.0)); + renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-hred)*cosf(temp),disp_ypos+(frad-hred)*sinf(temp), fg_color); + + + temp=((float)RtcTime.minute*(pi/30.0)-(pi/2.0)); + renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-MINUTE_REDUCT)*cosf(temp),disp_ypos+(frad-MINUTE_REDUCT)*sinf(temp), fg_color); +} +#endif + + +#ifdef USE_GRAPH + +typedef union { + uint8_t data; + struct { + uint8_t overlay : 1; + uint8_t draw : 1; + uint8_t nu3 : 1; + uint8_t nu4 : 1; + uint8_t nu5 : 1; + uint8_t nu6 : 1; + uint8_t nu7 : 1; + uint8_t nu8 : 1; + }; +} GFLAGS; + +struct GRAPH { + uint16_t xp; + uint16_t yp; + uint16_t xs; + uint16_t ys; + float ymin; + float ymax; + float range; + uint32_t x_time; + uint32_t last_ms; + uint32_t last_ms_redrawn; + int16_t decimation; + uint16_t dcnt; + uint32_t summ; + uint16_t xcnt; + uint8_t *values; + uint8_t xticks; + uint8_t yticks; + uint8_t last_val; + uint8_t color_index; + GFLAGS flags; +}; + + +struct GRAPH *graph[NUM_GRAPHS]; + +#define TICKLEN 4 +void ClrGraph(uint16_t num) { + struct GRAPH *gp=graph[num]; + + uint16_t xticks=gp->xticks; + uint16_t yticks=gp->yticks; + uint16_t count; + + + if (gp->flags.overlay) return; + + renderer->fillRect(gp->xp+1,gp->yp+1,gp->xs-2,gp->ys-2,bg_color); + + if (xticks) { + float cxp=gp->xp,xd=(float)gp->xs/(float)xticks; + for (count=0; countwriteFastVLine(cxp,gp->yp+gp->ys-TICKLEN,TICKLEN,fg_color); + cxp+=xd; + } + } + if (yticks) { + if (gp->ymin<0 && gp->ymax>0) { + + float cxp=0; + float czp=gp->yp+(gp->ymax/gp->range); + while (cxpxs) { + renderer->writeFastHLine(gp->xp+cxp,czp,2,fg_color); + cxp+=6.0; + } + + float cyp=0,yd=gp->ys/yticks; + for (count=0; countgp->yp) { + renderer->writeFastHLine(gp->xp,czp-cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp-cyp,TICKLEN,fg_color); + } + if ((czp+cyp)<(gp->yp+gp->ys)) { + renderer->writeFastHLine(gp->xp,czp+cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp+cyp,TICKLEN,fg_color); + } + cyp+=yd; + } + } else { + float cyp=gp->yp,yd=gp->ys/yticks; + for (count=0; countwriteFastHLine(gp->xp,cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,cyp,TICKLEN,fg_color); + cyp+=yd; + } + } + } +} + + +void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol) { + if (!renderer) return; + uint8_t rflg=0; + if (xs<0) { + rflg=1; + xs=abs(xs); + } + struct GRAPH *gp; + uint16_t count; + uint16_t index=num%NUM_GRAPHS; + if (!graph[index]) { + gp=(struct GRAPH*)calloc(sizeof(struct GRAPH),1); + if (!gp) return; + graph[index]=gp; + } else { + gp=graph[index]; + if (rflg) { + RedrawGraph(index,1); + return; + } + } + + + gp->xticks=(num>>4)&0x3f; + gp->yticks=(num>>10)&0x3f; + gp->xp=xp; + gp->yp=yp; + gp->xs=xs; + gp->ys=ys; + if (!dec) dec=1; + gp->decimation=dec; + if (dec>0) { + + gp->x_time=((float)dec*60000.0)/(float)xs; + gp->last_ms=millis()+gp->x_time; + } + gp->ymin=ymin; + gp->ymax=ymax; + gp->range=(ymax-ymin)/ys; + gp->xcnt=0; + gp->dcnt=0; + gp->summ=0; + if (gp->values) free(gp->values); + gp->values=(uint8_t*) calloc(1,xs+2); + if (!gp->values) { + free(gp); + graph[index]=0; + return; + } + + gp->values[0]=0; + + gp->last_ms_redrawn=millis(); + + if (!icol) icol=1; + gp->color_index=icol; + gp->flags.overlay=0; + gp->flags.draw=1; + + + if (index>0) { + for (uint8_t count=0; countxp==gp1->xp) && (gp->yp==gp1->yp)) { + gp->flags.overlay=1; + break; + } + } + } + } + + + renderer->drawRect(xp,yp,xs,ys,fg_color); + + ClrGraph(index); + +} + + +void DisplayCheckGraph() { + int16_t count; + struct GRAPH *gp; + for (count=0;countdecimation>0) { + + while (millis()>gp->last_ms) { + gp->last_ms+=gp->x_time; + uint8_t val; + if (gp->dcnt) { + val=gp->summ/gp->dcnt; + gp->dcnt=0; + gp->summ=0; + gp->last_val=val; + } else { + val=gp->last_val; + } + AddGraph(count,val); + } + } + } + } +} + + +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) +#include + +void Save_graph(uint8_t num, char *path) { + if (!renderer) return; + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + File fp; + SD.remove(path); + fp=SD.open(path,FILE_WRITE); + if (!fp) return; + char str[32]; + sprintf_P(str,PSTR("%d\t%d\t%d\t"),gp->xcnt,gp->xs,gp->ys); + fp.print(str); + dtostrfd(gp->ymin,2,str); + fp.print(str); + fp.print("\t"); + dtostrfd(gp->ymax,2,str); + fp.print(str); + fp.print("\t"); + for (uint32_t count=0;countxs;count++) { + dtostrfd(gp->values[count],0,str); + fp.print(str); + fp.print("\t"); + } + fp.print("\n"); + fp.close(); +} +void Restore_graph(uint8_t num, char *path) { + if (!renderer) return; + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + File fp; + fp=SD.open(path,FILE_READ); + if (!fp) return; + char vbuff[32]; + char *cp=vbuff; + uint8_t buf[2]; + uint8_t findex=0; + + for (uint32_t count=0;count<=gp->xs+4;count++) { + cp=vbuff; + findex=0; + while (fp.available()) { + fp.read(buf,1); + if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { + break; + } else { + *cp++=buf[0]; + findex++; + if (findex>=sizeof(vbuff)-1) break; + } + } + *cp=0; + if (count<=4) { + if (count==0) gp->xcnt=atoi(vbuff); + } else { + gp->values[count-5]=atoi(vbuff); + } + } + fp.close(); + RedrawGraph(num,1); +} +#endif + +void RedrawGraph(uint8_t num, uint8_t flags) { + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + if (!flags) { + gp->flags.draw=0; + return; + } + if (!renderer) return; + + gp->flags.draw=1; + uint16_t linecol=fg_color; + + if (color_type==COLOR_COLOR) { + linecol=renderer->GetColorFromIndex(gp->color_index); + } + + if (!gp->flags.overlay) { + + renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); + + ClrGraph(index); + } + + for (uint16_t count=0;countxs-1;count++) { + renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); + } +} + + +void AddGraph(uint8_t num,uint8_t val) { + struct GRAPH *gp=graph[num]; + if (!renderer) return; + + uint16_t linecol=fg_color; + if (color_type==COLOR_COLOR) { + linecol=renderer->GetColorFromIndex(gp->color_index); + } + gp->xcnt++; + if (gp->xcnt>gp->xs) { + gp->xcnt=gp->xs; + int16_t count; + + for (count=0;countxs-1;count++) { + gp->values[count]=gp->values[count+1]; + } + gp->values[gp->xcnt-1]=val; + + if (!gp->flags.draw) return; + + + if (millis()-gp->last_ms_redrawn>1000) { + gp->last_ms_redrawn=millis(); + + if (!gp->flags.overlay) { + + renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); + + ClrGraph(num); + } + + for (count=0;countxs-1;count++) { + renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); + } + } + } else { + + gp->values[gp->xcnt]=val; + if (!gp->flags.draw) return; + renderer->writeLine(gp->xp+gp->xcnt-1,gp->yp+gp->ys-gp->values[gp->xcnt-1]-1,gp->xp+gp->xcnt,gp->yp+gp->ys-gp->values[gp->xcnt]-1,linecol); + } +} + + + +void AddValue(uint8_t num,float fval) { + + num=num%NUM_GRAPHS; + struct GRAPH *gp=graph[num]; + if (!gp) return; + + if (fval>gp->ymax) fval=gp->ymax; + if (fvalymin) fval=gp->ymin; + + int16_t val; + val=(fval-gp->ymin)/gp->range; + + if (val>gp->ys-1) val=gp->ys-1; + if (val<0) val=0; + + + gp->summ+=val; + gp->dcnt++; + + + if (gp->decimation<0) { + if (gp->dcnt>=-gp->decimation) { + gp->dcnt=0; + + val=gp->summ/-gp->decimation; + gp->summ=0; + + AddGraph(num,val); + } + } +} +#endif + + + + + +bool Xdrv13(uint8_t function) +{ + bool result = false; + + if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { + switch (function) { + case FUNC_PRE_INIT: + DisplayInitDriver(); +#ifdef USE_GRAPH + for (uint8_t count=0;count + +TasmotaSerial *MP3Player; + + + + + +#define D_CMND_MP3 "MP3" + +const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; +const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; +const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device|Reset|DAC"; + + + + + +enum MP3_Commands { + CMND_MP3_TRACK, + CMND_MP3_PLAY, + CMND_MP3_PAUSE, + CMND_MP3_STOP, + CMND_MP3_VOLUME, + CMND_MP3_EQ, + CMND_MP3_DEVICE, + CMND_MP3_RESET, + CMND_MP3_DAC }; + + + + + + +#define MP3_CMD_RESET_VALUE 0 + +#define MP3_CMD_TRACK 0x03 +#define MP3_CMD_PLAY 0x0d +#define MP3_CMD_PAUSE 0x0e +#define MP3_CMD_STOP 0x16 +#define MP3_CMD_VOLUME 0x06 +#define MP3_CMD_EQ 0x07 +#define MP3_CMD_DEVICE 0x09 +#define MP3_CMD_RESET 0x0C +#define MP3_CMD_DAC 0x1A + + + + + + +uint16_t MP3_Checksum(uint8_t *array) +{ + uint16_t checksum = 0; + for (uint32_t i = 0; i < 6; i++) { + checksum += array[i]; + } + checksum = checksum^0xffff; + return (checksum+1); +} + + + + + + +void MP3PlayerInit(void) { + MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); + + if (MP3Player->begin(9600)) { + MP3Player->flush(); + delay(1000); + MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); + delay(3000); + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); + } + return; +} +# 159 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_14_mp3.ino" +void MP3_CMD(uint8_t mp3cmd,uint16_t val) { + uint8_t i = 0; + uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; + cmd[3] = mp3cmd; + cmd[4] = 0; + cmd[5] = val>>8; + cmd[6] = val; + uint16_t chks = MP3_Checksum(&cmd[1]); + cmd[7] = chks>>8; + cmd[8] = chks; + MP3Player->write(cmd, sizeof(cmd)); + delay(1000); + if (mp3cmd == MP3_CMD_RESET) { + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); + } + return; +} + + + + + +bool MP3PlayerCmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_MP3); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); + + switch (command_code) { + case CMND_MP3_TRACK: + case CMND_MP3_VOLUME: + case CMND_MP3_EQ: + case CMND_MP3_DEVICE: + case CMND_MP3_DAC: + + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_MP3_TRACK) { MP3_CMD(MP3_CMD_TRACK, XdrvMailbox.payload); } + if (command_code == CMND_MP3_VOLUME) { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } + if (command_code == CMND_MP3_EQ) { MP3_CMD(MP3_CMD_EQ, XdrvMailbox.payload); } + if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } + if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } + } + Response_P(S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_MP3_PLAY: + case CMND_MP3_PAUSE: + case CMND_MP3_STOP: + case CMND_MP3_RESET: + + if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } + if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } + if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } + if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } + Response_P(S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); + break; + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + + +bool Xdrv14(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_MP3_DFR562] < 99) { + switch (function) { + case FUNC_PRE_INIT: + MP3PlayerInit(); + break; + case FUNC_COMMAND: + result = MP3PlayerCmd(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_15_pca9685.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_15_pca9685.ino" +#ifdef USE_I2C +#ifdef USE_PCA9685 + + + + + + +#define XDRV_15 15 +#define XI2C_01 1 + +#define PCA9685_REG_MODE1 0x00 +#define PCA9685_REG_LED0_ON_L 0x06 +#define PCA9685_REG_PRE_SCALE 0xFE + +#ifndef USE_PCA9685_ADDR + #define USE_PCA9685_ADDR 0x40 +#endif +#ifndef USE_PCA9685_FREQ + #define USE_PCA9685_FREQ 50 +#endif + +bool pca9685_detected = false; +uint16_t pca9685_freq = USE_PCA9685_FREQ; +uint16_t pca9685_pin_pwm_value[16]; + +void PCA9685_Detect(void) +{ + if (I2cActive(USE_PCA9685_ADDR)) { return; } + + uint8_t buffer; + if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x20); + if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { + if (0x20 == buffer) { + pca9685_detected = true; + I2cSetActiveFound(USE_PCA9685_ADDR, "PCA9685"); + PCA9685_Reset(); + } + } + } +} + +void PCA9685_Reset(void) +{ + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); + PCA9685_SetPWMfreq(USE_PCA9685_FREQ); + for (uint32_t pin=0;pin<16;pin++) { + PCA9685_SetPWM(pin,0,false); + pca9685_pin_pwm_value[pin] = 0; + } + Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); +} + +void PCA9685_SetPWMfreq(double freq) { + + + + + if (freq > 23 && freq < 1527) { + pca9685_freq=freq; + } else { + pca9685_freq=50; + } + uint8_t pre_scale_osc = round(25000000/(4096*pca9685_freq))-1; + if (1526 == pca9685_freq) pre_scale_osc=0xFF; + uint8_t current_mode1 = I2cRead8(USE_PCA9685_ADDR, PCA9685_REG_MODE1); + uint8_t sleep_mode1 = (current_mode1&0x7F) | 0x10; + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, sleep_mode1); + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_PRE_SCALE, pre_scale_osc); + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, current_mode1 | 0xA0); +} + +void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off) { + uint8_t led_reg = PCA9685_REG_LED0_ON_L + 4 * pin; + uint32_t led_data = 0; + I2cWrite8(USE_PCA9685_ADDR, led_reg, on); + I2cWrite8(USE_PCA9685_ADDR, led_reg+1, (on >> 8)); + I2cWrite8(USE_PCA9685_ADDR, led_reg+2, off); + I2cWrite8(USE_PCA9685_ADDR, led_reg+3, (off >> 8)); +} + +void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { + if (4096 == pwm) { + PCA9685_SetPWM_Reg(pin, 4096, 0); + } else { + PCA9685_SetPWM_Reg(pin, 0, pwm); + } + pca9685_pin_pwm_value[pin] = pwm; +} + +bool PCA9685_Command(void) +{ + bool serviced = true; + bool validpin = false; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((new_freq >= 24) && (new_freq <= 1526)) { + PCA9685_SetPWMfreq(new_freq); + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); + return serviced; + } + } else { + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); + return serviced; + } + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWM")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (paramcount > 2) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { + PCA9685_SetPWM(pin, 4096, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); + serviced = true; + return serviced; + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { + PCA9685_SetPWM(pin, 0, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); + serviced = true; + return serviced; + } + uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { + PCA9685_SetPWM(pin, pwm, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); + serviced = true; + return serviced; + } + } + } + } + return serviced; +} + +void PCA9685_OutputTelemetry(bool telemetry) +{ + ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); + for (uint32_t pin=0;pin<16;pin++) { + ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); + } + ResponseAppend_P(PSTR("\"END\":1}}")); + if (telemetry) { + MqttPublishTeleSensor(); + } +} + +bool Xdrv15(uint8_t function) +{ + if (!I2cEnabled(XI2C_01)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + PCA9685_Detect(); + } + else if (pca9685_detected) { + switch (function) { + case FUNC_EVERY_SECOND: + if (tele_period == 0) { + PCA9685_OutputTelemetry(true); + } + break; + case FUNC_COMMAND_DRIVER: + if (XDRV_15 == XdrvMailbox.index) { + result = PCA9685_Command(); + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +#ifdef USE_LIGHT +#ifdef USE_TUYA_MCU + +#define XDRV_16 16 +#define XNRG_16 16 + +#ifndef TUYA_DIMMER_ID +#define TUYA_DIMMER_ID 0 +#endif + +#define TUYA_CMD_HEARTBEAT 0x00 +#define TUYA_CMD_QUERY_PRODUCT 0x01 +#define TUYA_CMD_MCU_CONF 0x02 +#define TUYA_CMD_WIFI_STATE 0x03 +#define TUYA_CMD_WIFI_RESET 0x04 +#define TUYA_CMD_WIFI_SELECT 0x05 +#define TUYA_CMD_SET_DP 0x06 +#define TUYA_CMD_STATE 0x07 +#define TUYA_CMD_QUERY_STATE 0x08 + +#define TUYA_LOW_POWER_CMD_WIFI_STATE 0x02 +#define TUYA_LOW_POWER_CMD_WIFI_RESET 0x03 +#define TUYA_LOW_POWER_CMD_WIFI_CONFIG 0x04 +#define TUYA_LOW_POWER_CMD_STATE 0x05 + +#define TUYA_TYPE_BOOL 0x01 +#define TUYA_TYPE_VALUE 0x02 +#define TUYA_TYPE_STRING 0x03 +#define TUYA_TYPE_ENUM 0x04 + +#define TUYA_BUFFER_SIZE 256 + +#include + +TasmotaSerial *TuyaSerial = nullptr; + +struct TUYA { + uint16_t new_dim = 0; + bool ignore_dim = false; + uint8_t cmd_status = 0; + uint8_t cmd_checksum = 0; + uint8_t data_len = 0; + uint8_t wifi_state = -2; + uint8_t heartbeat_timer = 0; +#ifdef USE_ENERGY_SENSOR + uint32_t lastPowerCheckTime = 0; +#endif + char *buffer = nullptr; + int byte_counter = 0; + bool low_power_mode = false; + bool send_success_next_second = false; +} Tuya; + + +enum TuyaSupportedFunctions { + TUYA_MCU_FUNC_NONE, + TUYA_MCU_FUNC_SWT1 = 1, + TUYA_MCU_FUNC_SWT2, + TUYA_MCU_FUNC_SWT3, + TUYA_MCU_FUNC_SWT4, + TUYA_MCU_FUNC_REL1 = 11, + TUYA_MCU_FUNC_REL2, + TUYA_MCU_FUNC_REL3, + TUYA_MCU_FUNC_REL4, + TUYA_MCU_FUNC_REL5, + TUYA_MCU_FUNC_REL6, + TUYA_MCU_FUNC_REL7, + TUYA_MCU_FUNC_REL8, + TUYA_MCU_FUNC_DIMMER = 21, + TUYA_MCU_FUNC_POWER = 31, + TUYA_MCU_FUNC_CURRENT, + TUYA_MCU_FUNC_VOLTAGE, + TUYA_MCU_FUNC_BATTERY_STATE, + TUYA_MCU_FUNC_BATTERY_PERCENTAGE, + TUYA_MCU_FUNC_REL1_INV = 41, + TUYA_MCU_FUNC_REL2_INV, + TUYA_MCU_FUNC_REL3_INV, + TUYA_MCU_FUNC_REL4_INV, + TUYA_MCU_FUNC_REL5_INV, + TUYA_MCU_FUNC_REL6_INV, + TUYA_MCU_FUNC_REL7_INV, + TUYA_MCU_FUNC_REL8_INV, + TUYA_MCU_FUNC_LOWPOWER_MODE = 51, + TUYA_MCU_FUNC_LAST = 255 +}; + +const char kTuyaCommand[] PROGMEM = "|" + D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE; + +void (* const TuyaCommand[])(void) PROGMEM = { + &CmndTuyaMcu, &CmndTuyaSend +}; +# 126 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +void CmndTuyaSend(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if (XdrvMailbox.data_len > 0) { + + char *p; + char *data; + uint8_t i = 0; + uint8_t dpId = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + if ( i == 0) { + dpId = strtoul(str, nullptr, 0); + } else { + data = str; + } + i++; + } + + if (1 == XdrvMailbox.index) { + TuyaSendBool(dpId, strtoul(data, nullptr, 0)); + } else if (2 == XdrvMailbox.index) { + TuyaSendValue(dpId, strtoull(data, nullptr, 0)); + } else if (3 == XdrvMailbox.index) { + TuyaSendString(dpId, data); + } else if (4 == XdrvMailbox.index) { + TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); + } + } + ResponseCmndDone(); + } +} + + + + + + + +void CmndTuyaMcu(void) { + if (XdrvMailbox.data_len > 0) { + char *p; + uint8_t i = 0; + uint8_t parm[3] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + parm[i] = strtoul(str, nullptr, 0); + i++; + } + + if (TuyaFuncIdValid(parm[0])) { + TuyaAddMcuFunc(parm[0], parm[1]); + restart_flag = 2; + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); + } + + } + + Response_P(PSTR("{\"" D_CMND_TUYA_MCU "\":[")); + bool added = false; + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].fnid != 0) { + if (added) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"fnId\":%d,\"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid); + added = true; + } + } + ResponseAppend_P(PSTR("]}")); +} + + + + + +void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { + bool added = false; + + if (fnId == 0 || dpId == 0) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) { + Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; + Settings.tuya_fnid_map[i].dpid = 0; + break; + } + } + } else { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) { + if (!added) { + Settings.tuya_fnid_map[i].fnid = fnId; + Settings.tuya_fnid_map[i].dpid = dpId; + added = true; + } else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { + Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; + Settings.tuya_fnid_map[i].dpid = 0; + } + } + } + } + UpdateDevices(); +} + +void UpdateDevices() { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + uint8_t fnId = Settings.tuya_fnid_map[i].fnid; + if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) { + + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { + bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1); + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { + bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); + } + + } + } +} + +inline bool TuyaFuncIdValid(uint8_t fnId) { + return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) || + (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || + fnId == TUYA_MCU_FUNC_DIMMER || + (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) || + (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) || + (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE); +} + +uint8_t TuyaGetFuncId(uint8_t dpid) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].dpid == dpid) { + return Settings.tuya_fnid_map[i].fnid; + } + } + return TUYA_MCU_FUNC_NONE; +} + +uint8_t TuyaGetDpId(uint8_t fnId) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].fnid == fnId) { + return Settings.tuya_fnid_map[i].dpid; + } + } + return 0; +} + +void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0) +{ + uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF)); + TuyaSerial->write(0x55); + TuyaSerial->write(0xAA); + TuyaSerial->write((uint8_t)0x00); + TuyaSerial->write(cmd); + TuyaSerial->write(payload_len >> 8); + TuyaSerial->write(payload_len & 0xFF); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); + for (uint32_t i = 0; i < payload_len; ++i) { + TuyaSerial->write(payload[i]); + checksum += payload[i]; + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, payload[i]); + } + TuyaSerial->write(checksum); + TuyaSerial->flush(); + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x\""), log_data, checksum); + AddLog(LOG_LEVEL_DEBUG); +} + +void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value) +{ + uint16_t payload_len = 4; + uint8_t payload_buffer[8]; + payload_buffer[0] = id; + payload_buffer[1] = type; + switch (type) { + case TUYA_TYPE_BOOL: + case TUYA_TYPE_ENUM: + payload_len += 1; + payload_buffer[2] = 0x00; + payload_buffer[3] = 0x01; + payload_buffer[4] = value[0]; + break; + case TUYA_TYPE_VALUE: + payload_len += 4; + payload_buffer[2] = 0x00; + payload_buffer[3] = 0x04; + payload_buffer[4] = value[3]; + payload_buffer[5] = value[2]; + payload_buffer[6] = value[1]; + payload_buffer[7] = value[0]; + break; + + } + + TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +void TuyaSendBool(uint8_t id, bool value) +{ + TuyaSendState(id, TUYA_TYPE_BOOL, (uint8_t*)&value); +} + +void TuyaSendValue(uint8_t id, uint32_t value) +{ + TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); +} + +void TuyaSendEnum(uint8_t id, uint32_t value) +{ + TuyaSendState(id, TUYA_TYPE_ENUM, (uint8_t*)(&value)); +} + +void TuyaSendString(uint8_t id, char data[]) { + + uint16_t len = strlen(data); + uint16_t payload_len = 4 + len; + uint8_t payload_buffer[payload_len]; + payload_buffer[0] = id; + payload_buffer[1] = TUYA_TYPE_STRING; + payload_buffer[2] = len >> 8; + payload_buffer[3] = len & 0xFF; + + for (uint16_t i = 0; i < len; i++) { + payload_buffer[4+i] = data[i]; + } + + TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +bool TuyaSetPower(void) +{ + bool status = false; + + uint8_t rpower = XdrvMailbox.index; + int16_t source = XdrvMailbox.payload; + + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + active_device - 1); + if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + active_device - 1); + + if (source != SRC_SWITCH && TuyaSerial) { + TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); + status = true; + } + return status; +} + +bool TuyaSetChannels(void) +{ + LightSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); + delay(20); + return true; +} + +void LightSerialDuty(uint16_t duty) +{ + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); + if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { + duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); + if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } + if (Tuya.new_dim != duty) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); + TuyaSendValue(dpid, duty); + } + } else if (dpid > 0) { + Tuya.ignore_dim = false; + duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); + } +} + +void TuyaRequestState(void) +{ + if (TuyaSerial) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Read MCU state")); + + TuyaSendCmd(TUYA_CMD_QUERY_STATE); + } +} + +void TuyaResetWifi(void) +{ + if (!Settings.flag.button_restrict) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); + ExecuteCommand(scmnd, SRC_BUTTON); + } +} + +void TuyaProcessStatePacket(void) { + char scmnd[20]; + uint8_t dpidStart = 6; + uint8_t fnId; + uint16_t dpDataLen; + + while (dpidStart + 4 < Tuya.byte_counter) { + dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; + fnId = TuyaGetFuncId(Tuya.buffer[dpidStart]); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[dpidStart]); + + if (Tuya.buffer[dpidStart + 1] == 1) { + + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); + if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], SRC_SWITCH); + } + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); + if (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4] ^ 1, SRC_SWITCH); + } + } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[dpidStart + 4], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); + + if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[dpidStart + 4]) { + SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[dpidStart + 4]); + SwitchHandler(1); + } + } + + } + else if (Tuya.buffer[dpidStart + 1] == 2) { + bool tuya_energy_enabled = (XNRG_16 == energy_flg); + uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; + if (fnId == TUYA_MCU_FUNC_DIMMER) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), packetValue); + Tuya.new_dim = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); + if ((power || Settings.flag3.tuya_apply_o20) && + (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { + Tuya.ignore_dim = true; + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + + #ifdef USE_ENERGY_SENSOR + else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { + Energy.voltage[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], packetValue); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { + Energy.current[0] = (float)packetValue / 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], packetValue); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { + Energy.active_power[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], packetValue); + + if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { + Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; + EnergyUpdateToday(); + } + Tuya.lastPowerCheckTime = Rtc.utc_time; + } + #endif + + } + + + dpidStart += dpDataLen + 4; + } +} + +void TuyaLowPowerModePacketProcess(void) { + switch (Tuya.buffer[3]) { + case TUYA_CMD_QUERY_PRODUCT: + TuyaHandleProductInfoPacket(); + TuyaSetWifiLed(); + break; + + case TUYA_LOW_POWER_CMD_STATE: + TuyaProcessStatePacket(); + Tuya.send_success_next_second = true; + break; + } + +} + +void TuyaHandleProductInfoPacket(void) { + uint16_t dataLength = Tuya.buffer[4] << 8 | Tuya.buffer[5]; + char *data = &Tuya.buffer[6]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: MCU Product ID: %.*s"), dataLength, data); +} + +void TuyaSendLowPowerSuccessIfNeeded(void) { + uint8_t success = 1; + + if (Tuya.send_success_next_second) { + TuyaSendCmd(TUYA_LOW_POWER_CMD_STATE, &success, 1); + Tuya.send_success_next_second = false; + } +} + +void TuyaNormalPowerModePacketProcess(void) +{ + switch (Tuya.buffer[3]) { + case TUYA_CMD_QUERY_PRODUCT: + TuyaHandleProductInfoPacket(); + TuyaSendCmd(TUYA_CMD_MCU_CONF); + break; + + case TUYA_CMD_HEARTBEAT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); + if (Tuya.buffer[6] == 0) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Detected MCU restart")); + Tuya.wifi_state = -2; + } + break; + + case TUYA_CMD_STATE: + TuyaProcessStatePacket(); + break; + + case TUYA_CMD_WIFI_RESET: + case TUYA_CMD_WIFI_SELECT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi Reset")); + TuyaResetWifi(); + break; + + case TUYA_CMD_WIFI_STATE: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi LED set ACK")); + Tuya.wifi_state = TuyaGetTuyaWifiState(); + break; + + case TUYA_CMD_MCU_CONF: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]); + + if (Tuya.buffer[5] == 2) { + uint8_t led1_gpio = Tuya.buffer[6]; + uint8_t key1_gpio = Tuya.buffer[7]; + bool key1_set = false; + bool led1_set = false; + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + if (Settings.my_gp.io[i] == GPIO_LED1) led1_set = true; + else if (Settings.my_gp.io[i] == GPIO_KEY1) key1_set = true; + } + if (!Settings.my_gp.io[led1_gpio] && !led1_set) { + Settings.my_gp.io[led1_gpio] = GPIO_LED1; + restart_flag = 2; + } + if (!Settings.my_gp.io[key1_gpio] && !key1_set) { + Settings.my_gp.io[key1_gpio] = GPIO_KEY1; + restart_flag = 2; + } + } + TuyaRequestState(); + break; + + default: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); + } +} + + + + + +bool TuyaModuleSelected(void) +{ + if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { + pin[GPIO_TUYA_TX] = 1; + pin[GPIO_TUYA_RX] = 3; + Settings.my_gp.io[1] = GPIO_TUYA_TX; + Settings.my_gp.io[3] = GPIO_TUYA_RX; + restart_flag = 2; + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); + } + + bool relaySet = false; + + for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) { + if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || + (Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { + relaySet = true; + devices_present++; + } + } + + if (!relaySet) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); + devices_present++; + SettingsSaveAll(); + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { + light_type = LT_SERIAL1; + } else { + light_type = LT_BASIC; + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { + Tuya.low_power_mode = true; + Settings.flag3.fast_power_cycle_disable = true; + } + + UpdateDevices(); + return true; +} + +void TuyaInit(void) +{ + Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); + if (Tuya.buffer != nullptr) { + TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); + if (TuyaSerial->begin(9600)) { + if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration")); + + TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); + } + } + Tuya.heartbeat_timer = 0; +} + +void TuyaSerialInput(void) +{ + while (TuyaSerial->available()) { + yield(); + uint8_t serial_in_byte = TuyaSerial->read(); + + if (serial_in_byte == 0x55) { + Tuya.cmd_status = 1; + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + Tuya.cmd_checksum += serial_in_byte; + } + else if (Tuya.cmd_status == 1 && serial_in_byte == 0xAA) { + Tuya.cmd_status = 2; + + Tuya.byte_counter = 0; + Tuya.buffer[Tuya.byte_counter++] = 0x55; + Tuya.buffer[Tuya.byte_counter++] = 0xAA; + Tuya.cmd_checksum = 0xFF; + } + else if (Tuya.cmd_status == 2) { + if (Tuya.byte_counter == 5) { + Tuya.cmd_status = 3; + Tuya.data_len = serial_in_byte; + } + Tuya.cmd_checksum += serial_in_byte; + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + } + else if ((Tuya.cmd_status == 3) && (Tuya.byte_counter == (6 + Tuya.data_len)) && (Tuya.cmd_checksum == serial_in_byte)) { + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + + char hex_char[(Tuya.byte_counter * 2) + 2]; + uint16_t len = Tuya.buffer[4] << 8 | Tuya.buffer[5]; + Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":{\"Data\":\"%s\",\"Cmnd\":%d"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char)), Tuya.buffer[3]); + + if (len > 0) { + ResponseAppend_P(PSTR(",\"CmndData\":\"%s\""), ToHex_P((unsigned char*)&Tuya.buffer[6], len, hex_char, sizeof(hex_char))); + if (TUYA_CMD_STATE == Tuya.buffer[3]) { + + + uint8_t dpidStart = 6; + while (dpidStart + 4 < Tuya.byte_counter) { + uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; + ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[dpidStart], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], ToHex_P((unsigned char*)&Tuya.buffer[dpidStart + 4], dpDataLen, hex_char, sizeof(hex_char))); + if (TUYA_TYPE_STRING == Tuya.buffer[dpidStart + 1]) { + ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, (char *)&Tuya.buffer[dpidStart + 4]); + } + ResponseAppend_P(PSTR("}")); + dpidStart += dpDataLen + 4; + } + } + } + + ResponseAppend_P(PSTR("}}")); + + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); + } else { + AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); + } + XdrvRulesProcess(); + + if (!Tuya.low_power_mode) { + TuyaNormalPowerModePacketProcess(); + } else { + TuyaLowPowerModePacketProcess(); + } + + Tuya.byte_counter = 0; + Tuya.cmd_status = 0; + Tuya.cmd_checksum = 0; + Tuya.data_len = 0; + } + else if (Tuya.byte_counter < TUYA_BUFFER_SIZE -1) { + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + Tuya.cmd_checksum += serial_in_byte; + } else { + Tuya.byte_counter = 0; + Tuya.cmd_status = 0; + Tuya.cmd_checksum = 0; + Tuya.data_len = 0; + } + } +} + +bool TuyaButtonPressed(void) +{ + if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == Button.last_state[XdrvMailbox.index]))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered")); + TuyaResetWifi(); + return true; + } + return false; +} + +uint8_t TuyaGetTuyaWifiState(void) { + + uint8_t wifi_state = 0x02; + switch(WifiState()){ + case WIFI_MANAGER: + wifi_state = 0x01; + break; + case WIFI_RESTART: + wifi_state = 0x03; + break; + } + + if (MqttIsConnected()) { + wifi_state = 0x04; + } + + return wifi_state; +} + +void TuyaSetWifiLed(void) +{ + Tuya.wifi_state = TuyaGetTuyaWifiState(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), Tuya.wifi_state, WifiState()); + + if (Tuya.low_power_mode) { + TuyaSendCmd(TUYA_LOW_POWER_CMD_WIFI_STATE, &Tuya.wifi_state, 1); + } else { + TuyaSendCmd(TUYA_CMD_WIFI_STATE, &Tuya.wifi_state, 1); + } +} + +#ifdef USE_ENERGY_SENSOR + + + + +bool Xnrg16(uint8_t function) +{ + bool result = false; + + if (TUYA_DIMMER == my_module_type) { + if (FUNC_PRE_INIT == function) { + if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) { + Energy.current_available = false; + } + if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) { + Energy.voltage_available = false; + } + energy_flg = XNRG_16; + } + } + } + return result; +} +#endif + + + + + +bool Xdrv16(uint8_t function) +{ + bool result = false; + + if (TUYA_DIMMER == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (TuyaSerial) { TuyaSerialInput(); } + break; + case FUNC_MODULE_INIT: + result = TuyaModuleSelected(); + break; + case FUNC_PRE_INIT: + TuyaInit(); + break; + case FUNC_SET_DEVICE_POWER: + result = TuyaSetPower(); + break; + case FUNC_BUTTON_PRESSED: + result = TuyaButtonPressed(); + break; + case FUNC_EVERY_SECOND: + if (TuyaSerial && Tuya.wifi_state != TuyaGetTuyaWifiState()) { TuyaSetWifiLed(); } + if (!Tuya.low_power_mode) { + Tuya.heartbeat_timer++; + if (Tuya.heartbeat_timer > 10) { + Tuya.heartbeat_timer = 0; + TuyaSendCmd(TUYA_CMD_HEARTBEAT); + } + } else { + TuyaSendLowPowerSuccessIfNeeded(); + } + break; + case FUNC_SET_CHANNELS: + result = TuyaSetChannels(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kTuyaCommand, TuyaCommand); + break; + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_17_rcswitch.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_17_rcswitch.ino" +#ifdef USE_RC_SWITCH + + + + +#define XDRV_17 17 + +#define D_JSON_RF_PROTOCOL "Protocol" +#define D_JSON_RF_BITS "Bits" +#define D_JSON_RF_DATA "Data" + +#define D_CMND_RFSEND "RFSend" +#define D_JSON_RF_PULSE "Pulse" +#define D_JSON_RF_REPEAT "Repeat" + +const char kRfSendCommands[] PROGMEM = "|" + D_CMND_RFSEND; + +void (* const RfSendCommand[])(void) PROGMEM = { + &CmndRfSend }; + +#include + +RCSwitch mySwitch = RCSwitch(); + +#define RF_TIME_AVOID_DUPLICATE 1000 + +uint32_t rf_lasttime = 0; + +void RfReceiveCheck(void) +{ + if (mySwitch.available()) { + + unsigned long data = mySwitch.getReceivedValue(); + unsigned int bits = mySwitch.getReceivedBitlength(); + int protocol = mySwitch.getReceivedProtocol(); + int delay = mySwitch.getReceivedDelay(); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data 0x%lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); + + uint32_t now = millis(); + if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) { + rf_lasttime = now; + + char stemp[16]; + if (Settings.flag.rf_receive_decimal) { + snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); + } + ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), + stemp, bits, protocol, delay); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, data); +#endif + } + mySwitch.resetAvailable(); + } +} + +void RfInit(void) +{ + if (pin[GPIO_RFSEND] < 99) { + mySwitch.enableTransmit(pin[GPIO_RFSEND]); + } + if (pin[GPIO_RFRECV] < 99) { + pinMode( pin[GPIO_RFRECV], INPUT); + mySwitch.enableReceive(pin[GPIO_RFRECV]); + } +} + + + + + +void CmndRfSend(void) +{ + bool error = false; + + if (XdrvMailbox.data_len) { + unsigned long data = 0; + unsigned int bits = 24; + int protocol = 1; + int repeat = 10; + int pulse = 350; + + char dataBufUc[XdrvMailbox.data_len + 1]; + UpperCase(dataBufUc, XdrvMailbox.data); + StaticJsonBuffer<150> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (root.success()) { + + char parm_uc[10]; + data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], nullptr, 0); + bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; + protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; + repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; + pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))]; + } else { + + char *p; + uint8_t i = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(nullptr, ", ", &p)) { + switch (i++) { + case 0: + data = strtoul(str, nullptr, 0); + break; + case 1: + bits = atoi(str); + break; + case 2: + protocol = atoi(str); + break; + case 3: + repeat = atoi(str); + break; + case 4: + pulse = atoi(str); + } + } + } + + if (!protocol) { protocol = 1; } + mySwitch.setProtocol(protocol); + if (!pulse) { pulse = 350; } + mySwitch.setPulseLength(pulse); + if (!repeat) { repeat = 10; } + mySwitch.setRepeatTransmit(repeat); + if (!bits) { bits = 24; } + if (data) { + mySwitch.send(data, bits); + ResponseCmndDone(); + } else { + error = true; + } + } else { + error = true; + } + if (error) { + Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); + } +} + + + + + +bool Xdrv17(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_RFRECV] < 99) { + RfReceiveCheck(); + } + break; + case FUNC_COMMAND: + if (pin[GPIO_RFSEND] < 99) { + result = DecodeCommand(kRfSendCommands, RfSendCommand); + } + break; + case FUNC_INIT: + RfInit(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" +#ifdef USE_LIGHT +#ifdef USE_ARMTRONIX_DIMMERS + + + + + + + +#define XDRV_18 18 + +#include + +TasmotaSerial *ArmtronixSerial = nullptr; + +struct ARMTRONIX { + bool ignore_dim = false; + int8_t wifi_state = -2; + int8_t dim_state[2]; + int8_t knob_state[2]; +} Armtronix; + + + + + +bool ArmtronixSetChannels(void) +{ + LightSerial2Duty(((uint8_t*)XdrvMailbox.data)[0], ((uint8_t*)XdrvMailbox.data)[1]); + return true; +} + +void LightSerial2Duty(uint8_t duty1, uint8_t duty2) +{ + if (ArmtronixSerial && !Armtronix.ignore_dim) { + duty1 = ((float)duty1)/2.575757; + duty2 = ((float)duty2)/2.575757; + Armtronix.dim_state[0] = duty1; + Armtronix.dim_state[1] = duty2; + ArmtronixSerial->print("Dimmer1:"); + ArmtronixSerial->print(duty1); + ArmtronixSerial->print("\nDimmer2:"); + ArmtronixSerial->println(duty2); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Serial Packet Dim Values=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); + + } else { + Armtronix.ignore_dim = false; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Dim Level skipped due to already set. Value=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); + + } +} + +void ArmtronixRequestState(void) +{ + if (ArmtronixSerial) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("ARM: Request MCU state")); + ArmtronixSerial->println("Status"); + + } +} + + + + + +bool ArmtronixModuleSelected(void) +{ + devices_present++; + light_type = LT_SERIAL2; + return true; +} + +void ArmtronixInit(void) +{ + Armtronix.dim_state[0] = -1; + Armtronix.dim_state[1] = -1; + Armtronix.knob_state[0] = -1; + Armtronix.knob_state[1] = -1; + ArmtronixSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (ArmtronixSerial->begin(115200)) { + if (ArmtronixSerial->hardwareSerial()) { ClaimSerial(); } + ArmtronixSerial->println("Status"); + } +} + +void ArmtronixSerialInput(void) +{ + String answer; + int8_t newDimState[2]; + uint8_t temp; + int commaIndex; + char scmnd[20]; + if (ArmtronixSerial->available()) { + yield(); + answer = ArmtronixSerial->readStringUntil('\n'); + if (answer.substring(0,7) == "Status:") { + commaIndex = 6; + for (uint32_t i =0; i<2; i++) { + newDimState[i] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + if (newDimState[i] != Armtronix.dim_state[i]) { + temp = ((float)newDimState[i])*1.01010101010101; + Armtronix.dim_state[i] = newDimState[i]; + Armtronix.ignore_dim = true; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "%d %d"),i+1, temp); + ExecuteCommand(scmnd,SRC_SWITCH); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); + } + commaIndex = answer.indexOf(',',commaIndex+1); + } + Armtronix.knob_state[0] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + commaIndex = answer.indexOf(',',commaIndex+1); + Armtronix.knob_state[1] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + } + } +} + +void ArmtronixSetWifiLed(void) +{ + uint8_t wifi_state = 0x02; + + switch (WifiState()) { + case WIFI_MANAGER: + wifi_state = 0x01; + break; + case WIFI_RESTART: + wifi_state = 0x03; + break; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Set WiFi LED to state %d (%d)"), wifi_state, WifiState()); + + char state = '0' + ((wifi_state & 1) > 0); + ArmtronixSerial->print("Setled:"); + ArmtronixSerial->write(state); + ArmtronixSerial->write(','); + state = '0' + ((wifi_state & 2) > 0); + ArmtronixSerial->write(state); + ArmtronixSerial->write(10); + Armtronix.wifi_state = WifiState(); +} + + + + + +bool Xdrv18(uint8_t function) +{ + bool result = false; + + if (ARMTRONIX_DIMMERS == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (ArmtronixSerial) { ArmtronixSerialInput(); } + break; + case FUNC_MODULE_INIT: + result = ArmtronixModuleSelected(); + break; + case FUNC_INIT: + ArmtronixInit(); + break; + case FUNC_EVERY_SECOND: + if (ArmtronixSerial) { + if (Armtronix.wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } + if (uptime &1) { + ArmtronixSerial->println("Status"); + } + } + break; + case FUNC_SET_CHANNELS: + result = ArmtronixSetChannels(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" +#ifdef USE_LIGHT +#ifdef USE_PS_16_DZ + + + + +#define XDRV_19 19 + +#define PS16DZ_BUFFER_SIZE 80 + +#include + +TasmotaSerial *PS16DZSerial = nullptr; + +struct PS16DZ { + char *rx_buffer = nullptr; + int byte_counter = 0; + uint8_t dimmer = 0; +} Ps16dz; + + + + + +void PS16DZSerialSend(const char *tx_buffer) +{ + + + PS16DZSerial->print(tx_buffer); + PS16DZSerial->write(0x1B); + PS16DZSerial->flush(); +} + +void PS16DZSerialSendOk(void) +{ + char tx_buffer[16]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+SEND=ok")); + PS16DZSerialSend(tx_buffer); +} + + + + +void PS16DZSerialSendUpdateCommand(void) +{ + uint8_t light_state_dimmer = light_state.getDimmer(); + + light_state_dimmer = (light_state_dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : light_state_dimmer; + light_state_dimmer = (light_state_dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : light_state_dimmer; + + char tx_buffer[80]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), + LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); + + PS16DZSerialSend(tx_buffer); +} + + + + + +void PS16DZSerialInput(void) +{ + char scmnd[20]; + while (PS16DZSerial->available()) { + yield(); + uint8_t serial_in_byte = PS16DZSerial->read(); + if (serial_in_byte != 0x1B) { + if (Ps16dz.byte_counter >= PS16DZ_BUFFER_SIZE - 1) { + memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); + Ps16dz.byte_counter = 0; + } + if (Ps16dz.byte_counter || (!Ps16dz.byte_counter && ('A' == serial_in_byte))) { + Ps16dz.rx_buffer[Ps16dz.byte_counter++] = serial_in_byte; + } + } else { + Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; + + + + + if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { + + } + else if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { + + char *end_str; + char *string = Ps16dz.rx_buffer+10; + char *token = strtok_r(string, ",", &end_str); + + bool is_switch_change = false; + bool is_brightness_change = false; + + while (token != nullptr) { + char* end_token; + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); + + if (!strncmp(token2, "\"switch\"", 8)) { + bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + + + is_switch_change = (switch_state != power); + if (is_switch_change) { + ExecuteCommandPower(1, switch_state, SRC_SWITCH); + } + } + else if (!strncmp(token2, "\"bright\"", 8)) { + Ps16dz.dimmer = atoi(token3); + + + + is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer; + if (power && (Ps16dz.dimmer > 0) && is_brightness_change) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Ps16dz.dimmer); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + else if (!strncmp(token2, "\"sequence\"", 10)) { + + + + } + token = strtok_r(nullptr, ",", &end_str); + } + + if (!is_brightness_change) { + + + + PS16DZSerialSendOk(); + } + } + else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) { + + + if (!Settings.flag.button_restrict) { + int state = WIFI_MANAGER; + if (!strncmp(Ps16dz.rx_buffer+10, "=exit", 5)) { state = WIFI_RETRY; } + if (state != Settings.sta_config) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " %d"), state); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + } + memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); + Ps16dz.byte_counter = 0; + } + } +} + +bool PS16DZSerialSendUpdateCommandIfRequired(void) +{ + if (!PS16DZSerial) { return true; } + + bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); + bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); + + if (is_switch_change || is_brightness_change) { + PS16DZSerialSendUpdateCommand(); + } + + return true; +} + +void PS16DZInit(void) +{ + Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); + if (Ps16dz.rx_buffer != nullptr) { + PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (PS16DZSerial->begin(19200)) { + if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } + } + } +} + +bool PS16DZModuleSelected(void) +{ + devices_present++; + light_type = LT_SERIAL1; + + return true; +} + + + + + +bool Xdrv19(uint8_t function) +{ + bool result = false; + + if (PS_16_DZ == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (PS16DZSerial) { PS16DZSerialInput(); } + break; + case FUNC_SET_DEVICE_POWER: + case FUNC_SET_CHANNELS: + result = PS16DZSerialSendUpdateCommandIfRequired(); + break; + case FUNC_INIT: + PS16DZInit(); + break; + case FUNC_MODULE_INIT: + result = PS16DZModuleSelected(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_20_hue.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_20_hue.ino" +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_20_hue.ino" +#define XDRV_20 20 + +const char HUE_RESPONSE[] PROGMEM = + "HTTP/1.1 200 OK\r\n" + "HOST: 239.255.255.250:1900\r\n" + "CACHE-CONTROL: max-age=100\r\n" + "EXT:\r\n" + "LOCATION: http://%s:80/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.24.0\r\n" + "hue-bridgeid: %s\r\n"; +const char HUE_ST1[] PROGMEM = + "ST: upnp:rootdevice\r\n" + "USN: uuid:%s::upnp:rootdevice\r\n" + "\r\n"; +const char HUE_ST2[] PROGMEM = + "ST: uuid:%s\r\n" + "USN: uuid:%s\r\n" + "\r\n"; +const char HUE_ST3[] PROGMEM = + "ST: urn:schemas-upnp-org:device:basic:1\r\n" + "USN: uuid:%s\r\n" + "\r\n"; + +String HueBridgeId(void) +{ + String temp = WiFi.macAddress(); + temp.replace(":", ""); + String bridgeid = temp.substring(0, 6) + "FFFE" + temp.substring(6); + return bridgeid; +} + +String HueSerialnumber(void) +{ + String serial = WiFi.macAddress(); + serial.replace(":", ""); + serial.toLowerCase(); + return serial; +} + +String HueUuid(void) +{ + String uuid = F("f6543a06-da50-11ba-8d8f-"); + uuid += HueSerialnumber(); + return uuid; +} + +void HueRespondToMSearch(void) +{ + char message[TOPSZ]; + + TickerMSearch.detach(); + if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { + char response[320]; + snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); + int len = strlen(response); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST1, HueUuid().c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST2, HueUuid().c_str(), HueUuid().c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST3, HueUuid().c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(message, sizeof(message), PSTR(D_3_RESPONSE_PACKETS_SENT)); + } else { + snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); + } + + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), + message, udp_remote_ip.toString().c_str(), udp_remote_port); + + udp_response_mutex = false; +} + + + + + +const char HUE_DESCRIPTION_XML[] PROGMEM = + "" + "" + "" + "1" + "0" + "" + + "http://{x1:80/" + "" + "urn:schemas-upnp-org:device:Basic:1" + "Amazon-Echo-HA-Bridge ({x1)" + + "Royal Philips Electronics" + "http://www.philips.com" + "Philips hue Personal Wireless Lighting" + "Philips hue bridge 2012" + "929000226503" + "{x3" + "uuid:{x2" + "" + "\r\n" + "\r\n"; +const char HUE_LIGHTS_STATUS_JSON1[] PROGMEM = + "{\"on\":{state}," + "{light_status}" + "\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":true}"; +const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = + ",\"type\":\"Extended color light\"," + "\"name\":\"{j1\"," + "\"modelid\":\"LCT007\"," + "\"uniqueid\":\"{j2\"," + "\"swversion\":\"5.50.1.19085\"}"; +const char HUE_GROUP0_STATUS_JSON[] PROGMEM = + "{\"name\":\"Group 0\"," + "\"lights\":[{l1]," + "\"type\":\"LightGroup\"," + "\"action\":"; + +const char HueConfigResponse_JSON[] PROGMEM = + "{\"name\":\"Philips hue\"," + "\"mac\":\"{ma\"," + "\"dhcp\":true," + "\"ipaddress\":\"{ip\"," + "\"netmask\":\"{ms\"," + "\"gateway\":\"{gw\"," + "\"proxyaddress\":\"none\"," + "\"proxyport\":0," + "\"bridgeid\":\"{br\"," + "\"UTC\":\"{dt\"," + "\"whitelist\":{\"{id\":{" + "\"last use date\":\"{dt\"," + "\"create date\":\"{dt\"," + "\"name\":\"Remote\"}}," + "\"swversion\":\"01041302\"," + "\"apiversion\":\"1.17.0\"," + "\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false}," + "\"linkbutton\":false," + "\"portalservices\":false" + "}"; +const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; +const char HUE_ERROR_JSON[] PROGMEM = + "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; + + + +String GetHueDeviceId(uint8_t id) +{ + String deviceid = WiFi.macAddress() + F(":00:11-") + String(id); + deviceid.toLowerCase(); + return deviceid; +} + +String GetHueUserId(void) +{ + char userid[7]; + + snprintf_P(userid, sizeof(userid), PSTR("%03x"), ESP.getChipId()); + return String(userid); +} + +void HandleUpnpSetupHue(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_HUE_BRIDGE_SETUP)); + String description_xml = FPSTR(HUE_DESCRIPTION_XML); + description_xml.replace("{x1", WiFi.localIP().toString()); + description_xml.replace("{x2", HueUuid()); + description_xml.replace("{x3", HueSerialnumber()); + WSSend(200, CT_XML, description_xml); +} + +void HueNotImplemented(String *path) +{ + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); + + WSSend(200, CT_JSON, "{}"); +} + +void HueConfigResponse(String *response) +{ + *response += FPSTR(HueConfigResponse_JSON); + response->replace("{ma", WiFi.macAddress()); + response->replace("{ip", WiFi.localIP().toString()); + response->replace("{ms", WiFi.subnetMask().toString()); + response->replace("{gw", WiFi.gatewayIP().toString()); + response->replace("{br", HueBridgeId()); + response->replace("{dt", GetDateAndTime(DT_UTC)); + response->replace("{id", GetHueUserId()); +} + +void HueConfig(String *path) +{ + String response = ""; + HueConfigResponse(&response); + WSSend(200, CT_JSON, response); +} + + + +bool g_gotct = false; + + + + +uint16_t prev_hue = 0; +uint8_t prev_sat = 0; +uint8_t prev_bri = 254; +uint16_t prev_ct = 254; +char prev_x_str[24] = "\0"; +char prev_y_str[24] = "\0"; + +uint8_t getLocalLightSubtype(uint8_t device) { + if (light_type) { + if (device >= Light.device) { + if (Settings.flag3.pwm_multi_channels) { + return LST_SINGLE; + } else { + return Light.subtype; + } + } else { + return LST_NONE; + } + } else { + return LST_NONE; + } +} + +void HueLightStatus1(uint8_t device, String *response) +{ + uint16_t ct = 0; + uint8_t color_mode; + String light_status = ""; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint32_t echo_gen = findEchoGeneration(); + + + uint8_t local_light_subtype = getLocalLightSubtype(device); + + bri = LightGetBri(device); + if (bri > 254) bri = 254; + if (bri < 1) bri = 1; + +#ifdef USE_SHUTTER + if (ShutterState(device)) { + bri = (float)((Settings.shutter_options[device-1] & 1) ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; + } +#endif + + if (light_type) { + light_state.getHSB(&hue, &sat, nullptr); + + if ((bri > prev_bri ? bri - prev_bri : prev_bri - bri) < 1) + bri = prev_bri; + + if (sat > 254) sat = 254; + if ((sat > prev_sat ? sat - prev_sat : prev_sat - sat) < 1) { + sat = prev_sat; + } else { + prev_x_str[0] = prev_y_str[0] = 0; + } + + hue = changeUIntScale(hue, 0, 359, 0, 65535); + if ((hue > prev_hue ? hue - prev_hue : prev_hue - hue) < 400) { + hue = prev_hue; + } else { + prev_x_str[0] = prev_y_str[0] = 0; + } + + color_mode = light_state.getColorMode(); + ct = light_state.getCT(); + if (LCM_RGB == color_mode) { g_gotct = false; } + if (LCM_CT == color_mode) { g_gotct = true; } + + + + if ((ct > prev_ct ? ct - prev_ct : prev_ct - ct) < 1) + ct = prev_ct; + + + + } + + *response += FPSTR(HUE_LIGHTS_STATUS_JSON1); + response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); + + if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { + light_status += "\"bri\":"; + light_status += String(bri); + light_status += ","; + } + if (LST_COLDWARM <= local_light_subtype) { + light_status += F("\"colormode\":\""); + light_status += (g_gotct ? "ct" : "hs"); + light_status += "\","; + } + if (LST_RGB <= local_light_subtype) { + if (prev_x_str[0] && prev_y_str[0]) { + light_status += "\"xy\":["; + light_status += prev_x_str; + light_status += ","; + light_status += prev_y_str; + light_status += "],"; + } else { + float x, y; + light_state.getXY(&x, &y); + light_status += "\"xy\":["; + light_status += String(x, 5); + light_status += ","; + light_status += String(y, 5); + light_status += "],"; + } + light_status += "\"hue\":"; + light_status += String(hue); + light_status += ","; + + light_status += "\"sat\":"; + light_status += String(sat); + light_status += ","; + } + if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { + light_status += "\"ct\":"; + light_status += String(ct > 0 ? ct : 284); + light_status += ","; + } + response->replace("{light_status}", light_status); +} + + + +bool HueActive(uint8_t device) { + if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } + return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1); +} + +void HueLightStatus2(uint8_t device, String *response) +{ + *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); + if (device <= MAX_FRIENDLYNAMES) { + response->replace("{j1", SettingsText(SET_FRIENDLYNAME1 +device -1)); + } else { + char fname[33]; + strcpy(fname, SettingsText(SET_FRIENDLYNAME1 + MAX_FRIENDLYNAMES -1)); + uint32_t fname_len = strlen(fname); + if (fname_len > 30) { fname_len = 30; } + fname[fname_len++] = '-'; + if (device - MAX_FRIENDLYNAMES < 10) { + fname[fname_len++] = '0' + device - MAX_FRIENDLYNAMES; + } else { + fname[fname_len++] = 'A' + device - MAX_FRIENDLYNAMES - 10; + } + fname[fname_len] = 0x00; + + response->replace("{j1", fname); + } + response->replace("{j2", GetHueDeviceId(device)); +} + + + + +uint32_t EncodeLightId(uint8_t relay_id) +{ + uint8_t mac[6]; + WiFi.macAddress(mac); + uint32_t id = 0; + + if (relay_id >= 32) { + relay_id = 0; + } + if (relay_id > 15) { + id = (1 << 28); + } + + id |= (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (relay_id & 0xF); + return id; +} + + + +uint32_t DecodeLightId(uint32_t hue_id) { + uint8_t relay_id = hue_id & 0xF; + if (hue_id & (1 << 28)) { + relay_id += 16; + } + if (0 == relay_id) { + relay_id = 32; + } + return relay_id; +} + +static const char * FIRST_GEN_UA[] = { + "AEOBC", +}; + + +uint32_t findEchoGeneration(void) { + + String user_agent = WebServer->header("User-Agent"); + uint32_t gen = 2; + + for (uint32_t i = 0; i < sizeof(FIRST_GEN_UA)/sizeof(char*); i++) { + if (user_agent.indexOf(FIRST_GEN_UA[i]) >= 0) { + gen = 1; + break; + } + } + if (0 == user_agent.length()) { + gen = 1; + } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, D_LOG_HTTP D_HUE " User-Agent: %s, gen=%d", user_agent.c_str(), gen); + + return gen; +} + +void HueGlobalConfig(String *path) { + String response; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + path->remove(0,1); + response = F("{\"lights\":{"); + bool appending = false; + for (uint32_t i = 1; i <= maxhue; i++) { + if (HueActive(i)) { + if (appending) { response += ","; } + response += "\""; + response += EncodeLightId(i); + response += F("\":{\"state\":"); + HueLightStatus1(i, &response); + HueLightStatus2(i, &response); + appending = true; + } + } + response += F("},\"groups\":{},\"schedules\":{},\"config\":"); + HueConfigResponse(&response); + response += "}"; + WSSend(200, CT_JSON, response); +} + +void HueAuthentication(String *path) +{ + char response[38]; + + snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); + WSSend(200, CT_JSON, response); +} + +void HueLights(String *path) +{ + + + + String response; + int code = 200; + uint16_t tmp = 0; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint16_t ct = 0; + bool resp = false; + bool on = false; + bool change = false; + uint8_t device = 1; + uint8_t local_light_subtype = Light.subtype; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + path->remove(0,path->indexOf("/lights")); + if (path->endsWith("/lights")) { + response = "{"; + bool appending = false; + for (uint32_t i = 1; i <= maxhue; i++) { + if (HueActive(i)) { + if (appending) { response += ","; } + response += "\""; + response += EncodeLightId(i); + response += F("\":{\"state\":"); + HueLightStatus1(i, &response); + HueLightStatus2(i, &response); + appending = true; + } + } +#ifdef USE_SCRIPT_HUE + Script_Check_Hue(&response); +#endif + response += "}"; + } + else if (path->endsWith("/state")) { + path->remove(0,8); + path->remove(path->indexOf("/state")); + device = DecodeLightId(atoi(path->c_str())); + +#ifdef USE_SCRIPT_HUE + if (device>devices_present) { + return Script_Handle_Hue(path); + } +#endif + + if ((device < 1) || (device > maxhue)) { + device = 1; + } + local_light_subtype = getLocalLightSubtype(device); + + if (WebServer->args()) { + response = "["; + + StaticJsonBuffer<400> jsonBuffer; + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + if (hue_json.containsKey("on")) { + + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "on"); + +#ifdef USE_SHUTTER + if (ShutterState(device)) { + if (!change) { + on = hue_json["on"]; + bri = on ? 1.0f : 0.0f; + change = true; + } + response.replace("{re", on ? "true" : "false"); + } else { +#endif + on = hue_json["on"]; + switch(on) + { + case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); + response.replace("{re", "false"); + break; + case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); + response.replace("{re", "true"); + break; + default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); + break; + } + resp = true; +#ifdef USE_SHUTTER + } +#endif + } + + if (light_type && (local_light_subtype >= LST_SINGLE)) { + if (!Settings.flag3.pwm_multi_channels) { + light_state.getHSB(&hue, &sat, nullptr); + bri = light_state.getBri(); + ct = light_state.getCT(); + uint8_t color_mode = light_state.getColorMode(); + if (LCM_RGB == color_mode) { g_gotct = false; } + if (LCM_CT == color_mode) { g_gotct = true; } + + } else { + bri = LightGetBri(device); + } + } + prev_x_str[0] = prev_y_str[0] = 0; + + if (hue_json.containsKey("bri")) { + tmp = hue_json["bri"]; + prev_bri = bri = tmp; + + if (254 <= bri) { bri = 255; } + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "bri"); + response.replace("{re", String(tmp)); + if (LST_SINGLE <= Light.subtype) { + change = true; + } + resp = true; + } + + + if (hue_json.containsKey("xy")) { + float x, y; + x = hue_json["xy"][0]; + y = hue_json["xy"][1]; + const String &x_str = hue_json["xy"][0]; + const String &y_str = hue_json["xy"][1]; + x_str.toCharArray(prev_x_str, sizeof(prev_x_str)); + y_str.toCharArray(prev_y_str, sizeof(prev_y_str)); + + uint8_t rr,gg,bb; + LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); + LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); + prev_hue = changeUIntScale(hue, 0, 359, 0, 65535); + prev_sat = (sat > 254 ? 254 : sat); + + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "xy"); + response.replace("{re", "[" + x_str + "," + y_str + "]"); + g_gotct = false; + resp = true; + change = true; + } + if (hue_json.containsKey("hue")) { + tmp = hue_json["hue"]; + prev_hue = tmp; + + hue = changeUIntScale(tmp, 0, 65535, 0, 359); + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "hue"); + response.replace("{re", String(tmp)); + if (LST_RGB <= Light.subtype) { + g_gotct = false; + change = true; + } + resp = true; + } + if (hue_json.containsKey("sat")) { + tmp = hue_json["sat"]; + prev_sat = sat = tmp; + + if (254 <= sat) { sat = 255; } + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "sat"); + response.replace("{re", String(tmp)); + if (LST_RGB <= Light.subtype) { + g_gotct = false; + change = true; + } + resp = true; + } + if (hue_json.containsKey("ct")) { + ct = hue_json["ct"]; + prev_ct = ct; + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "ct"); + response.replace("{re", String(ct)); + if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { + g_gotct = true; + change = true; + } + resp = true; + } + if (change) { +#ifdef USE_SHUTTER + if (ShutterState(device)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_options[device-1] & 1); + ShutterSetPosition(device, bri * 100.0f ); + } else +#endif + if (light_type && (local_light_subtype > LST_NONE)) { + if (!Settings.flag3.pwm_multi_channels) { + if (g_gotct) { + light_controller.changeCTB(ct, bri); + } else { + light_controller.changeHSB(hue, sat, bri); + } + LightPreparePower(); + } else { + LightSetBri(device, bri); + } + if (LST_COLDWARM <= local_light_subtype) { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); + } else { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_DIMMER)); + } + XdrvRulesProcess(); + } + change = false; + } + response += "]"; + if (2 == response.length()) { + response = FPSTR(HUE_ERROR_JSON); + } + } + else { + response = FPSTR(HUE_ERROR_JSON); + } + } + else if(path->indexOf("/lights/") >= 0) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "/lights path=%s", path->c_str()); + path->remove(0,8); + device = DecodeLightId(atoi(path->c_str())); + +#ifdef USE_SCRIPT_HUE + if (device>devices_present) { + Script_HueStatus(&response,device-devices_present-1); + goto exit; +} +#endif + + if ((device < 1) || (device > maxhue)) { + device = 1; + } + response += F("{\"state\":"); + HueLightStatus1(device, &response); + HueLightStatus2(device, &response); + } + else { + response = "{}"; + code = 406; + } + exit: + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); + WSSend(code, CT_JSON, response); +} + +void HueGroups(String *path) +{ + + + + String response = "{}"; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + if (path->endsWith("/0")) { + response = FPSTR(HUE_GROUP0_STATUS_JSON); + String lights = F("\"1\""); + for (uint32_t i = 2; i <= maxhue; i++) { + lights += ",\""; + lights += EncodeLightId(i); + lights += "\""; + } + response.replace("{l1", lights); + HueLightStatus1(1, &response); + response += F("}"); + } + + WSSend(200, CT_JSON, response); +} + +void HandleHueApi(String *path) +{ +# 784 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_20_hue.ino" + uint8_t args = 0; + + path->remove(0, 4); + uint16_t apilen = path->length(); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); + for (args = 0; args < WebServer->args(); args++) { + String json = WebServer->arg(args); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); + } + + if (path->endsWith("/invalid/")) {} + else if (!apilen) HueAuthentication(path); + else if (path->endsWith("/")) HueAuthentication(path); + else if (path->endsWith("/config")) HueConfig(path); + else if (path->indexOf("/lights") >= 0) HueLights(path); + else if (path->indexOf("/groups") >= 0) HueGroups(path); + else if (path->endsWith("/schedules")) HueNotImplemented(path); + else if (path->endsWith("/sensors")) HueNotImplemented(path); + else if (path->endsWith("/scenes")) HueNotImplemented(path); + else if (path->endsWith("/rules")) HueNotImplemented(path); + else if (path->endsWith("/resourcelinks")) HueNotImplemented(path); + else HueGlobalConfig(path); +} + + + + + +bool Xdrv20(uint8_t function) +{ + bool result = false; + +#ifdef USE_SCRIPT_HUE + if ((EMUL_HUE == Settings.flag2.emulation)) { +#else + if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) { +#endif + switch (function) { + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/description.xml", HandleUpnpSetupHue); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_21_wemo.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_21_wemo.ino" +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined (USE_EMULATION_WEMO) + + + + +#define XDRV_21 21 + +const char WEMO_MSEARCH[] PROGMEM = + "HTTP/1.1 200 OK\r\n" + "CACHE-CONTROL: max-age=86400\r\n" + "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" + "EXT:\r\n" + "LOCATION: http://%s:80/setup.xml\r\n" + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" + "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n" + "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n" + "ST: %s\r\n" + "USN: uuid:%s::%s\r\n" + "X-User-Agent: redsonic\r\n" + "\r\n"; + +String WemoSerialnumber(void) +{ + char serial[16]; + + snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId()); + return String(serial); +} + +String WemoUuid(void) +{ + char uuid[27]; + + snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str()); + return String(uuid); +} + +void WemoRespondToMSearch(int echo_type) +{ + char message[TOPSZ]; + + TickerMSearch.detach(); + if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { + char type[24]; + if (1 == echo_type) { + strcpy_P(type, URN_BELKIN_DEVICE_CAP); + } else { + strcpy_P(type, UPNP_ROOTDEVICE); + } + char response[400]; + snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); + PortUdp.write(response); + PortUdp.endPacket(); + snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); + } else { + snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); + } + + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), + echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); + + udp_response_mutex = false; +} + + + + + +const char WEMO_EVENTSERVICE_XML[] PROGMEM = + "" + "" + "" + "SetBinaryState" + "" + "" + "" + "BinaryState" + "BinaryState" + "in" + "" + "" + "" + "" + "GetBinaryState" + "" + "" + "" + "BinaryState" + "BinaryState" + "out" + "" + "" + "" + "" + "" + "" + "BinaryState" + "bool" + "0" + "" + "" + "level" + "string" + "0" + "" + "" + "\r\n\r\n"; + +const char WEMO_METASERVICE_XML[] PROGMEM = + "" + "" + "1" + "0" + "" + "" + "" + "GetMetaInfo" + "" + "" + "GetMetaInfo" + "MetaInfo" + "in" + "" + "" + "" + "" + "" + "MetaInfo" + "string" + "0" + "" + "" + "\r\n\r\n"; + +const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = + "" + "" + "" + "%d" + "" + "" + "\r\n"; + +const char WEMO_SETUP_XML[] PROGMEM = + "" + "" + "" + "urn:Belkin:device:controllee:1" + "{x1" + "Belkin International Inc." + "Socket" + "3.1415" + "uuid:{x2" + "{x3" + "0" + "" + "" + "urn:Belkin:service:basicevent:1" + "urn:Belkin:serviceId:basicevent1" + "/upnp/control/basicevent1" + "/upnp/event/basicevent1" + "/eventservice.xml" + "" + "" + "urn:Belkin:service:metainfo:1" + "urn:Belkin:serviceId:metainfo1" + "/upnp/control/metainfo1" + "/upnp/event/metainfo1" + "/metainfoservice.xml" + "" + "" + "" + "\r\n"; + + + +void HandleUpnpEvent(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); + + char event[500]; + strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); + + + + + char state = 'G'; + if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) { + state = 'S'; + uint8_t power = POWER_TOGGLE; + if (strstr_P(event, PSTR("State>10on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); + WebServer->on("/eventservice.xml", HandleUpnpService); + WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); + WebServer->on("/setup.xml", HandleUpnpSetupWemo); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" +#ifdef USE_SONOFF_IFAN + + + + +#define XDRV_22 22 + +const uint8_t MAX_FAN_SPEED = 4; + +const uint8_t kIFan02Speed[MAX_FAN_SPEED] = { 0x00, 0x01, 0x03, 0x05 }; +const uint8_t kIFan03Speed[MAX_FAN_SPEED +2] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x06 }; +const uint8_t kIFan03Sequence[MAX_FAN_SPEED][MAX_FAN_SPEED] = {{0, 2, 2, 2}, {0, 1, 2, 4}, {1, 1, 2, 5}, {4, 4, 5, 3}}; + +const char kSonoffIfanCommands[] PROGMEM = "|" + D_CMND_FANSPEED; + +void (* const SonoffIfanCommand[])(void) PROGMEM = { + &CmndFanspeed }; + +uint8_t ifan_fanspeed_timer = 0; +uint8_t ifan_fanspeed_goal = 0; +bool ifan_receive_flag = false; +bool ifan_restart_flag = true; + + + +bool IsModuleIfan(void) +{ + return ((SONOFF_IFAN02 == my_module_type) || (SONOFF_IFAN03 == my_module_type)); +} + +uint8_t MaxFanspeed(void) +{ + return MAX_FAN_SPEED; +} + +uint8_t GetFanspeed(void) +{ + if (ifan_fanspeed_timer) { + return ifan_fanspeed_goal; + } else { + + + + + + + uint8_t fanspeed = (uint8_t)(power &0xF) >> 1; + if (fanspeed) { fanspeed = (fanspeed >> 1) +1; } + return fanspeed; + } +} + + + +void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence) +{ + ifan_fanspeed_timer = 0; + ifan_fanspeed_goal = fanspeed; + + uint8_t fanspeed_now = GetFanspeed(); + + if (fanspeed == fanspeed_now) { return; } + + uint8_t fans = kIFan02Speed[fanspeed]; + if (SONOFF_IFAN03 == my_module_type) { + if (sequence) { + fanspeed = kIFan03Sequence[fanspeed_now][ifan_fanspeed_goal]; + if (fanspeed != ifan_fanspeed_goal) { + if (0 == fanspeed_now) { + ifan_fanspeed_timer = 20; + } else { + ifan_fanspeed_timer = 2; + } + } + } + fans = kIFan03Speed[fanspeed]; + } + for (uint32_t i = 2; i < 5; i++) { + uint8_t state = (fans &1) + POWER_OFF_NO_STATE; + ExecuteCommandPower(i, state, SRC_IGNORE); + fans >>= 1; + } + +#ifdef USE_DOMOTICZ + if (sequence) { DomoticzUpdateFanState(); } +#endif +} + + + +void SonoffIfanReceived(void) +{ + char svalue[32]; + + uint8_t mode = serial_in_buffer[3]; + uint8_t action = serial_in_buffer[6]; + + if (4 == mode) { + if (action < 4) { + + + + + if (action != GetFanspeed()) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), action); + ExecuteCommand(svalue, SRC_REMOTE); +#ifdef USE_BUZZER + BuzzerEnabledBeep((action) ? action : 1, (action) ? 1 : 4); +#endif + } + } else { + + ExecuteCommandPower(1, POWER_TOGGLE, SRC_REMOTE); + } + } + if (6 == mode) { + + Settings.flag3.buzzer_enable = !Settings.flag3.buzzer_enable; + } + if (7 == mode) { + +#ifdef USE_BUZZER + BuzzerEnabledBeep(4, 1); +#endif + } + + + + serial_in_buffer[5] = 0; + serial_in_buffer[6] = 0; + for (uint32_t i = 0; i < 7; i++) { + if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } + Serial.write(serial_in_buffer[i]); + } +} + +bool SonoffIfanSerialInput(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + if (0xAA == serial_in_byte) { + serial_in_byte_counter = 0; + ifan_receive_flag = true; + } + if (ifan_receive_flag) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (serial_in_byte_counter == 8) { +# 176 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" + AddLogSerial(LOG_LEVEL_DEBUG); + uint8_t crc = 0; + for (uint32_t i = 2; i < 7; i++) { + crc += serial_in_buffer[i]; + } + if (crc == serial_in_buffer[7]) { + SonoffIfanReceived(); + ifan_receive_flag = false; + return true; + } + } + serial_in_byte = 0; + } + return false; + } +} + + + + + +void CmndFanspeed(void) +{ + if (XdrvMailbox.data_len > 0) { + if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (int16_t)GetFanspeed() -1; + if (XdrvMailbox.payload < 0) { XdrvMailbox.payload = MAX_FAN_SPEED -1; } + } + else if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = GetFanspeed() +1; + if (XdrvMailbox.payload > MAX_FAN_SPEED -1) { XdrvMailbox.payload = 0; } + } + } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_FAN_SPEED)) { + SonoffIFanSetFanspeed(XdrvMailbox.payload, true); + } + ResponseCmndNumber(GetFanspeed()); +} + + + +bool SonoffIfanInit(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + SetSerial(9600, TS_SERIAL_8N1); + } + return false; +} + +void SonoffIfanUpdate(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + if (ifan_fanspeed_timer) { + ifan_fanspeed_timer--; + if (!ifan_fanspeed_timer) { + SonoffIFanSetFanspeed(ifan_fanspeed_goal, false); + } + } + } + + if (ifan_restart_flag && (4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { + ifan_restart_flag = false; + SetDevicePower(1, SRC_RETRY); + SetDevicePower(power, SRC_RETRY); + } +} + + + + + +bool Xdrv22(uint8_t function) +{ + bool result = false; + + if (IsModuleIfan()) { + switch (function) { + case FUNC_EVERY_250_MSECOND: + SonoffIfanUpdate(); + break; + case FUNC_SERIAL: + result = SonoffIfanSerialInput(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kSonoffIfanCommands, SonoffIfanCommand); + break; + case FUNC_MODULE_INIT: + result = SonoffIfanInit(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +#ifdef USE_ZIGBEE + +#define OCCUPANCY "Occupancy" + +typedef uint64_t Z_IEEEAddress; +typedef uint16_t Z_ShortAddress; + +enum ZnpCommandType { + Z_POLL = 0x00, + Z_SREQ = 0x20, + Z_AREQ = 0x40, + Z_SRSP = 0x60 +}; + +enum ZnpSubsystem { + Z_RPC_Error = 0x00, + Z_SYS = 0x01, + Z_MAC = 0x02, + Z_NWK = 0x03, + Z_AF = 0x04, + Z_ZDO = 0x05, + Z_SAPI = 0x06, + Z_UTIL = 0x07, + Z_DEBUG = 0x08, + Z_APP = 0x09 +}; + + +enum SysCommand { + SYS_RESET = 0x00, + SYS_PING = 0x01, + SYS_VERSION = 0x02, + SYS_SET_EXTADDR = 0x03, + SYS_GET_EXTADDR = 0x04, + SYS_RAM_READ = 0x05, + SYS_RAM_WRITE = 0x06, + SYS_OSAL_NV_ITEM_INIT = 0x07, + SYS_OSAL_NV_READ = 0x08, + SYS_OSAL_NV_WRITE = 0x09, + SYS_OSAL_START_TIMER = 0x0A, + SYS_OSAL_STOP_TIMER = 0x0B, + SYS_RANDOM = 0x0C, + SYS_ADC_READ = 0x0D, + SYS_GPIO = 0x0E, + SYS_STACK_TUNE = 0x0F, + SYS_SET_TIME = 0x10, + SYS_GET_TIME = 0x11, + SYS_OSAL_NV_DELETE = 0x12, + SYS_OSAL_NV_LENGTH = 0x13, + SYS_TEST_RF = 0x40, + SYS_TEST_LOOPBACK = 0x41, + SYS_RESET_IND = 0x80, + SYS_OSAL_TIMER_EXPIRED = 0x81, +}; + +enum SapiCommand { + SAPI_START_REQUEST = 0x00, + SAPI_BIND_DEVICE = 0x01, + SAPI_ALLOW_BIND = 0x02, + SAPI_SEND_DATA_REQUEST = 0x03, + SAPI_READ_CONFIGURATION = 0x04, + SAPI_WRITE_CONFIGURATION = 0x05, + SAPI_GET_DEVICE_INFO = 0x06, + SAPI_FIND_DEVICE_REQUEST = 0x07, + SAPI_PERMIT_JOINING_REQUEST = 0x08, + SAPI_SYSTEM_RESET = 0x09, + SAPI_START_CONFIRM = 0x80, + SAPI_BIND_CONFIRM = 0x81, + SAPI_ALLOW_BIND_CONFIRM = 0x82, + SAPI_SEND_DATA_CONFIRM = 0x83, + SAPI_FIND_DEVICE_CONFIRM = 0x85, + SAPI_RECEIVE_DATA_INDICATION = 0x87, +}; +enum Z_configuration { + CONF_EXTADDR = 0x01, + CONF_BOOTCOUNTER = 0x02, + CONF_STARTUP_OPTION = 0x03, + CONF_START_DELAY = 0x04, + CONF_NIB = 0x21, + CONF_DEVICE_LIST = 0x22, + CONF_ADDRMGR = 0x23, + CONF_POLL_RATE = 0x24, + CONF_QUEUED_POLL_RATE = 0x25, + CONF_RESPONSE_POLL_RATE = 0x26, + CONF_REJOIN_POLL_RATE = 0x27, + CONF_DATA_RETRIES = 0x28, + CONF_POLL_FAILURE_RETRIES = 0x29, + CONF_STACK_PROFILE = 0x2A, + CONF_INDIRECT_MSG_TIMEOUT = 0x2B, + CONF_ROUTE_EXPIRY_TIME = 0x2C, + CONF_EXTENDED_PAN_ID = 0x2D, + CONF_BCAST_RETRIES = 0x2E, + CONF_PASSIVE_ACK_TIMEOUT = 0x2F, + CONF_BCAST_DELIVERY_TIME = 0x30, + CONF_NWK_MODE = 0x31, + CONF_CONCENTRATOR_ENABLE = 0x32, + CONF_CONCENTRATOR_DISCOVERY = 0x33, + CONF_CONCENTRATOR_RADIUS = 0x34, + CONF_CONCENTRATOR_RC = 0x36, + CONF_NWK_MGR_MODE = 0x37, + CONF_SRC_RTG_EXPIRY_TIME = 0x38, + CONF_ROUTE_DISCOVERY_TIME = 0x39, + CONF_NWK_ACTIVE_KEY_INFO = 0x3A, + CONF_NWK_ALTERN_KEY_INFO = 0x3B, + CONF_ROUTER_OFF_ASSOC_CLEANUP = 0x3C, + CONF_NWK_LEAVE_REQ_ALLOWED = 0x3D, + CONF_NWK_CHILD_AGE_ENABLE = 0x3E, + CONF_DEVICE_LIST_KA_TIMEOUT = 0x3F, + CONF_BINDING_TABLE = 0x41, + CONF_GROUP_TABLE = 0x42, + CONF_APS_FRAME_RETRIES = 0x43, + CONF_APS_ACK_WAIT_DURATION = 0x44, + CONF_APS_ACK_WAIT_MULTIPLIER = 0x45, + CONF_BINDING_TIME = 0x46, + CONF_APS_USE_EXT_PANID = 0x47, + CONF_APS_USE_INSECURE_JOIN = 0x48, + CONF_COMMISSIONED_NWK_ADDR = 0x49, + CONF_APS_NONMEMBER_RADIUS = 0x4B, + CONF_APS_LINK_KEY_TABLE = 0x4C, + CONF_APS_DUPREJ_TIMEOUT_INC = 0x4D, + CONF_APS_DUPREJ_TIMEOUT_COUNT = 0x4E, + CONF_APS_DUPREJ_TABLE_SIZE = 0x4F, + CONF_DIAGNOSTIC_STATS = 0x50, + CONF_SECURITY_LEVEL = 0x61, + CONF_PRECFGKEY = 0x62, + CONF_PRECFGKEYS_ENABLE = 0x63, + CONF_SECURITY_MODE = 0x64, + CONF_SECURE_PERMIT_JOIN = 0x65, + CONF_APS_LINK_KEY_TYPE = 0x66, + CONF_APS_ALLOW_R19_SECURITY = 0x67, + CONF_IMPLICIT_CERTIFICATE = 0x69, + CONF_DEVICE_PRIVATE_KEY = 0x6A, + CONF_CA_PUBLIC_KEY = 0x6B, + CONF_KE_MAX_DEVICES = 0x6C, + CONF_USE_DEFAULT_TCLK = 0x6D, + CONF_RNG_COUNTER = 0x6F, + CONF_RANDOM_SEED = 0x70, + CONF_TRUSTCENTER_ADDR = 0x71, + CONF_USERDESC = 0x81, + CONF_NWKKEY = 0x82, + CONF_PANID = 0x83, + CONF_CHANLIST = 0x84, + CONF_LEAVE_CTRL = 0x85, + CONF_SCAN_DURATION = 0x86, + CONF_LOGICAL_TYPE = 0x87, + CONF_NWKMGR_MIN_TX = 0x88, + CONF_NWKMGR_ADDR = 0x89, + CONF_ZDO_DIRECT_CB = 0x8F, + CONF_TCLK_TABLE_START = 0x0101, + ZNP_HAS_CONFIGURED = 0xF00 +}; +# 210 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +enum Z_Status { + Z_Success = 0x00, + Z_Failure = 0x01, + Z_InvalidParameter = 0x02, + Z_MemError = 0x03, + Z_Created = 0x09, + Z_BufferFull = 0x11 +}; + +enum Z_App_Profiles { + Z_PROF_IPM = 0x0101, + Z_PROF_HA = 0x0104, + Z_PROF_CBA = 0x0105, + Z_PROF_TA = 0x0107, + Z_PROF_PHHC = 0x0108, + Z_PROF_AMI = 0x0109, +}; + +enum Z_Device_Ids { + Z_DEVID_CONF_TOOL = 0x0005, +# 262 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +}; +# 275 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +enum AfCommand : uint8_t { + AF_REGISTER = 0x00, + AF_DATA_REQUEST = 0x01, + AF_DATA_REQUEST_EXT = 0x02, + AF_DATA_REQUEST_SRC_RTG = 0x03, + AF_INTER_PAN_CTL = 0x10, + AF_DATA_STORE = 0x11, + AF_DATA_RETRIEVE = 0x12, + AF_APSF_CONFIG_SET = 0x13, + AF_DATA_CONFIRM = 0x80, + AF_REFLECT_ERROR = 0x83, + AF_INCOMING_MSG = 0x81, + AF_INCOMING_MSG_EXT = 0x82 +}; + + +enum : uint8_t { + ZDO_NWK_ADDR_REQ = 0x00, + ZDO_IEEE_ADDR_REQ = 0x01, + ZDO_NODE_DESC_REQ = 0x02, + ZDO_POWER_DESC_REQ = 0x03, + ZDO_SIMPLE_DESC_REQ = 0x04, + ZDO_ACTIVE_EP_REQ = 0x05, + ZDO_MATCH_DESC_REQ = 0x06, + ZDO_COMPLEX_DESC_REQ = 0x07, + ZDO_USER_DESC_REQ = 0x08, + ZDO_DEVICE_ANNCE = 0x0A, + ZDO_USER_DESC_SET = 0x0B, + ZDO_SERVER_DISC_REQ = 0x0C, + ZDO_END_DEVICE_BIND_REQ = 0x20, + ZDO_BIND_REQ = 0x21, + ZDO_UNBIND_REQ = 0x22, + ZDO_SET_LINK_KEY = 0x23, + ZDO_REMOVE_LINK_KEY = 0x24, + ZDO_GET_LINK_KEY = 0x25, + ZDO_MGMT_NWK_DISC_REQ = 0x30, + ZDO_MGMT_LQI_REQ = 0x31, + ZDO_MGMT_RTQ_REQ = 0x32, + ZDO_MGMT_BIND_REQ = 0x33, + ZDO_MGMT_LEAVE_REQ = 0x34, + ZDO_MGMT_DIRECT_JOIN_REQ = 0x35, + ZDO_MGMT_PERMIT_JOIN_REQ = 0x36, + ZDO_MGMT_NWK_UPDATE_REQ = 0x37, + ZDO_MSG_CB_REGISTER = 0x3E, + ZDO_MGS_CB_REMOVE = 0x3F, + ZDO_STARTUP_FROM_APP = 0x40, + ZDO_AUTO_FIND_DESTINATION = 0x41, + ZDO_EXT_REMOVE_GROUP = 0x47, + ZDO_EXT_REMOVE_ALL_GROUP = 0x48, + ZDO_EXT_FIND_ALL_GROUPS_ENDPOINT = 0x49, + ZDO_EXT_FIND_GROUP = 0x4A, + ZDO_EXT_ADD_GROUP = 0x4B, + ZDO_EXT_COUNT_ALL_GROUPS = 0x4C, + ZDO_NWK_ADDR_RSP = 0x80, + ZDO_IEEE_ADDR_RSP = 0x81, + ZDO_NODE_DESC_RSP = 0x82, + ZDO_POWER_DESC_RSP = 0x83, + ZDO_SIMPLE_DESC_RSP = 0x84, + ZDO_ACTIVE_EP_RSP = 0x85, + ZDO_MATCH_DESC_RSP = 0x86, + ZDO_COMPLEX_DESC_RSP = 0x87, + ZDO_USER_DESC_RSP = 0x88, + ZDO_USER_DESC_CONF = 0x89, + ZDO_SERVER_DISC_RSP = 0x8A, + ZDO_END_DEVICE_BIND_RSP = 0xA0, + ZDO_BIND_RSP = 0xA1, + ZDO_UNBIND_RSP = 0xA2, + ZDO_MGMT_NWK_DISC_RSP = 0xB0, + ZDO_MGMT_LQI_RSP = 0xB1, + ZDO_MGMT_RTG_RSP = 0xB2, + ZDO_MGMT_BIND_RSP = 0xB3, + ZDO_MGMT_LEAVE_RSP = 0xB4, + ZDO_MGMT_DIRECT_JOIN_RSP = 0xB5, + ZDO_MGMT_PERMIT_JOIN_RSP = 0xB6, + ZDO_STATE_CHANGE_IND = 0xC0, + ZDO_END_DEVICE_ANNCE_IND = 0xC1, + ZDO_MATCH_DESC_RSP_SENT = 0xC2, + ZDO_STATUS_ERROR_RSP = 0xC3, + ZDO_SRC_RTG_IND = 0xC4, + ZDO_LEAVE_IND = 0xC9, + ZDO_TC_DEV_IND = 0xCA, + ZDO_PERMIT_JOIN_IND = 0xCB, + ZDO_MSG_CB_INCOMING = 0xFF +}; + + +enum ZdoStates { + ZDO_DEV_HOLD = 0x00, + ZDO_DEV_INIT = 0x01, + ZDO_DEV_NWK_DISC = 0x02, + ZDO_DEV_NWK_JOINING = 0x03, + ZDO_DEV_NWK_REJOIN = 0x04, + ZDO_DEV_END_DEVICE_UNAUTH = 0x05, + ZDO_DEV_END_DEVICE = 0x06, + ZDO_DEV_ROUTER = 0x07, + ZDO_DEV_COORD_STARTING = 0x08, + ZDO_DEV_ZB_COORD = 0x09, + ZDO_DEV_NWK_ORPHAN = 0x0A, +}; + + +enum Z_Util { + Z_UTIL_GET_DEVICE_INFO = 0x00, + Z_UTIL_GET_NV_INFO = 0x01, + Z_UTIL_SET_PANID = 0x02, + Z_UTIL_SET_CHANNELS = 0x03, + Z_UTIL_SET_SECLEVEL = 0x04, + Z_UTIL_SET_PRECFGKEY = 0x05, + Z_UTIL_CALLBACK_SUB_CMD = 0x06, + Z_UTIL_KEY_EVENT = 0x07, + Z_UTIL_TIME_ALIVE = 0x09, + Z_UTIL_LED_CONTROL = 0x0A, + Z_UTIL_TEST_LOOPBACK = 0x10, + Z_UTIL_DATA_REQ = 0x11, + Z_UTIL_SRC_MATCH_ENABLE = 0x20, + Z_UTIL_SRC_MATCH_ADD_ENTRY = 0x21, + Z_UTIL_SRC_MATCH_DEL_ENTRY = 0x22, + Z_UTIL_SRC_MATCH_CHECK_SRC_ADDR = 0x23, + Z_UTIL_SRC_MATCH_ACK_ALL_PENDING = 0x24, + Z_UTIL_SRC_MATCH_CHECK_ALL_PENDING = 0x25, + Z_UTIL_ADDRMGR_EXT_ADDR_LOOKUP = 0x40, + Z_UTIL_ADDRMGR_NWK_ADDR_LOOKUP = 0x41, + Z_UTIL_APSME_LINK_KEY_DATA_GET = 0x44, + Z_UTIL_APSME_LINK_KEY_NV_ID_GET = 0x45, + Z_UTIL_ASSOC_COUNT = 0x48, + Z_UTIL_ASSOC_FIND_DEVICE = 0x49, + Z_UTIL_ASSOC_GET_WITH_ADDRESS = 0x4A, + Z_UTIL_APSME_REQUEST_KEY_CMD = 0x4B, + Z_UTIL_ZCL_KEY_EST_INIT_EST = 0x80, + Z_UTIL_ZCL_KEY_EST_SIGN = 0x81, + Z_UTIL_UTIL_SYNC_REQ = 0xE0, + Z_UTIL_ZCL_KEY_ESTABLISH_IND = 0xE1 +}; + +enum ZCL_Global_Commands { + ZCL_READ_ATTRIBUTES = 0x00, + ZCL_READ_ATTRIBUTES_RESPONSE = 0x01, + ZCL_WRITE_ATTRIBUTES = 0x02, + ZCL_WRITE_ATTRIBUTES_UNDIVIDED = 0x03, + ZCL_WRITE_ATTRIBUTES_RESPONSE = 0x04, + ZCL_WRITE_ATTRIBUTES_NORESPONSE = 0x05, + ZCL_CONFIGURE_REPORTING = 0x06, + ZCL_CONFIGURE_REPORTING_RESPONSE = 0x07, + ZCL_READ_REPORTING_CONFIGURATION = 0x08, + ZCL_READ_REPORTING_CONFIGURATION_RESPONSE = 0x09, + ZCL_REPORT_ATTRIBUTES = 0x0a, + ZCL_DEFAULT_RESPONSE = 0x0b, + ZCL_DISCOVER_ATTRIBUTES = 0x0c, + ZCL_DISCOVER_ATTRIBUTES_RESPONSE = 0x0d + +}; + +const uint16_t Z_ProfileIds[] PROGMEM = { 0x0104, 0x0109, 0xA10E, 0xC05E }; +const char Z_ProfileNames[] PROGMEM = "ZigBee Home Automation|ZigBee Smart Energy|ZigBee Green Power|ZigBee Light Link"; + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" +#ifdef USE_ZIGBEE + + + +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1); + + + +JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { + + if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) { + return *(JsonVariant*)nullptr; + } + + for (auto kv : json) { + const char *key = kv.key; + JsonVariant &value = kv.value; + + if (0 == strcasecmp_P(key, needle)) { + return value; + } + } + + return *(JsonVariant*)nullptr; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +#ifdef USE_ZIGBEE + +#include +#include + +#ifndef ZIGBEE_SAVE_DELAY_SECONDS +#define ZIGBEE_SAVE_DELAY_SECONDS 10; +#endif +const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; + +typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); + +typedef struct Z_Device { + uint16_t shortaddr; + uint64_t longaddr; + uint32_t firstSeen; + uint32_t lastSeen; + String manufacturerId; + String modelId; + String friendlyName; + std::vector endpoints; + std::vector clusters_in; + std::vector clusters_out; + + uint32_t timer; + uint16_t cluster; + uint16_t endpoint; + uint32_t value; + Z_DeviceTimer func; + + DynamicJsonBuffer *json_buffer; + JsonObject *json; +} Z_Device; + + + + + + + +class Z_Devices { +public: + Z_Devices() {}; + + + + + + + uint16_t isKnownShortAddr(uint16_t shortaddr) const; + uint16_t isKnownLongAddr(uint64_t longaddr) const; + uint16_t isKnownIndex(uint32_t index) const; + uint16_t isKnownFriendlyName(const char * name) const; + + uint64_t getDeviceLongAddr(uint16_t shortaddr) const; + + + + void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); + + + void addEndoint(uint16_t shortaddr, uint8_t endpoint); + + + void addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId); + + + void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out); + + uint8_t findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster); + + void setManufId(uint16_t shortaddr, const char * str); + void setModelId(uint16_t shortaddr, const char * str); + void setFriendlyName(uint16_t shortaddr, const char * str); + const String * getFriendlyName(uint16_t) const; + + + void updateLastSeen(uint16_t shortaddr); + + + String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; + + + void resetTimer(uint32_t shortaddr); + void setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func); + void runTimer(void); + + + void jsonClear(uint16_t shortaddr); + void jsonAppend(uint16_t shortaddr, const JsonObject &values); + const JsonObject *jsonGet(uint16_t shortaddr); + void jsonPublishFlush(uint16_t shortaddr); + bool jsonIsConflict(uint16_t shortaddr, const JsonObject &values); + void jsonPublishNow(uint16_t shortaddr, JsonObject &values); + + + size_t devicesSize(void) const { + return _devices.size(); + } + const Z_Device &devicesAt(size_t i) const { + return _devices.at(i); + } + + + bool removeDevice(uint16_t shortaddr); + + + void dirty(void); + void clean(void); + + + uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const; + +private: + std::vector _devices = {}; + uint32_t _saveTimer = 0; + + template < typename T> + static bool findInVector(const std::vector & vecOfElements, const T & element); + + template < typename T> + static int32_t findEndpointInVector(const std::vector & vecOfElements, uint8_t element); + + + static int32_t findClusterEndpoint(const std::vector & vecOfElements, uint16_t element); + + Z_Device & getShortAddr(uint16_t shortaddr); + const Z_Device & getShortAddrConst(uint16_t shortaddr) const ; + Z_Device & getLongAddr(uint64_t longaddr); + + int32_t findShortAddr(uint16_t shortaddr) const; + int32_t findLongAddr(uint64_t longaddr) const; + int32_t findFriendlyName(const char * name) const; + + void _updateLastSeen(Z_Device &device) { + if (&device != nullptr) { + device.lastSeen = Rtc.utc_time; + } + }; + + + Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0); +}; + +Z_Devices zigbee_devices = Z_Devices(); + + +uint64_t localIEEEAddr = 0; + + +template < typename T> +bool Z_Devices::findInVector(const std::vector & vecOfElements, const T & element) { + + auto it = std::find(vecOfElements.begin(), vecOfElements.end(), element); + + if (it != vecOfElements.end()) { + return true; + } else { + return false; + } +} + +template < typename T> +int32_t Z_Devices::findEndpointInVector(const std::vector & vecOfElements, uint8_t element) { + + + int32_t found = 0; + for (auto &elem : vecOfElements) { + if ( ((elem >> 16) & 0xFF) == element) { return found; } + found++; + } + + return -1; +} +# 204 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +int32_t Z_Devices::findClusterEndpoint(const std::vector & vecOfElements, uint16_t cluster) { + int32_t found = 0; + for (auto &elem : vecOfElements) { + if ((elem & 0xFFFF) == cluster) { return found; } + found++; + } + return -1; +} + + + + + +Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { + if (!shortaddr && !longaddr) { return *(Z_Device*) nullptr; } + Z_Device device = { shortaddr, longaddr, + Rtc.utc_time, Rtc.utc_time, + String(), + String(), + String(), + std::vector(), + std::vector(), + std::vector(), + 0,0,0,0, + nullptr, + nullptr, nullptr }; + device.json_buffer = new DynamicJsonBuffer(); + _devices.push_back(device); + dirty(); + return _devices.back(); +} +# 244 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +int32_t Z_Devices::findShortAddr(uint16_t shortaddr) const { + if (!shortaddr) { return -1; } + int32_t found = 0; + if (shortaddr) { + for (auto &elem : _devices) { + if (elem.shortaddr == shortaddr) { return found; } + found++; + } + } + return -1; +} +# 263 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +int32_t Z_Devices::findLongAddr(uint64_t longaddr) const { + if (!longaddr) { return -1; } + int32_t found = 0; + if (longaddr) { + for (auto &elem : _devices) { + if (elem.longaddr == longaddr) { return found; } + found++; + } + } + return -1; +} +# 282 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +int32_t Z_Devices::findFriendlyName(const char * name) const { + if (!name) { return -1; } + size_t name_len = strlen(name); + int32_t found = 0; + if (name_len) { + for (auto &elem : _devices) { + if (elem.friendlyName == name) { return found; } + found++; + } + } + return -1; +} + + +uint16_t Z_Devices::isKnownShortAddr(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + return shortaddr; + } else { + return 0; + } +} + +uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const { + int32_t found = findLongAddr(longaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.shortaddr; + } else { + return 0; + } +} + +uint16_t Z_Devices::isKnownIndex(uint32_t index) const { + if (index < devicesSize()) { + const Z_Device & device = devicesAt(index); + return device.shortaddr; + } else { + return 0; + } +} + +uint16_t Z_Devices::isKnownFriendlyName(const char * name) const { + if ((!name) || (0 == strlen(name))) { return 0xFFFF; } + int32_t found = findFriendlyName(name); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.shortaddr; + } else { + return 0; + } +} + +uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const { + const Z_Device & device = getShortAddrConst(shortaddr); + return device.longaddr; +} + + + + +Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) { + if (!shortaddr) { return *(Z_Device*) nullptr; } + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + return _devices[found]; + } + + return createDeviceEntry(shortaddr, 0); +} + +const Z_Device & Z_Devices::getShortAddrConst(uint16_t shortaddr) const { + if (!shortaddr) { return *(Z_Device*) nullptr; } + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + return _devices[found]; + } + return *((Z_Device*)nullptr); +} + + +Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) { + if (!longaddr) { return *(Z_Device*) nullptr; } + int32_t found = findLongAddr(longaddr); + if (found > 0) { + return _devices[found]; + } + return createDeviceEntry(0, longaddr); +} + + +bool Z_Devices::removeDevice(uint16_t shortaddr) { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + _devices.erase(_devices.begin() + found); + dirty(); + return true; + } + return false; +} + + + + + + +void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { + int32_t s_found = findShortAddr(shortaddr); + int32_t l_found = findLongAddr(longaddr); + + if ((s_found >= 0) && (l_found >= 0)) { + if (s_found == l_found) { + updateLastSeen(shortaddr); + } else { + + _devices[l_found].shortaddr = shortaddr; + + _devices.erase(_devices.begin() + s_found); + updateLastSeen(shortaddr); + dirty(); + } + } else if (s_found >= 0) { + + + _devices[s_found].longaddr = longaddr; + updateLastSeen(shortaddr); + dirty(); + } else if (l_found >= 0) { + + _devices[l_found].shortaddr = shortaddr; + dirty(); + } else { + + if (shortaddr || longaddr) { + createDeviceEntry(shortaddr, longaddr); + } + } +} + + + + +void Z_Devices::addEndoint(uint16_t shortaddr, uint8_t endpoint) { + if (!shortaddr) { return; } + uint32_t ep_profile = (endpoint << 16); + Z_Device &device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + if (findEndpointInVector(device.endpoints, endpoint) < 0) { + device.endpoints.push_back(ep_profile); + dirty(); + } +} + +void Z_Devices::addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId) { + if (!shortaddr) { return; } + uint32_t ep_profile = (endpoint << 16) | profileId; + Z_Device &device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + int32_t found = findEndpointInVector(device.endpoints, endpoint); + if (found < 0) { + device.endpoints.push_back(ep_profile); + dirty(); + } else { + if (device.endpoints[found] != ep_profile) { + device.endpoints[found] = ep_profile; + dirty(); + } + } +} + +void Z_Devices::addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out) { + if (!shortaddr) { return; } + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + uint32_t ep_cluster = (endpoint << 16) | cluster; + if (!out) { + if (!findInVector(device.clusters_in, ep_cluster)) { + device.clusters_in.push_back(ep_cluster); + dirty(); + } + } else { + if (!findInVector(device.clusters_out, ep_cluster)) { + device.clusters_out.push_back(ep_cluster); + dirty(); + } + } +} + + + +uint8_t Z_Devices::findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster){ + int32_t short_found = findShortAddr(shortaddr); + if (short_found < 0) return 0; + Z_Device &device = getShortAddr(shortaddr); + if (&device == nullptr) { return 0; } + int32_t found = findClusterEndpoint(device.clusters_in, cluster); + if (found >= 0) { + return (device.clusters_in[found] >> 16) & 0xFF; + } else { + return 0; + } +} + + +void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + if (!device.manufacturerId.equals(str)) { + dirty(); + } + device.manufacturerId = str; +} +void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + if (!device.modelId.equals(str)) { + dirty(); + } + device.modelId = str; +} +void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + if (!device.friendlyName.equals(str)) { + dirty(); + } + device.friendlyName = str; +} + +const String * Z_Devices::getFriendlyName(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + if (device.friendlyName.length() > 0) { + return &device.friendlyName; + } + } + return nullptr; +} + + +void Z_Devices::updateLastSeen(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); +} + + + + +void Z_Devices::resetTimer(uint32_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + device.timer = 0; + device.func = nullptr; +} + + +void Z_Devices::setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + + device.cluster = cluster; + device.endpoint = endpoint; + device.value = value; + device.func = func; + device.timer = wait_ms + millis(); +} + + +void Z_Devices::runTimer(void) { + for (std::vector::iterator it = _devices.begin(); it != _devices.end(); ++it) { + Z_Device &device = *it; + uint16_t shortaddr = device.shortaddr; + + uint32_t timer = device.timer; + if ((timer) && TimeReached(timer)) { + device.timer = 0; + + (*device.func)(device.shortaddr, device.cluster, device.endpoint, device.value); + } + } + + if ((_saveTimer) && TimeReached(_saveTimer)) { + saveZigbeeDevices(); + _saveTimer = 0; + } +} + +void Z_Devices::jsonClear(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + + device.json = nullptr; + device.json_buffer->clear(); +} + +void CopyJsonVariant(JsonObject &to, const String &key, const JsonVariant &val) { + to.remove(key); + + if (val.is()) { + String sval = val.as(); + to.set(key, sval); + } else if (val.is()) { + JsonArray &nested_arr = to.createNestedArray(key); + CopyJsonArray(nested_arr, val.as()); + } else if (val.is()) { + JsonObject &nested_obj = to.createNestedObject(key); + CopyJsonObject(nested_obj, val.as()); + } else { + to.set(key, val); + } +} + +void CopyJsonArray(JsonArray &to, const JsonArray &arr) { + for (auto v : arr) { + if (v.is()) { + String sval = v.as(); + to.add(sval); + } else if (v.is()) { + } else if (v.is()) { + } else { + to.add(v); + } + } +} + +void CopyJsonObject(JsonObject &to, const JsonObject &from) { + for (auto kv : from) { + String key_string = kv.key; + JsonVariant &val = kv.value; + + CopyJsonVariant(to, key_string, val); + } +} + + +bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const JsonObject &values) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return false; } + if (&values == nullptr) { return false; } + + if (nullptr == device.json) { + return false; + } + + for (auto kv : values) { + String key_string = kv.key; + + if (strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_LINKQUALITY))) { + if (device.json->containsKey(kv.key)) { + return true; + } + } + } + return false; +} + +void Z_Devices::jsonAppend(uint16_t shortaddr, const JsonObject &values) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + if (&values == nullptr) { return; } + + if (nullptr == device.json) { + device.json = &(device.json_buffer->createObject()); + } + + char sa[8]; + snprintf_P(sa, sizeof(sa), PSTR("0x%04X"), shortaddr); + device.json->set(F(D_JSON_ZIGBEE_DEVICE), sa); + + const String * fname = zigbee_devices.getFriendlyName(shortaddr); + if (fname) { + device.json->set(F(D_JSON_ZIGBEE_NAME), (char*)fname->c_str()); + } + + + CopyJsonObject(*device.json, values); +} + +const JsonObject *Z_Devices::jsonGet(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return nullptr; } + return device.json; +} + +void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + JsonObject * json = device.json; + if (json == nullptr) { return; } + + const String * fname = zigbee_devices.getFriendlyName(shortaddr); + bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); +# 693 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" + if (use_fname) { + json->remove(F(D_JSON_ZIGBEE_NAME)); + } else { + json->remove(F(D_JSON_ZIGBEE_DEVICE)); + } + + String msg = ""; + json->printTo(msg); + zigbee_devices.jsonClear(shortaddr); + + if (use_fname) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + } + + +} + +void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { + jsonPublishFlush(shortaddr); + jsonAppend(shortaddr, values); + jsonPublishFlush(shortaddr); +} + +void Z_Devices::dirty(void) { + _saveTimer = kZigbeeSaveDelaySeconds * 1000 + millis(); +} +void Z_Devices::clean(void) { + _saveTimer = 0; +} + + + + + + +uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const { + if (nullptr == param) { return 0; } + size_t param_len = strlen(param); + char dataBuf[param_len + 1]; + strcpy(dataBuf, param); + RemoveSpace(dataBuf); + uint16_t shortaddr = 0; + + if (strlen(dataBuf) < 4) { + + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) { + shortaddr = zigbee_devices.isKnownIndex(XdrvMailbox.payload - 1); + } + } else if ((dataBuf[0] == '0') && (dataBuf[1] == 'x')) { + + if (strlen(dataBuf) < 18) { + + shortaddr = strtoull(dataBuf, nullptr, 0); + if (short_must_be_known) { + shortaddr = zigbee_devices.isKnownShortAddr(shortaddr); + } + + } else { + + uint64_t longaddr = strtoull(dataBuf, nullptr, 0); + shortaddr = zigbee_devices.isKnownLongAddr(longaddr); + } + } else { + + shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf); + } + + return shortaddr; +} + + + + + +String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { + DynamicJsonBuffer jsonBuffer; + JsonArray& json = jsonBuffer.createArray(); + JsonArray& devices = json; + + for (std::vector::const_iterator it = _devices.begin(); it != _devices.end(); ++it) { + const Z_Device& device = *it; + uint16_t shortaddr = device.shortaddr; + char hex[22]; + + + if ((status_shortaddr) && (status_shortaddr != shortaddr)) { continue; } + + JsonObject& dev = devices.createNestedObject(); + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); + dev[F(D_JSON_ZIGBEE_DEVICE)] = hex; + + if (device.friendlyName.length() > 0) { + dev[F(D_JSON_ZIGBEE_NAME)] = device.friendlyName; + } + + if (2 <= dump_mode) { + hex[0] = '0'; + hex[1] = 'x'; + Uint64toHex(device.longaddr, &hex[2], 64); + dev[F("IEEEAddr")] = hex; + if (device.modelId.length() > 0) { + dev[F(D_JSON_MODEL D_JSON_ID)] = device.modelId; + } + if (device.manufacturerId.length() > 0) { + dev[F("Manufacturer")] = device.manufacturerId; + } + } + + + if (3 <= dump_mode) { + JsonObject& dev_endpoints = dev.createNestedObject(F("Endpoints")); + for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { + uint32_t ep_profile = *ite; + uint8_t endpoint = (ep_profile >> 16) & 0xFF; + uint16_t profileId = ep_profile & 0xFFFF; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + JsonObject& ep = dev_endpoints.createNestedObject(hex); + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), profileId); + ep[F("ProfileId")] = hex; + + int32_t found = -1; + for (uint32_t i = 0; i < sizeof(Z_ProfileIds) / sizeof(Z_ProfileIds[0]); i++) { + if (pgm_read_word(&Z_ProfileIds[i]) == profileId) { + found = i; + break; + } + } + if (found > 0) { + GetTextIndexed(hex, sizeof(hex), found, Z_ProfileNames); + ep[F("ProfileIdName")] = hex; + } + + ep.createNestedArray(F("ClustersIn")); + ep.createNestedArray(F("ClustersOut")); + } + + for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t endpoint = (*itc >> 16) & 0xFF; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersIn")]; + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); + cluster_arr.add(hex); + } + + for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t endpoint = (*itc >> 16) & 0xFF; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersOut")]; + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); + cluster_arr.add(hex); + } + } + } + String payload = ""; + payload.reserve(200); + json.printTo(payload); + return payload; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +#ifdef USE_ZIGBEE +# 50 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +const static uint16_t z_spi_start_sector = 0xFF; +const static uint8_t* z_spi_start = (uint8_t*) 0x402FF000; +const static uint8_t* z_dev_start = z_spi_start + 0x0800; +const static size_t z_spi_len = 0x1000; +const static size_t z_block_offset = 0x0800; +const static size_t z_block_len = 0x0800; + +class z_flashdata_t { +public: + uint32_t name; + uint16_t len; + uint16_t reserved; +}; + +const static uint32_t ZIGB_NAME = 0x3167697A; +const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); + + +const uint16_t Z_ClusterNumber[] PROGMEM = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0100, 0x0101, 0x0102, + 0x0201, 0x0202, 0x0203, 0x0204, + 0x0300, 0x0301, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, + 0x0500, 0x0501, 0x0502, + 0x0700, 0x0701, 0x0702, + 0x0B00, 0x0B01, 0x0B02, 0x0B03, 0x0B04, 0x0B05, + 0x1000, + 0xFC0F, +}; + + +uint16_t fromClusterCode(uint8_t c) { + if (c >= sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0])) { + return 0xFFFF; + } + return pgm_read_word(&Z_ClusterNumber[c]); +} + + +uint8_t toClusterCode(uint16_t c) { + for (uint32_t i = 0; i < sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0]); i++) { + if (c == pgm_read_word(&Z_ClusterNumber[i])) { + return i; + } + } + return 0xFF; +} + +class SBuffer hibernateDevice(const struct Z_Device &device) { + SBuffer buf(128); + + buf.add8(0x00); + buf.add16(device.shortaddr); + buf.add64(device.longaddr); + uint32_t endpoints = device.endpoints.size(); + if (endpoints > 254) { endpoints = 254; } + buf.add8(endpoints); + + for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { + uint32_t ep_profile = *ite; + uint8_t endpoint = (ep_profile >> 16) & 0xFF; + uint16_t profileId = ep_profile & 0xFFFF; + + buf.add8(endpoint); + buf.add16(profileId); + for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t c_endpoint = (*itc >> 16) & 0xFF; + + if (endpoint == c_endpoint) { + uint8_t clusterCode = toClusterCode(cluster); + if (0xFF != clusterCode) { buf.add8(clusterCode); } + } + } + buf.add8(0xFF); + + for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t c_endpoint = (*itc >> 16) & 0xFF; + + if (endpoint == c_endpoint) { + uint8_t clusterCode = toClusterCode(cluster); + if (0xFF != clusterCode) { buf.add8(clusterCode); } + } + } + buf.add8(0xFF); + } + + + size_t model_len = device.modelId.length(); + if (model_len > 32) { model_len = 32; } + buf.addBuffer(device.modelId.c_str(), model_len); + buf.add8(0x00); + + + size_t manuf_len = device.manufacturerId.length(); + if (manuf_len > 32) {manuf_len = 32; } + buf.addBuffer(device.manufacturerId.c_str(), manuf_len); + buf.add8(0x00); + + + size_t frname_len = device.friendlyName.length(); + if (frname_len > 32) {frname_len = 32; } + buf.addBuffer(device.friendlyName.c_str(), frname_len); + buf.add8(0x00); + + + buf.set8(0, buf.len()); + + return buf; +} + +class SBuffer hibernateDevices(void) { + SBuffer buf(2048); + + size_t devices_size = zigbee_devices.devicesSize(); + if (devices_size > 32) { devices_size = 32; } + buf.add8(devices_size); + + for (uint32_t i = 0; i < devices_size; i++) { + const Z_Device & device = zigbee_devices.devicesAt(i); + const SBuffer buf_device = hibernateDevice(device); + buf.addBuffer(buf_device); + } + + size_t buf_len = buf.len(); + if (buf_len > 2040) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Devices list too big to fit in Flash (%d)"), buf_len); + } + + + char *hex_char = (char*) malloc((buf_len * 2) + 2); + if (hex_char) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbFlashStore %s"), + ToHex_P(buf.getBuffer(), buf_len, hex_char, (buf_len * 2) + 2)); + free(hex_char); + } + + return buf; +} + +void hidrateDevices(const SBuffer &buf) { + uint32_t buf_len = buf.len(); + if (buf_len <= 10) { return; } + + uint32_t k = 0; + uint32_t num_devices = buf.get8(k++); + + for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { + uint32_t dev_record_len = buf.get8(k); + + SBuffer buf_d = buf.subBuffer(k, dev_record_len); + + uint32_t d = 1; + uint16_t shortaddr = buf_d.get16(d); d += 2; + uint64_t longaddr = buf_d.get64(d); d += 8; + zigbee_devices.updateDevice(shortaddr, longaddr); + + uint32_t endpoints = buf_d.get8(d++); + for (uint32_t j = 0; j < endpoints; j++) { + uint8_t ep = buf_d.get8(d++); + uint16_t ep_profile = buf_d.get16(d); d += 2; + zigbee_devices.addEndointProfile(shortaddr, ep, ep_profile); + + + while (d < dev_record_len) { + uint8_t ep_cluster = buf_d.get8(d++); + if (0xFF == ep_cluster) { break; } + zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), false); + } + + while (d < dev_record_len) { + uint8_t ep_cluster = buf_d.get8(d++); + if (0xFF == ep_cluster) { break; } + zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), true); + } + } + + + char empty[] = ""; + + + uint32_t s_len = buf_d.strlen_s(d); + char *ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setModelId(shortaddr, ptr); + d += s_len + 1; + + + s_len = buf_d.strlen_s(d); + ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setManufId(shortaddr, ptr); + d += s_len + 1; + + + s_len = buf_d.strlen_s(d); + ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setFriendlyName(shortaddr, ptr); + d += s_len + 1; + + + k += dev_record_len; + } +} + +void loadZigbeeDevices(void) { + z_flashdata_t flashdata; + memcpy_P(&flashdata, z_dev_start, sizeof(z_flashdata_t)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Zigbee signature in Flash: %08X - %d"), flashdata.name, flashdata.len); + + + if ((flashdata.name == ZIGB_NAME) && (flashdata.len > 0)) { + uint16_t buf_len = flashdata.len; + + SBuffer buf(buf_len); + buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); + hidrateDevices(buf); + zigbee_devices.clean(); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "No zigbee devices data in Flash")); + } +} + +void saveZigbeeDevices(void) { + SBuffer buf = hibernateDevices(); + size_t buf_len = buf.len(); + if (buf_len > Z_MAX_FLASH) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Buffer too big to fit in Flash (%d bytes)"), buf_len); + return; + } + + + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + + ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + + z_flashdata_t *flashdata = (z_flashdata_t*)(spi_buffer + z_block_offset); + flashdata->name = ZIGB_NAME; + flashdata->len = buf_len; + flashdata->reserved = 0; + + memcpy(spi_buffer + z_block_offset + sizeof(z_flashdata_t), buf.getBuffer(), buf_len); + + + if (ESP.flashEraseSector(z_spi_start_sector)) { + ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + + free(spi_buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data store in Flash (0x%08X - %d bytes)"), z_dev_start, buf_len); +} + + +void eraseZigbeeDevices(void) { + zigbee_devices.clean(); + + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + + ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + + + memset(spi_buffer + z_block_offset, 0xFF, z_block_len); + + + if (ESP.flashEraseSector(z_spi_start_sector)) { + ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + + free(spi_buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (0x%08X - %d bytes)"), z_dev_start, z_block_len); +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" +#ifdef USE_ZIGBEE + + + + + +typedef union ZCLHeaderFrameControl_t { + struct { + uint8_t frame_type : 2; + uint8_t manuf_specific : 1; + uint8_t direction : 1; + uint8_t disable_def_resp : 1; + uint8_t reserved : 3; + } b; + uint32_t d8; +} ZCLHeaderFrameControl_t; + + +class ZCLFrame { +public: + + ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id, + const char *buf, size_t buf_len, uint16_t clusterid, uint16_t groupid, + uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, + uint32_t timestamp): + _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), + _payload(buf_len ? buf_len : 250), + _cluster_id(clusterid), _group_id(groupid), + _srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast), + _linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber), + _timestamp(timestamp) + { + _frame_control.d8 = frame_control; + _payload.addBuffer(buf, buf_len); + }; + + + void log(void) { + char hex_char[_payload.len()*2+2]; + ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); + Response_P(PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" + "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," + "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," + "\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," + "\"timestamp\":%d," + "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," + "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), + _group_id, _cluster_id, _srcaddr, + _srcendpoint, _dstendpoint, _wasbroadcast, + _linkquality, _securityuse, _seqnumber, + _timestamp, + _frame_control, _manuf_code, _transact_seq, _cmd_id, + hex_char); + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); + } + } + + static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid, + uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, + uint32_t timestamp) { + uint32_t i = offset; + ZCLHeaderFrameControl_t frame_control; + uint16_t manuf_code = 0; + uint8_t transact_seq; + uint8_t cmd_id; + + frame_control.d8 = buf.get8(i++); + if (frame_control.b.manuf_specific) { + manuf_code = buf.get16(i); + i += 2; + } + transact_seq = buf.get8(i++); + cmd_id = buf.get8(i++); + ZCLFrame zcl_frame(frame_control.d8, manuf_code, transact_seq, cmd_id, + (const char *)(buf.buf() + i), len + offset - i, + clusterid, groupid, + srcaddr, srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp); + return zcl_frame; + } + + bool isClusterSpecificCommand(void) { + return _frame_control.b.frame_type & 1; + } + + static void generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len); + void parseRawAttributes(JsonObject& json, uint8_t offset = 0); + void parseReadAttributes(JsonObject& json, uint8_t offset = 0); + void parseClusterSpecificCommand(JsonObject& json, uint8_t offset = 0); + void postProcessAttributes(uint16_t shortaddr, JsonObject& json); + + inline void setGroupId(uint16_t groupid) { + _group_id = groupid; + } + + inline void setClusterId(uint16_t clusterid) { + _cluster_id = clusterid; + } + + inline uint8_t getCmdId(void) const { + return _cmd_id; + } + + inline uint16_t getClusterId(void) const { + return _cluster_id; + } + + inline uint16_t getSrcEndpoint(void) const { + return _srcendpoint; + } + + const SBuffer &getPayload(void) const { + return _payload; + } + + uint16_t getManufCode(void) const { + return _manuf_code; + } + +private: + ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; + uint16_t _manuf_code = 0; + uint8_t _transact_seq = 0; + uint8_t _cmd_id = 0; + uint16_t _cluster_id = 0; + uint16_t _group_id = 0; + SBuffer _payload; + + uint16_t _srcaddr; + uint8_t _srcendpoint; + uint8_t _dstendpoint; + uint8_t _wasbroadcast; + uint8_t _linkquality; + uint8_t _securityuse; + uint8_t _seqnumber; + uint32_t _timestamp; +}; + + + + + + +uint8_t toPercentageCR2032(uint32_t voltage) { + uint32_t percentage; + if (voltage < 2100) { + percentage = 0; + } else if (voltage < 2440) { + percentage = 6 - ((2440 - voltage) * 6) / 340; + } else if (voltage < 2740) { + percentage = 18 - ((2740 - voltage) * 12) / 300; + } else if (voltage < 2900) { + percentage = 42 - ((2900 - voltage) * 24) / 160; + } else if (voltage < 3000) { + percentage = 100 - ((3000 - voltage) * 58) / 100; + } else if (voltage >= 3000) { + percentage = 100; + } + return percentage; +} + + +uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, + uint32_t offset, uint32_t len) { + + uint32_t i = offset; + uint32_t attrtype = buf.get8(i++); + + + json[attrid_str] = (char*) nullptr; + + + switch (attrtype) { + case 0x00: + case 0xFF: + break; + case 0x10: + { + uint8_t val_bool = buf.get8(i++); + if (0xFF != val_bool) { + json[attrid_str] = (bool) (val_bool ? true : false); + } + } + break; + case 0x20: + { + uint8_t uint8_val = buf.get8(i); + i += 1; + if (0xFF != uint8_val) { + json[attrid_str] = uint8_val; + } + } + break; + case 0x21: + { + uint16_t uint16_val = buf.get16(i); + i += 2; + if (0xFFFF != uint16_val) { + json[attrid_str] = uint16_val; + } + } + break; + case 0x23: + { + uint32_t uint32_val = buf.get32(i); + i += 4; + if (0xFFFFFFFF != uint32_val) { + json[attrid_str] = uint32_val; + } + } + break; + + case 0x24: + case 0x25: + case 0x26: + case 0x27: + { + uint8_t len = attrtype - 0x1F; + + char hex[2*len+1]; + ToHex_P(buf.buf(i), len, hex, sizeof(hex)); + json[attrid_str] = hex; + i += len; + } + break; + case 0x28: + { + int8_t int8_val = buf.get8(i); + i += 1; + if (0x80 != int8_val) { + json[attrid_str] = int8_val; + } + } + break; + case 0x29: + { + int16_t int16_val = buf.get16(i); + i += 2; + if (0x8000 != int16_val) { + json[attrid_str] = int16_val; + } + } + break; + case 0x2B: + { + int32_t int32_val = buf.get32(i); + i += 4; + if (0x80000000 != int32_val) { + json[attrid_str] = int32_val; + } + } + break; + + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + { + uint8_t len = attrtype - 0x27; + + char hex[2*len+1]; + ToHex_P(buf.buf(i), len, hex, sizeof(hex)); + json[attrid_str] = hex; + i += len; + } + break; + + case 0x41: + case 0x42: + case 0x43: + case 0x44: + + { + bool parse_as_string = true; + uint32_t len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); + i += (attrtype <= 0x42) ? 1 : 2; + if (i + len > buf.len()) { + len = buf.len() - i; + } + + + if ((0x41 == attrtype) || (0x43 == attrtype)) { parse_as_string = false; } +# 318 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" + if (parse_as_string) { + char str[len+1]; + strncpy(str, buf.charptr(i), len); + str[len] = 0x00; + json[attrid_str] = str; + } else { + + char hex[2*len+1]; + ToHex_P(buf.buf(i), len, hex, sizeof(hex)); + json[attrid_str] = hex; + } + + i += len; + break; + } + i += buf.get8(i) + 1; + break; + + case 0x08: + case 0x18: + { + uint8_t uint8_val = buf.get8(i); + i += 1; + json[attrid_str] = uint8_val; + } + break; + case 0x09: + case 0x19: + { + uint16_t uint16_val = buf.get16(i); + i += 2; + json[attrid_str] = uint16_val; + } + break; + case 0x0B: + case 0x1B: + { + uint32_t uint32_val = buf.get32(i); + i += 4; + json[attrid_str] = uint32_val; + } + break; + + case 0x30: + case 0x31: + i += attrtype - 0x2F; + break; + + + case 0x39: + { + uint32_t uint32_val = buf.get32(i); + float * float_val = (float*) &uint32_val; + i += 4; + json[attrid_str] = *float_val; + } + break; + + case 0xE0: + case 0xE1: + case 0xE2: + i += 4; + break; + + case 0xE8: + case 0xE9: + i += 2; + break; + case 0xEA: + i += 4; + break; + + case 0xF0: + i += 8; + break; + case 0xF1: + i += 16; + break; + + + case 0x0A: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + i += attrtype - 0x07; + break; + + case 0x1A: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + i += attrtype - 0x17; + break; + + case 0x38: + i += 2; + break; + case 0x3A: + { + uint64_t uint64_val = buf.get64(i); + double * double_val = (double*) &uint64_val; + i += 8; + json[attrid_str] = *double_val; + } + break; + } + + + + + + + return i - offset; +} + + +void ZCLFrame::generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len) { + uint32_t suffix = 1; + + snprintf_P(key, key_len, PSTR("%04X/%04X"), cluster, attr); + while (json.containsKey(key)) { + suffix++; + snprintf_P(key, key_len, PSTR("%04X/%04X+%d"), cluster, attr, suffix); + } +} + + +void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { + uint32_t i = offset; + uint32_t len = _payload.len(); + + while (len >= i + 3) { + uint16_t attrid = _payload.get16(i); + i += 2; + + char key[16]; + generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); + + + if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { + if (0x42 == _payload.get8(i)) { + _payload.set8(i, 0x41); + } + } + i += parseSingleAttribute(json, key, _payload, i, len); + } +} + + +void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { + uint32_t i = offset; + uint32_t len = _payload.len(); + + while (len - i >= 4) { + uint16_t attrid = _payload.get16(i); + i += 2; + uint8_t status = _payload.get8(i++); + + if (0 == status) { + char key[16]; + generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); + + i += parseSingleAttribute(json, key, _payload, i, len); + } + } +} + + + + +void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { + uint32_t i = offset; + uint32_t len = _payload.len(); + + char attrid_str[12]; + snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X!%02X"), _cluster_id, _cmd_id); + + char hex_char[_payload.len()*2+2]; + ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); + + json[attrid_str] = hex_char; +} + + + + +typedef int32_t (*Z_AttrConverter)(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +typedef struct Z_AttributeConverter { + uint16_t cluster; + uint16_t attribute; + const char * name; + Z_AttrConverter func; +} Z_AttributeConverter; + + +const Z_AttributeConverter Z_PostProcess[] PROGMEM = { + { 0x0000, 0x0000, "ZCLVersion", &Z_Copy }, + { 0x0000, 0x0001, "AppVersion", &Z_Copy }, + { 0x0000, 0x0002, "StackVersion", &Z_Copy }, + { 0x0000, 0x0003, "HWVersion", &Z_Copy }, + { 0x0000, 0x0004, "Manufacturer", &Z_ManufKeep }, + { 0x0000, 0x0005, D_JSON_MODEL D_JSON_ID, &Z_ModelKeep }, + { 0x0000, 0x0006, "DateCode", &Z_Copy }, + { 0x0000, 0x0007, "PowerSource", &Z_Copy }, + { 0x0000, 0x4000, "SWBuildID", &Z_Copy }, + { 0x0000, 0xFFFF, nullptr, &Z_Remove }, + + { 0x0000, 0xFF01, nullptr, &Z_AqaraSensor }, + + + { 0x0001, 0x0000, "MainsVoltage", &Z_Copy }, + { 0x0001, 0x0001, "MainsFrequency", &Z_Copy }, + { 0x0001, 0x0020, "BatteryVoltage", &Z_Copy }, + { 0x0001, 0x0021, "BatteryPercentageRemaining",&Z_Copy }, + + + { 0x0002, 0x0000, "CurrentTemperature", &Z_Copy }, + { 0x0002, 0x0001, "MinTempExperienced", &Z_Copy }, + { 0x0002, 0x0002, "MaxTempExperienced", &Z_Copy }, + { 0x0002, 0x0003, "OverTempTotalDwell", &Z_Copy }, + + + { 0x0006, 0x0000, "Power", &Z_Copy }, + { 0x0006, 0x8000, "Power", &Z_Copy }, + + + { 0x0007, 0x0000, "SwitchType", &Z_Copy }, + + + { 0x0008, 0x0000, "Dimmer", &Z_Copy }, +# 558 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" + { 0x0009, 0x0000, "AlarmCount", &Z_Copy }, + + { 0x000A, 0x0000, "Time", &Z_Copy }, + { 0x000A, 0x0001, "TimeStatus", &Z_Copy }, + { 0x000A, 0x0002, "TimeZone", &Z_Copy }, + { 0x000A, 0x0003, "DstStart", &Z_Copy }, + { 0x000A, 0x0004, "DstStart", &Z_Copy }, + { 0x000A, 0x0005, "DstShift", &Z_Copy }, + { 0x000A, 0x0006, "StandardTime", &Z_Copy }, + { 0x000A, 0x0007, "LocalTime", &Z_Copy }, + { 0x000A, 0x0008, "LastSetTime", &Z_Copy }, + { 0x000A, 0x0009, "ValidUntilTime", &Z_Copy }, + + { 0x000B, 0x0000, "LocationType", &Z_Copy }, + { 0x000B, 0x0000, "LocationMethod", &Z_Copy }, + { 0x000B, 0x0000, "LocationAge", &Z_Copy }, + { 0x000B, 0x0000, "QualityMeasure", &Z_Copy }, + { 0x000B, 0x0000, "NumberOfDevices", &Z_Copy }, + + { 0x000C, 0x0004, "ActiveText", &Z_Copy }, + { 0x000C, 0x001C, "Description", &Z_Copy }, + { 0x000C, 0x002E, "InactiveText", &Z_Copy }, + { 0x000C, 0x0041, "MaxPresentValue", &Z_Copy }, + { 0x000C, 0x0045, "MinPresentValue", &Z_Copy }, + { 0x000C, 0x0051, "OutOfService", &Z_Copy }, + { 0x000C, 0x0055, "AqaraRotate", &Z_Copy }, + { 0x000C, 0x0057, "PriorityArray", &Z_Copy }, + { 0x000C, 0x0067, "Reliability", &Z_Copy }, + { 0x000C, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x000C, 0x006A, "Resolution", &Z_Copy }, + { 0x000C, 0x006F, "StatusFlags", &Z_Copy }, + { 0x000C, 0x0075, "EngineeringUnits", &Z_Copy }, + { 0x000C, 0x0100, "ApplicationType", &Z_Copy }, + { 0x000C, 0xFF05, "Aqara_FF05", &Z_Copy }, + + { 0x0010, 0x0004, "ActiveText", &Z_Copy }, + { 0x0010, 0x001C, "Description", &Z_Copy }, + { 0x0010, 0x002E, "InactiveText", &Z_Copy }, + { 0x0010, 0x0042, "MinimumOffTime", &Z_Copy }, + { 0x0010, 0x0043, "MinimumOnTime", &Z_Copy }, + { 0x0010, 0x0051, "OutOfService", &Z_Copy }, + { 0x0010, 0x0054, "Polarity", &Z_Copy }, + { 0x0010, 0x0055, "PresentValue", &Z_Copy }, + { 0x0010, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0010, 0x0067, "Reliability", &Z_Copy }, + { 0x0010, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0010, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0010, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x0011, 0x0004, "ActiveText", &Z_Copy }, + { 0x0011, 0x001C, "Description", &Z_Copy }, + { 0x0011, 0x002E, "InactiveText", &Z_Copy }, + { 0x0011, 0x0042, "MinimumOffTime", &Z_Copy }, + { 0x0011, 0x0043, "MinimumOnTime", &Z_Copy }, + { 0x0011, 0x0051, "OutOfService", &Z_Copy }, + { 0x0011, 0x0055, "PresentValue", &Z_Copy }, + { 0x0011, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0011, 0x0067, "Reliability", &Z_Copy }, + { 0x0011, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0011, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0011, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x0012, 0x000E, "StateText", &Z_Copy }, + { 0x0012, 0x001C, "Description", &Z_Copy }, + { 0x0012, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0012, 0x0051, "OutOfService", &Z_Copy }, + { 0x0012, 0x0055, "PresentValue", &Z_AqaraCube }, + { 0x0012, 0x0067, "Reliability", &Z_Copy }, + { 0x0012, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0012, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x0013, 0x000E, "StateText", &Z_Copy }, + { 0x0013, 0x001C, "Description", &Z_Copy }, + { 0x0013, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0013, 0x0051, "OutOfService", &Z_Copy }, + { 0x0013, 0x0055, "PresentValue", &Z_Copy }, + { 0x0013, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0013, 0x0067, "Reliability", &Z_Copy }, + { 0x0013, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0013, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0013, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x0014, 0x000E, "StateText", &Z_Copy }, + { 0x0014, 0x001C, "Description", &Z_Copy }, + { 0x0014, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0014, 0x0051, "OutOfService", &Z_Copy }, + { 0x0014, 0x0055, "PresentValue", &Z_Copy }, + { 0x0014, 0x0067, "Reliability", &Z_Copy }, + { 0x0014, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0014, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0014, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x001A, 0x0000, "TotalProfileNum", &Z_Copy }, + { 0x001A, 0x0001, "MultipleScheduling", &Z_Copy }, + { 0x001A, 0x0002, "EnergyFormatting", &Z_Copy }, + { 0x001A, 0x0003, "EnergyRemote", &Z_Copy }, + { 0x001A, 0x0004, "ScheduleMode", &Z_Copy }, + + { 0x0020, 0x0000, "CheckinInterval", &Z_Copy }, + { 0x0020, 0x0001, "LongPollInterval", &Z_Copy }, + { 0x0020, 0x0002, "ShortPollInterval", &Z_Copy }, + { 0x0020, 0x0003, "FastPollTimeout", &Z_Copy }, + { 0x0020, 0x0004, "CheckinIntervalMin", &Z_Copy }, + { 0x0020, 0x0005, "LongPollIntervalMin", &Z_Copy }, + { 0x0020, 0x0006, "FastPollTimeoutMax", &Z_Copy }, + + { 0x0100, 0x0000, "PhysicalClosedLimit", &Z_Copy }, + { 0x0100, 0x0001, "MotorStepSize", &Z_Copy }, + { 0x0100, 0x0002, "Status", &Z_Copy }, + { 0x0100, 0x0010, "ClosedLimit", &Z_Copy }, + { 0x0100, 0x0011, "Mode", &Z_Copy }, + + { 0x0101, 0x0000, "LockState", &Z_Copy }, + { 0x0101, 0x0001, "LockType", &Z_Copy }, + { 0x0101, 0x0002, "ActuatorEnabled", &Z_Copy }, + { 0x0101, 0x0003, "DoorState", &Z_Copy }, + { 0x0101, 0x0004, "DoorOpenEvents", &Z_Copy }, + { 0x0101, 0x0005, "DoorClosedEvents", &Z_Copy }, + { 0x0101, 0x0006, "OpenPeriod", &Z_Copy }, + + { 0x0101, 0x0055, "AqaraVibrationMode", &Z_AqaraVibration }, + { 0x0101, 0x0503, "AqaraVibrationsOrAngle", &Z_Copy }, + { 0x0101, 0x0505, "AqaraVibration505", &Z_Copy }, + { 0x0101, 0x0508, "AqaraAccelerometer", &Z_AqaraVibration }, + + { 0x0102, 0x0000, "WindowCoveringType", &Z_Copy }, + { 0x0102, 0x0001, "PhysicalClosedLimitLift",&Z_Copy }, + { 0x0102, 0x0002, "PhysicalClosedLimitTilt",&Z_Copy }, + { 0x0102, 0x0003, "CurrentPositionLift", &Z_Copy }, + { 0x0102, 0x0004, "CurrentPositionTilt", &Z_Copy }, + { 0x0102, 0x0005, "NumberofActuationsLift",&Z_Copy }, + { 0x0102, 0x0006, "NumberofActuationsTilt",&Z_Copy }, + { 0x0102, 0x0007, "ConfigStatus", &Z_Copy }, + { 0x0102, 0x0008, "CurrentPositionLiftPercentage",&Z_Copy }, + { 0x0102, 0x0009, "CurrentPositionTiltPercentage",&Z_Copy }, + { 0x0102, 0x0010, "InstalledOpenLimitLift",&Z_Copy }, + { 0x0102, 0x0011, "InstalledClosedLimitLift",&Z_Copy }, + { 0x0102, 0x0012, "InstalledOpenLimitTilt", &Z_Copy }, + { 0x0102, 0x0013, "InstalledClosedLimitTilt", &Z_Copy }, + { 0x0102, 0x0014, "VelocityLift",&Z_Copy }, + { 0x0102, 0x0015, "AccelerationTimeLift",&Z_Copy }, + { 0x0102, 0x0016, "DecelerationTimeLift", &Z_Copy }, + { 0x0102, 0x0017, "Mode",&Z_Copy }, + { 0x0102, 0x0018, "IntermediateSetpointsLift",&Z_Copy }, + { 0x0102, 0x0019, "IntermediateSetpointsTilt",&Z_Copy }, + + + { 0x0300, 0x0000, "Hue", &Z_Copy }, + { 0x0300, 0x0001, "Sat", &Z_Copy }, + { 0x0300, 0x0002, "RemainingTime", &Z_Copy }, + { 0x0300, 0x0003, "X", &Z_Copy }, + { 0x0300, 0x0004, "Y", &Z_Copy }, + { 0x0300, 0x0005, "DriftCompensation", &Z_Copy }, + { 0x0300, 0x0006, "CompensationText", &Z_Copy }, + { 0x0300, 0x0007, "CT", &Z_Copy }, + { 0x0300, 0x0008, "ColorMode", &Z_Copy }, + { 0x0300, 0x0010, "NumberOfPrimaries", &Z_Copy }, + { 0x0300, 0x0011, "Primary1X", &Z_Copy }, + { 0x0300, 0x0012, "Primary1Y", &Z_Copy }, + { 0x0300, 0x0013, "Primary1Intensity", &Z_Copy }, + { 0x0300, 0x0015, "Primary2X", &Z_Copy }, + { 0x0300, 0x0016, "Primary2Y", &Z_Copy }, + { 0x0300, 0x0017, "Primary2Intensity", &Z_Copy }, + { 0x0300, 0x0019, "Primary3X", &Z_Copy }, + { 0x0300, 0x001A, "Primary3Y", &Z_Copy }, + { 0x0300, 0x001B, "Primary3Intensity", &Z_Copy }, + { 0x0300, 0x0030, "WhitePointX", &Z_Copy }, + { 0x0300, 0x0031, "WhitePointY", &Z_Copy }, + { 0x0300, 0x0032, "ColorPointRX", &Z_Copy }, + { 0x0300, 0x0033, "ColorPointRY", &Z_Copy }, + { 0x0300, 0x0034, "ColorPointRIntensity", &Z_Copy }, + { 0x0300, 0x0036, "ColorPointGX", &Z_Copy }, + { 0x0300, 0x0037, "ColorPointGY", &Z_Copy }, + { 0x0300, 0x0038, "ColorPointGIntensity", &Z_Copy }, + { 0x0300, 0x003A, "ColorPointBX", &Z_Copy }, + { 0x0300, 0x003B, "ColorPointBY", &Z_Copy }, + { 0x0300, 0x003C, "ColorPointBIntensity", &Z_Copy }, + + + { 0x0400, 0x0000, D_JSON_ILLUMINANCE, &Z_Copy }, + { 0x0400, 0x0001, "MinMeasuredValue", &Z_Copy }, + { 0x0400, 0x0002, "MaxMeasuredValue", &Z_Copy }, + { 0x0400, 0x0003, "Tolerance", &Z_Copy }, + { 0x0400, 0x0004, "LightSensorType", &Z_Copy }, + { 0x0400, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0401, 0x0000, "LevelStatus", &Z_Copy }, + { 0x0401, 0x0001, "LightSensorType", &Z_Copy }, + { 0x0401, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0402, 0x0000, D_JSON_TEMPERATURE, &Z_FloatDiv100 }, + { 0x0402, 0x0001, "MinMeasuredValue", &Z_FloatDiv100 }, + { 0x0402, 0x0002, "MaxMeasuredValue", &Z_FloatDiv100 }, + { 0x0402, 0x0003, "Tolerance", &Z_FloatDiv100 }, + { 0x0402, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0403, 0x0000, D_JSON_PRESSURE_UNIT, &Z_AddPressureUnit }, + { 0x0403, 0x0000, D_JSON_PRESSURE, &Z_Copy }, + { 0x0403, 0x0001, "MinMeasuredValue", &Z_Copy }, + { 0x0403, 0x0002, "MaxMeasuredValue", &Z_Copy }, + { 0x0403, 0x0003, "Tolerance", &Z_Copy }, + { 0x0403, 0x0010, "ScaledValue", &Z_Copy }, + { 0x0403, 0x0011, "MinScaledValue", &Z_Copy }, + { 0x0403, 0x0012, "MaxScaledValue", &Z_Copy }, + { 0x0403, 0x0013, "ScaledTolerance", &Z_Copy }, + { 0x0403, 0x0014, "Scale", &Z_Copy }, + { 0x0403, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0404, 0x0000, D_JSON_FLOWRATE, &Z_FloatDiv10 }, + { 0x0404, 0x0001, "MinMeasuredValue", &Z_Copy }, + { 0x0404, 0x0002, "MaxMeasuredValue", &Z_Copy }, + { 0x0404, 0x0003, "Tolerance", &Z_Copy }, + { 0x0404, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0405, 0x0000, D_JSON_HUMIDITY, &Z_FloatDiv100 }, + { 0x0405, 0x0001, "MinMeasuredValue", &Z_Copy }, + { 0x0405, 0x0002, "MaxMeasuredValue", &Z_Copy }, + { 0x0405, 0x0003, "Tolerance", &Z_Copy }, + { 0x0405, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0406, 0x0000, OCCUPANCY, &Z_Copy }, + { 0x0406, 0x0001, "OccupancySensorType", &Z_Copy }, + { 0x0406, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0B01, 0x0000, "CompanyName", &Z_Copy }, + { 0x0B01, 0x0001, "MeterTypeID", &Z_Copy }, + { 0x0B01, 0x0004, "DataQualityID", &Z_Copy }, + { 0x0B01, 0x0005, "CustomerName", &Z_Copy }, + { 0x0B01, 0x0006, "Model", &Z_Copy }, + { 0x0B01, 0x0007, "PartNumber", &Z_Copy }, + { 0x0B01, 0x000A, "SoftwareRevision", &Z_Copy }, + { 0x0B01, 0x000C, "POD", &Z_Copy }, + { 0x0B01, 0x000D, "AvailablePower", &Z_Copy }, + { 0x0B01, 0x000E, "PowerThreshold", &Z_Copy }, + + + { 0x0B05, 0x0000, "NumberOfResets", &Z_Copy }, + { 0x0B05, 0x0001, "PersistentMemoryWrites",&Z_Copy }, + { 0x0B05, 0x011C, "LastMessageLQI", &Z_Copy }, + { 0x0B05, 0x011D, "LastMessageRSSI", &Z_Copy }, + +}; + + + +int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + zigbee_devices.setManufId(shortaddr, value.as()); + return 1; +} + +int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + zigbee_devices.setModelId(shortaddr, value.as()); + return 1; +} + + + +int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + return 1; +} + + +int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + return 1; +} + + +int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = F(D_UNIT_PRESSURE); + return 0; +} + + +int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = ((float)value) / 100.0f; + return 1; +} + +int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = ((float)value) / 10.0f; + return 1; +} + + +int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + json[F(OCCUPANCY)] = 0; + zigbee_devices.jsonPublishNow(shortaddr, json); +} + + +int32_t Z_AqaraCube(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + int32_t val = value; + const __FlashStringHelper *aqara_cube = F("AqaraCube"); + const __FlashStringHelper *aqara_cube_side = F("AqaraCubeSide"); + const __FlashStringHelper *aqara_cube_from_side = F("AqaraCubeFromSide"); + + switch (val) { + case 0: + json[aqara_cube] = F("shake"); + break; + case 2: + json[aqara_cube] = F("wakeup"); + break; + case 3: + json[aqara_cube] = F("fall"); + break; + case 64 ... 127: + json[aqara_cube] = F("flip90"); + json[aqara_cube_side] = val % 8; + json[aqara_cube_from_side] = (val - 64) / 8; + break; + case 128 ... 132: + json[aqara_cube] = F("flip180"); + json[aqara_cube_side] = val - 128; + break; + case 256 ... 261: + json[aqara_cube] = F("slide"); + json[aqara_cube_side] = val - 256; + break; + case 512 ... 517: + json[aqara_cube] = F("tap"); + json[aqara_cube_side] = val - 512; + break; + } +# 915 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" + return 1; +} + + +int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + + switch (attr) { + case 0x0055: + { + int32_t ivalue = value; + const __FlashStringHelper * svalue; + switch (ivalue) { + case 1: svalue = F("vibrate"); break; + case 2: svalue = F("tilt"); break; + case 3: svalue = F("drop"); break; + default: svalue = F("unknown"); break; + } + json[new_name] = svalue; + } + break; + + + + + case 0x0508: + { + + + String hex = value; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + int16_t x, y, z; + z = buf2.get16(0); + y = buf2.get16(2); + x = buf2.get16(4); + JsonArray& xyz = json.createNestedArray(new_name); + xyz.add(x); + xyz.add(y); + xyz.add(z); + + float X = x; + float Y = y; + float Z = z; + int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; + int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; + int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; + + + + JsonArray& angles = json.createNestedArray(F("AqaraAngles")); + angles.add(Angle_X); + angles.add(Angle_Y); + angles.add(Angle_Z); + } + break; + } + return 1; +} + +int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + String hex = value; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint32_t i = 0; + uint32_t len = buf2.len(); + char tmp[] = "tmp"; + + JsonVariant sub_value; + + while (len - i >= 2) { + uint8_t attrid = buf2.get8(i++); + + i += parseSingleAttribute(json, tmp, buf2, i, len); + float val = json[tmp]; + json.remove(tmp); + if (0x01 == attrid) { + json[F(D_JSON_VOLTAGE)] = val / 1000.0f; + json[F("Battery")] = toPercentageCR2032(val); + } else if (0 == zcl->getManufCode()) { + + if (0x64 == attrid) { + json[F(D_JSON_TEMPERATURE)] = val / 100.0f; + } else if (0x65 == attrid) { + json[F(D_JSON_HUMIDITY)] = val / 100.0f; + } else if (0x66 == attrid) { + json[F(D_JSON_PRESSURE)] = val / 100.0f; + json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); + } else if (0x01 == attrid) { + json[F(D_JSON_VOLTAGE)] = val / 1000.0f; + json[F("Battery")] = toPercentageCR2032(val); + } + } else if (0x115F == zcl->getManufCode()) { + + json[F("AqaraUnknown")] = val; + } + } + return 1; +} + + +void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { + + for (auto kv : json) { + String key_string = kv.key; + const char * key = key_string.c_str(); + JsonVariant& value = kv.value; + + char * delimiter = strchr(key, '/'); + char * delimiter2 = strchr(key, '+'); + if (delimiter) { + uint16_t attribute; + uint16_t suffix = 1; + uint16_t cluster = strtoul(key, &delimiter, 16); + if (!delimiter2) { + attribute = strtoul(delimiter+1, nullptr, 16); + } else { + attribute = strtoul(delimiter+1, &delimiter2, 16); + suffix = strtoul(delimiter2+1, nullptr, 10); + } + + + for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + uint16_t conv_cluster = pgm_read_word(&converter->cluster); + uint16_t conv_attribute = pgm_read_word(&converter->attribute); + + if ((conv_cluster == cluster) && + ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { + String new_name_str = converter->name; + if (suffix > 1) { new_name_str += suffix; } + int32_t drop = (*converter->func)(this, shortaddr, json, key, value, new_name_str, conv_cluster, conv_attribute); + if (drop) { + json.remove(key); + } + + } + } + } + } +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" +#ifdef USE_ZIGBEE + + +typedef struct Z_CommandConverter { + const char * tasmota_cmd; + const char * zcl_cmd; +} Z_CommandConverter; + + +const Z_CommandConverter Z_Commands[] = { + { "Power", "0006!xx" }, + { "Dimmer", "0008!04/xx0A00" }, + { "Dimmer+", "0008!06/001902" }, + { "Dimmer-", "0008!06/011902" }, + { "DimmerStop", "0008!03" }, + { "ResetAlarm", "0009!00/xxyyyy" }, + { "ResetAllAlarms","0009!01" }, + { "Hue", "0300!00/xx000A00" }, + { "Sat", "0300!03/xx0A00" }, + { "HueSat", "0300!06/xxyy0A00" }, + { "Color", "0300!07/xxxxyyyy0A00" }, + { "CT", "0300!0A/xxxx0A00" }, + { "Shutter", "0102!xx" }, + { "ShutterOpen", "0102!00" }, + { "ShutterClose", "0102!01" }, + { "ShutterStop", "0102!02" }, + { "ShutterLift", "0102!05xx" }, + { "ShutterTilt", "0102!08xx" }, +}; + +#define ZLE(x) ((x) & 0xFF), ((x) >> 8) + + +const uint8_t CLUSTER_0006[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007) }; + +int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + size_t attrs_len = 0; + const uint8_t* attrs = nullptr; + + switch (cluster) { + case 0x0006: + attrs = CLUSTER_0006; + attrs_len = sizeof(CLUSTER_0006); + break; + case 0x0008: + attrs = CLUSTER_0008; + attrs_len = sizeof(CLUSTER_0008); + break; + case 0x0009: + attrs = CLUSTER_0009; + attrs_len = sizeof(CLUSTER_0009); + break; + case 0x0300: + attrs = CLUSTER_0300; + attrs_len = sizeof(CLUSTER_0300); + break; + } + if (attrs) { + ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false ); + } +} + + + +void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint) { + uint32_t wait_ms = 0; + + switch (cluster) { + case 0x0006: + case 0x0009: + wait_ms = 200; + break; + case 0x0008: + case 0x0300: + wait_ms = 1050; + break; + case 0x0102: + wait_ms = 10000; + break; + } + if (wait_ms) { + zigbee_devices.setTimer(shortaddr, wait_ms, cluster, endpoint, 0 , &Z_ReadAttrCallback); + } +} + +const __FlashStringHelper* zigbeeFindCommand(const char *command) { + char parm_uc[16]; + for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { + const Z_CommandConverter *conv = &Z_Commands[i]; + if (0 == strcasecmp_P(command, conv->tasmota_cmd)) { + return (const __FlashStringHelper*) conv->zcl_cmd; + } + } + + return nullptr; +} + +inline bool isXYZ(char c) { + return (c >= 'x') && (c <= 'z'); +} + + +inline char hexDigit(uint32_t h) { + uint32_t nybble = h & 0x0F; + return (nybble > 9) ? 'A' - 10 + nybble : '0' + nybble; +} + + +String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z) { + size_t len = strlen_P(zcl_cmd_P); + char zcl_cmd[len+1]; + strcpy_P(zcl_cmd, zcl_cmd_P); + + char *p = zcl_cmd; + while (*p) { + if (isXYZ(*p) && (*p == *(p+1))) { + uint8_t val; + switch (*p) { + case 'x': + val = x & 0xFF; + x = x >> 8; + break; + case 'y': + val = y & 0xFF; + y = y >> 8; + break; + case 'z': + val = z & 0xFF; + z = z >> 8; + break; + } + *p = hexDigit(val >> 4); + *(p+1) = hexDigit(val); + p++; + } + p++; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SendZCLCommand_P: zcl_cmd = %s"), zcl_cmd); + + return String(zcl_cmd); +} + +const char kZ_Alias[] PROGMEM = "OFF|" D_OFF "|" D_FALSE "|" D_STOP "|" "OPEN" "|" + "ON|" D_ON "|" D_TRUE "|" D_START "|" "CLOSE" "|" + "TOGGLE|" D_TOGGLE "|" + "ALL" ; + +const uint8_t kZ_Numbers[] PROGMEM = { 0,0,0,0,0, + 1,1,1,1,1, + 2,2, + 255 }; + + +uint32_t ZigbeeAliasOrNumber(const char *state_text) { + char command[16]; + int state_number = GetCommandCode(command, sizeof(command), state_text, kZ_Alias); + if (state_number >= 0) { + + return pgm_read_byte(kZ_Numbers + state_number); + } else { + + return strtoul(state_text, nullptr, 0); + } +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +#ifdef USE_ZIGBEE + + + +const uint8_t ZIGBEE_STATUS_OK = 0; +const uint8_t ZIGBEE_STATUS_BOOT = 1; +const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; +const uint8_t ZIGBEE_STATUS_STARTING = 3; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_CLOSE = 20; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_60 = 21; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_XX = 22; +const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; +const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; +const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; +const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; +const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; +const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; +const uint8_t ZIGBEE_STATUS_CC_INFO = 51; +const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; +const uint8_t ZIGBEE_STATUS_ABORT = 99; + +typedef int32_t (*ZB_Func)(uint8_t value); +typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, const class SBuffer &buf); + +typedef union Zigbee_Instruction { + struct { + uint8_t i; + uint8_t d8; + uint16_t d16; + } i; + const void *p; + + + +} Zigbee_Instruction; + + + + +typedef struct Zigbee_Instruction_Type { + uint8_t instr; + uint8_t data; +} Zigbee_Instruction_Type; + +enum Zigbee_StateMachine_Instruction_Set { + + ZGB_INSTR_4_BYTES = 0, + ZGB_INSTR_NOOP = 0, + ZGB_INSTR_LABEL, + ZGB_INSTR_GOTO, + ZGB_INSTR_ON_ERROR_GOTO, + ZGB_INSTR_ON_TIMEOUT_GOTO, + ZGB_INSTR_WAIT, + ZGB_INSTR_WAIT_FOREVER, + ZGB_INSTR_STOP, + + + ZGB_INSTR_8_BYTES = 0x80, + ZGB_INSTR_CALL = 0x80, + ZGB_INSTR_LOG, + ZGB_INSTR_MQTT_STATE, + ZGB_INSTR_SEND, + ZGB_INSTR_WAIT_UNTIL, + ZGB_INSTR_WAIT_RECV, + ZGB_ON_RECV_UNEXPECTED, + + + ZGB_INSTR_12_BYTES = 0xF0, + ZGB_INSTR_WAIT_RECV_CALL, +}; + +#define ZI_NOOP() { .i = { ZGB_INSTR_NOOP, 0x00, 0x0000} }, +#define ZI_LABEL(x) { .i = { ZGB_INSTR_LABEL, (x), 0x0000} }, +#define ZI_GOTO(x) { .i = { ZGB_INSTR_GOTO, (x), 0x0000} }, +#define ZI_ON_ERROR_GOTO(x) { .i = { ZGB_INSTR_ON_ERROR_GOTO, (x), 0x0000} }, +#define ZI_ON_TIMEOUT_GOTO(x) { .i = { ZGB_INSTR_ON_TIMEOUT_GOTO, (x), 0x0000} }, +#define ZI_WAIT(x) { .i = { ZGB_INSTR_WAIT, 0x00, (x)} }, +#define ZI_WAIT_FOREVER() { .i = { ZGB_INSTR_WAIT_FOREVER, 0x00, 0x0000} }, +#define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, + +#define ZI_CALL(f,x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, +#define ZI_LOG(x,m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, +#define ZI_MQTT_STATE(x,m) { .i = { ZGB_INSTR_MQTT_STATE, (x), 0x0000 } }, { .p = ((const void*)(m)) }, +#define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, +#define ZI_SEND(m) { .i = { ZGB_INSTR_SEND, sizeof(m), 0x0000} }, { .p = (const void*)(m) }, +#define ZI_WAIT_RECV(x,m) { .i = { ZGB_INSTR_WAIT_RECV, sizeof(m), (x)} }, { .p = (const void*)(m) }, +#define ZI_WAIT_UNTIL(x,m) { .i = { ZGB_INSTR_WAIT_UNTIL, sizeof(m), (x)} }, { .p = (const void*)(m) }, +#define ZI_WAIT_RECV_FUNC(x,m,f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, + + +const uint8_t ZIGBEE_LABEL_START = 10; +const uint8_t ZIGBEE_LABEL_READY = 20; +const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; + +const uint8_t ZIGBEE_LABEL_ABORT = 99; +const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; + +struct ZigbeeStatus { + bool active = true; + bool state_machine = false; + bool state_waiting = false; + bool state_no_timeout = false; + bool ready = false; + uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; + uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; + int16_t pc = 0; + uint32_t next_timeout = 0; + + uint8_t *recv_filter = nullptr; + bool recv_until = false; + size_t recv_filter_len = 0; + ZB_RecvMsgFunc recv_func = nullptr; + ZB_RecvMsgFunc recv_unexpected = nullptr; + + bool init_phase = true; +}; +struct ZigbeeStatus zigbee; + +SBuffer *zigbee_buffer = nullptr; + + + + + +#define Z_B0(a) (uint8_t)( ((a) ) & 0xFF ) +#define Z_B1(a) (uint8_t)( ((a) >> 8) & 0xFF ) +#define Z_B2(a) (uint8_t)( ((a) >> 16) & 0xFF ) +#define Z_B3(a) (uint8_t)( ((a) >> 24) & 0xFF ) +#define Z_B4(a) (uint8_t)( ((a) >> 32) & 0xFF ) +#define Z_B5(a) (uint8_t)( ((a) >> 40) & 0xFF ) +#define Z_B6(a) (uint8_t)( ((a) >> 48) & 0xFF ) +#define Z_B7(a) (uint8_t)( ((a) >> 56) & 0xFF ) + +#define ZBM(n,x...) const uint8_t n[] PROGMEM = { x }; + +#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) + + + +ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) +ZBM(ZBR_RESET, Z_AREQ | Z_SYS, SYS_RESET_IND ) + +ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) +ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) + + +ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 ) +ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_Success, 0x01 , 0x55) + + +ZBM(ZBS_PAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PANID ) +ZBM(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PANID, 0x02 , + Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) + +ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) +ZBM(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_EXTENDED_PAN_ID, + 0x08 , + Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), + Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID), + ) + +ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) +ZBM(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_CHANLIST, + 0x04 , + Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), + ) + +ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) +ZBM(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEY, + 0x10 , + Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), + Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), + Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), + Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), + + ) + +ZBM(ZBS_PFGKEN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEYS_ENABLE ) +ZBM(ZBR_PFGKEN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEYS_ENABLE, + 0x01 , 0x00 ) + + + +ZBM(ZBR_W_OK, Z_SRSP | Z_SAPI, SAPI_WRITE_CONFIGURATION, Z_Success ) +ZBM(ZBR_WNV_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_WRITE, Z_Success ) + + +ZBM(ZBS_FACTRES, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x02 ) + +ZBM(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) + +ZBM(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , + Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), + Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID) + ) + +ZBM(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , + Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), + ) + +ZBM(ZBS_W_LOGTYP, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x00 ) + +ZBM(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, + 0x10 , + Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), + Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), + Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), + Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), + + ) + +ZBM(ZBS_W_PFGKEN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEYS_ENABLE, 0x01 , 0x00 ) + +ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_START), Z_B1(CONF_TCLK_TABLE_START), + 0x00 , 0x20 , + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, + 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + +ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_ZDO_DIRECT_CB, 0x01 , 0x01 ) + +ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, + 0x01, 0x00 , 0x01 , 0x00 ) + + +ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) + + +ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), + 0x00 , 0x01 , 0x55 ) + +ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 ) +ZBM(ZBR_STARTUPFROMAPP, Z_SRSP | Z_ZDO, ZDO_STARTUP_FROM_APP ) +ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) + +ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) +ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_Success ) +# 271 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +ZBM(ZBS_ZDO_NODEDESCREQ, Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, 0x00, 0x00 , 0x00, 0x00 ) +ZBM(ZBR_ZDO_NODEDESCREQ, Z_SRSP | Z_ZDO, ZDO_NODE_DESC_REQ, Z_Success ) + +ZBM(AREQ_ZDO_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) +# 289 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) +ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_Success) +ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, + 0x00, 0x00 , 0x00 ) +ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, + 0x00, 0x00 , 0x02 , 0x0B, 0x01 ) + + +ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , 0x00 , + 0x00 , 0x00 ) +ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_Success) +ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , 0x00 , + 0x00 , 0x00 ) + +ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 , + 0x00, 0x00 , 0x00 , 0x00 ) +ZBM(ZBS_PERMITJOINREQ_OPEN_60, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , + 0xFC, 0xFF , 60 , 0x00 ) +ZBM(ZBS_PERMITJOINREQ_OPEN_XX, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , + 0xFC, 0xFF , 0xFF , 0x00 ) +ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_Success) +ZBM(ZBR_PERMITJOIN_AREQ_CLOSE, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0x00 ) +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_60, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 60 ) +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_FF, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0xFF ) +ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 , Z_Success ) + +static const Zigbee_Instruction zb_prog[] PROGMEM = { + ZI_LABEL(0) + ZI_NOOP() + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) + ZI_WAIT(10500) + ZI_ON_ERROR_GOTO(50) + + + + ZI_SEND(ZBS_RESET) + ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &Z_Reboot) + ZI_WAIT(100) + ZI_LOG(LOG_LEVEL_DEBUG, D_LOG_ZIGBEE "checking device configuration") + ZI_SEND(ZBS_ZNPHC) + ZI_WAIT_RECV(2000, ZBR_ZNPHC) + ZI_SEND(ZBS_VERSION) + ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) + ZI_SEND(ZBS_PAN) + ZI_WAIT_RECV(1000, ZBR_PAN) + ZI_SEND(ZBS_EXTPAN) + ZI_WAIT_RECV(1000, ZBR_EXTPAN) + ZI_SEND(ZBS_CHANN) + ZI_WAIT_RECV(1000, ZBR_CHANN) + ZI_SEND(ZBS_PFGK) + ZI_WAIT_RECV(1000, ZBR_PFGK) + ZI_SEND(ZBS_PFGKEN) + ZI_WAIT_RECV(1000, ZBR_PFGKEN) + + + + ZI_LABEL(ZIGBEE_LABEL_START) + ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, "Configured, starting coordinator") + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + + +ZI_SEND(ZBS_STARTUPFROMAPP) + ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) + ZI_WAIT_UNTIL(10000, AREQ_STARTUPFROMAPP) + ZI_SEND(ZBS_GETDEVICEINFO) + ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) + + ZI_SEND(ZBS_ZDO_NODEDESCREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) + ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP) + ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) + ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE) + ZI_SEND(ZBS_AF_REGISTER01) + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + ZI_SEND(ZBS_AF_REGISTER0B) + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + + + ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) + ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_OK) + ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) + + + + + + + ZI_LABEL(ZIGBEE_LABEL_READY) + ZI_MQTT_STATE(ZIGBEE_STATUS_OK, "Started") + ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "Zigbee started") + ZI_CALL(&Z_State_Ready, 1) + ZI_CALL(&Z_Load_Devices, 0) + ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) + ZI_WAIT_FOREVER() + ZI_GOTO(ZIGBEE_LABEL_READY) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE) + + ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60) + + ZI_SEND(ZBS_PERMITJOINREQ_OPEN_60) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX) + + ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(50) + ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, "Reseting configuration") + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_SEND(ZBS_FACTRES) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_RESET) + ZI_WAIT_RECV(5000, ZBR_RESET) + ZI_SEND(ZBS_W_PAN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_EXTPAN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_CHANN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_LOGTYP) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_PFGK) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_PFGKEN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_WNV_SECMODE) + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + ZI_SEND(ZBS_W_ZDODCB) + ZI_WAIT_RECV(1000, ZBR_W_OK) + + ZI_SEND(ZBS_WNV_INITZNPHC) + ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite) + ZI_SEND(ZBS_WNV_ZNPHC) + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + + + ZI_GOTO(ZIGBEE_LABEL_START) + + ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) + ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, "Only ZNP 1.2 is currently supported") + ZI_GOTO(ZIGBEE_LABEL_ABORT) + + ZI_LABEL(ZIGBEE_LABEL_ABORT) + ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, "Abort") + ZI_LOG(LOG_LEVEL_ERROR, D_LOG_ZIGBEE "Abort") + ZI_STOP(ZIGBEE_LABEL_ABORT) +}; + +uint8_t ZigbeeGetInstructionSize(uint8_t instr) { + if (instr >= ZGB_INSTR_12_BYTES) { + return 3; + } else if (instr >= ZGB_INSTR_8_BYTES) { + return 2; + } else { + return 1; + } +} + +void ZigbeeGotoLabel(uint8_t label) { + + uint16_t goto_pc = 0xFFFF; + uint8_t cur_instr = 0; + uint8_t cur_d8 = 0; + uint8_t cur_instr_len = 1; + + for (uint32_t i = 0; i < sizeof(zb_prog)/sizeof(zb_prog[0]); i += cur_instr_len) { + const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; + cur_instr = pgm_read_byte(&cur_instr_line->i.i); + cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); + + + if (ZGB_INSTR_LABEL == cur_instr) { + + if (label == cur_d8) { + + zigbee.pc = i; + zigbee.state_machine = true; + zigbee.state_waiting = false; + return; + } + } + + cur_instr_len = ZigbeeGetInstructionSize(cur_instr); + } + + + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Goto label not found, label=%d pc=%d"), label, zigbee.pc); + if (ZIGBEE_LABEL_ABORT != label) { + + ZigbeeGotoLabel(ZIGBEE_LABEL_ABORT); + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Label Abort (%d) not present, aborting Zigbee"), ZIGBEE_LABEL_ABORT); + zigbee.state_machine = false; + zigbee.active = false; + } +} + +void ZigbeeStateMachine_Run(void) { + uint8_t cur_instr = 0; + uint8_t cur_d8 = 0; + uint16_t cur_d16 = 0; + const void* cur_ptr1 = nullptr; + const void* cur_ptr2 = nullptr; + uint32_t now = millis(); + + if (zigbee.state_waiting) { + + if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { + + if (!zigbee.state_no_timeout) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "timeout, goto label %d"), zigbee.on_timeout_goto); + ZigbeeGotoLabel(zigbee.on_timeout_goto); + } else { + zigbee.state_waiting = false; + } + } + } + + while ((zigbee.state_machine) && (!zigbee.state_waiting)) { + + zigbee.recv_filter = nullptr; + zigbee.recv_func = nullptr; + zigbee.recv_until = false; + zigbee.state_no_timeout = false; + + if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Invalid pc: %d, aborting"), zigbee.pc); + zigbee.pc = -1; + } + if (zigbee.pc < 0) { + zigbee.state_machine = false; + return; + } + + + + const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; + cur_instr = pgm_read_byte(&cur_instr_line->i.i); + cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); + cur_d16 = pgm_read_word(&cur_instr_line->i.d16); + if (cur_instr >= ZGB_INSTR_8_BYTES) { + cur_instr_line++; + cur_ptr1 = cur_instr_line->p; + } + if (cur_instr >= ZGB_INSTR_12_BYTES) { + cur_instr_line++; + cur_ptr2 = cur_instr_line->p; + } + + zigbee.pc += ZigbeeGetInstructionSize(cur_instr); + + switch (cur_instr) { + case ZGB_INSTR_NOOP: + case ZGB_INSTR_LABEL: + break; + case ZGB_INSTR_GOTO: + ZigbeeGotoLabel(cur_d8); + break; + case ZGB_INSTR_ON_ERROR_GOTO: + zigbee.on_error_goto = cur_d8; + break; + case ZGB_INSTR_ON_TIMEOUT_GOTO: + zigbee.on_timeout_goto = cur_d8; + break; + case ZGB_INSTR_WAIT: + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + zigbee.state_no_timeout = true; + break; + case ZGB_INSTR_WAIT_FOREVER: + zigbee.next_timeout = 0; + zigbee.state_waiting = true; + + break; + case ZGB_INSTR_STOP: + zigbee.state_machine = false; + if (cur_d8) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Stopping (%d)"), cur_d8); + } + break; + case ZGB_INSTR_CALL: + if (cur_ptr1) { + uint32_t res; + res = (*((ZB_Func)cur_ptr1))(cur_d8); + if (res > 0) { + ZigbeeGotoLabel(res); + continue; + } else if (res == 0) { + + } else if (res == -1) { + + } else { + ZigbeeGotoLabel(zigbee.on_error_goto); + continue; + } + } + break; + case ZGB_INSTR_LOG: + AddLog_P(cur_d8, (char*) cur_ptr1); + break; + case ZGB_INSTR_MQTT_STATE: + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":%d,\"Message\":\"%s\"}}"), + cur_d8, (char*) cur_ptr1); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + break; + case ZGB_INSTR_SEND: + ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 ); + break; + case ZGB_INSTR_WAIT_UNTIL: + zigbee.recv_until = true; + case ZGB_INSTR_WAIT_RECV: + zigbee.recv_filter = (uint8_t *) cur_ptr1; + zigbee.recv_filter_len = cur_d8; + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + break; + case ZGB_ON_RECV_UNEXPECTED: + zigbee.recv_unexpected = (ZB_RecvMsgFunc) cur_ptr1; + break; + case ZGB_INSTR_WAIT_RECV_CALL: + zigbee.recv_filter = (uint8_t *) cur_ptr1; + zigbee.recv_filter_len = cur_d8; + zigbee.recv_func = (ZB_RecvMsgFunc) cur_ptr2; + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + break; + } + } +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +#ifdef USE_ZIGBEE + +int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { + + + + + + + + Z_IEEEAddress long_adr = buf.get64(3); + Z_ShortAddress short_adr = buf.get16(11); + uint8_t device_type = buf.get8(13); + uint8_t device_state = buf.get8(14); + uint8_t device_associated = buf.get8(15); + + + localIEEEAddr = long_adr; + + char hex[20]; + Uint64toHex(long_adr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"DeviceType\":%d,\"DeviceState\":%d" + ",\"NumAssocDevices\":%d"), + ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, + device_associated); + + if (device_associated > 0) { + uint idx = 16; + ResponseAppend_P(PSTR(",\"AssocDevicesList\":[")); + for (uint32_t i = 0; i < device_associated; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(idx)); + idx += 2; + } + ResponseAppend_P(PSTR("]")); + } + + ResponseJsonEnd(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + + return res; +} + +int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { + + + + uint8_t status = buf.get8(2); + if ((0x00 == status) || (0x09 == status)) { + return 0; + } else { + return -2; + } +} + +const char Z_RebootReason[] PROGMEM = "Power-up|External|Watchdog"; + +int32_t Z_Reboot(int32_t res, class SBuffer &buf) { + + + + uint8_t reason = buf.get8(2); + uint8_t transport_rev = buf.get8(3); + uint8_t product_id = buf.get8(4); + uint8_t major_rel = buf.get8(5); + uint8_t minor_rel = buf.get8(6); + uint8_t hw_rev = buf.get8(7); + char reason_str[12]; + + if (reason > 3) { reason = 3; } + GetTextIndexed(reason_str, sizeof(reason_str), reason, Z_RebootReason); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Message\":\"%s\",\"RestartReason\":\"%s\"" + ",\"MajorRel\":%d,\"MinorRel\":%d}}"), + ZIGBEE_STATUS_BOOT, "CC2530 booted", reason_str, + major_rel, minor_rel); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + + if ((0x02 == major_rel) && (0x06 == minor_rel)) { + return 0; + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; + } +} + +int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { +# 122 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" + uint8_t major_rel = buf.get8(4); + uint8_t minor_rel = buf.get8(5); + uint8_t maint_rel = buf.get8(6); + uint32_t revision = buf.get32(7); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" + ",\"MaintRel\":%d,\"Revision\":%d}}"), + ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, + maint_rel, revision); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + + if ((0x02 == major_rel) && (0x06 == minor_rel)) { + return 0; + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; + } +} + +bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { + if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && + (pgm_read_byte(&match[1]) == buf.get8(1)) ) { + return true; + } else { + return false; + } +} + +int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { + + uint8_t duration = buf.get8(2); + uint8_t status_code; + const char* message; + + if (0xFF == duration) { + status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_XX; + message = PSTR("Enable Pairing mode until next boot"); + } else if (duration > 0) { + status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_60; + message = PSTR("Enable Pairing mode for %d seconds"); + } else { + status_code = ZIGBEE_STATUS_PERMITJOIN_CLOSE; + message = PSTR("Disable Pairing mode"); + } + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Message\":\""), + status_code); + ResponseAppend_P(message, duration); + ResponseAppend_P(PSTR("\"}}")); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + return -1; +} + + +void Z_SendActiveEpReq(uint16_t shortaddr) { + uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + + uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + + ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); + +} + + +void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint) { + uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), + endpoint }; + + ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); +} + +const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" }; +int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { + + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t logicalType = buf.get8(7); + uint8_t apsFlags = buf.get8(8); + uint8_t MACCapabilityFlags = buf.get8(9); + uint16_t manufacturerCapabilities = buf.get16(10); + uint8_t maxBufferSize = buf.get8(12); + uint16_t maxInTransferSize = buf.get16(13); + uint16_t serverMask = buf.get16(15); + uint16_t maxOutTransferSize = buf.get16(17); + uint8_t descriptorCapabilities = buf.get8(19); + + if (0 == status) { + zigbee_devices.updateLastSeen(nwkAddr); + + uint8_t deviceType = logicalType & 0x7; + if (deviceType > 3) { deviceType = 3; } + bool complexDescriptorAvailable = (logicalType & 0x08) ? 1 : 0; + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"NodeType\":\"%s\",\"ComplexDesc\":%s}}"), + ZIGBEE_STATUS_NODE_DESC, Z_DeviceType[deviceType], + complexDescriptorAvailable ? "true" : "false" + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + } + + return -1; +} + +int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { + + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t activeEpCount = buf.get8(7); + uint8_t* activeEpList = (uint8_t*) buf.charptr(8); + + + for (uint32_t i = 0; i < activeEpCount; i++) { + zigbee_devices.addEndoint(nwkAddr, activeEpList[i]); + } + + for (uint32_t i = 0; i < activeEpCount; i++) { + Z_SendSimpleDescReq(nwkAddr, activeEpList[i]); + } + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"ActiveEndpoints\":["), + ZIGBEE_STATUS_ACTIVE_EP); + for (uint32_t i = 0; i < activeEpCount; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%02X\""), activeEpList[i]); + } + ResponseAppend_P(PSTR("]}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + return -1; +} + +void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusterid, uint8_t transacid) { + SBuffer buf(100); + buf.add8(Z_SREQ | Z_AF); + buf.add8(AF_DATA_REQUEST); + buf.add16(shortaddr); + buf.add8(endpoint); + buf.add8(0x01); + buf.add16(clusterid); + buf.add8(transacid); + buf.add8(0x30); + buf.add8(0x1E); + + buf.add8(3 + 2*sizeof(uint16_t)); + buf.add8(0x00); + buf.add8(transacid); + buf.add8(ZCL_READ_ATTRIBUTES); + buf.add16(0x0004); + buf.add16(0x0005); + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +} + + +int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { + + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t lenDescriptor = buf.get8(7); + uint8_t endpoint = buf.get8(8); + uint16_t profileId = buf.get16(9); + uint16_t deviceId = buf.get16(11); + uint8_t deviceVersion = buf.get8(13); + uint8_t numInCluster = buf.get8(14); + uint8_t numOutCluster = buf.get8(15 + numInCluster*2); + + if (0 == status) { + zigbee_devices.addEndointProfile(nwkAddr, endpoint, profileId); + for (uint32_t i = 0; i < numInCluster; i++) { + zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(15 + i*2), false); + } + for (uint32_t i = 0; i < numOutCluster; i++) { + zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(16 + numInCluster*2 + i*2), true); + } + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Endpoint\":\"0x%02X\"" + ",\"ProfileId\":\"0x%04X\",\"DeviceId\":\"0x%04X\",\"DeviceVersion\":%d" + "\"InClusters\":["), + ZIGBEE_STATUS_SIMPLE_DESC, endpoint, + profileId, deviceId, deviceVersion); + for (uint32_t i = 0; i < numInCluster; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(15 + i*2)); + } + ResponseAppend_P(PSTR("],\"OutClusters\":[")); + for (uint32_t i = 0; i < numOutCluster; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(16 + numInCluster*2 + i*2)); + } + ResponseAppend_P(PSTR("]}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + uint8_t cluster = zigbee_devices.findClusterEndpointIn(nwkAddr, 0x0000); + if (cluster) { + Z_SendAFInfoRequest(nwkAddr, cluster, 0x0000, 0x01); + } + } + return -1; +} + +int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { + Z_ShortAddress srcAddr = buf.get16(2); + Z_ShortAddress nwkAddr = buf.get16(4); + Z_IEEEAddress ieeeAddr = buf.get64(6); + uint8_t capabilities = buf.get8(14); + + zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), + ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, + (capabilities & 0x04) ? "true" : "false", + (capabilities & 0x08) ? "true" : "false", + (capabilities & 0x40) ? "true" : "false" + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + Z_SendActiveEpReq(nwkAddr); + return -1; +} + + +int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { + Z_ShortAddress srcAddr = buf.get16(2); + Z_IEEEAddress ieeeAddr = buf.get64(4); + Z_ShortAddress parentNw = buf.get16(12); + + zigbee_devices.updateDevice(srcAddr, ieeeAddr); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"ParentNetwork\":\"0x%04X\"}}"), + ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + return -1; +} + + + +const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; + +void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, const JsonObject *json) { + + const JsonVariant &val_endpoint = getCaseInsensitive(*json, PSTR(OCCUPANCY)); + if (nullptr != &val_endpoint) { + uint32_t occupancy = strToUInt(val_endpoint); + + if (occupancy) { + zigbee_devices.setTimer(shortaddr, OCCUPANCY_TIMEOUT, cluster, endpoint, 0, &Z_OccupancyCallback); + } + } +} + + + +int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + const JsonObject *json = zigbee_devices.jsonGet(shortaddr); + if (json == nullptr) { return 0; } + + Z_AqaraOccupancy(shortaddr, cluster, endpoint, json); + + zigbee_devices.jsonPublishFlush(shortaddr); + return 1; +} + +int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { + uint16_t groupid = buf.get16(2); + uint16_t clusterid = buf.get16(4); + Z_ShortAddress srcaddr = buf.get16(6); + uint8_t srcendpoint = buf.get8(8); + uint8_t dstendpoint = buf.get8(9); + uint8_t wasbroadcast = buf.get8(10); + uint8_t linkquality = buf.get8(11); + uint8_t securityuse = buf.get8(12); + uint32_t timestamp = buf.get32(13); + uint8_t seqnumber = buf.get8(17); + + bool defer_attributes = false; + + zigbee_devices.updateLastSeen(srcaddr); + ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, + srcaddr, + srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp); + zcl_received.log(); + char shortaddr[8]; + snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); + + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + + if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { + zcl_received.parseRawAttributes(json); + if (clusterid) { defer_attributes = true; } + } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { + zcl_received.parseReadAttributes(json); + } else if (zcl_received.isClusterSpecificCommand()) { + zcl_received.parseClusterSpecificCommand(json); + } + String msg(""); + msg.reserve(100); + json.printTo(msg); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); + + zcl_received.postProcessAttributes(srcaddr, json); + + json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; + + if (defer_attributes) { + + if (zigbee_devices.jsonIsConflict(srcaddr, json)) { + + zigbee_devices.jsonPublishFlush(srcaddr); + } else { + zigbee_devices.jsonAppend(srcaddr, json); + zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); + } + } else { + + zigbee_devices.jsonPublishNow(srcaddr, json); + } + return -1; +} + +typedef struct Z_Dispatcher { + const uint8_t* match; + ZB_RecvMsgFunc func; +} Z_Dispatcher; + + +ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) +ZBM(AREQ_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) +ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) +ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) +ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) +ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) + +const Z_Dispatcher Z_DispatchTable[] PROGMEM = { + { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, + { AREQ_END_DEVICE_ANNCE_IND, &Z_ReceiveEndDeviceAnnonce }, + { AREQ_END_DEVICE_TC_DEV_IND, &Z_ReceiveTCDevInd }, + { AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus }, + { AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc }, + { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, + { AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc }, +}; + +int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { + + if (zigbee.init_phase) { + + return -1; + } else { + for (uint32_t i = 0; i < sizeof(Z_DispatchTable)/sizeof(Z_Dispatcher); i++) { + if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) { + (*Z_DispatchTable[i].func)(res, buf); + } + } + return -1; + } +} + +int32_t Z_Load_Devices(uint8_t value) { + + loadZigbeeDevices(); + return 0; +} + +int32_t Z_State_Ready(uint8_t value) { + zigbee.init_phase = false; + return 0; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" +#ifdef USE_ZIGBEE + +#define XDRV_23 23 + +const uint32_t ZIGBEE_BUFFER_SIZE = 256; +const uint8_t ZIGBEE_SOF = 0xFE; +const uint8_t ZIGBEE_SOF_ALT = 0xFF; + +#include +TasmotaSerial *ZigbeeSerial = nullptr; + + +const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" + D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" + D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" + D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; + +const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" + D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" + D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" + D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; + +void (* const ZigbeeCommand[])(void) PROGMEM = { + &CmndZbZNPSend, &CmndZbPermitJoin, + &CmndZbStatus, &CmndZbReset, &CmndZbSend, + &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, + &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind + }; + +int32_t ZigbeeProcessInput(class SBuffer &buf) { + if (!zigbee.state_machine) { return -1; } + + + bool recv_filter_match = true; + bool recv_prefix_match = false; + if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { + if (zigbee.recv_filter_len >= 2) { + recv_prefix_match = false; + if ( (pgm_read_byte(&zigbee.recv_filter[0]) == buf.get8(0)) && + (pgm_read_byte(&zigbee.recv_filter[1]) == buf.get8(1)) ) { + recv_prefix_match = true; + } + } + + for (uint32_t i = 0; i < zigbee.recv_filter_len; i++) { + if (pgm_read_byte(&zigbee.recv_filter[i]) != buf.get8(i)) { + recv_filter_match = false; + break; + } + } + + + } + + + int32_t res = -1; + + + + + + if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { + if (!recv_prefix_match) { + res = -1; + } else { + if (recv_filter_match) { + res = 0; + } else { + if (zigbee.recv_until) { + res = -1; + } else { + res = -2; + } + } + } + } else { + res = -1; + } + + if (recv_prefix_match) { + if (zigbee.recv_func) { + res = (*zigbee.recv_func)(res, buf); + } + } + if (-1 == res) { + + if (zigbee.recv_unexpected) { + res = (*zigbee.recv_unexpected)(res, buf); + } + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZbProcessInput: res = %d"), res); + + + if (0 == res) { + + zigbee.state_waiting = false; + } else if (res > 0) { + ZigbeeGotoLabel(res); + } else if (-1 == res) { + + + } else { + + ZigbeeGotoLabel(zigbee.on_error_goto); + } +} + +void ZigbeeInput(void) +{ + static uint32_t zigbee_polling_window = 0; + static uint8_t fcs = ZIGBEE_SOF; + static uint32_t zigbee_frame_len = 5; +# 142 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" + while (ZigbeeSerial->available()) { + yield(); + uint8_t zigbee_in_byte = ZigbeeSerial->read(); + + + if (0 == zigbee_buffer->len()) { + zigbee_frame_len = 5; + fcs = ZIGBEE_SOF; + + + + if (ZIGBEE_SOF_ALT == zigbee_in_byte) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput forgiven first byte %02X (only for statistics)"), zigbee_in_byte); + zigbee_in_byte = ZIGBEE_SOF; + } + } + + if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput discarding byte %02X"), zigbee_in_byte); + continue; + } + + if (zigbee_buffer->len() < zigbee_frame_len) { + zigbee_buffer->add8(zigbee_in_byte); + zigbee_polling_window = millis(); + fcs ^= zigbee_in_byte; + } + + if (zigbee_buffer->len() >= zigbee_frame_len) { + zigbee_polling_window = 0; + break; + } + + + if (02 == zigbee_buffer->len()) { + + uint8_t len_byte = zigbee_buffer->get8(1); + if (len_byte > 250) len_byte = 250; + + zigbee_frame_len = len_byte + 5; + } + } + + if (zigbee_buffer->len() && (millis() > (zigbee_polling_window + ZIGBEE_POLLING))) { + char hex_char[(zigbee_buffer->len() * 2) + 2]; + ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Bytes follow_read_metric = %0d"), ZigbeeSerial->getLoopReadMetric()); + + if (zigbee_buffer->len() != zigbee_frame_len) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received frame of wrong size %s, len %d, expected %d"), hex_char, zigbee_buffer->len(), zigbee_frame_len); + } else if (0x00 != fcs) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received bad FCS frame %s, %d"), hex_char, fcs); + } else { + + + + SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); + + ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char)); + Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); + } + + ZigbeeProcessInput(znp_buffer); + } + zigbee_buffer->setLen(0); + } +} + + + +void ZigbeeInit(void) +{ + zigbee.active = false; + if ((pin[GPIO_ZIGBEE_RX] < 99) && (pin[GPIO_ZIGBEE_TX] < 99)) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); + + ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], seriallog_level ? 1 : 2, 0, 256); + ZigbeeSerial->begin(115200); + if (ZigbeeSerial->hardwareSerial()) { + ClaimSerial(); + uint32_t aligned_buffer = ((uint32_t)serial_in_buffer + 3) & ~3; + zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer) - 3, (char*) aligned_buffer); + } else { + zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); + } + zigbee.active = true; + zigbee.init_phase = true; + zigbee.state_machine = true; + ZigbeeSerial->flush(); + } +} + + + + + +uint32_t strToUInt(const JsonVariant &val) { + + if (val.is()) { + return val.as(); + } else { + if (val.is()) { + String sval = val.as(); + return strtoull(sval.c_str(), nullptr, 0); + } + } + return 0; +} + +const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = + { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x01 }; + + +void CmndZbReset(void) { + if (ZigbeeSerial) { + switch (XdrvMailbox.payload) { + case 1: + ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET)); + eraseZigbeeDevices(); + restart_flag = 2; + ResponseCmndChar(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING); + break; + default: + ResponseCmndChar(D_JSON_ONE_TO_RESET); + } + } +} + +void CmndZbZNPSendOrReceive(bool send) +{ + if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { + uint8_t code; + + char *codes = RemoveSpace(XdrvMailbox.data); + int32_t size = strlen(XdrvMailbox.data); + + SBuffer buf((size+1)/2); + + while (size > 1) { + char stemp[3]; + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, nullptr, 16); + buf.add8(code); + size -= 2; + codes += 2; + } + if (send) { + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + } else { + ZigbeeProcessInput(buf); + } + } + ResponseCmndDone(); +} + + +void CmndZbZNPReceive(void) +{ + CmndZbZNPSendOrReceive(false); +} + +void CmndZbZNPSend(void) +{ + CmndZbZNPSendOrReceive(true); +} + +void ZigbeeZNPSend(const uint8_t *msg, size_t len) { + if ((len < 2) || (len > 252)) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPSENT ": bad message len %d"), len); + return; + } + uint8_t data_len = len - 2; + + if (ZigbeeSerial) { + uint8_t fcs = data_len; + + ZigbeeSerial->write(ZIGBEE_SOF); + + ZigbeeSerial->write(data_len); + + for (uint32_t i = 0; i < len; i++) { + uint8_t b = pgm_read_byte(msg + i); + ZigbeeSerial->write(b); + fcs ^= b; + + } + ZigbeeSerial->write(fcs); + + } + + char hex_char[(len * 2) + 2]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"), + ToHex_P(msg, len, hex_char, sizeof(hex_char))); +} + +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp, uint8_t transacId) { + SBuffer buf(25+len); + buf.add8(Z_SREQ | Z_AF); + buf.add8(AF_DATA_REQUEST); + buf.add16(dtsAddr); + buf.add8(endpoint); + buf.add8(0x01); + buf.add16(clusterId); + buf.add8(transacId); + buf.add8(0x30); + buf.add8(0x1E); + + buf.add8(3 + len); + buf.add8((disableDefResp ? 0x10 : 0x00) | (clusterSpecific ? 0x01 : 0x00)); + buf.add8(transacId); + buf.add8(cmdId); + if (len > 0) { + buf.addBuffer(msg, len); + } + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +} + +inline int8_t hexValue(char c) { + if ((c >= '0') && (c <= '9')) { + return c - '0'; + } + if ((c >= 'A') && (c <= 'F')) { + return 10 + c - 'A'; + } + if ((c >= 'a') && (c <= 'f')) { + return 10 + c - 'a'; + } + return -1; +} + +uint32_t parseHex(const char **data, size_t max_len = 8) { + uint32_t ret = 0; + for (uint32_t i = 0; i < max_len; i++) { + int8_t v = hexValue(**data); + if (v < 0) { break; } + ret = (ret << 4) | v; + *data += 1; + } + return ret; +} + +void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { + + uint16_t cluster = 0x0000; + uint8_t cmd = ZCL_READ_ATTRIBUTES; + bool clusterSpecific = false; + + + + cluster = parseHex(&data, 4); + + + if (('_' == *data) || ('!' == *data)) { + if ('!' == *data) { clusterSpecific = true; } + data++; + } else { + ResponseCmndChar("Wrong delimiter for payload"); + return; + } + + cmd = parseHex(&data, 2); + + + + if ('/' == *data) { data++; } + + size_t size = strlen(data); + SBuffer buf((size+2)/2); + + while (*data) { + uint8_t code = parseHex(&data, 2); + buf.add8(code); + } + + if (0 == endpoint) { + + endpoint = zigbee_devices.findClusterEndpointIn(dstAddr, cluster); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: dstAddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), + dstAddr, cluster, endpoint, cmd, data); + + if (0 == endpoint) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); + return; + } + + + ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len()); + + if (clusterSpecific) { + zigbeeSetCommandTimer(dstAddr, cluster, endpoint); + } + ResponseCmndDone(); +} + +void CmndZbSend(void) { +# 461 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + + static char delim[] = ", "; + uint16_t device = 0xFFFF; + uint8_t endpoint = 0x00; + String cmd_str = ""; + + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); + if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send")); + if (nullptr != &val_cmd) { + + + + if (val_cmd.is()) { + + JsonObject &cmd_obj = val_cmd.as(); + int32_t cmd_size = cmd_obj.size(); + if (cmd_size > 1) { + Response_P(PSTR("Only 1 command allowed (%d)"), cmd_size); + return; + } else if (1 == cmd_size) { + + JsonObject::iterator it = cmd_obj.begin(); + String key = it->key; + JsonVariant& value = it->value; + uint32_t x = 0, y = 0, z = 0; + + const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.c_str()); + if (tasmota_cmd) { + cmd_str = tasmota_cmd; + } else { + Response_P(PSTR("Unrecognized zigbee command: %s"), key.c_str()); + return; + } + + + if (value.is()) { + x = value.as() ? 1 : 0; + } else if (value.is()) { + x = value.as(); + } else { + + const char *s_const = value.as(); + if (s_const != nullptr) { + char s[strlen(s_const)+1]; + strcpy(s, s_const); + if ((nullptr != s) && (0x00 != *s)) { + char *sval = strtok(s, delim); + if (sval) { + x = ZigbeeAliasOrNumber(sval); + sval = strtok(nullptr, delim); + if (sval) { + y = ZigbeeAliasOrNumber(sval); + sval = strtok(nullptr, delim); + if (sval) { + z = ZigbeeAliasOrNumber(sval); + } + } + } + } + } + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_template = %s"), cmd_str.c_str()); + cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_final = %s"), cmd_str.c_str()); + } else { + + } + } else if (val_cmd.is()) { + + cmd_str = val_cmd.as(); + } else { + + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%s\"}"), + device, endpoint, cmd_str.c_str()); + zigbeeZCLSendStr(device, endpoint, cmd_str.c_str()); + } else { + Response_P(PSTR("Missing zigbee 'Send'")); + return; + } + +} + +ZBM(ZBS_BIND_REQ, Z_SREQ | Z_ZDO, ZDO_BIND_REQ, + 0,0, + 0,0,0,0,0,0,0,0, + 0x00, + 0x00, 0x00, + 0x03, + 0,0,0,0,0,0,0,0, + 0x01 +) + +void CmndZbBind(void) { + + + + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + + + uint16_t device = 0xFFFF; + uint8_t endpoint = 0x00; + uint16_t cluster = 0; + uint32_t group = 0xFFFFFFFF; + + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); + if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); + if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } + + + + SBuffer buf(sizeof(ZBS_BIND_REQ)); + buf.add8(Z_SREQ | Z_ZDO); + buf.add8(ZDO_BIND_REQ); + buf.add16(device); + buf.add64(zigbee_devices.getDeviceLongAddr(device)); + buf.add8(endpoint); + buf.add16(cluster); + buf.add8(0x03); + buf.add64(localIEEEAddr); + buf.add8(0x01); + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + + ResponseCmndDone(); +} + + +void CmndZbProbe(void) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + + Z_SendActiveEpReq(shortaddr); + ResponseCmndDone(); +} + + +void CmndZbName(void) { + + + + + + + + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + + + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + if (p == nullptr) { + const String * friendlyName = zigbee_devices.getFriendlyName(shortaddr); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName->c_str() : ""); + } else { + zigbee_devices.setFriendlyName(shortaddr, p); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p); + } +} + + +void CmndZbForget(void) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + + if (zigbee_devices.removeDevice(shortaddr)) { + ResponseCmndDone(); + } else { + ResponseCmndChar("Unknown device"); + } +} + + +void CmndZbSave(void) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + + saveZigbeeDevices(); + + ResponseCmndDone(); +} + + +void CmndZbRead(void) { + + + + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + + uint16_t device = 0xFFFF; + uint16_t cluster = 0x0000; + uint8_t endpoint = 0x00; + size_t attrs_len = 0; + uint8_t* attrs = nullptr; + + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); + if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } + const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); + if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + + const JsonVariant &val_attr = getCaseInsensitive(json, PSTR("Read")); + if (nullptr != &val_attr) { + uint16_t val = strToUInt(val_attr); + if (val_attr.is()) { + JsonArray& attr_arr = val_attr; + attrs_len = attr_arr.size() * 2; + attrs = new uint8_t[attrs_len]; + + uint32_t i = 0; + for (auto value : attr_arr) { + uint16_t val = strToUInt(value); + attrs[i++] = val & 0xFF; + attrs[i++] = val >> 8; + } + } else { + attrs_len = 2; + attrs = new uint8_t[attrs_len]; + attrs[0] = val & 0xFF; + attrs[1] = val >> 8; + } + } + + if ((0 != endpoint) && (attrs_len > 0)) { + ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false ); + ResponseCmndDone(); + } else { + ResponseCmndChar("Missing parameters"); + } + + if (attrs) { delete[] attrs; } +} + + +void CmndZbPermitJoin(void) +{ + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint32_t payload = XdrvMailbox.payload; + if (payload < 0) { payload = 0; } + if ((99 != payload) && (payload > 1)) { payload = 1; } + + if (1 == payload) { + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60); + } else if (99 == payload){ + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX); + } else { + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE); + } + ResponseCmndDone(); +} + +void CmndZbStatus(void) { + if (ZigbeeSerial) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + if (XdrvMailbox.payload > 0) { + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + } + + String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr); + Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); + } +} + + + + + +bool Xdrv23(uint8_t function) +{ + bool result = false; + + if (zigbee.active) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (!zigbee.init_phase) { + zigbee_devices.runTimer(); + } + break; + case FUNC_LOOP: + if (ZigbeeSerial) { ZigbeeInput(); } + if (zigbee.state_machine) { + + ZigbeeStateMachine_Run(); + } + break; + case FUNC_PRE_INIT: + ZigbeeInit(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kZbCommands, ZigbeeCommand); + result = result || DecodeCommand(kZigbeeCommands, ZigbeeCommand); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_24_buzzer.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_24_buzzer.ino" +#ifdef USE_BUZZER + + + + +#define XDRV_24 24 + +struct BUZZER { + uint32_t tune = 0; + uint32_t tune_reload = 0; + bool active = true; + bool enable = false; + uint8_t inverted = 0; + uint8_t count = 0; + uint8_t mode = 0; + uint8_t set[2]; + uint8_t duration; + uint8_t state = 0; +} Buzzer; + + + +void BuzzerOff(void) +{ + DigitalWrite(GPIO_BUZZER, Buzzer.inverted); +} + + +void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) +{ + Buzzer.set[0] = off; + Buzzer.set[1] = on; + Buzzer.duration = 1; + Buzzer.tune_reload = 0; + Buzzer.mode = mode; + + if (tune) { + uint32_t tune1 = tune; + uint32_t tune2 = tune; + for (uint32_t i = 0; i < 32; i++) { + if (!(tune2 & 0x80000000)) { + tune2 <<= 1; + } else { + Buzzer.tune_reload <<= 1; + Buzzer.tune_reload |= tune1 & 1; + tune1 >>= 1; + } + } + Buzzer.tune = Buzzer.tune_reload; + } + Buzzer.count = count * 2; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, Buzzer.count, on, off, tune, Buzzer.tune); + + Buzzer.enable = (Buzzer.count > 0); + if (!Buzzer.enable) { + BuzzerOff(); + } +} + +void BuzzerSetStateToLed(uint32_t state) +{ + if (Buzzer.enable && (2 == Buzzer.mode)) { + Buzzer.state = (state != 0); + DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); + } +} + +void BuzzerBeep(uint32_t count) +{ + BuzzerBeep(count, 1, 1, 0, 0); +} + +void BuzzerEnabledBeep(uint32_t count, uint32_t duration) +{ + if (Settings.flag3.buzzer_enable) { + BuzzerBeep(count, duration, 1, 0, 0); + } +} + + + +bool BuzzerPinState(void) +{ + if (XdrvMailbox.index == GPIO_BUZZER_INV) { + Buzzer.inverted = 1; + XdrvMailbox.index -= (GPIO_BUZZER_INV - GPIO_BUZZER); + return true; + } + return false; +} + +void BuzzerInit(void) +{ + if (pin[GPIO_BUZZER] < 99) { + pinMode(pin[GPIO_BUZZER], OUTPUT); + BuzzerOff(); + } else { + Buzzer.active = false; + } +} + +void BuzzerEvery100mSec(void) +{ + if (Buzzer.enable && (Buzzer.mode != 2)) { + if (Buzzer.count) { + if (Buzzer.duration) { + Buzzer.duration--; + if (!Buzzer.duration) { + if (Buzzer.tune) { + Buzzer.state = Buzzer.tune & 1; + Buzzer.tune >>= 1; + } else { + Buzzer.tune = Buzzer.tune_reload; + Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1; + Buzzer.state = Buzzer.count & 1; + if (Buzzer.mode) { + Buzzer.count |= 2; + } + } + Buzzer.duration = Buzzer.set[Buzzer.state]; + } + } + DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); + } else { + Buzzer.enable = false; + } + } +} + + + + + +const char kBuzzerCommands[] PROGMEM = "|" + "Buzzer" ; + +void (* const BuzzerCommand[])(void) PROGMEM = { + &CmndBuzzer }; + +void CmndBuzzer(void) +{ +# 174 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_24_buzzer.ino" + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload != 0) { + uint32_t parm[4] = { 0 }; + uint32_t mode = 0; + ParseParameters(4, parm); + if (XdrvMailbox.payload <= 0) { + parm[0] = 1; + mode = -XdrvMailbox.payload; + } + for (uint32_t i = 1; i < 3; i++) { + if (parm[i] < 1) { parm[i] = 1; } + } + BuzzerBeep(parm[0], parm[1], parm[2], parm[3], mode); + } else { + BuzzerBeep(0); + } + } else { + BuzzerBeep(1); + } + ResponseCmndDone(); +} + + + + + +bool Xdrv24(uint8_t function) +{ + bool result = false; + + if (Buzzer.active) { + switch (function) { + case FUNC_EVERY_100_MSECOND: + BuzzerEvery100mSec(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kBuzzerCommands, BuzzerCommand); + break; + case FUNC_PRE_INIT: + BuzzerInit(); + break; + case FUNC_PIN_STATE: + result = BuzzerPinState(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" +# 21 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" +#ifdef USE_A4988_STEPPER + + + + +#define XDRV_25 25 + +#include + +short A4988_dir_pin = pin[GPIO_MAX]; +short A4988_stp_pin = pin[GPIO_MAX]; +short A4988_ms1_pin = pin[GPIO_MAX]; +short A4988_ms2_pin = pin[GPIO_MAX]; +short A4988_ms3_pin = pin[GPIO_MAX]; +short A4988_ena_pin = pin[GPIO_MAX]; +int A4988_spr = 0; +float A4988_rpm = 0; +short A4988_mis = 0; + +A4988_Stepper* myA4988 = nullptr; + +void A4988Init(void) +{ + A4988_dir_pin = pin[GPIO_A4988_DIR]; + A4988_stp_pin = pin[GPIO_A4988_STP]; + A4988_ena_pin = pin[GPIO_A4988_ENA]; + A4988_ms1_pin = pin[GPIO_A4988_MS1]; + A4988_ms2_pin = pin[GPIO_A4988_MS2]; + A4988_ms3_pin = pin[GPIO_A4988_MS3]; + A4988_spr = 200; + A4988_rpm = 30; + A4988_mis = 1; + + myA4988 = new A4988_Stepper( A4988_spr + , A4988_rpm + , A4988_mis + , A4988_dir_pin + , A4988_stp_pin + , A4988_ena_pin + , A4988_ms1_pin + , A4988_ms2_pin + , A4988_ms3_pin ); +} + +const char kA4988Commands[] PROGMEM = "Motor|" + "Move|Rotate|Turn|MIS|SPR|RPM"; + +void (* const A4988Command[])(void) PROGMEM = { + &CmndDoMove,&CmndDoRotate,&CmndDoTurn,&CmndSetMIS,&CmndSetSPR,&CmndSetRPM}; + +void CmndDoMove(void) { + if (XdrvMailbox.data_len > 0) { + long stepsPlease = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->doMove(stepsPlease); + ResponseCmndDone(); + } +} + +void CmndDoRotate(void) { + if (XdrvMailbox.data_len > 0) { + long degrsPlease = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->doRotate(degrsPlease); + ResponseCmndDone(); + } +} + +void CmndDoTurn(void) { + if (XdrvMailbox.data_len > 0) { + float turnsPlease = strtod(XdrvMailbox.data,nullptr); + myA4988->doTurn(turnsPlease); + ResponseCmndDone(); + } +} + +void CmndSetMIS(void) { + if ((pin[GPIO_A4988_MS1] < 99) && (pin[GPIO_A4988_MS2] < 99) && (pin[GPIO_A4988_MS3] < 99) && (XdrvMailbox.data_len > 0)) { + short newMIS = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setMIS(newMIS); + ResponseCmndDone(); + } +} + +void CmndSetSPR(void) { + if (XdrvMailbox.data_len > 0) { + int newSPR = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setSPR(newSPR); + ResponseCmndDone(); + } +} + +void CmndSetRPM(void) { + if (XdrvMailbox.data_len > 0) { + short newRPM = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setRPM(newRPM); + ResponseCmndDone(); + } +} + + + + +bool Xdrv25(uint8_t function) +{ + bool result = false; + if ((pin[GPIO_A4988_DIR] < 99) && (pin[GPIO_A4988_STP] < 99)) { + switch (function) { + case FUNC_INIT: + A4988Init(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kA4988Commands, A4988Command); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_26_ariluxrf.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_26_ariluxrf.ino" +#ifdef USE_LIGHT +#ifdef USE_ARILUX_RF + + + + +#define XDRV_26 26 + +const uint32_t ARILUX_RF_TIME_AVOID_DUPLICATE = 1000; + +const uint8_t ARILUX_RF_MAX_CHANGES = 51; +const uint32_t ARILUX_RF_SEPARATION_LIMIT = 4300; +const uint32_t ARILUX_RF_RECEIVE_TOLERANCE = 60; + +struct ARILUX { + unsigned int rf_timings[ARILUX_RF_MAX_CHANGES]; + + unsigned long rf_received_value = 0; + unsigned long rf_last_received_value = 0; + unsigned long rf_last_time = 0; + unsigned long rf_lasttime = 0; + + unsigned int rf_change_count = 0; + unsigned int rf_repeat_count = 0; + + uint8_t rf_toggle = 0; +} Arilux; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +#ifndef USE_WS2812_DMA +void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; +#endif +#endif + +void AriluxRfInterrupt(void) +{ + unsigned long time = micros(); + unsigned int duration = time - Arilux.rf_lasttime; + + if (duration > ARILUX_RF_SEPARATION_LIMIT) { + if (abs(duration - Arilux.rf_timings[0]) < 200) { + Arilux.rf_repeat_count++; + if (Arilux.rf_repeat_count == 2) { + unsigned long code = 0; + const unsigned int delay = Arilux.rf_timings[0] / 31; + const unsigned int delayTolerance = delay * ARILUX_RF_RECEIVE_TOLERANCE / 100; + for (unsigned int i = 1; i < Arilux.rf_change_count -1; i += 2) { + code <<= 1; + if (abs(Arilux.rf_timings[i] - (delay *3)) < delayTolerance && abs(Arilux.rf_timings[i +1] - delay) < delayTolerance) { + code |= 1; + } + } + if (Arilux.rf_change_count > 49) { + Arilux.rf_received_value = code; + } + Arilux.rf_repeat_count = 0; + } + } + Arilux.rf_change_count = 0; + } + if (Arilux.rf_change_count >= ARILUX_RF_MAX_CHANGES) { + Arilux.rf_change_count = 0; + Arilux.rf_repeat_count = 0; + } + Arilux.rf_timings[Arilux.rf_change_count++] = duration; + Arilux.rf_lasttime = time; +} + +void AriluxRfHandler(void) +{ + unsigned long now = millis(); + if (Arilux.rf_received_value && !((Arilux.rf_received_value == Arilux.rf_last_received_value) && (now - Arilux.rf_last_time < ARILUX_RF_TIME_AVOID_DUPLICATE))) { + Arilux.rf_last_received_value = Arilux.rf_received_value; + Arilux.rf_last_time = now; + + uint16_t hostcode = Arilux.rf_received_value >> 8 & 0xFFFF; + if (Settings.rf_code[1][6] == Settings.rf_code[1][7]) { + Settings.rf_code[1][6] = hostcode >> 8 & 0xFF; + Settings.rf_code[1][7] = hostcode & 0xFF; + } + uint16_t stored_hostcode = Settings.rf_code[1][6] << 8 | Settings.rf_code[1][7]; + + DEBUG_DRIVER_LOG(PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, Arilux.rf_received_value); + + if (hostcode == stored_hostcode) { + char command[33]; + char value = '-'; + command[0] = '\0'; + uint8_t keycode = Arilux.rf_received_value & 0xFF; + switch (keycode) { + case 1: + case 3: + snprintf_P(command, sizeof(command), PSTR(D_CMND_POWER " %d"), (1 == keycode) ? 1 : 0); + break; + case 2: + Arilux.rf_toggle++; + Arilux.rf_toggle &= 0x3; + snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), 200 + Arilux.rf_toggle); + break; + case 4: + value = '+'; + case 7: + snprintf_P(command, sizeof(command), PSTR(D_CMND_SPEED " %c"), value); + break; + case 5: + value = '+'; + case 8: + snprintf_P(command, sizeof(command), PSTR(D_CMND_SCHEME " %c"), value); + break; + case 6: + value = '+'; + case 9: + snprintf_P(command, sizeof(command), PSTR(D_CMND_DIMMER " %c"), value); + break; + default: { + if ((keycode >= 10) && (keycode <= 21)) { + snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), keycode -9); + } + } + } + if (strlen(command)) { + ExecuteCommand(command, SRC_LIGHT); + } + } + } + Arilux.rf_received_value = 0; +} + +void AriluxRfInit(void) +{ + if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { + if (Settings.last_module != Settings.module) { + Settings.rf_code[1][6] = 0; + Settings.rf_code[1][7] = 0; + Settings.last_module = Settings.module; + } + Arilux.rf_received_value = 0; + + digitalWrite(pin[GPIO_ARIRFSEL], 0); + attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE); + } +} + +void AriluxRfDisable(void) +{ + if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { + detachInterrupt(pin[GPIO_ARIRFRCV]); + digitalWrite(pin[GPIO_ARIRFSEL], 1); + } +} + + + + + +bool Xdrv26(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_ARIRFRCV] < 99) { AriluxRfHandler(); } + break; + case FUNC_EVERY_SECOND: + if (10 == uptime) { AriluxRfInit(); } + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_27_shutter.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_27_shutter.ino" +#ifdef USE_SHUTTER + + + + +#define XDRV_27 27 + +#define D_SHUTTER "SHUTTER" + +const uint16_t MOTOR_STOP_TIME = 500; +const uint8_t steps_per_second = 20; + +uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; +uint16_t messwerte[5] = {30,50,70,90,100}; +uint16_t last_execute_step; + +enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; +enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; + +const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" + D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" + D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" + D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" + D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME; + +void (* const ShutterCommand[])(void) PROGMEM = { + &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, + &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, + &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, + &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime}; + + const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; + const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; + +#include + +Ticker TickerShutter; + +struct SHUTTER { + power_t mask = 0; + power_t old_power = 0; + power_t switched_relay = 0; + uint32_t time[MAX_SHUTTERS]; + int32_t open_max[MAX_SHUTTERS]; + int32_t target_position[MAX_SHUTTERS]; + int32_t start_position[MAX_SHUTTERS]; + int32_t real_position[MAX_SHUTTERS]; + uint16_t open_time[MAX_SHUTTERS]; + uint16_t close_time[MAX_SHUTTERS]; + uint16_t close_velocity[MAX_SHUTTERS]; + int8_t direction[MAX_SHUTTERS]; + uint8_t mode = 0; + int16_t motordelay[MAX_SHUTTERS]; + int16_t pwm_frequency; + uint16_t max_pwm_frequency = 1000; + uint16_t max_close_pwm_frequency[MAX_SHUTTERS]; + uint8_t skip_relay_change; + int32_t accelerator[MAX_SHUTTERS]; +} Shutter; + +void ShutterLogPos(uint32_t i) +{ + char stemp2[10]; + dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d"), + i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_frequency); +} + +void ShutterRtc50mS(void) +{ + for (uint32_t i = 0; i < shutters_present; i++) { + Shutter.time[i]++; + if (Shutter.accelerator[i]) { + Shutter.pwm_frequency += Shutter.accelerator[i]; + Shutter.pwm_frequency = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency)); + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 50); + } + } +} + +#define SHT_DIV_ROUND(__A,__B) (((__A) + (__B)/2) / (__B)) + +int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) +{ + if (0 == percent) return 0; + if (100 == percent) return Shutter.open_max[index]; + if (Settings.shutter_set50percent[index] != 50) { + return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; + } else { + uint32_t realpos; + + for (uint32_t j = 0; j < 5; j++) { + if (0 == Settings.shuttercoeff[j][index]) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); + for (uint32_t k = 0; k < 5; k++) { + Settings.shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]); + } + } + } + for (uint32_t i = 0; i < 5; i++) { + if ((percent * 10) >= Settings.shuttercoeff[i][index]) { + realpos = SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i+1], 100); + + } else { + if (0 == i) { + realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter.open_max[index] * calibrate_pos[i+1], Settings.shuttercoeff[i][index]), 10); + } else { + + + realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]), Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), 100); + } + break; + } + } + return realpos; + } +} + +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) +{ + if (0 >= realpos) return 0; + if (Shutter.open_max[index] <= realpos) return 100; + if (Settings.shutter_set50percent[index] != 50) { + return (Settings.shuttercoeff[2][index] * 5 > realpos) ? SHT_DIV_ROUND(realpos, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos-Settings.shuttercoeff[0][index], Settings.shuttercoeff[1][index]); + } else { + uint16_t realpercent; + + for (uint32_t i = 0; i < 5; i++) { + if (realpos >= Shutter.open_max[index] * calibrate_pos[i+1] / 100) { + realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[i][index], 10); + + } else { + if (0 == i) { + realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * Settings.shuttercoeff[i][index], calibrate_pos[i+1]), Shutter.open_max[index]); + } else { + + + + realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), (calibrate_pos[i+1] - calibrate_pos[i])), Shutter.open_max[index]) ; + } + break; + } + } + return realpercent; + } +} + +void ShutterInit(void) +{ + shutters_present = 0; + Shutter.mask = 0; + + Shutter.old_power = power; + bool relay_in_interlock = false; + + + if (Settings.shutter_startrelay[MAX_SHUTTERS] == 0) { + Shutter.max_pwm_frequency = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : Shutter.max_pwm_frequency; + } + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + + Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]); + if (Settings.shutter_startrelay[i] && (Settings.shutter_startrelay[i] < 9)) { + shutters_present++; + + + Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1) ; + + for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { + + if (Settings.interlock[j] && (Settings.interlock[j] & Shutter.mask)) { + + relay_in_interlock = true; + } + } + if (relay_in_interlock) { + if (Settings.pulse_timer[i] > 0) { + Shutter.mode = SHT_PULSE_OPEN__PULSE_CLOSE; + } else { + Shutter.mode = SHT_OFF_OPEN__OFF_CLOSE; + } + } else { + Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; + if ((pin[GPIO_PWM1+i] < 99) && (pin[GPIO_CNTR1+i] < 99)) { + Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER; + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 50); + } + } + + TickerShutter.attach_ms(50, ShutterRtc50mS ); + + Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] > 0) ? Settings.shutter_set50percent[i] : 50; + + + Shutter.open_time[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100; + Shutter.close_time[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100; + + + Shutter.open_max[i] = 200 * Shutter.open_time[i]; + Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ; + Shutter.max_close_pwm_frequency[i] = Shutter.max_pwm_frequency*Shutter.open_time[i] / Shutter.close_time[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Closefreq: %d"),i, Shutter.max_close_pwm_frequency[i]); + + + if (Settings.shutter_set50percent[i] != 50) { + Settings.shuttercoeff[1][i] = Shutter.open_max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; + Settings.shuttercoeff[0][i] = Shutter.open_max[i] - (Settings.shuttercoeff[1][i] * 100); + Settings.shuttercoeff[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5; + } + Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1); + + Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i); + + Shutter.start_position[i] = Shutter.target_position[i] = Shutter.real_position[i]; + Shutter.motordelay[i] = Settings.shutter_motordelay[i]; + + char shutter_open_chr[10]; + dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); + char shutter_close_chr[10]; + dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100, Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, is locked %d, end stop time enabled %d, shuttermode %d, motordelay %d"), + i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, + Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], + Shutter.mask, (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, Shutter.mode, Shutter.motordelay[i]); + + } else { + + break; + } + ShutterLimitRealAndTargetPositions(i); + Settings.shutter_accuracy = 1; + } +} + +void ShutterReportPosition(bool always) +{ + uint32_t shutter_moving = 0; + Response_P(PSTR("{")); + for (uint32_t i = 0; i < shutters_present; i++) { + + uint32_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); + if (Shutter.direction[i] != 0) { + shutter_moving = 1; + ShutterLogPos(i); + } + if (i) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i]); + } + ResponseJsonEnd(); + if (always || (1 == shutter_moving)) { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); + } + if (rules_flag.shutter_moving > shutter_moving) { + rules_flag.shutter_moved = 1; + } else { + rules_flag.shutter_moved = 0; + } + rules_flag.shutter_moving = shutter_moving; + +} + +void ShutterLimitRealAndTargetPositions(uint32_t i) { + if (Shutter.real_position[i]<0) Shutter.real_position[i] = 0; + if (Shutter.real_position[i]>Shutter.open_max[i]) Shutter.real_position[i] = Shutter.open_max[i]; + if (Shutter.target_position[i]<0) Shutter.target_position[i] = 0; + if (Shutter.target_position[i]>Shutter.open_max[i]) Shutter.target_position[i] = Shutter.open_max[i]; +} + +void ShutterUpdatePosition(void) +{ + + char scommand[CMDSZ]; + char stopic[TOPSZ]; + + for (uint32_t i = 0; i < shutters_present; i++) { + if (Shutter.direction[i] != 0) { + int32_t stop_position_delta = 20; + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { + + + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + + int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; + int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); + int32_t min_runtime_ms = Shutter.pwm_frequency*1000 / max_freq_change_per_sec; + int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; + int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency / max_frequency * Shutter.direction[i] ; + + int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; + stop_position_delta =200 * Shutter.pwm_frequency/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); + + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, + Shutter.pwm_frequency,max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); + + if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { + + Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); + + } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency == max_frequency) { + Shutter.accelerator[i] = 0; + } + } else { + Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + } + if ( Shutter.real_position[i] * Shutter.direction[i] + stop_position_delta >= Shutter.target_position[i] * Shutter.direction[i] ) { + + + uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; + int16_t missing_steps; + + switch (Shutter.mode) { + case SHT_PULSE_OPEN__PULSE_CLOSE: + + if (SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source) { + ExecuteCommandPower(cur_relay, 1, SRC_SHUTTER); + } else { + last_source = SRC_SHUTTER; + } + break; + case SHT_OFF_ON__OPEN_CLOSE_STEPPER: + missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); + Shutter.accelerator[i] = 0; + Shutter.pwm_frequency = Shutter.pwm_frequency > 250 ? 250 : Shutter.pwm_frequency; + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 50); + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); + while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { + delay(1); + } + analogWrite(pin[GPIO_PWM1+i], 0); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); + + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); + } + break; + case SHT_OFF_ON__OPEN_CLOSE: + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); + } + break; + case SHT_OFF_OPEN__OFF_CLOSE: + + if ((1 << (cur_relay-1)) & power) { + + ExecuteCommandPower(cur_relay, 0, SRC_SHUTTER); + } + break; + } + ShutterLimitRealAndTargetPositions(i); + Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); + + ShutterLogPos(i); + + Shutter.start_position[i] = Shutter.real_position[i]; + + + snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P("%d", (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); + MqttPublish(stopic, Settings.flag.mqtt_power_retain); + + Shutter.direction[i] = 0; + ShutterReportPosition(true); + XdrvRulesProcess(); + } + } + } +} + +bool ShutterState(uint32_t device) +{ + device--; + device &= 3; + return (Settings.flag3.shutter_mode && + (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) ); +} + +void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) +{ + + if ( ( (1 == direction) && ((Shutter.open_max[i] - Shutter.real_position[i]) / 100 <= 2) ) + || ( (-1 == direction) && (Shutter.real_position[i] / Shutter.close_velocity[i] <= 2)) ) { + Shutter.skip_relay_change = 1; + } else { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { + Shutter.pwm_frequency = 0; + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 0); + + if (pin[GPIO_CNTR1+i] < 99) { + RtcSettings.pulse_counter[i] = 0; + } + Shutter.accelerator[i] = Shutter.max_pwm_frequency / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Ramp up: %d"), Shutter.accelerator[i]); + } + Shutter.target_position[i] = target_pos; + Shutter.start_position[i] = Shutter.real_position[i]; + Shutter.time[i] = 0; + Shutter.skip_relay_change = 0; + Shutter.direction[i] = direction; + + } + +} + +void ShutterWaitForMotorStop(uint32_t i) +{ + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); + if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { + if (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode) { + + while (Shutter.pwm_frequency > 0) { + Shutter.accelerator[i] = 0; + Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); + analogWriteFreq(Shutter.pwm_frequency); + analogWrite(pin[GPIO_PWM1+i], 50); + delay(50); + } + analogWrite(pin[GPIO_PWM1+i], 0); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + } else { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + delay(MOTOR_STOP_TIME); + } + } else { + delay(MOTOR_STOP_TIME); + } +} + +int32_t ShutterCounterBasedPosition(uint32_t i) +{ + return ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; +} + +void ShutterRelayChanged(void) +{ + + + + + char stemp1[10]; + + for (uint32_t i = 0; i < shutters_present; i++) { + power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; + + uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; + + if (manual_relays_changed) { + + ShutterLimitRealAndTargetPositions(i); + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { + ShutterWaitForMotorStop(i); + switch (powerstate_local) { + case 1: + ShutterStartInit(i, 1, Shutter.open_max[i]); + break; + case 3: + ShutterStartInit(i, -1, 0); + break; + default: + + Shutter.target_position[i] = Shutter.real_position[i]; + } + } else { + if (Shutter.direction[i] != 0 && (!powerstate_local || (powerstate_local && Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE))) { + Shutter.target_position[i] = Shutter.real_position[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); + } else { + last_source = SRC_SHUTTER; + if (powerstate_local == 2) { + + ShutterWaitForMotorStop(i); + ShutterStartInit(i, -1, 0); + } else { + + ShutterWaitForMotorStop(i); + ShutterStartInit(i, 1, Shutter.open_max[i]); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter.target_position[i], powerstate_local); + } + } + } +} + +bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { + + uint32 min_shutterbutton_hold_timer = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) + min_shutterbutton_hold_timer = Button.hold_timer[i]; + } + return (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1)); +} + +void ShutterButtonHandler(void) +{ + uint8_t buttonState = SHT_NOT_PRESSED; + uint8_t button = XdrvMailbox.payload; + uint8_t press_index; + uint32_t button_index = XdrvMailbox.index; + uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; + + uint16_t loops_per_second = 1000 / Settings.button_debounce; + + if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { + if (Settings.flag.button_single) { + buttonState = SHT_PRESSED_MULTI; + press_index = 1; + } else { + if ((Shutter.direction[shutter_index]) && (Button.press_counter[button_index]==0)) { + buttonState = SHT_PRESSED_IMMEDIATE; + press_index = 1; + Button.press_counter[button_index] = 99; + } else + Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; + Button.window_timer[button_index] = loops_per_second / 2; + } + blinks = 201; + } + + if (NOT_PRESSED == button) { + Button.hold_timer[button_index] = 0; + } else { + Button.hold_timer[button_index]++; + if (!Settings.flag.button_single) { + if (Settings.param[P_HOLD_IGNORE] > 0) { + if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { + Button.hold_timer[button_index] = 0; + Button.press_counter[button_index] = 0; + } + } + if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { + + if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { + + for (uint32_t i = 0; i < MAX_KEYS; i++) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) + Button.press_counter[i] = 99; + press_index = 0; + buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS; + } + if (Button.press_counter[button_index]<99) { + press_index = 0; + buttonState = SHT_PRESSED_HOLD; + } + Button.press_counter[button_index] = 0; + } + if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { + + if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { + + press_index = 0; + buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; + } + } + } + } + + if (!Settings.flag.button_single) { + if (Button.window_timer[button_index]) { + Button.window_timer[button_index]--; + } else { + if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { + if (Button.press_counter[button_index]<99) { + + uint32 min_shutterbutton_press_counter = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) + min_shutterbutton_press_counter = Button.press_counter[i]; + } + if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { + + press_index = Button.press_counter[button_index]; + for (uint32_t i = 0; i < MAX_KEYS; i++) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) + Button.press_counter[i] = 99; + buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; + } + if ((buttonState != SHT_PRESSED_MULTI_SIMULTANEOUS) && (Button.press_counter[button_index]<99)) { + + press_index = Button.press_counter[button_index]; + buttonState = SHT_PRESSED_MULTI; + } + } + Button.press_counter[button_index] = 0; + } + } + } + + if (buttonState != SHT_NOT_PRESSED) { + if (buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) { + if ((press_index>=5) && (press_index<=7) && (!Settings.flag.button_restrict)) { + + char scmnd[20]; + GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { + + if (!Settings.flag.button_restrict) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } else if (buttonState <= SHT_PRESSED_IMMEDIATE) { + if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { + uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); + if (pos_press_index>3) pos_press_index=3; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); + XdrvMailbox.index = shutter_index +1; + last_source = SRC_BUTTON; + XdrvMailbox.data_len = 0; + char databuf[1] = ""; + XdrvMailbox.data = databuf; + XdrvMailbox.command = NULL; + if (buttonState == SHT_PRESSED_IMMEDIATE) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); + } + else { + uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; + if (position) { + if (Shutter.direction[shutter_index]) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); + } else { + XdrvMailbox.payload = position = (position-1)<<1; + CmndShutterPosition(); + if (Settings.shutter_button[button_index] & ((0x01<<26)< 0) && (XdrvMailbox.index <= shutters_present)) { + if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { + if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { + XdrvMailbox.index = XdrvMailbox.payload; + } + uint32_t i = XdrvMailbox.index -1; + if (Shutter.direction[i] != 0) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]); + + int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); + + last_source = SRC_WEBGUI; + CmndShutterPosition(); + } else { + if (XdrvMailbox.command) + ResponseCmndDone(); + } + } else { + if (XdrvMailbox.command) + ResponseCmndIdxChar("Locked"); + } + } +} + +void CmndShutterPosition(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { + uint32_t index = XdrvMailbox.index-1; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); + + + if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { + + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { + CmndShutterOpen(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN))) { + CmndShutterClose(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN)))) { + XdrvMailbox.payload = -99; + CmndShutterStop(); + return; + } + } + + int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? 0 : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); + + target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; + if (XdrvMailbox.payload != -99) { + + Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); + Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); + } + if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { + if (Settings.shutter_options[index] & 4) { + if (0 == target_pos_percent) Shutter.target_position[index] -= 1 * 2000; + if (100 == target_pos_percent) Shutter.target_position[index] += 1 * 2000; + } + int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; + if (Shutter.direction[index] == -new_shutterdirection) { + + if (SHT_PULSE_OPEN__PULSE_CLOSE == Shutter.mode) { + + ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 0 : 1), 1, SRC_SHUTTER); + delay(100); + } else { + if (SHT_OFF_OPEN__OFF_CLOSE == Shutter.mode) { + ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 1 : 0), 0, SRC_SHUTTER); + ShutterWaitForMotorStop(index); + } + } + } + if (Shutter.direction[index] != new_shutterdirection) { + if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { + + ShutterWaitForMotorStop(index); + ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); + if (Shutter.skip_relay_change == 0) { + + ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); + + ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); + } + } else { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start in dir %d"), Shutter.direction[index]); + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); + if (Shutter.skip_relay_change == 0) { + ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); + } + + } + Shutter.switched_relay = 0; + } + } else { + target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); + ShutterReportPosition(true); + } + XdrvMailbox.index = index +1; + if (XdrvMailbox.command) + ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent); + } else { + ShutterReportPosition(true); + if (XdrvMailbox.command) + ResponseCmndIdxChar("Locked"); + } + } +} + +void CmndShutterOpenTime(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_opentime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index -1]) / 10, 1, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterCloseTime(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_closetime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index -1]) / 10, 1, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterMotorDelay(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(steps_per_second * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / steps_per_second, 2, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterRelay(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) { + Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; + if (XdrvMailbox.payload > 0) { + Shutter.mask |= 3 << (XdrvMailbox.payload - 1); + } else { + Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1); + } + Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; + ShutterInit(); + + } + ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]); + } +} + +void CmndShutterButton(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + uint32_t setting = 0; +# 915 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_27_shutter.ino" + if (XdrvMailbox.data_len > 0) { + uint32_t i = 0; + uint32_t button_index = 0; + bool done = false; + bool isShortCommand = false; + char *str_ptr; + + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); + + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) { + int field; + if (str[0] == '-') { + field = -1; + } else { + field = atoi(str); + } + switch (i) { + case 0: + if ((field >= -1) && (field<=4)) { + button_index = (field<=0)?(-1):field; + done = (button_index==-1); + } else + done = true; + break; + case 1: + if (!strcmp_P(str, PSTR("up"))) { + setting |= (((100>>1)+1)<<2) | (((50>>1)+1)<<8) | (((75>>1)+1)<<14) | (((100>>1)+1)<<20); + isShortCommand = true; + break; + } else if (!strcmp_P(str, PSTR("down"))) { + setting |= (((0>>1)+1)<<2) | (((50>>1)+1)<<8) | (((25>>1)+1)<<14) | (((0>>1)+1)<<20); + isShortCommand = true; + break; + } else if (!strcmp_P(str, PSTR("updown"))) { + setting |= (((100>>1)+1)<<2) | (((0>>1)+1)<<8) | (((50>>1)+1)<<14); + isShortCommand = true; + break; + } + case 2: + if (isShortCommand) { + if ((field==1) && (setting & (0x3F<<(2+6*3)))) + + setting |= (0x3<<29); + done = true; + break; + } + case 3: + case 4: + if ((field >= -1) && (field<=100)) + setting |= (((field>>1)+1)<<(i*6 + (2-6))); + break; + case 5: + case 6: + case 7: + case 8: + case 9: + if (field==1) + setting |= (1<<(i + (26-5))); + break; + } + if (done) break; + } + + if (button_index) { + if (button_index==-1) { + + for (uint32_t i=0 ; i < MAX_KEYS ; i++) + if ((Settings.shutter_button[i]&0x3) == (XdrvMailbox.index-1)) + Settings.shutter_button[i] = 0; + } else { + if (setting) { + + setting |= (1<<31); + setting |= (XdrvMailbox.index-1) & 0x3; + } + Settings.shutter_button[button_index-1] = setting; + } + } + } + char setting_chr[30*MAX_KEYS] = "-", *setting_chr_ptr = setting_chr; + for (uint32_t i=0 ; i < MAX_KEYS ; i++) { + setting = Settings.shutter_button[i]; + if ((setting&(1<<31)) && ((setting&0x3) == (XdrvMailbox.index-1))) { + if (*setting_chr_ptr == 0) + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR("|")); + setting_chr_ptr += snprintf_P(setting_chr_ptr, 2, PSTR("%d"), i+1); + + for (uint32_t j=0 ; j < 4 ; j++) { + int8_t pos = (((setting>> (2+6*j))&(0x3f))-1)<<1; + if (pos>=0) + setting_chr_ptr += snprintf_P(setting_chr_ptr, 5, PSTR(" %d"), pos); + else + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); + } + for (uint32_t j=0 ; j < 5 ; j++) { + bool mqtt = ((setting>>(26+j))&(0x01)!=0); + if (mqtt) + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" 1")); + else + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); + } + } + } + ResponseCmndIdxChar(setting_chr); + } +} + +void CmndShutterSetHalfway(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Settings.shutter_set50percent[XdrvMailbox.index -1] = (Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; + ShutterInit(); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); + } +} + +void CmndShutterFrequency(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { + Shutter.max_pwm_frequency = XdrvMailbox.payload; + if (shutters_present < 4) { + Settings.shuttercoeff[4][3] = Shutter.max_pwm_frequency; + } + ShutterInit(); + ResponseCmndNumber(XdrvMailbox.payload); + } else { + ResponseCmndNumber(Shutter.max_pwm_frequency); + } +} + +void CmndShutterSetClose(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + Shutter.real_position[XdrvMailbox.index -1] = 0; + ShutterStartInit(XdrvMailbox.index -1, 0, 0); + Settings.shutter_position[XdrvMailbox.index -1] = 0; + ResponseCmndIdxChar(D_CONFIGURATION_RESET); + } +} + +void CmndShutterInvert(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(1); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (1); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 1 : 0); + } +} + +void CmndShutterCalibration(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + uint32_t i = 0; + char *str_ptr; + + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); + + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 5; str = strtok_r(nullptr, " ", &str_ptr), i++) { + int field = atoi(str); + + + if ((field <= 0) || (field > 30000) || ( (i>0) && (field <= messwerte[i-1]) ) ) { + break; + } + messwerte[i] = field; + } + for (i = 0; i < 5; i++) { + Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); + } + ShutterInit(); + ResponseCmndIdxChar(XdrvMailbox.data); + } else { + char setting_chr[30] = "0"; + snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings.shuttercoeff[0][XdrvMailbox.index -1], Settings.shuttercoeff[1][XdrvMailbox.index -1], Settings.shuttercoeff[2][XdrvMailbox.index -1], Settings.shuttercoeff[3][XdrvMailbox.index -1], Settings.shuttercoeff[4][XdrvMailbox.index -1]); + ResponseCmndIdxChar(setting_chr); + } + } +} + +void CmndShutterLock(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(2); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (2); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 2) ? 1 : 0); + } +} + +void CmndShutterEnableEndStopTime(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(4); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (4); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 4) ? 1 : 0); + } +} + + + + + +bool Xdrv27(uint8_t function) +{ + bool result = false; + + if (Settings.flag3.shutter_mode) { + switch (function) { + case FUNC_PRE_INIT: + ShutterInit(); + break; + case FUNC_EVERY_50_MSECOND: + ShutterUpdatePosition(); + break; + case FUNC_EVERY_SECOND: + + ShutterReportPosition(false); + break; + + case FUNC_COMMAND: + result = DecodeCommand(kShutterCommands, ShutterCommand); + break; + case FUNC_JSON_APPEND: + for (uint8_t i = 0; i < shutters_present; i++) { + uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; + ResponseAppend_P(","); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_SHUTTER, position); + } +#endif + } + break; + case FUNC_SET_POWER: + char stemp1[10]; + + Shutter.switched_relay = XdrvMailbox.index ^ Shutter.old_power; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), Shutter.switched_relay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); + ShutterRelayChanged(); + Shutter.old_power = XdrvMailbox.index; + break; + case FUNC_SET_DEVICE_POWER: + if (Shutter.skip_relay_change ) { + uint8_t i; + for (i = 0; i < devices_present; i++) { + if (Shutter.switched_relay &1) { + break; + } + Shutter.switched_relay >>= 1; + } + + result = true; + Shutter.skip_relay_change = 0; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"),i); + ExecuteCommandPower(i+1, 0, SRC_SHUTTER); + } + break; + case FUNC_BUTTON_PRESSED: + if (Settings.shutter_button[XdrvMailbox.index] & (1<<31)) { + ShutterButtonHandler(); + result = true; + } + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_28_pcf8574.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_28_pcf8574.ino" +#ifdef USE_I2C +#ifdef USE_PCF8574 + + + + + + + +#define XDRV_28 28 +#define XI2C_02 2 + +#define PCF8574_ADDR1 0x20 +#define PCF8574_ADDR2 0x38 + +struct PCF8574 { + int error; + uint8_t pin[64]; + uint8_t address[MAX_PCF8574]; + uint8_t pin_mask[MAX_PCF8574] = { 0 }; + uint8_t max_connected_ports = 0; + uint8_t max_devices = 0; + char stype[9]; + bool type = false; +} Pcf8574; + +void Pcf8574SwitchRelay(void) +{ + for (uint32_t i = 0; i < devices_present; i++) { + uint8_t relay_state = bitRead(XdrvMailbox.index, i); + + + + if (Pcf8574.max_devices > 0 && Pcf8574.pin[i] < 99) { + uint8_t board = Pcf8574.pin[i]>>3; + uint8_t oldpinmask = Pcf8574.pin_mask[board]; + uint8_t _val = bitRead(rel_inverted, i) ? !relay_state : relay_state; + + + + if (_val) { + Pcf8574.pin_mask[board] |= _val << (Pcf8574.pin[i]&0x7); + } else { + Pcf8574.pin_mask[board] &= ~(1 << (Pcf8574.pin[i]&0x7)); + } + if (oldpinmask != Pcf8574.pin_mask[board]) { + Wire.beginTransmission(Pcf8574.address[board]); + Wire.write(Pcf8574.pin_mask[board]); + Pcf8574.error = Wire.endTransmission(); + } + + } + } +} + +void Pcf8574Init(void) +{ + uint8_t pcf8574_address = PCF8574_ADDR1; + while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +8)) { + + + + if (I2cSetDevice(pcf8574_address)) { + Pcf8574.type = true; + + Pcf8574.address[Pcf8574.max_devices] = pcf8574_address; + Pcf8574.max_devices++; + + strcpy(Pcf8574.stype, "PCF8574"); + if (pcf8574_address >= PCF8574_ADDR2) { + strcpy(Pcf8574.stype, "PCF8574A"); + } + I2cSetActiveFound(pcf8574_address, Pcf8574.stype); + } + + pcf8574_address++; +#ifdef USE_MCP230xx_ADDR + if (USE_MCP230xx_ADDR == pcf8574_address) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Addr: 0x%x reserved for MCP320xx, skipping PCF8574 probe"), pcf8574_address); + pcf8574_address++; + } +#endif + if ((PCF8574_ADDR1 +7) == pcf8574_address) { + pcf8574_address = PCF8574_ADDR2 +1; + } + } + if (Pcf8574.type) { + for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { + Pcf8574.pin[i] = 99; + } + devices_present = devices_present - Pcf8574.max_connected_ports; + Pcf8574.max_connected_ports = 0; + for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Device %d config 0x%02x"), idx +1, Settings.pcf8574_config[idx]); + + for (uint32_t i = 0; i < 8; i++) { + uint8_t _result = Settings.pcf8574_config[idx] >> i &1; + + if (_result > 0) { + Pcf8574.pin[devices_present] = i + 8 * idx; + bitWrite(rel_inverted, devices_present, Settings.flag3.pcf8574_ports_inverted); + devices_present++; + Pcf8574.max_connected_ports++; + } + } + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Total devices %d, PCF8574 output ports %d"), Pcf8574.max_devices, Pcf8574.max_connected_ports); + } +} + + + + + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_PCF8574 "pcf" + +const char HTTP_BTN_MENU_PCF8574[] PROGMEM = + "

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

" D_INVERT_PORTS "


"; + +const char HTTP_FORM_I2C_PCF8574_2[] PROGMEM = + "" D_DEVICE " %d " D_PORT " %d"; + +void HandlePcf8574(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_PCF8574)); + + if (WebServer->hasArg("save")) { + Pcf8574SaveSettings(); + WebRestart(1); + return; + } + + WSContentStart_P(D_CONFIGURE_PCF8574); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? " checked" : ""); + WSContentSend_P(HTTP_TABLE100); + for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { + for (uint32_t idx2 = 0; idx2 < 8; idx2++) { + uint8_t helper = 1 << idx2; + WSContentSend_P(HTTP_FORM_I2C_PCF8574_2, + idx +1, idx2, + idx2 + 8*idx, + idx2 + 8*idx, + ((helper & Settings.pcf8574_config[idx]) >> idx2 == 0) ? " selected " : " ", + ((helper & Settings.pcf8574_config[idx]) >> idx2 == 1) ? " selected " : " " + ); + } + } + WSContentSend_P(PSTR("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void Pcf8574SaveSettings(void) +{ + char stemp[7]; + char tmp[100]; + + + + Settings.flag3.pcf8574_ports_inverted = WebServer->hasArg("b1"); + for (byte idx = 0; idx < Pcf8574.max_devices; idx++) { + byte count=0; + byte n = Settings.pcf8574_config[idx]; + while(n!=0) { + n = n&(n-1); + count++; + } + if (count <= devices_present) { + devices_present = devices_present - count; + } + for (byte i = 0; i < 8; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("i2cs%d"), i+8*idx); + WebGetArg(stemp, tmp, sizeof(tmp)); + byte _value = (!strlen(tmp)) ? 0 : atoi(tmp); + if (_value) { + Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] | 1 << i; + devices_present++; + Pcf8574.max_connected_ports++; + } else { + Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] & ~(1 << i ); + } + } + + + + } +} +#endif + + + + + +bool Xdrv28(uint8_t function) +{ + if (!I2cEnabled(XI2C_02)) { return false; } + + bool result = false; + + if (FUNC_PRE_INIT == function) { + Pcf8574Init(); + } + else if (Pcf8574.type) { + switch (function) { + case FUNC_SET_POWER: + Pcf8574SwitchRelay(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_PCF8574); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_PCF8574, HandlePcf8574); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_29_deepsleep.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_29_deepsleep.ino" +#ifdef USE_DEEPSLEEP +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_29_deepsleep.ino" +#define XDRV_29 29 + +#define D_PRFX_DEEPSLEEP "DeepSleep" +#define D_CMND_DEEPSLEEP_TIME "Time" + +const uint32_t DEEPSLEEP_MAX = 10 * 366 * 24 * 60 * 60; +const uint32_t DEEPSLEEP_MAX_CYCLE = 60 * 60; +const uint32_t DEEPSLEEP_MIN_TIME = 5; +const uint32_t DEEPSLEEP_START_COUNTDOWN = 4; + +const char kDeepsleepCommands[] PROGMEM = D_PRFX_DEEPSLEEP "|" + D_CMND_DEEPSLEEP_TIME ; + +void (* const DeepsleepCommand[])(void) PROGMEM = { + &CmndDeepsleepTime }; + +uint32_t deepsleep_sleeptime = 0; +uint8_t deepsleep_flag = 0; + +bool DeepSleepEnabled(void) +{ + if ((Settings.deepsleep < 10) || (Settings.deepsleep > DEEPSLEEP_MAX)) { + Settings.deepsleep = 0; + return false; + } + + if (pin[GPIO_DEEPSLEEP] < 99) { + pinMode(pin[GPIO_DEEPSLEEP], INPUT_PULLUP); + return (digitalRead(pin[GPIO_DEEPSLEEP])); + } + + return true; +} + +void DeepSleepReInit(void) +{ + if ((ResetReason() == REASON_DEEP_SLEEP_AWAKE) && DeepSleepEnabled()) { + if ((RtcSettings.ultradeepsleep > DEEPSLEEP_MAX_CYCLE) && (RtcSettings.ultradeepsleep < 1700000000)) { + + RtcSettings.ultradeepsleep = RtcSettings.ultradeepsleep - DEEPSLEEP_MAX_CYCLE; + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Remain DeepSleep %d"), RtcSettings.ultradeepsleep); + RtcSettingsSave(); + RtcRebootReset(); + ESP.deepSleep(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep), WAKE_RF_DEFAULT); + yield(); + + } + } + + RtcSettings.ultradeepsleep = 0; +} + +void DeepSleepPrepare(void) +{ + + + + + if ((RtcSettings.nextwakeup == 0) || + (RtcSettings.deepsleep_slip < 9000) || + (RtcSettings.deepsleep_slip > 11000) || + (RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip ); + RtcSettings.nextwakeup = 0; + RtcSettings.deepsleep_slip = 10000; + } + + + + int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - UtcTime()) * 10; + + + + timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; + if (timeslip) { + RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5); + + RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); + RtcSettings.nextwakeup += Settings.deepsleep; + } + + + + if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) { + + RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep; + } + + String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); + + + deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_CYCLE ,RtcSettings.nextwakeup - UtcTime()); + + + Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATUS)); + + + +} + +void DeepSleepStart(void) +{ + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Sleeping")); + + WifiShutdown(); + RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); + RtcSettingsSave(); + + ESP.deepSleep(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); + yield(); +} + +void DeepSleepEverySecond(void) +{ + if (!deepsleep_flag) { return; } + + if (DeepSleepEnabled()) { + if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { + SettingsSaveAll(); + DeepSleepPrepare(); + } + deepsleep_flag--; + if (deepsleep_flag <= 0) { + DeepSleepStart(); + } + } else { + deepsleep_flag = 0; + } +} + + + + + +void CmndDeepsleepTime(void) +{ + if ((0 == XdrvMailbox.payload) || + ((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < DEEPSLEEP_MAX))) { + Settings.deepsleep = XdrvMailbox.payload; + RtcSettings.nextwakeup = 0; + deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN; + if (deepsleep_flag) { + if (!Settings.tele_period) { + Settings.tele_period = TELE_PERIOD; + } + } + } + Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.deepsleep); +} + + + + + +bool Xdrv29(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_SECOND: + DeepSleepEverySecond(); + break; + case FUNC_AFTER_TELEPERIOD: + if (DeepSleepEnabled() && !deepsleep_flag && (Settings.tele_period == 10 || Settings.tele_period == 300 || UpTime() > Settings.tele_period)) { + deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kDeepsleepCommands, DeepsleepCommand); + break; + case FUNC_PRE_INIT: + DeepSleepReInit(); + break; + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" +#ifdef USE_LIGHT +#ifdef USE_EXS_DIMMER + + + + + + + +#define XDRV_30 30 + +#define EXS_GATE_1_ON 0x20 +#define EXS_GATE_1_OFF 0x21 +#define EXS_DIMM_1_ON 0x22 +#define EXS_DIMM_1_OFF 0x23 +#define EXS_DIMM_1_TBL 0x24 +#define EXS_DIMM_1_VAL 0x25 +#define EXS_GATE_2_ON 0x30 +#define EXS_GATE_2_OFF 0x31 +#define EXS_DIMM_2_ON 0x32 +#define EXS_DIMM_2_OFF 0x33 +#define EXS_DIMM_2_TBL 0x34 +#define EXS_DIMM_2_VAL 0x35 +#define EXS_GATES_ON 0x40 +#define EXS_GATES_OFF 0x41 +#define EXS_DIMMS_ON 0x50 +#define EXS_DIMMS_OFF 0x51 +#define EXS_CH_LOCK 0x60 +#define EXS_GET_VALUES 0xFA +#define EXS_WRITE_EE 0xFC +#define EXS_READ_EE 0xFD +#define EXS_GET_VERSION 0xFE +#define EXS_RESET 0xFF + +#define EXS_BUFFER_SIZE 256 +#define EXS_ACK_TIMEOUT 200 + +#include + +TasmotaSerial *ExsSerial = nullptr; + +typedef struct +{ + uint8_t on = 0; + uint8_t bright_tbl = 0; + uint8_t dimm = 0; + uint8_t impuls_start = 0; + uint32_t impuls_len = 0; +} CHANNEL; + +typedef struct +{ + uint8_t version_major = 0; + uint8_t version_minor = 0; + CHANNEL channel[2]; + uint8_t gate_lock = 0; +} DIMMER; + +struct EXS +{ + uint8_t *buffer = nullptr; + int byte_counter = 0; + int cmd_status = 0; + uint8_t power = 0; + uint8_t dimm[2] = {0, 0}; + DIMMER dimmer; +} Exs; + + + + + +uint8_t crc8(const uint8_t *p, uint8_t len) +{ + const uint8_t table[] = { + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D}; + + const uint8_t table_rev[] = { + 0x00, 0x70, 0xE0, 0x90, 0xC1, 0xB1, 0x21, 0x51, + 0x83, 0xF3, 0x63, 0x13, 0x42, 0x32, 0xA2, 0xD2}; + + uint8_t offset; + uint8_t temp, crc8_temp; + uint8_t crc8 = 0; + + for (int i = 0; i < len; i++) + { + temp = *(p + i); + offset = temp ^ crc8; + offset >>= 4; + crc8_temp = crc8 & 0x0f; + crc8 = crc8_temp ^ table_rev[offset]; + offset = crc8 ^ temp; + offset &= 0x0f; + crc8_temp = crc8 & 0xf0; + crc8 = crc8_temp ^ table[offset]; + } + return crc8 ^ 0x55; +} + +void ExsSerialSend(const uint8_t data[] = nullptr, uint16_t len = 0) +{ + int retries = 3; + char rc; + +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: Tx Packet: \"")); + for (uint32_t i = 0; i < len; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, data[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + while (retries) + { + retries--; + + ExsSerial->write(data, len); + ExsSerial->flush(); + + + uint32_t snd_time = millis(); + while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && + (!ExsSerial->available())) + ; + + if (!ExsSerial->available()) + { + +#ifdef EXS_DEBUG + AddLog_P(LOG_LEVEL_DEBUG, PSTR("ESX: serial send timeout")); +#endif + continue; + } + + rc = ExsSerial->read(); + if (rc == 0xFF) + break; + } +} + +void ExsSendCmd(uint8_t cmd, uint8_t value) +{ + uint8_t buffer[8]; + uint16_t len; + + buffer[0] = 0x7b; + buffer[3] = cmd; + + switch (cmd) + { + case EXS_GATE_1_ON: + case EXS_GATE_1_OFF: + case EXS_DIMM_1_ON: + case EXS_DIMM_1_OFF: + case EXS_GATE_2_ON: + case EXS_GATE_2_OFF: + case EXS_DIMM_2_ON: + case EXS_DIMM_2_OFF: + case EXS_GATES_ON: + case EXS_GATES_OFF: + case EXS_DIMMS_ON: + case EXS_DIMMS_OFF: + case EXS_GET_VALUES: + case EXS_GET_VERSION: + case EXS_RESET: + buffer[2] = 1; + len = 4; + break; + + case EXS_CH_LOCK: + case EXS_DIMM_1_TBL: + case EXS_DIMM_1_VAL: + case EXS_DIMM_2_TBL: + case EXS_DIMM_2_VAL: + buffer[2] = 2; + buffer[4] = value; + len = 5; + break; + } + buffer[1] = crc8(&buffer[3], buffer[2]); + + ExsSerialSend(buffer, len); +} + +uint8_t ExsSetPower(uint8_t device, uint8_t power) +{ + Exs.dimmer.channel[device].dimm = power; + ExsSendCmd(EXS_DIMM_1_ON + 0x10 * device + power ^ 1, 0); +} + +uint8_t ExsSetBri(uint8_t device, uint8_t bri) +{ + Exs.dimmer.channel[device].bright_tbl = bri; + ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * device, bri); +} + +uint8_t ExsSyncState(uint8_t device) +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Channel %d Power Want %d, Is %d"), + device, bitRead(Exs.power, device), Exs.dimmer.channel[device].dimm); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Set Channel %d Brightness Want %d, Is %d"), + device, Exs.dimm[device], Exs.dimmer.channel[device].bright_tbl); +#endif + + if (bitRead(Exs.power, device) && + Exs.dimm[device] != Exs.dimmer.channel[device].bright_tbl) { + ExsSetBri(device, Exs.dimm[device]); + } + + if (!Exs.dimm[device]) { + Exs.dimmer.channel[device].dimm = 0; + } else if (Exs.dimmer.channel[device].dimm != bitRead(Exs.power, device)) { + ExsSetPower(device, bitRead(Exs.power, device)); + } +} + +bool ExsSyncState() +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Serial %p, Cmd %d"), ExsSerial, Exs.cmd_status); +#endif + + if (!ExsSerial || Exs.cmd_status != 0) + return false; + + ExsSyncState(0); + ExsSyncState(1); +} + +void ExsDebugState() +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: MCU v%d.%d, c0: On:%d,Dim:%d,Tbl:%d(%d%%), c1: On:%d,Dim:%d,Tbl:%d(%d%%), ChLock: %d"), + Exs.dimmer.version_major, Exs.dimmer.version_minor, + Exs.dimmer.channel[0].on, Exs.dimmer.channel[0].dimm, + Exs.dimmer.channel[0].bright_tbl, + changeUIntScale(Exs.dimmer.channel[0].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.channel[1].on, Exs.dimmer.channel[1].dimm, + Exs.dimmer.channel[1].bright_tbl, + changeUIntScale(Exs.dimmer.channel[1].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.gate_lock); +#endif +} + +void ExsPacketProcess(void) +{ + uint8_t len = Exs.buffer[1]; + uint8_t cmd = Exs.buffer[2]; + + switch (cmd) + { + case EXS_GET_VALUES: +# 294 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" + if (len > 9) + { + Exs.dimmer.version_major = Exs.buffer[3]; + Exs.dimmer.version_minor = Exs.buffer[4]; + + + Exs.dimmer.channel[0].on = Exs.buffer[6]; + Exs.dimmer.channel[0].dimm = Exs.buffer[6]; + Exs.dimmer.channel[0].bright_tbl = Exs.buffer[7]; + + + Exs.dimmer.channel[1].on = Exs.buffer[9]; + Exs.dimmer.channel[1].dimm = Exs.buffer[9]; + Exs.dimmer.channel[1].bright_tbl = Exs.buffer[10]; + + Exs.dimmer.gate_lock = Exs.buffer[11]; + } + else +# 327 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" + { + Exs.dimmer.version_major = 1; + Exs.dimmer.version_minor = 0; + + + Exs.dimmer.channel[0].on = Exs.buffer[4] - 48; + Exs.dimmer.channel[0].dimm = Exs.buffer[4] - 48; + Exs.dimmer.channel[0].bright_tbl = Exs.buffer[5] - 48; + + + Exs.dimmer.channel[1].on = Exs.buffer[7] - 48; + Exs.dimmer.channel[1].dimm = Exs.buffer[7] - 48; + Exs.dimmer.channel[1].bright_tbl = Exs.buffer[8] - 48; + + Exs.dimmer.gate_lock = Exs.buffer[9] - 48; + } + + ExsDebugState(); + ExsSyncState(); + ExsDebugState(); + break; + default: + break; + } +} + + + +bool ExsModuleSelected(void) +{ + Settings.light_correction = 0; + Settings.flag.mqtt_serial = 0; + Settings.flag3.pwm_multi_channels = 1; + SetSeriallog(LOG_LEVEL_NONE); + + devices_present = +2; + light_type = LT_SERIAL2; + return true; +} + +bool ExsSetChannels(void) +{ +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: SetChannels: \"")); + for (int i = 0; i < XdrvMailbox.data_len; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, ((uint8_t *)XdrvMailbox.data)[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + Exs.dimm[0] = ((uint8_t *)XdrvMailbox.data)[0]; + Exs.dimm[1] = ((uint8_t *)XdrvMailbox.data)[1]; + return ExsSyncState(); +} + +bool ExsSetPower(void) +{ + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Set Power, Device %d, Power 0x%02x"), + active_device, XdrvMailbox.index); + + Exs.power = XdrvMailbox.index; + return ExsSyncState(); +} + +void EsxMcuStart(void) +{ + int retries = 3; + +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Request MCU configuration, PIN %d to Low"), pin[GPIO_EXS_ENABLE]); +#endif + + pinMode(pin[GPIO_EXS_ENABLE], OUTPUT); + digitalWrite(pin[GPIO_EXS_ENABLE], LOW); + + delay(1); + + while (ExsSerial->available()) + { + + ExsSerial->read(); + } +} + +void ExsInit(void) +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Starting Tx %d Rx %d"), pin[GPIO_TXD], pin[GPIO_RXD]); +#endif + + Exs.buffer = (uint8_t *)malloc(EXS_BUFFER_SIZE); + if (Exs.buffer != nullptr) + { + ExsSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (ExsSerial->begin(9600)) + { + if (ExsSerial->hardwareSerial()) + { + ClaimSerial(); + } + ExsSerial->flush(); + EsxMcuStart(); + ExsSendCmd(EXS_CH_LOCK, 0); + ExsSendCmd(EXS_GET_VALUES, 0); + } + } +} + +void ExsSerialInput(void) +{ + while (ExsSerial->available()) + { + yield(); + uint8_t serial_in_byte = ExsSerial->read(); + + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Serial In Byte 0x%02x"), serial_in_byte); + + if (Exs.cmd_status == 0 && + serial_in_byte == 0x7B) + { + Exs.cmd_status = 1; + Exs.byte_counter = 0; + } + else if (Exs.byte_counter >= EXS_BUFFER_SIZE) + { + Exs.cmd_status = 0; + } + else if (Exs.cmd_status == 1) + { + Exs.buffer[Exs.byte_counter++] = serial_in_byte; + + if (Exs.byte_counter > 2 && Exs.byte_counter == Exs.buffer[1] + 2) + { + uint8_t crc = crc8(&Exs.buffer[2], Exs.buffer[1]); + + + Exs.cmd_status = 0; + +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: RX Packet: \"")); + for (uint32_t i = 0; i < Exs.byte_counter; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Exs.buffer[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\", CRC: 0x%02x"), log_data, crc); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + if (Exs.buffer[0] == crc) + { + ExsSerial->write(0xFF); + ExsPacketProcess(); + } + else + { + ExsSerial->write(0x00); + } + + } + } + } +} + + + + + +#ifdef EXS_MCU_CMNDS + +#define D_PRFX_EXS "Exs" +#define D_CMND_EXS_DIMM "Dimm" +#define D_CMND_EXS_DIMM_TBL "DimmTbl" +#define D_CMND_EXS_DIMM_VAL "DimmVal" +#define D_CMND_EXS_DIMMS "Dimms" +#define D_CMND_EXS_CH_LOCK "ChLock" +#define D_CMND_EXS_STATE "State" + +const char kExsCommands[] PROGMEM = D_PRFX_EXS "|" + D_CMND_EXS_DIMM "|" D_CMND_EXS_DIMM_TBL "|" D_CMND_EXS_DIMM_VAL "|" + D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" + D_CMND_EXS_STATE; + +void (* const ExsCommand[])(void) PROGMEM = { + &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, + &CmndExsDimms, &CmndExsChLock, + &CmndExsState }; + +void CmndExsDimm(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1)) { + ExsSendCmd(EXS_DIMM_1_ON + 0x10 * (XdrvMailbox.index - 1) + + XdrvMailbox.payload ^ 1, 0); + } + CmndExsState(); +} + +void CmndExsDimmTbl(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { + ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * (XdrvMailbox.index - 1), + XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsDimmVal(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { + ExsSendCmd(EXS_DIMM_1_VAL + 0x10 * (XdrvMailbox.index - 1), + XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsDimms(void) +{ + if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { + ExsSendCmd(EXS_DIMMS_ON + XdrvMailbox.payload ^ 1, 0); + } + CmndExsState(); +} + +void CmndExsChLock(void) +{ + if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { + ExsSendCmd(EXS_CH_LOCK, XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsState(void) +{ + ExsSendCmd(EXS_GET_VALUES, 0); + + + uint32_t snd_time = millis(); + while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && + (!ExsSerial->available())) + ; + ExsSerialInput(); + + Response_P(PSTR("{\"" D_CMND_EXS_STATE "\":{")); + ResponseAppend_P(PSTR("\"McuVersion\":\"%d.%d\"," + "\"Channels\":["), + Exs.dimmer.version_major, Exs.dimmer.version_minor); + + for (uint32_t i = 0; i < 2; i++) { + if (i != 0) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"On\":\"%d\"," + "\"BrightProz\":\"%d\"," + "\"BrightTab\":\"%d\"," + "\"Dimm\":\"%d\"}"), + Exs.dimmer.channel[i].on, + changeUIntScale(Exs.dimmer.channel[i].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.channel[i].bright_tbl, + Exs.dimmer.channel[i].dimm); + } + ResponseAppend_P(PSTR("],")); + ResponseAppend_P(PSTR("\"GateLock\":\"%d\""), Exs.dimmer.gate_lock); + ResponseJsonEndEnd(); +} + +#endif + + + + + +bool Xdrv30(uint8_t function) +{ + bool result = false; + + if (EXS_DIMMER == my_module_type) + { + switch (function) + { + case FUNC_LOOP: + if (ExsSerial) + ExsSerialInput(); + break; + case FUNC_MODULE_INIT: + result = ExsModuleSelected(); + break; + case FUNC_INIT: + ExsInit(); + break; + case FUNC_SET_DEVICE_POWER: + result = ExsSetPower(); + break; + case FUNC_SET_CHANNELS: + result = ExsSetChannels(); + break; +#ifdef EXS_MCU_CMNDS + case FUNC_COMMAND: + result = DecodeCommand(kExsCommands, ExsCommand); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_31_tasmota_slave.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_31_tasmota_slave.ino" +#ifdef USE_TASMOTA_SLAVE + + + + +#define XDRV_31 31 + +#define CONST_STK_CRC_EOP 0x20 + +#define CMND_STK_GET_SYNC 0x30 +#define CMND_STK_SET_DEVICE 0x42 +#define CMND_STK_SET_DEVICE_EXT 0x45 +#define CMND_STK_ENTER_PROGMODE 0x50 +#define CMND_STK_LEAVE_PROGMODE 0x51 +#define CMND_STK_LOAD_ADDRESS 0x55 +#define CMND_STK_PROG_PAGE 0x64 + + + + + +#define CMND_START 0xFC +#define CMND_END 0xFD + +#define CMND_FEATURES 0x01 +#define CMND_JSON 0x02 +#define CMND_FUNC_EVERY_SECOND 0x03 +#define CMND_FUNC_EVERY_100_MSECOND 0x04 +#define CMND_SLAVE_SEND 0x05 +#define CMND_PUBLISH_TELE 0x06 +#define CMND_EXECUTE_CMND 0x07 + +#define PARAM_DATA_START 0xFE +#define PARAM_DATA_END 0xFF + +#include + + + + + +class SimpleHexParse { + public: + SimpleHexParse(void); + uint8_t parseLine(char *hexline); + uint8_t ptr_l = 0; + uint8_t ptr_h = 0; + bool PageIsReady = false; + bool firstrun = true; + bool EndOfFile = false; + uint8_t FlashPage[128]; + uint8_t FlashPageIdx = 0; + uint8_t layoverBuffer[16]; + uint8_t layoverIdx = 0; + uint8_t getByte(char *hexline, uint8_t idx); +}; + +SimpleHexParse::SimpleHexParse(void) +{ + +} + +uint8_t SimpleHexParse::parseLine(char *hexline) +{ + if (layoverIdx) { + memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx); + FlashPageIdx = layoverIdx; + layoverIdx = 0; + } + uint8_t len = getByte(hexline, 1); + uint8_t addr_h = getByte(hexline, 2); + uint8_t addr_l = getByte(hexline, 3); + uint8_t rectype = getByte(hexline, 4); + for (uint8_t idx = 0; idx < len; idx++) { + if (FlashPageIdx < 128) { + FlashPage[FlashPageIdx] = getByte(hexline, idx+5); + FlashPageIdx++; + } else { + layoverBuffer[layoverIdx] = getByte(hexline, idx+5); + layoverIdx++; + } + } + if (1 == rectype) { + EndOfFile = true; + while (FlashPageIdx < 128) { + FlashPage[FlashPageIdx] = 0xFF; + FlashPageIdx++; + } + } + if (FlashPageIdx == 128) { + if (firstrun) { + firstrun = false; + } else { + ptr_l += 0x40; + if (ptr_l == 0) { + ptr_l = 0; + ptr_h++; + } + } + firstrun = false; + PageIsReady = true; + } + return 0; +} + +uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) +{ + char buff[3]; + buff[3] = '\0'; + memcpy(&buff, &hexline[(idx*2)-1], 2); + return strtol(buff, 0, 16); +} + + + + + +struct TSLAVE { + uint32_t spi_hex_size = 0; + uint32_t spi_sector_counter = 0; + uint8_t spi_sector_cursor = 0; + uint8_t inverted = LOW; + bool type = false; + bool flashing = false; + bool SerialEnabled = false; + uint8_t waitstate = 0; + bool unsupported = false; +} TSlave; + +typedef union { + uint32_t data; + struct { + uint32_t func_json_append : 1; + uint32_t func_every_second : 1; + uint32_t func_every_100_msecond : 1; + uint32_t func_slave_send : 1; + uint32_t spare4 : 1; + uint32_t spare5 : 1; + uint32_t spare6 : 1; + uint32_t spare7 : 1; + uint32_t spare8 : 1; + uint32_t spare9 : 1; + uint32_t spare10 : 1; + uint32_t spare11 : 1; + uint32_t spare12 : 1; + uint32_t spare13 : 1; + uint32_t spare14 : 1; + uint32_t spare15 : 1; + uint32_t spare16 : 1; + uint32_t spare17 : 1; + uint32_t spare18 : 1; + uint32_t spare19 : 1; + uint32_t spare20 : 1; + uint32_t spare21 : 1; + uint32_t spare22 : 1; + uint32_t spare23 : 1; + uint32_t spare24 : 1; + uint32_t spare25 : 1; + uint32_t spare26 : 1; + uint32_t spare27 : 1; + uint32_t spare28 : 1; + uint32_t spare29 : 1; + uint32_t spare30 : 1; + uint32_t spare31 : 1; + }; +} TSlaveFeatureCfg; + + + + + + +struct TSLAVE_FEATURES { + uint32_t features_version; + TSlaveFeatureCfg features; +} TSlaveSettings; + +struct TSLAVE_COMMAND { + uint8_t command; + uint8_t parameter; + uint8_t unused2; + uint8_t unused3; +} TSlaveCommand; + +TasmotaSerial *TasmotaSlave_Serial; + +uint32_t TasmotaSlave_FlashStart(void) +{ + return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; +} + +uint8_t TasmotaSlave_UpdateInit(void) +{ + TSlave.spi_hex_size = 0; + TSlave.spi_sector_counter = TasmotaSlave_FlashStart(); + TSlave.spi_sector_cursor = 0; + return 0; +} + +void TasmotaSlave_Reset(void) +{ + if (TSlave.SerialEnabled) { + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); + delay(1); + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], TSlave.inverted); + delay(1); + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); + delay(5); + } +} + +uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout) +{ + int timer = 0; + while (timer < timeout) { + if (TasmotaSlave_Serial->available() >= dataCount) { + return 1; + } + delay(1); + timer++; + } + return 0; +} + +uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count) +{ + TasmotaSlave_Serial->write(bytes, count); + TasmotaSlave_waitForSerialData(2, 250); + uint8_t sync = TasmotaSlave_Serial->read(); + uint8_t ok = TasmotaSlave_Serial->read(); + if ((sync == 0x14) && (ok == 0x10)) { + return 1; + } + return 0; +} + +uint8_t TasmotaSlave_execCmd(uint8_t cmd) +{ + uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP }; + return TasmotaSlave_sendBytes(bytes, 2); +} + +uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count) +{ + uint8_t bytes[32]; + bytes[0] = cmd; + int i = 0; + while (i < count) { + bytes[i + 1] = params[i]; + i++; + } + bytes[i + 1] = CONST_STK_CRC_EOP; + return TasmotaSlave_sendBytes(bytes, i + 2); +} + +uint8_t TasmotaSlave_exitProgMode(void) +{ + return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); +} + +uint8_t TasmotaSlave_SetupFlash(void) +{ + uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; + uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00}; + TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_FLASH_SPEED); + if (TasmotaSlave_Serial->hardwareSerial()) { + ClaimSerial(); + } + + TasmotaSlave_Reset(); + + uint8_t timeout = 0; + uint8_t no_error = 0; + while (50 > timeout) { + if (TasmotaSlave_execCmd(CMND_STK_GET_SYNC)) { + timeout = 200; + no_error = 1; + } + timeout++; + delay(1); + } + if (no_error) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Found bootloader")); + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Bootloader could not be found")); + } + if (no_error) { + if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (1)")); + } + } + if (no_error) { + if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (2)")); + } + } + if (no_error) { + if (TasmotaSlave_execCmd(CMND_STK_ENTER_PROGMODE)) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Failed to put bootloader into programming mode")); + } + } + return no_error; +} + +uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo) +{ + uint8_t params[] = { adrLo, adrHi }; + return TasmotaSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); +} + +void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) +{ + uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; + TasmotaSlave_loadAddress(addr_h, addr_l); + TasmotaSlave_Serial->write(Header, 4); + for (int i = 0; i < 128; i++) { + TasmotaSlave_Serial->write(data[i]); + } + TasmotaSlave_Serial->write(CONST_STK_CRC_EOP); + TasmotaSlave_waitForSerialData(2, 250); + TasmotaSlave_Serial->read(); + TasmotaSlave_Serial->read(); +} + +void TasmotaSlave_Flash(void) +{ + bool reading = true; + uint32_t read = 0; + uint32_t processed = 0; + char thishexline[50]; + uint8_t position = 0; + char* flash_buffer; + + SimpleHexParse hexParse = SimpleHexParse(); + + if (!TasmotaSlave_SetupFlash()) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flashing aborted!")); + TSlave.flashing = false; + restart_flag = 2; + return; + } + + flash_buffer = new char[SPI_FLASH_SEC_SIZE]; + uint32_t flash_start = TasmotaSlave_FlashStart() * SPI_FLASH_SEC_SIZE; + while (reading) { + ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); + read = read + SPI_FLASH_SEC_SIZE; + if (read >= TSlave.spi_hex_size) { + reading = false; + } + for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) { + processed++; + if ((processed <= TSlave.spi_hex_size) && (!hexParse.EndOfFile)) { + if (':' == flash_buffer[ca]) { + position = 0; + } + if (0x0D == flash_buffer[ca]) { + thishexline[position] = 0; + hexParse.parseLine(thishexline); + if (hexParse.PageIsReady) { + TasmotaSlave_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage); + hexParse.PageIsReady = false; + hexParse.FlashPageIdx = 0; + } + } else { + if (0x0A != flash_buffer[ca]) { + thishexline[position] = flash_buffer[ca]; + position++; + } + } + } + } + } + TasmotaSlave_exitProgMode(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flash done!")); + TSlave.flashing = false; + restart_flag = 2; +} + +void TasmotaSlave_SetFlagFlashing(bool value) +{ + TSlave.flashing = value; +} + +bool TasmotaSlave_GetFlagFlashing(void) +{ + return TSlave.flashing; +} + +void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size) +{ + if (0 == TSlave.spi_sector_cursor) { + ESP.flashEraseSector(TSlave.spi_sector_counter); + } + TSlave.spi_sector_cursor++; + ESP.flashWrite((TSlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TSlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size); + TSlave.spi_hex_size = TSlave.spi_hex_size + size; + if (2 == TSlave.spi_sector_cursor) { + TSlave.spi_sector_cursor = 0; + TSlave.spi_sector_counter++; + } +} + +void TasmotaSlave_Init(void) +{ + if (TSlave.type) { + return; + } + if (10 > TSlave.waitstate) { + TSlave.waitstate++; + return; + } + if (!TSlave.SerialEnabled) { + if ((pin[GPIO_TASMOTASLAVE_RXD] < 99) && (pin[GPIO_TASMOTASLAVE_TXD] < 99) && + ((pin[GPIO_TASMOTASLAVE_RST] < 99) || (pin[GPIO_TASMOTASLAVE_RST_INV] < 99))) { + TasmotaSlave_Serial = new TasmotaSerial(pin[GPIO_TASMOTASLAVE_RXD], pin[GPIO_TASMOTASLAVE_TXD], 1, 0, 200); + if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) { + if (TasmotaSlave_Serial->hardwareSerial()) { + ClaimSerial(); + } + TasmotaSlave_Serial->setTimeout(50); + if (pin[GPIO_TASMOTASLAVE_RST_INV] < 99) { + pin[GPIO_TASMOTASLAVE_RST] = pin[GPIO_TASMOTASLAVE_RST_INV]; + pin[GPIO_TASMOTASLAVE_RST_INV] = 99; + TSlave.inverted = HIGH; + } + pinMode(pin[GPIO_TASMOTASLAVE_RST], OUTPUT); + TSlave.SerialEnabled = true; + TasmotaSlave_Reset(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Enabled")); + } + } + } + if (TSlave.SerialEnabled) { + TasmotaSlave_sendCmnd(CMND_FEATURES, 0); + char buffer[32]; + TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); + uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); + memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings)); + if (20191129 == TSlaveSettings.features_version) { + TSlave.type = true; + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version); + } else { + if ((!TSlave.unsupported) && (TSlaveSettings.features_version > 0)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u not supported!"), TSlaveSettings.features_version); + TSlave.unsupported = true; + } + } + } +} + +void TasmotaSlave_Show(void) +{ + if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { + char buffer[100]; + TasmotaSlave_sendCmnd(CMND_JSON, 0); + TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); + uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1); + buffer[len] = '\0'; + ResponseAppend_P(PSTR(",\"TasmotaSlave\":%s"), buffer); + } +} + +void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param) +{ + TSlaveCommand.command = cmnd; + TSlaveCommand.parameter = param; + char buffer[sizeof(TSlaveCommand)+2]; + buffer[0] = CMND_START; + memcpy(&buffer[1], &TSlaveCommand, sizeof(TSlaveCommand)); + buffer[sizeof(TSlaveCommand)+1] = CMND_END; + for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { + TasmotaSlave_Serial->write(buffer[ca]); + } +} + +#define D_PRFX_SLAVE "Slave" +#define D_CMND_SLAVE_RESET "Reset" +#define D_CMND_SLAVE_SEND "Send" + +const char kTasmotaSlaveCommands[] PROGMEM = D_PRFX_SLAVE "|" + D_CMND_SLAVE_RESET "|" D_CMND_SLAVE_SEND; + +void (* const TasmotaSlaveCommand[])(void) PROGMEM = { + &CmndTasmotaSlaveReset, &CmndTasmotaSlaveSend }; + +void CmndTasmotaSlaveReset(void) +{ + TasmotaSlave_Reset(); + TSlave.type = false; + TSlave.waitstate = 7; + TSlave.unsupported = false; + ResponseCmndDone(); +} + +void CmndTasmotaSlaveSend(void) +{ + if (0 < XdrvMailbox.data_len) { + TasmotaSlave_sendCmnd(CMND_SLAVE_SEND, XdrvMailbox.data_len); + TasmotaSlave_Serial->write(char(PARAM_DATA_START)); + for (uint8_t idx = 0; idx < XdrvMailbox.data_len; idx++) { + TasmotaSlave_Serial->write(XdrvMailbox.data[idx]); + } + TasmotaSlave_Serial->write(char(PARAM_DATA_END)); + } + ResponseCmndDone(); +} + +void TasmotaSlave_ProcessIn(void) +{ + uint8_t cmnd = TasmotaSlave_Serial->read(); + switch (cmnd) { + case CMND_START: + TasmotaSlave_waitForSerialData(sizeof(TSlaveCommand),50); + uint8_t buffer[sizeof(TSlaveCommand)]; + for (uint8_t idx = 0; idx < sizeof(TSlaveCommand); idx++) { + buffer[idx] = TasmotaSlave_Serial->read(); + } + TasmotaSlave_Serial->read(); + memcpy(&TSlaveCommand, &buffer, sizeof(TSlaveCommand)); + char inbuf[TSlaveCommand.parameter+1]; + TasmotaSlave_waitForSerialData(TSlaveCommand.parameter, 50); + TasmotaSlave_Serial->read(); + for (uint8_t idx = 0; idx < TSlaveCommand.parameter; idx++) { + inbuf[idx] = TasmotaSlave_Serial->read(); + } + TasmotaSlave_Serial->read(); + inbuf[TSlaveCommand.parameter] = '\0'; + + if (CMND_PUBLISH_TELE == TSlaveCommand.command) { + Response_P(PSTR("{\"TasmotaSlave\":")); + ResponseAppend_P("%s", inbuf); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + XdrvRulesProcess(); + } + if (CMND_EXECUTE_CMND == TSlaveCommand.command) { + ExecuteCommand(inbuf, SRC_IGNORE); + } + break; + default: + break; + } +} + + + + + + +bool Xdrv31(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_100_MSECOND: + if (TSlave.type) { + if (TasmotaSlave_Serial->available()) { + TasmotaSlave_ProcessIn(); + } + if (TSlaveSettings.features.func_every_100_msecond) { + TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0); + } + } + break; + case FUNC_EVERY_SECOND: + if ((TSlave.type) && (TSlaveSettings.features.func_every_second)) { + TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_SECOND, 0); + } + TasmotaSlave_Init(); + break; + case FUNC_JSON_APPEND: + if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { + TasmotaSlave_Show(); + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kTasmotaSlaveCommands, TasmotaSlaveCommand); + break; + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_32_hotplug.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_32_hotplug.ino" +#ifdef USE_HOTPLUG + + + + + + + +#define XDRV_32 32 + +const uint32_t HOTPLUG_MAX = 254; + +const char kHotPlugCommands[] PROGMEM = "|" + D_CMND_HOTPLUG; + +void (* const HotPlugCommand[])(void) PROGMEM = { + &CmndHotPlugTime }; + +struct { + + bool enabled = false; + uint8_t timeout = 0; +} Hotplug; + +void HotPlugInit(void) +{ + + if (Settings.hotplug_scan == 0xFF) { Settings.hotplug_scan = 0; } + if (Settings.hotplug_scan != 0) { + Hotplug.enabled = true; + Hotplug.timeout = 1; + } else + Hotplug.enabled = false; +} + +void HotPlugEverySecond(void) +{ + if (Hotplug.enabled) { + if (Hotplug.timeout == 0) { + XsnsCall(FUNC_HOTPLUG_SCAN); + Hotplug.timeout = Settings.hotplug_scan; + } + Hotplug.timeout--; + } +} + + + + + +void CmndHotPlugTime(void) +{ + if (XdrvMailbox.payload <= HOTPLUG_MAX) { + Settings.hotplug_scan = XdrvMailbox.payload; + HotPlugInit(); + } + ResponseCmndNumber(Settings.hotplug_scan); +} + + + + + +bool Xdrv32(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_SECOND: + HotPlugEverySecond(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kHotPlugCommands, HotPlugCommand); + break; + case FUNC_PRE_INIT: + HotPlugInit(); + break; + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_33_nrf24l01.ino" +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_33_nrf24l01.ino" +#ifdef USE_SPI +#ifdef USE_NRF24 + + + + + + + +#define XDRV_33 33 + +#define MOSI 13 +#define MISO 12 +#define SCK 14 + +#include +#include + +const char NRF24type[] PROGMEM = "NRF24"; + +const char HTTP_NRF24[] PROGMEM = + "{s}%sL01%c: " "{m}started{e}"; + +struct { + uint8_t chipType = 0; +} NRF24; + + + +RF24 NRF24radio; + +bool NRF24initRadio() +{ + NRF24radio.begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_DC]); + NRF24radio.powerUp(); + + if(NRF24radio.isChipConnected()){ + DEBUG_DRIVER_LOG(PSTR("NRF24 chip connected")); + return true; + } + DEBUG_DRIVER_LOG(PSTR("NRF24 chip NOT !!!! connected")); + return false; +} + +bool NRF24Detect(void) +{ + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_DC]<99)){ + SPI.pins(SCK,MOSI,MISO,-1); + if(NRF24initRadio()){ + NRF24.chipType = 32; + AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01 initialized")); + if(NRF24radio.isPVariant()){ + NRF24.chipType = 43; + AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01+ detected")); + } + return true; + } + } + return false; +} + + + + + +bool Xdrv33(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + result = NRF24Detect(); + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" +# 22 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" +#ifdef DEBUG_THEO +#ifndef USE_DEBUG_DRIVER +#define USE_DEBUG_DRIVER +#endif +#endif + +#ifdef USE_DEBUG_DRIVER + + + + + + +#define XDRV_99 99 + +#ifndef CPU_LOAD_CHECK +#define CPU_LOAD_CHECK 1 +#endif + + + + + +#define D_CMND_CFGDUMP "CfgDump" +#define D_CMND_CFGPEEK "CfgPeek" +#define D_CMND_CFGPOKE "CfgPoke" +#define D_CMND_CFGSHOW "CfgShow" +#define D_CMND_CFGXOR "CfgXor" +#define D_CMND_CPUCHECK "CpuChk" +#define D_CMND_EXCEPTION "Exception" +#define D_CMND_FLASHDUMP "FlashDump" +#define D_CMND_FLASHMODE "FlashMode" +#define D_CMND_FREEMEM "FreeMem" +#define D_CMND_HELP "Help" +#define D_CMND_RTCDUMP "RtcDump" +#define D_CMND_SETSENSOR "SetSensor" +#define D_CMND_I2CWRITE "I2CWrite" +#define D_CMND_I2CREAD "I2CRead" +#define D_CMND_I2CSTRETCH "I2CStretch" +#define D_CMND_I2CCLOCK "I2CClock" + +const char kDebugCommands[] PROGMEM = "|" + D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" +#ifdef USE_WEBSERVER + D_CMND_CFGXOR "|" +#endif + D_CMND_CPUCHECK "|" +#ifdef DEBUG_THEO + D_CMND_EXCEPTION "|" +#endif + D_CMND_FLASHDUMP "|" D_CMND_FLASHMODE "|" D_CMND_FREEMEM"|" D_CMND_HELP "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|" +#ifdef USE_I2C + D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK +#endif + ; + +void (* const DebugCommand[])(void) PROGMEM = { + &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, +#ifdef USE_WEBSERVER + &CmndCfgXor, +#endif + &CmndCpuCheck, +#ifdef DEBUG_THEO + &CmndException, +#endif + &CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor, +#ifdef USE_I2C + &CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock +#endif + }; + +uint32_t CPU_loops = 0; +uint32_t CPU_last_millis = 0; +uint32_t CPU_last_loop_time = 0; +uint8_t CPU_load_check = 0; +uint8_t CPU_show_freemem = 0; + + + +#ifdef DEBUG_THEO +void ExceptionTest(uint8_t type) +{ +# 145 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" + if (1 == type) { + char svalue[10]; + snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); + } +# 159 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" + if (2 == type) { + while(1) delay(1000); + } +} + +#endif + + + +void CpuLoadLoop(void) +{ + CPU_last_loop_time = millis(); + if (CPU_load_check && CPU_last_millis) { + CPU_loops ++; + if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { +#if defined(F_CPU) && (F_CPU == 160000000L) + int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); + CPU_loops = CPU_loops / CPU_load_check; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); +#else + int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); + CPU_loops = CPU_loops / CPU_load_check; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); +#endif + CPU_last_millis = CPU_last_loop_time; + CPU_loops = 0; + } + } +} + + + +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) + + + +extern "C" { +#include + extern cont_t g_cont; +} + +void DebugFreeMem(void) +{ + register uint32_t *sp asm("a1"); + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); +} + +#else + + + + +extern "C" { +#include + extern cont_t* g_pcont; +} + +void DebugFreeMem(void) +{ + register uint32_t *sp asm("a1"); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); +} + +#endif + + + +void DebugRtcDump(char* parms) +{ + #define CFG_COLS 16 + + uint16_t idx; + uint16_t maxrow; + uint16_t row; + uint16_t col; + char *p; +# 246 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" + uint8_t buffer[768]; + + system_rtc_mem_read(0, (uint32_t*)&buffer, sizeof(buffer)); + + maxrow = ((sizeof(buffer)+CFG_COLS)/CFG_COLS); + + uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; + uint16_t mrow = strtol(p, &p, 10); + + + + if (0 == mrow) { + mrow = 8; + } + if (srow > maxrow) { + srow = maxrow - mrow; + } + if (mrow < (maxrow - srow)) { + maxrow = srow + mrow; + } + + for (row = srow; row < maxrow; row++) { + idx = row * CFG_COLS; + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + for (col = 0; col < CFG_COLS; col++) { + if (!(col%4)) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (col = 0; col < CFG_COLS; col++) { + + + + snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); + AddLog(LOG_LEVEL_INFO); + } +} + + + +void DebugCfgDump(char* parms) +{ + #define CFG_COLS 16 + + uint16_t idx; + uint16_t maxrow; + uint16_t row; + uint16_t col; + char *p; + + uint8_t *buffer = (uint8_t *) &Settings; + maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); + + uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; + uint16_t mrow = strtol(p, &p, 10); + + + + if (0 == mrow) { + mrow = 8; + } + if (srow > maxrow) { + srow = maxrow - mrow; + } + if (mrow < (maxrow - srow)) { + maxrow = srow + mrow; + } + + for (row = srow; row < maxrow; row++) { + idx = row * CFG_COLS; + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + for (col = 0; col < CFG_COLS; col++) { + if (!(col%4)) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (col = 0; col < CFG_COLS; col++) { + + + + snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); + AddLog(LOG_LEVEL_INFO); + delay(1); + } +} + +void DebugCfgPeek(char* parms) +{ + char *p; + + uint16_t address = strtol(parms, &p, 16); + if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + address = (address >> 2) << 2; + + uint8_t *buffer = (uint8_t *) &Settings; + uint8_t data8 = buffer[address]; + uint16_t data16 = (buffer[address +1] << 8) + buffer[address]; + uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; + + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); + for (uint32_t i = 0; i < 4; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (uint32_t i = 0; i < 4; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); + AddLog(LOG_LEVEL_INFO); +} + +void DebugCfgPoke(char* parms) +{ + char *p; + + uint16_t address = strtol(parms, &p, 16); + if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + address = (address >> 2) << 2; + + uint32_t data = strtol(p, &p, 16); + + uint8_t *buffer = (uint8_t *) &Settings; + uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; + + uint8_t *nbuffer = (uint8_t *) &data; + for (uint32_t i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } + + uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; + + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); +} + +void SetFlashMode(uint8_t mode) +{ + uint8_t *_buffer; + uint32_t address; + + address = 0; + _buffer = new uint8_t[FLASH_SECTOR_SIZE]; + + if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { + if (_buffer[2] != mode) { + _buffer[2] = mode; + if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { + ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); + } + } + } + delete[] _buffer; +} + + + + + +void CmndHelp(void) +{ + AddLog_P(LOG_LEVEL_INFO, PSTR("HLP: "), kDebugCommands); + ResponseCmndDone(); +} + +void CmndRtcDump(void) +{ + DebugRtcDump(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgDump(void) +{ + DebugCfgDump(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgPeek(void) +{ + DebugCfgPeek(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgPoke(void) +{ + DebugCfgPoke(XdrvMailbox.data); + ResponseCmndDone(); +} + +#ifdef USE_WEBSERVER +void CmndCfgXor(void) +{ + if (XdrvMailbox.data_len > 0) { + Web.config_xor_on_set = XdrvMailbox.payload; + } + ResponseCmndNumber(Web.config_xor_on_set); +} +#endif + +#ifdef DEBUG_THEO +void CmndException(void) +{ + if (XdrvMailbox.data_len > 0) { ExceptionTest(XdrvMailbox.payload); } + ResponseCmndDone(); +} +#endif + +void CmndCpuCheck(void) +{ + if (XdrvMailbox.data_len > 0) { + CPU_load_check = XdrvMailbox.payload; + CPU_last_millis = CPU_last_loop_time; + } + ResponseCmndNumber(CPU_load_check); +} + +void CmndFreemem(void) +{ + if (XdrvMailbox.data_len > 0) { + CPU_show_freemem = XdrvMailbox.payload; + } + ResponseCmndNumber(CPU_show_freemem); +} + +void CmndSetSensor(void) +{ + if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { + if (XdrvMailbox.payload >= 0) { + bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); + if (1 == XdrvMailbox.payload) { + restart_flag = 2; + } + } + Response_P(PSTR("{\"" D_CMND_SETSENSOR "\":")); + XsnsSensorState(); + ResponseJsonEnd(); + } +} + +void CmndFlashMode(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + SetFlashMode(XdrvMailbox.payload); + } + ResponseCmndNumber(ESP.getFlashChipMode()); +} + +uint32_t DebugSwap32(uint32_t x) { + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} + +void CmndFlashDump(void) +{ + + + + const uint32_t flash_start = 0x40200000; + const uint8_t bytes_per_cols = 0x20; + const uint32_t max = (SPIFFS_END + 5) * SPI_FLASH_SEC_SIZE; + + uint32_t start = flash_start; + uint32_t rows = 8; + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= (max - bytes_per_cols))) { + start += (XdrvMailbox.payload &0x7FFFFFFC); + + char *p; + uint32_t is_payload = strtol(XdrvMailbox.data, &p, 16); + rows = strtol(p, &p, 10); + if (0 == rows) { rows = 8; } + } + uint32_t end = start + (rows * bytes_per_cols); + if ((end - flash_start) > max) { + end = flash_start + max; + } + + for (uint32_t pos = start; pos < end; pos += bytes_per_cols) { + uint32_t* values = (uint32_t*)(pos); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%06X: %08X %08X %08X %08X %08X %08X %08X %08X"), pos - flash_start, + DebugSwap32(values[0]), DebugSwap32(values[1]), DebugSwap32(values[2]), DebugSwap32(values[3]), + DebugSwap32(values[4]), DebugSwap32(values[5]), DebugSwap32(values[6]), DebugSwap32(values[7])); + } + ResponseCmndDone(); +} + +#ifdef USE_I2C +void CmndI2cWrite(void) +{ + + if (i2c_flg) { + char* parms = XdrvMailbox.data; + uint8_t buffer[100]; + uint32_t index = 0; + + char *p; + char *data = strtok_r(parms, " ,", &p); + while (data != NULL && index < sizeof(buffer)) { + buffer[index++] = strtol(data, nullptr, 16); + data = strtok_r(nullptr, " ,", &p); + } + + if (index > 1) { + AddLogBuffer(LOG_LEVEL_INFO, buffer, index); + + Wire.beginTransmission(buffer[0]); + for (uint32_t i = 1; i < index; i++) { + Wire.write(buffer[i]); + } + int result = Wire.endTransmission(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: Result %d"), result); + } + } + ResponseCmndDone(); +} + +void CmndI2cRead(void) +{ + + if (i2c_flg) { + char* parms = XdrvMailbox.data; + uint8_t buffer[100]; + uint32_t index = 0; + + char *p; + char *data = strtok_r(parms, " ,", &p); + while (data != NULL && index < sizeof(buffer)) { + buffer[index++] = strtol(data, nullptr, 16); + data = strtok_r(nullptr, " ,", &p); + } + + if (index > 0) { + uint8_t size = 1; + if (index > 1) { + size = buffer[1]; + } + Wire.requestFrom(buffer[0], size); + index = 0; + while (Wire.available() && index < sizeof(buffer)) { + buffer[index++] = Wire.read(); + } + if (index > 0) { + AddLogBuffer(LOG_LEVEL_INFO, buffer, index); + } + } + } + ResponseCmndDone(); +} + +void CmndI2cStretch(void) +{ + if (i2c_flg && (XdrvMailbox.payload > 0)) { + Wire.setClockStretchLimit(XdrvMailbox.payload); + } + ResponseCmndDone(); +} + +void CmndI2cClock(void) +{ + if (i2c_flg && (XdrvMailbox.payload > 0)) { + Wire.setClock(XdrvMailbox.payload); + } + ResponseCmndDone(); +} +#endif + + + + + +bool Xdrv99(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + CpuLoadLoop(); + break; + case FUNC_FREE_MEM: + if (CPU_show_freemem) { DebugFreeMem(); } + break; + case FUNC_PRE_INIT: + CPU_last_millis = millis(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kDebugCommands, DebugCommand); + break; + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_interface.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_interface.ino" +#ifdef XFUNC_PTR_IN_ROM +bool (* const xdrv_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xdrv_func_ptr[])(uint8_t) = { +#endif + +#ifdef XDRV_01 + &Xdrv01, +#endif + +#ifdef XDRV_02 + &Xdrv02, +#endif + +#ifdef XDRV_03 + &Xdrv03, +#endif + +#ifdef XDRV_04 + &Xdrv04, +#endif + +#ifdef XDRV_05 + &Xdrv05, +#endif + +#ifdef XDRV_06 + &Xdrv06, +#endif + +#ifdef XDRV_07 + &Xdrv07, +#endif + +#ifdef XDRV_08 + &Xdrv08, +#endif + +#ifdef XDRV_09 + &Xdrv09, +#endif + +#ifdef XDRV_10 + &Xdrv10, +#endif + +#ifdef XDRV_11 + &Xdrv11, +#endif + +#ifdef XDRV_12 + &Xdrv12, +#endif + +#ifdef XDRV_13 + &Xdrv13, +#endif + +#ifdef XDRV_14 + &Xdrv14, +#endif + +#ifdef XDRV_15 + &Xdrv15, +#endif + +#ifdef XDRV_16 + &Xdrv16, +#endif + +#ifdef XDRV_17 + &Xdrv17, +#endif + +#ifdef XDRV_18 + &Xdrv18, +#endif + +#ifdef XDRV_19 + &Xdrv19, +#endif + +#ifdef XDRV_20 + &Xdrv20, +#endif + +#ifdef XDRV_21 + &Xdrv21, +#endif + +#ifdef XDRV_22 + &Xdrv22, +#endif + +#ifdef XDRV_23 + &Xdrv23, +#endif + +#ifdef XDRV_24 + &Xdrv24, +#endif + +#ifdef XDRV_25 + &Xdrv25, +#endif + +#ifdef XDRV_26 + &Xdrv26, +#endif + +#ifdef XDRV_27 + &Xdrv27, +#endif + +#ifdef XDRV_28 + &Xdrv28, +#endif + +#ifdef XDRV_29 + &Xdrv29, +#endif + +#ifdef XDRV_30 + &Xdrv30, +#endif + +#ifdef XDRV_31 + &Xdrv31, +#endif + +#ifdef XDRV_32 + &Xdrv32, +#endif + +#ifdef XDRV_33 + &Xdrv33, +#endif + +#ifdef XDRV_34 + &Xdrv34, +#endif + +#ifdef XDRV_35 + &Xdrv35, +#endif + +#ifdef XDRV_36 + &Xdrv36, +#endif + +#ifdef XDRV_37 + &Xdrv37, +#endif + +#ifdef XDRV_38 + &Xdrv38, +#endif + +#ifdef XDRV_39 + &Xdrv39, +#endif + +#ifdef XDRV_40 + &Xdrv40, +#endif + +#ifdef XDRV_41 + &Xdrv41, +#endif + +#ifdef XDRV_42 + &Xdrv42, +#endif + +#ifdef XDRV_43 + &Xdrv43, +#endif + +#ifdef XDRV_44 + &Xdrv44, +#endif + +#ifdef XDRV_45 + &Xdrv45, +#endif + +#ifdef XDRV_46 + &Xdrv46, +#endif + +#ifdef XDRV_47 + &Xdrv47, +#endif + +#ifdef XDRV_48 + &Xdrv48, +#endif + +#ifdef XDRV_49 + &Xdrv49, +#endif + +#ifdef XDRV_50 + &Xdrv50, +#endif + +#ifdef XDRV_51 + &Xdrv51, +#endif + +#ifdef XDRV_52 + &Xdrv52, +#endif + +#ifdef XDRV_53 + &Xdrv53, +#endif + +#ifdef XDRV_54 + &Xdrv54, +#endif + +#ifdef XDRV_55 + &Xdrv55, +#endif + +#ifdef XDRV_56 + &Xdrv56, +#endif + +#ifdef XDRV_57 + &Xdrv57, +#endif + +#ifdef XDRV_58 + &Xdrv58, +#endif + +#ifdef XDRV_59 + &Xdrv59, +#endif + +#ifdef XDRV_60 + &Xdrv60, +#endif + +#ifdef XDRV_61 + &Xdrv61, +#endif + +#ifdef XDRV_62 + &Xdrv62, +#endif + +#ifdef XDRV_63 + &Xdrv63, +#endif + +#ifdef XDRV_64 + &Xdrv64, +#endif + +#ifdef XDRV_65 + &Xdrv65, +#endif + +#ifdef XDRV_66 + &Xdrv66, +#endif + +#ifdef XDRV_67 + &Xdrv67, +#endif + +#ifdef XDRV_68 + &Xdrv68, +#endif + +#ifdef XDRV_69 + &Xdrv69, +#endif + +#ifdef XDRV_70 + &Xdrv70, +#endif + +#ifdef XDRV_71 + &Xdrv71, +#endif + +#ifdef XDRV_72 + &Xdrv72, +#endif + +#ifdef XDRV_73 + &Xdrv73, +#endif + +#ifdef XDRV_74 + &Xdrv74, +#endif + +#ifdef XDRV_75 + &Xdrv75, +#endif + +#ifdef XDRV_76 + &Xdrv76, +#endif + +#ifdef XDRV_77 + &Xdrv77, +#endif + +#ifdef XDRV_78 + &Xdrv78, +#endif + +#ifdef XDRV_79 + &Xdrv79, +#endif + +#ifdef XDRV_80 + &Xdrv80, +#endif + +#ifdef XDRV_81 + &Xdrv81, +#endif + +#ifdef XDRV_82 + &Xdrv82, +#endif + +#ifdef XDRV_83 + &Xdrv83, +#endif + +#ifdef XDRV_84 + &Xdrv84, +#endif + +#ifdef XDRV_85 + &Xdrv85, +#endif + +#ifdef XDRV_86 + &Xdrv86, +#endif + +#ifdef XDRV_87 + &Xdrv87, +#endif + +#ifdef XDRV_88 + &Xdrv88, +#endif + +#ifdef XDRV_89 + &Xdrv89, +#endif + +#ifdef XDRV_90 + &Xdrv90, +#endif + +#ifdef XDRV_91 + &Xdrv91, +#endif + +#ifdef XDRV_92 + &Xdrv92, +#endif + +#ifdef XDRV_93 + &Xdrv93, +#endif + +#ifdef XDRV_94 + &Xdrv94, +#endif + +#ifdef XDRV_95 + &Xdrv95, +#endif + +#ifdef XDRV_96 + &Xdrv96, +#endif + +#ifdef XDRV_97 + &Xdrv97, +#endif + +#ifdef XDRV_98 + &Xdrv98, +#endif + +#ifdef XDRV_99 + &Xdrv99 +#endif +}; + +const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); + + + + + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXdrvList[] PROGMEM = { +#else +const uint8_t kXdrvList[] = { +#endif + +#ifdef XDRV_01 + XDRV_01, +#endif + +#ifdef XDRV_02 + XDRV_02, +#endif + +#ifdef XDRV_03 + XDRV_03, +#endif + +#ifdef XDRV_04 + XDRV_04, +#endif + +#ifdef XDRV_05 + XDRV_05, +#endif + +#ifdef XDRV_06 + XDRV_06, +#endif + +#ifdef XDRV_07 + XDRV_07, +#endif + +#ifdef XDRV_08 + XDRV_08, +#endif + +#ifdef XDRV_09 + XDRV_09, +#endif + +#ifdef XDRV_10 + XDRV_10, +#endif + +#ifdef XDRV_11 + XDRV_11, +#endif + +#ifdef XDRV_12 + XDRV_12, +#endif + +#ifdef XDRV_13 + XDRV_13, +#endif + +#ifdef XDRV_14 + XDRV_14, +#endif + +#ifdef XDRV_15 + XDRV_15, +#endif + +#ifdef XDRV_16 + XDRV_16, +#endif + +#ifdef XDRV_17 + XDRV_17, +#endif + +#ifdef XDRV_18 + XDRV_18, +#endif + +#ifdef XDRV_19 + XDRV_19, +#endif + +#ifdef XDRV_20 + XDRV_20, +#endif + +#ifdef XDRV_21 + XDRV_21, +#endif + +#ifdef XDRV_22 + XDRV_22, +#endif + +#ifdef XDRV_23 + XDRV_23, +#endif + +#ifdef XDRV_24 + XDRV_24, +#endif + +#ifdef XDRV_25 + XDRV_25, +#endif + +#ifdef XDRV_26 + XDRV_26, +#endif + +#ifdef XDRV_27 + XDRV_27, +#endif + +#ifdef XDRV_28 + XDRV_28, +#endif + +#ifdef XDRV_29 + XDRV_29, +#endif + +#ifdef XDRV_30 + XDRV_30, +#endif + +#ifdef XDRV_31 + XDRV_31, +#endif + +#ifdef XDRV_32 + XDRV_32, +#endif + +#ifdef XDRV_33 + XDRV_33, +#endif + +#ifdef XDRV_34 + XDRV_34, +#endif + +#ifdef XDRV_35 + XDRV_35, +#endif + +#ifdef XDRV_36 + XDRV_36, +#endif + +#ifdef XDRV_37 + XDRV_37, +#endif + +#ifdef XDRV_38 + XDRV_38, +#endif + +#ifdef XDRV_39 + XDRV_39, +#endif + +#ifdef XDRV_40 + XDRV_40, +#endif + +#ifdef XDRV_41 + XDRV_41, +#endif + +#ifdef XDRV_42 + XDRV_42, +#endif + +#ifdef XDRV_43 + XDRV_43, +#endif + +#ifdef XDRV_44 + XDRV_44, +#endif + +#ifdef XDRV_45 + XDRV_45, +#endif + +#ifdef XDRV_46 + XDRV_46, +#endif + +#ifdef XDRV_47 + XDRV_47, +#endif + +#ifdef XDRV_48 + XDRV_48, +#endif + +#ifdef XDRV_49 + XDRV_49, +#endif + +#ifdef XDRV_50 + XDRV_50, +#endif + +#ifdef XDRV_51 + XDRV_51, +#endif + +#ifdef XDRV_52 + XDRV_52, +#endif + +#ifdef XDRV_53 + XDRV_53, +#endif + +#ifdef XDRV_54 + XDRV_54, +#endif + +#ifdef XDRV_55 + XDRV_55, +#endif + +#ifdef XDRV_56 + XDRV_56, +#endif + +#ifdef XDRV_57 + XDRV_57, +#endif + +#ifdef XDRV_58 + XDRV_58, +#endif + +#ifdef XDRV_59 + XDRV_59, +#endif + +#ifdef XDRV_60 + XDRV_60, +#endif + +#ifdef XDRV_61 + XDRV_61, +#endif + +#ifdef XDRV_62 + XDRV_62, +#endif + +#ifdef XDRV_63 + XDRV_63, +#endif + +#ifdef XDRV_64 + XDRV_64, +#endif + +#ifdef XDRV_65 + XDRV_65, +#endif + +#ifdef XDRV_66 + XDRV_66, +#endif + +#ifdef XDRV_67 + XDRV_67, +#endif + +#ifdef XDRV_68 + XDRV_68, +#endif + +#ifdef XDRV_69 + XDRV_69, +#endif + +#ifdef XDRV_70 + XDRV_70, +#endif + +#ifdef XDRV_71 + XDRV_71, +#endif + +#ifdef XDRV_72 + XDRV_72, +#endif + +#ifdef XDRV_73 + XDRV_73, +#endif + +#ifdef XDRV_74 + XDRV_74, +#endif + +#ifdef XDRV_75 + XDRV_75, +#endif + +#ifdef XDRV_76 + XDRV_76, +#endif + +#ifdef XDRV_77 + XDRV_77, +#endif + +#ifdef XDRV_78 + XDRV_78, +#endif + +#ifdef XDRV_79 + XDRV_79, +#endif + +#ifdef XDRV_80 + XDRV_80, +#endif + +#ifdef XDRV_81 + XDRV_81, +#endif + +#ifdef XDRV_82 + XDRV_82, +#endif + +#ifdef XDRV_83 + XDRV_83, +#endif + +#ifdef XDRV_84 + XDRV_84, +#endif + +#ifdef XDRV_85 + XDRV_85, +#endif + +#ifdef XDRV_86 + XDRV_86, +#endif + +#ifdef XDRV_87 + XDRV_87, +#endif + +#ifdef XDRV_88 + XDRV_88, +#endif + +#ifdef XDRV_89 + XDRV_89, +#endif + +#ifdef XDRV_90 + XDRV_90, +#endif + +#ifdef XDRV_91 + XDRV_91, +#endif + +#ifdef XDRV_92 + XDRV_92, +#endif + +#ifdef XDRV_93 + XDRV_93, +#endif + +#ifdef XDRV_94 + XDRV_94, +#endif + +#ifdef XDRV_95 + XDRV_95, +#endif + +#ifdef XDRV_96 + XDRV_96, +#endif + +#ifdef XDRV_97 + XDRV_97, +#endif + +#ifdef XDRV_98 + XDRV_98, +#endif + +#ifdef XDRV_99 + XDRV_99 +#endif +}; + + + +void XsnsDriverState(void) +{ + ResponseAppend_P(PSTR(",\"Drivers\":\"")); + for (uint32_t i = 0; i < sizeof(kXdrvList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t driverid = pgm_read_byte(kXdrvList + i); +#else + uint32_t driverid = kXdrvList[i]; +#endif + ResponseAppend_P(PSTR("%s%d"), (i) ? "," : "", driverid); + } + ResponseAppend_P(PSTR("\"")); +} + + + +bool XdrvRulesProcess(void) +{ + return XdrvCallDriver(10, FUNC_RULES_PROCESS); +} + +#ifdef USE_DEBUG_DRIVER +void ShowFreeMem(const char *where) +{ + char stemp[30]; + snprintf_P(stemp, sizeof(stemp), where); + XdrvMailbox.data = stemp; + XdrvCall(FUNC_FREE_MEM); +} +#endif + + + + + +bool XdrvCallDriver(uint32_t driver, uint8_t Function) +{ + for (uint32_t x = 0; x < xdrv_present; x++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t listed = pgm_read_byte(kXdrvList + x); +#else + uint32_t listed = kXdrvList[x]; +#endif + if (driver == listed) { + return xdrv_func_ptr[x](Function); + } + } + return false; +} + + + + + +bool XdrvCall(uint8_t Function) +{ + bool result = false; + + DEBUG_TRACE_LOG(PSTR("DRV: %d"), Function); + + for (uint32_t x = 0; x < xdrv_present; x++) { + result = xdrv_func_ptr[x](Function); + + if (result && ((FUNC_COMMAND == Function) || + (FUNC_COMMAND_DRIVER == Function) || + (FUNC_MQTT_DATA == Function) || + (FUNC_RULES_PROCESS == Function) || + (FUNC_BUTTON_PRESSED == Function) || + (FUNC_SERIAL == Function) || + (FUNC_MODULE_INIT == Function) || + (FUNC_SET_CHANNELS == Function) || + (FUNC_PIN_STATE == Function) || + (FUNC_SET_DEVICE_POWER == Function) + )) { + break; + } + } + + return result; +} +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_01_lcd.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_01_lcd.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_LCD + +#define XDSP_01 1 +#define XI2C_03 3 + +#define LCD_ADDRESS1 0x27 +#define LCD_ADDRESS2 0x3F + +#include +#include + +LiquidCrystal_I2C *lcd; + + + +void LcdInitMode(void) +{ + lcd->init(); + lcd->clear(); +} + +void LcdInit(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + LcdInitMode(); +#ifdef USE_DISPLAY_MODES1TO5 + DisplayClearScreenBuffer(); +#endif + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void LcdInitDriver(void) +{ + if (!Settings.display_model) { + if (I2cSetDevice(LCD_ADDRESS1)) { + Settings.display_address[0] = LCD_ADDRESS1; + Settings.display_model = XDSP_01; + } + else if (I2cSetDevice(LCD_ADDRESS2)) { + Settings.display_address[0] = LCD_ADDRESS2; + Settings.display_model = XDSP_01; + } + } + + if (XDSP_01 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "LCD"); + + Settings.display_width = Settings.display_cols[0]; + Settings.display_height = Settings.display_rows; + lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows); + +#ifdef USE_DISPLAY_MODES1TO5 + DisplayAllocScreenBuffer(); +#endif + + LcdInitMode(); + } +} + +void LcdDrawStringAt(void) +{ + if (dsp_flag) { + dsp_x--; + dsp_y--; + } + lcd->setCursor(dsp_x, dsp_y); + lcd->print(dsp_str); +} + +void LcdDisplayOnOff(uint8_t on) +{ + if (on) { + lcd->backlight(); + } else { + lcd->noBacklight(); + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void LcdCenter(uint8_t row, char* txt) +{ + char line[Settings.display_cols[0] +2]; + + int len = strlen(txt); + int offset = 0; + if (len >= Settings.display_cols[0]) { + len = Settings.display_cols[0]; + } else { + offset = (Settings.display_cols[0] - len) / 2; + } + memset(line, 0x20, Settings.display_cols[0]); + line[Settings.display_cols[0]] = 0; + for (uint32_t i = 0; i < len; i++) { + line[offset +i] = txt[i]; + } + lcd->setCursor(0, row); + lcd->print(line); +} + +bool LcdPrintLog(void) +{ + bool result = false; + + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\337'); + if (txt != nullptr) { + uint8_t last_row = Settings.display_rows -1; + + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + lcd->setCursor(0, i); + lcd->print(disp_screen_buffer[i +1]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + lcd->setCursor(0, last_row); + lcd->print(disp_screen_buffer[last_row]); + + result = true; + } + } + return result; +} + +void LcdTime(void) +{ + char line[Settings.display_cols[0] +1]; + + snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + LcdCenter(0, line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + LcdCenter(1, line); +} + +void LcdRefresh(void) +{ + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + LcdTime(); + break; + case 2: + case 4: + LcdPrintLog(); + break; + case 3: + case 5: { + if (!LcdPrintLog()) { LcdTime(); } + break; + } + } + } +} + +#endif + + + + + +bool Xdsp01(uint8_t function) +{ + if (!I2cEnabled(XI2C_03)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + LcdInitDriver(); + } + else if (XDSP_01 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + LcdInit(dsp_init); + break; + case FUNC_DISPLAY_POWER: + LcdDisplayOnOff(disp_power); + break; + case FUNC_DISPLAY_CLEAR: + lcd->clear(); + break; +# 238 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_01_lcd.ino" + case FUNC_DISPLAY_DRAW_STRING: + LcdDrawStringAt(); + break; + case FUNC_DISPLAY_ONOFF: + LcdDisplayOnOff(dsp_on); + break; + + +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + LcdRefresh(); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_02_ssd1306.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_02_ssd1306.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SSD1306 + +#define XDSP_02 2 +#define XI2C_04 4 + +#define OLED_RESET 4 + +#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); + +#define OLED_ADDRESS1 0x3C +#define OLED_ADDRESS2 0x3D + +#define OLED_BUFFER_COLS 40 +#define OLED_BUFFER_ROWS 16 + +#define OLED_FONT_WIDTH 6 +#define OLED_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_SSD1306 *oled1306; + +extern uint8_t *buffer; + + + +void SSD1306InitDriver(void) +{ + if (!Settings.display_model) { + if (I2cSetDevice(OLED_ADDRESS1)) { + Settings.display_address[0] = OLED_ADDRESS1; + Settings.display_model = XDSP_02; + } + else if (I2cSetDevice(OLED_ADDRESS2)) { + Settings.display_address[0] = OLED_ADDRESS2; + Settings.display_model = XDSP_02; + } + } + + if (XDSP_02 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "SSD1306"); + + if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) { + Settings.display_width = 128; + } + if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 48) && (Settings.display_height != 64)) { + Settings.display_height = 64; + } + + uint8_t reset_pin = -1; + if (pin[GPIO_OLED_RESET] < 99) { + reset_pin = pin[GPIO_OLED_RESET]; + } + + + if (buffer) { free(buffer); } + buffer = (unsigned char*)calloc((Settings.display_width * Settings.display_height) / 8,1); + if (!buffer) { return; } + + + + oled1306 = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, reset_pin); + oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], reset_pin >= 0); + renderer = oled1306; + renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + renderer->setTextFont(0); + renderer->setTextSize(2); + renderer->setCursor(20,20); + renderer->println(F("SSD1306")); + renderer->Updateframe(); + renderer->DisplayOnff(1); +#endif + + } +} + + +#ifdef USE_DISPLAY_MODES1TO5 + +void Ssd1306PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void Ssd1306Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setTextFont(Settings.display_font); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void Ssd1306Refresh(void) +{ + if (!renderer) return; + + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + Ssd1306Time(); + break; + case 2: + case 3: + case 4: + case 5: + Ssd1306PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp02(byte function) +{ + if (!I2cEnabled(XI2C_04)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SSD1306InitDriver(); + } + else if (XDSP_02 == Settings.display_model) { + switch (function) { +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + Ssd1306Refresh(); + break; +#endif + case FUNC_DISPLAY_MODEL: + result = true; + break; + } + } + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_03_matrix.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_03_matrix.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_MATRIX + +#define XDSP_03 3 +#define XI2C_05 5 + +#define MTX_MAX_SCREEN_BUFFER 80 + +#include +#include +#include + +Adafruit_8x8matrix *matrix[8]; +uint8_t mtx_matrices = 0; +uint8_t mtx_state = 0; +uint8_t mtx_counter = 0; +int16_t mtx_x = 0; +int16_t mtx_y = 0; + + +char *mtx_buffer = nullptr; + +uint8_t mtx_mode = 0; +uint8_t mtx_loop = 0; +uint8_t mtx_done = 0; + + + +void MatrixWrite(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->writeDisplay(); + } +} + +void MatrixClear(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + } + MatrixWrite(); +} + +void MatrixFixed(char* txt) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(-i *8, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); +} + +void MatrixCenter(char* txt) +{ + int offset; + + int len = strlen(txt); + offset = (len < 8) ? offset = ((mtx_matrices *8) - (len *6)) / 2 : 0; + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(-(i *8)+offset, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); +} + +void MatrixScrollLeft(char* txt, int loop) +{ + switch (mtx_state) { + case 1: + mtx_state = 2; + + mtx_x = 8 * mtx_matrices; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), txt); + + disp_refresh = Settings.display_refresh; + case 2: + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(mtx_x - i *8, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); + + mtx_x--; + int16_t len = strlen(txt); + if (mtx_x < -(len *6)) { mtx_state = loop; } + } + break; + } +} + +void MatrixScrollUp(char* txt, int loop) +{ + int wordcounter = 0; + char tmpbuf[200]; + char *words[100]; + + + + char separators[] = " /"; + + switch (mtx_state) { + case 1: + mtx_state = 2; + + mtx_y = 8; + mtx_counter = 0; + disp_refresh = Settings.display_refresh; + case 2: + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + strlcpy(tmpbuf, txt, sizeof(tmpbuf)); + char *p = strtok(tmpbuf, separators); + while (p != nullptr && wordcounter < 40) { + words[wordcounter++] = p; + p = strtok(nullptr, separators); + } + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + for (uint32_t j = 0; j < wordcounter; j++) { + matrix[i]->setCursor(-i *8, mtx_y + (j *8)); + matrix[i]->println(words[j]); + } + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); + if (((mtx_y %8) == 0) && mtx_counter) { + mtx_counter--; + } else { + mtx_y--; + mtx_counter = STATES * 1; + } + if (mtx_y < -(wordcounter *8)) { mtx_state = loop; } + } + break; + } +} + + + +void MatrixInitMode(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->setRotation(Settings.display_rotate); + matrix[i]->setBrightness(Settings.display_dimmer); + matrix[i]->blinkRate(0); + matrix[i]->setTextWrap(false); + + + matrix[i]->cp437(true); + } + MatrixClear(); +} + +void MatrixInit(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + MatrixInitMode(); + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void MatrixInitDriver(void) +{ + mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); + if (mtx_buffer != nullptr) { + if (!Settings.display_model) { + if (I2cSetDevice(Settings.display_address[1])) { + Settings.display_model = XDSP_03; + } + } + + if (XDSP_03 == Settings.display_model) { + mtx_state = 1; + for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) { + if (Settings.display_address[mtx_matrices]) { + I2cSetActiveFound(Settings.display_address[mtx_matrices], "8x8Matrix"); + matrix[mtx_matrices] = new Adafruit_8x8matrix(); + matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]); + } else { + break; + } + } + + Settings.display_width = mtx_matrices * 8; + Settings.display_height = 8; + + MatrixInitMode(); + } + } +} + +void MatrixOnOff(void) +{ + if (!disp_power) { MatrixClear(); } +} + +void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + strlcpy(mtx_buffer, str, MTX_MAX_SCREEN_BUFFER); + mtx_mode = x &1; + mtx_loop = y &1; + if (!mtx_state) { mtx_state = 1; } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void MatrixPrintLog(uint8_t direction) +{ + char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer; + if (txt != nullptr) { + if (!mtx_state) { mtx_state = 1; } + + if (!mtx_done) { + + uint8_t space = 0; + uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER; + mtx_buffer[0] = '\0'; + uint8_t i = 0; + while ((txt[i] != '\0') && (i < max_cols)) { + if (txt[i] == ' ') { + space++; + } else { + space = 0; + } + if (space < 2) { + strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < MTX_MAX_SCREEN_BUFFER -1) ? 1 : 0); + } + i++; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); + + mtx_done = 1; + } + + if (direction) { + MatrixScrollUp(mtx_buffer, 0); + } else { + MatrixScrollLeft(mtx_buffer, 0); + } + if (!mtx_state) { mtx_done = 0; } + } else { + char disp_time[9]; + + snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + MatrixFixed(disp_time); + } +} + +#endif + +void MatrixRefresh(void) +{ + if (disp_power) { + switch (Settings.display_mode) { + case 0: { + switch (mtx_mode) { + case 0: + MatrixScrollLeft(mtx_buffer, mtx_loop); + break; + case 1: + MatrixScrollUp(mtx_buffer, mtx_loop); + break; + } + break; + } +#ifdef USE_DISPLAY_MODES1TO5 + case 2: { + char disp_date[9]; + snprintf_P(disp_date, sizeof(disp_date), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); + MatrixFixed(disp_date); + break; + } + case 3: { + char disp_day[10]; + snprintf_P(disp_day, sizeof(disp_day), PSTR("%d %s"), RtcTime.day_of_month, RtcTime.name_of_month); + MatrixCenter(disp_day); + break; + } + case 4: + MatrixPrintLog(0); + break; + case 1: + case 5: + MatrixPrintLog(1); + break; +#endif + } + } +} + + + + + +bool Xdsp03(uint8_t function) +{ + if (!I2cEnabled(XI2C_05)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + MatrixInitDriver(); + } + else if (XDSP_03 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + MatrixInit(dsp_init); + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: + MatrixRefresh(); + break; + case FUNC_DISPLAY_POWER: + MatrixOnOff(); + break; + case FUNC_DISPLAY_DRAW_STRING: + MatrixDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; + } + } + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_04_ili9341.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_04_ili9341.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_ILI9341 + +#define XDSP_04 4 + +#define TFT_TOP 16 +#define TFT_BOTTOM 16 +#define TFT_FONT_WIDTH 6 +#define TFT_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_ILI9341 *tft; + +uint16_t tft_scroll; + + + +void Ili9341InitMode(void) +{ + tft->setRotation(Settings.display_rotate); + tft->invertDisplay(0); + tft->fillScreen(ILI9341_BLACK); + tft->setTextWrap(false); + tft->cp437(true); + if (!Settings.display_mode) { + tft->setCursor(0, 0); + tft->setTextColor(ILI9341_WHITE, ILI9341_BLACK); + tft->setTextSize(1); + } else { + tft->setScrollMargins(TFT_TOP, TFT_BOTTOM); + tft->setCursor(0, 0); + tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); + tft->setTextSize(2); + + + tft_scroll = TFT_TOP; + } +} + +void Ili9341Init(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + Ili9341InitMode(); +#ifdef USE_DISPLAY_MODES1TO5 + if (Settings.display_rotate) { + DisplayClearScreenBuffer(); + } +#endif + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void Ili9341InitDriver(void) +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_04; + } + + if (XDSP_04 == Settings.display_model) { + if (Settings.display_width != ILI9341_TFTWIDTH) { + Settings.display_width = ILI9341_TFTWIDTH; + } + if (Settings.display_height != ILI9341_TFTHEIGHT) { + Settings.display_height = ILI9341_TFTHEIGHT; + } + tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]); + tft->begin(); + +#ifdef USE_DISPLAY_MODES1TO5 + if (Settings.display_rotate) { + DisplayAllocScreenBuffer(); + } +#endif + + Ili9341InitMode(); + } +} + +void Ili9341Clear(void) +{ + tft->fillScreen(ILI9341_BLACK); + tft->setCursor(0, 0); +} + +void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + uint16_t active_color = ILI9341_WHITE; + + tft->setTextSize(Settings.display_size); + if (!flag) { + tft->setCursor(x, y); + } else { + tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size); + } + if (color) { active_color = color; } + tft->setTextColor(active_color, ILI9341_BLACK); + tft->println(str); +} + +void Ili9341DisplayOnOff(uint8_t on) +{ + + + if (pin[GPIO_BACKLIGHT] < 99) { + pinMode(pin[GPIO_BACKLIGHT], OUTPUT); + digitalWrite(pin[GPIO_BACKLIGHT], on); + } +} + +void Ili9341OnOff(void) +{ + Ili9341DisplayOnOff(disp_power); +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void Ili9341PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (Settings.display_rotate) { + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + } + + char* txt = DisplayLogBuffer('\370'); + if (txt != nullptr) { + uint8_t size = Settings.display_size; + uint16_t theight = size * TFT_FONT_HEIGTH; + + tft->setTextSize(size); + tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); + if (!Settings.display_rotate) { + tft->setCursor(0, tft_scroll); + tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); + tft->print(txt); + tft_scroll += theight; + if (tft_scroll >= (tft->height() - TFT_BOTTOM)) { + tft_scroll = TFT_TOP; + } + tft->scrollTo(tft_scroll); + } else { + uint8_t last_row = Settings.display_rows -1; + + tft_scroll = theight; + tft->setCursor(0, tft_scroll); + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + + tft->print(disp_screen_buffer[i]); + tft_scroll += theight; + tft->setCursor(0, tft_scroll); + delay(1); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + tft->print(disp_screen_buffer[last_row]); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); + } + } +} + +void Ili9341Refresh(void) +{ + if (Settings.display_mode) { + char tftdt[Settings.display_cols[0] +1]; + char date4[11]; + char space[Settings.display_cols[0] - 17]; + char time[9]; + + tft->setTextSize(2); + tft->setTextColor(ILI9341_YELLOW, ILI9341_RED); + tft->setCursor(0, 0); + + snprintf_P(date4, sizeof(date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + memset(space, 0x20, sizeof(space)); + space[sizeof(space) -1] = '\0'; + snprintf_P(time, sizeof(time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + snprintf_P(tftdt, sizeof(tftdt), PSTR("%s%s%s"), date4, space, time); + + tft->print(tftdt); + + switch (Settings.display_mode) { + case 1: + case 2: + case 3: + case 4: + case 5: + Ili9341PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp04(uint8_t function) +{ + bool result = false; + + if (spi_flg) { + if (FUNC_DISPLAY_INIT_DRIVER == function) { + Ili9341InitDriver(); + } + else if (XDSP_04 == Settings.display_model) { + + if (!dsp_color) { dsp_color = ILI9341_WHITE; } + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + Ili9341Init(dsp_init); + break; + case FUNC_DISPLAY_POWER: + Ili9341OnOff(); + break; + case FUNC_DISPLAY_CLEAR: + Ili9341Clear(); + break; + case FUNC_DISPLAY_DRAW_HLINE: + tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color); + break; + case FUNC_DISPLAY_DRAW_VLINE: + tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color); + break; + case FUNC_DISPLAY_DRAW_LINE: + tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + case FUNC_DISPLAY_DRAW_CIRCLE: + tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color); + break; + case FUNC_DISPLAY_FILL_CIRCLE: + tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color); + break; + case FUNC_DISPLAY_DRAW_RECTANGLE: + tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + case FUNC_DISPLAY_FILL_RECTANGLE: + tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + + + + case FUNC_DISPLAY_TEXT_SIZE: + tft->setTextSize(Settings.display_size); + break; + case FUNC_DISPLAY_FONT_SIZE: + + break; + case FUNC_DISPLAY_DRAW_STRING: + Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; + case FUNC_DISPLAY_ONOFF: + Ili9341DisplayOnOff(dsp_on); + break; + case FUNC_DISPLAY_ROTATION: + tft->setRotation(Settings.display_rotate); + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + Ili9341Refresh(); + break; +#endif + } + } + } + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_05_epaper_29.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_05_epaper_29.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_EPAPER_29 + +#define XDSP_05 5 + +#define EPD_TOP 12 +#define EPD_FONT_HEIGTH 12 + +#define COLORED 1 +#define UNCOLORED 0 + + + +#define USE_TINY_FONT + +#include +#include + + +extern uint8_t *buffer; +uint16_t epd_scroll; + +Epd *epd; + + + +void EpdInitDriver29() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_05; + } + + if (XDSP_05 == Settings.display_model) { + if (Settings.display_width != EPD_WIDTH) { + Settings.display_width = EPD_WIDTH; + } + if (Settings.display_height != EPD_HEIGHT) { + Settings.display_height = EPD_HEIGHT; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((EPD_WIDTH * EPD_HEIGHT) / 8,1); + if (!buffer) return; + + + epd = new Epd(EPD_WIDTH,EPD_HEIGHT); + + + if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) { + epd->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SPI_CS], pin[GPIO_SPI_CLK], pin[GPIO_SPI_MOSI]); + } + else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { + epd->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SSPI_CS], pin[GPIO_SSPI_SCLK], pin[GPIO_SSPI_MOSI]); + } else { + free(buffer); + return; + } + + renderer = epd; + epd->Init(DISPLAY_INIT_FULL); + epd->Init(DISPLAY_INIT_PARTIAL); + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(1); + renderer->DrawStringAt(50, 50, "Waveshare E-Paper Display!", COLORED,0); + renderer->Updateframe(); + delay(1000); + renderer->fillScreen(0); +#endif + + } +} + + + + + + + +#ifdef USE_DISPLAY_MODES1TO5 +#define EPD_FONT_HEIGTH 12 +void EpdPrintLog29(void) +{ + + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + + char* txt = DisplayLogBuffer('\040'); + if (txt != nullptr) { + uint8_t size = Settings.display_size; + uint16_t theight = size * EPD_FONT_HEIGTH; + + renderer->setTextFont(size); + uint8_t last_row = Settings.display_rows -1; + + + epd_scroll = 0; + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0); + epd_scroll += theight; + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0); + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); + } + } +} + +void EpdRefresh29(void) +{ + if (Settings.display_mode) { + + if (!renderer) return; +# 165 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_05_epaper_29.ino" + switch (Settings.display_mode) { + case 1: + case 2: + case 3: + case 4: + case 5: + EpdPrintLog29(); + renderer->Updateframe(); + break; + } + + + } +} + +#endif + + + + + +bool Xdsp05(uint8_t function) +{ + bool result = false; + if (FUNC_DISPLAY_INIT_DRIVER == function) { + EpdInitDriver29(); + } + else if (XDSP_05 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh29(); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_06_epaper_42.ino" +# 21 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_06_epaper_42.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_EPAPER_42 + +#define XDSP_06 6 + +#define COLORED42 1 +#define UNCOLORED42 0 + + + +#define USE_TINY_FONT + +#include +#include + +extern uint8_t *buffer; + +Epd42 *epd42; + + + + +void EpdInitDriver42() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_06; + } + + if (XDSP_06 == Settings.display_model) { + + if (Settings.display_width != EPD_WIDTH42) { + Settings.display_width = EPD_WIDTH42; + } + if (Settings.display_height != EPD_HEIGHT42) { + Settings.display_height = EPD_HEIGHT42; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((EPD_WIDTH42 * EPD_HEIGHT42) / 8,1); + if (!buffer) return; + + + epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42); + + #ifdef USE_SPI + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)) { + epd42->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + } else { + free(buffer); + return; + } + #else + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { + epd42->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + } else { + free(buffer); + return; + } + #endif + + renderer = epd42; + + epd42->Init(); + + renderer->fillScreen(0); + + + epd42->Init(DISPLAY_INIT_FULL); + + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + + epd42->ClearFrame(); + renderer->Updateframe(); + delay(3000); + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->DrawStringAt(50, 140, "Waveshare E-Paper!", COLORED42,0); + renderer->Updateframe(); + delay(350); + renderer->fillScreen(0); +#endif + + } +} + + + + + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void EpdRefresh42() +{ + if (Settings.display_mode) { + + } +} + +#endif + + + + + + +bool Xdsp06(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + EpdInitDriver42(); + } + else if (XDSP_06 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh42(); + break; +#endif + } + } + return result; +} + + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_07_sh1106.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_07_sh1106.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SH1106 + +#define OLED_RESET 4 + +#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); + +extern uint8_t *buffer; + +#define XDSP_07 7 +#define XI2C_06 6 + +#define OLED_ADDRESS1 0x3C +#define OLED_ADDRESS2 0x3D + +#define OLED_BUFFER_COLS 40 +#define OLED_BUFFER_ROWS 16 + +#define OLED_FONT_WIDTH 6 +#define OLED_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_SH1106 *oled1106; + + + + +void SH1106InitDriver() +{ + if (!Settings.display_model) { + if (I2cSetDevice(OLED_ADDRESS1)) { + Settings.display_address[0] = OLED_ADDRESS1; + Settings.display_model = XDSP_07; + } + else if (I2cSetDevice(OLED_ADDRESS2)) { + Settings.display_address[0] = OLED_ADDRESS2; + Settings.display_model = XDSP_07; + } + } + + if (XDSP_07 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "SH1106"); + + if (Settings.display_width != SH1106_LCDWIDTH) { + Settings.display_width = SH1106_LCDWIDTH; + } + if (Settings.display_height != SH1106_LCDHEIGHT) { + Settings.display_height = SH1106_LCDHEIGHT; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((SH1106_LCDWIDTH * SH1106_LCDHEIGHT) / 8,1); + if (!buffer) return; + + + oled1106 = new Adafruit_SH1106(SH1106_LCDWIDTH,SH1106_LCDHEIGHT); + renderer=oled1106; + renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0); + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + renderer->setTextFont(0); + renderer->setTextSize(2); + renderer->setCursor(20,20); + renderer->println(F("SH1106")); + renderer->Updateframe(); + renderer->DisplayOnff(1); +#endif + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void SH1106PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void SH1106Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setTextFont(Settings.display_font); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void SH1106Refresh(void) +{ + if (!renderer) return; + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + SH1106Time(); + break; + case 2: + case 3: + case 4: + case 5: + SH1106PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp07(uint8_t function) +{ + if (!I2cEnabled(XI2C_06)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SH1106InitDriver(); + } + else if (XDSP_07 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + SH1106Refresh(); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_08_ILI9488.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_08_ILI9488.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_ILI9488 + +#define XDSP_08 8 +#define XI2C_38 38 + +#define COLORED 1 +#define UNCOLORED 0 + + +#define FT6236_address 0x38 + + + +#define USE_TINY_FONT + + +#include +#include + +TouchLocation ili9488_pLoc; +uint8_t ili9488_ctouch_counter = 0; + + +#define BACKPLANE_PIN 2 + +extern uint8_t *buffer; +extern uint8_t color_type; +ILI9488 *ili9488; + +#ifdef USE_TOUCH_BUTTONS +extern VButton *buttons[]; +#endif + +extern const uint16_t picture[]; +uint8_t FT6236_found; + + + +void ILI9488_InitDriver() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_08; + } + + if (XDSP_08 == Settings.display_model) { + + if (Settings.display_width != ILI9488_TFTWIDTH) { + Settings.display_width = ILI9488_TFTWIDTH; + } + if (Settings.display_height != ILI9488_TFTHEIGHT) { + Settings.display_height = ILI9488_TFTHEIGHT; + } + + + buffer=NULL; + + + fg_color = ILI9488_WHITE; + bg_color = ILI9488_BLACK; + + uint8_t bppin=BACKPLANE_PIN; + if (pin[GPIO_BACKLIGHT]<99) { + bppin=pin[GPIO_BACKLIGHT]; + } + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ + ili9488 = new ILI9488(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK],bppin); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { + ili9488 = new ILI9488(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK],bppin); + } else { + return; + } + } + + SPI.begin(); + ili9488->begin(); + renderer = ili9488; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(ILI9488_WHITE,ILI9488_BLACK); + renderer->DrawStringAt(50, 50, "ILI9488 TFT Display!", ILI9488_WHITE,0); + delay(1000); + + +#endif + + color_type = COLOR_COLOR; + + + if (I2cEnabled(XI2C_38) && I2cSetDevice(FT6236_address)) { + FT6236begin(FT6236_address); + FT6236_found=1; + I2cSetActiveFound(FT6236_address, "FT6236"); + } else { + FT6236_found=0; + } + + } +} + +#ifdef USE_TOUCH_BUTTONS +void ILI9488_MQTT(uint8_t count,const char *cp) { + ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); + MqttPublishTeleSensor(); +} + +void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower|=0x80; + else buttons[count]->vpower&=0x7f; +} + +void FT6236Check() { +uint16_t temp; +uint8_t rbutt=0,vbutt=0; +ili9488_ctouch_counter++; +if (2 == ili9488_ctouch_counter) { + + ili9488_ctouch_counter=0; + if (FT6236readTouchLocation(&ili9488_pLoc,1)) { + + if (renderer) { + uint8_t rot=renderer->getRotation(); + switch (rot) { + case 0: + temp=ili9488_pLoc.y; + ili9488_pLoc.y=renderer->height()-ili9488_pLoc.x; + ili9488_pLoc.x=temp; + break; + case 1: + break; + case 2: + break; + case 3: + temp=ili9488_pLoc.y; + ili9488_pLoc.y=ili9488_pLoc.x; + ili9488_pLoc.x=renderer->width()-temp; + break; + } + + for (uint8_t count=0; countvpower&0x7f; + if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) { + + buttons[count]->press(true); + if (buttons[count]->justPressed()) { + if (!bflags) { + uint8_t pwr=bitRead(power,rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + ILI9488_RDW_BUTT(count,!pwr); + } + } else { + + const char *cp; + if (bflags==1) { + + buttons[count]->vpower^=0x80; + cp="TBT"; + } else { + + buttons[count]->vpower|=0x80; + cp="PBT"; + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + ILI9488_MQTT(count,cp); + } + } + } + if (!bflags) { + rbutt++; + } else { + vbutt++; + } + } + } + } + } else { + + for (uint8_t count=0; countvpower&0x7f; + buttons[count]->press(false); + if (buttons[count]->justReleased()) { + uint8_t bflags=buttons[count]->vpower&0x7f; + if (bflags>0) { + if (bflags>1) { + + buttons[count]->vpower&=0x7f; + ILI9488_MQTT(count,"PBT"); + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + } + } + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; + if (pwr!=vpwr) { + ILI9488_RDW_BUTT(count,pwr); + } + rbutt++; + } + } + } + ili9488_pLoc.x=0; + ili9488_pLoc.y=0; + } +} +} +#endif + + + + +bool Xdsp08(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + ILI9488_InitDriver(); + } + else if (XDSP_08 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: +#ifdef USE_TOUCH_BUTTONS + if (FT6236_found) FT6236Check(); +#endif + break; + } + } + + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_09_SSD1351.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_09_SSD1351.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SSD1351 + +#define XDSP_09 9 + +#define COLORED 1 +#define UNCOLORED 0 + + + + +#define USE_TINY_FONT + +#include + +extern uint8_t *buffer; +extern uint8_t color_type; +SSD1351 *ssd1351; + + + +void SSD1351_InitDriver() { + if (!Settings.display_model) { + Settings.display_model = XDSP_09; + } + + if (XDSP_09 == Settings.display_model) { + + if (Settings.display_width != SSD1351_WIDTH) { + Settings.display_width = SSD1351_WIDTH; + } + if (Settings.display_height != SSD1351_HEIGHT) { + Settings.display_height = SSD1351_HEIGHT; + } + + buffer=0; + + + fg_color = SSD1351_WHITE; + bg_color = SSD1351_BLACK; + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ + ssd1351 = new SSD1351(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)){ + ssd1351 = new SSD1351(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + } else { + return; + } + } + + delay(100); + SPI.begin(); + ssd1351->begin(); + renderer = ssd1351; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->dim(Settings.display_dimmer); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(SSD1351_WHITE,SSD1351_BLACK); + renderer->DrawStringAt(10, 60, "SSD1351", SSD1351_RED,0); + delay(1000); + +#endif + color_type = COLOR_COLOR; + } +} + +#ifdef USE_DISPLAY_MODES1TO5 + +void SSD1351PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void SSD1351Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(2); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void SSD1351Refresh(void) +{ + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + SSD1351Time(); + break; + case 2: + case 3: + case 4: + case 5: + SSD1351PrintLog(); + break; + } + } +} + +#endif + + + + +bool Xdsp09(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SSD1351_InitDriver(); + } + else if (XDSP_09 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + SSD1351Refresh(); + break; +#endif + } + } + return result; +} +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_10_RA8876.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_10_RA8876.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_RA8876 + +#define XDSP_10 10 +#define XI2C_39 39 + +#define COLORED 1 +#define UNCOLORED 0 + + +#define FT5316_address 0x38 + + + +#define USE_TINY_FONT + +#include +#include + +TouchLocation ra8876_pLoc; +uint8_t ra8876_ctouch_counter = 0; + +#ifdef USE_TOUCH_BUTTONS +extern VButton *buttons[]; +#endif + +extern uint8_t *buffer; +extern uint8_t color_type; +RA8876 *ra8876; + +uint8_t FT5316_found; + + +void RA8876_InitDriver() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_10; + } + + if (XDSP_10 == Settings.display_model) { + + if (Settings.display_width != RA8876_TFTWIDTH) { + Settings.display_width = RA8876_TFTWIDTH; + } + if (Settings.display_height != RA8876_TFTHEIGHT) { + Settings.display_height = RA8876_TFTHEIGHT; + } + buffer=0; + + + fg_color = RA8876_WHITE; + bg_color = RA8876_BLACK; + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]==13) && (pin[GPIO_SSPI_MISO]==12) && (pin[GPIO_SSPI_SCLK]==14)) { + ra8876 = new RA8876(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_MISO],pin[GPIO_SSPI_SCLK],pin[GPIO_BACKLIGHT]); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]==13) && (pin[GPIO_SPI_MISO]==12) && (pin[GPIO_SPI_CLK]==14)) { + ra8876 = new RA8876(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_MISO],pin[GPIO_SPI_CLK],pin[GPIO_BACKLIGHT]); + } else { + return; + } + } + + ra8876->begin(); + renderer = ra8876; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->dim(Settings.display_dimmer); + + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(RA8876_WHITE,RA8876_BLACK); + renderer->DrawStringAt(600, 300, "RA8876", RA8876_RED,0); + delay(1000); + +#endif + color_type = COLOR_COLOR; + + if (I2cEnabled(XI2C_39) && I2cSetDevice(FT5316_address)) { + FT6236begin(FT5316_address); + FT5316_found=1; + I2cSetActiveFound(FT5316_address, "FT5316"); + } else { + FT5316_found=0; + } + + } +} + +#ifdef USE_TOUCH_BUTTONS +void RA8876_MQTT(uint8_t count,const char *cp) { + ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); + MqttPublishTeleSensor(); +} + +void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower|=0x80; + else buttons[count]->vpower&=0x7f; +} + + +void FT5316Check() { +uint16_t temp; +uint8_t rbutt=0,vbutt=0; +ra8876_ctouch_counter++; +if (2 == ra8876_ctouch_counter) { + + ra8876_ctouch_counter=0; + + if (FT6236readTouchLocation(&ra8876_pLoc,1)) { + ra8876_pLoc.x=ra8876_pLoc.x*RA8876_TFTWIDTH/800; + ra8876_pLoc.y=ra8876_pLoc.y*RA8876_TFTHEIGHT/480; + + + if (renderer) { + + + ra8876_pLoc.x=RA8876_TFTWIDTH-ra8876_pLoc.x; + ra8876_pLoc.y=RA8876_TFTHEIGHT-ra8876_pLoc.y; +# 170 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_10_RA8876.ino" + for (uint8_t count=0; countvpower&0x7f; + if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) { + + buttons[count]->press(true); + if (buttons[count]->justPressed()) { + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + RA8876_RDW_BUTT(count,!pwr); + } + } else { + + const char *cp; + if (bflags==1) { + + buttons[count]->vpower^=0x80; + cp="TBT"; + } else { + + buttons[count]->vpower|=0x80; + cp="PBT"; + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + RA8876_MQTT(count,cp); + } + } + } + if (!bflags) { + rbutt++; + } else { + vbutt++; + } + } + } + } + } else { + + for (uint8_t count=0; countvpower&0x7f; + buttons[count]->press(false); + if (buttons[count]->justReleased()) { + if (bflags>0) { + if (bflags>1) { + + buttons[count]->vpower&=0x7f; + RA8876_MQTT(count,"PBT"); + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + } + } + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; + if (pwr!=vpwr) { + RA8876_RDW_BUTT(count,pwr); + } + rbutt++; + } + } + } + ra8876_pLoc.x=0; + ra8876_pLoc.y=0; + } +} +} +#endif +# 426 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_10_RA8876.ino" +bool Xdsp10(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + RA8876_InitDriver(); + } + else if (XDSP_10 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: +#ifdef USE_TOUCH_BUTTONS + if (FT5316_found) FT5316Check(); +#endif + break; + } + } + return result; +} +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_interface.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_interface.ino" +#ifdef USE_DISPLAY + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xdsp_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xdsp_func_ptr[])(uint8_t) = { +#endif + +#ifdef XDSP_01 + &Xdsp01, +#endif + +#ifdef XDSP_02 + &Xdsp02, +#endif + +#ifdef XDSP_03 + &Xdsp03, +#endif + +#ifdef XDSP_04 + &Xdsp04, +#endif + +#ifdef XDSP_05 + &Xdsp05, +#endif + +#ifdef XDSP_06 + &Xdsp06, +#endif + +#ifdef XDSP_07 + &Xdsp07, +#endif + +#ifdef XDSP_08 + &Xdsp08, +#endif + +#ifdef XDSP_09 + &Xdsp09, +#endif + +#ifdef XDSP_10 + &Xdsp10, +#endif + +#ifdef XDSP_11 + &Xdsp11, +#endif + +#ifdef XDSP_12 + &Xdsp12, +#endif + +#ifdef XDSP_13 + &Xdsp13, +#endif + +#ifdef XDSP_14 + &Xdsp14, +#endif + +#ifdef XDSP_15 + &Xdsp15, +#endif + +#ifdef XDSP_16 + &Xdsp16 +#endif +}; + +const uint8_t xdsp_present = sizeof(xdsp_func_ptr) / sizeof(xdsp_func_ptr[0]); +# 117 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_interface.ino" +uint8_t XdspPresent(void) +{ + return xdsp_present; +} + +bool XdspCall(uint8_t Function) +{ + bool result = false; + + DEBUG_TRACE_LOG(PSTR("DSP: %d"), Function); + + for (uint32_t x = 0; x < xdsp_present; x++) { + result = xdsp_func_ptr[x](Function); + + if (result && (FUNC_DISPLAY_MODEL == Function)) { + break; + } + } + + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_01_ws2812.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_01_ws2812.ino" +#ifdef USE_LIGHT +#ifdef USE_WS2812 +# 38 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_01_ws2812.ino" +#define XLGT_01 1 + +const uint8_t WS2812_SCHEMES = 8; + +const char kWs2812Commands[] PROGMEM = "|" + D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH ; + +void (* const Ws2812Command[])(void) PROGMEM = { + &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth }; + +#include + +#if (USE_WS2812_CTYPE == NEO_GRB) + typedef NeoGrbFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_BRG) + typedef NeoBrgFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_RBG) + typedef NeoRbgFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_RGBW) + typedef NeoRgbwFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_GRBW) + typedef NeoGrbwFeature selectedNeoFeatureType; +#else + typedef NeoRgbFeature selectedNeoFeatureType; +#endif + +#ifdef USE_WS2812_DMA + + +#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) + typedef NeoEsp8266DmaWs2812xMethod selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) + typedef NeoEsp8266DmaSk6812Method selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) + typedef NeoEsp8266DmaApa106Method selectedNeoSpeedType; +#else + typedef NeoEsp8266Dma800KbpsMethod selectedNeoSpeedType; +#endif + +#else + + +#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) + typedef NeoEsp8266BitBangWs2812xMethod selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) + typedef NeoEsp8266BitBangSk6812Method selectedNeoSpeedType; +#else + typedef NeoEsp8266BitBang800KbpsMethod selectedNeoSpeedType; +#endif + +#endif + +NeoPixelBus *strip = nullptr; + +struct WsColor { + uint8_t red, green, blue; +}; + +struct ColorScheme { + WsColor* colors; + uint8_t count; +}; + +WsColor kIncandescent[2] = { 255,140,20, 0,0,0 }; +WsColor kRgb[3] = { 255,0,0, 0,255,0, 0,0,255 }; +WsColor kChristmas[2] = { 255,0,0, 0,255,0 }; +WsColor kHanukkah[2] = { 0,0,255, 255,255,255 }; +WsColor kwanzaa[3] = { 255,0,0, 0,0,0, 0,255,0 }; +WsColor kRainbow[7] = { 255,0,0, 255,128,0, 255,255,0, 0,255,0, 0,0,255, 128,0,255, 255,0,255 }; +WsColor kFire[3] = { 255,0,0, 255,102,0, 255,192,0 }; +ColorScheme kSchemes[WS2812_SCHEMES -1] = { + kIncandescent, 2, + kRgb, 3, + kChristmas, 2, + kHanukkah, 2, + kwanzaa, 3, + kRainbow, 7, + kFire, 3 }; + +uint8_t kWidth[5] = { + 1, + 2, + 4, + 8, + 255 }; +uint8_t kWsRepeat[5] = { + 8, + 6, + 4, + 2, + 1 }; + +struct WS2812 { + uint8_t show_next = 1; + uint8_t scheme_offset = 0; + bool suspend_update = false; +} Ws2812; + + + +void Ws2812StripShow(void) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; +#else + RgbColor c; +#endif + + if (Settings.light_correction) { + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + c = strip->GetPixelColor(i); + c.R = ledGamma(c.R); + c.G = ledGamma(c.G); + c.B = ledGamma(c.B); +#if (USE_WS2812_CTYPE > NEO_3LED) + c.W = ledGamma(c.W); +#endif + strip->SetPixelColor(i, c); + } + } + strip->Show(); +} + +int mod(int a, int b) +{ + int ret = a % b; + if (ret < 0) ret += b; + return ret; +} + +void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor color; +#else + RgbColor color; +#endif + + uint32_t mod_position = mod(position, (int)Settings.light_pixels); + + color = strip->GetPixelColor(mod_position); + float dimmer = 100 / (float)Settings.light_dimmer; + color.R = tmin(color.R + ((hand_color.red / dimmer) * offset), 255); + color.G = tmin(color.G + ((hand_color.green / dimmer) * offset), 255); + color.B = tmin(color.B + ((hand_color.blue / dimmer) * offset), 255); + strip->SetPixelColor(mod_position, color); +} + +void Ws2812UpdateHand(int position, uint32_t index) +{ + uint32_t width = Settings.light_width; + if (index < WS_MARKER) { width = Settings.ws_width[index]; } + if (!width) { return; } + + position = (position + Settings.light_rotation) % Settings.light_pixels; + + if (Settings.flag.ws_clock_reverse) { + position = Settings.light_pixels -position; + } + WsColor hand_color = { Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE] }; + + Ws2812UpdatePixelColor(position, hand_color, 1); + + uint32_t range = ((width -1) / 2) +1; + for (uint32_t h = 1; h < range; h++) { + float offset = (float)(range - h) / (float)range; + Ws2812UpdatePixelColor(position -h, hand_color, offset); + Ws2812UpdatePixelColor(position +h, hand_color, offset); + } +} + +void Ws2812Clock(void) +{ + strip->ClearTo(0); + int clksize = 60000 / (int)Settings.light_pixels; + + Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); + Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); + Ws2812UpdateHand((((RtcTime.hour % 12) * 5000) + ((RtcTime.minute * 1000) / 12 )) / clksize, WS_HOUR); + if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { + for (uint32_t i = 0; i < 12; i++) { + Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); + } + } + + Ws2812StripShow(); +} + +void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i) +{ + + + + + ColorScheme scheme = kSchemes[schemenr]; + uint32_t curRange = i / range; + uint32_t rangeIndex = i % range; + uint32_t colorIndex = rangeIndex / gradRange; + uint32_t start = colorIndex; + uint32_t end = colorIndex +1; + if (curRange % 2 != 0) { + start = (scheme.count -1) - start; + end = (scheme.count -1) - end; + } + float dimmer = 100 / (float)Settings.light_dimmer; + float fmyRed = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].red, scheme.colors[end].red) / dimmer; + float fmyGrn = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].green, scheme.colors[end].green) / dimmer; + float fmyBlu = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].blue, scheme.colors[end].blue) / dimmer; + mColor->red = (uint8_t)fmyRed; + mColor->green = (uint8_t)fmyGrn; + mColor->blue = (uint8_t)fmyBlu; +} + +void Ws2812Gradient(uint32_t schemenr) +{ + + + + + +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; + c.W = 0; +#else + RgbColor c; +#endif + + ColorScheme scheme = kSchemes[schemenr]; + if (scheme.count < 2) { return; } + + uint32_t repeat = kWsRepeat[Settings.light_width]; + uint32_t range = (uint32_t)ceil((float)Settings.light_pixels / (float)repeat); + uint32_t gradRange = (uint32_t)ceil((float)range / (float)(scheme.count - 1)); + uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); + uint32_t offset = speed > 0 ? Light.strip_timer_counter / speed : 0; + + WsColor oldColor, currentColor; + Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset); + currentColor = oldColor; + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + if (kWsRepeat[Settings.light_width] > 1) { + Ws2812GradientColor(schemenr, ¤tColor, range, gradRange, i +offset); + } + if (Settings.light_speed > 0) { + + c.R = map(Light.strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red); + c.G = map(Light.strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green); + c.B = map(Light.strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue); + } + else { + + c.R = currentColor.red; + c.G = currentColor.green; + c.B = currentColor.blue; + } + strip->SetPixelColor(i, c); + oldColor = currentColor; + } + Ws2812StripShow(); +} + +void Ws2812Bars(uint32_t schemenr) +{ + + + + + +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; + c.W = 0; +#else + RgbColor c; +#endif + + ColorScheme scheme = kSchemes[schemenr]; + + uint32_t maxSize = Settings.light_pixels / scheme.count; + if (kWidth[Settings.light_width] > maxSize) { maxSize = 0; } + + uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); + uint32_t offset = (speed > 0) ? Light.strip_timer_counter / speed : 0; + + WsColor mcolor[scheme.count]; + memcpy(mcolor, scheme.colors, sizeof(mcolor)); + float dimmer = 100 / (float)Settings.light_dimmer; + for (uint32_t i = 0; i < scheme.count; i++) { + float fmyRed = (float)mcolor[i].red / dimmer; + float fmyGrn = (float)mcolor[i].green / dimmer; + float fmyBlu = (float)mcolor[i].blue / dimmer; + mcolor[i].red = (uint8_t)fmyRed; + mcolor[i].green = (uint8_t)fmyGrn; + mcolor[i].blue = (uint8_t)fmyBlu; + } + uint32_t colorIndex = offset % scheme.count; + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + if (maxSize) { colorIndex = ((i + offset) % (scheme.count * kWidth[Settings.light_width])) / kWidth[Settings.light_width]; } + c.R = mcolor[colorIndex].red; + c.G = mcolor[colorIndex].green; + c.B = mcolor[colorIndex].blue; + strip->SetPixelColor(i, c); + } + Ws2812StripShow(); +} + +void Ws2812Clear(void) +{ + strip->ClearTo(0); + strip->Show(); + Ws2812.show_next = 1; +} + +void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor lcolor; + lcolor.W = white; +#else + RgbColor lcolor; +#endif + + lcolor.R = red; + lcolor.G = green; + lcolor.B = blue; + if (led) { + strip->SetPixelColor(led -1, lcolor); + } else { + + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + strip->SetPixelColor(i, lcolor); + } + } + + if (!Ws2812.suspend_update) { + strip->Show(); + Ws2812.show_next = 1; + } +} + +char* Ws2812GetColor(uint32_t led, char* scolor) +{ + uint8_t sl_ledcolor[4]; + + #if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor lcolor = strip->GetPixelColor(led -1); + sl_ledcolor[3] = lcolor.W; + #else + RgbColor lcolor = strip->GetPixelColor(led -1); + #endif + sl_ledcolor[0] = lcolor.R; + sl_ledcolor[1] = lcolor.G; + sl_ledcolor[2] = lcolor.B; + scolor[0] = '\0'; + for (uint32_t i = 0; i < Light.subtype; i++) { + if (Settings.flag.decimal_text) { + snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", sl_ledcolor[i]); + } else { + snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, sl_ledcolor[i]); + } + } + return scolor; +} + + + + + +void Ws2812ForceSuspend (void) +{ + Ws2812.suspend_update = true; +} + +void Ws2812ForceUpdate (void) +{ + Ws2812.suspend_update = false; + strip->Show(); + Ws2812.show_next = 1; +} + + + +bool Ws2812SetChannels(void) +{ + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); + + return true; +} + +void Ws2812ShowScheme(void) +{ + uint32_t scheme = Settings.light_scheme - Ws2812.scheme_offset; + + switch (scheme) { + case 0: + if ((1 == state_250mS) || (Ws2812.show_next)) { + Ws2812Clock(); + Ws2812.show_next = 0; + } + break; + default: + if (1 == Settings.light_fade) { + Ws2812Gradient(scheme -1); + } else { + Ws2812Bars(scheme -1); + } + Ws2812.show_next = 1; + break; + } +} + +void Ws2812ModuleSelected(void) +{ + if (pin[GPIO_WS2812] < 99) { + + + strip = new NeoPixelBus(WS2812_MAX_LEDS, pin[GPIO_WS2812]); + strip->Begin(); + + Ws2812Clear(); + + Ws2812.scheme_offset = Light.max_scheme +1; + Light.max_scheme += WS2812_SCHEMES; + +#if (USE_WS2812_CTYPE > NEO_3LED) + light_type = LT_RGBW; +#else + light_type = LT_RGB; +#endif + light_flg = XLGT_01; + } +} + + + +void CmndLed(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) { + if (XdrvMailbox.data_len > 0) { + char *p; + uint16_t idx = XdrvMailbox.index; + Ws2812ForceSuspend(); + for (char *color = strtok_r(XdrvMailbox.data, " ", &p); color; color = strtok_r(nullptr, " ", &p)) { + if (LightColorEntry(color, strlen(color))) { + Ws2812SetColor(idx, Light.entry_color[0], Light.entry_color[1], Light.entry_color[2], Light.entry_color[3]); + idx++; + if (idx > Settings.light_pixels) { break; } + } else { + break; + } + } + Ws2812ForceUpdate(); + } + char scolor[LIGHT_COLOR_SIZE]; + ResponseCmndIdxChar(Ws2812GetColor(XdrvMailbox.index, scolor)); + } +} + +void CmndPixels(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { + Settings.light_pixels = XdrvMailbox.payload; + Settings.light_rotation = 0; + Ws2812Clear(); + Light.update = true; + } + ResponseCmndNumber(Settings.light_pixels); +} + +void CmndRotation(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { + Settings.light_rotation = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_rotation); +} + +void CmndWidth(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if (1 == XdrvMailbox.index) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { + Settings.light_width = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_width); + } else { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32)) { + Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.ws_width[XdrvMailbox.index -2]); + } + } +} + + + + + +bool Xlgt01(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Ws2812SetChannels(); + break; + case FUNC_SET_SCHEME: + Ws2812ShowScheme(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kWs2812Commands, Ws2812Command); + break; + case FUNC_MODULE_INIT: + Ws2812ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_02_my92x1.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_02_my92x1.ino" +#ifdef USE_LIGHT +#ifdef USE_MY92X1 + + + + +#define XLGT_02 2 + +struct MY92X1 { + uint8_t pdi_pin = 0; + uint8_t pdcki_pin = 0; + uint8_t model = 0; +} My92x1; + +extern "C" { + void os_delay_us(unsigned int); +} + +void LightDiPulse(uint8_t times) +{ + for (uint32_t i = 0; i < times; i++) { + digitalWrite(My92x1.pdi_pin, HIGH); + digitalWrite(My92x1.pdi_pin, LOW); + } +} + +void LightDckiPulse(uint8_t times) +{ + for (uint32_t i = 0; i < times; i++) { + digitalWrite(My92x1.pdcki_pin, HIGH); + digitalWrite(My92x1.pdcki_pin, LOW); + } +} + +void LightMy92x1Write(uint8_t data) +{ + for (uint32_t i = 0; i < 4; i++) { + digitalWrite(My92x1.pdcki_pin, LOW); + digitalWrite(My92x1.pdi_pin, (data & 0x80)); + digitalWrite(My92x1.pdcki_pin, HIGH); + data = data << 1; + digitalWrite(My92x1.pdi_pin, (data & 0x80)); + digitalWrite(My92x1.pdcki_pin, LOW); + digitalWrite(My92x1.pdi_pin, LOW); + data = data << 1; + } +} + +void LightMy92x1Init(void) +{ + uint8_t chips[3] = { 1, 2, 2 }; + + LightDckiPulse(chips[My92x1.model] * 32); + os_delay_us(12); + + + LightDiPulse(12); + os_delay_us(12); + for (uint32_t n = 0; n < chips[My92x1.model]; n++) { + LightMy92x1Write(0x18); + } + os_delay_us(12); + + + LightDiPulse(16); + os_delay_us(12); +} + +void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) +{ + uint8_t channels[3] = { 4, 6, 6 }; + + uint8_t duty[3][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, + { duty_w, duty_c, 0, duty_g, duty_r, duty_b }, + { duty_r, duty_g, duty_b, duty_w, duty_w, duty_w }}; + + os_delay_us(12); + for (uint32_t channel = 0; channel < channels[My92x1.model]; channel++) { + LightMy92x1Write(duty[My92x1.model][channel]); + } + os_delay_us(12); + LightDiPulse(8); + os_delay_us(12); +} + + + +bool My92x1SetChannels(void) +{ + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); + + return true; +} + +void My92x1ModuleSelected(void) +{ + if ((pin[GPIO_DCKI] < 99) && (pin[GPIO_DI] < 99)) { + My92x1.pdi_pin = pin[GPIO_DI]; + My92x1.pdcki_pin = pin[GPIO_DCKI]; + + pinMode(My92x1.pdi_pin, OUTPUT); + pinMode(My92x1.pdcki_pin, OUTPUT); + digitalWrite(My92x1.pdi_pin, LOW); + digitalWrite(My92x1.pdcki_pin, LOW); + + My92x1.model = 2; + light_type = LT_RGBW; + if (AILIGHT == my_module_type) { + My92x1.model = 0; + + } + else if (SONOFF_B1 == my_module_type) { + My92x1.model = 1; + light_type = LT_RGBWC; + } + + LightMy92x1Init(); + + light_flg = XLGT_02; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: MY29x1 Found")); + } +} + + + + + +bool Xlgt02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = My92x1SetChannels(); + break; + case FUNC_MODULE_INIT: + My92x1ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" +#ifdef USE_LIGHT +#ifdef USE_SM16716 + + + + + + + +#define XLGT_03 3 + +#define D_LOG_SM16716 "SM16716: " + +struct SM16716 { + uint8_t pin_clk = 0; + uint8_t pin_dat = 0; + uint8_t pin_sel = 0; + bool enabled = false; +} Sm16716; + +void SM16716_SendBit(uint8_t v) +{ + + + + + + digitalWrite(Sm16716.pin_dat, (v != 0) ? HIGH : LOW); + + digitalWrite(Sm16716.pin_clk, HIGH); + + digitalWrite(Sm16716.pin_clk, LOW); +} + +void SM16716_SendByte(uint8_t v) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) { + SM16716_SendBit(v & mask); + } +} + +void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) +{ + if (Sm16716.pin_sel < 99) { + bool should_enable = (duty_r | duty_g | duty_b); + if (!Sm16716.enabled && should_enable) { + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on")); + Sm16716.enabled = true; + digitalWrite(Sm16716.pin_sel, HIGH); + + + delayMicroseconds(1000); + SM16716_Init(); + } + else if (Sm16716.enabled && !should_enable) { + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off")); + Sm16716.enabled = false; + digitalWrite(Sm16716.pin_sel, LOW); + } + } + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b); + + + SM16716_SendBit(1); + SM16716_SendByte(duty_r); + SM16716_SendByte(duty_g); + SM16716_SendByte(duty_b); + + + + + + SM16716_SendBit(0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_SendByte(0); +} +# 111 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" +void SM16716_Init(void) +{ + for (uint32_t t_init = 0; t_init < 50; ++t_init) { + SM16716_SendBit(0); + } +} + + + +bool Sm16716SetChannels(void) +{ +# 132 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); + + return true; +} + +void Sm16716ModuleSelected(void) +{ + if ((pin[GPIO_SM16716_CLK] < 99) && (pin[GPIO_SM16716_DAT] < 99)) { + Sm16716.pin_clk = pin[GPIO_SM16716_CLK]; + Sm16716.pin_dat = pin[GPIO_SM16716_DAT]; + Sm16716.pin_sel = pin[GPIO_SM16716_SEL]; +# 157 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" + pinMode(Sm16716.pin_clk, OUTPUT); + digitalWrite(Sm16716.pin_clk, LOW); + + pinMode(Sm16716.pin_dat, OUTPUT); + digitalWrite(Sm16716.pin_dat, LOW); + + if (Sm16716.pin_sel < 99) { + pinMode(Sm16716.pin_sel, OUTPUT); + digitalWrite(Sm16716.pin_sel, LOW); + + } else { + + SM16716_Init(); + } + + LightPwmOffset(LST_RGB); + light_type += LST_RGB; + light_flg = XLGT_03; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM16716 Found")); + } +} + + + + + +bool Xlgt03(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Sm16716SetChannels(); + break; + case FUNC_MODULE_INIT: + Sm16716ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_04_sm2135.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_04_sm2135.ino" +#ifdef USE_LIGHT +#ifdef USE_SM2135 + + + + + + +#define XLGT_04 4 + +#define SM2135_ADDR_MC 0xC0 +#define SM2135_ADDR_CH 0xC1 +#define SM2135_ADDR_R 0xC2 +#define SM2135_ADDR_G 0xC3 +#define SM2135_ADDR_B 0xC4 +#define SM2135_ADDR_C 0xC5 +#define SM2135_ADDR_W 0xC6 + +#define SM2135_RGB 0x00 +#define SM2135_CW 0x80 + +#define SM2135_10MA 0x00 +#define SM2135_15MA 0x01 +#define SM2135_20MA 0x02 +#define SM2135_25MA 0x03 +#define SM2135_30MA 0x04 +#define SM2135_35MA 0x05 +#define SM2135_40MA 0x06 +#define SM2135_45MA 0x07 +#define SM2135_50MA 0x08 +#define SM2135_55MA 0x09 +#define SM2135_60MA 0x0A + + +const uint8_t SM2135_CURRENT = (SM2135_20MA << 4) | SM2135_15MA; + +struct SM2135 { + uint8_t clk = 0; + uint8_t data = 0; +} Sm2135; + +uint8_t Sm2135Write(uint8_t data) +{ + for (uint32_t i = 0; i < 8; i++) { + digitalWrite(Sm2135.clk, LOW); + digitalWrite(Sm2135.data, (data & 0x80)); + digitalWrite(Sm2135.clk, HIGH); + data = data << 1; + } + digitalWrite(Sm2135.clk, LOW); + digitalWrite(Sm2135.data, HIGH); + pinMode(Sm2135.data, INPUT); + digitalWrite(Sm2135.clk, HIGH); + uint8_t ack = digitalRead(Sm2135.data); + pinMode(Sm2135.data, OUTPUT); + return ack; +} + +void Sm2135Send(uint8_t *buffer, uint8_t size) +{ + digitalWrite(Sm2135.data, LOW); + for (uint32_t i = 0; i < size; i++) { + Sm2135Write(buffer[i]); + } + digitalWrite(Sm2135.clk, LOW); + digitalWrite(Sm2135.clk, HIGH); + digitalWrite(Sm2135.data, HIGH); +} + + + +bool Sm2135SetChannels(void) +{ + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + uint8_t data[6]; + + if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) { +# 106 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_04_sm2135.ino" + data[0] = SM2135_ADDR_MC; + data[1] = SM2135_CURRENT; + data[2] = SM2135_CW; + Sm2135Send(data, 3); + delay(1); + data[0] = SM2135_ADDR_C; + data[1] = cur_col[4]; + data[2] = cur_col[3]; + Sm2135Send(data, 3); + } else { + + + + + + + + data[0] = SM2135_ADDR_MC; + data[1] = SM2135_CURRENT; + data[2] = SM2135_RGB; + data[3] = cur_col[1]; + data[4] = cur_col[0]; + data[5] = cur_col[2]; + Sm2135Send(data, 6); + } + + return true; +} + +void Sm2135ModuleSelected(void) +{ + if ((pin[GPIO_SM2135_CLK] < 99) && (pin[GPIO_SM2135_DAT] < 99)) { + Sm2135.clk = pin[GPIO_SM2135_CLK]; + Sm2135.data = pin[GPIO_SM2135_DAT]; + + pinMode(Sm2135.data, OUTPUT); + digitalWrite(Sm2135.data, HIGH); + pinMode(Sm2135.clk, OUTPUT); + digitalWrite(Sm2135.clk, HIGH); + + light_type = LT_RGBWC; + light_flg = XLGT_04; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 Found")); + } +} + + + + + +bool Xlgt04(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Sm2135SetChannels(); + break; + case FUNC_MODULE_INIT: + Sm2135ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" +#ifdef USE_LIGHT +#ifdef USE_SONOFF_L1 + + + + +#define XLGT_05 5 + +#define SONOFF_L1_BUFFER_SIZE 140 + +#define SONOFF_L1_MODE_COLORFUL 1 +#define SONOFF_L1_MODE_COLORFUL_GRADIENT 2 +#define SONOFF_L1_MODE_COLORFUL_BREATH 3 +#define SONOFF_L1_MODE_DIY_GRADIENT 4 +#define SONOFF_L1_MODE_DIY_PULSE 5 +#define SONOFF_L1_MODE_DIY_BREATH 6 +#define SONOFF_L1_MODE_DIY_STROBE 7 +#define SONOFF_L1_MODE_RGB_GRADIENT 8 +#define SONOFF_L1_MODE_RGB_PULSE 9 +#define SONOFF_L1_MODE_RGB_BREATH 10 +#define SONOFF_L1_MODE_RGB_STROBE 11 +#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 + +struct SNFL1 { + uint32_t unlock = 0; + bool receive_ready = true; +} Snfl1; + + + +void SnfL1Send(const char *buffer) +{ + + + Serial.print(buffer); + Serial.write(0x1B); + Serial.flush(); +} + +void SnfL1SerialSendOk(void) +{ + char buffer[16]; + snprintf_P(buffer, sizeof(buffer), PSTR("AT+SEND=ok")); + + SnfL1Send(buffer); +} + +bool SnfL1SerialInput(void) +{ + if (serial_in_byte != 0x1B) { + if (serial_in_byte_counter >= 140) { + serial_in_byte_counter = 0; + } + if (serial_in_byte_counter || (!serial_in_byte_counter && ('A' == serial_in_byte))) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + } else { + serial_in_buffer[serial_in_byte_counter++] = 0x00; + + + + + + + if (!strncmp(serial_in_buffer +3, "RESULT", 6)) { + Snfl1.receive_ready = true; + } + else if (!strncmp(serial_in_buffer +3, "UPDATE", 6)) { + char cmnd_dimmer[20]; + char cmnd_color[20]; + char *end_str; + char *string = serial_in_buffer +10; + char *token = strtok_r(string, ",", &end_str); + + bool color_updated[3] = { false, false, false }; + uint8_t current_color[3]; + memcpy(current_color, Settings.light_color, 3); + + bool switch_state = false; + bool is_power_change = false; + bool is_color_change = false; + bool is_brightness_change = false; + + while (token != nullptr) { + char* end_token; + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); + + if (!strncmp(token2, "\"sequence\"", 10)) { + + + + token = nullptr; + } + + else if (!strncmp(token2, "\"switch\"", 8)) { + switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + + + is_power_change = (switch_state != Light.power); + } + + else if (!strncmp(token2, "\"color", 6)) { + char color_channel_name = token2[6]; + int color_index; + switch(color_channel_name) + { + case 'R': color_index = 0; + break; + case 'G': color_index = 1; + break; + case 'B': color_index = 2; + break; + } + int color_value = atoi(token3); + current_color[color_index] = color_value; + color_updated[color_index] = true; + + bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; + if (all_color_channels_updated) { + + + + + + is_color_change = (Light.power && (memcmp(current_color, Settings.light_color, 3) != 0)); + } + snprintf_P(cmnd_color, sizeof(cmnd_color), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), current_color[0], current_color[1], current_color[2]); + } + + else if (!strncmp(token2, "\"bright\"", 8)) { + uint8_t dimmer = atoi(token3); + + + + is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings.light_dimmer)); + snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer); + } + + token = strtok_r(nullptr, ",", &end_str); + } + + if (is_power_change) { + if (Settings.light_scheme > 0) { + if (!switch_state) { + char cmnd_scheme[20]; + snprintf_P(cmnd_scheme, sizeof(cmnd_scheme), PSTR(D_CMND_SCHEME " 0")); + ExecuteCommand(cmnd_scheme, SRC_SWITCH); + } + } else { + ExecuteCommandPower(1, switch_state, SRC_SWITCH); + } + } + else if (is_brightness_change) { + ExecuteCommand(cmnd_dimmer, SRC_SWITCH); + } + else if (Light.power && is_color_change) { + if (0 == Settings.light_scheme) { + if (Settings.light_fade) { + char cmnd_fade[20]; + snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_FADE " 0")); + ExecuteCommand(cmnd_fade, SRC_SWITCH); + } + ExecuteCommand(cmnd_color, SRC_SWITCH); + } + } + } + + SnfL1SerialSendOk(); + + return true; + } + serial_in_byte = 0; + return false; +} + + + +bool SnfL1SetChannels(void) +{ + if (Snfl1.receive_ready || TimeReached(Snfl1.unlock)) { + + uint8_t *scale_col = (uint8_t*)XdrvMailbox.topic; + + char buffer[140]; + snprintf_P(buffer, sizeof(buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"light_type\":1,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"bright\":%d,\"mode\":%d"), + LocalTime(), millis()%1000, + Light.power ? "on" : "off", + scale_col[0], scale_col[1], scale_col[2], + light_state.getDimmer(), + SONOFF_L1_MODE_COLORFUL); + + SnfL1Send(buffer); + + Snfl1.unlock = millis() + 500; + Snfl1.receive_ready = false; + } + return true; +} + +void SnfL1ModuleSelected(void) +{ + if (SONOFF_L1 == my_module_type) { + if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { + SetSerial(19200, TS_SERIAL_8N1); + + light_type = LT_RGB; + light_flg = XLGT_05; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); + } + } +} + + + + + +bool Xlgt05(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SERIAL: + result = SnfL1SerialInput(); + break; + case FUNC_SET_CHANNELS: + result = SnfL1SetChannels(); + break; + case FUNC_MODULE_INIT: + SnfL1ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_interface.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_interface.ino" +#ifdef USE_LIGHT + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xlgt_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xlgt_func_ptr[])(uint8_t) = { +#endif + +#ifdef XLGT_01 + &Xlgt01, +#endif + +#ifdef XLGT_02 + &Xlgt02, +#endif + +#ifdef XLGT_03 + &Xlgt03, +#endif + +#ifdef XLGT_04 + &Xlgt04, +#endif + +#ifdef XLGT_05 + &Xlgt05, +#endif + +#ifdef XLGT_06 + &Xlgt06, +#endif + +#ifdef XLGT_07 + &Xlgt07, +#endif + +#ifdef XLGT_08 + &Xlgt08, +#endif + +#ifdef XLGT_09 + &Xlgt09, +#endif + +#ifdef XLGT_10 + &Xlgt10, +#endif + +#ifdef XLGT_11 + &Xlgt11, +#endif + +#ifdef XLGT_12 + &Xlgt12, +#endif + +#ifdef XLGT_13 + &Xlgt13, +#endif + +#ifdef XLGT_14 + &Xlgt14, +#endif + +#ifdef XLGT_15 + &Xlgt15, +#endif + +#ifdef XLGT_16 + &Xlgt16 +#endif +}; + +const uint8_t xlgt_present = sizeof(xlgt_func_ptr) / sizeof(xlgt_func_ptr[0]); + +uint8_t xlgt_active = 0; + +bool XlgtCall(uint8_t function) +{ + DEBUG_TRACE_LOG(PSTR("LGT: %d"), function); + + if (FUNC_MODULE_INIT == function) { + for (uint32_t x = 0; x < xlgt_present; x++) { + xlgt_func_ptr[x](function); + if (light_flg) { + xlgt_active = x; + return true; + } + } + } + else if (light_flg) { + return xlgt_func_ptr[xlgt_active](function); + } + return false; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_01_hlw8012.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_01_hlw8012.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_HLW8012 + + + + + + +#define XNRG_01 1 + + +#define HLW_PREF 10000 +#define HLW_UREF 2200 +#define HLW_IREF 4545 + + +#define HJL_PREF 1362 +#define HJL_UREF 822 +#define HJL_IREF 3300 + +#define HLW_POWER_PROBE_TIME 10 +#define HLW_SAMPLE_COUNT 10 + + + +struct HLW { +#ifdef HLW_DEBUG + unsigned long debug[HLW_SAMPLE_COUNT]; +#endif + unsigned long cf_pulse_length = 0; + unsigned long cf_pulse_last_time = 0; + unsigned long cf_power_pulse_length = 0; + + unsigned long cf1_pulse_length = 0; + unsigned long cf1_pulse_last_time = 0; + unsigned long cf1_summed_pulse_length = 0; + unsigned long cf1_pulse_counter = 0; + unsigned long cf1_voltage_pulse_length = 0; + unsigned long cf1_current_pulse_length = 0; + + unsigned long energy_period_counter = 0; + + unsigned long power_ratio = 0; + unsigned long voltage_ratio = 0; + unsigned long current_ratio = 0; + + uint8_t model_type = 0; + uint8_t cf1_timer = 0; + uint8_t power_retry = 0; + bool select_ui_flag = false; + bool ui_flag = true; + bool load_off = true; +} Hlw; + + +#ifndef USE_WS2812_DMA +void HlwCfInterrupt(void) ICACHE_RAM_ATTR; +void HlwCf1Interrupt(void) ICACHE_RAM_ATTR; +#endif + +void HlwCfInterrupt(void) +{ + unsigned long us = micros(); + + if (Hlw.load_off) { + Hlw.cf_pulse_last_time = us; + Hlw.load_off = false; + } else { + Hlw.cf_pulse_length = us - Hlw.cf_pulse_last_time; + Hlw.cf_pulse_last_time = us; + Hlw.energy_period_counter++; + } + Energy.data_valid[0] = 0; +} + +void HlwCf1Interrupt(void) +{ + unsigned long us = micros(); + + Hlw.cf1_pulse_length = us - Hlw.cf1_pulse_last_time; + Hlw.cf1_pulse_last_time = us; + if ((Hlw.cf1_timer > 2) && (Hlw.cf1_timer < 8)) { + Hlw.cf1_summed_pulse_length += Hlw.cf1_pulse_length; +#ifdef HLW_DEBUG + Hlw.debug[Hlw.cf1_pulse_counter] = Hlw.cf1_pulse_length; +#endif + Hlw.cf1_pulse_counter++; + if (HLW_SAMPLE_COUNT == Hlw.cf1_pulse_counter) { + Hlw.cf1_timer = 8; + } + } + Energy.data_valid[0] = 0; +} + + + +void HlwEvery200ms(void) +{ + unsigned long cf1_pulse_length = 0; + unsigned long hlw_w = 0; + unsigned long hlw_u = 0; + unsigned long hlw_i = 0; + + if (micros() - Hlw.cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { + Hlw.cf_pulse_length = 0; + Hlw.load_off = true; + } + Hlw.cf_power_pulse_length = Hlw.cf_pulse_length; + + if (Hlw.cf_power_pulse_length && Energy.power_on && !Hlw.load_off) { + hlw_w = (Hlw.power_ratio * Settings.energy_power_calibration) / Hlw.cf_power_pulse_length ; + Energy.active_power[0] = (float)hlw_w / 10; + Hlw.power_retry = 1; + } else { + if (Hlw.power_retry) { + Hlw.power_retry--; + } else { + Energy.active_power[0] = 0; + } + } + + if (pin[GPIO_NRG_CF1] < 99) { + Hlw.cf1_timer++; + if (Hlw.cf1_timer >= 8) { + Hlw.cf1_timer = 0; + Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; + DigitalWrite(GPIO_NRG_SEL, Hlw.select_ui_flag); + + if (Hlw.cf1_pulse_counter) { + cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter; + } + +#ifdef HLW_DEBUG + + char stemp[100]; + stemp[0] = '\0'; + for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, Hlw.debug[i]); + } + for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { + for (uint32_t j = i + 1; j < Hlw.cf1_pulse_counter; j++) { + if (Hlw.debug[i] > Hlw.debug[j]) { + std::swap(Hlw.debug[i], Hlw.debug[j]); + } + } + } + unsigned long median = Hlw.debug[(Hlw.cf1_pulse_counter +1) / 2]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), + Hlw.cf_power_pulse_length , Hlw.select_ui_flag, Hlw.cf1_pulse_counter, stemp, Hlw.cf1_summed_pulse_length, cf1_pulse_length, median); +#endif + + if (Hlw.select_ui_flag == Hlw.ui_flag) { + Hlw.cf1_voltage_pulse_length = cf1_pulse_length; + + if (Hlw.cf1_voltage_pulse_length && Energy.power_on) { + hlw_u = (Hlw.voltage_ratio * Settings.energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; + Energy.voltage[0] = (float)hlw_u / 10; + } else { + Energy.voltage[0] = 0; + } + + } else { + Hlw.cf1_current_pulse_length = cf1_pulse_length; + + if (Hlw.cf1_current_pulse_length && Energy.active_power[0]) { + hlw_i = (Hlw.current_ratio * Settings.energy_current_calibration) / Hlw.cf1_current_pulse_length; + Energy.current[0] = (float)hlw_i / 1000; + } else { + Energy.current[0] = 0; + } + + } + Hlw.cf1_summed_pulse_length = 0; + Hlw.cf1_pulse_counter = 0; + } + } +} + +void HlwEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Hlw.cf1_voltage_pulse_length = 0; + Hlw.cf1_current_pulse_length = 0; + Hlw.cf_power_pulse_length = 0; + } else { + unsigned long hlw_len; + + if (Hlw.energy_period_counter) { + hlw_len = 10000 / Hlw.energy_period_counter; + Hlw.energy_period_counter = 0; + if (hlw_len) { + Energy.kWhtoday_delta += ((Hlw.power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; + EnergyUpdateToday(); + } + } + } +} + +void HlwSnsInit(void) +{ + if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { + Settings.energy_power_calibration = HLW_PREF_PULSE; + Settings.energy_voltage_calibration = HLW_UREF_PULSE; + Settings.energy_current_calibration = HLW_IREF_PULSE; + } + + if (Hlw.model_type) { + Hlw.power_ratio = HJL_PREF; + Hlw.voltage_ratio = HJL_UREF; + Hlw.current_ratio = HJL_IREF; + } else { + Hlw.power_ratio = HLW_PREF; + Hlw.voltage_ratio = HLW_UREF; + Hlw.current_ratio = HLW_IREF; + } + + if (pin[GPIO_NRG_SEL] < 99) { + pinMode(pin[GPIO_NRG_SEL], OUTPUT); + digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); + } + if (pin[GPIO_NRG_CF1] < 99) { + pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); + attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); + } + pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); + attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); +} + +void HlwDrvInit(void) +{ + Hlw.model_type = 0; + if (pin[GPIO_HJL_CF] < 99) { + pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF]; + pin[GPIO_HJL_CF] = 99; + Hlw.model_type = 1; + } + + if (pin[GPIO_HLW_CF] < 99) { + + Hlw.ui_flag = true; + if (pin[GPIO_NRG_SEL_INV] < 99) { + pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; + pin[GPIO_NRG_SEL_INV] = 99; + Hlw.ui_flag = false; + } + + if (pin[GPIO_NRG_CF1] < 99) { + if (99 == pin[GPIO_NRG_SEL]) { + Energy.current_available = false; + } + } else { + Energy.current_available = false; + Energy.voltage_available = false; + } + + energy_flg = XNRG_01; + } +} + +bool HlwCommand(void) +{ + bool serviced = true; + + if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) { + + } + else if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) { + Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio; + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) { + Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio; + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) { + Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg01(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_200_MSECOND: + HlwEvery200ms(); + break; + case FUNC_ENERGY_EVERY_SECOND: + HlwEverySecond(); + break; + case FUNC_COMMAND: + result = HlwCommand(); + break; + case FUNC_INIT: + HlwSnsInit(); + break; + case FUNC_PRE_INIT: + HlwDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_02_cse7766.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_02_cse7766.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_CSE7766 + + + + + + + +#define XNRG_02 2 + +#define CSE_MAX_INVALID_POWER 128 + +#define CSE_NOT_CALIBRATED 0xAA + +#define CSE_PULSES_NOT_INITIALIZED -1 + +#define CSE_PREF 1000 +#define CSE_UREF 100 + +#define CSE_BUFFER_SIZE 25 + +#include + +TasmotaSerial *CseSerial = nullptr; + +struct CSE { + long voltage_cycle = 0; + long current_cycle = 0; + long power_cycle = 0; + long power_cycle_first = 0; + long cf_pulses = 0; + long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + + int byte_counter = 0; + uint8_t *rx_buffer = nullptr; + uint8_t power_invalid = 0; + bool received = false; +} Cse; + +void CseReceived(void) +{ + + + + + + + uint8_t header = Cse.rx_buffer[0]; + if ((header & 0xFC) == 0xFC) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); + return; + } + + + if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { + long voltage_coefficient = 191200; + if (CSE_NOT_CALIBRATED != header) { + voltage_coefficient = Cse.rx_buffer[2] << 16 | Cse.rx_buffer[3] << 8 | Cse.rx_buffer[4]; + } + Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; + } + if (HLW_IREF_PULSE == Settings.energy_current_calibration) { + long current_coefficient = 16140; + if (CSE_NOT_CALIBRATED != header) { + current_coefficient = Cse.rx_buffer[8] << 16 | Cse.rx_buffer[9] << 8 | Cse.rx_buffer[10]; + } + Settings.energy_current_calibration = current_coefficient; + } + if (HLW_PREF_PULSE == Settings.energy_power_calibration) { + long power_coefficient = 5364000; + if (CSE_NOT_CALIBRATED != header) { + power_coefficient = Cse.rx_buffer[14] << 16 | Cse.rx_buffer[15] << 8 | Cse.rx_buffer[16]; + } + Settings.energy_power_calibration = power_coefficient / CSE_PREF; + } + + uint8_t adjustement = Cse.rx_buffer[20]; + Cse.voltage_cycle = Cse.rx_buffer[5] << 16 | Cse.rx_buffer[6] << 8 | Cse.rx_buffer[7]; + Cse.current_cycle = Cse.rx_buffer[11] << 16 | Cse.rx_buffer[12] << 8 | Cse.rx_buffer[13]; + Cse.power_cycle = Cse.rx_buffer[17] << 16 | Cse.rx_buffer[18] << 8 | Cse.rx_buffer[19]; + Cse.cf_pulses = Cse.rx_buffer[21] << 8 | Cse.rx_buffer[22]; + + if (Energy.power_on) { + if (adjustement & 0x40) { + Energy.voltage[0] = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle; + } + if (adjustement & 0x10) { + Cse.power_invalid = 0; + if ((header & 0xF2) == 0xF2) { + Energy.active_power[0] = 0; + } else { + if (0 == Cse.power_cycle_first) { Cse.power_cycle_first = Cse.power_cycle; } + if (Cse.power_cycle_first != Cse.power_cycle) { + Cse.power_cycle_first = -1; + Energy.active_power[0] = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle; + } else { + Energy.active_power[0] = 0; + } + } + } else { + if (Cse.power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { + Cse.power_invalid++; + } else { + Cse.power_cycle_first = 0; + Energy.active_power[0] = 0; + } + } + if (adjustement & 0x20) { + if (0 == Energy.active_power[0]) { + Energy.current[0] = 0; + } else { + Energy.current[0] = (float)Settings.energy_current_calibration / (float)Cse.current_cycle; + } + } + } else { + Cse.power_cycle_first = 0; + Energy.voltage[0] = 0; + Energy.active_power[0] = 0; + Energy.current[0] = 0; + } +} + +bool CseSerialInput(void) +{ + while (CseSerial->available()) { + yield(); + uint8_t serial_in_byte = CseSerial->read(); + + if (Cse.received) { + Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; + if (24 == Cse.byte_counter) { + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Cse.rx_buffer, 24); + + uint8_t checksum = 0; + for (uint32_t i = 2; i < 23; i++) { checksum += Cse.rx_buffer[i]; } + if (checksum == Cse.rx_buffer[23]) { + Energy.data_valid[0] = 0; + CseReceived(); + Cse.received = false; + return true; + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); + do { + memmove(Cse.rx_buffer, Cse.rx_buffer +1, 24); + Cse.byte_counter--; + } while ((Cse.byte_counter > 2) && (0x5A != Cse.rx_buffer[1])); + if (0x5A != Cse.rx_buffer[1]) { + Cse.received = false; + Cse.byte_counter = 0; + } + } + } + } else { + if ((0x5A == serial_in_byte) && (1 == Cse.byte_counter)) { + Cse.received = true; + } else { + Cse.byte_counter = 0; + } + Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; + } + } +} + + + +void CseEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Cse.voltage_cycle = 0; + Cse.current_cycle = 0; + Cse.power_cycle = 0; + } else { + long cf_frequency = 0; + + if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) { + Cse.cf_pulses_last_time = Cse.cf_pulses; + } else { + if (Cse.cf_pulses < Cse.cf_pulses_last_time) { + cf_frequency = (65536 - Cse.cf_pulses_last_time) + Cse.cf_pulses; + } else { + cf_frequency = Cse.cf_pulses - Cse.cf_pulses_last_time; + } + if (cf_frequency && Energy.active_power[0]) { + unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; + + + + if (delta <= (4000*100/36) * 10 ) { + Cse.cf_pulses_last_time = Cse.cf_pulses; + Energy.kWhtoday_delta += delta; + } + else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow")); + Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + } + EnergyUpdateToday(); + } + } + } +} + +void CseSnsInit(void) +{ + + + CseSerial = new TasmotaSerial(pin[GPIO_CSE7766_RX], -1, 1); + if (CseSerial->begin(4800, 2)) { + if (CseSerial->hardwareSerial()) { + SetSerial(4800, TS_SERIAL_8E1); + ClaimSerial(); + } + if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { + Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; + } + Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER]; + } else { + energy_flg = ENERGY_NONE; + } +} + +void CseDrvInit(void) +{ + Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); + if (Cse.rx_buffer != nullptr) { + + if (pin[GPIO_CSE7766_RX] < 99) { + energy_flg = XNRG_02; + } + } +} + +bool CseCommand(void) +{ + bool serviced = true; + + if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.power_cycle) { + Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF; + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.voltage_cycle) { + Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF; + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.current_cycle) { + Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + if (CseSerial) { CseSerialInput(); } + break; + case FUNC_ENERGY_EVERY_SECOND: + CseEverySecond(); + break; + case FUNC_COMMAND: + result = CseCommand(); + break; + case FUNC_INIT: + CseSnsInit(); + break; + case FUNC_PRE_INIT: + CseDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_03_pzem004t.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_03_pzem004t.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM004T +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_03_pzem004t.ino" +#define XNRG_03 3 + +const uint32_t PZEM_STABILIZE = 30; + +#include + +TasmotaSerial *PzemSerial = nullptr; + +#define PZEM_VOLTAGE (uint8_t)0xB0 +#define RESP_VOLTAGE (uint8_t)0xA0 + +#define PZEM_CURRENT (uint8_t)0xB1 +#define RESP_CURRENT (uint8_t)0xA1 + +#define PZEM_POWER (uint8_t)0xB2 +#define RESP_POWER (uint8_t)0xA2 + +#define PZEM_ENERGY (uint8_t)0xB3 +#define RESP_ENERGY (uint8_t)0xA3 + +#define PZEM_SET_ADDRESS (uint8_t)0xB4 +#define RESP_SET_ADDRESS (uint8_t)0xA4 + +#define PZEM_POWER_ALARM (uint8_t)0xB5 +#define RESP_POWER_ALARM (uint8_t)0xA5 + +#define PZEM_DEFAULT_READ_TIMEOUT 500 + + + +struct PZEM { + float energy = 0; + float last_energy = 0; + uint8_t send_retry = 0; + uint8_t read_state = 0; + uint8_t phase = 0; + uint8_t address = 0; +} Pzem; + +struct PZEMCommand { + uint8_t command; + uint8_t addr[4]; + uint8_t data; + uint8_t crc; +}; + +uint8_t PzemCrc(uint8_t *data) +{ + uint16_t crc = 0; + for (uint32_t i = 0; i < sizeof(PZEMCommand) -1; i++) { + crc += *data++; + } + return (uint8_t)(crc & 0xFF); +} + +void PzemSend(uint8_t cmd) +{ + PZEMCommand pzem; + + pzem.command = cmd; + pzem.addr[0] = 192; + pzem.addr[1] = 168; + pzem.addr[2] = 1; + pzem.addr[3] = ((PZEM_SET_ADDRESS == cmd) && Pzem.address) ? Pzem.address : 1 + Pzem.phase; + pzem.data = 0; + + uint8_t *bytes = (uint8_t*)&pzem; + pzem.crc = PzemCrc(bytes); + + PzemSerial->flush(); + PzemSerial->write(bytes, sizeof(pzem)); + + Pzem.address = 0; +} + +bool PzemReceiveReady(void) +{ + return PzemSerial->available() >= (int)sizeof(PZEMCommand); +} + +bool PzemRecieve(uint8_t resp, float *data) +{ +# 124 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_03_pzem004t.ino" + uint8_t buffer[sizeof(PZEMCommand)] = { 0 }; + + unsigned long start = millis(); + uint8_t len = 0; + while ((len < sizeof(PZEMCommand)) && (millis() - start < PZEM_DEFAULT_READ_TIMEOUT)) { + if (PzemSerial->available() > 0) { + uint8_t c = (uint8_t)PzemSerial->read(); + if (!len && ((c & 0xF8) != 0xA0)) { + continue; + } + buffer[len++] = c; + } + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, len); + + if (len != sizeof(PZEMCommand)) { + + return false; + } + if (buffer[6] != PzemCrc(buffer)) { + + return false; + } + if (buffer[0] != resp) { + + return false; + } + + switch (resp) { + case RESP_VOLTAGE: + *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 10.0); + break; + case RESP_CURRENT: + *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 100.0); + break; + case RESP_POWER: + *data = (float)(buffer[1] << 8) + buffer[2]; + break; + case RESP_ENERGY: + *data = (float)((uint32_t)buffer[1] << 16) + ((uint16_t)buffer[2] << 8) + buffer[3]; + break; + } + return true; +} + + + +const uint8_t pzem_commands[] { PZEM_SET_ADDRESS, PZEM_VOLTAGE, PZEM_CURRENT, PZEM_POWER, PZEM_ENERGY }; +const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, RESP_POWER, RESP_ENERGY }; + +void PzemEvery250ms(void) +{ + bool data_ready = PzemReceiveReady(); + + if (data_ready) { + float value = 0; + if (PzemRecieve(pzem_responses[Pzem.read_state], &value)) { + Energy.data_valid[Pzem.phase] = 0; + switch (Pzem.read_state) { + case 1: + Energy.voltage[Pzem.phase] = value; + break; + case 2: + Energy.current[Pzem.phase] = value; + break; + case 3: + Energy.active_power[Pzem.phase] = value; + break; + case 4: + Pzem.energy += value; + if (Pzem.phase == Energy.phase_count -1) { + if (Pzem.energy > Pzem.last_energy) { + if (uptime > PZEM_STABILIZE) { + EnergyUpdateTotal(Pzem.energy, false); + } + Pzem.last_energy = Pzem.energy; + } + Pzem.energy = 0; + } + break; + } + Pzem.read_state++; + if (5 == Pzem.read_state) { + Pzem.read_state = 1; + } + + + } + } + + if (0 == Pzem.send_retry || data_ready) { + if (1 == Pzem.read_state) { + if (0 == Pzem.phase) { + Pzem.phase = Energy.phase_count -1; + } else { + Pzem.phase--; + } + + + } + + if (Pzem.address) { + Pzem.read_state = 0; + } + + Pzem.send_retry = 5; + PzemSend(pzem_commands[Pzem.read_state]); + } + else { + Pzem.send_retry--; + if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < PZEM_STABILIZE)) { + Energy.phase_count--; + } + } +} + +void PzemSnsInit(void) +{ + + PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); + if (PzemSerial->begin(9600)) { + if (PzemSerial->hardwareSerial()) { + ClaimSerial(); + } + Energy.phase_count = 3; + Pzem.phase = 0; + Pzem.read_state = 1; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDrvInit(void) +{ + if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_03; + } +} + +bool PzemCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { + Pzem.address = XdrvMailbox.payload; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg03(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (PzemSerial && (uptime > 4)) { PzemEvery250ms(); } + break; + case FUNC_COMMAND: + result = PzemCommand(); + break; + case FUNC_INIT: + PzemSnsInit(); + break; + case FUNC_PRE_INIT: + PzemDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_04_mcp39f501.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_04_mcp39f501.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_MCP39F501 + + + + + + + +#define XNRG_04 4 + +#define MCP_BAUDRATE 4800 +#define MCP_TIMEOUT 4 +#define MCP_CALIBRATION_TIMEOUT 2 + +#define MCP_CALIBRATE_POWER 0x001 +#define MCP_CALIBRATE_VOLTAGE 0x002 +#define MCP_CALIBRATE_CURRENT 0x004 +#define MCP_CALIBRATE_FREQUENCY 0x008 +#define MCP_SINGLE_WIRE_FLAG 0x100 + +#define MCP_START_FRAME 0xA5 +#define MCP_ACK_FRAME 0x06 +#define MCP_ERROR_NAK 0x15 +#define MCP_ERROR_CRC 0x51 + +#define MCP_SINGLE_WIRE 0xAB + +#define MCP_SET_ADDRESS 0x41 + +#define MCP_READ 0x4E +#define MCP_READ_16 0x52 +#define MCP_READ_32 0x44 + +#define MCP_WRITE 0x4D +#define MCP_WRITE_16 0x57 +#define MCP_WRITE_32 0x45 + +#define MCP_SAVE_REGISTERS 0x53 + +#define MCP_CALIBRATION_BASE 0x0028 +#define MCP_CALIBRATION_LEN 52 + +#define MCP_FREQUENCY_REF_BASE 0x0094 +#define MCP_FREQUENCY_GAIN_BASE 0x00AE +#define MCP_FREQUENCY_LEN 4 + +#define MCP_BUFFER_SIZE 60 + +#include +TasmotaSerial *McpSerial = nullptr; + +typedef struct mcp_cal_registers_type { + uint16_t gain_current_rms; + uint16_t gain_voltage_rms; + uint16_t gain_active_power; + uint16_t gain_reactive_power; + sint32_t offset_current_rms; + sint32_t offset_active_power; + sint32_t offset_reactive_power; + sint16_t dc_offset_current; + sint16_t phase_compensation; + uint16_t apparent_power_divisor; + + uint32_t system_configuration; + uint16_t dio_configuration; + uint32_t range; + + uint32_t calibration_current; + uint16_t calibration_voltage; + uint32_t calibration_active_power; + uint32_t calibration_reactive_power; + uint16_t accumulation_interval; +} mcp_cal_registers_type; + +char *mcp_buffer = nullptr; +unsigned long mcp_window = 0; +unsigned long mcp_kWhcounter = 0; +uint32_t mcp_system_configuration = 0x03000000; +uint32_t mcp_active_power; + + +uint32_t mcp_current_rms; +uint16_t mcp_voltage_rms; +uint16_t mcp_line_frequency; + +uint8_t mcp_address = 0; +uint8_t mcp_calibration_active = 0; +uint8_t mcp_init = 0; +uint8_t mcp_timeout = 0; +uint8_t mcp_calibrate = 0; +uint8_t mcp_byte_counter = 0; + + + + + + +uint8_t McpChecksum(uint8_t *data) +{ + uint8_t checksum = 0; + uint8_t offset = 0; + uint8_t len = data[1] -1; + + for (uint32_t i = offset; i < len; i++) { checksum += data[i]; } + return checksum; +} + +unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) +{ + unsigned long result = 0; + unsigned long pow = 1; + + for (uint32_t i = 0; i < size; i++) { + result = result + (uint8_t)data[offset + i] * pow; + pow = pow * 256; + } + return result; +} + +void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) +{ + for (uint32_t i = 0; i < size; i++) { + data[offset + i] = ((value >> (i * 8)) & 0xFF); + } +} + +void McpSend(uint8_t *data) +{ + if (mcp_timeout) { return; } + mcp_timeout = MCP_TIMEOUT; + + data[0] = MCP_START_FRAME; + data[data[1] -1] = McpChecksum(data); + + + + for (uint32_t i = 0; i < data[1]; i++) { + McpSerial->write(data[i]); + } +} + + + +void McpGetAddress(void) +{ + uint8_t data[] = { MCP_START_FRAME, 7, MCP_SET_ADDRESS, 0x00, 0x26, MCP_READ_16, 0x00 }; + + McpSend(data); +} + +void McpAddressReceive(void) +{ + + mcp_address = mcp_buffer[3]; +} + + + +void McpGetCalibration(void) +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; + + uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, (MCP_CALIBRATION_BASE >> 8) & 0xFF, MCP_CALIBRATION_BASE & 0xFF, MCP_READ, MCP_CALIBRATION_LEN, 0x00 }; + + McpSend(data); +} + +void McpParseCalibration(void) +{ + bool action = false; + mcp_cal_registers_type cal_registers; + + + cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); + cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); + cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); + cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); + cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); + cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); + cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); + cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); + cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); + cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); + + cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); + cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); + cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); + + cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); + cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); + cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); + cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); + cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); + + if (mcp_calibrate & MCP_CALIBRATE_POWER) { + cal_registers.calibration_active_power = Settings.energy_power_calibration; + if (McpCalibrationCalc(&cal_registers, 16)) { action = true; } + } + if (mcp_calibrate & MCP_CALIBRATE_VOLTAGE) { + cal_registers.calibration_voltage = Settings.energy_voltage_calibration; + if (McpCalibrationCalc(&cal_registers, 0)) { action = true; } + } + if (mcp_calibrate & MCP_CALIBRATE_CURRENT) { + cal_registers.calibration_current = Settings.energy_current_calibration; + if (McpCalibrationCalc(&cal_registers, 8)) { action = true; } + } + mcp_timeout = 0; + if (action) { McpSetCalibration(&cal_registers); } + + mcp_calibrate = 0; + + Settings.energy_power_calibration = cal_registers.calibration_active_power; + Settings.energy_voltage_calibration = cal_registers.calibration_voltage; + Settings.energy_current_calibration = cal_registers.calibration_current; + + mcp_system_configuration = cal_registers.system_configuration; + + if (mcp_system_configuration & MCP_SINGLE_WIRE_FLAG) { + mcp_system_configuration &= ~MCP_SINGLE_WIRE_FLAG; + McpSetSystemConfiguration(2); + } +} + +bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift) +{ + uint32_t measured; + uint32_t expected; + uint16_t *gain; + uint32_t new_gain; + + if (range_shift == 0) { + measured = mcp_voltage_rms; + expected = cal_registers->calibration_voltage; + gain = &(cal_registers->gain_voltage_rms); + } else if (range_shift == 8) { + measured = mcp_current_rms; + expected = cal_registers->calibration_current; + gain = &(cal_registers->gain_current_rms); + } else if (range_shift == 16) { + measured = mcp_active_power; + expected = cal_registers->calibration_active_power; + gain = &(cal_registers->gain_active_power); + } else { + return false; + } + + if (measured == 0) { + return false; + } + + uint32_t range = (cal_registers->range >> range_shift) & 0xFF; + +calc: + new_gain = (*gain) * expected / measured; + + if (new_gain < 25000) { + range++; + if (measured > 6) { + measured = measured / 2; + goto calc; + } + } + + if (new_gain > 55000) { + range--; + measured = measured * 2; + goto calc; + } + + *gain = new_gain; + uint32_t old_range = (cal_registers->range >> range_shift) & 0xFF; + cal_registers->range = cal_registers->range ^ (old_range << range_shift); + cal_registers->range = cal_registers->range | (range << range_shift); + + return true; +} + + + + + + +void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) +{ + uint8_t data[7 + MCP_CALIBRATION_LEN + 2 + 1]; + + data[1] = sizeof(data); + data[2] = MCP_SET_ADDRESS; + data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; + data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; + + data[5] = MCP_WRITE; + data[6] = MCP_CALIBRATION_LEN; + + McpSetInt(cal_registers->gain_current_rms, data, 0+7, 2); + McpSetInt(cal_registers->gain_voltage_rms, data, 2+7, 2); + McpSetInt(cal_registers->gain_active_power, data, 4+7, 2); + McpSetInt(cal_registers->gain_reactive_power, data, 6+7, 2); + McpSetInt(cal_registers->offset_current_rms, data, 8+7, 4); + McpSetInt(cal_registers->offset_active_power, data, 12+7, 4); + McpSetInt(cal_registers->offset_reactive_power, data, 16+7, 4); + McpSetInt(cal_registers->dc_offset_current, data, 20+7, 2); + McpSetInt(cal_registers->phase_compensation, data, 22+7, 2); + McpSetInt(cal_registers->apparent_power_divisor, data, 24+7, 2); + + McpSetInt(cal_registers->system_configuration, data, 26+7, 4); + McpSetInt(cal_registers->dio_configuration, data, 30+7, 2); + McpSetInt(cal_registers->range, data, 32+7, 4); + + McpSetInt(cal_registers->calibration_current, data, 36+7, 4); + McpSetInt(cal_registers->calibration_voltage, data, 40+7, 2); + McpSetInt(cal_registers->calibration_active_power, data, 42+7, 4); + McpSetInt(cal_registers->calibration_reactive_power, data, 46+7, 4); + McpSetInt(cal_registers->accumulation_interval, data, 50+7, 2); + + data[MCP_CALIBRATION_LEN+7] = MCP_SAVE_REGISTERS; + data[MCP_CALIBRATION_LEN+8] = mcp_address; + + McpSend(data); +} + + + +void McpSetSystemConfiguration(uint16 interval) +{ + + uint8_t data[17]; + + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; + data[ 3] = 0x00; + data[ 4] = 0x42; + data[ 5] = MCP_WRITE_32; + data[ 6] = (mcp_system_configuration >> 24) & 0xFF; + data[ 7] = (mcp_system_configuration >> 16) & 0xFF; + data[ 8] = (mcp_system_configuration >> 8) & 0xFF; + data[ 9] = (mcp_system_configuration >> 0) & 0xFF; + data[10] = MCP_SET_ADDRESS; + data[11] = 0x00; + data[12] = 0x5A; + data[13] = MCP_WRITE_16; + data[14] = (interval >> 8) & 0xFF; + data[15] = (interval >> 0) & 0xFF; + + McpSend(data); +} + + + +void McpGetFrequency(void) +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; + + uint8_t data[] = { MCP_START_FRAME, 11, MCP_SET_ADDRESS, (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF, MCP_FREQUENCY_REF_BASE & 0xFF, MCP_READ_16, + MCP_SET_ADDRESS, (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF, MCP_FREQUENCY_GAIN_BASE & 0xFF, MCP_READ_16, 0x00 }; + + McpSend(data); +} + +void McpParseFrequency(void) +{ + + uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; + uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; + + if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { + line_frequency_ref = Settings.energy_frequency_calibration; + + if ((0xFFFF == mcp_line_frequency) || (0 == gain_line_frequency)) { + mcp_line_frequency = 50000; + gain_line_frequency = 0x8000; + } + gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_line_frequency; + + mcp_timeout = 0; + McpSetFrequency(line_frequency_ref, gain_line_frequency); + } + + Settings.energy_frequency_calibration = line_frequency_ref; + + mcp_calibrate = 0; +} + +void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) +{ + + uint8_t data[17]; + + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; + data[ 3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; + data[ 4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; + + data[ 5] = MCP_WRITE_16; + data[ 6] = (line_frequency_ref >> 8) & 0xFF; + data[ 7] = (line_frequency_ref >> 0) & 0xFF; + + data[ 8] = MCP_SET_ADDRESS; + data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; + data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; + + data[11] = MCP_WRITE_16; + data[12] = (gain_line_frequency >> 8) & 0xFF; + data[13] = (gain_line_frequency >> 0) & 0xFF; + + data[14] = MCP_SAVE_REGISTERS; + data[15] = mcp_address; + + McpSend(data); +} + + + +void McpGetData(void) +{ + uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, 0x00, 0x04, MCP_READ, 22, 0x00 }; + + McpSend(data); +} + +void McpParseData(void) +{ + + + + + + mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); + mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); + mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); + + + mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); + + if (Energy.power_on) { + Energy.data_valid[0] = 0; + Energy.frequency[0] = (float)mcp_line_frequency / 1000; + Energy.voltage[0] = (float)mcp_voltage_rms / 10; + Energy.active_power[0] = (float)mcp_active_power / 100; + if (0 == Energy.active_power[0]) { + Energy.current[0] = 0; + } else { + Energy.current[0] = (float)mcp_current_rms / 10000; + } + } else { + Energy.data_valid[0] = ENERGY_WATCHDOG; + } +} + + + +void McpSerialInput(void) +{ + while ((McpSerial->available()) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { + yield(); + mcp_buffer[mcp_byte_counter++] = McpSerial->read(); + mcp_window = millis(); + } + + + if ((mcp_byte_counter) && (millis() - mcp_window > (24000 / MCP_BAUDRATE) +1)) { + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); + + if (MCP_BUFFER_SIZE == mcp_byte_counter) { + + } + else if (1 == mcp_byte_counter) { + if (MCP_ERROR_CRC == mcp_buffer[0]) { + + mcp_timeout = 0; + } + else if (MCP_ERROR_NAK == mcp_buffer[0]) { + + mcp_timeout = 0; + } + } + else if (MCP_ACK_FRAME == mcp_buffer[0]) { + if (mcp_byte_counter == mcp_buffer[1]) { + + if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); + } else { + if (5 == mcp_buffer[1]) { McpAddressReceive(); } + if (25 == mcp_buffer[1]) { McpParseData(); } + if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } + if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } + } + + } + mcp_timeout = 0; + } + else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { + mcp_timeout = 0; + } + + mcp_byte_counter = 0; + McpSerial->flush(); + } +} + + + +void McpEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + mcp_voltage_rms = 0; + mcp_current_rms = 0; + mcp_active_power = 0; + mcp_line_frequency = 0; + } + + if (mcp_active_power) { + Energy.kWhtoday_delta += ((mcp_active_power * 10) / 36); + EnergyUpdateToday(); + } + + if (mcp_timeout) { + mcp_timeout--; + } + else if (mcp_calibration_active) { + mcp_calibration_active--; + } + else if (mcp_init) { + if (2 == mcp_init) { + McpGetCalibration(); + } + else if (1 == mcp_init) { + McpGetFrequency(); + } + mcp_init--; + } + else if (!mcp_address) { + McpGetAddress(); + } + else { + McpGetData(); + } +} + +void McpSnsInit(void) +{ + + McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); + if (McpSerial->begin(MCP_BAUDRATE)) { + if (McpSerial->hardwareSerial()) { + ClaimSerial(); + mcp_buffer = serial_in_buffer; + } else { + mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); + } + DigitalWrite(GPIO_MCP39F5_RST, 1); + } else { + energy_flg = ENERGY_NONE; + } +} + +void McpDrvInit(void) +{ + if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { + if (pin[GPIO_MCP39F5_RST] < 99) { + pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); + digitalWrite(pin[GPIO_MCP39F5_RST], 0); + } + mcp_calibrate = 0; + mcp_timeout = 2; + mcp_init = 2; + energy_flg = XNRG_04; + } +} + +bool McpCommand(void) +{ + bool serviced = true; + unsigned long value = 0; + + if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_active_power) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100); + if ((value > 100) && (value < 200000)) { + Settings.energy_power_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_POWER; + McpGetCalibration(); + } + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_voltage_rms) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > 1000) && (value < 2600)) { + Settings.energy_voltage_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_VOLTAGE; + McpGetCalibration(); + } + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_current_rms) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > 100) && (value < 80000)) { + Settings.energy_current_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_CURRENT; + McpGetCalibration(); + } + } + } + else if (CMND_FREQUENCYSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_line_frequency) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000); + if ((value > 45000) && (value < 65000)) { + Settings.energy_frequency_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_FREQUENCY; + McpGetFrequency(); + } + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg04(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + if (McpSerial) { McpSerialInput(); } + break; + case FUNC_ENERGY_EVERY_SECOND: + if (McpSerial) { McpEverySecond(); } + break; + case FUNC_COMMAND: + result = McpCommand(); + break; + case FUNC_INIT: + McpSnsInit(); + break; + case FUNC_PRE_INIT: + McpDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_AC +# 33 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +#define XNRG_05 5 + +const uint8_t PZEM_AC_DEVICE_ADDRESS = 0x01; +const uint32_t PZEM_AC_STABILIZE = 30; + +#include +TasmotaModbus *PzemAcModbus; + +struct PZEMAC { + float energy = 0; + float last_energy = 0; + uint8_t send_retry = 0; + uint8_t phase = 0; + uint8_t address = 0; + uint8_t address_step = ADDR_IDLE; +} PzemAc; + +void PzemAcEverySecond(void) +{ + bool data_ready = PzemAcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[30]; + + uint8_t registers = 10; + if (ADDR_RECEIVE == PzemAc.address_step) { + registers = 2; + PzemAc.address_step--; + } + uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, registers); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemAcModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAC: PzemAc %d error %d"), PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, error); + } else { + Energy.data_valid[PzemAc.phase] = 0; + if (10 == registers) { + + + + + + Energy.voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0; + Energy.current[PzemAc.phase] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; + Energy.active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; + Energy.frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0; + Energy.power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0; + + PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); + if (PzemAc.phase == Energy.phase_count -1) { + if (PzemAc.energy > PzemAc.last_energy) { + if (uptime > PZEM_AC_STABILIZE) { + EnergyUpdateTotal(PzemAc.energy, false); + } + PzemAc.last_energy = PzemAc.energy; + } + PzemAc.energy = 0; + } + + } + } + } + + if (0 == PzemAc.send_retry || data_ready) { + if (0 == PzemAc.phase) { + PzemAc.phase = Energy.phase_count -1; + } else { + PzemAc.phase--; + } + PzemAc.send_retry = ENERGY_WATCHDOG; + if (ADDR_SEND == PzemAc.address_step) { + PzemAcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemAc.address); + PzemAc.address_step--; + } else { + PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, 0x04, 0, 10); + } + } + else { + PzemAc.send_retry--; + if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < PZEM_AC_STABILIZE)) { + Energy.phase_count--; + } + } +} + +void PzemAcSnsInit(void) +{ + PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemAcModbus->Begin(9600); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.phase_count = 3; + PzemAc.phase = 0; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemAcDrvInit(void) +{ + if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_05; + } +} + +bool PzemAcCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + PzemAc.address = XdrvMailbox.payload; + PzemAc.address_step = ADDR_SEND; + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg05(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { PzemAcEverySecond(); } + break; + case FUNC_COMMAND: + result = PzemAcCommand(); + break; + case FUNC_INIT: + PzemAcSnsInit(); + break; + case FUNC_PRE_INIT: + PzemAcDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_DC +# 32 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +#define XNRG_06 6 + +const uint8_t PZEM_DC_DEVICE_ADDRESS = 0x01; +const uint32_t PZEM_DC_STABILIZE = 30; + +#include +TasmotaModbus *PzemDcModbus; + +struct PZEMDC { + float energy = 0; + float last_energy = 0; + uint8_t send_retry = 0; + uint8_t channel = 0; + uint8_t address = 0; + uint8_t address_step = ADDR_IDLE; +} PzemDc; + +void PzemDcEverySecond(void) +{ + bool data_ready = PzemDcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[26]; + + uint8_t registers = 8; + if (ADDR_RECEIVE == PzemDc.address_step) { + registers = 2; + PzemDc.address_step--; + } + uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, registers); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemDcModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PDC: PzemDc %d error %d"), PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, error); + } else { + Energy.data_valid[PzemDc.channel] = 0; + if (8 == registers) { + + + + + + Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; + Energy.current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0; + Energy.active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; + + PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); + if (PzemDc.channel == Energy.phase_count -1) { + if (PzemDc.energy > PzemDc.last_energy) { + if (uptime > PZEM_DC_STABILIZE) { + EnergyUpdateTotal(PzemDc.energy, false); + } + PzemDc.last_energy = PzemDc.energy; + } + PzemDc.energy = 0; + } + } + } + } + + if (0 == PzemDc.send_retry || data_ready) { + if (0 == PzemDc.channel) { + PzemDc.channel = Energy.phase_count -1; + } else { + PzemDc.channel--; + } + PzemDc.send_retry = ENERGY_WATCHDOG; + if (ADDR_SEND == PzemDc.address_step) { + PzemDcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemDc.address); + PzemDc.address_step--; + } else { + PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, 0x04, 0, 8); + } + } + else { + PzemDc.send_retry--; + if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < PZEM_DC_STABILIZE)) { + Energy.phase_count--; + } + } +} + +void PzemDcSnsInit(void) +{ + PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemDcModbus->Begin(9600, 2); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.type_dc = true; + Energy.phase_count = 3; + PzemDc.channel = 0; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDcDrvInit(void) +{ + if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_06; + } +} + +bool PzemDcCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + PzemDc.address = XdrvMailbox.payload; + PzemDc.address_step = ADDR_SEND; + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg06(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { PzemDcEverySecond(); } + break; + case FUNC_COMMAND: + result = PzemDcCommand(); + break; + case FUNC_INIT: + PzemDcSnsInit(); + break; + case FUNC_PRE_INIT: + PzemDcDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_07_ade7953.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_07_ade7953.ino" +#ifdef USE_I2C +#ifdef USE_ENERGY_SENSOR +#ifdef USE_ADE7953 +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_07_ade7953.ino" +#define XNRG_07 7 +#define XI2C_07 7 + +#define ADE7953_PREF 1540 +#define ADE7953_UREF 26000 +#define ADE7953_IREF 10000 + +#define ADE7953_ADDR 0x38 + +const uint16_t Ade7953Registers[] { + 0x31B, + 0x313, + 0x311, + 0x315, + 0x31A, + 0x312, + 0x310, + 0x314, + 0x31C, + 0x10E +}; + +struct Ade7953 { + uint32_t voltage_rms = 0; + uint32_t period = 0; + uint32_t current_rms[2] = { 0, 0 }; + uint32_t active_power[2] = { 0, 0 }; + uint8_t init_step = 0; +} Ade7953; + +int Ade7953RegSize(uint16_t reg) +{ + int size = 0; + switch ((reg >> 8) & 0x0F) { + case 0x03: + size++; + case 0x02: + size++; + case 0x01: + size++; + case 0x00: + case 0x07: + case 0x08: + size++; + } + return size; +} + +void Ade7953Write(uint16_t reg, uint32_t val) +{ + int size = Ade7953RegSize(reg); + if (size) { + Wire.beginTransmission(ADE7953_ADDR); + Wire.write((reg >> 8) & 0xFF); + Wire.write(reg & 0xFF); + while (size--) { + Wire.write((val >> (8 * size)) & 0xFF); + } + Wire.endTransmission(); + delayMicroseconds(5); + } +} + +int32_t Ade7953Read(uint16_t reg) +{ + uint32_t response = 0; + + int size = Ade7953RegSize(reg); + if (size) { + Wire.beginTransmission(ADE7953_ADDR); + Wire.write((reg >> 8) & 0xFF); + Wire.write(reg & 0xFF); + Wire.endTransmission(0); + Wire.requestFrom(ADE7953_ADDR, size); + if (size <= Wire.available()) { + for (uint32_t i = 0; i < size; i++) { + response = response << 8 | Wire.read(); + } + } + } + return response; +} + +void Ade7953Init(void) +{ + Ade7953Write(0x102, 0x0004); + Ade7953Write(0x0FE, 0x00AD); + Ade7953Write(0x120, 0x0030); +} + +void Ade7953GetData(void) +{ + int32_t reg[2][4]; + for (uint32_t i = 0; i < sizeof(Ade7953Registers)/sizeof(uint16_t); i++) { + int32_t value = Ade7953Read(Ade7953Registers[i]); + if (8 == i) { + Ade7953.voltage_rms = value; + } else if (9 == i) { + Ade7953.period = value; + } else { + reg[i >> 2][i &3] = value; + } + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"), + Ade7953.voltage_rms, Ade7953.period, + reg[0][0], reg[0][1], reg[0][2], reg[0][3], + reg[1][0], reg[1][1], reg[1][2], reg[1][3]); + + uint32_t apparent_power[2] = { 0, 0 }; + uint32_t reactive_power[2] = { 0, 0 }; + + for (uint32_t channel = 0; channel < 2; channel++) { + Ade7953.current_rms[channel] = reg[channel][0]; + if (Ade7953.current_rms[channel] < 2000) { + Ade7953.current_rms[channel] = 0; + Ade7953.active_power[channel] = 0; + } else { + Ade7953.active_power[channel] = abs(reg[channel][1]); + apparent_power[channel] = abs(reg[channel][2]); + reactive_power[channel] = abs(reg[channel][3]); + } + } + + uint32_t current_rms_sum = Ade7953.current_rms[0] + Ade7953.current_rms[1]; + uint32_t active_power_sum = Ade7953.active_power[0] + Ade7953.active_power[1]; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, C %d, I %d + %d = %d, P %d + %d = %d"), + Ade7953.voltage_rms, Ade7953.period, + Ade7953.current_rms[0], Ade7953.current_rms[1], current_rms_sum, + Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum); + + if (Energy.power_on) { + Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration; + Energy.frequency[0] = 223750.0f / ( (float)Ade7953.period + 1); + + for (uint32_t channel = 0; channel < 2; channel++) { + Energy.data_valid[channel] = 0; + Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings.energy_power_calibration / 10); + Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings.energy_power_calibration / 10); + Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings.energy_power_calibration / 10); + if (0 == Energy.active_power[channel]) { + Energy.current[channel] = 0; + } else { + Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings.energy_current_calibration * 10); + } + } + } else { + Energy.data_valid[0] = ENERGY_WATCHDOG; + Energy.data_valid[1] = ENERGY_WATCHDOG; + } + + if (active_power_sum) { + Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings.energy_power_calibration / 10))) / 3600); + EnergyUpdateToday(); + } +} + +void Ade7953EnergyEverySecond(void) +{ + if (Ade7953.init_step) { + if (1 == Ade7953.init_step) { + Ade7953Init(); + } + Ade7953.init_step--; + } else { + Ade7953GetData(); + } +} + +void Ade7953DrvInit(void) +{ + if (pin[GPIO_ADE7953_IRQ] < 99) { + delay(100); + if (I2cSetDevice(ADE7953_ADDR)) { + if (HLW_PREF_PULSE == Settings.energy_power_calibration) { + Settings.energy_power_calibration = ADE7953_PREF; + Settings.energy_voltage_calibration = ADE7953_UREF; + Settings.energy_current_calibration = ADE7953_IREF; + } + I2cSetActiveFound(ADE7953_ADDR, "ADE7953"); + Ade7953.init_step = 2; + + Energy.phase_count = 2; + Energy.voltage_common = true; + + energy_flg = XNRG_07; + } + } +} + +bool Ade7953Command(void) +{ + bool serviced = true; + + uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0; + uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); + + if (CMND_POWERCAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; } + + } + else if (CMND_VOLTAGECAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_UREF; } + + } + else if (CMND_CURRENTCAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_IREF; } + + } + else if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.active_power[channel]) { + if ((value > 100) && (value < 200000)) { + Settings.energy_power_calibration = (Ade7953.active_power[channel] * 1000) / value; + } + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.voltage_rms) { + if ((value > 10000) && (value < 26000)) { + Settings.energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; + } + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) { + if ((value > 2000) && (value < 1000000)) { + Settings.energy_current_calibration = ((Ade7953.current_rms[channel] * 100) / value) * 100; + } + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg07(uint8_t function) +{ + if (!I2cEnabled(XI2C_07)) { return false; } + + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + Ade7953EnergyEverySecond(); + break; + case FUNC_COMMAND: + result = Ade7953Command(); + break; + case FUNC_PRE_INIT: + Ade7953DrvInit(); + break; + } + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_08_sdm120.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_08_sdm120.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM120 + + + + + + +#define XNRG_08 8 + + +#ifndef SDM120_SPEED + #define SDM120_SPEED 2400 +#endif + +#ifndef SDM120_ADDR + #define SDM120_ADDR 1 +#endif + +#include +TasmotaModbus *Sdm120Modbus; + +const uint8_t sdm120_table = 8; +const uint8_t sdm220_table = 13; + +const uint16_t sdm120_start_addresses[] { + 0x0000, + 0x0006, + 0x000C, + 0x0012, + 0x0018, + 0x001E, + 0x0046, + 0x0156, + + 0X0048, + 0X004A, + 0X004C, + 0X004E, + 0X0024 +}; + +struct SDM120 { + float total_active = 0; + float import_active = NAN; + float import_reactive = 0; + float export_reactive = 0; + float phase_angle = 0; + uint8_t read_state = 0; + uint8_t send_retry = 0; + uint8_t start_address_count = sdm220_table; +} Sdm120; + + + +void SDM120Every250ms(void) +{ + bool data_ready = Sdm120Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm120Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM120 error %d"), error); + } else { + Energy.data_valid[0] = 0; + + + + + float value; + ((uint8_t*)&value)[3] = buffer[3]; + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Sdm120.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.current[0] = value; + break; + + case 2: + Energy.active_power[0] = value; + break; + + case 3: + Energy.apparent_power[0] = value; + break; + + case 4: + Energy.reactive_power[0] = value; + break; + + case 5: + Energy.power_factor[0] = value; + break; + + case 6: + Energy.frequency[0] = value; + break; + + case 7: + Sdm120.total_active = value; + break; + + case 8: + Sdm120.import_active = value; + break; + + case 9: + Energy.export_active = value; + break; + + case 10: + Sdm120.import_reactive = value; + break; + + case 11: + Sdm120.export_reactive = value; + break; + + case 12: + Sdm120.phase_angle = value; + break; + } + + Sdm120.read_state++; + if (Sdm120.read_state == Sdm120.start_address_count) { + Sdm120.read_state = 0; + + if (Sdm120.start_address_count > sdm120_table) { + if (!isnan(Sdm120.import_active)) { + Sdm120.total_active = Sdm120.import_active; + } else { + Sdm120.start_address_count = sdm120_table; + } + } + EnergyUpdateTotal(Sdm120.total_active, true); + } + } + } + + if (0 == Sdm120.send_retry || data_ready) { + Sdm120.send_retry = 5; + Sdm120Modbus->Send(SDM120_ADDR, 0x04, sdm120_start_addresses[Sdm120.read_state], 2); + } else { + Sdm120.send_retry--; + } +} + +void Sdm120SnsInit(void) +{ + Sdm120Modbus = new TasmotaModbus(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX]); + uint8_t result = Sdm120Modbus->Begin(SDM120_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Sdm120DrvInit(void) +{ + if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { + energy_flg = XNRG_08; + } +} + +void Sdm220Reset(void) +{ + if (isnan(Sdm120.import_active)) { return; } + + Sdm120.import_active = 0; + Sdm120.import_reactive = 0; + Sdm120.export_reactive = 0; + Sdm120.phase_angle = 0; +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_SDM220[] PROGMEM = + "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}"; +#endif + +void Sdm220Show(bool json) +{ + if (isnan(Sdm120.import_active)) { return; } + + char import_active_chr[FLOATSZ]; + dtostrfd(Sdm120.import_active, Settings.flag2.energy_resolution, import_active_chr); + char import_reactive_chr[FLOATSZ]; + dtostrfd(Sdm120.import_reactive, Settings.flag2.energy_resolution, import_reactive_chr); + char export_reactive_chr[FLOATSZ]; + dtostrfd(Sdm120.export_reactive, Settings.flag2.energy_resolution, export_reactive_chr); + char phase_angle_chr[FLOATSZ]; + dtostrfd(Sdm120.phase_angle, 2, phase_angle_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s"), + import_active_chr, import_reactive_chr, export_reactive_chr, phase_angle_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_ENERGY_SDM220, import_reactive_chr, export_reactive_chr, phase_angle_chr); +#endif + } +} + + + + + +bool Xnrg08(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { SDM120Every250ms(); } + break; + case FUNC_JSON_APPEND: + Sdm220Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sdm220Show(0); + break; +#endif + case FUNC_ENERGY_RESET: + Sdm220Reset(); + break; + case FUNC_INIT: + Sdm120SnsInit(); + break; + case FUNC_PRE_INIT: + Sdm120DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_09_dds2382.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_09_dds2382.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_DDS2382 + + + + + + +#define XNRG_09 9 + +#ifndef DDS2382_SPEED +#define DDS2382_SPEED 9600 +#endif +#ifndef DDS2382_ADDR +#define DDS2382_ADDR 1 +#endif + +#include +TasmotaModbus *Dds2382Modbus; + +uint8_t Dds2382_send_retry = 0; + +void Dds2382EverySecond(void) +{ + bool data_ready = Dds2382Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[46]; + + uint32_t error = Dds2382Modbus->ReceiveBuffer(buffer, 18); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Dds2382Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "DDS2382 response error %d"), error); + } else { + Energy.data_valid[0] = 0; +# 67 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_09_dds2382.ino" + Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0; + Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0; + Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]); + Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]); + Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; + Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; + uint8_t offset = 11; + if (Settings.flag3.dds2382_model) { + offset = 19; + } + Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; + float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; + + EnergyUpdateTotal(import_active, true); + } + } + + if (0 == Dds2382_send_retry || data_ready) { + Dds2382_send_retry = 5; + Dds2382Modbus->Send(DDS2382_ADDR, 0x03, 0, 18); + } else { + Dds2382_send_retry--; + } +} + +void Dds2382SnsInit(void) +{ + Dds2382Modbus = new TasmotaModbus(pin[GPIO_DDS2382_RX], pin[GPIO_DDS2382_TX]); + uint8_t result = Dds2382Modbus->Begin(DDS2382_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Dds2382DrvInit(void) +{ + if ((pin[GPIO_DDS2382_RX] < 99) && (pin[GPIO_DDS2382_TX] < 99)) { + energy_flg = XNRG_09; + } +} + + + + + +bool Xnrg09(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { Dds2382EverySecond(); } + break; + case FUNC_INIT: + Dds2382SnsInit(); + break; + case FUNC_PRE_INIT: + Dds2382DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_10_sdm630.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_10_sdm630.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM630 + + + + + + +#define XNRG_10 10 + + +#ifndef SDM630_SPEED + #define SDM630_SPEED 9600 +#endif + +#ifndef SDM630_ADDR + #define SDM630_ADDR 1 +#endif + +#include +TasmotaModbus *Sdm630Modbus; + +const uint16_t sdm630_start_addresses[] { + 0x0000, + 0x0002, + 0x0004, + 0x0006, + 0x0008, + 0x000A, + 0x000C, + 0x000E, + 0x0010, + 0x0018, + 0x001A, + 0x001C, + 0x001E, + 0x0020, + 0x0022, + 0x0156 +}; + +struct SDM630 { + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Sdm630; + + + +void SDM630Every250ms(void) +{ + bool data_ready = Sdm630Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Sdm630Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm630Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM630 error %d"), error); + } else { + Energy.data_valid[0] = 0; + Energy.data_valid[1] = 0; + Energy.data_valid[2] = 0; + + + + + float value; + ((uint8_t*)&value)[3] = buffer[3]; + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Sdm630.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.voltage[1] = value; + break; + + case 2: + Energy.voltage[2] = value; + break; + + case 3: + Energy.current[0] = value; + break; + + case 4: + Energy.current[1] = value; + break; + + case 5: + Energy.current[2] = value; + break; + + case 6: + Energy.active_power[0] = value; + break; + + case 7: + Energy.active_power[1] = value; + break; + + case 8: + Energy.active_power[2] = value; + break; + + case 9: + Energy.reactive_power[0] = value; + break; + + case 10: + Energy.reactive_power[1] = value; + break; + + case 11: + Energy.reactive_power[2] = value; + break; + + case 12: + Energy.power_factor[0] = value; + break; + + case 13: + Energy.power_factor[1] = value; + break; + + case 14: + Energy.power_factor[2] = value; + break; + + case 15: + EnergyUpdateTotal(value, true); + break; + } + + Sdm630.read_state++; + if (sizeof(sdm630_start_addresses)/2 == Sdm630.read_state) { + Sdm630.read_state = 0; + } + } + } + + if (0 == Sdm630.send_retry || data_ready) { + Sdm630.send_retry = 5; + Sdm630Modbus->Send(SDM630_ADDR, 0x04, sdm630_start_addresses[Sdm630.read_state], 2); + } else { + Sdm630.send_retry--; + } +} + +void Sdm630SnsInit(void) +{ + Sdm630Modbus = new TasmotaModbus(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX]); + uint8_t result = Sdm630Modbus->Begin(SDM630_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.phase_count = 3; + } else { + energy_flg = ENERGY_NONE; + } +} + +void Sdm630DrvInit(void) +{ + if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { + energy_flg = XNRG_10; + } +} + + + + + +bool Xnrg10(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { SDM630Every250ms(); } + break; + case FUNC_INIT: + Sdm630SnsInit(); + break; + case FUNC_PRE_INIT: + Sdm630DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_11_ddsu666.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_11_ddsu666.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_DDSU666 + + + + +#define XNRG_11 11 + + +#ifndef DDSU666_SPEED + #define DDSU666_SPEED 9600 +#endif + +#ifndef DDSU666_ADDR + #define DDSU666_ADDR 1 +#endif + +#include +TasmotaModbus *Ddsu666Modbus; + +const uint16_t Ddsu666_start_addresses[] { + 0x2000, + 0x2002, + 0x2004, + 0x2006, + 0x200A, + 0x200E, + 0X4000, + 0X400A, +}; + +struct DDSU666 { + float import_active = NAN; + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Ddsu666; + + + +void DDSU666Every250ms(void) +{ + bool data_ready = Ddsu666Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Ddsu666Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Ddsu666Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: Ddsu666 error %d"), error); + } else { + Energy.data_valid[0] = 0; + + + + + float value; + ((uint8_t*)&value)[3] = buffer[3]; + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Ddsu666.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.current[0] = value; + break; + + case 2: + Energy.active_power[0] = value * 1000; + break; + + case 3: + Energy.reactive_power[0] = value * 1000; + break; + + case 4: + Energy.power_factor[0] = value; + break; + + case 5: + Energy.frequency[0] = value; + break; + + case 6: + Ddsu666.import_active = value; + break; + + case 7: + Energy.export_active = value; + break; + } + + Ddsu666.read_state++; + + if (Ddsu666.read_state == 8) { + Ddsu666.read_state = 0; + EnergyUpdateTotal(Ddsu666.import_active, true); + } + } + } + + if (0 == Ddsu666.send_retry || data_ready) { + Ddsu666.send_retry = 5; + Ddsu666Modbus->Send(DDSU666_ADDR, 0x04, Ddsu666_start_addresses[Ddsu666.read_state], 2); + } else { + Ddsu666.send_retry--; + } +} + +void Ddsu666SnsInit(void) +{ + Ddsu666Modbus = new TasmotaModbus(pin[GPIO_DDSU666_RX], pin[GPIO_DDSU666_TX]); + uint8_t result = Ddsu666Modbus->Begin(DDSU666_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Ddsu666DrvInit(void) +{ + if ((pin[GPIO_DDSU666_RX] < 99) && (pin[GPIO_DDSU666_TX] < 99)) { + energy_flg = XNRG_11; + } +} + + + + + +bool Xnrg11(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { DDSU666Every250ms(); } + break; + case FUNC_INIT: + Ddsu666SnsInit(); + break; + case FUNC_PRE_INIT: + Ddsu666DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_12_solaxX1.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_12_solaxX1.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SOLAX_X1 + + + + +#define XNRG_12 12 + +#ifndef SOLAXX1_SPEED +#define SOLAXX1_SPEED 9600 +#endif + +#define INVERTER_ADDRESS 0x0A + +#define D_SOLAX_X1 "SolaxX1" + +#include + +enum solaxX1_Error +{ + solaxX1_ERR_NO_ERROR, + solaxX1_ERR_CRC_ERROR +}; + +union { + uint32_t ErrMessage; + struct { + + uint8_t TzProtectFault:1; + uint8_t MainsLostFault:1; + uint8_t GridVoltFault:1; + uint8_t GridFreqFault:1; + uint8_t PLLLostFault:1; + uint8_t BusVoltFault:1; + uint8_t ErrBit06:1; + uint8_t OciFault:1; + + uint8_t Dci_OCP_Fault:1; + uint8_t ResidualCurrentFault:1; + uint8_t PvVoltFault:1; + uint8_t Ac10Mins_Voltage_Fault:1; + uint8_t IsolationFault:1; + uint8_t TemperatureOverFault:1; + uint8_t FanFault:1; + uint8_t ErrBit15:1; + + uint8_t SpiCommsFault:1; + uint8_t SciCommsFault:1; + uint8_t ErrBit18:1; + uint8_t InputConfigFault:1; + uint8_t EepromFault:1; + uint8_t RelayFault:1; + uint8_t SampleConsistenceFault:1; + uint8_t ResidualCurrent_DeviceFault:1; + + uint8_t ErrBit24:1; + uint8_t ErrBit25:1; + uint8_t ErrBit26:1; + uint8_t ErrBit27:1; + uint8_t ErrBit28:1; + uint8_t DCI_DeviceFault:1; + uint8_t OtherDeviceFault:1; + uint8_t ErrBit31:1; + }; +} ErrCode; + +const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; + +const char kSolaxError[] PROGMEM = + D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" + D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; + + + +TasmotaSerial *solaxX1Serial; + +uint8_t solaxX1_Init = 1; + +struct SOLAXX1 { + float temperature = 0; + float energy_today = 0; + float dc1_voltage = 0; + float dc2_voltage = 0; + float dc1_current = 0; + float dc2_current = 0; + float energy_total = 0; + float runtime_total = 0; + float dc1_power = 0; + float dc2_power = 0; + + uint8_t status = 0; + uint32_t errorCode = 0; +} solaxX1; + +union { + uint8_t status; + struct { + uint8_t freeBit7:1; + uint8_t freeBit6:1; + uint8_t freeBit5:1; + uint8_t queryOffline:1; + uint8_t queryOfflineSend:1; + uint8_t hasAddress:1; + uint8_t inverterAddressSend:1; + uint8_t inverterSnReceived:1; + }; +} protocolStatus; + +uint8_t header[2] = {0xAA, 0x55}; +uint8_t source[2] = {0x00, 0x00}; +uint8_t destination[2] = {0x00, 0x00}; +uint8_t controlCode[1] = {0x00}; +uint8_t functionCode[1] = {0x00}; +uint8_t dataLength[1] = {0x00}; +uint8_t data[16] = {0}; + +uint8_t message[30]; + + + +bool solaxX1_RS485ReceiveReady(void) +{ + return (solaxX1Serial->available() > 1); +} + +void solaxX1_RS485Send(uint16_t msgLen) +{ + memcpy(message, header, 2); + memcpy(message + 2, source, 2); + memcpy(message + 4, destination, 2); + memcpy(message + 6, controlCode, 1); + memcpy(message + 7, functionCode, 1); + memcpy(message + 8, dataLength, 1); + memcpy(message + 9, data, sizeof(data)); + uint16_t crc = solaxX1_calculateCRC(message, msgLen); + + while (solaxX1Serial->available() > 0) + { + solaxX1Serial->read(); + } + + solaxX1Serial->flush(); + solaxX1Serial->write(message, msgLen); + solaxX1Serial->write(highByte(crc)); + solaxX1Serial->write(lowByte(crc)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen); +} + +uint8_t solaxX1_RS485Receive(uint8_t *value) +{ + uint8_t len = 0; + + while (solaxX1Serial->available() > 0) + { + value[len++] = (uint8_t)solaxX1Serial->read(); + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, value, len); + + uint16_t crc = solaxX1_calculateCRC(value, len - 2); + + if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) + { + return solaxX1_ERR_NO_ERROR; + } + else + { + return solaxX1_ERR_CRC_ERROR; + } +} + +uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) +{ + uint8_t i; + uint16_t wChkSum; + wChkSum = 0; + + for (i = 0; i < bLen; i++) + { + wChkSum = wChkSum + bExternTxPackage[i]; + } + return wChkSum; +} + +void solaxX1_SendInverterAddress(void) +{ + source[0] = 0x00; + destination[0] = 0x00; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x01; + dataLength[0] = 0x0F; + data[14] = INVERTER_ADDRESS; + solaxX1_RS485Send(24); +} + +void solaxX1_QueryLiveData(void) +{ + source[0] = 0x01; + destination[0] = 0x00; + destination[1] = INVERTER_ADDRESS; + controlCode[0] = 0x11; + functionCode[0] = 0x02; + dataLength[0] = 0x00; + solaxX1_RS485Send(9); +} + +uint8_t solaxX1_ParseErrorCode(uint32_t code){ + ErrCode.ErrMessage = code; + + if (code == 0) return 0; + if (ErrCode.MainsLostFault) return 1; + if (ErrCode.GridVoltFault) return 2; + if (ErrCode.GridFreqFault) return 3; + if (ErrCode.PvVoltFault) return 4; + if (ErrCode.IsolationFault) return 5; + if (ErrCode.TemperatureOverFault) return 6; + if (ErrCode.FanFault) return 7; + if (ErrCode.OtherDeviceFault) return 8; +} + + + +uint8_t solaxX1_send_retry = 0; +uint8_t solaxX1_nodata_count = 0; + +void solaxX1250MSecond(void) +{ + uint8_t value[61] = {0}; + bool data_ready = solaxX1_RS485ReceiveReady(); + + if (protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + if (data_ready) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); + } + else + { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 12; + Energy.data_valid[0] = 0; + + solaxX1.temperature = (float)((value[9] << 8) | value[10]); + solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; + solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; + solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; + solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; + solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; + Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; + Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; + Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; + Energy.active_power[0] = (float)((value[27] << 8) | value[28]); + + solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; + solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); + solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); + + + + + + + + solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); + + solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; + solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; + + solaxX1_QueryLiveData(); + EnergyUpdateTotal(solaxX1.energy_total, true); + } + } + + if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { + solaxX1_send_retry = 12; + solaxX1_QueryLiveData(); + } + + + + if (255 == solaxX1_nodata_count) { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 12; + } + } + else + { + if ((solaxX1_nodata_count % 4) == 0) { DEBUG_SENSOR_LOG(PSTR("SX1: No Data count: %d"), solaxX1_nodata_count); } + if (solaxX1_nodata_count < 10 * 4) + { + solaxX1_nodata_count++; + } + else if (255 != solaxX1_nodata_count) + { + + solaxX1_nodata_count = 255; + solaxX1_send_retry = 12; + protocolStatus.status = 0b00001000; + Energy.data_valid[0] = ENERGY_WATCHDOG; + + solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0; + solaxX1.dc2_power = solaxX1.status = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; + + } + } + + if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + if (data_ready) + { + + if (protocolStatus.inverterAddressSend) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error")); + } + else + { + if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Set hasAddress")); + protocolStatus.status = 0b00100000; + } + } + } + + + if (protocolStatus.queryOfflineSend) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error")); + } + else + { + + if (value[6] == 0x10 && value[7] == 0x80 && protocolStatus.inverterSnReceived == false) + { + for (uint8_t i = 9; i <= 22; i++) + { + data[i - 9] = value[i]; + } + solaxX1_SendInverterAddress(); + protocolStatus.status = 0b1100000; + DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); + } + } + } + } + + if (solaxX1_send_retry == 0) + { + if (protocolStatus.queryOfflineSend) + { + protocolStatus.status = 0b00001000; + DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); + } + solaxX1_send_retry = 12; + } + + + if (protocolStatus.queryOffline) + { + + source[0] = 0x01; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x00; + dataLength[0] = 0x00; + solaxX1_RS485Send(9); + protocolStatus.status = 0b00010000; + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); + } + } + + if (!data_ready) + solaxX1_send_retry--; +} + +void solaxX1SnsInit(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SX1: Solax X1 Inverter Init")); + DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); + protocolStatus.status = 0b00100000; + + solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); + if (solaxX1Serial->begin(SOLAXX1_SPEED)) { + if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void solaxX1DrvInit(void) +{ + if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) { + energy_flg = XNRG_12; + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; +#ifdef SOLAXX1_PV2 +const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; +#endif +const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}" + "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" + "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"; +#endif + +void solaxX1Show(bool json) +{ + char solar_power[33]; + dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings.flag2.wattage_resolution, solar_power); + char pv1_voltage[33]; + dtostrfd(solaxX1.dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); + char pv1_current[33]; + dtostrfd(solaxX1.dc1_current, Settings.flag2.current_resolution, pv1_current); + char pv1_power[33]; + dtostrfd(solaxX1.dc1_power, Settings.flag2.wattage_resolution, pv1_power); +#ifdef SOLAXX1_PV2 + char pv2_voltage[33]; + dtostrfd(solaxX1.dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); + char pv2_current[33]; + dtostrfd(solaxX1.dc2_current, Settings.flag2.current_resolution, pv2_current); + char pv2_power[33]; + dtostrfd(solaxX1.dc2_power, Settings.flag2.wattage_resolution, pv2_power); +#endif + char temperature[33]; + dtostrfd(solaxX1.temperature, Settings.flag2.temperature_resolution, temperature); + char runtime[33]; + dtostrfd(solaxX1.runtime_total, 0, runtime); + char status[33]; + GetTextIndexed(status, sizeof(status), solaxX1.status, kSolaxMode); + + if (json) + { + ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), + solar_power, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), + pv2_voltage, pv2_current, pv2_power); +#endif + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), + temperature, runtime, status, solaxX1.errorCode); + +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, solar_power, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); +#endif + WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); + char errorCodeString[33]; + WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, + GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); +#endif + } +} + + + + + +bool Xnrg12(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { solaxX1250MSecond(); } + break; + case FUNC_JSON_APPEND: + solaxX1Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + solaxX1Show(0); + break; +#endif + case FUNC_INIT: + solaxX1SnsInit(); + break; + case FUNC_PRE_INIT: + solaxX1DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_LE01MR +# 71 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +#define XNRG_13 13 + + +#ifndef LE01MR_SPEED + #define LE01MR_SPEED 2400 +#endif + +#ifndef LE01MR_ADDR + #define LE01MR_ADDR 1 +#endif + +#include +TasmotaModbus *FifLEModbus; + +const uint8_t le01mr_table_sz = 9; + +const uint16_t le01mr_register_addresses[] { + + 0x0130, + 0x0131, + 0x0158, + 0x0139, + 0x0140, + 0x0148, + 0x0150, + 0xA000, + 0xA01E +}; + +struct LE01MR { + float total_active = 0; + float total_reactive = 0; + uint8_t read_state = 0; + uint8_t send_retry = 0; + uint8_t start_address_count = le01mr_table_sz; +} Le01mr; + + + +void FifLEEvery250ms(void) +{ + bool data_ready = FifLEModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + uint8_t reg_count = 2; + if (Le01mr.read_state < 3) { + reg_count=1; + } + + uint32_t error = FifLEModbus->ReceiveBuffer(buffer, reg_count); + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, FifLEModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); + } else { + Energy.data_valid[0] = 0; +# 146 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" + uint32_t value_buff = 0; + + if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { + value_buff = ((uint32_t)buffer[3])<<8 | buffer[4]; + } else { + value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; + } + + switch(Le01mr.read_state) { + case 0: + Energy.frequency[0] = value_buff * 0.01f; + break; + + case 1: + Energy.voltage[0] = value_buff * 0.01f; + break; + + case 2: + Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; + break; + + case 3: + Energy.current[0] = value_buff * 0.001f; + break; + + case 4: + Energy.active_power[0] = value_buff * 1.0f; + break; + + case 5: + Energy.reactive_power[0] = value_buff * 1.0f; + break; + + case 6: + Energy.apparent_power[0] = value_buff * 1.0f; + break; + + case 7: + Le01mr.total_active = value_buff * 0.01f; + break; + + case 8: + Le01mr.total_reactive = value_buff * 0.01f; + break; + } + + Le01mr.read_state++; + if (Le01mr.read_state == Le01mr.start_address_count) { + Le01mr.read_state = 0; + + EnergyUpdateTotal(Le01mr.total_active, true); + } + } + } + + if (0 == Le01mr.send_retry || data_ready) { + uint8_t reg_count = 2; + + Le01mr.send_retry = 5; + + if (Le01mr.read_state < 3) reg_count=1; + + FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); + } else { + Le01mr.send_retry--; + } +} + +void FifLESnsInit(void) +{ + FifLEModbus = new TasmotaModbus(pin[GPIO_LE01MR_RX], pin[GPIO_LE01MR_TX]); + uint8_t result = FifLEModbus->Begin(LE01MR_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void FifLEDrvInit(void) +{ + if ((pin[GPIO_LE01MR_RX] < 99) && (pin[GPIO_LE01MR_TX] < 99)) { + energy_flg = XNRG_13; + } +} + +void FifLEReset(void) +{ + Le01mr.total_active = 0; + Le01mr.total_reactive = 0; +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_LE01MR[] PROGMEM = + "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + ; +#endif + +void FifLEShow(bool json) +{ + char total_reactive_chr[FLOATSZ]; + dtostrfd(Le01mr.total_reactive, Settings.flag2.energy_resolution, total_reactive_chr); + char total_active_chr[FLOATSZ]; + dtostrfd(Le01mr.total_active, Settings.flag2.energy_resolution, total_active_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"), + total_active_chr, total_reactive_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_ENERGY_LE01MR, total_active_chr, total_reactive_chr); +#endif + } +} + + + + + +bool Xnrg13(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { + FifLEEvery250ms(); + } + break; + case FUNC_JSON_APPEND: + FifLEShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + FifLEShow(0); + break; +#endif + case FUNC_ENERGY_RESET: + FifLEReset(); + break; + case FUNC_INIT: + FifLESnsInit(); + break; + case FUNC_PRE_INIT: + FifLEDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_interface.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_interface.ino" +#ifdef USE_ENERGY_SENSOR + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xnrg_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xnrg_func_ptr[])(uint8_t) = { +#endif + +#ifdef XNRG_01 + &Xnrg01, +#endif + +#ifdef XNRG_02 + &Xnrg02, +#endif + +#ifdef XNRG_03 + &Xnrg03, +#endif + +#ifdef XNRG_04 + &Xnrg04, +#endif + +#ifdef XNRG_05 + &Xnrg05, +#endif + +#ifdef XNRG_06 + &Xnrg06, +#endif + +#ifdef XNRG_07 + &Xnrg07, +#endif + +#ifdef XNRG_08 + &Xnrg08, +#endif + +#ifdef XNRG_09 + &Xnrg09, +#endif + +#ifdef XNRG_10 + &Xnrg10, +#endif + +#ifdef XNRG_11 + &Xnrg11, +#endif + +#ifdef XNRG_12 + &Xnrg12, +#endif + +#ifdef XNRG_13 + &Xnrg13, +#endif + +#ifdef XNRG_14 + &Xnrg14, +#endif + +#ifdef XNRG_15 + &Xnrg15, +#endif + +#ifdef XNRG_16 + &Xnrg16 +#endif +}; + +const uint8_t xnrg_present = sizeof(xnrg_func_ptr) / sizeof(xnrg_func_ptr[0]); + +uint8_t xnrg_active = 0; + +bool XnrgCall(uint8_t function) +{ + DEBUG_TRACE_LOG(PSTR("NRG: %d"), function); + + if (FUNC_PRE_INIT == function) { + for (uint32_t x = 0; x < xnrg_present; x++) { + xnrg_func_ptr[x](function); + if (energy_flg) { + xnrg_active = x; + return true; + } + } + } + else if (energy_flg) { + return xnrg_func_ptr[xnrg_active](function); + } + return false; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_01_counter.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_01_counter.ino" +#ifdef USE_COUNTER + + + + +#define XSNS_01 1 + +#define D_PRFX_COUNTER "Counter" +#define D_CMND_COUNTERTYPE "Type" +#define D_CMND_COUNTERDEBOUNCE "Debounce" + +const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" + "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE ; + +void (* const CounterCommand[])(void) PROGMEM = { + &CmndCounter, &CmndCounterType, &CmndCounterDebounce }; + +struct COUNTER { + uint32_t timer[MAX_COUNTERS]; + uint8_t no_pullup = 0; + bool any_counter = false; +} Counter; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +void CounterUpdate(uint8_t index) ICACHE_RAM_ATTR; +void CounterUpdate1(void) ICACHE_RAM_ATTR; +void CounterUpdate2(void) ICACHE_RAM_ATTR; +void CounterUpdate3(void) ICACHE_RAM_ATTR; +void CounterUpdate4(void) ICACHE_RAM_ATTR; +#endif + +void CounterUpdate(uint8_t index) +{ + uint32_t time = micros(); + uint32_t debounce_time = time - Counter.timer[index]; + if (debounce_time > Settings.pulse_counter_debounce * 1000) { + Counter.timer[index] = time; + if (bitRead(Settings.pulse_counter_type, index)) { + RtcSettings.pulse_counter[index] = debounce_time; + } else { + RtcSettings.pulse_counter[index]++; + } + } +} + +void CounterUpdate1(void) +{ + CounterUpdate(0); +} + +void CounterUpdate2(void) +{ + CounterUpdate(1); +} + +void CounterUpdate3(void) +{ + CounterUpdate(2); +} + +void CounterUpdate4(void) +{ + CounterUpdate(3); +} + + + +bool CounterPinState(void) +{ + if ((XdrvMailbox.index >= GPIO_CNTR1_NP) && (XdrvMailbox.index < (GPIO_CNTR1_NP + MAX_COUNTERS))) { + bitSet(Counter.no_pullup, XdrvMailbox.index - GPIO_CNTR1_NP); + XdrvMailbox.index -= (GPIO_CNTR1_NP - GPIO_CNTR1); + return true; + } + return false; +} + +void CounterInit(void) +{ + typedef void (*function) () ; + function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; + + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + Counter.any_counter = true; + pinMode(pin[GPIO_CNTR1 +i], bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP); + attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); + } + } +} + +void CounterEverySecond(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + if (bitRead(Settings.pulse_counter_type, i)) { + uint32_t time = micros() - Counter.timer[i]; + if (time > 4200000000) { + RtcSettings.pulse_counter[i] = 4200000000; + } + } + } + } +} + +void CounterSaveState(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; + } + } +} + +void CounterShow(bool json) +{ + bool header = false; + uint8_t dsxflg = 0; + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + char counter[33]; + if (bitRead(Settings.pulse_counter_type, i)) { + dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); + } else { + dsxflg++; + snprintf_P(counter, sizeof(counter), PSTR("%lu"), RtcSettings.pulse_counter[i]); + } + + if (json) { + if (!header) { + ResponseAppend_P(PSTR(",\"COUNTER\":{")); + } + ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); + header = true; +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (1 == dsxflg)) { + DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); + dsxflg++; + } +#endif + if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { + RtcSettings.pulse_counter[i] = 0; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(PSTR("{s}" D_COUNTER "%d{m}%s%s{e}"), + i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); +#endif + } + } + } + if (header) { + ResponseJsonEnd(); + } +} + + + + + +void CmndCounter(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { + if ((XdrvMailbox.data_len > 0) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { + if ((XdrvMailbox.data[0] == '-') || (XdrvMailbox.data[0] == '+')) { + RtcSettings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; + Settings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; + } else { + RtcSettings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; + Settings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + } + ResponseCmndIdxNumber(RtcSettings.pulse_counter[XdrvMailbox.index -1]); + } +} + +void CmndCounterType(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { + bitWrite(Settings.pulse_counter_type, XdrvMailbox.index -1, XdrvMailbox.payload &1); + RtcSettings.pulse_counter[XdrvMailbox.index -1] = 0; + Settings.pulse_counter[XdrvMailbox.index -1] = 0; + } + ResponseCmndIdxNumber(bitRead(Settings.pulse_counter_type, XdrvMailbox.index -1)); + } +} + +void CmndCounterDebounce(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { + Settings.pulse_counter_debounce = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.pulse_counter_debounce); +} + + + + + +bool Xsns01(uint8_t function) +{ + bool result = false; + + if (Counter.any_counter) { + switch (function) { + case FUNC_EVERY_SECOND: + CounterEverySecond(); + break; + case FUNC_JSON_APPEND: + CounterShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + CounterShow(0); + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + case FUNC_SAVE_AT_MIDNIGHT: + CounterSaveState(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kCounterCommands, CounterCommand); + break; + } + } else { + switch (function) { + case FUNC_INIT: + CounterInit(); + break; + case FUNC_PIN_STATE: + result = CounterPinState(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_02_analog.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_02_analog.ino" +#ifndef USE_ADC_VCC + + + + +#define XSNS_02 2 + +#define TO_CELSIUS(x) ((x) - 273.15) +#define TO_KELVIN(x) ((x) + 273.15) + + +#define ANALOG_V33 3.3 +#define ANALOG_T0 TO_KELVIN(25.0) + + + + + +#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 +#define ANALOG_NTC_RESISTANCE 10000 +#define ANALOG_NTC_B_COEFFICIENT 3350 + + + + + +#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 +#define ANALOG_LDR_LUX_CALC_SCALAR 12518931 +#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 +# 58 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_02_analog.ino" +#define ANALOG_CT_FLAGS 0 +#define ANALOG_CT_MULTIPLIER 2146 +#define ANALOG_CT_VOLTAGE 2300 + +#define CT_FLAG_ENERGY_RESET (1 << 0) + +struct { + float temperature = 0; + float current = 0; + float energy = 0; + uint32_t previous_millis = 0; + uint16_t last_value = 0; +} Adc; + +void AdcInit(void) +{ + if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000)) { + if (ADC0_TEMP == my_adc0) { + + Settings.adc_param_type = ADC0_TEMP; + Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_NTC_RESISTANCE; + Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000; + } + else if (ADC0_LIGHT == my_adc0) { + Settings.adc_param_type = ADC0_LIGHT; + Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; + Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; + } + else if (ADC0_RANGE == my_adc0) { + Settings.adc_param_type = ADC0_RANGE; + Settings.adc_param1 = 0; + Settings.adc_param2 = 1023; + Settings.adc_param3 = 0; + Settings.adc_param4 = 100; + } + else if (ADC0_CT_POWER == my_adc0) { + Settings.adc_param_type = ADC0_CT_POWER; + Settings.adc_param1 = ANALOG_CT_FLAGS; + Settings.adc_param2 = ANALOG_CT_MULTIPLIER; + Settings.adc_param3 = ANALOG_CT_VOLTAGE; + } + } +} + +uint16_t AdcRead(uint8_t factor) +{ + + + + + + uint8_t samples = 1 << factor; + uint16_t analog = 0; + for (uint32_t i = 0; i < samples; i++) { + analog += analogRead(A0); + delay(1); + } + analog >>= factor; + return analog; +} + +#ifdef USE_RULES +void AdcEvery250ms(void) +{ + if (ADC0_INPUT == my_adc0) { + uint16_t new_value = AdcRead(5); + if ((new_value < Adc.last_value -10) || (new_value > Adc.last_value +10)) { + Adc.last_value = new_value; + uint16_t value = Adc.last_value / 10; + Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); + XdrvRulesProcess(); + } + } +} +#endif + +uint16_t AdcGetLux(void) +{ + int adc = AdcRead(2); + + double resistorVoltage = ((double)adc / 1023) * ANALOG_V33; + double ldrVoltage = ANALOG_V33 - resistorVoltage; + double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1; + double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000); + + return (uint16_t)ldrLux; +} + +uint16_t AdcGetRange(void) +{ + + + + int adc = AdcRead(2); + double adcrange = ( ((double)Settings.adc_param2 - (double)adc) / ( ((double)Settings.adc_param2 - (double)Settings.adc_param1)) * ((double)Settings.adc_param3 - (double)Settings.adc_param4) + (double)Settings.adc_param4 ); + return (uint16_t)adcrange; +} + +void AdcGetCurrentPower(uint8_t factor) +{ + + + + + + uint8_t samples = 1 << factor; + uint16_t analog = 0; + uint16_t analog_min = 1023; + uint16_t analog_max = 0; + for (uint32_t i = 0; i < samples; i++) { + analog = analogRead(A0); + if (analog < analog_min) { + analog_min = analog; + } + if (analog > analog_max) { + analog_max = analog; + } + delay(1); + } + + Adc.current = (float)(analog_max-analog_min) * ((float)(Settings.adc_param2) / 100000); + float power = Adc.current * (float)(Settings.adc_param3) / 10; + uint32_t current_millis = millis(); + Adc.energy = Adc.energy + ((power * (current_millis - Adc.previous_millis)) / 3600000000); + Adc.previous_millis = current_millis; +} + +void AdcEverySecond(void) +{ + if (ADC0_TEMP == my_adc0) { + int adc = AdcRead(2); + + double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc); + double BC = (double)Settings.adc_param3 / 10000; + double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2)); + Adc.temperature = ConvertTemp(TO_CELSIUS(T)); + } + else if (ADC0_CT_POWER == my_adc0) { + AdcGetCurrentPower(5); + } +} + +void AdcShow(bool json) +{ + if (ADC0_INPUT == my_adc0) { + uint16_t analog = AdcRead(5); + + if (json) { + ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); +#endif + } + } + + else if (ADC0_TEMP == my_adc0) { + char temperature[33]; + dtostrfd(Adc.temperature, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMP, "ANALOG", temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, Adc.temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); +#endif + } + } + + else if (ADC0_LIGHT == my_adc0) { + uint16_t adc_light = AdcGetLux(); + + if (json) { + ResponseAppend_P(JSON_SNS_ILLUMINANCE, "ANALOG", adc_light); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, adc_light); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light); +#endif + } + } + + else if (ADC0_RANGE == my_adc0) { + uint16_t adc_range = AdcGetRange(); + + if (json) { + ResponseAppend_P(JSON_SNS_RANGE, "ANALOG", adc_range); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_RANGE, "", adc_range); +#endif + } + } + + else if (ADC0_CT_POWER == my_adc0) { + AdcGetCurrentPower(5); + + float voltage = (float)(Settings.adc_param3) / 10; + char voltage_chr[FLOATSZ]; + dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr); + char current_chr[FLOATSZ]; + dtostrfd(Adc.current, Settings.flag2.current_resolution, current_chr); + char power_chr[FLOATSZ]; + dtostrfd(voltage * Adc.current, Settings.flag2.wattage_resolution, power_chr); + char energy_chr[FLOATSZ]; + dtostrfd(Adc.energy, Settings.flag2.energy_resolution, energy_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"ANALOG\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), + energy_chr, power_chr, voltage_chr, current_chr); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_POWER_ENERGY, power_chr); + DomoticzSensor(DZ_VOLTAGE, voltage_chr); + DomoticzSensor(DZ_CURRENT, current_chr); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr); + WSContentSend_PD(HTTP_SNS_CURRENT, current_chr); + WSContentSend_PD(HTTP_SNS_POWER, power_chr); + WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr); +#endif + } + } + +} + + + + + +const char kAdcCommands[] PROGMEM = "|" + D_CMND_ADC "|" D_CMND_ADCS "|" D_CMND_ADCPARAM; + +void (* const AdcCommand[])(void) PROGMEM = { + &CmndAdc, &CmndAdcs, &CmndAdcParam }; + +void CmndAdc(void) +{ + if (ValidAdc() && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < ADC0_END)) { + Settings.my_adc0 = XdrvMailbox.payload; + restart_flag = 2; + } + char stemp1[TOPSZ]; + Response_P(PSTR("{\"" D_CMND_ADC "0\":{\"%d\":\"%s\"}}"), Settings.my_adc0, GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_adc0, kAdc0Names)); +} + +void CmndAdcs(void) +{ + Response_P(PSTR("{\"" D_CMND_ADCS "\":{")); + bool jsflg = false; + char stemp1[TOPSZ]; + for (uint32_t i = 0; i < ADC0_END; i++) { + if (jsflg) { + ResponseAppend_P(PSTR(",")); + } + jsflg = true; + ResponseAppend_P(PSTR("\"%d\":\"%s\""), i, GetTextIndexed(stemp1, sizeof(stemp1), i, kAdc0Names)); + } + ResponseJsonEndEnd(); +} + +void CmndAdcParam(void) +{ + if (XdrvMailbox.data_len) { + if ((ADC0_TEMP == XdrvMailbox.payload) || + (ADC0_LIGHT == XdrvMailbox.payload) || + (ADC0_RANGE == XdrvMailbox.payload) || + (ADC0_CT_POWER == XdrvMailbox.payload)) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len +1]; + + + + Settings.adc_param_type = XdrvMailbox.payload; + Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); + if (ADC0_RANGE == XdrvMailbox.payload) { + Settings.adc_param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10)); + Settings.adc_param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10)); + } else { + Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); + } + if (ADC0_CT_POWER == XdrvMailbox.payload) { + if ((Settings.adc_param1 & CT_FLAG_ENERGY_RESET) > 0) { + Adc.energy = 0; + Settings.adc_param1 ^= CT_FLAG_ENERGY_RESET; + } + } + } else { + + + + + Settings.adc_param_type = 0; + AdcInit(); + } + } + } + + + Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2); + if (ADC0_RANGE == my_adc0) { + ResponseAppend_P(PSTR(",%d,%d"), Settings.adc_param3, Settings.adc_param4); + } else { + int value = Settings.adc_param3; + uint8_t precision; + for (precision = 4; precision > 0; precision--) { + if (value % 10) { break; } + value /= 10; + } + char param3[33]; + dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); + ResponseAppend_P(PSTR(",%s"), param3); + } + ResponseAppend_P(PSTR("]}")); +} + + + + + +bool Xsns02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_COMMAND: + result = DecodeCommand(kAdcCommands, AdcCommand); + break; + default: + if ((ADC0_INPUT == my_adc0) || + (ADC0_TEMP == my_adc0) || + (ADC0_LIGHT == my_adc0) || + (ADC0_RANGE == my_adc0) || + (ADC0_CT_POWER == my_adc0)) { + switch (function) { +#ifdef USE_RULES + case FUNC_EVERY_250_MSECOND: + AdcEvery250ms(); + break; +#endif + case FUNC_EVERY_SECOND: + AdcEverySecond(); + break; + case FUNC_INIT: + AdcInit(); + break; + case FUNC_JSON_APPEND: + AdcShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AdcShow(0); + break; +#endif + } + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_04_snfsc.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_04_snfsc.ino" +#ifdef USE_SONOFF_SC +# 57 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_04_snfsc.ino" +#define XSNS_04 4 + +uint16_t sc_value[5] = { 0 }; + +void SonoffScSend(const char *data) +{ + Serial.write(data); + Serial.write('\x1B'); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data); +} + +void SonoffScInit(void) +{ + + SonoffScSend("AT+START"); + +} + +void SonoffScSerialInput(char *rcvstat) +{ + char *p; + char *str; + uint16_t value[5] = { 0 }; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat); + + if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { + int8_t i = -1; + for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(nullptr, ":", &p)) { + value[i++] = atoi(str); + } + if (value[0] > 0) { + for (uint32_t i = 0; i < 5; i++) { + sc_value[i] = value[i]; + } + sc_value[2] = (11 - sc_value[2]) * 10; + sc_value[3] *= 10; + sc_value[4] = (11 - sc_value[4]) * 10; + SonoffScSend("AT+SEND=ok"); + } else { + SonoffScSend("AT+SEND=fail"); + } + } + else if (!strcasecmp_P(rcvstat, PSTR("AT+STATUS?"))) { + SonoffScSend("AT+STATUS=4"); + } +} + + + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SCPLUS[] PROGMEM = + "{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; +#endif + +void SonoffScShow(bool json) +{ + if (sc_value[0] > 0) { + float t = ConvertTemp(sc_value[1]); + float h = ConvertHumidity(sc_value[0]); + + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), + temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); + DomoticzSensor(DZ_COUNT, sc_value[3]); + DomoticzSensor(DZ_AIRQUALITY, 500 + ((100 - sc_value[4]) * 20)); + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, t); + KnxSensor(KNX_HUMIDITY, h); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, "", humidity); + WSContentSend_PD(HTTP_SNS_SCPLUS, sc_value[2], sc_value[3], sc_value[4]); +#endif + } + } +} + + + + + +bool Xsns04(uint8_t function) +{ + bool result = false; + + if (SONOFF_SC == my_module_type) { + switch (function) { + case FUNC_JSON_APPEND: + SonoffScShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SonoffScShow(0); + break; +#endif + case FUNC_INIT: + SonoffScInit(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_05_ds18x20.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_05_ds18x20.ino" +#ifdef USE_DS18x20 + + + + +#define XSNS_05 5 + + + +#define DS18S20_CHIPID 0x10 +#define DS1822_CHIPID 0x22 +#define DS18B20_CHIPID 0x28 +#define MAX31850_CHIPID 0x3B + +#define W1_SKIP_ROM 0xCC +#define W1_CONVERT_TEMP 0x44 +#define W1_WRITE_EEPROM 0x48 +#define W1_WRITE_SCRATCHPAD 0x4E +#define W1_READ_SCRATCHPAD 0xBE + +#define DS18X20_MAX_SENSORS 8 + +const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; + +uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; + +struct DS18X20STRUCT { + uint8_t address[8]; + uint8_t index; + uint8_t valid; + float temperature; +} ds18x20_sensor[DS18X20_MAX_SENSORS]; +uint8_t ds18x20_sensors = 0; +uint8_t ds18x20_pin = 0; +uint8_t ds18x20_pin_out = 0; +bool ds18x20_dual_mode = false; +char ds18x20_types[12]; +#ifdef W1_PARASITE_POWER +uint8_t ds18x20_sensor_curr = 0; +unsigned long w1_power_until = 0; +#endif + + + + + +#define W1_MATCH_ROM 0x55 +#define W1_SEARCH_ROM 0xF0 + +uint8_t onewire_last_discrepancy = 0; +uint8_t onewire_last_family_discrepancy = 0; +bool onewire_last_device_flag = false; +unsigned char onewire_rom_id[8] = { 0 }; + + + +uint8_t OneWireReset(void) +{ + uint8_t retries = 125; + + if (!ds18x20_dual_mode) { + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + do { + if (--retries == 0) { + return 0; + } + delayMicroseconds(2); + } while (!digitalRead(ds18x20_pin)); + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(480); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + } else { + digitalWrite(ds18x20_pin_out, HIGH); + do { + if (--retries == 0) { + return 0; + } + delayMicroseconds(2); + } while (!digitalRead(ds18x20_pin)); + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(480); + digitalWrite(ds18x20_pin_out, HIGH); + } + delayMicroseconds(70); + uint8_t r = !digitalRead(ds18x20_pin); + delayMicroseconds(410); + return r; +} + +void OneWireWriteBit(uint8_t v) +{ + static const uint8_t delay_low[2] = { 65, 10 }; + static const uint8_t delay_high[2] = { 5, 55 }; + + v &= 1; + if (!ds18x20_dual_mode) { + digitalWrite(ds18x20_pin, LOW); + pinMode(ds18x20_pin, OUTPUT); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin, HIGH); + } else { + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin_out, HIGH); + } + delayMicroseconds(delay_high[v]); +} + +uint8_t OneWireReadBit(void) +{ + if (!ds18x20_dual_mode) { + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(3); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + } else { + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(3); + digitalWrite(ds18x20_pin_out, HIGH); + } + delayMicroseconds(10); + uint8_t r = digitalRead(ds18x20_pin); + delayMicroseconds(53); + return r; +} + + + +void OneWireWrite(uint8_t v) +{ + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + OneWireWriteBit((bit_mask & v) ? 1 : 0); + } +} + +uint8_t OneWireRead(void) +{ + uint8_t r = 0; + + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + if (OneWireReadBit()) { + r |= bit_mask; + } + } + return r; +} + +void OneWireSelect(const uint8_t rom[8]) +{ + OneWireWrite(W1_MATCH_ROM); + for (uint32_t i = 0; i < 8; i++) { + OneWireWrite(rom[i]); + } +} + +void OneWireResetSearch(void) +{ + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + for (uint32_t i = 0; i < 8; i++) { + onewire_rom_id[i] = 0; + } +} + +uint8_t OneWireSearch(uint8_t *newAddr) +{ + uint8_t id_bit_number = 1; + uint8_t last_zero = 0; + uint8_t rom_byte_number = 0; + uint8_t search_result = 0; + uint8_t id_bit; + uint8_t cmp_id_bit; + unsigned char rom_byte_mask = 1; + unsigned char search_direction; + + if (!onewire_last_device_flag) { + if (!OneWireReset()) { + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + return false; + } + OneWireWrite(W1_SEARCH_ROM); + do { + id_bit = OneWireReadBit(); + cmp_id_bit = OneWireReadBit(); + + if ((id_bit == 1) && (cmp_id_bit == 1)) { + break; + } else { + if (id_bit != cmp_id_bit) { + search_direction = id_bit; + } else { + if (id_bit_number < onewire_last_discrepancy) { + search_direction = ((onewire_rom_id[rom_byte_number] & rom_byte_mask) > 0); + } else { + search_direction = (id_bit_number == onewire_last_discrepancy); + } + if (search_direction == 0) { + last_zero = id_bit_number; + if (last_zero < 9) { + onewire_last_family_discrepancy = last_zero; + } + } + } + if (search_direction == 1) { + onewire_rom_id[rom_byte_number] |= rom_byte_mask; + } else { + onewire_rom_id[rom_byte_number] &= ~rom_byte_mask; + } + OneWireWriteBit(search_direction); + id_bit_number++; + rom_byte_mask <<= 1; + if (rom_byte_mask == 0) { + rom_byte_number++; + rom_byte_mask = 1; + } + } + } while (rom_byte_number < 8); + if (!(id_bit_number < 65)) { + onewire_last_discrepancy = last_zero; + if (onewire_last_discrepancy == 0) { + onewire_last_device_flag = true; + } + search_result = true; + } + } + if (!search_result || !onewire_rom_id[0]) { + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + search_result = false; + } + for (uint32_t i = 0; i < 8; i++) { + newAddr[i] = onewire_rom_id[i]; + } + return search_result; +} + +bool OneWireCrc8(uint8_t *addr) +{ + uint8_t crc = 0; + uint8_t len = 8; + + while (len--) { + uint8_t inbyte = *addr++; + for (uint32_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) { + crc ^= 0x8C; + } + inbyte >>= 1; + } + } + return (crc == *addr); +} + + + +void Ds18x20Init(void) +{ + uint64_t ids[DS18X20_MAX_SENSORS]; + + ds18x20_pin = pin[GPIO_DSB]; + if (pin[GPIO_DSB_OUT] < 99) { + ds18x20_pin_out = pin[GPIO_DSB_OUT]; + ds18x20_dual_mode = true; + pinMode(ds18x20_pin_out, OUTPUT); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + } + + OneWireResetSearch(); + + ds18x20_sensors = 0; + while (ds18x20_sensors < DS18X20_MAX_SENSORS) { + if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { + break; + } + if (OneWireCrc8(ds18x20_sensor[ds18x20_sensors].address) && + ((ds18x20_sensor[ds18x20_sensors].address[0] == DS18S20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS1822_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS18B20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == MAX31850_CHIPID))) { + ds18x20_sensor[ds18x20_sensors].index = ds18x20_sensors; + ids[ds18x20_sensors] = ds18x20_sensor[ds18x20_sensors].address[0]; + for (uint32_t j = 6; j > 0; j--) { + ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_sensor[ds18x20_sensors].address[j]; + } + ds18x20_sensors++; + } + } + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + for (uint32_t j = i + 1; j < ds18x20_sensors; j++) { + if (ids[ds18x20_sensor[i].index] > ids[ds18x20_sensor[j].index]) { + std::swap(ds18x20_sensor[i].index, ds18x20_sensor[j].index); + } + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); +} + +void Ds18x20Convert(void) +{ + OneWireReset(); +#ifdef W1_PARASITE_POWER + + if (++ds18x20_sensor_curr >= ds18x20_sensors) + ds18x20_sensor_curr = 0; + OneWireSelect(ds18x20_sensor[ds18x20_sensor_curr].address); +#else + OneWireWrite(W1_SKIP_ROM); +#endif + OneWireWrite(W1_CONVERT_TEMP); + +} + +bool Ds18x20Read(uint8_t sensor) +{ + uint8_t data[9]; + int8_t sign = 1; + + uint8_t index = ds18x20_sensor[sensor].index; + if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } + for (uint32_t retry = 0; retry < 3; retry++) { + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_READ_SCRATCHPAD); + for (uint32_t i = 0; i < 9; i++) { + data[i] = OneWireRead(); + } + if (OneWireCrc8(data)) { + switch(ds18x20_sensor[index].address[0]) { + case DS18S20_CHIPID: { + if (data[1] > 0x80) { + data[0] = (~data[0]) +1; + sign = -1; + } + float temp9 = (float)(data[0] >> 1) * sign; + ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + case DS1822_CHIPID: + case DS18B20_CHIPID: { + if (data[4] != 0x7F) { + data[4] = 0x7F; + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_SCRATCHPAD); + OneWireWrite(data[2]); + OneWireWrite(data[3]); + OneWireWrite(data[4]); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_EEPROM); +#ifdef W1_PARASITE_POWER + w1_power_until = millis() + 10; +#endif + } + uint16_t temp12 = (data[1] << 8) + data[0]; + if (temp12 > 2047) { + temp12 = (~temp12) +1; + sign = -1; + } + ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + case MAX31850_CHIPID: { + int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); + ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + } + } + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); + return false; +} + +void Ds18x20Name(uint8_t sensor) +{ + uint8_t index = sizeof(ds18x20_chipids); + while (index) { + if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) { + break; + } + index--; + } + GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); + if (ds18x20_sensors > 1) { + snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), sensor +1); + } +} + + + +void Ds18x20EverySecond(void) +{ +#ifdef W1_PARASITE_POWER + + unsigned long now = millis(); + if (now < w1_power_until) + return; +#endif + if (uptime & 1 +#ifdef W1_PARASITE_POWER + + || ds18x20_sensors >= 2 +#endif + ) { + + Ds18x20Convert(); + } else { + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + + if (!Ds18x20Read(i)) { + Ds18x20Name(i); + AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); +#ifdef USE_DS18x20_RECONFIGURE + if (!ds18x20_sensor[ds18x20_sensor[i].index].valid) { + memset(&ds18x20_sensor, 0, sizeof(ds18x20_sensor)); + Ds18x20Init(); + } +#endif + } + } + } +} + +void Ds18x20Show(bool json) +{ + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + uint8_t index = ds18x20_sensor[i].index; + + if (ds18x20_sensor[index].valid) { + char temperature[33]; + dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); + + Ds18x20Name(i); + + if (json) { + char address[17]; + for (uint32_t j = 0; j < 6; j++) { + sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); + } + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); +#endif + } + } + } +} + + + + + +bool Xsns05(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_DSB] < 99) { + switch (function) { + case FUNC_INIT: + Ds18x20Init(); + break; + case FUNC_EVERY_SECOND: + Ds18x20EverySecond(); + break; + case FUNC_JSON_APPEND: + Ds18x20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ds18x20Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_old.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_old.ino" +#ifdef USE_DHT_OLD +# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_old.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint32_t dht_max_cycles; +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +void DhtReadPrep(void) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + if (!dht_dual_mode) { + digitalWrite(Dht[i].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + } +} + +int32_t DhtExpectPulse(uint8_t sensor, bool level) +{ + int32_t count = 0; + + while (digitalRead(Dht[sensor].pin) == level) { + if (count++ >= (int32_t)dht_max_cycles) { + return -1; + } + } + return count; +} + +bool DhtRead(uint8_t sensor) +{ + int32_t cycles[80]; + uint8_t error = 0; + + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + + + + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].lastresult = 0; + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delay(250); + } + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + if (GPIO_SI7021 == Dht[sensor].type) { + delayMicroseconds(500); + } else { + delay(20); + } + + noInterrupts(); + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + delayMicroseconds(40); + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + delayMicroseconds(40); + } + delayMicroseconds(10); + if (-1 == DhtExpectPulse(sensor, LOW)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + error = 1; + } + else if (-1 == DhtExpectPulse(sensor, HIGH)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); + error = 1; + } + else { + for (uint32_t i = 0; i < 80; i += 2) { + cycles[i] = DhtExpectPulse(sensor, LOW); + cycles[i+1] = DhtExpectPulse(sensor, HIGH); + } + } + interrupts(); + + if (error) { return false; } + + for (uint32_t i = 0; i < 40; ++i) { + int32_t lowCycles = cycles[2*i]; + int32_t highCycles = cycles[2*i+1]; + if ((-1 == lowCycles) || (-1 == highCycles)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); + return false; + } + dht_data[i/8] <<= 1; + if (highCycles > lowCycles) { + dht_data[i / 8] |= 1; + } + } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint8_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + dht_max_cycles = microsecondsToClockCycles(1000); + + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + + DhtReadPrep(); + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" +#ifdef USE_DHT_V2 +# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint32_t dht_max_cycles; +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +void DhtReadPrep(void) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + if (!dht_dual_mode) { + digitalWrite(Dht[i].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + } +} + +int32_t DhtExpectPulse(uint8_t sensor, bool level) +{ + int32_t count = 0; + + while (digitalRead(Dht[sensor].pin) == level) { + if (count++ >= (int32_t)dht_max_cycles) { + return -1; + } + } + return count; +} + +bool DhtRead(uint8_t sensor) +{ + int32_t cycles[80]; + uint8_t error = 0; + + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].lastresult = 0; + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delay(250); + } + + + noInterrupts(); + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_SI7021: +# 114 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" + delayMicroseconds(500); + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delayMicroseconds(40); + break; + + case GPIO_DHT22: +# 133 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" + delayMicroseconds(1100); + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delayMicroseconds(30); + break; + + case GPIO_DHT11: +# 151 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" + default: + + delay(20); + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delayMicroseconds(30); + break; + } + + + pinMode(Dht[sensor].pin, INPUT_PULLUP); + + if (-1 == DhtExpectPulse(sensor, LOW)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + error = 1; + } + else if (-1 == DhtExpectPulse(sensor, HIGH)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); + error = 1; + } + else { + for (uint32_t i = 0; i < 80; i += 2) { + cycles[i] = DhtExpectPulse(sensor, LOW); + cycles[i+1] = DhtExpectPulse(sensor, HIGH); + } + } + interrupts(); + if (error) { return false; } + + + for (uint32_t i = 0; i < 40; ++i) { + int32_t lowCycles = cycles[2*i]; + int32_t highCycles = cycles[2*i+1]; + if ((-1 == lowCycles) || (-1 == highCycles)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); + return false; + } + dht_data[i/8] <<= 1; + if (highCycles > lowCycles) { + dht_data[i / 8] |= 1; + } + } + + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint8_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + dht_max_cycles = microsecondsToClockCycles(1000); + + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v2) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + + DhtReadPrep(); + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v3.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v3.ino" +#ifdef USE_DHT_V3 +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v3.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +bool DhtExpectPulse(uint8_t sensor, int level) +{ + unsigned long timeout = micros() + 100; + while (digitalRead(Dht[sensor].pin) != level) { + if (micros() > timeout) { return false; } + delayMicroseconds(1); + } + return true; +} + +int DhtReadDat(uint8_t sensor) +{ + uint8_t result = 0; + for (uint32_t i = 0; i < 8; i++) { + if (!DhtExpectPulse(sensor, HIGH)) { return -1; } + + delayMicroseconds(35); + if (digitalRead(Dht[sensor].pin)) { + result |= (1 << (7 - i)); + } + + if (!DhtExpectPulse(sensor, LOW)) { return -1; } + } + return result; +} + +bool DhtRead(uint8_t sensor) +{ + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + delay(19); + break; + case GPIO_DHT22: + delay(2); + break; + case GPIO_SI7021: + delayMicroseconds(500); + break; + } + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + case GPIO_DHT22: + delayMicroseconds(50); + break; + case GPIO_SI7021: + + delayMicroseconds(20); + break; + } + + noInterrupts(); + if (!DhtExpectPulse(sensor, LOW)) { + interrupts(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + return false; + } + if (!DhtExpectPulse(sensor, HIGH)) { + interrupts(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); + return false; + } + if (!DhtExpectPulse(sensor, LOW)) { + interrupts(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + return false; + } + + int data = 0; + for (uint32_t i = 0; i < 5; i++) { + data = DhtReadDat(sensor); + if (-1 == data) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); + break; + } + dht_data[i] = data; + } + interrupts(); + if (-1 == data) { return false; } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint8_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v3) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + + + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v4.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v4.ino" +#ifdef USE_DHT_V4 +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v4.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +bool DhtExpectPulse(uint32_t sensor, uint32_t level) +{ + unsigned long timeout = micros() + 100; + while (digitalRead(Dht[sensor].pin) != level) { + if (micros() > timeout) { return false; } + delayMicroseconds(1); + } + return true; +} + +bool DhtRead(uint32_t sensor) +{ + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + delay(19); + break; + case GPIO_DHT22: + delay(2); + break; + case GPIO_SI7021: + delayMicroseconds(500); + break; + } + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + case GPIO_DHT22: + delayMicroseconds(50); + break; + case GPIO_SI7021: + delayMicroseconds(20); + break; + } + + uint32_t level = 9; + noInterrupts(); + for (uint32_t i = 0; i < 3; i++) { + level = i &1; + if (!DhtExpectPulse(sensor, level)) { break; } + level = 9; + } + if (9 == level) { + int data = 0; + for (uint32_t i = 0; i < 5; i++) { + data = 0; + for (uint32_t j = 0; j < 8; j++) { + level = 1; + if (!DhtExpectPulse(sensor, level)) { break; } + + delayMicroseconds(35); + if (digitalRead(Dht[sensor].pin)) { + data |= (1 << (7 - j)); + } + + level = 0; + if (!DhtExpectPulse(sensor, level)) { break; } + level = 9; + } + if (level < 2) { break; } + + dht_data[i] = data; + } + } + interrupts(); + if (level < 2) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), (0 == level) ? D_START_SIGNAL_LOW : D_START_SIGNAL_HIGH); + return false; + } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint32_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + if (Dht[sensor].h > 100) { Dht[sensor].h = 100.0; } + if (Dht[sensor].h < 0) { Dht[sensor].h = 0.0; } + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v4) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v5.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v5.ino" +#ifdef USE_DHT +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v5.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + uint8_t lastresult; + char stype[12]; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +bool DhtWaitState(uint32_t sensor, uint32_t level) +{ + unsigned long timeout = micros() + 100; + while (digitalRead(Dht[sensor].pin) != level) { + if (TimeReachedUsec(timeout)) { + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), + (level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW); + return false; + } + delayMicroseconds(1); + } + return true; +} + +bool DhtRead(uint32_t sensor) +{ + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + delay(19); + break; + case GPIO_DHT22: + delay(2); + break; + case GPIO_SI7021: + delayMicroseconds(500); + break; + } + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + case GPIO_DHT22: + delayMicroseconds(50); + break; + case GPIO_SI7021: + delayMicroseconds(20); + break; + } + + bool error = false; + noInterrupts(); + if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { + for (uint32_t i = 0; i < 5; i++) { + int data = 0; + for (uint32_t j = 0; j < 8; j++) { + if (!DhtWaitState(sensor, 1)) { + error = true; + break; + } + delayMicroseconds(35); + if (digitalRead(Dht[sensor].pin)) { + data |= (1 << (7 - j)); + } + if (!DhtWaitState(sensor, 0)) { + error = true; + break; + } + } + if (error) { break; } + dht_data[i] = data; + } + } else { + error = true; + } + interrupts(); + if (error) { return false; } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + float temperature = NAN; + float humidity = NAN; + switch (Dht[sensor].type) { + case GPIO_DHT11: + humidity = dht_data[0]; + temperature = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + humidity = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + temperature = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + temperature *= -1; + } + break; + } + if (isnan(temperature) || isnan(humidity)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid NAN reading")); + return false; + } + + if (humidity > 100) { humidity = 100.0; } + if (humidity < 0) { humidity = 0.1; } + Dht[sensor].h = ConvertHumidity(humidity); + Dht[sensor].t = ConvertTemp(temperature); + Dht[sensor].lastresult = 0; + + return true; +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastresult = DHT_MAX_RETRY; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v5) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { + + if (!DhtRead(sensor)) { + Dht[sensor].lastresult++; + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + } + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_07_sht1x.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_07_sht1x.ino" +#ifdef USE_I2C +#ifdef USE_SHT +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_07_sht1x.ino" +#define XSNS_07 7 +#define XI2C_08 8 + +enum { + SHT1X_CMD_MEASURE_TEMP = B00000011, + SHT1X_CMD_MEASURE_RH = B00000101, + SHT1X_CMD_SOFT_RESET = B00011110 +}; + +uint8_t sht_sda_pin; +uint8_t sht_scl_pin; +uint8_t sht_type = 0; +char sht_types[] = "SHT1X"; +uint8_t sht_valid = 0; +float sht_temperature = 0; +float sht_humidity = 0; + +bool ShtReset(void) +{ + pinMode(sht_sda_pin, INPUT_PULLUP); + pinMode(sht_scl_pin, OUTPUT); + delay(11); + for (uint32_t i = 0; i < 9; i++) { + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + } + bool success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); + delay(11); + return success; +} + +bool ShtSendCommand(const uint8_t cmd) +{ + pinMode(sht_sda_pin, OUTPUT); + + digitalWrite(sht_sda_pin, HIGH); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_sda_pin, LOW); + digitalWrite(sht_scl_pin, LOW); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_sda_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + + shiftOut(sht_sda_pin, sht_scl_pin, MSBFIRST, cmd); + + bool ackerror = false; + digitalWrite(sht_scl_pin, HIGH); + pinMode(sht_sda_pin, INPUT_PULLUP); + if (digitalRead(sht_sda_pin) != LOW) { + ackerror = true; + } + digitalWrite(sht_scl_pin, LOW); + delayMicroseconds(1); + if (digitalRead(sht_sda_pin) != HIGH) { + ackerror = true; + } + if (ackerror) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_DID_NOT_ACK_COMMAND)); + } + return (!ackerror); +} + +bool ShtAwaitResult(void) +{ + + for (uint32_t i = 0; i < 16; i++) { + if (LOW == digitalRead(sht_sda_pin)) { + return true; + } + delay(20); + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_BUSY)); + + return false; +} + +int ShtReadData(void) +{ + int val = 0; + + + val = shiftIn(sht_sda_pin, sht_scl_pin, 8); + val <<= 8; + + pinMode(sht_sda_pin, OUTPUT); + digitalWrite(sht_sda_pin, LOW); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + pinMode(sht_sda_pin, INPUT_PULLUP); + + val |= shiftIn(sht_sda_pin, sht_scl_pin, 8); + + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + return val; +} + +bool ShtRead(void) +{ + if (sht_valid) { sht_valid--; } + if (!ShtReset()) { return false; } + if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { return false; } + if (!ShtAwaitResult()) { return false; } + float tempRaw = ShtReadData(); + if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { return false; } + if (!ShtAwaitResult()) { return false; } + float humRaw = ShtReadData(); + + + const float d1 = -39.7; + const float d2 = 0.01; + sht_temperature = d1 + (tempRaw * d2); + const float c1 = -2.0468; + const float c2 = 0.0367; + const float c3 = -1.5955E-6; + const float t1 = 0.01; + const float t2 = 0.00008; + float rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; + sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear; + sht_temperature = ConvertTemp(sht_temperature); + ConvertHumidity(sht_humidity); + + sht_valid = SENSOR_MAX_MISS; + return true; +} + + + +void ShtDetect(void) +{ + sht_sda_pin = pin[GPIO_I2C_SDA]; + sht_scl_pin = pin[GPIO_I2C_SCL]; + if (ShtRead()) { + sht_type = 1; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); + } else { + Wire.begin(sht_sda_pin, sht_scl_pin); + sht_type = 0; + } +} + +void ShtEverySecond(void) +{ + if (!(uptime %4)) { + + if (!ShtRead()) { + AddLogMissed(sht_types, sht_valid); + } + } +} + +void ShtShow(bool json) +{ + if (sht_valid) { + char temperature[33]; + dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, sht_types, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, sht_temperature); + KnxSensor(KNX_HUMIDITY, sht_humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sht_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, sht_types, humidity); +#endif + } + } +} + + + + + +bool Xsns07(uint8_t function) +{ + if (!I2cEnabled(XI2C_08)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + ShtDetect(); + } + else if (sht_type) { + switch (function) { + case FUNC_EVERY_SECOND: + ShtEverySecond(); + break; + case FUNC_JSON_APPEND: + ShtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + ShtShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_08_htu21.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_08_htu21.ino" +#ifdef USE_I2C +#ifdef USE_HTU +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_08_htu21.ino" +#define XSNS_08 8 +#define XI2C_09 9 + +#define HTU21_ADDR 0x40 + +#define SI7013_CHIPID 0x0D +#define SI7020_CHIPID 0x14 +#define SI7021_CHIPID 0x15 +#define HTU21_CHIPID 0x32 + +#define HTU21_READTEMP 0xE3 +#define HTU21_READHUM 0xE5 +#define HTU21_WRITEREG 0xE6 +#define HTU21_READREG 0xE7 +#define HTU21_RESET 0xFE +#define HTU21_HEATER_WRITE 0x51 +#define HTU21_HEATER_READ 0x11 +#define HTU21_SERIAL2_READ1 0xFC +#define HTU21_SERIAL2_READ2 0xC9 + +#define HTU21_HEATER_ON 0x04 +#define HTU21_HEATER_OFF 0xFB + +#define HTU21_RES_RH12_T14 0x00 +#define HTU21_RES_RH8_T12 0x01 +#define HTU21_RES_RH10_T13 0x80 +#define HTU21_RES_RH11_T11 0x81 + +#define HTU21_CRC8_POLYNOM 0x13100 + +const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?"; + +uint8_t htu_address; +uint8_t htu_type = 0; +uint8_t htu_delay_temp; +uint8_t htu_delay_humidity = 50; +uint8_t htu_valid = 0; +float htu_temperature = 0; +float htu_humidity = 0; +char htu_types[7]; + +uint8_t HtuCheckCrc8(uint16_t data) +{ + for (uint32_t bit = 0; bit < 16; bit++) { + if (data & 0x8000) { + data = (data << 1) ^ HTU21_CRC8_POLYNOM; + } else { + data <<= 1; + } + } + return data >>= 8; +} + +uint8_t HtuReadDeviceId(void) +{ + uint16_t deviceID = 0; + uint8_t checksum = 0; + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_SERIAL2_READ1); + Wire.write(HTU21_SERIAL2_READ2); + Wire.endTransmission(); + + Wire.requestFrom(HTU21_ADDR, 3); + deviceID = Wire.read() << 8; + deviceID |= Wire.read(); + checksum = Wire.read(); + if (HtuCheckCrc8(deviceID) == checksum) { + deviceID = deviceID >> 8; + } else { + deviceID = 0; + } + return (uint8_t)deviceID; +} + +void HtuSetResolution(uint8_t resolution) +{ + uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); + current &= 0x7E; + current |= resolution; + I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); +} + +void HtuReset(void) +{ + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_RESET); + Wire.endTransmission(); + delay(15); +} + +void HtuHeater(uint8_t heater) +{ + uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); + + switch(heater) + { + case HTU21_HEATER_ON : current |= heater; + break; + case HTU21_HEATER_OFF : current &= heater; + break; + default : current &= heater; + break; + } + I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); +} + +void HtuInit(void) +{ + HtuReset(); + HtuHeater(HTU21_HEATER_OFF); + HtuSetResolution(HTU21_RES_RH12_T14); +} + +bool HtuRead(void) +{ + uint8_t checksum = 0; + uint16_t sensorval = 0; + + if (htu_valid) { htu_valid--; } + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_READTEMP); + if (Wire.endTransmission() != 0) { return false; } + delay(htu_delay_temp); + + Wire.requestFrom(HTU21_ADDR, 3); + if (3 == Wire.available()) { + sensorval = Wire.read() << 8; + sensorval |= Wire.read(); + checksum = Wire.read(); + } + if (HtuCheckCrc8(sensorval) != checksum) { return false; } + + htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_READHUM); + if (Wire.endTransmission() != 0) { return false; } + delay(htu_delay_humidity); + + Wire.requestFrom(HTU21_ADDR, 3); + if (3 <= Wire.available()) { + sensorval = Wire.read() << 8; + sensorval |= Wire.read(); + checksum = Wire.read(); + } + if (HtuCheckCrc8(sensorval) != checksum) { return false; } + + sensorval ^= 0x02; + htu_humidity = 0.001907 * (float)sensorval - 6; + if (htu_humidity > 100) { htu_humidity = 100.0; } + if (htu_humidity < 0) { htu_humidity = 0.01; } + + if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) { + htu_humidity = 0.0; + } + if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) { + htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity; + } + ConvertHumidity(htu_humidity); + + htu_valid = SENSOR_MAX_MISS; + return true; +} + + + +void HtuDetect(void) +{ + htu_address = HTU21_ADDR; + if (I2cActive(htu_address)) { return; } + + htu_type = HtuReadDeviceId(); + if (htu_type) { + uint8_t index = 0; + HtuInit(); + switch (htu_type) { + case HTU21_CHIPID: + htu_delay_temp = 50; + htu_delay_humidity = 16; + break; + case SI7021_CHIPID: + index++; + case SI7020_CHIPID: + index++; + case SI7013_CHIPID: + index++; + htu_delay_temp = 12; + htu_delay_humidity = 23; + break; + default: + index = 4; + htu_delay_temp = 50; + htu_delay_humidity = 23; + } + GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); + I2cSetActiveFound(htu_address, htu_types); + } +} + +void HtuEverySecond(void) +{ + if (uptime &1) { + + if (!HtuRead()) { + AddLogMissed(htu_types, htu_valid); + } + } +} + +void HtuShow(bool json) +{ + if (htu_valid) { + char temperature[33]; + dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, htu_types, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, htu_temperature); + KnxSensor(KNX_HUMIDITY, htu_humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, htu_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, htu_types, humidity); +#endif + } + } +} + + + + + +bool Xsns08(uint8_t function) +{ + if (!I2cEnabled(XI2C_09)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + HtuDetect(); + } + else if (htu_type) { + switch (function) { + case FUNC_EVERY_SECOND: + HtuEverySecond(); + break; + case FUNC_JSON_APPEND: + HtuShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HtuShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_09_bmp.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_09_bmp.ino" +#ifdef USE_I2C +#ifdef USE_BMP +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_09_bmp.ino" +#define XSNS_09 9 +#define XI2C_10 10 + +#define BMP_ADDR1 0x76 +#define BMP_ADDR2 0x77 + +#define BMP180_CHIPID 0x55 +#define BMP280_CHIPID 0x58 +#define BME280_CHIPID 0x60 +#define BME680_CHIPID 0x61 + +#define BMP_REGISTER_CHIPID 0xD0 + +#define BMP_REGISTER_RESET 0xE0 + +#define BMP_CMND_RESET 0xB6 + +#define BMP_MAX_SENSORS 2 + +const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; + +typedef struct { + uint8_t bmp_address; + char bmp_name[7]; + uint8_t bmp_type; + uint8_t bmp_model; +#ifdef USE_BME680 + uint8_t bme680_state; + float bmp_gas_resistance; +#endif + float bmp_temperature; + float bmp_pressure; + float bmp_humidity; +} bmp_sensors_t; + +uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; +uint8_t bmp_count = 0; +uint8_t bmp_once = 1; + +bmp_sensors_t *bmp_sensors = nullptr; + + + + + +#define BMP180_REG_CONTROL 0xF4 +#define BMP180_REG_RESULT 0xF6 +#define BMP180_TEMPERATURE 0x2E +#define BMP180_PRESSURE3 0xF4 + +#define BMP180_AC1 0xAA +#define BMP180_AC2 0xAC +#define BMP180_AC3 0xAE +#define BMP180_AC4 0xB0 +#define BMP180_AC5 0xB2 +#define BMP180_AC6 0xB4 +#define BMP180_VB1 0xB6 +#define BMP180_VB2 0xB8 +#define BMP180_MB 0xBA +#define BMP180_MC 0xBC +#define BMP180_MD 0xBE + +#define BMP180_OSS 3 + +typedef struct { + int16_t cal_ac1; + int16_t cal_ac2; + int16_t cal_ac3; + int16_t cal_b1; + int16_t cal_b2; + int16_t cal_mc; + int16_t cal_md; + uint16_t cal_ac4; + uint16_t cal_ac5; + uint16_t cal_ac6; +} bmp180_cal_data_t; + +bmp180_cal_data_t *bmp180_cal_data = nullptr; + +bool Bmp180Calibration(uint8_t bmp_idx) +{ + if (!bmp180_cal_data) { + bmp180_cal_data = (bmp180_cal_data_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp180_cal_data_t)); + } + if (!bmp180_cal_data) { return false; } + + bmp180_cal_data[bmp_idx].cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1); + bmp180_cal_data[bmp_idx].cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2); + bmp180_cal_data[bmp_idx].cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3); + bmp180_cal_data[bmp_idx].cal_ac4 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC4); + bmp180_cal_data[bmp_idx].cal_ac5 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC5); + bmp180_cal_data[bmp_idx].cal_ac6 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC6); + bmp180_cal_data[bmp_idx].cal_b1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB1); + bmp180_cal_data[bmp_idx].cal_b2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB2); + bmp180_cal_data[bmp_idx].cal_mc = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MC); + bmp180_cal_data[bmp_idx].cal_md = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MD); + + + if (!bmp180_cal_data[bmp_idx].cal_ac1 | + !bmp180_cal_data[bmp_idx].cal_ac2 | + !bmp180_cal_data[bmp_idx].cal_ac3 | + !bmp180_cal_data[bmp_idx].cal_ac4 | + !bmp180_cal_data[bmp_idx].cal_ac5 | + !bmp180_cal_data[bmp_idx].cal_ac6 | + !bmp180_cal_data[bmp_idx].cal_b1 | + !bmp180_cal_data[bmp_idx].cal_b2 | + !bmp180_cal_data[bmp_idx].cal_mc | + !bmp180_cal_data[bmp_idx].cal_md) { + return false; + } + + if ((bmp180_cal_data[bmp_idx].cal_ac1 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac2 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac3 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac4 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac5 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac6 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_b1 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_b2 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_mc == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_md == (int16_t)0xFFFF)) { + return false; + } + return true; +} + +void Bmp180Read(uint8_t bmp_idx) +{ + if (!bmp180_cal_data) { return; } + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); + delay(5); + int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); + int32_t xt1 = (ut - (int32_t)bmp180_cal_data[bmp_idx].cal_ac6) * ((int32_t)bmp180_cal_data[bmp_idx].cal_ac5) >> 15; + int32_t xt2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_mc << 11) / (xt1 + (int32_t)bmp180_cal_data[bmp_idx].cal_md); + int32_t bmp180_b5 = xt1 + xt2; + bmp_sensors[bmp_idx].bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); + delay(2 + (4 << BMP180_OSS)); + uint32_t up = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); + up >>= (8 - BMP180_OSS); + + int32_t b6 = bmp180_b5 - 4000; + int32_t x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b2 * ((b6 * b6) >> 12)) >> 11; + int32_t x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac2 * b6) >> 11; + int32_t x3 = x1 + x2; + int32_t b3 = ((((int32_t)bmp180_cal_data[bmp_idx].cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2; + + x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac3 * b6) >> 13; + x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b1 * ((b6 * b6) >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + uint32_t b4 = ((uint32_t)bmp180_cal_data[bmp_idx].cal_ac4 * (uint32_t)(x3 + 32768)) >> 15; + uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS); + + int32_t p; + if (b7 < 0x80000000) { + p = (b7 * 2) / b4; + } + else { + p = (b7 / b4) * 2; + } + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + p += ((x1 + x2 + (int32_t)3791) >> 4); + bmp_sensors[bmp_idx].bmp_pressure = (float)p / 100.0; +} + + + + + + + +#define BME280_REGISTER_CONTROLHUMID 0xF2 +#define BME280_REGISTER_CONTROL 0xF4 +#define BME280_REGISTER_CONFIG 0xF5 +#define BME280_REGISTER_PRESSUREDATA 0xF7 +#define BME280_REGISTER_TEMPDATA 0xFA +#define BME280_REGISTER_HUMIDDATA 0xFD + +#define BME280_REGISTER_DIG_T1 0x88 +#define BME280_REGISTER_DIG_T2 0x8A +#define BME280_REGISTER_DIG_T3 0x8C +#define BME280_REGISTER_DIG_P1 0x8E +#define BME280_REGISTER_DIG_P2 0x90 +#define BME280_REGISTER_DIG_P3 0x92 +#define BME280_REGISTER_DIG_P4 0x94 +#define BME280_REGISTER_DIG_P5 0x96 +#define BME280_REGISTER_DIG_P6 0x98 +#define BME280_REGISTER_DIG_P7 0x9A +#define BME280_REGISTER_DIG_P8 0x9C +#define BME280_REGISTER_DIG_P9 0x9E +#define BME280_REGISTER_DIG_H1 0xA1 +#define BME280_REGISTER_DIG_H2 0xE1 +#define BME280_REGISTER_DIG_H3 0xE3 +#define BME280_REGISTER_DIG_H4 0xE4 +#define BME280_REGISTER_DIG_H5 0xE5 +#define BME280_REGISTER_DIG_H6 0xE7 + +typedef struct { + uint16_t dig_T1; + int16_t dig_T2; + int16_t dig_T3; + uint16_t dig_P1; + int16_t dig_P2; + int16_t dig_P3; + int16_t dig_P4; + int16_t dig_P5; + int16_t dig_P6; + int16_t dig_P7; + int16_t dig_P8; + int16_t dig_P9; + int16_t dig_H2; + int16_t dig_H4; + int16_t dig_H5; + uint8_t dig_H1; + uint8_t dig_H3; + int8_t dig_H6; +} Bme280CalibrationData_t; + +Bme280CalibrationData_t *Bme280CalibrationData = nullptr; + +bool Bmx280Calibrate(uint8_t bmp_idx) +{ + + + if (!Bme280CalibrationData) { + Bme280CalibrationData = (Bme280CalibrationData_t*)malloc(BMP_MAX_SENSORS * sizeof(Bme280CalibrationData_t)); + } + if (!Bme280CalibrationData) { return false; } + + Bme280CalibrationData[bmp_idx].dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1); + Bme280CalibrationData[bmp_idx].dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2); + Bme280CalibrationData[bmp_idx].dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3); + Bme280CalibrationData[bmp_idx].dig_P1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P1); + Bme280CalibrationData[bmp_idx].dig_P2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P2); + Bme280CalibrationData[bmp_idx].dig_P3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P3); + Bme280CalibrationData[bmp_idx].dig_P4 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P4); + Bme280CalibrationData[bmp_idx].dig_P5 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P5); + Bme280CalibrationData[bmp_idx].dig_P6 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P6); + Bme280CalibrationData[bmp_idx].dig_P7 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P7); + Bme280CalibrationData[bmp_idx].dig_P8 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P8); + Bme280CalibrationData[bmp_idx].dig_P9 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P9); + if (BME280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { + Bme280CalibrationData[bmp_idx].dig_H1 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H1); + Bme280CalibrationData[bmp_idx].dig_H2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H2); + Bme280CalibrationData[bmp_idx].dig_H3 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H3); + Bme280CalibrationData[bmp_idx].dig_H4 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); + Bme280CalibrationData[bmp_idx].dig_H5 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5) >> 4); + Bme280CalibrationData[bmp_idx].dig_H6 = (int8_t)I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H6); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x00); + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROLHUMID, 0x01); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONFIG, 0xA0); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x27); + } else { + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0xB7); + } + + return true; +} + +void Bme280Read(uint8_t bmp_idx) +{ + if (!Bme280CalibrationData) { return; } + + int32_t adc_T = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_TEMPDATA); + adc_T >>= 4; + + int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1 << 1))) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_T2)) >> 11; + int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1))) >> 12) * + ((int32_t)Bme280CalibrationData[bmp_idx].dig_T3)) >> 14; + int32_t t_fine = vart1 + vart2; + float T = (t_fine * 5 + 128) >> 8; + bmp_sensors[bmp_idx].bmp_temperature = T / 100.0; + + int32_t adc_P = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_PRESSUREDATA); + adc_P >>= 4; + + int64_t var1 = ((int64_t)t_fine) - 128000; + int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P6; + var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P5) << 17); + var2 = var2 + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P4) << 35); + var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P2) << 12); + var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData[bmp_idx].dig_P1) >> 33; + if (0 == var1) { + return; + } + int64_t p = 1048576 - adc_P; + p = (((p << 31) - var2) * 3125) / var1; + var1 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P9) * (p >> 13) * (p >> 13)) >> 25; + var2 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P8) * p) >> 19; + p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P7) << 4); + bmp_sensors[bmp_idx].bmp_pressure = (float)p / 25600.0; + + if (BMP280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { return; } + + int32_t adc_H = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_HUMIDDATA); + + int32_t v_x1_u32r = (t_fine - ((int32_t)76800)); + v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H4) << 20) - + (((int32_t)Bme280CalibrationData[bmp_idx].dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * + (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H6)) >> 10) * + (((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + + ((int32_t)2097152)) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H2) + 8192) >> 14)); + v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * + ((int32_t)Bme280CalibrationData[bmp_idx].dig_H1)) >> 4)); + v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; + v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; + float h = (v_x1_u32r >> 12); + bmp_sensors[bmp_idx].bmp_humidity = h / 1024.0; +} + +#ifdef USE_BME680 + + + + +#include + +struct bme680_dev *gas_sensor = nullptr; + +static void BmeDelayMs(uint32_t ms) +{ + delay(ms); +} + +bool Bme680Init(uint8_t bmp_idx) +{ + if (!gas_sensor) { + gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); + } + if (!gas_sensor) { return false; } + + gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address; + gas_sensor[bmp_idx].intf = BME680_I2C_INTF; + gas_sensor[bmp_idx].read = &I2cReadBuffer; + gas_sensor[bmp_idx].write = &I2cWriteBuffer; + gas_sensor[bmp_idx].delay_ms = BmeDelayMs; + + + + gas_sensor[bmp_idx].amb_temp = 25; + + int8_t rslt = BME680_OK; + rslt = bme680_init(&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return false; } + + + gas_sensor[bmp_idx].tph_sett.os_hum = BME680_OS_2X; + gas_sensor[bmp_idx].tph_sett.os_pres = BME680_OS_4X; + gas_sensor[bmp_idx].tph_sett.os_temp = BME680_OS_8X; + gas_sensor[bmp_idx].tph_sett.filter = BME680_FILTER_SIZE_3; + + + gas_sensor[bmp_idx].gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; + + gas_sensor[bmp_idx].gas_sett.heatr_temp = 320; + gas_sensor[bmp_idx].gas_sett.heatr_dur = 150; + + + + gas_sensor[bmp_idx].power_mode = BME680_FORCED_MODE; + + + uint8_t set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; + + + rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return false; } + + bmp_sensors[bmp_idx].bme680_state = 0; + + return true; +} + +void Bme680Read(uint8_t bmp_idx) +{ + if (!gas_sensor) { return; } + + int8_t rslt = BME680_OK; + + if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { + if (0 == bmp_sensors[bmp_idx].bme680_state) { + + rslt = bme680_set_sensor_mode(&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return; } + + + + + + + + bmp_sensors[bmp_idx].bme680_state = 1; + } else { + bmp_sensors[bmp_idx].bme680_state = 0; + + struct bme680_field_data data; + rslt = bme680_get_sensor_data(&data, &gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return; } + + bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; + bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; + bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; + + if (data.status & BME680_GASM_VALID_MSK) { + bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; + } else { + bmp_sensors[bmp_idx].bmp_gas_resistance = 0; + } + } + } + return; +} + +#endif + + + +void BmpDetect(void) +{ + int bmp_sensor_size = BMP_MAX_SENSORS * sizeof(bmp_sensors_t); + if (!bmp_sensors) { + bmp_sensors = (bmp_sensors_t*)malloc(bmp_sensor_size); + } + if (!bmp_sensors) { return; } + memset(bmp_sensors, 0, bmp_sensor_size); + + for (uint32_t i = 0; i < BMP_MAX_SENSORS; i++) { + if (I2cActive(bmp_addresses[i])) { continue; } + uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); + if (bmp_type) { + bmp_sensors[bmp_count].bmp_address = bmp_addresses[i]; + bmp_sensors[bmp_count].bmp_type = bmp_type; + bmp_sensors[bmp_count].bmp_model = 0; + + bool success = false; + switch (bmp_type) { + case BMP180_CHIPID: + success = Bmp180Calibration(bmp_count); + break; + case BME280_CHIPID: + bmp_sensors[bmp_count].bmp_model++; + case BMP280_CHIPID: + bmp_sensors[bmp_count].bmp_model++; + success = Bmx280Calibrate(bmp_count); + break; +#ifdef USE_BME680 + case BME680_CHIPID: + bmp_sensors[bmp_count].bmp_model = 3; + success = Bme680Init(bmp_count); + break; +#endif + } + if (success) { + GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); + I2cSetActiveFound(bmp_sensors[bmp_count].bmp_address, bmp_sensors[bmp_count].bmp_name); + bmp_count++; + } + } + } +} + +void BmpRead(void) +{ + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + switch (bmp_sensors[bmp_idx].bmp_type) { + case BMP180_CHIPID: + Bmp180Read(bmp_idx); + break; + case BMP280_CHIPID: + case BME280_CHIPID: + Bme280Read(bmp_idx); + break; +#ifdef USE_BME680 + case BME680_CHIPID: + Bme680Read(bmp_idx); + break; +#endif + } + } + ConvertTemp(bmp_sensors[0].bmp_temperature); + ConvertHumidity(bmp_sensors[0].bmp_humidity); +} + +void BmpShow(bool json) +{ + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + if (bmp_sensors[bmp_idx].bmp_type) { + float bmp_sealevel = 0.0; + if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { + bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; + bmp_sealevel = ConvertPressure(bmp_sealevel); + } + float bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); + float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); + + char name[10]; + strlcpy(name, bmp_sensors[bmp_idx].bmp_name, sizeof(name)); + if (bmp_count > 1) { + snprintf_P(name, sizeof(name), PSTR("%s%c%02X"), name, IndexSeparator(), bmp_sensors[bmp_idx].bmp_address); + } + + char temperature[33]; + dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); + char pressure[33]; + dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); + char sea_pressure[33]; + dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); + char humidity[33]; + dtostrfd(bmp_sensors[bmp_idx].bmp_humidity, Settings.flag2.humidity_resolution, humidity); +#ifdef USE_BME680 + char gas_resistance[33]; + dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); +#endif + + if (json) { + char json_humidity[40]; + snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + char json_sealevel[40]; + snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); +#ifdef USE_BME680 + char json_gas[40]; + snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); + + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), + name, + temperature, + (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", + pressure, + (Settings.altitude != 0) ? json_sealevel : "", + (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); +#else + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), + name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); +#endif + +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == bmp_idx)) { + DomoticzTempHumPressureSensor(temperature, humidity, pressure); +#ifdef USE_BME680 + if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } +#endif + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, bmp_temperature); + KnxSensor(KNX_HUMIDITY, bmp_sensors[bmp_idx].bmp_humidity); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, name, temperature, TempUnit()); + if (bmp_sensors[bmp_idx].bmp_model >= 2) { + WSContentSend_PD(HTTP_SNS_HUM, name, humidity); + } + WSContentSend_PD(HTTP_SNS_PRESSURE, name, pressure, PressureUnit().c_str()); + if (Settings.altitude != 0) { + WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sea_pressure, PressureUnit().c_str()); + } +#ifdef USE_BME680 + if (bmp_sensors[bmp_idx].bmp_model >= 3) { + WSContentSend_PD(PSTR("{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), name, gas_resistance); + } +#endif + +#endif + } + } + } +} + +#ifdef USE_DEEPSLEEP + +void BMP_EnterSleep(void) +{ + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + switch (bmp_sensors[bmp_idx].bmp_type) { + case BMP180_CHIPID: + case BMP280_CHIPID: + case BME280_CHIPID: + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP_REGISTER_RESET, BMP_CMND_RESET); + break; + default: + break; + } + } +} + +#endif + + + + + +bool Xsns09(uint8_t function) +{ + if (!I2cEnabled(XI2C_10)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + BmpDetect(); + } + else if (bmp_count) { + switch (function) { + case FUNC_EVERY_SECOND: + BmpRead(); + break; + case FUNC_JSON_APPEND: + BmpShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + BmpShow(0); + break; +#endif +#ifdef USE_DEEPSLEEP + case FUNC_SAVE_BEFORE_RESTART: + BMP_EnterSleep(); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_10_bh1750.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_10_bh1750.ino" +#ifdef USE_I2C +#ifdef USE_BH1750 + + + + + + +#define XSNS_10 10 +#define XI2C_11 11 + +#define BH1750_ADDR1 0x23 +#define BH1750_ADDR2 0x5C + +#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 + +uint8_t bh1750_address; +uint8_t bh1750_addresses[] = { BH1750_ADDR1, BH1750_ADDR2 }; +uint8_t bh1750_type = 0; +uint8_t bh1750_valid = 0; +uint16_t bh1750_illuminance = 0; +char bh1750_types[] = "BH1750"; + +bool Bh1750Read(void) +{ + if (bh1750_valid) { bh1750_valid--; } + + if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } + uint8_t msb = Wire.read(); + uint8_t lsb = Wire.read(); + bh1750_illuminance = ((msb << 8) | lsb) / 1.2; + bh1750_valid = SENSOR_MAX_MISS; + return true; +} + + + +void Bh1750Detect(void) +{ + for (uint32_t i = 0; i < sizeof(bh1750_addresses); i++) { + bh1750_address = bh1750_addresses[i]; + if (I2cActive(bh1750_address)) { continue; } + Wire.beginTransmission(bh1750_address); + Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); + if (!Wire.endTransmission()) { + I2cSetActiveFound(bh1750_address, bh1750_types); + bh1750_type = 1; + break; + } + } +} + +void Bh1750EverySecond(void) +{ + + if (!Bh1750Read()) { + AddLogMissed(bh1750_types, bh1750_valid); + } +} + +void Bh1750Show(bool json) +{ + if (bh1750_valid) { + if (json) { + ResponseAppend_P(JSON_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); +#endif + } + } +} + + + + + +bool Xsns10(uint8_t function) +{ + if (!I2cEnabled(XI2C_11)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Bh1750Detect(); + } + else if (bh1750_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Bh1750EverySecond(); + break; + case FUNC_JSON_APPEND: + Bh1750Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Bh1750Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_11_veml6070.ino" +# 89 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_11_veml6070.ino" +#ifdef USE_I2C +#ifdef USE_VEML6070 + + + + + + +#define XSNS_11 11 +#define XI2C_12 12 + +#define VEML6070_ADDR_H 0x39 +#define VEML6070_ADDR_L 0x38 +#define VEML6070_INTEGRATION_TIME 3 +#define VEML6070_ENABLE 1 +#define VEML6070_DISABLE 0 +#define VEML6070_RSET_DEFAULT 270000 +#define VEML6070_UV_MAX_INDEX 15 +#define VEML6070_UV_MAX_DEFAULT 11 +#define VEML6070_POWER_COEFFCIENT 0.025 +#define VEML6070_TABLE_COEFFCIENT 32.86270591 + + + + + +const char kVemlTypes[] PROGMEM = "VEML6070"; +double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +double uvrisk = 0; +double uvpower = 0; +uint16_t uvlevel = 0; +uint8_t veml6070_addr_low = VEML6070_ADDR_L; +uint8_t veml6070_addr_high = VEML6070_ADDR_H; +uint8_t itime = VEML6070_INTEGRATION_TIME; +uint8_t veml6070_type = 0; +char veml6070_name[9]; +char str_uvrisk_text[10]; + + + +void Veml6070Detect(void) +{ + if (I2cActive(VEML6070_ADDR_L)) { return; } + + + Wire.beginTransmission(VEML6070_ADDR_L); + Wire.write((itime << 2) | 0x02); + uint8_t status = Wire.endTransmission(); + + if (!status) { + veml6070_type = 1; + Veml6070UvTableInit(); + uint8_t veml_model = 0; + GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); + I2cSetActiveFound(VEML6070_ADDR_L, veml6070_name); + } +} + + + +void Veml6070UvTableInit(void) +{ + + for (uint32_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { +#ifdef USE_VEML6070_RSET + if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { + uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + } else { + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); + } +#else + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); +#endif + } +} + + + +void Veml6070EverySecond(void) +{ + + Veml6070ModeCmd(1); + uvlevel = Veml6070ReadUv(); + uvrisk = Veml6070UvRiskLevel(uvlevel); + uvpower = Veml6070UvPower(uvrisk); + Veml6070ModeCmd(0); +} + + + +void Veml6070ModeCmd(bool mode_cmd) +{ + + + Wire.beginTransmission(VEML6070_ADDR_L); + Wire.write((mode_cmd << 0) | 0x02 | (itime << 2)); + uint8_t status = Wire.endTransmission(); + + if (!status) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 mode_cmd")); + } +} + + + +uint16_t Veml6070ReadUv(void) +{ + uint16_t uv_raw = 0; + + if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { + return -1; + } + uv_raw = Wire.read(); + uv_raw <<= 8; + + if (Wire.requestFrom(VEML6070_ADDR_L, 1) != 1) { + return -1; + } + uv_raw |= Wire.read(); + + return uv_raw; +} + + + +double Veml6070UvRiskLevel(uint16_t uv_level) +{ + double risk = 0; + if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { + risk = (double)uv_level / uv_risk_map[0]; + + if ( (risk >= 0) && (risk <= 2.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_1); } + else if ( (risk >= 3.0) && (risk <= 5.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_2); } + else if ( (risk >= 6.0) && (risk <= 7.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_3); } + else if ( (risk >= 8.0) && (risk <= 10.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_4); } + else if ( (risk >= 11.0) && (risk <= 12.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_5); } + else if ( (risk >= 13.0) && (risk <= 25.0) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_6); } + else { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); } + return risk; + } else { + + snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); + return ( risk = 99 ); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); + } +} + + + +double Veml6070UvPower(double uvrisk) +{ + + double power = 0; + return ( power = VEML6070_POWER_COEFFCIENT * uvrisk ); +} + + + + +#ifdef USE_WEBSERVER + +#ifdef USE_VEML6070_SHOW_RAW + const char HTTP_SNS_UV_LEVEL[] PROGMEM = "{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; +#endif + + const char HTTP_SNS_UV_INDEX[] PROGMEM = "{s}VEML6070 " D_UV_INDEX "{m}%s %s{e}"; + const char HTTP_SNS_UV_POWER[] PROGMEM = "{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; +#endif + + + +void Veml6070Show(bool json) +{ + + char str_uvlevel[33]; + dtostrfd((double)uvlevel, 0, str_uvlevel); + char str_uvrisk[33]; + dtostrfd(uvrisk, 2, str_uvrisk); + char str_uvpower[33]; + dtostrfd(uvpower, 3, str_uvpower); + if (json) { +#ifdef USE_VEML6070_SHOW_RAW + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); +#else + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); +#endif +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } +#endif +#ifdef USE_WEBSERVER + } else { +#ifdef USE_VEML6070_SHOW_RAW + WSContentSend_PD(HTTP_SNS_UV_LEVEL, str_uvlevel); +#endif + WSContentSend_PD(HTTP_SNS_UV_INDEX, str_uvrisk, str_uvrisk_text); + WSContentSend_PD(HTTP_SNS_UV_POWER, str_uvpower); +#endif + } +} + + + + + +bool Xsns11(uint8_t function) +{ + if (!I2cEnabled(XI2C_12)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Veml6070Detect(); + } + else if (veml6070_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Veml6070EverySecond(); + break; + case FUNC_JSON_APPEND: + Veml6070Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Veml6070Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_12_ads1115.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_12_ads1115.ino" +#ifdef USE_I2C +#ifdef USE_ADS1115 +# 43 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_12_ads1115.ino" +#define XSNS_12 12 +#define XI2C_13 13 + +#define ADS1115_ADDRESS_ADDR_GND 0x48 +#define ADS1115_ADDRESS_ADDR_VDD 0x49 +#define ADS1115_ADDRESS_ADDR_SDA 0x4A +#define ADS1115_ADDRESS_ADDR_SCL 0x4B + +#define ADS1115_CONVERSIONDELAY (8) + + + + +#define ADS1115_REG_POINTER_MASK (0x03) +#define ADS1115_REG_POINTER_CONVERT (0x00) +#define ADS1115_REG_POINTER_CONFIG (0x01) +#define ADS1115_REG_POINTER_LOWTHRESH (0x02) +#define ADS1115_REG_POINTER_HITHRESH (0x03) + + + + +#define ADS1115_REG_CONFIG_OS_MASK (0x8000) +#define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) +#define ADS1115_REG_CONFIG_OS_BUSY (0x0000) +#define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) + +#define ADS1115_REG_CONFIG_MUX_MASK (0x7000) +#define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) +#define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) +#define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) +#define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) + +#define ADS1115_REG_CONFIG_PGA_MASK (0x0E00) +#define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) +#define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) +#define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) +#define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) +#define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) +#define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) + +#define ADS1115_REG_CONFIG_MODE_MASK (0x0100) +#define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) +#define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) + +#define ADS1115_REG_CONFIG_DR_MASK (0x00E0) +#define ADS1115_REG_CONFIG_DR_128SPS (0x0000) +#define ADS1115_REG_CONFIG_DR_250SPS (0x0020) +#define ADS1115_REG_CONFIG_DR_490SPS (0x0040) +#define ADS1115_REG_CONFIG_DR_920SPS (0x0060) +#define ADS1115_REG_CONFIG_DR_1600SPS (0x0080) +#define ADS1115_REG_CONFIG_DR_2400SPS (0x00A0) +#define ADS1115_REG_CONFIG_DR_3300SPS (0x00C0) +#define ADS1115_REG_CONFIG_DR_6000SPS (0x00E0) + +#define ADS1115_REG_CONFIG_CMODE_MASK (0x0010) +#define ADS1115_REG_CONFIG_CMODE_TRAD (0x0000) +#define ADS1115_REG_CONFIG_CMODE_WINDOW (0x0010) + +#define ADS1115_REG_CONFIG_CPOL_MASK (0x0008) +#define ADS1115_REG_CONFIG_CPOL_ACTVLOW (0x0000) +#define ADS1115_REG_CONFIG_CPOL_ACTVHI (0x0008) + +#define ADS1115_REG_CONFIG_CLAT_MASK (0x0004) +#define ADS1115_REG_CONFIG_CLAT_NONLAT (0x0000) +#define ADS1115_REG_CONFIG_CLAT_LATCH (0x0004) + +#define ADS1115_REG_CONFIG_CQUE_MASK (0x0003) +#define ADS1115_REG_CONFIG_CQUE_1CONV (0x0000) +#define ADS1115_REG_CONFIG_CQUE_2CONV (0x0001) +#define ADS1115_REG_CONFIG_CQUE_4CONV (0x0002) +#define ADS1115_REG_CONFIG_CQUE_NONE (0x0003) + +struct ADS1115 { + uint8_t count = 0; + uint8_t address; + uint8_t addresses[4] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; + uint8_t found[4] = {false,false,false,false}; +} Ads1115; + + + +void Ads1115StartComparator(uint8_t channel, uint16_t mode) +{ + + uint16_t config = mode | + ADS1115_REG_CONFIG_CQUE_NONE | + ADS1115_REG_CONFIG_CLAT_NONLAT | + ADS1115_REG_CONFIG_PGA_6_144V | + ADS1115_REG_CONFIG_CPOL_ACTVLOW | + ADS1115_REG_CONFIG_CMODE_TRAD | + ADS1115_REG_CONFIG_DR_6000SPS; + + + config |= (ADS1115_REG_CONFIG_MUX_SINGLE_0 + (0x1000 * channel)); + + + I2cWrite16(Ads1115.address, ADS1115_REG_POINTER_CONFIG, config); +} + +int16_t Ads1115GetConversion(uint8_t channel) +{ + Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); + + delay(ADS1115_CONVERSIONDELAY); + + I2cRead16(Ads1115.address, ADS1115_REG_POINTER_CONVERT); + + Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); + delay(ADS1115_CONVERSIONDELAY); + + uint16_t res = I2cRead16(Ads1115.address, ADS1115_REG_POINTER_CONVERT); + return (int16_t)res; +} + + + +void Ads1115Detect(void) +{ + for (uint32_t i = 0; i < sizeof(Ads1115.addresses); i++) { + if (!Ads1115.found[i]) { + Ads1115.address = Ads1115.addresses[i]; + if (I2cActive(Ads1115.address)) { continue; } + uint16_t buffer; + if (I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONVERT) && + I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONFIG)) { + Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); + I2cSetActiveFound(Ads1115.address, "ADS1115"); + Ads1115.found[i] = 1; + Ads1115.count++; + } + } + } +} + +void Ads1115Show(bool json) +{ + int16_t values[4]; + + for (uint32_t t = 0; t < sizeof(Ads1115.addresses); t++) { + + if (Ads1115.found[t]) { + + uint8_t old_address = Ads1115.address; + Ads1115.address = Ads1115.addresses[t]; + for (uint32_t i = 0; i < 4; i++) { + values[i] = Ads1115GetConversion(i); + + } + Ads1115.address = old_address; + + char label[15]; + if (1 == Ads1115.count) { + + snprintf_P(label, sizeof(label), PSTR("ADS1115")); + } else { + + snprintf_P(label, sizeof(label), PSTR("ADS1115%c%02x"), IndexSeparator(), Ads1115.addresses[t]); + } + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{"), label); + for (uint32_t i = 0; i < 4; i++) { + ResponseAppend_P(PSTR("%s\"A%d\":%d"), (0 == i) ? "" : ",", i, values[i]); + } + ResponseJsonEnd(); + } +#ifdef USE_WEBSERVER + else { + for (uint32_t i = 0; i < 4; i++) { + WSContentSend_PD(HTTP_SNS_ANALOG, label, i, values[i]); + } + } +#endif + } + } +} + + + + + +bool Xsns12(uint8_t function) +{ + if (!I2cEnabled(XI2C_13)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Ads1115Detect(); + } + else if (Ads1115.count) { + switch (function) { + case FUNC_JSON_APPEND: + Ads1115Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ads1115Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_13_ina219.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_13_ina219.ino" +#ifdef USE_I2C +#ifdef USE_INA219 +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_13_ina219.ino" +#define XSNS_13 13 +#define XI2C_14 14 + +#define INA219_ADDRESS1 (0x40) +#define INA219_ADDRESS2 (0x41) +#define INA219_ADDRESS3 (0x44) +#define INA219_ADDRESS4 (0x45) + +#define INA219_READ (0x01) +#define INA219_REG_CONFIG (0x00) + +#define INA219_CONFIG_RESET (0x8000) + +#define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) +#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) +#define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) + +#define INA219_CONFIG_GAIN_MASK (0x1800) +#define INA219_CONFIG_GAIN_1_40MV (0x0000) +#define INA219_CONFIG_GAIN_2_80MV (0x0800) +#define INA219_CONFIG_GAIN_4_160MV (0x1000) +#define INA219_CONFIG_GAIN_8_320MV (0x1800) + +#define INA219_CONFIG_BADCRES_MASK (0x0780) +#define INA219_CONFIG_BADCRES_9BIT (0x0080) +#define INA219_CONFIG_BADCRES_10BIT (0x0100) +#define INA219_CONFIG_BADCRES_11BIT (0x0200) +#define INA219_CONFIG_BADCRES_12BIT (0x0400) + +#define INA219_CONFIG_SADCRES_MASK (0x0078) +#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) +#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) +#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) +#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) +#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) +#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) +#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) +#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) +#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) +#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) +#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) + +#define INA219_CONFIG_MODE_MASK (0x0007) +#define INA219_CONFIG_MODE_POWERDOWN (0x0000) +#define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001) +#define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002) +#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003) +#define INA219_CONFIG_MODE_ADCOFF (0x0004) +#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005) +#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006) +#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007) + +#define INA219_REG_SHUNTVOLTAGE (0x01) +#define INA219_REG_BUSVOLTAGE (0x02) +#define INA219_REG_POWER (0x03) +#define INA219_REG_CURRENT (0x04) +#define INA219_REG_CALIBRATION (0x05) + +uint8_t ina219_type[4] = {0,0,0,0}; +uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; + +uint32_t ina219_cal_value = 0; + +uint32_t ina219_current_divider_ma = 0; + +uint8_t ina219_valid[4] = {0,0,0,0}; +float ina219_voltage[4] = {0,0,0,0}; +float ina219_current[4] = {0,0,0,0}; +char ina219_types[] = "INA219"; +uint8_t ina219_count = 0; + +bool Ina219SetCalibration(uint8_t mode, uint16_t addr) +{ + uint16_t config = 0; + + switch (mode &3) { + case 0: + case 3: + ina219_cal_value = 4096; + ina219_current_divider_ma = 10; + config = INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + case 1: + ina219_cal_value = 10240; + ina219_current_divider_ma = 25; + config |= INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + case 2: + ina219_cal_value = 8192; + ina219_current_divider_ma = 20; + config |= INA219_CONFIG_BVOLTAGERANGE_16V | INA219_CONFIG_GAIN_1_40MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + } + + bool success = I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); + if (success) { + + I2cWrite16(addr, INA219_REG_CONFIG, config); + } + return success; +} + +float Ina219GetShuntVoltage_mV(uint16_t addr) +{ + + int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); + + return value * 0.01; +} + +float Ina219GetBusVoltage_V(uint16_t addr) +{ + + + int16_t value = (int16_t)(((uint16_t)I2cReadS16(addr, INA219_REG_BUSVOLTAGE) >> 3) * 4); + + return value * 0.001; +} + +float Ina219GetCurrent_mA(uint16_t addr) +{ + + + + I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); + + + float value = I2cReadS16(addr, INA219_REG_CURRENT); + value /= ina219_current_divider_ma; + + return value; +} + +bool Ina219Read(void) +{ + for (int i=0; i= 0) && (XdrvMailbox.payload <= 2)) { + Settings.ina219_mode = XdrvMailbox.payload; + restart_flag = 2; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); + + return true; +} + + + +void Ina219Detect(void) +{ + for (uint32_t i = 0; i < sizeof(ina219_type); i++) { + uint16_t addr = ina219_addresses[i]; + if (I2cActive(addr)) { continue; } + if (Ina219SetCalibration(Settings.ina219_mode, addr)) { + I2cSetActiveFound(addr, ina219_types); + ina219_type[i] = 1; + ina219_count++; + } + } +} + +void Ina219EverySecond(void) +{ + + Ina219Read(); +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_INA219_DATA[] PROGMEM = + "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; +#endif + +void Ina219Show(bool json) +{ + int num_found=0; + for (int i=0; i1) + snprintf_P(name, sizeof(name), PSTR("%s%c%d"), ina219_types, IndexSeparator(), sensor_num); + else + snprintf_P(name, sizeof(name), PSTR("%s"), ina219_types); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + name, ina219_addresses[i], voltage, current, power); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, voltage); + DomoticzSensor(DZ_CURRENT, current); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_INA219_DATA, name, voltage, name, current, name, power); +#endif + } + } +} + + + + + +bool Xsns13(uint8_t function) +{ + if (!I2cEnabled(XI2C_14)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Ina219Detect(); + } + else if (ina219_count) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_13 == XdrvMailbox.index) { + result = Ina219CommandSensor(); + } + break; + case FUNC_EVERY_SECOND: + Ina219EverySecond(); + break; + case FUNC_JSON_APPEND: + Ina219Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ina219Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_14_sht3x.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_14_sht3x.ino" +#ifdef USE_I2C +#ifdef USE_SHT3X + + + + + + +#define XSNS_14 14 +#define XI2C_15 15 + +#define SHT3X_ADDR_GND 0x44 +#define SHT3X_ADDR_VDD 0x45 +#define SHTC3_ADDR 0x70 + +#define SHT3X_MAX_SENSORS 3 + +const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3"; +uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR }; + +uint8_t sht3x_count = 0; +struct SHT3XSTRUCT { + uint8_t address; + char types[6]; +} sht3x_sensors[SHT3X_MAX_SENSORS]; + +bool Sht3xRead(float &t, float &h, uint8_t sht3x_address) +{ + unsigned int data[6]; + + t = NAN; + h = NAN; + + Wire.beginTransmission(sht3x_address); + if (SHTC3_ADDR == sht3x_address) { + Wire.write(0x35); + Wire.write(0x17); + Wire.endTransmission(); + Wire.beginTransmission(sht3x_address); + Wire.write(0x78); + Wire.write(0x66); + } else { + Wire.write(0x2C); + Wire.write(0x06); + } + if (Wire.endTransmission() != 0) { + return false; + } + delay(30); + Wire.requestFrom(sht3x_address, (uint8_t)6); + for (uint32_t i = 0; i < 6; i++) { + data[i] = Wire.read(); + }; + t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45); + h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0)); + return (!isnan(t) && !isnan(h) && (h != 0)); +} + + + +void Sht3xDetect(void) +{ + for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { + if (I2cActive(sht3x_addresses[i])) { continue; } + float t; + float h; + if (Sht3xRead(t, h, sht3x_addresses[i])) { + sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; + GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); + I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types); + sht3x_count++; + } + } +} + +void Sht3xShow(bool json) +{ + for (uint32_t i = 0; i < sht3x_count; i++) { + float t; + float h; + if (Sht3xRead(t, h, sht3x_sensors[i].address)) { + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + char types[11]; + snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, types, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, t); + KnxSensor(KNX_HUMIDITY, h); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, types, humidity); +#endif + } + } + } +} + + + + + +bool Xsns14(uint8_t function) +{ + if (!I2cEnabled(XI2C_15)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Sht3xDetect(); + } + else if (sht3x_count) { + switch (function) { + case FUNC_JSON_APPEND: + Sht3xShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sht3xShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" +#ifdef USE_MHZ19 +# 33 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" +#define XSNS_15 15 + +enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILTER_FAST, MHZ19_FILTER_MEDIUM, MHZ19_FILTER_SLOW}; + +#define MHZ19_FILTER_OPTION MHZ19_FILTER_FAST +# 58 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" +#include + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#define MHZ19_READ_TIMEOUT 400 +#define MHZ19_RETRY_COUNT 8 + +TasmotaSerial *MhzSerial; + +const char kMhzModels[] PROGMEM = "|B"; + +const char ABC_ENABLED[] = "ABC is Enabled"; +const char ABC_DISABLED[] = "ABC is Disabled"; + +enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; +const uint8_t kMhzCommands[][4] PROGMEM = { + + {0x86,0x00,0x00,0x00}, + {0x79,0xA0,0x00,0x00}, + {0x79,0x00,0x00,0x00}, + {0x87,0x00,0x00,0x00}, + {0x8D,0x00,0x00,0x00}, + {0x99,0x00,0x03,0xE8}, + {0x99,0x00,0x07,0xD0}, + {0x99,0x00,0x0B,0xB8}, + {0x99,0x00,0x13,0x88}}; + +uint8_t mhz_type = 1; +uint16_t mhz_last_ppm = 0; +uint8_t mhz_filter = MHZ19_FILTER_OPTION; +bool mhz_abc_must_apply = false; + +float mhz_temperature = 0; +uint8_t mhz_retry = MHZ19_RETRY_COUNT; +uint8_t mhz_received = 0; +uint8_t mhz_state = 0; + + + +uint8_t MhzCalculateChecksum(uint8_t *array) +{ + uint8_t checksum = 0; + for (uint32_t i = 1; i < 8; i++) { + checksum += array[i]; + } + checksum = 255 - checksum; + return (checksum +1); +} + +size_t MhzSendCmd(uint8_t command_id) +{ + uint8_t mhz_send[9] = { 0 }; + + mhz_send[0] = 0xFF; + mhz_send[1] = 0x01; + memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(uint16_t)); + + + + + memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); + mhz_send[8] = MhzCalculateChecksum(mhz_send); + + + + return MhzSerial->write(mhz_send, sizeof(mhz_send)); +} + + + +bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) +{ + if (1 == s) { + return false; + } + if (mhz_last_ppm < 400 || mhz_last_ppm > 5000) { + + + mhz_last_ppm = ppm; + return true; + } + int32_t difference = ppm - mhz_last_ppm; + if (s > 0 && s < 64 && mhz_filter != MHZ19_FILTER_OFF) { +# 154 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" + difference *= s; + difference /= 64; + } + if (MHZ19_FILTER_OFF == mhz_filter) { + if (s != 0 && s != 64) { + return false; + } + } else { + difference >>= (mhz_filter -1); + } + mhz_last_ppm = static_cast(mhz_last_ppm + difference); + return true; +} + +void MhzEverySecond(void) +{ + mhz_state++; + if (8 == mhz_state) { + mhz_state = 0; + + if (mhz_retry) { + mhz_retry--; + if (!mhz_retry) { + mhz_last_ppm = 0; + mhz_temperature = 0; + } + } + + MhzSerial->flush(); + MhzSendCmd(MHZ_CMND_READPPM); + mhz_received = 0; + } + + if ((mhz_state > 2) && !mhz_received) { + uint8_t mhz_response[9]; + + unsigned long start = millis(); + uint8_t counter = 0; + while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { + if (MhzSerial->available() > 0) { + mhz_response[counter++] = MhzSerial->read(); + } else { + delay(5); + } + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); + + if (counter < 9) { + + return; + } + + uint8_t crc = MhzCalculateChecksum(mhz_response); + if (mhz_response[8] != crc) { + + return; + } + if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { + + return; + } + + mhz_received = 1; + + uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; + if (15000 == u) { + if (Settings.SensorBits1.mhz19b_abc_disable) { + + + mhz_abc_must_apply = true; + } + } else { + uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; + mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); + uint8_t s = mhz_response[5]; + mhz_type = (s) ? 1 : 2; + if (MhzCheckAndApplyFilter(ppm, s)) { + mhz_retry = MHZ19_RETRY_COUNT; + LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); + + if (0 == s || 64 == s) { + if (mhz_abc_must_apply) { + mhz_abc_must_apply = false; + if (!Settings.SensorBits1.mhz19b_abc_disable) { + MhzSendCmd(MHZ_CMND_ABCENABLE); + } else { + MhzSendCmd(MHZ_CMND_ABCDISABLE); + } + } + } + + } + } + + } +} +# 266 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" +#define D_JSON_RANGE_1000 "1000 ppm range" +#define D_JSON_RANGE_2000 "2000 ppm range" +#define D_JSON_RANGE_3000 "3000 ppm range" +#define D_JSON_RANGE_5000 "5000 ppm range" + +bool MhzCommandSensor(void) +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + Settings.SensorBits1.mhz19b_abc_disable = true; + MhzSendCmd(MHZ_CMND_ABCDISABLE); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + break; + case 1: + Settings.SensorBits1.mhz19b_abc_disable = false; + MhzSendCmd(MHZ_CMND_ABCENABLE); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + break; + case 2: + MhzSendCmd(MHZ_CMND_ZEROPOINT); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); + break; + case 9: + MhzSendCmd(MHZ_CMND_RESET); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); + break; + case 1000: + MhzSendCmd(MHZ_CMND_RANGE_1000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); + break; + case 2000: + MhzSendCmd(MHZ_CMND_RANGE_2000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); + break; + case 3000: + MhzSendCmd(MHZ_CMND_RANGE_3000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); + break; + case 5000: + MhzSendCmd(MHZ_CMND_RANGE_5000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); + break; + default: + if (!Settings.SensorBits1.mhz19b_abc_disable) { + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + } else { + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + } + } + + return serviced; +} + + + +void MhzInit(void) +{ + mhz_type = 0; + if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { + MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD], 1); + if (MhzSerial->begin(9600)) { + if (MhzSerial->hardwareSerial()) { ClaimSerial(); } + mhz_type = 1; + } + + } +} + +void MhzShow(bool json) +{ + char types[7] = "MHZ19B"; + char temperature[33]; + dtostrfd(mhz_temperature, Settings.flag2.temperature_resolution, temperature); + char model[3]; + GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, types, mhz_last_ppm); + WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); +#endif + } +} + + + + + +bool Xsns15(uint8_t function) +{ + bool result = false; + + if (mhz_type) { + switch (function) { + case FUNC_INIT: + MhzInit(); + break; + case FUNC_EVERY_SECOND: + MhzEverySecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_15 == XdrvMailbox.index) { + result = MhzCommandSensor(); + } + break; + case FUNC_JSON_APPEND: + MhzShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MhzShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_16_tsl2561.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_16_tsl2561.ino" +#ifdef USE_I2C +#ifdef USE_TSL2561 +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_16_tsl2561.ino" +#define XSNS_16 16 +#define XI2C_16 16 + +#include + +Tsl2561 Tsl(Wire); + +uint8_t tsl2561_type = 0; +uint8_t tsl2561_valid = 0; +uint32_t tsl2561_milliLux = 0; +char tsl2561_types[] = "TSL2561"; + +bool Tsl2561Read(void) +{ + if (tsl2561_valid) { tsl2561_valid--; } + + uint8_t id; + bool gain; + Tsl2561::exposure_t exposure; + uint16_t scaledFull, scaledIr; + uint32_t full, ir; + + if (Tsl.on()) { + if (Tsl.id(id) + && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) + && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) + && Tsl2561Util::milliLux(full, ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { + } else{ + tsl2561_milliLux = 0; + } + } + tsl2561_valid = SENSOR_MAX_MISS; + return true; +} + +void Tsl2561Detect(void) +{ + if (I2cSetDevice(0x29) || I2cSetDevice(0x39) || I2cSetDevice(0x49)) { + uint8_t id; + Tsl.begin(); + if (!Tsl.id(id)) return; + if (Tsl.on()) { + tsl2561_type = 1; + I2cSetActiveFound(Tsl.address(), tsl2561_types); + } + } +} + +void Tsl2561EverySecond(void) +{ + if (!(uptime %2)) { + + if (!Tsl2561Read()) { + AddLogMissed(tsl2561_types, tsl2561_valid); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_TSL2561[] PROGMEM = + "{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; +#endif + +void Tsl2561Show(bool json) +{ + if (tsl2561_valid) { + if (json) { + ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), + tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TSL2561, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); +#endif + } + } +} + + + + + +bool Xsns16(uint8_t function) +{ + if (!I2cEnabled(XI2C_16)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Tsl2561Detect(); + } + else if (tsl2561_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Tsl2561EverySecond(); + break; + case FUNC_JSON_APPEND: + Tsl2561Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tsl2561Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_17_senseair.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_17_senseair.ino" +#ifdef USE_SENSEAIR +# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_17_senseair.ino" +#define XSNS_17 17 + +#define SENSEAIR_MODBUS_SPEED 9600 +#define SENSEAIR_DEVICE_ADDRESS 0xFE +#define SENSEAIR_READ_REGISTER 0x04 + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#include +TasmotaModbus *SenseairModbus; + +const char kSenseairTypes[] PROGMEM = "Kx0|S8"; + +uint8_t senseair_type = 1; +char senseair_types[7]; + +uint16_t senseair_co2 = 0; +float senseair_temperature = 0; +float senseair_humidity = 0; + + + +const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; + +uint8_t senseair_read_state = 0; +uint8_t senseair_send_retry = 0; + +void Senseair250ms(void) +{ + + + + + uint16_t value = 0; + bool data_ready = SenseairModbus->ReceiveReady(); + + if (data_ready) { + uint8_t error = SenseairModbus->Receive16BitRegister(&value); + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); + } else { + switch(senseair_read_state) { + case 0: + senseair_type = 2; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir type id low %04X"), value); + break; + case 1: + if (value) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir error %04X"), value); + } + break; + case 2: + senseair_co2 = value; + LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); + break; + case 3: + senseair_temperature = ConvertTemp((float)value / 100); + break; + case 4: + senseair_humidity = ConvertHumidity((float)value / 100); + break; + case 5: + { + bool relay_state = value >> 8 & 1; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir relay state %d"), relay_state); + break; + } + case 6: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir temp adjustment %d"), value); + break; + } + } + senseair_read_state++; + if (2 == senseair_type) { + if (3 == senseair_read_state) { + senseair_read_state = 1; + } + } else { + if (sizeof(start_addresses) == senseair_read_state) { + senseair_read_state = 1; + } + } + } + + if (0 == senseair_send_retry || data_ready) { + senseair_send_retry = 5; + SenseairModbus->Send(SENSEAIR_DEVICE_ADDRESS, SENSEAIR_READ_REGISTER, (uint16_t)start_addresses[senseair_read_state], 1); + } else { + senseair_send_retry--; + } + + +} + + + +void SenseairInit(void) +{ + senseair_type = 0; + if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { + SenseairModbus = new TasmotaModbus(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX]); + uint8_t result = SenseairModbus->Begin(SENSEAIR_MODBUS_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + senseair_type = 1; + } + } +} + +void SenseairShow(bool json) +{ + char temperature[33]; + dtostrfd(senseair_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(senseair_humidity, Settings.flag2.temperature_resolution, humidity); + GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2); + if (senseair_type != 2) { + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); + } + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, senseair_types, senseair_co2); + if (senseair_type != 2) { + WSContentSend_PD(HTTP_SNS_TEMP, senseair_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, senseair_types, humidity); + } +#endif + } +} + + + + + +bool Xsns17(uint8_t function) +{ + bool result = false; + + if (senseair_type) { + switch (function) { + case FUNC_INIT: + SenseairInit(); + break; + case FUNC_EVERY_250_MSECOND: + Senseair250ms(); + break; + case FUNC_JSON_APPEND: + SenseairShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SenseairShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_18_pms5003.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_18_pms5003.ino" +#ifdef USE_PMS5003 +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_18_pms5003.ino" +#define XSNS_18 18 + +#include + +TasmotaSerial *PmsSerial; + +uint8_t pms_type = 1; +uint8_t pms_valid = 0; + +struct pmsX003data { + uint16_t framelen; + uint16_t pm10_standard, pm25_standard, pm100_standard; + uint16_t pm10_env, pm25_env, pm100_env; +#ifdef PMS_MODEL_PMS3003 + uint16_t reserved1, reserved2, reserved3; +#else + uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um; + uint16_t unused; +#endif + uint16_t checksum; +} pms_data; + + + +bool PmsReadData(void) +{ + if (! PmsSerial->available()) { + return false; + } + while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { + PmsSerial->read(); + } +#ifdef PMS_MODEL_PMS3003 + if (PmsSerial->available() < 22) { +#else + if (PmsSerial->available() < 32) { +#endif + return false; + } + +#ifdef PMS_MODEL_PMS3003 + uint8_t buffer[22]; + PmsSerial->readBytes(buffer, 22); +#else + uint8_t buffer[32]; + PmsSerial->readBytes(buffer, 32); +#endif + uint16_t sum = 0; + PmsSerial->flush(); + +#ifdef PMS_MODEL_PMS3003 + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 22); +#else + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); +#endif + + +#ifdef PMS_MODEL_PMS3003 + for (uint32_t i = 0; i < 20; i++) { +#else + for (uint32_t i = 0; i < 30; i++) { +#endif + sum += buffer[i]; + } + +#ifdef PMS_MODEL_PMS3003 + uint16_t buffer_u16[10]; + for (uint32_t i = 0; i < 10; i++) { +#else + uint16_t buffer_u16[15]; + for (uint32_t i = 0; i < 15; i++) { +#endif + buffer_u16[i] = buffer[2 + i*2 + 1]; + buffer_u16[i] += (buffer[2 + i*2] << 8); + } +#ifdef PMS_MODEL_PMS3003 + if (sum != buffer_u16[9]) { +#else + if (sum != buffer_u16[14]) { +#endif + AddLog_P(LOG_LEVEL_DEBUG, PSTR("PMS: " D_CHECKSUM_FAILURE)); + return false; + } + +#ifdef PMS_MODEL_PMS3003 + memcpy((void *)&pms_data, (void *)buffer_u16, 20); +#else + memcpy((void *)&pms_data, (void *)buffer_u16, 30); +#endif + pms_valid = 10; + + return true; +} + + + +void PmsSecond(void) +{ + if (PmsReadData()) { + pms_valid = 10; + } else { + if (pms_valid) { + pms_valid--; + } + } +} + + + +void PmsInit(void) +{ + pms_type = 0; + if (pin[GPIO_PMS5003] < 99) { + PmsSerial = new TasmotaSerial(pin[GPIO_PMS5003], -1, 1); + if (PmsSerial->begin(9600)) { + if (PmsSerial->hardwareSerial()) { ClaimSerial(); } + pms_type = 1; + } + } +} + +#ifdef USE_WEBSERVER +#ifdef PMS_MODEL_PMS3003 +const char HTTP_PMS3003_SNS[] PROGMEM = + + + + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#else +const char HTTP_PMS5003_SNS[] PROGMEM = + + + + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 0.3 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 0.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; +#endif +#endif + +void PmsShow(bool json) +{ + if (pms_valid) { + if (json) { +#ifdef PMS_MODEL_PMS3003 + ResponseAppend_P(PSTR(",\"PMS3003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d}"), + pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); +#else + ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), + pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, + pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); +#endif +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_COUNT, pms_data.pm10_env); + DomoticzSensor(DZ_VOLTAGE, pms_data.pm25_env); + DomoticzSensor(DZ_CURRENT, pms_data.pm100_env); + } +#endif +#ifdef USE_WEBSERVER + } else { + +#ifdef PMS_MODEL_PMS3003 + WSContentSend_PD(HTTP_PMS3003_SNS, + + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); +#else + WSContentSend_PD(HTTP_PMS5003_SNS, + + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, + pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); +#endif +#endif + } + } +} + + + + + +bool Xsns18(uint8_t function) +{ + bool result = false; + + if (pms_type) { + switch (function) { + case FUNC_INIT: + PmsInit(); + break; + case FUNC_EVERY_SECOND: + PmsSecond(); + break; + case FUNC_JSON_APPEND: + PmsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + PmsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_19_mgs.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_19_mgs.ino" +#ifdef USE_I2C +#ifdef USE_MGS + + + + + + + +#define XSNS_19 19 +#define XI2C_17 17 + +#ifndef MGS_SENSOR_ADDR +#define MGS_SENSOR_ADDR 0x04 +#endif + +#include "MutichannelGasSensor.h" + +bool mgs_detected = false; + +void MGSInit(void) { + gas.begin(MGS_SENSOR_ADDR); +} + +void MGSPrepare(void) +{ + if (I2cActive(MGS_SENSOR_ADDR)) { return; } + + gas.begin(MGS_SENSOR_ADDR); + if (!gas.isError()) { + I2cSetActiveFound(MGS_SENSOR_ADDR, "MultiGas"); + mgs_detected = true; + } +} + +char* measure_gas(int gas_type, char* buffer) +{ + float f = gas.calcGas(gas_type); + dtostrfd(f, 2, buffer); + return buffer; +} + +#ifdef USE_WEBSERVER +const char HTTP_MGS_GAS[] PROGMEM = "{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; +#endif + +void MGSShow(bool json) +{ + char buffer[33]; + if (json) { + ResponseAppend_P(PSTR(",\"MGS\":{\"NH3\":%s"), measure_gas(NH3, buffer)); + ResponseAppend_P(PSTR(",\"CO\":%s"), measure_gas(CO, buffer)); + ResponseAppend_P(PSTR(",\"NO2\":%s"), measure_gas(NO2, buffer)); + ResponseAppend_P(PSTR(",\"C3H8\":%s"), measure_gas(C3H8, buffer)); + ResponseAppend_P(PSTR(",\"C4H10\":%s"), measure_gas(C4H10, buffer)); + ResponseAppend_P(PSTR(",\"CH4\":%s"), measure_gas(GAS_CH4, buffer)); + ResponseAppend_P(PSTR(",\"H2\":%s"), measure_gas(H2, buffer)); + ResponseAppend_P(PSTR(",\"C2H5OH\":%s}"), measure_gas(C2H5OH, buffer)); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "CO", measure_gas(CO, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "NO2", measure_gas(NO2, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C3H8", measure_gas(C3H8, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C4H10", measure_gas(C4H10, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "CH4", measure_gas(GAS_CH4, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "H2", measure_gas(H2, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C2H5OH", measure_gas(C2H5OH, buffer)); +#endif + } +} + + + + + +bool Xsns19(uint8_t function) +{ + if (!I2cEnabled(XI2C_17)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MGSPrepare(); + } + else if (mgs_detected) { + switch (function) { + case FUNC_JSON_APPEND: + MGSShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MGSShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_20_novasds.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_20_novasds.ino" +#ifdef USE_NOVA_SDS +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_20_novasds.ino" +#define XSNS_20 20 + +#include + +#ifndef STARTING_OFFSET +#define STARTING_OFFSET 30 +#endif +#if STARTING_OFFSET < 10 +#error "Please set STARTING_OFFSET >= 10" +#endif +#ifndef NOVA_SDS_RECDATA_TIMEOUT +#define NOVA_SDS_RECDATA_TIMEOUT 150 +#endif +#ifndef NOVA_SDS_DEVICE_ID +#define NOVA_SDS_DEVICE_ID 0xFFFF +#endif + +TasmotaSerial *NovaSdsSerial; + +uint8_t novasds_type = 1; +uint8_t novasds_valid = 0; +uint8_t cont_mode = 1; + +struct sds011data { + uint16_t pm100; + uint16_t pm25; +} novasds_data; +uint16_t pm100_sum; +uint16_t pm25_sum; + + +#define NOVA_SDS_REPORTING_MODE 2 +#define NOVA_SDS_QUERY_DATA 4 +#define NOVA_SDS_SET_DEVICE_ID 5 +#define NOVA_SDS_SLEEP_AND_WORK 6 +#define NOVA_SDS_WORKING_PERIOD 8 +#define NOVA_SDS_CHECK_FIRMWARE_VER 7 + #define NOVA_SDS_QUERY_MODE 0 + #define NOVA_SDS_SET_MODE 1 + #define NOVA_SDS_REPORT_ACTIVE 0 + #define NOVA_SDS_REPORT_QUERY 1 + #define NOVA_SDS_SLEEP 0 + #define NOVA_SDS_WORK 1 + + +bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) +{ + uint8_t novasds_cmnd[19] = {0xAA, 0xB4, byte1, byte2, byte3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t)(sensorid & 0xFF), (uint8_t)((sensorid>>8) & 0xFF), 0x00, 0xAB}; + + + for (uint32_t i = 2; i < 17; i++) { + novasds_cmnd[17] += novasds_cmnd[i]; + } + + + + + + NovaSdsSerial->write(novasds_cmnd, sizeof(novasds_cmnd)); + NovaSdsSerial->flush(); + + + unsigned long cmndtime = millis(); + while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( ! NovaSdsSerial->available() ) ); + if ( ! NovaSdsSerial->available() ) { + + return false; + } + uint8_t recbuf[10]; + memset(recbuf, 0, sizeof(recbuf)); + + while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( NovaSdsSerial->available() > 0) && (0xAA != (recbuf[0] = NovaSdsSerial->read())) ); + if ( 0xAA != recbuf[0] ) { + + return false; + } + + + NovaSdsSerial->readBytes(&recbuf[1], 9); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); + + if ( nullptr != buffer ) { + + memcpy(buffer, recbuf, sizeof(recbuf)); + } + + + if ((0xAB != recbuf[9] ) || (recbuf[8] != ((recbuf[2] + recbuf[3] + recbuf[4] + recbuf[5] + recbuf[6] + recbuf[7]) & 0xFF))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); + return false; + } + + return true; +} + +void NovaSdsSetWorkPeriod(void) +{ + + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, 0, NOVA_SDS_DEVICE_ID, nullptr); + + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); +} + +bool NovaSdsReadData(void) +{ + uint8_t d[10]; + if ( ! NovaSdsCommand(NOVA_SDS_QUERY_DATA, 0, 0, NOVA_SDS_DEVICE_ID, d) ) { + return false; + } + novasds_data.pm25 = (d[2] + 256 * d[3]); + novasds_data.pm100 = (d[4] + 256 * d[5]); + + return true; +} + + + +void NovaSdsSecond(void) +{ + if (!novasds_valid) + { + NovaSdsSetWorkPeriod(); + novasds_valid=1; + } + if((Settings.tele_period - Settings.novasds_startingoffset <= 0)) + { + if(!cont_mode) + { + cont_mode = 1; + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); + } + } + else + cont_mode = 0; + + if(tele_period == Settings.tele_period - Settings.novasds_startingoffset && !cont_mode) + { + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); + } + if(tele_period >= Settings.tele_period-5 && tele_period <= Settings.tele_period-2) + { + if(!(NovaSdsReadData())) novasds_valid=0; + pm100_sum += novasds_data.pm100; + pm25_sum += novasds_data.pm25; + } + if(tele_period == Settings.tele_period-1) + { + novasds_data.pm100 = pm100_sum >> 2; + novasds_data.pm25 = pm25_sum >> 2; + if(!cont_mode) + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_SLEEP, NOVA_SDS_DEVICE_ID, nullptr); + pm100_sum = pm25_sum = 0; + } +} + + + + + + + +bool NovaSdsCommandSensor(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { + if( XdrvMailbox.payload < 10 ) Settings.novasds_startingoffset = 10; + else Settings.novasds_startingoffset = XdrvMailbox.payload; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_startingoffset); + + return true; +} + +void NovaSdsInit(void) +{ + novasds_type = 0; + if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { + NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); + if (NovaSdsSerial->begin(9600)) { + if (NovaSdsSerial->hardwareSerial()) { + ClaimSerial(); + } + novasds_type = 1; + NovaSdsSetWorkPeriod(); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SDS0X1_SNS[] PROGMEM = + "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#endif + +void NovaSdsShow(bool json) +{ + if (novasds_valid) { + float pm10f = (float)(novasds_data.pm100) / 10.0f; + float pm2_5f = (float)(novasds_data.pm25) / 10.0f; + char pm10[33]; + dtostrfd(pm10f, 1, pm10); + char pm2_5[33]; + dtostrfd(pm2_5f, 1, pm2_5); + if (json) { + ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, pm2_5); + DomoticzSensor(DZ_CURRENT, pm10); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SDS0X1_SNS, pm2_5, pm10); +#endif + } + } +} + + + + + +bool Xsns20(uint8_t function) +{ + bool result = false; + + if (novasds_type) { + switch (function) { + case FUNC_INIT: + NovaSdsInit(); + break; + case FUNC_EVERY_SECOND: + NovaSdsSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_20 == XdrvMailbox.index) { + result = NovaSdsCommandSensor(); + } + break; + case FUNC_JSON_APPEND: + NovaSdsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + NovaSdsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_21_sgp30.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_21_sgp30.ino" +#ifdef USE_I2C +#ifdef USE_SGP30 +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_21_sgp30.ino" +#define XSNS_21 21 +#define XI2C_18 18 + +#define SGP30_ADDRESS 0x58 + +#include "Adafruit_SGP30.h" +Adafruit_SGP30 sgp; + +bool sgp30_type = false; +bool sgp30_ready = false; +float sgp30_abshum; + + + +void sgp30_Init(void) +{ + if (I2cActive(SGP30_ADDRESS)) { return; } + + if (sgp.begin()) { + sgp30_type = true; + + I2cSetActiveFound(SGP30_ADDRESS, "SGP30"); + } +} + + +#define POW_FUNC FastPrecisePow + +float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit) { + + + + + + float temp = NAN; + const float mw = 18.01534; + const float r = 8.31447215; + + if (isnan(temperature) || isnan(humidity) ) { + return NAN; + } + + if (tempUnit != 'C') { + temperature = (temperature - 32.0) * (5.0 / 9.0); + } + + temp = POW_FUNC(2.718281828, (17.67 * temperature) / (temperature + 243.5)); + + + return (6.112 * temp * humidity * mw) / ((273.15 + temperature) * r); +} + +#define SAVE_PERIOD 30 + +void Sgp30Update(void) +{ + sgp30_ready = false; + if (!sgp.IAQmeasure()) { + return; + } + if (global_update && (global_humidity > 0) && (global_temperature != 9999)) { + + sgp30_abshum=sgp30_AbsoluteHumidity(global_temperature,global_humidity,TempUnit()); + sgp.setHumidity(sgp30_abshum*1000); + } + sgp30_ready = true; + + + if (!(uptime%SAVE_PERIOD)) { + + uint16_t TVOC_base; + uint16_t eCO2_base; + + if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; + + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SGP30[] PROGMEM = + "{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" + "{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; +const char HTTP_SNS_AHUM[] PROGMEM = "{s}SGP30 Abs Humidity{m}%s g/m3{e}"; +#endif + +#define D_JSON_AHUM "aHumidity" + +void Sgp30Show(bool json) +{ + if (sgp30_ready) { + char abs_hum[33]; + + if (json) { + ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); + if (global_update && global_humidity>0 && global_temperature!=9999) { + + dtostrfd(sgp30_abshum,4,abs_hum); + ResponseAppend_P(PSTR(",\"" D_JSON_AHUM "\":%s"),abs_hum); + } + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC); + if (global_update) { + WSContentSend_PD(HTTP_SNS_AHUM, abs_hum); + } +#endif + } + } +} + + + + + +bool Xsns21(uint8_t function) +{ + if (!I2cEnabled(XI2C_18)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + sgp30_Init(); + } + else if (sgp30_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Sgp30Update(); + break; + case FUNC_JSON_APPEND: + Sgp30Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sgp30Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_22_sr04.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_22_sr04.ino" +#ifdef USE_SR04 + +#include +#include +# 32 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_22_sr04.ino" +#define XSNS_22 22 + +uint8_t sr04_type = 1; +int sr04_echo_pin = 0; +int sr04_trig_pin = 0; +real64_t distance; + +NewPing* sonar = nullptr; +TasmotaSerial* sonar_serial = nullptr; + + + +uint8_t Sr04TModeDetect(void) +{ + sr04_type = 0; + if (pin[GPIO_SR04_ECHO]>=99) return sr04_type; + + sr04_echo_pin = pin[GPIO_SR04_ECHO]; + sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : -1; + sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); + + if (sonar_serial->begin(9600,1)) { + DEBUG_SENSOR_LOG(PSTR("SR04: Detect mode")); + + if (sr04_trig_pin!=-1) { + sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance())!=NO_ECHO)?3:1; + } else { + sr04_type = 2; + } + } else { + sr04_type = 1; + } + + if (sr04_type < 2) { + delete sonar_serial; + sonar_serial = nullptr; + sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); + } else { + if (sonar_serial->hardwareSerial()) { + ClaimSerial(); + } + } + + AddLog_P2(LOG_LEVEL_INFO,PSTR("SR04: Mode %d"), sr04_type); + return sr04_type; +} + +uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) +{ + uint16_t ret = first; + if (first > second) { + first = second; + second = ret; + } + + if (third < first) { + return first; + } else if (third > second) { + return second; + } else { + return third; + } +} + +uint16_t Sr04TMode3Distance() { + + sonar_serial->write(0x55); + sonar_serial->flush(); + + return Sr04TMode2Distance(); +} + +uint16_t Sr04TMode2Distance(void) +{ + sonar_serial->setTimeout(300); + const char startByte = 0xff; + + if (!sonar_serial->find(startByte)) { + + return NO_ECHO; + } + + delay(5); + + uint8_t crc = sonar_serial->read(); + + uint16_t distance = ((uint16_t)crc) << 8; + + + distance += sonar_serial->read(); + crc += distance & 0x00ff; + crc += 0x00FF; + + + if (crc != sonar_serial->read()) { + AddLog_P2(LOG_LEVEL_ERROR,PSTR("SR04: Reading CRC error.")); + return NO_ECHO; + } + + return distance; +} + +void Sr04TReading(void) { + + if (sonar_serial==nullptr && sonar==nullptr) { + Sr04TModeDetect(); + } + + switch (sr04_type) { + case 3: + distance = (real64_t)(Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance()))/ 10; + break; + case 2: + + while(sonar_serial->available()) sonar_serial->read(); + distance = (real64_t)(Sr04TMiddleValue(Sr04TMode2Distance(),Sr04TMode2Distance(),Sr04TMode2Distance()))/10; + break; + case 1: + distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; + break; + default: + distance = NO_ECHO; + } + + return; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_DISTANCE[] PROGMEM = + "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; +#endif + +void Sr04Show(bool json) +{ + + if (distance != 0) { + char distance_chr[33]; + dtostrfd(distance, 3, distance_chr); + + if(json) { + ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_COUNT, distance_chr); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_DISTANCE, distance_chr); +#endif + } + } +} + + + + + +bool Xsns22(uint8_t function) +{ + bool result = false; + + if (sr04_type) { + switch (function) { + case FUNC_INIT: + result = (pin[GPIO_SR04_ECHO]<99); + break; + case FUNC_EVERY_SECOND: + Sr04TReading(); + result = true; + break; + case FUNC_JSON_APPEND: + Sr04Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sr04Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_24_si1145.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_24_si1145.ino" +#ifdef USE_I2C +#ifdef USE_SI1145 +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_24_si1145.ino" +#define XSNS_24 24 +#define XI2C_19 19 + +#define SI114X_ADDR 0X60 + + + +#define SI114X_QUERY 0X80 +#define SI114X_SET 0XA0 +#define SI114X_NOP 0X00 +#define SI114X_RESET 0X01 +#define SI114X_BUSADDR 0X02 +#define SI114X_PS_FORCE 0X05 +#define SI114X_GET_CAL 0X12 +#define SI114X_ALS_FORCE 0X06 +#define SI114X_PSALS_FORCE 0X07 +#define SI114X_PS_PAUSE 0X09 +#define SI114X_ALS_PAUSE 0X0A +#define SI114X_PSALS_PAUSE 0X0B +#define SI114X_PS_AUTO 0X0D +#define SI114X_ALS_AUTO 0X0E +#define SI114X_PSALS_AUTO 0X0F + + + +#define SI114X_PART_ID 0X00 +#define SI114X_REV_ID 0X01 +#define SI114X_SEQ_ID 0X02 +#define SI114X_INT_CFG 0X03 +#define SI114X_IRQ_ENABLE 0X04 +#define SI114X_IRQ_MODE1 0x05 +#define SI114X_IRQ_MODE2 0x06 +#define SI114X_HW_KEY 0X07 +#define SI114X_MEAS_RATE0 0X08 +#define SI114X_MEAS_RATE1 0X09 +#define SI114X_PS_RATE 0X0A +#define SI114X_PS_LED21 0X0F +#define SI114X_PS_LED3 0X10 +#define SI114X_UCOEFF0 0X13 +#define SI114X_UCOEFF1 0X14 +#define SI114X_UCOEFF2 0X15 +#define SI114X_UCOEFF3 0X16 +#define SI114X_WR 0X17 +#define SI114X_COMMAND 0X18 +#define SI114X_RESPONSE 0X20 +#define SI114X_IRQ_STATUS 0X21 +#define SI114X_ALS_VIS_DATA0 0X22 +#define SI114X_ALS_VIS_DATA1 0X23 +#define SI114X_ALS_IR_DATA0 0X24 +#define SI114X_ALS_IR_DATA1 0X25 +#define SI114X_PS1_DATA0 0X26 +#define SI114X_PS1_DATA1 0X27 +#define SI114X_PS2_DATA0 0X28 +#define SI114X_PS2_DATA1 0X29 +#define SI114X_PS3_DATA0 0X2A +#define SI114X_PS3_DATA1 0X2B +#define SI114X_AUX_DATA0_UVINDEX0 0X2C +#define SI114X_AUX_DATA1_UVINDEX1 0X2D +#define SI114X_RD 0X2E +#define SI114X_CHIP_STAT 0X30 + + + +#define SI114X_CHLIST 0X01 +#define SI114X_CHLIST_ENUV 0x80 +#define SI114X_CHLIST_ENAUX 0x40 +#define SI114X_CHLIST_ENALSIR 0x20 +#define SI114X_CHLIST_ENALSVIS 0x10 +#define SI114X_CHLIST_ENPS1 0x01 +#define SI114X_CHLIST_ENPS2 0x02 +#define SI114X_CHLIST_ENPS3 0x04 + +#define SI114X_PSLED12_SELECT 0X02 +#define SI114X_PSLED3_SELECT 0X03 + +#define SI114X_PS_ENCODE 0X05 +#define SI114X_ALS_ENCODE 0X06 + +#define SI114X_PS1_ADCMUX 0X07 +#define SI114X_PS2_ADCMUX 0X08 +#define SI114X_PS3_ADCMUX 0X09 + +#define SI114X_PS_ADC_COUNTER 0X0A +#define SI114X_PS_ADC_GAIN 0X0B +#define SI114X_PS_ADC_MISC 0X0C + +#define SI114X_ALS_IR_ADC_MUX 0X0E +#define SI114X_AUX_ADC_MUX 0X0F + +#define SI114X_ALS_VIS_ADC_COUNTER 0X10 +#define SI114X_ALS_VIS_ADC_GAIN 0X11 +#define SI114X_ALS_VIS_ADC_MISC 0X12 + +#define SI114X_LED_REC 0X1C + +#define SI114X_ALS_IR_ADC_COUNTER 0X1D +#define SI114X_ALS_IR_ADC_GAIN 0X1E +#define SI114X_ALS_IR_ADC_MISC 0X1F + + + + +#define SI114X_ADCMUX_SMALL_IR 0x00 +#define SI114X_ADCMUX_VISIABLE 0x02 +#define SI114X_ADCMUX_LARGE_IR 0x03 +#define SI114X_ADCMUX_NO 0x06 +#define SI114X_ADCMUX_GND 0x25 +#define SI114X_ADCMUX_TEMPERATURE 0x65 +#define SI114X_ADCMUX_VDD 0x75 + +#define SI114X_PSLED12_SELECT_PS1_NONE 0x00 +#define SI114X_PSLED12_SELECT_PS1_LED1 0x01 +#define SI114X_PSLED12_SELECT_PS1_LED2 0x02 +#define SI114X_PSLED12_SELECT_PS1_LED3 0x04 +#define SI114X_PSLED12_SELECT_PS2_NONE 0x00 +#define SI114X_PSLED12_SELECT_PS2_LED1 0x10 +#define SI114X_PSLED12_SELECT_PS2_LED2 0x20 +#define SI114X_PSLED12_SELECT_PS2_LED3 0x40 +#define SI114X_PSLED3_SELECT_PS2_NONE 0x00 +#define SI114X_PSLED3_SELECT_PS2_LED1 0x10 +#define SI114X_PSLED3_SELECT_PS2_LED2 0x20 +#define SI114X_PSLED3_SELECT_PS2_LED3 0x40 + +#define SI114X_ADC_GAIN_DIV1 0X00 +#define SI114X_ADC_GAIN_DIV2 0X01 +#define SI114X_ADC_GAIN_DIV4 0X02 +#define SI114X_ADC_GAIN_DIV8 0X03 +#define SI114X_ADC_GAIN_DIV16 0X04 +#define SI114X_ADC_GAIN_DIV32 0X05 + +#define SI114X_LED_CURRENT_5MA 0X01 +#define SI114X_LED_CURRENT_11MA 0X02 +#define SI114X_LED_CURRENT_22MA 0X03 +#define SI114X_LED_CURRENT_45MA 0X04 + +#define SI114X_ADC_COUNTER_1ADCCLK 0X00 +#define SI114X_ADC_COUNTER_7ADCCLK 0X01 +#define SI114X_ADC_COUNTER_15ADCCLK 0X02 +#define SI114X_ADC_COUNTER_31ADCCLK 0X03 +#define SI114X_ADC_COUNTER_63ADCCLK 0X04 +#define SI114X_ADC_COUNTER_127ADCCLK 0X05 +#define SI114X_ADC_COUNTER_255ADCCLK 0X06 +#define SI114X_ADC_COUNTER_511ADCCLK 0X07 + +#define SI114X_ADC_MISC_LOWRANGE 0X00 +#define SI114X_ADC_MISC_HIGHRANGE 0X20 +#define SI114X_ADC_MISC_ADC_NORMALPROXIMITY 0X00 +#define SI114X_ADC_MISC_ADC_RAWADC 0X04 + +#define SI114X_INT_CFG_INTOE 0X01 + +#define SI114X_IRQEN_ALS 0x01 +#define SI114X_IRQEN_PS1 0x04 +#define SI114X_IRQEN_PS2 0x08 +#define SI114X_IRQEN_PS3 0x10 + +uint16_t si1145_visible; +uint16_t si1145_infrared; +uint16_t si1145_uvindex; + +bool si1145_type = false; +uint8_t si1145_valid = 0; + + + +uint8_t Si1145ReadByte(uint8_t reg) +{ + return I2cRead8(SI114X_ADDR, reg); +} + +uint16_t Si1145ReadHalfWord(uint8_t reg) +{ + return I2cRead16LE(SI114X_ADDR, reg); +} + +bool Si1145WriteByte(uint8_t reg, uint16_t val) +{ + I2cWrite8(SI114X_ADDR, reg, val); +} + +uint8_t Si1145WriteParamData(uint8_t p, uint8_t v) +{ + Si1145WriteByte(SI114X_WR, v); + Si1145WriteByte(SI114X_COMMAND, p | SI114X_SET); + return Si1145ReadByte(SI114X_RD); +} + + + +bool Si1145Present(void) +{ + return (Si1145ReadByte(SI114X_PART_ID) == 0X45); +} + +void Si1145Reset(void) +{ + Si1145WriteByte(SI114X_MEAS_RATE0, 0); + Si1145WriteByte(SI114X_MEAS_RATE1, 0); + Si1145WriteByte(SI114X_IRQ_ENABLE, 0); + Si1145WriteByte(SI114X_IRQ_MODE1, 0); + Si1145WriteByte(SI114X_IRQ_MODE2, 0); + Si1145WriteByte(SI114X_INT_CFG, 0); + Si1145WriteByte(SI114X_IRQ_STATUS, 0xFF); + + Si1145WriteByte(SI114X_COMMAND, SI114X_RESET); + delay(10); + Si1145WriteByte(SI114X_HW_KEY, 0x17); + delay(10); +} + +void Si1145DeInit(void) +{ + + + Si1145WriteByte(SI114X_UCOEFF0, 0x29); + Si1145WriteByte(SI114X_UCOEFF1, 0x89); + Si1145WriteByte(SI114X_UCOEFF2, 0x02); + Si1145WriteByte(SI114X_UCOEFF3, 0x00); + Si1145WriteParamData(SI114X_CHLIST, SI114X_CHLIST_ENUV | SI114X_CHLIST_ENALSIR | SI114X_CHLIST_ENALSVIS | SI114X_CHLIST_ENPS1); + + + + Si1145WriteParamData(SI114X_PS1_ADCMUX, SI114X_ADCMUX_LARGE_IR); + Si1145WriteByte(SI114X_PS_LED21, SI114X_LED_CURRENT_22MA); + Si1145WriteParamData(SI114X_PSLED12_SELECT, SI114X_PSLED12_SELECT_PS1_LED1); + + + + Si1145WriteParamData(SI114X_PS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_PS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_PS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE | SI114X_ADC_MISC_ADC_RAWADC); + + + + Si1145WriteParamData(SI114X_ALS_VIS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_ALS_VIS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_ALS_VIS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); + + + + Si1145WriteParamData(SI114X_ALS_IR_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_ALS_IR_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_ALS_IR_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); + + + + Si1145WriteByte(SI114X_INT_CFG, SI114X_INT_CFG_INTOE); + Si1145WriteByte(SI114X_IRQ_ENABLE, SI114X_IRQEN_ALS); + + + + Si1145WriteByte(SI114X_MEAS_RATE0, 0xFF); + Si1145WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO); +} + +bool Si1145Begin(void) +{ + if (!Si1145Present()) { return false; } + + Si1145Reset(); + Si1145DeInit(); + return true; +} + + +uint16_t Si1145ReadUV(void) +{ + return Si1145ReadHalfWord(SI114X_AUX_DATA0_UVINDEX0); +} + + +uint16_t Si1145ReadVisible(void) +{ + return Si1145ReadHalfWord(SI114X_ALS_VIS_DATA0); +} + + +uint16_t Si1145ReadIR(void) +{ + return Si1145ReadHalfWord(SI114X_ALS_IR_DATA0); +} + + + +bool Si1145Read(void) +{ + if (si1145_valid) { si1145_valid--; } + + if (!Si1145Present()) { return false; } + + si1145_visible = Si1145ReadVisible(); + si1145_infrared = Si1145ReadIR(); + si1145_uvindex = Si1145ReadUV(); + si1145_valid = SENSOR_MAX_MISS; + return true; +} + +void Si1145Detect(void) +{ + if (I2cActive(SI114X_ADDR)) { return; } + + if (Si1145Begin()) { + si1145_type = true; + I2cSetActiveFound(SI114X_ADDR, "SI1145"); + } +} + +void Si1145Update(void) +{ + if (!Si1145Read()) { + AddLogMissed("SI1145", si1145_valid); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SI1145[] PROGMEM = + "{s}SI1145 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}" + "{s}SI1145 " D_INFRARED "{m}%d " D_UNIT_LUX "{e}" + "{s}SI1145 " D_UV_INDEX "{m}%d.%d{e}"; +#endif + +void Si1145Show(bool json) +{ + if (si1145_valid) { + if (json) { + ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), + si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, si1145_visible); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_SI1145, si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); +#endif + } + } +} + + + + + +bool Xsns24(uint8_t function) +{ + if (!I2cEnabled(XI2C_19)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Si1145Detect(); + } + else if (si1145_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Si1145Update(); + break; + case FUNC_JSON_APPEND: + Si1145Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Si1145Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_26_lm75ad.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_26_lm75ad.ino" +#ifdef USE_I2C +#ifdef USE_LM75AD +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_26_lm75ad.ino" +#define XSNS_26 26 +#define XI2C_20 20 + +#define LM75AD_ADDRESS1 0x48 +#define LM75AD_ADDRESS2 0x49 +#define LM75AD_ADDRESS3 0x4A +#define LM75AD_ADDRESS4 0x4B +#define LM75AD_ADDRESS5 0x4C +#define LM75AD_ADDRESS6 0x4D +#define LM75AD_ADDRESS7 0x4E +#define LM75AD_ADDRESS8 0x4F + +#define LM75_TEMP_REGISTER 0x00 +#define LM75_CONF_REGISTER 0x01 +#define LM75_THYST_REGISTER 0x02 +#define LM75_TOS_REGISTER 0x03 + +bool lm75ad_type = false; +uint8_t lm75ad_address; +uint8_t lm75ad_addresses[] = { LM75AD_ADDRESS1, LM75AD_ADDRESS2, LM75AD_ADDRESS3, LM75AD_ADDRESS4, LM75AD_ADDRESS5, LM75AD_ADDRESS6, LM75AD_ADDRESS7, LM75AD_ADDRESS8 }; + +void LM75ADDetect(void) +{ + for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { + lm75ad_address = lm75ad_addresses[i]; + if (I2cActive(lm75ad_address)) { + continue; } + if (!I2cSetDevice(lm75ad_address)) { + break; + } + uint16_t buffer; + if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { + if (buffer == 0x4B00) { + lm75ad_type = true; + I2cSetActiveFound(lm75ad_address, "LM75AD"); + break; + } + } + } +} + +float LM75ADGetTemp(void) +{ + int16_t sign = 1; + + uint16_t t = I2cRead16(lm75ad_address, LM75_TEMP_REGISTER); + if (t & 0x8000) { + t = (~t) +0x20; + sign = -1; + } + t = t >> 5; + return ConvertTemp(sign * t * 0.125); +} + +void LM75ADShow(bool json) +{ + float t = LM75ADGetTemp(); + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(PSTR(",\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "LM75AD", temperature, TempUnit()); +#endif + } +} + + + + + +bool Xsns26(uint8_t function) +{ + if (!I2cEnabled(XI2C_20)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + LM75ADDetect(); + } + else if (lm75ad_type) { + switch (function) { + case FUNC_JSON_APPEND: + LM75ADShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + LM75ADShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +# 28 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +#ifdef USE_I2C +#ifdef USE_APDS9960 +# 39 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +#define XSNS_27 27 +#define XI2C_21 21 + +#if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) + #warning **** Turned off conflicting drivers SHT and VEML6070 **** + #ifdef USE_SHT + #undef USE_SHT + #endif + #ifdef USE_VEML6070 + #undef USE_VEML6070 + #endif + #ifdef USE_TSL2561 + #undef USE_TSL2561 + #endif +#endif + +#define APDS9960_I2C_ADDR 0x39 + +#define APDS9960_CHIPID_1 0xAB +#define APDS9960_CHIPID_2 0x9C + +#define APDS9930_CHIPID_1 0x12 +#define APDS9930_CHIPID_2 0x39 + + +#define GESTURE_THRESHOLD_OUT 10 +#define GESTURE_SENSITIVITY_1 50 +#define GESTURE_SENSITIVITY_2 20 + +uint8_t APDS9960addr; +uint8_t APDS9960type = 0; +char APDS9960stype[] = "APDS9960"; +char currentGesture[6]; +uint8_t gesture_mode = 1; + + +volatile uint8_t recovery_loop_counter = 0; +#define APDS9960_LONG_RECOVERY 50 +#define APDS9960_MAX_GESTURE_CYCLES 50 +bool APDS9960_overload = false; + +#ifdef USE_WEBSERVER +const char HTTP_APDS_9960_SNS[] PROGMEM = + "{s}" "Red" "{m}%s{e}" + "{s}" "Green" "{m}%s{e}" + "{s}" "Blue" "{m}%s{e}" + "{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" + "{s}" "CCT" "{m}%s " "K" "{e}" + "{s}" "Proximity" "{m}%s{e}"; +#endif +# 97 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +#define FIFO_PAUSE_TIME 30 + + +#define APDS9960_ENABLE 0x80 +#define APDS9960_ATIME 0x81 +#define APDS9960_WTIME 0x83 +#define APDS9960_AILTL 0x84 +#define APDS9960_AILTH 0x85 +#define APDS9960_AIHTL 0x86 +#define APDS9960_AIHTH 0x87 +#define APDS9960_PILT 0x89 +#define APDS9960_PIHT 0x8B +#define APDS9960_PERS 0x8C +#define APDS9960_CONFIG1 0x8D +#define APDS9960_PPULSE 0x8E +#define APDS9960_CONTROL 0x8F +#define APDS9960_CONFIG2 0x90 +#define APDS9960_ID 0x92 +#define APDS9960_STATUS 0x93 +#define APDS9960_CDATAL 0x94 +#define APDS9960_CDATAH 0x95 +#define APDS9960_RDATAL 0x96 +#define APDS9960_RDATAH 0x97 +#define APDS9960_GDATAL 0x98 +#define APDS9960_GDATAH 0x99 +#define APDS9960_BDATAL 0x9A +#define APDS9960_BDATAH 0x9B +#define APDS9960_PDATA 0x9C +#define APDS9960_POFFSET_UR 0x9D +#define APDS9960_POFFSET_DL 0x9E +#define APDS9960_CONFIG3 0x9F +#define APDS9960_GPENTH 0xA0 +#define APDS9960_GEXTH 0xA1 +#define APDS9960_GCONF1 0xA2 +#define APDS9960_GCONF2 0xA3 +#define APDS9960_GOFFSET_U 0xA4 +#define APDS9960_GOFFSET_D 0xA5 +#define APDS9960_GOFFSET_L 0xA7 +#define APDS9960_GOFFSET_R 0xA9 +#define APDS9960_GPULSE 0xA6 +#define APDS9960_GCONF3 0xAA +#define APDS9960_GCONF4 0xAB +#define APDS9960_GFLVL 0xAE +#define APDS9960_GSTATUS 0xAF +#define APDS9960_IFORCE 0xE4 +#define APDS9960_PICLEAR 0xE5 +#define APDS9960_CICLEAR 0xE6 +#define APDS9960_AICLEAR 0xE7 +#define APDS9960_GFIFO_U 0xFC +#define APDS9960_GFIFO_D 0xFD +#define APDS9960_GFIFO_L 0xFE +#define APDS9960_GFIFO_R 0xFF + + +#define APDS9960_PON 0b00000001 +#define APDS9960_AEN 0b00000010 +#define APDS9960_PEN 0b00000100 +#define APDS9960_WEN 0b00001000 +#define APSD9960_AIEN 0b00010000 +#define APDS9960_PIEN 0b00100000 +#define APDS9960_GEN 0b01000000 +#define APDS9960_GVALID 0b00000001 + + +#define OFF 0 +#define ON 1 + + +#define POWER 0 +#define AMBIENT_LIGHT 1 +#define PROXIMITY 2 +#define WAIT 3 +#define AMBIENT_LIGHT_INT 4 +#define PROXIMITY_INT 5 +#define GESTURE 6 +#define ALL 7 + + +#define LED_DRIVE_100MA 0 +#define LED_DRIVE_50MA 1 +#define LED_DRIVE_25MA 2 +#define LED_DRIVE_12_5MA 3 + + +#define PGAIN_1X 0 +#define PGAIN_2X 1 +#define PGAIN_4X 2 +#define PGAIN_8X 3 + + +#define AGAIN_1X 0 +#define AGAIN_4X 1 +#define AGAIN_16X 2 +#define AGAIN_64X 3 + + +#define GGAIN_1X 0 +#define GGAIN_2X 1 +#define GGAIN_4X 2 +#define GGAIN_8X 3 + + +#define LED_BOOST_100 0 +#define LED_BOOST_150 1 +#define LED_BOOST_200 2 +#define LED_BOOST_300 3 + + +#define GWTIME_0MS 0 +#define GWTIME_2_8MS 1 +#define GWTIME_5_6MS 2 +#define GWTIME_8_4MS 3 +#define GWTIME_14_0MS 4 +#define GWTIME_22_4MS 5 +#define GWTIME_30_8MS 6 +#define GWTIME_39_2MS 7 + + +#define DEFAULT_ATIME 0xdb +#define DEFAULT_WTIME 246 +#define DEFAULT_PROX_PPULSE 0x87 +#define DEFAULT_GESTURE_PPULSE 0x89 +#define DEFAULT_POFFSET_UR 0 +#define DEFAULT_POFFSET_DL 0 +#define DEFAULT_CONFIG1 0x60 +#define DEFAULT_LDRIVE LED_DRIVE_100MA +#define DEFAULT_PGAIN PGAIN_4X +#define DEFAULT_AGAIN AGAIN_4X +#define DEFAULT_PILT 0 +#define DEFAULT_PIHT 50 +#define DEFAULT_AILT 0xFFFF +#define DEFAULT_AIHT 0 +#define DEFAULT_PERS 0x11 +#define DEFAULT_CONFIG2 0x01 +#define DEFAULT_CONFIG3 0 +#define DEFAULT_GPENTH 40 +#define DEFAULT_GEXTH 30 +#define DEFAULT_GCONF1 0x40 +#define DEFAULT_GGAIN GGAIN_4X +#define DEFAULT_GLDRIVE LED_DRIVE_100MA +#define DEFAULT_GWTIME GWTIME_2_8MS +#define DEFAULT_GOFFSET 0 +#define DEFAULT_GPULSE 0xC9 +#define DEFAULT_GCONF3 0 +#define DEFAULT_GIEN 0 + +#define ERROR 0xFF + + +enum { + DIR_NONE, + DIR_LEFT, + DIR_RIGHT, + DIR_UP, + DIR_DOWN, + DIR_ALL +}; + + +enum { + APDS9960_NA_STATE, + APDS9960_ALL_STATE +}; + + +typedef struct gesture_data_type { + uint8_t u_data[32]; + uint8_t d_data[32]; + uint8_t l_data[32]; + uint8_t r_data[32]; + uint8_t index; + uint8_t total_gestures; + uint8_t in_threshold; + uint8_t out_threshold; +} gesture_data_type; + + + gesture_data_type gesture_data_; + int16_t gesture_ud_delta_ = 0; + int16_t gesture_lr_delta_ = 0; + int16_t gesture_ud_count_ = 0; + int16_t gesture_lr_count_ = 0; + int16_t gesture_state_ = 0; + int16_t gesture_motion_ = DIR_NONE; + + typedef struct color_data_type { + uint16_t a; + uint16_t r; + uint16_t g; + uint16_t b; + uint8_t p; + uint16_t cct; + uint16_t lux; + } color_data_type; + + color_data_type color_data; + uint8_t APDS9960_aTime = DEFAULT_ATIME; +# 306 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + bool wireWriteByte(uint8_t val) + { + Wire.beginTransmission(APDS9960_I2C_ADDR); + Wire.write(val); + if( Wire.endTransmission() != 0 ) { + return false; + } + + return true; + } +# 325 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +int8_t wireReadDataBlock( uint8_t reg, + uint8_t *val, + uint16_t len) +{ + unsigned char i = 0; + + + if (!wireWriteByte(reg)) { + return -1; + } + + + Wire.requestFrom(APDS9960_I2C_ADDR, len); + while (Wire.available()) { + if (i >= len) { + return -1; + } + val[i] = Wire.read(); + i++; + } + + return i; +} + + + + + + + +void calculateColorTemperature(void) +{ + float X, Y, Z; + float xc, yc; + float n; + float cct; + + + + + + X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b); + Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); + Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b); + + + xc = (X) / (X + Y + Z); + yc = (Y) / (X + Y + Z); + + + n = (xc - 0.3320F) / (0.1858F - yc); + + + color_data.cct = (449.0F * FastPrecisePowf(n, 3)) + (3525.0F * FastPrecisePowf(n, 2)) + (6823.3F * n) + 5520.33F; + + return; +} +# 392 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getProxIntLowThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT) ; + return val; + } + + + + + + + void setProxIntLowThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); + } + + + + + + + uint8_t getProxIntHighThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; + return val; + } + + + + + + + + void setProxIntHighThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); + } +# 448 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getLEDDrive(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; + + val = (val >> 6) & 0b00000011; + + return val; + } +# 471 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void setLEDDrive(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + drive = drive << 6; + val &= 0b00111111; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 500 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getProximityGain(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; + + val = (val >> 2) & 0b00000011; + + return val; + } +# 523 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void setProximityGain(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + drive = drive << 2; + val &= 0b11110011; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 564 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void setAmbientLightGain(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + val &= 0b11111100; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 591 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getLEDBoost(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; + + + val = (val >> 4) & 0b00000011; + + return val; + } +# 615 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void setLEDBoost(uint8_t boost) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; + + boost &= 0b00000011; + boost = boost << 4; + val &= 0b11001111; + val |= boost; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, val) ; + } + + + + + + + uint8_t getProxGainCompEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + val = (val >> 5) & 0b00000001; + + return val; + } + + + + + + + void setProxGainCompEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; + } +# 683 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getProxPhotoMask(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + val &= 0b00001111; + + return val; + } +# 708 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void setProxPhotoMask(uint8_t mask) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + mask &= 0b00001111; + val &= 0b11110000; + val |= mask; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; + } + + + + + + + uint8_t getGestureEnterThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH) ; + + return val; + } + + + + + + + void setGestureEnterThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold) ; + + } + + + + + + + uint8_t getGestureExitThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GEXTH) ; + + return val; + } + + + + + + + void setGestureExitThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold) ; + } +# 786 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getGestureGain(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val = (val >> 5) & 0b00000011; + + return val; + } +# 810 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void setGestureGain(uint8_t gain) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + gain &= 0b00000011; + gain = gain << 5; + val &= 0b10011111; + val |= gain; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } +# 838 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getGestureLEDDrive(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val = (val >> 3) & 0b00000011; + + return val; + } +# 862 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void setGestureLEDDrive(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + drive &= 0b00000011; + drive = drive << 3; + val &= 0b11100111; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } +# 894 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getGestureWaitTime(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val &= 0b00000111; + + return val; + } +# 922 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void setGestureWaitTime(uint8_t time) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + time &= 0b00000111; + val &= 0b11111000; + val |= time; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } + + + + + + + void getLightIntLowThreshold(uint16_t &threshold) + { + uint8_t val_byte; + threshold = 0; + + + val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AILTL) ; + threshold = val_byte; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_byte) ; + threshold = threshold + ((uint16_t)val_byte << 8); + } + + + + + + + + void setLightIntLowThreshold(uint16_t threshold) + { + uint8_t val_low; + uint8_t val_high; + + + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTL, val_low) ; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_high) ; + + } + + + + + + + + void getLightIntHighThreshold(uint16_t &threshold) + { + uint8_t val_byte; + threshold = 0; + + + val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AIHTL); + threshold = val_byte; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_byte) ; + threshold = threshold + ((uint16_t)val_byte << 8); + } + + + + + + + void setLightIntHighThreshold(uint16_t threshold) + { + uint8_t val_low; + uint8_t val_high; + + + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTL, val_low); + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_high) ; + } + + + + + + + + void getProximityIntLowThreshold(uint8_t &threshold) + { + threshold = 0; + + + threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); + + } + + + + + + + void setProximityIntLowThreshold(uint8_t threshold) + { + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold) ; + } +# 1055 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" + void getProximityIntHighThreshold(uint8_t &threshold) + { + threshold = 0; + + + threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; + + } + + + + + + + void setProximityIntHighThreshold(uint8_t threshold) + { + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold) ; + } + + + + + + + uint8_t getAmbientLightIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + val = (val >> 4) & 0b00000001; + + return val; + } + + + + + + + void setAmbientLightIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); + + + enable &= 0b00000001; + enable = enable << 4; + val &= 0b11101111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; + } + + + + + + + uint8_t getProximityIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + val = (val >> 5) & 0b00000001; + + return val; + } + + + + + + + void setProximityIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; + } + + + + + + + uint8_t getGestureIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + val = (val >> 1) & 0b00000001; + + return val; + } + + + + + + + void setGestureIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + enable &= 0b00000001; + enable = enable << 1; + val &= 0b11111101; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; + } + + + + + + void clearAmbientLightInt(void) + { + uint8_t throwaway; + throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); + } + + + + + + void clearProximityInt(void) + { + uint8_t throwaway; + throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR) ; + + } + + + + + + + uint8_t getGestureMode(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + val &= 0b00000001; + + return val; + } + + + + + + + void setGestureMode(uint8_t mode) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + mode &= 0b00000001; + val &= 0b11111110; + val |= mode; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; + } + + +bool APDS9960_init(void) +{ + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, DEFAULT_WTIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG1, DEFAULT_CONFIG1) ; + + setLEDDrive(DEFAULT_LDRIVE); + + setProximityGain(DEFAULT_PGAIN); + + setAmbientLightGain(DEFAULT_AGAIN); + + setProxIntLowThresh(DEFAULT_PILT) ; + + setProxIntHighThresh(DEFAULT_PIHT); + + setLightIntLowThreshold(DEFAULT_AILT) ; + + setLightIntHighThreshold(DEFAULT_AIHT) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PERS, DEFAULT_PERS) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, DEFAULT_CONFIG2) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3) ; + + + setGestureEnterThresh(DEFAULT_GPENTH); + + setGestureExitThresh(DEFAULT_GEXTH) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF1, DEFAULT_GCONF1) ; + + setGestureGain(DEFAULT_GGAIN) ; + + setGestureLEDDrive(DEFAULT_GLDRIVE) ; + + setGestureWaitTime(DEFAULT_GWTIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPULSE, DEFAULT_GPULSE) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3) ; + + setGestureIntEnable(DEFAULT_GIEN); + + disablePower(); + + return true; +} +# 1333 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getMode(void) +{ + uint8_t enable_value; + + + enable_value = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + return enable_value; +} + + + + + + + +void setMode(uint8_t mode, uint8_t enable) +{ + uint8_t reg_val; + + + reg_val = getMode(); + + + + enable = enable & 0x01; + if( mode >= 0 && mode <= 6 ) { + if (enable) { + reg_val |= (1 << mode); + } else { + reg_val &= ~(1 << mode); + } + } else if( mode == ALL ) { + if (enable) { + reg_val = 0x7F; + } else { + reg_val = 0x00; + } + } + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, reg_val) ; +} + + + + + + +void enableLightSensor(void) +{ + + setAmbientLightGain(DEFAULT_AGAIN); + setAmbientLightIntEnable(0); + enablePower() ; + setMode(AMBIENT_LIGHT, 1) ; +} + + + + + +void disableLightSensor(void) +{ + setAmbientLightIntEnable(0) ; + setMode(AMBIENT_LIGHT, 0) ; +} + + + + + + +void enableProximitySensor(void) +{ + + setProximityGain(DEFAULT_PGAIN); + setLEDDrive(DEFAULT_LDRIVE) ; + setProximityIntEnable(0) ; + enablePower(); + setMode(PROXIMITY, 1) ; +} + + + + + +void disableProximitySensor(void) +{ + setProximityIntEnable(0) ; + setMode(PROXIMITY, 0) ; +} + + + + + + +void enableGestureSensor(void) +{ + + + + + + + + resetGestureParameters(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ; + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ; + setLEDBoost(LED_BOOST_100); + setGestureIntEnable(0) ; + setGestureMode(1); + enablePower() ; + setMode(WAIT, 1) ; + setMode(PROXIMITY, 1) ; + setMode(GESTURE, 1); +} + + + + + +void disableGestureSensor(void) +{ + resetGestureParameters(); + setGestureIntEnable(0) ; + setGestureMode(0) ; + setMode(GESTURE, 0) ; +} + + + + + + +bool isGestureAvailable(void) +{ + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS) ; + + + val &= APDS9960_GVALID; + + + if( val == 1) { + return true; + } else { + return false; + } +} + + + + + + +int16_t readGesture(void) +{ + uint8_t fifo_level = 0; + uint8_t bytes_read = 0; + uint8_t fifo_data[128]; + uint8_t gstatus; + uint16_t motion; + uint16_t i; + uint8_t gesture_loop_counter = 0; + + + if( !isGestureAvailable() || !(getMode() & 0b01000001) ) { + return DIR_NONE; + } + + + while(1) { + if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ + disableGestureSensor(); + APDS9960_overload = true; + AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); + } + gesture_loop_counter += 1; + + delay(FIFO_PAUSE_TIME); + + + gstatus = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); + + + if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { + + + fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ; + + + if( fifo_level > 0) { + bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, + (uint8_t*)fifo_data, + (fifo_level * 4) ); + if( bytes_read == -1 ) { + return ERROR; + } + + + if( bytes_read >= 4 ) { + for( i = 0; i < bytes_read; i += 4 ) { + gesture_data_.u_data[gesture_data_.index] = \ + fifo_data[i + 0]; + gesture_data_.d_data[gesture_data_.index] = \ + fifo_data[i + 1]; + gesture_data_.l_data[gesture_data_.index] = \ + fifo_data[i + 2]; + gesture_data_.r_data[gesture_data_.index] = \ + fifo_data[i + 3]; + gesture_data_.index++; + gesture_data_.total_gestures++; + } + + if( processGestureData() ) { + if( decodeGesture() ) { + + } + } + + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; + } + } + } else { + + + delay(FIFO_PAUSE_TIME); + decodeGesture(); + motion = gesture_motion_; + resetGestureParameters(); + return motion; + } + } +} + + + + + +void enablePower(void) +{ + setMode(POWER, 1) ; +} + + + + + +void disablePower(void) +{ + setMode(POWER, 0) ; +} +# 1600 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +void readAllColorAndProximityData(void) +{ + if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) + { + + + } +} +# 1616 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +void resetGestureParameters(void) +{ + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; + + gesture_ud_delta_ = 0; + gesture_lr_delta_ = 0; + + gesture_ud_count_ = 0; + gesture_lr_count_ = 0; + + gesture_state_ = 0; + gesture_motion_ = DIR_NONE; +} + + + + + + +bool processGestureData(void) +{ + uint8_t u_first = 0; + uint8_t d_first = 0; + uint8_t l_first = 0; + uint8_t r_first = 0; + uint8_t u_last = 0; + uint8_t d_last = 0; + uint8_t l_last = 0; + uint8_t r_last = 0; + uint16_t ud_ratio_first; + uint16_t lr_ratio_first; + uint16_t ud_ratio_last; + uint16_t lr_ratio_last; + uint16_t ud_delta; + uint16_t lr_delta; + uint16_t i; + + + if( gesture_data_.total_gestures <= 4 ) { + return false; + } + + + if( (gesture_data_.total_gestures <= 32) && \ + (gesture_data_.total_gestures > 0) ) { + + + for( i = 0; i < gesture_data_.total_gestures; i++ ) { + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_first = gesture_data_.u_data[i]; + d_first = gesture_data_.d_data[i]; + l_first = gesture_data_.l_data[i]; + r_first = gesture_data_.r_data[i]; + break; + } + } + + + if( (u_first == 0) || (d_first == 0) || \ + (l_first == 0) || (r_first == 0) ) { + + return false; + } + + for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { + + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_last = gesture_data_.u_data[i]; + d_last = gesture_data_.d_data[i]; + l_last = gesture_data_.l_data[i]; + r_last = gesture_data_.r_data[i]; + break; + } + } + } + + + ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); + lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); + ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); + lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); + + + ud_delta = ud_ratio_last - ud_ratio_first; + lr_delta = lr_ratio_last - lr_ratio_first; + + + gesture_ud_delta_ += ud_delta; + gesture_lr_delta_ += lr_delta; + + + if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = 1; + } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = -1; + } else { + gesture_ud_count_ = 0; + } + + + if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = 1; + } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = -1; + } else { + gesture_lr_count_ = 0; + } + return false; +} + + + + + + +bool decodeGesture(void) +{ + + + if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_UP; + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_DOWN; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { + gesture_motion_ = DIR_RIGHT; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { + gesture_motion_ = DIR_LEFT; + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else { + return false; + } + + return true; +} + +void handleGesture(void) { + if (isGestureAvailable() ) { + switch (readGesture()) { + case DIR_UP: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("UP")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Up")); + break; + case DIR_DOWN: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("DOWN")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Down")); + break; + case DIR_LEFT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LEFT")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); + break; + case DIR_RIGHT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("RIGHT")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); + break; + default: + if(APDS9960_overload) + { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); + } + else{ + AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); + } + } + MqttPublishSensor(); + } +} + +void APDS9960_adjustATime(void) +{ + + I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); + + + if (color_data.a < (uint16_t)20){ + APDS9960_aTime = 0x40; + } + else if (color_data.a < (uint16_t)40){ + APDS9960_aTime = 0x80; + } + else if (color_data.a < (uint16_t)50){ + APDS9960_aTime = DEFAULT_ATIME; + } + else if (color_data.a < (uint16_t)70){ + APDS9960_aTime = 0xc0; + } + if (color_data.a < 200){ + APDS9960_aTime = 0xe9; + } + + + + else{ + APDS9960_aTime = 0xff; + } + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime); + enablePower(); + enableLightSensor(); + delay(20); +} + + +void APDS9960_loop(void) +{ + if (recovery_loop_counter > 0){ + recovery_loop_counter -= 1; + } + if (recovery_loop_counter == 1 && APDS9960_overload){ + enableGestureSensor(); + APDS9960_overload = false; + Response_P(PSTR("{\"Gesture\":\"On\"}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + gesture_mode = 1; + } + + if (gesture_mode) { + if (recovery_loop_counter == 0){ + handleGesture(); + + if (APDS9960_overload) + { + disableGestureSensor(); + recovery_loop_counter = APDS9960_LONG_RECOVERY; + Response_P(PSTR("{\"Gesture\":\"Off\"}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + gesture_mode = 0; + } + } + } +} + +void APDS9960_detect(void) +{ + if (APDS9960type || I2cActive(APDS9960_I2C_ADDR)) { return; } + + APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); + if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2) { + if (APDS9960_init()) { + I2cSetActiveFound(APDS9960_I2C_ADDR, APDS9960stype); + + enableProximitySensor(); + enableGestureSensor(); + } else { + APDS9960type = 0; + } + } else { + APDS9960type = 0; + } + currentGesture[0] = '\0'; +} + + + + + +void APDS9960_show(bool json) +{ + if (!APDS9960type) { return; } + + if (!gesture_mode && !APDS9960_overload) { + char red_chr[10]; + char green_chr[10]; + char blue_chr[10]; + char ambient_chr[10]; + char cct_chr[10]; + char prox_chr[10]; + + readAllColorAndProximityData(); + + sprintf (ambient_chr, "%u", color_data.a/4); + sprintf (red_chr, "%u", color_data.r); + sprintf (green_chr, "%u", color_data.g); + sprintf (blue_chr, "%u", color_data.b ); + sprintf (prox_chr, "%u", color_data.p ); + + + + + + calculateColorTemperature(); + sprintf (cct_chr, "%u", color_data.cct); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), + APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); +#endif + } + } + else { + if (json && (currentGesture[0] != '\0' )) { + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); + currentGesture[0] = '\0'; + } + } +} +# 1961 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" +bool APDS9960CommandSensor(void) +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + disableGestureSensor(); + gesture_mode = 0; + enableLightSensor(); + APDS9960_overload = false; + break; + case 1: + if (APDS9960type) { + setGestureGain(DEFAULT_GGAIN); + setProximityGain(DEFAULT_PGAIN); + disableLightSensor(); + enableGestureSensor(); + gesture_mode = 1; + } + break; + case 2: + if (APDS9960type) { + setGestureGain(GGAIN_2X); + setProximityGain(PGAIN_2X); + disableLightSensor(); + enableGestureSensor(); + gesture_mode = 1; + } + break; + default: + int temp_aTime = (uint8_t)XdrvMailbox.payload; + if (temp_aTime > 2 && temp_aTime < 256){ + disablePower(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, temp_aTime); + enablePower(); + enableLightSensor(); + } + break; + } + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); + + return serviced; +} + + + + + +bool Xsns27(uint8_t function) +{ + if (!I2cEnabled(XI2C_21)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + APDS9960_detect(); + } + else if (APDS9960type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + APDS9960_loop(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_27 == XdrvMailbox.index) { + result = APDS9960CommandSensor(); + } + break; + case FUNC_JSON_APPEND: + APDS9960_show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + APDS9960_show(0); + break; +#endif + } + } + return result; +} +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_28_tm1638.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_28_tm1638.ino" +#ifdef USE_TM1638 + + + + + + +#define XSNS_28 28 + +#define TM1638_COLOR_NONE 0 +#define TM1638_COLOR_RED 1 +#define TM1638_COLOR_GREEN 2 + +#define TM1638_CLOCK_DELAY 1 + +uint8_t tm1638_type = 1; +uint8_t tm1638_clock_pin = 0; +uint8_t tm1638_data_pin = 0; +uint8_t tm1638_strobe_pin = 0; +uint8_t tm1638_displays = 8; +uint8_t tm1638_active_display = 1; +uint8_t tm1638_intensity = 0; +uint8_t tm1638_state = 0; + + + + + + +void Tm16XXSend(uint8_t data) +{ + for (uint32_t i = 0; i < 8; i++) { + digitalWrite(tm1638_data_pin, !!(data & (1 << i))); + digitalWrite(tm1638_clock_pin, LOW); + delayMicroseconds(TM1638_CLOCK_DELAY); + digitalWrite(tm1638_clock_pin, HIGH); + } +} + +void Tm16XXSendCommand(uint8_t cmd) +{ + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(cmd); + digitalWrite(tm1638_strobe_pin, HIGH); +} + +void TM16XXSendData(uint8_t address, uint8_t data) +{ + Tm16XXSendCommand(0x44); + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0xC0 | address); + Tm16XXSend(data); + digitalWrite(tm1638_strobe_pin, HIGH); +} + +uint8_t Tm16XXReceive(void) +{ + uint8_t temp = 0; + + + pinMode(tm1638_data_pin, INPUT); + digitalWrite(tm1638_data_pin, HIGH); + + for (uint32_t i = 0; i < 8; ++i) { + digitalWrite(tm1638_clock_pin, LOW); + delayMicroseconds(TM1638_CLOCK_DELAY); + temp |= digitalRead(tm1638_data_pin) << i; + digitalWrite(tm1638_clock_pin, HIGH); + } + + + pinMode(tm1638_data_pin, OUTPUT); + digitalWrite(tm1638_data_pin, LOW); + + return temp; +} + + + +void Tm16XXClearDisplay(void) +{ + for (uint32_t i = 0; i < tm1638_displays; i++) { + TM16XXSendData(i << 1, 0); + } +} + +void Tm1638SetLED(uint8_t color, uint8_t pos) +{ + TM16XXSendData((pos << 1) + 1, color); +} + +void Tm1638SetLEDs(word leds) +{ + for (uint32_t i = 0; i < tm1638_displays; i++) { + uint8_t color = 0; + + if ((leds & (1 << i)) != 0) { + color |= TM1638_COLOR_RED; + } + + if ((leds & (1 << (i + 8))) != 0) { + color |= TM1638_COLOR_GREEN; + } + + Tm1638SetLED(color, i); + } +} + +uint8_t Tm1638GetButtons(void) +{ + uint8_t keys = 0; + + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0x42); + for (uint32_t i = 0; i < 4; i++) { + keys |= Tm16XXReceive() << i; + } + digitalWrite(tm1638_strobe_pin, HIGH); + + return keys; +} + + + +void TmInit(void) +{ + tm1638_type = 0; + if ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99)) { + tm1638_clock_pin = pin[GPIO_TM16CLK]; + tm1638_data_pin = pin[GPIO_TM16DIO]; + tm1638_strobe_pin = pin[GPIO_TM16STB]; + + pinMode(tm1638_data_pin, OUTPUT); + pinMode(tm1638_clock_pin, OUTPUT); + pinMode(tm1638_strobe_pin, OUTPUT); + + digitalWrite(tm1638_strobe_pin, HIGH); + digitalWrite(tm1638_clock_pin, HIGH); + + Tm16XXSendCommand(0x40); + Tm16XXSendCommand(0x80 | (tm1638_active_display ? 8 : 0) | tmin(7, tm1638_intensity)); + + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0xC0); + for (uint32_t i = 0; i < 16; i++) { + Tm16XXSend(0x00); + } + digitalWrite(tm1638_strobe_pin, HIGH); + + tm1638_type = 1; + tm1638_state = 1; + } +} + +void TmLoop(void) +{ + if (tm1638_state) { + uint8_t buttons = Tm1638GetButtons(); + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + SwitchSetVirtual(i, (buttons &1) ^1); + uint8_t color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; + Tm1638SetLED(color, i); + buttons >>= 1; + } + SwitchHandler(1); + } +} +# 201 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_28_tm1638.ino" +bool Xsns28(uint8_t function) +{ + bool result = false; + + if (tm1638_type) { + switch (function) { + case FUNC_INIT: + TmInit(); + break; + case FUNC_EVERY_50_MSECOND: + TmLoop(); + break; +# 223 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_28_tm1638.ino" + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_29_mcp230xx.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_29_mcp230xx.ino" +#ifdef USE_I2C +#ifdef USE_MCP230xx +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_29_mcp230xx.ino" +#define XSNS_29 29 +#define XI2C_22 22 + + + + + +uint8_t MCP230xx_IODIR = 0x00; +uint8_t MCP230xx_GPINTEN = 0x02; +uint8_t MCP230xx_IOCON = 0x05; +uint8_t MCP230xx_GPPU = 0x06; +uint8_t MCP230xx_INTF = 0x07; +uint8_t MCP230xx_INTCAP = 0x08; +uint8_t MCP230xx_GPIO = 0x09; + +uint8_t mcp230xx_type = 0; +uint8_t mcp230xx_pincount = 0; +uint8_t mcp230xx_int_en = 0; +uint8_t mcp230xx_int_prio_counter = 0; +uint8_t mcp230xx_int_counter_en = 0; +uint8_t mcp230xx_int_retainer_en = 0; +uint8_t mcp230xx_int_sec_counter = 0; + +uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +uint8_t mcp230xx_int_retainer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +unsigned long int_millis[16]; + +const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL_UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; + +const char MCP230XX_INTCFG_RESPONSE[] PROGMEM = "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + +#ifdef USE_MCP230xx_OUTPUT +const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; +#endif + +void MCP230xx_CheckForIntCounter(void) { + uint8_t en = 0; + for (uint32_t ca=0;ca<16;ca++) { + if (Settings.mcp230xx_config[ca].int_count_en) { + en=1; + } + } + if (!Settings.mcp230xx_int_timer) en=0; + mcp230xx_int_counter_en=en; + if (!mcp230xx_int_counter_en) { + for (uint32_t ca=0;ca<16;ca++) { + mcp230xx_int_counter[ca] = 0; + } + } +} + +void MCP230xx_CheckForIntRetainer(void) { + uint8_t en = 0; + for (uint32_t ca=0;ca<16;ca++) { + if (Settings.mcp230xx_config[ca].int_retain_flag) { + en=1; + } + } + mcp230xx_int_retainer_en=en; + if (!mcp230xx_int_retainer_en) { + for (uint32_t ca=0;ca<16;ca++) { + mcp230xx_int_retainer[ca] = 0; + } + } +} + +const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { +#ifdef USE_MCP230xx_OUTPUT +if ((6 == pinmod) && (statu < 2)) { statu = abs(statu-1); } +#endif + switch (statu) { + case 0: + return "OFF"; + break; + case 1: + return "ON"; + break; +#ifdef USE_MCP230xx_OUTPUT + case 2: + return "TOGGLE"; + break; +#endif + } + return ""; +} + +const char* IntModeTxt(uint8_t intmo) { + switch (intmo) { + case 0: + return "ALL"; + break; + case 1: + return "EVENT"; + break; + case 2: + return "TELE"; + break; + case 3: + return "DISABLED"; + break; + } + return ""; +} + +uint8_t MCP230xx_readGPIO(uint8_t port) { + return I2cRead8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port); +} + +void MCP230xx_ApplySettings(void) +{ + uint8_t int_en = 0; + for (uint32_t mcp230xx_port = 0; mcp230xx_port < mcp230xx_type; mcp230xx_port++) { + uint8_t reg_gppu = 0; + uint8_t reg_gpinten = 0; + uint8_t reg_iodir = 0xFF; +#ifdef USE_MCP230xx_OUTPUT + uint8_t reg_portpins = 0x00; +#endif + for (uint32_t idx = 0; idx < 8; idx++) { + switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { + case 0 ... 1: + reg_iodir |= (1 << idx); + break; + case 2 ... 4: + reg_iodir |= (1 << idx); + reg_gpinten |= (1 << idx); + int_en = 1; + break; +#ifdef USE_MCP230xx_OUTPUT + case 5 ... 6: + reg_iodir &= ~(1 << idx); + if (Settings.flag.save_state) { + reg_portpins |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); + } else { + if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { + reg_portpins |= (1 << idx); + } + } + break; +#endif + default: + break; + } +#ifdef USE_MCP230xx_OUTPUT + if ((Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { + reg_gppu |= (1 << idx); + } +#else + if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { + reg_gppu |= (1 << idx); + } +#endif + } + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPPU+mcp230xx_port, reg_gppu); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IODIR+mcp230xx_port, reg_iodir); +#ifdef USE_MCP230xx_OUTPUT + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); +#endif + } + for (uint32_t idx=0;idx 0) { + if (I2cValidRead8(&mcp230xx_intcap, USE_MCP230xx_ADDR, MCP230xx_INTCAP+mcp230xx_port)) { + for (uint32_t intp = 0; intp < 8; intp++) { + if ((intf >> intp) & 0x01) { + report_int = 0; + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode > 1) { + switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode) { + case 2: + report_int = 1; + break; + case 3: + if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; + break; + case 4: + if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; + break; + default: + break; + } + + if ((mcp230xx_int_counter_en) && (report_int)) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { + mcp230xx_int_counter[intp+(mcp230xx_port*8)]++; + } + } + + if (report_int) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { + mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]++; + if (mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)] >= Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { + mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]=0; + } else { + report_int = 0; + } + } + } + + if (report_int) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_retain_flag) { + mcp230xx_int_retainer[intp+(mcp230xx_port*8)] = 1; + report_int = 0; + } + } + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { + report_int = 0; + } + if (report_int) { + bool int_tele = false; + bool int_event = false; + unsigned long millis_now = millis(); + unsigned long millis_since_last_int = millis_now - int_millis[intp+(mcp230xx_port*8)]; + int_millis[intp+(mcp230xx_port*8)]=millis_now; + switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_mode) { + case 0: + int_tele=true; + int_event=true; + break; + case 1: + int_event=true; + break; + case 2: + int_tele=true; + break; + } + if (int_tele) { + ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), + intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); + } + if (int_event) { + char command[19]; + sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); + ExecuteCommand(command, SRC_RULE); + } + } + } + } + } + } + } + } + } +} + +void MCP230xx_Show(bool json) +{ + if (json) { + uint8_t gpio = MCP230xx_readGPIO(0); + ResponseAppend_P(PSTR(",\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + if (2 == mcp230xx_type) { + gpio = MCP230xx_readGPIO(1); + ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + } + ResponseJsonEnd(); + } +} + +#ifdef USE_MCP230xx_OUTPUT + +void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { + uint8_t portpins; + uint8_t port = 0; + uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; + uint8_t interlock = Settings.flag.interlock; + int pinadd = (pin % 2)+1-(3*(pin % 2)); + char cmnd[7], stt[4]; + if (pin > 7) { port = 1; } + portpins = MCP230xx_readGPIO(port); + if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { + if (pinstate < 2) { + if (6 == pinmo) { + if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins |= (1 << (pin+pinadd-(port*8))),portpins &= ~(1 << (pin-(port*8))); + } else { + if (pinstate) portpins &= ~(1 << (pin+pinadd-(port*8))),portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); + } + } else { + if (6 == pinmo) { + portpins |= (1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); + } else { + portpins &= ~(1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); + } + } + } else { + if (pinstate < 2) { + if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); + } else { + portpins ^= (1 << (pin-(port*8))); + } + } + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port, portpins); + if (Settings.flag.save_state) { + Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; + Settings.mcp230xx_config[pin+pinadd].saved_state=portpins>>(pin+pinadd-(port*8))&1; + } + sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); + sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); + if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { + char stt1[4]; + sprintf(stt1,ConvertNumTxt((portpins >> (pin+pinadd-(port*8))&1), pinmo)); + Response_P(PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); + } else { + Response_P(MCP230XX_CMND_RESPONSE, pin, cmnd, stt); + } +} + +#endif + +void MCP230xx_Reset(uint8_t pinmode) { + uint8_t pullup = 0; + if ((pinmode > 1) && (pinmode < 5)) { pullup=1; } + for (uint32_t pinx=0;pinx<16;pinx++) { + Settings.mcp230xx_config[pinx].pinmode=pinmode; + Settings.mcp230xx_config[pinx].pullup=pullup; + Settings.mcp230xx_config[pinx].saved_state=0; + if ((pinmode > 1) && (pinmode < 5)) { + Settings.mcp230xx_config[pinx].int_report_mode=0; + } else { + Settings.mcp230xx_config[pinx].int_report_mode=3; + } + Settings.mcp230xx_config[pinx].int_report_defer=0; + Settings.mcp230xx_config[pinx].int_count_en=0; + Settings.mcp230xx_config[pinx].int_retain_flag=0; + Settings.mcp230xx_config[pinx].spare13=0; + Settings.mcp230xx_config[pinx].spare14=0; + Settings.mcp230xx_config[pinx].spare15=0; + } + Settings.mcp230xx_int_prio = 0; + Settings.mcp230xx_int_timer = 0; + MCP230xx_ApplySettings(); + char pulluptxt[7]; + char intmodetxt[9]; + sprintf(pulluptxt,ConvertNumTxt(pullup)); + uint8_t intmode = 3; + if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } + sprintf(intmodetxt,IntModeTxt(intmode)); + Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); +} + +bool MCP230xx_Command(void) +{ + bool serviced = true; + bool validpin = false; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((intpri >= 0) && (intpri <= 20)) { + Settings.mcp230xx_int_prio = intpri; + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTTIMER")) { + if (paramcount > 1) { + uint8_t inttim = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((inttim >= 0) && (inttim <= 3600)) { + Settings.mcp230xx_int_timer = inttim; + MCP230xx_CheckForIntCounter(); + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTDEF")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t intdef = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((intdef >= 0) && (intdef <= 15)) { + Settings.mcp230xx_config[pin].int_report_defer=intdef; + if (Settings.mcp230xx_config[pin].int_count_en) { + Settings.mcp230xx_config[pin].int_count_en=0; + MCP230xx_CheckForIntCounter(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); + } + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTCNT")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t intcnt = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((intcnt >= 0) && (intcnt <= 1)) { + Settings.mcp230xx_config[pin].int_count_en=intcnt; + if (Settings.mcp230xx_config[pin].int_report_defer) { + Settings.mcp230xx_config[pin].int_report_defer=0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTDEF for pin D%i"),pin); + } + if (Settings.mcp230xx_config[pin].int_report_mode < 3) { + Settings.mcp230xx_config[pin].int_report_mode=3; + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled immediate interrupt/telemetry reporting for pin D%i"),pin); + } + if ((Settings.mcp230xx_config[pin].int_count_en) && (!Settings.mcp230xx_int_timer)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); + } + MCP230xx_CheckForIntCounter(); + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTRETAIN")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((int_retain >= 0) && (int_retain <= 1)) { + Settings.mcp230xx_config[pin].int_retain_flag=int_retain; + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + MCP230xx_CheckForIntRetainer(); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + + if (pin < mcp230xx_pincount) { + if (0 == pin) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "0")) validpin=true; + } else { + validpin=true; + } + } + if (validpin && (paramcount > 1)) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "?")) { + uint8_t port = 0; + if (pin > 7) { port = 1; } + uint8_t portdata = MCP230xx_readGPIO(port); + char pulluptxtr[7],pinstatustxtr[7]; + char intmodetxt[9]; + sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); + sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); +#ifdef USE_MCP230xx_OUTPUT + uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); +#else + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); +#endif + return serviced; + } +#ifdef USE_MCP230xx_OUTPUT + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "1"))) { + MCP230xx_SetOutPin(pin,abs(pincmd-1)); + return serviced; + } + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0"))) { + MCP230xx_SetOutPin(pin,pincmd); + return serviced; + } + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "2"))) { + MCP230xx_SetOutPin(pin,2); + return serviced; + } + } +#endif + uint8_t pinmode = 0; + uint8_t pullup = 0; + uint8_t intmode = 0; + if (paramcount > 1) { + pinmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + } + if (paramcount > 2) { + pullup = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + } + if (paramcount > 3) { + intmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + } +#ifdef USE_MCP230xx_OUTPUT + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2) && (paramcount > 2)) { +#else + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 2)) { +#endif + Settings.mcp230xx_config[pin].pinmode=pinmode; + Settings.mcp230xx_config[pin].pullup=pullup; + if ((pinmode > 1) && (pinmode < 5)) { + if ((intmode >= 0) && (intmode <= 3)) { + Settings.mcp230xx_config[pin].int_report_mode=intmode; + } + } else { + Settings.mcp230xx_config[pin].int_report_mode=3; + } + MCP230xx_ApplySettings(); + uint8_t port = 0; + if (pin > 7) { port = 1; } + uint8_t portdata = MCP230xx_readGPIO(port); + char pulluptxtc[7], pinstatustxtc[7]; + char intmodetxt[9]; + sprintf(pulluptxtc,ConvertNumTxt(pullup)); + sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); +#ifdef USE_MCP230xx_OUTPUT + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); +#else + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); +#endif + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); + return serviced; + } + } else { + serviced=false; + return serviced; + } + return serviced; +} + +#ifdef USE_MCP230xx_DISPLAYOUTPUT + +const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; + +void MCP230xx_UpdateWebData(void) +{ + uint8_t gpio1 = MCP230xx_readGPIO(0); + uint8_t gpio2 = 0; + if (2 == mcp230xx_type) { + gpio2 = MCP230xx_readGPIO(1); + } + uint16_t gpio = (gpio2 << 8) + gpio1; + for (uint32_t pin = 0; pin < mcp230xx_pincount; pin++) { + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + char stt[7]; + sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); + WSContentSend_PD(HTTP_SNS_MCP230xx_OUTPUT, pin, stt); + } + } +} + +#endif + +#ifdef USE_MCP230xx_OUTPUT + +void MCP230xx_OutputTelemetry(void) +{ + uint8_t outputcount = 0; + uint16_t gpiototal = 0; + uint8_t gpioa = 0; + uint8_t gpiob = 0; + gpioa=MCP230xx_readGPIO(0); + if (2 == mcp230xx_type) { gpiob=MCP230xx_readGPIO(1); } + gpiototal=((uint16_t)gpiob << 8) | gpioa; + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; + } + if (outputcount) { + char stt[7]; + ResponseTime_P(PSTR(",\"MCP230_OUT\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].pinmode >= 5) { + sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); + ResponseAppend_P(PSTR("\"OUT_D%i\":\"%s\","),pinx,stt); + } + } + ResponseAppend_P(PSTR("\"END\":1}}")); + MqttPublishTeleSensor(); + } +} + +#endif + +void MCP230xx_Interrupt_Counter_Report(void) { + ResponseTime_P(PSTR(",\"MCP230_INTTIMER\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].int_count_en) { + ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); + mcp230xx_int_counter[pinx]=0; + } + } + ResponseAppend_P(PSTR("\"END\":1}}")); + MqttPublishTeleSensor(); + mcp230xx_int_sec_counter = 0; +} + +void MCP230xx_Interrupt_Retain_Report(void) { + uint16_t retainresult = 0; + ResponseTime_P(PSTR(",\"MCP_INTRETAIN\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].int_retain_flag) { + ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); + retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); + mcp230xx_int_retainer[pinx]=0; + } + } + ResponseAppend_P(PSTR("\"Value\":%u}}"),retainresult); + MqttPublishTeleSensor(); +} + + + + + +bool Xsns29(uint8_t function) +{ + if (!I2cEnabled(XI2C_22)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MCP230xx_Detect(); + } + else if (mcp230xx_type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (mcp230xx_int_en) { + mcp230xx_int_prio_counter++; + if ((mcp230xx_int_prio_counter) >= (Settings.mcp230xx_int_prio)) { + MCP230xx_CheckForInterrupt(); + mcp230xx_int_prio_counter=0; + } + } + break; + case FUNC_EVERY_SECOND: + if (mcp230xx_int_counter_en) { + mcp230xx_int_sec_counter++; + if (mcp230xx_int_sec_counter >= Settings.mcp230xx_int_timer) { + MCP230xx_Interrupt_Counter_Report(); + } + } + if (tele_period == 0) { + if (mcp230xx_int_retainer_en) { + MCP230xx_Interrupt_Retain_Report(); + } +#ifdef USE_MCP230xx_OUTPUT + MCP230xx_OutputTelemetry(); +#endif + } + break; + case FUNC_JSON_APPEND: + MCP230xx_Show(1); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_29 == XdrvMailbox.index) { + result = MCP230xx_Command(); + } + break; +#ifdef USE_WEBSERVER +#ifdef USE_MCP230xx_OUTPUT +#ifdef USE_MCP230xx_DISPLAYOUTPUT + case FUNC_WEB_SENSOR: + MCP230xx_UpdateWebData(); + break; +#endif +#endif +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" +# 46 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" +#ifdef USE_I2C +#ifdef USE_MPR121 + + + + + +#define XSNS_30 30 +#define XI2C_23 23 + + + + + + + +#define MPR121_ELEX_REG 0x00 + + +#define MPR121_MHDR_REG 0x2B + + +#define MPR121_MHDR_VAL 0x01 + + +#define MPR121_NHDR_REG 0x2C + + +#define MPR121_NHDR_VAL 0x01 + + +#define MPR121_NCLR_REG 0x2D + + +#define MPR121_NCLR_VAL 0x0E + + +#define MPR121_MHDF_REG 0x2F + + +#define MPR121_MHDF_VAL 0x01 + + +#define MPR121_NHDF_REG 0x30 + + +#define MPR121_NHDF_VAL 0x05 + + +#define MPR121_NCLF_REG 0x31 + + +#define MPR121_NCLF_VAL 0x01 + + +#define MPR121_MHDPROXR_REG 0x36 + + +#define MPR121_MHDPROXR_VAL 0x3F + + +#define MPR121_NHDPROXR_REG 0x37 + + +#define MPR121_NHDPROXR_VAL 0x5F + + +#define MPR121_NCLPROXR_REG 0x38 + + +#define MPR121_NCLPROXR_VAL 0x04 + + +#define MPR121_FDLPROXR_REG 0x39 + + +#define MPR121_FDLPROXR_VAL 0x00 + + +#define MPR121_MHDPROXF_REG 0x3A + + +#define MPR121_MHDPROXF_VAL 0x01 + + +#define MPR121_NHDPROXF_REG 0x3B + + +#define MPR121_NHDPROXF_VAL 0x01 + + +#define MPR121_NCLPROXF_REG 0x3C + + +#define MPR121_NCLPROXF_VAL 0x1F + + +#define MPR121_FDLPROXF_REG 0x3D + + +#define MPR121_FDLPROXF_VAL 0x04 + + +#define MPR121_E0TTH_REG 0x41 + + +#define MPR121_E0TTH_VAL 12 + + +#define MPR121_E0RTH_REG 0x42 + + +#define MPR121_E0RTH_VAL 6 + + +#define MPR121_CDT_REG 0x5D + + +#define MPR121_CDT_VAL 0x20 + + +#define MPR121_ECR_REG 0x5E + + +#define MPR121_ECR_VAL 0x8F + + + +#define MPR121_SRST_REG 0x80 + + +#define MPR121_SRST_VAL 0x63 + + +#define BITC(sensor,position) ((pS->current[sensor] >> position) & 1) + + +#define BITP(sensor,position) ((pS->previous[sensor] >> position) & 1) +# 195 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" +typedef struct mpr121 mpr121; +struct mpr121 { + const uint8_t i2c_addr[4] = { 0x5A, 0x5B, 0x5C, 0x5D }; + const char id[4] = { 'A', 'B', 'C', 'D' }; + bool connected[4] = { false, false, false, false }; + bool running[4] = { false, false, false, false }; + uint16_t current[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; + uint16_t previous[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; +}; + +bool mpr21_found = false; +# 217 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" +void Mpr121Init(struct mpr121 *pS, bool initial) +{ + + for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { + + if (initial && I2cActive(pS->i2c_addr[i])) { continue; } + + + pS->connected[i] = (I2cWrite8(pS->i2c_addr[i], MPR121_SRST_REG, MPR121_SRST_VAL) + && (0x24 == I2cRead8(pS->i2c_addr[i], 0x5D))); + if (pS->connected[i]) { + + + mpr21_found = true; + char device_name[16]; + snprintf_P(device_name, sizeof(device_name), PSTR("MPR121(%c)"), pS->id[i]); + I2cSetActiveFound(pS->i2c_addr[i], device_name); + + + for (uint32_t j = 0; j < 13; j++) { + + + I2cWrite8(pS->i2c_addr[i], MPR121_E0TTH_REG + 2 * j, MPR121_E0TTH_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_E0RTH_REG + 2 * j, MPR121_E0RTH_VAL); + } + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDR_REG, MPR121_MHDR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDR_REG, MPR121_NHDR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLR_REG, MPR121_NCLR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDF_REG, MPR121_MHDF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDF_REG, MPR121_NHDF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLF_REG, MPR121_NCLF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXR_REG, MPR121_MHDPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXR_REG, MPR121_NHDPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXR_REG, MPR121_NCLPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXR_REG, MPR121_FDLPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXF_REG, MPR121_MHDPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXF_REG, MPR121_NHDPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXF_REG, MPR121_NCLPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXF_REG, MPR121_FDLPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_CDT_REG, MPR121_CDT_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_ECR_REG, MPR121_ECR_VAL); + + + pS->running[i] = (0x00 != I2cRead8(pS->i2c_addr[i], MPR121_ECR_REG)); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121%c: %sRunning"), pS->id[i], (pS->running[i]) ? "" : "NOT"); + + } else { + + + pS->running[i] = false; + } + } + + + if (!(pS->connected[0] || pS->connected[1] || pS->connected[2] + || pS->connected[3])) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C "MPR121: No sensors found")); + } +} +# 326 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" +void Mpr121Show(struct mpr121 *pS, uint8_t function) +{ + + + for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { + + + if (pS->connected[i]) { + + + if (!I2cValidRead16LE(&pS->current[i], pS->i2c_addr[i], MPR121_ELEX_REG)) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]); + Mpr121Init(pS, false); + return; + } + + if (BITC(i, 15)) { + + + I2cWrite8(pS->i2c_addr[i], MPR121_ELEX_REG, 0x00); + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]); + Mpr121Init(pS, false); + return; + } + } + + if (pS->running[i]) { + + + if (FUNC_JSON_APPEND == function) { + ResponseAppend_P(PSTR(",\"MPR121%c\":{"), pS->id[i]); + } + + for (uint32_t j = 0; j < 13; j++) { + + + if ((FUNC_EVERY_50_MSECOND == function) + && (BITC(i, j) != BITP(i, j))) { + Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); + } + +#ifdef USE_WEBSERVER + if (FUNC_WEB_SENSOR == function) { + WSContentSend_PD(PSTR("{s}MPR121%c Button%d{m}%d{e}"), pS->id[i], j, BITC(i, j)); + } +#endif + + + if (FUNC_JSON_APPEND == function) { + ResponseAppend_P(PSTR("%s\"Button%i\":%i"), (j > 0 ? "," : ""), j, BITC(i, j)); + } + } + + + pS->previous[i] = pS->current[i]; + + + if (FUNC_JSON_APPEND == function) { + ResponseJsonEnd(); + } + } + } +} +# 410 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" +bool Xsns30(uint8_t function) +{ + if (!I2cEnabled(XI2C_23)) { return false; } + + bool result = false; + + + static struct mpr121 mpr121; + + if (FUNC_INIT == function) { + + Mpr121Init(&mpr121, true); + } + else if (mpr21_found) { + + switch (function) { + + + case FUNC_EVERY_50_MSECOND: + Mpr121Show(&mpr121, FUNC_EVERY_50_MSECOND); + break; + + + case FUNC_JSON_APPEND: + Mpr121Show(&mpr121, FUNC_JSON_APPEND); + break; + +#ifdef USE_WEBSERVER + + case FUNC_WEB_SENSOR: + Mpr121Show(&mpr121, FUNC_WEB_SENSOR); + break; +#endif + } + } + + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_31_ccs811.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_31_ccs811.ino" +#ifdef USE_I2C +#ifdef USE_CCS811 +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_31_ccs811.ino" +#define XSNS_31 31 +#define XI2C_24 24 + +#define EVERYNSECONDS 5 + +#include "Adafruit_CCS811.h" + +Adafruit_CCS811 ccs; +uint8_t CCS811_ready = 0; +uint8_t CCS811_type = 0;; +uint16_t eCO2; +uint16_t TVOC; +uint8_t tcnt = 0; +uint8_t ecnt = 0; + + + +void CCS811Detect(void) +{ + if (I2cActive(CCS811_ADDRESS)) { return; } + + if (!ccs.begin(CCS811_ADDRESS)) { + CCS811_type = 1; + I2cSetActiveFound(CCS811_ADDRESS, "CCS811"); + } +} + +void CCS811Update(void) +{ + tcnt++; + if (tcnt >= EVERYNSECONDS) { + tcnt = 0; + CCS811_ready = 0; + if (ccs.available()) { + if (!ccs.readData()){ + TVOC = ccs.getTVOC(); + eCO2 = ccs.geteCO2(); + CCS811_ready = 1; + if (global_update && global_humidity>0 && global_temperature!=9999) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); } + ecnt = 0; + } + } else { + + ecnt++; + if (ecnt > 6) { + + ccs.begin(CCS811_ADDRESS); + } + } + } +} + +const char HTTP_SNS_CCS811[] PROGMEM = + "{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" + "{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; + +void CCS811Show(bool json) +{ + if (CCS811_ready) { + if (json) { + ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CCS811, eCO2, TVOC); +#endif + } + } +} + + + + + +bool Xsns31(uint8_t function) +{ + if (!I2cEnabled(XI2C_24)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + CCS811Detect(); + } + else if (CCS811_type) { + switch (function) { + case FUNC_EVERY_SECOND: + CCS811Update(); + break; + case FUNC_JSON_APPEND: + CCS811Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + CCS811Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_32_mpu6050.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_32_mpu6050.ino" +#ifdef USE_I2C +#ifdef USE_MPU6050 +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_32_mpu6050.ino" +#define XSNS_32 32 +#define XI2C_25 25 + +#define D_SENSOR_MPU6050 "MPU6050" + +#define MPU_6050_ADDR_AD0_LOW 0x68 +#define MPU_6050_ADDR_AD0_HIGH 0x69 + +uint8_t MPU_6050_address; +uint8_t MPU_6050_addresses[] = { MPU_6050_ADDR_AD0_LOW, MPU_6050_ADDR_AD0_HIGH }; +uint8_t MPU_6050_found; + +int16_t MPU_6050_ax = 0, MPU_6050_ay = 0, MPU_6050_az = 0; +int16_t MPU_6050_gx = 0, MPU_6050_gy = 0, MPU_6050_gz = 0; +int16_t MPU_6050_temperature = 0; + +#ifdef USE_MPU6050_DMP + #include "MPU6050_6Axis_MotionApps20.h" + #include "I2Cdev.h" + #include + typedef struct MPU6050_DMP{ + uint8_t devStatus; + uint16_t packetSize; + uint16_t fifoCount; + uint8_t fifoBuffer[64]; + Quaternion q; + VectorInt16 aa; + VectorInt16 aaReal; + VectorFloat gravity; + float euler[3]; + float yawPitchRoll[3]; + } MPU6050_DMP; + + MPU6050_DMP MPU6050_dmp; +#else + #include +#endif +MPU6050 mpu6050; + +void MPU_6050PerformReading(void) +{ +#ifdef USE_MPU6050_DMP + mpu6050.resetFIFO(); + MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); + while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); + mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); + MPU6050_dmp.fifoCount -= MPU6050_dmp.packetSize; + + mpu6050.dmpGetQuaternion(&MPU6050_dmp.q, MPU6050_dmp.fifoBuffer); + mpu6050.dmpGetEuler(MPU6050_dmp.euler, &MPU6050_dmp.q); + mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); + mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); + mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); + mpu6050.dmpGetYawPitchRoll(MPU6050_dmp.yawPitchRoll, &MPU6050_dmp.q, &MPU6050_dmp.gravity); + MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; + MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; + MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; + MPU_6050_ax = MPU6050_dmp.aaReal.x; + MPU_6050_ay = MPU6050_dmp.aaReal.y; + MPU_6050_az = MPU6050_dmp.aaReal.z; +#else + mpu6050.getMotion6( + &MPU_6050_ax, + &MPU_6050_ay, + &MPU_6050_az, + &MPU_6050_gx, + &MPU_6050_gy, + &MPU_6050_gz + ); +#endif + MPU_6050_temperature = mpu6050.getTemperature(); +} +# 119 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_32_mpu6050.ino" +void MPU_6050Detect(void) +{ + for (uint32_t i = 0; i < sizeof(MPU_6050_addresses); i++) + { + MPU_6050_address = MPU_6050_addresses[i]; + if (!I2cSetDevice(MPU_6050_address)) { break; } + mpu6050.setAddr(MPU_6050_addresses[i]); + +#ifdef USE_MPU6050_DMP + MPU6050_dmp.devStatus = mpu6050.dmpInitialize(); + mpu6050.setXGyroOffset(220); + mpu6050.setYGyroOffset(76); + mpu6050.setZGyroOffset(-85); + mpu6050.setZAccelOffset(1788); + if (MPU6050_dmp.devStatus == 0) { + mpu6050.setDMPEnabled(true); + MPU6050_dmp.packetSize = mpu6050.dmpGetFIFOPacketSize(); + MPU_6050_found = true; + } +#else + mpu6050.initialize(); + MPU_6050_found = mpu6050.testConnection(); +#endif + Settings.flag2.axis_resolution = 2; + } + + if (MPU_6050_found) { + I2cSetActiveFound(MPU_6050_address, D_SENSOR_MPU6050); + } +} + +#define D_YAW "Yaw" +#define D_PITCH "Pitch" +#define D_ROLL "Roll" + +#ifdef USE_WEBSERVER +const char HTTP_SNS_AXIS[] PROGMEM = + "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_AY_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; +#ifdef USE_MPU6050_DMP +const char HTTP_SNS_YPR[] PROGMEM = + "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}"; +#endif +#endif + +#define D_JSON_AXIS_AX "AccelXAxis" +#define D_JSON_AXIS_AY "AccelYAxis" +#define D_JSON_AXIS_AZ "AccelZAxis" +#define D_JSON_AXIS_GX "GyroXAxis" +#define D_JSON_AXIS_GY "GyroYAxis" +#define D_JSON_AXIS_GZ "GyroZAxis" +#define D_JSON_YAW "Yaw" +#define D_JSON_PITCH "Pitch" +#define D_JSON_ROLL "Roll" + +void MPU_6050Show(bool json) +{ + MPU_6050PerformReading(); + + double tempConv = (MPU_6050_temperature / 340.0 + 35.53); + char temperature[33]; + dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature); + char axis_ax[33]; + dtostrfd(MPU_6050_ax, Settings.flag2.axis_resolution, axis_ax); + char axis_ay[33]; + dtostrfd(MPU_6050_ay, Settings.flag2.axis_resolution, axis_ay); + char axis_az[33]; + dtostrfd(MPU_6050_az, Settings.flag2.axis_resolution, axis_az); + char axis_gx[33]; + dtostrfd(MPU_6050_gx, Settings.flag2.axis_resolution, axis_gx); + char axis_gy[33]; + dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); + char axis_gz[33]; + dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); +#ifdef USE_MPU6050_DMP + char axis_yaw[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[0] / PI * 180.0, Settings.flag2.axis_resolution, axis_yaw); + char axis_pitch[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[1] / PI * 180.0, Settings.flag2.axis_resolution, axis_pitch); + char axis_roll[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[2] / PI * 180.0, Settings.flag2.axis_resolution, axis_roll); +#endif + + if (json) { + char json_axis_ax[25]; + snprintf_P(json_axis_ax, sizeof(json_axis_ax), PSTR(",\"" D_JSON_AXIS_AX "\":%s"), axis_ax); + char json_axis_ay[25]; + snprintf_P(json_axis_ay, sizeof(json_axis_ay), PSTR(",\"" D_JSON_AXIS_AY "\":%s"), axis_ay); + char json_axis_az[25]; + snprintf_P(json_axis_az, sizeof(json_axis_az), PSTR(",\"" D_JSON_AXIS_AZ "\":%s"), axis_az); + char json_axis_gx[25]; + snprintf_P(json_axis_gx, sizeof(json_axis_gx), PSTR(",\"" D_JSON_AXIS_GX "\":%s"), axis_gx); + char json_axis_gy[25]; + snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); + char json_axis_gz[25]; + snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); +#ifdef USE_MPU6050_DMP + char json_ypr_y[25]; + snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), axis_yaw); + char json_ypr_p[25]; + snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), axis_pitch); + char json_ypr_r[25]; + snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), axis_roll); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz, + json_ypr_y, json_ypr_p, json_ypr_r); +#else + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); +#endif +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); +#ifdef USE_MPU6050_DMP + WSContentSend_PD(HTTP_SNS_YPR, axis_yaw, axis_pitch, axis_roll); +#endif +#endif + } +} + + + + + +bool Xsns32(uint8_t function) +{ + if (!I2cEnabled(XI2C_25)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MPU_6050Detect(); + } + else if (MPU_6050_found) { + switch (function) { + case FUNC_EVERY_SECOND: + if (tele_period == Settings.tele_period -3) { + MPU_6050PerformReading(); + } + break; + case FUNC_JSON_APPEND: + MPU_6050Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MPU_6050Show(0); + MPU_6050PerformReading(); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_33_ds3231.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_33_ds3231.ino" +#ifdef USE_I2C +#ifdef USE_DS3231 +# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_33_ds3231.ino" +#define XSNS_33 33 +#define XI2C_26 26 + + +#ifndef USE_RTC_ADDR +#define USE_RTC_ADDR 0x68 +#endif + + +#define RTC_SECONDS 0x00 +#define RTC_MINUTES 0x01 +#define RTC_HOURS 0x02 +#define RTC_DAY 0x03 +#define RTC_DATE 0x04 +#define RTC_MONTH 0x05 +#define RTC_YEAR 0x06 +#define RTC_CONTROL 0x0E +#define RTC_STATUS 0x0F + +#define OSF 7 +#define EOSC 7 +#define BBSQW 6 +#define CONV 5 +#define RS2 4 +#define RS1 3 +#define INTCN 2 + + +#define HR1224 6 +#define CENTURY 7 +#define DYDT 6 +bool ds3231ReadStatus = false; +bool ds3231WriteStatus = false; +bool DS3231chipDetected = false; + + + + +void DS3231Detect(void) +{ + if (I2cActive(USE_RTC_ADDR)) { return; } + + if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { + I2cSetActiveFound(USE_RTC_ADDR, "DS3231"); + DS3231chipDetected = true; + } +} + + + + +uint8_t bcd2dec(uint8_t n) +{ + return n - 6 * (n >> 4); +} + + + + +uint8_t dec2bcd(uint8_t n) +{ + return n + 6 * (n / 10); +} + + + + +uint32_t ReadFromDS3231(void) +{ + TIME_T tm; + tm.second = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_SECONDS)); + tm.minute = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MINUTES)); + tm.hour = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_HOURS) & ~_BV(HR1224)); + tm.day_of_week = I2cRead8(USE_RTC_ADDR, RTC_DAY); + tm.day_of_month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_DATE)); + tm.month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MONTH) & ~_BV(CENTURY)); + tm.year = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_YEAR)); + return MakeTime(tm); +} + + + +void SetDS3231Time (uint32_t epoch_time) { + TIME_T tm; + BreakTime(epoch_time, tm); + I2cWrite8(USE_RTC_ADDR, RTC_SECONDS, dec2bcd(tm.second)); + I2cWrite8(USE_RTC_ADDR, RTC_MINUTES, dec2bcd(tm.minute)); + I2cWrite8(USE_RTC_ADDR, RTC_HOURS, dec2bcd(tm.hour)); + I2cWrite8(USE_RTC_ADDR, RTC_DAY, tm.day_of_week); + I2cWrite8(USE_RTC_ADDR, RTC_DATE, dec2bcd(tm.day_of_month)); + I2cWrite8(USE_RTC_ADDR, RTC_MONTH, dec2bcd(tm.month)); + I2cWrite8(USE_RTC_ADDR, RTC_YEAR, dec2bcd(tm.year)); + I2cWrite8(USE_RTC_ADDR, RTC_STATUS, I2cRead8(USE_RTC_ADDR, RTC_STATUS) & ~_BV(OSF)); +} + +void DS3231EverySecond(void) +{ + TIME_T tmpTime; + if (!ds3231ReadStatus && Rtc.utc_time < START_VALID_TIME ) { + ntp_force_sync = true; + Rtc.utc_time = ReadFromDS3231(); + + + BreakTime(Rtc.utc_time, tmpTime); + if (Rtc.utc_time < START_VALID_TIME ) { + ds3231ReadStatus = true; + } + RtcTime.year = tmpTime.year + 1970; + Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); + Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + if (Rtc.local_time < START_VALID_TIME) { + rules_flag.time_init = 1; + } else { + rules_flag.time_set = 1; + } + } + else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + SetDS3231Time (Rtc.utc_time); + ds3231WriteStatus = true; + } +} + + + + + +bool Xsns33(uint8_t function) +{ + if (!I2cEnabled(XI2C_26)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + DS3231Detect(); + } + else if (DS3231chipDetected) { + switch (function) { + case FUNC_EVERY_SECOND: + DS3231EverySecond(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_34_hx711.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_34_hx711.ino" +#ifdef USE_HX711 +# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_34_hx711.ino" +#define XSNS_34 34 + +#ifndef HX_MAX_WEIGHT +#define HX_MAX_WEIGHT 20000 +#endif +#ifndef HX_REFERENCE +#define HX_REFERENCE 250 +#endif +#ifndef HX_SCALE +#define HX_SCALE 120 +#endif + +#define HX_TIMEOUT 120 +#define HX_SAMPLES 10 +#define HX_CAL_TIMEOUT 15 + +#define HX_GAIN_128 1 +#define HX_GAIN_32 2 +#define HX_GAIN_64 3 + +#define D_JSON_WEIGHT_REF "WeightRef" +#define D_JSON_WEIGHT_CAL "WeightCal" +#define D_JSON_WEIGHT_MAX "WeightMax" +#define D_JSON_WEIGHT_ITEM "WeightItem" +#define D_JSON_WEIGHT_CHANGE "WeightChange" +#define D_JSON_WEIGHT_RAW "WeightRaw" +#define D_JSON_WEIGHT_DELTA "WeightDelta" + +enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; + +const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE; + +struct HX { + long weight = 0; + long raw = 0; + long last_weight = 0; + long sum_weight = 0; + long sum_raw = 0; + long offset = 0; + long scale = 1; + long weight_diff = 0; + uint8_t type = 1; + uint8_t sample_count = 0; + uint8_t calibrate_step = HX_CAL_END; + uint8_t calibrate_timer = 0; + uint8_t calibrate_msg = 0; + uint8_t pin_sck; + uint8_t pin_dout; + bool tare_flg = false; + bool weight_changed = false; + uint16_t weight_delta = 4; +} Hx; + + + +bool HxIsReady(uint16_t timeout) +{ + + uint32_t start = millis(); + while ((digitalRead(Hx.pin_dout) == HIGH) && (millis() - start < timeout)) { yield(); } + return (digitalRead(Hx.pin_dout) == LOW); +} + +long HxRead(void) +{ + if (!HxIsReady(HX_TIMEOUT)) { return -1; } + + uint8_t data[3] = { 0 }; + uint8_t filler = 0x00; + + + data[2] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + data[1] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + data[0] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + + + for (unsigned int i = 0; i < HX_GAIN_128; i++) { + digitalWrite(Hx.pin_sck, HIGH); + digitalWrite(Hx.pin_sck, LOW); + } + + + if (data[2] & 0x80) { filler = 0xFF; } + + + unsigned long value = ( static_cast(filler) << 24 + | static_cast(data[2]) << 16 + | static_cast(data[1]) << 8 + | static_cast(data[0]) ); + + return static_cast(value); +} + + + +void HxResetPart(void) +{ + Hx.tare_flg = true; + Hx.sum_weight = 0; + Hx.sample_count = 0; + Hx.last_weight = 0; +} + +void HxReset(void) +{ + HxResetPart(); + Settings.energy_frequency_calibration = 0; +} + +void HxCalibrationStateTextJson(uint8_t msg_id) +{ + char cal_text[30]; + + Hx.calibrate_msg = msg_id; + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); + + if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } +} + +void SetWeightDelta() +{ + + if (Settings.weight_change == 0) { + Hx.weight_delta = 4; + return; + } + + + if (Settings.weight_change > 100) { + Hx.weight_delta = (Settings.weight_change - 100) * 10 + 100; + return; + } + + + Hx.weight_delta = Settings.weight_change - 1; +} +# 192 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_34_hx711.ino" +bool HxCommand(void) +{ + bool serviced = true; + bool show_parms = false; + char sub_string[XdrvMailbox.data_len +1]; + + for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) { + if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; } + } + + switch (XdrvMailbox.payload) { + case 1: + HxReset(); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); + break; + case 2: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + Hx.scale = 1; + HxReset(); + Hx.calibrate_step = HX_CAL_START; + Hx.calibrate_timer = 1; + HxCalibrationStateTextJson(3); + break; + case 3: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + show_parms = true; + break; + case 4: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Hx.scale = Settings.weight_calibration; + } + show_parms = true; + break; + case 5: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000; + } + show_parms = true; + break; + case 6: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_item = (unsigned long)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); + } + show_parms = true; + break; + case 7: + Settings.energy_frequency_calibration = Hx.weight; + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE); + break; + case 8: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.SensorBits1.hx711_json_weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) & 1; + } + show_parms = true; + break; + case 9: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + SetWeightDelta(); + } + show_parms = true; + break; + default: + show_parms = true; + } + + if (show_parms) { + char item[33]; + dtostrfd((float)Settings.weight_item / 10, 1, item); + Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" + D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":%s,\"" D_JSON_WEIGHT_DELTA "\":%d}}"), + Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, + item, GetStateText(Settings.SensorBits1.hx711_json_weight_change), Settings.weight_change); + } + + return serviced; +} + + + +long HxWeight(void) +{ + return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; +} + +void HxInit(void) +{ + Hx.type = 0; + if ((pin[GPIO_HX711_DAT] < 99) && (pin[GPIO_HX711_SCK] < 99)) { + Hx.pin_sck = pin[GPIO_HX711_SCK]; + Hx.pin_dout = pin[GPIO_HX711_DAT]; + + pinMode(Hx.pin_sck, OUTPUT); + pinMode(Hx.pin_dout, INPUT); + + digitalWrite(Hx.pin_sck, LOW); + + SetWeightDelta(); + + if (HxIsReady(8 * HX_TIMEOUT)) { + if (!Settings.weight_max) { Settings.weight_max = HX_MAX_WEIGHT / 1000; } + if (!Settings.weight_calibration) { Settings.weight_calibration = HX_SCALE; } + if (!Settings.weight_reference) { Settings.weight_reference = HX_REFERENCE; } + Hx.scale = Settings.weight_calibration; + HxRead(); + HxResetPart(); + Hx.type = 1; + } + } +} + +void HxEvery100mSecond(void) +{ + long raw = HxRead(); + Hx.sum_raw += raw; + Hx.sum_weight += raw; + + Hx.sample_count++; + if (HX_SAMPLES == Hx.sample_count) { + long average = Hx.sum_weight / Hx.sample_count; + long raw_average = Hx.sum_raw / Hx.sample_count; + long value = average - Hx.offset; + Hx.weight = value / Hx.scale; + Hx.raw = raw_average / Hx.scale; + if (Hx.weight < 0) { + if (Settings.energy_frequency_calibration) { + long difference = Settings.energy_frequency_calibration + Hx.weight; + Hx.last_weight = difference; + if (difference < 0) { HxReset(); } + } + Hx.weight = 0; + } else { + Hx.last_weight = Settings.energy_frequency_calibration; + } + + if (Hx.tare_flg) { + Hx.tare_flg = false; + Hx.offset = average; + } + + if (Hx.calibrate_step) { + Hx.calibrate_timer--; + + if (HX_CAL_START == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); + } + else if (HX_CAL_RESET == Hx.calibrate_step) { + if (Hx.calibrate_timer) { + if (Hx.weight < (long)Settings.weight_reference) { + Hx.calibrate_step--; + Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); + HxCalibrationStateTextJson(2); + } + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + else if (HX_CAL_FIRST == Hx.calibrate_step) { + if (Hx.calibrate_timer) { + if (Hx.weight > (long)Settings.weight_reference) { + Hx.calibrate_step--; + } + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + else if (HX_CAL_DONE == Hx.calibrate_step) { + if (Hx.weight > (long)Settings.weight_reference) { + Hx.calibrate_step = HX_CAL_FINISH; + Settings.weight_calibration = Hx.weight / Settings.weight_reference; + Hx.weight = 0; + HxCalibrationStateTextJson(1); + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + + if (HX_CAL_FAIL == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.tare_flg = true; + HxCalibrationStateTextJson(0); + } + if (HX_CAL_FINISH == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.calibrate_timer = 3 * (10 / HX_SAMPLES); + Hx.scale = Settings.weight_calibration; + } + + if (!Hx.calibrate_timer) { + Hx.calibrate_step = HX_CAL_END; + } + } else { + Hx.weight += Hx.last_weight; + + if (Settings.SensorBits1.hx711_json_weight_change) { + if (abs(Hx.weight - Hx.weight_diff) > Hx.weight_delta) { + Hx.weight_diff = Hx.weight; + Hx.weight_changed = true; + } + else if (Hx.weight_changed && (Hx.weight == Hx.weight_diff)) { + mqtt_data[0] = '\0'; + ResponseAppendTime(); + HxShow(true); + ResponseJsonEnd(); + MqttPublishTeleSensor(); + Hx.weight_changed = false; + } + } + } + + Hx.sum_weight = 0; + Hx.sum_raw = 0; + Hx.sample_count = 0; + } +} + +void HxSaveBeforeRestart(void) +{ + Settings.energy_frequency_calibration = Hx.weight; + Hx.sample_count = HX_SAMPLES +1; +} + +#ifdef USE_WEBSERVER +const char HTTP_HX711_WEIGHT[] PROGMEM = + "{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; +const char HTTP_HX711_COUNT[] PROGMEM = + "{s}HX711 " D_COUNT "{m}%d{e}"; +const char HTTP_HX711_CAL[] PROGMEM = + "{s}HX711 %s{m}{e}"; +#endif + +void HxShow(bool json) +{ + char scount[30] = { 0 }; + + uint16_t count = 0; + float weight = 0; + if (Hx.calibrate_step < HX_CAL_FAIL) { + if (Hx.weight && Settings.weight_item) { + count = (Hx.weight * 10) / Settings.weight_item; + if (count > 1) { + snprintf_P(scount, sizeof(scount), PSTR(",\"" D_JSON_COUNT "\":%d"), count); + } + } + weight = (float)Hx.weight / 1000; + } + char weight_chr[33]; + dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s, \"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); + if (count > 1) { + WSContentSend_PD(HTTP_HX711_COUNT, count); + } + if (Hx.calibrate_step) { + char cal_text[30]; + WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); + } +#endif + } +} + +#ifdef USE_WEBSERVER +#ifdef USE_HX711_GUI + + + + +#define WEB_HANDLE_HX711 "s34" + +const char S_CONFIGURE_HX711[] PROGMEM = D_CONFIGURE_HX711; + +const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = + "

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

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

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" + "
" + "
" + "


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

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; + +void HandleHxAction(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); + + if (WebServer->hasArg("save")) { + HxSaveSettings(); + HandleConfiguration(); + return; + } + + char stemp1[20]; + + if (WebServer->hasArg("reset")) { + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); + ExecuteWebCommand(stemp1, SRC_WEBGUI); + + HandleRoot(); + return; + } + + if (WebServer->hasArg("calibrate")) { + WebGetArg("p1", stemp1, sizeof(stemp1)); + Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); + + HxLogUpdates(); + + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); + ExecuteWebCommand(stemp1, SRC_WEBGUI); + + HandleRoot(); + return; + } + + WSContentStart_P(S_CONFIGURE_HX711); + WSContentSendStyle(); + dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); + char stemp2[20]; + dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); + WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void HxSaveSettings(void) +{ + char tmp[100]; + + WebGetArg("p2", tmp, sizeof(tmp)); + Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToFloat(tmp) * 10000); + + HxLogUpdates(); +} + +void HxLogUpdates(void) +{ + char weigth_ref_chr[33]; + dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); + char weigth_item_chr[33]; + dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), weigth_ref_chr, weigth_item_chr); +} + +#endif +#endif + + + + + +bool Xsns34(uint8_t function) +{ + bool result = false; + + if (Hx.type) { + switch (function) { + case FUNC_EVERY_100_MSECOND: + HxEvery100mSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_34 == XdrvMailbox.index) { + result = HxCommand(); + } + break; + case FUNC_JSON_APPEND: + HxShow(1); + break; + case FUNC_SAVE_BEFORE_RESTART: + HxSaveBeforeRestart(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HxShow(0); + break; +#ifdef USE_HX711_GUI + case FUNC_WEB_ADD_MAIN_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711); + break; + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_HX711); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); + break; +#endif +#endif + case FUNC_INIT: + HxInit(); + break; + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_35_tx20.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_35_tx20.ino" +#ifdef USE_TX20_WIND_SENSOR +# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_35_tx20.ino" +#define XSNS_35 35 + +#define TX20_BIT_TIME 1220 +#define TX20_RESET_VALUES 60 + + + +extern "C" { +#include "gpio.h" +} + +#ifdef USE_WEBSERVER + +const char HTTP_SNS_TX20[] PROGMEM = + "{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_DIRECTION "{m}%s{e}"; + +#endif + +const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" + D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST "|" + D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST "|" + D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; + +uint8_t tx20_sa = 0; +uint8_t tx20_sb = 0; +uint8_t tx20_sd = 0; +uint8_t tx20_se = 0; +uint16_t tx20_sc = 0; +uint16_t tx20_sf = 0; + +float tx20_wind_speed_kmh = 0; +float tx20_wind_speed_max = 0; +float tx20_wind_speed_avg = 0; +float tx20_wind_sum = 0; +int tx20_count = 0; +uint8_t tx20_wind_direction = 0; + +bool tx20_available = false; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +void Tx20StartRead(void) ICACHE_RAM_ATTR; +#endif + +void Tx20StartRead(void) +{ +# 101 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_35_tx20.ino" + tx20_available = false; + + tx20_sa = 0; + tx20_sb = 0; + tx20_sd = 0; + tx20_se = 0; + tx20_sc = 0; + tx20_sf = 0; + + delayMicroseconds(TX20_BIT_TIME / 2); + + for (int32_t bitcount = 41; bitcount > 0; bitcount--) { + uint8_t dpin = (digitalRead(pin[GPIO_TX20_TXD_BLACK])); + if (bitcount > 41 - 5) { + + tx20_sa = (tx20_sa << 1) | (dpin ^ 1); + } else if (bitcount > 41 - 5 - 4) { + + tx20_sb = tx20_sb >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + + tx20_sc = tx20_sc >> 1 | ((dpin ^ 1) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + + tx20_sd = tx20_sd >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + + tx20_se = tx20_se >> 1 | (dpin << 3); + } else { + + tx20_sf = tx20_sf >> 1 | (dpin << 11); + } + + delayMicroseconds(TX20_BIT_TIME); + } + + uint8_t chk = (tx20_sb + (tx20_sc & 0xf) + ((tx20_sc >> 4) & 0xf) + ((tx20_sc >> 8) & 0xf)); + chk &= 0xf; + + if ((chk == tx20_sd) && (tx20_sc < 400)) { + tx20_available = true; + } + + + + + + + + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]); +} + +void Tx20Read(void) +{ + if (!(uptime % TX20_RESET_VALUES)) { + tx20_count = 0; + tx20_wind_sum = 0; + tx20_wind_speed_max = 0; + } + else if (tx20_available) { + tx20_wind_speed_kmh = float(tx20_sc) * 0.36; + if (tx20_wind_speed_kmh > tx20_wind_speed_max) { + tx20_wind_speed_max = tx20_wind_speed_kmh; + } + tx20_count++; + tx20_wind_sum += tx20_wind_speed_kmh; + tx20_wind_speed_avg = tx20_wind_sum / tx20_count; + tx20_wind_direction = tx20_sb; + } +} + +void Tx20Init(void) { + pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); + attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); +} + +void Tx20Show(bool json) +{ + char wind_speed_string[33]; + dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); + char wind_speed_max_string[33]; + dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); + char wind_speed_avg_string[33]; + dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); + char wind_direction_string[4]; + GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); + + if (json) { + ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), + wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); +#endif + } +} + + + + + +bool Xsns35(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_TX20_TXD_BLACK] < 99) { + switch (function) { + case FUNC_INIT: + Tx20Init(); + break; + case FUNC_EVERY_SECOND: + Tx20Read(); + break; + case FUNC_JSON_APPEND: + Tx20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tx20Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_36_mgc3130.ino" +# 22 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_36_mgc3130.ino" +#ifdef USE_I2C +#ifdef USE_MGC3130 +# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_36_mgc3130.ino" +#define XSNS_36 36 +#define XI2C_27 27 + +#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** + +#define MGC3130_I2C_ADDR 0x42 + +#define MGC3130_xfer pin[GPIO_MGC3130_XFER] +#define MGC3130_reset pin[GPIO_MGC3130_RESET] + + +bool MGC3130_type = false; +char MGC3130stype[] = "MGC3130"; + + +#define MGC3130_SYSTEM_STATUS 0x15 +#define MGC3130_REQUEST_MSG 0x06 +#define MGC3130_FW_VERSION 0x83 +#define MGC3130_SET_RUNTIME 0xA2 +#define MGC3130_SENSOR_DATA 0x91 + + +#define MGC3130_GESTURE_GARBAGE 1 +#define MGC3130_FLICK_WEST_EAST 2 +#define MGC3130_FLICK_EAST_WEST 3 +#define MGC3130_FLICK_SOUTH_NORTH 4 +#define MGC3130_FLICK_NORTH_SOUTH 5 +#define MGC3130_CIRCLE_CLOCKWISE 6 +#define MGC3130_CIRCLE_CCLOCKWISE 7 + +#define MGC3130_MIN_ROTVALUE 0 +#define MGC3130_MAX_ROTVALUE 1023 +#define MGC3130_MIN_ZVALUE 32768 + + +#ifdef USE_WEBSERVER +const char HTTP_MGC_3130_SNS[] PROGMEM = + "{s}" "%s" "{m}%s{e}" + "{s}" "HwRev" "{m}%u.%u{e}" + "{s}" "loaderVer" "{m}%u.%u{e}" + "{s}" "platVer" "{m}%u{e}"; +#endif + + + + + + + +#pragma pack(1) +union MGC3130_Union{ + uint8_t buffer[132]; + struct + { + + uint8_t msgSize; + uint8_t flag; + uint8_t counter; + uint8_t id; + + struct { + uint8_t DSPStatus:1; + uint8_t gestureInfo:1; + uint8_t touchInfo:1; + uint8_t airWheelInfo:1; + uint8_t xyzPosition:1; + uint8_t noisePower:1; + uint8_t reserved:2; + uint8_t electrodeConfiguration:3; + uint8_t CICData:1; + uint8_t SDData:1; + uint16_t reserved2:3; + } outputConfigMask; + uint8_t timestamp; + struct { + uint8_t positionValid:1; + uint8_t airWheelValid:1; + uint8_t rawDataValid:1; + uint8_t noisePowerValid:1; + uint8_t environmentalNoise:1; + uint8_t clipping:1; + uint8_t reserved:1; + uint8_t DSPRunning:1; + } systemInfo; + uint16_t dspInfo; + struct { + uint8_t gestureCode:8; + uint8_t reserved:4; + uint8_t gestureType:4; + uint8_t edgeFlick:1; + uint16_t reserved2:14; + uint8_t gestureInProgress:1; + } gestureInfo; + struct { + uint8_t touchSouth:1; + uint8_t touchWest:1; + uint8_t touchNorth:1; + uint8_t touchEast:1; + uint8_t touchCentre:1; + uint8_t tapSouth:1; + uint8_t tapWest:1; + uint8_t tapNorth:1; + uint8_t tapEast :1; + uint8_t tapCentre:1; + uint8_t doubleTapSouth:1; + uint8_t doubleTapWest:1; + uint8_t doubleTapNorth:1; + uint8_t doubleTapEast:1; + uint8_t doubleTapCentre:1; + uint8_t reserved:1; + uint8_t touchCounter; + uint8_t reserved2; + } touchInfo; + int8_t airWheel; + uint8_t reserved; + uint16_t x; + uint16_t y; + uint16_t z; + float noisePower; + float CICData[4]; + float SDData[4]; + } out; + struct { + uint8_t header[3]; + + uint8_t valid; + uint8_t hwRev[2]; + uint8_t parameterStartAddr; + uint8_t loaderVersion[2]; + uint8_t loaderPlatform; + uint8_t fwStartAddr; + char fwVersion[120]; + } fw; + struct{ + uint8_t id; + uint8_t size; + uint16_t error; + uint32_t reserved; + uint32_t reserved1; + } status; +} MGC_data; +#pragma pack() + +char MGC3130_currentGesture[12]; + +int8_t MGC3130_delta, MGC3130_lastrotation = 0; +int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0; + +uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0; + +uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0; +char MGC3130_firmwareInfo[20]; + +uint8_t MGC3130_touchTimeout = 0; +uint16_t MGC3130_touchCounter = 1; +uint32_t MGC3130_touchTimeStamp = millis(); +bool MGC3130_triggeredByTouch = false; + +uint8_t MGC3130_mode = 1; + + + +uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; +uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; +uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; + +void MGC3130_handleSensorData(){ + if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ + if (MGC3130_handleTouch()){ + MGC3130_triggeredByTouch = true; + MqttPublishSensor(); + } + } + + if(MGC3130_mode == 1){ + if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ + MGC3130_handleGesture(); + MqttPublishSensor(); + } + } + if(MGC3130_mode == 2){ + if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ + MGC3130_handleAirWheel(); + MqttPublishSensor(); + } + } + if(MGC3130_mode == 3){ + if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ + MqttPublishSensor(); + } + } +} + +void MGC3130_sendMessage(uint8_t data[], uint8_t length){ + Wire.beginTransmission(MGC3130_I2C_ADDR); + Wire.write(data,length); + Wire.endTransmission(); + delay(2); + MGC3130_receiveMessage(); +} + + +void MGC3130_handleGesture(){ + + char edge[5]; + if (MGC_data.out.gestureInfo.edgeFlick){ + snprintf_P(edge, sizeof(edge), PSTR("ED_")); + } + else{ + snprintf_P(edge, sizeof(edge), PSTR("")); + } + switch(MGC_data.out.gestureInfo.gestureCode){ + case MGC3130_GESTURE_GARBAGE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE")); + break; + case MGC3130_FLICK_WEST_EAST: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge); + break; + case MGC3130_FLICK_EAST_WEST: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge); + break; + case MGC3130_FLICK_SOUTH_NORTH: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge); + break; + case MGC3130_FLICK_NORTH_SOUTH: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge); + break; + case MGC3130_CIRCLE_CLOCKWISE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW")); + break; + case MGC3130_CIRCLE_CCLOCKWISE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW")); + break; + } + +} + +bool MGC3130_handleTouch(){ + + bool success = false; + if (MGC_data.out.touchInfo.doubleTapCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + if (MGC_data.out.touchInfo.tapCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.touchCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S")); + success = true; + MGC3130_touchCounter++; + } + + return success; +} + +void MGC3130_handleAirWheel(){ + MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation; + MGC3130_lastrotation = MGC_data.out.airWheel; + + MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta; + if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){ + MGC3130_rotValue = MGC3130_MIN_ROTVALUE; + } + if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){ + MGC3130_rotValue = MGC3130_MAX_ROTVALUE; + } +} + +void MGC3130_handleSystemStatus(){ + +} + +bool MGC3130_receiveMessage(){ + if(MGC3130_readData()){ + switch(MGC_data.out.id){ + case MGC3130_SENSOR_DATA: + MGC3130_handleSensorData(); + break; + case MGC3130_SYSTEM_STATUS: + MGC3130_handleSystemStatus(); + break; + case MGC3130_FW_VERSION: + hwRev[0] = MGC_data.fw.hwRev[1]; + hwRev[1] = MGC_data.fw.hwRev[0]; + loaderVersion[0] = MGC_data.fw.loaderVersion[0]; + loaderVersion[1] = MGC_data.fw.loaderVersion[1]; + loaderPlatform = MGC_data.fw.loaderPlatform; + snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion); + MGC3130_firmwareInfo[20] = '\0'; + + break; + } + return true; + } + return false; +} + +bool MGC3130_readData() +{ + bool success = false; + if (!digitalRead(MGC3130_xfer)){ + pinMode(MGC3130_xfer, OUTPUT); + digitalWrite(MGC3130_xfer, LOW); + Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); + + MGC_data.buffer[0] = 4; + unsigned char i = 0; + while(Wire.available() && (i < MGC_data.buffer[0])){ + MGC_data.buffer[i] = Wire.read(); + i++; + } + digitalWrite(MGC3130_xfer, HIGH); + pinMode(MGC3130_xfer, INPUT); + success = true; + } + return success; +} + +void MGC3130_nextMode(){ + if (MGC3130_mode < 3){ + MGC3130_mode++; + } + else{ + MGC3130_mode = 1; + } + switch(MGC3130_mode){ + case 1: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } +} + +void MGC3130_loop() +{ + if(MGC3130_touchTimeout > 0){ + MGC3130_touchTimeout--; + } + MGC3130_receiveMessage(); +} + +void MGC3130_detect(void) +{ + if (MGC3130_type || I2cActive(MGC3130_I2C_ADDR)) { return; } + + pinMode(MGC3130_xfer, INPUT_PULLUP); + pinMode(MGC3130_reset, OUTPUT); + digitalWrite(MGC3130_reset, LOW); + delay(10); + digitalWrite(MGC3130_reset, HIGH); + delay(50); + + if (MGC3130_receiveMessage()) { + I2cSetActiveFound(MGC3130_I2C_ADDR, MGC3130stype); + MGC3130_currentGesture[0] = '\0'; + MGC3130_type = true; + } +} + + + + + +void MGC3130_show(bool json) +{ + if (!MGC3130_type) { return; } + + char status_chr[2]; + if (MGC_data.out.systemInfo.DSPRunning) { + sprintf (status_chr, "1"); + } + else{ + sprintf (status_chr, "0"); + } + + if (json) { + if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { + if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { + ResponseAppend_P(PSTR(",\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), + MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); + MGC3130_lastSentX = MGC_data.out.x; + MGC3130_lastSentY = MGC_data.out.y; + MGC3130_lastSentZ = MGC_data.out.z; + } + } + MGC3130_triggeredByTouch = false; + + if (MGC3130_mode == 2) { + if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { + ResponseAppend_P(PSTR(",\"%s\":{\"AW\":%i}"), MGC3130stype, MGC3130_rotValue); + MGC3130_lastSentRotValue = MGC3130_rotValue; + } + } + + if (MGC3130_currentGesture[0] != '\0') { + if (millis() - MGC3130_touchTimeStamp > 220 ) { + MGC3130_touchCounter = 1; + } + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); + MGC3130_currentGesture[0] = '\0'; + MGC3130_touchTimeStamp = millis(); + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); +#endif + } +} +# 557 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_36_mgc3130.ino" +bool MGC3130CommandSensor() +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + MGC3130_nextMode(); + break; + case 1: + MGC3130_mode = 1; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: + MGC3130_mode = 2; + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: + MGC3130_mode = 3; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } + return serviced; +} + + + + + +bool Xsns36(uint8_t function) +{ + if (!I2cEnabled(XI2C_27)) { return false; } + + bool result = false; + + if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { + MGC3130_detect(); + } + else if (MGC3130_type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + MGC3130_loop(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_36 == XdrvMailbox.index) { + result = MGC3130CommandSensor(); + } + break; + case FUNC_JSON_APPEND: + MGC3130_show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MGC3130_show(0); + break; +#endif + } + } + return result; +} +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" +#ifdef USE_RF_SENSOR +# 33 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" +#define XSNS_37 37 + + + + +#define RFSNS_VALID_WINDOW 1800 + +#define RFSNS_LOOPS_PER_MILLI 1900 +#define RFSNS_RAW_BUFFER_SIZE 180 +#define RFSNS_MIN_RAW_PULSES 112 + +#define RFSNS_MIN_PULSE_LENGTH 300 +#define RFSNS_RAWSIGNAL_SAMPLE 50 +#define RFSNS_SIGNAL_TIMEOUT 10 +#define RFSNS_SIGNAL_REPEAT_TIME 500 + +typedef struct RawSignalStruct +{ + int Number; + uint8_t Repeats; + uint8_t Multiply; + unsigned long Time; + uint8_t Pulses[RFSNS_RAW_BUFFER_SIZE+2]; + +} raw_signal_t; + +raw_signal_t *rfsns_raw_signal = nullptr; +uint8_t rfsns_rf_bit; +uint8_t rfsns_rf_port; +uint8_t rfsns_any_sensor = 0; + + + + + +bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal) +{ + uint8_t Fbit = digitalPinToBitMask(DataPin); + uint8_t Fport = digitalPinToPort(DataPin); + uint8_t FstateMask = (StateSignal ? Fbit : 0); + + if ((*portInputRegister(Fport) & Fbit) == FstateMask) { + const unsigned long LoopsPerMilli = RFSNS_LOOPS_PER_MILLI; + + + + + + + unsigned long PulseLength = 0; + if (rfsns_raw_signal->Time) { + if (rfsns_raw_signal->Repeats && (rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) { + PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; + while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && (PulseLength > micros())) { + if ((*portInputRegister(Fport) & Fbit) == FstateMask) { + PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; + } + } + while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && ((*portInputRegister(Fport) & Fbit) != FstateMask)); + } + } + + int RawCodeLength = 1; + bool Ftoggle = false; + unsigned long numloops = 0; + unsigned long maxloops = RFSNS_SIGNAL_TIMEOUT * LoopsPerMilli; + rfsns_raw_signal->Multiply = RFSNS_RAWSIGNAL_SAMPLE; + do { + numloops = 0; + while(((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) { + if (numloops++ == maxloops) { break; } + } + PulseLength = (numloops *1000) / LoopsPerMilli; + if (PulseLength < RFSNS_MIN_PULSE_LENGTH) { break; } + Ftoggle = !Ftoggle; + rfsns_raw_signal->Pulses[RawCodeLength++] = PulseLength / (unsigned long)rfsns_raw_signal->Multiply; + } + while(RawCodeLength < RFSNS_RAW_BUFFER_SIZE && numloops <= maxloops); + + if ((RawCodeLength >= RFSNS_MIN_RAW_PULSES) && (RawCodeLength < RFSNS_RAW_BUFFER_SIZE -1)) { + rfsns_raw_signal->Repeats = 0; + rfsns_raw_signal->Number = RawCodeLength -1; + rfsns_raw_signal->Pulses[rfsns_raw_signal->Number] = 0; + rfsns_raw_signal->Time = millis(); + return true; + } + else + rfsns_raw_signal->Number = 0; + } + + return false; +} + +#ifdef USE_THEO_V2 +# 149 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" +#define RFSNS_THEOV2_MAX_CHANNEL 2 + +#define RFSNS_THEOV2_PULSECOUNT 114 +#define RFSNS_THEOV2_RF_PULSE_MID 1000 + +typedef struct { + uint32_t time; + int16_t temp; + uint16_t lux; + uint8_t volt; +} theo_v2_t1_t; + +typedef struct { + uint32_t time; + int16_t temp; + uint16_t hum; + uint8_t volt; +} theo_v2_t2_t; + +theo_v2_t1_t *rfsns_theo_v2_t1 = nullptr; +theo_v2_t2_t *rfsns_theo_v2_t2 = nullptr; + +void RfSnsInitTheoV2(void) +{ + rfsns_theo_v2_t1 = (theo_v2_t1_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t1_t)); + rfsns_theo_v2_t2 = (theo_v2_t2_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t2_t)); + rfsns_any_sensor++; +} + +void RfSnsAnalyzeTheov2(void) +{ + if (rfsns_raw_signal->Number != RFSNS_THEOV2_PULSECOUNT) { return; } + + uint8_t Checksum; + uint8_t Channel; + uint8_t Type; + uint8_t Voltage; + int Payload1; + int Payload2; + + uint8_t b, bytes, bits, id; + + uint8_t idx = 3; + uint8_t chksum = 0; + for (bytes = 0; bytes < 7; bytes++) { + b = 0; + for (bits = 0; bits <= 7; bits++) + { + if ((rfsns_raw_signal->Pulses[idx] * rfsns_raw_signal->Multiply) > RFSNS_THEOV2_RF_PULSE_MID) { + b |= 1 << bits; + } + idx += 2; + } + if (bytes > 0) { chksum += b; } + + switch (bytes) { + case 0: + Checksum = b; + break; + case 1: + id = b; + Channel = b & 0x7; + Type = (b >> 3) & 0x1f; + break; + case 2: + Voltage = b; + break; + case 3: + Payload1 = b; + break; + case 4: + Payload1 = (b << 8) | Payload1; + break; + case 5: + Payload2 = b; + break; + case 6: + Payload2 = (b << 8) | Payload2; + break; + } + } + + if (Checksum != chksum) { return; } + if ((Channel == 0) || (Channel > RFSNS_THEOV2_MAX_CHANNEL)) { return; } + Channel--; + + rfsns_raw_signal->Repeats = 1; + + int Payload3 = Voltage & 0x3f; + + switch (Type) { + case 1: + rfsns_theo_v2_t1[Channel].time = LocalTime(); + rfsns_theo_v2_t1[Channel].volt = Payload3; + rfsns_theo_v2_t1[Channel].temp = Payload1; + rfsns_theo_v2_t1[Channel].lux = Payload2; + break; + case 2: + rfsns_theo_v2_t2[Channel].time = LocalTime(); + rfsns_theo_v2_t2[Channel].volt = Payload3; + rfsns_theo_v2_t2[Channel].temp = Payload1; + rfsns_theo_v2_t2[Channel].hum = Payload2; + break; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), + chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2); +} + +void RfSnsTheoV2Show(bool json) +{ + bool sensor_once = false; + + for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { + if (rfsns_theo_v2_t1[i].time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1); + char voltage[33]; + dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage); + + if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); + } + } else { + char temperature[33]; + dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && !sensor_once) { + DomoticzSensor(DZ_TEMP, temperature); + DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux); + sensor_once = true; + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor, rfsns_theo_v2_t1[i].lux); +#endif + } + } + } + } + + sensor_once = false; + for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { + if (rfsns_theo_v2_t2[i].time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1); + char voltage[33]; + dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage); + + if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); + } + } else { + float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); + float humi = ConvertHumidity((float)rfsns_theo_v2_t2[i].hum / 100); + char temperature[33]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, humidity, voltage); + if ((0 == tele_period) && !sensor_once) { +#ifdef USE_DOMOTICZ + DomoticzTempHumSensor(temperature, humidity); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, temp); + KnxSensor(KNX_HUMIDITY, humi); +#endif + sensor_once = true; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, sensor, humidity); +#endif + } + } + } + } +} + +#endif + +#ifdef USE_ALECTO_V2 +# 392 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" +#define RFSNS_DKW2012_PULSECOUNT 176 +#define RFSNS_ACH2010_MIN_PULSECOUNT 160 +#define RFSNS_ACH2010_MAX_PULSECOUNT 160 + +#define D_ALECTOV2 "AlectoV2" + +const char kAlectoV2Directions[] PROGMEM = D_TX20_NORTH "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" + D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST "|" + D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST "|" + D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; + +typedef struct { + uint32_t time; + float temp; + float rain; + float wind; + float gust; + uint8_t type; + uint8_t humi; + uint8_t wdir; +} alecto_v2_t; + +alecto_v2_t *rfsns_alecto_v2 = nullptr; +uint16_t rfsns_alecto_rain_base = 0; + +void RfSnsInitAlectoV2(void) +{ + rfsns_alecto_v2 = (alecto_v2_t*)malloc(sizeof(alecto_v2_t)); + rfsns_any_sensor++; +} + +void RfSnsAnalyzeAlectov2() +{ + if (!(((rfsns_raw_signal->Number >= RFSNS_ACH2010_MIN_PULSECOUNT) && + (rfsns_raw_signal->Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal->Number == RFSNS_DKW2012_PULSECOUNT))) { return; } + + uint8_t c = 0; + uint8_t rfbit; + uint8_t data[9] = { 0 }; + uint8_t msgtype = 0; + uint8_t rc = 0; + int temp; + uint8_t checksum = 0; + uint8_t checksumcalc = 0; + uint8_t maxidx = 8; + unsigned long atime; + float factor; + char buf1[16]; + + if (rfsns_raw_signal->Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; } + + uint8_t idx = maxidx; + for (uint32_t x = rfsns_raw_signal->Number; x > 0; x = x-2) { + if (rfsns_raw_signal->Pulses[x-1] * rfsns_raw_signal->Multiply < 0x300) { + rfbit = 0x80; + } else { + rfbit = 0; + } + data[idx] = (data[idx] >> 1) | rfbit; + c++; + if (c == 8) { + if (idx == 0) { break; } + c = 0; + idx--; + } + } + + checksum = data[maxidx]; + checksumcalc = RfSnsAlectoCRC8(data, maxidx); + + msgtype = (data[0] >> 4) & 0xf; + rc = (data[0] << 4) | (data[1] >> 4); + + if (checksum != checksumcalc) { return; } + if ((msgtype != 10) && (msgtype != 5)) { return; } + + rfsns_raw_signal->Repeats = 1; + + + + + + factor = 1.22; + + + + + + rfsns_alecto_v2->time = LocalTime(); + rfsns_alecto_v2->type = (RFSNS_DKW2012_PULSECOUNT == rfsns_raw_signal->Number); + rfsns_alecto_v2->temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10; + rfsns_alecto_v2->humi = data[3]; + uint16_t rain = (data[6] * 256) + data[7]; + + if (rain < rfsns_alecto_rain_base) { rfsns_alecto_rain_base = rain; } + if (rfsns_alecto_rain_base > 0) { + rfsns_alecto_v2->rain += ((float)rain - rfsns_alecto_rain_base) * 0.30; + } + rfsns_alecto_rain_base = rain; + rfsns_alecto_v2->wind = (float)data[4] * factor; + rfsns_alecto_v2->gust = (float)data[5] * factor; + if (rfsns_alecto_v2->type) { + rfsns_alecto_v2->wdir = data[8] & 0xf; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), + checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); +} + +void RfSnsAlectoResetRain(void) +{ + if ((RtcTime.hour == 0) && (RtcTime.minute == 0) && (RtcTime.second == 5)) { + rfsns_alecto_v2->rain = 0; + } +} + + + + + + + +uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + while (len--) { + uint8_t inbyte = *addr++; + for (uint32_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x80; + crc <<= 1; + if (mix) { crc ^= 0x31; } + inbyte <<= 1; + } + } + return crc; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_ALECTOV2[] PROGMEM = + "{s}" D_ALECTOV2 " " D_RAIN "{m}%s " D_UNIT_MILLIMETER "{e}" + "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"; +const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = + "{s}" D_ALECTOV2 " " D_TX20_WIND_DIRECTION "{m}%s{e}"; +#endif + +void RfSnsAlectoV2Show(bool json) +{ + if (rfsns_alecto_v2->time) { + if (rfsns_alecto_v2->time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), GetDT(rfsns_alecto_v2->time).c_str()); + } + } else { + float temp = ConvertTemp(rfsns_alecto_v2->temp); + char temperature[33]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + float humi = ConvertHumidity((float)rfsns_alecto_v2->humi); + char humidity[33]; + dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); + char rain[33]; + dtostrfd(rfsns_alecto_v2->rain, 2, rain); + char wind[33]; + dtostrfd(rfsns_alecto_v2->wind, 2, wind); + char gust[33]; + dtostrfd(rfsns_alecto_v2->gust, 2, gust); + char wdir[4]; + char direction[20]; + if (rfsns_alecto_v2->type) { + GetTextIndexed(wdir, sizeof(wdir), rfsns_alecto_v2->wdir, kAlectoV2Directions); + snprintf_P(direction, sizeof(direction), PSTR(",\"Direction\":\"%s\""), wdir); + } + + if (json) { + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), + temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); + if (0 == tele_period) { +#ifdef USE_DOMOTICZ + + + + +#endif + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, D_ALECTOV2, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, D_ALECTOV2, humidity); + WSContentSend_PD(HTTP_SNS_ALECTOV2, rain, wind, gust); + if (rfsns_alecto_v2->type) { + WSContentSend_PD(HTTP_SNS_ALECTOV2_WDIR, wdir); + } +#endif + } + } + } +} +#endif + +void RfSnsInit(void) +{ + rfsns_raw_signal = (raw_signal_t*)(malloc(sizeof(raw_signal_t))); + if (rfsns_raw_signal) { + memset(rfsns_raw_signal, 0, sizeof(raw_signal_t)); +#ifdef USE_THEO_V2 + RfSnsInitTheoV2(); +#endif +#ifdef USE_ALECTO_V2 + RfSnsInitAlectoV2(); +#endif + if (rfsns_any_sensor) { + rfsns_rf_bit = digitalPinToBitMask(pin[GPIO_RF_SENSOR]); + rfsns_rf_port = digitalPinToPort(pin[GPIO_RF_SENSOR]); + pinMode(pin[GPIO_RF_SENSOR], INPUT); + } else { + free(rfsns_raw_signal); + rfsns_raw_signal = nullptr; + } + } +} + +void RfSnsAnalyzeRawSignal(void) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal->Number); + +#ifdef USE_THEO_V2 + RfSnsAnalyzeTheov2(); +#endif +#ifdef USE_ALECTO_V2 + RfSnsAnalyzeAlectov2(); +#endif +} + +void RfSnsEverySecond(void) +{ +#ifdef USE_ALECTO_V2 + RfSnsAlectoResetRain(); +#endif +} + +void RfSnsShow(bool json) +{ +#ifdef USE_THEO_V2 + RfSnsTheoV2Show(json); +#endif +#ifdef USE_ALECTO_V2 + RfSnsAlectoV2Show(json); +#endif +} + + + + + +bool Xsns37(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_RF_SENSOR] < 99) && (FUNC_INIT == function)) { + RfSnsInit(); + } + else if (rfsns_raw_signal) { + switch (function) { + case FUNC_LOOP: + if ((*portInputRegister(rfsns_rf_port) &rfsns_rf_bit) == rfsns_rf_bit) { + if (RfSnsFetchSignal(pin[GPIO_RF_SENSOR], HIGH)) { + RfSnsAnalyzeRawSignal(); + } + } + sleep = 0; + break; + case FUNC_EVERY_SECOND: + RfSnsEverySecond(); + break; + case FUNC_JSON_APPEND: + RfSnsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + RfSnsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_38_az7798.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_38_az7798.ino" +#ifdef USE_AZ7798 + +#define XSNS_38 38 +# 112 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_38_az7798.ino" +#include + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#define AZ_READ_TIMEOUT 400 + +#define AZ_CLOCK_UPDATE_INTERVAL (24UL * 60 * 60) +#define AZ_EPOCH (946684800UL) + +TasmotaSerial *AzSerial; + +const char ktype[] = "AZ7798"; +uint8_t az_type = 1; +uint16_t az_co2 = 0; +double az_temperature = 0; +double az_humidity = 0; +uint8_t az_received = 0; +uint8_t az_state = 0; +unsigned long az_clock_update = 10; + + + +void AzEverySecond(void) +{ + unsigned long start = millis(); + + az_state++; + if (5 == az_state) { + az_state = 0; + + AzSerial->flush(); + AzSerial->write(":\r", 2); + az_received = 0; + + uint8_t az_response[32]; + uint8_t counter = 0; + uint8_t i, j; + uint8_t response_substr[16]; + + do { + if (AzSerial->available() > 0) { + az_response[counter] = AzSerial->read(); + if(az_response[counter] == 0x0d) { az_received = 1; } + counter++; + } else { + delay(5); + } + } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received); + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, az_response, counter); + + if (!az_received) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout")); + return; + } + + i = 0; + while((az_response[i] != 'T') && (i < counter)) {i++;} + if(az_response[i] != 'T') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find start of response")); + return; + } + i++; + j = 0; + + while((az_response[i] != 'C') && (az_response[i] != 'F') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if((az_response[i] != 'C') && (az_response[i] != 'F')){ + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of temperature")); + return; + } + response_substr[j] = 0; + az_temperature = CharToFloat((char*)response_substr); + if(az_response[i] == 'C') { + az_temperature = ConvertTemp((float)az_temperature); + } else { + az_temperature = ConvertTemp((az_temperature - 32) / 1.8); + } + i++; + if(az_response[i] != ':') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error first delimiter")); + return; + } + i++; + if(az_response[i] != 'C') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of CO2")); + return; + } + i++; + j = 0; + + while((az_response[i] != 'p') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if(az_response[i] != 'p') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of CO2")); + return; + } + response_substr[j] = 0; + az_co2 = atoi((char*)response_substr); + LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); + i += 3; + if(az_response[i] != ':') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter")); + return; + } + i++; + if(az_response[i] != 'H') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of humidity")); + return; + } + i++; + j = 0; + + while((az_response[i] != '%') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if(az_response[i] != '%') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of humidity")); + return; + } + response_substr[j] = 0; + az_humidity = ConvertHumidity(CharToFloat((char*)response_substr)); + } + + + if ((az_clock_update == 0) && (LocalTime() > AZ_EPOCH)) { + char tmpString[16]; + sprintf(tmpString, "C %d\r", (int)(LocalTime() - AZ_EPOCH)); + AzSerial->write(tmpString); + + do { + if (AzSerial->available() > 0) { + if(AzSerial->read() == 0x0d) { break; } + } else { + delay(5); + } + } while(((millis() - start) < AZ_READ_TIMEOUT)); + az_clock_update = AZ_CLOCK_UPDATE_INTERVAL; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 clock updated")); + } else { + az_clock_update--; + } +} + + + +void AzInit(void) +{ + az_type = 0; + if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) { + AzSerial = new TasmotaSerial(pin[GPIO_AZ_RXD], pin[GPIO_AZ_TXD], 1); + if (AzSerial->begin(9600)) { + if (AzSerial->hardwareSerial()) { ClaimSerial(); } + az_type = 1; + } + } +} + +void AzShow(bool json) +{ + char temperature[33]; + dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), ktype, az_co2, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, ktype, az_co2); + WSContentSend_PD(HTTP_SNS_TEMP, ktype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, ktype, humidity); +#endif + } +} + + + + + +bool Xsns38(uint8_t function) +{ + bool result = false; + + if(az_type){ + switch (function) { + case FUNC_INIT: + AzInit(); + break; + case FUNC_EVERY_SECOND: + AzEverySecond(); + break; + case FUNC_JSON_APPEND: + AzShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AzShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_39_max31855.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_39_max31855.ino" +#ifdef USE_MAX31855 + +#define XSNS_39 39 + +bool initialized = false; + +struct MAX31855_ResultStruct{ + uint8_t ErrorCode; + float ProbeTemperature; + float ReferenceTemperature; +} MAX31855_Result; + +void MAX31855_Init(void){ + if(initialized) + return; + + + pinMode(pin[GPIO_MAX31855CS], OUTPUT); + pinMode(pin[GPIO_MAX31855CLK], OUTPUT); + pinMode(pin[GPIO_MAX31855DO], INPUT); + + + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + + initialized = true; +} + + + + + +void MAX31855_GetResult(void){ + int32_t RawData = MAX31855_ShiftIn(32); + uint8_t probeerror = RawData & 0x7; + + MAX31855_Result.ErrorCode = probeerror; + MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); + if(probeerror) + MAX31855_Result.ProbeTemperature = NAN; + else + MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); +} + + + + + + +float MAX31855_GetProbeTemperature(int32_t RawData){ + if(RawData & 0x80000000) + RawData = (RawData >> 18) | 0xFFFFC000; + else + RawData >>= 18; + + float result = (RawData * 0.25); + + return ConvertTemp(result); +} + + + + + +float MAX31855_GetReferenceTemperature(int32_t RawData){ + if(RawData & 0x8000) + RawData = (RawData >> 4) | 0xFFFFF000; + else + RawData = (RawData >> 4) & 0x00000FFF; + + float result = (RawData * 0.0625); + + return ConvertTemp(result); +} + + + + + +int32_t MAX31855_ShiftIn(uint8_t Length){ + int32_t dataIn = 0; + + digitalWrite(pin[GPIO_MAX31855CS], LOW); + delayMicroseconds(1); + + for (uint32_t i = 0; i < Length; i++) + { + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + delayMicroseconds(1); + dataIn <<= 1; + if(digitalRead(pin[GPIO_MAX31855DO])) + dataIn |= 1; + digitalWrite(pin[GPIO_MAX31855CLK], HIGH); + delayMicroseconds(1); + } + + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + return dataIn; +} + +void MAX31855_Show(bool Json){ + char probetemp[33]; + char referencetemp[33]; + dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); + dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); + + if(Json){ + ResponseAppend_P(PSTR(",\"MAX31855\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + probetemp, referencetemp, MAX31855_Result.ErrorCode); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, probetemp); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, MAX31855_Result.ProbeTemperature); + } +#endif + } else { +#ifdef USE_WEBSERVER + WSContentSend_PD(HTTP_SNS_TEMP, "MAX31855", probetemp, TempUnit()); +#endif + } +} + + + + + +bool Xsns39(uint8_t function) +{ + bool result = false; + if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ + + switch (function) { + case FUNC_INIT: + MAX31855_Init(); + break; + case FUNC_EVERY_SECOND: + MAX31855_GetResult(); + break; + case FUNC_JSON_APPEND: + MAX31855_Show(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MAX31855_Show(false); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_40_pn532.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_40_pn532.ino" +#ifdef USE_PN532_HSU + +#define XSNS_40 40 + +#include + +TasmotaSerial *PN532_Serial; + +#define PN532_INVALID_ACK -1 +#define PN532_TIMEOUT -2 +#define PN532_INVALID_FRAME -3 +#define PN532_NO_SPACE -4 + +#define PN532_PREAMBLE 0x00 +#define PN532_STARTCODE1 0x00 +#define PN532_STARTCODE2 0xFF +#define PN532_POSTAMBLE 0x00 + +#define PN532_HOSTTOPN532 0xD4 +#define PN532_PN532TOHOST 0xD5 + +#define PN532_ACK_WAIT_TIME 0x0A + +#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 +#define PN532_COMMAND_SAMCONFIGURATION 0x14 +#define PN532_COMMAND_RFCONFIGURATION 0x32 +#define PN532_COMMAND_INDATAEXCHANGE 0x40 +#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A + +#define PN532_MIFARE_ISO14443A 0x00 +#define MIFARE_CMD_READ 0x30 +#define MIFARE_CMD_AUTH_A 0x60 +#define MIFARE_CMD_AUTH_B 0x61 +#define MIFARE_CMD_WRITE 0xA0 + +uint8_t pn532_model = 0; +uint8_t pn532_command = 0; +uint8_t pn532_scantimer = 0; + +uint8_t pn532_packetbuffer[64]; + +#ifdef USE_PN532_DATA_FUNCTION +uint8_t pn532_function = 0; +uint8_t pn532_newdata[16]; +uint8_t pn532_newdata_len = 0; +#endif + +void PN532_Init(void) +{ + if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) { + PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1); + if (PN532_Serial->begin(115200)) { + if (PN532_Serial->hardwareSerial()) { ClaimSerial(); } + PN532_wakeup(); + uint32_t ver = PN532_getFirmwareVersion(); + if (ver) { + PN532_setPassiveActivationRetries(0xFF); + PN532_SAMConfig(); + pn532_model = 1; + AddLog_P2(LOG_LEVEL_INFO,"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); + } + } + } +} + +int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout) +{ + int read_bytes = 0; + int ret; + unsigned long start_millis; + while (read_bytes < len) { + start_millis = millis(); + do { + ret = PN532_Serial->read(); + if (ret >= 0) { + break; + } + } while((timeout == 0) || ((millis()- start_millis ) < timeout)); + + if (ret < 0) { + if (read_bytes) { + return read_bytes; + } else { + return PN532_TIMEOUT; + } + } + buf[read_bytes] = (uint8_t)ret; + read_bytes++; + } + return read_bytes; +} + +int8_t PN532_readAckFrame(void) +{ + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; + uint8_t ackBuf[sizeof(PN532_ACK)]; + + if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) { + return PN532_TIMEOUT; + } + + if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) { + return PN532_INVALID_ACK; + } + return 0; +} + +int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) +{ + + PN532_Serial->flush(); + + pn532_command = header[0]; + PN532_Serial->write((uint8_t)PN532_PREAMBLE); + PN532_Serial->write((uint8_t)PN532_STARTCODE1); + PN532_Serial->write(PN532_STARTCODE2); + + uint8_t length = hlen + blen + 1; + PN532_Serial->write(length); + PN532_Serial->write(~length + 1); + + PN532_Serial->write(PN532_HOSTTOPN532); + uint8_t sum = PN532_HOSTTOPN532; + + PN532_Serial->write(header, hlen); + for (uint32_t i = 0; i < hlen; i++) { + sum += header[i]; + } + + PN532_Serial->write(body, blen); + for (uint32_t i = 0; i < blen; i++) { + sum += body[i]; + } + + uint8_t checksum = ~sum + 1; + PN532_Serial->write(checksum); + PN532_Serial->write((uint8_t)PN532_POSTAMBLE); + + return PN532_readAckFrame(); +} + +int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50) +{ + uint8_t tmp[3]; + + + if (PN532_receive(tmp, 3, timeout)<=0) { + return PN532_TIMEOUT; + } + if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) { + return PN532_INVALID_FRAME; + } + + + uint8_t length[2]; + if (PN532_receive(length, 2, timeout) <= 0) { + return PN532_TIMEOUT; + } + + if (0 != (uint8_t)(length[0] + length[1])) { + return PN532_INVALID_FRAME; + } + length[0] -= 2; + if (length[0] > len) { + return PN532_NO_SPACE; + } + + + uint8_t cmd = pn532_command + 1; + if (PN532_receive(tmp, 2, timeout) <= 0) { + return PN532_TIMEOUT; + } + if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { + return PN532_INVALID_FRAME; + } + + if (PN532_receive(buf, length[0], timeout) != length[0]) { + return PN532_TIMEOUT; + } + + uint8_t sum = PN532_PN532TOHOST + cmd; + for (uint32_t i=0; i status) { + return 0; + } + + response = pn532_packetbuffer[0]; + response <<= 8; + response |= pn532_packetbuffer[1]; + response <<= 8; + response |= pn532_packetbuffer[2]; + response <<= 8; + response |= pn532_packetbuffer[3]; + + return response; +} + +void PN532_wakeup(void) +{ + uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 }; + PN532_Serial->write(wakeup,sizeof(wakeup)); + + + PN532_Serial->flush(); +} + +bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50) +{ + pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = cardbaudrate; + if (PN532_writeCommand(pn532_packetbuffer, 3)) { + return 0x0; + } + + if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { + return 0x0; + } +# 274 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_40_pn532.ino" + if (pn532_packetbuffer[0] != 1) { + return 0; + } + + uint16_t sens_res = pn532_packetbuffer[2]; + sens_res <<= 8; + sens_res |= pn532_packetbuffer[3]; + + + *uidLength = pn532_packetbuffer[5]; + + for (uint32_t i = 0; i < pn532_packetbuffer[5]; i++) { + uid[i] = pn532_packetbuffer[6 + i]; + } + + return 1; +} + +bool PN532_setPassiveActivationRetries(uint8_t maxRetries) +{ + pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; + pn532_packetbuffer[1] = 5; + pn532_packetbuffer[2] = 0xFF; + pn532_packetbuffer[3] = 0x01; + pn532_packetbuffer[4] = maxRetries; + if (PN532_writeCommand(pn532_packetbuffer, 5)) { + return 0; + } + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +bool PN532_SAMConfig(void) +{ + pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; + pn532_packetbuffer[1] = 0x01; + pn532_packetbuffer[2] = 0x14; + pn532_packetbuffer[3] = 0x00; + if (PN532_writeCommand(pn532_packetbuffer, 4)) { + return false; + } + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +#ifdef USE_PN532_DATA_FUNCTION + +uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) +{ + uint8_t i; + uint8_t _key[6]; + uint8_t _uid[7]; + uint8_t _uidLen; + + + memcpy(&_key, keyData, 6); + memcpy(&_uid, uid, uidLen); + _uidLen = uidLen; + + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; + pn532_packetbuffer[3] = blockNumber; + memcpy(&pn532_packetbuffer[4], &_key, 6); + for (i = 0; i < _uidLen; i++) { + pn532_packetbuffer[10 + i] = _uid[i]; + } + + if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; } + + + PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + + + + if (pn532_packetbuffer[0] != 0x00) { + + return 0; + } + + return 1; +} + +uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) +{ + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = MIFARE_CMD_READ; + pn532_packetbuffer[3] = blockNumber; + + + if (PN532_writeCommand(pn532_packetbuffer, 4)) { + return 0; + } + + + PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + + if (pn532_packetbuffer[0] != 0x00) { + return 0; + } + + + + memcpy (data, &pn532_packetbuffer[1], 16); + + return 1; +} + +uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) +{ + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = MIFARE_CMD_WRITE; + pn532_packetbuffer[3] = blockNumber; + memcpy(&pn532_packetbuffer[4], data, 16); + + + if (PN532_writeCommand(pn532_packetbuffer, 20)) { + return 0; + } + + + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +#endif + +void PN532_ScanForTag(void) +{ + if (!pn532_model) { return; } + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; + uint8_t uid_len = 0; + uint8_t card_data[16]; + bool erase_success = false; + bool set_success = false; + if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { + char uids[15]; + +#ifdef USE_PN532_DATA_FUNCTION + char card_datas[34]; +#endif + + ToHex_P((unsigned char*)uid, uid_len, uids, sizeof(uids)); + +#ifdef USE_PN532_DATA_FUNCTION + if (uid_len == 4) { + uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { + if (mifareclassic_ReadDataBlock(1, card_data)) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_datas,&card_data,sizeof(card_data)); +#else + for (uint32_t i = 0;i < sizeof(card_data);i++) { + if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { + card_datas[i] = char(card_data[i]); + } else { + card_datas[i] = '\0'; + } + } +#endif + } + if (pn532_function == 1) { + for (uint32_t i = 0;i<16;i++) { + card_data[i] = 0x00; + } + if (mifareclassic_WriteDataBlock(1, card_data)) { + erase_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase success")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } + } + if (pn532_function == 2) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_data,&pn532_newdata,sizeof(card_data)); + if (mifareclassic_WriteDataBlock(1, card_data)) { + set_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } +#else + bool IsAlphaNumeric = true; + for (uint32_t i = 0;i < pn532_newdata_len;i++) { + if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) { + IsAlphaNumeric = false; + } + } + if (IsAlphaNumeric) { + memcpy(&card_data,&pn532_newdata,pn532_newdata_len); + card_data[pn532_newdata_len] = '\0'; + if (mifareclassic_WriteDataBlock(1, card_data)) { + set_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data must be alphanumeric")); + } +#endif + } + } else { + sprintf(card_datas,"AUTHFAIL"); + } + } + switch (pn532_function) { + case 0x01: + if (!erase_success) { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase fail - exiting erase mode")); + } + break; + case 0x02: + if (!set_success) { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Write failed - exiting set mode")); + } + default: + break; + } + pn532_function = 0; +#endif + +#ifdef USE_PN532_DATA_FUNCTION + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); +#else + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); +#endif + + MqttPublishTeleSensor(); + +#ifdef USE_PN532_CAUSE_EVENTS + + char command[71]; +#ifdef USE_PN532_DATA_FUNCTION + sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); +#else + sprintf(command,"event PN532_UID=%s",uids); +#endif + ExecuteCommand(command, SRC_RULE); +#endif + + pn532_scantimer = 7; + } +} + +#ifdef USE_PN532_DATA_FUNCTION + +bool PN532_Command(void) +{ + bool serviced = true; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + char sub_string_tmp[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') { + serviced = false; + return serviced; + } + sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); + pn532_newdata_len = strlen(sub_string_tmp); + if (pn532_newdata_len > 15) { pn532_newdata_len = 15; } + memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len); + pn532_newdata[pn532_newdata_len] = 0x00; + pn532_function = 2; + AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); + ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}")); + return serviced; + } + } +} + +#endif + +bool Xsns40(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_INIT: + PN532_Init(); + result = true; + break; + case FUNC_EVERY_50_MSECOND: + break; + case FUNC_EVERY_100_MSECOND: + break; + case FUNC_EVERY_250_MSECOND: + if (pn532_scantimer > 0) { + pn532_scantimer--; + } else { + PN532_ScanForTag(); + } + break; + case FUNC_EVERY_SECOND: + break; +#ifdef USE_PN532_DATA_FUNCTION + case FUNC_COMMAND_SENSOR: + if (XSNS_40 == XdrvMailbox.index) { + result = PN532_Command(); + } + break; +#endif + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_41_max44009.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_41_max44009.ino" +#ifdef USE_I2C +#ifdef USE_MAX44009 + + + + + + +#define XSNS_41 41 +#define XI2C_28 28 + +#define MAX44009_ADDR1 0x4A +#define MAX44009_ADDR2 0x4B +#define MAX44009_NO_REGISTERS 8 +#define REG_CONFIG 0x02 +#define REG_LUMINANCE 0x03 +#define REG_LOWER_THRESHOLD 0x06 +#define REG_THRESHOLD_TIMER 0x07 + +#define MAX44009_CONTINUOUS_AUTO_MODE 0x80 + +uint8_t max44009_address; +uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2, 0 }; +uint8_t max44009_found = 0; +uint8_t max44009_valid = 0; +float max44009_illuminance = 0; +char max44009_types[] = "MAX44009"; + +bool Max4409Read_lum(void) +{ + max44009_valid = 0; + uint8_t regdata[2]; + + + if (I2cValidRead16((uint16_t *)®data, max44009_address, REG_LUMINANCE)) { + int exponent = (regdata[0] & 0xF0) >> 4; + int mantissa = ((regdata[0] & 0x0F) << 4) | (regdata[1] & 0x0F); + max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); + max44009_valid = 1; + return true; + } else { + return false; + } +} + + + +void Max4409Detect(void) +{ + uint8_t buffer1; + uint8_t buffer2; + for (uint32_t i = 0; 0 != max44009_addresses[i]; i++) { + + max44009_address = max44009_addresses[i]; + if (I2cActive(max44009_address)) { continue; } + + if ((I2cValidRead8(&buffer1, max44009_address, REG_LOWER_THRESHOLD)) && + (I2cValidRead8(&buffer2, max44009_address, REG_THRESHOLD_TIMER))) { + + if ((0x00 == buffer1) && + (0xFF == buffer2)) { + + + + Wire.beginTransmission(max44009_address); + + + Wire.write(REG_CONFIG); + Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); + if (0 == Wire.endTransmission()) { + I2cSetActiveFound(max44009_address, max44009_types); + max44009_found = 1; + break; + } + } + } + } +} + +void Max4409EverySecond(void) +{ + Max4409Read_lum(); +} + +void Max4409Show(bool json) +{ + char illum_str[8]; + + if (max44009_valid) { + + + + uint8_t prec = 0; + if (10 > max44009_illuminance ) { + prec = 3; + } else if (100 > max44009_illuminance) { + prec = 2; + } else if (1000 > max44009_illuminance) { + prec = 1; + } + dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, illum_str); + } +#endif +#ifdef USE_WEBSERVER + } else { + + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, max44009_types, (int)max44009_illuminance); +#endif + } + } +} + + + + + +bool Xsns41(uint8_t function) +{ + if (!I2cEnabled(XI2C_28)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Max4409Detect(); + } + else if (max44009_found) { + switch (function) { + case FUNC_EVERY_SECOND: + Max4409EverySecond(); + break; + case FUNC_JSON_APPEND: + Max4409Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Max4409Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_42_scd30.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_42_scd30.ino" +#ifdef USE_I2C +#ifdef USE_SCD30 + +#define XSNS_42 42 +#define XI2C_29 29 + + + +#define SCD30_ADDRESS 0x61 + +#define SCD30_MAX_MISSED_READS 3 +#define SCD30_STATE_NO_ERROR 0 +#define SCD30_STATE_ERROR_DATA_CRC 1 +#define SCD30_STATE_ERROR_READ_MEAS 2 +#define SCD30_STATE_ERROR_SOFT_RESET 3 +#define SCD30_STATE_ERROR_I2C_RESET 4 +#define SCD30_STATE_ERROR_UNKNOWN 5 + +#include "Arduino.h" +#include + +#define D_CMND_SCD30 "SCD30" + +const char S_JSON_SCD30_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d}"; +const char S_JSON_SCD30_COMMAND_NFW_VALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d.%d}"; +const char S_JSON_SCD30_COMMAND[] PROGMEM = "{\"" D_CMND_SCD30 "%s\"}"; +const char kSCD30_Commands[] PROGMEM = "Alt|Auto|Cal|FW|Int|Pres|TOff"; + + + + + +enum SCD30_Commands { + CMND_SCD30_ALTITUDE, + CMND_SCD30_AUTOMODE, + CMND_SCD30_CALIBRATE, + CMND_SCD30_FW, + CMND_SCD30_INTERVAL, + CMND_SCD30_PRESSURE, + CMND_SCD30_TEMPOFFSET +}; + +FrogmoreScd30 scd30; + +bool scd30Found = false; +bool scd30IsDataValid = false; +int scd30ErrorState = SCD30_STATE_NO_ERROR; +uint16_t scd30Interval_sec; +int scd30Loop_count = 0; +int scd30DataNotAvailable_count = 0; +int scd30GoodMeas_count = 0; +int scd30Reset_count = 0; +int scd30CrcError_count = 0; +int scd30Co2Zero_count = 0; +int i2cReset_count = 0; +uint16_t scd30_CO2 = 0; +uint16_t scd30_CO2EAvg = 0; +float scd30_Humid = 0.0; +float scd30_Temp = 0.0; + +void Scd30Detect(void) +{ + if (I2cActive(SCD30_ADDRESS)) { return; } + + scd30.begin(); + + uint8_t major = 0; + uint8_t minor = 0; + if (scd30.getFirmwareVersion(&major, &minor)) { return; } + uint16_t interval_sec; + if (scd30.getMeasurementInterval(&scd30Interval_sec)) { return; } + if (scd30.beginMeasuring()) { return; } + + I2cSetActiveFound(SCD30_ADDRESS, "SCD30"); + scd30Found = true; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SCD: FW v%d.%d"), major, minor); +} + + +void Scd30Update(void) +{ + scd30Loop_count++; + if (scd30Loop_count > (scd30Interval_sec - 1)) { + int error = 0; + switch (scd30ErrorState) { + case SCD30_STATE_NO_ERROR: { + error = scd30.readMeasurement(&scd30_CO2, &scd30_CO2EAvg, &scd30_Temp, &scd30_Humid); + switch (error) { + case ERROR_SCD30_NO_ERROR: + scd30Loop_count = 0; + scd30IsDataValid = true; + scd30GoodMeas_count++; + break; + + case ERROR_SCD30_NO_DATA: + scd30DataNotAvailable_count++; + break; + + case ERROR_SCD30_CRC_ERROR: + scd30ErrorState = SCD30_STATE_ERROR_DATA_CRC; + scd30CrcError_count++; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), + scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); +#endif + break; + + case ERROR_SCD30_CO2_ZERO: + scd30Co2Zero_count++; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), + scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); +#endif + break; + + default: { + scd30ErrorState = SCD30_STATE_ERROR_READ_MEAS; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, scd30Loop_count); +#endif + return; + } + break; + } + } + break; + + case SCD30_STATE_ERROR_DATA_CRC: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: got CRC error, try again, counter: %ld"), scd30Loop_count); +#endif + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + break; + + case SCD30_STATE_ERROR_READ_MEAS: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: not answering, sending soft reset, counter: %ld"), scd30Loop_count); +#endif + scd30Reset_count++; + error = scd30.softReset(); + if (error) { +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: resetting got error: 0x%lX"), error); +#endif + error >>= 8; + if (error == 4) { + scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; + } else { + scd30ErrorState = SCD30_STATE_ERROR_UNKNOWN; + } + } else { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + case SCD30_STATE_ERROR_SOFT_RESET: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P(LOG_LEVEL_ERROR, PSTR("SCD30: clearing i2c bus")); +#endif + i2cReset_count++; + error = scd30.clearI2CBus(); + if (error) { + scd30ErrorState = SCD30_STATE_ERROR_I2C_RESET; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error clearing i2c bus: 0x%lX"), error); +#endif + } else { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + default: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: unknown error state: 0x%lX"), scd30ErrorState); +#endif + scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; + } + } + + if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) { + scd30IsDataValid = false; + } + } +} + + +int Scd30GetCommand(int command_code, uint16_t *pvalue) +{ + switch (command_code) + { + case CMND_SCD30_ALTITUDE: + return scd30.getAltitudeCompensation(pvalue); + break; + + case CMND_SCD30_AUTOMODE: + return scd30.getCalibrationType(pvalue); + break; + + case CMND_SCD30_CALIBRATE: + return scd30.getForcedRecalibrationFactor(pvalue); + break; + + case CMND_SCD30_INTERVAL: + return scd30.getMeasurementInterval(pvalue); + break; + + case CMND_SCD30_PRESSURE: + return scd30.getAmbientPressure(pvalue); + break; + + case CMND_SCD30_TEMPOFFSET: + return scd30.getTemperatureOffset(pvalue); + break; + + default: + + break; + } +} + +int Scd30SetCommand(int command_code, uint16_t value) +{ + switch (command_code) + { + case CMND_SCD30_ALTITUDE: + return scd30.setAltitudeCompensation(value); + break; + + case CMND_SCD30_AUTOMODE: + return scd30.setCalibrationType(value); + break; + + case CMND_SCD30_CALIBRATE: + return scd30.setForcedRecalibrationFactor(value); + break; + + case CMND_SCD30_INTERVAL: + { + int error = scd30.setMeasurementInterval(value); + if (!error) + { + scd30Interval_sec = value; + } + + return error; + } + break; + + case CMND_SCD30_PRESSURE: + return scd30.setAmbientPressure(value); + break; + + case CMND_SCD30_TEMPOFFSET: + return scd30.setTemperatureOffset(value); + break; + + default: + + break; + } +} + + + + + +bool Scd30CommandSensor() +{ + char command[CMDSZ]; + bool serviced = true; + uint8_t prefix_len = strlen(D_CMND_SCD30); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_SCD30), prefix_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + prefix_len, kSCD30_Commands); + + switch (command_code) { + case CMND_SCD30_ALTITUDE: + case CMND_SCD30_AUTOMODE: + case CMND_SCD30_CALIBRATE: + case CMND_SCD30_INTERVAL: + case CMND_SCD30_PRESSURE: + case CMND_SCD30_TEMPOFFSET: + { + uint16_t value = 0; + if (XdrvMailbox.data_len > 0) + { + value = XdrvMailbox.payload; + Scd30SetCommand(command_code, value); + } + else + { + Scd30GetCommand(command_code, &value); + } + + Response_P(S_JSON_SCD30_COMMAND_NVALUE, command, value); + } + break; + + case CMND_SCD30_FW: + { + uint8_t major = 0; + uint8_t minor = 0; + int error; + error = scd30.getFirmwareVersion(&major, &minor); + if (error) + { +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error getting FW version: 0x%lX"), error); +#endif + serviced = false; + } + else + { + Response_P(S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); + } + } + break; + + default: + + serviced = false; + break; + } + } + return serviced; +} + +void Scd30Show(bool json) +{ + if (scd30IsDataValid) + { + char humidity[10]; + dtostrfd(ConvertHumidity(scd30_Humid), Settings.flag2.humidity_resolution, humidity); + char temperature[10]; + dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); + + if (json) { + + ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), + scd30_CO2, scd30_CO2EAvg, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) + { + DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); + WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); + WSContentSend_PD(HTTP_SNS_TEMP, "SCD30", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, "SCD30", humidity); +#endif + } + } +} + + + + + +bool Xsns42(byte function) +{ + if (!I2cEnabled(XI2C_29)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Scd30Detect(); + } + else if (scd30Found) { + switch (function) { + case FUNC_EVERY_SECOND: + Scd30Update(); + break; + case FUNC_COMMAND: + result = Scd30CommandSensor(); + break; + case FUNC_JSON_APPEND: + Scd30Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Scd30Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_43_hre.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_43_hre.ino" +#ifdef USE_HRE +# 49 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_43_hre.ino" +#define XSNS_43 43 + +enum hre_states { + hre_idle, + hre_sync, + hre_syncing, + hre_read, + hre_reading, + hre_sleep, + hre_sleeping +}; + +hre_states hre_state = hre_idle; + +float hre_usage = 0; +float hre_rate = 0; +uint32_t hre_usage_time = 0; + +int hre_read_errors = 0; +bool hre_good = false; + + + +int hreReadBit() +{ + digitalWrite(pin[GPIO_HRE_CLOCK], HIGH); + delay(1); + int bit = digitalRead(pin[GPIO_HRE_DATA]); + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + delay(1); + return bit; +} + + + +char hreReadChar(int &parity_errors) +{ + + hreReadBit(); + + unsigned ch=0; + int sum=0; + for (uint32_t i=0; i<7; i++) + { + int b = hreReadBit(); + ch |= b << i; + sum += b; + } + + + if ( (sum & 0x1) != hreReadBit()) + parity_errors++; + + + hreReadBit(); + + return ch; +} + +void hreInit(void) +{ + hre_read_errors = 0; + hre_good = false; + + pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); + pinMode(pin[GPIO_HRE_DATA], INPUT); + + + + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + + hre_state = hre_sync; +} + + +void hreEvery50ms(void) +{ + static int sync_counter = 0; + static int sync_run = 0; + + static uint32_t curr_start = 0; + static int read_counter = 0; + static int parity_errors = 0; + static char buff[46]; + + static char ch; + static size_t i; + + switch (hre_state) + { + case hre_sync: + if (uptime < 10) + break; + sync_run = 0; + sync_counter = 0; + hre_state = hre_syncing; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); + break; + + case hre_syncing: + + + for (uint32_t i=0; i<20; i++) + { + if (hreReadBit()) + sync_run++; + else + sync_run = 0; + if (sync_run == 62) + { + hre_state = hre_read; + break; + } + sync_counter++; + } + + if (sync_counter > 1000) + { + hre_state = hre_sleep; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE D_ERROR)); + } + break; + + + case hre_read: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); + read_counter = 0; + parity_errors = 0; + curr_start = uptime; + memset(buff, 0, sizeof(buff)); + hre_state = hre_reading; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); + + + + + + case hre_reading: + + buff[read_counter++] = hreReadChar(parity_errors); + buff[read_counter++] = hreReadChar(parity_errors); + + if (read_counter == 46) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), + parity_errors, hre_read_errors, buff); + if (parity_errors == 0) + { + float curr_usage; + curr_usage = 0.01 * atol(buff+24); + if (hre_usage_time) + { + double dt = 1.666e-2 * (curr_start - hre_usage_time); + hre_rate = (curr_usage - hre_usage)/dt; + } + hre_usage = curr_usage; + hre_usage_time = curr_start; + hre_good = true; + + hre_state = hre_sleep; + } + else + { + hre_read_errors++; + hre_state = hre_sleep; + } + } + break; + + case hre_sleep: + hre_usage_time = curr_start; + hre_state = hre_sleeping; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_sleeping")); + + case hre_sleeping: + + + if (uptime - hre_usage_time >= 27) + hre_state = hre_sync; + } +} + +void hreShow(boolean json) +{ + if (!hre_good) + return; + + const char *id = "HRE"; + + char usage[16]; + char rate[16]; + dtostrfd(hre_usage, 2, usage); + dtostrfd(hre_rate, 3, rate); + + if (json) + { + ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_GALLONS, id, usage); + WSContentSend_PD(HTTP_SNS_GPM, id, rate); +#endif + } +} + + + + + +bool Xsns43(byte function) +{ + + if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) + return false; + + switch (function) + { + case FUNC_INIT: + hreInit(); + break; + case FUNC_EVERY_50_MSECOND: + hreEvery50ms(); + break; + case FUNC_EVERY_SECOND: + break; + case FUNC_JSON_APPEND: + hreShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + hreShow(0); + break; +#endif + } + return false; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_44_sps30.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_44_sps30.ino" +#ifdef USE_I2C +#ifdef USE_SPS30 + +#define XSNS_44 44 +#define XI2C_30 30 + +#define SPS30_ADDR 0x69 + +#include +#include + +uint8_t sps30_ready = 0; +uint8_t sps30_running; + +struct SPS30 { + float PM1_0; + float PM2_5; + float PM4_0; + float PM10; + float NCPM0_5; + float NCPM1_0; + float NCPM2_5; + float NCPM4_0; + float NCPM10; + float TYPSIZ; +} sps30_result; + +#define SPS_CMD_START_MEASUREMENT 0x0010 +#define SPS_CMD_START_MEASUREMENT_ARG 0x0300 +#define SPS_CMD_STOP_MEASUREMENT 0x0104 +#define SPS_CMD_READ_MEASUREMENT 0x0300 +#define SPS_CMD_GET_DATA_READY 0x0202 +#define SPS_CMD_AUTOCLEAN_INTERVAL 0x8004 +#define SPS_CMD_CLEAN 0x5607 +#define SPS_CMD_GET_ACODE 0xd025 +#define SPS_CMD_GET_SERIAL 0xd033 +#define SPS_CMD_RESET 0xd304 +#define SPS_WRITE_DELAY_US 20000 +#define SPS_MAX_SERIAL_LEN 32 + +uint8_t sps30_calc_CRC(uint8_t *data) { + uint8_t crc = 0xFF; + for (uint32_t i = 0; i < 2; i++) { + crc ^= data[i]; + for (uint32_t bit = 8; bit > 0; --bit) { + if(crc & 0x80) { + crc = (crc << 1) ^ 0x31u; + } else { + crc = (crc << 1); + } + } + } + return crc; +} + +void CmdClean(void); + +unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop); + +void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen) { +unsigned char cmdb[2]; +uint8_t tmp[3]; +uint8_t index=0; +memset(data,0,dlen); +uint8_t twi_buff[64]; + + Wire.beginTransmission(SPS30_ADDR); + cmdb[0]=cmd>>8; + cmdb[1]=cmd; + Wire.write(cmdb,2); + Wire.endTransmission(); + + + dlen/=2; + dlen*=3; + + twi_readFrom(SPS30_ADDR,twi_buff,dlen,1); + + uint8_t bind=0; + while (bind>8; + cmdb[1]=cmd; + + if (cmd==SPS_CMD_START_MEASUREMENT) { + cmdb[2]=SPS_CMD_START_MEASUREMENT_ARG>>8; + cmdb[3]=SPS_CMD_START_MEASUREMENT_ARG&0xff; + cmdb[4]=sps30_calc_CRC(&cmdb[2]); + Wire.write(cmdb,5); + } else { + Wire.write(cmdb,2); + } + Wire.endTransmission(); +} + +void SPS30_Detect(void) +{ + if (!I2cSetDevice(SPS30_ADDR)) { return; } + I2cSetActiveFound(SPS30_ADDR, "SPS30"); + + uint8_t dcode[32]; + sps30_get_data(SPS_CMD_GET_SERIAL,dcode,sizeof(dcode)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("sps30 found with serial: %s"),dcode); + sps30_cmd(SPS_CMD_START_MEASUREMENT); + sps30_running = 1; + sps30_ready = 1; +} + +#define D_UNIT_PM "ug/m3" +#define D_UNIT_NCPM "#/m3" + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SPS30_a[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_PM "{e}"; +const char HTTP_SNS_SPS30_b[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_NCPM "{e}"; +const char HTTP_SNS_SPS30_c[] PROGMEM ="{s}SPS30 " "TYPSIZ" "{m}%s " "um" "{e}"; +#endif + +#define PMDP 2 + +#define SPS30_HOURS Settings.sps30_inuse_hours + + + +void SPS30_Every_Second() { + if (!sps30_running) return; + + if (uptime%10==0) { + uint8_t vars[sizeof(float)*10]; + sps30_get_data(SPS_CMD_READ_MEASUREMENT,vars,sizeof(vars)); + float *fp=&sps30_result.PM1_0; + + typedef union { + uint8_t array[4]; + float value; + } ByteToFloat; + + ByteToFloat conv; + + for (uint32_t count=0; count<10; count++) { + for (uint32_t i = 0; i < 4; i++){ + conv.array[3-i] = vars[count*sizeof(float)+i]; + } + *fp++=conv.value; + } + } + + if (uptime%3600==0 && uptime>60) { + + + SPS30_HOURS++; + if (SPS30_HOURS>(7*24)) { + CmdClean(); + SPS30_HOURS=0; + } + } + +} + +void SPS30_Show(bool json) +{ + if (!sps30_running) { return; } + + char str[64]; + if (json) { + dtostrfd(sps30_result.PM1_0,PMDP,str); + ResponseAppend_P(PSTR(",\"SPS30\":{\"" "PM1_0" "\":%s"), str); + dtostrfd(sps30_result.PM2_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM2_5" "\":%s"), str); + dtostrfd(sps30_result.PM4_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM4_0" "\":%s"), str); + dtostrfd(sps30_result.PM10,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM10" "\":%s"), str); + dtostrfd(sps30_result.NCPM0_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM0_5" "\":%s"), str); + dtostrfd(sps30_result.NCPM1_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM1_0" "\":%s"), str); + dtostrfd(sps30_result.NCPM2_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM2_5" "\":%s"), str); + dtostrfd(sps30_result.NCPM4_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM4_0" "\":%s"), str); + dtostrfd(sps30_result.NCPM10,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM10" "\":%s"), str); + dtostrfd(sps30_result.TYPSIZ,PMDP,str); + ResponseAppend_P(PSTR(",\"" "TYPSIZ" "\":%s}"), str); + +#ifdef USE_WEBSERVER + } else { + dtostrfd(sps30_result.PM1_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 1.0",str); + dtostrfd(sps30_result.PM2_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 2.5",str); + dtostrfd(sps30_result.PM4_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 4.0",str); + dtostrfd(sps30_result.PM10,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 10",str); + dtostrfd(sps30_result.NCPM0_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 0.5",str); + dtostrfd(sps30_result.NCPM1_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 1.0",str); + dtostrfd(sps30_result.NCPM2_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 2.5",str); + dtostrfd(sps30_result.NCPM4_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 4.0",str); + dtostrfd(sps30_result.NCPM10,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 10",str); + dtostrfd(sps30_result.TYPSIZ,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_c,str); +#endif + } +} + +void CmdClean(void) +{ + sps30_cmd(SPS_CMD_CLEAN); + ResponseTime_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}")); + MqttPublishTeleSensor(); +} + +bool SPS30_cmd(void) +{ + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + char *cp=XdrvMailbox.data; + if (*cp=='c') { + + CmdClean(); + } else if (*cp=='0' || *cp=='1') { + sps30_running=*cp&1; + sps30_cmd(sps30_running?SPS_CMD_START_MEASUREMENT:SPS_CMD_STOP_MEASUREMENT); + } else { + serviced=false; + } + } + Response_P(PSTR("{\"SPS30\":\"%s\"}"), sps30_running?"running":"stopped"); + + return serviced; +} + + + + + +bool Xsns44(byte function) +{ + if (!I2cEnabled(XI2C_30)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + SPS30_Detect(); + } + else if (sps30_ready) { + switch (function) { + case FUNC_EVERY_SECOND: + SPS30_Every_Second(); + break; + case FUNC_JSON_APPEND: + SPS30_Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SPS30_Show(0); + break; + #endif + case FUNC_COMMAND_SENSOR: + if (XSNS_44 == XdrvMailbox.index) { + result = SPS30_cmd(); + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_45_vl53l0x.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_45_vl53l0x.ino" +#ifdef USE_I2C +#ifdef USE_VL53L0X + +#define XSNS_45 45 +#define XI2C_31 31 + +#include +#include "VL53L0X.h" +VL53L0X sensor; + +uint8_t vl53l0x_ready = 0; +uint16_t vl53l0x_distance; +uint16_t Vl53l0_buffer[5]; +uint8_t Vl53l0_index; + + + +void Vl53l0Detect(void) +{ + if (!I2cSetDevice(0x29)) { return; } + + if (!sensor.init()) { return; } + + I2cSetActiveFound(sensor.getAddress(), "VL53L0X"); + + sensor.setTimeout(500); + + + + + + sensor.startContinuous(); + vl53l0x_ready = 1; + + Vl53l0_index=0; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_VL53L0X[] PROGMEM = + "{s}VL53L0X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; +#endif + +#define USE_VL_MEDIAN + +void Vl53l0Every_250MSecond(void) +{ + uint16_t tbuff[5],tmp; + uint8_t flag; + + + uint16_t dist = sensor.readRangeContinuousMillimeters(); + if (dist==0 || dist>2000) { + dist=9999; + } + +#ifdef USE_VL_MEDIAN + + Vl53l0_buffer[Vl53l0_index]=dist; + Vl53l0_index++; + if (Vl53l0_index>=5) Vl53l0_index=0; + + + memmove(tbuff,Vl53l0_buffer,sizeof(tbuff)); + for (byte ocnt=0; ocnt<5; ocnt++) { + flag=0; + for (byte count=0; count<4; count++) { + if (tbuff[count]>tbuff[count+1]) { + tmp=tbuff[count]; + tbuff[count]=tbuff[count+1]; + tbuff[count+1]=tmp; + flag=1; + } + } + if (!flag) break; + } + vl53l0x_distance=tbuff[2]; +#else + vl53l0x_distance=dist; +#endif +} + +void Vl53l0Show(boolean json) +{ + if (json) { + ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l0x_distance); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VL53L0X, vl53l0x_distance); +#endif + } +} + + + + + +bool Xsns45(byte function) +{ + if (!I2cEnabled(XI2C_31)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Vl53l0Detect(); + } + else if (vl53l0x_ready) { + switch (function) { + case FUNC_EVERY_250_MSECOND: + Vl53l0Every_250MSecond(); + break; + case FUNC_JSON_APPEND: + Vl53l0Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Vl53l0Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_46_MLX90614.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_46_MLX90614.ino" +#ifdef USE_I2C +#ifdef USE_MLX90614 + +#define XSNS_46 46 +#define XI2C_32 32 + +#define I2_ADR_IRT 0x5a + +#define MLX90614_RAWIR1 0x04 +#define MLX90614_RAWIR2 0x05 +#define MLX90614_TA 0x06 +#define MLX90614_TOBJ1 0x07 +#define MLX90614_TOBJ2 0x08 + +struct { + union { + uint16_t value; + uint32_t i2c_buf; + }; + float obj_temp; + float amb_temp; + bool ready = false; +} mlx90614; + +void MLX90614_Init(void) +{ + if (!I2cSetDevice(I2_ADR_IRT)) { return; } + I2cSetActiveFound(I2_ADR_IRT, "MLX90614"); + mlx90614.ready = true; +} + +void MLX90614_Every_Second(void) +{ + mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT, MLX90614_TOBJ1); + if (mlx90614.value & 0x8000) { + mlx90614.obj_temp = -999; + } else { + mlx90614.obj_temp = ((float)mlx90614.value * 0.02) - 273.15; + } + mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT,MLX90614_TA); + if (mlx90614.value & 0x8000) { + mlx90614.amb_temp = -999; + } else { + mlx90614.amb_temp = ((float)mlx90614.value * 0.02) - 273.15; + } +} + +#ifdef USE_WEBSERVER + const char HTTP_IRTMP[] PROGMEM = + "{s}MXL90614 " "OBJ-" D_TEMPERATURE "{m}%s C" "{e}" + "{s}MXL90614 " "AMB-" D_TEMPERATURE "{m}%s C" "{e}"; +#endif + +void MLX90614_Show(uint8_t json) +{ + char obj_tstr[16]; + dtostrfd(mlx90614.obj_temp, Settings.flag2.temperature_resolution, obj_tstr); + char amb_tstr[16]; + dtostrfd(mlx90614.amb_temp, Settings.flag2.temperature_resolution, amb_tstr); + + if (json) { + ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr, amb_tstr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_IRTMP, obj_tstr, amb_tstr); +#endif + } +} + + + + + +bool Xsns46(byte function) +{ + if (!I2cEnabled(XI2C_32)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MLX90614_Init(); + } + else if (mlx90614.ready) { + switch (function) { + case FUNC_EVERY_SECOND: + MLX90614_Every_Second(); + break; + case FUNC_JSON_APPEND: + MLX90614_Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MLX90614_Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_47_max31865.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_47_max31865.ino" +#ifdef USE_MAX31865 + +#ifndef USE_SPI +#error "MAX31865 requires USE_SPI enabled" +#endif + +#include "Adafruit_MAX31865.h" + +#define XSNS_47 47 + +#if MAX31865_PTD_WIRES == 4 + #define PTD_WIRES MAX31865_4WIRE +#elif MAX31865_PTD_WIRES == 3 + #define PTD_WIRES MAX31865_3WIRE +#else + #define PTD_WIRES MAX31865_2WIRE +#endif + +int8_t init_status = 0; + +Adafruit_MAX31865 max31865; + +struct MAX31865_Result_Struct { + uint8_t ErrorCode; + uint16_t Rtd; + float PtdResistance; + float PtdTemp; +} MAX31865_Result; + +void MAX31865_Init(void){ + if(init_status) + return; + + max31865.setPins( + pin[GPIO_SSPI_CS], + pin[GPIO_SSPI_MOSI], + pin[GPIO_SSPI_MISO], + pin[GPIO_SSPI_SCLK] + ); + + if(max31865.begin(PTD_WIRES)) + init_status = 1; + else + init_status = -1; +} + + + + + +void MAX31865_GetResult(void){ + uint16_t rtd; + + rtd = max31865.readRTD(); + MAX31865_Result.Rtd = rtd; + MAX31865_Result.PtdResistance = max31865.rtd_to_resistance(rtd, MAX31865_REF_RES); + MAX31865_Result.PtdTemp = max31865.rtd_to_temperature(rtd, MAX31865_PTD_RES, MAX31865_REF_RES) + MAX31865_PTD_BIAS; +} + +void MAX31865_Show(bool Json){ + char temperature[33]; + char resistance[33]; + + dtostrfd(MAX31865_Result.PtdResistance, Settings.flag2.temperature_resolution, resistance); + dtostrfd(MAX31865_Result.PtdTemp, Settings.flag2.temperature_resolution, temperature); + + if(Json){ + ResponseAppend_P(PSTR(",\"MAX31865\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + temperature, resistance, MAX31865_Result.ErrorCode); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, MAX31865_Result.PtdTemp); + } +#endif + } else { +#ifdef USE_WEBSERVER + WSContentSend_PD(HTTP_SNS_TEMP, "MAX31865", temperature, TempUnit()); +#endif + } +} + + + + + +bool Xsns47(uint8_t function) +{ + bool result = false; + if((pin[GPIO_SSPI_MISO] < 99) && (pin[GPIO_SSPI_MOSI] < 99) && + (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_CS] < 99)) { + + switch (function) { + case FUNC_INIT: + MAX31865_Init(); + break; + + case FUNC_EVERY_SECOND: + MAX31865_GetResult(); + break; + + case FUNC_JSON_APPEND: + MAX31865_Show(true); + break; + +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MAX31865_Show(false); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_48_chirp.ino" +# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_48_chirp.ino" +#ifdef USE_I2C +#ifdef USE_CHIRP +# 47 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_48_chirp.ino" +#define XSNS_48 48 +#define XI2C_33 33 + +#define CHIRP_MAX_SENSOR_COUNT 3 + +#define CHIRP_ADDR_STANDARD 0x20 + + + + + +#define D_CMND_CHIRP "CHIRP" + +const char S_JSON_CHIRP_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_CHIRP "%s\":%d}"; +const char S_JSON_CHIRP_COMMAND[] PROGMEM = "{\"" D_CMND_CHIRP "%s\"}"; +const char kCHIRP_Commands[] PROGMEM = "Select|Set|Scan|Reset|Sleep|Wake"; + +const char kChirpTypes[] PROGMEM = "CHIRP"; + + + + + +enum CHIRP_Commands { + CMND_CHIRP_SELECT, + CMND_CHIRP_SET, + CMND_CHIRP_SCAN, + CMND_CHIRP_RESET, + CMND_CHIRP_SLEEP, + CMND_CHIRP_WAKE }; + + + + + + +#define CHIRP_GET_CAPACITANCE 0x00 +#define CHIRP_SET_ADDRESS 0x01 +#define CHIRP_GET_ADDRESS 0x02 +#define CHIRP_MEASURE_LIGHT 0x03 +#define CHIRP_GET_LIGHT 0x04 +#define CHIRP_GET_TEMPERATURE 0x05 +#define CHIRP_RESET 0x06 +#define CHIRP_GET_VERSION 0x07 +#define CHIRP_SLEEP 0x08 +#define CHIRP_GET_BUSY 0x09 + + + + + +void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg) { + Wire.beginTransmission(addr); + Wire.write(reg); + Wire.endTransmission(); +} + +uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr) { + Wire.requestFrom(addr,(uint8_t)2); + uint16_t t = Wire.read() << 8; + t = t | Wire.read(); + return t; +} + + + + + +uint8_t chirp_current = 0; +uint8_t chirp_found_sensors = 0; + +char chirp_name[7]; +uint8_t chirp_next_job = 0; +uint32_t chirp_timeout_count = 0; + +#pragma pack(1) +struct ChirpSensor_t{ + uint16_t moisture = 0; + uint16_t light = 0; + int16_t temperature = 0; + uint8_t version = 0; + uint8_t address:7; + uint8_t explicitSleep:1; +}; +#pragma pack() + +ChirpSensor_t chirp_sensor[CHIRP_MAX_SENSOR_COUNT]; + + + +void ChirpReset(uint8_t addr) { + ChirpWriteI2CRegister(addr, CHIRP_RESET); +} + + + +void ChirpResetAll(void) { + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version) { + ChirpReset(chirp_sensor[i].address); + } + } +} + + +void ChirpClockSet() { + Wire.setClockStretchLimit(4000); + Wire.setClock(50000); +} + + + +void ChirpSleep(uint8_t addr) { + ChirpWriteI2CRegister(addr, CHIRP_SLEEP); +} +# 185 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_48_chirp.ino" +void ChirpSelect(uint8_t sensor) { + if(sensor < chirp_found_sensors) { + chirp_current = sensor; + DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u now active."), chirp_current); + } + if (sensor == 255) { + DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u active at address 0x%x."), chirp_current, chirp_sensor[chirp_current].address); + } +} + + + +uint8_t ChirpReadVersion(uint8_t addr) { + return (I2cRead8(addr, CHIRP_GET_VERSION)); +} + + + +bool ChirpSet(uint8_t addr) { + if(addr < 128){ + if (I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr)){ + if(chirp_sensor[chirp_current].version>0x25 && chirp_sensor[chirp_current].version != 255){ + delay(5); + I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); + + } + DEBUG_SENSOR_LOG(PSTR("CHIRP: Wrote adress %u "), addr); + ChirpReset(chirp_sensor[chirp_current].address); + chirp_sensor[chirp_current].address = addr; + chirp_timeout_count = 10; + chirp_next_job = 0; + if(chirp_sensor[chirp_current].version == 255){ + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: wrote new address %u, please power off device"), addr); + chirp_sensor[chirp_current].version == 0; + } + return true; + } + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: address %u incorrect and not used"), addr); + return false; +} + + + +bool ChirpScan() +{ + ChirpClockSet(); + chirp_found_sensors = 0; + for (uint8_t address = 1; address <= 127; address++) { + chirp_sensor[chirp_found_sensors].version = 0; + chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); + delay(2); + chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); + if (chirp_sensor[chirp_found_sensors].version > 0) { + I2cSetActiveFound(address, "CHIRP"); + if (chirp_found_sensors 0); +} + + + +void ChirpDetect(void) +{ + if (chirp_next_job > 0) { return; } + + DEBUG_SENSOR_LOG(PSTR("CHIRP: scan will start ...")); + if (ChirpScan()) { + uint8_t chirp_model = 0; + GetTextIndexed(chirp_name, sizeof(chirp_name), chirp_model, kChirpTypes); + } +} + + +void ChirpServiceAllSensors(uint8_t job){ + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare for sensor at address 0x%x"), chirp_sensor[i].address); + switch(job){ + case 0: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_CAPACITANCE); + break; + case 1: + chirp_sensor[i].moisture = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + case 2: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_TEMPERATURE); + break; + case 3: + chirp_sensor[i].temperature = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + case 4: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_MEASURE_LIGHT); + break; + case 5: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_LIGHT); + break; + case 6: + chirp_sensor[i].light = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + default: + break; + } + } + } +} + + + +void ChirpEvery100MSecond(void) +{ + + if(chirp_timeout_count == 0) { + switch(chirp_next_job) { + case 0: + DEBUG_SENSOR_LOG(PSTR("CHIRP: reset all")); + ChirpResetAll(); + chirp_timeout_count = 10; + chirp_next_job++; + break; + case 1: + + + chirp_next_job++; + break; + case 2: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read")); + ChirpServiceAllSensors(0); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 3: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read")); + ChirpServiceAllSensors(1); + chirp_next_job++; + break; + case 4: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read - 2nd")); + ChirpServiceAllSensors(0); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 5: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read - 2nd")); + ChirpServiceAllSensors(1); + chirp_next_job++; + break; + case 6: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read")); + ChirpServiceAllSensors(2); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 7: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read")); + ChirpServiceAllSensors(3); + chirp_next_job++; + break; + case 8: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read - 2nd")); + ChirpServiceAllSensors(2); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 9: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read - 2nd")); + ChirpServiceAllSensors(3); + chirp_next_job++; + break; + case 10: + DEBUG_SENSOR_LOG(PSTR("CHIRP: start light measure process")); + ChirpServiceAllSensors(4); + chirp_timeout_count = 90; + chirp_next_job++; + break; + case 11: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare light read")); + ChirpServiceAllSensors(5); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 12: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish light read")); + ChirpServiceAllSensors(6); + chirp_next_job++; + break; + case 13: + DEBUG_SENSOR_LOG(PSTR("CHIRP: paused, waiting for TELE")); + break; + case 14: + if (Settings.tele_period > 16){ + chirp_timeout_count = (Settings.tele_period - 17) * 10; + DEBUG_SENSOR_LOG(PSTR("CHIRP: timeout 1/10 sec: %u, tele: %u"), chirp_timeout_count, Settings.tele_period); + } + else{ + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: TELEPERIOD must be > 16 seconds !")); + + } + chirp_next_job = 1; + break; + } + } + else { + chirp_timeout_count--; + } +} + + + + +#ifdef USE_WEBSERVER + + +const char HTTP_SNS_DARKNESS[] PROGMEM = "{s} " D_JSON_DARKNESS "{m}%s %%{e}"; +const char HTTP_SNS_CHIRPVER[] PROGMEM = "{s} CHIRP-sensor %u at address{m}0x%x{e}" + "{s} FW-version{m}%s {e}"; ; +const char HTTP_SNS_CHIRPSLEEP[] PROGMEM = "{s} {m} is sleeping ...{e}"; +#endif + + + +void ChirpShow(bool json) +{ + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version) { + + char str_temperature[33]; + double t_temperature = ((double) chirp_sensor[i].temperature )/10.0; + dtostrfd(t_temperature, Settings.flag2.temperature_resolution, str_temperature); + char str_light[33]; + dtostrfd(chirp_sensor[i].light, 0, str_light); + char str_version[7]; + if(chirp_sensor[i].version == 0xff){ + strncpy_P(str_version, PSTR("Chirp!"), sizeof(str_version)); + } + else{ + sprintf(str_version, "%x", chirp_sensor[i].version); + } + + if (json) { + if(!chirp_sensor[i].explicitSleep) { + ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%d"), chirp_name, i, chirp_sensor[i].moisture); + if(chirp_sensor[i].temperature!=-1){ + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"),str_temperature); + } + ResponseAppend_P(PSTR(",\"" D_JSON_DARKNESS "\":%s}"),str_light); + } + else { + ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"),chirp_name, i); + } + #ifdef USE_DOMOTICZ + if (0 == tele_period) { + char str_moisture[33]; + dtostrfd(chirp_sensor[i].moisture, 0, str_moisture); + DomoticzTempHumSensor(str_temperature, str_moisture); + DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); + } + #endif + #ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CHIRPVER, i, chirp_sensor[i].address, str_version); + if (chirp_sensor[i].explicitSleep){ + WSContentSend_PD(HTTP_SNS_CHIRPSLEEP); + } + else { + WSContentSend_PD(HTTP_SNS_MOISTURE, "", chirp_sensor[i].moisture); + WSContentSend_PD(HTTP_SNS_DARKNESS, str_light); + if (chirp_sensor[i].temperature!=-1) { + WSContentSend_PD(HTTP_SNS_TEMP, "", str_temperature, TempUnit()); + } + } + + #endif + } + } + } +} + + + + + +bool ChirpCmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_CHIRP); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_CHIRP), disp_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kCHIRP_Commands); + + switch (command_code) { + case CMND_CHIRP_SELECT: + case CMND_CHIRP_SET: + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(XdrvMailbox.payload); } + if (command_code == CMND_CHIRP_SET) { ChirpSet((uint8_t)XdrvMailbox.payload); } + Response_P(S_JSON_CHIRP_COMMAND_NVALUE, command, XdrvMailbox.payload); + } + else { + if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(255); } + Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); + } + break; + case CMND_CHIRP_SCAN: + case CMND_CHIRP_SLEEP: + case CMND_CHIRP_WAKE: + case CMND_CHIRP_RESET: + if (command_code == CMND_CHIRP_SCAN) { chirp_next_job = 0; + ChirpDetect(); } + if (command_code == CMND_CHIRP_SLEEP) { chirp_sensor[chirp_current].explicitSleep = true; + ChirpSleep(chirp_sensor[chirp_current].address); } + if (command_code == CMND_CHIRP_WAKE) { chirp_sensor[chirp_current].explicitSleep = false; + ChirpReadVersion(chirp_sensor[chirp_current].address); } + if (command_code == CMND_CHIRP_RESET) { ChirpReset(chirp_sensor[chirp_current].address); } + Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); + break; + default: + + serviced = false; + break; + } + } + return serviced; +} + + + + + +bool Xsns48(uint8_t function) +{ + if (!I2cEnabled(XI2C_33)) { return false; } + + bool result = false; + + switch (function) { + case FUNC_EVERY_100_MSECOND: + if(chirp_found_sensors > 0){ + ChirpEvery100MSecond(); + } + break; + case FUNC_COMMAND: + result = ChirpCmd(); + break; + case FUNC_JSON_APPEND: + ChirpShow(1); + chirp_next_job = 14; + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + ChirpShow(0); + break; +#endif + case FUNC_INIT: + ChirpDetect(); + break; + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_50_paj7620.ino" +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_50_paj7620.ino" +#ifdef USE_I2C +#ifdef USE_PAJ7620 + + + + + + +#define XSNS_50 50 +#define XI2C_34 34 + +#define PAJ7620_ADDR 0x73 + +#define PAJ7620_BANK_SEL 0xEF + + + +#define PAJ7620_GET_GESTURE 0x43 +#define PAJ7620_PROXIMITY_AVG_Y 0x6c + +#define PAJ7620_OBJECT_CENTER_X 0xad +#define PAJ7620_OBJECT_CENTER_Y 0xaf + +#define PAJ7620_DOWN 1 +#define PAJ7620_UP 2 +#define PAJ7620_RIGHT 4 +#define PAJ7620_LEFT 8 +#define PAJ7620_NEAR 16 +#define PAJ7620_FAR 32 +#define PAJ7620_CW 64 +#define PAJ7620_CCW 128 + + + + +const uint8_t PAJ7620initRegisterArray[][2] PROGMEM = { + {0xEF,0x00}, + {0x32,0x29}, {0x33,0x01}, {0x34,0x00}, {0x35,0x01}, {0x36,0x00}, {0x37,0x07}, {0x38,0x17}, {0x39,0x06}, + {0x3A,0x12}, {0x3F,0x00}, {0x40,0x02}, {0x41,0xFF}, {0x42,0x01}, {0x46,0x2D}, {0x47,0x0F}, {0x48,0x3C}, + {0x49,0x00}, {0x4A,0x1E}, {0x4B,0x00}, {0x4C,0x20}, {0x4D,0x00}, {0x4E,0x1A}, {0x4F,0x14}, {0x50,0x00}, + {0x51,0x10}, {0x52,0x00}, {0x5C,0x02}, {0x5D,0x00}, {0x5E,0x10}, {0x5F,0x3F}, {0x60,0x27}, {0x61,0x28}, + {0x62,0x00}, {0x63,0x03}, {0x64,0xF7}, {0x65,0x03}, {0x66,0xD9}, {0x67,0x03}, {0x68,0x01}, {0x69,0xC8}, + {0x6A,0x40}, {0x6D,0x04}, {0x6E,0x00}, {0x6F,0x00}, {0x70,0x80}, {0x71,0x00}, {0x72,0x00}, {0x73,0x00}, + {0x74,0xF0}, {0x75,0x00}, {0x80,0x42}, {0x81,0x44}, {0x82,0x04}, {0x83,0x20}, {0x84,0x20}, {0x85,0x00}, + {0x86,0x10}, {0x87,0x00}, {0x88,0x05}, {0x89,0x18}, {0x8A,0x10}, {0x8B,0x01}, {0x8C,0x37}, {0x8D,0x00}, + {0x8E,0xF0}, {0x8F,0x81}, {0x90,0x06}, {0x91,0x06}, {0x92,0x1E}, {0x93,0x0D}, {0x94,0x0A}, {0x95,0x0A}, + {0x96,0x0C}, {0x97,0x05}, {0x98,0x0A}, {0x99,0x41}, {0x9A,0x14}, {0x9B,0x0A}, {0x9C,0x3F}, {0x9D,0x33}, + {0x9E,0xAE}, {0x9F,0xF9}, {0xA0,0x48}, {0xA1,0x13}, {0xA2,0x10}, {0xA3,0x08}, {0xA4,0x30}, {0xA5,0x19}, + {0xA6,0x10}, {0xA7,0x08}, {0xA8,0x24}, {0xA9,0x04}, {0xAA,0x1E}, {0xAB,0x1E}, {0xCC,0x19}, {0xCD,0x0B}, + {0xCE,0x13}, {0xCF,0x64}, {0xD0,0x21}, {0xD1,0x0F}, {0xD2,0x88}, {0xE0,0x01}, {0xE1,0x04}, {0xE2,0x41}, + {0xE3,0xD6}, {0xE4,0x00}, {0xE5,0x0C}, {0xE6,0x0A}, {0xE7,0x00}, {0xE8,0x00}, {0xE9,0x00}, {0xEE,0x07}, + {0xEF,0x01}, + {0x00,0x1E}, {0x01,0x1E}, {0x02,0x0F}, {0x03,0x10}, {0x04,0x02}, {0x05,0x00}, {0x06,0xB0}, {0x07,0x04}, + {0x08,0x0D}, {0x09,0x0E}, {0x0A,0x9C}, {0x0B,0x04}, {0x0C,0x05}, {0x0D,0x0F}, {0x0E,0x02}, {0x0F,0x12}, + {0x10,0x02}, {0x11,0x02}, {0x12,0x00}, {0x13,0x01}, {0x14,0x05}, {0x15,0x07}, {0x16,0x05}, {0x17,0x07}, + {0x18,0x01}, {0x19,0x04}, {0x1A,0x05}, {0x1B,0x0C}, {0x1C,0x2A}, {0x1D,0x01}, {0x1E,0x00}, {0x21,0x00}, + {0x22,0x00}, {0x23,0x00}, {0x25,0x01}, {0x26,0x00}, {0x27,0x39}, {0x28,0x7F}, {0x29,0x08}, {0x30,0x03}, + {0x31,0x00}, {0x32,0x1A}, {0x33,0x1A}, {0x34,0x07}, {0x35,0x07}, {0x36,0x01}, {0x37,0xFF}, {0x38,0x36}, + {0x39,0x07}, {0x3A,0x00}, {0x3E,0xFF}, {0x3F,0x00}, {0x40,0x77}, {0x41,0x40}, {0x42,0x00}, {0x43,0x30}, + {0x44,0xA0}, {0x45,0x5C}, {0x46,0x00}, {0x47,0x00}, {0x48,0x58}, {0x4A,0x1E}, {0x4B,0x1E}, {0x4C,0x00}, + {0x4D,0x00}, {0x4E,0xA0}, {0x4F,0x80}, {0x50,0x00}, {0x51,0x00}, {0x52,0x00}, {0x53,0x00}, {0x54,0x00}, + {0x57,0x80}, {0x59,0x10}, {0x5A,0x08}, {0x5B,0x94}, {0x5C,0xE8}, {0x5D,0x08}, {0x5E,0x3D}, {0x5F,0x99}, + {0x60,0x45}, {0x61,0x40}, {0x63,0x2D}, {0x64,0x02}, {0x65,0x96}, {0x66,0x00}, {0x67,0x97}, {0x68,0x01}, + {0x69,0xCD}, {0x6A,0x01}, {0x6B,0xB0}, {0x6C,0x04}, {0x6D,0x2C}, {0x6E,0x01}, {0x6F,0x32}, {0x71,0x00}, + {0x72,0x01}, {0x73,0x35}, {0x74,0x00}, {0x75,0x33}, {0x76,0x31}, {0x77,0x01}, {0x7C,0x84}, {0x7D,0x03}, + {0x7E,0x01}, + {0xEF,0x00} +}; + + + + + +const char kPaj7620Directions[] PROGMEM = "Down|Up|Right|Left|Near|Far|CW|CCW"; + +const uint8_t PAJ7620_PIN[]= {1,2,3,4}; + + + + + +char PAJ7620_name[] = "PAJ7620"; + +uint32_t PAJ7620_timeout_counter = 10; +uint32_t PAJ7620_next_job = 0; +uint32_t PAJ7620_mode = 1; + +struct { + uint8_t current; + uint8_t last; + uint8_t same; + uint8_t unfinished; +} PAJ7620_gesture; + +bool PAJ7620_finished_gesture = false; +char PAJ7620_currentGestureName[6]; + +struct{ + uint8_t x; + uint8_t y; + uint8_t last_x; + uint8_t last_y; + uint8_t proximity; + uint8_t last_proximity; + uint8_t corner; + struct { + uint8_t step:3; + uint8_t countdown:3; + uint8_t valid:1; + } PIN; +} PAJ7620_state; + + + + + +void PAJ7620SelectBank(uint8_t bank) +{ + I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, bank &1, 1); +} + + + +void PAJ7620DecodeGesture(void) +{ + uint32_t index = 0; + switch (PAJ7620_gesture.current) { + case PAJ7620_LEFT: + index++; + case PAJ7620_RIGHT: + index++; + case PAJ7620_UP: + index++; + case PAJ7620_DOWN: + if (PAJ7620_gesture.unfinished) { + PAJ7620_finished_gesture = true; + break; + } + PAJ7620_gesture.unfinished = PAJ7620_gesture.current; + PAJ7620_timeout_counter = 5; + break; + case PAJ7620_NEAR: + index = 4; + PAJ7620_finished_gesture = true; + PAJ7620_timeout_counter = 25; + break; + case PAJ7620_FAR: + index = 5; + PAJ7620_finished_gesture = true; + PAJ7620_timeout_counter = 25; + break; + case PAJ7620_CW: + index = 6; + PAJ7620_finished_gesture = true; + break; + case PAJ7620_CCW: + index = 7; + PAJ7620_finished_gesture = true; + break; + default: + index = 8; + if (PAJ7620_gesture.unfinished) { + PAJ7620_finished_gesture = true; + } + break; + } + if (index < 8) { + GetTextIndexed(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), index, kPaj7620Directions); + } + + if (PAJ7620_finished_gesture) { + if (PAJ7620_gesture.unfinished) { + if ((PAJ7620_gesture.current != PAJ7620_NEAR) && (PAJ7620_gesture.current != PAJ7620_FAR)) { + PAJ7620_gesture.current = PAJ7620_gesture.unfinished; + } + } + if (PAJ7620_gesture.current == PAJ7620_gesture.last) { + PAJ7620_gesture.same++; + } else { + PAJ7620_gesture.same = 1; + } + PAJ7620_gesture.last = PAJ7620_gesture.current; + PAJ7620_finished_gesture = false; + PAJ7620_gesture.unfinished = 0; + PAJ7620_timeout_counter += 3; + MqttPublishSensor(); + } +} + + + +void PAJ7620ReadGesture(void) +{ + switch (PAJ7620_mode) { + case 1: + PAJ7620_gesture.current = I2cRead8(PAJ7620_ADDR,PAJ7620_GET_GESTURE); + if ((PAJ7620_gesture.current > 0) || PAJ7620_gesture.unfinished) { + DEBUG_SENSOR_LOG(PSTR("PAJ: gesture: %u"), PAJ7620_gesture.current); + PAJ7620DecodeGesture(); + } + break; + case 2: + PAJ7620_state.proximity = I2cRead8(PAJ7620_ADDR, PAJ7620_PROXIMITY_AVG_Y); + if ((PAJ7620_state.proximity > 0) || (PAJ7620_state.last_proximity > 0)) { + if (PAJ7620_state.proximity != PAJ7620_state.last_proximity) { + PAJ7620_state.last_proximity = PAJ7620_state.proximity; + DEBUG_SENSOR_LOG(PSTR("PAJ: Proximity: %u"), PAJ7620_state.proximity); + MqttPublishSensor(); + } + } + break; + case 3: + case 4: + case 5: + PAJ7620_state.x = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_X); + PAJ7620_state.y = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_Y); + if ((PAJ7620_state.y > 0) && (PAJ7620_state.x > 0)) { + if ((PAJ7620_state.y != PAJ7620_state.last_y) || (PAJ7620_state.x != PAJ7620_state.last_x)) { + PAJ7620_state.last_y = PAJ7620_state.y; + PAJ7620_state.last_x = PAJ7620_state.x; + DEBUG_SENSOR_LOG(PSTR("PAJ: x: %u y: %u"), PAJ7620_state.x, PAJ7620_state.y); + + PAJ7620_state.corner = 0; + + + + switch (PAJ7620_state.y) { + case 0: case 1: case 2: case 3: case 4: case 5: + PAJ7620_state.corner = 3; + break; + case 9: case 10: case 11: case 12: case 13: case 14: + PAJ7620_state.corner = 1; + break; + } + if (PAJ7620_state.corner != 0) { + switch (PAJ7620_state.x) { + case 0: case 1: case 2: case 3: case 4: case 5: + break; + case 9: case 10: case 11: case 12: case 13: case 14: + PAJ7620_state.corner++; + break; + default: + PAJ7620_state.corner = 0; + break; + } + } + DEBUG_SENSOR_LOG(PSTR("PAJ: corner: %u"), PAJ7620_state.corner); + + if (PAJ7620_state.PIN.countdown == 0) { + PAJ7620_state.PIN.step = 0; + PAJ7620_state.PIN.valid = 0; + } + if (!PAJ7620_state.PIN.step) { + if (PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]) { + PAJ7620_state.PIN.step = 1; + PAJ7620_state.PIN.countdown = 7; + } + } else { + if (PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]) { + PAJ7620_state.PIN.step += 1; + PAJ7620_state.PIN.countdown = 7; + } else { + PAJ7620_state.PIN.countdown -= 1; + } + } + if (PAJ7620_state.PIN.step == 4) { + PAJ7620_state.PIN.valid = 1; + DEBUG_SENSOR_LOG(PSTR("PAJ: PIN valid!!")); + PAJ7620_state.PIN.countdown = 0; + } + MqttPublishSensor(); + } + } + break; + } +} + + + +void PAJ7620Detect(void) +{ + if (I2cActive(PAJ7620_ADDR)) { return; } + + PAJ7620SelectBank(0); + PAJ7620SelectBank(0); + uint16_t PAJ7620_id = I2cRead16LE(PAJ7620_ADDR,0); + uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); + if (0x7620 == PAJ7620_id) { + I2cSetActiveFound(PAJ7620_ADDR, PAJ7620_name); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ: ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); + PAJ7620_next_job = 1; + } + else { + DEBUG_SENSOR_LOG(PSTR("PAJ: sensor not found, false ID 0x%x"), PAJ7620_id); + } +} + + + +void PAJ7620Init(void) +{ + DEBUG_SENSOR_LOG(PSTR("PAJ: init sensor start %u"),millis()); + union{ + uint32_t raw; + uint8_t reg_val[4]; + } buf; + + for (uint32_t i = 0; i < (sizeof(PAJ7620initRegisterArray) / 2); i += 2) + { + buf.raw = pgm_read_dword(PAJ7620initRegisterArray + i); + DEBUG_SENSOR_LOG("PAJ: %x %x %x %x",buf.reg_val[0],buf.reg_val[1],buf.reg_val[2],buf.reg_val[3]); + I2cWrite(PAJ7620_ADDR, buf.reg_val[0], buf.reg_val[1], 1); + I2cWrite(PAJ7620_ADDR, buf.reg_val[2], buf.reg_val[3], 1); + } + DEBUG_SENSOR_LOG(PSTR("PAJ: init sensor done %u"),millis()); + PAJ7620_next_job = 2; +} + + + +void PAJ7620Loop(void) +{ + if (0 == PAJ7620_timeout_counter) { + switch (PAJ7620_next_job) { + case 1: + PAJ7620Init(); + break; + case 2: + if (PAJ7620_mode != 0) { + PAJ7620ReadGesture(); + } + break; + } + } else { + PAJ7620_timeout_counter--; + } +} + + + +void PAJ7620Show(bool json) +{ + if (json) { + if (PAJ7620_currentGestureName[0] != '\0' ) { + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), PAJ7620_name, PAJ7620_currentGestureName, PAJ7620_gesture.same); + PAJ7620_currentGestureName[0] = '\0'; + return; + } + switch (PAJ7620_mode) { + case 2: + ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), PAJ7620_name, PAJ7620_state.proximity); + break; + case 3: + if (PAJ7620_state.corner > 0) { + ResponseAppend_P(PSTR(",\"%s\":{\"Corner\":%u}"), PAJ7620_name, PAJ7620_state.corner); + } + break; + case 4: + if (PAJ7620_state.PIN.valid) { + ResponseAppend_P(PSTR(",\"%s\":{\"PIN\":%u}"), PAJ7620_name, 1); + PAJ7620_state.PIN.valid = 0; + } + break; + case 5: + ResponseAppend_P(PSTR(",\"%s\":{\"x\":%u,\"y\":%u}"), PAJ7620_name, PAJ7620_state.x, PAJ7620_state.y); + break; + } + } +} +# 411 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_50_paj7620.ino" +bool PAJ7620CommandSensor(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { + PAJ7620_mode = XdrvMailbox.payload; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_50, PAJ7620_mode); + + return true; +} + + + + + +bool Xsns50(uint8_t function) +{ + if (!I2cEnabled(XI2C_34)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + PAJ7620Detect(); + } + else if (PAJ7620_next_job) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_50 == XdrvMailbox.index){ + result = PAJ7620CommandSensor(); + } + break; + case FUNC_EVERY_100_MSECOND: + PAJ7620Loop(); + break; + case FUNC_JSON_APPEND: + PAJ7620Show(1); + break; + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_51_rdm6300.ino" +# 21 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_51_rdm6300.ino" +#ifdef USE_RDM6300 + +#define XSNS_51 51 + +#define RDM6300_BAUDRATE 9600 + +#include + +#define RDM_TIMEOUT 100 +char rdm_uid_str[10]; + + +#define RDM6300_BLOCK 2*10 + +uint8_t rdm_blcnt; +TasmotaSerial *RDM6300_Serial = nullptr; + +void RDM6300_Init() { + if (pin[GPIO_RDM6300_RX] < 99) { + RDM6300_Serial = new TasmotaSerial(pin[GPIO_RDM6300_RX],-1,1); + if (RDM6300_Serial->begin(RDM6300_BAUDRATE)) { + if (RDM6300_Serial->hardwareSerial()) { + ClaimSerial(); + } + } + } + rdm_blcnt=0; +} + + +void RDM6300_ScanForTag() { + char rdm_buffer[14]; + uint8_t rdm_index; + uint8_t rdm_array[6]; + + if (!RDM6300_Serial) return; + + if (rdm_blcnt>0) { + rdm_blcnt--; + while (RDM6300_Serial->available()) RDM6300_Serial->read(); + return; + } + + if (RDM6300_Serial->available()) { + + char c=RDM6300_Serial->read(); + if (c!=2) return; + + + rdm_index=0; + uint32_t cmillis=millis(); + while (1) { + if (RDM6300_Serial->available()) { + char c=RDM6300_Serial->read(); + if (c==3) { + + break; + } + rdm_buffer[rdm_index++]=c; + if (rdm_index>13) { + + return; + } + } + if ((millis()-cmillis)>RDM_TIMEOUT) { + + return; + } + } + + + rdm_blcnt=RDM6300_BLOCK; + + + rm6300_hstring_to_array(rdm_array,sizeof(rdm_array),rdm_buffer); + uint8_t accu=0; + for (uint8_t count=0;count<5;count++) { + accu^=rdm_array[count]; + } + if (accu!=rdm_array[5]) { + + return; + } + + + memcpy(rdm_uid_str,&rdm_buffer[2],8); + rdm_uid_str[9]=0; + + ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); + MqttPublishTeleSensor(); + + + + + + } + + +} + +uint8_t rm6300_hexnibble(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { + rVal = chr - '0'; + } else { + if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; + } + return rVal; +} + + +void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]) +{ + char *cp=buffer; + for (uint8_t i = 0; i < len; i++) { + uint8_t val = rm6300_hexnibble(*cp++) << 4; + array[i]= val | rm6300_hexnibble(*cp++); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_RDM6300[] PROGMEM = + "{s}RDM6300 " "UID" "{m}%s" "{e}"; + +void RDM6300_Show(void) { + if (!RDM6300_Serial) return; + if (!rdm_uid_str[0]) strcpy(rdm_uid_str,"????"); + WSContentSend_PD(HTTP_RDM6300,rdm_uid_str); +} +#endif + + + + + +bool Xsns51(byte function) +{ + bool result = false; + + switch (function) { + case FUNC_INIT: + RDM6300_Init(); + break; + case FUNC_EVERY_100_MSECOND: + RDM6300_ScanForTag(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + RDM6300_Show(); + break; +#endif + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_52_ibeacon.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_52_ibeacon.ino" +#ifdef USE_IBEACON + + + +#define XSNS_52 52 + +#include + +#define HM17_BAUDRATE 9600 + +#define IBEACON_DEBUG + + +#define HM17_V110 + + + +#define IB_TIMEOUT_INTERVAL 30 + +#define IB_UPDATE_TIME_INTERVAL 10 + +TasmotaSerial *IBEACON_Serial = nullptr; + + +uint8_t hm17_found,hm17_cmd,hm17_flag; + +#ifdef IBEACON_DEBUG +uint8_t hm17_debug=0; +#endif + + + +#define HM17_BSIZ 128 +char hm17_sbuffer[HM17_BSIZ]; +uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting; +uint32_t hm17_lastms; +char ib_mac[14]; + + +#if 1 +uint8_t ib_upd_interval,ib_tout_interval; +#define IB_UPDATE_TIME ib_upd_interval +#define IB_TIMEOUT_TIME ib_tout_interval +#else +#undef IB_UPDATE_TIME +#undef IB_TIMEOUT_TIME +#define IB_UPDATE_TIME Settings.ib_upd_interval +#define IB_TIMEOUT_TIME Settings.ib_tout_interval +#endif + +enum {HM17_TEST,HM17_ROLE,HM17_IMME,HM17_DISI,HM17_IBEA,HM17_SCAN,HM17_DISC,HM17_RESET,HM17_RENEW,HM17_CON}; +#define HM17_SUCESS 99 + +struct IBEACON { + char FACID[8]; + char UID[32]; + char MAJOR[4]; + char MINOR[4]; + char PWR[2]; + char MAC[12]; + char RSSI[4]; +}; + +#define MAX_IBEACONS 16 + +struct IBEACON_UID { + char MAC[12]; + char RSSI[4]; + uint8_t FLAGS; + uint8_t TIME; +} ibeacons[MAX_IBEACONS]; + + +void IBEACON_Init() { + + hm17_found=0; + + + if ((pin[GPIO_IBEACON_RX] < 99) && (pin[GPIO_IBEACON_TX] < 99)) { + IBEACON_Serial = new TasmotaSerial(pin[GPIO_IBEACON_RX], pin[GPIO_IBEACON_TX],1); + if (IBEACON_Serial->begin(HM17_BAUDRATE)) { + if (IBEACON_Serial->hardwareSerial()) { + ClaimSerial(); + } + hm17_sendcmd(HM17_TEST); + hm17_lastms=millis(); + + IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; + IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; + } + } +} + +void hm17_every_second(void) { + if (!IBEACON_Serial) return; + + if (hm17_found) { + if (IB_UPDATE_TIME && (uptime%IB_UPDATE_TIME==0)) { + if (hm17_cmd!=99) { + if (hm17_flag&2) { + ib_sendbeep(); + } else { + if (!hm17_connecting) { + hm17_sendcmd(HM17_DISI); + } + } + } + } + for (uint32_t cnt=0;cntIB_TIMEOUT_TIME) { + ibeacons[cnt].FLAGS=0; + ibeacon_mqtt(ibeacons[cnt].MAC,"0000"); + } + } + } + } else { + if (uptime%20==0) { + hm17_sendcmd(HM17_TEST); + } + } +} + +void hm17_sbclr(void) { + memset(hm17_sbuffer,0,HM17_BSIZ); + hm17_sindex=0; + IBEACON_Serial->flush(); +} + +void hm17_sendcmd(uint8_t cmd) { + hm17_sbclr(); + hm17_cmd=cmd; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("hm17cmd %d"),cmd); +#endif + switch (cmd) { + case HM17_TEST: + IBEACON_Serial->write("AT"); + break; + case HM17_ROLE: + IBEACON_Serial->write("AT+ROLE1"); + break; + case HM17_IMME: + IBEACON_Serial->write("AT+IMME1"); + break; + case HM17_DISI: + IBEACON_Serial->write("AT+DISI?"); + hm17_scanning=1; + break; + case HM17_IBEA: + IBEACON_Serial->write("AT+IBEA1"); + break; + case HM17_RESET: + IBEACON_Serial->write("AT+RESET"); + break; + case HM17_RENEW: + IBEACON_Serial->write("AT+RENEW"); + break; + case HM17_SCAN: + IBEACON_Serial->write("AT+SCAN5"); + break; + case HM17_DISC: + IBEACON_Serial->write("AT+DISC?"); + hm17_scanning=1; + break; + case HM17_CON: + IBEACON_Serial->write((const uint8_t*)"AT+CON",6); + IBEACON_Serial->write((const uint8_t*)ib_mac,12); + hm17_connecting=1; + break; + } +} + +uint32_t ibeacon_add(struct IBEACON *ib) { + + if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { + for (uint32_t cnt=0;cntMAC,12)) { + + memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); + ibeacons[cnt].TIME=0; + return 1; + } + } + } + for (uint32_t cnt=0;cntMAC,12); + memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); + ibeacons[cnt].FLAGS=1; + ibeacons[cnt].TIME=0; + return 1; + } + } + } + return 0; +} + +void hm17_decode(void) { + struct IBEACON ib; + switch (hm17_cmd) { + case HM17_TEST: + if (!strncmp(hm17_sbuffer,"OK",2)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("AT OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + hm17_found=1; + } + break; + case HM17_ROLE: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("ROLE OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_IMME: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IMME OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_IBEA: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IBEA OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_SCAN: + if (!strncmp(hm17_sbuffer,"OK+Set:5",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("SCAN OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_RESET: + if (!strncmp(hm17_sbuffer,"OK+RESET",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RESET OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_RENEW: + if (!strncmp(hm17_sbuffer,"OK+RENEW",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RENEW OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_CON: + if (!strncmp(hm17_sbuffer,"OK+CONNA",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNA OK")); +#endif + hm17_connecting=2; + break; + } + if (!strncmp(hm17_sbuffer,"OK+CONNE",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNE ERROR")); +#endif + break; + } + if (!strncmp(hm17_sbuffer,"OK+CONNF",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNF ERROR")); +#endif + break; + } + if (hm17_connecting==2 && !strncmp(hm17_sbuffer,"OK+CONN",7)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONN OK")); +#endif + hm17_connecting=3; + hm17_sendcmd(HM17_TEST); + hm17_connecting=0; + break; + } + break; + + case HM17_DISI: + case HM17_DISC: + if (!strncmp(hm17_sbuffer,"OK+DISCS",8)) { + hm17_sbclr(); + hm17_result=1; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCS OK")); +#endif + break; + } + if (!strncmp(hm17_sbuffer,"OK+DISIS",8)) { + hm17_sbclr(); + hm17_result=1; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISIS OK")); +#endif + break; + } + if (!strncmp(hm17_sbuffer,"OK+DISCE",8)) { + hm17_sbclr(); + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCE OK")); +#endif + hm17_scanning=0; + break; + } + if (!strncmp(hm17_sbuffer,"OK+NAME:",8)) { + if (hm17_sbuffer[hm17_sindex-1]=='\n') { + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("NAME OK")); + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + hm17_sbclr(); + } + break; + } + if (!strncmp(hm17_sbuffer,"OK+DIS0:",8)) { + if (hm17_cmd==HM17_DISI) { +#ifdef HM17_V110 + goto hm17_v110; +#endif + } else { + if (hm17_sindex==20) { + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("DIS0 OK")); + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + hm17_sbclr(); + } + } + break; + } + if (!strncmp(hm17_sbuffer,"OK+DISC:",8)) { +hm17_v110: + if (hm17_cmd==HM17_DISI) { + if (hm17_sindex==78) { +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("DISC: OK")); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + memcpy(ib.FACID,&hm17_sbuffer[8],8); + memcpy(ib.UID,&hm17_sbuffer[8+8+1],32); + memcpy(ib.MAJOR,&hm17_sbuffer[8+8+1+32+1],4); + memcpy(ib.MINOR,&hm17_sbuffer[8+8+1+32+1+4],4); + memcpy(ib.PWR,&hm17_sbuffer[8+8+1+32+1+4+4],2); + memcpy(ib.MAC,&hm17_sbuffer[8+8+1+32+1+4+4+2+1],12); + memcpy(ib.RSSI,&hm17_sbuffer[8+8+1+32+1+4+4+2+1+12+1],4); + + if (ibeacon_add(&ib)) { + ibeacon_mqtt(ib.MAC,ib.RSSI); + } + hm17_sbclr(); + hm17_result=1; + } + } else { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); +#endif + } + break; + } + } +} + +void IBEACON_loop() { + + if (!IBEACON_Serial) return; + +uint32_t difftime=millis()-hm17_lastms; + + while (IBEACON_Serial->available()) { + hm17_lastms=millis(); + + if (hm17_sindexread(); + hm17_sindex++; + hm17_decode(); + } else { + hm17_sindex=0; + break; + } + } + + if (hm17_cmd==99) { + if (hm17_sindex>=HM17_BSIZ-2 || (hm17_sindex && (difftime>100))) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),hm17_sbuffer); + hm17_sbclr(); + } + } + +} + +#ifdef USE_WEBSERVER +const char HTTP_IBEACON[] PROGMEM = + "{s}IBEACON-UID : %s" " - RSSI : %s" "{m}{e}"; + +void IBEACON_Show(void) { +char mac[14]; +char rssi[6]; + + for (uint32_t cnt=0;cnt 0) { + char *cp=XdrvMailbox.data; + if (*cp>='0' && *cp<='8') { + hm17_sendcmd(*cp&7); + Response_P(S_JSON_IBEACON, XSNS_52,"hm17cmd",*cp&7); + } else if (*cp=='s') { + cp++; + len--; + while (*cp==' ') { + len--; + cp++; + } + IBEACON_Serial->write((uint8_t*)cp,len); + hm17_cmd=99; + Response_P(S_JSON_IBEACON1, XSNS_52,"hm17cmd",cp); + } else if (*cp=='u') { + cp++; + if (*cp) IB_UPDATE_TIME=atoi(cp); + Response_P(S_JSON_IBEACON, XSNS_52,"uintv",IB_UPDATE_TIME); + } else if (*cp=='t') { + cp++; + if (*cp) IB_TIMEOUT_TIME=atoi(cp); + Response_P(S_JSON_IBEACON, XSNS_52,"lintv",IB_TIMEOUT_TIME); + } else if (*cp=='c') { + for (uint32_t cnt=0;cnt + + +#define SPECIAL_SS + + + + + +#if MY_LANGUAGE==de-DE + +#define D_TPWRIN "Verbrauch" +#define D_TPWROUT "Einspeisung" +#define D_TPWRCURR "Aktueller Verbrauch" +#define D_TPWRCURR1 "Verbrauch P1" +#define D_TPWRCURR2 "Verbrauch P2" +#define D_TPWRCURR3 "Verbrauch P3" +#define D_Strom_L1 "Strom L1" +#define D_Strom_L2 "Strom L2" +#define D_Strom_L3 "Strom L3" +#define D_Spannung_L1 "Spannung L1" +#define D_Spannung_L2 "Spannung L2" +#define D_Spannung_L3 "Spannung L3" +#define D_METERNR "Zähler Nr" +#define D_METERSID "Service ID" +#define D_GasIN "Zählerstand" +#define D_H2oIN "Zählerstand" +#define D_StL1L2L3 "Ströme L1+L2+L3" +#define D_SpL1L2L3 "Spannung L1+L2+L3/3" + +#else + +#undef D_TPWRIN +#undef D_TPWROUT +#undef D_TPWRCURR +#undef D_TPWRCURR1 +#undef D_TPWRCURR2 +#undef D_TPWRCURR3 +#undef D_Strom_L1 +#undef D_Strom_L2 +#undef D_Strom_L3 +#undef D_Spannung_L1 +#undef D_Spannung_L2 +#undef D_Spannung_L3 +#undef D_METERNR +#undef D_METERSID +#undef D_GasIN +#undef D_H2oIN +#undef D_StL1L2L3 +#undef D_SpL1L2L3 + +#define D_TPWRIN "Total-In" +#define D_TPWROUT "Total-Out" +#define D_TPWRCURR "Current-In/Out" +#define D_TPWRCURR1 "Current-In p1" +#define D_TPWRCURR2 "Current-In p2" +#define D_TPWRCURR3 "Current-In p3" +#define D_Strom_L1 "Current L1" +#define D_Strom_L2 "Current L2" +#define D_Strom_L3 "Current L3" +#define D_Spannung_L1 "Voltage L1" +#define D_Spannung_L2 "Voltage L2" +#define D_Spannung_L3 "Voltage L3" +#define D_METERNR "Meter_number" +#define D_METERSID "Service ID" +#define D_GasIN "Counter" +#define D_H2oIN "Counter" +#define D_StL1L2L3 "Current L1+L2+L3" +#define D_SpL1L2L3 "Voltage L1+L2+L3/3" + +#endif + + + +#define DJ_TPWRIN "Total_in" +#define DJ_TPWROUT "Total_out" +#define DJ_TPWRCURR "Power_curr" +#define DJ_TPWRCURR1 "Power_p1" +#define DJ_TPWRCURR2 "Power_p2" +#define DJ_TPWRCURR3 "Power_p3" +#define DJ_CURR1 "Curr_p1" +#define DJ_CURR2 "Curr_p2" +#define DJ_CURR3 "Curr_p3" +#define DJ_VOLT1 "Volt_p1" +#define DJ_VOLT2 "Volt_p2" +#define DJ_VOLT3 "Volt_p3" +#define DJ_METERNR "Meter_number" +#define DJ_METERSID "Meter_id" +#define DJ_CSUM "Curr_summ" +#define DJ_VAVG "Volt_avg" +#define DJ_COUNTER "Count" + +struct METER_DESC { + uint8_t srcpin; + uint8_t type; + uint16_t flag; + int32_t params; + char prefix[8]; + int8_t trxpin; + uint8_t tsecs; + char *txmem; + uint8_t index; + uint8_t max_index; +}; + + + + + + +#define EHZ161_0 1 +#define EHZ161_1 2 +#define EHZ363 3 +#define EHZH 4 +#define EDL300 5 +#define Q3B 6 +#define COMBO3 7 +#define COMBO2 8 +#define COMBO3a 9 +#define Q3B_V1 10 +#define EHZ363_2 11 +#define COMBO3b 12 +#define WGS_COMBO 13 +#define EBZD_G 14 + + +#define METER EHZ161_1 + + +#if METER==EHZ161_0 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" +"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" +"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" +"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + + + +#if METER==EHZ161_1 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZ363 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZH +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + + + +#if METER==EDL300 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + +#if METER==EBZD_G +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"strom",-1,1,0}}; +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" + +"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100600100ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + + +#if METER==Q3B +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + +#if METER==COMBO3 + +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, + [1]={14,'s',0,SML_BAUDRATE,"SML",-1,1,0}, + [2]={4,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; + + +const uint8_t meter[]= +"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" +"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" +"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" +"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"2,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"3,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + +#if METER==COMBO2 + +#undef METERS_USED +#define METERS_USED 2 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, + [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; + + +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" + +"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + +#if METER==COMBO3a +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, + [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}, + [2]={1,'o',0,SML_BAUDRATE,"OBIS3",-1,1,0}}; + + +const uint8_t meter[]= +"1,=h --- Zähler Nr 1 ---|" +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"2,=h --- Zähler Nr 2 ---|" +"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"3,=h --- Zähler Nr 3 ---|" +"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"3,=d 10 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + + + +#if METER==Q3B_V1 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ +[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZ363_2 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ +[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" + +"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + +#if METER==COMBO3b +#undef METERS_USED +#define METERS_USED 3 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, + [1]={14,'c',0,50,"Gas"}, + [2]={1,'c',0,10,"Wasser"}}; + + +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" + + +"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",2|" + +"3,1-0:1.8.0*255(@100," D_H2oIN ",cbm," DJ_COUNTER ",2"; +#endif + + +#if METER==WGS_COMBO +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={1,'c',0,10,"H20",-1,1,0}, + [1]={4,'c',0,50,"GAS",-1,1,0}, + [2]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + + +"1,1-0:1.8.0*255(@10000," D_H2oIN ",cbm," DJ_COUNTER ",4|" + + +"2,=h==================|" +"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",3|" + +"3,=h==================|" + +"3,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",3|" +"3,=h==================|" + +"3,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",2|" +"3,=h -------------------------------|" +"3,=m 10+11+12 @100," D_StL1L2L3 ",A," DJ_CSUM ",2|" + +"3,=m 13+14+15/#3 @100," D_SpL1L2L3 ",V," DJ_VAVG ",2|" +"3,=h==================|" + +"3,77070100240700ff@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",2|" + +"3,77070100380700ff@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",2|" + +"3,770701004c0700ff@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",2|" +"3,=h -------------------------------|" + +"3,770701001f0700ff@100," D_Strom_L1 ",A," DJ_CURR1 ",2|" + +"3,77070100330700ff@100," D_Strom_L2 ",A," DJ_CURR2 ",2|" + +"3,77070100470700ff@100," D_Strom_L3 ",A," DJ_CURR3 ",2|" +"3,=h -------------------------------|" + +"3,77070100200700ff@100," D_Spannung_L1 ",V," DJ_VOLT1 ",2|" + +"3,77070100340700ff@100," D_Spannung_L2 ",V," DJ_VOLT2 ",2|" + +"3,77070100480700ff@100," D_Spannung_L3 ",V," DJ_VOLT3 ",2|" +"3,=h==================|" + +"3,77070100000009ff@#," D_METERSID ",," DJ_METERSID ",0|" +"3,=h--------------------------------"; +#endif +# 499 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_53_sml.ino" +#define USE_SML_MEDIAN_FILTER + + +#ifndef SML_MAX_VARS +#define SML_MAX_VARS 20 +#endif + + +#define MAX_METERS 5 +double meter_vars[SML_MAX_VARS]; + +#define MAX_DVARS MAX_METERS*2 +double dvalues[MAX_DVARS]; +uint32_t dtimes[MAX_DVARS]; +uint8_t meters_used; + +struct METER_DESC const *meter_desc_p; +const uint8_t *meter_p; +uint8_t meter_spos[MAX_METERS]; + + +TasmotaSerial *meter_ss[MAX_METERS]; + + +#define SML_BSIZ 48 +uint8_t smltbuf[MAX_METERS][SML_BSIZ]; + + +#define METER_ID_SIZE 24 +char meter_id[MAX_METERS][METER_ID_SIZE]; + +#define EBUS_SYNC 0xaa +#define EBUS_ESC 0xa9 + +uint8_t sml_send_blocks; +uint8_t sml_100ms_cnt; +uint8_t sml_desc_cnt; + +#ifdef USE_SML_MEDIAN_FILTER + +#define MEDIAN_SIZE 5 +struct SML_MEDIAN_FILTER { +double buffer[MEDIAN_SIZE]; +int8_t index; +} sml_mf[SML_MAX_VARS]; + +#ifndef FLT_MAX +#define FLT_MAX 99999999 +#endif + +double sml_median_array(double *array,uint8_t len) { + uint8_t ind[len]; + uint8_t mind=0,index=0,flg; + double min=FLT_MAX; + + for (uint8_t hcnt=0; hcntbuffer[mf->index]=in; + mf->index++; + if (mf->index>=MEDIAN_SIZE) mf->index=0; + + return sml_median_array(mf->buffer,MEDIAN_SIZE); +# 603 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_53_sml.ino" +} +#endif + +#ifdef ANALOG_OPTO_SENSOR + +uint8_t ads1115_up; + + +#define SAMPLE_BIT (0x8000) + +#define ADS1115_COMP_QUEUE_SHIFT 0 +#define ADS1115_COMP_LATCH_SHIFT 2 +#define ADS1115_COMP_POLARITY_SHIFT 3 +#define ADS1115_COMP_MODE_SHIFT 4 +#define ADS1115_DATA_RATE_SHIFT 5 +#define ADS1115_MODE_SHIFT 8 +#define ADS1115_PGA_SHIFT 9 +#define ADS1115_MUX_SHIFT 12 + +enum ads1115_comp_queue { + ADS1115_COMP_QUEUE_AFTER_ONE = 0, + ADS1115_COMP_QUEUE_AFTER_TWO = 0x1 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_AFTER_FOUR = 0x2 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_DISABLE = 0x3 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_MASK = 0x3 << ADS1115_COMP_QUEUE_SHIFT, +}; + +enum ads1115_comp_latch { + ADS1115_COMP_LATCH_NO = 0, + ADS1115_COMP_LATCH_YES = 1 << ADS1115_COMP_LATCH_SHIFT, + ADS1115_COMP_LATCH_MASK = 1 << ADS1115_COMP_LATCH_SHIFT, +}; + +enum ads1115_comp_polarity { + ADS1115_COMP_POLARITY_ACTIVE_LOW = 0, + ADS1115_COMP_POLARITY_ACTIVE_HIGH = 1 << ADS1115_COMP_POLARITY_SHIFT, + ADS1115_COMP_POLARITY_MASK = 1 << ADS1115_COMP_POLARITY_SHIFT, +}; + +enum ads1115_comp_mode { + ADS1115_COMP_MODE_WINDOW = 0, + ADS1115_COMP_MODE_HYSTERESIS = 1 << ADS1115_COMP_MODE_SHIFT, + ADS1115_COMP_MODE_MASK = 1 << ADS1115_COMP_MODE_SHIFT, +}; + +enum ads1115_data_rate { + ADS1115_DATA_RATE_8_SPS = 0, + ADS1115_DATA_RATE_16_SPS = 0x1 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_32_SPS = 0x2 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_64_SPS = 0x3 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_128_SPS = 0x4 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_250_SPS = 0x5 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_475_SPS = 0x6 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_860_SPS = 0x7 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_MASK = 0x7 << ADS1115_DATA_RATE_SHIFT, +}; + +enum ads1115_mode { + ADS1115_MODE_CONTINUOUS = 0, + ADS1115_MODE_SINGLE_SHOT = 1 << ADS1115_MODE_SHIFT, + ADS1115_MODE_MASK = 1 << ADS1115_MODE_SHIFT, +}; + +enum ads1115_pga { + ADS1115_PGA_TWO_THIRDS = 0, + ADS1115_PGA_ONE = 0x1 << ADS1115_PGA_SHIFT, + ADS1115_PGA_TWO = 0x2 << ADS1115_PGA_SHIFT, + ADS1115_PGA_FOUR = 0x3 << ADS1115_PGA_SHIFT, + ADS1115_PGA_EIGHT = 0x4 << ADS1115_PGA_SHIFT, + ADS1115_PGA_SIXTEEN = 0x5 << ADS1115_PGA_SHIFT, + ADS1115_PGA_MASK = 0x7 << ADS1115_PGA_SHIFT, +}; + + +enum ads1115_mux { + ADS1115_MUX_DIFF_AIN0_AIN1 = 0, + ADS1115_MUX_DIFF_AIN0_AIN3 = 0x1 << ADS1115_MUX_SHIFT, + ADS1115_MUX_DIFF_AIN1_AIN3 = 0x2 << ADS1115_MUX_SHIFT, + ADS1115_MUX_DIFF_AIN2_AIN3 = 0x3 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN0 = 0x4 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN1 = 0x5 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN2 = 0x6 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN3 = 0x7 << ADS1115_MUX_SHIFT, + ADS1115_MUX_MASK = 0x7 << ADS1115_MUX_SHIFT, +}; + +class ADS1115 { +public: + ADS1115(uint8_t address = 0x48); + + void begin(); + uint8_t trigger_sample(); + uint8_t reset(); + bool is_sample_in_progress(); + int16_t read_sample(); + float sample_to_float(int16_t val); + float read_sample_float(); + + void set_comp_queue(enum ads1115_comp_queue val) { set_config(val, ADS1115_COMP_QUEUE_MASK); } + void set_comp_latching(enum ads1115_comp_latch val) { set_config(val, ADS1115_COMP_LATCH_MASK); } + void set_comp_polarity(enum ads1115_comp_polarity val) { set_config(val, ADS1115_COMP_POLARITY_MASK); } + void set_comp_mode(enum ads1115_comp_mode val) { set_config(val, ADS1115_COMP_MODE_MASK); } + void set_data_rate(enum ads1115_data_rate val) { set_config(val, ADS1115_DATA_RATE_MASK); } + void set_mode(enum ads1115_mode val) { set_config(val, ADS1115_MODE_MASK); } + void set_pga(enum ads1115_pga val) { set_config(val, ADS1115_PGA_MASK); m_voltage_range = val >> ADS1115_PGA_SHIFT; } + void set_mux(enum ads1115_mux val) { set_config(val, ADS1115_MUX_MASK); } + +private: + void set_config(uint16_t val, uint16_t mask) { + m_config = (m_config & ~mask) | val; + } + + uint8_t write_register(uint8_t reg, uint16_t val); + uint16_t read_register(uint8_t reg); + + uint8_t m_address; + uint16_t m_config; + int m_voltage_range; +}; + + +enum ads1115_register { + ADS1115_REGISTER_CONVERSION = 0, + ADS1115_REGISTER_CONFIG = 1, + ADS1115_REGISTER_LOW_THRESH = 2, + ADS1115_REGISTER_HIGH_THRESH = 3, +}; + +#define FACTOR 32768.0 +static float ranges[] = { 6.144 / FACTOR, 4.096 / FACTOR, 2.048 / FACTOR, 1.024 / FACTOR, 0.512 / FACTOR, 0.256 / FACTOR}; + +ADS1115::ADS1115(uint8_t address) +{ + m_address = address; + m_config = ADS1115_COMP_QUEUE_AFTER_ONE | + ADS1115_COMP_LATCH_NO | + ADS1115_COMP_POLARITY_ACTIVE_LOW | + ADS1115_COMP_MODE_WINDOW | + ADS1115_DATA_RATE_128_SPS | + ADS1115_MODE_SINGLE_SHOT | + ADS1115_MUX_GND_AIN0; + set_pga(ADS1115_PGA_ONE); +} + +uint8_t ADS1115::write_register(uint8_t reg, uint16_t val) +{ + Wire.beginTransmission(m_address); + Wire.write(reg); + Wire.write(val>>8); + Wire.write(val & 0xFF); + return Wire.endTransmission(); +} + +uint16_t ADS1115::read_register(uint8_t reg) +{ + Wire.beginTransmission(m_address); + Wire.write(reg); + Wire.endTransmission(); + + uint8_t result = Wire.requestFrom((int)m_address, 2, 1); + if (result != 2) { + return 0; + } + + uint16_t val; + + val = Wire.read() << 8; + val |= Wire.read(); + return val; +} + +void ADS1115::begin() +{ + Wire.begin(); +} + +uint8_t ADS1115::trigger_sample() +{ + return write_register(ADS1115_REGISTER_CONFIG, m_config | SAMPLE_BIT); +} + +uint8_t ADS1115::reset() +{ + Wire.beginTransmission(0); + Wire.write(0x6); + return Wire.endTransmission(); +} + +bool ADS1115::is_sample_in_progress() +{ + uint16_t val = read_register(ADS1115_REGISTER_CONFIG); + return (val & SAMPLE_BIT) == 0; +} + +int16_t ADS1115::read_sample() +{ + return read_register(ADS1115_REGISTER_CONVERSION); +} + +float ADS1115::sample_to_float(int16_t val) +{ + return val * ranges[m_voltage_range]; +} + +float ADS1115::read_sample_float() +{ + return sample_to_float(read_sample()); +} + +ADS1115 adc; + +void ADS1115_init(void) { + + ads1115_up=0; + if (!i2c_flg) return; + + adc.begin(); + adc.set_data_rate(ADS1115_DATA_RATE_128_SPS); + adc.set_mode(ADS1115_MODE_CONTINUOUS); + adc.set_mux(ADS1115_MUX_DIFF_AIN0_AIN3); + adc.set_pga(ADS1115_PGA_TWO); + + int16_t val = adc.read_sample(); + ads1115_up=1; +} + +#endif + +char sml_start; +uint8_t dump2log=0; + +#define SML_SAVAILABLE Serial_available() +#define SML_SREAD Serial_read() +#define SML_SPEAK Serial_peek() + +bool Serial_available() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->available(); +} + +uint8_t Serial_read() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->read(); +} + +uint8_t Serial_peek() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->peek(); +} + +uint8_t sml_logindex; + +void Dump2log(void) { + +int16_t index=0,hcnt=0; +uint32_t d_lastms; +uint8_t dchars[16]; + + + + if (dump2log&8) { + + while (SML_SAVAILABLE) { + log_data[index]=':'; + index++; + log_data[index]=' '; + index++; + d_lastms=millis(); + while ((millis()-d_lastms)<40) { + if (SML_SAVAILABLE) { + uint8_t c=SML_SREAD; + sprintf(&log_data[index],"%02x ",c); + dchars[hcnt]=c; + index+=3; + hcnt++; + if (hcnt>15) { + + log_data[index]='='; + index++; + log_data[index]='>'; + index++; + log_data[index]=' '; + index++; + for (uint8_t ccnt=0; ccnt<16; ccnt++) { + if (isprint(dchars[ccnt])) { + log_data[index]=dchars[ccnt]; + } else { + log_data[index]=' '; + } + index++; + } + break; + } + } + } + if (index>0) { + log_data[index]=0; + AddLog(LOG_LEVEL_INFO); + index=0; + hcnt=0; + } + } + } else { + if (meter_desc_p[(dump2log&7)-1].type=='o') { + + while (SML_SAVAILABLE) { + char c=SML_SREAD&0x7f; + if (c=='\n' || c=='\r') { + log_data[sml_logindex]=0; + AddLog(LOG_LEVEL_INFO); + sml_logindex=2; + log_data[0]=':'; + log_data[1]=' '; + break; + } + log_data[sml_logindex]=c; + if (sml_logindex2) { + log_data[index]=0; + AddLog(LOG_LEVEL_INFO); + } + } + } +} + + +uint8_t *skip_sml(uint8_t *cp,int16_t *res) { + uint8_t len,len1,type; + len=*cp&0xf; + type=*cp&0x70; + if (type==0x70) { + + + cp++; + while (len--) { + len1=*cp&0x0f; + cp+=len1; + } + *res=0; + } else { + + *res=(signed char)*(cp+1); + cp+=len; + } + return cp; +} + + + +double sml_getvalue(unsigned char *cp,uint8_t index) { +uint8_t len,unit,type; +int16_t scaler,result; +int64_t value; +double dval; + + + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + scaler=result; + + type=*cp&0x70; + len=*cp&0x0f; + cp++; + if (type==0x50 || type==0x60) { + + uint64_t uvalue=0; + uint8_t nlen=len; + while (--nlen) { + uvalue<<=8; + uvalue|=*cp++; + } + if (type==0x50) { + + switch (len-1) { + case 1: + + value=(signed char)uvalue; + break; + case 2: + +#ifdef DWS74_BUG + if (scaler==-2) { + value=(uint32_t)uvalue; + } else { + value=(int16_t)uvalue; + } +#else + value=(int16_t)uvalue; +#endif + break; + case 3: + case 4: + + value=(int32_t)uvalue; + break; + case 5: + case 6: + case 7: + case 8: + + value=(int64_t)uvalue; + break; + } + } else { + + value=uvalue; + } + + } else { + if (!(type&0xf0)) { + + + + if (len==9) { + + cp++; + uint32_t s1,s2; + s1=*cp<<16|*(cp+1)<<8|*(cp+2); + cp+=4; + s2=*cp<<16|*(cp+1)<<8|*(cp+2); + sprintf(&meter_id[index][0],"%u-%u",s1,s2); + } else { + + char *str=&meter_id[index][0]; + for (type=0; type= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + } + return rVal; +} + +uint8_t sb_counter; + + +double CharToDouble(const char *str) +{ + + char strbuf[24]; + + strlcpy(strbuf, str, sizeof(strbuf)); + char *pt = strbuf; + while ((*pt != '\0') && isblank(*pt)) { pt++; } + + signed char sign = 1; + if (*pt == '-') { sign = -1; } + if (*pt == '-' || *pt=='+') { pt++; } + + double left = 0; + if (*pt != '.') { + left = atoi(pt); + while (isdigit(*pt)) { pt++; } + } + + double right = 0; + if (*pt == '.') { + pt++; + right = atoi(pt); + while (isdigit(*pt)) { + pt++; + right /= 10.0; + } + } + + double result = left + right; + if (sign < 0) { + return -result; + } + return result; +} + + + +void ebus_esc(uint8_t *ebus_buffer, unsigned char len) { + short count,count1; + for (count=0; countavailable()) { + meter_ss[meters]->read(); + } +} + + +void sml_shift_in(uint32_t meters,uint32_t shard) { + uint32_t count; + if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p') { + + for (count=0; countread(); + + if (meter_desc_p[meters].type=='o') { + smltbuf[meters][SML_BSIZ-1]=iob&0x7f; + } else if (meter_desc_p[meters].type=='s') { + smltbuf[meters][SML_BSIZ-1]=iob; + } else if (meter_desc_p[meters].type=='r') { + smltbuf[meters][SML_BSIZ-1]=iob; + } else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M') { + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=9) { + SML_Decode(meters); + sml_empty_receiver(meters); + meter_spos[meters]=0; + } + } else if (meter_desc_p[meters].type=='p') { + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=7) { + SML_Decode(meters); + sml_empty_receiver(meters); + meter_spos[meters]=0; + } + } else { + if (iob==EBUS_SYNC) { + + + if (meter_spos[meters]>4+5) { + + uint8_t tlen=smltbuf[meters][4]+5; + + if (smltbuf[meters][tlen]=ebus_CalculateCRC(smltbuf[meters],tlen)) { + ebus_esc(smltbuf[meters],tlen); + SML_Decode(meters); + } else { + + + } + } + meter_spos[meters]=0; + return; + } + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=SML_BSIZ) { + meter_spos[meters]=0; + } + } + sb_counter++; + if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p') SML_Decode(meters); +} + + + +void SML_Poll(void) { +uint32_t meters; + + for (meters=0; metersavailable()) { + sml_shift_in(meters,0); + } + } + } +} + + +void SML_Decode(uint8_t index) { + const char *mp=(const char*)meter_p; + int8_t mindex; + uint8_t *cp; + uint8_t dindex=0,vindex=0; + delay(0); + while (mp != NULL) { + + + + mindex=((*mp)&7)-1; + + if (mindex<0 || mindex>=meters_used) mindex=0; + mp+=2; + if (*mp=='=' && *(mp+1)=='h') { + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + + if (index!=mindex) goto nextsect; + + + cp=&smltbuf[mindex][0]; + + + if (*mp=='=') { + + mp++; + + if (*mp=='m' && !sb_counter) { + + + mp++; + while (*mp==' ') mp++; + + double dvar; + uint8_t opr; + uint32_t ind; + ind=atoi(mp); + while (*mp>='0' && *mp<='9') mp++; + if (ind<1 || ind>SML_MAX_VARS) ind=1; + dvar=meter_vars[ind-1]; + for (uint8_t p=0;p<5;p++) { + if (*mp=='@') { + + meter_vars[vindex]=dvar; + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + break; + } + opr=*mp; + mp++; + uint8_t iflg=0; + if (*mp=='#') { + iflg=1; + mp++; + } + ind=atoi(mp); + while (*mp>='0' && *mp<='9') mp++; + if (ind<1 || ind>SML_MAX_VARS) ind=1; + switch (opr) { + case '+': + if (iflg) dvar+=ind; + else dvar+=meter_vars[ind-1]; + break; + case '-': + if (iflg) dvar-=ind; + else dvar-=meter_vars[ind-1]; + break; + case '*': + if (iflg) dvar*=ind; + else dvar*=meter_vars[ind-1]; + break; + case '/': + if (iflg) dvar/=ind; + else dvar/=meter_vars[ind-1]; + break; + } + while (*mp==' ') mp++; + if (*mp=='@') { + + meter_vars[vindex]=dvar; + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + break; + } + } + } else if (*mp=='d') { + + if (dindex='0' && *mp<='9') mp++; + if (ind<1 || ind>SML_MAX_VARS) ind=1; + uint32_t delay=atoi(mp)*1000; + uint32_t dtime=millis()-dtimes[dindex]; + if (dtime>delay) { + + dtimes[dindex]=millis(); + double vdiff = meter_vars[ind-1]-dvalues[dindex]; + dvalues[dindex]=meter_vars[ind-1]; + meter_vars[vindex]=(double)360000.0*vdiff/((double)dtime/10000.0); + + mp=strchr(mp,'@'); + if (mp) { + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + } + } + dindex++; + } + } else if (*mp=='h') { + + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + } else { + + uint8_t found=1; + uint32_t ebus_dval=99; + float mbus_dval=99; + while (*mp!='@') { + if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') { + if (*mp++!=*cp++) { + found=0; + } + } else { + if (meter_desc_p[mindex].type=='s') { + + uint8_t val = hexnibble(*mp++) << 4; + val |= hexnibble(*mp++); + if (val!=*cp++) { + found=0; + } + } else { + + + if (*mp=='x' && *(mp+1)=='x') { + + mp+=2; + cp++; + } else if (!strncmp(mp,"UUuuUUuu",8)) { + uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + ebus_dval=val; + mbus_dval=val; + mp+=8; + cp+=4; + } else if (*mp=='U' && *(mp+1)=='U' && *(mp+2)=='u' && *(mp+3)=='u'){ + uint16_t val = cp[1]|(cp[0]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (!strncmp(mp,"SSssSSss",8)) { + int32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + ebus_dval=val; + mbus_dval=val; + mp+=8; + cp+=4; + } else if (*mp=='u' && *(mp+1)=='u' && *(mp+2)=='U' && *(mp+3)=='U'){ + uint16_t val = cp[0]|(cp[1]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (*mp=='u' && *(mp+1)=='u') { + uint8_t val = *cp++; + mbus_dval=val; + ebus_dval=val; + mp+=2; + } else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='S' && *(mp+3)=='S') { + int16_t val = *cp|(*(cp+1)<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (*mp=='S' && *(mp+1)=='S' && *(mp+2)=='s' && *(mp+3)=='s') { + int16_t val = cp[1]|(cp[0]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } + else if (*mp=='s' && *(mp+1)=='s') { + int8_t val = *cp++; + mbus_dval=val; + ebus_dval=val; + mp+=2; + } + else if (!strncmp(mp,"ffffffff",8)) { + uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + float *fp=(float*)&val; + ebus_dval=*fp; + mbus_dval=*fp; + mp+=8; + cp+=4; + } + else if (!strncmp(mp,"FFffFFff",8)) { + + uint32_t val= (cp[1]<<0)|(cp[0]<<8)|(cp[3]<<16)|(cp[2]<<24); + float *fp=(float*)&val; + ebus_dval=*fp; + mbus_dval=*fp; + mp+=8; + cp+=4; + } + else if (!strncmp(mp,"eeeeee",6)) { + uint32_t val=(cp[0]<<16)|(cp[1]<<8)|(cp[2]<<0); + mbus_dval=val; + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"vvvvvv",6)) { + mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/10.0); + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"cccccc",6)) { + mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/100.0); + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"pppp",4)) { + mbus_dval=(float)((cp[0]<<8)|cp[1]); + mp+=4; + cp+=2; + } + else { + uint8_t val = hexnibble(*mp++) << 4; + val |= hexnibble(*mp++); + if (val!=*cp++) { + found=0; + } + } + } + } + } + if (found) { + + mp++; + if (*mp=='#') { + + mp++; + if (meter_desc_p[mindex].type=='o') { + for (uint8_t p=0;p>=shift; + ebus_dval&=1; + mp+=2; + } + if (*mp=='i') { + + mp++; + uint8_t mb_index=strtol((char*)mp,(char**)&mp,10); + if (mb_index!=meter_desc_p[mindex].index) { + goto nextsect; + } + uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7); + if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect; + if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect; + dval=mbus_dval; + + mp++; + } else { + if (meter_desc_p[mindex].type=='p') { + uint8_t crc = SML_PzemCrc(&smltbuf[mindex][0],6); + if (crc!=smltbuf[mindex][6]) goto nextsect; + dval=mbus_dval; + } else { + dval=ebus_dval; + } + } + + } +#ifdef USE_SML_MEDIAN_FILTER + if (meter_desc_p[mindex].flag&16) { + meter_vars[vindex]=sml_median(&sml_mf[vindex],dval); + } else { + meter_vars[vindex]=dval; + } +#else + meter_vars[vindex]=dval; +#endif + + + double fac=CharToDouble((char*)mp); + meter_vars[vindex]/=fac; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + } + } + } +nextsect: + + if (vindex=meters_used) lastmind=0; + while (mp != NULL) { + + mindex=((*mp)&7)-1; + if (mindex<0 || mindex>=meters_used) mindex=0; + mp+=2; + if (*mp=='=' && *(mp+1)=='h') { + mp+=2; + + if (json) { + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + + uint8_t i; + for (i=0;isml_counters[index].sml_debounce) { + RtcSettings.pulse_counter[index]++; + InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]); + } + } else { + + sml_counters[index].sml_counter_ltime=millis(); + } +} + +void SML_CounterUpd1(void) { + SML_CounterUpd(0); +} + +void SML_CounterUpd2(void) { + SML_CounterUpd(1); +} + +void SML_CounterUpd3(void) { + SML_CounterUpd(2); +} + +void SML_CounterUpd4(void) { + SML_CounterUpd(3); +} + +#ifdef USE_SCRIPT +struct METER_DESC script_meter_desc[MAX_METERS]; +uint8_t *script_meter; +#endif + +#ifndef METER_DEF_SIZE +#define METER_DEF_SIZE 3000 +#endif + +bool Gpio_used(uint8_t gpiopin) { + for (uint16_t i=0;iM",-2,0); + if (meter_script==99) { + + if (script_meter) free(script_meter); + script_meter=0; + uint8_t *tp=0; + uint16_t index=0; + uint8_t section=0; + uint8_t srcpin=0; + char *lp=glob_script_mem.scriptptr; + sml_send_blocks=0; + while (lp) { + if (!section) { + if (*lp=='>' && *(lp+1)=='M') { + lp+=2; + meters_used=strtol(lp,0,10); + section=1; + uint32_t mlen=0; + for (uint32_t cnt=0;cnt') { + if (*(tp-1)=='|') *(tp-1)=0; + break; + } + if (*lp=='+') { + + + lp++; + index=*lp&7; + lp+=2; + if (index<1 || index>meters_used) goto next_line; + index--; + srcpin=strtol(lp,&lp,10); + if (Gpio_used(srcpin)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("gpio rx double define!")); +dddef_exit: + if (script_meter) free(script_meter); + script_meter=0; + meters_used=METERS_USED; + goto init10; + } + script_meter_desc[index].srcpin=srcpin; + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].type=*lp; + lp+=2; + script_meter_desc[index].flag=strtol(lp,&lp,10); + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].params=strtol(lp,&lp,10); + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].prefix[7]=0; + for (uint32_t cnt=0; cnt<8; cnt++) { + if (*lp==SCRIPT_EOL || *lp==',') { + script_meter_desc[index].prefix[cnt]=0; + break; + } + script_meter_desc[index].prefix[cnt]=*lp++; + } + if (*lp==',') { + lp++; + script_meter_desc[index].trxpin=strtol(lp,&lp,10); + if (Gpio_used(script_meter_desc[index].trxpin)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("gpio tx double define!")); + goto dddef_exit; + } + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].tsecs=strtol(lp,&lp,10); + if (*lp==',') { + lp++; + char txbuff[256]; + uint32_t txlen=0,tx_entries=1; + for (uint32_t cnt=0; cntmeters_used) goto next_line; + while (1) { + if (*lp==SCRIPT_EOL) { + if (*(tp-1)!='|') *tp++='|'; + goto next_line; + } + *tp++=*lp++; + index++; + if (index>=METER_DEF_SIZE) break; + } + } + + } + +next_line: + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + *tp=0; + meter_desc_p=script_meter_desc; + meter_p=script_meter; + } +#endif + +init10: + typedef void (*function)(); + function counter_callbacks[] = {SML_CounterUpd1,SML_CounterUpd2,SML_CounterUpd3,SML_CounterUpd4}; + uint8_t cindex=0; + + for (byte i = 0; i < MAX_COUNTERS; i++) { + RtcSettings.pulse_counter[i]=Settings.pulse_counter[i]; + sml_counters[i].sml_cnt_last_ts=millis(); + } + for (uint8_t meters=0; metersbegin(meter_desc_p[meters].params)) { + meter_ss[meters]->flush(); + } + if (meter_ss[meters]->hardwareSerial()) { + if (meter_desc_p[meters].type=='M') { + Serial.begin(meter_desc_p[meters].params, SERIAL_8E1); + } + ClaimSerial(); + } + + } + } + +} + + +#ifdef USE_SML_SCRIPT_CMD +uint32_t SML_SetBaud(uint32_t meter, uint32_t br) { + if (meter<1 || meter>meters_used) return 0; + meter--; + if (!meter_ss[meter]) return 0; + if (meter_ss[meter]->begin(br)) { + meter_ss[meter]->flush(); + } + if (meter_ss[meter]->hardwareSerial()) { + if (meter_desc_p[meter].type=='M') { + Serial.begin(br, SERIAL_8E1); + } + } + return 1; +} + +uint32_t SML_Write(uint32_t meter,char *hstr) { + if (meter<1 || meter>meters_used) return 0; + meter--; + if (!meter_ss[meter]) return 0; + SML_Send_Seq(meter,hstr); + return 1; +} +#endif + + +void SetDBGLed(uint8_t srcpin, uint8_t ledpin) { + pinMode(ledpin, OUTPUT); + if (digitalRead(srcpin)) { + digitalWrite(ledpin,LOW); + } else { + digitalWrite(ledpin,HIGH); + } +} + + +void SML_Counter_Poll(void) { +uint16_t meters,cindex=0; +uint32_t ctime=millis(); + + for (meters=0; meters0) { + if (ctime-sml_counters[cindex].sml_cnt_last_ts>meter_desc_p[meters].params) { + sml_counters[cindex].sml_cnt_last_ts=ctime; + + if (meter_desc_p[meters].flag&2) { + +#ifdef ANALOG_OPTO_SENSOR + if (ads1115_up) { + int16_t val = adc.read_sample(); + if (val>sml_counters[cindex].ana_max) sml_counters[cindex].ana_max=val; + if (val10) { + sml_counters[cindex].sml_cnt_last_ts=ctime; +#ifdef DEBUG_CNT_LED1 + if (cindex==0) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED1); +#endif +#ifdef DEBUG_CNT_LED2 + if (cindex==1) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED2); +#endif + } + } + cindex++; + } + } +} + +#ifdef USE_SCRIPT +char *SML_Get_Sequence(char *cp,uint32_t index) { + if (!index) return cp; + uint32_t cindex=0; + while (cp) { + cp=strchr(cp,','); + if (cp) { + cp++; + cindex++; + if (cindex==index) { + return cp; + } + } + } +} + +void SML_Check_Send(void) { + sml_100ms_cnt++; + char *cp; + for (uint32_t cnt=sml_desc_cnt; cnt=0 && script_meter_desc[cnt].txmem) { + if ((sml_100ms_cnt%script_meter_desc[cnt].tsecs)==0) { + if (script_meter_desc[cnt].max_index>1) { + script_meter_desc[cnt].index++; + if (script_meter_desc[cnt].index>=script_meter_desc[cnt].max_index) { + script_meter_desc[cnt].index=0; + sml_desc_cnt++; + } + cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index); + + } else { + cp=script_meter_desc[cnt].txmem; + + sml_desc_cnt++; + } + + SML_Send_Seq(cnt,cp); + if (sml_desc_cnt>=meters_used) { + sml_desc_cnt=0; + } + break; + } + } else { + sml_desc_cnt++; + } + + if (sml_desc_cnt>=meters_used) { + sml_desc_cnt=0; + } + } +} + +uint8_t sml_hexnibble(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { + rVal = chr - '0'; + } else { + if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; + } + return rVal; +} + + +void SML_Send_Seq(uint32_t meter,char *seq) { + uint8_t sbuff[32]; + uint8_t *ucp=sbuff,slen=0; + char *cp=seq; + while (*cp) { + if (!*cp || !*(cp+1)) break; + if (*cp==',') break; + uint8_t iob=(sml_hexnibble(*cp) << 4) | sml_hexnibble(*(cp+1)); + cp+=2; + *ucp++=iob; + slen++; + if (slen>=sizeof(sbuff)) break; + } + if (script_meter_desc[meter].type=='m' || script_meter_desc[meter].type=='M') { + *ucp++=0; + *ucp++=2; + + uint16_t crc = MBUS_calculateCRC(sbuff,6); + *ucp++=lowByte(crc); + *ucp++=highByte(crc); + slen+=4; + } + if (script_meter_desc[meter].type=='o') { + for (uint32_t cnt=0;cntwrite(sbuff,slen); +} +#endif + +uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { + uint16_t crc, flag; + crc = 0xFFFF; + for (uint32_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint32_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + return crc; +} + +uint8_t SML_PzemCrc(uint8_t *data, uint8_t len) { + uint16_t crc = 0; + for (uint32_t i = 0; i < len; i++) crc += *data++; + return (uint8_t)(crc & 0xFF); +} + + +uint8_t CalcEvenParity(uint8_t data) { +uint8_t parity=0; + + while(data) { + parity^=(data &1); + data>>=1; + } + return parity; +} +# 2361 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_53_sml.ino" +bool XSNS_53_cmd(void) { + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + char *cp=XdrvMailbox.data; + if (*cp=='d') { + + cp++; + uint8_t index=atoi(cp); + if ((index&7)>meters_used) index=1; + if (index>0 && meter_desc_p[(index&7)-1].type=='c') { + index=0; + } + dump2log=index; + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); + } else if (*cp=='c') { + + cp++; + uint8_t index=*cp&7; + if (index<1 || index>MAX_COUNTERS) index=1; + cp++; + while (*cp==' ') cp++; + if (isdigit(*cp)) { + uint32_t cval=atoi(cp); + while (isdigit(*cp)) cp++; + RtcSettings.pulse_counter[index-1]=cval; + uint8_t cindex=0; + for (uint8_t meters=0; metersaddress, INA226_REG_CALIBRATION, si->calibrationValue); + +} + + + + + + +bool Ina226TestPresence(uint8_t device) +{ + + + + uint16_t config = I2cRead16( slaveInfo[device].address, INA226_REG_CONFIG ); + + + if (config != slaveInfo[device].config) + return false; + + return true; + +} + +void Ina226ResetActive(void) +{ + Ina226SlaveInfo_t *p = slaveInfo; + + for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) { + p = &slaveInfo[i]; + + uint8_t addr = p->address; + if (addr) { + I2cResetActive(addr); + } + } +} + + + + + +void Ina226Init() +{ + uint32_t i; + + slavesFound = 0; + + Ina226SlaveInfo_t *p = slaveInfo; +# 215 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_54_ina226.ino" + for (i = 0; i < 4; i++){ + *p = {0}; + } + + + + + + for (i = 0; i < INA226_MAX_ADDRESSES; i++){ + uint8_t addr = pgm_read_byte(probeAddresses + i); + + if (I2cActive(addr)) { continue; } + + + + + if (!Settings.ina226_i_fs[i]) + continue; + + + + + + + if (!I2cWrite16( addr, INA226_REG_CONFIG, INA226_CONFIG_RESET)){ + + AddLog_P2( LOG_LEVEL_DEBUG, "No INA226 at address: %02X", addr); + continue; + } + + + + uint16_t config = I2cRead16( addr, INA226_REG_CONFIG ); + + + if (INA226_RES_CONFIG != config) + continue; + + + config = INA226_DEF_CONFIG; + + + if (!I2cWrite16( addr, INA226_REG_CONFIG, config)) + continue; + + + p = &slaveInfo[i]; + + p->address = addr; + + p->config = config; + + + p->i_lsb = (((float) Settings.ina226_i_fs[i])/10.0f)/32768.0f; + + + + uint32_t r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[i]); + + + + p->calibrationValue = ((uint16_t) (0.00512/(p->i_lsb * r_shunt_uohms/1000000.0f))); + + p->present = true; + + + Ina226SetCalibration(i); + + I2cSetActiveFound(addr, Ina226Str); + + slavesFound++; + } +} + + + + + +float Ina226ReadBus_v(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE); + + float result = ((float) reg_bus_v) * 0.00125f; + + return result; + +} + + + + + +float Ina226ReadShunt_i(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); + + float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb; + + return result; +} + + + + + +float Ina226ReadPower_w(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); + + float result = ((float) reg_shunt_i) * (slaveInfo[device].i_lsb * 25.0); + + return result; +} + + + + + + +void Ina226Read(uint8_t device) +{ + + voltages[device] = Ina226ReadBus_v(device); + currents[device] = Ina226ReadShunt_i(device); + powers[device] = Ina226ReadPower_w(device); + + + + +} + + + + + +void Ina226EverySecond() +{ + + for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){ + + if (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){ + Ina226Read(device); + } + else { + powers[device] = currents[device] = voltages[device] = 0.0f; + + + + + + + slaveInfo[device].present = false; + } + } +} + + + + + +bool Ina226CommandSensor() +{ + bool serviced = true; + bool show_config = false; + char param_str[64]; + char *cp, *params[4]; + uint8_t i, param_count, device, p1 = XdrvMailbox.payload; + uint32_t r_shunt_uohms; + uint16_t compact_r_shunt_uohms; + + + + + + if (XdrvMailbox.data_len > 62){ + return false; + } + + strncpy(param_str, XdrvMailbox.data, XdrvMailbox.data_len + 1); + param_str[XdrvMailbox.data_len] = 0; + + + for (cp = param_str, i = 0, param_count = 0; *cp && (i < XdrvMailbox.data_len + 1) && (param_count <= 3); i++) + if (param_str[i] == ' ' || param_str[i] == ',' || param_str[i] == 0){ + param_str[i] = 0; + params[param_count] = cp; + + param_count++; + cp = param_str + i + 1; + } + + + if (p1 < 10 || p1 >= 50){ + + switch (p1){ + case 1: + Ina226ResetActive(); + Ina226Init(); + Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound); + break; + + case 2: + restart_flag = 2; + Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag); + break; + + default: + serviced = false; + } + } + else if (p1 < 50){ + + device = (p1 / 10) - 1; + switch (p1 % 10){ + case 0: + show_config = true; + break; + + case 1: + r_shunt_uohms = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f); + + + + if (r_shunt_uohms > 32767){ + uint32_t r_shunt_mohms = r_shunt_uohms/1000UL; + Settings.ina226_r_shunt[device] = (uint16_t) (r_shunt_mohms | 0x8000); + } + else + Settings.ina226_r_shunt[device] = (uint16_t) r_shunt_uohms; + + + show_config = true; + break; + + case 2: + Settings.ina226_i_fs[device] = (uint16_t) ((CharToFloat(params[1])) * 10.0f); + + show_config = true; + break; + + + default: + serviced = false; + break; + } + } + else + serviced = false; + + if (show_config) { + char shunt_r_str[16]; + char fs_i_str[16]; + + + r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[device]); + dtostrfd(((float)r_shunt_uohms)/1000000.0f, 6, shunt_r_str); + + dtostrfd(((float)Settings.ina226_i_fs[device])/10.0f, 1, fs_i_str); + + Response_P(PSTR("{\"Sensor54-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"), + device + 1, shunt_r_str, fs_i_str); + } + + return serviced; +} + + + + + +#ifdef USE_WEBSERVER +const char HTTP_SNS_INA226_DATA[] PROGMEM = + "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; +#endif + +void Ina226Show(bool json) +{ + int i, num_found; + for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) { + + if (!slaveInfo[i].present) + continue; + + num_found++; + + char voltage[16]; + dtostrfd(voltages[i], Settings.flag2.voltage_resolution, voltage); + char current[16]; + dtostrfd(currents[i], Settings.flag2.current_resolution, current); + char power[16]; + dtostrfd(powers[i], Settings.flag2.wattage_resolution, power); + char name[16]; + snprintf_P(name, sizeof(name), PSTR("INA226%c%d"),IndexSeparator(), i + 1); + + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%d,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + name, i, voltage, current, power); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, voltage); + DomoticzSensor(DZ_CURRENT, current); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_INA226_DATA, name, voltage, name, current, name, power); +#endif + } + + } + +} +# 546 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_54_ina226.ino" +bool Xsns54(byte callback_id) +{ + if (!I2cEnabled(XI2C_35)) { return false; } + + + bool result = false; + + + switch (callback_id) { + case FUNC_EVERY_SECOND: + Ina226EverySecond(); + break; + case FUNC_JSON_APPEND: + Ina226Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ina226Show(0); + break; +#endif + case FUNC_COMMAND_SENSOR: + if (XSNS_54 == XdrvMailbox.index) { + result = Ina226CommandSensor(); + } + break; + case FUNC_INIT: + Ina226Init(); + break; + } + + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_55_hih_series.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_55_hih_series.ino" +#ifdef USE_I2C +#ifdef USE_HIH6 +# 33 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_55_hih_series.ino" +#define XSNS_55 55 +#define XI2C_36 36 + +#define HIH6_ADDR 0x27 + +struct HIH6 { + float temperature = 0; + float humidity = 0; + uint8_t valid = 0; + uint8_t type = 0; + char types[4] = "HIH"; +} Hih6; + +bool Hih6Read(void) +{ + Wire.beginTransmission(HIH6_ADDR); + if (Wire.endTransmission() != 0) { return false; } + + delay(40); + + uint8_t data[4]; + Wire.requestFrom(HIH6_ADDR, 4); + if (4 == Wire.available()) { + data[0] = Wire.read(); + data[1] = Wire.read(); + data[2] = Wire.read(); + data[3] = Wire.read(); + } else { return false; } + + + + Hih6.humidity = ConvertHumidity(((float)(((data[0] & 0x3F) << 8) | data[1]) * 100.0) / 16383.0); + + int temp = ((data[2] << 8) | (data[3] & 0xFC)) / 4; + Hih6.temperature = ConvertTemp(((float)temp / 16384.0) * 165.0 - 40.0); + + Hih6.valid = SENSOR_MAX_MISS; + return true; +} + + + +void Hih6Detect(void) +{ + if (I2cActive(HIH6_ADDR)) { return; } + + if (uptime < 2) { delay(20); } + Hih6.type = Hih6Read(); + if (Hih6.type) { + I2cSetActiveFound(HIH6_ADDR, Hih6.types); + } +} + +void Hih6EverySecond(void) +{ + if (uptime &1) { + + if (!Hih6Read()) { + AddLogMissed(Hih6.types, Hih6.valid); + } + } +} + +void Hih6Show(bool json) +{ + if (Hih6.valid) { + char temperature[33]; + dtostrfd(Hih6.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Hih6.humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Hih6.types, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, Hih6.temperature); + KnxSensor(KNX_HUMIDITY, Hih6.humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Hih6.types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Hih6.types, humidity); +#endif + } + } +} + + + + + +bool Xsns55(uint8_t function) +{ + if (!I2cEnabled(XI2C_36)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Hih6Detect(); + } + else if (Hih6.type) { + switch (function) { + case FUNC_EVERY_SECOND: + Hih6EverySecond(); + break; + case FUNC_JSON_APPEND: + Hih6Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Hih6Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_56_hpma.ino" +# 21 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_56_hpma.ino" +#ifdef USE_HPMA +# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_56_hpma.ino" +#define XSNS_56 56 + +#include +#include + +TasmotaSerial *HpmaSerial; +HPMA115S0 *hpma115S0; + +uint8_t hpma_type = 1; +uint8_t hpma_valid = 0; + +struct hpmadata { + unsigned int pm10; + unsigned int pm2_5; +} hpma_data; + + + +void HpmaSecond(void) +{ + unsigned int pm2_5, pm10; + + + + + if (hpma115S0->ReadParticleMeasurement(&pm2_5, &pm10)) { + hpma_data.pm2_5 = pm2_5; + hpma_data.pm10 = pm10; + hpma_valid = 1; + } + +} + +void HpmaInit(void) +{ + hpma_type = 0; + if (pin[GPIO_HPMA_RX] < 99 && pin[GPIO_HPMA_TX] < 99) { + HpmaSerial = new TasmotaSerial(pin[GPIO_HPMA_RX], pin[GPIO_HPMA_TX], 1); + hpma115S0 = new HPMA115S0(*HpmaSerial); + + if (HpmaSerial->begin(9600)) { + if (HpmaSerial->hardwareSerial()) { + ClaimSerial(); + } + hpma_type = 1; + hpma115S0->Init(); + hpma115S0->StartParticleMeasurement(); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_HPMA_SNS[] PROGMEM = + "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#endif + +void HpmaShow(bool json) +{ + if (hpma_valid) { + char pm10[33]; + snprintf_P(pm10, 33, PSTR("%d"), hpma_data.pm10); + char pm2_5[33]; + snprintf_P(pm2_5, 33, PSTR("%d"), hpma_data.pm2_5); + + if (json) { + ResponseAppend_P(PSTR(",\"HPMA\":{\"PM2.5\":%d,\"PM10\":%d}"), hpma_data.pm2_5, hpma_data.pm10); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, pm2_5); + DomoticzSensor(DZ_CURRENT, pm10); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_HPMA_SNS, pm2_5, pm10); +#endif + } + } +} + + + + + +bool Xsns56(uint8_t function) +{ + bool result = false; + + if (hpma_type) { + switch (function) { + case FUNC_INIT: + HpmaInit(); + break; + case FUNC_EVERY_SECOND: + HpmaSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_56 == XdrvMailbox.index) { + return true; + } + break; + case FUNC_JSON_APPEND: + HpmaShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HpmaShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_57_tsl2591.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_57_tsl2591.ino" +#ifdef USE_I2C +#ifdef USE_TSL2591 + + + + + + + +#define XSNS_57 57 +#define XI2C_40 40 + +#define TSL2591_ADDRESS 0x29 + +#include + +Adafruit_TSL2591 tsl = Adafruit_TSL2591(); + +uint8_t tsl2591_type = 0; +uint8_t tsl2591_valid = 0; +float tsl2591_lux = 0; + +void Tsl2591Init(void) +{ + + if (I2cSetDevice(0x29)) { + if (tsl.begin()) { + tsl.setGain(TSL2591_GAIN_MED); + tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS); + tsl2591_type = 1; + I2cSetActiveFound(TSL2591_ADDRESS, "TSL2591"); + } + } +} + +bool Tsl2591Read(void) +{ + uint32_t lum = tsl.getFullLuminosity(); + uint16_t ir, full; + ir = lum >> 16; + full = lum & 0xFFFF; + tsl2591_lux = tsl.calculateLux(full, ir); + tsl2591_valid = 1; +} + +void Tsl2591EverySecond(void) +{ + Tsl2591Read(); +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_TSL2591[] PROGMEM = + "{s}TSL2591 " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; +#endif + +void Tsl2591Show(bool json) +{ + if (tsl2591_valid) { + char lux_str[10]; + dtostrf(tsl2591_lux, sizeof(lux_str)-1, 3, lux_str); + if (json) { + ResponseAppend_P(PSTR(",\"TSL2591\":{\"" D_JSON_ILLUMINANCE "\":%s}"), lux_str); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TSL2591, lux_str); +#endif + } + } +} + + + + + +bool Xsns57(uint8_t function) +{ + if (!I2cEnabled(XI2C_40)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Tsl2591Init(); + } + else if (tsl2591_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Tsl2591EverySecond(); + break; + case FUNC_JSON_APPEND: + Tsl2591Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tsl2591Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_58_dht12.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_58_dht12.ino" +#ifdef USE_I2C +#ifdef USE_DHT12 + + + + + + +#define XSNS_58 58 +#define XI2C_41 41 + +#define DHT12_ADDR 0x5C + +struct DHT12 { + float temperature = NAN; + float humidity = NAN; + uint8_t valid = 0; + uint8_t count = 0; + char name[6] = "DHT12"; +} Dht12; + +bool Dht12Read(void) +{ + if (Dht12.valid) { Dht12.valid--; } + + Wire.beginTransmission(DHT12_ADDR); + Wire.write(0); + if (Wire.endTransmission() != 0) { return false; } + + delay(50); + + Wire.requestFrom(DHT12_ADDR, 5); + delay(5); + uint8_t humidity = Wire.read(); + uint8_t humidityTenth = Wire.read(); + uint8_t temp = Wire.read(); + uint8_t tempTenth = Wire.read(); + uint8_t checksum = Wire.read(); + + Dht12.humidity = ConvertHumidity( (float) humidity + (float) humidityTenth/(float) 10.0 ); + Dht12.temperature = ConvertTemp( (float) temp + (float) tempTenth/(float) 10.0 ); + + if (isnan(Dht12.temperature) || isnan(Dht12.humidity)) { return false; } + + Dht12.valid = SENSOR_MAX_MISS; + return true; +} + + + +void Dht12Detect(void) +{ + if (I2cActive(DHT12_ADDR)) { return; } + + if (Dht12Read()) { + I2cSetActiveFound(DHT12_ADDR, Dht12.name); + Dht12.count = 1; + } +} + +void Dht12EverySecond(void) +{ + if (uptime &1) { + + if (!Dht12Read()) { + AddLogMissed(Dht12.name, Dht12.valid); + } + } +} + +void Dht12Show(bool json) +{ + if (Dht12.valid) { + char temperature[33]; + dtostrfd(Dht12.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht12.humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht12.name, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, Dht12.temperature); + KnxSensor(KNX_HUMIDITY, Dht12.humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht12.name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht12.name, humidity); +#endif + } + } +} + + + + + +bool Xsns58(uint8_t function) +{ + if (!I2cEnabled(XI2C_41)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Dht12Detect(); + } + else if (Dht12.count) { + switch (function) { + case FUNC_EVERY_SECOND: + Dht12EverySecond(); + break; + case FUNC_JSON_APPEND: + Dht12Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Dht12Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_59_ds1624.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_59_ds1624.ino" +#ifdef USE_I2C +#ifdef USE_DS1624 + + + + + + + +#define XSNS_59 59 +#define XI2C_42 42 + +#define DS1624_MEM_REGISTER 0x17 +#define DS1624_CONF_REGISTER 0xAC +#define DS1624_TEMP_REGISTER 0xAA +#define DS1624_START_REGISTER 0xEE +#define DS1624_STOP_REGISTER 0x22 + +#define DS1621_COUNTER_REGISTER 0xA8 +#define DS1621_SLOPE_REGISTER 0xA9 + +#define DS1621_CFG_1SHOT (1<<0) +#define DS1621_CFG_DONE (1<<7) + +enum { + DS1624_TYPE_DS1624, + DS1624_TYPE_DS1621 +}; + +#define DS1624_MAX_SENSORS 8 + +bool ds1624_init = false; + +struct { + float value; + uint8_t type; + int errcnt; + int misscnt; + bool valid; + char name[9]; +} ds1624_sns[DS1624_MAX_SENSORS]; + +uint32_t DS1624_Idx2Addr(uint32_t idx) { + return 0x48 + idx; +} + +int DS1624_Restart(uint8_t config, uint32_t idx) { + uint32_t addr = DS1624_Idx2Addr(idx); + if ((config & 1) == 1) { + config &= ~(DS1621_CFG_DONE|DS1621_CFG_1SHOT); + I2cWrite8(addr, DS1624_CONF_REGISTER, config); + delay(10); + AddLog_P2(LOG_LEVEL_ERROR, "%s addr %x is reset, reconfig: %x", ds1624_sns[idx].name, addr, config); + } + I2cValidRead(addr, DS1624_START_REGISTER, 1); +} + +void DS1624_HotPlugUp(uint32_t idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + + if (I2cActive(addr)) { return; } + if (!I2cSetDevice(addr)) { return; } + + uint8_t config; + if (I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { + uint8_t tmp; + ds1624_sns[idx].type = (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) ? DS1624_TYPE_DS1624 : DS1624_TYPE_DS1621; + + snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS162%c%c%d"), + (ds1624_sns[idx].type == DS1624_TYPE_DS1621) ? '1' : '4', IndexSeparator(), idx); + I2cSetActiveFound(addr, ds1624_sns[idx].name); + + ds1624_sns[idx].valid = true; + ds1624_sns[idx].errcnt = 0; + ds1624_sns[idx].misscnt = 0; + DS1624_Restart(config,idx); + AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); + } +} + +void DS1624_HotPlugDown(int idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + if (!I2cActive(addr)) { return; } + I2cResetActive(addr); + ds1624_sns[idx].valid = false; + AddLog_P2(LOG_LEVEL_INFO, "Hot UnPlug %s", ds1624_sns[idx].name); +} + +bool DS1624GetTemp(float *value, int idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + + uint8_t config; + if (!I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { + ds1624_sns[idx].misscnt++; + AddLog_P2(LOG_LEVEL_INFO, "%s device missing (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].misscnt); + return false; + } + ds1624_sns[idx].misscnt=0; + if (config & (DS1621_CFG_1SHOT|DS1621_CFG_DONE)) { + ds1624_sns[idx].errcnt++; + AddLog_P2(LOG_LEVEL_INFO, "%s config error, restart... (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].errcnt); + DS1624_Restart(config, idx); + return false; + } + + uint16_t t; + if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { return false; } + if (ds1624_sns[idx].type == DS1624_TYPE_DS1624) { + *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; + } else { + + *value = ((float)(int8_t)(t>>8)); + uint8_t remain; + if (!I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)) { return true; } + uint8_t perc; + if (!I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)) { return true; } + float fix=(float)(perc - remain)/(float)perc; + *value+=fix; + } + ds1624_sns[idx].errcnt=0; + config &= ~(DS1621_CFG_DONE); + I2cWrite8(addr, DS1624_CONF_REGISTER, config); + return true; +} + +void DS1624HotPlugScan(void) +{ + uint16_t t; + + for (uint32_t idx = 0; idx < DS1624_MAX_SENSORS; idx++) { + uint32_t addr = DS1624_Idx2Addr(idx); + if (I2cActive(addr) && !ds1624_sns[idx].valid) { + continue; + } + if (ds1624_sns[idx].valid) { + if ((ds1624_sns[idx].misscnt>2)||(ds1624_sns[idx].errcnt>2)) { + DS1624_HotPlugDown(idx); + continue; + } + } + DS1624_HotPlugUp(idx); + } +} + +void DS1624EverySecond(void) +{ + float t; + for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { + if (!ds1624_sns[i].valid) { continue; } + if (!DS1624GetTemp(&t, i)) { continue; } + ds1624_sns[i].value = ConvertTemp(t); + } +} + +void DS1624Show(bool json) +{ + char temperature[33]; + bool once = true; + + for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { + if (!ds1624_sns[i].valid) { continue; } + + dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds1624_sns[i].name, temperature); + if ((0 == tele_period) && once) { +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, temperature); +#endif + once = false; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds1624_sns[i].name, temperature, TempUnit()); +#endif + } + } +} + + + + + +bool Xsns59(uint8_t function) +{ + if (!I2cEnabled(XI2C_42)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + if (!ds1624_init) { + memset(ds1624_sns, 0, sizeof(ds1624_sns)); + ds1624_init = true; + DS1624HotPlugScan(); + } + } + switch (function) { + case FUNC_HOTPLUG_SCAN: + DS1624HotPlugScan(); + break; + case FUNC_EVERY_SECOND: + DS1624EverySecond(); + break; + case FUNC_JSON_APPEND: + DS1624Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DS1624Show(0); + break; +#endif + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_60_GPS.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_60_GPS.ino" +#ifdef USE_GPS +# 113 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_60_GPS.ino" +#define XSNS_60 60 + +#include "NTPServer.h" +#include "NTPPacket.h" + + + + + +#define D_CMND_UBX "UBX" + +const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; + +const char kUBXTypes[] PROGMEM = "UBX"; + +#define UBX_LAT_LON_THRESHOLD 1000 + +#define UBX_SERIAL_BUFFER_SIZE 256 +#define UBX_TCP_PORT 1234 + + + + + +const char UBLOX_INIT[] PROGMEM = { + + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, + + + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, + + + + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, + + + + + + +}; + +char UBX_name[4]; + +struct UBX_t { + const char UBX_HEADER[2] = { 0xB5, 0x62 }; + const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; + const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; + const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; + + struct entry_t { + int32_t lat; + int32_t lon; + uint32_t time; + }; + + union { + entry_t values; + uint8_t bytes[sizeof(entry_t)]; + } rec_buffer; + + struct POLL_MSG { + uint8_t cls; + uint8_t id; + uint16_t zero; + }; + + struct NAV_POSLLH { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + int32_t lon; + int32_t lat; + int32_t alt; + int32_t hMSL; + uint32_t hAcc; + uint32_t vAcc; + }; + + struct NAV_STATUS { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint8_t gpsFix; + uint8_t flags; + uint8_t fixStat; + uint8_t flags2; + uint32_t ttff; + uint32_t msss; + }; + + struct NAV_TIME_UTC { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint32_t tAcc; + int32_t nano; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + struct { + uint8_t UTC:1; + uint8_t WKN:1; + uint8_t TOW:1; + uint8_t padding:5; + } valid; + }; + + struct CFG_RATE { + uint8_t cls; + uint8_t id; + uint16_t len; + uint16_t measRate; + uint16_t navRate; + uint16_t timeRef; + char CK[2]; + }; + + struct { + uint32_t last_iTOW; + int32_t last_alt; + uint32_t last_hAcc; + uint32_t last_vAcc; + uint8_t gpsFix; + uint8_t non_empty_loops; + uint16_t log_interval; + } state; + + struct { + uint32_t init:1; + uint32_t filter_noise:1; + uint32_t send_when_new:1; + uint32_t send_UI_only:1; + uint32_t runningNTP:1; + uint32_t forceUTCupdate:1; + uint32_t runningVPort:1; + + } mode; + + union { + NAV_POSLLH navPosllh; + NAV_STATUS navStatus; + NAV_TIME_UTC navTime; + POLL_MSG pollMsg; + CFG_RATE cfgRate; + } Message; + + uint8_t TCPbuf[UBX_SERIAL_BUFFER_SIZE]; + size_t TCPbufSize; +} UBX; + +enum UBXMsgType { + MT_NONE, + MT_NAV_POSLLH, + MT_NAV_STATUS, + MT_NAV_TIME, + MT_POLL +}; + +#ifdef USE_FLOG +FLOG *Flog = nullptr; +#endif +TasmotaSerial *UBXSerial; + +NtpServer timeServer(PortUdp); + +WiFiServer vPortServer(UBX_TCP_PORT); +WiFiClient vPortClient; + + + + + +void UBXcalcChecksum(char* CK, size_t msgSize) +{ + memset(CK, 0, 2); + for (int i = 0; i < msgSize; i++) { + CK[0] += ((char*)(&UBX.Message))[i]; + CK[1] += CK[0]; + } +} + +bool UBXcompareMsgHeader(const char* msgHeader) +{ + char* ptr = (char*)(&UBX.Message); + return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; +} + +void UBXinitCFG(void) +{ + for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { + UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); + } + DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); +} + +void UBXTriggerTele(void) +{ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +#ifdef USE_RULES + RulesTeleperiod(); +#endif + } +} + + + +void UBXDetect(void) +{ + UBX.mode.init = 0; + if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { + UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, UBX_SERIAL_BUFFER_SIZE); + if (UBXSerial->begin(9600)) { + DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); + if (UBXSerial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); + } + } + } + else { + return; + } + + UBXinitCFG(); + UBX.mode.init = 1; + +#ifdef USE_FLOG + if (!Flog) { + Flog = new FLOG; + Flog->init(); + } +#endif + + UBX.state.log_interval = 10; + UBX.mode.send_UI_only = true; + UBXTriggerTele(); +} + +uint32_t UBXprocessGPS() +{ + static uint32_t fpos = 0; + static char checksum[2]; + static uint8_t currentMsgType = MT_NONE; + static size_t payloadSize = sizeof(UBX.Message); + + + uint32_t data_bytes = 0; + while ( UBXSerial->available() ) { + data_bytes++; + byte c = UBXSerial->read(); + if (UBX.mode.runningVPort){ + UBX.TCPbuf[data_bytes-1] = c; + UBX.TCPbufSize = data_bytes; + } + if ( fpos < 2 ) { + + if ( c == UBX.UBX_HEADER[fpos] ) { + fpos++; + } else { + fpos = 0; + } + } else { + + + + + + if ( (fpos-2) < payloadSize ) { + ((char*)(&UBX.Message))[fpos-2] = c; + } + fpos++; + + if ( fpos == 4 ) { + + + if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { + currentMsgType = MT_NAV_POSLLH; + payloadSize = sizeof(UBX_t::NAV_POSLLH); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { + currentMsgType = MT_NAV_STATUS; + payloadSize = sizeof(UBX_t::NAV_STATUS); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { + currentMsgType = MT_NAV_TIME; + payloadSize = sizeof(UBX_t::NAV_TIME_UTC); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); + } + else { + + fpos = 0; + continue; + } + } + + if ( fpos == (payloadSize+2) ) { + + + UBXcalcChecksum(checksum, payloadSize); + } + else if ( fpos == (payloadSize+3) ) { + + + if ( c != checksum[0] ) { + + fpos = 0; + } + } + else if ( fpos == (payloadSize+4) ) { + + + fpos = 0; + if ( c == checksum[1] ) { + + return currentMsgType; + } + } + else if ( fpos > (payloadSize+4) ) { + + + fpos = 0; + } + } + } + + if (data_bytes!=0) { + UBX.state.non_empty_loops++; + DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); + } else { + UBX.state.non_empty_loops = 0; + } + return MT_NONE; +} + + + + + +#ifdef USE_FLOG +void UBXsendHeader(void) +{ + WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); + WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); + WSSend(200, CT_STREAM, F( + "\r\n" + "\r\n" + "\r\n\r\n")); +} + +void UBXsendRecord(uint8_t *buf) +{ + char record[100]; + char stime[32]; + UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; + snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); + char lat[12]; + char lon[12]; + dtostrfd((double)entry->lat/10000000.0f,7,lat); + dtostrfd((double)entry->lon/10000000.0f,7,lon); + snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); + + WebServer->sendContent_P(record); +} + +void UBXsendFooter(void) +{ + WebServer->sendContent(F("\n\n")); + WebServer->sendContent(""); + Rtc.user_time_entry = false; +} + + + +void UBXsendFile(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); +} +#endif + + + +void UBXSetRate(uint16_t interval) +{ + UBX.Message.cfgRate.cls = 0x06; + UBX.Message.cfgRate.id = 0x08; + UBX.Message.cfgRate.len = 6; + uint32_t measRate = (1000*(uint32_t)interval); + if (measRate > 0xffff) { + measRate = 0xffff; + } + UBX.Message.cfgRate.measRate = (uint16_t)measRate; + UBX.Message.cfgRate.navRate = 1; + UBX.Message.cfgRate.timeRef = 1; + UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); + DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); + UBXSerial->write(UBX.UBX_HEADER[0]); + UBXSerial->write(UBX.UBX_HEADER[1]); + for (uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); + DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); + } + UBX.state.log_interval = 10*interval; +} + +void UBXSelectMode(uint16_t mode) +{ + DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); + switch(mode){ +#ifdef USE_FLOG + case 0: + Flog->mode = 0; + break; + case 1: + Flog->mode = 1; + break; + case 2: + UBX.mode.filter_noise = true; + break; + case 3: + UBX.mode.filter_noise = false; + break; + case 4: + Flog->startRecording(true); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); + break; + case 5: + Flog->startRecording(false); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); + break; + case 6: + if(Flog->recording == true){ + Flog->stopRecording(); + } + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); + break; +#endif + case 7: + UBX.mode.send_when_new = 1; + break; + case 8: + UBX.mode.send_when_new = 0; + break; + case 9: + if (timeServer.beginListening()) { + UBX.mode.runningNTP = true; + } + break; + case 10: + UBX.mode.runningNTP = false; + break; + case 11: + UBX.mode.forceUTCupdate = true; + break; + case 12: + UBX.mode.forceUTCupdate = false; + break; + case 13: + Settings.latitude = UBX.rec_buffer.values.lat/10; + Settings.longitude = UBX.rec_buffer.values.lon/10; + break; + case 14: + vPortServer.begin(); + UBX.mode.runningVPort = 1; + break; + case 15: + + UBX.mode.runningVPort = 0; + break; + default: + if (mode>1000 && mode <1066) { + + UBXSetRate(mode-1000); + } + break; + } + UBX.mode.send_UI_only = true; + UBXTriggerTele(); +} + + + +bool UBXHandlePOSLLH() +{ + DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); + if (UBX.state.gpsFix>1) { + if (UBX.mode.filter_noise) { + if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat6) { + if(UBX.mode.runningVPort) return; + UBXinitCFG(); + AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); + UBXSerial->flush(); + UBX.state.non_empty_loops = 0; + } +} + + + +void UBXLoop50msec(void) +{ + + if (UBX.mode.runningVPort){ + if(!vPortClient.connected()) { + vPortClient = vPortServer.available(); + } + while(vPortClient.available()) { + byte _newByte = vPortClient.read(); + UBXSerial->write(_newByte); + } + + if (UBX.TCPbufSize!=0){ + vPortClient.write((char*)UBX.TCPbuf, UBX.TCPbufSize); + UBX.TCPbufSize = 0; + } + } + + if(UBX.mode.runningNTP){ + timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000); + } +} + +void UBXLoop(void) +{ + static uint16_t counter; + static bool new_position; + + uint32_t msgType = UBXprocessGPS(); + + switch(msgType){ + case MT_NAV_POSLLH: + new_position = UBXHandlePOSLLH(); + break; + case MT_NAV_STATUS: + UBXHandleSTATUS(); + break; + case MT_NAV_TIME: + UBXHandleTIME(); + break; + default: + UBXHandleOther(); + break; + } + +#ifdef USE_FLOG + if (counter>UBX.state.log_interval) { + if (Flog->recording && new_position) { + UBX.rec_buffer.values.time = Rtc.local_time; + Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); + counter = 0; + } + } +#endif + + counter++; +} + + + + +#ifdef USE_WEBSERVER + + +#ifdef USE_FLOG +#ifdef DEBUG_TASMOTA_SENSOR + const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" + "{s} FLOG next sector for REC: {m} %u {e}" + "{s} %u sector(s) with data at sector: {m} %u {e}"; + const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; +#endif + + const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; + const char kFLOG_STATE0[] PROGMEM = "ready"; + const char kFLOG_STATE1[] PROGMEM = "recording"; + const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; + + const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; + +#endif + const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; + + const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" + "{s} GPS longitude {m}%s{e}" + "{s} GPS altitude {m}%s m{e}" + "{s} GPS hor. Accuracy {m}%s m{e}" + "{s} GPS vert. Accuracy {m}%s m{e}" + "{s} GPS sat-fix status {m}%s{e}"; + + const char kGPSFix0[] PROGMEM = "no fix"; + const char kGPSFix1[] PROGMEM = "dead reckoning only"; + const char kGPSFix2[] PROGMEM = "2D-fix"; + const char kGPSFix3[] PROGMEM = "3D-fix"; + const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; + const char kGPSFix5[] PROGMEM = "Time only fix"; + const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; + + + + +#endif + + + +void UBXShow(bool json) +{ + char lat[12]; + char lon[12]; + char alt[12]; + char hAcc[12]; + char vAcc[12]; + dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); + dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); + dtostrfd((double)UBX.state.last_alt/1000.0f,3,alt); + dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); + dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); + + if (json) { + ResponseAppend_P(PSTR(",\"GPS\":{")); + if (UBX.mode.send_UI_only) { + uint32_t i = UBX.state.log_interval / 10; + ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); + } else { + ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"alt\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, alt, hAcc, vAcc); + } +#ifdef USE_FLOG + ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); +#endif + UBX.mode.send_UI_only = false; +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_GPS, lat, lon, alt, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); + +#ifdef DEBUG_TASMOTA_SENSOR +#ifdef USE_FLOG + WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); + if (Flog->recording) { + WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); + } +#endif +#endif +#ifdef USE_FLOG + if (Flog->ready) { + WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); + } + if (!Flog->recording && Flog->found_saved_data) { + WSContentSend_P(HTTP_BTN_FLOG_DL); + } +#endif + if (UBX.mode.runningNTP) { + WSContentSend_P(HTTP_SNS_NTPSERVER); + } +#endif + } +} + + + + + +bool UBXCmd(void) +{ + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + UBXSelectMode(XdrvMailbox.payload); + Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } + return serviced; +} + + + + + +bool Xsns60(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + UBXDetect(); + } + + if (UBX.mode.init) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_60 == XdrvMailbox.index) { + result = UBXCmd(); + } + break; + case FUNC_EVERY_50_MSECOND: + UBXLoop50msec(); + break; + case FUNC_EVERY_100_MSECOND: +#ifdef USE_FLOG + if (!Flog->running_download) +#endif + { + UBXLoop(); + } + break; +#ifdef USE_FLOG + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/UBX", UBXsendFile); + break; +#endif + case FUNC_JSON_APPEND: + UBXShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: +#ifdef USE_FLOG + if (!Flog->running_download) +#endif + { + UBXShow(0); + } + break; +#endif + } + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +#ifdef USE_SPI +#ifdef USE_NRF24 +#ifdef USE_MIBLE + +#ifdef DEBUG_TASMOTA_SENSOR + #define MINRF_LOG_BUFFER(x) MINRFshowBuffer(x); +#else + #define MINRF_LOG_BUFFER(x) +#endif +# 53 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +#define XSNS_61 61 + +#include + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03 4 + +uint8_t kMINRFSlaveID[4][3] = { 0xC4,0x7C,0x8D, + 0x58,0x2D,0x34, + 0xE7,0x2E,0x00, + 0xA4,0xC1,0x38, + }; + +const char kMINRFSlaveType1[] PROGMEM = "Flora"; +const char kMINRFSlaveType2[] PROGMEM = "MJ_HT_V1"; +const char kMINRFSlaveType3[] PROGMEM = "LYWSD02"; +const char kMINRFSlaveType4[] PROGMEM = "LYWSD03"; +const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4}; + + +const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; +const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; +const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71da7646}; + +const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; + + +const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; +const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; + + +#pragma pack(1) +struct MJ_HT_V1Header_t { + uint8_t padding[3]; + uint8_t mesSize; + uint8_t padding2; + uint16_t uuid; + uint16_t type; + uint8_t padding3[2]; + uint8_t counter; + uint8_t serial[6]; + uint8_t mode; + uint8_t padding5; + uint8_t effectiveDataLength; + }; + +struct FlowerHeader_t { + uint8_t padding[4]; + uint8_t padding2; + uint16_t uuid; + uint8_t mesSize; + uint8_t padding22; + uint16_t uuid2; + uint16_t type; + uint8_t padding3[2]; + uint8_t counter; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + }; + +union floraPacket_t { + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t data; + } T; + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint32_t data:24; + } L; + struct { + uint8_t padding[3]; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint8_t data; + } M; + struct { + uint8_t padding[3]; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t data; + } F; +}; + +union MJ_HT_V1Packet_t { + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t temp; + uint16_t hum; + } TH; + struct { + uint8_t padding[3]; + uint8_t serial[6]; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint8_t battery; + } B; + +}; + +union LYWSD02Packet_t { + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t data; + } TH; +}; + +struct bleAdvPacket_t { + uint8_t pduType; + uint8_t payloadSize; + uint8_t mac[6]; + union { + uint8_t payload[24]; + MJ_HT_V1Header_t header; + FlowerHeader_t flowerHeader; + struct { + uint8_t padding[21]; + uint16_t temp; + uint8_t hum_lb; + } TH; + struct { + uint8_t padding[21]; + uint16_t temp; + } T; + struct { + uint8_t padding[21]; + uint16_t hum; + } H; + struct { + uint8_t padding[21]; + uint8_t battery; + } B; + struct { + uint8_t padding[2]; + uint8_t mode; + uint16_t size; + uint16_t data; + } F_T; + struct { + uint8_t padding[2]; + uint8_t mode; + uint16_t size; + uint16_t data; + uint8_t data2; + } F_L; + struct { + uint8_t padding[2]; + uint8_t mode; + uint16_t size; + uint8_t data; + } F_M; + struct { + uint8_t padding[2]; + uint8_t mode; + uint16_t size; + uint16_t data; + } F_F; + }; +}; + +union FIFO_t{ + bleAdvPacket_t bleAdv; + floraPacket_t floraPacket; + MJ_HT_V1Packet_t MJ_HT_V1Packet; + LYWSD02Packet_t LYWSD02Packet; + uint8_t raw[32]; +}; + +#pragma pack(0) + +struct { + const uint8_t channel[3] = {37,38,39}; + const uint8_t frequency[3] = { 2,26,80}; + + uint16_t timer; + uint8_t currentChan=0; + FIFO_t buffer; + uint8_t packetMode; + +#ifdef DEBUG_TASMOTA_SENSOR + uint8_t streamBuffer[sizeof(buffer)]; + uint8_t lsfrBuffer[sizeof(buffer)]; +#endif + +} MINRF; + +struct mi_sensor_t{ + uint8_t type; + uint8_t serial[6]; + uint8_t showedUp; + float temp; + union { + struct { + float moisture; + float fertility; + uint32_t lux; + }; + struct { + float hum; + uint8_t bat; + }; + }; +}; + +std::vector MIBLEsensors; + + + + +bool MINRFinitBLE(uint8_t _mode) +{ + if (MINRF.timer%1000 == 0){ + NRF24radio.begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_DC]); + NRF24radio.setAutoAck(false); + NRF24radio.setDataRate(RF24_1MBPS); + NRF24radio.disableCRC(); + NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); + NRF24radio.setRetries(0,0); + NRF24radio.setPALevel(RF24_PA_MIN); + NRF24radio.setAddressWidth(4); + + + NRF24radio.powerUp(); + } + if(NRF24radio.isChipConnected()){ + + MINRFchangePacketModeTo(_mode); + return true; + } + + return false; +} + +void MINRFhopChannel() +{ + MINRF.currentChan++; + if(MINRF.currentChan >= sizeof(MINRF.channel)) { + MINRF.currentChan = 0; + } + NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); +} + + + + + + + +bool MINRFreceivePacket(void) +{ + if(!NRF24radio.available()) { + return false; + } + while(NRF24radio.available()) { + + + NRF24radio.read( &MINRF.buffer, sizeof(MINRF.buffer) ); +#ifdef DEBUG_TASMOTA_SENSOR + memcpy(&MINRF.streamBuffer, &MINRF.buffer, sizeof(MINRF.buffer)); +#endif + MINRFswapbuf( sizeof(MINRF.buffer) ); + + + + switch (MINRF.packetMode) { + case 0: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); + break; + case 1: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); + break; + case 2: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); + break; + case 3: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); + break; + case 4: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); + break; + } + + + } + + return true; +} + +#ifdef DEBUG_TASMOTA_SENSOR +void MINRFshowBuffer(uint8_t (&buf)[32]){ + + + + + DEBUG_SENSOR_LOG(PSTR("MINRF: Buffer: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x ") + ,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11], + buf[12],buf[13],buf[14],buf[15],buf[16],buf[17],buf[18],buf[19],buf[20],buf[21],buf[22],buf[23], + buf[24],buf[25],buf[26],buf[27],buf[28],buf[29],buf[30],buf[31] + ); +} +#endif + + + + + + +void MINRFswapbuf(uint8_t len) +{ + uint8_t* buf = (uint8_t*)&MINRF.buffer; + while(len--) { + uint8_t a = *buf; + uint8_t v = 0; + if (a & 0x80) v |= 0x01; + if (a & 0x40) v |= 0x02; + if (a & 0x20) v |= 0x04; + if (a & 0x10) v |= 0x08; + if (a & 0x08) v |= 0x10; + if (a & 0x04) v |= 0x20; + if (a & 0x02) v |= 0x40; + if (a & 0x01) v |= 0x80; + *(buf++) = v; + } +} +# 420 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr) +{ + while(len--) { + uint8_t res = 0; + + for (uint8_t i = 1; i; i <<= 1) { + if (lfsr & 0x01) { + lfsr ^= 0x88; + res |= i; + } + lfsr >>= 1; + } + *(buf++) ^= res; +#ifdef DEBUG_TASMOTA_SENSOR + MINRF.lsfrBuffer[31-len] = lfsr; +#endif + } +} + +void MINRFreverseMAC(uint8_t _mac[]){ + uint8_t _reversedMAC[6]; + for (uint8_t i=0; i<6; i++){ + _reversedMAC[5-i] = _mac[i]; + } + memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); +} + + + + + + +void MINRFchangePacketModeTo(uint8_t _mode) { + uint32_t (_nextchannel) = MINRF.currentChan+1; + if (_nextchannel>2) _nextchannel=0; + + switch(_mode){ + case 0: + NRF24radio.openReadingPipe(0,0x6B7D9171); + break; + case 1: + NRF24radio.openReadingPipe(0,kMINRFFloPDU[_nextchannel]); + break; + case 2: + NRF24radio.openReadingPipe(0,kMINRFMJPDU[_nextchannel]); + break; + case 3: + NRF24radio.openReadingPipe(0,kMINRFL2PDU[_nextchannel]); + break; + case 4: + if(kMINRFL3PDU[_nextchannel]==0xffffffff) break; + NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]); + break; + } + + MINRF.packetMode = _mode; +} +# 485 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ + if(_type==0xff){ + DEBUG_SENSOR_LOG(PSTR("MINRF: will test MAC-type")); + for (uint32_t i=0;i<4;i++){ + if(memcmp(_serial,kMINRFSlaveID+i,3)==0){ + DEBUG_SENSOR_LOG(PSTR("MINRF: MAC is type %u"), i); + _type = i+1; + } + else { + DEBUG_SENSOR_LOG(PSTR("MINRF: MAC-type is unknown")); + } + } + } + if(_type==0xff) return _type; + + DEBUG_SENSOR_LOG(PSTR("MINRF: vector size %u"), MIBLEsensors.size()); + for(uint32_t i=0; i6000){ + DEBUG_SENSOR_LOG(PSTR("MINRF: check for FAKE sensors")); + MINRFpurgeFakeSensors(); + MINRF.timer=0; + } + MINRF.timer++; + + if (!MINRFreceivePacket()){ + + } + + else if(MINRF.buffer.bleAdv.header.uuid==0xfe95){ + MINRF_LOG_BUFFER(MINRF.streamBuffer); + MINRF_LOG_BUFFER(MINRF.lsfrBuffer); + MINRF_LOG_BUFFER(MINRF.buffer.raw); + DEBUG_SENSOR_LOG(PSTR("MINRF: Type: %x"), MINRF.buffer.bleAdv.header.type); + switch(MINRF.buffer.bleAdv.header.type){ + case 0x2050: + DEBUG_SENSOR_LOG(PSTR("MINRF: MJ_HT_V1 Packet")); + break; + case 0x1613:case 0x1614:case 0x1615: + DEBUG_SENSOR_LOG(PSTR("MINRF: Flora Packet")); + break; + default: + DEBUG_SENSOR_LOG(PSTR("MINRF: unknown Packet")); + break; + } + } + else if (MINRF.packetMode == FLORA){ + MINRFhandleFloraPacket(); + } + else if (MINRF.packetMode == MJ_HT_V1){ + MINRFhandleMJ_HT_V1Packet(); + } + else if (MINRF.packetMode == LYWSD02){ + MINRFhandleLYWSD02Packet(); + } + else if (MINRF.packetMode == LYWSD03){ + MINRFhandleLYWSD03Packet(); + } + + + if (MINRF.packetMode == LYWSD03){ + MINRFinitBLE(1); + } + else { + MINRFinitBLE(++MINRF.packetMode); + } + + MINRFhopChannel(); + NRF24radio.startListening(); +} + + + + +const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; +const char HTTP_MINRF_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; +const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; +const char HTTP_MINRF_HL[] PROGMEM = "{s}
{m}
{e}"; + +void MINRFShow(bool json) +{ + if (json) { + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if(MIBLEsensors.at(i).showedUp < 3){ + DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet")); + break; + } + char slave[33]; + sprintf_P(slave,"%s-%02x%02x%02x",kMINRFSlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + + ResponseAppend_P(PSTR(",\"%s\":{"),slave); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + if (MIBLEsensors.at(i).type==FLORA){ + char lux[33]; + char moisture[33]; + char fertility[33]; + dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); + dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + if(MIBLEsensors.at(i).lux!=0xffff){ + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ + ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ + ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); + } + } + if (MIBLEsensors.at(i).type>FLORA){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + if(MIBLEsensors.at(i).hum!=-1.0f){ + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); + } + } + ResponseAppend_P(PSTR("}")); + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_NRF24, NRF24type, NRF24.chipType); + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if(MIBLEsensors.at(i).showedUp < 3){ + DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet")); + break; + } + WSContentSend_PD(HTTP_MINRF_HL); + WSContentSend_PD(HTTP_MINRF_MAC, kMINRFSlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + WSContentSend_PD(HTTP_SNS_TEMP, kMINRFSlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); + } + if (MIBLEsensors.at(i).type==FLORA){ + if(MIBLEsensors.at(i).lux!=0x00ffffff){ + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ + WSContentSend_PD(HTTP_SNS_MOISTURE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ + char fertility[33]; + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + WSContentSend_PD(HTTP_MINRF_FLORA_DATA, kMINRFSlaveType[MIBLEsensors.at(i).type-1], fertility); + } + } + if (MIBLEsensors.at(i).type>FLORA){ + if(MIBLEsensors.at(i).hum!=-1.0f){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + WSContentSend_PD(HTTP_SNS_HUM, kMINRFSlaveType[MIBLEsensors.at(i).type-1], humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + WSContentSend_PD(HTTP_BATTERY, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); + } + } + } +#endif + } +} + + + + + +bool Xsns61(uint8_t function) +{ + bool result = false; + + if (NRF24.chipType) { + switch (function) { + case FUNC_INIT: + MINRFinitBLE(1); + AddLog_P2(LOG_LEVEL_INFO,PSTR("MINRF: started")); + break; + case FUNC_EVERY_50_MSECOND: + MINRF_EVERY_50_MSECOND(); + break; + case FUNC_JSON_APPEND: + MINRFShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MINRFShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_62_MI_HM10.ino" +# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_62_MI_HM10.ino" +#ifdef USE_HM10 + +#define XSNS_62 62 + +#include +#include + +TasmotaSerial *HM10Serial; +#define HM10_BAUDRATE 115200 + +#define HM10_MAX_TASK_NUMBER 12 +uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; + +#define HM10_MAX_RX_BUF 512 +char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; + +struct { + uint8_t current_task_delay; + uint8_t last_command; + uint16_t firmware; + uint32_t period; + uint32_t serialSpeed; + union { + uint32_t time; + uint8_t timebuf[4]; + }; + struct { + uint32_t init:1; + uint32_t pending_task:1; + uint32_t connected:1; + uint32_t subscribed:1; + uint32_t awaitingHT:1; + uint32_t awaitingB:1; + + } mode; + struct { + uint8_t sensor; + + } state; +} HM10; + +#pragma pack(1) +struct { + uint16_t temp; + uint8_t hum; +} LYWSD0x_HT; +#pragma pack(0) + +struct mi_sensor_t{ + uint8_t type; + uint8_t serial[6]; + uint8_t showedUp; + float temp; + union { + struct { + float moisture; + float fertility; + uint16_t lux; + }; + struct { + float hum; + uint8_t bat; + }; + }; +}; + +std::vector MIBLEsensors; + + + + + +#define D_CMND_HM10 "HM10" + +const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; +const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}"; +const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time"; + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03MMC 4 + +uint8_t kHM10SlaveID[4][3] = { 0xC4,0x7C,0x8D, + 0x58,0x2D,0x34, + 0xE7,0x2E,0x00, + 0xA4,0xC1,0x38, + }; + +const char kHM10SlaveType1[] PROGMEM = "Flora"; +const char kHM10SlaveType2[] PROGMEM = "MJ_HT_V1"; +const char kHM10SlaveType3[] PROGMEM = "LYWSD02"; +const char kHM10SlaveType4[] PROGMEM = "LYWSD03"; +const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4}; + + + + + +enum HM10_Commands { + CMND_HM10_DISC_SCAN, + CMND_HM10_AT, + CMND_HM10_PERIOD, + CMND_HM10_BAUD, + CMND_HM10_TIME + }; + + + + + +#define TASK_HM10_NOTASK 0 +#define TASK_HM10_ROLE1 1 +#define TASK_HM10_IMME1 2 +#define TASK_HM10_RENEW 3 +#define TASK_HM10_RESET 4 +#define TASK_HM10_DISC 5 +#define TASK_HM10_CONN 6 +#define TASK_HM10_VERSION 7 +#define TASK_HM10_NAME 8 +#define TASK_HM10_FEEDBACK 9 +#define TASK_HM10_DISCONN 10 +#define TASK_HM10_SUB_L3 11 +#define TASK_HM10_READ_HT 12 +#define TASK_HM10_FINDALLCHARS 13 +#define TASK_HM10_UN_L3 14 +#define TASK_HM10_DELAY_SUB 15 +#define TASK_HM10_READ_BT_L3 16 +#define TASK_HM10_SUB_L2 17 +#define TASK_HM10_UN_L2 18 +#define TASK_HM10_READ_BT_L2 19 +#define TASK_HM10_TIME_L2 20 + +#define TASK_HM10_DONE 99 + + + + + +void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){ + HM10_TASK_LIST[slot][0] = task; + HM10_TASK_LIST[slot][1] = delay; + HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; + HM10.current_task_delay = HM10_TASK_LIST[0][1]; +} + +void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ + HM10.last_command = HM10_TASK_LIST[slot][0]; + HM10_TASK_LIST[slot][0] = task; +} + + + + + +void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); + HM10_Launchtask(TASK_HM10_ROLE1,1,1); + HM10_Launchtask(TASK_HM10_IMME1,2,1); + HM10_Launchtask(TASK_HM10_RESET,3,1); + HM10_Launchtask(TASK_HM10_VERSION,4,10); + HM10_Launchtask(TASK_HM10_DISC,5,50); + } + +void HM10_Discovery_Scan(void) { + HM10_Launchtask(TASK_HM10_DISCONN,0,1); + HM10_Launchtask(TASK_HM10_DISC,1,1); + } + +void HM10_Read_LYWSD03(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); + HM10_Launchtask(TASK_HM10_SUB_L3,2,20); + HM10_Launchtask(TASK_HM10_UN_L3,3,80); + HM10_Launchtask(TASK_HM10_READ_BT_L3,4,5); + HM10_Launchtask(TASK_HM10_DISCONN,5,5); + } + +void HM10_Read_LYWSD02(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); + HM10_Launchtask(TASK_HM10_SUB_L2,2,20); + HM10_Launchtask(TASK_HM10_UN_L2,3,80); + HM10_Launchtask(TASK_HM10_READ_BT_L2,4,5); + HM10_Launchtask(TASK_HM10_DISCONN,5,5); + } + +void HM10_Time_LYWSD02(void) { + HM10_Launchtask(TASK_HM10_DISCONN,0,0); + HM10_Launchtask(TASK_HM10_CONN,1,5); + HM10_Launchtask(TASK_HM10_FEEDBACK,2,35); + HM10_Launchtask(TASK_HM10_TIME_L2,3,20); + HM10_Launchtask(TASK_HM10_DISCONN,4,5); + } +# 231 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_62_MI_HM10.ino" +uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ + if(_type==0xff){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: will test MAC-type")); + for (uint32_t i=0;i<4;i++){ + if(memcmp(_serial,kHM10SlaveID+i,3)==0){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC is type %u"), i); + _type = i+1; + } + else { + DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC-type is unknown")); + } + } + } + if(_type==0xff) return _type; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: vector size %u"), MIBLEsensors.size()); + for(uint32_t i=0; ibegin(HM10.serialSpeed)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start serial communication fixed to 115200 baud"),D_CMND_HM10); + if (HM10Serial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); + } + HM10_Reset(); + HM10.mode.pending_task = 1; + HM10.mode.init = 1; + HM10.period = Settings.tele_period; + DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); + } + return; +} +# 315 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_62_MI_HM10.ino" +void HM10MACStringToBytes(const char* string, uint8_t _mac[]) { + uint32_t index = 0; + while (index < 12) { + char c = string[index]; + uint32_t value = 0; + if(c >= '0' && c <= '9') + value = (c - '0'); + else if (c >= 'A' && c <= 'F') + value = (10 + (c - 'A')); + _mac[(index/2)] += value << (((index + 1) % 2) * 4); + + index++; + } + DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_mac[0],_mac[1],_mac[2],_mac[3],_mac[4],_mac[5]); +} + + + + + + +void HM10ParseResponse(char *buf) { + if (!strncmp(buf,"OK",2)) { + DEBUG_SENSOR_LOG(PSTR("HM10: got OK")); + } + if (!strncmp(buf,"HMSoft",6)) { + const char* _fw = "000"; + memcpy((void *)_fw,(void *)(buf+8),3); + HM10.firmware = atoi(_fw); + DEBUG_SENSOR_LOG(PSTR("HM10: Firmware: %d"), HM10.firmware); + return; + } + char * _pos = strstr(buf, "IS0:"); + if(_pos) { + const char* _mac = "000000000000"; + memcpy((void *)_mac,(void *)(_pos+4),12); + DEBUG_SENSOR_LOG(PSTR("HM10: found Mac: %s"), _mac); + uint8_t _newMacArray[6] = {0}; + HM10MACStringToBytes(_mac, _newMacArray); + DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); + MIBLEgetSensorSlot(_newMacArray, 0xff); + } + if (strstr(buf, "LOST")){ + HM10.mode.connected = false; + } + else { + DEBUG_SENSOR_LOG(PSTR("HM10: empty response")); + } +} + +void HM10readTempHum(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0] != 0 && _buf[1] != 0){ + memcpy(&LYWSD0x_HT,(void *)_buf,3); + DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD0x_HT.temp,LYWSD0x_HT.hum); + uint32_t _slot = HM10.state.sensor; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + static float _tempFloat; + _tempFloat=(float)(LYWSD0x_HT.temp)/100.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).temp=_tempFloat; + HM10.mode.awaitingHT = false; + HM10.current_task_delay = 0; + } + _tempFloat=(float)LYWSD0x_HT.hum; + if(_tempFloat<100){ + MIBLEsensors.at(_slot).hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("LYWSD03: hum updated")); + } + } +} + +bool HM10readBat(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0] != 0){ + DEBUG_SENSOR_LOG(PSTR("HM10: Battery: %u"),_buf[0]); + uint32_t _slot = HM10.state.sensor; + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + if(_buf[0]<101){ + MIBLEsensors.at(_slot).bat=_buf[0]; + return true; + } + } + return false; +} + + + + + +bool HM10SerialHandleFeedback(){ + bool success = false; + uint32_t i = 0; + char ret[HM10_MAX_RX_BUF] = {0}; + + + while(HM10Serial->available()) { + + if(iread(); + } + i++; + success = true; + } + if(HM10.mode.awaitingHT) { + if (HM10.mode.connected) HM10readTempHum(ret); + } + else if(HM10.mode.awaitingB) { + if (HM10.mode.connected) { + if (HM10readBat(ret)){ + HM10.mode.awaitingB = false; + HM10.current_task_delay = 0; + } + } + } + else if(success) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s response: %s"),D_CMND_HM10, (char *)ret); + HM10ParseResponse(ret); + } + else { + + } + return success; +} + + + + + +void HM10_TaskEvery100ms(){ + if (HM10.current_task_delay == 0) { + uint8_t i = 0; + bool runningTaskLoop = true; + while (runningTaskLoop) { + switch(HM10_TASK_LIST[i][0]) { + case TASK_HM10_ROLE1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+ROLE1"); + break; + case TASK_HM10_IMME1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set imme to 1"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+IMME1"); + break; + case TASK_HM10_DISC: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start discovery"),D_CMND_HM10); + HM10.current_task_delay = 35; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+DISC?"); + break; + case TASK_HM10_VERSION: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read version"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+VERR?"); + break; + case TASK_HM10_NAME: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read name"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+NAME?"); + break; + case TASK_HM10_CONN: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s connect"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + char _con[20]; + sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors.at(HM10.state.sensor).serial[0],MIBLEsensors.at(HM10.state.sensor).serial[1],MIBLEsensors.at(HM10.state.sensor).serial[2],MIBLEsensors.at(HM10.state.sensor).serial[3],MIBLEsensors.at(HM10.state.sensor).serial[4],MIBLEsensors.at(HM10.state.sensor).serial[5]); + HM10Serial->write(_con); + HM10.mode.awaitingB = false; + HM10.mode.connected = true; + break; + case TASK_HM10_DISCONN: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s disconnect"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT"); + break; + case TASK_HM10_RESET: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10); + HM10Serial->write("AT+RESET"); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + break; + case TASK_HM10_SUB_L3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); + HM10.current_task_delay = 25; + HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); + runningTaskLoop = false; + HM10Serial->write("AT+NOTIFY_ON0037"); + break; + case TASK_HM10_UN_L3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaitingHT = false; + HM10Serial->write("AT+NOTIFYOFF0037"); + break; + case TASK_HM10_SUB_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); + HM10.current_task_delay = 25; + HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); + runningTaskLoop = false; + HM10Serial->write("AT+NOTIFY_ON003C"); + break; + case TASK_HM10_UN_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaitingHT = false; + HM10Serial->write("AT+NOTIFYOFF003C"); + break; + case TASK_HM10_TIME_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set time"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.time = Rtc.utc_time; + HM10Serial->write("AT+SEND_DATAWR002F"); + HM10Serial->write(HM10.timebuf,4); + HM10Serial->write(Rtc.time_timezone / 60); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60)); + break; + case TASK_HM10_READ_HT: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0036"),D_CMND_HM10); + HM10.current_task_delay = 0; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0036?"); + HM10.mode.awaitingHT = true; + break; + case TASK_HM10_READ_BT_L3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 003A"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA003A?"); + HM10.mode.awaitingB = true; + break; + case TASK_HM10_READ_BT_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0043"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0043?"); + HM10.mode.awaitingB = true; + break; + + + + + + + + case TASK_HM10_FEEDBACK: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10); + HM10SerialHandleFeedback(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; + runningTaskLoop = false; + break; + case TASK_HM10_DELAY_SUB: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start reading"),D_CMND_HM10); + HM10SerialHandleFeedback(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; + HM10.mode.awaitingHT = true; + runningTaskLoop = false; + break; + case TASK_HM10_DONE: + + + if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { + DEBUG_SENSOR_LOG(PSTR("%sno Tasks left"),D_CMND_HM10); + DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i); + for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { + DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j); + HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; + HM10_TASK_LIST[j][1] = 0; + } + runningTaskLoop = false; + HM10.mode.pending_task = 0; + break; + } + } + i++; + } + } + else { + HM10.current_task_delay--; + } +} + + + + + + +void HM10EverySecond(){ + if(HM10.firmware == 0) return; + if(HM10.mode.pending_task == 1) return; + if (MIBLEsensors.size()==0) return; + + static uint32_t _counter = 0; + static uint32_t _nextSensorSlot = 0; + if(_counter==0) { + HM10.state.sensor = _nextSensorSlot; + _nextSensorSlot++; + if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD03MMC) { + HM10.mode.pending_task = 1; + HM10_Read_LYWSD03(); + } + if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD02) { + HM10.mode.pending_task = 1; + HM10_Read_LYWSD02(); + } + if (HM10.state.sensor==MIBLEsensors.size()-1) { + _nextSensorSlot= 0; + _counter++; + } + DEBUG_SENSOR_LOG(PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); + } + else _counter++; + if (_counter>HM10.period) _counter = 0; +} + +bool HM10Cmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_HM10); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_HM10), disp_len)) { + uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kHM10_Commands); + switch (command_code) { + case CMND_HM10_PERIOD: + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_HM10_PERIOD) { HM10.period = XdrvMailbox.payload; } + } + else { + if (command_code == CMND_HM10_PERIOD) XdrvMailbox.payload = HM10.period; + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_BAUD: + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_HM10_BAUD) { + HM10.serialSpeed = XdrvMailbox.payload; + HM10Serial->begin(HM10.serialSpeed); + } + } + else { + if (command_code == CMND_HM10_BAUD) XdrvMailbox.payload = HM10.serialSpeed; + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_TIME: + if (XdrvMailbox.data_len > 0) { + if(MIBLEsensors.size()>XdrvMailbox.payload){ + if(MIBLEsensors.at(XdrvMailbox.payload).type == LYWSD02){ + HM10.state.sensor = XdrvMailbox.payload; + HM10_Time_LYWSD02(); + } + } + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_AT: + HM10Serial->write("AT"); + if (strlen(XdrvMailbox.data)!=0) { + HM10Serial->write("+"); + HM10Serial->write(XdrvMailbox.data); + Response_P(S_JSON_HM10_COMMAND, ":AT+",XdrvMailbox.data); + } + else Response_P(S_JSON_HM10_COMMAND, ":AT",XdrvMailbox.data); + break; + case CMND_HM10_DISC_SCAN: + if (command_code == CMND_HM10_DISC_SCAN) { HM10_Discovery_Scan(); } + Response_P(S_JSON_HM10_COMMAND, command, ""); + break; + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + + + +const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}"; +const char HTTP_HM10_SERIAL[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; +const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; +const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; +const char HTTP_HM10_HL[] PROGMEM = "{s}
{m}
{e}"; + +void HM10Show(bool json) +{ + if (json) { + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + char slave[33]; + sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + + ResponseAppend_P(PSTR(",\"%s\":{"),slave); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + if (MIBLEsensors.at(i).type==FLORA){ + char lux[33]; + char moisture[33]; + char fertility[33]; + dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); + dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + if(MIBLEsensors.at(i).lux!=0xffff){ + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ + ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ + ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); + } + } + if (MIBLEsensors.at(i).type>FLORA){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + if(MIBLEsensors.at(i).hum!=-1.0f){ + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); + } + } + ResponseAppend_P(PSTR("}")); + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_HM10, HM10.firmware); + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + WSContentSend_PD(HTTP_HM10_HL); + WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); + } + if (MIBLEsensors.at(i).type==FLORA){ + if(MIBLEsensors.at(i).lux!=0xffff){ + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ + WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ + char fertility[33]; + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors.at(i).type-1], fertility); + } + } + if (MIBLEsensors.at(i).type>FLORA){ + if(MIBLEsensors.at(i).hum!=-1.0f){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); + } + } + } +#endif + } +} + + + + + +bool Xsns62(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_HM10_RX] < 99) && (pin[GPIO_HM10_TX] < 99)) { + switch (function) { + case FUNC_INIT: + HM10SerialInit(); + break; + case FUNC_EVERY_50_MSECOND: + HM10SerialHandleFeedback(); + break; + case FUNC_EVERY_100_MSECOND: + if (HM10_TASK_LIST[0][0] != TASK_HM10_NOTASK) { + HM10_TaskEvery100ms(); + } + break; + case FUNC_EVERY_SECOND: + HM10EverySecond(); + break; + case FUNC_COMMAND: + result = HM10Cmd(); + break; + case FUNC_JSON_APPEND: + HM10Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HM10Show(0); + break; +#endif + } + } + return result; +} +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_64_aht10.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_64_aht10.ino" +#ifdef USE_I2C +#ifdef USE_AHT10 + + + + + + +#define XSNS_64 64 +#define XI2C_43 43 + +#define AHT10_ADDR 0x38 + +unsigned char eSensorCalibrateCmd[3] = {0xE1, 0x08, 0x00}; +unsigned char eSensorNormalCmd[3] = {0xA8, 0x00, 0x00}; +unsigned char eSensorMeasureCmd[3] = {0xAC, 0x33, 0x00}; +unsigned char eSensorResetCmd = 0xBA; + +struct AHT10 { + float humidity = NAN; + float temperature = NAN; + uint8_t valid = 0; + uint8_t count = 0; + char name[6] = "AHT10"; +} AHT10; + +bool begin() +{ + Wire.begin(AHT10_ADDR); + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorCalibrateCmd, 3); + Wire.endTransmission(); + delay(500); + + if((readStatus() & 0x68) == 0x08) + return true; + else + { + return false; + } +} + +bool AHT10Read(void) +{ + unsigned long result, temp[6]; + + if (AHT10.valid) { AHT10.valid--; } + + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorMeasureCmd, 3); + Wire.endTransmission(); + delay(100); + + Wire.requestFrom(AHT10_ADDR, 6); + for(unsigned char i = 0; Wire.available() > 0; i++) + { + temp[i] = Wire.read(); + } + + AHT10.humidity = (((temp[1] << 16) | (temp[2] << 8) | temp[3]) >> 4)* 100 / 1048576; + AHT10.temperature = ((200 * (((temp[3] & 0x0F) << 16) | (temp[4] << 8) | temp[5])) / 1048576) - 50; + + if (isnan(AHT10.temperature) || isnan(AHT10.humidity)) { return false; } + + AHT10.valid = SENSOR_MAX_MISS; + return true; +} + + +unsigned char readStatus(void) +{ + unsigned char result = 0; + + Wire.requestFrom(AHT10_ADDR, 1); + result = Wire.read(); + return result; +} + +void AHT10Detect(void) +{ + if (I2cActive(AHT10_ADDR)) + { + return; + } + + if (begin()) + { + I2cSetActiveFound(AHT10_ADDR, AHT10.name); + AHT10.count = 1; + } +} + +void AHT10EverySecond(void) +{ + if (uptime &1) { + + if (!AHT10Read()) { + AddLogMissed(AHT10.name, AHT10.valid); + } + } +} + +void AHT10Show(bool json) +{ + if (AHT10.valid) { + char temperature[33]; + dtostrfd(AHT10.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(AHT10.humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, AHT10.name, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, AHT10.temperature); + KnxSensor(KNX_HUMIDITY, AHT10.humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, AHT10.name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, AHT10.name, humidity); +#endif + } + } +} + + + + + +bool Xsns64(uint8_t function) +{ + if (!I2cEnabled(XI2C_43)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + AHT10Detect(); + } + else if (AHT10.count) { + switch (function) { + case FUNC_EVERY_SECOND: + AHT10EverySecond(); + break; + case FUNC_JSON_APPEND: + AHT10Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AHT10Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_91_prometheus.ino" +# 22 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_91_prometheus.ino" +#ifdef USE_PROMETHEUS + + + + +#define XSNS_91 91 + +void HandleMetrics(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR("Prometheus")); + + WSContentBegin(200, CT_PLAIN); + + + char parameter[FLOATSZ]; + + if (global_temperature != 9999) { + dtostrfd(global_temperature, Settings.flag2.temperature_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_temperature gauge\nglobal_temperature %s\n"), parameter); + } + if (global_humidity != 0) { + dtostrfd(global_humidity, Settings.flag2.humidity_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_humidity gauge\nglobal_humidity %s\n"), parameter); + } + if (global_pressure != 0) { + dtostrfd(global_pressure, Settings.flag2.pressure_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_pressure gauge\nglobal_pressure %s\n"), parameter); + } + +#ifdef USE_ENERGY_SENSOR + dtostrfd(Energy.voltage[0], Settings.flag2.voltage_resolution, parameter); + WSContentSend_P(PSTR("# TYPE voltage gauge\nvoltage %s\n"), parameter); + dtostrfd(Energy.current[0], Settings.flag2.current_resolution, parameter); + WSContentSend_P(PSTR("# TYPE current gauge\ncurrent %s\n"), parameter); + dtostrfd(Energy.active_power[0], Settings.flag2.wattage_resolution, parameter); + WSContentSend_P(PSTR("# TYPE active_power gauge\nactive_power %s\n"), parameter); + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_daily gauge\nenergy_daily %s\n"), parameter); + dtostrfd(Energy.total, Settings.flag2.energy_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_total counter\nenergy_total %s\n"), parameter); +#endif +# 80 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_91_prometheus.ino" + WSContentEnd(); +} + + + + + +bool Xsns91(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/metrics", HandleMetrics); + break; + } + return result; +} + +#endif +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_interface.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_interface.ino" +#ifdef XFUNC_PTR_IN_ROM +bool (* const xsns_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xsns_func_ptr[])(uint8_t) = { +#endif + +#ifdef XSNS_01 + &Xsns01, +#endif + +#ifdef XSNS_02 + &Xsns02, +#endif + +#ifdef XSNS_03 + &Xsns03, +#endif + +#ifdef XSNS_04 + &Xsns04, +#endif + +#ifdef XSNS_05 + &Xsns05, +#endif + +#ifdef XSNS_06 + &Xsns06, +#endif + +#ifdef XSNS_07 + &Xsns07, +#endif + +#ifdef XSNS_08 + &Xsns08, +#endif + +#ifdef XSNS_09 + &Xsns09, +#endif + +#ifdef XSNS_10 + &Xsns10, +#endif + +#ifdef XSNS_11 + &Xsns11, +#endif + +#ifdef XSNS_12 + &Xsns12, +#endif + +#ifdef XSNS_13 + &Xsns13, +#endif + +#ifdef XSNS_14 + &Xsns14, +#endif + +#ifdef XSNS_15 + &Xsns15, +#endif + +#ifdef XSNS_16 + &Xsns16, +#endif + +#ifdef XSNS_17 + &Xsns17, +#endif + +#ifdef XSNS_18 + &Xsns18, +#endif + +#ifdef XSNS_19 + &Xsns19, +#endif + +#ifdef XSNS_20 + &Xsns20, +#endif + +#ifdef XSNS_21 + &Xsns21, +#endif + +#ifdef XSNS_22 + &Xsns22, +#endif + +#ifdef XSNS_23 + &Xsns23, +#endif + +#ifdef XSNS_24 + &Xsns24, +#endif + +#ifdef XSNS_25 + &Xsns25, +#endif + +#ifdef XSNS_26 + &Xsns26, +#endif + +#ifdef XSNS_27 + &Xsns27, +#endif + +#ifdef XSNS_28 + &Xsns28, +#endif + +#ifdef XSNS_29 + &Xsns29, +#endif + +#ifdef XSNS_30 + &Xsns30, +#endif + +#ifdef XSNS_31 + &Xsns31, +#endif + +#ifdef XSNS_32 + &Xsns32, +#endif + +#ifdef XSNS_33 + &Xsns33, +#endif + +#ifdef XSNS_34 + &Xsns34, +#endif + +#ifdef XSNS_35 + &Xsns35, +#endif + +#ifdef XSNS_36 + &Xsns36, +#endif + +#ifdef XSNS_37 + &Xsns37, +#endif + +#ifdef XSNS_38 + &Xsns38, +#endif + +#ifdef XSNS_39 + &Xsns39, +#endif + +#ifdef XSNS_40 + &Xsns40, +#endif + +#ifdef XSNS_41 + &Xsns41, +#endif + +#ifdef XSNS_42 + &Xsns42, +#endif + +#ifdef XSNS_43 + &Xsns43, +#endif + +#ifdef XSNS_44 + &Xsns44, +#endif + +#ifdef XSNS_45 + &Xsns45, +#endif + +#ifdef XSNS_46 + &Xsns46, +#endif + +#ifdef XSNS_47 + &Xsns47, +#endif + +#ifdef XSNS_48 + &Xsns48, +#endif + +#ifdef XSNS_49 + &Xsns49, +#endif + +#ifdef XSNS_50 + &Xsns50, +#endif + +#ifdef XSNS_51 + &Xsns51, +#endif + +#ifdef XSNS_52 + &Xsns52, +#endif + +#ifdef XSNS_53 + &Xsns53, +#endif + +#ifdef XSNS_54 + &Xsns54, +#endif + +#ifdef XSNS_55 + &Xsns55, +#endif + +#ifdef XSNS_56 + &Xsns56, +#endif + +#ifdef XSNS_57 + &Xsns57, +#endif + +#ifdef XSNS_58 + &Xsns58, +#endif + +#ifdef XSNS_59 + &Xsns59, +#endif + +#ifdef XSNS_60 + &Xsns60, +#endif + +#ifdef XSNS_61 + &Xsns61, +#endif + +#ifdef XSNS_62 + &Xsns62, +#endif + +#ifdef XSNS_63 + &Xsns63, +#endif + +#ifdef XSNS_64 + &Xsns64, +#endif + +#ifdef XSNS_65 + &Xsns65, +#endif + +#ifdef XSNS_66 + &Xsns66, +#endif + +#ifdef XSNS_67 + &Xsns67, +#endif + +#ifdef XSNS_68 + &Xsns68, +#endif + +#ifdef XSNS_69 + &Xsns69, +#endif + +#ifdef XSNS_70 + &Xsns70, +#endif + +#ifdef XSNS_71 + &Xsns71, +#endif + +#ifdef XSNS_72 + &Xsns72, +#endif + +#ifdef XSNS_73 + &Xsns73, +#endif + +#ifdef XSNS_74 + &Xsns74, +#endif + +#ifdef XSNS_75 + &Xsns75, +#endif + +#ifdef XSNS_76 + &Xsns76, +#endif + +#ifdef XSNS_77 + &Xsns77, +#endif + +#ifdef XSNS_78 + &Xsns78, +#endif + +#ifdef XSNS_79 + &Xsns79, +#endif + +#ifdef XSNS_80 + &Xsns80, +#endif + +#ifdef XSNS_81 + &Xsns81, +#endif + +#ifdef XSNS_82 + &Xsns82, +#endif + +#ifdef XSNS_83 + &Xsns83, +#endif + +#ifdef XSNS_84 + &Xsns84, +#endif + +#ifdef XSNS_85 + &Xsns85, +#endif + +#ifdef XSNS_86 + &Xsns86, +#endif + +#ifdef XSNS_87 + &Xsns87, +#endif + +#ifdef XSNS_88 + &Xsns88, +#endif + +#ifdef XSNS_89 + &Xsns89, +#endif + +#ifdef XSNS_90 + &Xsns90, +#endif + +#ifdef XSNS_91 + &Xsns91, +#endif + +#ifdef XSNS_92 + &Xsns92, +#endif + +#ifdef XSNS_93 + &Xsns93, +#endif + +#ifdef XSNS_94 + &Xsns94, +#endif + +#ifdef XSNS_95 + &Xsns95, +#endif + +#ifdef XSNS_96 + &Xsns96, +#endif + +#ifdef XSNS_97 + &Xsns97, +#endif + +#ifdef XSNS_98 + &Xsns98, +#endif + +#ifdef XSNS_99 + &Xsns99 +#endif +}; + +const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); + + + + + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXsnsList[] PROGMEM = { +#else +const uint8_t kXsnsList[] = { +#endif + +#ifdef XSNS_01 + XSNS_01, +#endif + +#ifdef XSNS_02 + XSNS_02, +#endif + +#ifdef XSNS_03 + XSNS_03, +#endif + +#ifdef XSNS_04 + XSNS_04, +#endif + +#ifdef XSNS_05 + XSNS_05, +#endif + +#ifdef XSNS_06 + XSNS_06, +#endif + +#ifdef XSNS_07 + XSNS_07, +#endif + +#ifdef XSNS_08 + XSNS_08, +#endif + +#ifdef XSNS_09 + XSNS_09, +#endif + +#ifdef XSNS_10 + XSNS_10, +#endif + +#ifdef XSNS_11 + XSNS_11, +#endif + +#ifdef XSNS_12 + XSNS_12, +#endif + +#ifdef XSNS_13 + XSNS_13, +#endif + +#ifdef XSNS_14 + XSNS_14, +#endif + +#ifdef XSNS_15 + XSNS_15, +#endif + +#ifdef XSNS_16 + XSNS_16, +#endif + +#ifdef XSNS_17 + XSNS_17, +#endif + +#ifdef XSNS_18 + XSNS_18, +#endif + +#ifdef XSNS_19 + XSNS_19, +#endif + +#ifdef XSNS_20 + XSNS_20, +#endif + +#ifdef XSNS_21 + XSNS_21, +#endif + +#ifdef XSNS_22 + XSNS_22, +#endif + +#ifdef XSNS_23 + XSNS_23, +#endif + +#ifdef XSNS_24 + XSNS_24, +#endif + +#ifdef XSNS_25 + XSNS_25, +#endif + +#ifdef XSNS_26 + XSNS_26, +#endif + +#ifdef XSNS_27 + XSNS_27, +#endif + +#ifdef XSNS_28 + XSNS_28, +#endif + +#ifdef XSNS_29 + XSNS_29, +#endif + +#ifdef XSNS_30 + XSNS_30, +#endif + +#ifdef XSNS_31 + XSNS_31, +#endif + +#ifdef XSNS_32 + XSNS_32, +#endif + +#ifdef XSNS_33 + XSNS_33, +#endif + +#ifdef XSNS_34 + XSNS_34, +#endif + +#ifdef XSNS_35 + XSNS_35, +#endif + +#ifdef XSNS_36 + XSNS_36, +#endif + +#ifdef XSNS_37 + XSNS_37, +#endif + +#ifdef XSNS_38 + XSNS_38, +#endif + +#ifdef XSNS_39 + XSNS_39, +#endif + +#ifdef XSNS_40 + XSNS_40, +#endif + +#ifdef XSNS_41 + XSNS_41, +#endif + +#ifdef XSNS_42 + XSNS_42, +#endif + +#ifdef XSNS_43 + XSNS_43, +#endif + +#ifdef XSNS_44 + XSNS_44, +#endif + +#ifdef XSNS_45 + XSNS_45, +#endif + +#ifdef XSNS_46 + XSNS_46, +#endif + +#ifdef XSNS_47 + XSNS_47, +#endif + +#ifdef XSNS_48 + XSNS_48, +#endif + +#ifdef XSNS_49 + XSNS_49, +#endif + +#ifdef XSNS_50 + XSNS_50, +#endif + +#ifdef XSNS_51 + XSNS_51, +#endif + +#ifdef XSNS_52 + XSNS_52, +#endif + +#ifdef XSNS_53 + XSNS_53, +#endif + +#ifdef XSNS_54 + XSNS_54, +#endif + +#ifdef XSNS_55 + XSNS_55, +#endif + +#ifdef XSNS_56 + XSNS_56, +#endif + +#ifdef XSNS_57 + XSNS_57, +#endif + +#ifdef XSNS_58 + XSNS_58, +#endif + +#ifdef XSNS_59 + XSNS_59, +#endif + +#ifdef XSNS_60 + XSNS_60, +#endif + +#ifdef XSNS_61 + XSNS_61, +#endif + +#ifdef XSNS_62 + XSNS_62, +#endif + +#ifdef XSNS_63 + XSNS_63, +#endif + +#ifdef XSNS_64 + XSNS_64, +#endif + +#ifdef XSNS_65 + XSNS_65, +#endif + +#ifdef XSNS_66 + XSNS_66, +#endif + +#ifdef XSNS_67 + XSNS_67, +#endif + +#ifdef XSNS_68 + XSNS_68, +#endif + +#ifdef XSNS_69 + XSNS_69, +#endif + +#ifdef XSNS_70 + XSNS_70, +#endif + +#ifdef XSNS_71 + XSNS_71, +#endif + +#ifdef XSNS_72 + XSNS_72, +#endif + +#ifdef XSNS_73 + XSNS_73, +#endif + +#ifdef XSNS_74 + XSNS_74, +#endif + +#ifdef XSNS_75 + XSNS_75, +#endif + +#ifdef XSNS_76 + XSNS_76, +#endif + +#ifdef XSNS_77 + XSNS_77, +#endif + +#ifdef XSNS_78 + XSNS_78, +#endif + +#ifdef XSNS_79 + XSNS_79, +#endif + +#ifdef XSNS_80 + XSNS_80, +#endif + +#ifdef XSNS_81 + XSNS_81, +#endif + +#ifdef XSNS_82 + XSNS_82, +#endif + +#ifdef XSNS_83 + XSNS_83, +#endif + +#ifdef XSNS_84 + XSNS_84, +#endif + +#ifdef XSNS_85 + XSNS_85, +#endif + +#ifdef XSNS_86 + XSNS_86, +#endif + +#ifdef XSNS_87 + XSNS_87, +#endif + +#ifdef XSNS_88 + XSNS_88, +#endif + +#ifdef XSNS_89 + XSNS_89, +#endif + +#ifdef XSNS_90 + XSNS_90, +#endif + +#ifdef XSNS_91 + XSNS_91, +#endif + +#ifdef XSNS_92 + XSNS_92, +#endif + +#ifdef XSNS_93 + XSNS_93, +#endif + +#ifdef XSNS_94 + XSNS_94, +#endif + +#ifdef XSNS_95 + XSNS_95, +#endif + +#ifdef XSNS_96 + XSNS_96, +#endif + +#ifdef XSNS_97 + XSNS_97, +#endif + +#ifdef XSNS_98 + XSNS_98, +#endif + +#ifdef XSNS_99 + XSNS_99 +#endif +}; + + + +bool XsnsEnabled(uint32_t sns_index) +{ + if (sns_index < sizeof(kXsnsList)) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t index = pgm_read_byte(kXsnsList + sns_index); +#else + uint32_t index = kXsnsList[sns_index]; +#endif + return bitRead(Settings.sensors[index / 32], index % 32); + } + return true; +} + +void XsnsSensorState(void) +{ + ResponseAppend_P(PSTR("\"")); + for (uint32_t i = 0; i < sizeof(kXsnsList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t sensorid = pgm_read_byte(kXsnsList + i); +#else + uint32_t sensorid = kXsnsList[i]; +#endif + bool disabled = false; + if (sensorid < MAX_XSNS_DRIVERS) { + disabled = !bitRead(Settings.sensors[sensorid / 32], sensorid % 32); + } + ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", sensorid); + } + ResponseAppend_P(PSTR("\"")); +} + + + + + +bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) +{ + xsns_index++; + if (xsns_index == xsns_present) { xsns_index = 0; } + +#ifndef USE_DEBUG_DRIVER + if (FUNC_WEB_SENSOR == Function) { +#endif + uint32_t max_disabled = xsns_present; + while (!XsnsEnabled(xsns_index) && max_disabled--) { + xsns_index++; + if (xsns_index == xsns_present) { xsns_index = 0; } + } +#ifndef USE_DEBUG_DRIVER + } +#endif + + return xsns_func_ptr[xsns_index](Function); +} + +bool XsnsCall(uint8_t Function) +{ + bool result = false; + + DEBUG_TRACE_LOG(PSTR("SNS: %d"), Function); + +#ifdef PROFILE_XSNS_EVERY_SECOND + uint32_t profile_start_millis = millis(); +#endif + + for (uint32_t x = 0; x < xsns_present; x++) { +#ifdef USE_DEBUG_DRIVER + if (XsnsEnabled(x)) { +#endif + + if ((FUNC_WEB_SENSOR == Function) && !XsnsEnabled(x)) { continue; } + +#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND + uint32_t profile_start_millis = millis(); +#endif + result = xsns_func_ptr[x](Function); + +#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); + } + } +#endif + + if (result && ((FUNC_COMMAND == Function) || + (FUNC_PIN_STATE == Function) || + (FUNC_COMMAND_SENSOR == Function) + )) { + break; + } +#ifdef USE_DEBUG_DRIVER + } +#endif + } + +#ifdef PROFILE_XSNS_EVERY_SECOND + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); + } + } +#endif + + return result; +} +# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xx2c_interface.ino" +# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xx2c_interface.ino" +#ifdef USE_I2C + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kI2cList[] PROGMEM = { +#else +const uint8_t kI2cList[] = { +#endif + +#ifdef XI2C_01 + XI2C_01, +#endif + +#ifdef XI2C_02 + XI2C_02, +#endif + +#ifdef XI2C_03 + XI2C_03, +#endif + +#ifdef XI2C_04 + XI2C_04, +#endif + +#ifdef XI2C_05 + XI2C_05, +#endif + +#ifdef XI2C_06 + XI2C_06, +#endif + +#ifdef XI2C_07 + XI2C_07, +#endif + +#ifdef XI2C_08 + XI2C_08, +#endif + +#ifdef XI2C_09 + XI2C_09, +#endif + +#ifdef XI2C_10 + XI2C_10, +#endif + +#ifdef XI2C_11 + XI2C_11, +#endif + +#ifdef XI2C_12 + XI2C_12, +#endif + +#ifdef XI2C_13 + XI2C_13, +#endif + +#ifdef XI2C_14 + XI2C_14, +#endif + +#ifdef XI2C_15 + XI2C_15, +#endif + +#ifdef XI2C_16 + XI2C_16, +#endif + +#ifdef XI2C_17 + XI2C_17, +#endif + +#ifdef XI2C_18 + XI2C_18, +#endif + +#ifdef XI2C_19 + XI2C_19, +#endif + +#ifdef XI2C_20 + XI2C_20, +#endif + +#ifdef XI2C_21 + XI2C_21, +#endif + +#ifdef XI2C_22 + XI2C_22, +#endif + +#ifdef XI2C_23 + XI2C_23, +#endif + +#ifdef XI2C_24 + XI2C_24, +#endif + +#ifdef XI2C_25 + XI2C_25, +#endif + +#ifdef XI2C_26 + XI2C_26, +#endif + +#ifdef XI2C_27 + XI2C_27, +#endif + +#ifdef XI2C_28 + XI2C_28, +#endif + +#ifdef XI2C_29 + XI2C_29, +#endif + +#ifdef XI2C_30 + XI2C_30, +#endif + +#ifdef XI2C_31 + XI2C_31, +#endif + +#ifdef XI2C_32 + XI2C_32, +#endif + +#ifdef XI2C_33 + XI2C_33, +#endif + +#ifdef XI2C_34 + XI2C_34, +#endif + +#ifdef XI2C_35 + XI2C_35, +#endif + +#ifdef XI2C_36 + XI2C_36, +#endif + +#ifdef XI2C_37 + XI2C_37, +#endif + +#ifdef XI2C_38 + XI2C_38, +#endif + +#ifdef XI2C_39 + XI2C_39, +#endif + +#ifdef XI2C_40 + XI2C_40, +#endif + +#ifdef XI2C_41 + XI2C_41, +#endif + +#ifdef XI2C_42 + XI2C_42, +#endif + +#ifdef XI2C_43 + XI2C_43, +#endif + +#ifdef XI2C_44 + XI2C_44, +#endif + +#ifdef XI2C_45 + XI2C_45, +#endif + +#ifdef XI2C_46 + XI2C_46, +#endif + +#ifdef XI2C_47 + XI2C_47, +#endif + +#ifdef XI2C_48 + XI2C_48, +#endif + +#ifdef XI2C_49 + XI2C_49, +#endif + +#ifdef XI2C_50 + XI2C_50, +#endif + +#ifdef XI2C_51 + XI2C_51, +#endif + +#ifdef XI2C_52 + XI2C_52, +#endif + +#ifdef XI2C_53 + XI2C_53, +#endif + +#ifdef XI2C_54 + XI2C_54, +#endif + +#ifdef XI2C_55 + XI2C_55, +#endif + +#ifdef XI2C_56 + XI2C_56, +#endif + +#ifdef XI2C_57 + XI2C_57, +#endif + +#ifdef XI2C_58 + XI2C_58, +#endif + +#ifdef XI2C_59 + XI2C_59, +#endif + +#ifdef XI2C_60 + XI2C_60, +#endif + +#ifdef XI2C_61 + XI2C_61, +#endif + +#ifdef XI2C_62 + XI2C_62, +#endif + +#ifdef XI2C_63 + XI2C_63, +#endif + +#ifdef XI2C_64 + XI2C_64, +#endif + +#ifdef XI2C_65 + XI2C_65, +#endif + +#ifdef XI2C_66 + XI2C_66, +#endif + +#ifdef XI2C_67 + XI2C_67, +#endif + +#ifdef XI2C_68 + XI2C_68, +#endif + +#ifdef XI2C_69 + XI2C_69, +#endif + +#ifdef XI2C_70 + XI2C_70, +#endif + +#ifdef XI2C_71 + XI2C_71, +#endif + +#ifdef XI2C_72 + XI2C_72, +#endif + +#ifdef XI2C_73 + XI2C_73, +#endif + +#ifdef XI2C_74 + XI2C_74, +#endif + +#ifdef XI2C_75 + XI2C_75, +#endif + +#ifdef XI2C_76 + XI2C_76, +#endif + +#ifdef XI2C_77 + XI2C_77, +#endif + +#ifdef XI2C_78 + XI2C_78, +#endif + +#ifdef XI2C_79 + XI2C_79, +#endif + +#ifdef XI2C_80 + XI2C_80, +#endif + +#ifdef XI2C_81 + XI2C_81, +#endif + +#ifdef XI2C_82 + XI2C_82, +#endif + +#ifdef XI2C_83 + XI2C_83, +#endif + +#ifdef XI2C_84 + XI2C_84, +#endif + +#ifdef XI2C_85 + XI2C_85, +#endif + +#ifdef XI2C_86 + XI2C_86, +#endif + +#ifdef XI2C_87 + XI2C_87, +#endif + +#ifdef XI2C_88 + XI2C_88, +#endif + +#ifdef XI2C_89 + XI2C_89, +#endif + +#ifdef XI2C_90 + XI2C_90, +#endif + +#ifdef XI2C_91 + XI2C_91, +#endif + +#ifdef XI2C_92 + XI2C_92, +#endif + +#ifdef XI2C_93 + XI2C_93, +#endif + +#ifdef XI2C_94 + XI2C_94, +#endif + +#ifdef XI2C_95 + XI2C_95, +#endif + +#ifdef XI2C_96 + XI2C_96 +#endif +}; + + + +bool I2cEnabled(uint32_t i2c_index) +{ + return (i2c_flg && bitRead(Settings.i2c_drivers[i2c_index / 32], i2c_index % 32)); +} + +void I2cDriverState(void) +{ + ResponseAppend_P(PSTR("\"")); + for (uint32_t i = 0; i < sizeof(kI2cList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t i2c_driver_id = pgm_read_byte(kI2cList + i); +#else + uint32_t i2c_driver_id = kI2cList[i]; +#endif + bool disabled = false; + if (i2c_driver_id < MAX_I2C_DRIVERS) { + disabled = !bitRead(Settings.i2c_drivers[i2c_driver_id / 32], i2c_driver_id % 32); + } + ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", i2c_driver_id); + } + ResponseAppend_P(PSTR("\"")); +} + +#endif \ No newline at end of file From 2e0a06c19aae33fe030245ece2c938c5e0fdda24 Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Tue, 18 Feb 2020 09:49:53 +0100 Subject: [PATCH 426/559] structual changes structual changes --- tasmota/xsns_64_aht10.ino | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tasmota/xsns_64_aht10.ino b/tasmota/xsns_64_aht10.ino index 15dbbb5c1..00a9a262c 100644 --- a/tasmota/xsns_64_aht10.ino +++ b/tasmota/xsns_64_aht10.ino @@ -56,12 +56,12 @@ bool begin() else { return false; - } + } } bool AHT10Read(void) { - unsigned long result, temp[6]; + unsigned long result_t, result_h, temp[6]; if (AHT10.valid) { AHT10.valid--; } @@ -69,15 +69,17 @@ bool AHT10Read(void) Wire.write(eSensorMeasureCmd, 3); Wire.endTransmission(); delay(100); - - Wire.requestFrom(AHT10_ADDR, 6); + + Wire.requestFrom(AHT10_ADDR, 6); for(unsigned char i = 0; Wire.available() > 0; i++) { temp[i] = Wire.read(); - } + } + result_h = ((temp[1] << 16) | (temp[2] << 8) | temp[3]) >> 4; + result_t = ((temp[3] & 0x0F) << 16) | (temp[4] << 8) | temp[5]; - AHT10.humidity = (((temp[1] << 16) | (temp[2] << 8) | temp[3]) >> 4)* 100 / 1048576; - AHT10.temperature = ((200 * (((temp[3] & 0x0F) << 16) | (temp[4] << 8) | temp[5])) / 1048576) - 50; + AHT10.humidity = result_h * 100 / 1048576; + AHT10.temperature = ((200 * result_t) / 1048576) - 50; if (isnan(AHT10.temperature) || isnan(AHT10.humidity)) { return false; } @@ -97,12 +99,12 @@ unsigned char readStatus(void) void AHT10Detect(void) { - if (I2cActive(AHT10_ADDR)) - { - return; + if (I2cActive(AHT10_ADDR)) + { + return; } - if (begin()) + if (begin()) { I2cSetActiveFound(AHT10_ADDR, AHT10.name); AHT10.count = 1; From b423c9716a7bf4318d99f9abe5e5780f900cbeb7 Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Tue, 18 Feb 2020 09:56:23 +0100 Subject: [PATCH 427/559] Update xsns_64_aht10.ino --- tasmota/xsns_64_aht10.ino | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tasmota/xsns_64_aht10.ino b/tasmota/xsns_64_aht10.ino index 00a9a262c..f45ca3f4f 100644 --- a/tasmota/xsns_64_aht10.ino +++ b/tasmota/xsns_64_aht10.ino @@ -91,7 +91,6 @@ bool AHT10Read(void) unsigned char readStatus(void) { unsigned char result = 0; - Wire.requestFrom(AHT10_ADDR, 1); result = Wire.read(); return result; @@ -100,9 +99,7 @@ unsigned char readStatus(void) void AHT10Detect(void) { if (I2cActive(AHT10_ADDR)) - { - return; - } + {return;} if (begin()) { From df3441786186cc2155ba76b0e1d2a2bb035cc93e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 18 Feb 2020 18:10:36 +0100 Subject: [PATCH 428/559] Fix DS18x20 driver --- tasmota/xsns_05_ds18x20.ino | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tasmota/xsns_05_ds18x20.ino b/tasmota/xsns_05_ds18x20.ino index ba87e3a5d..5b46d5519 100644 --- a/tasmota/xsns_05_ds18x20.ino +++ b/tasmota/xsns_05_ds18x20.ino @@ -126,6 +126,8 @@ void OneWireWriteBit(uint8_t v) delayMicroseconds(delay_high[v]); } +/* +// Fails for reasons unknown to me uint8_t OneWireReadBit(void) { if (!ds18x20_dual_mode) { @@ -143,6 +145,35 @@ uint8_t OneWireReadBit(void) delayMicroseconds(53); return r; } +*/ +// Works fine in contrast to above. Why? +void OneWireReadBit1(void) +{ + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(3); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); // SetOption74 - Enable internal pullup for single DS18x20 sensor +} + +void OneWireReadBit2(void) +{ + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(3); + digitalWrite(ds18x20_pin_out, HIGH); +} + +uint8_t OneWireReadBit(void) +{ + if (!ds18x20_dual_mode) { + OneWireReadBit1(); + } else { + OneWireReadBit2(); + } + delayMicroseconds(10); + uint8_t r = digitalRead(ds18x20_pin); + delayMicroseconds(53); + return r; +} /*------------------------------------------------------------------------------------------*/ @@ -284,6 +315,7 @@ void Ds18x20Init(void) uint64_t ids[DS18X20_MAX_SENSORS]; ds18x20_pin = pin[GPIO_DSB]; + if (pin[GPIO_DSB_OUT] < 99) { ds18x20_pin_out = pin[GPIO_DSB_OUT]; ds18x20_dual_mode = true; // Dual pins mode as used by Shelly @@ -419,6 +451,8 @@ void Ds18x20Name(uint8_t sensor) void Ds18x20EverySecond(void) { + if (!ds18x20_sensors) { return; } + #ifdef W1_PARASITE_POWER // skip access if there is still an eeprom write ongoing unsigned long now = millis(); From e2ede9ed5543c36d03210d09abe0dff51c70da0c Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Tue, 18 Feb 2020 20:08:22 +0100 Subject: [PATCH 429/559] Add Reset Command --- tasmota/xsns_64_aht10.ino | 42 +++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/tasmota/xsns_64_aht10.ino b/tasmota/xsns_64_aht10.ino index f45ca3f4f..7405c5537 100644 --- a/tasmota/xsns_64_aht10.ino +++ b/tasmota/xsns_64_aht10.ino @@ -43,21 +43,6 @@ struct AHT10 { char name[6] = "AHT10"; } AHT10; -bool begin() -{ - Wire.begin(AHT10_ADDR); - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorCalibrateCmd, 3); - Wire.endTransmission(); - delay(500); - - if((readStatus() & 0x68) == 0x08) - return true; - else - { - return false; - } -} bool AHT10Read(void) { @@ -88,7 +73,21 @@ bool AHT10Read(void) } /********************************************************************************************/ -unsigned char readStatus(void) +bool aht10init() +{ + Wire.begin(AHT10_ADDR); + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorCalibrateCmd, 3); + Wire.endTransmission(); + delay(500); + + if((aht10ReadStatus() & 0x68) == 0x08) { + return true;} + else + { return false; } +} + +unsigned char aht10ReadStatus(void) { unsigned char result = 0; Wire.requestFrom(AHT10_ADDR, 1); @@ -96,12 +95,21 @@ unsigned char readStatus(void) return result; } +void aht10Reset(void) +{ + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorResetCmd); + Wire.endTransmission(); + delay(20); +} + +/********************************************************************************************/ void AHT10Detect(void) { if (I2cActive(AHT10_ADDR)) {return;} - if (begin()) + if (aht10init()) { I2cSetActiveFound(AHT10_ADDR, AHT10.name); AHT10.count = 1; From 81b88a71a084ff83e6e975a1114d320ac16b38f3 Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Tue, 18 Feb 2020 20:13:12 +0100 Subject: [PATCH 430/559] Update xsns_64_aht10.ino Correct text --- tasmota/xsns_64_aht10.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/xsns_64_aht10.ino b/tasmota/xsns_64_aht10.ino index 7405c5537..95d5a3e2b 100644 --- a/tasmota/xsns_64_aht10.ino +++ b/tasmota/xsns_64_aht10.ino @@ -73,7 +73,7 @@ bool AHT10Read(void) } /********************************************************************************************/ -bool aht10init() +bool AHT10Init() { Wire.begin(AHT10_ADDR); Wire.beginTransmission(AHT10_ADDR); @@ -81,13 +81,13 @@ bool aht10init() Wire.endTransmission(); delay(500); - if((aht10ReadStatus() & 0x68) == 0x08) { + if((AHT10ReadStatus() & 0x68) == 0x08) { return true;} else { return false; } } -unsigned char aht10ReadStatus(void) +unsigned char AHT10ReadStatus(void) { unsigned char result = 0; Wire.requestFrom(AHT10_ADDR, 1); @@ -95,7 +95,7 @@ unsigned char aht10ReadStatus(void) return result; } -void aht10Reset(void) +void AHT10Reset(void) { Wire.beginTransmission(AHT10_ADDR); Wire.write(eSensorResetCmd); @@ -109,7 +109,7 @@ void AHT10Detect(void) if (I2cActive(AHT10_ADDR)) {return;} - if (aht10init()) + if (AHT10Init()) { I2cSetActiveFound(AHT10_ADDR, AHT10.name); AHT10.count = 1; From 6e0cd5bd68df595d31e63d744a48432b7327aa53 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Wed, 19 Feb 2020 18:10:07 +1100 Subject: [PATCH 431/559] print numbers as numbers in json, not strings. --- tasmota/xdrv_16_tuyamcu.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index 11b134489..f250f6409 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -696,14 +696,14 @@ void TuyaSerialInput(void) if (TUYA_CMD_STATE == Tuya.buffer[3]) { ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId); if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("\"%u\""), dpData[0]); + ResponseAppend_P(PSTR("%u"), dpData[0]); } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; - ResponseAppend_P(PSTR("\"%u\""), dpValue); + ResponseAppend_P(PSTR("%u"), dpValue); } else if (TUYA_TYPE_STRING == dpDataType) { ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("\"%u\""), dpData[0]); + ResponseAppend_P(PSTR("%u"), dpData[0]); } else { ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); } From 7f72d266f8eb5a38013c0cca20e76c3412958aa0 Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Wed, 19 Feb 2020 09:37:36 +0100 Subject: [PATCH 432/559] prepare for merging --- I2CDEVICES.md | 2 +- tasmota/my_user_config.h | 2 +- tasmota/support_features.ino | 4 +- tasmota/tasmota.ino.cpp | 77284 ---------------- .../{xsns_64_aht10.ino => xsns_63_aht1x.ino} | 15 +- 5 files changed, 12 insertions(+), 77295 deletions(-) delete mode 100644 tasmota/tasmota.ino.cpp rename tasmota/{xsns_64_aht10.ino => xsns_63_aht1x.ino} (94%) diff --git a/I2CDEVICES.md b/I2CDEVICES.md index be92d03dc..b607b3241 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -64,4 +64,4 @@ Index | Define | Driver | Device | Address(es) | Description 41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor 42 | USE_DS1624 | xsns_59 | DS1621 | 0x48 - 0x4F | Temperature sensor 42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor - 43 | USE_AHT10 | xsns_64 | AHT10 | 0x38 | Temperature and humidity sensor + 43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 | Temperature and humidity sensor diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 04395065a..7f7fa3a45 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -486,7 +486,7 @@ // #define USE_HIH6 // [I2cDriver36] Enable Honeywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) // #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) (+0k7 code) // #define USE_DS1624 // [I2cDriver42] Enable DS1624, DS1621 temperature sensor (I2C addresses 0x48 - 0x4F) (+1k2 code) - #define USE_AHT10 // [I2cDriver43] Enable AHT10 humidity and temperature sensor (I2C address 0x38) (+0k8 code) + #define USE_AHT1x // [I2cDriver43] Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 933db0960..648235f12 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -513,8 +513,8 @@ void GetFeatures(void) #ifdef USE_LE01MR feature5 |= 0x08000000; // xnrg_13_fif_le01mr.ino #endif -#ifdef USE_AHT10 - feature5 |= 0x10000000; // xsns_64_aht10.ino +#ifdef USE_AHT1x + feature5 |= 0x10000000; // xsns_63_aht1x.ino #endif // feature5 |= 0x10000000; // feature5 |= 0x20000000; diff --git a/tasmota/tasmota.ino.cpp b/tasmota/tasmota.ino.cpp deleted file mode 100644 index ddd9b7b19..000000000 --- a/tasmota/tasmota.ino.cpp +++ /dev/null @@ -1,77284 +0,0 @@ -# 1 "C:\\Users\\martin\\AppData\\Local\\Temp\\tmpeqetuoko" -#include -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/tasmota.ino" -# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/tasmota.ino" -#include -#include "tasmota_version.h" -#include "tasmota.h" -#include "my_user_config.h" -#ifdef USE_MQTT_TLS - #include -#endif -#include "tasmota_post.h" -#include "i18n.h" -#include "tasmota_template.h" - -#ifdef ARDUINO_ESP8266_RELEASE_2_4_0 -#include "lwip/init.h" -#if LWIP_VERSION_MAJOR != 1 - #error Please use stable lwIP v1.4 -#endif -#endif - - -#include -#include -#include -#include -#ifdef USE_ARDUINO_OTA - #include - #ifndef USE_DISCOVERY - #define USE_DISCOVERY - #endif -#endif -#ifdef USE_DISCOVERY - #include -#endif -#ifdef USE_I2C - #include -#endif -#ifdef USE_SPI - #include -#endif - - -#include "settings.h" - - - - - -WiFiUDP PortUdp; - -unsigned long feature_drv1; -unsigned long feature_drv2; -unsigned long feature_sns1; -unsigned long feature_sns2; -unsigned long feature5; -unsigned long feature6; -unsigned long serial_polling_window = 0; -unsigned long state_second = 0; -unsigned long state_50msecond = 0; -unsigned long state_100msecond = 0; -unsigned long state_250msecond = 0; -unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; -unsigned long blink_timer = 0; -unsigned long backlog_delay = 0; -power_t power = 0; -power_t last_power = 0; -power_t blink_power; -power_t blink_mask = 0; -power_t blink_powersave; -power_t latching_power = 0; -power_t rel_inverted = 0; -int serial_in_byte_counter = 0; -int ota_state_flag = 0; -int ota_result = 0; -int restart_flag = 0; -int wifi_state_flag = WIFI_RESTART; -int blinks = 201; -uint32_t uptime = 0; -uint32_t loop_load_avg = 0; -uint32_t global_update = 0; -uint32_t web_log_index = 1; -float global_temperature = 9999; -float global_humidity = 0; -float global_pressure = 0; -uint16_t tele_period = 9999; -uint16_t blink_counter = 0; -uint16_t seriallog_timer = 0; -uint16_t syslog_timer = 0; -int16_t save_data_counter; -RulesBitfield rules_flag; -uint8_t mqtt_cmnd_blocked = 0; -uint8_t mqtt_cmnd_blocked_reset = 0; -uint8_t state_250mS = 0; -uint8_t latching_relay_pulse = 0; -uint8_t sleep; -uint8_t blinkspeed = 1; -uint8_t pin[GPIO_MAX]; -uint8_t active_device = 1; -uint8_t leds_present = 0; -uint8_t led_inverted = 0; -uint8_t led_power = 0; -uint8_t ledlnk_inverted = 0; -uint8_t pwm_inverted = 0; -uint8_t energy_flg = 0; -uint8_t light_flg = 0; -uint8_t light_type = 0; -uint8_t serial_in_byte; -uint8_t ota_retry_counter = OTA_ATTEMPTS; -uint8_t devices_present = 0; -uint8_t seriallog_level; -uint8_t syslog_level; -uint8_t my_module_type; -uint8_t my_adc0; -uint8_t last_source = 0; -uint8_t shutters_present = 0; -uint8_t prepped_loglevel = 0; - -bool serial_local = false; -bool fallback_topic_flag = false; -bool backlog_mutex = false; -bool interlock_mutex = false; -bool stop_flash_rotate = false; -bool blinkstate = false; - -bool pwm_present = false; -bool i2c_flg = false; -bool spi_flg = false; -bool soft_spi_flg = false; -bool ntp_force_sync = false; -bool is_8285 = false; -myio my_module; -gpio_flag my_module_flag; -StateBitfield global_state; -char my_version[33]; -char my_image[33]; -char my_hostname[33]; -char mqtt_client[TOPSZ]; -char mqtt_topic[TOPSZ]; -char serial_in_buffer[INPUT_BUFFER_SIZE]; -char mqtt_data[MESSZ]; -char log_data[LOGSZ]; -char web_log[WEB_LOG_SIZE] = {'\0'}; -#ifdef SUPPORT_IF_STATEMENT - #include - LinkedList backlog; - #define BACKLOG_EMPTY (backlog.size() == 0) -#else - uint8_t backlog_index = 0; - uint8_t backlog_pointer = 0; - String backlog[MAX_BACKLOG]; - #define BACKLOG_EMPTY (backlog_pointer == backlog_index) -#endif -void setup(void); -void BacklogLoop(void); -void loop(void); -uint16_t SendMail(char *buffer); -uint32_t GetRtcSettingsCrc(void); -void RtcSettingsSave(void); -void RtcSettingsLoad(void); -bool RtcSettingsValid(void); -uint32_t GetRtcRebootCrc(void); -void RtcRebootSave(void); -void RtcRebootReset(void); -void RtcRebootLoad(void); -bool RtcRebootValid(void); -void SetFlashModeDout(void); -bool VersionCompatible(void); -void SettingsBufferFree(void); -bool SettingsBufferAlloc(void); -uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size); -uint16_t GetSettingsCrc(void); -uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size); -uint32_t GetSettingsCrc32(void); -void SettingsSaveAll(void); -void UpdateQuickPowerCycle(bool update); -uint32_t GetSettingsTextLen(void); -bool SettingsUpdateText(uint32_t index, const char* replace_me); -char* SettingsText(uint32_t index); -uint32_t GetSettingsAddress(void); -void SettingsSave(uint8_t rotate); -void SettingsLoad(void); -void EspErase(uint32_t start_sector, uint32_t end_sector); -void SettingsErase(uint8_t type); -void SettingsSdkErase(void); -void SettingsDefault(void); -void SettingsDefaultSet1(void); -void SettingsDefaultSet2(void); -void SettingsResetStd(void); -void SettingsResetDst(void); -void SettingsDefaultWebColor(void); -void SettingsEnableAllI2cDrivers(void); -void SettingsDelta(void); -void OsWatchTicker(void); -void OsWatchInit(void); -void OsWatchLoop(void); -bool OsWatchBlockedLoop(void); -uint32_t ResetReason(void); -String GetResetReason(void); -size_t strchrspn(const char *str1, int character); -char* subStr(char* dest, char* str, const char *delim, int index); -float CharToFloat(const char *str); -int TextToInt(char *str); -char* ulltoa(unsigned long long value, char *str, int radix); -char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween); -char* Uint64toHex(uint64_t value, char *str, uint16_t bits); -char* dtostrfd(double number, unsigned char prec, char *s); -char* Unescape(char* buffer, uint32_t* size); -char* RemoveSpace(char* p); -char* ReplaceCommaWithDot(char* p); -char* LowerCase(char* dest, const char* source); -char* UpperCase(char* dest, const char* source); -char* UpperCase_P(char* dest, const char* source); -char* Trim(char* p); -char* RemoveAllSpaces(char* p); -char* NoAlNumToUnderscore(char* dest, const char* source); -char IndexSeparator(void); -void SetShortcutDefault(void); -uint8_t Shortcut(void); -bool ValidIpAddress(const char* str); -bool ParseIp(uint32_t* addr, const char* str); -uint32_t ParseParameters(uint32_t count, uint32_t *params); -bool NewerVersion(char* version_str); -char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option); -char* GetPowerDevice(char* dest, uint32_t idx, size_t size); -void GetEspHardwareType(void); -String GetDeviceHardware(void); -float ConvertTemp(float c); -float ConvertTempToCelsius(float c); -char TempUnit(void); -float ConvertHumidity(float h); -float ConvertPressure(float p); -String PressureUnit(void); -void ResetGlobalValues(void); -uint32_t SqrtInt(uint32_t num); -uint32_t RoundSqrtInt(uint32_t num); -char* GetTextIndexed(char* destination, size_t destination_size, uint32_t index, const char* haystack); -int GetCommandCode(char* destination, size_t destination_size, const char* needle, const char* haystack); -int GetStateNumber(char *state_text); -String GetSerialConfig(void); -void SetSerialBegin(); -void SetSerialConfig(uint32_t serial_config); -void SetSerialBaudrate(uint32_t baudrate); -void SetSerial(uint32_t baudrate, uint32_t serial_config); -void ClaimSerial(void); -void SerialSendRaw(char *codes); -uint32_t GetHash(const char *buffer, size_t size); -void ShowSource(uint32_t source); -void WebHexCode(uint32_t i, const char* code); -uint32_t WebColor(uint32_t i); -char* ResponseGetTime(uint32_t format, char* time_str); -int Response_P(const char* format, ...); -int ResponseTime_P(const char* format, ...); -int ResponseAppend_P(const char* format, ...); -int ResponseAppendTimeFormat(uint32_t format); -int ResponseAppendTime(void); -int ResponseJsonEnd(void); -int ResponseJsonEndEnd(void); -void DigitalWrite(uint32_t gpio_pin, uint32_t state); -uint8_t ModuleNr(void); -bool ValidTemplateModule(uint32_t index); -bool ValidModule(uint32_t index); -String AnyModuleName(uint32_t index); -String ModuleName(void); -void ModuleGpios(myio *gp); -gpio_flag ModuleFlag(void); -void ModuleDefault(uint32_t module); -void SetModuleType(void); -bool FlashPin(uint32_t pin); -uint8_t ValidPin(uint32_t pin, uint32_t gpio); -bool ValidGPIO(uint32_t pin, uint32_t gpio); -bool ValidAdc(void); -bool GetUsedInModule(uint32_t val, uint8_t *arr); -bool JsonTemplate(const char* dataBuf); -void TemplateJson(void); -inline int32_t TimeDifference(uint32_t prev, uint32_t next); -int32_t TimePassedSince(uint32_t timestamp); -bool TimeReached(uint32_t timer); -void SetNextTimeInterval(unsigned long& timer, const unsigned long step); -int32_t TimePassedSinceUsec(uint32_t timestamp); -bool TimeReachedUsec(uint32_t timer); -bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size); -bool I2cValidRead8(uint8_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead16(uint16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead16LE(uint16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead24(int32_t *data, uint8_t addr, uint8_t reg); -uint8_t I2cRead8(uint8_t addr, uint8_t reg); -uint16_t I2cRead16(uint8_t addr, uint8_t reg); -int16_t I2cReadS16(uint8_t addr, uint8_t reg); -uint16_t I2cRead16LE(uint8_t addr, uint8_t reg); -int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg); -int32_t I2cRead24(uint8_t addr, uint8_t reg); -bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size); -bool I2cWrite8(uint8_t addr, uint8_t reg, uint16_t val); -bool I2cWrite16(uint8_t addr, uint8_t reg, uint16_t val); -int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len); -int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len); -void I2cScan(char *devs, unsigned int devs_len); -void I2cSetActiveFound(uint32_t addr, const char *types); -bool I2cActive(uint32_t addr); -bool I2cSetDevice(uint32_t addr); -void SetSeriallog(uint32_t loglevel); -void SetSyslog(uint32_t loglevel); -void GetLog(uint32_t idx, char** entry_pp, size_t* len_p); -void Syslog(void); -void AddLog(uint32_t loglevel); -void AddLog_P(uint32_t loglevel, const char *formatP); -void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2); -void PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...); -void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...); -void AddLog_Debug(PGM_P formatP, ...); -void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count); -void AddLogSerial(uint32_t loglevel); -void AddLogMissed(char *sensor, uint32_t misses); -void ButtonPullupFlag(uint8 button_bit); -void ButtonInvertFlag(uint8 button_bit); -void ButtonInit(void); -uint8_t ButtonSerial(uint8_t serial_in_byte); -void ButtonHandler(void); -void ButtonLoop(void); -void ResponseCmndNumber(int value); -void ResponseCmndFloat(float value, uint32_t decimals); -void ResponseCmndIdxNumber(int value); -void ResponseCmndChar(const char* value); -void ResponseCmndStateText(uint32_t value); -void ResponseCmndDone(void); -void ResponseCmndIdxChar(const char* value); -void ResponseCmndAll(uint32_t text_index, uint32_t count); -void ExecuteCommand(const char *cmnd, uint32_t source); -void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len); -void CmndBacklog(void); -void CmndDelay(void); -void CmndPower(void); -void CmndStatus(void); -void CmndState(void); -void CmndTempOffset(void); -void CmndSleep(void); -void CmndUpgrade(void); -void CmndOtaUrl(void); -void CmndSeriallog(void); -void CmndRestart(void); -void CmndPowerOnState(void); -void CmndPulsetime(void); -void CmndBlinktime(void); -void CmndBlinkcount(void); -void CmndSavedata(void); -void CmndSetoption(void); -void CmndTemperatureResolution(void); -void CmndHumidityResolution(void); -void CmndPressureResolution(void); -void CmndPowerResolution(void); -void CmndVoltageResolution(void); -void CmndFrequencyResolution(void); -void CmndCurrentResolution(void); -void CmndEnergyResolution(void); -void CmndWeightResolution(void); -void CmndModule(void); -void CmndModules(void); -void CmndGpio(void); -void CmndGpios(void); -void CmndTemplate(void); -void CmndPwm(void); -void CmndPwmfrequency(void); -void CmndPwmrange(void); -void CmndButtonDebounce(void); -void CmndSwitchDebounce(void); -void CmndBaudrate(void); -void CmndSerialConfig(void); -void CmndSerialSend(void); -void CmndSerialDelimiter(void); -void CmndSyslog(void); -void CmndLoghost(void); -void CmndLogport(void); -void CmndIpAddress(void); -void CmndNtpServer(void); -void CmndAp(void); -void CmndSsid(void); -void CmndPassword(void); -void CmndHostname(void); -void CmndWifiConfig(void); -void CmndFriendlyname(void); -void CmndSwitchMode(void); -void CmndInterlock(void); -void CmndTeleperiod(void); -void CmndReset(void); -void CmndTime(void); -void CmndTimezone(void); -void CmndTimeStdDst(uint32_t ts); -void CmndTimeStd(void); -void CmndTimeDst(void); -void CmndAltitude(void); -void CmndLedPower(void); -void CmndLedState(void); -void CmndLedMask(void); -void CmndWifiPower(void); -void CmndI2cScan(void); -void CmndI2cDriver(void); -void CmndSensor(void); -void CmndDriver(void); -void CmndCrash(void); -void CmndWDT(void); -void CmndBlockedLoop(void); -void CrashDumpClear(void); -bool CrashFlag(void); -void CrashDump(void); -static bool spiflash_is_ready(void); -static void spi_write_enable(void); -bool EsptoolEraseSector(uint32_t sector); -void EsptoolErase(uint32_t start_sector, uint32_t end_sector); -void GetFeatures(void); -float fmodf(float x, float y); -double FastPrecisePow(double a, double b); -float FastPrecisePowf(const float x, const float y); -double TaylorLog(double x); -inline float sinf(float x); -inline float cosf(float x); -inline float tanf(float x); -inline float atanf(float x); -inline float asinf(float x); -inline float acosf(float x); -inline float sqrtf(float x); -inline float powf(float x, float y); -float cos_52s(float x); -float cos_52(float x); -float sin_52(float x); -float tan_56s(float x); -float tan_56(float x); -float atan_66s(float x); -float atan_66(float x); -float asinf1(float x); -float acosf1(float x); -float sqrt1(const float x); -uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, - uint16_t ito_min, uint16_t ito_max); -void* memchr(const void* ptr, int value, size_t num); -size_t strcspn(const char *str1, const char *str2); -char* strpbrk(const char *s1, const char *s2); -void* memmove_P(void *dest, const void *src, size_t n); -void update_rotary(void); -bool RotaryButtonPressed(void); -void RotaryInit(void); -void RotaryHandler(void); -void RotaryLoop(void); -uint32_t UtcTime(void); -uint32_t LocalTime(void); -int32_t DriftTime(void); -uint32_t Midnight(void); -bool MidnightNow(void); -bool IsDst(void); -String GetBuildDateAndTime(void); -String GetMinuteTime(uint32_t minutes); -String GetTimeZone(void); -String GetDuration(uint32_t time); -String GetDT(uint32_t time); -String GetDateAndTime(uint8_t time_type); -String GetTime(int type); -uint32_t UpTime(void); -uint32_t MinutesUptime(void); -String GetUptime(void); -uint32_t MinutesPastMidnight(void); -void BreakTime(uint32_t time_input, TIME_T &tm); -uint32_t MakeTime(TIME_T &tm); -uint32_t RuleToTime(TimeRule r, int yr); -void RtcSecond(void); -void RtcSetTime(uint32_t epoch); -void RtcInit(void); -String GetStatistics(void); -String GetStatistics(void); -void SwitchPullupFlag(uint16 switch_bit); -void SwitchSetVirtual(uint32_t index, uint8_t state); -uint8_t SwitchGetVirtual(uint32_t index); -uint8_t SwitchLastState(uint32_t index); -bool SwitchState(uint32_t index); -void SwitchProbe(void); -void SwitchInit(void); -void SwitchHandler(uint8_t mode); -void SwitchLoop(void); -char* Format(char* output, const char* input, int size); -char* GetOtaUrl(char *otaurl, size_t otaurl_size); -char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic); -char* GetGroupTopic_P(char *stopic, const char* subtopic); -char* GetFallbackTopic_P(char *stopic, const char* subtopic); -char* GetStateText(uint32_t state); -void SetLatchingRelay(power_t lpower, uint32_t state); -void SetDevicePower(power_t rpower, uint32_t source); -void RestorePower(bool publish_power, uint32_t source); -void SetAllPower(uint32_t state, uint32_t source); -void SetPowerOnState(void); -void SetLedPowerIdx(uint32_t led, uint32_t state); -void SetLedPower(uint32_t state); -void SetLedPowerAll(uint32_t state); -void SetLedLink(uint32_t state); -void SetPulseTimer(uint32_t index, uint32_t time); -uint32_t GetPulseTimer(uint32_t index); -bool SendKey(uint32_t key, uint32_t device, uint32_t state); -void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source); -void StopAllPowerBlink(void); -void MqttShowPWMState(void); -void MqttShowState(void); -void MqttPublishTeleState(void); -bool MqttShowSensor(void); -void MqttPublishSensor(void); -void PerformEverySecond(void); -void Every100mSeconds(void); -void Every250mSeconds(void); -void ArduinoOTAInit(void); -void ArduinoOtaLoop(void); -void SerialInput(void); -void GpioInit(void); -bool UdpDisconnect(void); -bool UdpConnect(void); -void PollUdp(void); -int WifiGetRssiAsQuality(int rssi); -bool WifiConfigCounter(void); -void WifiConfig(uint8_t type); -void WifiSetMode(WiFiMode_t wifi_mode); -void WiFiSetSleepMode(void); -void WifiBegin(uint8_t flag, uint8_t channel); -void WifiBeginAfterScan(void); -uint16_t WifiLinkCount(void); -String WifiDowntime(void); -void WifiSetState(uint8_t state); -bool WifiCheckIPv6(void); -String WifiGetIPv6(void); -bool WifiCheckIPAddrStatus(void); -void WifiCheckIp(void); -void WifiCheck(uint8_t param); -int WifiState(void); -String WifiGetOutputPower(void); -void WifiSetOutputPower(void); -void WifiConnect(void); -void WifiDisconnect(void); -void WifiShutdown(void); -void EspRestart(void); -static void WebGetArg(const char* arg, char* out, size_t max); -static bool WifiIsInManagerMode(); -void ShowWebSource(uint32_t source); -void ExecuteWebCommand(char* svalue, uint32_t source); -void StartWebserver(int type, IPAddress ipweb); -void StopWebserver(void); -void WifiManagerBegin(bool reset_only); -void PollDnsWebserver(void); -bool WebAuthenticate(void); -void HttpHeaderCors(void); -void WSHeaderSend(void); -void WSSend(int code, int ctype, const String& content); -void WSContentBegin(int code, int ctype); -void _WSContentSend(const String& content); -void WSContentFlush(void); -void _WSContentSendBuffer(void); -void WSContentSend_P(const char* formatP, ...); -void WSContentSend_PD(const char* formatP, ...); -void WSContentStart_P(const char* title, bool auth); -void WSContentStart_P(const char* title); -void WSContentSendStyle_P(const char* formatP, ...); -void WSContentSendStyle(void); -void WSContentButton(uint32_t title_index); -void WSContentSpaceButton(uint32_t title_index); -void WSContentEnd(void); -void WSContentStop(void); -void WebRestart(uint32_t type); -void HandleWifiLogin(void); -void WebSliderColdWarm(void); -void HandleRoot(void); -bool HandleRootStatusRefresh(void); -int32_t IsShutterWebButton(uint32_t idx); -void HandleConfiguration(void); -void HandleTemplateConfiguration(void); -void TemplateSaveSettings(void); -void HandleModuleConfiguration(void); -void ModuleSaveSettings(void); -String HtmlEscape(const String unescaped); -void HandleWifiConfiguration(void); -void WifiSaveSettings(void); -void HandleLoggingConfiguration(void); -void LoggingSaveSettings(void); -void HandleOtherConfiguration(void); -void OtherSaveSettings(void); -void HandleBackupConfiguration(void); -void HandleResetConfiguration(void); -void HandleRestoreConfiguration(void); -void HandleInformation(void); -void HandleUpgradeFirmware(void); -void HandleUpgradeFirmwareStart(void); -void HandleUploadDone(void); -void HandleUploadLoop(void); -void HandlePreflightRequest(void); -void HandleHttpCommand(void); -void HandleConsole(void); -void HandleConsoleRefresh(void); -void HandleNotFound(void); -bool CaptivePortal(void); -String UrlEncode(const String& text); -int WebSend(char *buffer); -bool JsonWebColor(const char* dataBuf); -void CmndEmulation(void); -void CmndSendmail(void); -void CmndWebServer(void); -void CmndWebPassword(void); -void CmndWeblog(void); -void CmndWebRefresh(void); -void CmndWebSend(void); -void CmndWebColor(void); -void CmndWebSensor(void); -void CmndWebButton(void); -void CmndCors(void); -bool Xdrv01(uint8_t function); -bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value); -void MakeValidMqtt(uint32_t option, char* str); -void MqttDiscoverServer(void); -void MqttInit(void); -bool MqttIsConnected(void); -void MqttDisconnect(void); -void MqttSubscribeLib(const char *topic); -void MqttUnsubscribeLib(const char *topic); -bool MqttPublishLib(const char* topic, bool retained); -void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len); -void MqttRetryCounter(uint8_t value); -void MqttSubscribe(const char *topic); -void MqttUnsubscribe(const char *topic); -void MqttPublishLogging(const char *mxtime); -void MqttPublish(const char* topic, bool retained); -void MqttPublish(const char* topic); -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained); -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic); -void MqttPublishTeleSensor(void); -void MqttPublishPowerState(uint32_t device); -void MqttPublishAllPowerState(void); -void MqttPublishPowerBlinkState(uint32_t device); -uint16_t MqttConnectCount(void); -void MqttDisconnected(int state); -void MqttConnected(void); -void MqttReconnect(void); -void MqttCheck(void); -void CmndMqttFingerprint(void); -void CmndMqttUser(void); -void CmndMqttPassword(void); -void CmndMqttlog(void); -void CmndMqttHost(void); -void CmndMqttPort(void); -void CmndMqttRetry(void); -void CmndStateText(void); -void CmndMqttClient(void); -void CmndFullTopic(void); -void CmndPrefix(void); -void CmndPublish(void); -void CmndGroupTopic(void); -void CmndTopic(void); -void CmndButtonTopic(void); -void CmndSwitchTopic(void); -void CmndButtonRetain(void); -void CmndSwitchRetain(void); -void CmndPowerRetain(void); -void CmndSensorRetain(void); -inline void TlsEraseBuffer(uint8_t *buffer); -void loadTlsDir(void); -void CmndTlsKey(void); -uint32_t bswap32(uint32_t x); -void CmndTlsDump(void); -void HandleMqttConfiguration(void); -void MqttSaveSettings(void); -bool Xdrv02(uint8_t function); -bool EnergyTariff1Active(); -void EnergyUpdateToday(void); -void EnergyUpdateTotal(float value, bool kwh); -void Energy200ms(void); -void EnergySaveState(void); -bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag); -void EnergyMarginCheck(void); -void EnergyMqttShow(void); -void EnergyEverySecond(void); -void EnergyCommandCalResponse(uint32_t nvalue); -void CmndEnergyReset(void); -void CmndTariff(void); -void CmndPowerCal(void); -void CmndVoltageCal(void); -void CmndCurrentCal(void); -void CmndPowerSet(void); -void CmndVoltageSet(void); -void CmndCurrentSet(void); -void CmndFrequencySet(void); -void CmndModuleAddress(void); -void CmndPowerDelta(void); -void CmndPowerLow(void); -void CmndPowerHigh(void); -void CmndVoltageLow(void); -void CmndVoltageHigh(void); -void CmndCurrentLow(void); -void CmndCurrentHigh(void); -void CmndMaxPower(void); -void CmndMaxPowerHold(void); -void CmndMaxPowerWindow(void); -void CmndSafePower(void); -void CmndSafePowerHold(void); -void CmndSafePowerWindow(void); -void CmndMaxEnergy(void); -void CmndMaxEnergyStart(void); -void EnergySnsInit(void); -void EnergyShow(bool json); -bool Xdrv03(uint8_t function); -bool Xsns03(uint8_t function); -power_t LightPower(void); -power_t LightPowerIRAM(void); -uint8_t LightDevice(void); -static uint32_t min3(uint32_t a, uint32_t b, uint32_t c); -uint16_t change8to10(uint8_t v); -uint8_t change10to8(uint16_t v); -uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr); -uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr); -uint16_t ledGamma10_10(uint16_t v); -uint16_t ledGamma10(uint8_t v); -uint8_t ledGamma(uint8_t v); -void LightPwmOffset(uint32_t offset); -bool LightModuleInit(void); -void LightInit(void); -void LightUpdateColorMapping(void); -uint8_t LightGetDimmer(uint8_t dimmer); -void LightSetDimmer(uint8_t dimmer); -void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri); -void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); -uint8_t LightGetBri(uint8_t device); -void LightSetBri(uint8_t device, uint8_t bri); -void LightSetColorTemp(uint16_t ct); -uint16_t LightGetColorTemp(void); -void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value); -void LightPowerOn(void); -void LightState(uint8_t append); -void LightCycleColor(int8_t direction); -void LightSetPower(void); -void LightAnimate(void); -bool isChannelGammaCorrected(uint32_t channel); -uint16_t fadeGamma(uint32_t channel, uint16_t v); -uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg); -bool LightApplyFade(void); -void LightApplyPower(uint8_t new_color[LST_MAX], power_t power); -void LightSetOutputs(const uint16_t *cur_col_10); -void calcGammaMultiChannels(uint16_t cur_col_10[5]); -void calcGammaBulbs(uint16_t cur_col_10[5]); -bool LightColorEntry(char *buffer, uint32_t buffer_length); -void CmndSupportColor(void); -void CmndColor(void); -void CmndWhite(void); -void CmndChannel(void); -void CmndHsbColor(void); -void CmndScheme(void); -void CmndWakeup(void); -void CmndColorTemperature(void); -void CmndDimmer(void); -void CmndDimmerRange(void); -void CmndLedTable(void); -void CmndRgbwwTable(void); -void CmndFade(void); -void CmndSpeed(void); -void CmndWakeupDuration(void); -void CmndUndocA(void); -bool Xdrv04(uint8_t function); -void IrSendInit(void); -void IrReceiveUpdateThreshold(void); -void IrReceiveInit(void); -void IrReceiveCheck(void); -uint32_t IrRemoteCmndIrSendJson(void); -void CmndIrSend(void); -void IrRemoteCmndResponse(uint32_t error); -bool Xdrv05(uint8_t function); -void IrSendInit(void); -uint8_t reverseBitsInByte(uint8_t b); -uint64_t reverseBitsInBytes64(uint64_t b); -void IrReceiveUpdateThreshold(void); -void IrReceiveInit(void); -String sendIRJsonState(const struct decode_results &results); -void IrReceiveCheck(void); -String listSupportedProtocols(bool hvac); -uint32_t IrRemoteCmndIrHvacJson(void); -void CmndIrHvac(void); -uint32_t IrRemoteCmndIrSendJson(void); -uint32_t IrRemoteCmndIrSendRaw(void); -void CmndIrSend(void); -void IrRemoteCmndResponse(uint32_t error); -bool Xdrv05(uint8_t function); -ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size); -ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size); -ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len); -ssize_t rf_decode_and_write(uint8_t *record, size_t size); -ssize_t rf_search_and_write(uint8_t *buf, size_t size); -uint8_t rf_erase_flash(void); -uint8_t SnfBrUpdateInit(void); -void SonoffBridgeReceivedRaw(void); -void SonoffBridgeLearnFailed(void); -void SonoffBridgeReceived(void); -bool SonoffBridgeSerialInput(void); -void SonoffBridgeSendCommand(uint8_t code); -void SonoffBridgeSendAck(void); -void SonoffBridgeSendCode(uint32_t code); -void SonoffBridgeSend(uint8_t idx, uint8_t key); -void SonoffBridgeLearn(uint8_t key); -void CmndRfBridge(void); -void CmndRfKey(void); -void CmndRfRaw(void); -bool Xdrv06(uint8_t function); -int DomoticzBatteryQuality(void); -int DomoticzRssiQuality(void); -void MqttPublishDomoticzFanState(void); -void DomoticzUpdateFanState(void); -void MqttPublishDomoticzPowerState(uint8_t device); -void DomoticzUpdatePowerState(uint8_t device); -void DomoticzMqttUpdate(void); -void DomoticzMqttSubscribe(void); -bool DomoticzMqttData(void); -bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg); -uint8_t DomoticzHumidityState(char *hum); -void DomoticzSensor(uint8_t idx, char *data); -void DomoticzSensor(uint8_t idx, uint32_t value); -void DomoticzTempHumSensor(char *temp, char *hum); -void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro); -void DomoticzSensorPowerEnergy(int power, char *energy); -void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power); -void CmndDomoticzIdx(void); -void CmndDomoticzKeyIdx(void); -void CmndDomoticzSwitchIdx(void); -void CmndDomoticzSensorIdx(void); -void CmndDomoticzUpdateTimer(void); -void HandleDomoticzConfiguration(void); -void DomoticzSaveSettings(void); -bool Xdrv07(uint8_t function); -void SerialBridgeInput(void); -void SerialBridgeInit(void); -void CmndSSerialSend(void); -void CmndSBaudrate(void); -bool Xdrv08(uint8_t function); -float JulianischesDatum(void); -float InPi(float x); -float eps(float T); -float BerechneZeitgleichung(float *DK,float T); -void DuskTillDawn(uint8_t *hour_up,uint8_t *minute_up, uint8_t *hour_down, uint8_t *minute_down); -void ApplyTimerOffsets(Timer *duskdawn); -String GetSun(uint32_t dawn); -uint16_t SunMinutes(uint32_t dawn); -void TimerSetRandomWindow(uint32_t index); -void TimerSetRandomWindows(void); -void TimerEverySecond(void); -void PrepShowTimer(uint32_t index); -void CmndTimer(void); -void CmndTimers(void); -void CmndLongitude(void); -void CmndLatitude(void); -void HandleTimerConfiguration(void); -void TimerSaveSettings(void); -bool Xdrv09(uint8_t function); -bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule); -int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr); -void RulesVarReplace(String &commands, const String &sfind, const String &replace); -bool RuleSetProcess(uint8_t rule_set, String &event_saved); -bool RulesProcessEvent(char *json_event); -bool RulesProcess(void); -void RulesInit(void); -void RulesEvery50ms(void); -void RulesEvery100ms(void); -void RulesEverySecond(void); -void RulesSaveBeforeRestart(void); -void RulesSetPower(void); -void RulesTeleperiod(void); -bool RulesMqttData(void); -void CmndSubscribe(void); -void CmndUnsubscribe(void); -bool findNextNumber(char * &pNumber, float &value); -bool findNextVariableValue(char * &pVarname, float &value); -bool findNextObjectValue(char * &pointer, float &value); -bool findNextOperator(char * &pointer, int8_t &op); -float calculateTwoValues(float v1, float v2, uint8_t op); -float evaluateExpression(const char * expression, unsigned int len); -void CmndIf(void); -bool evaluateComparisonExpression(const char *expression, int len); -bool findNextLogicOperator(char * &pointer, int8_t &op); -bool findNextLogicObjectValue(char * &pointer, bool &value); -bool evaluateLogicalExpression(const char * expression, int len); -int8_t findIfBlock(char * &pointer, int &lenWord, int8_t block_type); -void ExecuteCommandBlock(const char * commands, int len); -void ProcessIfStatement(const char* statements); -void RulesPreprocessCommand(char *pCommands); -void CmndRule(void); -void CmndRuleTimer(void); -void CmndEvent(void); -void CmndVariable(void); -void CmndMemory(void); -void CmndCalcResolution(void); -void CmndAddition(void); -void CmndSubtract(void); -void CmndMultiply(void); -void CmndScale(void); -float map_double(float x, float in_min, float in_max, float out_min, float out_max); -bool Xdrv10(uint8_t function); -void ScriptEverySecond(void); -void RulesTeleperiod(void); -int16_t Init_Scripter(void); -void ws2812_set_array(float *array ,uint8_t len); -float median_array(float *array,uint8_t len); -float Get_MFVal(uint8_t index,uint8_t bind); -void Set_MFVal(uint8_t index,uint8_t bind,float val); -float Get_MFilter(uint8_t index); -void Set_MFilter(uint8_t index, float invar); -float DoMedian5(uint8_t index, float in); -uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value); -uint16_t GetStack(void); -uint16_t GetStack(void); -void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize); -void toLog(const char *str); -void toLogN(const char *cp,uint8_t len); -void toLogEOL(const char *s1,const char *str); -void toSLog(const char *str); -int16_t Run_Scripter(const char *type, int8_t tlen, char *js); -void ScripterEvery100ms(void); -void Scripter_save_pvars(void); -void ListDir(char *path, uint8_t depth); -void Script_FileUploadConfiguration(void); -void ScriptFileUploadSuccess(void); -void script_upload(void); -uint8_t DownloadFile(char *file); -void HandleScriptTextareaConfiguration(void); -void HandleScriptConfiguration(void); -void ScriptSaveSettings(void); -void Script_HueStatus(String *response, uint16_t hue_devs); -void Script_Check_Hue(String *response); -void Script_Handle_Hue(String *path); -bool Script_SubCmd(void); -void execute_script(char *script); -bool ScriptCommand(void); -uint16_t xFAT_DATE(uint16_t year, uint8_t month, uint8_t day); -uint16_t xFAT_TIME(uint8_t hour, uint8_t minute, uint8_t second); -void dateTime(uint16_t* date, uint16_t* time); -bool ScriptMqttData(void); -String ScriptSubscribe(const char *data, int data_len); -String ScriptUnsubscribe(const char * data, int data_len); -void Script_Check_HTML_Setvars(void); -void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen); -void ScriptWebShow(void); -void ScriptJsonAppend(void); -bool Xdrv10(uint8_t function); -void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ); -void KNX_DEL_GA( uint8_t GAnum ); -void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ); -void KNX_DEL_CB( uint8_t CBnum ); -bool KNX_CONFIG_NOT_MATCH(void); -void KNXStart(void); -void KNX_INIT(void); -void KNX_CB_Action(message_t const &msg, void *arg); -void KnxUpdatePowerState(uint8_t device, power_t state); -void KnxSendButtonPower(void); -void KnxSensor(uint8_t sensor_type, float value); -void HandleKNXConfiguration(void); -void KNX_Save_Settings(void); -void CmndKnxTxCmnd(void); -void CmndKnxTxVal(void); -void CmndKnxEnabled(void); -void CmndKnxEnhanced(void); -void CmndKnxPa(void); -void CmndKnxGa(void); -void CmndKnxCb(void); -bool Xdrv11(uint8_t function); -void TryResponseAppend_P(const char *format, ...); -void HAssAnnounceRelayLight(void); -void HAssAnnounceButtonSwitch(uint8_t device, char *topic, uint8_t present, uint8_t key, uint8_t toggle); -void HAssAnnounceSwitches(void); -void HAssAnnounceButtons(void); -void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, uint8_t subidx); -void HAssAnnounceSensors(void); -void HAssAnnounceStatusSensor(void); -void HAssPublishStatus(void); -void HAssDiscovery(void); -void HAssDiscover(void); -void HAssAnyKey(void); -bool Xdrv12(uint8_t function); -void DisplayInit(uint8_t mode); -void DisplayClear(void); -void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color); -void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color); -void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color); -void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color); -void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawFrame(void); -void DisplaySetSize(uint8_t size); -void DisplaySetFont(uint8_t font); -void DisplaySetRotation(uint8_t rotation); -void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void DisplayOnOff(uint8_t on); -uint8_t fatoiv(char *cp,float *res); -uint8_t atoiv(char *cp, int16_t *res); -uint8_t atoiV(char *cp, uint16_t *res); -void alignright(char *string); -uint32_t decode_te(char *line); -void DisplayText(void); -void DisplayClearScreenBuffer(void); -void DisplayFreeScreenBuffer(void); -void DisplayAllocScreenBuffer(void); -void DisplayReAllocScreenBuffer(void); -void DisplayFillScreen(uint32_t line); -void DisplayClearLogBuffer(void); -void DisplayFreeLogBuffer(void); -void DisplayAllocLogBuffer(void); -void DisplayReAllocLogBuffer(void); -void DisplayLogBufferAdd(char* txt); -char* DisplayLogBuffer(char temp_code); -void DisplayLogBufferInit(void); -void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value); -void DisplayAnalyzeJson(char *topic, char *json); -void DisplayMqttSubscribe(void); -bool DisplayMqttData(void); -void DisplayLocalSensor(void); -void DisplayInitDriver(void); -void DisplaySetPower(void); -void CmndDisplay(void); -void CmndDisplayModel(void); -void CmndDisplayWidth(void); -void CmndDisplayHeight(void); -void CmndDisplayMode(void); -void CmndDisplayDimmer(void); -void CmndDisplaySize(void); -void CmndDisplayFont(void); -void CmndDisplayRotate(void); -void CmndDisplayText(void); -void CmndDisplayAddress(void); -void CmndDisplayRefresh(void); -void CmndDisplayColumns(void); -void CmndDisplayRows(void); -void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp); -void DrawAClock(uint16_t rad); -void ClrGraph(uint16_t num); -void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol); -void DisplayCheckGraph(); -void Save_graph(uint8_t num, char *path); -void Restore_graph(uint8_t num, char *path); -void RedrawGraph(uint8_t num, uint8_t flags); -void AddGraph(uint8_t num,uint8_t val); -void AddValue(uint8_t num,float fval); -bool Xdrv13(uint8_t function); -uint16_t MP3_Checksum(uint8_t *array); -void MP3PlayerInit(void); -void MP3_CMD(uint8_t mp3cmd,uint16_t val); -bool MP3PlayerCmd(void); -bool Xdrv14(uint8_t function); -void PCA9685_Detect(void); -void PCA9685_Reset(void); -void PCA9685_SetPWMfreq(double freq); -void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off); -void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted); -bool PCA9685_Command(void); -void PCA9685_OutputTelemetry(bool telemetry); -bool Xdrv15(uint8_t function); -void CmndTuyaSend(void); -void CmndTuyaMcu(void); -void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId); -void UpdateDevices(); -inline bool TuyaFuncIdValid(uint8_t fnId); -uint8_t TuyaGetFuncId(uint8_t dpid); -uint8_t TuyaGetDpId(uint8_t fnId); -void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value); -void TuyaSendBool(uint8_t id, bool value); -void TuyaSendValue(uint8_t id, uint32_t value); -void TuyaSendEnum(uint8_t id, uint32_t value); -void TuyaSendString(uint8_t id, char data[]); -bool TuyaSetPower(void); -bool TuyaSetChannels(void); -void LightSerialDuty(uint16_t duty); -void TuyaRequestState(void); -void TuyaResetWifi(void); -void TuyaProcessStatePacket(void); -void TuyaLowPowerModePacketProcess(void); -void TuyaHandleProductInfoPacket(void); -void TuyaSendLowPowerSuccessIfNeeded(void); -void TuyaNormalPowerModePacketProcess(void); -bool TuyaModuleSelected(void); -void TuyaInit(void); -void TuyaSerialInput(void); -bool TuyaButtonPressed(void); -uint8_t TuyaGetTuyaWifiState(void); -void TuyaSetWifiLed(void); -bool Xnrg16(uint8_t function); -bool Xdrv16(uint8_t function); -void RfReceiveCheck(void); -void RfInit(void); -void CmndRfSend(void); -bool Xdrv17(uint8_t function); -bool ArmtronixSetChannels(void); -void LightSerial2Duty(uint8_t duty1, uint8_t duty2); -void ArmtronixRequestState(void); -bool ArmtronixModuleSelected(void); -void ArmtronixInit(void); -void ArmtronixSerialInput(void); -void ArmtronixSetWifiLed(void); -bool Xdrv18(uint8_t function); -void PS16DZSerialSend(const char *tx_buffer); -void PS16DZSerialSendOk(void); -void PS16DZSerialSendUpdateCommand(void); -void PS16DZSerialInput(void); -bool PS16DZSerialSendUpdateCommandIfRequired(void); -void PS16DZInit(void); -bool PS16DZModuleSelected(void); -bool Xdrv19(uint8_t function); -String HueBridgeId(void); -String HueSerialnumber(void); -String HueUuid(void); -void HueRespondToMSearch(void); -String GetHueDeviceId(uint8_t id); -String GetHueUserId(void); -void HandleUpnpSetupHue(void); -void HueNotImplemented(String *path); -void HueConfigResponse(String *response); -void HueConfig(String *path); -uint8_t getLocalLightSubtype(uint8_t device); -void HueLightStatus1(uint8_t device, String *response); -bool HueActive(uint8_t device); -void HueLightStatus2(uint8_t device, String *response); -uint32_t EncodeLightId(uint8_t relay_id); -uint32_t DecodeLightId(uint32_t hue_id); -uint32_t findEchoGeneration(void); -void HueGlobalConfig(String *path); -void HueAuthentication(String *path); -void HueLights(String *path); -void HueGroups(String *path); -void HandleHueApi(String *path); -bool Xdrv20(uint8_t function); -String WemoSerialnumber(void); -String WemoUuid(void); -void WemoRespondToMSearch(int echo_type); -void HandleUpnpEvent(void); -void HandleUpnpService(void); -void HandleUpnpMetaService(void); -void HandleUpnpSetupWemo(void); -bool Xdrv21(uint8_t function); -bool IsModuleIfan(void); -uint8_t MaxFanspeed(void); -uint8_t GetFanspeed(void); -void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence); -void SonoffIfanReceived(void); -bool SonoffIfanSerialInput(void); -void CmndFanspeed(void); -bool SonoffIfanInit(void); -void SonoffIfanUpdate(void); -bool Xdrv22(uint8_t function); -void CopyJsonVariant(JsonObject &to, const String &key, const JsonVariant &val); -void CopyJsonArray(JsonArray &to, const JsonArray &arr); -void CopyJsonObject(JsonObject &to, const JsonObject &from); -uint16_t fromClusterCode(uint8_t c); -uint8_t toClusterCode(uint16_t c); -class SBuffer hibernateDevice(const struct Z_Device &device); -class SBuffer hibernateDevices(void); -void hidrateDevices(const SBuffer &buf); -void loadZigbeeDevices(void); -void saveZigbeeDevices(void); -void eraseZigbeeDevices(void); -uint8_t toPercentageCR2032(uint32_t voltage); -uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, - uint32_t offset, uint32_t len); -int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); -int32_t Z_AqaraCube(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); -void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint); -const __FlashStringHelper* zigbeeFindCommand(const char *command); -inline bool isXYZ(char c); -inline char hexDigit(uint32_t h); -String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z); -uint32_t ZigbeeAliasOrNumber(const char *state_text); -uint8_t ZigbeeGetInstructionSize(uint8_t instr); -void ZigbeeGotoLabel(uint8_t label); -void ZigbeeStateMachine_Run(void); -int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf); -int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf); -int32_t Z_Reboot(int32_t res, class SBuffer &buf); -int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf); -bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match); -int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf); -void Z_SendActiveEpReq(uint16_t shortaddr); -void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint); -int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf); -void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusterid, uint8_t transacid); -int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf); -void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, const JsonObject *json); -int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); -int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf); -int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf); -int32_t Z_Load_Devices(uint8_t value); -int32_t Z_State_Ready(uint8_t value); -int32_t ZigbeeProcessInput(class SBuffer &buf); -void ZigbeeInput(void); -void ZigbeeInit(void); -uint32_t strToUInt(const JsonVariant &val); -void CmndZbReset(void); -void CmndZbZNPSendOrReceive(bool send); -void CmndZbZNPReceive(void); -void CmndZbZNPSend(void); -void ZigbeeZNPSend(const uint8_t *msg, size_t len); -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp, uint8_t transacId); -inline int8_t hexValue(char c); -void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data); -void CmndZbSend(void); -void CmndZbBind(void); -void CmndZbProbe(void); -void CmndZbName(void); -void CmndZbForget(void); -void CmndZbSave(void); -void CmndZbRead(void); -void CmndZbPermitJoin(void); -void CmndZbStatus(void); -bool Xdrv23(uint8_t function); -void BuzzerOff(void); -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode); -void BuzzerSetStateToLed(uint32_t state); -void BuzzerBeep(uint32_t count); -void BuzzerEnabledBeep(uint32_t count, uint32_t duration); -bool BuzzerPinState(void); -void BuzzerInit(void); -void BuzzerEvery100mSec(void); -void CmndBuzzer(void); -bool Xdrv24(uint8_t function); -void A4988Init(void); -void CmndDoMove(void); -void CmndDoRotate(void); -void CmndDoTurn(void); -void CmndSetMIS(void); -void CmndSetSPR(void); -void CmndSetRPM(void); -bool Xdrv25(uint8_t function); -void AriluxRfInterrupt(void); -void AriluxRfHandler(void); -void AriluxRfInit(void); -void AriluxRfDisable(void); -bool Xdrv26(uint8_t function); -void ShutterLogPos(uint32_t i); -void ShutterRtc50mS(void); -int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index); -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index); -void ShutterInit(void); -void ShutterReportPosition(bool always); -void ShutterLimitRealAndTargetPositions(uint32_t i); -void ShutterUpdatePosition(void); -bool ShutterState(uint32_t device); -void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos); -void ShutterWaitForMotorStop(uint32_t i); -int32_t ShutterCounterBasedPosition(uint32_t i); -void ShutterRelayChanged(void); -bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index); -void ShutterButtonHandler(void); -void ShutterSetPosition(uint32_t device, uint32_t position); -void CmndShutterOpen(void); -void CmndShutterClose(void); -void CmndShutterStop(void); -void CmndShutterPosition(void); -void CmndShutterOpenTime(void); -void CmndShutterCloseTime(void); -void CmndShutterMotorDelay(void); -void CmndShutterRelay(void); -void CmndShutterButton(void); -void CmndShutterSetHalfway(void); -void CmndShutterFrequency(void); -void CmndShutterSetClose(void); -void CmndShutterInvert(void); -void CmndShutterCalibration(void); -void CmndShutterLock(void); -void CmndShutterEnableEndStopTime(void); -bool Xdrv27(uint8_t function); -void Pcf8574SwitchRelay(void); -void Pcf8574Init(void); -void HandlePcf8574(void); -void Pcf8574SaveSettings(void); -bool Xdrv28(uint8_t function); -bool DeepSleepEnabled(void); -void DeepSleepReInit(void); -void DeepSleepPrepare(void); -void DeepSleepStart(void); -void DeepSleepEverySecond(void); -void CmndDeepsleepTime(void); -bool Xdrv29(uint8_t function); -uint8_t crc8(const uint8_t *p, uint8_t len); -void ExsSendCmd(uint8_t cmd, uint8_t value); -uint8_t ExsSetPower(uint8_t device, uint8_t power); -uint8_t ExsSetBri(uint8_t device, uint8_t bri); -uint8_t ExsSyncState(uint8_t device); -bool ExsSyncState(); -void ExsDebugState(); -void ExsPacketProcess(void); -bool ExsModuleSelected(void); -bool ExsSetChannels(void); -bool ExsSetPower(void); -void EsxMcuStart(void); -void ExsInit(void); -void ExsSerialInput(void); -void CmndExsDimm(void); -void CmndExsDimmTbl(void); -void CmndExsDimmVal(void); -void CmndExsDimms(void); -void CmndExsChLock(void); -void CmndExsState(void); -bool Xdrv30(uint8_t function); -uint32_t TasmotaSlave_FlashStart(void); -uint8_t TasmotaSlave_UpdateInit(void); -void TasmotaSlave_Reset(void); -uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout); -uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count); -uint8_t TasmotaSlave_execCmd(uint8_t cmd); -uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count); -uint8_t TasmotaSlave_exitProgMode(void); -uint8_t TasmotaSlave_SetupFlash(void); -uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo); -void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data); -void TasmotaSlave_Flash(void); -void TasmotaSlave_SetFlagFlashing(bool value); -bool TasmotaSlave_GetFlagFlashing(void); -void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size); -void TasmotaSlave_Init(void); -void TasmotaSlave_Show(void); -void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param); -void CmndTasmotaSlaveReset(void); -void CmndTasmotaSlaveSend(void); -void TasmotaSlave_ProcessIn(void); -bool Xdrv31(uint8_t function); -void HotPlugInit(void); -void HotPlugEverySecond(void); -void CmndHotPlugTime(void); -bool Xdrv32(uint8_t function); -bool NRF24initRadio(); -bool NRF24Detect(void); -bool Xdrv33(uint8_t function); -void ExceptionTest(uint8_t type); -void CpuLoadLoop(void); -void DebugFreeMem(void); -void DebugFreeMem(void); -void DebugRtcDump(char* parms); -void DebugCfgDump(char* parms); -void DebugCfgPeek(char* parms); -void DebugCfgPoke(char* parms); -void SetFlashMode(uint8_t mode); -void CmndHelp(void); -void CmndRtcDump(void); -void CmndCfgDump(void); -void CmndCfgPeek(void); -void CmndCfgPoke(void); -void CmndCfgXor(void); -void CmndException(void); -void CmndCpuCheck(void); -void CmndFreemem(void); -void CmndSetSensor(void); -void CmndFlashMode(void); -uint32_t DebugSwap32(uint32_t x); -void CmndFlashDump(void); -void CmndI2cWrite(void); -void CmndI2cRead(void); -void CmndI2cStretch(void); -void CmndI2cClock(void); -bool Xdrv99(uint8_t function); -void XsnsDriverState(void); -bool XdrvRulesProcess(void); -void ShowFreeMem(const char *where); -bool XdrvCallDriver(uint32_t driver, uint8_t Function); -bool XdrvCall(uint8_t Function); -void LcdInitMode(void); -void LcdInit(uint8_t mode); -void LcdInitDriver(void); -void LcdDrawStringAt(void); -void LcdDisplayOnOff(uint8_t on); -void LcdCenter(uint8_t row, char* txt); -bool LcdPrintLog(void); -void LcdTime(void); -void LcdRefresh(void); -bool Xdsp01(uint8_t function); -void SSD1306InitDriver(void); -void Ssd1306PrintLog(void); -void Ssd1306Time(void); -void Ssd1306Refresh(void); -bool Xdsp02(byte function); -void MatrixWrite(void); -void MatrixClear(void); -void MatrixFixed(char* txt); -void MatrixCenter(char* txt); -void MatrixScrollLeft(char* txt, int loop); -void MatrixScrollUp(char* txt, int loop); -void MatrixInitMode(void); -void MatrixInit(uint8_t mode); -void MatrixInitDriver(void); -void MatrixOnOff(void); -void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void MatrixPrintLog(uint8_t direction); -void MatrixRefresh(void); -bool Xdsp03(uint8_t function); -void Ili9341InitMode(void); -void Ili9341Init(uint8_t mode); -void Ili9341InitDriver(void); -void Ili9341Clear(void); -void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void Ili9341DisplayOnOff(uint8_t on); -void Ili9341OnOff(void); -void Ili9341PrintLog(void); -void Ili9341Refresh(void); -bool Xdsp04(uint8_t function); -void EpdInitDriver29(); -void EpdPrintLog29(void); -void EpdRefresh29(void); -bool Xdsp05(uint8_t function); -void EpdInitDriver42(); -void EpdRefresh42(); -bool Xdsp06(uint8_t function); -void SH1106InitDriver(); -void SH1106PrintLog(void); -void SH1106Time(void); -void SH1106Refresh(void); -bool Xdsp07(uint8_t function); -void ILI9488_InitDriver(); -void ILI9488_MQTT(uint8_t count,const char *cp); -void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr); -void FT6236Check(); -bool Xdsp08(uint8_t function); -void SSD1351_InitDriver(); -void SSD1351PrintLog(void); -void SSD1351Time(void); -void SSD1351Refresh(void); -bool Xdsp09(uint8_t function); -void RA8876_InitDriver(); -void RA8876_MQTT(uint8_t count,const char *cp); -void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr); -void FT5316Check(); -bool Xdsp10(uint8_t function); -uint8_t XdspPresent(void); -bool XdspCall(uint8_t Function); -void Ws2812StripShow(void); -int mod(int a, int b); -void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset); -void Ws2812UpdateHand(int position, uint32_t index); -void Ws2812Clock(void); -void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i); -void Ws2812Gradient(uint32_t schemenr); -void Ws2812Bars(uint32_t schemenr); -void Ws2812Clear(void); -void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white); -char* Ws2812GetColor(uint32_t led, char* scolor); -void Ws2812ForceSuspend (void); -void Ws2812ForceUpdate (void); -bool Ws2812SetChannels(void); -void Ws2812ShowScheme(void); -void Ws2812ModuleSelected(void); -void CmndLed(void); -void CmndPixels(void); -void CmndRotation(void); -void CmndWidth(void); -bool Xlgt01(uint8_t function); -void LightDiPulse(uint8_t times); -void LightDckiPulse(uint8_t times); -void LightMy92x1Write(uint8_t data); -void LightMy92x1Init(void); -void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c); -bool My92x1SetChannels(void); -void My92x1ModuleSelected(void); -bool Xlgt02(uint8_t function); -void SM16716_SendBit(uint8_t v); -void SM16716_SendByte(uint8_t v); -void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b); -void SM16716_Init(void); -bool Sm16716SetChannels(void); -void Sm16716ModuleSelected(void); -bool Xlgt03(uint8_t function); -uint8_t Sm2135Write(uint8_t data); -void Sm2135Send(uint8_t *buffer, uint8_t size); -bool Sm2135SetChannels(void); -void Sm2135ModuleSelected(void); -bool Xlgt04(uint8_t function); -void SnfL1Send(const char *buffer); -void SnfL1SerialSendOk(void); -bool SnfL1SerialInput(void); -bool SnfL1SetChannels(void); -void SnfL1ModuleSelected(void); -bool Xlgt05(uint8_t function); -bool XlgtCall(uint8_t function); -void HlwCfInterrupt(void); -void HlwCf1Interrupt(void); -void HlwEvery200ms(void); -void HlwEverySecond(void); -void HlwSnsInit(void); -void HlwDrvInit(void); -bool HlwCommand(void); -bool Xnrg01(uint8_t function); -void CseReceived(void); -bool CseSerialInput(void); -void CseEverySecond(void); -void CseSnsInit(void); -void CseDrvInit(void); -bool CseCommand(void); -bool Xnrg02(uint8_t function); -uint8_t PzemCrc(uint8_t *data); -void PzemSend(uint8_t cmd); -bool PzemReceiveReady(void); -bool PzemRecieve(uint8_t resp, float *data); -void PzemEvery250ms(void); -void PzemSnsInit(void); -void PzemDrvInit(void); -bool PzemCommand(void); -bool Xnrg03(uint8_t function); -uint8_t McpChecksum(uint8_t *data); -unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size); -void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size); -void McpSend(uint8_t *data); -void McpGetAddress(void); -void McpAddressReceive(void); -void McpGetCalibration(void); -void McpParseCalibration(void); -bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift); -void McpSetCalibration(struct mcp_cal_registers_type *cal_registers); -void McpSetSystemConfiguration(uint16 interval); -void McpGetFrequency(void); -void McpParseFrequency(void); -void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency); -void McpGetData(void); -void McpParseData(void); -void McpSerialInput(void); -void McpEverySecond(void); -void McpSnsInit(void); -void McpDrvInit(void); -bool McpCommand(void); -bool Xnrg04(uint8_t function); -void PzemAcEverySecond(void); -void PzemAcSnsInit(void); -void PzemAcDrvInit(void); -bool PzemAcCommand(void); -bool Xnrg05(uint8_t function); -void PzemDcEverySecond(void); -void PzemDcSnsInit(void); -void PzemDcDrvInit(void); -bool PzemDcCommand(void); -bool Xnrg06(uint8_t function); -int Ade7953RegSize(uint16_t reg); -void Ade7953Write(uint16_t reg, uint32_t val); -int32_t Ade7953Read(uint16_t reg); -void Ade7953Init(void); -void Ade7953GetData(void); -void Ade7953EnergyEverySecond(void); -void Ade7953DrvInit(void); -bool Ade7953Command(void); -bool Xnrg07(uint8_t function); -void SDM120Every250ms(void); -void Sdm120SnsInit(void); -void Sdm120DrvInit(void); -void Sdm220Reset(void); -void Sdm220Show(bool json); -bool Xnrg08(uint8_t function); -void Dds2382EverySecond(void); -void Dds2382SnsInit(void); -void Dds2382DrvInit(void); -bool Xnrg09(uint8_t function); -void SDM630Every250ms(void); -void Sdm630SnsInit(void); -void Sdm630DrvInit(void); -bool Xnrg10(uint8_t function); -void DDSU666Every250ms(void); -void Ddsu666SnsInit(void); -void Ddsu666DrvInit(void); -bool Xnrg11(uint8_t function); -bool solaxX1_RS485ReceiveReady(void); -void solaxX1_RS485Send(uint16_t msgLen); -uint8_t solaxX1_RS485Receive(uint8_t *value); -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen); -void solaxX1_SendInverterAddress(void); -void solaxX1_QueryLiveData(void); -uint8_t solaxX1_ParseErrorCode(uint32_t code); -void solaxX1250MSecond(void); -void solaxX1SnsInit(void); -void solaxX1DrvInit(void); -void solaxX1Show(bool json); -bool Xnrg12(uint8_t function); -void FifLEEvery250ms(void); -void FifLESnsInit(void); -void FifLEDrvInit(void); -void FifLEReset(void); -void FifLEShow(bool json); -bool Xnrg13(uint8_t function); -bool XnrgCall(uint8_t function); -void CounterUpdate(uint8_t index); -void CounterUpdate1(void); -void CounterUpdate2(void); -void CounterUpdate3(void); -void CounterUpdate4(void); -bool CounterPinState(void); -void CounterInit(void); -void CounterEverySecond(void); -void CounterSaveState(void); -void CounterShow(bool json); -void CmndCounter(void); -void CmndCounterType(void); -void CmndCounterDebounce(void); -bool Xsns01(uint8_t function); -void AdcInit(void); -uint16_t AdcRead(uint8_t factor); -void AdcEvery250ms(void); -uint16_t AdcGetLux(void); -uint16_t AdcGetRange(void); -void AdcGetCurrentPower(uint8_t factor); -void AdcEverySecond(void); -void AdcShow(bool json); -void CmndAdc(void); -void CmndAdcs(void); -void CmndAdcParam(void); -bool Xsns02(uint8_t function); -void SonoffScSend(const char *data); -void SonoffScInit(void); -void SonoffScSerialInput(char *rcvstat); -void SonoffScShow(bool json); -bool Xsns04(uint8_t function); -uint8_t OneWireReset(void); -void OneWireWriteBit(uint8_t v); -uint8_t OneWireReadBit(void); -void OneWireWrite(uint8_t v); -uint8_t OneWireRead(void); -void OneWireSelect(const uint8_t rom[8]); -void OneWireResetSearch(void); -uint8_t OneWireSearch(uint8_t *newAddr); -bool OneWireCrc8(uint8_t *addr); -void Ds18x20Init(void); -void Ds18x20Convert(void); -bool Ds18x20Read(uint8_t sensor); -void Ds18x20Name(uint8_t sensor); -void Ds18x20EverySecond(void); -void Ds18x20Show(bool json); -bool Xsns05(uint8_t function); -void DhtReadPrep(void); -int32_t DhtExpectPulse(uint8_t sensor, bool level); -bool DhtRead(uint8_t sensor); -void DhtReadTempHum(uint8_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -void DhtReadPrep(void); -int32_t DhtExpectPulse(uint8_t sensor, bool level); -bool DhtRead(uint8_t sensor); -void DhtReadTempHum(uint8_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool DhtExpectPulse(uint8_t sensor, int level); -int DhtReadDat(uint8_t sensor); -bool DhtRead(uint8_t sensor); -void DhtReadTempHum(uint8_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool DhtExpectPulse(uint32_t sensor, uint32_t level); -bool DhtRead(uint32_t sensor); -void DhtReadTempHum(uint32_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool DhtWaitState(uint32_t sensor, uint32_t level); -bool DhtRead(uint32_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool ShtReset(void); -bool ShtSendCommand(const uint8_t cmd); -bool ShtAwaitResult(void); -int ShtReadData(void); -bool ShtRead(void); -void ShtDetect(void); -void ShtEverySecond(void); -void ShtShow(bool json); -bool Xsns07(uint8_t function); -uint8_t HtuCheckCrc8(uint16_t data); -uint8_t HtuReadDeviceId(void); -void HtuSetResolution(uint8_t resolution); -void HtuReset(void); -void HtuHeater(uint8_t heater); -void HtuInit(void); -bool HtuRead(void); -void HtuDetect(void); -void HtuEverySecond(void); -void HtuShow(bool json); -bool Xsns08(uint8_t function); -bool Bmp180Calibration(uint8_t bmp_idx); -void Bmp180Read(uint8_t bmp_idx); -bool Bmx280Calibrate(uint8_t bmp_idx); -void Bme280Read(uint8_t bmp_idx); -static void BmeDelayMs(uint32_t ms); -bool Bme680Init(uint8_t bmp_idx); -void Bme680Read(uint8_t bmp_idx); -void BmpDetect(void); -void BmpRead(void); -void BmpShow(bool json); -void BMP_EnterSleep(void); -bool Xsns09(uint8_t function); -bool Bh1750Read(void); -void Bh1750Detect(void); -void Bh1750EverySecond(void); -void Bh1750Show(bool json); -bool Xsns10(uint8_t function); -void Veml6070Detect(void); -void Veml6070UvTableInit(void); -void Veml6070EverySecond(void); -void Veml6070ModeCmd(bool mode_cmd); -uint16_t Veml6070ReadUv(void); -double Veml6070UvRiskLevel(uint16_t uv_level); -double Veml6070UvPower(double uvrisk); -void Veml6070Show(bool json); -bool Xsns11(uint8_t function); -void Ads1115StartComparator(uint8_t channel, uint16_t mode); -int16_t Ads1115GetConversion(uint8_t channel); -void Ads1115Detect(void); -void Ads1115Show(bool json); -bool Xsns12(uint8_t function); -bool Ina219SetCalibration(uint8_t mode, uint16_t addr); -float Ina219GetShuntVoltage_mV(uint16_t addr); -float Ina219GetBusVoltage_V(uint16_t addr); -float Ina219GetCurrent_mA(uint16_t addr); -bool Ina219Read(void); -bool Ina219CommandSensor(void); -void Ina219Detect(void); -void Ina219EverySecond(void); -void Ina219Show(bool json); -bool Xsns13(uint8_t function); -bool Sht3xRead(float &t, float &h, uint8_t sht3x_address); -void Sht3xDetect(void); -void Sht3xShow(bool json); -bool Xsns14(uint8_t function); -uint8_t MhzCalculateChecksum(uint8_t *array); -size_t MhzSendCmd(uint8_t command_id); -bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s); -void MhzEverySecond(void); -bool MhzCommandSensor(void); -void MhzInit(void); -void MhzShow(bool json); -bool Xsns15(uint8_t function); -bool Tsl2561Read(void); -void Tsl2561Detect(void); -void Tsl2561EverySecond(void); -void Tsl2561Show(bool json); -bool Xsns16(uint8_t function); -void Senseair250ms(void); -void SenseairInit(void); -void SenseairShow(bool json); -bool Xsns17(uint8_t function); -bool PmsReadData(void); -void PmsSecond(void); -void PmsInit(void); -void PmsShow(bool json); -bool Xsns18(uint8_t function); -void MGSInit(void); -void MGSPrepare(void); -char* measure_gas(int gas_type, char* buffer); -void MGSShow(bool json); -bool Xsns19(uint8_t function); -bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer); -void NovaSdsSetWorkPeriod(void); -bool NovaSdsReadData(void); -void NovaSdsSecond(void); -bool NovaSdsCommandSensor(void); -void NovaSdsInit(void); -void NovaSdsShow(bool json); -bool Xsns20(uint8_t function); -void sgp30_Init(void); -float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit); -void Sgp30Update(void); -void Sgp30Show(bool json); -bool Xsns21(uint8_t function); -uint8_t Sr04TModeDetect(void); -uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third); -uint16_t Sr04TMode3Distance(); -uint16_t Sr04TMode2Distance(void); -void Sr04TReading(void); -void Sr04Show(bool json); -bool Xsns22(uint8_t function); -uint8_t Si1145ReadByte(uint8_t reg); -uint16_t Si1145ReadHalfWord(uint8_t reg); -bool Si1145WriteByte(uint8_t reg, uint16_t val); -uint8_t Si1145WriteParamData(uint8_t p, uint8_t v); -bool Si1145Present(void); -void Si1145Reset(void); -void Si1145DeInit(void); -bool Si1145Begin(void); -uint16_t Si1145ReadUV(void); -uint16_t Si1145ReadVisible(void); -uint16_t Si1145ReadIR(void); -bool Si1145Read(void); -void Si1145Detect(void); -void Si1145Update(void); -void Si1145Show(bool json); -bool Xsns24(uint8_t function); -void LM75ADDetect(void); -float LM75ADGetTemp(void); -void LM75ADShow(bool json); -bool Xsns26(uint8_t function); -int8_t wireReadDataBlock( uint8_t reg, - uint8_t *val, - uint16_t len); -void calculateColorTemperature(void); -bool APDS9960_init(void); -uint8_t getMode(void); -void setMode(uint8_t mode, uint8_t enable); -void enableLightSensor(void); -void disableLightSensor(void); -void enableProximitySensor(void); -void disableProximitySensor(void); -void enableGestureSensor(void); -void disableGestureSensor(void); -bool isGestureAvailable(void); -int16_t readGesture(void); -void enablePower(void); -void disablePower(void); -void readAllColorAndProximityData(void); -void resetGestureParameters(void); -bool processGestureData(void); -bool decodeGesture(void); -void handleGesture(void); -void APDS9960_adjustATime(void); -void APDS9960_loop(void); -void APDS9960_detect(void); -void APDS9960_show(bool json); -bool APDS9960CommandSensor(void); -bool Xsns27(uint8_t function); -void Tm16XXSend(uint8_t data); -void Tm16XXSendCommand(uint8_t cmd); -void TM16XXSendData(uint8_t address, uint8_t data); -uint8_t Tm16XXReceive(void); -void Tm16XXClearDisplay(void); -void Tm1638SetLED(uint8_t color, uint8_t pos); -void Tm1638SetLEDs(word leds); -uint8_t Tm1638GetButtons(void); -void TmInit(void); -void TmLoop(void); -bool Xsns28(uint8_t function); -void MCP230xx_CheckForIntCounter(void); -void MCP230xx_CheckForIntRetainer(void); -const char* IntModeTxt(uint8_t intmo); -uint8_t MCP230xx_readGPIO(uint8_t port); -void MCP230xx_ApplySettings(void); -void MCP230xx_Detect(void); -void MCP230xx_CheckForInterrupt(void); -void MCP230xx_Show(bool json); -void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate); -void MCP230xx_Reset(uint8_t pinmode); -bool MCP230xx_Command(void); -void MCP230xx_UpdateWebData(void); -void MCP230xx_OutputTelemetry(void); -void MCP230xx_Interrupt_Counter_Report(void); -void MCP230xx_Interrupt_Retain_Report(void); -bool Xsns29(uint8_t function); -void Mpr121Init(struct mpr121 *pS, bool initial); -void Mpr121Show(struct mpr121 *pS, uint8_t function); -bool Xsns30(uint8_t function); -void CCS811Detect(void); -void CCS811Update(void); -void CCS811Show(bool json); -bool Xsns31(uint8_t function); -void MPU_6050PerformReading(void); -void MPU_6050Detect(void); -void MPU_6050Show(bool json); -bool Xsns32(uint8_t function); -void DS3231Detect(void); -uint8_t bcd2dec(uint8_t n); -uint8_t dec2bcd(uint8_t n); -uint32_t ReadFromDS3231(void); -void SetDS3231Time (uint32_t epoch_time); -void DS3231EverySecond(void); -bool Xsns33(uint8_t function); -bool HxIsReady(uint16_t timeout); -long HxRead(void); -void HxResetPart(void); -void HxReset(void); -void HxCalibrationStateTextJson(uint8_t msg_id); -void SetWeightDelta(); -bool HxCommand(void); -long HxWeight(void); -void HxInit(void); -void HxEvery100mSecond(void); -void HxSaveBeforeRestart(void); -void HxShow(bool json); -void HandleHxAction(void); -void HxSaveSettings(void); -void HxLogUpdates(void); -bool Xsns34(uint8_t function); -void Tx20StartRead(void); -void Tx20Read(void); -void Tx20Init(void); -void Tx20Show(bool json); -bool Xsns35(uint8_t function); -void MGC3130_handleSensorData(); -void MGC3130_sendMessage(uint8_t data[], uint8_t length); -void MGC3130_handleGesture(); -bool MGC3130_handleTouch(); -void MGC3130_handleAirWheel(); -void MGC3130_handleSystemStatus(); -bool MGC3130_receiveMessage(); -bool MGC3130_readData(); -void MGC3130_nextMode(); -void MGC3130_loop(); -void MGC3130_detect(void); -void MGC3130_show(bool json); -bool MGC3130CommandSensor(); -bool Xsns36(uint8_t function); -bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal); -void RfSnsInitTheoV2(void); -void RfSnsAnalyzeTheov2(void); -void RfSnsTheoV2Show(bool json); -void RfSnsInitAlectoV2(void); -void RfSnsAnalyzeAlectov2(); -void RfSnsAlectoResetRain(void); -uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len); -void RfSnsAlectoV2Show(bool json); -void RfSnsInit(void); -void RfSnsAnalyzeRawSignal(void); -void RfSnsEverySecond(void); -void RfSnsShow(bool json); -bool Xsns37(uint8_t function); -void AzEverySecond(void); -void AzInit(void); -void AzShow(bool json); -bool Xsns38(uint8_t function); -void MAX31855_Init(void); -void MAX31855_GetResult(void); -float MAX31855_GetProbeTemperature(int32_t RawData); -float MAX31855_GetReferenceTemperature(int32_t RawData); -int32_t MAX31855_ShiftIn(uint8_t Length); -void MAX31855_Show(bool Json); -bool Xsns39(uint8_t function); -void PN532_Init(void); -int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout); -int8_t PN532_readAckFrame(void); -uint32_t PN532_getFirmwareVersion(void); -void PN532_wakeup(void); -bool PN532_setPassiveActivationRetries(uint8_t maxRetries); -bool PN532_SAMConfig(void); -uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData); -uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data); -uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data); -void PN532_ScanForTag(void); -bool PN532_Command(void); -bool Xsns40(uint8_t function); -bool Max4409Read_lum(void); -void Max4409Detect(void); -void Max4409EverySecond(void); -void Max4409Show(bool json); -bool Xsns41(uint8_t function); -void Scd30Detect(void); -void Scd30Update(void); -int Scd30GetCommand(int command_code, uint16_t *pvalue); -int Scd30SetCommand(int command_code, uint16_t value); -bool Scd30CommandSensor(); -void Scd30Show(bool json); -bool Xsns42(byte function); -int hreReadBit(); -char hreReadChar(int &parity_errors); -void hreInit(void); -void hreEvery50ms(void); -void hreShow(boolean json); -bool Xsns43(byte function); -uint8_t sps30_calc_CRC(uint8_t *data); -void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen); -void sps30_cmd(uint16_t cmd); -void SPS30_Detect(void); -void SPS30_Every_Second(); -void SPS30_Show(bool json); -bool SPS30_cmd(void); -bool Xsns44(byte function); -void Vl53l0Detect(void); -void Vl53l0Every_250MSecond(void); -void Vl53l0Show(boolean json); -bool Xsns45(byte function); -void MLX90614_Init(void); -void MLX90614_Every_Second(void); -void MLX90614_Show(uint8_t json); -bool Xsns46(byte function); -void MAX31865_Init(void); -void MAX31865_GetResult(void); -void MAX31865_Show(bool Json); -bool Xsns47(uint8_t function); -void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg); -uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr); -void ChirpReset(uint8_t addr); -void ChirpResetAll(void); -void ChirpClockSet(); -void ChirpSleep(uint8_t addr); -void ChirpSelect(uint8_t sensor); -uint8_t ChirpReadVersion(uint8_t addr); -bool ChirpSet(uint8_t addr); -bool ChirpScan(); -void ChirpDetect(void); -void ChirpServiceAllSensors(uint8_t job); -void ChirpEvery100MSecond(void); -void ChirpShow(bool json); -bool ChirpCmd(void); -bool Xsns48(uint8_t function); -void PAJ7620SelectBank(uint8_t bank); -void PAJ7620DecodeGesture(void); -void PAJ7620ReadGesture(void); -void PAJ7620Detect(void); -void PAJ7620Init(void); -void PAJ7620Loop(void); -void PAJ7620Show(bool json); -bool PAJ7620CommandSensor(void); -bool Xsns50(uint8_t function); -void RDM6300_Init(); -void RDM6300_ScanForTag(); -uint8_t rm6300_hexnibble(char chr); -void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]); -void RDM6300_Show(void); -bool Xsns51(byte function); -void IBEACON_Init(); -void hm17_every_second(void); -void hm17_sbclr(void); -void hm17_sendcmd(uint8_t cmd); -uint32_t ibeacon_add(struct IBEACON *ib); -void hm17_decode(void); -void IBEACON_loop(); -void IBEACON_Show(void); -bool xsns52_cmd(void); -bool ibeacon_cmd(void); -void ib_sendbeep(void); -void ibeacon_mqtt(const char *mac,const char *rssi); -bool Xsns52(byte function); -double sml_median_array(double *array,uint8_t len); -double sml_median(struct SML_MEDIAN_FILTER* mf, double in); -void ADS1115_init(void); -bool Serial_available(); -uint8_t Serial_read(); -uint8_t Serial_peek(); -void Dump2log(void); -double sml_getvalue(unsigned char *cp,uint8_t index); -uint8_t hexnibble(char chr); -double CharToDouble(const char *str); -void ebus_esc(uint8_t *ebus_buffer, unsigned char len); -uint8_t ebus_crc8(uint8_t data, uint8_t crc_init); -uint8_t ebus_CalculateCRC( uint8_t *Data, uint16_t DataLen ); -void sml_empty_receiver(uint32_t meters); -void sml_shift_in(uint32_t meters,uint32_t shard); -void SML_Poll(void); -void SML_Decode(uint8_t index); -void SML_Immediate_MQTT(const char *mp,uint8_t index,uint8_t mindex); -void SML_Show(boolean json); -void SML_CounterUpd(uint8_t index); -void SML_CounterUpd1(void); -void SML_CounterUpd2(void); -void SML_CounterUpd3(void); -void SML_CounterUpd4(void); -bool Gpio_used(uint8_t gpiopin); -void SML_Init(void); -uint32_t SML_SetBaud(uint32_t meter, uint32_t br); -uint32_t SML_Write(uint32_t meter,char *hstr); -void SetDBGLed(uint8_t srcpin, uint8_t ledpin); -void SML_Counter_Poll(void); -void SML_Check_Send(void); -uint8_t sml_hexnibble(char chr); -void SML_Send_Seq(uint32_t meter,char *seq); -uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num); -uint8_t SML_PzemCrc(uint8_t *data, uint8_t len); -uint8_t CalcEvenParity(uint8_t data); -bool XSNS_53_cmd(void); -void InjektCounterValue(uint8_t meter,uint32_t counter); -void SML_CounterSaveState(void); -bool Xsns53(byte function); -static uint32_t _expand_r_shunt(uint16_t compact_r_shunt); -void Ina226SetCalibration(uint8_t slaveIndex); -bool Ina226TestPresence(uint8_t device); -void Ina226ResetActive(void); -void Ina226Init(); -float Ina226ReadBus_v(uint8_t device); -float Ina226ReadShunt_i(uint8_t device); -float Ina226ReadPower_w(uint8_t device); -void Ina226Read(uint8_t device); -void Ina226EverySecond(); -bool Ina226CommandSensor(); -void Ina226Show(bool json); -bool Xsns54(byte callback_id); -bool Hih6Read(void); -void Hih6Detect(void); -void Hih6EverySecond(void); -void Hih6Show(bool json); -bool Xsns55(uint8_t function); -void HpmaSecond(void); -void HpmaInit(void); -void HpmaShow(bool json); -bool Xsns56(uint8_t function); -void Tsl2591Init(void); -bool Tsl2591Read(void); -void Tsl2591EverySecond(void); -void Tsl2591Show(bool json); -bool Xsns57(uint8_t function); -bool Dht12Read(void); -void Dht12Detect(void); -void Dht12EverySecond(void); -void Dht12Show(bool json); -bool Xsns58(uint8_t function); -uint32_t DS1624_Idx2Addr(uint32_t idx); -int DS1624_Restart(uint8_t config, uint32_t idx); -void DS1624_HotPlugUp(uint32_t idx); -void DS1624_HotPlugDown(int idx); -bool DS1624GetTemp(float *value, int idx); -void DS1624HotPlugScan(void); -void DS1624EverySecond(void); -void DS1624Show(bool json); -bool Xsns59(uint8_t function); -void UBXcalcChecksum(char* CK, size_t msgSize); -bool UBXcompareMsgHeader(const char* msgHeader); -void UBXinitCFG(void); -void UBXTriggerTele(void); -void UBXDetect(void); -uint32_t UBXprocessGPS(); -void UBXsendHeader(void); -void UBXsendRecord(uint8_t *buf); -void UBXsendFooter(void); -void UBXsendFile(void); -void UBXSetRate(uint16_t interval); -void UBXSelectMode(uint16_t mode); -bool UBXHandlePOSLLH(); -void UBXHandleSTATUS(); -void UBXHandleTIME(); -void UBXHandleOther(void); -void UBXLoop50msec(void); -void UBXLoop(void); -void UBXShow(bool json); -bool UBXCmd(void); -bool Xsns60(uint8_t function); -bool MINRFinitBLE(uint8_t _mode); -void MINRFhopChannel(); -bool MINRFreceivePacket(void); -void MINRFswapbuf(uint8_t len); -void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr); -void MINRFreverseMAC(uint8_t _mac[]); -void MINRFchangePacketModeTo(uint8_t _mode); -void MINRFpurgeFakeSensors(void); -void MINRFhandleFloraPacket(void); -void MINRFhandleMJ_HT_V1Packet(void); -void MINRFhandleLYWSD02Packet(void); -void MINRFhandleLYWSD03Packet(void); -void MINRF_EVERY_50_MSECOND(); -void MINRFShow(bool json); -bool Xsns61(uint8_t function); -void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay); -void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot); -void HM10_Reset(void); -void HM10_Discovery_Scan(void); -void HM10_Read_LYWSD03(void); -void HM10_Read_LYWSD02(void); -void HM10_Time_LYWSD02(void); -void HM10SerialInit(void); -void HM10MACStringToBytes(const char* string, uint8_t _mac[]); -void HM10ParseResponse(char *buf); -void HM10readTempHum(char *_buf); -bool HM10readBat(char *_buf); -bool HM10SerialHandleFeedback(); -void HM10_TaskEvery100ms(); -void HM10EverySecond(); -bool HM10Cmd(void); -void HM10Show(bool json); -bool Xsns62(uint8_t function); -bool begin(); -bool AHT10Read(void); -unsigned char readStatus(void); -void AHT10Detect(void); -void AHT10EverySecond(void); -void AHT10Show(bool json); -bool Xsns64(uint8_t function); -void HandleMetrics(void); -bool Xsns91(uint8_t function); -bool XsnsEnabled(uint32_t sns_index); -void XsnsSensorState(void); -bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index); -bool XsnsCall(uint8_t Function); -bool I2cEnabled(uint32_t i2c_index); -void I2cDriverState(void); -#line 184 "C:/shared/sonoff/Git/Tasmota/tasmota/tasmota.ino" -void setup(void) -{ - global_state.data = 3; - - RtcRebootLoad(); - if (!RtcRebootValid()) { - RtcReboot.fast_reboot_count = 0; - } - RtcReboot.fast_reboot_count++; - RtcRebootSave(); - - Serial.begin(APP_BAUDRATE); - seriallog_level = LOG_LEVEL_INFO; - - snprintf_P(my_version, sizeof(my_version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); - if (VERSION & 0xff) { - snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); - } - - snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); - - SettingsLoad(); - SettingsDelta(); - - OsWatchInit(); - - GetFeatures(); - - if (1 == RtcReboot.fast_reboot_count) { - UpdateQuickPowerCycle(true); - XdrvCall(FUNC_SETTINGS_OVERRIDE); - } - - - seriallog_level = Settings.seriallog_level; - seriallog_timer = SERIALLOG_TIMER; - syslog_level = Settings.syslog_level; - stop_flash_rotate = Settings.flag.stop_flash_rotate; - save_data_counter = Settings.save_data; - sleep = Settings.sleep; -#ifndef USE_EMULATION - Settings.flag2.emulation = 0; -#else -#ifndef USE_EMULATION_WEMO - if (EMUL_WEMO == Settings.flag2.emulation) { Settings.flag2.emulation = 0; } -#endif -#ifndef USE_EMULATION_HUE - if (EMUL_HUE == Settings.flag2.emulation) { Settings.flag2.emulation = 0; } -#endif -#endif - - if (Settings.param[P_BOOT_LOOP_OFFSET]) { - - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET]) { - Settings.flag3.user_esp8285_enable = 0; - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +1) { - for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { - if (bitRead(Settings.rule_stop, i)) { - bitWrite(Settings.rule_enabled, i, 0); - } - } - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +2) { - Settings.rule_enabled = 0; - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } - Settings.my_adc0 = ADC0_NONE; - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { - Settings.module = SONOFF_BASIC; - - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); - } - } - - Format(mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(mqtt_client)); - Format(mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(mqtt_topic)); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME), mqtt_topic, ESP.getChipId() & 0x1FFF); - } else { - snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME)); - } - - GetEspHardwareType(); - GpioInit(); - - - - WifiConnect(); - - SetPowerOnState(); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, SettingsText(SET_FRIENDLYNAME1), my_version, my_image); -#ifdef FIRMWARE_MINIMAL - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); -#endif - - memcpy_P(log_data, VERSION_MARKER, 1); - - RtcInit(); - -#ifdef USE_ARDUINO_OTA - ArduinoOTAInit(); -#endif - - XdrvCall(FUNC_INIT); - XsnsCall(FUNC_INIT); -} - -void BacklogLoop(void) -{ - if (TimeReached(backlog_delay)) { - if (!BACKLOG_EMPTY && !backlog_mutex) { -#ifdef SUPPORT_IF_STATEMENT - backlog_mutex = true; - String cmd = backlog.shift(); - backlog_mutex = false; - ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); -#else - backlog_mutex = true; - ExecuteCommand((char*)backlog[backlog_pointer].c_str(), SRC_BACKLOG); - backlog_pointer++; - if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } - backlog_mutex = false; -#endif - } - } -} - -void loop(void) -{ - uint32_t my_sleep = millis(); - - XdrvCall(FUNC_LOOP); - XsnsCall(FUNC_LOOP); - - OsWatchLoop(); - - ButtonLoop(); - SwitchLoop(); -#ifdef ROTARY_V1 - RotaryLoop(); -#endif - BacklogLoop(); - - if (TimeReached(state_50msecond)) { - SetNextTimeInterval(state_50msecond, 50); - XdrvCall(FUNC_EVERY_50_MSECOND); - XsnsCall(FUNC_EVERY_50_MSECOND); - } - if (TimeReached(state_100msecond)) { - SetNextTimeInterval(state_100msecond, 100); - Every100mSeconds(); - XdrvCall(FUNC_EVERY_100_MSECOND); - XsnsCall(FUNC_EVERY_100_MSECOND); - } - if (TimeReached(state_250msecond)) { - SetNextTimeInterval(state_250msecond, 250); - Every250mSeconds(); - XdrvCall(FUNC_EVERY_250_MSECOND); - XsnsCall(FUNC_EVERY_250_MSECOND); - } - if (TimeReached(state_second)) { - SetNextTimeInterval(state_second, 1000); - PerformEverySecond(); - XdrvCall(FUNC_EVERY_SECOND); - XsnsCall(FUNC_EVERY_SECOND); - } - - if (!serial_local) { SerialInput(); } - -#ifdef USE_ARDUINO_OTA - ArduinoOtaLoop(); -#endif - - uint32_t my_activity = millis() - my_sleep; - - if (Settings.flag3.sleep_normal) { - - delay(sleep); - } else { - if (my_activity < (uint32_t)sleep) { - delay((uint32_t)sleep - my_activity); - } else { - if (global_state.wifi_down) { - delay(my_activity /2); - } - } - } - - if (!my_activity) { my_activity++; } - uint32_t loop_delay = sleep; - if (!loop_delay) { loop_delay++; } - uint32_t loops_per_second = 1000 / loop_delay; - uint32_t this_cycle_ratio = 100 * my_activity / loop_delay; - loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/sendemail.ino" -#ifdef USE_SENDMAIL - -#include "sendemail.h" -# 25 "C:/shared/sonoff/Git/Tasmota/tasmota/sendemail.ino" -#ifndef SEND_MAIL_MINRAM -#define SEND_MAIL_MINRAM 12*1024 -#endif - -#define xPSTR(a) a - -uint16_t SendMail(char *buffer) { - char *params,*oparams; - const char *mserv; - uint16_t port; - const char *user; - const char *pstr; - const char *passwd; - const char *from; - const char *to; - const char *subject; - const char *cmd; - char auth=0; - uint16_t status=1; - SendEmail *mail=0; - uint16_t blen; - char *endcmd; - - - - uint16_t mem=ESP.getFreeHeap(); - if (memsend(from,to,subject,cmd); - delete mail; - if (result==true) status=0; - } - -exit: - if (oparams) free(oparams); - return status; -} - -void script_send_email_body(BearSSL::WiFiClientSecure_light *client); - - -SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) : - host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) { -} - -String SendEmail::readClient() { - delay(0); - String r = client->readStringUntil('\n'); - - r.trim(); - while (client->available()) { - delay(0); - r += client->readString(); - } - return r; -} - -bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) { -bool status=false; -String buffer; - - if (!host.length()) { - return status; - } - - client->setTimeout(timeout); - -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("Connecting: %s on port %d"),host.c_str(),port); -#endif - - if (!client->connect(host.c_str(), port)) { -#ifdef DEBUG_EMAIL_PORT - AddLog_P(LOG_LEVEL_INFO, PSTR("Connection failed")); -#endif - goto exit; - } - - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("220"))) { - goto exit; - } - - buffer = F("EHLO "); - buffer += client->localIP().toString(); - - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("250"))) { - goto exit; - } - if (user.length()>0 && passwd.length()>0 ) { - - buffer = F("AUTH LOGIN"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("334"))) - { - goto exit; - } - base64 b; - buffer = b.encode(user); - - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("334"))) { - goto exit; - } - buffer = b.encode(passwd); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("235"))) { - goto exit; - } - } - - - buffer = F("MAIL FROM:"); - buffer += from; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("250"))) { - goto exit; - } - buffer = F("RCPT TO:"); - buffer += to; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("250"))) { - goto exit; - } - - buffer = F("DATA"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("354"))) { - goto exit; - } - buffer = F("From: "); - buffer += from; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = F("To: "); - buffer += to; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = F("Subject: "); - buffer += subject; - buffer += F("\r\n"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - -#ifdef USE_SCRIPT - if (*msg=='*' && *(msg+1)==0) { - script_send_email_body(client); - } else { - client->println(msg); - } -#else - client->println(msg); -#endif - client->println('.'); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - - buffer = F("QUIT"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - - status=true; -exit: - - return status; -} - - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/settings.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/settings.ino" -#ifndef DOMOTICZ_UPDATE_TIMER -#define DOMOTICZ_UPDATE_TIMER 0 -#endif - -#ifndef EMULATION -#define EMULATION EMUL_NONE -#endif - -#ifndef MTX_ADDRESS1 -#define MTX_ADDRESS1 0 -#endif -#ifndef MTX_ADDRESS2 -#define MTX_ADDRESS2 0 -#endif -#ifndef MTX_ADDRESS3 -#define MTX_ADDRESS3 0 -#endif -#ifndef MTX_ADDRESS4 -#define MTX_ADDRESS4 0 -#endif -#ifndef MTX_ADDRESS5 -#define MTX_ADDRESS5 0 -#endif -#ifndef MTX_ADDRESS6 -#define MTX_ADDRESS6 0 -#endif -#ifndef MTX_ADDRESS7 -#define MTX_ADDRESS7 0 -#endif -#ifndef MTX_ADDRESS8 -#define MTX_ADDRESS8 0 -#endif - -#ifndef HOME_ASSISTANT_DISCOVERY_ENABLE -#define HOME_ASSISTANT_DISCOVERY_ENABLE 0 -#endif - -#ifndef LATITUDE -#define LATITUDE 48.858360 -#endif -#ifndef LONGITUDE -#define LONGITUDE 2.294442 -#endif - -#ifndef WORKING_PERIOD -#define WORKING_PERIOD 5 -#endif - -#ifndef COLOR_TEXT -#define COLOR_TEXT "#000" -#endif -#ifndef COLOR_BACKGROUND -#define COLOR_BACKGROUND "#fff" -#endif -#ifndef COLOR_FORM -#define COLOR_FORM "#f2f2f2" -#endif -#ifndef COLOR_INPUT_TEXT -#define COLOR_INPUT_TEXT "#000" -#endif -#ifndef COLOR_INPUT -#define COLOR_INPUT "#fff" -#endif -#ifndef COLOR_CONSOLE_TEXT -#define COLOR_CONSOLE_TEXT "#000" -#endif -#ifndef COLOR_CONSOLE -#define COLOR_CONSOLE "#fff" -#endif -#ifndef COLOR_TEXT_WARNING -#define COLOR_TEXT_WARNING "#f00" -#endif -#ifndef COLOR_TEXT_SUCCESS -#define COLOR_TEXT_SUCCESS "#008000" -#endif -#ifndef COLOR_BUTTON_TEXT -#define COLOR_BUTTON_TEXT "#fff" -#endif -#ifndef COLOR_BUTTON -#define COLOR_BUTTON "#1fa3ec" -#endif -#ifndef COLOR_BUTTON_HOVER -#define COLOR_BUTTON_HOVER "#0e70a4" -#endif -#ifndef COLOR_BUTTON_RESET -#define COLOR_BUTTON_RESET "#d43535" -#endif -#ifndef COLOR_BUTTON_RESET_HOVER -#define COLOR_BUTTON_RESET_HOVER "#931f1f" -#endif -#ifndef COLOR_BUTTON_SAVE -#define COLOR_BUTTON_SAVE "#47c266" -#endif -#ifndef COLOR_BUTTON_SAVE_HOVER -#define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" -#endif -#ifndef COLOR_TIMER_TAB_TEXT -#define COLOR_TIMER_TAB_TEXT "#fff" -#endif -#ifndef COLOR_TIMER_TAB_BACKGROUND -#define COLOR_TIMER_TAB_BACKGROUND "#999" -#endif -#ifndef COLOR_TITLE_TEXT -#define COLOR_TITLE_TEXT COLOR_TEXT -#endif -#ifndef IR_RCV_MIN_UNKNOWN_SIZE -#define IR_RCV_MIN_UNKNOWN_SIZE 6 -#endif -#ifndef ENERGY_OVERTEMP -#define ENERGY_OVERTEMP 90 -#endif -#ifndef DEFAULT_DIMMER_MAX -#define DEFAULT_DIMMER_MAX 100 -#endif -#ifndef DEFAULT_DIMMER_MIN -#define DEFAULT_DIMMER_MIN 0 -#endif -#ifndef DEFAULT_LIGHT_DIMMER -#define DEFAULT_LIGHT_DIMMER 10 -#endif -#ifndef DEFAULT_LIGHT_COMPONENT -#define DEFAULT_LIGHT_COMPONENT 255 -#endif -#ifndef CORS_ENABLED_ALL -#define CORS_ENABLED_ALL "*" -#endif - - -enum WebColors { - COL_TEXT, COL_BACKGROUND, COL_FORM, - COL_INPUT_TEXT, COL_INPUT, COL_CONSOLE_TEXT, COL_CONSOLE, - COL_TEXT_WARNING, COL_TEXT_SUCCESS, - COL_BUTTON_TEXT, COL_BUTTON, COL_BUTTON_HOVER, COL_BUTTON_RESET, COL_BUTTON_RESET_HOVER, COL_BUTTON_SAVE, COL_BUTTON_SAVE_HOVER, - COL_TIMER_TAB_TEXT, COL_TIMER_TAB_BACKGROUND, COL_TITLE, - COL_LAST }; - -const char kWebColors[] PROGMEM = - COLOR_TEXT "|" COLOR_BACKGROUND "|" COLOR_FORM "|" - COLOR_INPUT_TEXT "|" COLOR_INPUT "|" COLOR_CONSOLE_TEXT "|" COLOR_CONSOLE "|" - COLOR_TEXT_WARNING "|" COLOR_TEXT_SUCCESS "|" - COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|" - COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT; - -enum TasmotaSerialConfig { - TS_SERIAL_5N1, TS_SERIAL_6N1, TS_SERIAL_7N1, TS_SERIAL_8N1, - TS_SERIAL_5N2, TS_SERIAL_6N2, TS_SERIAL_7N2, TS_SERIAL_8N2, - TS_SERIAL_5E1, TS_SERIAL_6E1, TS_SERIAL_7E1, TS_SERIAL_8E1, - TS_SERIAL_5E2, TS_SERIAL_6E2, TS_SERIAL_7E2, TS_SERIAL_8E2, - TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1, - TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 }; - -const uint8_t kTasmotaSerialConfig[] PROGMEM = { - SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1, - SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2, - SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1, - SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2, - SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1, - SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2 -}; - - - - - -const uint16_t RTC_MEM_VALID = 0xA55A; - -uint32_t rtc_settings_crc = 0; - -uint32_t GetRtcSettingsCrc(void) -{ - uint32_t crc = 0; - uint8_t *bytes = (uint8_t*)&RtcSettings; - - for (uint32_t i = 0; i < sizeof(RTCMEM); i++) { - crc += bytes[i]*(i+1); - } - return crc; -} - -void RtcSettingsSave(void) -{ - if (GetRtcSettingsCrc() != rtc_settings_crc) { - RtcSettings.valid = RTC_MEM_VALID; - ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); - rtc_settings_crc = GetRtcSettingsCrc(); - } -} - -void RtcSettingsLoad(void) -{ - ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); - if (RtcSettings.valid != RTC_MEM_VALID) { - memset(&RtcSettings, 0, sizeof(RTCMEM)); - RtcSettings.valid = RTC_MEM_VALID; - RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; - RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; - RtcSettings.energy_usage = Settings.energy_usage; - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; - } - RtcSettings.power = Settings.power; - RtcSettingsSave(); - } - rtc_settings_crc = GetRtcSettingsCrc(); -} - -bool RtcSettingsValid(void) -{ - return (RTC_MEM_VALID == RtcSettings.valid); -} - - - -uint32_t rtc_reboot_crc = 0; - -uint32_t GetRtcRebootCrc(void) -{ - uint32_t crc = 0; - uint8_t *bytes = (uint8_t*)&RtcReboot; - - for (uint32_t i = 0; i < sizeof(RTCRBT); i++) { - crc += bytes[i]*(i+1); - } - return crc; -} - -void RtcRebootSave(void) -{ - if (GetRtcRebootCrc() != rtc_reboot_crc) { - RtcReboot.valid = RTC_MEM_VALID; - ESP.rtcUserMemoryWrite(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); - rtc_reboot_crc = GetRtcRebootCrc(); - } -} - -void RtcRebootReset(void) -{ - RtcReboot.fast_reboot_count = 0; - RtcRebootSave(); -} - -void RtcRebootLoad(void) -{ - ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); - if (RtcReboot.valid != RTC_MEM_VALID) { - memset(&RtcReboot, 0, sizeof(RTCRBT)); - RtcReboot.valid = RTC_MEM_VALID; - - RtcRebootSave(); - } - rtc_reboot_crc = GetRtcRebootCrc(); -} - -bool RtcRebootValid(void) -{ - return (RTC_MEM_VALID == RtcReboot.valid); -} - - - - - -extern "C" { -#include "spi_flash.h" -} -#include "eboot_command.h" - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) - -extern "C" uint32_t _SPIFFS_end; - -const uint32_t SPIFFS_END = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; - -#else - -#if AUTOFLASHSIZE - -#include "flash_hal.h" - - -const uint32_t SPIFFS_END = (FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; - -#else - -extern "C" uint32_t _FS_end; - -const uint32_t SPIFFS_END = ((uint32_t)&_FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; - -#endif - -#endif - - -const uint32_t SETTINGS_LOCATION = SPIFFS_END; - -const uint8_t CFG_ROTATES = 8; - -uint32_t settings_location = SETTINGS_LOCATION; -uint32_t settings_crc32 = 0; -uint8_t *settings_buffer = nullptr; - - - - - -void SetFlashModeDout(void) -{ - uint8_t *_buffer; - uint32_t address; - - eboot_command ebcmd; - eboot_command_read(&ebcmd); - address = ebcmd.args[0]; - _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - - if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { - if (_buffer[2] != 3) { - _buffer[2] = 3; - if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { - ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); - } - } - } - delete[] _buffer; -} - -bool VersionCompatible(void) -{ - if (Settings.flag3.compatibility_check) { - return true; - } - - eboot_command ebcmd; - eboot_command_read(&ebcmd); - uint32_t start_address = ebcmd.args[0]; - uint32_t end_address = start_address + (ebcmd.args[2] & 0xFFFFF000) + FLASH_SECTOR_SIZE; - uint32_t* buffer = new uint32_t[FLASH_SECTOR_SIZE / 4]; - - uint32_t version[3] = { 0 }; - bool found = false; - for (uint32_t address = start_address; address < end_address; address = address + FLASH_SECTOR_SIZE) { - ESP.flashRead(address, (uint32_t*)buffer, FLASH_SECTOR_SIZE); - if ((address == start_address) && (0x1F == (buffer[0] & 0xFF))) { - version[1] = 0xFFFFFFFF; - found = true; - } else { - for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) { - version[0] = version[1]; - version[1] = version[2]; - version[2] = buffer[i]; - if ((MARKER_START == version[0]) && (MARKER_END == version[2])) { - found = true; - break; - } - } - } - if (found) { break; } - } - delete[] buffer; - - if (!found) { version[1] = 0; } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: Version 0x%08X, Compatible 0x%08X"), version[1], VERSION_COMPATIBLE); - - if (version[1] < VERSION_COMPATIBLE) { - uint32_t eboot_magic = 0; - ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic)); - return false; - } - - return true; -} - -void SettingsBufferFree(void) -{ - if (settings_buffer != nullptr) { - free(settings_buffer); - settings_buffer = nullptr; - } -} - -bool SettingsBufferAlloc(void) -{ - SettingsBufferFree(); - if (!(settings_buffer = (uint8_t *)malloc(sizeof(Settings)))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_UPLOAD_ERR_2)); - return false; - } - return true; -} - -uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size) -{ - uint16_t crc = 0; - - for (uint32_t i = 0; i < size; i++) { - if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } - } - return crc; -} - -uint16_t GetSettingsCrc(void) -{ - - uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG); - return GetCfgCrc16((uint8_t*)&Settings, size); -} - -uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size) -{ - - uint32_t crc = 0; - - while (size--) { - crc ^= *bytes++; - for (uint32_t j = 0; j < 8; j++) { - crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); - } - } - return ~crc; -} - -uint32_t GetSettingsCrc32(void) -{ - return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); -} - -void SettingsSaveAll(void) -{ - if (Settings.flag.save_state) { - Settings.power = power; - } else { - Settings.power = 0; - } - XsnsCall(FUNC_SAVE_BEFORE_RESTART); - XdrvCall(FUNC_SAVE_BEFORE_RESTART); - SettingsSave(0); -} - - - - - -void UpdateQuickPowerCycle(bool update) -{ - if (Settings.flag3.fast_power_cycle_disable) { return; } - - uint32_t pc_register; - uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES; - - ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); - if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) { - uint32_t counter = ((pc_register & 0xF) << 1) & 0xF; - if (0 == counter) { - SettingsErase(3); - EspRestart(); - } else { - pc_register = 0xFFA55AB0 | counter; - ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter); - } - } - else if (pc_register != 0xFFA55ABF) { - pc_register = 0xFFA55ABF; - - if (ESP.flashEraseSector(pc_location)) { - ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset")); - } -} - - - - - -uint32_t GetSettingsTextLen(void) -{ - char* position = Settings.text_pool; - for (uint32_t size = 0; size < SET_MAX; size++) { - while (*position++ != '\0') { } - } - return position - Settings.text_pool; -} - -bool SettingsUpdateText(uint32_t index, const char* replace_me) -{ - if (index >= SET_MAX) { - return false; - } - - - uint32_t replace_len = strlen(replace_me); - char replace[replace_len +1]; - memcpy(replace, replace_me, sizeof(replace)); - - uint32_t start_pos = 0; - uint32_t end_pos = 0; - char* position = Settings.text_pool; - for (uint32_t size = 0; size < SET_MAX; size++) { - while (*position++ != '\0') { } - if (1 == index) { - start_pos = position - Settings.text_pool; - } - else if (0 == index) { - end_pos = position - Settings.text_pool -1; - } - index--; - } - uint32_t char_len = position - Settings.text_pool; - - uint32_t current_len = end_pos - start_pos; - int diff = replace_len - current_len; - - - - - int too_long = (char_len + diff) - settings_text_size; - if (too_long > 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text overflow by %d char(s)"), too_long); - return false; - } - - if (diff != 0) { - - memmove_P(Settings.text_pool + start_pos + replace_len, Settings.text_pool + end_pos, char_len - end_pos); - } - - memmove_P(Settings.text_pool + start_pos, replace, replace_len); - - memset(Settings.text_pool + char_len + diff, 0x00, settings_text_size - char_len - diff); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d"), GetSettingsTextLen(), settings_text_size); - - return true; -} - -char* SettingsText(uint32_t index) -{ - char* position = Settings.text_pool; - - if (index >= SET_MAX) { - position += settings_text_size -1; - } else { - for (;index > 0; index--) { - while (*position++ != '\0') { } - } - } - return position; -} - - - - - -uint32_t GetSettingsAddress(void) -{ - return settings_location * SPI_FLASH_SEC_SIZE; -} - -void SettingsSave(uint8_t rotate) -{ -# 590 "C:/shared/sonoff/Git/Tasmota/tasmota/settings.ino" -#ifndef FIRMWARE_MINIMAL - if ((GetSettingsCrc32() != settings_crc32) || rotate) { - if (1 == rotate) { - stop_flash_rotate = 1; - } - if (2 == rotate) { - settings_location = SETTINGS_LOCATION +1; - } - if (stop_flash_rotate) { - settings_location = SETTINGS_LOCATION; - } else { - settings_location--; - if (settings_location <= (SETTINGS_LOCATION - CFG_ROTATES)) { - settings_location = SETTINGS_LOCATION; - } - } - - Settings.save_flag++; - if (UtcTime() > START_VALID_TIME) { - Settings.cfg_timestamp = UtcTime(); - } else { - Settings.cfg_timestamp++; - } - Settings.cfg_size = sizeof(SYSCFG); - Settings.cfg_crc = GetSettingsCrc(); - Settings.cfg_crc32 = GetSettingsCrc32(); - - if (ESP.flashEraseSector(settings_location)) { - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - } - - if (!stop_flash_rotate && rotate) { - for (uint32_t i = 1; i < CFG_ROTATES; i++) { - ESP.flashEraseSector(settings_location -i); - delay(1); - } - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); - - settings_crc32 = Settings.cfg_crc32; - } -#endif - RtcSettingsSave(); -} - -void SettingsLoad(void) -{ - - struct SYSCFGH { - uint16_t cfg_holder; - uint16_t cfg_size; - unsigned long save_flag; - } _SettingsH; - unsigned long save_flag = 0; - - settings_location = 0; - uint32_t flash_location = SETTINGS_LOCATION +1; - uint16_t cfg_holder = 0; - for (uint32_t i = 0; i < CFG_ROTATES; i++) { - flash_location--; - ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - - bool valid = false; - if (Settings.version > 0x06000000) { - bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32()); - if (Settings.version < 0x0606000B) { - almost_valid = (Settings.cfg_crc == GetSettingsCrc()); - } - - if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } - valid = (cfg_holder == Settings.cfg_holder); - } else { - ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); - valid = (Settings.cfg_holder == _SettingsH.cfg_holder); - } - if (valid) { - if (Settings.save_flag > save_flag) { - save_flag = Settings.save_flag; - settings_location = flash_location; - if (Settings.flag.stop_flash_rotate && (0 == i)) { - break; - } - } - } - - delay(1); - } - if (settings_location > 0) { - ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); - } - -#ifndef FIRMWARE_MINIMAL - if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { - SettingsDefault(); - } - settings_crc32 = GetSettingsCrc32(); -#endif - - RtcSettingsLoad(); -} - -void EspErase(uint32_t start_sector, uint32_t end_sector) -{ - bool serial_output = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); - for (uint32_t sector = start_sector; sector < end_sector; sector++) { - - bool result = ESP.flashEraseSector(sector); - - - - if (serial_output) { -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - Serial.printf(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n", sector, (result) ? D_OK : D_ERROR); -#else - Serial.printf_P(PSTR(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n"), sector, (result) ? D_OK : D_ERROR); -#endif - delay(10); - } else { - yield(); - } - OsWatchLoop(); - } -} - -void SettingsErase(uint8_t type) -{ -# 733 "C:/shared/sonoff/Git/Tasmota/tasmota/settings.ino" -#ifndef FIRMWARE_MINIMAL - uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; - uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; - if (1 == type) { - - _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; - } - else if (2 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; - _sectorEnd = SETTINGS_LOCATION +1; - } - else if (3 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; - _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart); - - - EsptoolErase(_sectorStart, _sectorEnd); -#endif -} - -void SettingsSdkErase(void) -{ - WiFi.disconnect(true); - SettingsErase(1); - delay(1000); -} - - - -void SettingsDefault(void) -{ - AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_USE_DEFAULTS)); - SettingsDefaultSet1(); - SettingsDefaultSet2(); - SettingsSave(2); -} - -void SettingsDefaultSet1(void) -{ - memset(&Settings, 0x00, sizeof(SYSCFG)); - - Settings.cfg_holder = (uint16_t)CFG_HOLDER; - Settings.cfg_size = sizeof(SYSCFG); - - Settings.version = VERSION; - - -} - -void SettingsDefaultSet2(void) -{ - memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); - - Settings.flag.stop_flash_rotate = APP_FLASH_CYCLE; - Settings.flag.global_state = APP_ENABLE_LEDLINK; - Settings.flag3.sleep_normal = APP_NORMAL_SLEEP; - Settings.flag3.no_power_feedback = APP_NO_RELAY_SCAN; - Settings.flag3.fast_power_cycle_disable = APP_DISABLE_POWERCYCLE; - Settings.flag3.bootcount_update = DEEPSLEEP_BOOTCOUNT; - Settings.flag3.compatibility_check = OTA_COMPATIBILITY; - Settings.save_data = SAVE_DATA; - Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; - Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; - Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; - Settings.sleep = APP_SLEEP; - if (Settings.sleep < 50) { - Settings.sleep = 50; - } - - - - Settings.interlock[0] = 0xFF; - Settings.module = MODULE; - ModuleDefault(WEMOS); - - SettingsUpdateText(SET_FRIENDLYNAME1, FRIENDLY_NAME); - SettingsUpdateText(SET_FRIENDLYNAME2, FRIENDLY_NAME"2"); - SettingsUpdateText(SET_FRIENDLYNAME3, FRIENDLY_NAME"3"); - SettingsUpdateText(SET_FRIENDLYNAME4, FRIENDLY_NAME"4"); - SettingsUpdateText(SET_OTAURL, OTA_URL); - - - Settings.flag.save_state = SAVE_STATE; - Settings.power = APP_POWER; - Settings.poweronstate = APP_POWERON_STATE; - Settings.blinktime = APP_BLINKTIME; - Settings.blinkcount = APP_BLINKCOUNT; - Settings.ledstate = APP_LEDSTATE; - Settings.ledmask = APP_LEDMASK; - Settings.pulse_timer[0] = APP_PULSETIME; - - - - Settings.serial_config = TS_SERIAL_8N1; - Settings.baudrate = APP_BAUDRATE / 300; - Settings.sbaudrate = SOFT_BAUDRATE / 300; - Settings.serial_delimiter = 0xff; - Settings.seriallog_level = SERIAL_LOG_LEVEL; - - - Settings.flag3.use_wifi_scan = WIFI_SCAN_AT_RESTART; - Settings.flag3.use_wifi_rescan = WIFI_SCAN_REGULARLY; - Settings.wifi_output_power = 170; - ParseIp(&Settings.ip_address[0], WIFI_IP_ADDRESS); - ParseIp(&Settings.ip_address[1], WIFI_GATEWAY); - ParseIp(&Settings.ip_address[2], WIFI_SUBNETMASK); - ParseIp(&Settings.ip_address[3], WIFI_DNS); - Settings.sta_config = WIFI_CONFIG_TOOL; - - SettingsUpdateText(SET_STASSID1, STA_SSID1); - SettingsUpdateText(SET_STASSID2, STA_SSID2); - SettingsUpdateText(SET_STAPWD1, STA_PASS1); - SettingsUpdateText(SET_STAPWD2, STA_PASS2); - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - - - SettingsUpdateText(SET_SYSLOG_HOST, SYS_LOG_HOST); - Settings.syslog_port = SYS_LOG_PORT; - Settings.syslog_level = SYS_LOG_LEVEL; - - - Settings.flag2.emulation = EMULATION; - Settings.flag3.gui_hostname_ip = GUI_SHOW_HOSTNAME; - Settings.flag3.mdns_enabled = MDNS_ENABLED; - Settings.webserver = WEB_SERVER; - Settings.weblog_level = WEB_LOG_LEVEL; - SettingsUpdateText(SET_WEBPWD, WEB_PASSWORD); - SettingsUpdateText(SET_CORS, CORS_DOMAIN); - - - Settings.flag.button_restrict = KEY_DISABLE_MULTIPRESS; - Settings.flag.button_swap = KEY_SWAP_DOUBLE_PRESS; - Settings.flag.button_single = KEY_ONLY_SINGLE_PRESS; - Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; - - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { Settings.switchmode[i] = SWITCH_MODE; } - - - Settings.flag.mqtt_enabled = MQTT_USE; - Settings.flag.mqtt_response = MQTT_RESULT_COMMAND; - Settings.flag.mqtt_offline = MQTT_LWT_MESSAGE; - Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN; - Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; - Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - Settings.flag.mqtt_sensor_retain = MQTT_SENSOR_RETAIN; - - Settings.flag.device_index_enable = MQTT_POWER_FORMAT; - Settings.flag3.time_append_timezone = MQTT_APPEND_TIMEZONE; - Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL; - Settings.flag3.no_hold_retain = MQTT_NO_HOLD_RETAIN; - Settings.flag3.use_underscore = MQTT_INDEX_SEPARATOR; - Settings.flag3.grouptopic_mode = MQTT_GROUPTOPIC_FORMAT; - SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST); - Settings.mqtt_port = MQTT_PORT; - SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID); - SettingsUpdateText(SET_MQTT_USER, MQTT_USER); - SettingsUpdateText(SET_MQTT_PWD, MQTT_PASS); - SettingsUpdateText(SET_MQTT_TOPIC, MQTT_TOPIC); - SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); - SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); - SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); - SettingsUpdateText(SET_MQTT_FULLTOPIC, MQTT_FULLTOPIC); - Settings.mqtt_retry = MQTT_RETRY_SECS; - SettingsUpdateText(SET_MQTTPREFIX1, SUB_PREFIX); - SettingsUpdateText(SET_MQTTPREFIX2, PUB_PREFIX); - SettingsUpdateText(SET_MQTTPREFIX3, PUB_PREFIX2); - SettingsUpdateText(SET_STATE_TXT1, MQTT_STATUS_OFF); - SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON); - SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE); - SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD); - char fingerprint[60]; - strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint)); - char *p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16); - } - strlcpy(fingerprint, MQTT_FINGERPRINT2, sizeof(fingerprint)); - p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[1][i] = strtol(p, &p, 16); - } - Settings.tele_period = TELE_PERIOD; - Settings.mqttlog_level = MQTT_LOG_LEVEL; - - - Settings.flag.no_power_on_check = ENERGY_VOLTAGE_ALWAYS; - Settings.flag2.current_resolution = 3; - - - Settings.flag2.energy_resolution = ENERGY_RESOLUTION; - Settings.flag3.dds2382_model = ENERGY_DDS2382_MODE; - Settings.flag3.hardware_energy_total = ENERGY_HARDWARE_TOTALS; - Settings.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; - - Settings.energy_power_calibration = HLW_PREF_PULSE; - Settings.energy_voltage_calibration = HLW_UREF_PULSE; - Settings.energy_current_calibration = HLW_IREF_PULSE; -# 944 "C:/shared/sonoff/Git/Tasmota/tasmota/settings.ino" - Settings.energy_max_power_limit_hold = MAX_POWER_HOLD; - Settings.energy_max_power_limit_window = MAX_POWER_WINDOW; - - Settings.energy_max_power_safe_limit_hold = SAFE_POWER_HOLD; - Settings.energy_max_power_safe_limit_window = SAFE_POWER_WINDOW; - - - - RtcSettings.energy_kWhtotal = 0; - - memset((char*)&RtcSettings.energy_usage, 0x00, sizeof(RtcSettings.energy_usage)); - Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; - - - Settings.flag.ir_receive_decimal = IR_DATA_RADIX; - Settings.flag3.receive_raw = IR_ADD_RAW_DATA; - Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; - - - Settings.flag.rf_receive_decimal = RF_DATA_RADIX; - - memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); - - - Settings.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; -# 979 "C:/shared/sonoff/Git/Tasmota/tasmota/settings.ino" - Settings.flag.temperature_conversion = TEMP_CONVERSION; - Settings.flag.pressure_conversion = PRESSURE_CONVERSION; - Settings.flag2.pressure_resolution = PRESSURE_RESOLUTION; - Settings.flag2.humidity_resolution = HUMIDITY_RESOLUTION; - Settings.flag2.temperature_resolution = TEMP_RESOLUTION; - Settings.flag3.ds18x20_internal_pullup = DS18X20_PULL_UP; - Settings.flag3.counter_reset_on_tele = COUNTER_RESET; - - - - - - - Settings.flag2.calc_resolution = CALC_RESOLUTION; - - - Settings.flag3.timers_enable = TIMERS_ENABLED; - - - Settings.flag.hass_light = HASS_AS_LIGHT; - Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE; - Settings.flag3.hass_tele_on_power = TELE_ON_POWER; - - - Settings.flag.knx_enabled = KNX_ENABLED; - Settings.flag.knx_enable_enhancement = KNX_ENHANCED; - - - Settings.flag.pwm_control = LIGHT_MODE; - Settings.flag.ws_clock_reverse = LIGHT_CLOCK_DIRECTION; - Settings.flag.light_signal = LIGHT_PAIRS_CO2; - Settings.flag.not_power_linked = LIGHT_POWER_CONTROL; - Settings.flag.decimal_text = LIGHT_COLOR_RADIX; - Settings.flag3.pwm_multi_channels = LIGHT_CHANNEL_MODE; - Settings.flag3.slider_dimmer_stay_on = LIGHT_SLIDER_POWER; - Settings.flag4.alexa_ct_range = LIGHT_ALEXA_CT_RANGE; - - Settings.pwm_frequency = PWM_FREQ; - Settings.pwm_range = PWM_RANGE; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - Settings.light_color[i] = DEFAULT_LIGHT_COMPONENT; - - } - Settings.light_correction = 1; - Settings.light_dimmer = DEFAULT_LIGHT_DIMMER; - - Settings.light_speed = 1; - - Settings.light_width = 1; - - Settings.light_pixels = WS2812_LEDS; - - Settings.ws_width[WS_SECOND] = 1; - Settings.ws_color[WS_SECOND][WS_RED] = 255; - - Settings.ws_color[WS_SECOND][WS_BLUE] = 255; - Settings.ws_width[WS_MINUTE] = 3; - - Settings.ws_color[WS_MINUTE][WS_GREEN] = 255; - - Settings.ws_width[WS_HOUR] = 5; - Settings.ws_color[WS_HOUR][WS_RED] = 255; - - - - Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; - Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; - - - - Settings.display_mode = 1; - Settings.display_refresh = 2; - Settings.display_rows = 2; - Settings.display_cols[0] = 16; - Settings.display_cols[1] = 8; - Settings.display_dimmer = 1; - Settings.display_size = 1; - Settings.display_font = 1; - - Settings.display_address[0] = MTX_ADDRESS1; - Settings.display_address[1] = MTX_ADDRESS2; - Settings.display_address[2] = MTX_ADDRESS3; - Settings.display_address[3] = MTX_ADDRESS4; - Settings.display_address[4] = MTX_ADDRESS5; - Settings.display_address[5] = MTX_ADDRESS6; - Settings.display_address[6] = MTX_ADDRESS7; - Settings.display_address[7] = MTX_ADDRESS8; - - - if (((APP_TIMEZONE > -14) && (APP_TIMEZONE < 15)) || (99 == APP_TIMEZONE)) { - Settings.timezone = APP_TIMEZONE; - Settings.timezone_minutes = 0; - } else { - Settings.timezone = APP_TIMEZONE / 60; - Settings.timezone_minutes = abs(APP_TIMEZONE % 60); - } - SettingsUpdateText(SET_NTPSERVER1, NTP_SERVER1); - SettingsUpdateText(SET_NTPSERVER2, NTP_SERVER2); - SettingsUpdateText(SET_NTPSERVER3, NTP_SERVER3); - for (uint32_t i = 0; i < MAX_NTP_SERVERS; i++) { - SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i))); - } - Settings.latitude = (int)((double)LATITUDE * 1000000); - Settings.longitude = (int)((double)LONGITUDE * 1000000); - SettingsResetStd(); - SettingsResetDst(); - - Settings.button_debounce = KEY_DEBOUNCE_TIME; - Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; - - for (uint32_t j = 0; j < 5; j++) { - Settings.rgbwwTable[j] = 255; - } - - Settings.novasds_startingoffset = STARTING_OFFSET; - - SettingsDefaultWebColor(); - - memset(&Settings.monitors, 0xFF, 20); - SettingsEnableAllI2cDrivers(); - - - Settings.flag3.tuya_apply_o20 = TUYA_SETOPTION_20; - Settings.flag3.tuya_serial_mqtt_publish = MQTT_TUYA_RECEIVED; - - Settings.flag3.buzzer_enable = BUZZER_ENABLE; - Settings.flag3.shutter_mode = SHUTTER_SUPPORT; - Settings.flag3.pcf8574_ports_inverted = PCF8574_INVERT_PORTS; - Settings.flag4.zigbee_use_names = ZIGBEE_FRIENDLY_NAMES; -} - - - -void SettingsResetStd(void) -{ - Settings.tflag[0].hemis = TIME_STD_HEMISPHERE; - Settings.tflag[0].week = TIME_STD_WEEK; - Settings.tflag[0].dow = TIME_STD_DAY; - Settings.tflag[0].month = TIME_STD_MONTH; - Settings.tflag[0].hour = TIME_STD_HOUR; - Settings.toffset[0] = TIME_STD_OFFSET; -} - -void SettingsResetDst(void) -{ - Settings.tflag[1].hemis = TIME_DST_HEMISPHERE; - Settings.tflag[1].week = TIME_DST_WEEK; - Settings.tflag[1].dow = TIME_DST_DAY; - Settings.tflag[1].month = TIME_DST_MONTH; - Settings.tflag[1].hour = TIME_DST_HOUR; - Settings.toffset[1] = TIME_DST_OFFSET; -} - -void SettingsDefaultWebColor(void) -{ - char scolor[10]; - for (uint32_t i = 0; i < COL_LAST; i++) { - WebHexCode(i, GetTextIndexed(scolor, sizeof(scolor), i, kWebColors)); - } -} - -void SettingsEnableAllI2cDrivers(void) -{ - Settings.i2c_drivers[0] = 0xFFFFFFFF; - Settings.i2c_drivers[1] = 0xFFFFFFFF; - Settings.i2c_drivers[2] = 0xFFFFFFFF; -} - - - -void SettingsDelta(void) -{ - if (Settings.version != VERSION) { - if (Settings.version < 0x06000000) { - Settings.cfg_size = sizeof(SYSCFG); - Settings.cfg_crc = GetSettingsCrc(); - } - if (Settings.version < 0x06000002) { - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if (i < 4) { - Settings.switchmode[i] = Settings.interlock[i]; - } else { - Settings.switchmode[i] = SWITCH_MODE; - } - } - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (Settings.my_gp.io[i] >= GPIO_SWT5) { - Settings.my_gp.io[i] += 4; - } - } - } - if (Settings.version < 0x06000003) { - Settings.flag.mqtt_serial_raw = 0; - Settings.flag.pressure_conversion = 0; - Settings.flag3.data = 0; - } - if (Settings.version < 0x06010103) { - Settings.flag3.timers_enable = 1; - } - if (Settings.version < 0x0601010C) { - Settings.button_debounce = KEY_DEBOUNCE_TIME; - Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; - } - if (Settings.version < 0x0602010A) { - for (uint32_t j = 0; j < 5; j++) { - Settings.rgbwwTable[j] = 255; - } - } - if (Settings.version < 0x06030002) { - Settings.timezone_minutes = 0; - } - if (Settings.version < 0x06030004) { - memset(&Settings.monitors, 0xFF, 20); - } - if (Settings.version < 0x0603000E) { - Settings.flag2.calc_resolution = CALC_RESOLUTION; - } - if (Settings.version < 0x0603000F) { - if (Settings.sleep < 50) { - Settings.sleep = 50; - } - } - if (Settings.version < 0x06040105) { - Settings.flag3.mdns_enabled = MDNS_ENABLED; - Settings.param[P_MDNS_DELAYED_START] = 0; - } - if (Settings.version < 0x0604010B) { - Settings.interlock[0] = 0xFF; - for (uint32_t i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } - } - if (Settings.version < 0x0604010D) { - Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; - } - if (Settings.version < 0x06040110) { - ModuleDefault(WEMOS); - } - if (Settings.version < 0x06040113) { - Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; - } - if (Settings.version < 0x06050003) { - Settings.novasds_startingoffset = STARTING_OFFSET; - } - if (Settings.version < 0x06050006) { - SettingsDefaultWebColor(); - } - if (Settings.version < 0x06050007) { - Settings.ledmask = APP_LEDMASK; - } - if (Settings.version < 0x0605000A) { - Settings.my_adc0 = ADC0_NONE; - } - if (Settings.version < 0x0605000D) { - Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; - } - if (Settings.version < 0x06060001) { - Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; - } - if (Settings.version < 0x06060007) { - memset((char*)&Settings +0xE00, 0x00, sizeof(SYSCFG) -0xE00); - } - if (Settings.version < 0x06060008) { - - if (Settings.flag3.tuya_serial_mqtt_publish) { - Settings.param[P_ex_DIMMER_MAX] = 100; - } else { - Settings.param[P_ex_DIMMER_MAX] = 255; - } - } - if (Settings.version < 0x06060009) { - Settings.baudrate = APP_BAUDRATE / 300; - Settings.sbaudrate = SOFT_BAUDRATE / 300; - } - if (Settings.version < 0x0606000A) { - uint8_t tuyaindex = 0; - if (Settings.param[P_BACKLOG_DELAY] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 21; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_BACKLOG_DELAY]; - tuyaindex++; - } else if (Settings.flag3.fast_power_cycle_disable == 1) { - Settings.tuya_fnid_map[tuyaindex].fnid = 11; - Settings.tuya_fnid_map[tuyaindex].dpid = 1; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_RELAYS] > 0) { - for (uint8_t i = 0 ; i < Settings.param[P_ex_TUYA_RELAYS]; i++) { - Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; - Settings.tuya_fnid_map[tuyaindex].dpid = i + 2; - tuyaindex++; - } - } - if (Settings.param[P_ex_TUYA_POWER_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 31; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_POWER_ID]; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_VOLTAGE_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 33; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_VOLTAGE_ID]; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_CURRENT_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 32; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_CURRENT_ID]; - } - } - if (Settings.version < 0x0606000C) { - memset((char*)&Settings +0x1D6, 0x00, 16); - } - if (Settings.version < 0x0606000F) { - Settings.ex_shutter_accuracy = 0; - Settings.ex_mqttlog_level = MQTT_LOG_LEVEL; - } - if (Settings.version < 0x06060011) { - Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; - } - if (Settings.version < 0x06060012) { - Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; - Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; - if (TUYA_DIMMER == Settings.module) { - if (Settings.flag3.ex_tuya_dimmer_min_limit) { - Settings.dimmer_hw_min = 25; - } else { - Settings.dimmer_hw_min = 1; - } - Settings.dimmer_hw_max = Settings.param[P_ex_DIMMER_MAX]; - } - else if (PS_16_DZ == Settings.module) { - Settings.dimmer_hw_min = 10; - Settings.dimmer_hw_max = Settings.param[P_ex_DIMMER_MAX]; - } - } - if (Settings.version < 0x06060014) { -# 1323 "C:/shared/sonoff/Git/Tasmota/tasmota/settings.ino" - Settings.flag3.fast_power_cycle_disable = 0; - Settings.energy_power_delta = Settings.ex_energy_power_delta; - Settings.ex_energy_power_delta = 0; - } - if (Settings.version < 0x06060015) { - if ((EX_WIFI_SMARTCONFIG == Settings.ex_sta_config) || (EX_WIFI_WPSCONFIG == Settings.ex_sta_config)) { - Settings.ex_sta_config = WIFI_MANAGER; - } - } - - if (Settings.version < 0x07000002) { - Settings.web_color2[0][0] = Settings.web_color[0][0]; - Settings.web_color2[0][1] = Settings.web_color[0][1]; - Settings.web_color2[0][2] = Settings.web_color[0][2]; - } - if (Settings.version < 0x07000003) { - SettingsEnableAllI2cDrivers(); - } - if (Settings.version < 0x07000004) { - Settings.ex_wifi_output_power = 170; - } - if (Settings.version < 0x07010202) { - Settings.ex_serial_config = TS_SERIAL_8N1; - } - if (Settings.version < 0x07010204) { - if (Settings.flag3.ex_cors_enabled == 1) { - strlcpy(Settings.ex_cors_domain, CORS_ENABLED_ALL, sizeof(Settings.ex_cors_domain)); - } else { - Settings.ex_cors_domain[0] = 0; - } - } - if (Settings.version < 0x07010205) { - Settings.seriallog_level = Settings.ex_seriallog_level; - Settings.sta_config = Settings.ex_sta_config; - Settings.sta_active = Settings.ex_sta_active; - memcpy((char*)&Settings.rule_stop, (char*)&Settings.ex_rule_stop, 47); - } - if (Settings.version < 0x07010206) { - Settings.flag4 = Settings.ex_flag4; - Settings.mqtt_port = Settings.ex_mqtt_port; - memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); - } - - if (Settings.version < 0x08000000) { - char temp[strlen(Settings.text_pool) +1]; strncpy(temp, Settings.text_pool, sizeof(temp)); - char temp21[strlen(Settings.ex_mqtt_prefix[0]) +1]; strncpy(temp21, Settings.ex_mqtt_prefix[0], sizeof(temp21)); - char temp22[strlen(Settings.ex_mqtt_prefix[1]) +1]; strncpy(temp22, Settings.ex_mqtt_prefix[1], sizeof(temp22)); - char temp23[strlen(Settings.ex_mqtt_prefix[2]) +1]; strncpy(temp23, Settings.ex_mqtt_prefix[2], sizeof(temp23)); - char temp31[strlen(Settings.ex_sta_ssid[0]) +1]; strncpy(temp31, Settings.ex_sta_ssid[0], sizeof(temp31)); - char temp32[strlen(Settings.ex_sta_ssid[1]) +1]; strncpy(temp32, Settings.ex_sta_ssid[1], sizeof(temp32)); - char temp41[strlen(Settings.ex_sta_pwd[0]) +1]; strncpy(temp41, Settings.ex_sta_pwd[0], sizeof(temp41)); - char temp42[strlen(Settings.ex_sta_pwd[1]) +1]; strncpy(temp42, Settings.ex_sta_pwd[1], sizeof(temp42)); - char temp5[strlen(Settings.ex_hostname) +1]; strncpy(temp5, Settings.ex_hostname, sizeof(temp5)); - char temp6[strlen(Settings.ex_syslog_host) +1]; strncpy(temp6, Settings.ex_syslog_host, sizeof(temp6)); - char temp7[strlen(Settings.ex_mqtt_host) +1]; strncpy(temp7, Settings.ex_mqtt_host, sizeof(temp7)); - char temp8[strlen(Settings.ex_mqtt_client) +1]; strncpy(temp8, Settings.ex_mqtt_client, sizeof(temp8)); - char temp9[strlen(Settings.ex_mqtt_user) +1]; strncpy(temp9, Settings.ex_mqtt_user, sizeof(temp9)); - char temp10[strlen(Settings.ex_mqtt_pwd) +1]; strncpy(temp10, Settings.ex_mqtt_pwd, sizeof(temp10)); - char temp11[strlen(Settings.ex_mqtt_topic) +1]; strncpy(temp11, Settings.ex_mqtt_topic, sizeof(temp11)); - char temp12[strlen(Settings.ex_button_topic) +1]; strncpy(temp12, Settings.ex_button_topic, sizeof(temp12)); - char temp13[strlen(Settings.ex_mqtt_grptopic) +1]; strncpy(temp13, Settings.ex_mqtt_grptopic, sizeof(temp13)); - - memset(Settings.text_pool, 0x00, settings_text_size); - SettingsUpdateText(SET_OTAURL, temp); - SettingsUpdateText(SET_MQTTPREFIX1, temp21); - SettingsUpdateText(SET_MQTTPREFIX2, temp22); - SettingsUpdateText(SET_MQTTPREFIX3, temp23); - SettingsUpdateText(SET_STASSID1, temp31); - SettingsUpdateText(SET_STASSID2, temp32); - SettingsUpdateText(SET_STAPWD1, temp41); - SettingsUpdateText(SET_STAPWD2, temp42); - SettingsUpdateText(SET_HOSTNAME, temp5); - SettingsUpdateText(SET_SYSLOG_HOST, temp6); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (!strlen(Settings.ex_mqtt_user)) { - SettingsUpdateText(SET_MQTT_HOST, temp7); - SettingsUpdateText(SET_MQTT_USER, temp9); - } else { - char aws_mqtt_host[66]; - snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), temp9, temp7); - SettingsUpdateText(SET_MQTT_HOST, aws_mqtt_host); - SettingsUpdateText(SET_MQTT_USER, ""); - } -#else - SettingsUpdateText(SET_MQTT_HOST, temp7); - SettingsUpdateText(SET_MQTT_USER, temp9); -#endif - SettingsUpdateText(SET_MQTT_CLIENT, temp8); - SettingsUpdateText(SET_MQTT_PWD, temp10); - SettingsUpdateText(SET_MQTT_TOPIC, temp11); - SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); - SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); - - SettingsUpdateText(SET_WEBPWD, Settings.ex_web_password); - SettingsUpdateText(SET_CORS, Settings.ex_cors_domain); - SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.ex_mqtt_fulltopic); - SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.ex_switch_topic); - SettingsUpdateText(SET_STATE_TXT1, Settings.ex_state_text[0]); - SettingsUpdateText(SET_STATE_TXT2, Settings.ex_state_text[1]); - SettingsUpdateText(SET_STATE_TXT3, Settings.ex_state_text[2]); - SettingsUpdateText(SET_STATE_TXT4, Settings.ex_state_text[3]); - SettingsUpdateText(SET_NTPSERVER1, Settings.ex_ntp_server[0]); - SettingsUpdateText(SET_NTPSERVER2, Settings.ex_ntp_server[1]); - SettingsUpdateText(SET_NTPSERVER3, Settings.ex_ntp_server[2]); - SettingsUpdateText(SET_MEM1, Settings.script_pram[0]); - SettingsUpdateText(SET_MEM2, Settings.script_pram[1]); - SettingsUpdateText(SET_MEM3, Settings.script_pram[2]); - SettingsUpdateText(SET_MEM4, Settings.script_pram[3]); - SettingsUpdateText(SET_MEM5, Settings.script_pram[4]); - SettingsUpdateText(SET_FRIENDLYNAME1, Settings.ex_friendlyname[0]); - SettingsUpdateText(SET_FRIENDLYNAME2, Settings.ex_friendlyname[1]); - SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]); - SettingsUpdateText(SET_FRIENDLYNAME4, Settings.ex_friendlyname[3]); - } - - Settings.version = VERSION; - SettingsSave(1); - } -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support.ino" -IPAddress syslog_host_addr; -uint32_t syslog_host_hash = 0; - -extern "C" { -extern struct rst_info resetInfo; -} - - - - - -#include - -Ticker tickerOSWatch; - -const uint32_t OSWATCH_RESET_TIME = 120; - -static unsigned long oswatch_last_loop_time; -uint8_t oswatch_blocked_loop = 0; - -#ifndef USE_WS2812_DMA - -#endif - -#ifdef USE_KNX -bool knx_started = false; -#endif - -void OsWatchTicker(void) -{ - uint32_t t = millis(); - uint32_t last_run = abs(t - oswatch_last_loop_time); - -#ifdef DEBUG_THEO - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), last_run); -#endif - if (last_run >= (OSWATCH_RESET_TIME * 1000)) { - - RtcSettings.oswatch_blocked_loop = 1; - RtcSettingsSave(); - - - - - - volatile uint32_t dummy; - dummy = *((uint32_t*) 0x00000000); - } -} - -void OsWatchInit(void) -{ - oswatch_blocked_loop = RtcSettings.oswatch_blocked_loop; - RtcSettings.oswatch_blocked_loop = 0; - oswatch_last_loop_time = millis(); - tickerOSWatch.attach_ms(((OSWATCH_RESET_TIME / 3) * 1000), OsWatchTicker); -} - -void OsWatchLoop(void) -{ - oswatch_last_loop_time = millis(); - -} - -bool OsWatchBlockedLoop(void) -{ - return oswatch_blocked_loop; -} - -uint32_t ResetReason(void) -{ -# 101 "C:/shared/sonoff/Git/Tasmota/tasmota/support.ino" - return resetInfo.reason; -} - -String GetResetReason(void) -{ - if (oswatch_blocked_loop) { - char buff[32]; - strncpy_P(buff, PSTR(D_JSON_BLOCKED_LOOP), sizeof(buff)); - return String(buff); - } else { - return ESP.getResetReason(); - } -} - - - - - - -size_t strchrspn(const char *str1, int character) -{ - size_t ret = 0; - char *start = (char*)str1; - char *end = strchr(str1, character); - if (end) ret = end - start; - return ret; -} - - -char* subStr(char* dest, char* str, const char *delim, int index) -{ - char *act; - char *sub = nullptr; - char *ptr; - int i; - - - strncpy(dest, str, strlen(str)+1); - for (i = 1, act = dest; i <= index; i++, act = nullptr) { - sub = strtok_r(act, delim, &ptr); - if (sub == nullptr) break; - } - sub = Trim(sub); - return sub; -} - -float CharToFloat(const char *str) -{ - - char strbuf[24]; - - strlcpy(strbuf, str, sizeof(strbuf)); - char *pt = strbuf; - while ((*pt != '\0') && isblank(*pt)) { pt++; } - - signed char sign = 1; - if (*pt == '-') { sign = -1; } - if (*pt == '-' || *pt=='+') { pt++; } - - float left = 0; - if (*pt != '.') { - left = atoi(pt); - while (isdigit(*pt)) { pt++; } - } - - float right = 0; - if (*pt == '.') { - pt++; - right = atoi(pt); - while (isdigit(*pt)) { - pt++; - right /= 10.0f; - } - } - - float result = left + right; - if (sign < 0) { - return -result; - } - return result; -} - -int TextToInt(char *str) -{ - char *p; - uint8_t radix = 10; - if ('#' == str[0]) { - radix = 16; - str++; - } - return strtol(str, &p, radix); -} - -char* ulltoa(unsigned long long value, char *str, int radix) -{ - char digits[64]; - char *dst = str; - int i = 0; - - - - do { - int n = value % radix; - digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; - value /= radix; - } while (value != 0); - - while (i > 0) { *dst++ = digits[--i]; } - - *dst = 0; - return str; -} - - - -char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween) -{ - - - - static const char * hex = "0123456789ABCDEF"; - int between = (inbetween) ? 3 : 2; - const unsigned char * pin = in; - char * pout = out; - for (; pin < in+insz; pout += between, pin++) { - pout[0] = hex[(pgm_read_byte(pin)>>4) & 0xF]; - pout[1] = hex[ pgm_read_byte(pin) & 0xF]; - if (inbetween) { pout[2] = inbetween; } - if (pout + 3 - out > outsz) { break; } - } - pout[(inbetween && insz) ? -1 : 0] = 0; - return out; -} - -char* Uint64toHex(uint64_t value, char *str, uint16_t bits) -{ - ulltoa(value, str, 16); - - int fill = 8; - if ((bits > 3) && (bits < 65)) { - fill = bits / 4; - if (bits % 4) { fill++; } - } - int len = strlen(str); - fill -= len; - if (fill > 0) { - memmove(str + fill, str, len +1); - memset(str, '0', fill); - } - return str; -} - -char* dtostrfd(double number, unsigned char prec, char *s) -{ - if ((isnan(number)) || (isinf(number))) { - strcpy(s, "null"); - return s; - } else { - return dtostrf(number, 1, prec, s); - } -} - -char* Unescape(char* buffer, uint32_t* size) -{ - uint8_t* read = (uint8_t*)buffer; - uint8_t* write = (uint8_t*)buffer; - int32_t start_size = *size; - int32_t end_size = *size; - uint8_t che = 0; - - - - while (start_size > 0) { - uint8_t ch = *read++; - start_size--; - if (ch != '\\') { - *write++ = ch; - } else { - if (start_size > 0) { - uint8_t chi = *read++; - start_size--; - end_size--; - switch (chi) { - case '\\': che = '\\'; break; - case 'a': che = '\a'; break; - case 'b': che = '\b'; break; - case 'e': che = '\e'; break; - case 'f': che = '\f'; break; - case 'n': che = '\n'; break; - case 'r': che = '\r'; break; - case 's': che = ' '; break; - case 't': che = '\t'; break; - case 'v': che = '\v'; break; - case 'x': { - uint8_t* start = read; - che = (uint8_t)strtol((const char*)read, (char**)&read, 16); - start_size -= (uint16_t)(read - start); - end_size -= (uint16_t)(read - start); - break; - } - case '"': che = '\"'; break; - - default : { - che = chi; - *write++ = ch; - end_size++; - } - } - *write++ = che; - } - } - } - *size = end_size; - *write++ = 0; - - - return buffer; -} - -char* RemoveSpace(char* p) -{ - char* write = p; - char* read = p; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - if (!isspace(ch)) { - *write++ = ch; - } - } - - return p; -} - -char* ReplaceCommaWithDot(char* p) -{ - char* write = (char*)p; - char* read = (char*)p; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - if (ch == ',') { - ch = '.'; - } - *write++ = ch; - } - return p; -} - -char* LowerCase(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = tolower(ch); - } - return dest; -} - -char* UpperCase(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = toupper(ch); - } - return dest; -} - -char* UpperCase_P(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = pgm_read_byte(read++); - *write++ = toupper(ch); - } - return dest; -} - -char* Trim(char* p) -{ - while ((*p != '\0') && isblank(*p)) { p++; } - char* q = p + strlen(p) -1; - while ((q >= p) && isblank(*q)) { q--; } - q++; - *q = '\0'; - return p; -} - -char* RemoveAllSpaces(char* p) -{ - - char *cursor = p; - uint32_t offset = 0; - while (1) { - *cursor = *(cursor + offset); - if ((' ' == *cursor) || ('\t' == *cursor) || ('\n' == *cursor)) { - offset++; - } else { - if (0 == *cursor) { break; } - cursor++; - } - } - return p; -} - -char* NoAlNumToUnderscore(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = (isalnum(ch) || ('\0' == ch)) ? ch : '_'; - } - return dest; -} - -char IndexSeparator(void) -{ - - - - - - - if (Settings.flag3.use_underscore) { - return '_'; - } else { - return '-'; - } -} - -void SetShortcutDefault(void) -{ - if ('\0' != XdrvMailbox.data[0]) { - XdrvMailbox.data[0] = '0' + SC_DEFAULT; - XdrvMailbox.data[1] = '\0'; - } -} - -uint8_t Shortcut(void) -{ - uint8_t result = 10; - - if ('\0' == XdrvMailbox.data[1]) { - if (('"' == XdrvMailbox.data[0]) || ('0' == XdrvMailbox.data[0])) { - result = SC_CLEAR; - } else { - result = atoi(XdrvMailbox.data); - if (0 == result) { - result = 10; - } - } - } - return result; -} - -bool ValidIpAddress(const char* str) -{ - const char* p = str; - - while (*p && ((*p == '.') || ((*p >= '0') && (*p <= '9')))) { p++; } - return (*p == '\0'); -} - -bool ParseIp(uint32_t* addr, const char* str) -{ - uint8_t *part = (uint8_t*)addr; - uint8_t i; - - *addr = 0; - for (i = 0; i < 4; i++) { - part[i] = strtoul(str, nullptr, 10); - str = strchr(str, '.'); - if (str == nullptr || *str == '\0') { - break; - } - str++; - } - return (3 == i); -} - -uint32_t ParseParameters(uint32_t count, uint32_t *params) -{ - char *p; - uint32_t i = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p), i++) { - params[i] = strtoul(str, nullptr, 0); - } - return i; -} - - -bool NewerVersion(char* version_str) -{ - uint32_t version = 0; - uint32_t i = 0; - char *str_ptr; - - char version_dup[strlen(version_str) +1]; - strncpy(version_dup, version_str, sizeof(version_dup)); - - for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(nullptr, ".", &str_ptr), i++) { - int field = atoi(str); - - if ((field < 0) || (field > 255)) { - return false; - } - - version = (version << 8) + field; - - if ((2 == i) && isalpha(str[strlen(str)-1])) { - field = str[strlen(str)-1] & 0x1f; - version = (version << 8) + field; - i++; - } - } - - - if ((i < 2) || (i > sizeof(VERSION))) { - return false; - } - - - while (i < sizeof(VERSION)) { - version <<= 8; - i++; - } - - return (version > VERSION); -} - -char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option) -{ - strncpy_P(dest, S_RSLT_POWER, size); - if ((devices_present + option) > 1) { - char sidx[8]; - snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); - strncat(dest, sidx, size - strlen(dest) -1); - } - return dest; -} - -char* GetPowerDevice(char* dest, uint32_t idx, size_t size) -{ - return GetPowerDevice(dest, idx, size, 0); -} - -void GetEspHardwareType(void) -{ - - uint32_t efuse1 = *(uint32_t*)(0x3FF00050); - uint32_t efuse2 = *(uint32_t*)(0x3FF00054); - - - - is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); - if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { - is_8285 = false; - } -} - -String GetDeviceHardware(void) -{ - char buff[10]; - if (is_8285) { - strcpy_P(buff, PSTR("ESP8285")); - } else { - strcpy_P(buff, PSTR("ESP8266EX")); - } - return String(buff); -} - -float ConvertTemp(float c) -{ - float result = c; - - global_update = uptime; - global_temperature = c; - - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = c * 1.8 + 32; - } - result = result + (0.1 * Settings.temp_comp); - return result; -} - -float ConvertTempToCelsius(float c) -{ - float result = c; - - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = (c - 32) / 1.8; - } - result = result + (0.1 * Settings.temp_comp); - return result; -} - -char TempUnit(void) -{ - return (Settings.flag.temperature_conversion) ? 'F' : 'C'; -} - -float ConvertHumidity(float h) -{ - global_update = uptime; - global_humidity = h; - - return h; -} - -float ConvertPressure(float p) -{ - float result = p; - - global_update = uptime; - global_pressure = p; - - if (!isnan(p) && Settings.flag.pressure_conversion) { - result = p * 0.75006375541921; - } - return result; -} - -String PressureUnit(void) -{ - return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); -} - -void ResetGlobalValues(void) -{ - if ((uptime - global_update) > GLOBAL_VALUES_VALID) { - global_update = 0; - global_temperature = 9999; - global_humidity = 0; - global_pressure = 0; - } -} - -uint32_t SqrtInt(uint32_t num) -{ - if (num <= 1) { - return num; - } - - uint32_t x = num / 2; - uint32_t y; - do { - y = (x + num / x) / 2; - if (y >= x) { - return x; - } - x = y; - } while (true); -} - -uint32_t RoundSqrtInt(uint32_t num) -{ - uint32_t s = SqrtInt(4 * num); - if (s & 1) { - s++; - } - return s / 2; -} - -char* GetTextIndexed(char* destination, size_t destination_size, uint32_t index, const char* haystack) -{ - - - char* write = destination; - const char* read = haystack; - - index++; - while (index--) { - size_t size = destination_size -1; - write = destination; - char ch = '.'; - while ((ch != '\0') && (ch != '|')) { - ch = pgm_read_byte(read++); - if (size && (ch != '|')) { - *write++ = ch; - size--; - } - } - if (0 == ch) { - if (index) { - write = destination; - } - break; - } - } - *write = '\0'; - return destination; -} - -int GetCommandCode(char* destination, size_t destination_size, const char* needle, const char* haystack) -{ - - - int result = -1; - const char* read = haystack; - char* write = destination; - - while (true) { - result++; - size_t size = destination_size -1; - write = destination; - char ch = '.'; - while ((ch != '\0') && (ch != '|')) { - ch = pgm_read_byte(read++); - if (size && (ch != '|')) { - *write++ = ch; - size--; - } - } - *write = '\0'; - if (!strcasecmp(needle, destination)) { - break; - } - if (0 == ch) { - result = -1; - break; - } - } - return result; -} - -bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void)) -{ - GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); - int prefix_length = strlen(XdrvMailbox.command); - if (prefix_length) { - char prefix[prefix_length +1]; - snprintf_P(prefix, sizeof(prefix), XdrvMailbox.topic); - if (strcasecmp(prefix, XdrvMailbox.command)) { - return false; - } - } - int command_code = GetCommandCode(XdrvMailbox.command + prefix_length, CMDSZ, XdrvMailbox.topic + prefix_length, haystack); - if (command_code > 0) { - XdrvMailbox.command_code = command_code -1; - MyCommand[XdrvMailbox.command_code](); - return true; - } - return false; -} - -const char kOptions[] PROGMEM = "OFF|" D_OFF "|FALSE|" D_FALSE "|STOP|" D_STOP "|" D_CELSIUS "|" - "ON|" D_ON "|TRUE|" D_TRUE "|START|" D_START "|" D_FAHRENHEIT "|" D_USER "|" - "TOGGLE|" D_TOGGLE "|" D_ADMIN "|" - "BLINK|" D_BLINK "|" - "BLINKOFF|" D_BLINKOFF "|" - "ALL" ; - -const uint8_t sNumbers[] PROGMEM = { 0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1, - 2,2,2, - 3,3, - 4,4, - 255 }; - -int GetStateNumber(char *state_text) -{ - char command[CMDSZ]; - int state_number = GetCommandCode(command, sizeof(command), state_text, kOptions); - if (state_number >= 0) { - state_number = pgm_read_byte(sNumbers + state_number); - } - return state_number; -} - -String GetSerialConfig(void) -{ - - - - - - const char kParity[] = "NEOI"; - - char config[4]; - config[0] = '5' + (Settings.serial_config & 0x3); - config[1] = kParity[(Settings.serial_config >> 3) & 0x3]; - config[2] = '1' + ((Settings.serial_config >> 2) & 0x1); - config[3] = '\0'; - return String(config); -} - -void SetSerialBegin() -{ - uint32_t baudrate = Settings.baudrate * 300; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_SERIAL "Set to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); - Serial.flush(); - Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); -} - -void SetSerialConfig(uint32_t serial_config) -{ - if (serial_config > TS_SERIAL_8O2) { - serial_config = TS_SERIAL_8N1; - } - if (serial_config != Settings.serial_config) { - Settings.serial_config = serial_config; - SetSerialBegin(); - } -} - -void SetSerialBaudrate(uint32_t baudrate) -{ - Settings.baudrate = baudrate / 300; - if (Serial.baudRate() != baudrate) { - SetSerialBegin(); - } -} - -void SetSerial(uint32_t baudrate, uint32_t serial_config) -{ - Settings.flag.mqtt_serial = 0; - Settings.serial_config = serial_config; - Settings.baudrate = baudrate / 300; - SetSeriallog(LOG_LEVEL_NONE); - SetSerialBegin(); -} - -void ClaimSerial(void) -{ - serial_local = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial")); - SetSeriallog(LOG_LEVEL_NONE); - Settings.baudrate = Serial.baudRate() / 300; -} - -void SerialSendRaw(char *codes) -{ - char *p; - char stemp[3]; - uint8_t code; - - int size = strlen(codes); - - while (size > 1) { - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, &p, 16); - Serial.write(code); - size -= 2; - codes += 2; - } -} - -uint32_t GetHash(const char *buffer, size_t size) -{ - uint32_t hash = 0; - for (uint32_t i = 0; i <= size; i++) { - hash += (uint8_t)*buffer++ * (i +1); - } - return hash; -} - -void ShowSource(uint32_t source) -{ - if ((source > 0) && (source < SRC_MAX)) { - char stemp1[20]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource)); - } -} - -void WebHexCode(uint32_t i, const char* code) -{ - char scolor[10]; - - strlcpy(scolor, code, sizeof(scolor)); - char* p = scolor; - if ('#' == p[0]) { p++; } - - if (3 == strlen(p)) { - p[6] = p[3]; - p[5] = p[2]; - p[4] = p[2]; - p[3] = p[1]; - p[2] = p[1]; - p[1] = p[0]; - } - - uint32_t color = strtol(p, nullptr, 16); - - - - - - - uint32_t j = sizeof(Settings.web_color) / 3; -# 916 "C:/shared/sonoff/Git/Tasmota/tasmota/support.ino" - if (i >= j) { - - i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); - } - Settings.web_color[i][0] = (color >> 16) & 0xFF; - Settings.web_color[i][1] = (color >> 8) & 0xFF; - Settings.web_color[i][2] = color & 0xFF; -} - -uint32_t WebColor(uint32_t i) -{ - uint32_t j = sizeof(Settings.web_color) / 3; - - - - - if (i >= j) { - - i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); - } - uint32_t tcolor = (Settings.web_color[i][0] << 16) | (Settings.web_color[i][1] << 8) | Settings.web_color[i][2]; - - return tcolor; -} - - - - - -const uint16_t TIMESZ = 100; - -char* ResponseGetTime(uint32_t format, char* time_str) -{ - switch (format) { - case 1: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime()); - break; - case 2: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":%u"), UtcTime()); - break; - default: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - } - return time_str; -} - -int Response_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), format, args); - va_end(args); - return len; -} - -int ResponseTime_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - - ResponseGetTime(Settings.flag2.time_format, mqtt_data); - - int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); - va_end(args); - return len + mlen; -} - -int ResponseAppend_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); - va_end(args); - return len + mlen; -} - -int ResponseAppendTimeFormat(uint32_t format) -{ - char time_str[TIMESZ]; - return ResponseAppend_P(ResponseGetTime(format, time_str)); -} - -int ResponseAppendTime(void) -{ - return ResponseAppendTimeFormat(Settings.flag2.time_format); -} - -int ResponseJsonEnd(void) -{ - return ResponseAppend_P(PSTR("}")); -} - -int ResponseJsonEndEnd(void) -{ - return ResponseAppend_P(PSTR("}}")); -} - - - - - -void DigitalWrite(uint32_t gpio_pin, uint32_t state) -{ - if (pin[gpio_pin] < 99) { - digitalWrite(pin[gpio_pin], state &1); - } -} - -uint8_t ModuleNr(void) -{ - - - return (USER_MODULE == Settings.module) ? 0 : Settings.module +1; -} - -bool ValidTemplateModule(uint32_t index) -{ - for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { - if (index == pgm_read_byte(kModuleNiceList + i)) { - return true; - } - } - return false; -} - -bool ValidModule(uint32_t index) -{ - if (index == USER_MODULE) { return true; } - return ValidTemplateModule(index); -} - -String AnyModuleName(uint32_t index) -{ - if (USER_MODULE == index) { - return String(Settings.user_template.name); - } else { - return FPSTR(kModules[index].name); - } -} - -String ModuleName(void) -{ - return AnyModuleName(Settings.module); -} - -void ModuleGpios(myio *gp) -{ - uint8_t *dest = (uint8_t *)gp; - memset(dest, GPIO_NONE, sizeof(myio)); - - uint8_t src[sizeof(mycfgio)]; - if (USER_MODULE == Settings.module) { - memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); - } else { - memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); - } - - - - - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - dest[j] = src[i]; - j++; - } - - - -} - -gpio_flag ModuleFlag(void) -{ - gpio_flag flag; - - if (USER_MODULE == Settings.module) { - flag = Settings.user_template.flag; - } else { - memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); - } - - return flag; -} - -void ModuleDefault(uint32_t module) -{ - if (USER_MODULE == module) { module = WEMOS; } - Settings.user_template_base = module; - memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); -} - -void SetModuleType(void) -{ - my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; -} - -bool FlashPin(uint32_t pin) -{ - return (((pin > 5) && (pin < 9)) || (11 == pin)); -} - -uint8_t ValidPin(uint32_t pin, uint32_t gpio) -{ - if (FlashPin(pin)) { - return GPIO_NONE; - } - - - if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { - if ((pin == 9) || (pin == 10)) { - return GPIO_NONE; - } - } - - return gpio; -} - -bool ValidGPIO(uint32_t pin, uint32_t gpio) -{ - return (GPIO_USER == ValidPin(pin, gpio)); -} - -bool ValidAdc(void) -{ - gpio_flag flag = ModuleFlag(); - uint32_t template_adc0 = flag.data &15; - return (ADC0_USER == template_adc0); -} - -bool GetUsedInModule(uint32_t val, uint8_t *arr) -{ - int offset = 0; - - if (!val) { return false; } - - if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { - offset = (GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); - } - - if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { - offset = (GPIO_SWT1_NP - GPIO_SWT1); - } - if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { - offset = -(GPIO_SWT1_NP - GPIO_SWT1); - } - - if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { - offset = (GPIO_REL1_INV - GPIO_REL1); - } - if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { - offset = -(GPIO_REL1_INV - GPIO_REL1); - } - - if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { - offset = (GPIO_LED1_INV - GPIO_LED1); - } - if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { - offset = -(GPIO_LED1_INV - GPIO_LED1); - } - - if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { - offset = (GPIO_PWM1_INV - GPIO_PWM1); - } - if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { - offset = -(GPIO_PWM1_INV - GPIO_PWM1); - } - - if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { - offset = (GPIO_CNTR1_NP - GPIO_CNTR1); - } - if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { - offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); - } - - for (uint32_t i = 0; i < MAX_GPIO_PIN; i++) { - if (arr[i] == val) { return true; } - if (arr[i] == val + offset) { return true; } - } - return false; -} - -bool JsonTemplate(const char* dataBuf) -{ - - - if (strlen(dataBuf) < 9) { return false; } - - StaticJsonBuffer<350> jb; - JsonObject& obj = jb.parseObject(dataBuf); - if (!obj.success()) { return false; } - - - const char* name = obj[D_JSON_NAME]; - if (name != nullptr) { - strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name)); - } - if (obj[D_JSON_GPIO].success()) { - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0; - } - } - if (obj[D_JSON_FLAG].success()) { - uint8_t flag = obj[D_JSON_FLAG] | 0; - memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag)); - } - if (obj[D_JSON_BASE].success()) { - uint8_t base = obj[D_JSON_BASE]; - if ((0 == base) || !ValidTemplateModule(base -1)) { base = 18; } - Settings.user_template_base = base -1; - } - return true; -} - -void TemplateJson(void) -{ - Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); - } - ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); -} - - - - - -inline int32_t TimeDifference(uint32_t prev, uint32_t next) -{ - return ((int32_t) (next - prev)); -} - -int32_t TimePassedSince(uint32_t timestamp) -{ - - - return TimeDifference(timestamp, millis()); -} - -bool TimeReached(uint32_t timer) -{ - - const long passed = TimePassedSince(timer); - return (passed >= 0); -} - -void SetNextTimeInterval(unsigned long& timer, const unsigned long step) -{ - timer += step; - const long passed = TimePassedSince(timer); - if (passed < 0) { return; } - if (static_cast(passed) > step) { - - timer = millis() + step; - return; - } - - timer = millis() + (step - passed); -} - -int32_t TimePassedSinceUsec(uint32_t timestamp) -{ - return TimeDifference(timestamp, micros()); -} - -bool TimeReachedUsec(uint32_t timer) -{ - - const long passed = TimePassedSinceUsec(timer); - return (passed >= 0); -} - - - - - -#ifdef USE_I2C -const uint8_t I2C_RETRY_COUNTER = 3; - -uint32_t i2c_active[4] = { 0 }; -uint32_t i2c_buffer = 0; - -bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size) -{ - uint8_t retry = I2C_RETRY_COUNTER; - bool status = false; - - i2c_buffer = 0; - while (!status && retry) { - Wire.beginTransmission(addr); - Wire.write(reg); - if (0 == Wire.endTransmission(false)) { - Wire.requestFrom((int)addr, (int)size); - if (Wire.available() == size) { - for (uint32_t i = 0; i < size; i++) { - i2c_buffer = i2c_buffer << 8 | Wire.read(); - } - status = true; - } - } - retry--; - } - return status; -} - -bool I2cValidRead8(uint8_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 1); - *data = (uint8_t)i2c_buffer; - return status; -} - -bool I2cValidRead16(uint16_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 2); - *data = (uint16_t)i2c_buffer; - return status; -} - -bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 2); - *data = (int16_t)i2c_buffer; - return status; -} - -bool I2cValidRead16LE(uint16_t *data, uint8_t addr, uint8_t reg) -{ - uint16_t ldata; - bool status = I2cValidRead16(&ldata, addr, reg); - *data = (ldata >> 8) | (ldata << 8); - return status; -} - -bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg) -{ - uint16_t ldata; - bool status = I2cValidRead16LE(&ldata, addr, reg); - *data = (int16_t)ldata; - return status; -} - -bool I2cValidRead24(int32_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 3); - *data = i2c_buffer; - return status; -} - -uint8_t I2cRead8(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 1); - return (uint8_t)i2c_buffer; -} - -uint16_t I2cRead16(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - return (uint16_t)i2c_buffer; -} - -int16_t I2cReadS16(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - return (int16_t)i2c_buffer; -} - -uint16_t I2cRead16LE(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - uint16_t temp = (uint16_t)i2c_buffer; - return (temp >> 8) | (temp << 8); -} - -int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg) -{ - return (int16_t)I2cRead16LE(addr, reg); -} - -int32_t I2cRead24(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 3); - return i2c_buffer; -} - -bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size) -{ - uint8_t x = I2C_RETRY_COUNTER; - - do { - Wire.beginTransmission((uint8_t)addr); - Wire.write(reg); - uint8_t bytes = size; - while (bytes--) { - Wire.write((val >> (8 * bytes)) & 0xFF); - } - x--; - } while (Wire.endTransmission(true) != 0 && x != 0); - return (x); -} - -bool I2cWrite8(uint8_t addr, uint8_t reg, uint16_t val) -{ - return I2cWrite(addr, reg, val, 1); -} - -bool I2cWrite16(uint8_t addr, uint8_t reg, uint16_t val) -{ - return I2cWrite(addr, reg, val, 2); -} - -int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) -{ - Wire.beginTransmission((uint8_t)addr); - Wire.write((uint8_t)reg); - Wire.endTransmission(); - if (len != Wire.requestFrom((uint8_t)addr, (uint8_t)len)) { - return 1; - } - while (len--) { - *reg_data = (uint8_t)Wire.read(); - reg_data++; - } - return 0; -} - -int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) -{ - Wire.beginTransmission((uint8_t)addr); - Wire.write((uint8_t)reg); - while (len--) { - Wire.write(*reg_data); - reg_data++; - } - Wire.endTransmission(); - return 0; -} - -void I2cScan(char *devs, unsigned int devs_len) -{ - - - - - - - - uint8_t error = 0; - uint8_t address = 0; - uint8_t any = 0; - - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_DEVICES_FOUND_AT)); - for (address = 1; address <= 127; address++) { - Wire.beginTransmission(address); - error = Wire.endTransmission(); - if (0 == error) { - any = 1; - snprintf_P(devs, devs_len, PSTR("%s 0x%02x"), devs, address); - } - else if (error != 2) { - any = 2; - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"Error %d at 0x%02x"), error, address); - break; - } - } - if (any) { - strncat(devs, "\"}", devs_len - strlen(devs) -1); - } - else { - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_NO_DEVICES_FOUND "\"}")); - } -} - -void I2cResetActive(uint32_t addr, uint32_t count = 1) -{ - addr &= 0x7F; - count &= 0x7F; - while (count-- && (addr < 128)) { - i2c_active[addr / 32] &= ~(1 << (addr % 32)); - addr++; - } - -} - -void I2cSetActive(uint32_t addr, uint32_t count = 1) -{ - addr &= 0x7F; - count &= 0x7F; - while (count-- && (addr < 128)) { - i2c_active[addr / 32] |= (1 << (addr % 32)); - addr++; - } - -} - -void I2cSetActiveFound(uint32_t addr, const char *types) -{ - I2cSetActive(addr); - AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, types, addr); -} - -bool I2cActive(uint32_t addr) -{ - addr &= 0x7F; - if (i2c_active[addr / 32] & (1 << (addr % 32))) { - return true; - } - return false; -} - -bool I2cSetDevice(uint32_t addr) -{ - addr &= 0x7F; - if (I2cActive(addr)) { - return false; - } - Wire.beginTransmission((uint8_t)addr); - return (0 == Wire.endTransmission()); -} -#endif -# 1559 "C:/shared/sonoff/Git/Tasmota/tasmota/support.ino" -void SetSeriallog(uint32_t loglevel) -{ - Settings.seriallog_level = loglevel; - seriallog_level = loglevel; - seriallog_timer = 0; -} - -void SetSyslog(uint32_t loglevel) -{ - Settings.syslog_level = loglevel; - syslog_level = loglevel; - syslog_timer = 0; -} - -#ifdef USE_WEBSERVER -void GetLog(uint32_t idx, char** entry_pp, size_t* len_p) -{ - char* entry_p = nullptr; - size_t len = 0; - - if (idx) { - char* it = web_log; - do { - uint32_t cur_idx = *it; - it++; - size_t tmp = strchrspn(it, '\1'); - tmp++; - if (cur_idx == idx) { - len = tmp; - entry_p = it; - break; - } - it += tmp; - } while (it < web_log + WEB_LOG_SIZE && *it != '\0'); - } - *entry_pp = entry_p; - *len_p = len; -} -#endif - -void Syslog(void) -{ - - - uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); - if (syslog_host_hash != current_hash) { - syslog_host_hash = current_hash; - WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); - } - if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { - char syslog_preamble[64]; - snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), my_hostname); - memmove(log_data + strlen(syslog_preamble), log_data, sizeof(log_data) - strlen(syslog_preamble)); - log_data[sizeof(log_data) -1] = '\0'; - memcpy(log_data, syslog_preamble, strlen(syslog_preamble)); - PortUdp.write(log_data, strlen(log_data)); - PortUdp.endPacket(); - delay(1); - } else { - syslog_level = 0; - syslog_timer = SYSLOG_TIMER; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER); - } -} - -void AddLog(uint32_t loglevel) -{ - char mxtime[10]; - - snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d "), RtcTime.hour, RtcTime.minute, RtcTime.second); - - if (loglevel <= seriallog_level) { - Serial.printf("%s%s\r\n", mxtime, log_data); - } -#ifdef USE_WEBSERVER - if (Settings.webserver && (loglevel <= Settings.weblog_level)) { - - - web_log_index &= 0xFF; - if (!web_log_index) web_log_index++; - while (web_log_index == web_log[0] || - strlen(web_log) + strlen(log_data) + 13 > WEB_LOG_SIZE) - { - char* it = web_log; - it++; - it += strchrspn(it, '\1'); - it++; - memmove(web_log, it, WEB_LOG_SIZE -(it-web_log)); - } - snprintf_P(web_log, sizeof(web_log), PSTR("%s%c%s%s\1"), web_log, web_log_index++, mxtime, log_data); - web_log_index &= 0xFF; - if (!web_log_index) web_log_index++; - } -#endif - if (Settings.flag.mqtt_enabled && - !global_state.mqtt_down && - (loglevel <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } - - if (!global_state.wifi_down && - (loglevel <= syslog_level)) { Syslog(); } -} - -void AddLog_P(uint32_t loglevel, const char *formatP) -{ - snprintf_P(log_data, sizeof(log_data), formatP); - AddLog(loglevel); -} - -void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2) -{ - char message[sizeof(log_data)]; - - snprintf_P(log_data, sizeof(log_data), formatP); - snprintf_P(message, sizeof(message), formatP2); - strncat(log_data, message, sizeof(log_data) - strlen(log_data) -1); - AddLog(loglevel); -} - -void PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...) -{ - va_list arg; - va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); - va_end(arg); - - prepped_loglevel = loglevel; -} - -void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...) -{ - va_list arg; - va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); - va_end(arg); - - AddLog(loglevel); -} - -void AddLog_Debug(PGM_P formatP, ...) -{ - va_list arg; - va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); - va_end(arg); - - AddLog(LOG_LEVEL_DEBUG); -} - -void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count) -{ -# 1721 "C:/shared/sonoff/Git/Tasmota/tasmota/support.ino" - char hex_char[(count * 3) + 2]; - AddLog_P2(loglevel, PSTR("DMP: %s"), ToHex_P(buffer, count, hex_char, sizeof(hex_char), ' ')); -} - -void AddLogSerial(uint32_t loglevel) -{ - AddLogBuffer(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); -} - -void AddLogMissed(char *sensor, uint32_t misses) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_button.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_button.ino" -#define BUTTON_V1 -#ifdef BUTTON_V1 - - - - -#define MAX_BUTTON_COMMANDS 5 -const char kCommands[] PROGMEM = - D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; - -struct BUTTON { - unsigned long debounce = 0; - uint16_t hold_timer[MAX_KEYS] = { 0 }; - uint16_t dual_code = 0; - - uint8_t last_state[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; - uint8_t window_timer[MAX_KEYS] = { 0 }; - uint8_t press_counter[MAX_KEYS] = { 0 }; - - uint8_t dual_receive_count = 0; - uint8_t no_pullup_mask = 0; - uint8_t inverted_mask = 0; - uint8_t present = 0; - uint8_t adc = 99; -} Button; - - - -void ButtonPullupFlag(uint8 button_bit) -{ - bitSet(Button.no_pullup_mask, button_bit); -} - -void ButtonInvertFlag(uint8 button_bit) -{ - bitSet(Button.inverted_mask, button_bit); -} - -void ButtonInit(void) -{ - Button.present = 0; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if (pin[GPIO_KEY1 +i] < 99) { - Button.present++; - pinMode(pin[GPIO_KEY1 +i], bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); - } -#ifndef USE_ADC_VCC - else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) { - Button.present++; - Button.adc = i; - } -#endif - } -} - -uint8_t ButtonSerial(uint8_t serial_in_byte) -{ - if (Button.dual_receive_count) { - Button.dual_receive_count--; - if (Button.dual_receive_count) { - Button.dual_code = (Button.dual_code << 8) | serial_in_byte; - serial_in_byte = 0; - } else { - if (serial_in_byte != 0xA1) { - Button.dual_code = 0; - } - } - } - if (0xA0 == serial_in_byte) { - serial_in_byte = 0; - Button.dual_code = 0; - Button.dual_receive_count = 3; - } - - return serial_in_byte; -} -# 108 "C:/shared/sonoff/Git/Tasmota/tasmota/support_button.ino" -void ButtonHandler(void) -{ - if (uptime < 4) { return; } - - uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; - uint16_t loops_per_second = 1000 / Settings.button_debounce; - char scmnd[20]; - - - - for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { - uint8_t button = NOT_PRESSED; - uint8_t button_present = 0; - - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { - button_present = 1; - if (Button.dual_code) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code); - button = PRESSED; - if (0xF500 == Button.dual_code) { - Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; - hold_time_extent = 1; - } - Button.dual_code = 0; - } - } - else if (pin[GPIO_KEY1 +button_index] < 99) { - button_present = 1; - button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(Button.inverted_mask, button_index)); - } -#ifndef USE_ADC_VCC - if (Button.adc == button_index) { - button_present = 1; - if (ADC0_BUTTON_INV == my_adc0) { - button = (AdcRead(1) < 128); - } - else if (ADC0_BUTTON == my_adc0) { - button = (AdcRead(1) > 128); - } - } -#endif - - if (button_present) { - XdrvMailbox.index = button_index; - XdrvMailbox.payload = button; - if (XdrvCall(FUNC_BUTTON_PRESSED)) { - - } - else if (SONOFF_4CHPRO == my_module_type) { - if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; } - - bool button_pressed = false; - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); - Button.hold_timer[button_index] = loops_per_second; - button_pressed = true; - } - if ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index])) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); - if (!Button.hold_timer[button_index]) { button_pressed = true; } - } - if (button_pressed) { - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); - } - } - } - else { - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - if (Settings.flag.button_single) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); - } - } else { - Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]); - Button.window_timer[button_index] = loops_per_second / 2; - } - blinks = 201; - } - - if (NOT_PRESSED == button) { - Button.hold_timer[button_index] = 0; - } else { - Button.hold_timer[button_index]++; - if (Settings.flag.button_single) { - if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } else { - if (Settings.flag.button_restrict) { - if (Settings.param[P_HOLD_IGNORE] > 0) { - if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { - Button.hold_timer[button_index] = 0; - Button.press_counter[button_index] = 0; - DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]); - } - } - if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { - Button.press_counter[button_index] = 0; - SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); - } - } else { - if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { - Button.press_counter[button_index] = 0; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } - } - - if (!Settings.flag.button_single) { - if (Button.window_timer[button_index]) { - Button.window_timer[button_index]--; - } else { - if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS +3)) { - bool single_press = false; - if (Button.press_counter[button_index] < 3) { - if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - single_press = true; - } else { - single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); - if ((1 == Button.present) && (2 == devices_present)) { - if (Settings.flag.button_swap) { - Button.press_counter[button_index] = (single_press) ? 1 : 2; - } - } else { - Button.press_counter[button_index] = 1; - } - } - } -#if defined(USE_LIGHT) && defined(ROTARY_V1) - if (!((0 == button_index) && RotaryButtonPressed())) { -#endif - if (single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { - - } else { - if (Button.press_counter[button_index] < 3) { - if (WifiState() > WIFI_RESTART) { - restart_flag = 1; - } else { - ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); - } - } else { - if (!Settings.flag.button_restrict) { - GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -3, kCommands); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } -#if defined(USE_LIGHT) && defined(ROTARY_V1) - } -#endif - Button.press_counter[button_index] = 0; - } - } - } - } - } - Button.last_state[button_index] = button; - } -} - -void ButtonLoop(void) -{ - if (Button.present) { - if (TimeReached(Button.debounce)) { - SetNextTimeInterval(Button.debounce, Settings.button_debounce); - ButtonHandler(); - } - } -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_command.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_command.ino" -const char kTasmotaCommands[] PROGMEM = "|" - D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" - D_CMND_SERIALLOG "|" D_CMND_RESTART "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|" - D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" - D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" - D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" - D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|" - D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" - D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" - D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" -#ifdef USE_I2C - D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" -#endif - D_CMND_SENSOR "|" D_CMND_DRIVER; - -void (* const TasmotaCommand[])(void) PROGMEM = { - &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, - &CmndSeriallog, &CmndRestart, &CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata, - &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, - &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, - &CmndModule, &CmndModules, &CmndGpio, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange, - &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig, - &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, - &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, - &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, -#ifdef USE_I2C - &CmndI2cScan, CmndI2cDriver, -#endif - &CmndSensor, &CmndDriver }; - -const char kWifiConfig[] PROGMEM = - D_WCFG_0_RESTART "||" D_WCFG_2_WIFIMANAGER "||" D_WCFG_4_RETRY "|" D_WCFG_5_WAIT "|" D_WCFG_6_SERIAL "|" D_WCFG_7_WIFIMANAGER_RESET_ONLY; - - - -void ResponseCmndNumber(int value) -{ - Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, value); -} - -void ResponseCmndFloat(float value, uint32_t decimals) -{ - char stemp1[TOPSZ]; - dtostrfd(value, decimals, stemp1); - Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp1); -} - -void ResponseCmndIdxNumber(int value) -{ - Response_P(S_JSON_COMMAND_INDEX_NVALUE, XdrvMailbox.command, XdrvMailbox.index, value); -} - -void ResponseCmndChar(const char* value) -{ - Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, value); -} - -void ResponseCmndStateText(uint32_t value) -{ - ResponseCmndChar(GetStateText(value)); -} - -void ResponseCmndDone(void) -{ - ResponseCmndChar(D_JSON_DONE); -} - -void ResponseCmndIdxChar(const char* value) -{ - Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, value); -} - -void ResponseCmndAll(uint32_t text_index, uint32_t count) -{ - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < count; i++) { - ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, SettingsText(text_index +i)); - } - ResponseJsonEnd(); -} - - - -void ExecuteCommand(const char *cmnd, uint32_t source) -{ - - - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("ExecuteCommand")); -#endif - ShowSource(source); - - const char *pos = cmnd; - while (*pos && isspace(*pos)) { - pos++; - } - - const char *start = pos; - - while (*pos && (isalpha(*pos) || isdigit(*pos) || '_' == *pos || '/' == *pos)) { - if ('/' == *pos) { - start = pos + 1; - } - pos++; - } - if ('\0' == *start || pos <= start) { - return; - } - - uint32_t size = pos - start; - char stopic[size + 2]; - stopic[0] = '/'; - memcpy(stopic+1, start, size); - stopic[size+1] = '\0'; - - char svalue[strlen(pos) +1]; - strlcpy(svalue, pos, sizeof(svalue)); - CommandHandler(stopic, svalue, strlen(svalue)); -} -# 148 "C:/shared/sonoff/Git/Tasmota/tasmota/support_command.ino" -void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) -{ -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("CommandHandler")); -#endif - - while (*dataBuf && isspace(*dataBuf)) { - dataBuf++; - data_len--; - } - - bool grpflg = (strstr(topicBuf, SettingsText(SET_MQTT_GRP_TOPIC)) != nullptr); - - char stemp1[TOPSZ]; - GetFallbackTopic_P(stemp1, ""); - fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); - - char *type = strrchr(topicBuf, '/'); - - uint32_t index = 1; - bool user_index = false; - if (type != nullptr) { - type++; - uint32_t i; - for (i = 0; i < strlen(type); i++) { - type[i] = toupper(type[i]); - } - while (isdigit(type[i-1])) { - i--; - } - if (i < strlen(type)) { - index = atoi(type +i); - user_index = true; - } - type[i] = '\0'; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf); - - if (type != nullptr) { - Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); - - if (Settings.ledstate &0x02) { blinks++; } - - if (!strcmp(dataBuf,"?")) { data_len = 0; } - - char *p; - int32_t payload = strtol(dataBuf, &p, 0); - if (p == dataBuf) { payload = -99; } - int temp_payload = GetStateNumber(dataBuf); - if (temp_payload > -1) { payload = temp_payload; } - - DEBUG_CORE_LOG(PSTR("CMD: Payload %d"), payload); - - - backlog_delay = millis() + Settings.param[P_BACKLOG_DELAY]; - - char command[CMDSZ] = { 0 }; - XdrvMailbox.command = command; - XdrvMailbox.index = index; - XdrvMailbox.data_len = data_len; - XdrvMailbox.payload = payload; - XdrvMailbox.grpflg = grpflg; - XdrvMailbox.usridx = user_index; - XdrvMailbox.topic = type; - XdrvMailbox.data = dataBuf; - -#ifdef USE_SCRIPT_SUB_COMMAND - - if (!Script_SubCmd()) { - if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { - if (!XdrvCall(FUNC_COMMAND)) { - if (!XsnsCall(FUNC_COMMAND)) { - type = nullptr; - } - } - } - } -#else - if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { - if (!XdrvCall(FUNC_COMMAND)) { - if (!XsnsCall(FUNC_COMMAND)) { - type = nullptr; - } - } - } -#endif - - } - - if (type == nullptr) { - blinks = 201; - snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_COMMAND)); - Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); - type = (char*)stemp1; - } - - if (mqtt_data[0] != '\0') { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); - XdrvRulesProcess(); - } - fallback_topic_flag = false; -} - - - -void CmndBacklog(void) -{ - if (XdrvMailbox.data_len) { - -#ifdef SUPPORT_IF_STATEMENT - char *blcommand = strtok(XdrvMailbox.data, ";"); - while ((blcommand != nullptr) && (backlog.size() < MAX_BACKLOG)) -#else - uint32_t bl_pointer = (!backlog_pointer) ? MAX_BACKLOG -1 : backlog_pointer; - bl_pointer--; - char *blcommand = strtok(XdrvMailbox.data, ";"); - while ((blcommand != nullptr) && (backlog_index != bl_pointer)) -#endif - { - while(true) { - blcommand = Trim(blcommand); - if (!strncasecmp_P(blcommand, PSTR(D_CMND_BACKLOG), strlen(D_CMND_BACKLOG))) { - blcommand += strlen(D_CMND_BACKLOG); - } else { - break; - } - } - if (*blcommand != '\0') { -#ifdef SUPPORT_IF_STATEMENT - if (backlog.size() < MAX_BACKLOG) { - backlog.add(blcommand); - } -#else - backlog[backlog_index] = String(blcommand); - backlog_index++; - if (backlog_index >= MAX_BACKLOG) backlog_index = 0; -#endif - } - blcommand = strtok(nullptr, ";"); - } - - mqtt_data[0] = '\0'; - } else { - bool blflag = BACKLOG_EMPTY; -#ifdef SUPPORT_IF_STATEMENT - backlog.clear(); -#else - backlog_pointer = backlog_index; -#endif - ResponseCmndChar(blflag ? D_JSON_EMPTY : D_JSON_ABORTED); - } -} - -void CmndDelay(void) -{ - if ((XdrvMailbox.payload >= (MIN_BACKLOG_DELAY / 100)) && (XdrvMailbox.payload <= 3600)) { - backlog_delay = millis() + (100 * XdrvMailbox.payload); - } - uint32_t bl_delay = 0; - long bl_delta = TimePassedSince(backlog_delay); - if (bl_delta < 0) { bl_delay = (bl_delta *-1) / 100; } - ResponseCmndNumber(bl_delay); -} - -void CmndPower(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) { - if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_BLINK_STOP)) { - XdrvMailbox.payload = POWER_SHOW_STATE; - } - - ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE); - mqtt_data[0] = '\0'; - } - else if (0 == XdrvMailbox.index) { - if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_TOGGLE)) { - XdrvMailbox.payload = POWER_SHOW_STATE; - } - SetAllPower(XdrvMailbox.payload, SRC_IGNORE); - mqtt_data[0] = '\0'; - } -} - -void CmndStatus(void) -{ - uint32_t payload = ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > MAX_STATUS)) ? 99 : XdrvMailbox.payload; - - uint32_t option = STAT; - char stemp[200]; - char stemp2[TOPSZ]; - - - - - - if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } - if (!energy_flg && (9 == payload)) { payload = 99; } - if (!CrashFlag() && (12 == payload)) { payload = 99; } - - if ((0 == payload) || (99 == payload)) { - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { maxfn = 1; } -#endif - stemp[0] = '\0'; - for (uint32_t i = 0; i < maxfn; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), SettingsText(SET_FRIENDLYNAME1 +i)); - } - stemp2[0] = '\0'; - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); - } - Response_P(PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d,\"" D_CMND_FRIENDLYNAME "\":[%s],\"" D_CMND_TOPIC "\":\"%s\",\"" - D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" - D_CMND_LEDMASK "\":\"%04X\",\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" - D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), - ModuleNr(), stemp, mqtt_topic, - SettingsText(SET_MQTT_BUTTON_TOPIC), power, Settings.poweronstate, Settings.ledstate, - Settings.ledmask, Settings.save_data, - Settings.flag.save_state, - SettingsText(SET_MQTT_SWITCH_TOPIC), - stemp2, - Settings.flag.mqtt_button_retain, - Settings.flag.mqtt_switch_retain, - Settings.flag.mqtt_sensor_retain, - Settings.flag.mqtt_power_retain); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); - } - - if ((0 == payload) || (1 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_SERIALCONFIG "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" - D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" - D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"BCResetTime\":\"%s\",\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), - Settings.baudrate * 300, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), - GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, - Settings.cfg_holder, Settings.bootcount, GetDateAndTime(DT_BOOTCOUNT).c_str(), Settings.save_flag, GetSettingsAddress()); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); - } - - if ((0 == payload) || (2 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" - D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," - "\"Hardware\":\"%s\"" - "%s}}"), - my_version, my_image, GetBuildDateAndTime().c_str(), - ESP.getBootVersion(), ESP.getSdkVersion(), - GetDeviceHardware().c_str(), - GetStatistics().c_str()); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); - } - - if ((0 == payload) || (3 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" - D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" - D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\"]}}"), - Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, - SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), Settings.tele_period, - Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), - Settings.flag3.data, Settings.flag4.data); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3")); - } - - if ((0 == payload) || (4 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" - D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" - D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), - ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, - ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(), - LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6); - XsnsDriverState(); - ResponseAppend_P(PSTR(",\"Sensors\":")); - XsnsSensorState(); - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4")); - } - - if ((0 == payload) || (5 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\"" - D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" - D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"), - my_hostname, WiFi.localIP().toString().c_str(), IPAddress(Settings.ip_address[1]).toString().c_str(), - IPAddress(Settings.ip_address[2]).toString().c_str(), IPAddress(Settings.ip_address[3]).toString().c_str(), WiFi.macAddress().c_str(), - Settings.webserver, Settings.sta_config, WifiGetOutputPower().c_str()); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "5")); - } - - if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" - D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), - mqtt_client, SettingsText(SET_MQTT_USER), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); - } - - if ((0 == payload) || (7 == payload)) { - if (99 == Settings.timezone) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d" ), Settings.timezone); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"%s\"" ), GetTimeZone().c_str()); - } -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" - D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), - GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), - GetTime(3).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); -#else - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" - D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), - GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), - GetTime(3).c_str(), stemp); -#endif - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); - } - -#if defined(USE_ENERGY_SENSOR) && defined(USE_ENERGY_MARGIN_DETECTION) - if (energy_flg) { - if ((0 == payload) || (9 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":%d,\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" - D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), - Settings.energy_power_delta, Settings.energy_min_power, Settings.energy_max_power, - Settings.energy_min_voltage, Settings.energy_max_voltage, Settings.energy_min_current, Settings.energy_max_current); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "9")); - } - } -#endif - - if ((0 == payload) || (8 == payload) || (10 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); - MqttShowSensor(); - ResponseJsonEnd(); - if (8 == payload) { - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "8")); - } else { - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "10")); - } - } - - if ((0 == payload) || (11 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); - MqttShowState(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); - } - - if (CrashFlag()) { - if ((0 == payload) || (12 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); - CrashDump(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); - } - } - -#ifdef USE_SCRIPT_STATUS - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); -#endif - mqtt_data[0] = '\0'; -} - -void CmndState(void) -{ - mqtt_data[0] = '\0'; - MqttShowState(); - if (Settings.flag3.hass_tele_on_power) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); - } -#ifdef USE_HOME_ASSISTANT - if (Settings.flag.hass_discovery) { - HAssPublishStatus(); - } -#endif -} - -void CmndTempOffset(void) -{ - if (XdrvMailbox.data_len > 0) { - int value = (int)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > -127) && (value < 127)) { - Settings.temp_comp = value; - } - } - ResponseCmndFloat((float)(Settings.temp_comp) / 10, 1); -} - -void CmndSleep(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) { - Settings.sleep = XdrvMailbox.payload; - sleep = XdrvMailbox.payload; - WiFiSetSleepMode(); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, sleep); - -} - -void CmndUpgrade(void) -{ - - - - - if (((1 == XdrvMailbox.data_len) && (1 == XdrvMailbox.payload)) || ((XdrvMailbox.data_len >= 3) && NewerVersion(XdrvMailbox.data))) { - ota_state_flag = 3; - char stemp1[TOPSZ]; - Response_P(PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), XdrvMailbox.command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); - } else { - Response_P(PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), XdrvMailbox.command, my_version); - } -} - -void CmndOtaUrl(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_OTAURL)); -} - -void CmndSeriallog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - Settings.flag.mqtt_serial = 0; - SetSeriallog(XdrvMailbox.payload); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.seriallog_level, seriallog_level); -} - -void CmndRestart(void) -{ - switch (XdrvMailbox.payload) { - case 1: - restart_flag = 2; - ResponseCmndChar(D_JSON_RESTARTING); - break; - case -1: - CmndCrash(); - break; - case -2: - CmndWDT(); - break; - case -3: - CmndBlockedLoop(); - break; - case 99: - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - EspRestart(); - break; - default: - ResponseCmndChar(D_JSON_ONE_TO_RESTART); - } -} - -void CmndPowerOnState(void) -{ - if (my_module_type != MOTOR) { - - - - - - - - if ((XdrvMailbox.payload >= POWER_ALL_OFF) && (XdrvMailbox.payload <= POWER_ALL_OFF_PULSETIME_ON)) { - Settings.poweronstate = XdrvMailbox.payload; - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - for (uint32_t i = 1; i <= devices_present; i++) { - ExecuteCommandPower(i, POWER_ON, SRC_IGNORE); - } - } - } - ResponseCmndNumber(Settings.poweronstate); - } -} - -void CmndPulsetime(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PULSETIMERS)) { - uint32_t items = 1; - if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { - items = MAX_PULSETIMERS; - } else { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { - Settings.pulse_timer[XdrvMailbox.index -1] = XdrvMailbox.payload; - SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); - } - } - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < items; i++) { - uint32_t index = (1 == items) ? XdrvMailbox.index : i +1; - ResponseAppend_P(PSTR("%c\"%s%d\":{\"" D_JSON_SET "\":%d,\"" D_JSON_REMAINING "\":%d}"), - (i) ? ',' : '{', - XdrvMailbox.command, index, - Settings.pulse_timer[index -1], GetPulseTimer(index -1)); - } - ResponseJsonEnd(); - } -} - -void CmndBlinktime(void) -{ - if ((XdrvMailbox.payload > 1) && (XdrvMailbox.payload <= 3600)) { - Settings.blinktime = XdrvMailbox.payload; - if (blink_timer > 0) { blink_timer = millis() + (100 * XdrvMailbox.payload); } - } - ResponseCmndNumber(Settings.blinktime); -} - -void CmndBlinkcount(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { - Settings.blinkcount = XdrvMailbox.payload; - if (blink_counter) { blink_counter = Settings.blinkcount *2; } - } - ResponseCmndNumber(Settings.blinkcount); -} - -void CmndSavedata(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3600)) { - Settings.save_data = XdrvMailbox.payload; - save_data_counter = Settings.save_data; - } - SettingsSaveAll(); - char stemp1[TOPSZ]; - if (Settings.save_data > 1) { - snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_EVERY " %d " D_UNIT_SECOND), Settings.save_data); - } - ResponseCmndChar((Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); -} - -void CmndSetoption(void) -{ - if (XdrvMailbox.index < 114) { - uint32_t ptype; - uint32_t pindex; - if (XdrvMailbox.index <= 31) { - ptype = 2; - pindex = XdrvMailbox.index; - } - else if (XdrvMailbox.index <= 49) { - ptype = 1; - pindex = XdrvMailbox.index -32; - } - else if (XdrvMailbox.index <= 81) { - ptype = 3; - pindex = XdrvMailbox.index -50; - } - else { - ptype = 4; - pindex = XdrvMailbox.index -82; - } - - if (XdrvMailbox.payload >= 0) { - if (1 == ptype) { - uint32_t param_low = 0; - uint32_t param_high = 255; - switch (pindex) { - case P_HOLD_TIME: - case P_MAX_POWER_RETRY: - param_low = 1; - param_high = 250; - break; - } - if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) { - Settings.param[pindex] = XdrvMailbox.payload; -#ifdef USE_LIGHT - if (P_RGB_REMAP == pindex) { - LightUpdateColorMapping(); - restart_flag = 2; - } -#endif -#if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) - if (P_IR_UNKNOW_THRESHOLD == pindex) { - IrReceiveUpdateThreshold(); - } -#endif - } else { - ptype = 99; - } - } else { - if (XdrvMailbox.payload <= 1) { - if (2 == ptype) { - switch (pindex) { - case 5: - case 6: - case 7: - case 9: - case 14: - case 22: - case 23: - case 25: - case 27: - ptype = 99; - break; - case 3: - case 15: - restart_flag = 2; - default: - bitWrite(Settings.flag.data, pindex, XdrvMailbox.payload); - } - if (12 == pindex) { - stop_flash_rotate = XdrvMailbox.payload; - SettingsSave(2); - } - #ifdef USE_HOME_ASSISTANT - if ((19 == pindex) || (30 == pindex)) { - HAssDiscover(); - } - #endif - } - else if (3 == ptype) { - bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); - switch (pindex) { - case 5: - if (0 == XdrvMailbox.payload) { - restart_flag = 2; - } - break; - case 10: - WiFiSetSleepMode(); - break; - case 18: - case 25: - restart_flag = 2; - break; - } - } - else if (4 == ptype) { - bitWrite(Settings.flag4.data, pindex, XdrvMailbox.payload); - } - } else { - ptype = 99; - } - } - } - - if (ptype < 99) { - if (1 == ptype) { - ResponseCmndIdxNumber(Settings.param[pindex]); - } else { - uint32_t flag = Settings.flag.data; - if (3 == ptype) { - flag = Settings.flag3.data; - } - else if (4 == ptype) { - flag = Settings.flag4.data; - } - ResponseCmndIdxChar(GetStateText(bitRead(flag, pindex))); - } - } - } -} - -void CmndTemperatureResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.temperature_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.temperature_resolution); -} - -void CmndHumidityResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.humidity_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.humidity_resolution); -} - -void CmndPressureResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.pressure_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.pressure_resolution); -} - -void CmndPowerResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.wattage_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.wattage_resolution); -} - -void CmndVoltageResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.voltage_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.voltage_resolution); -} - -void CmndFrequencyResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.frequency_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.frequency_resolution); -} - -void CmndCurrentResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.current_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.current_resolution); -} - -void CmndEnergyResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - Settings.flag2.energy_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.energy_resolution); -} - -void CmndWeightResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.weight_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.weight_resolution); -} - -void CmndModule(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAXMODULE)) { - bool present = false; - if (0 == XdrvMailbox.payload) { - XdrvMailbox.payload = USER_MODULE; - present = true; - } else { - XdrvMailbox.payload--; - present = ValidTemplateModule(XdrvMailbox.payload); - } - if (present) { - Settings.last_module = Settings.module; - Settings.module = XdrvMailbox.payload; - SetModuleType(); - if (Settings.last_module != XdrvMailbox.payload) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } - } - restart_flag = 2; - } - } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, ModuleNr(), ModuleName().c_str()); -} - -void CmndModules(void) -{ - uint32_t midx = USER_MODULE; - uint32_t lines = 1; - bool jsflg = false; - for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { - if (i > 0) { midx = pgm_read_byte(kModuleNiceList + i -1); } - if (!jsflg) { - Response_P(PSTR("{\"" D_CMND_MODULES "%d\":{"), lines); - } else { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - uint32_t j = i ? midx +1 : 0; - if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), j, AnyModuleName(midx).c_str()) > (LOGSZ - TOPSZ)) || (i == sizeof(kModuleNiceList))) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command)); - jsflg = false; - lines++; - } - } - mqtt_data[0] = '\0'; -} - -void CmndGpio(void) -{ - if (XdrvMailbox.index < sizeof(Settings.my_gp)) { - myio cmodule; - ModuleGpios(&cmodule); - if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < GPIO_SENSOR_END)) { - bool present = false; - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - uint32_t midx = pgm_read_byte(kGpioNiceList + i); - if (midx == XdrvMailbox.payload) { present = true; } - } - if (present) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (ValidGPIO(i, cmodule.io[i]) && (Settings.my_gp.io[i] == XdrvMailbox.payload)) { - Settings.my_gp.io[i] = GPIO_NONE; - } - } - Settings.my_gp.io[XdrvMailbox.index] = XdrvMailbox.payload; - restart_flag = 2; - } - } - Response_P(PSTR("{")); - bool jsflg = false; - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (ValidGPIO(i, cmodule.io[i]) || ((GPIO_USER == XdrvMailbox.payload) && !FlashPin(i))) { - if (jsflg) { ResponseAppend_P(PSTR(",")); } - jsflg = true; - uint8_t sensor_type = Settings.my_gp.io[i]; - if (!ValidGPIO(i, cmodule.io[i])) { - sensor_type = cmodule.io[i]; - if (GPIO_USER == sensor_type) { - sensor_type = GPIO_NONE; - } - } - uint8_t sensor_name_idx = sensor_type; - const char *sensor_names = kSensorNames; - if (sensor_type > GPIO_FIX_START) { - sensor_name_idx = sensor_type - GPIO_FIX_START -1; - sensor_names = kSensorNamesFixed; - } - char stemp1[TOPSZ]; - ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s\"}"), - i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names)); - } - } - if (jsflg) { - ResponseJsonEnd(); - } else { - ResponseCmndChar(D_JSON_NOT_SUPPORTED); - } - } -} - -void CmndGpios(void) -{ - myio cmodule; - ModuleGpios(&cmodule); - uint32_t lines = 1; - bool jsflg = false; - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - uint32_t midx = pgm_read_byte(kGpioNiceList + i); - if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; } - if (!jsflg) { - Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":{"), lines); - } else { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - char stemp1[TOPSZ]; - if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command)); - jsflg = false; - lines++; - } - } - mqtt_data[0] = '\0'; -} - -void CmndTemplate(void) -{ - - bool error = false; - - if (strstr(XdrvMailbox.data, "{") == nullptr) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= MAXMODULE)) { - XdrvMailbox.payload--; - if (ValidTemplateModule(XdrvMailbox.payload)) { - ModuleDefault(XdrvMailbox.payload); - if (USER_MODULE == Settings.module) { restart_flag = 2; } - } - } - else if (0 == XdrvMailbox.payload) { - if (Settings.module != USER_MODULE) { - ModuleDefault(Settings.module); - } - } - else if (255 == XdrvMailbox.payload) { - if (Settings.module != USER_MODULE) { - ModuleDefault(Settings.module); - } - snprintf_P(Settings.user_template.name, sizeof(Settings.user_template.name), PSTR("Merged")); - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - if (my_module.io[j] > GPIO_NONE) { - Settings.user_template.gp.io[i] = my_module.io[j]; - } - j++; - } - } - } - else { - if (JsonTemplate(XdrvMailbox.data)) { - if (USER_MODULE == Settings.module) { restart_flag = 2; } - } else { - ResponseCmndChar(D_JSON_INVALID_JSON); - error = true; - } - } - if (!error) { TemplateJson(); } -} - -void CmndPwm(void) -{ - if (pwm_present && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PWMS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= Settings.pwm_range) && (pin[GPIO_PWM1 + XdrvMailbox.index -1] < 99)) { - Settings.pwm_value[XdrvMailbox.index -1] = XdrvMailbox.payload; - analogWrite(pin[GPIO_PWM1 + XdrvMailbox.index -1], bitRead(pwm_inverted, XdrvMailbox.index -1) ? Settings.pwm_range - XdrvMailbox.payload : XdrvMailbox.payload); - } - Response_P(PSTR("{")); - MqttShowPWMState(); - ResponseJsonEnd(); - } -} - -void CmndPwmfrequency(void) -{ - if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload >= PWM_MIN) && (XdrvMailbox.payload <= PWM_MAX))) { - Settings.pwm_frequency = (1 == XdrvMailbox.payload) ? PWM_FREQ : XdrvMailbox.payload; - analogWriteFreq(Settings.pwm_frequency); - } - ResponseCmndNumber(Settings.pwm_frequency); -} - -void CmndPwmrange(void) -{ - if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload > 254) && (XdrvMailbox.payload < 1024))) { - Settings.pwm_range = (1 == XdrvMailbox.payload) ? PWM_RANGE : XdrvMailbox.payload; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (Settings.pwm_value[i] > Settings.pwm_range) { - Settings.pwm_value[i] = Settings.pwm_range; - } - } - analogWriteRange(Settings.pwm_range); - } - ResponseCmndNumber(Settings.pwm_range); -} - -void CmndButtonDebounce(void) -{ - if ((XdrvMailbox.payload > 39) && (XdrvMailbox.payload < 1001)) { - Settings.button_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.button_debounce); -} - -void CmndSwitchDebounce(void) -{ - if ((XdrvMailbox.payload > 39) && (XdrvMailbox.payload < 1001)) { - Settings.switch_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.switch_debounce); -} - -void CmndBaudrate(void) -{ - if (XdrvMailbox.payload >= 300) { - XdrvMailbox.payload /= 300; - uint32_t baudrate = (XdrvMailbox.payload & 0xFFFF) * 300; - SetSerialBaudrate(baudrate); - } - ResponseCmndNumber(Settings.baudrate * 300); -} - -void CmndSerialConfig(void) -{ - - - - - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.data_len < 3) { - if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) { - SetSerialConfig(XdrvMailbox.payload); - } - } - else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { - uint8_t serial_config = XdrvMailbox.payload -5; - - bool valid = true; - char parity = (XdrvMailbox.data[1] & 0xdf); - if ('E' == parity) { - serial_config += 0x08; - } - else if ('O' == parity) { - serial_config += 0x10; - } - else if ('N' != parity) { - valid = false; - } - - if ('2' == XdrvMailbox.data[2]) { - serial_config += 0x04; - } - else if ('1' != XdrvMailbox.data[2]) { - valid = false; - } - - if (valid) { - SetSerialConfig(serial_config); - } - } - } - ResponseCmndChar(GetSerialConfig().c_str()); -} - -void CmndSerialSend(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { - SetSeriallog(LOG_LEVEL_NONE); - Settings.flag.mqtt_serial = 1; - Settings.flag.mqtt_serial_raw = (XdrvMailbox.index > 3) ? 1 : 0; - if (XdrvMailbox.data_len > 0) { - if (1 == XdrvMailbox.index) { - Serial.printf("%s\n", XdrvMailbox.data); - } - else if (2 == XdrvMailbox.index || 4 == XdrvMailbox.index) { - for (uint32_t i = 0; i < XdrvMailbox.data_len; i++) { - Serial.write(XdrvMailbox.data[i]); - } - } - else if (3 == XdrvMailbox.index) { - uint32_t dat_len = XdrvMailbox.data_len; - Serial.printf("%s", Unescape(XdrvMailbox.data, &dat_len)); - } - else if (5 == XdrvMailbox.index) { - SerialSendRaw(RemoveSpace(XdrvMailbox.data)); - } - ResponseCmndDone(); - } - } -} - -void CmndSerialDelimiter(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.payload < 256)) { - if (XdrvMailbox.payload > 0) { - Settings.serial_delimiter = XdrvMailbox.payload; - } else { - uint32_t dat_len = XdrvMailbox.data_len; - Unescape(XdrvMailbox.data, &dat_len); - Settings.serial_delimiter = XdrvMailbox.data[0]; - } - } - ResponseCmndNumber(Settings.serial_delimiter); -} - -void CmndSyslog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - SetSyslog(XdrvMailbox.payload); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.syslog_level, syslog_level); -} - -void CmndLoghost(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_SYSLOG_HOST, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_SYSLOG_HOST)); -} - -void CmndLogport(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { - Settings.syslog_port = (1 == XdrvMailbox.payload) ? SYS_LOG_PORT : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.syslog_port); -} - -void CmndIpAddress(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - uint32_t address; - if (ParseIp(&address, XdrvMailbox.data)) { - Settings.ip_address[XdrvMailbox.index -1] = address; - - } - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); - Response_P(S_JSON_COMMAND_INDEX_SVALUE_SVALUE, XdrvMailbox.command, XdrvMailbox.index, IPAddress(Settings.ip_address[XdrvMailbox.index -1]).toString().c_str(), (1 == XdrvMailbox.index) ? stemp1:""); - } -} - -void CmndNtpServer(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_NTP_SERVERS)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_NTPSERVER1, MAX_NTP_SERVERS); - } else { - uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1; - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(ntp_server, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? NTP_SERVER1 : (2 == XdrvMailbox.index) ? NTP_SERVER2 : NTP_SERVER3 : XdrvMailbox.data); - SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); - - ntp_force_sync = true; - } - ResponseCmndIdxChar(SettingsText(ntp_server)); - } - } -} - -void CmndAp(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - switch (XdrvMailbox.payload) { - case 0: - Settings.sta_active ^= 1; - break; - case 1: - case 2: - Settings.sta_active = XdrvMailbox.payload -1; - } - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active)); -} - -void CmndSsid(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SSIDS)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_STASSID1, MAX_SSIDS); - } else { - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; - } - ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); - } - } -} - -void CmndPassword(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.data_len > 4) || (SC_CLEAR == Shortcut()) || (SC_DEFAULT == Shortcut())) { - SettingsUpdateText(SET_STAPWD1 + XdrvMailbox.index -1, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; - ResponseCmndIdxChar(SettingsText(SET_STAPWD1 + XdrvMailbox.index -1)); - } else { - Response_P(S_JSON_COMMAND_INDEX_ASTERISK, XdrvMailbox.command, XdrvMailbox.index); - } - } -} - -void CmndHostname(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { - SettingsUpdateText(SET_HOSTNAME, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - } - restart_flag = 2; - } - ResponseCmndChar(SettingsText(SET_HOSTNAME)); -} - -void CmndWifiConfig(void) -{ - if ((XdrvMailbox.payload >= WIFI_RESTART) && (XdrvMailbox.payload < MAX_WIFI_OPTION)) { - if ((EX_WIFI_SMARTCONFIG == XdrvMailbox.payload) || (EX_WIFI_WPSCONFIG == XdrvMailbox.payload)) { - XdrvMailbox.payload = WIFI_MANAGER; - } - Settings.sta_config = XdrvMailbox.payload; - wifi_state_flag = Settings.sta_config; - if (WifiState() > WIFI_RESTART) { - restart_flag = 2; - } - } - char stemp1[TOPSZ]; - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, GetTextIndexed(stemp1, sizeof(stemp1), Settings.sta_config, kWifiConfig)); -} - -void CmndFriendlyname(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_FRIENDLYNAME1, MAX_FRIENDLYNAMES); - } else { - if (XdrvMailbox.data_len > 0) { - char stemp1[TOPSZ]; - if (1 == XdrvMailbox.index) { - snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME)); - } else { - snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); - } - SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); - } - ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1)); - } - } -} - -void CmndSwitchMode(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SWITCHES)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_SWITCH_OPTION)) { - Settings.switchmode[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.switchmode[XdrvMailbox.index-1]); - } -} - -void CmndInterlock(void) -{ - - uint32_t max_relays = devices_present; - if (light_type) { max_relays--; } - if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; } - if (max_relays > 1) { - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } - char *group; - char *q; - uint32_t group_index = 0; - power_t relay_mask = 0; - for (group = strtok_r(XdrvMailbox.data, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(nullptr, " ", &q)) { - char *str; - char *p; - for (str = strtok_r(group, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { - int pbit = atoi(str); - if ((pbit > 0) && (pbit <= max_relays)) { - pbit--; - if (!bitRead(relay_mask, pbit)) { - bitSet(relay_mask, pbit); - bitSet(Settings.interlock[group_index], pbit); - } - } - } - group_index++; - } - for (uint32_t i = 0; i < group_index; i++) { - uint32_t minimal_bits = 0; - for (uint32_t j = 0; j < max_relays; j++) { - if (bitRead(Settings.interlock[i], j)) { minimal_bits++; } - } - if (minimal_bits < 2) { Settings.interlock[i] = 0; } - } - } else { - Settings.flag.interlock = XdrvMailbox.payload &1; - if (Settings.flag.interlock) { - SetDevicePower(power, SRC_IGNORE); - } - } -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - ShutterInit(); - } -#endif - } - Response_P(PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); - uint32_t anygroup = 0; - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - if (Settings.interlock[i]) { - anygroup++; - ResponseAppend_P(PSTR("%s"), (anygroup > 1) ? " " : ""); - uint32_t anybit = 0; - power_t mask = 1; - for (uint32_t j = 0; j < max_relays; j++) { - if (Settings.interlock[i] & mask) { - anybit++; - ResponseAppend_P(PSTR("%s%d"), (anybit > 1) ? "," : "", j +1); - } - mask <<= 1; - } - } - } - if (!anygroup) { - for (uint32_t j = 1; j <= max_relays; j++) { - ResponseAppend_P(PSTR("%s%d"), (j > 1) ? "," : "", j); - } - } - ResponseAppend_P(PSTR("\"}")); - } else { - Settings.flag.interlock = 0; - ResponseCmndStateText(Settings.flag.interlock); - } -} - -void CmndTeleperiod(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.tele_period = (1 == XdrvMailbox.payload) ? TELE_PERIOD : XdrvMailbox.payload; - if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; - tele_period = Settings.tele_period; - } - ResponseCmndNumber(Settings.tele_period); -} - -void CmndReset(void) -{ - switch (XdrvMailbox.payload) { - case 1: - restart_flag = 211; - ResponseCmndChar(D_JSON_RESET_AND_RESTARTING); - break; - case 2 ... 6: - restart_flag = 210 + XdrvMailbox.payload; - Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); - break; - case 99: - Settings.bootcount = 0; - Settings.bootcount_reset_time = 0; - ResponseCmndDone(); - break; - default: - ResponseCmndChar(D_JSON_ONE_TO_RESET); - } -} - -void CmndTime(void) -{ - - - - - - - - uint32_t format = Settings.flag2.time_format; - if (XdrvMailbox.data_len > 0) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { - Settings.flag2.time_format = XdrvMailbox.payload -1; - format = Settings.flag2.time_format; - } else { - format = 1; - RtcSetTime(XdrvMailbox.payload); - } - } - mqtt_data[0] = '\0'; - ResponseAppendTimeFormat(format); - ResponseJsonEnd(); -} - -void CmndTimezone(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= -13)) { - Settings.timezone = XdrvMailbox.payload; - Settings.timezone_minutes = 0; - if (XdrvMailbox.payload < 15) { - char *p = strtok (XdrvMailbox.data, ":"); - if (p) { - p = strtok (nullptr, ":"); - if (p) { - Settings.timezone_minutes = strtol(p, nullptr, 10); - if (Settings.timezone_minutes > 59) { Settings.timezone_minutes = 59; } - } - } - } else { - Settings.timezone = 99; - } - ntp_force_sync = true; - } - if (99 == Settings.timezone) { - ResponseCmndNumber(Settings.timezone); - } else { - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%+03d:%02d"), Settings.timezone, Settings.timezone_minutes); - ResponseCmndChar(stemp1); - } -} - -void CmndTimeStdDst(uint32_t ts) -{ - - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - uint32_t tpos = 0; - int value = 0; - char *p = XdrvMailbox.data; - char *q = p; - while (p && (tpos < 7)) { - if (p > q) { - if (1 == tpos) { Settings.tflag[ts].hemis = value &1; } - if (2 == tpos) { Settings.tflag[ts].week = (value < 0) ? 0 : (value > 4) ? 4 : value; } - if (3 == tpos) { Settings.tflag[ts].month = (value < 1) ? 1 : (value > 12) ? 12 : value; } - if (4 == tpos) { Settings.tflag[ts].dow = (value < 1) ? 1 : (value > 7) ? 7 : value; } - if (5 == tpos) { Settings.tflag[ts].hour = (value < 0) ? 0 : (value > 23) ? 23 : value; } - if (6 == tpos) { Settings.toffset[ts] = (value < -900) ? -900 : (value > 900) ? 900 : value; } - } - p = Trim(p); - if (tpos && (*p == ',')) { p++; } - p = Trim(p); - q = p; - value = strtol(p, &p, 10); - tpos++; - } - ntp_force_sync = true; - } else { - if (0 == XdrvMailbox.payload) { - if (0 == ts) { - SettingsResetStd(); - } else { - SettingsResetDst(); - } - } - ntp_force_sync = true; - } - } - Response_P(PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), - XdrvMailbox.command, Settings.tflag[ts].hemis, Settings.tflag[ts].week, Settings.tflag[ts].month, Settings.tflag[ts].dow, Settings.tflag[ts].hour, Settings.toffset[ts]); -} - -void CmndTimeStd(void) -{ - CmndTimeStdDst(0); -} - -void CmndTimeDst(void) -{ - CmndTimeStdDst(1); -} - -void CmndAltitude(void) -{ - if ((XdrvMailbox.data_len > 0) && ((XdrvMailbox.payload >= -30000) && (XdrvMailbox.payload <= 30000))) { - Settings.altitude = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.altitude); -} - -void CmndLedPower(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { - if (99 == pin[GPIO_LEDLNK]) { XdrvMailbox.index = 1; } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - Settings.ledstate &= 8; - uint32_t mask = 1 << (XdrvMailbox.index -1); - switch (XdrvMailbox.payload) { - case 0: - led_power &= (0xFF ^ mask); - Settings.ledstate = 0; - break; - case 1: - led_power |= mask; - Settings.ledstate = 8; - break; - case 2: - led_power ^= mask; - Settings.ledstate ^= 8; - break; - } - blinks = 0; - if (99 == pin[GPIO_LEDLNK]) { - SetLedPower(Settings.ledstate &8); - } else { - SetLedPowerIdx(XdrvMailbox.index -1, (led_power & mask)); - } - } - bool state = bitRead(led_power, XdrvMailbox.index -1); - if (99 == pin[GPIO_LEDLNK]) { - state = bitRead(Settings.ledstate, 3); - } - ResponseCmndIdxChar(GetStateText(state)); - } -} - -void CmndLedState(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_LED_OPTION)) { - Settings.ledstate = XdrvMailbox.payload; - if (!Settings.ledstate) { - SetLedPowerAll(0); - SetLedLink(0); - } - } - ResponseCmndNumber(Settings.ledstate); -} - -void CmndLedMask(void) -{ - if (XdrvMailbox.data_len > 0) { - Settings.ledmask = XdrvMailbox.payload; - } - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d (0x%04X)"), Settings.ledmask, Settings.ledmask); - ResponseCmndChar(stemp1); -} - -void CmndWifiPower(void) -{ - if (XdrvMailbox.data_len > 0) { - Settings.wifi_output_power = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); - if (Settings.wifi_output_power > 205) { - Settings.wifi_output_power = 205; - } - WifiSetOutputPower(); - } - ResponseCmndChar(WifiGetOutputPower().c_str()); -} - -#ifdef USE_I2C -void CmndI2cScan(void) -{ - if (i2c_flg) { - I2cScan(mqtt_data, sizeof(mqtt_data)); - } -} - -void CmndI2cDriver(void) -{ - if (XdrvMailbox.index < MAX_I2C_DRIVERS) { - if (XdrvMailbox.payload >= 0) { - bitWrite(Settings.i2c_drivers[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - restart_flag = 2; - } - } - Response_P(PSTR("{\"" D_CMND_I2CDRIVER "\":")); - I2cDriverState(); - ResponseJsonEnd(); -} -#endif - -void CmndSensor(void) -{ - XsnsCall(FUNC_COMMAND_SENSOR); -} - -void CmndDriver(void) -{ - XdrvCall(FUNC_COMMAND_DRIVER); -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_crash_recorder.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_crash_recorder.ino" -const uint32_t crash_magic = 0x53415400; -const uint32_t crash_rtc_offset = 32; -const uint32_t crash_dump_max_len = 31; - - - - - - -extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) -{ - uint32_t addr_written = 0; - uint32_t value; - - for (uint32_t i = stack; i < stack_end; i += 4) { - value = *((uint32_t*) i); - if ((value >= 0x40000000) && (value < 0x40300000)) { - ESP.rtcUserMemoryWrite(crash_rtc_offset + addr_written, (uint32_t*)&value, sizeof(value)); - addr_written++; - if (addr_written >= crash_dump_max_len) { break; } - } - } - value = crash_magic + addr_written; - ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); -} - - -void CmndCrash(void) -{ - volatile uint32_t dummy; - dummy = *((uint32_t*) 0x00000000); -} - - -void CmndWDT(void) -{ - volatile uint32_t dummy = 0; - while (1) { - dummy++; - } -} - - -void CmndBlockedLoop(void) -{ - while (1) { - delay(1000); - } -} - - -void CrashDumpClear(void) -{ - uint32_t value = 0; - ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); -} - - - - - -bool CrashFlag(void) -{ - return ((ResetReason() == REASON_EXCEPTION_RST) || (ResetReason() == REASON_SOFT_WDT_RST) || oswatch_blocked_loop); -} - -void CrashDump(void) -{ - ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""), - resetInfo.exccause, - GetResetReason().c_str(), - resetInfo.epc1, - resetInfo.epc2, - resetInfo.epc3, - resetInfo.excvaddr, - resetInfo.depc); - - uint32_t value; - ESP.rtcUserMemoryRead(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); - if (crash_magic == (value & 0xFFFFFF00)) { - ResponseAppend_P(PSTR(",\"CallChain\":[")); - uint32_t count = value & 0x3F; - for (uint32_t i = 0; i < count; i++) { - ESP.rtcUserMemoryRead(crash_rtc_offset +i, (uint32_t*)&value, sizeof(value)); - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"%08x\""), value); - } - ResponseAppend_P(PSTR("]")); - } - - ResponseJsonEnd(); -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_esptool.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_esptool.ino" -#define USE_ESPTOOL -#ifdef USE_ESPTOOL - - - - - - - -#define READ_REG(REG) (*((volatile uint32_t *)(REG))) -#define WRITE_REG(REG,VAL) *((volatile uint32_t *)(REG)) = (VAL) -#define REG_SET_MASK(reg,mask) WRITE_REG((reg), (READ_REG(reg)|(mask))) - -#define SPI_BASE_REG 0x60000200 - -#define SPI_CMD_REG (SPI_BASE_REG + 0x00) -#define SPI_FLASH_RDSR (1<<27) -#define SPI_FLASH_SE (1<<24) -#define SPI_FLASH_BE (1<<23) -#define SPI_FLASH_WREN (1<<30) - -#define SPI_ADDR_REG (SPI_BASE_REG + 0x04) -#define SPI_CTRL_REG (SPI_BASE_REG + 0x08) -#define SPI_RD_STATUS_REG (SPI_BASE_REG + 0x10) -#define SPI_W0_REG (SPI_BASE_REG + 0x40) -#define SPI_EXT2_REG (SPI_BASE_REG + 0xF8) - -#define SPI_ST 0x7 - - -#define SECTORS_PER_BLOCK (FLASH_BLOCK_SIZE / SPI_FLASH_SEC_SIZE) - - -static const uint32_t STATUS_WIP_BIT = (1 << 0); - - -inline static void spi_wait_ready(void) -{ - while((READ_REG(SPI_EXT2_REG) & SPI_ST)) { } -} - - - -static bool spiflash_is_ready(void) -{ - spi_wait_ready(); - WRITE_REG(SPI_RD_STATUS_REG, 0); - WRITE_REG(SPI_CMD_REG, SPI_FLASH_RDSR); - while(READ_REG(SPI_CMD_REG) != 0) { } - uint32_t status_value = READ_REG(SPI_RD_STATUS_REG); - return (status_value & STATUS_WIP_BIT) == 0; -} - -static void spi_write_enable(void) -{ - while(!spiflash_is_ready()) { } - WRITE_REG(SPI_CMD_REG, SPI_FLASH_WREN); - while(READ_REG(SPI_CMD_REG) != 0) { } -} - -bool EsptoolEraseSector(uint32_t sector) -{ - spi_write_enable(); - spi_wait_ready(); - - WRITE_REG(SPI_ADDR_REG, (sector * SPI_FLASH_SEC_SIZE) & 0xffffff); - WRITE_REG(SPI_CMD_REG, SPI_FLASH_SE); - while(READ_REG(SPI_CMD_REG) != 0) { } - while(!spiflash_is_ready()) { } - - return true; -} - -void EsptoolErase(uint32_t start_sector, uint32_t end_sector) -{ - int next_erase_sector = start_sector; - int remaining_erase_sector = end_sector - start_sector; - - while (remaining_erase_sector > 0) { - spi_write_enable(); - - uint32_t command = SPI_FLASH_SE; - uint32_t sectors_to_erase = 1; - if (remaining_erase_sector >= SECTORS_PER_BLOCK && - next_erase_sector % SECTORS_PER_BLOCK == 0) { - command = SPI_FLASH_BE; - sectors_to_erase = SECTORS_PER_BLOCK; - } - uint32_t addr = next_erase_sector * SPI_FLASH_SEC_SIZE; - - spi_wait_ready(); - WRITE_REG(SPI_ADDR_REG, addr & 0xffffff); - WRITE_REG(SPI_CMD_REG, command); - while(READ_REG(SPI_CMD_REG) != 0) { } - remaining_erase_sector -= sectors_to_erase; - next_erase_sector += sectors_to_erase; - - while (!spiflash_is_ready()) { } - yield(); - OsWatchLoop(); - } -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_features.ino" -# 24 "C:/shared/sonoff/Git/Tasmota/tasmota/support_features.ino" -void GetFeatures(void) -{ - feature_drv1 = 0x00000000; - -#ifdef USE_ENERGY_MARGIN_DETECTION - feature_drv1 |= 0x00000001; -#endif -#ifdef USE_LIGHT - feature_drv1 |= 0x00000002; -#endif -#ifdef USE_I2C - feature_drv1 |= 0x00000004; -#endif -#ifdef USE_SPI - feature_drv1 |= 0x00000008; -#endif -#ifdef USE_DISCOVERY - feature_drv1 |= 0x00000010; -#endif -#ifdef USE_ARDUINO_OTA - feature_drv1 |= 0x00000020; -#endif -#ifdef USE_MQTT_TLS - feature_drv1 |= 0x00000040; -#endif -#ifdef USE_WEBSERVER - feature_drv1 |= 0x00000080; -#endif -#ifdef WEBSERVER_ADVERTISE - feature_drv1 |= 0x00000100; -#endif -#ifdef USE_EMULATION_HUE - feature_drv1 |= 0x00000200; -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) - feature_drv1 |= 0x00000400; -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) - -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) - -#endif -#ifdef MQTT_HOST_DISCOVERY - feature_drv1 |= 0x00002000; -#endif -#ifdef USE_ARILUX_RF - feature_drv1 |= 0x00004000; -#endif -#if defined(USE_LIGHT) && defined(USE_WS2812) - feature_drv1 |= 0x00008000; -#endif -#ifdef USE_WS2812_DMA - feature_drv1 |= 0x00010000; -#endif -#if defined(USE_IR_REMOTE) || defined(USE_IR_REMOTE_FULL) - feature_drv1 |= 0x00020000; -#endif -#ifdef USE_IR_HVAC - feature_drv1 |= 0x00040000; -#endif -#ifdef USE_IR_RECEIVE - feature_drv1 |= 0x00080000; -#endif -#ifdef USE_DOMOTICZ - feature_drv1 |= 0x00100000; -#endif -#ifdef USE_DISPLAY - feature_drv1 |= 0x00200000; -#endif -#ifdef USE_HOME_ASSISTANT - feature_drv1 |= 0x00400000; -#endif -#ifdef USE_SERIAL_BRIDGE - feature_drv1 |= 0x00800000; -#endif -#ifdef USE_TIMERS - feature_drv1 |= 0x01000000; -#endif -#ifdef USE_SUNRISE - feature_drv1 |= 0x02000000; -#endif -#ifdef USE_TIMERS_WEB - feature_drv1 |= 0x04000000; -#endif -#ifdef USE_RULES - feature_drv1 |= 0x08000000; -#endif -#ifdef USE_KNX - feature_drv1 |= 0x10000000; -#endif -#ifdef USE_WPS - feature_drv1 |= 0x20000000; -#endif -#ifdef USE_SMARTCONFIG - feature_drv1 |= 0x40000000; -#endif -#ifdef USE_ENERGY_POWER_LIMIT - feature_drv1 |= 0x80000000; -#endif - - - - feature_drv2 = 0x00000000; - -#ifdef USE_CONFIG_OVERRIDE - feature_drv2 |= 0x00000001; -#endif -#ifdef FIRMWARE_MINIMAL - feature_drv2 |= 0x00000002; -#endif -#ifdef FIRMWARE_SENSORS - feature_drv2 |= 0x00000004; -#endif -#ifdef FIRMWARE_CLASSIC - feature_drv2 |= 0x00000008; -#endif -#ifdef FIRMWARE_KNX_NO_EMULATION - feature_drv2 |= 0x00000010; -#endif -#ifdef USE_DISPLAY_MODES1TO5 - feature_drv2 |= 0x00000020; -#endif -#ifdef USE_DISPLAY_GRAPH - feature_drv2 |= 0x00000040; -#endif -#ifdef USE_DISPLAY_LCD - feature_drv2 |= 0x00000080; -#endif -#ifdef USE_DISPLAY_SSD1306 - feature_drv2 |= 0x00000100; -#endif -#ifdef USE_DISPLAY_MATRIX - feature_drv2 |= 0x00000200; -#endif -#ifdef USE_DISPLAY_ILI9341 - feature_drv2 |= 0x00000400; -#endif -#ifdef USE_DISPLAY_EPAPER_29 - feature_drv2 |= 0x00000800; -#endif -#ifdef USE_DISPLAY_SH1106 - feature_drv2 |= 0x00001000; -#endif -#ifdef USE_MP3_PLAYER - feature_drv2 |= 0x00002000; -#endif -#ifdef USE_PCA9685 - feature_drv2 |= 0x00004000; -#endif -#if defined(USE_LIGHT) && defined(USE_TUYA_MCU) - feature_drv2 |= 0x00008000; -#endif -#ifdef USE_RC_SWITCH - feature_drv2 |= 0x00010000; -#endif -#if defined(USE_LIGHT) && defined(USE_ARMTRONIX_DIMMERS) - feature_drv2 |= 0x00020000; -#endif -#if defined(USE_LIGHT) && defined(USE_SM16716) - feature_drv2 |= 0x00040000; -#endif -#ifdef USE_SCRIPT - feature_drv2 |= 0x00080000; -#endif -#ifdef USE_EMULATION_WEMO - feature_drv2 |= 0x00100000; -#endif -#ifdef USE_SONOFF_IFAN - feature_drv2 |= 0x00200000; -#endif -#ifdef USE_ZIGBEE - feature_drv2 |= 0x00400000; -#endif -#ifdef NO_EXTRA_4K_HEAP - feature_drv2 |= 0x00800000; -#endif -#ifdef VTABLES_IN_IRAM - feature_drv2 |= 0x01000000; -#endif -#ifdef VTABLES_IN_DRAM - feature_drv2 |= 0x02000000; -#endif -#ifdef VTABLES_IN_FLASH - feature_drv2 |= 0x04000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH - feature_drv2 |= 0x08000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY - feature_drv2 |= 0x10000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH - feature_drv2 |= 0x20000000; -#endif -#ifdef DEBUG_THEO - feature_drv2 |= 0x40000000; -#endif -#ifdef USE_DEBUG_DRIVER - feature_drv2 |= 0x80000000; -#endif - - - - feature_sns1 = 0x00000000; - -#ifdef USE_COUNTER - feature_sns1 |= 0x00000001; -#endif -#ifdef USE_ADC_VCC - feature_sns1 |= 0x00000002; -#endif -#ifdef USE_ENERGY_SENSOR - feature_sns1 |= 0x00000004; -#endif -#ifdef USE_PZEM004T - feature_sns1 |= 0x00000008; -#endif -#ifdef USE_DS18B20 - feature_sns1 |= 0x00000010; -#endif -#ifdef USE_DS18x20_LEGACY - feature_sns1 |= 0x00000020; -#endif -#ifdef USE_DS18x20 - feature_sns1 |= 0x00000040; -#endif -#ifdef USE_DHT - feature_sns1 |= 0x00000080; -#endif -#ifdef USE_SHT - feature_sns1 |= 0x00000100; -#endif -#ifdef USE_HTU - feature_sns1 |= 0x00000200; -#endif -#ifdef USE_BMP - feature_sns1 |= 0x00000400; -#endif -#ifdef USE_BME680 - feature_sns1 |= 0x00000800; -#endif -#ifdef USE_BH1750 - feature_sns1 |= 0x00001000; -#endif -#ifdef USE_VEML6070 - feature_sns1 |= 0x00002000; -#endif -#ifdef USE_ADS1115_I2CDEV - feature_sns1 |= 0x00004000; -#endif -#ifdef USE_ADS1115 - feature_sns1 |= 0x00008000; -#endif -#ifdef USE_INA219 - feature_sns1 |= 0x00010000; -#endif -#ifdef USE_SHT3X - feature_sns1 |= 0x00020000; -#endif -#ifdef USE_MHZ19 - feature_sns1 |= 0x00040000; -#endif -#ifdef USE_TSL2561 - feature_sns1 |= 0x00080000; -#endif -#ifdef USE_SENSEAIR - feature_sns1 |= 0x00100000; -#endif -#ifdef USE_PMS5003 - feature_sns1 |= 0x00200000; -#endif -#ifdef USE_MGS - feature_sns1 |= 0x00400000; -#endif -#ifdef USE_NOVA_SDS - feature_sns1 |= 0x00800000; -#endif -#ifdef USE_SGP30 - feature_sns1 |= 0x01000000; -#endif -#ifdef USE_SR04 - feature_sns1 |= 0x02000000; -#endif -#ifdef USE_SDM120 - feature_sns1 |= 0x04000000; -#endif -#ifdef USE_SI1145 - feature_sns1 |= 0x08000000; -#endif -#ifdef USE_SDM630 - feature_sns1 |= 0x10000000; -#endif -#ifdef USE_LM75AD - feature_sns1 |= 0x20000000; -#endif -#ifdef USE_APDS9960 - feature_sns1 |= 0x40000000; -#endif -#ifdef USE_TM1638 - feature_sns1 |= 0x80000000; -#endif - - - - feature_sns2 = 0x00000000; - -#ifdef USE_MCP230xx - feature_sns2 |= 0x00000001; -#endif -#ifdef USE_MPR121 - feature_sns2 |= 0x00000002; -#endif -#ifdef USE_CCS811 - feature_sns2 |= 0x00000004; -#endif -#ifdef USE_MPU6050 - feature_sns2 |= 0x00000008; -#endif -#ifdef USE_MCP230xx_OUTPUT - feature_sns2 |= 0x00000010; -#endif -#ifdef USE_MCP230xx_DISPLAYOUTPUT - feature_sns2 |= 0x00000020; -#endif -#ifdef USE_HLW8012 - feature_sns2 |= 0x00000040; -#endif -#ifdef USE_CSE7766 - feature_sns2 |= 0x00000080; -#endif -#ifdef USE_MCP39F501 - feature_sns2 |= 0x00000100; -#endif -#ifdef USE_PZEM_AC - feature_sns2 |= 0x00000200; -#endif -#ifdef USE_DS3231 - feature_sns2 |= 0x00000400; -#endif -#ifdef USE_HX711 - feature_sns2 |= 0x00000800; -#endif -#ifdef USE_PZEM_DC - feature_sns2 |= 0x00001000; -#endif -#ifdef USE_TX20_WIND_SENSOR - feature_sns2 |= 0x00002000; -#endif -#ifdef USE_MGC3130 - feature_sns2 |= 0x00004000; -#endif -#ifdef USE_RF_SENSOR - feature_sns2 |= 0x00008000; -#endif -#ifdef USE_THEO_V2 - feature_sns2 |= 0x00010000; -#endif -#ifdef USE_ALECTO_V2 - feature_sns2 |= 0x00020000; -#endif -#ifdef USE_AZ7798 - feature_sns2 |= 0x00040000; -#endif -#ifdef USE_MAX31855 - feature_sns2 |= 0x00080000; -#endif -#ifdef USE_PN532_HSU - feature_sns2 |= 0x00100000; -#endif -#ifdef USE_MAX44009 - feature_sns2 |= 0x00200000; -#endif -#ifdef USE_SCD30 - feature_sns2 |= 0x00400000; -#endif -#ifdef USE_HRE - feature_sns2 |= 0x00800000; -#endif -#ifdef USE_ADE7953 - feature_sns2 |= 0x01000000; -#endif -#ifdef USE_SPS30 - feature_sns2 |= 0x02000000; -#endif -#ifdef USE_VL53L0X - feature_sns2 |= 0x04000000; -#endif -#ifdef USE_MLX90614 - feature_sns2 |= 0x08000000; -#endif -#ifdef USE_MAX31865 - feature_sns2 |= 0x10000000; -#endif -#ifdef USE_CHIRP - feature_sns2 |= 0x20000000; -#endif -#ifdef USE_SOLAX_X1 - feature_sns2 |= 0x40000000; -#endif -#ifdef USE_PAJ7620 - feature_sns2 |= 0x80000000; -#endif - - - - feature5 = 0x00000000; - -#ifdef USE_BUZZER - feature5 |= 0x00000001; -#endif -#ifdef USE_RDM6300 - feature5 |= 0x00000002; -#endif -#ifdef USE_IBEACON - feature5 |= 0x00000004; -#endif -#ifdef USE_SML_M - feature5 |= 0x00000008; -#endif -#ifdef USE_INA226 - feature5 |= 0x00000010; -#endif -#ifdef USE_A4988_STEPPER - feature5 |= 0x00000020; -#endif -#ifdef USE_DDS2382 - feature5 |= 0x00000040; -#endif -#ifdef USE_SM2135 - feature5 |= 0x00000080; -#endif -#ifdef USE_SHUTTER - feature5 |= 0x00000100; -#endif -#ifdef USE_PCF8574 - feature5 |= 0x00000200; -#endif -#ifdef USE_DDSU666 - feature5 |= 0x00000400; -#endif -#ifdef USE_DEEPSLEEP - feature5 |= 0x00000800; -#endif -#ifdef USE_SONOFF_SC - feature5 |= 0x00001000; -#endif -#ifdef USE_SONOFF_RF - feature5 |= 0x00002000; -#endif -#ifdef USE_SONOFF_L1 - feature5 |= 0x00004000; -#endif -#ifdef USE_EXS_DIMMER - feature5 |= 0x00008000; -#endif -#ifdef USE_ARDUINO_SLAVE - feature5 |= 0x00010000; -#endif -#ifdef USE_HIH6 - feature5 |= 0x00020000; -#endif -#ifdef USE_HPMA - feature5 |= 0x00040000; -#endif -#ifdef USE_TSL2591 - feature5 |= 0x00080000; -#endif -#ifdef USE_DHT12 - feature5 |= 0x00100000; -#endif -#ifdef USE_DS1624 - feature5 |= 0x00200000; -#endif -#ifdef USE_GPS - feature5 |= 0x00400000; -#endif -#ifdef USE_HOTPLUG - feature5 |= 0x00800000; -#endif -#ifdef USE_NRF24 - feature5 |= 0x01000000; -#endif -#ifdef USE_MIBLE - feature5 |= 0x02000000; -#endif -#ifdef USE_HM10 - feature5 |= 0x04000000; -#endif -#ifdef USE_LE01MR - feature5 |= 0x08000000; -#endif -#ifdef USE_AHT10 - feature5 |= 0x10000000; -#endif - - - - - - - - feature6 = 0x00000000; -# 568 "C:/shared/sonoff/Git/Tasmota/tasmota/support_features.ino" -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_flash_log.ino" -# 39 "C:/shared/sonoff/Git/Tasmota/tasmota/support_flash_log.ino" -#ifdef USE_FLOG - -class FLOG - -#define MAGIC_WORD_FL 0x464c - -{ - -struct header_t{ - uint16_t magic_word; - uint16_t padding; - uint32_t physical_start_sector:10; - uint32_t number:10; - uint32_t buf_pointer:12; - }; - -private: -void _readSector(uint8_t one_sector); -void _eraseSector(uint8_t one_sector); -void _writeSector(uint8_t one_sector); -void _clearBuffer(void); -void _searchSaves(void); -void _findFirstErasedSector(void); -void _showBuffer(void); -void _initBuffer(void); -void _saveBufferToSector(void); -header_t _saved_header; - -public: - uint32_t size; - uint32_t start; - uint32_t end; - uint16_t num_sectors; - - uint16_t first_erased_sector; - uint16_t current_sector; - - uint16_t bytes_left; - uint16_t sectors_left; - - uint8_t mode = 0; - bool found_saved_data = false; - bool ready = false; - bool running_download = false; - bool recording = false; - - union sector_t{ - uint32_t dword_buffer[FLASH_SECTOR_SIZE/4]; - uint8_t byte_buffer[FLASH_SECTOR_SIZE]; - header_t header; - } sector; - - void init(void); - void addToBuffer(uint8_t src[], uint32_t size); - void startRecording(bool append); - void stopRecording(void); - - typedef void (*CallbackNoArgs) (); - typedef void (*CallbackWithArgs) (uint8_t *_record); - - void startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter); -}; - -extern "C" uint32_t _SPIFFS_start; -extern "C" uint32_t _FS_start; - - - - -void FLOG::init(void) -{ -DEBUG_SENSOR_LOG(PSTR("FLOG: init ...")); -size = ESP.getSketchSize(); - -start = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) -end = (uint32_t)&_SPIFFS_start - 0x40200000; -#else -end = (uint32_t)&_FS_start - 0x40200000; -#endif -num_sectors = (end - start)/FLASH_SECTOR_SIZE; -DEBUG_SENSOR_LOG(PSTR("FLOG: size: 0x%lx, start: 0x%lx, end: 0x%lx, num_sectors(dec): %lu"), size, start, end, num_sectors ); -_findFirstErasedSector(); -if(first_erased_sector == 0xffff){ - _eraseSector(0); - first_erased_sector = 0; -} -_searchSaves(); -_initBuffer(); -ready = true; -} -# 142 "C:/shared/sonoff/Git/Tasmota/tasmota/support_flash_log.ino" -void FLOG::_readSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: read sector number: %u" ), one_sector); - ESP.flashRead(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); -} - - - - - -void FLOG::_eraseSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: erasing sector number: %u" ), one_sector); - ESP.flashEraseSector((start/FLASH_SECTOR_SIZE)+one_sector); -} - - - - - -void FLOG::_writeSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to sector number: %u" ), one_sector); - ESP.flashWrite(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); -} - - - - -void FLOG::_clearBuffer(){ - for (uint32_t i = sizeof(sector.header)/4; i<(sizeof(sector.dword_buffer)/4); i++){ - sector.dword_buffer[i] = 0; - } - sector.header.buf_pointer = sizeof(sector.header); - -} - - - - -void FLOG::_saveBufferToSector(){ - DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to current sector: %u" ),current_sector); - _writeSector(current_sector); - if(current_sector == num_sectors){ - current_sector = 0; - } - else{ - current_sector++; - } - _eraseSector(current_sector); - _clearBuffer(); - sector.header.number++; - DEBUG_SENSOR_LOG(PSTR("FLOG: new sector header number: %u" ),sector.header.number); -} - - - - - -void FLOG::_findFirstErasedSector(){ - for (uint32_t i = 0; i3){ - break; - } - } -} - - - - - - - -void FLOG::addToBuffer(uint8_t src[], uint32_t size){ - if(mode == 0){ - if(sector.header.number == num_sectors && !ready){ - return; - } - } - if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ - - - - memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); - sector.header.buf_pointer+=size; - - } - else{ - DEBUG_SENSOR_LOG(PSTR("FLOG: save buffer to flash sector: %u"), current_sector); - DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); - _saveBufferToSector(); - sectors_left++; - - if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ - memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); - sector.header.buf_pointer+=size; - } - } -} - - - - - - -void FLOG::startRecording(bool append){ - if(recording){ - DEBUG_SENSOR_LOG(PSTR("FLOG: already recording")); - return; - } - recording = true; - DEBUG_SENSOR_LOG(PSTR("FLOG: start recording")); - _initBuffer(); - if(!found_saved_data) { - append = false; - } - if(append){ - sector.header.number = _saved_header.number+1; - sector.header.physical_start_sector = _saved_header.physical_start_sector; - } - else{ - sector.header.physical_start_sector = (uint16_t)first_erased_sector; - found_saved_data = false; - sectors_left = 0; - } - } - - - - - -void FLOG::stopRecording(void){ - _saveBufferToSector(); - _findFirstErasedSector(); - _searchSaves(); - _initBuffer(); - recording = false; - found_saved_data = true; - } -# 381 "C:/shared/sonoff/Git/Tasmota/tasmota/support_flash_log.ino" - void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ - - _readSector(sector.header.physical_start_sector); - uint32_t next_sector = sector.header.physical_start_sector; - bytes_left = sector.header.buf_pointer - sizeof(sector.header); - DEBUG_SENSOR_LOG(PSTR("FLOG: create file for download, will process %u bytes"), bytes_left); - running_download = true; - - sendHeader(); - - while(sectors_left){ - DEBUG_SENSOR_LOG(PSTR("FLOG: next sector: %u"), next_sector); - - uint32_t k = sizeof(sector.header); - while(bytes_left){ - - uint8_t *_record_start = (uint8_t*)§or.byte_buffer[k]; - - sendRecord(_record_start); - if(k%128 == 0){ - - OsWatchLoop(); - delay(sleep); - } - k+=size; - if(bytes_left>7){ - bytes_left-=size; - } - else{ - bytes_left = 0; - DEBUG_SENSOR_LOG(PSTR("FLOG: Flog->bytes_left not dividable by 8 ??????")); - } - } - next_sector++; - if(next_sector>num_sectors){ - next_sector = 0; - } - sectors_left--; - _readSector(next_sector); - bytes_left = sector.header.buf_pointer - sizeof(sector.header); - OsWatchLoop(); - delay(sleep); - } - running_download = false; - - sendFooter(); - - _searchSaves(); - _initBuffer(); - } - - #endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" -# 23 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" -float fmodf(float x, float y) -{ - - union {float f; uint32_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>23 & 0xff; - int ey = uy.i>>23 & 0xff; - uint32_t sx = ux.i & 0x80000000; - uint32_t i; - uint32_t uxi = ux.i; - - if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) - return (x*y)/(x*y); - if (uxi<<1 <= uy.i<<1) { - if (uxi<<1 == uy.i<<1) - return 0*x; - return x; - } - - - if (!ex) { - for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1U >> 9; - uxi |= 1U << 23; - } - if (!ey) { - for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1U >> 9; - uy.i |= 1U << 23; - } - - - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - for (; uxi>>23 == 0; uxi <<= 1, ex--); - - - if (ex > 0) { - uxi -= 1U << 23; - uxi |= (uint32_t)ex << 23; - } else { - uxi >>= -ex + 1; - } - uxi |= sx; - ux.i = uxi; - return ux.f; -} - - -double FastPrecisePow(double a, double b) -{ - - - int e = abs((int)b); - union { - double d; - int x[2]; - } u = { a }; - u.x[1] = (int)((b - e) * (u.x[1] - 1072632447) + 1072632447); - u.x[0] = 0; - - - double r = 1.0; - while (e) { - if (e & 1) { - r *= a; - } - a *= a; - e >>= 1; - } - return r * u.d; -} - -float FastPrecisePowf(const float x, const float y) -{ - - return (float)FastPrecisePow(x, y); -} - -double TaylorLog(double x) -{ - - - if (x <= 0.0) { return NAN; } - double z = (x + 1) / (x - 1); - double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); - double totalValue = 0; - double powe = 1; - for (uint32_t count = 0; count < 10; count++) { - z *= step; - double y = (1 / powe) * z; - totalValue = totalValue + y; - powe = powe + 2; - } - totalValue *= 2; -# 144 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" - return totalValue; -} -# 154 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" -inline float sinf(float x) { return sin_52(x); } -inline float cosf(float x) { return cos_52(x); } -inline float tanf(float x) { return tan_56(x); } -inline float atanf(float x) { return atan_66(x); } -inline float asinf(float x) { return asinf1(x); } -inline float acosf(float x) { return acosf1(x); } -inline float sqrtf(float x) { return sqrt1(x); } -inline float powf(float x, float y) { return FastPrecisePow(x, y); } - - -double const f_pi = 3.1415926535897932384626433; -double const f_twopi = 2.0 * f_pi; -double const f_two_over_pi = 2.0 / f_pi; -double const f_halfpi = f_pi / 2.0; -double const f_threehalfpi = 3.0 * f_pi / 2.0; -double const f_four_over_pi = 4.0 / f_pi; -double const f_qtrpi = f_pi / 4.0; -double const f_sixthpi = f_pi / 6.0; -double const f_tansixthpi = tan(f_sixthpi); -double const f_twelfthpi = f_pi / 12.0; -double const f_tantwelfthpi = tan(f_twelfthpi); -float const f_180pi = 180 / f_pi; -# 194 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" -float cos_52s(float x) -{ - const float c1 = 0.9999932946; - const float c2 = -0.4999124376; - const float c3 = 0.0414877472; - const float c4 = -0.0012712095; - - float x2 = x * x; - return (c1 + x2 * (c2 + x2 * (c3 + c4 * x2))); -} - - - - - - -float cos_52(float x) -{ - x = fmodf(x, f_twopi); - if (x < 0) { x = -x; } - int quad = int(x * (float)f_two_over_pi); - switch (quad) { - case 0: return cos_52s(x); - case 1: return -cos_52s((float)f_pi - x); - case 2: return -cos_52s(x-(float)f_pi); - case 3: return cos_52s((float)f_twopi - x); - } -} - - - - -float sin_52(float x) -{ - return cos_52((float)f_halfpi - x); -} -# 247 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" -float tan_56s(float x) -{ - const float c1 = -3.16783027; - const float c2 = 0.134516124; - const float c3 = -4.033321984; - - float x2 = x * x; - return (x * (c1 + c2 * x2) / (c3 + x2)); -} -# 267 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" -float tan_56(float x) -{ - x = fmodf(x, (float)f_twopi); - int octant = int(x * (float)f_four_over_pi); - switch (octant){ - case 0: return tan_56s(x * (float)f_four_over_pi); - case 1: return 1.0f / tan_56s(((float)f_halfpi - x) * (float)f_four_over_pi); - case 2: return -1.0f / tan_56s((x-(float)f_halfpi) * (float)f_four_over_pi); - case 3: return - tan_56s(((float)f_pi - x) * (float)f_four_over_pi); - case 4: return tan_56s((x-(float)f_pi) * (float)f_four_over_pi); - case 5: return 1.0f / tan_56s(((float)f_threehalfpi - x) * (float)f_four_over_pi); - case 6: return -1.0f / tan_56s((x-(float)f_threehalfpi) * (float)f_four_over_pi); - case 7: return - tan_56s(((float)f_twopi - x) * (float)f_four_over_pi); - } -} -# 296 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" -float atan_66s(float x) -{ - const float c1 = 1.6867629106; - const float c2 = 0.4378497304; - const float c3 = 1.6867633134; - - float x2 = x * x; - return (x * (c1 + x2 * c2) / (c3 + x2)); -} - - - - - -float atan_66(float x) -{ - float y; - bool complement= false; - bool region= false; - bool sign= false; - - if (x < 0) { - x = -x; - sign = true; - } - if (x > 1.0) { - x = 1.0 / x; - complement = true; - } - if (x > (float)f_tantwelfthpi) { - x = (x - (float)f_tansixthpi) / (1 + (float)f_tansixthpi * x); - region = true; - } - - y = atan_66s(x); - if (region) { y += (float)f_sixthpi; } - if (complement) { y = (float)f_halfpi-y; } - if (sign) { y = -y; } - return (y); -} - -float asinf1(float x) -{ - float d = 1.0f - x * x; - if (d < 0.0f) { return NAN; } - return 2 * atan_66(x / (1 + sqrt1(d))); -} - -float acosf1(float x) -{ - float d = 1.0f - x * x; - if (d < 0.0f) { return NAN; } - float y = asinf1(sqrt1(d)); - if (x >= 0.0f) { - return y; - } else { - return (float)f_pi - y; - } -} - - -float sqrt1(const float x) -{ - union { - int i; - float x; - } u; - u.x = x; - u.i = (1 << 29) + (u.i >> 1) - (1 << 22); - - - - - u.x = u.x + x / u.x; - u.x = 0.25f * u.x + x / u.x; - - return u.x; -} -# 387 "C:/shared/sonoff/Git/Tasmota/tasmota/support_float.ino" -uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, - uint16_t ito_min, uint16_t ito_max) { - - if (ifrom_min >= ifrom_max) { - if (ito_min > ito_max) { - return ito_max; - } else { - return ito_min; - } - } - - uint32_t num = inum; - uint32_t from_min = ifrom_min; - uint32_t from_max = ifrom_max; - uint32_t to_min = ito_min; - uint32_t to_max = ito_max; - - - num = (num > from_max ? from_max : (num < from_min ? from_min : num)); - - - if (to_min > to_max) { - - num = (from_max - num) + from_min; - to_min = ito_max; - to_max = ito_min; - } - - uint32_t numerator = (num - from_min) * (to_max - to_min); - uint32_t result; - if (numerator >= 0x80000000L) { - - result = numerator / (from_max - from_min) + to_min; - } else { - result = (((numerator * 2) / (from_max - from_min)) + 1) / 2 + to_min; - } - return (uint32_t) (result > to_max ? to_max : (result < to_min ? to_min : result)); -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_legacy_cores.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_legacy_cores.ino" -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - - - - - -void* memchr(const void* ptr, int value, size_t num) -{ - unsigned char *p = (unsigned char*)ptr; - while (num--) { - if (*p != (unsigned char)value) { - p++; - } else { - return p; - } - } - return 0; -} - - - -size_t strcspn(const char *str1, const char *str2) -{ - size_t ret = 0; - while (*str1) { - if (strchr(str2, *str1)) { - return ret; - } else { - str1++; - ret++; - } - } - return ret; -} - - - -char* strpbrk(const char *s1, const char *s2) -{ - while(*s1) { - if (strchr(s2, *s1++)) { - return (char*)--s1; - } - } - return 0; -} - - - -#ifndef __LONG_LONG_MAX__ -#define __LONG_LONG_MAX__ 9223372036854775807LL -#endif -#ifndef ULLONG_MAX -#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) -#endif - -unsigned long long strtoull(const char *__restrict nptr, char **__restrict endptr, int base) -{ - const char *s = nptr; - char c; - do { c = *s++; } while (isspace((unsigned char)c)); - - int neg = 0; - if (c == '-') { - neg = 1; - c = *s++; - } else { - if (c == '+') { - c = *s++; - } - } - - if ((base == 0 || base == 16) && (c == '0') && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) { base = (c == '0') ? 8 : 10; } - - unsigned long long acc = 0; - int any = 0; - if (base > 1 && base < 37) { - unsigned long long cutoff = ULLONG_MAX / base; - int cutlim = ULLONG_MAX % base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - - if (c >= base) - break; - - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULLONG_MAX; - } - else if (any && neg) { - acc = -acc; - } - } - - if (endptr != nullptr) { *endptr = (char *)(any ? s - 1 : nptr); } - - return acc; -} - -#endif - - - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) - - - - - -void* memmove_P(void *dest, const void *src, size_t n) -{ - if (src > (void*)0x40000000) { - return memcpy_P(dest, src, n); - } else { - return memmove(dest, src, n); - } -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_rotary.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_rotary.ino" -#ifdef USE_LIGHT - -#ifdef ROTARY_V1 - - - - -struct ROTARY { - unsigned long debounce = 0; - uint8_t present = 0; - uint8_t state = 0; - uint8_t position = 128; - uint8_t last_position = 128; - uint8_t interrupts_in_use_count = 0; - uint8_t changed = 0; -} Rotary; - - - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void update_rotary(void) ICACHE_RAM_ATTR; -#endif - -void update_rotary(void) -{ - if (MI_DESK_LAMP == my_module_type) { - if (LightPowerIRAM()) { - - - - - uint8_t s = Rotary.state & 3; - if (digitalRead(pin[GPIO_ROT1A])) { s |= 4; } - if (digitalRead(pin[GPIO_ROT1B])) { s |= 8; } - switch (s) { - case 0: case 5: case 10: case 15: - break; - case 1: case 7: case 8: case 14: - Rotary.position++; break; - case 2: case 4: case 11: case 13: - Rotary.position--; break; - case 3: case 12: - Rotary.position = Rotary.position + 2; break; - default: - Rotary.position = Rotary.position - 2; break; - } - Rotary.state = (s >> 2); - } - } -} - -bool RotaryButtonPressed(void) -{ - if ((MI_DESK_LAMP == my_module_type) && (Rotary.changed) && LightPower()) { - Rotary.changed = 0; - return true; - } - return false; -} - -void RotaryInit(void) -{ - Rotary.present = 0; - if ((pin[GPIO_ROT1A] < 99) && (pin[GPIO_ROT1B] < 99)) { - Rotary.present++; - pinMode(pin[GPIO_ROT1A], INPUT_PULLUP); - pinMode(pin[GPIO_ROT1B], INPUT_PULLUP); - - - - - if ((pin[GPIO_ROT1A] < 6) || (pin[GPIO_ROT1A] > 11)) { - attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1A]), update_rotary, CHANGE); - Rotary.interrupts_in_use_count++; - } - if ((pin[GPIO_ROT1B] < 6) || (pin[GPIO_ROT1B] > 11)) { - attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1B]), update_rotary, CHANGE); - Rotary.interrupts_in_use_count++; - } - } -} - - - - - -void RotaryHandler(void) -{ - if (Rotary.interrupts_in_use_count < 2) { - noInterrupts(); - update_rotary(); - } else { - noInterrupts(); - } - if (Rotary.last_position != Rotary.position) { - if (MI_DESK_LAMP == my_module_type) { - if (Button.hold_timer[0]) { - Rotary.changed = 1; - - int16_t t = LightGetColorTemp(); - t = t + (Rotary.position - Rotary.last_position); - if (t < 153) { - t = 153; - } - if (t > 500) { - t = 500; - } - DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_COLORTEMPERATURE " %d"), Rotary.position - Rotary.last_position); - LightSetColorTemp((uint16_t)t); - } else { - int8_t d = Settings.light_dimmer; - d = d + (Rotary.position - Rotary.last_position); - if (d < 1) { - d = 1; - } - if (d > 100) { - d = 100; - } - DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_DIMMER " %d"), Rotary.position - Rotary.last_position); - - LightSetDimmer((uint8_t)d); - Settings.light_dimmer = d; - } - } - Rotary.last_position = 128; - Rotary.position = 128; - } - interrupts(); -} - -void RotaryLoop(void) -{ - if (Rotary.present) { - if (TimeReached(Rotary.debounce)) { - SetNextTimeInterval(Rotary.debounce, Settings.button_debounce); - RotaryHandler(); - } - } -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_rtc.ino" -# 25 "C:/shared/sonoff/Git/Tasmota/tasmota/support_rtc.ino" -const uint32_t SECS_PER_MIN = 60UL; -const uint32_t SECS_PER_HOUR = 3600UL; -const uint32_t SECS_PER_DAY = SECS_PER_HOUR * 24UL; -const uint32_t MINS_PER_HOUR = 60UL; - -#define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) - -extern "C" { -#include "sntp.h" -} -#include - -Ticker TickerRtc; - -static const uint8_t kDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -static const char kMonthNamesEnglish[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; - -struct RTC { - uint32_t utc_time = 0; - uint32_t local_time = 0; - uint32_t daylight_saving_time = 0; - uint32_t standard_time = 0; - uint32_t ntp_time = 0; - uint32_t midnight = 0; - uint32_t restart_time = 0; - int32_t drift_time = 0; - int32_t time_timezone = 0; - uint8_t ntp_sync_minute = 0; - bool midnight_now = false; - bool user_time_entry = false; -} Rtc; - -uint32_t UtcTime(void) -{ - return Rtc.utc_time; -} - -uint32_t LocalTime(void) -{ - return Rtc.local_time; -} - -int32_t DriftTime(void) -{ - return Rtc.drift_time; -} - -uint32_t Midnight(void) -{ - return Rtc.midnight; -} - -bool MidnightNow(void) -{ - if (Rtc.midnight_now) { - Rtc.midnight_now = false; - return true; - } - return false; -} - -bool IsDst(void) -{ - if (Rtc.time_timezone == Settings.toffset[1]) { - return true; - } - return false; -} - -String GetBuildDateAndTime(void) -{ - - char bdt[21]; - char *p; - char mdate[] = __DATE__; - char *smonth = mdate; - int day = 0; - int year = 0; - - - uint8_t i = 0; - for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(nullptr, " ", &p)) { - switch (i++) { - case 0: - smonth = str; - break; - case 1: - day = atoi(str); - break; - case 2: - year = atoi(str); - } - } - int month = (strstr(kMonthNamesEnglish, smonth) -kMonthNamesEnglish) /3 +1; - snprintf_P(bdt, sizeof(bdt), PSTR("%d" D_YEAR_MONTH_SEPARATOR "%02d" D_MONTH_DAY_SEPARATOR "%02d" D_DATE_TIME_SEPARATOR "%s"), year, month, day, __TIME__); - return String(bdt); -} - -String GetMinuteTime(uint32_t minutes) -{ - char tm[6]; - snprintf_P(tm, sizeof(tm), PSTR("%02d:%02d"), minutes / 60, minutes % 60); - - return String(tm); -} - -String GetTimeZone(void) -{ - char tz[7]; - snprintf_P(tz, sizeof(tz), PSTR("%+03d:%02d"), Rtc.time_timezone / 60, abs(Rtc.time_timezone % 60)); - - return String(tz); -} - -String GetDuration(uint32_t time) -{ - char dt[16]; - - TIME_T ut; - BreakTime(time, ut); - - - - - - - snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second); - - return String(dt); -} - -String GetDT(uint32_t time) -{ - - - char dt[20]; - TIME_T tmpTime; - - BreakTime(time, tmpTime); - snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), - tmpTime.year +1970, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); - - return String(dt); -} -# 181 "C:/shared/sonoff/Git/Tasmota/tasmota/support_rtc.ino" -String GetDateAndTime(uint8_t time_type) -{ - - uint32_t time = Rtc.local_time; - - switch (time_type) { - case DT_BOOTCOUNT: - time = Settings.bootcount_reset_time; - break; - case DT_ENERGY: - time = Settings.energy_kWhtotal_time; - break; - case DT_UTC: - time = Rtc.utc_time; - break; - case DT_RESTART: - if (Rtc.restart_time == 0) { - return ""; - } - time = Rtc.restart_time; - break; - } - String dt = GetDT(time); - if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { - dt += GetTimeZone(); - } - return dt; -} - -String GetTime(int type) -{ - - - - - char stime[25]; - - uint32_t time = Rtc.utc_time; - if (1 == type) time = Rtc.local_time; - if (2 == type) time = Rtc.daylight_saving_time; - if (3 == type) time = Rtc.standard_time; - snprintf_P(stime, sizeof(stime), sntp_get_real_time(time)); - - return String(stime); -} - -uint32_t UpTime(void) -{ - if (Rtc.restart_time) { - return Rtc.utc_time - Rtc.restart_time; - } else { - return uptime; - } -} - -uint32_t MinutesUptime(void) -{ - return (UpTime() / 60); -} - -String GetUptime(void) -{ - return GetDuration(UpTime()); -} - -uint32_t MinutesPastMidnight(void) -{ - uint32_t minutes = 0; - - if (RtcTime.valid) { - minutes = (RtcTime.hour *60) + RtcTime.minute; - } - return minutes; -} - -void BreakTime(uint32_t time_input, TIME_T &tm) -{ - - - - - uint8_t year; - uint8_t month; - uint8_t month_length; - uint32_t time; - unsigned long days; - - time = time_input; - tm.second = time % 60; - time /= 60; - tm.minute = time % 60; - time /= 60; - tm.hour = time % 24; - time /= 24; - tm.days = time; - tm.day_of_week = ((time + 4) % 7) + 1; - - year = 0; - days = 0; - while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { - year++; - } - tm.year = year; - - days -= LEAP_YEAR(year) ? 366 : 365; - time -= days; - tm.day_of_year = time; - - for (month = 0; month < 12; month++) { - if (1 == month) { - if (LEAP_YEAR(year)) { - month_length = 29; - } else { - month_length = 28; - } - } else { - month_length = kDaysInMonth[month]; - } - - if (time >= month_length) { - time -= month_length; - } else { - break; - } - } - strlcpy(tm.name_of_month, kMonthNames + (month *3), 4); - tm.month = month + 1; - tm.day_of_month = time + 1; - tm.valid = (time_input > START_VALID_TIME); -} - -uint32_t MakeTime(TIME_T &tm) -{ - - - - int i; - uint32_t seconds; - - - seconds = tm.year * (SECS_PER_DAY * 365); - for (i = 0; i < tm.year; i++) { - if (LEAP_YEAR(i)) { - seconds += SECS_PER_DAY; - } - } - - - for (i = 1; i < tm.month; i++) { - if ((2 == i) && LEAP_YEAR(tm.year)) { - seconds += SECS_PER_DAY * 29; - } else { - seconds += SECS_PER_DAY * kDaysInMonth[i-1]; - } - } - seconds+= (tm.day_of_month - 1) * SECS_PER_DAY; - seconds+= tm.hour * SECS_PER_HOUR; - seconds+= tm.minute * SECS_PER_MIN; - seconds+= tm.second; - return seconds; -} - -uint32_t RuleToTime(TimeRule r, int yr) -{ - TIME_T tm; - uint32_t t; - uint8_t m; - uint8_t w; - - m = r.month; - w = r.week; - if (0 == w) { - if (++m > 12) { - m = 1; - yr++; - } - w = 1; - } - - tm.hour = r.hour; - tm.minute = 0; - tm.second = 0; - tm.day_of_month = 1; - tm.month = m; - tm.year = yr - 1970; - t = MakeTime(tm); - BreakTime(t, tm); - t += (7 * (w - 1) + (r.dow - tm.day_of_week + 7) % 7) * SECS_PER_DAY; - if (0 == r.week) { - t -= 7 * SECS_PER_DAY; - } - return t; -} - -void RtcSecond(void) -{ - TIME_T tmpTime; - - if (!Rtc.user_time_entry && !global_state.wifi_down) { - uint8_t uptime_minute = (uptime / 60) % 60; - if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) { - Rtc.ntp_sync_minute = 1; - } - uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; - if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || - (Rtc.ntp_sync_minute == uptime_minute))) || - ntp_force_sync ) ) { - Rtc.ntp_time = sntp_get_current_timestamp(); - if (Rtc.ntp_time > START_VALID_TIME) { - ntp_force_sync = false; - if (Rtc.utc_time > START_VALID_TIME) { Rtc.drift_time = Rtc.ntp_time - Rtc.utc_time; } - Rtc.utc_time = Rtc.ntp_time; - Rtc.ntp_sync_minute = 60; - if (Rtc.restart_time == 0) { - Rtc.restart_time = Rtc.utc_time - uptime; - } - BreakTime(Rtc.utc_time, tmpTime); - RtcTime.year = tmpTime.year + 1970; - Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); - Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - - - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - DriftTime(), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - - if (Rtc.local_time < START_VALID_TIME) { - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } else { - Rtc.ntp_sync_minute++; - } - } - } - - Rtc.utc_time++; - Rtc.local_time = Rtc.utc_time; - if (Rtc.local_time > START_VALID_TIME) { - int16_t timezone_minutes = Settings.timezone_minutes; - if (Settings.timezone < 0) { timezone_minutes *= -1; } - Rtc.time_timezone = (Settings.timezone * SECS_PER_HOUR) + (timezone_minutes * SECS_PER_MIN); - if (99 == Settings.timezone) { - int32_t dstoffset = Settings.toffset[1] * SECS_PER_MIN; - int32_t stdoffset = Settings.toffset[0] * SECS_PER_MIN; - if (Settings.tflag[1].hemis) { - - if ((Rtc.utc_time >= (Rtc.standard_time - dstoffset)) && (Rtc.utc_time < (Rtc.daylight_saving_time - stdoffset))) { - Rtc.time_timezone = stdoffset; - } else { - Rtc.time_timezone = dstoffset; - } - } else { - - if ((Rtc.utc_time >= (Rtc.daylight_saving_time - stdoffset)) && (Rtc.utc_time < (Rtc.standard_time - dstoffset))) { - Rtc.time_timezone = dstoffset; - } else { - Rtc.time_timezone = stdoffset; - } - } - } - Rtc.local_time += Rtc.time_timezone; - Rtc.time_timezone /= 60; - if (!Settings.energy_kWhtotal_time) { - Settings.energy_kWhtotal_time = Rtc.local_time; - } - if (Settings.bootcount_reset_time < START_VALID_TIME) { - Settings.bootcount_reset_time = Rtc.local_time; - } - } - - BreakTime(Rtc.local_time, RtcTime); - if (RtcTime.valid) { - if (!Rtc.midnight) { - Rtc.midnight = Rtc.local_time - (RtcTime.hour * 3600) - (RtcTime.minute * 60) - RtcTime.second; - } - if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { - Rtc.midnight = Rtc.local_time; - Rtc.midnight_now = true; - } - } - - RtcTime.year += 1970; -} - -void RtcSetTime(uint32_t epoch) -{ - if (epoch < START_VALID_TIME) { - Rtc.user_time_entry = false; - ntp_force_sync = true; - sntp_init(); - } else { - sntp_stop(); - Rtc.user_time_entry = true; - Rtc.utc_time = epoch -1; - } - RtcSecond(); -} - -void RtcInit(void) -{ - sntp_setservername(0, SettingsText(SET_NTPSERVER1)); - sntp_setservername(1, SettingsText(SET_NTPSERVER2)); - sntp_setservername(2, SettingsText(SET_NTPSERVER3)); - sntp_stop(); - sntp_set_timezone(0); - sntp_init(); - Rtc.utc_time = 0; - BreakTime(Rtc.utc_time, RtcTime); - TickerRtc.attach(1, RtcSecond); -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_static_buffer.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_static_buffer.ino" -typedef struct SBuffer_impl { - uint16_t size; - uint16_t len; - uint8_t buf[]; -} SBuffer_impl; - - - -typedef class SBuffer { - -protected: - SBuffer(void) { - - } - -public: - SBuffer(const size_t size) { - _buf = (SBuffer_impl*) new char[size+4]; - _buf->size = size; - _buf->len = 0; - - } - - inline size_t getSize(void) const { return _buf->size; } - inline size_t size(void) const { return _buf->size; } - inline size_t getLen(void) const { return _buf->len; } - inline size_t len(void) const { return _buf->len; } - inline uint8_t *getBuffer(void) const { return _buf->buf; } - inline uint8_t *buf(size_t i = 0) const { return &_buf->buf[i]; } - inline char *charptr(size_t i = 0) const { return (char*) &_buf->buf[i]; } - - virtual ~SBuffer(void) { - delete[] _buf; - } - - inline void setLen(const size_t len) { - uint16_t old_len = _buf->len; - _buf->len = (len <= _buf->size) ? len : _buf->size; - if (old_len < _buf->len) { - memset((void*) &_buf->buf[old_len], 0, _buf->len - old_len); - } - } - - void set8(const size_t offset, const uint8_t data) { - if (offset < _buf->len) { - _buf->buf[offset] = data; - } - } - - size_t add8(const uint8_t data) { - if (_buf->len < _buf->size) { - _buf->buf[_buf->len++] = data; - } - return _buf->len; - } - size_t add16(const uint16_t data) { - if (_buf->len < _buf->size - 1) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - } - return _buf->len; - } - size_t add32(const uint32_t data) { - if (_buf->len < _buf->size - 3) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - _buf->buf[_buf->len++] = data >> 16; - _buf->buf[_buf->len++] = data >> 24; - } - return _buf->len; - } - size_t add64(const uint64_t data) { - if (_buf->len < _buf->size - 7) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - _buf->buf[_buf->len++] = data >> 16; - _buf->buf[_buf->len++] = data >> 24; - _buf->buf[_buf->len++] = data >> 32; - _buf->buf[_buf->len++] = data >> 40; - _buf->buf[_buf->len++] = data >> 48; - _buf->buf[_buf->len++] = data >> 56; - } - return _buf->len; - } - - size_t addBuffer(const SBuffer &buf2) { - if (len() + buf2.len() <= size()) { - for (uint32_t i = 0; i < buf2.len(); i++) { - _buf->buf[_buf->len++] = buf2.buf()[i]; - } - } - return _buf->len; - } - - size_t addBuffer(const uint8_t *buf2, size_t len2) { - if (len() + len2 <= size()) { - for (uint32_t i = 0; i < len2; i++) { - _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); - } - } - return _buf->len; - } - - size_t addBuffer(const char *buf2, size_t len2) { - if (len() + len2 <= size()) { - for (uint32_t i = 0; i < len2; i++) { - _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); - } - } - return _buf->len; - } - - uint8_t get8(size_t offset) const { - if (offset < _buf->len) { - return _buf->buf[offset]; - } else { - return 0; - } - } - uint8_t read8(const size_t offset) const { - if (offset < len()) { - return _buf->buf[offset]; - } - return 0; - } - uint16_t get16(const size_t offset) const { - if (offset < len() - 1) { - return _buf->buf[offset] | (_buf->buf[offset+1] << 8); - } - return 0; - } - uint32_t get32(const size_t offset) const { - if (offset < len() - 3) { - return _buf->buf[offset] | (_buf->buf[offset+1] << 8) | - (_buf->buf[offset+2] << 16) | (_buf->buf[offset+3] << 24); - } - return 0; - } - uint64_t get64(const size_t offset) const { - if (offset < len() - 7) { - return (uint64_t)_buf->buf[offset] | ((uint64_t)_buf->buf[offset+1] << 8) | - ((uint64_t)_buf->buf[offset+2] << 16) | ((uint64_t)_buf->buf[offset+3] << 24) | - ((uint64_t)_buf->buf[offset+4] << 32) | ((uint64_t)_buf->buf[offset+5] << 40) | - ((uint64_t)_buf->buf[offset+6] << 48) | ((uint64_t)_buf->buf[offset+7] << 56); - } - return 0; - } - - - inline size_t strlen(const size_t offset) const { - return strnlen((const char*) &_buf->buf[offset], len() - offset); - } - - size_t strlen_s(const size_t offset) const { - size_t slen = this->strlen(offset); - if (slen == len() - offset) { - return 0; - } else { - return slen; - } - } - - SBuffer subBuffer(const size_t start, size_t len) const { - if (start >= _buf->len) { - len = 0; - } else if (start + len > _buf->len) { - len = _buf->len - start; - } - - SBuffer buf2(len); - memcpy(buf2.buf(), buf()+start, len); - buf2._buf->len = len; - return buf2; - } - - static SBuffer SBufferFromHex(const char *hex, size_t len) { - size_t buf_len = (len + 3) / 2; - SBuffer buf2(buf_len); - uint8_t val; - - for (; len > 1; len -= 2) { - val = asc2byte(*hex++) << 4; - val |= asc2byte(*hex++); - buf2.add8(val); - } - return buf2; - } - -protected: - - static uint8_t asc2byte(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { rVal = chr - '0'; } - else if (chr >= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; } - else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; } - return rVal; - } - - static void unHex(const char* in, uint8_t *out, size_t len) { - } - -protected: - SBuffer_impl * _buf; - -} SBuffer; - -typedef class PreAllocatedSBuffer : public SBuffer { - -public: - PreAllocatedSBuffer(const size_t size, void * buffer) { - _buf = (SBuffer_impl*) buffer; - _buf->size = size - 4; - _buf->len = 0; - } - - ~PreAllocatedSBuffer(void) { - - _buf = nullptr; - } -} PreAllocatedSBuffer; -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_statistics.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_statistics.ino" -#define USE_STATS_CODE - -#ifdef USE_STATS_CODE - - - - -String GetStatistics(void) -{ - char data[40]; - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); - return String(data); -} - -#else - -String GetStatistics(void) -{ - return String(""); -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_switch.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_switch.ino" -#define SWITCH_V2 -#ifdef SWITCH_V2 - - - - - - -const uint8_t SWITCH_PROBE_INTERVAL = 10; - -#include - -Ticker TickerSwitch; - -struct SWITCH { - unsigned long debounce = 0; - uint16_t no_pullup_mask = 0; - uint8_t state[MAX_SWITCHES] = { 0 }; - uint8_t last_state[MAX_SWITCHES]; - uint8_t hold_timer[MAX_SWITCHES] = { 0 }; - uint8_t virtual_state[MAX_SWITCHES]; - uint8_t present = 0; -} Switch; - - - -void SwitchPullupFlag(uint16 switch_bit) -{ - bitSet(Switch.no_pullup_mask, switch_bit); -} - -void SwitchSetVirtual(uint32_t index, uint8_t state) -{ - Switch.virtual_state[index] = state; -} - -uint8_t SwitchGetVirtual(uint32_t index) -{ - return Switch.virtual_state[index]; -} - -uint8_t SwitchLastState(uint32_t index) -{ - return Switch.last_state[index]; -} - -bool SwitchState(uint32_t index) -{ - uint32_t switchmode = Settings.switchmode[index]; - return ((FOLLOW_INV == switchmode) || - (PUSHBUTTON_INV == switchmode) || - (PUSHBUTTONHOLD_INV == switchmode) || - (FOLLOWMULTI_INV == switchmode) || - (PUSHHOLDMULTI_INV == switchmode) - ) ^ Switch.last_state[index]; -} - - - -void SwitchProbe(void) -{ - if (uptime < 4) { return; } - - uint8_t state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; - uint8_t force_high = (Settings.switch_debounce % 50) &1; - uint8_t force_low = (Settings.switch_debounce % 50) &2; - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if (pin[GPIO_SWT1 +i] < 99) { - - if (1 == digitalRead(pin[GPIO_SWT1 +i])) { - - if (force_high) { - if (1 == Switch.virtual_state[i]) { - Switch.state[i] = state_filter; - } - } - - if (Switch.state[i] < state_filter) { - Switch.state[i]++; - if (state_filter == Switch.state[i]) { - Switch.virtual_state[i] = 1; - } - } - } else { - - if (force_low) { - if (0 == Switch.virtual_state[i]) { - Switch.state[i] = 0; - } - } - - if (Switch.state[i] > 0) { - Switch.state[i]--; - if (0 == Switch.state[i]) { - Switch.virtual_state[i] = 0; - } - } - } - } - } - TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); -} - -void SwitchInit(void) -{ - Switch.present = 0; - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - Switch.last_state[i] = 1; - if (pin[GPIO_SWT1 +i] < 99) { - Switch.present++; - pinMode(pin[GPIO_SWT1 +i], bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); - Switch.last_state[i] = digitalRead(pin[GPIO_SWT1 +i]); - } - Switch.virtual_state[i] = Switch.last_state[i]; - } - if (Switch.present) { TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); } -} - - - - - -void SwitchHandler(uint8_t mode) -{ - if (uptime < 4) { return; } - - uint16_t loops_per_second = 1000 / Settings.switch_debounce; - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { - uint8_t button = Switch.virtual_state[i]; - uint8_t switchflag = POWER_TOGGLE +1; - - if (Switch.hold_timer[i]) { - Switch.hold_timer[i]--; - if (0 == Switch.hold_timer[i]) { - - switch (Settings.switchmode[i]) { - case TOGGLEMULTI: - switchflag = POWER_TOGGLE; - break; - case FOLLOWMULTI: - switchflag = button &1; - break; - case FOLLOWMULTI_INV: - switchflag = ~button &1; - break; - case PUSHHOLDMULTI: - if (NOT_PRESSED == button){ - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); - } - else - SendKey(KEY_SWITCH, i +1, POWER_CLEAR); - break; - case PUSHHOLDMULTI_INV: - if (PRESSED == button){ - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); - } - else - SendKey(KEY_SWITCH, i +1, POWER_CLEAR); - break; - default: - SendKey(KEY_SWITCH, i +1, POWER_HOLD); - break; - } - } - } - - - - if (button != Switch.last_state[i]) { - switch (Settings.switchmode[i]) { - case TOGGLE: - case PUSHBUTTON_TOGGLE: - switchflag = POWER_TOGGLE; - break; - case FOLLOW: - switchflag = button &1; - break; - case FOLLOW_INV: - switchflag = ~button &1; - break; - case PUSHBUTTON: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTON_INV: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTONHOLD: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTONHOLD_INV: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; - } - break; - case TOGGLEMULTI: - case FOLLOWMULTI: - case FOLLOWMULTI_INV: - if (Switch.hold_timer[i]) { - Switch.hold_timer[i] = 0; - SendKey(KEY_SWITCH, i +1, POWER_HOLD); - } else { - Switch.hold_timer[i] = loops_per_second / 2; - } - break; - case PUSHHOLDMULTI: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - if(Switch.hold_timer[i]!=0) - SendKey(KEY_SWITCH, i +1, POWER_INV); - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) - switchflag = POWER_TOGGLE; - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - break; - case PUSHHOLDMULTI_INV: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - if(Switch.hold_timer[i]!=0) - SendKey(KEY_SWITCH, i +1, POWER_INV); - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) - switchflag = POWER_TOGGLE; - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - break; - } - Switch.last_state[i] = button; - } - if (switchflag <= POWER_TOGGLE) { - if (!SendKey(KEY_SWITCH, i +1, switchflag)) { - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); - } - } - } - } -} - -void SwitchLoop(void) -{ - if (Switch.present) { - if (TimeReached(Switch.debounce)) { - SetNextTimeInterval(Switch.debounce, Settings.switch_debounce); - SwitchHandler(0); - } - } -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_tasmota.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_tasmota.ino" -const char kSleepMode[] PROGMEM = "Dynamic|Normal"; -const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; - -char* Format(char* output, const char* input, int size) -{ - char *token; - uint32_t digits = 0; - - if (strstr(input, "%") != nullptr) { - strlcpy(output, input, size); - token = strtok(output, "%"); - if (strstr(input, "%") == input) { - output[0] = '\0'; - } else { - token = strtok(nullptr, ""); - } - if (token != nullptr) { - digits = atoi(token); - if (digits) { - char tmp[size]; - if (strchr(token, 'd')) { - snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits); - snprintf_P(output, size, tmp, ESP.getChipId() & 0x1fff); - } else { - snprintf_P(tmp, size, PSTR("%s%c0%dX"), output, '%', digits); - snprintf_P(output, size, tmp, ESP.getChipId()); - } - } else { - if (strchr(token, 'd')) { - snprintf_P(output, size, PSTR("%s%d"), output, ESP.getChipId()); - digits = 8; - } - } - } - } - if (!digits) { - strlcpy(output, input, size); - } - return output; -} - -char* GetOtaUrl(char *otaurl, size_t otaurl_size) -{ - if (strstr(SettingsText(SET_OTAURL), "%04d") != nullptr) { - snprintf(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId() & 0x1fff); - } - else if (strstr(SettingsText(SET_OTAURL), "%d") != nullptr) { - snprintf_P(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId()); - } - else { - strlcpy(otaurl, SettingsText(SET_OTAURL), otaurl_size); - } - - return otaurl; -} - -char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) -{ -# 88 "C:/shared/sonoff/Git/Tasmota/tasmota/support_tasmota.ino" - char romram[CMDSZ]; - String fulltopic; - - snprintf_P(romram, sizeof(romram), subtopic); - if (fallback_topic_flag || (prefix > 3)) { - bool fallback = (prefix < 8); - prefix &= 3; - char stemp[11]; - fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); - fulltopic += F("/"); - if (fallback) { - fulltopic += mqtt_client; - fulltopic += F("_fb"); - } else { - fulltopic += topic; - } - } else { - fulltopic = SettingsText(SET_MQTT_FULLTOPIC); - if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { - fulltopic += F("/"); - fulltopic += FPSTR(MQTT_TOKEN_PREFIX); - } - for (uint32_t i = 0; i < MAX_MQTT_PREFIXES; i++) { - if (!strlen(SettingsText(SET_MQTTPREFIX1 + i))) { - char temp[TOPSZ]; - SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes)); - } - } - fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + prefix)); - - fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); - fulltopic.replace(F("%hostname%"), my_hostname); - String token_id = WiFi.macAddress(); - token_id.replace(":", ""); - fulltopic.replace(F("%id%"), token_id); - } - fulltopic.replace(F("#"), ""); - fulltopic.replace(F("//"), "/"); - if (!fulltopic.endsWith("/")) { - fulltopic += "/"; - } - snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); - return stopic; -} - -char* GetGroupTopic_P(char *stopic, const char* subtopic) -{ - - - return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(SET_MQTT_GRP_TOPIC), subtopic); -} - -char* GetFallbackTopic_P(char *stopic, const char* subtopic) -{ - return GetTopic_P(stopic, CMND +4, nullptr, subtopic); -} - -char* GetStateText(uint32_t state) -{ - if (state >= MAX_STATE_TEXT) { - state = 1; - } - return SettingsText(SET_STATE_TXT1 + state); -} - - - -void SetLatchingRelay(power_t lpower, uint32_t state) -{ - - - - - - if (state && !latching_relay_pulse) { - latching_power = lpower; - latching_relay_pulse = 2; - } - - for (uint32_t i = 0; i < devices_present; i++) { - uint32_t port = (i << 1) + ((latching_power >> i) &1); - DigitalWrite(GPIO_REL1 +port, bitRead(rel_inverted, port) ? !state : state); - } -} - -void SetDevicePower(power_t rpower, uint32_t source) -{ - ShowSource(source); - last_source = source; - - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - power = (1 << devices_present) -1; - rpower = power; - } - - if (Settings.flag.interlock) { - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - power_t mask = 1; - uint32_t count = 0; - for (uint32_t j = 0; j < devices_present; j++) { - if ((Settings.interlock[i] & mask) && (rpower & mask)) { - count++; - } - mask <<= 1; - } - if (count > 1) { - mask = ~Settings.interlock[i]; - power &= mask; - rpower &= mask; - } - } - } - - if (rpower) { - last_power = rpower; - } - - XdrvMailbox.index = rpower; - XdrvCall(FUNC_SET_POWER); - - XdrvMailbox.index = rpower; - XdrvMailbox.payload = source; - if (XdrvCall(FUNC_SET_DEVICE_POWER)) { - - } - else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - Serial.write(0xA0); - Serial.write(0x04); - Serial.write(rpower &0xFF); - Serial.write(0xA1); - Serial.write('\n'); - Serial.flush(); - } - else if (EXS_RELAY == my_module_type) { - SetLatchingRelay(rpower, 1); - } - else { - for (uint32_t i = 0; i < devices_present; i++) { - power_t state = rpower &1; - if (i < MAX_RELAYS) { - DigitalWrite(GPIO_REL1 +i, bitRead(rel_inverted, i) ? !state : state); - } - rpower >>= 1; - } - } -} - -void RestorePower(bool publish_power, uint32_t source) -{ - if (power != last_power) { - power = last_power; - SetDevicePower(power, source); - if (publish_power) { - MqttPublishAllPowerState(); - } - } -} - -void SetAllPower(uint32_t state, uint32_t source) -{ -# 256 "C:/shared/sonoff/Git/Tasmota/tasmota/support_tasmota.ino" - bool publish_power = true; - if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { - state &= 3; - publish_power = false; - } - if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) { - power_t all_on = (1 << devices_present) -1; - switch (state) { - case POWER_OFF: - power = 0; - break; - case POWER_ON: - power = all_on; - break; - case POWER_TOGGLE: - power ^= all_on; - } - SetDevicePower(power, source); - } - if (publish_power) { - MqttPublishAllPowerState(); - } -} - -void SetPowerOnState(void) -{ - if (MOTOR == my_module_type) { - Settings.poweronstate = POWER_ALL_ON; - } - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - SetDevicePower(1, SRC_RESTART); - } else { - if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == REASON_EXT_SYS_RST)) { - switch (Settings.poweronstate) { - case POWER_ALL_OFF: - case POWER_ALL_OFF_PULSETIME_ON: - power = 0; - SetDevicePower(power, SRC_RESTART); - break; - case POWER_ALL_ON: - power = (1 << devices_present) -1; - SetDevicePower(power, SRC_RESTART); - break; - case POWER_ALL_SAVED_TOGGLE: - power = (Settings.power & ((1 << devices_present) -1)) ^ POWER_MASK; - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - break; - case POWER_ALL_SAVED: - power = Settings.power & ((1 << devices_present) -1); - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - break; - } - } else { - power = Settings.power & ((1 << devices_present) -1); - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - } - } - - - for (uint32_t i = 0; i < devices_present; i++) { - if (!Settings.flag3.no_power_feedback) { - if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { - bitWrite(power, i, digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i)); - } - } - if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate))) { - SetPulseTimer(i, Settings.pulse_timer[i]); - } - } - blink_powersave = power; -} - -void SetLedPowerIdx(uint32_t led, uint32_t state) -{ - if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { - if (pin[GPIO_LED2] < 99) { - led = 1; - } - } - if (pin[GPIO_LED1 + led] < 99) { - uint32_t mask = 1 << led; - if (state) { - state = 1; - led_power |= mask; - } else { - led_power &= (0xFF ^ mask); - } - DigitalWrite(GPIO_LED1 + led, bitRead(led_inverted, led) ? !state : state); - } -#ifdef USE_BUZZER - if (led == 0) { - BuzzerSetStateToLed(state); - } -#endif -} - -void SetLedPower(uint32_t state) -{ - if (99 == pin[GPIO_LEDLNK]) { - SetLedPowerIdx(0, state); - } else { - power_t mask = 1; - for (uint32_t i = 0; i < leds_present; i++) { - bool tstate = (power & mask); - SetLedPowerIdx(i, tstate); - mask <<= 1; - } - } -} - -void SetLedPowerAll(uint32_t state) -{ - for (uint32_t i = 0; i < leds_present; i++) { - SetLedPowerIdx(i, state); - } -} - -void SetLedLink(uint32_t state) -{ - uint32_t led_pin = pin[GPIO_LEDLNK]; - uint32_t led_inv = ledlnk_inverted; - if (99 == led_pin) { - led_pin = pin[GPIO_LED1]; - led_inv = bitRead(led_inverted, 0); - } - if (led_pin < 99) { - if (state) { state = 1; } - digitalWrite(led_pin, (led_inv) ? !state : state); - } -#ifdef USE_BUZZER - BuzzerSetStateToLed(state); -#endif -} - -void SetPulseTimer(uint32_t index, uint32_t time) -{ - pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; -} - -uint32_t GetPulseTimer(uint32_t index) -{ - long time = TimePassedSince(pulse_timer[index]); - if (time < 0) { - time *= -1; - return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; - } - return 0; -} - - - -bool SendKey(uint32_t key, uint32_t device, uint32_t state) -{ -# 423 "C:/shared/sonoff/Git/Tasmota/tasmota/support_tasmota.ino" - char stopic[TOPSZ]; - char scommand[CMDSZ]; - char key_topic[TOPSZ]; - bool result = false; - - char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_BUTTON_TOPIC); - Format(key_topic, tmp, sizeof(key_topic)); - if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { - if (!key && (device > devices_present)) { - device = 1; - } - GetTopic_P(stopic, CMND, key_topic, - GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); - if (CLEAR_RETAIN == state) { - mqtt_data[0] = '\0'; - } else { - if ((Settings.flag3.button_switch_force_local || - !strcmp(mqtt_topic, key_topic) || - !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) && - (POWER_TOGGLE == state)) { - state = ~(power >> (device -1)) &1; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); - } -#ifdef USE_DOMOTICZ - if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { -#endif - MqttPublish(stopic, ((key) ? Settings.flag.mqtt_switch_retain - : Settings.flag.mqtt_button_retain) && - (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); -#ifdef USE_DOMOTICZ - } -#endif - result = !Settings.flag3.button_switch_force_local; - } else { - Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); - result = XdrvRulesProcess(); - } - int32_t payload_save = XdrvMailbox.payload; - XdrvMailbox.payload = key << 16 | state << 8 | device; - XdrvCall(FUNC_ANY_KEY); - XdrvMailbox.payload = payload_save; - return result; -} - -void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) -{ -# 483 "C:/shared/sonoff/Git/Tasmota/tasmota/support_tasmota.ino" -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - blink_mask &= 1; - Settings.flag.interlock = 0; - Settings.pulse_timer[1] = 0; - Settings.pulse_timer[2] = 0; - Settings.pulse_timer[3] = 0; - } -#endif - - bool publish_power = true; - if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { - state &= 3; - publish_power = false; - } - - if ((device < 1) || (device > devices_present)) { - device = 1; - } - active_device = device; - - if (device <= MAX_PULSETIMERS) { - SetPulseTimer(device -1, 0); - } - power_t mask = 1 << (device -1); - if (state <= POWER_TOGGLE) { - if ((blink_mask & mask)) { - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(device); - } - - if (Settings.flag.interlock && - !interlock_mutex && - ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(power & mask))) - ) { - interlock_mutex = true; - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - if (Settings.interlock[i] & mask) { - for (uint32_t j = 0; j < devices_present; j++) { - power_t imask = 1 << j; - if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { - ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); - delay(50); - } - } - break; - } - } - interlock_mutex = false; - } - - switch (state) { - case POWER_OFF: { - power &= (POWER_MASK ^ mask); - break; } - case POWER_ON: - power |= mask; - break; - case POWER_TOGGLE: - power ^= mask; - } - SetDevicePower(power, source); -#ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(device); -#endif -#ifdef USE_KNX - KnxUpdatePowerState(device, power); -#endif - if (publish_power && Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - if (device <= MAX_PULSETIMERS) { - SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); - } - } - else if (POWER_BLINK == state) { - if (!(blink_mask & mask)) { - blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); - blink_power = (power >> (device -1))&1; - } - blink_timer = millis() + 100; - blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; - blink_mask |= mask; - MqttPublishPowerBlinkState(device); - return; - } - else if (POWER_BLINK_STOP == state) { - bool flag = (blink_mask & mask); - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(device); - if (flag) { - ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); - } - return; - } - if (publish_power) { - MqttPublishPowerState(device); - } -} - -void StopAllPowerBlink(void) -{ - power_t mask; - - for (uint32_t i = 1; i <= devices_present; i++) { - mask = 1 << (i -1); - if (blink_mask & mask) { - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(i); - ExecuteCommandPower(i, (blink_powersave >> (i -1))&1, SRC_IGNORE); - } - } -} - -void MqttShowPWMState(void) -{ - ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); - bool first = true; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 + i] < 99) { - ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); - first = false; - } - } - ResponseJsonEnd(); -} - -void MqttShowState(void) -{ - char stemp1[TOPSZ]; - - ResponseAppendTime(); - ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); - -#ifdef USE_ADC_VCC - dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); - ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); -#endif - - ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"), - ESP.getFreeHeap()/1024, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), - sleep, loop_load_avg, MqttConnectCount()); - - for (uint32_t i = 1; i <= devices_present; i++) { -#ifdef USE_LIGHT - if ((LightDevice()) && (i >= LightDevice())) { - if (i == LightDevice()) { LightState(1); } - } else { -#endif - ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), - GetStateText(bitRead(power, i-1))); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); - break; - } -#endif -#ifdef USE_LIGHT - } -#endif - } - - if (pwm_present) { - ResponseAppend_P(PSTR(",")); - MqttShowPWMState(); - } - - ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(), - WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str()); -} - -void MqttPublishTeleState(void) -{ - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); -#if defined(USE_RULES) || defined(USE_SCRIPT) - RulesTeleperiod(); -#endif -} - -bool MqttShowSensor(void) -{ - ResponseAppendTime(); - - int json_data_start = strlen(mqtt_data); - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { -#ifdef USE_TM1638 - if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { -#else - if (pin[GPIO_SWT1 +i] < 99) { -#endif - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(SwitchState(i))); - } - } - XsnsCall(FUNC_JSON_APPEND); - XdrvCall(FUNC_JSON_APPEND); - - bool json_data_available = (strlen(mqtt_data) - json_data_start); - if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { - ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); - } - if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); - } - ResponseJsonEnd(); - - if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } - return json_data_available; -} - -void MqttPublishSensor(void) -{ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishTeleSensor(); - } -} -# 710 "C:/shared/sonoff/Git/Tasmota/tasmota/support_tasmota.ino" -void PerformEverySecond(void) -{ - uptime++; - - if (POWER_CYCLE_TIME == uptime) { - UpdateQuickPowerCycle(false); - } - - if (BOOT_LOOP_TIME == uptime) { - RtcRebootReset(); - -#ifdef USE_DEEPSLEEP - if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { -#endif - Settings.bootcount++; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); -#ifdef USE_DEEPSLEEP - } -#endif - } - - if (mqtt_cmnd_blocked_reset) { - mqtt_cmnd_blocked_reset--; - if (!mqtt_cmnd_blocked_reset) { - mqtt_cmnd_blocked = 0; - } - } - - if (seriallog_timer) { - seriallog_timer--; - if (!seriallog_timer) { - if (seriallog_level) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); - } - seriallog_level = 0; - } - } - - if (syslog_timer) { - syslog_timer--; - if (!syslog_timer) { - syslog_level = Settings.syslog_level; - if (Settings.syslog_level) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); - } - } - } - - ResetGlobalValues(); - - if (Settings.tele_period) { - if (tele_period >= 9999) { - if (!global_state.wifi_down) { - tele_period = 0; - } - } else { - tele_period++; - if (tele_period >= Settings.tele_period) { - tele_period = 0; - - MqttPublishTeleState(); - - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#if defined(USE_RULES) || defined(USE_SCRIPT) - RulesTeleperiod(); -#endif - } - - XdrvCall(FUNC_AFTER_TELEPERIOD); - } - } - } -} - - - - - -void Every100mSeconds(void) -{ - - power_t power_now; - - if (prepped_loglevel) { - AddLog(prepped_loglevel); - prepped_loglevel = 0; - } - - if (latching_relay_pulse) { - latching_relay_pulse--; - if (!latching_relay_pulse) SetLatchingRelay(0, 0); - } - - for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if (pulse_timer[i] != 0L) { - if (TimeReached(pulse_timer[i])) { - pulse_timer[i] = 0L; - ExecuteCommandPower(i +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER); - } - } - } - - if (blink_mask) { - if (TimeReached(blink_timer)) { - SetNextTimeInterval(blink_timer, 100 * Settings.blinktime); - blink_counter--; - if (!blink_counter) { - StopAllPowerBlink(); - } else { - blink_power ^= 1; - power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); - SetDevicePower(power_now, SRC_IGNORE); - } - } - } -} - - - - - -void Every250mSeconds(void) -{ - - - uint32_t blinkinterval = 1; - - state_250mS++; - state_250mS &= 0x3; - - if (!Settings.flag.global_state) { - if (global_state.data) { - if (global_state.mqtt_down) { blinkinterval = 7; } - if (global_state.wifi_down) { blinkinterval = 3; } - blinks = 201; - } - } - if (blinks || restart_flag || ota_state_flag) { - if (restart_flag || ota_state_flag) { - blinkstate = true; - } else { - blinkspeed--; - if (!blinkspeed) { - blinkspeed = blinkinterval; - blinkstate ^= 1; - } - } - if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { - SetLedLink(blinkstate); - } - if (!blinkstate) { - blinks--; - if (200 == blinks) blinks = 0; - } - } - if (Settings.ledstate &1 && (pin[GPIO_LEDLNK] < 99 || !(blinks || restart_flag || ota_state_flag)) ) { - bool tstate = power & Settings.ledmask; - if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) { - tstate = (!power) ? 1 : 0; - } - SetLedPower(tstate); - } - - - - - - switch (state_250mS) { - case 0: - if (ota_state_flag && BACKLOG_EMPTY) { - ota_state_flag--; - if (2 == ota_state_flag) { - RtcSettings.ota_loader = 0; - ota_retry_counter = OTA_ATTEMPTS; - ESPhttpUpdate.rebootOnUpdate(false); - SettingsSave(1); - } - if (ota_state_flag <= 0) { -#ifdef USE_WEBSERVER - if (Settings.webserver) StopWebserver(); -#endif -#ifdef USE_ARILUX_RF - AriluxRfDisable(); -#endif - ota_state_flag = 92; - ota_result = 0; - ota_retry_counter--; - if (ota_retry_counter) { - strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); -#ifndef FIRMWARE_MINIMAL - if (RtcSettings.ota_loader) { -# 915 "C:/shared/sonoff/Git/Tasmota/tasmota/support_tasmota.ino" - char *bch = strrchr(mqtt_data, '/'); - if (bch == nullptr) { bch = mqtt_data; } - - char *ech = strrchr(bch, '.'); - if ((ech != nullptr) && (0 == strncasecmp_P(ech, PSTR(".GZ"), 3))) { - char *fch = ech; - *fch = '\0'; - ech = strrchr(bch, '.'); - *fch = '.'; - } - if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } - char ota_url_type[strlen(ech) +1]; - strncpy(ota_url_type, ech, sizeof(ota_url_type)); - - char *pch = strrchr(bch, '-'); - if (pch == nullptr) { pch = ech; } - *pch = '\0'; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); - } -#endif - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); -#else - - WiFiClient OTAclient; - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); -#endif - if (!ota_result) { -#ifndef FIRMWARE_MINIMAL - int ota_error = ESPhttpUpdate.getLastError(); - DEBUG_CORE_LOG(PSTR("OTA: Error %d"), ota_error); - if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) { - RtcSettings.ota_loader = 1; - } -#endif - ota_state_flag = 2; - } - } - } - if (90 == ota_state_flag) { - ota_state_flag = 0; - Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\"")); - if (ota_result) { - - if (!VersionCompatible()) { - ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14)); - } else { - ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); - restart_flag = 2; - } - } else { - ResponseAppend_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); - } - ResponseAppend_P(PSTR("\"}")); - - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); - } - } - break; - case 1: - if (MidnightNow()) { - XsnsCall(FUNC_SAVE_AT_MIDNIGHT); - } - if (save_data_counter && BACKLOG_EMPTY) { - save_data_counter--; - if (save_data_counter <= 0) { - if (Settings.flag.save_state) { - power_t mask = POWER_MASK; - for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { - mask &= ~(1 << i); - } - } - if (!((Settings.power &mask) == (power &mask))) { - Settings.power = power; - } - } else { - Settings.power = 0; - } - SettingsSave(0); - save_data_counter = Settings.save_data; - } - } - if (restart_flag && BACKLOG_EMPTY) { - if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { - - char storage_ssid1[strlen(SettingsText(SET_STASSID1)) +1]; - strncpy(storage_ssid1, SettingsText(SET_STASSID1), sizeof(storage_ssid1)); - char storage_ssid2[strlen(SettingsText(SET_STASSID2)) +1]; - strncpy(storage_ssid2, SettingsText(SET_STASSID2), sizeof(storage_ssid2)); - char storage_pass1[strlen(SettingsText(SET_STAPWD1)) +1]; - strncpy(storage_pass1, SettingsText(SET_STAPWD1), sizeof(storage_pass1)); - char storage_pass2[strlen(SettingsText(SET_STAPWD2)) +1]; - strncpy(storage_pass2, SettingsText(SET_STAPWD2), sizeof(storage_pass2)); - - char storage_mqtthost[strlen(SettingsText(SET_MQTT_HOST)) +1]; - strncpy(storage_mqtthost, SettingsText(SET_MQTT_HOST), sizeof(storage_mqtthost)); - char storage_mqttuser[strlen(SettingsText(SET_MQTT_USER)) +1]; - strncpy(storage_mqttuser, SettingsText(SET_MQTT_USER), sizeof(storage_mqttuser)); - char storage_mqttpwd[strlen(SettingsText(SET_MQTT_PWD)) +1]; - strncpy(storage_mqttpwd, SettingsText(SET_MQTT_PWD), sizeof(storage_mqttpwd)); - char storage_mqtttopic[strlen(SettingsText(SET_MQTT_TOPIC)) +1]; - strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic)); - uint16_t mqtt_port = Settings.mqtt_port; - - - - - if ((215 == restart_flag) || (216 == restart_flag)) { - SettingsErase(0); - } - SettingsDefault(); - - SettingsUpdateText(SET_STASSID1, storage_ssid1); - SettingsUpdateText(SET_STASSID2, storage_ssid2); - SettingsUpdateText(SET_STAPWD1, storage_pass1); - SettingsUpdateText(SET_STAPWD2, storage_pass2); - if (216 == restart_flag) { - - SettingsUpdateText(SET_MQTT_HOST, storage_mqtthost); - SettingsUpdateText(SET_MQTT_USER, storage_mqttuser); - SettingsUpdateText(SET_MQTT_PWD, storage_mqttpwd); - SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic); - Settings.mqtt_port = mqtt_port; - } - restart_flag = 2; - } - else if (213 == restart_flag) { - SettingsSdkErase(); - restart_flag = 2; - } - else if (212 == restart_flag) { - SettingsErase(0); - restart_flag = 211; - } - if (211 == restart_flag) { - SettingsDefault(); - restart_flag = 2; - } - if (2 == restart_flag) { - SettingsSaveAll(); - } - restart_flag--; - if (restart_flag <= 0) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - EspRestart(); - } - } - break; - case 2: - WifiCheck(wifi_state_flag); - wifi_state_flag = WIFI_RESTART; - break; - case 3: - if (!global_state.wifi_down) { MqttCheck(); } - break; - } -} - -#ifdef USE_ARDUINO_OTA - - - - - - - -bool arduino_ota_triggered = false; -uint16_t arduino_ota_progress_dot_count = 0; - -void ArduinoOTAInit(void) -{ - ArduinoOTA.setPort(8266); - ArduinoOTA.setHostname(my_hostname); - if (strlen(SettingsText(SET_WEBPWD))) { - ArduinoOTA.setPassword(SettingsText(SET_WEBPWD)); - } - - ArduinoOTA.onStart([]() - { - SettingsSave(1); -#ifdef USE_WEBSERVER - if (Settings.webserver) { StopWebserver(); } -#endif -#ifdef USE_ARILUX_RF - AriluxRfDisable(); -#endif - if (Settings.flag.mqtt_enabled) { - MqttDisconnect(); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); - arduino_ota_triggered = true; - arduino_ota_progress_dot_count = 0; - delay(100); - }); - - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) - { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { - arduino_ota_progress_dot_count++; - Serial.printf("."); - if (!(arduino_ota_progress_dot_count % 80)) { Serial.println(); } - } - }); - - ArduinoOTA.onError([](ota_error_t error) - { - - - - - char error_str[100]; - - if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } - switch (error) { - case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break; - case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break; - case OTA_END_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_7), sizeof(error_str)); break; - default: - snprintf_P(error_str, sizeof(error_str), PSTR(D_UPLOAD_ERROR_CODE " %d"), error); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str); - EspRestart(); - }); - - ArduinoOTA.onEnd([]() - { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); - EspRestart(); - }); - - ArduinoOTA.begin(); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266")); -} - -void ArduinoOtaLoop(void) -{ - MDNS.update(); - ArduinoOTA.handle(); - - while (arduino_ota_triggered) { ArduinoOTA.handle(); } -} -#endif - - - -void SerialInput(void) -{ - while (Serial.available()) { - - delay(0); - serial_in_byte = Serial.read(); - - - - - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - serial_in_byte = ButtonSerial(serial_in_byte); - } - - - - if (XdrvCall(FUNC_SERIAL)) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - - - - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - if (!Settings.flag.mqtt_serial) { - if (isprint(serial_in_byte)) { - if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } else { - serial_in_byte_counter = 0; - } - } - } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && - ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || - ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || - Settings.flag.mqtt_serial_raw)) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - serial_polling_window = millis(); - } else { - serial_polling_window = 0; - break; - } - } - } - -#ifdef USE_SONOFF_SC - - - - if (SONOFF_SC == my_module_type) { - if (serial_in_byte == '\x1B') { - serial_in_buffer[serial_in_byte_counter] = 0; - SonoffScSerialInput(serial_in_buffer); - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - } else -#endif - - - if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { - serial_in_buffer[serial_in_byte_counter] = 0; - seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); - ExecuteCommand(serial_in_buffer, SRC_SERIAL); - serial_in_byte_counter = 0; - serial_polling_window = 0; - Serial.flush(); - return; - } - } - - if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { - serial_in_buffer[serial_in_byte_counter] = 0; - char hex_char[(serial_in_byte_counter * 2) + 2]; - bool assume_json = (!Settings.flag.mqtt_serial_raw && (serial_in_buffer[0] == '{')); - Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":%s%s%s}"), - (assume_json) ? "" : """", - (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer, - (assume_json) ? "" : """"); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); - XdrvRulesProcess(); - serial_in_byte_counter = 0; - } -} - - - -void GpioInit(void) -{ - uint32_t mpin; - - if (!ValidModule(Settings.module)) { - uint32_t module = MODULE; - if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } - Settings.module = module; - Settings.last_module = module; - } - SetModuleType(); - - if (Settings.module != Settings.last_module) { - Settings.baudrate = APP_BAUDRATE / 300; - Settings.serial_config = TS_SERIAL_8N1; - } - - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) { - Settings.user_template.gp.io[i] = GPIO_USER; - } - } - - myio def_gp; - ModuleGpios(&def_gp); - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) { - Settings.my_gp.io[i] = GPIO_NONE; - } - else if (Settings.my_gp.io[i] > GPIO_NONE) { - my_module.io[i] = Settings.my_gp.io[i]; - } - if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { - my_module.io[i] = def_gp.io[i]; - } - } - if ((Settings.my_adc0 >= ADC0_END) && (Settings.my_adc0 < ADC0_USER)) { - Settings.my_adc0 = ADC0_NONE; - } - else if (Settings.my_adc0 > ADC0_NONE) { - my_adc0 = Settings.my_adc0; - } - my_module_flag = ModuleFlag(); - uint32_t template_adc0 = my_module_flag.data &15; - if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) { - my_adc0 = template_adc0; - } - - for (uint32_t i = 0; i < GPIO_MAX; i++) { - pin[i] = 99; - } - for (uint32_t i = 0; i < sizeof(my_module.io); i++) { - mpin = ValidPin(i, my_module.io[i]); - - DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin); - - if (mpin) { - XdrvMailbox.index = mpin; - XdrvMailbox.payload = i; - - if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) { - SwitchPullupFlag(mpin - GPIO_SWT1_NP); - mpin -= (GPIO_SWT1_NP - GPIO_SWT1); - } - else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_NP); - mpin -= (GPIO_KEY1_NP - GPIO_KEY1); - } - else if ((mpin >= GPIO_KEY1_INV) && (mpin < (GPIO_KEY1_INV + MAX_KEYS))) { - ButtonInvertFlag(mpin - GPIO_KEY1_INV); - mpin -= (GPIO_KEY1_INV - GPIO_KEY1); - } - else if ((mpin >= GPIO_KEY1_INV_NP) && (mpin < (GPIO_KEY1_INV_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_INV_NP); - ButtonInvertFlag(mpin - GPIO_KEY1_INV_NP); - mpin -= (GPIO_KEY1_INV_NP - GPIO_KEY1); - } - else if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { - bitSet(rel_inverted, mpin - GPIO_REL1_INV); - mpin -= (GPIO_REL1_INV - GPIO_REL1); - } - else if ((mpin >= GPIO_LED1_INV) && (mpin < (GPIO_LED1_INV + MAX_LEDS))) { - bitSet(led_inverted, mpin - GPIO_LED1_INV); - mpin -= (GPIO_LED1_INV - GPIO_LED1); - } - else if (mpin == GPIO_LEDLNK_INV) { - ledlnk_inverted = 1; - mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK); - } - else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) { - bitSet(pwm_inverted, mpin - GPIO_PWM1_INV); - mpin -= (GPIO_PWM1_INV - GPIO_PWM1); - } - else if (XdrvCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - } - else if (XsnsCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - }; - } - if (mpin) pin[mpin] = i; - } - - if ((2 == pin[GPIO_TXD]) || (H801 == my_module_type)) { Serial.set_tx(2); } - - analogWriteRange(Settings.pwm_range); - analogWriteFreq(Settings.pwm_frequency); - -#ifdef USE_SPI - spi_flg = ((((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CS] > 14)) || (pin[GPIO_SPI_CS] < 12)) || (((pin[GPIO_SPI_DC] < 99) && (pin[GPIO_SPI_DC] > 14)) || (pin[GPIO_SPI_DC] < 12))); - if (spi_flg) { - for (uint32_t i = 0; i < GPIO_MAX; i++) { - if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; - } - my_module.io[12] = GPIO_SPI_MISO; - pin[GPIO_SPI_MISO] = 12; - my_module.io[13] = GPIO_SPI_MOSI; - pin[GPIO_SPI_MOSI] = 13; - my_module.io[14] = GPIO_SPI_CLK; - pin[GPIO_SPI_CLK] = 14; - } - soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); -#endif - -#ifdef USE_I2C - i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); - if (i2c_flg) { - Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); - } -#endif - - devices_present = 0; - light_type = LT_BASIC; - if (XdrvCall(FUNC_MODULE_INIT)) { - - } - else if (YTF_IR_BRIDGE == my_module_type) { - ClaimSerial(); - - } - else if (SONOFF_DUAL == my_module_type) { - devices_present = 2; - SetSerial(19200, TS_SERIAL_8N1); - } - else if (CH4 == my_module_type) { - devices_present = 4; - SetSerial(19200, TS_SERIAL_8N1); - } -#ifdef USE_SONOFF_SC - else if (SONOFF_SC == my_module_type) { - SetSerial(19200, TS_SERIAL_8N1); - } -#endif - - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 +i] < 99) { - pinMode(pin[GPIO_PWM1 +i], OUTPUT); - if (light_type) { - - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); - } else { - pwm_present = true; - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); - } - } - } - - for (uint32_t i = 0; i < MAX_RELAYS; i++) { - if (pin[GPIO_REL1 +i] < 99) { - pinMode(pin[GPIO_REL1 +i], OUTPUT); - devices_present++; - if (EXS_RELAY == my_module_type) { - digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0); - if (i &1) { devices_present--; } - } - } - } - - for (uint32_t i = 0; i < MAX_LEDS; i++) { - if (pin[GPIO_LED1 +i] < 99) { -#ifdef USE_ARILUX_RF - if ((3 == i) && (leds_present < 2) && (99 == pin[GPIO_ARIRFSEL])) { - pin[GPIO_ARIRFSEL] = pin[GPIO_LED4]; - pin[GPIO_LED4] = 99; - } else { -#endif - pinMode(pin[GPIO_LED1 +i], OUTPUT); - leds_present++; - digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); -#ifdef USE_ARILUX_RF - } -#endif - } - } - if (pin[GPIO_LEDLNK] < 99) { - pinMode(pin[GPIO_LEDLNK], OUTPUT); - digitalWrite(pin[GPIO_LEDLNK], ledlnk_inverted); - } - - ButtonInit(); - SwitchInit(); -#ifdef ROTARY_V1 - RotaryInit(); -#endif - - SetLedPower(Settings.ledstate &8); - SetLedLink(Settings.ledstate &8); - - XdrvCall(FUNC_PRE_INIT); -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_udp.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/support_udp.ino" -#ifdef USE_EMULATION - -#define UDP_BUFFER_SIZE 200 -#define UDP_MSEARCH_SEND_DELAY 1500 - -#include -Ticker TickerMSearch; - -IPAddress udp_remote_ip; -uint16_t udp_remote_port; - -bool udp_connected = false; -bool udp_response_mutex = false; - - - - - -const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**"; -const char URN_BELKIN_DEVICE_CAP[] PROGMEM = "urn:Belkin:device:**"; -const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice"; -const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all"; -const char SSDP_ALL[] PROGMEM = "ssdp:all"; - - - - - -bool UdpDisconnect(void) -{ - if (udp_connected) { - PortUdp.flush(); - WiFiUDP::stopAll(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); - udp_connected = false; - } - return udp_connected; -} - -bool UdpConnect(void) -{ - if (!udp_connected) { - - if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); - udp_response_mutex = false; - udp_connected = true; - } else { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED)); - udp_connected = false; - } - } - return udp_connected; -} - -void PollUdp(void) -{ - if (udp_connected) { - while (PortUdp.parsePacket()) { - char packet_buffer[UDP_BUFFER_SIZE]; - - int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); - packet_buffer[len] = 0; - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); - - - -#ifdef USE_SCRIPT_HUE - if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { -#else - if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { -#endif - udp_response_mutex = true; - - udp_remote_ip = PortUdp.remoteIP(); - udp_remote_port = PortUdp.remotePort(); - - - - - uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); - - LowerCase(packet_buffer, packet_buffer); - RemoveSpace(packet_buffer); - -#ifdef USE_EMULATION_WEMO - if (EMUL_WEMO == Settings.flag2.emulation) { - if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { - TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); - return; - } - else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || - (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || - (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { - TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); - return; - } - } -#endif - -#ifdef USE_EMULATION_HUE - if (EMUL_HUE == Settings.flag2.emulation) { - if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || - (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || - (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || - (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { - TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); - return; - } - } -#endif - - udp_response_mutex = false; - } - - } - optimistic_yield(100); - } -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/support_wifi.ino" -# 24 "C:/shared/sonoff/Git/Tasmota/tasmota/support_wifi.ino" -#ifndef WIFI_RSSI_THRESHOLD - -#define WIFI_RSSI_THRESHOLD 5 -#endif -#ifndef WIFI_RESCAN_MINUTES - -#define WIFI_RESCAN_MINUTES 5 -#endif - -const uint8_t WIFI_CONFIG_SEC = 180; - -const uint8_t WIFI_CHECK_SEC = 5; -const uint8_t WIFI_RETRY_OFFSET_SEC = 20; - -#include -#if LWIP_IPV6 -#include -#endif - -struct WIFI { - uint32_t last_event = 0; - uint32_t downtime = 0; - uint16_t link_count = 0; - uint8_t counter; - uint8_t retry_init; - uint8_t retry; - uint8_t status; - uint8_t config_type = 0; - uint8_t config_counter = 0; - uint8_t mdns_begun = 0; - uint8_t scan_state; - uint8_t bssid[6] = {0}; - uint8_t bssid_last[6] = {0}; - int8_t best_network_db; -} Wifi; - -int WifiGetRssiAsQuality(int rssi) -{ - int quality = 0; - - if (rssi <= -100) { - quality = 0; - } else if (rssi >= -50) { - quality = 100; - } else { - quality = 2 * (rssi + 100); - } - return quality; -} - -bool WifiConfigCounter(void) -{ - if (Wifi.config_counter) { - Wifi.config_counter = WIFI_CONFIG_SEC; - } - return (Wifi.config_counter); -} - -void WifiConfig(uint8_t type) -{ - if (!Wifi.config_type) { - if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; } -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - WiFi.disconnect(); - Wifi.config_type = type; - -#ifndef USE_WEBSERVER - if (WIFI_MANAGER == Wifi.config_type) { - Wifi.config_type = WIFI_SERIAL; - } -#endif - - Wifi.config_counter = WIFI_CONFIG_SEC; - Wifi.counter = Wifi.config_counter +5; - blinks = 1999; - if (WIFI_RESTART == Wifi.config_type) { - restart_flag = 2; - } - else if (WIFI_SERIAL == Wifi.config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES)); - } -#ifdef USE_WEBSERVER - else if (WIFI_MANAGER == Wifi.config_type || WIFI_MANAGER_RESET_ONLY == Wifi.config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES)); - WifiManagerBegin(WIFI_MANAGER_RESET_ONLY == Wifi.config_type); - } -#endif - } -} - -void WifiSetMode(WiFiMode_t wifi_mode) -{ - if (WiFi.getMode() == wifi_mode) { return; } - - if (wifi_mode != WIFI_OFF) { - - WiFi.forceSleepWake(); - delay(100); - } - - uint32_t retry = 2; - while (!WiFi.mode(wifi_mode) && retry--) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("Retry set Mode...")); - delay(100); - } - - if (wifi_mode == WIFI_OFF) { - delay(1000); - WiFi.forceSleepBegin(); - delay(1); - } else { - delay(30); - } -} - -void WiFiSetSleepMode(void) -{ -# 156 "C:/shared/sonoff/Git/Tasmota/tasmota/support_wifi.ino" -#if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) -#else - if (sleep && Settings.flag3.sleep_normal) { - WiFi.setSleepMode(WIFI_LIGHT_SLEEP); - } else { - WiFi.setSleepMode(WIFI_MODEM_SLEEP); - } -#endif - WifiSetOutputPower(); -} - -void WifiBegin(uint8_t flag, uint8_t channel) -{ - const char kWifiPhyMode[] = " BGN"; - -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186)); - - WifiSetMode(WIFI_OFF); -#endif - - WiFi.persistent(false); - WiFi.disconnect(true); - delay(200); - - WifiSetMode(WIFI_STA); - WiFiSetSleepMode(); - - - if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } - - - - - - switch (flag) { - case 0: - case 1: - Settings.sta_active = flag; - break; - case 2: - Settings.sta_active ^= 1; - } - if (!strlen(SettingsText(SET_STASSID1 + Settings.sta_active))) { - Settings.sta_active ^= 1; - } - if (Settings.ip_address[0]) { - WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); - } - WiFi.hostname(my_hostname); - - char stemp[40] = { 0 }; - if (channel) { - WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); - - char hex_char[18]; - snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s"), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':')); - } else { - WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); - -#if LWIP_IPV6 - for (bool configured = false; !configured;) { - uint16_t cfgcnt = 0; - for (auto addr : addrList) { - if ((configured = !addr.isLocal() && addr.isV6()) || cfgcnt==30) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI "Got IPv6 global address %s"), addr.toString().c_str()); - break; - } - delay(500); - cfgcnt++; - } - } -#endif -} - -void WifiBeginAfterScan(void) -{ - - if (0 == Wifi.scan_state) { return; } - - if (1 == Wifi.scan_state) { - memset((void*) &Wifi.bssid, 0, sizeof(Wifi.bssid)); - Wifi.best_network_db = -127; - Wifi.scan_state = 3; - } - - if (2 == Wifi.scan_state) { - uint8_t* bssid = WiFi.BSSID(); - memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid)); - Wifi.best_network_db = WiFi.RSSI(); - if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) { - Wifi.best_network_db += WIFI_RSSI_THRESHOLD; - } - Wifi.scan_state = 3; - } - - if (3 == Wifi.scan_state) { - if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) { - WiFi.scanNetworks(true); - Wifi.scan_state++; - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR("Network (re)scan started...")); - return; - } - } - int8_t wifi_scan_result = WiFi.scanComplete(); - - if (4 == Wifi.scan_state) { - if (wifi_scan_result != WIFI_SCAN_RUNNING) { - Wifi.scan_state++; - } - } - - if (5 == Wifi.scan_state) { - uint32_t number_known = 0; - int32_t channel_max = 0; - int8_t ap_max = 3; - uint8_t bssid_max[6]; - memcpy((void*) &bssid_max, (void*) &Wifi.bssid, sizeof(bssid_max)); - - int32_t channel = 0; - int8_t ap = 3; - uint8_t last_bssid[6]; - memcpy((void*) &last_bssid, (void*) &Wifi.bssid, sizeof(last_bssid)); - - if (wifi_scan_result > 0) { - - for (uint32_t i = 0; i < wifi_scan_result; ++i) { - - String ssid_scan; - int32_t rssi_scan; - uint8_t sec_scan; - uint8_t* bssid_scan; - int32_t chan_scan; - bool hidden_scan; - - WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, bssid_scan, chan_scan, hidden_scan); - - bool known = false; - uint32_t j; - for (j = 0; j < MAX_SSIDS; j++) { - if (ssid_scan == SettingsText(SET_STASSID1 + j)) { - known = true; - number_known++; - if (rssi_scan > Wifi.best_network_db) { - if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { - - memcpy((void*) &bssid_max, (void*) bssid_scan, sizeof(bssid_max)); - channel_max = chan_scan; - ap_max = j; - - for (uint32_t i = 0; i < sizeof(Wifi.bssid_last); i++) { - if (bssid_scan[i] != Wifi.bssid_last[i]) { - Wifi.best_network_db = (int8_t)rssi_scan; - channel = chan_scan; - ap = j; - memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); - - memcpy((void*) &Wifi.bssid_last, (void*) bssid_scan, sizeof(Wifi.bssid_last)); - break; - } - } - } - } - break; - } - } - char hex_char[18]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %s, RSSI %d, Encryption %d"), - i, - (known) ? (j) ? '2' : '1' : '-', - ssid_scan.c_str(), - chan_scan, - ToHex_P((unsigned char*)bssid_scan, 6, hex_char, sizeof(hex_char), ':'), - rssi_scan, - (sec_scan == ENC_TYPE_NONE) ? 0 : 1); - delay(0); - } - WiFi.scanDelete(); - delay(0); - } - - - if (number_known == 1) { - - memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last)); - memcpy((void*) &Wifi.bssid, (void*) bssid_max, sizeof(Wifi.bssid)); - channel = channel_max; - ap = ap_max; - } - - Wifi.scan_state = 0; - - for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) { - if (last_bssid[i] != Wifi.bssid[i]) { - WifiBegin(ap, channel); - break; - } - } - } -} - -uint16_t WifiLinkCount(void) -{ - return Wifi.link_count; -} - -String WifiDowntime(void) -{ - return GetDuration(Wifi.downtime); -} - -void WifiSetState(uint8_t state) -{ - if (state == global_state.wifi_down) { - if (state) { - rules_flag.wifi_connected = 1; - Wifi.link_count++; - Wifi.downtime += UpTime() - Wifi.last_event; - } else { - rules_flag.wifi_disconnected = 1; - Wifi.last_event = UpTime(); - } - } - global_state.wifi_down = state ^1; -} - -#if LWIP_IPV6 -bool WifiCheckIPv6(void) -{ - bool ipv6_global=false; - - for (auto a : addrList) { - if(!a.isLocal() && a.isV6()) ipv6_global=true; - } - return ipv6_global; -} - -String WifiGetIPv6(void) -{ - for (auto a : addrList) { - if(!a.isLocal() && a.isV6()) return a.toString(); - } - return ""; -} - -bool WifiCheckIPAddrStatus(void) -{ - bool ip_global=false; - - for (auto a : addrList) { - if(!a.isLocal()) ip_global=true; - } - return ip_global; -} -#endif - -void WifiCheckIp(void) -{ -#if LWIP_IPV6 - if(WifiCheckIPAddrStatus()) { - Wifi.status = WL_CONNECTED; -#else - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { -#endif - - memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last)); - WifiSetState(1); - Wifi.counter = WIFI_CHECK_SEC; - Wifi.retry = Wifi.retry_init; - if (Wifi.status != WL_CONNECTED) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECTED)); - } - Wifi.status = WL_CONNECTED; -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - if (2 == Wifi.mdns_begun) { - MDNS.update(); - AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update"); - } -#endif -#endif - } else { - WifiSetState(0); - uint8_t wifi_config_tool = Settings.sta_config; - Wifi.status = WiFi.status(); - switch (Wifi.status) { - case WL_CONNECTED: - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS)); - - - wifi_station_dhcpc_start(); - break; - case WL_NO_SSID_AVAIL: - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED)); - - if (WIFI_WAIT == Settings.sta_config) { - Wifi.retry = Wifi.retry_init; - } else { - if (Wifi.retry > (Wifi.retry_init / 2)) { - Wifi.retry = Wifi.retry_init / 2; - } - else if (Wifi.retry) { - Wifi.retry = 0; - } - } - - break; - case WL_CONNECT_FAILED: - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD)); - - if (Wifi.retry > (Wifi.retry_init / 2)) { - Wifi.retry = Wifi.retry_init / 2; - } - else if (Wifi.retry) { - Wifi.retry = 0; - } - - break; - default: - - if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); - } else { - if (!strlen(SettingsText(SET_STASSID1)) && !strlen(SettingsText(SET_STASSID2))) { - wifi_config_tool = WIFI_MANAGER; - Wifi.retry = 0; - } else { - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); - } - } - } - - if (Wifi.retry) { - if (Settings.flag3.use_wifi_scan) { - - if ((Wifi.retry_init == Wifi.retry) || ((Wifi.retry_init / 2) == Wifi.retry)){ - Wifi.scan_state = 1; - } - } else { - if (Wifi.retry_init == Wifi.retry) { - WifiBegin(3, 0); - } - if ((Settings.sta_config != WIFI_WAIT) && ((Wifi.retry_init / 2) == Wifi.retry)) { - WifiBegin(2, 0); - } - } - Wifi.counter = 1; - Wifi.retry--; - } else { - WifiConfig(wifi_config_tool); - Wifi.counter = 1; - Wifi.retry = Wifi.retry_init; - } - } -} - -void WifiCheck(uint8_t param) -{ - Wifi.counter--; - switch (param) { - case WIFI_SERIAL: - case WIFI_MANAGER: - WifiConfig(param); - break; - default: - if (Wifi.config_counter) { - Wifi.config_counter--; - Wifi.counter = Wifi.config_counter +5; - if (Wifi.config_counter) { - if (!Wifi.config_counter) { - if (strlen(WiFi.SSID().c_str())) { - SettingsUpdateText(SET_STASSID1, WiFi.SSID().c_str()); - } - if (strlen(WiFi.psk().c_str())) { - SettingsUpdateText(SET_STAPWD1, WiFi.psk().c_str()); - } - Settings.sta_active = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), SettingsText(SET_STASSID1)); - } - } - if (!Wifi.config_counter) { - - restart_flag = 2; - } - } else { - if (Wifi.scan_state) { WifiBeginAfterScan(); } - - if (Wifi.counter <= 0) { - AddLog_P(LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CHECKING_CONNECTION)); - Wifi.counter = WIFI_CHECK_SEC; - WifiCheckIp(); - } -#if LWIP_IPV6 - if (WifiCheckIPAddrStatus()) { -#else - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !Wifi.config_type) { -#endif - WifiSetState(1); - - if (Settings.flag3.use_wifi_rescan) { - if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) { - Wifi.scan_state = 2; - } - } - -#ifdef FIRMWARE_MINIMAL - if (1 == RtcSettings.ota_loader) { - RtcSettings.ota_loader = 0; - ota_state_flag = 3; - } -#endif - -#ifdef USE_DISCOVERY - if (Settings.flag3.mdns_enabled) { - if (!Wifi.mdns_begun) { - - - - - - Wifi.mdns_begun = (uint8_t)MDNS.begin(my_hostname); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Wifi.mdns_begun) ? D_INITIALIZED : D_FAILED); - - } - } -#endif - -#ifdef USE_WEBSERVER - if (Settings.webserver) { - StartWebserver(Settings.webserver, WiFi.localIP()); -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - if (1 == Wifi.mdns_begun) { - Wifi.mdns_begun = 2; - MDNS.addService("http", "tcp", WEB_PORT); - } -#endif -#endif - } else { - StopWebserver(); - } -#ifdef USE_EMULATION - if (Settings.flag2.emulation) { UdpConnect(); } -#endif -#endif - -#ifdef USE_KNX - if (!knx_started && Settings.flag.knx_enabled) { - KNXStart(); - knx_started = true; - } -#endif - - } else { - WifiSetState(0); -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - Wifi.mdns_begun = 0; -#ifdef USE_KNX - knx_started = false; -#endif - } - } - } -} - -int WifiState(void) -{ - int state = -1; - - if (!global_state.wifi_down) { state = WIFI_RESTART; } - if (Wifi.config_type) { state = Wifi.config_type; } - return state; -} - -String WifiGetOutputPower(void) -{ - char stemp1[TOPSZ]; - dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); - return String(stemp1); -} -void WifiSetOutputPower(void) -{ - WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); -} - -void WifiConnect(void) -{ - WifiSetState(0); - WifiSetOutputPower(); - WiFi.persistent(false); - Wifi.status = 0; - - - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP.getChipId() & 0xF); - Wifi.retry = Wifi.retry_init; - Wifi.counter = 1; -} - - - -void WifiDisconnect(void) -{ - - WiFi.persistent(true); - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); - ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); -} - -void WifiShutdown(void) -{ - delay(100); - if (Settings.flag.mqtt_enabled) { - MqttDisconnect(); - } - WifiDisconnect(); -} - -void EspRestart(void) -{ - WifiShutdown(); - CrashDumpClear(); - - ESP.reset(); -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/tasmota_ca.ino" -# 24 "C:/shared/sonoff/Git/Tasmota/tasmota/tasmota_ca.ino" -#ifdef USE_MQTT_TLS_CA_CERT - -#ifndef USE_MQTT_AWS_IOT -# 38 "C:/shared/sonoff/Git/Tasmota/tasmota/tasmota_ca.ino" -static const unsigned char PROGMEM TA0_DN[] = { - 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, - 0x79, 0x20, 0x58, 0x33 -}; - -static const unsigned char PROGMEM TA0_RSA_N[] = { - 0x9C, 0xD3, 0x0C, 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, 0x37, - 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, 0x35, 0x26, 0x19, 0x25, 0xE1, - 0xBD, 0xBE, 0x35, 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, 0x05, - 0xAB, 0xA9, 0x9E, 0x35, 0x08, 0x58, 0xEC, 0xB1, 0x2A, 0xC4, 0x68, 0x87, - 0x0B, 0xA3, 0xE3, 0x75, 0xE4, 0xE6, 0xF3, 0xA7, 0x62, 0x71, 0xBA, 0x79, - 0x81, 0x60, 0x1F, 0xD7, 0x91, 0x9A, 0x9F, 0xF3, 0xD0, 0x78, 0x67, 0x71, - 0xC8, 0x69, 0x0E, 0x95, 0x91, 0xCF, 0xFE, 0xE6, 0x99, 0xE9, 0x60, 0x3C, - 0x48, 0xCC, 0x7E, 0xCA, 0x4D, 0x77, 0x12, 0x24, 0x9D, 0x47, 0x1B, 0x5A, - 0xEB, 0xB9, 0xEC, 0x1E, 0x37, 0x00, 0x1C, 0x9C, 0xAC, 0x7B, 0xA7, 0x05, - 0xEA, 0xCE, 0x4A, 0xEB, 0xBD, 0x41, 0xE5, 0x36, 0x98, 0xB9, 0xCB, 0xFD, - 0x6D, 0x3C, 0x96, 0x68, 0xDF, 0x23, 0x2A, 0x42, 0x90, 0x0C, 0x86, 0x74, - 0x67, 0xC8, 0x7F, 0xA5, 0x9A, 0xB8, 0x52, 0x61, 0x14, 0x13, 0x3F, 0x65, - 0xE9, 0x82, 0x87, 0xCB, 0xDB, 0xFA, 0x0E, 0x56, 0xF6, 0x86, 0x89, 0xF3, - 0x85, 0x3F, 0x97, 0x86, 0xAF, 0xB0, 0xDC, 0x1A, 0xEF, 0x6B, 0x0D, 0x95, - 0x16, 0x7D, 0xC4, 0x2B, 0xA0, 0x65, 0xB2, 0x99, 0x04, 0x36, 0x75, 0x80, - 0x6B, 0xAC, 0x4A, 0xF3, 0x1B, 0x90, 0x49, 0x78, 0x2F, 0xA2, 0x96, 0x4F, - 0x2A, 0x20, 0x25, 0x29, 0x04, 0xC6, 0x74, 0xC0, 0xD0, 0x31, 0xCD, 0x8F, - 0x31, 0x38, 0x95, 0x16, 0xBA, 0xA8, 0x33, 0xB8, 0x43, 0xF1, 0xB1, 0x1F, - 0xC3, 0x30, 0x7F, 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, 0xE3, - 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, - 0x1D, 0x64, 0x16, 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, 0xC0, - 0xD8, 0x7D, 0xC3, 0x93 -}; - -static const unsigned char TA0_RSA_E[] = { - 0x01, 0x00, 0x01 -}; - -static const br_x509_trust_anchor PROGMEM LetsEncryptX3CrossSigned_TA = { - { (unsigned char *)TA0_DN, sizeof TA0_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, - (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, - } } - } -}; - -#define TAs_NUM 1 - -#endif - -#ifdef USE_MQTT_AWS_IOT -# 106 "C:/shared/sonoff/Git/Tasmota/tasmota/tasmota_ca.ino" -const unsigned char PROGMEM TA0_DN[] = { - 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, - 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 -}; - -const unsigned char PROGMEM TA0_RSA_N[] = { - 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, - 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, - 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, - 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, - 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, - 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, - 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, - 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, - 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, - 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, - 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, - 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, - 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, - 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, - 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, - 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, - 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, - 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, - 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, - 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, - 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, - 0x9A, 0xC8, 0xAA, 0x0D -}; - -static const unsigned char PROGMEM TA0_RSA_E[] = { - 0x01, 0x00, 0x01 -}; - -const br_x509_trust_anchor PROGMEM AmazonRootCA1_TA = { - { (unsigned char *)TA0_DN, sizeof TA0_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, - (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, - } } - } -}; - -#define TAs_NUM 1 - -#endif - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_01_webserver.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_01_webserver.ino" -#ifdef USE_WEBSERVER - - - - - - - -#define XDRV_01 1 - -#ifndef WIFI_SOFT_AP_CHANNEL -#define WIFI_SOFT_AP_CHANNEL 1 -#endif - -const uint16_t CHUNKED_BUFFER_SIZE = 400; - -const uint16_t HTTP_REFRESH_TIME = 2345; -#define HTTP_RESTART_RECONNECT_TIME 9000 -#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 - -#include -#include - -#ifdef USE_RF_FLASH -uint8_t *efm8bb1_update = nullptr; -#endif - -enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTASLAVE }; - -static const char * HEADER_KEYS[] = { "User-Agent", }; - -const char HTTP_HEADER[] PROGMEM = - "" - "" - "" - "" - "%s - %s" - - ""; - -const char HTTP_HEAD_STYLE1[] PROGMEM = - "" - - "" - "" - "
" -#ifdef FIRMWARE_MINIMAL - "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

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

" D_MODULE " %s

" -#else - "

%s " D_MODULE "

" -#endif - "

%s

"; - -const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM = - "
" - "" - "
"; -const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = - "
" D_CLOSE "" D_OPEN "
" - "
"; - -const char HTTP_MSG_RSTRT[] PROGMEM = - "
" D_DEVICE_WILL_RESTART "

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

" D_USER "

" - "

" D_PASSWORD "

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

" - "
 " D_TEMPLATE_FLAGS " 

" - - "

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

" D_MODULE_TYPE " (%s)

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

" D_AP1_SSID " (" STA_SSID1 ")

" - "

" D_AP1_PASSWORD "

" - "

" D_AP2_SSID " (" STA_SSID2 ")

" - "

" D_AP2_PASSWORD "

" - "

" D_HOSTNAME " (%s)

" - "

" D_CORS_DOMAIN "

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

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" - "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" - "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

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

" - "
 " D_TEMPLATE " " - "

" - "

" D_ACTIVATE "

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

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

" - "
" - "


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

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


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

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

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

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

"), - GetTextIndexed(action, sizeof(action), title_index, kButtonAction), - GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); - } -} - -void WSContentSpaceButton(uint32_t title_index) -{ - WSContentSend_P(PSTR("
")); - WSContentButton(title_index); -} - -void WSContentEnd(void) -{ - WSContentFlush(); - _WSContentSend(""); - WebServer->client().stop(); -} - -void WSContentStop(void) -{ - if (WifiIsInManagerMode()) { - if (WifiConfigCounter()) { - WSContentSend_P(HTTP_COUNTER); - } - } - WSContentSend_P(HTTP_END, my_version); - WSContentEnd(); -} - - - -void WebRestart(uint32_t type) -{ - - - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); - - bool reset_only = (HTTP_MANAGER_RESET_ONLY == Web.state); - - WSContentStart_P((type) ? S_SAVE_CONFIGURATION : S_RESTART, !reset_only); - WSContentSend_P(HTTP_SCRIPT_RELOAD); - WSContentSendStyle(); - if (type) { - WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); - if (2 == type) { - WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); - } - WSContentSend_P(PSTR("
")); - } - WSContentSend_P(HTTP_MSG_RSTRT); - if (HTTP_MANAGER == Web.state || reset_only) { - Web.state = HTTP_ADMIN; - } else { - WSContentSpaceButton(BUTTON_MAIN); - } - WSContentStop(); - - ShowWebSource(SRC_WEBGUI); - restart_flag = 2; -} - - - -void HandleWifiLogin(void) -{ - WSContentStart_P(S_CONFIGURE_WIFI, false); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_LOGIN); - - if (HTTP_MANAGER_RESET_ONLY == Web.state) { - WSContentSpaceButton(BUTTON_RESTART); -#ifndef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); -#endif - } - - WSContentStop(); -} - -void WebSliderColdWarm(void) -{ - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "a", - "#fff", "#ff0", - 1, - 153, 500, - LightGetColorTemp(), - 't', 0); -} - -void HandleRoot(void) -{ - if (CaptivePortal()) { return; } - - if (WebServer->hasArg("rst")) { - WebRestart(0); - return; - } - - if (WifiIsInManagerMode()) { -#ifndef FIRMWARE_MINIMAL - if (strlen(SettingsText(SET_WEBPWD)) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { - HandleWifiLogin(); - } else { - if (!strlen(SettingsText(SET_WEBPWD)) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { - HandleWifiConfiguration(); - } else { - - HandleWifiLogin(); - } - } -#endif - return; - } - - if (HandleRootStatusRefresh()) { - return; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); - - char stemp[33]; - - WSContentStart_P(S_MAIN_MENU); -#ifdef USE_SCRIPT_WEB_DISPLAY - WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh, Settings.web_refresh); -#else - WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); -#endif - WSContentSend_P(HTTP_SCRIPT_ROOT_PART2); - - WSContentSendStyle(); - - WSContentSend_P(PSTR("
")); - if (devices_present) { -#ifdef USE_LIGHT - if (light_type) { - uint8_t light_subtype = light_type &7; - if (!Settings.flag3.pwm_multi_channels) { - bool split_white = ((LST_RGBW <= light_subtype) && (devices_present > 1)); - - if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) { - WebSliderColdWarm(); - } - - if (light_subtype > 2) { - uint16_t hue; - uint8_t sat; - LightGetHSB(&hue, &sat, nullptr); - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "b", - "#800", "#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800", - 2, - 1, 359, - hue, - 'h', 0); - - uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255); - char scolor[8]; - snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); - uint8_t red, green, blue; - LightHsToRgb(hue, 255, &red, &green, &blue); - snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "s", - scolor, stemp, - 3, - 0, 100, - changeUIntScale(sat, 0, 255, 0, 100), - 'n', 0); - } - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "c", - "#000", "#fff", - 4, - Settings.flag3.slider_dimmer_stay_on, 100, - Settings.light_dimmer, - 'd', 0); - - if (split_white) { - if (LST_RGBCW == light_subtype) { - WebSliderColdWarm(); - } - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "f", - "#000", "#fff", - 5, - Settings.flag3.slider_dimmer_stay_on, 100, - LightGetDimmer(2), - 'w', 0); - } - } else { - uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; - stemp[0] = 'e'; stemp[1] = '0'; stemp[2] = '\0'; - for (uint32_t i = 0; i < pwm_channels; i++) { - stemp[1]++; - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - stemp, - "#000", "#fff", - i+1, - 1, 100, - changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), - 'e', i+1); - } - } - } -#endif -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - for (uint32_t i = 0; i < shutters_present; i++) { - WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1); - } - } -#endif - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("
")); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, - (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : D_BUTTON_TOGGLE, - ""); - for (uint32_t i = 0; i < MaxFanspeed(); i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); - WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, - (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp, - ""); - } - } else { -#endif - for (uint32_t idx = 1; idx <= devices_present; idx++) { - bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); -#ifdef USE_SHUTTER - int32_t ShutterWebButton; - if (ShutterWebButton = IsShutterWebButton(idx)) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) ? "-" : ((ShutterWebButton>0) ? "▲" : "▼")), - ""); - continue; - } -#endif - snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (devices_present < 5) ? D_BUTTON_TOGGLE : "", - (set_button) ? "" : (devices_present > 1) ? stemp : ""); - } -#ifdef USE_SONOFF_IFAN - } -#endif - WSContentSend_P(PSTR("
%s
")); - } -#ifdef USE_SONOFF_RF - if (SONOFF_BRIDGE == my_module_type) { - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("")); - uint32_t idx = 0; - for (uint32_t i = 0; i < 4; i++) { - if (idx > 0) { WSContentSend_P(PSTR("")); } - for (uint32_t j = 0; j < 4; j++) { - idx++; - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), idx); - WSContentSend_P(PSTR(""), idx, - (strlen(SettingsText(SET_BUTTON1 + idx -1))) ? SettingsText(SET_BUTTON1 + idx -1) : stemp); - } - } - WSContentSend_P(PSTR("")); - } -#endif - -#ifndef FIRMWARE_MINIMAL - XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); - XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); -#endif - - if (HTTP_ADMIN == Web.state) { -#ifdef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE); -#else - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentButton(BUTTON_INFORMATION); - WSContentButton(BUTTON_FIRMWARE_UPGRADE); -#endif - WSContentButton(BUTTON_CONSOLE); - WSContentButton(BUTTON_RESTART); - } - WSContentStop(); -} - -bool HandleRootStatusRefresh(void) -{ - if (!WebAuthenticate()) { - WebServer->requestAuthentication(); - return true; - } - - if (!WebServer->hasArg("m")) { - return false; - } - - #ifdef USE_SCRIPT_WEB_DISPLAY - Script_Check_HTML_Setvars(); - #endif - - char tmp[8]; - char svalue[32]; - char webindex[5]; - - WebGetArg("o", tmp, sizeof(tmp)); - if (strlen(tmp)) { - ShowWebSource(SRC_WEBGUI); - uint32_t device = atoi(tmp); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - if (device < 2) { - ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE); - } else { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), device -2); - ExecuteCommand(svalue, SRC_WEBGUI); - } - } else { -#endif -#ifdef USE_SHUTTER - int32_t ShutterWebButton; - if (ShutterWebButton = IsShutterWebButton(device)) { - snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_TOGGLEUP) : PSTR(D_CMND_SHUTTER_TOGGLEDOWN)); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } else { -#endif - ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); -#ifdef USE_SHUTTER - } -#endif -#ifdef USE_SONOFF_IFAN - } -#endif - } - WebGetArg("d0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("w0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - for (uint32_t j = 1; j <= pwm_channels; j++) { - snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j); - WebGetArg(webindex, tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j, tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - } - WebGetArg("t0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("h0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("n0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } -#ifdef USE_SHUTTER - for (uint32_t j = 1; j <= shutters_present; j++) { - snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); - WebGetArg(webindex, tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - } -#endif -#ifdef USE_SONOFF_RF - WebGetArg("k", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } -#endif - WSContentBegin(200, CT_HTML); - WSContentSend_P(PSTR("{t}")); - XsnsCall(FUNC_WEB_SENSOR); -#ifdef USE_SCRIPT_WEB_DISPLAY - XdrvCall(FUNC_WEB_SENSOR); -#endif - - WSContentSend_P(PSTR("")); - - if (devices_present) { - WSContentSend_P(PSTR("{t}")); - uint32_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); - uint32_t fanspeed = GetFanspeed(); - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); - WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); - } else { -#endif - for (uint32_t idx = 1; idx <= devices_present; idx++) { - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); - WSContentSend_P(HTTP_DEVICE_STATE, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); - } -#ifdef USE_SONOFF_IFAN - } -#endif - WSContentSend_P(PSTR("")); - } - WSContentEnd(); - - return true; -} - -#ifdef USE_SHUTTER -int32_t IsShutterWebButton(uint32_t idx) { - - int32_t ShutterWebButton = 0; - if (Settings.flag3.shutter_mode) { - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - if (Settings.shutter_startrelay[i] && ((Settings.shutter_startrelay[i] == idx) || (Settings.shutter_startrelay[i] == (idx-1)))) { - ShutterWebButton = (Settings.shutter_startrelay[i] == idx) ? (i+1): (-1-i); - break; - } - } - } - return ShutterWebButton; -} -#endif - - - -#ifndef FIRMWARE_MINIMAL - -void HandleConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); - - WSContentStart_P(S_CONFIGURATION); - WSContentSendStyle(); - - WSContentButton(BUTTON_MODULE); - WSContentButton(BUTTON_WIFI); - - XdrvCall(FUNC_WEB_ADD_BUTTON); - XsnsCall(FUNC_WEB_ADD_BUTTON); - - WSContentButton(BUTTON_LOGGING); - WSContentButton(BUTTON_OTHER); - WSContentButton(BUTTON_TEMPLATE); - - WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); - WSContentButton(BUTTON_BACKUP); - WSContentButton(BUTTON_RESTORE); - - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} - - - -void HandleTemplateConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - TemplateSaveSettings(); - WebRestart(1); - return; - } - - char stemp[30]; - - if (WebServer->hasArg("m")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { - uint32_t midx = pgm_read_byte(kModuleNiceList + i); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); - } - WSContentEnd(); - return; - } - - WebGetArg("t", stemp, sizeof(stemp)); - if (strlen(stemp)) { - uint32_t module = atoi(stemp); - uint32_t module_save = Settings.module; - Settings.module = module; - myio cmodule; - ModuleGpios(&cmodule); - gpio_flag flag = ModuleFlag(); - Settings.module = module_save; - - WSContentBegin(200, CT_PLAIN); - WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - if (1 == i) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); - } - uint32_t midx = pgm_read_byte(kGpioNiceList + i); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); - } - WSContentSend_P(PSTR("}1")); - - for (uint32_t i = 0; i < ADC0_END; i++) { - if (1 == i) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ADC0_USER, D_SENSOR_USER, ADC0_USER); - } - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, i, GetTextIndexed(stemp, sizeof(stemp), i, kAdc0Names), i); - } - WSContentSend_P(PSTR("}1")); - - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if ((i < 6) || ((i > 8) && (i != 11))) { - WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", cmodule.io[i]); - } - } - WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings.user_template_base); - WSContentEnd(); - return; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); - - WSContentStart_P(S_CONFIGURE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_TEMPLATE); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_TEMPLATE); - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("" D_TEMPLATE_NAME "" - "" D_BASE_TYPE "" - "" - "
")); - WSContentSend_P(HTTP_TABLE100); - for (uint32_t i = 0; i < 17; i++) { - if ((i < 6) || ((i > 8) && (i != 11))) { - WSContentSend_P(PSTR("" D_GPIO "%d"), - ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i); - } - } - WSContentSend_P(PSTR("" D_ADC "0"), WebColor(COL_TEXT)); - WSContentSend_P(PSTR("")); - gpio_flag flag = ModuleFlag(); - if (flag.data > ADC0_USER) { - WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); - } - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void TemplateSaveSettings(void) -{ - char tmp[sizeof(Settings.user_template.name)]; - char webindex[5]; - char svalue[128]; - - WebGetArg("s1", tmp, sizeof(tmp)); - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); - - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); - WebGetArg(webindex, tmp, sizeof(tmp)); - uint8_t gpio = atoi(tmp); - snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio); - j++; - } - - WebGetArg("g17", tmp, sizeof(tmp)); - uint32_t flag = atoi(tmp); - for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { - snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); - uint32_t state = WebServer->hasArg(webindex) << i +4; - flag += state; - } - WebGetArg("g99", tmp, sizeof(tmp)); - uint32_t base = atoi(tmp) +1; - - snprintf_P(svalue, sizeof(svalue), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), svalue, flag, base); - ExecuteWebCommand(svalue, SRC_WEBGUI); -} - - - -void HandleModuleConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - ModuleSaveSettings(); - WebRestart(1); - return; - } - - char stemp[30]; - uint32_t midx; - myio cmodule; - ModuleGpios(&cmodule); - - if (WebServer->hasArg("m")) { - WSContentBegin(200, CT_PLAIN); - uint32_t vidx = 0; - for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { - if (0 == i) { - midx = USER_MODULE; - vidx = 0; - } else { - midx = pgm_read_byte(kModuleNiceList + i -1); - vidx = midx +1; - } - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx); - } - WSContentEnd(); - return; - } - - if (WebServer->hasArg("g")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t j = 0; j < sizeof(kGpioNiceList); j++) { - midx = pgm_read_byte(kGpioNiceList + j); - if (!GetUsedInModule(midx, cmodule.io)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); - } - } - WSContentEnd(); - return; - } - -#ifndef USE_ADC_VCC - if (WebServer->hasArg("a")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t j = 0; j < ADC0_END; j++) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j); - } - WSContentEnd(); - return; - } -#endif - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); - - WSContentStart_P(S_CONFIGURE_MODULE); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); - } - } - WSContentSend_P(HTTP_SCRIPT_MODULE2, Settings.my_adc0); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(stemp, 3, PINS_WEMOS +i*2); - char sesp8285[40]; - snprintf_P(sesp8285, sizeof(sesp8285), PSTR("ESP8285"), WebColor(COL_TEXT_WARNING)); - WSContentSend_P(PSTR("%s " D_GPIO "%d %s"), - (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i); - } - } -#ifndef USE_ADC_VCC - if (ValidAdc()) { - WSContentSend_P(PSTR("%s " D_ADC "0"), (WEMOS==my_module_type)?"A0":""); - } -#endif - WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void ModuleSaveSettings(void) -{ - char tmp[8]; - char webindex[5]; - - WebGetArg("g99", tmp, sizeof(tmp)); - uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); - Settings.last_module = Settings.module; - Settings.module = new_module; - SetModuleType(); - myio cmodule; - ModuleGpios(&cmodule); - String gpios = ""; - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (Settings.last_module != new_module) { - Settings.my_gp.io[i] = GPIO_NONE; - } else { - if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); - WebGetArg(webindex, tmp, sizeof(tmp)); - Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); - } - } - } -#ifndef USE_ADC_VCC - WebGetArg("g17", tmp, sizeof(tmp)); - Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0); -#endif - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); -} - - - -const char kUnescapeCode[] = "&><\"\'"; -const char kEscapeCode[] PROGMEM = "&|>|<|"|'"; - -String HtmlEscape(const String unescaped) { - char escaped[10]; - size_t ulen = unescaped.length(); - String result = ""; - for (size_t i = 0; i < ulen; i++) { - char c = unescaped[i]; - char *p = strchr(kUnescapeCode, c); - if (p != nullptr) { - result += GetTextIndexed(escaped, sizeof(escaped), p - kUnescapeCode, kEscapeCode); - } else { - result += c; - } - } - return result; -} - - -const char kEncryptionType[] PROGMEM = "|||" D_WPA_PSK "||" D_WPA2_PSK "|" D_WEP "||" D_NONE "|" D_AUTO; - -void HandleWifiConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); - - if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { - WifiSaveSettings(); - WebRestart(2); - return; - } - - WSContentStart_P(S_CONFIGURE_WIFI, !WifiIsInManagerMode()); - WSContentSend_P(HTTP_SCRIPT_WIFI); - WSContentSendStyle(); - - if (HTTP_MANAGER_RESET_ONLY != Web.state) { - if (WebServer->hasArg("scan")) { -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - int n = WiFi.scanNetworks(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); - - if (0 == n) { - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); - WSContentSend_P(S_NO_NETWORKS_FOUND); - WSContentSend_P(PSTR(". " D_REFRESH_TO_SCAN_AGAIN ".")); - } else { - - int indices[n]; - for (uint32_t i = 0; i < n; i++) { - indices[i] = i; - } - - - for (uint32_t i = 0; i < n; i++) { - for (uint32_t j = i + 1; j < n; j++) { - if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { - std::swap(indices[i], indices[j]); - } - } - } - - - String cssid; - for (uint32_t i = 0; i < n; i++) { - if (-1 == indices[i]) { continue; } - cssid = WiFi.SSID(indices[i]); - uint32_t cschn = WiFi.channel(indices[i]); - for (uint32_t j = i + 1; j < n; j++) { - if ((cssid == WiFi.SSID(indices[j])) && (cschn == WiFi.channel(indices[j]))) { - DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); - indices[j] = -1; - } - } - } - - - for (uint32_t i = 0; i < n; i++) { - if (-1 == indices[i]) { continue; } - DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), - WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); - int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); - int auth = WiFi.encryptionType(indices[i]); - char encryption[20]; - WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), - HtmlEscape(WiFi.SSID(indices[i])).c_str(), - WiFi.channel(indices[i]), - GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality, WiFi.RSSI(indices[i]) - ); - delay(0); - - } - WSContentSend_P(PSTR("
")); - } - } else { - WSContentSend_P(PSTR("
")); - } - - - WSContentSend_P(HTTP_FORM_WIFI, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS)); - WSContentSend_P(HTTP_FORM_END); - } - - if (WifiIsInManagerMode()) { -#ifndef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_RESTORE); - WSContentButton(BUTTON_RESET_CONFIGURATION); -#endif - WSContentSpaceButton(BUTTON_RESTART); - } else { - WSContentSpaceButton(BUTTON_CONFIGURATION); - } - WSContentStop(); -} - -void WifiSaveSettings(void) -{ - char tmp[TOPSZ]; - - WebGetArg("h", tmp, sizeof(tmp)); - SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - } - WebGetArg("c", tmp, sizeof(tmp)); - SettingsUpdateText(SET_CORS, (!strlen(tmp)) ? CORS_DOMAIN : tmp); - WebGetArg("s1", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STASSID1, (!strlen(tmp)) ? STA_SSID1 : tmp); - WebGetArg("s2", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STASSID2, (!strlen(tmp)) ? STA_SSID2 : tmp); - WebGetArg("p1", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STAPWD1, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD1) : tmp); - WebGetArg("p2", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STAPWD2, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD2) : tmp); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), - SettingsText(SET_HOSTNAME), SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), SettingsText(SET_CORS)); -} - - - -void HandleLoggingConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); - - if (WebServer->hasArg("save")) { - LoggingSaveSettings(); - HandleConfiguration(); - return; - } - - WSContentStart_P(S_CONFIGURE_LOGGING); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_LOG1); - char stemp1[45]; - char stemp2[32]; - uint8_t dlevel[4] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE, LOG_LEVEL_NONE }; - for (uint32_t idx = 0; idx < 4; idx++) { - if ((2==idx) && !Settings.flag.mqtt_enabled) { continue; } - uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:(2==idx)?Settings.mqttlog_level:Settings.syslog_level; - WSContentSend_P(PSTR("

%s (%s)

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

"), - i +1, - (i) ? stemp : "", - i, - (i) ? stemp : "", - SettingsText(SET_FRIENDLYNAME1 + i)); - } - -#ifdef USE_EMULATION - WSContentSend_P(PSTR("

 " D_EMULATION " 

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

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

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

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

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

" D_HOST " (" MQTT_HOST ")

" - "

" D_PORT " (" STR(MQTT_PORT) ")

" - "

" D_CLIENT " (%s)

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

" D_USER " (" MQTT_USER ")

" - "

" D_PASSWORD "

" - "

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

" - "

" D_FULL_TOPIC " (%s)

"; - -void HandleMqttConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); - - if (WebServer->hasArg("save")) { - MqttSaveSettings(); - WebRestart(1); - return; - } - - char str[TOPSZ]; - - WSContentStart_P(S_CONFIGURE_MQTT); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MQTT1, - SettingsText(SET_MQTT_HOST), - Settings.mqtt_port, - Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); - WSContentSend_P(HTTP_FORM_MQTT2, - (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), - Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC), - MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void MqttSaveSettings(void) -{ - char tmp[TOPSZ]; - char stemp[TOPSZ]; - char stemp2[TOPSZ]; - - WebGetArg("mt", tmp, sizeof(tmp)); - strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); - MakeValidMqtt(0, stemp); - WebGetArg("mf", tmp, sizeof(tmp)); - strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); - MakeValidMqtt(1, stemp2); - if ((strcmp(stemp, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) { - Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, S_LWT, true); - } - SettingsUpdateText(SET_MQTT_TOPIC, stemp); - SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2); - WebGetArg("mh", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); - WebGetArg("ml", tmp, sizeof(tmp)); - Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); - WebGetArg("mc", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); -#else - WebGetArg("mu", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp); - WebGetArg("mp", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); -#endif -} -#endif - - - - - -bool Xdrv02(uint8_t function) -{ - bool result = false; - - if (Settings.flag.mqtt_enabled) { - switch (function) { - case FUNC_PRE_INIT: - MqttInit(); - break; - case FUNC_EVERY_50_MSECOND: - MqttClient.loop(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_MQTT); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); - break; -#endif - case FUNC_COMMAND: - result = DecodeCommand(kMqttCommands, MqttCommand); - break; - } - } - return result; -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_03_energy.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_03_energy.ino" -#ifdef USE_ENERGY_SENSOR - - - - -#define XDRV_03 3 -#define XSNS_03 3 - - - - -#define ENERGY_NONE 0 -#define ENERGY_WATCHDOG 4 - -#include - -#define D_CMND_POWERCAL "PowerCal" -#define D_CMND_VOLTAGECAL "VoltageCal" -#define D_CMND_CURRENTCAL "CurrentCal" -#define D_CMND_TARIFF "Tariff" -#define D_CMND_MODULEADDRESS "ModuleAddress" - -enum EnergyCommands { - CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, - CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS }; - -const char kEnergyCommands[] PROGMEM = "|" - D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" - D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|" -#ifdef USE_ENERGY_MARGIN_DETECTION - D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" -#ifdef USE_ENERGY_POWER_LIMIT - D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|" - D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" - D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|" -#endif -#endif - D_CMND_ENERGYRESET "|" D_CMND_TARIFF ; - -void (* const EnergyCommand[])(void) PROGMEM = { - &CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, - &CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress, -#ifdef USE_ENERGY_MARGIN_DETECTION - &CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh, -#ifdef USE_ENERGY_POWER_LIMIT - &CmndMaxEnergy, &CmndMaxEnergyStart, - &CmndMaxPower, &CmndMaxPowerHold, &CmndMaxPowerWindow, - &CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow, -#endif -#endif - &CmndEnergyReset, &CmndTariff }; - -const char kEnergyPhases[] PROGMEM = "|%s / %s|%s / %s / %s||[%s,%s]|[%s,%s,%s]"; - -struct ENERGY { - float voltage[3] = { 0, 0, 0 }; - float current[3] = { 0, 0, 0 }; - float active_power[3] = { 0, 0, 0 }; - float apparent_power[3] = { NAN, NAN, NAN }; - float reactive_power[3] = { NAN, NAN, NAN }; - float power_factor[3] = { NAN, NAN, NAN }; - float frequency[3] = { NAN, NAN, NAN }; - - float start_energy = 0; - float daily = 0; - float total = 0; - float export_active = NAN; - - unsigned long kWhtoday_delta = 0; - unsigned long kWhtoday_offset = 0; - unsigned long kWhtoday; - unsigned long period = 0; - - uint8_t fifth_second = 0; - uint8_t command_code = 0; - uint8_t data_valid[3] = { 0, 0, 0 }; - - uint8_t phase_count = 1; - bool voltage_common = false; - - bool voltage_available = true; - bool current_available = true; - - bool type_dc = false; - bool power_on = true; - -#ifdef USE_ENERGY_MARGIN_DETECTION - uint16_t power_history[3] = { 0 }; - uint8_t power_steady_counter = 8; - bool power_delta = false; - bool min_power_flag = false; - bool max_power_flag = false; - bool min_voltage_flag = false; - bool max_voltage_flag = false; - bool min_current_flag = false; - bool max_current_flag = false; - -#ifdef USE_ENERGY_POWER_LIMIT - uint16_t mplh_counter = 0; - uint16_t mplw_counter = 0; - uint8_t mplr_counter = 0; - uint8_t max_energy_state = 0; -#endif -#endif -} Energy; - -Ticker ticker_energy; - - - -bool EnergyTariff1Active() -{ - uint8_t dst = 0; - if (IsDst() && (Settings.tariff[0][1] != Settings.tariff[1][1])) { - dst = 1; - } - if (Settings.tariff[0][dst] != Settings.tariff[1][dst]) { - if (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || - (RtcTime.day_of_week == 7))) { - return true; - } - uint32_t minutes = MinutesPastMidnight(); - if (Settings.tariff[0][dst] > Settings.tariff[1][dst]) { - - return ((minutes >= Settings.tariff[0][dst]) || (minutes < Settings.tariff[1][dst])); - } else { - - return ((minutes >= Settings.tariff[0][dst]) && (minutes < Settings.tariff[1][dst])); - } - } else { - return false; - } -} - -void EnergyUpdateToday(void) -{ - if (Energy.kWhtoday_delta > 1000) { - unsigned long delta = Energy.kWhtoday_delta / 1000; - Energy.kWhtoday_delta -= (delta * 1000); - Energy.kWhtoday += delta; - } - - RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday; - Energy.daily = (float)(RtcSettings.energy_kWhtoday) / 100000; - Energy.total = (float)(RtcSettings.energy_kWhtotal + RtcSettings.energy_kWhtoday) / 100000; - - if (RtcTime.valid){ - - uint32_t energy_diff = (uint32_t)(Energy.total * 100000) - RtcSettings.energy_usage.last_usage_kWhtotal; - RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 100000); - - uint32_t return_diff = 0; - if (!isnan(Energy.export_active)) { - return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; - RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000); - } - - if (EnergyTariff1Active()) { - RtcSettings.energy_usage.usage1_kWhtotal += energy_diff; - RtcSettings.energy_usage.return1_kWhtotal += return_diff; - } else { - RtcSettings.energy_usage.usage2_kWhtotal += energy_diff; - RtcSettings.energy_usage.return2_kWhtotal += return_diff; - } - } -} - -void EnergyUpdateTotal(float value, bool kwh) -{ - - - - - uint32_t multiplier = (kwh) ? 100000 : 100; - - if (0 == Energy.start_energy || (value < Energy.start_energy)) { - Energy.start_energy = value; - } - else if (value != Energy.start_energy) { - Energy.kWhtoday = (unsigned long)((value - Energy.start_energy) * multiplier); - } - - if ((Energy.total < (value - 0.01)) && - Settings.flag3.hardware_energy_total) { - RtcSettings.energy_kWhtotal = (unsigned long)((value * multiplier) - Energy.kWhtoday_offset - Energy.kWhtoday); - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; - Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); - - } - EnergyUpdateToday(); -} - - - -void Energy200ms(void) -{ - Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; - - Energy.fifth_second++; - if (5 == Energy.fifth_second) { - Energy.fifth_second = 0; - - XnrgCall(FUNC_ENERGY_EVERY_SECOND); - - if (RtcTime.valid) { - if (LocalTime() == Midnight()) { - Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; - - RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.kWhtoday = 0; - Energy.kWhtoday_offset = 0; - RtcSettings.energy_kWhtoday = 0; - Energy.start_energy = 0; - - Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday; - EnergyUpdateToday(); -#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) - Energy.max_energy_state = 3; -#endif - } -#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) - if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == Energy.max_energy_state )) { - Energy.max_energy_state = 0; - } -#endif - - } - } - - XnrgCall(FUNC_EVERY_200_MSECOND); -} - -void EnergySaveState(void) -{ - Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; - - Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - - Settings.energy_usage = RtcSettings.energy_usage; -} - -#ifdef USE_ENERGY_MARGIN_DETECTION -bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) -{ - bool change; - - if (!margin) return false; - change = save_flag; - if (type) { - flag = (value > margin); - } else { - flag = (value < margin); - } - save_flag = flag; - return (change != save_flag); -} - -void EnergyMarginCheck(void) -{ - if (Energy.power_steady_counter) { - Energy.power_steady_counter--; - return; - } - - uint16_t energy_power_u = (uint16_t)(Energy.active_power[0]); - - if (Settings.energy_power_delta) { - uint16_t delta = abs(Energy.power_history[0] - energy_power_u); - if (delta > 0) { - if (Settings.energy_power_delta < 101) { - uint16_t min_power = (Energy.power_history[0] > energy_power_u) ? energy_power_u : Energy.power_history[0]; - if (0 == min_power) { min_power++; } - if (((delta * 100) / min_power) > Settings.energy_power_delta) { - Energy.power_delta = true; - } - } else { - if (delta > (Settings.energy_power_delta -100)) { - Energy.power_delta = true; - } - } - if (Energy.power_delta) { - Energy.power_history[1] = Energy.active_power[0]; - Energy.power_history[2] = Energy.active_power[0]; - } - } - } - Energy.power_history[0] = Energy.power_history[1]; - Energy.power_history[1] = Energy.power_history[2]; - Energy.power_history[2] = energy_power_u; - - if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { - uint16_t energy_voltage_u = (uint16_t)(Energy.voltage[0]); - uint16_t energy_current_u = (uint16_t)(Energy.current[0] * 1000); - - DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); - - Response_P(PSTR("{")); - bool flag; - bool jsonflg = false; - if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, Energy.max_power_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, Energy.min_current_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, Energy.max_current_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (jsonflg) { - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); - EnergyMqttShow(); - } - } - -#ifdef USE_ENERGY_POWER_LIMIT - - if (Settings.energy_max_power_limit) { - if (Energy.active_power[0] > Settings.energy_max_power_limit) { - if (!Energy.mplh_counter) { - Energy.mplh_counter = Settings.energy_max_power_limit_hold; - } else { - Energy.mplh_counter--; - if (!Energy.mplh_counter) { - ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":%d}"), energy_power_u); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); - if (!Energy.mplr_counter) { - Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; - } - Energy.mplw_counter = Settings.energy_max_power_limit_window; - } - } - } - else if (power && (energy_power_u <= Settings.energy_max_power_limit)) { - Energy.mplh_counter = 0; - Energy.mplr_counter = 0; - Energy.mplw_counter = 0; - } - if (!power) { - if (Energy.mplw_counter) { - Energy.mplw_counter--; - } else { - if (Energy.mplr_counter) { - Energy.mplr_counter--; - if (Energy.mplr_counter) { - ResponseTime_P(PSTR(",\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); - RestorePower(true, SRC_MAXPOWER); - } else { - ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); - } - } - } - } - } - - - if (Settings.energy_max_energy) { - uint16_t energy_daily_u = (uint16_t)(Energy.daily * 1000); - if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { - Energy.max_energy_state = 1; - ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); - RestorePower(true, SRC_MAXENERGY); - } - else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { - Energy.max_energy_state = 2; - char stemp[FLOATSZ]; - dtostrfd(Energy.daily, 3, stemp); - ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":%s}"), stemp); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); - } - } -#endif - - if (Energy.power_delta) { EnergyMqttShow(); } -} - -void EnergyMqttShow(void) -{ - - int tele_period_save = tele_period; - tele_period = 2; - mqtt_data[0] = '\0'; - ResponseAppendTime(); - EnergyShow(true); - tele_period = tele_period_save; - ResponseJsonEnd(); - MqttPublishTeleSensor(); - Energy.power_delta = false; -} -#endif - -void EnergyEverySecond(void) -{ - - if (global_update) { - if (power && (global_temperature != 9999) && (global_temperature > Settings.param[P_OVER_TEMP])) { - SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); - } - } - - - uint32_t data_valid = Energy.phase_count; - for (uint32_t i = 0; i < Energy.phase_count; i++) { - if (Energy.data_valid[i] <= ENERGY_WATCHDOG) { - Energy.data_valid[i]++; - if (Energy.data_valid[i] > ENERGY_WATCHDOG) { - - Energy.voltage[i] = 0; - Energy.current[i] = 0; - Energy.active_power[i] = 0; - if (!isnan(Energy.apparent_power[i])) { Energy.apparent_power[i] = 0; } - if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; } - if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; } - if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; } - - data_valid--; - } - } - } - if (!data_valid) { - if (!isnan(Energy.export_active)) { Energy.export_active = 0; } - Energy.start_energy = 0; - - XnrgCall(FUNC_ENERGY_RESET); - } - -#ifdef USE_ENERGY_MARGIN_DETECTION - EnergyMarginCheck(); -#endif -} - - - - - -void EnergyCommandCalResponse(uint32_t nvalue) -{ - snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); - ResponseCmndNumber(nvalue); -} - -void CmndEnergyReset(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - char *p; - unsigned long lnum = strtoul(XdrvMailbox.data, &p, 10); - if (p != XdrvMailbox.data) { - switch (XdrvMailbox.index) { - case 1: - - Energy.kWhtoday_offset = lnum *100; - Energy.kWhtoday = 0; - Energy.kWhtoday_delta = 0; - Energy.start_energy = 0; - Energy.period = Energy.kWhtoday_offset; - Settings.energy_kWhtoday = Energy.kWhtoday_offset; - RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset; - Energy.daily = (float)Energy.kWhtoday_offset / 100000; - if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) { - Settings.energy_kWhtotal_time = LocalTime(); - } - break; - case 2: - - Settings.energy_kWhyesterday = lnum *100; - break; - case 3: - - RtcSettings.energy_kWhtotal = lnum *100; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - - Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); - RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); - break; - } - } - } - else if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { - uint32_t values[2] = { 0 }; - uint32_t position = ParseParameters(2, values); - values[0] *= 100; - values[1] *= 100; - - switch (XdrvMailbox.index) - { - case 4: - - if (position > 0) { - RtcSettings.energy_usage.usage1_kWhtotal = values[0]; - } - if (position > 1) { - RtcSettings.energy_usage.usage2_kWhtotal = values[1]; - } - Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; - Settings.energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal; - break; - case 5: - - if (position > 0) { - RtcSettings.energy_usage.return1_kWhtotal = values[0]; - } - if (position > 1) { - RtcSettings.energy_usage.return2_kWhtotal = values[1]; - } - Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal; - Settings.energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal; - break; - } - } - - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; - - char energy_total_chr[FLOATSZ]; - dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); - char energy_daily_chr[FLOATSZ]; - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); - char energy_yesterday_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - - char energy_usage1_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage1_chr); - char energy_usage2_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage2_chr); - char energy_return1_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return1_chr); - char energy_return2_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return2_chr); - - Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s,\"" D_JSON_USAGE "\":[%s,%s],\"" D_JSON_EXPORT "\":[%s,%s]}}"), - XdrvMailbox.command, energy_total_chr, energy_yesterday_chr, energy_daily_chr, energy_usage1_chr, energy_usage2_chr, energy_return1_chr, energy_return2_chr); -} - -void CmndTariff(void) -{ - - - - - - - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - uint32_t tariff = XdrvMailbox.index -1; - uint32_t time_type = 0; - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - while ((str != nullptr) && (time_type < 2)) { - char *q; - uint32_t value = strtol(str, &q, 10); - Settings.tariff[tariff][time_type] = value; - if (value < 24) { - Settings.tariff[tariff][time_type] *= 60; - char *minute = strtok_r(nullptr, ":", &q); - if (minute) { - value = strtol(minute, nullptr, 10); - if (value > 59) { - value = 59; - } - Settings.tariff[tariff][time_type] += value; - } - } - if (Settings.tariff[tariff][time_type] > 1439) { - Settings.tariff[tariff][time_type] = 1439; - } - str = strtok_r(nullptr, ", ", &p); - time_type++; - } - } - else if (XdrvMailbox.index == 9) { - Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; - } - Response_P(PSTR("{\"%s\":{\"Off-Peak\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Standard\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Weekend\":\"%s\"}}"), - XdrvMailbox.command, - GetMinuteTime(Settings.tariff[0][0]).c_str(),GetMinuteTime(Settings.tariff[0][1]).c_str(), - GetMinuteTime(Settings.tariff[1][0]).c_str(),GetMinuteTime(Settings.tariff[1][1]).c_str(), - GetStateText(Settings.flag3.energy_weekend)); -} - -void CmndPowerCal(void) -{ - Energy.command_code = CMND_POWERCAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_power_calibration = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_power_calibration); - } -} - -void CmndVoltageCal(void) -{ - Energy.command_code = CMND_VOLTAGECAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_voltage_calibration = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_voltage_calibration); - } -} - -void CmndCurrentCal(void) -{ - Energy.command_code = CMND_CURRENTCAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_current_calibration = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_current_calibration); - } -} - -void CmndPowerSet(void) -{ - Energy.command_code = CMND_POWERSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_power_calibration); - } -} - -void CmndVoltageSet(void) -{ - Energy.command_code = CMND_VOLTAGESET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_voltage_calibration); - } -} - -void CmndCurrentSet(void) -{ - Energy.command_code = CMND_CURRENTSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_current_calibration); - } -} - -void CmndFrequencySet(void) -{ - Energy.command_code = CMND_FREQUENCYSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_frequency_calibration); - } -} - -void CmndModuleAddress(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) { - Energy.command_code = CMND_MODULEADDRESS; - if (XnrgCall(FUNC_COMMAND)) { - ResponseCmndDone(); - } - } -} - -#ifdef USE_ENERGY_MARGIN_DETECTION -void CmndPowerDelta(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { - Settings.energy_power_delta = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_power_delta); -} - -void CmndPowerLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_min_power = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_power); -} - -void CmndPowerHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power); -} - -void CmndVoltageLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { - Settings.energy_min_voltage = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_voltage); -} - -void CmndVoltageHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { - Settings.energy_max_voltage = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_voltage); -} - -void CmndCurrentLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { - Settings.energy_min_current = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_current); -} - -void CmndCurrentHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { - Settings.energy_max_current = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_current); -} - -#ifdef USE_ENERGY_POWER_LIMIT -void CmndMaxPower(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit); -} - -void CmndMaxPowerHold(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit_hold); -} - -void CmndMaxPowerWindow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit_window); -} - -void CmndSafePower(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_safe_limit = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit); -} - -void CmndSafePowerHold(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold); -} - -void CmndSafePowerWindow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) { - Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit_window); -} - -void CmndMaxEnergy(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_energy = XdrvMailbox.payload; - Energy.max_energy_state = 3; - } - ResponseCmndNumber(Settings.energy_max_energy); -} - -void CmndMaxEnergyStart(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { - Settings.energy_max_energy_start = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_energy_start); -} -#endif -#endif - -void EnergySnsInit(void) -{ - XnrgCall(FUNC_INIT); - - if (energy_flg) { - if (RtcSettingsValid()) { - Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; - } - else if (RtcTime.day_of_year == Settings.energy_kWhdoy) { - Energy.kWhtoday_offset = Settings.energy_kWhtoday; - } - else { - Energy.kWhtoday_offset = 0; - } - Energy.kWhtoday = 0; - Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday_offset; - EnergyUpdateToday(); - ticker_energy.attach_ms(200, Energy200ms); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_SNS1[] PROGMEM = - "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" - "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" - "{s}" D_POWER_FACTOR "{m}%s{e}"; - -const char HTTP_ENERGY_SNS2[] PROGMEM = - "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; - -const char HTTP_ENERGY_SNS3[] PROGMEM = - "{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; -#endif - -char* EnergyFormatIndex(char* result, char* input, bool json, uint32_t index, bool single = false) -{ - char layout[16]; - GetTextIndexed(layout, sizeof(layout), (index -1) + (3 * json), kEnergyPhases); - switch (index) { - case 2: - snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ); - break; - case 3: - snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ, input + FLOATSZ + FLOATSZ); - break; - default: - snprintf_P(result, FLOATSZ *3, input); - } - return result; -} - -char* EnergyFormat(char* result, char* input, bool json, bool single = false) -{ - uint8_t index = (single) ? 1 : Energy.phase_count; - return EnergyFormatIndex(result, input, json, index, single); -} - -void EnergyShow(bool json) -{ - for (uint32_t i = 0; i < Energy.phase_count; i++) { - if (Energy.voltage_common) { - Energy.voltage[i] = Energy.voltage[0]; - } - } - - float power_factor_knx = Energy.power_factor[0]; - - char apparent_power_chr[Energy.phase_count][FLOATSZ]; - char reactive_power_chr[Energy.phase_count][FLOATSZ]; - char power_factor_chr[Energy.phase_count][FLOATSZ]; - char frequency_chr[Energy.phase_count][FLOATSZ]; - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - for (uint32_t i = 0; i < Energy.phase_count; i++) { - float apparent_power = Energy.apparent_power[i]; - if (isnan(apparent_power)) { - apparent_power = Energy.voltage[i] * Energy.current[i]; - } - if (apparent_power < Energy.active_power[i]) { - Energy.active_power[i] = apparent_power; - } - - float power_factor = Energy.power_factor[i]; - if (isnan(power_factor)) { - power_factor = (Energy.active_power[i] && apparent_power) ? Energy.active_power[i] / apparent_power : 0; - if (power_factor > 1) { - power_factor = 1; - } - } - if (0 == i) { power_factor_knx = power_factor; } - - float reactive_power = Energy.reactive_power[i]; - if (isnan(reactive_power)) { - reactive_power = 0; - uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(Energy.active_power[i] * 100)) / 10; - if ((Energy.current[i] > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { - - - reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(Energy.active_power[i] * Energy.active_power[i] * 100))) / 10; - } - } - - dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr[i]); - dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr[i]); - dtostrfd(power_factor, 2, power_factor_chr[i]); - } - } - for (uint32_t i = 0; i < Energy.phase_count; i++) { - float frequency = Energy.frequency[i]; - if (isnan(Energy.frequency[i])) { - frequency = 0; - } - dtostrfd(frequency, Settings.flag2.frequency_resolution, frequency_chr[i]); - } - } - - char voltage_chr[Energy.phase_count][FLOATSZ]; - char current_chr[Energy.phase_count][FLOATSZ]; - char active_power_chr[Energy.phase_count][FLOATSZ]; - for (uint32_t i = 0; i < Energy.phase_count; i++) { - dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]); - dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]); - dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]); - } - - char energy_daily_chr[FLOATSZ]; - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); - char energy_yesterday_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - - char energy_total_chr[3][FLOATSZ]; - dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr[0]); - char export_active_chr[3][FLOATSZ]; - dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]); - uint8_t energy_total_fields = 1; - - if (Settings.tariff[0][0] != Settings.tariff[1][0]) { - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[2]); - energy_total_fields = 3; - } - - char value_chr[FLOATSZ *3]; - char value2_chr[FLOATSZ *3]; - char value3_chr[FLOATSZ *3]; - - if (json) { - bool show_energy_period = (0 == tele_period); - - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), - GetDateAndTime(DT_ENERGY).c_str(), - EnergyFormatIndex(value_chr, energy_total_chr[0], json, energy_total_fields), - energy_yesterday_chr, - energy_daily_chr); - - if (!isnan(Energy.export_active)) { - ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), - EnergyFormatIndex(value_chr, export_active_chr[0], json, energy_total_fields)); - } - - if (show_energy_period) { - float energy = 0; - if (Energy.period) { - energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100; - } - Energy.period = RtcSettings.energy_kWhtoday; - char energy_period_chr[FLOATSZ]; - dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); - ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); - } - ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"), - EnergyFormat(value_chr, active_power_chr[0], json)); - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"), - EnergyFormat(value_chr, apparent_power_chr[0], json), - EnergyFormat(value2_chr, reactive_power_chr[0], json), - EnergyFormat(value3_chr, power_factor_chr[0], json)); - } - if (!isnan(Energy.frequency[0])) { - ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), - EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); - } - } - if (Energy.voltage_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), - EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); - } - if (Energy.current_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), - EnergyFormat(value_chr, current_chr[0], json)); - } - XnrgCall(FUNC_JSON_APPEND); - ResponseJsonEnd(); - -#ifdef USE_DOMOTICZ - if (show_energy_period) { - dtostrfd(Energy.total * 1000, 1, energy_total_chr[0]); - DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr[0]); - - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_total_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_total_chr[2]); - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, export_active_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, export_active_chr[2]); - DomoticzSensorP1SmartMeter(energy_total_chr[1], energy_total_chr[2], export_active_chr[1], export_active_chr[2], (int)Energy.active_power[0]); - - if (Energy.voltage_available) { - DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); - } - if (Energy.current_available) { - DomoticzSensor(DZ_CURRENT, current_chr[0]); - } - } -#endif -#ifdef USE_KNX - if (show_energy_period) { - if (Energy.voltage_available) { - KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage[0]); - } - if (Energy.current_available) { - KnxSensor(KNX_ENERGY_CURRENT, Energy.current[0]); - } - KnxSensor(KNX_ENERGY_POWER, Energy.active_power[0]); - if (!Energy.type_dc) { - KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor_knx); - } - KnxSensor(KNX_ENERGY_DAILY, Energy.daily); - KnxSensor(KNX_ENERGY_TOTAL, Energy.total); - KnxSensor(KNX_ENERGY_START, Energy.start_energy); - } -#endif -#ifdef USE_WEBSERVER - } else { - if (Energy.voltage_available) { - WSContentSend_PD(HTTP_SNS_VOLTAGE, EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); - } - if (Energy.current_available) { - WSContentSend_PD(HTTP_SNS_CURRENT, EnergyFormat(value_chr, current_chr[0], json)); - } - WSContentSend_PD(HTTP_SNS_POWER, EnergyFormat(value_chr, active_power_chr[0], json)); - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - WSContentSend_PD(HTTP_ENERGY_SNS1, EnergyFormat(value_chr, apparent_power_chr[0], json), - EnergyFormat(value2_chr, reactive_power_chr[0], json), - EnergyFormat(value3_chr, power_factor_chr[0], json)); - } - if (!isnan(Energy.frequency[0])) { - WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), - EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); - } - } - WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]); - if (!isnan(Energy.export_active)) { - WSContentSend_PD(HTTP_ENERGY_SNS3, export_active_chr[0]); - } - - XnrgCall(FUNC_WEB_SENSOR); -#endif - } -} - - - - - -bool Xdrv03(uint8_t function) -{ - bool result = false; - - if (FUNC_PRE_INIT == function) { - energy_flg = ENERGY_NONE; - XnrgCall(FUNC_PRE_INIT); - } - else if (energy_flg) { - switch (function) { - case FUNC_LOOP: - XnrgCall(FUNC_LOOP); - break; - case FUNC_EVERY_250_MSECOND: - XnrgCall(FUNC_EVERY_250_MSECOND); - break; - case FUNC_SERIAL: - result = XnrgCall(FUNC_SERIAL); - break; -#ifdef USE_ENERGY_MARGIN_DETECTION - case FUNC_SET_POWER: - Energy.power_steady_counter = 2; - break; -#endif - case FUNC_COMMAND: - result = DecodeCommand(kEnergyCommands, EnergyCommand); - break; - } - } - return result; -} - -bool Xsns03(uint8_t function) -{ - bool result = false; - - if (energy_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - EnergyEverySecond(); - break; - case FUNC_JSON_APPEND: - EnergyShow(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - EnergyShow(false); - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - EnergySaveState(); - break; - case FUNC_INIT: - EnergySnsInit(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" -#ifdef USE_LIGHT -# 124 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" -#define XDRV_04 4 - - -enum LightSchemes { LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX }; - -const uint8_t LIGHT_COLOR_SIZE = 25; - -const char kLightCommands[] PROGMEM = "|" - D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" - D_CMND_RGBWWTABLE "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" - D_CMND_WHITE "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; - -void (* const LightCommand[])(void) PROGMEM = { - &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndDimmerRange, &CmndLedTable, &CmndFade, - &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, - &CmndWhite, &CmndChannel, &CmndHsbColor, &CmndUndocA }; - - -enum LightColorModes { - LCM_RGB = 1, LCM_CT = 2, LCM_BOTH = 3 }; - -struct LRgbColor { - uint8_t R, G, B; -}; -const uint8_t MAX_FIXED_COLOR = 12; -const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = - { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; - -struct LWColor { - uint8_t W; -}; -const uint8_t MAX_FIXED_WHITE = 4; -const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; - -struct LCwColor { - uint8_t C, W; -}; -const uint8_t MAX_FIXED_COLD_WARM = 4; -const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; - - -const uint16_t CT_MIN = 153; -const uint16_t CT_MAX = 500; - -const uint16_t CT_MIN_ALEXA = 200; -const uint16_t CT_MAX_ALEXA = 380; - - - - - - -typedef struct gamma_table_t { - uint16_t to_src; - uint16_t to_gamma; -} gamma_table_t; - -const gamma_table_t gamma_table[] = { - { 1, 1 }, - { 4, 1 }, - { 209, 13 }, - { 312, 41 }, - { 457, 106 }, - { 626, 261 }, - { 762, 450 }, - { 895, 703 }, - { 1023, 1023 }, - { 0xFFFF, 0xFFFF } -}; - - -const gamma_table_t gamma_table_fast[] = { - { 384, 192 }, - { 768, 576 }, - { 1023, 1023 }, - { 0xFFFF, 0xFFFF } -}; -# 248 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" -struct LIGHT { - uint32_t strip_timer_counter = 0; - power_t power = 0; - - uint16_t wakeup_counter = 0; - - uint8_t entry_color[LST_MAX]; - uint8_t current_color[LST_MAX]; - uint8_t new_color[LST_MAX]; - uint8_t last_color[LST_MAX]; - uint8_t color_remap[LST_MAX]; - - uint8_t wheel = 0; - uint8_t random = 0; - uint8_t subtype = 0; - uint8_t device = 0; - uint8_t old_power = 1; - uint8_t wakeup_active = 0; - uint8_t wakeup_dimmer = 0; - uint8_t fixed_color_index = 1; - uint8_t pwm_offset = 0; - uint8_t max_scheme = LS_MAX -1; - - bool update = true; - bool pwm_multi_channels = false; - - bool fade_initialized = false; - bool fade_running = false; - uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; - uint16_t fade_cur_10[LST_MAX]; - uint16_t fade_end_10[LST_MAX]; - uint16_t fade_duration = 0; - uint32_t fade_start = 0; -} Light; - -power_t LightPower(void) -{ - return Light.power; -} - - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -power_t LightPowerIRAM(void) ICACHE_RAM_ATTR; -#endif - -power_t LightPowerIRAM(void) -{ - return Light.power; -} - -uint8_t LightDevice(void) -{ - return Light.device; -} - -static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) { - return (a < b && a < c) ? a : (b < c) ? b : c; -} -# 344 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" -class LightStateClass { - private: - uint16_t _hue = 0; - uint8_t _sat = 255; - uint8_t _briRGB = 255; - - uint8_t _r = 255; - uint8_t _g = 255; - uint8_t _b = 255; - - uint8_t _subtype = 0; - uint16_t _ct = CT_MIN; - uint8_t _wc = 255; - uint8_t _ww = 0; - uint8_t _briCT = 255; - - uint8_t _color_mode = LCM_RGB; - - - - - - uint16_t _ct_min_range = CT_MIN; - uint16_t _ct_max_range = CT_MAX; - - public: - LightStateClass() { - - } - - void setSubType(uint8_t sub_type) { - _subtype = sub_type; - } -# 386 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" - uint8_t setColorMode(uint8_t cm) { - uint8_t prev_cm = _color_mode; - if (cm < LCM_RGB) { cm = LCM_RGB; } - if (cm > LCM_BOTH) { cm = LCM_BOTH; } - uint8_t maxbri = (_briRGB >= _briCT) ? _briRGB : _briCT; - - switch (_subtype) { - case LST_COLDWARM: - _color_mode = LCM_CT; - break; - - case LST_NONE: - case LST_SINGLE: - case LST_RGB: - default: - _color_mode = LCM_RGB; - break; - - case LST_RGBW: - case LST_RGBCW: - _color_mode = cm; - break; - } - if (LCM_RGB == _color_mode) { - _briCT = 0; - if (0 == _briRGB) { _briRGB = maxbri; } - } - if (LCM_CT == _color_mode) { - _briRGB = 0; - if (0 == _briCT) { _briCT = maxbri; } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setColorMode prev_cm (%d) req_cm (%d) new_cm (%d)", prev_cm, cm, _color_mode); -#endif - return prev_cm; - } - - inline uint8_t getColorMode() { - return _color_mode; - } - - void addRGBMode() { - setColorMode(_color_mode | LCM_RGB); - } - void addCTMode() { - setColorMode(_color_mode | LCM_CT); - } - - - void getRGB(uint8_t *r, uint8_t *g, uint8_t *b) { - if (r) { *r = _r; } - if (g) { *g = _g; } - if (b) { *b = _b; } - } - - - - void getCW(uint8_t *rc, uint8_t *rw) { - if (rc) { *rc = _wc; } - if (rw) { *rw = _ww; } - } - - - void getActualRGBCW(uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *c, uint8_t *w) { - bool rgb_channels_on = _color_mode & LCM_RGB; - bool ct_channels_on = _color_mode & LCM_CT; - - if (r) { *r = rgb_channels_on ? changeUIntScale(_r, 0, 255, 0, _briRGB) : 0; } - if (g) { *g = rgb_channels_on ? changeUIntScale(_g, 0, 255, 0, _briRGB) : 0; } - if (b) { *b = rgb_channels_on ? changeUIntScale(_b, 0, 255, 0, _briRGB) : 0; } - - if (c) { *c = ct_channels_on ? changeUIntScale(_wc, 0, 255, 0, _briCT) : 0; } - if (w) { *w = ct_channels_on ? changeUIntScale(_ww, 0, 255, 0, _briCT) : 0; } - } - - uint8_t getChannels(uint8_t *channels) { - getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); - } - - void getChannelsRaw(uint8_t *channels) { - channels[0] = _r; - channels[1] = _g; - channels[2] = _b; - channels[3] = _wc; - channels[4] = _ww; - } - - void getHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { - if (hue) { *hue = _hue; } - if (sat) { *sat = _sat; } - if (bri) { *bri = _briRGB; } - } - - - uint8_t getBri(void) { - - return (_briRGB >= _briCT) ? _briRGB : _briCT; - } - - - inline uint8_t getBriCT() { - return _briCT; - } - - static inline uint8_t DimmerToBri(uint8_t dimmer) { - return changeUIntScale(dimmer, 0, 100, 0, 255); - } - static uint8_t BriToDimmer(uint8_t bri) { - uint8_t dimmer = changeUIntScale(bri, 0, 255, 0, 100); - - if ((dimmer == 0) && (bri > 0)) { dimmer = 1; } - return dimmer; - } - - uint8_t getDimmer(uint32_t mode = 0) { - uint8_t bri; - switch (mode) { - case 1: - bri = getBriRGB(); - break; - case 2: - bri = getBriCT(); - break; - default: - bri = getBri(); - break; - } - return BriToDimmer(bri); - } - - inline uint16_t getCT() const { - return _ct; - } - - - uint16_t getCT10bits() const { - return changeUIntScale(_ct, _ct_min_range, _ct_max_range, 0, 1023); - } - - inline void setCTRange(uint16_t ct_min_range, uint16_t ct_max_range) { - _ct_min_range = ct_min_range; - _ct_max_range = ct_max_range; - } - - inline void getCTRange(uint16_t *ct_min_range, uint16_t *ct_max_range) const { - if (ct_min_range) { *ct_min_range = _ct_min_range; } - if (ct_max_range) { *ct_max_range = _ct_max_range; } - } - - - void getXY(float *x, float *y) { - RgbToXy(_r, _g, _b, x, y); - } - - - - void setBri(uint8_t bri) { - setBriRGB(_color_mode & LCM_RGB ? bri : 0); - setBriCT(_color_mode & LCM_CT ? bri : 0); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setBri RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - } - - - uint8_t setBriRGB(uint8_t bri_rgb) { - uint8_t prev_bri = _briRGB; - _briRGB = bri_rgb; - if (bri_rgb > 0) { addRGBMode(); } - return prev_bri; - } - - - uint8_t setBriCT(uint8_t bri_ct) { - uint8_t prev_bri = _briCT; - _briCT = bri_ct; - if (bri_ct > 0) { addCTMode(); } - return prev_bri; - } - - inline uint8_t getBriRGB() { - return _briRGB; - } - - void setDimmer(uint8_t dimmer) { - setBri(DimmerToBri(dimmer)); - } - - void setCT(uint16_t ct) { - if (0 == ct) { - - setColorMode(LCM_RGB); - } else { - ct = (ct < CT_MIN ? CT_MIN : (ct > CT_MAX ? CT_MAX : ct)); - _ww = changeUIntScale(ct, _ct_min_range, _ct_max_range, 0, 255); - _wc = 255 - _ww; - _ct = ct; - addCTMode(); - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCT RGB raw (%d %d %d) HS (%d %d) briRGB (%d) briCT (%d) CT (%d)", _r, _g, _b, _hue, _sat, _briRGB, _briCT, _ct); -#endif - } -# 604 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" - void setCW(uint8_t c, uint8_t w, bool free_range = false) { - uint16_t max = (w > c) ? w : c; - uint16_t sum = c + w; - - if (0 == max) { - _briCT = 0; - setColorMode(LCM_RGB); - } else { - if (!free_range) { - - _ww = changeUIntScale(w, 0, sum, 0, 255); - _wc = 255 - _ww; - } else { - _ww = changeUIntScale(w, 0, max, 0, 255); - _wc = changeUIntScale(c, 0, max, 0, 255); - } - _ct = changeUIntScale(w, 0, sum, _ct_min_range, _ct_max_range); - addCTMode(); - if (_color_mode & LCM_CT) { _briCT = free_range ? max : (sum > 255 ? 255 : sum); } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCW CW (%d %d) CT (%d) briCT (%d)", c, w, _ct, _briCT); -#endif - } - - - uint8_t setRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { - uint16_t hue; - uint8_t sat; -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB input (%d %d %d)", r, g, b); -#endif - - uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; - - if (0 == max) { - r = g = b = 255; - setColorMode(LCM_CT); - } else { - if (255 > max) { - - r = changeUIntScale(r, 0, max, 0, 255); - g = changeUIntScale(g, 0, max, 0, 255); - b = changeUIntScale(b, 0, max, 0, 255); - } - addRGBMode(); - } - if (!keep_bri) { - _briRGB = (_color_mode & LCM_RGB) ? max : 0; - } - - RgbToHsb(r, g, b, &hue, &sat, nullptr); - _r = r; - _g = g; - _b = b; - _hue = hue; - _sat = sat; -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - return max; - } - - void setHS(uint16_t hue, uint8_t sat) { - uint8_t r, g, b; - HsToRgb(hue, sat, &r, &g, &b); - _r = r; - _g = g; - _b = b; - _hue = hue; - _sat = sat; - addRGBMode(); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS HS (%d %d) rgb (%d %d %d)", hue, sat, r, g, b); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - } - - - - void setChannelsRaw(uint8_t *channels) { - _r = channels[0]; - _g = channels[1]; - _b = channels[2]; - _wc = channels[3]; - _ww = channels[4]; -} - - - - - void setChannels(uint8_t *channels) { - setRGB(channels[0], channels[1], channels[2]); - setCW(channels[3], channels[4], true); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels (%d %d %d %d %d)", - channels[0], channels[1], channels[2], channels[3], channels[4]); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels CT (%d) briRGB (%d) briCT (%d)", _ct, _briRGB, _briCT); -#endif - } - - - static void RgbToHsb(uint8_t r, uint8_t g, uint8_t b, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri); - static void HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); - static void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y); - static void XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb); - -}; -# 720 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_04_light.ino" -void LightStateClass::RgbToHsb(uint8_t ir, uint8_t ig, uint8_t ib, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri) { - uint32_t r = ir; - uint32_t g = ig; - uint32_t b = ib; - uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; - uint32_t min = (r < g && r < b) ? r : (g < b) ? g : b; - uint32_t d = max - min; - - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = max; - - if (d != 0) { - sat = changeUIntScale(d, 0, max, 0, 255); - if (r == max) { - hue = (g > b) ? changeUIntScale(g-b,0,d,0,60) : 360 - changeUIntScale(b-g,0,d,0,60); - } else if (g == max) { - hue = (b > r) ? 120 + changeUIntScale(b-r,0,d,0,60) : 120 - changeUIntScale(r-b,0,d,0,60); - } else { - hue = (r > g) ? 240 + changeUIntScale(r-g,0,d,0,60) : 240 - changeUIntScale(g-r,0,d,0,60); - } - hue = hue % 360; - } - - if (r_hue) *r_hue = hue; - if (r_sat) *r_sat = sat; - if (r_bri) *r_bri = bri; - -} - -void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { - uint32_t r = 255; - uint32_t g = 255; - uint32_t b = 255; - - hue = hue % 360; - - if (sat > 0) { - uint32_t i = hue / 60; - uint32_t f = hue % 60; - uint32_t q = 255 - changeUIntScale(f, 0, 60, 0, sat); - uint32_t p = 255 - sat; - uint32_t t = 255 - changeUIntScale(60 - f, 0, 60, 0, sat); - - switch (i) { - case 0: - - g = t; - b = p; - break; - case 1: - r = q; - - b = p; - break; - case 2: - r = p; - - b = t; - break; - case 3: - r = p; - g = q; - - break; - case 4: - r = t; - g = p; - - break; - default: - - g = p; - b = q; - break; - } - } - if (r_r) *r_r = r; - if (r_g) *r_g = g; - if (r_b) *r_b = b; -} - -#define POW FastPrecisePowf - -void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) { - float x = 0.31271f; - float y = 0.32902f; - - if (i_r + i_b + i_g > 0) { - float r = (float)i_r / 255.0f; - float g = (float)i_g / 255.0f; - float b = (float)i_b / 255.0f; - - - r = (r > 0.04045f) ? POW((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f); - g = (g > 0.04045f) ? POW((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f); - b = (b > 0.04045f) ? POW((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f); - - - - float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; - float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; - float Z = r * 0.000000f + g * 0.053077f + b * 1.035763f; - - x = X / (X + Y + Z); - y = Y / (X + Y + Z); - - } - if (r_x) *r_x = x; - if (r_y) *r_y = y; -} - -void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb) -{ - x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x)); - y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y)); - float z = 1.0f - x - y; - - float X = x / y; - float Z = z / y; - - - - float r = X * 3.2406f - 1.5372f - Z * 0.4986f; - float g = -X * 0.9689f + 1.8758f + Z * 0.0415f; - float b = X * 0.0557f - 0.2040f + Z * 1.0570f; - float max = (r > g && r > b) ? r : (g > b) ? g : b; - r = r / max; - g = g / max; - b = b / max; - r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * POW(r, (1.0f / 2.4f)) - 0.055f; - g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * POW(g, (1.0f / 2.4f)) - 0.055f; - b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * POW(b, (1.0f / 2.4f)) - 0.055f; - - - - - - int32_t ir = r * 255.0f + 0.5f; - int32_t ig = g * 255.0f + 0.5f; - int32_t ib = b * 255.0f + 0.5f; - if (rr) { *rr = (ir > 255 ? 255: (ir < 0 ? 0 : ir)); } - if (rg) { *rg = (ig > 255 ? 255: (ig < 0 ? 0 : ig)); } - if (rb) { *rb = (ib > 255 ? 255: (ib < 0 ? 0 : ib)); } -} - -class LightControllerClass { -private: - LightStateClass *_state; - - - bool _ct_rgb_linked = true; - bool _pwm_multi_channels = false; - -public: - LightControllerClass(LightStateClass& state) { - _state = &state; - } - - void setSubType(uint8_t sub_type) { - _state->setSubType(sub_type); - } - - inline bool setCTRGBLinked(bool ct_rgb_linked) { - bool prev = _ct_rgb_linked; - if (_pwm_multi_channels) { - _ct_rgb_linked = false; - } else { - _ct_rgb_linked = ct_rgb_linked; - } - return prev; - } - - void setAlexaCTRange(bool alexa_ct_range) { - - if (alexa_ct_range) { - _state->setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA); - } else { - _state->setCTRange(CT_MIN, CT_MAX); - } - } - - inline bool isCTRGBLinked() { - return _ct_rgb_linked; - } - - inline bool setPWMMultiChannel(bool pwm_multi_channels) { - bool prev = _pwm_multi_channels; - _pwm_multi_channels = pwm_multi_channels; - if (pwm_multi_channels) setCTRGBLinked(false); - return prev; - } - - inline bool isPWMMultiChannel(void) { - return _pwm_multi_channels; - } - -#ifdef DEBUG_LIGHT - void debugLogs() { - uint8_t r,g,b,c,w; - _state->getActualRGBCW(&r,&g,&b,&c,&w); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs rgb (%d %d %d) cw (%d %d)", - r, g, b, c, w); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs lightCurrent (%d %d %d %d %d)", - Light.current_color[0], Light.current_color[1], Light.current_color[2], - Light.current_color[3], Light.current_color[4]); - } -#endif - - void loadSettings() { -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings Settings.light_color (%d %d %d %d %d - %d)", - Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], - Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", - light_type, Light.subtype); -#endif - if (_pwm_multi_channels) { - _state->setChannelsRaw(Settings.light_color); - } else { - - _state->setCW(Settings.light_color[3], Settings.light_color[4], true); - _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); - - - - uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); - if (Settings.light_color[0] + Settings.light_color[1] + Settings.light_color[2] > 0) { - - - if ( (DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) && - (DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) { - _state->setColorMode(LCM_RGB); - } - _state->setBriRGB(bri); - } else { - _state->setBriCT(bri); - } - } - } - - void changeCTB(uint16_t new_ct, uint8_t briCT) { - - - - - - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBW > Light.subtype)) { - return; - } - _state->setCT(new_ct); - _state->setBriCT(briCT); - if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } - saveSettings(); - calcLevels(); - - } - - void changeDimmer(uint8_t dimmer, uint32_t mode = 0) { - uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); - switch (mode) { - case 1: - changeBriRGB(bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - break; - case 2: - changeBriCT(bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } - break; - default: - changeBri(bri); - break; - } - } - - void changeBri(uint8_t bri) { - _state->setBri(bri); - saveSettings(); - calcLevels(); - } - - void changeBriRGB(uint8_t bri) { - _state->setBriRGB(bri); - saveSettings(); - calcLevels(); - } - - void changeBriCT(uint8_t bri) { - _state->setBriCT(bri); - saveSettings(); - calcLevels(); - } - - void changeRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { - _state->setRGB(r, g, b, keep_bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - saveSettings(); - calcLevels(); - } - - - - void calcLevels(uint8_t *current_color = nullptr) { - uint8_t r,g,b,c,w,briRGB,briCT; - if (current_color == nullptr) { current_color = Light.current_color; } - - if (_pwm_multi_channels) { - _state->getChannelsRaw(current_color); - return; - } - - _state->getActualRGBCW(&r,&g,&b,&c,&w); - briRGB = _state->getBriRGB(); - briCT = _state->getBriCT(); - - current_color[0] = current_color[1] = current_color[2] = 0; - current_color[3] = current_color[4] = 0; - switch (Light.subtype) { - case LST_NONE: - current_color[0] = 255; - break; - case LST_SINGLE: - current_color[0] = briRGB; - break; - case LST_COLDWARM: - current_color[0] = c; - current_color[1] = w; - break; - case LST_RGBW: - case LST_RGBCW: - if (LST_RGBCW == Light.subtype) { - current_color[3] = c; - current_color[4] = w; - } else { - current_color[3] = briCT; - } - - case LST_RGB: - current_color[0] = r; - current_color[1] = g; - current_color[2] = b; - break; - } - } - - void changeHSB(uint16_t hue, uint8_t sat, uint8_t briRGB) { - _state->setHS(hue, sat); - _state->setBriRGB(briRGB); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - saveSettings(); - calcLevels(); - } - - - void saveSettings() { - if (Light.pwm_multi_channels) { - - _state->getChannelsRaw(Settings.light_color); - Settings.light_dimmer = 100; - } else { - uint8_t cm = _state->getColorMode(); - - memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); - if (LCM_RGB & cm) { - _state->getRGB(&Settings.light_color[0], &Settings.light_color[1], &Settings.light_color[2]); - Settings.light_dimmer = _state->BriToDimmer(_state->getBriRGB()); - - if (LCM_BOTH == cm) { - - _state->getActualRGBCW(nullptr, nullptr, nullptr, &Settings.light_color[3], &Settings.light_color[4]); - } - } else if (LCM_CT == cm) { - _state->getCW(&Settings.light_color[3], &Settings.light_color[4]); - Settings.light_dimmer = _state->BriToDimmer(_state->getBriCT()); - } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::saveSettings Settings.light_color (%d %d %d %d %d - %d)", - Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], - Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); -#endif - } - - - - - void changeChannels(uint8_t *channels) { - if (Light.pwm_multi_channels) { - _state->setChannelsRaw(channels); - } else if (LST_COLDWARM == Light.subtype) { - - uint8_t remapped_channels[5] = {0,0,0,channels[0],channels[1]}; - _state->setChannels(remapped_channels); - } else { - _state->setChannels(channels); - } - - saveSettings(); - calcLevels(); - } -}; - - - -LightStateClass light_state = LightStateClass(); -LightControllerClass light_controller = LightControllerClass(light_state); - - - - - -uint16_t change8to10(uint8_t v) { - return changeUIntScale(v, 0, 255, 0, 1023); -} - -uint8_t change10to8(uint16_t v) { - return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); -} - - - - - -uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { - uint16_t from_src = 0; - uint16_t from_gamma = 0; - - for (const gamma_table_t *gt = gt_ptr; ; gt++) { - uint16_t to_src = gt->to_src; - uint16_t to_gamma = gt->to_gamma; - if (v <= to_src) { - return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); - } - from_src = to_src; - from_gamma = to_gamma; - } -} - -uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) { - uint16_t from_src = 0; - uint16_t from_gamma = 0; - - for (const gamma_table_t *gt = gt_ptr; ; gt++) { - uint16_t to_src = gt->to_src; - uint16_t to_gamma = gt->to_gamma; - if (vg <= to_gamma) { - return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src); - } - from_src = to_src; - from_gamma = to_gamma; - } -} - - -uint16_t ledGamma10_10(uint16_t v) { - return ledGamma_internal(v, gamma_table); -} - -uint16_t ledGamma10(uint8_t v) { - return ledGamma10_10(change8to10(v)); -} - - -uint8_t ledGamma(uint8_t v) { - return change10to8(ledGamma10(v)); -} - - - -void LightPwmOffset(uint32_t offset) -{ - Light.pwm_offset = offset; -} - -bool LightModuleInit(void) -{ - light_type = LT_BASIC; - - if (Settings.flag.pwm_control) { - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 +i] < 99) { light_type++; } - } - } - - light_flg = 0; - if (XlgtCall(FUNC_MODULE_INIT)) { - - } - else if (SONOFF_BN == my_module_type) { - light_type = LT_PWM1; - } - else if (SONOFF_LED == my_module_type) { - if (!my_module.io[4]) { - pinMode(4, OUTPUT); - digitalWrite(4, LOW); - } - if (!my_module.io[5]) { - pinMode(5, OUTPUT); - digitalWrite(5, LOW); - } - if (!my_module.io[14]) { - pinMode(14, OUTPUT); - digitalWrite(14, LOW); - } - light_type = LT_PWM2; - } - - if (light_type > LT_BASIC) { - devices_present++; - } - - - if (Settings.flag3.pwm_multi_channels) { - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - if (0 == pwm_channels) { pwm_channels = 1; } - devices_present += pwm_channels - 1; - } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= (light_type & 7))) { - - devices_present++; - } - - return (light_type > LT_BASIC); -} - -void LightInit(void) -{ - Light.device = devices_present; - Light.subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; - - if (LST_RGBW <= Light.subtype) { - - - bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); - light_controller.setCTRGBLinked(ct_rgb_linked); - } - - if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) { - - light_controller.setPWMMultiChannel(true); - Light.device = devices_present - Light.subtype + 1; - } else if (!light_controller.isCTRGBLinked()) { - - Light.device--; - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", - Light.pwm_multi_channels, Light.subtype, Light.device, devices_present); -#endif - - light_controller.setSubType(Light.subtype); - light_controller.loadSettings(); - light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); - - if (LST_SINGLE == Light.subtype) { - Settings.light_color[0] = 255; - } - if (light_type < LT_PWM6) { - for (uint32_t i = 0; i < light_type; i++) { - Settings.pwm_value[i] = 0; - if (pin[GPIO_PWM1 +i] < 99) { - pinMode(pin[GPIO_PWM1 +i], OUTPUT); - } - } - if (pin[GPIO_ARIRFRCV] < 99) { - if (pin[GPIO_ARIRFSEL] < 99) { - pinMode(pin[GPIO_ARIRFSEL], OUTPUT); - digitalWrite(pin[GPIO_ARIRFSEL], 1); - } - } - } - - uint32_t max_scheme = Light.max_scheme; - if (Light.subtype < LST_RGB) { - max_scheme = LS_POWER; - } - if ((LS_WAKEUP == Settings.light_scheme) || (Settings.light_scheme > max_scheme)) { - Settings.light_scheme = LS_POWER; - } - Light.power = 0; - Light.update = true; - Light.wakeup_active = 0; - - LightUpdateColorMapping(); -} - -void LightUpdateColorMapping(void) -{ - uint8_t param = Settings.param[P_RGB_REMAP] & 127; - if (param > 119){ param = 0; } - - uint8_t tmp[] = {0,1,2,3,4}; - Light.color_remap[0] = tmp[param / 24]; - for (uint32_t i = param / 24; i<4; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 24; - Light.color_remap[1] = tmp[(param / 6)]; - for (uint32_t i = param / 6; i<3; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 6; - Light.color_remap[2] = tmp[(param / 2)]; - for (uint32_t i = param / 2; i<2; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 2; - Light.color_remap[3] = tmp[param]; - Light.color_remap[4] = tmp[1-param]; - - Light.update = true; - -} - -uint8_t LightGetDimmer(uint8_t dimmer) { - return light_state.getDimmer(dimmer); -} - -void LightSetDimmer(uint8_t dimmer) { - light_controller.changeDimmer(dimmer); -} - -void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { - light_state.getHSB(hue, sat, bri); -} - -void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { - light_state.HsToRgb(hue, sat, r_r, r_g, r_b); -} - - -uint8_t LightGetBri(uint8_t device) { - uint8_t bri = 254; - if (Light.pwm_multi_channels) { - if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { - bri = Light.current_color[device - Light.device]; - } - } else if (light_controller.isCTRGBLinked()) { - if (device == Light.device) { - bri = light_state.getBri(); - } - } else { - if (device == Light.device) { - bri = light_state.getBriRGB(); - } else if (device == Light.device + 1) { - bri = light_state.getBriCT(); - } - } - return bri; -} - - -void LightSetBri(uint8_t device, uint8_t bri) { - if (Light.pwm_multi_channels) { - if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { - Light.current_color[device - Light.device] = bri; - light_controller.changeChannels(Light.current_color); - } - } else if (light_controller.isCTRGBLinked()) { - if (device == Light.device) { - light_controller.changeBri(bri); - } - } else { - if (device == Light.device) { - light_controller.changeBriRGB(bri); - } else if (device == Light.device + 1) { - light_controller.changeBriCT(bri); - } - } -} - -void LightSetColorTemp(uint16_t ct) -{ - - - - - - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { - return; - } - light_controller.changeCTB(ct, light_state.getBriCT()); -} - -uint16_t LightGetColorTemp(void) -{ - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { - return 0; - } - return (light_state.getColorMode() & LCM_CT) ? light_state.getCT() : 0; -} - -void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) -{ - - - - if (Settings.flag.light_signal) { - uint16_t signal = changeUIntScale(value, lo, hi, 0, 255); - - light_controller.changeRGB(signal, 255 - signal, 0, true); - Settings.light_scheme = 0; - if (0 == light_state.getBri()) { - light_controller.changeBri(50); - } - } -} - - -char* LightGetColor(char* scolor, boolean force_hex = false) -{ - light_controller.calcLevels(); - scolor[0] = '\0'; - for (uint32_t i = 0; i < Light.subtype; i++) { - if (!force_hex && Settings.flag.decimal_text) { - snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Light.current_color[i]); - } else { - snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%02X"), scolor, Light.current_color[i]); - } - } - return scolor; -} - -void LightPowerOn(void) -{ - if (light_state.getBri() && !(Light.power)) { - ExecuteCommandPower(Light.device, POWER_ON, SRC_LIGHT); - } -} - -void LightState(uint8_t append) -{ - char scolor[LIGHT_COLOR_SIZE]; - char scommand[33]; - bool unlinked = !light_controller.isCTRGBLinked() && (Light.subtype >= LST_RGBW); - - if (append) { - ResponseAppend_P(PSTR(",")); - } else { - Response_P(PSTR("{")); - } - if (!Light.pwm_multi_channels) { - if (unlinked) { - - ResponseAppend_P(PSTR("\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d" - ",\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d"), - Light.device, GetStateText(Light.power & 1), Light.device, light_state.getDimmer(1), - Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), Light.device + 1, light_state.getDimmer(2)); - } else { - GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); - ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1), - light_state.getDimmer()); - } - - - if (Light.subtype > LST_SINGLE) { - ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); - if (LST_RGB <= Light.subtype) { - uint16_t hue; - uint8_t sat, bri; - light_state.getHSB(&hue, &sat, &bri); - sat = changeUIntScale(sat, 0, 255, 0, 100); - bri = changeUIntScale(bri, 0, 255, 0, 100); - - ResponseAppend_P(PSTR(",\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), hue,sat,bri); - } - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { - ResponseAppend_P(PSTR(",\"" D_CMND_WHITE "\":%d"), light_state.getDimmer(2)); - } - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), light_state.getCT()); - } - - ResponseAppend_P(PSTR(",\"" D_CMND_CHANNEL "\":[" )); - for (uint32_t i = 0; i < Light.subtype; i++) { - uint8_t channel_raw = Light.current_color[i]; - uint8_t channel = changeUIntScale(channel_raw,0,255,0,100); - - if ((0 == channel) && (channel_raw > 0)) { channel = 1; } - ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), channel); - } - ResponseAppend_P(PSTR("]")); - } - - if (append) { - if (Light.subtype >= LST_RGB) { - ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); - } - if (Light.max_scheme > LS_MAX) { - ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width); - } - ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), - GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); - } - } else { - for (uint32_t i = 0; i < Light.subtype; i++) { - GetPowerDevice(scommand, Light.device + i, sizeof(scommand), 1); - uint32_t light_power_masked = Light.power & (1 << i); - light_power_masked = light_power_masked ? 1 : 0; - ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_CHANNEL "%d\":%d,"), scommand, GetStateText(light_power_masked), Light.device + i, - changeUIntScale(Light.current_color[i], 0, 255, 0, 100)); - } - ResponseAppend_P(PSTR("\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); - } - - if (!append) { - ResponseJsonEnd(); - } -} - -void LightPreparePower(power_t channels = 0xFFFFFFFF) { -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); -#endif - - if (Light.pwm_multi_channels) { - for (uint32_t i = 0; i < Light.subtype; i++) { - if (bitRead(channels, i)) { - - if ((Light.current_color[i]) && (!bitRead(Light.power, i))) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device + i, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else { - - if ((0 == Light.current_color[i]) && bitRead(Light.power, i)) { - ExecuteCommandPower(Light.device + i, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } - #ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(Light.device + i); - #endif - } - } - } else { - if (light_controller.isCTRGBLinked()) { - if (light_state.getBri() && !(Light.power)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else if (!light_state.getBri() && Light.power) { - ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } else { - - if (channels & 1) { - if (light_state.getBriRGB() && !(Light.power & 1)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else if (!light_state.getBriRGB() && (Light.power & 1)) { - ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } - - if (channels & 2) { - if (light_state.getBriCT() && !(Light.power & 2)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else if (!light_state.getBriCT() && (Light.power & 2)) { - ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } - } -#ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(Light.device); -#endif - } - - if (Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); -#endif - Light.power = power >> (Light.device - 1); - LightState(0); -} - -void LightCycleColor(int8_t direction) -{ - if (Light.strip_timer_counter % (Settings.light_speed * 2)) { - return; - } - - if (0 == direction) { - if (Light.random == Light.wheel) { - Light.random = random(255); - - uint8_t my_dir = (Light.random < Light.wheel -128) ? 1 : - (Light.random < Light.wheel ) ? 0 : - (Light.random > Light.wheel +128) ? 0 : 1; - Light.random = (Light.random & 0xFE) | my_dir; - - - } - - direction = (Light.random &0x01) ? 1 : -1; - } - Light.wheel += direction; - uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); - - - - uint8_t sat; - light_state.getHSB(nullptr, &sat, nullptr); - light_state.setHS(hue, sat); - light_controller.calcLevels(Light.new_color); -} - -void LightSetPower(void) -{ - - Light.old_power = Light.power; - - uint32_t mask = 1; - if (Light.pwm_multi_channels) { - mask = (1 << Light.subtype) - 1; - } else if (!light_controller.isCTRGBLinked()) { - mask = 3; - } - uint32_t shift = Light.device - 1; - - - - - - Light.power = (XdrvMailbox.index & (mask << shift)) >> shift; - if (Light.wakeup_active) { - Light.wakeup_active--; - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightSetPower XdrvMailbox.index=%d Light.old_power=%d Light.power=%d mask=%d shift=%d", - XdrvMailbox.index, Light.old_power, Light.power, mask, shift); -#endif - if (Light.power != Light.old_power) { - Light.update = true; - } - LightAnimate(); -} - - - - -void LightAnimate(void) -{ - uint16_t light_still_on = 0; - bool power_off = false; - - - light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); - Light.strip_timer_counter++; - - - - if (Light.power || Light.fade_running) { - if (Settings.sleep > PWM_MAX_SLEEP) { - sleep = PWM_MAX_SLEEP; - } else { - sleep = Settings.sleep; - } - } else { - sleep = Settings.sleep; - } - - if (!Light.power) { - Light.strip_timer_counter = 0; - if (Settings.light_scheme >= LS_MAX) { - power_off = true; - } - } else { - switch (Settings.light_scheme) { - case LS_POWER: - light_controller.calcLevels(Light.new_color); - break; - case LS_WAKEUP: - if (2 == Light.wakeup_active) { - Light.wakeup_active = 1; - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.new_color[i] = 0; - } - Light.wakeup_counter = 0; - Light.wakeup_dimmer = 0; - } - Light.wakeup_counter++; - if (Light.wakeup_counter > ((Settings.light_wakeup * STATES) / Settings.light_dimmer)) { - Light.wakeup_counter = 0; - Light.wakeup_dimmer++; - if (Light.wakeup_dimmer <= Settings.light_dimmer) { - light_state.setDimmer(Light.wakeup_dimmer); - light_controller.calcLevels(); - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.new_color[i] = Light.current_color[i]; - } - } else { - - - - - Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"")); - LightState(1); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); - XdrvRulesProcess(); - - Light.wakeup_active = 0; - Settings.light_scheme = LS_POWER; - } - } - break; - case LS_CYCLEUP: - LightCycleColor(1); - break; - case LS_CYCLEDN: - LightCycleColor(-1); - break; - case LS_RANDOM: - LightCycleColor(0); - break; - default: - XlgtCall(FUNC_SET_SCHEME); - } - } - - if ((Settings.light_scheme < LS_MAX) || power_off) { - - - LightApplyPower(Light.new_color, Light.power); - - - - - - - - if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { - Light.update = true; - } - if (Light.update) { - uint16_t cur_col_10[LST_MAX]; - Light.update = false; - - - for (uint32_t i = 0; i < LST_MAX; i++) { - Light.last_color[i] = Light.new_color[i]; - - cur_col_10[i] = change8to10(Light.new_color[i]); - } - - if (Light.pwm_multi_channels) { - calcGammaMultiChannels(cur_col_10); - } else { - calcGammaBulbs(cur_col_10); - - - - if ((LST_RGBW <= Light.subtype) && (0 == Settings.rgbwwTable[4]) && (0 == cur_col_10[3]+cur_col_10[4])) { - uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); - for (uint32_t i=0; i<3; i++) { - - uint32_t adjust10 = change8to10(Settings.rgbwwTable[i]); - cur_col_10[i] = changeUIntScale(cur_col_10[i] - min_rgb_10, 0, 1023, 0, adjust10); - } - - - uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); - uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); - if (LST_RGBW == Light.subtype) { - - cur_col_10[3] = white_10; - } else { - - uint32_t ct = light_state.getCT10bits(); - cur_col_10[4] = changeUIntScale(ct, 0, 1023, 0, white_10); - cur_col_10[3] = white_10 - cur_col_10[4]; - } - } - } - - - if (0 != Settings.rgbwwTable[4]) { - for (uint32_t i = 0; i 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0; - } - - - uint16_t orig_col_10bits[LST_MAX]; - memcpy(orig_col_10bits, cur_col_10, sizeof(orig_col_10bits)); - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col_10[i] = orig_col_10bits[Light.color_remap[i]]; - } - - if (!Settings.light_fade || power_off || (!Light.fade_initialized)) { - - memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10)); - - LightSetOutputs(cur_col_10); - Light.fade_initialized = true; - } else { - if (Light.fade_running) { - - memcpy(Light.fade_start_10, Light.fade_cur_10, sizeof(Light.fade_start_10)); - } - memcpy(Light.fade_end_10, cur_col_10, sizeof(Light.fade_start_10)); - Light.fade_running = true; - Light.fade_duration = 0; - Light.fade_start = 0; - - } - } - if (Light.fade_running) { - if (LightApplyFade()) { - - - - LightSetOutputs(Light.fade_cur_10); - } - } - } -} - -bool isChannelGammaCorrected(uint32_t channel) { - if (!Settings.light_correction) { return false; } - if (channel >= Light.subtype) { return false; } - - if (PHILIPS == my_module_type) { - if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } - if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } - } - return true; -} - - -uint16_t fadeGamma(uint32_t channel, uint16_t v) { - if (isChannelGammaCorrected(channel)) { - return ledGamma_internal(v, gamma_table_fast); - } else { - return v; - } -} -uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg) { - if (isChannelGammaCorrected(channel)) { - return ledGammaReverse_internal(vg, gamma_table_fast); - } else { - return vg; - } -} - -bool LightApplyFade(void) { - static uint32_t last_millis = 0; - uint32_t now = millis(); - - if ((now - last_millis) <= 5) { - return false; - } - last_millis = now; - - - if (0 == Light.fade_duration) { - Light.fade_start = now; - - uint32_t distance = 0; - for (uint32_t i = 0; i < Light.subtype; i++) { - int32_t channel_distance = fadeGammaReverse(i, Light.fade_end_10[i]) - fadeGammaReverse(i, Light.fade_start_10[i]); - if (channel_distance < 0) { channel_distance = - channel_distance; } - if (channel_distance > distance) { distance = channel_distance; } - } - if (distance > 0) { - - - - Light.fade_duration = (distance * Settings.light_speed * 500) / 1023; - if (Settings.save_data) { - - uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; - - if (save_data_counter < delay_seconds) { - save_data_counter = delay_seconds; - } - } - } else { - - Light.fade_running = false; - } - } - - uint16_t fade_current = now - Light.fade_start; - if (fade_current <= Light.fade_duration) { - - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.fade_cur_10[i] = fadeGamma(i, - changeUIntScale(fadeGammaReverse(i, fade_current), - 0, Light.fade_duration, - fadeGammaReverse(i, Light.fade_start_10[i]), - fadeGammaReverse(i, Light.fade_end_10[i]))); - - - - } - } else { - - - Light.fade_running = false; - Light.fade_start = 0; - Light.fade_duration = 0; - - memcpy(Light.fade_cur_10, Light.fade_end_10, sizeof(Light.fade_end_10)); - - memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10)); - } - return true; -} - - - -void LightApplyPower(uint8_t new_color[LST_MAX], power_t power) { - - if (Light.pwm_multi_channels) { - - for (uint32_t i = 0; i < LST_MAX; i++) { - if (0 == bitRead(power,i)) { - new_color[i] = 0; - } - } - - - - - - } else { - if (!light_controller.isCTRGBLinked()) { - - if (0 == (power & 1)) { - new_color[0] = new_color[1] = new_color[2] = 0; - } - if (0 == (power & 2)) { - new_color[3] = new_color[4] = 0; - } - } else if (!power) { - for (uint32_t i = 0; i < LST_MAX; i++) { - new_color[i] = 0; - } - } - } -} - -void LightSetOutputs(const uint16_t *cur_col_10) { - - if (light_type < LT_PWM6) { - for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { - if (pin[GPIO_PWM1 +i] < 99) { - - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10[(i + Light.pwm_offset)] : cur_col_10[(i + Light.pwm_offset)]); - } - } - } - - - - - uint8_t cur_col[LST_MAX]; - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col[i] = change10to8(cur_col_10[i]); - } - - - uint8_t scale_col[3]; - uint32_t max = (cur_col[0] > cur_col[1] && cur_col[0] > cur_col[2]) ? cur_col[0] : (cur_col[1] > cur_col[2]) ? cur_col[1] : cur_col[2]; - for (uint32_t i = 0; i < 3; i++) { - scale_col[i] = (0 == max) ? 255 : (255 > max) ? changeUIntScale(cur_col[i], 0, max, 0, 255) : cur_col[i]; - } - - char *tmp_data = XdrvMailbox.data; - char *tmp_topic = XdrvMailbox.topic; - XdrvMailbox.data = (char*)cur_col; - XdrvMailbox.topic = (char*)scale_col; - if (XlgtCall(FUNC_SET_CHANNELS)) { } - else if (XdrvCall(FUNC_SET_CHANNELS)) { } - XdrvMailbox.data = tmp_data; - XdrvMailbox.topic = tmp_topic; -} - - -void calcGammaMultiChannels(uint16_t cur_col_10[5]) { - - if (Settings.light_correction) { - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col_10[i] = ledGamma10_10(cur_col_10[i]); - } - } -} - -void calcGammaBulbs(uint16_t cur_col_10[5]) { - - - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - - uint32_t cw1 = Light.subtype - 1; - uint32_t cw0 = Light.subtype - 2; - uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; - uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; - - if (PHILIPS == my_module_type) { - - cur_col_10[cw1] = light_state.getCT10bits(); - - if (Settings.light_correction) { - cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); - } else { - cur_col_10[cw0] = white_bri10_1023; - } - } else if (Settings.light_correction) { - - if (white_bri10 <= 1031) { - - uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); - - cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); - cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); - } else { - cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); - cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); - } - } - } - - if (Settings.light_correction) { - - if (LST_RGB <= Light.subtype) { - for (uint32_t i = 0; i < 3; i++) { - cur_col_10[i] = ledGamma10_10(cur_col_10[i]); - } - } - - if ((LST_SINGLE == Light.subtype) || (LST_RGBW == Light.subtype)) { - cur_col_10[Light.subtype - 1] = ledGamma10_10(cur_col_10[Light.subtype - 1]); - } - } -} - - - - - -bool LightColorEntry(char *buffer, uint32_t buffer_length) -{ - char scolor[10]; - char *p; - char *str; - uint32_t entry_type = 0; - uint8_t value = Light.fixed_color_index; - - if (buffer[0] == '#') { - buffer++; - buffer_length--; - } - - if (Light.subtype >= LST_RGB) { - char option = (1 == buffer_length) ? buffer[0] : '\0'; - if (('+' == option) && (Light.fixed_color_index < MAX_FIXED_COLOR)) { - value++; - } - else if (('-' == option) && (Light.fixed_color_index > 1)) { - value--; - } else { - value = atoi(buffer); - } - } - - memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); - - while ((buffer_length > 0) && ('=' == buffer[buffer_length - 1])) { - buffer_length--; - memcpy(&Light.entry_color, &Light.current_color, sizeof(Light.entry_color)); - } - if (strstr(buffer, ",") != nullptr) { - int8_t i = 0; - for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) { - if (i < LST_MAX) { - Light.entry_color[i++] = atoi(str); - } - } - entry_type = 2; - } - else if (((2 * Light.subtype) == buffer_length) || (buffer_length > 3)) { - for (uint32_t i = 0; i < tmin((uint)(buffer_length / 2), sizeof(Light.entry_color)); i++) { - strlcpy(scolor, buffer + (i *2), 3); - Light.entry_color[i] = (uint8_t)strtol(scolor, &p, 16); - } - entry_type = 1; - } - else if ((Light.subtype >= LST_RGB) && (value > 0) && (value <= MAX_FIXED_COLOR)) { - Light.fixed_color_index = value; - memcpy_P(&Light.entry_color, &kFixedColor[value -1], 3); - entry_type = 1; - } - else if ((value > 199) && (value <= 199 + MAX_FIXED_COLD_WARM)) { - if (LST_RGBW == Light.subtype) { - memcpy_P(&Light.entry_color[3], &kFixedWhite[value -200], 1); - entry_type = 1; - } - else if (LST_COLDWARM == Light.subtype) { - memcpy_P(&Light.entry_color, &kFixedColdWarm[value -200], 2); - entry_type = 1; - } - else if (LST_RGBCW == Light.subtype) { - memcpy_P(&Light.entry_color[3], &kFixedColdWarm[value -200], 2); - entry_type = 1; - } - } - if (entry_type) { - Settings.flag.decimal_text = entry_type -1; - } - return (entry_type); -} - - - -void CmndSupportColor(void) -{ - bool valid_entry = false; - bool coldim = false; - - if (XdrvMailbox.data_len > 0) { - valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); - if (valid_entry) { - if (XdrvMailbox.index <= 2) { - uint32_t old_bri = light_state.getBri(); - - light_controller.changeChannels(Light.entry_color); - if (2 == XdrvMailbox.index) { - - light_controller.changeBri(old_bri); - } - - Settings.light_scheme = 0; - coldim = true; - } else { - for (uint32_t i = 0; i < LST_RGB; i++) { - Settings.ws_color[XdrvMailbox.index -3][i] = Light.entry_color[i]; - } - } - } - } - char scolor[LIGHT_COLOR_SIZE]; - if (!valid_entry && (XdrvMailbox.index <= 2)) { - ResponseCmndChar(LightGetColor(scolor)); - } - if (XdrvMailbox.index >= 3) { - scolor[0] = '\0'; - for (uint32_t i = 0; i < LST_RGB; i++) { - if (Settings.flag.decimal_text) { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.ws_color[XdrvMailbox.index -3][i]); - } else { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]); - } - } - ResponseCmndIdxChar(scolor); - } - if (coldim) { - LightPreparePower(); - } -} - -void CmndColor(void) -{ - - - - - - - - if ((Light.subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { - CmndSupportColor(); - } -} - -void CmndWhite(void) -{ - - - if (Light.pwm_multi_channels) { return; } - if ( ((Light.subtype >= LST_RGBW) || (LST_COLDWARM == Light.subtype)) && (XdrvMailbox.index == 1)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - light_controller.changeDimmer(XdrvMailbox.payload, 2); - LightPreparePower(2); - } else { - ResponseCmndNumber(light_state.getDimmer(2)); - } - } -} - -void CmndChannel(void) -{ - - - - - if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { - uint32_t light_index = XdrvMailbox.index - Light.device; - power_t coldim = 0; - - - if (1 == XdrvMailbox.data_len) { - uint8_t channel = changeUIntScale(Light.current_color[light_index],0,255,0,100); - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; - } else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (channel < 11) ? 1 : channel - 10; - } - } - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Light.current_color[light_index] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); - if (Light.pwm_multi_channels) { - coldim = 1 << light_index; - } else { - if (light_controller.isCTRGBLinked()) { - - if ((light_index < 3) && (light_controller.isCTRGBLinked())) { - Light.current_color[3] = Light.current_color[4] = 0; - } else { - Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; - } - coldim = 1; - } else { - if (light_index < 3) { coldim = 1; } - else { coldim = 2; } - } - } - light_controller.changeChannels(Light.current_color); - } - ResponseCmndIdxNumber(changeUIntScale(Light.current_color[light_index],0,255,0,100)); - if (coldim) { - LightPreparePower(coldim); - } - } -} - -void CmndHsbColor(void) -{ - - - - - - - - if (Light.subtype >= LST_RGB) { - if (XdrvMailbox.data_len > 0) { - uint16_t c_hue; - uint8_t c_sat; - light_state.getHSB(&c_hue, &c_sat, nullptr); - uint32_t HSB[3]; - HSB[0] = c_hue; - HSB[1] = c_sat; - HSB[2] = light_state.getBriRGB(); - if ((2 == XdrvMailbox.index) || (3 == XdrvMailbox.index)) { - if ((uint32_t)XdrvMailbox.payload > 100) { XdrvMailbox.payload = 100; } - HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); - } else { - uint32_t paramcount = ParseParameters(3, HSB); - if (HSB[0] > 360) { HSB[0] = 360; } - for (uint32_t i = 1; i < paramcount; i++) { - if (HSB[i] > 100) { HSB[i] == 100; } - HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); - } - } - light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); - LightPreparePower(1); - } else { - LightState(0); - } - } -} - -void CmndScheme(void) -{ - - - - - - if (Light.subtype >= LST_RGB) { - uint32_t max_scheme = Light.max_scheme; - - if (1 == XdrvMailbox.data_len) { - if (('+' == XdrvMailbox.data[0]) && (Settings.light_scheme < max_scheme)) { - XdrvMailbox.payload = Settings.light_scheme + ((0 == Settings.light_scheme) ? 2 : 1); - } - else if (('-' == XdrvMailbox.data[0]) && (Settings.light_scheme > 0)) { - XdrvMailbox.payload = Settings.light_scheme - ((2 == Settings.light_scheme) ? 2 : 1); - } - } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= max_scheme)) { - uint32_t parm[2]; - if (ParseParameters(2, parm) > 1) { - Light.wheel = parm[1]; - } - Settings.light_scheme = XdrvMailbox.payload; - if (LS_WAKEUP == Settings.light_scheme) { - Light.wakeup_active = 3; - } - LightPowerOn(); - Light.strip_timer_counter = 0; - - if (Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - } - ResponseCmndNumber(Settings.light_scheme); - } -} - -void CmndWakeup(void) -{ - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - light_controller.changeDimmer(XdrvMailbox.payload); - } - Light.wakeup_active = 3; - Settings.light_scheme = LS_WAKEUP; - LightPowerOn(); - ResponseCmndChar(D_JSON_STARTED); -} - -void CmndColorTemperature(void) -{ - - - - - if (Light.pwm_multi_channels) { return; } - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - uint32_t ct = light_state.getCT(); - if (1 == XdrvMailbox.data_len) { - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (ct > (CT_MAX-34)) ? CT_MAX : ct + 34; - } - else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (ct < (CT_MIN+34)) ? CT_MIN : ct - 34; - } - } - if ((XdrvMailbox.payload >= CT_MIN) && (XdrvMailbox.payload <= CT_MAX)) { - light_controller.changeCTB(XdrvMailbox.payload, light_state.getBriCT()); - LightPreparePower(2); - } else { - ResponseCmndNumber(ct); - } - } -} - -void CmndDimmer(void) -{ - - - - - - - uint32_t dimmer; - if (XdrvMailbox.index > 2) { XdrvMailbox.index = 1; } - - if ((light_controller.isCTRGBLinked()) || (0 == XdrvMailbox.index)) { - dimmer = light_state.getDimmer(); - } else { - dimmer = light_state.getDimmer(XdrvMailbox.index); - } - - if (1 == XdrvMailbox.data_len) { - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (dimmer > 89) ? 100 : dimmer + 10; - } else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (dimmer < 11) ? 1 : dimmer - 10; - } - } - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - if (light_controller.isCTRGBLinked()) { - - light_controller.changeDimmer(XdrvMailbox.payload); - LightPreparePower(); - } else { - if (0 != XdrvMailbox.index) { - light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); - LightPreparePower(1 << (XdrvMailbox.index - 1)); - } else { - - light_controller.changeDimmer(XdrvMailbox.payload, 1); - light_controller.changeDimmer(XdrvMailbox.payload, 2); - LightPreparePower(); - } - } - Light.update = true; - } else { - ResponseCmndNumber(dimmer); - } -} - -void CmndDimmerRange(void) -{ - - - if (XdrvMailbox.data_len > 0) { - uint32_t parm[2]; - parm[0] = Settings.dimmer_hw_min; - parm[1] = Settings.dimmer_hw_max; - ParseParameters(2, parm); - if (parm[0] < parm[1]) { - Settings.dimmer_hw_min = parm[0]; - Settings.dimmer_hw_max = parm[1]; - } else { - Settings.dimmer_hw_min = parm[1]; - Settings.dimmer_hw_max = parm[0]; - } - restart_flag = 2; - } - Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); -} - -void CmndLedTable(void) -{ - - - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - Settings.light_correction = XdrvMailbox.payload; - break; - case 2: - Settings.light_correction ^= 1; - break; - } - Light.update = true; - } - ResponseCmndStateText(Settings.light_correction); -} - -void CmndRgbwwTable(void) -{ - - - if ((XdrvMailbox.data_len > 0)) { - uint32_t parm[LST_RGBCW -1]; - uint32_t parmcount = ParseParameters(LST_RGBCW, parm); - for (uint32_t i = 0; i < parmcount; i++) { - Settings.rgbwwTable[i] = parm[i]; - } - Light.update = true; - } - char scolor[LIGHT_COLOR_SIZE]; - scolor[0] = '\0'; - for (uint32_t i = 0; i < LST_RGBCW; i++) { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); - } - ResponseCmndChar(scolor); -} - -void CmndFade(void) -{ - - - - - switch (XdrvMailbox.payload) { - case 0: - case 1: - Settings.light_fade = XdrvMailbox.payload; - break; - case 2: - Settings.light_fade ^= 1; - break; - } - if (!Settings.light_fade) { Light.fade_running = false; } - ResponseCmndStateText(Settings.light_fade); -} - -void CmndSpeed(void) -{ - - - - - if (1 == XdrvMailbox.data_len) { - if (('+' == XdrvMailbox.data[0]) && (Settings.light_speed > 1)) { - XdrvMailbox.payload = Settings.light_speed - 1; - } - else if (('-' == XdrvMailbox.data[0]) && (Settings.light_speed < 40)) { - XdrvMailbox.payload = Settings.light_speed + 1; - } - } - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 40)) { - Settings.light_speed = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_speed); -} - -void CmndWakeupDuration(void) -{ - - - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { - Settings.light_wakeup = XdrvMailbox.payload; - Light.wakeup_active = 0; - } - ResponseCmndNumber(Settings.light_wakeup); -} - -void CmndUndocA(void) -{ - - char scolor[LIGHT_COLOR_SIZE]; - LightGetColor(scolor, true); - scolor[6] = '\0'; - Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); - MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); - mqtt_data[0] = '\0'; -} - - - - - -bool Xdrv04(uint8_t function) -{ - bool result = false; - - if (FUNC_MODULE_INIT == function) { - return LightModuleInit(); - } - else if (light_type) { - switch (function) { - case FUNC_SERIAL: - result = XlgtCall(FUNC_SERIAL); - break; - case FUNC_LOOP: - if (Light.fade_running) { - if (LightApplyFade()) { - LightSetOutputs(Light.fade_cur_10); - } - } - break; - case FUNC_EVERY_50_MSECOND: - LightAnimate(); - break; - case FUNC_SET_POWER: - LightSetPower(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kLightCommands, LightCommand); - if (!result) { - result = XlgtCall(FUNC_COMMAND); - } - break; - case FUNC_PRE_INIT: - LightInit(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_05_irremote.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_05_irremote.ino" -#if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) - - - - -#define XDRV_05 5 - -#include - -enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND }; - -const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; - - -void (* const IrRemoteCommand[])(void) PROGMEM = { - &CmndIrSend }; - - -static const uint8_t MAX_STANDARD_IR = NEC; -const char kIrRemoteProtocols[] PROGMEM = "UNKNOWN|RC5|RC6|NEC"; - - - - - -#include - -IRsend *irsend = nullptr; -bool irsend_active = false; - -void IrSendInit(void) -{ - irsend = new IRsend(pin[GPIO_IRSEND]); - irsend->begin(); -} - -#ifdef USE_IR_RECEIVE - - - - -const bool IR_RCV_SAVE_BUFFER = false; -const uint32_t IR_TIME_AVOID_DUPLICATE = 500; - -#include - -IRrecv *irrecv = nullptr; - -unsigned long ir_lasttime = 0; - -void IrReceiveUpdateThreshold(void) -{ - if (irrecv != nullptr) { - if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - } -} - -void IrReceiveInit(void) -{ - - irrecv = new IRrecv(pin[GPIO_IRRECV], IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER); - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - irrecv->enableIRIn(); - - -} - -void IrReceiveCheck(void) -{ - char sirtype[8]; - int8_t iridx = 0; - - decode_results results; - - if (irrecv->decode(&results)) { - char hvalue[65]; - - iridx = results.decode_type; - if ((iridx < 0) || (iridx > MAX_STANDARD_IR)) { iridx = 0; } - - if (iridx) { - if (results.bits > 64) { - - uint32_t digits2 = results.bits / 8; - if (results.bits % 8) { digits2++; } - ToHex_P((unsigned char*)results.state, digits2, hvalue, sizeof(hvalue)); - } else { - Uint64toHex(results.value, hvalue, results.bits); - } - } else { - Uint64toHex(results.value, hvalue, 32); - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%s, Decode %d"), - irsend_active, results.rawlen, results.overflow, results.bits, hvalue, results.decode_type); - - unsigned long now = millis(); - - if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { - ir_lasttime = now; - - char svalue[64]; - if (Settings.flag.ir_receive_decimal) { - ulltoa(results.value, svalue, 10); - } else { - snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue); - } - ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d"), - GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits); - if (iridx) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_DATA "\":%s"), svalue); - } else { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_HASH "\":%s"), svalue); - } - - if (Settings.flag3.receive_raw) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); - uint16_t i; - for (i = 1; i < results.rawlen; i++) { - if (i > 1) { ResponseAppend_P(PSTR(",")); } - uint32_t usecs; - for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); - } - ResponseAppend_P(PSTR("%d"), usecs); - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } - } - uint16_t extended_length = results.rawlen - 1; - for (uint32_t j = 0; j < results.rawlen - 1; j++) { - uint32_t usecs = results.rawbuf[j] * kRawTick; - - extended_length += (usecs / (UINT16_MAX + 1)) * 2; - } - ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - - XdrvRulesProcess(); -#ifdef USE_DOMOTICZ - if (iridx) { - unsigned long value = results.value | (iridx << 28); - DomoticzSensor(DZ_COUNT, value); - } -#endif - } - - irrecv->resume(); - } -} -#endif - - - - - -uint32_t IrRemoteCmndIrSendJson(void) -{ - - - - - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { - return IE_INVALID_JSON; - } - - StaticJsonBuffer<140> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); - if (!root.success()) { - return IE_INVALID_JSON; - } - - - - char parm_uc[10]; - const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; - uint16_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint64_t data = strtoull(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); - uint16_t repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT))]; - - if (XdrvMailbox.index > repeat + 1) { - repeat = XdrvMailbox.index - 1; - } - if (!(protocol && bits)) { - return IE_SYNTAX_IRSEND; - } - - char protocol_text[20]; - int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - - char dvalue[64]; - char hvalue[20]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %s (0x%s), repeat %d, protocol_code %d"), - protocol_text, protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat, protocol_code); - - irsend_active = true; - switch (protocol_code) { -#ifdef USE_IR_SEND_RC5 - case RC5: - irsend->sendRC5(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_RC6 - case RC6: - irsend->sendRC6(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_NEC - case NEC: - irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits, repeat); break; -#endif - default: - irsend_active = false; - ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); - } - - return IE_NO_ERROR; -} - -void CmndIrSend(void) -{ - uint8_t error = IE_SYNTAX_IRSEND; - - if (XdrvMailbox.data_len) { - - if (strstr(XdrvMailbox.data, "{") == nullptr) { - error = IE_INVALID_JSON; - } else { - error = IrRemoteCmndIrSendJson(); - } - } - IrRemoteCmndResponse(error); -} - -void IrRemoteCmndResponse(uint32_t error) -{ - switch (error) { - case IE_INVALID_RAWDATA: - ResponseCmndChar(D_JSON_INVALID_RAWDATA); - break; - case IE_INVALID_JSON: - ResponseCmndChar(D_JSON_INVALID_JSON); - break; - case IE_SYNTAX_IRSEND: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); - break; - default: - ResponseCmndDone(); - } -} - - - - - -bool Xdrv05(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { - switch (function) { - case FUNC_PRE_INIT: - if (pin[GPIO_IRSEND] < 99) { - IrSendInit(); - } -#ifdef USE_IR_RECEIVE - if (pin[GPIO_IRRECV] < 99) { - IrReceiveInit(); - } -#endif - break; - case FUNC_EVERY_50_MSECOND: -#ifdef USE_IR_RECEIVE - if (pin[GPIO_IRRECV] < 99) { - IrReceiveCheck(); - } -#endif - irsend_active = false; - break; - case FUNC_COMMAND: - if (pin[GPIO_IRSEND] < 99) { - result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); - } - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_05_irremote_full.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_05_irremote_full.ino" -#ifdef USE_IR_REMOTE_FULL - - - - -#define XDRV_05 5 - -#include -#include -#include -#include -#include - -enum IrErrors { IE_RESPONSE_PROVIDED, IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC, - IE_UNSUPPORTED_HVAC, IE_UNSUPPORTED_PROTOCOL }; - -const char kIrRemoteCommands[] PROGMEM = "|" - D_CMND_IRHVAC "|" D_CMND_IRSEND ; - -void (* const IrRemoteCommand[])(void) PROGMEM = { - &CmndIrHvac, &CmndIrSend }; - - - - - -IRsend *irsend = nullptr; -bool irsend_active = false; - -void IrSendInit(void) -{ - irsend = new IRsend(pin[GPIO_IRSEND]); - irsend->begin(); -} - - - -uint8_t reverseBitsInByte(uint8_t b) { - b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; - b = (b & 0xCC) >> 2 | (b & 0x33) << 2; - b = (b & 0xAA) >> 1 | (b & 0x55) << 1; - return b; -} - - -uint64_t reverseBitsInBytes64(uint64_t b) { - union { - uint8_t b[8]; - uint64_t i; - } a; - a.i = b; - for (uint32_t i=0; i<8; i++) { - a.b[i] = reverseBitsInByte(a.b[i]); - } - return a.i; -} - - - - - -const bool IR_FULL_RCV_SAVE_BUFFER = false; -const uint32_t IR_TIME_AVOID_DUPLICATE = 500; - - - - -const uint16_t IR_FULL_BUFFER_SIZE = 1024; - - - -const uint8_t IR__FULL_RCV_TIMEOUT = 50; - -IRrecv *irrecv = nullptr; - -unsigned long ir_lasttime = 0; - -void IrReceiveUpdateThreshold(void) -{ - if (irrecv != nullptr) { - if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - } -} - -void IrReceiveInit(void) -{ - - irrecv = new IRrecv(pin[GPIO_IRRECV], IR_FULL_BUFFER_SIZE, IR__FULL_RCV_TIMEOUT, IR_FULL_RCV_SAVE_BUFFER); - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - irrecv->enableIRIn(); -} - -String sendACJsonState(const stdAc::state_t &state) { - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); - json[D_JSON_IRHVAC_VENDOR] = typeToString(state.protocol); - json[D_JSON_IRHVAC_MODEL] = state.model; - json[D_JSON_IRHVAC_POWER] = IRac::boolToString(state.power); - json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(state.mode); - - if (state.mode == stdAc::opmode_t::kOff || !state.power) { - json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff); - json[D_JSON_IRHVAC_POWER] = IRac::boolToString(false); - } - json[D_JSON_IRHVAC_CELSIUS] = IRac::boolToString(state.celsius); - if (floorf(state.degrees) == state.degrees) { - json[D_JSON_IRHVAC_TEMP] = floorf(state.degrees); - } else { - json[D_JSON_IRHVAC_TEMP] = RawJson(String(state.degrees, 1)); - } - json[D_JSON_IRHVAC_FANSPEED] = IRac::fanspeedToString(state.fanspeed); - json[D_JSON_IRHVAC_SWINGV] = IRac::swingvToString(state.swingv); - json[D_JSON_IRHVAC_SWINGH] = IRac::swinghToString(state.swingh); - json[D_JSON_IRHVAC_QUIET] = IRac::boolToString(state.quiet); - json[D_JSON_IRHVAC_TURBO] = IRac::boolToString(state.turbo); - json[D_JSON_IRHVAC_ECONO] = IRac::boolToString(state.econo); - json[D_JSON_IRHVAC_LIGHT] = IRac::boolToString(state.light); - json[D_JSON_IRHVAC_FILTER] = IRac::boolToString(state.filter); - json[D_JSON_IRHVAC_CLEAN] = IRac::boolToString(state.clean); - json[D_JSON_IRHVAC_BEEP] = IRac::boolToString(state.beep); - json[D_JSON_IRHVAC_SLEEP] = state.sleep; - - String payload = ""; - payload.reserve(200); - json.printTo(payload); - return payload; -} - -String sendIRJsonState(const struct decode_results &results) { - String json("{"); - json += "\"" D_JSON_IR_PROTOCOL "\":\""; - json += typeToString(results.decode_type); - json += "\",\"" D_JSON_IR_BITS "\":"; - json += results.bits; - - if (hasACState(results.decode_type)) { - json += ",\"" D_JSON_IR_DATA "\":\"0x"; - json += resultToHexidecimal(&results); - json += "\""; - } else { - if (UNKNOWN != results.decode_type) { - json += ",\"" D_JSON_IR_DATA "\":"; - } else { - json += ",\"" D_JSON_IR_HASH "\":"; - } - if (Settings.flag.ir_receive_decimal) { - char svalue[32]; - ulltoa(results.value, svalue, 10); - json += svalue; - } else { - char hvalue[64]; - if (UNKNOWN != results.decode_type) { - Uint64toHex(results.value, hvalue, results.bits); - json += "\"0x"; - json += hvalue; - json += "\",\"" D_JSON_IR_DATALSB "\":\"0x"; - Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); - json += hvalue; - json += "\""; - } else { - Uint64toHex(results.value, hvalue, 32); - json += "\"0x"; - json += hvalue; - json += "\""; - } - } - } - json += ",\"" D_JSON_IR_REPEAT "\":"; - json += results.repeat; - - stdAc::state_t ac_result; - if (IRAcUtils::decodeToState(&results, &ac_result, nullptr)) { - - json += ",\"" D_CMND_IRHVAC "\":"; - json += sendACJsonState(ac_result); - } - - return json; -} - -void IrReceiveCheck(void) -{ - decode_results results; - - if (irrecv->decode(&results)) { - uint32_t now = millis(); - - - if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { - ir_lasttime = now; - Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); - - if (Settings.flag3.receive_raw) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); - uint16_t i; - for (i = 1; i < results.rawlen; i++) { - if (i > 1) { ResponseAppend_P(PSTR(",")); } - uint32_t usecs; - for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); - } - ResponseAppend_P(PSTR("%d"), usecs); - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } - } - uint16_t extended_length = results.rawlen - 1; - for (uint32_t j = 0; j < results.rawlen - 1; j++) { - uint32_t usecs = results.rawbuf[j] * kRawTick; - - extended_length += (usecs / (UINT16_MAX + 1)) * 2; - } - ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - - XdrvRulesProcess(); - } - - irrecv->resume(); - } -} - - - - - - - -String listSupportedProtocols(bool hvac) { - String l(""); - bool first = true; - for (uint32_t i = UNUSED + 1; i <= kLastDecodeType; i++) { - bool found = false; - if (hvac) { - found = IRac::isProtocolSupported((decode_type_t)i); - } else { - found = (IRsend::defaultBits((decode_type_t)i) > 0) && (!IRac::isProtocolSupported((decode_type_t)i)); - } - if (found) { - if (first) { - first = false; - } else { - l += "|"; - } - l += typeToString((decode_type_t)i); - } - } - return l; -} - - -const stdAc::fanspeed_t IrHvacFanSpeed[] PROGMEM = { stdAc::fanspeed_t::kAuto, - stdAc::fanspeed_t::kMin, stdAc::fanspeed_t::kLow,stdAc::fanspeed_t::kMedium, - stdAc::fanspeed_t::kHigh, stdAc::fanspeed_t::kMax }; - -uint32_t IrRemoteCmndIrHvacJson(void) -{ - stdAc::state_t state, prev; - char parm_uc[12]; - - - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } - - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(dataBufUc); - if (!json.success()) { return IE_INVALID_JSON; } - - - state.protocol = decode_type_t::UNKNOWN; - state.model = 1; - state.mode = stdAc::opmode_t::kAuto; - state.power = false; - state.celsius = true; - state.degrees = 21.0f; - state.fanspeed = stdAc::fanspeed_t::kMedium; - state.swingv = stdAc::swingv_t::kOff; - state.swingh = stdAc::swingh_t::kOff; - state.light = false; - state.beep = false; - state.econo = false; - state.filter = false; - state.turbo = false; - state.quiet = false; - state.sleep = -1; - state.clean = false; - state.clock = -1; - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); - if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); - if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } - if (decode_type_t::UNKNOWN == state.protocol) { return IE_UNSUPPORTED_HVAC; } - if (!IRac::isProtocolSupported(state.protocol)) { return IE_UNSUPPORTED_HVAC; } - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED)); - if (json.containsKey(parm_uc)) { - uint32_t fan_speed = json[parm_uc]; - if ((fan_speed >= 1) && (fan_speed <= 5)) { - state.fanspeed = (stdAc::fanspeed_t) pgm_read_byte(&IrHvacFanSpeed[fan_speed]); - } else { - state.fanspeed = IRac::strToFanspeed(json[parm_uc]); - } - } - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODEL)); - if (json.containsKey(parm_uc)) { state.model = IRac::strToModel(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE)); - if (json.containsKey(parm_uc)) { state.mode = IRac::strToOpmode(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGV)); - if (json.containsKey(parm_uc)) { state.swingv = IRac::strToSwingV(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGH)); - if (json.containsKey(parm_uc)) { state.swingh = IRac::strToSwingH(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TEMP)); - if (json.containsKey(parm_uc)) { state.degrees = json[parm_uc]; } - - - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER)); - if (json.containsKey(parm_uc)) { state.power = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CELSIUS)); - if (json.containsKey(parm_uc)) { state.celsius = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_LIGHT)); - if (json.containsKey(parm_uc)) { state.light = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_BEEP)); - if (json.containsKey(parm_uc)) { state.beep = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_ECONO)); - if (json.containsKey(parm_uc)) { state.econo = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FILTER)); - if (json.containsKey(parm_uc)) { state.filter = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TURBO)); - if (json.containsKey(parm_uc)) { state.turbo = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_QUIET)); - if (json.containsKey(parm_uc)) { state.quiet = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CLEAN)); - if (json.containsKey(parm_uc)) { state.clean = IRac::strToBool(json[parm_uc]); } - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SLEEP)); - if (json[parm_uc]) { state.sleep = json[parm_uc]; } - - - IRac ac(pin[GPIO_IRSEND]); - bool success = ac.sendAc(state, &prev); - if (!success) { return IE_SYNTAX_IRHVAC; } - - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":%s}"), sendACJsonState(state).c_str()); - return IE_RESPONSE_PROVIDED; -} - -void CmndIrHvac(void) -{ - uint8_t error = IE_SYNTAX_IRHVAC; - - if (XdrvMailbox.data_len) { - error = IrRemoteCmndIrHvacJson(); - } - if (error != IE_RESPONSE_PROVIDED) { IrRemoteCmndResponse(error); } -} - - - - - -uint32_t IrRemoteCmndIrSendJson(void) -{ - char parm_uc[12]; - - - - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } - - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(dataBufUc); - if (!json.success()) { return IE_INVALID_JSON; } - - - - decode_type_t protocol = decode_type_t::UNKNOWN; - uint16_t bits = 0; - uint64_t data; - uint8_t repeat = 0; - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); - if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); - if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } - if (decode_type_t::UNKNOWN == protocol) { return IE_UNSUPPORTED_PROTOCOL; } - - UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS)); - if (json.containsKey(parm_uc)) { bits = json[parm_uc]; } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT)); - if (json.containsKey(parm_uc)) { repeat = json[parm_uc]; } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATALSB)); - if (json.containsKey(parm_uc)) { data = reverseBitsInBytes64(strtoull(json[parm_uc], nullptr, 0)); } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA)); - if (json.containsKey(parm_uc)) { data = strtoull(json[parm_uc], nullptr, 0); } - if (0 == bits) { return IE_SYNTAX_IRSEND; } - - - if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; } - - char dvalue[32]; - char hvalue[32]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data 0x%s (%s), repeat %d"), - protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat); - - irsend_active = true; - bool success = irsend->send(protocol, data, bits, repeat); - - if (!success) { - irsend_active = false; - ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); - } - return IE_NO_ERROR; -} - -uint32_t IrRemoteCmndIrSendRaw(void) -{ - - - - - - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - if (p == nullptr) { - return IE_INVALID_RAWDATA; - } - - - uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; - - uint16_t freq = atoi(str); - if (!freq && (*str != '0')) { - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (count < 2) { - return IE_INVALID_RAWDATA; - } - - uint16_t parm[count]; - for (uint32_t i = 0; i < count; i++) { - parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - if (!parm[i]) { - if (!i) { - parm[0] = 38000; - } else { - return IE_INVALID_RAWDATA; - } - } - } - - uint16_t i = 0; - if (count < 4) { - - uint16_t mark = parm[1] *2; - if (3 == count) { - if (parm[2] < parm[1]) { - - mark = parm[1] * parm[2]; - } else { - - mark = parm[2]; - } - } - uint16_t raw_array[strlen(p)]; - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[1]; - } - else if (*p == '1') { - raw_array[i++] = mark; - } - } - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { - irsend->space(40000); - } - } - } - else if (6 == count) { - - uint16_t raw_array[strlen(p)*2+3]; - raw_array[i++] = parm[1]; - raw_array[i++] = parm[2]; - uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; - uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[3]; - raw_array[i++] = parm[4]; - } - else if (*p == '1') { - raw_array[i++] = parm[3]; - raw_array[i++] = parm[5]; - } - } - raw_array[i++] = parm[3]; - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { - irsend->space(inter_message); - } - } - } - else { - return IE_INVALID_RAWDATA; - } - } else { - if (!freq) { freq = 38000; } - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (0 == count) { - return IE_INVALID_RAWDATA; - } - - - count++; - if (count < 200) { - uint16_t raw_array[count]; - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - } - - - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - } else { - uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); - if (raw_array == nullptr) { - return IE_INVALID_RAWDATA; - } - - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - } - - - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - free(raw_array); - } - } - - return IE_NO_ERROR; -} - -void CmndIrSend(void) -{ - uint8_t error = IE_SYNTAX_IRSEND; - - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, "{") == nullptr) { - error = IrRemoteCmndIrSendRaw(); - } else { - error = IrRemoteCmndIrSendJson(); - } - } - IrRemoteCmndResponse(error); -} - -void IrRemoteCmndResponse(uint32_t error) -{ - switch (error) { - case IE_INVALID_RAWDATA: - ResponseCmndChar(D_JSON_INVALID_RAWDATA); - break; - case IE_INVALID_JSON: - ResponseCmndChar(D_JSON_INVALID_JSON); - break; - case IE_SYNTAX_IRSEND: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); - break; - case IE_SYNTAX_IRHVAC: - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); - break; - case IE_UNSUPPORTED_HVAC: - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR " (%s)\"}"), listSupportedProtocols(true).c_str()); - break; - case IE_UNSUPPORTED_PROTOCOL: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_PROTOCOL " (%s)\"}"), listSupportedProtocols(false).c_str()); - break; - default: - ResponseCmndDone(); - } -} - - - - - -bool Xdrv05(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { - switch (function) { - case FUNC_PRE_INIT: - if (pin[GPIO_IRSEND] < 99) { - IrSendInit(); - } - if (pin[GPIO_IRRECV] < 99) { - IrReceiveInit(); - } - break; - case FUNC_EVERY_50_MSECOND: - if (pin[GPIO_IRRECV] < 99) { - IrReceiveCheck(); - } - irsend_active = false; - break; - case FUNC_COMMAND: - if (pin[GPIO_IRSEND] < 99) { - result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); - } - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_06_snfbridge.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_06_snfbridge.ino" -#ifdef USE_SONOFF_RF - - - - -#define XDRV_06 6 - -const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; - -enum SonoffBridgeCommands { - CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE }; - -const char kSonoffBridgeCommands[] PROGMEM = "|" - D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY "|" D_CMND_RFRAW; - -void (* const SonoffBridgeCommand[])(void) PROGMEM = { - &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfKey, &CmndRfRaw }; - -struct SONOFFBRIDGE { - uint32_t last_received_id = 0; - uint32_t last_send_code = 0; - uint32_t last_time = 0; - uint32_t last_learn_time = 0; - uint8_t receive_flag = 0; - uint8_t receive_raw_flag = 0; - uint8_t learn_key = 1; - uint8_t learn_active = 0; - uint8_t expected_bytes = 0; -} SnfBridge; - -#ifdef USE_RF_FLASH - - - - - - - -#include "ihx.h" -#include "c2.h" - -const ssize_t RF_RECORD_NO_START_FOUND = -1; -const ssize_t RF_RECORD_NO_END_FOUND = -2; - -ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) -{ - for (size_t i = 0; i < size; i++) { - if (buf[i] == ':') { - return i; - } - } - return RF_RECORD_NO_START_FOUND; -} - -ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size) -{ - for (size_t i = 0; i < size; i++) { - if (buf[i] == '\n') { - return i; - } - } - return RF_RECORD_NO_END_FOUND; -} - -ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len) -{ - ssize_t record_start; - ssize_t record_end; - ssize_t glue_record_sz; - uint8_t *glue_buf; - ssize_t result; - - if (remnant_data[0] != ':') { return -8; } - - - record_end = rf_find_hex_record_end(new_data, new_data_len); - record_start = rf_find_hex_record_start(new_data, new_data_len); - - - - - if ((record_start != RF_RECORD_NO_START_FOUND) && (record_start < record_end)) { - return -8; - } - - glue_record_sz = strlen((const char *) remnant_data) + record_end; - - glue_buf = (uint8_t *) malloc(glue_record_sz); - if (glue_buf == nullptr) { return -2; } - - - memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); - memcpy(glue_buf + strlen((const char *) remnant_data), new_data, record_end); - - result = rf_decode_and_write(glue_buf, glue_record_sz); - free(glue_buf); - return result; -} - -ssize_t rf_decode_and_write(uint8_t *record, size_t size) -{ - uint8_t err = ihx_decode(record, size); - if (err != IHX_SUCCESS) { return -13; } - - ihx_t *h = (ihx_t *) record; - if (h->record_type == IHX_RT_DATA) { - int retries = 5; - uint16_t address = h->address_high * 0x100 + h->address_low; - - do { - err = c2_programming_init(); - err = c2_block_write(address, h->data, h->len); - } while (err != C2_SUCCESS && retries--); - } else if (h->record_type == IHX_RT_END_OF_FILE) { - - err = c2_reset(); - } - - if (err != C2_SUCCESS) { return -12; } - - return 0; -} - -ssize_t rf_search_and_write(uint8_t *buf, size_t size) -{ - - ssize_t rec_end; - ssize_t rec_start; - ssize_t err; - - for (size_t i = 0; i < size; i++) { - - rec_start = rf_find_hex_record_start(buf + i, size - i); - if (rec_start == RF_RECORD_NO_START_FOUND) { - - return -8; - } - - - rec_start += i; - rec_end = rf_find_hex_record_end(buf + rec_start, size - rec_start); - if (rec_end == RF_RECORD_NO_END_FOUND) { - - return rec_start; - } - - - rec_end += rec_start; - - err = rf_decode_and_write(buf + rec_start, rec_end - rec_start); - if (err < 0) { return err; } - i = rec_end; - } - - return 0; -} - -uint8_t rf_erase_flash(void) -{ - uint8_t err; - - for (uint32_t i = 0; i < 4; i++) { - err = c2_programming_init(); - if (err != C2_SUCCESS) { - return 10; - } - err = c2_device_erase(); - if (err != C2_SUCCESS) { - if (i < 3) { - c2_reset(); - } else { - return 11; - } - } else { - break; - } - } - return 0; -} - -uint8_t SnfBrUpdateInit(void) -{ - pinMode(PIN_C2CK, OUTPUT); - pinMode(PIN_C2D, INPUT); - - return rf_erase_flash(); -} -#endif - - - -void SonoffBridgeReceivedRaw(void) -{ - - uint8_t buckets = 0; - - if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } - - ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); - for (uint32_t i = 0; i < serial_in_byte_counter; i++) { - ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); - if (0xB1 == serial_in_buffer[1]) { - if ((i > 3) && buckets) { buckets--; } - if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { - ResponseAppend_P(PSTR(" ")); - } - } - } - ResponseAppend_P(PSTR("\"}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); - - XdrvRulesProcess(); -} - - - -void SonoffBridgeLearnFailed(void) -{ - SnfBridge.learn_active = 0; - Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARN_FAILED); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); -} - -void SonoffBridgeReceived(void) -{ - uint16_t sync_time = 0; - uint16_t low_time = 0; - uint16_t high_time = 0; - uint32_t received_id = 0; - char rfkey[8]; - char stemp[16]; - - AddLogSerial(LOG_LEVEL_DEBUG); - - if (0xA2 == serial_in_buffer[0]) { - SonoffBridgeLearnFailed(); - } - else if (0xA3 == serial_in_buffer[0]) { - SnfBridge.learn_active = 0; - low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; - high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; - if (low_time && high_time) { - for (uint32_t i = 0; i < 9; i++) { - Settings.rf_code[SnfBridge.learn_key][i] = serial_in_buffer[i +1]; - } - Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); - } else { - SonoffBridgeLearnFailed(); - } - } - else if (0xA4 == serial_in_buffer[0]) { - if (SnfBridge.learn_active) { - SonoffBridgeLearnFailed(); - } else { - sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; - low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; - high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; - received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9]; - - unsigned long now = millis(); - if (!((received_id == SnfBridge.last_received_id) && (now - SnfBridge.last_time < SFB_TIME_AVOID_DUPLICATE))) { - SnfBridge.last_received_id = received_id; - SnfBridge.last_time = now; - strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey)); - for (uint32_t i = 1; i <= 16; i++) { - if (Settings.rf_code[i][0]) { - uint32_t send_id = Settings.rf_code[i][6] << 16 | Settings.rf_code[i][7] << 8 | Settings.rf_code[i][8]; - if (send_id == received_id) { - snprintf_P(rfkey, sizeof(rfkey), PSTR("%d"), i); - break; - } - } - } - if (Settings.flag.rf_receive_decimal) { - snprintf_P(stemp, sizeof(stemp), PSTR("%u"), received_id); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); - } - ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), - sync_time, low_time, high_time, stemp, rfkey); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); - XdrvRulesProcess(); - #ifdef USE_DOMOTICZ - DomoticzSensor(DZ_COUNT, received_id); - #endif - } - } - } -} - -bool SonoffBridgeSerialInput(void) -{ - - static int8_t receive_len = 0; - - if (SnfBridge.receive_flag) { - if (SnfBridge.receive_raw_flag) { - if (!serial_in_byte_counter) { - serial_in_buffer[serial_in_byte_counter++] = 0xAA; - } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 3) { - if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { - receive_len = serial_in_buffer[2] + 4; - } - } - if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { - SonoffBridgeReceivedRaw(); - SnfBridge.receive_flag = 0; - return 1; - } - } - else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { - if (0 == serial_in_byte_counter) { - SnfBridge.expected_bytes = 2; - if (serial_in_byte >= 0xA3) { - SnfBridge.expected_bytes = 11; - } - if (serial_in_byte == 0xA6) { - SnfBridge.expected_bytes = 0; - serial_in_buffer[serial_in_byte_counter++] = 0xAA; - SnfBridge.receive_raw_flag = 1; - } - } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if ((SnfBridge.expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { - SonoffBridgeReceived(); - SnfBridge.receive_flag = 0; - return 1; - } - } - serial_in_byte = 0; - } - if (0xAA == serial_in_byte) { - serial_in_byte_counter = 0; - serial_in_byte = 0; - SnfBridge.receive_flag = 1; - receive_len = 0; - } - return 0; -} - -void SonoffBridgeSendCommand(uint8_t code) -{ - Serial.write(0xAA); - Serial.write(code); - Serial.write(0x55); -} - -void SonoffBridgeSendAck(void) -{ - Serial.write(0xAA); - Serial.write(0xA0); - Serial.write(0x55); -} - -void SonoffBridgeSendCode(uint32_t code) -{ - Serial.write(0xAA); - Serial.write(0xA5); - for (uint32_t i = 0; i < 6; i++) { - Serial.write(Settings.rf_code[0][i]); - } - Serial.write((code >> 16) & 0xff); - Serial.write((code >> 8) & 0xff); - Serial.write(code & 0xff); - Serial.write(0x55); - Serial.flush(); -} - -void SonoffBridgeSend(uint8_t idx, uint8_t key) -{ - uint8_t code; - - key--; - Serial.write(0xAA); - Serial.write(0xA5); - for (uint32_t i = 0; i < 8; i++) { - Serial.write(Settings.rf_code[idx][i]); - } - if (0 == idx) { - code = (0x10 << (key >> 2)) | (1 << (key & 3)); - } else { - code = Settings.rf_code[idx][8]; - } - Serial.write(code); - Serial.write(0x55); - Serial.flush(); -#ifdef USE_DOMOTICZ - - -#endif -} - -void SonoffBridgeLearn(uint8_t key) -{ - SnfBridge.learn_key = key; - SnfBridge.learn_active = 1; - SnfBridge.last_learn_time = millis(); - Serial.write(0xAA); - Serial.write(0xA1); - Serial.write(0x55); -} - - - - - -void CmndRfBridge(void) -{ - char *p; - char stemp [10]; - uint32_t code = 0; - uint8_t radix = 10; - - uint32_t set_index = XdrvMailbox.command_code *2; - - if (XdrvMailbox.data[0] == '#') { - XdrvMailbox.data++; - XdrvMailbox.data_len--; - radix = 16; - } - - if (XdrvMailbox.data_len) { - code = strtol(XdrvMailbox.data, &p, radix); - if (code) { - if (CMND_RFCODE == XdrvMailbox.command_code) { - SnfBridge.last_send_code = code; - SonoffBridgeSendCode(code); - } else { - if (1 == XdrvMailbox.payload) { - code = pgm_read_byte(kDefaultRfCode + set_index) << 8 | pgm_read_byte(kDefaultRfCode + set_index +1); - } - uint8_t msb = code >> 8; - uint8_t lsb = code & 0xFF; - if ((code > 0) && (code < 0x7FFF) && (msb != 0x55) && (lsb != 0x55)) { - Settings.rf_code[0][set_index] = msb; - Settings.rf_code[0][set_index +1] = lsb; - } - } - } - } - if (CMND_RFCODE == XdrvMailbox.command_code) { - code = SnfBridge.last_send_code; - } else { - code = Settings.rf_code[0][set_index] << 8 | Settings.rf_code[0][set_index +1]; - } - if (10 == radix) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), code); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"#%06X\""), code); - } - Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp); -} - -void CmndRfKey(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) { - unsigned long now = millis(); - if ((!SnfBridge.learn_active) || (now - SnfBridge.last_learn_time > 60100)) { - SnfBridge.learn_active = 0; - if (2 == XdrvMailbox.payload) { - SonoffBridgeLearn(XdrvMailbox.index); - ResponseCmndIdxChar(D_JSON_START_LEARNING); - } - else if (3 == XdrvMailbox.payload) { - Settings.rf_code[XdrvMailbox.index][0] = 0; - ResponseCmndIdxChar(D_JSON_SET_TO_DEFAULT); - } - else if (4 == XdrvMailbox.payload) { - for (uint32_t i = 0; i < 6; i++) { - Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i]; - } - Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff; - Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff; - Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff; - ResponseCmndIdxChar(D_JSON_SAVED); - } else if (5 == XdrvMailbox.payload) { - uint8_t key = XdrvMailbox.index; - uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; - uint16_t sync_time = (Settings.rf_code[index][0] << 8) | Settings.rf_code[index][1]; - uint16_t low_time = (Settings.rf_code[index][2] << 8) | Settings.rf_code[index][3]; - uint16_t high_time = (Settings.rf_code[index][4] << 8) | Settings.rf_code[index][5]; - uint32_t code = (Settings.rf_code[index][6] << 16) | (Settings.rf_code[index][7] << 8); - if (0 == index) { - key--; - code |= (uint8_t)((0x10 << (key >> 2)) | (1 << (key & 3))); - } else { - code |= Settings.rf_code[index][8]; - } - Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), - XdrvMailbox.command, XdrvMailbox.index, sync_time, low_time, high_time, code); - } else { - if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { - SonoffBridgeSend(0, XdrvMailbox.index); - ResponseCmndIdxChar(D_JSON_DEFAULT_SENT); - } else { - SonoffBridgeSend(XdrvMailbox.index, 0); - ResponseCmndIdxChar(D_JSON_LEARNED_SENT); - } - } - } else { - Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, SnfBridge.learn_key, D_JSON_LEARNING_ACTIVE); - } - } -} - -void CmndRfRaw(void) -{ - if (XdrvMailbox.data_len) { - if (XdrvMailbox.data_len < 6) { - switch (XdrvMailbox.payload) { - case 0: - SonoffBridgeSendCommand(0xA7); - case 1: - SnfBridge.receive_raw_flag = XdrvMailbox.payload; - break; - case 166: - case 167: - case 169: - case 176: - case 177: - case 255: - SonoffBridgeSendCommand(XdrvMailbox.payload); - SnfBridge.receive_raw_flag = 1; - break; - case 192: - char beep[] = "AAC000C055\0"; - SerialSendRaw(beep); - break; - } - } else { - SerialSendRaw(RemoveSpace(XdrvMailbox.data)); - SnfBridge.receive_raw_flag = 1; - } - } - ResponseCmndStateText(SnfBridge.receive_raw_flag); -} - - - - - -bool Xdrv06(uint8_t function) -{ - bool result = false; - - if (SONOFF_BRIDGE == my_module_type) { - switch (function) { - case FUNC_SERIAL: - result = SonoffBridgeSerialInput(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kSonoffBridgeCommands, SonoffBridgeCommand); - break; - case FUNC_INIT: - SnfBridge.receive_raw_flag = 0; - SonoffBridgeSendCommand(0xA7); - break; - case FUNC_PRE_INIT: - SetSerial(19200, TS_SERIAL_8N1); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_07_domoticz.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_07_domoticz.ino" -#ifdef USE_DOMOTICZ - -#define XDRV_07 7 - -#define D_PRFX_DOMOTICZ "Domoticz" -#define D_CMND_IDX "Idx" -#define D_CMND_KEYIDX "KeyIdx" -#define D_CMND_SWITCHIDX "SwitchIdx" -#define D_CMND_SENSORIDX "SensorIdx" -#define D_CMND_UPDATETIMER "UpdateTimer" - -const char kDomoticzCommands[] PROGMEM = D_PRFX_DOMOTICZ "|" - D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ; - -void (* const DomoticzCommand[])(void) PROGMEM = { - &CmndDomoticzIdx, &CmndDomoticzKeyIdx, &CmndDomoticzSwitchIdx, &CmndDomoticzSensorIdx, &CmndDomoticzUpdateTimer }; - -const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; - -#if MAX_DOMOTICZ_SNS_IDX < DZ_MAX_SENSORS - #error "Domoticz: Too many sensors or change settings.h layout" -#endif - -const char kDomoticzSensors[] PROGMEM = - D_DOMOTICZ_TEMP "|" D_DOMOTICZ_TEMP_HUM "|" D_DOMOTICZ_TEMP_HUM_BARO "|" D_DOMOTICZ_POWER_ENERGY "|" D_DOMOTICZ_ILLUMINANCE "|" - D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER "|" D_DOMOTICZ_SHUTTER ; - -char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; - -int domoticz_update_timer = 0; -uint32_t domoticz_fan_debounce = 0; -bool domoticz_subscribe = false; -bool domoticz_update_flag = true; - -#ifdef USE_SHUTTER -bool domoticz_is_shutter = false; -#endif - -int DomoticzBatteryQuality(void) -{ - - - - - int quality = 100; - -#ifdef USE_ADC_VCC - uint16_t voltage = ESP.getVcc(); - if (voltage <= 2600) { - quality = 0; - } else if (voltage >= 4600) { - quality = 200; - } else { - quality = (voltage - 2600) / 10; - } -#endif - return quality; -} - -int DomoticzRssiQuality(void) -{ - - - return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; -} - -#ifdef USE_SONOFF_IFAN -void MqttPublishDomoticzFanState(void) -{ - if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { - char svalue[8]; - - int fan_speed = GetFanspeed(); - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); - Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); - MqttPublish(domoticz_in_topic); - - domoticz_fan_debounce = millis(); - } -} - -void DomoticzUpdateFanState(void) -{ - if (domoticz_update_flag) { - MqttPublishDomoticzFanState(); - } - domoticz_update_flag = true; -} -#endif - -void MqttPublishDomoticzPowerState(uint8_t device) -{ - if (Settings.flag.mqtt_enabled) { - if ((device < 1) || (device > devices_present)) { device = 1; } - if (Settings.domoticz_relay_idx[device -1]) { -#ifdef USE_SHUTTER - if (domoticz_is_shutter) { - - } else { -#endif -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (device > 1)) { - - } else { -#endif - char svalue[8]; - - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); - Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); - MqttPublish(domoticz_in_topic); -#ifdef USE_SONOFF_IFAN - } -#endif -#ifdef USE_SHUTTER - } -#endif - } - } -} - -void DomoticzUpdatePowerState(uint8_t device) -{ - if (domoticz_update_flag) { - MqttPublishDomoticzPowerState(device); - } - domoticz_update_flag = true; -} - -void DomoticzMqttUpdate(void) -{ - if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) { - domoticz_update_timer--; - if (domoticz_update_timer <= 0) { - domoticz_update_timer = Settings.domoticz_update_timer; - for (uint32_t i = 1; i <= devices_present; i++) { -#ifdef USE_SHUTTER - if (domoticz_is_shutter) - { - - break; - } -#endif -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (i > 1)) { - MqttPublishDomoticzFanState(); - break; - } else { -#endif - MqttPublishDomoticzPowerState(i); -#ifdef USE_SONOFF_IFAN - } -#endif - } - } - } -} - -void DomoticzMqttSubscribe(void) -{ - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (uint32_t i = 0; i < maxdev; i++) { - if (Settings.domoticz_relay_idx[i]) { - domoticz_subscribe = true; - } - } - - if (domoticz_subscribe) { - char stopic[TOPSZ]; - snprintf_P(stopic, sizeof(stopic), PSTR(DOMOTICZ_OUT_TOPIC "/#")); - MqttSubscribe(stopic); - } -} -# 219 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_07_domoticz.ino" -bool DomoticzMqttData(void) -{ - domoticz_update_flag = true; - - if (strncasecmp_P(XdrvMailbox.topic, PSTR(DOMOTICZ_OUT_TOPIC), strlen(DOMOTICZ_OUT_TOPIC)) != 0) { - return false; - } - - - if (XdrvMailbox.data_len < 20) { - return true; - } - StaticJsonBuffer<400> jsonBuf; - JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data); - if (!domoticz.success()) { - return true; - } - - - - uint32_t idx = domoticz["idx"]; - int16_t nvalue = -1; - if (domoticz.containsKey("nvalue")) { - nvalue = domoticz["nvalue"]; - } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); - - bool found = false; - if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (uint32_t i = 0; i < maxdev; i++) { - if (idx == Settings.domoticz_relay_idx[i]) { - bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; - bool isShutter = strcmp_P(domoticz["dtype"],PSTR("Light/Switch")) == 0 & strncmp_P(domoticz["switchType"],PSTR("Blinds"), 6) == 0; - - char stemp1[10]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (1 == i)) { - uint8_t svalue = 0; - if (domoticz.containsKey("svalue1")) { - svalue = domoticz["svalue1"]; - } else { - return true; - } - svalue = (nvalue == 2) ? svalue / 10 : 0; - if (GetFanspeed() == svalue) { - return true; - } - if (TimePassedSince(domoticz_fan_debounce) < 1000) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); - found = true; - } else -#endif -#ifdef USE_SHUTTER - if (isShutter) - { - if (domoticz.containsKey("nvalue")) { - nvalue = domoticz["nvalue"]; - } - - uint8_t position = 0; - if (domoticz.containsKey("svalue1")) { - position = domoticz["svalue1"]; - } - if (nvalue != 2) { - position = nvalue == 0 ? 0 : 100; - } - - snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); - XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); - - found = true; - } else -#endif - if (iscolordimmer && 10 == nvalue) { - - JsonObject& color = domoticz["Color"]; - uint16_t level = nvalue = domoticz["svalue1"]; - uint16_t r = color["r"]; r = r * level / 100; - uint16_t g = color["g"]; g = g * level / 100; - uint16_t b = color["b"]; b = b * level / 100; - uint16_t cw = color["cw"]; cw = cw * level / 100; - uint16_t ww = color["ww"]; ww = ww * level / 100; - uint16_t m = 0; - uint16_t t = 0; - if (color.containsKey("m")) { - m = color["m"]; - t = color["t"]; - } - if (2 == m) { - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_BACKLOG)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR(D_CMND_COLORTEMPERATURE " %d;" D_CMND_DIMMER " %d"), changeUIntScale(t, 0, 255, CT_MIN, CT_MAX), level); - } else { - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); - } - found = true; - } - else if ((!iscolordimmer && 2 == nvalue) || - (iscolordimmer && 15 == nvalue)) { - if (domoticz.containsKey("svalue1")) { - nvalue = domoticz["svalue1"]; - } else { - return true; - } - if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } - else if (1 == nvalue || 0 == nvalue) { - if (((power >> i) &1) == (power_t)nvalue) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } - break; - } - } - } - if (!found) { return true; } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); - - domoticz_update_flag = false; - return false; -} - - - -bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg) -{ - bool result = false; - - if (device <= MAX_DOMOTICZ_IDX) { - if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { - Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), - (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); - MqttPublish(domoticz_in_topic); - result = true; - } - } - return result; -} -# 391 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_07_domoticz.ino" -uint8_t DomoticzHumidityState(char *hum) -{ - uint8_t h = atoi(hum); - return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; -} - -void DomoticzSensor(uint8_t idx, char *data) -{ - if (Settings.domoticz_sensor_idx[idx]) { - char dmess[128]; - - memcpy(dmess, mqtt_data, sizeof(dmess)); - if (DZ_AIRQUALITY == idx) { - Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), - Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); - } else { - uint8_t nvalue = 0; -#ifdef USE_SHUTTER - if (DZ_SHUTTER == idx) { - uint8_t position = atoi(data); - nvalue = position < 2 ? 0 : (position == 100 ? 1 : 2); - } -#endif - Response_P(DOMOTICZ_MESSAGE, - Settings.domoticz_sensor_idx[idx], nvalue, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); - } - MqttPublish(domoticz_in_topic); - memcpy(mqtt_data, dmess, sizeof(dmess)); - } -} - -void DomoticzSensor(uint8_t idx, uint32_t value) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%d"), value); - DomoticzSensor(idx, data); -} - -void DomoticzTempHumSensor(char *temp, char *hum) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temp, hum, DomoticzHumidityState(hum)); - DomoticzSensor(DZ_TEMP_HUM, data); -} - -void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro) -{ - char data[32]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temp, hum, DomoticzHumidityState(hum), baro); - DomoticzSensor(DZ_TEMP_HUM_BARO, data); -} - -void DomoticzSensorPowerEnergy(int power, char *energy) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%d;%s"), power, energy); - DomoticzSensor(DZ_POWER_ENERGY, data); -} - -void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power) -{ - - - - - - int consumed = power; - int produced = 0; - if (power < 0) { - consumed = 0; - produced = -power; - } - char data[64]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced); - DomoticzSensor(DZ_P1_SMART_METER, data); -} - - - - - -void CmndDomoticzIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndIdxNumber(Settings.domoticz_relay_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzKeyIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_key_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzSwitchIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_switch_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzSensorIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzUpdateTimer(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.domoticz_update_timer = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.domoticz_update_timer); -} - - - - - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_DOMOTICZ "dm" - -const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; - -const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = - "

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

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


" - "



" - "

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

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

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

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

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

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

")); - WSContentSend_P(PSTR("

"),"/upl",D_UPL_DONE); - - WSContentStop(); -} - - - -void script_upload(void) { - - - - HTTPUpload& upload = WebServer->upload(); - if (upload.status == UPLOAD_FILE_START) { - char npath[48]; - sprintf(npath,"%s/%s",path,upload.filename.c_str()); - SD.remove(npath); - upload_file=SD.open(npath,FILE_WRITE); - if (!upload_file) Web.upload_error=1; - } else if(upload.status == UPLOAD_FILE_WRITE) { - if (upload_file) upload_file.write(upload.buf,upload.currentSize); - } else if(upload.status == UPLOAD_FILE_END) { - if (upload_file) upload_file.close(); - if (Web.upload_error) { - AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error")); - } - } else { - Web.upload_error=1; - WebServer->send(500, "text/plain", "500: couldn't create file"); - } -} - -uint8_t DownloadFile(char *file) { - File download_file; - WiFiClient download_Client; - - if (!SD.exists(file)) { - AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); - return 0; - } - - download_file=SD.open(file,FILE_READ); - if (!download_file) { - AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); - return 0; - } - - if (download_file.isDirectory()) { - download_file.close(); - return 1; - } - - uint32_t flen=download_file.size(); - - download_Client = WebServer->client(); - WebServer->setContentLength(flen); - - char attachment[100]; - char *cp; - for (uint8_t cnt=strlen(file); cnt>=0; cnt--) { - if (file[cnt]=='/') { - cp=&file[cnt+1]; - break; - } - } - snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp); - WebServer->sendHeader(F("Content-Disposition"), attachment); - WSSend(200, CT_STREAM, ""); - - uint8_t buff[512]; - uint16_t bread; - - - uint8_t cnt=0; - while (download_file.available()) { - bread=download_file.read(buff,sizeof(buff)); - uint16_t bw=download_Client.write((const char*)buff,bread); - if (!bw) break; - cnt++; - if (cnt>7) { - cnt=0; - if (glob_script_mem.script_loglevel&0x80) { - - loop(); - } - } - } - download_file.close(); - download_Client.stop(); - return 0; -} - -#endif - - -void HandleScriptTextareaConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - ScriptSaveSettings(); - HandleConfiguration(); - return; - } -} - -void HandleScriptConfiguration(void) { - - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT); - -#ifdef USE_SCRIPT_FATFS - if (WebServer->hasArg("d1")) { - DownloadFile(glob_script_mem.flink[0]); - } - if (WebServer->hasArg("d2")) { - DownloadFile(glob_script_mem.flink[1]); - } - if (WebServer->hasArg("upl")) { - Script_FileUploadConfiguration(); - } -#endif - - WSContentStart_P(S_CONFIGURE_SCRIPT); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_SCRIPT); - - -#ifdef xSCRIPT_STRIP_COMMENTS - uint16_t ssize=glob_script_mem.script_size; - if (bitRead(Settings.rule_enabled, 1)) ssize*=2; - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",ssize); -#else - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); -#endif - - - if (glob_script_mem.script_ram[0]) { - _WSContentSend(glob_script_mem.script_ram); - } - WSContentSend_P(HTTP_FORM_SCRIPT1b); - -#ifdef USE_SCRIPT_FATFS - if (glob_script_mem.script_sd_found) { - WSContentSend_P(HTTP_FORM_SCRIPT1d); - if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); - if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); - } -#endif - - WSContentSend_P(HTTP_SCRIPT_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); - } - - -void ScriptSaveSettings(void) { - - if (WebServer->hasArg("c1")) { - bitWrite(Settings.rule_enabled,0,1); - } else { - bitWrite(Settings.rule_enabled,0,0); - } - - - String str = WebServer->arg("t1"); - - if (*str.c_str()) { - - str.replace("\r\n","\n"); - str.replace("\r","\n"); - -#ifdef xSCRIPT_STRIP_COMMENTS - if (bitRead(Settings.rule_enabled, 1)) { - char *sp=(char*)str.c_str(); - char *sp1=sp; - char *dp=sp; - uint8_t flg=0; - while (*sp) { - while (*sp==' ') sp++; - sp1=sp; - sp=strchr(sp,'\n'); - if (!sp) { - flg=1; - } else { - *sp=0; - } - if (*sp1!=';') { - uint8_t slen=strlen(sp1); - if (slen) { - strcpy(dp,sp1); - dp+=slen; - *dp++='\n'; - } - } - if (flg) { - *dp=0; - break; - } - sp++; - } - } -#endif - - strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); - -#ifdef USE_24C256 -#ifndef USE_SCRIPT_FATFS - if (glob_script_mem.flags&1) { - EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); - } -#endif -#endif - -#ifdef USE_SCRIPT_FATFS - if (glob_script_mem.flags&1) { - SD.remove(FAT_SCRIPT_NAME); - File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE); - file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE); - file.close(); - } -#endif - - } - - if (glob_script_mem.script_mem) { - Scripter_save_pvars(); - free(glob_script_mem.script_mem); - glob_script_mem.script_mem=0; - glob_script_mem.script_mem_size=0; - } - - if (bitRead(Settings.rule_enabled, 0)) { - int16_t res=Init_Scripter(); - if (res) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); - return; - } - Run_Scripter(">B",2,0); - fast_script=Run_Scripter(">F",-2,0); - } -} - -#endif - - -#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) - - -#define HUE_DEV_MVNUM 5 -#define HUE_DEV_NSIZE 16 -struct HUE_SCRIPT { - char name[HUE_DEV_NSIZE]; - uint8_t type; - uint8_t index[HUE_DEV_MVNUM]; - uint8_t vindex[HUE_DEV_MVNUM]; -} hue_script[32]; - - -const char SCRIPT_HUE_LIGHTS_STATUS_JSON1[] PROGMEM = - "{\"state\":" - "{\"on\":{state}," - "{light_status}" - "\"alert\":\"none\"," - "\"effect\":\"none\"," - "\"reachable\":true}" - ",\"type\":\"{type}\"," - "\"name\":\"{j1\"," - "\"modelid\":\"{m1}\"," - "\"uniqueid\":\"{j2\"," - "\"swversion\":\"5.50.1.19085\"}"; -# 3624 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" -const char SCRIPT_HUE_LIGHTS_STATUS_JSON2[] PROGMEM = -"{\"state\":{" -"\"presence\":{state}," -"\"lastupdated\":\"2017-10-01T12:37:30\"" -"}," -"\"swupdate\":{" -"\"state\":\"noupdates\"," -"\"lastinstall\": null" -"}," -"\"config\":{" -"\"on\":true," -"\"battery\":100," -"\"reachable\":true," -"\"alert\":\"none\"," -"\"ledindication\":false," -"\"usertest\":false," -"\"sensitivity\":2," -"\"sensitivitymax\":2," -"\"pending\":[]" -"}," -"\"name\":\"{j1\"," -"\"type\":\"ZLLPresence\"," -"\"modelid\":\"SML001\"," -"\"manufacturername\":\"Philips\"," -"\"swversion\":\"6.1.0.18912\"," -"\"uniqueid\":\"{j2\"" -"}"; -# 3705 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" -void Script_HueStatus(String *response, uint16_t hue_devs) { - - if (hue_script[hue_devs].type=='p') { - *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON2); - response->replace("{j1",hue_script[hue_devs].name); - response->replace("{j2", GetHueDeviceId(hue_devs)); - uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; - response->replace("{state}", (pwr ? "true" : "false")); - return; - } - - *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1); - uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; - response->replace("{state}", (pwr ? "true" : "false")); - String light_status = ""; - if (hue_script[hue_devs].index[1]>0) { - - light_status += "\"bri\":"; - uint32_t bri=glob_script_mem.fvars[hue_script[hue_devs].index[1]-1]; - if (bri > 254) bri = 254; - if (bri < 1) bri = 1; - light_status += String(bri); - light_status += ","; - } - if (hue_script[hue_devs].index[2]>0) { - - uint32_t hue=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1]; - - light_status += "\"hue\":"; - light_status += String(hue); - light_status += ","; - } - if (hue_script[hue_devs].index[3]>0) { - - uint32_t sat=glob_script_mem.fvars[hue_script[hue_devs].index[3]-1] ; - if (sat > 254) sat = 254; - if (sat < 1) sat = 1; - light_status += "\"sat\":"; - light_status += String(sat); - light_status += ","; - } - if (hue_script[hue_devs].index[4]>0) { - - uint32_t ct=glob_script_mem.fvars[hue_script[hue_devs].index[4]-1]; - light_status += "\"ct\":"; - light_status += String(ct); - light_status += ","; - } - - float temp; - switch (hue_script[hue_devs].type) { - case 'C': - response->replace("{type}","Color Ligh"); - response->replace("{m1","LST001"); - break; - case 'D': - response->replace("{type}","Dimmable Light"); - response->replace("{m1","LWB004"); - break; - case 'T': - response->replace("{type}","Color Temperature Light"); - response->replace("{m1","LTW011"); - break; - case 'E': - response->replace("{type}","Extended color light"); - response->replace("{m1","LCT007"); - break; - case 'S': - response->replace("{type}","On/Off light"); - response->replace("{m1","LCT007"); - break; - default: - response->replace("{type}","color light"); - response->replace("{m1","LST001"); - break; - } - - response->replace("{light_status}", light_status); - response->replace("{j1",hue_script[hue_devs].name); - response->replace("{j2", GetHueDeviceId(hue_devs)); - -} - -void Script_Check_Hue(String *response) { - if (!bitRead(Settings.rule_enabled, 0)) return; - - uint8_t hue_script_found=Run_Scripter(">H",-2,0); - if (hue_script_found!=99) return; - - char line[128]; - char tmp[128]; - uint8_t hue_devs=0; - uint8_t vindex=0; - char *cp; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - SCRIPT_SKIP_SPACES - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - cp=line; - for (uint32_t i=0; i0) *response+=",\""; - } - *response+=String(EncodeLightId(hue_devs+devices_present+1))+"\":"; - Script_HueStatus(response,hue_devs); - } - - hue_devs++; - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } -#if 0 - if (response) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs); - toLog(">>>>"); - toLog(response->c_str()); - toLog(response->c_str()+LOGSZ); - } -#endif -} - -const char sHUE_LIGHT_RESPONSE_JSON[] PROGMEM = - "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; - -const char sHUE_SENSOR_RESPONSE_JSON[] PROGMEM = - "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; - -const char sHUE_ERROR_JSON[] PROGMEM = - "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; - - - -void Script_Handle_Hue(String *path) { - String response; - int code = 200; - uint16_t tmp = 0; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint16_t ct = 0; - bool resp = false; - - uint8_t device = DecodeLightId(atoi(path->c_str())); - uint8_t index = device-devices_present-1; - - if (WebServer->args()) { - response = "["; - - StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); - if (hue_json.containsKey("on")) { - - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "on"); - - bool on = hue_json["on"]; - switch(on) - { - case false : glob_script_mem.fvars[hue_script[index].index[0]-1]=0; - response.replace("{re", "false"); - break; - case true : glob_script_mem.fvars[hue_script[index].index[0]-1]=1; - response.replace("{re", "true"); - break; - } - glob_script_mem.type[hue_script[index].vindex[0]].bits.changed=1; - resp = true; - } - if (hue_json.containsKey("bri")) { - tmp = hue_json["bri"]; - bri=tmp; - if (254 <= bri) { bri = 255; } - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "bri"); - response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[1]-1]=bri; - glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1; - resp = true; - } - if (hue_json.containsKey("xy")) { - float x, y; - x = hue_json["xy"][0]; - y = hue_json["xy"][1]; - const String &x_str = hue_json["xy"][0]; - const String &y_str = hue_json["xy"][1]; - uint8_t rr,gg,bb; - LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); - LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "xy"); - response.replace("{re", "[" + x_str + "," + y_str + "]"); - glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; - glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; - glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; - glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; - resp = true; - } - - if (hue_json.containsKey("hue")) { - tmp = hue_json["hue"]; - - - hue=tmp; - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "hue"); - response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; - glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; - resp = true; - } - if (hue_json.containsKey("sat")) { - tmp = hue_json["sat"]; - sat=tmp; - if (254 <= sat) { sat = 255; } - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "sat"); - response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; - glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; - resp = true; - } - if (hue_json.containsKey("ct")) { - ct = hue_json["ct"]; - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "ct"); - response.replace("{re", String(ct)); - glob_script_mem.fvars[hue_script[index].index[4]-1]=ct; - glob_script_mem.type[hue_script[index].vindex[4]].bits.changed=1; - resp = true; - } - response += "]"; - - } else { - response = FPSTR(sHUE_ERROR_JSON); - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); - WSSend(code, CT_JSON, response); - if (resp) { - Run_Scripter(">E",2,0); - } -} -#endif - - -#ifdef USE_SCRIPT_SUB_COMMAND -bool Script_SubCmd(void) { - if (!bitRead(Settings.rule_enabled, 0)) return false; - - if (tasm_cmd_activ) return false; - - char command[CMDSZ]; - strlcpy(command,XdrvMailbox.topic,CMDSZ); - uint32_t pl=XdrvMailbox.payload; - char pld[64]; - strlcpy(pld,XdrvMailbox.data,sizeof(pld)); - - char cmdbuff[128]; - char *cp=cmdbuff; - *cp++='#'; - strcpy(cp,XdrvMailbox.topic); - uint8_t tlen=strlen(XdrvMailbox.topic); - cp+=tlen; - if (XdrvMailbox.index > 0) { - *cp++=XdrvMailbox.index|0x30; - tlen++; - } - if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) { - *cp++='('; - strncpy(cp,XdrvMailbox.data,XdrvMailbox.data_len); - cp+=XdrvMailbox.data_len; - *cp++=')'; - *cp=0; - } - - uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); - - if (res) return false; - else { - if (pl>=0) { - Response_P(S_JSON_COMMAND_NVALUE, command, pl); - } else { - Response_P(S_JSON_COMMAND_SVALUE, command, pld); - } - } - return true; -} -#endif - -void execute_script(char *script) { - char *svd_sp=glob_script_mem.scriptptr; - strcat(script,"\n#"); - glob_script_mem.scriptptr=script; - Run_Scripter(">",1,0); - glob_script_mem.scriptptr=svd_sp; -} -#define D_CMND_SCRIPT "Script" -#define D_CMND_SUBSCRIBE "Subscribe" -#define D_CMND_UNSUBSCRIBE "Unsubscribe" - -enum ScriptCommands { CMND_SCRIPT,CMND_SUBSCRIBE, CMND_UNSUBSCRIBE }; -const char kScriptCommands[] PROGMEM = D_CMND_SCRIPT "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE; - -bool ScriptCommand(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t index = XdrvMailbox.index; - - if (tasm_cmd_activ) return false; - - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); - if (-1 == command_code) { - serviced = false; - } - else if ((CMND_SCRIPT == command_code) && (index > 0)) { - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); - break; -#ifdef xSCRIPT_STRIP_COMMENTS - case 2: - bitWrite(Settings.rule_enabled, 1,0); - break; - case 3: - bitWrite(Settings.rule_enabled, 1,1); - break; -#endif - } - } else { - if ('>' == XdrvMailbox.data[0]) { - - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),command,XdrvMailbox.data); - if (bitRead(Settings.rule_enabled, 0)) { - for (uint8_t count=0; count> 1; -} - -void dateTime(uint16_t* date, uint16_t* time) { - - *date = xFAT_DATE(RtcTime.year,RtcTime.month, RtcTime.day_of_month); - - *time = xFAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second); -} - -#endif - - - -#ifdef SUPPORT_MQTT_EVENT -# 4199 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" -bool ScriptMqttData(void) -{ - bool serviced = false; - - toLog(XdrvMailbox.data); - if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { - return false; - } - String sTopic = XdrvMailbox.topic; - String sData = XdrvMailbox.data; - - MQTT_Subscription event_item; - - for (uint32_t index = 0; index < subscriptions.size(); index++) { - event_item = subscriptions.get(index); - - - if (sTopic.startsWith(event_item.Topic)) { - - serviced = true; - String value; - String lkey; - if (event_item.Key.length() == 0) { - value = sData; - } else { - StaticJsonBuffer<400> jsonBuf; - JsonObject& jsonData = jsonBuf.parseObject(sData); - String key1 = event_item.Key; - String key2; - if (!jsonData.success()) break; - int dot; - if ((dot = key1.indexOf('.')) > 0) { - key2 = key1.substring(dot+1); - key1 = key1.substring(0, dot); - lkey=key2; - if (!jsonData[key1][key2].success()) break; - value = (const char *)jsonData[key1][key2]; - } else { - if (!jsonData[key1].success()) break; - value = (const char *)jsonData[key1]; - lkey=key1; - } - } - value.trim(); - char sbuffer[128]; - - if (!strncmp(lkey.c_str(),"Epoch",5)) { - uint32_t ep=atoi(value.c_str())-(uint32_t)EPOCH_OFFSET; - snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(),ep); - } else { - snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); - } - - execute_script(sbuffer); - } - } - return serviced; -} -# 4274 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" -String ScriptSubscribe(const char *data, int data_len) -{ - MQTT_Subscription subscription_item; - String events; - if (data_len > 0) { - char parameters[data_len+1]; - memcpy(parameters, data, data_len); - parameters[data_len] = '\0'; - String event_name, topic, key; - - char * pos = strtok(parameters, ","); - if (pos) { - event_name = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - topic = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - key = Trim(pos); - } - } - } - - - if (event_name.length() > 0 && topic.length() > 0) { - - for (uint32_t index=0; index < subscriptions.size(); index++) { - if (subscriptions.get(index).Event.equals(event_name)) { - - String stopic = subscriptions.get(index).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(index); - break; - } - } - - if (!topic.endsWith("#")) { - if (topic.endsWith("/")) { - topic.concat("#"); - } else { - topic.concat("/#"); - } - } - - - subscription_item.Event = event_name; - subscription_item.Topic = topic.substring(0, topic.length() - 2); - subscription_item.Key = key; - subscriptions.add(subscription_item); - - MqttSubscribe(topic.c_str()); - events.concat(event_name + "," + topic - + (key.length()>0 ? "," : "") - + key); - } else { - events = D_JSON_WRONG_PARAMETERS; - } - } else { - - for (uint32_t index=0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - events.concat(subscription_item.Event + "," + subscription_item.Topic - + (subscription_item.Key.length()>0 ? "," : "") - + subscription_item.Key + "; "); - } - } - return events; -} -# 4354 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_10_scripter.ino" -String ScriptUnsubscribe(const char * data, int data_len) -{ - MQTT_Subscription subscription_item; - String events; - if (data_len > 0) { - for (uint32_t index = 0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - if (subscription_item.Event.equalsIgnoreCase(data)) { - String stopic = subscription_item.Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - events = subscription_item.Event; - subscriptions.remove(index); - break; - } - } - } else { - - String stopic; - while (subscriptions.size() > 0) { - events.concat(subscriptions.get(0).Event + "; "); - stopic = subscriptions.get(0).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(0); - } - } - return events; -} -#endif - - - -#ifdef USE_SCRIPT_WEB_DISPLAY - -void Script_Check_HTML_Setvars(void) { - - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("sv")) { - String stmp = WebServer->arg("sv"); - char cmdbuf[64]; - memset(cmdbuf,0,sizeof(cmdbuf)); - char *cp=cmdbuf; - *cp++='>'; - strncpy(cp,stmp.c_str(),sizeof(cmdbuf)-1); - char *cp1=strchr(cp,'_'); - if (!cp1) return; - *cp1=0; - char vname[32]; - strncpy(vname,cp,sizeof(vname)); - *cp1='='; - cp1++; - - struct T_INDEX ind; - uint8_t vtype; - isvar(vname,&vtype,&ind,0,0,0); - if (vtype!=NUM_RES && vtype&STYPE) { - - uint8_t tlen=strlen(cp1); - memmove(cp1+1,cp1,tlen); - *cp1='\"'; - *(cp1+tlen+1)='\"'; - } - - - execute_script(cmdbuf); - Run_Scripter(">E",2,0); - } -} - - -const char SCRIPT_MSG_BUTTONa[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUTTONb[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUT_START[] PROGMEM = - "
"; -const char SCRIPT_MSG_BUT_START_TBL[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUT_STOP[] PROGMEM = - ""; -const char SCRIPT_MSG_BUT_STOP_TBL[] PROGMEM = - "
"; - -const char SCRIPT_MSG_SLIDER[] PROGMEM = - "
%s
%s%s
" - "
"; - -const char SCRIPT_MSG_CHKBOX[] PROGMEM = - "
"; - -const char SCRIPT_MSG_TEXTINP[] PROGMEM = - "
"; - -const char SCRIPT_MSG_NUMINP[] PROGMEM = - "
"; - - -void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { -uint32_t cnt; - for (cnt=0;cntW",-2,0); - if (web_script==99) { - char line[128]; - char tmp[128]; - uint8_t optflg=0; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; i0) { - cp="checked='checked'"; - uval=0; - } else { - cp=""; - uval=1; - } - WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); - - } else if (!strncmp(lin,"bu(",3)) { - char *lp=lin+3; - uint8_t bcnt=0; - char *found=lin; - while (bcnt<4) { - found=strstr(found,"bu("); - if (!found) break; - found+=3; - bcnt++; - } - uint8_t proz=100/bcnt; - if (!optflg && bcnt>1) proz-=2; - if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); - else WSContentSend_PD(SCRIPT_MSG_BUT_START); - for (uint32_t cnt=0;cnt0) { - cp=ontxt; - uval=0; - } else { - cp=offtxt; - uval=1; - } - if (bcnt>1 && cnt==bcnt-1) { - if (!optflg) proz+=2; - } - if (!optflg) { - WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); - } else { - WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); - } - if (bcnt>1 && cnt%s
"),tmp); - } else { - WSContentSend_PD(PSTR("{s}%s{e}"),tmp); - } - } - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - } -} -#endif - - -#ifdef USE_SENDMAIL -void script_send_email_body(BearSSL::WiFiClientSecure_light *client) { -uint8_t msect=Run_Scripter(">m",-2,0); - if (msect==99) { - char line[128]; - char tmp[128]; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; iprintln(tmp); - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - } else { - client->println("*"); - } -} -#endif - -#ifdef USE_SCRIPT_JSON_EXPORT -void ScriptJsonAppend(void) { - uint8_t web_script=Run_Scripter(">J",-2,0); - if (web_script==99) { - char line[128]; - char tmp[128]; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; iB",2,0); - fast_script=Run_Scripter(">F",-2,0); -#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) - Script_Check_Hue(0); -#endif - } - break; - case FUNC_EVERY_100_MSECOND: - ScripterEvery100ms(); - break; - case FUNC_EVERY_SECOND: - ScriptEverySecond(); - break; - case FUNC_COMMAND: - result = ScriptCommand(); - break; - case FUNC_SET_POWER: -#ifdef SCRIPT_POWER_SECTION - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P",2,0); -#else - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,0); -#endif - break; - case FUNC_RULES_PROCESS: - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_RULES); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); - WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); - -#ifdef USE_SCRIPT_FATFS - WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload); - WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess); - WebServer->on("/upl", HTTP_GET,Script_FileUploadConfiguration); -#endif - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">R",2,0); - Scripter_save_pvars(); - } - break; -#ifdef SUPPORT_MQTT_EVENT - case FUNC_MQTT_DATA: - if (bitRead(Settings.rule_enabled, 0)) { - result = ScriptMqttData(); - } - break; -#endif -#ifdef USE_SCRIPT_WEB_DISPLAY - case FUNC_WEB_SENSOR: - if (bitRead(Settings.rule_enabled, 0)) { - ScriptWebShow(); - } - break; -#endif - -#ifdef USE_SCRIPT_JSON_EXPORT - case FUNC_JSON_APPEND: - if (bitRead(Settings.rule_enabled, 0)) { - ScriptJsonAppend(); - } - break; -#endif - -#ifdef USE_BUTTON_EVENT - case FUNC_BUTTON_PRESSED: - if (bitRead(Settings.rule_enabled, 0)) { - if ((script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) { - script_button[XdrvMailbox.index]=XdrvMailbox.payload; - Run_Scripter(">b",2,0); - } - } - break; -#endif - - } - return result; -} - - - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" -#ifdef USE_KNX -# 51 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" -#define XDRV_11 11 - -#include - -address_t KNX_physs_addr; -address_t KNX_addr; - -#define KNX_Empty 255 - -#define TOGGLE_INHIBIT_TIME 15 - -float last_temp; -float last_hum; -uint8_t toggle_inhibit; - -typedef struct __device_parameters -{ - uint8_t type; - - - - - bool show; - - bool last_state; - - callback_id_t CB_id; - - - - - -} device_parameters_t; - - -device_parameters_t device_param[] = { - { 1, false, false, KNX_Empty }, - { 2, false, false, KNX_Empty }, - { 3, false, false, KNX_Empty }, - { 4, false, false, KNX_Empty }, - { 5, false, false, KNX_Empty }, - { 6, false, false, KNX_Empty }, - { 7, false, false, KNX_Empty }, - { 8, false, false, KNX_Empty }, - { 9, false, false, KNX_Empty }, - { 10, false, false, KNX_Empty }, - { 11, false, false, KNX_Empty }, - { 12, false, false, KNX_Empty }, - { 13, false, false, KNX_Empty }, - { 14, false, false, KNX_Empty }, - { 15, false, false, KNX_Empty }, - { 16, false, false, KNX_Empty }, - { KNX_TEMPERATURE, false, false, KNX_Empty }, - { KNX_HUMIDITY , false, false, KNX_Empty }, - { KNX_ENERGY_VOLTAGE , false, false, KNX_Empty }, - { KNX_ENERGY_CURRENT , false, false, KNX_Empty }, - { KNX_ENERGY_POWER , false, false, KNX_Empty }, - { KNX_ENERGY_POWERFACTOR , false, false, KNX_Empty }, - { KNX_ENERGY_DAILY , false, false, KNX_Empty }, - { KNX_ENERGY_START , false, false, KNX_Empty }, - { KNX_ENERGY_TOTAL , false, false, KNX_Empty }, - { KNX_SLOT1 , false, false, KNX_Empty }, - { KNX_SLOT2 , false, false, KNX_Empty }, - { KNX_SLOT3 , false, false, KNX_Empty }, - { KNX_SLOT4 , false, false, KNX_Empty }, - { KNX_SLOT5 , false, false, KNX_Empty }, - { KNX_Empty, false, false, KNX_Empty} -}; - - -const char * device_param_ga[] = { - D_TIMER_OUTPUT " 1", - D_TIMER_OUTPUT " 2", - D_TIMER_OUTPUT " 3", - D_TIMER_OUTPUT " 4", - D_TIMER_OUTPUT " 5", - D_TIMER_OUTPUT " 6", - D_TIMER_OUTPUT " 7", - D_TIMER_OUTPUT " 8", - D_SENSOR_BUTTON " 1", - D_SENSOR_BUTTON " 2", - D_SENSOR_BUTTON " 3", - D_SENSOR_BUTTON " 4", - D_SENSOR_BUTTON " 5", - D_SENSOR_BUTTON " 6", - D_SENSOR_BUTTON " 7", - D_SENSOR_BUTTON " 8", - D_TEMPERATURE , - D_HUMIDITY , - D_VOLTAGE , - D_CURRENT , - D_POWERUSAGE , - D_POWER_FACTOR , - D_ENERGY_TODAY , - D_ENERGY_YESTERDAY , - D_ENERGY_TOTAL , - D_KNX_TX_SLOT " 1", - D_KNX_TX_SLOT " 2", - D_KNX_TX_SLOT " 3", - D_KNX_TX_SLOT " 4", - D_KNX_TX_SLOT " 5", - nullptr -}; - - -const char *device_param_cb[] = { - D_TIMER_OUTPUT " 1", - D_TIMER_OUTPUT " 2", - D_TIMER_OUTPUT " 3", - D_TIMER_OUTPUT " 4", - D_TIMER_OUTPUT " 5", - D_TIMER_OUTPUT " 6", - D_TIMER_OUTPUT " 7", - D_TIMER_OUTPUT " 8", - D_TIMER_OUTPUT " 1 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 2 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 3 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 4 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 5 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 6 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 7 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 8 " D_BUTTON_TOGGLE, - D_REPLY " " D_TEMPERATURE, - D_REPLY " " D_HUMIDITY, - D_REPLY " " D_VOLTAGE , - D_REPLY " " D_CURRENT , - D_REPLY " " D_POWERUSAGE , - D_REPLY " " D_POWER_FACTOR , - D_REPLY " " D_ENERGY_TODAY , - D_REPLY " " D_ENERGY_YESTERDAY , - D_REPLY " " D_ENERGY_TOTAL , - D_KNX_RX_SLOT " 1", - D_KNX_RX_SLOT " 2", - D_KNX_RX_SLOT " 3", - D_KNX_RX_SLOT " 4", - D_KNX_RX_SLOT " 5", - nullptr -}; - - -#define D_PRFX_KNX "Knx" -#define D_CMND_KNXTXCMND "Tx_Cmnd" -#define D_CMND_KNXTXVAL "Tx_Val" -#define D_CMND_KNX_ENABLED "_Enabled" -#define D_CMND_KNX_ENHANCED "_Enhanced" -#define D_CMND_KNX_PA "_PA" -#define D_CMND_KNX_GA "_GA" -#define D_CMND_KNX_CB "_CB" - -const char kKnxCommands[] PROGMEM = D_PRFX_KNX "|" - D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ; - -void (* const KnxCommand[])(void) PROGMEM = { - &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb }; - -uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 ) -{ - for (uint32_t i = start; i < Settings.knx_GA_registered; ++i) - { - if ( Settings.knx_GA_param[i] == param ) - { - if ( Settings.knx_GA_addr[i] != 0 ) - { - if ( i >= start ) { return i; } - } - } - } - return KNX_Empty; -} - - -uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 ) -{ - for (uint32_t i = start; i < Settings.knx_CB_registered; ++i) - { - if ( Settings.knx_CB_param[i] == param ) - { - if ( Settings.knx_CB_addr[i] != 0 ) - { - if ( i >= start ) { return i; } - } - } - } - return KNX_Empty; -} - - -void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ) -{ - - if ( Settings.knx_GA_registered >= MAX_KNX_GA ) { return; } - if ( GA_FNUM == 0 && GA_AREA == 0 && GA_FDEF == 0 ) { return; } - - - Settings.knx_GA_param[Settings.knx_GA_registered] = GAop; - KNX_addr.ga.area = GA_FNUM; - KNX_addr.ga.line = GA_AREA; - KNX_addr.ga.member = GA_FDEF; - Settings.knx_GA_addr[Settings.knx_GA_registered] = KNX_addr.value; - - Settings.knx_GA_registered++; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), - Settings.knx_GA_registered, - device_param_ga[GAop-1], - GA_FNUM, GA_AREA, GA_FDEF ); -} - - -void KNX_DEL_GA( uint8_t GAnum ) -{ - - uint8_t dest_offset = 0; - uint8_t src_offset = 0; - uint8_t len = 0; - - - Settings.knx_GA_param[GAnum-1] = 0; - - if (GAnum == 1) - { - - src_offset = 1; - - - - len = (Settings.knx_GA_registered - 1); - } - else if (GAnum == Settings.knx_GA_registered) - { - - } - else - { - - - - - dest_offset = GAnum -1 ; - src_offset = dest_offset + 1; - len = (Settings.knx_GA_registered - GAnum); - } - - if (len > 0) - { - memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(uint8_t)); - memmove(Settings.knx_GA_addr + dest_offset, Settings.knx_GA_addr + src_offset, len * sizeof(uint16_t)); - } - - Settings.knx_GA_registered--; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " GA #%d"), - GAnum ); -} - - -void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ) -{ - - if ( Settings.knx_CB_registered >= MAX_KNX_CB ) { return; } - if ( CB_FNUM == 0 && CB_AREA == 0 && CB_FDEF == 0 ) { return; } - - - if ( device_param[CBop-1].CB_id == KNX_Empty ) - { - - device_param[CBop-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[CBop-1]); - - - - - } - - Settings.knx_CB_param[Settings.knx_CB_registered] = CBop; - KNX_addr.ga.area = CB_FNUM; - KNX_addr.ga.line = CB_AREA; - KNX_addr.ga.member = CB_FDEF; - Settings.knx_CB_addr[Settings.knx_CB_registered] = KNX_addr.value; - - knx.callback_assign( device_param[CBop-1].CB_id, KNX_addr ); - - Settings.knx_CB_registered++; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"), - Settings.knx_CB_registered, - CB_FNUM, CB_AREA, CB_FDEF, - device_param_cb[CBop-1] ); -} - - -void KNX_DEL_CB( uint8_t CBnum ) -{ - uint8_t oldparam = Settings.knx_CB_param[CBnum-1]; - uint8_t dest_offset = 0; - uint8_t src_offset = 0; - uint8_t len = 0; - - - knx.callback_unassign(CBnum-1); - Settings.knx_CB_param[CBnum-1] = 0; - - if (CBnum == 1) - { - - src_offset = 1; - - - - len = (Settings.knx_CB_registered - 1); - } - else if (CBnum == Settings.knx_CB_registered) - { - - } - else - { - - - - - dest_offset = CBnum -1 ; - src_offset = dest_offset + 1; - len = (Settings.knx_CB_registered - CBnum); - } - - if (len > 0) - { - memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(uint8_t)); - memmove(Settings.knx_CB_addr + dest_offset, Settings.knx_CB_addr + src_offset, len * sizeof(uint16_t)); - } - - Settings.knx_CB_registered--; - - - if ( KNX_CB_Search( oldparam ) == KNX_Empty ) { - knx.callback_deregister( device_param[oldparam-1].CB_id ); - device_param[oldparam-1].CB_id = KNX_Empty; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " CB #%d"), CBnum ); -} - - -bool KNX_CONFIG_NOT_MATCH(void) -{ - - for (uint32_t i = 0; i < KNX_MAX_device_param; ++i) - { - if ( !device_param[i].show ) { - - - - if ( KNX_GA_Search(i+1) != KNX_Empty ) { return true; } - - if ( i < 8 ) - { - if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } - if ( KNX_CB_Search(i+9) != KNX_Empty ) { return true; } - } - - if ( i > 15 ) - { - if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } - } - } - } - - - for (uint32_t i = 0; i < Settings.knx_GA_registered; ++i) - { - if ( Settings.knx_GA_param[i] != 0 ) - { - if ( Settings.knx_GA_addr[i] == 0 ) - { - return true; - } - } - } - for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) - { - if ( Settings.knx_CB_param[i] != 0 ) - { - if ( Settings.knx_CB_addr[i] == 0 ) - { - return true; - } - } - } - - return false; -} - - -void KNXStart(void) -{ - knx.start(nullptr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_START)); -} - - -void KNX_INIT(void) -{ - - if (Settings.knx_GA_registered > MAX_KNX_GA) { Settings.knx_GA_registered = MAX_KNX_GA; } - if (Settings.knx_CB_registered > MAX_KNX_CB) { Settings.knx_CB_registered = MAX_KNX_CB; } - - - KNX_physs_addr.value = Settings.knx_physsical_addr; - knx.physical_address_set( KNX_physs_addr ); -# 472 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" - for (uint32_t i = 0; i < devices_present; ++i) - { - device_param[i].show = true; - } - for (uint32_t i = GPIO_SWT1; i < GPIO_SWT4 + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } - } - for (uint32_t i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } - } - for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } - } - for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } - } - if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } -#ifdef USE_DS18x20 - if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } -#endif - if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - -#if defined(USE_ENERGY_SENSOR) - - if ( energy_flg != ENERGY_NONE ) { - device_param[KNX_ENERGY_POWER-1].show = true; - device_param[KNX_ENERGY_DAILY-1].show = true; - device_param[KNX_ENERGY_START-1].show = true; - device_param[KNX_ENERGY_TOTAL-1].show = true; - device_param[KNX_ENERGY_VOLTAGE-1].show = true; - device_param[KNX_ENERGY_CURRENT-1].show = true; - device_param[KNX_ENERGY_POWERFACTOR-1].show = true; - } -#endif - -#ifdef USE_RULES - device_param[KNX_SLOT1-1].show = true; - device_param[KNX_SLOT2-1].show = true; - device_param[KNX_SLOT3-1].show = true; - device_param[KNX_SLOT4-1].show = true; - device_param[KNX_SLOT5-1].show = true; -#endif - - - if (KNX_CONFIG_NOT_MATCH()) { - Settings.knx_GA_registered = 0; - Settings.knx_CB_registered = 0; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS)); - } - - - - - uint8_t j; - for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) - { - j = Settings.knx_CB_param[i]; - if ( j > 0 ) - { - device_param[j-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[j-1]); - - - - KNX_addr.value = Settings.knx_CB_addr[i]; - knx.callback_assign( device_param[j-1].CB_id, KNX_addr ); - } - } -} - - -void KNX_CB_Action(message_t const &msg, void *arg) -{ - device_parameters_t *chan = (device_parameters_t *)arg; - if (!(Settings.flag.knx_enabled)) { return; } - - char tempchar[33]; - - if (msg.data_len == 1) { - - tempchar[0] = msg.data[0]; - tempchar[1] = '\0'; - } else { - - float tempvar = knx.data_to_2byte_float(msg.data); - dtostrfd(tempvar,2,tempchar); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"), - msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, - (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, - tempchar, - device_param_cb[(chan->type)-1]); - - switch (msg.ct) - { - case KNX_CT_WRITE: - if (chan->type < 9) - { - ExecuteCommandPower(chan->type, msg.data[0], SRC_KNX); - } - else if (chan->type < 17) - { - if (!toggle_inhibit) { - ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#ifdef USE_RULES - else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) - { - if (!toggle_inhibit) { - char command[25]; - if (msg.data_len == 1) { - - snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]); - } else { - - snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar); - } - ExecuteCommand(command, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#endif - break; - - case KNX_CT_READ: - if (chan->type < 9) - { - knx.answer_1bit(msg.received_on, chan->last_state); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_1bit(msg.received_on, chan->last_state); - knx.answer_1bit(msg.received_on, chan->last_state); - } - } - else if (chan->type == KNX_TEMPERATURE) - { - knx.answer_2byte_float(msg.received_on, last_temp); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_2byte_float(msg.received_on, last_temp); - knx.answer_2byte_float(msg.received_on, last_temp); - } - } - else if (chan->type == KNX_HUMIDITY) - { - knx.answer_2byte_float(msg.received_on, last_hum); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_2byte_float(msg.received_on, last_hum); - knx.answer_2byte_float(msg.received_on, last_hum); - } - } -#ifdef USE_RULES - else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) - { - if (!toggle_inhibit) { - char command[25]; - snprintf_P(command, sizeof(command), PSTR("event KNXRX_REQ%d"), ((chan->type) - KNX_SLOT1 + 1 ) ); - ExecuteCommand(command, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#endif - break; - } -} - - -void KnxUpdatePowerState(uint8_t device, power_t state) -{ - if (!(Settings.flag.knx_enabled)) { return; } - - device_param[device -1].last_state = bitRead(state, device -1); - - - uint8_t i = KNX_GA_Search(device); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[device -1], device_param[device -1].last_state, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(device, i + 1); - } -} - - -void KnxSendButtonPower(void) -{ - if (!(Settings.flag.knx_enabled)) { return; } - - uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; - uint32_t device = XdrvMailbox.payload & 0xFF; - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; -# 693 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_11_knx.ino" - uint8_t i = KNX_GA_Search(device + 8); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, !(state == 0)); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, !(state == 0)); - knx.write_1bit(KNX_addr, !(state == 0)); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[device + 7], !(state == 0), - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(device + 8, i + 1); - } - -} - - -void KnxSensor(uint8_t sensor_type, float value) -{ - if (sensor_type == KNX_TEMPERATURE) - { - last_temp = value; - } else if (sensor_type == KNX_HUMIDITY) - { - last_hum = value; - } - - if (!(Settings.flag.knx_enabled)) { return; } - - uint8_t i = KNX_GA_Search(sensor_type); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_2byte_float(KNX_addr, value); - if (Settings.flag.knx_enable_enhancement) { - knx.write_2byte_float(KNX_addr, value); - knx.write_2byte_float(KNX_addr, value); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "), - device_param_ga[sensor_type -1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(sensor_type, i+1); - } -} - - - - - - -#ifdef USE_WEBSERVER -#ifdef USE_KNX_WEB_MENU -const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; - -const char HTTP_BTN_MENU_KNX[] PROGMEM = - "

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

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" - "" D_KNX_ENABLE "" D_KNX_ENHANCEMENT "

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

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

" - "
" - "" D_KNX_GROUP_ADDRESS_TO_READ "
"; - -const char HTTP_FORM_KNX4[] PROGMEM = - "-> -> ")); - WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_AREA", "GA_FDEF"); - WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); - for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) - { - if ( Settings.knx_GA_param[i] ) - { - KNX_addr.value = Settings.knx_GA_addr[i]; - WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1); - } - } - - WSContentSend_P(HTTP_FORM_KNX3); - WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_AREA", "CB_FDEF"); - WSContentSend_P(HTTP_FORM_KNX4); - - uint8_t j; - for (uint32_t i = 0; i < KNX_MAX_device_param ; i++) - { - - if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } - if ( i == 8 ) { j = 0; } - if ( device_param[j].show ) - { - WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); - } - } - WSContentSend_P(PSTR(" ")); - WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); - - for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) - { - if ( Settings.knx_CB_param[i] ) - { - KNX_addr.value = Settings.knx_CB_addr[i]; - WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); - } - } - WSContentSend_P(PSTR("
")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); - } - -} - - -void KNX_Save_Settings(void) -{ - String stmp; - address_t KNX_addr; - - Settings.flag.knx_enabled = WebServer->hasArg("b1"); - Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2"); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), - Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement ); - - stmp = WebServer->arg("area"); - KNX_addr.pa.area = stmp.toInt(); - stmp = WebServer->arg("line"); - KNX_addr.pa.line = stmp.toInt(); - stmp = WebServer->arg("member"); - KNX_addr.pa.member = stmp.toInt(); - Settings.knx_physsical_addr = KNX_addr.value; - knx.physical_address_set( KNX_addr ); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "), - KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA: %d"), - Settings.knx_GA_registered ); - for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) - { - KNX_addr.value = Settings.knx_GA_addr[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), - i+1, device_param_ga[Settings.knx_GA_param[i]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB: %d"), - Settings.knx_CB_registered ); - for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) - { - KNX_addr.value = Settings.knx_CB_addr[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), - i+1, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, - device_param_cb[Settings.knx_CB_param[i]-1] ); - } -} - -#endif -#endif - - - - - -void CmndKnxTxCmnd(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { - - - - uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], !(XdrvMailbox.payload == 0), - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); - } - ResponseCmndIdxChar (XdrvMailbox.data ); - } -} - -void CmndKnxTxVal(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { - - - - uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - - float tempvar = CharToFloat(XdrvMailbox.data); - dtostrfd(tempvar,2,XdrvMailbox.data); - - knx.write_2byte_float(KNX_addr, tempvar); - if (Settings.flag.knx_enable_enhancement) { - knx.write_2byte_float(KNX_addr, tempvar); - knx.write_2byte_float(KNX_addr, tempvar); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), - device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], XdrvMailbox.data, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); - } - ResponseCmndIdxChar (XdrvMailbox.data ); - } -} - -void CmndKnxEnabled(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag.knx_enabled = XdrvMailbox.payload; - } - ResponseCmndChar (GetStateText(Settings.flag.knx_enabled) ); -} - -void CmndKnxEnhanced(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag.knx_enable_enhancement = XdrvMailbox.payload; - } - ResponseCmndChar (GetStateText(Settings.flag.knx_enable_enhancement) ); -} - -void CmndKnxPa(void) -{ - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ".") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); - int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2)); - int pa_member = atoi(subStr(sub_string, XdrvMailbox.data, ".", 3)); - - if ( ((pa_area == 0) && (pa_line == 0) && (pa_member == 0)) - || (pa_area > 15) || (pa_line > 15) || (pa_member > 255) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.pa.area = pa_area; - KNX_addr.pa.line = pa_line; - KNX_addr.pa.member = pa_member; - Settings.knx_physsical_addr = KNX_addr.value; - } - } - KNX_addr.value = Settings.knx_physsical_addr; - Response_P (PSTR("{\"%s\":\"%d.%d.%d\"}"), - XdrvMailbox.command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); -} - -void CmndKnxGa(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_GA)) { - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - int ga_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - int ga_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - - if ( ((ga_area == 0) && (ga_line == 0) && (ga_member == 0)) - || (ga_area > 31) || (ga_line > 7) || (ga_member > 255) - || (ga_option < 0) || ((ga_option > KNX_MAX_device_param ) && (ga_option != KNX_Empty)) - || (!device_param[ga_option-1].show) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.ga.area = ga_area; - KNX_addr.ga.line = ga_line; - KNX_addr.ga.member = ga_member; - - if ( XdrvMailbox.index > Settings.knx_GA_registered ) { - Settings.knx_GA_registered ++; - XdrvMailbox.index = Settings.knx_GA_registered; - } - - Settings.knx_GA_addr[XdrvMailbox.index -1] = KNX_addr.value; - Settings.knx_GA_param[XdrvMailbox.index -1] = ga_option; - } else { - if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) { - XdrvMailbox.index = XdrvMailbox.payload; - } else { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - } - if ( XdrvMailbox.index <= Settings.knx_GA_registered ) { - KNX_addr.value = Settings.knx_GA_addr[XdrvMailbox.index -1]; - Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), - XdrvMailbox.command, XdrvMailbox.index, device_param_ga[Settings.knx_GA_param[XdrvMailbox.index-1]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - } - } else { - ResponseCmndNumber (Settings.knx_GA_registered ); - } - } -} - -void CmndKnxCb(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_CB)) { - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - int cb_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - int cb_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - - if ( ((cb_area == 0) && (cb_line == 0) && (cb_member == 0)) - || (cb_area > 31) || (cb_line > 7) || (cb_member > 255) - || (cb_option < 0) || ((cb_option > KNX_MAX_device_param ) && (cb_option != KNX_Empty)) - || (!device_param[cb_option-1].show) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.ga.area = cb_area; - KNX_addr.ga.line = cb_line; - KNX_addr.ga.member = cb_member; - - if ( XdrvMailbox.index > Settings.knx_CB_registered ) { - Settings.knx_CB_registered ++; - XdrvMailbox.index = Settings.knx_CB_registered; - } - - Settings.knx_CB_addr[XdrvMailbox.index -1] = KNX_addr.value; - Settings.knx_CB_param[XdrvMailbox.index -1] = cb_option; - } else { - if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) { - XdrvMailbox.index = XdrvMailbox.payload; - } else { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - } - if ( XdrvMailbox.index <= Settings.knx_CB_registered ) { - KNX_addr.value = Settings.knx_CB_addr[XdrvMailbox.index -1]; - Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), - XdrvMailbox.command, XdrvMailbox.index, device_param_cb[Settings.knx_CB_param[XdrvMailbox.index-1]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - } - } else { - ResponseCmndNumber (Settings.knx_CB_registered ); - } - } -} - - - - - -bool Xdrv11(uint8_t function) -{ - bool result = false; - switch (function) { - case FUNC_LOOP: - if (!global_state.wifi_down) { knx.loop(); } - break; - case FUNC_EVERY_50_MSECOND: - if (toggle_inhibit) { - toggle_inhibit--; - } - break; - case FUNC_ANY_KEY: - KnxSendButtonPower(); - break; -#ifdef USE_WEBSERVER -#ifdef USE_KNX_WEB_MENU - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_KNX); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/kn", HandleKNXConfiguration); - break; -#endif -#endif - case FUNC_COMMAND: - result = DecodeCommand(kKnxCommands, KnxCommand); - break; - case FUNC_PRE_INIT: - KNX_INIT(); - break; - - - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_12_home_assistant.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_12_home_assistant.ino" -#ifdef USE_HOME_ASSISTANT - -#define XDRV_12 12 - - -const char kHAssJsonSensorTypes[] PROGMEM = - D_JSON_TEMPERATURE "|" D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" - D_JSON_APPARENT_POWERUSAGE "|Battery|" D_JSON_CURRENT "|" D_JSON_DISTANCE "|" D_JSON_FREQUENCY "|" D_JSON_HUMIDITY "|" D_JSON_ILLUMINANCE "|" - D_JSON_MOISTURE "|PB0.3|PB0.5|PB1|PB2.5|PB5|PB10|PM1|PM2.5|PM10|" D_JSON_POWERFACTOR "|" D_JSON_POWERUSAGE "|" - D_JSON_REACTIVE_POWERUSAGE "|" D_JSON_TODAY "|" D_JSON_TOTAL "|" D_JSON_VOLTAGE "|" D_JSON_WEIGHT "|" D_JSON_YESTERDAY; -const char kHAssJsonSensorUnits[] PROGMEM = - "|||" - "W|%|A|Cm|Hz|%|LX|" - "%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³||W|" - "W|KWh|KWh|V|Kg|KWh"; -const char kHAssJsonSensorDevCla[] PROGMEM = - "dev_cla\":\"temperature|dev_cla\":\"pressure|dev_cla\":\"pressure|" - "dev_cla\":\"power|dev_cla\":\"battery|ic\":\"mdi:alpha-a-circle-outline|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" - "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" - "ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|" - "dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power"; - - -const char HASS_DISCOVER_SENSOR[] PROGMEM = - ",\"unit_of_meas\":\"%s\",\"%s\"," - "\"frc_upd\":true," - "\"val_tpl\":\"{{value_json['%s']['%s']"; - -const char HASS_DISCOVER_BASE[] PROGMEM = - "{\"name\":\"%s\"," - "\"stat_t\":\"%s\"," - "\"avty_t\":\"%s\"," - "\"pl_avail\":\"" D_ONLINE "\"," - "\"pl_not_avail\":\"" D_OFFLINE "\""; - -const char HASS_DISCOVER_RELAY[] PROGMEM = - ",\"cmd_t\":\"%s\"," - "\"val_tpl\":\"{{value_json.%s}}\"," - "\"pl_off\":\"%s\"," - "\"pl_on\":\"%s\""; - -const char HASS_DISCOVER_BUTTON_TOGGLE[] PROGMEM = - ",\"value_template\":\"{%%if is_state(entity_id,\\\"off\\\")-%%}ON{%%-endif%%}\"," - "\"off_delay\":1"; - -const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = - ",\"value_template\":\"{{value_json.%s}}\"," - "\"frc_upd\":true," - "\"pl_on\":\"%s\"," - "\"pl_off\":\"%s\""; - -const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = - ",\"bri_cmd_t\":\"%s\"," - "\"bri_stat_t\":\"%s\"," - "\"bri_scl\":100," - "\"on_cmd_type\":\"%s\"," - "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; - -const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = - ",\"rgb_cmd_t\":\"%s2\"," - "\"rgb_stat_t\":\"%s\"," - "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; - -const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = - ",\"whit_val_cmd_t\":\"%s\"," - "\"whit_val_stat_t\":\"%s\"," - "\"white_value_scale\":100," - "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; - -const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = - ",\"clr_temp_cmd_t\":\"%s\"," - "\"clr_temp_stat_t\":\"%s\"," - "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; - -const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = - ",\"fx_cmd_t\":\"%s\"," - "\"fx_stat_t\":\"%s\"," - "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," - "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; - -const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = - ",\"json_attributes_topic\":\"%s\"," - "\"unit_of_meas\":\" \"," - "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"," - "\"ic\":\"mdi:information-outline\""; - -const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = - ",\"uniq_id\":\"%s\"," - "\"device\":{\"identifiers\":[\"%06X\"]," - "\"connections\":[[\"mac\",\"%s\"]]," - "\"name\":\"%s\"," - "\"model\":\"%s\"," - "\"sw_version\":\"%s%s\"," - "\"manufacturer\":\"Tasmota\"}"; - -const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = - ",\"uniq_id\":\"%s\"," - "\"device\":{\"identifiers\":[\"%06X\"]," - "\"connections\":[[\"mac\",\"%s\"]]}"; - -uint8_t hass_init_step = 0; -uint8_t hass_mode = 0; -int hass_tele_period = 0; - -void TryResponseAppend_P(const char *format, ...) -{ - va_list args; - va_start(args, format); - char dummy[2]; - int dlen = vsnprintf_P(dummy, 1, format, args); - - int mlen = strlen(mqtt_data); - int slen = sizeof(mqtt_data) - 1 - mlen; - if (dlen >= slen) - { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: MQTT discovery failed due to too long topic or friendly name. " - "Please shorten topic and friendly name. Failed to format(%u/%u):"), - dlen, slen); - va_start(args, format); - vsnprintf_P(log_data, sizeof(log_data), format, args); - AddLog(LOG_LEVEL_ERROR); - } - else - { - va_start(args, format); - vsnprintf_P(mqtt_data + mlen, slen, format, args); - } - va_end(args); -} - -void HAssAnnounceRelayLight(void) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char stemp3[TOPSZ]; - char unique_id[30]; - bool is_light = false; - bool is_topic_light = false; - - for (uint32_t i = 1; i <= MAX_RELAYS; i++) - { - is_light = ((i == devices_present) && (light_type)); - is_topic_light = Settings.flag.hass_light || is_light; - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), - (is_topic_light) ? "switch" : "light", unique_id); - MqttPublish(stopic, true); - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), - (is_topic_light) ? "light" : "switch", unique_id); - - if (Settings.flag.hass_discovery && (i <= devices_present)) - { - char name[33 + 2]; - char value_template[33]; - char prefix[TOPSZ]; - char *command_topic = stemp1; - char *state_topic = stemp2; - char *availability_topic = stemp3; - - if (i > MAX_FRIENDLYNAMES) - { - snprintf_P(name, sizeof(name), PSTR("%s %d"), SettingsText(SET_FRIENDLYNAME1), i); - } - else - { - snprintf_P(name, sizeof(name), SettingsText(SET_FRIENDLYNAME1 + i - 1)); - } - GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); - GetTopic_P(command_topic, CMND, mqtt_topic, value_template); - GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - -#ifdef USE_LIGHT - if (is_light) - { - char *brightness_command_topic = stemp1; - - GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); - strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic, stemp3); - - if (Light.subtype >= LST_RGB) - { - char *rgb_command_topic = stemp1; - - GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); - - char *effect_command_topic = stemp1; - GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); - } - if (LST_RGBW == Light.subtype) - { - char *white_temp_command_topic = stemp1; - - GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); - } - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) - { - char *color_temp_command_topic = stemp1; - - GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); - } - } -#endif - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); - } -} - -void HAssAnnounceButtonSwitch(uint8_t device, char *topic, uint8_t present, uint8_t key, uint8_t toggle) -{ - - - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), key ? "SW" : "BTN", device + 1); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); - - if (Settings.flag.hass_discovery && present) - { - char name[33 + 6]; - char value_template[33]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - char jsoname[8]; - - snprintf_P(name, sizeof(name), PSTR("%s %s%d"), SettingsText(SET_FRIENDLYNAME1), key ? "Switch" : "Button", device + 1); - snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key ? "SWITCH" : "BUTTON", device + 1); - GetPowerDevice(value_template, device + 1, sizeof(value_template), - key + Settings.flag.device_index_enable); - GetTopic_P(state_topic, STAT, mqtt_topic, (PSTR("/'%s'"), jsoname)); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - - if (toggle) { - if (!key) { - TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE); - } else { - TryResponseAppend_P(",\"value_template\":\"{%%if is_state(entity_id,\\\"on\\\")-%%}OFF{%%-else-%%}ON{%%-endif%%}\""); - } - } else { - TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2), SettingsText(SET_STATE_TXT1)); - } - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); -} - -void HAssAnnounceSwitches(void) -{ - char sw_topic[TOPSZ]; - - - char *tmp = SettingsText(SET_MQTT_SWITCH_TOPIC); - Format(sw_topic, tmp, sizeof(sw_topic)); - if (!strcmp_P(sw_topic, "0") || strlen(sw_topic) == 0) - { - for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) - { - uint8_t switch_present = 0; - uint8_t toggle = 1; - - if (pin[GPIO_SWT1 + switch_index] < 99) - { - switch_present = 1; - } - - - if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || - Settings.flag3.button_switch_force_local || - !strcmp(mqtt_topic, sw_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), sw_topic)) - { - toggle = 0; - } - HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 1, toggle); - } - } -} - -void HAssAnnounceButtons(void) -{ - char key_topic[TOPSZ]; - - - char *tmp = SettingsText(SET_MQTT_BUTTON_TOPIC); - Format(key_topic, tmp, sizeof(key_topic)); - if (!strcmp_P(key_topic, "0") || strlen(key_topic) == 0) - { - for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) - { - uint8_t button_present = 0; - uint8_t toggle = 1; - - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) - { - button_present = 1; - } - else - { - if (pin[GPIO_KEY1 + button_index] < 99) - { - button_present = 1; - } - } - - - if (Settings.flag3.button_switch_force_local || - !strcmp(mqtt_topic, key_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) - { - toggle = 0; - } - HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 0, toggle); - } - } -} - -void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, uint8_t subidx) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - mqtt_data[0] = '\0'; - - char subname[20]; - NoAlNumToUnderscore(subname, MultiSubName); - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subname); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);; - - if (Settings.flag.hass_discovery) - { - char name[33 + 42]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); - snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_FRIENDLYNAME1), sensorname, MultiSubName); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - - char jname[32]; - int sensor_index = GetCommandCode(jname, sizeof(jname), subsensortype, kHAssJsonSensorTypes); - if (sensor_index > -1) { - char param1[20]; - GetTextIndexed(param1, sizeof(param1), sensor_index, kHAssJsonSensorUnits); - switch (sensor_index) { - case 0: - snprintf_P(param1, sizeof(param1), PSTR("°%c"),TempUnit()); - break; - case 1: - case 2: - snprintf_P(param1, sizeof(param1), PSTR("%s"), PressureUnit().c_str()); - break; - } - char param2[50]; - GetTextIndexed(param2, sizeof(param2), sensor_index, kHAssJsonSensorDevCla); - TryResponseAppend_P(HASS_DISCOVER_SENSOR, param1, param2, sensorname, subsensortype); - if (subidx) { - TryResponseAppend_P(PSTR("[%d]"), subqty -1); - } - } else { - TryResponseAppend_P(HASS_DISCOVER_SENSOR, " ", "ic\":\"mdi:eye", sensorname, subsensortype); - } - TryResponseAppend_P(PSTR("}}\"}")); - } - MqttPublish(stopic, true); -} - -void HAssAnnounceSensors(void) -{ - uint8_t hass_xsns_index = 0; - bool is_sensor = true; - uint8_t subqty = 0; - do - { - mqtt_data[0] = '\0'; - int tele_period_save = tele_period; - tele_period = 2; - XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); - tele_period = tele_period_save; - - char sensordata[512]; - strlcpy(sensordata, mqtt_data, sizeof(sensordata)); - - if (strlen(sensordata)) - { - sensordata[0] = '{'; - snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); - - - - StaticJsonBuffer<500> jsonBuffer; - JsonObject &root = jsonBuffer.parseObject(sensordata); - if (!root.success()) - { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: jsonBuffer failed to parse '%s'"), sensordata); - continue; - } - for (auto sensor : root) - { - const char *sensorname = sensor.key; - JsonObject &sensors = sensor.value.as(); - if (!sensors.success()) - { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: JsonObject failed to parse '%s'"), sensordata); - continue; - } - for (auto subsensor : sensors) - { - - if (subsensor.value.is()) { - JsonArray& subsensors = subsensor.value.as(); - subqty = subsensors.size(); - char MultiSubName[20]; - for (int i = 1; i <= subqty; i++) { - snprintf_P(MultiSubName, sizeof(MultiSubName), PSTR("%s %d"), subsensor.key, i); - HAssAnnounceSensor(sensorname, subsensor.key, MultiSubName, i, 1); - } - } else { HAssAnnounceSensor(sensorname, subsensor.key, subsensor.key, 0, 0);} - } - } - } - yield(); - } while (hass_xsns_index != 0); -} - -void HAssAnnounceStatusSensor(void) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP.getChipId()); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); - - if (Settings.flag.hass_discovery) - { - char name[33 + 7]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - - snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_FRIENDLYNAME1)); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(), - SettingsText(SET_FRIENDLYNAME1), ModuleName().c_str(), my_version, my_image); - - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); -} - -void HAssPublishStatus(void) -{ - Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," - "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," - "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," - "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," - "\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_CMND_IPADDRESS "\":\"%s\"," - "\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), - my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getSdkVersion(), ModuleName().c_str(), - GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), - Settings.bootcount, Settings.save_flag, WiFi.localIP().toString().c_str(), - WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); -} - -void HAssDiscovery(void) -{ - - if (Settings.flag.hass_discovery) - { - Settings.flag.mqtt_response = 0; - Settings.flag.decimal_text = 1; - Settings.flag3.hass_tele_on_power = 1; - Settings.light_scheme = 0; - } - - if (Settings.flag.hass_discovery || (1 == hass_mode)) - { - - HAssAnnounceRelayLight(); - - - HAssAnnounceButtons(); - - - HAssAnnounceSwitches(); - - - HAssAnnounceSensors(); - - - HAssAnnounceStatusSensor(); - } -} - -void HAssDiscover(void) -{ - hass_mode = 1; - hass_init_step = 1; -} - -void HAssAnyKey(void) -{ - if (!Settings.flag.hass_discovery) - { - return; - } - - uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; - uint32_t device = XdrvMailbox.payload & 0xFF; - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; - - char scommand[CMDSZ]; - snprintf_P(scommand, sizeof(scommand), PSTR("%s%d"), (key) ? "SWITCH" : "BUTTON", device); - char stopic[TOPSZ]; - - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(S_JSON_COMMAND_SVALUE, PSTR(D_RSLT_STATE), GetStateText(state)); - MqttPublish(stopic); -} - - - - - -bool Xdrv12(uint8_t function) -{ - bool result = false; - - if (Settings.flag.mqtt_enabled) - { - switch (function) - { - case FUNC_EVERY_SECOND: - if (hass_init_step) - { - hass_init_step--; - if (!hass_init_step) - { - HAssDiscovery(); - } - } - else if (Settings.flag.hass_discovery && Settings.tele_period) - { - hass_tele_period++; - if (hass_tele_period >= Settings.tele_period) - { - hass_tele_period = 0; - - mqtt_data[0] = '\0'; - HAssPublishStatus(); - } - } - break; - case FUNC_ANY_KEY: - HAssAnyKey(); - break; - case FUNC_MQTT_INIT: - hass_mode = 0; - hass_init_step = 2; - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_13_display.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_13_display.ino" -#if defined(USE_I2C) || defined(USE_SPI) -#ifdef USE_DISPLAY - -#define XDRV_13 13 - -#include -#include - -Renderer *renderer; - -enum ColorType { COLOR_BW, COLOR_COLOR }; - -#ifndef MAXBUTTONS -#define MAXBUTTONS 16 -#endif - -#ifdef USE_TOUCH_BUTTONS -VButton *buttons[MAXBUTTONS]; -#endif - - - -uint16_t fg_color = 1; -uint16_t bg_color = 0; -uint8_t color_type = COLOR_BW; -uint8_t auto_draw=1; - -const uint8_t DISPLAY_MAX_DRIVERS = 16; -const uint8_t DISPLAY_MAX_COLS = 44; -const uint8_t DISPLAY_MAX_ROWS = 32; - -const uint8_t DISPLAY_LOG_ROWS = 32; - -#define D_PRFX_DISPLAY "Display" -#define D_CMND_DISP_ADDRESS "Address" -#define D_CMND_DISP_COLS "Cols" -#define D_CMND_DISP_DIMMER "Dimmer" -#define D_CMND_DISP_MODE "Mode" -#define D_CMND_DISP_MODEL "Model" -#define D_CMND_DISP_REFRESH "Refresh" -#define D_CMND_DISP_ROWS "Rows" -#define D_CMND_DISP_SIZE "Size" -#define D_CMND_DISP_FONT "Font" -#define D_CMND_DISP_ROTATE "Rotate" -#define D_CMND_DISP_TEXT "Text" -#define D_CMND_DISP_WIDTH "Width" -#define D_CMND_DISP_HEIGHT "Height" - -enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND, - FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER, - FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_DRAW_FRAME, - FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_LINE, - FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE, - FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE, - FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING, FUNC_DISPLAY_ONOFF }; - -enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; - -const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" - "|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" - D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" - D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; - -void (* const DisplayCommand[])(void) PROGMEM = { - &CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh, - &CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont, - &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress }; - -char *dsp_str; - -uint16_t dsp_x; -uint16_t dsp_y; -uint16_t dsp_x2; -uint16_t dsp_y2; -uint16_t dsp_rad; -uint16_t dsp_color; -int16_t dsp_len; -int16_t disp_xpos = 0; -int16_t disp_ypos = 0; - -uint8_t disp_power = 0; -uint8_t disp_device = 0; -uint8_t disp_refresh = 1; -uint8_t disp_autodraw = 1; -uint8_t dsp_init; -uint8_t dsp_font; -uint8_t dsp_flag; -uint8_t dsp_on; - -#ifdef USE_DISPLAY_MODES1TO5 - -char **disp_log_buffer; -char **disp_screen_buffer; -char disp_temp[2]; -char disp_pres[5]; - -uint8_t disp_log_buffer_cols = 0; -uint8_t disp_log_buffer_idx = 0; -uint8_t disp_log_buffer_ptr = 0; -uint8_t disp_screen_buffer_cols = 0; -uint8_t disp_screen_buffer_rows = 0; -bool disp_subscribed = false; - -#endif - - - -void DisplayInit(uint8_t mode) -{ - if (renderer) { - renderer->DisplayInit(mode, Settings.display_size, Settings.display_rotate, Settings.display_font); - } - else { - dsp_init = mode; - XdspCall(FUNC_DISPLAY_INIT); - } -} - -void DisplayClear(void) -{ - XdspCall(FUNC_DISPLAY_CLEAR); -} - -void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_len = len; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_HLINE); -} - -void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_len = len; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_VLINE); -} - -void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_LINE); -} - -void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_rad = rad; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_CIRCLE); -} - -void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_rad = rad; - dsp_color = color; - XdspCall(FUNC_DISPLAY_FILL_CIRCLE); -} - -void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_RECTANGLE); -} - -void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_FILL_RECTANGLE); -} - -void DisplayDrawFrame(void) -{ - XdspCall(FUNC_DISPLAY_DRAW_FRAME); -} - -void DisplaySetSize(uint8_t size) -{ - Settings.display_size = size &3; - XdspCall(FUNC_DISPLAY_TEXT_SIZE); -} - -void DisplaySetFont(uint8_t font) -{ - Settings.display_font = font &3; - XdspCall(FUNC_DISPLAY_FONT_SIZE); -} - -void DisplaySetRotation(uint8_t rotation) -{ - Settings.display_rotate = rotation &3; - XdspCall(FUNC_DISPLAY_ROTATION); -} - -void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - dsp_x = x; - dsp_y = y; - dsp_str = str; - dsp_color = color; - dsp_flag = flag; - XdspCall(FUNC_DISPLAY_DRAW_STRING); -} - -void DisplayOnOff(uint8_t on) -{ - dsp_on = on; - XdspCall(FUNC_DISPLAY_ONOFF); -} - - - - -uint8_t fatoiv(char *cp,float *res) { - uint8_t index=0; - *res=CharToFloat(cp); - while (*cp) { - if ((*cp>='0' && *cp<='9') || (*cp=='-') || (*cp=='.')) { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -uint8_t atoiv(char *cp, int16_t *res) -{ - uint8_t index = 0; - *res = atoi(cp); - while (*cp) { - if ((*cp>='0' && *cp<='9') || (*cp=='-')) { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -uint8_t atoiV(char *cp, uint16_t *res) -{ - uint8_t index = 0; - *res = atoi(cp); - while (*cp) { - if (*cp>='0' && *cp<='9') { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -void alignright(char *string) { - uint16_t slen=strlen(string); - uint16_t len=slen; - while (len) { - - if (string[len-1]!=' ') { - break; - } - len--; - } - uint16_t diff=slen-len; - if (diff>0) { - - memmove(&string[diff],string,len); - memset(string,' ',diff); - } -} - -char *get_string(char *buff,uint8_t len,char *cp) { -uint8_t index=0; - while (*cp!=':') { - buff[index]=*cp++; - index++; - if (index>=len) break; - } - buff[index]=0; - cp++; - return cp; -} - -#define ESCAPE_CHAR '~' - - -uint32_t decode_te(char *line) { - uint32_t skip = 0; - char sbuf[3],*cp; - while (*line) { - if (*line==ESCAPE_CHAR) { - cp=line+1; - if (*cp!=0 && *cp==ESCAPE_CHAR) { - - memmove(cp,cp+1,strlen(cp)); - skip++; - } else { - - if (strlen(cp)<2) { - - return skip; - } - - sbuf[0]=*(cp); - sbuf[1]=*(cp+1); - sbuf[2]=0; - *line=strtol(sbuf,0,16); - - memmove(cp,cp+2,strlen(cp)-1); - skip += 2; - } - } - line++; - } - return skip; -} - - - -#define DISPLAY_BUFFER_COLS 128 - -void DisplayText(void) -{ - uint8_t lpos; - uint8_t escape = 0; - uint8_t var; - int16_t lin = 0; - int16_t col = 0; - int16_t fill = 0; - int16_t temp; - int16_t temp1; - float ftemp; - - char linebuf[DISPLAY_BUFFER_COLS]; - char *dp = linebuf; - char *cp = XdrvMailbox.data; - - memset(linebuf, ' ', sizeof(linebuf)); - linebuf[sizeof(linebuf)-1] = 0; - *dp = 0; - - while (*cp) { - if (!escape) { - - if (*cp == '[') { - escape = 1; - cp++; - - if ((uint32_t)dp - (uint32_t)linebuf) { - if (!fill) { *dp = 0; } - if (col > 0 && lin > 0) { - - if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); - else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); - } else { - - if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - } - memset(linebuf, ' ', sizeof(linebuf)); - linebuf[sizeof(linebuf)-1] = 0; - dp = linebuf; - } - } else { - - if (dp < (linebuf + DISPLAY_BUFFER_COLS)) { *dp++ = *cp++; } - } - } else { - - if (*cp == ']') { - escape = 0; - cp++; - } else { - - switch (*cp++) { - case 'z': - - if (!renderer) DisplayClear(); - else renderer->fillScreen(bg_color); - disp_xpos = 0; - disp_ypos = 0; - col = 0; - lin = 0; - break; - case 'i': - - DisplayInit(DISPLAY_INIT_PARTIAL); - break; - case 'I': - - DisplayInit(DISPLAY_INIT_FULL); - break; - case 'o': - if (!renderer) { - DisplayOnOff(0); - } else { - renderer->DisplayOnff(0); - } - break; - case 'O': - if (!renderer) { - DisplayOnOff(1); - } else { - renderer->DisplayOnff(1); - } - break; - case 'x': - - var = atoiv(cp, &disp_xpos); - cp += var; - break; - case 'y': - - var = atoiv(cp, &disp_ypos); - cp += var; - break; - case 'l': - - var = atoiv(cp, &lin); - cp += var; - - break; - case 'c': - - var = atoiv(cp, &col); - cp += var; - - break; - case 'C': - - if (*cp=='i') { - - cp++; - var = atoiv(cp, &temp); - if (renderer) ftemp=renderer->GetColorFromIndex(temp); - } else { - - var = fatoiv(cp,&ftemp); - } - fg_color=ftemp; - cp += var; - if (renderer) renderer->setTextColor(fg_color,bg_color); - break; - case 'B': - - if (*cp=='i') { - - cp++; - var = atoiv(cp, &temp); - if (renderer) ftemp=renderer->GetColorFromIndex(temp); - } else { - var = fatoiv(cp,&ftemp); - } - bg_color=ftemp; - cp += var; - if (renderer) renderer->setTextColor(fg_color,bg_color); - break; - case 'p': - - var = atoiv(cp, &fill); - cp += var; - linebuf[fill] = 0; - break; -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) - case 'P': - { char *ep=strchr(cp,':'); - if (ep) { - *ep=0; - ep++; - Draw_RGB_Bitmap(cp,disp_xpos,disp_ypos); - cp=ep; - } - } - break; -#endif - case 'h': - - var = atoiv(cp, &temp); - cp += var; - if (temp < 0) { - if (renderer) renderer->writeFastHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); - else DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); - } else { - if (renderer) renderer->writeFastHLine(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawHLine(disp_xpos, disp_ypos, temp, fg_color); - } - disp_xpos += temp; - break; - case 'v': - - var = atoiv(cp, &temp); - cp += var; - if (temp < 0) { - if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); - else DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); - } else { - if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawVLine(disp_xpos, disp_ypos, temp, fg_color); - } - disp_ypos += temp; - break; - case 'L': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->writeLine(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, fg_color); - disp_xpos += temp; - disp_ypos += temp1; - break; - case 'k': - - var = atoiv(cp, &temp); - cp += var; - if (renderer) renderer->drawCircle(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawCircle(disp_xpos, disp_ypos, temp, fg_color); - break; - case 'K': - - var = atoiv(cp, &temp); - cp += var; - if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color); - break; - case 'r': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->drawRect(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); - break; - case 'R': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->fillRect(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); - break; - case 'u': - - { int16_t rad; - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - cp++; - var = atoiv(cp, &rad); - cp += var; - if (renderer) renderer->drawRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); - - } - break; - case 'U': - - { int16_t rad; - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - cp++; - var = atoiv(cp, &rad); - cp += var; - if (renderer) renderer->fillRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); - - } - break; - - case 't': - if (*cp=='S') { - cp++; - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { - snprintf_P(dp, 9, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - dp += 8; - } - } else { - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -5) { - snprintf_P(dp, 6, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute); - dp += 5; - } - } - break; - case 'T': - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { - snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year%2000); - dp += 8; - } - break; - case 'd': - - if (renderer) renderer->Updateframe(); - else DisplayDrawFrame(); - break; - case 'D': - - auto_draw=*cp&3; - if (renderer) renderer->setDrawMode(auto_draw>>1); - cp += 1; - break; - case 's': - - if (renderer) renderer->setTextSize(*cp&7); - else DisplaySetSize(*cp&3); - cp += 1; - break; - case 'f': - - if (renderer) renderer->setTextFont(*cp&7); - else DisplaySetFont(*cp&7); - cp += 1; - break; - case 'a': - - if (renderer) renderer->setRotation(*cp&3); - else DisplaySetRotation(*cp&3); - cp+=1; - break; - -#ifdef USE_GRAPH - case 'G': - - if (*cp=='d') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - var=atoiv(cp,&temp1); - cp+=var; - RedrawGraph(temp,temp1); - break; - } -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) - if (*cp=='s') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - - char bbuff[128]; - cp=get_string(bbuff,sizeof(bbuff),cp); - Save_graph(temp,bbuff); - break; - } - if (*cp=='r') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - - char bbuff[128]; - cp=get_string(bbuff,sizeof(bbuff),cp); - Restore_graph(temp,bbuff); - break; - } -#endif - { int16_t num,gxp,gyp,gxs,gys,dec,icol; - float ymin,ymax; - var=atoiv(cp,&num); - cp+=var; - cp++; - var=atoiv(cp,&gxp); - cp+=var; - cp++; - var=atoiv(cp,&gyp); - cp+=var; - cp++; - var=atoiv(cp,&gxs); - cp+=var; - cp++; - var=atoiv(cp,&gys); - cp+=var; - cp++; - var=atoiv(cp,&dec); - cp+=var; - cp++; - var=fatoiv(cp,&ymin); - cp+=var; - cp++; - var=fatoiv(cp,&ymax); - cp+=var; - if (color_type==COLOR_COLOR) { - - cp++; - var=atoiv(cp,&icol); - cp+=var; - } else { - icol=0; - } - DefineGraph(num,gxp,gyp,gxs,gys,dec,ymin,ymax,icol); - } - break; - case 'g': - { float temp; - int16_t num; - var=atoiv(cp,&num); - cp+=var; - cp++; - var=fatoiv(cp,&temp); - cp+=var; - AddValue(num,temp); - } - break; -#endif - -#ifdef USE_AWATCH - case 'w': - var = atoiv(cp, &temp); - cp += var; - DrawAClock(temp); - break; -#endif - -#ifdef USE_TOUCH_BUTTONS - case 'b': - { int16_t num,gxp,gyp,gxs,gys,outline,fill,textcolor,textsize; - var=atoiv(cp,&num); - cp+=var; - cp++; - uint8_t bflags=num>>8; - num=num%MAXBUTTONS; - var=atoiv(cp,&gxp); - cp+=var; - cp++; - var=atoiv(cp,&gyp); - cp+=var; - cp++; - var=atoiv(cp,&gxs); - cp+=var; - cp++; - var=atoiv(cp,&gys); - cp+=var; - cp++; - var=atoiv(cp,&outline); - cp+=var; - cp++; - var=atoiv(cp,&fill); - cp+=var; - cp++; - var=atoiv(cp,&textcolor); - cp+=var; - cp++; - var=atoiv(cp,&textsize); - cp+=var; - cp++; - - char bbuff[32]; - cp=get_string(bbuff,sizeof(bbuff),cp); - - if (buttons[num]) { - delete buttons[num]; - } - if (renderer) { - buttons[num]= new VButton(); - if (buttons[num]) { - buttons[num]->vpower=bflags; - buttons[num]->initButtonUL(renderer,gxp,gyp,gxs,gys,renderer->GetColorFromIndex(outline),\ - renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); - if (!bflags) { - - buttons[num]->xdrawButton(bitRead(power,num)); - } else { - - buttons[num]->vpower&=0x7f; - buttons[num]->xdrawButton(buttons[num]->vpower&0x80); - } - } - } - } - break; -#endif - default: - - Response_P(PSTR("Unknown Escape")); - goto exit; - break; - } - } - } - } - exit: - - dp -= decode_te(linebuf); - if ((uint32_t)dp - (uint32_t)linebuf) { - if (!fill) { - *dp = 0; - } else { - linebuf[abs(fill)] = 0; - } - if (fill<0) { - - alignright(linebuf); - } - if (col > 0 && lin > 0) { - - if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); - else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); - } else { - - if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - } - } - - if (auto_draw&1) { - if (renderer) renderer->Updateframe(); - else DisplayDrawFrame(); - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void DisplayClearScreenBuffer(void) -{ - if (disp_screen_buffer_cols) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - memset(disp_screen_buffer[i], 0, disp_screen_buffer_cols); - } - } -} - -void DisplayFreeScreenBuffer(void) -{ - if (disp_screen_buffer != nullptr) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - if (disp_screen_buffer[i] != nullptr) { free(disp_screen_buffer[i]); } - } - free(disp_screen_buffer); - disp_screen_buffer_cols = 0; - disp_screen_buffer_rows = 0; - } -} - -void DisplayAllocScreenBuffer(void) -{ - if (!disp_screen_buffer_cols) { - disp_screen_buffer_rows = Settings.display_rows; - disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); - if (disp_screen_buffer != nullptr) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_screen_buffer[i] == nullptr) { - DisplayFreeScreenBuffer(); - break; - } - } - } - if (disp_screen_buffer != nullptr) { - disp_screen_buffer_cols = Settings.display_cols[0] +1; - DisplayClearScreenBuffer(); - } - } -} - -void DisplayReAllocScreenBuffer(void) -{ - DisplayFreeScreenBuffer(); - DisplayAllocScreenBuffer(); -} - -void DisplayFillScreen(uint32_t line) -{ - uint32_t len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]); - if (len) { - memset(disp_screen_buffer[line] + strlen(disp_screen_buffer[line]), 0x20, len); - disp_screen_buffer[line][disp_screen_buffer_cols -1] = 0; - } -} - - - -void DisplayClearLogBuffer(void) -{ - if (disp_log_buffer_cols) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - memset(disp_log_buffer[i], 0, disp_log_buffer_cols); - } - } -} - -void DisplayFreeLogBuffer(void) -{ - if (disp_log_buffer != nullptr) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - if (disp_log_buffer[i] != nullptr) { free(disp_log_buffer[i]); } - } - free(disp_log_buffer); - disp_log_buffer_cols = 0; - } -} - -void DisplayAllocLogBuffer(void) -{ - if (!disp_log_buffer_cols) { - disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); - if (disp_log_buffer != nullptr) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_log_buffer[i] == nullptr) { - DisplayFreeLogBuffer(); - break; - } - } - } - if (disp_log_buffer != nullptr) { - disp_log_buffer_cols = Settings.display_cols[0] +1; - DisplayClearLogBuffer(); - } - } -} - -void DisplayReAllocLogBuffer(void) -{ - DisplayFreeLogBuffer(); - DisplayAllocLogBuffer(); -} - -void DisplayLogBufferAdd(char* txt) -{ - if (disp_log_buffer_cols) { - strlcpy(disp_log_buffer[disp_log_buffer_idx], txt, disp_log_buffer_cols); - disp_log_buffer_idx++; - if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) { disp_log_buffer_idx = 0; } - } -} - -char* DisplayLogBuffer(char temp_code) -{ - char* result = nullptr; - if (disp_log_buffer_cols) { - if (disp_log_buffer_idx != disp_log_buffer_ptr) { - result = disp_log_buffer[disp_log_buffer_ptr]; - disp_log_buffer_ptr++; - if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; } - - char *pch = strchr(result, '~'); - if (pch != nullptr) { result[pch - result] = temp_code; } - } - } - return result; -} - -void DisplayLogBufferInit(void) -{ - if (Settings.display_mode) { - disp_log_buffer_idx = 0; - disp_log_buffer_ptr = 0; - disp_refresh = Settings.display_refresh; - - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); - snprintf_P(disp_pres, sizeof(disp_pres), PressureUnit().c_str()); - - DisplayReAllocLogBuffer(); - - char buffer[40]; - snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), my_version, my_image); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); - DisplayLogBufferAdd(buffer); - - snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active)); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str()); - DisplayLogBufferAdd(buffer); - if (!global_state.wifi_down) { - snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), WiFi.localIP().toString().c_str()); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI())); - DisplayLogBufferAdd(buffer); - } - } -} - - - - - -enum SensorQuantity { - JSON_TEMPERATURE, - JSON_HUMIDITY, JSON_LIGHT, JSON_NOISE, JSON_AIRQUALITY, - JSON_PRESSURE, JSON_PRESSUREATSEALEVEL, - JSON_ILLUMINANCE, - JSON_GAS, - JSON_YESTERDAY, JSON_TOTAL, JSON_TODAY, - JSON_PERIOD, - JSON_POWERFACTOR, JSON_COUNTER, JSON_ANALOG_INPUT, JSON_UV_LEVEL, - JSON_CURRENT, - JSON_VOLTAGE, - JSON_POWERUSAGE, - JSON_CO2, - JSON_FREQUENCY }; -const char kSensorQuantity[] PROGMEM = - D_JSON_TEMPERATURE "|" - D_JSON_HUMIDITY "|" D_JSON_LIGHT "|" D_JSON_NOISE "|" D_JSON_AIRQUALITY "|" - D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" - D_JSON_ILLUMINANCE "|" - D_JSON_GAS "|" - D_JSON_YESTERDAY "|" D_JSON_TOTAL "|" D_JSON_TODAY "|" - D_JSON_PERIOD "|" - D_JSON_POWERFACTOR "|" D_JSON_COUNTER "|" D_JSON_ANALOG_INPUT "|" D_JSON_UV_LEVEL "|" - D_JSON_CURRENT "|" - D_JSON_VOLTAGE "|" - D_JSON_POWERUSAGE "|" - D_JSON_CO2 "|" - D_JSON_FREQUENCY ; - -void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value) -{ - char quantity[TOPSZ]; - char buffer[Settings.display_cols[0] +1]; - char spaces[Settings.display_cols[0]]; - char source[Settings.display_cols[0] - Settings.display_cols[1]]; - char svalue[Settings.display_cols[1] +1]; - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("DisplayJsonValue")); -#endif - - memset(spaces, 0x20, sizeof(spaces)); - spaces[sizeof(spaces) -1] = '\0'; - snprintf_P(source, sizeof(source), PSTR("%s%s%s%s"), topic, (strlen(topic))?"/":"", mkey, spaces); - - int quantity_code = GetCommandCode(quantity, sizeof(quantity), mkey, kSensorQuantity); - if ((-1 == quantity_code) || !strcmp_P(mkey, S_RSLT_POWER)) { - return; - } - if (JSON_TEMPERATURE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s~%s"), value, disp_temp); - } - else if ((quantity_code >= JSON_HUMIDITY) && (quantity_code <= JSON_AIRQUALITY)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s%%"), value); - } - else if ((quantity_code >= JSON_PRESSURE) && (quantity_code <= JSON_PRESSUREATSEALEVEL)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s%s"), value, disp_pres); - } - else if (JSON_ILLUMINANCE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_LUX), value); - } - else if (JSON_GAS == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOOHM), value); - } - else if ((quantity_code >= JSON_YESTERDAY) && (quantity_code <= JSON_TODAY)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOWATTHOUR), value); - } - else if (JSON_PERIOD == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATTHOUR), value); - } - else if ((quantity_code >= JSON_POWERFACTOR) && (quantity_code <= JSON_UV_LEVEL)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), value); - } - else if (JSON_CURRENT == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_AMPERE), value); - } - else if (JSON_VOLTAGE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_VOLT), value); - } - else if (JSON_POWERUSAGE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATT), value); - } - else if (JSON_CO2 == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value); - } - else if (JSON_FREQUENCY == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_HERTZ), value); - } - snprintf_P(buffer, sizeof(buffer), PSTR("%s %s"), source, svalue); - - - - DisplayLogBufferAdd(buffer); -} - -void DisplayAnalyzeJson(char *topic, char *json) -{ -# 1145 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_13_display.ino" - String jsonStr = json; - - StaticJsonBuffer<1024> jsonBuf; - JsonObject &root = jsonBuf.parseObject(jsonStr); - if (root.success()) { - - const char *unit; - unit = root[D_JSON_TEMPERATURE_UNIT]; - if (unit) { - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), unit); - } - unit = root[D_JSON_PRESSURE_UNIT]; - if (unit) { - snprintf_P(disp_pres, sizeof(disp_pres), PSTR("%s"), unit); - } - - for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) { - JsonVariant value = it->value; - if (value.is()) { - JsonObject& Object2 = value; - for (JsonObject::iterator it2 = Object2.begin(); it2 != Object2.end(); ++it2) { - JsonVariant value2 = it2->value; - if (value2.is()) { - JsonObject& Object3 = value2; - for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) { - const char* value = it3->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it3->key, value); - } - } - } else { - const char* value = it2->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it2->key, value); - } - } - } - } else { - const char* value = it->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it->key, value); - } - } - } - } -} - -void DisplayMqttSubscribe(void) -{ - - - - - - - if (Settings.display_model && (Settings.display_mode &0x04)) { - - char stopic[TOPSZ]; - char ntopic[TOPSZ]; - - ntopic[0] = '\0'; - strlcpy(stopic, SettingsText(SET_MQTT_FULLTOPIC), sizeof(stopic)); - char *tp = strtok(stopic, "/"); - while (tp != nullptr) { - if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { - break; - } - strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); - tp = strtok(nullptr, "/"); - } - strncat(ntopic, SettingsText(SET_MQTTPREFIX3), sizeof(ntopic) - strlen(ntopic) -1); - strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); - MqttSubscribe(ntopic); - disp_subscribed = true; - } else { - disp_subscribed = false; - } -} - -bool DisplayMqttData(void) -{ - if (disp_subscribed) { - char stopic[TOPSZ]; - - snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), SettingsText(SET_MQTTPREFIX3)); - char *tp = strstr(XdrvMailbox.topic, stopic); - if (tp) { - if (Settings.display_mode &0x04) { - tp = tp + strlen(stopic); - char *topic = strtok(tp, "/"); - DisplayAnalyzeJson(topic, XdrvMailbox.data); - } - return true; - } - } - return false; -} - -void DisplayLocalSensor(void) -{ - if ((Settings.display_mode &0x02) && (0 == tele_period)) { - char no_topic[1] = { 0 }; - - DisplayAnalyzeJson(no_topic, mqtt_data); - } -} - -#endif - - - - - -void DisplayInitDriver(void) -{ - XdspCall(FUNC_DISPLAY_INIT_DRIVER); - - if (renderer) { - renderer->setTextFont(Settings.display_font); - renderer->setTextSize(Settings.display_size); - } - - - - - if (Settings.display_model) { - devices_present++; - disp_device = devices_present; - -#ifndef USE_DISPLAY_MODES1TO5 - Settings.display_mode = 0; -#else - DisplayLogBufferInit(); -#endif - } -} - -void DisplaySetPower(void) -{ - disp_power = bitRead(XdrvMailbox.index, disp_device -1); - - - - if (Settings.display_model) { - if (!renderer) { - XdspCall(FUNC_DISPLAY_POWER); - } else { - renderer->DisplayOnff(disp_power); - } - } -} - - - - - -void CmndDisplay(void) -{ - Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\"" - D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" - D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), - Settings.display_model, Settings.display_width, Settings.display_height, - Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, - Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); -} - -void CmndDisplayModel(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) { - uint32_t last_display_model = Settings.display_model; - Settings.display_model = XdrvMailbox.payload; - if (XdspCall(FUNC_DISPLAY_MODEL)) { - restart_flag = 2; - } else { - Settings.display_model = last_display_model; - } - } - ResponseCmndNumber(Settings.display_model); -} - -void CmndDisplayWidth(void) -{ - if (XdrvMailbox.payload > 0) { - if (XdrvMailbox.payload != Settings.display_width) { - Settings.display_width = XdrvMailbox.payload; - restart_flag = 2; - } - } - ResponseCmndNumber(Settings.display_width); -} - -void CmndDisplayHeight(void) -{ - if (XdrvMailbox.payload > 0) { - if (XdrvMailbox.payload != Settings.display_height) { - Settings.display_height = XdrvMailbox.payload; - restart_flag = 2; - } - } - ResponseCmndNumber(Settings.display_height); -} - -void CmndDisplayMode(void) -{ -#ifdef USE_DISPLAY_MODES1TO5 - - - - - - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - uint32_t last_display_mode = Settings.display_mode; - Settings.display_mode = XdrvMailbox.payload; - - if (disp_subscribed != (Settings.display_mode &0x04)) { - restart_flag = 2; - } else { - if (last_display_mode && !Settings.display_mode) { - DisplayInit(DISPLAY_INIT_MODE); - if (renderer) renderer->fillScreen(bg_color); - else DisplayClear(); - } else { - DisplayLogBufferInit(); - DisplayInit(DISPLAY_INIT_MODE); - } - } - } -#endif - ResponseCmndNumber(Settings.display_mode); -} - -void CmndDisplayDimmer(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; - if (Settings.display_dimmer && !(disp_power)) { - ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY); - } - else if (!Settings.display_dimmer && disp_power) { - ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); - } - if (renderer) renderer->dim(Settings.display_dimmer); - } - ResponseCmndNumber(Settings.display_dimmer); -} - -void CmndDisplaySize(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { - Settings.display_size = XdrvMailbox.payload; - if (renderer) renderer->setTextSize(Settings.display_size); - else DisplaySetSize(Settings.display_size); - } - ResponseCmndNumber(Settings.display_size); -} - -void CmndDisplayFont(void) -{ - if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) { - Settings.display_font = XdrvMailbox.payload; - if (renderer) renderer->setTextFont(Settings.display_font); - else DisplaySetFont(Settings.display_font); - } - ResponseCmndNumber(Settings.display_font); -} - -void CmndDisplayRotate(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { - if (Settings.display_rotate != XdrvMailbox.payload) { -# 1428 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_13_display.ino" - Settings.display_rotate = XdrvMailbox.payload; - DisplayInit(DISPLAY_INIT_MODE); -#ifdef USE_DISPLAY_MODES1TO5 - DisplayLogBufferInit(); -#endif - } - } - ResponseCmndNumber(Settings.display_rotate); -} - -void CmndDisplayText(void) -{ - if (disp_device && XdrvMailbox.data_len > 0) { -#ifndef USE_DISPLAY_MODES1TO5 - DisplayText(); -#else - if (!Settings.display_mode) { - DisplayText(); - } else { - DisplayLogBufferAdd(XdrvMailbox.data); - } -#endif - ResponseCmndChar(XdrvMailbox.data); - } -} - -void CmndDisplayAddress(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { - Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]); - } -} - -void CmndDisplayRefresh(void) -{ - if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { - Settings.display_refresh = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.display_refresh); -} - -void CmndDisplayColumns(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { - Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload; -#ifdef USE_DISPLAY_MODES1TO5 - if (1 == XdrvMailbox.index) { - DisplayLogBufferInit(); - DisplayReAllocScreenBuffer(); - } -#endif - } - ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]); - } -} - -void CmndDisplayRows(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { - Settings.display_rows = XdrvMailbox.payload; -#ifdef USE_DISPLAY_MODES1TO5 - DisplayLogBufferInit(); - DisplayReAllocScreenBuffer(); -#endif - } - ResponseCmndNumber(Settings.display_rows); -} - - - - - -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) -void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { - if (!renderer) return; - - - File fp; - fp=SD.open(file,FILE_READ); - if (!fp) return; - uint16_t xsize; - fp.read((uint8_t*)&xsize,2); - uint16_t ysize; - fp.read((uint8_t*)&ysize,2); - -#if 1 -#define XBUFF 128 - uint16_t xdiv=xsize/XBUFF; - renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); - for(int16_t j=0; j=2) renderer->pushColors(rgb,len/2,true); - } - OsWatchLoop(); - } - renderer->setAddrWindow(0,0,0,0); -#else - for(int16_t j=0; jwritePixel(xp+i,yp,rgb); - } - delay(0); - OsWatchLoop(); - yp++; - } -#endif - fp.close(); -} -#endif - -#ifdef USE_AWATCH -#define MINUTE_REDUCT 4 - -#ifndef pi -#define pi 3.14159265359 -#endif - - -void DrawAClock(uint16_t rad) { - if (!renderer) return; - float frad=rad; - uint16_t hred=frad/3.0; - renderer->fillCircle(disp_xpos, disp_ypos, rad, bg_color); - renderer->drawCircle(disp_xpos, disp_ypos, rad, fg_color); - renderer->fillCircle(disp_xpos, disp_ypos, 4, fg_color); - for (uint8_t count=0; count<60; count+=5) { - float p1=((float)count*(pi/30)-(pi/2)); - uint8_t len; - if ((count%15)==0) { - len=4; - } else { - len=2; - } - renderer->writeLine(disp_xpos+((float)(rad-len)*cosf(p1)), disp_ypos+((float)(rad-len)*sinf(p1)), disp_xpos+(frad*cosf(p1)), disp_ypos+(frad*sinf(p1)), fg_color); - } - - - float hour=((float)RtcTime.hour*60.0+(float)RtcTime.minute)/60.0; - float temp=(hour*(pi/6.0)-(pi/2.0)); - renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-hred)*cosf(temp),disp_ypos+(frad-hred)*sinf(temp), fg_color); - - - temp=((float)RtcTime.minute*(pi/30.0)-(pi/2.0)); - renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-MINUTE_REDUCT)*cosf(temp),disp_ypos+(frad-MINUTE_REDUCT)*sinf(temp), fg_color); -} -#endif - - -#ifdef USE_GRAPH - -typedef union { - uint8_t data; - struct { - uint8_t overlay : 1; - uint8_t draw : 1; - uint8_t nu3 : 1; - uint8_t nu4 : 1; - uint8_t nu5 : 1; - uint8_t nu6 : 1; - uint8_t nu7 : 1; - uint8_t nu8 : 1; - }; -} GFLAGS; - -struct GRAPH { - uint16_t xp; - uint16_t yp; - uint16_t xs; - uint16_t ys; - float ymin; - float ymax; - float range; - uint32_t x_time; - uint32_t last_ms; - uint32_t last_ms_redrawn; - int16_t decimation; - uint16_t dcnt; - uint32_t summ; - uint16_t xcnt; - uint8_t *values; - uint8_t xticks; - uint8_t yticks; - uint8_t last_val; - uint8_t color_index; - GFLAGS flags; -}; - - -struct GRAPH *graph[NUM_GRAPHS]; - -#define TICKLEN 4 -void ClrGraph(uint16_t num) { - struct GRAPH *gp=graph[num]; - - uint16_t xticks=gp->xticks; - uint16_t yticks=gp->yticks; - uint16_t count; - - - if (gp->flags.overlay) return; - - renderer->fillRect(gp->xp+1,gp->yp+1,gp->xs-2,gp->ys-2,bg_color); - - if (xticks) { - float cxp=gp->xp,xd=(float)gp->xs/(float)xticks; - for (count=0; countwriteFastVLine(cxp,gp->yp+gp->ys-TICKLEN,TICKLEN,fg_color); - cxp+=xd; - } - } - if (yticks) { - if (gp->ymin<0 && gp->ymax>0) { - - float cxp=0; - float czp=gp->yp+(gp->ymax/gp->range); - while (cxpxs) { - renderer->writeFastHLine(gp->xp+cxp,czp,2,fg_color); - cxp+=6.0; - } - - float cyp=0,yd=gp->ys/yticks; - for (count=0; countgp->yp) { - renderer->writeFastHLine(gp->xp,czp-cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp-cyp,TICKLEN,fg_color); - } - if ((czp+cyp)<(gp->yp+gp->ys)) { - renderer->writeFastHLine(gp->xp,czp+cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp+cyp,TICKLEN,fg_color); - } - cyp+=yd; - } - } else { - float cyp=gp->yp,yd=gp->ys/yticks; - for (count=0; countwriteFastHLine(gp->xp,cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,cyp,TICKLEN,fg_color); - cyp+=yd; - } - } - } -} - - -void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol) { - if (!renderer) return; - uint8_t rflg=0; - if (xs<0) { - rflg=1; - xs=abs(xs); - } - struct GRAPH *gp; - uint16_t count; - uint16_t index=num%NUM_GRAPHS; - if (!graph[index]) { - gp=(struct GRAPH*)calloc(sizeof(struct GRAPH),1); - if (!gp) return; - graph[index]=gp; - } else { - gp=graph[index]; - if (rflg) { - RedrawGraph(index,1); - return; - } - } - - - gp->xticks=(num>>4)&0x3f; - gp->yticks=(num>>10)&0x3f; - gp->xp=xp; - gp->yp=yp; - gp->xs=xs; - gp->ys=ys; - if (!dec) dec=1; - gp->decimation=dec; - if (dec>0) { - - gp->x_time=((float)dec*60000.0)/(float)xs; - gp->last_ms=millis()+gp->x_time; - } - gp->ymin=ymin; - gp->ymax=ymax; - gp->range=(ymax-ymin)/ys; - gp->xcnt=0; - gp->dcnt=0; - gp->summ=0; - if (gp->values) free(gp->values); - gp->values=(uint8_t*) calloc(1,xs+2); - if (!gp->values) { - free(gp); - graph[index]=0; - return; - } - - gp->values[0]=0; - - gp->last_ms_redrawn=millis(); - - if (!icol) icol=1; - gp->color_index=icol; - gp->flags.overlay=0; - gp->flags.draw=1; - - - if (index>0) { - for (uint8_t count=0; countxp==gp1->xp) && (gp->yp==gp1->yp)) { - gp->flags.overlay=1; - break; - } - } - } - } - - - renderer->drawRect(xp,yp,xs,ys,fg_color); - - ClrGraph(index); - -} - - -void DisplayCheckGraph() { - int16_t count; - struct GRAPH *gp; - for (count=0;countdecimation>0) { - - while (millis()>gp->last_ms) { - gp->last_ms+=gp->x_time; - uint8_t val; - if (gp->dcnt) { - val=gp->summ/gp->dcnt; - gp->dcnt=0; - gp->summ=0; - gp->last_val=val; - } else { - val=gp->last_val; - } - AddGraph(count,val); - } - } - } - } -} - - -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) -#include - -void Save_graph(uint8_t num, char *path) { - if (!renderer) return; - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - File fp; - SD.remove(path); - fp=SD.open(path,FILE_WRITE); - if (!fp) return; - char str[32]; - sprintf_P(str,PSTR("%d\t%d\t%d\t"),gp->xcnt,gp->xs,gp->ys); - fp.print(str); - dtostrfd(gp->ymin,2,str); - fp.print(str); - fp.print("\t"); - dtostrfd(gp->ymax,2,str); - fp.print(str); - fp.print("\t"); - for (uint32_t count=0;countxs;count++) { - dtostrfd(gp->values[count],0,str); - fp.print(str); - fp.print("\t"); - } - fp.print("\n"); - fp.close(); -} -void Restore_graph(uint8_t num, char *path) { - if (!renderer) return; - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - File fp; - fp=SD.open(path,FILE_READ); - if (!fp) return; - char vbuff[32]; - char *cp=vbuff; - uint8_t buf[2]; - uint8_t findex=0; - - for (uint32_t count=0;count<=gp->xs+4;count++) { - cp=vbuff; - findex=0; - while (fp.available()) { - fp.read(buf,1); - if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { - break; - } else { - *cp++=buf[0]; - findex++; - if (findex>=sizeof(vbuff)-1) break; - } - } - *cp=0; - if (count<=4) { - if (count==0) gp->xcnt=atoi(vbuff); - } else { - gp->values[count-5]=atoi(vbuff); - } - } - fp.close(); - RedrawGraph(num,1); -} -#endif - -void RedrawGraph(uint8_t num, uint8_t flags) { - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - if (!flags) { - gp->flags.draw=0; - return; - } - if (!renderer) return; - - gp->flags.draw=1; - uint16_t linecol=fg_color; - - if (color_type==COLOR_COLOR) { - linecol=renderer->GetColorFromIndex(gp->color_index); - } - - if (!gp->flags.overlay) { - - renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); - - ClrGraph(index); - } - - for (uint16_t count=0;countxs-1;count++) { - renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); - } -} - - -void AddGraph(uint8_t num,uint8_t val) { - struct GRAPH *gp=graph[num]; - if (!renderer) return; - - uint16_t linecol=fg_color; - if (color_type==COLOR_COLOR) { - linecol=renderer->GetColorFromIndex(gp->color_index); - } - gp->xcnt++; - if (gp->xcnt>gp->xs) { - gp->xcnt=gp->xs; - int16_t count; - - for (count=0;countxs-1;count++) { - gp->values[count]=gp->values[count+1]; - } - gp->values[gp->xcnt-1]=val; - - if (!gp->flags.draw) return; - - - if (millis()-gp->last_ms_redrawn>1000) { - gp->last_ms_redrawn=millis(); - - if (!gp->flags.overlay) { - - renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); - - ClrGraph(num); - } - - for (count=0;countxs-1;count++) { - renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); - } - } - } else { - - gp->values[gp->xcnt]=val; - if (!gp->flags.draw) return; - renderer->writeLine(gp->xp+gp->xcnt-1,gp->yp+gp->ys-gp->values[gp->xcnt-1]-1,gp->xp+gp->xcnt,gp->yp+gp->ys-gp->values[gp->xcnt]-1,linecol); - } -} - - - -void AddValue(uint8_t num,float fval) { - - num=num%NUM_GRAPHS; - struct GRAPH *gp=graph[num]; - if (!gp) return; - - if (fval>gp->ymax) fval=gp->ymax; - if (fvalymin) fval=gp->ymin; - - int16_t val; - val=(fval-gp->ymin)/gp->range; - - if (val>gp->ys-1) val=gp->ys-1; - if (val<0) val=0; - - - gp->summ+=val; - gp->dcnt++; - - - if (gp->decimation<0) { - if (gp->dcnt>=-gp->decimation) { - gp->dcnt=0; - - val=gp->summ/-gp->decimation; - gp->summ=0; - - AddGraph(num,val); - } - } -} -#endif - - - - - -bool Xdrv13(uint8_t function) -{ - bool result = false; - - if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { - switch (function) { - case FUNC_PRE_INIT: - DisplayInitDriver(); -#ifdef USE_GRAPH - for (uint8_t count=0;count - -TasmotaSerial *MP3Player; - - - - - -#define D_CMND_MP3 "MP3" - -const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; -const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; -const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device|Reset|DAC"; - - - - - -enum MP3_Commands { - CMND_MP3_TRACK, - CMND_MP3_PLAY, - CMND_MP3_PAUSE, - CMND_MP3_STOP, - CMND_MP3_VOLUME, - CMND_MP3_EQ, - CMND_MP3_DEVICE, - CMND_MP3_RESET, - CMND_MP3_DAC }; - - - - - - -#define MP3_CMD_RESET_VALUE 0 - -#define MP3_CMD_TRACK 0x03 -#define MP3_CMD_PLAY 0x0d -#define MP3_CMD_PAUSE 0x0e -#define MP3_CMD_STOP 0x16 -#define MP3_CMD_VOLUME 0x06 -#define MP3_CMD_EQ 0x07 -#define MP3_CMD_DEVICE 0x09 -#define MP3_CMD_RESET 0x0C -#define MP3_CMD_DAC 0x1A - - - - - - -uint16_t MP3_Checksum(uint8_t *array) -{ - uint16_t checksum = 0; - for (uint32_t i = 0; i < 6; i++) { - checksum += array[i]; - } - checksum = checksum^0xffff; - return (checksum+1); -} - - - - - - -void MP3PlayerInit(void) { - MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); - - if (MP3Player->begin(9600)) { - MP3Player->flush(); - delay(1000); - MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); - delay(3000); - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); - } - return; -} -# 159 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_14_mp3.ino" -void MP3_CMD(uint8_t mp3cmd,uint16_t val) { - uint8_t i = 0; - uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; - cmd[3] = mp3cmd; - cmd[4] = 0; - cmd[5] = val>>8; - cmd[6] = val; - uint16_t chks = MP3_Checksum(&cmd[1]); - cmd[7] = chks>>8; - cmd[8] = chks; - MP3Player->write(cmd, sizeof(cmd)); - delay(1000); - if (mp3cmd == MP3_CMD_RESET) { - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); - } - return; -} - - - - - -bool MP3PlayerCmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_MP3); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); - - switch (command_code) { - case CMND_MP3_TRACK: - case CMND_MP3_VOLUME: - case CMND_MP3_EQ: - case CMND_MP3_DEVICE: - case CMND_MP3_DAC: - - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_MP3_TRACK) { MP3_CMD(MP3_CMD_TRACK, XdrvMailbox.payload); } - if (command_code == CMND_MP3_VOLUME) { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } - if (command_code == CMND_MP3_EQ) { MP3_CMD(MP3_CMD_EQ, XdrvMailbox.payload); } - if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } - if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } - } - Response_P(S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_MP3_PLAY: - case CMND_MP3_PAUSE: - case CMND_MP3_STOP: - case CMND_MP3_RESET: - - if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } - if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } - if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } - if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } - Response_P(S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); - break; - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - - -bool Xdrv14(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_MP3_DFR562] < 99) { - switch (function) { - case FUNC_PRE_INIT: - MP3PlayerInit(); - break; - case FUNC_COMMAND: - result = MP3PlayerCmd(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_15_pca9685.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_15_pca9685.ino" -#ifdef USE_I2C -#ifdef USE_PCA9685 - - - - - - -#define XDRV_15 15 -#define XI2C_01 1 - -#define PCA9685_REG_MODE1 0x00 -#define PCA9685_REG_LED0_ON_L 0x06 -#define PCA9685_REG_PRE_SCALE 0xFE - -#ifndef USE_PCA9685_ADDR - #define USE_PCA9685_ADDR 0x40 -#endif -#ifndef USE_PCA9685_FREQ - #define USE_PCA9685_FREQ 50 -#endif - -bool pca9685_detected = false; -uint16_t pca9685_freq = USE_PCA9685_FREQ; -uint16_t pca9685_pin_pwm_value[16]; - -void PCA9685_Detect(void) -{ - if (I2cActive(USE_PCA9685_ADDR)) { return; } - - uint8_t buffer; - if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x20); - if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { - if (0x20 == buffer) { - pca9685_detected = true; - I2cSetActiveFound(USE_PCA9685_ADDR, "PCA9685"); - PCA9685_Reset(); - } - } - } -} - -void PCA9685_Reset(void) -{ - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); - PCA9685_SetPWMfreq(USE_PCA9685_FREQ); - for (uint32_t pin=0;pin<16;pin++) { - PCA9685_SetPWM(pin,0,false); - pca9685_pin_pwm_value[pin] = 0; - } - Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); -} - -void PCA9685_SetPWMfreq(double freq) { - - - - - if (freq > 23 && freq < 1527) { - pca9685_freq=freq; - } else { - pca9685_freq=50; - } - uint8_t pre_scale_osc = round(25000000/(4096*pca9685_freq))-1; - if (1526 == pca9685_freq) pre_scale_osc=0xFF; - uint8_t current_mode1 = I2cRead8(USE_PCA9685_ADDR, PCA9685_REG_MODE1); - uint8_t sleep_mode1 = (current_mode1&0x7F) | 0x10; - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, sleep_mode1); - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_PRE_SCALE, pre_scale_osc); - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, current_mode1 | 0xA0); -} - -void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off) { - uint8_t led_reg = PCA9685_REG_LED0_ON_L + 4 * pin; - uint32_t led_data = 0; - I2cWrite8(USE_PCA9685_ADDR, led_reg, on); - I2cWrite8(USE_PCA9685_ADDR, led_reg+1, (on >> 8)); - I2cWrite8(USE_PCA9685_ADDR, led_reg+2, off); - I2cWrite8(USE_PCA9685_ADDR, led_reg+3, (off >> 8)); -} - -void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { - if (4096 == pwm) { - PCA9685_SetPWM_Reg(pin, 4096, 0); - } else { - PCA9685_SetPWM_Reg(pin, 0, pwm); - } - pca9685_pin_pwm_value[pin] = pwm; -} - -bool PCA9685_Command(void) -{ - bool serviced = true; - bool validpin = false; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((new_freq >= 24) && (new_freq <= 1526)) { - PCA9685_SetPWMfreq(new_freq); - Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); - return serviced; - } - } else { - Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); - return serviced; - } - } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWM")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (paramcount > 2) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { - PCA9685_SetPWM(pin, 4096, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); - serviced = true; - return serviced; - } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { - PCA9685_SetPWM(pin, 0, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); - serviced = true; - return serviced; - } - uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { - PCA9685_SetPWM(pin, pwm, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); - serviced = true; - return serviced; - } - } - } - } - return serviced; -} - -void PCA9685_OutputTelemetry(bool telemetry) -{ - ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); - for (uint32_t pin=0;pin<16;pin++) { - ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); - } - ResponseAppend_P(PSTR("\"END\":1}}")); - if (telemetry) { - MqttPublishTeleSensor(); - } -} - -bool Xdrv15(uint8_t function) -{ - if (!I2cEnabled(XI2C_01)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - PCA9685_Detect(); - } - else if (pca9685_detected) { - switch (function) { - case FUNC_EVERY_SECOND: - if (tele_period == 0) { - PCA9685_OutputTelemetry(true); - } - break; - case FUNC_COMMAND_DRIVER: - if (XDRV_15 == XdrvMailbox.index) { - result = PCA9685_Command(); - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -#ifdef USE_LIGHT -#ifdef USE_TUYA_MCU - -#define XDRV_16 16 -#define XNRG_16 16 - -#ifndef TUYA_DIMMER_ID -#define TUYA_DIMMER_ID 0 -#endif - -#define TUYA_CMD_HEARTBEAT 0x00 -#define TUYA_CMD_QUERY_PRODUCT 0x01 -#define TUYA_CMD_MCU_CONF 0x02 -#define TUYA_CMD_WIFI_STATE 0x03 -#define TUYA_CMD_WIFI_RESET 0x04 -#define TUYA_CMD_WIFI_SELECT 0x05 -#define TUYA_CMD_SET_DP 0x06 -#define TUYA_CMD_STATE 0x07 -#define TUYA_CMD_QUERY_STATE 0x08 - -#define TUYA_LOW_POWER_CMD_WIFI_STATE 0x02 -#define TUYA_LOW_POWER_CMD_WIFI_RESET 0x03 -#define TUYA_LOW_POWER_CMD_WIFI_CONFIG 0x04 -#define TUYA_LOW_POWER_CMD_STATE 0x05 - -#define TUYA_TYPE_BOOL 0x01 -#define TUYA_TYPE_VALUE 0x02 -#define TUYA_TYPE_STRING 0x03 -#define TUYA_TYPE_ENUM 0x04 - -#define TUYA_BUFFER_SIZE 256 - -#include - -TasmotaSerial *TuyaSerial = nullptr; - -struct TUYA { - uint16_t new_dim = 0; - bool ignore_dim = false; - uint8_t cmd_status = 0; - uint8_t cmd_checksum = 0; - uint8_t data_len = 0; - uint8_t wifi_state = -2; - uint8_t heartbeat_timer = 0; -#ifdef USE_ENERGY_SENSOR - uint32_t lastPowerCheckTime = 0; -#endif - char *buffer = nullptr; - int byte_counter = 0; - bool low_power_mode = false; - bool send_success_next_second = false; -} Tuya; - - -enum TuyaSupportedFunctions { - TUYA_MCU_FUNC_NONE, - TUYA_MCU_FUNC_SWT1 = 1, - TUYA_MCU_FUNC_SWT2, - TUYA_MCU_FUNC_SWT3, - TUYA_MCU_FUNC_SWT4, - TUYA_MCU_FUNC_REL1 = 11, - TUYA_MCU_FUNC_REL2, - TUYA_MCU_FUNC_REL3, - TUYA_MCU_FUNC_REL4, - TUYA_MCU_FUNC_REL5, - TUYA_MCU_FUNC_REL6, - TUYA_MCU_FUNC_REL7, - TUYA_MCU_FUNC_REL8, - TUYA_MCU_FUNC_DIMMER = 21, - TUYA_MCU_FUNC_POWER = 31, - TUYA_MCU_FUNC_CURRENT, - TUYA_MCU_FUNC_VOLTAGE, - TUYA_MCU_FUNC_BATTERY_STATE, - TUYA_MCU_FUNC_BATTERY_PERCENTAGE, - TUYA_MCU_FUNC_REL1_INV = 41, - TUYA_MCU_FUNC_REL2_INV, - TUYA_MCU_FUNC_REL3_INV, - TUYA_MCU_FUNC_REL4_INV, - TUYA_MCU_FUNC_REL5_INV, - TUYA_MCU_FUNC_REL6_INV, - TUYA_MCU_FUNC_REL7_INV, - TUYA_MCU_FUNC_REL8_INV, - TUYA_MCU_FUNC_LOWPOWER_MODE = 51, - TUYA_MCU_FUNC_LAST = 255 -}; - -const char kTuyaCommand[] PROGMEM = "|" - D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE; - -void (* const TuyaCommand[])(void) PROGMEM = { - &CmndTuyaMcu, &CmndTuyaSend -}; -# 126 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -void CmndTuyaSend(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - if (XdrvMailbox.data_len > 0) { - - char *p; - char *data; - uint8_t i = 0; - uint8_t dpId = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { - if ( i == 0) { - dpId = strtoul(str, nullptr, 0); - } else { - data = str; - } - i++; - } - - if (1 == XdrvMailbox.index) { - TuyaSendBool(dpId, strtoul(data, nullptr, 0)); - } else if (2 == XdrvMailbox.index) { - TuyaSendValue(dpId, strtoull(data, nullptr, 0)); - } else if (3 == XdrvMailbox.index) { - TuyaSendString(dpId, data); - } else if (4 == XdrvMailbox.index) { - TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); - } - } - ResponseCmndDone(); - } -} - - - - - - - -void CmndTuyaMcu(void) { - if (XdrvMailbox.data_len > 0) { - char *p; - uint8_t i = 0; - uint8_t parm[3] = { 0 }; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { - parm[i] = strtoul(str, nullptr, 0); - i++; - } - - if (TuyaFuncIdValid(parm[0])) { - TuyaAddMcuFunc(parm[0], parm[1]); - restart_flag = 2; - } else { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); - } - - } - - Response_P(PSTR("{\"" D_CMND_TUYA_MCU "\":[")); - bool added = false; - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].fnid != 0) { - if (added) { - ResponseAppend_P(PSTR(",")); - } - ResponseAppend_P(PSTR("{\"fnId\":%d,\"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid); - added = true; - } - } - ResponseAppend_P(PSTR("]}")); -} - - - - - -void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { - bool added = false; - - if (fnId == 0 || dpId == 0) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) { - Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; - Settings.tuya_fnid_map[i].dpid = 0; - break; - } - } - } else { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) { - if (!added) { - Settings.tuya_fnid_map[i].fnid = fnId; - Settings.tuya_fnid_map[i].dpid = dpId; - added = true; - } else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { - Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; - Settings.tuya_fnid_map[i].dpid = 0; - } - } - } - } - UpdateDevices(); -} - -void UpdateDevices() { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - uint8_t fnId = Settings.tuya_fnid_map[i].fnid; - if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) { - - if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1); - } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { - bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); - } - - } - } -} - -inline bool TuyaFuncIdValid(uint8_t fnId) { - return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) || - (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || - fnId == TUYA_MCU_FUNC_DIMMER || - (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) || - (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) || - (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE); -} - -uint8_t TuyaGetFuncId(uint8_t dpid) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].dpid == dpid) { - return Settings.tuya_fnid_map[i].fnid; - } - } - return TUYA_MCU_FUNC_NONE; -} - -uint8_t TuyaGetDpId(uint8_t fnId) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].fnid == fnId) { - return Settings.tuya_fnid_map[i].dpid; - } - } - return 0; -} - -void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0) -{ - uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF)); - TuyaSerial->write(0x55); - TuyaSerial->write(0xAA); - TuyaSerial->write((uint8_t)0x00); - TuyaSerial->write(cmd); - TuyaSerial->write(payload_len >> 8); - TuyaSerial->write(payload_len & 0xFF); - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); - for (uint32_t i = 0; i < payload_len; ++i) { - TuyaSerial->write(payload[i]); - checksum += payload[i]; - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, payload[i]); - } - TuyaSerial->write(checksum); - TuyaSerial->flush(); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x\""), log_data, checksum); - AddLog(LOG_LEVEL_DEBUG); -} - -void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value) -{ - uint16_t payload_len = 4; - uint8_t payload_buffer[8]; - payload_buffer[0] = id; - payload_buffer[1] = type; - switch (type) { - case TUYA_TYPE_BOOL: - case TUYA_TYPE_ENUM: - payload_len += 1; - payload_buffer[2] = 0x00; - payload_buffer[3] = 0x01; - payload_buffer[4] = value[0]; - break; - case TUYA_TYPE_VALUE: - payload_len += 4; - payload_buffer[2] = 0x00; - payload_buffer[3] = 0x04; - payload_buffer[4] = value[3]; - payload_buffer[5] = value[2]; - payload_buffer[6] = value[1]; - payload_buffer[7] = value[0]; - break; - - } - - TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); -} - -void TuyaSendBool(uint8_t id, bool value) -{ - TuyaSendState(id, TUYA_TYPE_BOOL, (uint8_t*)&value); -} - -void TuyaSendValue(uint8_t id, uint32_t value) -{ - TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); -} - -void TuyaSendEnum(uint8_t id, uint32_t value) -{ - TuyaSendState(id, TUYA_TYPE_ENUM, (uint8_t*)(&value)); -} - -void TuyaSendString(uint8_t id, char data[]) { - - uint16_t len = strlen(data); - uint16_t payload_len = 4 + len; - uint8_t payload_buffer[payload_len]; - payload_buffer[0] = id; - payload_buffer[1] = TUYA_TYPE_STRING; - payload_buffer[2] = len >> 8; - payload_buffer[3] = len & 0xFF; - - for (uint16_t i = 0; i < len; i++) { - payload_buffer[4+i] = data[i]; - } - - TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); -} - -bool TuyaSetPower(void) -{ - bool status = false; - - uint8_t rpower = XdrvMailbox.index; - int16_t source = XdrvMailbox.payload; - - uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + active_device - 1); - if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + active_device - 1); - - if (source != SRC_SWITCH && TuyaSerial) { - TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); - status = true; - } - return status; -} - -bool TuyaSetChannels(void) -{ - LightSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); - delay(20); - return true; -} - -void LightSerialDuty(uint16_t duty) -{ - uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); - if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { - duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); - if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } - if (Tuya.new_dim != duty) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); - TuyaSendValue(dpid, duty); - } - } else if (dpid > 0) { - Tuya.ignore_dim = false; - duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); - } -} - -void TuyaRequestState(void) -{ - if (TuyaSerial) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Read MCU state")); - - TuyaSendCmd(TUYA_CMD_QUERY_STATE); - } -} - -void TuyaResetWifi(void) -{ - if (!Settings.flag.button_restrict) { - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); - ExecuteCommand(scmnd, SRC_BUTTON); - } -} - -void TuyaProcessStatePacket(void) { - char scmnd[20]; - uint8_t dpidStart = 6; - uint8_t fnId; - uint16_t dpDataLen; - - while (dpidStart + 4 < Tuya.byte_counter) { - dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - fnId = TuyaGetFuncId(Tuya.buffer[dpidStart]); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[dpidStart]); - - if (Tuya.buffer[dpidStart + 1] == 1) { - - if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); - if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], SRC_SWITCH); - } - } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); - if (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4] ^ 1, SRC_SWITCH); - } - } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[dpidStart + 4], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); - - if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[dpidStart + 4]) { - SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[dpidStart + 4]); - SwitchHandler(1); - } - } - - } - else if (Tuya.buffer[dpidStart + 1] == 2) { - bool tuya_energy_enabled = (XNRG_16 == energy_flg); - uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; - if (fnId == TUYA_MCU_FUNC_DIMMER) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), packetValue); - Tuya.new_dim = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); - if ((power || Settings.flag3.tuya_apply_o20) && - (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { - Tuya.ignore_dim = true; - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - - #ifdef USE_ENERGY_SENSOR - else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { - Energy.voltage[0] = (float)packetValue / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], packetValue); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { - Energy.current[0] = (float)packetValue / 1000; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], packetValue); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { - Energy.active_power[0] = (float)packetValue / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], packetValue); - - if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { - Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; - EnergyUpdateToday(); - } - Tuya.lastPowerCheckTime = Rtc.utc_time; - } - #endif - - } - - - dpidStart += dpDataLen + 4; - } -} - -void TuyaLowPowerModePacketProcess(void) { - switch (Tuya.buffer[3]) { - case TUYA_CMD_QUERY_PRODUCT: - TuyaHandleProductInfoPacket(); - TuyaSetWifiLed(); - break; - - case TUYA_LOW_POWER_CMD_STATE: - TuyaProcessStatePacket(); - Tuya.send_success_next_second = true; - break; - } - -} - -void TuyaHandleProductInfoPacket(void) { - uint16_t dataLength = Tuya.buffer[4] << 8 | Tuya.buffer[5]; - char *data = &Tuya.buffer[6]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: MCU Product ID: %.*s"), dataLength, data); -} - -void TuyaSendLowPowerSuccessIfNeeded(void) { - uint8_t success = 1; - - if (Tuya.send_success_next_second) { - TuyaSendCmd(TUYA_LOW_POWER_CMD_STATE, &success, 1); - Tuya.send_success_next_second = false; - } -} - -void TuyaNormalPowerModePacketProcess(void) -{ - switch (Tuya.buffer[3]) { - case TUYA_CMD_QUERY_PRODUCT: - TuyaHandleProductInfoPacket(); - TuyaSendCmd(TUYA_CMD_MCU_CONF); - break; - - case TUYA_CMD_HEARTBEAT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); - if (Tuya.buffer[6] == 0) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Detected MCU restart")); - Tuya.wifi_state = -2; - } - break; - - case TUYA_CMD_STATE: - TuyaProcessStatePacket(); - break; - - case TUYA_CMD_WIFI_RESET: - case TUYA_CMD_WIFI_SELECT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi Reset")); - TuyaResetWifi(); - break; - - case TUYA_CMD_WIFI_STATE: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi LED set ACK")); - Tuya.wifi_state = TuyaGetTuyaWifiState(); - break; - - case TUYA_CMD_MCU_CONF: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]); - - if (Tuya.buffer[5] == 2) { - uint8_t led1_gpio = Tuya.buffer[6]; - uint8_t key1_gpio = Tuya.buffer[7]; - bool key1_set = false; - bool led1_set = false; - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (Settings.my_gp.io[i] == GPIO_LED1) led1_set = true; - else if (Settings.my_gp.io[i] == GPIO_KEY1) key1_set = true; - } - if (!Settings.my_gp.io[led1_gpio] && !led1_set) { - Settings.my_gp.io[led1_gpio] = GPIO_LED1; - restart_flag = 2; - } - if (!Settings.my_gp.io[key1_gpio] && !key1_set) { - Settings.my_gp.io[key1_gpio] = GPIO_KEY1; - restart_flag = 2; - } - } - TuyaRequestState(); - break; - - default: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); - } -} - - - - - -bool TuyaModuleSelected(void) -{ - if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { - pin[GPIO_TUYA_TX] = 1; - pin[GPIO_TUYA_RX] = 3; - Settings.my_gp.io[1] = GPIO_TUYA_TX; - Settings.my_gp.io[3] = GPIO_TUYA_RX; - restart_flag = 2; - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { - TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); - } - - bool relaySet = false; - - for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) { - if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || - (Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { - relaySet = true; - devices_present++; - } - } - - if (!relaySet) { - TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); - devices_present++; - SettingsSaveAll(); - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { - light_type = LT_SERIAL1; - } else { - light_type = LT_BASIC; - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { - Tuya.low_power_mode = true; - Settings.flag3.fast_power_cycle_disable = true; - } - - UpdateDevices(); - return true; -} - -void TuyaInit(void) -{ - Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); - if (Tuya.buffer != nullptr) { - TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); - if (TuyaSerial->begin(9600)) { - if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration")); - - TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); - } - } - Tuya.heartbeat_timer = 0; -} - -void TuyaSerialInput(void) -{ - while (TuyaSerial->available()) { - yield(); - uint8_t serial_in_byte = TuyaSerial->read(); - - if (serial_in_byte == 0x55) { - Tuya.cmd_status = 1; - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - Tuya.cmd_checksum += serial_in_byte; - } - else if (Tuya.cmd_status == 1 && serial_in_byte == 0xAA) { - Tuya.cmd_status = 2; - - Tuya.byte_counter = 0; - Tuya.buffer[Tuya.byte_counter++] = 0x55; - Tuya.buffer[Tuya.byte_counter++] = 0xAA; - Tuya.cmd_checksum = 0xFF; - } - else if (Tuya.cmd_status == 2) { - if (Tuya.byte_counter == 5) { - Tuya.cmd_status = 3; - Tuya.data_len = serial_in_byte; - } - Tuya.cmd_checksum += serial_in_byte; - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - } - else if ((Tuya.cmd_status == 3) && (Tuya.byte_counter == (6 + Tuya.data_len)) && (Tuya.cmd_checksum == serial_in_byte)) { - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - - char hex_char[(Tuya.byte_counter * 2) + 2]; - uint16_t len = Tuya.buffer[4] << 8 | Tuya.buffer[5]; - Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":{\"Data\":\"%s\",\"Cmnd\":%d"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char)), Tuya.buffer[3]); - - if (len > 0) { - ResponseAppend_P(PSTR(",\"CmndData\":\"%s\""), ToHex_P((unsigned char*)&Tuya.buffer[6], len, hex_char, sizeof(hex_char))); - if (TUYA_CMD_STATE == Tuya.buffer[3]) { - - - uint8_t dpidStart = 6; - while (dpidStart + 4 < Tuya.byte_counter) { - uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), Tuya.buffer[dpidStart], Tuya.buffer[dpidStart], Tuya.buffer[dpidStart + 1], ToHex_P((unsigned char*)&Tuya.buffer[dpidStart + 4], dpDataLen, hex_char, sizeof(hex_char))); - if (TUYA_TYPE_STRING == Tuya.buffer[dpidStart + 1]) { - ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, (char *)&Tuya.buffer[dpidStart + 4]); - } - ResponseAppend_P(PSTR("}")); - dpidStart += dpDataLen + 4; - } - } - } - - ResponseAppend_P(PSTR("}}")); - - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); - } else { - AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); - } - XdrvRulesProcess(); - - if (!Tuya.low_power_mode) { - TuyaNormalPowerModePacketProcess(); - } else { - TuyaLowPowerModePacketProcess(); - } - - Tuya.byte_counter = 0; - Tuya.cmd_status = 0; - Tuya.cmd_checksum = 0; - Tuya.data_len = 0; - } - else if (Tuya.byte_counter < TUYA_BUFFER_SIZE -1) { - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - Tuya.cmd_checksum += serial_in_byte; - } else { - Tuya.byte_counter = 0; - Tuya.cmd_status = 0; - Tuya.cmd_checksum = 0; - Tuya.data_len = 0; - } - } -} - -bool TuyaButtonPressed(void) -{ - if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == Button.last_state[XdrvMailbox.index]))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered")); - TuyaResetWifi(); - return true; - } - return false; -} - -uint8_t TuyaGetTuyaWifiState(void) { - - uint8_t wifi_state = 0x02; - switch(WifiState()){ - case WIFI_MANAGER: - wifi_state = 0x01; - break; - case WIFI_RESTART: - wifi_state = 0x03; - break; - } - - if (MqttIsConnected()) { - wifi_state = 0x04; - } - - return wifi_state; -} - -void TuyaSetWifiLed(void) -{ - Tuya.wifi_state = TuyaGetTuyaWifiState(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), Tuya.wifi_state, WifiState()); - - if (Tuya.low_power_mode) { - TuyaSendCmd(TUYA_LOW_POWER_CMD_WIFI_STATE, &Tuya.wifi_state, 1); - } else { - TuyaSendCmd(TUYA_CMD_WIFI_STATE, &Tuya.wifi_state, 1); - } -} - -#ifdef USE_ENERGY_SENSOR - - - - -bool Xnrg16(uint8_t function) -{ - bool result = false; - - if (TUYA_DIMMER == my_module_type) { - if (FUNC_PRE_INIT == function) { - if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) { - Energy.current_available = false; - } - if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) { - Energy.voltage_available = false; - } - energy_flg = XNRG_16; - } - } - } - return result; -} -#endif - - - - - -bool Xdrv16(uint8_t function) -{ - bool result = false; - - if (TUYA_DIMMER == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (TuyaSerial) { TuyaSerialInput(); } - break; - case FUNC_MODULE_INIT: - result = TuyaModuleSelected(); - break; - case FUNC_PRE_INIT: - TuyaInit(); - break; - case FUNC_SET_DEVICE_POWER: - result = TuyaSetPower(); - break; - case FUNC_BUTTON_PRESSED: - result = TuyaButtonPressed(); - break; - case FUNC_EVERY_SECOND: - if (TuyaSerial && Tuya.wifi_state != TuyaGetTuyaWifiState()) { TuyaSetWifiLed(); } - if (!Tuya.low_power_mode) { - Tuya.heartbeat_timer++; - if (Tuya.heartbeat_timer > 10) { - Tuya.heartbeat_timer = 0; - TuyaSendCmd(TUYA_CMD_HEARTBEAT); - } - } else { - TuyaSendLowPowerSuccessIfNeeded(); - } - break; - case FUNC_SET_CHANNELS: - result = TuyaSetChannels(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kTuyaCommand, TuyaCommand); - break; - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_17_rcswitch.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_17_rcswitch.ino" -#ifdef USE_RC_SWITCH - - - - -#define XDRV_17 17 - -#define D_JSON_RF_PROTOCOL "Protocol" -#define D_JSON_RF_BITS "Bits" -#define D_JSON_RF_DATA "Data" - -#define D_CMND_RFSEND "RFSend" -#define D_JSON_RF_PULSE "Pulse" -#define D_JSON_RF_REPEAT "Repeat" - -const char kRfSendCommands[] PROGMEM = "|" - D_CMND_RFSEND; - -void (* const RfSendCommand[])(void) PROGMEM = { - &CmndRfSend }; - -#include - -RCSwitch mySwitch = RCSwitch(); - -#define RF_TIME_AVOID_DUPLICATE 1000 - -uint32_t rf_lasttime = 0; - -void RfReceiveCheck(void) -{ - if (mySwitch.available()) { - - unsigned long data = mySwitch.getReceivedValue(); - unsigned int bits = mySwitch.getReceivedBitlength(); - int protocol = mySwitch.getReceivedProtocol(); - int delay = mySwitch.getReceivedDelay(); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data 0x%lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); - - uint32_t now = millis(); - if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) { - rf_lasttime = now; - - char stemp[16]; - if (Settings.flag.rf_receive_decimal) { - snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); - } - ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), - stemp, bits, protocol, delay); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); - XdrvRulesProcess(); -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_COUNT, data); -#endif - } - mySwitch.resetAvailable(); - } -} - -void RfInit(void) -{ - if (pin[GPIO_RFSEND] < 99) { - mySwitch.enableTransmit(pin[GPIO_RFSEND]); - } - if (pin[GPIO_RFRECV] < 99) { - pinMode( pin[GPIO_RFRECV], INPUT); - mySwitch.enableReceive(pin[GPIO_RFRECV]); - } -} - - - - - -void CmndRfSend(void) -{ - bool error = false; - - if (XdrvMailbox.data_len) { - unsigned long data = 0; - unsigned int bits = 24; - int protocol = 1; - int repeat = 10; - int pulse = 350; - - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - StaticJsonBuffer<150> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); - if (root.success()) { - - char parm_uc[10]; - data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], nullptr, 0); - bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; - protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; - repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; - pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))]; - } else { - - char *p; - uint8_t i = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(nullptr, ", ", &p)) { - switch (i++) { - case 0: - data = strtoul(str, nullptr, 0); - break; - case 1: - bits = atoi(str); - break; - case 2: - protocol = atoi(str); - break; - case 3: - repeat = atoi(str); - break; - case 4: - pulse = atoi(str); - } - } - } - - if (!protocol) { protocol = 1; } - mySwitch.setProtocol(protocol); - if (!pulse) { pulse = 350; } - mySwitch.setPulseLength(pulse); - if (!repeat) { repeat = 10; } - mySwitch.setRepeatTransmit(repeat); - if (!bits) { bits = 24; } - if (data) { - mySwitch.send(data, bits); - ResponseCmndDone(); - } else { - error = true; - } - } else { - error = true; - } - if (error) { - Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); - } -} - - - - - -bool Xdrv17(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (pin[GPIO_RFRECV] < 99) { - RfReceiveCheck(); - } - break; - case FUNC_COMMAND: - if (pin[GPIO_RFSEND] < 99) { - result = DecodeCommand(kRfSendCommands, RfSendCommand); - } - break; - case FUNC_INIT: - RfInit(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" -#ifdef USE_LIGHT -#ifdef USE_ARMTRONIX_DIMMERS - - - - - - - -#define XDRV_18 18 - -#include - -TasmotaSerial *ArmtronixSerial = nullptr; - -struct ARMTRONIX { - bool ignore_dim = false; - int8_t wifi_state = -2; - int8_t dim_state[2]; - int8_t knob_state[2]; -} Armtronix; - - - - - -bool ArmtronixSetChannels(void) -{ - LightSerial2Duty(((uint8_t*)XdrvMailbox.data)[0], ((uint8_t*)XdrvMailbox.data)[1]); - return true; -} - -void LightSerial2Duty(uint8_t duty1, uint8_t duty2) -{ - if (ArmtronixSerial && !Armtronix.ignore_dim) { - duty1 = ((float)duty1)/2.575757; - duty2 = ((float)duty2)/2.575757; - Armtronix.dim_state[0] = duty1; - Armtronix.dim_state[1] = duty2; - ArmtronixSerial->print("Dimmer1:"); - ArmtronixSerial->print(duty1); - ArmtronixSerial->print("\nDimmer2:"); - ArmtronixSerial->println(duty2); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Serial Packet Dim Values=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); - - } else { - Armtronix.ignore_dim = false; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Dim Level skipped due to already set. Value=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); - - } -} - -void ArmtronixRequestState(void) -{ - if (ArmtronixSerial) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("ARM: Request MCU state")); - ArmtronixSerial->println("Status"); - - } -} - - - - - -bool ArmtronixModuleSelected(void) -{ - devices_present++; - light_type = LT_SERIAL2; - return true; -} - -void ArmtronixInit(void) -{ - Armtronix.dim_state[0] = -1; - Armtronix.dim_state[1] = -1; - Armtronix.knob_state[0] = -1; - Armtronix.knob_state[1] = -1; - ArmtronixSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (ArmtronixSerial->begin(115200)) { - if (ArmtronixSerial->hardwareSerial()) { ClaimSerial(); } - ArmtronixSerial->println("Status"); - } -} - -void ArmtronixSerialInput(void) -{ - String answer; - int8_t newDimState[2]; - uint8_t temp; - int commaIndex; - char scmnd[20]; - if (ArmtronixSerial->available()) { - yield(); - answer = ArmtronixSerial->readStringUntil('\n'); - if (answer.substring(0,7) == "Status:") { - commaIndex = 6; - for (uint32_t i =0; i<2; i++) { - newDimState[i] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - if (newDimState[i] != Armtronix.dim_state[i]) { - temp = ((float)newDimState[i])*1.01010101010101; - Armtronix.dim_state[i] = newDimState[i]; - Armtronix.ignore_dim = true; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "%d %d"),i+1, temp); - ExecuteCommand(scmnd,SRC_SWITCH); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); - } - commaIndex = answer.indexOf(',',commaIndex+1); - } - Armtronix.knob_state[0] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - commaIndex = answer.indexOf(',',commaIndex+1); - Armtronix.knob_state[1] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - } - } -} - -void ArmtronixSetWifiLed(void) -{ - uint8_t wifi_state = 0x02; - - switch (WifiState()) { - case WIFI_MANAGER: - wifi_state = 0x01; - break; - case WIFI_RESTART: - wifi_state = 0x03; - break; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Set WiFi LED to state %d (%d)"), wifi_state, WifiState()); - - char state = '0' + ((wifi_state & 1) > 0); - ArmtronixSerial->print("Setled:"); - ArmtronixSerial->write(state); - ArmtronixSerial->write(','); - state = '0' + ((wifi_state & 2) > 0); - ArmtronixSerial->write(state); - ArmtronixSerial->write(10); - Armtronix.wifi_state = WifiState(); -} - - - - - -bool Xdrv18(uint8_t function) -{ - bool result = false; - - if (ARMTRONIX_DIMMERS == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (ArmtronixSerial) { ArmtronixSerialInput(); } - break; - case FUNC_MODULE_INIT: - result = ArmtronixModuleSelected(); - break; - case FUNC_INIT: - ArmtronixInit(); - break; - case FUNC_EVERY_SECOND: - if (ArmtronixSerial) { - if (Armtronix.wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } - if (uptime &1) { - ArmtronixSerial->println("Status"); - } - } - break; - case FUNC_SET_CHANNELS: - result = ArmtronixSetChannels(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" -#ifdef USE_LIGHT -#ifdef USE_PS_16_DZ - - - - -#define XDRV_19 19 - -#define PS16DZ_BUFFER_SIZE 80 - -#include - -TasmotaSerial *PS16DZSerial = nullptr; - -struct PS16DZ { - char *rx_buffer = nullptr; - int byte_counter = 0; - uint8_t dimmer = 0; -} Ps16dz; - - - - - -void PS16DZSerialSend(const char *tx_buffer) -{ - - - PS16DZSerial->print(tx_buffer); - PS16DZSerial->write(0x1B); - PS16DZSerial->flush(); -} - -void PS16DZSerialSendOk(void) -{ - char tx_buffer[16]; - snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+SEND=ok")); - PS16DZSerialSend(tx_buffer); -} - - - - -void PS16DZSerialSendUpdateCommand(void) -{ - uint8_t light_state_dimmer = light_state.getDimmer(); - - light_state_dimmer = (light_state_dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : light_state_dimmer; - light_state_dimmer = (light_state_dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : light_state_dimmer; - - char tx_buffer[80]; - snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), - LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); - - PS16DZSerialSend(tx_buffer); -} - - - - - -void PS16DZSerialInput(void) -{ - char scmnd[20]; - while (PS16DZSerial->available()) { - yield(); - uint8_t serial_in_byte = PS16DZSerial->read(); - if (serial_in_byte != 0x1B) { - if (Ps16dz.byte_counter >= PS16DZ_BUFFER_SIZE - 1) { - memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); - Ps16dz.byte_counter = 0; - } - if (Ps16dz.byte_counter || (!Ps16dz.byte_counter && ('A' == serial_in_byte))) { - Ps16dz.rx_buffer[Ps16dz.byte_counter++] = serial_in_byte; - } - } else { - Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; - - - - - if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { - - } - else if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { - - char *end_str; - char *string = Ps16dz.rx_buffer+10; - char *token = strtok_r(string, ",", &end_str); - - bool is_switch_change = false; - bool is_brightness_change = false; - - while (token != nullptr) { - char* end_token; - char* token2 = strtok_r(token, ":", &end_token); - char* token3 = strtok_r(nullptr, ":", &end_token); - - if (!strncmp(token2, "\"switch\"", 8)) { - bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - - - - is_switch_change = (switch_state != power); - if (is_switch_change) { - ExecuteCommandPower(1, switch_state, SRC_SWITCH); - } - } - else if (!strncmp(token2, "\"bright\"", 8)) { - Ps16dz.dimmer = atoi(token3); - - - - is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer; - if (power && (Ps16dz.dimmer > 0) && is_brightness_change) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Ps16dz.dimmer); - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - else if (!strncmp(token2, "\"sequence\"", 10)) { - - - - } - token = strtok_r(nullptr, ",", &end_str); - } - - if (!is_brightness_change) { - - - - PS16DZSerialSendOk(); - } - } - else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) { - - - if (!Settings.flag.button_restrict) { - int state = WIFI_MANAGER; - if (!strncmp(Ps16dz.rx_buffer+10, "=exit", 5)) { state = WIFI_RETRY; } - if (state != Settings.sta_config) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " %d"), state); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } - memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); - Ps16dz.byte_counter = 0; - } - } -} - -bool PS16DZSerialSendUpdateCommandIfRequired(void) -{ - if (!PS16DZSerial) { return true; } - - bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); - bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); - - if (is_switch_change || is_brightness_change) { - PS16DZSerialSendUpdateCommand(); - } - - return true; -} - -void PS16DZInit(void) -{ - Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (Ps16dz.rx_buffer != nullptr) { - PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (PS16DZSerial->begin(19200)) { - if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } - } - } -} - -bool PS16DZModuleSelected(void) -{ - devices_present++; - light_type = LT_SERIAL1; - - return true; -} - - - - - -bool Xdrv19(uint8_t function) -{ - bool result = false; - - if (PS_16_DZ == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (PS16DZSerial) { PS16DZSerialInput(); } - break; - case FUNC_SET_DEVICE_POWER: - case FUNC_SET_CHANNELS: - result = PS16DZSerialSendUpdateCommandIfRequired(); - break; - case FUNC_INIT: - PS16DZInit(); - break; - case FUNC_MODULE_INIT: - result = PS16DZModuleSelected(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_20_hue.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_20_hue.ino" -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_20_hue.ino" -#define XDRV_20 20 - -const char HUE_RESPONSE[] PROGMEM = - "HTTP/1.1 200 OK\r\n" - "HOST: 239.255.255.250:1900\r\n" - "CACHE-CONTROL: max-age=100\r\n" - "EXT:\r\n" - "LOCATION: http://%s:80/description.xml\r\n" - "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.24.0\r\n" - "hue-bridgeid: %s\r\n"; -const char HUE_ST1[] PROGMEM = - "ST: upnp:rootdevice\r\n" - "USN: uuid:%s::upnp:rootdevice\r\n" - "\r\n"; -const char HUE_ST2[] PROGMEM = - "ST: uuid:%s\r\n" - "USN: uuid:%s\r\n" - "\r\n"; -const char HUE_ST3[] PROGMEM = - "ST: urn:schemas-upnp-org:device:basic:1\r\n" - "USN: uuid:%s\r\n" - "\r\n"; - -String HueBridgeId(void) -{ - String temp = WiFi.macAddress(); - temp.replace(":", ""); - String bridgeid = temp.substring(0, 6) + "FFFE" + temp.substring(6); - return bridgeid; -} - -String HueSerialnumber(void) -{ - String serial = WiFi.macAddress(); - serial.replace(":", ""); - serial.toLowerCase(); - return serial; -} - -String HueUuid(void) -{ - String uuid = F("f6543a06-da50-11ba-8d8f-"); - uuid += HueSerialnumber(); - return uuid; -} - -void HueRespondToMSearch(void) -{ - char message[TOPSZ]; - - TickerMSearch.detach(); - if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - char response[320]; - snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); - int len = strlen(response); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST1, HueUuid().c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST2, HueUuid().c_str(), HueUuid().c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST3, HueUuid().c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(message, sizeof(message), PSTR(D_3_RESPONSE_PACKETS_SENT)); - } else { - snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); - } - - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), - message, udp_remote_ip.toString().c_str(), udp_remote_port); - - udp_response_mutex = false; -} - - - - - -const char HUE_DESCRIPTION_XML[] PROGMEM = - "" - "" - "" - "1" - "0" - "" - - "http://{x1:80/" - "" - "urn:schemas-upnp-org:device:Basic:1" - "Amazon-Echo-HA-Bridge ({x1)" - - "Royal Philips Electronics" - "http://www.philips.com" - "Philips hue Personal Wireless Lighting" - "Philips hue bridge 2012" - "929000226503" - "{x3" - "uuid:{x2" - "" - "\r\n" - "\r\n"; -const char HUE_LIGHTS_STATUS_JSON1[] PROGMEM = - "{\"on\":{state}," - "{light_status}" - "\"alert\":\"none\"," - "\"effect\":\"none\"," - "\"reachable\":true}"; -const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = - ",\"type\":\"Extended color light\"," - "\"name\":\"{j1\"," - "\"modelid\":\"LCT007\"," - "\"uniqueid\":\"{j2\"," - "\"swversion\":\"5.50.1.19085\"}"; -const char HUE_GROUP0_STATUS_JSON[] PROGMEM = - "{\"name\":\"Group 0\"," - "\"lights\":[{l1]," - "\"type\":\"LightGroup\"," - "\"action\":"; - -const char HueConfigResponse_JSON[] PROGMEM = - "{\"name\":\"Philips hue\"," - "\"mac\":\"{ma\"," - "\"dhcp\":true," - "\"ipaddress\":\"{ip\"," - "\"netmask\":\"{ms\"," - "\"gateway\":\"{gw\"," - "\"proxyaddress\":\"none\"," - "\"proxyport\":0," - "\"bridgeid\":\"{br\"," - "\"UTC\":\"{dt\"," - "\"whitelist\":{\"{id\":{" - "\"last use date\":\"{dt\"," - "\"create date\":\"{dt\"," - "\"name\":\"Remote\"}}," - "\"swversion\":\"01041302\"," - "\"apiversion\":\"1.17.0\"," - "\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false}," - "\"linkbutton\":false," - "\"portalservices\":false" - "}"; -const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM = - "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; -const char HUE_ERROR_JSON[] PROGMEM = - "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; - - - -String GetHueDeviceId(uint8_t id) -{ - String deviceid = WiFi.macAddress() + F(":00:11-") + String(id); - deviceid.toLowerCase(); - return deviceid; -} - -String GetHueUserId(void) -{ - char userid[7]; - - snprintf_P(userid, sizeof(userid), PSTR("%03x"), ESP.getChipId()); - return String(userid); -} - -void HandleUpnpSetupHue(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_HUE_BRIDGE_SETUP)); - String description_xml = FPSTR(HUE_DESCRIPTION_XML); - description_xml.replace("{x1", WiFi.localIP().toString()); - description_xml.replace("{x2", HueUuid()); - description_xml.replace("{x3", HueSerialnumber()); - WSSend(200, CT_XML, description_xml); -} - -void HueNotImplemented(String *path) -{ - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); - - WSSend(200, CT_JSON, "{}"); -} - -void HueConfigResponse(String *response) -{ - *response += FPSTR(HueConfigResponse_JSON); - response->replace("{ma", WiFi.macAddress()); - response->replace("{ip", WiFi.localIP().toString()); - response->replace("{ms", WiFi.subnetMask().toString()); - response->replace("{gw", WiFi.gatewayIP().toString()); - response->replace("{br", HueBridgeId()); - response->replace("{dt", GetDateAndTime(DT_UTC)); - response->replace("{id", GetHueUserId()); -} - -void HueConfig(String *path) -{ - String response = ""; - HueConfigResponse(&response); - WSSend(200, CT_JSON, response); -} - - - -bool g_gotct = false; - - - - -uint16_t prev_hue = 0; -uint8_t prev_sat = 0; -uint8_t prev_bri = 254; -uint16_t prev_ct = 254; -char prev_x_str[24] = "\0"; -char prev_y_str[24] = "\0"; - -uint8_t getLocalLightSubtype(uint8_t device) { - if (light_type) { - if (device >= Light.device) { - if (Settings.flag3.pwm_multi_channels) { - return LST_SINGLE; - } else { - return Light.subtype; - } - } else { - return LST_NONE; - } - } else { - return LST_NONE; - } -} - -void HueLightStatus1(uint8_t device, String *response) -{ - uint16_t ct = 0; - uint8_t color_mode; - String light_status = ""; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint32_t echo_gen = findEchoGeneration(); - - - uint8_t local_light_subtype = getLocalLightSubtype(device); - - bri = LightGetBri(device); - if (bri > 254) bri = 254; - if (bri < 1) bri = 1; - -#ifdef USE_SHUTTER - if (ShutterState(device)) { - bri = (float)((Settings.shutter_options[device-1] & 1) ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; - } -#endif - - if (light_type) { - light_state.getHSB(&hue, &sat, nullptr); - - if ((bri > prev_bri ? bri - prev_bri : prev_bri - bri) < 1) - bri = prev_bri; - - if (sat > 254) sat = 254; - if ((sat > prev_sat ? sat - prev_sat : prev_sat - sat) < 1) { - sat = prev_sat; - } else { - prev_x_str[0] = prev_y_str[0] = 0; - } - - hue = changeUIntScale(hue, 0, 359, 0, 65535); - if ((hue > prev_hue ? hue - prev_hue : prev_hue - hue) < 400) { - hue = prev_hue; - } else { - prev_x_str[0] = prev_y_str[0] = 0; - } - - color_mode = light_state.getColorMode(); - ct = light_state.getCT(); - if (LCM_RGB == color_mode) { g_gotct = false; } - if (LCM_CT == color_mode) { g_gotct = true; } - - - - if ((ct > prev_ct ? ct - prev_ct : prev_ct - ct) < 1) - ct = prev_ct; - - - - } - - *response += FPSTR(HUE_LIGHTS_STATUS_JSON1); - response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); - - if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { - light_status += "\"bri\":"; - light_status += String(bri); - light_status += ","; - } - if (LST_COLDWARM <= local_light_subtype) { - light_status += F("\"colormode\":\""); - light_status += (g_gotct ? "ct" : "hs"); - light_status += "\","; - } - if (LST_RGB <= local_light_subtype) { - if (prev_x_str[0] && prev_y_str[0]) { - light_status += "\"xy\":["; - light_status += prev_x_str; - light_status += ","; - light_status += prev_y_str; - light_status += "],"; - } else { - float x, y; - light_state.getXY(&x, &y); - light_status += "\"xy\":["; - light_status += String(x, 5); - light_status += ","; - light_status += String(y, 5); - light_status += "],"; - } - light_status += "\"hue\":"; - light_status += String(hue); - light_status += ","; - - light_status += "\"sat\":"; - light_status += String(sat); - light_status += ","; - } - if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { - light_status += "\"ct\":"; - light_status += String(ct > 0 ? ct : 284); - light_status += ","; - } - response->replace("{light_status}", light_status); -} - - - -bool HueActive(uint8_t device) { - if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } - return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1); -} - -void HueLightStatus2(uint8_t device, String *response) -{ - *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); - if (device <= MAX_FRIENDLYNAMES) { - response->replace("{j1", SettingsText(SET_FRIENDLYNAME1 +device -1)); - } else { - char fname[33]; - strcpy(fname, SettingsText(SET_FRIENDLYNAME1 + MAX_FRIENDLYNAMES -1)); - uint32_t fname_len = strlen(fname); - if (fname_len > 30) { fname_len = 30; } - fname[fname_len++] = '-'; - if (device - MAX_FRIENDLYNAMES < 10) { - fname[fname_len++] = '0' + device - MAX_FRIENDLYNAMES; - } else { - fname[fname_len++] = 'A' + device - MAX_FRIENDLYNAMES - 10; - } - fname[fname_len] = 0x00; - - response->replace("{j1", fname); - } - response->replace("{j2", GetHueDeviceId(device)); -} - - - - -uint32_t EncodeLightId(uint8_t relay_id) -{ - uint8_t mac[6]; - WiFi.macAddress(mac); - uint32_t id = 0; - - if (relay_id >= 32) { - relay_id = 0; - } - if (relay_id > 15) { - id = (1 << 28); - } - - id |= (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (relay_id & 0xF); - return id; -} - - - -uint32_t DecodeLightId(uint32_t hue_id) { - uint8_t relay_id = hue_id & 0xF; - if (hue_id & (1 << 28)) { - relay_id += 16; - } - if (0 == relay_id) { - relay_id = 32; - } - return relay_id; -} - -static const char * FIRST_GEN_UA[] = { - "AEOBC", -}; - - -uint32_t findEchoGeneration(void) { - - String user_agent = WebServer->header("User-Agent"); - uint32_t gen = 2; - - for (uint32_t i = 0; i < sizeof(FIRST_GEN_UA)/sizeof(char*); i++) { - if (user_agent.indexOf(FIRST_GEN_UA[i]) >= 0) { - gen = 1; - break; - } - } - if (0 == user_agent.length()) { - gen = 1; - } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, D_LOG_HTTP D_HUE " User-Agent: %s, gen=%d", user_agent.c_str(), gen); - - return gen; -} - -void HueGlobalConfig(String *path) { - String response; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - path->remove(0,1); - response = F("{\"lights\":{"); - bool appending = false; - for (uint32_t i = 1; i <= maxhue; i++) { - if (HueActive(i)) { - if (appending) { response += ","; } - response += "\""; - response += EncodeLightId(i); - response += F("\":{\"state\":"); - HueLightStatus1(i, &response); - HueLightStatus2(i, &response); - appending = true; - } - } - response += F("},\"groups\":{},\"schedules\":{},\"config\":"); - HueConfigResponse(&response); - response += "}"; - WSSend(200, CT_JSON, response); -} - -void HueAuthentication(String *path) -{ - char response[38]; - - snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); - WSSend(200, CT_JSON, response); -} - -void HueLights(String *path) -{ - - - - String response; - int code = 200; - uint16_t tmp = 0; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint16_t ct = 0; - bool resp = false; - bool on = false; - bool change = false; - uint8_t device = 1; - uint8_t local_light_subtype = Light.subtype; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - path->remove(0,path->indexOf("/lights")); - if (path->endsWith("/lights")) { - response = "{"; - bool appending = false; - for (uint32_t i = 1; i <= maxhue; i++) { - if (HueActive(i)) { - if (appending) { response += ","; } - response += "\""; - response += EncodeLightId(i); - response += F("\":{\"state\":"); - HueLightStatus1(i, &response); - HueLightStatus2(i, &response); - appending = true; - } - } -#ifdef USE_SCRIPT_HUE - Script_Check_Hue(&response); -#endif - response += "}"; - } - else if (path->endsWith("/state")) { - path->remove(0,8); - path->remove(path->indexOf("/state")); - device = DecodeLightId(atoi(path->c_str())); - -#ifdef USE_SCRIPT_HUE - if (device>devices_present) { - return Script_Handle_Hue(path); - } -#endif - - if ((device < 1) || (device > maxhue)) { - device = 1; - } - local_light_subtype = getLocalLightSubtype(device); - - if (WebServer->args()) { - response = "["; - - StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); - if (hue_json.containsKey("on")) { - - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "on"); - -#ifdef USE_SHUTTER - if (ShutterState(device)) { - if (!change) { - on = hue_json["on"]; - bri = on ? 1.0f : 0.0f; - change = true; - } - response.replace("{re", on ? "true" : "false"); - } else { -#endif - on = hue_json["on"]; - switch(on) - { - case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); - response.replace("{re", "false"); - break; - case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); - response.replace("{re", "true"); - break; - default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); - break; - } - resp = true; -#ifdef USE_SHUTTER - } -#endif - } - - if (light_type && (local_light_subtype >= LST_SINGLE)) { - if (!Settings.flag3.pwm_multi_channels) { - light_state.getHSB(&hue, &sat, nullptr); - bri = light_state.getBri(); - ct = light_state.getCT(); - uint8_t color_mode = light_state.getColorMode(); - if (LCM_RGB == color_mode) { g_gotct = false; } - if (LCM_CT == color_mode) { g_gotct = true; } - - } else { - bri = LightGetBri(device); - } - } - prev_x_str[0] = prev_y_str[0] = 0; - - if (hue_json.containsKey("bri")) { - tmp = hue_json["bri"]; - prev_bri = bri = tmp; - - if (254 <= bri) { bri = 255; } - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "bri"); - response.replace("{re", String(tmp)); - if (LST_SINGLE <= Light.subtype) { - change = true; - } - resp = true; - } - - - if (hue_json.containsKey("xy")) { - float x, y; - x = hue_json["xy"][0]; - y = hue_json["xy"][1]; - const String &x_str = hue_json["xy"][0]; - const String &y_str = hue_json["xy"][1]; - x_str.toCharArray(prev_x_str, sizeof(prev_x_str)); - y_str.toCharArray(prev_y_str, sizeof(prev_y_str)); - - uint8_t rr,gg,bb; - LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); - LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); - prev_hue = changeUIntScale(hue, 0, 359, 0, 65535); - prev_sat = (sat > 254 ? 254 : sat); - - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "xy"); - response.replace("{re", "[" + x_str + "," + y_str + "]"); - g_gotct = false; - resp = true; - change = true; - } - if (hue_json.containsKey("hue")) { - tmp = hue_json["hue"]; - prev_hue = tmp; - - hue = changeUIntScale(tmp, 0, 65535, 0, 359); - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "hue"); - response.replace("{re", String(tmp)); - if (LST_RGB <= Light.subtype) { - g_gotct = false; - change = true; - } - resp = true; - } - if (hue_json.containsKey("sat")) { - tmp = hue_json["sat"]; - prev_sat = sat = tmp; - - if (254 <= sat) { sat = 255; } - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "sat"); - response.replace("{re", String(tmp)); - if (LST_RGB <= Light.subtype) { - g_gotct = false; - change = true; - } - resp = true; - } - if (hue_json.containsKey("ct")) { - ct = hue_json["ct"]; - prev_ct = ct; - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "ct"); - response.replace("{re", String(ct)); - if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { - g_gotct = true; - change = true; - } - resp = true; - } - if (change) { -#ifdef USE_SHUTTER - if (ShutterState(device)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_options[device-1] & 1); - ShutterSetPosition(device, bri * 100.0f ); - } else -#endif - if (light_type && (local_light_subtype > LST_NONE)) { - if (!Settings.flag3.pwm_multi_channels) { - if (g_gotct) { - light_controller.changeCTB(ct, bri); - } else { - light_controller.changeHSB(hue, sat, bri); - } - LightPreparePower(); - } else { - LightSetBri(device, bri); - } - if (LST_COLDWARM <= local_light_subtype) { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); - } else { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_DIMMER)); - } - XdrvRulesProcess(); - } - change = false; - } - response += "]"; - if (2 == response.length()) { - response = FPSTR(HUE_ERROR_JSON); - } - } - else { - response = FPSTR(HUE_ERROR_JSON); - } - } - else if(path->indexOf("/lights/") >= 0) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "/lights path=%s", path->c_str()); - path->remove(0,8); - device = DecodeLightId(atoi(path->c_str())); - -#ifdef USE_SCRIPT_HUE - if (device>devices_present) { - Script_HueStatus(&response,device-devices_present-1); - goto exit; -} -#endif - - if ((device < 1) || (device > maxhue)) { - device = 1; - } - response += F("{\"state\":"); - HueLightStatus1(device, &response); - HueLightStatus2(device, &response); - } - else { - response = "{}"; - code = 406; - } - exit: - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); - WSSend(code, CT_JSON, response); -} - -void HueGroups(String *path) -{ - - - - String response = "{}"; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - if (path->endsWith("/0")) { - response = FPSTR(HUE_GROUP0_STATUS_JSON); - String lights = F("\"1\""); - for (uint32_t i = 2; i <= maxhue; i++) { - lights += ",\""; - lights += EncodeLightId(i); - lights += "\""; - } - response.replace("{l1", lights); - HueLightStatus1(1, &response); - response += F("}"); - } - - WSSend(200, CT_JSON, response); -} - -void HandleHueApi(String *path) -{ -# 784 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_20_hue.ino" - uint8_t args = 0; - - path->remove(0, 4); - uint16_t apilen = path->length(); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); - for (args = 0; args < WebServer->args(); args++) { - String json = WebServer->arg(args); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); - } - - if (path->endsWith("/invalid/")) {} - else if (!apilen) HueAuthentication(path); - else if (path->endsWith("/")) HueAuthentication(path); - else if (path->endsWith("/config")) HueConfig(path); - else if (path->indexOf("/lights") >= 0) HueLights(path); - else if (path->indexOf("/groups") >= 0) HueGroups(path); - else if (path->endsWith("/schedules")) HueNotImplemented(path); - else if (path->endsWith("/sensors")) HueNotImplemented(path); - else if (path->endsWith("/scenes")) HueNotImplemented(path); - else if (path->endsWith("/rules")) HueNotImplemented(path); - else if (path->endsWith("/resourcelinks")) HueNotImplemented(path); - else HueGlobalConfig(path); -} - - - - - -bool Xdrv20(uint8_t function) -{ - bool result = false; - -#ifdef USE_SCRIPT_HUE - if ((EMUL_HUE == Settings.flag2.emulation)) { -#else - if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) { -#endif - switch (function) { - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/description.xml", HandleUpnpSetupHue); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_21_wemo.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_21_wemo.ino" -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined (USE_EMULATION_WEMO) - - - - -#define XDRV_21 21 - -const char WEMO_MSEARCH[] PROGMEM = - "HTTP/1.1 200 OK\r\n" - "CACHE-CONTROL: max-age=86400\r\n" - "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" - "EXT:\r\n" - "LOCATION: http://%s:80/setup.xml\r\n" - "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" - "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n" - "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n" - "ST: %s\r\n" - "USN: uuid:%s::%s\r\n" - "X-User-Agent: redsonic\r\n" - "\r\n"; - -String WemoSerialnumber(void) -{ - char serial[16]; - - snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId()); - return String(serial); -} - -String WemoUuid(void) -{ - char uuid[27]; - - snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str()); - return String(uuid); -} - -void WemoRespondToMSearch(int echo_type) -{ - char message[TOPSZ]; - - TickerMSearch.detach(); - if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - char type[24]; - if (1 == echo_type) { - strcpy_P(type, URN_BELKIN_DEVICE_CAP); - } else { - strcpy_P(type, UPNP_ROOTDEVICE); - } - char response[400]; - snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); - PortUdp.write(response); - PortUdp.endPacket(); - snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); - } else { - snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); - } - - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), - echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); - - udp_response_mutex = false; -} - - - - - -const char WEMO_EVENTSERVICE_XML[] PROGMEM = - "" - "" - "" - "SetBinaryState" - "" - "" - "" - "BinaryState" - "BinaryState" - "in" - "" - "" - "" - "" - "GetBinaryState" - "" - "" - "" - "BinaryState" - "BinaryState" - "out" - "" - "" - "" - "" - "" - "" - "BinaryState" - "bool" - "0" - "" - "" - "level" - "string" - "0" - "" - "" - "\r\n\r\n"; - -const char WEMO_METASERVICE_XML[] PROGMEM = - "" - "" - "1" - "0" - "" - "" - "" - "GetMetaInfo" - "" - "" - "GetMetaInfo" - "MetaInfo" - "in" - "" - "" - "" - "" - "" - "MetaInfo" - "string" - "0" - "" - "" - "\r\n\r\n"; - -const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = - "" - "" - "" - "%d" - "" - "" - "\r\n"; - -const char WEMO_SETUP_XML[] PROGMEM = - "" - "" - "" - "urn:Belkin:device:controllee:1" - "{x1" - "Belkin International Inc." - "Socket" - "3.1415" - "uuid:{x2" - "{x3" - "0" - "" - "" - "urn:Belkin:service:basicevent:1" - "urn:Belkin:serviceId:basicevent1" - "/upnp/control/basicevent1" - "/upnp/event/basicevent1" - "/eventservice.xml" - "" - "" - "urn:Belkin:service:metainfo:1" - "urn:Belkin:serviceId:metainfo1" - "/upnp/control/metainfo1" - "/upnp/event/metainfo1" - "/metainfoservice.xml" - "" - "" - "" - "\r\n"; - - - -void HandleUpnpEvent(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); - - char event[500]; - strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); - - - - - char state = 'G'; - if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) { - state = 'S'; - uint8_t power = POWER_TOGGLE; - if (strstr_P(event, PSTR("State>10on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); - WebServer->on("/eventservice.xml", HandleUpnpService); - WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); - WebServer->on("/setup.xml", HandleUpnpSetupWemo); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" -#ifdef USE_SONOFF_IFAN - - - - -#define XDRV_22 22 - -const uint8_t MAX_FAN_SPEED = 4; - -const uint8_t kIFan02Speed[MAX_FAN_SPEED] = { 0x00, 0x01, 0x03, 0x05 }; -const uint8_t kIFan03Speed[MAX_FAN_SPEED +2] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x06 }; -const uint8_t kIFan03Sequence[MAX_FAN_SPEED][MAX_FAN_SPEED] = {{0, 2, 2, 2}, {0, 1, 2, 4}, {1, 1, 2, 5}, {4, 4, 5, 3}}; - -const char kSonoffIfanCommands[] PROGMEM = "|" - D_CMND_FANSPEED; - -void (* const SonoffIfanCommand[])(void) PROGMEM = { - &CmndFanspeed }; - -uint8_t ifan_fanspeed_timer = 0; -uint8_t ifan_fanspeed_goal = 0; -bool ifan_receive_flag = false; -bool ifan_restart_flag = true; - - - -bool IsModuleIfan(void) -{ - return ((SONOFF_IFAN02 == my_module_type) || (SONOFF_IFAN03 == my_module_type)); -} - -uint8_t MaxFanspeed(void) -{ - return MAX_FAN_SPEED; -} - -uint8_t GetFanspeed(void) -{ - if (ifan_fanspeed_timer) { - return ifan_fanspeed_goal; - } else { - - - - - - - uint8_t fanspeed = (uint8_t)(power &0xF) >> 1; - if (fanspeed) { fanspeed = (fanspeed >> 1) +1; } - return fanspeed; - } -} - - - -void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence) -{ - ifan_fanspeed_timer = 0; - ifan_fanspeed_goal = fanspeed; - - uint8_t fanspeed_now = GetFanspeed(); - - if (fanspeed == fanspeed_now) { return; } - - uint8_t fans = kIFan02Speed[fanspeed]; - if (SONOFF_IFAN03 == my_module_type) { - if (sequence) { - fanspeed = kIFan03Sequence[fanspeed_now][ifan_fanspeed_goal]; - if (fanspeed != ifan_fanspeed_goal) { - if (0 == fanspeed_now) { - ifan_fanspeed_timer = 20; - } else { - ifan_fanspeed_timer = 2; - } - } - } - fans = kIFan03Speed[fanspeed]; - } - for (uint32_t i = 2; i < 5; i++) { - uint8_t state = (fans &1) + POWER_OFF_NO_STATE; - ExecuteCommandPower(i, state, SRC_IGNORE); - fans >>= 1; - } - -#ifdef USE_DOMOTICZ - if (sequence) { DomoticzUpdateFanState(); } -#endif -} - - - -void SonoffIfanReceived(void) -{ - char svalue[32]; - - uint8_t mode = serial_in_buffer[3]; - uint8_t action = serial_in_buffer[6]; - - if (4 == mode) { - if (action < 4) { - - - - - if (action != GetFanspeed()) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), action); - ExecuteCommand(svalue, SRC_REMOTE); -#ifdef USE_BUZZER - BuzzerEnabledBeep((action) ? action : 1, (action) ? 1 : 4); -#endif - } - } else { - - ExecuteCommandPower(1, POWER_TOGGLE, SRC_REMOTE); - } - } - if (6 == mode) { - - Settings.flag3.buzzer_enable = !Settings.flag3.buzzer_enable; - } - if (7 == mode) { - -#ifdef USE_BUZZER - BuzzerEnabledBeep(4, 1); -#endif - } - - - - serial_in_buffer[5] = 0; - serial_in_buffer[6] = 0; - for (uint32_t i = 0; i < 7; i++) { - if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } - Serial.write(serial_in_buffer[i]); - } -} - -bool SonoffIfanSerialInput(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - if (0xAA == serial_in_byte) { - serial_in_byte_counter = 0; - ifan_receive_flag = true; - } - if (ifan_receive_flag) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 8) { -# 176 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" - AddLogSerial(LOG_LEVEL_DEBUG); - uint8_t crc = 0; - for (uint32_t i = 2; i < 7; i++) { - crc += serial_in_buffer[i]; - } - if (crc == serial_in_buffer[7]) { - SonoffIfanReceived(); - ifan_receive_flag = false; - return true; - } - } - serial_in_byte = 0; - } - return false; - } -} - - - - - -void CmndFanspeed(void) -{ - if (XdrvMailbox.data_len > 0) { - if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (int16_t)GetFanspeed() -1; - if (XdrvMailbox.payload < 0) { XdrvMailbox.payload = MAX_FAN_SPEED -1; } - } - else if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = GetFanspeed() +1; - if (XdrvMailbox.payload > MAX_FAN_SPEED -1) { XdrvMailbox.payload = 0; } - } - } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_FAN_SPEED)) { - SonoffIFanSetFanspeed(XdrvMailbox.payload, true); - } - ResponseCmndNumber(GetFanspeed()); -} - - - -bool SonoffIfanInit(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - SetSerial(9600, TS_SERIAL_8N1); - } - return false; -} - -void SonoffIfanUpdate(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - if (ifan_fanspeed_timer) { - ifan_fanspeed_timer--; - if (!ifan_fanspeed_timer) { - SonoffIFanSetFanspeed(ifan_fanspeed_goal, false); - } - } - } - - if (ifan_restart_flag && (4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { - ifan_restart_flag = false; - SetDevicePower(1, SRC_RETRY); - SetDevicePower(power, SRC_RETRY); - } -} - - - - - -bool Xdrv22(uint8_t function) -{ - bool result = false; - - if (IsModuleIfan()) { - switch (function) { - case FUNC_EVERY_250_MSECOND: - SonoffIfanUpdate(); - break; - case FUNC_SERIAL: - result = SonoffIfanSerialInput(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kSonoffIfanCommands, SonoffIfanCommand); - break; - case FUNC_MODULE_INIT: - result = SonoffIfanInit(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -#ifdef USE_ZIGBEE - -#define OCCUPANCY "Occupancy" - -typedef uint64_t Z_IEEEAddress; -typedef uint16_t Z_ShortAddress; - -enum ZnpCommandType { - Z_POLL = 0x00, - Z_SREQ = 0x20, - Z_AREQ = 0x40, - Z_SRSP = 0x60 -}; - -enum ZnpSubsystem { - Z_RPC_Error = 0x00, - Z_SYS = 0x01, - Z_MAC = 0x02, - Z_NWK = 0x03, - Z_AF = 0x04, - Z_ZDO = 0x05, - Z_SAPI = 0x06, - Z_UTIL = 0x07, - Z_DEBUG = 0x08, - Z_APP = 0x09 -}; - - -enum SysCommand { - SYS_RESET = 0x00, - SYS_PING = 0x01, - SYS_VERSION = 0x02, - SYS_SET_EXTADDR = 0x03, - SYS_GET_EXTADDR = 0x04, - SYS_RAM_READ = 0x05, - SYS_RAM_WRITE = 0x06, - SYS_OSAL_NV_ITEM_INIT = 0x07, - SYS_OSAL_NV_READ = 0x08, - SYS_OSAL_NV_WRITE = 0x09, - SYS_OSAL_START_TIMER = 0x0A, - SYS_OSAL_STOP_TIMER = 0x0B, - SYS_RANDOM = 0x0C, - SYS_ADC_READ = 0x0D, - SYS_GPIO = 0x0E, - SYS_STACK_TUNE = 0x0F, - SYS_SET_TIME = 0x10, - SYS_GET_TIME = 0x11, - SYS_OSAL_NV_DELETE = 0x12, - SYS_OSAL_NV_LENGTH = 0x13, - SYS_TEST_RF = 0x40, - SYS_TEST_LOOPBACK = 0x41, - SYS_RESET_IND = 0x80, - SYS_OSAL_TIMER_EXPIRED = 0x81, -}; - -enum SapiCommand { - SAPI_START_REQUEST = 0x00, - SAPI_BIND_DEVICE = 0x01, - SAPI_ALLOW_BIND = 0x02, - SAPI_SEND_DATA_REQUEST = 0x03, - SAPI_READ_CONFIGURATION = 0x04, - SAPI_WRITE_CONFIGURATION = 0x05, - SAPI_GET_DEVICE_INFO = 0x06, - SAPI_FIND_DEVICE_REQUEST = 0x07, - SAPI_PERMIT_JOINING_REQUEST = 0x08, - SAPI_SYSTEM_RESET = 0x09, - SAPI_START_CONFIRM = 0x80, - SAPI_BIND_CONFIRM = 0x81, - SAPI_ALLOW_BIND_CONFIRM = 0x82, - SAPI_SEND_DATA_CONFIRM = 0x83, - SAPI_FIND_DEVICE_CONFIRM = 0x85, - SAPI_RECEIVE_DATA_INDICATION = 0x87, -}; -enum Z_configuration { - CONF_EXTADDR = 0x01, - CONF_BOOTCOUNTER = 0x02, - CONF_STARTUP_OPTION = 0x03, - CONF_START_DELAY = 0x04, - CONF_NIB = 0x21, - CONF_DEVICE_LIST = 0x22, - CONF_ADDRMGR = 0x23, - CONF_POLL_RATE = 0x24, - CONF_QUEUED_POLL_RATE = 0x25, - CONF_RESPONSE_POLL_RATE = 0x26, - CONF_REJOIN_POLL_RATE = 0x27, - CONF_DATA_RETRIES = 0x28, - CONF_POLL_FAILURE_RETRIES = 0x29, - CONF_STACK_PROFILE = 0x2A, - CONF_INDIRECT_MSG_TIMEOUT = 0x2B, - CONF_ROUTE_EXPIRY_TIME = 0x2C, - CONF_EXTENDED_PAN_ID = 0x2D, - CONF_BCAST_RETRIES = 0x2E, - CONF_PASSIVE_ACK_TIMEOUT = 0x2F, - CONF_BCAST_DELIVERY_TIME = 0x30, - CONF_NWK_MODE = 0x31, - CONF_CONCENTRATOR_ENABLE = 0x32, - CONF_CONCENTRATOR_DISCOVERY = 0x33, - CONF_CONCENTRATOR_RADIUS = 0x34, - CONF_CONCENTRATOR_RC = 0x36, - CONF_NWK_MGR_MODE = 0x37, - CONF_SRC_RTG_EXPIRY_TIME = 0x38, - CONF_ROUTE_DISCOVERY_TIME = 0x39, - CONF_NWK_ACTIVE_KEY_INFO = 0x3A, - CONF_NWK_ALTERN_KEY_INFO = 0x3B, - CONF_ROUTER_OFF_ASSOC_CLEANUP = 0x3C, - CONF_NWK_LEAVE_REQ_ALLOWED = 0x3D, - CONF_NWK_CHILD_AGE_ENABLE = 0x3E, - CONF_DEVICE_LIST_KA_TIMEOUT = 0x3F, - CONF_BINDING_TABLE = 0x41, - CONF_GROUP_TABLE = 0x42, - CONF_APS_FRAME_RETRIES = 0x43, - CONF_APS_ACK_WAIT_DURATION = 0x44, - CONF_APS_ACK_WAIT_MULTIPLIER = 0x45, - CONF_BINDING_TIME = 0x46, - CONF_APS_USE_EXT_PANID = 0x47, - CONF_APS_USE_INSECURE_JOIN = 0x48, - CONF_COMMISSIONED_NWK_ADDR = 0x49, - CONF_APS_NONMEMBER_RADIUS = 0x4B, - CONF_APS_LINK_KEY_TABLE = 0x4C, - CONF_APS_DUPREJ_TIMEOUT_INC = 0x4D, - CONF_APS_DUPREJ_TIMEOUT_COUNT = 0x4E, - CONF_APS_DUPREJ_TABLE_SIZE = 0x4F, - CONF_DIAGNOSTIC_STATS = 0x50, - CONF_SECURITY_LEVEL = 0x61, - CONF_PRECFGKEY = 0x62, - CONF_PRECFGKEYS_ENABLE = 0x63, - CONF_SECURITY_MODE = 0x64, - CONF_SECURE_PERMIT_JOIN = 0x65, - CONF_APS_LINK_KEY_TYPE = 0x66, - CONF_APS_ALLOW_R19_SECURITY = 0x67, - CONF_IMPLICIT_CERTIFICATE = 0x69, - CONF_DEVICE_PRIVATE_KEY = 0x6A, - CONF_CA_PUBLIC_KEY = 0x6B, - CONF_KE_MAX_DEVICES = 0x6C, - CONF_USE_DEFAULT_TCLK = 0x6D, - CONF_RNG_COUNTER = 0x6F, - CONF_RANDOM_SEED = 0x70, - CONF_TRUSTCENTER_ADDR = 0x71, - CONF_USERDESC = 0x81, - CONF_NWKKEY = 0x82, - CONF_PANID = 0x83, - CONF_CHANLIST = 0x84, - CONF_LEAVE_CTRL = 0x85, - CONF_SCAN_DURATION = 0x86, - CONF_LOGICAL_TYPE = 0x87, - CONF_NWKMGR_MIN_TX = 0x88, - CONF_NWKMGR_ADDR = 0x89, - CONF_ZDO_DIRECT_CB = 0x8F, - CONF_TCLK_TABLE_START = 0x0101, - ZNP_HAS_CONFIGURED = 0xF00 -}; -# 210 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -enum Z_Status { - Z_Success = 0x00, - Z_Failure = 0x01, - Z_InvalidParameter = 0x02, - Z_MemError = 0x03, - Z_Created = 0x09, - Z_BufferFull = 0x11 -}; - -enum Z_App_Profiles { - Z_PROF_IPM = 0x0101, - Z_PROF_HA = 0x0104, - Z_PROF_CBA = 0x0105, - Z_PROF_TA = 0x0107, - Z_PROF_PHHC = 0x0108, - Z_PROF_AMI = 0x0109, -}; - -enum Z_Device_Ids { - Z_DEVID_CONF_TOOL = 0x0005, -# 262 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -}; -# 275 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -enum AfCommand : uint8_t { - AF_REGISTER = 0x00, - AF_DATA_REQUEST = 0x01, - AF_DATA_REQUEST_EXT = 0x02, - AF_DATA_REQUEST_SRC_RTG = 0x03, - AF_INTER_PAN_CTL = 0x10, - AF_DATA_STORE = 0x11, - AF_DATA_RETRIEVE = 0x12, - AF_APSF_CONFIG_SET = 0x13, - AF_DATA_CONFIRM = 0x80, - AF_REFLECT_ERROR = 0x83, - AF_INCOMING_MSG = 0x81, - AF_INCOMING_MSG_EXT = 0x82 -}; - - -enum : uint8_t { - ZDO_NWK_ADDR_REQ = 0x00, - ZDO_IEEE_ADDR_REQ = 0x01, - ZDO_NODE_DESC_REQ = 0x02, - ZDO_POWER_DESC_REQ = 0x03, - ZDO_SIMPLE_DESC_REQ = 0x04, - ZDO_ACTIVE_EP_REQ = 0x05, - ZDO_MATCH_DESC_REQ = 0x06, - ZDO_COMPLEX_DESC_REQ = 0x07, - ZDO_USER_DESC_REQ = 0x08, - ZDO_DEVICE_ANNCE = 0x0A, - ZDO_USER_DESC_SET = 0x0B, - ZDO_SERVER_DISC_REQ = 0x0C, - ZDO_END_DEVICE_BIND_REQ = 0x20, - ZDO_BIND_REQ = 0x21, - ZDO_UNBIND_REQ = 0x22, - ZDO_SET_LINK_KEY = 0x23, - ZDO_REMOVE_LINK_KEY = 0x24, - ZDO_GET_LINK_KEY = 0x25, - ZDO_MGMT_NWK_DISC_REQ = 0x30, - ZDO_MGMT_LQI_REQ = 0x31, - ZDO_MGMT_RTQ_REQ = 0x32, - ZDO_MGMT_BIND_REQ = 0x33, - ZDO_MGMT_LEAVE_REQ = 0x34, - ZDO_MGMT_DIRECT_JOIN_REQ = 0x35, - ZDO_MGMT_PERMIT_JOIN_REQ = 0x36, - ZDO_MGMT_NWK_UPDATE_REQ = 0x37, - ZDO_MSG_CB_REGISTER = 0x3E, - ZDO_MGS_CB_REMOVE = 0x3F, - ZDO_STARTUP_FROM_APP = 0x40, - ZDO_AUTO_FIND_DESTINATION = 0x41, - ZDO_EXT_REMOVE_GROUP = 0x47, - ZDO_EXT_REMOVE_ALL_GROUP = 0x48, - ZDO_EXT_FIND_ALL_GROUPS_ENDPOINT = 0x49, - ZDO_EXT_FIND_GROUP = 0x4A, - ZDO_EXT_ADD_GROUP = 0x4B, - ZDO_EXT_COUNT_ALL_GROUPS = 0x4C, - ZDO_NWK_ADDR_RSP = 0x80, - ZDO_IEEE_ADDR_RSP = 0x81, - ZDO_NODE_DESC_RSP = 0x82, - ZDO_POWER_DESC_RSP = 0x83, - ZDO_SIMPLE_DESC_RSP = 0x84, - ZDO_ACTIVE_EP_RSP = 0x85, - ZDO_MATCH_DESC_RSP = 0x86, - ZDO_COMPLEX_DESC_RSP = 0x87, - ZDO_USER_DESC_RSP = 0x88, - ZDO_USER_DESC_CONF = 0x89, - ZDO_SERVER_DISC_RSP = 0x8A, - ZDO_END_DEVICE_BIND_RSP = 0xA0, - ZDO_BIND_RSP = 0xA1, - ZDO_UNBIND_RSP = 0xA2, - ZDO_MGMT_NWK_DISC_RSP = 0xB0, - ZDO_MGMT_LQI_RSP = 0xB1, - ZDO_MGMT_RTG_RSP = 0xB2, - ZDO_MGMT_BIND_RSP = 0xB3, - ZDO_MGMT_LEAVE_RSP = 0xB4, - ZDO_MGMT_DIRECT_JOIN_RSP = 0xB5, - ZDO_MGMT_PERMIT_JOIN_RSP = 0xB6, - ZDO_STATE_CHANGE_IND = 0xC0, - ZDO_END_DEVICE_ANNCE_IND = 0xC1, - ZDO_MATCH_DESC_RSP_SENT = 0xC2, - ZDO_STATUS_ERROR_RSP = 0xC3, - ZDO_SRC_RTG_IND = 0xC4, - ZDO_LEAVE_IND = 0xC9, - ZDO_TC_DEV_IND = 0xCA, - ZDO_PERMIT_JOIN_IND = 0xCB, - ZDO_MSG_CB_INCOMING = 0xFF -}; - - -enum ZdoStates { - ZDO_DEV_HOLD = 0x00, - ZDO_DEV_INIT = 0x01, - ZDO_DEV_NWK_DISC = 0x02, - ZDO_DEV_NWK_JOINING = 0x03, - ZDO_DEV_NWK_REJOIN = 0x04, - ZDO_DEV_END_DEVICE_UNAUTH = 0x05, - ZDO_DEV_END_DEVICE = 0x06, - ZDO_DEV_ROUTER = 0x07, - ZDO_DEV_COORD_STARTING = 0x08, - ZDO_DEV_ZB_COORD = 0x09, - ZDO_DEV_NWK_ORPHAN = 0x0A, -}; - - -enum Z_Util { - Z_UTIL_GET_DEVICE_INFO = 0x00, - Z_UTIL_GET_NV_INFO = 0x01, - Z_UTIL_SET_PANID = 0x02, - Z_UTIL_SET_CHANNELS = 0x03, - Z_UTIL_SET_SECLEVEL = 0x04, - Z_UTIL_SET_PRECFGKEY = 0x05, - Z_UTIL_CALLBACK_SUB_CMD = 0x06, - Z_UTIL_KEY_EVENT = 0x07, - Z_UTIL_TIME_ALIVE = 0x09, - Z_UTIL_LED_CONTROL = 0x0A, - Z_UTIL_TEST_LOOPBACK = 0x10, - Z_UTIL_DATA_REQ = 0x11, - Z_UTIL_SRC_MATCH_ENABLE = 0x20, - Z_UTIL_SRC_MATCH_ADD_ENTRY = 0x21, - Z_UTIL_SRC_MATCH_DEL_ENTRY = 0x22, - Z_UTIL_SRC_MATCH_CHECK_SRC_ADDR = 0x23, - Z_UTIL_SRC_MATCH_ACK_ALL_PENDING = 0x24, - Z_UTIL_SRC_MATCH_CHECK_ALL_PENDING = 0x25, - Z_UTIL_ADDRMGR_EXT_ADDR_LOOKUP = 0x40, - Z_UTIL_ADDRMGR_NWK_ADDR_LOOKUP = 0x41, - Z_UTIL_APSME_LINK_KEY_DATA_GET = 0x44, - Z_UTIL_APSME_LINK_KEY_NV_ID_GET = 0x45, - Z_UTIL_ASSOC_COUNT = 0x48, - Z_UTIL_ASSOC_FIND_DEVICE = 0x49, - Z_UTIL_ASSOC_GET_WITH_ADDRESS = 0x4A, - Z_UTIL_APSME_REQUEST_KEY_CMD = 0x4B, - Z_UTIL_ZCL_KEY_EST_INIT_EST = 0x80, - Z_UTIL_ZCL_KEY_EST_SIGN = 0x81, - Z_UTIL_UTIL_SYNC_REQ = 0xE0, - Z_UTIL_ZCL_KEY_ESTABLISH_IND = 0xE1 -}; - -enum ZCL_Global_Commands { - ZCL_READ_ATTRIBUTES = 0x00, - ZCL_READ_ATTRIBUTES_RESPONSE = 0x01, - ZCL_WRITE_ATTRIBUTES = 0x02, - ZCL_WRITE_ATTRIBUTES_UNDIVIDED = 0x03, - ZCL_WRITE_ATTRIBUTES_RESPONSE = 0x04, - ZCL_WRITE_ATTRIBUTES_NORESPONSE = 0x05, - ZCL_CONFIGURE_REPORTING = 0x06, - ZCL_CONFIGURE_REPORTING_RESPONSE = 0x07, - ZCL_READ_REPORTING_CONFIGURATION = 0x08, - ZCL_READ_REPORTING_CONFIGURATION_RESPONSE = 0x09, - ZCL_REPORT_ATTRIBUTES = 0x0a, - ZCL_DEFAULT_RESPONSE = 0x0b, - ZCL_DISCOVER_ATTRIBUTES = 0x0c, - ZCL_DISCOVER_ATTRIBUTES_RESPONSE = 0x0d - -}; - -const uint16_t Z_ProfileIds[] PROGMEM = { 0x0104, 0x0109, 0xA10E, 0xC05E }; -const char Z_ProfileNames[] PROGMEM = "ZigBee Home Automation|ZigBee Smart Energy|ZigBee Green Power|ZigBee Light Link"; - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" -#ifdef USE_ZIGBEE - - - -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1); - - - -JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { - - if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) { - return *(JsonVariant*)nullptr; - } - - for (auto kv : json) { - const char *key = kv.key; - JsonVariant &value = kv.value; - - if (0 == strcasecmp_P(key, needle)) { - return value; - } - } - - return *(JsonVariant*)nullptr; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -#ifdef USE_ZIGBEE - -#include -#include - -#ifndef ZIGBEE_SAVE_DELAY_SECONDS -#define ZIGBEE_SAVE_DELAY_SECONDS 10; -#endif -const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; - -typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); - -typedef struct Z_Device { - uint16_t shortaddr; - uint64_t longaddr; - uint32_t firstSeen; - uint32_t lastSeen; - String manufacturerId; - String modelId; - String friendlyName; - std::vector endpoints; - std::vector clusters_in; - std::vector clusters_out; - - uint32_t timer; - uint16_t cluster; - uint16_t endpoint; - uint32_t value; - Z_DeviceTimer func; - - DynamicJsonBuffer *json_buffer; - JsonObject *json; -} Z_Device; - - - - - - - -class Z_Devices { -public: - Z_Devices() {}; - - - - - - - uint16_t isKnownShortAddr(uint16_t shortaddr) const; - uint16_t isKnownLongAddr(uint64_t longaddr) const; - uint16_t isKnownIndex(uint32_t index) const; - uint16_t isKnownFriendlyName(const char * name) const; - - uint64_t getDeviceLongAddr(uint16_t shortaddr) const; - - - - void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); - - - void addEndoint(uint16_t shortaddr, uint8_t endpoint); - - - void addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId); - - - void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out); - - uint8_t findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster); - - void setManufId(uint16_t shortaddr, const char * str); - void setModelId(uint16_t shortaddr, const char * str); - void setFriendlyName(uint16_t shortaddr, const char * str); - const String * getFriendlyName(uint16_t) const; - - - void updateLastSeen(uint16_t shortaddr); - - - String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; - - - void resetTimer(uint32_t shortaddr); - void setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func); - void runTimer(void); - - - void jsonClear(uint16_t shortaddr); - void jsonAppend(uint16_t shortaddr, const JsonObject &values); - const JsonObject *jsonGet(uint16_t shortaddr); - void jsonPublishFlush(uint16_t shortaddr); - bool jsonIsConflict(uint16_t shortaddr, const JsonObject &values); - void jsonPublishNow(uint16_t shortaddr, JsonObject &values); - - - size_t devicesSize(void) const { - return _devices.size(); - } - const Z_Device &devicesAt(size_t i) const { - return _devices.at(i); - } - - - bool removeDevice(uint16_t shortaddr); - - - void dirty(void); - void clean(void); - - - uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const; - -private: - std::vector _devices = {}; - uint32_t _saveTimer = 0; - - template < typename T> - static bool findInVector(const std::vector & vecOfElements, const T & element); - - template < typename T> - static int32_t findEndpointInVector(const std::vector & vecOfElements, uint8_t element); - - - static int32_t findClusterEndpoint(const std::vector & vecOfElements, uint16_t element); - - Z_Device & getShortAddr(uint16_t shortaddr); - const Z_Device & getShortAddrConst(uint16_t shortaddr) const ; - Z_Device & getLongAddr(uint64_t longaddr); - - int32_t findShortAddr(uint16_t shortaddr) const; - int32_t findLongAddr(uint64_t longaddr) const; - int32_t findFriendlyName(const char * name) const; - - void _updateLastSeen(Z_Device &device) { - if (&device != nullptr) { - device.lastSeen = Rtc.utc_time; - } - }; - - - Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0); -}; - -Z_Devices zigbee_devices = Z_Devices(); - - -uint64_t localIEEEAddr = 0; - - -template < typename T> -bool Z_Devices::findInVector(const std::vector & vecOfElements, const T & element) { - - auto it = std::find(vecOfElements.begin(), vecOfElements.end(), element); - - if (it != vecOfElements.end()) { - return true; - } else { - return false; - } -} - -template < typename T> -int32_t Z_Devices::findEndpointInVector(const std::vector & vecOfElements, uint8_t element) { - - - int32_t found = 0; - for (auto &elem : vecOfElements) { - if ( ((elem >> 16) & 0xFF) == element) { return found; } - found++; - } - - return -1; -} -# 204 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -int32_t Z_Devices::findClusterEndpoint(const std::vector & vecOfElements, uint16_t cluster) { - int32_t found = 0; - for (auto &elem : vecOfElements) { - if ((elem & 0xFFFF) == cluster) { return found; } - found++; - } - return -1; -} - - - - - -Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { - if (!shortaddr && !longaddr) { return *(Z_Device*) nullptr; } - Z_Device device = { shortaddr, longaddr, - Rtc.utc_time, Rtc.utc_time, - String(), - String(), - String(), - std::vector(), - std::vector(), - std::vector(), - 0,0,0,0, - nullptr, - nullptr, nullptr }; - device.json_buffer = new DynamicJsonBuffer(); - _devices.push_back(device); - dirty(); - return _devices.back(); -} -# 244 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -int32_t Z_Devices::findShortAddr(uint16_t shortaddr) const { - if (!shortaddr) { return -1; } - int32_t found = 0; - if (shortaddr) { - for (auto &elem : _devices) { - if (elem.shortaddr == shortaddr) { return found; } - found++; - } - } - return -1; -} -# 263 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -int32_t Z_Devices::findLongAddr(uint64_t longaddr) const { - if (!longaddr) { return -1; } - int32_t found = 0; - if (longaddr) { - for (auto &elem : _devices) { - if (elem.longaddr == longaddr) { return found; } - found++; - } - } - return -1; -} -# 282 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -int32_t Z_Devices::findFriendlyName(const char * name) const { - if (!name) { return -1; } - size_t name_len = strlen(name); - int32_t found = 0; - if (name_len) { - for (auto &elem : _devices) { - if (elem.friendlyName == name) { return found; } - found++; - } - } - return -1; -} - - -uint16_t Z_Devices::isKnownShortAddr(uint16_t shortaddr) const { - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - return shortaddr; - } else { - return 0; - } -} - -uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const { - int32_t found = findLongAddr(longaddr); - if (found >= 0) { - const Z_Device & device = devicesAt(found); - return device.shortaddr; - } else { - return 0; - } -} - -uint16_t Z_Devices::isKnownIndex(uint32_t index) const { - if (index < devicesSize()) { - const Z_Device & device = devicesAt(index); - return device.shortaddr; - } else { - return 0; - } -} - -uint16_t Z_Devices::isKnownFriendlyName(const char * name) const { - if ((!name) || (0 == strlen(name))) { return 0xFFFF; } - int32_t found = findFriendlyName(name); - if (found >= 0) { - const Z_Device & device = devicesAt(found); - return device.shortaddr; - } else { - return 0; - } -} - -uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const { - const Z_Device & device = getShortAddrConst(shortaddr); - return device.longaddr; -} - - - - -Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) { - if (!shortaddr) { return *(Z_Device*) nullptr; } - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - return _devices[found]; - } - - return createDeviceEntry(shortaddr, 0); -} - -const Z_Device & Z_Devices::getShortAddrConst(uint16_t shortaddr) const { - if (!shortaddr) { return *(Z_Device*) nullptr; } - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - return _devices[found]; - } - return *((Z_Device*)nullptr); -} - - -Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) { - if (!longaddr) { return *(Z_Device*) nullptr; } - int32_t found = findLongAddr(longaddr); - if (found > 0) { - return _devices[found]; - } - return createDeviceEntry(0, longaddr); -} - - -bool Z_Devices::removeDevice(uint16_t shortaddr) { - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - _devices.erase(_devices.begin() + found); - dirty(); - return true; - } - return false; -} - - - - - - -void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { - int32_t s_found = findShortAddr(shortaddr); - int32_t l_found = findLongAddr(longaddr); - - if ((s_found >= 0) && (l_found >= 0)) { - if (s_found == l_found) { - updateLastSeen(shortaddr); - } else { - - _devices[l_found].shortaddr = shortaddr; - - _devices.erase(_devices.begin() + s_found); - updateLastSeen(shortaddr); - dirty(); - } - } else if (s_found >= 0) { - - - _devices[s_found].longaddr = longaddr; - updateLastSeen(shortaddr); - dirty(); - } else if (l_found >= 0) { - - _devices[l_found].shortaddr = shortaddr; - dirty(); - } else { - - if (shortaddr || longaddr) { - createDeviceEntry(shortaddr, longaddr); - } - } -} - - - - -void Z_Devices::addEndoint(uint16_t shortaddr, uint8_t endpoint) { - if (!shortaddr) { return; } - uint32_t ep_profile = (endpoint << 16); - Z_Device &device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - if (findEndpointInVector(device.endpoints, endpoint) < 0) { - device.endpoints.push_back(ep_profile); - dirty(); - } -} - -void Z_Devices::addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId) { - if (!shortaddr) { return; } - uint32_t ep_profile = (endpoint << 16) | profileId; - Z_Device &device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - int32_t found = findEndpointInVector(device.endpoints, endpoint); - if (found < 0) { - device.endpoints.push_back(ep_profile); - dirty(); - } else { - if (device.endpoints[found] != ep_profile) { - device.endpoints[found] = ep_profile; - dirty(); - } - } -} - -void Z_Devices::addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out) { - if (!shortaddr) { return; } - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - uint32_t ep_cluster = (endpoint << 16) | cluster; - if (!out) { - if (!findInVector(device.clusters_in, ep_cluster)) { - device.clusters_in.push_back(ep_cluster); - dirty(); - } - } else { - if (!findInVector(device.clusters_out, ep_cluster)) { - device.clusters_out.push_back(ep_cluster); - dirty(); - } - } -} - - - -uint8_t Z_Devices::findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster){ - int32_t short_found = findShortAddr(shortaddr); - if (short_found < 0) return 0; - Z_Device &device = getShortAddr(shortaddr); - if (&device == nullptr) { return 0; } - int32_t found = findClusterEndpoint(device.clusters_in, cluster); - if (found >= 0) { - return (device.clusters_in[found] >> 16) & 0xFF; - } else { - return 0; - } -} - - -void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - if (!device.manufacturerId.equals(str)) { - dirty(); - } - device.manufacturerId = str; -} -void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - if (!device.modelId.equals(str)) { - dirty(); - } - device.modelId = str; -} -void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - if (!device.friendlyName.equals(str)) { - dirty(); - } - device.friendlyName = str; -} - -const String * Z_Devices::getFriendlyName(uint16_t shortaddr) const { - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - const Z_Device & device = devicesAt(found); - if (device.friendlyName.length() > 0) { - return &device.friendlyName; - } - } - return nullptr; -} - - -void Z_Devices::updateLastSeen(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); -} - - - - -void Z_Devices::resetTimer(uint32_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - device.timer = 0; - device.func = nullptr; -} - - -void Z_Devices::setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - - device.cluster = cluster; - device.endpoint = endpoint; - device.value = value; - device.func = func; - device.timer = wait_ms + millis(); -} - - -void Z_Devices::runTimer(void) { - for (std::vector::iterator it = _devices.begin(); it != _devices.end(); ++it) { - Z_Device &device = *it; - uint16_t shortaddr = device.shortaddr; - - uint32_t timer = device.timer; - if ((timer) && TimeReached(timer)) { - device.timer = 0; - - (*device.func)(device.shortaddr, device.cluster, device.endpoint, device.value); - } - } - - if ((_saveTimer) && TimeReached(_saveTimer)) { - saveZigbeeDevices(); - _saveTimer = 0; - } -} - -void Z_Devices::jsonClear(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - - device.json = nullptr; - device.json_buffer->clear(); -} - -void CopyJsonVariant(JsonObject &to, const String &key, const JsonVariant &val) { - to.remove(key); - - if (val.is()) { - String sval = val.as(); - to.set(key, sval); - } else if (val.is()) { - JsonArray &nested_arr = to.createNestedArray(key); - CopyJsonArray(nested_arr, val.as()); - } else if (val.is()) { - JsonObject &nested_obj = to.createNestedObject(key); - CopyJsonObject(nested_obj, val.as()); - } else { - to.set(key, val); - } -} - -void CopyJsonArray(JsonArray &to, const JsonArray &arr) { - for (auto v : arr) { - if (v.is()) { - String sval = v.as(); - to.add(sval); - } else if (v.is()) { - } else if (v.is()) { - } else { - to.add(v); - } - } -} - -void CopyJsonObject(JsonObject &to, const JsonObject &from) { - for (auto kv : from) { - String key_string = kv.key; - JsonVariant &val = kv.value; - - CopyJsonVariant(to, key_string, val); - } -} - - -bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const JsonObject &values) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return false; } - if (&values == nullptr) { return false; } - - if (nullptr == device.json) { - return false; - } - - for (auto kv : values) { - String key_string = kv.key; - - if (strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_LINKQUALITY))) { - if (device.json->containsKey(kv.key)) { - return true; - } - } - } - return false; -} - -void Z_Devices::jsonAppend(uint16_t shortaddr, const JsonObject &values) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - if (&values == nullptr) { return; } - - if (nullptr == device.json) { - device.json = &(device.json_buffer->createObject()); - } - - char sa[8]; - snprintf_P(sa, sizeof(sa), PSTR("0x%04X"), shortaddr); - device.json->set(F(D_JSON_ZIGBEE_DEVICE), sa); - - const String * fname = zigbee_devices.getFriendlyName(shortaddr); - if (fname) { - device.json->set(F(D_JSON_ZIGBEE_NAME), (char*)fname->c_str()); - } - - - CopyJsonObject(*device.json, values); -} - -const JsonObject *Z_Devices::jsonGet(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return nullptr; } - return device.json; -} - -void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - JsonObject * json = device.json; - if (json == nullptr) { return; } - - const String * fname = zigbee_devices.getFriendlyName(shortaddr); - bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); -# 693 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" - if (use_fname) { - json->remove(F(D_JSON_ZIGBEE_NAME)); - } else { - json->remove(F(D_JSON_ZIGBEE_DEVICE)); - } - - String msg = ""; - json->printTo(msg); - zigbee_devices.jsonClear(shortaddr); - - if (use_fname) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); - } else { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); - } - - -} - -void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { - jsonPublishFlush(shortaddr); - jsonAppend(shortaddr, values); - jsonPublishFlush(shortaddr); -} - -void Z_Devices::dirty(void) { - _saveTimer = kZigbeeSaveDelaySeconds * 1000 + millis(); -} -void Z_Devices::clean(void) { - _saveTimer = 0; -} - - - - - - -uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const { - if (nullptr == param) { return 0; } - size_t param_len = strlen(param); - char dataBuf[param_len + 1]; - strcpy(dataBuf, param); - RemoveSpace(dataBuf); - uint16_t shortaddr = 0; - - if (strlen(dataBuf) < 4) { - - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) { - shortaddr = zigbee_devices.isKnownIndex(XdrvMailbox.payload - 1); - } - } else if ((dataBuf[0] == '0') && (dataBuf[1] == 'x')) { - - if (strlen(dataBuf) < 18) { - - shortaddr = strtoull(dataBuf, nullptr, 0); - if (short_must_be_known) { - shortaddr = zigbee_devices.isKnownShortAddr(shortaddr); - } - - } else { - - uint64_t longaddr = strtoull(dataBuf, nullptr, 0); - shortaddr = zigbee_devices.isKnownLongAddr(longaddr); - } - } else { - - shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf); - } - - return shortaddr; -} - - - - - -String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { - DynamicJsonBuffer jsonBuffer; - JsonArray& json = jsonBuffer.createArray(); - JsonArray& devices = json; - - for (std::vector::const_iterator it = _devices.begin(); it != _devices.end(); ++it) { - const Z_Device& device = *it; - uint16_t shortaddr = device.shortaddr; - char hex[22]; - - - if ((status_shortaddr) && (status_shortaddr != shortaddr)) { continue; } - - JsonObject& dev = devices.createNestedObject(); - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); - dev[F(D_JSON_ZIGBEE_DEVICE)] = hex; - - if (device.friendlyName.length() > 0) { - dev[F(D_JSON_ZIGBEE_NAME)] = device.friendlyName; - } - - if (2 <= dump_mode) { - hex[0] = '0'; - hex[1] = 'x'; - Uint64toHex(device.longaddr, &hex[2], 64); - dev[F("IEEEAddr")] = hex; - if (device.modelId.length() > 0) { - dev[F(D_JSON_MODEL D_JSON_ID)] = device.modelId; - } - if (device.manufacturerId.length() > 0) { - dev[F("Manufacturer")] = device.manufacturerId; - } - } - - - if (3 <= dump_mode) { - JsonObject& dev_endpoints = dev.createNestedObject(F("Endpoints")); - for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { - uint32_t ep_profile = *ite; - uint8_t endpoint = (ep_profile >> 16) & 0xFF; - uint16_t profileId = ep_profile & 0xFFFF; - - snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonObject& ep = dev_endpoints.createNestedObject(hex); - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), profileId); - ep[F("ProfileId")] = hex; - - int32_t found = -1; - for (uint32_t i = 0; i < sizeof(Z_ProfileIds) / sizeof(Z_ProfileIds[0]); i++) { - if (pgm_read_word(&Z_ProfileIds[i]) == profileId) { - found = i; - break; - } - } - if (found > 0) { - GetTextIndexed(hex, sizeof(hex), found, Z_ProfileNames); - ep[F("ProfileIdName")] = hex; - } - - ep.createNestedArray(F("ClustersIn")); - ep.createNestedArray(F("ClustersOut")); - } - - for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t endpoint = (*itc >> 16) & 0xFF; - - snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersIn")]; - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); - cluster_arr.add(hex); - } - - for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t endpoint = (*itc >> 16) & 0xFF; - - snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersOut")]; - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); - cluster_arr.add(hex); - } - } - } - String payload = ""; - payload.reserve(200); - json.printTo(payload); - return payload; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -#ifdef USE_ZIGBEE -# 50 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -const static uint16_t z_spi_start_sector = 0xFF; -const static uint8_t* z_spi_start = (uint8_t*) 0x402FF000; -const static uint8_t* z_dev_start = z_spi_start + 0x0800; -const static size_t z_spi_len = 0x1000; -const static size_t z_block_offset = 0x0800; -const static size_t z_block_len = 0x0800; - -class z_flashdata_t { -public: - uint32_t name; - uint16_t len; - uint16_t reserved; -}; - -const static uint32_t ZIGB_NAME = 0x3167697A; -const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); - - -const uint16_t Z_ClusterNumber[] PROGMEM = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0100, 0x0101, 0x0102, - 0x0201, 0x0202, 0x0203, 0x0204, - 0x0300, 0x0301, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, - 0x0500, 0x0501, 0x0502, - 0x0700, 0x0701, 0x0702, - 0x0B00, 0x0B01, 0x0B02, 0x0B03, 0x0B04, 0x0B05, - 0x1000, - 0xFC0F, -}; - - -uint16_t fromClusterCode(uint8_t c) { - if (c >= sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0])) { - return 0xFFFF; - } - return pgm_read_word(&Z_ClusterNumber[c]); -} - - -uint8_t toClusterCode(uint16_t c) { - for (uint32_t i = 0; i < sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0]); i++) { - if (c == pgm_read_word(&Z_ClusterNumber[i])) { - return i; - } - } - return 0xFF; -} - -class SBuffer hibernateDevice(const struct Z_Device &device) { - SBuffer buf(128); - - buf.add8(0x00); - buf.add16(device.shortaddr); - buf.add64(device.longaddr); - uint32_t endpoints = device.endpoints.size(); - if (endpoints > 254) { endpoints = 254; } - buf.add8(endpoints); - - for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { - uint32_t ep_profile = *ite; - uint8_t endpoint = (ep_profile >> 16) & 0xFF; - uint16_t profileId = ep_profile & 0xFFFF; - - buf.add8(endpoint); - buf.add16(profileId); - for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t c_endpoint = (*itc >> 16) & 0xFF; - - if (endpoint == c_endpoint) { - uint8_t clusterCode = toClusterCode(cluster); - if (0xFF != clusterCode) { buf.add8(clusterCode); } - } - } - buf.add8(0xFF); - - for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t c_endpoint = (*itc >> 16) & 0xFF; - - if (endpoint == c_endpoint) { - uint8_t clusterCode = toClusterCode(cluster); - if (0xFF != clusterCode) { buf.add8(clusterCode); } - } - } - buf.add8(0xFF); - } - - - size_t model_len = device.modelId.length(); - if (model_len > 32) { model_len = 32; } - buf.addBuffer(device.modelId.c_str(), model_len); - buf.add8(0x00); - - - size_t manuf_len = device.manufacturerId.length(); - if (manuf_len > 32) {manuf_len = 32; } - buf.addBuffer(device.manufacturerId.c_str(), manuf_len); - buf.add8(0x00); - - - size_t frname_len = device.friendlyName.length(); - if (frname_len > 32) {frname_len = 32; } - buf.addBuffer(device.friendlyName.c_str(), frname_len); - buf.add8(0x00); - - - buf.set8(0, buf.len()); - - return buf; -} - -class SBuffer hibernateDevices(void) { - SBuffer buf(2048); - - size_t devices_size = zigbee_devices.devicesSize(); - if (devices_size > 32) { devices_size = 32; } - buf.add8(devices_size); - - for (uint32_t i = 0; i < devices_size; i++) { - const Z_Device & device = zigbee_devices.devicesAt(i); - const SBuffer buf_device = hibernateDevice(device); - buf.addBuffer(buf_device); - } - - size_t buf_len = buf.len(); - if (buf_len > 2040) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Devices list too big to fit in Flash (%d)"), buf_len); - } - - - char *hex_char = (char*) malloc((buf_len * 2) + 2); - if (hex_char) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbFlashStore %s"), - ToHex_P(buf.getBuffer(), buf_len, hex_char, (buf_len * 2) + 2)); - free(hex_char); - } - - return buf; -} - -void hidrateDevices(const SBuffer &buf) { - uint32_t buf_len = buf.len(); - if (buf_len <= 10) { return; } - - uint32_t k = 0; - uint32_t num_devices = buf.get8(k++); - - for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { - uint32_t dev_record_len = buf.get8(k); - - SBuffer buf_d = buf.subBuffer(k, dev_record_len); - - uint32_t d = 1; - uint16_t shortaddr = buf_d.get16(d); d += 2; - uint64_t longaddr = buf_d.get64(d); d += 8; - zigbee_devices.updateDevice(shortaddr, longaddr); - - uint32_t endpoints = buf_d.get8(d++); - for (uint32_t j = 0; j < endpoints; j++) { - uint8_t ep = buf_d.get8(d++); - uint16_t ep_profile = buf_d.get16(d); d += 2; - zigbee_devices.addEndointProfile(shortaddr, ep, ep_profile); - - - while (d < dev_record_len) { - uint8_t ep_cluster = buf_d.get8(d++); - if (0xFF == ep_cluster) { break; } - zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), false); - } - - while (d < dev_record_len) { - uint8_t ep_cluster = buf_d.get8(d++); - if (0xFF == ep_cluster) { break; } - zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), true); - } - } - - - char empty[] = ""; - - - uint32_t s_len = buf_d.strlen_s(d); - char *ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setModelId(shortaddr, ptr); - d += s_len + 1; - - - s_len = buf_d.strlen_s(d); - ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setManufId(shortaddr, ptr); - d += s_len + 1; - - - s_len = buf_d.strlen_s(d); - ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setFriendlyName(shortaddr, ptr); - d += s_len + 1; - - - k += dev_record_len; - } -} - -void loadZigbeeDevices(void) { - z_flashdata_t flashdata; - memcpy_P(&flashdata, z_dev_start, sizeof(z_flashdata_t)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Zigbee signature in Flash: %08X - %d"), flashdata.name, flashdata.len); - - - if ((flashdata.name == ZIGB_NAME) && (flashdata.len > 0)) { - uint16_t buf_len = flashdata.len; - - SBuffer buf(buf_len); - buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); - hidrateDevices(buf); - zigbee_devices.clean(); - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "No zigbee devices data in Flash")); - } -} - -void saveZigbeeDevices(void) { - SBuffer buf = hibernateDevices(); - size_t buf_len = buf.len(); - if (buf_len > Z_MAX_FLASH) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Buffer too big to fit in Flash (%d bytes)"), buf_len); - return; - } - - - uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); - if (!spi_buffer) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); - return; - } - - ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - - z_flashdata_t *flashdata = (z_flashdata_t*)(spi_buffer + z_block_offset); - flashdata->name = ZIGB_NAME; - flashdata->len = buf_len; - flashdata->reserved = 0; - - memcpy(spi_buffer + z_block_offset + sizeof(z_flashdata_t), buf.getBuffer(), buf_len); - - - if (ESP.flashEraseSector(z_spi_start_sector)) { - ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - } - - free(spi_buffer); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data store in Flash (0x%08X - %d bytes)"), z_dev_start, buf_len); -} - - -void eraseZigbeeDevices(void) { - zigbee_devices.clean(); - - uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); - if (!spi_buffer) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); - return; - } - - ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - - - memset(spi_buffer + z_block_offset, 0xFF, z_block_len); - - - if (ESP.flashEraseSector(z_spi_start_sector)) { - ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - } - - free(spi_buffer); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (0x%08X - %d bytes)"), z_dev_start, z_block_len); -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" -#ifdef USE_ZIGBEE - - - - - -typedef union ZCLHeaderFrameControl_t { - struct { - uint8_t frame_type : 2; - uint8_t manuf_specific : 1; - uint8_t direction : 1; - uint8_t disable_def_resp : 1; - uint8_t reserved : 3; - } b; - uint32_t d8; -} ZCLHeaderFrameControl_t; - - -class ZCLFrame { -public: - - ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id, - const char *buf, size_t buf_len, uint16_t clusterid, uint16_t groupid, - uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, - uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, - uint32_t timestamp): - _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), - _payload(buf_len ? buf_len : 250), - _cluster_id(clusterid), _group_id(groupid), - _srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast), - _linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber), - _timestamp(timestamp) - { - _frame_control.d8 = frame_control; - _payload.addBuffer(buf, buf_len); - }; - - - void log(void) { - char hex_char[_payload.len()*2+2]; - ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" - "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," - "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," - "\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," - "\"timestamp\":%d," - "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," - "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), - _group_id, _cluster_id, _srcaddr, - _srcendpoint, _dstendpoint, _wasbroadcast, - _linkquality, _securityuse, _seqnumber, - _timestamp, - _frame_control, _manuf_code, _transact_seq, _cmd_id, - hex_char); - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); - } - } - - static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid, - uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, - uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, - uint32_t timestamp) { - uint32_t i = offset; - ZCLHeaderFrameControl_t frame_control; - uint16_t manuf_code = 0; - uint8_t transact_seq; - uint8_t cmd_id; - - frame_control.d8 = buf.get8(i++); - if (frame_control.b.manuf_specific) { - manuf_code = buf.get16(i); - i += 2; - } - transact_seq = buf.get8(i++); - cmd_id = buf.get8(i++); - ZCLFrame zcl_frame(frame_control.d8, manuf_code, transact_seq, cmd_id, - (const char *)(buf.buf() + i), len + offset - i, - clusterid, groupid, - srcaddr, srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp); - return zcl_frame; - } - - bool isClusterSpecificCommand(void) { - return _frame_control.b.frame_type & 1; - } - - static void generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len); - void parseRawAttributes(JsonObject& json, uint8_t offset = 0); - void parseReadAttributes(JsonObject& json, uint8_t offset = 0); - void parseClusterSpecificCommand(JsonObject& json, uint8_t offset = 0); - void postProcessAttributes(uint16_t shortaddr, JsonObject& json); - - inline void setGroupId(uint16_t groupid) { - _group_id = groupid; - } - - inline void setClusterId(uint16_t clusterid) { - _cluster_id = clusterid; - } - - inline uint8_t getCmdId(void) const { - return _cmd_id; - } - - inline uint16_t getClusterId(void) const { - return _cluster_id; - } - - inline uint16_t getSrcEndpoint(void) const { - return _srcendpoint; - } - - const SBuffer &getPayload(void) const { - return _payload; - } - - uint16_t getManufCode(void) const { - return _manuf_code; - } - -private: - ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; - uint16_t _manuf_code = 0; - uint8_t _transact_seq = 0; - uint8_t _cmd_id = 0; - uint16_t _cluster_id = 0; - uint16_t _group_id = 0; - SBuffer _payload; - - uint16_t _srcaddr; - uint8_t _srcendpoint; - uint8_t _dstendpoint; - uint8_t _wasbroadcast; - uint8_t _linkquality; - uint8_t _securityuse; - uint8_t _seqnumber; - uint32_t _timestamp; -}; - - - - - - -uint8_t toPercentageCR2032(uint32_t voltage) { - uint32_t percentage; - if (voltage < 2100) { - percentage = 0; - } else if (voltage < 2440) { - percentage = 6 - ((2440 - voltage) * 6) / 340; - } else if (voltage < 2740) { - percentage = 18 - ((2740 - voltage) * 12) / 300; - } else if (voltage < 2900) { - percentage = 42 - ((2900 - voltage) * 24) / 160; - } else if (voltage < 3000) { - percentage = 100 - ((3000 - voltage) * 58) / 100; - } else if (voltage >= 3000) { - percentage = 100; - } - return percentage; -} - - -uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, - uint32_t offset, uint32_t len) { - - uint32_t i = offset; - uint32_t attrtype = buf.get8(i++); - - - json[attrid_str] = (char*) nullptr; - - - switch (attrtype) { - case 0x00: - case 0xFF: - break; - case 0x10: - { - uint8_t val_bool = buf.get8(i++); - if (0xFF != val_bool) { - json[attrid_str] = (bool) (val_bool ? true : false); - } - } - break; - case 0x20: - { - uint8_t uint8_val = buf.get8(i); - i += 1; - if (0xFF != uint8_val) { - json[attrid_str] = uint8_val; - } - } - break; - case 0x21: - { - uint16_t uint16_val = buf.get16(i); - i += 2; - if (0xFFFF != uint16_val) { - json[attrid_str] = uint16_val; - } - } - break; - case 0x23: - { - uint32_t uint32_val = buf.get32(i); - i += 4; - if (0xFFFFFFFF != uint32_val) { - json[attrid_str] = uint32_val; - } - } - break; - - case 0x24: - case 0x25: - case 0x26: - case 0x27: - { - uint8_t len = attrtype - 0x1F; - - char hex[2*len+1]; - ToHex_P(buf.buf(i), len, hex, sizeof(hex)); - json[attrid_str] = hex; - i += len; - } - break; - case 0x28: - { - int8_t int8_val = buf.get8(i); - i += 1; - if (0x80 != int8_val) { - json[attrid_str] = int8_val; - } - } - break; - case 0x29: - { - int16_t int16_val = buf.get16(i); - i += 2; - if (0x8000 != int16_val) { - json[attrid_str] = int16_val; - } - } - break; - case 0x2B: - { - int32_t int32_val = buf.get32(i); - i += 4; - if (0x80000000 != int32_val) { - json[attrid_str] = int32_val; - } - } - break; - - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - { - uint8_t len = attrtype - 0x27; - - char hex[2*len+1]; - ToHex_P(buf.buf(i), len, hex, sizeof(hex)); - json[attrid_str] = hex; - i += len; - } - break; - - case 0x41: - case 0x42: - case 0x43: - case 0x44: - - { - bool parse_as_string = true; - uint32_t len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); - i += (attrtype <= 0x42) ? 1 : 2; - if (i + len > buf.len()) { - len = buf.len() - i; - } - - - if ((0x41 == attrtype) || (0x43 == attrtype)) { parse_as_string = false; } -# 318 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" - if (parse_as_string) { - char str[len+1]; - strncpy(str, buf.charptr(i), len); - str[len] = 0x00; - json[attrid_str] = str; - } else { - - char hex[2*len+1]; - ToHex_P(buf.buf(i), len, hex, sizeof(hex)); - json[attrid_str] = hex; - } - - i += len; - break; - } - i += buf.get8(i) + 1; - break; - - case 0x08: - case 0x18: - { - uint8_t uint8_val = buf.get8(i); - i += 1; - json[attrid_str] = uint8_val; - } - break; - case 0x09: - case 0x19: - { - uint16_t uint16_val = buf.get16(i); - i += 2; - json[attrid_str] = uint16_val; - } - break; - case 0x0B: - case 0x1B: - { - uint32_t uint32_val = buf.get32(i); - i += 4; - json[attrid_str] = uint32_val; - } - break; - - case 0x30: - case 0x31: - i += attrtype - 0x2F; - break; - - - case 0x39: - { - uint32_t uint32_val = buf.get32(i); - float * float_val = (float*) &uint32_val; - i += 4; - json[attrid_str] = *float_val; - } - break; - - case 0xE0: - case 0xE1: - case 0xE2: - i += 4; - break; - - case 0xE8: - case 0xE9: - i += 2; - break; - case 0xEA: - i += 4; - break; - - case 0xF0: - i += 8; - break; - case 0xF1: - i += 16; - break; - - - case 0x0A: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - i += attrtype - 0x07; - break; - - case 0x1A: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - i += attrtype - 0x17; - break; - - case 0x38: - i += 2; - break; - case 0x3A: - { - uint64_t uint64_val = buf.get64(i); - double * double_val = (double*) &uint64_val; - i += 8; - json[attrid_str] = *double_val; - } - break; - } - - - - - - - return i - offset; -} - - -void ZCLFrame::generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len) { - uint32_t suffix = 1; - - snprintf_P(key, key_len, PSTR("%04X/%04X"), cluster, attr); - while (json.containsKey(key)) { - suffix++; - snprintf_P(key, key_len, PSTR("%04X/%04X+%d"), cluster, attr, suffix); - } -} - - -void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - - while (len >= i + 3) { - uint16_t attrid = _payload.get16(i); - i += 2; - - char key[16]; - generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); - - - if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { - if (0x42 == _payload.get8(i)) { - _payload.set8(i, 0x41); - } - } - i += parseSingleAttribute(json, key, _payload, i, len); - } -} - - -void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - - while (len - i >= 4) { - uint16_t attrid = _payload.get16(i); - i += 2; - uint8_t status = _payload.get8(i++); - - if (0 == status) { - char key[16]; - generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); - - i += parseSingleAttribute(json, key, _payload, i, len); - } - } -} - - - - -void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - - char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X!%02X"), _cluster_id, _cmd_id); - - char hex_char[_payload.len()*2+2]; - ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - - json[attrid_str] = hex_char; -} - - - - -typedef int32_t (*Z_AttrConverter)(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -typedef struct Z_AttributeConverter { - uint16_t cluster; - uint16_t attribute; - const char * name; - Z_AttrConverter func; -} Z_AttributeConverter; - - -const Z_AttributeConverter Z_PostProcess[] PROGMEM = { - { 0x0000, 0x0000, "ZCLVersion", &Z_Copy }, - { 0x0000, 0x0001, "AppVersion", &Z_Copy }, - { 0x0000, 0x0002, "StackVersion", &Z_Copy }, - { 0x0000, 0x0003, "HWVersion", &Z_Copy }, - { 0x0000, 0x0004, "Manufacturer", &Z_ManufKeep }, - { 0x0000, 0x0005, D_JSON_MODEL D_JSON_ID, &Z_ModelKeep }, - { 0x0000, 0x0006, "DateCode", &Z_Copy }, - { 0x0000, 0x0007, "PowerSource", &Z_Copy }, - { 0x0000, 0x4000, "SWBuildID", &Z_Copy }, - { 0x0000, 0xFFFF, nullptr, &Z_Remove }, - - { 0x0000, 0xFF01, nullptr, &Z_AqaraSensor }, - - - { 0x0001, 0x0000, "MainsVoltage", &Z_Copy }, - { 0x0001, 0x0001, "MainsFrequency", &Z_Copy }, - { 0x0001, 0x0020, "BatteryVoltage", &Z_Copy }, - { 0x0001, 0x0021, "BatteryPercentageRemaining",&Z_Copy }, - - - { 0x0002, 0x0000, "CurrentTemperature", &Z_Copy }, - { 0x0002, 0x0001, "MinTempExperienced", &Z_Copy }, - { 0x0002, 0x0002, "MaxTempExperienced", &Z_Copy }, - { 0x0002, 0x0003, "OverTempTotalDwell", &Z_Copy }, - - - { 0x0006, 0x0000, "Power", &Z_Copy }, - { 0x0006, 0x8000, "Power", &Z_Copy }, - - - { 0x0007, 0x0000, "SwitchType", &Z_Copy }, - - - { 0x0008, 0x0000, "Dimmer", &Z_Copy }, -# 558 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" - { 0x0009, 0x0000, "AlarmCount", &Z_Copy }, - - { 0x000A, 0x0000, "Time", &Z_Copy }, - { 0x000A, 0x0001, "TimeStatus", &Z_Copy }, - { 0x000A, 0x0002, "TimeZone", &Z_Copy }, - { 0x000A, 0x0003, "DstStart", &Z_Copy }, - { 0x000A, 0x0004, "DstStart", &Z_Copy }, - { 0x000A, 0x0005, "DstShift", &Z_Copy }, - { 0x000A, 0x0006, "StandardTime", &Z_Copy }, - { 0x000A, 0x0007, "LocalTime", &Z_Copy }, - { 0x000A, 0x0008, "LastSetTime", &Z_Copy }, - { 0x000A, 0x0009, "ValidUntilTime", &Z_Copy }, - - { 0x000B, 0x0000, "LocationType", &Z_Copy }, - { 0x000B, 0x0000, "LocationMethod", &Z_Copy }, - { 0x000B, 0x0000, "LocationAge", &Z_Copy }, - { 0x000B, 0x0000, "QualityMeasure", &Z_Copy }, - { 0x000B, 0x0000, "NumberOfDevices", &Z_Copy }, - - { 0x000C, 0x0004, "ActiveText", &Z_Copy }, - { 0x000C, 0x001C, "Description", &Z_Copy }, - { 0x000C, 0x002E, "InactiveText", &Z_Copy }, - { 0x000C, 0x0041, "MaxPresentValue", &Z_Copy }, - { 0x000C, 0x0045, "MinPresentValue", &Z_Copy }, - { 0x000C, 0x0051, "OutOfService", &Z_Copy }, - { 0x000C, 0x0055, "AqaraRotate", &Z_Copy }, - { 0x000C, 0x0057, "PriorityArray", &Z_Copy }, - { 0x000C, 0x0067, "Reliability", &Z_Copy }, - { 0x000C, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x000C, 0x006A, "Resolution", &Z_Copy }, - { 0x000C, 0x006F, "StatusFlags", &Z_Copy }, - { 0x000C, 0x0075, "EngineeringUnits", &Z_Copy }, - { 0x000C, 0x0100, "ApplicationType", &Z_Copy }, - { 0x000C, 0xFF05, "Aqara_FF05", &Z_Copy }, - - { 0x0010, 0x0004, "ActiveText", &Z_Copy }, - { 0x0010, 0x001C, "Description", &Z_Copy }, - { 0x0010, 0x002E, "InactiveText", &Z_Copy }, - { 0x0010, 0x0042, "MinimumOffTime", &Z_Copy }, - { 0x0010, 0x0043, "MinimumOnTime", &Z_Copy }, - { 0x0010, 0x0051, "OutOfService", &Z_Copy }, - { 0x0010, 0x0054, "Polarity", &Z_Copy }, - { 0x0010, 0x0055, "PresentValue", &Z_Copy }, - { 0x0010, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0010, 0x0067, "Reliability", &Z_Copy }, - { 0x0010, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0010, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0010, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x0011, 0x0004, "ActiveText", &Z_Copy }, - { 0x0011, 0x001C, "Description", &Z_Copy }, - { 0x0011, 0x002E, "InactiveText", &Z_Copy }, - { 0x0011, 0x0042, "MinimumOffTime", &Z_Copy }, - { 0x0011, 0x0043, "MinimumOnTime", &Z_Copy }, - { 0x0011, 0x0051, "OutOfService", &Z_Copy }, - { 0x0011, 0x0055, "PresentValue", &Z_Copy }, - { 0x0011, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0011, 0x0067, "Reliability", &Z_Copy }, - { 0x0011, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0011, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0011, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x0012, 0x000E, "StateText", &Z_Copy }, - { 0x0012, 0x001C, "Description", &Z_Copy }, - { 0x0012, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0012, 0x0051, "OutOfService", &Z_Copy }, - { 0x0012, 0x0055, "PresentValue", &Z_AqaraCube }, - { 0x0012, 0x0067, "Reliability", &Z_Copy }, - { 0x0012, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0012, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x0013, 0x000E, "StateText", &Z_Copy }, - { 0x0013, 0x001C, "Description", &Z_Copy }, - { 0x0013, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0013, 0x0051, "OutOfService", &Z_Copy }, - { 0x0013, 0x0055, "PresentValue", &Z_Copy }, - { 0x0013, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0013, 0x0067, "Reliability", &Z_Copy }, - { 0x0013, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0013, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0013, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x0014, 0x000E, "StateText", &Z_Copy }, - { 0x0014, 0x001C, "Description", &Z_Copy }, - { 0x0014, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0014, 0x0051, "OutOfService", &Z_Copy }, - { 0x0014, 0x0055, "PresentValue", &Z_Copy }, - { 0x0014, 0x0067, "Reliability", &Z_Copy }, - { 0x0014, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0014, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0014, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x001A, 0x0000, "TotalProfileNum", &Z_Copy }, - { 0x001A, 0x0001, "MultipleScheduling", &Z_Copy }, - { 0x001A, 0x0002, "EnergyFormatting", &Z_Copy }, - { 0x001A, 0x0003, "EnergyRemote", &Z_Copy }, - { 0x001A, 0x0004, "ScheduleMode", &Z_Copy }, - - { 0x0020, 0x0000, "CheckinInterval", &Z_Copy }, - { 0x0020, 0x0001, "LongPollInterval", &Z_Copy }, - { 0x0020, 0x0002, "ShortPollInterval", &Z_Copy }, - { 0x0020, 0x0003, "FastPollTimeout", &Z_Copy }, - { 0x0020, 0x0004, "CheckinIntervalMin", &Z_Copy }, - { 0x0020, 0x0005, "LongPollIntervalMin", &Z_Copy }, - { 0x0020, 0x0006, "FastPollTimeoutMax", &Z_Copy }, - - { 0x0100, 0x0000, "PhysicalClosedLimit", &Z_Copy }, - { 0x0100, 0x0001, "MotorStepSize", &Z_Copy }, - { 0x0100, 0x0002, "Status", &Z_Copy }, - { 0x0100, 0x0010, "ClosedLimit", &Z_Copy }, - { 0x0100, 0x0011, "Mode", &Z_Copy }, - - { 0x0101, 0x0000, "LockState", &Z_Copy }, - { 0x0101, 0x0001, "LockType", &Z_Copy }, - { 0x0101, 0x0002, "ActuatorEnabled", &Z_Copy }, - { 0x0101, 0x0003, "DoorState", &Z_Copy }, - { 0x0101, 0x0004, "DoorOpenEvents", &Z_Copy }, - { 0x0101, 0x0005, "DoorClosedEvents", &Z_Copy }, - { 0x0101, 0x0006, "OpenPeriod", &Z_Copy }, - - { 0x0101, 0x0055, "AqaraVibrationMode", &Z_AqaraVibration }, - { 0x0101, 0x0503, "AqaraVibrationsOrAngle", &Z_Copy }, - { 0x0101, 0x0505, "AqaraVibration505", &Z_Copy }, - { 0x0101, 0x0508, "AqaraAccelerometer", &Z_AqaraVibration }, - - { 0x0102, 0x0000, "WindowCoveringType", &Z_Copy }, - { 0x0102, 0x0001, "PhysicalClosedLimitLift",&Z_Copy }, - { 0x0102, 0x0002, "PhysicalClosedLimitTilt",&Z_Copy }, - { 0x0102, 0x0003, "CurrentPositionLift", &Z_Copy }, - { 0x0102, 0x0004, "CurrentPositionTilt", &Z_Copy }, - { 0x0102, 0x0005, "NumberofActuationsLift",&Z_Copy }, - { 0x0102, 0x0006, "NumberofActuationsTilt",&Z_Copy }, - { 0x0102, 0x0007, "ConfigStatus", &Z_Copy }, - { 0x0102, 0x0008, "CurrentPositionLiftPercentage",&Z_Copy }, - { 0x0102, 0x0009, "CurrentPositionTiltPercentage",&Z_Copy }, - { 0x0102, 0x0010, "InstalledOpenLimitLift",&Z_Copy }, - { 0x0102, 0x0011, "InstalledClosedLimitLift",&Z_Copy }, - { 0x0102, 0x0012, "InstalledOpenLimitTilt", &Z_Copy }, - { 0x0102, 0x0013, "InstalledClosedLimitTilt", &Z_Copy }, - { 0x0102, 0x0014, "VelocityLift",&Z_Copy }, - { 0x0102, 0x0015, "AccelerationTimeLift",&Z_Copy }, - { 0x0102, 0x0016, "DecelerationTimeLift", &Z_Copy }, - { 0x0102, 0x0017, "Mode",&Z_Copy }, - { 0x0102, 0x0018, "IntermediateSetpointsLift",&Z_Copy }, - { 0x0102, 0x0019, "IntermediateSetpointsTilt",&Z_Copy }, - - - { 0x0300, 0x0000, "Hue", &Z_Copy }, - { 0x0300, 0x0001, "Sat", &Z_Copy }, - { 0x0300, 0x0002, "RemainingTime", &Z_Copy }, - { 0x0300, 0x0003, "X", &Z_Copy }, - { 0x0300, 0x0004, "Y", &Z_Copy }, - { 0x0300, 0x0005, "DriftCompensation", &Z_Copy }, - { 0x0300, 0x0006, "CompensationText", &Z_Copy }, - { 0x0300, 0x0007, "CT", &Z_Copy }, - { 0x0300, 0x0008, "ColorMode", &Z_Copy }, - { 0x0300, 0x0010, "NumberOfPrimaries", &Z_Copy }, - { 0x0300, 0x0011, "Primary1X", &Z_Copy }, - { 0x0300, 0x0012, "Primary1Y", &Z_Copy }, - { 0x0300, 0x0013, "Primary1Intensity", &Z_Copy }, - { 0x0300, 0x0015, "Primary2X", &Z_Copy }, - { 0x0300, 0x0016, "Primary2Y", &Z_Copy }, - { 0x0300, 0x0017, "Primary2Intensity", &Z_Copy }, - { 0x0300, 0x0019, "Primary3X", &Z_Copy }, - { 0x0300, 0x001A, "Primary3Y", &Z_Copy }, - { 0x0300, 0x001B, "Primary3Intensity", &Z_Copy }, - { 0x0300, 0x0030, "WhitePointX", &Z_Copy }, - { 0x0300, 0x0031, "WhitePointY", &Z_Copy }, - { 0x0300, 0x0032, "ColorPointRX", &Z_Copy }, - { 0x0300, 0x0033, "ColorPointRY", &Z_Copy }, - { 0x0300, 0x0034, "ColorPointRIntensity", &Z_Copy }, - { 0x0300, 0x0036, "ColorPointGX", &Z_Copy }, - { 0x0300, 0x0037, "ColorPointGY", &Z_Copy }, - { 0x0300, 0x0038, "ColorPointGIntensity", &Z_Copy }, - { 0x0300, 0x003A, "ColorPointBX", &Z_Copy }, - { 0x0300, 0x003B, "ColorPointBY", &Z_Copy }, - { 0x0300, 0x003C, "ColorPointBIntensity", &Z_Copy }, - - - { 0x0400, 0x0000, D_JSON_ILLUMINANCE, &Z_Copy }, - { 0x0400, 0x0001, "MinMeasuredValue", &Z_Copy }, - { 0x0400, 0x0002, "MaxMeasuredValue", &Z_Copy }, - { 0x0400, 0x0003, "Tolerance", &Z_Copy }, - { 0x0400, 0x0004, "LightSensorType", &Z_Copy }, - { 0x0400, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0401, 0x0000, "LevelStatus", &Z_Copy }, - { 0x0401, 0x0001, "LightSensorType", &Z_Copy }, - { 0x0401, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0402, 0x0000, D_JSON_TEMPERATURE, &Z_FloatDiv100 }, - { 0x0402, 0x0001, "MinMeasuredValue", &Z_FloatDiv100 }, - { 0x0402, 0x0002, "MaxMeasuredValue", &Z_FloatDiv100 }, - { 0x0402, 0x0003, "Tolerance", &Z_FloatDiv100 }, - { 0x0402, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0403, 0x0000, D_JSON_PRESSURE_UNIT, &Z_AddPressureUnit }, - { 0x0403, 0x0000, D_JSON_PRESSURE, &Z_Copy }, - { 0x0403, 0x0001, "MinMeasuredValue", &Z_Copy }, - { 0x0403, 0x0002, "MaxMeasuredValue", &Z_Copy }, - { 0x0403, 0x0003, "Tolerance", &Z_Copy }, - { 0x0403, 0x0010, "ScaledValue", &Z_Copy }, - { 0x0403, 0x0011, "MinScaledValue", &Z_Copy }, - { 0x0403, 0x0012, "MaxScaledValue", &Z_Copy }, - { 0x0403, 0x0013, "ScaledTolerance", &Z_Copy }, - { 0x0403, 0x0014, "Scale", &Z_Copy }, - { 0x0403, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0404, 0x0000, D_JSON_FLOWRATE, &Z_FloatDiv10 }, - { 0x0404, 0x0001, "MinMeasuredValue", &Z_Copy }, - { 0x0404, 0x0002, "MaxMeasuredValue", &Z_Copy }, - { 0x0404, 0x0003, "Tolerance", &Z_Copy }, - { 0x0404, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0405, 0x0000, D_JSON_HUMIDITY, &Z_FloatDiv100 }, - { 0x0405, 0x0001, "MinMeasuredValue", &Z_Copy }, - { 0x0405, 0x0002, "MaxMeasuredValue", &Z_Copy }, - { 0x0405, 0x0003, "Tolerance", &Z_Copy }, - { 0x0405, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0406, 0x0000, OCCUPANCY, &Z_Copy }, - { 0x0406, 0x0001, "OccupancySensorType", &Z_Copy }, - { 0x0406, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0B01, 0x0000, "CompanyName", &Z_Copy }, - { 0x0B01, 0x0001, "MeterTypeID", &Z_Copy }, - { 0x0B01, 0x0004, "DataQualityID", &Z_Copy }, - { 0x0B01, 0x0005, "CustomerName", &Z_Copy }, - { 0x0B01, 0x0006, "Model", &Z_Copy }, - { 0x0B01, 0x0007, "PartNumber", &Z_Copy }, - { 0x0B01, 0x000A, "SoftwareRevision", &Z_Copy }, - { 0x0B01, 0x000C, "POD", &Z_Copy }, - { 0x0B01, 0x000D, "AvailablePower", &Z_Copy }, - { 0x0B01, 0x000E, "PowerThreshold", &Z_Copy }, - - - { 0x0B05, 0x0000, "NumberOfResets", &Z_Copy }, - { 0x0B05, 0x0001, "PersistentMemoryWrites",&Z_Copy }, - { 0x0B05, 0x011C, "LastMessageLQI", &Z_Copy }, - { 0x0B05, 0x011D, "LastMessageRSSI", &Z_Copy }, - -}; - - - -int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - zigbee_devices.setManufId(shortaddr, value.as()); - return 1; -} - -int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - zigbee_devices.setModelId(shortaddr, value.as()); - return 1; -} - - - -int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - return 1; -} - - -int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - return 1; -} - - -int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = F(D_UNIT_PRESSURE); - return 0; -} - - -int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = ((float)value) / 100.0f; - return 1; -} - -int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = ((float)value) / 10.0f; - return 1; -} - - -int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); - json[F(OCCUPANCY)] = 0; - zigbee_devices.jsonPublishNow(shortaddr, json); -} - - -int32_t Z_AqaraCube(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - int32_t val = value; - const __FlashStringHelper *aqara_cube = F("AqaraCube"); - const __FlashStringHelper *aqara_cube_side = F("AqaraCubeSide"); - const __FlashStringHelper *aqara_cube_from_side = F("AqaraCubeFromSide"); - - switch (val) { - case 0: - json[aqara_cube] = F("shake"); - break; - case 2: - json[aqara_cube] = F("wakeup"); - break; - case 3: - json[aqara_cube] = F("fall"); - break; - case 64 ... 127: - json[aqara_cube] = F("flip90"); - json[aqara_cube_side] = val % 8; - json[aqara_cube_from_side] = (val - 64) / 8; - break; - case 128 ... 132: - json[aqara_cube] = F("flip180"); - json[aqara_cube_side] = val - 128; - break; - case 256 ... 261: - json[aqara_cube] = F("slide"); - json[aqara_cube_side] = val - 256; - break; - case 512 ... 517: - json[aqara_cube] = F("tap"); - json[aqara_cube_side] = val - 512; - break; - } -# 915 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" - return 1; -} - - -int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - - switch (attr) { - case 0x0055: - { - int32_t ivalue = value; - const __FlashStringHelper * svalue; - switch (ivalue) { - case 1: svalue = F("vibrate"); break; - case 2: svalue = F("tilt"); break; - case 3: svalue = F("drop"); break; - default: svalue = F("unknown"); break; - } - json[new_name] = svalue; - } - break; - - - - - case 0x0508: - { - - - String hex = value; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - int16_t x, y, z; - z = buf2.get16(0); - y = buf2.get16(2); - x = buf2.get16(4); - JsonArray& xyz = json.createNestedArray(new_name); - xyz.add(x); - xyz.add(y); - xyz.add(z); - - float X = x; - float Y = y; - float Z = z; - int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; - int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; - int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; - - - - JsonArray& angles = json.createNestedArray(F("AqaraAngles")); - angles.add(Angle_X); - angles.add(Angle_Y); - angles.add(Angle_Z); - } - break; - } - return 1; -} - -int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - String hex = value; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint32_t i = 0; - uint32_t len = buf2.len(); - char tmp[] = "tmp"; - - JsonVariant sub_value; - - while (len - i >= 2) { - uint8_t attrid = buf2.get8(i++); - - i += parseSingleAttribute(json, tmp, buf2, i, len); - float val = json[tmp]; - json.remove(tmp); - if (0x01 == attrid) { - json[F(D_JSON_VOLTAGE)] = val / 1000.0f; - json[F("Battery")] = toPercentageCR2032(val); - } else if (0 == zcl->getManufCode()) { - - if (0x64 == attrid) { - json[F(D_JSON_TEMPERATURE)] = val / 100.0f; - } else if (0x65 == attrid) { - json[F(D_JSON_HUMIDITY)] = val / 100.0f; - } else if (0x66 == attrid) { - json[F(D_JSON_PRESSURE)] = val / 100.0f; - json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); - } else if (0x01 == attrid) { - json[F(D_JSON_VOLTAGE)] = val / 1000.0f; - json[F("Battery")] = toPercentageCR2032(val); - } - } else if (0x115F == zcl->getManufCode()) { - - json[F("AqaraUnknown")] = val; - } - } - return 1; -} - - -void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { - - for (auto kv : json) { - String key_string = kv.key; - const char * key = key_string.c_str(); - JsonVariant& value = kv.value; - - char * delimiter = strchr(key, '/'); - char * delimiter2 = strchr(key, '+'); - if (delimiter) { - uint16_t attribute; - uint16_t suffix = 1; - uint16_t cluster = strtoul(key, &delimiter, 16); - if (!delimiter2) { - attribute = strtoul(delimiter+1, nullptr, 16); - } else { - attribute = strtoul(delimiter+1, &delimiter2, 16); - suffix = strtoul(delimiter2+1, nullptr, 10); - } - - - for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - uint16_t conv_cluster = pgm_read_word(&converter->cluster); - uint16_t conv_attribute = pgm_read_word(&converter->attribute); - - if ((conv_cluster == cluster) && - ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { - String new_name_str = converter->name; - if (suffix > 1) { new_name_str += suffix; } - int32_t drop = (*converter->func)(this, shortaddr, json, key, value, new_name_str, conv_cluster, conv_attribute); - if (drop) { - json.remove(key); - } - - } - } - } - } -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" -#ifdef USE_ZIGBEE - - -typedef struct Z_CommandConverter { - const char * tasmota_cmd; - const char * zcl_cmd; -} Z_CommandConverter; - - -const Z_CommandConverter Z_Commands[] = { - { "Power", "0006!xx" }, - { "Dimmer", "0008!04/xx0A00" }, - { "Dimmer+", "0008!06/001902" }, - { "Dimmer-", "0008!06/011902" }, - { "DimmerStop", "0008!03" }, - { "ResetAlarm", "0009!00/xxyyyy" }, - { "ResetAllAlarms","0009!01" }, - { "Hue", "0300!00/xx000A00" }, - { "Sat", "0300!03/xx0A00" }, - { "HueSat", "0300!06/xxyy0A00" }, - { "Color", "0300!07/xxxxyyyy0A00" }, - { "CT", "0300!0A/xxxx0A00" }, - { "Shutter", "0102!xx" }, - { "ShutterOpen", "0102!00" }, - { "ShutterClose", "0102!01" }, - { "ShutterStop", "0102!02" }, - { "ShutterLift", "0102!05xx" }, - { "ShutterTilt", "0102!08xx" }, -}; - -#define ZLE(x) ((x) & 0xFF), ((x) >> 8) - - -const uint8_t CLUSTER_0006[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007) }; - -int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { - size_t attrs_len = 0; - const uint8_t* attrs = nullptr; - - switch (cluster) { - case 0x0006: - attrs = CLUSTER_0006; - attrs_len = sizeof(CLUSTER_0006); - break; - case 0x0008: - attrs = CLUSTER_0008; - attrs_len = sizeof(CLUSTER_0008); - break; - case 0x0009: - attrs = CLUSTER_0009; - attrs_len = sizeof(CLUSTER_0009); - break; - case 0x0300: - attrs = CLUSTER_0300; - attrs_len = sizeof(CLUSTER_0300); - break; - } - if (attrs) { - ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false ); - } -} - - - -void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint) { - uint32_t wait_ms = 0; - - switch (cluster) { - case 0x0006: - case 0x0009: - wait_ms = 200; - break; - case 0x0008: - case 0x0300: - wait_ms = 1050; - break; - case 0x0102: - wait_ms = 10000; - break; - } - if (wait_ms) { - zigbee_devices.setTimer(shortaddr, wait_ms, cluster, endpoint, 0 , &Z_ReadAttrCallback); - } -} - -const __FlashStringHelper* zigbeeFindCommand(const char *command) { - char parm_uc[16]; - for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { - const Z_CommandConverter *conv = &Z_Commands[i]; - if (0 == strcasecmp_P(command, conv->tasmota_cmd)) { - return (const __FlashStringHelper*) conv->zcl_cmd; - } - } - - return nullptr; -} - -inline bool isXYZ(char c) { - return (c >= 'x') && (c <= 'z'); -} - - -inline char hexDigit(uint32_t h) { - uint32_t nybble = h & 0x0F; - return (nybble > 9) ? 'A' - 10 + nybble : '0' + nybble; -} - - -String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z) { - size_t len = strlen_P(zcl_cmd_P); - char zcl_cmd[len+1]; - strcpy_P(zcl_cmd, zcl_cmd_P); - - char *p = zcl_cmd; - while (*p) { - if (isXYZ(*p) && (*p == *(p+1))) { - uint8_t val; - switch (*p) { - case 'x': - val = x & 0xFF; - x = x >> 8; - break; - case 'y': - val = y & 0xFF; - y = y >> 8; - break; - case 'z': - val = z & 0xFF; - z = z >> 8; - break; - } - *p = hexDigit(val >> 4); - *(p+1) = hexDigit(val); - p++; - } - p++; - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SendZCLCommand_P: zcl_cmd = %s"), zcl_cmd); - - return String(zcl_cmd); -} - -const char kZ_Alias[] PROGMEM = "OFF|" D_OFF "|" D_FALSE "|" D_STOP "|" "OPEN" "|" - "ON|" D_ON "|" D_TRUE "|" D_START "|" "CLOSE" "|" - "TOGGLE|" D_TOGGLE "|" - "ALL" ; - -const uint8_t kZ_Numbers[] PROGMEM = { 0,0,0,0,0, - 1,1,1,1,1, - 2,2, - 255 }; - - -uint32_t ZigbeeAliasOrNumber(const char *state_text) { - char command[16]; - int state_number = GetCommandCode(command, sizeof(command), state_text, kZ_Alias); - if (state_number >= 0) { - - return pgm_read_byte(kZ_Numbers + state_number); - } else { - - return strtoul(state_text, nullptr, 0); - } -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -#ifdef USE_ZIGBEE - - - -const uint8_t ZIGBEE_STATUS_OK = 0; -const uint8_t ZIGBEE_STATUS_BOOT = 1; -const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; -const uint8_t ZIGBEE_STATUS_STARTING = 3; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_CLOSE = 20; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_60 = 21; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_XX = 22; -const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; -const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; -const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; -const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; -const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; -const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; -const uint8_t ZIGBEE_STATUS_CC_INFO = 51; -const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; -const uint8_t ZIGBEE_STATUS_ABORT = 99; - -typedef int32_t (*ZB_Func)(uint8_t value); -typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, const class SBuffer &buf); - -typedef union Zigbee_Instruction { - struct { - uint8_t i; - uint8_t d8; - uint16_t d16; - } i; - const void *p; - - - -} Zigbee_Instruction; - - - - -typedef struct Zigbee_Instruction_Type { - uint8_t instr; - uint8_t data; -} Zigbee_Instruction_Type; - -enum Zigbee_StateMachine_Instruction_Set { - - ZGB_INSTR_4_BYTES = 0, - ZGB_INSTR_NOOP = 0, - ZGB_INSTR_LABEL, - ZGB_INSTR_GOTO, - ZGB_INSTR_ON_ERROR_GOTO, - ZGB_INSTR_ON_TIMEOUT_GOTO, - ZGB_INSTR_WAIT, - ZGB_INSTR_WAIT_FOREVER, - ZGB_INSTR_STOP, - - - ZGB_INSTR_8_BYTES = 0x80, - ZGB_INSTR_CALL = 0x80, - ZGB_INSTR_LOG, - ZGB_INSTR_MQTT_STATE, - ZGB_INSTR_SEND, - ZGB_INSTR_WAIT_UNTIL, - ZGB_INSTR_WAIT_RECV, - ZGB_ON_RECV_UNEXPECTED, - - - ZGB_INSTR_12_BYTES = 0xF0, - ZGB_INSTR_WAIT_RECV_CALL, -}; - -#define ZI_NOOP() { .i = { ZGB_INSTR_NOOP, 0x00, 0x0000} }, -#define ZI_LABEL(x) { .i = { ZGB_INSTR_LABEL, (x), 0x0000} }, -#define ZI_GOTO(x) { .i = { ZGB_INSTR_GOTO, (x), 0x0000} }, -#define ZI_ON_ERROR_GOTO(x) { .i = { ZGB_INSTR_ON_ERROR_GOTO, (x), 0x0000} }, -#define ZI_ON_TIMEOUT_GOTO(x) { .i = { ZGB_INSTR_ON_TIMEOUT_GOTO, (x), 0x0000} }, -#define ZI_WAIT(x) { .i = { ZGB_INSTR_WAIT, 0x00, (x)} }, -#define ZI_WAIT_FOREVER() { .i = { ZGB_INSTR_WAIT_FOREVER, 0x00, 0x0000} }, -#define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, - -#define ZI_CALL(f,x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, -#define ZI_LOG(x,m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, -#define ZI_MQTT_STATE(x,m) { .i = { ZGB_INSTR_MQTT_STATE, (x), 0x0000 } }, { .p = ((const void*)(m)) }, -#define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, -#define ZI_SEND(m) { .i = { ZGB_INSTR_SEND, sizeof(m), 0x0000} }, { .p = (const void*)(m) }, -#define ZI_WAIT_RECV(x,m) { .i = { ZGB_INSTR_WAIT_RECV, sizeof(m), (x)} }, { .p = (const void*)(m) }, -#define ZI_WAIT_UNTIL(x,m) { .i = { ZGB_INSTR_WAIT_UNTIL, sizeof(m), (x)} }, { .p = (const void*)(m) }, -#define ZI_WAIT_RECV_FUNC(x,m,f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, - - -const uint8_t ZIGBEE_LABEL_START = 10; -const uint8_t ZIGBEE_LABEL_READY = 20; -const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; - -const uint8_t ZIGBEE_LABEL_ABORT = 99; -const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; - -struct ZigbeeStatus { - bool active = true; - bool state_machine = false; - bool state_waiting = false; - bool state_no_timeout = false; - bool ready = false; - uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; - uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; - int16_t pc = 0; - uint32_t next_timeout = 0; - - uint8_t *recv_filter = nullptr; - bool recv_until = false; - size_t recv_filter_len = 0; - ZB_RecvMsgFunc recv_func = nullptr; - ZB_RecvMsgFunc recv_unexpected = nullptr; - - bool init_phase = true; -}; -struct ZigbeeStatus zigbee; - -SBuffer *zigbee_buffer = nullptr; - - - - - -#define Z_B0(a) (uint8_t)( ((a) ) & 0xFF ) -#define Z_B1(a) (uint8_t)( ((a) >> 8) & 0xFF ) -#define Z_B2(a) (uint8_t)( ((a) >> 16) & 0xFF ) -#define Z_B3(a) (uint8_t)( ((a) >> 24) & 0xFF ) -#define Z_B4(a) (uint8_t)( ((a) >> 32) & 0xFF ) -#define Z_B5(a) (uint8_t)( ((a) >> 40) & 0xFF ) -#define Z_B6(a) (uint8_t)( ((a) >> 48) & 0xFF ) -#define Z_B7(a) (uint8_t)( ((a) >> 56) & 0xFF ) - -#define ZBM(n,x...) const uint8_t n[] PROGMEM = { x }; - -#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) - - - -ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) -ZBM(ZBR_RESET, Z_AREQ | Z_SYS, SYS_RESET_IND ) - -ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) -ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) - - -ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 ) -ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_Success, 0x01 , 0x55) - - -ZBM(ZBS_PAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PANID ) -ZBM(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PANID, 0x02 , - Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) - -ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) -ZBM(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_EXTENDED_PAN_ID, - 0x08 , - Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), - Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID), - ) - -ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) -ZBM(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_CHANLIST, - 0x04 , - Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), - ) - -ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) -ZBM(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEY, - 0x10 , - Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), - Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), - Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), - Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), - - ) - -ZBM(ZBS_PFGKEN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEYS_ENABLE ) -ZBM(ZBR_PFGKEN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEYS_ENABLE, - 0x01 , 0x00 ) - - - -ZBM(ZBR_W_OK, Z_SRSP | Z_SAPI, SAPI_WRITE_CONFIGURATION, Z_Success ) -ZBM(ZBR_WNV_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_WRITE, Z_Success ) - - -ZBM(ZBS_FACTRES, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x02 ) - -ZBM(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) - -ZBM(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , - Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), - Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID) - ) - -ZBM(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , - Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), - ) - -ZBM(ZBS_W_LOGTYP, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x00 ) - -ZBM(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, - 0x10 , - Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), - Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), - Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), - Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), - - ) - -ZBM(ZBS_W_PFGKEN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEYS_ENABLE, 0x01 , 0x00 ) - -ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_START), Z_B1(CONF_TCLK_TABLE_START), - 0x00 , 0x20 , - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, - 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - -ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_ZDO_DIRECT_CB, 0x01 , 0x01 ) - -ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, - 0x01, 0x00 , 0x01 , 0x00 ) - - -ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) - - -ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), - 0x00 , 0x01 , 0x55 ) - -ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 ) -ZBM(ZBR_STARTUPFROMAPP, Z_SRSP | Z_ZDO, ZDO_STARTUP_FROM_APP ) -ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) - -ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) -ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_Success ) -# 271 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -ZBM(ZBS_ZDO_NODEDESCREQ, Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, 0x00, 0x00 , 0x00, 0x00 ) -ZBM(ZBR_ZDO_NODEDESCREQ, Z_SRSP | Z_ZDO, ZDO_NODE_DESC_REQ, Z_Success ) - -ZBM(AREQ_ZDO_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) -# 289 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) -ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_Success) -ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, - 0x00, 0x00 , 0x00 ) -ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, - 0x00, 0x00 , 0x02 , 0x0B, 0x01 ) - - -ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , 0x00 , - 0x00 , 0x00 ) -ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_Success) -ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , 0x00 , - 0x00 , 0x00 ) - -ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 , - 0x00, 0x00 , 0x00 , 0x00 ) -ZBM(ZBS_PERMITJOINREQ_OPEN_60, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , - 0xFC, 0xFF , 60 , 0x00 ) -ZBM(ZBS_PERMITJOINREQ_OPEN_XX, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , - 0xFC, 0xFF , 0xFF , 0x00 ) -ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_Success) -ZBM(ZBR_PERMITJOIN_AREQ_CLOSE, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0x00 ) -ZBM(ZBR_PERMITJOIN_AREQ_OPEN_60, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 60 ) -ZBM(ZBR_PERMITJOIN_AREQ_OPEN_FF, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0xFF ) -ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 , Z_Success ) - -static const Zigbee_Instruction zb_prog[] PROGMEM = { - ZI_LABEL(0) - ZI_NOOP() - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) - ZI_WAIT(10500) - ZI_ON_ERROR_GOTO(50) - - - - ZI_SEND(ZBS_RESET) - ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &Z_Reboot) - ZI_WAIT(100) - ZI_LOG(LOG_LEVEL_DEBUG, D_LOG_ZIGBEE "checking device configuration") - ZI_SEND(ZBS_ZNPHC) - ZI_WAIT_RECV(2000, ZBR_ZNPHC) - ZI_SEND(ZBS_VERSION) - ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) - ZI_SEND(ZBS_PAN) - ZI_WAIT_RECV(1000, ZBR_PAN) - ZI_SEND(ZBS_EXTPAN) - ZI_WAIT_RECV(1000, ZBR_EXTPAN) - ZI_SEND(ZBS_CHANN) - ZI_WAIT_RECV(1000, ZBR_CHANN) - ZI_SEND(ZBS_PFGK) - ZI_WAIT_RECV(1000, ZBR_PFGK) - ZI_SEND(ZBS_PFGKEN) - ZI_WAIT_RECV(1000, ZBR_PFGKEN) - - - - ZI_LABEL(ZIGBEE_LABEL_START) - ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, "Configured, starting coordinator") - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - - -ZI_SEND(ZBS_STARTUPFROMAPP) - ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) - ZI_WAIT_UNTIL(10000, AREQ_STARTUPFROMAPP) - ZI_SEND(ZBS_GETDEVICEINFO) - ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) - - ZI_SEND(ZBS_ZDO_NODEDESCREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) - ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP) - ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) - ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE) - ZI_SEND(ZBS_AF_REGISTER01) - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - ZI_SEND(ZBS_AF_REGISTER0B) - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - - - ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) - ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_OK) - ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) - - - - - - - ZI_LABEL(ZIGBEE_LABEL_READY) - ZI_MQTT_STATE(ZIGBEE_STATUS_OK, "Started") - ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "Zigbee started") - ZI_CALL(&Z_State_Ready, 1) - ZI_CALL(&Z_Load_Devices, 0) - ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) - ZI_WAIT_FOREVER() - ZI_GOTO(ZIGBEE_LABEL_READY) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE) - - ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60) - - ZI_SEND(ZBS_PERMITJOINREQ_OPEN_60) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX) - - ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(50) - ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, "Reseting configuration") - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_SEND(ZBS_FACTRES) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_RESET) - ZI_WAIT_RECV(5000, ZBR_RESET) - ZI_SEND(ZBS_W_PAN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_EXTPAN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_CHANN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_LOGTYP) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_PFGK) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_PFGKEN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_WNV_SECMODE) - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - ZI_SEND(ZBS_W_ZDODCB) - ZI_WAIT_RECV(1000, ZBR_W_OK) - - ZI_SEND(ZBS_WNV_INITZNPHC) - ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite) - ZI_SEND(ZBS_WNV_ZNPHC) - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - - - ZI_GOTO(ZIGBEE_LABEL_START) - - ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) - ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, "Only ZNP 1.2 is currently supported") - ZI_GOTO(ZIGBEE_LABEL_ABORT) - - ZI_LABEL(ZIGBEE_LABEL_ABORT) - ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, "Abort") - ZI_LOG(LOG_LEVEL_ERROR, D_LOG_ZIGBEE "Abort") - ZI_STOP(ZIGBEE_LABEL_ABORT) -}; - -uint8_t ZigbeeGetInstructionSize(uint8_t instr) { - if (instr >= ZGB_INSTR_12_BYTES) { - return 3; - } else if (instr >= ZGB_INSTR_8_BYTES) { - return 2; - } else { - return 1; - } -} - -void ZigbeeGotoLabel(uint8_t label) { - - uint16_t goto_pc = 0xFFFF; - uint8_t cur_instr = 0; - uint8_t cur_d8 = 0; - uint8_t cur_instr_len = 1; - - for (uint32_t i = 0; i < sizeof(zb_prog)/sizeof(zb_prog[0]); i += cur_instr_len) { - const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; - cur_instr = pgm_read_byte(&cur_instr_line->i.i); - cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); - - - if (ZGB_INSTR_LABEL == cur_instr) { - - if (label == cur_d8) { - - zigbee.pc = i; - zigbee.state_machine = true; - zigbee.state_waiting = false; - return; - } - } - - cur_instr_len = ZigbeeGetInstructionSize(cur_instr); - } - - - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Goto label not found, label=%d pc=%d"), label, zigbee.pc); - if (ZIGBEE_LABEL_ABORT != label) { - - ZigbeeGotoLabel(ZIGBEE_LABEL_ABORT); - } else { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Label Abort (%d) not present, aborting Zigbee"), ZIGBEE_LABEL_ABORT); - zigbee.state_machine = false; - zigbee.active = false; - } -} - -void ZigbeeStateMachine_Run(void) { - uint8_t cur_instr = 0; - uint8_t cur_d8 = 0; - uint16_t cur_d16 = 0; - const void* cur_ptr1 = nullptr; - const void* cur_ptr2 = nullptr; - uint32_t now = millis(); - - if (zigbee.state_waiting) { - - if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { - - if (!zigbee.state_no_timeout) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "timeout, goto label %d"), zigbee.on_timeout_goto); - ZigbeeGotoLabel(zigbee.on_timeout_goto); - } else { - zigbee.state_waiting = false; - } - } - } - - while ((zigbee.state_machine) && (!zigbee.state_waiting)) { - - zigbee.recv_filter = nullptr; - zigbee.recv_func = nullptr; - zigbee.recv_until = false; - zigbee.state_no_timeout = false; - - if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Invalid pc: %d, aborting"), zigbee.pc); - zigbee.pc = -1; - } - if (zigbee.pc < 0) { - zigbee.state_machine = false; - return; - } - - - - const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; - cur_instr = pgm_read_byte(&cur_instr_line->i.i); - cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); - cur_d16 = pgm_read_word(&cur_instr_line->i.d16); - if (cur_instr >= ZGB_INSTR_8_BYTES) { - cur_instr_line++; - cur_ptr1 = cur_instr_line->p; - } - if (cur_instr >= ZGB_INSTR_12_BYTES) { - cur_instr_line++; - cur_ptr2 = cur_instr_line->p; - } - - zigbee.pc += ZigbeeGetInstructionSize(cur_instr); - - switch (cur_instr) { - case ZGB_INSTR_NOOP: - case ZGB_INSTR_LABEL: - break; - case ZGB_INSTR_GOTO: - ZigbeeGotoLabel(cur_d8); - break; - case ZGB_INSTR_ON_ERROR_GOTO: - zigbee.on_error_goto = cur_d8; - break; - case ZGB_INSTR_ON_TIMEOUT_GOTO: - zigbee.on_timeout_goto = cur_d8; - break; - case ZGB_INSTR_WAIT: - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - zigbee.state_no_timeout = true; - break; - case ZGB_INSTR_WAIT_FOREVER: - zigbee.next_timeout = 0; - zigbee.state_waiting = true; - - break; - case ZGB_INSTR_STOP: - zigbee.state_machine = false; - if (cur_d8) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Stopping (%d)"), cur_d8); - } - break; - case ZGB_INSTR_CALL: - if (cur_ptr1) { - uint32_t res; - res = (*((ZB_Func)cur_ptr1))(cur_d8); - if (res > 0) { - ZigbeeGotoLabel(res); - continue; - } else if (res == 0) { - - } else if (res == -1) { - - } else { - ZigbeeGotoLabel(zigbee.on_error_goto); - continue; - } - } - break; - case ZGB_INSTR_LOG: - AddLog_P(cur_d8, (char*) cur_ptr1); - break; - case ZGB_INSTR_MQTT_STATE: - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":%d,\"Message\":\"%s\"}}"), - cur_d8, (char*) cur_ptr1); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - break; - case ZGB_INSTR_SEND: - ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 ); - break; - case ZGB_INSTR_WAIT_UNTIL: - zigbee.recv_until = true; - case ZGB_INSTR_WAIT_RECV: - zigbee.recv_filter = (uint8_t *) cur_ptr1; - zigbee.recv_filter_len = cur_d8; - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - break; - case ZGB_ON_RECV_UNEXPECTED: - zigbee.recv_unexpected = (ZB_RecvMsgFunc) cur_ptr1; - break; - case ZGB_INSTR_WAIT_RECV_CALL: - zigbee.recv_filter = (uint8_t *) cur_ptr1; - zigbee.recv_filter_len = cur_d8; - zigbee.recv_func = (ZB_RecvMsgFunc) cur_ptr2; - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - break; - } - } -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -#ifdef USE_ZIGBEE - -int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { - - - - - - - - Z_IEEEAddress long_adr = buf.get64(3); - Z_ShortAddress short_adr = buf.get16(11); - uint8_t device_type = buf.get8(13); - uint8_t device_state = buf.get8(14); - uint8_t device_associated = buf.get8(15); - - - localIEEEAddr = long_adr; - - char hex[20]; - Uint64toHex(long_adr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"DeviceType\":%d,\"DeviceState\":%d" - ",\"NumAssocDevices\":%d"), - ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, - device_associated); - - if (device_associated > 0) { - uint idx = 16; - ResponseAppend_P(PSTR(",\"AssocDevicesList\":[")); - for (uint32_t i = 0; i < device_associated; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(idx)); - idx += 2; - } - ResponseAppend_P(PSTR("]")); - } - - ResponseJsonEnd(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - - return res; -} - -int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { - - - - uint8_t status = buf.get8(2); - if ((0x00 == status) || (0x09 == status)) { - return 0; - } else { - return -2; - } -} - -const char Z_RebootReason[] PROGMEM = "Power-up|External|Watchdog"; - -int32_t Z_Reboot(int32_t res, class SBuffer &buf) { - - - - uint8_t reason = buf.get8(2); - uint8_t transport_rev = buf.get8(3); - uint8_t product_id = buf.get8(4); - uint8_t major_rel = buf.get8(5); - uint8_t minor_rel = buf.get8(6); - uint8_t hw_rev = buf.get8(7); - char reason_str[12]; - - if (reason > 3) { reason = 3; } - GetTextIndexed(reason_str, sizeof(reason_str), reason, Z_RebootReason); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Message\":\"%s\",\"RestartReason\":\"%s\"" - ",\"MajorRel\":%d,\"MinorRel\":%d}}"), - ZIGBEE_STATUS_BOOT, "CC2530 booted", reason_str, - major_rel, minor_rel); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - - if ((0x02 == major_rel) && (0x06 == minor_rel)) { - return 0; - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; - } -} - -int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { -# 122 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" - uint8_t major_rel = buf.get8(4); - uint8_t minor_rel = buf.get8(5); - uint8_t maint_rel = buf.get8(6); - uint32_t revision = buf.get32(7); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" - ",\"MaintRel\":%d,\"Revision\":%d}}"), - ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, - maint_rel, revision); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - - if ((0x02 == major_rel) && (0x06 == minor_rel)) { - return 0; - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; - } -} - -bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { - if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && - (pgm_read_byte(&match[1]) == buf.get8(1)) ) { - return true; - } else { - return false; - } -} - -int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { - - uint8_t duration = buf.get8(2); - uint8_t status_code; - const char* message; - - if (0xFF == duration) { - status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_XX; - message = PSTR("Enable Pairing mode until next boot"); - } else if (duration > 0) { - status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_60; - message = PSTR("Enable Pairing mode for %d seconds"); - } else { - status_code = ZIGBEE_STATUS_PERMITJOIN_CLOSE; - message = PSTR("Disable Pairing mode"); - } - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Message\":\""), - status_code); - ResponseAppend_P(message, duration); - ResponseAppend_P(PSTR("\"}}")); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - return -1; -} - - -void Z_SendActiveEpReq(uint16_t shortaddr) { - uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - - uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - - ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); - -} - - -void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint) { - uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), - endpoint }; - - ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); -} - -const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" }; -int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { - - Z_ShortAddress srcAddr = buf.get16(2); - uint8_t status = buf.get8(4); - Z_ShortAddress nwkAddr = buf.get16(5); - uint8_t logicalType = buf.get8(7); - uint8_t apsFlags = buf.get8(8); - uint8_t MACCapabilityFlags = buf.get8(9); - uint16_t manufacturerCapabilities = buf.get16(10); - uint8_t maxBufferSize = buf.get8(12); - uint16_t maxInTransferSize = buf.get16(13); - uint16_t serverMask = buf.get16(15); - uint16_t maxOutTransferSize = buf.get16(17); - uint8_t descriptorCapabilities = buf.get8(19); - - if (0 == status) { - zigbee_devices.updateLastSeen(nwkAddr); - - uint8_t deviceType = logicalType & 0x7; - if (deviceType > 3) { deviceType = 3; } - bool complexDescriptorAvailable = (logicalType & 0x08) ? 1 : 0; - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"NodeType\":\"%s\",\"ComplexDesc\":%s}}"), - ZIGBEE_STATUS_NODE_DESC, Z_DeviceType[deviceType], - complexDescriptorAvailable ? "true" : "false" - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - } - - return -1; -} - -int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { - - Z_ShortAddress srcAddr = buf.get16(2); - uint8_t status = buf.get8(4); - Z_ShortAddress nwkAddr = buf.get16(5); - uint8_t activeEpCount = buf.get8(7); - uint8_t* activeEpList = (uint8_t*) buf.charptr(8); - - - for (uint32_t i = 0; i < activeEpCount; i++) { - zigbee_devices.addEndoint(nwkAddr, activeEpList[i]); - } - - for (uint32_t i = 0; i < activeEpCount; i++) { - Z_SendSimpleDescReq(nwkAddr, activeEpList[i]); - } - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"ActiveEndpoints\":["), - ZIGBEE_STATUS_ACTIVE_EP); - for (uint32_t i = 0; i < activeEpCount; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%02X\""), activeEpList[i]); - } - ResponseAppend_P(PSTR("]}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - return -1; -} - -void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusterid, uint8_t transacid) { - SBuffer buf(100); - buf.add8(Z_SREQ | Z_AF); - buf.add8(AF_DATA_REQUEST); - buf.add16(shortaddr); - buf.add8(endpoint); - buf.add8(0x01); - buf.add16(clusterid); - buf.add8(transacid); - buf.add8(0x30); - buf.add8(0x1E); - - buf.add8(3 + 2*sizeof(uint16_t)); - buf.add8(0x00); - buf.add8(transacid); - buf.add8(ZCL_READ_ATTRIBUTES); - buf.add16(0x0004); - buf.add16(0x0005); - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -} - - -int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { - - Z_ShortAddress srcAddr = buf.get16(2); - uint8_t status = buf.get8(4); - Z_ShortAddress nwkAddr = buf.get16(5); - uint8_t lenDescriptor = buf.get8(7); - uint8_t endpoint = buf.get8(8); - uint16_t profileId = buf.get16(9); - uint16_t deviceId = buf.get16(11); - uint8_t deviceVersion = buf.get8(13); - uint8_t numInCluster = buf.get8(14); - uint8_t numOutCluster = buf.get8(15 + numInCluster*2); - - if (0 == status) { - zigbee_devices.addEndointProfile(nwkAddr, endpoint, profileId); - for (uint32_t i = 0; i < numInCluster; i++) { - zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(15 + i*2), false); - } - for (uint32_t i = 0; i < numOutCluster; i++) { - zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(16 + numInCluster*2 + i*2), true); - } - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Endpoint\":\"0x%02X\"" - ",\"ProfileId\":\"0x%04X\",\"DeviceId\":\"0x%04X\",\"DeviceVersion\":%d" - "\"InClusters\":["), - ZIGBEE_STATUS_SIMPLE_DESC, endpoint, - profileId, deviceId, deviceVersion); - for (uint32_t i = 0; i < numInCluster; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(15 + i*2)); - } - ResponseAppend_P(PSTR("],\"OutClusters\":[")); - for (uint32_t i = 0; i < numOutCluster; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(16 + numInCluster*2 + i*2)); - } - ResponseAppend_P(PSTR("]}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - - uint8_t cluster = zigbee_devices.findClusterEndpointIn(nwkAddr, 0x0000); - if (cluster) { - Z_SendAFInfoRequest(nwkAddr, cluster, 0x0000, 0x01); - } - } - return -1; -} - -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { - Z_ShortAddress srcAddr = buf.get16(2); - Z_ShortAddress nwkAddr = buf.get16(4); - Z_IEEEAddress ieeeAddr = buf.get64(6); - uint8_t capabilities = buf.get8(14); - - zigbee_devices.updateDevice(nwkAddr, ieeeAddr); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), - ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, - (capabilities & 0x04) ? "true" : "false", - (capabilities & 0x08) ? "true" : "false", - (capabilities & 0x40) ? "true" : "false" - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - Z_SendActiveEpReq(nwkAddr); - return -1; -} - - -int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { - Z_ShortAddress srcAddr = buf.get16(2); - Z_IEEEAddress ieeeAddr = buf.get64(4); - Z_ShortAddress parentNw = buf.get16(12); - - zigbee_devices.updateDevice(srcAddr, ieeeAddr); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"ParentNetwork\":\"0x%04X\"}}"), - ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - - return -1; -} - - - -const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; - -void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, const JsonObject *json) { - - const JsonVariant &val_endpoint = getCaseInsensitive(*json, PSTR(OCCUPANCY)); - if (nullptr != &val_endpoint) { - uint32_t occupancy = strToUInt(val_endpoint); - - if (occupancy) { - zigbee_devices.setTimer(shortaddr, OCCUPANCY_TIMEOUT, cluster, endpoint, 0, &Z_OccupancyCallback); - } - } -} - - - -int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { - const JsonObject *json = zigbee_devices.jsonGet(shortaddr); - if (json == nullptr) { return 0; } - - Z_AqaraOccupancy(shortaddr, cluster, endpoint, json); - - zigbee_devices.jsonPublishFlush(shortaddr); - return 1; -} - -int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { - uint16_t groupid = buf.get16(2); - uint16_t clusterid = buf.get16(4); - Z_ShortAddress srcaddr = buf.get16(6); - uint8_t srcendpoint = buf.get8(8); - uint8_t dstendpoint = buf.get8(9); - uint8_t wasbroadcast = buf.get8(10); - uint8_t linkquality = buf.get8(11); - uint8_t securityuse = buf.get8(12); - uint32_t timestamp = buf.get32(13); - uint8_t seqnumber = buf.get8(17); - - bool defer_attributes = false; - - zigbee_devices.updateLastSeen(srcaddr); - ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, - srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp); - zcl_received.log(); - char shortaddr[8]; - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); - - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); - - if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { - zcl_received.parseRawAttributes(json); - if (clusterid) { defer_attributes = true; } - } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { - zcl_received.parseReadAttributes(json); - } else if (zcl_received.isClusterSpecificCommand()) { - zcl_received.parseClusterSpecificCommand(json); - } - String msg(""); - msg.reserve(100); - json.printTo(msg); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); - - zcl_received.postProcessAttributes(srcaddr, json); - - json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; - - if (defer_attributes) { - - if (zigbee_devices.jsonIsConflict(srcaddr, json)) { - - zigbee_devices.jsonPublishFlush(srcaddr); - } else { - zigbee_devices.jsonAppend(srcaddr, json); - zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); - } - } else { - - zigbee_devices.jsonPublishNow(srcaddr, json); - } - return -1; -} - -typedef struct Z_Dispatcher { - const uint8_t* match; - ZB_RecvMsgFunc func; -} Z_Dispatcher; - - -ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) -ZBM(AREQ_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) -ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) -ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) -ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) -ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) - -const Z_Dispatcher Z_DispatchTable[] PROGMEM = { - { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, - { AREQ_END_DEVICE_ANNCE_IND, &Z_ReceiveEndDeviceAnnonce }, - { AREQ_END_DEVICE_TC_DEV_IND, &Z_ReceiveTCDevInd }, - { AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus }, - { AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc }, - { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, - { AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc }, -}; - -int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { - - if (zigbee.init_phase) { - - return -1; - } else { - for (uint32_t i = 0; i < sizeof(Z_DispatchTable)/sizeof(Z_Dispatcher); i++) { - if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) { - (*Z_DispatchTable[i].func)(res, buf); - } - } - return -1; - } -} - -int32_t Z_Load_Devices(uint8_t value) { - - loadZigbeeDevices(); - return 0; -} - -int32_t Z_State_Ready(uint8_t value) { - zigbee.init_phase = false; - return 0; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" -#ifdef USE_ZIGBEE - -#define XDRV_23 23 - -const uint32_t ZIGBEE_BUFFER_SIZE = 256; -const uint8_t ZIGBEE_SOF = 0xFE; -const uint8_t ZIGBEE_SOF_ALT = 0xFF; - -#include -TasmotaSerial *ZigbeeSerial = nullptr; - - -const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" - D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" - D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" - D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; - -const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" - D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" - D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" - D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; - -void (* const ZigbeeCommand[])(void) PROGMEM = { - &CmndZbZNPSend, &CmndZbPermitJoin, - &CmndZbStatus, &CmndZbReset, &CmndZbSend, - &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, - &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind - }; - -int32_t ZigbeeProcessInput(class SBuffer &buf) { - if (!zigbee.state_machine) { return -1; } - - - bool recv_filter_match = true; - bool recv_prefix_match = false; - if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { - if (zigbee.recv_filter_len >= 2) { - recv_prefix_match = false; - if ( (pgm_read_byte(&zigbee.recv_filter[0]) == buf.get8(0)) && - (pgm_read_byte(&zigbee.recv_filter[1]) == buf.get8(1)) ) { - recv_prefix_match = true; - } - } - - for (uint32_t i = 0; i < zigbee.recv_filter_len; i++) { - if (pgm_read_byte(&zigbee.recv_filter[i]) != buf.get8(i)) { - recv_filter_match = false; - break; - } - } - - - } - - - int32_t res = -1; - - - - - - if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { - if (!recv_prefix_match) { - res = -1; - } else { - if (recv_filter_match) { - res = 0; - } else { - if (zigbee.recv_until) { - res = -1; - } else { - res = -2; - } - } - } - } else { - res = -1; - } - - if (recv_prefix_match) { - if (zigbee.recv_func) { - res = (*zigbee.recv_func)(res, buf); - } - } - if (-1 == res) { - - if (zigbee.recv_unexpected) { - res = (*zigbee.recv_unexpected)(res, buf); - } - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZbProcessInput: res = %d"), res); - - - if (0 == res) { - - zigbee.state_waiting = false; - } else if (res > 0) { - ZigbeeGotoLabel(res); - } else if (-1 == res) { - - - } else { - - ZigbeeGotoLabel(zigbee.on_error_goto); - } -} - -void ZigbeeInput(void) -{ - static uint32_t zigbee_polling_window = 0; - static uint8_t fcs = ZIGBEE_SOF; - static uint32_t zigbee_frame_len = 5; -# 142 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" - while (ZigbeeSerial->available()) { - yield(); - uint8_t zigbee_in_byte = ZigbeeSerial->read(); - - - if (0 == zigbee_buffer->len()) { - zigbee_frame_len = 5; - fcs = ZIGBEE_SOF; - - - - if (ZIGBEE_SOF_ALT == zigbee_in_byte) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput forgiven first byte %02X (only for statistics)"), zigbee_in_byte); - zigbee_in_byte = ZIGBEE_SOF; - } - } - - if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput discarding byte %02X"), zigbee_in_byte); - continue; - } - - if (zigbee_buffer->len() < zigbee_frame_len) { - zigbee_buffer->add8(zigbee_in_byte); - zigbee_polling_window = millis(); - fcs ^= zigbee_in_byte; - } - - if (zigbee_buffer->len() >= zigbee_frame_len) { - zigbee_polling_window = 0; - break; - } - - - if (02 == zigbee_buffer->len()) { - - uint8_t len_byte = zigbee_buffer->get8(1); - if (len_byte > 250) len_byte = 250; - - zigbee_frame_len = len_byte + 5; - } - } - - if (zigbee_buffer->len() && (millis() > (zigbee_polling_window + ZIGBEE_POLLING))) { - char hex_char[(zigbee_buffer->len() * 2) + 2]; - ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Bytes follow_read_metric = %0d"), ZigbeeSerial->getLoopReadMetric()); - - if (zigbee_buffer->len() != zigbee_frame_len) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received frame of wrong size %s, len %d, expected %d"), hex_char, zigbee_buffer->len(), zigbee_frame_len); - } else if (0x00 != fcs) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received bad FCS frame %s, %d"), hex_char, fcs); - } else { - - - - SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); - - ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); - } - - ZigbeeProcessInput(znp_buffer); - } - zigbee_buffer->setLen(0); - } -} - - - -void ZigbeeInit(void) -{ - zigbee.active = false; - if ((pin[GPIO_ZIGBEE_RX] < 99) && (pin[GPIO_ZIGBEE_TX] < 99)) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); - - ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], seriallog_level ? 1 : 2, 0, 256); - ZigbeeSerial->begin(115200); - if (ZigbeeSerial->hardwareSerial()) { - ClaimSerial(); - uint32_t aligned_buffer = ((uint32_t)serial_in_buffer + 3) & ~3; - zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer) - 3, (char*) aligned_buffer); - } else { - zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); - } - zigbee.active = true; - zigbee.init_phase = true; - zigbee.state_machine = true; - ZigbeeSerial->flush(); - } -} - - - - - -uint32_t strToUInt(const JsonVariant &val) { - - if (val.is()) { - return val.as(); - } else { - if (val.is()) { - String sval = val.as(); - return strtoull(sval.c_str(), nullptr, 0); - } - } - return 0; -} - -const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = - { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x01 }; - - -void CmndZbReset(void) { - if (ZigbeeSerial) { - switch (XdrvMailbox.payload) { - case 1: - ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET)); - eraseZigbeeDevices(); - restart_flag = 2; - ResponseCmndChar(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING); - break; - default: - ResponseCmndChar(D_JSON_ONE_TO_RESET); - } - } -} - -void CmndZbZNPSendOrReceive(bool send) -{ - if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { - uint8_t code; - - char *codes = RemoveSpace(XdrvMailbox.data); - int32_t size = strlen(XdrvMailbox.data); - - SBuffer buf((size+1)/2); - - while (size > 1) { - char stemp[3]; - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, nullptr, 16); - buf.add8(code); - size -= 2; - codes += 2; - } - if (send) { - ZigbeeZNPSend(buf.getBuffer(), buf.len()); - } else { - ZigbeeProcessInput(buf); - } - } - ResponseCmndDone(); -} - - -void CmndZbZNPReceive(void) -{ - CmndZbZNPSendOrReceive(false); -} - -void CmndZbZNPSend(void) -{ - CmndZbZNPSendOrReceive(true); -} - -void ZigbeeZNPSend(const uint8_t *msg, size_t len) { - if ((len < 2) || (len > 252)) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPSENT ": bad message len %d"), len); - return; - } - uint8_t data_len = len - 2; - - if (ZigbeeSerial) { - uint8_t fcs = data_len; - - ZigbeeSerial->write(ZIGBEE_SOF); - - ZigbeeSerial->write(data_len); - - for (uint32_t i = 0; i < len; i++) { - uint8_t b = pgm_read_byte(msg + i); - ZigbeeSerial->write(b); - fcs ^= b; - - } - ZigbeeSerial->write(fcs); - - } - - char hex_char[(len * 2) + 2]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"), - ToHex_P(msg, len, hex_char, sizeof(hex_char))); -} - -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp, uint8_t transacId) { - SBuffer buf(25+len); - buf.add8(Z_SREQ | Z_AF); - buf.add8(AF_DATA_REQUEST); - buf.add16(dtsAddr); - buf.add8(endpoint); - buf.add8(0x01); - buf.add16(clusterId); - buf.add8(transacId); - buf.add8(0x30); - buf.add8(0x1E); - - buf.add8(3 + len); - buf.add8((disableDefResp ? 0x10 : 0x00) | (clusterSpecific ? 0x01 : 0x00)); - buf.add8(transacId); - buf.add8(cmdId); - if (len > 0) { - buf.addBuffer(msg, len); - } - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -} - -inline int8_t hexValue(char c) { - if ((c >= '0') && (c <= '9')) { - return c - '0'; - } - if ((c >= 'A') && (c <= 'F')) { - return 10 + c - 'A'; - } - if ((c >= 'a') && (c <= 'f')) { - return 10 + c - 'a'; - } - return -1; -} - -uint32_t parseHex(const char **data, size_t max_len = 8) { - uint32_t ret = 0; - for (uint32_t i = 0; i < max_len; i++) { - int8_t v = hexValue(**data); - if (v < 0) { break; } - ret = (ret << 4) | v; - *data += 1; - } - return ret; -} - -void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { - - uint16_t cluster = 0x0000; - uint8_t cmd = ZCL_READ_ATTRIBUTES; - bool clusterSpecific = false; - - - - cluster = parseHex(&data, 4); - - - if (('_' == *data) || ('!' == *data)) { - if ('!' == *data) { clusterSpecific = true; } - data++; - } else { - ResponseCmndChar("Wrong delimiter for payload"); - return; - } - - cmd = parseHex(&data, 2); - - - - if ('/' == *data) { data++; } - - size_t size = strlen(data); - SBuffer buf((size+2)/2); - - while (*data) { - uint8_t code = parseHex(&data, 2); - buf.add8(code); - } - - if (0 == endpoint) { - - endpoint = zigbee_devices.findClusterEndpointIn(dstAddr, cluster); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: dstAddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), - dstAddr, cluster, endpoint, cmd, data); - - if (0 == endpoint) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); - return; - } - - - ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len()); - - if (clusterSpecific) { - zigbeeSetCommandTimer(dstAddr, cluster, endpoint); - } - ResponseCmndDone(); -} - -void CmndZbSend(void) { -# 461 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); - if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } - - - static char delim[] = ", "; - uint16_t device = 0xFFFF; - uint8_t endpoint = 0x00; - String cmd_str = ""; - - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } - } - if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } - - const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); - if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } - const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send")); - if (nullptr != &val_cmd) { - - - - if (val_cmd.is()) { - - JsonObject &cmd_obj = val_cmd.as(); - int32_t cmd_size = cmd_obj.size(); - if (cmd_size > 1) { - Response_P(PSTR("Only 1 command allowed (%d)"), cmd_size); - return; - } else if (1 == cmd_size) { - - JsonObject::iterator it = cmd_obj.begin(); - String key = it->key; - JsonVariant& value = it->value; - uint32_t x = 0, y = 0, z = 0; - - const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.c_str()); - if (tasmota_cmd) { - cmd_str = tasmota_cmd; - } else { - Response_P(PSTR("Unrecognized zigbee command: %s"), key.c_str()); - return; - } - - - if (value.is()) { - x = value.as() ? 1 : 0; - } else if (value.is()) { - x = value.as(); - } else { - - const char *s_const = value.as(); - if (s_const != nullptr) { - char s[strlen(s_const)+1]; - strcpy(s, s_const); - if ((nullptr != s) && (0x00 != *s)) { - char *sval = strtok(s, delim); - if (sval) { - x = ZigbeeAliasOrNumber(sval); - sval = strtok(nullptr, delim); - if (sval) { - y = ZigbeeAliasOrNumber(sval); - sval = strtok(nullptr, delim); - if (sval) { - z = ZigbeeAliasOrNumber(sval); - } - } - } - } - } - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_template = %s"), cmd_str.c_str()); - cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_final = %s"), cmd_str.c_str()); - } else { - - } - } else if (val_cmd.is()) { - - cmd_str = val_cmd.as(); - } else { - - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%s\"}"), - device, endpoint, cmd_str.c_str()); - zigbeeZCLSendStr(device, endpoint, cmd_str.c_str()); - } else { - Response_P(PSTR("Missing zigbee 'Send'")); - return; - } - -} - -ZBM(ZBS_BIND_REQ, Z_SREQ | Z_ZDO, ZDO_BIND_REQ, - 0,0, - 0,0,0,0,0,0,0,0, - 0x00, - 0x00, 0x00, - 0x03, - 0,0,0,0,0,0,0,0, - 0x01 -) - -void CmndZbBind(void) { - - - - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); - if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } - - - - uint16_t device = 0xFFFF; - uint8_t endpoint = 0x00; - uint16_t cluster = 0; - uint32_t group = 0xFFFFFFFF; - - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } - } - if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } - - const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); - if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } - const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); - if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } - - - - SBuffer buf(sizeof(ZBS_BIND_REQ)); - buf.add8(Z_SREQ | Z_ZDO); - buf.add8(ZDO_BIND_REQ); - buf.add16(device); - buf.add64(zigbee_devices.getDeviceLongAddr(device)); - buf.add8(endpoint); - buf.add16(cluster); - buf.add8(0x03); - buf.add64(localIEEEAddr); - buf.add8(0x01); - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); - - ResponseCmndDone(); -} - - -void CmndZbProbe(void) { - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } - if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } - - - Z_SendActiveEpReq(shortaddr); - ResponseCmndDone(); -} - - -void CmndZbName(void) { - - - - - - - - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - - - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); - if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } - if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } - - if (p == nullptr) { - const String * friendlyName = zigbee_devices.getFriendlyName(shortaddr); - Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName->c_str() : ""); - } else { - zigbee_devices.setFriendlyName(shortaddr, p); - Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p); - } -} - - -void CmndZbForget(void) { - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } - if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } - - - if (zigbee_devices.removeDevice(shortaddr)) { - ResponseCmndDone(); - } else { - ResponseCmndChar("Unknown device"); - } -} - - -void CmndZbSave(void) { - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - - saveZigbeeDevices(); - - ResponseCmndDone(); -} - - -void CmndZbRead(void) { - - - - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); - if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } - - - uint16_t device = 0xFFFF; - uint16_t cluster = 0x0000; - uint8_t endpoint = 0x00; - size_t attrs_len = 0; - uint8_t* attrs = nullptr; - - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } - } - if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } - - const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); - if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } - const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); - if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } - - const JsonVariant &val_attr = getCaseInsensitive(json, PSTR("Read")); - if (nullptr != &val_attr) { - uint16_t val = strToUInt(val_attr); - if (val_attr.is()) { - JsonArray& attr_arr = val_attr; - attrs_len = attr_arr.size() * 2; - attrs = new uint8_t[attrs_len]; - - uint32_t i = 0; - for (auto value : attr_arr) { - uint16_t val = strToUInt(value); - attrs[i++] = val & 0xFF; - attrs[i++] = val >> 8; - } - } else { - attrs_len = 2; - attrs = new uint8_t[attrs_len]; - attrs[0] = val & 0xFF; - attrs[1] = val >> 8; - } - } - - if ((0 != endpoint) && (attrs_len > 0)) { - ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false ); - ResponseCmndDone(); - } else { - ResponseCmndChar("Missing parameters"); - } - - if (attrs) { delete[] attrs; } -} - - -void CmndZbPermitJoin(void) -{ - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - uint32_t payload = XdrvMailbox.payload; - if (payload < 0) { payload = 0; } - if ((99 != payload) && (payload > 1)) { payload = 1; } - - if (1 == payload) { - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60); - } else if (99 == payload){ - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX); - } else { - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE); - } - ResponseCmndDone(); -} - -void CmndZbStatus(void) { - if (ZigbeeSerial) { - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } - if (XdrvMailbox.payload > 0) { - if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } - } - - String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr); - Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); - } -} - - - - - -bool Xdrv23(uint8_t function) -{ - bool result = false; - - if (zigbee.active) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (!zigbee.init_phase) { - zigbee_devices.runTimer(); - } - break; - case FUNC_LOOP: - if (ZigbeeSerial) { ZigbeeInput(); } - if (zigbee.state_machine) { - - ZigbeeStateMachine_Run(); - } - break; - case FUNC_PRE_INIT: - ZigbeeInit(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kZbCommands, ZigbeeCommand); - result = result || DecodeCommand(kZigbeeCommands, ZigbeeCommand); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_24_buzzer.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_24_buzzer.ino" -#ifdef USE_BUZZER - - - - -#define XDRV_24 24 - -struct BUZZER { - uint32_t tune = 0; - uint32_t tune_reload = 0; - bool active = true; - bool enable = false; - uint8_t inverted = 0; - uint8_t count = 0; - uint8_t mode = 0; - uint8_t set[2]; - uint8_t duration; - uint8_t state = 0; -} Buzzer; - - - -void BuzzerOff(void) -{ - DigitalWrite(GPIO_BUZZER, Buzzer.inverted); -} - - -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) -{ - Buzzer.set[0] = off; - Buzzer.set[1] = on; - Buzzer.duration = 1; - Buzzer.tune_reload = 0; - Buzzer.mode = mode; - - if (tune) { - uint32_t tune1 = tune; - uint32_t tune2 = tune; - for (uint32_t i = 0; i < 32; i++) { - if (!(tune2 & 0x80000000)) { - tune2 <<= 1; - } else { - Buzzer.tune_reload <<= 1; - Buzzer.tune_reload |= tune1 & 1; - tune1 >>= 1; - } - } - Buzzer.tune = Buzzer.tune_reload; - } - Buzzer.count = count * 2; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, Buzzer.count, on, off, tune, Buzzer.tune); - - Buzzer.enable = (Buzzer.count > 0); - if (!Buzzer.enable) { - BuzzerOff(); - } -} - -void BuzzerSetStateToLed(uint32_t state) -{ - if (Buzzer.enable && (2 == Buzzer.mode)) { - Buzzer.state = (state != 0); - DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); - } -} - -void BuzzerBeep(uint32_t count) -{ - BuzzerBeep(count, 1, 1, 0, 0); -} - -void BuzzerEnabledBeep(uint32_t count, uint32_t duration) -{ - if (Settings.flag3.buzzer_enable) { - BuzzerBeep(count, duration, 1, 0, 0); - } -} - - - -bool BuzzerPinState(void) -{ - if (XdrvMailbox.index == GPIO_BUZZER_INV) { - Buzzer.inverted = 1; - XdrvMailbox.index -= (GPIO_BUZZER_INV - GPIO_BUZZER); - return true; - } - return false; -} - -void BuzzerInit(void) -{ - if (pin[GPIO_BUZZER] < 99) { - pinMode(pin[GPIO_BUZZER], OUTPUT); - BuzzerOff(); - } else { - Buzzer.active = false; - } -} - -void BuzzerEvery100mSec(void) -{ - if (Buzzer.enable && (Buzzer.mode != 2)) { - if (Buzzer.count) { - if (Buzzer.duration) { - Buzzer.duration--; - if (!Buzzer.duration) { - if (Buzzer.tune) { - Buzzer.state = Buzzer.tune & 1; - Buzzer.tune >>= 1; - } else { - Buzzer.tune = Buzzer.tune_reload; - Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1; - Buzzer.state = Buzzer.count & 1; - if (Buzzer.mode) { - Buzzer.count |= 2; - } - } - Buzzer.duration = Buzzer.set[Buzzer.state]; - } - } - DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); - } else { - Buzzer.enable = false; - } - } -} - - - - - -const char kBuzzerCommands[] PROGMEM = "|" - "Buzzer" ; - -void (* const BuzzerCommand[])(void) PROGMEM = { - &CmndBuzzer }; - -void CmndBuzzer(void) -{ -# 174 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_24_buzzer.ino" - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload != 0) { - uint32_t parm[4] = { 0 }; - uint32_t mode = 0; - ParseParameters(4, parm); - if (XdrvMailbox.payload <= 0) { - parm[0] = 1; - mode = -XdrvMailbox.payload; - } - for (uint32_t i = 1; i < 3; i++) { - if (parm[i] < 1) { parm[i] = 1; } - } - BuzzerBeep(parm[0], parm[1], parm[2], parm[3], mode); - } else { - BuzzerBeep(0); - } - } else { - BuzzerBeep(1); - } - ResponseCmndDone(); -} - - - - - -bool Xdrv24(uint8_t function) -{ - bool result = false; - - if (Buzzer.active) { - switch (function) { - case FUNC_EVERY_100_MSECOND: - BuzzerEvery100mSec(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kBuzzerCommands, BuzzerCommand); - break; - case FUNC_PRE_INIT: - BuzzerInit(); - break; - case FUNC_PIN_STATE: - result = BuzzerPinState(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" -# 21 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" -#ifdef USE_A4988_STEPPER - - - - -#define XDRV_25 25 - -#include - -short A4988_dir_pin = pin[GPIO_MAX]; -short A4988_stp_pin = pin[GPIO_MAX]; -short A4988_ms1_pin = pin[GPIO_MAX]; -short A4988_ms2_pin = pin[GPIO_MAX]; -short A4988_ms3_pin = pin[GPIO_MAX]; -short A4988_ena_pin = pin[GPIO_MAX]; -int A4988_spr = 0; -float A4988_rpm = 0; -short A4988_mis = 0; - -A4988_Stepper* myA4988 = nullptr; - -void A4988Init(void) -{ - A4988_dir_pin = pin[GPIO_A4988_DIR]; - A4988_stp_pin = pin[GPIO_A4988_STP]; - A4988_ena_pin = pin[GPIO_A4988_ENA]; - A4988_ms1_pin = pin[GPIO_A4988_MS1]; - A4988_ms2_pin = pin[GPIO_A4988_MS2]; - A4988_ms3_pin = pin[GPIO_A4988_MS3]; - A4988_spr = 200; - A4988_rpm = 30; - A4988_mis = 1; - - myA4988 = new A4988_Stepper( A4988_spr - , A4988_rpm - , A4988_mis - , A4988_dir_pin - , A4988_stp_pin - , A4988_ena_pin - , A4988_ms1_pin - , A4988_ms2_pin - , A4988_ms3_pin ); -} - -const char kA4988Commands[] PROGMEM = "Motor|" - "Move|Rotate|Turn|MIS|SPR|RPM"; - -void (* const A4988Command[])(void) PROGMEM = { - &CmndDoMove,&CmndDoRotate,&CmndDoTurn,&CmndSetMIS,&CmndSetSPR,&CmndSetRPM}; - -void CmndDoMove(void) { - if (XdrvMailbox.data_len > 0) { - long stepsPlease = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->doMove(stepsPlease); - ResponseCmndDone(); - } -} - -void CmndDoRotate(void) { - if (XdrvMailbox.data_len > 0) { - long degrsPlease = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->doRotate(degrsPlease); - ResponseCmndDone(); - } -} - -void CmndDoTurn(void) { - if (XdrvMailbox.data_len > 0) { - float turnsPlease = strtod(XdrvMailbox.data,nullptr); - myA4988->doTurn(turnsPlease); - ResponseCmndDone(); - } -} - -void CmndSetMIS(void) { - if ((pin[GPIO_A4988_MS1] < 99) && (pin[GPIO_A4988_MS2] < 99) && (pin[GPIO_A4988_MS3] < 99) && (XdrvMailbox.data_len > 0)) { - short newMIS = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setMIS(newMIS); - ResponseCmndDone(); - } -} - -void CmndSetSPR(void) { - if (XdrvMailbox.data_len > 0) { - int newSPR = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setSPR(newSPR); - ResponseCmndDone(); - } -} - -void CmndSetRPM(void) { - if (XdrvMailbox.data_len > 0) { - short newRPM = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setRPM(newRPM); - ResponseCmndDone(); - } -} - - - - -bool Xdrv25(uint8_t function) -{ - bool result = false; - if ((pin[GPIO_A4988_DIR] < 99) && (pin[GPIO_A4988_STP] < 99)) { - switch (function) { - case FUNC_INIT: - A4988Init(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kA4988Commands, A4988Command); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_26_ariluxrf.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_26_ariluxrf.ino" -#ifdef USE_LIGHT -#ifdef USE_ARILUX_RF - - - - -#define XDRV_26 26 - -const uint32_t ARILUX_RF_TIME_AVOID_DUPLICATE = 1000; - -const uint8_t ARILUX_RF_MAX_CHANGES = 51; -const uint32_t ARILUX_RF_SEPARATION_LIMIT = 4300; -const uint32_t ARILUX_RF_RECEIVE_TOLERANCE = 60; - -struct ARILUX { - unsigned int rf_timings[ARILUX_RF_MAX_CHANGES]; - - unsigned long rf_received_value = 0; - unsigned long rf_last_received_value = 0; - unsigned long rf_last_time = 0; - unsigned long rf_lasttime = 0; - - unsigned int rf_change_count = 0; - unsigned int rf_repeat_count = 0; - - uint8_t rf_toggle = 0; -} Arilux; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -#ifndef USE_WS2812_DMA -void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; -#endif -#endif - -void AriluxRfInterrupt(void) -{ - unsigned long time = micros(); - unsigned int duration = time - Arilux.rf_lasttime; - - if (duration > ARILUX_RF_SEPARATION_LIMIT) { - if (abs(duration - Arilux.rf_timings[0]) < 200) { - Arilux.rf_repeat_count++; - if (Arilux.rf_repeat_count == 2) { - unsigned long code = 0; - const unsigned int delay = Arilux.rf_timings[0] / 31; - const unsigned int delayTolerance = delay * ARILUX_RF_RECEIVE_TOLERANCE / 100; - for (unsigned int i = 1; i < Arilux.rf_change_count -1; i += 2) { - code <<= 1; - if (abs(Arilux.rf_timings[i] - (delay *3)) < delayTolerance && abs(Arilux.rf_timings[i +1] - delay) < delayTolerance) { - code |= 1; - } - } - if (Arilux.rf_change_count > 49) { - Arilux.rf_received_value = code; - } - Arilux.rf_repeat_count = 0; - } - } - Arilux.rf_change_count = 0; - } - if (Arilux.rf_change_count >= ARILUX_RF_MAX_CHANGES) { - Arilux.rf_change_count = 0; - Arilux.rf_repeat_count = 0; - } - Arilux.rf_timings[Arilux.rf_change_count++] = duration; - Arilux.rf_lasttime = time; -} - -void AriluxRfHandler(void) -{ - unsigned long now = millis(); - if (Arilux.rf_received_value && !((Arilux.rf_received_value == Arilux.rf_last_received_value) && (now - Arilux.rf_last_time < ARILUX_RF_TIME_AVOID_DUPLICATE))) { - Arilux.rf_last_received_value = Arilux.rf_received_value; - Arilux.rf_last_time = now; - - uint16_t hostcode = Arilux.rf_received_value >> 8 & 0xFFFF; - if (Settings.rf_code[1][6] == Settings.rf_code[1][7]) { - Settings.rf_code[1][6] = hostcode >> 8 & 0xFF; - Settings.rf_code[1][7] = hostcode & 0xFF; - } - uint16_t stored_hostcode = Settings.rf_code[1][6] << 8 | Settings.rf_code[1][7]; - - DEBUG_DRIVER_LOG(PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, Arilux.rf_received_value); - - if (hostcode == stored_hostcode) { - char command[33]; - char value = '-'; - command[0] = '\0'; - uint8_t keycode = Arilux.rf_received_value & 0xFF; - switch (keycode) { - case 1: - case 3: - snprintf_P(command, sizeof(command), PSTR(D_CMND_POWER " %d"), (1 == keycode) ? 1 : 0); - break; - case 2: - Arilux.rf_toggle++; - Arilux.rf_toggle &= 0x3; - snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), 200 + Arilux.rf_toggle); - break; - case 4: - value = '+'; - case 7: - snprintf_P(command, sizeof(command), PSTR(D_CMND_SPEED " %c"), value); - break; - case 5: - value = '+'; - case 8: - snprintf_P(command, sizeof(command), PSTR(D_CMND_SCHEME " %c"), value); - break; - case 6: - value = '+'; - case 9: - snprintf_P(command, sizeof(command), PSTR(D_CMND_DIMMER " %c"), value); - break; - default: { - if ((keycode >= 10) && (keycode <= 21)) { - snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), keycode -9); - } - } - } - if (strlen(command)) { - ExecuteCommand(command, SRC_LIGHT); - } - } - } - Arilux.rf_received_value = 0; -} - -void AriluxRfInit(void) -{ - if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { - if (Settings.last_module != Settings.module) { - Settings.rf_code[1][6] = 0; - Settings.rf_code[1][7] = 0; - Settings.last_module = Settings.module; - } - Arilux.rf_received_value = 0; - - digitalWrite(pin[GPIO_ARIRFSEL], 0); - attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE); - } -} - -void AriluxRfDisable(void) -{ - if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { - detachInterrupt(pin[GPIO_ARIRFRCV]); - digitalWrite(pin[GPIO_ARIRFSEL], 1); - } -} - - - - - -bool Xdrv26(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (pin[GPIO_ARIRFRCV] < 99) { AriluxRfHandler(); } - break; - case FUNC_EVERY_SECOND: - if (10 == uptime) { AriluxRfInit(); } - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_27_shutter.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_27_shutter.ino" -#ifdef USE_SHUTTER - - - - -#define XDRV_27 27 - -#define D_SHUTTER "SHUTTER" - -const uint16_t MOTOR_STOP_TIME = 500; -const uint8_t steps_per_second = 20; - -uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; -uint16_t messwerte[5] = {30,50,70,90,100}; -uint16_t last_execute_step; - -enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; -enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; - -const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" - D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" - D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" - D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" - D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME; - -void (* const ShutterCommand[])(void) PROGMEM = { - &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, - &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, - &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, - &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime}; - - const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; - const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; - -#include - -Ticker TickerShutter; - -struct SHUTTER { - power_t mask = 0; - power_t old_power = 0; - power_t switched_relay = 0; - uint32_t time[MAX_SHUTTERS]; - int32_t open_max[MAX_SHUTTERS]; - int32_t target_position[MAX_SHUTTERS]; - int32_t start_position[MAX_SHUTTERS]; - int32_t real_position[MAX_SHUTTERS]; - uint16_t open_time[MAX_SHUTTERS]; - uint16_t close_time[MAX_SHUTTERS]; - uint16_t close_velocity[MAX_SHUTTERS]; - int8_t direction[MAX_SHUTTERS]; - uint8_t mode = 0; - int16_t motordelay[MAX_SHUTTERS]; - int16_t pwm_frequency; - uint16_t max_pwm_frequency = 1000; - uint16_t max_close_pwm_frequency[MAX_SHUTTERS]; - uint8_t skip_relay_change; - int32_t accelerator[MAX_SHUTTERS]; -} Shutter; - -void ShutterLogPos(uint32_t i) -{ - char stemp2[10]; - dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d"), - i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_frequency); -} - -void ShutterRtc50mS(void) -{ - for (uint32_t i = 0; i < shutters_present; i++) { - Shutter.time[i]++; - if (Shutter.accelerator[i]) { - Shutter.pwm_frequency += Shutter.accelerator[i]; - Shutter.pwm_frequency = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency)); - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+i], 50); - } - } -} - -#define SHT_DIV_ROUND(__A,__B) (((__A) + (__B)/2) / (__B)) - -int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) -{ - if (0 == percent) return 0; - if (100 == percent) return Shutter.open_max[index]; - if (Settings.shutter_set50percent[index] != 50) { - return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; - } else { - uint32_t realpos; - - for (uint32_t j = 0; j < 5; j++) { - if (0 == Settings.shuttercoeff[j][index]) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); - for (uint32_t k = 0; k < 5; k++) { - Settings.shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]); - } - } - } - for (uint32_t i = 0; i < 5; i++) { - if ((percent * 10) >= Settings.shuttercoeff[i][index]) { - realpos = SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i+1], 100); - - } else { - if (0 == i) { - realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter.open_max[index] * calibrate_pos[i+1], Settings.shuttercoeff[i][index]), 10); - } else { - - - realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]), Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), 100); - } - break; - } - } - return realpos; - } -} - -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) -{ - if (0 >= realpos) return 0; - if (Shutter.open_max[index] <= realpos) return 100; - if (Settings.shutter_set50percent[index] != 50) { - return (Settings.shuttercoeff[2][index] * 5 > realpos) ? SHT_DIV_ROUND(realpos, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos-Settings.shuttercoeff[0][index], Settings.shuttercoeff[1][index]); - } else { - uint16_t realpercent; - - for (uint32_t i = 0; i < 5; i++) { - if (realpos >= Shutter.open_max[index] * calibrate_pos[i+1] / 100) { - realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[i][index], 10); - - } else { - if (0 == i) { - realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * Settings.shuttercoeff[i][index], calibrate_pos[i+1]), Shutter.open_max[index]); - } else { - - - - realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), (calibrate_pos[i+1] - calibrate_pos[i])), Shutter.open_max[index]) ; - } - break; - } - } - return realpercent; - } -} - -void ShutterInit(void) -{ - shutters_present = 0; - Shutter.mask = 0; - - Shutter.old_power = power; - bool relay_in_interlock = false; - - - if (Settings.shutter_startrelay[MAX_SHUTTERS] == 0) { - Shutter.max_pwm_frequency = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : Shutter.max_pwm_frequency; - } - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - - Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]); - if (Settings.shutter_startrelay[i] && (Settings.shutter_startrelay[i] < 9)) { - shutters_present++; - - - Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1) ; - - for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { - - if (Settings.interlock[j] && (Settings.interlock[j] & Shutter.mask)) { - - relay_in_interlock = true; - } - } - if (relay_in_interlock) { - if (Settings.pulse_timer[i] > 0) { - Shutter.mode = SHT_PULSE_OPEN__PULSE_CLOSE; - } else { - Shutter.mode = SHT_OFF_OPEN__OFF_CLOSE; - } - } else { - Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; - if ((pin[GPIO_PWM1+i] < 99) && (pin[GPIO_CNTR1+i] < 99)) { - Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER; - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+i], 50); - } - } - - TickerShutter.attach_ms(50, ShutterRtc50mS ); - - Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] > 0) ? Settings.shutter_set50percent[i] : 50; - - - Shutter.open_time[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100; - Shutter.close_time[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100; - - - Shutter.open_max[i] = 200 * Shutter.open_time[i]; - Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ; - Shutter.max_close_pwm_frequency[i] = Shutter.max_pwm_frequency*Shutter.open_time[i] / Shutter.close_time[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Closefreq: %d"),i, Shutter.max_close_pwm_frequency[i]); - - - if (Settings.shutter_set50percent[i] != 50) { - Settings.shuttercoeff[1][i] = Shutter.open_max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; - Settings.shuttercoeff[0][i] = Shutter.open_max[i] - (Settings.shuttercoeff[1][i] * 100); - Settings.shuttercoeff[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5; - } - Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1); - - Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i); - - Shutter.start_position[i] = Shutter.target_position[i] = Shutter.real_position[i]; - Shutter.motordelay[i] = Settings.shutter_motordelay[i]; - - char shutter_open_chr[10]; - dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); - char shutter_close_chr[10]; - dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100, Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, is locked %d, end stop time enabled %d, shuttermode %d, motordelay %d"), - i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, - Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], - Shutter.mask, (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, Shutter.mode, Shutter.motordelay[i]); - - } else { - - break; - } - ShutterLimitRealAndTargetPositions(i); - Settings.shutter_accuracy = 1; - } -} - -void ShutterReportPosition(bool always) -{ - uint32_t shutter_moving = 0; - Response_P(PSTR("{")); - for (uint32_t i = 0; i < shutters_present; i++) { - - uint32_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); - if (Shutter.direction[i] != 0) { - shutter_moving = 1; - ShutterLogPos(i); - } - if (i) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i]); - } - ResponseJsonEnd(); - if (always || (1 == shutter_moving)) { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); - } - if (rules_flag.shutter_moving > shutter_moving) { - rules_flag.shutter_moved = 1; - } else { - rules_flag.shutter_moved = 0; - } - rules_flag.shutter_moving = shutter_moving; - -} - -void ShutterLimitRealAndTargetPositions(uint32_t i) { - if (Shutter.real_position[i]<0) Shutter.real_position[i] = 0; - if (Shutter.real_position[i]>Shutter.open_max[i]) Shutter.real_position[i] = Shutter.open_max[i]; - if (Shutter.target_position[i]<0) Shutter.target_position[i] = 0; - if (Shutter.target_position[i]>Shutter.open_max[i]) Shutter.target_position[i] = Shutter.open_max[i]; -} - -void ShutterUpdatePosition(void) -{ - - char scommand[CMDSZ]; - char stopic[TOPSZ]; - - for (uint32_t i = 0; i < shutters_present; i++) { - if (Shutter.direction[i] != 0) { - int32_t stop_position_delta = 20; - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { - - - Shutter.real_position[i] = ShutterCounterBasedPosition(i); - - int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; - int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); - int32_t min_runtime_ms = Shutter.pwm_frequency*1000 / max_freq_change_per_sec; - int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; - int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency / max_frequency * Shutter.direction[i] ; - - int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; - stop_position_delta =200 * Shutter.pwm_frequency/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); - - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, - Shutter.pwm_frequency,max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); - - if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { - - Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); - - } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency == max_frequency) { - Shutter.accelerator[i] = 0; - } - } else { - Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); - } - if ( Shutter.real_position[i] * Shutter.direction[i] + stop_position_delta >= Shutter.target_position[i] * Shutter.direction[i] ) { - - - uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; - int16_t missing_steps; - - switch (Shutter.mode) { - case SHT_PULSE_OPEN__PULSE_CLOSE: - - if (SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source) { - ExecuteCommandPower(cur_relay, 1, SRC_SHUTTER); - } else { - last_source = SRC_SHUTTER; - } - break; - case SHT_OFF_ON__OPEN_CLOSE_STEPPER: - missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); - Shutter.accelerator[i] = 0; - Shutter.pwm_frequency = Shutter.pwm_frequency > 250 ? 250 : Shutter.pwm_frequency; - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+i], 50); - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); - while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { - delay(1); - } - analogWrite(pin[GPIO_PWM1+i], 0); - Shutter.real_position[i] = ShutterCounterBasedPosition(i); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); - - if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { - ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); - ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); - } - break; - case SHT_OFF_ON__OPEN_CLOSE: - if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { - ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); - ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); - } - break; - case SHT_OFF_OPEN__OFF_CLOSE: - - if ((1 << (cur_relay-1)) & power) { - - ExecuteCommandPower(cur_relay, 0, SRC_SHUTTER); - } - break; - } - ShutterLimitRealAndTargetPositions(i); - Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); - - ShutterLogPos(i); - - Shutter.start_position[i] = Shutter.real_position[i]; - - - snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P("%d", (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); - MqttPublish(stopic, Settings.flag.mqtt_power_retain); - - Shutter.direction[i] = 0; - ShutterReportPosition(true); - XdrvRulesProcess(); - } - } - } -} - -bool ShutterState(uint32_t device) -{ - device--; - device &= 3; - return (Settings.flag3.shutter_mode && - (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) ); -} - -void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) -{ - - if ( ( (1 == direction) && ((Shutter.open_max[i] - Shutter.real_position[i]) / 100 <= 2) ) - || ( (-1 == direction) && (Shutter.real_position[i] / Shutter.close_velocity[i] <= 2)) ) { - Shutter.skip_relay_change = 1; - } else { - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+i], 0); - - if (pin[GPIO_CNTR1+i] < 99) { - RtcSettings.pulse_counter[i] = 0; - } - Shutter.accelerator[i] = Shutter.max_pwm_frequency / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Ramp up: %d"), Shutter.accelerator[i]); - } - Shutter.target_position[i] = target_pos; - Shutter.start_position[i] = Shutter.real_position[i]; - Shutter.time[i] = 0; - Shutter.skip_relay_change = 0; - Shutter.direction[i] = direction; - - } - -} - -void ShutterWaitForMotorStop(uint32_t i) -{ - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); - if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { - if (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode) { - - while (Shutter.pwm_frequency > 0) { - Shutter.accelerator[i] = 0; - Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); - analogWriteFreq(Shutter.pwm_frequency); - analogWrite(pin[GPIO_PWM1+i], 50); - delay(50); - } - analogWrite(pin[GPIO_PWM1+i], 0); - Shutter.real_position[i] = ShutterCounterBasedPosition(i); - } else { - ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); - delay(MOTOR_STOP_TIME); - } - } else { - delay(MOTOR_STOP_TIME); - } -} - -int32_t ShutterCounterBasedPosition(uint32_t i) -{ - return ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; -} - -void ShutterRelayChanged(void) -{ - - - - - char stemp1[10]; - - for (uint32_t i = 0; i < shutters_present; i++) { - power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; - - uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; - - if (manual_relays_changed) { - - ShutterLimitRealAndTargetPositions(i); - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { - ShutterWaitForMotorStop(i); - switch (powerstate_local) { - case 1: - ShutterStartInit(i, 1, Shutter.open_max[i]); - break; - case 3: - ShutterStartInit(i, -1, 0); - break; - default: - - Shutter.target_position[i] = Shutter.real_position[i]; - } - } else { - if (Shutter.direction[i] != 0 && (!powerstate_local || (powerstate_local && Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE))) { - Shutter.target_position[i] = Shutter.real_position[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); - } else { - last_source = SRC_SHUTTER; - if (powerstate_local == 2) { - - ShutterWaitForMotorStop(i); - ShutterStartInit(i, -1, 0); - } else { - - ShutterWaitForMotorStop(i); - ShutterStartInit(i, 1, Shutter.open_max[i]); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter.target_position[i], powerstate_local); - } - } - } -} - -bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { - - uint32 min_shutterbutton_hold_timer = -1; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) - min_shutterbutton_hold_timer = Button.hold_timer[i]; - } - return (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1)); -} - -void ShutterButtonHandler(void) -{ - uint8_t buttonState = SHT_NOT_PRESSED; - uint8_t button = XdrvMailbox.payload; - uint8_t press_index; - uint32_t button_index = XdrvMailbox.index; - uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; - - uint16_t loops_per_second = 1000 / Settings.button_debounce; - - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - if (Settings.flag.button_single) { - buttonState = SHT_PRESSED_MULTI; - press_index = 1; - } else { - if ((Shutter.direction[shutter_index]) && (Button.press_counter[button_index]==0)) { - buttonState = SHT_PRESSED_IMMEDIATE; - press_index = 1; - Button.press_counter[button_index] = 99; - } else - Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - Button.window_timer[button_index] = loops_per_second / 2; - } - blinks = 201; - } - - if (NOT_PRESSED == button) { - Button.hold_timer[button_index] = 0; - } else { - Button.hold_timer[button_index]++; - if (!Settings.flag.button_single) { - if (Settings.param[P_HOLD_IGNORE] > 0) { - if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { - Button.hold_timer[button_index] = 0; - Button.press_counter[button_index] = 0; - } - } - if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { - - if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { - - for (uint32_t i = 0; i < MAX_KEYS; i++) - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) - Button.press_counter[i] = 99; - press_index = 0; - buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS; - } - if (Button.press_counter[button_index]<99) { - press_index = 0; - buttonState = SHT_PRESSED_HOLD; - } - Button.press_counter[button_index] = 0; - } - if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { - - if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { - - press_index = 0; - buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; - } - } - } - } - - if (!Settings.flag.button_single) { - if (Button.window_timer[button_index]) { - Button.window_timer[button_index]--; - } else { - if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { - if (Button.press_counter[button_index]<99) { - - uint32 min_shutterbutton_press_counter = -1; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) - min_shutterbutton_press_counter = Button.press_counter[i]; - } - if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { - - press_index = Button.press_counter[button_index]; - for (uint32_t i = 0; i < MAX_KEYS; i++) - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) - Button.press_counter[i] = 99; - buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; - } - if ((buttonState != SHT_PRESSED_MULTI_SIMULTANEOUS) && (Button.press_counter[button_index]<99)) { - - press_index = Button.press_counter[button_index]; - buttonState = SHT_PRESSED_MULTI; - } - } - Button.press_counter[button_index] = 0; - } - } - } - - if (buttonState != SHT_NOT_PRESSED) { - if (buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) { - if ((press_index>=5) && (press_index<=7) && (!Settings.flag.button_restrict)) { - - char scmnd[20]; - GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } - } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { - - if (!Settings.flag.button_restrict) { - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } - } else if (buttonState <= SHT_PRESSED_IMMEDIATE) { - if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { - uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); - if (pos_press_index>3) pos_press_index=3; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); - XdrvMailbox.index = shutter_index +1; - last_source = SRC_BUTTON; - XdrvMailbox.data_len = 0; - char databuf[1] = ""; - XdrvMailbox.data = databuf; - XdrvMailbox.command = NULL; - if (buttonState == SHT_PRESSED_IMMEDIATE) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } - else { - uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; - if (position) { - if (Shutter.direction[shutter_index]) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } else { - XdrvMailbox.payload = position = (position-1)<<1; - CmndShutterPosition(); - if (Settings.shutter_button[button_index] & ((0x01<<26)< 0) && (XdrvMailbox.index <= shutters_present)) { - if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { - if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { - XdrvMailbox.index = XdrvMailbox.payload; - } - uint32_t i = XdrvMailbox.index -1; - if (Shutter.direction[i] != 0) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]); - - int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); - XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); - - last_source = SRC_WEBGUI; - CmndShutterPosition(); - } else { - if (XdrvMailbox.command) - ResponseCmndDone(); - } - } else { - if (XdrvMailbox.command) - ResponseCmndIdxChar("Locked"); - } - } -} - -void CmndShutterPosition(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { - uint32_t index = XdrvMailbox.index-1; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); - - - if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { - - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { - CmndShutterOpen(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN))) { - CmndShutterClose(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN)))) { - XdrvMailbox.payload = -99; - CmndShutterStop(); - return; - } - } - - int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? 0 : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); - - target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; - if (XdrvMailbox.payload != -99) { - - Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); - Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); - } - if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { - if (Settings.shutter_options[index] & 4) { - if (0 == target_pos_percent) Shutter.target_position[index] -= 1 * 2000; - if (100 == target_pos_percent) Shutter.target_position[index] += 1 * 2000; - } - int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; - if (Shutter.direction[index] == -new_shutterdirection) { - - if (SHT_PULSE_OPEN__PULSE_CLOSE == Shutter.mode) { - - ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 0 : 1), 1, SRC_SHUTTER); - delay(100); - } else { - if (SHT_OFF_OPEN__OFF_CLOSE == Shutter.mode) { - ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 1 : 0), 0, SRC_SHUTTER); - ShutterWaitForMotorStop(index); - } - } - } - if (Shutter.direction[index] != new_shutterdirection) { - if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { - - ShutterWaitForMotorStop(index); - ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); - ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - if (Shutter.skip_relay_change == 0) { - - ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); - - ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); - } - } else { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start in dir %d"), Shutter.direction[index]); - ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - if (Shutter.skip_relay_change == 0) { - ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); - } - - } - Shutter.switched_relay = 0; - } - } else { - target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); - ShutterReportPosition(true); - } - XdrvMailbox.index = index +1; - if (XdrvMailbox.command) - ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent); - } else { - ShutterReportPosition(true); - if (XdrvMailbox.command) - ResponseCmndIdxChar("Locked"); - } - } -} - -void CmndShutterOpenTime(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - Settings.shutter_opentime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); - ShutterInit(); - } - char time_chr[10]; - dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index -1]) / 10, 1, time_chr); - ResponseCmndIdxChar(time_chr); - } -} - -void CmndShutterCloseTime(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - Settings.shutter_closetime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); - ShutterInit(); - } - char time_chr[10]; - dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index -1]) / 10, 1, time_chr); - ResponseCmndIdxChar(time_chr); - } -} - -void CmndShutterMotorDelay(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(steps_per_second * CharToFloat(XdrvMailbox.data)); - ShutterInit(); - } - char time_chr[10]; - dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / steps_per_second, 2, time_chr); - ResponseCmndIdxChar(time_chr); - } -} - -void CmndShutterRelay(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) { - Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; - if (XdrvMailbox.payload > 0) { - Shutter.mask |= 3 << (XdrvMailbox.payload - 1); - } else { - Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1); - } - Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; - ShutterInit(); - - } - ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]); - } -} - -void CmndShutterButton(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { - uint32_t setting = 0; -# 915 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_27_shutter.ino" - if (XdrvMailbox.data_len > 0) { - uint32_t i = 0; - uint32_t button_index = 0; - bool done = false; - bool isShortCommand = false; - char *str_ptr; - - char data_copy[strlen(XdrvMailbox.data) +1]; - strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); - - for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) { - int field; - if (str[0] == '-') { - field = -1; - } else { - field = atoi(str); - } - switch (i) { - case 0: - if ((field >= -1) && (field<=4)) { - button_index = (field<=0)?(-1):field; - done = (button_index==-1); - } else - done = true; - break; - case 1: - if (!strcmp_P(str, PSTR("up"))) { - setting |= (((100>>1)+1)<<2) | (((50>>1)+1)<<8) | (((75>>1)+1)<<14) | (((100>>1)+1)<<20); - isShortCommand = true; - break; - } else if (!strcmp_P(str, PSTR("down"))) { - setting |= (((0>>1)+1)<<2) | (((50>>1)+1)<<8) | (((25>>1)+1)<<14) | (((0>>1)+1)<<20); - isShortCommand = true; - break; - } else if (!strcmp_P(str, PSTR("updown"))) { - setting |= (((100>>1)+1)<<2) | (((0>>1)+1)<<8) | (((50>>1)+1)<<14); - isShortCommand = true; - break; - } - case 2: - if (isShortCommand) { - if ((field==1) && (setting & (0x3F<<(2+6*3)))) - - setting |= (0x3<<29); - done = true; - break; - } - case 3: - case 4: - if ((field >= -1) && (field<=100)) - setting |= (((field>>1)+1)<<(i*6 + (2-6))); - break; - case 5: - case 6: - case 7: - case 8: - case 9: - if (field==1) - setting |= (1<<(i + (26-5))); - break; - } - if (done) break; - } - - if (button_index) { - if (button_index==-1) { - - for (uint32_t i=0 ; i < MAX_KEYS ; i++) - if ((Settings.shutter_button[i]&0x3) == (XdrvMailbox.index-1)) - Settings.shutter_button[i] = 0; - } else { - if (setting) { - - setting |= (1<<31); - setting |= (XdrvMailbox.index-1) & 0x3; - } - Settings.shutter_button[button_index-1] = setting; - } - } - } - char setting_chr[30*MAX_KEYS] = "-", *setting_chr_ptr = setting_chr; - for (uint32_t i=0 ; i < MAX_KEYS ; i++) { - setting = Settings.shutter_button[i]; - if ((setting&(1<<31)) && ((setting&0x3) == (XdrvMailbox.index-1))) { - if (*setting_chr_ptr == 0) - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR("|")); - setting_chr_ptr += snprintf_P(setting_chr_ptr, 2, PSTR("%d"), i+1); - - for (uint32_t j=0 ; j < 4 ; j++) { - int8_t pos = (((setting>> (2+6*j))&(0x3f))-1)<<1; - if (pos>=0) - setting_chr_ptr += snprintf_P(setting_chr_ptr, 5, PSTR(" %d"), pos); - else - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); - } - for (uint32_t j=0 ; j < 5 ; j++) { - bool mqtt = ((setting>>(26+j))&(0x01)!=0); - if (mqtt) - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" 1")); - else - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); - } - } - } - ResponseCmndIdxChar(setting_chr); - } -} - -void CmndShutterSetHalfway(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.shutter_set50percent[XdrvMailbox.index -1] = (Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; - ShutterInit(); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); - } -} - -void CmndShutterFrequency(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { - Shutter.max_pwm_frequency = XdrvMailbox.payload; - if (shutters_present < 4) { - Settings.shuttercoeff[4][3] = Shutter.max_pwm_frequency; - } - ShutterInit(); - ResponseCmndNumber(XdrvMailbox.payload); - } else { - ResponseCmndNumber(Shutter.max_pwm_frequency); - } -} - -void CmndShutterSetClose(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - Shutter.real_position[XdrvMailbox.index -1] = 0; - ShutterStartInit(XdrvMailbox.index -1, 0, 0); - Settings.shutter_position[XdrvMailbox.index -1] = 0; - ResponseCmndIdxChar(D_CONFIGURATION_RESET); - } -} - -void CmndShutterInvert(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.payload == 0) { - Settings.shutter_options[XdrvMailbox.index -1] &= ~(1); - } else if (XdrvMailbox.payload == 1) { - Settings.shutter_options[XdrvMailbox.index -1] |= (1); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 1 : 0); - } -} - -void CmndShutterCalibration(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - uint32_t i = 0; - char *str_ptr; - - char data_copy[strlen(XdrvMailbox.data) +1]; - strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); - - for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 5; str = strtok_r(nullptr, " ", &str_ptr), i++) { - int field = atoi(str); - - - if ((field <= 0) || (field > 30000) || ( (i>0) && (field <= messwerte[i-1]) ) ) { - break; - } - messwerte[i] = field; - } - for (i = 0; i < 5; i++) { - Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); - } - ShutterInit(); - ResponseCmndIdxChar(XdrvMailbox.data); - } else { - char setting_chr[30] = "0"; - snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings.shuttercoeff[0][XdrvMailbox.index -1], Settings.shuttercoeff[1][XdrvMailbox.index -1], Settings.shuttercoeff[2][XdrvMailbox.index -1], Settings.shuttercoeff[3][XdrvMailbox.index -1], Settings.shuttercoeff[4][XdrvMailbox.index -1]); - ResponseCmndIdxChar(setting_chr); - } - } -} - -void CmndShutterLock(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.payload == 0) { - Settings.shutter_options[XdrvMailbox.index -1] &= ~(2); - } else if (XdrvMailbox.payload == 1) { - Settings.shutter_options[XdrvMailbox.index -1] |= (2); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 2) ? 1 : 0); - } -} - -void CmndShutterEnableEndStopTime(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.payload == 0) { - Settings.shutter_options[XdrvMailbox.index -1] &= ~(4); - } else if (XdrvMailbox.payload == 1) { - Settings.shutter_options[XdrvMailbox.index -1] |= (4); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 4) ? 1 : 0); - } -} - - - - - -bool Xdrv27(uint8_t function) -{ - bool result = false; - - if (Settings.flag3.shutter_mode) { - switch (function) { - case FUNC_PRE_INIT: - ShutterInit(); - break; - case FUNC_EVERY_50_MSECOND: - ShutterUpdatePosition(); - break; - case FUNC_EVERY_SECOND: - - ShutterReportPosition(false); - break; - - case FUNC_COMMAND: - result = DecodeCommand(kShutterCommands, ShutterCommand); - break; - case FUNC_JSON_APPEND: - for (uint8_t i = 0; i < shutters_present; i++) { - uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; - ResponseAppend_P(","); - ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzSensor(DZ_SHUTTER, position); - } -#endif - } - break; - case FUNC_SET_POWER: - char stemp1[10]; - - Shutter.switched_relay = XdrvMailbox.index ^ Shutter.old_power; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), Shutter.switched_relay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); - ShutterRelayChanged(); - Shutter.old_power = XdrvMailbox.index; - break; - case FUNC_SET_DEVICE_POWER: - if (Shutter.skip_relay_change ) { - uint8_t i; - for (i = 0; i < devices_present; i++) { - if (Shutter.switched_relay &1) { - break; - } - Shutter.switched_relay >>= 1; - } - - result = true; - Shutter.skip_relay_change = 0; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"),i); - ExecuteCommandPower(i+1, 0, SRC_SHUTTER); - } - break; - case FUNC_BUTTON_PRESSED: - if (Settings.shutter_button[XdrvMailbox.index] & (1<<31)) { - ShutterButtonHandler(); - result = true; - } - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_28_pcf8574.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_28_pcf8574.ino" -#ifdef USE_I2C -#ifdef USE_PCF8574 - - - - - - - -#define XDRV_28 28 -#define XI2C_02 2 - -#define PCF8574_ADDR1 0x20 -#define PCF8574_ADDR2 0x38 - -struct PCF8574 { - int error; - uint8_t pin[64]; - uint8_t address[MAX_PCF8574]; - uint8_t pin_mask[MAX_PCF8574] = { 0 }; - uint8_t max_connected_ports = 0; - uint8_t max_devices = 0; - char stype[9]; - bool type = false; -} Pcf8574; - -void Pcf8574SwitchRelay(void) -{ - for (uint32_t i = 0; i < devices_present; i++) { - uint8_t relay_state = bitRead(XdrvMailbox.index, i); - - - - if (Pcf8574.max_devices > 0 && Pcf8574.pin[i] < 99) { - uint8_t board = Pcf8574.pin[i]>>3; - uint8_t oldpinmask = Pcf8574.pin_mask[board]; - uint8_t _val = bitRead(rel_inverted, i) ? !relay_state : relay_state; - - - - if (_val) { - Pcf8574.pin_mask[board] |= _val << (Pcf8574.pin[i]&0x7); - } else { - Pcf8574.pin_mask[board] &= ~(1 << (Pcf8574.pin[i]&0x7)); - } - if (oldpinmask != Pcf8574.pin_mask[board]) { - Wire.beginTransmission(Pcf8574.address[board]); - Wire.write(Pcf8574.pin_mask[board]); - Pcf8574.error = Wire.endTransmission(); - } - - } - } -} - -void Pcf8574Init(void) -{ - uint8_t pcf8574_address = PCF8574_ADDR1; - while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +8)) { - - - - if (I2cSetDevice(pcf8574_address)) { - Pcf8574.type = true; - - Pcf8574.address[Pcf8574.max_devices] = pcf8574_address; - Pcf8574.max_devices++; - - strcpy(Pcf8574.stype, "PCF8574"); - if (pcf8574_address >= PCF8574_ADDR2) { - strcpy(Pcf8574.stype, "PCF8574A"); - } - I2cSetActiveFound(pcf8574_address, Pcf8574.stype); - } - - pcf8574_address++; -#ifdef USE_MCP230xx_ADDR - if (USE_MCP230xx_ADDR == pcf8574_address) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Addr: 0x%x reserved for MCP320xx, skipping PCF8574 probe"), pcf8574_address); - pcf8574_address++; - } -#endif - if ((PCF8574_ADDR1 +7) == pcf8574_address) { - pcf8574_address = PCF8574_ADDR2 +1; - } - } - if (Pcf8574.type) { - for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { - Pcf8574.pin[i] = 99; - } - devices_present = devices_present - Pcf8574.max_connected_ports; - Pcf8574.max_connected_ports = 0; - for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Device %d config 0x%02x"), idx +1, Settings.pcf8574_config[idx]); - - for (uint32_t i = 0; i < 8; i++) { - uint8_t _result = Settings.pcf8574_config[idx] >> i &1; - - if (_result > 0) { - Pcf8574.pin[devices_present] = i + 8 * idx; - bitWrite(rel_inverted, devices_present, Settings.flag3.pcf8574_ports_inverted); - devices_present++; - Pcf8574.max_connected_ports++; - } - } - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Total devices %d, PCF8574 output ports %d"), Pcf8574.max_devices, Pcf8574.max_connected_ports); - } -} - - - - - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_PCF8574 "pcf" - -const char HTTP_BTN_MENU_PCF8574[] PROGMEM = - "

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

" D_INVERT_PORTS "


"; - -const char HTTP_FORM_I2C_PCF8574_2[] PROGMEM = - "" D_DEVICE " %d " D_PORT " %d"; - -void HandlePcf8574(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_PCF8574)); - - if (WebServer->hasArg("save")) { - Pcf8574SaveSettings(); - WebRestart(1); - return; - } - - WSContentStart_P(D_CONFIGURE_PCF8574); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? " checked" : ""); - WSContentSend_P(HTTP_TABLE100); - for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { - for (uint32_t idx2 = 0; idx2 < 8; idx2++) { - uint8_t helper = 1 << idx2; - WSContentSend_P(HTTP_FORM_I2C_PCF8574_2, - idx +1, idx2, - idx2 + 8*idx, - idx2 + 8*idx, - ((helper & Settings.pcf8574_config[idx]) >> idx2 == 0) ? " selected " : " ", - ((helper & Settings.pcf8574_config[idx]) >> idx2 == 1) ? " selected " : " " - ); - } - } - WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void Pcf8574SaveSettings(void) -{ - char stemp[7]; - char tmp[100]; - - - - Settings.flag3.pcf8574_ports_inverted = WebServer->hasArg("b1"); - for (byte idx = 0; idx < Pcf8574.max_devices; idx++) { - byte count=0; - byte n = Settings.pcf8574_config[idx]; - while(n!=0) { - n = n&(n-1); - count++; - } - if (count <= devices_present) { - devices_present = devices_present - count; - } - for (byte i = 0; i < 8; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("i2cs%d"), i+8*idx); - WebGetArg(stemp, tmp, sizeof(tmp)); - byte _value = (!strlen(tmp)) ? 0 : atoi(tmp); - if (_value) { - Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] | 1 << i; - devices_present++; - Pcf8574.max_connected_ports++; - } else { - Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] & ~(1 << i ); - } - } - - - - } -} -#endif - - - - - -bool Xdrv28(uint8_t function) -{ - if (!I2cEnabled(XI2C_02)) { return false; } - - bool result = false; - - if (FUNC_PRE_INIT == function) { - Pcf8574Init(); - } - else if (Pcf8574.type) { - switch (function) { - case FUNC_SET_POWER: - Pcf8574SwitchRelay(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_PCF8574); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_PCF8574, HandlePcf8574); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_29_deepsleep.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_29_deepsleep.ino" -#ifdef USE_DEEPSLEEP -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_29_deepsleep.ino" -#define XDRV_29 29 - -#define D_PRFX_DEEPSLEEP "DeepSleep" -#define D_CMND_DEEPSLEEP_TIME "Time" - -const uint32_t DEEPSLEEP_MAX = 10 * 366 * 24 * 60 * 60; -const uint32_t DEEPSLEEP_MAX_CYCLE = 60 * 60; -const uint32_t DEEPSLEEP_MIN_TIME = 5; -const uint32_t DEEPSLEEP_START_COUNTDOWN = 4; - -const char kDeepsleepCommands[] PROGMEM = D_PRFX_DEEPSLEEP "|" - D_CMND_DEEPSLEEP_TIME ; - -void (* const DeepsleepCommand[])(void) PROGMEM = { - &CmndDeepsleepTime }; - -uint32_t deepsleep_sleeptime = 0; -uint8_t deepsleep_flag = 0; - -bool DeepSleepEnabled(void) -{ - if ((Settings.deepsleep < 10) || (Settings.deepsleep > DEEPSLEEP_MAX)) { - Settings.deepsleep = 0; - return false; - } - - if (pin[GPIO_DEEPSLEEP] < 99) { - pinMode(pin[GPIO_DEEPSLEEP], INPUT_PULLUP); - return (digitalRead(pin[GPIO_DEEPSLEEP])); - } - - return true; -} - -void DeepSleepReInit(void) -{ - if ((ResetReason() == REASON_DEEP_SLEEP_AWAKE) && DeepSleepEnabled()) { - if ((RtcSettings.ultradeepsleep > DEEPSLEEP_MAX_CYCLE) && (RtcSettings.ultradeepsleep < 1700000000)) { - - RtcSettings.ultradeepsleep = RtcSettings.ultradeepsleep - DEEPSLEEP_MAX_CYCLE; - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Remain DeepSleep %d"), RtcSettings.ultradeepsleep); - RtcSettingsSave(); - RtcRebootReset(); - ESP.deepSleep(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep), WAKE_RF_DEFAULT); - yield(); - - } - } - - RtcSettings.ultradeepsleep = 0; -} - -void DeepSleepPrepare(void) -{ - - - - - if ((RtcSettings.nextwakeup == 0) || - (RtcSettings.deepsleep_slip < 9000) || - (RtcSettings.deepsleep_slip > 11000) || - (RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip ); - RtcSettings.nextwakeup = 0; - RtcSettings.deepsleep_slip = 10000; - } - - - - int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - UtcTime()) * 10; - - - - timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; - if (timeslip) { - RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5); - - RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); - RtcSettings.nextwakeup += Settings.deepsleep; - } - - - - if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) { - - RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep; - } - - String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); - - - deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_CYCLE ,RtcSettings.nextwakeup - UtcTime()); - - - Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATUS)); - - - -} - -void DeepSleepStart(void) -{ - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Sleeping")); - - WifiShutdown(); - RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); - RtcSettingsSave(); - - ESP.deepSleep(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); - yield(); -} - -void DeepSleepEverySecond(void) -{ - if (!deepsleep_flag) { return; } - - if (DeepSleepEnabled()) { - if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { - SettingsSaveAll(); - DeepSleepPrepare(); - } - deepsleep_flag--; - if (deepsleep_flag <= 0) { - DeepSleepStart(); - } - } else { - deepsleep_flag = 0; - } -} - - - - - -void CmndDeepsleepTime(void) -{ - if ((0 == XdrvMailbox.payload) || - ((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < DEEPSLEEP_MAX))) { - Settings.deepsleep = XdrvMailbox.payload; - RtcSettings.nextwakeup = 0; - deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN; - if (deepsleep_flag) { - if (!Settings.tele_period) { - Settings.tele_period = TELE_PERIOD; - } - } - } - Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.deepsleep); -} - - - - - -bool Xdrv29(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_SECOND: - DeepSleepEverySecond(); - break; - case FUNC_AFTER_TELEPERIOD: - if (DeepSleepEnabled() && !deepsleep_flag && (Settings.tele_period == 10 || Settings.tele_period == 300 || UpTime() > Settings.tele_period)) { - deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kDeepsleepCommands, DeepsleepCommand); - break; - case FUNC_PRE_INIT: - DeepSleepReInit(); - break; - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" -#ifdef USE_LIGHT -#ifdef USE_EXS_DIMMER - - - - - - - -#define XDRV_30 30 - -#define EXS_GATE_1_ON 0x20 -#define EXS_GATE_1_OFF 0x21 -#define EXS_DIMM_1_ON 0x22 -#define EXS_DIMM_1_OFF 0x23 -#define EXS_DIMM_1_TBL 0x24 -#define EXS_DIMM_1_VAL 0x25 -#define EXS_GATE_2_ON 0x30 -#define EXS_GATE_2_OFF 0x31 -#define EXS_DIMM_2_ON 0x32 -#define EXS_DIMM_2_OFF 0x33 -#define EXS_DIMM_2_TBL 0x34 -#define EXS_DIMM_2_VAL 0x35 -#define EXS_GATES_ON 0x40 -#define EXS_GATES_OFF 0x41 -#define EXS_DIMMS_ON 0x50 -#define EXS_DIMMS_OFF 0x51 -#define EXS_CH_LOCK 0x60 -#define EXS_GET_VALUES 0xFA -#define EXS_WRITE_EE 0xFC -#define EXS_READ_EE 0xFD -#define EXS_GET_VERSION 0xFE -#define EXS_RESET 0xFF - -#define EXS_BUFFER_SIZE 256 -#define EXS_ACK_TIMEOUT 200 - -#include - -TasmotaSerial *ExsSerial = nullptr; - -typedef struct -{ - uint8_t on = 0; - uint8_t bright_tbl = 0; - uint8_t dimm = 0; - uint8_t impuls_start = 0; - uint32_t impuls_len = 0; -} CHANNEL; - -typedef struct -{ - uint8_t version_major = 0; - uint8_t version_minor = 0; - CHANNEL channel[2]; - uint8_t gate_lock = 0; -} DIMMER; - -struct EXS -{ - uint8_t *buffer = nullptr; - int byte_counter = 0; - int cmd_status = 0; - uint8_t power = 0; - uint8_t dimm[2] = {0, 0}; - DIMMER dimmer; -} Exs; - - - - - -uint8_t crc8(const uint8_t *p, uint8_t len) -{ - const uint8_t table[] = { - 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, - 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D}; - - const uint8_t table_rev[] = { - 0x00, 0x70, 0xE0, 0x90, 0xC1, 0xB1, 0x21, 0x51, - 0x83, 0xF3, 0x63, 0x13, 0x42, 0x32, 0xA2, 0xD2}; - - uint8_t offset; - uint8_t temp, crc8_temp; - uint8_t crc8 = 0; - - for (int i = 0; i < len; i++) - { - temp = *(p + i); - offset = temp ^ crc8; - offset >>= 4; - crc8_temp = crc8 & 0x0f; - crc8 = crc8_temp ^ table_rev[offset]; - offset = crc8 ^ temp; - offset &= 0x0f; - crc8_temp = crc8 & 0xf0; - crc8 = crc8_temp ^ table[offset]; - } - return crc8 ^ 0x55; -} - -void ExsSerialSend(const uint8_t data[] = nullptr, uint16_t len = 0) -{ - int retries = 3; - char rc; - -#ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: Tx Packet: \"")); - for (uint32_t i = 0; i < len; i++) - { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, data[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); - AddLog(LOG_LEVEL_DEBUG_MORE); -#endif - - while (retries) - { - retries--; - - ExsSerial->write(data, len); - ExsSerial->flush(); - - - uint32_t snd_time = millis(); - while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && - (!ExsSerial->available())) - ; - - if (!ExsSerial->available()) - { - -#ifdef EXS_DEBUG - AddLog_P(LOG_LEVEL_DEBUG, PSTR("ESX: serial send timeout")); -#endif - continue; - } - - rc = ExsSerial->read(); - if (rc == 0xFF) - break; - } -} - -void ExsSendCmd(uint8_t cmd, uint8_t value) -{ - uint8_t buffer[8]; - uint16_t len; - - buffer[0] = 0x7b; - buffer[3] = cmd; - - switch (cmd) - { - case EXS_GATE_1_ON: - case EXS_GATE_1_OFF: - case EXS_DIMM_1_ON: - case EXS_DIMM_1_OFF: - case EXS_GATE_2_ON: - case EXS_GATE_2_OFF: - case EXS_DIMM_2_ON: - case EXS_DIMM_2_OFF: - case EXS_GATES_ON: - case EXS_GATES_OFF: - case EXS_DIMMS_ON: - case EXS_DIMMS_OFF: - case EXS_GET_VALUES: - case EXS_GET_VERSION: - case EXS_RESET: - buffer[2] = 1; - len = 4; - break; - - case EXS_CH_LOCK: - case EXS_DIMM_1_TBL: - case EXS_DIMM_1_VAL: - case EXS_DIMM_2_TBL: - case EXS_DIMM_2_VAL: - buffer[2] = 2; - buffer[4] = value; - len = 5; - break; - } - buffer[1] = crc8(&buffer[3], buffer[2]); - - ExsSerialSend(buffer, len); -} - -uint8_t ExsSetPower(uint8_t device, uint8_t power) -{ - Exs.dimmer.channel[device].dimm = power; - ExsSendCmd(EXS_DIMM_1_ON + 0x10 * device + power ^ 1, 0); -} - -uint8_t ExsSetBri(uint8_t device, uint8_t bri) -{ - Exs.dimmer.channel[device].bright_tbl = bri; - ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * device, bri); -} - -uint8_t ExsSyncState(uint8_t device) -{ -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Channel %d Power Want %d, Is %d"), - device, bitRead(Exs.power, device), Exs.dimmer.channel[device].dimm); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Set Channel %d Brightness Want %d, Is %d"), - device, Exs.dimm[device], Exs.dimmer.channel[device].bright_tbl); -#endif - - if (bitRead(Exs.power, device) && - Exs.dimm[device] != Exs.dimmer.channel[device].bright_tbl) { - ExsSetBri(device, Exs.dimm[device]); - } - - if (!Exs.dimm[device]) { - Exs.dimmer.channel[device].dimm = 0; - } else if (Exs.dimmer.channel[device].dimm != bitRead(Exs.power, device)) { - ExsSetPower(device, bitRead(Exs.power, device)); - } -} - -bool ExsSyncState() -{ -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Serial %p, Cmd %d"), ExsSerial, Exs.cmd_status); -#endif - - if (!ExsSerial || Exs.cmd_status != 0) - return false; - - ExsSyncState(0); - ExsSyncState(1); -} - -void ExsDebugState() -{ -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: MCU v%d.%d, c0: On:%d,Dim:%d,Tbl:%d(%d%%), c1: On:%d,Dim:%d,Tbl:%d(%d%%), ChLock: %d"), - Exs.dimmer.version_major, Exs.dimmer.version_minor, - Exs.dimmer.channel[0].on, Exs.dimmer.channel[0].dimm, - Exs.dimmer.channel[0].bright_tbl, - changeUIntScale(Exs.dimmer.channel[0].bright_tbl, 0, 255, 0, 100), - Exs.dimmer.channel[1].on, Exs.dimmer.channel[1].dimm, - Exs.dimmer.channel[1].bright_tbl, - changeUIntScale(Exs.dimmer.channel[1].bright_tbl, 0, 255, 0, 100), - Exs.dimmer.gate_lock); -#endif -} - -void ExsPacketProcess(void) -{ - uint8_t len = Exs.buffer[1]; - uint8_t cmd = Exs.buffer[2]; - - switch (cmd) - { - case EXS_GET_VALUES: -# 294 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" - if (len > 9) - { - Exs.dimmer.version_major = Exs.buffer[3]; - Exs.dimmer.version_minor = Exs.buffer[4]; - - - Exs.dimmer.channel[0].on = Exs.buffer[6]; - Exs.dimmer.channel[0].dimm = Exs.buffer[6]; - Exs.dimmer.channel[0].bright_tbl = Exs.buffer[7]; - - - Exs.dimmer.channel[1].on = Exs.buffer[9]; - Exs.dimmer.channel[1].dimm = Exs.buffer[9]; - Exs.dimmer.channel[1].bright_tbl = Exs.buffer[10]; - - Exs.dimmer.gate_lock = Exs.buffer[11]; - } - else -# 327 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" - { - Exs.dimmer.version_major = 1; - Exs.dimmer.version_minor = 0; - - - Exs.dimmer.channel[0].on = Exs.buffer[4] - 48; - Exs.dimmer.channel[0].dimm = Exs.buffer[4] - 48; - Exs.dimmer.channel[0].bright_tbl = Exs.buffer[5] - 48; - - - Exs.dimmer.channel[1].on = Exs.buffer[7] - 48; - Exs.dimmer.channel[1].dimm = Exs.buffer[7] - 48; - Exs.dimmer.channel[1].bright_tbl = Exs.buffer[8] - 48; - - Exs.dimmer.gate_lock = Exs.buffer[9] - 48; - } - - ExsDebugState(); - ExsSyncState(); - ExsDebugState(); - break; - default: - break; - } -} - - - -bool ExsModuleSelected(void) -{ - Settings.light_correction = 0; - Settings.flag.mqtt_serial = 0; - Settings.flag3.pwm_multi_channels = 1; - SetSeriallog(LOG_LEVEL_NONE); - - devices_present = +2; - light_type = LT_SERIAL2; - return true; -} - -bool ExsSetChannels(void) -{ -#ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: SetChannels: \"")); - for (int i = 0; i < XdrvMailbox.data_len; i++) - { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, ((uint8_t *)XdrvMailbox.data)[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); - AddLog(LOG_LEVEL_DEBUG_MORE); -#endif - - Exs.dimm[0] = ((uint8_t *)XdrvMailbox.data)[0]; - Exs.dimm[1] = ((uint8_t *)XdrvMailbox.data)[1]; - return ExsSyncState(); -} - -bool ExsSetPower(void) -{ - AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Set Power, Device %d, Power 0x%02x"), - active_device, XdrvMailbox.index); - - Exs.power = XdrvMailbox.index; - return ExsSyncState(); -} - -void EsxMcuStart(void) -{ - int retries = 3; - -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Request MCU configuration, PIN %d to Low"), pin[GPIO_EXS_ENABLE]); -#endif - - pinMode(pin[GPIO_EXS_ENABLE], OUTPUT); - digitalWrite(pin[GPIO_EXS_ENABLE], LOW); - - delay(1); - - while (ExsSerial->available()) - { - - ExsSerial->read(); - } -} - -void ExsInit(void) -{ -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Starting Tx %d Rx %d"), pin[GPIO_TXD], pin[GPIO_RXD]); -#endif - - Exs.buffer = (uint8_t *)malloc(EXS_BUFFER_SIZE); - if (Exs.buffer != nullptr) - { - ExsSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (ExsSerial->begin(9600)) - { - if (ExsSerial->hardwareSerial()) - { - ClaimSerial(); - } - ExsSerial->flush(); - EsxMcuStart(); - ExsSendCmd(EXS_CH_LOCK, 0); - ExsSendCmd(EXS_GET_VALUES, 0); - } - } -} - -void ExsSerialInput(void) -{ - while (ExsSerial->available()) - { - yield(); - uint8_t serial_in_byte = ExsSerial->read(); - - AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Serial In Byte 0x%02x"), serial_in_byte); - - if (Exs.cmd_status == 0 && - serial_in_byte == 0x7B) - { - Exs.cmd_status = 1; - Exs.byte_counter = 0; - } - else if (Exs.byte_counter >= EXS_BUFFER_SIZE) - { - Exs.cmd_status = 0; - } - else if (Exs.cmd_status == 1) - { - Exs.buffer[Exs.byte_counter++] = serial_in_byte; - - if (Exs.byte_counter > 2 && Exs.byte_counter == Exs.buffer[1] + 2) - { - uint8_t crc = crc8(&Exs.buffer[2], Exs.buffer[1]); - - - Exs.cmd_status = 0; - -#ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: RX Packet: \"")); - for (uint32_t i = 0; i < Exs.byte_counter; i++) - { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Exs.buffer[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\", CRC: 0x%02x"), log_data, crc); - AddLog(LOG_LEVEL_DEBUG_MORE); -#endif - - if (Exs.buffer[0] == crc) - { - ExsSerial->write(0xFF); - ExsPacketProcess(); - } - else - { - ExsSerial->write(0x00); - } - - } - } - } -} - - - - - -#ifdef EXS_MCU_CMNDS - -#define D_PRFX_EXS "Exs" -#define D_CMND_EXS_DIMM "Dimm" -#define D_CMND_EXS_DIMM_TBL "DimmTbl" -#define D_CMND_EXS_DIMM_VAL "DimmVal" -#define D_CMND_EXS_DIMMS "Dimms" -#define D_CMND_EXS_CH_LOCK "ChLock" -#define D_CMND_EXS_STATE "State" - -const char kExsCommands[] PROGMEM = D_PRFX_EXS "|" - D_CMND_EXS_DIMM "|" D_CMND_EXS_DIMM_TBL "|" D_CMND_EXS_DIMM_VAL "|" - D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" - D_CMND_EXS_STATE; - -void (* const ExsCommand[])(void) PROGMEM = { - &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, - &CmndExsDimms, &CmndExsChLock, - &CmndExsState }; - -void CmndExsDimm(void) -{ - if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && - (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1)) { - ExsSendCmd(EXS_DIMM_1_ON + 0x10 * (XdrvMailbox.index - 1) + - XdrvMailbox.payload ^ 1, 0); - } - CmndExsState(); -} - -void CmndExsDimmTbl(void) -{ - if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && - (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { - ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * (XdrvMailbox.index - 1), - XdrvMailbox.payload); - } - CmndExsState(); -} - -void CmndExsDimmVal(void) -{ - if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && - (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { - ExsSendCmd(EXS_DIMM_1_VAL + 0x10 * (XdrvMailbox.index - 1), - XdrvMailbox.payload); - } - CmndExsState(); -} - -void CmndExsDimms(void) -{ - if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { - ExsSendCmd(EXS_DIMMS_ON + XdrvMailbox.payload ^ 1, 0); - } - CmndExsState(); -} - -void CmndExsChLock(void) -{ - if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { - ExsSendCmd(EXS_CH_LOCK, XdrvMailbox.payload); - } - CmndExsState(); -} - -void CmndExsState(void) -{ - ExsSendCmd(EXS_GET_VALUES, 0); - - - uint32_t snd_time = millis(); - while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && - (!ExsSerial->available())) - ; - ExsSerialInput(); - - Response_P(PSTR("{\"" D_CMND_EXS_STATE "\":{")); - ResponseAppend_P(PSTR("\"McuVersion\":\"%d.%d\"," - "\"Channels\":["), - Exs.dimmer.version_major, Exs.dimmer.version_minor); - - for (uint32_t i = 0; i < 2; i++) { - if (i != 0) { - ResponseAppend_P(PSTR(",")); - } - ResponseAppend_P(PSTR("{\"On\":\"%d\"," - "\"BrightProz\":\"%d\"," - "\"BrightTab\":\"%d\"," - "\"Dimm\":\"%d\"}"), - Exs.dimmer.channel[i].on, - changeUIntScale(Exs.dimmer.channel[i].bright_tbl, 0, 255, 0, 100), - Exs.dimmer.channel[i].bright_tbl, - Exs.dimmer.channel[i].dimm); - } - ResponseAppend_P(PSTR("],")); - ResponseAppend_P(PSTR("\"GateLock\":\"%d\""), Exs.dimmer.gate_lock); - ResponseJsonEndEnd(); -} - -#endif - - - - - -bool Xdrv30(uint8_t function) -{ - bool result = false; - - if (EXS_DIMMER == my_module_type) - { - switch (function) - { - case FUNC_LOOP: - if (ExsSerial) - ExsSerialInput(); - break; - case FUNC_MODULE_INIT: - result = ExsModuleSelected(); - break; - case FUNC_INIT: - ExsInit(); - break; - case FUNC_SET_DEVICE_POWER: - result = ExsSetPower(); - break; - case FUNC_SET_CHANNELS: - result = ExsSetChannels(); - break; -#ifdef EXS_MCU_CMNDS - case FUNC_COMMAND: - result = DecodeCommand(kExsCommands, ExsCommand); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_31_tasmota_slave.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_31_tasmota_slave.ino" -#ifdef USE_TASMOTA_SLAVE - - - - -#define XDRV_31 31 - -#define CONST_STK_CRC_EOP 0x20 - -#define CMND_STK_GET_SYNC 0x30 -#define CMND_STK_SET_DEVICE 0x42 -#define CMND_STK_SET_DEVICE_EXT 0x45 -#define CMND_STK_ENTER_PROGMODE 0x50 -#define CMND_STK_LEAVE_PROGMODE 0x51 -#define CMND_STK_LOAD_ADDRESS 0x55 -#define CMND_STK_PROG_PAGE 0x64 - - - - - -#define CMND_START 0xFC -#define CMND_END 0xFD - -#define CMND_FEATURES 0x01 -#define CMND_JSON 0x02 -#define CMND_FUNC_EVERY_SECOND 0x03 -#define CMND_FUNC_EVERY_100_MSECOND 0x04 -#define CMND_SLAVE_SEND 0x05 -#define CMND_PUBLISH_TELE 0x06 -#define CMND_EXECUTE_CMND 0x07 - -#define PARAM_DATA_START 0xFE -#define PARAM_DATA_END 0xFF - -#include - - - - - -class SimpleHexParse { - public: - SimpleHexParse(void); - uint8_t parseLine(char *hexline); - uint8_t ptr_l = 0; - uint8_t ptr_h = 0; - bool PageIsReady = false; - bool firstrun = true; - bool EndOfFile = false; - uint8_t FlashPage[128]; - uint8_t FlashPageIdx = 0; - uint8_t layoverBuffer[16]; - uint8_t layoverIdx = 0; - uint8_t getByte(char *hexline, uint8_t idx); -}; - -SimpleHexParse::SimpleHexParse(void) -{ - -} - -uint8_t SimpleHexParse::parseLine(char *hexline) -{ - if (layoverIdx) { - memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx); - FlashPageIdx = layoverIdx; - layoverIdx = 0; - } - uint8_t len = getByte(hexline, 1); - uint8_t addr_h = getByte(hexline, 2); - uint8_t addr_l = getByte(hexline, 3); - uint8_t rectype = getByte(hexline, 4); - for (uint8_t idx = 0; idx < len; idx++) { - if (FlashPageIdx < 128) { - FlashPage[FlashPageIdx] = getByte(hexline, idx+5); - FlashPageIdx++; - } else { - layoverBuffer[layoverIdx] = getByte(hexline, idx+5); - layoverIdx++; - } - } - if (1 == rectype) { - EndOfFile = true; - while (FlashPageIdx < 128) { - FlashPage[FlashPageIdx] = 0xFF; - FlashPageIdx++; - } - } - if (FlashPageIdx == 128) { - if (firstrun) { - firstrun = false; - } else { - ptr_l += 0x40; - if (ptr_l == 0) { - ptr_l = 0; - ptr_h++; - } - } - firstrun = false; - PageIsReady = true; - } - return 0; -} - -uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) -{ - char buff[3]; - buff[3] = '\0'; - memcpy(&buff, &hexline[(idx*2)-1], 2); - return strtol(buff, 0, 16); -} - - - - - -struct TSLAVE { - uint32_t spi_hex_size = 0; - uint32_t spi_sector_counter = 0; - uint8_t spi_sector_cursor = 0; - uint8_t inverted = LOW; - bool type = false; - bool flashing = false; - bool SerialEnabled = false; - uint8_t waitstate = 0; - bool unsupported = false; -} TSlave; - -typedef union { - uint32_t data; - struct { - uint32_t func_json_append : 1; - uint32_t func_every_second : 1; - uint32_t func_every_100_msecond : 1; - uint32_t func_slave_send : 1; - uint32_t spare4 : 1; - uint32_t spare5 : 1; - uint32_t spare6 : 1; - uint32_t spare7 : 1; - uint32_t spare8 : 1; - uint32_t spare9 : 1; - uint32_t spare10 : 1; - uint32_t spare11 : 1; - uint32_t spare12 : 1; - uint32_t spare13 : 1; - uint32_t spare14 : 1; - uint32_t spare15 : 1; - uint32_t spare16 : 1; - uint32_t spare17 : 1; - uint32_t spare18 : 1; - uint32_t spare19 : 1; - uint32_t spare20 : 1; - uint32_t spare21 : 1; - uint32_t spare22 : 1; - uint32_t spare23 : 1; - uint32_t spare24 : 1; - uint32_t spare25 : 1; - uint32_t spare26 : 1; - uint32_t spare27 : 1; - uint32_t spare28 : 1; - uint32_t spare29 : 1; - uint32_t spare30 : 1; - uint32_t spare31 : 1; - }; -} TSlaveFeatureCfg; - - - - - - -struct TSLAVE_FEATURES { - uint32_t features_version; - TSlaveFeatureCfg features; -} TSlaveSettings; - -struct TSLAVE_COMMAND { - uint8_t command; - uint8_t parameter; - uint8_t unused2; - uint8_t unused3; -} TSlaveCommand; - -TasmotaSerial *TasmotaSlave_Serial; - -uint32_t TasmotaSlave_FlashStart(void) -{ - return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; -} - -uint8_t TasmotaSlave_UpdateInit(void) -{ - TSlave.spi_hex_size = 0; - TSlave.spi_sector_counter = TasmotaSlave_FlashStart(); - TSlave.spi_sector_cursor = 0; - return 0; -} - -void TasmotaSlave_Reset(void) -{ - if (TSlave.SerialEnabled) { - digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); - delay(1); - digitalWrite(pin[GPIO_TASMOTASLAVE_RST], TSlave.inverted); - delay(1); - digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); - delay(5); - } -} - -uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout) -{ - int timer = 0; - while (timer < timeout) { - if (TasmotaSlave_Serial->available() >= dataCount) { - return 1; - } - delay(1); - timer++; - } - return 0; -} - -uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count) -{ - TasmotaSlave_Serial->write(bytes, count); - TasmotaSlave_waitForSerialData(2, 250); - uint8_t sync = TasmotaSlave_Serial->read(); - uint8_t ok = TasmotaSlave_Serial->read(); - if ((sync == 0x14) && (ok == 0x10)) { - return 1; - } - return 0; -} - -uint8_t TasmotaSlave_execCmd(uint8_t cmd) -{ - uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP }; - return TasmotaSlave_sendBytes(bytes, 2); -} - -uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count) -{ - uint8_t bytes[32]; - bytes[0] = cmd; - int i = 0; - while (i < count) { - bytes[i + 1] = params[i]; - i++; - } - bytes[i + 1] = CONST_STK_CRC_EOP; - return TasmotaSlave_sendBytes(bytes, i + 2); -} - -uint8_t TasmotaSlave_exitProgMode(void) -{ - return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); -} - -uint8_t TasmotaSlave_SetupFlash(void) -{ - uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; - uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00}; - TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_FLASH_SPEED); - if (TasmotaSlave_Serial->hardwareSerial()) { - ClaimSerial(); - } - - TasmotaSlave_Reset(); - - uint8_t timeout = 0; - uint8_t no_error = 0; - while (50 > timeout) { - if (TasmotaSlave_execCmd(CMND_STK_GET_SYNC)) { - timeout = 200; - no_error = 1; - } - timeout++; - delay(1); - } - if (no_error) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Found bootloader")); - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Bootloader could not be found")); - } - if (no_error) { - if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (1)")); - } - } - if (no_error) { - if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (2)")); - } - } - if (no_error) { - if (TasmotaSlave_execCmd(CMND_STK_ENTER_PROGMODE)) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Failed to put bootloader into programming mode")); - } - } - return no_error; -} - -uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo) -{ - uint8_t params[] = { adrLo, adrHi }; - return TasmotaSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); -} - -void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) -{ - uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; - TasmotaSlave_loadAddress(addr_h, addr_l); - TasmotaSlave_Serial->write(Header, 4); - for (int i = 0; i < 128; i++) { - TasmotaSlave_Serial->write(data[i]); - } - TasmotaSlave_Serial->write(CONST_STK_CRC_EOP); - TasmotaSlave_waitForSerialData(2, 250); - TasmotaSlave_Serial->read(); - TasmotaSlave_Serial->read(); -} - -void TasmotaSlave_Flash(void) -{ - bool reading = true; - uint32_t read = 0; - uint32_t processed = 0; - char thishexline[50]; - uint8_t position = 0; - char* flash_buffer; - - SimpleHexParse hexParse = SimpleHexParse(); - - if (!TasmotaSlave_SetupFlash()) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flashing aborted!")); - TSlave.flashing = false; - restart_flag = 2; - return; - } - - flash_buffer = new char[SPI_FLASH_SEC_SIZE]; - uint32_t flash_start = TasmotaSlave_FlashStart() * SPI_FLASH_SEC_SIZE; - while (reading) { - ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); - read = read + SPI_FLASH_SEC_SIZE; - if (read >= TSlave.spi_hex_size) { - reading = false; - } - for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) { - processed++; - if ((processed <= TSlave.spi_hex_size) && (!hexParse.EndOfFile)) { - if (':' == flash_buffer[ca]) { - position = 0; - } - if (0x0D == flash_buffer[ca]) { - thishexline[position] = 0; - hexParse.parseLine(thishexline); - if (hexParse.PageIsReady) { - TasmotaSlave_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage); - hexParse.PageIsReady = false; - hexParse.FlashPageIdx = 0; - } - } else { - if (0x0A != flash_buffer[ca]) { - thishexline[position] = flash_buffer[ca]; - position++; - } - } - } - } - } - TasmotaSlave_exitProgMode(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flash done!")); - TSlave.flashing = false; - restart_flag = 2; -} - -void TasmotaSlave_SetFlagFlashing(bool value) -{ - TSlave.flashing = value; -} - -bool TasmotaSlave_GetFlagFlashing(void) -{ - return TSlave.flashing; -} - -void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size) -{ - if (0 == TSlave.spi_sector_cursor) { - ESP.flashEraseSector(TSlave.spi_sector_counter); - } - TSlave.spi_sector_cursor++; - ESP.flashWrite((TSlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TSlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size); - TSlave.spi_hex_size = TSlave.spi_hex_size + size; - if (2 == TSlave.spi_sector_cursor) { - TSlave.spi_sector_cursor = 0; - TSlave.spi_sector_counter++; - } -} - -void TasmotaSlave_Init(void) -{ - if (TSlave.type) { - return; - } - if (10 > TSlave.waitstate) { - TSlave.waitstate++; - return; - } - if (!TSlave.SerialEnabled) { - if ((pin[GPIO_TASMOTASLAVE_RXD] < 99) && (pin[GPIO_TASMOTASLAVE_TXD] < 99) && - ((pin[GPIO_TASMOTASLAVE_RST] < 99) || (pin[GPIO_TASMOTASLAVE_RST_INV] < 99))) { - TasmotaSlave_Serial = new TasmotaSerial(pin[GPIO_TASMOTASLAVE_RXD], pin[GPIO_TASMOTASLAVE_TXD], 1, 0, 200); - if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) { - if (TasmotaSlave_Serial->hardwareSerial()) { - ClaimSerial(); - } - TasmotaSlave_Serial->setTimeout(50); - if (pin[GPIO_TASMOTASLAVE_RST_INV] < 99) { - pin[GPIO_TASMOTASLAVE_RST] = pin[GPIO_TASMOTASLAVE_RST_INV]; - pin[GPIO_TASMOTASLAVE_RST_INV] = 99; - TSlave.inverted = HIGH; - } - pinMode(pin[GPIO_TASMOTASLAVE_RST], OUTPUT); - TSlave.SerialEnabled = true; - TasmotaSlave_Reset(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Enabled")); - } - } - } - if (TSlave.SerialEnabled) { - TasmotaSlave_sendCmnd(CMND_FEATURES, 0); - char buffer[32]; - TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); - uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); - memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings)); - if (20191129 == TSlaveSettings.features_version) { - TSlave.type = true; - AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version); - } else { - if ((!TSlave.unsupported) && (TSlaveSettings.features_version > 0)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u not supported!"), TSlaveSettings.features_version); - TSlave.unsupported = true; - } - } - } -} - -void TasmotaSlave_Show(void) -{ - if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { - char buffer[100]; - TasmotaSlave_sendCmnd(CMND_JSON, 0); - TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); - uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1); - buffer[len] = '\0'; - ResponseAppend_P(PSTR(",\"TasmotaSlave\":%s"), buffer); - } -} - -void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param) -{ - TSlaveCommand.command = cmnd; - TSlaveCommand.parameter = param; - char buffer[sizeof(TSlaveCommand)+2]; - buffer[0] = CMND_START; - memcpy(&buffer[1], &TSlaveCommand, sizeof(TSlaveCommand)); - buffer[sizeof(TSlaveCommand)+1] = CMND_END; - for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { - TasmotaSlave_Serial->write(buffer[ca]); - } -} - -#define D_PRFX_SLAVE "Slave" -#define D_CMND_SLAVE_RESET "Reset" -#define D_CMND_SLAVE_SEND "Send" - -const char kTasmotaSlaveCommands[] PROGMEM = D_PRFX_SLAVE "|" - D_CMND_SLAVE_RESET "|" D_CMND_SLAVE_SEND; - -void (* const TasmotaSlaveCommand[])(void) PROGMEM = { - &CmndTasmotaSlaveReset, &CmndTasmotaSlaveSend }; - -void CmndTasmotaSlaveReset(void) -{ - TasmotaSlave_Reset(); - TSlave.type = false; - TSlave.waitstate = 7; - TSlave.unsupported = false; - ResponseCmndDone(); -} - -void CmndTasmotaSlaveSend(void) -{ - if (0 < XdrvMailbox.data_len) { - TasmotaSlave_sendCmnd(CMND_SLAVE_SEND, XdrvMailbox.data_len); - TasmotaSlave_Serial->write(char(PARAM_DATA_START)); - for (uint8_t idx = 0; idx < XdrvMailbox.data_len; idx++) { - TasmotaSlave_Serial->write(XdrvMailbox.data[idx]); - } - TasmotaSlave_Serial->write(char(PARAM_DATA_END)); - } - ResponseCmndDone(); -} - -void TasmotaSlave_ProcessIn(void) -{ - uint8_t cmnd = TasmotaSlave_Serial->read(); - switch (cmnd) { - case CMND_START: - TasmotaSlave_waitForSerialData(sizeof(TSlaveCommand),50); - uint8_t buffer[sizeof(TSlaveCommand)]; - for (uint8_t idx = 0; idx < sizeof(TSlaveCommand); idx++) { - buffer[idx] = TasmotaSlave_Serial->read(); - } - TasmotaSlave_Serial->read(); - memcpy(&TSlaveCommand, &buffer, sizeof(TSlaveCommand)); - char inbuf[TSlaveCommand.parameter+1]; - TasmotaSlave_waitForSerialData(TSlaveCommand.parameter, 50); - TasmotaSlave_Serial->read(); - for (uint8_t idx = 0; idx < TSlaveCommand.parameter; idx++) { - inbuf[idx] = TasmotaSlave_Serial->read(); - } - TasmotaSlave_Serial->read(); - inbuf[TSlaveCommand.parameter] = '\0'; - - if (CMND_PUBLISH_TELE == TSlaveCommand.command) { - Response_P(PSTR("{\"TasmotaSlave\":")); - ResponseAppend_P("%s", inbuf); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - XdrvRulesProcess(); - } - if (CMND_EXECUTE_CMND == TSlaveCommand.command) { - ExecuteCommand(inbuf, SRC_IGNORE); - } - break; - default: - break; - } -} - - - - - - -bool Xdrv31(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_100_MSECOND: - if (TSlave.type) { - if (TasmotaSlave_Serial->available()) { - TasmotaSlave_ProcessIn(); - } - if (TSlaveSettings.features.func_every_100_msecond) { - TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0); - } - } - break; - case FUNC_EVERY_SECOND: - if ((TSlave.type) && (TSlaveSettings.features.func_every_second)) { - TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_SECOND, 0); - } - TasmotaSlave_Init(); - break; - case FUNC_JSON_APPEND: - if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { - TasmotaSlave_Show(); - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kTasmotaSlaveCommands, TasmotaSlaveCommand); - break; - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_32_hotplug.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_32_hotplug.ino" -#ifdef USE_HOTPLUG - - - - - - - -#define XDRV_32 32 - -const uint32_t HOTPLUG_MAX = 254; - -const char kHotPlugCommands[] PROGMEM = "|" - D_CMND_HOTPLUG; - -void (* const HotPlugCommand[])(void) PROGMEM = { - &CmndHotPlugTime }; - -struct { - - bool enabled = false; - uint8_t timeout = 0; -} Hotplug; - -void HotPlugInit(void) -{ - - if (Settings.hotplug_scan == 0xFF) { Settings.hotplug_scan = 0; } - if (Settings.hotplug_scan != 0) { - Hotplug.enabled = true; - Hotplug.timeout = 1; - } else - Hotplug.enabled = false; -} - -void HotPlugEverySecond(void) -{ - if (Hotplug.enabled) { - if (Hotplug.timeout == 0) { - XsnsCall(FUNC_HOTPLUG_SCAN); - Hotplug.timeout = Settings.hotplug_scan; - } - Hotplug.timeout--; - } -} - - - - - -void CmndHotPlugTime(void) -{ - if (XdrvMailbox.payload <= HOTPLUG_MAX) { - Settings.hotplug_scan = XdrvMailbox.payload; - HotPlugInit(); - } - ResponseCmndNumber(Settings.hotplug_scan); -} - - - - - -bool Xdrv32(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_SECOND: - HotPlugEverySecond(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kHotPlugCommands, HotPlugCommand); - break; - case FUNC_PRE_INIT: - HotPlugInit(); - break; - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_33_nrf24l01.ino" -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_33_nrf24l01.ino" -#ifdef USE_SPI -#ifdef USE_NRF24 - - - - - - - -#define XDRV_33 33 - -#define MOSI 13 -#define MISO 12 -#define SCK 14 - -#include -#include - -const char NRF24type[] PROGMEM = "NRF24"; - -const char HTTP_NRF24[] PROGMEM = - "{s}%sL01%c: " "{m}started{e}"; - -struct { - uint8_t chipType = 0; -} NRF24; - - - -RF24 NRF24radio; - -bool NRF24initRadio() -{ - NRF24radio.begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_DC]); - NRF24radio.powerUp(); - - if(NRF24radio.isChipConnected()){ - DEBUG_DRIVER_LOG(PSTR("NRF24 chip connected")); - return true; - } - DEBUG_DRIVER_LOG(PSTR("NRF24 chip NOT !!!! connected")); - return false; -} - -bool NRF24Detect(void) -{ - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_DC]<99)){ - SPI.pins(SCK,MOSI,MISO,-1); - if(NRF24initRadio()){ - NRF24.chipType = 32; - AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01 initialized")); - if(NRF24radio.isPVariant()){ - NRF24.chipType = 43; - AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01+ detected")); - } - return true; - } - } - return false; -} - - - - - -bool Xdrv33(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - result = NRF24Detect(); - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" -# 22 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" -#ifdef DEBUG_THEO -#ifndef USE_DEBUG_DRIVER -#define USE_DEBUG_DRIVER -#endif -#endif - -#ifdef USE_DEBUG_DRIVER - - - - - - -#define XDRV_99 99 - -#ifndef CPU_LOAD_CHECK -#define CPU_LOAD_CHECK 1 -#endif - - - - - -#define D_CMND_CFGDUMP "CfgDump" -#define D_CMND_CFGPEEK "CfgPeek" -#define D_CMND_CFGPOKE "CfgPoke" -#define D_CMND_CFGSHOW "CfgShow" -#define D_CMND_CFGXOR "CfgXor" -#define D_CMND_CPUCHECK "CpuChk" -#define D_CMND_EXCEPTION "Exception" -#define D_CMND_FLASHDUMP "FlashDump" -#define D_CMND_FLASHMODE "FlashMode" -#define D_CMND_FREEMEM "FreeMem" -#define D_CMND_HELP "Help" -#define D_CMND_RTCDUMP "RtcDump" -#define D_CMND_SETSENSOR "SetSensor" -#define D_CMND_I2CWRITE "I2CWrite" -#define D_CMND_I2CREAD "I2CRead" -#define D_CMND_I2CSTRETCH "I2CStretch" -#define D_CMND_I2CCLOCK "I2CClock" - -const char kDebugCommands[] PROGMEM = "|" - D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" -#ifdef USE_WEBSERVER - D_CMND_CFGXOR "|" -#endif - D_CMND_CPUCHECK "|" -#ifdef DEBUG_THEO - D_CMND_EXCEPTION "|" -#endif - D_CMND_FLASHDUMP "|" D_CMND_FLASHMODE "|" D_CMND_FREEMEM"|" D_CMND_HELP "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|" -#ifdef USE_I2C - D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK -#endif - ; - -void (* const DebugCommand[])(void) PROGMEM = { - &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, -#ifdef USE_WEBSERVER - &CmndCfgXor, -#endif - &CmndCpuCheck, -#ifdef DEBUG_THEO - &CmndException, -#endif - &CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor, -#ifdef USE_I2C - &CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock -#endif - }; - -uint32_t CPU_loops = 0; -uint32_t CPU_last_millis = 0; -uint32_t CPU_last_loop_time = 0; -uint8_t CPU_load_check = 0; -uint8_t CPU_show_freemem = 0; - - - -#ifdef DEBUG_THEO -void ExceptionTest(uint8_t type) -{ -# 145 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" - if (1 == type) { - char svalue[10]; - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); - } -# 159 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" - if (2 == type) { - while(1) delay(1000); - } -} - -#endif - - - -void CpuLoadLoop(void) -{ - CPU_last_loop_time = millis(); - if (CPU_load_check && CPU_last_millis) { - CPU_loops ++; - if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { -#if defined(F_CPU) && (F_CPU == 160000000L) - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); - CPU_loops = CPU_loops / CPU_load_check; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); -#else - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); - CPU_loops = CPU_loops / CPU_load_check; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); -#endif - CPU_last_millis = CPU_last_loop_time; - CPU_loops = 0; - } - } -} - - - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) - - - -extern "C" { -#include - extern cont_t g_cont; -} - -void DebugFreeMem(void) -{ - register uint32_t *sp asm("a1"); - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); -} - -#else - - - - -extern "C" { -#include - extern cont_t* g_pcont; -} - -void DebugFreeMem(void) -{ - register uint32_t *sp asm("a1"); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); -} - -#endif - - - -void DebugRtcDump(char* parms) -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; -# 246 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_99_debug.ino" - uint8_t buffer[768]; - - system_rtc_mem_read(0, (uint32_t*)&buffer, sizeof(buffer)); - - maxrow = ((sizeof(buffer)+CFG_COLS)/CFG_COLS); - - uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; - uint16_t mrow = strtol(p, &p, 10); - - - - if (0 == mrow) { - mrow = 8; - } - if (srow > maxrow) { - srow = maxrow - mrow; - } - if (mrow < (maxrow - srow)) { - maxrow = srow + mrow; - } - - for (row = srow; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { - - - - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); - AddLog(LOG_LEVEL_INFO); - } -} - - - -void DebugCfgDump(char* parms) -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; - - uint8_t *buffer = (uint8_t *) &Settings; - maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); - - uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; - uint16_t mrow = strtol(p, &p, 10); - - - - if (0 == mrow) { - mrow = 8; - } - if (srow > maxrow) { - srow = maxrow - mrow; - } - if (mrow < (maxrow - srow)) { - maxrow = srow + mrow; - } - - for (row = srow; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { - - - - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); - AddLog(LOG_LEVEL_INFO); - delay(1); - } -} - -void DebugCfgPeek(char* parms) -{ - char *p; - - uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; - address = (address >> 2) << 2; - - uint8_t *buffer = (uint8_t *) &Settings; - uint8_t data8 = buffer[address]; - uint16_t data16 = (buffer[address +1] << 8) + buffer[address]; - uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; - - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); - for (uint32_t i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (uint32_t i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); - AddLog(LOG_LEVEL_INFO); -} - -void DebugCfgPoke(char* parms) -{ - char *p; - - uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; - address = (address >> 2) << 2; - - uint32_t data = strtol(p, &p, 16); - - uint8_t *buffer = (uint8_t *) &Settings; - uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - - uint8_t *nbuffer = (uint8_t *) &data; - for (uint32_t i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } - - uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); -} - -void SetFlashMode(uint8_t mode) -{ - uint8_t *_buffer; - uint32_t address; - - address = 0; - _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - - if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { - if (_buffer[2] != mode) { - _buffer[2] = mode; - if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { - ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); - } - } - } - delete[] _buffer; -} - - - - - -void CmndHelp(void) -{ - AddLog_P(LOG_LEVEL_INFO, PSTR("HLP: "), kDebugCommands); - ResponseCmndDone(); -} - -void CmndRtcDump(void) -{ - DebugRtcDump(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgDump(void) -{ - DebugCfgDump(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgPeek(void) -{ - DebugCfgPeek(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgPoke(void) -{ - DebugCfgPoke(XdrvMailbox.data); - ResponseCmndDone(); -} - -#ifdef USE_WEBSERVER -void CmndCfgXor(void) -{ - if (XdrvMailbox.data_len > 0) { - Web.config_xor_on_set = XdrvMailbox.payload; - } - ResponseCmndNumber(Web.config_xor_on_set); -} -#endif - -#ifdef DEBUG_THEO -void CmndException(void) -{ - if (XdrvMailbox.data_len > 0) { ExceptionTest(XdrvMailbox.payload); } - ResponseCmndDone(); -} -#endif - -void CmndCpuCheck(void) -{ - if (XdrvMailbox.data_len > 0) { - CPU_load_check = XdrvMailbox.payload; - CPU_last_millis = CPU_last_loop_time; - } - ResponseCmndNumber(CPU_load_check); -} - -void CmndFreemem(void) -{ - if (XdrvMailbox.data_len > 0) { - CPU_show_freemem = XdrvMailbox.payload; - } - ResponseCmndNumber(CPU_show_freemem); -} - -void CmndSetSensor(void) -{ - if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { - if (XdrvMailbox.payload >= 0) { - bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - if (1 == XdrvMailbox.payload) { - restart_flag = 2; - } - } - Response_P(PSTR("{\"" D_CMND_SETSENSOR "\":")); - XsnsSensorState(); - ResponseJsonEnd(); - } -} - -void CmndFlashMode(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - SetFlashMode(XdrvMailbox.payload); - } - ResponseCmndNumber(ESP.getFlashChipMode()); -} - -uint32_t DebugSwap32(uint32_t x) { - return ((x << 24) & 0xff000000 ) | - ((x << 8) & 0x00ff0000 ) | - ((x >> 8) & 0x0000ff00 ) | - ((x >> 24) & 0x000000ff ); -} - -void CmndFlashDump(void) -{ - - - - const uint32_t flash_start = 0x40200000; - const uint8_t bytes_per_cols = 0x20; - const uint32_t max = (SPIFFS_END + 5) * SPI_FLASH_SEC_SIZE; - - uint32_t start = flash_start; - uint32_t rows = 8; - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= (max - bytes_per_cols))) { - start += (XdrvMailbox.payload &0x7FFFFFFC); - - char *p; - uint32_t is_payload = strtol(XdrvMailbox.data, &p, 16); - rows = strtol(p, &p, 10); - if (0 == rows) { rows = 8; } - } - uint32_t end = start + (rows * bytes_per_cols); - if ((end - flash_start) > max) { - end = flash_start + max; - } - - for (uint32_t pos = start; pos < end; pos += bytes_per_cols) { - uint32_t* values = (uint32_t*)(pos); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%06X: %08X %08X %08X %08X %08X %08X %08X %08X"), pos - flash_start, - DebugSwap32(values[0]), DebugSwap32(values[1]), DebugSwap32(values[2]), DebugSwap32(values[3]), - DebugSwap32(values[4]), DebugSwap32(values[5]), DebugSwap32(values[6]), DebugSwap32(values[7])); - } - ResponseCmndDone(); -} - -#ifdef USE_I2C -void CmndI2cWrite(void) -{ - - if (i2c_flg) { - char* parms = XdrvMailbox.data; - uint8_t buffer[100]; - uint32_t index = 0; - - char *p; - char *data = strtok_r(parms, " ,", &p); - while (data != NULL && index < sizeof(buffer)) { - buffer[index++] = strtol(data, nullptr, 16); - data = strtok_r(nullptr, " ,", &p); - } - - if (index > 1) { - AddLogBuffer(LOG_LEVEL_INFO, buffer, index); - - Wire.beginTransmission(buffer[0]); - for (uint32_t i = 1; i < index; i++) { - Wire.write(buffer[i]); - } - int result = Wire.endTransmission(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: Result %d"), result); - } - } - ResponseCmndDone(); -} - -void CmndI2cRead(void) -{ - - if (i2c_flg) { - char* parms = XdrvMailbox.data; - uint8_t buffer[100]; - uint32_t index = 0; - - char *p; - char *data = strtok_r(parms, " ,", &p); - while (data != NULL && index < sizeof(buffer)) { - buffer[index++] = strtol(data, nullptr, 16); - data = strtok_r(nullptr, " ,", &p); - } - - if (index > 0) { - uint8_t size = 1; - if (index > 1) { - size = buffer[1]; - } - Wire.requestFrom(buffer[0], size); - index = 0; - while (Wire.available() && index < sizeof(buffer)) { - buffer[index++] = Wire.read(); - } - if (index > 0) { - AddLogBuffer(LOG_LEVEL_INFO, buffer, index); - } - } - } - ResponseCmndDone(); -} - -void CmndI2cStretch(void) -{ - if (i2c_flg && (XdrvMailbox.payload > 0)) { - Wire.setClockStretchLimit(XdrvMailbox.payload); - } - ResponseCmndDone(); -} - -void CmndI2cClock(void) -{ - if (i2c_flg && (XdrvMailbox.payload > 0)) { - Wire.setClock(XdrvMailbox.payload); - } - ResponseCmndDone(); -} -#endif - - - - - -bool Xdrv99(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - CpuLoadLoop(); - break; - case FUNC_FREE_MEM: - if (CPU_show_freemem) { DebugFreeMem(); } - break; - case FUNC_PRE_INIT: - CPU_last_millis = millis(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kDebugCommands, DebugCommand); - break; - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_interface.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdrv_interface.ino" -#ifdef XFUNC_PTR_IN_ROM -bool (* const xdrv_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xdrv_func_ptr[])(uint8_t) = { -#endif - -#ifdef XDRV_01 - &Xdrv01, -#endif - -#ifdef XDRV_02 - &Xdrv02, -#endif - -#ifdef XDRV_03 - &Xdrv03, -#endif - -#ifdef XDRV_04 - &Xdrv04, -#endif - -#ifdef XDRV_05 - &Xdrv05, -#endif - -#ifdef XDRV_06 - &Xdrv06, -#endif - -#ifdef XDRV_07 - &Xdrv07, -#endif - -#ifdef XDRV_08 - &Xdrv08, -#endif - -#ifdef XDRV_09 - &Xdrv09, -#endif - -#ifdef XDRV_10 - &Xdrv10, -#endif - -#ifdef XDRV_11 - &Xdrv11, -#endif - -#ifdef XDRV_12 - &Xdrv12, -#endif - -#ifdef XDRV_13 - &Xdrv13, -#endif - -#ifdef XDRV_14 - &Xdrv14, -#endif - -#ifdef XDRV_15 - &Xdrv15, -#endif - -#ifdef XDRV_16 - &Xdrv16, -#endif - -#ifdef XDRV_17 - &Xdrv17, -#endif - -#ifdef XDRV_18 - &Xdrv18, -#endif - -#ifdef XDRV_19 - &Xdrv19, -#endif - -#ifdef XDRV_20 - &Xdrv20, -#endif - -#ifdef XDRV_21 - &Xdrv21, -#endif - -#ifdef XDRV_22 - &Xdrv22, -#endif - -#ifdef XDRV_23 - &Xdrv23, -#endif - -#ifdef XDRV_24 - &Xdrv24, -#endif - -#ifdef XDRV_25 - &Xdrv25, -#endif - -#ifdef XDRV_26 - &Xdrv26, -#endif - -#ifdef XDRV_27 - &Xdrv27, -#endif - -#ifdef XDRV_28 - &Xdrv28, -#endif - -#ifdef XDRV_29 - &Xdrv29, -#endif - -#ifdef XDRV_30 - &Xdrv30, -#endif - -#ifdef XDRV_31 - &Xdrv31, -#endif - -#ifdef XDRV_32 - &Xdrv32, -#endif - -#ifdef XDRV_33 - &Xdrv33, -#endif - -#ifdef XDRV_34 - &Xdrv34, -#endif - -#ifdef XDRV_35 - &Xdrv35, -#endif - -#ifdef XDRV_36 - &Xdrv36, -#endif - -#ifdef XDRV_37 - &Xdrv37, -#endif - -#ifdef XDRV_38 - &Xdrv38, -#endif - -#ifdef XDRV_39 - &Xdrv39, -#endif - -#ifdef XDRV_40 - &Xdrv40, -#endif - -#ifdef XDRV_41 - &Xdrv41, -#endif - -#ifdef XDRV_42 - &Xdrv42, -#endif - -#ifdef XDRV_43 - &Xdrv43, -#endif - -#ifdef XDRV_44 - &Xdrv44, -#endif - -#ifdef XDRV_45 - &Xdrv45, -#endif - -#ifdef XDRV_46 - &Xdrv46, -#endif - -#ifdef XDRV_47 - &Xdrv47, -#endif - -#ifdef XDRV_48 - &Xdrv48, -#endif - -#ifdef XDRV_49 - &Xdrv49, -#endif - -#ifdef XDRV_50 - &Xdrv50, -#endif - -#ifdef XDRV_51 - &Xdrv51, -#endif - -#ifdef XDRV_52 - &Xdrv52, -#endif - -#ifdef XDRV_53 - &Xdrv53, -#endif - -#ifdef XDRV_54 - &Xdrv54, -#endif - -#ifdef XDRV_55 - &Xdrv55, -#endif - -#ifdef XDRV_56 - &Xdrv56, -#endif - -#ifdef XDRV_57 - &Xdrv57, -#endif - -#ifdef XDRV_58 - &Xdrv58, -#endif - -#ifdef XDRV_59 - &Xdrv59, -#endif - -#ifdef XDRV_60 - &Xdrv60, -#endif - -#ifdef XDRV_61 - &Xdrv61, -#endif - -#ifdef XDRV_62 - &Xdrv62, -#endif - -#ifdef XDRV_63 - &Xdrv63, -#endif - -#ifdef XDRV_64 - &Xdrv64, -#endif - -#ifdef XDRV_65 - &Xdrv65, -#endif - -#ifdef XDRV_66 - &Xdrv66, -#endif - -#ifdef XDRV_67 - &Xdrv67, -#endif - -#ifdef XDRV_68 - &Xdrv68, -#endif - -#ifdef XDRV_69 - &Xdrv69, -#endif - -#ifdef XDRV_70 - &Xdrv70, -#endif - -#ifdef XDRV_71 - &Xdrv71, -#endif - -#ifdef XDRV_72 - &Xdrv72, -#endif - -#ifdef XDRV_73 - &Xdrv73, -#endif - -#ifdef XDRV_74 - &Xdrv74, -#endif - -#ifdef XDRV_75 - &Xdrv75, -#endif - -#ifdef XDRV_76 - &Xdrv76, -#endif - -#ifdef XDRV_77 - &Xdrv77, -#endif - -#ifdef XDRV_78 - &Xdrv78, -#endif - -#ifdef XDRV_79 - &Xdrv79, -#endif - -#ifdef XDRV_80 - &Xdrv80, -#endif - -#ifdef XDRV_81 - &Xdrv81, -#endif - -#ifdef XDRV_82 - &Xdrv82, -#endif - -#ifdef XDRV_83 - &Xdrv83, -#endif - -#ifdef XDRV_84 - &Xdrv84, -#endif - -#ifdef XDRV_85 - &Xdrv85, -#endif - -#ifdef XDRV_86 - &Xdrv86, -#endif - -#ifdef XDRV_87 - &Xdrv87, -#endif - -#ifdef XDRV_88 - &Xdrv88, -#endif - -#ifdef XDRV_89 - &Xdrv89, -#endif - -#ifdef XDRV_90 - &Xdrv90, -#endif - -#ifdef XDRV_91 - &Xdrv91, -#endif - -#ifdef XDRV_92 - &Xdrv92, -#endif - -#ifdef XDRV_93 - &Xdrv93, -#endif - -#ifdef XDRV_94 - &Xdrv94, -#endif - -#ifdef XDRV_95 - &Xdrv95, -#endif - -#ifdef XDRV_96 - &Xdrv96, -#endif - -#ifdef XDRV_97 - &Xdrv97, -#endif - -#ifdef XDRV_98 - &Xdrv98, -#endif - -#ifdef XDRV_99 - &Xdrv99 -#endif -}; - -const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); - - - - - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXdrvList[] PROGMEM = { -#else -const uint8_t kXdrvList[] = { -#endif - -#ifdef XDRV_01 - XDRV_01, -#endif - -#ifdef XDRV_02 - XDRV_02, -#endif - -#ifdef XDRV_03 - XDRV_03, -#endif - -#ifdef XDRV_04 - XDRV_04, -#endif - -#ifdef XDRV_05 - XDRV_05, -#endif - -#ifdef XDRV_06 - XDRV_06, -#endif - -#ifdef XDRV_07 - XDRV_07, -#endif - -#ifdef XDRV_08 - XDRV_08, -#endif - -#ifdef XDRV_09 - XDRV_09, -#endif - -#ifdef XDRV_10 - XDRV_10, -#endif - -#ifdef XDRV_11 - XDRV_11, -#endif - -#ifdef XDRV_12 - XDRV_12, -#endif - -#ifdef XDRV_13 - XDRV_13, -#endif - -#ifdef XDRV_14 - XDRV_14, -#endif - -#ifdef XDRV_15 - XDRV_15, -#endif - -#ifdef XDRV_16 - XDRV_16, -#endif - -#ifdef XDRV_17 - XDRV_17, -#endif - -#ifdef XDRV_18 - XDRV_18, -#endif - -#ifdef XDRV_19 - XDRV_19, -#endif - -#ifdef XDRV_20 - XDRV_20, -#endif - -#ifdef XDRV_21 - XDRV_21, -#endif - -#ifdef XDRV_22 - XDRV_22, -#endif - -#ifdef XDRV_23 - XDRV_23, -#endif - -#ifdef XDRV_24 - XDRV_24, -#endif - -#ifdef XDRV_25 - XDRV_25, -#endif - -#ifdef XDRV_26 - XDRV_26, -#endif - -#ifdef XDRV_27 - XDRV_27, -#endif - -#ifdef XDRV_28 - XDRV_28, -#endif - -#ifdef XDRV_29 - XDRV_29, -#endif - -#ifdef XDRV_30 - XDRV_30, -#endif - -#ifdef XDRV_31 - XDRV_31, -#endif - -#ifdef XDRV_32 - XDRV_32, -#endif - -#ifdef XDRV_33 - XDRV_33, -#endif - -#ifdef XDRV_34 - XDRV_34, -#endif - -#ifdef XDRV_35 - XDRV_35, -#endif - -#ifdef XDRV_36 - XDRV_36, -#endif - -#ifdef XDRV_37 - XDRV_37, -#endif - -#ifdef XDRV_38 - XDRV_38, -#endif - -#ifdef XDRV_39 - XDRV_39, -#endif - -#ifdef XDRV_40 - XDRV_40, -#endif - -#ifdef XDRV_41 - XDRV_41, -#endif - -#ifdef XDRV_42 - XDRV_42, -#endif - -#ifdef XDRV_43 - XDRV_43, -#endif - -#ifdef XDRV_44 - XDRV_44, -#endif - -#ifdef XDRV_45 - XDRV_45, -#endif - -#ifdef XDRV_46 - XDRV_46, -#endif - -#ifdef XDRV_47 - XDRV_47, -#endif - -#ifdef XDRV_48 - XDRV_48, -#endif - -#ifdef XDRV_49 - XDRV_49, -#endif - -#ifdef XDRV_50 - XDRV_50, -#endif - -#ifdef XDRV_51 - XDRV_51, -#endif - -#ifdef XDRV_52 - XDRV_52, -#endif - -#ifdef XDRV_53 - XDRV_53, -#endif - -#ifdef XDRV_54 - XDRV_54, -#endif - -#ifdef XDRV_55 - XDRV_55, -#endif - -#ifdef XDRV_56 - XDRV_56, -#endif - -#ifdef XDRV_57 - XDRV_57, -#endif - -#ifdef XDRV_58 - XDRV_58, -#endif - -#ifdef XDRV_59 - XDRV_59, -#endif - -#ifdef XDRV_60 - XDRV_60, -#endif - -#ifdef XDRV_61 - XDRV_61, -#endif - -#ifdef XDRV_62 - XDRV_62, -#endif - -#ifdef XDRV_63 - XDRV_63, -#endif - -#ifdef XDRV_64 - XDRV_64, -#endif - -#ifdef XDRV_65 - XDRV_65, -#endif - -#ifdef XDRV_66 - XDRV_66, -#endif - -#ifdef XDRV_67 - XDRV_67, -#endif - -#ifdef XDRV_68 - XDRV_68, -#endif - -#ifdef XDRV_69 - XDRV_69, -#endif - -#ifdef XDRV_70 - XDRV_70, -#endif - -#ifdef XDRV_71 - XDRV_71, -#endif - -#ifdef XDRV_72 - XDRV_72, -#endif - -#ifdef XDRV_73 - XDRV_73, -#endif - -#ifdef XDRV_74 - XDRV_74, -#endif - -#ifdef XDRV_75 - XDRV_75, -#endif - -#ifdef XDRV_76 - XDRV_76, -#endif - -#ifdef XDRV_77 - XDRV_77, -#endif - -#ifdef XDRV_78 - XDRV_78, -#endif - -#ifdef XDRV_79 - XDRV_79, -#endif - -#ifdef XDRV_80 - XDRV_80, -#endif - -#ifdef XDRV_81 - XDRV_81, -#endif - -#ifdef XDRV_82 - XDRV_82, -#endif - -#ifdef XDRV_83 - XDRV_83, -#endif - -#ifdef XDRV_84 - XDRV_84, -#endif - -#ifdef XDRV_85 - XDRV_85, -#endif - -#ifdef XDRV_86 - XDRV_86, -#endif - -#ifdef XDRV_87 - XDRV_87, -#endif - -#ifdef XDRV_88 - XDRV_88, -#endif - -#ifdef XDRV_89 - XDRV_89, -#endif - -#ifdef XDRV_90 - XDRV_90, -#endif - -#ifdef XDRV_91 - XDRV_91, -#endif - -#ifdef XDRV_92 - XDRV_92, -#endif - -#ifdef XDRV_93 - XDRV_93, -#endif - -#ifdef XDRV_94 - XDRV_94, -#endif - -#ifdef XDRV_95 - XDRV_95, -#endif - -#ifdef XDRV_96 - XDRV_96, -#endif - -#ifdef XDRV_97 - XDRV_97, -#endif - -#ifdef XDRV_98 - XDRV_98, -#endif - -#ifdef XDRV_99 - XDRV_99 -#endif -}; - - - -void XsnsDriverState(void) -{ - ResponseAppend_P(PSTR(",\"Drivers\":\"")); - for (uint32_t i = 0; i < sizeof(kXdrvList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t driverid = pgm_read_byte(kXdrvList + i); -#else - uint32_t driverid = kXdrvList[i]; -#endif - ResponseAppend_P(PSTR("%s%d"), (i) ? "," : "", driverid); - } - ResponseAppend_P(PSTR("\"")); -} - - - -bool XdrvRulesProcess(void) -{ - return XdrvCallDriver(10, FUNC_RULES_PROCESS); -} - -#ifdef USE_DEBUG_DRIVER -void ShowFreeMem(const char *where) -{ - char stemp[30]; - snprintf_P(stemp, sizeof(stemp), where); - XdrvMailbox.data = stemp; - XdrvCall(FUNC_FREE_MEM); -} -#endif - - - - - -bool XdrvCallDriver(uint32_t driver, uint8_t Function) -{ - for (uint32_t x = 0; x < xdrv_present; x++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t listed = pgm_read_byte(kXdrvList + x); -#else - uint32_t listed = kXdrvList[x]; -#endif - if (driver == listed) { - return xdrv_func_ptr[x](Function); - } - } - return false; -} - - - - - -bool XdrvCall(uint8_t Function) -{ - bool result = false; - - DEBUG_TRACE_LOG(PSTR("DRV: %d"), Function); - - for (uint32_t x = 0; x < xdrv_present; x++) { - result = xdrv_func_ptr[x](Function); - - if (result && ((FUNC_COMMAND == Function) || - (FUNC_COMMAND_DRIVER == Function) || - (FUNC_MQTT_DATA == Function) || - (FUNC_RULES_PROCESS == Function) || - (FUNC_BUTTON_PRESSED == Function) || - (FUNC_SERIAL == Function) || - (FUNC_MODULE_INIT == Function) || - (FUNC_SET_CHANNELS == Function) || - (FUNC_PIN_STATE == Function) || - (FUNC_SET_DEVICE_POWER == Function) - )) { - break; - } - } - - return result; -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_01_lcd.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_01_lcd.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_LCD - -#define XDSP_01 1 -#define XI2C_03 3 - -#define LCD_ADDRESS1 0x27 -#define LCD_ADDRESS2 0x3F - -#include -#include - -LiquidCrystal_I2C *lcd; - - - -void LcdInitMode(void) -{ - lcd->init(); - lcd->clear(); -} - -void LcdInit(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - LcdInitMode(); -#ifdef USE_DISPLAY_MODES1TO5 - DisplayClearScreenBuffer(); -#endif - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void LcdInitDriver(void) -{ - if (!Settings.display_model) { - if (I2cSetDevice(LCD_ADDRESS1)) { - Settings.display_address[0] = LCD_ADDRESS1; - Settings.display_model = XDSP_01; - } - else if (I2cSetDevice(LCD_ADDRESS2)) { - Settings.display_address[0] = LCD_ADDRESS2; - Settings.display_model = XDSP_01; - } - } - - if (XDSP_01 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "LCD"); - - Settings.display_width = Settings.display_cols[0]; - Settings.display_height = Settings.display_rows; - lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows); - -#ifdef USE_DISPLAY_MODES1TO5 - DisplayAllocScreenBuffer(); -#endif - - LcdInitMode(); - } -} - -void LcdDrawStringAt(void) -{ - if (dsp_flag) { - dsp_x--; - dsp_y--; - } - lcd->setCursor(dsp_x, dsp_y); - lcd->print(dsp_str); -} - -void LcdDisplayOnOff(uint8_t on) -{ - if (on) { - lcd->backlight(); - } else { - lcd->noBacklight(); - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void LcdCenter(uint8_t row, char* txt) -{ - char line[Settings.display_cols[0] +2]; - - int len = strlen(txt); - int offset = 0; - if (len >= Settings.display_cols[0]) { - len = Settings.display_cols[0]; - } else { - offset = (Settings.display_cols[0] - len) / 2; - } - memset(line, 0x20, Settings.display_cols[0]); - line[Settings.display_cols[0]] = 0; - for (uint32_t i = 0; i < len; i++) { - line[offset +i] = txt[i]; - } - lcd->setCursor(0, row); - lcd->print(line); -} - -bool LcdPrintLog(void) -{ - bool result = false; - - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\337'); - if (txt != nullptr) { - uint8_t last_row = Settings.display_rows -1; - - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - lcd->setCursor(0, i); - lcd->print(disp_screen_buffer[i +1]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - lcd->setCursor(0, last_row); - lcd->print(disp_screen_buffer[last_row]); - - result = true; - } - } - return result; -} - -void LcdTime(void) -{ - char line[Settings.display_cols[0] +1]; - - snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - LcdCenter(0, line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - LcdCenter(1, line); -} - -void LcdRefresh(void) -{ - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - LcdTime(); - break; - case 2: - case 4: - LcdPrintLog(); - break; - case 3: - case 5: { - if (!LcdPrintLog()) { LcdTime(); } - break; - } - } - } -} - -#endif - - - - - -bool Xdsp01(uint8_t function) -{ - if (!I2cEnabled(XI2C_03)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - LcdInitDriver(); - } - else if (XDSP_01 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - LcdInit(dsp_init); - break; - case FUNC_DISPLAY_POWER: - LcdDisplayOnOff(disp_power); - break; - case FUNC_DISPLAY_CLEAR: - lcd->clear(); - break; -# 238 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_01_lcd.ino" - case FUNC_DISPLAY_DRAW_STRING: - LcdDrawStringAt(); - break; - case FUNC_DISPLAY_ONOFF: - LcdDisplayOnOff(dsp_on); - break; - - -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - LcdRefresh(); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_02_ssd1306.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_02_ssd1306.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SSD1306 - -#define XDSP_02 2 -#define XI2C_04 4 - -#define OLED_RESET 4 - -#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); - -#define OLED_ADDRESS1 0x3C -#define OLED_ADDRESS2 0x3D - -#define OLED_BUFFER_COLS 40 -#define OLED_BUFFER_ROWS 16 - -#define OLED_FONT_WIDTH 6 -#define OLED_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_SSD1306 *oled1306; - -extern uint8_t *buffer; - - - -void SSD1306InitDriver(void) -{ - if (!Settings.display_model) { - if (I2cSetDevice(OLED_ADDRESS1)) { - Settings.display_address[0] = OLED_ADDRESS1; - Settings.display_model = XDSP_02; - } - else if (I2cSetDevice(OLED_ADDRESS2)) { - Settings.display_address[0] = OLED_ADDRESS2; - Settings.display_model = XDSP_02; - } - } - - if (XDSP_02 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "SSD1306"); - - if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) { - Settings.display_width = 128; - } - if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 48) && (Settings.display_height != 64)) { - Settings.display_height = 64; - } - - uint8_t reset_pin = -1; - if (pin[GPIO_OLED_RESET] < 99) { - reset_pin = pin[GPIO_OLED_RESET]; - } - - - if (buffer) { free(buffer); } - buffer = (unsigned char*)calloc((Settings.display_width * Settings.display_height) / 8,1); - if (!buffer) { return; } - - - - oled1306 = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, reset_pin); - oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], reset_pin >= 0); - renderer = oled1306; - renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - renderer->setTextFont(0); - renderer->setTextSize(2); - renderer->setCursor(20,20); - renderer->println(F("SSD1306")); - renderer->Updateframe(); - renderer->DisplayOnff(1); -#endif - - } -} - - -#ifdef USE_DISPLAY_MODES1TO5 - -void Ssd1306PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void Ssd1306Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setTextFont(Settings.display_font); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void Ssd1306Refresh(void) -{ - if (!renderer) return; - - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - Ssd1306Time(); - break; - case 2: - case 3: - case 4: - case 5: - Ssd1306PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp02(byte function) -{ - if (!I2cEnabled(XI2C_04)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SSD1306InitDriver(); - } - else if (XDSP_02 == Settings.display_model) { - switch (function) { -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - Ssd1306Refresh(); - break; -#endif - case FUNC_DISPLAY_MODEL: - result = true; - break; - } - } - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_03_matrix.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_03_matrix.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_MATRIX - -#define XDSP_03 3 -#define XI2C_05 5 - -#define MTX_MAX_SCREEN_BUFFER 80 - -#include -#include -#include - -Adafruit_8x8matrix *matrix[8]; -uint8_t mtx_matrices = 0; -uint8_t mtx_state = 0; -uint8_t mtx_counter = 0; -int16_t mtx_x = 0; -int16_t mtx_y = 0; - - -char *mtx_buffer = nullptr; - -uint8_t mtx_mode = 0; -uint8_t mtx_loop = 0; -uint8_t mtx_done = 0; - - - -void MatrixWrite(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->writeDisplay(); - } -} - -void MatrixClear(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - } - MatrixWrite(); -} - -void MatrixFixed(char* txt) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(-i *8, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); -} - -void MatrixCenter(char* txt) -{ - int offset; - - int len = strlen(txt); - offset = (len < 8) ? offset = ((mtx_matrices *8) - (len *6)) / 2 : 0; - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(-(i *8)+offset, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); -} - -void MatrixScrollLeft(char* txt, int loop) -{ - switch (mtx_state) { - case 1: - mtx_state = 2; - - mtx_x = 8 * mtx_matrices; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), txt); - - disp_refresh = Settings.display_refresh; - case 2: - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(mtx_x - i *8, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); - - mtx_x--; - int16_t len = strlen(txt); - if (mtx_x < -(len *6)) { mtx_state = loop; } - } - break; - } -} - -void MatrixScrollUp(char* txt, int loop) -{ - int wordcounter = 0; - char tmpbuf[200]; - char *words[100]; - - - - char separators[] = " /"; - - switch (mtx_state) { - case 1: - mtx_state = 2; - - mtx_y = 8; - mtx_counter = 0; - disp_refresh = Settings.display_refresh; - case 2: - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - strlcpy(tmpbuf, txt, sizeof(tmpbuf)); - char *p = strtok(tmpbuf, separators); - while (p != nullptr && wordcounter < 40) { - words[wordcounter++] = p; - p = strtok(nullptr, separators); - } - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - for (uint32_t j = 0; j < wordcounter; j++) { - matrix[i]->setCursor(-i *8, mtx_y + (j *8)); - matrix[i]->println(words[j]); - } - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); - if (((mtx_y %8) == 0) && mtx_counter) { - mtx_counter--; - } else { - mtx_y--; - mtx_counter = STATES * 1; - } - if (mtx_y < -(wordcounter *8)) { mtx_state = loop; } - } - break; - } -} - - - -void MatrixInitMode(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->setRotation(Settings.display_rotate); - matrix[i]->setBrightness(Settings.display_dimmer); - matrix[i]->blinkRate(0); - matrix[i]->setTextWrap(false); - - - matrix[i]->cp437(true); - } - MatrixClear(); -} - -void MatrixInit(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - MatrixInitMode(); - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void MatrixInitDriver(void) -{ - mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); - if (mtx_buffer != nullptr) { - if (!Settings.display_model) { - if (I2cSetDevice(Settings.display_address[1])) { - Settings.display_model = XDSP_03; - } - } - - if (XDSP_03 == Settings.display_model) { - mtx_state = 1; - for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) { - if (Settings.display_address[mtx_matrices]) { - I2cSetActiveFound(Settings.display_address[mtx_matrices], "8x8Matrix"); - matrix[mtx_matrices] = new Adafruit_8x8matrix(); - matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]); - } else { - break; - } - } - - Settings.display_width = mtx_matrices * 8; - Settings.display_height = 8; - - MatrixInitMode(); - } - } -} - -void MatrixOnOff(void) -{ - if (!disp_power) { MatrixClear(); } -} - -void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - strlcpy(mtx_buffer, str, MTX_MAX_SCREEN_BUFFER); - mtx_mode = x &1; - mtx_loop = y &1; - if (!mtx_state) { mtx_state = 1; } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void MatrixPrintLog(uint8_t direction) -{ - char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer; - if (txt != nullptr) { - if (!mtx_state) { mtx_state = 1; } - - if (!mtx_done) { - - uint8_t space = 0; - uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER; - mtx_buffer[0] = '\0'; - uint8_t i = 0; - while ((txt[i] != '\0') && (i < max_cols)) { - if (txt[i] == ' ') { - space++; - } else { - space = 0; - } - if (space < 2) { - strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < MTX_MAX_SCREEN_BUFFER -1) ? 1 : 0); - } - i++; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); - - mtx_done = 1; - } - - if (direction) { - MatrixScrollUp(mtx_buffer, 0); - } else { - MatrixScrollLeft(mtx_buffer, 0); - } - if (!mtx_state) { mtx_done = 0; } - } else { - char disp_time[9]; - - snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - MatrixFixed(disp_time); - } -} - -#endif - -void MatrixRefresh(void) -{ - if (disp_power) { - switch (Settings.display_mode) { - case 0: { - switch (mtx_mode) { - case 0: - MatrixScrollLeft(mtx_buffer, mtx_loop); - break; - case 1: - MatrixScrollUp(mtx_buffer, mtx_loop); - break; - } - break; - } -#ifdef USE_DISPLAY_MODES1TO5 - case 2: { - char disp_date[9]; - snprintf_P(disp_date, sizeof(disp_date), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); - MatrixFixed(disp_date); - break; - } - case 3: { - char disp_day[10]; - snprintf_P(disp_day, sizeof(disp_day), PSTR("%d %s"), RtcTime.day_of_month, RtcTime.name_of_month); - MatrixCenter(disp_day); - break; - } - case 4: - MatrixPrintLog(0); - break; - case 1: - case 5: - MatrixPrintLog(1); - break; -#endif - } - } -} - - - - - -bool Xdsp03(uint8_t function) -{ - if (!I2cEnabled(XI2C_05)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - MatrixInitDriver(); - } - else if (XDSP_03 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - MatrixInit(dsp_init); - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: - MatrixRefresh(); - break; - case FUNC_DISPLAY_POWER: - MatrixOnOff(); - break; - case FUNC_DISPLAY_DRAW_STRING: - MatrixDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); - break; - } - } - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_04_ili9341.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_04_ili9341.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9341 - -#define XDSP_04 4 - -#define TFT_TOP 16 -#define TFT_BOTTOM 16 -#define TFT_FONT_WIDTH 6 -#define TFT_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_ILI9341 *tft; - -uint16_t tft_scroll; - - - -void Ili9341InitMode(void) -{ - tft->setRotation(Settings.display_rotate); - tft->invertDisplay(0); - tft->fillScreen(ILI9341_BLACK); - tft->setTextWrap(false); - tft->cp437(true); - if (!Settings.display_mode) { - tft->setCursor(0, 0); - tft->setTextColor(ILI9341_WHITE, ILI9341_BLACK); - tft->setTextSize(1); - } else { - tft->setScrollMargins(TFT_TOP, TFT_BOTTOM); - tft->setCursor(0, 0); - tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); - tft->setTextSize(2); - - - tft_scroll = TFT_TOP; - } -} - -void Ili9341Init(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - Ili9341InitMode(); -#ifdef USE_DISPLAY_MODES1TO5 - if (Settings.display_rotate) { - DisplayClearScreenBuffer(); - } -#endif - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void Ili9341InitDriver(void) -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_04; - } - - if (XDSP_04 == Settings.display_model) { - if (Settings.display_width != ILI9341_TFTWIDTH) { - Settings.display_width = ILI9341_TFTWIDTH; - } - if (Settings.display_height != ILI9341_TFTHEIGHT) { - Settings.display_height = ILI9341_TFTHEIGHT; - } - tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]); - tft->begin(); - -#ifdef USE_DISPLAY_MODES1TO5 - if (Settings.display_rotate) { - DisplayAllocScreenBuffer(); - } -#endif - - Ili9341InitMode(); - } -} - -void Ili9341Clear(void) -{ - tft->fillScreen(ILI9341_BLACK); - tft->setCursor(0, 0); -} - -void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - uint16_t active_color = ILI9341_WHITE; - - tft->setTextSize(Settings.display_size); - if (!flag) { - tft->setCursor(x, y); - } else { - tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size); - } - if (color) { active_color = color; } - tft->setTextColor(active_color, ILI9341_BLACK); - tft->println(str); -} - -void Ili9341DisplayOnOff(uint8_t on) -{ - - - if (pin[GPIO_BACKLIGHT] < 99) { - pinMode(pin[GPIO_BACKLIGHT], OUTPUT); - digitalWrite(pin[GPIO_BACKLIGHT], on); - } -} - -void Ili9341OnOff(void) -{ - Ili9341DisplayOnOff(disp_power); -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void Ili9341PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (Settings.display_rotate) { - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - } - - char* txt = DisplayLogBuffer('\370'); - if (txt != nullptr) { - uint8_t size = Settings.display_size; - uint16_t theight = size * TFT_FONT_HEIGTH; - - tft->setTextSize(size); - tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); - if (!Settings.display_rotate) { - tft->setCursor(0, tft_scroll); - tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); - tft->print(txt); - tft_scroll += theight; - if (tft_scroll >= (tft->height() - TFT_BOTTOM)) { - tft_scroll = TFT_TOP; - } - tft->scrollTo(tft_scroll); - } else { - uint8_t last_row = Settings.display_rows -1; - - tft_scroll = theight; - tft->setCursor(0, tft_scroll); - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - - tft->print(disp_screen_buffer[i]); - tft_scroll += theight; - tft->setCursor(0, tft_scroll); - delay(1); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - tft->print(disp_screen_buffer[last_row]); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); - } - } -} - -void Ili9341Refresh(void) -{ - if (Settings.display_mode) { - char tftdt[Settings.display_cols[0] +1]; - char date4[11]; - char space[Settings.display_cols[0] - 17]; - char time[9]; - - tft->setTextSize(2); - tft->setTextColor(ILI9341_YELLOW, ILI9341_RED); - tft->setCursor(0, 0); - - snprintf_P(date4, sizeof(date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - memset(space, 0x20, sizeof(space)); - space[sizeof(space) -1] = '\0'; - snprintf_P(time, sizeof(time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - snprintf_P(tftdt, sizeof(tftdt), PSTR("%s%s%s"), date4, space, time); - - tft->print(tftdt); - - switch (Settings.display_mode) { - case 1: - case 2: - case 3: - case 4: - case 5: - Ili9341PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp04(uint8_t function) -{ - bool result = false; - - if (spi_flg) { - if (FUNC_DISPLAY_INIT_DRIVER == function) { - Ili9341InitDriver(); - } - else if (XDSP_04 == Settings.display_model) { - - if (!dsp_color) { dsp_color = ILI9341_WHITE; } - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - Ili9341Init(dsp_init); - break; - case FUNC_DISPLAY_POWER: - Ili9341OnOff(); - break; - case FUNC_DISPLAY_CLEAR: - Ili9341Clear(); - break; - case FUNC_DISPLAY_DRAW_HLINE: - tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color); - break; - case FUNC_DISPLAY_DRAW_VLINE: - tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color); - break; - case FUNC_DISPLAY_DRAW_LINE: - tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - case FUNC_DISPLAY_DRAW_CIRCLE: - tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color); - break; - case FUNC_DISPLAY_FILL_CIRCLE: - tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color); - break; - case FUNC_DISPLAY_DRAW_RECTANGLE: - tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - case FUNC_DISPLAY_FILL_RECTANGLE: - tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - - - - case FUNC_DISPLAY_TEXT_SIZE: - tft->setTextSize(Settings.display_size); - break; - case FUNC_DISPLAY_FONT_SIZE: - - break; - case FUNC_DISPLAY_DRAW_STRING: - Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); - break; - case FUNC_DISPLAY_ONOFF: - Ili9341DisplayOnOff(dsp_on); - break; - case FUNC_DISPLAY_ROTATION: - tft->setRotation(Settings.display_rotate); - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - Ili9341Refresh(); - break; -#endif - } - } - } - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_05_epaper_29.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_05_epaper_29.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_EPAPER_29 - -#define XDSP_05 5 - -#define EPD_TOP 12 -#define EPD_FONT_HEIGTH 12 - -#define COLORED 1 -#define UNCOLORED 0 - - - -#define USE_TINY_FONT - -#include -#include - - -extern uint8_t *buffer; -uint16_t epd_scroll; - -Epd *epd; - - - -void EpdInitDriver29() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_05; - } - - if (XDSP_05 == Settings.display_model) { - if (Settings.display_width != EPD_WIDTH) { - Settings.display_width = EPD_WIDTH; - } - if (Settings.display_height != EPD_HEIGHT) { - Settings.display_height = EPD_HEIGHT; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((EPD_WIDTH * EPD_HEIGHT) / 8,1); - if (!buffer) return; - - - epd = new Epd(EPD_WIDTH,EPD_HEIGHT); - - - if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) { - epd->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SPI_CS], pin[GPIO_SPI_CLK], pin[GPIO_SPI_MOSI]); - } - else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { - epd->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SSPI_CS], pin[GPIO_SSPI_SCLK], pin[GPIO_SSPI_MOSI]); - } else { - free(buffer); - return; - } - - renderer = epd; - epd->Init(DISPLAY_INIT_FULL); - epd->Init(DISPLAY_INIT_PARTIAL); - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(1); - renderer->DrawStringAt(50, 50, "Waveshare E-Paper Display!", COLORED,0); - renderer->Updateframe(); - delay(1000); - renderer->fillScreen(0); -#endif - - } -} - - - - - - - -#ifdef USE_DISPLAY_MODES1TO5 -#define EPD_FONT_HEIGTH 12 -void EpdPrintLog29(void) -{ - - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - - char* txt = DisplayLogBuffer('\040'); - if (txt != nullptr) { - uint8_t size = Settings.display_size; - uint16_t theight = size * EPD_FONT_HEIGTH; - - renderer->setTextFont(size); - uint8_t last_row = Settings.display_rows -1; - - - epd_scroll = 0; - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0); - epd_scroll += theight; - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0); - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); - } - } -} - -void EpdRefresh29(void) -{ - if (Settings.display_mode) { - - if (!renderer) return; -# 165 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_05_epaper_29.ino" - switch (Settings.display_mode) { - case 1: - case 2: - case 3: - case 4: - case 5: - EpdPrintLog29(); - renderer->Updateframe(); - break; - } - - - } -} - -#endif - - - - - -bool Xdsp05(uint8_t function) -{ - bool result = false; - if (FUNC_DISPLAY_INIT_DRIVER == function) { - EpdInitDriver29(); - } - else if (XDSP_05 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh29(); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_06_epaper_42.ino" -# 21 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_06_epaper_42.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_EPAPER_42 - -#define XDSP_06 6 - -#define COLORED42 1 -#define UNCOLORED42 0 - - - -#define USE_TINY_FONT - -#include -#include - -extern uint8_t *buffer; - -Epd42 *epd42; - - - - -void EpdInitDriver42() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_06; - } - - if (XDSP_06 == Settings.display_model) { - - if (Settings.display_width != EPD_WIDTH42) { - Settings.display_width = EPD_WIDTH42; - } - if (Settings.display_height != EPD_HEIGHT42) { - Settings.display_height = EPD_HEIGHT42; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((EPD_WIDTH42 * EPD_HEIGHT42) / 8,1); - if (!buffer) return; - - - epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42); - - #ifdef USE_SPI - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)) { - epd42->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - } else { - free(buffer); - return; - } - #else - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { - epd42->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - } else { - free(buffer); - return; - } - #endif - - renderer = epd42; - - epd42->Init(); - - renderer->fillScreen(0); - - - epd42->Init(DISPLAY_INIT_FULL); - - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - - epd42->ClearFrame(); - renderer->Updateframe(); - delay(3000); - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->DrawStringAt(50, 140, "Waveshare E-Paper!", COLORED42,0); - renderer->Updateframe(); - delay(350); - renderer->fillScreen(0); -#endif - - } -} - - - - - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void EpdRefresh42() -{ - if (Settings.display_mode) { - - } -} - -#endif - - - - - - -bool Xdsp06(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - EpdInitDriver42(); - } - else if (XDSP_06 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh42(); - break; -#endif - } - } - return result; -} - - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_07_sh1106.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_07_sh1106.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SH1106 - -#define OLED_RESET 4 - -#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); - -extern uint8_t *buffer; - -#define XDSP_07 7 -#define XI2C_06 6 - -#define OLED_ADDRESS1 0x3C -#define OLED_ADDRESS2 0x3D - -#define OLED_BUFFER_COLS 40 -#define OLED_BUFFER_ROWS 16 - -#define OLED_FONT_WIDTH 6 -#define OLED_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_SH1106 *oled1106; - - - - -void SH1106InitDriver() -{ - if (!Settings.display_model) { - if (I2cSetDevice(OLED_ADDRESS1)) { - Settings.display_address[0] = OLED_ADDRESS1; - Settings.display_model = XDSP_07; - } - else if (I2cSetDevice(OLED_ADDRESS2)) { - Settings.display_address[0] = OLED_ADDRESS2; - Settings.display_model = XDSP_07; - } - } - - if (XDSP_07 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "SH1106"); - - if (Settings.display_width != SH1106_LCDWIDTH) { - Settings.display_width = SH1106_LCDWIDTH; - } - if (Settings.display_height != SH1106_LCDHEIGHT) { - Settings.display_height = SH1106_LCDHEIGHT; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((SH1106_LCDWIDTH * SH1106_LCDHEIGHT) / 8,1); - if (!buffer) return; - - - oled1106 = new Adafruit_SH1106(SH1106_LCDWIDTH,SH1106_LCDHEIGHT); - renderer=oled1106; - renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0); - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - renderer->setTextFont(0); - renderer->setTextSize(2); - renderer->setCursor(20,20); - renderer->println(F("SH1106")); - renderer->Updateframe(); - renderer->DisplayOnff(1); -#endif - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void SH1106PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void SH1106Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setTextFont(Settings.display_font); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void SH1106Refresh(void) -{ - if (!renderer) return; - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - SH1106Time(); - break; - case 2: - case 3: - case 4: - case 5: - SH1106PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp07(uint8_t function) -{ - if (!I2cEnabled(XI2C_06)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SH1106InitDriver(); - } - else if (XDSP_07 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - SH1106Refresh(); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_08_ILI9488.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_08_ILI9488.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9488 - -#define XDSP_08 8 -#define XI2C_38 38 - -#define COLORED 1 -#define UNCOLORED 0 - - -#define FT6236_address 0x38 - - - -#define USE_TINY_FONT - - -#include -#include - -TouchLocation ili9488_pLoc; -uint8_t ili9488_ctouch_counter = 0; - - -#define BACKPLANE_PIN 2 - -extern uint8_t *buffer; -extern uint8_t color_type; -ILI9488 *ili9488; - -#ifdef USE_TOUCH_BUTTONS -extern VButton *buttons[]; -#endif - -extern const uint16_t picture[]; -uint8_t FT6236_found; - - - -void ILI9488_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_08; - } - - if (XDSP_08 == Settings.display_model) { - - if (Settings.display_width != ILI9488_TFTWIDTH) { - Settings.display_width = ILI9488_TFTWIDTH; - } - if (Settings.display_height != ILI9488_TFTHEIGHT) { - Settings.display_height = ILI9488_TFTHEIGHT; - } - - - buffer=NULL; - - - fg_color = ILI9488_WHITE; - bg_color = ILI9488_BLACK; - - uint8_t bppin=BACKPLANE_PIN; - if (pin[GPIO_BACKLIGHT]<99) { - bppin=pin[GPIO_BACKLIGHT]; - } - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ - ili9488 = new ILI9488(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK],bppin); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { - ili9488 = new ILI9488(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK],bppin); - } else { - return; - } - } - - SPI.begin(); - ili9488->begin(); - renderer = ili9488; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(ILI9488_WHITE,ILI9488_BLACK); - renderer->DrawStringAt(50, 50, "ILI9488 TFT Display!", ILI9488_WHITE,0); - delay(1000); - - -#endif - - color_type = COLOR_COLOR; - - - if (I2cEnabled(XI2C_38) && I2cSetDevice(FT6236_address)) { - FT6236begin(FT6236_address); - FT6236_found=1; - I2cSetActiveFound(FT6236_address, "FT6236"); - } else { - FT6236_found=0; - } - - } -} - -#ifdef USE_TOUCH_BUTTONS -void ILI9488_MQTT(uint8_t count,const char *cp) { - ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); - MqttPublishTeleSensor(); -} - -void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr) { - buttons[count]->xdrawButton(pwr); - if (pwr) buttons[count]->vpower|=0x80; - else buttons[count]->vpower&=0x7f; -} - -void FT6236Check() { -uint16_t temp; -uint8_t rbutt=0,vbutt=0; -ili9488_ctouch_counter++; -if (2 == ili9488_ctouch_counter) { - - ili9488_ctouch_counter=0; - if (FT6236readTouchLocation(&ili9488_pLoc,1)) { - - if (renderer) { - uint8_t rot=renderer->getRotation(); - switch (rot) { - case 0: - temp=ili9488_pLoc.y; - ili9488_pLoc.y=renderer->height()-ili9488_pLoc.x; - ili9488_pLoc.x=temp; - break; - case 1: - break; - case 2: - break; - case 3: - temp=ili9488_pLoc.y; - ili9488_pLoc.y=ili9488_pLoc.x; - ili9488_pLoc.x=renderer->width()-temp; - break; - } - - for (uint8_t count=0; countvpower&0x7f; - if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) { - - buttons[count]->press(true); - if (buttons[count]->justPressed()) { - if (!bflags) { - uint8_t pwr=bitRead(power,rbutt); - if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { - ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); - ILI9488_RDW_BUTT(count,!pwr); - } - } else { - - const char *cp; - if (bflags==1) { - - buttons[count]->vpower^=0x80; - cp="TBT"; - } else { - - buttons[count]->vpower|=0x80; - cp="PBT"; - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - ILI9488_MQTT(count,cp); - } - } - } - if (!bflags) { - rbutt++; - } else { - vbutt++; - } - } - } - } - } else { - - for (uint8_t count=0; countvpower&0x7f; - buttons[count]->press(false); - if (buttons[count]->justReleased()) { - uint8_t bflags=buttons[count]->vpower&0x7f; - if (bflags>0) { - if (bflags>1) { - - buttons[count]->vpower&=0x7f; - ILI9488_MQTT(count,"PBT"); - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - } - } - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; - if (pwr!=vpwr) { - ILI9488_RDW_BUTT(count,pwr); - } - rbutt++; - } - } - } - ili9488_pLoc.x=0; - ili9488_pLoc.y=0; - } -} -} -#endif - - - - -bool Xdsp08(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - ILI9488_InitDriver(); - } - else if (XDSP_08 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_TOUCH_BUTTONS - if (FT6236_found) FT6236Check(); -#endif - break; - } - } - - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_09_SSD1351.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_09_SSD1351.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SSD1351 - -#define XDSP_09 9 - -#define COLORED 1 -#define UNCOLORED 0 - - - - -#define USE_TINY_FONT - -#include - -extern uint8_t *buffer; -extern uint8_t color_type; -SSD1351 *ssd1351; - - - -void SSD1351_InitDriver() { - if (!Settings.display_model) { - Settings.display_model = XDSP_09; - } - - if (XDSP_09 == Settings.display_model) { - - if (Settings.display_width != SSD1351_WIDTH) { - Settings.display_width = SSD1351_WIDTH; - } - if (Settings.display_height != SSD1351_HEIGHT) { - Settings.display_height = SSD1351_HEIGHT; - } - - buffer=0; - - - fg_color = SSD1351_WHITE; - bg_color = SSD1351_BLACK; - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ - ssd1351 = new SSD1351(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)){ - ssd1351 = new SSD1351(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - } else { - return; - } - } - - delay(100); - SPI.begin(); - ssd1351->begin(); - renderer = ssd1351; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->dim(Settings.display_dimmer); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(SSD1351_WHITE,SSD1351_BLACK); - renderer->DrawStringAt(10, 60, "SSD1351", SSD1351_RED,0); - delay(1000); - -#endif - color_type = COLOR_COLOR; - } -} - -#ifdef USE_DISPLAY_MODES1TO5 - -void SSD1351PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void SSD1351Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(2); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void SSD1351Refresh(void) -{ - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - SSD1351Time(); - break; - case 2: - case 3: - case 4: - case 5: - SSD1351PrintLog(); - break; - } - } -} - -#endif - - - - -bool Xdsp09(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SSD1351_InitDriver(); - } - else if (XDSP_09 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - SSD1351Refresh(); - break; -#endif - } - } - return result; -} -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_10_RA8876.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_10_RA8876.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_RA8876 - -#define XDSP_10 10 -#define XI2C_39 39 - -#define COLORED 1 -#define UNCOLORED 0 - - -#define FT5316_address 0x38 - - - -#define USE_TINY_FONT - -#include -#include - -TouchLocation ra8876_pLoc; -uint8_t ra8876_ctouch_counter = 0; - -#ifdef USE_TOUCH_BUTTONS -extern VButton *buttons[]; -#endif - -extern uint8_t *buffer; -extern uint8_t color_type; -RA8876 *ra8876; - -uint8_t FT5316_found; - - -void RA8876_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_10; - } - - if (XDSP_10 == Settings.display_model) { - - if (Settings.display_width != RA8876_TFTWIDTH) { - Settings.display_width = RA8876_TFTWIDTH; - } - if (Settings.display_height != RA8876_TFTHEIGHT) { - Settings.display_height = RA8876_TFTHEIGHT; - } - buffer=0; - - - fg_color = RA8876_WHITE; - bg_color = RA8876_BLACK; - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]==13) && (pin[GPIO_SSPI_MISO]==12) && (pin[GPIO_SSPI_SCLK]==14)) { - ra8876 = new RA8876(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_MISO],pin[GPIO_SSPI_SCLK],pin[GPIO_BACKLIGHT]); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]==13) && (pin[GPIO_SPI_MISO]==12) && (pin[GPIO_SPI_CLK]==14)) { - ra8876 = new RA8876(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_MISO],pin[GPIO_SPI_CLK],pin[GPIO_BACKLIGHT]); - } else { - return; - } - } - - ra8876->begin(); - renderer = ra8876; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->dim(Settings.display_dimmer); - - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(RA8876_WHITE,RA8876_BLACK); - renderer->DrawStringAt(600, 300, "RA8876", RA8876_RED,0); - delay(1000); - -#endif - color_type = COLOR_COLOR; - - if (I2cEnabled(XI2C_39) && I2cSetDevice(FT5316_address)) { - FT6236begin(FT5316_address); - FT5316_found=1; - I2cSetActiveFound(FT5316_address, "FT5316"); - } else { - FT5316_found=0; - } - - } -} - -#ifdef USE_TOUCH_BUTTONS -void RA8876_MQTT(uint8_t count,const char *cp) { - ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); - MqttPublishTeleSensor(); -} - -void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr) { - buttons[count]->xdrawButton(pwr); - if (pwr) buttons[count]->vpower|=0x80; - else buttons[count]->vpower&=0x7f; -} - - -void FT5316Check() { -uint16_t temp; -uint8_t rbutt=0,vbutt=0; -ra8876_ctouch_counter++; -if (2 == ra8876_ctouch_counter) { - - ra8876_ctouch_counter=0; - - if (FT6236readTouchLocation(&ra8876_pLoc,1)) { - ra8876_pLoc.x=ra8876_pLoc.x*RA8876_TFTWIDTH/800; - ra8876_pLoc.y=ra8876_pLoc.y*RA8876_TFTHEIGHT/480; - - - if (renderer) { - - - ra8876_pLoc.x=RA8876_TFTWIDTH-ra8876_pLoc.x; - ra8876_pLoc.y=RA8876_TFTHEIGHT-ra8876_pLoc.y; -# 170 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_10_RA8876.ino" - for (uint8_t count=0; countvpower&0x7f; - if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) { - - buttons[count]->press(true); - if (buttons[count]->justPressed()) { - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { - ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); - RA8876_RDW_BUTT(count,!pwr); - } - } else { - - const char *cp; - if (bflags==1) { - - buttons[count]->vpower^=0x80; - cp="TBT"; - } else { - - buttons[count]->vpower|=0x80; - cp="PBT"; - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - RA8876_MQTT(count,cp); - } - } - } - if (!bflags) { - rbutt++; - } else { - vbutt++; - } - } - } - } - } else { - - for (uint8_t count=0; countvpower&0x7f; - buttons[count]->press(false); - if (buttons[count]->justReleased()) { - if (bflags>0) { - if (bflags>1) { - - buttons[count]->vpower&=0x7f; - RA8876_MQTT(count,"PBT"); - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - } - } - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; - if (pwr!=vpwr) { - RA8876_RDW_BUTT(count,pwr); - } - rbutt++; - } - } - } - ra8876_pLoc.x=0; - ra8876_pLoc.y=0; - } -} -} -#endif -# 426 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_10_RA8876.ino" -bool Xdsp10(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - RA8876_InitDriver(); - } - else if (XDSP_10 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_TOUCH_BUTTONS - if (FT5316_found) FT5316Check(); -#endif - break; - } - } - return result; -} -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_interface.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_interface.ino" -#ifdef USE_DISPLAY - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xdsp_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xdsp_func_ptr[])(uint8_t) = { -#endif - -#ifdef XDSP_01 - &Xdsp01, -#endif - -#ifdef XDSP_02 - &Xdsp02, -#endif - -#ifdef XDSP_03 - &Xdsp03, -#endif - -#ifdef XDSP_04 - &Xdsp04, -#endif - -#ifdef XDSP_05 - &Xdsp05, -#endif - -#ifdef XDSP_06 - &Xdsp06, -#endif - -#ifdef XDSP_07 - &Xdsp07, -#endif - -#ifdef XDSP_08 - &Xdsp08, -#endif - -#ifdef XDSP_09 - &Xdsp09, -#endif - -#ifdef XDSP_10 - &Xdsp10, -#endif - -#ifdef XDSP_11 - &Xdsp11, -#endif - -#ifdef XDSP_12 - &Xdsp12, -#endif - -#ifdef XDSP_13 - &Xdsp13, -#endif - -#ifdef XDSP_14 - &Xdsp14, -#endif - -#ifdef XDSP_15 - &Xdsp15, -#endif - -#ifdef XDSP_16 - &Xdsp16 -#endif -}; - -const uint8_t xdsp_present = sizeof(xdsp_func_ptr) / sizeof(xdsp_func_ptr[0]); -# 117 "C:/shared/sonoff/Git/Tasmota/tasmota/xdsp_interface.ino" -uint8_t XdspPresent(void) -{ - return xdsp_present; -} - -bool XdspCall(uint8_t Function) -{ - bool result = false; - - DEBUG_TRACE_LOG(PSTR("DSP: %d"), Function); - - for (uint32_t x = 0; x < xdsp_present; x++) { - result = xdsp_func_ptr[x](Function); - - if (result && (FUNC_DISPLAY_MODEL == Function)) { - break; - } - } - - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_01_ws2812.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_01_ws2812.ino" -#ifdef USE_LIGHT -#ifdef USE_WS2812 -# 38 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_01_ws2812.ino" -#define XLGT_01 1 - -const uint8_t WS2812_SCHEMES = 8; - -const char kWs2812Commands[] PROGMEM = "|" - D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH ; - -void (* const Ws2812Command[])(void) PROGMEM = { - &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth }; - -#include - -#if (USE_WS2812_CTYPE == NEO_GRB) - typedef NeoGrbFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_BRG) - typedef NeoBrgFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_RBG) - typedef NeoRbgFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_RGBW) - typedef NeoRgbwFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_GRBW) - typedef NeoGrbwFeature selectedNeoFeatureType; -#else - typedef NeoRgbFeature selectedNeoFeatureType; -#endif - -#ifdef USE_WS2812_DMA - - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266DmaWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266DmaSk6812Method selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) - typedef NeoEsp8266DmaApa106Method selectedNeoSpeedType; -#else - typedef NeoEsp8266Dma800KbpsMethod selectedNeoSpeedType; -#endif - -#else - - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266BitBangWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266BitBangSk6812Method selectedNeoSpeedType; -#else - typedef NeoEsp8266BitBang800KbpsMethod selectedNeoSpeedType; -#endif - -#endif - -NeoPixelBus *strip = nullptr; - -struct WsColor { - uint8_t red, green, blue; -}; - -struct ColorScheme { - WsColor* colors; - uint8_t count; -}; - -WsColor kIncandescent[2] = { 255,140,20, 0,0,0 }; -WsColor kRgb[3] = { 255,0,0, 0,255,0, 0,0,255 }; -WsColor kChristmas[2] = { 255,0,0, 0,255,0 }; -WsColor kHanukkah[2] = { 0,0,255, 255,255,255 }; -WsColor kwanzaa[3] = { 255,0,0, 0,0,0, 0,255,0 }; -WsColor kRainbow[7] = { 255,0,0, 255,128,0, 255,255,0, 0,255,0, 0,0,255, 128,0,255, 255,0,255 }; -WsColor kFire[3] = { 255,0,0, 255,102,0, 255,192,0 }; -ColorScheme kSchemes[WS2812_SCHEMES -1] = { - kIncandescent, 2, - kRgb, 3, - kChristmas, 2, - kHanukkah, 2, - kwanzaa, 3, - kRainbow, 7, - kFire, 3 }; - -uint8_t kWidth[5] = { - 1, - 2, - 4, - 8, - 255 }; -uint8_t kWsRepeat[5] = { - 8, - 6, - 4, - 2, - 1 }; - -struct WS2812 { - uint8_t show_next = 1; - uint8_t scheme_offset = 0; - bool suspend_update = false; -} Ws2812; - - - -void Ws2812StripShow(void) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; -#else - RgbColor c; -#endif - - if (Settings.light_correction) { - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - c = strip->GetPixelColor(i); - c.R = ledGamma(c.R); - c.G = ledGamma(c.G); - c.B = ledGamma(c.B); -#if (USE_WS2812_CTYPE > NEO_3LED) - c.W = ledGamma(c.W); -#endif - strip->SetPixelColor(i, c); - } - } - strip->Show(); -} - -int mod(int a, int b) -{ - int ret = a % b; - if (ret < 0) ret += b; - return ret; -} - -void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor color; -#else - RgbColor color; -#endif - - uint32_t mod_position = mod(position, (int)Settings.light_pixels); - - color = strip->GetPixelColor(mod_position); - float dimmer = 100 / (float)Settings.light_dimmer; - color.R = tmin(color.R + ((hand_color.red / dimmer) * offset), 255); - color.G = tmin(color.G + ((hand_color.green / dimmer) * offset), 255); - color.B = tmin(color.B + ((hand_color.blue / dimmer) * offset), 255); - strip->SetPixelColor(mod_position, color); -} - -void Ws2812UpdateHand(int position, uint32_t index) -{ - uint32_t width = Settings.light_width; - if (index < WS_MARKER) { width = Settings.ws_width[index]; } - if (!width) { return; } - - position = (position + Settings.light_rotation) % Settings.light_pixels; - - if (Settings.flag.ws_clock_reverse) { - position = Settings.light_pixels -position; - } - WsColor hand_color = { Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE] }; - - Ws2812UpdatePixelColor(position, hand_color, 1); - - uint32_t range = ((width -1) / 2) +1; - for (uint32_t h = 1; h < range; h++) { - float offset = (float)(range - h) / (float)range; - Ws2812UpdatePixelColor(position -h, hand_color, offset); - Ws2812UpdatePixelColor(position +h, hand_color, offset); - } -} - -void Ws2812Clock(void) -{ - strip->ClearTo(0); - int clksize = 60000 / (int)Settings.light_pixels; - - Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); - Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); - Ws2812UpdateHand((((RtcTime.hour % 12) * 5000) + ((RtcTime.minute * 1000) / 12 )) / clksize, WS_HOUR); - if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { - for (uint32_t i = 0; i < 12; i++) { - Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); - } - } - - Ws2812StripShow(); -} - -void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i) -{ - - - - - ColorScheme scheme = kSchemes[schemenr]; - uint32_t curRange = i / range; - uint32_t rangeIndex = i % range; - uint32_t colorIndex = rangeIndex / gradRange; - uint32_t start = colorIndex; - uint32_t end = colorIndex +1; - if (curRange % 2 != 0) { - start = (scheme.count -1) - start; - end = (scheme.count -1) - end; - } - float dimmer = 100 / (float)Settings.light_dimmer; - float fmyRed = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].red, scheme.colors[end].red) / dimmer; - float fmyGrn = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].green, scheme.colors[end].green) / dimmer; - float fmyBlu = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].blue, scheme.colors[end].blue) / dimmer; - mColor->red = (uint8_t)fmyRed; - mColor->green = (uint8_t)fmyGrn; - mColor->blue = (uint8_t)fmyBlu; -} - -void Ws2812Gradient(uint32_t schemenr) -{ - - - - - -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; - c.W = 0; -#else - RgbColor c; -#endif - - ColorScheme scheme = kSchemes[schemenr]; - if (scheme.count < 2) { return; } - - uint32_t repeat = kWsRepeat[Settings.light_width]; - uint32_t range = (uint32_t)ceil((float)Settings.light_pixels / (float)repeat); - uint32_t gradRange = (uint32_t)ceil((float)range / (float)(scheme.count - 1)); - uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); - uint32_t offset = speed > 0 ? Light.strip_timer_counter / speed : 0; - - WsColor oldColor, currentColor; - Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset); - currentColor = oldColor; - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - if (kWsRepeat[Settings.light_width] > 1) { - Ws2812GradientColor(schemenr, ¤tColor, range, gradRange, i +offset); - } - if (Settings.light_speed > 0) { - - c.R = map(Light.strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red); - c.G = map(Light.strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green); - c.B = map(Light.strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue); - } - else { - - c.R = currentColor.red; - c.G = currentColor.green; - c.B = currentColor.blue; - } - strip->SetPixelColor(i, c); - oldColor = currentColor; - } - Ws2812StripShow(); -} - -void Ws2812Bars(uint32_t schemenr) -{ - - - - - -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; - c.W = 0; -#else - RgbColor c; -#endif - - ColorScheme scheme = kSchemes[schemenr]; - - uint32_t maxSize = Settings.light_pixels / scheme.count; - if (kWidth[Settings.light_width] > maxSize) { maxSize = 0; } - - uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); - uint32_t offset = (speed > 0) ? Light.strip_timer_counter / speed : 0; - - WsColor mcolor[scheme.count]; - memcpy(mcolor, scheme.colors, sizeof(mcolor)); - float dimmer = 100 / (float)Settings.light_dimmer; - for (uint32_t i = 0; i < scheme.count; i++) { - float fmyRed = (float)mcolor[i].red / dimmer; - float fmyGrn = (float)mcolor[i].green / dimmer; - float fmyBlu = (float)mcolor[i].blue / dimmer; - mcolor[i].red = (uint8_t)fmyRed; - mcolor[i].green = (uint8_t)fmyGrn; - mcolor[i].blue = (uint8_t)fmyBlu; - } - uint32_t colorIndex = offset % scheme.count; - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - if (maxSize) { colorIndex = ((i + offset) % (scheme.count * kWidth[Settings.light_width])) / kWidth[Settings.light_width]; } - c.R = mcolor[colorIndex].red; - c.G = mcolor[colorIndex].green; - c.B = mcolor[colorIndex].blue; - strip->SetPixelColor(i, c); - } - Ws2812StripShow(); -} - -void Ws2812Clear(void) -{ - strip->ClearTo(0); - strip->Show(); - Ws2812.show_next = 1; -} - -void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor lcolor; - lcolor.W = white; -#else - RgbColor lcolor; -#endif - - lcolor.R = red; - lcolor.G = green; - lcolor.B = blue; - if (led) { - strip->SetPixelColor(led -1, lcolor); - } else { - - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - strip->SetPixelColor(i, lcolor); - } - } - - if (!Ws2812.suspend_update) { - strip->Show(); - Ws2812.show_next = 1; - } -} - -char* Ws2812GetColor(uint32_t led, char* scolor) -{ - uint8_t sl_ledcolor[4]; - - #if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor lcolor = strip->GetPixelColor(led -1); - sl_ledcolor[3] = lcolor.W; - #else - RgbColor lcolor = strip->GetPixelColor(led -1); - #endif - sl_ledcolor[0] = lcolor.R; - sl_ledcolor[1] = lcolor.G; - sl_ledcolor[2] = lcolor.B; - scolor[0] = '\0'; - for (uint32_t i = 0; i < Light.subtype; i++) { - if (Settings.flag.decimal_text) { - snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", sl_ledcolor[i]); - } else { - snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, sl_ledcolor[i]); - } - } - return scolor; -} - - - - - -void Ws2812ForceSuspend (void) -{ - Ws2812.suspend_update = true; -} - -void Ws2812ForceUpdate (void) -{ - Ws2812.suspend_update = false; - strip->Show(); - Ws2812.show_next = 1; -} - - - -bool Ws2812SetChannels(void) -{ - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); - - return true; -} - -void Ws2812ShowScheme(void) -{ - uint32_t scheme = Settings.light_scheme - Ws2812.scheme_offset; - - switch (scheme) { - case 0: - if ((1 == state_250mS) || (Ws2812.show_next)) { - Ws2812Clock(); - Ws2812.show_next = 0; - } - break; - default: - if (1 == Settings.light_fade) { - Ws2812Gradient(scheme -1); - } else { - Ws2812Bars(scheme -1); - } - Ws2812.show_next = 1; - break; - } -} - -void Ws2812ModuleSelected(void) -{ - if (pin[GPIO_WS2812] < 99) { - - - strip = new NeoPixelBus(WS2812_MAX_LEDS, pin[GPIO_WS2812]); - strip->Begin(); - - Ws2812Clear(); - - Ws2812.scheme_offset = Light.max_scheme +1; - Light.max_scheme += WS2812_SCHEMES; - -#if (USE_WS2812_CTYPE > NEO_3LED) - light_type = LT_RGBW; -#else - light_type = LT_RGB; -#endif - light_flg = XLGT_01; - } -} - - - -void CmndLed(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) { - if (XdrvMailbox.data_len > 0) { - char *p; - uint16_t idx = XdrvMailbox.index; - Ws2812ForceSuspend(); - for (char *color = strtok_r(XdrvMailbox.data, " ", &p); color; color = strtok_r(nullptr, " ", &p)) { - if (LightColorEntry(color, strlen(color))) { - Ws2812SetColor(idx, Light.entry_color[0], Light.entry_color[1], Light.entry_color[2], Light.entry_color[3]); - idx++; - if (idx > Settings.light_pixels) { break; } - } else { - break; - } - } - Ws2812ForceUpdate(); - } - char scolor[LIGHT_COLOR_SIZE]; - ResponseCmndIdxChar(Ws2812GetColor(XdrvMailbox.index, scolor)); - } -} - -void CmndPixels(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { - Settings.light_pixels = XdrvMailbox.payload; - Settings.light_rotation = 0; - Ws2812Clear(); - Light.update = true; - } - ResponseCmndNumber(Settings.light_pixels); -} - -void CmndRotation(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { - Settings.light_rotation = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_rotation); -} - -void CmndWidth(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - if (1 == XdrvMailbox.index) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { - Settings.light_width = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_width); - } else { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32)) { - Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.ws_width[XdrvMailbox.index -2]); - } - } -} - - - - - -bool Xlgt01(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Ws2812SetChannels(); - break; - case FUNC_SET_SCHEME: - Ws2812ShowScheme(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kWs2812Commands, Ws2812Command); - break; - case FUNC_MODULE_INIT: - Ws2812ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_02_my92x1.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_02_my92x1.ino" -#ifdef USE_LIGHT -#ifdef USE_MY92X1 - - - - -#define XLGT_02 2 - -struct MY92X1 { - uint8_t pdi_pin = 0; - uint8_t pdcki_pin = 0; - uint8_t model = 0; -} My92x1; - -extern "C" { - void os_delay_us(unsigned int); -} - -void LightDiPulse(uint8_t times) -{ - for (uint32_t i = 0; i < times; i++) { - digitalWrite(My92x1.pdi_pin, HIGH); - digitalWrite(My92x1.pdi_pin, LOW); - } -} - -void LightDckiPulse(uint8_t times) -{ - for (uint32_t i = 0; i < times; i++) { - digitalWrite(My92x1.pdcki_pin, HIGH); - digitalWrite(My92x1.pdcki_pin, LOW); - } -} - -void LightMy92x1Write(uint8_t data) -{ - for (uint32_t i = 0; i < 4; i++) { - digitalWrite(My92x1.pdcki_pin, LOW); - digitalWrite(My92x1.pdi_pin, (data & 0x80)); - digitalWrite(My92x1.pdcki_pin, HIGH); - data = data << 1; - digitalWrite(My92x1.pdi_pin, (data & 0x80)); - digitalWrite(My92x1.pdcki_pin, LOW); - digitalWrite(My92x1.pdi_pin, LOW); - data = data << 1; - } -} - -void LightMy92x1Init(void) -{ - uint8_t chips[3] = { 1, 2, 2 }; - - LightDckiPulse(chips[My92x1.model] * 32); - os_delay_us(12); - - - LightDiPulse(12); - os_delay_us(12); - for (uint32_t n = 0; n < chips[My92x1.model]; n++) { - LightMy92x1Write(0x18); - } - os_delay_us(12); - - - LightDiPulse(16); - os_delay_us(12); -} - -void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) -{ - uint8_t channels[3] = { 4, 6, 6 }; - - uint8_t duty[3][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, - { duty_w, duty_c, 0, duty_g, duty_r, duty_b }, - { duty_r, duty_g, duty_b, duty_w, duty_w, duty_w }}; - - os_delay_us(12); - for (uint32_t channel = 0; channel < channels[My92x1.model]; channel++) { - LightMy92x1Write(duty[My92x1.model][channel]); - } - os_delay_us(12); - LightDiPulse(8); - os_delay_us(12); -} - - - -bool My92x1SetChannels(void) -{ - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); - - return true; -} - -void My92x1ModuleSelected(void) -{ - if ((pin[GPIO_DCKI] < 99) && (pin[GPIO_DI] < 99)) { - My92x1.pdi_pin = pin[GPIO_DI]; - My92x1.pdcki_pin = pin[GPIO_DCKI]; - - pinMode(My92x1.pdi_pin, OUTPUT); - pinMode(My92x1.pdcki_pin, OUTPUT); - digitalWrite(My92x1.pdi_pin, LOW); - digitalWrite(My92x1.pdcki_pin, LOW); - - My92x1.model = 2; - light_type = LT_RGBW; - if (AILIGHT == my_module_type) { - My92x1.model = 0; - - } - else if (SONOFF_B1 == my_module_type) { - My92x1.model = 1; - light_type = LT_RGBWC; - } - - LightMy92x1Init(); - - light_flg = XLGT_02; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: MY29x1 Found")); - } -} - - - - - -bool Xlgt02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = My92x1SetChannels(); - break; - case FUNC_MODULE_INIT: - My92x1ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" -#ifdef USE_LIGHT -#ifdef USE_SM16716 - - - - - - - -#define XLGT_03 3 - -#define D_LOG_SM16716 "SM16716: " - -struct SM16716 { - uint8_t pin_clk = 0; - uint8_t pin_dat = 0; - uint8_t pin_sel = 0; - bool enabled = false; -} Sm16716; - -void SM16716_SendBit(uint8_t v) -{ - - - - - - digitalWrite(Sm16716.pin_dat, (v != 0) ? HIGH : LOW); - - digitalWrite(Sm16716.pin_clk, HIGH); - - digitalWrite(Sm16716.pin_clk, LOW); -} - -void SM16716_SendByte(uint8_t v) -{ - uint8_t mask; - - for (mask = 0x80; mask; mask >>= 1) { - SM16716_SendBit(v & mask); - } -} - -void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) -{ - if (Sm16716.pin_sel < 99) { - bool should_enable = (duty_r | duty_g | duty_b); - if (!Sm16716.enabled && should_enable) { - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on")); - Sm16716.enabled = true; - digitalWrite(Sm16716.pin_sel, HIGH); - - - delayMicroseconds(1000); - SM16716_Init(); - } - else if (Sm16716.enabled && !should_enable) { - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off")); - Sm16716.enabled = false; - digitalWrite(Sm16716.pin_sel, LOW); - } - } - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b); - - - SM16716_SendBit(1); - SM16716_SendByte(duty_r); - SM16716_SendByte(duty_g); - SM16716_SendByte(duty_b); - - - - - - SM16716_SendBit(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_SendByte(0); -} -# 111 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" -void SM16716_Init(void) -{ - for (uint32_t t_init = 0; t_init < 50; ++t_init) { - SM16716_SendBit(0); - } -} - - - -bool Sm16716SetChannels(void) -{ -# 132 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); - - return true; -} - -void Sm16716ModuleSelected(void) -{ - if ((pin[GPIO_SM16716_CLK] < 99) && (pin[GPIO_SM16716_DAT] < 99)) { - Sm16716.pin_clk = pin[GPIO_SM16716_CLK]; - Sm16716.pin_dat = pin[GPIO_SM16716_DAT]; - Sm16716.pin_sel = pin[GPIO_SM16716_SEL]; -# 157 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_03_sm16716.ino" - pinMode(Sm16716.pin_clk, OUTPUT); - digitalWrite(Sm16716.pin_clk, LOW); - - pinMode(Sm16716.pin_dat, OUTPUT); - digitalWrite(Sm16716.pin_dat, LOW); - - if (Sm16716.pin_sel < 99) { - pinMode(Sm16716.pin_sel, OUTPUT); - digitalWrite(Sm16716.pin_sel, LOW); - - } else { - - SM16716_Init(); - } - - LightPwmOffset(LST_RGB); - light_type += LST_RGB; - light_flg = XLGT_03; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM16716 Found")); - } -} - - - - - -bool Xlgt03(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Sm16716SetChannels(); - break; - case FUNC_MODULE_INIT: - Sm16716ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_04_sm2135.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_04_sm2135.ino" -#ifdef USE_LIGHT -#ifdef USE_SM2135 - - - - - - -#define XLGT_04 4 - -#define SM2135_ADDR_MC 0xC0 -#define SM2135_ADDR_CH 0xC1 -#define SM2135_ADDR_R 0xC2 -#define SM2135_ADDR_G 0xC3 -#define SM2135_ADDR_B 0xC4 -#define SM2135_ADDR_C 0xC5 -#define SM2135_ADDR_W 0xC6 - -#define SM2135_RGB 0x00 -#define SM2135_CW 0x80 - -#define SM2135_10MA 0x00 -#define SM2135_15MA 0x01 -#define SM2135_20MA 0x02 -#define SM2135_25MA 0x03 -#define SM2135_30MA 0x04 -#define SM2135_35MA 0x05 -#define SM2135_40MA 0x06 -#define SM2135_45MA 0x07 -#define SM2135_50MA 0x08 -#define SM2135_55MA 0x09 -#define SM2135_60MA 0x0A - - -const uint8_t SM2135_CURRENT = (SM2135_20MA << 4) | SM2135_15MA; - -struct SM2135 { - uint8_t clk = 0; - uint8_t data = 0; -} Sm2135; - -uint8_t Sm2135Write(uint8_t data) -{ - for (uint32_t i = 0; i < 8; i++) { - digitalWrite(Sm2135.clk, LOW); - digitalWrite(Sm2135.data, (data & 0x80)); - digitalWrite(Sm2135.clk, HIGH); - data = data << 1; - } - digitalWrite(Sm2135.clk, LOW); - digitalWrite(Sm2135.data, HIGH); - pinMode(Sm2135.data, INPUT); - digitalWrite(Sm2135.clk, HIGH); - uint8_t ack = digitalRead(Sm2135.data); - pinMode(Sm2135.data, OUTPUT); - return ack; -} - -void Sm2135Send(uint8_t *buffer, uint8_t size) -{ - digitalWrite(Sm2135.data, LOW); - for (uint32_t i = 0; i < size; i++) { - Sm2135Write(buffer[i]); - } - digitalWrite(Sm2135.clk, LOW); - digitalWrite(Sm2135.clk, HIGH); - digitalWrite(Sm2135.data, HIGH); -} - - - -bool Sm2135SetChannels(void) -{ - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - uint8_t data[6]; - - if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) { -# 106 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_04_sm2135.ino" - data[0] = SM2135_ADDR_MC; - data[1] = SM2135_CURRENT; - data[2] = SM2135_CW; - Sm2135Send(data, 3); - delay(1); - data[0] = SM2135_ADDR_C; - data[1] = cur_col[4]; - data[2] = cur_col[3]; - Sm2135Send(data, 3); - } else { - - - - - - - - data[0] = SM2135_ADDR_MC; - data[1] = SM2135_CURRENT; - data[2] = SM2135_RGB; - data[3] = cur_col[1]; - data[4] = cur_col[0]; - data[5] = cur_col[2]; - Sm2135Send(data, 6); - } - - return true; -} - -void Sm2135ModuleSelected(void) -{ - if ((pin[GPIO_SM2135_CLK] < 99) && (pin[GPIO_SM2135_DAT] < 99)) { - Sm2135.clk = pin[GPIO_SM2135_CLK]; - Sm2135.data = pin[GPIO_SM2135_DAT]; - - pinMode(Sm2135.data, OUTPUT); - digitalWrite(Sm2135.data, HIGH); - pinMode(Sm2135.clk, OUTPUT); - digitalWrite(Sm2135.clk, HIGH); - - light_type = LT_RGBWC; - light_flg = XLGT_04; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 Found")); - } -} - - - - - -bool Xlgt04(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Sm2135SetChannels(); - break; - case FUNC_MODULE_INIT: - Sm2135ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" -#ifdef USE_LIGHT -#ifdef USE_SONOFF_L1 - - - - -#define XLGT_05 5 - -#define SONOFF_L1_BUFFER_SIZE 140 - -#define SONOFF_L1_MODE_COLORFUL 1 -#define SONOFF_L1_MODE_COLORFUL_GRADIENT 2 -#define SONOFF_L1_MODE_COLORFUL_BREATH 3 -#define SONOFF_L1_MODE_DIY_GRADIENT 4 -#define SONOFF_L1_MODE_DIY_PULSE 5 -#define SONOFF_L1_MODE_DIY_BREATH 6 -#define SONOFF_L1_MODE_DIY_STROBE 7 -#define SONOFF_L1_MODE_RGB_GRADIENT 8 -#define SONOFF_L1_MODE_RGB_PULSE 9 -#define SONOFF_L1_MODE_RGB_BREATH 10 -#define SONOFF_L1_MODE_RGB_STROBE 11 -#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 - -struct SNFL1 { - uint32_t unlock = 0; - bool receive_ready = true; -} Snfl1; - - - -void SnfL1Send(const char *buffer) -{ - - - Serial.print(buffer); - Serial.write(0x1B); - Serial.flush(); -} - -void SnfL1SerialSendOk(void) -{ - char buffer[16]; - snprintf_P(buffer, sizeof(buffer), PSTR("AT+SEND=ok")); - - SnfL1Send(buffer); -} - -bool SnfL1SerialInput(void) -{ - if (serial_in_byte != 0x1B) { - if (serial_in_byte_counter >= 140) { - serial_in_byte_counter = 0; - } - if (serial_in_byte_counter || (!serial_in_byte_counter && ('A' == serial_in_byte))) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } - } else { - serial_in_buffer[serial_in_byte_counter++] = 0x00; - - - - - - - if (!strncmp(serial_in_buffer +3, "RESULT", 6)) { - Snfl1.receive_ready = true; - } - else if (!strncmp(serial_in_buffer +3, "UPDATE", 6)) { - char cmnd_dimmer[20]; - char cmnd_color[20]; - char *end_str; - char *string = serial_in_buffer +10; - char *token = strtok_r(string, ",", &end_str); - - bool color_updated[3] = { false, false, false }; - uint8_t current_color[3]; - memcpy(current_color, Settings.light_color, 3); - - bool switch_state = false; - bool is_power_change = false; - bool is_color_change = false; - bool is_brightness_change = false; - - while (token != nullptr) { - char* end_token; - char* token2 = strtok_r(token, ":", &end_token); - char* token3 = strtok_r(nullptr, ":", &end_token); - - if (!strncmp(token2, "\"sequence\"", 10)) { - - - - token = nullptr; - } - - else if (!strncmp(token2, "\"switch\"", 8)) { - switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - - - - is_power_change = (switch_state != Light.power); - } - - else if (!strncmp(token2, "\"color", 6)) { - char color_channel_name = token2[6]; - int color_index; - switch(color_channel_name) - { - case 'R': color_index = 0; - break; - case 'G': color_index = 1; - break; - case 'B': color_index = 2; - break; - } - int color_value = atoi(token3); - current_color[color_index] = color_value; - color_updated[color_index] = true; - - bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; - if (all_color_channels_updated) { - - - - - - is_color_change = (Light.power && (memcmp(current_color, Settings.light_color, 3) != 0)); - } - snprintf_P(cmnd_color, sizeof(cmnd_color), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), current_color[0], current_color[1], current_color[2]); - } - - else if (!strncmp(token2, "\"bright\"", 8)) { - uint8_t dimmer = atoi(token3); - - - - is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings.light_dimmer)); - snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer); - } - - token = strtok_r(nullptr, ",", &end_str); - } - - if (is_power_change) { - if (Settings.light_scheme > 0) { - if (!switch_state) { - char cmnd_scheme[20]; - snprintf_P(cmnd_scheme, sizeof(cmnd_scheme), PSTR(D_CMND_SCHEME " 0")); - ExecuteCommand(cmnd_scheme, SRC_SWITCH); - } - } else { - ExecuteCommandPower(1, switch_state, SRC_SWITCH); - } - } - else if (is_brightness_change) { - ExecuteCommand(cmnd_dimmer, SRC_SWITCH); - } - else if (Light.power && is_color_change) { - if (0 == Settings.light_scheme) { - if (Settings.light_fade) { - char cmnd_fade[20]; - snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_FADE " 0")); - ExecuteCommand(cmnd_fade, SRC_SWITCH); - } - ExecuteCommand(cmnd_color, SRC_SWITCH); - } - } - } - - SnfL1SerialSendOk(); - - return true; - } - serial_in_byte = 0; - return false; -} - - - -bool SnfL1SetChannels(void) -{ - if (Snfl1.receive_ready || TimeReached(Snfl1.unlock)) { - - uint8_t *scale_col = (uint8_t*)XdrvMailbox.topic; - - char buffer[140]; - snprintf_P(buffer, sizeof(buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"light_type\":1,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"bright\":%d,\"mode\":%d"), - LocalTime(), millis()%1000, - Light.power ? "on" : "off", - scale_col[0], scale_col[1], scale_col[2], - light_state.getDimmer(), - SONOFF_L1_MODE_COLORFUL); - - SnfL1Send(buffer); - - Snfl1.unlock = millis() + 500; - Snfl1.receive_ready = false; - } - return true; -} - -void SnfL1ModuleSelected(void) -{ - if (SONOFF_L1 == my_module_type) { - if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { - SetSerial(19200, TS_SERIAL_8N1); - - light_type = LT_RGB; - light_flg = XLGT_05; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); - } - } -} - - - - - -bool Xlgt05(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SERIAL: - result = SnfL1SerialInput(); - break; - case FUNC_SET_CHANNELS: - result = SnfL1SetChannels(); - break; - case FUNC_MODULE_INIT: - SnfL1ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_interface.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xlgt_interface.ino" -#ifdef USE_LIGHT - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xlgt_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xlgt_func_ptr[])(uint8_t) = { -#endif - -#ifdef XLGT_01 - &Xlgt01, -#endif - -#ifdef XLGT_02 - &Xlgt02, -#endif - -#ifdef XLGT_03 - &Xlgt03, -#endif - -#ifdef XLGT_04 - &Xlgt04, -#endif - -#ifdef XLGT_05 - &Xlgt05, -#endif - -#ifdef XLGT_06 - &Xlgt06, -#endif - -#ifdef XLGT_07 - &Xlgt07, -#endif - -#ifdef XLGT_08 - &Xlgt08, -#endif - -#ifdef XLGT_09 - &Xlgt09, -#endif - -#ifdef XLGT_10 - &Xlgt10, -#endif - -#ifdef XLGT_11 - &Xlgt11, -#endif - -#ifdef XLGT_12 - &Xlgt12, -#endif - -#ifdef XLGT_13 - &Xlgt13, -#endif - -#ifdef XLGT_14 - &Xlgt14, -#endif - -#ifdef XLGT_15 - &Xlgt15, -#endif - -#ifdef XLGT_16 - &Xlgt16 -#endif -}; - -const uint8_t xlgt_present = sizeof(xlgt_func_ptr) / sizeof(xlgt_func_ptr[0]); - -uint8_t xlgt_active = 0; - -bool XlgtCall(uint8_t function) -{ - DEBUG_TRACE_LOG(PSTR("LGT: %d"), function); - - if (FUNC_MODULE_INIT == function) { - for (uint32_t x = 0; x < xlgt_present; x++) { - xlgt_func_ptr[x](function); - if (light_flg) { - xlgt_active = x; - return true; - } - } - } - else if (light_flg) { - return xlgt_func_ptr[xlgt_active](function); - } - return false; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_01_hlw8012.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_01_hlw8012.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_HLW8012 - - - - - - -#define XNRG_01 1 - - -#define HLW_PREF 10000 -#define HLW_UREF 2200 -#define HLW_IREF 4545 - - -#define HJL_PREF 1362 -#define HJL_UREF 822 -#define HJL_IREF 3300 - -#define HLW_POWER_PROBE_TIME 10 -#define HLW_SAMPLE_COUNT 10 - - - -struct HLW { -#ifdef HLW_DEBUG - unsigned long debug[HLW_SAMPLE_COUNT]; -#endif - unsigned long cf_pulse_length = 0; - unsigned long cf_pulse_last_time = 0; - unsigned long cf_power_pulse_length = 0; - - unsigned long cf1_pulse_length = 0; - unsigned long cf1_pulse_last_time = 0; - unsigned long cf1_summed_pulse_length = 0; - unsigned long cf1_pulse_counter = 0; - unsigned long cf1_voltage_pulse_length = 0; - unsigned long cf1_current_pulse_length = 0; - - unsigned long energy_period_counter = 0; - - unsigned long power_ratio = 0; - unsigned long voltage_ratio = 0; - unsigned long current_ratio = 0; - - uint8_t model_type = 0; - uint8_t cf1_timer = 0; - uint8_t power_retry = 0; - bool select_ui_flag = false; - bool ui_flag = true; - bool load_off = true; -} Hlw; - - -#ifndef USE_WS2812_DMA -void HlwCfInterrupt(void) ICACHE_RAM_ATTR; -void HlwCf1Interrupt(void) ICACHE_RAM_ATTR; -#endif - -void HlwCfInterrupt(void) -{ - unsigned long us = micros(); - - if (Hlw.load_off) { - Hlw.cf_pulse_last_time = us; - Hlw.load_off = false; - } else { - Hlw.cf_pulse_length = us - Hlw.cf_pulse_last_time; - Hlw.cf_pulse_last_time = us; - Hlw.energy_period_counter++; - } - Energy.data_valid[0] = 0; -} - -void HlwCf1Interrupt(void) -{ - unsigned long us = micros(); - - Hlw.cf1_pulse_length = us - Hlw.cf1_pulse_last_time; - Hlw.cf1_pulse_last_time = us; - if ((Hlw.cf1_timer > 2) && (Hlw.cf1_timer < 8)) { - Hlw.cf1_summed_pulse_length += Hlw.cf1_pulse_length; -#ifdef HLW_DEBUG - Hlw.debug[Hlw.cf1_pulse_counter] = Hlw.cf1_pulse_length; -#endif - Hlw.cf1_pulse_counter++; - if (HLW_SAMPLE_COUNT == Hlw.cf1_pulse_counter) { - Hlw.cf1_timer = 8; - } - } - Energy.data_valid[0] = 0; -} - - - -void HlwEvery200ms(void) -{ - unsigned long cf1_pulse_length = 0; - unsigned long hlw_w = 0; - unsigned long hlw_u = 0; - unsigned long hlw_i = 0; - - if (micros() - Hlw.cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { - Hlw.cf_pulse_length = 0; - Hlw.load_off = true; - } - Hlw.cf_power_pulse_length = Hlw.cf_pulse_length; - - if (Hlw.cf_power_pulse_length && Energy.power_on && !Hlw.load_off) { - hlw_w = (Hlw.power_ratio * Settings.energy_power_calibration) / Hlw.cf_power_pulse_length ; - Energy.active_power[0] = (float)hlw_w / 10; - Hlw.power_retry = 1; - } else { - if (Hlw.power_retry) { - Hlw.power_retry--; - } else { - Energy.active_power[0] = 0; - } - } - - if (pin[GPIO_NRG_CF1] < 99) { - Hlw.cf1_timer++; - if (Hlw.cf1_timer >= 8) { - Hlw.cf1_timer = 0; - Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; - DigitalWrite(GPIO_NRG_SEL, Hlw.select_ui_flag); - - if (Hlw.cf1_pulse_counter) { - cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter; - } - -#ifdef HLW_DEBUG - - char stemp[100]; - stemp[0] = '\0'; - for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, Hlw.debug[i]); - } - for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { - for (uint32_t j = i + 1; j < Hlw.cf1_pulse_counter; j++) { - if (Hlw.debug[i] > Hlw.debug[j]) { - std::swap(Hlw.debug[i], Hlw.debug[j]); - } - } - } - unsigned long median = Hlw.debug[(Hlw.cf1_pulse_counter +1) / 2]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), - Hlw.cf_power_pulse_length , Hlw.select_ui_flag, Hlw.cf1_pulse_counter, stemp, Hlw.cf1_summed_pulse_length, cf1_pulse_length, median); -#endif - - if (Hlw.select_ui_flag == Hlw.ui_flag) { - Hlw.cf1_voltage_pulse_length = cf1_pulse_length; - - if (Hlw.cf1_voltage_pulse_length && Energy.power_on) { - hlw_u = (Hlw.voltage_ratio * Settings.energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; - Energy.voltage[0] = (float)hlw_u / 10; - } else { - Energy.voltage[0] = 0; - } - - } else { - Hlw.cf1_current_pulse_length = cf1_pulse_length; - - if (Hlw.cf1_current_pulse_length && Energy.active_power[0]) { - hlw_i = (Hlw.current_ratio * Settings.energy_current_calibration) / Hlw.cf1_current_pulse_length; - Energy.current[0] = (float)hlw_i / 1000; - } else { - Energy.current[0] = 0; - } - - } - Hlw.cf1_summed_pulse_length = 0; - Hlw.cf1_pulse_counter = 0; - } - } -} - -void HlwEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - Hlw.cf1_voltage_pulse_length = 0; - Hlw.cf1_current_pulse_length = 0; - Hlw.cf_power_pulse_length = 0; - } else { - unsigned long hlw_len; - - if (Hlw.energy_period_counter) { - hlw_len = 10000 / Hlw.energy_period_counter; - Hlw.energy_period_counter = 0; - if (hlw_len) { - Energy.kWhtoday_delta += ((Hlw.power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; - EnergyUpdateToday(); - } - } - } -} - -void HlwSnsInit(void) -{ - if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { - Settings.energy_power_calibration = HLW_PREF_PULSE; - Settings.energy_voltage_calibration = HLW_UREF_PULSE; - Settings.energy_current_calibration = HLW_IREF_PULSE; - } - - if (Hlw.model_type) { - Hlw.power_ratio = HJL_PREF; - Hlw.voltage_ratio = HJL_UREF; - Hlw.current_ratio = HJL_IREF; - } else { - Hlw.power_ratio = HLW_PREF; - Hlw.voltage_ratio = HLW_UREF; - Hlw.current_ratio = HLW_IREF; - } - - if (pin[GPIO_NRG_SEL] < 99) { - pinMode(pin[GPIO_NRG_SEL], OUTPUT); - digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); - } - if (pin[GPIO_NRG_CF1] < 99) { - pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); - attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); - } - pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); - attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); -} - -void HlwDrvInit(void) -{ - Hlw.model_type = 0; - if (pin[GPIO_HJL_CF] < 99) { - pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF]; - pin[GPIO_HJL_CF] = 99; - Hlw.model_type = 1; - } - - if (pin[GPIO_HLW_CF] < 99) { - - Hlw.ui_flag = true; - if (pin[GPIO_NRG_SEL_INV] < 99) { - pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; - pin[GPIO_NRG_SEL_INV] = 99; - Hlw.ui_flag = false; - } - - if (pin[GPIO_NRG_CF1] < 99) { - if (99 == pin[GPIO_NRG_SEL]) { - Energy.current_available = false; - } - } else { - Energy.current_available = false; - Energy.voltage_available = false; - } - - energy_flg = XNRG_01; - } -} - -bool HlwCommand(void) -{ - bool serviced = true; - - if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) { - - } - else if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) { - Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio; - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) { - Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio; - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) { - Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg01(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_200_MSECOND: - HlwEvery200ms(); - break; - case FUNC_ENERGY_EVERY_SECOND: - HlwEverySecond(); - break; - case FUNC_COMMAND: - result = HlwCommand(); - break; - case FUNC_INIT: - HlwSnsInit(); - break; - case FUNC_PRE_INIT: - HlwDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_02_cse7766.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_02_cse7766.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_CSE7766 - - - - - - - -#define XNRG_02 2 - -#define CSE_MAX_INVALID_POWER 128 - -#define CSE_NOT_CALIBRATED 0xAA - -#define CSE_PULSES_NOT_INITIALIZED -1 - -#define CSE_PREF 1000 -#define CSE_UREF 100 - -#define CSE_BUFFER_SIZE 25 - -#include - -TasmotaSerial *CseSerial = nullptr; - -struct CSE { - long voltage_cycle = 0; - long current_cycle = 0; - long power_cycle = 0; - long power_cycle_first = 0; - long cf_pulses = 0; - long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; - - int byte_counter = 0; - uint8_t *rx_buffer = nullptr; - uint8_t power_invalid = 0; - bool received = false; -} Cse; - -void CseReceived(void) -{ - - - - - - - uint8_t header = Cse.rx_buffer[0]; - if ((header & 0xFC) == 0xFC) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); - return; - } - - - if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { - long voltage_coefficient = 191200; - if (CSE_NOT_CALIBRATED != header) { - voltage_coefficient = Cse.rx_buffer[2] << 16 | Cse.rx_buffer[3] << 8 | Cse.rx_buffer[4]; - } - Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; - } - if (HLW_IREF_PULSE == Settings.energy_current_calibration) { - long current_coefficient = 16140; - if (CSE_NOT_CALIBRATED != header) { - current_coefficient = Cse.rx_buffer[8] << 16 | Cse.rx_buffer[9] << 8 | Cse.rx_buffer[10]; - } - Settings.energy_current_calibration = current_coefficient; - } - if (HLW_PREF_PULSE == Settings.energy_power_calibration) { - long power_coefficient = 5364000; - if (CSE_NOT_CALIBRATED != header) { - power_coefficient = Cse.rx_buffer[14] << 16 | Cse.rx_buffer[15] << 8 | Cse.rx_buffer[16]; - } - Settings.energy_power_calibration = power_coefficient / CSE_PREF; - } - - uint8_t adjustement = Cse.rx_buffer[20]; - Cse.voltage_cycle = Cse.rx_buffer[5] << 16 | Cse.rx_buffer[6] << 8 | Cse.rx_buffer[7]; - Cse.current_cycle = Cse.rx_buffer[11] << 16 | Cse.rx_buffer[12] << 8 | Cse.rx_buffer[13]; - Cse.power_cycle = Cse.rx_buffer[17] << 16 | Cse.rx_buffer[18] << 8 | Cse.rx_buffer[19]; - Cse.cf_pulses = Cse.rx_buffer[21] << 8 | Cse.rx_buffer[22]; - - if (Energy.power_on) { - if (adjustement & 0x40) { - Energy.voltage[0] = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle; - } - if (adjustement & 0x10) { - Cse.power_invalid = 0; - if ((header & 0xF2) == 0xF2) { - Energy.active_power[0] = 0; - } else { - if (0 == Cse.power_cycle_first) { Cse.power_cycle_first = Cse.power_cycle; } - if (Cse.power_cycle_first != Cse.power_cycle) { - Cse.power_cycle_first = -1; - Energy.active_power[0] = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle; - } else { - Energy.active_power[0] = 0; - } - } - } else { - if (Cse.power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { - Cse.power_invalid++; - } else { - Cse.power_cycle_first = 0; - Energy.active_power[0] = 0; - } - } - if (adjustement & 0x20) { - if (0 == Energy.active_power[0]) { - Energy.current[0] = 0; - } else { - Energy.current[0] = (float)Settings.energy_current_calibration / (float)Cse.current_cycle; - } - } - } else { - Cse.power_cycle_first = 0; - Energy.voltage[0] = 0; - Energy.active_power[0] = 0; - Energy.current[0] = 0; - } -} - -bool CseSerialInput(void) -{ - while (CseSerial->available()) { - yield(); - uint8_t serial_in_byte = CseSerial->read(); - - if (Cse.received) { - Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; - if (24 == Cse.byte_counter) { - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Cse.rx_buffer, 24); - - uint8_t checksum = 0; - for (uint32_t i = 2; i < 23; i++) { checksum += Cse.rx_buffer[i]; } - if (checksum == Cse.rx_buffer[23]) { - Energy.data_valid[0] = 0; - CseReceived(); - Cse.received = false; - return true; - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); - do { - memmove(Cse.rx_buffer, Cse.rx_buffer +1, 24); - Cse.byte_counter--; - } while ((Cse.byte_counter > 2) && (0x5A != Cse.rx_buffer[1])); - if (0x5A != Cse.rx_buffer[1]) { - Cse.received = false; - Cse.byte_counter = 0; - } - } - } - } else { - if ((0x5A == serial_in_byte) && (1 == Cse.byte_counter)) { - Cse.received = true; - } else { - Cse.byte_counter = 0; - } - Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; - } - } -} - - - -void CseEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - Cse.voltage_cycle = 0; - Cse.current_cycle = 0; - Cse.power_cycle = 0; - } else { - long cf_frequency = 0; - - if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) { - Cse.cf_pulses_last_time = Cse.cf_pulses; - } else { - if (Cse.cf_pulses < Cse.cf_pulses_last_time) { - cf_frequency = (65536 - Cse.cf_pulses_last_time) + Cse.cf_pulses; - } else { - cf_frequency = Cse.cf_pulses - Cse.cf_pulses_last_time; - } - if (cf_frequency && Energy.active_power[0]) { - unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; - - - - if (delta <= (4000*100/36) * 10 ) { - Cse.cf_pulses_last_time = Cse.cf_pulses; - Energy.kWhtoday_delta += delta; - } - else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow")); - Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; - } - EnergyUpdateToday(); - } - } - } -} - -void CseSnsInit(void) -{ - - - CseSerial = new TasmotaSerial(pin[GPIO_CSE7766_RX], -1, 1); - if (CseSerial->begin(4800, 2)) { - if (CseSerial->hardwareSerial()) { - SetSerial(4800, TS_SERIAL_8E1); - ClaimSerial(); - } - if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { - Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; - } - Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER]; - } else { - energy_flg = ENERGY_NONE; - } -} - -void CseDrvInit(void) -{ - Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); - if (Cse.rx_buffer != nullptr) { - - if (pin[GPIO_CSE7766_RX] < 99) { - energy_flg = XNRG_02; - } - } -} - -bool CseCommand(void) -{ - bool serviced = true; - - if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.power_cycle) { - Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF; - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.voltage_cycle) { - Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF; - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.current_cycle) { - Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - if (CseSerial) { CseSerialInput(); } - break; - case FUNC_ENERGY_EVERY_SECOND: - CseEverySecond(); - break; - case FUNC_COMMAND: - result = CseCommand(); - break; - case FUNC_INIT: - CseSnsInit(); - break; - case FUNC_PRE_INIT: - CseDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_03_pzem004t.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_03_pzem004t.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM004T -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_03_pzem004t.ino" -#define XNRG_03 3 - -const uint32_t PZEM_STABILIZE = 30; - -#include - -TasmotaSerial *PzemSerial = nullptr; - -#define PZEM_VOLTAGE (uint8_t)0xB0 -#define RESP_VOLTAGE (uint8_t)0xA0 - -#define PZEM_CURRENT (uint8_t)0xB1 -#define RESP_CURRENT (uint8_t)0xA1 - -#define PZEM_POWER (uint8_t)0xB2 -#define RESP_POWER (uint8_t)0xA2 - -#define PZEM_ENERGY (uint8_t)0xB3 -#define RESP_ENERGY (uint8_t)0xA3 - -#define PZEM_SET_ADDRESS (uint8_t)0xB4 -#define RESP_SET_ADDRESS (uint8_t)0xA4 - -#define PZEM_POWER_ALARM (uint8_t)0xB5 -#define RESP_POWER_ALARM (uint8_t)0xA5 - -#define PZEM_DEFAULT_READ_TIMEOUT 500 - - - -struct PZEM { - float energy = 0; - float last_energy = 0; - uint8_t send_retry = 0; - uint8_t read_state = 0; - uint8_t phase = 0; - uint8_t address = 0; -} Pzem; - -struct PZEMCommand { - uint8_t command; - uint8_t addr[4]; - uint8_t data; - uint8_t crc; -}; - -uint8_t PzemCrc(uint8_t *data) -{ - uint16_t crc = 0; - for (uint32_t i = 0; i < sizeof(PZEMCommand) -1; i++) { - crc += *data++; - } - return (uint8_t)(crc & 0xFF); -} - -void PzemSend(uint8_t cmd) -{ - PZEMCommand pzem; - - pzem.command = cmd; - pzem.addr[0] = 192; - pzem.addr[1] = 168; - pzem.addr[2] = 1; - pzem.addr[3] = ((PZEM_SET_ADDRESS == cmd) && Pzem.address) ? Pzem.address : 1 + Pzem.phase; - pzem.data = 0; - - uint8_t *bytes = (uint8_t*)&pzem; - pzem.crc = PzemCrc(bytes); - - PzemSerial->flush(); - PzemSerial->write(bytes, sizeof(pzem)); - - Pzem.address = 0; -} - -bool PzemReceiveReady(void) -{ - return PzemSerial->available() >= (int)sizeof(PZEMCommand); -} - -bool PzemRecieve(uint8_t resp, float *data) -{ -# 124 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_03_pzem004t.ino" - uint8_t buffer[sizeof(PZEMCommand)] = { 0 }; - - unsigned long start = millis(); - uint8_t len = 0; - while ((len < sizeof(PZEMCommand)) && (millis() - start < PZEM_DEFAULT_READ_TIMEOUT)) { - if (PzemSerial->available() > 0) { - uint8_t c = (uint8_t)PzemSerial->read(); - if (!len && ((c & 0xF8) != 0xA0)) { - continue; - } - buffer[len++] = c; - } - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, len); - - if (len != sizeof(PZEMCommand)) { - - return false; - } - if (buffer[6] != PzemCrc(buffer)) { - - return false; - } - if (buffer[0] != resp) { - - return false; - } - - switch (resp) { - case RESP_VOLTAGE: - *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 10.0); - break; - case RESP_CURRENT: - *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 100.0); - break; - case RESP_POWER: - *data = (float)(buffer[1] << 8) + buffer[2]; - break; - case RESP_ENERGY: - *data = (float)((uint32_t)buffer[1] << 16) + ((uint16_t)buffer[2] << 8) + buffer[3]; - break; - } - return true; -} - - - -const uint8_t pzem_commands[] { PZEM_SET_ADDRESS, PZEM_VOLTAGE, PZEM_CURRENT, PZEM_POWER, PZEM_ENERGY }; -const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, RESP_POWER, RESP_ENERGY }; - -void PzemEvery250ms(void) -{ - bool data_ready = PzemReceiveReady(); - - if (data_ready) { - float value = 0; - if (PzemRecieve(pzem_responses[Pzem.read_state], &value)) { - Energy.data_valid[Pzem.phase] = 0; - switch (Pzem.read_state) { - case 1: - Energy.voltage[Pzem.phase] = value; - break; - case 2: - Energy.current[Pzem.phase] = value; - break; - case 3: - Energy.active_power[Pzem.phase] = value; - break; - case 4: - Pzem.energy += value; - if (Pzem.phase == Energy.phase_count -1) { - if (Pzem.energy > Pzem.last_energy) { - if (uptime > PZEM_STABILIZE) { - EnergyUpdateTotal(Pzem.energy, false); - } - Pzem.last_energy = Pzem.energy; - } - Pzem.energy = 0; - } - break; - } - Pzem.read_state++; - if (5 == Pzem.read_state) { - Pzem.read_state = 1; - } - - - } - } - - if (0 == Pzem.send_retry || data_ready) { - if (1 == Pzem.read_state) { - if (0 == Pzem.phase) { - Pzem.phase = Energy.phase_count -1; - } else { - Pzem.phase--; - } - - - } - - if (Pzem.address) { - Pzem.read_state = 0; - } - - Pzem.send_retry = 5; - PzemSend(pzem_commands[Pzem.read_state]); - } - else { - Pzem.send_retry--; - if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < PZEM_STABILIZE)) { - Energy.phase_count--; - } - } -} - -void PzemSnsInit(void) -{ - - PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); - if (PzemSerial->begin(9600)) { - if (PzemSerial->hardwareSerial()) { - ClaimSerial(); - } - Energy.phase_count = 3; - Pzem.phase = 0; - Pzem.read_state = 1; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemDrvInit(void) -{ - if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_03; - } -} - -bool PzemCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { - Pzem.address = XdrvMailbox.payload; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg03(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (PzemSerial && (uptime > 4)) { PzemEvery250ms(); } - break; - case FUNC_COMMAND: - result = PzemCommand(); - break; - case FUNC_INIT: - PzemSnsInit(); - break; - case FUNC_PRE_INIT: - PzemDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_04_mcp39f501.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_04_mcp39f501.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_MCP39F501 - - - - - - - -#define XNRG_04 4 - -#define MCP_BAUDRATE 4800 -#define MCP_TIMEOUT 4 -#define MCP_CALIBRATION_TIMEOUT 2 - -#define MCP_CALIBRATE_POWER 0x001 -#define MCP_CALIBRATE_VOLTAGE 0x002 -#define MCP_CALIBRATE_CURRENT 0x004 -#define MCP_CALIBRATE_FREQUENCY 0x008 -#define MCP_SINGLE_WIRE_FLAG 0x100 - -#define MCP_START_FRAME 0xA5 -#define MCP_ACK_FRAME 0x06 -#define MCP_ERROR_NAK 0x15 -#define MCP_ERROR_CRC 0x51 - -#define MCP_SINGLE_WIRE 0xAB - -#define MCP_SET_ADDRESS 0x41 - -#define MCP_READ 0x4E -#define MCP_READ_16 0x52 -#define MCP_READ_32 0x44 - -#define MCP_WRITE 0x4D -#define MCP_WRITE_16 0x57 -#define MCP_WRITE_32 0x45 - -#define MCP_SAVE_REGISTERS 0x53 - -#define MCP_CALIBRATION_BASE 0x0028 -#define MCP_CALIBRATION_LEN 52 - -#define MCP_FREQUENCY_REF_BASE 0x0094 -#define MCP_FREQUENCY_GAIN_BASE 0x00AE -#define MCP_FREQUENCY_LEN 4 - -#define MCP_BUFFER_SIZE 60 - -#include -TasmotaSerial *McpSerial = nullptr; - -typedef struct mcp_cal_registers_type { - uint16_t gain_current_rms; - uint16_t gain_voltage_rms; - uint16_t gain_active_power; - uint16_t gain_reactive_power; - sint32_t offset_current_rms; - sint32_t offset_active_power; - sint32_t offset_reactive_power; - sint16_t dc_offset_current; - sint16_t phase_compensation; - uint16_t apparent_power_divisor; - - uint32_t system_configuration; - uint16_t dio_configuration; - uint32_t range; - - uint32_t calibration_current; - uint16_t calibration_voltage; - uint32_t calibration_active_power; - uint32_t calibration_reactive_power; - uint16_t accumulation_interval; -} mcp_cal_registers_type; - -char *mcp_buffer = nullptr; -unsigned long mcp_window = 0; -unsigned long mcp_kWhcounter = 0; -uint32_t mcp_system_configuration = 0x03000000; -uint32_t mcp_active_power; - - -uint32_t mcp_current_rms; -uint16_t mcp_voltage_rms; -uint16_t mcp_line_frequency; - -uint8_t mcp_address = 0; -uint8_t mcp_calibration_active = 0; -uint8_t mcp_init = 0; -uint8_t mcp_timeout = 0; -uint8_t mcp_calibrate = 0; -uint8_t mcp_byte_counter = 0; - - - - - - -uint8_t McpChecksum(uint8_t *data) -{ - uint8_t checksum = 0; - uint8_t offset = 0; - uint8_t len = data[1] -1; - - for (uint32_t i = offset; i < len; i++) { checksum += data[i]; } - return checksum; -} - -unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) -{ - unsigned long result = 0; - unsigned long pow = 1; - - for (uint32_t i = 0; i < size; i++) { - result = result + (uint8_t)data[offset + i] * pow; - pow = pow * 256; - } - return result; -} - -void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) -{ - for (uint32_t i = 0; i < size; i++) { - data[offset + i] = ((value >> (i * 8)) & 0xFF); - } -} - -void McpSend(uint8_t *data) -{ - if (mcp_timeout) { return; } - mcp_timeout = MCP_TIMEOUT; - - data[0] = MCP_START_FRAME; - data[data[1] -1] = McpChecksum(data); - - - - for (uint32_t i = 0; i < data[1]; i++) { - McpSerial->write(data[i]); - } -} - - - -void McpGetAddress(void) -{ - uint8_t data[] = { MCP_START_FRAME, 7, MCP_SET_ADDRESS, 0x00, 0x26, MCP_READ_16, 0x00 }; - - McpSend(data); -} - -void McpAddressReceive(void) -{ - - mcp_address = mcp_buffer[3]; -} - - - -void McpGetCalibration(void) -{ - if (mcp_calibration_active) { return; } - mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; - - uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, (MCP_CALIBRATION_BASE >> 8) & 0xFF, MCP_CALIBRATION_BASE & 0xFF, MCP_READ, MCP_CALIBRATION_LEN, 0x00 }; - - McpSend(data); -} - -void McpParseCalibration(void) -{ - bool action = false; - mcp_cal_registers_type cal_registers; - - - cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); - cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); - cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); - cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); - cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); - cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); - cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); - cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); - cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); - cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); - - cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); - cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); - cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); - - cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); - cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); - cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); - cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); - cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); - - if (mcp_calibrate & MCP_CALIBRATE_POWER) { - cal_registers.calibration_active_power = Settings.energy_power_calibration; - if (McpCalibrationCalc(&cal_registers, 16)) { action = true; } - } - if (mcp_calibrate & MCP_CALIBRATE_VOLTAGE) { - cal_registers.calibration_voltage = Settings.energy_voltage_calibration; - if (McpCalibrationCalc(&cal_registers, 0)) { action = true; } - } - if (mcp_calibrate & MCP_CALIBRATE_CURRENT) { - cal_registers.calibration_current = Settings.energy_current_calibration; - if (McpCalibrationCalc(&cal_registers, 8)) { action = true; } - } - mcp_timeout = 0; - if (action) { McpSetCalibration(&cal_registers); } - - mcp_calibrate = 0; - - Settings.energy_power_calibration = cal_registers.calibration_active_power; - Settings.energy_voltage_calibration = cal_registers.calibration_voltage; - Settings.energy_current_calibration = cal_registers.calibration_current; - - mcp_system_configuration = cal_registers.system_configuration; - - if (mcp_system_configuration & MCP_SINGLE_WIRE_FLAG) { - mcp_system_configuration &= ~MCP_SINGLE_WIRE_FLAG; - McpSetSystemConfiguration(2); - } -} - -bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift) -{ - uint32_t measured; - uint32_t expected; - uint16_t *gain; - uint32_t new_gain; - - if (range_shift == 0) { - measured = mcp_voltage_rms; - expected = cal_registers->calibration_voltage; - gain = &(cal_registers->gain_voltage_rms); - } else if (range_shift == 8) { - measured = mcp_current_rms; - expected = cal_registers->calibration_current; - gain = &(cal_registers->gain_current_rms); - } else if (range_shift == 16) { - measured = mcp_active_power; - expected = cal_registers->calibration_active_power; - gain = &(cal_registers->gain_active_power); - } else { - return false; - } - - if (measured == 0) { - return false; - } - - uint32_t range = (cal_registers->range >> range_shift) & 0xFF; - -calc: - new_gain = (*gain) * expected / measured; - - if (new_gain < 25000) { - range++; - if (measured > 6) { - measured = measured / 2; - goto calc; - } - } - - if (new_gain > 55000) { - range--; - measured = measured * 2; - goto calc; - } - - *gain = new_gain; - uint32_t old_range = (cal_registers->range >> range_shift) & 0xFF; - cal_registers->range = cal_registers->range ^ (old_range << range_shift); - cal_registers->range = cal_registers->range | (range << range_shift); - - return true; -} - - - - - - -void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) -{ - uint8_t data[7 + MCP_CALIBRATION_LEN + 2 + 1]; - - data[1] = sizeof(data); - data[2] = MCP_SET_ADDRESS; - data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; - data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; - - data[5] = MCP_WRITE; - data[6] = MCP_CALIBRATION_LEN; - - McpSetInt(cal_registers->gain_current_rms, data, 0+7, 2); - McpSetInt(cal_registers->gain_voltage_rms, data, 2+7, 2); - McpSetInt(cal_registers->gain_active_power, data, 4+7, 2); - McpSetInt(cal_registers->gain_reactive_power, data, 6+7, 2); - McpSetInt(cal_registers->offset_current_rms, data, 8+7, 4); - McpSetInt(cal_registers->offset_active_power, data, 12+7, 4); - McpSetInt(cal_registers->offset_reactive_power, data, 16+7, 4); - McpSetInt(cal_registers->dc_offset_current, data, 20+7, 2); - McpSetInt(cal_registers->phase_compensation, data, 22+7, 2); - McpSetInt(cal_registers->apparent_power_divisor, data, 24+7, 2); - - McpSetInt(cal_registers->system_configuration, data, 26+7, 4); - McpSetInt(cal_registers->dio_configuration, data, 30+7, 2); - McpSetInt(cal_registers->range, data, 32+7, 4); - - McpSetInt(cal_registers->calibration_current, data, 36+7, 4); - McpSetInt(cal_registers->calibration_voltage, data, 40+7, 2); - McpSetInt(cal_registers->calibration_active_power, data, 42+7, 4); - McpSetInt(cal_registers->calibration_reactive_power, data, 46+7, 4); - McpSetInt(cal_registers->accumulation_interval, data, 50+7, 2); - - data[MCP_CALIBRATION_LEN+7] = MCP_SAVE_REGISTERS; - data[MCP_CALIBRATION_LEN+8] = mcp_address; - - McpSend(data); -} - - - -void McpSetSystemConfiguration(uint16 interval) -{ - - uint8_t data[17]; - - data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; - data[ 3] = 0x00; - data[ 4] = 0x42; - data[ 5] = MCP_WRITE_32; - data[ 6] = (mcp_system_configuration >> 24) & 0xFF; - data[ 7] = (mcp_system_configuration >> 16) & 0xFF; - data[ 8] = (mcp_system_configuration >> 8) & 0xFF; - data[ 9] = (mcp_system_configuration >> 0) & 0xFF; - data[10] = MCP_SET_ADDRESS; - data[11] = 0x00; - data[12] = 0x5A; - data[13] = MCP_WRITE_16; - data[14] = (interval >> 8) & 0xFF; - data[15] = (interval >> 0) & 0xFF; - - McpSend(data); -} - - - -void McpGetFrequency(void) -{ - if (mcp_calibration_active) { return; } - mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; - - uint8_t data[] = { MCP_START_FRAME, 11, MCP_SET_ADDRESS, (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF, MCP_FREQUENCY_REF_BASE & 0xFF, MCP_READ_16, - MCP_SET_ADDRESS, (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF, MCP_FREQUENCY_GAIN_BASE & 0xFF, MCP_READ_16, 0x00 }; - - McpSend(data); -} - -void McpParseFrequency(void) -{ - - uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; - uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; - - if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { - line_frequency_ref = Settings.energy_frequency_calibration; - - if ((0xFFFF == mcp_line_frequency) || (0 == gain_line_frequency)) { - mcp_line_frequency = 50000; - gain_line_frequency = 0x8000; - } - gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_line_frequency; - - mcp_timeout = 0; - McpSetFrequency(line_frequency_ref, gain_line_frequency); - } - - Settings.energy_frequency_calibration = line_frequency_ref; - - mcp_calibrate = 0; -} - -void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) -{ - - uint8_t data[17]; - - data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; - data[ 3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; - data[ 4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; - - data[ 5] = MCP_WRITE_16; - data[ 6] = (line_frequency_ref >> 8) & 0xFF; - data[ 7] = (line_frequency_ref >> 0) & 0xFF; - - data[ 8] = MCP_SET_ADDRESS; - data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; - data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; - - data[11] = MCP_WRITE_16; - data[12] = (gain_line_frequency >> 8) & 0xFF; - data[13] = (gain_line_frequency >> 0) & 0xFF; - - data[14] = MCP_SAVE_REGISTERS; - data[15] = mcp_address; - - McpSend(data); -} - - - -void McpGetData(void) -{ - uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, 0x00, 0x04, MCP_READ, 22, 0x00 }; - - McpSend(data); -} - -void McpParseData(void) -{ - - - - - - mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); - mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); - mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); - - - mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); - - if (Energy.power_on) { - Energy.data_valid[0] = 0; - Energy.frequency[0] = (float)mcp_line_frequency / 1000; - Energy.voltage[0] = (float)mcp_voltage_rms / 10; - Energy.active_power[0] = (float)mcp_active_power / 100; - if (0 == Energy.active_power[0]) { - Energy.current[0] = 0; - } else { - Energy.current[0] = (float)mcp_current_rms / 10000; - } - } else { - Energy.data_valid[0] = ENERGY_WATCHDOG; - } -} - - - -void McpSerialInput(void) -{ - while ((McpSerial->available()) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { - yield(); - mcp_buffer[mcp_byte_counter++] = McpSerial->read(); - mcp_window = millis(); - } - - - if ((mcp_byte_counter) && (millis() - mcp_window > (24000 / MCP_BAUDRATE) +1)) { - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); - - if (MCP_BUFFER_SIZE == mcp_byte_counter) { - - } - else if (1 == mcp_byte_counter) { - if (MCP_ERROR_CRC == mcp_buffer[0]) { - - mcp_timeout = 0; - } - else if (MCP_ERROR_NAK == mcp_buffer[0]) { - - mcp_timeout = 0; - } - } - else if (MCP_ACK_FRAME == mcp_buffer[0]) { - if (mcp_byte_counter == mcp_buffer[1]) { - - if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); - } else { - if (5 == mcp_buffer[1]) { McpAddressReceive(); } - if (25 == mcp_buffer[1]) { McpParseData(); } - if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } - if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } - } - - } - mcp_timeout = 0; - } - else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { - mcp_timeout = 0; - } - - mcp_byte_counter = 0; - McpSerial->flush(); - } -} - - - -void McpEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - mcp_voltage_rms = 0; - mcp_current_rms = 0; - mcp_active_power = 0; - mcp_line_frequency = 0; - } - - if (mcp_active_power) { - Energy.kWhtoday_delta += ((mcp_active_power * 10) / 36); - EnergyUpdateToday(); - } - - if (mcp_timeout) { - mcp_timeout--; - } - else if (mcp_calibration_active) { - mcp_calibration_active--; - } - else if (mcp_init) { - if (2 == mcp_init) { - McpGetCalibration(); - } - else if (1 == mcp_init) { - McpGetFrequency(); - } - mcp_init--; - } - else if (!mcp_address) { - McpGetAddress(); - } - else { - McpGetData(); - } -} - -void McpSnsInit(void) -{ - - McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); - if (McpSerial->begin(MCP_BAUDRATE)) { - if (McpSerial->hardwareSerial()) { - ClaimSerial(); - mcp_buffer = serial_in_buffer; - } else { - mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); - } - DigitalWrite(GPIO_MCP39F5_RST, 1); - } else { - energy_flg = ENERGY_NONE; - } -} - -void McpDrvInit(void) -{ - if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { - if (pin[GPIO_MCP39F5_RST] < 99) { - pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); - digitalWrite(pin[GPIO_MCP39F5_RST], 0); - } - mcp_calibrate = 0; - mcp_timeout = 2; - mcp_init = 2; - energy_flg = XNRG_04; - } -} - -bool McpCommand(void) -{ - bool serviced = true; - unsigned long value = 0; - - if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_active_power) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100); - if ((value > 100) && (value < 200000)) { - Settings.energy_power_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_POWER; - McpGetCalibration(); - } - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_voltage_rms) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > 1000) && (value < 2600)) { - Settings.energy_voltage_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_VOLTAGE; - McpGetCalibration(); - } - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_current_rms) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > 100) && (value < 80000)) { - Settings.energy_current_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_CURRENT; - McpGetCalibration(); - } - } - } - else if (CMND_FREQUENCYSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_line_frequency) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000); - if ((value > 45000) && (value < 65000)) { - Settings.energy_frequency_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_FREQUENCY; - McpGetFrequency(); - } - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg04(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - if (McpSerial) { McpSerialInput(); } - break; - case FUNC_ENERGY_EVERY_SECOND: - if (McpSerial) { McpEverySecond(); } - break; - case FUNC_COMMAND: - result = McpCommand(); - break; - case FUNC_INIT: - McpSnsInit(); - break; - case FUNC_PRE_INIT: - McpDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM_AC -# 33 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -#define XNRG_05 5 - -const uint8_t PZEM_AC_DEVICE_ADDRESS = 0x01; -const uint32_t PZEM_AC_STABILIZE = 30; - -#include -TasmotaModbus *PzemAcModbus; - -struct PZEMAC { - float energy = 0; - float last_energy = 0; - uint8_t send_retry = 0; - uint8_t phase = 0; - uint8_t address = 0; - uint8_t address_step = ADDR_IDLE; -} PzemAc; - -void PzemAcEverySecond(void) -{ - bool data_ready = PzemAcModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[30]; - - uint8_t registers = 10; - if (ADDR_RECEIVE == PzemAc.address_step) { - registers = 2; - PzemAc.address_step--; - } - uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, registers); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemAcModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAC: PzemAc %d error %d"), PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, error); - } else { - Energy.data_valid[PzemAc.phase] = 0; - if (10 == registers) { - - - - - - Energy.voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0; - Energy.current[PzemAc.phase] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; - Energy.active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; - Energy.frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0; - Energy.power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0; - - PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); - if (PzemAc.phase == Energy.phase_count -1) { - if (PzemAc.energy > PzemAc.last_energy) { - if (uptime > PZEM_AC_STABILIZE) { - EnergyUpdateTotal(PzemAc.energy, false); - } - PzemAc.last_energy = PzemAc.energy; - } - PzemAc.energy = 0; - } - - } - } - } - - if (0 == PzemAc.send_retry || data_ready) { - if (0 == PzemAc.phase) { - PzemAc.phase = Energy.phase_count -1; - } else { - PzemAc.phase--; - } - PzemAc.send_retry = ENERGY_WATCHDOG; - if (ADDR_SEND == PzemAc.address_step) { - PzemAcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemAc.address); - PzemAc.address_step--; - } else { - PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, 0x04, 0, 10); - } - } - else { - PzemAc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < PZEM_AC_STABILIZE)) { - Energy.phase_count--; - } - } -} - -void PzemAcSnsInit(void) -{ - PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); - uint8_t result = PzemAcModbus->Begin(9600); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.phase_count = 3; - PzemAc.phase = 0; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemAcDrvInit(void) -{ - if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_05; - } -} - -bool PzemAcCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - PzemAc.address = XdrvMailbox.payload; - PzemAc.address_step = ADDR_SEND; - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg05(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { PzemAcEverySecond(); } - break; - case FUNC_COMMAND: - result = PzemAcCommand(); - break; - case FUNC_INIT: - PzemAcSnsInit(); - break; - case FUNC_PRE_INIT: - PzemAcDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM_DC -# 32 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -#define XNRG_06 6 - -const uint8_t PZEM_DC_DEVICE_ADDRESS = 0x01; -const uint32_t PZEM_DC_STABILIZE = 30; - -#include -TasmotaModbus *PzemDcModbus; - -struct PZEMDC { - float energy = 0; - float last_energy = 0; - uint8_t send_retry = 0; - uint8_t channel = 0; - uint8_t address = 0; - uint8_t address_step = ADDR_IDLE; -} PzemDc; - -void PzemDcEverySecond(void) -{ - bool data_ready = PzemDcModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[26]; - - uint8_t registers = 8; - if (ADDR_RECEIVE == PzemDc.address_step) { - registers = 2; - PzemDc.address_step--; - } - uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, registers); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemDcModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PDC: PzemDc %d error %d"), PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, error); - } else { - Energy.data_valid[PzemDc.channel] = 0; - if (8 == registers) { - - - - - - Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; - Energy.current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0; - Energy.active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; - - PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); - if (PzemDc.channel == Energy.phase_count -1) { - if (PzemDc.energy > PzemDc.last_energy) { - if (uptime > PZEM_DC_STABILIZE) { - EnergyUpdateTotal(PzemDc.energy, false); - } - PzemDc.last_energy = PzemDc.energy; - } - PzemDc.energy = 0; - } - } - } - } - - if (0 == PzemDc.send_retry || data_ready) { - if (0 == PzemDc.channel) { - PzemDc.channel = Energy.phase_count -1; - } else { - PzemDc.channel--; - } - PzemDc.send_retry = ENERGY_WATCHDOG; - if (ADDR_SEND == PzemDc.address_step) { - PzemDcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemDc.address); - PzemDc.address_step--; - } else { - PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, 0x04, 0, 8); - } - } - else { - PzemDc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < PZEM_DC_STABILIZE)) { - Energy.phase_count--; - } - } -} - -void PzemDcSnsInit(void) -{ - PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); - uint8_t result = PzemDcModbus->Begin(9600, 2); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.type_dc = true; - Energy.phase_count = 3; - PzemDc.channel = 0; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemDcDrvInit(void) -{ - if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_06; - } -} - -bool PzemDcCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - PzemDc.address = XdrvMailbox.payload; - PzemDc.address_step = ADDR_SEND; - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg06(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { PzemDcEverySecond(); } - break; - case FUNC_COMMAND: - result = PzemDcCommand(); - break; - case FUNC_INIT: - PzemDcSnsInit(); - break; - case FUNC_PRE_INIT: - PzemDcDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_07_ade7953.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_07_ade7953.ino" -#ifdef USE_I2C -#ifdef USE_ENERGY_SENSOR -#ifdef USE_ADE7953 -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_07_ade7953.ino" -#define XNRG_07 7 -#define XI2C_07 7 - -#define ADE7953_PREF 1540 -#define ADE7953_UREF 26000 -#define ADE7953_IREF 10000 - -#define ADE7953_ADDR 0x38 - -const uint16_t Ade7953Registers[] { - 0x31B, - 0x313, - 0x311, - 0x315, - 0x31A, - 0x312, - 0x310, - 0x314, - 0x31C, - 0x10E -}; - -struct Ade7953 { - uint32_t voltage_rms = 0; - uint32_t period = 0; - uint32_t current_rms[2] = { 0, 0 }; - uint32_t active_power[2] = { 0, 0 }; - uint8_t init_step = 0; -} Ade7953; - -int Ade7953RegSize(uint16_t reg) -{ - int size = 0; - switch ((reg >> 8) & 0x0F) { - case 0x03: - size++; - case 0x02: - size++; - case 0x01: - size++; - case 0x00: - case 0x07: - case 0x08: - size++; - } - return size; -} - -void Ade7953Write(uint16_t reg, uint32_t val) -{ - int size = Ade7953RegSize(reg); - if (size) { - Wire.beginTransmission(ADE7953_ADDR); - Wire.write((reg >> 8) & 0xFF); - Wire.write(reg & 0xFF); - while (size--) { - Wire.write((val >> (8 * size)) & 0xFF); - } - Wire.endTransmission(); - delayMicroseconds(5); - } -} - -int32_t Ade7953Read(uint16_t reg) -{ - uint32_t response = 0; - - int size = Ade7953RegSize(reg); - if (size) { - Wire.beginTransmission(ADE7953_ADDR); - Wire.write((reg >> 8) & 0xFF); - Wire.write(reg & 0xFF); - Wire.endTransmission(0); - Wire.requestFrom(ADE7953_ADDR, size); - if (size <= Wire.available()) { - for (uint32_t i = 0; i < size; i++) { - response = response << 8 | Wire.read(); - } - } - } - return response; -} - -void Ade7953Init(void) -{ - Ade7953Write(0x102, 0x0004); - Ade7953Write(0x0FE, 0x00AD); - Ade7953Write(0x120, 0x0030); -} - -void Ade7953GetData(void) -{ - int32_t reg[2][4]; - for (uint32_t i = 0; i < sizeof(Ade7953Registers)/sizeof(uint16_t); i++) { - int32_t value = Ade7953Read(Ade7953Registers[i]); - if (8 == i) { - Ade7953.voltage_rms = value; - } else if (9 == i) { - Ade7953.period = value; - } else { - reg[i >> 2][i &3] = value; - } - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"), - Ade7953.voltage_rms, Ade7953.period, - reg[0][0], reg[0][1], reg[0][2], reg[0][3], - reg[1][0], reg[1][1], reg[1][2], reg[1][3]); - - uint32_t apparent_power[2] = { 0, 0 }; - uint32_t reactive_power[2] = { 0, 0 }; - - for (uint32_t channel = 0; channel < 2; channel++) { - Ade7953.current_rms[channel] = reg[channel][0]; - if (Ade7953.current_rms[channel] < 2000) { - Ade7953.current_rms[channel] = 0; - Ade7953.active_power[channel] = 0; - } else { - Ade7953.active_power[channel] = abs(reg[channel][1]); - apparent_power[channel] = abs(reg[channel][2]); - reactive_power[channel] = abs(reg[channel][3]); - } - } - - uint32_t current_rms_sum = Ade7953.current_rms[0] + Ade7953.current_rms[1]; - uint32_t active_power_sum = Ade7953.active_power[0] + Ade7953.active_power[1]; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, C %d, I %d + %d = %d, P %d + %d = %d"), - Ade7953.voltage_rms, Ade7953.period, - Ade7953.current_rms[0], Ade7953.current_rms[1], current_rms_sum, - Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum); - - if (Energy.power_on) { - Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration; - Energy.frequency[0] = 223750.0f / ( (float)Ade7953.period + 1); - - for (uint32_t channel = 0; channel < 2; channel++) { - Energy.data_valid[channel] = 0; - Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings.energy_power_calibration / 10); - Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings.energy_power_calibration / 10); - Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings.energy_power_calibration / 10); - if (0 == Energy.active_power[channel]) { - Energy.current[channel] = 0; - } else { - Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings.energy_current_calibration * 10); - } - } - } else { - Energy.data_valid[0] = ENERGY_WATCHDOG; - Energy.data_valid[1] = ENERGY_WATCHDOG; - } - - if (active_power_sum) { - Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings.energy_power_calibration / 10))) / 3600); - EnergyUpdateToday(); - } -} - -void Ade7953EnergyEverySecond(void) -{ - if (Ade7953.init_step) { - if (1 == Ade7953.init_step) { - Ade7953Init(); - } - Ade7953.init_step--; - } else { - Ade7953GetData(); - } -} - -void Ade7953DrvInit(void) -{ - if (pin[GPIO_ADE7953_IRQ] < 99) { - delay(100); - if (I2cSetDevice(ADE7953_ADDR)) { - if (HLW_PREF_PULSE == Settings.energy_power_calibration) { - Settings.energy_power_calibration = ADE7953_PREF; - Settings.energy_voltage_calibration = ADE7953_UREF; - Settings.energy_current_calibration = ADE7953_IREF; - } - I2cSetActiveFound(ADE7953_ADDR, "ADE7953"); - Ade7953.init_step = 2; - - Energy.phase_count = 2; - Energy.voltage_common = true; - - energy_flg = XNRG_07; - } - } -} - -bool Ade7953Command(void) -{ - bool serviced = true; - - uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0; - uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); - - if (CMND_POWERCAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; } - - } - else if (CMND_VOLTAGECAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_UREF; } - - } - else if (CMND_CURRENTCAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_IREF; } - - } - else if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.active_power[channel]) { - if ((value > 100) && (value < 200000)) { - Settings.energy_power_calibration = (Ade7953.active_power[channel] * 1000) / value; - } - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.voltage_rms) { - if ((value > 10000) && (value < 26000)) { - Settings.energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; - } - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) { - if ((value > 2000) && (value < 1000000)) { - Settings.energy_current_calibration = ((Ade7953.current_rms[channel] * 100) / value) * 100; - } - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg07(uint8_t function) -{ - if (!I2cEnabled(XI2C_07)) { return false; } - - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - Ade7953EnergyEverySecond(); - break; - case FUNC_COMMAND: - result = Ade7953Command(); - break; - case FUNC_PRE_INIT: - Ade7953DrvInit(); - break; - } - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_08_sdm120.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_08_sdm120.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM120 - - - - - - -#define XNRG_08 8 - - -#ifndef SDM120_SPEED - #define SDM120_SPEED 2400 -#endif - -#ifndef SDM120_ADDR - #define SDM120_ADDR 1 -#endif - -#include -TasmotaModbus *Sdm120Modbus; - -const uint8_t sdm120_table = 8; -const uint8_t sdm220_table = 13; - -const uint16_t sdm120_start_addresses[] { - 0x0000, - 0x0006, - 0x000C, - 0x0012, - 0x0018, - 0x001E, - 0x0046, - 0x0156, - - 0X0048, - 0X004A, - 0X004C, - 0X004E, - 0X0024 -}; - -struct SDM120 { - float total_active = 0; - float import_active = NAN; - float import_reactive = 0; - float export_reactive = 0; - float phase_angle = 0; - uint8_t read_state = 0; - uint8_t send_retry = 0; - uint8_t start_address_count = sdm220_table; -} Sdm120; - - - -void SDM120Every250ms(void) -{ - bool data_ready = Sdm120Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm120Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM120 error %d"), error); - } else { - Energy.data_valid[0] = 0; - - - - - float value; - ((uint8_t*)&value)[3] = buffer[3]; - ((uint8_t*)&value)[2] = buffer[4]; - ((uint8_t*)&value)[1] = buffer[5]; - ((uint8_t*)&value)[0] = buffer[6]; - - switch(Sdm120.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.current[0] = value; - break; - - case 2: - Energy.active_power[0] = value; - break; - - case 3: - Energy.apparent_power[0] = value; - break; - - case 4: - Energy.reactive_power[0] = value; - break; - - case 5: - Energy.power_factor[0] = value; - break; - - case 6: - Energy.frequency[0] = value; - break; - - case 7: - Sdm120.total_active = value; - break; - - case 8: - Sdm120.import_active = value; - break; - - case 9: - Energy.export_active = value; - break; - - case 10: - Sdm120.import_reactive = value; - break; - - case 11: - Sdm120.export_reactive = value; - break; - - case 12: - Sdm120.phase_angle = value; - break; - } - - Sdm120.read_state++; - if (Sdm120.read_state == Sdm120.start_address_count) { - Sdm120.read_state = 0; - - if (Sdm120.start_address_count > sdm120_table) { - if (!isnan(Sdm120.import_active)) { - Sdm120.total_active = Sdm120.import_active; - } else { - Sdm120.start_address_count = sdm120_table; - } - } - EnergyUpdateTotal(Sdm120.total_active, true); - } - } - } - - if (0 == Sdm120.send_retry || data_ready) { - Sdm120.send_retry = 5; - Sdm120Modbus->Send(SDM120_ADDR, 0x04, sdm120_start_addresses[Sdm120.read_state], 2); - } else { - Sdm120.send_retry--; - } -} - -void Sdm120SnsInit(void) -{ - Sdm120Modbus = new TasmotaModbus(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX]); - uint8_t result = Sdm120Modbus->Begin(SDM120_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Sdm120DrvInit(void) -{ - if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { - energy_flg = XNRG_08; - } -} - -void Sdm220Reset(void) -{ - if (isnan(Sdm120.import_active)) { return; } - - Sdm120.import_active = 0; - Sdm120.import_reactive = 0; - Sdm120.export_reactive = 0; - Sdm120.phase_angle = 0; -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_SDM220[] PROGMEM = - "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}"; -#endif - -void Sdm220Show(bool json) -{ - if (isnan(Sdm120.import_active)) { return; } - - char import_active_chr[FLOATSZ]; - dtostrfd(Sdm120.import_active, Settings.flag2.energy_resolution, import_active_chr); - char import_reactive_chr[FLOATSZ]; - dtostrfd(Sdm120.import_reactive, Settings.flag2.energy_resolution, import_reactive_chr); - char export_reactive_chr[FLOATSZ]; - dtostrfd(Sdm120.export_reactive, Settings.flag2.energy_resolution, export_reactive_chr); - char phase_angle_chr[FLOATSZ]; - dtostrfd(Sdm120.phase_angle, 2, phase_angle_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s"), - import_active_chr, import_reactive_chr, export_reactive_chr, phase_angle_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_ENERGY_SDM220, import_reactive_chr, export_reactive_chr, phase_angle_chr); -#endif - } -} - - - - - -bool Xnrg08(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { SDM120Every250ms(); } - break; - case FUNC_JSON_APPEND: - Sdm220Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sdm220Show(0); - break; -#endif - case FUNC_ENERGY_RESET: - Sdm220Reset(); - break; - case FUNC_INIT: - Sdm120SnsInit(); - break; - case FUNC_PRE_INIT: - Sdm120DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_09_dds2382.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_09_dds2382.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_DDS2382 - - - - - - -#define XNRG_09 9 - -#ifndef DDS2382_SPEED -#define DDS2382_SPEED 9600 -#endif -#ifndef DDS2382_ADDR -#define DDS2382_ADDR 1 -#endif - -#include -TasmotaModbus *Dds2382Modbus; - -uint8_t Dds2382_send_retry = 0; - -void Dds2382EverySecond(void) -{ - bool data_ready = Dds2382Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[46]; - - uint32_t error = Dds2382Modbus->ReceiveBuffer(buffer, 18); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Dds2382Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "DDS2382 response error %d"), error); - } else { - Energy.data_valid[0] = 0; -# 67 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_09_dds2382.ino" - Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0; - Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0; - Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]); - Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]); - Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; - Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; - uint8_t offset = 11; - if (Settings.flag3.dds2382_model) { - offset = 19; - } - Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; - float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; - - EnergyUpdateTotal(import_active, true); - } - } - - if (0 == Dds2382_send_retry || data_ready) { - Dds2382_send_retry = 5; - Dds2382Modbus->Send(DDS2382_ADDR, 0x03, 0, 18); - } else { - Dds2382_send_retry--; - } -} - -void Dds2382SnsInit(void) -{ - Dds2382Modbus = new TasmotaModbus(pin[GPIO_DDS2382_RX], pin[GPIO_DDS2382_TX]); - uint8_t result = Dds2382Modbus->Begin(DDS2382_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Dds2382DrvInit(void) -{ - if ((pin[GPIO_DDS2382_RX] < 99) && (pin[GPIO_DDS2382_TX] < 99)) { - energy_flg = XNRG_09; - } -} - - - - - -bool Xnrg09(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { Dds2382EverySecond(); } - break; - case FUNC_INIT: - Dds2382SnsInit(); - break; - case FUNC_PRE_INIT: - Dds2382DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_10_sdm630.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_10_sdm630.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM630 - - - - - - -#define XNRG_10 10 - - -#ifndef SDM630_SPEED - #define SDM630_SPEED 9600 -#endif - -#ifndef SDM630_ADDR - #define SDM630_ADDR 1 -#endif - -#include -TasmotaModbus *Sdm630Modbus; - -const uint16_t sdm630_start_addresses[] { - 0x0000, - 0x0002, - 0x0004, - 0x0006, - 0x0008, - 0x000A, - 0x000C, - 0x000E, - 0x0010, - 0x0018, - 0x001A, - 0x001C, - 0x001E, - 0x0020, - 0x0022, - 0x0156 -}; - -struct SDM630 { - uint8_t read_state = 0; - uint8_t send_retry = 0; -} Sdm630; - - - -void SDM630Every250ms(void) -{ - bool data_ready = Sdm630Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Sdm630Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm630Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM630 error %d"), error); - } else { - Energy.data_valid[0] = 0; - Energy.data_valid[1] = 0; - Energy.data_valid[2] = 0; - - - - - float value; - ((uint8_t*)&value)[3] = buffer[3]; - ((uint8_t*)&value)[2] = buffer[4]; - ((uint8_t*)&value)[1] = buffer[5]; - ((uint8_t*)&value)[0] = buffer[6]; - - switch(Sdm630.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.voltage[1] = value; - break; - - case 2: - Energy.voltage[2] = value; - break; - - case 3: - Energy.current[0] = value; - break; - - case 4: - Energy.current[1] = value; - break; - - case 5: - Energy.current[2] = value; - break; - - case 6: - Energy.active_power[0] = value; - break; - - case 7: - Energy.active_power[1] = value; - break; - - case 8: - Energy.active_power[2] = value; - break; - - case 9: - Energy.reactive_power[0] = value; - break; - - case 10: - Energy.reactive_power[1] = value; - break; - - case 11: - Energy.reactive_power[2] = value; - break; - - case 12: - Energy.power_factor[0] = value; - break; - - case 13: - Energy.power_factor[1] = value; - break; - - case 14: - Energy.power_factor[2] = value; - break; - - case 15: - EnergyUpdateTotal(value, true); - break; - } - - Sdm630.read_state++; - if (sizeof(sdm630_start_addresses)/2 == Sdm630.read_state) { - Sdm630.read_state = 0; - } - } - } - - if (0 == Sdm630.send_retry || data_ready) { - Sdm630.send_retry = 5; - Sdm630Modbus->Send(SDM630_ADDR, 0x04, sdm630_start_addresses[Sdm630.read_state], 2); - } else { - Sdm630.send_retry--; - } -} - -void Sdm630SnsInit(void) -{ - Sdm630Modbus = new TasmotaModbus(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX]); - uint8_t result = Sdm630Modbus->Begin(SDM630_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.phase_count = 3; - } else { - energy_flg = ENERGY_NONE; - } -} - -void Sdm630DrvInit(void) -{ - if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { - energy_flg = XNRG_10; - } -} - - - - - -bool Xnrg10(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { SDM630Every250ms(); } - break; - case FUNC_INIT: - Sdm630SnsInit(); - break; - case FUNC_PRE_INIT: - Sdm630DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_11_ddsu666.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_11_ddsu666.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_DDSU666 - - - - -#define XNRG_11 11 - - -#ifndef DDSU666_SPEED - #define DDSU666_SPEED 9600 -#endif - -#ifndef DDSU666_ADDR - #define DDSU666_ADDR 1 -#endif - -#include -TasmotaModbus *Ddsu666Modbus; - -const uint16_t Ddsu666_start_addresses[] { - 0x2000, - 0x2002, - 0x2004, - 0x2006, - 0x200A, - 0x200E, - 0X4000, - 0X400A, -}; - -struct DDSU666 { - float import_active = NAN; - uint8_t read_state = 0; - uint8_t send_retry = 0; -} Ddsu666; - - - -void DDSU666Every250ms(void) -{ - bool data_ready = Ddsu666Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Ddsu666Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Ddsu666Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: Ddsu666 error %d"), error); - } else { - Energy.data_valid[0] = 0; - - - - - float value; - ((uint8_t*)&value)[3] = buffer[3]; - ((uint8_t*)&value)[2] = buffer[4]; - ((uint8_t*)&value)[1] = buffer[5]; - ((uint8_t*)&value)[0] = buffer[6]; - - switch(Ddsu666.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.current[0] = value; - break; - - case 2: - Energy.active_power[0] = value * 1000; - break; - - case 3: - Energy.reactive_power[0] = value * 1000; - break; - - case 4: - Energy.power_factor[0] = value; - break; - - case 5: - Energy.frequency[0] = value; - break; - - case 6: - Ddsu666.import_active = value; - break; - - case 7: - Energy.export_active = value; - break; - } - - Ddsu666.read_state++; - - if (Ddsu666.read_state == 8) { - Ddsu666.read_state = 0; - EnergyUpdateTotal(Ddsu666.import_active, true); - } - } - } - - if (0 == Ddsu666.send_retry || data_ready) { - Ddsu666.send_retry = 5; - Ddsu666Modbus->Send(DDSU666_ADDR, 0x04, Ddsu666_start_addresses[Ddsu666.read_state], 2); - } else { - Ddsu666.send_retry--; - } -} - -void Ddsu666SnsInit(void) -{ - Ddsu666Modbus = new TasmotaModbus(pin[GPIO_DDSU666_RX], pin[GPIO_DDSU666_TX]); - uint8_t result = Ddsu666Modbus->Begin(DDSU666_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Ddsu666DrvInit(void) -{ - if ((pin[GPIO_DDSU666_RX] < 99) && (pin[GPIO_DDSU666_TX] < 99)) { - energy_flg = XNRG_11; - } -} - - - - - -bool Xnrg11(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { DDSU666Every250ms(); } - break; - case FUNC_INIT: - Ddsu666SnsInit(); - break; - case FUNC_PRE_INIT: - Ddsu666DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_12_solaxX1.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_12_solaxX1.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SOLAX_X1 - - - - -#define XNRG_12 12 - -#ifndef SOLAXX1_SPEED -#define SOLAXX1_SPEED 9600 -#endif - -#define INVERTER_ADDRESS 0x0A - -#define D_SOLAX_X1 "SolaxX1" - -#include - -enum solaxX1_Error -{ - solaxX1_ERR_NO_ERROR, - solaxX1_ERR_CRC_ERROR -}; - -union { - uint32_t ErrMessage; - struct { - - uint8_t TzProtectFault:1; - uint8_t MainsLostFault:1; - uint8_t GridVoltFault:1; - uint8_t GridFreqFault:1; - uint8_t PLLLostFault:1; - uint8_t BusVoltFault:1; - uint8_t ErrBit06:1; - uint8_t OciFault:1; - - uint8_t Dci_OCP_Fault:1; - uint8_t ResidualCurrentFault:1; - uint8_t PvVoltFault:1; - uint8_t Ac10Mins_Voltage_Fault:1; - uint8_t IsolationFault:1; - uint8_t TemperatureOverFault:1; - uint8_t FanFault:1; - uint8_t ErrBit15:1; - - uint8_t SpiCommsFault:1; - uint8_t SciCommsFault:1; - uint8_t ErrBit18:1; - uint8_t InputConfigFault:1; - uint8_t EepromFault:1; - uint8_t RelayFault:1; - uint8_t SampleConsistenceFault:1; - uint8_t ResidualCurrent_DeviceFault:1; - - uint8_t ErrBit24:1; - uint8_t ErrBit25:1; - uint8_t ErrBit26:1; - uint8_t ErrBit27:1; - uint8_t ErrBit28:1; - uint8_t DCI_DeviceFault:1; - uint8_t OtherDeviceFault:1; - uint8_t ErrBit31:1; - }; -} ErrCode; - -const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; - -const char kSolaxError[] PROGMEM = - D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" - D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; - - - -TasmotaSerial *solaxX1Serial; - -uint8_t solaxX1_Init = 1; - -struct SOLAXX1 { - float temperature = 0; - float energy_today = 0; - float dc1_voltage = 0; - float dc2_voltage = 0; - float dc1_current = 0; - float dc2_current = 0; - float energy_total = 0; - float runtime_total = 0; - float dc1_power = 0; - float dc2_power = 0; - - uint8_t status = 0; - uint32_t errorCode = 0; -} solaxX1; - -union { - uint8_t status; - struct { - uint8_t freeBit7:1; - uint8_t freeBit6:1; - uint8_t freeBit5:1; - uint8_t queryOffline:1; - uint8_t queryOfflineSend:1; - uint8_t hasAddress:1; - uint8_t inverterAddressSend:1; - uint8_t inverterSnReceived:1; - }; -} protocolStatus; - -uint8_t header[2] = {0xAA, 0x55}; -uint8_t source[2] = {0x00, 0x00}; -uint8_t destination[2] = {0x00, 0x00}; -uint8_t controlCode[1] = {0x00}; -uint8_t functionCode[1] = {0x00}; -uint8_t dataLength[1] = {0x00}; -uint8_t data[16] = {0}; - -uint8_t message[30]; - - - -bool solaxX1_RS485ReceiveReady(void) -{ - return (solaxX1Serial->available() > 1); -} - -void solaxX1_RS485Send(uint16_t msgLen) -{ - memcpy(message, header, 2); - memcpy(message + 2, source, 2); - memcpy(message + 4, destination, 2); - memcpy(message + 6, controlCode, 1); - memcpy(message + 7, functionCode, 1); - memcpy(message + 8, dataLength, 1); - memcpy(message + 9, data, sizeof(data)); - uint16_t crc = solaxX1_calculateCRC(message, msgLen); - - while (solaxX1Serial->available() > 0) - { - solaxX1Serial->read(); - } - - solaxX1Serial->flush(); - solaxX1Serial->write(message, msgLen); - solaxX1Serial->write(highByte(crc)); - solaxX1Serial->write(lowByte(crc)); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen); -} - -uint8_t solaxX1_RS485Receive(uint8_t *value) -{ - uint8_t len = 0; - - while (solaxX1Serial->available() > 0) - { - value[len++] = (uint8_t)solaxX1Serial->read(); - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, value, len); - - uint16_t crc = solaxX1_calculateCRC(value, len - 2); - - if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) - { - return solaxX1_ERR_NO_ERROR; - } - else - { - return solaxX1_ERR_CRC_ERROR; - } -} - -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) -{ - uint8_t i; - uint16_t wChkSum; - wChkSum = 0; - - for (i = 0; i < bLen; i++) - { - wChkSum = wChkSum + bExternTxPackage[i]; - } - return wChkSum; -} - -void solaxX1_SendInverterAddress(void) -{ - source[0] = 0x00; - destination[0] = 0x00; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x01; - dataLength[0] = 0x0F; - data[14] = INVERTER_ADDRESS; - solaxX1_RS485Send(24); -} - -void solaxX1_QueryLiveData(void) -{ - source[0] = 0x01; - destination[0] = 0x00; - destination[1] = INVERTER_ADDRESS; - controlCode[0] = 0x11; - functionCode[0] = 0x02; - dataLength[0] = 0x00; - solaxX1_RS485Send(9); -} - -uint8_t solaxX1_ParseErrorCode(uint32_t code){ - ErrCode.ErrMessage = code; - - if (code == 0) return 0; - if (ErrCode.MainsLostFault) return 1; - if (ErrCode.GridVoltFault) return 2; - if (ErrCode.GridFreqFault) return 3; - if (ErrCode.PvVoltFault) return 4; - if (ErrCode.IsolationFault) return 5; - if (ErrCode.TemperatureOverFault) return 6; - if (ErrCode.FanFault) return 7; - if (ErrCode.OtherDeviceFault) return 8; -} - - - -uint8_t solaxX1_send_retry = 0; -uint8_t solaxX1_nodata_count = 0; - -void solaxX1250MSecond(void) -{ - uint8_t value[61] = {0}; - bool data_ready = solaxX1_RS485ReceiveReady(); - - if (protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - if (data_ready) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); - } - else - { - solaxX1_nodata_count = 0; - solaxX1_send_retry = 12; - Energy.data_valid[0] = 0; - - solaxX1.temperature = (float)((value[9] << 8) | value[10]); - solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; - solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; - solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; - solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; - solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; - Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; - Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; - Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; - Energy.active_power[0] = (float)((value[27] << 8) | value[28]); - - solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; - solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); - solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); - - - - - - - - solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); - - solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; - solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; - - solaxX1_QueryLiveData(); - EnergyUpdateTotal(solaxX1.energy_total, true); - } - } - - if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { - solaxX1_send_retry = 12; - solaxX1_QueryLiveData(); - } - - - - if (255 == solaxX1_nodata_count) { - solaxX1_nodata_count = 0; - solaxX1_send_retry = 12; - } - } - else - { - if ((solaxX1_nodata_count % 4) == 0) { DEBUG_SENSOR_LOG(PSTR("SX1: No Data count: %d"), solaxX1_nodata_count); } - if (solaxX1_nodata_count < 10 * 4) - { - solaxX1_nodata_count++; - } - else if (255 != solaxX1_nodata_count) - { - - solaxX1_nodata_count = 255; - solaxX1_send_retry = 12; - protocolStatus.status = 0b00001000; - Energy.data_valid[0] = ENERGY_WATCHDOG; - - solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0; - solaxX1.dc2_power = solaxX1.status = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; - - } - } - - if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - if (data_ready) - { - - if (protocolStatus.inverterAddressSend) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error")); - } - else - { - if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Set hasAddress")); - protocolStatus.status = 0b00100000; - } - } - } - - - if (protocolStatus.queryOfflineSend) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error")); - } - else - { - - if (value[6] == 0x10 && value[7] == 0x80 && protocolStatus.inverterSnReceived == false) - { - for (uint8_t i = 9; i <= 22; i++) - { - data[i - 9] = value[i]; - } - solaxX1_SendInverterAddress(); - protocolStatus.status = 0b1100000; - DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); - } - } - } - } - - if (solaxX1_send_retry == 0) - { - if (protocolStatus.queryOfflineSend) - { - protocolStatus.status = 0b00001000; - DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); - } - solaxX1_send_retry = 12; - } - - - if (protocolStatus.queryOffline) - { - - source[0] = 0x01; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x00; - dataLength[0] = 0x00; - solaxX1_RS485Send(9); - protocolStatus.status = 0b00010000; - DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); - } - } - - if (!data_ready) - solaxX1_send_retry--; -} - -void solaxX1SnsInit(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SX1: Solax X1 Inverter Init")); - DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); - protocolStatus.status = 0b00100000; - - solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); - if (solaxX1Serial->begin(SOLAXX1_SPEED)) { - if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void solaxX1DrvInit(void) -{ - if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) { - energy_flg = XNRG_12; - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; -#ifdef SOLAXX1_PV2 -const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; -#endif -const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}" - "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" - "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"; -#endif - -void solaxX1Show(bool json) -{ - char solar_power[33]; - dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings.flag2.wattage_resolution, solar_power); - char pv1_voltage[33]; - dtostrfd(solaxX1.dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); - char pv1_current[33]; - dtostrfd(solaxX1.dc1_current, Settings.flag2.current_resolution, pv1_current); - char pv1_power[33]; - dtostrfd(solaxX1.dc1_power, Settings.flag2.wattage_resolution, pv1_power); -#ifdef SOLAXX1_PV2 - char pv2_voltage[33]; - dtostrfd(solaxX1.dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); - char pv2_current[33]; - dtostrfd(solaxX1.dc2_current, Settings.flag2.current_resolution, pv2_current); - char pv2_power[33]; - dtostrfd(solaxX1.dc2_power, Settings.flag2.wattage_resolution, pv2_power); -#endif - char temperature[33]; - dtostrfd(solaxX1.temperature, Settings.flag2.temperature_resolution, temperature); - char runtime[33]; - dtostrfd(solaxX1.runtime_total, 0, runtime); - char status[33]; - GetTextIndexed(status, sizeof(status), solaxX1.status, kSolaxMode); - - if (json) - { - ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), - solar_power, pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), - pv2_voltage, pv2_current, pv2_power); -#endif - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), - temperature, runtime, status, solaxX1.errorCode); - -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, solar_power, pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); -#endif - WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); - char errorCodeString[33]; - WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, - GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); -#endif - } -} - - - - - -bool Xnrg12(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { solaxX1250MSecond(); } - break; - case FUNC_JSON_APPEND: - solaxX1Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - solaxX1Show(0); - break; -#endif - case FUNC_INIT: - solaxX1SnsInit(); - break; - case FUNC_PRE_INIT: - solaxX1DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_LE01MR -# 71 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -#define XNRG_13 13 - - -#ifndef LE01MR_SPEED - #define LE01MR_SPEED 2400 -#endif - -#ifndef LE01MR_ADDR - #define LE01MR_ADDR 1 -#endif - -#include -TasmotaModbus *FifLEModbus; - -const uint8_t le01mr_table_sz = 9; - -const uint16_t le01mr_register_addresses[] { - - 0x0130, - 0x0131, - 0x0158, - 0x0139, - 0x0140, - 0x0148, - 0x0150, - 0xA000, - 0xA01E -}; - -struct LE01MR { - float total_active = 0; - float total_reactive = 0; - uint8_t read_state = 0; - uint8_t send_retry = 0; - uint8_t start_address_count = le01mr_table_sz; -} Le01mr; - - - -void FifLEEvery250ms(void) -{ - bool data_ready = FifLEModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - uint8_t reg_count = 2; - if (Le01mr.read_state < 3) { - reg_count=1; - } - - uint32_t error = FifLEModbus->ReceiveBuffer(buffer, reg_count); - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, FifLEModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); - } else { - Energy.data_valid[0] = 0; -# 146 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" - uint32_t value_buff = 0; - - if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { - value_buff = ((uint32_t)buffer[3])<<8 | buffer[4]; - } else { - value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; - } - - switch(Le01mr.read_state) { - case 0: - Energy.frequency[0] = value_buff * 0.01f; - break; - - case 1: - Energy.voltage[0] = value_buff * 0.01f; - break; - - case 2: - Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; - break; - - case 3: - Energy.current[0] = value_buff * 0.001f; - break; - - case 4: - Energy.active_power[0] = value_buff * 1.0f; - break; - - case 5: - Energy.reactive_power[0] = value_buff * 1.0f; - break; - - case 6: - Energy.apparent_power[0] = value_buff * 1.0f; - break; - - case 7: - Le01mr.total_active = value_buff * 0.01f; - break; - - case 8: - Le01mr.total_reactive = value_buff * 0.01f; - break; - } - - Le01mr.read_state++; - if (Le01mr.read_state == Le01mr.start_address_count) { - Le01mr.read_state = 0; - - EnergyUpdateTotal(Le01mr.total_active, true); - } - } - } - - if (0 == Le01mr.send_retry || data_ready) { - uint8_t reg_count = 2; - - Le01mr.send_retry = 5; - - if (Le01mr.read_state < 3) reg_count=1; - - FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); - } else { - Le01mr.send_retry--; - } -} - -void FifLESnsInit(void) -{ - FifLEModbus = new TasmotaModbus(pin[GPIO_LE01MR_RX], pin[GPIO_LE01MR_TX]); - uint8_t result = FifLEModbus->Begin(LE01MR_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void FifLEDrvInit(void) -{ - if ((pin[GPIO_LE01MR_RX] < 99) && (pin[GPIO_LE01MR_TX] < 99)) { - energy_flg = XNRG_13; - } -} - -void FifLEReset(void) -{ - Le01mr.total_active = 0; - Le01mr.total_reactive = 0; -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_LE01MR[] PROGMEM = - "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - ; -#endif - -void FifLEShow(bool json) -{ - char total_reactive_chr[FLOATSZ]; - dtostrfd(Le01mr.total_reactive, Settings.flag2.energy_resolution, total_reactive_chr); - char total_active_chr[FLOATSZ]; - dtostrfd(Le01mr.total_active, Settings.flag2.energy_resolution, total_active_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"), - total_active_chr, total_reactive_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_ENERGY_LE01MR, total_active_chr, total_reactive_chr); -#endif - } -} - - - - - -bool Xnrg13(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { - FifLEEvery250ms(); - } - break; - case FUNC_JSON_APPEND: - FifLEShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - FifLEShow(0); - break; -#endif - case FUNC_ENERGY_RESET: - FifLEReset(); - break; - case FUNC_INIT: - FifLESnsInit(); - break; - case FUNC_PRE_INIT: - FifLEDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_interface.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xnrg_interface.ino" -#ifdef USE_ENERGY_SENSOR - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xnrg_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xnrg_func_ptr[])(uint8_t) = { -#endif - -#ifdef XNRG_01 - &Xnrg01, -#endif - -#ifdef XNRG_02 - &Xnrg02, -#endif - -#ifdef XNRG_03 - &Xnrg03, -#endif - -#ifdef XNRG_04 - &Xnrg04, -#endif - -#ifdef XNRG_05 - &Xnrg05, -#endif - -#ifdef XNRG_06 - &Xnrg06, -#endif - -#ifdef XNRG_07 - &Xnrg07, -#endif - -#ifdef XNRG_08 - &Xnrg08, -#endif - -#ifdef XNRG_09 - &Xnrg09, -#endif - -#ifdef XNRG_10 - &Xnrg10, -#endif - -#ifdef XNRG_11 - &Xnrg11, -#endif - -#ifdef XNRG_12 - &Xnrg12, -#endif - -#ifdef XNRG_13 - &Xnrg13, -#endif - -#ifdef XNRG_14 - &Xnrg14, -#endif - -#ifdef XNRG_15 - &Xnrg15, -#endif - -#ifdef XNRG_16 - &Xnrg16 -#endif -}; - -const uint8_t xnrg_present = sizeof(xnrg_func_ptr) / sizeof(xnrg_func_ptr[0]); - -uint8_t xnrg_active = 0; - -bool XnrgCall(uint8_t function) -{ - DEBUG_TRACE_LOG(PSTR("NRG: %d"), function); - - if (FUNC_PRE_INIT == function) { - for (uint32_t x = 0; x < xnrg_present; x++) { - xnrg_func_ptr[x](function); - if (energy_flg) { - xnrg_active = x; - return true; - } - } - } - else if (energy_flg) { - return xnrg_func_ptr[xnrg_active](function); - } - return false; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_01_counter.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_01_counter.ino" -#ifdef USE_COUNTER - - - - -#define XSNS_01 1 - -#define D_PRFX_COUNTER "Counter" -#define D_CMND_COUNTERTYPE "Type" -#define D_CMND_COUNTERDEBOUNCE "Debounce" - -const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" - "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE ; - -void (* const CounterCommand[])(void) PROGMEM = { - &CmndCounter, &CmndCounterType, &CmndCounterDebounce }; - -struct COUNTER { - uint32_t timer[MAX_COUNTERS]; - uint8_t no_pullup = 0; - bool any_counter = false; -} Counter; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void CounterUpdate(uint8_t index) ICACHE_RAM_ATTR; -void CounterUpdate1(void) ICACHE_RAM_ATTR; -void CounterUpdate2(void) ICACHE_RAM_ATTR; -void CounterUpdate3(void) ICACHE_RAM_ATTR; -void CounterUpdate4(void) ICACHE_RAM_ATTR; -#endif - -void CounterUpdate(uint8_t index) -{ - uint32_t time = micros(); - uint32_t debounce_time = time - Counter.timer[index]; - if (debounce_time > Settings.pulse_counter_debounce * 1000) { - Counter.timer[index] = time; - if (bitRead(Settings.pulse_counter_type, index)) { - RtcSettings.pulse_counter[index] = debounce_time; - } else { - RtcSettings.pulse_counter[index]++; - } - } -} - -void CounterUpdate1(void) -{ - CounterUpdate(0); -} - -void CounterUpdate2(void) -{ - CounterUpdate(1); -} - -void CounterUpdate3(void) -{ - CounterUpdate(2); -} - -void CounterUpdate4(void) -{ - CounterUpdate(3); -} - - - -bool CounterPinState(void) -{ - if ((XdrvMailbox.index >= GPIO_CNTR1_NP) && (XdrvMailbox.index < (GPIO_CNTR1_NP + MAX_COUNTERS))) { - bitSet(Counter.no_pullup, XdrvMailbox.index - GPIO_CNTR1_NP); - XdrvMailbox.index -= (GPIO_CNTR1_NP - GPIO_CNTR1); - return true; - } - return false; -} - -void CounterInit(void) -{ - typedef void (*function) () ; - function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; - - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - Counter.any_counter = true; - pinMode(pin[GPIO_CNTR1 +i], bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP); - attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); - } - } -} - -void CounterEverySecond(void) -{ - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - if (bitRead(Settings.pulse_counter_type, i)) { - uint32_t time = micros() - Counter.timer[i]; - if (time > 4200000000) { - RtcSettings.pulse_counter[i] = 4200000000; - } - } - } - } -} - -void CounterSaveState(void) -{ - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; - } - } -} - -void CounterShow(bool json) -{ - bool header = false; - uint8_t dsxflg = 0; - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - char counter[33]; - if (bitRead(Settings.pulse_counter_type, i)) { - dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); - } else { - dsxflg++; - snprintf_P(counter, sizeof(counter), PSTR("%lu"), RtcSettings.pulse_counter[i]); - } - - if (json) { - if (!header) { - ResponseAppend_P(PSTR(",\"COUNTER\":{")); - } - ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); - header = true; -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (1 == dsxflg)) { - DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); - dsxflg++; - } -#endif - if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { - RtcSettings.pulse_counter[i] = 0; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(PSTR("{s}" D_COUNTER "%d{m}%s%s{e}"), - i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); -#endif - } - } - } - if (header) { - ResponseJsonEnd(); - } -} - - - - - -void CmndCounter(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { - if ((XdrvMailbox.data_len > 0) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { - if ((XdrvMailbox.data[0] == '-') || (XdrvMailbox.data[0] == '+')) { - RtcSettings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; - Settings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; - } else { - RtcSettings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; - Settings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - } - ResponseCmndIdxNumber(RtcSettings.pulse_counter[XdrvMailbox.index -1]); - } -} - -void CmndCounterType(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { - bitWrite(Settings.pulse_counter_type, XdrvMailbox.index -1, XdrvMailbox.payload &1); - RtcSettings.pulse_counter[XdrvMailbox.index -1] = 0; - Settings.pulse_counter[XdrvMailbox.index -1] = 0; - } - ResponseCmndIdxNumber(bitRead(Settings.pulse_counter_type, XdrvMailbox.index -1)); - } -} - -void CmndCounterDebounce(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { - Settings.pulse_counter_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.pulse_counter_debounce); -} - - - - - -bool Xsns01(uint8_t function) -{ - bool result = false; - - if (Counter.any_counter) { - switch (function) { - case FUNC_EVERY_SECOND: - CounterEverySecond(); - break; - case FUNC_JSON_APPEND: - CounterShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - CounterShow(0); - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - case FUNC_SAVE_AT_MIDNIGHT: - CounterSaveState(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kCounterCommands, CounterCommand); - break; - } - } else { - switch (function) { - case FUNC_INIT: - CounterInit(); - break; - case FUNC_PIN_STATE: - result = CounterPinState(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_02_analog.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_02_analog.ino" -#ifndef USE_ADC_VCC - - - - -#define XSNS_02 2 - -#define TO_CELSIUS(x) ((x) - 273.15) -#define TO_KELVIN(x) ((x) + 273.15) - - -#define ANALOG_V33 3.3 -#define ANALOG_T0 TO_KELVIN(25.0) - - - - - -#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 -#define ANALOG_NTC_RESISTANCE 10000 -#define ANALOG_NTC_B_COEFFICIENT 3350 - - - - - -#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 -#define ANALOG_LDR_LUX_CALC_SCALAR 12518931 -#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 -# 58 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_02_analog.ino" -#define ANALOG_CT_FLAGS 0 -#define ANALOG_CT_MULTIPLIER 2146 -#define ANALOG_CT_VOLTAGE 2300 - -#define CT_FLAG_ENERGY_RESET (1 << 0) - -struct { - float temperature = 0; - float current = 0; - float energy = 0; - uint32_t previous_millis = 0; - uint16_t last_value = 0; -} Adc; - -void AdcInit(void) -{ - if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000)) { - if (ADC0_TEMP == my_adc0) { - - Settings.adc_param_type = ADC0_TEMP; - Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE; - Settings.adc_param2 = ANALOG_NTC_RESISTANCE; - Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000; - } - else if (ADC0_LIGHT == my_adc0) { - Settings.adc_param_type = ADC0_LIGHT; - Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE; - Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; - Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; - } - else if (ADC0_RANGE == my_adc0) { - Settings.adc_param_type = ADC0_RANGE; - Settings.adc_param1 = 0; - Settings.adc_param2 = 1023; - Settings.adc_param3 = 0; - Settings.adc_param4 = 100; - } - else if (ADC0_CT_POWER == my_adc0) { - Settings.adc_param_type = ADC0_CT_POWER; - Settings.adc_param1 = ANALOG_CT_FLAGS; - Settings.adc_param2 = ANALOG_CT_MULTIPLIER; - Settings.adc_param3 = ANALOG_CT_VOLTAGE; - } - } -} - -uint16_t AdcRead(uint8_t factor) -{ - - - - - - uint8_t samples = 1 << factor; - uint16_t analog = 0; - for (uint32_t i = 0; i < samples; i++) { - analog += analogRead(A0); - delay(1); - } - analog >>= factor; - return analog; -} - -#ifdef USE_RULES -void AdcEvery250ms(void) -{ - if (ADC0_INPUT == my_adc0) { - uint16_t new_value = AdcRead(5); - if ((new_value < Adc.last_value -10) || (new_value > Adc.last_value +10)) { - Adc.last_value = new_value; - uint16_t value = Adc.last_value / 10; - Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); - XdrvRulesProcess(); - } - } -} -#endif - -uint16_t AdcGetLux(void) -{ - int adc = AdcRead(2); - - double resistorVoltage = ((double)adc / 1023) * ANALOG_V33; - double ldrVoltage = ANALOG_V33 - resistorVoltage; - double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1; - double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000); - - return (uint16_t)ldrLux; -} - -uint16_t AdcGetRange(void) -{ - - - - int adc = AdcRead(2); - double adcrange = ( ((double)Settings.adc_param2 - (double)adc) / ( ((double)Settings.adc_param2 - (double)Settings.adc_param1)) * ((double)Settings.adc_param3 - (double)Settings.adc_param4) + (double)Settings.adc_param4 ); - return (uint16_t)adcrange; -} - -void AdcGetCurrentPower(uint8_t factor) -{ - - - - - - uint8_t samples = 1 << factor; - uint16_t analog = 0; - uint16_t analog_min = 1023; - uint16_t analog_max = 0; - for (uint32_t i = 0; i < samples; i++) { - analog = analogRead(A0); - if (analog < analog_min) { - analog_min = analog; - } - if (analog > analog_max) { - analog_max = analog; - } - delay(1); - } - - Adc.current = (float)(analog_max-analog_min) * ((float)(Settings.adc_param2) / 100000); - float power = Adc.current * (float)(Settings.adc_param3) / 10; - uint32_t current_millis = millis(); - Adc.energy = Adc.energy + ((power * (current_millis - Adc.previous_millis)) / 3600000000); - Adc.previous_millis = current_millis; -} - -void AdcEverySecond(void) -{ - if (ADC0_TEMP == my_adc0) { - int adc = AdcRead(2); - - double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc); - double BC = (double)Settings.adc_param3 / 10000; - double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2)); - Adc.temperature = ConvertTemp(TO_CELSIUS(T)); - } - else if (ADC0_CT_POWER == my_adc0) { - AdcGetCurrentPower(5); - } -} - -void AdcShow(bool json) -{ - if (ADC0_INPUT == my_adc0) { - uint16_t analog = AdcRead(5); - - if (json) { - ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); -#endif - } - } - - else if (ADC0_TEMP == my_adc0) { - char temperature[33]; - dtostrfd(Adc.temperature, Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMP, "ANALOG", temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, Adc.temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); -#endif - } - } - - else if (ADC0_LIGHT == my_adc0) { - uint16_t adc_light = AdcGetLux(); - - if (json) { - ResponseAppend_P(JSON_SNS_ILLUMINANCE, "ANALOG", adc_light); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, adc_light); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light); -#endif - } - } - - else if (ADC0_RANGE == my_adc0) { - uint16_t adc_range = AdcGetRange(); - - if (json) { - ResponseAppend_P(JSON_SNS_RANGE, "ANALOG", adc_range); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_RANGE, "", adc_range); -#endif - } - } - - else if (ADC0_CT_POWER == my_adc0) { - AdcGetCurrentPower(5); - - float voltage = (float)(Settings.adc_param3) / 10; - char voltage_chr[FLOATSZ]; - dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr); - char current_chr[FLOATSZ]; - dtostrfd(Adc.current, Settings.flag2.current_resolution, current_chr); - char power_chr[FLOATSZ]; - dtostrfd(voltage * Adc.current, Settings.flag2.wattage_resolution, power_chr); - char energy_chr[FLOATSZ]; - dtostrfd(Adc.energy, Settings.flag2.energy_resolution, energy_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"ANALOG\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), - energy_chr, power_chr, voltage_chr, current_chr); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_POWER_ENERGY, power_chr); - DomoticzSensor(DZ_VOLTAGE, voltage_chr); - DomoticzSensor(DZ_CURRENT, current_chr); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr); - WSContentSend_PD(HTTP_SNS_CURRENT, current_chr); - WSContentSend_PD(HTTP_SNS_POWER, power_chr); - WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr); -#endif - } - } - -} - - - - - -const char kAdcCommands[] PROGMEM = "|" - D_CMND_ADC "|" D_CMND_ADCS "|" D_CMND_ADCPARAM; - -void (* const AdcCommand[])(void) PROGMEM = { - &CmndAdc, &CmndAdcs, &CmndAdcParam }; - -void CmndAdc(void) -{ - if (ValidAdc() && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < ADC0_END)) { - Settings.my_adc0 = XdrvMailbox.payload; - restart_flag = 2; - } - char stemp1[TOPSZ]; - Response_P(PSTR("{\"" D_CMND_ADC "0\":{\"%d\":\"%s\"}}"), Settings.my_adc0, GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_adc0, kAdc0Names)); -} - -void CmndAdcs(void) -{ - Response_P(PSTR("{\"" D_CMND_ADCS "\":{")); - bool jsflg = false; - char stemp1[TOPSZ]; - for (uint32_t i = 0; i < ADC0_END; i++) { - if (jsflg) { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - ResponseAppend_P(PSTR("\"%d\":\"%s\""), i, GetTextIndexed(stemp1, sizeof(stemp1), i, kAdc0Names)); - } - ResponseJsonEndEnd(); -} - -void CmndAdcParam(void) -{ - if (XdrvMailbox.data_len) { - if ((ADC0_TEMP == XdrvMailbox.payload) || - (ADC0_LIGHT == XdrvMailbox.payload) || - (ADC0_RANGE == XdrvMailbox.payload) || - (ADC0_CT_POWER == XdrvMailbox.payload)) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len +1]; - - - - Settings.adc_param_type = XdrvMailbox.payload; - Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); - if (ADC0_RANGE == XdrvMailbox.payload) { - Settings.adc_param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10)); - Settings.adc_param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10)); - } else { - Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); - } - if (ADC0_CT_POWER == XdrvMailbox.payload) { - if ((Settings.adc_param1 & CT_FLAG_ENERGY_RESET) > 0) { - Adc.energy = 0; - Settings.adc_param1 ^= CT_FLAG_ENERGY_RESET; - } - } - } else { - - - - - Settings.adc_param_type = 0; - AdcInit(); - } - } - } - - - Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2); - if (ADC0_RANGE == my_adc0) { - ResponseAppend_P(PSTR(",%d,%d"), Settings.adc_param3, Settings.adc_param4); - } else { - int value = Settings.adc_param3; - uint8_t precision; - for (precision = 4; precision > 0; precision--) { - if (value % 10) { break; } - value /= 10; - } - char param3[33]; - dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); - ResponseAppend_P(PSTR(",%s"), param3); - } - ResponseAppend_P(PSTR("]}")); -} - - - - - -bool Xsns02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_COMMAND: - result = DecodeCommand(kAdcCommands, AdcCommand); - break; - default: - if ((ADC0_INPUT == my_adc0) || - (ADC0_TEMP == my_adc0) || - (ADC0_LIGHT == my_adc0) || - (ADC0_RANGE == my_adc0) || - (ADC0_CT_POWER == my_adc0)) { - switch (function) { -#ifdef USE_RULES - case FUNC_EVERY_250_MSECOND: - AdcEvery250ms(); - break; -#endif - case FUNC_EVERY_SECOND: - AdcEverySecond(); - break; - case FUNC_INIT: - AdcInit(); - break; - case FUNC_JSON_APPEND: - AdcShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AdcShow(0); - break; -#endif - } - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_04_snfsc.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_04_snfsc.ino" -#ifdef USE_SONOFF_SC -# 57 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_04_snfsc.ino" -#define XSNS_04 4 - -uint16_t sc_value[5] = { 0 }; - -void SonoffScSend(const char *data) -{ - Serial.write(data); - Serial.write('\x1B'); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data); -} - -void SonoffScInit(void) -{ - - SonoffScSend("AT+START"); - -} - -void SonoffScSerialInput(char *rcvstat) -{ - char *p; - char *str; - uint16_t value[5] = { 0 }; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat); - - if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { - int8_t i = -1; - for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(nullptr, ":", &p)) { - value[i++] = atoi(str); - } - if (value[0] > 0) { - for (uint32_t i = 0; i < 5; i++) { - sc_value[i] = value[i]; - } - sc_value[2] = (11 - sc_value[2]) * 10; - sc_value[3] *= 10; - sc_value[4] = (11 - sc_value[4]) * 10; - SonoffScSend("AT+SEND=ok"); - } else { - SonoffScSend("AT+SEND=fail"); - } - } - else if (!strcasecmp_P(rcvstat, PSTR("AT+STATUS?"))) { - SonoffScSend("AT+STATUS=4"); - } -} - - - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SCPLUS[] PROGMEM = - "{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; -#endif - -void SonoffScShow(bool json) -{ - if (sc_value[0] > 0) { - float t = ConvertTemp(sc_value[1]); - float h = ConvertHumidity(sc_value[0]); - - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), - temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); - DomoticzSensor(DZ_COUNT, sc_value[3]); - DomoticzSensor(DZ_AIRQUALITY, 500 + ((100 - sc_value[4]) * 20)); - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, "", humidity); - WSContentSend_PD(HTTP_SNS_SCPLUS, sc_value[2], sc_value[3], sc_value[4]); -#endif - } - } -} - - - - - -bool Xsns04(uint8_t function) -{ - bool result = false; - - if (SONOFF_SC == my_module_type) { - switch (function) { - case FUNC_JSON_APPEND: - SonoffScShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SonoffScShow(0); - break; -#endif - case FUNC_INIT: - SonoffScInit(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_05_ds18x20.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_05_ds18x20.ino" -#ifdef USE_DS18x20 - - - - -#define XSNS_05 5 - - - -#define DS18S20_CHIPID 0x10 -#define DS1822_CHIPID 0x22 -#define DS18B20_CHIPID 0x28 -#define MAX31850_CHIPID 0x3B - -#define W1_SKIP_ROM 0xCC -#define W1_CONVERT_TEMP 0x44 -#define W1_WRITE_EEPROM 0x48 -#define W1_WRITE_SCRATCHPAD 0x4E -#define W1_READ_SCRATCHPAD 0xBE - -#define DS18X20_MAX_SENSORS 8 - -const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; - -uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; - -struct DS18X20STRUCT { - uint8_t address[8]; - uint8_t index; - uint8_t valid; - float temperature; -} ds18x20_sensor[DS18X20_MAX_SENSORS]; -uint8_t ds18x20_sensors = 0; -uint8_t ds18x20_pin = 0; -uint8_t ds18x20_pin_out = 0; -bool ds18x20_dual_mode = false; -char ds18x20_types[12]; -#ifdef W1_PARASITE_POWER -uint8_t ds18x20_sensor_curr = 0; -unsigned long w1_power_until = 0; -#endif - - - - - -#define W1_MATCH_ROM 0x55 -#define W1_SEARCH_ROM 0xF0 - -uint8_t onewire_last_discrepancy = 0; -uint8_t onewire_last_family_discrepancy = 0; -bool onewire_last_device_flag = false; -unsigned char onewire_rom_id[8] = { 0 }; - - - -uint8_t OneWireReset(void) -{ - uint8_t retries = 125; - - if (!ds18x20_dual_mode) { - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - do { - if (--retries == 0) { - return 0; - } - delayMicroseconds(2); - } while (!digitalRead(ds18x20_pin)); - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(480); - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - } else { - digitalWrite(ds18x20_pin_out, HIGH); - do { - if (--retries == 0) { - return 0; - } - delayMicroseconds(2); - } while (!digitalRead(ds18x20_pin)); - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(480); - digitalWrite(ds18x20_pin_out, HIGH); - } - delayMicroseconds(70); - uint8_t r = !digitalRead(ds18x20_pin); - delayMicroseconds(410); - return r; -} - -void OneWireWriteBit(uint8_t v) -{ - static const uint8_t delay_low[2] = { 65, 10 }; - static const uint8_t delay_high[2] = { 5, 55 }; - - v &= 1; - if (!ds18x20_dual_mode) { - digitalWrite(ds18x20_pin, LOW); - pinMode(ds18x20_pin, OUTPUT); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin, HIGH); - } else { - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin_out, HIGH); - } - delayMicroseconds(delay_high[v]); -} - -uint8_t OneWireReadBit(void) -{ - if (!ds18x20_dual_mode) { - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(3); - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - } else { - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(3); - digitalWrite(ds18x20_pin_out, HIGH); - } - delayMicroseconds(10); - uint8_t r = digitalRead(ds18x20_pin); - delayMicroseconds(53); - return r; -} - - - -void OneWireWrite(uint8_t v) -{ - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - OneWireWriteBit((bit_mask & v) ? 1 : 0); - } -} - -uint8_t OneWireRead(void) -{ - uint8_t r = 0; - - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - if (OneWireReadBit()) { - r |= bit_mask; - } - } - return r; -} - -void OneWireSelect(const uint8_t rom[8]) -{ - OneWireWrite(W1_MATCH_ROM); - for (uint32_t i = 0; i < 8; i++) { - OneWireWrite(rom[i]); - } -} - -void OneWireResetSearch(void) -{ - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - for (uint32_t i = 0; i < 8; i++) { - onewire_rom_id[i] = 0; - } -} - -uint8_t OneWireSearch(uint8_t *newAddr) -{ - uint8_t id_bit_number = 1; - uint8_t last_zero = 0; - uint8_t rom_byte_number = 0; - uint8_t search_result = 0; - uint8_t id_bit; - uint8_t cmp_id_bit; - unsigned char rom_byte_mask = 1; - unsigned char search_direction; - - if (!onewire_last_device_flag) { - if (!OneWireReset()) { - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - return false; - } - OneWireWrite(W1_SEARCH_ROM); - do { - id_bit = OneWireReadBit(); - cmp_id_bit = OneWireReadBit(); - - if ((id_bit == 1) && (cmp_id_bit == 1)) { - break; - } else { - if (id_bit != cmp_id_bit) { - search_direction = id_bit; - } else { - if (id_bit_number < onewire_last_discrepancy) { - search_direction = ((onewire_rom_id[rom_byte_number] & rom_byte_mask) > 0); - } else { - search_direction = (id_bit_number == onewire_last_discrepancy); - } - if (search_direction == 0) { - last_zero = id_bit_number; - if (last_zero < 9) { - onewire_last_family_discrepancy = last_zero; - } - } - } - if (search_direction == 1) { - onewire_rom_id[rom_byte_number] |= rom_byte_mask; - } else { - onewire_rom_id[rom_byte_number] &= ~rom_byte_mask; - } - OneWireWriteBit(search_direction); - id_bit_number++; - rom_byte_mask <<= 1; - if (rom_byte_mask == 0) { - rom_byte_number++; - rom_byte_mask = 1; - } - } - } while (rom_byte_number < 8); - if (!(id_bit_number < 65)) { - onewire_last_discrepancy = last_zero; - if (onewire_last_discrepancy == 0) { - onewire_last_device_flag = true; - } - search_result = true; - } - } - if (!search_result || !onewire_rom_id[0]) { - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - search_result = false; - } - for (uint32_t i = 0; i < 8; i++) { - newAddr[i] = onewire_rom_id[i]; - } - return search_result; -} - -bool OneWireCrc8(uint8_t *addr) -{ - uint8_t crc = 0; - uint8_t len = 8; - - while (len--) { - uint8_t inbyte = *addr++; - for (uint32_t i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x01; - crc >>= 1; - if (mix) { - crc ^= 0x8C; - } - inbyte >>= 1; - } - } - return (crc == *addr); -} - - - -void Ds18x20Init(void) -{ - uint64_t ids[DS18X20_MAX_SENSORS]; - - ds18x20_pin = pin[GPIO_DSB]; - if (pin[GPIO_DSB_OUT] < 99) { - ds18x20_pin_out = pin[GPIO_DSB_OUT]; - ds18x20_dual_mode = true; - pinMode(ds18x20_pin_out, OUTPUT); - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - } - - OneWireResetSearch(); - - ds18x20_sensors = 0; - while (ds18x20_sensors < DS18X20_MAX_SENSORS) { - if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { - break; - } - if (OneWireCrc8(ds18x20_sensor[ds18x20_sensors].address) && - ((ds18x20_sensor[ds18x20_sensors].address[0] == DS18S20_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == DS1822_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == DS18B20_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == MAX31850_CHIPID))) { - ds18x20_sensor[ds18x20_sensors].index = ds18x20_sensors; - ids[ds18x20_sensors] = ds18x20_sensor[ds18x20_sensors].address[0]; - for (uint32_t j = 6; j > 0; j--) { - ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_sensor[ds18x20_sensors].address[j]; - } - ds18x20_sensors++; - } - } - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - for (uint32_t j = i + 1; j < ds18x20_sensors; j++) { - if (ids[ds18x20_sensor[i].index] > ids[ds18x20_sensor[j].index]) { - std::swap(ds18x20_sensor[i].index, ds18x20_sensor[j].index); - } - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); -} - -void Ds18x20Convert(void) -{ - OneWireReset(); -#ifdef W1_PARASITE_POWER - - if (++ds18x20_sensor_curr >= ds18x20_sensors) - ds18x20_sensor_curr = 0; - OneWireSelect(ds18x20_sensor[ds18x20_sensor_curr].address); -#else - OneWireWrite(W1_SKIP_ROM); -#endif - OneWireWrite(W1_CONVERT_TEMP); - -} - -bool Ds18x20Read(uint8_t sensor) -{ - uint8_t data[9]; - int8_t sign = 1; - - uint8_t index = ds18x20_sensor[sensor].index; - if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } - for (uint32_t retry = 0; retry < 3; retry++) { - OneWireReset(); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_READ_SCRATCHPAD); - for (uint32_t i = 0; i < 9; i++) { - data[i] = OneWireRead(); - } - if (OneWireCrc8(data)) { - switch(ds18x20_sensor[index].address[0]) { - case DS18S20_CHIPID: { - if (data[1] > 0x80) { - data[0] = (~data[0]) +1; - sign = -1; - } - float temp9 = (float)(data[0] >> 1) * sign; - ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - case DS1822_CHIPID: - case DS18B20_CHIPID: { - if (data[4] != 0x7F) { - data[4] = 0x7F; - OneWireReset(); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_WRITE_SCRATCHPAD); - OneWireWrite(data[2]); - OneWireWrite(data[3]); - OneWireWrite(data[4]); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_WRITE_EEPROM); -#ifdef W1_PARASITE_POWER - w1_power_until = millis() + 10; -#endif - } - uint16_t temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; - } - ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - case MAX31850_CHIPID: { - int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); - ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - } - } - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); - return false; -} - -void Ds18x20Name(uint8_t sensor) -{ - uint8_t index = sizeof(ds18x20_chipids); - while (index) { - if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) { - break; - } - index--; - } - GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); - if (ds18x20_sensors > 1) { - snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), sensor +1); - } -} - - - -void Ds18x20EverySecond(void) -{ -#ifdef W1_PARASITE_POWER - - unsigned long now = millis(); - if (now < w1_power_until) - return; -#endif - if (uptime & 1 -#ifdef W1_PARASITE_POWER - - || ds18x20_sensors >= 2 -#endif - ) { - - Ds18x20Convert(); - } else { - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - - if (!Ds18x20Read(i)) { - Ds18x20Name(i); - AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); -#ifdef USE_DS18x20_RECONFIGURE - if (!ds18x20_sensor[ds18x20_sensor[i].index].valid) { - memset(&ds18x20_sensor, 0, sizeof(ds18x20_sensor)); - Ds18x20Init(); - } -#endif - } - } - } -} - -void Ds18x20Show(bool json) -{ - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - uint8_t index = ds18x20_sensor[i].index; - - if (ds18x20_sensor[index].valid) { - char temperature[33]; - dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); - - Ds18x20Name(i); - - if (json) { - char address[17]; - for (uint32_t j = 0; j < 6; j++) { - sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); - } - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); -#endif - } - } - } -} - - - - - -bool Xsns05(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_DSB] < 99) { - switch (function) { - case FUNC_INIT: - Ds18x20Init(); - break; - case FUNC_EVERY_SECOND: - Ds18x20EverySecond(); - break; - case FUNC_JSON_APPEND: - Ds18x20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ds18x20Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_old.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_old.ino" -#ifdef USE_DHT_OLD -# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_old.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint32_t dht_max_cycles; -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -void DhtReadPrep(void) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - if (!dht_dual_mode) { - digitalWrite(Dht[i].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - } -} - -int32_t DhtExpectPulse(uint8_t sensor, bool level) -{ - int32_t count = 0; - - while (digitalRead(Dht[sensor].pin) == level) { - if (count++ >= (int32_t)dht_max_cycles) { - return -1; - } - } - return count; -} - -bool DhtRead(uint8_t sensor) -{ - int32_t cycles[80]; - uint8_t error = 0; - - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - - - - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { - Dht[sensor].lastresult = 0; - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delay(250); - } - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - if (GPIO_SI7021 == Dht[sensor].type) { - delayMicroseconds(500); - } else { - delay(20); - } - - noInterrupts(); - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - delayMicroseconds(40); - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - delayMicroseconds(40); - } - delayMicroseconds(10); - if (-1 == DhtExpectPulse(sensor, LOW)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - error = 1; - } - else if (-1 == DhtExpectPulse(sensor, HIGH)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - error = 1; - } - else { - for (uint32_t i = 0; i < 80; i += 2) { - cycles[i] = DhtExpectPulse(sensor, LOW); - cycles[i+1] = DhtExpectPulse(sensor, HIGH); - } - } - interrupts(); - - if (error) { return false; } - - for (uint32_t i = 0; i < 40; ++i) { - int32_t lowCycles = cycles[2*i]; - int32_t highCycles = cycles[2*i+1]; - if ((-1 == lowCycles) || (-1 == highCycles)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - return false; - } - dht_data[i/8] <<= 1; - if (highCycles > lowCycles) { - dht_data[i / 8] |= 1; - } - } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint8_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - dht_max_cycles = microsecondsToClockCycles(1000); - - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - - DhtReadPrep(); - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" -#ifdef USE_DHT_V2 -# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint32_t dht_max_cycles; -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -void DhtReadPrep(void) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - if (!dht_dual_mode) { - digitalWrite(Dht[i].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - } -} - -int32_t DhtExpectPulse(uint8_t sensor, bool level) -{ - int32_t count = 0; - - while (digitalRead(Dht[sensor].pin) == level) { - if (count++ >= (int32_t)dht_max_cycles) { - return -1; - } - } - return count; -} - -bool DhtRead(uint8_t sensor) -{ - int32_t cycles[80]; - uint8_t error = 0; - - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { - Dht[sensor].lastresult = 0; - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delay(250); - } - - - noInterrupts(); - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_SI7021: -# 114 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" - delayMicroseconds(500); - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delayMicroseconds(40); - break; - - case GPIO_DHT22: -# 133 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" - delayMicroseconds(1100); - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delayMicroseconds(30); - break; - - case GPIO_DHT11: -# 151 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v2.ino" - default: - - delay(20); - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delayMicroseconds(30); - break; - } - - - pinMode(Dht[sensor].pin, INPUT_PULLUP); - - if (-1 == DhtExpectPulse(sensor, LOW)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - error = 1; - } - else if (-1 == DhtExpectPulse(sensor, HIGH)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - error = 1; - } - else { - for (uint32_t i = 0; i < 80; i += 2) { - cycles[i] = DhtExpectPulse(sensor, LOW); - cycles[i+1] = DhtExpectPulse(sensor, HIGH); - } - } - interrupts(); - if (error) { return false; } - - - for (uint32_t i = 0; i < 40; ++i) { - int32_t lowCycles = cycles[2*i]; - int32_t highCycles = cycles[2*i+1]; - if ((-1 == lowCycles) || (-1 == highCycles)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - return false; - } - dht_data[i/8] <<= 1; - if (highCycles > lowCycles) { - dht_data[i / 8] |= 1; - } - } - - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint8_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - dht_max_cycles = microsecondsToClockCycles(1000); - - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v2) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - - DhtReadPrep(); - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v3.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v3.ino" -#ifdef USE_DHT_V3 -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v3.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -bool DhtExpectPulse(uint8_t sensor, int level) -{ - unsigned long timeout = micros() + 100; - while (digitalRead(Dht[sensor].pin) != level) { - if (micros() > timeout) { return false; } - delayMicroseconds(1); - } - return true; -} - -int DhtReadDat(uint8_t sensor) -{ - uint8_t result = 0; - for (uint32_t i = 0; i < 8; i++) { - if (!DhtExpectPulse(sensor, HIGH)) { return -1; } - - delayMicroseconds(35); - if (digitalRead(Dht[sensor].pin)) { - result |= (1 << (7 - i)); - } - - if (!DhtExpectPulse(sensor, LOW)) { return -1; } - } - return result; -} - -bool DhtRead(uint8_t sensor) -{ - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - delay(19); - break; - case GPIO_DHT22: - delay(2); - break; - case GPIO_SI7021: - delayMicroseconds(500); - break; - } - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - case GPIO_DHT22: - delayMicroseconds(50); - break; - case GPIO_SI7021: - - delayMicroseconds(20); - break; - } - - noInterrupts(); - if (!DhtExpectPulse(sensor, LOW)) { - interrupts(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - return false; - } - if (!DhtExpectPulse(sensor, HIGH)) { - interrupts(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - return false; - } - if (!DhtExpectPulse(sensor, LOW)) { - interrupts(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - return false; - } - - int data = 0; - for (uint32_t i = 0; i < 5; i++) { - data = DhtReadDat(sensor); - if (-1 == data) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - break; - } - dht_data[i] = data; - } - interrupts(); - if (-1 == data) { return false; } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint8_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v3) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - - - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v4.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v4.ino" -#ifdef USE_DHT_V4 -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v4.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -bool DhtExpectPulse(uint32_t sensor, uint32_t level) -{ - unsigned long timeout = micros() + 100; - while (digitalRead(Dht[sensor].pin) != level) { - if (micros() > timeout) { return false; } - delayMicroseconds(1); - } - return true; -} - -bool DhtRead(uint32_t sensor) -{ - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - delay(19); - break; - case GPIO_DHT22: - delay(2); - break; - case GPIO_SI7021: - delayMicroseconds(500); - break; - } - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - case GPIO_DHT22: - delayMicroseconds(50); - break; - case GPIO_SI7021: - delayMicroseconds(20); - break; - } - - uint32_t level = 9; - noInterrupts(); - for (uint32_t i = 0; i < 3; i++) { - level = i &1; - if (!DhtExpectPulse(sensor, level)) { break; } - level = 9; - } - if (9 == level) { - int data = 0; - for (uint32_t i = 0; i < 5; i++) { - data = 0; - for (uint32_t j = 0; j < 8; j++) { - level = 1; - if (!DhtExpectPulse(sensor, level)) { break; } - - delayMicroseconds(35); - if (digitalRead(Dht[sensor].pin)) { - data |= (1 << (7 - j)); - } - - level = 0; - if (!DhtExpectPulse(sensor, level)) { break; } - level = 9; - } - if (level < 2) { break; } - - dht_data[i] = data; - } - } - interrupts(); - if (level < 2) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), (0 == level) ? D_START_SIGNAL_LOW : D_START_SIGNAL_HIGH); - return false; - } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint32_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - if (Dht[sensor].h > 100) { Dht[sensor].h = 100.0; } - if (Dht[sensor].h < 0) { Dht[sensor].h = 0.0; } - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v4) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v5.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v5.ino" -#ifdef USE_DHT -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_06_dht_v5.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - uint8_t lastresult; - char stype[12]; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -bool DhtWaitState(uint32_t sensor, uint32_t level) -{ - unsigned long timeout = micros() + 100; - while (digitalRead(Dht[sensor].pin) != level) { - if (TimeReachedUsec(timeout)) { - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), - (level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW); - return false; - } - delayMicroseconds(1); - } - return true; -} - -bool DhtRead(uint32_t sensor) -{ - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - delay(19); - break; - case GPIO_DHT22: - delay(2); - break; - case GPIO_SI7021: - delayMicroseconds(500); - break; - } - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - case GPIO_DHT22: - delayMicroseconds(50); - break; - case GPIO_SI7021: - delayMicroseconds(20); - break; - } - - bool error = false; - noInterrupts(); - if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { - for (uint32_t i = 0; i < 5; i++) { - int data = 0; - for (uint32_t j = 0; j < 8; j++) { - if (!DhtWaitState(sensor, 1)) { - error = true; - break; - } - delayMicroseconds(35); - if (digitalRead(Dht[sensor].pin)) { - data |= (1 << (7 - j)); - } - if (!DhtWaitState(sensor, 0)) { - error = true; - break; - } - } - if (error) { break; } - dht_data[i] = data; - } - } else { - error = true; - } - interrupts(); - if (error) { return false; } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - float temperature = NAN; - float humidity = NAN; - switch (Dht[sensor].type) { - case GPIO_DHT11: - humidity = dht_data[0]; - temperature = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - humidity = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - temperature = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - temperature *= -1; - } - break; - } - if (isnan(temperature) || isnan(humidity)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid NAN reading")); - return false; - } - - if (humidity > 100) { humidity = 100.0; } - if (humidity < 0) { humidity = 0.1; } - Dht[sensor].h = ConvertHumidity(humidity); - Dht[sensor].t = ConvertTemp(temperature); - Dht[sensor].lastresult = 0; - - return true; -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastresult = DHT_MAX_RETRY; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v5) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { - - if (!DhtRead(sensor)) { - Dht[sensor].lastresult++; - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - } - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_07_sht1x.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_07_sht1x.ino" -#ifdef USE_I2C -#ifdef USE_SHT -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_07_sht1x.ino" -#define XSNS_07 7 -#define XI2C_08 8 - -enum { - SHT1X_CMD_MEASURE_TEMP = B00000011, - SHT1X_CMD_MEASURE_RH = B00000101, - SHT1X_CMD_SOFT_RESET = B00011110 -}; - -uint8_t sht_sda_pin; -uint8_t sht_scl_pin; -uint8_t sht_type = 0; -char sht_types[] = "SHT1X"; -uint8_t sht_valid = 0; -float sht_temperature = 0; -float sht_humidity = 0; - -bool ShtReset(void) -{ - pinMode(sht_sda_pin, INPUT_PULLUP); - pinMode(sht_scl_pin, OUTPUT); - delay(11); - for (uint32_t i = 0; i < 9; i++) { - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - } - bool success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); - delay(11); - return success; -} - -bool ShtSendCommand(const uint8_t cmd) -{ - pinMode(sht_sda_pin, OUTPUT); - - digitalWrite(sht_sda_pin, HIGH); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_sda_pin, LOW); - digitalWrite(sht_scl_pin, LOW); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_sda_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - - shiftOut(sht_sda_pin, sht_scl_pin, MSBFIRST, cmd); - - bool ackerror = false; - digitalWrite(sht_scl_pin, HIGH); - pinMode(sht_sda_pin, INPUT_PULLUP); - if (digitalRead(sht_sda_pin) != LOW) { - ackerror = true; - } - digitalWrite(sht_scl_pin, LOW); - delayMicroseconds(1); - if (digitalRead(sht_sda_pin) != HIGH) { - ackerror = true; - } - if (ackerror) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_DID_NOT_ACK_COMMAND)); - } - return (!ackerror); -} - -bool ShtAwaitResult(void) -{ - - for (uint32_t i = 0; i < 16; i++) { - if (LOW == digitalRead(sht_sda_pin)) { - return true; - } - delay(20); - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_BUSY)); - - return false; -} - -int ShtReadData(void) -{ - int val = 0; - - - val = shiftIn(sht_sda_pin, sht_scl_pin, 8); - val <<= 8; - - pinMode(sht_sda_pin, OUTPUT); - digitalWrite(sht_sda_pin, LOW); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - pinMode(sht_sda_pin, INPUT_PULLUP); - - val |= shiftIn(sht_sda_pin, sht_scl_pin, 8); - - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - return val; -} - -bool ShtRead(void) -{ - if (sht_valid) { sht_valid--; } - if (!ShtReset()) { return false; } - if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { return false; } - if (!ShtAwaitResult()) { return false; } - float tempRaw = ShtReadData(); - if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { return false; } - if (!ShtAwaitResult()) { return false; } - float humRaw = ShtReadData(); - - - const float d1 = -39.7; - const float d2 = 0.01; - sht_temperature = d1 + (tempRaw * d2); - const float c1 = -2.0468; - const float c2 = 0.0367; - const float c3 = -1.5955E-6; - const float t1 = 0.01; - const float t2 = 0.00008; - float rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; - sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear; - sht_temperature = ConvertTemp(sht_temperature); - ConvertHumidity(sht_humidity); - - sht_valid = SENSOR_MAX_MISS; - return true; -} - - - -void ShtDetect(void) -{ - sht_sda_pin = pin[GPIO_I2C_SDA]; - sht_scl_pin = pin[GPIO_I2C_SCL]; - if (ShtRead()) { - sht_type = 1; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); - } else { - Wire.begin(sht_sda_pin, sht_scl_pin); - sht_type = 0; - } -} - -void ShtEverySecond(void) -{ - if (!(uptime %4)) { - - if (!ShtRead()) { - AddLogMissed(sht_types, sht_valid); - } - } -} - -void ShtShow(bool json) -{ - if (sht_valid) { - char temperature[33]; - dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, sht_types, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, sht_temperature); - KnxSensor(KNX_HUMIDITY, sht_humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sht_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, sht_types, humidity); -#endif - } - } -} - - - - - -bool Xsns07(uint8_t function) -{ - if (!I2cEnabled(XI2C_08)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - ShtDetect(); - } - else if (sht_type) { - switch (function) { - case FUNC_EVERY_SECOND: - ShtEverySecond(); - break; - case FUNC_JSON_APPEND: - ShtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - ShtShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_08_htu21.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_08_htu21.ino" -#ifdef USE_I2C -#ifdef USE_HTU -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_08_htu21.ino" -#define XSNS_08 8 -#define XI2C_09 9 - -#define HTU21_ADDR 0x40 - -#define SI7013_CHIPID 0x0D -#define SI7020_CHIPID 0x14 -#define SI7021_CHIPID 0x15 -#define HTU21_CHIPID 0x32 - -#define HTU21_READTEMP 0xE3 -#define HTU21_READHUM 0xE5 -#define HTU21_WRITEREG 0xE6 -#define HTU21_READREG 0xE7 -#define HTU21_RESET 0xFE -#define HTU21_HEATER_WRITE 0x51 -#define HTU21_HEATER_READ 0x11 -#define HTU21_SERIAL2_READ1 0xFC -#define HTU21_SERIAL2_READ2 0xC9 - -#define HTU21_HEATER_ON 0x04 -#define HTU21_HEATER_OFF 0xFB - -#define HTU21_RES_RH12_T14 0x00 -#define HTU21_RES_RH8_T12 0x01 -#define HTU21_RES_RH10_T13 0x80 -#define HTU21_RES_RH11_T11 0x81 - -#define HTU21_CRC8_POLYNOM 0x13100 - -const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?"; - -uint8_t htu_address; -uint8_t htu_type = 0; -uint8_t htu_delay_temp; -uint8_t htu_delay_humidity = 50; -uint8_t htu_valid = 0; -float htu_temperature = 0; -float htu_humidity = 0; -char htu_types[7]; - -uint8_t HtuCheckCrc8(uint16_t data) -{ - for (uint32_t bit = 0; bit < 16; bit++) { - if (data & 0x8000) { - data = (data << 1) ^ HTU21_CRC8_POLYNOM; - } else { - data <<= 1; - } - } - return data >>= 8; -} - -uint8_t HtuReadDeviceId(void) -{ - uint16_t deviceID = 0; - uint8_t checksum = 0; - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_SERIAL2_READ1); - Wire.write(HTU21_SERIAL2_READ2); - Wire.endTransmission(); - - Wire.requestFrom(HTU21_ADDR, 3); - deviceID = Wire.read() << 8; - deviceID |= Wire.read(); - checksum = Wire.read(); - if (HtuCheckCrc8(deviceID) == checksum) { - deviceID = deviceID >> 8; - } else { - deviceID = 0; - } - return (uint8_t)deviceID; -} - -void HtuSetResolution(uint8_t resolution) -{ - uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); - current &= 0x7E; - current |= resolution; - I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); -} - -void HtuReset(void) -{ - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_RESET); - Wire.endTransmission(); - delay(15); -} - -void HtuHeater(uint8_t heater) -{ - uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); - - switch(heater) - { - case HTU21_HEATER_ON : current |= heater; - break; - case HTU21_HEATER_OFF : current &= heater; - break; - default : current &= heater; - break; - } - I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); -} - -void HtuInit(void) -{ - HtuReset(); - HtuHeater(HTU21_HEATER_OFF); - HtuSetResolution(HTU21_RES_RH12_T14); -} - -bool HtuRead(void) -{ - uint8_t checksum = 0; - uint16_t sensorval = 0; - - if (htu_valid) { htu_valid--; } - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_READTEMP); - if (Wire.endTransmission() != 0) { return false; } - delay(htu_delay_temp); - - Wire.requestFrom(HTU21_ADDR, 3); - if (3 == Wire.available()) { - sensorval = Wire.read() << 8; - sensorval |= Wire.read(); - checksum = Wire.read(); - } - if (HtuCheckCrc8(sensorval) != checksum) { return false; } - - htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_READHUM); - if (Wire.endTransmission() != 0) { return false; } - delay(htu_delay_humidity); - - Wire.requestFrom(HTU21_ADDR, 3); - if (3 <= Wire.available()) { - sensorval = Wire.read() << 8; - sensorval |= Wire.read(); - checksum = Wire.read(); - } - if (HtuCheckCrc8(sensorval) != checksum) { return false; } - - sensorval ^= 0x02; - htu_humidity = 0.001907 * (float)sensorval - 6; - if (htu_humidity > 100) { htu_humidity = 100.0; } - if (htu_humidity < 0) { htu_humidity = 0.01; } - - if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) { - htu_humidity = 0.0; - } - if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) { - htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity; - } - ConvertHumidity(htu_humidity); - - htu_valid = SENSOR_MAX_MISS; - return true; -} - - - -void HtuDetect(void) -{ - htu_address = HTU21_ADDR; - if (I2cActive(htu_address)) { return; } - - htu_type = HtuReadDeviceId(); - if (htu_type) { - uint8_t index = 0; - HtuInit(); - switch (htu_type) { - case HTU21_CHIPID: - htu_delay_temp = 50; - htu_delay_humidity = 16; - break; - case SI7021_CHIPID: - index++; - case SI7020_CHIPID: - index++; - case SI7013_CHIPID: - index++; - htu_delay_temp = 12; - htu_delay_humidity = 23; - break; - default: - index = 4; - htu_delay_temp = 50; - htu_delay_humidity = 23; - } - GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); - I2cSetActiveFound(htu_address, htu_types); - } -} - -void HtuEverySecond(void) -{ - if (uptime &1) { - - if (!HtuRead()) { - AddLogMissed(htu_types, htu_valid); - } - } -} - -void HtuShow(bool json) -{ - if (htu_valid) { - char temperature[33]; - dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, htu_types, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, htu_temperature); - KnxSensor(KNX_HUMIDITY, htu_humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, htu_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, htu_types, humidity); -#endif - } - } -} - - - - - -bool Xsns08(uint8_t function) -{ - if (!I2cEnabled(XI2C_09)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - HtuDetect(); - } - else if (htu_type) { - switch (function) { - case FUNC_EVERY_SECOND: - HtuEverySecond(); - break; - case FUNC_JSON_APPEND: - HtuShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HtuShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_09_bmp.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_09_bmp.ino" -#ifdef USE_I2C -#ifdef USE_BMP -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_09_bmp.ino" -#define XSNS_09 9 -#define XI2C_10 10 - -#define BMP_ADDR1 0x76 -#define BMP_ADDR2 0x77 - -#define BMP180_CHIPID 0x55 -#define BMP280_CHIPID 0x58 -#define BME280_CHIPID 0x60 -#define BME680_CHIPID 0x61 - -#define BMP_REGISTER_CHIPID 0xD0 - -#define BMP_REGISTER_RESET 0xE0 - -#define BMP_CMND_RESET 0xB6 - -#define BMP_MAX_SENSORS 2 - -const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; - -typedef struct { - uint8_t bmp_address; - char bmp_name[7]; - uint8_t bmp_type; - uint8_t bmp_model; -#ifdef USE_BME680 - uint8_t bme680_state; - float bmp_gas_resistance; -#endif - float bmp_temperature; - float bmp_pressure; - float bmp_humidity; -} bmp_sensors_t; - -uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; -uint8_t bmp_count = 0; -uint8_t bmp_once = 1; - -bmp_sensors_t *bmp_sensors = nullptr; - - - - - -#define BMP180_REG_CONTROL 0xF4 -#define BMP180_REG_RESULT 0xF6 -#define BMP180_TEMPERATURE 0x2E -#define BMP180_PRESSURE3 0xF4 - -#define BMP180_AC1 0xAA -#define BMP180_AC2 0xAC -#define BMP180_AC3 0xAE -#define BMP180_AC4 0xB0 -#define BMP180_AC5 0xB2 -#define BMP180_AC6 0xB4 -#define BMP180_VB1 0xB6 -#define BMP180_VB2 0xB8 -#define BMP180_MB 0xBA -#define BMP180_MC 0xBC -#define BMP180_MD 0xBE - -#define BMP180_OSS 3 - -typedef struct { - int16_t cal_ac1; - int16_t cal_ac2; - int16_t cal_ac3; - int16_t cal_b1; - int16_t cal_b2; - int16_t cal_mc; - int16_t cal_md; - uint16_t cal_ac4; - uint16_t cal_ac5; - uint16_t cal_ac6; -} bmp180_cal_data_t; - -bmp180_cal_data_t *bmp180_cal_data = nullptr; - -bool Bmp180Calibration(uint8_t bmp_idx) -{ - if (!bmp180_cal_data) { - bmp180_cal_data = (bmp180_cal_data_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp180_cal_data_t)); - } - if (!bmp180_cal_data) { return false; } - - bmp180_cal_data[bmp_idx].cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1); - bmp180_cal_data[bmp_idx].cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2); - bmp180_cal_data[bmp_idx].cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3); - bmp180_cal_data[bmp_idx].cal_ac4 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC4); - bmp180_cal_data[bmp_idx].cal_ac5 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC5); - bmp180_cal_data[bmp_idx].cal_ac6 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC6); - bmp180_cal_data[bmp_idx].cal_b1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB1); - bmp180_cal_data[bmp_idx].cal_b2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB2); - bmp180_cal_data[bmp_idx].cal_mc = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MC); - bmp180_cal_data[bmp_idx].cal_md = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MD); - - - if (!bmp180_cal_data[bmp_idx].cal_ac1 | - !bmp180_cal_data[bmp_idx].cal_ac2 | - !bmp180_cal_data[bmp_idx].cal_ac3 | - !bmp180_cal_data[bmp_idx].cal_ac4 | - !bmp180_cal_data[bmp_idx].cal_ac5 | - !bmp180_cal_data[bmp_idx].cal_ac6 | - !bmp180_cal_data[bmp_idx].cal_b1 | - !bmp180_cal_data[bmp_idx].cal_b2 | - !bmp180_cal_data[bmp_idx].cal_mc | - !bmp180_cal_data[bmp_idx].cal_md) { - return false; - } - - if ((bmp180_cal_data[bmp_idx].cal_ac1 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac2 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac3 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac4 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac5 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac6 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_b1 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_b2 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_mc == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_md == (int16_t)0xFFFF)) { - return false; - } - return true; -} - -void Bmp180Read(uint8_t bmp_idx) -{ - if (!bmp180_cal_data) { return; } - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); - delay(5); - int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); - int32_t xt1 = (ut - (int32_t)bmp180_cal_data[bmp_idx].cal_ac6) * ((int32_t)bmp180_cal_data[bmp_idx].cal_ac5) >> 15; - int32_t xt2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_mc << 11) / (xt1 + (int32_t)bmp180_cal_data[bmp_idx].cal_md); - int32_t bmp180_b5 = xt1 + xt2; - bmp_sensors[bmp_idx].bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); - delay(2 + (4 << BMP180_OSS)); - uint32_t up = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); - up >>= (8 - BMP180_OSS); - - int32_t b6 = bmp180_b5 - 4000; - int32_t x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b2 * ((b6 * b6) >> 12)) >> 11; - int32_t x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac2 * b6) >> 11; - int32_t x3 = x1 + x2; - int32_t b3 = ((((int32_t)bmp180_cal_data[bmp_idx].cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2; - - x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac3 * b6) >> 13; - x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b1 * ((b6 * b6) >> 12)) >> 16; - x3 = ((x1 + x2) + 2) >> 2; - uint32_t b4 = ((uint32_t)bmp180_cal_data[bmp_idx].cal_ac4 * (uint32_t)(x3 + 32768)) >> 15; - uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS); - - int32_t p; - if (b7 < 0x80000000) { - p = (b7 * 2) / b4; - } - else { - p = (b7 / b4) * 2; - } - x1 = (p >> 8) * (p >> 8); - x1 = (x1 * 3038) >> 16; - x2 = (-7357 * p) >> 16; - p += ((x1 + x2 + (int32_t)3791) >> 4); - bmp_sensors[bmp_idx].bmp_pressure = (float)p / 100.0; -} - - - - - - - -#define BME280_REGISTER_CONTROLHUMID 0xF2 -#define BME280_REGISTER_CONTROL 0xF4 -#define BME280_REGISTER_CONFIG 0xF5 -#define BME280_REGISTER_PRESSUREDATA 0xF7 -#define BME280_REGISTER_TEMPDATA 0xFA -#define BME280_REGISTER_HUMIDDATA 0xFD - -#define BME280_REGISTER_DIG_T1 0x88 -#define BME280_REGISTER_DIG_T2 0x8A -#define BME280_REGISTER_DIG_T3 0x8C -#define BME280_REGISTER_DIG_P1 0x8E -#define BME280_REGISTER_DIG_P2 0x90 -#define BME280_REGISTER_DIG_P3 0x92 -#define BME280_REGISTER_DIG_P4 0x94 -#define BME280_REGISTER_DIG_P5 0x96 -#define BME280_REGISTER_DIG_P6 0x98 -#define BME280_REGISTER_DIG_P7 0x9A -#define BME280_REGISTER_DIG_P8 0x9C -#define BME280_REGISTER_DIG_P9 0x9E -#define BME280_REGISTER_DIG_H1 0xA1 -#define BME280_REGISTER_DIG_H2 0xE1 -#define BME280_REGISTER_DIG_H3 0xE3 -#define BME280_REGISTER_DIG_H4 0xE4 -#define BME280_REGISTER_DIG_H5 0xE5 -#define BME280_REGISTER_DIG_H6 0xE7 - -typedef struct { - uint16_t dig_T1; - int16_t dig_T2; - int16_t dig_T3; - uint16_t dig_P1; - int16_t dig_P2; - int16_t dig_P3; - int16_t dig_P4; - int16_t dig_P5; - int16_t dig_P6; - int16_t dig_P7; - int16_t dig_P8; - int16_t dig_P9; - int16_t dig_H2; - int16_t dig_H4; - int16_t dig_H5; - uint8_t dig_H1; - uint8_t dig_H3; - int8_t dig_H6; -} Bme280CalibrationData_t; - -Bme280CalibrationData_t *Bme280CalibrationData = nullptr; - -bool Bmx280Calibrate(uint8_t bmp_idx) -{ - - - if (!Bme280CalibrationData) { - Bme280CalibrationData = (Bme280CalibrationData_t*)malloc(BMP_MAX_SENSORS * sizeof(Bme280CalibrationData_t)); - } - if (!Bme280CalibrationData) { return false; } - - Bme280CalibrationData[bmp_idx].dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1); - Bme280CalibrationData[bmp_idx].dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2); - Bme280CalibrationData[bmp_idx].dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3); - Bme280CalibrationData[bmp_idx].dig_P1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P1); - Bme280CalibrationData[bmp_idx].dig_P2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P2); - Bme280CalibrationData[bmp_idx].dig_P3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P3); - Bme280CalibrationData[bmp_idx].dig_P4 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P4); - Bme280CalibrationData[bmp_idx].dig_P5 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P5); - Bme280CalibrationData[bmp_idx].dig_P6 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P6); - Bme280CalibrationData[bmp_idx].dig_P7 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P7); - Bme280CalibrationData[bmp_idx].dig_P8 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P8); - Bme280CalibrationData[bmp_idx].dig_P9 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P9); - if (BME280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { - Bme280CalibrationData[bmp_idx].dig_H1 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H1); - Bme280CalibrationData[bmp_idx].dig_H2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H2); - Bme280CalibrationData[bmp_idx].dig_H3 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H3); - Bme280CalibrationData[bmp_idx].dig_H4 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); - Bme280CalibrationData[bmp_idx].dig_H5 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5) >> 4); - Bme280CalibrationData[bmp_idx].dig_H6 = (int8_t)I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H6); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x00); - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROLHUMID, 0x01); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONFIG, 0xA0); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x27); - } else { - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0xB7); - } - - return true; -} - -void Bme280Read(uint8_t bmp_idx) -{ - if (!Bme280CalibrationData) { return; } - - int32_t adc_T = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_TEMPDATA); - adc_T >>= 4; - - int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1 << 1))) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_T2)) >> 11; - int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1))) >> 12) * - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T3)) >> 14; - int32_t t_fine = vart1 + vart2; - float T = (t_fine * 5 + 128) >> 8; - bmp_sensors[bmp_idx].bmp_temperature = T / 100.0; - - int32_t adc_P = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_PRESSUREDATA); - adc_P >>= 4; - - int64_t var1 = ((int64_t)t_fine) - 128000; - int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P6; - var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P5) << 17); - var2 = var2 + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P4) << 35); - var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P2) << 12); - var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData[bmp_idx].dig_P1) >> 33; - if (0 == var1) { - return; - } - int64_t p = 1048576 - adc_P; - p = (((p << 31) - var2) * 3125) / var1; - var1 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P9) * (p >> 13) * (p >> 13)) >> 25; - var2 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P7) << 4); - bmp_sensors[bmp_idx].bmp_pressure = (float)p / 25600.0; - - if (BMP280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { return; } - - int32_t adc_H = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_HUMIDDATA); - - int32_t v_x1_u32r = (t_fine - ((int32_t)76800)); - v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H4) << 20) - - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * - (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H6)) >> 10) * - (((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + - ((int32_t)2097152)) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H2) + 8192) >> 14)); - v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * - ((int32_t)Bme280CalibrationData[bmp_idx].dig_H1)) >> 4)); - v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; - v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; - float h = (v_x1_u32r >> 12); - bmp_sensors[bmp_idx].bmp_humidity = h / 1024.0; -} - -#ifdef USE_BME680 - - - - -#include - -struct bme680_dev *gas_sensor = nullptr; - -static void BmeDelayMs(uint32_t ms) -{ - delay(ms); -} - -bool Bme680Init(uint8_t bmp_idx) -{ - if (!gas_sensor) { - gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); - } - if (!gas_sensor) { return false; } - - gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address; - gas_sensor[bmp_idx].intf = BME680_I2C_INTF; - gas_sensor[bmp_idx].read = &I2cReadBuffer; - gas_sensor[bmp_idx].write = &I2cWriteBuffer; - gas_sensor[bmp_idx].delay_ms = BmeDelayMs; - - - - gas_sensor[bmp_idx].amb_temp = 25; - - int8_t rslt = BME680_OK; - rslt = bme680_init(&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return false; } - - - gas_sensor[bmp_idx].tph_sett.os_hum = BME680_OS_2X; - gas_sensor[bmp_idx].tph_sett.os_pres = BME680_OS_4X; - gas_sensor[bmp_idx].tph_sett.os_temp = BME680_OS_8X; - gas_sensor[bmp_idx].tph_sett.filter = BME680_FILTER_SIZE_3; - - - gas_sensor[bmp_idx].gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; - - gas_sensor[bmp_idx].gas_sett.heatr_temp = 320; - gas_sensor[bmp_idx].gas_sett.heatr_dur = 150; - - - - gas_sensor[bmp_idx].power_mode = BME680_FORCED_MODE; - - - uint8_t set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; - - - rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return false; } - - bmp_sensors[bmp_idx].bme680_state = 0; - - return true; -} - -void Bme680Read(uint8_t bmp_idx) -{ - if (!gas_sensor) { return; } - - int8_t rslt = BME680_OK; - - if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { - if (0 == bmp_sensors[bmp_idx].bme680_state) { - - rslt = bme680_set_sensor_mode(&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return; } - - - - - - - - bmp_sensors[bmp_idx].bme680_state = 1; - } else { - bmp_sensors[bmp_idx].bme680_state = 0; - - struct bme680_field_data data; - rslt = bme680_get_sensor_data(&data, &gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return; } - - bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; - bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; - bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; - - if (data.status & BME680_GASM_VALID_MSK) { - bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; - } else { - bmp_sensors[bmp_idx].bmp_gas_resistance = 0; - } - } - } - return; -} - -#endif - - - -void BmpDetect(void) -{ - int bmp_sensor_size = BMP_MAX_SENSORS * sizeof(bmp_sensors_t); - if (!bmp_sensors) { - bmp_sensors = (bmp_sensors_t*)malloc(bmp_sensor_size); - } - if (!bmp_sensors) { return; } - memset(bmp_sensors, 0, bmp_sensor_size); - - for (uint32_t i = 0; i < BMP_MAX_SENSORS; i++) { - if (I2cActive(bmp_addresses[i])) { continue; } - uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); - if (bmp_type) { - bmp_sensors[bmp_count].bmp_address = bmp_addresses[i]; - bmp_sensors[bmp_count].bmp_type = bmp_type; - bmp_sensors[bmp_count].bmp_model = 0; - - bool success = false; - switch (bmp_type) { - case BMP180_CHIPID: - success = Bmp180Calibration(bmp_count); - break; - case BME280_CHIPID: - bmp_sensors[bmp_count].bmp_model++; - case BMP280_CHIPID: - bmp_sensors[bmp_count].bmp_model++; - success = Bmx280Calibrate(bmp_count); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - bmp_sensors[bmp_count].bmp_model = 3; - success = Bme680Init(bmp_count); - break; -#endif - } - if (success) { - GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); - I2cSetActiveFound(bmp_sensors[bmp_count].bmp_address, bmp_sensors[bmp_count].bmp_name); - bmp_count++; - } - } - } -} - -void BmpRead(void) -{ - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - switch (bmp_sensors[bmp_idx].bmp_type) { - case BMP180_CHIPID: - Bmp180Read(bmp_idx); - break; - case BMP280_CHIPID: - case BME280_CHIPID: - Bme280Read(bmp_idx); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - Bme680Read(bmp_idx); - break; -#endif - } - } - ConvertTemp(bmp_sensors[0].bmp_temperature); - ConvertHumidity(bmp_sensors[0].bmp_humidity); -} - -void BmpShow(bool json) -{ - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - if (bmp_sensors[bmp_idx].bmp_type) { - float bmp_sealevel = 0.0; - if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { - bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; - bmp_sealevel = ConvertPressure(bmp_sealevel); - } - float bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); - float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); - - char name[10]; - strlcpy(name, bmp_sensors[bmp_idx].bmp_name, sizeof(name)); - if (bmp_count > 1) { - snprintf_P(name, sizeof(name), PSTR("%s%c%02X"), name, IndexSeparator(), bmp_sensors[bmp_idx].bmp_address); - } - - char temperature[33]; - dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); - char pressure[33]; - dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); - char sea_pressure[33]; - dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); - char humidity[33]; - dtostrfd(bmp_sensors[bmp_idx].bmp_humidity, Settings.flag2.humidity_resolution, humidity); -#ifdef USE_BME680 - char gas_resistance[33]; - dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); -#endif - - if (json) { - char json_humidity[40]; - snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - char json_sealevel[40]; - snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); -#ifdef USE_BME680 - char json_gas[40]; - snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); - - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), - name, - temperature, - (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", - pressure, - (Settings.altitude != 0) ? json_sealevel : "", - (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); -#else - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), - name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); -#endif - -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == bmp_idx)) { - DomoticzTempHumPressureSensor(temperature, humidity, pressure); -#ifdef USE_BME680 - if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } -#endif - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, bmp_temperature); - KnxSensor(KNX_HUMIDITY, bmp_sensors[bmp_idx].bmp_humidity); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, name, temperature, TempUnit()); - if (bmp_sensors[bmp_idx].bmp_model >= 2) { - WSContentSend_PD(HTTP_SNS_HUM, name, humidity); - } - WSContentSend_PD(HTTP_SNS_PRESSURE, name, pressure, PressureUnit().c_str()); - if (Settings.altitude != 0) { - WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sea_pressure, PressureUnit().c_str()); - } -#ifdef USE_BME680 - if (bmp_sensors[bmp_idx].bmp_model >= 3) { - WSContentSend_PD(PSTR("{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), name, gas_resistance); - } -#endif - -#endif - } - } - } -} - -#ifdef USE_DEEPSLEEP - -void BMP_EnterSleep(void) -{ - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - switch (bmp_sensors[bmp_idx].bmp_type) { - case BMP180_CHIPID: - case BMP280_CHIPID: - case BME280_CHIPID: - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP_REGISTER_RESET, BMP_CMND_RESET); - break; - default: - break; - } - } -} - -#endif - - - - - -bool Xsns09(uint8_t function) -{ - if (!I2cEnabled(XI2C_10)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - BmpDetect(); - } - else if (bmp_count) { - switch (function) { - case FUNC_EVERY_SECOND: - BmpRead(); - break; - case FUNC_JSON_APPEND: - BmpShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - BmpShow(0); - break; -#endif -#ifdef USE_DEEPSLEEP - case FUNC_SAVE_BEFORE_RESTART: - BMP_EnterSleep(); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_10_bh1750.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_10_bh1750.ino" -#ifdef USE_I2C -#ifdef USE_BH1750 - - - - - - -#define XSNS_10 10 -#define XI2C_11 11 - -#define BH1750_ADDR1 0x23 -#define BH1750_ADDR2 0x5C - -#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 - -uint8_t bh1750_address; -uint8_t bh1750_addresses[] = { BH1750_ADDR1, BH1750_ADDR2 }; -uint8_t bh1750_type = 0; -uint8_t bh1750_valid = 0; -uint16_t bh1750_illuminance = 0; -char bh1750_types[] = "BH1750"; - -bool Bh1750Read(void) -{ - if (bh1750_valid) { bh1750_valid--; } - - if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } - uint8_t msb = Wire.read(); - uint8_t lsb = Wire.read(); - bh1750_illuminance = ((msb << 8) | lsb) / 1.2; - bh1750_valid = SENSOR_MAX_MISS; - return true; -} - - - -void Bh1750Detect(void) -{ - for (uint32_t i = 0; i < sizeof(bh1750_addresses); i++) { - bh1750_address = bh1750_addresses[i]; - if (I2cActive(bh1750_address)) { continue; } - Wire.beginTransmission(bh1750_address); - Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); - if (!Wire.endTransmission()) { - I2cSetActiveFound(bh1750_address, bh1750_types); - bh1750_type = 1; - break; - } - } -} - -void Bh1750EverySecond(void) -{ - - if (!Bh1750Read()) { - AddLogMissed(bh1750_types, bh1750_valid); - } -} - -void Bh1750Show(bool json) -{ - if (bh1750_valid) { - if (json) { - ResponseAppend_P(JSON_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); -#endif - } - } -} - - - - - -bool Xsns10(uint8_t function) -{ - if (!I2cEnabled(XI2C_11)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Bh1750Detect(); - } - else if (bh1750_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Bh1750EverySecond(); - break; - case FUNC_JSON_APPEND: - Bh1750Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Bh1750Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_11_veml6070.ino" -# 89 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_11_veml6070.ino" -#ifdef USE_I2C -#ifdef USE_VEML6070 - - - - - - -#define XSNS_11 11 -#define XI2C_12 12 - -#define VEML6070_ADDR_H 0x39 -#define VEML6070_ADDR_L 0x38 -#define VEML6070_INTEGRATION_TIME 3 -#define VEML6070_ENABLE 1 -#define VEML6070_DISABLE 0 -#define VEML6070_RSET_DEFAULT 270000 -#define VEML6070_UV_MAX_INDEX 15 -#define VEML6070_UV_MAX_DEFAULT 11 -#define VEML6070_POWER_COEFFCIENT 0.025 -#define VEML6070_TABLE_COEFFCIENT 32.86270591 - - - - - -const char kVemlTypes[] PROGMEM = "VEML6070"; -double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -double uvrisk = 0; -double uvpower = 0; -uint16_t uvlevel = 0; -uint8_t veml6070_addr_low = VEML6070_ADDR_L; -uint8_t veml6070_addr_high = VEML6070_ADDR_H; -uint8_t itime = VEML6070_INTEGRATION_TIME; -uint8_t veml6070_type = 0; -char veml6070_name[9]; -char str_uvrisk_text[10]; - - - -void Veml6070Detect(void) -{ - if (I2cActive(VEML6070_ADDR_L)) { return; } - - - Wire.beginTransmission(VEML6070_ADDR_L); - Wire.write((itime << 2) | 0x02); - uint8_t status = Wire.endTransmission(); - - if (!status) { - veml6070_type = 1; - Veml6070UvTableInit(); - uint8_t veml_model = 0; - GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); - I2cSetActiveFound(VEML6070_ADDR_L, veml6070_name); - } -} - - - -void Veml6070UvTableInit(void) -{ - - for (uint32_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { -#ifdef USE_VEML6070_RSET - if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { - uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - } else { - uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); - } -#else - uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); -#endif - } -} - - - -void Veml6070EverySecond(void) -{ - - Veml6070ModeCmd(1); - uvlevel = Veml6070ReadUv(); - uvrisk = Veml6070UvRiskLevel(uvlevel); - uvpower = Veml6070UvPower(uvrisk); - Veml6070ModeCmd(0); -} - - - -void Veml6070ModeCmd(bool mode_cmd) -{ - - - Wire.beginTransmission(VEML6070_ADDR_L); - Wire.write((mode_cmd << 0) | 0x02 | (itime << 2)); - uint8_t status = Wire.endTransmission(); - - if (!status) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 mode_cmd")); - } -} - - - -uint16_t Veml6070ReadUv(void) -{ - uint16_t uv_raw = 0; - - if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { - return -1; - } - uv_raw = Wire.read(); - uv_raw <<= 8; - - if (Wire.requestFrom(VEML6070_ADDR_L, 1) != 1) { - return -1; - } - uv_raw |= Wire.read(); - - return uv_raw; -} - - - -double Veml6070UvRiskLevel(uint16_t uv_level) -{ - double risk = 0; - if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { - risk = (double)uv_level / uv_risk_map[0]; - - if ( (risk >= 0) && (risk <= 2.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_1); } - else if ( (risk >= 3.0) && (risk <= 5.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_2); } - else if ( (risk >= 6.0) && (risk <= 7.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_3); } - else if ( (risk >= 8.0) && (risk <= 10.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_4); } - else if ( (risk >= 11.0) && (risk <= 12.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_5); } - else if ( (risk >= 13.0) && (risk <= 25.0) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_6); } - else { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); } - return risk; - } else { - - snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); - return ( risk = 99 ); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); - } -} - - - -double Veml6070UvPower(double uvrisk) -{ - - double power = 0; - return ( power = VEML6070_POWER_COEFFCIENT * uvrisk ); -} - - - - -#ifdef USE_WEBSERVER - -#ifdef USE_VEML6070_SHOW_RAW - const char HTTP_SNS_UV_LEVEL[] PROGMEM = "{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; -#endif - - const char HTTP_SNS_UV_INDEX[] PROGMEM = "{s}VEML6070 " D_UV_INDEX "{m}%s %s{e}"; - const char HTTP_SNS_UV_POWER[] PROGMEM = "{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; -#endif - - - -void Veml6070Show(bool json) -{ - - char str_uvlevel[33]; - dtostrfd((double)uvlevel, 0, str_uvlevel); - char str_uvrisk[33]; - dtostrfd(uvrisk, 2, str_uvrisk); - char str_uvpower[33]; - dtostrfd(uvpower, 3, str_uvpower); - if (json) { -#ifdef USE_VEML6070_SHOW_RAW - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); -#else - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); -#endif -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } -#endif -#ifdef USE_WEBSERVER - } else { -#ifdef USE_VEML6070_SHOW_RAW - WSContentSend_PD(HTTP_SNS_UV_LEVEL, str_uvlevel); -#endif - WSContentSend_PD(HTTP_SNS_UV_INDEX, str_uvrisk, str_uvrisk_text); - WSContentSend_PD(HTTP_SNS_UV_POWER, str_uvpower); -#endif - } -} - - - - - -bool Xsns11(uint8_t function) -{ - if (!I2cEnabled(XI2C_12)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Veml6070Detect(); - } - else if (veml6070_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Veml6070EverySecond(); - break; - case FUNC_JSON_APPEND: - Veml6070Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Veml6070Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_12_ads1115.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_12_ads1115.ino" -#ifdef USE_I2C -#ifdef USE_ADS1115 -# 43 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_12_ads1115.ino" -#define XSNS_12 12 -#define XI2C_13 13 - -#define ADS1115_ADDRESS_ADDR_GND 0x48 -#define ADS1115_ADDRESS_ADDR_VDD 0x49 -#define ADS1115_ADDRESS_ADDR_SDA 0x4A -#define ADS1115_ADDRESS_ADDR_SCL 0x4B - -#define ADS1115_CONVERSIONDELAY (8) - - - - -#define ADS1115_REG_POINTER_MASK (0x03) -#define ADS1115_REG_POINTER_CONVERT (0x00) -#define ADS1115_REG_POINTER_CONFIG (0x01) -#define ADS1115_REG_POINTER_LOWTHRESH (0x02) -#define ADS1115_REG_POINTER_HITHRESH (0x03) - - - - -#define ADS1115_REG_CONFIG_OS_MASK (0x8000) -#define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) -#define ADS1115_REG_CONFIG_OS_BUSY (0x0000) -#define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) - -#define ADS1115_REG_CONFIG_MUX_MASK (0x7000) -#define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) -#define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) -#define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) -#define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) - -#define ADS1115_REG_CONFIG_PGA_MASK (0x0E00) -#define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) -#define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) -#define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) -#define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) -#define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) -#define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) - -#define ADS1115_REG_CONFIG_MODE_MASK (0x0100) -#define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) -#define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) - -#define ADS1115_REG_CONFIG_DR_MASK (0x00E0) -#define ADS1115_REG_CONFIG_DR_128SPS (0x0000) -#define ADS1115_REG_CONFIG_DR_250SPS (0x0020) -#define ADS1115_REG_CONFIG_DR_490SPS (0x0040) -#define ADS1115_REG_CONFIG_DR_920SPS (0x0060) -#define ADS1115_REG_CONFIG_DR_1600SPS (0x0080) -#define ADS1115_REG_CONFIG_DR_2400SPS (0x00A0) -#define ADS1115_REG_CONFIG_DR_3300SPS (0x00C0) -#define ADS1115_REG_CONFIG_DR_6000SPS (0x00E0) - -#define ADS1115_REG_CONFIG_CMODE_MASK (0x0010) -#define ADS1115_REG_CONFIG_CMODE_TRAD (0x0000) -#define ADS1115_REG_CONFIG_CMODE_WINDOW (0x0010) - -#define ADS1115_REG_CONFIG_CPOL_MASK (0x0008) -#define ADS1115_REG_CONFIG_CPOL_ACTVLOW (0x0000) -#define ADS1115_REG_CONFIG_CPOL_ACTVHI (0x0008) - -#define ADS1115_REG_CONFIG_CLAT_MASK (0x0004) -#define ADS1115_REG_CONFIG_CLAT_NONLAT (0x0000) -#define ADS1115_REG_CONFIG_CLAT_LATCH (0x0004) - -#define ADS1115_REG_CONFIG_CQUE_MASK (0x0003) -#define ADS1115_REG_CONFIG_CQUE_1CONV (0x0000) -#define ADS1115_REG_CONFIG_CQUE_2CONV (0x0001) -#define ADS1115_REG_CONFIG_CQUE_4CONV (0x0002) -#define ADS1115_REG_CONFIG_CQUE_NONE (0x0003) - -struct ADS1115 { - uint8_t count = 0; - uint8_t address; - uint8_t addresses[4] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; - uint8_t found[4] = {false,false,false,false}; -} Ads1115; - - - -void Ads1115StartComparator(uint8_t channel, uint16_t mode) -{ - - uint16_t config = mode | - ADS1115_REG_CONFIG_CQUE_NONE | - ADS1115_REG_CONFIG_CLAT_NONLAT | - ADS1115_REG_CONFIG_PGA_6_144V | - ADS1115_REG_CONFIG_CPOL_ACTVLOW | - ADS1115_REG_CONFIG_CMODE_TRAD | - ADS1115_REG_CONFIG_DR_6000SPS; - - - config |= (ADS1115_REG_CONFIG_MUX_SINGLE_0 + (0x1000 * channel)); - - - I2cWrite16(Ads1115.address, ADS1115_REG_POINTER_CONFIG, config); -} - -int16_t Ads1115GetConversion(uint8_t channel) -{ - Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); - - delay(ADS1115_CONVERSIONDELAY); - - I2cRead16(Ads1115.address, ADS1115_REG_POINTER_CONVERT); - - Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); - delay(ADS1115_CONVERSIONDELAY); - - uint16_t res = I2cRead16(Ads1115.address, ADS1115_REG_POINTER_CONVERT); - return (int16_t)res; -} - - - -void Ads1115Detect(void) -{ - for (uint32_t i = 0; i < sizeof(Ads1115.addresses); i++) { - if (!Ads1115.found[i]) { - Ads1115.address = Ads1115.addresses[i]; - if (I2cActive(Ads1115.address)) { continue; } - uint16_t buffer; - if (I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONVERT) && - I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONFIG)) { - Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); - I2cSetActiveFound(Ads1115.address, "ADS1115"); - Ads1115.found[i] = 1; - Ads1115.count++; - } - } - } -} - -void Ads1115Show(bool json) -{ - int16_t values[4]; - - for (uint32_t t = 0; t < sizeof(Ads1115.addresses); t++) { - - if (Ads1115.found[t]) { - - uint8_t old_address = Ads1115.address; - Ads1115.address = Ads1115.addresses[t]; - for (uint32_t i = 0; i < 4; i++) { - values[i] = Ads1115GetConversion(i); - - } - Ads1115.address = old_address; - - char label[15]; - if (1 == Ads1115.count) { - - snprintf_P(label, sizeof(label), PSTR("ADS1115")); - } else { - - snprintf_P(label, sizeof(label), PSTR("ADS1115%c%02x"), IndexSeparator(), Ads1115.addresses[t]); - } - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{"), label); - for (uint32_t i = 0; i < 4; i++) { - ResponseAppend_P(PSTR("%s\"A%d\":%d"), (0 == i) ? "" : ",", i, values[i]); - } - ResponseJsonEnd(); - } -#ifdef USE_WEBSERVER - else { - for (uint32_t i = 0; i < 4; i++) { - WSContentSend_PD(HTTP_SNS_ANALOG, label, i, values[i]); - } - } -#endif - } - } -} - - - - - -bool Xsns12(uint8_t function) -{ - if (!I2cEnabled(XI2C_13)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Ads1115Detect(); - } - else if (Ads1115.count) { - switch (function) { - case FUNC_JSON_APPEND: - Ads1115Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ads1115Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_13_ina219.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_13_ina219.ino" -#ifdef USE_I2C -#ifdef USE_INA219 -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_13_ina219.ino" -#define XSNS_13 13 -#define XI2C_14 14 - -#define INA219_ADDRESS1 (0x40) -#define INA219_ADDRESS2 (0x41) -#define INA219_ADDRESS3 (0x44) -#define INA219_ADDRESS4 (0x45) - -#define INA219_READ (0x01) -#define INA219_REG_CONFIG (0x00) - -#define INA219_CONFIG_RESET (0x8000) - -#define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) -#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) -#define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) - -#define INA219_CONFIG_GAIN_MASK (0x1800) -#define INA219_CONFIG_GAIN_1_40MV (0x0000) -#define INA219_CONFIG_GAIN_2_80MV (0x0800) -#define INA219_CONFIG_GAIN_4_160MV (0x1000) -#define INA219_CONFIG_GAIN_8_320MV (0x1800) - -#define INA219_CONFIG_BADCRES_MASK (0x0780) -#define INA219_CONFIG_BADCRES_9BIT (0x0080) -#define INA219_CONFIG_BADCRES_10BIT (0x0100) -#define INA219_CONFIG_BADCRES_11BIT (0x0200) -#define INA219_CONFIG_BADCRES_12BIT (0x0400) - -#define INA219_CONFIG_SADCRES_MASK (0x0078) -#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) -#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) -#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) -#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) -#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) -#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) -#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) -#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) -#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) -#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) -#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) - -#define INA219_CONFIG_MODE_MASK (0x0007) -#define INA219_CONFIG_MODE_POWERDOWN (0x0000) -#define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001) -#define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002) -#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003) -#define INA219_CONFIG_MODE_ADCOFF (0x0004) -#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005) -#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006) -#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007) - -#define INA219_REG_SHUNTVOLTAGE (0x01) -#define INA219_REG_BUSVOLTAGE (0x02) -#define INA219_REG_POWER (0x03) -#define INA219_REG_CURRENT (0x04) -#define INA219_REG_CALIBRATION (0x05) - -uint8_t ina219_type[4] = {0,0,0,0}; -uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; - -uint32_t ina219_cal_value = 0; - -uint32_t ina219_current_divider_ma = 0; - -uint8_t ina219_valid[4] = {0,0,0,0}; -float ina219_voltage[4] = {0,0,0,0}; -float ina219_current[4] = {0,0,0,0}; -char ina219_types[] = "INA219"; -uint8_t ina219_count = 0; - -bool Ina219SetCalibration(uint8_t mode, uint16_t addr) -{ - uint16_t config = 0; - - switch (mode &3) { - case 0: - case 3: - ina219_cal_value = 4096; - ina219_current_divider_ma = 10; - config = INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - case 1: - ina219_cal_value = 10240; - ina219_current_divider_ma = 25; - config |= INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - case 2: - ina219_cal_value = 8192; - ina219_current_divider_ma = 20; - config |= INA219_CONFIG_BVOLTAGERANGE_16V | INA219_CONFIG_GAIN_1_40MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - } - - bool success = I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); - if (success) { - - I2cWrite16(addr, INA219_REG_CONFIG, config); - } - return success; -} - -float Ina219GetShuntVoltage_mV(uint16_t addr) -{ - - int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); - - return value * 0.01; -} - -float Ina219GetBusVoltage_V(uint16_t addr) -{ - - - int16_t value = (int16_t)(((uint16_t)I2cReadS16(addr, INA219_REG_BUSVOLTAGE) >> 3) * 4); - - return value * 0.001; -} - -float Ina219GetCurrent_mA(uint16_t addr) -{ - - - - I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); - - - float value = I2cReadS16(addr, INA219_REG_CURRENT); - value /= ina219_current_divider_ma; - - return value; -} - -bool Ina219Read(void) -{ - for (int i=0; i= 0) && (XdrvMailbox.payload <= 2)) { - Settings.ina219_mode = XdrvMailbox.payload; - restart_flag = 2; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); - - return true; -} - - - -void Ina219Detect(void) -{ - for (uint32_t i = 0; i < sizeof(ina219_type); i++) { - uint16_t addr = ina219_addresses[i]; - if (I2cActive(addr)) { continue; } - if (Ina219SetCalibration(Settings.ina219_mode, addr)) { - I2cSetActiveFound(addr, ina219_types); - ina219_type[i] = 1; - ina219_count++; - } - } -} - -void Ina219EverySecond(void) -{ - - Ina219Read(); -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_INA219_DATA[] PROGMEM = - "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; -#endif - -void Ina219Show(bool json) -{ - int num_found=0; - for (int i=0; i1) - snprintf_P(name, sizeof(name), PSTR("%s%c%d"), ina219_types, IndexSeparator(), sensor_num); - else - snprintf_P(name, sizeof(name), PSTR("%s"), ina219_types); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - name, ina219_addresses[i], voltage, current, power); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_INA219_DATA, name, voltage, name, current, name, power); -#endif - } - } -} - - - - - -bool Xsns13(uint8_t function) -{ - if (!I2cEnabled(XI2C_14)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Ina219Detect(); - } - else if (ina219_count) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_13 == XdrvMailbox.index) { - result = Ina219CommandSensor(); - } - break; - case FUNC_EVERY_SECOND: - Ina219EverySecond(); - break; - case FUNC_JSON_APPEND: - Ina219Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ina219Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_14_sht3x.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_14_sht3x.ino" -#ifdef USE_I2C -#ifdef USE_SHT3X - - - - - - -#define XSNS_14 14 -#define XI2C_15 15 - -#define SHT3X_ADDR_GND 0x44 -#define SHT3X_ADDR_VDD 0x45 -#define SHTC3_ADDR 0x70 - -#define SHT3X_MAX_SENSORS 3 - -const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3"; -uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR }; - -uint8_t sht3x_count = 0; -struct SHT3XSTRUCT { - uint8_t address; - char types[6]; -} sht3x_sensors[SHT3X_MAX_SENSORS]; - -bool Sht3xRead(float &t, float &h, uint8_t sht3x_address) -{ - unsigned int data[6]; - - t = NAN; - h = NAN; - - Wire.beginTransmission(sht3x_address); - if (SHTC3_ADDR == sht3x_address) { - Wire.write(0x35); - Wire.write(0x17); - Wire.endTransmission(); - Wire.beginTransmission(sht3x_address); - Wire.write(0x78); - Wire.write(0x66); - } else { - Wire.write(0x2C); - Wire.write(0x06); - } - if (Wire.endTransmission() != 0) { - return false; - } - delay(30); - Wire.requestFrom(sht3x_address, (uint8_t)6); - for (uint32_t i = 0; i < 6; i++) { - data[i] = Wire.read(); - }; - t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45); - h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0)); - return (!isnan(t) && !isnan(h) && (h != 0)); -} - - - -void Sht3xDetect(void) -{ - for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { - if (I2cActive(sht3x_addresses[i])) { continue; } - float t; - float h; - if (Sht3xRead(t, h, sht3x_addresses[i])) { - sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; - GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); - I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types); - sht3x_count++; - } - } -} - -void Sht3xShow(bool json) -{ - for (uint32_t i = 0; i < sht3x_count; i++) { - float t; - float h; - if (Sht3xRead(t, h, sht3x_sensors[i].address)) { - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); - char types[11]; - snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, types, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, types, humidity); -#endif - } - } - } -} - - - - - -bool Xsns14(uint8_t function) -{ - if (!I2cEnabled(XI2C_15)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Sht3xDetect(); - } - else if (sht3x_count) { - switch (function) { - case FUNC_JSON_APPEND: - Sht3xShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sht3xShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" -#ifdef USE_MHZ19 -# 33 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" -#define XSNS_15 15 - -enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILTER_FAST, MHZ19_FILTER_MEDIUM, MHZ19_FILTER_SLOW}; - -#define MHZ19_FILTER_OPTION MHZ19_FILTER_FAST -# 58 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" -#include - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#define MHZ19_READ_TIMEOUT 400 -#define MHZ19_RETRY_COUNT 8 - -TasmotaSerial *MhzSerial; - -const char kMhzModels[] PROGMEM = "|B"; - -const char ABC_ENABLED[] = "ABC is Enabled"; -const char ABC_DISABLED[] = "ABC is Disabled"; - -enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; -const uint8_t kMhzCommands[][4] PROGMEM = { - - {0x86,0x00,0x00,0x00}, - {0x79,0xA0,0x00,0x00}, - {0x79,0x00,0x00,0x00}, - {0x87,0x00,0x00,0x00}, - {0x8D,0x00,0x00,0x00}, - {0x99,0x00,0x03,0xE8}, - {0x99,0x00,0x07,0xD0}, - {0x99,0x00,0x0B,0xB8}, - {0x99,0x00,0x13,0x88}}; - -uint8_t mhz_type = 1; -uint16_t mhz_last_ppm = 0; -uint8_t mhz_filter = MHZ19_FILTER_OPTION; -bool mhz_abc_must_apply = false; - -float mhz_temperature = 0; -uint8_t mhz_retry = MHZ19_RETRY_COUNT; -uint8_t mhz_received = 0; -uint8_t mhz_state = 0; - - - -uint8_t MhzCalculateChecksum(uint8_t *array) -{ - uint8_t checksum = 0; - for (uint32_t i = 1; i < 8; i++) { - checksum += array[i]; - } - checksum = 255 - checksum; - return (checksum +1); -} - -size_t MhzSendCmd(uint8_t command_id) -{ - uint8_t mhz_send[9] = { 0 }; - - mhz_send[0] = 0xFF; - mhz_send[1] = 0x01; - memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(uint16_t)); - - - - - memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); - mhz_send[8] = MhzCalculateChecksum(mhz_send); - - - - return MhzSerial->write(mhz_send, sizeof(mhz_send)); -} - - - -bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) -{ - if (1 == s) { - return false; - } - if (mhz_last_ppm < 400 || mhz_last_ppm > 5000) { - - - mhz_last_ppm = ppm; - return true; - } - int32_t difference = ppm - mhz_last_ppm; - if (s > 0 && s < 64 && mhz_filter != MHZ19_FILTER_OFF) { -# 154 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" - difference *= s; - difference /= 64; - } - if (MHZ19_FILTER_OFF == mhz_filter) { - if (s != 0 && s != 64) { - return false; - } - } else { - difference >>= (mhz_filter -1); - } - mhz_last_ppm = static_cast(mhz_last_ppm + difference); - return true; -} - -void MhzEverySecond(void) -{ - mhz_state++; - if (8 == mhz_state) { - mhz_state = 0; - - if (mhz_retry) { - mhz_retry--; - if (!mhz_retry) { - mhz_last_ppm = 0; - mhz_temperature = 0; - } - } - - MhzSerial->flush(); - MhzSendCmd(MHZ_CMND_READPPM); - mhz_received = 0; - } - - if ((mhz_state > 2) && !mhz_received) { - uint8_t mhz_response[9]; - - unsigned long start = millis(); - uint8_t counter = 0; - while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { - if (MhzSerial->available() > 0) { - mhz_response[counter++] = MhzSerial->read(); - } else { - delay(5); - } - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); - - if (counter < 9) { - - return; - } - - uint8_t crc = MhzCalculateChecksum(mhz_response); - if (mhz_response[8] != crc) { - - return; - } - if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { - - return; - } - - mhz_received = 1; - - uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; - if (15000 == u) { - if (Settings.SensorBits1.mhz19b_abc_disable) { - - - mhz_abc_must_apply = true; - } - } else { - uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; - mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); - uint8_t s = mhz_response[5]; - mhz_type = (s) ? 1 : 2; - if (MhzCheckAndApplyFilter(ppm, s)) { - mhz_retry = MHZ19_RETRY_COUNT; - LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); - - if (0 == s || 64 == s) { - if (mhz_abc_must_apply) { - mhz_abc_must_apply = false; - if (!Settings.SensorBits1.mhz19b_abc_disable) { - MhzSendCmd(MHZ_CMND_ABCENABLE); - } else { - MhzSendCmd(MHZ_CMND_ABCDISABLE); - } - } - } - - } - } - - } -} -# 266 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_15_mhz19.ino" -#define D_JSON_RANGE_1000 "1000 ppm range" -#define D_JSON_RANGE_2000 "2000 ppm range" -#define D_JSON_RANGE_3000 "3000 ppm range" -#define D_JSON_RANGE_5000 "5000 ppm range" - -bool MhzCommandSensor(void) -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - Settings.SensorBits1.mhz19b_abc_disable = true; - MhzSendCmd(MHZ_CMND_ABCDISABLE); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); - break; - case 1: - Settings.SensorBits1.mhz19b_abc_disable = false; - MhzSendCmd(MHZ_CMND_ABCENABLE); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); - break; - case 2: - MhzSendCmd(MHZ_CMND_ZEROPOINT); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); - break; - case 9: - MhzSendCmd(MHZ_CMND_RESET); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); - break; - case 1000: - MhzSendCmd(MHZ_CMND_RANGE_1000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); - break; - case 2000: - MhzSendCmd(MHZ_CMND_RANGE_2000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); - break; - case 3000: - MhzSendCmd(MHZ_CMND_RANGE_3000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); - break; - case 5000: - MhzSendCmd(MHZ_CMND_RANGE_5000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); - break; - default: - if (!Settings.SensorBits1.mhz19b_abc_disable) { - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); - } else { - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); - } - } - - return serviced; -} - - - -void MhzInit(void) -{ - mhz_type = 0; - if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { - MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD], 1); - if (MhzSerial->begin(9600)) { - if (MhzSerial->hardwareSerial()) { ClaimSerial(); } - mhz_type = 1; - } - - } -} - -void MhzShow(bool json) -{ - char types[7] = "MHZ19B"; - char temperature[33]; - dtostrfd(mhz_temperature, Settings.flag2.temperature_resolution, temperature); - char model[3]; - GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, types, mhz_last_ppm); - WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); -#endif - } -} - - - - - -bool Xsns15(uint8_t function) -{ - bool result = false; - - if (mhz_type) { - switch (function) { - case FUNC_INIT: - MhzInit(); - break; - case FUNC_EVERY_SECOND: - MhzEverySecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_15 == XdrvMailbox.index) { - result = MhzCommandSensor(); - } - break; - case FUNC_JSON_APPEND: - MhzShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MhzShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_16_tsl2561.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_16_tsl2561.ino" -#ifdef USE_I2C -#ifdef USE_TSL2561 -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_16_tsl2561.ino" -#define XSNS_16 16 -#define XI2C_16 16 - -#include - -Tsl2561 Tsl(Wire); - -uint8_t tsl2561_type = 0; -uint8_t tsl2561_valid = 0; -uint32_t tsl2561_milliLux = 0; -char tsl2561_types[] = "TSL2561"; - -bool Tsl2561Read(void) -{ - if (tsl2561_valid) { tsl2561_valid--; } - - uint8_t id; - bool gain; - Tsl2561::exposure_t exposure; - uint16_t scaledFull, scaledIr; - uint32_t full, ir; - - if (Tsl.on()) { - if (Tsl.id(id) - && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) - && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) - && Tsl2561Util::milliLux(full, ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { - } else{ - tsl2561_milliLux = 0; - } - } - tsl2561_valid = SENSOR_MAX_MISS; - return true; -} - -void Tsl2561Detect(void) -{ - if (I2cSetDevice(0x29) || I2cSetDevice(0x39) || I2cSetDevice(0x49)) { - uint8_t id; - Tsl.begin(); - if (!Tsl.id(id)) return; - if (Tsl.on()) { - tsl2561_type = 1; - I2cSetActiveFound(Tsl.address(), tsl2561_types); - } - } -} - -void Tsl2561EverySecond(void) -{ - if (!(uptime %2)) { - - if (!Tsl2561Read()) { - AddLogMissed(tsl2561_types, tsl2561_valid); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_TSL2561[] PROGMEM = - "{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; -#endif - -void Tsl2561Show(bool json) -{ - if (tsl2561_valid) { - if (json) { - ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), - tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TSL2561, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); -#endif - } - } -} - - - - - -bool Xsns16(uint8_t function) -{ - if (!I2cEnabled(XI2C_16)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Tsl2561Detect(); - } - else if (tsl2561_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Tsl2561EverySecond(); - break; - case FUNC_JSON_APPEND: - Tsl2561Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tsl2561Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_17_senseair.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_17_senseair.ino" -#ifdef USE_SENSEAIR -# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_17_senseair.ino" -#define XSNS_17 17 - -#define SENSEAIR_MODBUS_SPEED 9600 -#define SENSEAIR_DEVICE_ADDRESS 0xFE -#define SENSEAIR_READ_REGISTER 0x04 - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#include -TasmotaModbus *SenseairModbus; - -const char kSenseairTypes[] PROGMEM = "Kx0|S8"; - -uint8_t senseair_type = 1; -char senseair_types[7]; - -uint16_t senseair_co2 = 0; -float senseair_temperature = 0; -float senseair_humidity = 0; - - - -const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; - -uint8_t senseair_read_state = 0; -uint8_t senseair_send_retry = 0; - -void Senseair250ms(void) -{ - - - - - uint16_t value = 0; - bool data_ready = SenseairModbus->ReceiveReady(); - - if (data_ready) { - uint8_t error = SenseairModbus->Receive16BitRegister(&value); - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); - } else { - switch(senseair_read_state) { - case 0: - senseair_type = 2; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir type id low %04X"), value); - break; - case 1: - if (value) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir error %04X"), value); - } - break; - case 2: - senseair_co2 = value; - LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); - break; - case 3: - senseair_temperature = ConvertTemp((float)value / 100); - break; - case 4: - senseair_humidity = ConvertHumidity((float)value / 100); - break; - case 5: - { - bool relay_state = value >> 8 & 1; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir relay state %d"), relay_state); - break; - } - case 6: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir temp adjustment %d"), value); - break; - } - } - senseair_read_state++; - if (2 == senseair_type) { - if (3 == senseair_read_state) { - senseair_read_state = 1; - } - } else { - if (sizeof(start_addresses) == senseair_read_state) { - senseair_read_state = 1; - } - } - } - - if (0 == senseair_send_retry || data_ready) { - senseair_send_retry = 5; - SenseairModbus->Send(SENSEAIR_DEVICE_ADDRESS, SENSEAIR_READ_REGISTER, (uint16_t)start_addresses[senseair_read_state], 1); - } else { - senseair_send_retry--; - } - - -} - - - -void SenseairInit(void) -{ - senseair_type = 0; - if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { - SenseairModbus = new TasmotaModbus(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX]); - uint8_t result = SenseairModbus->Begin(SENSEAIR_MODBUS_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - senseair_type = 1; - } - } -} - -void SenseairShow(bool json) -{ - char temperature[33]; - dtostrfd(senseair_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(senseair_humidity, Settings.flag2.temperature_resolution, humidity); - GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2); - if (senseair_type != 2) { - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); - } - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, senseair_types, senseair_co2); - if (senseair_type != 2) { - WSContentSend_PD(HTTP_SNS_TEMP, senseair_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, senseair_types, humidity); - } -#endif - } -} - - - - - -bool Xsns17(uint8_t function) -{ - bool result = false; - - if (senseair_type) { - switch (function) { - case FUNC_INIT: - SenseairInit(); - break; - case FUNC_EVERY_250_MSECOND: - Senseair250ms(); - break; - case FUNC_JSON_APPEND: - SenseairShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SenseairShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_18_pms5003.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_18_pms5003.ino" -#ifdef USE_PMS5003 -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_18_pms5003.ino" -#define XSNS_18 18 - -#include - -TasmotaSerial *PmsSerial; - -uint8_t pms_type = 1; -uint8_t pms_valid = 0; - -struct pmsX003data { - uint16_t framelen; - uint16_t pm10_standard, pm25_standard, pm100_standard; - uint16_t pm10_env, pm25_env, pm100_env; -#ifdef PMS_MODEL_PMS3003 - uint16_t reserved1, reserved2, reserved3; -#else - uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um; - uint16_t unused; -#endif - uint16_t checksum; -} pms_data; - - - -bool PmsReadData(void) -{ - if (! PmsSerial->available()) { - return false; - } - while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { - PmsSerial->read(); - } -#ifdef PMS_MODEL_PMS3003 - if (PmsSerial->available() < 22) { -#else - if (PmsSerial->available() < 32) { -#endif - return false; - } - -#ifdef PMS_MODEL_PMS3003 - uint8_t buffer[22]; - PmsSerial->readBytes(buffer, 22); -#else - uint8_t buffer[32]; - PmsSerial->readBytes(buffer, 32); -#endif - uint16_t sum = 0; - PmsSerial->flush(); - -#ifdef PMS_MODEL_PMS3003 - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 22); -#else - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); -#endif - - -#ifdef PMS_MODEL_PMS3003 - for (uint32_t i = 0; i < 20; i++) { -#else - for (uint32_t i = 0; i < 30; i++) { -#endif - sum += buffer[i]; - } - -#ifdef PMS_MODEL_PMS3003 - uint16_t buffer_u16[10]; - for (uint32_t i = 0; i < 10; i++) { -#else - uint16_t buffer_u16[15]; - for (uint32_t i = 0; i < 15; i++) { -#endif - buffer_u16[i] = buffer[2 + i*2 + 1]; - buffer_u16[i] += (buffer[2 + i*2] << 8); - } -#ifdef PMS_MODEL_PMS3003 - if (sum != buffer_u16[9]) { -#else - if (sum != buffer_u16[14]) { -#endif - AddLog_P(LOG_LEVEL_DEBUG, PSTR("PMS: " D_CHECKSUM_FAILURE)); - return false; - } - -#ifdef PMS_MODEL_PMS3003 - memcpy((void *)&pms_data, (void *)buffer_u16, 20); -#else - memcpy((void *)&pms_data, (void *)buffer_u16, 30); -#endif - pms_valid = 10; - - return true; -} - - - -void PmsSecond(void) -{ - if (PmsReadData()) { - pms_valid = 10; - } else { - if (pms_valid) { - pms_valid--; - } - } -} - - - -void PmsInit(void) -{ - pms_type = 0; - if (pin[GPIO_PMS5003] < 99) { - PmsSerial = new TasmotaSerial(pin[GPIO_PMS5003], -1, 1); - if (PmsSerial->begin(9600)) { - if (PmsSerial->hardwareSerial()) { ClaimSerial(); } - pms_type = 1; - } - } -} - -#ifdef USE_WEBSERVER -#ifdef PMS_MODEL_PMS3003 -const char HTTP_PMS3003_SNS[] PROGMEM = - - - - "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; -#else -const char HTTP_PMS5003_SNS[] PROGMEM = - - - - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 0.3 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 0.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; -#endif -#endif - -void PmsShow(bool json) -{ - if (pms_valid) { - if (json) { -#ifdef PMS_MODEL_PMS3003 - ResponseAppend_P(PSTR(",\"PMS3003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d}"), - pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); -#else - ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), - pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, - pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); -#endif -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_COUNT, pms_data.pm10_env); - DomoticzSensor(DZ_VOLTAGE, pms_data.pm25_env); - DomoticzSensor(DZ_CURRENT, pms_data.pm100_env); - } -#endif -#ifdef USE_WEBSERVER - } else { - -#ifdef PMS_MODEL_PMS3003 - WSContentSend_PD(HTTP_PMS3003_SNS, - - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); -#else - WSContentSend_PD(HTTP_PMS5003_SNS, - - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, - pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); -#endif -#endif - } - } -} - - - - - -bool Xsns18(uint8_t function) -{ - bool result = false; - - if (pms_type) { - switch (function) { - case FUNC_INIT: - PmsInit(); - break; - case FUNC_EVERY_SECOND: - PmsSecond(); - break; - case FUNC_JSON_APPEND: - PmsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - PmsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_19_mgs.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_19_mgs.ino" -#ifdef USE_I2C -#ifdef USE_MGS - - - - - - - -#define XSNS_19 19 -#define XI2C_17 17 - -#ifndef MGS_SENSOR_ADDR -#define MGS_SENSOR_ADDR 0x04 -#endif - -#include "MutichannelGasSensor.h" - -bool mgs_detected = false; - -void MGSInit(void) { - gas.begin(MGS_SENSOR_ADDR); -} - -void MGSPrepare(void) -{ - if (I2cActive(MGS_SENSOR_ADDR)) { return; } - - gas.begin(MGS_SENSOR_ADDR); - if (!gas.isError()) { - I2cSetActiveFound(MGS_SENSOR_ADDR, "MultiGas"); - mgs_detected = true; - } -} - -char* measure_gas(int gas_type, char* buffer) -{ - float f = gas.calcGas(gas_type); - dtostrfd(f, 2, buffer); - return buffer; -} - -#ifdef USE_WEBSERVER -const char HTTP_MGS_GAS[] PROGMEM = "{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; -#endif - -void MGSShow(bool json) -{ - char buffer[33]; - if (json) { - ResponseAppend_P(PSTR(",\"MGS\":{\"NH3\":%s"), measure_gas(NH3, buffer)); - ResponseAppend_P(PSTR(",\"CO\":%s"), measure_gas(CO, buffer)); - ResponseAppend_P(PSTR(",\"NO2\":%s"), measure_gas(NO2, buffer)); - ResponseAppend_P(PSTR(",\"C3H8\":%s"), measure_gas(C3H8, buffer)); - ResponseAppend_P(PSTR(",\"C4H10\":%s"), measure_gas(C4H10, buffer)); - ResponseAppend_P(PSTR(",\"CH4\":%s"), measure_gas(GAS_CH4, buffer)); - ResponseAppend_P(PSTR(",\"H2\":%s"), measure_gas(H2, buffer)); - ResponseAppend_P(PSTR(",\"C2H5OH\":%s}"), measure_gas(C2H5OH, buffer)); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "CO", measure_gas(CO, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "NO2", measure_gas(NO2, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C3H8", measure_gas(C3H8, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C4H10", measure_gas(C4H10, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "CH4", measure_gas(GAS_CH4, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "H2", measure_gas(H2, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C2H5OH", measure_gas(C2H5OH, buffer)); -#endif - } -} - - - - - -bool Xsns19(uint8_t function) -{ - if (!I2cEnabled(XI2C_17)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MGSPrepare(); - } - else if (mgs_detected) { - switch (function) { - case FUNC_JSON_APPEND: - MGSShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MGSShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_20_novasds.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_20_novasds.ino" -#ifdef USE_NOVA_SDS -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_20_novasds.ino" -#define XSNS_20 20 - -#include - -#ifndef STARTING_OFFSET -#define STARTING_OFFSET 30 -#endif -#if STARTING_OFFSET < 10 -#error "Please set STARTING_OFFSET >= 10" -#endif -#ifndef NOVA_SDS_RECDATA_TIMEOUT -#define NOVA_SDS_RECDATA_TIMEOUT 150 -#endif -#ifndef NOVA_SDS_DEVICE_ID -#define NOVA_SDS_DEVICE_ID 0xFFFF -#endif - -TasmotaSerial *NovaSdsSerial; - -uint8_t novasds_type = 1; -uint8_t novasds_valid = 0; -uint8_t cont_mode = 1; - -struct sds011data { - uint16_t pm100; - uint16_t pm25; -} novasds_data; -uint16_t pm100_sum; -uint16_t pm25_sum; - - -#define NOVA_SDS_REPORTING_MODE 2 -#define NOVA_SDS_QUERY_DATA 4 -#define NOVA_SDS_SET_DEVICE_ID 5 -#define NOVA_SDS_SLEEP_AND_WORK 6 -#define NOVA_SDS_WORKING_PERIOD 8 -#define NOVA_SDS_CHECK_FIRMWARE_VER 7 - #define NOVA_SDS_QUERY_MODE 0 - #define NOVA_SDS_SET_MODE 1 - #define NOVA_SDS_REPORT_ACTIVE 0 - #define NOVA_SDS_REPORT_QUERY 1 - #define NOVA_SDS_SLEEP 0 - #define NOVA_SDS_WORK 1 - - -bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) -{ - uint8_t novasds_cmnd[19] = {0xAA, 0xB4, byte1, byte2, byte3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t)(sensorid & 0xFF), (uint8_t)((sensorid>>8) & 0xFF), 0x00, 0xAB}; - - - for (uint32_t i = 2; i < 17; i++) { - novasds_cmnd[17] += novasds_cmnd[i]; - } - - - - - - NovaSdsSerial->write(novasds_cmnd, sizeof(novasds_cmnd)); - NovaSdsSerial->flush(); - - - unsigned long cmndtime = millis(); - while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( ! NovaSdsSerial->available() ) ); - if ( ! NovaSdsSerial->available() ) { - - return false; - } - uint8_t recbuf[10]; - memset(recbuf, 0, sizeof(recbuf)); - - while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( NovaSdsSerial->available() > 0) && (0xAA != (recbuf[0] = NovaSdsSerial->read())) ); - if ( 0xAA != recbuf[0] ) { - - return false; - } - - - NovaSdsSerial->readBytes(&recbuf[1], 9); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); - - if ( nullptr != buffer ) { - - memcpy(buffer, recbuf, sizeof(recbuf)); - } - - - if ((0xAB != recbuf[9] ) || (recbuf[8] != ((recbuf[2] + recbuf[3] + recbuf[4] + recbuf[5] + recbuf[6] + recbuf[7]) & 0xFF))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); - return false; - } - - return true; -} - -void NovaSdsSetWorkPeriod(void) -{ - - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, 0, NOVA_SDS_DEVICE_ID, nullptr); - - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); -} - -bool NovaSdsReadData(void) -{ - uint8_t d[10]; - if ( ! NovaSdsCommand(NOVA_SDS_QUERY_DATA, 0, 0, NOVA_SDS_DEVICE_ID, d) ) { - return false; - } - novasds_data.pm25 = (d[2] + 256 * d[3]); - novasds_data.pm100 = (d[4] + 256 * d[5]); - - return true; -} - - - -void NovaSdsSecond(void) -{ - if (!novasds_valid) - { - NovaSdsSetWorkPeriod(); - novasds_valid=1; - } - if((Settings.tele_period - Settings.novasds_startingoffset <= 0)) - { - if(!cont_mode) - { - cont_mode = 1; - NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); - } - } - else - cont_mode = 0; - - if(tele_period == Settings.tele_period - Settings.novasds_startingoffset && !cont_mode) - { - NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); - } - if(tele_period >= Settings.tele_period-5 && tele_period <= Settings.tele_period-2) - { - if(!(NovaSdsReadData())) novasds_valid=0; - pm100_sum += novasds_data.pm100; - pm25_sum += novasds_data.pm25; - } - if(tele_period == Settings.tele_period-1) - { - novasds_data.pm100 = pm100_sum >> 2; - novasds_data.pm25 = pm25_sum >> 2; - if(!cont_mode) - NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_SLEEP, NOVA_SDS_DEVICE_ID, nullptr); - pm100_sum = pm25_sum = 0; - } -} - - - - - - - -bool NovaSdsCommandSensor(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { - if( XdrvMailbox.payload < 10 ) Settings.novasds_startingoffset = 10; - else Settings.novasds_startingoffset = XdrvMailbox.payload; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_startingoffset); - - return true; -} - -void NovaSdsInit(void) -{ - novasds_type = 0; - if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { - NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); - if (NovaSdsSerial->begin(9600)) { - if (NovaSdsSerial->hardwareSerial()) { - ClaimSerial(); - } - novasds_type = 1; - NovaSdsSetWorkPeriod(); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SDS0X1_SNS[] PROGMEM = - "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; -#endif - -void NovaSdsShow(bool json) -{ - if (novasds_valid) { - float pm10f = (float)(novasds_data.pm100) / 10.0f; - float pm2_5f = (float)(novasds_data.pm25) / 10.0f; - char pm10[33]; - dtostrfd(pm10f, 1, pm10); - char pm2_5[33]; - dtostrfd(pm2_5f, 1, pm2_5); - if (json) { - ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, pm2_5); - DomoticzSensor(DZ_CURRENT, pm10); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SDS0X1_SNS, pm2_5, pm10); -#endif - } - } -} - - - - - -bool Xsns20(uint8_t function) -{ - bool result = false; - - if (novasds_type) { - switch (function) { - case FUNC_INIT: - NovaSdsInit(); - break; - case FUNC_EVERY_SECOND: - NovaSdsSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_20 == XdrvMailbox.index) { - result = NovaSdsCommandSensor(); - } - break; - case FUNC_JSON_APPEND: - NovaSdsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - NovaSdsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_21_sgp30.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_21_sgp30.ino" -#ifdef USE_I2C -#ifdef USE_SGP30 -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_21_sgp30.ino" -#define XSNS_21 21 -#define XI2C_18 18 - -#define SGP30_ADDRESS 0x58 - -#include "Adafruit_SGP30.h" -Adafruit_SGP30 sgp; - -bool sgp30_type = false; -bool sgp30_ready = false; -float sgp30_abshum; - - - -void sgp30_Init(void) -{ - if (I2cActive(SGP30_ADDRESS)) { return; } - - if (sgp.begin()) { - sgp30_type = true; - - I2cSetActiveFound(SGP30_ADDRESS, "SGP30"); - } -} - - -#define POW_FUNC FastPrecisePow - -float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit) { - - - - - - float temp = NAN; - const float mw = 18.01534; - const float r = 8.31447215; - - if (isnan(temperature) || isnan(humidity) ) { - return NAN; - } - - if (tempUnit != 'C') { - temperature = (temperature - 32.0) * (5.0 / 9.0); - } - - temp = POW_FUNC(2.718281828, (17.67 * temperature) / (temperature + 243.5)); - - - return (6.112 * temp * humidity * mw) / ((273.15 + temperature) * r); -} - -#define SAVE_PERIOD 30 - -void Sgp30Update(void) -{ - sgp30_ready = false; - if (!sgp.IAQmeasure()) { - return; - } - if (global_update && (global_humidity > 0) && (global_temperature != 9999)) { - - sgp30_abshum=sgp30_AbsoluteHumidity(global_temperature,global_humidity,TempUnit()); - sgp.setHumidity(sgp30_abshum*1000); - } - sgp30_ready = true; - - - if (!(uptime%SAVE_PERIOD)) { - - uint16_t TVOC_base; - uint16_t eCO2_base; - - if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; - - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SGP30[] PROGMEM = - "{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" - "{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; -const char HTTP_SNS_AHUM[] PROGMEM = "{s}SGP30 Abs Humidity{m}%s g/m3{e}"; -#endif - -#define D_JSON_AHUM "aHumidity" - -void Sgp30Show(bool json) -{ - if (sgp30_ready) { - char abs_hum[33]; - - if (json) { - ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); - if (global_update && global_humidity>0 && global_temperature!=9999) { - - dtostrfd(sgp30_abshum,4,abs_hum); - ResponseAppend_P(PSTR(",\"" D_JSON_AHUM "\":%s"),abs_hum); - } - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC); - if (global_update) { - WSContentSend_PD(HTTP_SNS_AHUM, abs_hum); - } -#endif - } - } -} - - - - - -bool Xsns21(uint8_t function) -{ - if (!I2cEnabled(XI2C_18)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - sgp30_Init(); - } - else if (sgp30_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Sgp30Update(); - break; - case FUNC_JSON_APPEND: - Sgp30Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sgp30Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_22_sr04.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_22_sr04.ino" -#ifdef USE_SR04 - -#include -#include -# 32 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_22_sr04.ino" -#define XSNS_22 22 - -uint8_t sr04_type = 1; -int sr04_echo_pin = 0; -int sr04_trig_pin = 0; -real64_t distance; - -NewPing* sonar = nullptr; -TasmotaSerial* sonar_serial = nullptr; - - - -uint8_t Sr04TModeDetect(void) -{ - sr04_type = 0; - if (pin[GPIO_SR04_ECHO]>=99) return sr04_type; - - sr04_echo_pin = pin[GPIO_SR04_ECHO]; - sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : -1; - sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); - - if (sonar_serial->begin(9600,1)) { - DEBUG_SENSOR_LOG(PSTR("SR04: Detect mode")); - - if (sr04_trig_pin!=-1) { - sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance())!=NO_ECHO)?3:1; - } else { - sr04_type = 2; - } - } else { - sr04_type = 1; - } - - if (sr04_type < 2) { - delete sonar_serial; - sonar_serial = nullptr; - sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); - } else { - if (sonar_serial->hardwareSerial()) { - ClaimSerial(); - } - } - - AddLog_P2(LOG_LEVEL_INFO,PSTR("SR04: Mode %d"), sr04_type); - return sr04_type; -} - -uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) -{ - uint16_t ret = first; - if (first > second) { - first = second; - second = ret; - } - - if (third < first) { - return first; - } else if (third > second) { - return second; - } else { - return third; - } -} - -uint16_t Sr04TMode3Distance() { - - sonar_serial->write(0x55); - sonar_serial->flush(); - - return Sr04TMode2Distance(); -} - -uint16_t Sr04TMode2Distance(void) -{ - sonar_serial->setTimeout(300); - const char startByte = 0xff; - - if (!sonar_serial->find(startByte)) { - - return NO_ECHO; - } - - delay(5); - - uint8_t crc = sonar_serial->read(); - - uint16_t distance = ((uint16_t)crc) << 8; - - - distance += sonar_serial->read(); - crc += distance & 0x00ff; - crc += 0x00FF; - - - if (crc != sonar_serial->read()) { - AddLog_P2(LOG_LEVEL_ERROR,PSTR("SR04: Reading CRC error.")); - return NO_ECHO; - } - - return distance; -} - -void Sr04TReading(void) { - - if (sonar_serial==nullptr && sonar==nullptr) { - Sr04TModeDetect(); - } - - switch (sr04_type) { - case 3: - distance = (real64_t)(Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance()))/ 10; - break; - case 2: - - while(sonar_serial->available()) sonar_serial->read(); - distance = (real64_t)(Sr04TMiddleValue(Sr04TMode2Distance(),Sr04TMode2Distance(),Sr04TMode2Distance()))/10; - break; - case 1: - distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; - break; - default: - distance = NO_ECHO; - } - - return; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_DISTANCE[] PROGMEM = - "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; -#endif - -void Sr04Show(bool json) -{ - - if (distance != 0) { - char distance_chr[33]; - dtostrfd(distance, 3, distance_chr); - - if(json) { - ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_COUNT, distance_chr); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_DISTANCE, distance_chr); -#endif - } - } -} - - - - - -bool Xsns22(uint8_t function) -{ - bool result = false; - - if (sr04_type) { - switch (function) { - case FUNC_INIT: - result = (pin[GPIO_SR04_ECHO]<99); - break; - case FUNC_EVERY_SECOND: - Sr04TReading(); - result = true; - break; - case FUNC_JSON_APPEND: - Sr04Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sr04Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_24_si1145.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_24_si1145.ino" -#ifdef USE_I2C -#ifdef USE_SI1145 -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_24_si1145.ino" -#define XSNS_24 24 -#define XI2C_19 19 - -#define SI114X_ADDR 0X60 - - - -#define SI114X_QUERY 0X80 -#define SI114X_SET 0XA0 -#define SI114X_NOP 0X00 -#define SI114X_RESET 0X01 -#define SI114X_BUSADDR 0X02 -#define SI114X_PS_FORCE 0X05 -#define SI114X_GET_CAL 0X12 -#define SI114X_ALS_FORCE 0X06 -#define SI114X_PSALS_FORCE 0X07 -#define SI114X_PS_PAUSE 0X09 -#define SI114X_ALS_PAUSE 0X0A -#define SI114X_PSALS_PAUSE 0X0B -#define SI114X_PS_AUTO 0X0D -#define SI114X_ALS_AUTO 0X0E -#define SI114X_PSALS_AUTO 0X0F - - - -#define SI114X_PART_ID 0X00 -#define SI114X_REV_ID 0X01 -#define SI114X_SEQ_ID 0X02 -#define SI114X_INT_CFG 0X03 -#define SI114X_IRQ_ENABLE 0X04 -#define SI114X_IRQ_MODE1 0x05 -#define SI114X_IRQ_MODE2 0x06 -#define SI114X_HW_KEY 0X07 -#define SI114X_MEAS_RATE0 0X08 -#define SI114X_MEAS_RATE1 0X09 -#define SI114X_PS_RATE 0X0A -#define SI114X_PS_LED21 0X0F -#define SI114X_PS_LED3 0X10 -#define SI114X_UCOEFF0 0X13 -#define SI114X_UCOEFF1 0X14 -#define SI114X_UCOEFF2 0X15 -#define SI114X_UCOEFF3 0X16 -#define SI114X_WR 0X17 -#define SI114X_COMMAND 0X18 -#define SI114X_RESPONSE 0X20 -#define SI114X_IRQ_STATUS 0X21 -#define SI114X_ALS_VIS_DATA0 0X22 -#define SI114X_ALS_VIS_DATA1 0X23 -#define SI114X_ALS_IR_DATA0 0X24 -#define SI114X_ALS_IR_DATA1 0X25 -#define SI114X_PS1_DATA0 0X26 -#define SI114X_PS1_DATA1 0X27 -#define SI114X_PS2_DATA0 0X28 -#define SI114X_PS2_DATA1 0X29 -#define SI114X_PS3_DATA0 0X2A -#define SI114X_PS3_DATA1 0X2B -#define SI114X_AUX_DATA0_UVINDEX0 0X2C -#define SI114X_AUX_DATA1_UVINDEX1 0X2D -#define SI114X_RD 0X2E -#define SI114X_CHIP_STAT 0X30 - - - -#define SI114X_CHLIST 0X01 -#define SI114X_CHLIST_ENUV 0x80 -#define SI114X_CHLIST_ENAUX 0x40 -#define SI114X_CHLIST_ENALSIR 0x20 -#define SI114X_CHLIST_ENALSVIS 0x10 -#define SI114X_CHLIST_ENPS1 0x01 -#define SI114X_CHLIST_ENPS2 0x02 -#define SI114X_CHLIST_ENPS3 0x04 - -#define SI114X_PSLED12_SELECT 0X02 -#define SI114X_PSLED3_SELECT 0X03 - -#define SI114X_PS_ENCODE 0X05 -#define SI114X_ALS_ENCODE 0X06 - -#define SI114X_PS1_ADCMUX 0X07 -#define SI114X_PS2_ADCMUX 0X08 -#define SI114X_PS3_ADCMUX 0X09 - -#define SI114X_PS_ADC_COUNTER 0X0A -#define SI114X_PS_ADC_GAIN 0X0B -#define SI114X_PS_ADC_MISC 0X0C - -#define SI114X_ALS_IR_ADC_MUX 0X0E -#define SI114X_AUX_ADC_MUX 0X0F - -#define SI114X_ALS_VIS_ADC_COUNTER 0X10 -#define SI114X_ALS_VIS_ADC_GAIN 0X11 -#define SI114X_ALS_VIS_ADC_MISC 0X12 - -#define SI114X_LED_REC 0X1C - -#define SI114X_ALS_IR_ADC_COUNTER 0X1D -#define SI114X_ALS_IR_ADC_GAIN 0X1E -#define SI114X_ALS_IR_ADC_MISC 0X1F - - - - -#define SI114X_ADCMUX_SMALL_IR 0x00 -#define SI114X_ADCMUX_VISIABLE 0x02 -#define SI114X_ADCMUX_LARGE_IR 0x03 -#define SI114X_ADCMUX_NO 0x06 -#define SI114X_ADCMUX_GND 0x25 -#define SI114X_ADCMUX_TEMPERATURE 0x65 -#define SI114X_ADCMUX_VDD 0x75 - -#define SI114X_PSLED12_SELECT_PS1_NONE 0x00 -#define SI114X_PSLED12_SELECT_PS1_LED1 0x01 -#define SI114X_PSLED12_SELECT_PS1_LED2 0x02 -#define SI114X_PSLED12_SELECT_PS1_LED3 0x04 -#define SI114X_PSLED12_SELECT_PS2_NONE 0x00 -#define SI114X_PSLED12_SELECT_PS2_LED1 0x10 -#define SI114X_PSLED12_SELECT_PS2_LED2 0x20 -#define SI114X_PSLED12_SELECT_PS2_LED3 0x40 -#define SI114X_PSLED3_SELECT_PS2_NONE 0x00 -#define SI114X_PSLED3_SELECT_PS2_LED1 0x10 -#define SI114X_PSLED3_SELECT_PS2_LED2 0x20 -#define SI114X_PSLED3_SELECT_PS2_LED3 0x40 - -#define SI114X_ADC_GAIN_DIV1 0X00 -#define SI114X_ADC_GAIN_DIV2 0X01 -#define SI114X_ADC_GAIN_DIV4 0X02 -#define SI114X_ADC_GAIN_DIV8 0X03 -#define SI114X_ADC_GAIN_DIV16 0X04 -#define SI114X_ADC_GAIN_DIV32 0X05 - -#define SI114X_LED_CURRENT_5MA 0X01 -#define SI114X_LED_CURRENT_11MA 0X02 -#define SI114X_LED_CURRENT_22MA 0X03 -#define SI114X_LED_CURRENT_45MA 0X04 - -#define SI114X_ADC_COUNTER_1ADCCLK 0X00 -#define SI114X_ADC_COUNTER_7ADCCLK 0X01 -#define SI114X_ADC_COUNTER_15ADCCLK 0X02 -#define SI114X_ADC_COUNTER_31ADCCLK 0X03 -#define SI114X_ADC_COUNTER_63ADCCLK 0X04 -#define SI114X_ADC_COUNTER_127ADCCLK 0X05 -#define SI114X_ADC_COUNTER_255ADCCLK 0X06 -#define SI114X_ADC_COUNTER_511ADCCLK 0X07 - -#define SI114X_ADC_MISC_LOWRANGE 0X00 -#define SI114X_ADC_MISC_HIGHRANGE 0X20 -#define SI114X_ADC_MISC_ADC_NORMALPROXIMITY 0X00 -#define SI114X_ADC_MISC_ADC_RAWADC 0X04 - -#define SI114X_INT_CFG_INTOE 0X01 - -#define SI114X_IRQEN_ALS 0x01 -#define SI114X_IRQEN_PS1 0x04 -#define SI114X_IRQEN_PS2 0x08 -#define SI114X_IRQEN_PS3 0x10 - -uint16_t si1145_visible; -uint16_t si1145_infrared; -uint16_t si1145_uvindex; - -bool si1145_type = false; -uint8_t si1145_valid = 0; - - - -uint8_t Si1145ReadByte(uint8_t reg) -{ - return I2cRead8(SI114X_ADDR, reg); -} - -uint16_t Si1145ReadHalfWord(uint8_t reg) -{ - return I2cRead16LE(SI114X_ADDR, reg); -} - -bool Si1145WriteByte(uint8_t reg, uint16_t val) -{ - I2cWrite8(SI114X_ADDR, reg, val); -} - -uint8_t Si1145WriteParamData(uint8_t p, uint8_t v) -{ - Si1145WriteByte(SI114X_WR, v); - Si1145WriteByte(SI114X_COMMAND, p | SI114X_SET); - return Si1145ReadByte(SI114X_RD); -} - - - -bool Si1145Present(void) -{ - return (Si1145ReadByte(SI114X_PART_ID) == 0X45); -} - -void Si1145Reset(void) -{ - Si1145WriteByte(SI114X_MEAS_RATE0, 0); - Si1145WriteByte(SI114X_MEAS_RATE1, 0); - Si1145WriteByte(SI114X_IRQ_ENABLE, 0); - Si1145WriteByte(SI114X_IRQ_MODE1, 0); - Si1145WriteByte(SI114X_IRQ_MODE2, 0); - Si1145WriteByte(SI114X_INT_CFG, 0); - Si1145WriteByte(SI114X_IRQ_STATUS, 0xFF); - - Si1145WriteByte(SI114X_COMMAND, SI114X_RESET); - delay(10); - Si1145WriteByte(SI114X_HW_KEY, 0x17); - delay(10); -} - -void Si1145DeInit(void) -{ - - - Si1145WriteByte(SI114X_UCOEFF0, 0x29); - Si1145WriteByte(SI114X_UCOEFF1, 0x89); - Si1145WriteByte(SI114X_UCOEFF2, 0x02); - Si1145WriteByte(SI114X_UCOEFF3, 0x00); - Si1145WriteParamData(SI114X_CHLIST, SI114X_CHLIST_ENUV | SI114X_CHLIST_ENALSIR | SI114X_CHLIST_ENALSVIS | SI114X_CHLIST_ENPS1); - - - - Si1145WriteParamData(SI114X_PS1_ADCMUX, SI114X_ADCMUX_LARGE_IR); - Si1145WriteByte(SI114X_PS_LED21, SI114X_LED_CURRENT_22MA); - Si1145WriteParamData(SI114X_PSLED12_SELECT, SI114X_PSLED12_SELECT_PS1_LED1); - - - - Si1145WriteParamData(SI114X_PS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_PS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_PS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE | SI114X_ADC_MISC_ADC_RAWADC); - - - - Si1145WriteParamData(SI114X_ALS_VIS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_ALS_VIS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_ALS_VIS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); - - - - Si1145WriteParamData(SI114X_ALS_IR_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_ALS_IR_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_ALS_IR_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); - - - - Si1145WriteByte(SI114X_INT_CFG, SI114X_INT_CFG_INTOE); - Si1145WriteByte(SI114X_IRQ_ENABLE, SI114X_IRQEN_ALS); - - - - Si1145WriteByte(SI114X_MEAS_RATE0, 0xFF); - Si1145WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO); -} - -bool Si1145Begin(void) -{ - if (!Si1145Present()) { return false; } - - Si1145Reset(); - Si1145DeInit(); - return true; -} - - -uint16_t Si1145ReadUV(void) -{ - return Si1145ReadHalfWord(SI114X_AUX_DATA0_UVINDEX0); -} - - -uint16_t Si1145ReadVisible(void) -{ - return Si1145ReadHalfWord(SI114X_ALS_VIS_DATA0); -} - - -uint16_t Si1145ReadIR(void) -{ - return Si1145ReadHalfWord(SI114X_ALS_IR_DATA0); -} - - - -bool Si1145Read(void) -{ - if (si1145_valid) { si1145_valid--; } - - if (!Si1145Present()) { return false; } - - si1145_visible = Si1145ReadVisible(); - si1145_infrared = Si1145ReadIR(); - si1145_uvindex = Si1145ReadUV(); - si1145_valid = SENSOR_MAX_MISS; - return true; -} - -void Si1145Detect(void) -{ - if (I2cActive(SI114X_ADDR)) { return; } - - if (Si1145Begin()) { - si1145_type = true; - I2cSetActiveFound(SI114X_ADDR, "SI1145"); - } -} - -void Si1145Update(void) -{ - if (!Si1145Read()) { - AddLogMissed("SI1145", si1145_valid); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SI1145[] PROGMEM = - "{s}SI1145 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}" - "{s}SI1145 " D_INFRARED "{m}%d " D_UNIT_LUX "{e}" - "{s}SI1145 " D_UV_INDEX "{m}%d.%d{e}"; -#endif - -void Si1145Show(bool json) -{ - if (si1145_valid) { - if (json) { - ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), - si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, si1145_visible); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SI1145, si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); -#endif - } - } -} - - - - - -bool Xsns24(uint8_t function) -{ - if (!I2cEnabled(XI2C_19)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Si1145Detect(); - } - else if (si1145_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Si1145Update(); - break; - case FUNC_JSON_APPEND: - Si1145Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Si1145Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_26_lm75ad.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_26_lm75ad.ino" -#ifdef USE_I2C -#ifdef USE_LM75AD -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_26_lm75ad.ino" -#define XSNS_26 26 -#define XI2C_20 20 - -#define LM75AD_ADDRESS1 0x48 -#define LM75AD_ADDRESS2 0x49 -#define LM75AD_ADDRESS3 0x4A -#define LM75AD_ADDRESS4 0x4B -#define LM75AD_ADDRESS5 0x4C -#define LM75AD_ADDRESS6 0x4D -#define LM75AD_ADDRESS7 0x4E -#define LM75AD_ADDRESS8 0x4F - -#define LM75_TEMP_REGISTER 0x00 -#define LM75_CONF_REGISTER 0x01 -#define LM75_THYST_REGISTER 0x02 -#define LM75_TOS_REGISTER 0x03 - -bool lm75ad_type = false; -uint8_t lm75ad_address; -uint8_t lm75ad_addresses[] = { LM75AD_ADDRESS1, LM75AD_ADDRESS2, LM75AD_ADDRESS3, LM75AD_ADDRESS4, LM75AD_ADDRESS5, LM75AD_ADDRESS6, LM75AD_ADDRESS7, LM75AD_ADDRESS8 }; - -void LM75ADDetect(void) -{ - for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { - lm75ad_address = lm75ad_addresses[i]; - if (I2cActive(lm75ad_address)) { - continue; } - if (!I2cSetDevice(lm75ad_address)) { - break; - } - uint16_t buffer; - if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { - if (buffer == 0x4B00) { - lm75ad_type = true; - I2cSetActiveFound(lm75ad_address, "LM75AD"); - break; - } - } - } -} - -float LM75ADGetTemp(void) -{ - int16_t sign = 1; - - uint16_t t = I2cRead16(lm75ad_address, LM75_TEMP_REGISTER); - if (t & 0x8000) { - t = (~t) +0x20; - sign = -1; - } - t = t >> 5; - return ConvertTemp(sign * t * 0.125); -} - -void LM75ADShow(bool json) -{ - float t = LM75ADGetTemp(); - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(PSTR(",\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "LM75AD", temperature, TempUnit()); -#endif - } -} - - - - - -bool Xsns26(uint8_t function) -{ - if (!I2cEnabled(XI2C_20)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - LM75ADDetect(); - } - else if (lm75ad_type) { - switch (function) { - case FUNC_JSON_APPEND: - LM75ADShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - LM75ADShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -# 28 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -#ifdef USE_I2C -#ifdef USE_APDS9960 -# 39 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -#define XSNS_27 27 -#define XI2C_21 21 - -#if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) - #warning **** Turned off conflicting drivers SHT and VEML6070 **** - #ifdef USE_SHT - #undef USE_SHT - #endif - #ifdef USE_VEML6070 - #undef USE_VEML6070 - #endif - #ifdef USE_TSL2561 - #undef USE_TSL2561 - #endif -#endif - -#define APDS9960_I2C_ADDR 0x39 - -#define APDS9960_CHIPID_1 0xAB -#define APDS9960_CHIPID_2 0x9C - -#define APDS9930_CHIPID_1 0x12 -#define APDS9930_CHIPID_2 0x39 - - -#define GESTURE_THRESHOLD_OUT 10 -#define GESTURE_SENSITIVITY_1 50 -#define GESTURE_SENSITIVITY_2 20 - -uint8_t APDS9960addr; -uint8_t APDS9960type = 0; -char APDS9960stype[] = "APDS9960"; -char currentGesture[6]; -uint8_t gesture_mode = 1; - - -volatile uint8_t recovery_loop_counter = 0; -#define APDS9960_LONG_RECOVERY 50 -#define APDS9960_MAX_GESTURE_CYCLES 50 -bool APDS9960_overload = false; - -#ifdef USE_WEBSERVER -const char HTTP_APDS_9960_SNS[] PROGMEM = - "{s}" "Red" "{m}%s{e}" - "{s}" "Green" "{m}%s{e}" - "{s}" "Blue" "{m}%s{e}" - "{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" - "{s}" "CCT" "{m}%s " "K" "{e}" - "{s}" "Proximity" "{m}%s{e}"; -#endif -# 97 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -#define FIFO_PAUSE_TIME 30 - - -#define APDS9960_ENABLE 0x80 -#define APDS9960_ATIME 0x81 -#define APDS9960_WTIME 0x83 -#define APDS9960_AILTL 0x84 -#define APDS9960_AILTH 0x85 -#define APDS9960_AIHTL 0x86 -#define APDS9960_AIHTH 0x87 -#define APDS9960_PILT 0x89 -#define APDS9960_PIHT 0x8B -#define APDS9960_PERS 0x8C -#define APDS9960_CONFIG1 0x8D -#define APDS9960_PPULSE 0x8E -#define APDS9960_CONTROL 0x8F -#define APDS9960_CONFIG2 0x90 -#define APDS9960_ID 0x92 -#define APDS9960_STATUS 0x93 -#define APDS9960_CDATAL 0x94 -#define APDS9960_CDATAH 0x95 -#define APDS9960_RDATAL 0x96 -#define APDS9960_RDATAH 0x97 -#define APDS9960_GDATAL 0x98 -#define APDS9960_GDATAH 0x99 -#define APDS9960_BDATAL 0x9A -#define APDS9960_BDATAH 0x9B -#define APDS9960_PDATA 0x9C -#define APDS9960_POFFSET_UR 0x9D -#define APDS9960_POFFSET_DL 0x9E -#define APDS9960_CONFIG3 0x9F -#define APDS9960_GPENTH 0xA0 -#define APDS9960_GEXTH 0xA1 -#define APDS9960_GCONF1 0xA2 -#define APDS9960_GCONF2 0xA3 -#define APDS9960_GOFFSET_U 0xA4 -#define APDS9960_GOFFSET_D 0xA5 -#define APDS9960_GOFFSET_L 0xA7 -#define APDS9960_GOFFSET_R 0xA9 -#define APDS9960_GPULSE 0xA6 -#define APDS9960_GCONF3 0xAA -#define APDS9960_GCONF4 0xAB -#define APDS9960_GFLVL 0xAE -#define APDS9960_GSTATUS 0xAF -#define APDS9960_IFORCE 0xE4 -#define APDS9960_PICLEAR 0xE5 -#define APDS9960_CICLEAR 0xE6 -#define APDS9960_AICLEAR 0xE7 -#define APDS9960_GFIFO_U 0xFC -#define APDS9960_GFIFO_D 0xFD -#define APDS9960_GFIFO_L 0xFE -#define APDS9960_GFIFO_R 0xFF - - -#define APDS9960_PON 0b00000001 -#define APDS9960_AEN 0b00000010 -#define APDS9960_PEN 0b00000100 -#define APDS9960_WEN 0b00001000 -#define APSD9960_AIEN 0b00010000 -#define APDS9960_PIEN 0b00100000 -#define APDS9960_GEN 0b01000000 -#define APDS9960_GVALID 0b00000001 - - -#define OFF 0 -#define ON 1 - - -#define POWER 0 -#define AMBIENT_LIGHT 1 -#define PROXIMITY 2 -#define WAIT 3 -#define AMBIENT_LIGHT_INT 4 -#define PROXIMITY_INT 5 -#define GESTURE 6 -#define ALL 7 - - -#define LED_DRIVE_100MA 0 -#define LED_DRIVE_50MA 1 -#define LED_DRIVE_25MA 2 -#define LED_DRIVE_12_5MA 3 - - -#define PGAIN_1X 0 -#define PGAIN_2X 1 -#define PGAIN_4X 2 -#define PGAIN_8X 3 - - -#define AGAIN_1X 0 -#define AGAIN_4X 1 -#define AGAIN_16X 2 -#define AGAIN_64X 3 - - -#define GGAIN_1X 0 -#define GGAIN_2X 1 -#define GGAIN_4X 2 -#define GGAIN_8X 3 - - -#define LED_BOOST_100 0 -#define LED_BOOST_150 1 -#define LED_BOOST_200 2 -#define LED_BOOST_300 3 - - -#define GWTIME_0MS 0 -#define GWTIME_2_8MS 1 -#define GWTIME_5_6MS 2 -#define GWTIME_8_4MS 3 -#define GWTIME_14_0MS 4 -#define GWTIME_22_4MS 5 -#define GWTIME_30_8MS 6 -#define GWTIME_39_2MS 7 - - -#define DEFAULT_ATIME 0xdb -#define DEFAULT_WTIME 246 -#define DEFAULT_PROX_PPULSE 0x87 -#define DEFAULT_GESTURE_PPULSE 0x89 -#define DEFAULT_POFFSET_UR 0 -#define DEFAULT_POFFSET_DL 0 -#define DEFAULT_CONFIG1 0x60 -#define DEFAULT_LDRIVE LED_DRIVE_100MA -#define DEFAULT_PGAIN PGAIN_4X -#define DEFAULT_AGAIN AGAIN_4X -#define DEFAULT_PILT 0 -#define DEFAULT_PIHT 50 -#define DEFAULT_AILT 0xFFFF -#define DEFAULT_AIHT 0 -#define DEFAULT_PERS 0x11 -#define DEFAULT_CONFIG2 0x01 -#define DEFAULT_CONFIG3 0 -#define DEFAULT_GPENTH 40 -#define DEFAULT_GEXTH 30 -#define DEFAULT_GCONF1 0x40 -#define DEFAULT_GGAIN GGAIN_4X -#define DEFAULT_GLDRIVE LED_DRIVE_100MA -#define DEFAULT_GWTIME GWTIME_2_8MS -#define DEFAULT_GOFFSET 0 -#define DEFAULT_GPULSE 0xC9 -#define DEFAULT_GCONF3 0 -#define DEFAULT_GIEN 0 - -#define ERROR 0xFF - - -enum { - DIR_NONE, - DIR_LEFT, - DIR_RIGHT, - DIR_UP, - DIR_DOWN, - DIR_ALL -}; - - -enum { - APDS9960_NA_STATE, - APDS9960_ALL_STATE -}; - - -typedef struct gesture_data_type { - uint8_t u_data[32]; - uint8_t d_data[32]; - uint8_t l_data[32]; - uint8_t r_data[32]; - uint8_t index; - uint8_t total_gestures; - uint8_t in_threshold; - uint8_t out_threshold; -} gesture_data_type; - - - gesture_data_type gesture_data_; - int16_t gesture_ud_delta_ = 0; - int16_t gesture_lr_delta_ = 0; - int16_t gesture_ud_count_ = 0; - int16_t gesture_lr_count_ = 0; - int16_t gesture_state_ = 0; - int16_t gesture_motion_ = DIR_NONE; - - typedef struct color_data_type { - uint16_t a; - uint16_t r; - uint16_t g; - uint16_t b; - uint8_t p; - uint16_t cct; - uint16_t lux; - } color_data_type; - - color_data_type color_data; - uint8_t APDS9960_aTime = DEFAULT_ATIME; -# 306 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - bool wireWriteByte(uint8_t val) - { - Wire.beginTransmission(APDS9960_I2C_ADDR); - Wire.write(val); - if( Wire.endTransmission() != 0 ) { - return false; - } - - return true; - } -# 325 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -int8_t wireReadDataBlock( uint8_t reg, - uint8_t *val, - uint16_t len) -{ - unsigned char i = 0; - - - if (!wireWriteByte(reg)) { - return -1; - } - - - Wire.requestFrom(APDS9960_I2C_ADDR, len); - while (Wire.available()) { - if (i >= len) { - return -1; - } - val[i] = Wire.read(); - i++; - } - - return i; -} - - - - - - - -void calculateColorTemperature(void) -{ - float X, Y, Z; - float xc, yc; - float n; - float cct; - - - - - - X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b); - Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); - Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b); - - - xc = (X) / (X + Y + Z); - yc = (Y) / (X + Y + Z); - - - n = (xc - 0.3320F) / (0.1858F - yc); - - - color_data.cct = (449.0F * FastPrecisePowf(n, 3)) + (3525.0F * FastPrecisePowf(n, 2)) + (6823.3F * n) + 5520.33F; - - return; -} -# 392 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getProxIntLowThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT) ; - return val; - } - - - - - - - void setProxIntLowThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); - } - - - - - - - uint8_t getProxIntHighThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; - return val; - } - - - - - - - - void setProxIntHighThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); - } -# 448 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getLEDDrive(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; - - val = (val >> 6) & 0b00000011; - - return val; - } -# 471 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void setLEDDrive(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - drive = drive << 6; - val &= 0b00111111; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 500 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getProximityGain(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; - - val = (val >> 2) & 0b00000011; - - return val; - } -# 523 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void setProximityGain(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - drive = drive << 2; - val &= 0b11110011; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 564 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void setAmbientLightGain(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - val &= 0b11111100; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 591 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getLEDBoost(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; - - - val = (val >> 4) & 0b00000011; - - return val; - } -# 615 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void setLEDBoost(uint8_t boost) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; - - boost &= 0b00000011; - boost = boost << 4; - val &= 0b11001111; - val |= boost; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, val) ; - } - - - - - - - uint8_t getProxGainCompEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - val = (val >> 5) & 0b00000001; - - return val; - } - - - - - - - void setProxGainCompEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - enable &= 0b00000001; - enable = enable << 5; - val &= 0b11011111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; - } -# 683 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getProxPhotoMask(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - val &= 0b00001111; - - return val; - } -# 708 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void setProxPhotoMask(uint8_t mask) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - mask &= 0b00001111; - val &= 0b11110000; - val |= mask; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; - } - - - - - - - uint8_t getGestureEnterThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH) ; - - return val; - } - - - - - - - void setGestureEnterThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold) ; - - } - - - - - - - uint8_t getGestureExitThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GEXTH) ; - - return val; - } - - - - - - - void setGestureExitThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold) ; - } -# 786 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getGestureGain(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val = (val >> 5) & 0b00000011; - - return val; - } -# 810 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void setGestureGain(uint8_t gain) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - gain &= 0b00000011; - gain = gain << 5; - val &= 0b10011111; - val |= gain; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } -# 838 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getGestureLEDDrive(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val = (val >> 3) & 0b00000011; - - return val; - } -# 862 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void setGestureLEDDrive(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - drive &= 0b00000011; - drive = drive << 3; - val &= 0b11100111; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } -# 894 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getGestureWaitTime(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val &= 0b00000111; - - return val; - } -# 922 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void setGestureWaitTime(uint8_t time) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - time &= 0b00000111; - val &= 0b11111000; - val |= time; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } - - - - - - - void getLightIntLowThreshold(uint16_t &threshold) - { - uint8_t val_byte; - threshold = 0; - - - val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AILTL) ; - threshold = val_byte; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_byte) ; - threshold = threshold + ((uint16_t)val_byte << 8); - } - - - - - - - - void setLightIntLowThreshold(uint16_t threshold) - { - uint8_t val_low; - uint8_t val_high; - - - val_low = threshold & 0x00FF; - val_high = (threshold & 0xFF00) >> 8; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTL, val_low) ; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_high) ; - - } - - - - - - - - void getLightIntHighThreshold(uint16_t &threshold) - { - uint8_t val_byte; - threshold = 0; - - - val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AIHTL); - threshold = val_byte; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_byte) ; - threshold = threshold + ((uint16_t)val_byte << 8); - } - - - - - - - void setLightIntHighThreshold(uint16_t threshold) - { - uint8_t val_low; - uint8_t val_high; - - - val_low = threshold & 0x00FF; - val_high = (threshold & 0xFF00) >> 8; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTL, val_low); - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_high) ; - } - - - - - - - - void getProximityIntLowThreshold(uint8_t &threshold) - { - threshold = 0; - - - threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); - - } - - - - - - - void setProximityIntLowThreshold(uint8_t threshold) - { - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold) ; - } -# 1055 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" - void getProximityIntHighThreshold(uint8_t &threshold) - { - threshold = 0; - - - threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; - - } - - - - - - - void setProximityIntHighThreshold(uint8_t threshold) - { - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold) ; - } - - - - - - - uint8_t getAmbientLightIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - val = (val >> 4) & 0b00000001; - - return val; - } - - - - - - - void setAmbientLightIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); - - - enable &= 0b00000001; - enable = enable << 4; - val &= 0b11101111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; - } - - - - - - - uint8_t getProximityIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - val = (val >> 5) & 0b00000001; - - return val; - } - - - - - - - void setProximityIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - enable &= 0b00000001; - enable = enable << 5; - val &= 0b11011111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; - } - - - - - - - uint8_t getGestureIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - val = (val >> 1) & 0b00000001; - - return val; - } - - - - - - - void setGestureIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - enable &= 0b00000001; - enable = enable << 1; - val &= 0b11111101; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; - } - - - - - - void clearAmbientLightInt(void) - { - uint8_t throwaway; - throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); - } - - - - - - void clearProximityInt(void) - { - uint8_t throwaway; - throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR) ; - - } - - - - - - - uint8_t getGestureMode(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - val &= 0b00000001; - - return val; - } - - - - - - - void setGestureMode(uint8_t mode) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - mode &= 0b00000001; - val &= 0b11111110; - val |= mode; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; - } - - -bool APDS9960_init(void) -{ - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, DEFAULT_WTIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG1, DEFAULT_CONFIG1) ; - - setLEDDrive(DEFAULT_LDRIVE); - - setProximityGain(DEFAULT_PGAIN); - - setAmbientLightGain(DEFAULT_AGAIN); - - setProxIntLowThresh(DEFAULT_PILT) ; - - setProxIntHighThresh(DEFAULT_PIHT); - - setLightIntLowThreshold(DEFAULT_AILT) ; - - setLightIntHighThreshold(DEFAULT_AIHT) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PERS, DEFAULT_PERS) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, DEFAULT_CONFIG2) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3) ; - - - setGestureEnterThresh(DEFAULT_GPENTH); - - setGestureExitThresh(DEFAULT_GEXTH) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF1, DEFAULT_GCONF1) ; - - setGestureGain(DEFAULT_GGAIN) ; - - setGestureLEDDrive(DEFAULT_GLDRIVE) ; - - setGestureWaitTime(DEFAULT_GWTIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPULSE, DEFAULT_GPULSE) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3) ; - - setGestureIntEnable(DEFAULT_GIEN); - - disablePower(); - - return true; -} -# 1333 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getMode(void) -{ - uint8_t enable_value; - - - enable_value = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - return enable_value; -} - - - - - - - -void setMode(uint8_t mode, uint8_t enable) -{ - uint8_t reg_val; - - - reg_val = getMode(); - - - - enable = enable & 0x01; - if( mode >= 0 && mode <= 6 ) { - if (enable) { - reg_val |= (1 << mode); - } else { - reg_val &= ~(1 << mode); - } - } else if( mode == ALL ) { - if (enable) { - reg_val = 0x7F; - } else { - reg_val = 0x00; - } - } - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, reg_val) ; -} - - - - - - -void enableLightSensor(void) -{ - - setAmbientLightGain(DEFAULT_AGAIN); - setAmbientLightIntEnable(0); - enablePower() ; - setMode(AMBIENT_LIGHT, 1) ; -} - - - - - -void disableLightSensor(void) -{ - setAmbientLightIntEnable(0) ; - setMode(AMBIENT_LIGHT, 0) ; -} - - - - - - -void enableProximitySensor(void) -{ - - setProximityGain(DEFAULT_PGAIN); - setLEDDrive(DEFAULT_LDRIVE) ; - setProximityIntEnable(0) ; - enablePower(); - setMode(PROXIMITY, 1) ; -} - - - - - -void disableProximitySensor(void) -{ - setProximityIntEnable(0) ; - setMode(PROXIMITY, 0) ; -} - - - - - - -void enableGestureSensor(void) -{ - - - - - - - - resetGestureParameters(); - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ; - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ; - setLEDBoost(LED_BOOST_100); - setGestureIntEnable(0) ; - setGestureMode(1); - enablePower() ; - setMode(WAIT, 1) ; - setMode(PROXIMITY, 1) ; - setMode(GESTURE, 1); -} - - - - - -void disableGestureSensor(void) -{ - resetGestureParameters(); - setGestureIntEnable(0) ; - setGestureMode(0) ; - setMode(GESTURE, 0) ; -} - - - - - - -bool isGestureAvailable(void) -{ - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS) ; - - - val &= APDS9960_GVALID; - - - if( val == 1) { - return true; - } else { - return false; - } -} - - - - - - -int16_t readGesture(void) -{ - uint8_t fifo_level = 0; - uint8_t bytes_read = 0; - uint8_t fifo_data[128]; - uint8_t gstatus; - uint16_t motion; - uint16_t i; - uint8_t gesture_loop_counter = 0; - - - if( !isGestureAvailable() || !(getMode() & 0b01000001) ) { - return DIR_NONE; - } - - - while(1) { - if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ - disableGestureSensor(); - APDS9960_overload = true; - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); - } - gesture_loop_counter += 1; - - delay(FIFO_PAUSE_TIME); - - - gstatus = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); - - - if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { - - - fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ; - - - if( fifo_level > 0) { - bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, - (uint8_t*)fifo_data, - (fifo_level * 4) ); - if( bytes_read == -1 ) { - return ERROR; - } - - - if( bytes_read >= 4 ) { - for( i = 0; i < bytes_read; i += 4 ) { - gesture_data_.u_data[gesture_data_.index] = \ - fifo_data[i + 0]; - gesture_data_.d_data[gesture_data_.index] = \ - fifo_data[i + 1]; - gesture_data_.l_data[gesture_data_.index] = \ - fifo_data[i + 2]; - gesture_data_.r_data[gesture_data_.index] = \ - fifo_data[i + 3]; - gesture_data_.index++; - gesture_data_.total_gestures++; - } - - if( processGestureData() ) { - if( decodeGesture() ) { - - } - } - - gesture_data_.index = 0; - gesture_data_.total_gestures = 0; - } - } - } else { - - - delay(FIFO_PAUSE_TIME); - decodeGesture(); - motion = gesture_motion_; - resetGestureParameters(); - return motion; - } - } -} - - - - - -void enablePower(void) -{ - setMode(POWER, 1) ; -} - - - - - -void disablePower(void) -{ - setMode(POWER, 0) ; -} -# 1600 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -void readAllColorAndProximityData(void) -{ - if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) - { - - - } -} -# 1616 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -void resetGestureParameters(void) -{ - gesture_data_.index = 0; - gesture_data_.total_gestures = 0; - - gesture_ud_delta_ = 0; - gesture_lr_delta_ = 0; - - gesture_ud_count_ = 0; - gesture_lr_count_ = 0; - - gesture_state_ = 0; - gesture_motion_ = DIR_NONE; -} - - - - - - -bool processGestureData(void) -{ - uint8_t u_first = 0; - uint8_t d_first = 0; - uint8_t l_first = 0; - uint8_t r_first = 0; - uint8_t u_last = 0; - uint8_t d_last = 0; - uint8_t l_last = 0; - uint8_t r_last = 0; - uint16_t ud_ratio_first; - uint16_t lr_ratio_first; - uint16_t ud_ratio_last; - uint16_t lr_ratio_last; - uint16_t ud_delta; - uint16_t lr_delta; - uint16_t i; - - - if( gesture_data_.total_gestures <= 4 ) { - return false; - } - - - if( (gesture_data_.total_gestures <= 32) && \ - (gesture_data_.total_gestures > 0) ) { - - - for( i = 0; i < gesture_data_.total_gestures; i++ ) { - if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { - - u_first = gesture_data_.u_data[i]; - d_first = gesture_data_.d_data[i]; - l_first = gesture_data_.l_data[i]; - r_first = gesture_data_.r_data[i]; - break; - } - } - - - if( (u_first == 0) || (d_first == 0) || \ - (l_first == 0) || (r_first == 0) ) { - - return false; - } - - for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { - - if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { - - u_last = gesture_data_.u_data[i]; - d_last = gesture_data_.d_data[i]; - l_last = gesture_data_.l_data[i]; - r_last = gesture_data_.r_data[i]; - break; - } - } - } - - - ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); - lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); - ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); - lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); - - - ud_delta = ud_ratio_last - ud_ratio_first; - lr_delta = lr_ratio_last - lr_ratio_first; - - - gesture_ud_delta_ += ud_delta; - gesture_lr_delta_ += lr_delta; - - - if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { - gesture_ud_count_ = 1; - } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { - gesture_ud_count_ = -1; - } else { - gesture_ud_count_ = 0; - } - - - if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { - gesture_lr_count_ = 1; - } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { - gesture_lr_count_ = -1; - } else { - gesture_lr_count_ = 0; - } - return false; -} - - - - - - -bool decodeGesture(void) -{ - - - if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { - gesture_motion_ = DIR_UP; - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { - gesture_motion_ = DIR_DOWN; - } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { - gesture_motion_ = DIR_RIGHT; - } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { - gesture_motion_ = DIR_LEFT; - } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_UP; - } else { - gesture_motion_ = DIR_RIGHT; - } - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_DOWN; - } else { - gesture_motion_ = DIR_LEFT; - } - } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_UP; - } else { - gesture_motion_ = DIR_LEFT; - } - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_DOWN; - } else { - gesture_motion_ = DIR_RIGHT; - } - } else { - return false; - } - - return true; -} - -void handleGesture(void) { - if (isGestureAvailable() ) { - switch (readGesture()) { - case DIR_UP: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("UP")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Up")); - break; - case DIR_DOWN: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("DOWN")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Down")); - break; - case DIR_LEFT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("LEFT")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); - break; - case DIR_RIGHT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("RIGHT")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); - break; - default: - if(APDS9960_overload) - { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); - } - else{ - AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); - } - } - MqttPublishSensor(); - } -} - -void APDS9960_adjustATime(void) -{ - - I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); - - - if (color_data.a < (uint16_t)20){ - APDS9960_aTime = 0x40; - } - else if (color_data.a < (uint16_t)40){ - APDS9960_aTime = 0x80; - } - else if (color_data.a < (uint16_t)50){ - APDS9960_aTime = DEFAULT_ATIME; - } - else if (color_data.a < (uint16_t)70){ - APDS9960_aTime = 0xc0; - } - if (color_data.a < 200){ - APDS9960_aTime = 0xe9; - } - - - - else{ - APDS9960_aTime = 0xff; - } - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime); - enablePower(); - enableLightSensor(); - delay(20); -} - - -void APDS9960_loop(void) -{ - if (recovery_loop_counter > 0){ - recovery_loop_counter -= 1; - } - if (recovery_loop_counter == 1 && APDS9960_overload){ - enableGestureSensor(); - APDS9960_overload = false; - Response_P(PSTR("{\"Gesture\":\"On\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - gesture_mode = 1; - } - - if (gesture_mode) { - if (recovery_loop_counter == 0){ - handleGesture(); - - if (APDS9960_overload) - { - disableGestureSensor(); - recovery_loop_counter = APDS9960_LONG_RECOVERY; - Response_P(PSTR("{\"Gesture\":\"Off\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - gesture_mode = 0; - } - } - } -} - -void APDS9960_detect(void) -{ - if (APDS9960type || I2cActive(APDS9960_I2C_ADDR)) { return; } - - APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); - if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2) { - if (APDS9960_init()) { - I2cSetActiveFound(APDS9960_I2C_ADDR, APDS9960stype); - - enableProximitySensor(); - enableGestureSensor(); - } else { - APDS9960type = 0; - } - } else { - APDS9960type = 0; - } - currentGesture[0] = '\0'; -} - - - - - -void APDS9960_show(bool json) -{ - if (!APDS9960type) { return; } - - if (!gesture_mode && !APDS9960_overload) { - char red_chr[10]; - char green_chr[10]; - char blue_chr[10]; - char ambient_chr[10]; - char cct_chr[10]; - char prox_chr[10]; - - readAllColorAndProximityData(); - - sprintf (ambient_chr, "%u", color_data.a/4); - sprintf (red_chr, "%u", color_data.r); - sprintf (green_chr, "%u", color_data.g); - sprintf (blue_chr, "%u", color_data.b ); - sprintf (prox_chr, "%u", color_data.p ); - - - - - - calculateColorTemperature(); - sprintf (cct_chr, "%u", color_data.cct); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), - APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); -#endif - } - } - else { - if (json && (currentGesture[0] != '\0' )) { - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); - currentGesture[0] = '\0'; - } - } -} -# 1961 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_27_apds9960.ino" -bool APDS9960CommandSensor(void) -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - disableGestureSensor(); - gesture_mode = 0; - enableLightSensor(); - APDS9960_overload = false; - break; - case 1: - if (APDS9960type) { - setGestureGain(DEFAULT_GGAIN); - setProximityGain(DEFAULT_PGAIN); - disableLightSensor(); - enableGestureSensor(); - gesture_mode = 1; - } - break; - case 2: - if (APDS9960type) { - setGestureGain(GGAIN_2X); - setProximityGain(PGAIN_2X); - disableLightSensor(); - enableGestureSensor(); - gesture_mode = 1; - } - break; - default: - int temp_aTime = (uint8_t)XdrvMailbox.payload; - if (temp_aTime > 2 && temp_aTime < 256){ - disablePower(); - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, temp_aTime); - enablePower(); - enableLightSensor(); - } - break; - } - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); - - return serviced; -} - - - - - -bool Xsns27(uint8_t function) -{ - if (!I2cEnabled(XI2C_21)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - APDS9960_detect(); - } - else if (APDS9960type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - APDS9960_loop(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_27 == XdrvMailbox.index) { - result = APDS9960CommandSensor(); - } - break; - case FUNC_JSON_APPEND: - APDS9960_show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - APDS9960_show(0); - break; -#endif - } - } - return result; -} -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_28_tm1638.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_28_tm1638.ino" -#ifdef USE_TM1638 - - - - - - -#define XSNS_28 28 - -#define TM1638_COLOR_NONE 0 -#define TM1638_COLOR_RED 1 -#define TM1638_COLOR_GREEN 2 - -#define TM1638_CLOCK_DELAY 1 - -uint8_t tm1638_type = 1; -uint8_t tm1638_clock_pin = 0; -uint8_t tm1638_data_pin = 0; -uint8_t tm1638_strobe_pin = 0; -uint8_t tm1638_displays = 8; -uint8_t tm1638_active_display = 1; -uint8_t tm1638_intensity = 0; -uint8_t tm1638_state = 0; - - - - - - -void Tm16XXSend(uint8_t data) -{ - for (uint32_t i = 0; i < 8; i++) { - digitalWrite(tm1638_data_pin, !!(data & (1 << i))); - digitalWrite(tm1638_clock_pin, LOW); - delayMicroseconds(TM1638_CLOCK_DELAY); - digitalWrite(tm1638_clock_pin, HIGH); - } -} - -void Tm16XXSendCommand(uint8_t cmd) -{ - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(cmd); - digitalWrite(tm1638_strobe_pin, HIGH); -} - -void TM16XXSendData(uint8_t address, uint8_t data) -{ - Tm16XXSendCommand(0x44); - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0xC0 | address); - Tm16XXSend(data); - digitalWrite(tm1638_strobe_pin, HIGH); -} - -uint8_t Tm16XXReceive(void) -{ - uint8_t temp = 0; - - - pinMode(tm1638_data_pin, INPUT); - digitalWrite(tm1638_data_pin, HIGH); - - for (uint32_t i = 0; i < 8; ++i) { - digitalWrite(tm1638_clock_pin, LOW); - delayMicroseconds(TM1638_CLOCK_DELAY); - temp |= digitalRead(tm1638_data_pin) << i; - digitalWrite(tm1638_clock_pin, HIGH); - } - - - pinMode(tm1638_data_pin, OUTPUT); - digitalWrite(tm1638_data_pin, LOW); - - return temp; -} - - - -void Tm16XXClearDisplay(void) -{ - for (uint32_t i = 0; i < tm1638_displays; i++) { - TM16XXSendData(i << 1, 0); - } -} - -void Tm1638SetLED(uint8_t color, uint8_t pos) -{ - TM16XXSendData((pos << 1) + 1, color); -} - -void Tm1638SetLEDs(word leds) -{ - for (uint32_t i = 0; i < tm1638_displays; i++) { - uint8_t color = 0; - - if ((leds & (1 << i)) != 0) { - color |= TM1638_COLOR_RED; - } - - if ((leds & (1 << (i + 8))) != 0) { - color |= TM1638_COLOR_GREEN; - } - - Tm1638SetLED(color, i); - } -} - -uint8_t Tm1638GetButtons(void) -{ - uint8_t keys = 0; - - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0x42); - for (uint32_t i = 0; i < 4; i++) { - keys |= Tm16XXReceive() << i; - } - digitalWrite(tm1638_strobe_pin, HIGH); - - return keys; -} - - - -void TmInit(void) -{ - tm1638_type = 0; - if ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99)) { - tm1638_clock_pin = pin[GPIO_TM16CLK]; - tm1638_data_pin = pin[GPIO_TM16DIO]; - tm1638_strobe_pin = pin[GPIO_TM16STB]; - - pinMode(tm1638_data_pin, OUTPUT); - pinMode(tm1638_clock_pin, OUTPUT); - pinMode(tm1638_strobe_pin, OUTPUT); - - digitalWrite(tm1638_strobe_pin, HIGH); - digitalWrite(tm1638_clock_pin, HIGH); - - Tm16XXSendCommand(0x40); - Tm16XXSendCommand(0x80 | (tm1638_active_display ? 8 : 0) | tmin(7, tm1638_intensity)); - - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0xC0); - for (uint32_t i = 0; i < 16; i++) { - Tm16XXSend(0x00); - } - digitalWrite(tm1638_strobe_pin, HIGH); - - tm1638_type = 1; - tm1638_state = 1; - } -} - -void TmLoop(void) -{ - if (tm1638_state) { - uint8_t buttons = Tm1638GetButtons(); - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - SwitchSetVirtual(i, (buttons &1) ^1); - uint8_t color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; - Tm1638SetLED(color, i); - buttons >>= 1; - } - SwitchHandler(1); - } -} -# 201 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_28_tm1638.ino" -bool Xsns28(uint8_t function) -{ - bool result = false; - - if (tm1638_type) { - switch (function) { - case FUNC_INIT: - TmInit(); - break; - case FUNC_EVERY_50_MSECOND: - TmLoop(); - break; -# 223 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_28_tm1638.ino" - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_29_mcp230xx.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_29_mcp230xx.ino" -#ifdef USE_I2C -#ifdef USE_MCP230xx -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_29_mcp230xx.ino" -#define XSNS_29 29 -#define XI2C_22 22 - - - - - -uint8_t MCP230xx_IODIR = 0x00; -uint8_t MCP230xx_GPINTEN = 0x02; -uint8_t MCP230xx_IOCON = 0x05; -uint8_t MCP230xx_GPPU = 0x06; -uint8_t MCP230xx_INTF = 0x07; -uint8_t MCP230xx_INTCAP = 0x08; -uint8_t MCP230xx_GPIO = 0x09; - -uint8_t mcp230xx_type = 0; -uint8_t mcp230xx_pincount = 0; -uint8_t mcp230xx_int_en = 0; -uint8_t mcp230xx_int_prio_counter = 0; -uint8_t mcp230xx_int_counter_en = 0; -uint8_t mcp230xx_int_retainer_en = 0; -uint8_t mcp230xx_int_sec_counter = 0; - -uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -uint8_t mcp230xx_int_retainer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -unsigned long int_millis[16]; - -const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL_UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; - -const char MCP230XX_INTCFG_RESPONSE[] PROGMEM = "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; - -#ifdef USE_MCP230xx_OUTPUT -const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; -#endif - -void MCP230xx_CheckForIntCounter(void) { - uint8_t en = 0; - for (uint32_t ca=0;ca<16;ca++) { - if (Settings.mcp230xx_config[ca].int_count_en) { - en=1; - } - } - if (!Settings.mcp230xx_int_timer) en=0; - mcp230xx_int_counter_en=en; - if (!mcp230xx_int_counter_en) { - for (uint32_t ca=0;ca<16;ca++) { - mcp230xx_int_counter[ca] = 0; - } - } -} - -void MCP230xx_CheckForIntRetainer(void) { - uint8_t en = 0; - for (uint32_t ca=0;ca<16;ca++) { - if (Settings.mcp230xx_config[ca].int_retain_flag) { - en=1; - } - } - mcp230xx_int_retainer_en=en; - if (!mcp230xx_int_retainer_en) { - for (uint32_t ca=0;ca<16;ca++) { - mcp230xx_int_retainer[ca] = 0; - } - } -} - -const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { -#ifdef USE_MCP230xx_OUTPUT -if ((6 == pinmod) && (statu < 2)) { statu = abs(statu-1); } -#endif - switch (statu) { - case 0: - return "OFF"; - break; - case 1: - return "ON"; - break; -#ifdef USE_MCP230xx_OUTPUT - case 2: - return "TOGGLE"; - break; -#endif - } - return ""; -} - -const char* IntModeTxt(uint8_t intmo) { - switch (intmo) { - case 0: - return "ALL"; - break; - case 1: - return "EVENT"; - break; - case 2: - return "TELE"; - break; - case 3: - return "DISABLED"; - break; - } - return ""; -} - -uint8_t MCP230xx_readGPIO(uint8_t port) { - return I2cRead8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port); -} - -void MCP230xx_ApplySettings(void) -{ - uint8_t int_en = 0; - for (uint32_t mcp230xx_port = 0; mcp230xx_port < mcp230xx_type; mcp230xx_port++) { - uint8_t reg_gppu = 0; - uint8_t reg_gpinten = 0; - uint8_t reg_iodir = 0xFF; -#ifdef USE_MCP230xx_OUTPUT - uint8_t reg_portpins = 0x00; -#endif - for (uint32_t idx = 0; idx < 8; idx++) { - switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { - case 0 ... 1: - reg_iodir |= (1 << idx); - break; - case 2 ... 4: - reg_iodir |= (1 << idx); - reg_gpinten |= (1 << idx); - int_en = 1; - break; -#ifdef USE_MCP230xx_OUTPUT - case 5 ... 6: - reg_iodir &= ~(1 << idx); - if (Settings.flag.save_state) { - reg_portpins |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); - } else { - if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { - reg_portpins |= (1 << idx); - } - } - break; -#endif - default: - break; - } -#ifdef USE_MCP230xx_OUTPUT - if ((Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { - reg_gppu |= (1 << idx); - } -#else - if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { - reg_gppu |= (1 << idx); - } -#endif - } - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPPU+mcp230xx_port, reg_gppu); - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IODIR+mcp230xx_port, reg_iodir); -#ifdef USE_MCP230xx_OUTPUT - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); -#endif - } - for (uint32_t idx=0;idx 0) { - if (I2cValidRead8(&mcp230xx_intcap, USE_MCP230xx_ADDR, MCP230xx_INTCAP+mcp230xx_port)) { - for (uint32_t intp = 0; intp < 8; intp++) { - if ((intf >> intp) & 0x01) { - report_int = 0; - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode > 1) { - switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode) { - case 2: - report_int = 1; - break; - case 3: - if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; - break; - case 4: - if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; - break; - default: - break; - } - - if ((mcp230xx_int_counter_en) && (report_int)) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { - mcp230xx_int_counter[intp+(mcp230xx_port*8)]++; - } - } - - if (report_int) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { - mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]++; - if (mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)] >= Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { - mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]=0; - } else { - report_int = 0; - } - } - } - - if (report_int) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_retain_flag) { - mcp230xx_int_retainer[intp+(mcp230xx_port*8)] = 1; - report_int = 0; - } - } - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { - report_int = 0; - } - if (report_int) { - bool int_tele = false; - bool int_event = false; - unsigned long millis_now = millis(); - unsigned long millis_since_last_int = millis_now - int_millis[intp+(mcp230xx_port*8)]; - int_millis[intp+(mcp230xx_port*8)]=millis_now; - switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_mode) { - case 0: - int_tele=true; - int_event=true; - break; - case 1: - int_event=true; - break; - case 2: - int_tele=true; - break; - } - if (int_tele) { - ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), - intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); - } - if (int_event) { - char command[19]; - sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); - ExecuteCommand(command, SRC_RULE); - } - } - } - } - } - } - } - } - } -} - -void MCP230xx_Show(bool json) -{ - if (json) { - uint8_t gpio = MCP230xx_readGPIO(0); - ResponseAppend_P(PSTR(",\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), - (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); - if (2 == mcp230xx_type) { - gpio = MCP230xx_readGPIO(1); - ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), - (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); - } - ResponseJsonEnd(); - } -} - -#ifdef USE_MCP230xx_OUTPUT - -void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { - uint8_t portpins; - uint8_t port = 0; - uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; - uint8_t interlock = Settings.flag.interlock; - int pinadd = (pin % 2)+1-(3*(pin % 2)); - char cmnd[7], stt[4]; - if (pin > 7) { port = 1; } - portpins = MCP230xx_readGPIO(port); - if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { - if (pinstate < 2) { - if (6 == pinmo) { - if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins |= (1 << (pin+pinadd-(port*8))),portpins &= ~(1 << (pin-(port*8))); - } else { - if (pinstate) portpins &= ~(1 << (pin+pinadd-(port*8))),portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); - } - } else { - if (6 == pinmo) { - portpins |= (1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); - } else { - portpins &= ~(1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); - } - } - } else { - if (pinstate < 2) { - if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); - } else { - portpins ^= (1 << (pin-(port*8))); - } - } - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port, portpins); - if (Settings.flag.save_state) { - Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; - Settings.mcp230xx_config[pin+pinadd].saved_state=portpins>>(pin+pinadd-(port*8))&1; - } - sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); - sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); - if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { - char stt1[4]; - sprintf(stt1,ConvertNumTxt((portpins >> (pin+pinadd-(port*8))&1), pinmo)); - Response_P(PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); - } else { - Response_P(MCP230XX_CMND_RESPONSE, pin, cmnd, stt); - } -} - -#endif - -void MCP230xx_Reset(uint8_t pinmode) { - uint8_t pullup = 0; - if ((pinmode > 1) && (pinmode < 5)) { pullup=1; } - for (uint32_t pinx=0;pinx<16;pinx++) { - Settings.mcp230xx_config[pinx].pinmode=pinmode; - Settings.mcp230xx_config[pinx].pullup=pullup; - Settings.mcp230xx_config[pinx].saved_state=0; - if ((pinmode > 1) && (pinmode < 5)) { - Settings.mcp230xx_config[pinx].int_report_mode=0; - } else { - Settings.mcp230xx_config[pinx].int_report_mode=3; - } - Settings.mcp230xx_config[pinx].int_report_defer=0; - Settings.mcp230xx_config[pinx].int_count_en=0; - Settings.mcp230xx_config[pinx].int_retain_flag=0; - Settings.mcp230xx_config[pinx].spare13=0; - Settings.mcp230xx_config[pinx].spare14=0; - Settings.mcp230xx_config[pinx].spare15=0; - } - Settings.mcp230xx_int_prio = 0; - Settings.mcp230xx_int_timer = 0; - MCP230xx_ApplySettings(); - char pulluptxt[7]; - char intmodetxt[9]; - sprintf(pulluptxt,ConvertNumTxt(pullup)); - uint8_t intmode = 3; - if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } - sprintf(intmodetxt,IntModeTxt(intmode)); - Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); -} - -bool MCP230xx_Command(void) -{ - bool serviced = true; - bool validpin = false; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((intpri >= 0) && (intpri <= 20)) { - Settings.mcp230xx_int_prio = intpri; - Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTTIMER")) { - if (paramcount > 1) { - uint8_t inttim = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((inttim >= 0) && (inttim <= 3600)) { - Settings.mcp230xx_int_timer = inttim; - MCP230xx_CheckForIntCounter(); - Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTDEF")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t intdef = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((intdef >= 0) && (intdef <= 15)) { - Settings.mcp230xx_config[pin].int_report_defer=intdef; - if (Settings.mcp230xx_config[pin].int_count_en) { - Settings.mcp230xx_config[pin].int_count_en=0; - MCP230xx_CheckForIntCounter(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); - } - Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTCNT")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t intcnt = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((intcnt >= 0) && (intcnt <= 1)) { - Settings.mcp230xx_config[pin].int_count_en=intcnt; - if (Settings.mcp230xx_config[pin].int_report_defer) { - Settings.mcp230xx_config[pin].int_report_defer=0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTDEF for pin D%i"),pin); - } - if (Settings.mcp230xx_config[pin].int_report_mode < 3) { - Settings.mcp230xx_config[pin].int_report_mode=3; - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled immediate interrupt/telemetry reporting for pin D%i"),pin); - } - if ((Settings.mcp230xx_config[pin].int_count_en) && (!Settings.mcp230xx_int_timer)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); - } - MCP230xx_CheckForIntCounter(); - Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTRETAIN")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((int_retain >= 0) && (int_retain <= 1)) { - Settings.mcp230xx_config[pin].int_retain_flag=int_retain; - Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); - MCP230xx_CheckForIntRetainer(); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - - if (pin < mcp230xx_pincount) { - if (0 == pin) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "0")) validpin=true; - } else { - validpin=true; - } - } - if (validpin && (paramcount > 1)) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "?")) { - uint8_t port = 0; - if (pin > 7) { port = 1; } - uint8_t portdata = MCP230xx_readGPIO(port); - char pulluptxtr[7],pinstatustxtr[7]; - char intmodetxt[9]; - sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); - sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); -#ifdef USE_MCP230xx_OUTPUT - uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; - sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); - Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); -#else - sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); - Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); -#endif - return serviced; - } -#ifdef USE_MCP230xx_OUTPUT - if (Settings.mcp230xx_config[pin].pinmode >= 5) { - uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "1"))) { - MCP230xx_SetOutPin(pin,abs(pincmd-1)); - return serviced; - } - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0"))) { - MCP230xx_SetOutPin(pin,pincmd); - return serviced; - } - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "2"))) { - MCP230xx_SetOutPin(pin,2); - return serviced; - } - } -#endif - uint8_t pinmode = 0; - uint8_t pullup = 0; - uint8_t intmode = 0; - if (paramcount > 1) { - pinmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - } - if (paramcount > 2) { - pullup = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - } - if (paramcount > 3) { - intmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - } -#ifdef USE_MCP230xx_OUTPUT - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2) && (paramcount > 2)) { -#else - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 2)) { -#endif - Settings.mcp230xx_config[pin].pinmode=pinmode; - Settings.mcp230xx_config[pin].pullup=pullup; - if ((pinmode > 1) && (pinmode < 5)) { - if ((intmode >= 0) && (intmode <= 3)) { - Settings.mcp230xx_config[pin].int_report_mode=intmode; - } - } else { - Settings.mcp230xx_config[pin].int_report_mode=3; - } - MCP230xx_ApplySettings(); - uint8_t port = 0; - if (pin > 7) { port = 1; } - uint8_t portdata = MCP230xx_readGPIO(port); - char pulluptxtc[7], pinstatustxtc[7]; - char intmodetxt[9]; - sprintf(pulluptxtc,ConvertNumTxt(pullup)); - sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); -#ifdef USE_MCP230xx_OUTPUT - sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); -#else - sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); -#endif - Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); - return serviced; - } - } else { - serviced=false; - return serviced; - } - return serviced; -} - -#ifdef USE_MCP230xx_DISPLAYOUTPUT - -const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; - -void MCP230xx_UpdateWebData(void) -{ - uint8_t gpio1 = MCP230xx_readGPIO(0); - uint8_t gpio2 = 0; - if (2 == mcp230xx_type) { - gpio2 = MCP230xx_readGPIO(1); - } - uint16_t gpio = (gpio2 << 8) + gpio1; - for (uint32_t pin = 0; pin < mcp230xx_pincount; pin++) { - if (Settings.mcp230xx_config[pin].pinmode >= 5) { - char stt[7]; - sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); - WSContentSend_PD(HTTP_SNS_MCP230xx_OUTPUT, pin, stt); - } - } -} - -#endif - -#ifdef USE_MCP230xx_OUTPUT - -void MCP230xx_OutputTelemetry(void) -{ - uint8_t outputcount = 0; - uint16_t gpiototal = 0; - uint8_t gpioa = 0; - uint8_t gpiob = 0; - gpioa=MCP230xx_readGPIO(0); - if (2 == mcp230xx_type) { gpiob=MCP230xx_readGPIO(1); } - gpiototal=((uint16_t)gpiob << 8) | gpioa; - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; - } - if (outputcount) { - char stt[7]; - ResponseTime_P(PSTR(",\"MCP230_OUT\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode >= 5) { - sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); - ResponseAppend_P(PSTR("\"OUT_D%i\":\"%s\","),pinx,stt); - } - } - ResponseAppend_P(PSTR("\"END\":1}}")); - MqttPublishTeleSensor(); - } -} - -#endif - -void MCP230xx_Interrupt_Counter_Report(void) { - ResponseTime_P(PSTR(",\"MCP230_INTTIMER\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].int_count_en) { - ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); - mcp230xx_int_counter[pinx]=0; - } - } - ResponseAppend_P(PSTR("\"END\":1}}")); - MqttPublishTeleSensor(); - mcp230xx_int_sec_counter = 0; -} - -void MCP230xx_Interrupt_Retain_Report(void) { - uint16_t retainresult = 0; - ResponseTime_P(PSTR(",\"MCP_INTRETAIN\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].int_retain_flag) { - ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); - retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); - mcp230xx_int_retainer[pinx]=0; - } - } - ResponseAppend_P(PSTR("\"Value\":%u}}"),retainresult); - MqttPublishTeleSensor(); -} - - - - - -bool Xsns29(uint8_t function) -{ - if (!I2cEnabled(XI2C_22)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MCP230xx_Detect(); - } - else if (mcp230xx_type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (mcp230xx_int_en) { - mcp230xx_int_prio_counter++; - if ((mcp230xx_int_prio_counter) >= (Settings.mcp230xx_int_prio)) { - MCP230xx_CheckForInterrupt(); - mcp230xx_int_prio_counter=0; - } - } - break; - case FUNC_EVERY_SECOND: - if (mcp230xx_int_counter_en) { - mcp230xx_int_sec_counter++; - if (mcp230xx_int_sec_counter >= Settings.mcp230xx_int_timer) { - MCP230xx_Interrupt_Counter_Report(); - } - } - if (tele_period == 0) { - if (mcp230xx_int_retainer_en) { - MCP230xx_Interrupt_Retain_Report(); - } -#ifdef USE_MCP230xx_OUTPUT - MCP230xx_OutputTelemetry(); -#endif - } - break; - case FUNC_JSON_APPEND: - MCP230xx_Show(1); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_29 == XdrvMailbox.index) { - result = MCP230xx_Command(); - } - break; -#ifdef USE_WEBSERVER -#ifdef USE_MCP230xx_OUTPUT -#ifdef USE_MCP230xx_DISPLAYOUTPUT - case FUNC_WEB_SENSOR: - MCP230xx_UpdateWebData(); - break; -#endif -#endif -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" -# 46 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" -#ifdef USE_I2C -#ifdef USE_MPR121 - - - - - -#define XSNS_30 30 -#define XI2C_23 23 - - - - - - - -#define MPR121_ELEX_REG 0x00 - - -#define MPR121_MHDR_REG 0x2B - - -#define MPR121_MHDR_VAL 0x01 - - -#define MPR121_NHDR_REG 0x2C - - -#define MPR121_NHDR_VAL 0x01 - - -#define MPR121_NCLR_REG 0x2D - - -#define MPR121_NCLR_VAL 0x0E - - -#define MPR121_MHDF_REG 0x2F - - -#define MPR121_MHDF_VAL 0x01 - - -#define MPR121_NHDF_REG 0x30 - - -#define MPR121_NHDF_VAL 0x05 - - -#define MPR121_NCLF_REG 0x31 - - -#define MPR121_NCLF_VAL 0x01 - - -#define MPR121_MHDPROXR_REG 0x36 - - -#define MPR121_MHDPROXR_VAL 0x3F - - -#define MPR121_NHDPROXR_REG 0x37 - - -#define MPR121_NHDPROXR_VAL 0x5F - - -#define MPR121_NCLPROXR_REG 0x38 - - -#define MPR121_NCLPROXR_VAL 0x04 - - -#define MPR121_FDLPROXR_REG 0x39 - - -#define MPR121_FDLPROXR_VAL 0x00 - - -#define MPR121_MHDPROXF_REG 0x3A - - -#define MPR121_MHDPROXF_VAL 0x01 - - -#define MPR121_NHDPROXF_REG 0x3B - - -#define MPR121_NHDPROXF_VAL 0x01 - - -#define MPR121_NCLPROXF_REG 0x3C - - -#define MPR121_NCLPROXF_VAL 0x1F - - -#define MPR121_FDLPROXF_REG 0x3D - - -#define MPR121_FDLPROXF_VAL 0x04 - - -#define MPR121_E0TTH_REG 0x41 - - -#define MPR121_E0TTH_VAL 12 - - -#define MPR121_E0RTH_REG 0x42 - - -#define MPR121_E0RTH_VAL 6 - - -#define MPR121_CDT_REG 0x5D - - -#define MPR121_CDT_VAL 0x20 - - -#define MPR121_ECR_REG 0x5E - - -#define MPR121_ECR_VAL 0x8F - - - -#define MPR121_SRST_REG 0x80 - - -#define MPR121_SRST_VAL 0x63 - - -#define BITC(sensor,position) ((pS->current[sensor] >> position) & 1) - - -#define BITP(sensor,position) ((pS->previous[sensor] >> position) & 1) -# 195 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" -typedef struct mpr121 mpr121; -struct mpr121 { - const uint8_t i2c_addr[4] = { 0x5A, 0x5B, 0x5C, 0x5D }; - const char id[4] = { 'A', 'B', 'C', 'D' }; - bool connected[4] = { false, false, false, false }; - bool running[4] = { false, false, false, false }; - uint16_t current[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; - uint16_t previous[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; -}; - -bool mpr21_found = false; -# 217 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" -void Mpr121Init(struct mpr121 *pS, bool initial) -{ - - for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { - - if (initial && I2cActive(pS->i2c_addr[i])) { continue; } - - - pS->connected[i] = (I2cWrite8(pS->i2c_addr[i], MPR121_SRST_REG, MPR121_SRST_VAL) - && (0x24 == I2cRead8(pS->i2c_addr[i], 0x5D))); - if (pS->connected[i]) { - - - mpr21_found = true; - char device_name[16]; - snprintf_P(device_name, sizeof(device_name), PSTR("MPR121(%c)"), pS->id[i]); - I2cSetActiveFound(pS->i2c_addr[i], device_name); - - - for (uint32_t j = 0; j < 13; j++) { - - - I2cWrite8(pS->i2c_addr[i], MPR121_E0TTH_REG + 2 * j, MPR121_E0TTH_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_E0RTH_REG + 2 * j, MPR121_E0RTH_VAL); - } - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDR_REG, MPR121_MHDR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDR_REG, MPR121_NHDR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLR_REG, MPR121_NCLR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDF_REG, MPR121_MHDF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDF_REG, MPR121_NHDF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLF_REG, MPR121_NCLF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXR_REG, MPR121_MHDPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXR_REG, MPR121_NHDPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXR_REG, MPR121_NCLPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXR_REG, MPR121_FDLPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXF_REG, MPR121_MHDPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXF_REG, MPR121_NHDPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXF_REG, MPR121_NCLPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXF_REG, MPR121_FDLPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_CDT_REG, MPR121_CDT_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_ECR_REG, MPR121_ECR_VAL); - - - pS->running[i] = (0x00 != I2cRead8(pS->i2c_addr[i], MPR121_ECR_REG)); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121%c: %sRunning"), pS->id[i], (pS->running[i]) ? "" : "NOT"); - - } else { - - - pS->running[i] = false; - } - } - - - if (!(pS->connected[0] || pS->connected[1] || pS->connected[2] - || pS->connected[3])) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C "MPR121: No sensors found")); - } -} -# 326 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" -void Mpr121Show(struct mpr121 *pS, uint8_t function) -{ - - - for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { - - - if (pS->connected[i]) { - - - if (!I2cValidRead16LE(&pS->current[i], pS->i2c_addr[i], MPR121_ELEX_REG)) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]); - Mpr121Init(pS, false); - return; - } - - if (BITC(i, 15)) { - - - I2cWrite8(pS->i2c_addr[i], MPR121_ELEX_REG, 0x00); - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]); - Mpr121Init(pS, false); - return; - } - } - - if (pS->running[i]) { - - - if (FUNC_JSON_APPEND == function) { - ResponseAppend_P(PSTR(",\"MPR121%c\":{"), pS->id[i]); - } - - for (uint32_t j = 0; j < 13; j++) { - - - if ((FUNC_EVERY_50_MSECOND == function) - && (BITC(i, j) != BITP(i, j))) { - Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); - } - -#ifdef USE_WEBSERVER - if (FUNC_WEB_SENSOR == function) { - WSContentSend_PD(PSTR("{s}MPR121%c Button%d{m}%d{e}"), pS->id[i], j, BITC(i, j)); - } -#endif - - - if (FUNC_JSON_APPEND == function) { - ResponseAppend_P(PSTR("%s\"Button%i\":%i"), (j > 0 ? "," : ""), j, BITC(i, j)); - } - } - - - pS->previous[i] = pS->current[i]; - - - if (FUNC_JSON_APPEND == function) { - ResponseJsonEnd(); - } - } - } -} -# 410 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_30_mpr121.ino" -bool Xsns30(uint8_t function) -{ - if (!I2cEnabled(XI2C_23)) { return false; } - - bool result = false; - - - static struct mpr121 mpr121; - - if (FUNC_INIT == function) { - - Mpr121Init(&mpr121, true); - } - else if (mpr21_found) { - - switch (function) { - - - case FUNC_EVERY_50_MSECOND: - Mpr121Show(&mpr121, FUNC_EVERY_50_MSECOND); - break; - - - case FUNC_JSON_APPEND: - Mpr121Show(&mpr121, FUNC_JSON_APPEND); - break; - -#ifdef USE_WEBSERVER - - case FUNC_WEB_SENSOR: - Mpr121Show(&mpr121, FUNC_WEB_SENSOR); - break; -#endif - } - } - - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_31_ccs811.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_31_ccs811.ino" -#ifdef USE_I2C -#ifdef USE_CCS811 -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_31_ccs811.ino" -#define XSNS_31 31 -#define XI2C_24 24 - -#define EVERYNSECONDS 5 - -#include "Adafruit_CCS811.h" - -Adafruit_CCS811 ccs; -uint8_t CCS811_ready = 0; -uint8_t CCS811_type = 0;; -uint16_t eCO2; -uint16_t TVOC; -uint8_t tcnt = 0; -uint8_t ecnt = 0; - - - -void CCS811Detect(void) -{ - if (I2cActive(CCS811_ADDRESS)) { return; } - - if (!ccs.begin(CCS811_ADDRESS)) { - CCS811_type = 1; - I2cSetActiveFound(CCS811_ADDRESS, "CCS811"); - } -} - -void CCS811Update(void) -{ - tcnt++; - if (tcnt >= EVERYNSECONDS) { - tcnt = 0; - CCS811_ready = 0; - if (ccs.available()) { - if (!ccs.readData()){ - TVOC = ccs.getTVOC(); - eCO2 = ccs.geteCO2(); - CCS811_ready = 1; - if (global_update && global_humidity>0 && global_temperature!=9999) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); } - ecnt = 0; - } - } else { - - ecnt++; - if (ecnt > 6) { - - ccs.begin(CCS811_ADDRESS); - } - } - } -} - -const char HTTP_SNS_CCS811[] PROGMEM = - "{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" - "{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; - -void CCS811Show(bool json) -{ - if (CCS811_ready) { - if (json) { - ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CCS811, eCO2, TVOC); -#endif - } - } -} - - - - - -bool Xsns31(uint8_t function) -{ - if (!I2cEnabled(XI2C_24)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - CCS811Detect(); - } - else if (CCS811_type) { - switch (function) { - case FUNC_EVERY_SECOND: - CCS811Update(); - break; - case FUNC_JSON_APPEND: - CCS811Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - CCS811Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_32_mpu6050.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_32_mpu6050.ino" -#ifdef USE_I2C -#ifdef USE_MPU6050 -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_32_mpu6050.ino" -#define XSNS_32 32 -#define XI2C_25 25 - -#define D_SENSOR_MPU6050 "MPU6050" - -#define MPU_6050_ADDR_AD0_LOW 0x68 -#define MPU_6050_ADDR_AD0_HIGH 0x69 - -uint8_t MPU_6050_address; -uint8_t MPU_6050_addresses[] = { MPU_6050_ADDR_AD0_LOW, MPU_6050_ADDR_AD0_HIGH }; -uint8_t MPU_6050_found; - -int16_t MPU_6050_ax = 0, MPU_6050_ay = 0, MPU_6050_az = 0; -int16_t MPU_6050_gx = 0, MPU_6050_gy = 0, MPU_6050_gz = 0; -int16_t MPU_6050_temperature = 0; - -#ifdef USE_MPU6050_DMP - #include "MPU6050_6Axis_MotionApps20.h" - #include "I2Cdev.h" - #include - typedef struct MPU6050_DMP{ - uint8_t devStatus; - uint16_t packetSize; - uint16_t fifoCount; - uint8_t fifoBuffer[64]; - Quaternion q; - VectorInt16 aa; - VectorInt16 aaReal; - VectorFloat gravity; - float euler[3]; - float yawPitchRoll[3]; - } MPU6050_DMP; - - MPU6050_DMP MPU6050_dmp; -#else - #include -#endif -MPU6050 mpu6050; - -void MPU_6050PerformReading(void) -{ -#ifdef USE_MPU6050_DMP - mpu6050.resetFIFO(); - MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); - while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); - mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); - MPU6050_dmp.fifoCount -= MPU6050_dmp.packetSize; - - mpu6050.dmpGetQuaternion(&MPU6050_dmp.q, MPU6050_dmp.fifoBuffer); - mpu6050.dmpGetEuler(MPU6050_dmp.euler, &MPU6050_dmp.q); - mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); - mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); - mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); - mpu6050.dmpGetYawPitchRoll(MPU6050_dmp.yawPitchRoll, &MPU6050_dmp.q, &MPU6050_dmp.gravity); - MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; - MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; - MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; - MPU_6050_ax = MPU6050_dmp.aaReal.x; - MPU_6050_ay = MPU6050_dmp.aaReal.y; - MPU_6050_az = MPU6050_dmp.aaReal.z; -#else - mpu6050.getMotion6( - &MPU_6050_ax, - &MPU_6050_ay, - &MPU_6050_az, - &MPU_6050_gx, - &MPU_6050_gy, - &MPU_6050_gz - ); -#endif - MPU_6050_temperature = mpu6050.getTemperature(); -} -# 119 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_32_mpu6050.ino" -void MPU_6050Detect(void) -{ - for (uint32_t i = 0; i < sizeof(MPU_6050_addresses); i++) - { - MPU_6050_address = MPU_6050_addresses[i]; - if (!I2cSetDevice(MPU_6050_address)) { break; } - mpu6050.setAddr(MPU_6050_addresses[i]); - -#ifdef USE_MPU6050_DMP - MPU6050_dmp.devStatus = mpu6050.dmpInitialize(); - mpu6050.setXGyroOffset(220); - mpu6050.setYGyroOffset(76); - mpu6050.setZGyroOffset(-85); - mpu6050.setZAccelOffset(1788); - if (MPU6050_dmp.devStatus == 0) { - mpu6050.setDMPEnabled(true); - MPU6050_dmp.packetSize = mpu6050.dmpGetFIFOPacketSize(); - MPU_6050_found = true; - } -#else - mpu6050.initialize(); - MPU_6050_found = mpu6050.testConnection(); -#endif - Settings.flag2.axis_resolution = 2; - } - - if (MPU_6050_found) { - I2cSetActiveFound(MPU_6050_address, D_SENSOR_MPU6050); - } -} - -#define D_YAW "Yaw" -#define D_PITCH "Pitch" -#define D_ROLL "Roll" - -#ifdef USE_WEBSERVER -const char HTTP_SNS_AXIS[] PROGMEM = - "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_AY_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; -#ifdef USE_MPU6050_DMP -const char HTTP_SNS_YPR[] PROGMEM = - "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}"; -#endif -#endif - -#define D_JSON_AXIS_AX "AccelXAxis" -#define D_JSON_AXIS_AY "AccelYAxis" -#define D_JSON_AXIS_AZ "AccelZAxis" -#define D_JSON_AXIS_GX "GyroXAxis" -#define D_JSON_AXIS_GY "GyroYAxis" -#define D_JSON_AXIS_GZ "GyroZAxis" -#define D_JSON_YAW "Yaw" -#define D_JSON_PITCH "Pitch" -#define D_JSON_ROLL "Roll" - -void MPU_6050Show(bool json) -{ - MPU_6050PerformReading(); - - double tempConv = (MPU_6050_temperature / 340.0 + 35.53); - char temperature[33]; - dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature); - char axis_ax[33]; - dtostrfd(MPU_6050_ax, Settings.flag2.axis_resolution, axis_ax); - char axis_ay[33]; - dtostrfd(MPU_6050_ay, Settings.flag2.axis_resolution, axis_ay); - char axis_az[33]; - dtostrfd(MPU_6050_az, Settings.flag2.axis_resolution, axis_az); - char axis_gx[33]; - dtostrfd(MPU_6050_gx, Settings.flag2.axis_resolution, axis_gx); - char axis_gy[33]; - dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); - char axis_gz[33]; - dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); -#ifdef USE_MPU6050_DMP - char axis_yaw[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[0] / PI * 180.0, Settings.flag2.axis_resolution, axis_yaw); - char axis_pitch[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[1] / PI * 180.0, Settings.flag2.axis_resolution, axis_pitch); - char axis_roll[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[2] / PI * 180.0, Settings.flag2.axis_resolution, axis_roll); -#endif - - if (json) { - char json_axis_ax[25]; - snprintf_P(json_axis_ax, sizeof(json_axis_ax), PSTR(",\"" D_JSON_AXIS_AX "\":%s"), axis_ax); - char json_axis_ay[25]; - snprintf_P(json_axis_ay, sizeof(json_axis_ay), PSTR(",\"" D_JSON_AXIS_AY "\":%s"), axis_ay); - char json_axis_az[25]; - snprintf_P(json_axis_az, sizeof(json_axis_az), PSTR(",\"" D_JSON_AXIS_AZ "\":%s"), axis_az); - char json_axis_gx[25]; - snprintf_P(json_axis_gx, sizeof(json_axis_gx), PSTR(",\"" D_JSON_AXIS_GX "\":%s"), axis_gx); - char json_axis_gy[25]; - snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); - char json_axis_gz[25]; - snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); -#ifdef USE_MPU6050_DMP - char json_ypr_y[25]; - snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), axis_yaw); - char json_ypr_p[25]; - snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), axis_pitch); - char json_ypr_r[25]; - snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), axis_roll); - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s%s%s%s}"), - D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz, - json_ypr_y, json_ypr_p, json_ypr_r); -#else - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), - D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); -#endif -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); -#ifdef USE_MPU6050_DMP - WSContentSend_PD(HTTP_SNS_YPR, axis_yaw, axis_pitch, axis_roll); -#endif -#endif - } -} - - - - - -bool Xsns32(uint8_t function) -{ - if (!I2cEnabled(XI2C_25)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MPU_6050Detect(); - } - else if (MPU_6050_found) { - switch (function) { - case FUNC_EVERY_SECOND: - if (tele_period == Settings.tele_period -3) { - MPU_6050PerformReading(); - } - break; - case FUNC_JSON_APPEND: - MPU_6050Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MPU_6050Show(0); - MPU_6050PerformReading(); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_33_ds3231.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_33_ds3231.ino" -#ifdef USE_I2C -#ifdef USE_DS3231 -# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_33_ds3231.ino" -#define XSNS_33 33 -#define XI2C_26 26 - - -#ifndef USE_RTC_ADDR -#define USE_RTC_ADDR 0x68 -#endif - - -#define RTC_SECONDS 0x00 -#define RTC_MINUTES 0x01 -#define RTC_HOURS 0x02 -#define RTC_DAY 0x03 -#define RTC_DATE 0x04 -#define RTC_MONTH 0x05 -#define RTC_YEAR 0x06 -#define RTC_CONTROL 0x0E -#define RTC_STATUS 0x0F - -#define OSF 7 -#define EOSC 7 -#define BBSQW 6 -#define CONV 5 -#define RS2 4 -#define RS1 3 -#define INTCN 2 - - -#define HR1224 6 -#define CENTURY 7 -#define DYDT 6 -bool ds3231ReadStatus = false; -bool ds3231WriteStatus = false; -bool DS3231chipDetected = false; - - - - -void DS3231Detect(void) -{ - if (I2cActive(USE_RTC_ADDR)) { return; } - - if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { - I2cSetActiveFound(USE_RTC_ADDR, "DS3231"); - DS3231chipDetected = true; - } -} - - - - -uint8_t bcd2dec(uint8_t n) -{ - return n - 6 * (n >> 4); -} - - - - -uint8_t dec2bcd(uint8_t n) -{ - return n + 6 * (n / 10); -} - - - - -uint32_t ReadFromDS3231(void) -{ - TIME_T tm; - tm.second = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_SECONDS)); - tm.minute = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MINUTES)); - tm.hour = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_HOURS) & ~_BV(HR1224)); - tm.day_of_week = I2cRead8(USE_RTC_ADDR, RTC_DAY); - tm.day_of_month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_DATE)); - tm.month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MONTH) & ~_BV(CENTURY)); - tm.year = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_YEAR)); - return MakeTime(tm); -} - - - -void SetDS3231Time (uint32_t epoch_time) { - TIME_T tm; - BreakTime(epoch_time, tm); - I2cWrite8(USE_RTC_ADDR, RTC_SECONDS, dec2bcd(tm.second)); - I2cWrite8(USE_RTC_ADDR, RTC_MINUTES, dec2bcd(tm.minute)); - I2cWrite8(USE_RTC_ADDR, RTC_HOURS, dec2bcd(tm.hour)); - I2cWrite8(USE_RTC_ADDR, RTC_DAY, tm.day_of_week); - I2cWrite8(USE_RTC_ADDR, RTC_DATE, dec2bcd(tm.day_of_month)); - I2cWrite8(USE_RTC_ADDR, RTC_MONTH, dec2bcd(tm.month)); - I2cWrite8(USE_RTC_ADDR, RTC_YEAR, dec2bcd(tm.year)); - I2cWrite8(USE_RTC_ADDR, RTC_STATUS, I2cRead8(USE_RTC_ADDR, RTC_STATUS) & ~_BV(OSF)); -} - -void DS3231EverySecond(void) -{ - TIME_T tmpTime; - if (!ds3231ReadStatus && Rtc.utc_time < START_VALID_TIME ) { - ntp_force_sync = true; - Rtc.utc_time = ReadFromDS3231(); - - - BreakTime(Rtc.utc_time, tmpTime); - if (Rtc.utc_time < START_VALID_TIME ) { - ds3231ReadStatus = true; - } - RtcTime.year = tmpTime.year + 1970; - Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); - Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - if (Rtc.local_time < START_VALID_TIME) { - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } - else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); - SetDS3231Time (Rtc.utc_time); - ds3231WriteStatus = true; - } -} - - - - - -bool Xsns33(uint8_t function) -{ - if (!I2cEnabled(XI2C_26)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - DS3231Detect(); - } - else if (DS3231chipDetected) { - switch (function) { - case FUNC_EVERY_SECOND: - DS3231EverySecond(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_34_hx711.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_34_hx711.ino" -#ifdef USE_HX711 -# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_34_hx711.ino" -#define XSNS_34 34 - -#ifndef HX_MAX_WEIGHT -#define HX_MAX_WEIGHT 20000 -#endif -#ifndef HX_REFERENCE -#define HX_REFERENCE 250 -#endif -#ifndef HX_SCALE -#define HX_SCALE 120 -#endif - -#define HX_TIMEOUT 120 -#define HX_SAMPLES 10 -#define HX_CAL_TIMEOUT 15 - -#define HX_GAIN_128 1 -#define HX_GAIN_32 2 -#define HX_GAIN_64 3 - -#define D_JSON_WEIGHT_REF "WeightRef" -#define D_JSON_WEIGHT_CAL "WeightCal" -#define D_JSON_WEIGHT_MAX "WeightMax" -#define D_JSON_WEIGHT_ITEM "WeightItem" -#define D_JSON_WEIGHT_CHANGE "WeightChange" -#define D_JSON_WEIGHT_RAW "WeightRaw" -#define D_JSON_WEIGHT_DELTA "WeightDelta" - -enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; - -const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE; - -struct HX { - long weight = 0; - long raw = 0; - long last_weight = 0; - long sum_weight = 0; - long sum_raw = 0; - long offset = 0; - long scale = 1; - long weight_diff = 0; - uint8_t type = 1; - uint8_t sample_count = 0; - uint8_t calibrate_step = HX_CAL_END; - uint8_t calibrate_timer = 0; - uint8_t calibrate_msg = 0; - uint8_t pin_sck; - uint8_t pin_dout; - bool tare_flg = false; - bool weight_changed = false; - uint16_t weight_delta = 4; -} Hx; - - - -bool HxIsReady(uint16_t timeout) -{ - - uint32_t start = millis(); - while ((digitalRead(Hx.pin_dout) == HIGH) && (millis() - start < timeout)) { yield(); } - return (digitalRead(Hx.pin_dout) == LOW); -} - -long HxRead(void) -{ - if (!HxIsReady(HX_TIMEOUT)) { return -1; } - - uint8_t data[3] = { 0 }; - uint8_t filler = 0x00; - - - data[2] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - data[1] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - data[0] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - - - for (unsigned int i = 0; i < HX_GAIN_128; i++) { - digitalWrite(Hx.pin_sck, HIGH); - digitalWrite(Hx.pin_sck, LOW); - } - - - if (data[2] & 0x80) { filler = 0xFF; } - - - unsigned long value = ( static_cast(filler) << 24 - | static_cast(data[2]) << 16 - | static_cast(data[1]) << 8 - | static_cast(data[0]) ); - - return static_cast(value); -} - - - -void HxResetPart(void) -{ - Hx.tare_flg = true; - Hx.sum_weight = 0; - Hx.sample_count = 0; - Hx.last_weight = 0; -} - -void HxReset(void) -{ - HxResetPart(); - Settings.energy_frequency_calibration = 0; -} - -void HxCalibrationStateTextJson(uint8_t msg_id) -{ - char cal_text[30]; - - Hx.calibrate_msg = msg_id; - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); - - if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } -} - -void SetWeightDelta() -{ - - if (Settings.weight_change == 0) { - Hx.weight_delta = 4; - return; - } - - - if (Settings.weight_change > 100) { - Hx.weight_delta = (Settings.weight_change - 100) * 10 + 100; - return; - } - - - Hx.weight_delta = Settings.weight_change - 1; -} -# 192 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_34_hx711.ino" -bool HxCommand(void) -{ - bool serviced = true; - bool show_parms = false; - char sub_string[XdrvMailbox.data_len +1]; - - for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) { - if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; } - } - - switch (XdrvMailbox.payload) { - case 1: - HxReset(); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); - break; - case 2: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - Hx.scale = 1; - HxReset(); - Hx.calibrate_step = HX_CAL_START; - Hx.calibrate_timer = 1; - HxCalibrationStateTextJson(3); - break; - case 3: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - show_parms = true; - break; - case 4: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - Hx.scale = Settings.weight_calibration; - } - show_parms = true; - break; - case 5: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000; - } - show_parms = true; - break; - case 6: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_item = (unsigned long)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); - } - show_parms = true; - break; - case 7: - Settings.energy_frequency_calibration = Hx.weight; - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE); - break; - case 8: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.SensorBits1.hx711_json_weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) & 1; - } - show_parms = true; - break; - case 9: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - SetWeightDelta(); - } - show_parms = true; - break; - default: - show_parms = true; - } - - if (show_parms) { - char item[33]; - dtostrfd((float)Settings.weight_item / 10, 1, item); - Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" - D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":%s,\"" D_JSON_WEIGHT_DELTA "\":%d}}"), - Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, - item, GetStateText(Settings.SensorBits1.hx711_json_weight_change), Settings.weight_change); - } - - return serviced; -} - - - -long HxWeight(void) -{ - return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; -} - -void HxInit(void) -{ - Hx.type = 0; - if ((pin[GPIO_HX711_DAT] < 99) && (pin[GPIO_HX711_SCK] < 99)) { - Hx.pin_sck = pin[GPIO_HX711_SCK]; - Hx.pin_dout = pin[GPIO_HX711_DAT]; - - pinMode(Hx.pin_sck, OUTPUT); - pinMode(Hx.pin_dout, INPUT); - - digitalWrite(Hx.pin_sck, LOW); - - SetWeightDelta(); - - if (HxIsReady(8 * HX_TIMEOUT)) { - if (!Settings.weight_max) { Settings.weight_max = HX_MAX_WEIGHT / 1000; } - if (!Settings.weight_calibration) { Settings.weight_calibration = HX_SCALE; } - if (!Settings.weight_reference) { Settings.weight_reference = HX_REFERENCE; } - Hx.scale = Settings.weight_calibration; - HxRead(); - HxResetPart(); - Hx.type = 1; - } - } -} - -void HxEvery100mSecond(void) -{ - long raw = HxRead(); - Hx.sum_raw += raw; - Hx.sum_weight += raw; - - Hx.sample_count++; - if (HX_SAMPLES == Hx.sample_count) { - long average = Hx.sum_weight / Hx.sample_count; - long raw_average = Hx.sum_raw / Hx.sample_count; - long value = average - Hx.offset; - Hx.weight = value / Hx.scale; - Hx.raw = raw_average / Hx.scale; - if (Hx.weight < 0) { - if (Settings.energy_frequency_calibration) { - long difference = Settings.energy_frequency_calibration + Hx.weight; - Hx.last_weight = difference; - if (difference < 0) { HxReset(); } - } - Hx.weight = 0; - } else { - Hx.last_weight = Settings.energy_frequency_calibration; - } - - if (Hx.tare_flg) { - Hx.tare_flg = false; - Hx.offset = average; - } - - if (Hx.calibrate_step) { - Hx.calibrate_timer--; - - if (HX_CAL_START == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); - } - else if (HX_CAL_RESET == Hx.calibrate_step) { - if (Hx.calibrate_timer) { - if (Hx.weight < (long)Settings.weight_reference) { - Hx.calibrate_step--; - Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); - HxCalibrationStateTextJson(2); - } - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - else if (HX_CAL_FIRST == Hx.calibrate_step) { - if (Hx.calibrate_timer) { - if (Hx.weight > (long)Settings.weight_reference) { - Hx.calibrate_step--; - } - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - else if (HX_CAL_DONE == Hx.calibrate_step) { - if (Hx.weight > (long)Settings.weight_reference) { - Hx.calibrate_step = HX_CAL_FINISH; - Settings.weight_calibration = Hx.weight / Settings.weight_reference; - Hx.weight = 0; - HxCalibrationStateTextJson(1); - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - - if (HX_CAL_FAIL == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.tare_flg = true; - HxCalibrationStateTextJson(0); - } - if (HX_CAL_FINISH == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.calibrate_timer = 3 * (10 / HX_SAMPLES); - Hx.scale = Settings.weight_calibration; - } - - if (!Hx.calibrate_timer) { - Hx.calibrate_step = HX_CAL_END; - } - } else { - Hx.weight += Hx.last_weight; - - if (Settings.SensorBits1.hx711_json_weight_change) { - if (abs(Hx.weight - Hx.weight_diff) > Hx.weight_delta) { - Hx.weight_diff = Hx.weight; - Hx.weight_changed = true; - } - else if (Hx.weight_changed && (Hx.weight == Hx.weight_diff)) { - mqtt_data[0] = '\0'; - ResponseAppendTime(); - HxShow(true); - ResponseJsonEnd(); - MqttPublishTeleSensor(); - Hx.weight_changed = false; - } - } - } - - Hx.sum_weight = 0; - Hx.sum_raw = 0; - Hx.sample_count = 0; - } -} - -void HxSaveBeforeRestart(void) -{ - Settings.energy_frequency_calibration = Hx.weight; - Hx.sample_count = HX_SAMPLES +1; -} - -#ifdef USE_WEBSERVER -const char HTTP_HX711_WEIGHT[] PROGMEM = - "{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; -const char HTTP_HX711_COUNT[] PROGMEM = - "{s}HX711 " D_COUNT "{m}%d{e}"; -const char HTTP_HX711_CAL[] PROGMEM = - "{s}HX711 %s{m}{e}"; -#endif - -void HxShow(bool json) -{ - char scount[30] = { 0 }; - - uint16_t count = 0; - float weight = 0; - if (Hx.calibrate_step < HX_CAL_FAIL) { - if (Hx.weight && Settings.weight_item) { - count = (Hx.weight * 10) / Settings.weight_item; - if (count > 1) { - snprintf_P(scount, sizeof(scount), PSTR(",\"" D_JSON_COUNT "\":%d"), count); - } - } - weight = (float)Hx.weight / 1000; - } - char weight_chr[33]; - dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s, \"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); - if (count > 1) { - WSContentSend_PD(HTTP_HX711_COUNT, count); - } - if (Hx.calibrate_step) { - char cal_text[30]; - WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); - } -#endif - } -} - -#ifdef USE_WEBSERVER -#ifdef USE_HX711_GUI - - - - -#define WEB_HANDLE_HX711 "s34" - -const char S_CONFIGURE_HX711[] PROGMEM = D_CONFIGURE_HX711; - -const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = - "

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

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

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" - "
" - "
" - "


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

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; - -void HandleHxAction(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); - - if (WebServer->hasArg("save")) { - HxSaveSettings(); - HandleConfiguration(); - return; - } - - char stemp1[20]; - - if (WebServer->hasArg("reset")) { - snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); - ExecuteWebCommand(stemp1, SRC_WEBGUI); - - HandleRoot(); - return; - } - - if (WebServer->hasArg("calibrate")) { - WebGetArg("p1", stemp1, sizeof(stemp1)); - Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); - - HxLogUpdates(); - - snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); - ExecuteWebCommand(stemp1, SRC_WEBGUI); - - HandleRoot(); - return; - } - - WSContentStart_P(S_CONFIGURE_HX711); - WSContentSendStyle(); - dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); - char stemp2[20]; - dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); - WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void HxSaveSettings(void) -{ - char tmp[100]; - - WebGetArg("p2", tmp, sizeof(tmp)); - Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToFloat(tmp) * 10000); - - HxLogUpdates(); -} - -void HxLogUpdates(void) -{ - char weigth_ref_chr[33]; - dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); - char weigth_item_chr[33]; - dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), weigth_ref_chr, weigth_item_chr); -} - -#endif -#endif - - - - - -bool Xsns34(uint8_t function) -{ - bool result = false; - - if (Hx.type) { - switch (function) { - case FUNC_EVERY_100_MSECOND: - HxEvery100mSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_34 == XdrvMailbox.index) { - result = HxCommand(); - } - break; - case FUNC_JSON_APPEND: - HxShow(1); - break; - case FUNC_SAVE_BEFORE_RESTART: - HxSaveBeforeRestart(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HxShow(0); - break; -#ifdef USE_HX711_GUI - case FUNC_WEB_ADD_MAIN_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711); - break; - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_HX711); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); - break; -#endif -#endif - case FUNC_INIT: - HxInit(); - break; - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_35_tx20.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_35_tx20.ino" -#ifdef USE_TX20_WIND_SENSOR -# 29 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_35_tx20.ino" -#define XSNS_35 35 - -#define TX20_BIT_TIME 1220 -#define TX20_RESET_VALUES 60 - - - -extern "C" { -#include "gpio.h" -} - -#ifdef USE_WEBSERVER - -const char HTTP_SNS_TX20[] PROGMEM = - "{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_DIRECTION "{m}%s{e}"; - -#endif - -const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" - D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST "|" - D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST "|" - D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; - -uint8_t tx20_sa = 0; -uint8_t tx20_sb = 0; -uint8_t tx20_sd = 0; -uint8_t tx20_se = 0; -uint16_t tx20_sc = 0; -uint16_t tx20_sf = 0; - -float tx20_wind_speed_kmh = 0; -float tx20_wind_speed_max = 0; -float tx20_wind_speed_avg = 0; -float tx20_wind_sum = 0; -int tx20_count = 0; -uint8_t tx20_wind_direction = 0; - -bool tx20_available = false; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void Tx20StartRead(void) ICACHE_RAM_ATTR; -#endif - -void Tx20StartRead(void) -{ -# 101 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_35_tx20.ino" - tx20_available = false; - - tx20_sa = 0; - tx20_sb = 0; - tx20_sd = 0; - tx20_se = 0; - tx20_sc = 0; - tx20_sf = 0; - - delayMicroseconds(TX20_BIT_TIME / 2); - - for (int32_t bitcount = 41; bitcount > 0; bitcount--) { - uint8_t dpin = (digitalRead(pin[GPIO_TX20_TXD_BLACK])); - if (bitcount > 41 - 5) { - - tx20_sa = (tx20_sa << 1) | (dpin ^ 1); - } else if (bitcount > 41 - 5 - 4) { - - tx20_sb = tx20_sb >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12) { - - tx20_sc = tx20_sc >> 1 | ((dpin ^ 1) << 11); - } else if (bitcount > 41 - 5 - 4 - 12 - 4) { - - tx20_sd = tx20_sd >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { - - tx20_se = tx20_se >> 1 | (dpin << 3); - } else { - - tx20_sf = tx20_sf >> 1 | (dpin << 11); - } - - delayMicroseconds(TX20_BIT_TIME); - } - - uint8_t chk = (tx20_sb + (tx20_sc & 0xf) + ((tx20_sc >> 4) & 0xf) + ((tx20_sc >> 8) & 0xf)); - chk &= 0xf; - - if ((chk == tx20_sd) && (tx20_sc < 400)) { - tx20_available = true; - } - - - - - - - - GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]); -} - -void Tx20Read(void) -{ - if (!(uptime % TX20_RESET_VALUES)) { - tx20_count = 0; - tx20_wind_sum = 0; - tx20_wind_speed_max = 0; - } - else if (tx20_available) { - tx20_wind_speed_kmh = float(tx20_sc) * 0.36; - if (tx20_wind_speed_kmh > tx20_wind_speed_max) { - tx20_wind_speed_max = tx20_wind_speed_kmh; - } - tx20_count++; - tx20_wind_sum += tx20_wind_speed_kmh; - tx20_wind_speed_avg = tx20_wind_sum / tx20_count; - tx20_wind_direction = tx20_sb; - } -} - -void Tx20Init(void) { - pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); - attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); -} - -void Tx20Show(bool json) -{ - char wind_speed_string[33]; - dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); - char wind_speed_max_string[33]; - dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); - char wind_speed_avg_string[33]; - dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); - char wind_direction_string[4]; - GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); - - if (json) { - ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), - wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); -#endif - } -} - - - - - -bool Xsns35(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_TX20_TXD_BLACK] < 99) { - switch (function) { - case FUNC_INIT: - Tx20Init(); - break; - case FUNC_EVERY_SECOND: - Tx20Read(); - break; - case FUNC_JSON_APPEND: - Tx20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tx20Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_36_mgc3130.ino" -# 22 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_36_mgc3130.ino" -#ifdef USE_I2C -#ifdef USE_MGC3130 -# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_36_mgc3130.ino" -#define XSNS_36 36 -#define XI2C_27 27 - -#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** - -#define MGC3130_I2C_ADDR 0x42 - -#define MGC3130_xfer pin[GPIO_MGC3130_XFER] -#define MGC3130_reset pin[GPIO_MGC3130_RESET] - - -bool MGC3130_type = false; -char MGC3130stype[] = "MGC3130"; - - -#define MGC3130_SYSTEM_STATUS 0x15 -#define MGC3130_REQUEST_MSG 0x06 -#define MGC3130_FW_VERSION 0x83 -#define MGC3130_SET_RUNTIME 0xA2 -#define MGC3130_SENSOR_DATA 0x91 - - -#define MGC3130_GESTURE_GARBAGE 1 -#define MGC3130_FLICK_WEST_EAST 2 -#define MGC3130_FLICK_EAST_WEST 3 -#define MGC3130_FLICK_SOUTH_NORTH 4 -#define MGC3130_FLICK_NORTH_SOUTH 5 -#define MGC3130_CIRCLE_CLOCKWISE 6 -#define MGC3130_CIRCLE_CCLOCKWISE 7 - -#define MGC3130_MIN_ROTVALUE 0 -#define MGC3130_MAX_ROTVALUE 1023 -#define MGC3130_MIN_ZVALUE 32768 - - -#ifdef USE_WEBSERVER -const char HTTP_MGC_3130_SNS[] PROGMEM = - "{s}" "%s" "{m}%s{e}" - "{s}" "HwRev" "{m}%u.%u{e}" - "{s}" "loaderVer" "{m}%u.%u{e}" - "{s}" "platVer" "{m}%u{e}"; -#endif - - - - - - - -#pragma pack(1) -union MGC3130_Union{ - uint8_t buffer[132]; - struct - { - - uint8_t msgSize; - uint8_t flag; - uint8_t counter; - uint8_t id; - - struct { - uint8_t DSPStatus:1; - uint8_t gestureInfo:1; - uint8_t touchInfo:1; - uint8_t airWheelInfo:1; - uint8_t xyzPosition:1; - uint8_t noisePower:1; - uint8_t reserved:2; - uint8_t electrodeConfiguration:3; - uint8_t CICData:1; - uint8_t SDData:1; - uint16_t reserved2:3; - } outputConfigMask; - uint8_t timestamp; - struct { - uint8_t positionValid:1; - uint8_t airWheelValid:1; - uint8_t rawDataValid:1; - uint8_t noisePowerValid:1; - uint8_t environmentalNoise:1; - uint8_t clipping:1; - uint8_t reserved:1; - uint8_t DSPRunning:1; - } systemInfo; - uint16_t dspInfo; - struct { - uint8_t gestureCode:8; - uint8_t reserved:4; - uint8_t gestureType:4; - uint8_t edgeFlick:1; - uint16_t reserved2:14; - uint8_t gestureInProgress:1; - } gestureInfo; - struct { - uint8_t touchSouth:1; - uint8_t touchWest:1; - uint8_t touchNorth:1; - uint8_t touchEast:1; - uint8_t touchCentre:1; - uint8_t tapSouth:1; - uint8_t tapWest:1; - uint8_t tapNorth:1; - uint8_t tapEast :1; - uint8_t tapCentre:1; - uint8_t doubleTapSouth:1; - uint8_t doubleTapWest:1; - uint8_t doubleTapNorth:1; - uint8_t doubleTapEast:1; - uint8_t doubleTapCentre:1; - uint8_t reserved:1; - uint8_t touchCounter; - uint8_t reserved2; - } touchInfo; - int8_t airWheel; - uint8_t reserved; - uint16_t x; - uint16_t y; - uint16_t z; - float noisePower; - float CICData[4]; - float SDData[4]; - } out; - struct { - uint8_t header[3]; - - uint8_t valid; - uint8_t hwRev[2]; - uint8_t parameterStartAddr; - uint8_t loaderVersion[2]; - uint8_t loaderPlatform; - uint8_t fwStartAddr; - char fwVersion[120]; - } fw; - struct{ - uint8_t id; - uint8_t size; - uint16_t error; - uint32_t reserved; - uint32_t reserved1; - } status; -} MGC_data; -#pragma pack() - -char MGC3130_currentGesture[12]; - -int8_t MGC3130_delta, MGC3130_lastrotation = 0; -int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0; - -uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0; - -uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0; -char MGC3130_firmwareInfo[20]; - -uint8_t MGC3130_touchTimeout = 0; -uint16_t MGC3130_touchCounter = 1; -uint32_t MGC3130_touchTimeStamp = millis(); -bool MGC3130_triggeredByTouch = false; - -uint8_t MGC3130_mode = 1; - - - -uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; -uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; -uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; - -void MGC3130_handleSensorData(){ - if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ - if (MGC3130_handleTouch()){ - MGC3130_triggeredByTouch = true; - MqttPublishSensor(); - } - } - - if(MGC3130_mode == 1){ - if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ - MGC3130_handleGesture(); - MqttPublishSensor(); - } - } - if(MGC3130_mode == 2){ - if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ - MGC3130_handleAirWheel(); - MqttPublishSensor(); - } - } - if(MGC3130_mode == 3){ - if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ - MqttPublishSensor(); - } - } -} - -void MGC3130_sendMessage(uint8_t data[], uint8_t length){ - Wire.beginTransmission(MGC3130_I2C_ADDR); - Wire.write(data,length); - Wire.endTransmission(); - delay(2); - MGC3130_receiveMessage(); -} - - -void MGC3130_handleGesture(){ - - char edge[5]; - if (MGC_data.out.gestureInfo.edgeFlick){ - snprintf_P(edge, sizeof(edge), PSTR("ED_")); - } - else{ - snprintf_P(edge, sizeof(edge), PSTR("")); - } - switch(MGC_data.out.gestureInfo.gestureCode){ - case MGC3130_GESTURE_GARBAGE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE")); - break; - case MGC3130_FLICK_WEST_EAST: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge); - break; - case MGC3130_FLICK_EAST_WEST: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge); - break; - case MGC3130_FLICK_SOUTH_NORTH: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge); - break; - case MGC3130_FLICK_NORTH_SOUTH: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge); - break; - case MGC3130_CIRCLE_CLOCKWISE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW")); - break; - case MGC3130_CIRCLE_CCLOCKWISE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW")); - break; - } - -} - -bool MGC3130_handleTouch(){ - - bool success = false; - if (MGC_data.out.touchInfo.doubleTapCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - if (MGC_data.out.touchInfo.tapCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.touchCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S")); - success = true; - MGC3130_touchCounter++; - } - - return success; -} - -void MGC3130_handleAirWheel(){ - MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation; - MGC3130_lastrotation = MGC_data.out.airWheel; - - MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta; - if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){ - MGC3130_rotValue = MGC3130_MIN_ROTVALUE; - } - if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){ - MGC3130_rotValue = MGC3130_MAX_ROTVALUE; - } -} - -void MGC3130_handleSystemStatus(){ - -} - -bool MGC3130_receiveMessage(){ - if(MGC3130_readData()){ - switch(MGC_data.out.id){ - case MGC3130_SENSOR_DATA: - MGC3130_handleSensorData(); - break; - case MGC3130_SYSTEM_STATUS: - MGC3130_handleSystemStatus(); - break; - case MGC3130_FW_VERSION: - hwRev[0] = MGC_data.fw.hwRev[1]; - hwRev[1] = MGC_data.fw.hwRev[0]; - loaderVersion[0] = MGC_data.fw.loaderVersion[0]; - loaderVersion[1] = MGC_data.fw.loaderVersion[1]; - loaderPlatform = MGC_data.fw.loaderPlatform; - snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion); - MGC3130_firmwareInfo[20] = '\0'; - - break; - } - return true; - } - return false; -} - -bool MGC3130_readData() -{ - bool success = false; - if (!digitalRead(MGC3130_xfer)){ - pinMode(MGC3130_xfer, OUTPUT); - digitalWrite(MGC3130_xfer, LOW); - Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); - - MGC_data.buffer[0] = 4; - unsigned char i = 0; - while(Wire.available() && (i < MGC_data.buffer[0])){ - MGC_data.buffer[i] = Wire.read(); - i++; - } - digitalWrite(MGC3130_xfer, HIGH); - pinMode(MGC3130_xfer, INPUT); - success = true; - } - return success; -} - -void MGC3130_nextMode(){ - if (MGC3130_mode < 3){ - MGC3130_mode++; - } - else{ - MGC3130_mode = 1; - } - switch(MGC3130_mode){ - case 1: - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - case 2: - MGC3130_sendMessage(MGC3130enableAirwheel,16); - break; - case 3: - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - } -} - -void MGC3130_loop() -{ - if(MGC3130_touchTimeout > 0){ - MGC3130_touchTimeout--; - } - MGC3130_receiveMessage(); -} - -void MGC3130_detect(void) -{ - if (MGC3130_type || I2cActive(MGC3130_I2C_ADDR)) { return; } - - pinMode(MGC3130_xfer, INPUT_PULLUP); - pinMode(MGC3130_reset, OUTPUT); - digitalWrite(MGC3130_reset, LOW); - delay(10); - digitalWrite(MGC3130_reset, HIGH); - delay(50); - - if (MGC3130_receiveMessage()) { - I2cSetActiveFound(MGC3130_I2C_ADDR, MGC3130stype); - MGC3130_currentGesture[0] = '\0'; - MGC3130_type = true; - } -} - - - - - -void MGC3130_show(bool json) -{ - if (!MGC3130_type) { return; } - - char status_chr[2]; - if (MGC_data.out.systemInfo.DSPRunning) { - sprintf (status_chr, "1"); - } - else{ - sprintf (status_chr, "0"); - } - - if (json) { - if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { - if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { - ResponseAppend_P(PSTR(",\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), - MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); - MGC3130_lastSentX = MGC_data.out.x; - MGC3130_lastSentY = MGC_data.out.y; - MGC3130_lastSentZ = MGC_data.out.z; - } - } - MGC3130_triggeredByTouch = false; - - if (MGC3130_mode == 2) { - if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { - ResponseAppend_P(PSTR(",\"%s\":{\"AW\":%i}"), MGC3130stype, MGC3130_rotValue); - MGC3130_lastSentRotValue = MGC3130_rotValue; - } - } - - if (MGC3130_currentGesture[0] != '\0') { - if (millis() - MGC3130_touchTimeStamp > 220 ) { - MGC3130_touchCounter = 1; - } - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); - MGC3130_currentGesture[0] = '\0'; - MGC3130_touchTimeStamp = millis(); - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); -#endif - } -} -# 557 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_36_mgc3130.ino" -bool MGC3130CommandSensor() -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - MGC3130_nextMode(); - break; - case 1: - MGC3130_mode = 1; - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - case 2: - MGC3130_mode = 2; - MGC3130_sendMessage(MGC3130enableAirwheel,16); - break; - case 3: - MGC3130_mode = 3; - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - } - return serviced; -} - - - - - -bool Xsns36(uint8_t function) -{ - if (!I2cEnabled(XI2C_27)) { return false; } - - bool result = false; - - if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { - MGC3130_detect(); - } - else if (MGC3130_type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - MGC3130_loop(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_36 == XdrvMailbox.index) { - result = MGC3130CommandSensor(); - } - break; - case FUNC_JSON_APPEND: - MGC3130_show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MGC3130_show(0); - break; -#endif - } - } - return result; -} -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" -#ifdef USE_RF_SENSOR -# 33 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" -#define XSNS_37 37 - - - - -#define RFSNS_VALID_WINDOW 1800 - -#define RFSNS_LOOPS_PER_MILLI 1900 -#define RFSNS_RAW_BUFFER_SIZE 180 -#define RFSNS_MIN_RAW_PULSES 112 - -#define RFSNS_MIN_PULSE_LENGTH 300 -#define RFSNS_RAWSIGNAL_SAMPLE 50 -#define RFSNS_SIGNAL_TIMEOUT 10 -#define RFSNS_SIGNAL_REPEAT_TIME 500 - -typedef struct RawSignalStruct -{ - int Number; - uint8_t Repeats; - uint8_t Multiply; - unsigned long Time; - uint8_t Pulses[RFSNS_RAW_BUFFER_SIZE+2]; - -} raw_signal_t; - -raw_signal_t *rfsns_raw_signal = nullptr; -uint8_t rfsns_rf_bit; -uint8_t rfsns_rf_port; -uint8_t rfsns_any_sensor = 0; - - - - - -bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal) -{ - uint8_t Fbit = digitalPinToBitMask(DataPin); - uint8_t Fport = digitalPinToPort(DataPin); - uint8_t FstateMask = (StateSignal ? Fbit : 0); - - if ((*portInputRegister(Fport) & Fbit) == FstateMask) { - const unsigned long LoopsPerMilli = RFSNS_LOOPS_PER_MILLI; - - - - - - - unsigned long PulseLength = 0; - if (rfsns_raw_signal->Time) { - if (rfsns_raw_signal->Repeats && (rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) { - PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; - while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && (PulseLength > micros())) { - if ((*portInputRegister(Fport) & Fbit) == FstateMask) { - PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; - } - } - while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && ((*portInputRegister(Fport) & Fbit) != FstateMask)); - } - } - - int RawCodeLength = 1; - bool Ftoggle = false; - unsigned long numloops = 0; - unsigned long maxloops = RFSNS_SIGNAL_TIMEOUT * LoopsPerMilli; - rfsns_raw_signal->Multiply = RFSNS_RAWSIGNAL_SAMPLE; - do { - numloops = 0; - while(((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) { - if (numloops++ == maxloops) { break; } - } - PulseLength = (numloops *1000) / LoopsPerMilli; - if (PulseLength < RFSNS_MIN_PULSE_LENGTH) { break; } - Ftoggle = !Ftoggle; - rfsns_raw_signal->Pulses[RawCodeLength++] = PulseLength / (unsigned long)rfsns_raw_signal->Multiply; - } - while(RawCodeLength < RFSNS_RAW_BUFFER_SIZE && numloops <= maxloops); - - if ((RawCodeLength >= RFSNS_MIN_RAW_PULSES) && (RawCodeLength < RFSNS_RAW_BUFFER_SIZE -1)) { - rfsns_raw_signal->Repeats = 0; - rfsns_raw_signal->Number = RawCodeLength -1; - rfsns_raw_signal->Pulses[rfsns_raw_signal->Number] = 0; - rfsns_raw_signal->Time = millis(); - return true; - } - else - rfsns_raw_signal->Number = 0; - } - - return false; -} - -#ifdef USE_THEO_V2 -# 149 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" -#define RFSNS_THEOV2_MAX_CHANNEL 2 - -#define RFSNS_THEOV2_PULSECOUNT 114 -#define RFSNS_THEOV2_RF_PULSE_MID 1000 - -typedef struct { - uint32_t time; - int16_t temp; - uint16_t lux; - uint8_t volt; -} theo_v2_t1_t; - -typedef struct { - uint32_t time; - int16_t temp; - uint16_t hum; - uint8_t volt; -} theo_v2_t2_t; - -theo_v2_t1_t *rfsns_theo_v2_t1 = nullptr; -theo_v2_t2_t *rfsns_theo_v2_t2 = nullptr; - -void RfSnsInitTheoV2(void) -{ - rfsns_theo_v2_t1 = (theo_v2_t1_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t1_t)); - rfsns_theo_v2_t2 = (theo_v2_t2_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t2_t)); - rfsns_any_sensor++; -} - -void RfSnsAnalyzeTheov2(void) -{ - if (rfsns_raw_signal->Number != RFSNS_THEOV2_PULSECOUNT) { return; } - - uint8_t Checksum; - uint8_t Channel; - uint8_t Type; - uint8_t Voltage; - int Payload1; - int Payload2; - - uint8_t b, bytes, bits, id; - - uint8_t idx = 3; - uint8_t chksum = 0; - for (bytes = 0; bytes < 7; bytes++) { - b = 0; - for (bits = 0; bits <= 7; bits++) - { - if ((rfsns_raw_signal->Pulses[idx] * rfsns_raw_signal->Multiply) > RFSNS_THEOV2_RF_PULSE_MID) { - b |= 1 << bits; - } - idx += 2; - } - if (bytes > 0) { chksum += b; } - - switch (bytes) { - case 0: - Checksum = b; - break; - case 1: - id = b; - Channel = b & 0x7; - Type = (b >> 3) & 0x1f; - break; - case 2: - Voltage = b; - break; - case 3: - Payload1 = b; - break; - case 4: - Payload1 = (b << 8) | Payload1; - break; - case 5: - Payload2 = b; - break; - case 6: - Payload2 = (b << 8) | Payload2; - break; - } - } - - if (Checksum != chksum) { return; } - if ((Channel == 0) || (Channel > RFSNS_THEOV2_MAX_CHANNEL)) { return; } - Channel--; - - rfsns_raw_signal->Repeats = 1; - - int Payload3 = Voltage & 0x3f; - - switch (Type) { - case 1: - rfsns_theo_v2_t1[Channel].time = LocalTime(); - rfsns_theo_v2_t1[Channel].volt = Payload3; - rfsns_theo_v2_t1[Channel].temp = Payload1; - rfsns_theo_v2_t1[Channel].lux = Payload2; - break; - case 2: - rfsns_theo_v2_t2[Channel].time = LocalTime(); - rfsns_theo_v2_t2[Channel].volt = Payload3; - rfsns_theo_v2_t2[Channel].temp = Payload1; - rfsns_theo_v2_t2[Channel].hum = Payload2; - break; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), - chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2); -} - -void RfSnsTheoV2Show(bool json) -{ - bool sensor_once = false; - - for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { - if (rfsns_theo_v2_t1[i].time) { - char sensor[10]; - snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1); - char voltage[33]; - dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage); - - if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); - } - } else { - char temperature[33]; - dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), - sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && !sensor_once) { - DomoticzSensor(DZ_TEMP, temperature); - DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux); - sensor_once = true; - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor, rfsns_theo_v2_t1[i].lux); -#endif - } - } - } - } - - sensor_once = false; - for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { - if (rfsns_theo_v2_t2[i].time) { - char sensor[10]; - snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1); - char voltage[33]; - dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage); - - if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); - } - } else { - float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); - float humi = ConvertHumidity((float)rfsns_theo_v2_t2[i].hum / 100); - char temperature[33]; - dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), - sensor, temperature, humidity, voltage); - if ((0 == tele_period) && !sensor_once) { -#ifdef USE_DOMOTICZ - DomoticzTempHumSensor(temperature, humidity); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, temp); - KnxSensor(KNX_HUMIDITY, humi); -#endif - sensor_once = true; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, sensor, humidity); -#endif - } - } - } - } -} - -#endif - -#ifdef USE_ALECTO_V2 -# 392 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_37_rfsensor.ino" -#define RFSNS_DKW2012_PULSECOUNT 176 -#define RFSNS_ACH2010_MIN_PULSECOUNT 160 -#define RFSNS_ACH2010_MAX_PULSECOUNT 160 - -#define D_ALECTOV2 "AlectoV2" - -const char kAlectoV2Directions[] PROGMEM = D_TX20_NORTH "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" - D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST "|" - D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST "|" - D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; - -typedef struct { - uint32_t time; - float temp; - float rain; - float wind; - float gust; - uint8_t type; - uint8_t humi; - uint8_t wdir; -} alecto_v2_t; - -alecto_v2_t *rfsns_alecto_v2 = nullptr; -uint16_t rfsns_alecto_rain_base = 0; - -void RfSnsInitAlectoV2(void) -{ - rfsns_alecto_v2 = (alecto_v2_t*)malloc(sizeof(alecto_v2_t)); - rfsns_any_sensor++; -} - -void RfSnsAnalyzeAlectov2() -{ - if (!(((rfsns_raw_signal->Number >= RFSNS_ACH2010_MIN_PULSECOUNT) && - (rfsns_raw_signal->Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal->Number == RFSNS_DKW2012_PULSECOUNT))) { return; } - - uint8_t c = 0; - uint8_t rfbit; - uint8_t data[9] = { 0 }; - uint8_t msgtype = 0; - uint8_t rc = 0; - int temp; - uint8_t checksum = 0; - uint8_t checksumcalc = 0; - uint8_t maxidx = 8; - unsigned long atime; - float factor; - char buf1[16]; - - if (rfsns_raw_signal->Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; } - - uint8_t idx = maxidx; - for (uint32_t x = rfsns_raw_signal->Number; x > 0; x = x-2) { - if (rfsns_raw_signal->Pulses[x-1] * rfsns_raw_signal->Multiply < 0x300) { - rfbit = 0x80; - } else { - rfbit = 0; - } - data[idx] = (data[idx] >> 1) | rfbit; - c++; - if (c == 8) { - if (idx == 0) { break; } - c = 0; - idx--; - } - } - - checksum = data[maxidx]; - checksumcalc = RfSnsAlectoCRC8(data, maxidx); - - msgtype = (data[0] >> 4) & 0xf; - rc = (data[0] << 4) | (data[1] >> 4); - - if (checksum != checksumcalc) { return; } - if ((msgtype != 10) && (msgtype != 5)) { return; } - - rfsns_raw_signal->Repeats = 1; - - - - - - factor = 1.22; - - - - - - rfsns_alecto_v2->time = LocalTime(); - rfsns_alecto_v2->type = (RFSNS_DKW2012_PULSECOUNT == rfsns_raw_signal->Number); - rfsns_alecto_v2->temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10; - rfsns_alecto_v2->humi = data[3]; - uint16_t rain = (data[6] * 256) + data[7]; - - if (rain < rfsns_alecto_rain_base) { rfsns_alecto_rain_base = rain; } - if (rfsns_alecto_rain_base > 0) { - rfsns_alecto_v2->rain += ((float)rain - rfsns_alecto_rain_base) * 0.30; - } - rfsns_alecto_rain_base = rain; - rfsns_alecto_v2->wind = (float)data[4] * factor; - rfsns_alecto_v2->gust = (float)data[5] * factor; - if (rfsns_alecto_v2->type) { - rfsns_alecto_v2->wdir = data[8] & 0xf; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), - checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); -} - -void RfSnsAlectoResetRain(void) -{ - if ((RtcTime.hour == 0) && (RtcTime.minute == 0) && (RtcTime.second == 5)) { - rfsns_alecto_v2->rain = 0; - } -} - - - - - - - -uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) -{ - uint8_t crc = 0; - while (len--) { - uint8_t inbyte = *addr++; - for (uint32_t i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x80; - crc <<= 1; - if (mix) { crc ^= 0x31; } - inbyte <<= 1; - } - } - return crc; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_ALECTOV2[] PROGMEM = - "{s}" D_ALECTOV2 " " D_RAIN "{m}%s " D_UNIT_MILLIMETER "{e}" - "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"; -const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = - "{s}" D_ALECTOV2 " " D_TX20_WIND_DIRECTION "{m}%s{e}"; -#endif - -void RfSnsAlectoV2Show(bool json) -{ - if (rfsns_alecto_v2->time) { - if (rfsns_alecto_v2->time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), GetDT(rfsns_alecto_v2->time).c_str()); - } - } else { - float temp = ConvertTemp(rfsns_alecto_v2->temp); - char temperature[33]; - dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); - float humi = ConvertHumidity((float)rfsns_alecto_v2->humi); - char humidity[33]; - dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); - char rain[33]; - dtostrfd(rfsns_alecto_v2->rain, 2, rain); - char wind[33]; - dtostrfd(rfsns_alecto_v2->wind, 2, wind); - char gust[33]; - dtostrfd(rfsns_alecto_v2->gust, 2, gust); - char wdir[4]; - char direction[20]; - if (rfsns_alecto_v2->type) { - GetTextIndexed(wdir, sizeof(wdir), rfsns_alecto_v2->wdir, kAlectoV2Directions); - snprintf_P(direction, sizeof(direction), PSTR(",\"Direction\":\"%s\""), wdir); - } - - if (json) { - ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), - temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); - if (0 == tele_period) { -#ifdef USE_DOMOTICZ - - - - -#endif - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, D_ALECTOV2, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, D_ALECTOV2, humidity); - WSContentSend_PD(HTTP_SNS_ALECTOV2, rain, wind, gust); - if (rfsns_alecto_v2->type) { - WSContentSend_PD(HTTP_SNS_ALECTOV2_WDIR, wdir); - } -#endif - } - } - } -} -#endif - -void RfSnsInit(void) -{ - rfsns_raw_signal = (raw_signal_t*)(malloc(sizeof(raw_signal_t))); - if (rfsns_raw_signal) { - memset(rfsns_raw_signal, 0, sizeof(raw_signal_t)); -#ifdef USE_THEO_V2 - RfSnsInitTheoV2(); -#endif -#ifdef USE_ALECTO_V2 - RfSnsInitAlectoV2(); -#endif - if (rfsns_any_sensor) { - rfsns_rf_bit = digitalPinToBitMask(pin[GPIO_RF_SENSOR]); - rfsns_rf_port = digitalPinToPort(pin[GPIO_RF_SENSOR]); - pinMode(pin[GPIO_RF_SENSOR], INPUT); - } else { - free(rfsns_raw_signal); - rfsns_raw_signal = nullptr; - } - } -} - -void RfSnsAnalyzeRawSignal(void) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal->Number); - -#ifdef USE_THEO_V2 - RfSnsAnalyzeTheov2(); -#endif -#ifdef USE_ALECTO_V2 - RfSnsAnalyzeAlectov2(); -#endif -} - -void RfSnsEverySecond(void) -{ -#ifdef USE_ALECTO_V2 - RfSnsAlectoResetRain(); -#endif -} - -void RfSnsShow(bool json) -{ -#ifdef USE_THEO_V2 - RfSnsTheoV2Show(json); -#endif -#ifdef USE_ALECTO_V2 - RfSnsAlectoV2Show(json); -#endif -} - - - - - -bool Xsns37(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_RF_SENSOR] < 99) && (FUNC_INIT == function)) { - RfSnsInit(); - } - else if (rfsns_raw_signal) { - switch (function) { - case FUNC_LOOP: - if ((*portInputRegister(rfsns_rf_port) &rfsns_rf_bit) == rfsns_rf_bit) { - if (RfSnsFetchSignal(pin[GPIO_RF_SENSOR], HIGH)) { - RfSnsAnalyzeRawSignal(); - } - } - sleep = 0; - break; - case FUNC_EVERY_SECOND: - RfSnsEverySecond(); - break; - case FUNC_JSON_APPEND: - RfSnsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - RfSnsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_38_az7798.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_38_az7798.ino" -#ifdef USE_AZ7798 - -#define XSNS_38 38 -# 112 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_38_az7798.ino" -#include - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#define AZ_READ_TIMEOUT 400 - -#define AZ_CLOCK_UPDATE_INTERVAL (24UL * 60 * 60) -#define AZ_EPOCH (946684800UL) - -TasmotaSerial *AzSerial; - -const char ktype[] = "AZ7798"; -uint8_t az_type = 1; -uint16_t az_co2 = 0; -double az_temperature = 0; -double az_humidity = 0; -uint8_t az_received = 0; -uint8_t az_state = 0; -unsigned long az_clock_update = 10; - - - -void AzEverySecond(void) -{ - unsigned long start = millis(); - - az_state++; - if (5 == az_state) { - az_state = 0; - - AzSerial->flush(); - AzSerial->write(":\r", 2); - az_received = 0; - - uint8_t az_response[32]; - uint8_t counter = 0; - uint8_t i, j; - uint8_t response_substr[16]; - - do { - if (AzSerial->available() > 0) { - az_response[counter] = AzSerial->read(); - if(az_response[counter] == 0x0d) { az_received = 1; } - counter++; - } else { - delay(5); - } - } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received); - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, az_response, counter); - - if (!az_received) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout")); - return; - } - - i = 0; - while((az_response[i] != 'T') && (i < counter)) {i++;} - if(az_response[i] != 'T') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find start of response")); - return; - } - i++; - j = 0; - - while((az_response[i] != 'C') && (az_response[i] != 'F') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if((az_response[i] != 'C') && (az_response[i] != 'F')){ - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of temperature")); - return; - } - response_substr[j] = 0; - az_temperature = CharToFloat((char*)response_substr); - if(az_response[i] == 'C') { - az_temperature = ConvertTemp((float)az_temperature); - } else { - az_temperature = ConvertTemp((az_temperature - 32) / 1.8); - } - i++; - if(az_response[i] != ':') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error first delimiter")); - return; - } - i++; - if(az_response[i] != 'C') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of CO2")); - return; - } - i++; - j = 0; - - while((az_response[i] != 'p') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if(az_response[i] != 'p') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of CO2")); - return; - } - response_substr[j] = 0; - az_co2 = atoi((char*)response_substr); - LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); - i += 3; - if(az_response[i] != ':') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter")); - return; - } - i++; - if(az_response[i] != 'H') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of humidity")); - return; - } - i++; - j = 0; - - while((az_response[i] != '%') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if(az_response[i] != '%') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of humidity")); - return; - } - response_substr[j] = 0; - az_humidity = ConvertHumidity(CharToFloat((char*)response_substr)); - } - - - if ((az_clock_update == 0) && (LocalTime() > AZ_EPOCH)) { - char tmpString[16]; - sprintf(tmpString, "C %d\r", (int)(LocalTime() - AZ_EPOCH)); - AzSerial->write(tmpString); - - do { - if (AzSerial->available() > 0) { - if(AzSerial->read() == 0x0d) { break; } - } else { - delay(5); - } - } while(((millis() - start) < AZ_READ_TIMEOUT)); - az_clock_update = AZ_CLOCK_UPDATE_INTERVAL; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 clock updated")); - } else { - az_clock_update--; - } -} - - - -void AzInit(void) -{ - az_type = 0; - if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) { - AzSerial = new TasmotaSerial(pin[GPIO_AZ_RXD], pin[GPIO_AZ_TXD], 1); - if (AzSerial->begin(9600)) { - if (AzSerial->hardwareSerial()) { ClaimSerial(); } - az_type = 1; - } - } -} - -void AzShow(bool json) -{ - char temperature[33]; - dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), ktype, az_co2, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, ktype, az_co2); - WSContentSend_PD(HTTP_SNS_TEMP, ktype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, ktype, humidity); -#endif - } -} - - - - - -bool Xsns38(uint8_t function) -{ - bool result = false; - - if(az_type){ - switch (function) { - case FUNC_INIT: - AzInit(); - break; - case FUNC_EVERY_SECOND: - AzEverySecond(); - break; - case FUNC_JSON_APPEND: - AzShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AzShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_39_max31855.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_39_max31855.ino" -#ifdef USE_MAX31855 - -#define XSNS_39 39 - -bool initialized = false; - -struct MAX31855_ResultStruct{ - uint8_t ErrorCode; - float ProbeTemperature; - float ReferenceTemperature; -} MAX31855_Result; - -void MAX31855_Init(void){ - if(initialized) - return; - - - pinMode(pin[GPIO_MAX31855CS], OUTPUT); - pinMode(pin[GPIO_MAX31855CLK], OUTPUT); - pinMode(pin[GPIO_MAX31855DO], INPUT); - - - digitalWrite(pin[GPIO_MAX31855CS], HIGH); - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - - initialized = true; -} - - - - - -void MAX31855_GetResult(void){ - int32_t RawData = MAX31855_ShiftIn(32); - uint8_t probeerror = RawData & 0x7; - - MAX31855_Result.ErrorCode = probeerror; - MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); - if(probeerror) - MAX31855_Result.ProbeTemperature = NAN; - else - MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); -} - - - - - - -float MAX31855_GetProbeTemperature(int32_t RawData){ - if(RawData & 0x80000000) - RawData = (RawData >> 18) | 0xFFFFC000; - else - RawData >>= 18; - - float result = (RawData * 0.25); - - return ConvertTemp(result); -} - - - - - -float MAX31855_GetReferenceTemperature(int32_t RawData){ - if(RawData & 0x8000) - RawData = (RawData >> 4) | 0xFFFFF000; - else - RawData = (RawData >> 4) & 0x00000FFF; - - float result = (RawData * 0.0625); - - return ConvertTemp(result); -} - - - - - -int32_t MAX31855_ShiftIn(uint8_t Length){ - int32_t dataIn = 0; - - digitalWrite(pin[GPIO_MAX31855CS], LOW); - delayMicroseconds(1); - - for (uint32_t i = 0; i < Length; i++) - { - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - delayMicroseconds(1); - dataIn <<= 1; - if(digitalRead(pin[GPIO_MAX31855DO])) - dataIn |= 1; - digitalWrite(pin[GPIO_MAX31855CLK], HIGH); - delayMicroseconds(1); - } - - digitalWrite(pin[GPIO_MAX31855CS], HIGH); - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - return dataIn; -} - -void MAX31855_Show(bool Json){ - char probetemp[33]; - char referencetemp[33]; - dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); - dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); - - if(Json){ - ResponseAppend_P(PSTR(",\"MAX31855\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - probetemp, referencetemp, MAX31855_Result.ErrorCode); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, probetemp); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, MAX31855_Result.ProbeTemperature); - } -#endif - } else { -#ifdef USE_WEBSERVER - WSContentSend_PD(HTTP_SNS_TEMP, "MAX31855", probetemp, TempUnit()); -#endif - } -} - - - - - -bool Xsns39(uint8_t function) -{ - bool result = false; - if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ - - switch (function) { - case FUNC_INIT: - MAX31855_Init(); - break; - case FUNC_EVERY_SECOND: - MAX31855_GetResult(); - break; - case FUNC_JSON_APPEND: - MAX31855_Show(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MAX31855_Show(false); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_40_pn532.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_40_pn532.ino" -#ifdef USE_PN532_HSU - -#define XSNS_40 40 - -#include - -TasmotaSerial *PN532_Serial; - -#define PN532_INVALID_ACK -1 -#define PN532_TIMEOUT -2 -#define PN532_INVALID_FRAME -3 -#define PN532_NO_SPACE -4 - -#define PN532_PREAMBLE 0x00 -#define PN532_STARTCODE1 0x00 -#define PN532_STARTCODE2 0xFF -#define PN532_POSTAMBLE 0x00 - -#define PN532_HOSTTOPN532 0xD4 -#define PN532_PN532TOHOST 0xD5 - -#define PN532_ACK_WAIT_TIME 0x0A - -#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 -#define PN532_COMMAND_SAMCONFIGURATION 0x14 -#define PN532_COMMAND_RFCONFIGURATION 0x32 -#define PN532_COMMAND_INDATAEXCHANGE 0x40 -#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A - -#define PN532_MIFARE_ISO14443A 0x00 -#define MIFARE_CMD_READ 0x30 -#define MIFARE_CMD_AUTH_A 0x60 -#define MIFARE_CMD_AUTH_B 0x61 -#define MIFARE_CMD_WRITE 0xA0 - -uint8_t pn532_model = 0; -uint8_t pn532_command = 0; -uint8_t pn532_scantimer = 0; - -uint8_t pn532_packetbuffer[64]; - -#ifdef USE_PN532_DATA_FUNCTION -uint8_t pn532_function = 0; -uint8_t pn532_newdata[16]; -uint8_t pn532_newdata_len = 0; -#endif - -void PN532_Init(void) -{ - if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) { - PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1); - if (PN532_Serial->begin(115200)) { - if (PN532_Serial->hardwareSerial()) { ClaimSerial(); } - PN532_wakeup(); - uint32_t ver = PN532_getFirmwareVersion(); - if (ver) { - PN532_setPassiveActivationRetries(0xFF); - PN532_SAMConfig(); - pn532_model = 1; - AddLog_P2(LOG_LEVEL_INFO,"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); - } - } - } -} - -int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout) -{ - int read_bytes = 0; - int ret; - unsigned long start_millis; - while (read_bytes < len) { - start_millis = millis(); - do { - ret = PN532_Serial->read(); - if (ret >= 0) { - break; - } - } while((timeout == 0) || ((millis()- start_millis ) < timeout)); - - if (ret < 0) { - if (read_bytes) { - return read_bytes; - } else { - return PN532_TIMEOUT; - } - } - buf[read_bytes] = (uint8_t)ret; - read_bytes++; - } - return read_bytes; -} - -int8_t PN532_readAckFrame(void) -{ - const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; - uint8_t ackBuf[sizeof(PN532_ACK)]; - - if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) { - return PN532_TIMEOUT; - } - - if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) { - return PN532_INVALID_ACK; - } - return 0; -} - -int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) -{ - - PN532_Serial->flush(); - - pn532_command = header[0]; - PN532_Serial->write((uint8_t)PN532_PREAMBLE); - PN532_Serial->write((uint8_t)PN532_STARTCODE1); - PN532_Serial->write(PN532_STARTCODE2); - - uint8_t length = hlen + blen + 1; - PN532_Serial->write(length); - PN532_Serial->write(~length + 1); - - PN532_Serial->write(PN532_HOSTTOPN532); - uint8_t sum = PN532_HOSTTOPN532; - - PN532_Serial->write(header, hlen); - for (uint32_t i = 0; i < hlen; i++) { - sum += header[i]; - } - - PN532_Serial->write(body, blen); - for (uint32_t i = 0; i < blen; i++) { - sum += body[i]; - } - - uint8_t checksum = ~sum + 1; - PN532_Serial->write(checksum); - PN532_Serial->write((uint8_t)PN532_POSTAMBLE); - - return PN532_readAckFrame(); -} - -int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50) -{ - uint8_t tmp[3]; - - - if (PN532_receive(tmp, 3, timeout)<=0) { - return PN532_TIMEOUT; - } - if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) { - return PN532_INVALID_FRAME; - } - - - uint8_t length[2]; - if (PN532_receive(length, 2, timeout) <= 0) { - return PN532_TIMEOUT; - } - - if (0 != (uint8_t)(length[0] + length[1])) { - return PN532_INVALID_FRAME; - } - length[0] -= 2; - if (length[0] > len) { - return PN532_NO_SPACE; - } - - - uint8_t cmd = pn532_command + 1; - if (PN532_receive(tmp, 2, timeout) <= 0) { - return PN532_TIMEOUT; - } - if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { - return PN532_INVALID_FRAME; - } - - if (PN532_receive(buf, length[0], timeout) != length[0]) { - return PN532_TIMEOUT; - } - - uint8_t sum = PN532_PN532TOHOST + cmd; - for (uint32_t i=0; i status) { - return 0; - } - - response = pn532_packetbuffer[0]; - response <<= 8; - response |= pn532_packetbuffer[1]; - response <<= 8; - response |= pn532_packetbuffer[2]; - response <<= 8; - response |= pn532_packetbuffer[3]; - - return response; -} - -void PN532_wakeup(void) -{ - uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 }; - PN532_Serial->write(wakeup,sizeof(wakeup)); - - - PN532_Serial->flush(); -} - -bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50) -{ - pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = cardbaudrate; - if (PN532_writeCommand(pn532_packetbuffer, 3)) { - return 0x0; - } - - if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { - return 0x0; - } -# 274 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_40_pn532.ino" - if (pn532_packetbuffer[0] != 1) { - return 0; - } - - uint16_t sens_res = pn532_packetbuffer[2]; - sens_res <<= 8; - sens_res |= pn532_packetbuffer[3]; - - - *uidLength = pn532_packetbuffer[5]; - - for (uint32_t i = 0; i < pn532_packetbuffer[5]; i++) { - uid[i] = pn532_packetbuffer[6 + i]; - } - - return 1; -} - -bool PN532_setPassiveActivationRetries(uint8_t maxRetries) -{ - pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; - pn532_packetbuffer[1] = 5; - pn532_packetbuffer[2] = 0xFF; - pn532_packetbuffer[3] = 0x01; - pn532_packetbuffer[4] = maxRetries; - if (PN532_writeCommand(pn532_packetbuffer, 5)) { - return 0; - } - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -bool PN532_SAMConfig(void) -{ - pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; - pn532_packetbuffer[1] = 0x01; - pn532_packetbuffer[2] = 0x14; - pn532_packetbuffer[3] = 0x00; - if (PN532_writeCommand(pn532_packetbuffer, 4)) { - return false; - } - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -#ifdef USE_PN532_DATA_FUNCTION - -uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) -{ - uint8_t i; - uint8_t _key[6]; - uint8_t _uid[7]; - uint8_t _uidLen; - - - memcpy(&_key, keyData, 6); - memcpy(&_uid, uid, uidLen); - _uidLen = uidLen; - - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; - pn532_packetbuffer[3] = blockNumber; - memcpy(&pn532_packetbuffer[4], &_key, 6); - for (i = 0; i < _uidLen; i++) { - pn532_packetbuffer[10 + i] = _uid[i]; - } - - if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; } - - - PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); - - - - - if (pn532_packetbuffer[0] != 0x00) { - - return 0; - } - - return 1; -} - -uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) -{ - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = MIFARE_CMD_READ; - pn532_packetbuffer[3] = blockNumber; - - - if (PN532_writeCommand(pn532_packetbuffer, 4)) { - return 0; - } - - - PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); - - - if (pn532_packetbuffer[0] != 0x00) { - return 0; - } - - - - memcpy (data, &pn532_packetbuffer[1], 16); - - return 1; -} - -uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) -{ - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = MIFARE_CMD_WRITE; - pn532_packetbuffer[3] = blockNumber; - memcpy(&pn532_packetbuffer[4], data, 16); - - - if (PN532_writeCommand(pn532_packetbuffer, 20)) { - return 0; - } - - - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -#endif - -void PN532_ScanForTag(void) -{ - if (!pn532_model) { return; } - uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; - uint8_t uid_len = 0; - uint8_t card_data[16]; - bool erase_success = false; - bool set_success = false; - if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { - char uids[15]; - -#ifdef USE_PN532_DATA_FUNCTION - char card_datas[34]; -#endif - - ToHex_P((unsigned char*)uid, uid_len, uids, sizeof(uids)); - -#ifdef USE_PN532_DATA_FUNCTION - if (uid_len == 4) { - uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { - if (mifareclassic_ReadDataBlock(1, card_data)) { -#ifdef USE_PN532_DATA_RAW - memcpy(&card_datas,&card_data,sizeof(card_data)); -#else - for (uint32_t i = 0;i < sizeof(card_data);i++) { - if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { - card_datas[i] = char(card_data[i]); - } else { - card_datas[i] = '\0'; - } - } -#endif - } - if (pn532_function == 1) { - for (uint32_t i = 0;i<16;i++) { - card_data[i] = 0x00; - } - if (mifareclassic_WriteDataBlock(1, card_data)) { - erase_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase success")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } - } - if (pn532_function == 2) { -#ifdef USE_PN532_DATA_RAW - memcpy(&card_data,&pn532_newdata,sizeof(card_data)); - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } -#else - bool IsAlphaNumeric = true; - for (uint32_t i = 0;i < pn532_newdata_len;i++) { - if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) { - IsAlphaNumeric = false; - } - } - if (IsAlphaNumeric) { - memcpy(&card_data,&pn532_newdata,pn532_newdata_len); - card_data[pn532_newdata_len] = '\0'; - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } - } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data must be alphanumeric")); - } -#endif - } - } else { - sprintf(card_datas,"AUTHFAIL"); - } - } - switch (pn532_function) { - case 0x01: - if (!erase_success) { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase fail - exiting erase mode")); - } - break; - case 0x02: - if (!set_success) { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Write failed - exiting set mode")); - } - default: - break; - } - pn532_function = 0; -#endif - -#ifdef USE_PN532_DATA_FUNCTION - ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); -#else - ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); -#endif - - MqttPublishTeleSensor(); - -#ifdef USE_PN532_CAUSE_EVENTS - - char command[71]; -#ifdef USE_PN532_DATA_FUNCTION - sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); -#else - sprintf(command,"event PN532_UID=%s",uids); -#endif - ExecuteCommand(command, SRC_RULE); -#endif - - pn532_scantimer = 7; - } -} - -#ifdef USE_PN532_DATA_FUNCTION - -bool PN532_Command(void) -{ - bool serviced = true; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - char sub_string_tmp[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') { - serviced = false; - return serviced; - } - sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); - pn532_newdata_len = strlen(sub_string_tmp); - if (pn532_newdata_len > 15) { pn532_newdata_len = 15; } - memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len); - pn532_newdata[pn532_newdata_len] = 0x00; - pn532_function = 2; - AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); - ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}")); - return serviced; - } - } -} - -#endif - -bool Xsns40(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_INIT: - PN532_Init(); - result = true; - break; - case FUNC_EVERY_50_MSECOND: - break; - case FUNC_EVERY_100_MSECOND: - break; - case FUNC_EVERY_250_MSECOND: - if (pn532_scantimer > 0) { - pn532_scantimer--; - } else { - PN532_ScanForTag(); - } - break; - case FUNC_EVERY_SECOND: - break; -#ifdef USE_PN532_DATA_FUNCTION - case FUNC_COMMAND_SENSOR: - if (XSNS_40 == XdrvMailbox.index) { - result = PN532_Command(); - } - break; -#endif - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_41_max44009.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_41_max44009.ino" -#ifdef USE_I2C -#ifdef USE_MAX44009 - - - - - - -#define XSNS_41 41 -#define XI2C_28 28 - -#define MAX44009_ADDR1 0x4A -#define MAX44009_ADDR2 0x4B -#define MAX44009_NO_REGISTERS 8 -#define REG_CONFIG 0x02 -#define REG_LUMINANCE 0x03 -#define REG_LOWER_THRESHOLD 0x06 -#define REG_THRESHOLD_TIMER 0x07 - -#define MAX44009_CONTINUOUS_AUTO_MODE 0x80 - -uint8_t max44009_address; -uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2, 0 }; -uint8_t max44009_found = 0; -uint8_t max44009_valid = 0; -float max44009_illuminance = 0; -char max44009_types[] = "MAX44009"; - -bool Max4409Read_lum(void) -{ - max44009_valid = 0; - uint8_t regdata[2]; - - - if (I2cValidRead16((uint16_t *)®data, max44009_address, REG_LUMINANCE)) { - int exponent = (regdata[0] & 0xF0) >> 4; - int mantissa = ((regdata[0] & 0x0F) << 4) | (regdata[1] & 0x0F); - max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); - max44009_valid = 1; - return true; - } else { - return false; - } -} - - - -void Max4409Detect(void) -{ - uint8_t buffer1; - uint8_t buffer2; - for (uint32_t i = 0; 0 != max44009_addresses[i]; i++) { - - max44009_address = max44009_addresses[i]; - if (I2cActive(max44009_address)) { continue; } - - if ((I2cValidRead8(&buffer1, max44009_address, REG_LOWER_THRESHOLD)) && - (I2cValidRead8(&buffer2, max44009_address, REG_THRESHOLD_TIMER))) { - - if ((0x00 == buffer1) && - (0xFF == buffer2)) { - - - - Wire.beginTransmission(max44009_address); - - - Wire.write(REG_CONFIG); - Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); - if (0 == Wire.endTransmission()) { - I2cSetActiveFound(max44009_address, max44009_types); - max44009_found = 1; - break; - } - } - } - } -} - -void Max4409EverySecond(void) -{ - Max4409Read_lum(); -} - -void Max4409Show(bool json) -{ - char illum_str[8]; - - if (max44009_valid) { - - - - uint8_t prec = 0; - if (10 > max44009_illuminance ) { - prec = 3; - } else if (100 > max44009_illuminance) { - prec = 2; - } else if (1000 > max44009_illuminance) { - prec = 1; - } - dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, illum_str); - } -#endif -#ifdef USE_WEBSERVER - } else { - - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, max44009_types, (int)max44009_illuminance); -#endif - } - } -} - - - - - -bool Xsns41(uint8_t function) -{ - if (!I2cEnabled(XI2C_28)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Max4409Detect(); - } - else if (max44009_found) { - switch (function) { - case FUNC_EVERY_SECOND: - Max4409EverySecond(); - break; - case FUNC_JSON_APPEND: - Max4409Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Max4409Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_42_scd30.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_42_scd30.ino" -#ifdef USE_I2C -#ifdef USE_SCD30 - -#define XSNS_42 42 -#define XI2C_29 29 - - - -#define SCD30_ADDRESS 0x61 - -#define SCD30_MAX_MISSED_READS 3 -#define SCD30_STATE_NO_ERROR 0 -#define SCD30_STATE_ERROR_DATA_CRC 1 -#define SCD30_STATE_ERROR_READ_MEAS 2 -#define SCD30_STATE_ERROR_SOFT_RESET 3 -#define SCD30_STATE_ERROR_I2C_RESET 4 -#define SCD30_STATE_ERROR_UNKNOWN 5 - -#include "Arduino.h" -#include - -#define D_CMND_SCD30 "SCD30" - -const char S_JSON_SCD30_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d}"; -const char S_JSON_SCD30_COMMAND_NFW_VALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d.%d}"; -const char S_JSON_SCD30_COMMAND[] PROGMEM = "{\"" D_CMND_SCD30 "%s\"}"; -const char kSCD30_Commands[] PROGMEM = "Alt|Auto|Cal|FW|Int|Pres|TOff"; - - - - - -enum SCD30_Commands { - CMND_SCD30_ALTITUDE, - CMND_SCD30_AUTOMODE, - CMND_SCD30_CALIBRATE, - CMND_SCD30_FW, - CMND_SCD30_INTERVAL, - CMND_SCD30_PRESSURE, - CMND_SCD30_TEMPOFFSET -}; - -FrogmoreScd30 scd30; - -bool scd30Found = false; -bool scd30IsDataValid = false; -int scd30ErrorState = SCD30_STATE_NO_ERROR; -uint16_t scd30Interval_sec; -int scd30Loop_count = 0; -int scd30DataNotAvailable_count = 0; -int scd30GoodMeas_count = 0; -int scd30Reset_count = 0; -int scd30CrcError_count = 0; -int scd30Co2Zero_count = 0; -int i2cReset_count = 0; -uint16_t scd30_CO2 = 0; -uint16_t scd30_CO2EAvg = 0; -float scd30_Humid = 0.0; -float scd30_Temp = 0.0; - -void Scd30Detect(void) -{ - if (I2cActive(SCD30_ADDRESS)) { return; } - - scd30.begin(); - - uint8_t major = 0; - uint8_t minor = 0; - if (scd30.getFirmwareVersion(&major, &minor)) { return; } - uint16_t interval_sec; - if (scd30.getMeasurementInterval(&scd30Interval_sec)) { return; } - if (scd30.beginMeasuring()) { return; } - - I2cSetActiveFound(SCD30_ADDRESS, "SCD30"); - scd30Found = true; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SCD: FW v%d.%d"), major, minor); -} - - -void Scd30Update(void) -{ - scd30Loop_count++; - if (scd30Loop_count > (scd30Interval_sec - 1)) { - int error = 0; - switch (scd30ErrorState) { - case SCD30_STATE_NO_ERROR: { - error = scd30.readMeasurement(&scd30_CO2, &scd30_CO2EAvg, &scd30_Temp, &scd30_Humid); - switch (error) { - case ERROR_SCD30_NO_ERROR: - scd30Loop_count = 0; - scd30IsDataValid = true; - scd30GoodMeas_count++; - break; - - case ERROR_SCD30_NO_DATA: - scd30DataNotAvailable_count++; - break; - - case ERROR_SCD30_CRC_ERROR: - scd30ErrorState = SCD30_STATE_ERROR_DATA_CRC; - scd30CrcError_count++; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), - scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); -#endif - break; - - case ERROR_SCD30_CO2_ZERO: - scd30Co2Zero_count++; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), - scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); -#endif - break; - - default: { - scd30ErrorState = SCD30_STATE_ERROR_READ_MEAS; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, scd30Loop_count); -#endif - return; - } - break; - } - } - break; - - case SCD30_STATE_ERROR_DATA_CRC: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: got CRC error, try again, counter: %ld"), scd30Loop_count); -#endif - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - break; - - case SCD30_STATE_ERROR_READ_MEAS: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: not answering, sending soft reset, counter: %ld"), scd30Loop_count); -#endif - scd30Reset_count++; - error = scd30.softReset(); - if (error) { -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: resetting got error: 0x%lX"), error); -#endif - error >>= 8; - if (error == 4) { - scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; - } else { - scd30ErrorState = SCD30_STATE_ERROR_UNKNOWN; - } - } else { - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - } - break; - - case SCD30_STATE_ERROR_SOFT_RESET: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog_P(LOG_LEVEL_ERROR, PSTR("SCD30: clearing i2c bus")); -#endif - i2cReset_count++; - error = scd30.clearI2CBus(); - if (error) { - scd30ErrorState = SCD30_STATE_ERROR_I2C_RESET; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error clearing i2c bus: 0x%lX"), error); -#endif - } else { - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - } - break; - - default: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: unknown error state: 0x%lX"), scd30ErrorState); -#endif - scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; - } - } - - if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) { - scd30IsDataValid = false; - } - } -} - - -int Scd30GetCommand(int command_code, uint16_t *pvalue) -{ - switch (command_code) - { - case CMND_SCD30_ALTITUDE: - return scd30.getAltitudeCompensation(pvalue); - break; - - case CMND_SCD30_AUTOMODE: - return scd30.getCalibrationType(pvalue); - break; - - case CMND_SCD30_CALIBRATE: - return scd30.getForcedRecalibrationFactor(pvalue); - break; - - case CMND_SCD30_INTERVAL: - return scd30.getMeasurementInterval(pvalue); - break; - - case CMND_SCD30_PRESSURE: - return scd30.getAmbientPressure(pvalue); - break; - - case CMND_SCD30_TEMPOFFSET: - return scd30.getTemperatureOffset(pvalue); - break; - - default: - - break; - } -} - -int Scd30SetCommand(int command_code, uint16_t value) -{ - switch (command_code) - { - case CMND_SCD30_ALTITUDE: - return scd30.setAltitudeCompensation(value); - break; - - case CMND_SCD30_AUTOMODE: - return scd30.setCalibrationType(value); - break; - - case CMND_SCD30_CALIBRATE: - return scd30.setForcedRecalibrationFactor(value); - break; - - case CMND_SCD30_INTERVAL: - { - int error = scd30.setMeasurementInterval(value); - if (!error) - { - scd30Interval_sec = value; - } - - return error; - } - break; - - case CMND_SCD30_PRESSURE: - return scd30.setAmbientPressure(value); - break; - - case CMND_SCD30_TEMPOFFSET: - return scd30.setTemperatureOffset(value); - break; - - default: - - break; - } -} - - - - - -bool Scd30CommandSensor() -{ - char command[CMDSZ]; - bool serviced = true; - uint8_t prefix_len = strlen(D_CMND_SCD30); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_SCD30), prefix_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + prefix_len, kSCD30_Commands); - - switch (command_code) { - case CMND_SCD30_ALTITUDE: - case CMND_SCD30_AUTOMODE: - case CMND_SCD30_CALIBRATE: - case CMND_SCD30_INTERVAL: - case CMND_SCD30_PRESSURE: - case CMND_SCD30_TEMPOFFSET: - { - uint16_t value = 0; - if (XdrvMailbox.data_len > 0) - { - value = XdrvMailbox.payload; - Scd30SetCommand(command_code, value); - } - else - { - Scd30GetCommand(command_code, &value); - } - - Response_P(S_JSON_SCD30_COMMAND_NVALUE, command, value); - } - break; - - case CMND_SCD30_FW: - { - uint8_t major = 0; - uint8_t minor = 0; - int error; - error = scd30.getFirmwareVersion(&major, &minor); - if (error) - { -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error getting FW version: 0x%lX"), error); -#endif - serviced = false; - } - else - { - Response_P(S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); - } - } - break; - - default: - - serviced = false; - break; - } - } - return serviced; -} - -void Scd30Show(bool json) -{ - if (scd30IsDataValid) - { - char humidity[10]; - dtostrfd(ConvertHumidity(scd30_Humid), Settings.flag2.humidity_resolution, humidity); - char temperature[10]; - dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); - - if (json) { - - ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), - scd30_CO2, scd30_CO2EAvg, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) - { - DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); - WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); - WSContentSend_PD(HTTP_SNS_TEMP, "SCD30", temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, "SCD30", humidity); -#endif - } - } -} - - - - - -bool Xsns42(byte function) -{ - if (!I2cEnabled(XI2C_29)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Scd30Detect(); - } - else if (scd30Found) { - switch (function) { - case FUNC_EVERY_SECOND: - Scd30Update(); - break; - case FUNC_COMMAND: - result = Scd30CommandSensor(); - break; - case FUNC_JSON_APPEND: - Scd30Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Scd30Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_43_hre.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_43_hre.ino" -#ifdef USE_HRE -# 49 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_43_hre.ino" -#define XSNS_43 43 - -enum hre_states { - hre_idle, - hre_sync, - hre_syncing, - hre_read, - hre_reading, - hre_sleep, - hre_sleeping -}; - -hre_states hre_state = hre_idle; - -float hre_usage = 0; -float hre_rate = 0; -uint32_t hre_usage_time = 0; - -int hre_read_errors = 0; -bool hre_good = false; - - - -int hreReadBit() -{ - digitalWrite(pin[GPIO_HRE_CLOCK], HIGH); - delay(1); - int bit = digitalRead(pin[GPIO_HRE_DATA]); - digitalWrite(pin[GPIO_HRE_CLOCK], LOW); - delay(1); - return bit; -} - - - -char hreReadChar(int &parity_errors) -{ - - hreReadBit(); - - unsigned ch=0; - int sum=0; - for (uint32_t i=0; i<7; i++) - { - int b = hreReadBit(); - ch |= b << i; - sum += b; - } - - - if ( (sum & 0x1) != hreReadBit()) - parity_errors++; - - - hreReadBit(); - - return ch; -} - -void hreInit(void) -{ - hre_read_errors = 0; - hre_good = false; - - pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); - pinMode(pin[GPIO_HRE_DATA], INPUT); - - - - digitalWrite(pin[GPIO_HRE_CLOCK], LOW); - - hre_state = hre_sync; -} - - -void hreEvery50ms(void) -{ - static int sync_counter = 0; - static int sync_run = 0; - - static uint32_t curr_start = 0; - static int read_counter = 0; - static int parity_errors = 0; - static char buff[46]; - - static char ch; - static size_t i; - - switch (hre_state) - { - case hre_sync: - if (uptime < 10) - break; - sync_run = 0; - sync_counter = 0; - hre_state = hre_syncing; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); - break; - - case hre_syncing: - - - for (uint32_t i=0; i<20; i++) - { - if (hreReadBit()) - sync_run++; - else - sync_run = 0; - if (sync_run == 62) - { - hre_state = hre_read; - break; - } - sync_counter++; - } - - if (sync_counter > 1000) - { - hre_state = hre_sleep; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE D_ERROR)); - } - break; - - - case hre_read: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); - read_counter = 0; - parity_errors = 0; - curr_start = uptime; - memset(buff, 0, sizeof(buff)); - hre_state = hre_reading; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); - - - - - - case hre_reading: - - buff[read_counter++] = hreReadChar(parity_errors); - buff[read_counter++] = hreReadChar(parity_errors); - - if (read_counter == 46) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), - parity_errors, hre_read_errors, buff); - if (parity_errors == 0) - { - float curr_usage; - curr_usage = 0.01 * atol(buff+24); - if (hre_usage_time) - { - double dt = 1.666e-2 * (curr_start - hre_usage_time); - hre_rate = (curr_usage - hre_usage)/dt; - } - hre_usage = curr_usage; - hre_usage_time = curr_start; - hre_good = true; - - hre_state = hre_sleep; - } - else - { - hre_read_errors++; - hre_state = hre_sleep; - } - } - break; - - case hre_sleep: - hre_usage_time = curr_start; - hre_state = hre_sleeping; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_sleeping")); - - case hre_sleeping: - - - if (uptime - hre_usage_time >= 27) - hre_state = hre_sync; - } -} - -void hreShow(boolean json) -{ - if (!hre_good) - return; - - const char *id = "HRE"; - - char usage[16]; - char rate[16]; - dtostrfd(hre_usage, 2, usage); - dtostrfd(hre_rate, 3, rate); - - if (json) - { - ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_GALLONS, id, usage); - WSContentSend_PD(HTTP_SNS_GPM, id, rate); -#endif - } -} - - - - - -bool Xsns43(byte function) -{ - - if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) - return false; - - switch (function) - { - case FUNC_INIT: - hreInit(); - break; - case FUNC_EVERY_50_MSECOND: - hreEvery50ms(); - break; - case FUNC_EVERY_SECOND: - break; - case FUNC_JSON_APPEND: - hreShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - hreShow(0); - break; -#endif - } - return false; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_44_sps30.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_44_sps30.ino" -#ifdef USE_I2C -#ifdef USE_SPS30 - -#define XSNS_44 44 -#define XI2C_30 30 - -#define SPS30_ADDR 0x69 - -#include -#include - -uint8_t sps30_ready = 0; -uint8_t sps30_running; - -struct SPS30 { - float PM1_0; - float PM2_5; - float PM4_0; - float PM10; - float NCPM0_5; - float NCPM1_0; - float NCPM2_5; - float NCPM4_0; - float NCPM10; - float TYPSIZ; -} sps30_result; - -#define SPS_CMD_START_MEASUREMENT 0x0010 -#define SPS_CMD_START_MEASUREMENT_ARG 0x0300 -#define SPS_CMD_STOP_MEASUREMENT 0x0104 -#define SPS_CMD_READ_MEASUREMENT 0x0300 -#define SPS_CMD_GET_DATA_READY 0x0202 -#define SPS_CMD_AUTOCLEAN_INTERVAL 0x8004 -#define SPS_CMD_CLEAN 0x5607 -#define SPS_CMD_GET_ACODE 0xd025 -#define SPS_CMD_GET_SERIAL 0xd033 -#define SPS_CMD_RESET 0xd304 -#define SPS_WRITE_DELAY_US 20000 -#define SPS_MAX_SERIAL_LEN 32 - -uint8_t sps30_calc_CRC(uint8_t *data) { - uint8_t crc = 0xFF; - for (uint32_t i = 0; i < 2; i++) { - crc ^= data[i]; - for (uint32_t bit = 8; bit > 0; --bit) { - if(crc & 0x80) { - crc = (crc << 1) ^ 0x31u; - } else { - crc = (crc << 1); - } - } - } - return crc; -} - -void CmdClean(void); - -unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop); - -void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen) { -unsigned char cmdb[2]; -uint8_t tmp[3]; -uint8_t index=0; -memset(data,0,dlen); -uint8_t twi_buff[64]; - - Wire.beginTransmission(SPS30_ADDR); - cmdb[0]=cmd>>8; - cmdb[1]=cmd; - Wire.write(cmdb,2); - Wire.endTransmission(); - - - dlen/=2; - dlen*=3; - - twi_readFrom(SPS30_ADDR,twi_buff,dlen,1); - - uint8_t bind=0; - while (bind>8; - cmdb[1]=cmd; - - if (cmd==SPS_CMD_START_MEASUREMENT) { - cmdb[2]=SPS_CMD_START_MEASUREMENT_ARG>>8; - cmdb[3]=SPS_CMD_START_MEASUREMENT_ARG&0xff; - cmdb[4]=sps30_calc_CRC(&cmdb[2]); - Wire.write(cmdb,5); - } else { - Wire.write(cmdb,2); - } - Wire.endTransmission(); -} - -void SPS30_Detect(void) -{ - if (!I2cSetDevice(SPS30_ADDR)) { return; } - I2cSetActiveFound(SPS30_ADDR, "SPS30"); - - uint8_t dcode[32]; - sps30_get_data(SPS_CMD_GET_SERIAL,dcode,sizeof(dcode)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("sps30 found with serial: %s"),dcode); - sps30_cmd(SPS_CMD_START_MEASUREMENT); - sps30_running = 1; - sps30_ready = 1; -} - -#define D_UNIT_PM "ug/m3" -#define D_UNIT_NCPM "#/m3" - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SPS30_a[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_PM "{e}"; -const char HTTP_SNS_SPS30_b[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_NCPM "{e}"; -const char HTTP_SNS_SPS30_c[] PROGMEM ="{s}SPS30 " "TYPSIZ" "{m}%s " "um" "{e}"; -#endif - -#define PMDP 2 - -#define SPS30_HOURS Settings.sps30_inuse_hours - - - -void SPS30_Every_Second() { - if (!sps30_running) return; - - if (uptime%10==0) { - uint8_t vars[sizeof(float)*10]; - sps30_get_data(SPS_CMD_READ_MEASUREMENT,vars,sizeof(vars)); - float *fp=&sps30_result.PM1_0; - - typedef union { - uint8_t array[4]; - float value; - } ByteToFloat; - - ByteToFloat conv; - - for (uint32_t count=0; count<10; count++) { - for (uint32_t i = 0; i < 4; i++){ - conv.array[3-i] = vars[count*sizeof(float)+i]; - } - *fp++=conv.value; - } - } - - if (uptime%3600==0 && uptime>60) { - - - SPS30_HOURS++; - if (SPS30_HOURS>(7*24)) { - CmdClean(); - SPS30_HOURS=0; - } - } - -} - -void SPS30_Show(bool json) -{ - if (!sps30_running) { return; } - - char str[64]; - if (json) { - dtostrfd(sps30_result.PM1_0,PMDP,str); - ResponseAppend_P(PSTR(",\"SPS30\":{\"" "PM1_0" "\":%s"), str); - dtostrfd(sps30_result.PM2_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM2_5" "\":%s"), str); - dtostrfd(sps30_result.PM4_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM4_0" "\":%s"), str); - dtostrfd(sps30_result.PM10,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM10" "\":%s"), str); - dtostrfd(sps30_result.NCPM0_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM0_5" "\":%s"), str); - dtostrfd(sps30_result.NCPM1_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM1_0" "\":%s"), str); - dtostrfd(sps30_result.NCPM2_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM2_5" "\":%s"), str); - dtostrfd(sps30_result.NCPM4_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM4_0" "\":%s"), str); - dtostrfd(sps30_result.NCPM10,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM10" "\":%s"), str); - dtostrfd(sps30_result.TYPSIZ,PMDP,str); - ResponseAppend_P(PSTR(",\"" "TYPSIZ" "\":%s}"), str); - -#ifdef USE_WEBSERVER - } else { - dtostrfd(sps30_result.PM1_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 1.0",str); - dtostrfd(sps30_result.PM2_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 2.5",str); - dtostrfd(sps30_result.PM4_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 4.0",str); - dtostrfd(sps30_result.PM10,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 10",str); - dtostrfd(sps30_result.NCPM0_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 0.5",str); - dtostrfd(sps30_result.NCPM1_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 1.0",str); - dtostrfd(sps30_result.NCPM2_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 2.5",str); - dtostrfd(sps30_result.NCPM4_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 4.0",str); - dtostrfd(sps30_result.NCPM10,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 10",str); - dtostrfd(sps30_result.TYPSIZ,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_c,str); -#endif - } -} - -void CmdClean(void) -{ - sps30_cmd(SPS_CMD_CLEAN); - ResponseTime_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}")); - MqttPublishTeleSensor(); -} - -bool SPS30_cmd(void) -{ - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - char *cp=XdrvMailbox.data; - if (*cp=='c') { - - CmdClean(); - } else if (*cp=='0' || *cp=='1') { - sps30_running=*cp&1; - sps30_cmd(sps30_running?SPS_CMD_START_MEASUREMENT:SPS_CMD_STOP_MEASUREMENT); - } else { - serviced=false; - } - } - Response_P(PSTR("{\"SPS30\":\"%s\"}"), sps30_running?"running":"stopped"); - - return serviced; -} - - - - - -bool Xsns44(byte function) -{ - if (!I2cEnabled(XI2C_30)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - SPS30_Detect(); - } - else if (sps30_ready) { - switch (function) { - case FUNC_EVERY_SECOND: - SPS30_Every_Second(); - break; - case FUNC_JSON_APPEND: - SPS30_Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SPS30_Show(0); - break; - #endif - case FUNC_COMMAND_SENSOR: - if (XSNS_44 == XdrvMailbox.index) { - result = SPS30_cmd(); - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_45_vl53l0x.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_45_vl53l0x.ino" -#ifdef USE_I2C -#ifdef USE_VL53L0X - -#define XSNS_45 45 -#define XI2C_31 31 - -#include -#include "VL53L0X.h" -VL53L0X sensor; - -uint8_t vl53l0x_ready = 0; -uint16_t vl53l0x_distance; -uint16_t Vl53l0_buffer[5]; -uint8_t Vl53l0_index; - - - -void Vl53l0Detect(void) -{ - if (!I2cSetDevice(0x29)) { return; } - - if (!sensor.init()) { return; } - - I2cSetActiveFound(sensor.getAddress(), "VL53L0X"); - - sensor.setTimeout(500); - - - - - - sensor.startContinuous(); - vl53l0x_ready = 1; - - Vl53l0_index=0; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_VL53L0X[] PROGMEM = - "{s}VL53L0X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; -#endif - -#define USE_VL_MEDIAN - -void Vl53l0Every_250MSecond(void) -{ - uint16_t tbuff[5],tmp; - uint8_t flag; - - - uint16_t dist = sensor.readRangeContinuousMillimeters(); - if (dist==0 || dist>2000) { - dist=9999; - } - -#ifdef USE_VL_MEDIAN - - Vl53l0_buffer[Vl53l0_index]=dist; - Vl53l0_index++; - if (Vl53l0_index>=5) Vl53l0_index=0; - - - memmove(tbuff,Vl53l0_buffer,sizeof(tbuff)); - for (byte ocnt=0; ocnt<5; ocnt++) { - flag=0; - for (byte count=0; count<4; count++) { - if (tbuff[count]>tbuff[count+1]) { - tmp=tbuff[count]; - tbuff[count]=tbuff[count+1]; - tbuff[count+1]=tmp; - flag=1; - } - } - if (!flag) break; - } - vl53l0x_distance=tbuff[2]; -#else - vl53l0x_distance=dist; -#endif -} - -void Vl53l0Show(boolean json) -{ - if (json) { - ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l0x_distance); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_VL53L0X, vl53l0x_distance); -#endif - } -} - - - - - -bool Xsns45(byte function) -{ - if (!I2cEnabled(XI2C_31)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Vl53l0Detect(); - } - else if (vl53l0x_ready) { - switch (function) { - case FUNC_EVERY_250_MSECOND: - Vl53l0Every_250MSecond(); - break; - case FUNC_JSON_APPEND: - Vl53l0Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Vl53l0Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_46_MLX90614.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_46_MLX90614.ino" -#ifdef USE_I2C -#ifdef USE_MLX90614 - -#define XSNS_46 46 -#define XI2C_32 32 - -#define I2_ADR_IRT 0x5a - -#define MLX90614_RAWIR1 0x04 -#define MLX90614_RAWIR2 0x05 -#define MLX90614_TA 0x06 -#define MLX90614_TOBJ1 0x07 -#define MLX90614_TOBJ2 0x08 - -struct { - union { - uint16_t value; - uint32_t i2c_buf; - }; - float obj_temp; - float amb_temp; - bool ready = false; -} mlx90614; - -void MLX90614_Init(void) -{ - if (!I2cSetDevice(I2_ADR_IRT)) { return; } - I2cSetActiveFound(I2_ADR_IRT, "MLX90614"); - mlx90614.ready = true; -} - -void MLX90614_Every_Second(void) -{ - mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT, MLX90614_TOBJ1); - if (mlx90614.value & 0x8000) { - mlx90614.obj_temp = -999; - } else { - mlx90614.obj_temp = ((float)mlx90614.value * 0.02) - 273.15; - } - mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT,MLX90614_TA); - if (mlx90614.value & 0x8000) { - mlx90614.amb_temp = -999; - } else { - mlx90614.amb_temp = ((float)mlx90614.value * 0.02) - 273.15; - } -} - -#ifdef USE_WEBSERVER - const char HTTP_IRTMP[] PROGMEM = - "{s}MXL90614 " "OBJ-" D_TEMPERATURE "{m}%s C" "{e}" - "{s}MXL90614 " "AMB-" D_TEMPERATURE "{m}%s C" "{e}"; -#endif - -void MLX90614_Show(uint8_t json) -{ - char obj_tstr[16]; - dtostrfd(mlx90614.obj_temp, Settings.flag2.temperature_resolution, obj_tstr); - char amb_tstr[16]; - dtostrfd(mlx90614.amb_temp, Settings.flag2.temperature_resolution, amb_tstr); - - if (json) { - ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr, amb_tstr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_IRTMP, obj_tstr, amb_tstr); -#endif - } -} - - - - - -bool Xsns46(byte function) -{ - if (!I2cEnabled(XI2C_32)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MLX90614_Init(); - } - else if (mlx90614.ready) { - switch (function) { - case FUNC_EVERY_SECOND: - MLX90614_Every_Second(); - break; - case FUNC_JSON_APPEND: - MLX90614_Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MLX90614_Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_47_max31865.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_47_max31865.ino" -#ifdef USE_MAX31865 - -#ifndef USE_SPI -#error "MAX31865 requires USE_SPI enabled" -#endif - -#include "Adafruit_MAX31865.h" - -#define XSNS_47 47 - -#if MAX31865_PTD_WIRES == 4 - #define PTD_WIRES MAX31865_4WIRE -#elif MAX31865_PTD_WIRES == 3 - #define PTD_WIRES MAX31865_3WIRE -#else - #define PTD_WIRES MAX31865_2WIRE -#endif - -int8_t init_status = 0; - -Adafruit_MAX31865 max31865; - -struct MAX31865_Result_Struct { - uint8_t ErrorCode; - uint16_t Rtd; - float PtdResistance; - float PtdTemp; -} MAX31865_Result; - -void MAX31865_Init(void){ - if(init_status) - return; - - max31865.setPins( - pin[GPIO_SSPI_CS], - pin[GPIO_SSPI_MOSI], - pin[GPIO_SSPI_MISO], - pin[GPIO_SSPI_SCLK] - ); - - if(max31865.begin(PTD_WIRES)) - init_status = 1; - else - init_status = -1; -} - - - - - -void MAX31865_GetResult(void){ - uint16_t rtd; - - rtd = max31865.readRTD(); - MAX31865_Result.Rtd = rtd; - MAX31865_Result.PtdResistance = max31865.rtd_to_resistance(rtd, MAX31865_REF_RES); - MAX31865_Result.PtdTemp = max31865.rtd_to_temperature(rtd, MAX31865_PTD_RES, MAX31865_REF_RES) + MAX31865_PTD_BIAS; -} - -void MAX31865_Show(bool Json){ - char temperature[33]; - char resistance[33]; - - dtostrfd(MAX31865_Result.PtdResistance, Settings.flag2.temperature_resolution, resistance); - dtostrfd(MAX31865_Result.PtdTemp, Settings.flag2.temperature_resolution, temperature); - - if(Json){ - ResponseAppend_P(PSTR(",\"MAX31865\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - temperature, resistance, MAX31865_Result.ErrorCode); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, MAX31865_Result.PtdTemp); - } -#endif - } else { -#ifdef USE_WEBSERVER - WSContentSend_PD(HTTP_SNS_TEMP, "MAX31865", temperature, TempUnit()); -#endif - } -} - - - - - -bool Xsns47(uint8_t function) -{ - bool result = false; - if((pin[GPIO_SSPI_MISO] < 99) && (pin[GPIO_SSPI_MOSI] < 99) && - (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_CS] < 99)) { - - switch (function) { - case FUNC_INIT: - MAX31865_Init(); - break; - - case FUNC_EVERY_SECOND: - MAX31865_GetResult(); - break; - - case FUNC_JSON_APPEND: - MAX31865_Show(true); - break; - -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MAX31865_Show(false); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_48_chirp.ino" -# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_48_chirp.ino" -#ifdef USE_I2C -#ifdef USE_CHIRP -# 47 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_48_chirp.ino" -#define XSNS_48 48 -#define XI2C_33 33 - -#define CHIRP_MAX_SENSOR_COUNT 3 - -#define CHIRP_ADDR_STANDARD 0x20 - - - - - -#define D_CMND_CHIRP "CHIRP" - -const char S_JSON_CHIRP_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_CHIRP "%s\":%d}"; -const char S_JSON_CHIRP_COMMAND[] PROGMEM = "{\"" D_CMND_CHIRP "%s\"}"; -const char kCHIRP_Commands[] PROGMEM = "Select|Set|Scan|Reset|Sleep|Wake"; - -const char kChirpTypes[] PROGMEM = "CHIRP"; - - - - - -enum CHIRP_Commands { - CMND_CHIRP_SELECT, - CMND_CHIRP_SET, - CMND_CHIRP_SCAN, - CMND_CHIRP_RESET, - CMND_CHIRP_SLEEP, - CMND_CHIRP_WAKE }; - - - - - - -#define CHIRP_GET_CAPACITANCE 0x00 -#define CHIRP_SET_ADDRESS 0x01 -#define CHIRP_GET_ADDRESS 0x02 -#define CHIRP_MEASURE_LIGHT 0x03 -#define CHIRP_GET_LIGHT 0x04 -#define CHIRP_GET_TEMPERATURE 0x05 -#define CHIRP_RESET 0x06 -#define CHIRP_GET_VERSION 0x07 -#define CHIRP_SLEEP 0x08 -#define CHIRP_GET_BUSY 0x09 - - - - - -void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg) { - Wire.beginTransmission(addr); - Wire.write(reg); - Wire.endTransmission(); -} - -uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr) { - Wire.requestFrom(addr,(uint8_t)2); - uint16_t t = Wire.read() << 8; - t = t | Wire.read(); - return t; -} - - - - - -uint8_t chirp_current = 0; -uint8_t chirp_found_sensors = 0; - -char chirp_name[7]; -uint8_t chirp_next_job = 0; -uint32_t chirp_timeout_count = 0; - -#pragma pack(1) -struct ChirpSensor_t{ - uint16_t moisture = 0; - uint16_t light = 0; - int16_t temperature = 0; - uint8_t version = 0; - uint8_t address:7; - uint8_t explicitSleep:1; -}; -#pragma pack() - -ChirpSensor_t chirp_sensor[CHIRP_MAX_SENSOR_COUNT]; - - - -void ChirpReset(uint8_t addr) { - ChirpWriteI2CRegister(addr, CHIRP_RESET); -} - - - -void ChirpResetAll(void) { - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version) { - ChirpReset(chirp_sensor[i].address); - } - } -} - - -void ChirpClockSet() { - Wire.setClockStretchLimit(4000); - Wire.setClock(50000); -} - - - -void ChirpSleep(uint8_t addr) { - ChirpWriteI2CRegister(addr, CHIRP_SLEEP); -} -# 185 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_48_chirp.ino" -void ChirpSelect(uint8_t sensor) { - if(sensor < chirp_found_sensors) { - chirp_current = sensor; - DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u now active."), chirp_current); - } - if (sensor == 255) { - DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u active at address 0x%x."), chirp_current, chirp_sensor[chirp_current].address); - } -} - - - -uint8_t ChirpReadVersion(uint8_t addr) { - return (I2cRead8(addr, CHIRP_GET_VERSION)); -} - - - -bool ChirpSet(uint8_t addr) { - if(addr < 128){ - if (I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr)){ - if(chirp_sensor[chirp_current].version>0x25 && chirp_sensor[chirp_current].version != 255){ - delay(5); - I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); - - } - DEBUG_SENSOR_LOG(PSTR("CHIRP: Wrote adress %u "), addr); - ChirpReset(chirp_sensor[chirp_current].address); - chirp_sensor[chirp_current].address = addr; - chirp_timeout_count = 10; - chirp_next_job = 0; - if(chirp_sensor[chirp_current].version == 255){ - AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: wrote new address %u, please power off device"), addr); - chirp_sensor[chirp_current].version == 0; - } - return true; - } - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: address %u incorrect and not used"), addr); - return false; -} - - - -bool ChirpScan() -{ - ChirpClockSet(); - chirp_found_sensors = 0; - for (uint8_t address = 1; address <= 127; address++) { - chirp_sensor[chirp_found_sensors].version = 0; - chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); - delay(2); - chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); - if (chirp_sensor[chirp_found_sensors].version > 0) { - I2cSetActiveFound(address, "CHIRP"); - if (chirp_found_sensors 0); -} - - - -void ChirpDetect(void) -{ - if (chirp_next_job > 0) { return; } - - DEBUG_SENSOR_LOG(PSTR("CHIRP: scan will start ...")); - if (ChirpScan()) { - uint8_t chirp_model = 0; - GetTextIndexed(chirp_name, sizeof(chirp_name), chirp_model, kChirpTypes); - } -} - - -void ChirpServiceAllSensors(uint8_t job){ - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare for sensor at address 0x%x"), chirp_sensor[i].address); - switch(job){ - case 0: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_CAPACITANCE); - break; - case 1: - chirp_sensor[i].moisture = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - case 2: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_TEMPERATURE); - break; - case 3: - chirp_sensor[i].temperature = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - case 4: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_MEASURE_LIGHT); - break; - case 5: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_LIGHT); - break; - case 6: - chirp_sensor[i].light = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - default: - break; - } - } - } -} - - - -void ChirpEvery100MSecond(void) -{ - - if(chirp_timeout_count == 0) { - switch(chirp_next_job) { - case 0: - DEBUG_SENSOR_LOG(PSTR("CHIRP: reset all")); - ChirpResetAll(); - chirp_timeout_count = 10; - chirp_next_job++; - break; - case 1: - - - chirp_next_job++; - break; - case 2: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read")); - ChirpServiceAllSensors(0); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 3: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read")); - ChirpServiceAllSensors(1); - chirp_next_job++; - break; - case 4: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read - 2nd")); - ChirpServiceAllSensors(0); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 5: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read - 2nd")); - ChirpServiceAllSensors(1); - chirp_next_job++; - break; - case 6: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read")); - ChirpServiceAllSensors(2); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 7: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read")); - ChirpServiceAllSensors(3); - chirp_next_job++; - break; - case 8: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read - 2nd")); - ChirpServiceAllSensors(2); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 9: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read - 2nd")); - ChirpServiceAllSensors(3); - chirp_next_job++; - break; - case 10: - DEBUG_SENSOR_LOG(PSTR("CHIRP: start light measure process")); - ChirpServiceAllSensors(4); - chirp_timeout_count = 90; - chirp_next_job++; - break; - case 11: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare light read")); - ChirpServiceAllSensors(5); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 12: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish light read")); - ChirpServiceAllSensors(6); - chirp_next_job++; - break; - case 13: - DEBUG_SENSOR_LOG(PSTR("CHIRP: paused, waiting for TELE")); - break; - case 14: - if (Settings.tele_period > 16){ - chirp_timeout_count = (Settings.tele_period - 17) * 10; - DEBUG_SENSOR_LOG(PSTR("CHIRP: timeout 1/10 sec: %u, tele: %u"), chirp_timeout_count, Settings.tele_period); - } - else{ - AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: TELEPERIOD must be > 16 seconds !")); - - } - chirp_next_job = 1; - break; - } - } - else { - chirp_timeout_count--; - } -} - - - - -#ifdef USE_WEBSERVER - - -const char HTTP_SNS_DARKNESS[] PROGMEM = "{s} " D_JSON_DARKNESS "{m}%s %%{e}"; -const char HTTP_SNS_CHIRPVER[] PROGMEM = "{s} CHIRP-sensor %u at address{m}0x%x{e}" - "{s} FW-version{m}%s {e}"; ; -const char HTTP_SNS_CHIRPSLEEP[] PROGMEM = "{s} {m} is sleeping ...{e}"; -#endif - - - -void ChirpShow(bool json) -{ - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version) { - - char str_temperature[33]; - double t_temperature = ((double) chirp_sensor[i].temperature )/10.0; - dtostrfd(t_temperature, Settings.flag2.temperature_resolution, str_temperature); - char str_light[33]; - dtostrfd(chirp_sensor[i].light, 0, str_light); - char str_version[7]; - if(chirp_sensor[i].version == 0xff){ - strncpy_P(str_version, PSTR("Chirp!"), sizeof(str_version)); - } - else{ - sprintf(str_version, "%x", chirp_sensor[i].version); - } - - if (json) { - if(!chirp_sensor[i].explicitSleep) { - ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%d"), chirp_name, i, chirp_sensor[i].moisture); - if(chirp_sensor[i].temperature!=-1){ - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"),str_temperature); - } - ResponseAppend_P(PSTR(",\"" D_JSON_DARKNESS "\":%s}"),str_light); - } - else { - ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"),chirp_name, i); - } - #ifdef USE_DOMOTICZ - if (0 == tele_period) { - char str_moisture[33]; - dtostrfd(chirp_sensor[i].moisture, 0, str_moisture); - DomoticzTempHumSensor(str_temperature, str_moisture); - DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); - } - #endif - #ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CHIRPVER, i, chirp_sensor[i].address, str_version); - if (chirp_sensor[i].explicitSleep){ - WSContentSend_PD(HTTP_SNS_CHIRPSLEEP); - } - else { - WSContentSend_PD(HTTP_SNS_MOISTURE, "", chirp_sensor[i].moisture); - WSContentSend_PD(HTTP_SNS_DARKNESS, str_light); - if (chirp_sensor[i].temperature!=-1) { - WSContentSend_PD(HTTP_SNS_TEMP, "", str_temperature, TempUnit()); - } - } - - #endif - } - } - } -} - - - - - -bool ChirpCmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_CHIRP); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_CHIRP), disp_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kCHIRP_Commands); - - switch (command_code) { - case CMND_CHIRP_SELECT: - case CMND_CHIRP_SET: - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(XdrvMailbox.payload); } - if (command_code == CMND_CHIRP_SET) { ChirpSet((uint8_t)XdrvMailbox.payload); } - Response_P(S_JSON_CHIRP_COMMAND_NVALUE, command, XdrvMailbox.payload); - } - else { - if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(255); } - Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); - } - break; - case CMND_CHIRP_SCAN: - case CMND_CHIRP_SLEEP: - case CMND_CHIRP_WAKE: - case CMND_CHIRP_RESET: - if (command_code == CMND_CHIRP_SCAN) { chirp_next_job = 0; - ChirpDetect(); } - if (command_code == CMND_CHIRP_SLEEP) { chirp_sensor[chirp_current].explicitSleep = true; - ChirpSleep(chirp_sensor[chirp_current].address); } - if (command_code == CMND_CHIRP_WAKE) { chirp_sensor[chirp_current].explicitSleep = false; - ChirpReadVersion(chirp_sensor[chirp_current].address); } - if (command_code == CMND_CHIRP_RESET) { ChirpReset(chirp_sensor[chirp_current].address); } - Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); - break; - default: - - serviced = false; - break; - } - } - return serviced; -} - - - - - -bool Xsns48(uint8_t function) -{ - if (!I2cEnabled(XI2C_33)) { return false; } - - bool result = false; - - switch (function) { - case FUNC_EVERY_100_MSECOND: - if(chirp_found_sensors > 0){ - ChirpEvery100MSecond(); - } - break; - case FUNC_COMMAND: - result = ChirpCmd(); - break; - case FUNC_JSON_APPEND: - ChirpShow(1); - chirp_next_job = 14; - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - ChirpShow(0); - break; -#endif - case FUNC_INIT: - ChirpDetect(); - break; - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_50_paj7620.ino" -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_50_paj7620.ino" -#ifdef USE_I2C -#ifdef USE_PAJ7620 - - - - - - -#define XSNS_50 50 -#define XI2C_34 34 - -#define PAJ7620_ADDR 0x73 - -#define PAJ7620_BANK_SEL 0xEF - - - -#define PAJ7620_GET_GESTURE 0x43 -#define PAJ7620_PROXIMITY_AVG_Y 0x6c - -#define PAJ7620_OBJECT_CENTER_X 0xad -#define PAJ7620_OBJECT_CENTER_Y 0xaf - -#define PAJ7620_DOWN 1 -#define PAJ7620_UP 2 -#define PAJ7620_RIGHT 4 -#define PAJ7620_LEFT 8 -#define PAJ7620_NEAR 16 -#define PAJ7620_FAR 32 -#define PAJ7620_CW 64 -#define PAJ7620_CCW 128 - - - - -const uint8_t PAJ7620initRegisterArray[][2] PROGMEM = { - {0xEF,0x00}, - {0x32,0x29}, {0x33,0x01}, {0x34,0x00}, {0x35,0x01}, {0x36,0x00}, {0x37,0x07}, {0x38,0x17}, {0x39,0x06}, - {0x3A,0x12}, {0x3F,0x00}, {0x40,0x02}, {0x41,0xFF}, {0x42,0x01}, {0x46,0x2D}, {0x47,0x0F}, {0x48,0x3C}, - {0x49,0x00}, {0x4A,0x1E}, {0x4B,0x00}, {0x4C,0x20}, {0x4D,0x00}, {0x4E,0x1A}, {0x4F,0x14}, {0x50,0x00}, - {0x51,0x10}, {0x52,0x00}, {0x5C,0x02}, {0x5D,0x00}, {0x5E,0x10}, {0x5F,0x3F}, {0x60,0x27}, {0x61,0x28}, - {0x62,0x00}, {0x63,0x03}, {0x64,0xF7}, {0x65,0x03}, {0x66,0xD9}, {0x67,0x03}, {0x68,0x01}, {0x69,0xC8}, - {0x6A,0x40}, {0x6D,0x04}, {0x6E,0x00}, {0x6F,0x00}, {0x70,0x80}, {0x71,0x00}, {0x72,0x00}, {0x73,0x00}, - {0x74,0xF0}, {0x75,0x00}, {0x80,0x42}, {0x81,0x44}, {0x82,0x04}, {0x83,0x20}, {0x84,0x20}, {0x85,0x00}, - {0x86,0x10}, {0x87,0x00}, {0x88,0x05}, {0x89,0x18}, {0x8A,0x10}, {0x8B,0x01}, {0x8C,0x37}, {0x8D,0x00}, - {0x8E,0xF0}, {0x8F,0x81}, {0x90,0x06}, {0x91,0x06}, {0x92,0x1E}, {0x93,0x0D}, {0x94,0x0A}, {0x95,0x0A}, - {0x96,0x0C}, {0x97,0x05}, {0x98,0x0A}, {0x99,0x41}, {0x9A,0x14}, {0x9B,0x0A}, {0x9C,0x3F}, {0x9D,0x33}, - {0x9E,0xAE}, {0x9F,0xF9}, {0xA0,0x48}, {0xA1,0x13}, {0xA2,0x10}, {0xA3,0x08}, {0xA4,0x30}, {0xA5,0x19}, - {0xA6,0x10}, {0xA7,0x08}, {0xA8,0x24}, {0xA9,0x04}, {0xAA,0x1E}, {0xAB,0x1E}, {0xCC,0x19}, {0xCD,0x0B}, - {0xCE,0x13}, {0xCF,0x64}, {0xD0,0x21}, {0xD1,0x0F}, {0xD2,0x88}, {0xE0,0x01}, {0xE1,0x04}, {0xE2,0x41}, - {0xE3,0xD6}, {0xE4,0x00}, {0xE5,0x0C}, {0xE6,0x0A}, {0xE7,0x00}, {0xE8,0x00}, {0xE9,0x00}, {0xEE,0x07}, - {0xEF,0x01}, - {0x00,0x1E}, {0x01,0x1E}, {0x02,0x0F}, {0x03,0x10}, {0x04,0x02}, {0x05,0x00}, {0x06,0xB0}, {0x07,0x04}, - {0x08,0x0D}, {0x09,0x0E}, {0x0A,0x9C}, {0x0B,0x04}, {0x0C,0x05}, {0x0D,0x0F}, {0x0E,0x02}, {0x0F,0x12}, - {0x10,0x02}, {0x11,0x02}, {0x12,0x00}, {0x13,0x01}, {0x14,0x05}, {0x15,0x07}, {0x16,0x05}, {0x17,0x07}, - {0x18,0x01}, {0x19,0x04}, {0x1A,0x05}, {0x1B,0x0C}, {0x1C,0x2A}, {0x1D,0x01}, {0x1E,0x00}, {0x21,0x00}, - {0x22,0x00}, {0x23,0x00}, {0x25,0x01}, {0x26,0x00}, {0x27,0x39}, {0x28,0x7F}, {0x29,0x08}, {0x30,0x03}, - {0x31,0x00}, {0x32,0x1A}, {0x33,0x1A}, {0x34,0x07}, {0x35,0x07}, {0x36,0x01}, {0x37,0xFF}, {0x38,0x36}, - {0x39,0x07}, {0x3A,0x00}, {0x3E,0xFF}, {0x3F,0x00}, {0x40,0x77}, {0x41,0x40}, {0x42,0x00}, {0x43,0x30}, - {0x44,0xA0}, {0x45,0x5C}, {0x46,0x00}, {0x47,0x00}, {0x48,0x58}, {0x4A,0x1E}, {0x4B,0x1E}, {0x4C,0x00}, - {0x4D,0x00}, {0x4E,0xA0}, {0x4F,0x80}, {0x50,0x00}, {0x51,0x00}, {0x52,0x00}, {0x53,0x00}, {0x54,0x00}, - {0x57,0x80}, {0x59,0x10}, {0x5A,0x08}, {0x5B,0x94}, {0x5C,0xE8}, {0x5D,0x08}, {0x5E,0x3D}, {0x5F,0x99}, - {0x60,0x45}, {0x61,0x40}, {0x63,0x2D}, {0x64,0x02}, {0x65,0x96}, {0x66,0x00}, {0x67,0x97}, {0x68,0x01}, - {0x69,0xCD}, {0x6A,0x01}, {0x6B,0xB0}, {0x6C,0x04}, {0x6D,0x2C}, {0x6E,0x01}, {0x6F,0x32}, {0x71,0x00}, - {0x72,0x01}, {0x73,0x35}, {0x74,0x00}, {0x75,0x33}, {0x76,0x31}, {0x77,0x01}, {0x7C,0x84}, {0x7D,0x03}, - {0x7E,0x01}, - {0xEF,0x00} -}; - - - - - -const char kPaj7620Directions[] PROGMEM = "Down|Up|Right|Left|Near|Far|CW|CCW"; - -const uint8_t PAJ7620_PIN[]= {1,2,3,4}; - - - - - -char PAJ7620_name[] = "PAJ7620"; - -uint32_t PAJ7620_timeout_counter = 10; -uint32_t PAJ7620_next_job = 0; -uint32_t PAJ7620_mode = 1; - -struct { - uint8_t current; - uint8_t last; - uint8_t same; - uint8_t unfinished; -} PAJ7620_gesture; - -bool PAJ7620_finished_gesture = false; -char PAJ7620_currentGestureName[6]; - -struct{ - uint8_t x; - uint8_t y; - uint8_t last_x; - uint8_t last_y; - uint8_t proximity; - uint8_t last_proximity; - uint8_t corner; - struct { - uint8_t step:3; - uint8_t countdown:3; - uint8_t valid:1; - } PIN; -} PAJ7620_state; - - - - - -void PAJ7620SelectBank(uint8_t bank) -{ - I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, bank &1, 1); -} - - - -void PAJ7620DecodeGesture(void) -{ - uint32_t index = 0; - switch (PAJ7620_gesture.current) { - case PAJ7620_LEFT: - index++; - case PAJ7620_RIGHT: - index++; - case PAJ7620_UP: - index++; - case PAJ7620_DOWN: - if (PAJ7620_gesture.unfinished) { - PAJ7620_finished_gesture = true; - break; - } - PAJ7620_gesture.unfinished = PAJ7620_gesture.current; - PAJ7620_timeout_counter = 5; - break; - case PAJ7620_NEAR: - index = 4; - PAJ7620_finished_gesture = true; - PAJ7620_timeout_counter = 25; - break; - case PAJ7620_FAR: - index = 5; - PAJ7620_finished_gesture = true; - PAJ7620_timeout_counter = 25; - break; - case PAJ7620_CW: - index = 6; - PAJ7620_finished_gesture = true; - break; - case PAJ7620_CCW: - index = 7; - PAJ7620_finished_gesture = true; - break; - default: - index = 8; - if (PAJ7620_gesture.unfinished) { - PAJ7620_finished_gesture = true; - } - break; - } - if (index < 8) { - GetTextIndexed(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), index, kPaj7620Directions); - } - - if (PAJ7620_finished_gesture) { - if (PAJ7620_gesture.unfinished) { - if ((PAJ7620_gesture.current != PAJ7620_NEAR) && (PAJ7620_gesture.current != PAJ7620_FAR)) { - PAJ7620_gesture.current = PAJ7620_gesture.unfinished; - } - } - if (PAJ7620_gesture.current == PAJ7620_gesture.last) { - PAJ7620_gesture.same++; - } else { - PAJ7620_gesture.same = 1; - } - PAJ7620_gesture.last = PAJ7620_gesture.current; - PAJ7620_finished_gesture = false; - PAJ7620_gesture.unfinished = 0; - PAJ7620_timeout_counter += 3; - MqttPublishSensor(); - } -} - - - -void PAJ7620ReadGesture(void) -{ - switch (PAJ7620_mode) { - case 1: - PAJ7620_gesture.current = I2cRead8(PAJ7620_ADDR,PAJ7620_GET_GESTURE); - if ((PAJ7620_gesture.current > 0) || PAJ7620_gesture.unfinished) { - DEBUG_SENSOR_LOG(PSTR("PAJ: gesture: %u"), PAJ7620_gesture.current); - PAJ7620DecodeGesture(); - } - break; - case 2: - PAJ7620_state.proximity = I2cRead8(PAJ7620_ADDR, PAJ7620_PROXIMITY_AVG_Y); - if ((PAJ7620_state.proximity > 0) || (PAJ7620_state.last_proximity > 0)) { - if (PAJ7620_state.proximity != PAJ7620_state.last_proximity) { - PAJ7620_state.last_proximity = PAJ7620_state.proximity; - DEBUG_SENSOR_LOG(PSTR("PAJ: Proximity: %u"), PAJ7620_state.proximity); - MqttPublishSensor(); - } - } - break; - case 3: - case 4: - case 5: - PAJ7620_state.x = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_X); - PAJ7620_state.y = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_Y); - if ((PAJ7620_state.y > 0) && (PAJ7620_state.x > 0)) { - if ((PAJ7620_state.y != PAJ7620_state.last_y) || (PAJ7620_state.x != PAJ7620_state.last_x)) { - PAJ7620_state.last_y = PAJ7620_state.y; - PAJ7620_state.last_x = PAJ7620_state.x; - DEBUG_SENSOR_LOG(PSTR("PAJ: x: %u y: %u"), PAJ7620_state.x, PAJ7620_state.y); - - PAJ7620_state.corner = 0; - - - - switch (PAJ7620_state.y) { - case 0: case 1: case 2: case 3: case 4: case 5: - PAJ7620_state.corner = 3; - break; - case 9: case 10: case 11: case 12: case 13: case 14: - PAJ7620_state.corner = 1; - break; - } - if (PAJ7620_state.corner != 0) { - switch (PAJ7620_state.x) { - case 0: case 1: case 2: case 3: case 4: case 5: - break; - case 9: case 10: case 11: case 12: case 13: case 14: - PAJ7620_state.corner++; - break; - default: - PAJ7620_state.corner = 0; - break; - } - } - DEBUG_SENSOR_LOG(PSTR("PAJ: corner: %u"), PAJ7620_state.corner); - - if (PAJ7620_state.PIN.countdown == 0) { - PAJ7620_state.PIN.step = 0; - PAJ7620_state.PIN.valid = 0; - } - if (!PAJ7620_state.PIN.step) { - if (PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]) { - PAJ7620_state.PIN.step = 1; - PAJ7620_state.PIN.countdown = 7; - } - } else { - if (PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]) { - PAJ7620_state.PIN.step += 1; - PAJ7620_state.PIN.countdown = 7; - } else { - PAJ7620_state.PIN.countdown -= 1; - } - } - if (PAJ7620_state.PIN.step == 4) { - PAJ7620_state.PIN.valid = 1; - DEBUG_SENSOR_LOG(PSTR("PAJ: PIN valid!!")); - PAJ7620_state.PIN.countdown = 0; - } - MqttPublishSensor(); - } - } - break; - } -} - - - -void PAJ7620Detect(void) -{ - if (I2cActive(PAJ7620_ADDR)) { return; } - - PAJ7620SelectBank(0); - PAJ7620SelectBank(0); - uint16_t PAJ7620_id = I2cRead16LE(PAJ7620_ADDR,0); - uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); - if (0x7620 == PAJ7620_id) { - I2cSetActiveFound(PAJ7620_ADDR, PAJ7620_name); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ: ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); - PAJ7620_next_job = 1; - } - else { - DEBUG_SENSOR_LOG(PSTR("PAJ: sensor not found, false ID 0x%x"), PAJ7620_id); - } -} - - - -void PAJ7620Init(void) -{ - DEBUG_SENSOR_LOG(PSTR("PAJ: init sensor start %u"),millis()); - union{ - uint32_t raw; - uint8_t reg_val[4]; - } buf; - - for (uint32_t i = 0; i < (sizeof(PAJ7620initRegisterArray) / 2); i += 2) - { - buf.raw = pgm_read_dword(PAJ7620initRegisterArray + i); - DEBUG_SENSOR_LOG("PAJ: %x %x %x %x",buf.reg_val[0],buf.reg_val[1],buf.reg_val[2],buf.reg_val[3]); - I2cWrite(PAJ7620_ADDR, buf.reg_val[0], buf.reg_val[1], 1); - I2cWrite(PAJ7620_ADDR, buf.reg_val[2], buf.reg_val[3], 1); - } - DEBUG_SENSOR_LOG(PSTR("PAJ: init sensor done %u"),millis()); - PAJ7620_next_job = 2; -} - - - -void PAJ7620Loop(void) -{ - if (0 == PAJ7620_timeout_counter) { - switch (PAJ7620_next_job) { - case 1: - PAJ7620Init(); - break; - case 2: - if (PAJ7620_mode != 0) { - PAJ7620ReadGesture(); - } - break; - } - } else { - PAJ7620_timeout_counter--; - } -} - - - -void PAJ7620Show(bool json) -{ - if (json) { - if (PAJ7620_currentGestureName[0] != '\0' ) { - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), PAJ7620_name, PAJ7620_currentGestureName, PAJ7620_gesture.same); - PAJ7620_currentGestureName[0] = '\0'; - return; - } - switch (PAJ7620_mode) { - case 2: - ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), PAJ7620_name, PAJ7620_state.proximity); - break; - case 3: - if (PAJ7620_state.corner > 0) { - ResponseAppend_P(PSTR(",\"%s\":{\"Corner\":%u}"), PAJ7620_name, PAJ7620_state.corner); - } - break; - case 4: - if (PAJ7620_state.PIN.valid) { - ResponseAppend_P(PSTR(",\"%s\":{\"PIN\":%u}"), PAJ7620_name, 1); - PAJ7620_state.PIN.valid = 0; - } - break; - case 5: - ResponseAppend_P(PSTR(",\"%s\":{\"x\":%u,\"y\":%u}"), PAJ7620_name, PAJ7620_state.x, PAJ7620_state.y); - break; - } - } -} -# 411 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_50_paj7620.ino" -bool PAJ7620CommandSensor(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - PAJ7620_mode = XdrvMailbox.payload; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_50, PAJ7620_mode); - - return true; -} - - - - - -bool Xsns50(uint8_t function) -{ - if (!I2cEnabled(XI2C_34)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - PAJ7620Detect(); - } - else if (PAJ7620_next_job) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_50 == XdrvMailbox.index){ - result = PAJ7620CommandSensor(); - } - break; - case FUNC_EVERY_100_MSECOND: - PAJ7620Loop(); - break; - case FUNC_JSON_APPEND: - PAJ7620Show(1); - break; - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_51_rdm6300.ino" -# 21 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_51_rdm6300.ino" -#ifdef USE_RDM6300 - -#define XSNS_51 51 - -#define RDM6300_BAUDRATE 9600 - -#include - -#define RDM_TIMEOUT 100 -char rdm_uid_str[10]; - - -#define RDM6300_BLOCK 2*10 - -uint8_t rdm_blcnt; -TasmotaSerial *RDM6300_Serial = nullptr; - -void RDM6300_Init() { - if (pin[GPIO_RDM6300_RX] < 99) { - RDM6300_Serial = new TasmotaSerial(pin[GPIO_RDM6300_RX],-1,1); - if (RDM6300_Serial->begin(RDM6300_BAUDRATE)) { - if (RDM6300_Serial->hardwareSerial()) { - ClaimSerial(); - } - } - } - rdm_blcnt=0; -} - - -void RDM6300_ScanForTag() { - char rdm_buffer[14]; - uint8_t rdm_index; - uint8_t rdm_array[6]; - - if (!RDM6300_Serial) return; - - if (rdm_blcnt>0) { - rdm_blcnt--; - while (RDM6300_Serial->available()) RDM6300_Serial->read(); - return; - } - - if (RDM6300_Serial->available()) { - - char c=RDM6300_Serial->read(); - if (c!=2) return; - - - rdm_index=0; - uint32_t cmillis=millis(); - while (1) { - if (RDM6300_Serial->available()) { - char c=RDM6300_Serial->read(); - if (c==3) { - - break; - } - rdm_buffer[rdm_index++]=c; - if (rdm_index>13) { - - return; - } - } - if ((millis()-cmillis)>RDM_TIMEOUT) { - - return; - } - } - - - rdm_blcnt=RDM6300_BLOCK; - - - rm6300_hstring_to_array(rdm_array,sizeof(rdm_array),rdm_buffer); - uint8_t accu=0; - for (uint8_t count=0;count<5;count++) { - accu^=rdm_array[count]; - } - if (accu!=rdm_array[5]) { - - return; - } - - - memcpy(rdm_uid_str,&rdm_buffer[2],8); - rdm_uid_str[9]=0; - - ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); - MqttPublishTeleSensor(); - - - - - - } - - -} - -uint8_t rm6300_hexnibble(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { - rVal = chr - '0'; - } else { - if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; - } - return rVal; -} - - -void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]) -{ - char *cp=buffer; - for (uint8_t i = 0; i < len; i++) { - uint8_t val = rm6300_hexnibble(*cp++) << 4; - array[i]= val | rm6300_hexnibble(*cp++); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_RDM6300[] PROGMEM = - "{s}RDM6300 " "UID" "{m}%s" "{e}"; - -void RDM6300_Show(void) { - if (!RDM6300_Serial) return; - if (!rdm_uid_str[0]) strcpy(rdm_uid_str,"????"); - WSContentSend_PD(HTTP_RDM6300,rdm_uid_str); -} -#endif - - - - - -bool Xsns51(byte function) -{ - bool result = false; - - switch (function) { - case FUNC_INIT: - RDM6300_Init(); - break; - case FUNC_EVERY_100_MSECOND: - RDM6300_ScanForTag(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - RDM6300_Show(); - break; -#endif - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_52_ibeacon.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_52_ibeacon.ino" -#ifdef USE_IBEACON - - - -#define XSNS_52 52 - -#include - -#define HM17_BAUDRATE 9600 - -#define IBEACON_DEBUG - - -#define HM17_V110 - - - -#define IB_TIMEOUT_INTERVAL 30 - -#define IB_UPDATE_TIME_INTERVAL 10 - -TasmotaSerial *IBEACON_Serial = nullptr; - - -uint8_t hm17_found,hm17_cmd,hm17_flag; - -#ifdef IBEACON_DEBUG -uint8_t hm17_debug=0; -#endif - - - -#define HM17_BSIZ 128 -char hm17_sbuffer[HM17_BSIZ]; -uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting; -uint32_t hm17_lastms; -char ib_mac[14]; - - -#if 1 -uint8_t ib_upd_interval,ib_tout_interval; -#define IB_UPDATE_TIME ib_upd_interval -#define IB_TIMEOUT_TIME ib_tout_interval -#else -#undef IB_UPDATE_TIME -#undef IB_TIMEOUT_TIME -#define IB_UPDATE_TIME Settings.ib_upd_interval -#define IB_TIMEOUT_TIME Settings.ib_tout_interval -#endif - -enum {HM17_TEST,HM17_ROLE,HM17_IMME,HM17_DISI,HM17_IBEA,HM17_SCAN,HM17_DISC,HM17_RESET,HM17_RENEW,HM17_CON}; -#define HM17_SUCESS 99 - -struct IBEACON { - char FACID[8]; - char UID[32]; - char MAJOR[4]; - char MINOR[4]; - char PWR[2]; - char MAC[12]; - char RSSI[4]; -}; - -#define MAX_IBEACONS 16 - -struct IBEACON_UID { - char MAC[12]; - char RSSI[4]; - uint8_t FLAGS; - uint8_t TIME; -} ibeacons[MAX_IBEACONS]; - - -void IBEACON_Init() { - - hm17_found=0; - - - if ((pin[GPIO_IBEACON_RX] < 99) && (pin[GPIO_IBEACON_TX] < 99)) { - IBEACON_Serial = new TasmotaSerial(pin[GPIO_IBEACON_RX], pin[GPIO_IBEACON_TX],1); - if (IBEACON_Serial->begin(HM17_BAUDRATE)) { - if (IBEACON_Serial->hardwareSerial()) { - ClaimSerial(); - } - hm17_sendcmd(HM17_TEST); - hm17_lastms=millis(); - - IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; - IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; - } - } -} - -void hm17_every_second(void) { - if (!IBEACON_Serial) return; - - if (hm17_found) { - if (IB_UPDATE_TIME && (uptime%IB_UPDATE_TIME==0)) { - if (hm17_cmd!=99) { - if (hm17_flag&2) { - ib_sendbeep(); - } else { - if (!hm17_connecting) { - hm17_sendcmd(HM17_DISI); - } - } - } - } - for (uint32_t cnt=0;cntIB_TIMEOUT_TIME) { - ibeacons[cnt].FLAGS=0; - ibeacon_mqtt(ibeacons[cnt].MAC,"0000"); - } - } - } - } else { - if (uptime%20==0) { - hm17_sendcmd(HM17_TEST); - } - } -} - -void hm17_sbclr(void) { - memset(hm17_sbuffer,0,HM17_BSIZ); - hm17_sindex=0; - IBEACON_Serial->flush(); -} - -void hm17_sendcmd(uint8_t cmd) { - hm17_sbclr(); - hm17_cmd=cmd; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("hm17cmd %d"),cmd); -#endif - switch (cmd) { - case HM17_TEST: - IBEACON_Serial->write("AT"); - break; - case HM17_ROLE: - IBEACON_Serial->write("AT+ROLE1"); - break; - case HM17_IMME: - IBEACON_Serial->write("AT+IMME1"); - break; - case HM17_DISI: - IBEACON_Serial->write("AT+DISI?"); - hm17_scanning=1; - break; - case HM17_IBEA: - IBEACON_Serial->write("AT+IBEA1"); - break; - case HM17_RESET: - IBEACON_Serial->write("AT+RESET"); - break; - case HM17_RENEW: - IBEACON_Serial->write("AT+RENEW"); - break; - case HM17_SCAN: - IBEACON_Serial->write("AT+SCAN5"); - break; - case HM17_DISC: - IBEACON_Serial->write("AT+DISC?"); - hm17_scanning=1; - break; - case HM17_CON: - IBEACON_Serial->write((const uint8_t*)"AT+CON",6); - IBEACON_Serial->write((const uint8_t*)ib_mac,12); - hm17_connecting=1; - break; - } -} - -uint32_t ibeacon_add(struct IBEACON *ib) { - - if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { - for (uint32_t cnt=0;cntMAC,12)) { - - memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); - ibeacons[cnt].TIME=0; - return 1; - } - } - } - for (uint32_t cnt=0;cntMAC,12); - memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); - ibeacons[cnt].FLAGS=1; - ibeacons[cnt].TIME=0; - return 1; - } - } - } - return 0; -} - -void hm17_decode(void) { - struct IBEACON ib; - switch (hm17_cmd) { - case HM17_TEST: - if (!strncmp(hm17_sbuffer,"OK",2)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("AT OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - hm17_found=1; - } - break; - case HM17_ROLE: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("ROLE OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_IMME: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IMME OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_IBEA: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IBEA OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_SCAN: - if (!strncmp(hm17_sbuffer,"OK+Set:5",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("SCAN OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_RESET: - if (!strncmp(hm17_sbuffer,"OK+RESET",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RESET OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_RENEW: - if (!strncmp(hm17_sbuffer,"OK+RENEW",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RENEW OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_CON: - if (!strncmp(hm17_sbuffer,"OK+CONNA",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNA OK")); -#endif - hm17_connecting=2; - break; - } - if (!strncmp(hm17_sbuffer,"OK+CONNE",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNE ERROR")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+CONNF",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNF ERROR")); -#endif - break; - } - if (hm17_connecting==2 && !strncmp(hm17_sbuffer,"OK+CONN",7)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONN OK")); -#endif - hm17_connecting=3; - hm17_sendcmd(HM17_TEST); - hm17_connecting=0; - break; - } - break; - - case HM17_DISI: - case HM17_DISC: - if (!strncmp(hm17_sbuffer,"OK+DISCS",8)) { - hm17_sbclr(); - hm17_result=1; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCS OK")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISIS",8)) { - hm17_sbclr(); - hm17_result=1; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISIS OK")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISCE",8)) { - hm17_sbclr(); - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCE OK")); -#endif - hm17_scanning=0; - break; - } - if (!strncmp(hm17_sbuffer,"OK+NAME:",8)) { - if (hm17_sbuffer[hm17_sindex-1]=='\n') { - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("NAME OK")); - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - hm17_sbclr(); - } - break; - } - if (!strncmp(hm17_sbuffer,"OK+DIS0:",8)) { - if (hm17_cmd==HM17_DISI) { -#ifdef HM17_V110 - goto hm17_v110; -#endif - } else { - if (hm17_sindex==20) { - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("DIS0 OK")); - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - hm17_sbclr(); - } - } - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISC:",8)) { -hm17_v110: - if (hm17_cmd==HM17_DISI) { - if (hm17_sindex==78) { -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("DISC: OK")); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - memcpy(ib.FACID,&hm17_sbuffer[8],8); - memcpy(ib.UID,&hm17_sbuffer[8+8+1],32); - memcpy(ib.MAJOR,&hm17_sbuffer[8+8+1+32+1],4); - memcpy(ib.MINOR,&hm17_sbuffer[8+8+1+32+1+4],4); - memcpy(ib.PWR,&hm17_sbuffer[8+8+1+32+1+4+4],2); - memcpy(ib.MAC,&hm17_sbuffer[8+8+1+32+1+4+4+2+1],12); - memcpy(ib.RSSI,&hm17_sbuffer[8+8+1+32+1+4+4+2+1+12+1],4); - - if (ibeacon_add(&ib)) { - ibeacon_mqtt(ib.MAC,ib.RSSI); - } - hm17_sbclr(); - hm17_result=1; - } - } else { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); -#endif - } - break; - } - } -} - -void IBEACON_loop() { - - if (!IBEACON_Serial) return; - -uint32_t difftime=millis()-hm17_lastms; - - while (IBEACON_Serial->available()) { - hm17_lastms=millis(); - - if (hm17_sindexread(); - hm17_sindex++; - hm17_decode(); - } else { - hm17_sindex=0; - break; - } - } - - if (hm17_cmd==99) { - if (hm17_sindex>=HM17_BSIZ-2 || (hm17_sindex && (difftime>100))) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),hm17_sbuffer); - hm17_sbclr(); - } - } - -} - -#ifdef USE_WEBSERVER -const char HTTP_IBEACON[] PROGMEM = - "{s}IBEACON-UID : %s" " - RSSI : %s" "{m}{e}"; - -void IBEACON_Show(void) { -char mac[14]; -char rssi[6]; - - for (uint32_t cnt=0;cnt 0) { - char *cp=XdrvMailbox.data; - if (*cp>='0' && *cp<='8') { - hm17_sendcmd(*cp&7); - Response_P(S_JSON_IBEACON, XSNS_52,"hm17cmd",*cp&7); - } else if (*cp=='s') { - cp++; - len--; - while (*cp==' ') { - len--; - cp++; - } - IBEACON_Serial->write((uint8_t*)cp,len); - hm17_cmd=99; - Response_P(S_JSON_IBEACON1, XSNS_52,"hm17cmd",cp); - } else if (*cp=='u') { - cp++; - if (*cp) IB_UPDATE_TIME=atoi(cp); - Response_P(S_JSON_IBEACON, XSNS_52,"uintv",IB_UPDATE_TIME); - } else if (*cp=='t') { - cp++; - if (*cp) IB_TIMEOUT_TIME=atoi(cp); - Response_P(S_JSON_IBEACON, XSNS_52,"lintv",IB_TIMEOUT_TIME); - } else if (*cp=='c') { - for (uint32_t cnt=0;cnt - - -#define SPECIAL_SS - - - - - -#if MY_LANGUAGE==de-DE - -#define D_TPWRIN "Verbrauch" -#define D_TPWROUT "Einspeisung" -#define D_TPWRCURR "Aktueller Verbrauch" -#define D_TPWRCURR1 "Verbrauch P1" -#define D_TPWRCURR2 "Verbrauch P2" -#define D_TPWRCURR3 "Verbrauch P3" -#define D_Strom_L1 "Strom L1" -#define D_Strom_L2 "Strom L2" -#define D_Strom_L3 "Strom L3" -#define D_Spannung_L1 "Spannung L1" -#define D_Spannung_L2 "Spannung L2" -#define D_Spannung_L3 "Spannung L3" -#define D_METERNR "Zähler Nr" -#define D_METERSID "Service ID" -#define D_GasIN "Zählerstand" -#define D_H2oIN "Zählerstand" -#define D_StL1L2L3 "Ströme L1+L2+L3" -#define D_SpL1L2L3 "Spannung L1+L2+L3/3" - -#else - -#undef D_TPWRIN -#undef D_TPWROUT -#undef D_TPWRCURR -#undef D_TPWRCURR1 -#undef D_TPWRCURR2 -#undef D_TPWRCURR3 -#undef D_Strom_L1 -#undef D_Strom_L2 -#undef D_Strom_L3 -#undef D_Spannung_L1 -#undef D_Spannung_L2 -#undef D_Spannung_L3 -#undef D_METERNR -#undef D_METERSID -#undef D_GasIN -#undef D_H2oIN -#undef D_StL1L2L3 -#undef D_SpL1L2L3 - -#define D_TPWRIN "Total-In" -#define D_TPWROUT "Total-Out" -#define D_TPWRCURR "Current-In/Out" -#define D_TPWRCURR1 "Current-In p1" -#define D_TPWRCURR2 "Current-In p2" -#define D_TPWRCURR3 "Current-In p3" -#define D_Strom_L1 "Current L1" -#define D_Strom_L2 "Current L2" -#define D_Strom_L3 "Current L3" -#define D_Spannung_L1 "Voltage L1" -#define D_Spannung_L2 "Voltage L2" -#define D_Spannung_L3 "Voltage L3" -#define D_METERNR "Meter_number" -#define D_METERSID "Service ID" -#define D_GasIN "Counter" -#define D_H2oIN "Counter" -#define D_StL1L2L3 "Current L1+L2+L3" -#define D_SpL1L2L3 "Voltage L1+L2+L3/3" - -#endif - - - -#define DJ_TPWRIN "Total_in" -#define DJ_TPWROUT "Total_out" -#define DJ_TPWRCURR "Power_curr" -#define DJ_TPWRCURR1 "Power_p1" -#define DJ_TPWRCURR2 "Power_p2" -#define DJ_TPWRCURR3 "Power_p3" -#define DJ_CURR1 "Curr_p1" -#define DJ_CURR2 "Curr_p2" -#define DJ_CURR3 "Curr_p3" -#define DJ_VOLT1 "Volt_p1" -#define DJ_VOLT2 "Volt_p2" -#define DJ_VOLT3 "Volt_p3" -#define DJ_METERNR "Meter_number" -#define DJ_METERSID "Meter_id" -#define DJ_CSUM "Curr_summ" -#define DJ_VAVG "Volt_avg" -#define DJ_COUNTER "Count" - -struct METER_DESC { - uint8_t srcpin; - uint8_t type; - uint16_t flag; - int32_t params; - char prefix[8]; - int8_t trxpin; - uint8_t tsecs; - char *txmem; - uint8_t index; - uint8_t max_index; -}; - - - - - - -#define EHZ161_0 1 -#define EHZ161_1 2 -#define EHZ363 3 -#define EHZH 4 -#define EDL300 5 -#define Q3B 6 -#define COMBO3 7 -#define COMBO2 8 -#define COMBO3a 9 -#define Q3B_V1 10 -#define EHZ363_2 11 -#define COMBO3b 12 -#define WGS_COMBO 13 -#define EBZD_G 14 - - -#define METER EHZ161_1 - - -#if METER==EHZ161_0 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" -"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" -"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" -"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - - - -#if METER==EHZ161_1 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZ363 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZH -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - - - -#if METER==EDL300 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - -#if METER==EBZD_G -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"strom",-1,1,0}}; -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" - -"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100600100ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - - -#if METER==Q3B -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - -#if METER==COMBO3 - -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, - [1]={14,'s',0,SML_BAUDRATE,"SML",-1,1,0}, - [2]={4,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; - - -const uint8_t meter[]= -"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" -"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" -"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" -"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"2,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"3,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - -#if METER==COMBO2 - -#undef METERS_USED -#define METERS_USED 2 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, - [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; - - -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" - -"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - -#if METER==COMBO3a -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, - [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}, - [2]={1,'o',0,SML_BAUDRATE,"OBIS3",-1,1,0}}; - - -const uint8_t meter[]= -"1,=h --- Zähler Nr 1 ---|" -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"2,=h --- Zähler Nr 2 ---|" -"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"3,=h --- Zähler Nr 3 ---|" -"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"3,=d 10 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - - - -#if METER==Q3B_V1 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ -[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZ363_2 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ -[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" - -"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - -#if METER==COMBO3b -#undef METERS_USED -#define METERS_USED 3 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, - [1]={14,'c',0,50,"Gas"}, - [2]={1,'c',0,10,"Wasser"}}; - - -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" - - -"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",2|" - -"3,1-0:1.8.0*255(@100," D_H2oIN ",cbm," DJ_COUNTER ",2"; -#endif - - -#if METER==WGS_COMBO -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={1,'c',0,10,"H20",-1,1,0}, - [1]={4,'c',0,50,"GAS",-1,1,0}, - [2]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - - -"1,1-0:1.8.0*255(@10000," D_H2oIN ",cbm," DJ_COUNTER ",4|" - - -"2,=h==================|" -"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",3|" - -"3,=h==================|" - -"3,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",3|" -"3,=h==================|" - -"3,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",2|" -"3,=h -------------------------------|" -"3,=m 10+11+12 @100," D_StL1L2L3 ",A," DJ_CSUM ",2|" - -"3,=m 13+14+15/#3 @100," D_SpL1L2L3 ",V," DJ_VAVG ",2|" -"3,=h==================|" - -"3,77070100240700ff@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",2|" - -"3,77070100380700ff@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",2|" - -"3,770701004c0700ff@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",2|" -"3,=h -------------------------------|" - -"3,770701001f0700ff@100," D_Strom_L1 ",A," DJ_CURR1 ",2|" - -"3,77070100330700ff@100," D_Strom_L2 ",A," DJ_CURR2 ",2|" - -"3,77070100470700ff@100," D_Strom_L3 ",A," DJ_CURR3 ",2|" -"3,=h -------------------------------|" - -"3,77070100200700ff@100," D_Spannung_L1 ",V," DJ_VOLT1 ",2|" - -"3,77070100340700ff@100," D_Spannung_L2 ",V," DJ_VOLT2 ",2|" - -"3,77070100480700ff@100," D_Spannung_L3 ",V," DJ_VOLT3 ",2|" -"3,=h==================|" - -"3,77070100000009ff@#," D_METERSID ",," DJ_METERSID ",0|" -"3,=h--------------------------------"; -#endif -# 499 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_53_sml.ino" -#define USE_SML_MEDIAN_FILTER - - -#ifndef SML_MAX_VARS -#define SML_MAX_VARS 20 -#endif - - -#define MAX_METERS 5 -double meter_vars[SML_MAX_VARS]; - -#define MAX_DVARS MAX_METERS*2 -double dvalues[MAX_DVARS]; -uint32_t dtimes[MAX_DVARS]; -uint8_t meters_used; - -struct METER_DESC const *meter_desc_p; -const uint8_t *meter_p; -uint8_t meter_spos[MAX_METERS]; - - -TasmotaSerial *meter_ss[MAX_METERS]; - - -#define SML_BSIZ 48 -uint8_t smltbuf[MAX_METERS][SML_BSIZ]; - - -#define METER_ID_SIZE 24 -char meter_id[MAX_METERS][METER_ID_SIZE]; - -#define EBUS_SYNC 0xaa -#define EBUS_ESC 0xa9 - -uint8_t sml_send_blocks; -uint8_t sml_100ms_cnt; -uint8_t sml_desc_cnt; - -#ifdef USE_SML_MEDIAN_FILTER - -#define MEDIAN_SIZE 5 -struct SML_MEDIAN_FILTER { -double buffer[MEDIAN_SIZE]; -int8_t index; -} sml_mf[SML_MAX_VARS]; - -#ifndef FLT_MAX -#define FLT_MAX 99999999 -#endif - -double sml_median_array(double *array,uint8_t len) { - uint8_t ind[len]; - uint8_t mind=0,index=0,flg; - double min=FLT_MAX; - - for (uint8_t hcnt=0; hcntbuffer[mf->index]=in; - mf->index++; - if (mf->index>=MEDIAN_SIZE) mf->index=0; - - return sml_median_array(mf->buffer,MEDIAN_SIZE); -# 603 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_53_sml.ino" -} -#endif - -#ifdef ANALOG_OPTO_SENSOR - -uint8_t ads1115_up; - - -#define SAMPLE_BIT (0x8000) - -#define ADS1115_COMP_QUEUE_SHIFT 0 -#define ADS1115_COMP_LATCH_SHIFT 2 -#define ADS1115_COMP_POLARITY_SHIFT 3 -#define ADS1115_COMP_MODE_SHIFT 4 -#define ADS1115_DATA_RATE_SHIFT 5 -#define ADS1115_MODE_SHIFT 8 -#define ADS1115_PGA_SHIFT 9 -#define ADS1115_MUX_SHIFT 12 - -enum ads1115_comp_queue { - ADS1115_COMP_QUEUE_AFTER_ONE = 0, - ADS1115_COMP_QUEUE_AFTER_TWO = 0x1 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_AFTER_FOUR = 0x2 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_DISABLE = 0x3 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_MASK = 0x3 << ADS1115_COMP_QUEUE_SHIFT, -}; - -enum ads1115_comp_latch { - ADS1115_COMP_LATCH_NO = 0, - ADS1115_COMP_LATCH_YES = 1 << ADS1115_COMP_LATCH_SHIFT, - ADS1115_COMP_LATCH_MASK = 1 << ADS1115_COMP_LATCH_SHIFT, -}; - -enum ads1115_comp_polarity { - ADS1115_COMP_POLARITY_ACTIVE_LOW = 0, - ADS1115_COMP_POLARITY_ACTIVE_HIGH = 1 << ADS1115_COMP_POLARITY_SHIFT, - ADS1115_COMP_POLARITY_MASK = 1 << ADS1115_COMP_POLARITY_SHIFT, -}; - -enum ads1115_comp_mode { - ADS1115_COMP_MODE_WINDOW = 0, - ADS1115_COMP_MODE_HYSTERESIS = 1 << ADS1115_COMP_MODE_SHIFT, - ADS1115_COMP_MODE_MASK = 1 << ADS1115_COMP_MODE_SHIFT, -}; - -enum ads1115_data_rate { - ADS1115_DATA_RATE_8_SPS = 0, - ADS1115_DATA_RATE_16_SPS = 0x1 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_32_SPS = 0x2 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_64_SPS = 0x3 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_128_SPS = 0x4 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_250_SPS = 0x5 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_475_SPS = 0x6 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_860_SPS = 0x7 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_MASK = 0x7 << ADS1115_DATA_RATE_SHIFT, -}; - -enum ads1115_mode { - ADS1115_MODE_CONTINUOUS = 0, - ADS1115_MODE_SINGLE_SHOT = 1 << ADS1115_MODE_SHIFT, - ADS1115_MODE_MASK = 1 << ADS1115_MODE_SHIFT, -}; - -enum ads1115_pga { - ADS1115_PGA_TWO_THIRDS = 0, - ADS1115_PGA_ONE = 0x1 << ADS1115_PGA_SHIFT, - ADS1115_PGA_TWO = 0x2 << ADS1115_PGA_SHIFT, - ADS1115_PGA_FOUR = 0x3 << ADS1115_PGA_SHIFT, - ADS1115_PGA_EIGHT = 0x4 << ADS1115_PGA_SHIFT, - ADS1115_PGA_SIXTEEN = 0x5 << ADS1115_PGA_SHIFT, - ADS1115_PGA_MASK = 0x7 << ADS1115_PGA_SHIFT, -}; - - -enum ads1115_mux { - ADS1115_MUX_DIFF_AIN0_AIN1 = 0, - ADS1115_MUX_DIFF_AIN0_AIN3 = 0x1 << ADS1115_MUX_SHIFT, - ADS1115_MUX_DIFF_AIN1_AIN3 = 0x2 << ADS1115_MUX_SHIFT, - ADS1115_MUX_DIFF_AIN2_AIN3 = 0x3 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN0 = 0x4 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN1 = 0x5 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN2 = 0x6 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN3 = 0x7 << ADS1115_MUX_SHIFT, - ADS1115_MUX_MASK = 0x7 << ADS1115_MUX_SHIFT, -}; - -class ADS1115 { -public: - ADS1115(uint8_t address = 0x48); - - void begin(); - uint8_t trigger_sample(); - uint8_t reset(); - bool is_sample_in_progress(); - int16_t read_sample(); - float sample_to_float(int16_t val); - float read_sample_float(); - - void set_comp_queue(enum ads1115_comp_queue val) { set_config(val, ADS1115_COMP_QUEUE_MASK); } - void set_comp_latching(enum ads1115_comp_latch val) { set_config(val, ADS1115_COMP_LATCH_MASK); } - void set_comp_polarity(enum ads1115_comp_polarity val) { set_config(val, ADS1115_COMP_POLARITY_MASK); } - void set_comp_mode(enum ads1115_comp_mode val) { set_config(val, ADS1115_COMP_MODE_MASK); } - void set_data_rate(enum ads1115_data_rate val) { set_config(val, ADS1115_DATA_RATE_MASK); } - void set_mode(enum ads1115_mode val) { set_config(val, ADS1115_MODE_MASK); } - void set_pga(enum ads1115_pga val) { set_config(val, ADS1115_PGA_MASK); m_voltage_range = val >> ADS1115_PGA_SHIFT; } - void set_mux(enum ads1115_mux val) { set_config(val, ADS1115_MUX_MASK); } - -private: - void set_config(uint16_t val, uint16_t mask) { - m_config = (m_config & ~mask) | val; - } - - uint8_t write_register(uint8_t reg, uint16_t val); - uint16_t read_register(uint8_t reg); - - uint8_t m_address; - uint16_t m_config; - int m_voltage_range; -}; - - -enum ads1115_register { - ADS1115_REGISTER_CONVERSION = 0, - ADS1115_REGISTER_CONFIG = 1, - ADS1115_REGISTER_LOW_THRESH = 2, - ADS1115_REGISTER_HIGH_THRESH = 3, -}; - -#define FACTOR 32768.0 -static float ranges[] = { 6.144 / FACTOR, 4.096 / FACTOR, 2.048 / FACTOR, 1.024 / FACTOR, 0.512 / FACTOR, 0.256 / FACTOR}; - -ADS1115::ADS1115(uint8_t address) -{ - m_address = address; - m_config = ADS1115_COMP_QUEUE_AFTER_ONE | - ADS1115_COMP_LATCH_NO | - ADS1115_COMP_POLARITY_ACTIVE_LOW | - ADS1115_COMP_MODE_WINDOW | - ADS1115_DATA_RATE_128_SPS | - ADS1115_MODE_SINGLE_SHOT | - ADS1115_MUX_GND_AIN0; - set_pga(ADS1115_PGA_ONE); -} - -uint8_t ADS1115::write_register(uint8_t reg, uint16_t val) -{ - Wire.beginTransmission(m_address); - Wire.write(reg); - Wire.write(val>>8); - Wire.write(val & 0xFF); - return Wire.endTransmission(); -} - -uint16_t ADS1115::read_register(uint8_t reg) -{ - Wire.beginTransmission(m_address); - Wire.write(reg); - Wire.endTransmission(); - - uint8_t result = Wire.requestFrom((int)m_address, 2, 1); - if (result != 2) { - return 0; - } - - uint16_t val; - - val = Wire.read() << 8; - val |= Wire.read(); - return val; -} - -void ADS1115::begin() -{ - Wire.begin(); -} - -uint8_t ADS1115::trigger_sample() -{ - return write_register(ADS1115_REGISTER_CONFIG, m_config | SAMPLE_BIT); -} - -uint8_t ADS1115::reset() -{ - Wire.beginTransmission(0); - Wire.write(0x6); - return Wire.endTransmission(); -} - -bool ADS1115::is_sample_in_progress() -{ - uint16_t val = read_register(ADS1115_REGISTER_CONFIG); - return (val & SAMPLE_BIT) == 0; -} - -int16_t ADS1115::read_sample() -{ - return read_register(ADS1115_REGISTER_CONVERSION); -} - -float ADS1115::sample_to_float(int16_t val) -{ - return val * ranges[m_voltage_range]; -} - -float ADS1115::read_sample_float() -{ - return sample_to_float(read_sample()); -} - -ADS1115 adc; - -void ADS1115_init(void) { - - ads1115_up=0; - if (!i2c_flg) return; - - adc.begin(); - adc.set_data_rate(ADS1115_DATA_RATE_128_SPS); - adc.set_mode(ADS1115_MODE_CONTINUOUS); - adc.set_mux(ADS1115_MUX_DIFF_AIN0_AIN3); - adc.set_pga(ADS1115_PGA_TWO); - - int16_t val = adc.read_sample(); - ads1115_up=1; -} - -#endif - -char sml_start; -uint8_t dump2log=0; - -#define SML_SAVAILABLE Serial_available() -#define SML_SREAD Serial_read() -#define SML_SPEAK Serial_peek() - -bool Serial_available() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->available(); -} - -uint8_t Serial_read() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->read(); -} - -uint8_t Serial_peek() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->peek(); -} - -uint8_t sml_logindex; - -void Dump2log(void) { - -int16_t index=0,hcnt=0; -uint32_t d_lastms; -uint8_t dchars[16]; - - - - if (dump2log&8) { - - while (SML_SAVAILABLE) { - log_data[index]=':'; - index++; - log_data[index]=' '; - index++; - d_lastms=millis(); - while ((millis()-d_lastms)<40) { - if (SML_SAVAILABLE) { - uint8_t c=SML_SREAD; - sprintf(&log_data[index],"%02x ",c); - dchars[hcnt]=c; - index+=3; - hcnt++; - if (hcnt>15) { - - log_data[index]='='; - index++; - log_data[index]='>'; - index++; - log_data[index]=' '; - index++; - for (uint8_t ccnt=0; ccnt<16; ccnt++) { - if (isprint(dchars[ccnt])) { - log_data[index]=dchars[ccnt]; - } else { - log_data[index]=' '; - } - index++; - } - break; - } - } - } - if (index>0) { - log_data[index]=0; - AddLog(LOG_LEVEL_INFO); - index=0; - hcnt=0; - } - } - } else { - if (meter_desc_p[(dump2log&7)-1].type=='o') { - - while (SML_SAVAILABLE) { - char c=SML_SREAD&0x7f; - if (c=='\n' || c=='\r') { - log_data[sml_logindex]=0; - AddLog(LOG_LEVEL_INFO); - sml_logindex=2; - log_data[0]=':'; - log_data[1]=' '; - break; - } - log_data[sml_logindex]=c; - if (sml_logindex2) { - log_data[index]=0; - AddLog(LOG_LEVEL_INFO); - } - } - } -} - - -uint8_t *skip_sml(uint8_t *cp,int16_t *res) { - uint8_t len,len1,type; - len=*cp&0xf; - type=*cp&0x70; - if (type==0x70) { - - - cp++; - while (len--) { - len1=*cp&0x0f; - cp+=len1; - } - *res=0; - } else { - - *res=(signed char)*(cp+1); - cp+=len; - } - return cp; -} - - - -double sml_getvalue(unsigned char *cp,uint8_t index) { -uint8_t len,unit,type; -int16_t scaler,result; -int64_t value; -double dval; - - - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - scaler=result; - - type=*cp&0x70; - len=*cp&0x0f; - cp++; - if (type==0x50 || type==0x60) { - - uint64_t uvalue=0; - uint8_t nlen=len; - while (--nlen) { - uvalue<<=8; - uvalue|=*cp++; - } - if (type==0x50) { - - switch (len-1) { - case 1: - - value=(signed char)uvalue; - break; - case 2: - -#ifdef DWS74_BUG - if (scaler==-2) { - value=(uint32_t)uvalue; - } else { - value=(int16_t)uvalue; - } -#else - value=(int16_t)uvalue; -#endif - break; - case 3: - case 4: - - value=(int32_t)uvalue; - break; - case 5: - case 6: - case 7: - case 8: - - value=(int64_t)uvalue; - break; - } - } else { - - value=uvalue; - } - - } else { - if (!(type&0xf0)) { - - - - if (len==9) { - - cp++; - uint32_t s1,s2; - s1=*cp<<16|*(cp+1)<<8|*(cp+2); - cp+=4; - s2=*cp<<16|*(cp+1)<<8|*(cp+2); - sprintf(&meter_id[index][0],"%u-%u",s1,s2); - } else { - - char *str=&meter_id[index][0]; - for (type=0; type= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - } - return rVal; -} - -uint8_t sb_counter; - - -double CharToDouble(const char *str) -{ - - char strbuf[24]; - - strlcpy(strbuf, str, sizeof(strbuf)); - char *pt = strbuf; - while ((*pt != '\0') && isblank(*pt)) { pt++; } - - signed char sign = 1; - if (*pt == '-') { sign = -1; } - if (*pt == '-' || *pt=='+') { pt++; } - - double left = 0; - if (*pt != '.') { - left = atoi(pt); - while (isdigit(*pt)) { pt++; } - } - - double right = 0; - if (*pt == '.') { - pt++; - right = atoi(pt); - while (isdigit(*pt)) { - pt++; - right /= 10.0; - } - } - - double result = left + right; - if (sign < 0) { - return -result; - } - return result; -} - - - -void ebus_esc(uint8_t *ebus_buffer, unsigned char len) { - short count,count1; - for (count=0; countavailable()) { - meter_ss[meters]->read(); - } -} - - -void sml_shift_in(uint32_t meters,uint32_t shard) { - uint32_t count; - if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p') { - - for (count=0; countread(); - - if (meter_desc_p[meters].type=='o') { - smltbuf[meters][SML_BSIZ-1]=iob&0x7f; - } else if (meter_desc_p[meters].type=='s') { - smltbuf[meters][SML_BSIZ-1]=iob; - } else if (meter_desc_p[meters].type=='r') { - smltbuf[meters][SML_BSIZ-1]=iob; - } else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M') { - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=9) { - SML_Decode(meters); - sml_empty_receiver(meters); - meter_spos[meters]=0; - } - } else if (meter_desc_p[meters].type=='p') { - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=7) { - SML_Decode(meters); - sml_empty_receiver(meters); - meter_spos[meters]=0; - } - } else { - if (iob==EBUS_SYNC) { - - - if (meter_spos[meters]>4+5) { - - uint8_t tlen=smltbuf[meters][4]+5; - - if (smltbuf[meters][tlen]=ebus_CalculateCRC(smltbuf[meters],tlen)) { - ebus_esc(smltbuf[meters],tlen); - SML_Decode(meters); - } else { - - - } - } - meter_spos[meters]=0; - return; - } - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=SML_BSIZ) { - meter_spos[meters]=0; - } - } - sb_counter++; - if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p') SML_Decode(meters); -} - - - -void SML_Poll(void) { -uint32_t meters; - - for (meters=0; metersavailable()) { - sml_shift_in(meters,0); - } - } - } -} - - -void SML_Decode(uint8_t index) { - const char *mp=(const char*)meter_p; - int8_t mindex; - uint8_t *cp; - uint8_t dindex=0,vindex=0; - delay(0); - while (mp != NULL) { - - - - mindex=((*mp)&7)-1; - - if (mindex<0 || mindex>=meters_used) mindex=0; - mp+=2; - if (*mp=='=' && *(mp+1)=='h') { - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - - if (index!=mindex) goto nextsect; - - - cp=&smltbuf[mindex][0]; - - - if (*mp=='=') { - - mp++; - - if (*mp=='m' && !sb_counter) { - - - mp++; - while (*mp==' ') mp++; - - double dvar; - uint8_t opr; - uint32_t ind; - ind=atoi(mp); - while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>SML_MAX_VARS) ind=1; - dvar=meter_vars[ind-1]; - for (uint8_t p=0;p<5;p++) { - if (*mp=='@') { - - meter_vars[vindex]=dvar; - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - break; - } - opr=*mp; - mp++; - uint8_t iflg=0; - if (*mp=='#') { - iflg=1; - mp++; - } - ind=atoi(mp); - while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>SML_MAX_VARS) ind=1; - switch (opr) { - case '+': - if (iflg) dvar+=ind; - else dvar+=meter_vars[ind-1]; - break; - case '-': - if (iflg) dvar-=ind; - else dvar-=meter_vars[ind-1]; - break; - case '*': - if (iflg) dvar*=ind; - else dvar*=meter_vars[ind-1]; - break; - case '/': - if (iflg) dvar/=ind; - else dvar/=meter_vars[ind-1]; - break; - } - while (*mp==' ') mp++; - if (*mp=='@') { - - meter_vars[vindex]=dvar; - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - break; - } - } - } else if (*mp=='d') { - - if (dindex='0' && *mp<='9') mp++; - if (ind<1 || ind>SML_MAX_VARS) ind=1; - uint32_t delay=atoi(mp)*1000; - uint32_t dtime=millis()-dtimes[dindex]; - if (dtime>delay) { - - dtimes[dindex]=millis(); - double vdiff = meter_vars[ind-1]-dvalues[dindex]; - dvalues[dindex]=meter_vars[ind-1]; - meter_vars[vindex]=(double)360000.0*vdiff/((double)dtime/10000.0); - - mp=strchr(mp,'@'); - if (mp) { - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - } - } - dindex++; - } - } else if (*mp=='h') { - - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - } else { - - uint8_t found=1; - uint32_t ebus_dval=99; - float mbus_dval=99; - while (*mp!='@') { - if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') { - if (*mp++!=*cp++) { - found=0; - } - } else { - if (meter_desc_p[mindex].type=='s') { - - uint8_t val = hexnibble(*mp++) << 4; - val |= hexnibble(*mp++); - if (val!=*cp++) { - found=0; - } - } else { - - - if (*mp=='x' && *(mp+1)=='x') { - - mp+=2; - cp++; - } else if (!strncmp(mp,"UUuuUUuu",8)) { - uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); - ebus_dval=val; - mbus_dval=val; - mp+=8; - cp+=4; - } else if (*mp=='U' && *(mp+1)=='U' && *(mp+2)=='u' && *(mp+3)=='u'){ - uint16_t val = cp[1]|(cp[0]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (!strncmp(mp,"SSssSSss",8)) { - int32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); - ebus_dval=val; - mbus_dval=val; - mp+=8; - cp+=4; - } else if (*mp=='u' && *(mp+1)=='u' && *(mp+2)=='U' && *(mp+3)=='U'){ - uint16_t val = cp[0]|(cp[1]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (*mp=='u' && *(mp+1)=='u') { - uint8_t val = *cp++; - mbus_dval=val; - ebus_dval=val; - mp+=2; - } else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='S' && *(mp+3)=='S') { - int16_t val = *cp|(*(cp+1)<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (*mp=='S' && *(mp+1)=='S' && *(mp+2)=='s' && *(mp+3)=='s') { - int16_t val = cp[1]|(cp[0]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } - else if (*mp=='s' && *(mp+1)=='s') { - int8_t val = *cp++; - mbus_dval=val; - ebus_dval=val; - mp+=2; - } - else if (!strncmp(mp,"ffffffff",8)) { - uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); - float *fp=(float*)&val; - ebus_dval=*fp; - mbus_dval=*fp; - mp+=8; - cp+=4; - } - else if (!strncmp(mp,"FFffFFff",8)) { - - uint32_t val= (cp[1]<<0)|(cp[0]<<8)|(cp[3]<<16)|(cp[2]<<24); - float *fp=(float*)&val; - ebus_dval=*fp; - mbus_dval=*fp; - mp+=8; - cp+=4; - } - else if (!strncmp(mp,"eeeeee",6)) { - uint32_t val=(cp[0]<<16)|(cp[1]<<8)|(cp[2]<<0); - mbus_dval=val; - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"vvvvvv",6)) { - mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/10.0); - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"cccccc",6)) { - mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/100.0); - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"pppp",4)) { - mbus_dval=(float)((cp[0]<<8)|cp[1]); - mp+=4; - cp+=2; - } - else { - uint8_t val = hexnibble(*mp++) << 4; - val |= hexnibble(*mp++); - if (val!=*cp++) { - found=0; - } - } - } - } - } - if (found) { - - mp++; - if (*mp=='#') { - - mp++; - if (meter_desc_p[mindex].type=='o') { - for (uint8_t p=0;p>=shift; - ebus_dval&=1; - mp+=2; - } - if (*mp=='i') { - - mp++; - uint8_t mb_index=strtol((char*)mp,(char**)&mp,10); - if (mb_index!=meter_desc_p[mindex].index) { - goto nextsect; - } - uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7); - if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect; - if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect; - dval=mbus_dval; - - mp++; - } else { - if (meter_desc_p[mindex].type=='p') { - uint8_t crc = SML_PzemCrc(&smltbuf[mindex][0],6); - if (crc!=smltbuf[mindex][6]) goto nextsect; - dval=mbus_dval; - } else { - dval=ebus_dval; - } - } - - } -#ifdef USE_SML_MEDIAN_FILTER - if (meter_desc_p[mindex].flag&16) { - meter_vars[vindex]=sml_median(&sml_mf[vindex],dval); - } else { - meter_vars[vindex]=dval; - } -#else - meter_vars[vindex]=dval; -#endif - - - double fac=CharToDouble((char*)mp); - meter_vars[vindex]/=fac; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - } - } - } -nextsect: - - if (vindex=meters_used) lastmind=0; - while (mp != NULL) { - - mindex=((*mp)&7)-1; - if (mindex<0 || mindex>=meters_used) mindex=0; - mp+=2; - if (*mp=='=' && *(mp+1)=='h') { - mp+=2; - - if (json) { - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - - uint8_t i; - for (i=0;isml_counters[index].sml_debounce) { - RtcSettings.pulse_counter[index]++; - InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]); - } - } else { - - sml_counters[index].sml_counter_ltime=millis(); - } -} - -void SML_CounterUpd1(void) { - SML_CounterUpd(0); -} - -void SML_CounterUpd2(void) { - SML_CounterUpd(1); -} - -void SML_CounterUpd3(void) { - SML_CounterUpd(2); -} - -void SML_CounterUpd4(void) { - SML_CounterUpd(3); -} - -#ifdef USE_SCRIPT -struct METER_DESC script_meter_desc[MAX_METERS]; -uint8_t *script_meter; -#endif - -#ifndef METER_DEF_SIZE -#define METER_DEF_SIZE 3000 -#endif - -bool Gpio_used(uint8_t gpiopin) { - for (uint16_t i=0;iM",-2,0); - if (meter_script==99) { - - if (script_meter) free(script_meter); - script_meter=0; - uint8_t *tp=0; - uint16_t index=0; - uint8_t section=0; - uint8_t srcpin=0; - char *lp=glob_script_mem.scriptptr; - sml_send_blocks=0; - while (lp) { - if (!section) { - if (*lp=='>' && *(lp+1)=='M') { - lp+=2; - meters_used=strtol(lp,0,10); - section=1; - uint32_t mlen=0; - for (uint32_t cnt=0;cnt') { - if (*(tp-1)=='|') *(tp-1)=0; - break; - } - if (*lp=='+') { - - - lp++; - index=*lp&7; - lp+=2; - if (index<1 || index>meters_used) goto next_line; - index--; - srcpin=strtol(lp,&lp,10); - if (Gpio_used(srcpin)) { - AddLog_P(LOG_LEVEL_INFO, PSTR("gpio rx double define!")); -dddef_exit: - if (script_meter) free(script_meter); - script_meter=0; - meters_used=METERS_USED; - goto init10; - } - script_meter_desc[index].srcpin=srcpin; - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].type=*lp; - lp+=2; - script_meter_desc[index].flag=strtol(lp,&lp,10); - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].params=strtol(lp,&lp,10); - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].prefix[7]=0; - for (uint32_t cnt=0; cnt<8; cnt++) { - if (*lp==SCRIPT_EOL || *lp==',') { - script_meter_desc[index].prefix[cnt]=0; - break; - } - script_meter_desc[index].prefix[cnt]=*lp++; - } - if (*lp==',') { - lp++; - script_meter_desc[index].trxpin=strtol(lp,&lp,10); - if (Gpio_used(script_meter_desc[index].trxpin)) { - AddLog_P(LOG_LEVEL_INFO, PSTR("gpio tx double define!")); - goto dddef_exit; - } - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].tsecs=strtol(lp,&lp,10); - if (*lp==',') { - lp++; - char txbuff[256]; - uint32_t txlen=0,tx_entries=1; - for (uint32_t cnt=0; cntmeters_used) goto next_line; - while (1) { - if (*lp==SCRIPT_EOL) { - if (*(tp-1)!='|') *tp++='|'; - goto next_line; - } - *tp++=*lp++; - index++; - if (index>=METER_DEF_SIZE) break; - } - } - - } - -next_line: - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - *tp=0; - meter_desc_p=script_meter_desc; - meter_p=script_meter; - } -#endif - -init10: - typedef void (*function)(); - function counter_callbacks[] = {SML_CounterUpd1,SML_CounterUpd2,SML_CounterUpd3,SML_CounterUpd4}; - uint8_t cindex=0; - - for (byte i = 0; i < MAX_COUNTERS; i++) { - RtcSettings.pulse_counter[i]=Settings.pulse_counter[i]; - sml_counters[i].sml_cnt_last_ts=millis(); - } - for (uint8_t meters=0; metersbegin(meter_desc_p[meters].params)) { - meter_ss[meters]->flush(); - } - if (meter_ss[meters]->hardwareSerial()) { - if (meter_desc_p[meters].type=='M') { - Serial.begin(meter_desc_p[meters].params, SERIAL_8E1); - } - ClaimSerial(); - } - - } - } - -} - - -#ifdef USE_SML_SCRIPT_CMD -uint32_t SML_SetBaud(uint32_t meter, uint32_t br) { - if (meter<1 || meter>meters_used) return 0; - meter--; - if (!meter_ss[meter]) return 0; - if (meter_ss[meter]->begin(br)) { - meter_ss[meter]->flush(); - } - if (meter_ss[meter]->hardwareSerial()) { - if (meter_desc_p[meter].type=='M') { - Serial.begin(br, SERIAL_8E1); - } - } - return 1; -} - -uint32_t SML_Write(uint32_t meter,char *hstr) { - if (meter<1 || meter>meters_used) return 0; - meter--; - if (!meter_ss[meter]) return 0; - SML_Send_Seq(meter,hstr); - return 1; -} -#endif - - -void SetDBGLed(uint8_t srcpin, uint8_t ledpin) { - pinMode(ledpin, OUTPUT); - if (digitalRead(srcpin)) { - digitalWrite(ledpin,LOW); - } else { - digitalWrite(ledpin,HIGH); - } -} - - -void SML_Counter_Poll(void) { -uint16_t meters,cindex=0; -uint32_t ctime=millis(); - - for (meters=0; meters0) { - if (ctime-sml_counters[cindex].sml_cnt_last_ts>meter_desc_p[meters].params) { - sml_counters[cindex].sml_cnt_last_ts=ctime; - - if (meter_desc_p[meters].flag&2) { - -#ifdef ANALOG_OPTO_SENSOR - if (ads1115_up) { - int16_t val = adc.read_sample(); - if (val>sml_counters[cindex].ana_max) sml_counters[cindex].ana_max=val; - if (val10) { - sml_counters[cindex].sml_cnt_last_ts=ctime; -#ifdef DEBUG_CNT_LED1 - if (cindex==0) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED1); -#endif -#ifdef DEBUG_CNT_LED2 - if (cindex==1) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED2); -#endif - } - } - cindex++; - } - } -} - -#ifdef USE_SCRIPT -char *SML_Get_Sequence(char *cp,uint32_t index) { - if (!index) return cp; - uint32_t cindex=0; - while (cp) { - cp=strchr(cp,','); - if (cp) { - cp++; - cindex++; - if (cindex==index) { - return cp; - } - } - } -} - -void SML_Check_Send(void) { - sml_100ms_cnt++; - char *cp; - for (uint32_t cnt=sml_desc_cnt; cnt=0 && script_meter_desc[cnt].txmem) { - if ((sml_100ms_cnt%script_meter_desc[cnt].tsecs)==0) { - if (script_meter_desc[cnt].max_index>1) { - script_meter_desc[cnt].index++; - if (script_meter_desc[cnt].index>=script_meter_desc[cnt].max_index) { - script_meter_desc[cnt].index=0; - sml_desc_cnt++; - } - cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index); - - } else { - cp=script_meter_desc[cnt].txmem; - - sml_desc_cnt++; - } - - SML_Send_Seq(cnt,cp); - if (sml_desc_cnt>=meters_used) { - sml_desc_cnt=0; - } - break; - } - } else { - sml_desc_cnt++; - } - - if (sml_desc_cnt>=meters_used) { - sml_desc_cnt=0; - } - } -} - -uint8_t sml_hexnibble(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { - rVal = chr - '0'; - } else { - if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; - } - return rVal; -} - - -void SML_Send_Seq(uint32_t meter,char *seq) { - uint8_t sbuff[32]; - uint8_t *ucp=sbuff,slen=0; - char *cp=seq; - while (*cp) { - if (!*cp || !*(cp+1)) break; - if (*cp==',') break; - uint8_t iob=(sml_hexnibble(*cp) << 4) | sml_hexnibble(*(cp+1)); - cp+=2; - *ucp++=iob; - slen++; - if (slen>=sizeof(sbuff)) break; - } - if (script_meter_desc[meter].type=='m' || script_meter_desc[meter].type=='M') { - *ucp++=0; - *ucp++=2; - - uint16_t crc = MBUS_calculateCRC(sbuff,6); - *ucp++=lowByte(crc); - *ucp++=highByte(crc); - slen+=4; - } - if (script_meter_desc[meter].type=='o') { - for (uint32_t cnt=0;cntwrite(sbuff,slen); -} -#endif - -uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { - uint16_t crc, flag; - crc = 0xFFFF; - for (uint32_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint32_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { - crc >>= 1; - crc ^= 0xA001; - } else { - crc >>= 1; - } - } - } - return crc; -} - -uint8_t SML_PzemCrc(uint8_t *data, uint8_t len) { - uint16_t crc = 0; - for (uint32_t i = 0; i < len; i++) crc += *data++; - return (uint8_t)(crc & 0xFF); -} - - -uint8_t CalcEvenParity(uint8_t data) { -uint8_t parity=0; - - while(data) { - parity^=(data &1); - data>>=1; - } - return parity; -} -# 2361 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_53_sml.ino" -bool XSNS_53_cmd(void) { - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - char *cp=XdrvMailbox.data; - if (*cp=='d') { - - cp++; - uint8_t index=atoi(cp); - if ((index&7)>meters_used) index=1; - if (index>0 && meter_desc_p[(index&7)-1].type=='c') { - index=0; - } - dump2log=index; - ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); - } else if (*cp=='c') { - - cp++; - uint8_t index=*cp&7; - if (index<1 || index>MAX_COUNTERS) index=1; - cp++; - while (*cp==' ') cp++; - if (isdigit(*cp)) { - uint32_t cval=atoi(cp); - while (isdigit(*cp)) cp++; - RtcSettings.pulse_counter[index-1]=cval; - uint8_t cindex=0; - for (uint8_t meters=0; metersaddress, INA226_REG_CALIBRATION, si->calibrationValue); - -} - - - - - - -bool Ina226TestPresence(uint8_t device) -{ - - - - uint16_t config = I2cRead16( slaveInfo[device].address, INA226_REG_CONFIG ); - - - if (config != slaveInfo[device].config) - return false; - - return true; - -} - -void Ina226ResetActive(void) -{ - Ina226SlaveInfo_t *p = slaveInfo; - - for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) { - p = &slaveInfo[i]; - - uint8_t addr = p->address; - if (addr) { - I2cResetActive(addr); - } - } -} - - - - - -void Ina226Init() -{ - uint32_t i; - - slavesFound = 0; - - Ina226SlaveInfo_t *p = slaveInfo; -# 215 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_54_ina226.ino" - for (i = 0; i < 4; i++){ - *p = {0}; - } - - - - - - for (i = 0; i < INA226_MAX_ADDRESSES; i++){ - uint8_t addr = pgm_read_byte(probeAddresses + i); - - if (I2cActive(addr)) { continue; } - - - - - if (!Settings.ina226_i_fs[i]) - continue; - - - - - - - if (!I2cWrite16( addr, INA226_REG_CONFIG, INA226_CONFIG_RESET)){ - - AddLog_P2( LOG_LEVEL_DEBUG, "No INA226 at address: %02X", addr); - continue; - } - - - - uint16_t config = I2cRead16( addr, INA226_REG_CONFIG ); - - - if (INA226_RES_CONFIG != config) - continue; - - - config = INA226_DEF_CONFIG; - - - if (!I2cWrite16( addr, INA226_REG_CONFIG, config)) - continue; - - - p = &slaveInfo[i]; - - p->address = addr; - - p->config = config; - - - p->i_lsb = (((float) Settings.ina226_i_fs[i])/10.0f)/32768.0f; - - - - uint32_t r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[i]); - - - - p->calibrationValue = ((uint16_t) (0.00512/(p->i_lsb * r_shunt_uohms/1000000.0f))); - - p->present = true; - - - Ina226SetCalibration(i); - - I2cSetActiveFound(addr, Ina226Str); - - slavesFound++; - } -} - - - - - -float Ina226ReadBus_v(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE); - - float result = ((float) reg_bus_v) * 0.00125f; - - return result; - -} - - - - - -float Ina226ReadShunt_i(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); - - float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb; - - return result; -} - - - - - -float Ina226ReadPower_w(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); - - float result = ((float) reg_shunt_i) * (slaveInfo[device].i_lsb * 25.0); - - return result; -} - - - - - - -void Ina226Read(uint8_t device) -{ - - voltages[device] = Ina226ReadBus_v(device); - currents[device] = Ina226ReadShunt_i(device); - powers[device] = Ina226ReadPower_w(device); - - - - -} - - - - - -void Ina226EverySecond() -{ - - for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){ - - if (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){ - Ina226Read(device); - } - else { - powers[device] = currents[device] = voltages[device] = 0.0f; - - - - - - - slaveInfo[device].present = false; - } - } -} - - - - - -bool Ina226CommandSensor() -{ - bool serviced = true; - bool show_config = false; - char param_str[64]; - char *cp, *params[4]; - uint8_t i, param_count, device, p1 = XdrvMailbox.payload; - uint32_t r_shunt_uohms; - uint16_t compact_r_shunt_uohms; - - - - - - if (XdrvMailbox.data_len > 62){ - return false; - } - - strncpy(param_str, XdrvMailbox.data, XdrvMailbox.data_len + 1); - param_str[XdrvMailbox.data_len] = 0; - - - for (cp = param_str, i = 0, param_count = 0; *cp && (i < XdrvMailbox.data_len + 1) && (param_count <= 3); i++) - if (param_str[i] == ' ' || param_str[i] == ',' || param_str[i] == 0){ - param_str[i] = 0; - params[param_count] = cp; - - param_count++; - cp = param_str + i + 1; - } - - - if (p1 < 10 || p1 >= 50){ - - switch (p1){ - case 1: - Ina226ResetActive(); - Ina226Init(); - Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound); - break; - - case 2: - restart_flag = 2; - Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag); - break; - - default: - serviced = false; - } - } - else if (p1 < 50){ - - device = (p1 / 10) - 1; - switch (p1 % 10){ - case 0: - show_config = true; - break; - - case 1: - r_shunt_uohms = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f); - - - - if (r_shunt_uohms > 32767){ - uint32_t r_shunt_mohms = r_shunt_uohms/1000UL; - Settings.ina226_r_shunt[device] = (uint16_t) (r_shunt_mohms | 0x8000); - } - else - Settings.ina226_r_shunt[device] = (uint16_t) r_shunt_uohms; - - - show_config = true; - break; - - case 2: - Settings.ina226_i_fs[device] = (uint16_t) ((CharToFloat(params[1])) * 10.0f); - - show_config = true; - break; - - - default: - serviced = false; - break; - } - } - else - serviced = false; - - if (show_config) { - char shunt_r_str[16]; - char fs_i_str[16]; - - - r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[device]); - dtostrfd(((float)r_shunt_uohms)/1000000.0f, 6, shunt_r_str); - - dtostrfd(((float)Settings.ina226_i_fs[device])/10.0f, 1, fs_i_str); - - Response_P(PSTR("{\"Sensor54-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"), - device + 1, shunt_r_str, fs_i_str); - } - - return serviced; -} - - - - - -#ifdef USE_WEBSERVER -const char HTTP_SNS_INA226_DATA[] PROGMEM = - "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; -#endif - -void Ina226Show(bool json) -{ - int i, num_found; - for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) { - - if (!slaveInfo[i].present) - continue; - - num_found++; - - char voltage[16]; - dtostrfd(voltages[i], Settings.flag2.voltage_resolution, voltage); - char current[16]; - dtostrfd(currents[i], Settings.flag2.current_resolution, current); - char power[16]; - dtostrfd(powers[i], Settings.flag2.wattage_resolution, power); - char name[16]; - snprintf_P(name, sizeof(name), PSTR("INA226%c%d"),IndexSeparator(), i + 1); - - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%d,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - name, i, voltage, current, power); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_INA226_DATA, name, voltage, name, current, name, power); -#endif - } - - } - -} -# 546 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_54_ina226.ino" -bool Xsns54(byte callback_id) -{ - if (!I2cEnabled(XI2C_35)) { return false; } - - - bool result = false; - - - switch (callback_id) { - case FUNC_EVERY_SECOND: - Ina226EverySecond(); - break; - case FUNC_JSON_APPEND: - Ina226Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ina226Show(0); - break; -#endif - case FUNC_COMMAND_SENSOR: - if (XSNS_54 == XdrvMailbox.index) { - result = Ina226CommandSensor(); - } - break; - case FUNC_INIT: - Ina226Init(); - break; - } - - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_55_hih_series.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_55_hih_series.ino" -#ifdef USE_I2C -#ifdef USE_HIH6 -# 33 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_55_hih_series.ino" -#define XSNS_55 55 -#define XI2C_36 36 - -#define HIH6_ADDR 0x27 - -struct HIH6 { - float temperature = 0; - float humidity = 0; - uint8_t valid = 0; - uint8_t type = 0; - char types[4] = "HIH"; -} Hih6; - -bool Hih6Read(void) -{ - Wire.beginTransmission(HIH6_ADDR); - if (Wire.endTransmission() != 0) { return false; } - - delay(40); - - uint8_t data[4]; - Wire.requestFrom(HIH6_ADDR, 4); - if (4 == Wire.available()) { - data[0] = Wire.read(); - data[1] = Wire.read(); - data[2] = Wire.read(); - data[3] = Wire.read(); - } else { return false; } - - - - Hih6.humidity = ConvertHumidity(((float)(((data[0] & 0x3F) << 8) | data[1]) * 100.0) / 16383.0); - - int temp = ((data[2] << 8) | (data[3] & 0xFC)) / 4; - Hih6.temperature = ConvertTemp(((float)temp / 16384.0) * 165.0 - 40.0); - - Hih6.valid = SENSOR_MAX_MISS; - return true; -} - - - -void Hih6Detect(void) -{ - if (I2cActive(HIH6_ADDR)) { return; } - - if (uptime < 2) { delay(20); } - Hih6.type = Hih6Read(); - if (Hih6.type) { - I2cSetActiveFound(HIH6_ADDR, Hih6.types); - } -} - -void Hih6EverySecond(void) -{ - if (uptime &1) { - - if (!Hih6Read()) { - AddLogMissed(Hih6.types, Hih6.valid); - } - } -} - -void Hih6Show(bool json) -{ - if (Hih6.valid) { - char temperature[33]; - dtostrfd(Hih6.temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Hih6.humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Hih6.types, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, Hih6.temperature); - KnxSensor(KNX_HUMIDITY, Hih6.humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Hih6.types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Hih6.types, humidity); -#endif - } - } -} - - - - - -bool Xsns55(uint8_t function) -{ - if (!I2cEnabled(XI2C_36)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Hih6Detect(); - } - else if (Hih6.type) { - switch (function) { - case FUNC_EVERY_SECOND: - Hih6EverySecond(); - break; - case FUNC_JSON_APPEND: - Hih6Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Hih6Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_56_hpma.ino" -# 21 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_56_hpma.ino" -#ifdef USE_HPMA -# 31 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_56_hpma.ino" -#define XSNS_56 56 - -#include -#include - -TasmotaSerial *HpmaSerial; -HPMA115S0 *hpma115S0; - -uint8_t hpma_type = 1; -uint8_t hpma_valid = 0; - -struct hpmadata { - unsigned int pm10; - unsigned int pm2_5; -} hpma_data; - - - -void HpmaSecond(void) -{ - unsigned int pm2_5, pm10; - - - - - if (hpma115S0->ReadParticleMeasurement(&pm2_5, &pm10)) { - hpma_data.pm2_5 = pm2_5; - hpma_data.pm10 = pm10; - hpma_valid = 1; - } - -} - -void HpmaInit(void) -{ - hpma_type = 0; - if (pin[GPIO_HPMA_RX] < 99 && pin[GPIO_HPMA_TX] < 99) { - HpmaSerial = new TasmotaSerial(pin[GPIO_HPMA_RX], pin[GPIO_HPMA_TX], 1); - hpma115S0 = new HPMA115S0(*HpmaSerial); - - if (HpmaSerial->begin(9600)) { - if (HpmaSerial->hardwareSerial()) { - ClaimSerial(); - } - hpma_type = 1; - hpma115S0->Init(); - hpma115S0->StartParticleMeasurement(); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_HPMA_SNS[] PROGMEM = - "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; -#endif - -void HpmaShow(bool json) -{ - if (hpma_valid) { - char pm10[33]; - snprintf_P(pm10, 33, PSTR("%d"), hpma_data.pm10); - char pm2_5[33]; - snprintf_P(pm2_5, 33, PSTR("%d"), hpma_data.pm2_5); - - if (json) { - ResponseAppend_P(PSTR(",\"HPMA\":{\"PM2.5\":%d,\"PM10\":%d}"), hpma_data.pm2_5, hpma_data.pm10); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, pm2_5); - DomoticzSensor(DZ_CURRENT, pm10); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_HPMA_SNS, pm2_5, pm10); -#endif - } - } -} - - - - - -bool Xsns56(uint8_t function) -{ - bool result = false; - - if (hpma_type) { - switch (function) { - case FUNC_INIT: - HpmaInit(); - break; - case FUNC_EVERY_SECOND: - HpmaSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_56 == XdrvMailbox.index) { - return true; - } - break; - case FUNC_JSON_APPEND: - HpmaShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HpmaShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_57_tsl2591.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_57_tsl2591.ino" -#ifdef USE_I2C -#ifdef USE_TSL2591 - - - - - - - -#define XSNS_57 57 -#define XI2C_40 40 - -#define TSL2591_ADDRESS 0x29 - -#include - -Adafruit_TSL2591 tsl = Adafruit_TSL2591(); - -uint8_t tsl2591_type = 0; -uint8_t tsl2591_valid = 0; -float tsl2591_lux = 0; - -void Tsl2591Init(void) -{ - - if (I2cSetDevice(0x29)) { - if (tsl.begin()) { - tsl.setGain(TSL2591_GAIN_MED); - tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS); - tsl2591_type = 1; - I2cSetActiveFound(TSL2591_ADDRESS, "TSL2591"); - } - } -} - -bool Tsl2591Read(void) -{ - uint32_t lum = tsl.getFullLuminosity(); - uint16_t ir, full; - ir = lum >> 16; - full = lum & 0xFFFF; - tsl2591_lux = tsl.calculateLux(full, ir); - tsl2591_valid = 1; -} - -void Tsl2591EverySecond(void) -{ - Tsl2591Read(); -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_TSL2591[] PROGMEM = - "{s}TSL2591 " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; -#endif - -void Tsl2591Show(bool json) -{ - if (tsl2591_valid) { - char lux_str[10]; - dtostrf(tsl2591_lux, sizeof(lux_str)-1, 3, lux_str); - if (json) { - ResponseAppend_P(PSTR(",\"TSL2591\":{\"" D_JSON_ILLUMINANCE "\":%s}"), lux_str); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TSL2591, lux_str); -#endif - } - } -} - - - - - -bool Xsns57(uint8_t function) -{ - if (!I2cEnabled(XI2C_40)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Tsl2591Init(); - } - else if (tsl2591_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Tsl2591EverySecond(); - break; - case FUNC_JSON_APPEND: - Tsl2591Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tsl2591Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_58_dht12.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_58_dht12.ino" -#ifdef USE_I2C -#ifdef USE_DHT12 - - - - - - -#define XSNS_58 58 -#define XI2C_41 41 - -#define DHT12_ADDR 0x5C - -struct DHT12 { - float temperature = NAN; - float humidity = NAN; - uint8_t valid = 0; - uint8_t count = 0; - char name[6] = "DHT12"; -} Dht12; - -bool Dht12Read(void) -{ - if (Dht12.valid) { Dht12.valid--; } - - Wire.beginTransmission(DHT12_ADDR); - Wire.write(0); - if (Wire.endTransmission() != 0) { return false; } - - delay(50); - - Wire.requestFrom(DHT12_ADDR, 5); - delay(5); - uint8_t humidity = Wire.read(); - uint8_t humidityTenth = Wire.read(); - uint8_t temp = Wire.read(); - uint8_t tempTenth = Wire.read(); - uint8_t checksum = Wire.read(); - - Dht12.humidity = ConvertHumidity( (float) humidity + (float) humidityTenth/(float) 10.0 ); - Dht12.temperature = ConvertTemp( (float) temp + (float) tempTenth/(float) 10.0 ); - - if (isnan(Dht12.temperature) || isnan(Dht12.humidity)) { return false; } - - Dht12.valid = SENSOR_MAX_MISS; - return true; -} - - - -void Dht12Detect(void) -{ - if (I2cActive(DHT12_ADDR)) { return; } - - if (Dht12Read()) { - I2cSetActiveFound(DHT12_ADDR, Dht12.name); - Dht12.count = 1; - } -} - -void Dht12EverySecond(void) -{ - if (uptime &1) { - - if (!Dht12Read()) { - AddLogMissed(Dht12.name, Dht12.valid); - } - } -} - -void Dht12Show(bool json) -{ - if (Dht12.valid) { - char temperature[33]; - dtostrfd(Dht12.temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht12.humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht12.name, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, Dht12.temperature); - KnxSensor(KNX_HUMIDITY, Dht12.humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht12.name, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht12.name, humidity); -#endif - } - } -} - - - - - -bool Xsns58(uint8_t function) -{ - if (!I2cEnabled(XI2C_41)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Dht12Detect(); - } - else if (Dht12.count) { - switch (function) { - case FUNC_EVERY_SECOND: - Dht12EverySecond(); - break; - case FUNC_JSON_APPEND: - Dht12Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Dht12Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_59_ds1624.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_59_ds1624.ino" -#ifdef USE_I2C -#ifdef USE_DS1624 - - - - - - - -#define XSNS_59 59 -#define XI2C_42 42 - -#define DS1624_MEM_REGISTER 0x17 -#define DS1624_CONF_REGISTER 0xAC -#define DS1624_TEMP_REGISTER 0xAA -#define DS1624_START_REGISTER 0xEE -#define DS1624_STOP_REGISTER 0x22 - -#define DS1621_COUNTER_REGISTER 0xA8 -#define DS1621_SLOPE_REGISTER 0xA9 - -#define DS1621_CFG_1SHOT (1<<0) -#define DS1621_CFG_DONE (1<<7) - -enum { - DS1624_TYPE_DS1624, - DS1624_TYPE_DS1621 -}; - -#define DS1624_MAX_SENSORS 8 - -bool ds1624_init = false; - -struct { - float value; - uint8_t type; - int errcnt; - int misscnt; - bool valid; - char name[9]; -} ds1624_sns[DS1624_MAX_SENSORS]; - -uint32_t DS1624_Idx2Addr(uint32_t idx) { - return 0x48 + idx; -} - -int DS1624_Restart(uint8_t config, uint32_t idx) { - uint32_t addr = DS1624_Idx2Addr(idx); - if ((config & 1) == 1) { - config &= ~(DS1621_CFG_DONE|DS1621_CFG_1SHOT); - I2cWrite8(addr, DS1624_CONF_REGISTER, config); - delay(10); - AddLog_P2(LOG_LEVEL_ERROR, "%s addr %x is reset, reconfig: %x", ds1624_sns[idx].name, addr, config); - } - I2cValidRead(addr, DS1624_START_REGISTER, 1); -} - -void DS1624_HotPlugUp(uint32_t idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - - if (I2cActive(addr)) { return; } - if (!I2cSetDevice(addr)) { return; } - - uint8_t config; - if (I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { - uint8_t tmp; - ds1624_sns[idx].type = (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) ? DS1624_TYPE_DS1624 : DS1624_TYPE_DS1621; - - snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS162%c%c%d"), - (ds1624_sns[idx].type == DS1624_TYPE_DS1621) ? '1' : '4', IndexSeparator(), idx); - I2cSetActiveFound(addr, ds1624_sns[idx].name); - - ds1624_sns[idx].valid = true; - ds1624_sns[idx].errcnt = 0; - ds1624_sns[idx].misscnt = 0; - DS1624_Restart(config,idx); - AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); - } -} - -void DS1624_HotPlugDown(int idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - if (!I2cActive(addr)) { return; } - I2cResetActive(addr); - ds1624_sns[idx].valid = false; - AddLog_P2(LOG_LEVEL_INFO, "Hot UnPlug %s", ds1624_sns[idx].name); -} - -bool DS1624GetTemp(float *value, int idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - - uint8_t config; - if (!I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { - ds1624_sns[idx].misscnt++; - AddLog_P2(LOG_LEVEL_INFO, "%s device missing (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].misscnt); - return false; - } - ds1624_sns[idx].misscnt=0; - if (config & (DS1621_CFG_1SHOT|DS1621_CFG_DONE)) { - ds1624_sns[idx].errcnt++; - AddLog_P2(LOG_LEVEL_INFO, "%s config error, restart... (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].errcnt); - DS1624_Restart(config, idx); - return false; - } - - uint16_t t; - if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { return false; } - if (ds1624_sns[idx].type == DS1624_TYPE_DS1624) { - *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; - } else { - - *value = ((float)(int8_t)(t>>8)); - uint8_t remain; - if (!I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)) { return true; } - uint8_t perc; - if (!I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)) { return true; } - float fix=(float)(perc - remain)/(float)perc; - *value+=fix; - } - ds1624_sns[idx].errcnt=0; - config &= ~(DS1621_CFG_DONE); - I2cWrite8(addr, DS1624_CONF_REGISTER, config); - return true; -} - -void DS1624HotPlugScan(void) -{ - uint16_t t; - - for (uint32_t idx = 0; idx < DS1624_MAX_SENSORS; idx++) { - uint32_t addr = DS1624_Idx2Addr(idx); - if (I2cActive(addr) && !ds1624_sns[idx].valid) { - continue; - } - if (ds1624_sns[idx].valid) { - if ((ds1624_sns[idx].misscnt>2)||(ds1624_sns[idx].errcnt>2)) { - DS1624_HotPlugDown(idx); - continue; - } - } - DS1624_HotPlugUp(idx); - } -} - -void DS1624EverySecond(void) -{ - float t; - for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { - if (!ds1624_sns[i].valid) { continue; } - if (!DS1624GetTemp(&t, i)) { continue; } - ds1624_sns[i].value = ConvertTemp(t); - } -} - -void DS1624Show(bool json) -{ - char temperature[33]; - bool once = true; - - for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { - if (!ds1624_sns[i].valid) { continue; } - - dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds1624_sns[i].name, temperature); - if ((0 == tele_period) && once) { -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, temperature); -#endif - once = false; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, ds1624_sns[i].name, temperature, TempUnit()); -#endif - } - } -} - - - - - -bool Xsns59(uint8_t function) -{ - if (!I2cEnabled(XI2C_42)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - if (!ds1624_init) { - memset(ds1624_sns, 0, sizeof(ds1624_sns)); - ds1624_init = true; - DS1624HotPlugScan(); - } - } - switch (function) { - case FUNC_HOTPLUG_SCAN: - DS1624HotPlugScan(); - break; - case FUNC_EVERY_SECOND: - DS1624EverySecond(); - break; - case FUNC_JSON_APPEND: - DS1624Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DS1624Show(0); - break; -#endif - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_60_GPS.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_60_GPS.ino" -#ifdef USE_GPS -# 113 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_60_GPS.ino" -#define XSNS_60 60 - -#include "NTPServer.h" -#include "NTPPacket.h" - - - - - -#define D_CMND_UBX "UBX" - -const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; - -const char kUBXTypes[] PROGMEM = "UBX"; - -#define UBX_LAT_LON_THRESHOLD 1000 - -#define UBX_SERIAL_BUFFER_SIZE 256 -#define UBX_TCP_PORT 1234 - - - - - -const char UBLOX_INIT[] PROGMEM = { - - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, - - - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, - - - - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, - - - - - - -}; - -char UBX_name[4]; - -struct UBX_t { - const char UBX_HEADER[2] = { 0xB5, 0x62 }; - const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; - const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; - const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; - - struct entry_t { - int32_t lat; - int32_t lon; - uint32_t time; - }; - - union { - entry_t values; - uint8_t bytes[sizeof(entry_t)]; - } rec_buffer; - - struct POLL_MSG { - uint8_t cls; - uint8_t id; - uint16_t zero; - }; - - struct NAV_POSLLH { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - int32_t lon; - int32_t lat; - int32_t alt; - int32_t hMSL; - uint32_t hAcc; - uint32_t vAcc; - }; - - struct NAV_STATUS { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - uint8_t gpsFix; - uint8_t flags; - uint8_t fixStat; - uint8_t flags2; - uint32_t ttff; - uint32_t msss; - }; - - struct NAV_TIME_UTC { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - uint32_t tAcc; - int32_t nano; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; - struct { - uint8_t UTC:1; - uint8_t WKN:1; - uint8_t TOW:1; - uint8_t padding:5; - } valid; - }; - - struct CFG_RATE { - uint8_t cls; - uint8_t id; - uint16_t len; - uint16_t measRate; - uint16_t navRate; - uint16_t timeRef; - char CK[2]; - }; - - struct { - uint32_t last_iTOW; - int32_t last_alt; - uint32_t last_hAcc; - uint32_t last_vAcc; - uint8_t gpsFix; - uint8_t non_empty_loops; - uint16_t log_interval; - } state; - - struct { - uint32_t init:1; - uint32_t filter_noise:1; - uint32_t send_when_new:1; - uint32_t send_UI_only:1; - uint32_t runningNTP:1; - uint32_t forceUTCupdate:1; - uint32_t runningVPort:1; - - } mode; - - union { - NAV_POSLLH navPosllh; - NAV_STATUS navStatus; - NAV_TIME_UTC navTime; - POLL_MSG pollMsg; - CFG_RATE cfgRate; - } Message; - - uint8_t TCPbuf[UBX_SERIAL_BUFFER_SIZE]; - size_t TCPbufSize; -} UBX; - -enum UBXMsgType { - MT_NONE, - MT_NAV_POSLLH, - MT_NAV_STATUS, - MT_NAV_TIME, - MT_POLL -}; - -#ifdef USE_FLOG -FLOG *Flog = nullptr; -#endif -TasmotaSerial *UBXSerial; - -NtpServer timeServer(PortUdp); - -WiFiServer vPortServer(UBX_TCP_PORT); -WiFiClient vPortClient; - - - - - -void UBXcalcChecksum(char* CK, size_t msgSize) -{ - memset(CK, 0, 2); - for (int i = 0; i < msgSize; i++) { - CK[0] += ((char*)(&UBX.Message))[i]; - CK[1] += CK[0]; - } -} - -bool UBXcompareMsgHeader(const char* msgHeader) -{ - char* ptr = (char*)(&UBX.Message); - return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; -} - -void UBXinitCFG(void) -{ - for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { - UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); - } - DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); -} - -void UBXTriggerTele(void) -{ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#ifdef USE_RULES - RulesTeleperiod(); -#endif - } -} - - - -void UBXDetect(void) -{ - UBX.mode.init = 0; - if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { - UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, UBX_SERIAL_BUFFER_SIZE); - if (UBXSerial->begin(9600)) { - DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); - if (UBXSerial->hardwareSerial()) { - ClaimSerial(); - DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); - } - } - } - else { - return; - } - - UBXinitCFG(); - UBX.mode.init = 1; - -#ifdef USE_FLOG - if (!Flog) { - Flog = new FLOG; - Flog->init(); - } -#endif - - UBX.state.log_interval = 10; - UBX.mode.send_UI_only = true; - UBXTriggerTele(); -} - -uint32_t UBXprocessGPS() -{ - static uint32_t fpos = 0; - static char checksum[2]; - static uint8_t currentMsgType = MT_NONE; - static size_t payloadSize = sizeof(UBX.Message); - - - uint32_t data_bytes = 0; - while ( UBXSerial->available() ) { - data_bytes++; - byte c = UBXSerial->read(); - if (UBX.mode.runningVPort){ - UBX.TCPbuf[data_bytes-1] = c; - UBX.TCPbufSize = data_bytes; - } - if ( fpos < 2 ) { - - if ( c == UBX.UBX_HEADER[fpos] ) { - fpos++; - } else { - fpos = 0; - } - } else { - - - - - - if ( (fpos-2) < payloadSize ) { - ((char*)(&UBX.Message))[fpos-2] = c; - } - fpos++; - - if ( fpos == 4 ) { - - - if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { - currentMsgType = MT_NAV_POSLLH; - payloadSize = sizeof(UBX_t::NAV_POSLLH); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); - } - else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { - currentMsgType = MT_NAV_STATUS; - payloadSize = sizeof(UBX_t::NAV_STATUS); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); - } - else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { - currentMsgType = MT_NAV_TIME; - payloadSize = sizeof(UBX_t::NAV_TIME_UTC); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); - } - else { - - fpos = 0; - continue; - } - } - - if ( fpos == (payloadSize+2) ) { - - - UBXcalcChecksum(checksum, payloadSize); - } - else if ( fpos == (payloadSize+3) ) { - - - if ( c != checksum[0] ) { - - fpos = 0; - } - } - else if ( fpos == (payloadSize+4) ) { - - - fpos = 0; - if ( c == checksum[1] ) { - - return currentMsgType; - } - } - else if ( fpos > (payloadSize+4) ) { - - - fpos = 0; - } - } - } - - if (data_bytes!=0) { - UBX.state.non_empty_loops++; - DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); - } else { - UBX.state.non_empty_loops = 0; - } - return MT_NONE; -} - - - - - -#ifdef USE_FLOG -void UBXsendHeader(void) -{ - WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); - WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); - WSSend(200, CT_STREAM, F( - "\r\n" - "\r\n" - "\r\n\r\n")); -} - -void UBXsendRecord(uint8_t *buf) -{ - char record[100]; - char stime[32]; - UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; - snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); - char lat[12]; - char lon[12]; - dtostrfd((double)entry->lat/10000000.0f,7,lat); - dtostrfd((double)entry->lon/10000000.0f,7,lon); - snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); - - WebServer->sendContent_P(record); -} - -void UBXsendFooter(void) -{ - WebServer->sendContent(F("\n\n")); - WebServer->sendContent(""); - Rtc.user_time_entry = false; -} - - - -void UBXsendFile(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); -} -#endif - - - -void UBXSetRate(uint16_t interval) -{ - UBX.Message.cfgRate.cls = 0x06; - UBX.Message.cfgRate.id = 0x08; - UBX.Message.cfgRate.len = 6; - uint32_t measRate = (1000*(uint32_t)interval); - if (measRate > 0xffff) { - measRate = 0xffff; - } - UBX.Message.cfgRate.measRate = (uint16_t)measRate; - UBX.Message.cfgRate.navRate = 1; - UBX.Message.cfgRate.timeRef = 1; - UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); - DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); - UBXSerial->write(UBX.UBX_HEADER[0]); - UBXSerial->write(UBX.UBX_HEADER[1]); - for (uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); - DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); - } - UBX.state.log_interval = 10*interval; -} - -void UBXSelectMode(uint16_t mode) -{ - DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); - switch(mode){ -#ifdef USE_FLOG - case 0: - Flog->mode = 0; - break; - case 1: - Flog->mode = 1; - break; - case 2: - UBX.mode.filter_noise = true; - break; - case 3: - UBX.mode.filter_noise = false; - break; - case 4: - Flog->startRecording(true); - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); - break; - case 5: - Flog->startRecording(false); - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); - break; - case 6: - if(Flog->recording == true){ - Flog->stopRecording(); - } - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); - break; -#endif - case 7: - UBX.mode.send_when_new = 1; - break; - case 8: - UBX.mode.send_when_new = 0; - break; - case 9: - if (timeServer.beginListening()) { - UBX.mode.runningNTP = true; - } - break; - case 10: - UBX.mode.runningNTP = false; - break; - case 11: - UBX.mode.forceUTCupdate = true; - break; - case 12: - UBX.mode.forceUTCupdate = false; - break; - case 13: - Settings.latitude = UBX.rec_buffer.values.lat/10; - Settings.longitude = UBX.rec_buffer.values.lon/10; - break; - case 14: - vPortServer.begin(); - UBX.mode.runningVPort = 1; - break; - case 15: - - UBX.mode.runningVPort = 0; - break; - default: - if (mode>1000 && mode <1066) { - - UBXSetRate(mode-1000); - } - break; - } - UBX.mode.send_UI_only = true; - UBXTriggerTele(); -} - - - -bool UBXHandlePOSLLH() -{ - DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); - if (UBX.state.gpsFix>1) { - if (UBX.mode.filter_noise) { - if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat6) { - if(UBX.mode.runningVPort) return; - UBXinitCFG(); - AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); - UBXSerial->flush(); - UBX.state.non_empty_loops = 0; - } -} - - - -void UBXLoop50msec(void) -{ - - if (UBX.mode.runningVPort){ - if(!vPortClient.connected()) { - vPortClient = vPortServer.available(); - } - while(vPortClient.available()) { - byte _newByte = vPortClient.read(); - UBXSerial->write(_newByte); - } - - if (UBX.TCPbufSize!=0){ - vPortClient.write((char*)UBX.TCPbuf, UBX.TCPbufSize); - UBX.TCPbufSize = 0; - } - } - - if(UBX.mode.runningNTP){ - timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000); - } -} - -void UBXLoop(void) -{ - static uint16_t counter; - static bool new_position; - - uint32_t msgType = UBXprocessGPS(); - - switch(msgType){ - case MT_NAV_POSLLH: - new_position = UBXHandlePOSLLH(); - break; - case MT_NAV_STATUS: - UBXHandleSTATUS(); - break; - case MT_NAV_TIME: - UBXHandleTIME(); - break; - default: - UBXHandleOther(); - break; - } - -#ifdef USE_FLOG - if (counter>UBX.state.log_interval) { - if (Flog->recording && new_position) { - UBX.rec_buffer.values.time = Rtc.local_time; - Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); - counter = 0; - } - } -#endif - - counter++; -} - - - - -#ifdef USE_WEBSERVER - - -#ifdef USE_FLOG -#ifdef DEBUG_TASMOTA_SENSOR - const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" - "{s} FLOG next sector for REC: {m} %u {e}" - "{s} %u sector(s) with data at sector: {m} %u {e}"; - const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; -#endif - - const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; - const char kFLOG_STATE0[] PROGMEM = "ready"; - const char kFLOG_STATE1[] PROGMEM = "recording"; - const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; - - const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; - -#endif - const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; - - const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" - "{s} GPS longitude {m}%s{e}" - "{s} GPS altitude {m}%s m{e}" - "{s} GPS hor. Accuracy {m}%s m{e}" - "{s} GPS vert. Accuracy {m}%s m{e}" - "{s} GPS sat-fix status {m}%s{e}"; - - const char kGPSFix0[] PROGMEM = "no fix"; - const char kGPSFix1[] PROGMEM = "dead reckoning only"; - const char kGPSFix2[] PROGMEM = "2D-fix"; - const char kGPSFix3[] PROGMEM = "3D-fix"; - const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; - const char kGPSFix5[] PROGMEM = "Time only fix"; - const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; - - - - -#endif - - - -void UBXShow(bool json) -{ - char lat[12]; - char lon[12]; - char alt[12]; - char hAcc[12]; - char vAcc[12]; - dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); - dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); - dtostrfd((double)UBX.state.last_alt/1000.0f,3,alt); - dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); - dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); - - if (json) { - ResponseAppend_P(PSTR(",\"GPS\":{")); - if (UBX.mode.send_UI_only) { - uint32_t i = UBX.state.log_interval / 10; - ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); - } else { - ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"alt\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, alt, hAcc, vAcc); - } -#ifdef USE_FLOG - ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); -#endif - UBX.mode.send_UI_only = false; -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_GPS, lat, lon, alt, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); - -#ifdef DEBUG_TASMOTA_SENSOR -#ifdef USE_FLOG - WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); - if (Flog->recording) { - WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); - } -#endif -#endif -#ifdef USE_FLOG - if (Flog->ready) { - WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); - } - if (!Flog->recording && Flog->found_saved_data) { - WSContentSend_P(HTTP_BTN_FLOG_DL); - } -#endif - if (UBX.mode.runningNTP) { - WSContentSend_P(HTTP_SNS_NTPSERVER); - } -#endif - } -} - - - - - -bool UBXCmd(void) -{ - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - UBXSelectMode(XdrvMailbox.payload); - Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); - } - return serviced; -} - - - - - -bool Xsns60(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - UBXDetect(); - } - - if (UBX.mode.init) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_60 == XdrvMailbox.index) { - result = UBXCmd(); - } - break; - case FUNC_EVERY_50_MSECOND: - UBXLoop50msec(); - break; - case FUNC_EVERY_100_MSECOND: -#ifdef USE_FLOG - if (!Flog->running_download) -#endif - { - UBXLoop(); - } - break; -#ifdef USE_FLOG - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/UBX", UBXsendFile); - break; -#endif - case FUNC_JSON_APPEND: - UBXShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: -#ifdef USE_FLOG - if (!Flog->running_download) -#endif - { - UBXShow(0); - } - break; -#endif - } - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -# 35 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -#ifdef USE_SPI -#ifdef USE_NRF24 -#ifdef USE_MIBLE - -#ifdef DEBUG_TASMOTA_SENSOR - #define MINRF_LOG_BUFFER(x) MINRFshowBuffer(x); -#else - #define MINRF_LOG_BUFFER(x) -#endif -# 53 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -#define XSNS_61 61 - -#include - -#define FLORA 1 -#define MJ_HT_V1 2 -#define LYWSD02 3 -#define LYWSD03 4 - -uint8_t kMINRFSlaveID[4][3] = { 0xC4,0x7C,0x8D, - 0x58,0x2D,0x34, - 0xE7,0x2E,0x00, - 0xA4,0xC1,0x38, - }; - -const char kMINRFSlaveType1[] PROGMEM = "Flora"; -const char kMINRFSlaveType2[] PROGMEM = "MJ_HT_V1"; -const char kMINRFSlaveType3[] PROGMEM = "LYWSD02"; -const char kMINRFSlaveType4[] PROGMEM = "LYWSD03"; -const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4}; - - -const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; -const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; -const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71da7646}; - -const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; - - -const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; -const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; - - -#pragma pack(1) -struct MJ_HT_V1Header_t { - uint8_t padding[3]; - uint8_t mesSize; - uint8_t padding2; - uint16_t uuid; - uint16_t type; - uint8_t padding3[2]; - uint8_t counter; - uint8_t serial[6]; - uint8_t mode; - uint8_t padding5; - uint8_t effectiveDataLength; - }; - -struct FlowerHeader_t { - uint8_t padding[4]; - uint8_t padding2; - uint16_t uuid; - uint8_t mesSize; - uint8_t padding22; - uint16_t uuid2; - uint16_t type; - uint8_t padding3[2]; - uint8_t counter; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - }; - -union floraPacket_t { - struct { - uint16_t idWord; - uint8_t padding; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint16_t data; - } T; - struct { - uint16_t idWord; - uint8_t padding; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint32_t data:24; - } L; - struct { - uint8_t padding[3]; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint8_t data; - } M; - struct { - uint8_t padding[3]; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint16_t data; - } F; -}; - -union MJ_HT_V1Packet_t { - struct { - uint16_t idWord; - uint8_t padding; - uint8_t serial[6]; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint16_t temp; - uint16_t hum; - } TH; - struct { - uint8_t padding[3]; - uint8_t serial[6]; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint8_t battery; - } B; - -}; - -union LYWSD02Packet_t { - struct { - uint16_t idWord; - uint8_t padding; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint16_t data; - } TH; -}; - -struct bleAdvPacket_t { - uint8_t pduType; - uint8_t payloadSize; - uint8_t mac[6]; - union { - uint8_t payload[24]; - MJ_HT_V1Header_t header; - FlowerHeader_t flowerHeader; - struct { - uint8_t padding[21]; - uint16_t temp; - uint8_t hum_lb; - } TH; - struct { - uint8_t padding[21]; - uint16_t temp; - } T; - struct { - uint8_t padding[21]; - uint16_t hum; - } H; - struct { - uint8_t padding[21]; - uint8_t battery; - } B; - struct { - uint8_t padding[2]; - uint8_t mode; - uint16_t size; - uint16_t data; - } F_T; - struct { - uint8_t padding[2]; - uint8_t mode; - uint16_t size; - uint16_t data; - uint8_t data2; - } F_L; - struct { - uint8_t padding[2]; - uint8_t mode; - uint16_t size; - uint8_t data; - } F_M; - struct { - uint8_t padding[2]; - uint8_t mode; - uint16_t size; - uint16_t data; - } F_F; - }; -}; - -union FIFO_t{ - bleAdvPacket_t bleAdv; - floraPacket_t floraPacket; - MJ_HT_V1Packet_t MJ_HT_V1Packet; - LYWSD02Packet_t LYWSD02Packet; - uint8_t raw[32]; -}; - -#pragma pack(0) - -struct { - const uint8_t channel[3] = {37,38,39}; - const uint8_t frequency[3] = { 2,26,80}; - - uint16_t timer; - uint8_t currentChan=0; - FIFO_t buffer; - uint8_t packetMode; - -#ifdef DEBUG_TASMOTA_SENSOR - uint8_t streamBuffer[sizeof(buffer)]; - uint8_t lsfrBuffer[sizeof(buffer)]; -#endif - -} MINRF; - -struct mi_sensor_t{ - uint8_t type; - uint8_t serial[6]; - uint8_t showedUp; - float temp; - union { - struct { - float moisture; - float fertility; - uint32_t lux; - }; - struct { - float hum; - uint8_t bat; - }; - }; -}; - -std::vector MIBLEsensors; - - - - -bool MINRFinitBLE(uint8_t _mode) -{ - if (MINRF.timer%1000 == 0){ - NRF24radio.begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_DC]); - NRF24radio.setAutoAck(false); - NRF24radio.setDataRate(RF24_1MBPS); - NRF24radio.disableCRC(); - NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); - NRF24radio.setRetries(0,0); - NRF24radio.setPALevel(RF24_PA_MIN); - NRF24radio.setAddressWidth(4); - - - NRF24radio.powerUp(); - } - if(NRF24radio.isChipConnected()){ - - MINRFchangePacketModeTo(_mode); - return true; - } - - return false; -} - -void MINRFhopChannel() -{ - MINRF.currentChan++; - if(MINRF.currentChan >= sizeof(MINRF.channel)) { - MINRF.currentChan = 0; - } - NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); -} - - - - - - - -bool MINRFreceivePacket(void) -{ - if(!NRF24radio.available()) { - return false; - } - while(NRF24radio.available()) { - - - NRF24radio.read( &MINRF.buffer, sizeof(MINRF.buffer) ); -#ifdef DEBUG_TASMOTA_SENSOR - memcpy(&MINRF.streamBuffer, &MINRF.buffer, sizeof(MINRF.buffer)); -#endif - MINRFswapbuf( sizeof(MINRF.buffer) ); - - - - switch (MINRF.packetMode) { - case 0: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); - break; - case 1: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); - break; - case 2: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); - break; - case 3: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); - break; - case 4: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); - break; - } - - - } - - return true; -} - -#ifdef DEBUG_TASMOTA_SENSOR -void MINRFshowBuffer(uint8_t (&buf)[32]){ - - - - - DEBUG_SENSOR_LOG(PSTR("MINRF: Buffer: %02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x ") - ,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11], - buf[12],buf[13],buf[14],buf[15],buf[16],buf[17],buf[18],buf[19],buf[20],buf[21],buf[22],buf[23], - buf[24],buf[25],buf[26],buf[27],buf[28],buf[29],buf[30],buf[31] - ); -} -#endif - - - - - - -void MINRFswapbuf(uint8_t len) -{ - uint8_t* buf = (uint8_t*)&MINRF.buffer; - while(len--) { - uint8_t a = *buf; - uint8_t v = 0; - if (a & 0x80) v |= 0x01; - if (a & 0x40) v |= 0x02; - if (a & 0x20) v |= 0x04; - if (a & 0x10) v |= 0x08; - if (a & 0x08) v |= 0x10; - if (a & 0x04) v |= 0x20; - if (a & 0x02) v |= 0x40; - if (a & 0x01) v |= 0x80; - *(buf++) = v; - } -} -# 420 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr) -{ - while(len--) { - uint8_t res = 0; - - for (uint8_t i = 1; i; i <<= 1) { - if (lfsr & 0x01) { - lfsr ^= 0x88; - res |= i; - } - lfsr >>= 1; - } - *(buf++) ^= res; -#ifdef DEBUG_TASMOTA_SENSOR - MINRF.lsfrBuffer[31-len] = lfsr; -#endif - } -} - -void MINRFreverseMAC(uint8_t _mac[]){ - uint8_t _reversedMAC[6]; - for (uint8_t i=0; i<6; i++){ - _reversedMAC[5-i] = _mac[i]; - } - memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); -} - - - - - - -void MINRFchangePacketModeTo(uint8_t _mode) { - uint32_t (_nextchannel) = MINRF.currentChan+1; - if (_nextchannel>2) _nextchannel=0; - - switch(_mode){ - case 0: - NRF24radio.openReadingPipe(0,0x6B7D9171); - break; - case 1: - NRF24radio.openReadingPipe(0,kMINRFFloPDU[_nextchannel]); - break; - case 2: - NRF24radio.openReadingPipe(0,kMINRFMJPDU[_nextchannel]); - break; - case 3: - NRF24radio.openReadingPipe(0,kMINRFL2PDU[_nextchannel]); - break; - case 4: - if(kMINRFL3PDU[_nextchannel]==0xffffffff) break; - NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]); - break; - } - - MINRF.packetMode = _mode; -} -# 485 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ - if(_type==0xff){ - DEBUG_SENSOR_LOG(PSTR("MINRF: will test MAC-type")); - for (uint32_t i=0;i<4;i++){ - if(memcmp(_serial,kMINRFSlaveID+i,3)==0){ - DEBUG_SENSOR_LOG(PSTR("MINRF: MAC is type %u"), i); - _type = i+1; - } - else { - DEBUG_SENSOR_LOG(PSTR("MINRF: MAC-type is unknown")); - } - } - } - if(_type==0xff) return _type; - - DEBUG_SENSOR_LOG(PSTR("MINRF: vector size %u"), MIBLEsensors.size()); - for(uint32_t i=0; i6000){ - DEBUG_SENSOR_LOG(PSTR("MINRF: check for FAKE sensors")); - MINRFpurgeFakeSensors(); - MINRF.timer=0; - } - MINRF.timer++; - - if (!MINRFreceivePacket()){ - - } - - else if(MINRF.buffer.bleAdv.header.uuid==0xfe95){ - MINRF_LOG_BUFFER(MINRF.streamBuffer); - MINRF_LOG_BUFFER(MINRF.lsfrBuffer); - MINRF_LOG_BUFFER(MINRF.buffer.raw); - DEBUG_SENSOR_LOG(PSTR("MINRF: Type: %x"), MINRF.buffer.bleAdv.header.type); - switch(MINRF.buffer.bleAdv.header.type){ - case 0x2050: - DEBUG_SENSOR_LOG(PSTR("MINRF: MJ_HT_V1 Packet")); - break; - case 0x1613:case 0x1614:case 0x1615: - DEBUG_SENSOR_LOG(PSTR("MINRF: Flora Packet")); - break; - default: - DEBUG_SENSOR_LOG(PSTR("MINRF: unknown Packet")); - break; - } - } - else if (MINRF.packetMode == FLORA){ - MINRFhandleFloraPacket(); - } - else if (MINRF.packetMode == MJ_HT_V1){ - MINRFhandleMJ_HT_V1Packet(); - } - else if (MINRF.packetMode == LYWSD02){ - MINRFhandleLYWSD02Packet(); - } - else if (MINRF.packetMode == LYWSD03){ - MINRFhandleLYWSD03Packet(); - } - - - if (MINRF.packetMode == LYWSD03){ - MINRFinitBLE(1); - } - else { - MINRFinitBLE(++MINRF.packetMode); - } - - MINRFhopChannel(); - NRF24radio.startListening(); -} - - - - -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; -const char HTTP_MINRF_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; -const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; -const char HTTP_MINRF_HL[] PROGMEM = "{s}
{m}
{e}"; - -void MINRFShow(bool json) -{ - if (json) { - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - if(MIBLEsensors.at(i).showedUp < 3){ - DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet")); - break; - } - char slave[33]; - sprintf_P(slave,"%s-%02x%02x%02x",kMINRFSlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - - ResponseAppend_P(PSTR(",\"%s\":{"),slave); - if(MIBLEsensors.at(i).temp!=-1000.0f){ - ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); - } - if (MIBLEsensors.at(i).type==FLORA){ - char lux[33]; - char moisture[33]; - char fertility[33]; - dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); - dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); - dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - if(MIBLEsensors.at(i).lux!=0xffff){ - ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); - } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ - ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); - } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ - ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); - } - } - if (MIBLEsensors.at(i).type>FLORA){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - if(MIBLEsensors.at(i).hum!=-1.0f){ - ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - } - if(MIBLEsensors.at(i).bat!=0xff){ - ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); - } - } - ResponseAppend_P(PSTR("}")); - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_NRF24, NRF24type, NRF24.chipType); - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - if(MIBLEsensors.at(i).showedUp < 3){ - DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet")); - break; - } - WSContentSend_PD(HTTP_MINRF_HL); - WSContentSend_PD(HTTP_MINRF_MAC, kMINRFSlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - if(MIBLEsensors.at(i).temp!=-1000.0f){ - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - WSContentSend_PD(HTTP_SNS_TEMP, kMINRFSlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); - } - if (MIBLEsensors.at(i).type==FLORA){ - if(MIBLEsensors.at(i).lux!=0x00ffffff){ - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); - } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ - WSContentSend_PD(HTTP_SNS_MOISTURE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); - } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ - char fertility[33]; - dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - WSContentSend_PD(HTTP_MINRF_FLORA_DATA, kMINRFSlaveType[MIBLEsensors.at(i).type-1], fertility); - } - } - if (MIBLEsensors.at(i).type>FLORA){ - if(MIBLEsensors.at(i).hum!=-1.0f){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - WSContentSend_PD(HTTP_SNS_HUM, kMINRFSlaveType[MIBLEsensors.at(i).type-1], humidity); - } - if(MIBLEsensors.at(i).bat!=0xff){ - WSContentSend_PD(HTTP_BATTERY, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); - } - } - } -#endif - } -} - - - - - -bool Xsns61(uint8_t function) -{ - bool result = false; - - if (NRF24.chipType) { - switch (function) { - case FUNC_INIT: - MINRFinitBLE(1); - AddLog_P2(LOG_LEVEL_INFO,PSTR("MINRF: started")); - break; - case FUNC_EVERY_50_MSECOND: - MINRF_EVERY_50_MSECOND(); - break; - case FUNC_JSON_APPEND: - MINRFShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MINRFShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_62_MI_HM10.ino" -# 30 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_62_MI_HM10.ino" -#ifdef USE_HM10 - -#define XSNS_62 62 - -#include -#include - -TasmotaSerial *HM10Serial; -#define HM10_BAUDRATE 115200 - -#define HM10_MAX_TASK_NUMBER 12 -uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; - -#define HM10_MAX_RX_BUF 512 -char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; - -struct { - uint8_t current_task_delay; - uint8_t last_command; - uint16_t firmware; - uint32_t period; - uint32_t serialSpeed; - union { - uint32_t time; - uint8_t timebuf[4]; - }; - struct { - uint32_t init:1; - uint32_t pending_task:1; - uint32_t connected:1; - uint32_t subscribed:1; - uint32_t awaitingHT:1; - uint32_t awaitingB:1; - - } mode; - struct { - uint8_t sensor; - - } state; -} HM10; - -#pragma pack(1) -struct { - uint16_t temp; - uint8_t hum; -} LYWSD0x_HT; -#pragma pack(0) - -struct mi_sensor_t{ - uint8_t type; - uint8_t serial[6]; - uint8_t showedUp; - float temp; - union { - struct { - float moisture; - float fertility; - uint16_t lux; - }; - struct { - float hum; - uint8_t bat; - }; - }; -}; - -std::vector MIBLEsensors; - - - - - -#define D_CMND_HM10 "HM10" - -const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; -const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}"; -const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time"; - -#define FLORA 1 -#define MJ_HT_V1 2 -#define LYWSD02 3 -#define LYWSD03MMC 4 - -uint8_t kHM10SlaveID[4][3] = { 0xC4,0x7C,0x8D, - 0x58,0x2D,0x34, - 0xE7,0x2E,0x00, - 0xA4,0xC1,0x38, - }; - -const char kHM10SlaveType1[] PROGMEM = "Flora"; -const char kHM10SlaveType2[] PROGMEM = "MJ_HT_V1"; -const char kHM10SlaveType3[] PROGMEM = "LYWSD02"; -const char kHM10SlaveType4[] PROGMEM = "LYWSD03"; -const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4}; - - - - - -enum HM10_Commands { - CMND_HM10_DISC_SCAN, - CMND_HM10_AT, - CMND_HM10_PERIOD, - CMND_HM10_BAUD, - CMND_HM10_TIME - }; - - - - - -#define TASK_HM10_NOTASK 0 -#define TASK_HM10_ROLE1 1 -#define TASK_HM10_IMME1 2 -#define TASK_HM10_RENEW 3 -#define TASK_HM10_RESET 4 -#define TASK_HM10_DISC 5 -#define TASK_HM10_CONN 6 -#define TASK_HM10_VERSION 7 -#define TASK_HM10_NAME 8 -#define TASK_HM10_FEEDBACK 9 -#define TASK_HM10_DISCONN 10 -#define TASK_HM10_SUB_L3 11 -#define TASK_HM10_READ_HT 12 -#define TASK_HM10_FINDALLCHARS 13 -#define TASK_HM10_UN_L3 14 -#define TASK_HM10_DELAY_SUB 15 -#define TASK_HM10_READ_BT_L3 16 -#define TASK_HM10_SUB_L2 17 -#define TASK_HM10_UN_L2 18 -#define TASK_HM10_READ_BT_L2 19 -#define TASK_HM10_TIME_L2 20 - -#define TASK_HM10_DONE 99 - - - - - -void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){ - HM10_TASK_LIST[slot][0] = task; - HM10_TASK_LIST[slot][1] = delay; - HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; - HM10.current_task_delay = HM10_TASK_LIST[0][1]; -} - -void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ - HM10.last_command = HM10_TASK_LIST[slot][0]; - HM10_TASK_LIST[slot][0] = task; -} - - - - - -void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); - HM10_Launchtask(TASK_HM10_ROLE1,1,1); - HM10_Launchtask(TASK_HM10_IMME1,2,1); - HM10_Launchtask(TASK_HM10_RESET,3,1); - HM10_Launchtask(TASK_HM10_VERSION,4,10); - HM10_Launchtask(TASK_HM10_DISC,5,50); - } - -void HM10_Discovery_Scan(void) { - HM10_Launchtask(TASK_HM10_DISCONN,0,1); - HM10_Launchtask(TASK_HM10_DISC,1,1); - } - -void HM10_Read_LYWSD03(void) { - HM10_Launchtask(TASK_HM10_CONN,0,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); - HM10_Launchtask(TASK_HM10_SUB_L3,2,20); - HM10_Launchtask(TASK_HM10_UN_L3,3,80); - HM10_Launchtask(TASK_HM10_READ_BT_L3,4,5); - HM10_Launchtask(TASK_HM10_DISCONN,5,5); - } - -void HM10_Read_LYWSD02(void) { - HM10_Launchtask(TASK_HM10_CONN,0,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); - HM10_Launchtask(TASK_HM10_SUB_L2,2,20); - HM10_Launchtask(TASK_HM10_UN_L2,3,80); - HM10_Launchtask(TASK_HM10_READ_BT_L2,4,5); - HM10_Launchtask(TASK_HM10_DISCONN,5,5); - } - -void HM10_Time_LYWSD02(void) { - HM10_Launchtask(TASK_HM10_DISCONN,0,0); - HM10_Launchtask(TASK_HM10_CONN,1,5); - HM10_Launchtask(TASK_HM10_FEEDBACK,2,35); - HM10_Launchtask(TASK_HM10_TIME_L2,3,20); - HM10_Launchtask(TASK_HM10_DISCONN,4,5); - } -# 231 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_62_MI_HM10.ino" -uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ - if(_type==0xff){ - DEBUG_SENSOR_LOG(PSTR("MIBLE: will test MAC-type")); - for (uint32_t i=0;i<4;i++){ - if(memcmp(_serial,kHM10SlaveID+i,3)==0){ - DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC is type %u"), i); - _type = i+1; - } - else { - DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC-type is unknown")); - } - } - } - if(_type==0xff) return _type; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: vector size %u"), MIBLEsensors.size()); - for(uint32_t i=0; ibegin(HM10.serialSpeed)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start serial communication fixed to 115200 baud"),D_CMND_HM10); - if (HM10Serial->hardwareSerial()) { - ClaimSerial(); - DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); - } - HM10_Reset(); - HM10.mode.pending_task = 1; - HM10.mode.init = 1; - HM10.period = Settings.tele_period; - DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); - } - return; -} -# 315 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_62_MI_HM10.ino" -void HM10MACStringToBytes(const char* string, uint8_t _mac[]) { - uint32_t index = 0; - while (index < 12) { - char c = string[index]; - uint32_t value = 0; - if(c >= '0' && c <= '9') - value = (c - '0'); - else if (c >= 'A' && c <= 'F') - value = (10 + (c - 'A')); - _mac[(index/2)] += value << (((index + 1) % 2) * 4); - - index++; - } - DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_mac[0],_mac[1],_mac[2],_mac[3],_mac[4],_mac[5]); -} - - - - - - -void HM10ParseResponse(char *buf) { - if (!strncmp(buf,"OK",2)) { - DEBUG_SENSOR_LOG(PSTR("HM10: got OK")); - } - if (!strncmp(buf,"HMSoft",6)) { - const char* _fw = "000"; - memcpy((void *)_fw,(void *)(buf+8),3); - HM10.firmware = atoi(_fw); - DEBUG_SENSOR_LOG(PSTR("HM10: Firmware: %d"), HM10.firmware); - return; - } - char * _pos = strstr(buf, "IS0:"); - if(_pos) { - const char* _mac = "000000000000"; - memcpy((void *)_mac,(void *)(_pos+4),12); - DEBUG_SENSOR_LOG(PSTR("HM10: found Mac: %s"), _mac); - uint8_t _newMacArray[6] = {0}; - HM10MACStringToBytes(_mac, _newMacArray); - DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); - MIBLEgetSensorSlot(_newMacArray, 0xff); - } - if (strstr(buf, "LOST")){ - HM10.mode.connected = false; - } - else { - DEBUG_SENSOR_LOG(PSTR("HM10: empty response")); - } -} - -void HM10readTempHum(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0] != 0 && _buf[1] != 0){ - memcpy(&LYWSD0x_HT,(void *)_buf,3); - DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD0x_HT.temp,LYWSD0x_HT.hum); - uint32_t _slot = HM10.state.sensor; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - static float _tempFloat; - _tempFloat=(float)(LYWSD0x_HT.temp)/100.0f; - if(_tempFloat<60){ - MIBLEsensors.at(_slot).temp=_tempFloat; - HM10.mode.awaitingHT = false; - HM10.current_task_delay = 0; - } - _tempFloat=(float)LYWSD0x_HT.hum; - if(_tempFloat<100){ - MIBLEsensors.at(_slot).hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("LYWSD03: hum updated")); - } - } -} - -bool HM10readBat(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0] != 0){ - DEBUG_SENSOR_LOG(PSTR("HM10: Battery: %u"),_buf[0]); - uint32_t _slot = HM10.state.sensor; - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - if(_buf[0]<101){ - MIBLEsensors.at(_slot).bat=_buf[0]; - return true; - } - } - return false; -} - - - - - -bool HM10SerialHandleFeedback(){ - bool success = false; - uint32_t i = 0; - char ret[HM10_MAX_RX_BUF] = {0}; - - - while(HM10Serial->available()) { - - if(iread(); - } - i++; - success = true; - } - if(HM10.mode.awaitingHT) { - if (HM10.mode.connected) HM10readTempHum(ret); - } - else if(HM10.mode.awaitingB) { - if (HM10.mode.connected) { - if (HM10readBat(ret)){ - HM10.mode.awaitingB = false; - HM10.current_task_delay = 0; - } - } - } - else if(success) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s response: %s"),D_CMND_HM10, (char *)ret); - HM10ParseResponse(ret); - } - else { - - } - return success; -} - - - - - -void HM10_TaskEvery100ms(){ - if (HM10.current_task_delay == 0) { - uint8_t i = 0; - bool runningTaskLoop = true; - while (runningTaskLoop) { - switch(HM10_TASK_LIST[i][0]) { - case TASK_HM10_ROLE1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+ROLE1"); - break; - case TASK_HM10_IMME1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set imme to 1"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+IMME1"); - break; - case TASK_HM10_DISC: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start discovery"),D_CMND_HM10); - HM10.current_task_delay = 35; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+DISC?"); - break; - case TASK_HM10_VERSION: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read version"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+VERR?"); - break; - case TASK_HM10_NAME: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read name"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+NAME?"); - break; - case TASK_HM10_CONN: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s connect"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - char _con[20]; - sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors.at(HM10.state.sensor).serial[0],MIBLEsensors.at(HM10.state.sensor).serial[1],MIBLEsensors.at(HM10.state.sensor).serial[2],MIBLEsensors.at(HM10.state.sensor).serial[3],MIBLEsensors.at(HM10.state.sensor).serial[4],MIBLEsensors.at(HM10.state.sensor).serial[5]); - HM10Serial->write(_con); - HM10.mode.awaitingB = false; - HM10.mode.connected = true; - break; - case TASK_HM10_DISCONN: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s disconnect"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT"); - break; - case TASK_HM10_RESET: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10); - HM10Serial->write("AT+RESET"); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - break; - case TASK_HM10_SUB_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); - HM10.current_task_delay = 25; - HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); - runningTaskLoop = false; - HM10Serial->write("AT+NOTIFY_ON0037"); - break; - case TASK_HM10_UN_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaitingHT = false; - HM10Serial->write("AT+NOTIFYOFF0037"); - break; - case TASK_HM10_SUB_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); - HM10.current_task_delay = 25; - HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); - runningTaskLoop = false; - HM10Serial->write("AT+NOTIFY_ON003C"); - break; - case TASK_HM10_UN_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaitingHT = false; - HM10Serial->write("AT+NOTIFYOFF003C"); - break; - case TASK_HM10_TIME_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set time"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.time = Rtc.utc_time; - HM10Serial->write("AT+SEND_DATAWR002F"); - HM10Serial->write(HM10.timebuf,4); - HM10Serial->write(Rtc.time_timezone / 60); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60)); - break; - case TASK_HM10_READ_HT: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0036"),D_CMND_HM10); - HM10.current_task_delay = 0; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA0036?"); - HM10.mode.awaitingHT = true; - break; - case TASK_HM10_READ_BT_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 003A"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA003A?"); - HM10.mode.awaitingB = true; - break; - case TASK_HM10_READ_BT_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0043"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA0043?"); - HM10.mode.awaitingB = true; - break; - - - - - - - - case TASK_HM10_FEEDBACK: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10); - HM10SerialHandleFeedback(); - HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; - HM10_TASK_LIST[i][0] = TASK_HM10_DONE; - runningTaskLoop = false; - break; - case TASK_HM10_DELAY_SUB: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start reading"),D_CMND_HM10); - HM10SerialHandleFeedback(); - HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; - HM10_TASK_LIST[i][0] = TASK_HM10_DONE; - HM10.mode.awaitingHT = true; - runningTaskLoop = false; - break; - case TASK_HM10_DONE: - - - if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { - DEBUG_SENSOR_LOG(PSTR("%sno Tasks left"),D_CMND_HM10); - DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i); - for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { - DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j); - HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; - HM10_TASK_LIST[j][1] = 0; - } - runningTaskLoop = false; - HM10.mode.pending_task = 0; - break; - } - } - i++; - } - } - else { - HM10.current_task_delay--; - } -} - - - - - - -void HM10EverySecond(){ - if(HM10.firmware == 0) return; - if(HM10.mode.pending_task == 1) return; - if (MIBLEsensors.size()==0) return; - - static uint32_t _counter = 0; - static uint32_t _nextSensorSlot = 0; - if(_counter==0) { - HM10.state.sensor = _nextSensorSlot; - _nextSensorSlot++; - if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD03MMC) { - HM10.mode.pending_task = 1; - HM10_Read_LYWSD03(); - } - if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD02) { - HM10.mode.pending_task = 1; - HM10_Read_LYWSD02(); - } - if (HM10.state.sensor==MIBLEsensors.size()-1) { - _nextSensorSlot= 0; - _counter++; - } - DEBUG_SENSOR_LOG(PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); - } - else _counter++; - if (_counter>HM10.period) _counter = 0; -} - -bool HM10Cmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_HM10); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_HM10), disp_len)) { - uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kHM10_Commands); - switch (command_code) { - case CMND_HM10_PERIOD: - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_HM10_PERIOD) { HM10.period = XdrvMailbox.payload; } - } - else { - if (command_code == CMND_HM10_PERIOD) XdrvMailbox.payload = HM10.period; - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_BAUD: - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_HM10_BAUD) { - HM10.serialSpeed = XdrvMailbox.payload; - HM10Serial->begin(HM10.serialSpeed); - } - } - else { - if (command_code == CMND_HM10_BAUD) XdrvMailbox.payload = HM10.serialSpeed; - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_TIME: - if (XdrvMailbox.data_len > 0) { - if(MIBLEsensors.size()>XdrvMailbox.payload){ - if(MIBLEsensors.at(XdrvMailbox.payload).type == LYWSD02){ - HM10.state.sensor = XdrvMailbox.payload; - HM10_Time_LYWSD02(); - } - } - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_AT: - HM10Serial->write("AT"); - if (strlen(XdrvMailbox.data)!=0) { - HM10Serial->write("+"); - HM10Serial->write(XdrvMailbox.data); - Response_P(S_JSON_HM10_COMMAND, ":AT+",XdrvMailbox.data); - } - else Response_P(S_JSON_HM10_COMMAND, ":AT",XdrvMailbox.data); - break; - case CMND_HM10_DISC_SCAN: - if (command_code == CMND_HM10_DISC_SCAN) { HM10_Discovery_Scan(); } - Response_P(S_JSON_HM10_COMMAND, command, ""); - break; - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - - - -const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}"; -const char HTTP_HM10_SERIAL[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; -const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; -const char HTTP_HM10_HL[] PROGMEM = "{s}
{m}
{e}"; - -void HM10Show(bool json) -{ - if (json) { - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - char slave[33]; - sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - - ResponseAppend_P(PSTR(",\"%s\":{"),slave); - if(MIBLEsensors.at(i).temp!=-1000.0f){ - ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); - } - if (MIBLEsensors.at(i).type==FLORA){ - char lux[33]; - char moisture[33]; - char fertility[33]; - dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); - dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); - dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - if(MIBLEsensors.at(i).lux!=0xffff){ - ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); - } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ - ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); - } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ - ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); - } - } - if (MIBLEsensors.at(i).type>FLORA){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - if(MIBLEsensors.at(i).hum!=-1.0f){ - ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - } - if(MIBLEsensors.at(i).bat!=0xff){ - ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); - } - } - ResponseAppend_P(PSTR("}")); - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_HM10, HM10.firmware); - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - WSContentSend_PD(HTTP_HM10_HL); - WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - if(MIBLEsensors.at(i).temp!=-1000.0f){ - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); - } - if (MIBLEsensors.at(i).type==FLORA){ - if(MIBLEsensors.at(i).lux!=0xffff){ - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); - } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ - WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); - } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ - char fertility[33]; - dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors.at(i).type-1], fertility); - } - } - if (MIBLEsensors.at(i).type>FLORA){ - if(MIBLEsensors.at(i).hum!=-1.0f){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); - } - if(MIBLEsensors.at(i).bat!=0xff){ - WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); - } - } - } -#endif - } -} - - - - - -bool Xsns62(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_HM10_RX] < 99) && (pin[GPIO_HM10_TX] < 99)) { - switch (function) { - case FUNC_INIT: - HM10SerialInit(); - break; - case FUNC_EVERY_50_MSECOND: - HM10SerialHandleFeedback(); - break; - case FUNC_EVERY_100_MSECOND: - if (HM10_TASK_LIST[0][0] != TASK_HM10_NOTASK) { - HM10_TaskEvery100ms(); - } - break; - case FUNC_EVERY_SECOND: - HM10EverySecond(); - break; - case FUNC_COMMAND: - result = HM10Cmd(); - break; - case FUNC_JSON_APPEND: - HM10Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HM10Show(0); - break; -#endif - } - } - return result; -} -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_64_aht10.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_64_aht10.ino" -#ifdef USE_I2C -#ifdef USE_AHT10 - - - - - - -#define XSNS_64 64 -#define XI2C_43 43 - -#define AHT10_ADDR 0x38 - -unsigned char eSensorCalibrateCmd[3] = {0xE1, 0x08, 0x00}; -unsigned char eSensorNormalCmd[3] = {0xA8, 0x00, 0x00}; -unsigned char eSensorMeasureCmd[3] = {0xAC, 0x33, 0x00}; -unsigned char eSensorResetCmd = 0xBA; - -struct AHT10 { - float humidity = NAN; - float temperature = NAN; - uint8_t valid = 0; - uint8_t count = 0; - char name[6] = "AHT10"; -} AHT10; - -bool begin() -{ - Wire.begin(AHT10_ADDR); - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorCalibrateCmd, 3); - Wire.endTransmission(); - delay(500); - - if((readStatus() & 0x68) == 0x08) - return true; - else - { - return false; - } -} - -bool AHT10Read(void) -{ - unsigned long result, temp[6]; - - if (AHT10.valid) { AHT10.valid--; } - - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorMeasureCmd, 3); - Wire.endTransmission(); - delay(100); - - Wire.requestFrom(AHT10_ADDR, 6); - for(unsigned char i = 0; Wire.available() > 0; i++) - { - temp[i] = Wire.read(); - } - - AHT10.humidity = (((temp[1] << 16) | (temp[2] << 8) | temp[3]) >> 4)* 100 / 1048576; - AHT10.temperature = ((200 * (((temp[3] & 0x0F) << 16) | (temp[4] << 8) | temp[5])) / 1048576) - 50; - - if (isnan(AHT10.temperature) || isnan(AHT10.humidity)) { return false; } - - AHT10.valid = SENSOR_MAX_MISS; - return true; -} - - -unsigned char readStatus(void) -{ - unsigned char result = 0; - - Wire.requestFrom(AHT10_ADDR, 1); - result = Wire.read(); - return result; -} - -void AHT10Detect(void) -{ - if (I2cActive(AHT10_ADDR)) - { - return; - } - - if (begin()) - { - I2cSetActiveFound(AHT10_ADDR, AHT10.name); - AHT10.count = 1; - } -} - -void AHT10EverySecond(void) -{ - if (uptime &1) { - - if (!AHT10Read()) { - AddLogMissed(AHT10.name, AHT10.valid); - } - } -} - -void AHT10Show(bool json) -{ - if (AHT10.valid) { - char temperature[33]; - dtostrfd(AHT10.temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(AHT10.humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, AHT10.name, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, AHT10.temperature); - KnxSensor(KNX_HUMIDITY, AHT10.humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, AHT10.name, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, AHT10.name, humidity); -#endif - } - } -} - - - - - -bool Xsns64(uint8_t function) -{ - if (!I2cEnabled(XI2C_43)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - AHT10Detect(); - } - else if (AHT10.count) { - switch (function) { - case FUNC_EVERY_SECOND: - AHT10EverySecond(); - break; - case FUNC_JSON_APPEND: - AHT10Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AHT10Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_91_prometheus.ino" -# 22 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_91_prometheus.ino" -#ifdef USE_PROMETHEUS - - - - -#define XSNS_91 91 - -void HandleMetrics(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR("Prometheus")); - - WSContentBegin(200, CT_PLAIN); - - - char parameter[FLOATSZ]; - - if (global_temperature != 9999) { - dtostrfd(global_temperature, Settings.flag2.temperature_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_temperature gauge\nglobal_temperature %s\n"), parameter); - } - if (global_humidity != 0) { - dtostrfd(global_humidity, Settings.flag2.humidity_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_humidity gauge\nglobal_humidity %s\n"), parameter); - } - if (global_pressure != 0) { - dtostrfd(global_pressure, Settings.flag2.pressure_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_pressure gauge\nglobal_pressure %s\n"), parameter); - } - -#ifdef USE_ENERGY_SENSOR - dtostrfd(Energy.voltage[0], Settings.flag2.voltage_resolution, parameter); - WSContentSend_P(PSTR("# TYPE voltage gauge\nvoltage %s\n"), parameter); - dtostrfd(Energy.current[0], Settings.flag2.current_resolution, parameter); - WSContentSend_P(PSTR("# TYPE current gauge\ncurrent %s\n"), parameter); - dtostrfd(Energy.active_power[0], Settings.flag2.wattage_resolution, parameter); - WSContentSend_P(PSTR("# TYPE active_power gauge\nactive_power %s\n"), parameter); - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_daily gauge\nenergy_daily %s\n"), parameter); - dtostrfd(Energy.total, Settings.flag2.energy_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_total counter\nenergy_total %s\n"), parameter); -#endif -# 80 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_91_prometheus.ino" - WSContentEnd(); -} - - - - - -bool Xsns91(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/metrics", HandleMetrics); - break; - } - return result; -} - -#endif -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_interface.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xsns_interface.ino" -#ifdef XFUNC_PTR_IN_ROM -bool (* const xsns_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xsns_func_ptr[])(uint8_t) = { -#endif - -#ifdef XSNS_01 - &Xsns01, -#endif - -#ifdef XSNS_02 - &Xsns02, -#endif - -#ifdef XSNS_03 - &Xsns03, -#endif - -#ifdef XSNS_04 - &Xsns04, -#endif - -#ifdef XSNS_05 - &Xsns05, -#endif - -#ifdef XSNS_06 - &Xsns06, -#endif - -#ifdef XSNS_07 - &Xsns07, -#endif - -#ifdef XSNS_08 - &Xsns08, -#endif - -#ifdef XSNS_09 - &Xsns09, -#endif - -#ifdef XSNS_10 - &Xsns10, -#endif - -#ifdef XSNS_11 - &Xsns11, -#endif - -#ifdef XSNS_12 - &Xsns12, -#endif - -#ifdef XSNS_13 - &Xsns13, -#endif - -#ifdef XSNS_14 - &Xsns14, -#endif - -#ifdef XSNS_15 - &Xsns15, -#endif - -#ifdef XSNS_16 - &Xsns16, -#endif - -#ifdef XSNS_17 - &Xsns17, -#endif - -#ifdef XSNS_18 - &Xsns18, -#endif - -#ifdef XSNS_19 - &Xsns19, -#endif - -#ifdef XSNS_20 - &Xsns20, -#endif - -#ifdef XSNS_21 - &Xsns21, -#endif - -#ifdef XSNS_22 - &Xsns22, -#endif - -#ifdef XSNS_23 - &Xsns23, -#endif - -#ifdef XSNS_24 - &Xsns24, -#endif - -#ifdef XSNS_25 - &Xsns25, -#endif - -#ifdef XSNS_26 - &Xsns26, -#endif - -#ifdef XSNS_27 - &Xsns27, -#endif - -#ifdef XSNS_28 - &Xsns28, -#endif - -#ifdef XSNS_29 - &Xsns29, -#endif - -#ifdef XSNS_30 - &Xsns30, -#endif - -#ifdef XSNS_31 - &Xsns31, -#endif - -#ifdef XSNS_32 - &Xsns32, -#endif - -#ifdef XSNS_33 - &Xsns33, -#endif - -#ifdef XSNS_34 - &Xsns34, -#endif - -#ifdef XSNS_35 - &Xsns35, -#endif - -#ifdef XSNS_36 - &Xsns36, -#endif - -#ifdef XSNS_37 - &Xsns37, -#endif - -#ifdef XSNS_38 - &Xsns38, -#endif - -#ifdef XSNS_39 - &Xsns39, -#endif - -#ifdef XSNS_40 - &Xsns40, -#endif - -#ifdef XSNS_41 - &Xsns41, -#endif - -#ifdef XSNS_42 - &Xsns42, -#endif - -#ifdef XSNS_43 - &Xsns43, -#endif - -#ifdef XSNS_44 - &Xsns44, -#endif - -#ifdef XSNS_45 - &Xsns45, -#endif - -#ifdef XSNS_46 - &Xsns46, -#endif - -#ifdef XSNS_47 - &Xsns47, -#endif - -#ifdef XSNS_48 - &Xsns48, -#endif - -#ifdef XSNS_49 - &Xsns49, -#endif - -#ifdef XSNS_50 - &Xsns50, -#endif - -#ifdef XSNS_51 - &Xsns51, -#endif - -#ifdef XSNS_52 - &Xsns52, -#endif - -#ifdef XSNS_53 - &Xsns53, -#endif - -#ifdef XSNS_54 - &Xsns54, -#endif - -#ifdef XSNS_55 - &Xsns55, -#endif - -#ifdef XSNS_56 - &Xsns56, -#endif - -#ifdef XSNS_57 - &Xsns57, -#endif - -#ifdef XSNS_58 - &Xsns58, -#endif - -#ifdef XSNS_59 - &Xsns59, -#endif - -#ifdef XSNS_60 - &Xsns60, -#endif - -#ifdef XSNS_61 - &Xsns61, -#endif - -#ifdef XSNS_62 - &Xsns62, -#endif - -#ifdef XSNS_63 - &Xsns63, -#endif - -#ifdef XSNS_64 - &Xsns64, -#endif - -#ifdef XSNS_65 - &Xsns65, -#endif - -#ifdef XSNS_66 - &Xsns66, -#endif - -#ifdef XSNS_67 - &Xsns67, -#endif - -#ifdef XSNS_68 - &Xsns68, -#endif - -#ifdef XSNS_69 - &Xsns69, -#endif - -#ifdef XSNS_70 - &Xsns70, -#endif - -#ifdef XSNS_71 - &Xsns71, -#endif - -#ifdef XSNS_72 - &Xsns72, -#endif - -#ifdef XSNS_73 - &Xsns73, -#endif - -#ifdef XSNS_74 - &Xsns74, -#endif - -#ifdef XSNS_75 - &Xsns75, -#endif - -#ifdef XSNS_76 - &Xsns76, -#endif - -#ifdef XSNS_77 - &Xsns77, -#endif - -#ifdef XSNS_78 - &Xsns78, -#endif - -#ifdef XSNS_79 - &Xsns79, -#endif - -#ifdef XSNS_80 - &Xsns80, -#endif - -#ifdef XSNS_81 - &Xsns81, -#endif - -#ifdef XSNS_82 - &Xsns82, -#endif - -#ifdef XSNS_83 - &Xsns83, -#endif - -#ifdef XSNS_84 - &Xsns84, -#endif - -#ifdef XSNS_85 - &Xsns85, -#endif - -#ifdef XSNS_86 - &Xsns86, -#endif - -#ifdef XSNS_87 - &Xsns87, -#endif - -#ifdef XSNS_88 - &Xsns88, -#endif - -#ifdef XSNS_89 - &Xsns89, -#endif - -#ifdef XSNS_90 - &Xsns90, -#endif - -#ifdef XSNS_91 - &Xsns91, -#endif - -#ifdef XSNS_92 - &Xsns92, -#endif - -#ifdef XSNS_93 - &Xsns93, -#endif - -#ifdef XSNS_94 - &Xsns94, -#endif - -#ifdef XSNS_95 - &Xsns95, -#endif - -#ifdef XSNS_96 - &Xsns96, -#endif - -#ifdef XSNS_97 - &Xsns97, -#endif - -#ifdef XSNS_98 - &Xsns98, -#endif - -#ifdef XSNS_99 - &Xsns99 -#endif -}; - -const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); - - - - - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXsnsList[] PROGMEM = { -#else -const uint8_t kXsnsList[] = { -#endif - -#ifdef XSNS_01 - XSNS_01, -#endif - -#ifdef XSNS_02 - XSNS_02, -#endif - -#ifdef XSNS_03 - XSNS_03, -#endif - -#ifdef XSNS_04 - XSNS_04, -#endif - -#ifdef XSNS_05 - XSNS_05, -#endif - -#ifdef XSNS_06 - XSNS_06, -#endif - -#ifdef XSNS_07 - XSNS_07, -#endif - -#ifdef XSNS_08 - XSNS_08, -#endif - -#ifdef XSNS_09 - XSNS_09, -#endif - -#ifdef XSNS_10 - XSNS_10, -#endif - -#ifdef XSNS_11 - XSNS_11, -#endif - -#ifdef XSNS_12 - XSNS_12, -#endif - -#ifdef XSNS_13 - XSNS_13, -#endif - -#ifdef XSNS_14 - XSNS_14, -#endif - -#ifdef XSNS_15 - XSNS_15, -#endif - -#ifdef XSNS_16 - XSNS_16, -#endif - -#ifdef XSNS_17 - XSNS_17, -#endif - -#ifdef XSNS_18 - XSNS_18, -#endif - -#ifdef XSNS_19 - XSNS_19, -#endif - -#ifdef XSNS_20 - XSNS_20, -#endif - -#ifdef XSNS_21 - XSNS_21, -#endif - -#ifdef XSNS_22 - XSNS_22, -#endif - -#ifdef XSNS_23 - XSNS_23, -#endif - -#ifdef XSNS_24 - XSNS_24, -#endif - -#ifdef XSNS_25 - XSNS_25, -#endif - -#ifdef XSNS_26 - XSNS_26, -#endif - -#ifdef XSNS_27 - XSNS_27, -#endif - -#ifdef XSNS_28 - XSNS_28, -#endif - -#ifdef XSNS_29 - XSNS_29, -#endif - -#ifdef XSNS_30 - XSNS_30, -#endif - -#ifdef XSNS_31 - XSNS_31, -#endif - -#ifdef XSNS_32 - XSNS_32, -#endif - -#ifdef XSNS_33 - XSNS_33, -#endif - -#ifdef XSNS_34 - XSNS_34, -#endif - -#ifdef XSNS_35 - XSNS_35, -#endif - -#ifdef XSNS_36 - XSNS_36, -#endif - -#ifdef XSNS_37 - XSNS_37, -#endif - -#ifdef XSNS_38 - XSNS_38, -#endif - -#ifdef XSNS_39 - XSNS_39, -#endif - -#ifdef XSNS_40 - XSNS_40, -#endif - -#ifdef XSNS_41 - XSNS_41, -#endif - -#ifdef XSNS_42 - XSNS_42, -#endif - -#ifdef XSNS_43 - XSNS_43, -#endif - -#ifdef XSNS_44 - XSNS_44, -#endif - -#ifdef XSNS_45 - XSNS_45, -#endif - -#ifdef XSNS_46 - XSNS_46, -#endif - -#ifdef XSNS_47 - XSNS_47, -#endif - -#ifdef XSNS_48 - XSNS_48, -#endif - -#ifdef XSNS_49 - XSNS_49, -#endif - -#ifdef XSNS_50 - XSNS_50, -#endif - -#ifdef XSNS_51 - XSNS_51, -#endif - -#ifdef XSNS_52 - XSNS_52, -#endif - -#ifdef XSNS_53 - XSNS_53, -#endif - -#ifdef XSNS_54 - XSNS_54, -#endif - -#ifdef XSNS_55 - XSNS_55, -#endif - -#ifdef XSNS_56 - XSNS_56, -#endif - -#ifdef XSNS_57 - XSNS_57, -#endif - -#ifdef XSNS_58 - XSNS_58, -#endif - -#ifdef XSNS_59 - XSNS_59, -#endif - -#ifdef XSNS_60 - XSNS_60, -#endif - -#ifdef XSNS_61 - XSNS_61, -#endif - -#ifdef XSNS_62 - XSNS_62, -#endif - -#ifdef XSNS_63 - XSNS_63, -#endif - -#ifdef XSNS_64 - XSNS_64, -#endif - -#ifdef XSNS_65 - XSNS_65, -#endif - -#ifdef XSNS_66 - XSNS_66, -#endif - -#ifdef XSNS_67 - XSNS_67, -#endif - -#ifdef XSNS_68 - XSNS_68, -#endif - -#ifdef XSNS_69 - XSNS_69, -#endif - -#ifdef XSNS_70 - XSNS_70, -#endif - -#ifdef XSNS_71 - XSNS_71, -#endif - -#ifdef XSNS_72 - XSNS_72, -#endif - -#ifdef XSNS_73 - XSNS_73, -#endif - -#ifdef XSNS_74 - XSNS_74, -#endif - -#ifdef XSNS_75 - XSNS_75, -#endif - -#ifdef XSNS_76 - XSNS_76, -#endif - -#ifdef XSNS_77 - XSNS_77, -#endif - -#ifdef XSNS_78 - XSNS_78, -#endif - -#ifdef XSNS_79 - XSNS_79, -#endif - -#ifdef XSNS_80 - XSNS_80, -#endif - -#ifdef XSNS_81 - XSNS_81, -#endif - -#ifdef XSNS_82 - XSNS_82, -#endif - -#ifdef XSNS_83 - XSNS_83, -#endif - -#ifdef XSNS_84 - XSNS_84, -#endif - -#ifdef XSNS_85 - XSNS_85, -#endif - -#ifdef XSNS_86 - XSNS_86, -#endif - -#ifdef XSNS_87 - XSNS_87, -#endif - -#ifdef XSNS_88 - XSNS_88, -#endif - -#ifdef XSNS_89 - XSNS_89, -#endif - -#ifdef XSNS_90 - XSNS_90, -#endif - -#ifdef XSNS_91 - XSNS_91, -#endif - -#ifdef XSNS_92 - XSNS_92, -#endif - -#ifdef XSNS_93 - XSNS_93, -#endif - -#ifdef XSNS_94 - XSNS_94, -#endif - -#ifdef XSNS_95 - XSNS_95, -#endif - -#ifdef XSNS_96 - XSNS_96, -#endif - -#ifdef XSNS_97 - XSNS_97, -#endif - -#ifdef XSNS_98 - XSNS_98, -#endif - -#ifdef XSNS_99 - XSNS_99 -#endif -}; - - - -bool XsnsEnabled(uint32_t sns_index) -{ - if (sns_index < sizeof(kXsnsList)) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t index = pgm_read_byte(kXsnsList + sns_index); -#else - uint32_t index = kXsnsList[sns_index]; -#endif - return bitRead(Settings.sensors[index / 32], index % 32); - } - return true; -} - -void XsnsSensorState(void) -{ - ResponseAppend_P(PSTR("\"")); - for (uint32_t i = 0; i < sizeof(kXsnsList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t sensorid = pgm_read_byte(kXsnsList + i); -#else - uint32_t sensorid = kXsnsList[i]; -#endif - bool disabled = false; - if (sensorid < MAX_XSNS_DRIVERS) { - disabled = !bitRead(Settings.sensors[sensorid / 32], sensorid % 32); - } - ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", sensorid); - } - ResponseAppend_P(PSTR("\"")); -} - - - - - -bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) -{ - xsns_index++; - if (xsns_index == xsns_present) { xsns_index = 0; } - -#ifndef USE_DEBUG_DRIVER - if (FUNC_WEB_SENSOR == Function) { -#endif - uint32_t max_disabled = xsns_present; - while (!XsnsEnabled(xsns_index) && max_disabled--) { - xsns_index++; - if (xsns_index == xsns_present) { xsns_index = 0; } - } -#ifndef USE_DEBUG_DRIVER - } -#endif - - return xsns_func_ptr[xsns_index](Function); -} - -bool XsnsCall(uint8_t Function) -{ - bool result = false; - - DEBUG_TRACE_LOG(PSTR("SNS: %d"), Function); - -#ifdef PROFILE_XSNS_EVERY_SECOND - uint32_t profile_start_millis = millis(); -#endif - - for (uint32_t x = 0; x < xsns_present; x++) { -#ifdef USE_DEBUG_DRIVER - if (XsnsEnabled(x)) { -#endif - - if ((FUNC_WEB_SENSOR == Function) && !XsnsEnabled(x)) { continue; } - -#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND - uint32_t profile_start_millis = millis(); -#endif - result = xsns_func_ptr[x](Function); - -#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND - uint32_t profile_millis = millis() - profile_start_millis; - if (profile_millis) { - if (FUNC_EVERY_SECOND == Function) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); - } - } -#endif - - if (result && ((FUNC_COMMAND == Function) || - (FUNC_PIN_STATE == Function) || - (FUNC_COMMAND_SENSOR == Function) - )) { - break; - } -#ifdef USE_DEBUG_DRIVER - } -#endif - } - -#ifdef PROFILE_XSNS_EVERY_SECOND - uint32_t profile_millis = millis() - profile_start_millis; - if (profile_millis) { - if (FUNC_EVERY_SECOND == Function) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); - } - } -#endif - - return result; -} -# 1 "C:/shared/sonoff/Git/Tasmota/tasmota/xx2c_interface.ino" -# 20 "C:/shared/sonoff/Git/Tasmota/tasmota/xx2c_interface.ino" -#ifdef USE_I2C - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kI2cList[] PROGMEM = { -#else -const uint8_t kI2cList[] = { -#endif - -#ifdef XI2C_01 - XI2C_01, -#endif - -#ifdef XI2C_02 - XI2C_02, -#endif - -#ifdef XI2C_03 - XI2C_03, -#endif - -#ifdef XI2C_04 - XI2C_04, -#endif - -#ifdef XI2C_05 - XI2C_05, -#endif - -#ifdef XI2C_06 - XI2C_06, -#endif - -#ifdef XI2C_07 - XI2C_07, -#endif - -#ifdef XI2C_08 - XI2C_08, -#endif - -#ifdef XI2C_09 - XI2C_09, -#endif - -#ifdef XI2C_10 - XI2C_10, -#endif - -#ifdef XI2C_11 - XI2C_11, -#endif - -#ifdef XI2C_12 - XI2C_12, -#endif - -#ifdef XI2C_13 - XI2C_13, -#endif - -#ifdef XI2C_14 - XI2C_14, -#endif - -#ifdef XI2C_15 - XI2C_15, -#endif - -#ifdef XI2C_16 - XI2C_16, -#endif - -#ifdef XI2C_17 - XI2C_17, -#endif - -#ifdef XI2C_18 - XI2C_18, -#endif - -#ifdef XI2C_19 - XI2C_19, -#endif - -#ifdef XI2C_20 - XI2C_20, -#endif - -#ifdef XI2C_21 - XI2C_21, -#endif - -#ifdef XI2C_22 - XI2C_22, -#endif - -#ifdef XI2C_23 - XI2C_23, -#endif - -#ifdef XI2C_24 - XI2C_24, -#endif - -#ifdef XI2C_25 - XI2C_25, -#endif - -#ifdef XI2C_26 - XI2C_26, -#endif - -#ifdef XI2C_27 - XI2C_27, -#endif - -#ifdef XI2C_28 - XI2C_28, -#endif - -#ifdef XI2C_29 - XI2C_29, -#endif - -#ifdef XI2C_30 - XI2C_30, -#endif - -#ifdef XI2C_31 - XI2C_31, -#endif - -#ifdef XI2C_32 - XI2C_32, -#endif - -#ifdef XI2C_33 - XI2C_33, -#endif - -#ifdef XI2C_34 - XI2C_34, -#endif - -#ifdef XI2C_35 - XI2C_35, -#endif - -#ifdef XI2C_36 - XI2C_36, -#endif - -#ifdef XI2C_37 - XI2C_37, -#endif - -#ifdef XI2C_38 - XI2C_38, -#endif - -#ifdef XI2C_39 - XI2C_39, -#endif - -#ifdef XI2C_40 - XI2C_40, -#endif - -#ifdef XI2C_41 - XI2C_41, -#endif - -#ifdef XI2C_42 - XI2C_42, -#endif - -#ifdef XI2C_43 - XI2C_43, -#endif - -#ifdef XI2C_44 - XI2C_44, -#endif - -#ifdef XI2C_45 - XI2C_45, -#endif - -#ifdef XI2C_46 - XI2C_46, -#endif - -#ifdef XI2C_47 - XI2C_47, -#endif - -#ifdef XI2C_48 - XI2C_48, -#endif - -#ifdef XI2C_49 - XI2C_49, -#endif - -#ifdef XI2C_50 - XI2C_50, -#endif - -#ifdef XI2C_51 - XI2C_51, -#endif - -#ifdef XI2C_52 - XI2C_52, -#endif - -#ifdef XI2C_53 - XI2C_53, -#endif - -#ifdef XI2C_54 - XI2C_54, -#endif - -#ifdef XI2C_55 - XI2C_55, -#endif - -#ifdef XI2C_56 - XI2C_56, -#endif - -#ifdef XI2C_57 - XI2C_57, -#endif - -#ifdef XI2C_58 - XI2C_58, -#endif - -#ifdef XI2C_59 - XI2C_59, -#endif - -#ifdef XI2C_60 - XI2C_60, -#endif - -#ifdef XI2C_61 - XI2C_61, -#endif - -#ifdef XI2C_62 - XI2C_62, -#endif - -#ifdef XI2C_63 - XI2C_63, -#endif - -#ifdef XI2C_64 - XI2C_64, -#endif - -#ifdef XI2C_65 - XI2C_65, -#endif - -#ifdef XI2C_66 - XI2C_66, -#endif - -#ifdef XI2C_67 - XI2C_67, -#endif - -#ifdef XI2C_68 - XI2C_68, -#endif - -#ifdef XI2C_69 - XI2C_69, -#endif - -#ifdef XI2C_70 - XI2C_70, -#endif - -#ifdef XI2C_71 - XI2C_71, -#endif - -#ifdef XI2C_72 - XI2C_72, -#endif - -#ifdef XI2C_73 - XI2C_73, -#endif - -#ifdef XI2C_74 - XI2C_74, -#endif - -#ifdef XI2C_75 - XI2C_75, -#endif - -#ifdef XI2C_76 - XI2C_76, -#endif - -#ifdef XI2C_77 - XI2C_77, -#endif - -#ifdef XI2C_78 - XI2C_78, -#endif - -#ifdef XI2C_79 - XI2C_79, -#endif - -#ifdef XI2C_80 - XI2C_80, -#endif - -#ifdef XI2C_81 - XI2C_81, -#endif - -#ifdef XI2C_82 - XI2C_82, -#endif - -#ifdef XI2C_83 - XI2C_83, -#endif - -#ifdef XI2C_84 - XI2C_84, -#endif - -#ifdef XI2C_85 - XI2C_85, -#endif - -#ifdef XI2C_86 - XI2C_86, -#endif - -#ifdef XI2C_87 - XI2C_87, -#endif - -#ifdef XI2C_88 - XI2C_88, -#endif - -#ifdef XI2C_89 - XI2C_89, -#endif - -#ifdef XI2C_90 - XI2C_90, -#endif - -#ifdef XI2C_91 - XI2C_91, -#endif - -#ifdef XI2C_92 - XI2C_92, -#endif - -#ifdef XI2C_93 - XI2C_93, -#endif - -#ifdef XI2C_94 - XI2C_94, -#endif - -#ifdef XI2C_95 - XI2C_95, -#endif - -#ifdef XI2C_96 - XI2C_96 -#endif -}; - - - -bool I2cEnabled(uint32_t i2c_index) -{ - return (i2c_flg && bitRead(Settings.i2c_drivers[i2c_index / 32], i2c_index % 32)); -} - -void I2cDriverState(void) -{ - ResponseAppend_P(PSTR("\"")); - for (uint32_t i = 0; i < sizeof(kI2cList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t i2c_driver_id = pgm_read_byte(kI2cList + i); -#else - uint32_t i2c_driver_id = kI2cList[i]; -#endif - bool disabled = false; - if (i2c_driver_id < MAX_I2C_DRIVERS) { - disabled = !bitRead(Settings.i2c_drivers[i2c_driver_id / 32], i2c_driver_id % 32); - } - ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", i2c_driver_id); - } - ResponseAppend_P(PSTR("\"")); -} - -#endif \ No newline at end of file diff --git a/tasmota/xsns_64_aht10.ino b/tasmota/xsns_63_aht1x.ino similarity index 94% rename from tasmota/xsns_64_aht10.ino rename to tasmota/xsns_63_aht1x.ino index 95d5a3e2b..59a02a7de 100644 --- a/tasmota/xsns_64_aht10.ino +++ b/tasmota/xsns_63_aht1x.ino @@ -1,7 +1,7 @@ /* - xsns_64_AHT10.ino - AHT10 I2C temperature and humidity sensor support for Tasmota + xsns_63_AHT1x.ino - AHT10 I2C temperature and humidity sensor support for Tasmota - Copyright (C) 2020 M. Wagner + Copyright (C) 2020 Martin Wagner 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 @@ -18,14 +18,14 @@ */ #ifdef USE_I2C -#ifdef USE_AHT10 +#ifdef USE_AHT1x /*********************************************************************************************\ - * AHT10 - Temperature and Humidity + * AHT10/15 - Temperature and Humidity * * I2C Address: 0x38 \*********************************************************************************************/ -#define XSNS_64 64 +#define XSNS_63 63 #define XI2C_43 43 // See I2CDEVICES.md #define AHT10_ADDR 0x38 @@ -40,7 +40,7 @@ struct AHT10 { float temperature = NAN; uint8_t valid = 0; uint8_t count = 0; - char name[6] = "AHT10"; + char name[9] = "AHT10/15"; } AHT10; @@ -60,6 +60,7 @@ bool AHT10Read(void) { temp[i] = Wire.read(); } + result_h = ((temp[1] << 16) | (temp[2] << 8) | temp[3]) >> 4; result_t = ((temp[3] & 0x0F) << 16) | (temp[4] << 8) | temp[5]; @@ -160,7 +161,7 @@ void AHT10Show(bool json) * Interface \*********************************************************************************************/ -bool Xsns64(uint8_t function) +bool Xsns63(uint8_t function) { if (!I2cEnabled(XI2C_43)) { return false; } From 5c4864499401af9a84a3c90aec43d53904398971 Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Wed, 19 Feb 2020 10:23:56 +0100 Subject: [PATCH 433/559] typo change --- tasmota/my_user_config.h | 2 +- tasmota/xsns_63_aht1x.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 7f7fa3a45..d641ac761 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -486,7 +486,7 @@ // #define USE_HIH6 // [I2cDriver36] Enable Honeywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) // #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) (+0k7 code) // #define USE_DS1624 // [I2cDriver42] Enable DS1624, DS1621 temperature sensor (I2C addresses 0x48 - 0x4F) (+1k2 code) - #define USE_AHT1x // [I2cDriver43] Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code) +// #define USE_AHT1x // [I2cDriver43] Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/xsns_63_aht1x.ino b/tasmota/xsns_63_aht1x.ino index 59a02a7de..4407fb625 100644 --- a/tasmota/xsns_63_aht1x.ino +++ b/tasmota/xsns_63_aht1x.ino @@ -56,7 +56,7 @@ bool AHT10Read(void) delay(100); Wire.requestFrom(AHT10_ADDR, 6); - for(unsigned char i = 0; Wire.available() > 0; i++) + for(uint8_t i = 0; Wire.available() > 0; i++) { temp[i] = Wire.read(); } From 414020d19fe959e5a04365a26f9fdcf433d01fbf Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 19 Feb 2020 12:21:53 +0100 Subject: [PATCH 434/559] Use new syntax for providing ldscript --- platformio_override_sample.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 383e7f04b..93bbbb5ba 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -226,10 +226,10 @@ build_flags = ${esp82xx_defaults.build_flags} [core_stage] ; *** Esp8266 core for Arduino version latest beta -platform = espressif8266@2.3.1 +platform = espressif8266@2.3.2 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git +board_build.ldscript = eagle.flash.1m.ld build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC -DNOPRINTFLOAT ; NONOSDK221 From fbd2216d094778f28198965d49a7b2a47f32e676 Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Wed, 19 Feb 2020 14:06:35 +0100 Subject: [PATCH 435/559] Update xsns_63_aht1x.ino Sensor Name changement --- tasmota/xsns_63_aht1x.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasmota/xsns_63_aht1x.ino b/tasmota/xsns_63_aht1x.ino index 4407fb625..815f3a30a 100644 --- a/tasmota/xsns_63_aht1x.ino +++ b/tasmota/xsns_63_aht1x.ino @@ -40,13 +40,13 @@ struct AHT10 { float temperature = NAN; uint8_t valid = 0; uint8_t count = 0; - char name[9] = "AHT10/15"; + char name[6] = "AHT1x"; } AHT10; bool AHT10Read(void) { - unsigned long result_t, result_h, temp[6]; + unsigned long result_t, result_h, data[6]; if (AHT10.valid) { AHT10.valid--; } @@ -58,11 +58,11 @@ bool AHT10Read(void) Wire.requestFrom(AHT10_ADDR, 6); for(uint8_t i = 0; Wire.available() > 0; i++) { - temp[i] = Wire.read(); + data[i] = Wire.read(); } - result_h = ((temp[1] << 16) | (temp[2] << 8) | temp[3]) >> 4; - result_t = ((temp[3] & 0x0F) << 16) | (temp[4] << 8) | temp[5]; + result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; + result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; AHT10.humidity = result_h * 100 / 1048576; AHT10.temperature = ((200 * result_t) / 1048576) - 50; From 84a2da2ee27c480747668583242bfb1a2051ec36 Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Wed, 19 Feb 2020 14:24:37 +0100 Subject: [PATCH 436/559] Update support_features.ino --- tasmota/support_features.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 648235f12..85f5a77ea 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -516,7 +516,6 @@ void GetFeatures(void) #ifdef USE_AHT1x feature5 |= 0x10000000; // xsns_63_aht1x.ino #endif -// feature5 |= 0x10000000; // feature5 |= 0x20000000; // feature5 |= 0x40000000; // feature5 |= 0x80000000; From 6a84899e1072358a2505d24018a9a4ecedf8fba1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 19 Feb 2020 15:23:59 +0100 Subject: [PATCH 437/559] Eliminating call sntp_get_real_time Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/support_command.ino | 8 +++---- tasmota/support_rtc.ino | 46 +++++++++++++++---------------------- tasmota/tasmota.h | 2 +- tasmota/xsns_33_ds3231.ino | 4 ++-- 6 files changed, 28 insertions(+), 34 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0962f6617..5ec616909 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -61,6 +61,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change wifi connectivity stability (#7602) - Change some wifi code to attempt faster connection (#7621) - Change MQTT message size with additional 200 characters +- Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Fix ``White`` added to light status (#7142) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 0366cfb7f..ff2a178f6 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Change MQTT message size with additional 200 characters - Change some wifi code to attempt faster connection (#7621) +- Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" - Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717) ### 8.1.0.7 20200210 diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index df5abda86..c749a3be2 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -449,13 +449,13 @@ void CmndStatus(void) #if defined(USE_TIMERS) && defined(USE_SUNRISE) Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), - GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), - GetTime(3).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), + GetDateAndTime(DT_STD).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); #else Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), - GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), - GetTime(3).c_str(), stemp); + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), + GetDateAndTime(DT_STD).c_str(), stemp); #endif // USE_TIMERS and USE_SUNRISE MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); } diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index f8fb25779..7af66653a 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -170,8 +170,8 @@ String GetDT(uint32_t time) /* * timestamps in https://en.wikipedia.org/wiki/ISO_8601 format * - * DT_UTC - current data and time in Greenwich, England (aka GMT) - * DT_LOCAL - current date and time taking timezone into account + * DT_UTC - current data and time in Greenwich, England (aka GMT) + * DT_LOCAL - current date and time taking timezone into account * DT_RESTART - the date and time this device last started, in local timezone * * Format: @@ -184,21 +184,30 @@ String GetDateAndTime(uint8_t time_type) uint32_t time = Rtc.local_time; switch (time_type) { - case DT_BOOTCOUNT: - time = Settings.bootcount_reset_time; - break; - case DT_ENERGY: - time = Settings.energy_kWhtotal_time; - break; case DT_UTC: time = Rtc.utc_time; break; +// case DT_LOCALNOTZ: // Is default anyway but allows for not appendig timezone +// time = Rtc.local_time; +// break; + case DT_DST: + time = Rtc.daylight_saving_time; + break; + case DT_STD: + time = Rtc.standard_time; + break; case DT_RESTART: if (Rtc.restart_time == 0) { return ""; } time = Rtc.restart_time; break; + case DT_ENERGY: + time = Settings.energy_kWhtotal_time; + break; + case DT_BOOTCOUNT: + time = Settings.bootcount_reset_time; + break; } String dt = GetDT(time); // 2017-03-07T11:08:02 if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { // SetOption52 - Append timezone to JSON time @@ -207,23 +216,6 @@ String GetDateAndTime(uint8_t time_type) return dt; // 2017-03-07T11:08:02-07:00 } -String GetTime(int type) -{ - /* type 1 - Local time - * type 2 - Daylight Savings time - * type 3 - Standard time - */ - char stime[25]; // Skip newline - - uint32_t time = Rtc.utc_time; - if (1 == type) time = Rtc.local_time; - if (2 == type) time = Rtc.daylight_saving_time; - if (3 == type) time = Rtc.standard_time; - snprintf_P(stime, sizeof(stime), sntp_get_real_time(time)); - - return String(stime); // Thu Nov 01 11:41:02 2018 -} - uint32_t UpTime(void) { if (Rtc.restart_time) { @@ -400,8 +392,8 @@ void RtcSecond(void) Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); // Do not use AddLog_P2 here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9 - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - DriftTime(), GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ")%s, (" D_DST_TIME ")%s, (" D_STD_TIME ")%s"), + DriftTime(), GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01 rules_flag.time_init = 1; diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 2aa441878..377f9e8b8 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -226,7 +226,7 @@ enum WeekInMonthOptions {Last, First, Second, Third, Fourth}; enum DayOfTheWeekOptions {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat}; enum MonthNamesOptions {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; enum HemisphereOptions {North, South}; -enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_RESTART, DT_ENERGY, DT_BOOTCOUNT }; +enum GetDateAndTimeOptions { DT_LOCAL, DT_UTC, DT_LOCALNOTZ, DT_DST, DT_STD, DT_RESTART, DT_ENERGY, DT_BOOTCOUNT }; enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE}; diff --git a/tasmota/xsns_33_ds3231.ino b/tasmota/xsns_33_ds3231.ino index 0c72c6b11..09814bcf0 100644 --- a/tasmota/xsns_33_ds3231.ino +++ b/tasmota/xsns_33_ds3231.ino @@ -143,7 +143,7 @@ void DS3231EverySecond(void) Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01 rules_flag.time_init = 1; } else { @@ -152,7 +152,7 @@ void DS3231EverySecond(void) } else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) {//if time is valid and is drift from RTC in more that 60 second AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str()); + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); SetDS3231Time (Rtc.utc_time); //update the DS3231 time ds3231WriteStatus = true; } From f7d4d5ddb18870e3b3687bb1e62f388acc92cec3 Mon Sep 17 00:00:00 2001 From: device111 <48546979+device111@users.noreply.github.com> Date: Wed, 19 Feb 2020 19:49:09 +0100 Subject: [PATCH 438/559] Ad release note --- RELEASENOTES.md | 1 + tasmota/xsns_63_aht1x.ino | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 0962f6617..cf7184534 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -103,3 +103,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for FiF LE-01MR energy meter by saper-2 (#7584) - Add new DHT driver. The old driver can still be used using define USE_DHT_OLD (#7468) - Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717) +- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) \ No newline at end of file diff --git a/tasmota/xsns_63_aht1x.ino b/tasmota/xsns_63_aht1x.ino index 815f3a30a..b3b17e0e4 100644 --- a/tasmota/xsns_63_aht1x.ino +++ b/tasmota/xsns_63_aht1x.ino @@ -50,22 +50,22 @@ bool AHT10Read(void) if (AHT10.valid) { AHT10.valid--; } - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorMeasureCmd, 3); - Wire.endTransmission(); - delay(100); + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorMeasureCmd, 3); + Wire.endTransmission(); + delay(100); - Wire.requestFrom(AHT10_ADDR, 6); - for(uint8_t i = 0; Wire.available() > 0; i++) - { - data[i] = Wire.read(); - } + Wire.requestFrom(AHT10_ADDR, 6); + for(uint8_t i = 0; Wire.available() > 0; i++) + { + data[i] = Wire.read(); + } - result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; - result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; + result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; + result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; - AHT10.humidity = result_h * 100 / 1048576; - AHT10.temperature = ((200 * result_t) / 1048576) - 50; + AHT10.humidity = result_h * 100 / 1048576; + AHT10.temperature = ((200 * result_t) / 1048576) - 50; if (isnan(AHT10.temperature) || isnan(AHT10.humidity)) { return false; } From 46ad5166e1b02472f5ff26614b8154501d3569c0 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 19 Feb 2020 21:55:20 -0800 Subject: [PATCH 439/559] Add Wemos DC mottor shild (v1.0.0) support --- I2CDEVICES.md | 1 + tasmota/my_user_config.h | 3 + tasmota/support_features.ino | 4 +- tasmota/tasmota_post.h | 3 + tasmota/xdrv_34_wemos_motor_v1.ino | 188 +++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 tasmota/xdrv_34_wemos_motor_v1.ino diff --git a/I2CDEVICES.md b/I2CDEVICES.md index c7b42108f..57e906af7 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -64,4 +64,5 @@ Index | Define | Driver | Device | Address(es) | Description 41 | USE_DHT12 | xsns_58 | DHT12 | 0x5C | Temperature and humidity sensor 42 | USE_DS1624 | xsns_59 | DS1621 | 0x48 - 0x4F | Temperature sensor 42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor + 43 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x30 | WEMOS motor shield v1.0.0 (6612FNG) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 67ab1cf1c..af3295928 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -501,6 +501,9 @@ #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module // #define USE_DISPLAY_SH1106 // [DisplayModel 7] [I2cDriver6] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D) + #define USE_WEMOS_MOTOR_V1 + #define USE_WEMOS_MOTOR_V1_ADDR 0x30 + #define USE_WEMOS_MOTOR_V1_FREQ 1000 #endif // USE_I2C // -- SPI sensors --------------------------------- diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 2dc25b8e5..224ef86f6 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -513,8 +513,10 @@ void GetFeatures(void) #ifdef USE_LE01MR feature5 |= 0x08000000; // xnrg_13_fif_le01mr.ino #endif +#ifdef USE_WEMOS_MOTOR_V1 + feature5 |= 0x10000000; // xdrv_34_wemos_motor_v1.ino +#endif -// feature5 |= 0x10000000; // feature5 |= 0x20000000; // feature5 |= 0x40000000; // feature5 |= 0x80000000; diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 615ff8919..33e9c200b 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -221,6 +221,9 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack //#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code +#define USE_WEMOS_MOTOR_V1 + #define USE_WEMOS_MOTOR_V1_ADDR 0x30 + #define USE_WEMOS_MOTOR_V1_FREQ 1000 #endif // FIRMWARE_SENSORS /*********************************************************************************************\ diff --git a/tasmota/xdrv_34_wemos_motor_v1.ino b/tasmota/xdrv_34_wemos_motor_v1.ino new file mode 100644 index 000000000..fbf03d66d --- /dev/null +++ b/tasmota/xdrv_34_wemos_motor_v1.ino @@ -0,0 +1,188 @@ +/* + xdrv_34_wemos_motor_v1.ino - Support for I2C WEMOS motor shield (6612FNG) + + Copyright (C) 2020 Andre Thomas and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_I2C +#ifdef USE_WEMOS_MOTOR_V1 +/*********************************************************************************************\ + * WEMOS_MOTOR_V1 - DC motor driver shield (6612FNG) v 1.0.0 + * + * I2C Address: 0x30 + * Command format: + * driver43 ,,{,} + * command: + * RESET - reset a motor shield + * SETMOTOR - seter motor state + * motor: + * 0 - motor A + * 1 - motor B + * direction: + * 0 - short break + * 1 - CCW + * 2 - CW + * 3 - stop + * 4 - standby + * duty (optional): + * 0 - 100% (100% by default) +\*********************************************************************************************/ + +#define XDRV_34 34 +#define XI2C_43 43 // See I2CDEVICES.md + +#define MOTOR_A 0 +#define MOTOR_B 1 + +#define SHORT_BRAKE 0 +#define CCW 1 +#define CW 2 +#define STOP 3 +#define STANDBY 4 + +bool wemos_driver_detected = false; + +uint8_t _motor; + +void Wemos_Driver_Detect(void) +{ + if (!I2cActive(USE_WEMOS_MOTOR_V1_ADDR)) + { + I2cSetActiveFound(USE_WEMOS_MOTOR_V1_ADDR, "WEMOS_MOTOR_V1"); + wemos_driver_detected = true; + Motor_Reset(); + return; + } +} + +void Motor_Reset(void) +{ + Wire.begin(); + Motor_SetFreq(USE_WEMOS_MOTOR_V1_FREQ); + Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"RESET\":\"OK\"}}")); +} + +void Motor_SetFreq(uint32_t freq) +{ + Wire.beginTransmission(USE_WEMOS_MOTOR_V1_ADDR); + Wire.write(((byte)(freq >> 16)) & (byte)0x0f); + Wire.write((byte)(freq >> 16)); + Wire.write((byte)(freq >> 8)); + Wire.write((byte)freq); + Wire.endTransmission(); // stop transmitting + delay(100); +} + +void Motor_SetMotor(uint8_t motor, uint8_t dir, float pwm_val) +{ + uint16_t _pwm_val; + Wire.beginTransmission(USE_WEMOS_MOTOR_V1_ADDR); + Wire.write(motor | (byte)0x10); + Wire.write(dir); + + _pwm_val = uint16_t(pwm_val * 100); + + if (_pwm_val > 10000) + _pwm_val = 10000; + + Wire.write((byte)(_pwm_val >> 8)); + Wire.write((byte)_pwm_val); + Wire.endTransmission(); + + delay(100); + + Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"SETMOTOR\":\"OK\"}}")); +} + +bool Motor_Command(void) +{ + uint8_t args_count = 0; + if (XdrvMailbox.data_len > 0) + { + args_count = 1; + } + else + { + return false; + } + + for (uint32_t idx = 0; idx < XdrvMailbox.data_len; idx++) + { + if (' ' == XdrvMailbox.data[idx]) + { + XdrvMailbox.data[idx] = ','; + } + if (',' == XdrvMailbox.data[idx]) + { + args_count++; + } + } + UpperCase(XdrvMailbox.data, XdrvMailbox.data); + + char *command = strtok(XdrvMailbox.data, ","); + + if (strcmp(command, "RESET") == 0) + { + Motor_Reset(); + return true; + } + + if (strcmp(command, "SETMOTOR") == 0) + { + if (args_count >= 3) + { + + int motor = atoi(strtok(NULL, ",")); + int dir = atoi(strtok(NULL, ",")); + int duty = 100; + + if (args_count == 4) + { + duty = atoi(strtok(NULL, ",")); + } + + Motor_SetMotor(motor, dir, duty); + + return true; + } + } + return false; +} + +bool Xdrv34(uint8_t function) +{ + if (!I2cEnabled(XI2C_43)) + { + return false; + } + bool result = false; + if (FUNC_INIT == function) + { + Wemos_Driver_Detect(); + result = wemos_driver_detected; + } + else if (wemos_driver_detected) + { + if (FUNC_COMMAND_DRIVER == function && XI2C_43 == XdrvMailbox.index) + { + result = Motor_Command(); + } + } + return result; +} + +#endif // USE_WEMOS_MOTOR_V1 +#endif // USE_IC2 From 5e4d8e5641936f58bc448d36444a63a70266c984 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 20 Feb 2020 10:07:00 +0100 Subject: [PATCH 440/559] Fix relation between RSSI and signal strength Fix relation between RSSI and signal strength --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/support.ino | 3 ++- tasmota/support_tasmota.ino | 3 ++- tasmota/xdrv_01_webserver.ino | 10 ++++++---- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5ec616909..781913f39 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -75,6 +75,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix PWM flickering at low levels (#7415) - Fix Hass sensor discovery part 1/4 by Federico Leoni (#7582, #7548) - Fix MaxPower functionality (#7647) +- Fix relation between RSSI and signal strength - Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 - Add command ``SetOption84 1`` to send AWS IoT device shadow updates (alternative to retained) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index ff2a178f6..cf1679ad0 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Change MQTT message size with additional 200 characters - Change some wifi code to attempt faster connection (#7621) - Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" +- Fix relation between RSSI and signal strength - Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717) ### 8.1.0.7 20200210 diff --git a/tasmota/support.ino b/tasmota/support.ino index 336774105..ed2cea4c1 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -51,7 +51,8 @@ void OsWatchTicker(void) uint32_t last_run = abs(t - oswatch_last_loop_time); #ifdef DEBUG_THEO - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), last_run); + int32_t rssi = WiFi.RSSI(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(rssi), rssi, last_run); #endif // DEBUG_THEO if (last_run >= (OSWATCH_RESET_TIME * 1000)) { // AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_OSWATCH " " D_BLOCKED_LOOP ". " D_RESTARTING)); // Save iram space diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 888893fea..1ea7f631d 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -647,9 +647,10 @@ void MqttShowState(void) MqttShowPWMState(); } + int32_t rssi = WiFi.RSSI(); ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(), - WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str()); + WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str()); } void MqttPublishTeleState(void) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index fc143f73a..29eece8d4 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1719,16 +1719,17 @@ void HandleWifiConfiguration(void) //display networks in page for (uint32_t i = 0; i < n; i++) { if (-1 == indices[i]) { continue; } // skip dups + int32_t rssi = WiFi.RSSI(indices[i]) DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), - WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), WiFi.RSSI(indices[i])); - int quality = WifiGetRssiAsQuality(WiFi.RSSI(indices[i])); + WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), rssi); + int quality = WifiGetRssiAsQuality(rssi); int auth = WiFi.encryptionType(indices[i]); char encryption[20]; WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), HtmlEscape(WiFi.SSID(indices[i])).c_str(), WiFi.channel(indices[i]), GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality, WiFi.RSSI(indices[i]) + quality, rssi ); delay(0); @@ -2067,7 +2068,8 @@ void HandleInformation(void) WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsText(SET_FRIENDLYNAME1 +i)); } WSContentSend_P(PSTR("}1}2 ")); // Empty line - WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.RSSI()); + int32_t rssi = WiFi.RSSI(); + WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(rssi), rssi); WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Wifi.mdns_begun) ? ".local" : ""); #if LWIP_IPV6 String ipv6_addr = WifiGetIPv6(); From 9b1fc4342bd1262d71d6a406e99374d5e6548bd5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 20 Feb 2020 11:24:35 +0100 Subject: [PATCH 441/559] Revert wifi connectivity stability introduced in 8.1.0.5 Revert wifi connectivity stability introduced in 8.1.0.5 (#7746, #7602, #7621) --- RELEASENOTES.md | 4 +- tasmota/CHANGELOG.md | 4 ++ tasmota/support_wifi.ino | 82 +++++++++------------------------------ tasmota/tasmota_version.h | 2 +- 4 files changed, 25 insertions(+), 67 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 781913f39..c22a4c59d 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,14 +52,12 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.1.0.8 +### Version 8.1.0.9 - Change Lights: simplified gamma correction and 10 bits internal computation - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items - Change IRremoteESP8266 library updated to v2.7.3 - Change Zigbee command prefix from ``Zigbee*`` to ``Zb*`` -- Change wifi connectivity stability (#7602) -- Change some wifi code to attempt faster connection (#7621) - Change MQTT message size with additional 200 characters - Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index cf1679ad0..186ff457e 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 8.1.0.9 20200220 + +- Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) + ### 8.1.0.8 20200212 - Change MQTT message size with additional 200 characters diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 376e7c6b1..df509b9d3 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -22,17 +22,14 @@ \*********************************************************************************************/ #ifndef WIFI_RSSI_THRESHOLD -// Decrease the roam threshold from 10 to 5 to address devices connecting at very low RSSI and being close to inoperative -#define WIFI_RSSI_THRESHOLD 5 // Difference in dB between current network and scanned network +#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network #endif #ifndef WIFI_RESCAN_MINUTES -// Increase rescan interval from 44 to 5 minutes to improve ability for devices to reach network harmony -#define WIFI_RESCAN_MINUTES 5 // Number of minutes between wifi network rescan +#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan #endif const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart -// Drop from 20 seconds to 5 seconds since we control the reconnections, not the Arduino SDK -const uint8_t WIFI_CHECK_SEC = 5; // seconds +const uint8_t WIFI_CHECK_SEC = 20; // seconds const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds #include // Wifi, MQTT, Ota, WifiManager @@ -52,8 +49,7 @@ struct WIFI { uint8_t config_counter = 0; uint8_t mdns_begun = 0; // mDNS active uint8_t scan_state; - uint8_t bssid[6] = {0}; - uint8_t bssid_last[6] = {0}; // store the last connect bssid + uint8_t bssid[6]; int8_t best_network_db; } Wifi; @@ -187,11 +183,7 @@ void WifiBegin(uint8_t flag, uint8_t channel) // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11N) { WiFi.setPhyMode(WIFI_PHY_MODE_11N); } // B/G/N // if (WiFi.getPhyMode() != WIFI_PHY_MODE_11G) { WiFi.setPhyMode(WIFI_PHY_MODE_11G); } // B/G if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } - - // Handle the reconnection in WifiCheckIp() since the autoreconnect keeps sending deauthentication messages which causes the AP to block traffic as it looks like an DoS attack - // This needs to be explicitly called as "false" otherwise the default is enabled -// WiFi.setAutoReconnect(false); // See #7621 - +// WiFi.setAutoReconnect(true); switch (flag) { case 0: // AP1 case 1: // AP2 @@ -249,7 +241,7 @@ void WifiBeginAfterScan(void) if (2 == Wifi.scan_state) { uint8_t* bssid = WiFi.BSSID(); // Get current bssid memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid)); - Wifi.best_network_db = WiFi.RSSI(); // Get current rssi and add threshold + Wifi.best_network_db = WiFi.RSSI(); // Get current rssi and add threshold if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) { Wifi.best_network_db += WIFI_RSSI_THRESHOLD; } @@ -273,12 +265,6 @@ void WifiBeginAfterScan(void) } // Scan done if (5 == Wifi.scan_state) { - uint32_t number_known = 0; // count the number of known AP's so we can clear the Wifi.bssid_last if there is only one - int32_t channel_max = 0; // No scan result - int8_t ap_max = 3; // AP default if not found - uint8_t bssid_max[6]; // Save last bssid - memcpy((void*) &bssid_max, (void*) &Wifi.bssid, sizeof(bssid_max)); // store the strongest bssid - int32_t channel = 0; // No scan result int8_t ap = 3; // AP default if not found uint8_t last_bssid[6]; // Save last bssid @@ -302,25 +288,12 @@ void WifiBeginAfterScan(void) for (j = 0; j < MAX_SSIDS; j++) { if (ssid_scan == SettingsText(SET_STASSID1 + j)) { // SSID match known = true; - number_known++; if (rssi_scan > Wifi.best_network_db) { // Best network if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { // Check for passphrase if not open wlan - // store the max values in case there is only one AP and we need to try to reconnect - memcpy((void*) &bssid_max, (void*) bssid_scan, sizeof(bssid_max)); - channel_max = chan_scan; - ap_max = j; - // if the bssid is not the same as the last failed attempt, force picking the next strongest AP to prevent getting stuck on a strong RSSI, but poor channel health - for (uint32_t i = 0; i < sizeof(Wifi.bssid_last); i++) { - if (bssid_scan[i] != Wifi.bssid_last[i]) { - Wifi.best_network_db = (int8_t)rssi_scan; - channel = chan_scan; - ap = j; // AP1 or AP2 - memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); - // save the last bssid used - memcpy((void*) &Wifi.bssid_last, (void*) bssid_scan, sizeof(Wifi.bssid_last)); - break; - } - } + Wifi.best_network_db = (int8_t)rssi_scan; + channel = chan_scan; + ap = j; // AP1 or AP2 + memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); } } break; @@ -340,16 +313,6 @@ void WifiBeginAfterScan(void) WiFi.scanDelete(); // Clean up Ram delay(0); } - - // reset the last bssid if there is only one AP to allow the reconnect of the same AP on the next cycle - if (number_known == 1) { - // clear the last value - memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last)); - memcpy((void*) &Wifi.bssid, (void*) bssid_max, sizeof(Wifi.bssid)); - channel = channel_max; - ap = ap_max; - } - Wifi.scan_state = 0; // If bssid changed then (re)connect wifi for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) { @@ -424,13 +387,15 @@ void WifiCheckIp(void) #else if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { #endif // LWIP_IPV6=1 - // initialize the last connect bssid since we had a successful connection - memset((void*) &Wifi.bssid_last, 0, sizeof(Wifi.bssid_last)); WifiSetState(1); Wifi.counter = WIFI_CHECK_SEC; Wifi.retry = Wifi.retry_init; if (Wifi.status != WL_CONNECTED) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECTED)); +// AddLog_P(LOG_LEVEL_INFO, PSTR("Wifi: Set IP addresses")); + Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP(); + Settings.ip_address[2] = (uint32_t)WiFi.subnetMask(); + Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); } Wifi.status = WL_CONNECTED; #ifdef USE_DISCOVERY @@ -448,13 +413,11 @@ void WifiCheckIp(void) switch (Wifi.status) { case WL_CONNECTED: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS)); - // if poor channel health prevents DHCP broadcast from succeeding, restart the request - // The code will eventually do a recoonect when the 1/2 interval is hit to try another access point if this remains unsuccessful - wifi_station_dhcpc_start(); + Wifi.status = 0; + Wifi.retry = Wifi.retry_init; break; case WL_NO_SSID_AVAIL: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED)); - if (WIFI_WAIT == Settings.sta_config) { Wifi.retry = Wifi.retry_init; } else { @@ -465,21 +428,17 @@ void WifiCheckIp(void) Wifi.retry = 0; } } - break; case WL_CONNECT_FAILED: AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD)); - if (Wifi.retry > (Wifi.retry_init / 2)) { Wifi.retry = Wifi.retry_init / 2; } else if (Wifi.retry) { Wifi.retry = 0; } - break; default: // WL_IDLE_STATUS and WL_DISCONNECTED - // log on the 1/2 or full interval if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); } else { @@ -491,11 +450,9 @@ void WifiCheckIp(void) } } } - if (Wifi.retry) { if (Settings.flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's - // check the 1/2 interval as well when rescanning - scan state machine takes 4 seconds - if ((Wifi.retry_init == Wifi.retry) || ((Wifi.retry_init / 2) == Wifi.retry)){ + if (Wifi.retry_init == Wifi.retry) { Wifi.scan_state = 1; // Select scanned SSID } } else { @@ -642,6 +599,7 @@ String WifiGetOutputPower(void) dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); return String(stemp1); } + void WifiSetOutputPower(void) { WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); @@ -653,9 +611,7 @@ void WifiConnect(void) WifiSetOutputPower(); WiFi.persistent(false); // Solve possible wifi init errors Wifi.status = 0; - // lower the rety times now Tasmota control the reconnections, not the Arduino SDK - // Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP.getChipId() & 0xF); + Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); Wifi.retry = Wifi.retry_init; Wifi.counter = 1; } diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index d0db39f4b..b1e4eba9f 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08010008; +const uint32_t VERSION = 0x08010009; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; From f674feb0ef0950c46a132be6e509251f0f181d98 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 20 Feb 2020 13:38:03 +0100 Subject: [PATCH 442/559] Add initial support for Sensors AHT1x Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) --- tasmota/CHANGELOG.md | 1 + tasmota/tasmota_post.h | 1 + tasmota/xsns_63_aht1x.ino | 88 +++++++++++++++++++-------------------- tools/decode-status.py | 4 +- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 186ff457e..2689a7222 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.1.0.9 20200220 - Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) +- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) ### 8.1.0.8 20200212 diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 615ff8919..c148efd9f 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -164,6 +164,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack //#define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) //#define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code) #define USE_HIH6 // Enable Honywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) +//#define USE_AHT1x // Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code) #define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) #define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) diff --git a/tasmota/xsns_63_aht1x.ino b/tasmota/xsns_63_aht1x.ino index b3b17e0e4..542cb72ea 100644 --- a/tasmota/xsns_63_aht1x.ino +++ b/tasmota/xsns_63_aht1x.ino @@ -30,10 +30,10 @@ #define AHT10_ADDR 0x38 -unsigned char eSensorCalibrateCmd[3] = {0xE1, 0x08, 0x00}; -unsigned char eSensorNormalCmd[3] = {0xA8, 0x00, 0x00}; -unsigned char eSensorMeasureCmd[3] = {0xAC, 0x33, 0x00}; -unsigned char eSensorResetCmd = 0xBA; +uint8_t eSensorCalibrateCmd[3] = {0xE1, 0x08, 0x00}; +uint8_t eSensorNormalCmd[3] = {0xA8, 0x00, 0x00}; +uint8_t eSensorMeasureCmd[3] = {0xAC, 0x33, 0x00}; +uint8_t eSensorResetCmd = 0xBA; struct AHT10 { float humidity = NAN; @@ -43,75 +43,73 @@ struct AHT10 { char name[6] = "AHT1x"; } AHT10; - bool AHT10Read(void) { - unsigned long result_t, result_h, data[6]; - if (AHT10.valid) { AHT10.valid--; } - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorMeasureCmd, 3); - Wire.endTransmission(); - delay(100); + uint8_t data[6]; - Wire.requestFrom(AHT10_ADDR, 6); - for(uint8_t i = 0; Wire.available() > 0; i++) - { - data[i] = Wire.read(); - } + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorMeasureCmd, 3); + Wire.endTransmission(); + delay(100); - result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; - result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; + Wire.requestFrom(AHT10_ADDR, 6); + for (uint32_t i = 0; Wire.available() > 0; i++) { + data[i] = Wire.read(); + } - AHT10.humidity = result_h * 100 / 1048576; - AHT10.temperature = ((200 * result_t) / 1048576) - 50; + uint32_t result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; + uint32_t result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; - if (isnan(AHT10.temperature) || isnan(AHT10.humidity)) { return false; } + float humidity = result_h * 100 / 1048576; + float temperature = ((200 * result_t) / 1048576) - 50; + + if (isnan(temperature) || isnan(humidity)) { return false; } + + AHT10.humidity = ConvertHumidity(humidity); + AHT10.temperature = ConvertTemp(temperature); AHT10.valid = SENSOR_MAX_MISS; return true; } /********************************************************************************************/ -bool AHT10Init() -{ - Wire.begin(AHT10_ADDR); - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorCalibrateCmd, 3); - Wire.endTransmission(); - delay(500); - if((AHT10ReadStatus() & 0x68) == 0x08) { - return true;} - else - { return false; } +bool AHT10Init(void) +{ + Wire.begin(AHT10_ADDR); + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorCalibrateCmd, 3); + Wire.endTransmission(); + + delay(500); // ?!?! too long + + return (0x08 == (AHT10ReadStatus() & 0x68)); } -unsigned char AHT10ReadStatus(void) +uint8_t AHT10ReadStatus(void) { - unsigned char result = 0; - Wire.requestFrom(AHT10_ADDR, 1); - result = Wire.read(); - return result; + Wire.requestFrom(AHT10_ADDR, 1); + uint8_t result = Wire.read(); + return result; } void AHT10Reset(void) { - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorResetCmd); - Wire.endTransmission(); - delay(20); + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorResetCmd); + Wire.endTransmission(); + delay(20); } /********************************************************************************************/ + void AHT10Detect(void) { - if (I2cActive(AHT10_ADDR)) - {return;} + if (I2cActive(AHT10_ADDR)) { return; } - if (AHT10Init()) - { + if (AHT10Init()) { I2cSetActiveFound(AHT10_ADDR, AHT10.name); AHT10.count = 1; } diff --git a/tools/decode-status.py b/tools/decode-status.py index f4d00833a..210175de8 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -193,7 +193,7 @@ a_features = [[ "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", "USE_DHT12","USE_DS1624","USE_GPS","USE_HOTPLUG", "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", - "","","","" + "USE_AHT1x","","","" ],[ "","","","", "","","","", @@ -236,7 +236,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200210 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200220 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From e9c7026e823f305802a776004e30f4302cbadab5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 20 Feb 2020 14:55:41 +0100 Subject: [PATCH 443/559] Remove NTP drift information Remove NTP drift information --- tasmota/support_rtc.ino | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index 7af66653a..3b7da8e37 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -47,7 +47,6 @@ struct RTC { uint32_t ntp_time = 0; uint32_t midnight = 0; uint32_t restart_time = 0; - int32_t drift_time = 0; int32_t time_timezone = 0; uint8_t ntp_sync_minute = 0; bool midnight_now = false; @@ -64,11 +63,6 @@ uint32_t LocalTime(void) return Rtc.local_time; } -int32_t DriftTime(void) -{ - return Rtc.drift_time; -} - uint32_t Midnight(void) { return Rtc.midnight; @@ -380,7 +374,6 @@ void RtcSecond(void) Rtc.ntp_time = sntp_get_current_timestamp(); if (Rtc.ntp_time > START_VALID_TIME) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) ntp_force_sync = false; - if (Rtc.utc_time > START_VALID_TIME) { Rtc.drift_time = Rtc.ntp_time - Rtc.utc_time; } Rtc.utc_time = Rtc.ntp_time; Rtc.ntp_sync_minute = 60; // Sync so block further requests if (Rtc.restart_time == 0) { @@ -392,8 +385,8 @@ void RtcSecond(void) Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); // Do not use AddLog_P2 here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9 - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: Drift %d, (" D_UTC_TIME ")%s, (" D_DST_TIME ")%s, (" D_STD_TIME ")%s"), - DriftTime(), GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01 rules_flag.time_init = 1; From ea99cdce5700e87f13218ce2729656b33e2f5cc5 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Thu, 20 Feb 2020 18:50:43 +0100 Subject: [PATCH 444/559] Add support for La Crosse TX23 Anemometer (#3146) --- tasmota/language/bg-BG.h | 2 +- tasmota/language/cs-CZ.h | 2 +- tasmota/language/de-DE.h | 2 +- tasmota/language/el-GR.h | 2 +- tasmota/language/en-GB.h | 2 +- tasmota/language/es-ES.h | 2 +- tasmota/language/fr-FR.h | 2 +- tasmota/language/he-HE.h | 2 +- tasmota/language/hu-HU.h | 2 +- tasmota/language/it-IT.h | 2 +- tasmota/language/ko-KO.h | 2 +- tasmota/language/nl-NL.h | 2 +- tasmota/language/pl-PL.h | 2 +- tasmota/language/pt-BR.h | 2 +- tasmota/language/pt-PT.h | 2 +- tasmota/language/ru-RU.h | 2 +- tasmota/language/sk-SK.h | 2 +- tasmota/language/sv-SE.h | 2 +- tasmota/language/tr-TR.h | 2 +- tasmota/language/uk-UA.h | 2 +- tasmota/language/zh-CN.h | 2 +- tasmota/language/zh-TW.h | 2 +- tasmota/my_user_config.h | 4 +- tasmota/support_features.ino | 2 +- tasmota/tasmota_post.h | 6 +- tasmota/tasmota_template.h | 8 +- tasmota/xsns_35_tx20.ino | 311 +++++++++++++++++++++++------------ 27 files changed, 241 insertions(+), 134 deletions(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 270300bf7..be2fceb3c 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 8c47e47ab..6ef51f27d 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 615020f33..e7e3c6a74 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX20_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index a73651d93..b3608bb7b 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index b9f03bacc..66a6e0243 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 9b0b08888..59916f487 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 455bec483..5356848d8 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RF TX" #define D_SENSOR_RFRECV "RF RX" #define D_SENSOR_TUYA_TX "Tuya TX" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index 009191f54..fa3b07a31 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 65de942cb..541d0c783 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index a8ab6f1c6..62127ef24 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 9607cd9d5..2a20ce2d0 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 6602a7129..658f18547 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 06bf65d06..e2d59a2dc 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index a896196b1..da386917c 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 551f4767e..1f9c36a6b 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index b4708ac10..846a653ac 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index 5427059bc..f335ca42d 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index dea7e0210..9485c1f4e 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 8fc13e0df..ee2a548ae 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index 9365f68e7..98a352ea7 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFRecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 019b679f4..c46d353ea 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 5d7c00069..118aeb501 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index d641ac761..6c4af1e31 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -618,7 +618,9 @@ #define USE_HX711 // Add support for HX711 load cell (+1k5 code) // #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) -//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) +// Select none or only one of the below defines +//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+1k3 code) +//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+1k4 code) //#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 85f5a77ea..ba1a2e465 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -367,7 +367,7 @@ void GetFeatures(void) #ifdef USE_PZEM_DC feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino #endif -#ifdef USE_TX20_WIND_SENSOR +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) feature_sns2 |= 0x00002000; // xsns_35_tx20.ino #endif #ifdef USE_MGC3130 diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index c148efd9f..0d0b65d6e 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -212,7 +212,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) #define USE_HX711 // Add support for HX711 load cell (+1k5 code) //#define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) -//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) +//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+1k3 code) +//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+1k4 code) #define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) @@ -404,6 +405,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) @@ -513,6 +515,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) @@ -625,6 +628,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 #undef USE_HX711 // Disable support for HX711 load cell #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer +#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) #undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index b099eb49b..c4ee7b19d 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -128,7 +128,7 @@ enum UserSelectablePins { GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface GPIO_HX711_SCK, // HX711 Load Cell clock GPIO_HX711_DAT, // HX711 Load Cell data - GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin + GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin GPIO_RFSEND, // RF transmitter GPIO_RFRECV, // RF receiver GPIO_TUYA_TX, // Tuya Serial interface @@ -267,7 +267,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|" D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|" D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|" - D_SENSOR_TX20_TX "|" + D_SENSOR_TX2X_TX "|" D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|" D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|" D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET "|" @@ -721,8 +721,8 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_PMS5003 GPIO_PMS5003, // Plantower PMS5003 Serial interface #endif -#ifdef USE_TX20_WIND_SENSOR - GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) + GPIO_TX2X_TXD_BLACK, // TX20/TX23 Transmission Pin #endif #ifdef USE_MP3_PLAYER GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface diff --git a/tasmota/xsns_35_tx20.ino b/tasmota/xsns_35_tx20.ino index 0c61392bc..850c7deda 100644 --- a/tasmota/xsns_35_tx20.ino +++ b/tasmota/xsns_35_tx20.ino @@ -1,7 +1,7 @@ /* - xsns_35_Tx20.ino - La Crosse Tx20 wind sensor support for Tasmota + xsns_35_Tx20.ino - La Crosse Tx20/Tx23 wind sensor support for Tasmota - Copyright (C) 2020 Thomas Eckerstorfer and Theo Arends + Copyright (C) 2020 Thomas Eckerstorfer, Norbert Richter and Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,19 +17,31 @@ along with this program. If not, see . */ -#ifdef USE_TX20_WIND_SENSOR +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) +#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR) +#undef USE_TX20_WIND_SENSOR +#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled **** +#endif /*********************************************************************************************\ - * La Crosse Tx20 wind sensor + * La Crosse TX20/TX23 Anemometer * * based on https://github.com/bunnyhu/ESP8266_TX20_wind_sensor/ * http://blog.bubux.de/windsensor-tx20-mit-esp8266/ * https://www.john.geek.nz/2011/07/la-crosse-tx20-anemometer-communication-protocol/ + * http://www.rd-1000.com/chpm78/lacrosse/Lacrosse_TX23_protocol.html + * https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/ + * + * TX23 RJ11 connection: + * 1 yellow - GND + * 2 green - NC + * 3 red - Vcc 3.3V + * 4 black/brown - TxD Signal (GPIOxx) \*********************************************************************************************/ #define XSNS_35 35 -#define TX20_BIT_TIME 1220 // microseconds -#define TX20_RESET_VALUES 60 // seconds +#define TX2X_BIT_TIME 1220 // microseconds +#define TX2X_RESET_VALUES 60 // seconds // The Arduino standard GPIO routines are not enough, // must use some from the Espressif SDK as well @@ -37,17 +49,21 @@ extern "C" { #include "gpio.h" } +#ifdef USE_TX20_WIND_SENSOR + #define D_TX2x_NAME "TX20" +#else + #define D_TX2x_NAME "TX23" +#endif + #ifdef USE_WEBSERVER - -const char HTTP_SNS_TX20[] PROGMEM = - "{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}TX20 " D_TX20_WIND_DIRECTION "{m}%s{e}"; - +const char HTTP_SNS_TX2X[] PROGMEM = + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s (%s°){e}"; #endif // USE_WEBSERVER -const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" +const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" D_TX20_NORTH D_TX20_EAST "|" D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" @@ -64,133 +80,218 @@ const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" D_TX20_NORTH D_TX20_WEST "|" D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; -uint8_t tx20_sa = 0; -uint8_t tx20_sb = 0; -uint8_t tx20_sd = 0; -uint8_t tx20_se = 0; -uint16_t tx20_sc = 0; -uint16_t tx20_sf = 0; +uint8_t tx2x_sa = 0; +uint8_t tx2x_sb = 0; +uint8_t tx2x_sd = 0; +uint8_t tx2x_se = 0; +uint16_t tx2x_sc = 0; +uint16_t tx2x_sf = 0; -float tx20_wind_speed_kmh = 0; -float tx20_wind_speed_max = 0; -float tx20_wind_speed_avg = 0; -float tx20_wind_sum = 0; -int tx20_count = 0; -uint8_t tx20_wind_direction = 0; +float tx2x_wind_speed_kmh = 0; +float tx2x_wind_speed_max = 0; +float tx2x_wind_speed_avg = 0; +float tx2x_wind_sum = 0; +int tx2x_count = 0; +uint8_t tx2x_wind_direction = 0; -bool tx20_available = false; +bool tx2x_available = false; + +#ifdef USE_TX23_WIND_SENSOR +uint8_t tx23_stage = 0; +#endif #ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception -void Tx20StartRead(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too +void TX2xStartRead(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too #endif // ARDUINO_ESP8266_RELEASE_2_3_0 -void Tx20StartRead(void) +void TX2xStartRead(void) { - /* La Crosse TX20 Anemometer datagram every 2 seconds + /** + * La Crosse TX20 Anemometer datagram every 2 seconds * 0-0 11011 0011 111010101111 0101 1100 000101010000 0-0 - Received pin data at 1200 uSec per bit * sa sb sc sd se sf * 00100 1100 000101010000 1010 1100 000101010000 - sa to sd inverted user data, LSB first - * sa - Start frame always 00100 + * sa - Start frame (invert) 00100 + * sb - Wind direction (invert) 0 - 15 + * sc - Wind speed 0 (invert) - 511 + * sd - Checksum (invert) + * se - Wind direction 0 - 15 + * sf - Wind speed 0 - 511 + * + * La Crosse TX23 Anemometer datagram after setting TxD to low/high + * 1-1 0 1 0-0 11011 0011 111010101111 0101 1100 000101010000 1-1 - Received pin data at 1200 uSec per bit + * t s c sa sb sc sd se sf + * 1 0 1-1 00100 1100 000101010000 1010 1100 000101010000 - sa to sd inverted user data, LSB first + * t - host pulls TxD low - signals TX23 to sent measurement + * s - TxD released - TxD is pulled high due to pullup + * c - TX23U pulls TxD low - calculation in progress + * sa - Start frame 11011 * sb - Wind direction 0 - 15 * sc - Wind speed 0 - 511 * sd - Checksum - * se - Wind direction 0 - 15 - * sf - Wind speed 0 - 511 + * se - Wind direction (invert) 0 - 15 + * sf - Wind speed (invert) 0 - 511 */ +#ifdef USE_TX23_WIND_SENSOR + if (0!=tx23_stage) + { + if ((2==tx23_stage) || (3==tx23_stage)) + { +#endif + tx2x_available = false; - tx20_available = false; + tx2x_sa = 0; + tx2x_sb = 0; + tx2x_sd = 0; + tx2x_se = 0; + tx2x_sc = 0; + tx2x_sf = 0; - tx20_sa = 0; - tx20_sb = 0; - tx20_sd = 0; - tx20_se = 0; - tx20_sc = 0; - tx20_sf = 0; + delayMicroseconds(TX2X_BIT_TIME / 2); - delayMicroseconds(TX20_BIT_TIME / 2); + for (int32_t bitcount = 41; bitcount > 0; bitcount--) { + uint8_t dpin = (digitalRead(pin[GPIO_TX2X_TXD_BLACK])); +#ifdef USE_TX23_WIND_SENSOR + if (bitcount > 41 - 5) { + // start + tx2x_sa = (tx2x_sa << 1) | (dpin); + } else if (bitcount > 41 - 5 - 4) { + // wind dir + tx2x_sb = tx2x_sb >> 1 | ((dpin) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + // windspeed + tx2x_sc = tx2x_sc >> 1 | ((dpin) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + // checksum + tx2x_sd = tx2x_sd >> 1 | ((dpin) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + // wind dir (invert) + tx2x_se = tx2x_se >> 1 | ((dpin ^ 1) << 3); + } else { + // windspeed (invert) + tx2x_sf = tx2x_sf >> 1 | ((dpin ^ 1) << 11); + } +#else + if (bitcount > 41 - 5) { + // start frame (invert) + tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1); + } else if (bitcount > 41 - 5 - 4) { + // wind dir (invert) + tx2x_sb = tx2x_sb >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + // windspeed (invert) + tx2x_sc = tx2x_sc >> 1 | ((dpin ^ 1) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + // checksum (invert) + tx2x_sd = tx2x_sd >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + // wind dir + tx2x_se = tx2x_se >> 1 | (dpin << 3); + } else { + // windspeed + tx2x_sf = tx2x_sf >> 1 | (dpin << 11); + } +#endif + delayMicroseconds(TX2X_BIT_TIME); + } - for (int32_t bitcount = 41; bitcount > 0; bitcount--) { - uint8_t dpin = (digitalRead(pin[GPIO_TX20_TXD_BLACK])); - if (bitcount > 41 - 5) { - // start, inverted - tx20_sa = (tx20_sa << 1) | (dpin ^ 1); - } else if (bitcount > 41 - 5 - 4) { - // wind dir, inverted - tx20_sb = tx20_sb >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12) { - // windspeed, inverted - tx20_sc = tx20_sc >> 1 | ((dpin ^ 1) << 11); - } else if (bitcount > 41 - 5 - 4 - 12 - 4) { - // checksum, inverted - tx20_sd = tx20_sd >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { - // wind dir - tx20_se = tx20_se >> 1 | (dpin << 3); - } else { - // windspeed - tx20_sf = tx20_sf >> 1 | (dpin << 11); + uint8_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); + chk &= 0xf; + +#ifdef USE_TX23_WIND_SENSOR + // check checksum, non-inverted with inverted values and max. speed + if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { + tx2x_available = true; + } +#else + if ((chk == tx2x_sd) && (tx2x_sc < 511)) { // if checksum seems to be ok and wind speed below 51.1 m/s + tx2x_available = true; + } +#endif +#ifdef USE_TX23_WIND_SENSOR } - - delayMicroseconds(TX20_BIT_TIME); + tx23_stage++; } +#endif - uint8_t chk = (tx20_sb + (tx20_sc & 0xf) + ((tx20_sc >> 4) & 0xf) + ((tx20_sc >> 8) & 0xf)); - chk &= 0xf; - - if ((chk == tx20_sd) && (tx20_sc < 400)) { // if checksum seems to be ok and wind speed below 40 m/s - tx20_available = true; - } -/* - if ((tx20_sb == tx20_se) && (tx20_sc == tx20_sf) && (tx20_sc < 400)) { - tx20_available = true; - } -*/ // Must clear this bit in the interrupt register, // it gets set even when interrupts are disabled - GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]); + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX2X_TXD_BLACK]); } -void Tx20Read(void) +void Tx2xReset(void) { - if (!(uptime % TX20_RESET_VALUES)) { - tx20_count = 0; - tx20_wind_sum = 0; - tx20_wind_speed_max = 0; + tx2x_count = 0; + tx2x_wind_sum = 0; + tx2x_wind_speed_max = 0; +} + +void Tx2xRead(void) +{ +#ifdef USE_TX23_WIND_SENSOR + // note: TX23 speed calculation is unstable when conversion starts + // less than 2 seconds after last request + if ((uptime % 3)==0) { + // TX23 start transmission by pulling down TxD line for at minimum 500ms + // so we pull TxD signal to low every 3 seconds + tx23_stage = 0; + pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); + digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); + } else if ((uptime % 3)==1) { + // after pulling down TxD every 3 second we pull-up TxD every 3+1 seconds + // to trigger start transmission + tx23_stage = 1; // first rising signal is invalid + pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT_PULLUP); } - else if (tx20_available) { - tx20_wind_speed_kmh = float(tx20_sc) * 0.36; - if (tx20_wind_speed_kmh > tx20_wind_speed_max) { - tx20_wind_speed_max = tx20_wind_speed_kmh; +#endif + if (0==Settings.tele_period && !(uptime % TX2X_RESET_VALUES)) { + Tx2xReset(); + } + else if (tx2x_available) { + // Wind speed spec: 0 to 180 km/h (0 to 50 m/s) + tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36; + if (tx2x_wind_speed_kmh > tx2x_wind_speed_max) { + tx2x_wind_speed_max = tx2x_wind_speed_kmh; } - tx20_count++; - tx20_wind_sum += tx20_wind_speed_kmh; - tx20_wind_speed_avg = tx20_wind_sum / tx20_count; - tx20_wind_direction = tx20_sb; + tx2x_count++; + tx2x_wind_sum += tx2x_wind_speed_kmh; + tx2x_wind_speed_avg = tx2x_wind_sum / tx2x_count; + tx2x_wind_direction = tx2x_sb; } } -void Tx20Init(void) { - pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); - attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); +void Tx2xInit(void) +{ +#ifdef USE_TX23_WIND_SENSOR + tx23_stage = 0; + pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); + digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); +#else + pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT); +#endif + attachInterrupt(pin[GPIO_TX2X_TXD_BLACK], TX2xStartRead, RISING); } -void Tx20Show(bool json) +void Tx2xShow(bool json) { char wind_speed_string[33]; - dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); + dtostrfd(tx2x_wind_speed_kmh, 1, wind_speed_string); char wind_speed_max_string[33]; - dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); + dtostrfd(tx2x_wind_speed_max, 1, wind_speed_max_string); char wind_speed_avg_string[33]; - dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); + dtostrfd(tx2x_wind_speed_avg, 1, wind_speed_avg_string); char wind_direction_string[4]; - GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); + GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx2x_wind_direction, kTx2xDirections); + char wind_direction_degree[33]; + dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_degree); if (json) { - ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), - wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), + wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); + Tx2xReset(); #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); + WSContentSend_PD(HTTP_SNS_TX2X, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); #endif // USE_WEBSERVER } } @@ -203,20 +304,20 @@ bool Xsns35(uint8_t function) { bool result = false; - if (pin[GPIO_TX20_TXD_BLACK] < 99) { + if (pin[GPIO_TX2X_TXD_BLACK] < 99) { switch (function) { case FUNC_INIT: - Tx20Init(); + Tx2xInit(); break; case FUNC_EVERY_SECOND: - Tx20Read(); + Tx2xRead(); break; case FUNC_JSON_APPEND: - Tx20Show(1); + Tx2xShow(1); break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: - Tx20Show(0); + Tx2xShow(0); break; #endif // USE_WEBSERVER } @@ -224,4 +325,4 @@ bool Xsns35(uint8_t function) return result; } -#endif // USE_TX20_WIND_SENSOR \ No newline at end of file +#endif // USE_TX20_WIND_SENSOR || USE_TX23_WIND_SENSOR \ No newline at end of file From a912daff0ba4057f199b37b8721c7bb4b42d9c3e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 20 Feb 2020 21:07:58 +0100 Subject: [PATCH 445/559] Update de-DE.h --- tasmota/language/de-DE.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index e7e3c6a74..cf2aa258b 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -564,7 +564,7 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" -#define D_SENSOR_TX20_TX "TX2x" +#define D_SENSOR_TX2X_TX "TX2x" #define D_SENSOR_RFSEND "RFSend" #define D_SENSOR_RFRECV "RFrecv" #define D_SENSOR_TUYA_TX "Tuya Tx" From f409d7258e88efb35bce7bd8b3337df8e89a8574 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Fri, 21 Feb 2020 09:09:21 -0600 Subject: [PATCH 446/559] Initial device groups support (power and light) --- tasmota/i18n.h | 1 + tasmota/my_user_config.h | 1 + tasmota/settings.h | 5 + tasmota/support_command.ino | 17 + tasmota/support_device_groups.ino | 716 ++++++++++++++++++++++++++++++ tasmota/support_tasmota.ino | 3 + tasmota/support_udp.ino | 64 +-- tasmota/support_wifi.ino | 6 +- tasmota/tasmota.h | 27 +- tasmota/tasmota.ino | 6 + tasmota/tasmota_post.h | 11 + tasmota/xdrv_01_webserver.ino | 4 + tasmota/xdrv_02_mqtt.ino | 7 + tasmota/xdrv_04_light.ino | 98 ++++ 14 files changed, 936 insertions(+), 30 deletions(-) create mode 100644 tasmota/support_device_groups.ino diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 00cda53b4..cb9bb1196 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -289,6 +289,7 @@ #define D_CMND_WIFIPOWER "WifiPower" #define D_CMND_I2CSCAN "I2CScan" #define D_CMND_I2CDRIVER "I2CDriver" +#define D_CMND_DEVGROUP_SHARE "DevGroupShare" #define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALDELIMITER "SerialDelimiter" #define D_CMND_BAUDRATE "Baudrate" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 67ab1cf1c..406fd19af 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -415,6 +415,7 @@ //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug +// #define USE_DEVICE_GROUPS // Add support for device groups (+4k code) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/settings.h b/tasmota/settings.h index b1afca3ea..972af6974 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -573,4 +573,9 @@ typedef union { ADC_MODE(ADC_VCC); // Set ADC input for Power Supply Voltage usage #endif +// Settings re-purposed for device groups +#define device_groups_enabled ws_clock_reverse // SetOption16 - Enable device groups +#define device_group_share_in domoticz_sensor_idx[0] // Bitmask of device group items imported +#define device_group_share_out domoticz_sensor_idx[1] // Bitmask of device group items exported + #endif // _SETTINGS_H_ diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index df5abda86..b4c575e31 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -30,6 +30,9 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif +#ifdef USE_DEVICE_GROUPS + D_CMND_DEVGROUP_SHARE "|" +#endif // USE_DEVICE_GROUPS D_CMND_SENSOR "|" D_CMND_DRIVER; void (* const TasmotaCommand[])(void) PROGMEM = { @@ -45,6 +48,9 @@ void (* const TasmotaCommand[])(void) PROGMEM = { #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif +#ifdef USE_DEVICE_GROUPS + &CmndDevGroupShare, +#endif // USE_DEVICE_GROUPS &CmndSensor, &CmndDriver }; const char kWifiConfig[] PROGMEM = @@ -1664,6 +1670,17 @@ void CmndI2cDriver(void) } #endif // USE_I2C +#ifdef USE_DEVICE_GROUPS +void CmndDevGroupShare(void) +{ + uint32_t parm[2] = { Settings.device_group_share_in, Settings.device_group_share_out }; + ParseParameters(2, parm); + Settings.device_group_share_in = parm[0]; + Settings.device_group_share_out = parm[1]; + Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":%d,\"Out\":%d}}"), Settings.device_group_share_in, Settings.device_group_share_out); +} +#endif // USE_DEVICE_GROUPS + void CmndSensor(void) { XsnsCall(FUNC_COMMAND_SENSOR); diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino new file mode 100644 index 000000000..3add948a7 --- /dev/null +++ b/tasmota/support_device_groups.ino @@ -0,0 +1,716 @@ +/* + support_device_groups.ino - device groups support for Tasmota + + Copyright (C) 2020 Paul C Diem + + Device group allow multiple devices to be in a group with power, light + brightness, fade and speed settings and other module-specific settings + kept in sync across all devices in the group. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifdef USE_DEVICE_GROUPS + +//#define DEVICE_GROUPS_DEBUG + +extern bool udp_connected; + +struct device_group_member { + struct device_group_member * flink; + IPAddress ip_address; + uint32_t timeout_time; + uint16_t received_sequence; + uint16_t acked_sequence; +}; + +struct device_group { + uint32_t next_ack_check_time; + power_t power; + uint16_t last_full_status_sequence; + uint16_t message_length; + uint8_t message_header_length; + uint8_t initial_status_requests_remaining; + bool local; + char group_name[TOPSZ]; + char message[128]; + uint8_t group_member_count; + struct device_group_member * device_group_members; +}; + +struct device_group * device_groups; +uint16_t outgoing_sequence = 0; +bool initialized = false; +bool building_status_message = false; +bool processing_remote_device_message = false; +bool waiting_for_acks; +bool udp_was_connected = false; + +void DeviceGroupsInit(void) +{ + /* + Initialize the device information for each device group. The group name is the MQTT group topic. + */ + if (Settings.flag.device_groups_enabled) { + device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); + if (device_groups == nullptr) { + AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: error allocating %u-element device group array", device_group_count); + Settings.flag.device_groups_enabled = false; + return; + } + + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { + struct device_group * device_group = &device_groups[device_group_index]; + strcpy(device_group->group_name, SettingsText((device_group_index == 0 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + device_group_index - 1))); + device_group->message_header_length = sprintf(device_group->message, "%s%s HTTP/1.1\n\n", kDeviceGroupMessage, device_group->group_name); + device_group->last_full_status_sequence = -1; + } + + device_groups[0].local = true; + + // If both in and out shared items masks are 0, assume they're unitialized and initialize them. + if (!Settings.device_group_share_in && !Settings.device_group_share_out) { + Settings.device_group_share_in = Settings.device_group_share_out = 0xff; + } + + initialized = true; + } +} + +char * IPAddressToString(const IPAddress& ip_address) +{ + static char buffer[16]; + sprintf(buffer, "%u.%u.%u.%u", ip_address[0], ip_address[1], ip_address[2], ip_address[3]); + return buffer; +} + +// Return true if we're configured to share the specified item. +bool DeviceGroupItemShared(bool incoming, uint8_t item) +{ + uint8_t mask = 0; + switch (item) { + case DGR_ITEM_LIGHT_BRI: + mask = DGR_SHARE_LIGHT_BRI; + break; + case DGR_ITEM_POWER: + mask = DGR_SHARE_POWER; + break; + case DGR_ITEM_LIGHT_SCHEME: + mask = DGR_SHARE_LIGHT_SCHEME; + break; + case DGR_ITEM_LIGHT_FIXED_COLOR: + case DGR_ITEM_LIGHT_CHANNELS: + mask = DGR_SHARE_LIGHT_COLOR; + break; + case DGR_ITEM_LIGHT_FADE: + case DGR_ITEM_LIGHT_SPEED: + mask = DGR_SHARE_LIGHT_FADE; + break; + case DGR_ITEM_BRI_MIN: + mask = DGR_SHARE_BRI_MIN; + break; + } + return (!mask || ((incoming ? Settings.device_group_share_in : Settings.device_group_share_out) & mask)); +} + +void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * label) +{ + for (int attempt = 1; attempt <= 5; attempt++) { + if (PortUdp.beginPacket(ip, 1900)) { + PortUdp.write(packet, len); + if (PortUdp.endPacket()) return; + } + delay(10); + } + AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: error sending %s packet", label); +} + +void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...) +{ + // If device groups are not enabled, ignore this request. + if (!Settings.flag.device_groups_enabled) return; + + // If UDP is not set up, ignore this request. + if (!udp_connected) return; + + // If we're currently processing a remote device message, ignore this request. + if (processing_remote_device_message) return; + + // Get a pointer to the device information for this device. + device_group * device_group = &device_groups[device_group_index]; + + // If we're still sending initial status requests, ignore this request. + if (device_group->initial_status_requests_remaining) return; + + // A full status request is a request from a remote device for the status of every item we + // control. As long as we're building it, we may as well broadcast the status update to all + // device group members. + char * message_ptr = &device_group->message[device_group->message_header_length]; + if (message_type == DGR_MSGTYP_FULL_STATUS) { + + // Set the flag indicating we're currently building a status message. SendDeviceGroupMessage + // will build but not send messages while this flag is set. + building_status_message = true; + + // Call the drivers to build the status update. + if (!++outgoing_sequence) outgoing_sequence = 1; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "Building device group %s full status packet", device_group->group_name); +#endif // DEVICE_GROUPS_DEBUG + device_group->message_length = 0; + _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); + XdrvMailbox.command_code = DGR_ITEM_STATUS; + XdrvCall(FUNC_DEVICE_GROUP_REQUEST); + building_status_message = false; + + // If we have nothing to share with the other members, restore the message sequence and return. + if (!device_group->message_length) { + if (!--outgoing_sequence) outgoing_sequence = -1; + return; + } + device_group->last_full_status_sequence = outgoing_sequence; + + // Set the status update flag in the outgoing message. + *(message_ptr + 2) |= DGR_FLAG_FULL_STATUS; + } + + else { + bool shared; + uint8_t item; + uint32_t value; + uint8_t * value_ptr; + va_list ap; + +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "Building device group %s packet", device_group->group_name); +#endif // DEVICE_GROUPS_DEBUG + uint16_t original_sequence = outgoing_sequence; + if (!building_status_message && message_type != DGR_MSGTYP_PARTIAL_UPDATE && !++outgoing_sequence) outgoing_sequence = 1; + *message_ptr++ = outgoing_sequence & 0xff; + *message_ptr++ = outgoing_sequence >> 8; + + value = 0; + if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) + value |= DGR_FLAG_MORE_TO_COME; + else if (message_type == DGR_MSGTYP_UPDATE_DIRECT) + value |= DGR_FLAG_DIRECT; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, ">sequence=%u, flags=%u", outgoing_sequence, value); +#endif // DEVICE_GROUPS_DEBUG + *message_ptr++ = value & 0xff; + *message_ptr++ = value >> 8; + char * first_item_ptr = message_ptr; + + // If we're still building this update or all group members haven't acknowledged the previous + // update yet, update the message to include these new updates. First we need to rebuild the + // previous update message to remove any items and their values that are included in this new + // update. + if (device_group->message_length) { + uint8_t item_array[32]; + int item_index = 0; + int kept_item_count = 0; + + // Build an array of all the items in this new update. + va_start(ap, message_type); + while ((item = va_arg(ap, int))) { + item_array[item_index++] = item; + if (item <= DGR_ITEM_MAX_32BIT) + va_arg(ap, int); + else if (item <= DGR_ITEM_MAX_STRING) + va_arg(ap, char *); + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + va_arg(ap, uint8_t *) ; + break; + } + } + } + va_end(ap); + item_array[item_index] = 0; + + // Rebuild the previous update message, removing any items their values that are included in + // this new update. + char * previous_message_ptr = message_ptr; + while (item = *previous_message_ptr++) { + + // Search for this item in the new update. + for (item_index = 0; item_array[item_index]; item_index++) { + if (item_array[item_index] == item) break; + } + + // If this item was found in the new update skip over it and it's value. + if (item_array[item_index]) { + if (item <= DGR_ITEM_MAX_32BIT) { + previous_message_ptr++; + if (item > DGR_ITEM_MAX_8BIT) { + previous_message_ptr++; + if (item > DGR_ITEM_MAX_16BIT) { + previous_message_ptr++; + previous_message_ptr++; + } + } + } + else if (item <= DGR_ITEM_MAX_STRING) + previous_message_ptr += *previous_message_ptr++; + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + previous_message_ptr += 5; + break; + } + } + } + + // If this item was not found in the new udpate, copy it to the new update message. + else { + *message_ptr++ = item; + if (item <= DGR_ITEM_MAX_32BIT) { + *message_ptr++ = *previous_message_ptr++; + if (item > DGR_ITEM_MAX_8BIT) { + *message_ptr++ = *previous_message_ptr++; + if (item > DGR_ITEM_MAX_16BIT) { + *message_ptr++ = *previous_message_ptr++; + *message_ptr++ = *previous_message_ptr++; + } + } + } + else if (item <= DGR_ITEM_MAX_STRING) { + *message_ptr++ = value = *previous_message_ptr++; + memmove(message_ptr, previous_message_ptr, value); + previous_message_ptr += value; + message_ptr += value; + } + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + memmove(message_ptr, previous_message_ptr, 5); + previous_message_ptr += 5; + message_ptr += 5; + break; + } + } + kept_item_count++; + } + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "%u items carried over from previous update", kept_item_count); +#endif // DEVICE_GROUPS_DEBUG + } + + // Itertate through the passed items adding them and their values to the message. + va_start(ap, message_type); + while ((item = va_arg(ap, int))) { + shared = DeviceGroupItemShared(false, item); + if (shared) *message_ptr++ = item; + if (item <= DGR_ITEM_MAX_32BIT) { + value = va_arg(ap, int); + if (shared) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%u", item, value); +#endif // DEVICE_GROUPS_DEBUG + *message_ptr++ = value & 0xff; + if (item > DGR_ITEM_MAX_8BIT) { + value >>= 8; + *message_ptr++ = value & 0xff; + } + if (item > DGR_ITEM_MAX_16BIT) { + value >>= 8; + *message_ptr++ = value & 0xff; + *message_ptr++ = value >> 8; + } + } + } + else if (item <= DGR_ITEM_MAX_STRING) { + value_ptr = va_arg(ap, uint8_t *); + if (shared) { + value = strlen((const char *)value_ptr); +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%s", item, value_ptr); +#endif // DEVICE_GROUPS_DEBUG + *message_ptr++ = value; + memcpy(message_ptr, value_ptr, value); + message_ptr += value; + } + } + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + value_ptr = va_arg(ap, uint8_t *); + if (shared) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%u,%u,%u,%u,%u", item, *value_ptr, *(value_ptr + 1), *(value_ptr + 2), *(value_ptr + 3), *(value_ptr + 4)); +#endif // DEVICE_GROUPS_DEBUG + memmove(message_ptr, value_ptr, 5); + message_ptr += 5; + } + break; + } + } + } + va_end(ap); + + // If there weren't any items added to the message, restore the outgoing message sequence and + // return. + if (message_ptr == first_item_ptr) { + outgoing_sequence = original_sequence; + return; + } + + // Add the EOL item code and calculate the message length. + *message_ptr++ = 0; + device_group->message_length = message_ptr - device_group->message; + + // If there's going to be more items added to this message, return. + if (building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE) return; + } + + // Broadcast the packet. +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: sending %u-byte device group %s packet via broadcast, sequence=%u", device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); +#endif // DEVICE_GROUPS_DEBUG + SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, "Broadcast"); + device_group->next_ack_check_time = millis() + 100; + + if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) { + for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member != nullptr; device_group_member = device_group_member->flink) { + device_group_member->acked_sequence = outgoing_sequence; + } + } + else { + waiting_for_acks = true; + } +} + +void ProcessDeviceGroupMessage(char * packet, int packet_length) +{ + // Make the group name a null-terminated string. + char * message_group_name = packet + sizeof(DEVICE_GROUP_MESSAGE) - 1; + char * message_ptr = strchr(message_group_name, ' '); + if (message_ptr == nullptr) return; + *message_ptr = 0; + + // Search for a device group with the target group name. If one isn't found, return. + struct device_group * device_group; + uint32_t device_group_index = 0; + for (;;) { + device_group = &device_groups[device_group_index]; + if (!strcmp(message_group_name, device_group->group_name)) break; + if (++device_group_index >= device_group_count) return; + } + *message_ptr++ = ' '; + + // Find the group member. If this is a new group member, add it. + IPAddress remote_ip = PortUdp.remoteIP(); + struct device_group_member * * flink = &device_group->device_group_members; + struct device_group_member * device_group_member; + for (;;) { + device_group_member = *flink; + if (!device_group_member) { + device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member)); + if (device_group_member == nullptr) { + AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: error allocating device group member block"); + return; + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: adding member %s (%p)", IPAddressToString(remote_ip), device_group_member); +#endif // DEVICE_GROUPS_DEBUG + device_group_member->ip_address = remote_ip; + *flink = device_group_member; + break; + } + else if (device_group_member->ip_address == remote_ip) { + break; + } + flink = &device_group_member->flink; + } + + // Find the start of the actual message (after the http header). + message_ptr = strstr(message_ptr, "\n\n"); + if (message_ptr == nullptr) return; + message_ptr += 2; + + bool light_fade; + uint16_t flags; + uint16_t item; + uint16_t message_sequence; + int32_t value; + + // Get the message sequence and flags. + if (packet_length - (message_ptr - packet) < 4) goto badmsg; // Malformed message - must be at least 16-bit sequence, 16-bit flags left + message_sequence = *message_ptr++; + message_sequence |= *message_ptr++ << 8; + flags = *message_ptr++; + flags |= *message_ptr++ << 8; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "Received device group %s packet from %s: sequence=%u, flags=%u", device_group->group_name, IPAddressToString(remote_ip), message_sequence, flags); +#endif // DEVICE_GROUPS_DEBUG + + // If this is an ack message, save the message sequence if it's newwer than the last ack we + // received from this member. + if (flags == DGR_FLAG_ACK) { + if (message_sequence > device_group_member->acked_sequence || device_group_member->acked_sequence - message_sequence < 64536) { + device_group_member->acked_sequence = message_sequence; + } + device_group_member->timeout_time = 0; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "acked_sequence != device_group->last_full_status_sequence) { + _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "received_sequence && device_group_member->received_sequence - message_sequence > 64536) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "received_sequence = message_sequence; + + // Set the flag indicating we're currently processing a remote device message. + // SendDeviceGroupMessage will not send messages while this flag is set. + processing_remote_device_message = true; + + /* + XdrvMailbox + bool grpflg + bool usridx + uint16_t command_code Item code + uint32_t index Flags + uint32_t data_len String item value length + int32_t payload Integer item value + char *topic + char *data Pointer to non-integer item value + char *command nullptr + */ + XdrvMailbox.command = nullptr; // Indicates the source is a device group update + XdrvMailbox.index = flags; + light_fade = Settings.light_fade; + if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) Settings.light_fade = false; + + for (;;) { + if (packet_length - (message_ptr - packet) < 1) goto badmsg; // Malformed message + item = *message_ptr++; + if (!item) break; // Done + +#ifdef DEVICE_GROUPS_DEBUG + switch (item) { + case DGR_ITEM_LIGHT_FADE: + case DGR_ITEM_LIGHT_SPEED: + case DGR_ITEM_LIGHT_BRI: + case DGR_ITEM_LIGHT_SCHEME: + case DGR_ITEM_LIGHT_FIXED_COLOR: + case DGR_ITEM_BRI_MIN: + case DGR_ITEM_BRI_PRESET_LOW: + case DGR_ITEM_BRI_PRESET_HIGH: + case DGR_ITEM_BRI_POWER_ON: + case DGR_ITEM_POWER: + case DGR_ITEM_LIGHT_CHANNELS: + break; + default: + AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: ********** invalid item=%u received from device group %s member %s", item, device_group->group_name, IPAddressToString(remote_ip)); + } +#endif // DEVICE_GROUPS_DEBUG + + XdrvMailbox.command_code = item; + if (item <= DGR_ITEM_LAST_32BIT) { + value = *message_ptr++; + if (item > DGR_ITEM_MAX_8BIT) { + value |= *message_ptr++ << 8; + if (item > DGR_ITEM_MAX_16BIT) { + value |= *message_ptr++ << 16; + value |= *message_ptr++ << 24; + } + } + else if (item == DGR_ITEM_LIGHT_FADE) { + light_fade = value; + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "= packet_length - (message_ptr - packet)) goto badmsg; // Malformed message +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "message[device_group->message_header_length]; + if (!++outgoing_sequence) outgoing_sequence = 1; + *message_ptr++ = outgoing_sequence & 0xff; + *message_ptr++ = outgoing_sequence >> 8; + *message_ptr++ = DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST; + *message_ptr++ = 0; + device_group->message_length = message_ptr - device_group->message; + device_group->initial_status_requests_remaining = 5; + device_group->next_ack_check_time = millis() + 2000; + } + + waiting_for_acks = true; + } + + if (waiting_for_acks) { + uint32_t now = millis(); + waiting_for_acks = false; + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { + device_group * device_group = &device_groups[device_group_index]; + if (device_group->next_ack_check_time) { + if (device_group->next_ack_check_time <= now) { + if (device_group->initial_status_requests_remaining) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: sending initial status request for group %s", device_group->group_name); +#endif // DEVICE_GROUPS_DEBUG + if (--device_group->initial_status_requests_remaining) { + SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, "Initial"); + device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; // The reset flag is on only for the first packet - turn it off now + device_group->next_ack_check_time = now + 200; + waiting_for_acks = true; + } + else { + device_group->next_ack_check_time = 0; + _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); + } + } + else { + bool acked = true; + struct device_group_member ** flink = &device_group->device_group_members; + struct device_group_member * device_group_member; + while ((device_group_member = *flink)) { + if (device_group_member->acked_sequence != outgoing_sequence) { + + if (device_group_member->timeout_time && device_group_member->timeout_time < now) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: removing member %s (%p)", IPAddressToString(device_group_member->ip_address), device_group_member); +#endif // DEVICE_GROUPS_DEBUG + *flink = device_group_member->flink; + free(device_group_member); + } + else { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u", device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); +#endif // DEVICE_GROUPS_DEBUG + SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, "Unicast"); + if (!device_group_member->timeout_time) device_group_member->timeout_time = now + 15000; + acked = false; + flink = &device_group_member->flink; + } + } + else { + flink = &device_group_member->flink; + } + } + if (acked) { + device_group->next_ack_check_time = 0; + device_group->message_length = 0; + } + else { + device_group->next_ack_check_time = now + 500; + waiting_for_acks = true; + } + } + } + else { + waiting_for_acks = true; + } + } + } + } + } + else { + udp_was_connected = false; + } +} + +#endif // USE_DEVICE_GROUPS diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 888893fea..a638ef26e 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -541,6 +541,9 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) case POWER_TOGGLE: power ^= mask; } +#ifdef USE_DEVICE_GROUPS + if (SRC_REMOTE != source && SRC_RETRY != source) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, power); +#endif // USE_DEVICE_GROUPS SetDevicePower(power, source); #ifdef USE_DOMOTICZ DomoticzUpdatePowerState(device); diff --git a/tasmota/support_udp.ino b/tasmota/support_udp.ino index 71fb07490..6f1d12c2e 100644 --- a/tasmota/support_udp.ino +++ b/tasmota/support_udp.ino @@ -85,54 +85,62 @@ void PollUdp(void) // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); // Simple Service Discovery Protocol (SSDP) + if (Settings.flag2.emulation) { #ifdef USE_SCRIPT_HUE - if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { + if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { #else - if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { + if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { #endif - udp_response_mutex = true; + udp_response_mutex = true; - udp_remote_ip = PortUdp.remoteIP(); - udp_remote_port = PortUdp.remotePort(); + udp_remote_ip = PortUdp.remoteIP(); + udp_remote_port = PortUdp.remotePort(); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), // udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); - uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); // 1500 - 2200 msec + uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); // 1500 - 2200 msec - LowerCase(packet_buffer, packet_buffer); - RemoveSpace(packet_buffer); + LowerCase(packet_buffer, packet_buffer); + RemoveSpace(packet_buffer); #ifdef USE_EMULATION_WEMO - if (EMUL_WEMO == Settings.flag2.emulation) { - if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { // type1 echo dot 2g, echo 1g's - TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); - return; + if (EMUL_WEMO == Settings.flag2.emulation) { + if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { // type1 echo dot 2g, echo 1g's + TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); + return; + } + else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || // type2 Echo 2g (echo & echo plus) + (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || + (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { + TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); + return; + } } - else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || // type2 Echo 2g (echo & echo plus) - (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || - (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { - TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); - return; - } - } #endif // USE_EMULATION_WEMO #ifdef USE_EMULATION_HUE - if (EMUL_HUE == Settings.flag2.emulation) { - if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || - (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || - (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || - (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { - TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); - return; + if (EMUL_HUE == Settings.flag2.emulation) { + if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || + (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || + (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || + (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { + TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); + return; + } } - } #endif // USE_EMULATION_HUE - udp_response_mutex = false; + udp_response_mutex = false; + continue; + } } +#ifdef USE_DEVICE_GROUPS + if (Settings.flag.device_groups_enabled && !strncmp_P(packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) { + ProcessDeviceGroupMessage(packet_buffer, len); + } +#endif // USE_DEVICE_GROUPS } optimistic_yield(100); } diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 376e7c6b1..47a45ba00 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -602,7 +602,11 @@ void WifiCheck(uint8_t param) StopWebserver(); } #ifdef USE_EMULATION - if (Settings.flag2.emulation) { UdpConnect(); } +#ifdef USE_DEVICE_GROUPS + if (Settings.flag2.emulation || Settings.flag.device_groups_enabled) { UdpConnect(); } +#else // USE_DEVICE_GROUPS + if (Settings.flag2.emulation) { UdpConnect(); } +#endif // USE_DEVICE_GROUPS #endif // USE_EMULATION #endif // USE_WEBSERVER diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 2aa441878..d5db7abb9 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -277,7 +277,8 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FU FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, FUNC_ANY_KEY, FUNC_ENERGY_EVERY_SECOND, FUNC_ENERGY_RESET, FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, - FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER, FUNC_SET_CHANNELS, FUNC_SET_SCHEME, FUNC_HOTPLUG_SCAN}; + FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER, FUNC_SET_CHANNELS, FUNC_SET_SCHEME, FUNC_HOTPLUG_SCAN, + FUNC_DEVICE_GROUP_REQUEST }; enum AddressConfigSteps { ADDR_IDLE, ADDR_RECEIVE, ADDR_SEND }; @@ -299,8 +300,32 @@ enum SettingsTextIndex { SET_OTAURL, SET_FRIENDLYNAME5, SET_FRIENDLYNAME6, SET_FRIENDLYNAME7, SET_FRIENDLYNAME8, SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8, SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16, + SET_MQTT_GRP_TOPIC2, SET_MQTT_GRP_TOPIC3, SET_MQTT_GRP_TOPIC4, SET_MAX }; +enum DeviceGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYP_REUPDATE }; + +enum DeviceGroupMessageFlag { DGR_FLAG_RESET = 1, DGR_FLAG_STATUS_REQUEST = 2, DGR_FLAG_FULL_STATUS = 4, DGR_FLAG_ACK = 8, DGR_FLAG_MORE_TO_COME = 16, DGR_FLAG_DIRECT = 32 }; + +enum DeviceGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS, + DGR_ITEM_LIGHT_FADE, DGR_ITEM_LIGHT_SPEED, DGR_ITEM_LIGHT_BRI, DGR_ITEM_LIGHT_SCHEME, DGR_ITEM_LIGHT_FIXED_COLOR, + DGR_ITEM_BRI_MIN, DGR_ITEM_BRI_PRESET_LOW, DGR_ITEM_BRI_PRESET_HIGH, DGR_ITEM_BRI_POWER_ON, + // Add new 8-bit items before this line + DGR_ITEM_LAST_8BIT, DGR_ITEM_MAX_8BIT = 63, + DGR_ITEM_ACK, + DGR_ITEM_ANALOG1, DGR_ITEM_ANALOG2, DGR_ITEM_ANALOG3, DGR_ITEM_ANALOG4, DGR_ITEM_ANALOG5, + // Add new 16-bit items before this line + DGR_ITEM_LAST_16BIT, DGR_ITEM_MAX_16BIT = 127, + DGR_ITEM_POWER, + // Add new 32-bit items before this line + DGR_ITEM_LAST_32BIT, DGR_ITEM_MAX_32BIT = 191, + // Add new string items before this line + DGR_ITEM_LAST_STRING, DGR_ITEM_MAX_STRING = 223, + DGR_ITEM_LIGHT_CHANNELS }; + +enum DeviceGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE_LIGHT_FADE = 4, DGR_SHARE_LIGHT_SCHEME = 8, + DGR_SHARE_LIGHT_COLOR = 16, DGR_SHARE_BRI_MIN = 32 }; + enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER, SRC_MAX }; diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 2ed7976e1..8d17a0eb4 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -290,6 +290,9 @@ void setup(void) #ifdef USE_ARDUINO_OTA ArduinoOTAInit(); #endif // USE_ARDUINO_OTA +#ifdef USE_DEVICE_GROUPS + DeviceGroupsInit(); +#endif // USE_DEVICE_GROUPS XdrvCall(FUNC_INIT); XsnsCall(FUNC_INIT); @@ -329,6 +332,9 @@ void loop(void) #ifdef ROTARY_V1 RotaryLoop(); #endif +#ifdef USE_DEVICE_GROUPS + DeviceGroupsLoop(); +#endif // USE_DEVICE_GROUPS BacklogLoop(); if (TimeReached(state_50msecond)) { diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 615ff8919..74d6b0d84 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -55,6 +55,9 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #ifdef USE_EMULATION_WEMO #define USE_EMULATION #endif +#ifdef USE_DEVICE_GROUPS +#define USE_EMULATION +#endif #ifdef USE_MQTT_TLS const uint16_t WEB_LOG_SIZE = 2000; // Max number of characters in weblog @@ -692,6 +695,14 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_MQTT_TLS_CA_CERT #endif +#ifdef USE_DEVICE_GROUPS +#define SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, ...) _SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, __VA_ARGS__, 0) +#define SendLocalDeviceGroupMessage(REQUEST_TYPE, ...) _SendDeviceGroupMessage(0, REQUEST_TYPE, __VA_ARGS__, 0) +#define DEVICE_GROUP_MESSAGE "M-TASMOTA_DGR/" +const char kDeviceGroupMessage[] PROGMEM = DEVICE_GROUP_MESSAGE; +uint8_t device_group_count = 1; +#endif // USE_DEVICE_GROUPS + #ifdef DEBUG_TASMOTA_CORE #define DEBUG_CORE_LOG(...) AddLog_Debug(__VA_ARGS__) #else diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index fc143f73a..4296583e1 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2968,7 +2968,11 @@ bool Xdrv01(uint8_t function) case FUNC_LOOP: PollDnsWebserver(); #ifdef USE_EMULATION +#ifdef USE_DEVICE_GROUPS + if (Settings.flag2.emulation || Settings.flag.device_groups_enabled) { PollUdp(); } +#else // USE_DEVICE_GROUPS if (Settings.flag2.emulation) { PollUdp(); } +#endif // USE_DEVICE_GROUPS #endif // USE_EMULATION break; case FUNC_COMMAND: diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index aadf44f71..f72ec5ab3 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -871,10 +871,17 @@ void CmndPublish(void) void CmndGroupTopic(void) { +#ifdef USE_DEVICE_GROUPS + uint32_t settings_text_index = (XdrvMailbox.index <= 1 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + XdrvMailbox.index - 2); +#endif // USE_DEVICE_GROUPS if (XdrvMailbox.data_len > 0) { MakeValidMqtt(0, XdrvMailbox.data); if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } +#ifdef USE_DEVICE_GROUPS + SettingsUpdateText(settings_text_index, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); +#else // USE_DEVICE_GROUPS SettingsUpdateText(SET_MQTT_GRP_TOPIC, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data); +#endif // USE_DEVICE_GROUPS restart_flag = 2; } ResponseCmndChar(SettingsText(SET_MQTT_GRP_TOPIC)); diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index a45a5499d..baaf2b7a7 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1767,6 +1767,10 @@ void LightAnimate(void) Light.update = true; } if (Light.update) { +#ifdef USE_DEVICE_GROUPS + if (Light.power) LightSendDeviceGroupStatus(); +#endif // USE_DEVICE_GROUPS + uint16_t cur_col_10[LST_MAX]; // 10 bits resolution Light.update = false; @@ -2077,6 +2081,86 @@ void calcGammaBulbs(uint16_t cur_col_10[5]) { } } +#ifdef USE_DEVICE_GROUPS +void LightSendDeviceGroupStatus() +{ + uint8_t channels[LST_MAX]; + light_state.getChannels(channels); + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme, DGR_ITEM_LIGHT_CHANNELS, channels, + DGR_ITEM_LIGHT_BRI, (power ? light_state.getBri() : 0)); +} + +void LightHandleDeviceGroupRequest() +{ + static bool send_state = false; + uint32_t value = XdrvMailbox.payload; + switch (XdrvMailbox.command_code) { + case DGR_ITEM_EOL: + LightAnimate(); + if (send_state && !(XdrvMailbox.index & DGR_FLAG_MORE_TO_COME)) { + light_controller.saveSettings(); + if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT + MqttPublishTeleState(); + } + send_state = false; + } + break; + case DGR_ITEM_LIGHT_BRI: + if (light_state.getBri() != value) { + light_controller.changeBri(value); + send_state = true; + } + break; + case DGR_ITEM_LIGHT_SCHEME: + if (Settings.light_scheme != value) { + Settings.light_scheme = value; + send_state = true; + } + break; + case DGR_ITEM_LIGHT_CHANNELS: + light_controller.changeChannels((uint8_t *)XdrvMailbox.data); + send_state = true; + break; + case DGR_ITEM_LIGHT_FIXED_COLOR: + { + power_t save_power = Light.power; + if (value) { + bool save_decimal_text = Settings.flag.decimal_text; + char str[16]; + XdrvMailbox.index = 2; + XdrvMailbox.data_len = sprintf_P(str, PSTR("%u"), value); + XdrvMailbox.data = str; + CmndSupportColor(); + Settings.flag.decimal_text = save_decimal_text; + } + else { + Light.fixed_color_index = 0; + XdrvMailbox.index = 1; + XdrvMailbox.payload = light_state.BriToDimmer(light_state.getBri()); + CmndWhite(); + } + if (Light.power != save_power) { + XdrvMailbox.index = save_power; + LightSetPower(); + } + send_state = true; + } + break; + case DGR_ITEM_LIGHT_SPEED: + if (Settings.light_speed != value && value > 0 && value <= 40) { + Settings.light_speed = value; + send_state = true; + } + break; + case DGR_ITEM_STATUS: + SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, + DGR_ITEM_LIGHT_SPEED, Settings.light_speed); + LightSendDeviceGroupStatus(); + break; + } +} +#endif // USE_DEVICE_GROUPS + /*********************************************************************************************\ * Commands \*********************************************************************************************/ @@ -2339,6 +2423,9 @@ void CmndScheme(void) Light.wheel = parm[1]; } Settings.light_scheme = XdrvMailbox.payload; +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); +#endif // USE_DEVICE_GROUPS if (LS_WAKEUP == Settings.light_scheme) { Light.wakeup_active = 3; } @@ -2516,6 +2603,9 @@ void CmndFade(void) Settings.light_fade ^= 1; break; } +#ifdef USE_DEVICE_GROUPS + if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade); +#endif // USE_DEVICE_GROUPS if (!Settings.light_fade) { Light.fade_running = false; } ResponseCmndStateText(Settings.light_fade); } @@ -2536,6 +2626,9 @@ void CmndSpeed(void) } if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 40)) { Settings.light_speed = XdrvMailbox.payload; +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SPEED, Settings.light_speed); +#endif // USE_DEVICE_GROUPS } ResponseCmndNumber(Settings.light_speed); } @@ -2588,6 +2681,11 @@ bool Xdrv04(uint8_t function) case FUNC_EVERY_50_MSECOND: LightAnimate(); break; +#ifdef USE_DEVICE_GROUPS + case FUNC_DEVICE_GROUP_REQUEST: + LightHandleDeviceGroupRequest(); + break; +#endif // USE_DEVICE_GROUPS case FUNC_SET_POWER: LightSetPower(); break; From a721e35449f7b9de6ac90d3b79009a4d746c943f Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Fri, 21 Feb 2020 21:47:33 -0600 Subject: [PATCH 447/559] Remove power from struct, use DGR log prefix --- tasmota/support_device_groups.ino | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index 3add948a7..336b13cad 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -36,7 +36,6 @@ struct device_group_member { struct device_group { uint32_t next_ack_check_time; - power_t power; uint16_t last_full_status_sequence; uint16_t message_length; uint8_t message_header_length; @@ -64,7 +63,7 @@ void DeviceGroupsInit(void) if (Settings.flag.device_groups_enabled) { device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); if (device_groups == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: error allocating %u-element device group array", device_group_count); + AddLog_P2(LOG_LEVEL_ERROR, "DGR: error allocating %u-element device group array", device_group_count); Settings.flag.device_groups_enabled = false; return; } @@ -132,7 +131,7 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la } delay(10); } - AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: error sending %s packet", label); + AddLog_P2(LOG_LEVEL_ERROR, "DGR: error sending %s packet", label); } void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...) @@ -377,7 +376,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType // Broadcast the packet. #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: sending %u-byte device group %s packet via broadcast, sequence=%u", device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); + AddLog_P2(LOG_LEVEL_DEBUG, "DGR: sending %u-byte device group %s packet via broadcast, sequence=%u", device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); #endif // DEVICE_GROUPS_DEBUG SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, "Broadcast"); device_group->next_ack_check_time = millis() + 100; @@ -419,11 +418,11 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) if (!device_group_member) { device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member)); if (device_group_member == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: error allocating device group member block"); + AddLog_P2(LOG_LEVEL_ERROR, "DGR: error allocating device group member block"); return; } #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: adding member %s (%p)", IPAddressToString(remote_ip), device_group_member); + AddLog_P2(LOG_LEVEL_DEBUG, "DGR: adding member %s (%p)", IPAddressToString(remote_ip), device_group_member); #endif // DEVICE_GROUPS_DEBUG device_group_member->ip_address = remote_ip; *flink = device_group_member; @@ -538,7 +537,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) case DGR_ITEM_LIGHT_CHANNELS: break; default: - AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: ********** invalid item=%u received from device group %s member %s", item, device_group->group_name, IPAddressToString(remote_ip)); + AddLog_P2(LOG_LEVEL_ERROR, "DGR: ********** invalid item=%u received from device group %s member %s", item, device_group->group_name, IPAddressToString(remote_ip)); } #endif // DEVICE_GROUPS_DEBUG @@ -607,7 +606,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) return; badmsg: - AddLog_P2(LOG_LEVEL_ERROR, "DeviceGroups: malformed message received from %s", IPAddressToString(remote_ip)); + AddLog_P2(LOG_LEVEL_ERROR, "DGR: malformed message received from %s", IPAddressToString(remote_ip)); #ifdef DEVICE_GROUPS_DEBUG AddLog_P2(LOG_LEVEL_DEBUG, "packet_length=%u, offset=%u", packet_length, message_ptr - packet); #endif // DEVICE_GROUPS_DEBUG @@ -650,7 +649,7 @@ void DeviceGroupsLoop(void) if (device_group->next_ack_check_time <= now) { if (device_group->initial_status_requests_remaining) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: sending initial status request for group %s", device_group->group_name); + AddLog_P2(LOG_LEVEL_DEBUG, "DGR: sending initial status request for group %s", device_group->group_name); #endif // DEVICE_GROUPS_DEBUG if (--device_group->initial_status_requests_remaining) { SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, "Initial"); @@ -672,14 +671,14 @@ void DeviceGroupsLoop(void) if (device_group_member->timeout_time && device_group_member->timeout_time < now) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: removing member %s (%p)", IPAddressToString(device_group_member->ip_address), device_group_member); + AddLog_P2(LOG_LEVEL_DEBUG, "DGR: removing member %s (%p)", IPAddressToString(device_group_member->ip_address), device_group_member); #endif // DEVICE_GROUPS_DEBUG *flink = device_group_member->flink; free(device_group_member); } else { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DeviceGroups: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u", device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); + AddLog_P2(LOG_LEVEL_DEBUG, "DGR: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u", device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); #endif // DEVICE_GROUPS_DEBUG SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, "Unicast"); if (!device_group_member->timeout_time) device_group_member->timeout_time = now + 15000; From 5f1dac2119de6676f8cf410d9c40ffe3ed2042c4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Feb 2020 11:01:47 +0100 Subject: [PATCH 448/559] Update my_user_config.h --- tasmota/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 15f8e3a3f..8bf359605 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -502,7 +502,7 @@ #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module // #define USE_DISPLAY_SH1106 // [DisplayModel 7] [I2cDriver6] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D) - #define USE_WEMOS_MOTOR_V1 +// #define USE_WEMOS_MOTOR_V1 #define USE_WEMOS_MOTOR_V1_ADDR 0x30 #define USE_WEMOS_MOTOR_V1_FREQ 1000 #endif // USE_I2C From f706b7c4900edc0820ed688ab6396647cd30a66d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 22 Feb 2020 12:18:20 +0100 Subject: [PATCH 449/559] Add support for Wemos Motor Shield V1 Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) --- BUILDS.md | 7 ++ RELEASENOTES.md | 3 +- tasmota/CHANGELOG.md | 1 + tasmota/my_user_config.h | 6 +- tasmota/tasmota_post.h | 6 +- tasmota/xdrv_34_wemos_motor_v1.ino | 130 ++++++++++++++--------------- tools/decode-status.py | 4 +- 7 files changed, 81 insertions(+), 76 deletions(-) diff --git a/BUILDS.md b/BUILDS.md index aa1834061..88ee58cd0 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -62,6 +62,7 @@ | USE_DDS2382 | - | - | - | - | x | - | - | | USE_DDSU666 | - | - | - | - | x | - | - | | USE_SOLAX_X1 | - | - | - | - | - | - | - | +| USE_LE01MR | - | - | - | - | - | - | - | | | | | | | | | | | USE_ADC_VCC | x | x | - | - | - | - | - | | USE_COUNTER | - | - | x | x | x | x | x | @@ -109,6 +110,8 @@ | USE_HIH6 | - | - | - | - | x | - | - | | USE_DHT12 | - | - | - | - | x | - | - | | USE_DS1624 | - | - | - | - | x | - | - | +| USE_AHT1x | - | - | - | - | - | - | - | +| USE_WEMOS_MOTOR_V1 | - | - | - | - | x | - | - | | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | @@ -124,6 +127,10 @@ | USE_RDM6300 | - | - | - | - | x | - | - | | USE_IBEACON | - | - | - | - | x | - | - | | USE_GPS | - | - | - | - | - | - | - | +| USE_HM10 | - | - | - | - | x | - | - | +| | | | | | | | | +| USE_NRF24 | - | - | - | - | - | - | - | +| USE_MIBLE | - | - | - | - | - | - | - | | USE_ZIGBEE | - | - | - | - | - | - | - | | | | | | | | | | | USE_IR_REMOTE | - | - | x | x | x | x | x | diff --git a/RELEASENOTES.md b/RELEASENOTES.md index dba7abeed..e5e08674c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -103,4 +103,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for FiF LE-01MR energy meter by saper-2 (#7584) - Add new DHT driver. The old driver can still be used using define USE_DHT_OLD (#7468) - Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717) -- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) \ No newline at end of file +- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) +- Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 2689a7222..465bcde8f 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) - Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) +- Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) ### 8.1.0.8 20200212 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 8bf359605..c2cf75fe0 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -487,6 +487,9 @@ // #define USE_DHT12 // [I2cDriver41] Enable DHT12 humidity and temperature sensor (I2C address 0x5C) (+0k7 code) // #define USE_DS1624 // [I2cDriver42] Enable DS1624, DS1621 temperature sensor (I2C addresses 0x48 - 0x4F) (+1k2 code) // #define USE_AHT1x // [I2cDriver43] Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code) +// #define USE_WEMOS_MOTOR_V1 // [I2cDriver44] Enable Wemos motor driver V1 (I2C addresses 0x2D - 0x30) (+0k7 code) +// #define WEMOS_MOTOR_V1_ADDR 0x30 // Default I2C address 0x30 +// #define WEMOS_MOTOR_V1_FREQ 1000 // Default frequency // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 @@ -502,9 +505,6 @@ #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module // #define USE_DISPLAY_SH1106 // [DisplayModel 7] [I2cDriver6] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D) -// #define USE_WEMOS_MOTOR_V1 - #define USE_WEMOS_MOTOR_V1_ADDR 0x30 - #define USE_WEMOS_MOTOR_V1_FREQ 1000 #endif // USE_I2C // -- SPI sensors --------------------------------- diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index a126ff6fc..a2b49e677 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -165,6 +165,9 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack //#define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code) #define USE_HIH6 // Enable Honywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) //#define USE_AHT1x // Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code) +#define USE_WEMOS_MOTOR_V1 // Enable Wemos motor driver V1 (I2C addresses 0x2D - 0x30) (+0k7 code) + #define WEMOS_MOTOR_V1_ADDR 0x30 // Default I2C address 0x30 + #define WEMOS_MOTOR_V1_FREQ 1000 // Default frequency #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) @@ -223,9 +226,6 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack //#define USE_ARDUINO_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code -#define USE_WEMOS_MOTOR_V1 - #define USE_WEMOS_MOTOR_V1_ADDR 0x30 - #define USE_WEMOS_MOTOR_V1_FREQ 1000 #endif // FIRMWARE_SENSORS /*********************************************************************************************\ diff --git a/tasmota/xdrv_34_wemos_motor_v1.ino b/tasmota/xdrv_34_wemos_motor_v1.ino index 5f744a914..9e6c0a967 100644 --- a/tasmota/xdrv_34_wemos_motor_v1.ino +++ b/tasmota/xdrv_34_wemos_motor_v1.ino @@ -1,7 +1,7 @@ /* xdrv_34_wemos_motor_v1.ino - Support for I2C WEMOS motor shield (6612FNG) - Copyright (C) 2020 Andre Thomas and Theo Arends + Copyright (C) 2020 Denis Sborets and Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ * WEMOS_MOTOR_V1 - DC motor driver shield (6612FNG) v 1.0.0 * * I2C Address: 0x30 + * * Command format: * driver44 ,,{,} * command: @@ -41,8 +42,15 @@ * 0 - 100% (100% by default) \*********************************************************************************************/ -#define XDRV_34 34 -#define XI2C_44 44 // See I2CDEVICES.md +#define XDRV_34 34 +#define XI2C_44 44 // See I2CDEVICES.md + +#ifndef WEMOS_MOTOR_V1_ADDR +#define WEMOS_MOTOR_V1_ADDR 0x30 // Default I2C address 0x30 +#endif +#ifndef WEMOS_MOTOR_V1_FREQ +#define WEMOS_MOTOR_V1_FREQ 1000 // Default frequency +#endif #define MOTOR_A 0 #define MOTOR_B 1 @@ -53,80 +61,69 @@ #define STOP 3 #define STANDBY 4 -bool wemos_driver_detected = false; +struct WMOTORV1 { + bool detected = false; + uint8_t motor; +} WMotorV1; -uint8_t _motor; - -void Wemos_Driver_Detect(void) +void WMotorV1Detect(void) { - if (!I2cActive(USE_WEMOS_MOTOR_V1_ADDR)) - { - I2cSetActiveFound(USE_WEMOS_MOTOR_V1_ADDR, "WEMOS_MOTOR_V1"); - wemos_driver_detected = true; - Motor_Reset(); - return; + if (I2cSetDevice(WEMOS_MOTOR_V1_ADDR)) { + WMotorV1.detected = true; + I2cSetActiveFound(WEMOS_MOTOR_V1_ADDR, "WEMOS_MOTOR_V1"); + WMotorV1Reset(); } } -void Motor_Reset(void) +void WMotorV1Reset(void) { - Wire.begin(); - Motor_SetFreq(USE_WEMOS_MOTOR_V1_FREQ); - Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"RESET\":\"OK\"}}")); +// Wire.begin(); + WMotorV1SetFrequency(WEMOS_MOTOR_V1_FREQ); } -void Motor_SetFreq(uint32_t freq) +void WMotorV1SetFrequency(uint32_t freq) { - Wire.beginTransmission(USE_WEMOS_MOTOR_V1_ADDR); + Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); Wire.write(((byte)(freq >> 16)) & (byte)0x0f); Wire.write((byte)(freq >> 16)); Wire.write((byte)(freq >> 8)); Wire.write((byte)freq); Wire.endTransmission(); // stop transmitting - delay(100); +// delay(100); } -void Motor_SetMotor(uint8_t motor, uint8_t dir, float pwm_val) +void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val) { - uint16_t _pwm_val; - Wire.beginTransmission(USE_WEMOS_MOTOR_V1_ADDR); + Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); Wire.write(motor | (byte)0x10); Wire.write(dir); - _pwm_val = uint16_t(pwm_val * 100); - - if (_pwm_val > 10000) + uint16_t _pwm_val = uint16_t(pwm_val * 100); + if (_pwm_val > 10000) { _pwm_val = 10000; + } Wire.write((byte)(_pwm_val >> 8)); Wire.write((byte)_pwm_val); Wire.endTransmission(); - - delay(100); - - Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"SETMOTOR\":\"OK\"}}")); +// delay(100); } -bool Motor_Command(void) +bool WMotorV1Command(void) { uint8_t args_count = 0; - if (XdrvMailbox.data_len > 0) - { + + if (XdrvMailbox.data_len > 0) { args_count = 1; - } - else - { + } else { return false; } - for (uint32_t idx = 0; idx < XdrvMailbox.data_len; idx++) - { - if (' ' == XdrvMailbox.data[idx]) - { + for (uint32_t idx = 0; idx < XdrvMailbox.data_len; idx++) { + if (' ' == XdrvMailbox.data[idx]) { XdrvMailbox.data[idx] = ','; } - if (',' == XdrvMailbox.data[idx]) - { + if (',' == XdrvMailbox.data[idx]) { args_count++; } } @@ -134,51 +131,50 @@ bool Motor_Command(void) char *command = strtok(XdrvMailbox.data, ","); - if (strcmp(command, "RESET") == 0) - { - Motor_Reset(); + if (strcmp(command, "RESET") == 0) { + WMotorV1Reset(); + Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"RESET\":\"OK\"}}")); return true; } - if (strcmp(command, "SETMOTOR") == 0) - { - if (args_count >= 3) - { + if (strcmp(command, "SETMOTOR") == 0) { + if (args_count >= 3) { int motor = atoi(strtok(NULL, ",")); int dir = atoi(strtok(NULL, ",")); int duty = 100; - - if (args_count == 4) - { + if (args_count == 4) { duty = atoi(strtok(NULL, ",")); } - Motor_SetMotor(motor, dir, duty); - + WMotorV1SetMotor(motor, dir, duty); + Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"SETMOTOR\":\"OK\"}}")); return true; } } return false; } +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + bool Xdrv34(uint8_t function) { - if (!I2cEnabled(XI2C_44)) - { - return false; - } + if (!I2cEnabled(XI2C_44)) { return false; } + bool result = false; - if (FUNC_INIT == function) - { - Wemos_Driver_Detect(); - result = wemos_driver_detected; + + if (FUNC_INIT == function) { + WMotorV1Detect(); } - else if (wemos_driver_detected) - { - if (FUNC_COMMAND_DRIVER == function && XI2C_44 == XdrvMailbox.index) - { - result = Motor_Command(); + else if (WMotorV1.detected) { + switch (function) { + case FUNC_COMMAND_DRIVER: + if (XI2C_44 == XdrvMailbox.index) { + result = WMotorV1Command(); + } + break; } } return result; diff --git a/tools/decode-status.py b/tools/decode-status.py index 210175de8..3838d8faf 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -193,7 +193,7 @@ a_features = [[ "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", "USE_DHT12","USE_DS1624","USE_GPS","USE_HOTPLUG", "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", - "USE_AHT1x","","","" + "USE_AHT1x","USE_WEMOS_MOTOR_V1","","" ],[ "","","","", "","","","", @@ -236,7 +236,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200220 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200222 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From 13763f55a68361c13e81b56b279cdb0d798c76b3 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 22 Feb 2020 20:53:55 +0100 Subject: [PATCH 450/559] Fix Zigbee auto-increment transaction number (#7757) --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 1 + tasmota/xdrv_23_zigbee_1_headers.ino | 2 +- tasmota/xdrv_23_zigbee_3_devices.ino | 23 ++++++++++++++++++++++- tasmota/xdrv_23_zigbee_6_commands.ino | 2 +- tasmota/xdrv_23_zigbee_8_parsers.ino | 2 ++ tasmota/xdrv_23_zigbee_9_impl.ino | 9 +++++---- 7 files changed, 33 insertions(+), 7 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 465bcde8f..c8cf0ab3a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) - Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) +- Fix Zigbee auto-increment transaction number (#7757) ### 8.1.0.8 20200212 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 00cda53b4..c7930e79b 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -489,6 +489,7 @@ #define D_CMND_ZIGBEE_FORGET "Forget" #define D_CMND_ZIGBEE_SAVE "Save" #define D_CMND_ZIGBEE_LINKQUALITY "LinkQuality" + #define D_CMND_ZIGBEE_ENDPOINT "Endpoint" #define D_CMND_ZIGBEE_READ "Read" #define D_CMND_ZIGBEE_SEND "Send" #define D_JSON_ZIGBEE_ZCL_SENT "ZbZCLSent" diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 101d5703d..0bc592266 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -21,7 +21,7 @@ // contains some definitions for functions used before their declarations -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1); +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId); // Get an JSON attribute, with case insensitive key search diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 4814bdb8a..78c192cc1 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -49,6 +49,8 @@ typedef struct Z_Device { // json buffer used for attribute reporting DynamicJsonBuffer *json_buffer; JsonObject *json; + // sequence number for Zigbee frames + uint8_t seqNumber; } Z_Device; // All devices are stored in a Vector @@ -96,6 +98,9 @@ public: // device just seen on the network, update the lastSeen field void updateLastSeen(uint16_t shortaddr); + // get next sequence number for (increment at each all) + uint8_t getNextSeqNumber(uint16_t shortaddr); + // Dump json String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; @@ -133,6 +138,7 @@ public: private: std::vector _devices = {}; uint32_t _saveTimer = 0; + uint8_t _seqNumber = 0; // global seqNumber if device is unknown template < typename T> static bool findInVector(const std::vector & vecOfElements, const T & element); @@ -226,7 +232,9 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { std::vector(), 0,0,0,0, nullptr, - nullptr, nullptr }; + nullptr, nullptr, + 0, // seqNumber + }; device.json_buffer = new DynamicJsonBuffer(); _devices.push_back(device); dirty(); @@ -532,6 +540,19 @@ void Z_Devices::updateLastSeen(uint16_t shortaddr) { _updateLastSeen(device); } +// get the next sequance number for the device, or use the global seq number if device is unknown +uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) { + int32_t short_found = findShortAddr(shortaddr); + if (short_found >= 0) { + Z_Device &device = getShortAddr(shortaddr); + device.seqNumber += 1; + return device.seqNumber; + } else { + _seqNumber += 1; + return _seqNumber; + } +} + // Per device timers // // Reset the timer for a specific device diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 073ab8e4c..9d6f38b95 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -78,7 +78,7 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoi break; } if (attrs) { - ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(shortaddr)); } } diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 668f85471..7d84124ed 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -451,6 +451,8 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); zcl_received.postProcessAttributes(srcaddr, json); + // Add Endpoint + json[F(D_CMND_ZIGBEE_ENDPOINT)] = srcendpoint; // Add linkquality json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 6ea08c4ac..eccfc56be 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -344,7 +344,7 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { ToHex_P(msg, len, hex_char, sizeof(hex_char))); } -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp, uint8_t transacId) { +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { SBuffer buf(25+len); buf.add8(Z_SREQ | Z_AF); // 24 buf.add8(AF_DATA_REQUEST); // 01 @@ -357,7 +357,7 @@ void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8 buf.add8(0x1E); // 1E radius buf.add8(3 + len); - buf.add8((disableDefResp ? 0x10 : 0x00) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field + buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field buf.add8(transacId); // Transaction Sequance Number buf.add8(cmdId); if (len > 0) { @@ -438,7 +438,7 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { } // everything is good, we can send the command - ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len()); + ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len(), false, zigbee_devices.getNextSeqNumber(dstAddr)); // now set the timer, if any, to read back the state later if (clusterSpecific) { zigbeeSetCommandTimer(dstAddr, cluster, endpoint); @@ -469,6 +469,7 @@ void CmndZbSend(void) { uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint String cmd_str = ""; // the actual low-level command, either specified or computed + // parse JSON const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); if (nullptr != &val_device) { device = zigbee_devices.parseDeviceParam(val_device.as()); @@ -729,7 +730,7 @@ void CmndZbRead(void) { } if ((0 != endpoint) && (attrs_len > 0)) { - ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(device)); ResponseCmndDone(); } else { ResponseCmndChar("Missing parameters"); From 73b2fdd6f472891631be54233d0968597d5d3bbd Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 23 Feb 2020 09:21:54 +0100 Subject: [PATCH 451/559] fix OUI-bug --- tasmota/xsns_61_MI_NRF24.ino | 115 +++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 32 deletions(-) diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/xsns_61_MI_NRF24.ino index 8527c9749..cc865f6d6 100644 --- a/tasmota/xsns_61_MI_NRF24.ino +++ b/tasmota/xsns_61_MI_NRF24.ino @@ -21,6 +21,9 @@ Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + 0.9.3.0 20200222 integrate - use now the correct id-word instead of MAC-OUI, + add CGG1 + --- 0.9.2.0 20200212 integrate - "backports" from MI-HM10, change reading pattern, add missing PDU-types, renaming driver --- @@ -58,18 +61,21 @@ #define MJ_HT_V1 2 #define LYWSD02 3 #define LYWSD03 4 +#define CGG1 5 -uint8_t kMINRFSlaveID[4][3] = { 0xC4,0x7C,0x8D, // Flora - 0x58,0x2D,0x34, // MJ_HT_V1 - 0xE7,0x2E,0x00, // LYWSD02 - 0xA4,0xC1,0x38, // LYWSD03 - }; +const uint16_t kMINRFSlaveID[5]={ 0x0098, // Flora + 0x01aa, // MJ_HT_V1 + 0x045b, // LYWSD02 + 0x055b, // LYWSD03 + 0x0347 // CGG1 + }; const char kMINRFSlaveType1[] PROGMEM = "Flora"; const char kMINRFSlaveType2[] PROGMEM = "MJ_HT_V1"; const char kMINRFSlaveType3[] PROGMEM = "LYWSD02"; const char kMINRFSlaveType4[] PROGMEM = "LYWSD03"; -const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4}; +const char kMINRFSlaveType5[] PROGMEM = "CGG1"; +const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4,kMINRFSlaveType5}; // PDU's or different channels 37-39 const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; @@ -77,10 +83,11 @@ const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71da7646}; // 1 and 3 unsure // const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0xffffffff}; //encrypted - 58 58 const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; //unencrypted - 30 58 +const uint32_t kMINRFCGPDU[3] = {0x4760cd78,0xdbcc0ccd,0x33048deb}; // very unsure!!! // start-LSFR for different channels 37-39 const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; // Flora, LYWSD02 -const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03 +const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03, ???CGG1???? #pragma pack(1) // important!! @@ -269,7 +276,7 @@ struct { } MINRF; struct mi_sensor_t{ - uint8_t type; //Flora = 1; MJ_HT_V1=2; LYWSD02=3; LYWSD03=4 + uint8_t type; //Flora = 1; MJ_HT_V1=2; LYWSD02=3; LYWSD03=4; ; CGG1=5 uint8_t serial[6]; uint8_t showedUp; float temp; //Flora, MJ_HT_V1, LYWSD0x @@ -362,6 +369,9 @@ bool MINRFreceivePacket(void) case 4: MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); // "LYWSD03" mode break; + case 5: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); // "CGG1" mode + break; } // DEBUG_SENSOR_LOG(PSTR("MINRF: LSFR:%x"),_lsfr); // if (_lsfr>254) _lsfr=0; @@ -470,6 +480,9 @@ void MINRFchangePacketModeTo(uint8_t _mode) { if(kMINRFL3PDU[_nextchannel]==0xffffffff) break; NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]);// 95 fe 58 30 -> LYWSD03 (= no data message) break; + case 5: // special CGG1 packet + NRF24radio.openReadingPipe(0,kMINRFCGPDU[_nextchannel]); // 95 fe 50 30 -> CGG1 + break; } // DEBUG_SENSOR_LOG(PSTR("MINRF: Change Mode to %u"),_mode); MINRF.packetMode = _mode; @@ -479,24 +492,25 @@ void MINRFchangePacketModeTo(uint8_t _mode) { * @brief Return the slot number of a known sensor or return create new sensor slot * * @param _serial BLE address of the sensor - * @param _type Type number of the sensor, 0xff for Auto-type + * @param _type Type number of the sensor * @return uint32_t Known or new slot in the sensors-vector */ -uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ - if(_type==0xff){ - DEBUG_SENSOR_LOG(PSTR("MINRF: will test MAC-type")); - for (uint32_t i=0;i<4;i++){ - if(memcmp(_serial,kMINRFSlaveID+i,3)==0){ - DEBUG_SENSOR_LOG(PSTR("MINRF: MAC is type %u"), i); - _type = i+1; - } - else { - DEBUG_SENSOR_LOG(PSTR("MINRF: MAC-type is unknown")); - } +uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ + + DEBUG_SENSOR_LOG(PSTR("MINRF: will test ID-type: %x"), _type); + bool _success = false; + for (uint32_t i=0;i<5;i++){ + if(_type == kMINRFSlaveID[i]){ + DEBUG_SENSOR_LOG(PSTR("MINRF: ID is type %u"), i); + _type = i+1; + _success = true; + } + else { + DEBUG_SENSOR_LOG(PSTR("MINRF: ID-type is not: %x"),kMINRFSlaveID[i]); } } - if(_type==0xff) return _type; // error - + if(!_success) return 0xff; + DEBUG_SENSOR_LOG(PSTR("MINRF: vector size %u"), MIBLEsensors.size()); for(uint32_t i=0; i6000){ // happens every 6000/20 = 300 seconds @@ -712,9 +762,10 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds else if (MINRF.packetMode == LYWSD03){ MINRFhandleLYWSD03Packet(); } - - // DEBUG_SENSOR_LOG(PSTR("MINRF: Change packet mode every 50 msec")); - if (MINRF.packetMode == LYWSD03){ + else if (MINRF.packetMode == CGG1){ + MINRFhandleCGG1Packet(); + } + if (MINRF.packetMode == CGG1){ MINRFinitBLE(1); // no real ble packets in release mode, otherwise for developing use 0 } else { From 11604e30d4fcb5a56f996b41f745e24f17730d8e Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 23 Feb 2020 10:29:04 +0100 Subject: [PATCH 452/559] Moved 'Updated shadow' do DEBUG log level --- tasmota/xdrv_02_mqtt.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index aadf44f71..1fda2a95a 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -398,7 +398,7 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retain free(mqtt_save); bool result = MqttClient.publish(romram, mqtt_data, false); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "Updated shadow: %s"), romram); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Updated shadow: %s"), romram); yield(); // #3313 } #endif // USE_MQTT_AWS_IOT From 8411178dacef96ccf20b9536de0bb4540bbb5e20 Mon Sep 17 00:00:00 2001 From: Staars Date: Sun, 23 Feb 2020 14:52:26 +0100 Subject: [PATCH 453/559] use now the correct PDU-types --- tasmota/xsns_61_MI_NRF24.ino | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/xsns_61_MI_NRF24.ino index cc865f6d6..f1db19d74 100644 --- a/tasmota/xsns_61_MI_NRF24.ino +++ b/tasmota/xsns_61_MI_NRF24.ino @@ -83,11 +83,11 @@ const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71da7646}; // 1 and 3 unsure // const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0xffffffff}; //encrypted - 58 58 const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; //unencrypted - 30 58 -const uint32_t kMINRFCGPDU[3] = {0x4760cd78,0xdbcc0ccd,0x33048deb}; // very unsure!!! +const uint32_t kMINRFCGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; // start-LSFR for different channels 37-39 const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; // Flora, LYWSD02 -const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03, ???CGG1???? +const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03, CGG1 #pragma pack(1) // important!! @@ -720,6 +720,10 @@ void MINRFhandleCGG1Packet(void){ // we assume, that the packet structure is equ } } +/*********************************************************************************************\ + * Main loop of the driver +\*********************************************************************************************/ + void MINRF_EVERY_50_MSECOND() { // Every 50mseconds if(MINRF.timer>6000){ // happens every 6000/20 = 300 seconds @@ -771,7 +775,7 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds else { MINRFinitBLE(++MINRF.packetMode); } - + MINRFhopChannel(); NRF24radio.startListening(); } From d4dd0a39a5ab865055c99c2a8e045972d67b7da7 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 23 Feb 2020 16:46:00 +0100 Subject: [PATCH 454/559] Add Zigbee enhanced commands decoding, added ``ZbPing`` --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 2 + tasmota/xdrv_23_zigbee_3_devices.ino | 8 + tasmota/xdrv_23_zigbee_5_converters.ino | 12 +- tasmota/xdrv_23_zigbee_6_commands.ino | 261 +++++++++++++++++++--- tasmota/xdrv_23_zigbee_7_statemachine.ino | 1 + tasmota/xdrv_23_zigbee_8_parsers.ino | 51 ++++- tasmota/xdrv_23_zigbee_9_impl.ino | 114 +++++----- 8 files changed, 344 insertions(+), 106 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index c8cf0ab3a..ef9ce17f4 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -6,6 +6,7 @@ - Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) - Fix Zigbee auto-increment transaction number (#7757) +- Add Zigbee enhanced commands decoding, added ``ZbPing`` ### 8.1.0.8 20200212 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index c7930e79b..ab7d18ce0 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -496,6 +496,8 @@ #define D_JSON_ZIGBEE_RECEIVED "ZbReceived" #define D_JSON_ZIGBEE_RECEIVED_LEGACY "ZigbeeReceived" #define D_CMND_ZIGBEE_BIND "Bind" +#define D_CMND_ZIGBEE_PING "Ping" + #define D_JSON_ZIGBEE_PING "ZbPing" // Commands xdrv_25_A4988_Stepper.ino #define D_CMND_MOTOR "MOTOR" diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 78c192cc1..71752f4e3 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -19,6 +19,10 @@ #ifdef USE_ZIGBEE +#ifndef ZIGBEERECEIVED +#define ZIGBEERECEIVED 1 +#endif + #include #include @@ -725,18 +729,22 @@ void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); +#if ZIGBEERECEIVED // DEPRECATED TODO Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); +#endif } else { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); +#if ZIGBEERECEIVED // DEPRECATED TODO Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); +#endif } // MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); // XdrvRulesProcess(); diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index d97e5e7d4..4debd73fd 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -486,18 +486,8 @@ void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { // Parse non-normalized attributes -// The key is "s_" followed by 16 bits clusterId, "_" followed by 8 bits command id void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - - char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X!%02X"), _cluster_id, _cmd_id); - - char hex_char[_payload.len()*2+2]; - ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - - json[attrid_str] = hex_char; + convertClusterSpecific(json, _cluster_id, _cmd_id, _frame_control.b.direction, _payload); } // return value: diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 9d6f38b95..83841f90c 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -19,34 +19,79 @@ #ifdef USE_ZIGBEE -//typedef int32_t (*Z_AttrConverter)(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param); typedef struct Z_CommandConverter { const char * tasmota_cmd; - const char * zcl_cmd; + uint16_t cluster; + uint8_t cmd; // normally 8 bits, 0xFF means it's a parameter + uint8_t direction; // direction of the command. 0x01 client->server, 0x02 server->client, 0x03 both + const char * param; } Z_CommandConverter; +typedef struct Z_XYZ_Var { // Holds values for vairables X, Y and Z + uint32_t x = 0; + uint32_t y = 0; + uint32_t z = 0; + uint8_t x_type = 0; // 0 = no value, 1 = 1 bytes, 2 = 2 bytes + uint8_t y_type = 0; + uint8_t z_type = 0; +} Z_XYZ_Var; + // list of post-processing directives const Z_CommandConverter Z_Commands[] = { - { "Power", "0006!xx" }, // 0=Off, 1=On, 2=Toggle - { "Dimmer", "0008!04/xx0A00" }, // Move to Level with On/Off, xx=0..254 (255 is invalid) - { "Dimmer+", "0008!06/001902" }, // Step up by 10%, 0.2 secs - { "Dimmer-", "0008!06/011902" }, // Step down by 10%, 0.2 secs - { "DimmerStop", "0008!03" }, // Stop any Dimmer animation - { "ResetAlarm", "0009!00/xxyyyy" }, // Reset alarm (alarm code + cluster identifier) - { "ResetAllAlarms","0009!01" }, // Reset all alarms - { "Hue", "0300!00/xx000A00" }, // Move to Hue, shortest time, 1s - { "Sat", "0300!03/xx0A00" }, // Move to Sat - { "HueSat", "0300!06/xxyy0A00" }, // Hue, Sat - { "Color", "0300!07/xxxxyyyy0A00" }, // x, y (uint16) - { "CT", "0300!0A/xxxx0A00" }, // Color Temperature Mireds (uint16) - { "Shutter", "0102!xx" }, - { "ShutterOpen", "0102!00" }, - { "ShutterClose", "0102!01" }, - { "ShutterStop", "0102!02" }, - { "ShutterLift", "0102!05xx" }, // Lift percentage, 0%=open, 100%=closed - { "ShutterTilt", "0102!08xx" }, // Tilt percentage + // Group adress commands + { "AddGroup", 0x0004, 0x00, 0x01, "xxxx00" }, // Add group id, group name is not supported + { "ViewGroup", 0x0004, 0x01, 0x01, "xxxx" }, // Ask for the group name + { "GetGroup", 0x0004, 0x02, 0x01, "01xxxx" }, // Get one group membership + { "GetAllGroups", 0x0004, 0x02, 0x01, "00" }, // Get all groups membership + { "RemoveGroup", 0x0004, 0x03, 0x01, "xxxx" }, // Remove one group + { "RemoveAllGroups",0x0004, 0x04, 0x01, "" }, // Remove all groups + // Light & Shutter commands + { "Power", 0x0006, 0xFF, 0x01, "" }, // 0=Off, 1=On, 2=Toggle + { "Dimmer", 0x0008, 0x04, 0x01, "xx0A00" }, // Move to Level with On/Off, xx=0..254 (255 is invalid) + { "Dimmer+", 0x0008, 0x06, 0x01, "001902" }, // Step up by 10%, 0.2 secs + { "Dimmer-", 0x0008, 0x06, 0x01, "011902" }, // Step down by 10%, 0.2 secs + { "DimmerStop", 0x0008, 0x03, 0x01, "" }, // Stop any Dimmer animation + { "ResetAlarm", 0x0009, 0x00, 0x01, "xxyyyy" }, // Reset alarm (alarm code + cluster identifier) + { "ResetAllAlarms", 0x0009, 0x01, 0x01, "" }, // Reset all alarms + { "Hue", 0x0300, 0x00, 0x01, "xx000A00" }, // Move to Hue, shortest time, 1s + { "Sat", 0x0300, 0x03, 0x01, "xx0A00" }, // Move to Sat + { "HueSat", 0x0300, 0x06, 0x01, "xxyy0A00" }, // Hue, Sat + { "Color", 0x0300, 0x07, 0x01, "xxxxyyyy0A00" }, // x, y (uint16) + { "CT", 0x0300, 0x0A, 0x01, "xxxx0A00" }, // Color Temperature Mireds (uint16) + { "ShutterOpen", 0x0102, 0x00, 0x01, "" }, + { "ShutterClose", 0x0102, 0x01, 0x01, "" }, + { "ShutterStop", 0x0102, 0x02, 0x01, "" }, + { "ShutterLift", 0x0102, 0x05, 0x01, "xx" }, // Lift percentage, 0%=open, 100%=closed + { "ShutterTilt", 0x0102, 0x08, 0x01, "xx" }, // Tilt percentage + { "Shutter", 0x0102, 0xFF, 0x01, "" }, + // Blitzwolf PIR + { "Occupancy", 0xEF00, 0x01, 0x01, "xx"}, // Specific decoder for Blitzwolf PIR, empty name means special treatment + // Decoders only - normally not used to send, and names may be masked by previous definitions + { "Dimmer", 0x0008, 0x00, 0x01, "xx" }, + { "DimmerMove", 0x0008, 0x01, 0x01, "xx0A" }, + { "DimmerStep", 0x0008, 0x02, 0x01, "xx190A00" }, + { "DimmerMove", 0x0008, 0x05, 0x01, "xx0A" }, + { "Dimmer+", 0x0008, 0x06, 0x01, "00" }, + { "Dimmer-", 0x0008, 0x06, 0x01, "01" }, + { "DimmerStop", 0x0008, 0x07, 0x01, "" }, + { "HueMove", 0x0300, 0x01, 0x01, "xx19" }, + { "HueStep", 0x0300, 0x02, 0x01, "xx190A00" }, + { "SatMove", 0x0300, 0x04, 0x01, "xx19" }, + { "SatStep", 0x0300, 0x05, 0x01, "xx190A" }, + { "ColorMove", 0x0300, 0x08, 0x01, "xxxxyyyy" }, + { "ColorStep", 0x0300, 0x09, 0x01, "xxxxyyyy0A00" }, + // Tradfri + { "ArrowClick", 0x0005, 0x07, 0x01, "xx" }, // xx == 0x01 = left, 0x00 = right + { "ArrowHold", 0x0005, 0x08, 0x01, "xx" }, // xx == 0x01 = left, 0x00 = right + { "ArrowRelease", 0x0005, 0x09, 0x01, "" }, + // responses for Group cluster commands + { "AddGroupResp", 0x0004, 0x00, 0x02, "xxyyyy" }, // xx = status, yy = group id + { "ViewGroupResp", 0x0004, 0x01, 0x02, "xxyyyy" }, // xx = status, yy = group id, name ignored + { "GetGroupResp", 0x0004, 0x02, 0x02, "xxyyzzzz" }, // xx = capacity, yy = count, zzzz = first group id, following groups ignored + { "RemoveGroup", 0x0004, 0x03, 0x02, "xxyyyy" }, // xx = status, yy = group id }; + #define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian // Below are the attributes we wand to read from each cluster @@ -55,6 +100,7 @@ const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; // CurrentLevel const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; // AlarmCount const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007) }; // Hue, Sat, X, Y, CT +// This callback is registered after a cluster specific command and sends a read command for the same cluster int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { size_t attrs_len = 0; const uint8_t* attrs = nullptr; @@ -82,7 +128,6 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoi } } - // set a timer to read back the value in the future void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint) { uint32_t wait_ms = 0; @@ -105,22 +150,182 @@ void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoi } } -const __FlashStringHelper* zigbeeFindCommand(const char *command) { - char parm_uc[16]; // used to convert JSON keys to uppercase +// returns true if char is 'x', 'y' or 'z' +inline bool isXYZ(char c) { + return (c >= 'x') && (c <= 'z'); +} + +// returns the Hex value of a digit [0-9A-Fa-f] +// return: 0x00-0x0F +// or -1 if cannot be parsed +inline int8_t hexValue(char c) { + if ((c >= '0') && (c <= '9')) { + return c - '0'; + } + if ((c >= 'A') && (c <= 'F')) { + return 10 + c - 'A'; + } + if ((c >= 'a') && (c <= 'f')) { + return 10 + c - 'a'; + } + return -1; +} + +// Parse a Big Endian suite of max_len digits, or stops when a non-hex digit is found +uint32_t parseHex_P(const char **data, size_t max_len = 8) { + uint32_t ret = 0; + for (uint32_t i = 0; i < max_len; i++) { + int8_t v = hexValue(pgm_read_byte(*data)); + if (v < 0) { break; } // non hex digit, we stop parsing + ret = (ret << 4) | v; + *data += 1; + } + return ret; +} + +// Parse a model like "xxyy00" +// and fill x, y and z values +// Little Endian encoding +// On exit, xyz is updated, and x_type, y_type, z_type contain the number of bytes read for each +void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz) { + const char *p = model; // pointer to the model character + uint32_t v = 0; // index in the payload bytes buffer + char c = pgm_read_byte(p); // cur char + while (c) { + char c1 = pgm_read_byte(p+1); // next char + if (!c1) { break; } // unexpected end of model + if (isXYZ(c) && (c == c1) && (v < payload.len())) { // if char is [x-z] and followed by same char + uint8_t val = payload.get8(v); + switch (c) { + case 'x': + xyz->x = xyz->x | (val << (xyz->x_type * 8)); + xyz->x_type++; + break; + case 'y': + xyz->y = xyz->y | (val << (xyz->y_type * 8)); + xyz->y_type++; + break; + case 'z': + xyz->z = xyz->z | (val << (xyz->z_type * 8)); + xyz->z_type++; + break; + } + } + p += 2; + v++; + c = pgm_read_byte(p); + } +} + +// works on big endiand hex only +// Returns if found: +// - cluster number +// - command number or 0xFF if command is part of the variable part +// - the payload in the form of a HEX string with x/y/z variables + + + +// Parse a cluster specific command, and try to convert into human readable +void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, bool direction, const SBuffer &payload) { + size_t hex_char_len = payload.len()*2+2; + char *hex_char = (char*) malloc(hex_char_len); + if (!hex_char) { return; } + ToHex_P((unsigned char*)payload.getBuffer(), payload.len(), hex_char, hex_char_len); + + const __FlashStringHelper* command_name = nullptr; + Z_XYZ_Var xyz; + +//AddLog_P2(LOG_LEVEL_INFO, PSTR(">>> len = %d - %02X%02X%02X"), payload.len(), payload.get8(0), payload.get8(1), payload.get8(2)); + for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { + const Z_CommandConverter *conv = &Z_Commands[i]; + if (conv->cluster == cluster) { + // cluster match + if ((0xFF == conv->cmd) || (cmd == conv->cmd)) { + // cmd match + if ((direction && (conv->direction & 0x02)) || (!direction && (conv->direction & 0x01))) { + // check if we have a match for params too + // Match if: + // - payload exactly matches conv->param (conv->param may be longer) + // - payload matches conv->param until 'x', 'y' or 'z' + const char * p = conv->param; + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">>>++1 param = %s"), p); + bool match = true; + for (uint8_t i = 0; i < payload.len(); i++) { + const char c1 = pgm_read_byte(p); + const char c2 = pgm_read_byte(p+1); + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">>>++2 c1 = %c, c2 = %c"), c1, c2); + if ((0x00 == c1) || isXYZ(c1)) { + break; + } + const char * p2 = p; + uint32_t nextbyte = parseHex_P(&p2, 2); + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">>>++3 parseHex_P = %02X"), nextbyte); + if (nextbyte != payload.get8(i)) { + match = false; + break; + } + p += 2; + } + if (match) { + command_name = (const __FlashStringHelper*) conv->tasmota_cmd; + parseXYZ(conv->param, payload, &xyz); + if (0xFF == conv->cmd) { + // shift all values + xyz.z = xyz.y; + xyz.z_type = xyz.y_type; + xyz.y = xyz.x; + xyz.y_type = xyz.x_type; + xyz.x = cmd; + xyz.x_type = 1; // 1 byte + } + break; + } + } + } + } + } + + // always report attribute in raw format + // Format: "0001!06": "00" = "!": "" for commands to devices + // Format: "0004<00": "00" = "<": "" for commands to devices + char attrid_str[12]; + snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); + json[attrid_str] = hex_char; + free(hex_char); + + if (command_name) { + if (0 == xyz.x_type) { + json[command_name] = true; // no parameter + } else if (0 == xyz.y_type) { + json[command_name] = xyz.x; // 1 parameter + } else { + // multiple answers, create an array + JsonArray &arr = json.createNestedArray(command_name); + arr.add(xyz.x); + arr.add(xyz.y); + if (xyz.z_type) { + arr.add(xyz.z); + } + } + } +} + +// Find the command details by command name +// If not found: +// - returns nullptr +const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd) { for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { const Z_CommandConverter *conv = &Z_Commands[i]; if (0 == strcasecmp_P(command, conv->tasmota_cmd)) { - return (const __FlashStringHelper*) conv->zcl_cmd; + *cluster = conv->cluster; + *cmd = conv->cmd; + return (const __FlashStringHelper*) conv->param; } } return nullptr; } -inline bool isXYZ(char c) { - return (c >= 'x') && (c <= 'z'); -} - // take the lower 4 bits and turn it to an hex char inline char hexDigit(uint32_t h) { uint32_t nybble = h & 0x0F; diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index 5a3d78e85..d0616a40b 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -33,6 +33,7 @@ const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; // Node descriptor const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; // Endpoints descriptor const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; // Simple Descriptor (clusters) const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; // Device announces its address +const uint8_t ZIGBEE_STATUS_DEVICE_IEEE = 35; // Request of device address const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 7d84124ed..b67add374 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -176,15 +176,24 @@ int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { return -1; } +// Send ZDO_IEEE_ADDR_REQ request to get IEEE long address +void Z_SendIEEEAddrReq(uint16_t shortaddr) { + uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; + + ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq)); +} + // Send ACTIVE_EP_REQ to collect active endpoints for this address void Z_SendActiveEpReq(uint16_t shortaddr) { uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); + + // uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, + // Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + //ZigbeeZNPSend(NodeDescReq, sizeof(NodeDescReq)); Not sure this is useful } @@ -335,6 +344,40 @@ int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { return -1; } +int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { + uint8_t status = buf.get8(2); + Z_IEEEAddress ieeeAddr = buf.get64(3); + Z_ShortAddress nwkAddr = buf.get16(11); + // uint8_t startIndex = buf.get8(13); + // uint8_t numAssocDev = buf.get8(14); + + if (0 == status) { // SUCCESS + zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + "}}"), + ZIGBEE_STATUS_DEVICE_IEEE, hex, nwkAddr + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + // Ping response + const String * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + if (friendlyName) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), nwkAddr, friendlyName->c_str()); + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"}}"), nwkAddr); + } + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + } + return -1; +} + int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { Z_ShortAddress srcAddr = buf.get16(2); Z_ShortAddress nwkAddr = buf.get16(4); @@ -484,6 +527,7 @@ ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) // 45CA ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) // 45CB ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4585 ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 +ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581 const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, @@ -493,6 +537,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc }, { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, { AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc }, + { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, }; int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index eccfc56be..08055ba9e 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -33,19 +33,22 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" + D_CMND_ZIGBEE_PING ; const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" // legacy prefix -- deprecated D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" + D_CMND_ZIGBEE_PING ; void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbZNPSend, &CmndZbPermitJoin, &CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, - &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind + &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, + &CmndZbPing, }; int32_t ZigbeeProcessInput(class SBuffer &buf) { @@ -367,61 +370,16 @@ void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8 ZigbeeZNPSend(buf.getBuffer(), buf.len()); } -inline int8_t hexValue(char c) { - if ((c >= '0') && (c <= '9')) { - return c - '0'; - } - if ((c >= 'A') && (c <= 'F')) { - return 10 + c - 'A'; - } - if ((c >= 'a') && (c <= 'f')) { - return 10 + c - 'a'; - } - return -1; -} - -uint32_t parseHex(const char **data, size_t max_len = 8) { - uint32_t ret = 0; - for (uint32_t i = 0; i < max_len; i++) { - int8_t v = hexValue(**data); - if (v < 0) { break; } // non hex digit, we stop parsing - ret = (ret << 4) | v; - *data += 1; - } - return ret; -} - -void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { - - uint16_t cluster = 0x0000; // 0x0000 is a valid default value - uint8_t cmd = ZCL_READ_ATTRIBUTES; // default command is READ_ATTRIBUTES - bool clusterSpecific = false; - // Parse 'cmd' in the form "AAAA_BB/CCCCCCCC" or "AAAA!BB/CCCCCCCC" - // where AA is the cluster number, BBBB the command number, CCCC... the payload - // First delimiter is '_' for a global command, or '!' for a cluster specific commanc - cluster = parseHex(&data, 4); - - // delimiter - if (('_' == *data) || ('!' == *data)) { - if ('!' == *data) { clusterSpecific = true; } - data++; - } else { - ResponseCmndChar("Wrong delimiter for payload"); - return; - } - // parse cmd number - cmd = parseHex(&data, 2); - - // move to end of payload - // delimiter is optional - if ('/' == *data) { data++; } // skip delimiter - - size_t size = strlen(data); +void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, bool clusterSpecific, + uint16_t cluster, uint8_t cmd, const char *param) { + size_t size = param ? strlen(param) : 0; SBuffer buf((size+2)/2); // actual bytes buffer for data - while (*data) { - uint8_t code = parseHex(&data, 2); - buf.add8(code); + if (param) { + while (*param) { + uint8_t code = parseHex_P(¶m, 2); + buf.add8(code); + } } if (0 == endpoint) { @@ -430,7 +388,7 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: dstAddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), - dstAddr, cluster, endpoint, cmd, data); + dstAddr, cluster, endpoint, cmd, param); if (0 == endpoint) { AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); @@ -467,6 +425,9 @@ void CmndZbSend(void) { static char delim[] = ", "; // delimiters for parameters uint16_t device = 0xFFFF; // 0xFFFF is broadcast, so considered valid uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint + // Command elements + uint16_t cluster = 0; + uint8_t cmd = 0; String cmd_str = ""; // the actual low-level command, either specified or computed // parse JSON @@ -497,8 +458,9 @@ void CmndZbSend(void) { String key = it->key; JsonVariant& value = it->value; uint32_t x = 0, y = 0, z = 0; + uint16_t cmd_var; - const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.c_str()); + const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.c_str(), &cluster, &cmd_var); if (tasmota_cmd) { cmd_str = tasmota_cmd; } else { @@ -534,9 +496,16 @@ void CmndZbSend(void) { } } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_template = %s"), cmd_str.c_str()); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_template = %s"), cmd_str.c_str()); + if (0xFF == cmd_var) { // if command number is a variable, replace it with x + cmd = x; + x = y; // and shift other variables + y = z; + } else { + cmd = cmd_var; // or simply copy the cmd number + } cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); // fill in parameters - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_final = %s"), cmd_str.c_str()); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_final = %s"), cmd_str.c_str()); } else { // we have zero command, pass through until last error for missing command } @@ -547,9 +516,9 @@ void CmndZbSend(void) { // we have an unsupported command type, just ignore it and fallback to missing command } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%s\"}"), - device, endpoint, cmd_str.c_str()); - zigbeeZCLSendStr(device, endpoint, cmd_str.c_str()); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%04X!%02X/%s\"}"), + device, endpoint, cluster, cmd, cmd_str.c_str()); + zigbeeZCLSendStr(device, endpoint, true, cluster, cmd, cmd_str.c_str()); } else { Response_P(PSTR("Missing zigbee 'Send'")); return; @@ -615,16 +584,28 @@ void CmndZbBind(void) { // Probe a specific device to get its endpoints and supported clusters void CmndZbProbe(void) { + CmndZbProbeOrPing(true); +} + +void CmndZbProbeOrPing(boolean probe) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } // everything is good, we can send the command - Z_SendActiveEpReq(shortaddr); + Z_SendIEEEAddrReq(shortaddr); + if (probe) { + Z_SendActiveEpReq(shortaddr); + } ResponseCmndDone(); } +// Ping a device, actually a simplified version of ZbProbe +void CmndZbPing(void) { + CmndZbProbeOrPing(false); +} + // Specify, read or erase a Friendly Name void CmndZbName(void) { // Syntax is: @@ -729,6 +710,11 @@ void CmndZbRead(void) { } } + if (0 == endpoint) { // try to compute the endpoint + endpoint = zigbee_devices.findClusterEndpointIn(device, cluster); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); + } + if ((0 != endpoint) && (attrs_len > 0)) { ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(device)); ResponseCmndDone(); From 21976005e13e1161031f21519ab601f3011338cf Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 23 Feb 2020 17:11:51 +0100 Subject: [PATCH 455/559] Support for BW-IS5 leak detector --- tasmota/xdrv_23_zigbee_6_commands.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 83841f90c..5c3e3fc1b 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -84,6 +84,8 @@ const Z_CommandConverter Z_Commands[] = { { "ArrowClick", 0x0005, 0x07, 0x01, "xx" }, // xx == 0x01 = left, 0x00 = right { "ArrowHold", 0x0005, 0x08, 0x01, "xx" }, // xx == 0x01 = left, 0x00 = right { "ArrowRelease", 0x0005, 0x09, 0x01, "" }, + // IAS - Intruder Alarm System + leak/fire detection + { "ZoneStatusChange",0x0500, 0x00, 0x02, "xxxxyyzz" }, // xxxx = zone status, yy = extended status, zz = zone id, Delay is ignored // responses for Group cluster commands { "AddGroupResp", 0x0004, 0x00, 0x02, "xxyyyy" }, // xx = status, yy = group id { "ViewGroupResp", 0x0004, 0x01, 0x02, "xxyyyy" }, // xx = status, yy = group id, name ignored From 9b758350b580542f556e1815c56f7f679eb2f759 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 23 Feb 2020 20:49:54 +0100 Subject: [PATCH 456/559] Fix Domoticz compile error Fix compile error when Domoticz is enabled but Lights is disabled --- tasmota/xdrv_07_domoticz.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino index 49e546b65..90563eeed 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/xdrv_07_domoticz.ino @@ -296,6 +296,7 @@ bool DomoticzMqttData(void) found = true; } else #endif // USE_SHUTTER +#ifdef USE_LIGHT if (iscolordimmer && 10 == nvalue) { // Color_SetColor // https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Set_a_light_to_a_certain_color_or_color_temperature JsonObject& color = domoticz["Color"]; @@ -333,8 +334,9 @@ bool DomoticzMqttData(void) snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); found = true; - } - else if (1 == nvalue || 0 == nvalue) { + } else +#endif // USE_LIGHT + if (1 == nvalue || 0 == nvalue) { if (((power >> i) &1) == (power_t)nvalue) { return true; // Stop loop } From 8969877502503a536f4f2df15ae0ee9d1c33383b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 23 Feb 2020 21:26:58 +0100 Subject: [PATCH 457/559] Refactor DHT driver Refactor DHT driver (#7717) --- tasmota/xsns_06_dht_v5.ino | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tasmota/xsns_06_dht_v5.ino b/tasmota/xsns_06_dht_v5.ino index f08286b43..9c7003970 100644 --- a/tasmota/xsns_06_dht_v5.ino +++ b/tasmota/xsns_06_dht_v5.ino @@ -100,6 +100,7 @@ bool DhtRead(uint32_t sensor) break; } +/* bool error = false; noInterrupts(); if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { @@ -127,6 +128,22 @@ bool DhtRead(uint32_t sensor) } interrupts(); if (error) { return false; } +*/ + + uint32_t i = 0; + noInterrupts(); + if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { + for (i = 0; i < 40; i++) { + if (!DhtWaitState(sensor, 1)) { break; } + delayMicroseconds(35); // Was 30 + if (digitalRead(Dht[sensor].pin)) { + dht_data[i / 8] |= (1 << (7 - i % 8)); + } + if (!DhtWaitState(sensor, 0)) { break; } + } + } + interrupts(); + if (i < 40) { return false; } uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; if (dht_data[4] != checksum) { From 18af25bb71ba612b6536aeb4b87c29353d16f4db Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Feb 2020 09:57:51 +0100 Subject: [PATCH 458/559] Update platformio_tasmota_env.ini --- platformio_tasmota_env.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 2a26ba4d2..cfcd53686 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -3,6 +3,7 @@ platform = ${common.platform} platform_packages = ${common.platform_packages} framework = ${common.framework} board = ${common.board} +board_build.ldscript = ${common.board_build.ldscript} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} From 3b0b9088e1e40962137493d7976edffe232498be Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Feb 2020 10:01:26 +0100 Subject: [PATCH 459/559] Update platformio.ini --- platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/platformio.ini b/platformio.ini index 16553f0d6..552408790 100755 --- a/platformio.ini +++ b/platformio.ini @@ -56,6 +56,7 @@ default_envs = framework = arduino board = esp01_1m board_build.flash_mode = dout +board_build.ldscript = eagle.flash.1m.ld platform = ${core_active.platform} platform_packages = ${core_active.platform_packages} From 25301b8cdcbd5afd8d28ef6e4108d68ccefb9655 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 24 Feb 2020 10:04:48 +0100 Subject: [PATCH 460/559] Fix using new syntax for custom LD script --- platformio_override_sample.ini | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 93bbbb5ba..0c63c6e8f 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -135,10 +135,9 @@ build_flags = ${esp82xx_defaults.build_flags} [core_2_6_3] ; *** Esp8266 core for Arduino version 2.6.3 -platform = espressif8266@2.3.2 +platform = espressif8266@2.3.3 platform_packages = build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC ; NONOSDK221 ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 @@ -180,12 +179,10 @@ build_flags = ${esp82xx_defaults.build_flags} [tasmota_core_stage] ; *** Esp8266 core for Arduino version stable beta -platform = espressif8266@2.3.2 +platform = espressif8266@2.3.3 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#6be561617f645f6a2ae82b8211f6af8c43e834cf build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC - -DNOPRINTFLOAT ; NONOSDK221 ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 ; NONOSDK22x_190313 @@ -226,12 +223,10 @@ build_flags = ${esp82xx_defaults.build_flags} [core_stage] ; *** Esp8266 core for Arduino version latest beta -platform = espressif8266@2.3.2 +platform = espressif8266@2.3.3 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git -board_build.ldscript = eagle.flash.1m.ld build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC - -DNOPRINTFLOAT ; NONOSDK221 ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 ; NONOSDK22x_190313 From 7a3a9bd364e332b8ffe3f37a98eb74ad17a5eb6c Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 24 Feb 2020 12:23:03 +0100 Subject: [PATCH 461/559] fixes and enhancements - shutterposition now reports actual position if the shutter is moving #7686 - new RuleEvent: Shutter1#Target to get upfront info where the shutter is moving - RuleExecution now every second to get an update of the current position - New functionality for Stepper Motors. Now supporting 4 Stepper shutters working simultanously --- tasmota/xdrv_27_shutter.ino | 129 +++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 59 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index c353a1dd4..0fd6d861b 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -48,7 +48,7 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime}; - const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; + const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}"; const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; #include @@ -70,7 +70,7 @@ struct SHUTTER { int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE int16_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. - int16_t pwm_frequency; // frequency of PWN for stepper motors + int16_t pwm_frequency[MAX_SHUTTERS]; // frequency of PWN for stepper motors uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency for openig the shutter. depend on the motor and drivers uint16_t max_close_pwm_frequency[MAX_SHUTTERS];// maximum of PWM frequency for closeing the shutter. depend on the motor and drivers uint8_t skip_relay_change; // avoid overrun at endstops @@ -82,17 +82,18 @@ void ShutterLogPos(uint32_t i) char stemp2[10]; dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d"), - i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_frequency); + i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_frequency[i]); } void ShutterRtc50mS(void) { - for (uint32_t i = 0; i < shutters_present; i++) { + for (uint8_t i = 0; i < shutters_present; i++) { Shutter.time[i]++; if (Shutter.accelerator[i]) { - Shutter.pwm_frequency += Shutter.accelerator[i]; - Shutter.pwm_frequency = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency)); - analogWriteFreq(Shutter.pwm_frequency); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: accelerator i=%d -> %d"),i, Shutter.accelerator[i]); + Shutter.pwm_frequency[i] += Shutter.accelerator[i]; + Shutter.pwm_frequency[i] = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency[i])); + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); } } @@ -102,8 +103,6 @@ void ShutterRtc50mS(void) int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) { - if (0 == percent) return 0; - if (100 == percent) return Shutter.open_max[index]; if (Settings.shutter_set50percent[index] != 50) { return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; } else { @@ -138,8 +137,6 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) { - if (0 >= realpos) return 0; - if (Shutter.open_max[index] <= realpos) return 100; if (Settings.shutter_set50percent[index] != 50) { return (Settings.shuttercoeff[2][index] * 5 > realpos) ? SHT_DIV_ROUND(realpos, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos-Settings.shuttercoeff[0][index], Settings.shuttercoeff[1][index]); } else { @@ -203,8 +200,9 @@ void ShutterInit(void) Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; if ((pin[GPIO_PWM1+i] < 99) && (pin[GPIO_CNTR1+i] < 99)) { Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER; - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); + Shutter.pwm_frequency[i] = 0; + Shutter.accelerator[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); } } @@ -256,29 +254,24 @@ void ShutterInit(void) void ShutterReportPosition(bool always) { - uint32_t shutter_moving = 0; Response_P(PSTR("{")); for (uint32_t i = 0; i < shutters_present; i++) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d"), i+1,Shutter.real_position[i]); uint32_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); if (Shutter.direction[i] != 0) { - shutter_moving = 1; + rules_flag.shutter_moving = 1; ShutterLogPos(i); } if (i) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i]); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i], ShutterRealToPercentPosition(Shutter.target_position[i], i)); } ResponseJsonEnd(); - if (always || (1 == shutter_moving)) { + if (always || (rules_flag.shutter_moving)) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); + XdrvRulesProcess(); } - if (rules_flag.shutter_moving > shutter_moving) { - rules_flag.shutter_moved = 1; - } else { - rules_flag.shutter_moved = 0; - } - rules_flag.shutter_moving = shutter_moving; - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); + } void ShutterLimitRealAndTargetPositions(uint32_t i) { @@ -304,22 +297,22 @@ void ShutterUpdatePosition(void) int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); - int32_t min_runtime_ms = Shutter.pwm_frequency*1000 / max_freq_change_per_sec; + int32_t min_runtime_ms = Shutter.pwm_frequency[i]*1000 / max_freq_change_per_sec; int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; - int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency / max_frequency * Shutter.direction[i] ; + int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency[i] / max_frequency * Shutter.direction[i] ; int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; - stop_position_delta =200 * Shutter.pwm_frequency/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); + stop_position_delta =200 * Shutter.pwm_frequency[i]/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); //Shutter.accelerator[i] = tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); //int32_t act_freq_change = max_freq_change_per_sec/20; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, - Shutter.pwm_frequency,max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); + Shutter.pwm_frequency[i],max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]); - } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency == max_frequency) { + } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency[i] == max_frequency) { Shutter.accelerator[i] = 0; } } else { @@ -343,13 +336,13 @@ void ShutterUpdatePosition(void) case SHT_OFF_ON__OPEN_CLOSE_STEPPER: missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; //prepare for stop PWM - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency[i]); Shutter.accelerator[i] = 0; - Shutter.pwm_frequency = Shutter.pwm_frequency > 250 ? 250 : Shutter.pwm_frequency; - analogWriteFreq(Shutter.pwm_frequency); + Shutter.pwm_frequency[i] = Shutter.pwm_frequency[i] > 250 ? 250 : Shutter.pwm_frequency[i]; + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); + Shutter.pwm_frequency[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { delay(1); } @@ -391,6 +384,7 @@ void ShutterUpdatePosition(void) Shutter.direction[i] = 0; ShutterReportPosition(true); + rules_flag.shutter_moved = 1; XdrvRulesProcess(); } } @@ -413,8 +407,8 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter.skip_relay_change = 1; } else { if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); + Shutter.pwm_frequency[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 0); // can be operated without counter, but then not that acurate. if (pin[GPIO_CNTR1+i] < 99) { @@ -435,14 +429,16 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) void ShutterWaitForMotorStop(uint32_t i) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..dir %d, akt freq: %d, max %d, maxclose %d"),Shutter.direction[i],Shutter.pwm_frequency[i], Shutter.max_pwm_frequency, Shutter.max_close_pwm_frequency[i]); if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { if (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Frequency change %d"), Shutter.pwm_frequency); - while (Shutter.pwm_frequency > 0) { - Shutter.accelerator[i] = 0; - Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); - analogWriteFreq(Shutter.pwm_frequency); + while (Shutter.pwm_frequency[i] > 0) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Frequency: %ld, delta: %d"), Shutter.pwm_frequency[i], (int32_t)((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) ); + + Shutter.pwm_frequency[i] = tmax(Shutter.pwm_frequency[i]-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Frequency: %ld"), Shutter.pwm_frequency[i]); + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); delay(50); } @@ -532,7 +528,10 @@ void ShutterButtonHandler(void) uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) - + if ( button != Button.last_state[button_index]) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d, button %d, presstate %d, lasttate %d, Settings.flag.button_single %d)"), shutter_index+1, button_index+1, button, Button.last_state[button_index], Settings.flag.button_single); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Button.press_counter[button_index] %d, Button.hold_timer[button_index] %d, Button.window_timer[button_index] %d "), Button.press_counter[button_index], Button.hold_timer[button_index], Button.window_timer[button_index] ); + } if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action buttonState = SHT_PRESSED_MULTI; @@ -542,9 +541,10 @@ void ShutterButtonHandler(void) buttonState = SHT_PRESSED_IMMEDIATE; press_index = 1; Button.press_counter[button_index] = 99; // Remember to discard further action for press & hold within button timings - } else + } else { Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window + Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window + } } blinks = 201; } @@ -596,14 +596,18 @@ void ShutterButtonHandler(void) // check for simultaneous shutter button press uint32 min_shutterbutton_press_counter = -1; for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter); + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { min_shutterbutton_press_counter = Button.press_counter[i]; + } + } if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { // simultaneous shutter button press detected + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:simultanous presss deteced")); press_index = Button.press_counter[button_index]; for (uint32_t i = 0; i < MAX_KEYS; i++) - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; } @@ -617,9 +621,13 @@ void ShutterButtonHandler(void) } } } + if (buttonState) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Final buttonState %d"), buttonState); + } if (buttonState != SHT_NOT_PRESSED) { if (buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: SHT_PRESSED_MULTI_SIMULTANEOUS")); if ((press_index>=5) && (press_index<=7) && (!Settings.flag.button_restrict)) { // 5x..7x && no SetOption1 (0) // simultaneous shutter button press 5x, 6x, 7x detected char scmnd[20]; @@ -628,7 +636,7 @@ void ShutterButtonHandler(void) return; } } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { - // simultaneous shutter button extend hold detected + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: SHT_PRESSED_EXT_HOLD_SIMULTANEOUS"));// simultaneous shutter button extend hold detected if (!Settings.flag.button_restrict) { // no SetOption1 (0) char scmnd[20]; snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); @@ -636,6 +644,7 @@ void ShutterButtonHandler(void) return; } } else if (buttonState <= SHT_PRESSED_IMMEDIATE) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: SHT_PRESSED_IMMEDIATE")); if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); if (pos_press_index>3) pos_press_index=3; @@ -647,14 +656,15 @@ void ShutterButtonHandler(void) XdrvMailbox.data = databuf; XdrvMailbox.command = NULL; if (buttonState == SHT_PRESSED_IMMEDIATE) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } - else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: SHT_PRESSED_IMMEDIATE stop")); + //XdrvMailbox.payload = XdrvMailbox.index; + //CmndShutterStop(); + } else { uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; if (position) { if (Shutter.direction[shutter_index]) { XdrvMailbox.payload = XdrvMailbox.index; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: immegency stop")); CmndShutterStop(); } else { XdrvMailbox.payload = position = (position-1)<<1; @@ -670,12 +680,12 @@ void ShutterButtonHandler(void) Response_P("%d", position); MqttPublish(stopic, false); } - } - } - } - } - } - } + } // for (uint32_t) + } // if (Settings.shutter) + } // ende else + } // if (position) + } // end else + } // if if (Settings.shutter_startrelay[shutter_index] } Response_P(PSTR("{")); ResponseAppend_P(JSON_SHUTTER_BUTTON, shutter_index+1, (buttonState <= SHT_PRESSED_IMMEDIATE) ? (button_index+1) : 0, press_index); @@ -756,6 +766,7 @@ void CmndShutterPosition(void) AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); // value 0 with data_len > 0 can mean Open + // special handling fo UP,DOWN,TOGGLE,STOP command comming with payload -99 if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { //UpperCase(XdrvMailbox.data, XdrvMailbox.data); if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { @@ -773,13 +784,13 @@ void CmndShutterPosition(void) } } - int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? 0 : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); + int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? (XdrvMailbox.payload == -99 ? ShutterRealToPercentPosition(Shutter.real_position[index], index) : 0) : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); // webgui still send also on inverted shutter the native position. target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; if (XdrvMailbox.payload != -99) { //target_pos_percent = (Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent; Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); - Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); + //Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); } From 66a1dc957336b1a4d9a86f910d45fc4cdee3a5bf Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 24 Feb 2020 12:33:52 +0100 Subject: [PATCH 462/559] Update xdrv_27_shutter.ino - fixed shutter#moved rule not triggered --- tasmota/xdrv_27_shutter.ino | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 0fd6d861b..4c8ae1d52 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -429,15 +429,14 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) void ShutterWaitForMotorStop(uint32_t i) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..dir %d, akt freq: %d, max %d, maxclose %d"),Shutter.direction[i],Shutter.pwm_frequency[i], Shutter.max_pwm_frequency, Shutter.max_close_pwm_frequency[i]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { if (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Frequency change %d"), Shutter.pwm_frequency); while (Shutter.pwm_frequency[i] > 0) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Frequency: %ld, delta: %d"), Shutter.pwm_frequency[i], (int32_t)((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) ); - + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Frequency: %ld, delta: %d"), Shutter.pwm_frequency[i], (int32_t)((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) ); Shutter.pwm_frequency[i] = tmax(Shutter.pwm_frequency[i]-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Frequency: %ld"), Shutter.pwm_frequency[i]); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Frequency: %ld"), Shutter.pwm_frequency[i]); analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); delay(50); @@ -528,10 +527,6 @@ void ShutterButtonHandler(void) uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) - if ( button != Button.last_state[button_index]) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d, button %d, presstate %d, lasttate %d, Settings.flag.button_single %d)"), shutter_index+1, button_index+1, button, Button.last_state[button_index], Settings.flag.button_single); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Button.press_counter[button_index] %d, Button.hold_timer[button_index] %d, Button.window_timer[button_index] %d "), Button.press_counter[button_index], Button.hold_timer[button_index], Button.window_timer[button_index] ); - } if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action buttonState = SHT_PRESSED_MULTI; @@ -543,7 +538,6 @@ void ShutterButtonHandler(void) Button.press_counter[button_index] = 99; // Remember to discard further action for press & hold within button timings } else { Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window } } blinks = 201; @@ -597,7 +591,7 @@ void ShutterButtonHandler(void) uint32 min_shutterbutton_press_counter = -1; for (uint32_t i = 0; i < MAX_KEYS; i++) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter); - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) min_shutterbutton_press_counter = Button.press_counter[i]; } @@ -621,13 +615,9 @@ void ShutterButtonHandler(void) } } } - if (buttonState) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Final buttonState %d"), buttonState); - } if (buttonState != SHT_NOT_PRESSED) { if (buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: SHT_PRESSED_MULTI_SIMULTANEOUS")); if ((press_index>=5) && (press_index<=7) && (!Settings.flag.button_restrict)) { // 5x..7x && no SetOption1 (0) // simultaneous shutter button press 5x, 6x, 7x detected char scmnd[20]; @@ -636,7 +626,6 @@ void ShutterButtonHandler(void) return; } } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: SHT_PRESSED_EXT_HOLD_SIMULTANEOUS"));// simultaneous shutter button extend hold detected if (!Settings.flag.button_restrict) { // no SetOption1 (0) char scmnd[20]; snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); @@ -644,7 +633,6 @@ void ShutterButtonHandler(void) return; } } else if (buttonState <= SHT_PRESSED_IMMEDIATE) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: SHT_PRESSED_IMMEDIATE")); if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); if (pos_press_index>3) pos_press_index=3; @@ -656,15 +644,13 @@ void ShutterButtonHandler(void) XdrvMailbox.data = databuf; XdrvMailbox.command = NULL; if (buttonState == SHT_PRESSED_IMMEDIATE) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: SHT_PRESSED_IMMEDIATE stop")); - //XdrvMailbox.payload = XdrvMailbox.index; - //CmndShutterStop(); + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); } else { uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; if (position) { if (Shutter.direction[shutter_index]) { XdrvMailbox.payload = XdrvMailbox.index; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: immegency stop")); CmndShutterStop(); } else { XdrvMailbox.payload = position = (position-1)<<1; From b54f2d406eca8853dbaaffef33d89897fdc5437d Mon Sep 17 00:00:00 2001 From: stefanbode Date: Mon, 24 Feb 2020 12:38:00 +0100 Subject: [PATCH 463/559] Update xdrv_27_shutter.ino --- tasmota/xdrv_27_shutter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 4c8ae1d52..6f4d711d7 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -591,7 +591,7 @@ void ShutterButtonHandler(void) uint32 min_shutterbutton_press_counter = -1; for (uint32_t i = 0; i < MAX_KEYS; i++) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter); - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { min_shutterbutton_press_counter = Button.press_counter[i]; } From 94c9072815e0aab9397bcf6871f9cd24d4068cbb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 24 Feb 2020 13:27:22 +0100 Subject: [PATCH 464/559] Add wifi debug code --- tasmota/settings.ino | 42 +++++++++++++++++++++++++++++++++++++--- tasmota/support_wifi.ino | 5 +++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 33da93562..c2ddc6607 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -277,6 +277,23 @@ bool RtcRebootValid(void) /*********************************************************************************************\ * Config - Flash + * + * Tasmota 1M flash usage + * 0x00000000 - Unzipped binary bootloader + * 0x00001000 - Unzipped binary code start + * :::: + * 0x000xxxxx - Unzipped binary code end + * 0x000x1000 - First page used by Core OTA + * :::: + * 0x000F3000 - Tasmota Quick Power Cycle counter (SETTINGS_LOCATION - CFG_ROTATES) - First four bytes only + * 0x000F4000 - First Tasmota rotating settings page + * :::: + * 0x000FA000 - Last Tasmota rotating settings page = Last page used by Core OTA + * 0x000FB000 - Core SPIFFS end = Core EEPROM = Tasmota settings page during OTA and when no flash rotation is active (SETTINGS_LOCATION) + * 0x000FC000 - SDK - Uses first 128 bytes for phy init data mirrored by Core in RAM. See core_esp8266_phy.cpp phy_init_data[128] = Core user_rf_cal_sector + * 0x000FD000 - SDK - Uses scattered bytes from 0x340 (iTead use as settings storage from 0x000FD000) + * 0x000FE000 - SDK - Uses scattered bytes from 0x340 (iTead use as mirrored settings storage from 0x000FE000) + * 0x000FF000 - SDK - Uses at least first 32 bytes of this page - Tasmota Zigbee persistence from 0x000FF800 to 0x000FFFFF \*********************************************************************************************/ extern "C" { @@ -745,8 +762,17 @@ void SettingsErase(uint8_t type) _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; // Flash size as seen by SDK } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart); +#ifdef USE_WIFI_SDK_ERASE + else if (4 == type) { + _sectorStart = SETTINGS_LOCATION +1; // SDK phy area and Core calibration sector (0x0FC000) + _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0x0FCFFF) + } + else if (5 == type) { + _sectorStart = (ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE) -4; // SDK phy area and Core calibration sector (0xxFC000) + _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0xxFCFFF) + } +#endif // USE_WIFI_SDK_ERASE + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); // EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK EsptoolErase(_sectorStart, _sectorEnd); // Esptool - erases flash completely @@ -755,11 +781,21 @@ void SettingsErase(uint8_t type) void SettingsSdkErase(void) { - WiFi.disconnect(true); // Delete SDK wifi config + WiFi.disconnect(false); // Delete SDK wifi config SettingsErase(1); delay(1000); } +#ifdef USE_WIFI_SDK_ERASE +void SettingsSdkWifiErase(void) +{ + WiFi.disconnect(false); // Delete SDK wifi config + SettingsErase(4); + SettingsErase(5); + delay(200); +} +#endif // USE_WIFI_SDK_ERASE + /********************************************************************************************/ void SettingsDefault(void) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index df509b9d3..866ca4eee 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -620,12 +620,17 @@ void WifiConnect(void) // Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset void WifiDisconnect(void) { +#ifdef USE_WIFI_SDK_ERASE // Do not enable with DeepSleep as it will wear out flash + SettingsSdkWifiErase(); +#else // Courtesy of EspEasy WiFi.persistent(true); // use SDK storage of SSID/WPA parameters ETS_UART_INTR_DISABLE(); wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage ETS_UART_INTR_ENABLE(); WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters + delay(100); // Flush anything in the network buffers. +#endif // USE_WIFI_SDK_ERASE } void WifiShutdown(void) From 9fdd5e25de2789a376d749fcd0615c2478d29a91 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 07:15:19 -0600 Subject: [PATCH 465/559] Add Device_Groups.md --- Device_Groups.md | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Device_Groups.md diff --git a/Device_Groups.md b/Device_Groups.md new file mode 100644 index 000000000..c5990136f --- /dev/null +++ b/Device_Groups.md @@ -0,0 +1,45 @@ +# Device Groups + +The device groups module provides a framework to allow multiple devices to be in a group with values such as power, light color/temperature/brightness, PWM values, sensor values, etc. shared with other devices in the group. For example, with multiple light modules in a device group, the light settings can be changed on one module and the settings will automatically be changed on the other light modules. Dimmer switch modules could be in a device group with light modules and the dimmer switch could control the power, brightness and colors of all the lights in the group. Multiple dimmer switches could be in a device group to form a 3-way/4-way dimmer switch. + +UDP broadcasts, followed by UDP unicasts if necessary, are used to send updates to all devices so updates are fast. There is no need for an MQTT server but all the devices in a group must be on the same IP network. + +To include device groups support in the build, define USE_DEVICE_GROUPS in your user_config_override. This adds 3.5K to the code size. All devices in a group must be running firmware with device group support and have device groups enabled. + +To enable device groups, set Option16 to 1 and **restart the device**. + + +## Device Groups Operation + +The device group name is the MQTT group topic set with the GroupTopic command. All devices in the same IP network with the same group topic are in the same group. Some modules may define additional device groups. For example, if Remote Device Mode is enabled, the PWM Dimmer module defines three devices groups. + +The items that are sent to the group and the items that are received from the group are selected with the DevGroupShare command. By default all items are sent and received from the group. An example of when the DevGroupShare command would be used is when you have a group of lights that you control with a dimmer switch and home automation software. You want the dimmer switch to be able to control all items. The home automation software controls each light individually. When it controls the whole group, it actually sends command to each light in the group. If you use the home automation software to turn an individual light on or off or change it’s brightness, color or scheme, you do not want the change to be replicated to the other lights. In this case, you would set the incoming and outgoing item masks to 255 on the dimmer switch (DevGroupShare 255,255) and set the incoming item mask to 255 and outgoing item mask to 0 on all the lights (DevGroupShare 255,0). + + +### Commands + + + + + + + + + + + + + + + +
Command + Parameters +
DevGroupShare + ,<out> = set incoming and outgoing shared item mask (default = 255,255) +

+1 = Power, 2 = Light brightness, 4 = Light fade/speed, 8 = Light scheme, 16 = Light color, 32 = Minimum brightness +

GroupTopic<x> + 1 = reset device group <x> MQTT group topic to firmware default (MQTT_GRPTOPIC) and restart +

+ = set device group <x> MQTT group topic (32 chars max) and restart +

From c0a5156d8f2b04079b5cb746d1f63f8be7bf00d1 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 07:19:15 -0600 Subject: [PATCH 466/559] Initial pwm dimmer support --- BUILDS.md | 7 + I2CDEVICES.md | 1 + MODULES.md | 1 + PWM_Dimmer.md | 197 ++++ RELEASENOTES.md | 3 +- TEMPLATES.md | 1 + platformio.ini | 1 + platformio_override_sample.ini | 11 +- platformio_tasmota_env.ini | 1 + tasmota/CHANGELOG.md | 3 + tasmota/i18n.h | 8 + tasmota/my_user_config.h | 4 +- tasmota/settings.h | 14 + tasmota/settings.ino | 42 +- tasmota/support_features.ino | 5 +- tasmota/support_tasmota.ino | 6 + tasmota/tasmota_post.h | 10 + tasmota/tasmota_template.h | 31 + tasmota/xdrv_01_webserver.ino | 11 + tasmota/xdrv_04_light.ino | 11 +- tasmota/xdrv_07_domoticz.ino | 6 +- tasmota/xdrv_12_home_assistant.ino | 8 +- tasmota/xdrv_23_zigbee_1_headers.ino | 2 +- tasmota/xdrv_23_zigbee_3_devices.ino | 31 +- tasmota/xdrv_23_zigbee_5_converters.ino | 12 +- tasmota/xdrv_23_zigbee_6_commands.ino | 265 ++++- tasmota/xdrv_23_zigbee_7_statemachine.ino | 1 + tasmota/xdrv_23_zigbee_8_parsers.ino | 53 +- tasmota/xdrv_23_zigbee_9_impl.ino | 123 +-- tasmota/xdrv_27_shutter.ino | 109 +- tasmota/xdrv_35_pwm_dimmer.ino | 1141 +++++++++++++++++++++ tasmota/xsns_06_dht_v5.ino | 17 + tasmota/xsns_61_MI_NRF24.ino | 121 ++- tools/decode-status.py | 4 +- 34 files changed, 2037 insertions(+), 224 deletions(-) create mode 100644 PWM_Dimmer.md create mode 100644 tasmota/xdrv_35_pwm_dimmer.ino diff --git a/BUILDS.md b/BUILDS.md index aa1834061..88ee58cd0 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -62,6 +62,7 @@ | USE_DDS2382 | - | - | - | - | x | - | - | | USE_DDSU666 | - | - | - | - | x | - | - | | USE_SOLAX_X1 | - | - | - | - | - | - | - | +| USE_LE01MR | - | - | - | - | - | - | - | | | | | | | | | | | USE_ADC_VCC | x | x | - | - | - | - | - | | USE_COUNTER | - | - | x | x | x | x | x | @@ -109,6 +110,8 @@ | USE_HIH6 | - | - | - | - | x | - | - | | USE_DHT12 | - | - | - | - | x | - | - | | USE_DS1624 | - | - | - | - | x | - | - | +| USE_AHT1x | - | - | - | - | - | - | - | +| USE_WEMOS_MOTOR_V1 | - | - | - | - | x | - | - | | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | @@ -124,6 +127,10 @@ | USE_RDM6300 | - | - | - | - | x | - | - | | USE_IBEACON | - | - | - | - | x | - | - | | USE_GPS | - | - | - | - | - | - | - | +| USE_HM10 | - | - | - | - | x | - | - | +| | | | | | | | | +| USE_NRF24 | - | - | - | - | - | - | - | +| USE_MIBLE | - | - | - | - | - | - | - | | USE_ZIGBEE | - | - | - | - | - | - | - | | | | | | | | | | | USE_IR_REMOTE | - | - | x | x | x | x | x | diff --git a/I2CDEVICES.md b/I2CDEVICES.md index b607b3241..f9cf5b0e3 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -65,3 +65,4 @@ Index | Define | Driver | Device | Address(es) | Description 42 | USE_DS1624 | xsns_59 | DS1621 | 0x48 - 0x4F | Temperature sensor 42 | USE_DS1624 | xsns_59 | DS1624 | 0x48 - 0x4F | Temperature sensor 43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 | Temperature and humidity sensor + 44 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x2D - 0x30 | WEMOS motor shield v1.0.0 (6612FNG) diff --git a/MODULES.md b/MODULES.md index bb02bfe73..be1d5d110 100644 --- a/MODULES.md +++ b/MODULES.md @@ -76,5 +76,6 @@ Module | Description 70 Sonoff L1 | Sonoff L1 light strip 71 Sonoff iFan03 | Sonoff iFan03 Wifi Smart Ceiling Fan with Light 72 EXS Dimmer | EXS Wifi Dimmer v4 +73 PWM Dimmer | Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM Dimmer Switches Over 600 additional devices are supported using [templates](TEMPLATES.md). diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md new file mode 100644 index 000000000..528b3f9fb --- /dev/null +++ b/PWM_Dimmer.md @@ -0,0 +1,197 @@ +# PWM Dimmer + +The PWM Dimmer module adds support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches. The brightness of the load for these dimmers is controlled by a PWM GPIO pin. They typically have power, up and down buttons, a powered-on LED, five brightness LEDs and another status LED. Examples are:[ https://www.amazon.com/dp/B07FXYSVR1](https://www.amazon.com/dp/B07FXYSVR1),[ https://www.amazon.com/dp/B07V26Q3VD](https://www.amazon.com/dp/B07V26Q3VD),[ https://www.amazon.com/dp/B07K67D43J](https://www.amazon.com/dp/B07K67D43J),[ https://www.amazon.com/dp/B07TTGFWFM](https://www.amazon.com/dp/B07TTGFWFM) + +To include PWM dimmer support in the build, define USE_PWM_DIMMER in your user_config_override. This adds 4.5K to the code size. The light module is not required for PWM dimmer operation so you can #undef USE_LIGHT to reduce the firmware bin size. + +To enable PWM dimmer operation, select the PWM Dimmer module. + + +## PWM Dimmer Operation + +Pressing and releasing the power button toggles the power on/off. If the toggle turns the power on, the load is returned to the last brightness it was adjusted to. If Fade is enabled, the load is faded on/off at the rate defined by the Speed setting. + +When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster as higher brightnesses. The BriMin command defines the lowest value the brightness can be decreased to. + +The brightness can also be changed using just the power button. When the power is on, holding the power button alternately increases or decreases the brightness. Initially, holding the power button increases the brightness. Releasing and then holding the power button again decreases the brightness. + +When the power is off, holding the down or up button turns the power on at a temporary brightness of the low/high levels set by the BriPreset command (default =10,255). Turning the power on at the low preset can also be accomplished by holding the power button while the power is off. The brightness presets are intended to enable quickly turning on a light to a dim or bright level without changing the normal desired brightness. Turning the power on to a preset does not change the brightness the load will be set to when the switch is turned on the next time. For example, if the light is on and you adjust the brightness to 80 and then turn the light off, when you turn it back on, the brightness will return to 80. If you turn the power off again and then press the down button, the light will be turned on with a brightness of the low preset. If you then turn the light off and on again, the brightness will return to 80. + +If there are LED’s defined in the template, they are turned on to indicate the current brightness. More LEDs are turned on at higher brightnesses. The LedTimeout command enables/disables an LED timeout. If LED timeout is enabled, the LED’s turn off five seconds after the last change in brightness. Note that the lowest LED and the blue power LED are always on when the power is on. + +The LEDLink LED can be used as a nightlight/powered-off indicator. The PoweredOffLed command enables/disables turning the LEDLink LED on when the power is off. + +Tapping (pressing and releasing quickly) the down or up buttons a given number of times and then holding the down or up button decreases or increases settings according to the table below. For example, tapping the down button once and then holding the up button sets all RGB lights in the device group to the next fixed color. Tapping the up button three times and then holding the down button decreases the high brightness preset. + + + + + + + + + + + + + + + + + + + + + + + +
Taps + Down Button + Up Button +
1 + Set fixed color1 + Publish MQTT event2 +
2 + Adjust minimum brightness + Adjust fade speed +
3 + Adjust low brightness preset + Adjust high brightness preset +
+ + +1. Setting the previous/next color only functions when remote device mode is enabled (see below) and only when the switch is in a device group with an RGB light. The color sequence as defined by the Light module is red, green, blue, orange, light green, light blue, amber, cyan, purple, yellow, pink, white using RGB channels, white using CT channels. + +2. The MQTT topic has the format %group-topic%/cmnd/Event, where %group-topic% is the group topic set by the GroupTopic command. The MQTT payload is SwitchTrigger#, where # is 1 if the down button is held or 2 if the up button is held. These triggers can be used in rules on remote devices (ON Event#SwitchTrigger1) or by automation software to trigger automations such as scene changes. For example, the Event topic SwitchTrigger1 payload could trigger the automation software to turn on the previous scene in a list and the SwitchTrigger2 payload could trigger the automation software to turn on the next scene in a list. + +Holding the power button, pressing the down/up buttons a given number of times and then releasing the power button toggles options according to the table below. Note that you must press a down or up button within 0.5 seconds to prevent the power button hold action from taking place. + + + + + + + + + + + + + + + + + + +
Presses + Down Button + Up Button +
1 + Toggle powered-off LED + Toggle brightness LED timeout +
2 + Toggle fading + +
+ + +Holding any button for over 10 seconds executes the WiFiConfig 2 command. + +When Device Groups are enabled, the PWM Dimmer minimum brightness and brightness presets are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. + + +### Commands + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Command + Parameters +
BriMin + 1..255 = set minimum brightness +

++ = increase minimum brightness +

+- = decrease minimum brightness +

BriPreset + ,<high> = set brightness low and high presets +

+1..255 = set brightness preset +

++ = increase brightness preset +

+- = decrease brightness preset +

Dimmer + 0..100 = set dimmer value from 0 to 100% +

++ = increase by 10 +

+- = decrease by 10 +

Fade + 0 = do not use fade (default) +

+1 = use fade +

LedTimeout + 0 = disable LED timeout +

+1 = enable LED timeout +

PoweredOffLed + 0 = disable powered-off LED +

+1 = disable powered-off LED +

Speed + 1..20 = set fade speed from fast 1 to very slow 20 +

++ = increase speed +

+- = decrease speed +

+ + + +### Remote Device Mode + +Remote device mode allows PWM Dimmer switches to control remote devices. With remote device mode enabled, each button controls a different device. Note that dimmer switches with toggle-style down/up buttons have limited functionality as remote device mode switches because you can not push the down and up buttons simultaneously. + +To include remote device mode support in the build, define USE_PWM_DIMMER_REMOTE in your user_config_override. Remote device mode support requires device group support so USE_DEVICE_GROUPS is automatically defined if USE_PWM_DIMMER_REMOTE is defined. Remote device mode support adds 0.7K to the code size in addition to the code size required for device groups support. + +To enable remote device mode, set Option71 to 1. Each remote device must be running firmware with device group support and have remote device support enabled. The remote devices do not need to be built with PWM dimmer support nor do they need to be switches. + +If a remote device is a PWM dimmer, the device acts like a 3-way dimmer switch would and may or may not have a load connected to it. It’s also possible to use a PWM dimmer switch without a load to act as a wall switch to control the power, brightness and color of one or more smart lights with Tasmota with device group support loaded on them. + +With remote device mode enabled, button 1 is the power button for the local device while buttons 2 and 3 are the power buttons for remote devices. Group names for buttons 2 and 3 are set by the GroupTopic2 and GroupTopic3 commands respectively. Note that the button numbers are defined by the module template and can be in any physical order on the switch (button 1 can be defined as the top button, the middle button or the bottom button). + +Pressing and releasing a power button toggles the power on all devices in the group assigned to the button. When the power is on, holding the button alternately increases or decreases the brightness. When the power is off, holding the button turns the power on at a temporary brightness of the low level set by the BriPreset command (default =10). + +While holding a power button, the other two buttons act like the down and up buttons for the remote device. All the functions performed by the down and up buttons in non-remote device mode are available in remote device mode. While holding button 1, button 2 performs the functions of the down button and button 3 performs the functions of the up button. While holding button 2, button 1 performs the functions of the down button and button 3 performs the functions of the up button. While holding button 3, button 1 performs the functions of the down button and button 2 performs the functions of the up button. diff --git a/RELEASENOTES.md b/RELEASENOTES.md index dba7abeed..e5e08674c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -103,4 +103,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for FiF LE-01MR energy meter by saper-2 (#7584) - Add new DHT driver. The old driver can still be used using define USE_DHT_OLD (#7468) - Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717) -- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) \ No newline at end of file +- Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) +- Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) diff --git a/TEMPLATES.md b/TEMPLATES.md index 2cb5b4773..d922a4174 100644 --- a/TEMPLATES.md +++ b/TEMPLATES.md @@ -130,6 +130,7 @@ Kingart Touch {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255 Moes DS01 {"NAME":"MOES - DS01","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} Moes QS-WiFi-D01 Dimmer 150W {"NAME":"WiFi-Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,42,37,0,0],"FLAG":0,"BASE":18} PS-16-DZ {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58} +PWM Dimmer {"NAME":"PWM Dimmer","GPIO":[19,18,0,59,158,58,0,0,57,37,56,122,29],"FLAG":0,"BASE":73} Zemismart KS-7011 {"NAME":"KS-7011 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} ``` diff --git a/platformio.ini b/platformio.ini index 16553f0d6..552408790 100755 --- a/platformio.ini +++ b/platformio.ini @@ -56,6 +56,7 @@ default_envs = framework = arduino board = esp01_1m board_build.flash_mode = dout +board_build.ldscript = eagle.flash.1m.ld platform = ${core_active.platform} platform_packages = ${core_active.platform_packages} diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 93bbbb5ba..0c63c6e8f 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -135,10 +135,9 @@ build_flags = ${esp82xx_defaults.build_flags} [core_2_6_3] ; *** Esp8266 core for Arduino version 2.6.3 -platform = espressif8266@2.3.2 +platform = espressif8266@2.3.3 platform_packages = build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC ; NONOSDK221 ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 @@ -180,12 +179,10 @@ build_flags = ${esp82xx_defaults.build_flags} [tasmota_core_stage] ; *** Esp8266 core for Arduino version stable beta -platform = espressif8266@2.3.2 +platform = espressif8266@2.3.3 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#6be561617f645f6a2ae82b8211f6af8c43e834cf build_flags = ${esp82xx_defaults.build_flags} - -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC - -DNOPRINTFLOAT ; NONOSDK221 ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 ; NONOSDK22x_190313 @@ -226,12 +223,10 @@ build_flags = ${esp82xx_defaults.build_flags} [core_stage] ; *** Esp8266 core for Arduino version latest beta -platform = espressif8266@2.3.2 +platform = espressif8266@2.3.3 platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git -board_build.ldscript = eagle.flash.1m.ld build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC - -DNOPRINTFLOAT ; NONOSDK221 ; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221 ; NONOSDK22x_190313 diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index 2a26ba4d2..cfcd53686 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -3,6 +3,7 @@ platform = ${common.platform} platform_packages = ${common.platform_packages} framework = ${common.framework} board = ${common.board} +board_build.ldscript = ${common.board_build.ldscript} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 2689a7222..ef9ce17f4 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,9 @@ - Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) - Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) +- Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) +- Fix Zigbee auto-increment transaction number (#7757) +- Add Zigbee enhanced commands decoding, added ``ZbPing`` ### 8.1.0.8 20200212 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index cb9bb1196..630da2f6f 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -532,6 +532,14 @@ // Commands xdrv_32_hotplug.ino #define D_CMND_HOTPLUG "HotPlug" +// Commands xdrv_34_pwm_dimmer.ino +#ifdef USE_PWM_DIMMER +#define D_CMND_BRI_MIN "BriMin" +#define D_CMND_BRI_PRESET "BriPreset" +#define D_CMND_LED_TIMEOUT "LedTimeout" +#define D_CMND_POWERED_OFF_LED "PoweredOffLed" +#endif + // Commands xsns_02_analog.ino #define D_CMND_ADCPARAM "AdcParam" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 57e10c955..0d43b9489 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -415,7 +415,9 @@ //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug -// #define USE_DEVICE_GROUPS // Add support for device groups (+4k code) +// #define USE_DEVICE_GROUPS // Add support for device groups (+3k5 code) +// #define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) +// #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/settings.h b/tasmota/settings.h index 972af6974..88862f090 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -578,4 +578,18 @@ typedef union { #define device_group_share_in domoticz_sensor_idx[0] // Bitmask of device group items imported #define device_group_share_out domoticz_sensor_idx[1] // Bitmask of device group items exported +// Settings re-purposed for the PWM_DIMMER module +#ifdef USE_PWM_DIMMER +#define led_timeout light_signal // SetOption18 - Turn brightness LED's off 5 seconds after last change +#define powered_off_led buzzer_enable // SetOption67 - Turn red LED on when powered off +#define bri_power_on pcf8574_config[0] // Brightness when next powered-on +#define bri_min pcf8574_config[1] // Minimum brightness +#define bri_preset_low pcf8574_config[2] // Bri preset low +#define bri_preset_high pcf8574_config[3] // Bri preset high +#define button_devices pcf8574_config[4] // Button-device map +#ifdef USE_PWM_DIMMER_REMOTE +#define remote_device_mode dds2382_model // SetOption71 - Buttons control remote devices +#endif // USE_PWM_DIMMER_REMOTE +#endif // USE_PWM_DIMMER + #endif // _SETTINGS_H_ diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 33da93562..c2ddc6607 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -277,6 +277,23 @@ bool RtcRebootValid(void) /*********************************************************************************************\ * Config - Flash + * + * Tasmota 1M flash usage + * 0x00000000 - Unzipped binary bootloader + * 0x00001000 - Unzipped binary code start + * :::: + * 0x000xxxxx - Unzipped binary code end + * 0x000x1000 - First page used by Core OTA + * :::: + * 0x000F3000 - Tasmota Quick Power Cycle counter (SETTINGS_LOCATION - CFG_ROTATES) - First four bytes only + * 0x000F4000 - First Tasmota rotating settings page + * :::: + * 0x000FA000 - Last Tasmota rotating settings page = Last page used by Core OTA + * 0x000FB000 - Core SPIFFS end = Core EEPROM = Tasmota settings page during OTA and when no flash rotation is active (SETTINGS_LOCATION) + * 0x000FC000 - SDK - Uses first 128 bytes for phy init data mirrored by Core in RAM. See core_esp8266_phy.cpp phy_init_data[128] = Core user_rf_cal_sector + * 0x000FD000 - SDK - Uses scattered bytes from 0x340 (iTead use as settings storage from 0x000FD000) + * 0x000FE000 - SDK - Uses scattered bytes from 0x340 (iTead use as mirrored settings storage from 0x000FE000) + * 0x000FF000 - SDK - Uses at least first 32 bytes of this page - Tasmota Zigbee persistence from 0x000FF800 to 0x000FFFFF \*********************************************************************************************/ extern "C" { @@ -745,8 +762,17 @@ void SettingsErase(uint8_t type) _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; // Flash size as seen by SDK } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart); +#ifdef USE_WIFI_SDK_ERASE + else if (4 == type) { + _sectorStart = SETTINGS_LOCATION +1; // SDK phy area and Core calibration sector (0x0FC000) + _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0x0FCFFF) + } + else if (5 == type) { + _sectorStart = (ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE) -4; // SDK phy area and Core calibration sector (0xxFC000) + _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0xxFCFFF) + } +#endif // USE_WIFI_SDK_ERASE + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); // EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK EsptoolErase(_sectorStart, _sectorEnd); // Esptool - erases flash completely @@ -755,11 +781,21 @@ void SettingsErase(uint8_t type) void SettingsSdkErase(void) { - WiFi.disconnect(true); // Delete SDK wifi config + WiFi.disconnect(false); // Delete SDK wifi config SettingsErase(1); delay(1000); } +#ifdef USE_WIFI_SDK_ERASE +void SettingsSdkWifiErase(void) +{ + WiFi.disconnect(false); // Delete SDK wifi config + SettingsErase(4); + SettingsErase(5); + delay(200); +} +#endif // USE_WIFI_SDK_ERASE + /********************************************************************************************/ void SettingsDefault(void) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index ba1a2e465..b6101b1cf 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -516,7 +516,10 @@ void GetFeatures(void) #ifdef USE_AHT1x feature5 |= 0x10000000; // xsns_63_aht1x.ino #endif -// feature5 |= 0x20000000; +#ifdef USE_WEMOS_MOTOR_V1 + feature5 |= 0x20000000; // xdrv_34_wemos_motor_v1.ino +#endif + // feature5 |= 0x40000000; // feature5 |= 0x80000000; diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index b4d699cb6..ad9b38165 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -640,6 +640,12 @@ void MqttShowState(void) break; } #endif // USE_SONOFF_IFAN +#ifdef USE_PWM_DIMMER + if (PWM_DIMMER == my_module_type) { + ResponseAppend_P(PSTR(",\"" D_CMND_DIMMER "\":%d,\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d"), + Settings.light_dimmer, GetStateText(Settings.light_fade), Settings.light_speed); + } +#endif // USE_PWM_DIMMER #ifdef USE_LIGHT } #endif diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index fc94e5167..a8ff65967 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -708,6 +708,16 @@ const char kDeviceGroupMessage[] PROGMEM = DEVICE_GROUP_MESSAGE; uint8_t device_group_count = 1; #endif // USE_DEVICE_GROUPS +#ifdef USE_PWM_DIMMER_REMOTE +#ifdef USE_PWM_DIMMER +#ifndef USE_DEVICE_GROUPS +#define USE_DEVICE_GROUPS +#endif // USE_DEVICE_GROUPS +#else // USE_PWM_DIMMER +#undef USE_PWM_DIMMER_REMOTE +#endif // USE_PWM_DIMMER +#endif // USE_PWM_DIMMER_REMOTE + #ifdef DEBUG_TASMOTA_CORE #define DEBUG_CORE_LOG(...) AddLog_Debug(__VA_ARGS__) #else diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index c4ee7b19d..6f5aa0f8c 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -418,6 +418,7 @@ enum SupportedModules { SONOFF_L1, SONOFF_IFAN03, EXS_DIMMER, + PWM_DIMMER, MAXMODULE}; #define USER_MODULE 255 @@ -864,6 +865,9 @@ const uint8_t kModuleNiceList[] PROGMEM = { #endif #ifdef USE_EXS_DIMMER EXS_DIMMER, +#endif +#ifdef USE_PWM_DIMMER + PWM_DIMMER, #endif H801, // Light Devices MAGICHOME, @@ -2204,6 +2208,33 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO14 0, // GPIO15 0, 0 + }, + { "PWM Dimmer", // PWM_DIMMER - Support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM + // dimmer switches. The brightness of the load for these dimmers is + // controlled by a PWM GPIO pin. There are typically power, up & down + // buttons and 4 LED's. Examples are: + // https://www.amazon.com/dp/B07FXYSVR1 + // https://www.amazon.com/dp/B07V26Q3VD + // https://www.amazon.com/dp/B07K67D43J + // https://www.amazon.com/dp/B07TTGFWFM + GPIO_KEY3, // GPIO00 Up button + GPIO_KEY2, // GPIO01 Down button + 0, // GPIO02 + GPIO_LED4_INV, // GPIO03 Level 5 LED + GPIO_LEDLNK_INV, // GPIO04 LED Link + GPIO_LED3_INV, // GPIO05 Level 4 LED + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 (SD_DATA2 Flash QIO or ESP8285) + 0, // GPIO10 (SD_DATA3 Flash QIO or ESP8285) + // GPIO11 (SD_CMD Flash) + GPIO_LED2_INV, // GPIO12 Level 3 LED + GPIO_PWM1, // GPIO13 Dimmer PWM + GPIO_LED1_INV, // GPIO12 Level 2 LED + GPIO_KEY1_INV, // GPIO15 Power button + GPIO_REL1_INV, // GPIO16 Power relay/Level 1 LED + 0 } }; diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 3eaa24ef5..377799a72 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1123,6 +1123,17 @@ void HandleRoot(void) } // Settings.flag3.pwm_multi_channels } #endif // USE_LIGHT +#ifdef USE_PWM_DIMMER + if (PWM_DIMMER == my_module_type) { + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Brightness - Black to White + "c", // c - Unique HTML id + "#000", "#fff", // Black to White + 4, // sl4 - Unique range HTML id - Used as source for Saturation begin color + Settings.flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% + Settings.light_dimmer, + 'd', 0); // d0 - Value id is related to lc("d0", value) and WebGetArg("d0", tmp, sizeof(tmp)); + } +#endif // USE_PWM_DIMMER #ifdef USE_SHUTTER if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support for (uint32_t i = 0; i < shutters_present; i++) { diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index baaf2b7a7..d54598077 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2588,6 +2588,8 @@ void CmndRgbwwTable(void) ResponseCmndChar(scolor); } +#endif // USE_LIGHT +#if defined(USE_LIGHT) || defined(USE_PWM_DIMMER) void CmndFade(void) { // Fade - Show current Fade state @@ -2606,7 +2608,9 @@ void CmndFade(void) #ifdef USE_DEVICE_GROUPS if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade); #endif // USE_DEVICE_GROUPS +#ifdef USE_LIGHT if (!Settings.light_fade) { Light.fade_running = false; } +#endif // USE_LIGHT ResponseCmndStateText(Settings.light_fade); } @@ -2632,6 +2636,8 @@ void CmndSpeed(void) } ResponseCmndNumber(Settings.light_speed); } +#endif // #if defined(USE_LIGHT) || defined(USE_PWM_DIMMER) +#ifdef USE_LIGHT void CmndWakeupDuration(void) { @@ -2664,7 +2670,10 @@ bool Xdrv04(uint8_t function) bool result = false; if (FUNC_MODULE_INIT == function) { - return LightModuleInit(); +#ifdef USE_PWM_DIMMER + if (PWM_DIMMER != my_module_type) +#endif // USE_PWM_DIMMER + return LightModuleInit(); } else if (light_type) { switch (function) { diff --git a/tasmota/xdrv_07_domoticz.ino b/tasmota/xdrv_07_domoticz.ino index 49e546b65..90563eeed 100644 --- a/tasmota/xdrv_07_domoticz.ino +++ b/tasmota/xdrv_07_domoticz.ino @@ -296,6 +296,7 @@ bool DomoticzMqttData(void) found = true; } else #endif // USE_SHUTTER +#ifdef USE_LIGHT if (iscolordimmer && 10 == nvalue) { // Color_SetColor // https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Set_a_light_to_a_certain_color_or_color_temperature JsonObject& color = domoticz["Color"]; @@ -333,8 +334,9 @@ bool DomoticzMqttData(void) snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); found = true; - } - else if (1 == nvalue || 0 == nvalue) { + } else +#endif // USE_LIGHT + if (1 == nvalue || 0 == nvalue) { if (((power >> i) &1) == (power_t)nvalue) { return true; // Stop loop } diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index 7396694af..fde47a623 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -200,8 +200,8 @@ void HAssAnnounceRelayLight(void) TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); -#ifdef USE_LIGHT - if (is_light) +#if defined(USE_LIGHT) || defined(USE_PWM_DIMMER) + if (is_light || PWM_DIMMER == my_module_type) { char *brightness_command_topic = stemp1; @@ -209,6 +209,7 @@ void HAssAnnounceRelayLight(void) strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); // SetOption20 - Control power in relation to Dimmer/Color/Ct changes TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic, stemp3); +#ifdef USE_LIGHT if (Light.subtype >= LST_RGB) { char *rgb_command_topic = stemp1; @@ -234,8 +235,9 @@ void HAssAnnounceRelayLight(void) GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); } +#endif // USE_LIGHT } -#endif // USE_LIGHT +#endif // defined(USE_LIGHT) || defined(USE_PWM_DIMMER) TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); diff --git a/tasmota/xdrv_23_zigbee_1_headers.ino b/tasmota/xdrv_23_zigbee_1_headers.ino index 101d5703d..0bc592266 100644 --- a/tasmota/xdrv_23_zigbee_1_headers.ino +++ b/tasmota/xdrv_23_zigbee_1_headers.ino @@ -21,7 +21,7 @@ // contains some definitions for functions used before their declarations -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp = true, uint8_t transacId = 1); +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId); // Get an JSON attribute, with case insensitive key search diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 4814bdb8a..71752f4e3 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -19,6 +19,10 @@ #ifdef USE_ZIGBEE +#ifndef ZIGBEERECEIVED +#define ZIGBEERECEIVED 1 +#endif + #include #include @@ -49,6 +53,8 @@ typedef struct Z_Device { // json buffer used for attribute reporting DynamicJsonBuffer *json_buffer; JsonObject *json; + // sequence number for Zigbee frames + uint8_t seqNumber; } Z_Device; // All devices are stored in a Vector @@ -96,6 +102,9 @@ public: // device just seen on the network, update the lastSeen field void updateLastSeen(uint16_t shortaddr); + // get next sequence number for (increment at each all) + uint8_t getNextSeqNumber(uint16_t shortaddr); + // Dump json String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; @@ -133,6 +142,7 @@ public: private: std::vector _devices = {}; uint32_t _saveTimer = 0; + uint8_t _seqNumber = 0; // global seqNumber if device is unknown template < typename T> static bool findInVector(const std::vector & vecOfElements, const T & element); @@ -226,7 +236,9 @@ Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { std::vector(), 0,0,0,0, nullptr, - nullptr, nullptr }; + nullptr, nullptr, + 0, // seqNumber + }; device.json_buffer = new DynamicJsonBuffer(); _devices.push_back(device); dirty(); @@ -532,6 +544,19 @@ void Z_Devices::updateLastSeen(uint16_t shortaddr) { _updateLastSeen(device); } +// get the next sequance number for the device, or use the global seq number if device is unknown +uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) { + int32_t short_found = findShortAddr(shortaddr); + if (short_found >= 0) { + Z_Device &device = getShortAddr(shortaddr); + device.seqNumber += 1; + return device.seqNumber; + } else { + _seqNumber += 1; + return _seqNumber; + } +} + // Per device timers // // Reset the timer for a specific device @@ -704,18 +729,22 @@ void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); +#if ZIGBEERECEIVED // DEPRECATED TODO Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); +#endif } else { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); +#if ZIGBEERECEIVED // DEPRECATED TODO Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); +#endif } // MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); // XdrvRulesProcess(); diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index d97e5e7d4..4debd73fd 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -486,18 +486,8 @@ void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { // Parse non-normalized attributes -// The key is "s_" followed by 16 bits clusterId, "_" followed by 8 bits command id void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - - char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X!%02X"), _cluster_id, _cmd_id); - - char hex_char[_payload.len()*2+2]; - ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - - json[attrid_str] = hex_char; + convertClusterSpecific(json, _cluster_id, _cmd_id, _frame_control.b.direction, _payload); } // return value: diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 073ab8e4c..5c3e3fc1b 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -19,34 +19,81 @@ #ifdef USE_ZIGBEE -//typedef int32_t (*Z_AttrConverter)(uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const char *new_name, void * param); typedef struct Z_CommandConverter { const char * tasmota_cmd; - const char * zcl_cmd; + uint16_t cluster; + uint8_t cmd; // normally 8 bits, 0xFF means it's a parameter + uint8_t direction; // direction of the command. 0x01 client->server, 0x02 server->client, 0x03 both + const char * param; } Z_CommandConverter; +typedef struct Z_XYZ_Var { // Holds values for vairables X, Y and Z + uint32_t x = 0; + uint32_t y = 0; + uint32_t z = 0; + uint8_t x_type = 0; // 0 = no value, 1 = 1 bytes, 2 = 2 bytes + uint8_t y_type = 0; + uint8_t z_type = 0; +} Z_XYZ_Var; + // list of post-processing directives const Z_CommandConverter Z_Commands[] = { - { "Power", "0006!xx" }, // 0=Off, 1=On, 2=Toggle - { "Dimmer", "0008!04/xx0A00" }, // Move to Level with On/Off, xx=0..254 (255 is invalid) - { "Dimmer+", "0008!06/001902" }, // Step up by 10%, 0.2 secs - { "Dimmer-", "0008!06/011902" }, // Step down by 10%, 0.2 secs - { "DimmerStop", "0008!03" }, // Stop any Dimmer animation - { "ResetAlarm", "0009!00/xxyyyy" }, // Reset alarm (alarm code + cluster identifier) - { "ResetAllAlarms","0009!01" }, // Reset all alarms - { "Hue", "0300!00/xx000A00" }, // Move to Hue, shortest time, 1s - { "Sat", "0300!03/xx0A00" }, // Move to Sat - { "HueSat", "0300!06/xxyy0A00" }, // Hue, Sat - { "Color", "0300!07/xxxxyyyy0A00" }, // x, y (uint16) - { "CT", "0300!0A/xxxx0A00" }, // Color Temperature Mireds (uint16) - { "Shutter", "0102!xx" }, - { "ShutterOpen", "0102!00" }, - { "ShutterClose", "0102!01" }, - { "ShutterStop", "0102!02" }, - { "ShutterLift", "0102!05xx" }, // Lift percentage, 0%=open, 100%=closed - { "ShutterTilt", "0102!08xx" }, // Tilt percentage + // Group adress commands + { "AddGroup", 0x0004, 0x00, 0x01, "xxxx00" }, // Add group id, group name is not supported + { "ViewGroup", 0x0004, 0x01, 0x01, "xxxx" }, // Ask for the group name + { "GetGroup", 0x0004, 0x02, 0x01, "01xxxx" }, // Get one group membership + { "GetAllGroups", 0x0004, 0x02, 0x01, "00" }, // Get all groups membership + { "RemoveGroup", 0x0004, 0x03, 0x01, "xxxx" }, // Remove one group + { "RemoveAllGroups",0x0004, 0x04, 0x01, "" }, // Remove all groups + // Light & Shutter commands + { "Power", 0x0006, 0xFF, 0x01, "" }, // 0=Off, 1=On, 2=Toggle + { "Dimmer", 0x0008, 0x04, 0x01, "xx0A00" }, // Move to Level with On/Off, xx=0..254 (255 is invalid) + { "Dimmer+", 0x0008, 0x06, 0x01, "001902" }, // Step up by 10%, 0.2 secs + { "Dimmer-", 0x0008, 0x06, 0x01, "011902" }, // Step down by 10%, 0.2 secs + { "DimmerStop", 0x0008, 0x03, 0x01, "" }, // Stop any Dimmer animation + { "ResetAlarm", 0x0009, 0x00, 0x01, "xxyyyy" }, // Reset alarm (alarm code + cluster identifier) + { "ResetAllAlarms", 0x0009, 0x01, 0x01, "" }, // Reset all alarms + { "Hue", 0x0300, 0x00, 0x01, "xx000A00" }, // Move to Hue, shortest time, 1s + { "Sat", 0x0300, 0x03, 0x01, "xx0A00" }, // Move to Sat + { "HueSat", 0x0300, 0x06, 0x01, "xxyy0A00" }, // Hue, Sat + { "Color", 0x0300, 0x07, 0x01, "xxxxyyyy0A00" }, // x, y (uint16) + { "CT", 0x0300, 0x0A, 0x01, "xxxx0A00" }, // Color Temperature Mireds (uint16) + { "ShutterOpen", 0x0102, 0x00, 0x01, "" }, + { "ShutterClose", 0x0102, 0x01, 0x01, "" }, + { "ShutterStop", 0x0102, 0x02, 0x01, "" }, + { "ShutterLift", 0x0102, 0x05, 0x01, "xx" }, // Lift percentage, 0%=open, 100%=closed + { "ShutterTilt", 0x0102, 0x08, 0x01, "xx" }, // Tilt percentage + { "Shutter", 0x0102, 0xFF, 0x01, "" }, + // Blitzwolf PIR + { "Occupancy", 0xEF00, 0x01, 0x01, "xx"}, // Specific decoder for Blitzwolf PIR, empty name means special treatment + // Decoders only - normally not used to send, and names may be masked by previous definitions + { "Dimmer", 0x0008, 0x00, 0x01, "xx" }, + { "DimmerMove", 0x0008, 0x01, 0x01, "xx0A" }, + { "DimmerStep", 0x0008, 0x02, 0x01, "xx190A00" }, + { "DimmerMove", 0x0008, 0x05, 0x01, "xx0A" }, + { "Dimmer+", 0x0008, 0x06, 0x01, "00" }, + { "Dimmer-", 0x0008, 0x06, 0x01, "01" }, + { "DimmerStop", 0x0008, 0x07, 0x01, "" }, + { "HueMove", 0x0300, 0x01, 0x01, "xx19" }, + { "HueStep", 0x0300, 0x02, 0x01, "xx190A00" }, + { "SatMove", 0x0300, 0x04, 0x01, "xx19" }, + { "SatStep", 0x0300, 0x05, 0x01, "xx190A" }, + { "ColorMove", 0x0300, 0x08, 0x01, "xxxxyyyy" }, + { "ColorStep", 0x0300, 0x09, 0x01, "xxxxyyyy0A00" }, + // Tradfri + { "ArrowClick", 0x0005, 0x07, 0x01, "xx" }, // xx == 0x01 = left, 0x00 = right + { "ArrowHold", 0x0005, 0x08, 0x01, "xx" }, // xx == 0x01 = left, 0x00 = right + { "ArrowRelease", 0x0005, 0x09, 0x01, "" }, + // IAS - Intruder Alarm System + leak/fire detection + { "ZoneStatusChange",0x0500, 0x00, 0x02, "xxxxyyzz" }, // xxxx = zone status, yy = extended status, zz = zone id, Delay is ignored + // responses for Group cluster commands + { "AddGroupResp", 0x0004, 0x00, 0x02, "xxyyyy" }, // xx = status, yy = group id + { "ViewGroupResp", 0x0004, 0x01, 0x02, "xxyyyy" }, // xx = status, yy = group id, name ignored + { "GetGroupResp", 0x0004, 0x02, 0x02, "xxyyzzzz" }, // xx = capacity, yy = count, zzzz = first group id, following groups ignored + { "RemoveGroup", 0x0004, 0x03, 0x02, "xxyyyy" }, // xx = status, yy = group id }; + #define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian // Below are the attributes we wand to read from each cluster @@ -55,6 +102,7 @@ const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; // CurrentLevel const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; // AlarmCount const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007) }; // Hue, Sat, X, Y, CT +// This callback is registered after a cluster specific command and sends a read command for the same cluster int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { size_t attrs_len = 0; const uint8_t* attrs = nullptr; @@ -78,11 +126,10 @@ int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoi break; } if (attrs) { - ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(shortaddr)); } } - // set a timer to read back the value in the future void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint) { uint32_t wait_ms = 0; @@ -105,22 +152,182 @@ void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoi } } -const __FlashStringHelper* zigbeeFindCommand(const char *command) { - char parm_uc[16]; // used to convert JSON keys to uppercase +// returns true if char is 'x', 'y' or 'z' +inline bool isXYZ(char c) { + return (c >= 'x') && (c <= 'z'); +} + +// returns the Hex value of a digit [0-9A-Fa-f] +// return: 0x00-0x0F +// or -1 if cannot be parsed +inline int8_t hexValue(char c) { + if ((c >= '0') && (c <= '9')) { + return c - '0'; + } + if ((c >= 'A') && (c <= 'F')) { + return 10 + c - 'A'; + } + if ((c >= 'a') && (c <= 'f')) { + return 10 + c - 'a'; + } + return -1; +} + +// Parse a Big Endian suite of max_len digits, or stops when a non-hex digit is found +uint32_t parseHex_P(const char **data, size_t max_len = 8) { + uint32_t ret = 0; + for (uint32_t i = 0; i < max_len; i++) { + int8_t v = hexValue(pgm_read_byte(*data)); + if (v < 0) { break; } // non hex digit, we stop parsing + ret = (ret << 4) | v; + *data += 1; + } + return ret; +} + +// Parse a model like "xxyy00" +// and fill x, y and z values +// Little Endian encoding +// On exit, xyz is updated, and x_type, y_type, z_type contain the number of bytes read for each +void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz) { + const char *p = model; // pointer to the model character + uint32_t v = 0; // index in the payload bytes buffer + char c = pgm_read_byte(p); // cur char + while (c) { + char c1 = pgm_read_byte(p+1); // next char + if (!c1) { break; } // unexpected end of model + if (isXYZ(c) && (c == c1) && (v < payload.len())) { // if char is [x-z] and followed by same char + uint8_t val = payload.get8(v); + switch (c) { + case 'x': + xyz->x = xyz->x | (val << (xyz->x_type * 8)); + xyz->x_type++; + break; + case 'y': + xyz->y = xyz->y | (val << (xyz->y_type * 8)); + xyz->y_type++; + break; + case 'z': + xyz->z = xyz->z | (val << (xyz->z_type * 8)); + xyz->z_type++; + break; + } + } + p += 2; + v++; + c = pgm_read_byte(p); + } +} + +// works on big endiand hex only +// Returns if found: +// - cluster number +// - command number or 0xFF if command is part of the variable part +// - the payload in the form of a HEX string with x/y/z variables + + + +// Parse a cluster specific command, and try to convert into human readable +void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, bool direction, const SBuffer &payload) { + size_t hex_char_len = payload.len()*2+2; + char *hex_char = (char*) malloc(hex_char_len); + if (!hex_char) { return; } + ToHex_P((unsigned char*)payload.getBuffer(), payload.len(), hex_char, hex_char_len); + + const __FlashStringHelper* command_name = nullptr; + Z_XYZ_Var xyz; + +//AddLog_P2(LOG_LEVEL_INFO, PSTR(">>> len = %d - %02X%02X%02X"), payload.len(), payload.get8(0), payload.get8(1), payload.get8(2)); + for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { + const Z_CommandConverter *conv = &Z_Commands[i]; + if (conv->cluster == cluster) { + // cluster match + if ((0xFF == conv->cmd) || (cmd == conv->cmd)) { + // cmd match + if ((direction && (conv->direction & 0x02)) || (!direction && (conv->direction & 0x01))) { + // check if we have a match for params too + // Match if: + // - payload exactly matches conv->param (conv->param may be longer) + // - payload matches conv->param until 'x', 'y' or 'z' + const char * p = conv->param; + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">>>++1 param = %s"), p); + bool match = true; + for (uint8_t i = 0; i < payload.len(); i++) { + const char c1 = pgm_read_byte(p); + const char c2 = pgm_read_byte(p+1); + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">>>++2 c1 = %c, c2 = %c"), c1, c2); + if ((0x00 == c1) || isXYZ(c1)) { + break; + } + const char * p2 = p; + uint32_t nextbyte = parseHex_P(&p2, 2); + //AddLog_P2(LOG_LEVEL_INFO, PSTR(">>>++3 parseHex_P = %02X"), nextbyte); + if (nextbyte != payload.get8(i)) { + match = false; + break; + } + p += 2; + } + if (match) { + command_name = (const __FlashStringHelper*) conv->tasmota_cmd; + parseXYZ(conv->param, payload, &xyz); + if (0xFF == conv->cmd) { + // shift all values + xyz.z = xyz.y; + xyz.z_type = xyz.y_type; + xyz.y = xyz.x; + xyz.y_type = xyz.x_type; + xyz.x = cmd; + xyz.x_type = 1; // 1 byte + } + break; + } + } + } + } + } + + // always report attribute in raw format + // Format: "0001!06": "00" = "!": "" for commands to devices + // Format: "0004<00": "00" = "<": "" for commands to devices + char attrid_str[12]; + snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); + json[attrid_str] = hex_char; + free(hex_char); + + if (command_name) { + if (0 == xyz.x_type) { + json[command_name] = true; // no parameter + } else if (0 == xyz.y_type) { + json[command_name] = xyz.x; // 1 parameter + } else { + // multiple answers, create an array + JsonArray &arr = json.createNestedArray(command_name); + arr.add(xyz.x); + arr.add(xyz.y); + if (xyz.z_type) { + arr.add(xyz.z); + } + } + } +} + +// Find the command details by command name +// If not found: +// - returns nullptr +const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd) { for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { const Z_CommandConverter *conv = &Z_Commands[i]; if (0 == strcasecmp_P(command, conv->tasmota_cmd)) { - return (const __FlashStringHelper*) conv->zcl_cmd; + *cluster = conv->cluster; + *cmd = conv->cmd; + return (const __FlashStringHelper*) conv->param; } } return nullptr; } -inline bool isXYZ(char c) { - return (c >= 'x') && (c <= 'z'); -} - // take the lower 4 bits and turn it to an hex char inline char hexDigit(uint32_t h) { uint32_t nybble = h & 0x0F; diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index 5a3d78e85..d0616a40b 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -33,6 +33,7 @@ const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; // Node descriptor const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; // Endpoints descriptor const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; // Simple Descriptor (clusters) const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; // Device announces its address +const uint8_t ZIGBEE_STATUS_DEVICE_IEEE = 35; // Request of device address const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 668f85471..b67add374 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -176,15 +176,24 @@ int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { return -1; } +// Send ZDO_IEEE_ADDR_REQ request to get IEEE long address +void Z_SendIEEEAddrReq(uint16_t shortaddr) { + uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; + + ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq)); +} + // Send ACTIVE_EP_REQ to collect active endpoints for this address void Z_SendActiveEpReq(uint16_t shortaddr) { uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); + + // uint8_t NodeDescReq[] = { Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, + // Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + //ZigbeeZNPSend(NodeDescReq, sizeof(NodeDescReq)); Not sure this is useful } @@ -335,6 +344,40 @@ int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { return -1; } +int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { + uint8_t status = buf.get8(2); + Z_IEEEAddress ieeeAddr = buf.get64(3); + Z_ShortAddress nwkAddr = buf.get16(11); + // uint8_t startIndex = buf.get8(13); + // uint8_t numAssocDev = buf.get8(14); + + if (0 == status) { // SUCCESS + zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + "}}"), + ZIGBEE_STATUS_DEVICE_IEEE, hex, nwkAddr + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + // Ping response + const String * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + if (friendlyName) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), nwkAddr, friendlyName->c_str()); + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"}}"), nwkAddr); + } + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + } + return -1; +} + int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { Z_ShortAddress srcAddr = buf.get16(2); Z_ShortAddress nwkAddr = buf.get16(4); @@ -451,6 +494,8 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); zcl_received.postProcessAttributes(srcaddr, json); + // Add Endpoint + json[F(D_CMND_ZIGBEE_ENDPOINT)] = srcendpoint; // Add linkquality json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; @@ -482,6 +527,7 @@ ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) // 45CA ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) // 45CB ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4585 ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 +ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581 const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, @@ -491,6 +537,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc }, { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, { AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc }, + { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, }; int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 6ea08c4ac..08055ba9e 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -33,19 +33,22 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" + D_CMND_ZIGBEE_PING ; const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" // legacy prefix -- deprecated D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND ; + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" + D_CMND_ZIGBEE_PING ; void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbZNPSend, &CmndZbPermitJoin, &CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, - &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind + &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, + &CmndZbPing, }; int32_t ZigbeeProcessInput(class SBuffer &buf) { @@ -344,7 +347,7 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) { ToHex_P(msg, len, hex_char, sizeof(hex_char))); } -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool disableDefResp, uint8_t transacId) { +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { SBuffer buf(25+len); buf.add8(Z_SREQ | Z_AF); // 24 buf.add8(AF_DATA_REQUEST); // 01 @@ -357,7 +360,7 @@ void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8 buf.add8(0x1E); // 1E radius buf.add8(3 + len); - buf.add8((disableDefResp ? 0x10 : 0x00) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field + buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00)); // Frame Control Field buf.add8(transacId); // Transaction Sequance Number buf.add8(cmdId); if (len > 0) { @@ -367,61 +370,16 @@ void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8 ZigbeeZNPSend(buf.getBuffer(), buf.len()); } -inline int8_t hexValue(char c) { - if ((c >= '0') && (c <= '9')) { - return c - '0'; - } - if ((c >= 'A') && (c <= 'F')) { - return 10 + c - 'A'; - } - if ((c >= 'a') && (c <= 'f')) { - return 10 + c - 'a'; - } - return -1; -} - -uint32_t parseHex(const char **data, size_t max_len = 8) { - uint32_t ret = 0; - for (uint32_t i = 0; i < max_len; i++) { - int8_t v = hexValue(**data); - if (v < 0) { break; } // non hex digit, we stop parsing - ret = (ret << 4) | v; - *data += 1; - } - return ret; -} - -void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { - - uint16_t cluster = 0x0000; // 0x0000 is a valid default value - uint8_t cmd = ZCL_READ_ATTRIBUTES; // default command is READ_ATTRIBUTES - bool clusterSpecific = false; - // Parse 'cmd' in the form "AAAA_BB/CCCCCCCC" or "AAAA!BB/CCCCCCCC" - // where AA is the cluster number, BBBB the command number, CCCC... the payload - // First delimiter is '_' for a global command, or '!' for a cluster specific commanc - cluster = parseHex(&data, 4); - - // delimiter - if (('_' == *data) || ('!' == *data)) { - if ('!' == *data) { clusterSpecific = true; } - data++; - } else { - ResponseCmndChar("Wrong delimiter for payload"); - return; - } - // parse cmd number - cmd = parseHex(&data, 2); - - // move to end of payload - // delimiter is optional - if ('/' == *data) { data++; } // skip delimiter - - size_t size = strlen(data); +void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, bool clusterSpecific, + uint16_t cluster, uint8_t cmd, const char *param) { + size_t size = param ? strlen(param) : 0; SBuffer buf((size+2)/2); // actual bytes buffer for data - while (*data) { - uint8_t code = parseHex(&data, 2); - buf.add8(code); + if (param) { + while (*param) { + uint8_t code = parseHex_P(¶m, 2); + buf.add8(code); + } } if (0 == endpoint) { @@ -430,7 +388,7 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: dstAddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), - dstAddr, cluster, endpoint, cmd, data); + dstAddr, cluster, endpoint, cmd, param); if (0 == endpoint) { AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); @@ -438,7 +396,7 @@ void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, const char *data) { } // everything is good, we can send the command - ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len()); + ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len(), false, zigbee_devices.getNextSeqNumber(dstAddr)); // now set the timer, if any, to read back the state later if (clusterSpecific) { zigbeeSetCommandTimer(dstAddr, cluster, endpoint); @@ -467,8 +425,12 @@ void CmndZbSend(void) { static char delim[] = ", "; // delimiters for parameters uint16_t device = 0xFFFF; // 0xFFFF is broadcast, so considered valid uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint + // Command elements + uint16_t cluster = 0; + uint8_t cmd = 0; String cmd_str = ""; // the actual low-level command, either specified or computed + // parse JSON const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); if (nullptr != &val_device) { device = zigbee_devices.parseDeviceParam(val_device.as()); @@ -496,8 +458,9 @@ void CmndZbSend(void) { String key = it->key; JsonVariant& value = it->value; uint32_t x = 0, y = 0, z = 0; + uint16_t cmd_var; - const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.c_str()); + const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.c_str(), &cluster, &cmd_var); if (tasmota_cmd) { cmd_str = tasmota_cmd; } else { @@ -533,9 +496,16 @@ void CmndZbSend(void) { } } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_template = %s"), cmd_str.c_str()); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_template = %s"), cmd_str.c_str()); + if (0xFF == cmd_var) { // if command number is a variable, replace it with x + cmd = x; + x = y; // and shift other variables + y = z; + } else { + cmd = cmd_var; // or simply copy the cmd number + } cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); // fill in parameters - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_final = %s"), cmd_str.c_str()); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: command_final = %s"), cmd_str.c_str()); } else { // we have zero command, pass through until last error for missing command } @@ -546,9 +516,9 @@ void CmndZbSend(void) { // we have an unsupported command type, just ignore it and fallback to missing command } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%s\"}"), - device, endpoint, cmd_str.c_str()); - zigbeeZCLSendStr(device, endpoint, cmd_str.c_str()); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%04X!%02X/%s\"}"), + device, endpoint, cluster, cmd, cmd_str.c_str()); + zigbeeZCLSendStr(device, endpoint, true, cluster, cmd, cmd_str.c_str()); } else { Response_P(PSTR("Missing zigbee 'Send'")); return; @@ -614,16 +584,28 @@ void CmndZbBind(void) { // Probe a specific device to get its endpoints and supported clusters void CmndZbProbe(void) { + CmndZbProbeOrPing(true); +} + +void CmndZbProbeOrPing(boolean probe) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } // everything is good, we can send the command - Z_SendActiveEpReq(shortaddr); + Z_SendIEEEAddrReq(shortaddr); + if (probe) { + Z_SendActiveEpReq(shortaddr); + } ResponseCmndDone(); } +// Ping a device, actually a simplified version of ZbProbe +void CmndZbPing(void) { + CmndZbProbeOrPing(false); +} + // Specify, read or erase a Friendly Name void CmndZbName(void) { // Syntax is: @@ -728,8 +710,13 @@ void CmndZbRead(void) { } } + if (0 == endpoint) { // try to compute the endpoint + endpoint = zigbee_devices.findClusterEndpointIn(device, cluster); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); + } + if ((0 != endpoint) && (attrs_len > 0)) { - ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, false /* we do want a response */); + ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true /* we do want a response */, zigbee_devices.getNextSeqNumber(device)); ResponseCmndDone(); } else { ResponseCmndChar("Missing parameters"); diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index c353a1dd4..6f4d711d7 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -48,7 +48,7 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime}; - const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; + const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}"; const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; #include @@ -70,7 +70,7 @@ struct SHUTTER { int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE int16_t motordelay[MAX_SHUTTERS]; // initial motorstarttime in 0.05sec. - int16_t pwm_frequency; // frequency of PWN for stepper motors + int16_t pwm_frequency[MAX_SHUTTERS]; // frequency of PWN for stepper motors uint16_t max_pwm_frequency = 1000; // maximum of PWM frequency for openig the shutter. depend on the motor and drivers uint16_t max_close_pwm_frequency[MAX_SHUTTERS];// maximum of PWM frequency for closeing the shutter. depend on the motor and drivers uint8_t skip_relay_change; // avoid overrun at endstops @@ -82,17 +82,18 @@ void ShutterLogPos(uint32_t i) char stemp2[10]; dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d"), - i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_frequency); + i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_frequency[i]); } void ShutterRtc50mS(void) { - for (uint32_t i = 0; i < shutters_present; i++) { + for (uint8_t i = 0; i < shutters_present; i++) { Shutter.time[i]++; if (Shutter.accelerator[i]) { - Shutter.pwm_frequency += Shutter.accelerator[i]; - Shutter.pwm_frequency = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency)); - analogWriteFreq(Shutter.pwm_frequency); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: accelerator i=%d -> %d"),i, Shutter.accelerator[i]); + Shutter.pwm_frequency[i] += Shutter.accelerator[i]; + Shutter.pwm_frequency[i] = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency[i])); + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); } } @@ -102,8 +103,6 @@ void ShutterRtc50mS(void) int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) { - if (0 == percent) return 0; - if (100 == percent) return Shutter.open_max[index]; if (Settings.shutter_set50percent[index] != 50) { return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; } else { @@ -138,8 +137,6 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) { - if (0 >= realpos) return 0; - if (Shutter.open_max[index] <= realpos) return 100; if (Settings.shutter_set50percent[index] != 50) { return (Settings.shuttercoeff[2][index] * 5 > realpos) ? SHT_DIV_ROUND(realpos, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos-Settings.shuttercoeff[0][index], Settings.shuttercoeff[1][index]); } else { @@ -203,8 +200,9 @@ void ShutterInit(void) Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; if ((pin[GPIO_PWM1+i] < 99) && (pin[GPIO_CNTR1+i] < 99)) { Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER; - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); + Shutter.pwm_frequency[i] = 0; + Shutter.accelerator[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); } } @@ -256,29 +254,24 @@ void ShutterInit(void) void ShutterReportPosition(bool always) { - uint32_t shutter_moving = 0; Response_P(PSTR("{")); for (uint32_t i = 0; i < shutters_present; i++) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d"), i+1,Shutter.real_position[i]); uint32_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); if (Shutter.direction[i] != 0) { - shutter_moving = 1; + rules_flag.shutter_moving = 1; ShutterLogPos(i); } if (i) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i]); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i], ShutterRealToPercentPosition(Shutter.target_position[i], i)); } ResponseJsonEnd(); - if (always || (1 == shutter_moving)) { + if (always || (rules_flag.shutter_moving)) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); + XdrvRulesProcess(); } - if (rules_flag.shutter_moving > shutter_moving) { - rules_flag.shutter_moved = 1; - } else { - rules_flag.shutter_moved = 0; - } - rules_flag.shutter_moving = shutter_moving; - //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); + } void ShutterLimitRealAndTargetPositions(uint32_t i) { @@ -304,22 +297,22 @@ void ShutterUpdatePosition(void) int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); - int32_t min_runtime_ms = Shutter.pwm_frequency*1000 / max_freq_change_per_sec; + int32_t min_runtime_ms = Shutter.pwm_frequency[i]*1000 / max_freq_change_per_sec; int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; - int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency / max_frequency * Shutter.direction[i] ; + int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency[i] / max_frequency * Shutter.direction[i] ; int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; - stop_position_delta =200 * Shutter.pwm_frequency/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); + stop_position_delta =200 * Shutter.pwm_frequency[i]/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); //Shutter.accelerator[i] = tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); //int32_t act_freq_change = max_freq_change_per_sec/20; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, - Shutter.pwm_frequency,max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); + Shutter.pwm_frequency[i],max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]); - } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency == max_frequency) { + } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency[i] == max_frequency) { Shutter.accelerator[i] = 0; } } else { @@ -343,13 +336,13 @@ void ShutterUpdatePosition(void) case SHT_OFF_ON__OPEN_CLOSE_STEPPER: missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; //prepare for stop PWM - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency[i]); Shutter.accelerator[i] = 0; - Shutter.pwm_frequency = Shutter.pwm_frequency > 250 ? 250 : Shutter.pwm_frequency; - analogWriteFreq(Shutter.pwm_frequency); + Shutter.pwm_frequency[i] = Shutter.pwm_frequency[i] > 250 ? 250 : Shutter.pwm_frequency[i]; + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); + Shutter.pwm_frequency[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { delay(1); } @@ -391,6 +384,7 @@ void ShutterUpdatePosition(void) Shutter.direction[i] = 0; ShutterReportPosition(true); + rules_flag.shutter_moved = 1; XdrvRulesProcess(); } } @@ -413,8 +407,8 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter.skip_relay_change = 1; } else { if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { - Shutter.pwm_frequency = 0; - analogWriteFreq(Shutter.pwm_frequency); + Shutter.pwm_frequency[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 0); // can be operated without counter, but then not that acurate. if (pin[GPIO_CNTR1+i] < 99) { @@ -439,10 +433,11 @@ void ShutterWaitForMotorStop(uint32_t i) if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { if (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Frequency change %d"), Shutter.pwm_frequency); - while (Shutter.pwm_frequency > 0) { - Shutter.accelerator[i] = 0; - Shutter.pwm_frequency = tmax(Shutter.pwm_frequency-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); - analogWriteFreq(Shutter.pwm_frequency); + while (Shutter.pwm_frequency[i] > 0) { + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Frequency: %ld, delta: %d"), Shutter.pwm_frequency[i], (int32_t)((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) ); + Shutter.pwm_frequency[i] = tmax(Shutter.pwm_frequency[i]-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); + //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Frequency: %ld"), Shutter.pwm_frequency[i]); + analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 50); delay(50); } @@ -532,7 +527,6 @@ void ShutterButtonHandler(void) uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action buttonState = SHT_PRESSED_MULTI; @@ -542,9 +536,9 @@ void ShutterButtonHandler(void) buttonState = SHT_PRESSED_IMMEDIATE; press_index = 1; Button.press_counter[button_index] = 99; // Remember to discard further action for press & hold within button timings - } else + } else { Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window + } } blinks = 201; } @@ -596,14 +590,18 @@ void ShutterButtonHandler(void) // check for simultaneous shutter button press uint32 min_shutterbutton_press_counter = -1; for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter); + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { min_shutterbutton_press_counter = Button.press_counter[i]; + } + } if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { // simultaneous shutter button press detected + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:simultanous presss deteced")); press_index = Button.press_counter[button_index]; for (uint32_t i = 0; i < MAX_KEYS; i++) - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; } @@ -628,7 +626,6 @@ void ShutterButtonHandler(void) return; } } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { - // simultaneous shutter button extend hold detected if (!Settings.flag.button_restrict) { // no SetOption1 (0) char scmnd[20]; snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); @@ -649,8 +646,7 @@ void ShutterButtonHandler(void) if (buttonState == SHT_PRESSED_IMMEDIATE) { XdrvMailbox.payload = XdrvMailbox.index; CmndShutterStop(); - } - else { + } else { uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; if (position) { if (Shutter.direction[shutter_index]) { @@ -670,12 +666,12 @@ void ShutterButtonHandler(void) Response_P("%d", position); MqttPublish(stopic, false); } - } - } - } - } - } - } + } // for (uint32_t) + } // if (Settings.shutter) + } // ende else + } // if (position) + } // end else + } // if if (Settings.shutter_startrelay[shutter_index] } Response_P(PSTR("{")); ResponseAppend_P(JSON_SHUTTER_BUTTON, shutter_index+1, (buttonState <= SHT_PRESSED_IMMEDIATE) ? (button_index+1) : 0, press_index); @@ -756,6 +752,7 @@ void CmndShutterPosition(void) AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); // value 0 with data_len > 0 can mean Open + // special handling fo UP,DOWN,TOGGLE,STOP command comming with payload -99 if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { //UpperCase(XdrvMailbox.data, XdrvMailbox.data); if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { @@ -773,13 +770,13 @@ void CmndShutterPosition(void) } } - int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? 0 : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); + int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? (XdrvMailbox.payload == -99 ? ShutterRealToPercentPosition(Shutter.real_position[index], index) : 0) : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); // webgui still send also on inverted shutter the native position. target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; if (XdrvMailbox.payload != -99) { //target_pos_percent = (Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent; Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); - Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); + //Shutter.accelerator[index] = Shutter.max_pwm_frequency / ((Shutter.motordelay[index] > 0) ? Shutter.motordelay[index] : 1); //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); } diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino new file mode 100644 index 000000000..ea3211563 --- /dev/null +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -0,0 +1,1141 @@ +/* + xdrv_35_pwm_dimmer.ino - PWM Dimmer Switch support for Tasmota + + Copyright (C) 2020 Paul C Diem + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_PWM_DIMMER + +/*********************************************************************************************\ +* Support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches. The brightness of +* the load for these dimmers is controlled by a PWM GPIO pin. Examples are: +* +* https://www.amazon.com/dp/B07FXYSVR1 +* https://www.amazon.com/dp/B07V26Q3VD +* https://www.amazon.com/dp/B07K67D43J +* https://www.amazon.com/dp/B07TTGFWFM +* +\*********************************************************************************************/ + +#define XDRV_35 35 + +#ifndef MAX_FIXED_COLOR +#define MAX_FIXED_COLOR 12 +#endif // MAX_FIXED_COLOR + +const char kPWMDimmerCommands[] PROGMEM = "|" // No prefix + D_CMND_BRI_MIN "|" D_CMND_BRI_PRESET "|" D_CMND_DIMMER "|" D_CMND_FADE "|" D_CMND_LED_TIMEOUT "|" + D_CMND_POWERED_OFF_LED "|" D_CMND_SPEED; + +void (* const PWMDimmerCommand[])(void) PROGMEM = { + &CmndBriMin, &CmndBriPreset, &PWMDmmerCmndDimmer, &CmndFade, &CmndLedTimeout, + &CmndPoweredOffLed, &CmndSpeed }; + +#ifdef USE_PWM_DIMMER_REMOTE +struct remote_pwm_dimmer { + power_t power; + uint8_t light_speed; + uint8_t x_bri_power_on; + uint8_t x_bri_min; + uint8_t x_bri_preset_low; + uint8_t x_bri_preset_high; + uint8_t fixed_color_index; + uint8_t bri; + bool power_button_increases_bri; + bool light_fade; +}; +#endif // USE_PWM_DIMMER_REMOTE + +uint32_t led_timeout_time = 0; +uint32_t turn_off_brightness_leds_time = 0; +uint32_t button_hold_time[3]; +uint8_t current_bri; +uint8_t target_bri; +uint8_t restore_powered_off_led = 0; +uint8_t power_button_index = 0; +uint8_t down_button_index = 1; +uint8_t up_button_index = 2; +uint8_t fixed_color_index; +uint8_t button_press_count[3] = { 0, 0, 0 }; +bool relay_is_on = false; +bool ignore_power_button_hold; +bool ignore_power_button_release; +bool button_was_held = false; +bool power_button_increases_bri = true; +bool invert_power_button_bri_direction = false; +bool button_hold_sent[3]; +bool button_pressed[3] = { false, false, false }; +#ifdef USE_PWM_DIMMER_REMOTE +struct remote_pwm_dimmer * remote_pwm_dimmers; +struct device_group * active_device_group; +struct remote_pwm_dimmer * active_remote_pwm_dimmer; +uint8_t buttons_pressed = 0; +bool active_device_is_local; +#endif // USE_PWM_DIMMER_REMOTE + +void PWMDimmerCheckBri(uint8_t * value_ptr) +{ + if (*value_ptr < Settings.bri_min) *value_ptr = Settings.bri_min; +} + +void PWMModuleInit() +{ + Settings.seriallog_level = 0; + Settings.flag.mqtt_serial = 0; // Disable serial logging + Settings.ledstate = 0; // Disable LED usage + Settings.flag.pwm_control = 0; // Use basic PWM control instead of Light + + if (Settings.last_module != Settings.module) { + Settings.bri_min = 8; + Settings.bri_power_on = 50; + Settings.bri_preset_low = 8; + Settings.bri_preset_high = 255; + Settings.last_module = Settings.module; + } + else { + if (Settings.bri_min < 1) Settings.bri_min = 8; + PWMDimmerCheckBri(&Settings.bri_power_on); + PWMDimmerCheckBri(&Settings.bri_preset_low); + PWMDimmerCheckBri(&Settings.bri_preset_high); + } + + if (Settings.light_speed < 1) Settings.light_speed = 1; + + target_bri = ((Settings.power & 1) ? changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255) : 0); + PWMDimmerCheckBri(&target_bri); + current_bri = target_bri; + + if (pin[GPIO_PWM1] < 99) { + uint32_t pwm_value = changeUIntScale(current_bri, 0, 255, 0, Settings.pwm_range); + analogWrite(pin[GPIO_PWM1], bitRead(pwm_inverted, 0) ? Settings.pwm_range - pwm_value : pwm_value); + } + + relay_is_on = (current_bri > 0); + if (pin[GPIO_REL1] < 99) DigitalWrite(GPIO_REL1, bitRead(rel_inverted, 0) ? !relay_is_on : relay_is_on); + + PWMDimmerSetPoweredOffLed(); + PWMDimmerSetBrightnessLeds(0); +} + +void PWMDimmerInit(void) +{ +#ifdef USE_PWM_DIMMER_REMOTE + if (Settings.flag3.remote_device_mode) { + if (device_group_count > 1) { + if ((remote_pwm_dimmers = (struct remote_pwm_dimmer *) calloc(device_group_count - 1, sizeof(struct remote_pwm_dimmer))) == nullptr) { + AddLog_P2(LOG_LEVEL_ERROR, "PWMDimmer: error allocating PWM dimmer array"); + Settings.flag3.remote_device_mode = false; + } + } + } + + active_device_group = &device_groups[0]; + active_device_is_local = true; +#endif // USE_PWM_DIMMER_REMOTE +} + +// operation: 0 = normal, -1 = all off, 1 = all on +void PWMDimmerSetBrightnessLeds(int32_t operation) +{ + if (leds_present) { + uint32_t step = (!operation ? (255 - Settings.bri_min) / (leds_present + 1) : operation < 0 ? 255 : 0); + uint32_t level = step; + SetLedPowerIdx(0, current_bri >= level); + if (leds_present > 1) { + level += step; + SetLedPowerIdx(1, current_bri >= level); + if (leds_present > 2) { + level += step; + SetLedPowerIdx(2, current_bri >= level); + if (leds_present > 3) { + level += step; + SetLedPowerIdx(3, current_bri >= level); + } + } + } + + // If enabled, set the LED timeout. + if (!operation) led_timeout_time = (current_bri && Settings.flag.led_timeout ? millis() + 5000 : 0); + } +} + +void PWMDimmerSetPoweredOffLed(void) +{ + // Set the powered-off LED state. + if (pin[GPIO_LEDLNK] < 99) { + bool power_off_led_on = !power && Settings.flag3.powered_off_led; + if (ledlnk_inverted) power_off_led_on ^= 1; + digitalWrite(pin[GPIO_LEDLNK], power_off_led_on); + } +} + +void PWMDimmerAnimate(bool no_fade) +{ + // We're only here if something changed. If this is no longer the case, uncomment the following + // line. + //if (current_bri == target_bri) return; + + // Advance the current brightness towards the target. + if (!no_fade && Settings.light_fade) { + if (current_bri < Settings.bri_min) { + current_bri = Settings.bri_min; + } + else { + uint8_t offset = current_bri / Settings.light_speed / 5 + 1; + uint8_t max_offset = abs(target_bri - current_bri); + if (offset > max_offset) offset = max_offset; + if (current_bri < target_bri) + current_bri += offset; + else + current_bri -= offset; + } + } + else { + current_bri = target_bri; + } + + // If the current brightness is now < bri_min, set the current and target brightness to 0. + if (current_bri < Settings.bri_min) current_bri = target_bri = 0; + + // Sset the new PWM value. + if (pin[GPIO_PWM1] < 99) { + uint32_t pwm_value = changeUIntScale(current_bri, 0, 255, 0, Settings.pwm_range); + analogWrite(pin[GPIO_PWM1], bitRead(pwm_inverted, 0) ? Settings.pwm_range - pwm_value : pwm_value); + } + + // Handle a power state change. + if (relay_is_on != (current_bri > 0)) { + bool power_is_on = ((power & 1) != 0); + if (power_is_on == relay_is_on) { +AddLog_P2(LOG_LEVEL_DEBUG, "****************** ExecuteCommandPower(1, %d, SRC_SWITCH)", (relay_is_on ? 0 : 1)); + ExecuteCommandPower(1, (relay_is_on ? POWER_OFF : POWER_ON), SRC_SWITCH); + } + + relay_is_on = !relay_is_on; + if (pin[GPIO_REL1] < 99) DigitalWrite(GPIO_REL1, bitRead(rel_inverted, 0) ? !relay_is_on : relay_is_on); + + // Set the powered-off LED. + PWMDimmerSetPoweredOffLed(); + } + + // Set the brightness LED's. + PWMDimmerSetBrightnessLeds(0); +} + +void PWMDimmerSetBri(uint8_t bri) +{ + if (bri == target_bri) return; + target_bri = bri; + if (target_bri && target_bri < Settings.bri_min) target_bri = Settings.bri_min; + Settings.bri_power_on = target_bri; + Settings.light_dimmer = changeUIntScale(target_bri, 0, 255, 0, 100); + if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT + MqttPublishTeleState(); + } + PWMDimmerAnimate(false); +} + +#ifdef USE_DEVICE_GROUPS +void PWMDimmerHandleDeviceGroupRequest() +{ + static bool send_state = false; + uint8_t value = XdrvMailbox.payload; + switch (XdrvMailbox.command_code) { + case DGR_ITEM_BRI_MIN: + Settings.bri_min = 1; + case DGR_ITEM_BRI_PRESET_LOW: + case DGR_ITEM_BRI_PRESET_HIGH: + case DGR_ITEM_BRI_POWER_ON: + PWMDimmerCheckBri(&value); + break; + case DGR_ITEM_LIGHT_BRI: + if (value) PWMDimmerCheckBri(&value); + break; + } + + switch (XdrvMailbox.command_code) { + case DGR_ITEM_EOL: + if (send_state && !(XdrvMailbox.index & DGR_FLAG_MORE_TO_COME)) { + if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT + MqttPublishTeleState(); + } + send_state = false; + } + break; + case DGR_ITEM_LIGHT_BRI: + if (target_bri != value) { + PWMDimmerSetBri(value); + send_state = true; + } + break; + case DGR_ITEM_LIGHT_SPEED: + if (Settings.light_speed != value && value > 0 && value <= 40) { + Settings.light_speed = value; + send_state = true; + } + break; + case DGR_ITEM_BRI_MIN: + if (Settings.bri_min != value) { + Settings.bri_min = value; + send_state = true; + } + break; + case DGR_ITEM_BRI_PRESET_LOW: + if (Settings.bri_preset_low != value) { + Settings.bri_preset_low = value; + send_state = true; + } + break; + case DGR_ITEM_BRI_PRESET_HIGH: + if (Settings.bri_preset_high != value) { + Settings.bri_preset_high = value; + send_state = true; + } + break; + case DGR_ITEM_BRI_POWER_ON: + if (Settings.bri_power_on != value) { + Settings.bri_power_on = value; + send_state = true; + } + break; + case DGR_ITEM_STATUS: + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, + DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_BRI, target_bri, + DGR_ITEM_BRI_MIN, Settings.bri_min, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, + DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); + break; + } +} +#endif // USE_DEVICE_GROUPS + +void PWMDimmerHandleButton() +{ + /* + * Power Button Up/Down Buttons State Remote Mode Action + * -------------------- ---------------------- ----- ------------ ---------------------------- + * Press & release Released Any Any Toggle power + * Hold for hold time Released On Any Brighter/dimmer while held + * then reverse direction + * Hold for hold time Released Off Any Power on at bri preset low + * Hold while Press & release up Any Any Toggle/change options + * Hold while Press & release down Any Any Toggle/change options + * Hold while Press up On Yes Brighter + * Hold while Press down On Yes Dimmer + * Released Press up On No Brigther + * Released Press down On No Dimmer + * Released Press & release up Off No Power on at bri preset low + * Released Press & release down Off No Power on at bri preset high + * + * Holding any button for over 10 seconds executes the WiFiConfig 2 command. + * + * In remote mode, whichever button is pressed first becomes the power button and any buttons + * pressed while it is held affect the device associated with it. The up and down buttons change + * depeneding on which button is the current power button: + * + * Power Down Up + * ----- ---- -- + * 1 2 3 + * 2 1 3 + * 3 1 2 + */ + uint32_t button_index = XdrvMailbox.index; + uint32_t now = millis(); + bool toggle_power = false; + uint8_t dgr_item = 0; + uint8_t dgr_value; + + // If the button is pressed, ... + if (!XdrvMailbox.payload) { + int8_t bri_direction = 0; + + // If the button was just pressed, reset the press count if it was released for longer than 1 + // second, flag the button as pressed, clear the hold sent flag and increment the buttons + // pressed count. + if (!button_pressed[button_index]) { + if (now > button_hold_time[button_index] && now - button_hold_time[button_index] > 1000) button_press_count[button_index] = 0; + button_pressed[button_index] = true; + button_hold_sent[button_index] = false; +#ifdef USE_PWM_DIMMER_REMOTE + buttons_pressed++; + + // If there are no other buttons pressed right now and remote mode is enabled, make the device + // associated with this button the device we're going to control. + if (buttons_pressed == 1 && Settings.flag3.remote_device_mode) { + power_button_index = button_index; + up_button_index = (button_index == 2 ? 1 : 2); + down_button_index = (button_index ? 0 : 1); + active_device_group = &device_groups[power_button_index]; + active_device_is_local = active_device_group->local; + if (!active_device_is_local) active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index - 1]; + } + if (button_index == power_button_index) { +#else // USE_PWM_DIMMER_REMOTE + // If this is about the power button, initialize some variables. + if (!button_index) { +#endif // USE_PWM_DIMMER_REMOTE + button_hold_time[button_index] = now + 500; + ignore_power_button_hold = false; + ignore_power_button_release = false; + return; + } + + // If this is not about the power button, load the new hold time. Note that the hold time for + // the power button is longer than the hold time for the other buttons. + button_hold_time[button_index] = now + 250; + } + + // If the button is being held, send a button hold. + else if (button_hold_time[button_index] < now) { + if (!button_hold_sent[button_index]) { + button_hold_sent[button_index] = true; + SendKey(KEY_BUTTON, button_index + 1, POWER_HOLD); + } + + // If the button has been held for over 10 seconds, execute the WiFiConfig 2 command. + if (now - button_hold_time[button_index] > 10000) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2")); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } + + // If this is about the power button, ... +#ifdef USE_PWM_DIMMER_REMOTE + if (button_index == power_button_index) { +#else // USE_PWM_DIMMER_REMOTE + if (!button_index) { +#endif // USE_PWM_DIMMER_REMOTE + + // If the power button has been held with no other buttons pressed, ... + if (!ignore_power_button_hold && button_hold_time[button_index] < now) { + ignore_power_button_release = true; + + // If the device power is on, adjust the brightness. Set the direction based on the current + // direction for the device and then invert the direction when the power button is released. + // The new brightness will be calculated below. +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local ? active_remote_pwm_dimmer->power : power) { + bri_direction = (!active_device_is_local ? (active_remote_pwm_dimmer->power_button_increases_bri ? 1 : -1) : (power_button_increases_bri ? 1 : -1)); +#else // USE_PWM_DIMMER_REMOTE + if (power) { + bri_direction = (power_button_increases_bri ? 1 : -1); +#endif // USE_PWM_DIMMER_REMOTE + invert_power_button_bri_direction = true; + } + + // If the power is not on, turn it on using an initial brightness of bri_preset_low and set + // the power button hold dimmer direction to true so holding the power switch increases the + // brightness. + else { +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) { + active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->x_bri_preset_low; + active_remote_pwm_dimmer->power_button_increases_bri = true; + } + else { +#endif // USE_PWM_DIMMER_REMOTE + target_bri = Settings.bri_preset_low; + power_button_increases_bri = true; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + toggle_power = true; + + // Reset the power button hold time to delay before we start increasing the brightness. + button_hold_time[button_index] = now + 500; + } + } + } + + // If this is about the down or up buttons, ... + else { + + // If the power button is also pressed, set flags to ignore the power button being held and + // the next power button release. + if (button_pressed[power_button_index]) { + ignore_power_button_release = ignore_power_button_hold = true; + } + + // If the active device is local or the power button if also pressed, then if the down/up + // button has been held, handle the action based on the number of times the down or up button + // was pressed and released before holding it. +#ifdef USE_PWM_DIMMER_REMOTE + if (active_device_is_local == !button_pressed[power_button_index]) { +#endif // USE_PWM_DIMMER_REMOTE + if (button_hold_time[button_index] < now) { + + uint8_t uint8_value; + uint8_t min_uint8_value; + bool down_button_is_held = (button_index == down_button_index); + bool down_button_was_tapped = (button_press_count[down_button_index] > 0); + uint8_t tap_count = (down_button_was_tapped ? button_press_count[down_button_index] : button_press_count[up_button_index]); + switch (tap_count) { + case 0: + // If the power is on, adjust the brightness. Set the direction based on which button is + // pressed. The new brightness will be calculated below. +#ifdef USE_PWM_DIMMER_REMOTE + if ((!active_device_is_local ? active_remote_pwm_dimmer->power : power)) { +#else // USE_PWM_DIMMER_REMOTE + if (power) { +#endif // USE_PWM_DIMMER_REMOTE + bri_direction = (down_button_is_held ? -1 : 1); + } + + // If the power is not on, turn it on using a temporary brightness of bri_preset_low if + // the down button is pressed or bri_preset_low if the up button is pressed. + else { +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->bri = (down_button_is_held ? active_remote_pwm_dimmer->x_bri_preset_low : active_remote_pwm_dimmer->x_bri_preset_high); + else +#endif // USE_PWM_DIMMER_REMOTE + target_bri = (down_button_is_held ? Settings.bri_preset_low : Settings.bri_preset_high); + toggle_power = true; + button_hold_time[button_index] = now + 1000; + + // If the power button is also pressed, set the power button hold dimmer direction + // so holding the power switch adjusts the brightness away from the brightness we + // just set. +#ifdef USE_PWM_DIMMER_REMOTE + if (button_pressed[power_button_index]) active_remote_pwm_dimmer->power_button_increases_bri = down_button_is_held; +#endif // USE_PWM_DIMMER_REMOTE + } + break; + + case 1: + if (down_button_was_tapped) { + // Select the previous/next color. +#ifdef USE_DEVICE_GROUPS +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + uint8_value = active_remote_pwm_dimmer->fixed_color_index; + else +#endif // USE_PWM_DIMMER_REMOTE + uint8_value = fixed_color_index; + if (down_button_is_held) { + if (uint8_value) + uint8_value--; + else + uint8_value = MAX_FIXED_COLOR; + } + else { + if (uint8_value < MAX_FIXED_COLOR) + uint8_value++; + else + uint8_value = 0; + } +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->fixed_color_index = uint8_value; + else +#endif // USE_PWM_DIMMER_REMOTE + fixed_color_index = uint8_value; + dgr_item = DGR_ITEM_LIGHT_FIXED_COLOR; + dgr_value = uint8_value; +#endif // USE_DEVICE_GROUPS + ; + } + else { + // Publish MQTT Event SwitchTrigger#. + char topic[TOPSZ]; +#ifdef USE_PWM_DIMMER_REMOTE + snprintf(topic, sizeof(topic), "%s/cmnd/Event", active_device_group->group_name); +#else // USE_PWM_DIMMER_REMOTE + snprintf(topic, sizeof(topic), "%s/cmnd/Event", SettingsText(SET_MQTT_GRP_TOPIC)); +#endif // USE_PWM_DIMMER_REMOTE + sprintf(mqtt_data, "SwitchTrigger%u", (down_button_is_held ? 1 : 2)); + MqttPublish(topic); + } + break; + + case 2: + if (down_button_was_tapped) { + // Decrease/increase the minimum brightness. +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + uint8_value = active_remote_pwm_dimmer->x_bri_min; + else +#endif // USE_PWM_DIMMER_REMOTE + uint8_value = Settings.bri_min; + if (down_button_is_held) { + if (uint8_value > 4) uint8_value--; + } + else if (uint8_value < 255) { + uint8_value++; + } +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) { + active_remote_pwm_dimmer->x_bri_min = uint8_value; + if (active_remote_pwm_dimmer->x_bri_power_on < uint8_value) active_remote_pwm_dimmer->x_bri_power_on = uint8_value; + } + else { +#endif // USE_PWM_DIMMER_REMOTE + Settings.bri_min = uint8_value; + if (Settings.bri_power_on < uint8_value) Settings.bri_power_on = uint8_value; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + dgr_item = DGR_ITEM_BRI_MIN; + dgr_value = uint8_value; + } + else { + // Decrease/increase the fade speed. +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + uint8_value = active_remote_pwm_dimmer->light_speed; + else +#endif // USE_PWM_DIMMER_REMOTE + uint8_value = Settings.light_speed; + if (down_button_is_held) { + if (uint8_value > 1) uint8_value--; + } + else if (uint8_value < 40) { + uint8_value++; + } +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->light_speed = uint8_value; + else +#endif // USE_PWM_DIMMER_REMOTE + Settings.light_speed = uint8_value; + dgr_item = DGR_ITEM_LIGHT_SPEED; + dgr_value = uint8_value; + } + break; + + case 3: + if (down_button_was_tapped) { + // Decrease/increase the low brightness preset. +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) { + uint8_value = active_remote_pwm_dimmer->x_bri_preset_low; + min_uint8_value =active_remote_pwm_dimmer->x_bri_min; + } + else { +#endif // USE_PWM_DIMMER_REMOTE + uint8_value = Settings.bri_preset_low; + min_uint8_value = Settings.bri_min; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + if (down_button_is_held) { + if (uint8_value > min_uint8_value) uint8_value--; + } + else if (uint8_value < 255) { + uint8_value++; + } +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->x_bri_preset_low = uint8_value; + else +#endif // USE_PWM_DIMMER_REMOTE + Settings.bri_preset_low = uint8_value; + dgr_item = DGR_ITEM_BRI_PRESET_LOW; + dgr_value = uint8_value; + } + else { + // Decrease/increase the high brightness preset. +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + uint8_value = active_remote_pwm_dimmer->x_bri_preset_high; + else +#endif // USE_PWM_DIMMER_REMOTE + uint8_value = Settings.bri_preset_high; + if (down_button_is_held) { + if (uint8_value > 4) uint8_value--; + } + else if (uint8_value < 255) { + uint8_value++; + } +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->x_bri_preset_high = uint8_value; + else +#endif // USE_PWM_DIMMER_REMOTE + Settings.bri_preset_high = uint8_value; + dgr_item = DGR_ITEM_BRI_PRESET_HIGH; + dgr_value = uint8_value; + } + break; + } + + button_was_held = true; + + // If the button was tapped before it was held, reset the button hold time to one second and + // turn all the brightness LEDs on for 250ms. + if (tap_count > 0) { + button_hold_time[button_index] = now + 1000; + turn_off_brightness_leds_time = now + 250; + PWMDimmerSetBrightnessLeds(1); + } + } + else if (turn_off_brightness_leds_time && turn_off_brightness_leds_time < millis()) { + turn_off_brightness_leds_time = 0; + PWMDimmerSetBrightnessLeds(-1); + } +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + } + + // If we need to adjust the brightness, do it. The brightness is adjusted faster the longer the + // button is held. + if (bri_direction) { + int32_t bri; +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + bri = active_remote_pwm_dimmer->bri; + else +#endif // USE_PWM_DIMMER_REMOTE + bri = target_bri; + int32_t new_bri; + int32_t offset = bri / 12 + 1; + if (bri_direction > 0) { + new_bri = bri + offset; + if (new_bri > 255) new_bri = 255; + } + else { + new_bri = bri - offset; + if (new_bri < Settings.bri_min) new_bri = Settings.bri_min; + } + if (new_bri != bri) { +#ifdef USE_DEVICE_GROUPS + SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_ITEM_LIGHT_BRI, new_bri); +#endif // USE_DEVICE_GROUPS +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->x_bri_power_on = active_remote_pwm_dimmer->bri = new_bri; + else { +#endif // USE_PWM_DIMMER_REMOTE + Settings.bri_power_on = target_bri = new_bri; + Settings.light_dimmer = changeUIntScale(target_bri, 0, 255, 0, 100); + PWMDimmerAnimate(true); +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + } + } + } + + // If the button was just released, ... + else if (button_pressed[button_index]) { + + // If the button was held, send a button off; otherwise, send a button toggle. + SendKey(KEY_BUTTON, button_index + 1, (button_hold_sent[button_index] ? POWER_OFF : POWER_TOGGLE)); + + // If this is about the power button, ... +#ifdef USE_PWM_DIMMER_REMOTE + if (button_index == power_button_index) { +#else // USE_PWM_DIMMER_REMOTE + if (!button_index) { +#endif // USE_PWM_DIMMER_REMOTE + + // If we're ignoring the next power button released, ... + if (ignore_power_button_release) { + ignore_power_button_release = false; + + // If the power button was held with no other buttons pressed, we changed the brightness so + // invert the bri direction for the next time and send a final update. + if (invert_power_button_bri_direction) { + invert_power_button_bri_direction = false; + dgr_item = DGR_ITEM_LIGHT_BRI; +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) { + active_remote_pwm_dimmer->power_button_increases_bri ^= 1; + dgr_value = active_remote_pwm_dimmer->bri; + } + else { +#endif // USE_PWM_DIMMER_REMOTE + power_button_increases_bri ^= 1; + dgr_value = target_bri; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + } + + // The up and/or down buttons were pressed while the power button was pressed. Handle the + // options based on the number of times the buttons were pressed. + else { + switch (button_press_count[down_button_index]) { + case 1: + // Toggle the powered-off LED option. +#ifdef USE_PWM_DIMMER_REMOTE + if (active_device_is_local) { +#endif // USE_PWM_DIMMER_REMOTE + Settings.flag3.powered_off_led ^= 1; + PWMDimmerSetPoweredOffLed(); +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + break; + case 2: + // Toggle fading. + dgr_item = DGR_ITEM_LIGHT_FADE; +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) { + active_remote_pwm_dimmer->light_fade ^= 1; + dgr_value = active_remote_pwm_dimmer->light_fade; + } + else { +#endif // USE_PWM_DIMMER_REMOTE + Settings.light_fade ^= 1; + dgr_value = Settings.light_fade; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + break; + } + button_press_count[down_button_index] = 0; + + switch (button_press_count[up_button_index]) { + case 1: + // Toggle the LED timeout. +#ifdef USE_PWM_DIMMER_REMOTE + if (active_device_is_local) { +#endif // USE_PWM_DIMMER_REMOTE + Settings.flag.led_timeout ^= 1; + if (relay_is_on) PWMDimmerSetBrightnessLeds(Settings.flag.led_timeout ? -1 : 0); +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + break; + } + button_press_count[up_button_index] = 0; + } + } + + // If we're not ignoring the power button until it's released, toggle the power. + else { +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->x_bri_power_on; + else +#endif // USE_PWM_DIMMER_REMOTE + target_bri = Settings.bri_power_on; + toggle_power = true; + } + } + + // If this is about the up or down buttons, ... + else { + + // If the button was held, ... + if (button_was_held) { + button_was_held = false; + + // If the button was tapped before it was held, we used the brightness LEDs to inidcate the + // operation so reset the brightness LEDs. + if (button_press_count[down_button_index] > 0 || button_press_count[up_button_index]) { + turn_off_brightness_leds_time = 0; + PWMDimmerSetBrightnessLeds(0); + } + + // If the button was not tapped before it was held, we changed the brightness and sent + // updates with the more-to-come message type. Send a final update. + else { + dgr_item = DGR_ITEM_LIGHT_BRI; +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + dgr_value = active_remote_pwm_dimmer->bri; + else +#endif // USE_PWM_DIMMER_REMOTE + dgr_value = target_bri; + } + + // Reset the the button press count. + button_press_count[button_index] = 0; + } + + // If the button was tapped (pressed and released quickly), increment the count of how many + // times this button has been pressed. + else if (button_hold_time[button_index] >= now) { + button_press_count[button_index]++; + } + } + + // Flag the button as released. + button_pressed[button_index] = false; +#ifdef USE_PWM_DIMMER_REMOTE + buttons_pressed--; +#endif // USE_PWM_DIMMER_REMOTE + } + + if (toggle_power) { + power_t new_power; + uint8_t new_bri; +#ifdef USE_DEVICE_GROUPS +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) { + active_remote_pwm_dimmer->power ^= 1; + new_power = active_remote_pwm_dimmer->power; + new_bri = active_remote_pwm_dimmer->bri; + } + else { +#endif // USE_PWM_DIMMER_REMOTE + new_power = power ^ 1; + new_bri = target_bri; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE + if (new_power) + SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_BRI, new_bri, DGR_ITEM_POWER, new_power); + else + SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, new_power); +#endif // USE_DEVICE_GROUPS + +#ifdef USE_PWM_DIMMER_REMOTE + // The target brightness has already been set. Execute the toggle power command with a source of + // SRC_RETRY. This will turn the power on using the current target brightness (see + // FUNC_SET_DEVICE_POWER below). + if (active_device_is_local) +#endif // USE_PWM_DIMMER_REMOTE + ExecuteCommandPower(1, POWER_TOGGLE, SRC_RETRY); + } + + // If we're not toggling the power and we made changes, send a group update. + else if (dgr_item) { +#ifdef USE_DEVICE_GROUPS + SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE_DIRECT, dgr_item, dgr_value); +#endif // USE_DEVICE_GROUPS + if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT + MqttPublishTeleState(); + } + } +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +void CmndBriMin(void) +{ + uint8_t new_bri_min = Settings.bri_min; + if (XdrvMailbox.payload > 0 && XdrvMailbox.payload <= 255) { + new_bri_min = (XdrvMailbox.payload < 4 ? 4 : XdrvMailbox.payload); + } + else if (1 == XdrvMailbox.data_len) { + if ('-' == XdrvMailbox.data[0]) { + if (new_bri_min > 4) new_bri_min--; + } + else if ('+' == XdrvMailbox.data[0] && new_bri_min < 255) + new_bri_min++; + } + + if (new_bri_min != Settings.bri_min) { + Settings.bri_min = new_bri_min; + PWMDimmerCheckBri(&Settings.bri_power_on); + PWMDimmerCheckBri(&Settings.bri_preset_low); + PWMDimmerCheckBri(&Settings.bri_preset_high); + +#ifdef DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_MIN, Settings.bri_min, + DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, + DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); +#endif // DEVICE_GROUPS + } + + ResponseCmndNumber(Settings.bri_min); +} + +void CmndBriPreset(void) +{ + if (XdrvMailbox.data_len > 0) { + bool valid = true; + uint32_t value; + uint8_t parm[2]; + parm[0] = Settings.bri_preset_low; + parm[1] = Settings.bri_preset_high; + char * ptr = XdrvMailbox.data; + for (uint32_t i = 0; i < 2; i++) { + while (*ptr == ' ') ptr++; + if (*ptr == '+') { + if (parm[i] < 255) parm[i]++; + } + else if (*ptr == '-') { + if (parm[i] > Settings.bri_min) parm[i]--; + } + else { + value = strtoul(ptr, &ptr, 0); + if (value < 1 || parm[i] > 255) { + valid = false; + break; + } + parm[i] = value; + PWMDimmerCheckBri(&parm[i]); + if (*ptr != ',') break; + } + ptr++; + } + if (valid && !*ptr) { + if (parm[0] < parm[1]) { + Settings.bri_preset_low = parm[0]; + Settings.bri_preset_high = parm[1]; + } else + { + Settings.bri_preset_low = parm[1]; + Settings.bri_preset_high = parm[0]; + } +#ifdef DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); +#endif // DEVICE_GROUPS + } + } + Response_P(PSTR("{\"" D_CMND_BRI_PRESET "\":{\"Low\":%d,\"High\":%d}}"), Settings.bri_preset_low, Settings.bri_preset_high); +} + +void PWMDmmerCmndDimmer(void) +{ + uint8_t dimmer = changeUIntScale(target_bri, 0, 255, 0, 100); + if (1 == XdrvMailbox.data_len) { + if ('+' == XdrvMailbox.data[0]) + XdrvMailbox.payload = (dimmer > 89) ? 100 : dimmer + 10; + else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (dimmer < 11) ? 1 : dimmer - 10; + } + } + + if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 100) { + uint8_t bri = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_BRI, bri); +#endif // USE_DEVICE_GROUPS + PWMDimmerSetBri(bri); + } + + ResponseCmndNumber(Settings.light_dimmer); +} + +void CmndLedTimeout(void) +{ + // Set the brightness LED timeout state. + switch (XdrvMailbox.payload) { + case 0: // Off + case 1: // On + Settings.flag.led_timeout = XdrvMailbox.payload; + break; + case 2: // Toggle + Settings.flag.led_timeout ^= 1; + break; + } + if (relay_is_on) PWMDimmerSetBrightnessLeds(0); + ResponseCmndStateText(Settings.flag.led_timeout); +} + +void CmndPoweredOffLed(void) +{ + // Set the powered-off LED state. + switch (XdrvMailbox.payload) { + case 0: // Off + case 1: // On + Settings.flag3.powered_off_led = XdrvMailbox.payload; + break; + case 2: // Toggle + Settings.flag3.powered_off_led ^= 1; + break; + } + PWMDimmerSetPoweredOffLed(); + ResponseCmndStateText(Settings.flag3.powered_off_led); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv35(uint8_t function) +{ + bool result = false; + + if (PWM_DIMMER != my_module_type) return result; + + switch (function) { + case FUNC_LOOP: + if (current_bri != target_bri) PWMDimmerAnimate(false); + break; + + case FUNC_EVERY_SECOND: + // Turn off the brightness LED's if it's time. + if (led_timeout_time && led_timeout_time < millis()) { + for (uint32_t index = 0; index < leds_present; index++) SetLedPowerIdx(index, 0); + led_timeout_time = 0; + } + + // The powered-off LED is also the LedLink LED. If we lose the WiFi or MQTT server + // connection, the LED will be set to a blinking state and will be turned off when the + // connection is restored. If the state is blinking now, set a flag so we know that we need + // to restore it when it stops blinking. + if (global_state.data) + restore_powered_off_led = 5; + else if (restore_powered_off_led) { + PWMDimmerSetPoweredOffLed(); + restore_powered_off_led--; + } + break; + + case FUNC_BUTTON_PRESSED: + // Handle the button press/release instead of the button handler. + PWMDimmerHandleButton(); + result = true; + break; + +#ifdef USE_DEVICE_GROUPS + case FUNC_DEVICE_GROUP_REQUEST: + PWMDimmerHandleDeviceGroupRequest(); + break; +#endif // USE_DEVICE_GROUPS + + case FUNC_SET_DEVICE_POWER: + // Handle turning the power on/off here so we can fade off. Set the target brightness and let + // Animate handle turning the power off/on. If the source is SRC_RETRY, we're turning the + // power on with a brightness preset and the target brightness has already been set. + if (!XdrvMailbox.index) + target_bri = 0; + else if (SRC_RETRY != XdrvMailbox.payload) { + target_bri = Settings.bri_power_on; + Settings.light_dimmer = changeUIntScale(target_bri, 0, 255, 0, 100); + } + result = true; + break; + + case FUNC_COMMAND: + result = DecodeCommand(kPWMDimmerCommands, PWMDimmerCommand); + break; + + case FUNC_INIT: + PWMDimmerInit(); + break; + + case FUNC_PRE_INIT: +#ifdef USE_PWM_DIMMER_REMOTE + // If remote device mode is enabled, set the device group count to the number of buttons + // present. + if (Settings.flag3.remote_device_mode) { + for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { + if (pin[GPIO_KEY1 + button_index] < 99) device_group_count++; + } + } +#endif // USE_PWM_DIMMER_REMOTE + break; + + case FUNC_MODULE_INIT: + PWMModuleInit(); + result = true; + break; + } + return result; +} + +#endif // USE_PWM_DIMMER \ No newline at end of file diff --git a/tasmota/xsns_06_dht_v5.ino b/tasmota/xsns_06_dht_v5.ino index f08286b43..9c7003970 100644 --- a/tasmota/xsns_06_dht_v5.ino +++ b/tasmota/xsns_06_dht_v5.ino @@ -100,6 +100,7 @@ bool DhtRead(uint32_t sensor) break; } +/* bool error = false; noInterrupts(); if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { @@ -127,6 +128,22 @@ bool DhtRead(uint32_t sensor) } interrupts(); if (error) { return false; } +*/ + + uint32_t i = 0; + noInterrupts(); + if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { + for (i = 0; i < 40; i++) { + if (!DhtWaitState(sensor, 1)) { break; } + delayMicroseconds(35); // Was 30 + if (digitalRead(Dht[sensor].pin)) { + dht_data[i / 8] |= (1 << (7 - i % 8)); + } + if (!DhtWaitState(sensor, 0)) { break; } + } + } + interrupts(); + if (i < 40) { return false; } uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; if (dht_data[4] != checksum) { diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/xsns_61_MI_NRF24.ino index 8527c9749..f1db19d74 100644 --- a/tasmota/xsns_61_MI_NRF24.ino +++ b/tasmota/xsns_61_MI_NRF24.ino @@ -21,6 +21,9 @@ Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + 0.9.3.0 20200222 integrate - use now the correct id-word instead of MAC-OUI, + add CGG1 + --- 0.9.2.0 20200212 integrate - "backports" from MI-HM10, change reading pattern, add missing PDU-types, renaming driver --- @@ -58,18 +61,21 @@ #define MJ_HT_V1 2 #define LYWSD02 3 #define LYWSD03 4 +#define CGG1 5 -uint8_t kMINRFSlaveID[4][3] = { 0xC4,0x7C,0x8D, // Flora - 0x58,0x2D,0x34, // MJ_HT_V1 - 0xE7,0x2E,0x00, // LYWSD02 - 0xA4,0xC1,0x38, // LYWSD03 - }; +const uint16_t kMINRFSlaveID[5]={ 0x0098, // Flora + 0x01aa, // MJ_HT_V1 + 0x045b, // LYWSD02 + 0x055b, // LYWSD03 + 0x0347 // CGG1 + }; const char kMINRFSlaveType1[] PROGMEM = "Flora"; const char kMINRFSlaveType2[] PROGMEM = "MJ_HT_V1"; const char kMINRFSlaveType3[] PROGMEM = "LYWSD02"; const char kMINRFSlaveType4[] PROGMEM = "LYWSD03"; -const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4}; +const char kMINRFSlaveType5[] PROGMEM = "CGG1"; +const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4,kMINRFSlaveType5}; // PDU's or different channels 37-39 const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; @@ -77,10 +83,11 @@ const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71da7646}; // 1 and 3 unsure // const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0xffffffff}; //encrypted - 58 58 const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; //unencrypted - 30 58 +const uint32_t kMINRFCGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; // start-LSFR for different channels 37-39 const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; // Flora, LYWSD02 -const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03 +const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03, CGG1 #pragma pack(1) // important!! @@ -269,7 +276,7 @@ struct { } MINRF; struct mi_sensor_t{ - uint8_t type; //Flora = 1; MJ_HT_V1=2; LYWSD02=3; LYWSD03=4 + uint8_t type; //Flora = 1; MJ_HT_V1=2; LYWSD02=3; LYWSD03=4; ; CGG1=5 uint8_t serial[6]; uint8_t showedUp; float temp; //Flora, MJ_HT_V1, LYWSD0x @@ -362,6 +369,9 @@ bool MINRFreceivePacket(void) case 4: MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); // "LYWSD03" mode break; + case 5: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); // "CGG1" mode + break; } // DEBUG_SENSOR_LOG(PSTR("MINRF: LSFR:%x"),_lsfr); // if (_lsfr>254) _lsfr=0; @@ -470,6 +480,9 @@ void MINRFchangePacketModeTo(uint8_t _mode) { if(kMINRFL3PDU[_nextchannel]==0xffffffff) break; NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]);// 95 fe 58 30 -> LYWSD03 (= no data message) break; + case 5: // special CGG1 packet + NRF24radio.openReadingPipe(0,kMINRFCGPDU[_nextchannel]); // 95 fe 50 30 -> CGG1 + break; } // DEBUG_SENSOR_LOG(PSTR("MINRF: Change Mode to %u"),_mode); MINRF.packetMode = _mode; @@ -479,24 +492,25 @@ void MINRFchangePacketModeTo(uint8_t _mode) { * @brief Return the slot number of a known sensor or return create new sensor slot * * @param _serial BLE address of the sensor - * @param _type Type number of the sensor, 0xff for Auto-type + * @param _type Type number of the sensor * @return uint32_t Known or new slot in the sensors-vector */ -uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ - if(_type==0xff){ - DEBUG_SENSOR_LOG(PSTR("MINRF: will test MAC-type")); - for (uint32_t i=0;i<4;i++){ - if(memcmp(_serial,kMINRFSlaveID+i,3)==0){ - DEBUG_SENSOR_LOG(PSTR("MINRF: MAC is type %u"), i); - _type = i+1; - } - else { - DEBUG_SENSOR_LOG(PSTR("MINRF: MAC-type is unknown")); - } +uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ + + DEBUG_SENSOR_LOG(PSTR("MINRF: will test ID-type: %x"), _type); + bool _success = false; + for (uint32_t i=0;i<5;i++){ + if(_type == kMINRFSlaveID[i]){ + DEBUG_SENSOR_LOG(PSTR("MINRF: ID is type %u"), i); + _type = i+1; + _success = true; + } + else { + DEBUG_SENSOR_LOG(PSTR("MINRF: ID-type is not: %x"),kMINRFSlaveID[i]); } } - if(_type==0xff) return _type; // error - + if(!_success) return 0xff; + DEBUG_SENSOR_LOG(PSTR("MINRF: vector size %u"), MIBLEsensors.size()); for(uint32_t i=0; i6000){ // happens every 6000/20 = 300 seconds @@ -712,15 +766,16 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds else if (MINRF.packetMode == LYWSD03){ MINRFhandleLYWSD03Packet(); } - - // DEBUG_SENSOR_LOG(PSTR("MINRF: Change packet mode every 50 msec")); - if (MINRF.packetMode == LYWSD03){ + else if (MINRF.packetMode == CGG1){ + MINRFhandleCGG1Packet(); + } + if (MINRF.packetMode == CGG1){ MINRFinitBLE(1); // no real ble packets in release mode, otherwise for developing use 0 } else { MINRFinitBLE(++MINRF.packetMode); } - + MINRFhopChannel(); NRF24radio.startListening(); } diff --git a/tools/decode-status.py b/tools/decode-status.py index 210175de8..3838d8faf 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -193,7 +193,7 @@ a_features = [[ "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", "USE_DHT12","USE_DS1624","USE_GPS","USE_HOTPLUG", "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", - "USE_AHT1x","","","" + "USE_AHT1x","USE_WEMOS_MOTOR_V1","","" ],[ "","","","", "","","","", @@ -236,7 +236,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200220 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200222 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From 2b94cd77a0a474a363d4f43223dffa1578e82214 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 07:34:30 -0600 Subject: [PATCH 467/559] Build with device groups, pwm dimmer (with remote) --- tasmota/my_user_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 353dc1130..0ae6d4663 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -415,9 +415,9 @@ //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug -// #define USE_DEVICE_GROUPS // Add support for device groups (+3k5 code) -// #define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) -// #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) +#define USE_DEVICE_GROUPS // Add support for device groups (+3k5 code) +#define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) +#define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // From 9682da603a817cde2782582b960dfcf5f60e2e4e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 24 Feb 2020 16:47:41 +0100 Subject: [PATCH 468/559] Add Device Group storage Add Device Group storage (#7786) --- tasmota/settings.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index b1afca3ea..7952dd9cf 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -104,7 +104,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t alexa_ct_range : 1; // bit 0 (v8.1.0.2) - SetOption82 - Reduced CT range for Alexa uint32_t zigbee_use_names : 1; // bit 1 (v8.1.0.4) - SetOption83 - Use FriendlyNames instead of ShortAddresses when possible uint32_t awsiot_shadow : 1; // bit 2 (v8.1.0.5) - SetOption84 - (AWS IoT) publish MQTT state to a device shadow - uint32_t spare03 : 1; + uint32_t device_groups_enabled : 1; // bit 3 (v8.1.0.9) - SetOption85 - Enable Device Groups uint32_t spare04 : 1; uint32_t spare05 : 1; uint32_t spare06 : 1; @@ -467,8 +467,10 @@ struct SYSCFG { uint8_t hotplug_scan; // F03 uint8_t reserved1; // F04 - reserved for s-hadinger - uint8_t free_f05[207]; // F05 + uint8_t free_f05[199]; // F05 + uint32_t device_group_share_in; // FCC - Bitmask of device group items imported + uint32_t device_group_share_out; // FD0 - Bitmask of device group items exported uint32_t bootcount_reset_time; // FD4 int adc_param4; // FD8 uint32_t shutter_button[MAX_KEYS]; // FDC From 5ec1ab83edb7257015d524b79776ca23234d603b Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Mon, 24 Feb 2020 17:25:03 +0100 Subject: [PATCH 469/559] extend TX2x sensor stats new JSON for TX2x (for legacy format define USE_TX2x_LEGACY_JSON) exp weighted average prevents jump in avg values after period refactor sensor reading --- tasmota/language/bg-BG.h | 2 + tasmota/language/cs-CZ.h | 2 + tasmota/language/de-DE.h | 8 ++- tasmota/language/el-GR.h | 2 + tasmota/language/en-GB.h | 2 + tasmota/language/es-ES.h | 2 + tasmota/language/fr-FR.h | 2 + tasmota/language/he-HE.h | 2 + tasmota/language/hu-HU.h | 2 + tasmota/language/it-IT.h | 2 + tasmota/language/ko-KO.h | 4 +- tasmota/language/nl-NL.h | 2 + tasmota/language/pl-PL.h | 2 + tasmota/language/pt-BR.h | 2 + tasmota/language/pt-PT.h | 2 + tasmota/language/ru-RU.h | 2 + tasmota/language/sk-SK.h | 2 + tasmota/language/sv-SE.h | 2 + tasmota/language/tr-TR.h | 2 + tasmota/language/uk-UA.h | 2 + tasmota/language/zh-CN.h | 2 + tasmota/language/zh-TW.h | 2 + tasmota/xsns_35_tx20.ino | 140 ++++++++++++++++++++++++--------------- 23 files changed, 134 insertions(+), 58 deletions(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index be2fceb3c..8acbff8e1 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Посока на вятъра" +#define D_TX20_WIND_DEGREES "Степени на вятъра" #define D_TX20_WIND_SPEED "Скорост на вятъра" #define D_TX20_WIND_SPEED_AVG "Средна скорост на вятъра" +#define D_TX20_WIND_SPEED_MIN "Мини. скорост на вятъра" #define D_TX20_WIND_SPEED_MAX "Макс. скорост на вятъра" #define D_TX20_NORTH "С" #define D_TX20_EAST "И" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 6ef51f27d..2d15ac443 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Směr větru" +#define D_TX20_WIND_DEGREES "Úhel větru" #define D_TX20_WIND_SPEED "Rychlost větru" #define D_TX20_WIND_SPEED_AVG "Průměrná rychlost větru" +#define D_TX20_WIND_SPEED_MIN "Minimální rychlost větru" #define D_TX20_WIND_SPEED_MAX "Maximální rychlost větru" #define D_TX20_NORTH "S" #define D_TX20_EAST "V" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index cf2aa258b..e87624bfa 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -503,10 +503,12 @@ #define D_CALIBRATION "Kalibrierung" //xsns_35_tx20.ino -#define D_TX20_WIND_DIRECTION "Wind Richtung" +#define D_TX20_WIND_DIRECTION "Windrichtung" +#define D_TX20_WIND_DEGREES "Windrichtung Grad" #define D_TX20_WIND_SPEED "Windgeschwindigkeit" -#define D_TX20_WIND_SPEED_AVG "Ø Windgeschwindigkeit" -#define D_TX20_WIND_SPEED_MAX "max Windgeschwindigkeit" +#define D_TX20_WIND_SPEED_AVG "Windgeschwindigkeit Ø" +#define D_TX20_WIND_SPEED_MIN "Windgeschwindigkeit Min" +#define D_TX20_WIND_SPEED_MAX "Windgeschwindigkeit Max" #define D_TX20_NORTH "N" #define D_TX20_EAST "O" #define D_TX20_SOUTH "S" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index b3608bb7b..dbeb71a68 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Κατεύθυνση ανέμου" +#define D_TX20_WIND_DEGREES "Βαθμός ανέμου" #define D_TX20_WIND_SPEED "Ταχύτητα ανέμου" #define D_TX20_WIND_SPEED_AVG "Μέση ταχύτητα ανέμου" +#define D_TX20_WIND_SPEED_MIN "Ελάχιστη ταχύτητα ανέμου" #define D_TX20_WIND_SPEED_MAX "Μέγιστη ταχύτητα ανέμου" #define D_TX20_NORTH "Β" #define D_TX20_EAST "Α" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 66a6e0243..792c2b597 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_DEGREES "Wind Degrees" #define D_TX20_WIND_SPEED "Wind Speed" #define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MIN "Wind Speed Min" #define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 59916f487..77e7c6047 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Dirección del Viento" +#define D_TX20_WIND_DEGREES "Ángulo del Viento" #define D_TX20_WIND_SPEED "Vel. del Viento" #define D_TX20_WIND_SPEED_AVG "Vel. Prom. del Viento" +#define D_TX20_WIND_SPEED_MIN "Vel. Min. del Viento" #define D_TX20_WIND_SPEED_MAX "Vel. Max. del Viento" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index 5356848d8..a63955ab7 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -504,8 +504,10 @@ //xsns_35_TX20.ino #define D_TX20_WIND_DIRECTION "Direction du vent" +#define D_TX20_WIND_DEGREES "Degré de vent" #define D_TX20_WIND_SPEED "Vitesse du vent" #define D_TX20_WIND_SPEED_AVG "Vitesse Moy." +#define D_TX20_WIND_SPEED_MIN "Vitesse Min" #define D_TX20_WIND_SPEED_MAX "Vitesse Max" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index fa3b07a31..86af3c35a 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "כיוון הרוח" +#define D_TX20_WIND_DEGREES "זווית הרוח" #define D_TX20_WIND_SPEED "מהירות הרוח" #define D_TX20_WIND_SPEED_AVG "מהירות הרוח ממוצעת" +#define D_TX20_WIND_SPEED_MIN "מהירות הרוח היא מינימלית" #define D_TX20_WIND_SPEED_MAX "מהירות הרוח מקסימלית" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index 541d0c783..d9348dde1 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Szélirány" +#define D_TX20_WIND_DEGREES "Szél mértéke" #define D_TX20_WIND_SPEED "Szélsebesség" #define D_TX20_WIND_SPEED_AVG "Átlag szélsebesség" +#define D_TX20_WIND_SPEED_MIN "Min. szélsebesség" #define D_TX20_WIND_SPEED_MAX "Max. szélsebesség" #define D_TX20_NORTH "É" #define D_TX20_EAST "K" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index 62127ef24..e5ee2f1aa 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Direzione Vento" +#define D_TX20_WIND_DEGREES "Angolo Vento" #define D_TX20_WIND_SPEED "Velocità Vento" #define D_TX20_WIND_SPEED_AVG "Velocità Media Vento" +#define D_TX20_WIND_SPEED_MIN "Velocità Minima Vento" #define D_TX20_WIND_SPEED_MAX "Velocità Massima Vento" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 2a20ce2d0..f8cd83e99 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -504,9 +504,11 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "풍향" +#define D_TX20_WIND_DEGREES "바람 정도" #define D_TX20_WIND_SPEED "풍속" #define D_TX20_WIND_SPEED_AVG "평균 풍속" -#define D_TX20_WIND_SPEED_MAX "최대 풍속" +#define D_TX20_WIND_SPEED_MIN "풍속 최소" +#define D_TX20_WIND_SPEED_MAX "풍속 최대" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" #define D_TX20_SOUTH "S" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 658f18547..bc9b1876e 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Windrichting" +#define D_TX20_WIND_DEGREES "Wind graad" #define D_TX20_WIND_SPEED "Windsnelheid" #define D_TX20_WIND_SPEED_AVG "Windsnelheid gemiddeld" +#define D_TX20_WIND_SPEED_MIN "Windsnelhied minimum" #define D_TX20_WIND_SPEED_MAX "Windsnelhied maximaal" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index e2d59a2dc..9cc522fa7 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Kierunek" +#define D_TX20_WIND_DEGREES "Grad" #define D_TX20_WIND_SPEED "Prędkość" #define D_TX20_WIND_SPEED_AVG "Średnia prędkość" +#define D_TX20_WIND_SPEED_MIN "Minimalna prędkość" #define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index da386917c..4909fc08c 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Direção do vento" +#define D_TX20_WIND_DEGREES "Ângulo do vento" #define D_TX20_WIND_SPEED "Velocidade do vento" #define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" +#define D_TX20_WIND_SPEED_MIN "Velocidade do vento Mínima" #define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima" #define D_TX20_NORTH "N" #define D_TX20_EAST "L" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 1f9c36a6b..1e49c449c 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Direção do vento" +#define D_TX20_WIND_DEGREES "Ângulo do vento" #define D_TX20_WIND_SPEED "Velocidade do vento" #define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" +#define D_TX20_WIND_SPEED_MIN "Velocidade mínima do vento" #define D_TX20_WIND_SPEED_MAX "Velocidade máxima do vento" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 846a653ac..a312000b7 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_DEGREES "Wind Degrees" #define D_TX20_WIND_SPEED "Wind Speed" #define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MIN "Wind Speed Min" #define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index f335ca42d..f5041901a 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Smer vetra" +#define D_TX20_WIND_DEGREES "Uhol vetra" #define D_TX20_WIND_SPEED "Rýchlosť vetra" #define D_TX20_WIND_SPEED_AVG "Priemerná rýchlosť vetra" +#define D_TX20_WIND_SPEED_MIN "Minimálna rýchlosť vetra" #define D_TX20_WIND_SPEED_MAX "Maximálna rýchlosť vetra" #define D_TX20_NORTH "S" #define D_TX20_EAST "V" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index 9485c1f4e..7741c8937 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Vindriktning" +#define D_TX20_WIND_DEGREES "Vindvinkel" #define D_TX20_WIND_SPEED "Vindstyrka" #define D_TX20_WIND_SPEED_AVG "Vindstyrka medel" +#define D_TX20_WIND_SPEED_MIN "Vindstyrka min" #define D_TX20_WIND_SPEED_MAX "Vindstyrka max" #define D_TX20_NORTH "N" #define D_TX20_EAST "Ö" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index ee2a548ae..51f0a3ddb 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_DEGREES "Wind Degrees" #define D_TX20_WIND_SPEED "Wind Speed" #define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MIN "Wind Speed Min" #define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index 98a352ea7..a7bcfa5da 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Напрям вітру" +#define D_TX20_WIND_DEGREES "Кут вітру" #define D_TX20_WIND_SPEED "Швидкість вітру" #define D_TX20_WIND_SPEED_AVG "Середня швидкість вітру" +#define D_TX20_WIND_SPEED_MIN "Мінімальна швидкість вітру" #define D_TX20_WIND_SPEED_MAX "Максимальна швидкість вітру" #define D_TX20_NORTH "Пн" #define D_TX20_EAST "Сх" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index c46d353ea..53e05b1f4 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "风向" +#define D_TX20_WIND_DEGREES "风度" #define D_TX20_WIND_SPEED "风速" #define D_TX20_WIND_SPEED_AVG "平均风速" +#define D_TX20_WIND_SPEED_MIN "最低风速" #define D_TX20_WIND_SPEED_MAX "最高风速" #define D_TX20_NORTH "北" #define D_TX20_EAST "东" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 118aeb501..2e9994046 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -504,8 +504,10 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_DEGREES "Wind Degrees" #define D_TX20_WIND_SPEED "Wind Speed" #define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MIN "Wind Speed Min" #define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_NORTH "N" #define D_TX20_EAST "E" diff --git a/tasmota/xsns_35_tx20.ino b/tasmota/xsns_35_tx20.ino index 850c7deda..14fd5c9f9 100644 --- a/tasmota/xsns_35_tx20.ino +++ b/tasmota/xsns_35_tx20.ino @@ -41,7 +41,8 @@ #define XSNS_35 35 #define TX2X_BIT_TIME 1220 // microseconds -#define TX2X_RESET_VALUES 60 // seconds +#define TX2X_WEIGHT_AVG_SAMPLE 150 // seconds +#define TX23_READ_INTERVAL 4 // seconds (don't use less than 3) // The Arduino standard GPIO routines are not enough, // must use some from the Espressif SDK as well @@ -59,8 +60,9 @@ extern "C" { const char HTTP_SNS_TX2X[] PROGMEM = "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s (%s°){e}"; + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s %s°{e}"; #endif // USE_WEBSERVER const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" @@ -88,11 +90,12 @@ uint16_t tx2x_sc = 0; uint16_t tx2x_sf = 0; float tx2x_wind_speed_kmh = 0; +float tx2x_wind_speed_min = 200.0; float tx2x_wind_speed_max = 0; float tx2x_wind_speed_avg = 0; -float tx2x_wind_sum = 0; -int tx2x_count = 0; uint8_t tx2x_wind_direction = 0; +int tx2x_count = 0; +uint16_t tx2x_avg_samples; bool tx2x_available = false; @@ -121,7 +124,6 @@ void TX2xStartRead(void) * La Crosse TX23 Anemometer datagram after setting TxD to low/high * 1-1 0 1 0-0 11011 0011 111010101111 0101 1100 000101010000 1-1 - Received pin data at 1200 uSec per bit * t s c sa sb sc sd se sf - * 1 0 1-1 00100 1100 000101010000 1010 1100 000101010000 - sa to sd inverted user data, LSB first * t - host pulls TxD low - signals TX23 to sent measurement * s - TxD released - TxD is pulled high due to pullup * c - TX23U pulls TxD low - calculation in progress @@ -152,26 +154,8 @@ void TX2xStartRead(void) for (int32_t bitcount = 41; bitcount > 0; bitcount--) { uint8_t dpin = (digitalRead(pin[GPIO_TX2X_TXD_BLACK])); #ifdef USE_TX23_WIND_SENSOR - if (bitcount > 41 - 5) { - // start - tx2x_sa = (tx2x_sa << 1) | (dpin); - } else if (bitcount > 41 - 5 - 4) { - // wind dir - tx2x_sb = tx2x_sb >> 1 | ((dpin) << 3); - } else if (bitcount > 41 - 5 - 4 - 12) { - // windspeed - tx2x_sc = tx2x_sc >> 1 | ((dpin) << 11); - } else if (bitcount > 41 - 5 - 4 - 12 - 4) { - // checksum - tx2x_sd = tx2x_sd >> 1 | ((dpin) << 3); - } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { - // wind dir (invert) - tx2x_se = tx2x_se >> 1 | ((dpin ^ 1) << 3); - } else { - // windspeed (invert) - tx2x_sf = tx2x_sf >> 1 | ((dpin ^ 1) << 11); - } -#else + dpin ^= 1; +#endif if (bitcount > 41 - 5) { // start frame (invert) tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1); @@ -191,23 +175,14 @@ void TX2xStartRead(void) // windspeed tx2x_sf = tx2x_sf >> 1 | (dpin << 11); } -#endif delayMicroseconds(TX2X_BIT_TIME); } uint8_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); chk &= 0xf; -#ifdef USE_TX23_WIND_SENSOR // check checksum, non-inverted with inverted values and max. speed - if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { - tx2x_available = true; - } -#else - if ((chk == tx2x_sd) && (tx2x_sc < 511)) { // if checksum seems to be ok and wind speed below 51.1 m/s - tx2x_available = true; - } -#endif + tx2x_available = ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)); #ifdef USE_TX23_WIND_SENSOR } tx23_stage++; @@ -219,49 +194,82 @@ void TX2xStartRead(void) GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX2X_TXD_BLACK]); } -void Tx2xReset(void) +void Tx2xResetStat(void) { + tx2x_wind_speed_min = tx2x_wind_speed_kmh; + tx2x_wind_speed_max = tx2x_wind_speed_kmh; + uint16_t tx2x_prev_avg_samples = tx2x_avg_samples; + if (Settings.tele_period) { + // number for avg samples = teleperiod value if set + tx2x_avg_samples = Settings.tele_period; + } else { + // otherwise use default number of samples for this driver + tx2x_avg_samples = TX2X_WEIGHT_AVG_SAMPLE; + } + if (tx2x_prev_avg_samples != tx2x_avg_samples) { + tx2x_wind_speed_avg = tx2x_wind_speed_kmh; tx2x_count = 0; - tx2x_wind_sum = 0; - tx2x_wind_speed_max = 0; + } } void Tx2xRead(void) { #ifdef USE_TX23_WIND_SENSOR + // TX23 needs to trigger start transmission - TxD Line + // ___________ _ ___ ___ + // |____| |___________| |_| |__XXXXXXXXXX + // trigger start conv Startframe Data + // // note: TX23 speed calculation is unstable when conversion starts // less than 2 seconds after last request - if ((uptime % 3)==0) { + if ((uptime % TX23_READ_INTERVAL)==0) { // TX23 start transmission by pulling down TxD line for at minimum 500ms // so we pull TxD signal to low every 3 seconds tx23_stage = 0; pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); - } else if ((uptime % 3)==1) { - // after pulling down TxD every 3 second we pull-up TxD every 3+1 seconds - // to trigger start transmission + } else if ((uptime % TX23_READ_INTERVAL)==1) { + // after pulling down TxD: pull-up TxD every x+1 seconds + // to trigger TX23 start transmission tx23_stage = 1; // first rising signal is invalid pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT_PULLUP); } #endif - if (0==Settings.tele_period && !(uptime % TX2X_RESET_VALUES)) { - Tx2xReset(); + if (0!=Settings.tele_period && Settings.tele_period!=tx2x_avg_samples) { + // new teleperiod value + Tx2xResetStat(); } - else if (tx2x_available) { + if (tx2x_available) { // Wind speed spec: 0 to 180 km/h (0 to 50 m/s) tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36; + if (tx2x_wind_speed_kmh < tx2x_wind_speed_min) { + tx2x_wind_speed_min = tx2x_wind_speed_kmh; + } if (tx2x_wind_speed_kmh > tx2x_wind_speed_max) { tx2x_wind_speed_max = tx2x_wind_speed_kmh; } - tx2x_count++; - tx2x_wind_sum += tx2x_wind_speed_kmh; - tx2x_wind_speed_avg = tx2x_wind_sum / tx2x_count; + // exponentially weighted average is not quite as smooth as the arithmetic average + // but close enough to the moving average and does not require the regular reset + // of the divider with the associated jump in avg values after period is over + if (tx2x_count <= tx2x_avg_samples) { + tx2x_count++; + } + tx2x_wind_speed_avg -= tx2x_wind_speed_avg / tx2x_count; + tx2x_wind_speed_avg += tx2x_wind_speed_kmh / tx2x_count; + tx2x_wind_direction = tx2x_sb; + + if (!(uptime % tx2x_avg_samples)) { + tx2x_wind_speed_min = tx2x_wind_speed_kmh; + tx2x_wind_speed_max = tx2x_wind_speed_kmh; + + } } } void Tx2xInit(void) { + Tx2xResetStat(); #ifdef USE_TX23_WIND_SENSOR tx23_stage = 0; pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); @@ -276,22 +284,46 @@ void Tx2xShow(bool json) { char wind_speed_string[33]; dtostrfd(tx2x_wind_speed_kmh, 1, wind_speed_string); + char wind_speed_min_string[33]; + dtostrfd(tx2x_wind_speed_min, 1, wind_speed_min_string); char wind_speed_max_string[33]; dtostrfd(tx2x_wind_speed_max, 1, wind_speed_max_string); char wind_speed_avg_string[33]; dtostrfd(tx2x_wind_speed_avg, 1, wind_speed_avg_string); + char wind_direction_degree_string[33]; + dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_degree_string); char wind_direction_string[4]; GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx2x_wind_direction, kTx2xDirections); - char wind_direction_degree[33]; - dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_degree); if (json) { +#ifdef USE_TX2x_LEGACY_JSON ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); - Tx2xReset(); +#else + // new format grouped by Speed and Dir(ection) + // Card = cardianal (N../O../S../W..) + // Deg = Degree + ResponseAppend_P( + PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s},\"Direction\":{\"Cardinal\":\"%s\",\"Degree\":%s}}"), + wind_speed_string, + wind_speed_avg_string, + wind_speed_min_string, + wind_speed_max_string, + wind_direction_string, + wind_direction_degree_string + ); +#endif #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_SNS_TX2X, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); + WSContentSend_PD( + HTTP_SNS_TX2X, + wind_speed_string, + wind_speed_avg_string, + wind_speed_min_string, + wind_speed_max_string, + wind_direction_string, + wind_direction_degree_string + ); #endif // USE_WEBSERVER } } @@ -313,11 +345,11 @@ bool Xsns35(uint8_t function) Tx2xRead(); break; case FUNC_JSON_APPEND: - Tx2xShow(1); + Tx2xShow(true); break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: - Tx2xShow(0); + Tx2xShow(false); break; #endif // USE_WEBSERVER } From e25f14f37aa97361159e536856b8cb81d08d1548 Mon Sep 17 00:00:00 2001 From: "he.so" Date: Thu, 20 Feb 2020 20:50:46 +0100 Subject: [PATCH 470/559] Jarolift shutter working with keeloq --- lib/KeeloqLib/README.md | 12 + lib/KeeloqLib/keywords.txt | 20 + lib/KeeloqLib/library.properties | 9 + lib/KeeloqLib/src/KeeloqLib.cpp | 58 ++ lib/KeeloqLib/src/KeeloqLib.h | 28 + .../tests/KeeloqLibTest/KeeloqLibTest.ino | 27 + lib/cc1101/README.md | 1 + lib/cc1101/cc1101.cpp | 548 +++++++++++++++++ lib/cc1101/cc1101.h | 548 +++++++++++++++++ lib/cc1101/cc1101.h.txt | 549 ++++++++++++++++++ lib/cc1101/ccpacket.h | 70 +++ tasmota/my_user_config.h | 1 + tasmota/settings.h | 6 +- tasmota/xdrv_35_keeloq.ino | 275 +++++++++ 14 files changed, 2151 insertions(+), 1 deletion(-) create mode 100644 lib/KeeloqLib/README.md create mode 100644 lib/KeeloqLib/keywords.txt create mode 100644 lib/KeeloqLib/library.properties create mode 100644 lib/KeeloqLib/src/KeeloqLib.cpp create mode 100644 lib/KeeloqLib/src/KeeloqLib.h create mode 100644 lib/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino create mode 100644 lib/cc1101/README.md create mode 100644 lib/cc1101/cc1101.cpp create mode 100644 lib/cc1101/cc1101.h create mode 100644 lib/cc1101/cc1101.h.txt create mode 100644 lib/cc1101/ccpacket.h create mode 100644 tasmota/xdrv_35_keeloq.ino diff --git a/lib/KeeloqLib/README.md b/lib/KeeloqLib/README.md new file mode 100644 index 000000000..5b8e5b77d --- /dev/null +++ b/lib/KeeloqLib/README.md @@ -0,0 +1,12 @@ +## Keeloq encryption algorithm +This implementations might be useful if you are playing around with [Microchip Keeloq](http://www.microchip.com/pagehandler/en-us/technology/embeddedsecurity/technology/keeloqencoderdl.html) chips. +I verified that this algorithm gives the same results as that produced by the Microchip SDK for several test cases. +The Keeloq algorithm is not patented. +However, since Microchip does hold a patent on its application to secure keyless entry, +it probably would not be wise to make a commercial secure keyless entry product using this algorithm in a non-Microchip processor. +Personal experimentation should be okay. + +__If you decide to make something commercial, buy Microchip's processors.__ + + + diff --git a/lib/KeeloqLib/keywords.txt b/lib/KeeloqLib/keywords.txt new file mode 100644 index 000000000..c07c1ea48 --- /dev/null +++ b/lib/KeeloqLib/keywords.txt @@ -0,0 +1,20 @@ +####################################### +# Syntax Coloring Map For CamelliaLib. +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Keeloq KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +encrypt KEYWORD2 +decrypt KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/lib/KeeloqLib/library.properties b/lib/KeeloqLib/library.properties new file mode 100644 index 000000000..fa974d9bf --- /dev/null +++ b/lib/KeeloqLib/library.properties @@ -0,0 +1,9 @@ +name=KeeloqLib +version=1.1 +author=Mirko Falchetto +maintainer=Mirko Falchetto +sentence=C++ Class Implementing Keeloq cipher by Microchip.com. +paragraph=Developed/Tested on Arduino/ESP8266 with Arduino IDE Environment. +category=Uncategorized +url=http://none.net +architectures=* diff --git a/lib/KeeloqLib/src/KeeloqLib.cpp b/lib/KeeloqLib/src/KeeloqLib.cpp new file mode 100644 index 000000000..5dc1619b9 --- /dev/null +++ b/lib/KeeloqLib/src/KeeloqLib.cpp @@ -0,0 +1,58 @@ +/* + Keeloq.cpp - Keeloq encryption/decryption + Written by Frank Kienast in November, 2010 +*/ + +#include "KeeloqLib.h" + +#define KeeLoq_NLF (0x3A5C742EUL) + +Keeloq::Keeloq(const unsigned long keyHigh, const unsigned long keyLow) : +_keyHigh( keyHigh ), +_keyLow( keyLow ) +{ +} + +unsigned long Keeloq::encrypt( const unsigned long data ) +{ + unsigned long x = data; + unsigned long r; + int keyBitNo, index; + unsigned long keyBitVal,bitVal; + + for ( r = 0; r < 528; r++ ) + { + keyBitNo = r & 63; + if(keyBitNo < 32) + keyBitVal = bitRead(_keyLow,keyBitNo); + else + keyBitVal = bitRead(_keyHigh, keyBitNo - 32); + index = 1 * bitRead(x,1) + 2 * bitRead(x,9) + 4 * bitRead(x,20) + 8 * bitRead(x,26) + 16 * bitRead(x,31); + bitVal = bitRead(x,0) ^ bitRead(x, 16) ^ bitRead(KeeLoq_NLF,index) ^ keyBitVal; + x = (x>>1) ^ bitVal<<31; + } + return x; +} + +unsigned long Keeloq::decrypt( const unsigned long data ) +{ + unsigned long x = data; + unsigned long r; + int keyBitNo, index; + unsigned long keyBitVal,bitVal; + + for (r = 0; r < 528; r++) + { + keyBitNo = (15-r) & 63; + if(keyBitNo < 32) + keyBitVal = bitRead(_keyLow,keyBitNo); + else + keyBitVal = bitRead(_keyHigh, keyBitNo - 32); + index = 1 * bitRead(x,0) + 2 * bitRead(x,8) + 4 * bitRead(x,19) + 8 * bitRead(x,25) + 16 * bitRead(x,30); + bitVal = bitRead(x,31) ^ bitRead(x, 15) ^ bitRead(KeeLoq_NLF,index) ^ keyBitVal; + x = (x<<1) ^ bitVal; + } + return x; + } + + diff --git a/lib/KeeloqLib/src/KeeloqLib.h b/lib/KeeloqLib/src/KeeloqLib.h new file mode 100644 index 000000000..ea18fadb6 --- /dev/null +++ b/lib/KeeloqLib/src/KeeloqLib.h @@ -0,0 +1,28 @@ +/* + Keeloq.h - Crypto library + Written by Frank Kienast in November, 2010 +*/ +#ifndef Keeloq_lib_h +#define Keeloq_lib_h +#if defined(ARDUINO) && ARDUINO >= 100 +#include +#else +#include +#endif + +class Keeloq +{ + public: + Keeloq( + const unsigned long keyHigh, + const unsigned long keyLow ); + + unsigned long encrypt( const unsigned long data ); + unsigned long decrypt( const unsigned long data ); + + private: + unsigned long _keyHigh; + unsigned long _keyLow; +}; + +#endif /*Keeloq_lib_h*/ diff --git a/lib/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino b/lib/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino new file mode 100644 index 000000000..2e25730dd --- /dev/null +++ b/lib/KeeloqLib/tests/KeeloqLibTest/KeeloqLibTest.ino @@ -0,0 +1,27 @@ +#include + +void setup( void ) +{ + Serial.begin(9600); + + Keeloq k(0x01020304,0x05060708); + + const unsigned long p = 6623281UL; + const unsigned long enc = k.encrypt(p); + const unsigned long dec = k.decrypt(enc); + + Serial.print("Plaintext : "); + Serial.println(p,DEC); + + Serial.print("After encrypt: "); + Serial.println(enc,HEX); + + Serial.print("After decrypt: "); + Serial.println(dec,DEC); +} + +void loop( void ) +{ + delay(3000); +} + diff --git a/lib/cc1101/README.md b/lib/cc1101/README.md new file mode 100644 index 000000000..249930ed1 --- /dev/null +++ b/lib/cc1101/README.md @@ -0,0 +1 @@ +Port of panStamp's CC1101 Library to ESP8266. diff --git a/lib/cc1101/cc1101.cpp b/lib/cc1101/cc1101.cpp new file mode 100644 index 000000000..6a828e7d8 --- /dev/null +++ b/lib/cc1101/cc1101.cpp @@ -0,0 +1,548 @@ +#include + +/** + * Copyright (c) 2011 panStamp + * + * This file is part of the panStamp project. + * + * panStamp is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * panStamp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with panStamp; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Author: Daniel Berenguer + * Creation date: 03/03/2011 + */ + +extern "C" { +#include "cc1101.h" +} + +#define PORT_GDO0 5 +#define byte uint8_t + +/** + * Macros + */ +// Select (SPI) CC1101 +#define cc1101_Select() spi.begin() +// Deselect (SPI) CC1101 +#define cc1101_Deselect() spi.end() +// Wait until SPI MISO line goes low +#define wait_Miso() delay(10) +//while(digitalRead(PORT_SPI_MISO)) +// Get GDO0 pin state +#define getGDO0state() digitalRead(PORT_GDO0) +// Wait until GDO0 line goes high +#define wait_GDO0_high() while(!getGDO0state()) {delay(1);} +// Wait until GDO0 line goes low +#define wait_GDO0_low() while(getGDO0state()) {delay(1);} + + /** + * PATABLE + */ +const byte paTable[8] = {0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/** + * CC1101 + * + * Class constructor + */ +CC1101::CC1101(void) +{ + carrierFreq = CFREQ_868; + channel = CC1101_DEFVAL_CHANNR; + syncWord[0] = CC1101_DEFVAL_SYNC1; + syncWord[1] = CC1101_DEFVAL_SYNC0; + devAddress = CC1101_DEFVAL_ADDR; + paTableByte = PA_LowPower; // Priority = Low power +} + +/** + * wakeUp + * + * Wake up CC1101 from Power Down state + */ +void CC1101::wakeUp(void) +{ + cc1101_Select(); // Select CC1101 + wait_Miso(); // Wait until MISO goes low + cc1101_Deselect(); // Deselect CC1101 +} + +/** + * writeReg + * + * Write single register into the CC1101 IC via SPI + * + * 'regAddr' Register address + * 'value' Value to be writen + */ +void CC1101::writeReg(byte regAddr, byte value) +{ + cc1101_Select(); // Select CC1101 + wait_Miso(); // Wait until MISO goes low + spi.transfer(regAddr); // Send register address + spi.transfer(value); // Send value + cc1101_Deselect(); // Deselect CC1101 +} + +/** + * writeBurstReg + * + * Write multiple registers into the CC1101 IC via SPI + * + * 'regAddr' Register address + * 'buffer' Data to be writen + * 'len' Data length + */ +void CC1101::writeBurstReg(byte regAddr, byte* buffer, byte len) +{ + byte addr, i; + + addr = regAddr | WRITE_BURST; // Enable burst transfer + cc1101_Select(); // Select CC1101 + wait_Miso(); // Wait until MISO goes low + spi.transfer(addr); // Send register address + + for(i=0 ; i 0) + { + // Set data length at the first position of the TX FIFO + writeReg(CC1101_TXFIFO, packet.length); + // Write data into the TX FIFO + writeBurstReg(CC1101_TXFIFO, packet.data, packet.length); + + // CCA enabled: will enter TX state only if the channel is clear + setTxState(); + } + + // Check that TX state is being entered (state = RXTX_SETTLING) + marcState = readStatusReg(CC1101_MARCSTATE) & 0x1F; + if((marcState != 0x13) && (marcState != 0x14) && (marcState != 0x15)) + { + setIdleState(); // Enter IDLE state + flushTxFifo(); // Flush Tx FIFO + setRxState(); // Back to RX state + + // Declare to be in Rx state + rfState = RFSTATE_RX; + return false; + } + + // Wait for the sync word to be transmitted + wait_GDO0_high(); + + // Wait until the end of the packet transmission + wait_GDO0_low(); + + // Check that the TX FIFO is empty + if((readStatusReg(CC1101_TXBYTES) & 0x7F) == 0) + res = true; + + setIdleState(); // Enter IDLE state + flushTxFifo(); // Flush Tx FIFO + + // Enter back into RX state + setRxState(); + + // Declare to be in Rx state + rfState = RFSTATE_RX; + + return res; +} + +/** + * receiveData + * + * Read data packet from RX FIFO + * + * 'packet' Container for the packet received + * + * Return: + * Amount of bytes received + */ +byte CC1101::receiveData(CCPACKET * packet) +{ + byte val; + byte rxBytes = readStatusReg(CC1101_RXBYTES); + + // Any byte waiting to be read and no overflow? + if (rxBytes & 0x7F) + { + // Read data length + packet->length = readConfigReg(CC1101_RXFIFO); + // If packet is too long + if (packet->length > CCPACKET_DATA_LEN) + packet->length = 0; // Discard packet + else + { + // Read data packet + readBurstReg(packet->data, CC1101_RXFIFO, packet->length); + // Read RSSI + packet->rssi = readConfigReg(CC1101_RXFIFO); + // Read LQI and CRC_OK + val = readConfigReg(CC1101_RXFIFO); + packet->lqi = val & 0x7F; + packet->crc_ok = bitRead(val, 7); + } + } + else + packet->length = 0; + + setIdleState(); // Enter IDLE state + flushRxFifo(); // Flush Rx FIFO + //cmdStrobe(CC1101_SCAL); + + // Back to RX state + setRxState(); + + return packet->length; +} + +/** + * setRxState + * + * Enter Rx state + */ +void CC1101::setRxState(void) +{ + cmdStrobe(CC1101_SRX); + rfState = RFSTATE_RX; +} + +/** + * setTxState + * + * Enter Tx state + */ +void CC1101::setTxState(void) +{ + cmdStrobe(CC1101_STX); + rfState = RFSTATE_TX; +} diff --git a/lib/cc1101/cc1101.h b/lib/cc1101/cc1101.h new file mode 100644 index 000000000..8636d8678 --- /dev/null +++ b/lib/cc1101/cc1101.h @@ -0,0 +1,548 @@ +#include + +/** + * Copyright (c) 2011 panStamp + * + * This file is part of the panStamp project. + * + * panStamp is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * panStamp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with panStamp; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Author: Daniel Berenguer + * Creation date: 03/03/2011 + */ + +#ifndef _CC1101_H +#define _CC1101_H + +//#include "simplespi.h" +extern "C" { +#include +#include "ccpacket.h" +} + +/** + * Carrier frequencies + */ +enum CFREQ +{ + CFREQ_868 = 0, + CFREQ_915, + CFREQ_433, + CFREQ_918, + CFREQ_LAST +}; + +/** + * RF STATES + */ +enum RFSTATE +{ + RFSTATE_IDLE = 0, + RFSTATE_RX, + RFSTATE_TX +}; + + +/** + * Frequency channels + */ +#define NUMBER_OF_FCHANNELS 10 + +/** + * Type of transfers + */ +#define WRITE_BURST 0x40 +#define READ_SINGLE 0x80 +#define READ_BURST 0xC0 + +/** + * Type of register + */ +#define CC1101_CONFIG_REGISTER READ_SINGLE +#define CC1101_STATUS_REGISTER READ_BURST + +/** + * PATABLE & FIFO's + */ +#define CC1101_PATABLE 0x3E // PATABLE address +#define CC1101_TXFIFO 0x3F // TX FIFO address +#define CC1101_RXFIFO 0x3F // RX FIFO address + +/** + * Command strobes + */ +#define CC1101_SRES 0x30 // Reset CC1101 chip +#define CC1101_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA): + // Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround). +#define CC1101_SXOFF 0x32 // Turn off crystal oscillator +#define CC1101_SCAL 0x33 // Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without + // setting manual calibration mode (MCSM0.FS_AUTOCAL=0) +#define CC1101_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1 +#define CC1101_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1. + // If in RX state and CCA is enabled: Only go to TX if channel is clear +#define CC1101_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable +#define CC1101_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio) as described in Section 19.5 if + // WORCTRL.RC_PD=0 +#define CC1101_SPWD 0x39 // Enter power down mode when CSn goes high +#define CC1101_SFRX 0x3A // Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states +#define CC1101_SFTX 0x3B // Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states +#define CC1101_SWORRST 0x3C // Reset real time clock to Event1 value +#define CC1101_SNOP 0x3D // No operation. May be used to get access to the chip status byte + +/** + * CC1101 configuration registers + */ +#define CC1101_IOCFG2 0x00 // GDO2 Output Pin Configuration +#define CC1101_IOCFG1 0x01 // GDO1 Output Pin Configuration +#define CC1101_IOCFG0 0x02 // GDO0 Output Pin Configuration +#define CC1101_FIFOTHR 0x03 // RX FIFO and TX FIFO Thresholds +#define CC1101_SYNC1 0x04 // Sync Word, High Byte +#define CC1101_SYNC0 0x05 // Sync Word, Low Byte +#define CC1101_PKTLEN 0x06 // Packet Length +#define CC1101_PKTCTRL1 0x07 // Packet Automation Control +#define CC1101_PKTCTRL0 0x08 // Packet Automation Control +#define CC1101_ADDR 0x09 // Device Address +#define CC1101_CHANNR 0x0A // Channel Number +#define CC1101_FSCTRL1 0x0B // Frequency Synthesizer Control +#define CC1101_FSCTRL0 0x0C // Frequency Synthesizer Control +#define CC1101_FREQ2 0x0D // Frequency Control Word, High Byte +#define CC1101_FREQ1 0x0E // Frequency Control Word, Middle Byte +#define CC1101_FREQ0 0x0F // Frequency Control Word, Low Byte +#define CC1101_MDMCFG4 0x10 // Modem Configuration +#define CC1101_MDMCFG3 0x11 // Modem Configuration +#define CC1101_MDMCFG2 0x12 // Modem Configuration +#define CC1101_MDMCFG1 0x13 // Modem Configuration +#define CC1101_MDMCFG0 0x14 // Modem Configuration +#define CC1101_DEVIATN 0x15 // Modem Deviation Setting +#define CC1101_MCSM2 0x16 // Main Radio Control State Machine Configuration +#define CC1101_MCSM1 0x17 // Main Radio Control State Machine Configuration +#define CC1101_MCSM0 0x18 // Main Radio Control State Machine Configuration +#define CC1101_FOCCFG 0x19 // Frequency Offset Compensation Configuration +#define CC1101_BSCFG 0x1A // Bit Synchronization Configuration +#define CC1101_AGCCTRL2 0x1B // AGC Control +#define CC1101_AGCCTRL1 0x1C // AGC Control +#define CC1101_AGCCTRL0 0x1D // AGC Control +#define CC1101_WOREVT1 0x1E // High Byte Event0 Timeout +#define CC1101_WOREVT0 0x1F // Low Byte Event0 Timeout +#define CC1101_WORCTRL 0x20 // Wake On Radio Control +#define CC1101_FREND1 0x21 // Front End RX Configuration +#define CC1101_FREND0 0x22 // Front End TX Configuration +#define CC1101_FSCAL3 0x23 // Frequency Synthesizer Calibration +#define CC1101_FSCAL2 0x24 // Frequency Synthesizer Calibration +#define CC1101_FSCAL1 0x25 // Frequency Synthesizer Calibration +#define CC1101_FSCAL0 0x26 // Frequency Synthesizer Calibration +#define CC1101_RCCTRL1 0x27 // RC Oscillator Configuration +#define CC1101_RCCTRL0 0x28 // RC Oscillator Configuration +#define CC1101_FSTEST 0x29 // Frequency Synthesizer Calibration Control +#define CC1101_PTEST 0x2A // Production Test +#define CC1101_AGCTEST 0x2B // AGC Test +#define CC1101_TEST2 0x2C // Various Test Settings +#define CC1101_TEST1 0x2D // Various Test Settings +#define CC1101_TEST0 0x2E // Various Test Settings + +/** + * Status registers + */ +#define CC1101_PARTNUM 0x30 // Chip ID +#define CC1101_VERSION 0x31 // Chip ID +#define CC1101_FREQEST 0x32 // Frequency Offset Estimate from Demodulator +#define CC1101_LQI 0x33 // Demodulator Estimate for Link Quality +#define CC1101_RSSI 0x34 // Received Signal Strength Indication +#define CC1101_MARCSTATE 0x35 // Main Radio Control State Machine State +#define CC1101_WORTIME1 0x36 // High Byte of WOR Time +#define CC1101_WORTIME0 0x37 // Low Byte of WOR Time +#define CC1101_PKTSTATUS 0x38 // Current GDOx Status and Packet Status +#define CC1101_VCO_VC_DAC 0x39 // Current Setting from PLL Calibration Module +#define CC1101_TXBYTES 0x3A // Underflow and Number of Bytes +#define CC1101_RXBYTES 0x3B // Overflow and Number of Bytes +#define CC1101_RCCTRL1_STATUS 0x3C // Last RC Oscillator Calibration Result +#define CC1101_RCCTRL0_STATUS 0x3D // Last RC Oscillator Calibration Result + +/** + * CC1101 configuration registers - Default values extracted from SmartRF Studio + * + * Configuration: + * + * Deviation = 20.629883 + * Base frequency = 867.999939 + * Carrier frequency = 867.999939 + * Channel number = 0 + * Carrier frequency = 867.999939 + * Modulated = true + * Modulation format = GFSK + * Manchester enable = false + * Data whitening = off + * Sync word qualifier mode = 30/32 sync word bits detected + * Preamble count = 4 + * Channel spacing = 199.951172 + * Carrier frequency = 867.999939 + * Data rate = 38.3835 Kbps + * RX filter BW = 101.562500 + * Data format = Normal mode + * Length config = Variable packet length mode. Packet length configured by the first byte after sync word + * CRC enable = true + * Packet length = 255 + * Device address = 1 + * Address config = Enable address check + * Append status = Append two status bytes to the payload of the packet. The status bytes contain RSSI and + * LQI values, as well as CRC OK + * CRC autoflush = false + * PA ramping = false + * TX power = 12 + * GDO0 mode = Asserts when sync word has been sent / received, and de-asserts at the end of the packet. + * In RX, the pin will also de-assert when a packet is discarded due to address or maximum length filtering + * or when the radio enters RXFIFO_OVERFLOW state. In TX the pin will de-assert if the TX FIFO underflows + * Settings optimized for low current consumption + */ + +#define CC1101_DEFVAL_IOCFG2 0x0D // GDO2 Output Pin Configuration +#define CC1101_DEFVAL_IOCFG1 0x2E // GDO1 Output Pin Configuration +#define CC1101_DEFVAL_IOCFG0 0x2D // GDO0 Output Pin Configuration +#define CC1101_DEFVAL_FIFOTHR 0x07 // RX FIFO and TX FIFO Thresholds +#define CC1101_DEFVAL_SYNC1 0xD3 // Synchronization word, high byte +#define CC1101_DEFVAL_SYNC0 0x91 // Synchronization word, low byte +#define CC1101_DEFVAL_PKTLEN 0x3D // Packet Length +#define CC1101_DEFVAL_PKTCTRL1 0x04 // Packet Automation Control +#define CC1101_DEFVAL_PKTCTRL0 0x32 // Packet Automation Control +#define CC1101_DEFVAL_ADDR 0xFF // Device Address +#define CC1101_DEFVAL_CHANNR 0x00 // Channel Number +#define CC1101_DEFVAL_FSCTRL1 0x06 // Frequency Synthesizer Control +#define CC1101_DEFVAL_FSCTRL0 0x00 // Frequency Synthesizer Control +// Carrier frequency = 868 MHz +#define CC1101_DEFVAL_FREQ2_868 0x21 // Frequency Control Word, High Byte +#define CC1101_DEFVAL_FREQ1_868 0x62 // Frequency Control Word, Middle Byte +#define CC1101_DEFVAL_FREQ0_868 0x76 // Frequency Control Word, Low Byte +// Carrier frequency = 902 MHz +#define CC1101_DEFVAL_FREQ2_915 0x22 // Frequency Control Word, High Byte +#define CC1101_DEFVAL_FREQ1_915 0xB1 // Frequency Control Word, Middle Byte +#define CC1101_DEFVAL_FREQ0_915 0x3B // Frequency Control Word, Low Byte +// Carrier frequency = 918 MHz +#define CC1101_DEFVAL_FREQ2_918 0x23 // Frequency Control Word, High Byte +#define CC1101_DEFVAL_FREQ1_918 0x4E // Frequency Control Word, Middle Byte +#define CC1101_DEFVAL_FREQ0_918 0xC4 // Frequency Control Word, Low Byte + +// Carrier frequency = 433 MHz +#define CC1101_DEFVAL_FREQ2_433 0x10 // Frequency Control Word, High Byte +#define CC1101_DEFVAL_FREQ1_433 0xB0 // Frequency Control Word, Middle Byte +#define CC1101_DEFVAL_FREQ0_433 0xBD // Frequency Control Word, Low Byte + +#define CC1101_DEFVAL_MDMCFG4 0x56 // Modem Configuration +#define CC1101_DEFVAL_MDMCFG3 0x83 // Modem Configuration +#define CC1101_DEFVAL_MDMCFG2 0x30 // Modem Configuration +#define CC1101_DEFVAL_MDMCFG1 0x22 // Modem Configuration +#define CC1101_DEFVAL_MDMCFG0 0xF8 // Modem Configuration +#define CC1101_DEFVAL_DEVIATN 0x00 // Modem Deviation Setting +#define CC1101_DEFVAL_MCSM2 0x07 // Main Radio Control State Machine Configuration +#define CC1101_DEFVAL_MCSM1 0x00 // Main Radio Control State Machine Configuration +#define CC1101_DEFVAL_MCSM0 0x18 // Main Radio Control State Machine Configuration +#define CC1101_DEFVAL_FOCCFG 0x14 // Frequency Offset Compensation Configuration +#define CC1101_DEFVAL_BSCFG 0x6C // Bit Synchronization Configuration +#define CC1101_DEFVAL_AGCCTRL2 0x07 // AGC Control +#define CC1101_DEFVAL_AGCCTRL1 0x00 // AGC Control +#define CC1101_DEFVAL_AGCCTRL0 0x91 // AGC Control +#define CC1101_DEFVAL_WOREVT1 0x87 // High Byte Event0 Timeout +#define CC1101_DEFVAL_WOREVT0 0x6B // Low Byte Event0 Timeout +#define CC1101_DEFVAL_WORCTRL 0xF8 // Wake On Radio Control +#define CC1101_DEFVAL_FREND1 0x56 // Front End RX Configuration +#define CC1101_DEFVAL_FREND0 0x11 // Front End TX Configuration +#define CC1101_DEFVAL_FSCAL3 0xE9 // Frequency Synthesizer Calibration +#define CC1101_DEFVAL_FSCAL2 0x2A // Frequency Synthesizer Calibration +#define CC1101_DEFVAL_FSCAL1 0x00 // Frequency Synthesizer Calibration +#define CC1101_DEFVAL_FSCAL0 0x1F // Frequency Synthesizer Calibration +#define CC1101_DEFVAL_RCCTRL1 0x41 // RC Oscillator Configuration +#define CC1101_DEFVAL_RCCTRL0 0x00 // RC Oscillator Configuration +#define CC1101_DEFVAL_FSTEST 0x59 // Frequency Synthesizer Calibration Control +#define CC1101_DEFVAL_PTEST 0x7F // Production Test +#define CC1101_DEFVAL_AGCTEST 0x3F // AGC Test +#define CC1101_DEFVAL_TEST2 0x88 // Various Test Settings +#define CC1101_DEFVAL_TEST1 0x31 // Various Test Settings +#define CC1101_DEFVAL_TEST0 0x09 // Various Test Settings + +/** + * Alias for some default values + */ +#define CCDEF_CHANNR CC1101_DEFVAL_CHANNR +#define CCDEF_SYNC0 CC1101_DEFVAL_SYNC0 +#define CCDEF_SYNC1 CC1101_DEFVAL_SYNC1 +#define CCDEF_ADDR CC1101_DEFVAL_ADDR + +/** + * Macros + */ +// Read CC1101 Config register +#define readConfigReg(regAddr) readReg(regAddr, CC1101_CONFIG_REGISTER) +// Read CC1101 Status register +#define readStatusReg(regAddr) readReg(regAddr, CC1101_STATUS_REGISTER) +// Enter Rx state +//#define setRxState() cmdStrobe(CC1101_SRX) +// Enter Tx state +//#define setTxState() cmdStrobe(CC1101_STX) +// Enter IDLE state +#define setIdleState() cmdStrobe(CC1101_SIDLE) +// Flush Rx FIFO +#define flushRxFifo() cmdStrobe(CC1101_SFRX) +// Flush Tx FIFO +#define flushTxFifo() cmdStrobe(CC1101_SFTX) +// Disable address check +#define disableAddressCheck() writeReg(CC1101_PKTCTRL1, 0x04) +// Enable address check +#define enableAddressCheck() writeReg(CC1101_PKTCTRL1, 0x06) +// Disable CCA +#define disableCCA() writeReg(CC1101_MCSM1, 0) +// Enable CCA +#define enableCCA() writeReg(CC1101_MCSM1, CC1101_DEFVAL_MCSM1) +// Set PATABLE single byte +#define setTxPowerAmp(setting) paTableByte = setting +// PATABLE values +#define PA_LowPower 0x60 +#define PA_LongDistance 0xC0 + +/** + * Class: CC1101 + * + * Description: + * CC1101 interface + */ +class CC1101 +{ + private: + /** + * Atmega's SPI interface + */ + SPIClass spi; + + /** + * writeBurstReg + * + * Write multiple registers into the CC1101 IC via SPI + * + * 'regAddr' Register address + * 'buffer' Data to be writen + * 'len' Data length + */ + void writeBurstReg(uint8_t regAddr, uint8_t* buffer, uint8_t len); + + /** + * readBurstReg + * + * Read burst data from CC1101 via SPI + * + * 'buffer' Buffer where to copy the result to + * 'regAddr' Register address + * 'len' Data length + */ + void readBurstReg(uint8_t * buffer, uint8_t regAddr, uint8_t len); + + /** + * setRegsFromEeprom + * + * Set registers from EEPROM + */ + void setRegsFromEeprom(void); + + public: + /* + * RF state + */ + uint8_t rfState; + + /** + * Tx Power byte (single PATABLE config) + */ + uint8_t paTableByte; + + /** + * Carrier frequency + */ + uint8_t carrierFreq; + + /** + * Frequency channel + */ + uint8_t channel; + + /** + * Synchronization word + */ + uint8_t syncWord[2]; + + /** + * Device address + */ + uint8_t devAddress; + + /** + * CC1101 + * + * Class constructor + */ + CC1101(void); + + /** + * cmdStrobe + * + * Send command strobe to the CC1101 IC via SPI + * + * 'cmd' Command strobe + */ + void cmdStrobe(uint8_t cmd); + + /** + * wakeUp + * + * Wake up CC1101 from Power Down state + */ + void wakeUp(void); + + /** + * readReg + * + * Read CC1101 register via SPI + * + * 'regAddr' Register address + * 'regType' Type of register: CC1101_CONFIG_REGISTER or CC1101_STATUS_REGISTER + * + * Return: + * Data byte returned by the CC1101 IC + */ + uint8_t readReg(uint8_t regAddr, uint8_t regType); + + /** + * writeReg + * + * Write single register into the CC1101 IC via SPI + * + * 'regAddr' Register address + * 'value' Value to be writen + */ + void writeReg(uint8_t regAddr, uint8_t value); + + /** + * setCCregs + * + * Configure CC1101 registers + */ + void setCCregs(void); + + /** + * reset + * + * Reset CC1101 + */ + void reset(void); + + /** + * init + * + * Initialize CC1101 radio + * + * @param freq Carrier frequency + */ + void init(uint8_t freq=CFREQ_868); + + /** + * setSyncWord + * + * Set synchronization word + * + * 'syncH' Synchronization word - High byte + * 'syncL' Synchronization word - Low byte + */ + void setSyncWord(uint8_t syncH, uint8_t syncL); + + /** + * setSyncWord (overriding method) + * + * Set synchronization word + * + * 'syncH' Synchronization word - pointer to 2-byte array + */ + void setSyncWord(uint8_t *sync); + + /** + * setDevAddress + * + * Set device address + * + * 'addr' Device address + */ + void setDevAddress(uint8_t addr); + + /** + * setCarrierFreq + * + * Set carrier frequency + * + * 'freq' New carrier frequency + */ + void setCarrierFreq(uint8_t freq); + + /** + * setChannel + * + * Set frequency channel + * + * 'chnl' Frequency channel + */ + void setChannel(uint8_t chnl); + + /** + * setPowerDownState + * + * Put CC1101 into power-down state + */ + void setPowerDownState(); + + /** + * sendData + * + * Send data packet via RF + * + * 'packet' Packet to be transmitted. First byte is the destination address + * + * Return: + * True if the transmission succeeds + * False otherwise + */ + bool sendData(CCPACKET packet); + + /** + * receiveData + * + * Read data packet from RX FIFO + * + * Return: + * Amount of bytes received + */ + uint8_t receiveData(CCPACKET *packet); + + /** + * setRxState + * + * Enter Rx state + */ + void setRxState(void); + + /** + * setTxState + * + * Enter Tx state + */ + void setTxState(void); +}; + +#endif + diff --git a/lib/cc1101/cc1101.h.txt b/lib/cc1101/cc1101.h.txt new file mode 100644 index 000000000..6f48d992f --- /dev/null +++ b/lib/cc1101/cc1101.h.txt @@ -0,0 +1,549 @@ +#include + +/** + * Copyright (c) 2011 panStamp + * + * This file is part of the panStamp project. + * + * panStamp is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * panStamp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with panStamp; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Author: Daniel Berenguer + * Creation date: 03/03/2011 + */ + +#ifndef _CC1101_H +#define _CC1101_H + +//#include "simplespi.h" +extern "C" { +#include +#include "ccpacket.h" +} + +/** + * Carrier frequencies + */ +enum CFREQ +{ + CFREQ_868 = 0, + CFREQ_915, + CFREQ_433, + CFREQ_918, + CFREQ_LAST +}; + +/** + * RF STATES + */ +enum RFSTATE +{ + RFSTATE_IDLE = 0, + RFSTATE_RX, + RFSTATE_TX +}; + + +/** + * Frequency channels + */ +#define NUMBER_OF_FCHANNELS 10 + +/** + * Type of transfers + */ +#define WRITE_BURST 0x40 +#define READ_SINGLE 0x80 +#define READ_BURST 0xC0 + +/** + * Type of register + */ +#define CC1101_CONFIG_REGISTER READ_SINGLE +#define CC1101_STATUS_REGISTER READ_BURST + +/** + * PATABLE & FIFO's + */ +#define CC1101_PATABLE 0x3E // PATABLE address +#define CC1101_TXFIFO 0x3F // TX FIFO address +#define CC1101_RXFIFO 0x3F // RX FIFO address + +/** + * Command strobes + */ +#define CC1101_SRES 0x30 // Reset CC1101 chip +#define CC1101_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA): + // Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround). +#define CC1101_SXOFF 0x32 // Turn off crystal oscillator +#define CC1101_SCAL 0x33 // Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without + // setting manual calibration mode (MCSM0.FS_AUTOCAL=0) +#define CC1101_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1 +#define CC1101_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1. + // If in RX state and CCA is enabled: Only go to TX if channel is clear +#define CC1101_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable +#define CC1101_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio) as described in Section 19.5 if + // WORCTRL.RC_PD=0 +#define CC1101_SPWD 0x39 // Enter power down mode when CSn goes high +#define CC1101_SFRX 0x3A // Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states +#define CC1101_SFTX 0x3B // Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states +#define CC1101_SWORRST 0x3C // Reset real time clock to Event1 value +#define CC1101_SNOP 0x3D // No operation. May be used to get access to the chip status byte + +/** + * CC1101 configuration registers + */ +#define CC1101_IOCFG2 0x00 // GDO2 Output Pin Configuration +#define CC1101_IOCFG1 0x01 // GDO1 Output Pin Configuration +#define CC1101_IOCFG0 0x02 // GDO0 Output Pin Configuration +#define CC1101_FIFOTHR 0x03 // RX FIFO and TX FIFO Thresholds +#define CC1101_SYNC1 0x04 // Sync Word, High Byte +#define CC1101_SYNC0 0x05 // Sync Word, Low Byte +#define CC1101_PKTLEN 0x06 // Packet Length +#define CC1101_PKTCTRL1 0x07 // Packet Automation Control +#define CC1101_PKTCTRL0 0x08 // Packet Automation Control +#define CC1101_ADDR 0x09 // Device Address +#define CC1101_CHANNR 0x0A // Channel Number +#define CC1101_FSCTRL1 0x0B // Frequency Synthesizer Control +#define CC1101_FSCTRL0 0x0C // Frequency Synthesizer Control +#define CC1101_FREQ2 0x0D // Frequency Control Word, High Byte +#define CC1101_FREQ1 0x0E // Frequency Control Word, Middle Byte +#define CC1101_FREQ0 0x0F // Frequency Control Word, Low Byte +#define CC1101_MDMCFG4 0x10 // Modem Configuration +#define CC1101_MDMCFG3 0x11 // Modem Configuration +#define CC1101_MDMCFG2 0x12 // Modem Configuration +#define CC1101_MDMCFG1 0x13 // Modem Configuration +#define CC1101_MDMCFG0 0x14 // Modem Configuration +#define CC1101_DEVIATN 0x15 // Modem Deviation Setting +#define CC1101_MCSM2 0x16 // Main Radio Control State Machine Configuration +#define CC1101_MCSM1 0x17 // Main Radio Control State Machine Configuration +#define CC1101_MCSM0 0x18 // Main Radio Control State Machine Configuration +#define CC1101_FOCCFG 0x19 // Frequency Offset Compensation Configuration +#define CC1101_BSCFG 0x1A // Bit Synchronization Configuration +#define CC1101_AGCCTRL2 0x1B // AGC Control +#define CC1101_AGCCTRL1 0x1C // AGC Control +#define CC1101_AGCCTRL0 0x1D // AGC Control +#define CC1101_WOREVT1 0x1E // High Byte Event0 Timeout +#define CC1101_WOREVT0 0x1F // Low Byte Event0 Timeout +#define CC1101_WORCTRL 0x20 // Wake On Radio Control +#define CC1101_FREND1 0x21 // Front End RX Configuration +#define CC1101_FREND0 0x22 // Front End TX Configuration +#define CC1101_FSCAL3 0x23 // Frequency Synthesizer Calibration +#define CC1101_FSCAL2 0x24 // Frequency Synthesizer Calibration +#define CC1101_FSCAL1 0x25 // Frequency Synthesizer Calibration +#define CC1101_FSCAL0 0x26 // Frequency Synthesizer Calibration +#define CC1101_RCCTRL1 0x27 // RC Oscillator Configuration +#define CC1101_RCCTRL0 0x28 // RC Oscillator Configuration +#define CC1101_FSTEST 0x29 // Frequency Synthesizer Calibration Control +#define CC1101_PTEST 0x2A // Production Test +#define CC1101_AGCTEST 0x2B // AGC Test +#define CC1101_TEST2 0x2C // Various Test Settings +#define CC1101_TEST1 0x2D // Various Test Settings +#define CC1101_TEST0 0x2E // Various Test Settings + +/** + * Status registers + */ +#define CC1101_PARTNUM 0x30 // Chip ID +#define CC1101_VERSION 0x31 // Chip ID +#define CC1101_FREQEST 0x32 // Frequency Offset Estimate from Demodulator +#define CC1101_LQI 0x33 // Demodulator Estimate for Link Quality +#define CC1101_RSSI 0x34 // Received Signal Strength Indication +#define CC1101_MARCSTATE 0x35 // Main Radio Control State Machine State +#define CC1101_WORTIME1 0x36 // High Byte of WOR Time +#define CC1101_WORTIME0 0x37 // Low Byte of WOR Time +#define CC1101_PKTSTATUS 0x38 // Current GDOx Status and Packet Status +#define CC1101_VCO_VC_DAC 0x39 // Current Setting from PLL Calibration Module +#define CC1101_TXBYTES 0x3A // Underflow and Number of Bytes +#define CC1101_RXBYTES 0x3B // Overflow and Number of Bytes +#define CC1101_RCCTRL1_STATUS 0x3C // Last RC Oscillator Calibration Result +#define CC1101_RCCTRL0_STATUS 0x3D // Last RC Oscillator Calibration Result + +/** + * CC1101 configuration registers - Default values extracted from SmartRF Studio + * + * Configuration: + * + * Deviation = 20.629883 + * Base frequency = 867.999939 + * Carrier frequency = 867.999939 + * Channel number = 0 + * Carrier frequency = 867.999939 + * Modulated = true + * Modulation format = GFSK + * Manchester enable = false + * Data whitening = off + * Sync word qualifier mode = 30/32 sync word bits detected + * Preamble count = 4 + * Channel spacing = 199.951172 + * Carrier frequency = 867.999939 + * Data rate = 38.3835 Kbps + * RX filter BW = 101.562500 + * Data format = Normal mode + * Length config = Variable packet length mode. Packet length configured by the first byte after sync word + * CRC enable = true + * Packet length = 255 + * Device address = 1 + * Address config = Enable address check + * Append status = Append two status bytes to the payload of the packet. The status bytes contain RSSI and + * LQI values, as well as CRC OK + * CRC autoflush = false + * PA ramping = false + * TX power = 12 + * GDO0 mode = Asserts when sync word has been sent / received, and de-asserts at the end of the packet. + * In RX, the pin will also de-assert when a packet is discarded due to address or maximum length filtering + * or when the radio enters RXFIFO_OVERFLOW state. In TX the pin will de-assert if the TX FIFO underflows + * Settings optimized for low current consumption + */ +//#define CC1101_DEFVAL_IOCFG2 0x29 // GDO2 Output Pin Configuration +#define CC1101_DEFVAL_IOCFG2 0x0D // GDO2 Output Pin Configuration +#define CC1101_DEFVAL_IOCFG1 0x2E // GDO1 Output Pin Configuration +#define CC1101_DEFVAL_IOCFG0 0x2D // GDO0 Output Pin Configuration +#define CC1101_DEFVAL_FIFOTHR 0x07 // RX FIFO and TX FIFO Thresholds +#define CC1101_DEFVAL_SYNC1 0xD3 // Synchronization word, high byte +#define CC1101_DEFVAL_SYNC0 0x91 // Synchronization word, low byte +#define CC1101_DEFVAL_PKTLEN 0x3D // Packet Length +#define CC1101_DEFVAL_PKTCTRL1 0x04 // Packet Automation Control +#define CC1101_DEFVAL_PKTCTRL0 0x32 // Packet Automation Control +#define CC1101_DEFVAL_ADDR 0xFF // Device Address +#define CC1101_DEFVAL_CHANNR 0x00 // Channel Number +#define CC1101_DEFVAL_FSCTRL1 0x06 // Frequency Synthesizer Control +#define CC1101_DEFVAL_FSCTRL0 0x00 // Frequency Synthesizer Control +// Carrier frequency = 868 MHz +#define CC1101_DEFVAL_FREQ2_868 0x21 // Frequency Control Word, High Byte +#define CC1101_DEFVAL_FREQ1_868 0x62 // Frequency Control Word, Middle Byte +#define CC1101_DEFVAL_FREQ0_868 0x76 // Frequency Control Word, Low Byte +// Carrier frequency = 902 MHz +#define CC1101_DEFVAL_FREQ2_915 0x22 // Frequency Control Word, High Byte +#define CC1101_DEFVAL_FREQ1_915 0xB1 // Frequency Control Word, Middle Byte +#define CC1101_DEFVAL_FREQ0_915 0x3B // Frequency Control Word, Low Byte +// Carrier frequency = 918 MHz +#define CC1101_DEFVAL_FREQ2_918 0x23 // Frequency Control Word, High Byte +#define CC1101_DEFVAL_FREQ1_918 0x4E // Frequency Control Word, Middle Byte +#define CC1101_DEFVAL_FREQ0_918 0xC4 // Frequency Control Word, Low Byte + +// Carrier frequency = 433 MHz +#define CC1101_DEFVAL_FREQ2_433 0x10 // Frequency Control Word, High Byte +#define CC1101_DEFVAL_FREQ1_433 0xB0 // Frequency Control Word, Middle Byte +#define CC1101_DEFVAL_FREQ0_433 0xB0 // Frequency Control Word, Low Byte + +#define CC1101_DEFVAL_MDMCFG4 0xA9 // Modem Configuration +#define CC1101_DEFVAL_MDMCFG3 0xE4 // Modem Configuration +#define CC1101_DEFVAL_MDMCFG2 0x30 // Modem Configuration +#define CC1101_DEFVAL_MDMCFG1 0x22 // Modem Configuration +#define CC1101_DEFVAL_MDMCFG0 0xF8 // Modem Configuration +#define CC1101_DEFVAL_DEVIATN 0x00 // Modem Deviation Setting +#define CC1101_DEFVAL_MCSM2 0x07 // Main Radio Control State Machine Configuration +//#define CC1101_DEFVAL_MCSM1 0x30 // Main Radio Control State Machine Configuration +#define CC1101_DEFVAL_MCSM1 0x30 // Main Radio Control State Machine Configuration +#define CC1101_DEFVAL_MCSM0 0x18 // Main Radio Control State Machine Configuration +#define CC1101_DEFVAL_FOCCFG 0x14 // Frequency Offset Compensation Configuration +#define CC1101_DEFVAL_BSCFG 0x6C // Bit Synchronization Configuration +#define CC1101_DEFVAL_AGCCTRL2 0x04 // AGC Control +#define CC1101_DEFVAL_AGCCTRL1 0x00 // AGC Control +#define CC1101_DEFVAL_AGCCTRL0 0x92 // AGC Control +#define CC1101_DEFVAL_WOREVT1 0x87 // High Byte Event0 Timeout +#define CC1101_DEFVAL_WOREVT0 0x6B // Low Byte Event0 Timeout +#define CC1101_DEFVAL_WORCTRL 0xF8 // Wake On Radio Control +#define CC1101_DEFVAL_FREND1 0xB6 // Front End RX Configuration +#define CC1101_DEFVAL_FREND0 0x11 // Front End TX Configuration +#define CC1101_DEFVAL_FSCAL3 0xE9 // Frequency Synthesizer Calibration +#define CC1101_DEFVAL_FSCAL2 0x2A // Frequency Synthesizer Calibration +#define CC1101_DEFVAL_FSCAL1 0x00 // Frequency Synthesizer Calibration +#define CC1101_DEFVAL_FSCAL0 0x1F // Frequency Synthesizer Calibration +#define CC1101_DEFVAL_RCCTRL1 0x41 // RC Oscillator Configuration +#define CC1101_DEFVAL_RCCTRL0 0x00 // RC Oscillator Configuration +#define CC1101_DEFVAL_FSTEST 0x59 // Frequency Synthesizer Calibration Control +#define CC1101_DEFVAL_PTEST 0x7F // Production Test +#define CC1101_DEFVAL_AGCTEST 0x3F // AGC Test +#define CC1101_DEFVAL_TEST2 0x81 // Various Test Settings +#define CC1101_DEFVAL_TEST1 0x35 // Various Test Settings +#define CC1101_DEFVAL_TEST0 0x09 // Various Test Settings + +/** + * Alias for some default values + */ +#define CCDEF_CHANNR CC1101_DEFVAL_CHANNR +#define CCDEF_SYNC0 CC1101_DEFVAL_SYNC0 +#define CCDEF_SYNC1 CC1101_DEFVAL_SYNC1 +#define CCDEF_ADDR CC1101_DEFVAL_ADDR + +/** + * Macros + */ +// Read CC1101 Config register +#define readConfigReg(regAddr) readReg(regAddr, CC1101_CONFIG_REGISTER) +// Read CC1101 Status register +#define readStatusReg(regAddr) readReg(regAddr, CC1101_STATUS_REGISTER) +// Enter Rx state +//#define setRxState() cmdStrobe(CC1101_SRX) +// Enter Tx state +//#define setTxState() cmdStrobe(CC1101_STX) +// Enter IDLE state +#define setIdleState() cmdStrobe(CC1101_SIDLE) +// Flush Rx FIFO +#define flushRxFifo() cmdStrobe(CC1101_SFRX) +// Flush Tx FIFO +#define flushTxFifo() cmdStrobe(CC1101_SFTX) +// Disable address check +#define disableAddressCheck() writeReg(CC1101_PKTCTRL1, 0x04) +// Enable address check +#define enableAddressCheck() writeReg(CC1101_PKTCTRL1, 0x06) +// Disable CCA +#define disableCCA() writeReg(CC1101_MCSM1, 0) +// Enable CCA +#define enableCCA() writeReg(CC1101_MCSM1, CC1101_DEFVAL_MCSM1) +// Set PATABLE single byte +#define setTxPowerAmp(setting) paTableByte = setting +// PATABLE values +#define PA_LowPower 0x60 +#define PA_LongDistance 0xC0 + +/** + * Class: CC1101 + * + * Description: + * CC1101 interface + */ +class CC1101 +{ + private: + /** + * Atmega's SPI interface + */ + SPIClass spi; + + /** + * writeBurstReg + * + * Write multiple registers into the CC1101 IC via SPI + * + * 'regAddr' Register address + * 'buffer' Data to be writen + * 'len' Data length + */ + void writeBurstReg(uint8_t regAddr, uint8_t* buffer, uint8_t len); + + /** + * readBurstReg + * + * Read burst data from CC1101 via SPI + * + * 'buffer' Buffer where to copy the result to + * 'regAddr' Register address + * 'len' Data length + */ + void readBurstReg(uint8_t * buffer, uint8_t regAddr, uint8_t len); + + /** + * setRegsFromEeprom + * + * Set registers from EEPROM + */ + void setRegsFromEeprom(void); + + public: + /* + * RF state + */ + uint8_t rfState; + + /** + * Tx Power byte (single PATABLE config) + */ + uint8_t paTableByte; + + /** + * Carrier frequency + */ + uint8_t carrierFreq; + + /** + * Frequency channel + */ + uint8_t channel; + + /** + * Synchronization word + */ + uint8_t syncWord[2]; + + /** + * Device address + */ + uint8_t devAddress; + + /** + * CC1101 + * + * Class constructor + */ + CC1101(void); + + /** + * cmdStrobe + * + * Send command strobe to the CC1101 IC via SPI + * + * 'cmd' Command strobe + */ + void cmdStrobe(uint8_t cmd); + + /** + * wakeUp + * + * Wake up CC1101 from Power Down state + */ + void wakeUp(void); + + /** + * readReg + * + * Read CC1101 register via SPI + * + * 'regAddr' Register address + * 'regType' Type of register: CC1101_CONFIG_REGISTER or CC1101_STATUS_REGISTER + * + * Return: + * Data byte returned by the CC1101 IC + */ + uint8_t readReg(uint8_t regAddr, uint8_t regType); + + /** + * writeReg + * + * Write single register into the CC1101 IC via SPI + * + * 'regAddr' Register address + * 'value' Value to be writen + */ + void writeReg(uint8_t regAddr, uint8_t value); + + /** + * setCCregs + * + * Configure CC1101 registers + */ + void setCCregs(void); + + /** + * reset + * + * Reset CC1101 + */ + void reset(void); + + /** + * init + * + * Initialize CC1101 radio + * + * @param freq Carrier frequency + */ + void init(uint8_t freq=CFREQ_868); + + /** + * setSyncWord + * + * Set synchronization word + * + * 'syncH' Synchronization word - High byte + * 'syncL' Synchronization word - Low byte + */ + void setSyncWord(uint8_t syncH, uint8_t syncL); + + /** + * setSyncWord (overriding method) + * + * Set synchronization word + * + * 'syncH' Synchronization word - pointer to 2-byte array + */ + void setSyncWord(uint8_t *sync); + + /** + * setDevAddress + * + * Set device address + * + * 'addr' Device address + */ + void setDevAddress(uint8_t addr); + + /** + * setCarrierFreq + * + * Set carrier frequency + * + * 'freq' New carrier frequency + */ + void setCarrierFreq(uint8_t freq); + + /** + * setChannel + * + * Set frequency channel + * + * 'chnl' Frequency channel + */ + void setChannel(uint8_t chnl); + + /** + * setPowerDownState + * + * Put CC1101 into power-down state + */ + void setPowerDownState(); + + /** + * sendData + * + * Send data packet via RF + * + * 'packet' Packet to be transmitted. First byte is the destination address + * + * Return: + * True if the transmission succeeds + * False otherwise + */ + bool sendData(CCPACKET packet); + + /** + * receiveData + * + * Read data packet from RX FIFO + * + * Return: + * Amount of bytes received + */ + uint8_t receiveData(CCPACKET *packet); + + /** + * setRxState + * + * Enter Rx state + */ + void setRxState(void); + + /** + * setTxState + * + * Enter Tx state + */ + void setTxState(void); +}; + +#endif + diff --git a/lib/cc1101/ccpacket.h b/lib/cc1101/ccpacket.h new file mode 100644 index 000000000..02f131e94 --- /dev/null +++ b/lib/cc1101/ccpacket.h @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2011 panStamp + * + * This file is part of the panStamp project. + * + * panStamp is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * panStamp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with panStamp; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + * + * Author: Daniel Berenguer + * Creation date: 06/03/2013 + */ + +#ifndef _CCPACKET_H +#define _CCPACKET_H + +/** + * Buffer and data lengths + */ +#define CCPACKET_BUFFER_LEN 64 +#define CCPACKET_DATA_LEN CCPACKET_BUFFER_LEN - 3 + +/** + * Class: CCPACKET + * + * Description: + * CC1101 data packet class + */ +struct CCPACKET +{ + public: + /** + * Data length + */ + unsigned char length; + + /** + * Data buffer + */ + unsigned char data[CCPACKET_DATA_LEN]; + + /** + * CRC OK flag + */ + bool crc_ok; + + /** + * Received Strength Signal Indication + */ + unsigned char rssi; + + /** + * Link Quality Index + */ + unsigned char lqi; +}; + +#endif + diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index c2cf75fe0..fa31b37ef 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -415,6 +415,7 @@ //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug +//#define USE_KEELOQ // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/settings.h b/tasmota/settings.h index b1afca3ea..51151afd1 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -466,8 +466,12 @@ struct SYSCFG { uint8_t sps30_inuse_hours; // F02 uint8_t hotplug_scan; // F03 uint8_t reserved1; // F04 - reserved for s-hadinger + uint8_t free_f05[191]; // F05 - uint8_t free_f05[207]; // F05 + uint32_t keeloq_master_msb; // FC4 + uint32_t keeloq_master_lsb; // FC8 + uint32_t keeloq_serial; // FCD + uint32_t keeloq_count; // FD0 uint32_t bootcount_reset_time; // FD4 int adc_param4; // FD8 diff --git a/tasmota/xdrv_35_keeloq.ino b/tasmota/xdrv_35_keeloq.ino new file mode 100644 index 000000000..c360fdb8e --- /dev/null +++ b/tasmota/xdrv_35_keeloq.ino @@ -0,0 +1,275 @@ +/* + xdrv_35 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_KEELOQ + +#define XDRV_35 35 + +#include "cc1101.h" +#include + +#define SYNC_WORD 199 + +#define Lowpulse 400 +#define Highpulse 800 + +#define TX_PORT 4 // Outputport for transmission +#define RX_PORT 5 // Inputport for reception + +const char kJaroliftCommands[] PROGMEM = "Keeloq|" // prefix + "SendRaw|SendButton|Set"; + +void (* const jaroliftCommand[])(void) PROGMEM = { + &CmndSendRaw, &CmdSendButton, &CmdSet}; + +CC1101 cc1101; + +struct JAROLIFT_DEVICE { + int device_key_msb = 0x0; // stores cryptkey MSB + int device_key_lsb = 0x0; // stores cryptkey LSB + uint64_t button = 0x0; // 1000=0x8 up, 0100=0x4 stop, 0010=0x2 down, 0001=0x1 learning + int disc = 0x0100; // 0x0100 for single channel remote + uint32_t enc = 0x0; // stores the 32Bit encrypted code + uint64_t pack = 0; // Contains data to send. + int count = 0; + uint32_t serial = 0x0; +} jaroliftDevice; + +void CmdSet(void) +{ + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("set called, check for params master key high, low, serial, counter..")); + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload > 0) { + char *p; + uint32_t i = 0; + uint32_t param[4] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 4; str = strtok_r(nullptr, ", ", &p)) { + param[i] = strtoul(str, nullptr, 0); + i++; + } + for (uint32_t i = 0; i < 3; i++) { + if (param[i] < 1) { param[i] = 1; } // msb, lsb, serial, counter + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("params: %08x %08x %08x %08x"), param[0], param[1], param[2], param[3]); + Settings.keeloq_master_msb = param[0]; + Settings.keeloq_master_lsb = param[1]; + Settings.keeloq_serial = param[2]; + Settings.keeloq_count = param[3]; + + jaroliftDevice.serial = param[2]; + jaroliftDevice.count = param[3]; + + GenerateDeviceCryptKey(); + ResponseCmndDone(); + } else { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("no payload")); + } + } else { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("no param")); + } +} + +void GenerateDeviceCryptKey() +{ + Keeloq k(Settings.keeloq_master_msb, Settings.keeloq_master_lsb); + jaroliftDevice.device_key_msb = k.decrypt(jaroliftDevice.serial | 0x60000000L); + jaroliftDevice.device_key_lsb = k.decrypt(jaroliftDevice.serial | 0x20000000L); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("device keys: %08x %08x"), jaroliftDevice.device_key_msb, jaroliftDevice.device_key_lsb); +} + +void CmdSendButton(void) +{ + noInterrupts(); + entertx(); + + if (XdrvMailbox.data_len > 0) + { + if (XdrvMailbox.payload > 0) + { + jaroliftDevice.button = strtoul(XdrvMailbox.data, nullptr, 0); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("msb: %08x"), jaroliftDevice.device_key_msb); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("lsb: %08x"), jaroliftDevice.device_key_lsb); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("count: %08x"), jaroliftDevice.count); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("serial: %08x"), jaroliftDevice.serial); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("disc: %08x"), jaroliftDevice.disc); + + CreateKeeloqPacket(); + jaroliftDevice.count++; + Settings.keeloq_count = jaroliftDevice.count; + + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("sync frame")); + digitalWrite(TX_PORT, LOW); // CC1101 in TX Mode+ + delayMicroseconds(1150); + SendSyncPreamble(13); + delayMicroseconds(3500); + for(int i=72; i>0; i--) + { + SendBit(jaroliftDevice.pack & 0x0000000000000001); + jaroliftDevice.pack >>= 1; + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); + + delay(16); // delay in loop context is save for wdt + } + } + + interrupts(); + enterrx(); + + ResponseCmndDone(); +} + +void SendBit(byte bitToSend) +{ + if (bitToSend==1) + { + digitalWrite(TX_PORT, LOW); // Simple encoding of bit state 1 + delayMicroseconds(Lowpulse); + digitalWrite(TX_PORT, HIGH); + delayMicroseconds(Highpulse); + } + else + { + digitalWrite(TX_PORT, LOW); // Simple encoding of bit state 0 + delayMicroseconds(Highpulse); + digitalWrite(TX_PORT, HIGH); + delayMicroseconds(Lowpulse); + } +} + +void CmndSendRaw(void) +{ + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("cmd send called at %d"), micros()); + noInterrupts(); + entertx(); + for(int repeat = 0; repeat < 1; repeat++) + { + if (XdrvMailbox.data_len > 0) + { + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("sync frame")); + digitalWrite(TX_PORT, LOW); + delayMicroseconds(1150); + SendSyncPreamble(13); + delayMicroseconds(3500); + + for(int i=XdrvMailbox.data_len-1; i>=0; i--) + { + SendBit(XdrvMailbox.data[i] == '1'); + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); + + delay(16); // delay in loop context is save for wdt + } + interrupts(); + } + enterrx(); + ResponseCmndDone(); +} + +void enterrx() { + unsigned char marcState = 0; + cc1101.setRxState(); + delay(2); + unsigned long rx_time = micros(); + while (((marcState = cc1101.readStatusReg(CC1101_MARCSTATE)) & 0x1F) != 0x0D ) + { + if (micros() - rx_time > 50000) break; // Quit when marcState does not change... + } +} // void enterrx + +//#################################################################### +// put CC1101 to send mode +//#################################################################### +void entertx() { + unsigned char marcState = 0; + cc1101.setTxState(); + delay(2); + unsigned long rx_time = micros(); + while (((marcState = cc1101.readStatusReg(CC1101_MARCSTATE)) & 0x1F) != 0x13 && 0x14 && 0x15) + { + if (micros() - rx_time > 50000) break; // Quit when marcState does not change... + } +} // void entertx + +void SendSyncPreamble(int l) +{ + for (int i = 0; i < l; ++i) + { + digitalWrite(TX_PORT, LOW); + delayMicroseconds(400); + digitalWrite(TX_PORT, HIGH); + delayMicroseconds(380); + } +} + +void CreateKeeloqPacket() +{ + Keeloq k(jaroliftDevice.device_key_msb, jaroliftDevice.device_key_lsb); + unsigned int result = (jaroliftDevice.disc << 16) | jaroliftDevice.count; + jaroliftDevice.pack = (uint64_t)0; + jaroliftDevice.pack |= jaroliftDevice.serial & 0xfffffffL; + jaroliftDevice.pack |= (jaroliftDevice.button & 0xfL) << 28; + jaroliftDevice.pack <<= 32; + + jaroliftDevice.enc = k.encrypt(result); + jaroliftDevice.pack |= jaroliftDevice.enc; + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("pack high: %08x"), jaroliftDevice.pack>>32); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("pack low: %08x"), jaroliftDevice.pack); +} + +void InitKeeloq() +{ + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("cc1101.init()")); + delay(100); + cc1101.init(); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("CC1101 done.")); + cc1101.setSyncWord(SYNC_WORD, false); + cc1101.setCarrierFreq(CFREQ_433); + cc1101.disableAddressCheck(); + + pinMode(TX_PORT, OUTPUT); + pinMode(RX_PORT, INPUT_PULLUP); + + jaroliftDevice.serial = Settings.keeloq_serial; + jaroliftDevice.count = Settings.keeloq_count; + GenerateDeviceCryptKey(); +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ +bool Xdrv35(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_INIT: + InitKeeloq(); + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("init done.")); + break; + case FUNC_COMMAND: + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("calling command")); + result = DecodeCommand(kJaroliftCommands, jaroliftCommand); + break; + } + + return result; +} + +#endif // USE_KEELOQ From a550fe3ac765a2761e153308a7df21865fc4c425 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 16:34:45 -0600 Subject: [PATCH 471/559] Use newly allocated settings and flag --- Device_Groups.md | 8 +- tasmota/settings.h | 11 +-- tasmota/support_command.ino | 2 +- tasmota/support_device_groups.ino | 129 +++++++++++++++--------------- tasmota/support_udp.ino | 2 +- tasmota/support_wifi.ino | 2 +- tasmota/tasmota.ino | 3 - tasmota/tasmota_post.h | 4 + tasmota/xdrv_01_webserver.ino | 2 +- 9 files changed, 81 insertions(+), 82 deletions(-) diff --git a/Device_Groups.md b/Device_Groups.md index c5990136f..3384132b4 100644 --- a/Device_Groups.md +++ b/Device_Groups.md @@ -2,7 +2,7 @@ The device groups module provides a framework to allow multiple devices to be in a group with values such as power, light color/temperature/brightness, PWM values, sensor values, etc. shared with other devices in the group. For example, with multiple light modules in a device group, the light settings can be changed on one module and the settings will automatically be changed on the other light modules. Dimmer switch modules could be in a device group with light modules and the dimmer switch could control the power, brightness and colors of all the lights in the group. Multiple dimmer switches could be in a device group to form a 3-way/4-way dimmer switch. -UDP broadcasts, followed by UDP unicasts if necessary, are used to send updates to all devices so updates are fast. There is no need for an MQTT server but all the devices in a group must be on the same IP network. +UDP multicasts, followed by UDP unicasts if necessary, are used to send updates to all devices so updates are fast. There is no need for an MQTT server but all the devices in a group must be on the same IP network. To include device groups support in the build, define USE_DEVICE_GROUPS in your user_config_override. This adds 3.5K to the code size. All devices in a group must be running firmware with device group support and have device groups enabled. @@ -13,7 +13,7 @@ To enable device groups, set Option16 to 1 and **restart the device**. The device group name is the MQTT group topic set with the GroupTopic command. All devices in the same IP network with the same group topic are in the same group. Some modules may define additional device groups. For example, if Remote Device Mode is enabled, the PWM Dimmer module defines three devices groups. -The items that are sent to the group and the items that are received from the group are selected with the DevGroupShare command. By default all items are sent and received from the group. An example of when the DevGroupShare command would be used is when you have a group of lights that you control with a dimmer switch and home automation software. You want the dimmer switch to be able to control all items. The home automation software controls each light individually. When it controls the whole group, it actually sends command to each light in the group. If you use the home automation software to turn an individual light on or off or change it’s brightness, color or scheme, you do not want the change to be replicated to the other lights. In this case, you would set the incoming and outgoing item masks to 255 on the dimmer switch (DevGroupShare 255,255) and set the incoming item mask to 255 and outgoing item mask to 0 on all the lights (DevGroupShare 255,0). +The items that are sent to the group and the items that are received from the group are selected with the DevGroupShare command. By default all items are sent and received from the group. An example of when the DevGroupShare command would be used is when you have a group of lights that you control with a dimmer switch and home automation software. You want the dimmer switch to be able to control all items. The home automation software controls each light individually. When it controls the whole group, it actually sends command to each light in the group. If you use the home automation software to turn an individual light on or off or change it’s brightness, color or scheme, you do not want the change to be replicated to the other lights. In this case, you would set the incoming and outgoing item masks to 0xffffffff (all items) on the dimmer switch (DevGroupShare 0xffffffff,0xffffffff) and set the incoming item mask to 0xffffffff and outgoing item mask to 0 on all the lights (DevGroupShare 0xffffffff,0). ### Commands @@ -29,7 +29,7 @@ The items that are sent to the group and the items that are received from the gr DevGroupShare - ,<out> = set incoming and outgoing shared item mask (default = 255,255) + ,<out> = set incoming and outgoing shared item mask (default = 0xffffffff,0xffffffff)

1 = Power, 2 = Light brightness, 4 = Light fade/speed, 8 = Light scheme, 16 = Light color, 32 = Minimum brightness @@ -42,4 +42,4 @@ The items that are sent to the group and the items that are received from the gr = set device group <x> MQTT group topic (32 chars max) and restart - + \ No newline at end of file diff --git a/tasmota/settings.h b/tasmota/settings.h index 972af6974..514cf7bdd 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -104,7 +104,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t alexa_ct_range : 1; // bit 0 (v8.1.0.2) - SetOption82 - Reduced CT range for Alexa uint32_t zigbee_use_names : 1; // bit 1 (v8.1.0.4) - SetOption83 - Use FriendlyNames instead of ShortAddresses when possible uint32_t awsiot_shadow : 1; // bit 2 (v8.1.0.5) - SetOption84 - (AWS IoT) publish MQTT state to a device shadow - uint32_t spare03 : 1; + uint32_t device_groups_enabled : 1; // bit 3 (v8.1.0.10) - SetOption85 - Enable device groups uint32_t spare04 : 1; uint32_t spare05 : 1; uint32_t spare06 : 1; @@ -467,8 +467,10 @@ struct SYSCFG { uint8_t hotplug_scan; // F03 uint8_t reserved1; // F04 - reserved for s-hadinger - uint8_t free_f05[207]; // F05 + uint8_t free_f05[199]; // F05 + uint32_t device_group_share_in; // FCC - Bitmask of device group items imported + uint32_t device_group_share_out; // FD0 - Bitmask of device group items exported uint32_t bootcount_reset_time; // FD4 int adc_param4; // FD8 uint32_t shutter_button[MAX_KEYS]; // FDC @@ -573,9 +575,4 @@ typedef union { ADC_MODE(ADC_VCC); // Set ADC input for Power Supply Voltage usage #endif -// Settings re-purposed for device groups -#define device_groups_enabled ws_clock_reverse // SetOption16 - Enable device groups -#define device_group_share_in domoticz_sensor_idx[0] // Bitmask of device group items imported -#define device_group_share_out domoticz_sensor_idx[1] // Bitmask of device group items exported - #endif // _SETTINGS_H_ diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 772e22eeb..59d6b11d5 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1677,7 +1677,7 @@ void CmndDevGroupShare(void) ParseParameters(2, parm); Settings.device_group_share_in = parm[0]; Settings.device_group_share_out = parm[1]; - Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":%d,\"Out\":%d}}"), Settings.device_group_share_in, Settings.device_group_share_out); + Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":%x,\"Out\":%x}}"), Settings.device_group_share_in, Settings.device_group_share_out); } #endif // USE_DEVICE_GROUPS diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index 336b13cad..63775d0c3 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -49,7 +49,7 @@ struct device_group { struct device_group * device_groups; uint16_t outgoing_sequence = 0; -bool initialized = false; +bool device_groups_active = false; bool building_status_message = false; bool processing_remote_device_message = false; bool waiting_for_acks; @@ -60,36 +60,33 @@ void DeviceGroupsInit(void) /* Initialize the device information for each device group. The group name is the MQTT group topic. */ - if (Settings.flag.device_groups_enabled) { - device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); - if (device_groups == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, "DGR: error allocating %u-element device group array", device_group_count); - Settings.flag.device_groups_enabled = false; - return; - } - - for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { - struct device_group * device_group = &device_groups[device_group_index]; - strcpy(device_group->group_name, SettingsText((device_group_index == 0 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + device_group_index - 1))); - device_group->message_header_length = sprintf(device_group->message, "%s%s HTTP/1.1\n\n", kDeviceGroupMessage, device_group->group_name); - device_group->last_full_status_sequence = -1; - } - - device_groups[0].local = true; - - // If both in and out shared items masks are 0, assume they're unitialized and initialize them. - if (!Settings.device_group_share_in && !Settings.device_group_share_out) { - Settings.device_group_share_in = Settings.device_group_share_out = 0xff; - } - - initialized = true; + device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); + if (device_groups == nullptr) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count); + return; } + + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { + struct device_group * device_group = &device_groups[device_group_index]; + strcpy(device_group->group_name, SettingsText((device_group_index == 0 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + device_group_index - 1))); + device_group->message_header_length = sprintf_P(device_group->message, PSTR("%s%s HTTP/1.1\n\n"), kDeviceGroupMessage, device_group->group_name); + device_group->last_full_status_sequence = -1; + } + + device_groups[0].local = true; + + // If both in and out shared items masks are 0, assume they're unitialized and initialize them. + if (!Settings.device_group_share_in && !Settings.device_group_share_out) { + Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff; + } + + device_groups_active = true; } char * IPAddressToString(const IPAddress& ip_address) { static char buffer[16]; - sprintf(buffer, "%u.%u.%u.%u", ip_address[0], ip_address[1], ip_address[2], ip_address[3]); + sprintf_P(buffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]); return buffer; } @@ -131,13 +128,13 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la } delay(10); } - AddLog_P2(LOG_LEVEL_ERROR, "DGR: error sending %s packet", label); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error sending %s packet"), label); } void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...) { - // If device groups are not enabled, ignore this request. - if (!Settings.flag.device_groups_enabled) return; + // If device groups are not active, ignore this request. + if (!device_groups_active) return; // If UDP is not set up, ignore this request. if (!udp_connected) return; @@ -152,7 +149,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType if (device_group->initial_status_requests_remaining) return; // A full status request is a request from a remote device for the status of every item we - // control. As long as we're building it, we may as well broadcast the status update to all + // control. As long as we're building it, we may as well multicast the status update to all // device group members. char * message_ptr = &device_group->message[device_group->message_header_length]; if (message_type == DGR_MSGTYP_FULL_STATUS) { @@ -164,7 +161,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType // Call the drivers to build the status update. if (!++outgoing_sequence) outgoing_sequence = 1; #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "Building device group %s full status packet", device_group->group_name); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s full status packet"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG device_group->message_length = 0; _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); @@ -191,7 +188,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType va_list ap; #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "Building device group %s packet", device_group->group_name); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s packet"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG uint16_t original_sequence = outgoing_sequence; if (!building_status_message && message_type != DGR_MSGTYP_PARTIAL_UPDATE && !++outgoing_sequence) outgoing_sequence = 1; @@ -204,7 +201,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType else if (message_type == DGR_MSGTYP_UPDATE_DIRECT) value |= DGR_FLAG_DIRECT; #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, ">sequence=%u, flags=%u", outgoing_sequence, value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">sequence=%u, flags=%u"), outgoing_sequence, value); #endif // DEVICE_GROUPS_DEBUG *message_ptr++ = value & 0xff; *message_ptr++ = value >> 8; @@ -303,7 +300,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType } } #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "%u items carried over from previous update", kept_item_count); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count); #endif // DEVICE_GROUPS_DEBUG } @@ -316,7 +313,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType value = va_arg(ap, int); if (shared) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%u", item, value); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u"), item, value); #endif // DEVICE_GROUPS_DEBUG *message_ptr++ = value & 0xff; if (item > DGR_ITEM_MAX_8BIT) { @@ -335,7 +332,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType if (shared) { value = strlen((const char *)value_ptr); #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%s", item, value_ptr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%s"), item, value_ptr); #endif // DEVICE_GROUPS_DEBUG *message_ptr++ = value; memcpy(message_ptr, value_ptr, value); @@ -348,7 +345,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType value_ptr = va_arg(ap, uint8_t *); if (shared) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, ">item=%u, value=%u,%u,%u,%u,%u", item, *value_ptr, *(value_ptr + 1), *(value_ptr + 2), *(value_ptr + 3), *(value_ptr + 4)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u,%u,%u,%u,%u"), item, *value_ptr, *(value_ptr + 1), *(value_ptr + 2), *(value_ptr + 3), *(value_ptr + 4)); #endif // DEVICE_GROUPS_DEBUG memmove(message_ptr, value_ptr, 5); message_ptr += 5; @@ -374,11 +371,11 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType if (building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE) return; } - // Broadcast the packet. + // Multicast the packet. #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DGR: sending %u-byte device group %s packet via broadcast, sequence=%u", device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); #endif // DEVICE_GROUPS_DEBUG - SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, "Broadcast"); + SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, PSTR("Multicast")); device_group->next_ack_check_time = millis() + 100; if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) { @@ -393,6 +390,9 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType void ProcessDeviceGroupMessage(char * packet, int packet_length) { + // If device groups are not active, ignore this request. + if (!device_groups_active) return; + // Make the group name a null-terminated string. char * message_group_name = packet + sizeof(DEVICE_GROUP_MESSAGE) - 1; char * message_ptr = strchr(message_group_name, ' '); @@ -418,11 +418,11 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) if (!device_group_member) { device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member)); if (device_group_member == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, "DGR: error allocating device group member block"); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating device group member block")); return; } #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DGR: adding member %s (%p)", IPAddressToString(remote_ip), device_group_member); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: adding member %s (%p)"), IPAddressToString(remote_ip), device_group_member); #endif // DEVICE_GROUPS_DEBUG device_group_member->ip_address = remote_ip; *flink = device_group_member; @@ -435,7 +435,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) } // Find the start of the actual message (after the http header). - message_ptr = strstr(message_ptr, "\n\n"); + message_ptr = strstr_P(message_ptr, PSTR("\n\n")); if (message_ptr == nullptr) return; message_ptr += 2; @@ -452,7 +452,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) flags = *message_ptr++; flags |= *message_ptr++ << 8; #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "Received device group %s packet from %s: sequence=%u, flags=%u", device_group->group_name, IPAddressToString(remote_ip), message_sequence, flags); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Received device group %s packet from %s: sequence=%u, flags=%u"), device_group->group_name, IPAddressToString(remote_ip), message_sequence, flags); #endif // DEVICE_GROUPS_DEBUG // If this is an ack message, save the message sequence if it's newwer than the last ack we @@ -463,7 +463,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) } device_group_member->timeout_time = 0; #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "received_sequence && device_group_member->received_sequence - message_sequence > 64536) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "group_name, IPAddressToString(remote_ip)); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip)); } #endif // DEVICE_GROUPS_DEBUG @@ -555,7 +555,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) light_fade = value; } #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "= packet_length - (message_ptr - packet)) goto badmsg; // Malformed message #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "next_ack_check_time <= now) { if (device_group->initial_status_requests_remaining) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DGR: sending initial status request for group %s", device_group->group_name); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending initial status request for group %s"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG if (--device_group->initial_status_requests_remaining) { - SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, "Initial"); + SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, PSTR("Initial")); device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; // The reset flag is on only for the first packet - turn it off now device_group->next_ack_check_time = now + 200; waiting_for_acks = true; @@ -671,16 +672,16 @@ void DeviceGroupsLoop(void) if (device_group_member->timeout_time && device_group_member->timeout_time < now) { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DGR: removing member %s (%p)", IPAddressToString(device_group_member->ip_address), device_group_member); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: removing member %s (%p)"), IPAddressToString(device_group_member->ip_address), device_group_member); #endif // DEVICE_GROUPS_DEBUG *flink = device_group_member->flink; free(device_group_member); } else { #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, "DGR: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u", device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u"), device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); #endif // DEVICE_GROUPS_DEBUG - SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, "Unicast"); + SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, PSTR("Unicast")); if (!device_group_member->timeout_time) device_group_member->timeout_time = now + 15000; acked = false; flink = &device_group_member->flink; diff --git a/tasmota/support_udp.ino b/tasmota/support_udp.ino index 6f1d12c2e..9ff745364 100644 --- a/tasmota/support_udp.ino +++ b/tasmota/support_udp.ino @@ -137,7 +137,7 @@ void PollUdp(void) } #ifdef USE_DEVICE_GROUPS - if (Settings.flag.device_groups_enabled && !strncmp_P(packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) { + if (Settings.flag4.device_groups_enabled && !strncmp_P(packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) { ProcessDeviceGroupMessage(packet_buffer, len); } #endif // USE_DEVICE_GROUPS diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 6d902e2a9..dd8d2441c 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -560,7 +560,7 @@ void WifiCheck(uint8_t param) } #ifdef USE_EMULATION #ifdef USE_DEVICE_GROUPS - if (Settings.flag2.emulation || Settings.flag.device_groups_enabled) { UdpConnect(); } + if (Settings.flag2.emulation || Settings.flag4.device_groups_enabled) { UdpConnect(); } #else // USE_DEVICE_GROUPS if (Settings.flag2.emulation) { UdpConnect(); } #endif // USE_DEVICE_GROUPS diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 8d17a0eb4..8e9546ed6 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -290,9 +290,6 @@ void setup(void) #ifdef USE_ARDUINO_OTA ArduinoOTAInit(); #endif // USE_ARDUINO_OTA -#ifdef USE_DEVICE_GROUPS - DeviceGroupsInit(); -#endif // USE_DEVICE_GROUPS XdrvCall(FUNC_INIT); XsnsCall(FUNC_INIT); diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 39ceb8208..e27213b5a 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -249,6 +249,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) #undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common) #undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) +#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_KNX_NO_EMULATION @@ -286,6 +287,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #undef USE_HOTPLUG // Disable support for HotPlug +#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) #undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) #undef USE_PZEM004T // Disable PZEM004T energy sensor @@ -362,6 +364,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #undef USE_HOTPLUG // Disable support for HotPlug +#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) // -- Optional light modules ---------------------- //#undef USE_LIGHT // Also disable all Dimmer/Light support @@ -583,6 +586,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #undef USE_HOTPLUG // Disable support for HotPlug +#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) // -- Optional light modules ---------------------- #undef USE_LIGHT // Disable support for lights diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 3eaa24ef5..e8c728024 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2971,7 +2971,7 @@ bool Xdrv01(uint8_t function) PollDnsWebserver(); #ifdef USE_EMULATION #ifdef USE_DEVICE_GROUPS - if (Settings.flag2.emulation || Settings.flag.device_groups_enabled) { PollUdp(); } + if (Settings.flag2.emulation || Settings.flag4.device_groups_enabled) { PollUdp(); } #else // USE_DEVICE_GROUPS if (Settings.flag2.emulation) { PollUdp(); } #endif // USE_DEVICE_GROUPS From 9c5e5b689ee6560a457f8fed53316f99b5d41be3 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 18:40:44 -0600 Subject: [PATCH 472/559] Improve dgr initialization failure handling --- tasmota/support_device_groups.ino | 35 ++++++++++++++----------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index 63775d0c3..7036169e8 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -22,7 +22,7 @@ */ #ifdef USE_DEVICE_GROUPS -//#define DEVICE_GROUPS_DEBUG +#define DEVICE_GROUPS_DEBUG extern bool udp_connected; @@ -49,7 +49,8 @@ struct device_group { struct device_group * device_groups; uint16_t outgoing_sequence = 0; -bool device_groups_active = false; +bool device_groups_initialized = false; +bool device_groups_initialization_failed = false; bool building_status_message = false; bool processing_remote_device_message = false; bool waiting_for_acks; @@ -57,12 +58,11 @@ bool udp_was_connected = false; void DeviceGroupsInit(void) { - /* - Initialize the device information for each device group. The group name is the MQTT group topic. - */ + // Initialize the device information for each device group. The group name is the MQTT group topic. device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); if (device_groups == nullptr) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count); + device_groups_initialization_failed = true; return; } @@ -80,7 +80,7 @@ void DeviceGroupsInit(void) Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff; } - device_groups_active = true; + device_groups_initialized = true; } char * IPAddressToString(const IPAddress& ip_address) @@ -133,8 +133,8 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...) { - // If device groups are not active, ignore this request. - if (!device_groups_active) return; + // If device groups are not enabled, ignore this request. + if (!Settings.flag4.device_groups_enabled) return; // If UDP is not set up, ignore this request. if (!udp_connected) return; @@ -164,7 +164,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s full status packet"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG device_group->message_length = 0; - _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); + SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); XdrvMailbox.command_code = DGR_ITEM_STATUS; XdrvCall(FUNC_DEVICE_GROUP_REQUEST); building_status_message = false; @@ -300,7 +300,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType } } #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count); #endif // DEVICE_GROUPS_DEBUG } @@ -390,9 +390,6 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType void ProcessDeviceGroupMessage(char * packet, int packet_length) { - // If device groups are not active, ignore this request. - if (!device_groups_active) return; - // Make the group name a null-terminated string. char * message_group_name = packet + sizeof(DEVICE_GROUP_MESSAGE) - 1; char * message_ptr = strchr(message_group_name, ' '); @@ -617,14 +614,12 @@ void DeviceGroupsLoop(void) { if (!Settings.flag4.device_groups_enabled) return; if (udp_connected) { - if (!device_groups_active) { - DeviceGroupsInit(); - if (!device_groups_active) return; - } - if (!udp_was_connected) { udp_was_connected = true; + if (!device_groups_initialized) DeviceGroupsInit(); + if (device_groups_initialization_failed) return; + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { device_group * device_group = &device_groups[device_group_index]; char * message_ptr = &device_group->message[device_group->message_header_length]; @@ -635,12 +630,14 @@ void DeviceGroupsLoop(void) *message_ptr++ = 0; device_group->message_length = message_ptr - device_group->message; device_group->initial_status_requests_remaining = 5; - device_group->next_ack_check_time = millis() + 2000; + device_group->next_ack_check_time = millis() + 1000; } waiting_for_acks = true; } + if (device_groups_initialization_failed) return; + if (waiting_for_acks) { uint32_t now = millis(); waiting_for_acks = false; From e1103b248fe09e1f3b44f2ca50797c0e5b6dd53a Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 19:07:46 -0600 Subject: [PATCH 473/559] Improve dgr initialization failure handling --- tasmota/my_user_config.h | 2 +- tasmota/support_device_groups.ino | 33 +- tasmota/tasmota.ino.cpp | 78659 ++++++++++++++++++++++++++++ 3 files changed, 78675 insertions(+), 19 deletions(-) create mode 100644 tasmota/tasmota.ino.cpp diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 931996bf4..836fbeb10 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -415,7 +415,7 @@ //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug -// #define USE_DEVICE_GROUPS // Add support for device groups (+4k code) +#define USE_DEVICE_GROUPS // Add support for device groups (+4k code) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index 63775d0c3..c94ea2f57 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -49,7 +49,8 @@ struct device_group { struct device_group * device_groups; uint16_t outgoing_sequence = 0; -bool device_groups_active = false; +bool device_groups_initialized = false; +bool device_groups_initialization_failed = false; bool building_status_message = false; bool processing_remote_device_message = false; bool waiting_for_acks; @@ -57,12 +58,11 @@ bool udp_was_connected = false; void DeviceGroupsInit(void) { - /* - Initialize the device information for each device group. The group name is the MQTT group topic. - */ + // Initialize the device information for each device group. The group name is the MQTT group topic. device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); if (device_groups == nullptr) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count); + device_groups_initialization_failed = true; return; } @@ -80,7 +80,7 @@ void DeviceGroupsInit(void) Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff; } - device_groups_active = true; + device_groups_initialized = true; } char * IPAddressToString(const IPAddress& ip_address) @@ -133,8 +133,8 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...) { - // If device groups are not active, ignore this request. - if (!device_groups_active) return; + // If device groups are not enabled, ignore this request. + if (!Settings.flag4.device_groups_enabled) return; // If UDP is not set up, ignore this request. if (!udp_connected) return; @@ -164,7 +164,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s full status packet"), device_group->group_name); #endif // DEVICE_GROUPS_DEBUG device_group->message_length = 0; - _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); + SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); XdrvMailbox.command_code = DGR_ITEM_STATUS; XdrvCall(FUNC_DEVICE_GROUP_REQUEST); building_status_message = false; @@ -300,7 +300,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType } } #ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count); #endif // DEVICE_GROUPS_DEBUG } @@ -390,9 +390,6 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType void ProcessDeviceGroupMessage(char * packet, int packet_length) { - // If device groups are not active, ignore this request. - if (!device_groups_active) return; - // Make the group name a null-terminated string. char * message_group_name = packet + sizeof(DEVICE_GROUP_MESSAGE) - 1; char * message_ptr = strchr(message_group_name, ' '); @@ -617,14 +614,12 @@ void DeviceGroupsLoop(void) { if (!Settings.flag4.device_groups_enabled) return; if (udp_connected) { - if (!device_groups_active) { - DeviceGroupsInit(); - if (!device_groups_active) return; - } - if (!udp_was_connected) { udp_was_connected = true; + if (!device_groups_initialized) DeviceGroupsInit(); + if (device_groups_initialization_failed) return; + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { device_group * device_group = &device_groups[device_group_index]; char * message_ptr = &device_group->message[device_group->message_header_length]; @@ -635,12 +630,14 @@ void DeviceGroupsLoop(void) *message_ptr++ = 0; device_group->message_length = message_ptr - device_group->message; device_group->initial_status_requests_remaining = 5; - device_group->next_ack_check_time = millis() + 2000; + device_group->next_ack_check_time = millis() + 1000; } waiting_for_acks = true; } + if (device_groups_initialization_failed) return; + if (waiting_for_acks) { uint32_t now = millis(); waiting_for_acks = false; diff --git a/tasmota/tasmota.ino.cpp b/tasmota/tasmota.ino.cpp new file mode 100644 index 000000000..8f8387ba2 --- /dev/null +++ b/tasmota/tasmota.ino.cpp @@ -0,0 +1,78659 @@ +# 1 "C:\\Users\\pcdie\\AppData\\Local\\Temp\\tmpnb0ml5sg" +#include +# 1 "S:/Development/Tasmota/tasmota/tasmota.ino" +# 29 "S:/Development/Tasmota/tasmota/tasmota.ino" +#include +#include "tasmota_version.h" +#include "tasmota.h" +#include "my_user_config.h" +#ifdef USE_MQTT_TLS + #include +#endif +#include "tasmota_post.h" +#include "i18n.h" +#include "tasmota_template.h" + +#ifdef ARDUINO_ESP8266_RELEASE_2_4_0 +#include "lwip/init.h" +#if LWIP_VERSION_MAJOR != 1 + #error Please use stable lwIP v1.4 +#endif +#endif + + +#include +#include +#include +#include +#ifdef USE_ARDUINO_OTA + #include + #ifndef USE_DISCOVERY + #define USE_DISCOVERY + #endif +#endif +#ifdef USE_DISCOVERY + #include +#endif +#ifdef USE_I2C + #include +#endif +#ifdef USE_SPI + #include +#endif + + +#include "settings.h" + + + + + +WiFiUDP PortUdp; + +unsigned long feature_drv1; +unsigned long feature_drv2; +unsigned long feature_sns1; +unsigned long feature_sns2; +unsigned long feature5; +unsigned long feature6; +unsigned long serial_polling_window = 0; +unsigned long state_second = 0; +unsigned long state_50msecond = 0; +unsigned long state_100msecond = 0; +unsigned long state_250msecond = 0; +unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; +unsigned long blink_timer = 0; +unsigned long backlog_delay = 0; +power_t power = 0; +power_t last_power = 0; +power_t blink_power; +power_t blink_mask = 0; +power_t blink_powersave; +power_t latching_power = 0; +power_t rel_inverted = 0; +int serial_in_byte_counter = 0; +int ota_state_flag = 0; +int ota_result = 0; +int restart_flag = 0; +int wifi_state_flag = WIFI_RESTART; +int blinks = 201; +uint32_t uptime = 0; +uint32_t loop_load_avg = 0; +uint32_t global_update = 0; +uint32_t web_log_index = 1; +float global_temperature = 9999; +float global_humidity = 0; +float global_pressure = 0; +uint16_t tele_period = 9999; +uint16_t blink_counter = 0; +uint16_t seriallog_timer = 0; +uint16_t syslog_timer = 0; +int16_t save_data_counter; +RulesBitfield rules_flag; +uint8_t mqtt_cmnd_blocked = 0; +uint8_t mqtt_cmnd_blocked_reset = 0; +uint8_t state_250mS = 0; +uint8_t latching_relay_pulse = 0; +uint8_t sleep; +uint8_t blinkspeed = 1; +uint8_t pin[GPIO_MAX]; +uint8_t active_device = 1; +uint8_t leds_present = 0; +uint8_t led_inverted = 0; +uint8_t led_power = 0; +uint8_t ledlnk_inverted = 0; +uint8_t pwm_inverted = 0; +uint8_t energy_flg = 0; +uint8_t light_flg = 0; +uint8_t light_type = 0; +uint8_t serial_in_byte; +uint8_t ota_retry_counter = OTA_ATTEMPTS; +uint8_t devices_present = 0; +uint8_t seriallog_level; +uint8_t syslog_level; +uint8_t my_module_type; +uint8_t my_adc0; +uint8_t last_source = 0; +uint8_t shutters_present = 0; +uint8_t prepped_loglevel = 0; + +bool serial_local = false; +bool fallback_topic_flag = false; +bool backlog_mutex = false; +bool interlock_mutex = false; +bool stop_flash_rotate = false; +bool blinkstate = false; + +bool pwm_present = false; +bool i2c_flg = false; +bool spi_flg = false; +bool soft_spi_flg = false; +bool ntp_force_sync = false; +bool is_8285 = false; +myio my_module; +gpio_flag my_module_flag; +StateBitfield global_state; +char my_version[33]; +char my_image[33]; +char my_hostname[33]; +char mqtt_client[TOPSZ]; +char mqtt_topic[TOPSZ]; +char serial_in_buffer[INPUT_BUFFER_SIZE]; +char mqtt_data[MESSZ]; +char log_data[LOGSZ]; +char web_log[WEB_LOG_SIZE] = {'\0'}; +#ifdef SUPPORT_IF_STATEMENT + #include + LinkedList backlog; + #define BACKLOG_EMPTY (backlog.size() == 0) +#else + uint8_t backlog_index = 0; + uint8_t backlog_pointer = 0; + String backlog[MAX_BACKLOG]; + #define BACKLOG_EMPTY (backlog_pointer == backlog_index) +#endif +void setup(void); +void BacklogLoop(void); +void loop(void); +uint16_t SendMail(char *buffer); +uint32_t GetRtcSettingsCrc(void); +void RtcSettingsSave(void); +void RtcSettingsLoad(void); +bool RtcSettingsValid(void); +uint32_t GetRtcRebootCrc(void); +void RtcRebootSave(void); +void RtcRebootReset(void); +void RtcRebootLoad(void); +bool RtcRebootValid(void); +void SetFlashModeDout(void); +bool VersionCompatible(void); +void SettingsBufferFree(void); +bool SettingsBufferAlloc(void); +uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size); +uint16_t GetSettingsCrc(void); +uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size); +uint32_t GetSettingsCrc32(void); +void SettingsSaveAll(void); +void UpdateQuickPowerCycle(bool update); +uint32_t GetSettingsTextLen(void); +bool SettingsUpdateText(uint32_t index, const char* replace_me); +char* SettingsText(uint32_t index); +uint32_t GetSettingsAddress(void); +void SettingsSave(uint8_t rotate); +void SettingsLoad(void); +void EspErase(uint32_t start_sector, uint32_t end_sector); +void SettingsErase(uint8_t type); +void SettingsSdkErase(void); +void SettingsSdkWifiErase(void); +void SettingsDefault(void); +void SettingsDefaultSet1(void); +void SettingsDefaultSet2(void); +void SettingsResetStd(void); +void SettingsResetDst(void); +void SettingsDefaultWebColor(void); +void SettingsEnableAllI2cDrivers(void); +void SettingsDelta(void); +void OsWatchTicker(void); +void OsWatchInit(void); +void OsWatchLoop(void); +bool OsWatchBlockedLoop(void); +uint32_t ResetReason(void); +String GetResetReason(void); +size_t strchrspn(const char *str1, int character); +char* subStr(char* dest, char* str, const char *delim, int index); +float CharToFloat(const char *str); +int TextToInt(char *str); +char* ulltoa(unsigned long long value, char *str, int radix); +char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween); +char* Uint64toHex(uint64_t value, char *str, uint16_t bits); +char* dtostrfd(double number, unsigned char prec, char *s); +char* Unescape(char* buffer, uint32_t* size); +char* RemoveSpace(char* p); +char* ReplaceCommaWithDot(char* p); +char* LowerCase(char* dest, const char* source); +char* UpperCase(char* dest, const char* source); +char* UpperCase_P(char* dest, const char* source); +char* Trim(char* p); +char* RemoveAllSpaces(char* p); +char* NoAlNumToUnderscore(char* dest, const char* source); +char IndexSeparator(void); +void SetShortcutDefault(void); +uint8_t Shortcut(void); +bool ValidIpAddress(const char* str); +bool ParseIp(uint32_t* addr, const char* str); +uint32_t ParseParameters(uint32_t count, uint32_t *params); +bool NewerVersion(char* version_str); +char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option); +char* GetPowerDevice(char* dest, uint32_t idx, size_t size); +void GetEspHardwareType(void); +String GetDeviceHardware(void); +float ConvertTemp(float c); +float ConvertTempToCelsius(float c); +char TempUnit(void); +float ConvertHumidity(float h); +float ConvertPressure(float p); +String PressureUnit(void); +void ResetGlobalValues(void); +uint32_t SqrtInt(uint32_t num); +uint32_t RoundSqrtInt(uint32_t num); +char* GetTextIndexed(char* destination, size_t destination_size, uint32_t index, const char* haystack); +int GetCommandCode(char* destination, size_t destination_size, const char* needle, const char* haystack); +int GetStateNumber(char *state_text); +String GetSerialConfig(void); +void SetSerialBegin(); +void SetSerialConfig(uint32_t serial_config); +void SetSerialBaudrate(uint32_t baudrate); +void SetSerial(uint32_t baudrate, uint32_t serial_config); +void ClaimSerial(void); +void SerialSendRaw(char *codes); +uint32_t GetHash(const char *buffer, size_t size); +void ShowSource(uint32_t source); +void WebHexCode(uint32_t i, const char* code); +uint32_t WebColor(uint32_t i); +char* ResponseGetTime(uint32_t format, char* time_str); +int Response_P(const char* format, ...); +int ResponseTime_P(const char* format, ...); +int ResponseAppend_P(const char* format, ...); +int ResponseAppendTimeFormat(uint32_t format); +int ResponseAppendTime(void); +int ResponseJsonEnd(void); +int ResponseJsonEndEnd(void); +void DigitalWrite(uint32_t gpio_pin, uint32_t state); +uint8_t ModuleNr(void); +bool ValidTemplateModule(uint32_t index); +bool ValidModule(uint32_t index); +String AnyModuleName(uint32_t index); +String ModuleName(void); +void ModuleGpios(myio *gp); +gpio_flag ModuleFlag(void); +void ModuleDefault(uint32_t module); +void SetModuleType(void); +bool FlashPin(uint32_t pin); +uint8_t ValidPin(uint32_t pin, uint32_t gpio); +bool ValidGPIO(uint32_t pin, uint32_t gpio); +bool ValidAdc(void); +bool GetUsedInModule(uint32_t val, uint8_t *arr); +bool JsonTemplate(const char* dataBuf); +void TemplateJson(void); +inline int32_t TimeDifference(uint32_t prev, uint32_t next); +int32_t TimePassedSince(uint32_t timestamp); +bool TimeReached(uint32_t timer); +void SetNextTimeInterval(unsigned long& timer, const unsigned long step); +int32_t TimePassedSinceUsec(uint32_t timestamp); +bool TimeReachedUsec(uint32_t timer); +bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size); +bool I2cValidRead8(uint8_t *data, uint8_t addr, uint8_t reg); +bool I2cValidRead16(uint16_t *data, uint8_t addr, uint8_t reg); +bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg); +bool I2cValidRead16LE(uint16_t *data, uint8_t addr, uint8_t reg); +bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg); +bool I2cValidRead24(int32_t *data, uint8_t addr, uint8_t reg); +uint8_t I2cRead8(uint8_t addr, uint8_t reg); +uint16_t I2cRead16(uint8_t addr, uint8_t reg); +int16_t I2cReadS16(uint8_t addr, uint8_t reg); +uint16_t I2cRead16LE(uint8_t addr, uint8_t reg); +int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg); +int32_t I2cRead24(uint8_t addr, uint8_t reg); +bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size); +bool I2cWrite8(uint8_t addr, uint8_t reg, uint16_t val); +bool I2cWrite16(uint8_t addr, uint8_t reg, uint16_t val); +int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len); +int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len); +void I2cScan(char *devs, unsigned int devs_len); +void I2cSetActiveFound(uint32_t addr, const char *types); +bool I2cActive(uint32_t addr); +bool I2cSetDevice(uint32_t addr); +void SetSeriallog(uint32_t loglevel); +void SetSyslog(uint32_t loglevel); +void GetLog(uint32_t idx, char** entry_pp, size_t* len_p); +void Syslog(void); +void AddLog(uint32_t loglevel); +void AddLog_P(uint32_t loglevel, const char *formatP); +void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2); +void PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...); +void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...); +void AddLog_Debug(PGM_P formatP, ...); +void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count); +void AddLogSerial(uint32_t loglevel); +void AddLogMissed(char *sensor, uint32_t misses); +void ButtonPullupFlag(uint8 button_bit); +void ButtonInvertFlag(uint8 button_bit); +void ButtonInit(void); +uint8_t ButtonSerial(uint8_t serial_in_byte); +void ButtonHandler(void); +void ButtonLoop(void); +void ResponseCmndNumber(int value); +void ResponseCmndFloat(float value, uint32_t decimals); +void ResponseCmndIdxNumber(int value); +void ResponseCmndChar(const char* value); +void ResponseCmndStateText(uint32_t value); +void ResponseCmndDone(void); +void ResponseCmndIdxChar(const char* value); +void ResponseCmndAll(uint32_t text_index, uint32_t count); +void ExecuteCommand(const char *cmnd, uint32_t source); +void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len); +void CmndBacklog(void); +void CmndDelay(void); +void CmndPower(void); +void CmndStatus(void); +void CmndState(void); +void CmndTempOffset(void); +void CmndSleep(void); +void CmndUpgrade(void); +void CmndOtaUrl(void); +void CmndSeriallog(void); +void CmndRestart(void); +void CmndPowerOnState(void); +void CmndPulsetime(void); +void CmndBlinktime(void); +void CmndBlinkcount(void); +void CmndSavedata(void); +void CmndSetoption(void); +void CmndTemperatureResolution(void); +void CmndHumidityResolution(void); +void CmndPressureResolution(void); +void CmndPowerResolution(void); +void CmndVoltageResolution(void); +void CmndFrequencyResolution(void); +void CmndCurrentResolution(void); +void CmndEnergyResolution(void); +void CmndWeightResolution(void); +void CmndModule(void); +void CmndModules(void); +void CmndGpio(void); +void CmndGpios(void); +void CmndTemplate(void); +void CmndPwm(void); +void CmndPwmfrequency(void); +void CmndPwmrange(void); +void CmndButtonDebounce(void); +void CmndSwitchDebounce(void); +void CmndBaudrate(void); +void CmndSerialConfig(void); +void CmndSerialSend(void); +void CmndSerialDelimiter(void); +void CmndSyslog(void); +void CmndLoghost(void); +void CmndLogport(void); +void CmndIpAddress(void); +void CmndNtpServer(void); +void CmndAp(void); +void CmndSsid(void); +void CmndPassword(void); +void CmndHostname(void); +void CmndWifiConfig(void); +void CmndFriendlyname(void); +void CmndSwitchMode(void); +void CmndInterlock(void); +void CmndTeleperiod(void); +void CmndReset(void); +void CmndTime(void); +void CmndTimezone(void); +void CmndTimeStdDst(uint32_t ts); +void CmndTimeStd(void); +void CmndTimeDst(void); +void CmndAltitude(void); +void CmndLedPower(void); +void CmndLedState(void); +void CmndLedMask(void); +void CmndWifiPower(void); +void CmndI2cScan(void); +void CmndI2cDriver(void); +void CmndDevGroupShare(void); +void CmndSensor(void); +void CmndDriver(void); +void CmndCrash(void); +void CmndWDT(void); +void CmndBlockedLoop(void); +void CrashDumpClear(void); +bool CrashFlag(void); +void CrashDump(void); +void DeviceGroupsInit(void); +bool DeviceGroupItemShared(bool incoming, uint8_t item); +void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * label); +void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...); +void ProcessDeviceGroupMessage(char * packet, int packet_length); +void DeviceGroupsLoop(void); +static bool spiflash_is_ready(void); +static void spi_write_enable(void); +bool EsptoolEraseSector(uint32_t sector); +void EsptoolErase(uint32_t start_sector, uint32_t end_sector); +void GetFeatures(void); +float fmodf(float x, float y); +double FastPrecisePow(double a, double b); +float FastPrecisePowf(const float x, const float y); +double TaylorLog(double x); +inline float sinf(float x); +inline float cosf(float x); +inline float tanf(float x); +inline float atanf(float x); +inline float asinf(float x); +inline float acosf(float x); +inline float sqrtf(float x); +inline float powf(float x, float y); +float cos_52s(float x); +float cos_52(float x); +float sin_52(float x); +float tan_56s(float x); +float tan_56(float x); +float atan_66s(float x); +float atan_66(float x); +float asinf1(float x); +float acosf1(float x); +float sqrt1(const float x); +uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, + uint16_t ito_min, uint16_t ito_max); +void* memchr(const void* ptr, int value, size_t num); +size_t strcspn(const char *str1, const char *str2); +char* strpbrk(const char *s1, const char *s2); +void* memmove_P(void *dest, const void *src, size_t n); +void update_rotary(void); +bool RotaryButtonPressed(void); +void RotaryInit(void); +void RotaryHandler(void); +void RotaryLoop(void); +uint32_t UtcTime(void); +uint32_t LocalTime(void); +uint32_t Midnight(void); +bool MidnightNow(void); +bool IsDst(void); +String GetBuildDateAndTime(void); +String GetMinuteTime(uint32_t minutes); +String GetTimeZone(void); +String GetDuration(uint32_t time); +String GetDT(uint32_t time); +String GetDateAndTime(uint8_t time_type); +uint32_t UpTime(void); +uint32_t MinutesUptime(void); +String GetUptime(void); +uint32_t MinutesPastMidnight(void); +void BreakTime(uint32_t time_input, TIME_T &tm); +uint32_t MakeTime(TIME_T &tm); +uint32_t RuleToTime(TimeRule r, int yr); +void RtcSecond(void); +void RtcSetTime(uint32_t epoch); +void RtcInit(void); +String GetStatistics(void); +String GetStatistics(void); +void SwitchPullupFlag(uint16 switch_bit); +void SwitchSetVirtual(uint32_t index, uint8_t state); +uint8_t SwitchGetVirtual(uint32_t index); +uint8_t SwitchLastState(uint32_t index); +bool SwitchState(uint32_t index); +void SwitchProbe(void); +void SwitchInit(void); +void SwitchHandler(uint8_t mode); +void SwitchLoop(void); +char* Format(char* output, const char* input, int size); +char* GetOtaUrl(char *otaurl, size_t otaurl_size); +char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic); +char* GetGroupTopic_P(char *stopic, const char* subtopic); +char* GetFallbackTopic_P(char *stopic, const char* subtopic); +char* GetStateText(uint32_t state); +void SetLatchingRelay(power_t lpower, uint32_t state); +void SetDevicePower(power_t rpower, uint32_t source); +void RestorePower(bool publish_power, uint32_t source); +void SetAllPower(uint32_t state, uint32_t source); +void SetPowerOnState(void); +void SetLedPowerIdx(uint32_t led, uint32_t state); +void SetLedPower(uint32_t state); +void SetLedPowerAll(uint32_t state); +void SetLedLink(uint32_t state); +void SetPulseTimer(uint32_t index, uint32_t time); +uint32_t GetPulseTimer(uint32_t index); +bool SendKey(uint32_t key, uint32_t device, uint32_t state); +void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source); +void StopAllPowerBlink(void); +void MqttShowPWMState(void); +void MqttShowState(void); +void MqttPublishTeleState(void); +bool MqttShowSensor(void); +void MqttPublishSensor(void); +void PerformEverySecond(void); +void Every100mSeconds(void); +void Every250mSeconds(void); +void ArduinoOTAInit(void); +void ArduinoOtaLoop(void); +void SerialInput(void); +void GpioInit(void); +bool UdpDisconnect(void); +bool UdpConnect(void); +void PollUdp(void); +int WifiGetRssiAsQuality(int rssi); +bool WifiConfigCounter(void); +void WifiConfig(uint8_t type); +void WifiSetMode(WiFiMode_t wifi_mode); +void WiFiSetSleepMode(void); +void WifiBegin(uint8_t flag, uint8_t channel); +void WifiBeginAfterScan(void); +uint16_t WifiLinkCount(void); +String WifiDowntime(void); +void WifiSetState(uint8_t state); +bool WifiCheckIPv6(void); +String WifiGetIPv6(void); +bool WifiCheckIPAddrStatus(void); +void WifiCheckIp(void); +void WifiCheck(uint8_t param); +int WifiState(void); +String WifiGetOutputPower(void); +void WifiSetOutputPower(void); +void WifiConnect(void); +void WifiDisconnect(void); +void WifiShutdown(void); +void EspRestart(void); +static void WebGetArg(const char* arg, char* out, size_t max); +static bool WifiIsInManagerMode(); +void ShowWebSource(uint32_t source); +void ExecuteWebCommand(char* svalue, uint32_t source); +void StartWebserver(int type, IPAddress ipweb); +void StopWebserver(void); +void WifiManagerBegin(bool reset_only); +void PollDnsWebserver(void); +bool WebAuthenticate(void); +void HttpHeaderCors(void); +void WSHeaderSend(void); +void WSSend(int code, int ctype, const String& content); +void WSContentBegin(int code, int ctype); +void _WSContentSend(const String& content); +void WSContentFlush(void); +void _WSContentSendBuffer(void); +void WSContentSend_P(const char* formatP, ...); +void WSContentSend_PD(const char* formatP, ...); +void WSContentStart_P(const char* title, bool auth); +void WSContentStart_P(const char* title); +void WSContentSendStyle_P(const char* formatP, ...); +void WSContentSendStyle(void); +void WSContentButton(uint32_t title_index); +void WSContentSpaceButton(uint32_t title_index); +void WSContentEnd(void); +void WSContentStop(void); +void WebRestart(uint32_t type); +void HandleWifiLogin(void); +void WebSliderColdWarm(void); +void HandleRoot(void); +bool HandleRootStatusRefresh(void); +int32_t IsShutterWebButton(uint32_t idx); +void HandleConfiguration(void); +void HandleTemplateConfiguration(void); +void TemplateSaveSettings(void); +void HandleModuleConfiguration(void); +void ModuleSaveSettings(void); +String HtmlEscape(const String unescaped); +void HandleWifiConfiguration(void); +void WifiSaveSettings(void); +void HandleLoggingConfiguration(void); +void LoggingSaveSettings(void); +void HandleOtherConfiguration(void); +void OtherSaveSettings(void); +void HandleBackupConfiguration(void); +void HandleResetConfiguration(void); +void HandleRestoreConfiguration(void); +void HandleInformation(void); +void HandleUpgradeFirmware(void); +void HandleUpgradeFirmwareStart(void); +void HandleUploadDone(void); +void HandleUploadLoop(void); +void HandlePreflightRequest(void); +void HandleHttpCommand(void); +void HandleConsole(void); +void HandleConsoleRefresh(void); +void HandleNotFound(void); +bool CaptivePortal(void); +String UrlEncode(const String& text); +int WebSend(char *buffer); +bool JsonWebColor(const char* dataBuf); +void CmndEmulation(void); +void CmndSendmail(void); +void CmndWebServer(void); +void CmndWebPassword(void); +void CmndWeblog(void); +void CmndWebRefresh(void); +void CmndWebSend(void); +void CmndWebColor(void); +void CmndWebSensor(void); +void CmndWebButton(void); +void CmndCors(void); +bool Xdrv01(uint8_t function); +bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value); +void MakeValidMqtt(uint32_t option, char* str); +void MqttDiscoverServer(void); +void MqttInit(void); +bool MqttIsConnected(void); +void MqttDisconnect(void); +void MqttSubscribeLib(const char *topic); +void MqttUnsubscribeLib(const char *topic); +bool MqttPublishLib(const char* topic, bool retained); +void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len); +void MqttRetryCounter(uint8_t value); +void MqttSubscribe(const char *topic); +void MqttUnsubscribe(const char *topic); +void MqttPublishLogging(const char *mxtime); +void MqttPublish(const char* topic, bool retained); +void MqttPublish(const char* topic); +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained); +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic); +void MqttPublishTeleSensor(void); +void MqttPublishPowerState(uint32_t device); +void MqttPublishAllPowerState(void); +void MqttPublishPowerBlinkState(uint32_t device); +uint16_t MqttConnectCount(void); +void MqttDisconnected(int state); +void MqttConnected(void); +void MqttReconnect(void); +void MqttCheck(void); +void CmndMqttFingerprint(void); +void CmndMqttUser(void); +void CmndMqttPassword(void); +void CmndMqttlog(void); +void CmndMqttHost(void); +void CmndMqttPort(void); +void CmndMqttRetry(void); +void CmndStateText(void); +void CmndMqttClient(void); +void CmndFullTopic(void); +void CmndPrefix(void); +void CmndPublish(void); +void CmndGroupTopic(void); +void CmndTopic(void); +void CmndButtonTopic(void); +void CmndSwitchTopic(void); +void CmndButtonRetain(void); +void CmndSwitchRetain(void); +void CmndPowerRetain(void); +void CmndSensorRetain(void); +inline void TlsEraseBuffer(uint8_t *buffer); +void loadTlsDir(void); +void CmndTlsKey(void); +uint32_t bswap32(uint32_t x); +void CmndTlsDump(void); +void HandleMqttConfiguration(void); +void MqttSaveSettings(void); +bool Xdrv02(uint8_t function); +bool EnergyTariff1Active(); +void EnergyUpdateToday(void); +void EnergyUpdateTotal(float value, bool kwh); +void Energy200ms(void); +void EnergySaveState(void); +bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag); +void EnergyMarginCheck(void); +void EnergyMqttShow(void); +void EnergyEverySecond(void); +void EnergyCommandCalResponse(uint32_t nvalue); +void CmndEnergyReset(void); +void CmndTariff(void); +void CmndPowerCal(void); +void CmndVoltageCal(void); +void CmndCurrentCal(void); +void CmndPowerSet(void); +void CmndVoltageSet(void); +void CmndCurrentSet(void); +void CmndFrequencySet(void); +void CmndModuleAddress(void); +void CmndPowerDelta(void); +void CmndPowerLow(void); +void CmndPowerHigh(void); +void CmndVoltageLow(void); +void CmndVoltageHigh(void); +void CmndCurrentLow(void); +void CmndCurrentHigh(void); +void CmndMaxPower(void); +void CmndMaxPowerHold(void); +void CmndMaxPowerWindow(void); +void CmndSafePower(void); +void CmndSafePowerHold(void); +void CmndSafePowerWindow(void); +void CmndMaxEnergy(void); +void CmndMaxEnergyStart(void); +void EnergySnsInit(void); +void EnergyShow(bool json); +bool Xdrv03(uint8_t function); +bool Xsns03(uint8_t function); +power_t LightPower(void); +power_t LightPowerIRAM(void); +uint8_t LightDevice(void); +static uint32_t min3(uint32_t a, uint32_t b, uint32_t c); +uint16_t change8to10(uint8_t v); +uint8_t change10to8(uint16_t v); +uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr); +uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr); +uint16_t ledGamma10_10(uint16_t v); +uint16_t ledGamma10(uint8_t v); +uint8_t ledGamma(uint8_t v); +void LightPwmOffset(uint32_t offset); +bool LightModuleInit(void); +void LightInit(void); +void LightUpdateColorMapping(void); +uint8_t LightGetDimmer(uint8_t dimmer); +void LightSetDimmer(uint8_t dimmer); +void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri); +void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); +uint8_t LightGetBri(uint8_t device); +void LightSetBri(uint8_t device, uint8_t bri); +void LightSetColorTemp(uint16_t ct); +uint16_t LightGetColorTemp(void); +void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value); +void LightPowerOn(void); +void LightState(uint8_t append); +void LightCycleColor(int8_t direction); +void LightSetPower(void); +void LightAnimate(void); +bool isChannelGammaCorrected(uint32_t channel); +uint16_t fadeGamma(uint32_t channel, uint16_t v); +uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg); +bool LightApplyFade(void); +void LightApplyPower(uint8_t new_color[LST_MAX], power_t power); +void LightSetOutputs(const uint16_t *cur_col_10); +void calcGammaMultiChannels(uint16_t cur_col_10[5]); +void calcGammaBulbs(uint16_t cur_col_10[5]); +void LightSendDeviceGroupStatus(); +void LightHandleDeviceGroupRequest(); +bool LightColorEntry(char *buffer, uint32_t buffer_length); +void CmndSupportColor(void); +void CmndColor(void); +void CmndWhite(void); +void CmndChannel(void); +void CmndHsbColor(void); +void CmndScheme(void); +void CmndWakeup(void); +void CmndColorTemperature(void); +void CmndDimmer(void); +void CmndDimmerRange(void); +void CmndLedTable(void); +void CmndRgbwwTable(void); +void CmndFade(void); +void CmndSpeed(void); +void CmndWakeupDuration(void); +void CmndUndocA(void); +bool Xdrv04(uint8_t function); +void IrSendInit(void); +void IrReceiveUpdateThreshold(void); +void IrReceiveInit(void); +void IrReceiveCheck(void); +uint32_t IrRemoteCmndIrSendJson(void); +void CmndIrSend(void); +void IrRemoteCmndResponse(uint32_t error); +bool Xdrv05(uint8_t function); +void IrSendInit(void); +uint8_t reverseBitsInByte(uint8_t b); +uint64_t reverseBitsInBytes64(uint64_t b); +void IrReceiveUpdateThreshold(void); +void IrReceiveInit(void); +String sendIRJsonState(const struct decode_results &results); +void IrReceiveCheck(void); +String listSupportedProtocols(bool hvac); +uint32_t IrRemoteCmndIrHvacJson(void); +void CmndIrHvac(void); +uint32_t IrRemoteCmndIrSendJson(void); +uint32_t IrRemoteCmndIrSendRaw(void); +void CmndIrSend(void); +void IrRemoteCmndResponse(uint32_t error); +bool Xdrv05(uint8_t function); +ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size); +ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size); +ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len); +ssize_t rf_decode_and_write(uint8_t *record, size_t size); +ssize_t rf_search_and_write(uint8_t *buf, size_t size); +uint8_t rf_erase_flash(void); +uint8_t SnfBrUpdateInit(void); +void SonoffBridgeReceivedRaw(void); +void SonoffBridgeLearnFailed(void); +void SonoffBridgeReceived(void); +bool SonoffBridgeSerialInput(void); +void SonoffBridgeSendCommand(uint8_t code); +void SonoffBridgeSendAck(void); +void SonoffBridgeSendCode(uint32_t code); +void SonoffBridgeSend(uint8_t idx, uint8_t key); +void SonoffBridgeLearn(uint8_t key); +void CmndRfBridge(void); +void CmndRfKey(void); +void CmndRfRaw(void); +bool Xdrv06(uint8_t function); +int DomoticzBatteryQuality(void); +int DomoticzRssiQuality(void); +void MqttPublishDomoticzFanState(void); +void DomoticzUpdateFanState(void); +void MqttPublishDomoticzPowerState(uint8_t device); +void DomoticzUpdatePowerState(uint8_t device); +void DomoticzMqttUpdate(void); +void DomoticzMqttSubscribe(void); +bool DomoticzMqttData(void); +bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg); +uint8_t DomoticzHumidityState(char *hum); +void DomoticzSensor(uint8_t idx, char *data); +void DomoticzSensor(uint8_t idx, uint32_t value); +void DomoticzTempHumSensor(char *temp, char *hum); +void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro); +void DomoticzSensorPowerEnergy(int power, char *energy); +void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power); +void CmndDomoticzIdx(void); +void CmndDomoticzKeyIdx(void); +void CmndDomoticzSwitchIdx(void); +void CmndDomoticzSensorIdx(void); +void CmndDomoticzUpdateTimer(void); +void HandleDomoticzConfiguration(void); +void DomoticzSaveSettings(void); +bool Xdrv07(uint8_t function); +void SerialBridgeInput(void); +void SerialBridgeInit(void); +void CmndSSerialSend(void); +void CmndSBaudrate(void); +bool Xdrv08(uint8_t function); +float JulianischesDatum(void); +float InPi(float x); +float eps(float T); +float BerechneZeitgleichung(float *DK,float T); +void DuskTillDawn(uint8_t *hour_up,uint8_t *minute_up, uint8_t *hour_down, uint8_t *minute_down); +void ApplyTimerOffsets(Timer *duskdawn); +String GetSun(uint32_t dawn); +uint16_t SunMinutes(uint32_t dawn); +void TimerSetRandomWindow(uint32_t index); +void TimerSetRandomWindows(void); +void TimerEverySecond(void); +void PrepShowTimer(uint32_t index); +void CmndTimer(void); +void CmndTimers(void); +void CmndLongitude(void); +void CmndLatitude(void); +void HandleTimerConfiguration(void); +void TimerSaveSettings(void); +bool Xdrv09(uint8_t function); +bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule); +int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr); +void RulesVarReplace(String &commands, const String &sfind, const String &replace); +bool RuleSetProcess(uint8_t rule_set, String &event_saved); +bool RulesProcessEvent(char *json_event); +bool RulesProcess(void); +void RulesInit(void); +void RulesEvery50ms(void); +void RulesEvery100ms(void); +void RulesEverySecond(void); +void RulesSaveBeforeRestart(void); +void RulesSetPower(void); +void RulesTeleperiod(void); +bool RulesMqttData(void); +void CmndSubscribe(void); +void CmndUnsubscribe(void); +bool findNextNumber(char * &pNumber, float &value); +bool findNextVariableValue(char * &pVarname, float &value); +bool findNextObjectValue(char * &pointer, float &value); +bool findNextOperator(char * &pointer, int8_t &op); +float calculateTwoValues(float v1, float v2, uint8_t op); +float evaluateExpression(const char * expression, unsigned int len); +void CmndIf(void); +bool evaluateComparisonExpression(const char *expression, int len); +bool findNextLogicOperator(char * &pointer, int8_t &op); +bool findNextLogicObjectValue(char * &pointer, bool &value); +bool evaluateLogicalExpression(const char * expression, int len); +int8_t findIfBlock(char * &pointer, int &lenWord, int8_t block_type); +void ExecuteCommandBlock(const char * commands, int len); +void ProcessIfStatement(const char* statements); +void RulesPreprocessCommand(char *pCommands); +void CmndRule(void); +void CmndRuleTimer(void); +void CmndEvent(void); +void CmndVariable(void); +void CmndMemory(void); +void CmndCalcResolution(void); +void CmndAddition(void); +void CmndSubtract(void); +void CmndMultiply(void); +void CmndScale(void); +float map_double(float x, float in_min, float in_max, float out_min, float out_max); +bool Xdrv10(uint8_t function); +void ScriptEverySecond(void); +void RulesTeleperiod(void); +int16_t Init_Scripter(void); +void ws2812_set_array(float *array ,uint8_t len); +float median_array(float *array,uint8_t len); +float Get_MFVal(uint8_t index,uint8_t bind); +void Set_MFVal(uint8_t index,uint8_t bind,float val); +float Get_MFilter(uint8_t index); +void Set_MFilter(uint8_t index, float invar); +float DoMedian5(uint8_t index, float in); +uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value); +uint16_t GetStack(void); +uint16_t GetStack(void); +void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize); +void toLog(const char *str); +void toLogN(const char *cp,uint8_t len); +void toLogEOL(const char *s1,const char *str); +void toSLog(const char *str); +int16_t Run_Scripter(const char *type, int8_t tlen, char *js); +void ScripterEvery100ms(void); +void Scripter_save_pvars(void); +void ListDir(char *path, uint8_t depth); +void Script_FileUploadConfiguration(void); +void ScriptFileUploadSuccess(void); +void script_upload(void); +uint8_t DownloadFile(char *file); +void HandleScriptTextareaConfiguration(void); +void HandleScriptConfiguration(void); +void ScriptSaveSettings(void); +void Script_HueStatus(String *response, uint16_t hue_devs); +void Script_Check_Hue(String *response); +void Script_Handle_Hue(String *path); +bool Script_SubCmd(void); +void execute_script(char *script); +bool ScriptCommand(void); +uint16_t xFAT_DATE(uint16_t year, uint8_t month, uint8_t day); +uint16_t xFAT_TIME(uint8_t hour, uint8_t minute, uint8_t second); +void dateTime(uint16_t* date, uint16_t* time); +bool ScriptMqttData(void); +String ScriptSubscribe(const char *data, int data_len); +String ScriptUnsubscribe(const char * data, int data_len); +void Script_Check_HTML_Setvars(void); +void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen); +void ScriptWebShow(void); +void ScriptJsonAppend(void); +bool Xdrv10(uint8_t function); +void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ); +void KNX_DEL_GA( uint8_t GAnum ); +void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ); +void KNX_DEL_CB( uint8_t CBnum ); +bool KNX_CONFIG_NOT_MATCH(void); +void KNXStart(void); +void KNX_INIT(void); +void KNX_CB_Action(message_t const &msg, void *arg); +void KnxUpdatePowerState(uint8_t device, power_t state); +void KnxSendButtonPower(void); +void KnxSensor(uint8_t sensor_type, float value); +void HandleKNXConfiguration(void); +void KNX_Save_Settings(void); +void CmndKnxTxCmnd(void); +void CmndKnxTxVal(void); +void CmndKnxEnabled(void); +void CmndKnxEnhanced(void); +void CmndKnxPa(void); +void CmndKnxGa(void); +void CmndKnxCb(void); +bool Xdrv11(uint8_t function); +void TryResponseAppend_P(const char *format, ...); +void HAssAnnounceRelayLight(void); +void HAssAnnounceButtonSwitch(uint8_t device, char *topic, uint8_t present, uint8_t key, uint8_t toggle); +void HAssAnnounceSwitches(void); +void HAssAnnounceButtons(void); +void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, uint8_t subidx); +void HAssAnnounceSensors(void); +void HAssAnnounceStatusSensor(void); +void HAssPublishStatus(void); +void HAssDiscovery(void); +void HAssDiscover(void); +void HAssAnyKey(void); +bool Xdrv12(uint8_t function); +void DisplayInit(uint8_t mode); +void DisplayClear(void); +void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color); +void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color); +void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); +void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color); +void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color); +void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); +void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); +void DisplayDrawFrame(void); +void DisplaySetSize(uint8_t size); +void DisplaySetFont(uint8_t font); +void DisplaySetRotation(uint8_t rotation); +void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); +void DisplayOnOff(uint8_t on); +uint8_t fatoiv(char *cp,float *res); +uint8_t atoiv(char *cp, int16_t *res); +uint8_t atoiV(char *cp, uint16_t *res); +void alignright(char *string); +uint32_t decode_te(char *line); +void DisplayText(void); +void DisplayClearScreenBuffer(void); +void DisplayFreeScreenBuffer(void); +void DisplayAllocScreenBuffer(void); +void DisplayReAllocScreenBuffer(void); +void DisplayFillScreen(uint32_t line); +void DisplayClearLogBuffer(void); +void DisplayFreeLogBuffer(void); +void DisplayAllocLogBuffer(void); +void DisplayReAllocLogBuffer(void); +void DisplayLogBufferAdd(char* txt); +char* DisplayLogBuffer(char temp_code); +void DisplayLogBufferInit(void); +void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value); +void DisplayAnalyzeJson(char *topic, char *json); +void DisplayMqttSubscribe(void); +bool DisplayMqttData(void); +void DisplayLocalSensor(void); +void DisplayInitDriver(void); +void DisplaySetPower(void); +void CmndDisplay(void); +void CmndDisplayModel(void); +void CmndDisplayWidth(void); +void CmndDisplayHeight(void); +void CmndDisplayMode(void); +void CmndDisplayDimmer(void); +void CmndDisplaySize(void); +void CmndDisplayFont(void); +void CmndDisplayRotate(void); +void CmndDisplayText(void); +void CmndDisplayAddress(void); +void CmndDisplayRefresh(void); +void CmndDisplayColumns(void); +void CmndDisplayRows(void); +void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp); +void DrawAClock(uint16_t rad); +void ClrGraph(uint16_t num); +void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol); +void DisplayCheckGraph(); +void Save_graph(uint8_t num, char *path); +void Restore_graph(uint8_t num, char *path); +void RedrawGraph(uint8_t num, uint8_t flags); +void AddGraph(uint8_t num,uint8_t val); +void AddValue(uint8_t num,float fval); +bool Xdrv13(uint8_t function); +uint16_t MP3_Checksum(uint8_t *array); +void MP3PlayerInit(void); +void MP3_CMD(uint8_t mp3cmd,uint16_t val); +bool MP3PlayerCmd(void); +bool Xdrv14(uint8_t function); +void PCA9685_Detect(void); +void PCA9685_Reset(void); +void PCA9685_SetPWMfreq(double freq); +void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off); +void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted); +bool PCA9685_Command(void); +void PCA9685_OutputTelemetry(bool telemetry); +bool Xdrv15(uint8_t function); +void CmndTuyaSend(void); +void CmndTuyaMcu(void); +void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId); +void UpdateDevices(); +inline bool TuyaFuncIdValid(uint8_t fnId); +uint8_t TuyaGetFuncId(uint8_t dpid); +uint8_t TuyaGetDpId(uint8_t fnId); +void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value); +void TuyaSendBool(uint8_t id, bool value); +void TuyaSendValue(uint8_t id, uint32_t value); +void TuyaSendEnum(uint8_t id, uint32_t value); +void TuyaSendString(uint8_t id, char data[]); +bool TuyaSetPower(void); +bool TuyaSetChannels(void); +void LightSerialDuty(uint16_t duty); +void TuyaRequestState(void); +void TuyaResetWifi(void); +void TuyaProcessStatePacket(void); +void TuyaLowPowerModePacketProcess(void); +void TuyaHandleProductInfoPacket(void); +void TuyaSendLowPowerSuccessIfNeeded(void); +void TuyaNormalPowerModePacketProcess(void); +bool TuyaModuleSelected(void); +void TuyaInit(void); +void TuyaSerialInput(void); +bool TuyaButtonPressed(void); +uint8_t TuyaGetTuyaWifiState(void); +void TuyaSetWifiLed(void); +bool Xnrg16(uint8_t function); +bool Xdrv16(uint8_t function); +void RfReceiveCheck(void); +void RfInit(void); +void CmndRfSend(void); +bool Xdrv17(uint8_t function); +bool ArmtronixSetChannels(void); +void LightSerial2Duty(uint8_t duty1, uint8_t duty2); +void ArmtronixRequestState(void); +bool ArmtronixModuleSelected(void); +void ArmtronixInit(void); +void ArmtronixSerialInput(void); +void ArmtronixSetWifiLed(void); +bool Xdrv18(uint8_t function); +void PS16DZSerialSend(const char *tx_buffer); +void PS16DZSerialSendOk(void); +void PS16DZSerialSendUpdateCommand(void); +void PS16DZSerialInput(void); +bool PS16DZSerialSendUpdateCommandIfRequired(void); +void PS16DZInit(void); +bool PS16DZModuleSelected(void); +bool Xdrv19(uint8_t function); +String HueBridgeId(void); +String HueSerialnumber(void); +String HueUuid(void); +void HueRespondToMSearch(void); +String GetHueDeviceId(uint8_t id); +String GetHueUserId(void); +void HandleUpnpSetupHue(void); +void HueNotImplemented(String *path); +void HueConfigResponse(String *response); +void HueConfig(String *path); +uint8_t getLocalLightSubtype(uint8_t device); +void HueLightStatus1(uint8_t device, String *response); +bool HueActive(uint8_t device); +void HueLightStatus2(uint8_t device, String *response); +uint32_t EncodeLightId(uint8_t relay_id); +uint32_t DecodeLightId(uint32_t hue_id); +uint32_t findEchoGeneration(void); +void HueGlobalConfig(String *path); +void HueAuthentication(String *path); +void HueLights(String *path); +void HueGroups(String *path); +void HandleHueApi(String *path); +bool Xdrv20(uint8_t function); +String WemoSerialnumber(void); +String WemoUuid(void); +void WemoRespondToMSearch(int echo_type); +void HandleUpnpEvent(void); +void HandleUpnpService(void); +void HandleUpnpMetaService(void); +void HandleUpnpSetupWemo(void); +bool Xdrv21(uint8_t function); +bool IsModuleIfan(void); +uint8_t MaxFanspeed(void); +uint8_t GetFanspeed(void); +void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence); +void SonoffIfanReceived(void); +bool SonoffIfanSerialInput(void); +void CmndFanspeed(void); +bool SonoffIfanInit(void); +void SonoffIfanUpdate(void); +bool Xdrv22(uint8_t function); +void CopyJsonVariant(JsonObject &to, const String &key, const JsonVariant &val); +void CopyJsonArray(JsonArray &to, const JsonArray &arr); +void CopyJsonObject(JsonObject &to, const JsonObject &from); +uint16_t fromClusterCode(uint8_t c); +uint8_t toClusterCode(uint16_t c); +class SBuffer hibernateDevice(const struct Z_Device &device); +class SBuffer hibernateDevices(void); +void hidrateDevices(const SBuffer &buf); +void loadZigbeeDevices(void); +void saveZigbeeDevices(void); +void eraseZigbeeDevices(void); +uint8_t toPercentageCR2032(uint32_t voltage); +uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, + uint32_t offset, uint32_t len); +int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); +int32_t Z_AqaraCube(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); +void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint); +inline bool isXYZ(char c); +inline int8_t hexValue(char c); +void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz); +void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, bool direction, const SBuffer &payload); +const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd); +inline char hexDigit(uint32_t h); +String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z); +uint32_t ZigbeeAliasOrNumber(const char *state_text); +uint8_t ZigbeeGetInstructionSize(uint8_t instr); +void ZigbeeGotoLabel(uint8_t label); +void ZigbeeStateMachine_Run(void); +int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf); +int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf); +int32_t Z_Reboot(int32_t res, class SBuffer &buf); +int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf); +bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match); +int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf); +void Z_SendIEEEAddrReq(uint16_t shortaddr); +void Z_SendActiveEpReq(uint16_t shortaddr); +void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint); +int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf); +int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf); +void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusterid, uint8_t transacid); +int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf); +int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf); +int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf); +int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf); +void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, const JsonObject *json); +int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); +int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf); +int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf); +int32_t Z_Load_Devices(uint8_t value); +int32_t Z_State_Ready(uint8_t value); +int32_t ZigbeeProcessInput(class SBuffer &buf); +void ZigbeeInput(void); +void ZigbeeInit(void); +uint32_t strToUInt(const JsonVariant &val); +void CmndZbReset(void); +void CmndZbZNPSendOrReceive(bool send); +void CmndZbZNPReceive(void); +void CmndZbZNPSend(void); +void ZigbeeZNPSend(const uint8_t *msg, size_t len); +void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, bool clusterSpecific, + uint16_t cluster, uint8_t cmd, const char *param); +void CmndZbSend(void); +void CmndZbBind(void); +void CmndZbProbe(void); +void CmndZbProbeOrPing(boolean probe); +void CmndZbPing(void); +void CmndZbName(void); +void CmndZbForget(void); +void CmndZbSave(void); +void CmndZbRead(void); +void CmndZbPermitJoin(void); +void CmndZbStatus(void); +bool Xdrv23(uint8_t function); +void BuzzerOff(void); +void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode); +void BuzzerSetStateToLed(uint32_t state); +void BuzzerBeep(uint32_t count); +void BuzzerEnabledBeep(uint32_t count, uint32_t duration); +bool BuzzerPinState(void); +void BuzzerInit(void); +void BuzzerEvery100mSec(void); +void CmndBuzzer(void); +bool Xdrv24(uint8_t function); +void A4988Init(void); +void CmndDoMove(void); +void CmndDoRotate(void); +void CmndDoTurn(void); +void CmndSetMIS(void); +void CmndSetSPR(void); +void CmndSetRPM(void); +bool Xdrv25(uint8_t function); +void AriluxRfInterrupt(void); +void AriluxRfHandler(void); +void AriluxRfInit(void); +void AriluxRfDisable(void); +bool Xdrv26(uint8_t function); +void ShutterLogPos(uint32_t i); +void ShutterRtc50mS(void); +int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index); +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index); +void ShutterInit(void); +void ShutterReportPosition(bool always); +void ShutterLimitRealAndTargetPositions(uint32_t i); +void ShutterUpdatePosition(void); +bool ShutterState(uint32_t device); +void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos); +void ShutterWaitForMotorStop(uint32_t i); +int32_t ShutterCounterBasedPosition(uint32_t i); +void ShutterRelayChanged(void); +bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index); +void ShutterButtonHandler(void); +void ShutterSetPosition(uint32_t device, uint32_t position); +void CmndShutterOpen(void); +void CmndShutterClose(void); +void CmndShutterStop(void); +void CmndShutterPosition(void); +void CmndShutterOpenTime(void); +void CmndShutterCloseTime(void); +void CmndShutterMotorDelay(void); +void CmndShutterRelay(void); +void CmndShutterButton(void); +void CmndShutterSetHalfway(void); +void CmndShutterFrequency(void); +void CmndShutterSetClose(void); +void CmndShutterInvert(void); +void CmndShutterCalibration(void); +void CmndShutterLock(void); +void CmndShutterEnableEndStopTime(void); +bool Xdrv27(uint8_t function); +void Pcf8574SwitchRelay(void); +void Pcf8574Init(void); +void HandlePcf8574(void); +void Pcf8574SaveSettings(void); +bool Xdrv28(uint8_t function); +bool DeepSleepEnabled(void); +void DeepSleepReInit(void); +void DeepSleepPrepare(void); +void DeepSleepStart(void); +void DeepSleepEverySecond(void); +void CmndDeepsleepTime(void); +bool Xdrv29(uint8_t function); +uint8_t crc8(const uint8_t *p, uint8_t len); +void ExsSendCmd(uint8_t cmd, uint8_t value); +uint8_t ExsSetPower(uint8_t device, uint8_t power); +uint8_t ExsSetBri(uint8_t device, uint8_t bri); +uint8_t ExsSyncState(uint8_t device); +bool ExsSyncState(); +void ExsDebugState(); +void ExsPacketProcess(void); +bool ExsModuleSelected(void); +bool ExsSetChannels(void); +bool ExsSetPower(void); +void EsxMcuStart(void); +void ExsInit(void); +void ExsSerialInput(void); +void CmndExsDimm(void); +void CmndExsDimmTbl(void); +void CmndExsDimmVal(void); +void CmndExsDimms(void); +void CmndExsChLock(void); +void CmndExsState(void); +bool Xdrv30(uint8_t function); +uint32_t TasmotaSlave_FlashStart(void); +uint8_t TasmotaSlave_UpdateInit(void); +void TasmotaSlave_Reset(void); +uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout); +uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count); +uint8_t TasmotaSlave_execCmd(uint8_t cmd); +uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count); +uint8_t TasmotaSlave_exitProgMode(void); +uint8_t TasmotaSlave_SetupFlash(void); +uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo); +void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data); +void TasmotaSlave_Flash(void); +void TasmotaSlave_SetFlagFlashing(bool value); +bool TasmotaSlave_GetFlagFlashing(void); +void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size); +void TasmotaSlave_Init(void); +void TasmotaSlave_Show(void); +void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param); +void CmndTasmotaSlaveReset(void); +void CmndTasmotaSlaveSend(void); +void TasmotaSlave_ProcessIn(void); +bool Xdrv31(uint8_t function); +void HotPlugInit(void); +void HotPlugEverySecond(void); +void CmndHotPlugTime(void); +bool Xdrv32(uint8_t function); +bool NRF24initRadio(); +bool NRF24Detect(void); +bool Xdrv33(uint8_t function); +void WMotorV1Detect(void); +void WMotorV1Reset(void); +void WMotorV1SetFrequency(uint32_t freq); +void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val); +bool WMotorV1Command(void); +bool Xdrv34(uint8_t function); +void ExceptionTest(uint8_t type); +void CpuLoadLoop(void); +void DebugFreeMem(void); +void DebugFreeMem(void); +void DebugRtcDump(char* parms); +void DebugCfgDump(char* parms); +void DebugCfgPeek(char* parms); +void DebugCfgPoke(char* parms); +void SetFlashMode(uint8_t mode); +void CmndHelp(void); +void CmndRtcDump(void); +void CmndCfgDump(void); +void CmndCfgPeek(void); +void CmndCfgPoke(void); +void CmndCfgXor(void); +void CmndException(void); +void CmndCpuCheck(void); +void CmndFreemem(void); +void CmndSetSensor(void); +void CmndFlashMode(void); +uint32_t DebugSwap32(uint32_t x); +void CmndFlashDump(void); +void CmndI2cWrite(void); +void CmndI2cRead(void); +void CmndI2cStretch(void); +void CmndI2cClock(void); +bool Xdrv99(uint8_t function); +void XsnsDriverState(void); +bool XdrvRulesProcess(void); +void ShowFreeMem(const char *where); +bool XdrvCallDriver(uint32_t driver, uint8_t Function); +bool XdrvCall(uint8_t Function); +void LcdInitMode(void); +void LcdInit(uint8_t mode); +void LcdInitDriver(void); +void LcdDrawStringAt(void); +void LcdDisplayOnOff(uint8_t on); +void LcdCenter(uint8_t row, char* txt); +bool LcdPrintLog(void); +void LcdTime(void); +void LcdRefresh(void); +bool Xdsp01(uint8_t function); +void SSD1306InitDriver(void); +void Ssd1306PrintLog(void); +void Ssd1306Time(void); +void Ssd1306Refresh(void); +bool Xdsp02(byte function); +void MatrixWrite(void); +void MatrixClear(void); +void MatrixFixed(char* txt); +void MatrixCenter(char* txt); +void MatrixScrollLeft(char* txt, int loop); +void MatrixScrollUp(char* txt, int loop); +void MatrixInitMode(void); +void MatrixInit(uint8_t mode); +void MatrixInitDriver(void); +void MatrixOnOff(void); +void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); +void MatrixPrintLog(uint8_t direction); +void MatrixRefresh(void); +bool Xdsp03(uint8_t function); +void Ili9341InitMode(void); +void Ili9341Init(uint8_t mode); +void Ili9341InitDriver(void); +void Ili9341Clear(void); +void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); +void Ili9341DisplayOnOff(uint8_t on); +void Ili9341OnOff(void); +void Ili9341PrintLog(void); +void Ili9341Refresh(void); +bool Xdsp04(uint8_t function); +void EpdInitDriver29(); +void EpdPrintLog29(void); +void EpdRefresh29(void); +bool Xdsp05(uint8_t function); +void EpdInitDriver42(); +void EpdRefresh42(); +bool Xdsp06(uint8_t function); +void SH1106InitDriver(); +void SH1106PrintLog(void); +void SH1106Time(void); +void SH1106Refresh(void); +bool Xdsp07(uint8_t function); +void ILI9488_InitDriver(); +void ILI9488_MQTT(uint8_t count,const char *cp); +void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr); +void FT6236Check(); +bool Xdsp08(uint8_t function); +void SSD1351_InitDriver(); +void SSD1351PrintLog(void); +void SSD1351Time(void); +void SSD1351Refresh(void); +bool Xdsp09(uint8_t function); +void RA8876_InitDriver(); +void RA8876_MQTT(uint8_t count,const char *cp); +void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr); +void FT5316Check(); +bool Xdsp10(uint8_t function); +uint8_t XdspPresent(void); +bool XdspCall(uint8_t Function); +void Ws2812StripShow(void); +int mod(int a, int b); +void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset); +void Ws2812UpdateHand(int position, uint32_t index); +void Ws2812Clock(void); +void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i); +void Ws2812Gradient(uint32_t schemenr); +void Ws2812Bars(uint32_t schemenr); +void Ws2812Clear(void); +void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white); +char* Ws2812GetColor(uint32_t led, char* scolor); +void Ws2812ForceSuspend (void); +void Ws2812ForceUpdate (void); +bool Ws2812SetChannels(void); +void Ws2812ShowScheme(void); +void Ws2812ModuleSelected(void); +void CmndLed(void); +void CmndPixels(void); +void CmndRotation(void); +void CmndWidth(void); +bool Xlgt01(uint8_t function); +void LightDiPulse(uint8_t times); +void LightDckiPulse(uint8_t times); +void LightMy92x1Write(uint8_t data); +void LightMy92x1Init(void); +void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c); +bool My92x1SetChannels(void); +void My92x1ModuleSelected(void); +bool Xlgt02(uint8_t function); +void SM16716_SendBit(uint8_t v); +void SM16716_SendByte(uint8_t v); +void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b); +void SM16716_Init(void); +bool Sm16716SetChannels(void); +void Sm16716ModuleSelected(void); +bool Xlgt03(uint8_t function); +uint8_t Sm2135Write(uint8_t data); +void Sm2135Send(uint8_t *buffer, uint8_t size); +bool Sm2135SetChannels(void); +void Sm2135ModuleSelected(void); +bool Xlgt04(uint8_t function); +void SnfL1Send(const char *buffer); +void SnfL1SerialSendOk(void); +bool SnfL1SerialInput(void); +bool SnfL1SetChannels(void); +void SnfL1ModuleSelected(void); +bool Xlgt05(uint8_t function); +bool XlgtCall(uint8_t function); +void HlwCfInterrupt(void); +void HlwCf1Interrupt(void); +void HlwEvery200ms(void); +void HlwEverySecond(void); +void HlwSnsInit(void); +void HlwDrvInit(void); +bool HlwCommand(void); +bool Xnrg01(uint8_t function); +void CseReceived(void); +bool CseSerialInput(void); +void CseEverySecond(void); +void CseSnsInit(void); +void CseDrvInit(void); +bool CseCommand(void); +bool Xnrg02(uint8_t function); +uint8_t PzemCrc(uint8_t *data); +void PzemSend(uint8_t cmd); +bool PzemReceiveReady(void); +bool PzemRecieve(uint8_t resp, float *data); +void PzemEvery250ms(void); +void PzemSnsInit(void); +void PzemDrvInit(void); +bool PzemCommand(void); +bool Xnrg03(uint8_t function); +uint8_t McpChecksum(uint8_t *data); +unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size); +void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size); +void McpSend(uint8_t *data); +void McpGetAddress(void); +void McpAddressReceive(void); +void McpGetCalibration(void); +void McpParseCalibration(void); +bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift); +void McpSetCalibration(struct mcp_cal_registers_type *cal_registers); +void McpSetSystemConfiguration(uint16 interval); +void McpGetFrequency(void); +void McpParseFrequency(void); +void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency); +void McpGetData(void); +void McpParseData(void); +void McpSerialInput(void); +void McpEverySecond(void); +void McpSnsInit(void); +void McpDrvInit(void); +bool McpCommand(void); +bool Xnrg04(uint8_t function); +void PzemAcEverySecond(void); +void PzemAcSnsInit(void); +void PzemAcDrvInit(void); +bool PzemAcCommand(void); +bool Xnrg05(uint8_t function); +void PzemDcEverySecond(void); +void PzemDcSnsInit(void); +void PzemDcDrvInit(void); +bool PzemDcCommand(void); +bool Xnrg06(uint8_t function); +int Ade7953RegSize(uint16_t reg); +void Ade7953Write(uint16_t reg, uint32_t val); +int32_t Ade7953Read(uint16_t reg); +void Ade7953Init(void); +void Ade7953GetData(void); +void Ade7953EnergyEverySecond(void); +void Ade7953DrvInit(void); +bool Ade7953Command(void); +bool Xnrg07(uint8_t function); +void SDM120Every250ms(void); +void Sdm120SnsInit(void); +void Sdm120DrvInit(void); +void Sdm220Reset(void); +void Sdm220Show(bool json); +bool Xnrg08(uint8_t function); +void Dds2382EverySecond(void); +void Dds2382SnsInit(void); +void Dds2382DrvInit(void); +bool Xnrg09(uint8_t function); +void SDM630Every250ms(void); +void Sdm630SnsInit(void); +void Sdm630DrvInit(void); +bool Xnrg10(uint8_t function); +void DDSU666Every250ms(void); +void Ddsu666SnsInit(void); +void Ddsu666DrvInit(void); +bool Xnrg11(uint8_t function); +bool solaxX1_RS485ReceiveReady(void); +void solaxX1_RS485Send(uint16_t msgLen); +uint8_t solaxX1_RS485Receive(uint8_t *value); +uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen); +void solaxX1_SendInverterAddress(void); +void solaxX1_QueryLiveData(void); +uint8_t solaxX1_ParseErrorCode(uint32_t code); +void solaxX1250MSecond(void); +void solaxX1SnsInit(void); +void solaxX1DrvInit(void); +void solaxX1Show(bool json); +bool Xnrg12(uint8_t function); +void FifLEEvery250ms(void); +void FifLESnsInit(void); +void FifLEDrvInit(void); +void FifLEReset(void); +void FifLEShow(bool json); +bool Xnrg13(uint8_t function); +bool XnrgCall(uint8_t function); +void CounterUpdate(uint8_t index); +void CounterUpdate1(void); +void CounterUpdate2(void); +void CounterUpdate3(void); +void CounterUpdate4(void); +bool CounterPinState(void); +void CounterInit(void); +void CounterEverySecond(void); +void CounterSaveState(void); +void CounterShow(bool json); +void CmndCounter(void); +void CmndCounterType(void); +void CmndCounterDebounce(void); +bool Xsns01(uint8_t function); +void AdcInit(void); +uint16_t AdcRead(uint8_t factor); +void AdcEvery250ms(void); +uint16_t AdcGetLux(void); +uint16_t AdcGetRange(void); +void AdcGetCurrentPower(uint8_t factor); +void AdcEverySecond(void); +void AdcShow(bool json); +void CmndAdc(void); +void CmndAdcs(void); +void CmndAdcParam(void); +bool Xsns02(uint8_t function); +void SonoffScSend(const char *data); +void SonoffScInit(void); +void SonoffScSerialInput(char *rcvstat); +void SonoffScShow(bool json); +bool Xsns04(uint8_t function); +uint8_t OneWireReset(void); +void OneWireWriteBit(uint8_t v); +void OneWireReadBit1(void); +void OneWireReadBit2(void); +uint8_t OneWireReadBit(void); +void OneWireWrite(uint8_t v); +uint8_t OneWireRead(void); +void OneWireSelect(const uint8_t rom[8]); +void OneWireResetSearch(void); +uint8_t OneWireSearch(uint8_t *newAddr); +bool OneWireCrc8(uint8_t *addr); +void Ds18x20Init(void); +void Ds18x20Convert(void); +bool Ds18x20Read(uint8_t sensor); +void Ds18x20Name(uint8_t sensor); +void Ds18x20EverySecond(void); +void Ds18x20Show(bool json); +bool Xsns05(uint8_t function); +void DhtReadPrep(void); +int32_t DhtExpectPulse(uint8_t sensor, bool level); +bool DhtRead(uint8_t sensor); +void DhtReadTempHum(uint8_t sensor); +bool DhtPinState(); +void DhtInit(void); +void DhtEverySecond(void); +void DhtShow(bool json); +bool Xsns06(uint8_t function); +void DhtReadPrep(void); +int32_t DhtExpectPulse(uint8_t sensor, bool level); +bool DhtRead(uint8_t sensor); +void DhtReadTempHum(uint8_t sensor); +bool DhtPinState(); +void DhtInit(void); +void DhtEverySecond(void); +void DhtShow(bool json); +bool Xsns06(uint8_t function); +bool DhtExpectPulse(uint8_t sensor, int level); +int DhtReadDat(uint8_t sensor); +bool DhtRead(uint8_t sensor); +void DhtReadTempHum(uint8_t sensor); +bool DhtPinState(); +void DhtInit(void); +void DhtEverySecond(void); +void DhtShow(bool json); +bool Xsns06(uint8_t function); +bool DhtExpectPulse(uint32_t sensor, uint32_t level); +bool DhtRead(uint32_t sensor); +void DhtReadTempHum(uint32_t sensor); +bool DhtPinState(); +void DhtInit(void); +void DhtEverySecond(void); +void DhtShow(bool json); +bool Xsns06(uint8_t function); +bool DhtWaitState(uint32_t sensor, uint32_t level); +bool DhtRead(uint32_t sensor); +bool DhtPinState(); +void DhtInit(void); +void DhtEverySecond(void); +void DhtShow(bool json); +bool Xsns06(uint8_t function); +bool ShtReset(void); +bool ShtSendCommand(const uint8_t cmd); +bool ShtAwaitResult(void); +int ShtReadData(void); +bool ShtRead(void); +void ShtDetect(void); +void ShtEverySecond(void); +void ShtShow(bool json); +bool Xsns07(uint8_t function); +uint8_t HtuCheckCrc8(uint16_t data); +uint8_t HtuReadDeviceId(void); +void HtuSetResolution(uint8_t resolution); +void HtuReset(void); +void HtuHeater(uint8_t heater); +void HtuInit(void); +bool HtuRead(void); +void HtuDetect(void); +void HtuEverySecond(void); +void HtuShow(bool json); +bool Xsns08(uint8_t function); +bool Bmp180Calibration(uint8_t bmp_idx); +void Bmp180Read(uint8_t bmp_idx); +bool Bmx280Calibrate(uint8_t bmp_idx); +void Bme280Read(uint8_t bmp_idx); +static void BmeDelayMs(uint32_t ms); +bool Bme680Init(uint8_t bmp_idx); +void Bme680Read(uint8_t bmp_idx); +void BmpDetect(void); +void BmpRead(void); +void BmpShow(bool json); +void BMP_EnterSleep(void); +bool Xsns09(uint8_t function); +bool Bh1750Read(void); +void Bh1750Detect(void); +void Bh1750EverySecond(void); +void Bh1750Show(bool json); +bool Xsns10(uint8_t function); +void Veml6070Detect(void); +void Veml6070UvTableInit(void); +void Veml6070EverySecond(void); +void Veml6070ModeCmd(bool mode_cmd); +uint16_t Veml6070ReadUv(void); +double Veml6070UvRiskLevel(uint16_t uv_level); +double Veml6070UvPower(double uvrisk); +void Veml6070Show(bool json); +bool Xsns11(uint8_t function); +void Ads1115StartComparator(uint8_t channel, uint16_t mode); +int16_t Ads1115GetConversion(uint8_t channel); +void Ads1115Detect(void); +void Ads1115Show(bool json); +bool Xsns12(uint8_t function); +bool Ina219SetCalibration(uint8_t mode, uint16_t addr); +float Ina219GetShuntVoltage_mV(uint16_t addr); +float Ina219GetBusVoltage_V(uint16_t addr); +float Ina219GetCurrent_mA(uint16_t addr); +bool Ina219Read(void); +bool Ina219CommandSensor(void); +void Ina219Detect(void); +void Ina219EverySecond(void); +void Ina219Show(bool json); +bool Xsns13(uint8_t function); +bool Sht3xRead(float &t, float &h, uint8_t sht3x_address); +void Sht3xDetect(void); +void Sht3xShow(bool json); +bool Xsns14(uint8_t function); +uint8_t MhzCalculateChecksum(uint8_t *array); +size_t MhzSendCmd(uint8_t command_id); +bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s); +void MhzEverySecond(void); +bool MhzCommandSensor(void); +void MhzInit(void); +void MhzShow(bool json); +bool Xsns15(uint8_t function); +bool Tsl2561Read(void); +void Tsl2561Detect(void); +void Tsl2561EverySecond(void); +void Tsl2561Show(bool json); +bool Xsns16(uint8_t function); +void Senseair250ms(void); +void SenseairInit(void); +void SenseairShow(bool json); +bool Xsns17(uint8_t function); +bool PmsReadData(void); +void PmsSecond(void); +void PmsInit(void); +void PmsShow(bool json); +bool Xsns18(uint8_t function); +void MGSInit(void); +void MGSPrepare(void); +char* measure_gas(int gas_type, char* buffer); +void MGSShow(bool json); +bool Xsns19(uint8_t function); +bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer); +void NovaSdsSetWorkPeriod(void); +bool NovaSdsReadData(void); +void NovaSdsSecond(void); +bool NovaSdsCommandSensor(void); +void NovaSdsInit(void); +void NovaSdsShow(bool json); +bool Xsns20(uint8_t function); +void sgp30_Init(void); +float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit); +void Sgp30Update(void); +void Sgp30Show(bool json); +bool Xsns21(uint8_t function); +uint8_t Sr04TModeDetect(void); +uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third); +uint16_t Sr04TMode3Distance(); +uint16_t Sr04TMode2Distance(void); +void Sr04TReading(void); +void Sr04Show(bool json); +bool Xsns22(uint8_t function); +uint8_t Si1145ReadByte(uint8_t reg); +uint16_t Si1145ReadHalfWord(uint8_t reg); +bool Si1145WriteByte(uint8_t reg, uint16_t val); +uint8_t Si1145WriteParamData(uint8_t p, uint8_t v); +bool Si1145Present(void); +void Si1145Reset(void); +void Si1145DeInit(void); +bool Si1145Begin(void); +uint16_t Si1145ReadUV(void); +uint16_t Si1145ReadVisible(void); +uint16_t Si1145ReadIR(void); +bool Si1145Read(void); +void Si1145Detect(void); +void Si1145Update(void); +void Si1145Show(bool json); +bool Xsns24(uint8_t function); +void LM75ADDetect(void); +float LM75ADGetTemp(void); +void LM75ADShow(bool json); +bool Xsns26(uint8_t function); +int8_t wireReadDataBlock( uint8_t reg, + uint8_t *val, + uint16_t len); +void calculateColorTemperature(void); +bool APDS9960_init(void); +uint8_t getMode(void); +void setMode(uint8_t mode, uint8_t enable); +void enableLightSensor(void); +void disableLightSensor(void); +void enableProximitySensor(void); +void disableProximitySensor(void); +void enableGestureSensor(void); +void disableGestureSensor(void); +bool isGestureAvailable(void); +int16_t readGesture(void); +void enablePower(void); +void disablePower(void); +void readAllColorAndProximityData(void); +void resetGestureParameters(void); +bool processGestureData(void); +bool decodeGesture(void); +void handleGesture(void); +void APDS9960_adjustATime(void); +void APDS9960_loop(void); +void APDS9960_detect(void); +void APDS9960_show(bool json); +bool APDS9960CommandSensor(void); +bool Xsns27(uint8_t function); +void Tm16XXSend(uint8_t data); +void Tm16XXSendCommand(uint8_t cmd); +void TM16XXSendData(uint8_t address, uint8_t data); +uint8_t Tm16XXReceive(void); +void Tm16XXClearDisplay(void); +void Tm1638SetLED(uint8_t color, uint8_t pos); +void Tm1638SetLEDs(word leds); +uint8_t Tm1638GetButtons(void); +void TmInit(void); +void TmLoop(void); +bool Xsns28(uint8_t function); +void MCP230xx_CheckForIntCounter(void); +void MCP230xx_CheckForIntRetainer(void); +const char* IntModeTxt(uint8_t intmo); +uint8_t MCP230xx_readGPIO(uint8_t port); +void MCP230xx_ApplySettings(void); +void MCP230xx_Detect(void); +void MCP230xx_CheckForInterrupt(void); +void MCP230xx_Show(bool json); +void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate); +void MCP230xx_Reset(uint8_t pinmode); +bool MCP230xx_Command(void); +void MCP230xx_UpdateWebData(void); +void MCP230xx_OutputTelemetry(void); +void MCP230xx_Interrupt_Counter_Report(void); +void MCP230xx_Interrupt_Retain_Report(void); +bool Xsns29(uint8_t function); +void Mpr121Init(struct mpr121 *pS, bool initial); +void Mpr121Show(struct mpr121 *pS, uint8_t function); +bool Xsns30(uint8_t function); +void CCS811Detect(void); +void CCS811Update(void); +void CCS811Show(bool json); +bool Xsns31(uint8_t function); +void MPU_6050PerformReading(void); +void MPU_6050Detect(void); +void MPU_6050Show(bool json); +bool Xsns32(uint8_t function); +void DS3231Detect(void); +uint8_t bcd2dec(uint8_t n); +uint8_t dec2bcd(uint8_t n); +uint32_t ReadFromDS3231(void); +void SetDS3231Time (uint32_t epoch_time); +void DS3231EverySecond(void); +bool Xsns33(uint8_t function); +bool HxIsReady(uint16_t timeout); +long HxRead(void); +void HxResetPart(void); +void HxReset(void); +void HxCalibrationStateTextJson(uint8_t msg_id); +void SetWeightDelta(); +bool HxCommand(void); +long HxWeight(void); +void HxInit(void); +void HxEvery100mSecond(void); +void HxSaveBeforeRestart(void); +void HxShow(bool json); +void HandleHxAction(void); +void HxSaveSettings(void); +void HxLogUpdates(void); +bool Xsns34(uint8_t function); +void TX2xStartRead(void); +void Tx2xReset(void); +void Tx2xRead(void); +void Tx2xInit(void); +void Tx2xShow(bool json); +bool Xsns35(uint8_t function); +void MGC3130_handleSensorData(); +void MGC3130_sendMessage(uint8_t data[], uint8_t length); +void MGC3130_handleGesture(); +bool MGC3130_handleTouch(); +void MGC3130_handleAirWheel(); +void MGC3130_handleSystemStatus(); +bool MGC3130_receiveMessage(); +bool MGC3130_readData(); +void MGC3130_nextMode(); +void MGC3130_loop(); +void MGC3130_detect(void); +void MGC3130_show(bool json); +bool MGC3130CommandSensor(); +bool Xsns36(uint8_t function); +bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal); +void RfSnsInitTheoV2(void); +void RfSnsAnalyzeTheov2(void); +void RfSnsTheoV2Show(bool json); +void RfSnsInitAlectoV2(void); +void RfSnsAnalyzeAlectov2(); +void RfSnsAlectoResetRain(void); +uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len); +void RfSnsAlectoV2Show(bool json); +void RfSnsInit(void); +void RfSnsAnalyzeRawSignal(void); +void RfSnsEverySecond(void); +void RfSnsShow(bool json); +bool Xsns37(uint8_t function); +void AzEverySecond(void); +void AzInit(void); +void AzShow(bool json); +bool Xsns38(uint8_t function); +void MAX31855_Init(void); +void MAX31855_GetResult(void); +float MAX31855_GetProbeTemperature(int32_t RawData); +float MAX31855_GetReferenceTemperature(int32_t RawData); +int32_t MAX31855_ShiftIn(uint8_t Length); +void MAX31855_Show(bool Json); +bool Xsns39(uint8_t function); +void PN532_Init(void); +int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout); +int8_t PN532_readAckFrame(void); +uint32_t PN532_getFirmwareVersion(void); +void PN532_wakeup(void); +bool PN532_setPassiveActivationRetries(uint8_t maxRetries); +bool PN532_SAMConfig(void); +uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData); +uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data); +uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data); +void PN532_ScanForTag(void); +bool PN532_Command(void); +bool Xsns40(uint8_t function); +bool Max4409Read_lum(void); +void Max4409Detect(void); +void Max4409EverySecond(void); +void Max4409Show(bool json); +bool Xsns41(uint8_t function); +void Scd30Detect(void); +void Scd30Update(void); +int Scd30GetCommand(int command_code, uint16_t *pvalue); +int Scd30SetCommand(int command_code, uint16_t value); +bool Scd30CommandSensor(); +void Scd30Show(bool json); +bool Xsns42(byte function); +int hreReadBit(); +char hreReadChar(int &parity_errors); +void hreInit(void); +void hreEvery50ms(void); +void hreShow(boolean json); +bool Xsns43(byte function); +uint8_t sps30_calc_CRC(uint8_t *data); +void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen); +void sps30_cmd(uint16_t cmd); +void SPS30_Detect(void); +void SPS30_Every_Second(); +void SPS30_Show(bool json); +bool SPS30_cmd(void); +bool Xsns44(byte function); +void Vl53l0Detect(void); +void Vl53l0Every_250MSecond(void); +void Vl53l0Show(boolean json); +bool Xsns45(byte function); +void MLX90614_Init(void); +void MLX90614_Every_Second(void); +void MLX90614_Show(uint8_t json); +bool Xsns46(byte function); +void MAX31865_Init(void); +void MAX31865_GetResult(void); +void MAX31865_Show(bool Json); +bool Xsns47(uint8_t function); +void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg); +uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr); +void ChirpReset(uint8_t addr); +void ChirpResetAll(void); +void ChirpClockSet(); +void ChirpSleep(uint8_t addr); +void ChirpSelect(uint8_t sensor); +uint8_t ChirpReadVersion(uint8_t addr); +bool ChirpSet(uint8_t addr); +bool ChirpScan(); +void ChirpDetect(void); +void ChirpServiceAllSensors(uint8_t job); +void ChirpEvery100MSecond(void); +void ChirpShow(bool json); +bool ChirpCmd(void); +bool Xsns48(uint8_t function); +void PAJ7620SelectBank(uint8_t bank); +void PAJ7620DecodeGesture(void); +void PAJ7620ReadGesture(void); +void PAJ7620Detect(void); +void PAJ7620Init(void); +void PAJ7620Loop(void); +void PAJ7620Show(bool json); +bool PAJ7620CommandSensor(void); +bool Xsns50(uint8_t function); +void RDM6300_Init(); +void RDM6300_ScanForTag(); +uint8_t rm6300_hexnibble(char chr); +void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]); +void RDM6300_Show(void); +bool Xsns51(byte function); +void IBEACON_Init(); +void hm17_every_second(void); +void hm17_sbclr(void); +void hm17_sendcmd(uint8_t cmd); +uint32_t ibeacon_add(struct IBEACON *ib); +void hm17_decode(void); +void IBEACON_loop(); +void IBEACON_Show(void); +bool xsns52_cmd(void); +bool ibeacon_cmd(void); +void ib_sendbeep(void); +void ibeacon_mqtt(const char *mac,const char *rssi); +bool Xsns52(byte function); +double sml_median_array(double *array,uint8_t len); +double sml_median(struct SML_MEDIAN_FILTER* mf, double in); +void ADS1115_init(void); +bool Serial_available(); +uint8_t Serial_read(); +uint8_t Serial_peek(); +void Dump2log(void); +double sml_getvalue(unsigned char *cp,uint8_t index); +uint8_t hexnibble(char chr); +double CharToDouble(const char *str); +void ebus_esc(uint8_t *ebus_buffer, unsigned char len); +uint8_t ebus_crc8(uint8_t data, uint8_t crc_init); +uint8_t ebus_CalculateCRC( uint8_t *Data, uint16_t DataLen ); +void sml_empty_receiver(uint32_t meters); +void sml_shift_in(uint32_t meters,uint32_t shard); +void SML_Poll(void); +void SML_Decode(uint8_t index); +void SML_Immediate_MQTT(const char *mp,uint8_t index,uint8_t mindex); +void SML_Show(boolean json); +void SML_CounterUpd(uint8_t index); +void SML_CounterUpd1(void); +void SML_CounterUpd2(void); +void SML_CounterUpd3(void); +void SML_CounterUpd4(void); +bool Gpio_used(uint8_t gpiopin); +void SML_Init(void); +uint32_t SML_SetBaud(uint32_t meter, uint32_t br); +uint32_t SML_Write(uint32_t meter,char *hstr); +void SetDBGLed(uint8_t srcpin, uint8_t ledpin); +void SML_Counter_Poll(void); +void SML_Check_Send(void); +uint8_t sml_hexnibble(char chr); +void SML_Send_Seq(uint32_t meter,char *seq); +uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num); +uint8_t SML_PzemCrc(uint8_t *data, uint8_t len); +uint8_t CalcEvenParity(uint8_t data); +bool XSNS_53_cmd(void); +void InjektCounterValue(uint8_t meter,uint32_t counter); +void SML_CounterSaveState(void); +bool Xsns53(byte function); +static uint32_t _expand_r_shunt(uint16_t compact_r_shunt); +void Ina226SetCalibration(uint8_t slaveIndex); +bool Ina226TestPresence(uint8_t device); +void Ina226ResetActive(void); +void Ina226Init(); +float Ina226ReadBus_v(uint8_t device); +float Ina226ReadShunt_i(uint8_t device); +float Ina226ReadPower_w(uint8_t device); +void Ina226Read(uint8_t device); +void Ina226EverySecond(); +bool Ina226CommandSensor(); +void Ina226Show(bool json); +bool Xsns54(byte callback_id); +bool Hih6Read(void); +void Hih6Detect(void); +void Hih6EverySecond(void); +void Hih6Show(bool json); +bool Xsns55(uint8_t function); +void HpmaSecond(void); +void HpmaInit(void); +void HpmaShow(bool json); +bool Xsns56(uint8_t function); +void Tsl2591Init(void); +bool Tsl2591Read(void); +void Tsl2591EverySecond(void); +void Tsl2591Show(bool json); +bool Xsns57(uint8_t function); +bool Dht12Read(void); +void Dht12Detect(void); +void Dht12EverySecond(void); +void Dht12Show(bool json); +bool Xsns58(uint8_t function); +uint32_t DS1624_Idx2Addr(uint32_t idx); +int DS1624_Restart(uint8_t config, uint32_t idx); +void DS1624_HotPlugUp(uint32_t idx); +void DS1624_HotPlugDown(int idx); +bool DS1624GetTemp(float *value, int idx); +void DS1624HotPlugScan(void); +void DS1624EverySecond(void); +void DS1624Show(bool json); +bool Xsns59(uint8_t function); +void UBXcalcChecksum(char* CK, size_t msgSize); +bool UBXcompareMsgHeader(const char* msgHeader); +void UBXinitCFG(void); +void UBXTriggerTele(void); +void UBXDetect(void); +uint32_t UBXprocessGPS(); +void UBXsendHeader(void); +void UBXsendRecord(uint8_t *buf); +void UBXsendFooter(void); +void UBXsendFile(void); +void UBXSetRate(uint16_t interval); +void UBXSelectMode(uint16_t mode); +bool UBXHandlePOSLLH(); +void UBXHandleSTATUS(); +void UBXHandleTIME(); +void UBXHandleOther(void); +void UBXLoop50msec(void); +void UBXLoop(void); +void UBXShow(bool json); +bool UBXCmd(void); +bool Xsns60(uint8_t function); +bool MINRFinitBLE(uint8_t _mode); +void MINRFhopChannel(); +bool MINRFreceivePacket(void); +void MINRFswapbuf(uint8_t len); +void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr); +void MINRFreverseMAC(uint8_t _mac[]); +void MINRFchangePacketModeTo(uint8_t _mode); +void MINRFpurgeFakeSensors(void); +void MINRFhandleFloraPacket(void); +void MINRFhandleMJ_HT_V1Packet(void); +void MINRFhandleLYWSD02Packet(void); +void MINRFhandleLYWSD03Packet(void); +void MINRFhandleCGG1Packet(void); +void MINRF_EVERY_50_MSECOND(); +void MINRFShow(bool json); +bool Xsns61(uint8_t function); +void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay); +void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot); +void HM10_Reset(void); +void HM10_Discovery_Scan(void); +void HM10_Read_LYWSD03(void); +void HM10_Read_LYWSD02(void); +void HM10_Time_LYWSD02(void); +void HM10SerialInit(void); +void HM10MACStringToBytes(const char* string, uint8_t _mac[]); +void HM10ParseResponse(char *buf); +void HM10readTempHum(char *_buf); +bool HM10readBat(char *_buf); +bool HM10SerialHandleFeedback(); +void HM10_TaskEvery100ms(); +void HM10EverySecond(); +bool HM10Cmd(void); +void HM10Show(bool json); +bool Xsns62(uint8_t function); +bool AHT10Read(void); +bool AHT10Init(void); +uint8_t AHT10ReadStatus(void); +void AHT10Reset(void); +void AHT10Detect(void); +void AHT10EverySecond(void); +void AHT10Show(bool json); +bool Xsns63(uint8_t function); +void HandleMetrics(void); +bool Xsns91(uint8_t function); +bool XsnsEnabled(uint32_t sns_index); +void XsnsSensorState(void); +bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index); +bool XsnsCall(uint8_t Function); +bool I2cEnabled(uint32_t i2c_index); +void I2cDriverState(void); +#line 184 "S:/Development/Tasmota/tasmota/tasmota.ino" +void setup(void) +{ + global_state.data = 3; + + RtcRebootLoad(); + if (!RtcRebootValid()) { + RtcReboot.fast_reboot_count = 0; + } + RtcReboot.fast_reboot_count++; + RtcRebootSave(); + + Serial.begin(APP_BAUDRATE); + seriallog_level = LOG_LEVEL_INFO; + + snprintf_P(my_version, sizeof(my_version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); + if (VERSION & 0xff) { + snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); + } + + snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); + + SettingsLoad(); + SettingsDelta(); + + OsWatchInit(); + + GetFeatures(); + + if (1 == RtcReboot.fast_reboot_count) { + UpdateQuickPowerCycle(true); + XdrvCall(FUNC_SETTINGS_OVERRIDE); + } + + + seriallog_level = Settings.seriallog_level; + seriallog_timer = SERIALLOG_TIMER; + syslog_level = Settings.syslog_level; + stop_flash_rotate = Settings.flag.stop_flash_rotate; + save_data_counter = Settings.save_data; + sleep = Settings.sleep; +#ifndef USE_EMULATION + Settings.flag2.emulation = 0; +#else +#ifndef USE_EMULATION_WEMO + if (EMUL_WEMO == Settings.flag2.emulation) { Settings.flag2.emulation = 0; } +#endif +#ifndef USE_EMULATION_HUE + if (EMUL_HUE == Settings.flag2.emulation) { Settings.flag2.emulation = 0; } +#endif +#endif + + if (Settings.param[P_BOOT_LOOP_OFFSET]) { + + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET]) { + Settings.flag3.user_esp8285_enable = 0; + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +1) { + for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { + if (bitRead(Settings.rule_stop, i)) { + bitWrite(Settings.rule_enabled, i, 0); + } + } + } + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +2) { + Settings.rule_enabled = 0; + } + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + Settings.my_gp.io[i] = GPIO_NONE; + } + Settings.my_adc0 = ADC0_NONE; + } + if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { + Settings.module = SONOFF_BASIC; + + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); + } + } + + Format(mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(mqtt_client)); + Format(mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(mqtt_topic)); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME), mqtt_topic, ESP.getChipId() & 0x1FFF); + } else { + snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME)); + } + + GetEspHardwareType(); + GpioInit(); + + + + WifiConnect(); + + SetPowerOnState(); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, SettingsText(SET_FRIENDLYNAME1), my_version, my_image); +#ifdef FIRMWARE_MINIMAL + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); +#endif + + memcpy_P(log_data, VERSION_MARKER, 1); + + RtcInit(); + +#ifdef USE_ARDUINO_OTA + ArduinoOTAInit(); +#endif + + XdrvCall(FUNC_INIT); + XsnsCall(FUNC_INIT); +} + +void BacklogLoop(void) +{ + if (TimeReached(backlog_delay)) { + if (!BACKLOG_EMPTY && !backlog_mutex) { +#ifdef SUPPORT_IF_STATEMENT + backlog_mutex = true; + String cmd = backlog.shift(); + backlog_mutex = false; + ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); +#else + backlog_mutex = true; + ExecuteCommand((char*)backlog[backlog_pointer].c_str(), SRC_BACKLOG); + backlog_pointer++; + if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } + backlog_mutex = false; +#endif + } + } +} + +void loop(void) +{ + uint32_t my_sleep = millis(); + + XdrvCall(FUNC_LOOP); + XsnsCall(FUNC_LOOP); + + OsWatchLoop(); + + ButtonLoop(); + SwitchLoop(); +#ifdef ROTARY_V1 + RotaryLoop(); +#endif +#ifdef USE_DEVICE_GROUPS + DeviceGroupsLoop(); +#endif + BacklogLoop(); + + if (TimeReached(state_50msecond)) { + SetNextTimeInterval(state_50msecond, 50); + XdrvCall(FUNC_EVERY_50_MSECOND); + XsnsCall(FUNC_EVERY_50_MSECOND); + } + if (TimeReached(state_100msecond)) { + SetNextTimeInterval(state_100msecond, 100); + Every100mSeconds(); + XdrvCall(FUNC_EVERY_100_MSECOND); + XsnsCall(FUNC_EVERY_100_MSECOND); + } + if (TimeReached(state_250msecond)) { + SetNextTimeInterval(state_250msecond, 250); + Every250mSeconds(); + XdrvCall(FUNC_EVERY_250_MSECOND); + XsnsCall(FUNC_EVERY_250_MSECOND); + } + if (TimeReached(state_second)) { + SetNextTimeInterval(state_second, 1000); + PerformEverySecond(); + XdrvCall(FUNC_EVERY_SECOND); + XsnsCall(FUNC_EVERY_SECOND); + } + + if (!serial_local) { SerialInput(); } + +#ifdef USE_ARDUINO_OTA + ArduinoOtaLoop(); +#endif + + uint32_t my_activity = millis() - my_sleep; + + if (Settings.flag3.sleep_normal) { + + delay(sleep); + } else { + if (my_activity < (uint32_t)sleep) { + delay((uint32_t)sleep - my_activity); + } else { + if (global_state.wifi_down) { + delay(my_activity /2); + } + } + } + + if (!my_activity) { my_activity++; } + uint32_t loop_delay = sleep; + if (!loop_delay) { loop_delay++; } + uint32_t loops_per_second = 1000 / loop_delay; + uint32_t this_cycle_ratio = 100 * my_activity / loop_delay; + loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); +} +# 1 "S:/Development/Tasmota/tasmota/sendemail.ino" +#ifdef USE_SENDMAIL + +#include "sendemail.h" +# 25 "S:/Development/Tasmota/tasmota/sendemail.ino" +#ifndef SEND_MAIL_MINRAM +#define SEND_MAIL_MINRAM 12*1024 +#endif + +#define xPSTR(a) a + +uint16_t SendMail(char *buffer) { + char *params,*oparams; + const char *mserv; + uint16_t port; + const char *user; + const char *pstr; + const char *passwd; + const char *from; + const char *to; + const char *subject; + const char *cmd; + char auth=0; + uint16_t status=1; + SendEmail *mail=0; + uint16_t blen; + char *endcmd; + + + + uint16_t mem=ESP.getFreeHeap(); + if (memsend(from,to,subject,cmd); + delete mail; + if (result==true) status=0; + } + +exit: + if (oparams) free(oparams); + return status; +} + +void script_send_email_body(BearSSL::WiFiClientSecure_light *client); + + +SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) : + host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) { +} + +String SendEmail::readClient() { + delay(0); + String r = client->readStringUntil('\n'); + + r.trim(); + while (client->available()) { + delay(0); + r += client->readString(); + } + return r; +} + +bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) { +bool status=false; +String buffer; + + if (!host.length()) { + return status; + } + + client->setTimeout(timeout); + +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("Connecting: %s on port %d"),host.c_str(),port); +#endif + + if (!client->connect(host.c_str(), port)) { +#ifdef DEBUG_EMAIL_PORT + AddLog_P(LOG_LEVEL_INFO, PSTR("Connection failed")); +#endif + goto exit; + } + + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("220"))) { + goto exit; + } + + buffer = F("EHLO "); + buffer += client->localIP().toString(); + + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("250"))) { + goto exit; + } + if (user.length()>0 && passwd.length()>0 ) { + + buffer = F("AUTH LOGIN"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("334"))) + { + goto exit; + } + base64 b; + buffer = b.encode(user); + + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("334"))) { + goto exit; + } + buffer = b.encode(passwd); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("235"))) { + goto exit; + } + } + + + buffer = F("MAIL FROM:"); + buffer += from; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("250"))) { + goto exit; + } + buffer = F("RCPT TO:"); + buffer += to; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("250"))) { + goto exit; + } + + buffer = F("DATA"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = readClient(); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + if (!buffer.startsWith(F("354"))) { + goto exit; + } + buffer = F("From: "); + buffer += from; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = F("To: "); + buffer += to; + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + buffer = F("Subject: "); + buffer += subject; + buffer += F("\r\n"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + +#ifdef USE_SCRIPT + if (*msg=='*' && *(msg+1)==0) { + script_send_email_body(client); + } else { + client->println(msg); + } +#else + client->println(msg); +#endif + client->println('.'); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + + buffer = F("QUIT"); + client->println(buffer); +#ifdef DEBUG_EMAIL_PORT + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); +#endif + + status=true; +exit: + + return status; +} + + +#endif +# 1 "S:/Development/Tasmota/tasmota/settings.ino" +# 20 "S:/Development/Tasmota/tasmota/settings.ino" +#ifndef DOMOTICZ_UPDATE_TIMER +#define DOMOTICZ_UPDATE_TIMER 0 +#endif + +#ifndef EMULATION +#define EMULATION EMUL_NONE +#endif + +#ifndef MTX_ADDRESS1 +#define MTX_ADDRESS1 0 +#endif +#ifndef MTX_ADDRESS2 +#define MTX_ADDRESS2 0 +#endif +#ifndef MTX_ADDRESS3 +#define MTX_ADDRESS3 0 +#endif +#ifndef MTX_ADDRESS4 +#define MTX_ADDRESS4 0 +#endif +#ifndef MTX_ADDRESS5 +#define MTX_ADDRESS5 0 +#endif +#ifndef MTX_ADDRESS6 +#define MTX_ADDRESS6 0 +#endif +#ifndef MTX_ADDRESS7 +#define MTX_ADDRESS7 0 +#endif +#ifndef MTX_ADDRESS8 +#define MTX_ADDRESS8 0 +#endif + +#ifndef HOME_ASSISTANT_DISCOVERY_ENABLE +#define HOME_ASSISTANT_DISCOVERY_ENABLE 0 +#endif + +#ifndef LATITUDE +#define LATITUDE 48.858360 +#endif +#ifndef LONGITUDE +#define LONGITUDE 2.294442 +#endif + +#ifndef WORKING_PERIOD +#define WORKING_PERIOD 5 +#endif + +#ifndef COLOR_TEXT +#define COLOR_TEXT "#000" +#endif +#ifndef COLOR_BACKGROUND +#define COLOR_BACKGROUND "#fff" +#endif +#ifndef COLOR_FORM +#define COLOR_FORM "#f2f2f2" +#endif +#ifndef COLOR_INPUT_TEXT +#define COLOR_INPUT_TEXT "#000" +#endif +#ifndef COLOR_INPUT +#define COLOR_INPUT "#fff" +#endif +#ifndef COLOR_CONSOLE_TEXT +#define COLOR_CONSOLE_TEXT "#000" +#endif +#ifndef COLOR_CONSOLE +#define COLOR_CONSOLE "#fff" +#endif +#ifndef COLOR_TEXT_WARNING +#define COLOR_TEXT_WARNING "#f00" +#endif +#ifndef COLOR_TEXT_SUCCESS +#define COLOR_TEXT_SUCCESS "#008000" +#endif +#ifndef COLOR_BUTTON_TEXT +#define COLOR_BUTTON_TEXT "#fff" +#endif +#ifndef COLOR_BUTTON +#define COLOR_BUTTON "#1fa3ec" +#endif +#ifndef COLOR_BUTTON_HOVER +#define COLOR_BUTTON_HOVER "#0e70a4" +#endif +#ifndef COLOR_BUTTON_RESET +#define COLOR_BUTTON_RESET "#d43535" +#endif +#ifndef COLOR_BUTTON_RESET_HOVER +#define COLOR_BUTTON_RESET_HOVER "#931f1f" +#endif +#ifndef COLOR_BUTTON_SAVE +#define COLOR_BUTTON_SAVE "#47c266" +#endif +#ifndef COLOR_BUTTON_SAVE_HOVER +#define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" +#endif +#ifndef COLOR_TIMER_TAB_TEXT +#define COLOR_TIMER_TAB_TEXT "#fff" +#endif +#ifndef COLOR_TIMER_TAB_BACKGROUND +#define COLOR_TIMER_TAB_BACKGROUND "#999" +#endif +#ifndef COLOR_TITLE_TEXT +#define COLOR_TITLE_TEXT COLOR_TEXT +#endif +#ifndef IR_RCV_MIN_UNKNOWN_SIZE +#define IR_RCV_MIN_UNKNOWN_SIZE 6 +#endif +#ifndef ENERGY_OVERTEMP +#define ENERGY_OVERTEMP 90 +#endif +#ifndef DEFAULT_DIMMER_MAX +#define DEFAULT_DIMMER_MAX 100 +#endif +#ifndef DEFAULT_DIMMER_MIN +#define DEFAULT_DIMMER_MIN 0 +#endif +#ifndef DEFAULT_LIGHT_DIMMER +#define DEFAULT_LIGHT_DIMMER 10 +#endif +#ifndef DEFAULT_LIGHT_COMPONENT +#define DEFAULT_LIGHT_COMPONENT 255 +#endif +#ifndef CORS_ENABLED_ALL +#define CORS_ENABLED_ALL "*" +#endif + + +enum WebColors { + COL_TEXT, COL_BACKGROUND, COL_FORM, + COL_INPUT_TEXT, COL_INPUT, COL_CONSOLE_TEXT, COL_CONSOLE, + COL_TEXT_WARNING, COL_TEXT_SUCCESS, + COL_BUTTON_TEXT, COL_BUTTON, COL_BUTTON_HOVER, COL_BUTTON_RESET, COL_BUTTON_RESET_HOVER, COL_BUTTON_SAVE, COL_BUTTON_SAVE_HOVER, + COL_TIMER_TAB_TEXT, COL_TIMER_TAB_BACKGROUND, COL_TITLE, + COL_LAST }; + +const char kWebColors[] PROGMEM = + COLOR_TEXT "|" COLOR_BACKGROUND "|" COLOR_FORM "|" + COLOR_INPUT_TEXT "|" COLOR_INPUT "|" COLOR_CONSOLE_TEXT "|" COLOR_CONSOLE "|" + COLOR_TEXT_WARNING "|" COLOR_TEXT_SUCCESS "|" + COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|" + COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT; + +enum TasmotaSerialConfig { + TS_SERIAL_5N1, TS_SERIAL_6N1, TS_SERIAL_7N1, TS_SERIAL_8N1, + TS_SERIAL_5N2, TS_SERIAL_6N2, TS_SERIAL_7N2, TS_SERIAL_8N2, + TS_SERIAL_5E1, TS_SERIAL_6E1, TS_SERIAL_7E1, TS_SERIAL_8E1, + TS_SERIAL_5E2, TS_SERIAL_6E2, TS_SERIAL_7E2, TS_SERIAL_8E2, + TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1, + TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 }; + +const uint8_t kTasmotaSerialConfig[] PROGMEM = { + SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1, + SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2, + SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1, + SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2, + SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1, + SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2 +}; + + + + + +const uint16_t RTC_MEM_VALID = 0xA55A; + +uint32_t rtc_settings_crc = 0; + +uint32_t GetRtcSettingsCrc(void) +{ + uint32_t crc = 0; + uint8_t *bytes = (uint8_t*)&RtcSettings; + + for (uint32_t i = 0; i < sizeof(RTCMEM); i++) { + crc += bytes[i]*(i+1); + } + return crc; +} + +void RtcSettingsSave(void) +{ + if (GetRtcSettingsCrc() != rtc_settings_crc) { + RtcSettings.valid = RTC_MEM_VALID; + ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); + rtc_settings_crc = GetRtcSettingsCrc(); + } +} + +void RtcSettingsLoad(void) +{ + ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); + if (RtcSettings.valid != RTC_MEM_VALID) { + memset(&RtcSettings, 0, sizeof(RTCMEM)); + RtcSettings.valid = RTC_MEM_VALID; + RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; + RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; + RtcSettings.energy_usage = Settings.energy_usage; + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; + } + RtcSettings.power = Settings.power; + RtcSettingsSave(); + } + rtc_settings_crc = GetRtcSettingsCrc(); +} + +bool RtcSettingsValid(void) +{ + return (RTC_MEM_VALID == RtcSettings.valid); +} + + + +uint32_t rtc_reboot_crc = 0; + +uint32_t GetRtcRebootCrc(void) +{ + uint32_t crc = 0; + uint8_t *bytes = (uint8_t*)&RtcReboot; + + for (uint32_t i = 0; i < sizeof(RTCRBT); i++) { + crc += bytes[i]*(i+1); + } + return crc; +} + +void RtcRebootSave(void) +{ + if (GetRtcRebootCrc() != rtc_reboot_crc) { + RtcReboot.valid = RTC_MEM_VALID; + ESP.rtcUserMemoryWrite(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); + rtc_reboot_crc = GetRtcRebootCrc(); + } +} + +void RtcRebootReset(void) +{ + RtcReboot.fast_reboot_count = 0; + RtcRebootSave(); +} + +void RtcRebootLoad(void) +{ + ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); + if (RtcReboot.valid != RTC_MEM_VALID) { + memset(&RtcReboot, 0, sizeof(RTCRBT)); + RtcReboot.valid = RTC_MEM_VALID; + + RtcRebootSave(); + } + rtc_reboot_crc = GetRtcRebootCrc(); +} + +bool RtcRebootValid(void) +{ + return (RTC_MEM_VALID == RtcReboot.valid); +} +# 299 "S:/Development/Tasmota/tasmota/settings.ino" +extern "C" { +#include "spi_flash.h" +} +#include "eboot_command.h" + +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) + +extern "C" uint32_t _SPIFFS_end; + +const uint32_t SPIFFS_END = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; + +#else + +#if AUTOFLASHSIZE + +#include "flash_hal.h" + + +const uint32_t SPIFFS_END = (FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; + +#else + +extern "C" uint32_t _FS_end; + +const uint32_t SPIFFS_END = ((uint32_t)&_FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; + +#endif + +#endif + + +const uint32_t SETTINGS_LOCATION = SPIFFS_END; + +const uint8_t CFG_ROTATES = 8; + +uint32_t settings_location = SETTINGS_LOCATION; +uint32_t settings_crc32 = 0; +uint8_t *settings_buffer = nullptr; + + + + + +void SetFlashModeDout(void) +{ + uint8_t *_buffer; + uint32_t address; + + eboot_command ebcmd; + eboot_command_read(&ebcmd); + address = ebcmd.args[0]; + _buffer = new uint8_t[FLASH_SECTOR_SIZE]; + + if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { + if (_buffer[2] != 3) { + _buffer[2] = 3; + if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { + ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); + } + } + } + delete[] _buffer; +} + +bool VersionCompatible(void) +{ + if (Settings.flag3.compatibility_check) { + return true; + } + + eboot_command ebcmd; + eboot_command_read(&ebcmd); + uint32_t start_address = ebcmd.args[0]; + uint32_t end_address = start_address + (ebcmd.args[2] & 0xFFFFF000) + FLASH_SECTOR_SIZE; + uint32_t* buffer = new uint32_t[FLASH_SECTOR_SIZE / 4]; + + uint32_t version[3] = { 0 }; + bool found = false; + for (uint32_t address = start_address; address < end_address; address = address + FLASH_SECTOR_SIZE) { + ESP.flashRead(address, (uint32_t*)buffer, FLASH_SECTOR_SIZE); + if ((address == start_address) && (0x1F == (buffer[0] & 0xFF))) { + version[1] = 0xFFFFFFFF; + found = true; + } else { + for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) { + version[0] = version[1]; + version[1] = version[2]; + version[2] = buffer[i]; + if ((MARKER_START == version[0]) && (MARKER_END == version[2])) { + found = true; + break; + } + } + } + if (found) { break; } + } + delete[] buffer; + + if (!found) { version[1] = 0; } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: Version 0x%08X, Compatible 0x%08X"), version[1], VERSION_COMPATIBLE); + + if (version[1] < VERSION_COMPATIBLE) { + uint32_t eboot_magic = 0; + ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic)); + return false; + } + + return true; +} + +void SettingsBufferFree(void) +{ + if (settings_buffer != nullptr) { + free(settings_buffer); + settings_buffer = nullptr; + } +} + +bool SettingsBufferAlloc(void) +{ + SettingsBufferFree(); + if (!(settings_buffer = (uint8_t *)malloc(sizeof(Settings)))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_UPLOAD_ERR_2)); + return false; + } + return true; +} + +uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size) +{ + uint16_t crc = 0; + + for (uint32_t i = 0; i < size; i++) { + if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } + } + return crc; +} + +uint16_t GetSettingsCrc(void) +{ + + uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG); + return GetCfgCrc16((uint8_t*)&Settings, size); +} + +uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size) +{ + + uint32_t crc = 0; + + while (size--) { + crc ^= *bytes++; + for (uint32_t j = 0; j < 8; j++) { + crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); + } + } + return ~crc; +} + +uint32_t GetSettingsCrc32(void) +{ + return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); +} + +void SettingsSaveAll(void) +{ + if (Settings.flag.save_state) { + Settings.power = power; + } else { + Settings.power = 0; + } + XsnsCall(FUNC_SAVE_BEFORE_RESTART); + XdrvCall(FUNC_SAVE_BEFORE_RESTART); + SettingsSave(0); +} + + + + + +void UpdateQuickPowerCycle(bool update) +{ + if (Settings.flag3.fast_power_cycle_disable) { return; } + + uint32_t pc_register; + uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES; + + ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); + if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) { + uint32_t counter = ((pc_register & 0xF) << 1) & 0xF; + if (0 == counter) { + SettingsErase(3); + EspRestart(); + } else { + pc_register = 0xFFA55AB0 | counter; + ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter); + } + } + else if (pc_register != 0xFFA55ABF) { + pc_register = 0xFFA55ABF; + + if (ESP.flashEraseSector(pc_location)) { + ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset")); + } +} + + + + + +uint32_t GetSettingsTextLen(void) +{ + char* position = Settings.text_pool; + for (uint32_t size = 0; size < SET_MAX; size++) { + while (*position++ != '\0') { } + } + return position - Settings.text_pool; +} + +bool SettingsUpdateText(uint32_t index, const char* replace_me) +{ + if (index >= SET_MAX) { + return false; + } + + + uint32_t replace_len = strlen(replace_me); + char replace[replace_len +1]; + memcpy(replace, replace_me, sizeof(replace)); + + uint32_t start_pos = 0; + uint32_t end_pos = 0; + char* position = Settings.text_pool; + for (uint32_t size = 0; size < SET_MAX; size++) { + while (*position++ != '\0') { } + if (1 == index) { + start_pos = position - Settings.text_pool; + } + else if (0 == index) { + end_pos = position - Settings.text_pool -1; + } + index--; + } + uint32_t char_len = position - Settings.text_pool; + + uint32_t current_len = end_pos - start_pos; + int diff = replace_len - current_len; + + + + + int too_long = (char_len + diff) - settings_text_size; + if (too_long > 0) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text overflow by %d char(s)"), too_long); + return false; + } + + if (diff != 0) { + + memmove_P(Settings.text_pool + start_pos + replace_len, Settings.text_pool + end_pos, char_len - end_pos); + } + + memmove_P(Settings.text_pool + start_pos, replace, replace_len); + + memset(Settings.text_pool + char_len + diff, 0x00, settings_text_size - char_len - diff); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d"), GetSettingsTextLen(), settings_text_size); + + return true; +} + +char* SettingsText(uint32_t index) +{ + char* position = Settings.text_pool; + + if (index >= SET_MAX) { + position += settings_text_size -1; + } else { + for (;index > 0; index--) { + while (*position++ != '\0') { } + } + } + return position; +} + + + + + +uint32_t GetSettingsAddress(void) +{ + return settings_location * SPI_FLASH_SEC_SIZE; +} + +void SettingsSave(uint8_t rotate) +{ +# 607 "S:/Development/Tasmota/tasmota/settings.ino" +#ifndef FIRMWARE_MINIMAL + if ((GetSettingsCrc32() != settings_crc32) || rotate) { + if (1 == rotate) { + stop_flash_rotate = 1; + } + if (2 == rotate) { + settings_location = SETTINGS_LOCATION +1; + } + if (stop_flash_rotate) { + settings_location = SETTINGS_LOCATION; + } else { + settings_location--; + if (settings_location <= (SETTINGS_LOCATION - CFG_ROTATES)) { + settings_location = SETTINGS_LOCATION; + } + } + + Settings.save_flag++; + if (UtcTime() > START_VALID_TIME) { + Settings.cfg_timestamp = UtcTime(); + } else { + Settings.cfg_timestamp++; + } + Settings.cfg_size = sizeof(SYSCFG); + Settings.cfg_crc = GetSettingsCrc(); + Settings.cfg_crc32 = GetSettingsCrc32(); + + if (ESP.flashEraseSector(settings_location)) { + ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + } + + if (!stop_flash_rotate && rotate) { + for (uint32_t i = 1; i < CFG_ROTATES; i++) { + ESP.flashEraseSector(settings_location -i); + delay(1); + } + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); + + settings_crc32 = Settings.cfg_crc32; + } +#endif + RtcSettingsSave(); +} + +void SettingsLoad(void) +{ + + struct SYSCFGH { + uint16_t cfg_holder; + uint16_t cfg_size; + unsigned long save_flag; + } _SettingsH; + unsigned long save_flag = 0; + + settings_location = 0; + uint32_t flash_location = SETTINGS_LOCATION +1; + uint16_t cfg_holder = 0; + for (uint32_t i = 0; i < CFG_ROTATES; i++) { + flash_location--; + ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + + bool valid = false; + if (Settings.version > 0x06000000) { + bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32()); + if (Settings.version < 0x0606000B) { + almost_valid = (Settings.cfg_crc == GetSettingsCrc()); + } + + if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } + valid = (cfg_holder == Settings.cfg_holder); + } else { + ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); + valid = (Settings.cfg_holder == _SettingsH.cfg_holder); + } + if (valid) { + if (Settings.save_flag > save_flag) { + save_flag = Settings.save_flag; + settings_location = flash_location; + if (Settings.flag.stop_flash_rotate && (0 == i)) { + break; + } + } + } + + delay(1); + } + if (settings_location > 0) { + ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); + } + +#ifndef FIRMWARE_MINIMAL + if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { + SettingsDefault(); + } + settings_crc32 = GetSettingsCrc32(); +#endif + + RtcSettingsLoad(); +} + +void EspErase(uint32_t start_sector, uint32_t end_sector) +{ + bool serial_output = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); + for (uint32_t sector = start_sector; sector < end_sector; sector++) { + + bool result = ESP.flashEraseSector(sector); + + + + if (serial_output) { +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + Serial.printf(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n", sector, (result) ? D_OK : D_ERROR); +#else + Serial.printf_P(PSTR(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n"), sector, (result) ? D_OK : D_ERROR); +#endif + delay(10); + } else { + yield(); + } + OsWatchLoop(); + } +} + +void SettingsErase(uint8_t type) +{ +# 750 "S:/Development/Tasmota/tasmota/settings.ino" +#ifndef FIRMWARE_MINIMAL + uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; + uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; + if (1 == type) { + + _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; + } + else if (2 == type) { + _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; + _sectorEnd = SETTINGS_LOCATION +1; + } + else if (3 == type) { + _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; + _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; + } +#ifdef USE_WIFI_SDK_ERASE + else if (4 == type) { + _sectorStart = SETTINGS_LOCATION +1; + _sectorEnd = _sectorStart +1; + } + else if (5 == type) { + _sectorStart = (ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE) -4; + _sectorEnd = _sectorStart +1; + } +#endif + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); + + + EsptoolErase(_sectorStart, _sectorEnd); +#endif +} + +void SettingsSdkErase(void) +{ + WiFi.disconnect(false); + SettingsErase(1); + delay(1000); +} + +#ifdef USE_WIFI_SDK_ERASE +void SettingsSdkWifiErase(void) +{ + WiFi.disconnect(false); + SettingsErase(4); + SettingsErase(5); + delay(200); +} +#endif + + + +void SettingsDefault(void) +{ + AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_USE_DEFAULTS)); + SettingsDefaultSet1(); + SettingsDefaultSet2(); + SettingsSave(2); +} + +void SettingsDefaultSet1(void) +{ + memset(&Settings, 0x00, sizeof(SYSCFG)); + + Settings.cfg_holder = (uint16_t)CFG_HOLDER; + Settings.cfg_size = sizeof(SYSCFG); + + Settings.version = VERSION; + + +} + +void SettingsDefaultSet2(void) +{ + memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); + + Settings.flag.stop_flash_rotate = APP_FLASH_CYCLE; + Settings.flag.global_state = APP_ENABLE_LEDLINK; + Settings.flag3.sleep_normal = APP_NORMAL_SLEEP; + Settings.flag3.no_power_feedback = APP_NO_RELAY_SCAN; + Settings.flag3.fast_power_cycle_disable = APP_DISABLE_POWERCYCLE; + Settings.flag3.bootcount_update = DEEPSLEEP_BOOTCOUNT; + Settings.flag3.compatibility_check = OTA_COMPATIBILITY; + Settings.save_data = SAVE_DATA; + Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; + Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; + Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; + Settings.sleep = APP_SLEEP; + if (Settings.sleep < 50) { + Settings.sleep = 50; + } + + + + Settings.interlock[0] = 0xFF; + Settings.module = MODULE; + ModuleDefault(WEMOS); + + SettingsUpdateText(SET_FRIENDLYNAME1, FRIENDLY_NAME); + SettingsUpdateText(SET_FRIENDLYNAME2, FRIENDLY_NAME"2"); + SettingsUpdateText(SET_FRIENDLYNAME3, FRIENDLY_NAME"3"); + SettingsUpdateText(SET_FRIENDLYNAME4, FRIENDLY_NAME"4"); + SettingsUpdateText(SET_OTAURL, OTA_URL); + + + Settings.flag.save_state = SAVE_STATE; + Settings.power = APP_POWER; + Settings.poweronstate = APP_POWERON_STATE; + Settings.blinktime = APP_BLINKTIME; + Settings.blinkcount = APP_BLINKCOUNT; + Settings.ledstate = APP_LEDSTATE; + Settings.ledmask = APP_LEDMASK; + Settings.pulse_timer[0] = APP_PULSETIME; + + + + Settings.serial_config = TS_SERIAL_8N1; + Settings.baudrate = APP_BAUDRATE / 300; + Settings.sbaudrate = SOFT_BAUDRATE / 300; + Settings.serial_delimiter = 0xff; + Settings.seriallog_level = SERIAL_LOG_LEVEL; + + + Settings.flag3.use_wifi_scan = WIFI_SCAN_AT_RESTART; + Settings.flag3.use_wifi_rescan = WIFI_SCAN_REGULARLY; + Settings.wifi_output_power = 170; + ParseIp(&Settings.ip_address[0], WIFI_IP_ADDRESS); + ParseIp(&Settings.ip_address[1], WIFI_GATEWAY); + ParseIp(&Settings.ip_address[2], WIFI_SUBNETMASK); + ParseIp(&Settings.ip_address[3], WIFI_DNS); + Settings.sta_config = WIFI_CONFIG_TOOL; + + SettingsUpdateText(SET_STASSID1, STA_SSID1); + SettingsUpdateText(SET_STASSID2, STA_SSID2); + SettingsUpdateText(SET_STAPWD1, STA_PASS1); + SettingsUpdateText(SET_STAPWD2, STA_PASS2); + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + + + SettingsUpdateText(SET_SYSLOG_HOST, SYS_LOG_HOST); + Settings.syslog_port = SYS_LOG_PORT; + Settings.syslog_level = SYS_LOG_LEVEL; + + + Settings.flag2.emulation = EMULATION; + Settings.flag3.gui_hostname_ip = GUI_SHOW_HOSTNAME; + Settings.flag3.mdns_enabled = MDNS_ENABLED; + Settings.webserver = WEB_SERVER; + Settings.weblog_level = WEB_LOG_LEVEL; + SettingsUpdateText(SET_WEBPWD, WEB_PASSWORD); + SettingsUpdateText(SET_CORS, CORS_DOMAIN); + + + Settings.flag.button_restrict = KEY_DISABLE_MULTIPRESS; + Settings.flag.button_swap = KEY_SWAP_DOUBLE_PRESS; + Settings.flag.button_single = KEY_ONLY_SINGLE_PRESS; + Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; + + + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { Settings.switchmode[i] = SWITCH_MODE; } + + + Settings.flag.mqtt_enabled = MQTT_USE; + Settings.flag.mqtt_response = MQTT_RESULT_COMMAND; + Settings.flag.mqtt_offline = MQTT_LWT_MESSAGE; + Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN; + Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; + Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; + Settings.flag.mqtt_sensor_retain = MQTT_SENSOR_RETAIN; + + Settings.flag.device_index_enable = MQTT_POWER_FORMAT; + Settings.flag3.time_append_timezone = MQTT_APPEND_TIMEZONE; + Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL; + Settings.flag3.no_hold_retain = MQTT_NO_HOLD_RETAIN; + Settings.flag3.use_underscore = MQTT_INDEX_SEPARATOR; + Settings.flag3.grouptopic_mode = MQTT_GROUPTOPIC_FORMAT; + SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST); + Settings.mqtt_port = MQTT_PORT; + SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID); + SettingsUpdateText(SET_MQTT_USER, MQTT_USER); + SettingsUpdateText(SET_MQTT_PWD, MQTT_PASS); + SettingsUpdateText(SET_MQTT_TOPIC, MQTT_TOPIC); + SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); + SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); + SettingsUpdateText(SET_MQTT_FULLTOPIC, MQTT_FULLTOPIC); + Settings.mqtt_retry = MQTT_RETRY_SECS; + SettingsUpdateText(SET_MQTTPREFIX1, SUB_PREFIX); + SettingsUpdateText(SET_MQTTPREFIX2, PUB_PREFIX); + SettingsUpdateText(SET_MQTTPREFIX3, PUB_PREFIX2); + SettingsUpdateText(SET_STATE_TXT1, MQTT_STATUS_OFF); + SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON); + SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE); + SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD); + char fingerprint[60]; + strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint)); + char *p = fingerprint; + for (uint32_t i = 0; i < 20; i++) { + Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16); + } + strlcpy(fingerprint, MQTT_FINGERPRINT2, sizeof(fingerprint)); + p = fingerprint; + for (uint32_t i = 0; i < 20; i++) { + Settings.mqtt_fingerprint[1][i] = strtol(p, &p, 16); + } + Settings.tele_period = TELE_PERIOD; + Settings.mqttlog_level = MQTT_LOG_LEVEL; + + + Settings.flag.no_power_on_check = ENERGY_VOLTAGE_ALWAYS; + Settings.flag2.current_resolution = 3; + + + Settings.flag2.energy_resolution = ENERGY_RESOLUTION; + Settings.flag3.dds2382_model = ENERGY_DDS2382_MODE; + Settings.flag3.hardware_energy_total = ENERGY_HARDWARE_TOTALS; + Settings.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; + + Settings.energy_power_calibration = HLW_PREF_PULSE; + Settings.energy_voltage_calibration = HLW_UREF_PULSE; + Settings.energy_current_calibration = HLW_IREF_PULSE; +# 980 "S:/Development/Tasmota/tasmota/settings.ino" + Settings.energy_max_power_limit_hold = MAX_POWER_HOLD; + Settings.energy_max_power_limit_window = MAX_POWER_WINDOW; + + Settings.energy_max_power_safe_limit_hold = SAFE_POWER_HOLD; + Settings.energy_max_power_safe_limit_window = SAFE_POWER_WINDOW; + + + + RtcSettings.energy_kWhtotal = 0; + + memset((char*)&RtcSettings.energy_usage, 0x00, sizeof(RtcSettings.energy_usage)); + Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; + + + Settings.flag.ir_receive_decimal = IR_DATA_RADIX; + Settings.flag3.receive_raw = IR_ADD_RAW_DATA; + Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; + + + Settings.flag.rf_receive_decimal = RF_DATA_RADIX; + + memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); + + + Settings.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; +# 1015 "S:/Development/Tasmota/tasmota/settings.ino" + Settings.flag.temperature_conversion = TEMP_CONVERSION; + Settings.flag.pressure_conversion = PRESSURE_CONVERSION; + Settings.flag2.pressure_resolution = PRESSURE_RESOLUTION; + Settings.flag2.humidity_resolution = HUMIDITY_RESOLUTION; + Settings.flag2.temperature_resolution = TEMP_RESOLUTION; + Settings.flag3.ds18x20_internal_pullup = DS18X20_PULL_UP; + Settings.flag3.counter_reset_on_tele = COUNTER_RESET; + + + + + + + Settings.flag2.calc_resolution = CALC_RESOLUTION; + + + Settings.flag3.timers_enable = TIMERS_ENABLED; + + + Settings.flag.hass_light = HASS_AS_LIGHT; + Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE; + Settings.flag3.hass_tele_on_power = TELE_ON_POWER; + + + Settings.flag.knx_enabled = KNX_ENABLED; + Settings.flag.knx_enable_enhancement = KNX_ENHANCED; + + + Settings.flag.pwm_control = LIGHT_MODE; + Settings.flag.ws_clock_reverse = LIGHT_CLOCK_DIRECTION; + Settings.flag.light_signal = LIGHT_PAIRS_CO2; + Settings.flag.not_power_linked = LIGHT_POWER_CONTROL; + Settings.flag.decimal_text = LIGHT_COLOR_RADIX; + Settings.flag3.pwm_multi_channels = LIGHT_CHANNEL_MODE; + Settings.flag3.slider_dimmer_stay_on = LIGHT_SLIDER_POWER; + Settings.flag4.alexa_ct_range = LIGHT_ALEXA_CT_RANGE; + + Settings.pwm_frequency = PWM_FREQ; + Settings.pwm_range = PWM_RANGE; + for (uint32_t i = 0; i < MAX_PWMS; i++) { + Settings.light_color[i] = DEFAULT_LIGHT_COMPONENT; + + } + Settings.light_correction = 1; + Settings.light_dimmer = DEFAULT_LIGHT_DIMMER; + + Settings.light_speed = 1; + + Settings.light_width = 1; + + Settings.light_pixels = WS2812_LEDS; + + Settings.ws_width[WS_SECOND] = 1; + Settings.ws_color[WS_SECOND][WS_RED] = 255; + + Settings.ws_color[WS_SECOND][WS_BLUE] = 255; + Settings.ws_width[WS_MINUTE] = 3; + + Settings.ws_color[WS_MINUTE][WS_GREEN] = 255; + + Settings.ws_width[WS_HOUR] = 5; + Settings.ws_color[WS_HOUR][WS_RED] = 255; + + + + Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; + Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; + + + + Settings.display_mode = 1; + Settings.display_refresh = 2; + Settings.display_rows = 2; + Settings.display_cols[0] = 16; + Settings.display_cols[1] = 8; + Settings.display_dimmer = 1; + Settings.display_size = 1; + Settings.display_font = 1; + + Settings.display_address[0] = MTX_ADDRESS1; + Settings.display_address[1] = MTX_ADDRESS2; + Settings.display_address[2] = MTX_ADDRESS3; + Settings.display_address[3] = MTX_ADDRESS4; + Settings.display_address[4] = MTX_ADDRESS5; + Settings.display_address[5] = MTX_ADDRESS6; + Settings.display_address[6] = MTX_ADDRESS7; + Settings.display_address[7] = MTX_ADDRESS8; + + + if (((APP_TIMEZONE > -14) && (APP_TIMEZONE < 15)) || (99 == APP_TIMEZONE)) { + Settings.timezone = APP_TIMEZONE; + Settings.timezone_minutes = 0; + } else { + Settings.timezone = APP_TIMEZONE / 60; + Settings.timezone_minutes = abs(APP_TIMEZONE % 60); + } + SettingsUpdateText(SET_NTPSERVER1, NTP_SERVER1); + SettingsUpdateText(SET_NTPSERVER2, NTP_SERVER2); + SettingsUpdateText(SET_NTPSERVER3, NTP_SERVER3); + for (uint32_t i = 0; i < MAX_NTP_SERVERS; i++) { + SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i))); + } + Settings.latitude = (int)((double)LATITUDE * 1000000); + Settings.longitude = (int)((double)LONGITUDE * 1000000); + SettingsResetStd(); + SettingsResetDst(); + + Settings.button_debounce = KEY_DEBOUNCE_TIME; + Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; + + for (uint32_t j = 0; j < 5; j++) { + Settings.rgbwwTable[j] = 255; + } + + Settings.novasds_startingoffset = STARTING_OFFSET; + + SettingsDefaultWebColor(); + + memset(&Settings.monitors, 0xFF, 20); + SettingsEnableAllI2cDrivers(); + + + Settings.flag3.tuya_apply_o20 = TUYA_SETOPTION_20; + Settings.flag3.tuya_serial_mqtt_publish = MQTT_TUYA_RECEIVED; + + Settings.flag3.buzzer_enable = BUZZER_ENABLE; + Settings.flag3.shutter_mode = SHUTTER_SUPPORT; + Settings.flag3.pcf8574_ports_inverted = PCF8574_INVERT_PORTS; + Settings.flag4.zigbee_use_names = ZIGBEE_FRIENDLY_NAMES; +} + + + +void SettingsResetStd(void) +{ + Settings.tflag[0].hemis = TIME_STD_HEMISPHERE; + Settings.tflag[0].week = TIME_STD_WEEK; + Settings.tflag[0].dow = TIME_STD_DAY; + Settings.tflag[0].month = TIME_STD_MONTH; + Settings.tflag[0].hour = TIME_STD_HOUR; + Settings.toffset[0] = TIME_STD_OFFSET; +} + +void SettingsResetDst(void) +{ + Settings.tflag[1].hemis = TIME_DST_HEMISPHERE; + Settings.tflag[1].week = TIME_DST_WEEK; + Settings.tflag[1].dow = TIME_DST_DAY; + Settings.tflag[1].month = TIME_DST_MONTH; + Settings.tflag[1].hour = TIME_DST_HOUR; + Settings.toffset[1] = TIME_DST_OFFSET; +} + +void SettingsDefaultWebColor(void) +{ + char scolor[10]; + for (uint32_t i = 0; i < COL_LAST; i++) { + WebHexCode(i, GetTextIndexed(scolor, sizeof(scolor), i, kWebColors)); + } +} + +void SettingsEnableAllI2cDrivers(void) +{ + Settings.i2c_drivers[0] = 0xFFFFFFFF; + Settings.i2c_drivers[1] = 0xFFFFFFFF; + Settings.i2c_drivers[2] = 0xFFFFFFFF; +} + + + +void SettingsDelta(void) +{ + if (Settings.version != VERSION) { + if (Settings.version < 0x06000000) { + Settings.cfg_size = sizeof(SYSCFG); + Settings.cfg_crc = GetSettingsCrc(); + } + if (Settings.version < 0x06000002) { + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + if (i < 4) { + Settings.switchmode[i] = Settings.interlock[i]; + } else { + Settings.switchmode[i] = SWITCH_MODE; + } + } + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + if (Settings.my_gp.io[i] >= GPIO_SWT5) { + Settings.my_gp.io[i] += 4; + } + } + } + if (Settings.version < 0x06000003) { + Settings.flag.mqtt_serial_raw = 0; + Settings.flag.pressure_conversion = 0; + Settings.flag3.data = 0; + } + if (Settings.version < 0x06010103) { + Settings.flag3.timers_enable = 1; + } + if (Settings.version < 0x0601010C) { + Settings.button_debounce = KEY_DEBOUNCE_TIME; + Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; + } + if (Settings.version < 0x0602010A) { + for (uint32_t j = 0; j < 5; j++) { + Settings.rgbwwTable[j] = 255; + } + } + if (Settings.version < 0x06030002) { + Settings.timezone_minutes = 0; + } + if (Settings.version < 0x06030004) { + memset(&Settings.monitors, 0xFF, 20); + } + if (Settings.version < 0x0603000E) { + Settings.flag2.calc_resolution = CALC_RESOLUTION; + } + if (Settings.version < 0x0603000F) { + if (Settings.sleep < 50) { + Settings.sleep = 50; + } + } + if (Settings.version < 0x06040105) { + Settings.flag3.mdns_enabled = MDNS_ENABLED; + Settings.param[P_MDNS_DELAYED_START] = 0; + } + if (Settings.version < 0x0604010B) { + Settings.interlock[0] = 0xFF; + for (uint32_t i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } + } + if (Settings.version < 0x0604010D) { + Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; + } + if (Settings.version < 0x06040110) { + ModuleDefault(WEMOS); + } + if (Settings.version < 0x06040113) { + Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; + } + if (Settings.version < 0x06050003) { + Settings.novasds_startingoffset = STARTING_OFFSET; + } + if (Settings.version < 0x06050006) { + SettingsDefaultWebColor(); + } + if (Settings.version < 0x06050007) { + Settings.ledmask = APP_LEDMASK; + } + if (Settings.version < 0x0605000A) { + Settings.my_adc0 = ADC0_NONE; + } + if (Settings.version < 0x0605000D) { + Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; + } + if (Settings.version < 0x06060001) { + Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; + } + if (Settings.version < 0x06060007) { + memset((char*)&Settings +0xE00, 0x00, sizeof(SYSCFG) -0xE00); + } + if (Settings.version < 0x06060008) { + + if (Settings.flag3.tuya_serial_mqtt_publish) { + Settings.param[P_ex_DIMMER_MAX] = 100; + } else { + Settings.param[P_ex_DIMMER_MAX] = 255; + } + } + if (Settings.version < 0x06060009) { + Settings.baudrate = APP_BAUDRATE / 300; + Settings.sbaudrate = SOFT_BAUDRATE / 300; + } + if (Settings.version < 0x0606000A) { + uint8_t tuyaindex = 0; + if (Settings.param[P_BACKLOG_DELAY] > 0) { + Settings.tuya_fnid_map[tuyaindex].fnid = 21; + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_BACKLOG_DELAY]; + tuyaindex++; + } else if (Settings.flag3.fast_power_cycle_disable == 1) { + Settings.tuya_fnid_map[tuyaindex].fnid = 11; + Settings.tuya_fnid_map[tuyaindex].dpid = 1; + tuyaindex++; + } + if (Settings.param[P_ex_TUYA_RELAYS] > 0) { + for (uint8_t i = 0 ; i < Settings.param[P_ex_TUYA_RELAYS]; i++) { + Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; + Settings.tuya_fnid_map[tuyaindex].dpid = i + 2; + tuyaindex++; + } + } + if (Settings.param[P_ex_TUYA_POWER_ID] > 0) { + Settings.tuya_fnid_map[tuyaindex].fnid = 31; + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_POWER_ID]; + tuyaindex++; + } + if (Settings.param[P_ex_TUYA_VOLTAGE_ID] > 0) { + Settings.tuya_fnid_map[tuyaindex].fnid = 33; + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_VOLTAGE_ID]; + tuyaindex++; + } + if (Settings.param[P_ex_TUYA_CURRENT_ID] > 0) { + Settings.tuya_fnid_map[tuyaindex].fnid = 32; + Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_CURRENT_ID]; + } + } + if (Settings.version < 0x0606000C) { + memset((char*)&Settings +0x1D6, 0x00, 16); + } + if (Settings.version < 0x0606000F) { + Settings.ex_shutter_accuracy = 0; + Settings.ex_mqttlog_level = MQTT_LOG_LEVEL; + } + if (Settings.version < 0x06060011) { + Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; + } + if (Settings.version < 0x06060012) { + Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; + Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; + if (TUYA_DIMMER == Settings.module) { + if (Settings.flag3.ex_tuya_dimmer_min_limit) { + Settings.dimmer_hw_min = 25; + } else { + Settings.dimmer_hw_min = 1; + } + Settings.dimmer_hw_max = Settings.param[P_ex_DIMMER_MAX]; + } + else if (PS_16_DZ == Settings.module) { + Settings.dimmer_hw_min = 10; + Settings.dimmer_hw_max = Settings.param[P_ex_DIMMER_MAX]; + } + } + if (Settings.version < 0x06060014) { +# 1359 "S:/Development/Tasmota/tasmota/settings.ino" + Settings.flag3.fast_power_cycle_disable = 0; + Settings.energy_power_delta = Settings.ex_energy_power_delta; + Settings.ex_energy_power_delta = 0; + } + if (Settings.version < 0x06060015) { + if ((EX_WIFI_SMARTCONFIG == Settings.ex_sta_config) || (EX_WIFI_WPSCONFIG == Settings.ex_sta_config)) { + Settings.ex_sta_config = WIFI_MANAGER; + } + } + + if (Settings.version < 0x07000002) { + Settings.web_color2[0][0] = Settings.web_color[0][0]; + Settings.web_color2[0][1] = Settings.web_color[0][1]; + Settings.web_color2[0][2] = Settings.web_color[0][2]; + } + if (Settings.version < 0x07000003) { + SettingsEnableAllI2cDrivers(); + } + if (Settings.version < 0x07000004) { + Settings.ex_wifi_output_power = 170; + } + if (Settings.version < 0x07010202) { + Settings.ex_serial_config = TS_SERIAL_8N1; + } + if (Settings.version < 0x07010204) { + if (Settings.flag3.ex_cors_enabled == 1) { + strlcpy(Settings.ex_cors_domain, CORS_ENABLED_ALL, sizeof(Settings.ex_cors_domain)); + } else { + Settings.ex_cors_domain[0] = 0; + } + } + if (Settings.version < 0x07010205) { + Settings.seriallog_level = Settings.ex_seriallog_level; + Settings.sta_config = Settings.ex_sta_config; + Settings.sta_active = Settings.ex_sta_active; + memcpy((char*)&Settings.rule_stop, (char*)&Settings.ex_rule_stop, 47); + } + if (Settings.version < 0x07010206) { + Settings.flag4 = Settings.ex_flag4; + Settings.mqtt_port = Settings.ex_mqtt_port; + memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); + } + + if (Settings.version < 0x08000000) { + char temp[strlen(Settings.text_pool) +1]; strncpy(temp, Settings.text_pool, sizeof(temp)); + char temp21[strlen(Settings.ex_mqtt_prefix[0]) +1]; strncpy(temp21, Settings.ex_mqtt_prefix[0], sizeof(temp21)); + char temp22[strlen(Settings.ex_mqtt_prefix[1]) +1]; strncpy(temp22, Settings.ex_mqtt_prefix[1], sizeof(temp22)); + char temp23[strlen(Settings.ex_mqtt_prefix[2]) +1]; strncpy(temp23, Settings.ex_mqtt_prefix[2], sizeof(temp23)); + char temp31[strlen(Settings.ex_sta_ssid[0]) +1]; strncpy(temp31, Settings.ex_sta_ssid[0], sizeof(temp31)); + char temp32[strlen(Settings.ex_sta_ssid[1]) +1]; strncpy(temp32, Settings.ex_sta_ssid[1], sizeof(temp32)); + char temp41[strlen(Settings.ex_sta_pwd[0]) +1]; strncpy(temp41, Settings.ex_sta_pwd[0], sizeof(temp41)); + char temp42[strlen(Settings.ex_sta_pwd[1]) +1]; strncpy(temp42, Settings.ex_sta_pwd[1], sizeof(temp42)); + char temp5[strlen(Settings.ex_hostname) +1]; strncpy(temp5, Settings.ex_hostname, sizeof(temp5)); + char temp6[strlen(Settings.ex_syslog_host) +1]; strncpy(temp6, Settings.ex_syslog_host, sizeof(temp6)); + char temp7[strlen(Settings.ex_mqtt_host) +1]; strncpy(temp7, Settings.ex_mqtt_host, sizeof(temp7)); + char temp8[strlen(Settings.ex_mqtt_client) +1]; strncpy(temp8, Settings.ex_mqtt_client, sizeof(temp8)); + char temp9[strlen(Settings.ex_mqtt_user) +1]; strncpy(temp9, Settings.ex_mqtt_user, sizeof(temp9)); + char temp10[strlen(Settings.ex_mqtt_pwd) +1]; strncpy(temp10, Settings.ex_mqtt_pwd, sizeof(temp10)); + char temp11[strlen(Settings.ex_mqtt_topic) +1]; strncpy(temp11, Settings.ex_mqtt_topic, sizeof(temp11)); + char temp12[strlen(Settings.ex_button_topic) +1]; strncpy(temp12, Settings.ex_button_topic, sizeof(temp12)); + char temp13[strlen(Settings.ex_mqtt_grptopic) +1]; strncpy(temp13, Settings.ex_mqtt_grptopic, sizeof(temp13)); + + memset(Settings.text_pool, 0x00, settings_text_size); + SettingsUpdateText(SET_OTAURL, temp); + SettingsUpdateText(SET_MQTTPREFIX1, temp21); + SettingsUpdateText(SET_MQTTPREFIX2, temp22); + SettingsUpdateText(SET_MQTTPREFIX3, temp23); + SettingsUpdateText(SET_STASSID1, temp31); + SettingsUpdateText(SET_STASSID2, temp32); + SettingsUpdateText(SET_STAPWD1, temp41); + SettingsUpdateText(SET_STAPWD2, temp42); + SettingsUpdateText(SET_HOSTNAME, temp5); + SettingsUpdateText(SET_SYSLOG_HOST, temp6); +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + if (!strlen(Settings.ex_mqtt_user)) { + SettingsUpdateText(SET_MQTT_HOST, temp7); + SettingsUpdateText(SET_MQTT_USER, temp9); + } else { + char aws_mqtt_host[66]; + snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), temp9, temp7); + SettingsUpdateText(SET_MQTT_HOST, aws_mqtt_host); + SettingsUpdateText(SET_MQTT_USER, ""); + } +#else + SettingsUpdateText(SET_MQTT_HOST, temp7); + SettingsUpdateText(SET_MQTT_USER, temp9); +#endif + SettingsUpdateText(SET_MQTT_CLIENT, temp8); + SettingsUpdateText(SET_MQTT_PWD, temp10); + SettingsUpdateText(SET_MQTT_TOPIC, temp11); + SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); + SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); + + SettingsUpdateText(SET_WEBPWD, Settings.ex_web_password); + SettingsUpdateText(SET_CORS, Settings.ex_cors_domain); + SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.ex_mqtt_fulltopic); + SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.ex_switch_topic); + SettingsUpdateText(SET_STATE_TXT1, Settings.ex_state_text[0]); + SettingsUpdateText(SET_STATE_TXT2, Settings.ex_state_text[1]); + SettingsUpdateText(SET_STATE_TXT3, Settings.ex_state_text[2]); + SettingsUpdateText(SET_STATE_TXT4, Settings.ex_state_text[3]); + SettingsUpdateText(SET_NTPSERVER1, Settings.ex_ntp_server[0]); + SettingsUpdateText(SET_NTPSERVER2, Settings.ex_ntp_server[1]); + SettingsUpdateText(SET_NTPSERVER3, Settings.ex_ntp_server[2]); + SettingsUpdateText(SET_MEM1, Settings.script_pram[0]); + SettingsUpdateText(SET_MEM2, Settings.script_pram[1]); + SettingsUpdateText(SET_MEM3, Settings.script_pram[2]); + SettingsUpdateText(SET_MEM4, Settings.script_pram[3]); + SettingsUpdateText(SET_MEM5, Settings.script_pram[4]); + SettingsUpdateText(SET_FRIENDLYNAME1, Settings.ex_friendlyname[0]); + SettingsUpdateText(SET_FRIENDLYNAME2, Settings.ex_friendlyname[1]); + SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]); + SettingsUpdateText(SET_FRIENDLYNAME4, Settings.ex_friendlyname[3]); + } + + Settings.version = VERSION; + SettingsSave(1); + } +} +# 1 "S:/Development/Tasmota/tasmota/support.ino" +# 20 "S:/Development/Tasmota/tasmota/support.ino" +IPAddress syslog_host_addr; +uint32_t syslog_host_hash = 0; + +extern "C" { +extern struct rst_info resetInfo; +} + + + + + +#include + +Ticker tickerOSWatch; + +const uint32_t OSWATCH_RESET_TIME = 120; + +static unsigned long oswatch_last_loop_time; +uint8_t oswatch_blocked_loop = 0; + +#ifndef USE_WS2812_DMA + +#endif + +#ifdef USE_KNX +bool knx_started = false; +#endif + +void OsWatchTicker(void) +{ + uint32_t t = millis(); + uint32_t last_run = abs(t - oswatch_last_loop_time); + +#ifdef DEBUG_THEO + int32_t rssi = WiFi.RSSI(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(rssi), rssi, last_run); +#endif + if (last_run >= (OSWATCH_RESET_TIME * 1000)) { + + RtcSettings.oswatch_blocked_loop = 1; + RtcSettingsSave(); + + + + + + volatile uint32_t dummy; + dummy = *((uint32_t*) 0x00000000); + } +} + +void OsWatchInit(void) +{ + oswatch_blocked_loop = RtcSettings.oswatch_blocked_loop; + RtcSettings.oswatch_blocked_loop = 0; + oswatch_last_loop_time = millis(); + tickerOSWatch.attach_ms(((OSWATCH_RESET_TIME / 3) * 1000), OsWatchTicker); +} + +void OsWatchLoop(void) +{ + oswatch_last_loop_time = millis(); + +} + +bool OsWatchBlockedLoop(void) +{ + return oswatch_blocked_loop; +} + +uint32_t ResetReason(void) +{ +# 102 "S:/Development/Tasmota/tasmota/support.ino" + return resetInfo.reason; +} + +String GetResetReason(void) +{ + if (oswatch_blocked_loop) { + char buff[32]; + strncpy_P(buff, PSTR(D_JSON_BLOCKED_LOOP), sizeof(buff)); + return String(buff); + } else { + return ESP.getResetReason(); + } +} + + + + + + +size_t strchrspn(const char *str1, int character) +{ + size_t ret = 0; + char *start = (char*)str1; + char *end = strchr(str1, character); + if (end) ret = end - start; + return ret; +} + + +char* subStr(char* dest, char* str, const char *delim, int index) +{ + char *act; + char *sub = nullptr; + char *ptr; + int i; + + + strncpy(dest, str, strlen(str)+1); + for (i = 1, act = dest; i <= index; i++, act = nullptr) { + sub = strtok_r(act, delim, &ptr); + if (sub == nullptr) break; + } + sub = Trim(sub); + return sub; +} + +float CharToFloat(const char *str) +{ + + char strbuf[24]; + + strlcpy(strbuf, str, sizeof(strbuf)); + char *pt = strbuf; + while ((*pt != '\0') && isblank(*pt)) { pt++; } + + signed char sign = 1; + if (*pt == '-') { sign = -1; } + if (*pt == '-' || *pt=='+') { pt++; } + + float left = 0; + if (*pt != '.') { + left = atoi(pt); + while (isdigit(*pt)) { pt++; } + } + + float right = 0; + if (*pt == '.') { + pt++; + right = atoi(pt); + while (isdigit(*pt)) { + pt++; + right /= 10.0f; + } + } + + float result = left + right; + if (sign < 0) { + return -result; + } + return result; +} + +int TextToInt(char *str) +{ + char *p; + uint8_t radix = 10; + if ('#' == str[0]) { + radix = 16; + str++; + } + return strtol(str, &p, radix); +} + +char* ulltoa(unsigned long long value, char *str, int radix) +{ + char digits[64]; + char *dst = str; + int i = 0; + + + + do { + int n = value % radix; + digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; + value /= radix; + } while (value != 0); + + while (i > 0) { *dst++ = digits[--i]; } + + *dst = 0; + return str; +} + + + +char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween) +{ + + + + static const char * hex = "0123456789ABCDEF"; + int between = (inbetween) ? 3 : 2; + const unsigned char * pin = in; + char * pout = out; + for (; pin < in+insz; pout += between, pin++) { + pout[0] = hex[(pgm_read_byte(pin)>>4) & 0xF]; + pout[1] = hex[ pgm_read_byte(pin) & 0xF]; + if (inbetween) { pout[2] = inbetween; } + if (pout + 3 - out > outsz) { break; } + } + pout[(inbetween && insz) ? -1 : 0] = 0; + return out; +} + +char* Uint64toHex(uint64_t value, char *str, uint16_t bits) +{ + ulltoa(value, str, 16); + + int fill = 8; + if ((bits > 3) && (bits < 65)) { + fill = bits / 4; + if (bits % 4) { fill++; } + } + int len = strlen(str); + fill -= len; + if (fill > 0) { + memmove(str + fill, str, len +1); + memset(str, '0', fill); + } + return str; +} + +char* dtostrfd(double number, unsigned char prec, char *s) +{ + if ((isnan(number)) || (isinf(number))) { + strcpy(s, "null"); + return s; + } else { + return dtostrf(number, 1, prec, s); + } +} + +char* Unescape(char* buffer, uint32_t* size) +{ + uint8_t* read = (uint8_t*)buffer; + uint8_t* write = (uint8_t*)buffer; + int32_t start_size = *size; + int32_t end_size = *size; + uint8_t che = 0; + + + + while (start_size > 0) { + uint8_t ch = *read++; + start_size--; + if (ch != '\\') { + *write++ = ch; + } else { + if (start_size > 0) { + uint8_t chi = *read++; + start_size--; + end_size--; + switch (chi) { + case '\\': che = '\\'; break; + case 'a': che = '\a'; break; + case 'b': che = '\b'; break; + case 'e': che = '\e'; break; + case 'f': che = '\f'; break; + case 'n': che = '\n'; break; + case 'r': che = '\r'; break; + case 's': che = ' '; break; + case 't': che = '\t'; break; + case 'v': che = '\v'; break; + case 'x': { + uint8_t* start = read; + che = (uint8_t)strtol((const char*)read, (char**)&read, 16); + start_size -= (uint16_t)(read - start); + end_size -= (uint16_t)(read - start); + break; + } + case '"': che = '\"'; break; + + default : { + che = chi; + *write++ = ch; + end_size++; + } + } + *write++ = che; + } + } + } + *size = end_size; + *write++ = 0; + + + return buffer; +} + +char* RemoveSpace(char* p) +{ + char* write = p; + char* read = p; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + if (!isspace(ch)) { + *write++ = ch; + } + } + + return p; +} + +char* ReplaceCommaWithDot(char* p) +{ + char* write = (char*)p; + char* read = (char*)p; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + if (ch == ',') { + ch = '.'; + } + *write++ = ch; + } + return p; +} + +char* LowerCase(char* dest, const char* source) +{ + char* write = dest; + const char* read = source; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + *write++ = tolower(ch); + } + return dest; +} + +char* UpperCase(char* dest, const char* source) +{ + char* write = dest; + const char* read = source; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + *write++ = toupper(ch); + } + return dest; +} + +char* UpperCase_P(char* dest, const char* source) +{ + char* write = dest; + const char* read = source; + char ch = '.'; + + while (ch != '\0') { + ch = pgm_read_byte(read++); + *write++ = toupper(ch); + } + return dest; +} + +char* Trim(char* p) +{ + while ((*p != '\0') && isblank(*p)) { p++; } + char* q = p + strlen(p) -1; + while ((q >= p) && isblank(*q)) { q--; } + q++; + *q = '\0'; + return p; +} + +char* RemoveAllSpaces(char* p) +{ + + char *cursor = p; + uint32_t offset = 0; + while (1) { + *cursor = *(cursor + offset); + if ((' ' == *cursor) || ('\t' == *cursor) || ('\n' == *cursor)) { + offset++; + } else { + if (0 == *cursor) { break; } + cursor++; + } + } + return p; +} + +char* NoAlNumToUnderscore(char* dest, const char* source) +{ + char* write = dest; + const char* read = source; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + *write++ = (isalnum(ch) || ('\0' == ch)) ? ch : '_'; + } + return dest; +} + +char IndexSeparator(void) +{ + + + + + + + if (Settings.flag3.use_underscore) { + return '_'; + } else { + return '-'; + } +} + +void SetShortcutDefault(void) +{ + if ('\0' != XdrvMailbox.data[0]) { + XdrvMailbox.data[0] = '0' + SC_DEFAULT; + XdrvMailbox.data[1] = '\0'; + } +} + +uint8_t Shortcut(void) +{ + uint8_t result = 10; + + if ('\0' == XdrvMailbox.data[1]) { + if (('"' == XdrvMailbox.data[0]) || ('0' == XdrvMailbox.data[0])) { + result = SC_CLEAR; + } else { + result = atoi(XdrvMailbox.data); + if (0 == result) { + result = 10; + } + } + } + return result; +} + +bool ValidIpAddress(const char* str) +{ + const char* p = str; + + while (*p && ((*p == '.') || ((*p >= '0') && (*p <= '9')))) { p++; } + return (*p == '\0'); +} + +bool ParseIp(uint32_t* addr, const char* str) +{ + uint8_t *part = (uint8_t*)addr; + uint8_t i; + + *addr = 0; + for (i = 0; i < 4; i++) { + part[i] = strtoul(str, nullptr, 10); + str = strchr(str, '.'); + if (str == nullptr || *str == '\0') { + break; + } + str++; + } + return (3 == i); +} + +uint32_t ParseParameters(uint32_t count, uint32_t *params) +{ + char *p; + uint32_t i = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p), i++) { + params[i] = strtoul(str, nullptr, 0); + } + return i; +} + + +bool NewerVersion(char* version_str) +{ + uint32_t version = 0; + uint32_t i = 0; + char *str_ptr; + + char version_dup[strlen(version_str) +1]; + strncpy(version_dup, version_str, sizeof(version_dup)); + + for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(nullptr, ".", &str_ptr), i++) { + int field = atoi(str); + + if ((field < 0) || (field > 255)) { + return false; + } + + version = (version << 8) + field; + + if ((2 == i) && isalpha(str[strlen(str)-1])) { + field = str[strlen(str)-1] & 0x1f; + version = (version << 8) + field; + i++; + } + } + + + if ((i < 2) || (i > sizeof(VERSION))) { + return false; + } + + + while (i < sizeof(VERSION)) { + version <<= 8; + i++; + } + + return (version > VERSION); +} + +char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option) +{ + strncpy_P(dest, S_RSLT_POWER, size); + if ((devices_present + option) > 1) { + char sidx[8]; + snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); + strncat(dest, sidx, size - strlen(dest) -1); + } + return dest; +} + +char* GetPowerDevice(char* dest, uint32_t idx, size_t size) +{ + return GetPowerDevice(dest, idx, size, 0); +} + +void GetEspHardwareType(void) +{ + + uint32_t efuse1 = *(uint32_t*)(0x3FF00050); + uint32_t efuse2 = *(uint32_t*)(0x3FF00054); + + + + is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); + if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { + is_8285 = false; + } +} + +String GetDeviceHardware(void) +{ + char buff[10]; + if (is_8285) { + strcpy_P(buff, PSTR("ESP8285")); + } else { + strcpy_P(buff, PSTR("ESP8266EX")); + } + return String(buff); +} + +float ConvertTemp(float c) +{ + float result = c; + + global_update = uptime; + global_temperature = c; + + if (!isnan(c) && Settings.flag.temperature_conversion) { + result = c * 1.8 + 32; + } + result = result + (0.1 * Settings.temp_comp); + return result; +} + +float ConvertTempToCelsius(float c) +{ + float result = c; + + if (!isnan(c) && Settings.flag.temperature_conversion) { + result = (c - 32) / 1.8; + } + result = result + (0.1 * Settings.temp_comp); + return result; +} + +char TempUnit(void) +{ + return (Settings.flag.temperature_conversion) ? 'F' : 'C'; +} + +float ConvertHumidity(float h) +{ + global_update = uptime; + global_humidity = h; + + return h; +} + +float ConvertPressure(float p) +{ + float result = p; + + global_update = uptime; + global_pressure = p; + + if (!isnan(p) && Settings.flag.pressure_conversion) { + result = p * 0.75006375541921; + } + return result; +} + +String PressureUnit(void) +{ + return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); +} + +void ResetGlobalValues(void) +{ + if ((uptime - global_update) > GLOBAL_VALUES_VALID) { + global_update = 0; + global_temperature = 9999; + global_humidity = 0; + global_pressure = 0; + } +} + +uint32_t SqrtInt(uint32_t num) +{ + if (num <= 1) { + return num; + } + + uint32_t x = num / 2; + uint32_t y; + do { + y = (x + num / x) / 2; + if (y >= x) { + return x; + } + x = y; + } while (true); +} + +uint32_t RoundSqrtInt(uint32_t num) +{ + uint32_t s = SqrtInt(4 * num); + if (s & 1) { + s++; + } + return s / 2; +} + +char* GetTextIndexed(char* destination, size_t destination_size, uint32_t index, const char* haystack) +{ + + + char* write = destination; + const char* read = haystack; + + index++; + while (index--) { + size_t size = destination_size -1; + write = destination; + char ch = '.'; + while ((ch != '\0') && (ch != '|')) { + ch = pgm_read_byte(read++); + if (size && (ch != '|')) { + *write++ = ch; + size--; + } + } + if (0 == ch) { + if (index) { + write = destination; + } + break; + } + } + *write = '\0'; + return destination; +} + +int GetCommandCode(char* destination, size_t destination_size, const char* needle, const char* haystack) +{ + + + int result = -1; + const char* read = haystack; + char* write = destination; + + while (true) { + result++; + size_t size = destination_size -1; + write = destination; + char ch = '.'; + while ((ch != '\0') && (ch != '|')) { + ch = pgm_read_byte(read++); + if (size && (ch != '|')) { + *write++ = ch; + size--; + } + } + *write = '\0'; + if (!strcasecmp(needle, destination)) { + break; + } + if (0 == ch) { + result = -1; + break; + } + } + return result; +} + +bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void)) +{ + GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); + int prefix_length = strlen(XdrvMailbox.command); + if (prefix_length) { + char prefix[prefix_length +1]; + snprintf_P(prefix, sizeof(prefix), XdrvMailbox.topic); + if (strcasecmp(prefix, XdrvMailbox.command)) { + return false; + } + } + int command_code = GetCommandCode(XdrvMailbox.command + prefix_length, CMDSZ, XdrvMailbox.topic + prefix_length, haystack); + if (command_code > 0) { + XdrvMailbox.command_code = command_code -1; + MyCommand[XdrvMailbox.command_code](); + return true; + } + return false; +} + +const char kOptions[] PROGMEM = "OFF|" D_OFF "|FALSE|" D_FALSE "|STOP|" D_STOP "|" D_CELSIUS "|" + "ON|" D_ON "|TRUE|" D_TRUE "|START|" D_START "|" D_FAHRENHEIT "|" D_USER "|" + "TOGGLE|" D_TOGGLE "|" D_ADMIN "|" + "BLINK|" D_BLINK "|" + "BLINKOFF|" D_BLINKOFF "|" + "ALL" ; + +const uint8_t sNumbers[] PROGMEM = { 0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1, + 2,2,2, + 3,3, + 4,4, + 255 }; + +int GetStateNumber(char *state_text) +{ + char command[CMDSZ]; + int state_number = GetCommandCode(command, sizeof(command), state_text, kOptions); + if (state_number >= 0) { + state_number = pgm_read_byte(sNumbers + state_number); + } + return state_number; +} + +String GetSerialConfig(void) +{ + + + + + + const char kParity[] = "NEOI"; + + char config[4]; + config[0] = '5' + (Settings.serial_config & 0x3); + config[1] = kParity[(Settings.serial_config >> 3) & 0x3]; + config[2] = '1' + ((Settings.serial_config >> 2) & 0x1); + config[3] = '\0'; + return String(config); +} + +void SetSerialBegin() +{ + uint32_t baudrate = Settings.baudrate * 300; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_SERIAL "Set to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); + Serial.flush(); + Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); +} + +void SetSerialConfig(uint32_t serial_config) +{ + if (serial_config > TS_SERIAL_8O2) { + serial_config = TS_SERIAL_8N1; + } + if (serial_config != Settings.serial_config) { + Settings.serial_config = serial_config; + SetSerialBegin(); + } +} + +void SetSerialBaudrate(uint32_t baudrate) +{ + Settings.baudrate = baudrate / 300; + if (Serial.baudRate() != baudrate) { + SetSerialBegin(); + } +} + +void SetSerial(uint32_t baudrate, uint32_t serial_config) +{ + Settings.flag.mqtt_serial = 0; + Settings.serial_config = serial_config; + Settings.baudrate = baudrate / 300; + SetSeriallog(LOG_LEVEL_NONE); + SetSerialBegin(); +} + +void ClaimSerial(void) +{ + serial_local = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial")); + SetSeriallog(LOG_LEVEL_NONE); + Settings.baudrate = Serial.baudRate() / 300; +} + +void SerialSendRaw(char *codes) +{ + char *p; + char stemp[3]; + uint8_t code; + + int size = strlen(codes); + + while (size > 1) { + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, &p, 16); + Serial.write(code); + size -= 2; + codes += 2; + } +} + +uint32_t GetHash(const char *buffer, size_t size) +{ + uint32_t hash = 0; + for (uint32_t i = 0; i <= size; i++) { + hash += (uint8_t)*buffer++ * (i +1); + } + return hash; +} + +void ShowSource(uint32_t source) +{ + if ((source > 0) && (source < SRC_MAX)) { + char stemp1[20]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource)); + } +} + +void WebHexCode(uint32_t i, const char* code) +{ + char scolor[10]; + + strlcpy(scolor, code, sizeof(scolor)); + char* p = scolor; + if ('#' == p[0]) { p++; } + + if (3 == strlen(p)) { + p[6] = p[3]; + p[5] = p[2]; + p[4] = p[2]; + p[3] = p[1]; + p[2] = p[1]; + p[1] = p[0]; + } + + uint32_t color = strtol(p, nullptr, 16); + + + + + + + uint32_t j = sizeof(Settings.web_color) / 3; +# 917 "S:/Development/Tasmota/tasmota/support.ino" + if (i >= j) { + + i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); + } + Settings.web_color[i][0] = (color >> 16) & 0xFF; + Settings.web_color[i][1] = (color >> 8) & 0xFF; + Settings.web_color[i][2] = color & 0xFF; +} + +uint32_t WebColor(uint32_t i) +{ + uint32_t j = sizeof(Settings.web_color) / 3; + + + + + if (i >= j) { + + i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); + } + uint32_t tcolor = (Settings.web_color[i][0] << 16) | (Settings.web_color[i][1] << 8) | Settings.web_color[i][2]; + + return tcolor; +} + + + + + +const uint16_t TIMESZ = 100; + +char* ResponseGetTime(uint32_t format, char* time_str) +{ + switch (format) { + case 1: + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime()); + break; + case 2: + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":%u"), UtcTime()); + break; + default: + snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + } + return time_str; +} + +int Response_P(const char* format, ...) +{ + + va_list args; + va_start(args, format); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), format, args); + va_end(args); + return len; +} + +int ResponseTime_P(const char* format, ...) +{ + + va_list args; + va_start(args, format); + + ResponseGetTime(Settings.flag2.time_format, mqtt_data); + + int mlen = strlen(mqtt_data); + int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); + va_end(args); + return len + mlen; +} + +int ResponseAppend_P(const char* format, ...) +{ + + va_list args; + va_start(args, format); + int mlen = strlen(mqtt_data); + int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); + va_end(args); + return len + mlen; +} + +int ResponseAppendTimeFormat(uint32_t format) +{ + char time_str[TIMESZ]; + return ResponseAppend_P(ResponseGetTime(format, time_str)); +} + +int ResponseAppendTime(void) +{ + return ResponseAppendTimeFormat(Settings.flag2.time_format); +} + +int ResponseJsonEnd(void) +{ + return ResponseAppend_P(PSTR("}")); +} + +int ResponseJsonEndEnd(void) +{ + return ResponseAppend_P(PSTR("}}")); +} + + + + + +void DigitalWrite(uint32_t gpio_pin, uint32_t state) +{ + if (pin[gpio_pin] < 99) { + digitalWrite(pin[gpio_pin], state &1); + } +} + +uint8_t ModuleNr(void) +{ + + + return (USER_MODULE == Settings.module) ? 0 : Settings.module +1; +} + +bool ValidTemplateModule(uint32_t index) +{ + for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { + if (index == pgm_read_byte(kModuleNiceList + i)) { + return true; + } + } + return false; +} + +bool ValidModule(uint32_t index) +{ + if (index == USER_MODULE) { return true; } + return ValidTemplateModule(index); +} + +String AnyModuleName(uint32_t index) +{ + if (USER_MODULE == index) { + return String(Settings.user_template.name); + } else { + return FPSTR(kModules[index].name); + } +} + +String ModuleName(void) +{ + return AnyModuleName(Settings.module); +} + +void ModuleGpios(myio *gp) +{ + uint8_t *dest = (uint8_t *)gp; + memset(dest, GPIO_NONE, sizeof(myio)); + + uint8_t src[sizeof(mycfgio)]; + if (USER_MODULE == Settings.module) { + memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); + } else { + memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); + } + + + + + uint32_t j = 0; + for (uint32_t i = 0; i < sizeof(mycfgio); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + dest[j] = src[i]; + j++; + } + + + +} + +gpio_flag ModuleFlag(void) +{ + gpio_flag flag; + + if (USER_MODULE == Settings.module) { + flag = Settings.user_template.flag; + } else { + memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); + } + + return flag; +} + +void ModuleDefault(uint32_t module) +{ + if (USER_MODULE == module) { module = WEMOS; } + Settings.user_template_base = module; + memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); +} + +void SetModuleType(void) +{ + my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; +} + +bool FlashPin(uint32_t pin) +{ + return (((pin > 5) && (pin < 9)) || (11 == pin)); +} + +uint8_t ValidPin(uint32_t pin, uint32_t gpio) +{ + if (FlashPin(pin)) { + return GPIO_NONE; + } + + + if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { + if ((pin == 9) || (pin == 10)) { + return GPIO_NONE; + } + } + + return gpio; +} + +bool ValidGPIO(uint32_t pin, uint32_t gpio) +{ + return (GPIO_USER == ValidPin(pin, gpio)); +} + +bool ValidAdc(void) +{ + gpio_flag flag = ModuleFlag(); + uint32_t template_adc0 = flag.data &15; + return (ADC0_USER == template_adc0); +} + +bool GetUsedInModule(uint32_t val, uint8_t *arr) +{ + int offset = 0; + + if (!val) { return false; } + + if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { + offset = (GPIO_KEY1_NP - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_NP - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV - GPIO_KEY1); + } + if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { + offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); + } + + if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { + offset = (GPIO_SWT1_NP - GPIO_SWT1); + } + if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { + offset = -(GPIO_SWT1_NP - GPIO_SWT1); + } + + if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { + offset = (GPIO_REL1_INV - GPIO_REL1); + } + if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { + offset = -(GPIO_REL1_INV - GPIO_REL1); + } + + if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { + offset = (GPIO_LED1_INV - GPIO_LED1); + } + if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { + offset = -(GPIO_LED1_INV - GPIO_LED1); + } + + if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { + offset = (GPIO_PWM1_INV - GPIO_PWM1); + } + if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { + offset = -(GPIO_PWM1_INV - GPIO_PWM1); + } + + if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { + offset = (GPIO_CNTR1_NP - GPIO_CNTR1); + } + if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { + offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); + } + + for (uint32_t i = 0; i < MAX_GPIO_PIN; i++) { + if (arr[i] == val) { return true; } + if (arr[i] == val + offset) { return true; } + } + return false; +} + +bool JsonTemplate(const char* dataBuf) +{ + + + if (strlen(dataBuf) < 9) { return false; } + + StaticJsonBuffer<350> jb; + JsonObject& obj = jb.parseObject(dataBuf); + if (!obj.success()) { return false; } + + + const char* name = obj[D_JSON_NAME]; + if (name != nullptr) { + strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name)); + } + if (obj[D_JSON_GPIO].success()) { + for (uint32_t i = 0; i < sizeof(mycfgio); i++) { + Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0; + } + } + if (obj[D_JSON_FLAG].success()) { + uint8_t flag = obj[D_JSON_FLAG] | 0; + memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag)); + } + if (obj[D_JSON_BASE].success()) { + uint8_t base = obj[D_JSON_BASE]; + if ((0 == base) || !ValidTemplateModule(base -1)) { base = 18; } + Settings.user_template_base = base -1; + } + return true; +} + +void TemplateJson(void) +{ + Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); + for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); + } + ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); +} + + + + + +inline int32_t TimeDifference(uint32_t prev, uint32_t next) +{ + return ((int32_t) (next - prev)); +} + +int32_t TimePassedSince(uint32_t timestamp) +{ + + + return TimeDifference(timestamp, millis()); +} + +bool TimeReached(uint32_t timer) +{ + + const long passed = TimePassedSince(timer); + return (passed >= 0); +} + +void SetNextTimeInterval(unsigned long& timer, const unsigned long step) +{ + timer += step; + const long passed = TimePassedSince(timer); + if (passed < 0) { return; } + if (static_cast(passed) > step) { + + timer = millis() + step; + return; + } + + timer = millis() + (step - passed); +} + +int32_t TimePassedSinceUsec(uint32_t timestamp) +{ + return TimeDifference(timestamp, micros()); +} + +bool TimeReachedUsec(uint32_t timer) +{ + + const long passed = TimePassedSinceUsec(timer); + return (passed >= 0); +} + + + + + +#ifdef USE_I2C +const uint8_t I2C_RETRY_COUNTER = 3; + +uint32_t i2c_active[4] = { 0 }; +uint32_t i2c_buffer = 0; + +bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size) +{ + uint8_t retry = I2C_RETRY_COUNTER; + bool status = false; + + i2c_buffer = 0; + while (!status && retry) { + Wire.beginTransmission(addr); + Wire.write(reg); + if (0 == Wire.endTransmission(false)) { + Wire.requestFrom((int)addr, (int)size); + if (Wire.available() == size) { + for (uint32_t i = 0; i < size; i++) { + i2c_buffer = i2c_buffer << 8 | Wire.read(); + } + status = true; + } + } + retry--; + } + return status; +} + +bool I2cValidRead8(uint8_t *data, uint8_t addr, uint8_t reg) +{ + bool status = I2cValidRead(addr, reg, 1); + *data = (uint8_t)i2c_buffer; + return status; +} + +bool I2cValidRead16(uint16_t *data, uint8_t addr, uint8_t reg) +{ + bool status = I2cValidRead(addr, reg, 2); + *data = (uint16_t)i2c_buffer; + return status; +} + +bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg) +{ + bool status = I2cValidRead(addr, reg, 2); + *data = (int16_t)i2c_buffer; + return status; +} + +bool I2cValidRead16LE(uint16_t *data, uint8_t addr, uint8_t reg) +{ + uint16_t ldata; + bool status = I2cValidRead16(&ldata, addr, reg); + *data = (ldata >> 8) | (ldata << 8); + return status; +} + +bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg) +{ + uint16_t ldata; + bool status = I2cValidRead16LE(&ldata, addr, reg); + *data = (int16_t)ldata; + return status; +} + +bool I2cValidRead24(int32_t *data, uint8_t addr, uint8_t reg) +{ + bool status = I2cValidRead(addr, reg, 3); + *data = i2c_buffer; + return status; +} + +uint8_t I2cRead8(uint8_t addr, uint8_t reg) +{ + I2cValidRead(addr, reg, 1); + return (uint8_t)i2c_buffer; +} + +uint16_t I2cRead16(uint8_t addr, uint8_t reg) +{ + I2cValidRead(addr, reg, 2); + return (uint16_t)i2c_buffer; +} + +int16_t I2cReadS16(uint8_t addr, uint8_t reg) +{ + I2cValidRead(addr, reg, 2); + return (int16_t)i2c_buffer; +} + +uint16_t I2cRead16LE(uint8_t addr, uint8_t reg) +{ + I2cValidRead(addr, reg, 2); + uint16_t temp = (uint16_t)i2c_buffer; + return (temp >> 8) | (temp << 8); +} + +int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg) +{ + return (int16_t)I2cRead16LE(addr, reg); +} + +int32_t I2cRead24(uint8_t addr, uint8_t reg) +{ + I2cValidRead(addr, reg, 3); + return i2c_buffer; +} + +bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size) +{ + uint8_t x = I2C_RETRY_COUNTER; + + do { + Wire.beginTransmission((uint8_t)addr); + Wire.write(reg); + uint8_t bytes = size; + while (bytes--) { + Wire.write((val >> (8 * bytes)) & 0xFF); + } + x--; + } while (Wire.endTransmission(true) != 0 && x != 0); + return (x); +} + +bool I2cWrite8(uint8_t addr, uint8_t reg, uint16_t val) +{ + return I2cWrite(addr, reg, val, 1); +} + +bool I2cWrite16(uint8_t addr, uint8_t reg, uint16_t val) +{ + return I2cWrite(addr, reg, val, 2); +} + +int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) +{ + Wire.beginTransmission((uint8_t)addr); + Wire.write((uint8_t)reg); + Wire.endTransmission(); + if (len != Wire.requestFrom((uint8_t)addr, (uint8_t)len)) { + return 1; + } + while (len--) { + *reg_data = (uint8_t)Wire.read(); + reg_data++; + } + return 0; +} + +int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) +{ + Wire.beginTransmission((uint8_t)addr); + Wire.write((uint8_t)reg); + while (len--) { + Wire.write(*reg_data); + reg_data++; + } + Wire.endTransmission(); + return 0; +} + +void I2cScan(char *devs, unsigned int devs_len) +{ + + + + + + + + uint8_t error = 0; + uint8_t address = 0; + uint8_t any = 0; + + snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_DEVICES_FOUND_AT)); + for (address = 1; address <= 127; address++) { + Wire.beginTransmission(address); + error = Wire.endTransmission(); + if (0 == error) { + any = 1; + snprintf_P(devs, devs_len, PSTR("%s 0x%02x"), devs, address); + } + else if (error != 2) { + any = 2; + snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"Error %d at 0x%02x"), error, address); + break; + } + } + if (any) { + strncat(devs, "\"}", devs_len - strlen(devs) -1); + } + else { + snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_NO_DEVICES_FOUND "\"}")); + } +} + +void I2cResetActive(uint32_t addr, uint32_t count = 1) +{ + addr &= 0x7F; + count &= 0x7F; + while (count-- && (addr < 128)) { + i2c_active[addr / 32] &= ~(1 << (addr % 32)); + addr++; + } + +} + +void I2cSetActive(uint32_t addr, uint32_t count = 1) +{ + addr &= 0x7F; + count &= 0x7F; + while (count-- && (addr < 128)) { + i2c_active[addr / 32] |= (1 << (addr % 32)); + addr++; + } + +} + +void I2cSetActiveFound(uint32_t addr, const char *types) +{ + I2cSetActive(addr); + AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, types, addr); +} + +bool I2cActive(uint32_t addr) +{ + addr &= 0x7F; + if (i2c_active[addr / 32] & (1 << (addr % 32))) { + return true; + } + return false; +} + +bool I2cSetDevice(uint32_t addr) +{ + addr &= 0x7F; + if (I2cActive(addr)) { + return false; + } + Wire.beginTransmission((uint8_t)addr); + return (0 == Wire.endTransmission()); +} +#endif +# 1560 "S:/Development/Tasmota/tasmota/support.ino" +void SetSeriallog(uint32_t loglevel) +{ + Settings.seriallog_level = loglevel; + seriallog_level = loglevel; + seriallog_timer = 0; +} + +void SetSyslog(uint32_t loglevel) +{ + Settings.syslog_level = loglevel; + syslog_level = loglevel; + syslog_timer = 0; +} + +#ifdef USE_WEBSERVER +void GetLog(uint32_t idx, char** entry_pp, size_t* len_p) +{ + char* entry_p = nullptr; + size_t len = 0; + + if (idx) { + char* it = web_log; + do { + uint32_t cur_idx = *it; + it++; + size_t tmp = strchrspn(it, '\1'); + tmp++; + if (cur_idx == idx) { + len = tmp; + entry_p = it; + break; + } + it += tmp; + } while (it < web_log + WEB_LOG_SIZE && *it != '\0'); + } + *entry_pp = entry_p; + *len_p = len; +} +#endif + +void Syslog(void) +{ + + + uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); + if (syslog_host_hash != current_hash) { + syslog_host_hash = current_hash; + WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); + } + if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { + char syslog_preamble[64]; + snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), my_hostname); + memmove(log_data + strlen(syslog_preamble), log_data, sizeof(log_data) - strlen(syslog_preamble)); + log_data[sizeof(log_data) -1] = '\0'; + memcpy(log_data, syslog_preamble, strlen(syslog_preamble)); + PortUdp.write(log_data, strlen(log_data)); + PortUdp.endPacket(); + delay(1); + } else { + syslog_level = 0; + syslog_timer = SYSLOG_TIMER; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER); + } +} + +void AddLog(uint32_t loglevel) +{ + char mxtime[10]; + + snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d "), RtcTime.hour, RtcTime.minute, RtcTime.second); + + if (loglevel <= seriallog_level) { + Serial.printf("%s%s\r\n", mxtime, log_data); + } +#ifdef USE_WEBSERVER + if (Settings.webserver && (loglevel <= Settings.weblog_level)) { + + + web_log_index &= 0xFF; + if (!web_log_index) web_log_index++; + while (web_log_index == web_log[0] || + strlen(web_log) + strlen(log_data) + 13 > WEB_LOG_SIZE) + { + char* it = web_log; + it++; + it += strchrspn(it, '\1'); + it++; + memmove(web_log, it, WEB_LOG_SIZE -(it-web_log)); + } + snprintf_P(web_log, sizeof(web_log), PSTR("%s%c%s%s\1"), web_log, web_log_index++, mxtime, log_data); + web_log_index &= 0xFF; + if (!web_log_index) web_log_index++; + } +#endif + if (Settings.flag.mqtt_enabled && + !global_state.mqtt_down && + (loglevel <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } + + if (!global_state.wifi_down && + (loglevel <= syslog_level)) { Syslog(); } +} + +void AddLog_P(uint32_t loglevel, const char *formatP) +{ + snprintf_P(log_data, sizeof(log_data), formatP); + AddLog(loglevel); +} + +void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2) +{ + char message[sizeof(log_data)]; + + snprintf_P(log_data, sizeof(log_data), formatP); + snprintf_P(message, sizeof(message), formatP2); + strncat(log_data, message, sizeof(log_data) - strlen(log_data) -1); + AddLog(loglevel); +} + +void PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...) +{ + va_list arg; + va_start(arg, formatP); + vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + va_end(arg); + + prepped_loglevel = loglevel; +} + +void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...) +{ + va_list arg; + va_start(arg, formatP); + vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + va_end(arg); + + AddLog(loglevel); +} + +void AddLog_Debug(PGM_P formatP, ...) +{ + va_list arg; + va_start(arg, formatP); + vsnprintf_P(log_data, sizeof(log_data), formatP, arg); + va_end(arg); + + AddLog(LOG_LEVEL_DEBUG); +} + +void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count) +{ +# 1722 "S:/Development/Tasmota/tasmota/support.ino" + char hex_char[(count * 3) + 2]; + AddLog_P2(loglevel, PSTR("DMP: %s"), ToHex_P(buffer, count, hex_char, sizeof(hex_char), ' ')); +} + +void AddLogSerial(uint32_t loglevel) +{ + AddLogBuffer(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); +} + +void AddLogMissed(char *sensor, uint32_t misses) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); +} +# 1 "S:/Development/Tasmota/tasmota/support_button.ino" +# 20 "S:/Development/Tasmota/tasmota/support_button.ino" +#define BUTTON_V1 +#ifdef BUTTON_V1 + + + + +#define MAX_BUTTON_COMMANDS 5 +const char kCommands[] PROGMEM = + D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; + +struct BUTTON { + unsigned long debounce = 0; + uint16_t hold_timer[MAX_KEYS] = { 0 }; + uint16_t dual_code = 0; + + uint8_t last_state[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; + uint8_t window_timer[MAX_KEYS] = { 0 }; + uint8_t press_counter[MAX_KEYS] = { 0 }; + + uint8_t dual_receive_count = 0; + uint8_t no_pullup_mask = 0; + uint8_t inverted_mask = 0; + uint8_t present = 0; + uint8_t adc = 99; +} Button; + + + +void ButtonPullupFlag(uint8 button_bit) +{ + bitSet(Button.no_pullup_mask, button_bit); +} + +void ButtonInvertFlag(uint8 button_bit) +{ + bitSet(Button.inverted_mask, button_bit); +} + +void ButtonInit(void) +{ + Button.present = 0; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if (pin[GPIO_KEY1 +i] < 99) { + Button.present++; + pinMode(pin[GPIO_KEY1 +i], bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); + } +#ifndef USE_ADC_VCC + else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) { + Button.present++; + Button.adc = i; + } +#endif + } +} + +uint8_t ButtonSerial(uint8_t serial_in_byte) +{ + if (Button.dual_receive_count) { + Button.dual_receive_count--; + if (Button.dual_receive_count) { + Button.dual_code = (Button.dual_code << 8) | serial_in_byte; + serial_in_byte = 0; + } else { + if (serial_in_byte != 0xA1) { + Button.dual_code = 0; + } + } + } + if (0xA0 == serial_in_byte) { + serial_in_byte = 0; + Button.dual_code = 0; + Button.dual_receive_count = 3; + } + + return serial_in_byte; +} +# 108 "S:/Development/Tasmota/tasmota/support_button.ino" +void ButtonHandler(void) +{ + if (uptime < 4) { return; } + + uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; + uint16_t loops_per_second = 1000 / Settings.button_debounce; + char scmnd[20]; + + + + for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { + uint8_t button = NOT_PRESSED; + uint8_t button_present = 0; + + if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { + button_present = 1; + if (Button.dual_code) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code); + button = PRESSED; + if (0xF500 == Button.dual_code) { + Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; + hold_time_extent = 1; + } + Button.dual_code = 0; + } + } + else if (pin[GPIO_KEY1 +button_index] < 99) { + button_present = 1; + button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(Button.inverted_mask, button_index)); + } +#ifndef USE_ADC_VCC + if (Button.adc == button_index) { + button_present = 1; + if (ADC0_BUTTON_INV == my_adc0) { + button = (AdcRead(1) < 128); + } + else if (ADC0_BUTTON == my_adc0) { + button = (AdcRead(1) > 128); + } + } +#endif + + if (button_present) { + XdrvMailbox.index = button_index; + XdrvMailbox.payload = button; + if (XdrvCall(FUNC_BUTTON_PRESSED)) { + + } + else if (SONOFF_4CHPRO == my_module_type) { + if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; } + + bool button_pressed = false; + if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); + Button.hold_timer[button_index] = loops_per_second; + button_pressed = true; + } + if ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index])) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); + if (!Button.hold_timer[button_index]) { button_pressed = true; } + } + if (button_pressed) { + if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { + ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); + } + } + } + else { + if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { + if (Settings.flag.button_single) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); + if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { + ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); + } + } else { + Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]); + Button.window_timer[button_index] = loops_per_second / 2; + } + blinks = 201; + } + + if (NOT_PRESSED == button) { + Button.hold_timer[button_index] = 0; + } else { + Button.hold_timer[button_index]++; + if (Settings.flag.button_single) { + if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } else { + if (Settings.flag.button_restrict) { + if (Settings.param[P_HOLD_IGNORE] > 0) { + if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { + Button.hold_timer[button_index] = 0; + Button.press_counter[button_index] = 0; + DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]); + } + } + if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { + Button.press_counter[button_index] = 0; + SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); + } + } else { + if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { + Button.press_counter[button_index] = 0; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + } + } + + if (!Settings.flag.button_single) { + if (Button.window_timer[button_index]) { + Button.window_timer[button_index]--; + } else { + if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS +3)) { + bool single_press = false; + if (Button.press_counter[button_index] < 3) { + if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + single_press = true; + } else { + single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); + if ((1 == Button.present) && (2 == devices_present)) { + if (Settings.flag.button_swap) { + Button.press_counter[button_index] = (single_press) ? 1 : 2; + } + } else { + Button.press_counter[button_index] = 1; + } + } + } +#if defined(USE_LIGHT) && defined(ROTARY_V1) + if (!((0 == button_index) && RotaryButtonPressed())) { +#endif + if (single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { + + } else { + if (Button.press_counter[button_index] < 3) { + if (WifiState() > WIFI_RESTART) { + restart_flag = 1; + } else { + ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); + } + } else { + if (!Settings.flag.button_restrict) { + GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -3, kCommands); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + } +#if defined(USE_LIGHT) && defined(ROTARY_V1) + } +#endif + Button.press_counter[button_index] = 0; + } + } + } + } + } + Button.last_state[button_index] = button; + } +} + +void ButtonLoop(void) +{ + if (Button.present) { + if (TimeReached(Button.debounce)) { + SetNextTimeInterval(Button.debounce, Settings.button_debounce); + ButtonHandler(); + } + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/support_command.ino" +# 20 "S:/Development/Tasmota/tasmota/support_command.ino" +const char kTasmotaCommands[] PROGMEM = "|" + D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" + D_CMND_SERIALLOG "|" D_CMND_RESTART "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|" + D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" + D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" + D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" + D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|" + D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" + D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" + D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" +#ifdef USE_I2C + D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" +#endif +#ifdef USE_DEVICE_GROUPS + D_CMND_DEVGROUP_SHARE "|" +#endif + D_CMND_SENSOR "|" D_CMND_DRIVER; + +void (* const TasmotaCommand[])(void) PROGMEM = { + &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, + &CmndSeriallog, &CmndRestart, &CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata, + &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, + &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, + &CmndModule, &CmndModules, &CmndGpio, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange, + &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig, + &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, + &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, + &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, +#ifdef USE_I2C + &CmndI2cScan, CmndI2cDriver, +#endif +#ifdef USE_DEVICE_GROUPS + &CmndDevGroupShare, +#endif + &CmndSensor, &CmndDriver }; + +const char kWifiConfig[] PROGMEM = + D_WCFG_0_RESTART "||" D_WCFG_2_WIFIMANAGER "||" D_WCFG_4_RETRY "|" D_WCFG_5_WAIT "|" D_WCFG_6_SERIAL "|" D_WCFG_7_WIFIMANAGER_RESET_ONLY; + + + +void ResponseCmndNumber(int value) +{ + Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, value); +} + +void ResponseCmndFloat(float value, uint32_t decimals) +{ + char stemp1[TOPSZ]; + dtostrfd(value, decimals, stemp1); + Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp1); +} + +void ResponseCmndIdxNumber(int value) +{ + Response_P(S_JSON_COMMAND_INDEX_NVALUE, XdrvMailbox.command, XdrvMailbox.index, value); +} + +void ResponseCmndChar(const char* value) +{ + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, value); +} + +void ResponseCmndStateText(uint32_t value) +{ + ResponseCmndChar(GetStateText(value)); +} + +void ResponseCmndDone(void) +{ + ResponseCmndChar(D_JSON_DONE); +} + +void ResponseCmndIdxChar(const char* value) +{ + Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, value); +} + +void ResponseCmndAll(uint32_t text_index, uint32_t count) +{ + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < count; i++) { + ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, SettingsText(text_index +i)); + } + ResponseJsonEnd(); +} + + + +void ExecuteCommand(const char *cmnd, uint32_t source) +{ + + + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("ExecuteCommand")); +#endif + ShowSource(source); + + const char *pos = cmnd; + while (*pos && isspace(*pos)) { + pos++; + } + + const char *start = pos; + + while (*pos && (isalpha(*pos) || isdigit(*pos) || '_' == *pos || '/' == *pos)) { + if ('/' == *pos) { + start = pos + 1; + } + pos++; + } + if ('\0' == *start || pos <= start) { + return; + } + + uint32_t size = pos - start; + char stopic[size + 2]; + stopic[0] = '/'; + memcpy(stopic+1, start, size); + stopic[size+1] = '\0'; + + char svalue[strlen(pos) +1]; + strlcpy(svalue, pos, sizeof(svalue)); + CommandHandler(stopic, svalue, strlen(svalue)); +} +# 154 "S:/Development/Tasmota/tasmota/support_command.ino" +void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) +{ +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("CommandHandler")); +#endif + + while (*dataBuf && isspace(*dataBuf)) { + dataBuf++; + data_len--; + } + + bool grpflg = (strstr(topicBuf, SettingsText(SET_MQTT_GRP_TOPIC)) != nullptr); + + char stemp1[TOPSZ]; + GetFallbackTopic_P(stemp1, ""); + fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); + + char *type = strrchr(topicBuf, '/'); + + uint32_t index = 1; + bool user_index = false; + if (type != nullptr) { + type++; + uint32_t i; + for (i = 0; i < strlen(type); i++) { + type[i] = toupper(type[i]); + } + while (isdigit(type[i-1])) { + i--; + } + if (i < strlen(type)) { + index = atoi(type +i); + user_index = true; + } + type[i] = '\0'; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf); + + if (type != nullptr) { + Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); + + if (Settings.ledstate &0x02) { blinks++; } + + if (!strcmp(dataBuf,"?")) { data_len = 0; } + + char *p; + int32_t payload = strtol(dataBuf, &p, 0); + if (p == dataBuf) { payload = -99; } + int temp_payload = GetStateNumber(dataBuf); + if (temp_payload > -1) { payload = temp_payload; } + + DEBUG_CORE_LOG(PSTR("CMD: Payload %d"), payload); + + + backlog_delay = millis() + Settings.param[P_BACKLOG_DELAY]; + + char command[CMDSZ] = { 0 }; + XdrvMailbox.command = command; + XdrvMailbox.index = index; + XdrvMailbox.data_len = data_len; + XdrvMailbox.payload = payload; + XdrvMailbox.grpflg = grpflg; + XdrvMailbox.usridx = user_index; + XdrvMailbox.topic = type; + XdrvMailbox.data = dataBuf; + +#ifdef USE_SCRIPT_SUB_COMMAND + + if (!Script_SubCmd()) { + if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { + if (!XdrvCall(FUNC_COMMAND)) { + if (!XsnsCall(FUNC_COMMAND)) { + type = nullptr; + } + } + } + } +#else + if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { + if (!XdrvCall(FUNC_COMMAND)) { + if (!XsnsCall(FUNC_COMMAND)) { + type = nullptr; + } + } + } +#endif + + } + + if (type == nullptr) { + blinks = 201; + snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_COMMAND)); + Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); + type = (char*)stemp1; + } + + if (mqtt_data[0] != '\0') { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); + XdrvRulesProcess(); + } + fallback_topic_flag = false; +} + + + +void CmndBacklog(void) +{ + if (XdrvMailbox.data_len) { + +#ifdef SUPPORT_IF_STATEMENT + char *blcommand = strtok(XdrvMailbox.data, ";"); + while ((blcommand != nullptr) && (backlog.size() < MAX_BACKLOG)) +#else + uint32_t bl_pointer = (!backlog_pointer) ? MAX_BACKLOG -1 : backlog_pointer; + bl_pointer--; + char *blcommand = strtok(XdrvMailbox.data, ";"); + while ((blcommand != nullptr) && (backlog_index != bl_pointer)) +#endif + { + while(true) { + blcommand = Trim(blcommand); + if (!strncasecmp_P(blcommand, PSTR(D_CMND_BACKLOG), strlen(D_CMND_BACKLOG))) { + blcommand += strlen(D_CMND_BACKLOG); + } else { + break; + } + } + if (*blcommand != '\0') { +#ifdef SUPPORT_IF_STATEMENT + if (backlog.size() < MAX_BACKLOG) { + backlog.add(blcommand); + } +#else + backlog[backlog_index] = String(blcommand); + backlog_index++; + if (backlog_index >= MAX_BACKLOG) backlog_index = 0; +#endif + } + blcommand = strtok(nullptr, ";"); + } + + mqtt_data[0] = '\0'; + } else { + bool blflag = BACKLOG_EMPTY; +#ifdef SUPPORT_IF_STATEMENT + backlog.clear(); +#else + backlog_pointer = backlog_index; +#endif + ResponseCmndChar(blflag ? D_JSON_EMPTY : D_JSON_ABORTED); + } +} + +void CmndDelay(void) +{ + if ((XdrvMailbox.payload >= (MIN_BACKLOG_DELAY / 100)) && (XdrvMailbox.payload <= 3600)) { + backlog_delay = millis() + (100 * XdrvMailbox.payload); + } + uint32_t bl_delay = 0; + long bl_delta = TimePassedSince(backlog_delay); + if (bl_delta < 0) { bl_delay = (bl_delta *-1) / 100; } + ResponseCmndNumber(bl_delay); +} + +void CmndPower(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) { + if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_BLINK_STOP)) { + XdrvMailbox.payload = POWER_SHOW_STATE; + } + + ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE); + mqtt_data[0] = '\0'; + } + else if (0 == XdrvMailbox.index) { + if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_TOGGLE)) { + XdrvMailbox.payload = POWER_SHOW_STATE; + } + SetAllPower(XdrvMailbox.payload, SRC_IGNORE); + mqtt_data[0] = '\0'; + } +} + +void CmndStatus(void) +{ + uint32_t payload = ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > MAX_STATUS)) ? 99 : XdrvMailbox.payload; + + uint32_t option = STAT; + char stemp[200]; + char stemp2[TOPSZ]; + + + + + + if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } + if (!energy_flg && (9 == payload)) { payload = 99; } + if (!CrashFlag() && (12 == payload)) { payload = 99; } + + if ((0 == payload) || (99 == payload)) { + uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { maxfn = 1; } +#endif + stemp[0] = '\0'; + for (uint32_t i = 0; i < maxfn; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), SettingsText(SET_FRIENDLYNAME1 +i)); + } + stemp2[0] = '\0'; + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); + } + Response_P(PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d,\"" D_CMND_FRIENDLYNAME "\":[%s],\"" D_CMND_TOPIC "\":\"%s\",\"" + D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" + D_CMND_LEDMASK "\":\"%04X\",\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" + D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), + ModuleNr(), stemp, mqtt_topic, + SettingsText(SET_MQTT_BUTTON_TOPIC), power, Settings.poweronstate, Settings.ledstate, + Settings.ledmask, Settings.save_data, + Settings.flag.save_state, + SettingsText(SET_MQTT_SWITCH_TOPIC), + stemp2, + Settings.flag.mqtt_button_retain, + Settings.flag.mqtt_switch_retain, + Settings.flag.mqtt_sensor_retain, + Settings.flag.mqtt_power_retain); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); + } + + if ((0 == payload) || (1 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_SERIALCONFIG "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" + D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" + D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"BCResetTime\":\"%s\",\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), + Settings.baudrate * 300, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), + GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, + Settings.cfg_holder, Settings.bootcount, GetDateAndTime(DT_BOOTCOUNT).c_str(), Settings.save_flag, GetSettingsAddress()); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); + } + + if ((0 == payload) || (2 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" + D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," + "\"Hardware\":\"%s\"" + "%s}}"), + my_version, my_image, GetBuildDateAndTime().c_str(), + ESP.getBootVersion(), ESP.getSdkVersion(), + GetDeviceHardware().c_str(), + GetStatistics().c_str()); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); + } + + if ((0 == payload) || (3 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" + D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" + D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\"]}}"), + Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, + SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), Settings.tele_period, + Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), + Settings.flag3.data, Settings.flag4.data); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3")); + } + + if ((0 == payload) || (4 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" + D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" + D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), + ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, + ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(), + LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6); + XsnsDriverState(); + ResponseAppend_P(PSTR(",\"Sensors\":")); + XsnsSensorState(); + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4")); + } + + if ((0 == payload) || (5 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\"" + D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" + D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"), + my_hostname, WiFi.localIP().toString().c_str(), IPAddress(Settings.ip_address[1]).toString().c_str(), + IPAddress(Settings.ip_address[2]).toString().c_str(), IPAddress(Settings.ip_address[3]).toString().c_str(), WiFi.macAddress().c_str(), + Settings.webserver, Settings.sta_config, WifiGetOutputPower().c_str()); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "5")); + } + + if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" + D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), + mqtt_client, SettingsText(SET_MQTT_USER), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); + } + + if ((0 == payload) || (7 == payload)) { + if (99 == Settings.timezone) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d" ), Settings.timezone); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"%s\"" ), GetTimeZone().c_str()); + } +#if defined(USE_TIMERS) && defined(USE_SUNRISE) + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" + D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), + GetDateAndTime(DT_STD).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); +#else + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" + D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), + GetDateAndTime(DT_STD).c_str(), stemp); +#endif + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); + } + +#if defined(USE_ENERGY_SENSOR) && defined(USE_ENERGY_MARGIN_DETECTION) + if (energy_flg) { + if ((0 == payload) || (9 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":%d,\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" + D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), + Settings.energy_power_delta, Settings.energy_min_power, Settings.energy_max_power, + Settings.energy_min_voltage, Settings.energy_max_voltage, Settings.energy_min_current, Settings.energy_max_current); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "9")); + } + } +#endif + + if ((0 == payload) || (8 == payload) || (10 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); + MqttShowSensor(); + ResponseJsonEnd(); + if (8 == payload) { + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "8")); + } else { + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "10")); + } + } + + if ((0 == payload) || (11 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); + MqttShowState(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); + } + + if (CrashFlag()) { + if ((0 == payload) || (12 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); + CrashDump(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); + } + } + +#ifdef USE_SCRIPT_STATUS + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); +#endif + mqtt_data[0] = '\0'; +} + +void CmndState(void) +{ + mqtt_data[0] = '\0'; + MqttShowState(); + if (Settings.flag3.hass_tele_on_power) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); + } +#ifdef USE_HOME_ASSISTANT + if (Settings.flag.hass_discovery) { + HAssPublishStatus(); + } +#endif +} + +void CmndTempOffset(void) +{ + if (XdrvMailbox.data_len > 0) { + int value = (int)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > -127) && (value < 127)) { + Settings.temp_comp = value; + } + } + ResponseCmndFloat((float)(Settings.temp_comp) / 10, 1); +} + +void CmndSleep(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) { + Settings.sleep = XdrvMailbox.payload; + sleep = XdrvMailbox.payload; + WiFiSetSleepMode(); + } + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, sleep); + +} + +void CmndUpgrade(void) +{ + + + + + if (((1 == XdrvMailbox.data_len) && (1 == XdrvMailbox.payload)) || ((XdrvMailbox.data_len >= 3) && NewerVersion(XdrvMailbox.data))) { + ota_state_flag = 3; + char stemp1[TOPSZ]; + Response_P(PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), XdrvMailbox.command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); + } else { + Response_P(PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), XdrvMailbox.command, my_version); + } +} + +void CmndOtaUrl(void) +{ + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data); + } + ResponseCmndChar(SettingsText(SET_OTAURL)); +} + +void CmndSeriallog(void) +{ + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { + Settings.flag.mqtt_serial = 0; + SetSeriallog(XdrvMailbox.payload); + } + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.seriallog_level, seriallog_level); +} + +void CmndRestart(void) +{ + switch (XdrvMailbox.payload) { + case 1: + restart_flag = 2; + ResponseCmndChar(D_JSON_RESTARTING); + break; + case -1: + CmndCrash(); + break; + case -2: + CmndWDT(); + break; + case -3: + CmndBlockedLoop(); + break; + case 99: + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); + EspRestart(); + break; + default: + ResponseCmndChar(D_JSON_ONE_TO_RESTART); + } +} + +void CmndPowerOnState(void) +{ + if (my_module_type != MOTOR) { + + + + + + + + if ((XdrvMailbox.payload >= POWER_ALL_OFF) && (XdrvMailbox.payload <= POWER_ALL_OFF_PULSETIME_ON)) { + Settings.poweronstate = XdrvMailbox.payload; + if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { + for (uint32_t i = 1; i <= devices_present; i++) { + ExecuteCommandPower(i, POWER_ON, SRC_IGNORE); + } + } + } + ResponseCmndNumber(Settings.poweronstate); + } +} + +void CmndPulsetime(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PULSETIMERS)) { + uint32_t items = 1; + if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { + items = MAX_PULSETIMERS; + } else { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { + Settings.pulse_timer[XdrvMailbox.index -1] = XdrvMailbox.payload; + SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); + } + } + mqtt_data[0] = '\0'; + for (uint32_t i = 0; i < items; i++) { + uint32_t index = (1 == items) ? XdrvMailbox.index : i +1; + ResponseAppend_P(PSTR("%c\"%s%d\":{\"" D_JSON_SET "\":%d,\"" D_JSON_REMAINING "\":%d}"), + (i) ? ',' : '{', + XdrvMailbox.command, index, + Settings.pulse_timer[index -1], GetPulseTimer(index -1)); + } + ResponseJsonEnd(); + } +} + +void CmndBlinktime(void) +{ + if ((XdrvMailbox.payload > 1) && (XdrvMailbox.payload <= 3600)) { + Settings.blinktime = XdrvMailbox.payload; + if (blink_timer > 0) { blink_timer = millis() + (100 * XdrvMailbox.payload); } + } + ResponseCmndNumber(Settings.blinktime); +} + +void CmndBlinkcount(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { + Settings.blinkcount = XdrvMailbox.payload; + if (blink_counter) { blink_counter = Settings.blinkcount *2; } + } + ResponseCmndNumber(Settings.blinkcount); +} + +void CmndSavedata(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3600)) { + Settings.save_data = XdrvMailbox.payload; + save_data_counter = Settings.save_data; + } + SettingsSaveAll(); + char stemp1[TOPSZ]; + if (Settings.save_data > 1) { + snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_EVERY " %d " D_UNIT_SECOND), Settings.save_data); + } + ResponseCmndChar((Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); +} + +void CmndSetoption(void) +{ + if (XdrvMailbox.index < 114) { + uint32_t ptype; + uint32_t pindex; + if (XdrvMailbox.index <= 31) { + ptype = 2; + pindex = XdrvMailbox.index; + } + else if (XdrvMailbox.index <= 49) { + ptype = 1; + pindex = XdrvMailbox.index -32; + } + else if (XdrvMailbox.index <= 81) { + ptype = 3; + pindex = XdrvMailbox.index -50; + } + else { + ptype = 4; + pindex = XdrvMailbox.index -82; + } + + if (XdrvMailbox.payload >= 0) { + if (1 == ptype) { + uint32_t param_low = 0; + uint32_t param_high = 255; + switch (pindex) { + case P_HOLD_TIME: + case P_MAX_POWER_RETRY: + param_low = 1; + param_high = 250; + break; + } + if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) { + Settings.param[pindex] = XdrvMailbox.payload; +#ifdef USE_LIGHT + if (P_RGB_REMAP == pindex) { + LightUpdateColorMapping(); + restart_flag = 2; + } +#endif +#if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) + if (P_IR_UNKNOW_THRESHOLD == pindex) { + IrReceiveUpdateThreshold(); + } +#endif + } else { + ptype = 99; + } + } else { + if (XdrvMailbox.payload <= 1) { + if (2 == ptype) { + switch (pindex) { + case 5: + case 6: + case 7: + case 9: + case 14: + case 22: + case 23: + case 25: + case 27: + ptype = 99; + break; + case 3: + case 15: + restart_flag = 2; + default: + bitWrite(Settings.flag.data, pindex, XdrvMailbox.payload); + } + if (12 == pindex) { + stop_flash_rotate = XdrvMailbox.payload; + SettingsSave(2); + } + #ifdef USE_HOME_ASSISTANT + if ((19 == pindex) || (30 == pindex)) { + HAssDiscover(); + } + #endif + } + else if (3 == ptype) { + bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); + switch (pindex) { + case 5: + if (0 == XdrvMailbox.payload) { + restart_flag = 2; + } + break; + case 10: + WiFiSetSleepMode(); + break; + case 18: + case 25: + restart_flag = 2; + break; + } + } + else if (4 == ptype) { + bitWrite(Settings.flag4.data, pindex, XdrvMailbox.payload); + } + } else { + ptype = 99; + } + } + } + + if (ptype < 99) { + if (1 == ptype) { + ResponseCmndIdxNumber(Settings.param[pindex]); + } else { + uint32_t flag = Settings.flag.data; + if (3 == ptype) { + flag = Settings.flag3.data; + } + else if (4 == ptype) { + flag = Settings.flag4.data; + } + ResponseCmndIdxChar(GetStateText(bitRead(flag, pindex))); + } + } + } +} + +void CmndTemperatureResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.flag2.temperature_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.temperature_resolution); +} + +void CmndHumidityResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.flag2.humidity_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.humidity_resolution); +} + +void CmndPressureResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.flag2.pressure_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.pressure_resolution); +} + +void CmndPowerResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.flag2.wattage_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.wattage_resolution); +} + +void CmndVoltageResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.flag2.voltage_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.voltage_resolution); +} + +void CmndFrequencyResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.flag2.frequency_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.frequency_resolution); +} + +void CmndCurrentResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.flag2.current_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.current_resolution); +} + +void CmndEnergyResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { + Settings.flag2.energy_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.energy_resolution); +} + +void CmndWeightResolution(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + Settings.flag2.weight_resolution = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.weight_resolution); +} + +void CmndModule(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAXMODULE)) { + bool present = false; + if (0 == XdrvMailbox.payload) { + XdrvMailbox.payload = USER_MODULE; + present = true; + } else { + XdrvMailbox.payload--; + present = ValidTemplateModule(XdrvMailbox.payload); + } + if (present) { + Settings.last_module = Settings.module; + Settings.module = XdrvMailbox.payload; + SetModuleType(); + if (Settings.last_module != XdrvMailbox.payload) { + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + Settings.my_gp.io[i] = GPIO_NONE; + } + } + restart_flag = 2; + } + } + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, ModuleNr(), ModuleName().c_str()); +} + +void CmndModules(void) +{ + uint32_t midx = USER_MODULE; + uint32_t lines = 1; + bool jsflg = false; + for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { + if (i > 0) { midx = pgm_read_byte(kModuleNiceList + i -1); } + if (!jsflg) { + Response_P(PSTR("{\"" D_CMND_MODULES "%d\":{"), lines); + } else { + ResponseAppend_P(PSTR(",")); + } + jsflg = true; + uint32_t j = i ? midx +1 : 0; + if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), j, AnyModuleName(midx).c_str()) > (LOGSZ - TOPSZ)) || (i == sizeof(kModuleNiceList))) { + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command)); + jsflg = false; + lines++; + } + } + mqtt_data[0] = '\0'; +} + +void CmndGpio(void) +{ + if (XdrvMailbox.index < sizeof(Settings.my_gp)) { + myio cmodule; + ModuleGpios(&cmodule); + if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < GPIO_SENSOR_END)) { + bool present = false; + for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { + uint32_t midx = pgm_read_byte(kGpioNiceList + i); + if (midx == XdrvMailbox.payload) { present = true; } + } + if (present) { + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + if (ValidGPIO(i, cmodule.io[i]) && (Settings.my_gp.io[i] == XdrvMailbox.payload)) { + Settings.my_gp.io[i] = GPIO_NONE; + } + } + Settings.my_gp.io[XdrvMailbox.index] = XdrvMailbox.payload; + restart_flag = 2; + } + } + Response_P(PSTR("{")); + bool jsflg = false; + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + if (ValidGPIO(i, cmodule.io[i]) || ((GPIO_USER == XdrvMailbox.payload) && !FlashPin(i))) { + if (jsflg) { ResponseAppend_P(PSTR(",")); } + jsflg = true; + uint8_t sensor_type = Settings.my_gp.io[i]; + if (!ValidGPIO(i, cmodule.io[i])) { + sensor_type = cmodule.io[i]; + if (GPIO_USER == sensor_type) { + sensor_type = GPIO_NONE; + } + } + uint8_t sensor_name_idx = sensor_type; + const char *sensor_names = kSensorNames; + if (sensor_type > GPIO_FIX_START) { + sensor_name_idx = sensor_type - GPIO_FIX_START -1; + sensor_names = kSensorNamesFixed; + } + char stemp1[TOPSZ]; + ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s\"}"), + i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names)); + } + } + if (jsflg) { + ResponseJsonEnd(); + } else { + ResponseCmndChar(D_JSON_NOT_SUPPORTED); + } + } +} + +void CmndGpios(void) +{ + myio cmodule; + ModuleGpios(&cmodule); + uint32_t lines = 1; + bool jsflg = false; + for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { + uint32_t midx = pgm_read_byte(kGpioNiceList + i); + if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; } + if (!jsflg) { + Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":{"), lines); + } else { + ResponseAppend_P(PSTR(",")); + } + jsflg = true; + char stemp1[TOPSZ]; + if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command)); + jsflg = false; + lines++; + } + } + mqtt_data[0] = '\0'; +} + +void CmndTemplate(void) +{ + + bool error = false; + + if (strstr(XdrvMailbox.data, "{") == nullptr) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= MAXMODULE)) { + XdrvMailbox.payload--; + if (ValidTemplateModule(XdrvMailbox.payload)) { + ModuleDefault(XdrvMailbox.payload); + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } + } + else if (0 == XdrvMailbox.payload) { + if (Settings.module != USER_MODULE) { + ModuleDefault(Settings.module); + } + } + else if (255 == XdrvMailbox.payload) { + if (Settings.module != USER_MODULE) { + ModuleDefault(Settings.module); + } + snprintf_P(Settings.user_template.name, sizeof(Settings.user_template.name), PSTR("Merged")); + uint32_t j = 0; + for (uint32_t i = 0; i < sizeof(mycfgio); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + if (my_module.io[j] > GPIO_NONE) { + Settings.user_template.gp.io[i] = my_module.io[j]; + } + j++; + } + } + } + else { + if (JsonTemplate(XdrvMailbox.data)) { + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } else { + ResponseCmndChar(D_JSON_INVALID_JSON); + error = true; + } + } + if (!error) { TemplateJson(); } +} + +void CmndPwm(void) +{ + if (pwm_present && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PWMS)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= Settings.pwm_range) && (pin[GPIO_PWM1 + XdrvMailbox.index -1] < 99)) { + Settings.pwm_value[XdrvMailbox.index -1] = XdrvMailbox.payload; + analogWrite(pin[GPIO_PWM1 + XdrvMailbox.index -1], bitRead(pwm_inverted, XdrvMailbox.index -1) ? Settings.pwm_range - XdrvMailbox.payload : XdrvMailbox.payload); + } + Response_P(PSTR("{")); + MqttShowPWMState(); + ResponseJsonEnd(); + } +} + +void CmndPwmfrequency(void) +{ + if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload >= PWM_MIN) && (XdrvMailbox.payload <= PWM_MAX))) { + Settings.pwm_frequency = (1 == XdrvMailbox.payload) ? PWM_FREQ : XdrvMailbox.payload; + analogWriteFreq(Settings.pwm_frequency); + } + ResponseCmndNumber(Settings.pwm_frequency); +} + +void CmndPwmrange(void) +{ + if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload > 254) && (XdrvMailbox.payload < 1024))) { + Settings.pwm_range = (1 == XdrvMailbox.payload) ? PWM_RANGE : XdrvMailbox.payload; + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (Settings.pwm_value[i] > Settings.pwm_range) { + Settings.pwm_value[i] = Settings.pwm_range; + } + } + analogWriteRange(Settings.pwm_range); + } + ResponseCmndNumber(Settings.pwm_range); +} + +void CmndButtonDebounce(void) +{ + if ((XdrvMailbox.payload > 39) && (XdrvMailbox.payload < 1001)) { + Settings.button_debounce = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.button_debounce); +} + +void CmndSwitchDebounce(void) +{ + if ((XdrvMailbox.payload > 39) && (XdrvMailbox.payload < 1001)) { + Settings.switch_debounce = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.switch_debounce); +} + +void CmndBaudrate(void) +{ + if (XdrvMailbox.payload >= 300) { + XdrvMailbox.payload /= 300; + uint32_t baudrate = (XdrvMailbox.payload & 0xFFFF) * 300; + SetSerialBaudrate(baudrate); + } + ResponseCmndNumber(Settings.baudrate * 300); +} + +void CmndSerialConfig(void) +{ + + + + + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.data_len < 3) { + if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) { + SetSerialConfig(XdrvMailbox.payload); + } + } + else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { + uint8_t serial_config = XdrvMailbox.payload -5; + + bool valid = true; + char parity = (XdrvMailbox.data[1] & 0xdf); + if ('E' == parity) { + serial_config += 0x08; + } + else if ('O' == parity) { + serial_config += 0x10; + } + else if ('N' != parity) { + valid = false; + } + + if ('2' == XdrvMailbox.data[2]) { + serial_config += 0x04; + } + else if ('1' != XdrvMailbox.data[2]) { + valid = false; + } + + if (valid) { + SetSerialConfig(serial_config); + } + } + } + ResponseCmndChar(GetSerialConfig().c_str()); +} + +void CmndSerialSend(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { + SetSeriallog(LOG_LEVEL_NONE); + Settings.flag.mqtt_serial = 1; + Settings.flag.mqtt_serial_raw = (XdrvMailbox.index > 3) ? 1 : 0; + if (XdrvMailbox.data_len > 0) { + if (1 == XdrvMailbox.index) { + Serial.printf("%s\n", XdrvMailbox.data); + } + else if (2 == XdrvMailbox.index || 4 == XdrvMailbox.index) { + for (uint32_t i = 0; i < XdrvMailbox.data_len; i++) { + Serial.write(XdrvMailbox.data[i]); + } + } + else if (3 == XdrvMailbox.index) { + uint32_t dat_len = XdrvMailbox.data_len; + Serial.printf("%s", Unescape(XdrvMailbox.data, &dat_len)); + } + else if (5 == XdrvMailbox.index) { + SerialSendRaw(RemoveSpace(XdrvMailbox.data)); + } + ResponseCmndDone(); + } + } +} + +void CmndSerialDelimiter(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.payload < 256)) { + if (XdrvMailbox.payload > 0) { + Settings.serial_delimiter = XdrvMailbox.payload; + } else { + uint32_t dat_len = XdrvMailbox.data_len; + Unescape(XdrvMailbox.data, &dat_len); + Settings.serial_delimiter = XdrvMailbox.data[0]; + } + } + ResponseCmndNumber(Settings.serial_delimiter); +} + +void CmndSyslog(void) +{ + if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { + SetSyslog(XdrvMailbox.payload); + } + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.syslog_level, syslog_level); +} + +void CmndLoghost(void) +{ + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_SYSLOG_HOST, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data); + } + ResponseCmndChar(SettingsText(SET_SYSLOG_HOST)); +} + +void CmndLogport(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { + Settings.syslog_port = (1 == XdrvMailbox.payload) ? SYS_LOG_PORT : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.syslog_port); +} + +void CmndIpAddress(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + uint32_t address; + if (ParseIp(&address, XdrvMailbox.data)) { + Settings.ip_address[XdrvMailbox.index -1] = address; + + } + char stemp1[TOPSZ]; + snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); + Response_P(S_JSON_COMMAND_INDEX_SVALUE_SVALUE, XdrvMailbox.command, XdrvMailbox.index, IPAddress(Settings.ip_address[XdrvMailbox.index -1]).toString().c_str(), (1 == XdrvMailbox.index) ? stemp1:""); + } +} + +void CmndNtpServer(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_NTP_SERVERS)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_NTPSERVER1, MAX_NTP_SERVERS); + } else { + uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1; + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(ntp_server, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? NTP_SERVER1 : (2 == XdrvMailbox.index) ? NTP_SERVER2 : NTP_SERVER3 : XdrvMailbox.data); + SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); + + ntp_force_sync = true; + } + ResponseCmndIdxChar(SettingsText(ntp_server)); + } + } +} + +void CmndAp(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + switch (XdrvMailbox.payload) { + case 0: + Settings.sta_active ^= 1; + break; + case 1: + case 2: + Settings.sta_active = XdrvMailbox.payload -1; + } + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active)); +} + +void CmndSsid(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SSIDS)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_STASSID1, MAX_SSIDS); + } else { + if (XdrvMailbox.data_len > 0) { + SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); + Settings.sta_active = XdrvMailbox.index -1; + restart_flag = 2; + } + ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); + } + } +} + +void CmndPassword(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + if ((XdrvMailbox.data_len > 4) || (SC_CLEAR == Shortcut()) || (SC_DEFAULT == Shortcut())) { + SettingsUpdateText(SET_STAPWD1 + XdrvMailbox.index -1, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data); + Settings.sta_active = XdrvMailbox.index -1; + restart_flag = 2; + ResponseCmndIdxChar(SettingsText(SET_STAPWD1 + XdrvMailbox.index -1)); + } else { + Response_P(S_JSON_COMMAND_INDEX_ASTERISK, XdrvMailbox.command, XdrvMailbox.index); + } + } +} + +void CmndHostname(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { + SettingsUpdateText(SET_HOSTNAME, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + } + restart_flag = 2; + } + ResponseCmndChar(SettingsText(SET_HOSTNAME)); +} + +void CmndWifiConfig(void) +{ + if ((XdrvMailbox.payload >= WIFI_RESTART) && (XdrvMailbox.payload < MAX_WIFI_OPTION)) { + if ((EX_WIFI_SMARTCONFIG == XdrvMailbox.payload) || (EX_WIFI_WPSCONFIG == XdrvMailbox.payload)) { + XdrvMailbox.payload = WIFI_MANAGER; + } + Settings.sta_config = XdrvMailbox.payload; + wifi_state_flag = Settings.sta_config; + if (WifiState() > WIFI_RESTART) { + restart_flag = 2; + } + } + char stemp1[TOPSZ]; + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, GetTextIndexed(stemp1, sizeof(stemp1), Settings.sta_config, kWifiConfig)); +} + +void CmndFriendlyname(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) { + if (!XdrvMailbox.usridx) { + ResponseCmndAll(SET_FRIENDLYNAME1, MAX_FRIENDLYNAMES); + } else { + if (XdrvMailbox.data_len > 0) { + char stemp1[TOPSZ]; + if (1 == XdrvMailbox.index) { + snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME)); + } else { + snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); + } + SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); + } + ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1)); + } + } +} + +void CmndSwitchMode(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SWITCHES)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_SWITCH_OPTION)) { + Settings.switchmode[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.switchmode[XdrvMailbox.index-1]); + } +} + +void CmndInterlock(void) +{ + + uint32_t max_relays = devices_present; + if (light_type) { max_relays--; } + if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; } + if (max_relays > 1) { + if (XdrvMailbox.data_len > 0) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } + char *group; + char *q; + uint32_t group_index = 0; + power_t relay_mask = 0; + for (group = strtok_r(XdrvMailbox.data, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(nullptr, " ", &q)) { + char *str; + char *p; + for (str = strtok_r(group, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { + int pbit = atoi(str); + if ((pbit > 0) && (pbit <= max_relays)) { + pbit--; + if (!bitRead(relay_mask, pbit)) { + bitSet(relay_mask, pbit); + bitSet(Settings.interlock[group_index], pbit); + } + } + } + group_index++; + } + for (uint32_t i = 0; i < group_index; i++) { + uint32_t minimal_bits = 0; + for (uint32_t j = 0; j < max_relays; j++) { + if (bitRead(Settings.interlock[i], j)) { minimal_bits++; } + } + if (minimal_bits < 2) { Settings.interlock[i] = 0; } + } + } else { + Settings.flag.interlock = XdrvMailbox.payload &1; + if (Settings.flag.interlock) { + SetDevicePower(power, SRC_IGNORE); + } + } +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + ShutterInit(); + } +#endif + } + Response_P(PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); + uint32_t anygroup = 0; + for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { + if (Settings.interlock[i]) { + anygroup++; + ResponseAppend_P(PSTR("%s"), (anygroup > 1) ? " " : ""); + uint32_t anybit = 0; + power_t mask = 1; + for (uint32_t j = 0; j < max_relays; j++) { + if (Settings.interlock[i] & mask) { + anybit++; + ResponseAppend_P(PSTR("%s%d"), (anybit > 1) ? "," : "", j +1); + } + mask <<= 1; + } + } + } + if (!anygroup) { + for (uint32_t j = 1; j <= max_relays; j++) { + ResponseAppend_P(PSTR("%s%d"), (j > 1) ? "," : "", j); + } + } + ResponseAppend_P(PSTR("\"}")); + } else { + Settings.flag.interlock = 0; + ResponseCmndStateText(Settings.flag.interlock); + } +} + +void CmndTeleperiod(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.tele_period = (1 == XdrvMailbox.payload) ? TELE_PERIOD : XdrvMailbox.payload; + if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; + tele_period = Settings.tele_period; + } + ResponseCmndNumber(Settings.tele_period); +} + +void CmndReset(void) +{ + switch (XdrvMailbox.payload) { + case 1: + restart_flag = 211; + ResponseCmndChar(D_JSON_RESET_AND_RESTARTING); + break; + case 2 ... 6: + restart_flag = 210 + XdrvMailbox.payload; + Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); + break; + case 99: + Settings.bootcount = 0; + Settings.bootcount_reset_time = 0; + ResponseCmndDone(); + break; + default: + ResponseCmndChar(D_JSON_ONE_TO_RESET); + } +} + +void CmndTime(void) +{ + + + + + + + + uint32_t format = Settings.flag2.time_format; + if (XdrvMailbox.data_len > 0) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { + Settings.flag2.time_format = XdrvMailbox.payload -1; + format = Settings.flag2.time_format; + } else { + format = 1; + RtcSetTime(XdrvMailbox.payload); + } + } + mqtt_data[0] = '\0'; + ResponseAppendTimeFormat(format); + ResponseJsonEnd(); +} + +void CmndTimezone(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= -13)) { + Settings.timezone = XdrvMailbox.payload; + Settings.timezone_minutes = 0; + if (XdrvMailbox.payload < 15) { + char *p = strtok (XdrvMailbox.data, ":"); + if (p) { + p = strtok (nullptr, ":"); + if (p) { + Settings.timezone_minutes = strtol(p, nullptr, 10); + if (Settings.timezone_minutes > 59) { Settings.timezone_minutes = 59; } + } + } + } else { + Settings.timezone = 99; + } + ntp_force_sync = true; + } + if (99 == Settings.timezone) { + ResponseCmndNumber(Settings.timezone); + } else { + char stemp1[TOPSZ]; + snprintf_P(stemp1, sizeof(stemp1), PSTR("%+03d:%02d"), Settings.timezone, Settings.timezone_minutes); + ResponseCmndChar(stemp1); + } +} + +void CmndTimeStdDst(uint32_t ts) +{ + + if (XdrvMailbox.data_len > 0) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + uint32_t tpos = 0; + int value = 0; + char *p = XdrvMailbox.data; + char *q = p; + while (p && (tpos < 7)) { + if (p > q) { + if (1 == tpos) { Settings.tflag[ts].hemis = value &1; } + if (2 == tpos) { Settings.tflag[ts].week = (value < 0) ? 0 : (value > 4) ? 4 : value; } + if (3 == tpos) { Settings.tflag[ts].month = (value < 1) ? 1 : (value > 12) ? 12 : value; } + if (4 == tpos) { Settings.tflag[ts].dow = (value < 1) ? 1 : (value > 7) ? 7 : value; } + if (5 == tpos) { Settings.tflag[ts].hour = (value < 0) ? 0 : (value > 23) ? 23 : value; } + if (6 == tpos) { Settings.toffset[ts] = (value < -900) ? -900 : (value > 900) ? 900 : value; } + } + p = Trim(p); + if (tpos && (*p == ',')) { p++; } + p = Trim(p); + q = p; + value = strtol(p, &p, 10); + tpos++; + } + ntp_force_sync = true; + } else { + if (0 == XdrvMailbox.payload) { + if (0 == ts) { + SettingsResetStd(); + } else { + SettingsResetDst(); + } + } + ntp_force_sync = true; + } + } + Response_P(PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), + XdrvMailbox.command, Settings.tflag[ts].hemis, Settings.tflag[ts].week, Settings.tflag[ts].month, Settings.tflag[ts].dow, Settings.tflag[ts].hour, Settings.toffset[ts]); +} + +void CmndTimeStd(void) +{ + CmndTimeStdDst(0); +} + +void CmndTimeDst(void) +{ + CmndTimeStdDst(1); +} + +void CmndAltitude(void) +{ + if ((XdrvMailbox.data_len > 0) && ((XdrvMailbox.payload >= -30000) && (XdrvMailbox.payload <= 30000))) { + Settings.altitude = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.altitude); +} + +void CmndLedPower(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { + if (99 == pin[GPIO_LEDLNK]) { XdrvMailbox.index = 1; } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + Settings.ledstate &= 8; + uint32_t mask = 1 << (XdrvMailbox.index -1); + switch (XdrvMailbox.payload) { + case 0: + led_power &= (0xFF ^ mask); + Settings.ledstate = 0; + break; + case 1: + led_power |= mask; + Settings.ledstate = 8; + break; + case 2: + led_power ^= mask; + Settings.ledstate ^= 8; + break; + } + blinks = 0; + if (99 == pin[GPIO_LEDLNK]) { + SetLedPower(Settings.ledstate &8); + } else { + SetLedPowerIdx(XdrvMailbox.index -1, (led_power & mask)); + } + } + bool state = bitRead(led_power, XdrvMailbox.index -1); + if (99 == pin[GPIO_LEDLNK]) { + state = bitRead(Settings.ledstate, 3); + } + ResponseCmndIdxChar(GetStateText(state)); + } +} + +void CmndLedState(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_LED_OPTION)) { + Settings.ledstate = XdrvMailbox.payload; + if (!Settings.ledstate) { + SetLedPowerAll(0); + SetLedLink(0); + } + } + ResponseCmndNumber(Settings.ledstate); +} + +void CmndLedMask(void) +{ + if (XdrvMailbox.data_len > 0) { + Settings.ledmask = XdrvMailbox.payload; + } + char stemp1[TOPSZ]; + snprintf_P(stemp1, sizeof(stemp1), PSTR("%d (0x%04X)"), Settings.ledmask, Settings.ledmask); + ResponseCmndChar(stemp1); +} + +void CmndWifiPower(void) +{ + if (XdrvMailbox.data_len > 0) { + Settings.wifi_output_power = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); + if (Settings.wifi_output_power > 205) { + Settings.wifi_output_power = 205; + } + WifiSetOutputPower(); + } + ResponseCmndChar(WifiGetOutputPower().c_str()); +} + +#ifdef USE_I2C +void CmndI2cScan(void) +{ + if (i2c_flg) { + I2cScan(mqtt_data, sizeof(mqtt_data)); + } +} + +void CmndI2cDriver(void) +{ + if (XdrvMailbox.index < MAX_I2C_DRIVERS) { + if (XdrvMailbox.payload >= 0) { + bitWrite(Settings.i2c_drivers[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); + restart_flag = 2; + } + } + Response_P(PSTR("{\"" D_CMND_I2CDRIVER "\":")); + I2cDriverState(); + ResponseJsonEnd(); +} +#endif + +#ifdef USE_DEVICE_GROUPS +void CmndDevGroupShare(void) +{ + uint32_t parm[2] = { Settings.device_group_share_in, Settings.device_group_share_out }; + ParseParameters(2, parm); + Settings.device_group_share_in = parm[0]; + Settings.device_group_share_out = parm[1]; + Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":%x,\"Out\":%x}}"), Settings.device_group_share_in, Settings.device_group_share_out); +} +#endif + +void CmndSensor(void) +{ + XsnsCall(FUNC_COMMAND_SENSOR); +} + +void CmndDriver(void) +{ + XdrvCall(FUNC_COMMAND_DRIVER); +} +# 1 "S:/Development/Tasmota/tasmota/support_crash_recorder.ino" +# 20 "S:/Development/Tasmota/tasmota/support_crash_recorder.ino" +const uint32_t crash_magic = 0x53415400; +const uint32_t crash_rtc_offset = 32; +const uint32_t crash_dump_max_len = 31; + + + + + + +extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) +{ + uint32_t addr_written = 0; + uint32_t value; + + for (uint32_t i = stack; i < stack_end; i += 4) { + value = *((uint32_t*) i); + if ((value >= 0x40000000) && (value < 0x40300000)) { + ESP.rtcUserMemoryWrite(crash_rtc_offset + addr_written, (uint32_t*)&value, sizeof(value)); + addr_written++; + if (addr_written >= crash_dump_max_len) { break; } + } + } + value = crash_magic + addr_written; + ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); +} + + +void CmndCrash(void) +{ + volatile uint32_t dummy; + dummy = *((uint32_t*) 0x00000000); +} + + +void CmndWDT(void) +{ + volatile uint32_t dummy = 0; + while (1) { + dummy++; + } +} + + +void CmndBlockedLoop(void) +{ + while (1) { + delay(1000); + } +} + + +void CrashDumpClear(void) +{ + uint32_t value = 0; + ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); +} + + + + + +bool CrashFlag(void) +{ + return ((ResetReason() == REASON_EXCEPTION_RST) || (ResetReason() == REASON_SOFT_WDT_RST) || oswatch_blocked_loop); +} + +void CrashDump(void) +{ + ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""), + resetInfo.exccause, + GetResetReason().c_str(), + resetInfo.epc1, + resetInfo.epc2, + resetInfo.epc3, + resetInfo.excvaddr, + resetInfo.depc); + + uint32_t value; + ESP.rtcUserMemoryRead(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); + if (crash_magic == (value & 0xFFFFFF00)) { + ResponseAppend_P(PSTR(",\"CallChain\":[")); + uint32_t count = value & 0x3F; + for (uint32_t i = 0; i < count; i++) { + ESP.rtcUserMemoryRead(crash_rtc_offset +i, (uint32_t*)&value, sizeof(value)); + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"%08x\""), value); + } + ResponseAppend_P(PSTR("]")); + } + + ResponseJsonEnd(); +} +# 1 "S:/Development/Tasmota/tasmota/support_device_groups.ino" +# 23 "S:/Development/Tasmota/tasmota/support_device_groups.ino" +#ifdef USE_DEVICE_GROUPS + + + +extern bool udp_connected; + +struct device_group_member { + struct device_group_member * flink; + IPAddress ip_address; + uint32_t timeout_time; + uint16_t received_sequence; + uint16_t acked_sequence; +}; + +struct device_group { + uint32_t next_ack_check_time; + uint16_t last_full_status_sequence; + uint16_t message_length; + uint8_t message_header_length; + uint8_t initial_status_requests_remaining; + bool local; + char group_name[TOPSZ]; + char message[128]; + uint8_t group_member_count; + struct device_group_member * device_group_members; +}; + +struct device_group * device_groups; +uint16_t outgoing_sequence = 0; +bool device_groups_initialized = false; +bool device_groups_initialization_failed = false; +bool building_status_message = false; +bool processing_remote_device_message = false; +bool waiting_for_acks; +bool udp_was_connected = false; + +void DeviceGroupsInit(void) +{ + + device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); + if (device_groups == nullptr) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count); + device_groups_initialization_failed = true; + return; + } + + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { + struct device_group * device_group = &device_groups[device_group_index]; + strcpy(device_group->group_name, SettingsText((device_group_index == 0 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + device_group_index - 1))); + device_group->message_header_length = sprintf_P(device_group->message, PSTR("%s%s HTTP/1.1\n\n"), kDeviceGroupMessage, device_group->group_name); + device_group->last_full_status_sequence = -1; + } + + device_groups[0].local = true; + + + if (!Settings.device_group_share_in && !Settings.device_group_share_out) { + Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff; + } + + device_groups_initialized = true; +} + +char * IPAddressToString(const IPAddress& ip_address) +{ + static char buffer[16]; + sprintf_P(buffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]); + return buffer; +} + + +bool DeviceGroupItemShared(bool incoming, uint8_t item) +{ + uint8_t mask = 0; + switch (item) { + case DGR_ITEM_LIGHT_BRI: + mask = DGR_SHARE_LIGHT_BRI; + break; + case DGR_ITEM_POWER: + mask = DGR_SHARE_POWER; + break; + case DGR_ITEM_LIGHT_SCHEME: + mask = DGR_SHARE_LIGHT_SCHEME; + break; + case DGR_ITEM_LIGHT_FIXED_COLOR: + case DGR_ITEM_LIGHT_CHANNELS: + mask = DGR_SHARE_LIGHT_COLOR; + break; + case DGR_ITEM_LIGHT_FADE: + case DGR_ITEM_LIGHT_SPEED: + mask = DGR_SHARE_LIGHT_FADE; + break; + case DGR_ITEM_BRI_MIN: + mask = DGR_SHARE_BRI_MIN; + break; + } + return (!mask || ((incoming ? Settings.device_group_share_in : Settings.device_group_share_out) & mask)); +} + +void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * label) +{ + for (int attempt = 1; attempt <= 5; attempt++) { + if (PortUdp.beginPacket(ip, 1900)) { + PortUdp.write(packet, len); + if (PortUdp.endPacket()) return; + } + delay(10); + } + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error sending %s packet"), label); +} + +void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...) +{ + + if (!Settings.flag4.device_groups_enabled) return; + + + if (!udp_connected) return; + + + if (processing_remote_device_message) return; + + + device_group * device_group = &device_groups[device_group_index]; + + + if (device_group->initial_status_requests_remaining) return; + + + + + char * message_ptr = &device_group->message[device_group->message_header_length]; + if (message_type == DGR_MSGTYP_FULL_STATUS) { + + + + building_status_message = true; + + + if (!++outgoing_sequence) outgoing_sequence = 1; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s full status packet"), device_group->group_name); +#endif + device_group->message_length = 0; + SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); + XdrvMailbox.command_code = DGR_ITEM_STATUS; + XdrvCall(FUNC_DEVICE_GROUP_REQUEST); + building_status_message = false; + + + if (!device_group->message_length) { + if (!--outgoing_sequence) outgoing_sequence = -1; + return; + } + device_group->last_full_status_sequence = outgoing_sequence; + + + *(message_ptr + 2) |= DGR_FLAG_FULL_STATUS; + } + + else { + bool shared; + uint8_t item; + uint32_t value; + uint8_t * value_ptr; + va_list ap; + +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s packet"), device_group->group_name); +#endif + uint16_t original_sequence = outgoing_sequence; + if (!building_status_message && message_type != DGR_MSGTYP_PARTIAL_UPDATE && !++outgoing_sequence) outgoing_sequence = 1; + *message_ptr++ = outgoing_sequence & 0xff; + *message_ptr++ = outgoing_sequence >> 8; + + value = 0; + if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) + value |= DGR_FLAG_MORE_TO_COME; + else if (message_type == DGR_MSGTYP_UPDATE_DIRECT) + value |= DGR_FLAG_DIRECT; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">sequence=%u, flags=%u"), outgoing_sequence, value); +#endif + *message_ptr++ = value & 0xff; + *message_ptr++ = value >> 8; + char * first_item_ptr = message_ptr; + + + + + + if (device_group->message_length) { + uint8_t item_array[32]; + int item_index = 0; + int kept_item_count = 0; + + + va_start(ap, message_type); + while ((item = va_arg(ap, int))) { + item_array[item_index++] = item; + if (item <= DGR_ITEM_MAX_32BIT) + va_arg(ap, int); + else if (item <= DGR_ITEM_MAX_STRING) + va_arg(ap, char *); + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + va_arg(ap, uint8_t *) ; + break; + } + } + } + va_end(ap); + item_array[item_index] = 0; + + + + char * previous_message_ptr = message_ptr; + while (item = *previous_message_ptr++) { + + + for (item_index = 0; item_array[item_index]; item_index++) { + if (item_array[item_index] == item) break; + } + + + if (item_array[item_index]) { + if (item <= DGR_ITEM_MAX_32BIT) { + previous_message_ptr++; + if (item > DGR_ITEM_MAX_8BIT) { + previous_message_ptr++; + if (item > DGR_ITEM_MAX_16BIT) { + previous_message_ptr++; + previous_message_ptr++; + } + } + } + else if (item <= DGR_ITEM_MAX_STRING) + previous_message_ptr += *previous_message_ptr++; + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + previous_message_ptr += 5; + break; + } + } + } + + + else { + *message_ptr++ = item; + if (item <= DGR_ITEM_MAX_32BIT) { + *message_ptr++ = *previous_message_ptr++; + if (item > DGR_ITEM_MAX_8BIT) { + *message_ptr++ = *previous_message_ptr++; + if (item > DGR_ITEM_MAX_16BIT) { + *message_ptr++ = *previous_message_ptr++; + *message_ptr++ = *previous_message_ptr++; + } + } + } + else if (item <= DGR_ITEM_MAX_STRING) { + *message_ptr++ = value = *previous_message_ptr++; + memmove(message_ptr, previous_message_ptr, value); + previous_message_ptr += value; + message_ptr += value; + } + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + memmove(message_ptr, previous_message_ptr, 5); + previous_message_ptr += 5; + message_ptr += 5; + break; + } + } + kept_item_count++; + } + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count); +#endif + } + + + va_start(ap, message_type); + while ((item = va_arg(ap, int))) { + shared = DeviceGroupItemShared(false, item); + if (shared) *message_ptr++ = item; + if (item <= DGR_ITEM_MAX_32BIT) { + value = va_arg(ap, int); + if (shared) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u"), item, value); +#endif + *message_ptr++ = value & 0xff; + if (item > DGR_ITEM_MAX_8BIT) { + value >>= 8; + *message_ptr++ = value & 0xff; + } + if (item > DGR_ITEM_MAX_16BIT) { + value >>= 8; + *message_ptr++ = value & 0xff; + *message_ptr++ = value >> 8; + } + } + } + else if (item <= DGR_ITEM_MAX_STRING) { + value_ptr = va_arg(ap, uint8_t *); + if (shared) { + value = strlen((const char *)value_ptr); +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%s"), item, value_ptr); +#endif + *message_ptr++ = value; + memcpy(message_ptr, value_ptr, value); + message_ptr += value; + } + } + else { + switch (item) { + case DGR_ITEM_LIGHT_CHANNELS: + value_ptr = va_arg(ap, uint8_t *); + if (shared) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u,%u,%u,%u,%u"), item, *value_ptr, *(value_ptr + 1), *(value_ptr + 2), *(value_ptr + 3), *(value_ptr + 4)); +#endif + memmove(message_ptr, value_ptr, 5); + message_ptr += 5; + } + break; + } + } + } + va_end(ap); + + + + if (message_ptr == first_item_ptr) { + outgoing_sequence = original_sequence; + return; + } + + + *message_ptr++ = 0; + device_group->message_length = message_ptr - device_group->message; + + + if (building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE) return; + } + + +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); +#endif + SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, PSTR("Multicast")); + device_group->next_ack_check_time = millis() + 100; + + if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) { + for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member != nullptr; device_group_member = device_group_member->flink) { + device_group_member->acked_sequence = outgoing_sequence; + } + } + else { + waiting_for_acks = true; + } +} + +void ProcessDeviceGroupMessage(char * packet, int packet_length) +{ + + char * message_group_name = packet + sizeof(DEVICE_GROUP_MESSAGE) - 1; + char * message_ptr = strchr(message_group_name, ' '); + if (message_ptr == nullptr) return; + *message_ptr = 0; + + + struct device_group * device_group; + uint32_t device_group_index = 0; + for (;;) { + device_group = &device_groups[device_group_index]; + if (!strcmp(message_group_name, device_group->group_name)) break; + if (++device_group_index >= device_group_count) return; + } + *message_ptr++ = ' '; + + + IPAddress remote_ip = PortUdp.remoteIP(); + struct device_group_member * * flink = &device_group->device_group_members; + struct device_group_member * device_group_member; + for (;;) { + device_group_member = *flink; + if (!device_group_member) { + device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member)); + if (device_group_member == nullptr) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating device group member block")); + return; + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: adding member %s (%p)"), IPAddressToString(remote_ip), device_group_member); +#endif + device_group_member->ip_address = remote_ip; + *flink = device_group_member; + break; + } + else if (device_group_member->ip_address == remote_ip) { + break; + } + flink = &device_group_member->flink; + } + + + message_ptr = strstr_P(message_ptr, PSTR("\n\n")); + if (message_ptr == nullptr) return; + message_ptr += 2; + + bool light_fade; + uint16_t flags; + uint16_t item; + uint16_t message_sequence; + int32_t value; + + + if (packet_length - (message_ptr - packet) < 4) goto badmsg; + message_sequence = *message_ptr++; + message_sequence |= *message_ptr++ << 8; + flags = *message_ptr++; + flags |= *message_ptr++ << 8; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Received device group %s packet from %s: sequence=%u, flags=%u"), device_group->group_name, IPAddressToString(remote_ip), message_sequence, flags); +#endif + + + + if (flags == DGR_FLAG_ACK) { + if (message_sequence > device_group_member->acked_sequence || device_group_member->acked_sequence - message_sequence < 64536) { + device_group_member->acked_sequence = message_sequence; + } + device_group_member->timeout_time = 0; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("acked_sequence != device_group->last_full_status_sequence) { + _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("received_sequence && device_group_member->received_sequence - message_sequence > 64536) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("received_sequence = message_sequence; + + + + processing_remote_device_message = true; +# 512 "S:/Development/Tasmota/tasmota/support_device_groups.ino" + XdrvMailbox.command = nullptr; + XdrvMailbox.index = flags; + light_fade = Settings.light_fade; + if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) Settings.light_fade = false; + + for (;;) { + if (packet_length - (message_ptr - packet) < 1) goto badmsg; + item = *message_ptr++; + if (!item) break; + +#ifdef DEVICE_GROUPS_DEBUG + switch (item) { + case DGR_ITEM_LIGHT_FADE: + case DGR_ITEM_LIGHT_SPEED: + case DGR_ITEM_LIGHT_BRI: + case DGR_ITEM_LIGHT_SCHEME: + case DGR_ITEM_LIGHT_FIXED_COLOR: + case DGR_ITEM_BRI_MIN: + case DGR_ITEM_BRI_PRESET_LOW: + case DGR_ITEM_BRI_PRESET_HIGH: + case DGR_ITEM_BRI_POWER_ON: + case DGR_ITEM_POWER: + case DGR_ITEM_LIGHT_CHANNELS: + break; + default: + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip)); + } +#endif + + XdrvMailbox.command_code = item; + if (item <= DGR_ITEM_LAST_32BIT) { + value = *message_ptr++; + if (item > DGR_ITEM_MAX_8BIT) { + value |= *message_ptr++ << 8; + if (item > DGR_ITEM_MAX_16BIT) { + value |= *message_ptr++ << 16; + value |= *message_ptr++ << 24; + } + } + else if (item == DGR_ITEM_LIGHT_FADE) { + light_fade = value; + } +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("= packet_length - (message_ptr - packet)) goto badmsg; +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("message[device_group->message_header_length]; + if (!++outgoing_sequence) outgoing_sequence = 1; + *message_ptr++ = outgoing_sequence & 0xff; + *message_ptr++ = outgoing_sequence >> 8; + *message_ptr++ = DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST; + *message_ptr++ = 0; + device_group->message_length = message_ptr - device_group->message; + device_group->initial_status_requests_remaining = 5; + device_group->next_ack_check_time = millis() + 1000; + } + + waiting_for_acks = true; + } + + if (device_groups_initialization_failed) return; + + if (waiting_for_acks) { + uint32_t now = millis(); + waiting_for_acks = false; + for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { + device_group * device_group = &device_groups[device_group_index]; + if (device_group->next_ack_check_time) { + if (device_group->next_ack_check_time <= now) { + if (device_group->initial_status_requests_remaining) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending initial status request for group %s"), device_group->group_name); +#endif + if (--device_group->initial_status_requests_remaining) { + SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, PSTR("Initial")); + device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; + device_group->next_ack_check_time = now + 200; + waiting_for_acks = true; + } + else { + device_group->next_ack_check_time = 0; + _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); + } + } + else { + bool acked = true; + struct device_group_member ** flink = &device_group->device_group_members; + struct device_group_member * device_group_member; + while ((device_group_member = *flink)) { + if (device_group_member->acked_sequence != outgoing_sequence) { + + if (device_group_member->timeout_time && device_group_member->timeout_time < now) { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: removing member %s (%p)"), IPAddressToString(device_group_member->ip_address), device_group_member); +#endif + *flink = device_group_member->flink; + free(device_group_member); + } + else { +#ifdef DEVICE_GROUPS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u"), device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); +#endif + SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, PSTR("Unicast")); + if (!device_group_member->timeout_time) device_group_member->timeout_time = now + 15000; + acked = false; + flink = &device_group_member->flink; + } + } + else { + flink = &device_group_member->flink; + } + } + if (acked) { + device_group->next_ack_check_time = 0; + device_group->message_length = 0; + } + else { + device_group->next_ack_check_time = now + 500; + waiting_for_acks = true; + } + } + } + else { + waiting_for_acks = true; + } + } + } + } + } + else { + udp_was_connected = false; + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/support_esptool.ino" +# 20 "S:/Development/Tasmota/tasmota/support_esptool.ino" +#define USE_ESPTOOL +#ifdef USE_ESPTOOL + + + + + + + +#define READ_REG(REG) (*((volatile uint32_t *)(REG))) +#define WRITE_REG(REG,VAL) *((volatile uint32_t *)(REG)) = (VAL) +#define REG_SET_MASK(reg,mask) WRITE_REG((reg), (READ_REG(reg)|(mask))) + +#define SPI_BASE_REG 0x60000200 + +#define SPI_CMD_REG (SPI_BASE_REG + 0x00) +#define SPI_FLASH_RDSR (1<<27) +#define SPI_FLASH_SE (1<<24) +#define SPI_FLASH_BE (1<<23) +#define SPI_FLASH_WREN (1<<30) + +#define SPI_ADDR_REG (SPI_BASE_REG + 0x04) +#define SPI_CTRL_REG (SPI_BASE_REG + 0x08) +#define SPI_RD_STATUS_REG (SPI_BASE_REG + 0x10) +#define SPI_W0_REG (SPI_BASE_REG + 0x40) +#define SPI_EXT2_REG (SPI_BASE_REG + 0xF8) + +#define SPI_ST 0x7 + + +#define SECTORS_PER_BLOCK (FLASH_BLOCK_SIZE / SPI_FLASH_SEC_SIZE) + + +static const uint32_t STATUS_WIP_BIT = (1 << 0); + + +inline static void spi_wait_ready(void) +{ + while((READ_REG(SPI_EXT2_REG) & SPI_ST)) { } +} + + + +static bool spiflash_is_ready(void) +{ + spi_wait_ready(); + WRITE_REG(SPI_RD_STATUS_REG, 0); + WRITE_REG(SPI_CMD_REG, SPI_FLASH_RDSR); + while(READ_REG(SPI_CMD_REG) != 0) { } + uint32_t status_value = READ_REG(SPI_RD_STATUS_REG); + return (status_value & STATUS_WIP_BIT) == 0; +} + +static void spi_write_enable(void) +{ + while(!spiflash_is_ready()) { } + WRITE_REG(SPI_CMD_REG, SPI_FLASH_WREN); + while(READ_REG(SPI_CMD_REG) != 0) { } +} + +bool EsptoolEraseSector(uint32_t sector) +{ + spi_write_enable(); + spi_wait_ready(); + + WRITE_REG(SPI_ADDR_REG, (sector * SPI_FLASH_SEC_SIZE) & 0xffffff); + WRITE_REG(SPI_CMD_REG, SPI_FLASH_SE); + while(READ_REG(SPI_CMD_REG) != 0) { } + while(!spiflash_is_ready()) { } + + return true; +} + +void EsptoolErase(uint32_t start_sector, uint32_t end_sector) +{ + int next_erase_sector = start_sector; + int remaining_erase_sector = end_sector - start_sector; + + while (remaining_erase_sector > 0) { + spi_write_enable(); + + uint32_t command = SPI_FLASH_SE; + uint32_t sectors_to_erase = 1; + if (remaining_erase_sector >= SECTORS_PER_BLOCK && + next_erase_sector % SECTORS_PER_BLOCK == 0) { + command = SPI_FLASH_BE; + sectors_to_erase = SECTORS_PER_BLOCK; + } + uint32_t addr = next_erase_sector * SPI_FLASH_SEC_SIZE; + + spi_wait_ready(); + WRITE_REG(SPI_ADDR_REG, addr & 0xffffff); + WRITE_REG(SPI_CMD_REG, command); + while(READ_REG(SPI_CMD_REG) != 0) { } + remaining_erase_sector -= sectors_to_erase; + next_erase_sector += sectors_to_erase; + + while (!spiflash_is_ready()) { } + yield(); + OsWatchLoop(); + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/support_features.ino" +# 24 "S:/Development/Tasmota/tasmota/support_features.ino" +void GetFeatures(void) +{ + feature_drv1 = 0x00000000; + +#ifdef USE_ENERGY_MARGIN_DETECTION + feature_drv1 |= 0x00000001; +#endif +#ifdef USE_LIGHT + feature_drv1 |= 0x00000002; +#endif +#ifdef USE_I2C + feature_drv1 |= 0x00000004; +#endif +#ifdef USE_SPI + feature_drv1 |= 0x00000008; +#endif +#ifdef USE_DISCOVERY + feature_drv1 |= 0x00000010; +#endif +#ifdef USE_ARDUINO_OTA + feature_drv1 |= 0x00000020; +#endif +#ifdef USE_MQTT_TLS + feature_drv1 |= 0x00000040; +#endif +#ifdef USE_WEBSERVER + feature_drv1 |= 0x00000080; +#endif +#ifdef WEBSERVER_ADVERTISE + feature_drv1 |= 0x00000100; +#endif +#ifdef USE_EMULATION_HUE + feature_drv1 |= 0x00000200; +#endif +#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) + feature_drv1 |= 0x00000400; +#endif +#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) + +#endif +#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) + +#endif +#ifdef MQTT_HOST_DISCOVERY + feature_drv1 |= 0x00002000; +#endif +#ifdef USE_ARILUX_RF + feature_drv1 |= 0x00004000; +#endif +#if defined(USE_LIGHT) && defined(USE_WS2812) + feature_drv1 |= 0x00008000; +#endif +#ifdef USE_WS2812_DMA + feature_drv1 |= 0x00010000; +#endif +#if defined(USE_IR_REMOTE) || defined(USE_IR_REMOTE_FULL) + feature_drv1 |= 0x00020000; +#endif +#ifdef USE_IR_HVAC + feature_drv1 |= 0x00040000; +#endif +#ifdef USE_IR_RECEIVE + feature_drv1 |= 0x00080000; +#endif +#ifdef USE_DOMOTICZ + feature_drv1 |= 0x00100000; +#endif +#ifdef USE_DISPLAY + feature_drv1 |= 0x00200000; +#endif +#ifdef USE_HOME_ASSISTANT + feature_drv1 |= 0x00400000; +#endif +#ifdef USE_SERIAL_BRIDGE + feature_drv1 |= 0x00800000; +#endif +#ifdef USE_TIMERS + feature_drv1 |= 0x01000000; +#endif +#ifdef USE_SUNRISE + feature_drv1 |= 0x02000000; +#endif +#ifdef USE_TIMERS_WEB + feature_drv1 |= 0x04000000; +#endif +#ifdef USE_RULES + feature_drv1 |= 0x08000000; +#endif +#ifdef USE_KNX + feature_drv1 |= 0x10000000; +#endif +#ifdef USE_WPS + feature_drv1 |= 0x20000000; +#endif +#ifdef USE_SMARTCONFIG + feature_drv1 |= 0x40000000; +#endif +#ifdef USE_ENERGY_POWER_LIMIT + feature_drv1 |= 0x80000000; +#endif + + + + feature_drv2 = 0x00000000; + +#ifdef USE_CONFIG_OVERRIDE + feature_drv2 |= 0x00000001; +#endif +#ifdef FIRMWARE_MINIMAL + feature_drv2 |= 0x00000002; +#endif +#ifdef FIRMWARE_SENSORS + feature_drv2 |= 0x00000004; +#endif +#ifdef FIRMWARE_CLASSIC + feature_drv2 |= 0x00000008; +#endif +#ifdef FIRMWARE_KNX_NO_EMULATION + feature_drv2 |= 0x00000010; +#endif +#ifdef USE_DISPLAY_MODES1TO5 + feature_drv2 |= 0x00000020; +#endif +#ifdef USE_DISPLAY_GRAPH + feature_drv2 |= 0x00000040; +#endif +#ifdef USE_DISPLAY_LCD + feature_drv2 |= 0x00000080; +#endif +#ifdef USE_DISPLAY_SSD1306 + feature_drv2 |= 0x00000100; +#endif +#ifdef USE_DISPLAY_MATRIX + feature_drv2 |= 0x00000200; +#endif +#ifdef USE_DISPLAY_ILI9341 + feature_drv2 |= 0x00000400; +#endif +#ifdef USE_DISPLAY_EPAPER_29 + feature_drv2 |= 0x00000800; +#endif +#ifdef USE_DISPLAY_SH1106 + feature_drv2 |= 0x00001000; +#endif +#ifdef USE_MP3_PLAYER + feature_drv2 |= 0x00002000; +#endif +#ifdef USE_PCA9685 + feature_drv2 |= 0x00004000; +#endif +#if defined(USE_LIGHT) && defined(USE_TUYA_MCU) + feature_drv2 |= 0x00008000; +#endif +#ifdef USE_RC_SWITCH + feature_drv2 |= 0x00010000; +#endif +#if defined(USE_LIGHT) && defined(USE_ARMTRONIX_DIMMERS) + feature_drv2 |= 0x00020000; +#endif +#if defined(USE_LIGHT) && defined(USE_SM16716) + feature_drv2 |= 0x00040000; +#endif +#ifdef USE_SCRIPT + feature_drv2 |= 0x00080000; +#endif +#ifdef USE_EMULATION_WEMO + feature_drv2 |= 0x00100000; +#endif +#ifdef USE_SONOFF_IFAN + feature_drv2 |= 0x00200000; +#endif +#ifdef USE_ZIGBEE + feature_drv2 |= 0x00400000; +#endif +#ifdef NO_EXTRA_4K_HEAP + feature_drv2 |= 0x00800000; +#endif +#ifdef VTABLES_IN_IRAM + feature_drv2 |= 0x01000000; +#endif +#ifdef VTABLES_IN_DRAM + feature_drv2 |= 0x02000000; +#endif +#ifdef VTABLES_IN_FLASH + feature_drv2 |= 0x04000000; +#endif +#ifdef PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH + feature_drv2 |= 0x08000000; +#endif +#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY + feature_drv2 |= 0x10000000; +#endif +#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH + feature_drv2 |= 0x20000000; +#endif +#ifdef DEBUG_THEO + feature_drv2 |= 0x40000000; +#endif +#ifdef USE_DEBUG_DRIVER + feature_drv2 |= 0x80000000; +#endif + + + + feature_sns1 = 0x00000000; + +#ifdef USE_COUNTER + feature_sns1 |= 0x00000001; +#endif +#ifdef USE_ADC_VCC + feature_sns1 |= 0x00000002; +#endif +#ifdef USE_ENERGY_SENSOR + feature_sns1 |= 0x00000004; +#endif +#ifdef USE_PZEM004T + feature_sns1 |= 0x00000008; +#endif +#ifdef USE_DS18B20 + feature_sns1 |= 0x00000010; +#endif +#ifdef USE_DS18x20_LEGACY + feature_sns1 |= 0x00000020; +#endif +#ifdef USE_DS18x20 + feature_sns1 |= 0x00000040; +#endif +#ifdef USE_DHT + feature_sns1 |= 0x00000080; +#endif +#ifdef USE_SHT + feature_sns1 |= 0x00000100; +#endif +#ifdef USE_HTU + feature_sns1 |= 0x00000200; +#endif +#ifdef USE_BMP + feature_sns1 |= 0x00000400; +#endif +#ifdef USE_BME680 + feature_sns1 |= 0x00000800; +#endif +#ifdef USE_BH1750 + feature_sns1 |= 0x00001000; +#endif +#ifdef USE_VEML6070 + feature_sns1 |= 0x00002000; +#endif +#ifdef USE_ADS1115_I2CDEV + feature_sns1 |= 0x00004000; +#endif +#ifdef USE_ADS1115 + feature_sns1 |= 0x00008000; +#endif +#ifdef USE_INA219 + feature_sns1 |= 0x00010000; +#endif +#ifdef USE_SHT3X + feature_sns1 |= 0x00020000; +#endif +#ifdef USE_MHZ19 + feature_sns1 |= 0x00040000; +#endif +#ifdef USE_TSL2561 + feature_sns1 |= 0x00080000; +#endif +#ifdef USE_SENSEAIR + feature_sns1 |= 0x00100000; +#endif +#ifdef USE_PMS5003 + feature_sns1 |= 0x00200000; +#endif +#ifdef USE_MGS + feature_sns1 |= 0x00400000; +#endif +#ifdef USE_NOVA_SDS + feature_sns1 |= 0x00800000; +#endif +#ifdef USE_SGP30 + feature_sns1 |= 0x01000000; +#endif +#ifdef USE_SR04 + feature_sns1 |= 0x02000000; +#endif +#ifdef USE_SDM120 + feature_sns1 |= 0x04000000; +#endif +#ifdef USE_SI1145 + feature_sns1 |= 0x08000000; +#endif +#ifdef USE_SDM630 + feature_sns1 |= 0x10000000; +#endif +#ifdef USE_LM75AD + feature_sns1 |= 0x20000000; +#endif +#ifdef USE_APDS9960 + feature_sns1 |= 0x40000000; +#endif +#ifdef USE_TM1638 + feature_sns1 |= 0x80000000; +#endif + + + + feature_sns2 = 0x00000000; + +#ifdef USE_MCP230xx + feature_sns2 |= 0x00000001; +#endif +#ifdef USE_MPR121 + feature_sns2 |= 0x00000002; +#endif +#ifdef USE_CCS811 + feature_sns2 |= 0x00000004; +#endif +#ifdef USE_MPU6050 + feature_sns2 |= 0x00000008; +#endif +#ifdef USE_MCP230xx_OUTPUT + feature_sns2 |= 0x00000010; +#endif +#ifdef USE_MCP230xx_DISPLAYOUTPUT + feature_sns2 |= 0x00000020; +#endif +#ifdef USE_HLW8012 + feature_sns2 |= 0x00000040; +#endif +#ifdef USE_CSE7766 + feature_sns2 |= 0x00000080; +#endif +#ifdef USE_MCP39F501 + feature_sns2 |= 0x00000100; +#endif +#ifdef USE_PZEM_AC + feature_sns2 |= 0x00000200; +#endif +#ifdef USE_DS3231 + feature_sns2 |= 0x00000400; +#endif +#ifdef USE_HX711 + feature_sns2 |= 0x00000800; +#endif +#ifdef USE_PZEM_DC + feature_sns2 |= 0x00001000; +#endif +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) + feature_sns2 |= 0x00002000; +#endif +#ifdef USE_MGC3130 + feature_sns2 |= 0x00004000; +#endif +#ifdef USE_RF_SENSOR + feature_sns2 |= 0x00008000; +#endif +#ifdef USE_THEO_V2 + feature_sns2 |= 0x00010000; +#endif +#ifdef USE_ALECTO_V2 + feature_sns2 |= 0x00020000; +#endif +#ifdef USE_AZ7798 + feature_sns2 |= 0x00040000; +#endif +#ifdef USE_MAX31855 + feature_sns2 |= 0x00080000; +#endif +#ifdef USE_PN532_HSU + feature_sns2 |= 0x00100000; +#endif +#ifdef USE_MAX44009 + feature_sns2 |= 0x00200000; +#endif +#ifdef USE_SCD30 + feature_sns2 |= 0x00400000; +#endif +#ifdef USE_HRE + feature_sns2 |= 0x00800000; +#endif +#ifdef USE_ADE7953 + feature_sns2 |= 0x01000000; +#endif +#ifdef USE_SPS30 + feature_sns2 |= 0x02000000; +#endif +#ifdef USE_VL53L0X + feature_sns2 |= 0x04000000; +#endif +#ifdef USE_MLX90614 + feature_sns2 |= 0x08000000; +#endif +#ifdef USE_MAX31865 + feature_sns2 |= 0x10000000; +#endif +#ifdef USE_CHIRP + feature_sns2 |= 0x20000000; +#endif +#ifdef USE_SOLAX_X1 + feature_sns2 |= 0x40000000; +#endif +#ifdef USE_PAJ7620 + feature_sns2 |= 0x80000000; +#endif + + + + feature5 = 0x00000000; + +#ifdef USE_BUZZER + feature5 |= 0x00000001; +#endif +#ifdef USE_RDM6300 + feature5 |= 0x00000002; +#endif +#ifdef USE_IBEACON + feature5 |= 0x00000004; +#endif +#ifdef USE_SML_M + feature5 |= 0x00000008; +#endif +#ifdef USE_INA226 + feature5 |= 0x00000010; +#endif +#ifdef USE_A4988_STEPPER + feature5 |= 0x00000020; +#endif +#ifdef USE_DDS2382 + feature5 |= 0x00000040; +#endif +#ifdef USE_SM2135 + feature5 |= 0x00000080; +#endif +#ifdef USE_SHUTTER + feature5 |= 0x00000100; +#endif +#ifdef USE_PCF8574 + feature5 |= 0x00000200; +#endif +#ifdef USE_DDSU666 + feature5 |= 0x00000400; +#endif +#ifdef USE_DEEPSLEEP + feature5 |= 0x00000800; +#endif +#ifdef USE_SONOFF_SC + feature5 |= 0x00001000; +#endif +#ifdef USE_SONOFF_RF + feature5 |= 0x00002000; +#endif +#ifdef USE_SONOFF_L1 + feature5 |= 0x00004000; +#endif +#ifdef USE_EXS_DIMMER + feature5 |= 0x00008000; +#endif +#ifdef USE_ARDUINO_SLAVE + feature5 |= 0x00010000; +#endif +#ifdef USE_HIH6 + feature5 |= 0x00020000; +#endif +#ifdef USE_HPMA + feature5 |= 0x00040000; +#endif +#ifdef USE_TSL2591 + feature5 |= 0x00080000; +#endif +#ifdef USE_DHT12 + feature5 |= 0x00100000; +#endif +#ifdef USE_DS1624 + feature5 |= 0x00200000; +#endif +#ifdef USE_GPS + feature5 |= 0x00400000; +#endif +#ifdef USE_HOTPLUG + feature5 |= 0x00800000; +#endif +#ifdef USE_NRF24 + feature5 |= 0x01000000; +#endif +#ifdef USE_MIBLE + feature5 |= 0x02000000; +#endif +#ifdef USE_HM10 + feature5 |= 0x04000000; +#endif +#ifdef USE_LE01MR + feature5 |= 0x08000000; +#endif +#ifdef USE_AHT1x + feature5 |= 0x10000000; +#endif +#ifdef USE_WEMOS_MOTOR_V1 + feature5 |= 0x20000000; +#endif + + + + + + + feature6 = 0x00000000; +# 570 "S:/Development/Tasmota/tasmota/support_features.ino" +} +# 1 "S:/Development/Tasmota/tasmota/support_flash_log.ino" +# 39 "S:/Development/Tasmota/tasmota/support_flash_log.ino" +#ifdef USE_FLOG + +class FLOG + +#define MAGIC_WORD_FL 0x464c + +{ + +struct header_t{ + uint16_t magic_word; + uint16_t padding; + uint32_t physical_start_sector:10; + uint32_t number:10; + uint32_t buf_pointer:12; + }; + +private: +void _readSector(uint8_t one_sector); +void _eraseSector(uint8_t one_sector); +void _writeSector(uint8_t one_sector); +void _clearBuffer(void); +void _searchSaves(void); +void _findFirstErasedSector(void); +void _showBuffer(void); +void _initBuffer(void); +void _saveBufferToSector(void); +header_t _saved_header; + +public: + uint32_t size; + uint32_t start; + uint32_t end; + uint16_t num_sectors; + + uint16_t first_erased_sector; + uint16_t current_sector; + + uint16_t bytes_left; + uint16_t sectors_left; + + uint8_t mode = 0; + bool found_saved_data = false; + bool ready = false; + bool running_download = false; + bool recording = false; + + union sector_t{ + uint32_t dword_buffer[FLASH_SECTOR_SIZE/4]; + uint8_t byte_buffer[FLASH_SECTOR_SIZE]; + header_t header; + } sector; + + void init(void); + void addToBuffer(uint8_t src[], uint32_t size); + void startRecording(bool append); + void stopRecording(void); + + typedef void (*CallbackNoArgs) (); + typedef void (*CallbackWithArgs) (uint8_t *_record); + + void startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter); +}; + +extern "C" uint32_t _SPIFFS_start; +extern "C" uint32_t _FS_start; + + + + +void FLOG::init(void) +{ +DEBUG_SENSOR_LOG(PSTR("FLOG: init ...")); +size = ESP.getSketchSize(); + +start = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) +end = (uint32_t)&_SPIFFS_start - 0x40200000; +#else +end = (uint32_t)&_FS_start - 0x40200000; +#endif +num_sectors = (end - start)/FLASH_SECTOR_SIZE; +DEBUG_SENSOR_LOG(PSTR("FLOG: size: 0x%lx, start: 0x%lx, end: 0x%lx, num_sectors(dec): %lu"), size, start, end, num_sectors ); +_findFirstErasedSector(); +if(first_erased_sector == 0xffff){ + _eraseSector(0); + first_erased_sector = 0; +} +_searchSaves(); +_initBuffer(); +ready = true; +} +# 142 "S:/Development/Tasmota/tasmota/support_flash_log.ino" +void FLOG::_readSector(uint8_t one_sector){ + DEBUG_SENSOR_LOG(PSTR("FLOG: read sector number: %u" ), one_sector); + ESP.flashRead(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); +} + + + + + +void FLOG::_eraseSector(uint8_t one_sector){ + DEBUG_SENSOR_LOG(PSTR("FLOG: erasing sector number: %u" ), one_sector); + ESP.flashEraseSector((start/FLASH_SECTOR_SIZE)+one_sector); +} + + + + + +void FLOG::_writeSector(uint8_t one_sector){ + DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to sector number: %u" ), one_sector); + ESP.flashWrite(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); +} + + + + +void FLOG::_clearBuffer(){ + for (uint32_t i = sizeof(sector.header)/4; i<(sizeof(sector.dword_buffer)/4); i++){ + sector.dword_buffer[i] = 0; + } + sector.header.buf_pointer = sizeof(sector.header); + +} + + + + +void FLOG::_saveBufferToSector(){ + DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to current sector: %u" ),current_sector); + _writeSector(current_sector); + if(current_sector == num_sectors){ + current_sector = 0; + } + else{ + current_sector++; + } + _eraseSector(current_sector); + _clearBuffer(); + sector.header.number++; + DEBUG_SENSOR_LOG(PSTR("FLOG: new sector header number: %u" ),sector.header.number); +} + + + + + +void FLOG::_findFirstErasedSector(){ + for (uint32_t i = 0; i3){ + break; + } + } +} + + + + + + + +void FLOG::addToBuffer(uint8_t src[], uint32_t size){ + if(mode == 0){ + if(sector.header.number == num_sectors && !ready){ + return; + } + } + if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ + + + + memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); + sector.header.buf_pointer+=size; + + } + else{ + DEBUG_SENSOR_LOG(PSTR("FLOG: save buffer to flash sector: %u"), current_sector); + DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); + _saveBufferToSector(); + sectors_left++; + + if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ + memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); + sector.header.buf_pointer+=size; + } + } +} + + + + + + +void FLOG::startRecording(bool append){ + if(recording){ + DEBUG_SENSOR_LOG(PSTR("FLOG: already recording")); + return; + } + recording = true; + DEBUG_SENSOR_LOG(PSTR("FLOG: start recording")); + _initBuffer(); + if(!found_saved_data) { + append = false; + } + if(append){ + sector.header.number = _saved_header.number+1; + sector.header.physical_start_sector = _saved_header.physical_start_sector; + } + else{ + sector.header.physical_start_sector = (uint16_t)first_erased_sector; + found_saved_data = false; + sectors_left = 0; + } + } + + + + + +void FLOG::stopRecording(void){ + _saveBufferToSector(); + _findFirstErasedSector(); + _searchSaves(); + _initBuffer(); + recording = false; + found_saved_data = true; + } +# 381 "S:/Development/Tasmota/tasmota/support_flash_log.ino" + void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ + + _readSector(sector.header.physical_start_sector); + uint32_t next_sector = sector.header.physical_start_sector; + bytes_left = sector.header.buf_pointer - sizeof(sector.header); + DEBUG_SENSOR_LOG(PSTR("FLOG: create file for download, will process %u bytes"), bytes_left); + running_download = true; + + sendHeader(); + + while(sectors_left){ + DEBUG_SENSOR_LOG(PSTR("FLOG: next sector: %u"), next_sector); + + uint32_t k = sizeof(sector.header); + while(bytes_left){ + + uint8_t *_record_start = (uint8_t*)§or.byte_buffer[k]; + + sendRecord(_record_start); + if(k%128 == 0){ + + OsWatchLoop(); + delay(sleep); + } + k+=size; + if(bytes_left>7){ + bytes_left-=size; + } + else{ + bytes_left = 0; + DEBUG_SENSOR_LOG(PSTR("FLOG: Flog->bytes_left not dividable by 8 ??????")); + } + } + next_sector++; + if(next_sector>num_sectors){ + next_sector = 0; + } + sectors_left--; + _readSector(next_sector); + bytes_left = sector.header.buf_pointer - sizeof(sector.header); + OsWatchLoop(); + delay(sleep); + } + running_download = false; + + sendFooter(); + + _searchSaves(); + _initBuffer(); + } + + #endif +# 1 "S:/Development/Tasmota/tasmota/support_float.ino" +# 23 "S:/Development/Tasmota/tasmota/support_float.ino" +float fmodf(float x, float y) +{ + + union {float f; uint32_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>23 & 0xff; + int ey = uy.i>>23 & 0xff; + uint32_t sx = ux.i & 0x80000000; + uint32_t i; + uint32_t uxi = ux.i; + + if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) + return (x*y)/(x*y); + if (uxi<<1 <= uy.i<<1) { + if (uxi<<1 == uy.i<<1) + return 0*x; + return x; + } + + + if (!ex) { + for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1U >> 9; + uxi |= 1U << 23; + } + if (!ey) { + for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1U >> 9; + uy.i |= 1U << 23; + } + + + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 31 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + uxi <<= 1; + } + i = uxi - uy.i; + if (i >> 31 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + for (; uxi>>23 == 0; uxi <<= 1, ex--); + + + if (ex > 0) { + uxi -= 1U << 23; + uxi |= (uint32_t)ex << 23; + } else { + uxi >>= -ex + 1; + } + uxi |= sx; + ux.i = uxi; + return ux.f; +} + + +double FastPrecisePow(double a, double b) +{ + + + int e = abs((int)b); + union { + double d; + int x[2]; + } u = { a }; + u.x[1] = (int)((b - e) * (u.x[1] - 1072632447) + 1072632447); + u.x[0] = 0; + + + double r = 1.0; + while (e) { + if (e & 1) { + r *= a; + } + a *= a; + e >>= 1; + } + return r * u.d; +} + +float FastPrecisePowf(const float x, const float y) +{ + + return (float)FastPrecisePow(x, y); +} + +double TaylorLog(double x) +{ + + + if (x <= 0.0) { return NAN; } + double z = (x + 1) / (x - 1); + double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); + double totalValue = 0; + double powe = 1; + for (uint32_t count = 0; count < 10; count++) { + z *= step; + double y = (1 / powe) * z; + totalValue = totalValue + y; + powe = powe + 2; + } + totalValue *= 2; +# 144 "S:/Development/Tasmota/tasmota/support_float.ino" + return totalValue; +} +# 154 "S:/Development/Tasmota/tasmota/support_float.ino" +inline float sinf(float x) { return sin_52(x); } +inline float cosf(float x) { return cos_52(x); } +inline float tanf(float x) { return tan_56(x); } +inline float atanf(float x) { return atan_66(x); } +inline float asinf(float x) { return asinf1(x); } +inline float acosf(float x) { return acosf1(x); } +inline float sqrtf(float x) { return sqrt1(x); } +inline float powf(float x, float y) { return FastPrecisePow(x, y); } + + +double const f_pi = 3.1415926535897932384626433; +double const f_twopi = 2.0 * f_pi; +double const f_two_over_pi = 2.0 / f_pi; +double const f_halfpi = f_pi / 2.0; +double const f_threehalfpi = 3.0 * f_pi / 2.0; +double const f_four_over_pi = 4.0 / f_pi; +double const f_qtrpi = f_pi / 4.0; +double const f_sixthpi = f_pi / 6.0; +double const f_tansixthpi = tan(f_sixthpi); +double const f_twelfthpi = f_pi / 12.0; +double const f_tantwelfthpi = tan(f_twelfthpi); +float const f_180pi = 180 / f_pi; +# 194 "S:/Development/Tasmota/tasmota/support_float.ino" +float cos_52s(float x) +{ + const float c1 = 0.9999932946; + const float c2 = -0.4999124376; + const float c3 = 0.0414877472; + const float c4 = -0.0012712095; + + float x2 = x * x; + return (c1 + x2 * (c2 + x2 * (c3 + c4 * x2))); +} + + + + + + +float cos_52(float x) +{ + x = fmodf(x, f_twopi); + if (x < 0) { x = -x; } + int quad = int(x * (float)f_two_over_pi); + switch (quad) { + case 0: return cos_52s(x); + case 1: return -cos_52s((float)f_pi - x); + case 2: return -cos_52s(x-(float)f_pi); + case 3: return cos_52s((float)f_twopi - x); + } +} + + + + +float sin_52(float x) +{ + return cos_52((float)f_halfpi - x); +} +# 247 "S:/Development/Tasmota/tasmota/support_float.ino" +float tan_56s(float x) +{ + const float c1 = -3.16783027; + const float c2 = 0.134516124; + const float c3 = -4.033321984; + + float x2 = x * x; + return (x * (c1 + c2 * x2) / (c3 + x2)); +} +# 267 "S:/Development/Tasmota/tasmota/support_float.ino" +float tan_56(float x) +{ + x = fmodf(x, (float)f_twopi); + int octant = int(x * (float)f_four_over_pi); + switch (octant){ + case 0: return tan_56s(x * (float)f_four_over_pi); + case 1: return 1.0f / tan_56s(((float)f_halfpi - x) * (float)f_four_over_pi); + case 2: return -1.0f / tan_56s((x-(float)f_halfpi) * (float)f_four_over_pi); + case 3: return - tan_56s(((float)f_pi - x) * (float)f_four_over_pi); + case 4: return tan_56s((x-(float)f_pi) * (float)f_four_over_pi); + case 5: return 1.0f / tan_56s(((float)f_threehalfpi - x) * (float)f_four_over_pi); + case 6: return -1.0f / tan_56s((x-(float)f_threehalfpi) * (float)f_four_over_pi); + case 7: return - tan_56s(((float)f_twopi - x) * (float)f_four_over_pi); + } +} +# 296 "S:/Development/Tasmota/tasmota/support_float.ino" +float atan_66s(float x) +{ + const float c1 = 1.6867629106; + const float c2 = 0.4378497304; + const float c3 = 1.6867633134; + + float x2 = x * x; + return (x * (c1 + x2 * c2) / (c3 + x2)); +} + + + + + +float atan_66(float x) +{ + float y; + bool complement= false; + bool region= false; + bool sign= false; + + if (x < 0) { + x = -x; + sign = true; + } + if (x > 1.0) { + x = 1.0 / x; + complement = true; + } + if (x > (float)f_tantwelfthpi) { + x = (x - (float)f_tansixthpi) / (1 + (float)f_tansixthpi * x); + region = true; + } + + y = atan_66s(x); + if (region) { y += (float)f_sixthpi; } + if (complement) { y = (float)f_halfpi-y; } + if (sign) { y = -y; } + return (y); +} + +float asinf1(float x) +{ + float d = 1.0f - x * x; + if (d < 0.0f) { return NAN; } + return 2 * atan_66(x / (1 + sqrt1(d))); +} + +float acosf1(float x) +{ + float d = 1.0f - x * x; + if (d < 0.0f) { return NAN; } + float y = asinf1(sqrt1(d)); + if (x >= 0.0f) { + return y; + } else { + return (float)f_pi - y; + } +} + + +float sqrt1(const float x) +{ + union { + int i; + float x; + } u; + u.x = x; + u.i = (1 << 29) + (u.i >> 1) - (1 << 22); + + + + + u.x = u.x + x / u.x; + u.x = 0.25f * u.x + x / u.x; + + return u.x; +} +# 387 "S:/Development/Tasmota/tasmota/support_float.ino" +uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, + uint16_t ito_min, uint16_t ito_max) { + + if (ifrom_min >= ifrom_max) { + if (ito_min > ito_max) { + return ito_max; + } else { + return ito_min; + } + } + + uint32_t num = inum; + uint32_t from_min = ifrom_min; + uint32_t from_max = ifrom_max; + uint32_t to_min = ito_min; + uint32_t to_max = ito_max; + + + num = (num > from_max ? from_max : (num < from_min ? from_min : num)); + + + if (to_min > to_max) { + + num = (from_max - num) + from_min; + to_min = ito_max; + to_max = ito_min; + } + + uint32_t numerator = (num - from_min) * (to_max - to_min); + uint32_t result; + if (numerator >= 0x80000000L) { + + result = numerator / (from_max - from_min) + to_min; + } else { + result = (((numerator * 2) / (from_max - from_min)) + 1) / 2 + to_min; + } + return (uint32_t) (result > to_max ? to_max : (result < to_min ? to_min : result)); +} +# 1 "S:/Development/Tasmota/tasmota/support_legacy_cores.ino" +# 20 "S:/Development/Tasmota/tasmota/support_legacy_cores.ino" +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + + + + + +void* memchr(const void* ptr, int value, size_t num) +{ + unsigned char *p = (unsigned char*)ptr; + while (num--) { + if (*p != (unsigned char)value) { + p++; + } else { + return p; + } + } + return 0; +} + + + +size_t strcspn(const char *str1, const char *str2) +{ + size_t ret = 0; + while (*str1) { + if (strchr(str2, *str1)) { + return ret; + } else { + str1++; + ret++; + } + } + return ret; +} + + + +char* strpbrk(const char *s1, const char *s2) +{ + while(*s1) { + if (strchr(s2, *s1++)) { + return (char*)--s1; + } + } + return 0; +} + + + +#ifndef __LONG_LONG_MAX__ +#define __LONG_LONG_MAX__ 9223372036854775807LL +#endif +#ifndef ULLONG_MAX +#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) +#endif + +unsigned long long strtoull(const char *__restrict nptr, char **__restrict endptr, int base) +{ + const char *s = nptr; + char c; + do { c = *s++; } while (isspace((unsigned char)c)); + + int neg = 0; + if (c == '-') { + neg = 1; + c = *s++; + } else { + if (c == '+') { + c = *s++; + } + } + + if ((base == 0 || base == 16) && (c == '0') && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) { base = (c == '0') ? 8 : 10; } + + unsigned long long acc = 0; + int any = 0; + if (base > 1 && base < 37) { + unsigned long long cutoff = ULLONG_MAX / base; + int cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + + if (c >= base) + break; + + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + } + else if (any && neg) { + acc = -acc; + } + } + + if (endptr != nullptr) { *endptr = (char *)(any ? s - 1 : nptr); } + + return acc; +} + +#endif + + + +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) + + + + + +void* memmove_P(void *dest, const void *src, size_t n) +{ + if (src > (void*)0x40000000) { + return memcpy_P(dest, src, n); + } else { + return memmove(dest, src, n); + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/support_rotary.ino" +# 20 "S:/Development/Tasmota/tasmota/support_rotary.ino" +#ifdef USE_LIGHT + +#ifdef ROTARY_V1 + + + + +struct ROTARY { + unsigned long debounce = 0; + uint8_t present = 0; + uint8_t state = 0; + uint8_t position = 128; + uint8_t last_position = 128; + uint8_t interrupts_in_use_count = 0; + uint8_t changed = 0; +} Rotary; + + + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +void update_rotary(void) ICACHE_RAM_ATTR; +#endif + +void update_rotary(void) +{ + if (MI_DESK_LAMP == my_module_type) { + if (LightPowerIRAM()) { + + + + + uint8_t s = Rotary.state & 3; + if (digitalRead(pin[GPIO_ROT1A])) { s |= 4; } + if (digitalRead(pin[GPIO_ROT1B])) { s |= 8; } + switch (s) { + case 0: case 5: case 10: case 15: + break; + case 1: case 7: case 8: case 14: + Rotary.position++; break; + case 2: case 4: case 11: case 13: + Rotary.position--; break; + case 3: case 12: + Rotary.position = Rotary.position + 2; break; + default: + Rotary.position = Rotary.position - 2; break; + } + Rotary.state = (s >> 2); + } + } +} + +bool RotaryButtonPressed(void) +{ + if ((MI_DESK_LAMP == my_module_type) && (Rotary.changed) && LightPower()) { + Rotary.changed = 0; + return true; + } + return false; +} + +void RotaryInit(void) +{ + Rotary.present = 0; + if ((pin[GPIO_ROT1A] < 99) && (pin[GPIO_ROT1B] < 99)) { + Rotary.present++; + pinMode(pin[GPIO_ROT1A], INPUT_PULLUP); + pinMode(pin[GPIO_ROT1B], INPUT_PULLUP); + + + + + if ((pin[GPIO_ROT1A] < 6) || (pin[GPIO_ROT1A] > 11)) { + attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1A]), update_rotary, CHANGE); + Rotary.interrupts_in_use_count++; + } + if ((pin[GPIO_ROT1B] < 6) || (pin[GPIO_ROT1B] > 11)) { + attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1B]), update_rotary, CHANGE); + Rotary.interrupts_in_use_count++; + } + } +} + + + + + +void RotaryHandler(void) +{ + if (Rotary.interrupts_in_use_count < 2) { + noInterrupts(); + update_rotary(); + } else { + noInterrupts(); + } + if (Rotary.last_position != Rotary.position) { + if (MI_DESK_LAMP == my_module_type) { + if (Button.hold_timer[0]) { + Rotary.changed = 1; + + int16_t t = LightGetColorTemp(); + t = t + (Rotary.position - Rotary.last_position); + if (t < 153) { + t = 153; + } + if (t > 500) { + t = 500; + } + DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_COLORTEMPERATURE " %d"), Rotary.position - Rotary.last_position); + LightSetColorTemp((uint16_t)t); + } else { + int8_t d = Settings.light_dimmer; + d = d + (Rotary.position - Rotary.last_position); + if (d < 1) { + d = 1; + } + if (d > 100) { + d = 100; + } + DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_DIMMER " %d"), Rotary.position - Rotary.last_position); + + LightSetDimmer((uint8_t)d); + Settings.light_dimmer = d; + } + } + Rotary.last_position = 128; + Rotary.position = 128; + } + interrupts(); +} + +void RotaryLoop(void) +{ + if (Rotary.present) { + if (TimeReached(Rotary.debounce)) { + SetNextTimeInterval(Rotary.debounce, Settings.button_debounce); + RotaryHandler(); + } + } +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/support_rtc.ino" +# 25 "S:/Development/Tasmota/tasmota/support_rtc.ino" +const uint32_t SECS_PER_MIN = 60UL; +const uint32_t SECS_PER_HOUR = 3600UL; +const uint32_t SECS_PER_DAY = SECS_PER_HOUR * 24UL; +const uint32_t MINS_PER_HOUR = 60UL; + +#define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) + +extern "C" { +#include "sntp.h" +} +#include + +Ticker TickerRtc; + +static const uint8_t kDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static const char kMonthNamesEnglish[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + +struct RTC { + uint32_t utc_time = 0; + uint32_t local_time = 0; + uint32_t daylight_saving_time = 0; + uint32_t standard_time = 0; + uint32_t ntp_time = 0; + uint32_t midnight = 0; + uint32_t restart_time = 0; + int32_t time_timezone = 0; + uint8_t ntp_sync_minute = 0; + bool midnight_now = false; + bool user_time_entry = false; +} Rtc; + +uint32_t UtcTime(void) +{ + return Rtc.utc_time; +} + +uint32_t LocalTime(void) +{ + return Rtc.local_time; +} + +uint32_t Midnight(void) +{ + return Rtc.midnight; +} + +bool MidnightNow(void) +{ + if (Rtc.midnight_now) { + Rtc.midnight_now = false; + return true; + } + return false; +} + +bool IsDst(void) +{ + if (Rtc.time_timezone == Settings.toffset[1]) { + return true; + } + return false; +} + +String GetBuildDateAndTime(void) +{ + + char bdt[21]; + char *p; + char mdate[] = __DATE__; + char *smonth = mdate; + int day = 0; + int year = 0; + + + uint8_t i = 0; + for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(nullptr, " ", &p)) { + switch (i++) { + case 0: + smonth = str; + break; + case 1: + day = atoi(str); + break; + case 2: + year = atoi(str); + } + } + int month = (strstr(kMonthNamesEnglish, smonth) -kMonthNamesEnglish) /3 +1; + snprintf_P(bdt, sizeof(bdt), PSTR("%d" D_YEAR_MONTH_SEPARATOR "%02d" D_MONTH_DAY_SEPARATOR "%02d" D_DATE_TIME_SEPARATOR "%s"), year, month, day, __TIME__); + return String(bdt); +} + +String GetMinuteTime(uint32_t minutes) +{ + char tm[6]; + snprintf_P(tm, sizeof(tm), PSTR("%02d:%02d"), minutes / 60, minutes % 60); + + return String(tm); +} + +String GetTimeZone(void) +{ + char tz[7]; + snprintf_P(tz, sizeof(tz), PSTR("%+03d:%02d"), Rtc.time_timezone / 60, abs(Rtc.time_timezone % 60)); + + return String(tz); +} + +String GetDuration(uint32_t time) +{ + char dt[16]; + + TIME_T ut; + BreakTime(time, ut); + + + + + + + snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second); + + return String(dt); +} + +String GetDT(uint32_t time) +{ + + + char dt[20]; + TIME_T tmpTime; + + BreakTime(time, tmpTime); + snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), + tmpTime.year +1970, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); + + return String(dt); +} +# 175 "S:/Development/Tasmota/tasmota/support_rtc.ino" +String GetDateAndTime(uint8_t time_type) +{ + + uint32_t time = Rtc.local_time; + + switch (time_type) { + case DT_UTC: + time = Rtc.utc_time; + break; + + + + case DT_DST: + time = Rtc.daylight_saving_time; + break; + case DT_STD: + time = Rtc.standard_time; + break; + case DT_RESTART: + if (Rtc.restart_time == 0) { + return ""; + } + time = Rtc.restart_time; + break; + case DT_ENERGY: + time = Settings.energy_kWhtotal_time; + break; + case DT_BOOTCOUNT: + time = Settings.bootcount_reset_time; + break; + } + String dt = GetDT(time); + if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { + dt += GetTimeZone(); + } + return dt; +} + +uint32_t UpTime(void) +{ + if (Rtc.restart_time) { + return Rtc.utc_time - Rtc.restart_time; + } else { + return uptime; + } +} + +uint32_t MinutesUptime(void) +{ + return (UpTime() / 60); +} + +String GetUptime(void) +{ + return GetDuration(UpTime()); +} + +uint32_t MinutesPastMidnight(void) +{ + uint32_t minutes = 0; + + if (RtcTime.valid) { + minutes = (RtcTime.hour *60) + RtcTime.minute; + } + return minutes; +} + +void BreakTime(uint32_t time_input, TIME_T &tm) +{ + + + + + uint8_t year; + uint8_t month; + uint8_t month_length; + uint32_t time; + unsigned long days; + + time = time_input; + tm.second = time % 60; + time /= 60; + tm.minute = time % 60; + time /= 60; + tm.hour = time % 24; + time /= 24; + tm.days = time; + tm.day_of_week = ((time + 4) % 7) + 1; + + year = 0; + days = 0; + while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { + year++; + } + tm.year = year; + + days -= LEAP_YEAR(year) ? 366 : 365; + time -= days; + tm.day_of_year = time; + + for (month = 0; month < 12; month++) { + if (1 == month) { + if (LEAP_YEAR(year)) { + month_length = 29; + } else { + month_length = 28; + } + } else { + month_length = kDaysInMonth[month]; + } + + if (time >= month_length) { + time -= month_length; + } else { + break; + } + } + strlcpy(tm.name_of_month, kMonthNames + (month *3), 4); + tm.month = month + 1; + tm.day_of_month = time + 1; + tm.valid = (time_input > START_VALID_TIME); +} + +uint32_t MakeTime(TIME_T &tm) +{ + + + + int i; + uint32_t seconds; + + + seconds = tm.year * (SECS_PER_DAY * 365); + for (i = 0; i < tm.year; i++) { + if (LEAP_YEAR(i)) { + seconds += SECS_PER_DAY; + } + } + + + for (i = 1; i < tm.month; i++) { + if ((2 == i) && LEAP_YEAR(tm.year)) { + seconds += SECS_PER_DAY * 29; + } else { + seconds += SECS_PER_DAY * kDaysInMonth[i-1]; + } + } + seconds+= (tm.day_of_month - 1) * SECS_PER_DAY; + seconds+= tm.hour * SECS_PER_HOUR; + seconds+= tm.minute * SECS_PER_MIN; + seconds+= tm.second; + return seconds; +} + +uint32_t RuleToTime(TimeRule r, int yr) +{ + TIME_T tm; + uint32_t t; + uint8_t m; + uint8_t w; + + m = r.month; + w = r.week; + if (0 == w) { + if (++m > 12) { + m = 1; + yr++; + } + w = 1; + } + + tm.hour = r.hour; + tm.minute = 0; + tm.second = 0; + tm.day_of_month = 1; + tm.month = m; + tm.year = yr - 1970; + t = MakeTime(tm); + BreakTime(t, tm); + t += (7 * (w - 1) + (r.dow - tm.day_of_week + 7) % 7) * SECS_PER_DAY; + if (0 == r.week) { + t -= 7 * SECS_PER_DAY; + } + return t; +} + +void RtcSecond(void) +{ + TIME_T tmpTime; + + if (!Rtc.user_time_entry && !global_state.wifi_down) { + uint8_t uptime_minute = (uptime / 60) % 60; + if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) { + Rtc.ntp_sync_minute = 1; + } + uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; + if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || + (Rtc.ntp_sync_minute == uptime_minute))) || + ntp_force_sync ) ) { + Rtc.ntp_time = sntp_get_current_timestamp(); + if (Rtc.ntp_time > START_VALID_TIME) { + ntp_force_sync = false; + Rtc.utc_time = Rtc.ntp_time; + Rtc.ntp_sync_minute = 60; + if (Rtc.restart_time == 0) { + Rtc.restart_time = Rtc.utc_time - uptime; + } + BreakTime(Rtc.utc_time, tmpTime); + RtcTime.year = tmpTime.year + 1970; + Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); + Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); + + + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); + + if (Rtc.local_time < START_VALID_TIME) { + rules_flag.time_init = 1; + } else { + rules_flag.time_set = 1; + } + } else { + Rtc.ntp_sync_minute++; + } + } + } + + Rtc.utc_time++; + Rtc.local_time = Rtc.utc_time; + if (Rtc.local_time > START_VALID_TIME) { + int16_t timezone_minutes = Settings.timezone_minutes; + if (Settings.timezone < 0) { timezone_minutes *= -1; } + Rtc.time_timezone = (Settings.timezone * SECS_PER_HOUR) + (timezone_minutes * SECS_PER_MIN); + if (99 == Settings.timezone) { + int32_t dstoffset = Settings.toffset[1] * SECS_PER_MIN; + int32_t stdoffset = Settings.toffset[0] * SECS_PER_MIN; + if (Settings.tflag[1].hemis) { + + if ((Rtc.utc_time >= (Rtc.standard_time - dstoffset)) && (Rtc.utc_time < (Rtc.daylight_saving_time - stdoffset))) { + Rtc.time_timezone = stdoffset; + } else { + Rtc.time_timezone = dstoffset; + } + } else { + + if ((Rtc.utc_time >= (Rtc.daylight_saving_time - stdoffset)) && (Rtc.utc_time < (Rtc.standard_time - dstoffset))) { + Rtc.time_timezone = dstoffset; + } else { + Rtc.time_timezone = stdoffset; + } + } + } + Rtc.local_time += Rtc.time_timezone; + Rtc.time_timezone /= 60; + if (!Settings.energy_kWhtotal_time) { + Settings.energy_kWhtotal_time = Rtc.local_time; + } + if (Settings.bootcount_reset_time < START_VALID_TIME) { + Settings.bootcount_reset_time = Rtc.local_time; + } + } + + BreakTime(Rtc.local_time, RtcTime); + if (RtcTime.valid) { + if (!Rtc.midnight) { + Rtc.midnight = Rtc.local_time - (RtcTime.hour * 3600) - (RtcTime.minute * 60) - RtcTime.second; + } + if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { + Rtc.midnight = Rtc.local_time; + Rtc.midnight_now = true; + } + } + + RtcTime.year += 1970; +} + +void RtcSetTime(uint32_t epoch) +{ + if (epoch < START_VALID_TIME) { + Rtc.user_time_entry = false; + ntp_force_sync = true; + sntp_init(); + } else { + sntp_stop(); + Rtc.user_time_entry = true; + Rtc.utc_time = epoch -1; + } + RtcSecond(); +} + +void RtcInit(void) +{ + sntp_setservername(0, SettingsText(SET_NTPSERVER1)); + sntp_setservername(1, SettingsText(SET_NTPSERVER2)); + sntp_setservername(2, SettingsText(SET_NTPSERVER3)); + sntp_stop(); + sntp_set_timezone(0); + sntp_init(); + Rtc.utc_time = 0; + BreakTime(Rtc.utc_time, RtcTime); + TickerRtc.attach(1, RtcSecond); +} +# 1 "S:/Development/Tasmota/tasmota/support_static_buffer.ino" +# 20 "S:/Development/Tasmota/tasmota/support_static_buffer.ino" +typedef struct SBuffer_impl { + uint16_t size; + uint16_t len; + uint8_t buf[]; +} SBuffer_impl; + + + +typedef class SBuffer { + +protected: + SBuffer(void) { + + } + +public: + SBuffer(const size_t size) { + _buf = (SBuffer_impl*) new char[size+4]; + _buf->size = size; + _buf->len = 0; + + } + + inline size_t getSize(void) const { return _buf->size; } + inline size_t size(void) const { return _buf->size; } + inline size_t getLen(void) const { return _buf->len; } + inline size_t len(void) const { return _buf->len; } + inline uint8_t *getBuffer(void) const { return _buf->buf; } + inline uint8_t *buf(size_t i = 0) const { return &_buf->buf[i]; } + inline char *charptr(size_t i = 0) const { return (char*) &_buf->buf[i]; } + + virtual ~SBuffer(void) { + delete[] _buf; + } + + inline void setLen(const size_t len) { + uint16_t old_len = _buf->len; + _buf->len = (len <= _buf->size) ? len : _buf->size; + if (old_len < _buf->len) { + memset((void*) &_buf->buf[old_len], 0, _buf->len - old_len); + } + } + + void set8(const size_t offset, const uint8_t data) { + if (offset < _buf->len) { + _buf->buf[offset] = data; + } + } + + size_t add8(const uint8_t data) { + if (_buf->len < _buf->size) { + _buf->buf[_buf->len++] = data; + } + return _buf->len; + } + size_t add16(const uint16_t data) { + if (_buf->len < _buf->size - 1) { + _buf->buf[_buf->len++] = data; + _buf->buf[_buf->len++] = data >> 8; + } + return _buf->len; + } + size_t add32(const uint32_t data) { + if (_buf->len < _buf->size - 3) { + _buf->buf[_buf->len++] = data; + _buf->buf[_buf->len++] = data >> 8; + _buf->buf[_buf->len++] = data >> 16; + _buf->buf[_buf->len++] = data >> 24; + } + return _buf->len; + } + size_t add64(const uint64_t data) { + if (_buf->len < _buf->size - 7) { + _buf->buf[_buf->len++] = data; + _buf->buf[_buf->len++] = data >> 8; + _buf->buf[_buf->len++] = data >> 16; + _buf->buf[_buf->len++] = data >> 24; + _buf->buf[_buf->len++] = data >> 32; + _buf->buf[_buf->len++] = data >> 40; + _buf->buf[_buf->len++] = data >> 48; + _buf->buf[_buf->len++] = data >> 56; + } + return _buf->len; + } + + size_t addBuffer(const SBuffer &buf2) { + if (len() + buf2.len() <= size()) { + for (uint32_t i = 0; i < buf2.len(); i++) { + _buf->buf[_buf->len++] = buf2.buf()[i]; + } + } + return _buf->len; + } + + size_t addBuffer(const uint8_t *buf2, size_t len2) { + if (len() + len2 <= size()) { + for (uint32_t i = 0; i < len2; i++) { + _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); + } + } + return _buf->len; + } + + size_t addBuffer(const char *buf2, size_t len2) { + if (len() + len2 <= size()) { + for (uint32_t i = 0; i < len2; i++) { + _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); + } + } + return _buf->len; + } + + uint8_t get8(size_t offset) const { + if (offset < _buf->len) { + return _buf->buf[offset]; + } else { + return 0; + } + } + uint8_t read8(const size_t offset) const { + if (offset < len()) { + return _buf->buf[offset]; + } + return 0; + } + uint16_t get16(const size_t offset) const { + if (offset < len() - 1) { + return _buf->buf[offset] | (_buf->buf[offset+1] << 8); + } + return 0; + } + uint32_t get32(const size_t offset) const { + if (offset < len() - 3) { + return _buf->buf[offset] | (_buf->buf[offset+1] << 8) | + (_buf->buf[offset+2] << 16) | (_buf->buf[offset+3] << 24); + } + return 0; + } + uint64_t get64(const size_t offset) const { + if (offset < len() - 7) { + return (uint64_t)_buf->buf[offset] | ((uint64_t)_buf->buf[offset+1] << 8) | + ((uint64_t)_buf->buf[offset+2] << 16) | ((uint64_t)_buf->buf[offset+3] << 24) | + ((uint64_t)_buf->buf[offset+4] << 32) | ((uint64_t)_buf->buf[offset+5] << 40) | + ((uint64_t)_buf->buf[offset+6] << 48) | ((uint64_t)_buf->buf[offset+7] << 56); + } + return 0; + } + + + inline size_t strlen(const size_t offset) const { + return strnlen((const char*) &_buf->buf[offset], len() - offset); + } + + size_t strlen_s(const size_t offset) const { + size_t slen = this->strlen(offset); + if (slen == len() - offset) { + return 0; + } else { + return slen; + } + } + + SBuffer subBuffer(const size_t start, size_t len) const { + if (start >= _buf->len) { + len = 0; + } else if (start + len > _buf->len) { + len = _buf->len - start; + } + + SBuffer buf2(len); + memcpy(buf2.buf(), buf()+start, len); + buf2._buf->len = len; + return buf2; + } + + static SBuffer SBufferFromHex(const char *hex, size_t len) { + size_t buf_len = (len + 3) / 2; + SBuffer buf2(buf_len); + uint8_t val; + + for (; len > 1; len -= 2) { + val = asc2byte(*hex++) << 4; + val |= asc2byte(*hex++); + buf2.add8(val); + } + return buf2; + } + +protected: + + static uint8_t asc2byte(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { rVal = chr - '0'; } + else if (chr >= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; } + else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; } + return rVal; + } + + static void unHex(const char* in, uint8_t *out, size_t len) { + } + +protected: + SBuffer_impl * _buf; + +} SBuffer; + +typedef class PreAllocatedSBuffer : public SBuffer { + +public: + PreAllocatedSBuffer(const size_t size, void * buffer) { + _buf = (SBuffer_impl*) buffer; + _buf->size = size - 4; + _buf->len = 0; + } + + ~PreAllocatedSBuffer(void) { + + _buf = nullptr; + } +} PreAllocatedSBuffer; +# 1 "S:/Development/Tasmota/tasmota/support_statistics.ino" +# 20 "S:/Development/Tasmota/tasmota/support_statistics.ino" +#define USE_STATS_CODE + +#ifdef USE_STATS_CODE + + + + +String GetStatistics(void) +{ + char data[40]; + snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); + return String(data); +} + +#else + +String GetStatistics(void) +{ + return String(""); +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/support_switch.ino" +# 20 "S:/Development/Tasmota/tasmota/support_switch.ino" +#define SWITCH_V2 +#ifdef SWITCH_V2 + + + + + + +const uint8_t SWITCH_PROBE_INTERVAL = 10; + +#include + +Ticker TickerSwitch; + +struct SWITCH { + unsigned long debounce = 0; + uint16_t no_pullup_mask = 0; + uint8_t state[MAX_SWITCHES] = { 0 }; + uint8_t last_state[MAX_SWITCHES]; + uint8_t hold_timer[MAX_SWITCHES] = { 0 }; + uint8_t virtual_state[MAX_SWITCHES]; + uint8_t present = 0; +} Switch; + + + +void SwitchPullupFlag(uint16 switch_bit) +{ + bitSet(Switch.no_pullup_mask, switch_bit); +} + +void SwitchSetVirtual(uint32_t index, uint8_t state) +{ + Switch.virtual_state[index] = state; +} + +uint8_t SwitchGetVirtual(uint32_t index) +{ + return Switch.virtual_state[index]; +} + +uint8_t SwitchLastState(uint32_t index) +{ + return Switch.last_state[index]; +} + +bool SwitchState(uint32_t index) +{ + uint32_t switchmode = Settings.switchmode[index]; + return ((FOLLOW_INV == switchmode) || + (PUSHBUTTON_INV == switchmode) || + (PUSHBUTTONHOLD_INV == switchmode) || + (FOLLOWMULTI_INV == switchmode) || + (PUSHHOLDMULTI_INV == switchmode) + ) ^ Switch.last_state[index]; +} + + + +void SwitchProbe(void) +{ + if (uptime < 4) { return; } + + uint8_t state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; + uint8_t force_high = (Settings.switch_debounce % 50) &1; + uint8_t force_low = (Settings.switch_debounce % 50) &2; + + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + if (pin[GPIO_SWT1 +i] < 99) { + + if (1 == digitalRead(pin[GPIO_SWT1 +i])) { + + if (force_high) { + if (1 == Switch.virtual_state[i]) { + Switch.state[i] = state_filter; + } + } + + if (Switch.state[i] < state_filter) { + Switch.state[i]++; + if (state_filter == Switch.state[i]) { + Switch.virtual_state[i] = 1; + } + } + } else { + + if (force_low) { + if (0 == Switch.virtual_state[i]) { + Switch.state[i] = 0; + } + } + + if (Switch.state[i] > 0) { + Switch.state[i]--; + if (0 == Switch.state[i]) { + Switch.virtual_state[i] = 0; + } + } + } + } + } + TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); +} + +void SwitchInit(void) +{ + Switch.present = 0; + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + Switch.last_state[i] = 1; + if (pin[GPIO_SWT1 +i] < 99) { + Switch.present++; + pinMode(pin[GPIO_SWT1 +i], bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); + Switch.last_state[i] = digitalRead(pin[GPIO_SWT1 +i]); + } + Switch.virtual_state[i] = Switch.last_state[i]; + } + if (Switch.present) { TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); } +} + + + + + +void SwitchHandler(uint8_t mode) +{ + if (uptime < 4) { return; } + + uint16_t loops_per_second = 1000 / Settings.switch_debounce; + + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { + uint8_t button = Switch.virtual_state[i]; + uint8_t switchflag = POWER_TOGGLE +1; + + if (Switch.hold_timer[i]) { + Switch.hold_timer[i]--; + if (0 == Switch.hold_timer[i]) { + + switch (Settings.switchmode[i]) { + case TOGGLEMULTI: + switchflag = POWER_TOGGLE; + break; + case FOLLOWMULTI: + switchflag = button &1; + break; + case FOLLOWMULTI_INV: + switchflag = ~button &1; + break; + case PUSHHOLDMULTI: + if (NOT_PRESSED == button){ + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); + } + else + SendKey(KEY_SWITCH, i +1, POWER_CLEAR); + break; + case PUSHHOLDMULTI_INV: + if (PRESSED == button){ + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; + SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); + } + else + SendKey(KEY_SWITCH, i +1, POWER_CLEAR); + break; + default: + SendKey(KEY_SWITCH, i +1, POWER_HOLD); + break; + } + } + } + + + + if (button != Switch.last_state[i]) { + switch (Settings.switchmode[i]) { + case TOGGLE: + case PUSHBUTTON_TOGGLE: + switchflag = POWER_TOGGLE; + break; + case FOLLOW: + switchflag = button &1; + break; + case FOLLOW_INV: + switchflag = ~button &1; + break; + case PUSHBUTTON: + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + switchflag = POWER_TOGGLE; + } + break; + case PUSHBUTTON_INV: + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + switchflag = POWER_TOGGLE; + } + break; + case PUSHBUTTONHOLD: + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { + Switch.hold_timer[i] = 0; + switchflag = POWER_TOGGLE; + } + break; + case PUSHBUTTONHOLD_INV: + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { + Switch.hold_timer[i] = 0; + switchflag = POWER_TOGGLE; + } + break; + case TOGGLEMULTI: + case FOLLOWMULTI: + case FOLLOWMULTI_INV: + if (Switch.hold_timer[i]) { + Switch.hold_timer[i] = 0; + SendKey(KEY_SWITCH, i +1, POWER_HOLD); + } else { + Switch.hold_timer[i] = loops_per_second / 2; + } + break; + case PUSHHOLDMULTI: + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + if(Switch.hold_timer[i]!=0) + SendKey(KEY_SWITCH, i +1, POWER_INV); + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) + switchflag = POWER_TOGGLE; + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + break; + case PUSHHOLDMULTI_INV: + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + if(Switch.hold_timer[i]!=0) + SendKey(KEY_SWITCH, i +1, POWER_INV); + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) + switchflag = POWER_TOGGLE; + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + } + break; + } + Switch.last_state[i] = button; + } + if (switchflag <= POWER_TOGGLE) { + if (!SendKey(KEY_SWITCH, i +1, switchflag)) { + ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); + } + } + } + } +} + +void SwitchLoop(void) +{ + if (Switch.present) { + if (TimeReached(Switch.debounce)) { + SetNextTimeInterval(Switch.debounce, Settings.switch_debounce); + SwitchHandler(0); + } + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/support_tasmota.ino" +# 20 "S:/Development/Tasmota/tasmota/support_tasmota.ino" +const char kSleepMode[] PROGMEM = "Dynamic|Normal"; +const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; + +char* Format(char* output, const char* input, int size) +{ + char *token; + uint32_t digits = 0; + + if (strstr(input, "%") != nullptr) { + strlcpy(output, input, size); + token = strtok(output, "%"); + if (strstr(input, "%") == input) { + output[0] = '\0'; + } else { + token = strtok(nullptr, ""); + } + if (token != nullptr) { + digits = atoi(token); + if (digits) { + char tmp[size]; + if (strchr(token, 'd')) { + snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits); + snprintf_P(output, size, tmp, ESP.getChipId() & 0x1fff); + } else { + snprintf_P(tmp, size, PSTR("%s%c0%dX"), output, '%', digits); + snprintf_P(output, size, tmp, ESP.getChipId()); + } + } else { + if (strchr(token, 'd')) { + snprintf_P(output, size, PSTR("%s%d"), output, ESP.getChipId()); + digits = 8; + } + } + } + } + if (!digits) { + strlcpy(output, input, size); + } + return output; +} + +char* GetOtaUrl(char *otaurl, size_t otaurl_size) +{ + if (strstr(SettingsText(SET_OTAURL), "%04d") != nullptr) { + snprintf(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId() & 0x1fff); + } + else if (strstr(SettingsText(SET_OTAURL), "%d") != nullptr) { + snprintf_P(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId()); + } + else { + strlcpy(otaurl, SettingsText(SET_OTAURL), otaurl_size); + } + + return otaurl; +} + +char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) +{ +# 88 "S:/Development/Tasmota/tasmota/support_tasmota.ino" + char romram[CMDSZ]; + String fulltopic; + + snprintf_P(romram, sizeof(romram), subtopic); + if (fallback_topic_flag || (prefix > 3)) { + bool fallback = (prefix < 8); + prefix &= 3; + char stemp[11]; + fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); + fulltopic += F("/"); + if (fallback) { + fulltopic += mqtt_client; + fulltopic += F("_fb"); + } else { + fulltopic += topic; + } + } else { + fulltopic = SettingsText(SET_MQTT_FULLTOPIC); + if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { + fulltopic += F("/"); + fulltopic += FPSTR(MQTT_TOKEN_PREFIX); + } + for (uint32_t i = 0; i < MAX_MQTT_PREFIXES; i++) { + if (!strlen(SettingsText(SET_MQTTPREFIX1 + i))) { + char temp[TOPSZ]; + SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes)); + } + } + fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + prefix)); + + fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); + fulltopic.replace(F("%hostname%"), my_hostname); + String token_id = WiFi.macAddress(); + token_id.replace(":", ""); + fulltopic.replace(F("%id%"), token_id); + } + fulltopic.replace(F("#"), ""); + fulltopic.replace(F("//"), "/"); + if (!fulltopic.endsWith("/")) { + fulltopic += "/"; + } + snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); + return stopic; +} + +char* GetGroupTopic_P(char *stopic, const char* subtopic) +{ + + + return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(SET_MQTT_GRP_TOPIC), subtopic); +} + +char* GetFallbackTopic_P(char *stopic, const char* subtopic) +{ + return GetTopic_P(stopic, CMND +4, nullptr, subtopic); +} + +char* GetStateText(uint32_t state) +{ + if (state >= MAX_STATE_TEXT) { + state = 1; + } + return SettingsText(SET_STATE_TXT1 + state); +} + + + +void SetLatchingRelay(power_t lpower, uint32_t state) +{ + + + + + + if (state && !latching_relay_pulse) { + latching_power = lpower; + latching_relay_pulse = 2; + } + + for (uint32_t i = 0; i < devices_present; i++) { + uint32_t port = (i << 1) + ((latching_power >> i) &1); + DigitalWrite(GPIO_REL1 +port, bitRead(rel_inverted, port) ? !state : state); + } +} + +void SetDevicePower(power_t rpower, uint32_t source) +{ + ShowSource(source); + last_source = source; + + if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { + power = (1 << devices_present) -1; + rpower = power; + } + + if (Settings.flag.interlock) { + for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { + power_t mask = 1; + uint32_t count = 0; + for (uint32_t j = 0; j < devices_present; j++) { + if ((Settings.interlock[i] & mask) && (rpower & mask)) { + count++; + } + mask <<= 1; + } + if (count > 1) { + mask = ~Settings.interlock[i]; + power &= mask; + rpower &= mask; + } + } + } + + if (rpower) { + last_power = rpower; + } + + XdrvMailbox.index = rpower; + XdrvCall(FUNC_SET_POWER); + + XdrvMailbox.index = rpower; + XdrvMailbox.payload = source; + if (XdrvCall(FUNC_SET_DEVICE_POWER)) { + + } + else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + Serial.write(0xA0); + Serial.write(0x04); + Serial.write(rpower &0xFF); + Serial.write(0xA1); + Serial.write('\n'); + Serial.flush(); + } + else if (EXS_RELAY == my_module_type) { + SetLatchingRelay(rpower, 1); + } + else { + for (uint32_t i = 0; i < devices_present; i++) { + power_t state = rpower &1; + if (i < MAX_RELAYS) { + DigitalWrite(GPIO_REL1 +i, bitRead(rel_inverted, i) ? !state : state); + } + rpower >>= 1; + } + } +} + +void RestorePower(bool publish_power, uint32_t source) +{ + if (power != last_power) { + power = last_power; + SetDevicePower(power, source); + if (publish_power) { + MqttPublishAllPowerState(); + } + } +} + +void SetAllPower(uint32_t state, uint32_t source) +{ +# 256 "S:/Development/Tasmota/tasmota/support_tasmota.ino" + bool publish_power = true; + if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { + state &= 3; + publish_power = false; + } + if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) { + power_t all_on = (1 << devices_present) -1; + switch (state) { + case POWER_OFF: + power = 0; + break; + case POWER_ON: + power = all_on; + break; + case POWER_TOGGLE: + power ^= all_on; + } + SetDevicePower(power, source); + } + if (publish_power) { + MqttPublishAllPowerState(); + } +} + +void SetPowerOnState(void) +{ + if (MOTOR == my_module_type) { + Settings.poweronstate = POWER_ALL_ON; + } + if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { + SetDevicePower(1, SRC_RESTART); + } else { + if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == REASON_EXT_SYS_RST)) { + switch (Settings.poweronstate) { + case POWER_ALL_OFF: + case POWER_ALL_OFF_PULSETIME_ON: + power = 0; + SetDevicePower(power, SRC_RESTART); + break; + case POWER_ALL_ON: + power = (1 << devices_present) -1; + SetDevicePower(power, SRC_RESTART); + break; + case POWER_ALL_SAVED_TOGGLE: + power = (Settings.power & ((1 << devices_present) -1)) ^ POWER_MASK; + if (Settings.flag.save_state) { + SetDevicePower(power, SRC_RESTART); + } + break; + case POWER_ALL_SAVED: + power = Settings.power & ((1 << devices_present) -1); + if (Settings.flag.save_state) { + SetDevicePower(power, SRC_RESTART); + } + break; + } + } else { + power = Settings.power & ((1 << devices_present) -1); + if (Settings.flag.save_state) { + SetDevicePower(power, SRC_RESTART); + } + } + } + + + for (uint32_t i = 0; i < devices_present; i++) { + if (!Settings.flag3.no_power_feedback) { + if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { + bitWrite(power, i, digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i)); + } + } + if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate))) { + SetPulseTimer(i, Settings.pulse_timer[i]); + } + } + blink_powersave = power; +} + +void SetLedPowerIdx(uint32_t led, uint32_t state) +{ + if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { + if (pin[GPIO_LED2] < 99) { + led = 1; + } + } + if (pin[GPIO_LED1 + led] < 99) { + uint32_t mask = 1 << led; + if (state) { + state = 1; + led_power |= mask; + } else { + led_power &= (0xFF ^ mask); + } + DigitalWrite(GPIO_LED1 + led, bitRead(led_inverted, led) ? !state : state); + } +#ifdef USE_BUZZER + if (led == 0) { + BuzzerSetStateToLed(state); + } +#endif +} + +void SetLedPower(uint32_t state) +{ + if (99 == pin[GPIO_LEDLNK]) { + SetLedPowerIdx(0, state); + } else { + power_t mask = 1; + for (uint32_t i = 0; i < leds_present; i++) { + bool tstate = (power & mask); + SetLedPowerIdx(i, tstate); + mask <<= 1; + } + } +} + +void SetLedPowerAll(uint32_t state) +{ + for (uint32_t i = 0; i < leds_present; i++) { + SetLedPowerIdx(i, state); + } +} + +void SetLedLink(uint32_t state) +{ + uint32_t led_pin = pin[GPIO_LEDLNK]; + uint32_t led_inv = ledlnk_inverted; + if (99 == led_pin) { + led_pin = pin[GPIO_LED1]; + led_inv = bitRead(led_inverted, 0); + } + if (led_pin < 99) { + if (state) { state = 1; } + digitalWrite(led_pin, (led_inv) ? !state : state); + } +#ifdef USE_BUZZER + BuzzerSetStateToLed(state); +#endif +} + +void SetPulseTimer(uint32_t index, uint32_t time) +{ + pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; +} + +uint32_t GetPulseTimer(uint32_t index) +{ + long time = TimePassedSince(pulse_timer[index]); + if (time < 0) { + time *= -1; + return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; + } + return 0; +} + + + +bool SendKey(uint32_t key, uint32_t device, uint32_t state) +{ +# 423 "S:/Development/Tasmota/tasmota/support_tasmota.ino" + char stopic[TOPSZ]; + char scommand[CMDSZ]; + char key_topic[TOPSZ]; + bool result = false; + + char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_BUTTON_TOPIC); + Format(key_topic, tmp, sizeof(key_topic)); + if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { + if (!key && (device > devices_present)) { + device = 1; + } + GetTopic_P(stopic, CMND, key_topic, + GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); + if (CLEAR_RETAIN == state) { + mqtt_data[0] = '\0'; + } else { + if ((Settings.flag3.button_switch_force_local || + !strcmp(mqtt_topic, key_topic) || + !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) && + (POWER_TOGGLE == state)) { + state = ~(power >> (device -1)) &1; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); + } +#ifdef USE_DOMOTICZ + if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { +#endif + MqttPublish(stopic, ((key) ? Settings.flag.mqtt_switch_retain + : Settings.flag.mqtt_button_retain) && + (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); +#ifdef USE_DOMOTICZ + } +#endif + result = !Settings.flag3.button_switch_force_local; + } else { + Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); + result = XdrvRulesProcess(); + } + int32_t payload_save = XdrvMailbox.payload; + XdrvMailbox.payload = key << 16 | state << 8 | device; + XdrvCall(FUNC_ANY_KEY); + XdrvMailbox.payload = payload_save; + return result; +} + +void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) +{ +# 483 "S:/Development/Tasmota/tasmota/support_tasmota.ino" +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + blink_mask &= 1; + Settings.flag.interlock = 0; + Settings.pulse_timer[1] = 0; + Settings.pulse_timer[2] = 0; + Settings.pulse_timer[3] = 0; + } +#endif + + bool publish_power = true; + if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { + state &= 3; + publish_power = false; + } + + if ((device < 1) || (device > devices_present)) { + device = 1; + } + active_device = device; + + if (device <= MAX_PULSETIMERS) { + SetPulseTimer(device -1, 0); + } + power_t mask = 1 << (device -1); + if (state <= POWER_TOGGLE) { + if ((blink_mask & mask)) { + blink_mask &= (POWER_MASK ^ mask); + MqttPublishPowerBlinkState(device); + } + + if (Settings.flag.interlock && + !interlock_mutex && + ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(power & mask))) + ) { + interlock_mutex = true; + for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { + if (Settings.interlock[i] & mask) { + for (uint32_t j = 0; j < devices_present; j++) { + power_t imask = 1 << j; + if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { + ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); + delay(50); + } + } + break; + } + } + interlock_mutex = false; + } + + switch (state) { + case POWER_OFF: { + power &= (POWER_MASK ^ mask); + break; } + case POWER_ON: + power |= mask; + break; + case POWER_TOGGLE: + power ^= mask; + } +#ifdef USE_DEVICE_GROUPS + if (SRC_REMOTE != source && SRC_RETRY != source) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, power); +#endif + SetDevicePower(power, source); +#ifdef USE_DOMOTICZ + DomoticzUpdatePowerState(device); +#endif +#ifdef USE_KNX + KnxUpdatePowerState(device, power); +#endif + if (publish_power && Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } + if (device <= MAX_PULSETIMERS) { + SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); + } + } + else if (POWER_BLINK == state) { + if (!(blink_mask & mask)) { + blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); + blink_power = (power >> (device -1))&1; + } + blink_timer = millis() + 100; + blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; + blink_mask |= mask; + MqttPublishPowerBlinkState(device); + return; + } + else if (POWER_BLINK_STOP == state) { + bool flag = (blink_mask & mask); + blink_mask &= (POWER_MASK ^ mask); + MqttPublishPowerBlinkState(device); + if (flag) { + ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); + } + return; + } + if (publish_power) { + MqttPublishPowerState(device); + } +} + +void StopAllPowerBlink(void) +{ + power_t mask; + + for (uint32_t i = 1; i <= devices_present; i++) { + mask = 1 << (i -1); + if (blink_mask & mask) { + blink_mask &= (POWER_MASK ^ mask); + MqttPublishPowerBlinkState(i); + ExecuteCommandPower(i, (blink_powersave >> (i -1))&1, SRC_IGNORE); + } + } +} + +void MqttShowPWMState(void) +{ + ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); + bool first = true; + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 + i] < 99) { + ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); + first = false; + } + } + ResponseJsonEnd(); +} + +void MqttShowState(void) +{ + char stemp1[TOPSZ]; + + ResponseAppendTime(); + ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); + +#ifdef USE_ADC_VCC + dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); + ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); +#endif + + ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"), + ESP.getFreeHeap()/1024, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), + sleep, loop_load_avg, MqttConnectCount()); + + for (uint32_t i = 1; i <= devices_present; i++) { +#ifdef USE_LIGHT + if ((LightDevice()) && (i >= LightDevice())) { + if (i == LightDevice()) { LightState(1); } + } else { +#endif + ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), + GetStateText(bitRead(power, i-1))); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); + break; + } +#endif +#ifdef USE_LIGHT + } +#endif + } + + if (pwm_present) { + ResponseAppend_P(PSTR(",")); + MqttShowPWMState(); + } + + int32_t rssi = WiFi.RSSI(); + ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(), + WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str()); +} + +void MqttPublishTeleState(void) +{ + mqtt_data[0] = '\0'; + MqttShowState(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); +#if defined(USE_RULES) || defined(USE_SCRIPT) + RulesTeleperiod(); +#endif +} + +bool MqttShowSensor(void) +{ + ResponseAppendTime(); + + int json_data_start = strlen(mqtt_data); + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { +#ifdef USE_TM1638 + if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { +#else + if (pin[GPIO_SWT1 +i] < 99) { +#endif + ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(SwitchState(i))); + } + } + XsnsCall(FUNC_JSON_APPEND); + XdrvCall(FUNC_JSON_APPEND); + + bool json_data_available = (strlen(mqtt_data) - json_data_start); + if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { + ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); + } + if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); + } + ResponseJsonEnd(); + + if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } + return json_data_available; +} + +void MqttPublishSensor(void) +{ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishTeleSensor(); + } +} +# 714 "S:/Development/Tasmota/tasmota/support_tasmota.ino" +void PerformEverySecond(void) +{ + uptime++; + + if (POWER_CYCLE_TIME == uptime) { + UpdateQuickPowerCycle(false); + } + + if (BOOT_LOOP_TIME == uptime) { + RtcRebootReset(); + +#ifdef USE_DEEPSLEEP + if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { +#endif + Settings.bootcount++; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); +#ifdef USE_DEEPSLEEP + } +#endif + } + + if (mqtt_cmnd_blocked_reset) { + mqtt_cmnd_blocked_reset--; + if (!mqtt_cmnd_blocked_reset) { + mqtt_cmnd_blocked = 0; + } + } + + if (seriallog_timer) { + seriallog_timer--; + if (!seriallog_timer) { + if (seriallog_level) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); + } + seriallog_level = 0; + } + } + + if (syslog_timer) { + syslog_timer--; + if (!syslog_timer) { + syslog_level = Settings.syslog_level; + if (Settings.syslog_level) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); + } + } + } + + ResetGlobalValues(); + + if (Settings.tele_period) { + if (tele_period >= 9999) { + if (!global_state.wifi_down) { + tele_period = 0; + } + } else { + tele_period++; + if (tele_period >= Settings.tele_period) { + tele_period = 0; + + MqttPublishTeleState(); + + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +#if defined(USE_RULES) || defined(USE_SCRIPT) + RulesTeleperiod(); +#endif + } + + XdrvCall(FUNC_AFTER_TELEPERIOD); + } + } + } +} + + + + + +void Every100mSeconds(void) +{ + + power_t power_now; + + if (prepped_loglevel) { + AddLog(prepped_loglevel); + prepped_loglevel = 0; + } + + if (latching_relay_pulse) { + latching_relay_pulse--; + if (!latching_relay_pulse) SetLatchingRelay(0, 0); + } + + for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { + if (pulse_timer[i] != 0L) { + if (TimeReached(pulse_timer[i])) { + pulse_timer[i] = 0L; + ExecuteCommandPower(i +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER); + } + } + } + + if (blink_mask) { + if (TimeReached(blink_timer)) { + SetNextTimeInterval(blink_timer, 100 * Settings.blinktime); + blink_counter--; + if (!blink_counter) { + StopAllPowerBlink(); + } else { + blink_power ^= 1; + power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); + SetDevicePower(power_now, SRC_IGNORE); + } + } + } +} + + + + + +void Every250mSeconds(void) +{ + + + uint32_t blinkinterval = 1; + + state_250mS++; + state_250mS &= 0x3; + + if (!Settings.flag.global_state) { + if (global_state.data) { + if (global_state.mqtt_down) { blinkinterval = 7; } + if (global_state.wifi_down) { blinkinterval = 3; } + blinks = 201; + } + } + if (blinks || restart_flag || ota_state_flag) { + if (restart_flag || ota_state_flag) { + blinkstate = true; + } else { + blinkspeed--; + if (!blinkspeed) { + blinkspeed = blinkinterval; + blinkstate ^= 1; + } + } + if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { + SetLedLink(blinkstate); + } + if (!blinkstate) { + blinks--; + if (200 == blinks) blinks = 0; + } + } + if (Settings.ledstate &1 && (pin[GPIO_LEDLNK] < 99 || !(blinks || restart_flag || ota_state_flag)) ) { + bool tstate = power & Settings.ledmask; + if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) { + tstate = (!power) ? 1 : 0; + } + SetLedPower(tstate); + } + + + + + + switch (state_250mS) { + case 0: + if (ota_state_flag && BACKLOG_EMPTY) { + ota_state_flag--; + if (2 == ota_state_flag) { + RtcSettings.ota_loader = 0; + ota_retry_counter = OTA_ATTEMPTS; + ESPhttpUpdate.rebootOnUpdate(false); + SettingsSave(1); + } + if (ota_state_flag <= 0) { +#ifdef USE_WEBSERVER + if (Settings.webserver) StopWebserver(); +#endif +#ifdef USE_ARILUX_RF + AriluxRfDisable(); +#endif + ota_state_flag = 92; + ota_result = 0; + ota_retry_counter--; + if (ota_retry_counter) { + strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); +#ifndef FIRMWARE_MINIMAL + if (RtcSettings.ota_loader) { +# 919 "S:/Development/Tasmota/tasmota/support_tasmota.ino" + char *bch = strrchr(mqtt_data, '/'); + if (bch == nullptr) { bch = mqtt_data; } + + char *ech = strrchr(bch, '.'); + if ((ech != nullptr) && (0 == strncasecmp_P(ech, PSTR(".GZ"), 3))) { + char *fch = ech; + *fch = '\0'; + ech = strrchr(bch, '.'); + *fch = '.'; + } + if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } + char ota_url_type[strlen(ech) +1]; + strncpy(ota_url_type, ech, sizeof(ota_url_type)); + + char *pch = strrchr(bch, '-'); + if (pch == nullptr) { pch = ech; } + *pch = '\0'; + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); + } +#endif + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); +#else + + WiFiClient OTAclient; + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); +#endif + if (!ota_result) { +#ifndef FIRMWARE_MINIMAL + int ota_error = ESPhttpUpdate.getLastError(); + DEBUG_CORE_LOG(PSTR("OTA: Error %d"), ota_error); + if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) { + RtcSettings.ota_loader = 1; + } +#endif + ota_state_flag = 2; + } + } + } + if (90 == ota_state_flag) { + ota_state_flag = 0; + Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\"")); + if (ota_result) { + + if (!VersionCompatible()) { + ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14)); + } else { + ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); + restart_flag = 2; + } + } else { + ResponseAppend_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); + } + ResponseAppend_P(PSTR("\"}")); + + MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); + } + } + break; + case 1: + if (MidnightNow()) { + XsnsCall(FUNC_SAVE_AT_MIDNIGHT); + } + if (save_data_counter && BACKLOG_EMPTY) { + save_data_counter--; + if (save_data_counter <= 0) { + if (Settings.flag.save_state) { + power_t mask = POWER_MASK; + for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { + if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { + mask &= ~(1 << i); + } + } + if (!((Settings.power &mask) == (power &mask))) { + Settings.power = power; + } + } else { + Settings.power = 0; + } + SettingsSave(0); + save_data_counter = Settings.save_data; + } + } + if (restart_flag && BACKLOG_EMPTY) { + if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { + + char storage_ssid1[strlen(SettingsText(SET_STASSID1)) +1]; + strncpy(storage_ssid1, SettingsText(SET_STASSID1), sizeof(storage_ssid1)); + char storage_ssid2[strlen(SettingsText(SET_STASSID2)) +1]; + strncpy(storage_ssid2, SettingsText(SET_STASSID2), sizeof(storage_ssid2)); + char storage_pass1[strlen(SettingsText(SET_STAPWD1)) +1]; + strncpy(storage_pass1, SettingsText(SET_STAPWD1), sizeof(storage_pass1)); + char storage_pass2[strlen(SettingsText(SET_STAPWD2)) +1]; + strncpy(storage_pass2, SettingsText(SET_STAPWD2), sizeof(storage_pass2)); + + char storage_mqtthost[strlen(SettingsText(SET_MQTT_HOST)) +1]; + strncpy(storage_mqtthost, SettingsText(SET_MQTT_HOST), sizeof(storage_mqtthost)); + char storage_mqttuser[strlen(SettingsText(SET_MQTT_USER)) +1]; + strncpy(storage_mqttuser, SettingsText(SET_MQTT_USER), sizeof(storage_mqttuser)); + char storage_mqttpwd[strlen(SettingsText(SET_MQTT_PWD)) +1]; + strncpy(storage_mqttpwd, SettingsText(SET_MQTT_PWD), sizeof(storage_mqttpwd)); + char storage_mqtttopic[strlen(SettingsText(SET_MQTT_TOPIC)) +1]; + strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic)); + uint16_t mqtt_port = Settings.mqtt_port; + + + + + if ((215 == restart_flag) || (216 == restart_flag)) { + SettingsErase(0); + } + SettingsDefault(); + + SettingsUpdateText(SET_STASSID1, storage_ssid1); + SettingsUpdateText(SET_STASSID2, storage_ssid2); + SettingsUpdateText(SET_STAPWD1, storage_pass1); + SettingsUpdateText(SET_STAPWD2, storage_pass2); + if (216 == restart_flag) { + + SettingsUpdateText(SET_MQTT_HOST, storage_mqtthost); + SettingsUpdateText(SET_MQTT_USER, storage_mqttuser); + SettingsUpdateText(SET_MQTT_PWD, storage_mqttpwd); + SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic); + Settings.mqtt_port = mqtt_port; + } + restart_flag = 2; + } + else if (213 == restart_flag) { + SettingsSdkErase(); + restart_flag = 2; + } + else if (212 == restart_flag) { + SettingsErase(0); + restart_flag = 211; + } + if (211 == restart_flag) { + SettingsDefault(); + restart_flag = 2; + } + if (2 == restart_flag) { + SettingsSaveAll(); + } + restart_flag--; + if (restart_flag <= 0) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); + EspRestart(); + } + } + break; + case 2: + WifiCheck(wifi_state_flag); + wifi_state_flag = WIFI_RESTART; + break; + case 3: + if (!global_state.wifi_down) { MqttCheck(); } + break; + } +} + +#ifdef USE_ARDUINO_OTA + + + + + + + +bool arduino_ota_triggered = false; +uint16_t arduino_ota_progress_dot_count = 0; + +void ArduinoOTAInit(void) +{ + ArduinoOTA.setPort(8266); + ArduinoOTA.setHostname(my_hostname); + if (strlen(SettingsText(SET_WEBPWD))) { + ArduinoOTA.setPassword(SettingsText(SET_WEBPWD)); + } + + ArduinoOTA.onStart([]() + { + SettingsSave(1); +#ifdef USE_WEBSERVER + if (Settings.webserver) { StopWebserver(); } +#endif +#ifdef USE_ARILUX_RF + AriluxRfDisable(); +#endif + if (Settings.flag.mqtt_enabled) { + MqttDisconnect(); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); + arduino_ota_triggered = true; + arduino_ota_progress_dot_count = 0; + delay(100); + }); + + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) + { + if ((LOG_LEVEL_DEBUG <= seriallog_level)) { + arduino_ota_progress_dot_count++; + Serial.printf("."); + if (!(arduino_ota_progress_dot_count % 80)) { Serial.println(); } + } + }); + + ArduinoOTA.onError([](ota_error_t error) + { + + + + + char error_str[100]; + + if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } + switch (error) { + case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break; + case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break; + case OTA_END_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_7), sizeof(error_str)); break; + default: + snprintf_P(error_str, sizeof(error_str), PSTR(D_UPLOAD_ERROR_CODE " %d"), error); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str); + EspRestart(); + }); + + ArduinoOTA.onEnd([]() + { + if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); + EspRestart(); + }); + + ArduinoOTA.begin(); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266")); +} + +void ArduinoOtaLoop(void) +{ + MDNS.update(); + ArduinoOTA.handle(); + + while (arduino_ota_triggered) { ArduinoOTA.handle(); } +} +#endif + + + +void SerialInput(void) +{ + while (Serial.available()) { + + delay(0); + serial_in_byte = Serial.read(); + + + + + if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { + serial_in_byte = ButtonSerial(serial_in_byte); + } + + + + if (XdrvCall(FUNC_SERIAL)) { + serial_in_byte_counter = 0; + Serial.flush(); + return; + } + + + + if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { + serial_in_byte_counter = 0; + Serial.flush(); + return; + } + if (!Settings.flag.mqtt_serial) { + if (isprint(serial_in_byte)) { + if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } else { + serial_in_byte_counter = 0; + } + } + } else { + if (serial_in_byte || Settings.flag.mqtt_serial_raw) { + if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && + ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || + ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || + Settings.flag.mqtt_serial_raw)) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + serial_polling_window = millis(); + } else { + serial_polling_window = 0; + break; + } + } + } + +#ifdef USE_SONOFF_SC + + + + if (SONOFF_SC == my_module_type) { + if (serial_in_byte == '\x1B') { + serial_in_buffer[serial_in_byte_counter] = 0; + SonoffScSerialInput(serial_in_buffer); + serial_in_byte_counter = 0; + Serial.flush(); + return; + } + } else +#endif + + + if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { + serial_in_buffer[serial_in_byte_counter] = 0; + seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); + ExecuteCommand(serial_in_buffer, SRC_SERIAL); + serial_in_byte_counter = 0; + serial_polling_window = 0; + Serial.flush(); + return; + } + } + + if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { + serial_in_buffer[serial_in_byte_counter] = 0; + char hex_char[(serial_in_byte_counter * 2) + 2]; + bool assume_json = (!Settings.flag.mqtt_serial_raw && (serial_in_buffer[0] == '{')); + Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":%s%s%s}"), + (assume_json) ? "" : """", + (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer, + (assume_json) ? "" : """"); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); + XdrvRulesProcess(); + serial_in_byte_counter = 0; + } +} + + + +void GpioInit(void) +{ + uint32_t mpin; + + if (!ValidModule(Settings.module)) { + uint32_t module = MODULE; + if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } + Settings.module = module; + Settings.last_module = module; + } + SetModuleType(); + + if (Settings.module != Settings.last_module) { + Settings.baudrate = APP_BAUDRATE / 300; + Settings.serial_config = TS_SERIAL_8N1; + } + + for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) { + Settings.user_template.gp.io[i] = GPIO_USER; + } + } + + myio def_gp; + ModuleGpios(&def_gp); + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) { + Settings.my_gp.io[i] = GPIO_NONE; + } + else if (Settings.my_gp.io[i] > GPIO_NONE) { + my_module.io[i] = Settings.my_gp.io[i]; + } + if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { + my_module.io[i] = def_gp.io[i]; + } + } + if ((Settings.my_adc0 >= ADC0_END) && (Settings.my_adc0 < ADC0_USER)) { + Settings.my_adc0 = ADC0_NONE; + } + else if (Settings.my_adc0 > ADC0_NONE) { + my_adc0 = Settings.my_adc0; + } + my_module_flag = ModuleFlag(); + uint32_t template_adc0 = my_module_flag.data &15; + if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) { + my_adc0 = template_adc0; + } + + for (uint32_t i = 0; i < GPIO_MAX; i++) { + pin[i] = 99; + } + for (uint32_t i = 0; i < sizeof(my_module.io); i++) { + mpin = ValidPin(i, my_module.io[i]); + + DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin); + + if (mpin) { + XdrvMailbox.index = mpin; + XdrvMailbox.payload = i; + + if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) { + SwitchPullupFlag(mpin - GPIO_SWT1_NP); + mpin -= (GPIO_SWT1_NP - GPIO_SWT1); + } + else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { + ButtonPullupFlag(mpin - GPIO_KEY1_NP); + mpin -= (GPIO_KEY1_NP - GPIO_KEY1); + } + else if ((mpin >= GPIO_KEY1_INV) && (mpin < (GPIO_KEY1_INV + MAX_KEYS))) { + ButtonInvertFlag(mpin - GPIO_KEY1_INV); + mpin -= (GPIO_KEY1_INV - GPIO_KEY1); + } + else if ((mpin >= GPIO_KEY1_INV_NP) && (mpin < (GPIO_KEY1_INV_NP + MAX_KEYS))) { + ButtonPullupFlag(mpin - GPIO_KEY1_INV_NP); + ButtonInvertFlag(mpin - GPIO_KEY1_INV_NP); + mpin -= (GPIO_KEY1_INV_NP - GPIO_KEY1); + } + else if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { + bitSet(rel_inverted, mpin - GPIO_REL1_INV); + mpin -= (GPIO_REL1_INV - GPIO_REL1); + } + else if ((mpin >= GPIO_LED1_INV) && (mpin < (GPIO_LED1_INV + MAX_LEDS))) { + bitSet(led_inverted, mpin - GPIO_LED1_INV); + mpin -= (GPIO_LED1_INV - GPIO_LED1); + } + else if (mpin == GPIO_LEDLNK_INV) { + ledlnk_inverted = 1; + mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK); + } + else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) { + bitSet(pwm_inverted, mpin - GPIO_PWM1_INV); + mpin -= (GPIO_PWM1_INV - GPIO_PWM1); + } + else if (XdrvCall(FUNC_PIN_STATE)) { + mpin = XdrvMailbox.index; + } + else if (XsnsCall(FUNC_PIN_STATE)) { + mpin = XdrvMailbox.index; + }; + } + if (mpin) pin[mpin] = i; + } + + if ((2 == pin[GPIO_TXD]) || (H801 == my_module_type)) { Serial.set_tx(2); } + + analogWriteRange(Settings.pwm_range); + analogWriteFreq(Settings.pwm_frequency); + +#ifdef USE_SPI + spi_flg = ((((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CS] > 14)) || (pin[GPIO_SPI_CS] < 12)) || (((pin[GPIO_SPI_DC] < 99) && (pin[GPIO_SPI_DC] > 14)) || (pin[GPIO_SPI_DC] < 12))); + if (spi_flg) { + for (uint32_t i = 0; i < GPIO_MAX; i++) { + if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; + } + my_module.io[12] = GPIO_SPI_MISO; + pin[GPIO_SPI_MISO] = 12; + my_module.io[13] = GPIO_SPI_MOSI; + pin[GPIO_SPI_MOSI] = 13; + my_module.io[14] = GPIO_SPI_CLK; + pin[GPIO_SPI_CLK] = 14; + } + soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); +#endif + +#ifdef USE_I2C + i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); + if (i2c_flg) { + Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); + } +#endif + + devices_present = 0; + light_type = LT_BASIC; + if (XdrvCall(FUNC_MODULE_INIT)) { + + } + else if (YTF_IR_BRIDGE == my_module_type) { + ClaimSerial(); + + } + else if (SONOFF_DUAL == my_module_type) { + devices_present = 2; + SetSerial(19200, TS_SERIAL_8N1); + } + else if (CH4 == my_module_type) { + devices_present = 4; + SetSerial(19200, TS_SERIAL_8N1); + } +#ifdef USE_SONOFF_SC + else if (SONOFF_SC == my_module_type) { + SetSerial(19200, TS_SERIAL_8N1); + } +#endif + + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + if (light_type) { + + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); + } else { + pwm_present = true; + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); + } + } + } + + for (uint32_t i = 0; i < MAX_RELAYS; i++) { + if (pin[GPIO_REL1 +i] < 99) { + pinMode(pin[GPIO_REL1 +i], OUTPUT); + devices_present++; + if (EXS_RELAY == my_module_type) { + digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0); + if (i &1) { devices_present--; } + } + } + } + + for (uint32_t i = 0; i < MAX_LEDS; i++) { + if (pin[GPIO_LED1 +i] < 99) { +#ifdef USE_ARILUX_RF + if ((3 == i) && (leds_present < 2) && (99 == pin[GPIO_ARIRFSEL])) { + pin[GPIO_ARIRFSEL] = pin[GPIO_LED4]; + pin[GPIO_LED4] = 99; + } else { +#endif + pinMode(pin[GPIO_LED1 +i], OUTPUT); + leds_present++; + digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); +#ifdef USE_ARILUX_RF + } +#endif + } + } + if (pin[GPIO_LEDLNK] < 99) { + pinMode(pin[GPIO_LEDLNK], OUTPUT); + digitalWrite(pin[GPIO_LEDLNK], ledlnk_inverted); + } + + ButtonInit(); + SwitchInit(); +#ifdef ROTARY_V1 + RotaryInit(); +#endif + + SetLedPower(Settings.ledstate &8); + SetLedLink(Settings.ledstate &8); + + XdrvCall(FUNC_PRE_INIT); +} +# 1 "S:/Development/Tasmota/tasmota/support_udp.ino" +# 20 "S:/Development/Tasmota/tasmota/support_udp.ino" +#ifdef USE_EMULATION + +#define UDP_BUFFER_SIZE 200 +#define UDP_MSEARCH_SEND_DELAY 1500 + +#include +Ticker TickerMSearch; + +IPAddress udp_remote_ip; +uint16_t udp_remote_port; + +bool udp_connected = false; +bool udp_response_mutex = false; + + + + + +const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**"; +const char URN_BELKIN_DEVICE_CAP[] PROGMEM = "urn:Belkin:device:**"; +const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice"; +const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all"; +const char SSDP_ALL[] PROGMEM = "ssdp:all"; + + + + + +bool UdpDisconnect(void) +{ + if (udp_connected) { + PortUdp.flush(); + WiFiUDP::stopAll(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); + udp_connected = false; + } + return udp_connected; +} + +bool UdpConnect(void) +{ + if (!udp_connected) { + + if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); + udp_response_mutex = false; + udp_connected = true; + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED)); + udp_connected = false; + } + } + return udp_connected; +} + +void PollUdp(void) +{ + if (udp_connected) { + while (PortUdp.parsePacket()) { + char packet_buffer[UDP_BUFFER_SIZE]; + + int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); + packet_buffer[len] = 0; + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); + + + + if (Settings.flag2.emulation) { +#ifdef USE_SCRIPT_HUE + if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { +#else + if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { +#endif + udp_response_mutex = true; + + udp_remote_ip = PortUdp.remoteIP(); + udp_remote_port = PortUdp.remotePort(); + + + + + uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); + + LowerCase(packet_buffer, packet_buffer); + RemoveSpace(packet_buffer); + +#ifdef USE_EMULATION_WEMO + if (EMUL_WEMO == Settings.flag2.emulation) { + if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { + TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); + return; + } + else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || + (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || + (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { + TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); + return; + } + } +#endif + +#ifdef USE_EMULATION_HUE + if (EMUL_HUE == Settings.flag2.emulation) { + if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || + (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || + (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || + (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { + TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); + return; + } + } +#endif + + udp_response_mutex = false; + continue; + } + } + +#ifdef USE_DEVICE_GROUPS + if (Settings.flag4.device_groups_enabled && !strncmp_P(packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) { + ProcessDeviceGroupMessage(packet_buffer, len); + } +#endif + } + optimistic_yield(100); + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/support_wifi.ino" +# 24 "S:/Development/Tasmota/tasmota/support_wifi.ino" +#ifndef WIFI_RSSI_THRESHOLD +#define WIFI_RSSI_THRESHOLD 10 +#endif +#ifndef WIFI_RESCAN_MINUTES +#define WIFI_RESCAN_MINUTES 44 +#endif + +const uint8_t WIFI_CONFIG_SEC = 180; +const uint8_t WIFI_CHECK_SEC = 20; +const uint8_t WIFI_RETRY_OFFSET_SEC = 20; + +#include +#if LWIP_IPV6 +#include +#endif + +struct WIFI { + uint32_t last_event = 0; + uint32_t downtime = 0; + uint16_t link_count = 0; + uint8_t counter; + uint8_t retry_init; + uint8_t retry; + uint8_t status; + uint8_t config_type = 0; + uint8_t config_counter = 0; + uint8_t mdns_begun = 0; + uint8_t scan_state; + uint8_t bssid[6]; + int8_t best_network_db; +} Wifi; + +int WifiGetRssiAsQuality(int rssi) +{ + int quality = 0; + + if (rssi <= -100) { + quality = 0; + } else if (rssi >= -50) { + quality = 100; + } else { + quality = 2 * (rssi + 100); + } + return quality; +} + +bool WifiConfigCounter(void) +{ + if (Wifi.config_counter) { + Wifi.config_counter = WIFI_CONFIG_SEC; + } + return (Wifi.config_counter); +} + +void WifiConfig(uint8_t type) +{ + if (!Wifi.config_type) { + if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; } +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + WiFi.disconnect(); + Wifi.config_type = type; + +#ifndef USE_WEBSERVER + if (WIFI_MANAGER == Wifi.config_type) { + Wifi.config_type = WIFI_SERIAL; + } +#endif + + Wifi.config_counter = WIFI_CONFIG_SEC; + Wifi.counter = Wifi.config_counter +5; + blinks = 1999; + if (WIFI_RESTART == Wifi.config_type) { + restart_flag = 2; + } + else if (WIFI_SERIAL == Wifi.config_type) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES)); + } +#ifdef USE_WEBSERVER + else if (WIFI_MANAGER == Wifi.config_type || WIFI_MANAGER_RESET_ONLY == Wifi.config_type) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES)); + WifiManagerBegin(WIFI_MANAGER_RESET_ONLY == Wifi.config_type); + } +#endif + } +} + +void WifiSetMode(WiFiMode_t wifi_mode) +{ + if (WiFi.getMode() == wifi_mode) { return; } + + if (wifi_mode != WIFI_OFF) { + + WiFi.forceSleepWake(); + delay(100); + } + + uint32_t retry = 2; + while (!WiFi.mode(wifi_mode) && retry--) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("Retry set Mode...")); + delay(100); + } + + if (wifi_mode == WIFI_OFF) { + delay(1000); + WiFi.forceSleepBegin(); + delay(1); + } else { + delay(30); + } +} + +void WiFiSetSleepMode(void) +{ +# 152 "S:/Development/Tasmota/tasmota/support_wifi.ino" +#if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) +#else + if (sleep && Settings.flag3.sleep_normal) { + WiFi.setSleepMode(WIFI_LIGHT_SLEEP); + } else { + WiFi.setSleepMode(WIFI_MODEM_SLEEP); + } +#endif + WifiSetOutputPower(); +} + +void WifiBegin(uint8_t flag, uint8_t channel) +{ + const char kWifiPhyMode[] = " BGN"; + +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + +#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186)); + + WifiSetMode(WIFI_OFF); +#endif + + WiFi.persistent(false); + WiFi.disconnect(true); + delay(200); + + WifiSetMode(WIFI_STA); + WiFiSetSleepMode(); + + + if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } + + switch (flag) { + case 0: + case 1: + Settings.sta_active = flag; + break; + case 2: + Settings.sta_active ^= 1; + } + if (!strlen(SettingsText(SET_STASSID1 + Settings.sta_active))) { + Settings.sta_active ^= 1; + } + if (Settings.ip_address[0]) { + WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); + } + WiFi.hostname(my_hostname); + + char stemp[40] = { 0 }; + if (channel) { + WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); + + char hex_char[18]; + snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s"), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':')); + } else { + WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), + Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); + +#if LWIP_IPV6 + for (bool configured = false; !configured;) { + uint16_t cfgcnt = 0; + for (auto addr : addrList) { + if ((configured = !addr.isLocal() && addr.isV6()) || cfgcnt==30) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI "Got IPv6 global address %s"), addr.toString().c_str()); + break; + } + delay(500); + cfgcnt++; + } + } +#endif +} + +void WifiBeginAfterScan(void) +{ + + if (0 == Wifi.scan_state) { return; } + + if (1 == Wifi.scan_state) { + memset((void*) &Wifi.bssid, 0, sizeof(Wifi.bssid)); + Wifi.best_network_db = -127; + Wifi.scan_state = 3; + } + + if (2 == Wifi.scan_state) { + uint8_t* bssid = WiFi.BSSID(); + memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid)); + Wifi.best_network_db = WiFi.RSSI(); + if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) { + Wifi.best_network_db += WIFI_RSSI_THRESHOLD; + } + Wifi.scan_state = 3; + } + + if (3 == Wifi.scan_state) { + if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) { + WiFi.scanNetworks(true); + Wifi.scan_state++; + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR("Network (re)scan started...")); + return; + } + } + int8_t wifi_scan_result = WiFi.scanComplete(); + + if (4 == Wifi.scan_state) { + if (wifi_scan_result != WIFI_SCAN_RUNNING) { + Wifi.scan_state++; + } + } + + if (5 == Wifi.scan_state) { + int32_t channel = 0; + int8_t ap = 3; + uint8_t last_bssid[6]; + memcpy((void*) &last_bssid, (void*) &Wifi.bssid, sizeof(last_bssid)); + + if (wifi_scan_result > 0) { + + for (uint32_t i = 0; i < wifi_scan_result; ++i) { + + String ssid_scan; + int32_t rssi_scan; + uint8_t sec_scan; + uint8_t* bssid_scan; + int32_t chan_scan; + bool hidden_scan; + + WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, bssid_scan, chan_scan, hidden_scan); + + bool known = false; + uint32_t j; + for (j = 0; j < MAX_SSIDS; j++) { + if (ssid_scan == SettingsText(SET_STASSID1 + j)) { + known = true; + if (rssi_scan > Wifi.best_network_db) { + if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { + Wifi.best_network_db = (int8_t)rssi_scan; + channel = chan_scan; + ap = j; + memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); + } + } + break; + } + } + char hex_char[18]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %s, RSSI %d, Encryption %d"), + i, + (known) ? (j) ? '2' : '1' : '-', + ssid_scan.c_str(), + chan_scan, + ToHex_P((unsigned char*)bssid_scan, 6, hex_char, sizeof(hex_char), ':'), + rssi_scan, + (sec_scan == ENC_TYPE_NONE) ? 0 : 1); + delay(0); + } + WiFi.scanDelete(); + delay(0); + } + Wifi.scan_state = 0; + + for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) { + if (last_bssid[i] != Wifi.bssid[i]) { + WifiBegin(ap, channel); + break; + } + } + } +} + +uint16_t WifiLinkCount(void) +{ + return Wifi.link_count; +} + +String WifiDowntime(void) +{ + return GetDuration(Wifi.downtime); +} + +void WifiSetState(uint8_t state) +{ + if (state == global_state.wifi_down) { + if (state) { + rules_flag.wifi_connected = 1; + Wifi.link_count++; + Wifi.downtime += UpTime() - Wifi.last_event; + } else { + rules_flag.wifi_disconnected = 1; + Wifi.last_event = UpTime(); + } + } + global_state.wifi_down = state ^1; +} + +#if LWIP_IPV6 +bool WifiCheckIPv6(void) +{ + bool ipv6_global=false; + + for (auto a : addrList) { + if(!a.isLocal() && a.isV6()) ipv6_global=true; + } + return ipv6_global; +} + +String WifiGetIPv6(void) +{ + for (auto a : addrList) { + if(!a.isLocal() && a.isV6()) return a.toString(); + } + return ""; +} + +bool WifiCheckIPAddrStatus(void) +{ + bool ip_global=false; + + for (auto a : addrList) { + if(!a.isLocal()) ip_global=true; + } + return ip_global; +} +#endif + +void WifiCheckIp(void) +{ +#if LWIP_IPV6 + if(WifiCheckIPAddrStatus()) { + Wifi.status = WL_CONNECTED; +#else + if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { +#endif + WifiSetState(1); + Wifi.counter = WIFI_CHECK_SEC; + Wifi.retry = Wifi.retry_init; + if (Wifi.status != WL_CONNECTED) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECTED)); + + Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP(); + Settings.ip_address[2] = (uint32_t)WiFi.subnetMask(); + Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); + } + Wifi.status = WL_CONNECTED; +#ifdef USE_DISCOVERY +#ifdef WEBSERVER_ADVERTISE + if (2 == Wifi.mdns_begun) { + MDNS.update(); + AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update"); + } +#endif +#endif + } else { + WifiSetState(0); + uint8_t wifi_config_tool = Settings.sta_config; + Wifi.status = WiFi.status(); + switch (Wifi.status) { + case WL_CONNECTED: + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS)); + Wifi.status = 0; + Wifi.retry = Wifi.retry_init; + break; + case WL_NO_SSID_AVAIL: + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED)); + if (WIFI_WAIT == Settings.sta_config) { + Wifi.retry = Wifi.retry_init; + } else { + if (Wifi.retry > (Wifi.retry_init / 2)) { + Wifi.retry = Wifi.retry_init / 2; + } + else if (Wifi.retry) { + Wifi.retry = 0; + } + } + break; + case WL_CONNECT_FAILED: + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD)); + if (Wifi.retry > (Wifi.retry_init / 2)) { + Wifi.retry = Wifi.retry_init / 2; + } + else if (Wifi.retry) { + Wifi.retry = 0; + } + break; + default: + if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { + AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); + } else { + if (!strlen(SettingsText(SET_STASSID1)) && !strlen(SettingsText(SET_STASSID2))) { + wifi_config_tool = WIFI_MANAGER; + Wifi.retry = 0; + } else { + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); + } + } + } + if (Wifi.retry) { + if (Settings.flag3.use_wifi_scan) { + if (Wifi.retry_init == Wifi.retry) { + Wifi.scan_state = 1; + } + } else { + if (Wifi.retry_init == Wifi.retry) { + WifiBegin(3, 0); + } + if ((Settings.sta_config != WIFI_WAIT) && ((Wifi.retry_init / 2) == Wifi.retry)) { + WifiBegin(2, 0); + } + } + Wifi.counter = 1; + Wifi.retry--; + } else { + WifiConfig(wifi_config_tool); + Wifi.counter = 1; + Wifi.retry = Wifi.retry_init; + } + } +} + +void WifiCheck(uint8_t param) +{ + Wifi.counter--; + switch (param) { + case WIFI_SERIAL: + case WIFI_MANAGER: + WifiConfig(param); + break; + default: + if (Wifi.config_counter) { + Wifi.config_counter--; + Wifi.counter = Wifi.config_counter +5; + if (Wifi.config_counter) { + if (!Wifi.config_counter) { + if (strlen(WiFi.SSID().c_str())) { + SettingsUpdateText(SET_STASSID1, WiFi.SSID().c_str()); + } + if (strlen(WiFi.psk().c_str())) { + SettingsUpdateText(SET_STAPWD1, WiFi.psk().c_str()); + } + Settings.sta_active = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), SettingsText(SET_STASSID1)); + } + } + if (!Wifi.config_counter) { + + restart_flag = 2; + } + } else { + if (Wifi.scan_state) { WifiBeginAfterScan(); } + + if (Wifi.counter <= 0) { + AddLog_P(LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CHECKING_CONNECTION)); + Wifi.counter = WIFI_CHECK_SEC; + WifiCheckIp(); + } +#if LWIP_IPV6 + if (WifiCheckIPAddrStatus()) { +#else + if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !Wifi.config_type) { +#endif + WifiSetState(1); + + if (Settings.flag3.use_wifi_rescan) { + if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) { + Wifi.scan_state = 2; + } + } + +#ifdef FIRMWARE_MINIMAL + if (1 == RtcSettings.ota_loader) { + RtcSettings.ota_loader = 0; + ota_state_flag = 3; + } +#endif + +#ifdef USE_DISCOVERY + if (Settings.flag3.mdns_enabled) { + if (!Wifi.mdns_begun) { + + + + + + Wifi.mdns_begun = (uint8_t)MDNS.begin(my_hostname); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Wifi.mdns_begun) ? D_INITIALIZED : D_FAILED); + + } + } +#endif + +#ifdef USE_WEBSERVER + if (Settings.webserver) { + StartWebserver(Settings.webserver, WiFi.localIP()); +#ifdef USE_DISCOVERY +#ifdef WEBSERVER_ADVERTISE + if (1 == Wifi.mdns_begun) { + Wifi.mdns_begun = 2; + MDNS.addService("http", "tcp", WEB_PORT); + } +#endif +#endif + } else { + StopWebserver(); + } +#ifdef USE_EMULATION +#ifdef USE_DEVICE_GROUPS + if (Settings.flag2.emulation || Settings.flag4.device_groups_enabled) { UdpConnect(); } +#else + if (Settings.flag2.emulation) { UdpConnect(); } +#endif +#endif +#endif + +#ifdef USE_KNX + if (!knx_started && Settings.flag.knx_enabled) { + KNXStart(); + knx_started = true; + } +#endif + + } else { + WifiSetState(0); +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + Wifi.mdns_begun = 0; +#ifdef USE_KNX + knx_started = false; +#endif + } + } + } +} + +int WifiState(void) +{ + int state = -1; + + if (!global_state.wifi_down) { state = WIFI_RESTART; } + if (Wifi.config_type) { state = Wifi.config_type; } + return state; +} + +String WifiGetOutputPower(void) +{ + char stemp1[TOPSZ]; + dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); + return String(stemp1); +} + +void WifiSetOutputPower(void) +{ + WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); +} + +void WifiConnect(void) +{ + WifiSetState(0); + WifiSetOutputPower(); + WiFi.persistent(false); + Wifi.status = 0; + Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); + Wifi.retry = Wifi.retry_init; + Wifi.counter = 1; +} + + + +void WifiDisconnect(void) +{ +#ifdef USE_WIFI_SDK_ERASE + SettingsSdkWifiErase(); +#else + + WiFi.persistent(true); + ETS_UART_INTR_DISABLE(); + wifi_station_disconnect(); + ETS_UART_INTR_ENABLE(); + WiFi.persistent(false); + delay(100); +#endif +} + +void WifiShutdown(void) +{ + delay(100); + if (Settings.flag.mqtt_enabled) { + MqttDisconnect(); + } + WifiDisconnect(); +} + +void EspRestart(void) +{ + WifiShutdown(); + CrashDumpClear(); + + ESP.reset(); +} +# 1 "S:/Development/Tasmota/tasmota/tasmota_ca.ino" +# 24 "S:/Development/Tasmota/tasmota/tasmota_ca.ino" +#ifdef USE_MQTT_TLS_CA_CERT + +#ifndef USE_MQTT_AWS_IOT +# 38 "S:/Development/Tasmota/tasmota/tasmota_ca.ino" +static const unsigned char PROGMEM TA0_DN[] = { + 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x58, 0x33 +}; + +static const unsigned char PROGMEM TA0_RSA_N[] = { + 0x9C, 0xD3, 0x0C, 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, 0x37, + 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, 0x35, 0x26, 0x19, 0x25, 0xE1, + 0xBD, 0xBE, 0x35, 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, 0x05, + 0xAB, 0xA9, 0x9E, 0x35, 0x08, 0x58, 0xEC, 0xB1, 0x2A, 0xC4, 0x68, 0x87, + 0x0B, 0xA3, 0xE3, 0x75, 0xE4, 0xE6, 0xF3, 0xA7, 0x62, 0x71, 0xBA, 0x79, + 0x81, 0x60, 0x1F, 0xD7, 0x91, 0x9A, 0x9F, 0xF3, 0xD0, 0x78, 0x67, 0x71, + 0xC8, 0x69, 0x0E, 0x95, 0x91, 0xCF, 0xFE, 0xE6, 0x99, 0xE9, 0x60, 0x3C, + 0x48, 0xCC, 0x7E, 0xCA, 0x4D, 0x77, 0x12, 0x24, 0x9D, 0x47, 0x1B, 0x5A, + 0xEB, 0xB9, 0xEC, 0x1E, 0x37, 0x00, 0x1C, 0x9C, 0xAC, 0x7B, 0xA7, 0x05, + 0xEA, 0xCE, 0x4A, 0xEB, 0xBD, 0x41, 0xE5, 0x36, 0x98, 0xB9, 0xCB, 0xFD, + 0x6D, 0x3C, 0x96, 0x68, 0xDF, 0x23, 0x2A, 0x42, 0x90, 0x0C, 0x86, 0x74, + 0x67, 0xC8, 0x7F, 0xA5, 0x9A, 0xB8, 0x52, 0x61, 0x14, 0x13, 0x3F, 0x65, + 0xE9, 0x82, 0x87, 0xCB, 0xDB, 0xFA, 0x0E, 0x56, 0xF6, 0x86, 0x89, 0xF3, + 0x85, 0x3F, 0x97, 0x86, 0xAF, 0xB0, 0xDC, 0x1A, 0xEF, 0x6B, 0x0D, 0x95, + 0x16, 0x7D, 0xC4, 0x2B, 0xA0, 0x65, 0xB2, 0x99, 0x04, 0x36, 0x75, 0x80, + 0x6B, 0xAC, 0x4A, 0xF3, 0x1B, 0x90, 0x49, 0x78, 0x2F, 0xA2, 0x96, 0x4F, + 0x2A, 0x20, 0x25, 0x29, 0x04, 0xC6, 0x74, 0xC0, 0xD0, 0x31, 0xCD, 0x8F, + 0x31, 0x38, 0x95, 0x16, 0xBA, 0xA8, 0x33, 0xB8, 0x43, 0xF1, 0xB1, 0x1F, + 0xC3, 0x30, 0x7F, 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, 0xE3, + 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, + 0x1D, 0x64, 0x16, 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, 0xC0, + 0xD8, 0x7D, 0xC3, 0x93 +}; + +static const unsigned char TA0_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +static const br_x509_trust_anchor PROGMEM LetsEncryptX3CrossSigned_TA = { + { (unsigned char *)TA0_DN, sizeof TA0_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, + (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, + } } + } +}; + +#define TAs_NUM 1 + +#endif + +#ifdef USE_MQTT_AWS_IOT +# 106 "S:/Development/Tasmota/tasmota/tasmota_ca.ino" +const unsigned char PROGMEM TA0_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +const unsigned char PROGMEM TA0_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char PROGMEM TA0_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +const br_x509_trust_anchor PROGMEM AmazonRootCA1_TA = { + { (unsigned char *)TA0_DN, sizeof TA0_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, + (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, + } } + } +}; + +#define TAs_NUM 1 + +#endif + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_01_webserver.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_01_webserver.ino" +#ifdef USE_WEBSERVER + + + + + + + +#define XDRV_01 1 + +#ifndef WIFI_SOFT_AP_CHANNEL +#define WIFI_SOFT_AP_CHANNEL 1 +#endif + +const uint16_t CHUNKED_BUFFER_SIZE = 400; + +const uint16_t HTTP_REFRESH_TIME = 2345; +#define HTTP_RESTART_RECONNECT_TIME 9000 +#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 + +#include +#include + +#ifdef USE_RF_FLASH +uint8_t *efm8bb1_update = nullptr; +#endif + +enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTASLAVE }; + +static const char * HEADER_KEYS[] = { "User-Agent", }; + +const char HTTP_HEADER[] PROGMEM = + "" + "" + "" + "" + "%s - %s" + + ""; + +const char HTTP_HEAD_STYLE1[] PROGMEM = + "" + + "" + "" + "

" +#ifdef FIRMWARE_MINIMAL + "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

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

" D_MODULE " %s

" +#else + "

%s " D_MODULE "

" +#endif + "

%s

"; + +const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM = + "
" + "" + "
"; +const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = + "
" D_CLOSE "" D_OPEN "
" + "
"; + +const char HTTP_MSG_RSTRT[] PROGMEM = + "
" D_DEVICE_WILL_RESTART "

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

" D_USER "

" + "

" D_PASSWORD "

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

" + "
 " D_TEMPLATE_FLAGS " 

" + + "

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

" D_MODULE_TYPE " (%s)

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

" D_AP1_SSID " (" STA_SSID1 ")

" + "

" D_AP1_PASSWORD "

" + "

" D_AP2_SSID " (" STA_SSID2 ")

" + "

" D_AP2_PASSWORD "

" + "

" D_HOSTNAME " (%s)

" + "

" D_CORS_DOMAIN "

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

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" + "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" + "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

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

" + "
 " D_TEMPLATE " " + "

" + "

" D_ACTIVATE "

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

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

" + "
" + "


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

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


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

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

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

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

"), + GetTextIndexed(action, sizeof(action), title_index, kButtonAction), + GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); + } +} + +void WSContentSpaceButton(uint32_t title_index) +{ + WSContentSend_P(PSTR("
")); + WSContentButton(title_index); +} + +void WSContentEnd(void) +{ + WSContentFlush(); + _WSContentSend(""); + WebServer->client().stop(); +} + +void WSContentStop(void) +{ + if (WifiIsInManagerMode()) { + if (WifiConfigCounter()) { + WSContentSend_P(HTTP_COUNTER); + } + } + WSContentSend_P(HTTP_END, my_version); + WSContentEnd(); +} + + + +void WebRestart(uint32_t type) +{ + + + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); + + bool reset_only = (HTTP_MANAGER_RESET_ONLY == Web.state); + + WSContentStart_P((type) ? S_SAVE_CONFIGURATION : S_RESTART, !reset_only); + WSContentSend_P(HTTP_SCRIPT_RELOAD); + WSContentSendStyle(); + if (type) { + WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); + if (2 == type) { + WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); + } + WSContentSend_P(PSTR("
")); + } + WSContentSend_P(HTTP_MSG_RSTRT); + if (HTTP_MANAGER == Web.state || reset_only) { + Web.state = HTTP_ADMIN; + } else { + WSContentSpaceButton(BUTTON_MAIN); + } + WSContentStop(); + + ShowWebSource(SRC_WEBGUI); + restart_flag = 2; +} + + + +void HandleWifiLogin(void) +{ + WSContentStart_P(S_CONFIGURE_WIFI, false); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_LOGIN); + + if (HTTP_MANAGER_RESET_ONLY == Web.state) { + WSContentSpaceButton(BUTTON_RESTART); +#ifndef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); +#endif + } + + WSContentStop(); +} + +void WebSliderColdWarm(void) +{ + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "a", + "#fff", "#ff0", + 1, + 153, 500, + LightGetColorTemp(), + 't', 0); +} + +void HandleRoot(void) +{ + if (CaptivePortal()) { return; } + + if (WebServer->hasArg("rst")) { + WebRestart(0); + return; + } + + if (WifiIsInManagerMode()) { +#ifndef FIRMWARE_MINIMAL + if (strlen(SettingsText(SET_WEBPWD)) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { + HandleWifiLogin(); + } else { + if (!strlen(SettingsText(SET_WEBPWD)) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { + HandleWifiConfiguration(); + } else { + + HandleWifiLogin(); + } + } +#endif + return; + } + + if (HandleRootStatusRefresh()) { + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); + + char stemp[33]; + + WSContentStart_P(S_MAIN_MENU); +#ifdef USE_SCRIPT_WEB_DISPLAY + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh, Settings.web_refresh); +#else + WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); +#endif + WSContentSend_P(HTTP_SCRIPT_ROOT_PART2); + + WSContentSendStyle(); + + WSContentSend_P(PSTR("
")); + if (devices_present) { +#ifdef USE_LIGHT + if (light_type) { + uint8_t light_subtype = light_type &7; + if (!Settings.flag3.pwm_multi_channels) { + bool split_white = ((LST_RGBW <= light_subtype) && (devices_present > 1)); + + if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) { + WebSliderColdWarm(); + } + + if (light_subtype > 2) { + uint16_t hue; + uint8_t sat; + LightGetHSB(&hue, &sat, nullptr); + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "b", + "#800", "#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800", + 2, + 1, 359, + hue, + 'h', 0); + + uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255); + char scolor[8]; + snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); + uint8_t red, green, blue; + LightHsToRgb(hue, 255, &red, &green, &blue); + snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "s", + scolor, stemp, + 3, + 0, 100, + changeUIntScale(sat, 0, 255, 0, 100), + 'n', 0); + } + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "c", + "#000", "#fff", + 4, + Settings.flag3.slider_dimmer_stay_on, 100, + Settings.light_dimmer, + 'd', 0); + + if (split_white) { + if (LST_RGBCW == light_subtype) { + WebSliderColdWarm(); + } + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + "f", + "#000", "#fff", + 5, + Settings.flag3.slider_dimmer_stay_on, 100, + LightGetDimmer(2), + 'w', 0); + } + } else { + uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; + stemp[0] = 'e'; stemp[1] = '0'; stemp[2] = '\0'; + for (uint32_t i = 0; i < pwm_channels; i++) { + stemp[1]++; + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, + stemp, + "#000", "#fff", + i+1, + 1, 100, + changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), + 'e', i+1); + } + } + } +#endif +#ifdef USE_SHUTTER + if (Settings.flag3.shutter_mode) { + for (uint32_t i = 0; i < shutters_present; i++) { + WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1); + } + } +#endif + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("
")); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, + (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : D_BUTTON_TOGGLE, + ""); + for (uint32_t i = 0; i < MaxFanspeed(); i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); + WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, + (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp, + ""); + } + } else { +#endif + for (uint32_t idx = 1; idx <= devices_present; idx++) { + bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); +#ifdef USE_SHUTTER + int32_t ShutterWebButton; + if (ShutterWebButton = IsShutterWebButton(idx)) { + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) ? "-" : ((ShutterWebButton>0) ? "▲" : "▼")), + ""); + continue; + } +#endif + snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); + WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, + (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (devices_present < 5) ? D_BUTTON_TOGGLE : "", + (set_button) ? "" : (devices_present > 1) ? stemp : ""); + } +#ifdef USE_SONOFF_IFAN + } +#endif + WSContentSend_P(PSTR("
%s
")); + } +#ifdef USE_SONOFF_RF + if (SONOFF_BRIDGE == my_module_type) { + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("")); + uint32_t idx = 0; + for (uint32_t i = 0; i < 4; i++) { + if (idx > 0) { WSContentSend_P(PSTR("")); } + for (uint32_t j = 0; j < 4; j++) { + idx++; + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), idx); + WSContentSend_P(PSTR(""), idx, + (strlen(SettingsText(SET_BUTTON1 + idx -1))) ? SettingsText(SET_BUTTON1 + idx -1) : stemp); + } + } + WSContentSend_P(PSTR("")); + } +#endif + +#ifndef FIRMWARE_MINIMAL + XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); + XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); +#endif + + if (HTTP_ADMIN == Web.state) { +#ifdef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE); +#else + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentButton(BUTTON_INFORMATION); + WSContentButton(BUTTON_FIRMWARE_UPGRADE); +#endif + WSContentButton(BUTTON_CONSOLE); + WSContentButton(BUTTON_RESTART); + } + WSContentStop(); +} + +bool HandleRootStatusRefresh(void) +{ + if (!WebAuthenticate()) { + WebServer->requestAuthentication(); + return true; + } + + if (!WebServer->hasArg("m")) { + return false; + } + + #ifdef USE_SCRIPT_WEB_DISPLAY + Script_Check_HTML_Setvars(); + #endif + + char tmp[8]; + char svalue[32]; + char webindex[5]; + + WebGetArg("o", tmp, sizeof(tmp)); + if (strlen(tmp)) { + ShowWebSource(SRC_WEBGUI); + uint32_t device = atoi(tmp); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + if (device < 2) { + ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE); + } else { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), device -2); + ExecuteCommand(svalue, SRC_WEBGUI); + } + } else { +#endif +#ifdef USE_SHUTTER + int32_t ShutterWebButton; + if (ShutterWebButton = IsShutterWebButton(device)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_TOGGLEUP) : PSTR(D_CMND_SHUTTER_TOGGLEDOWN)); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } else { +#endif + ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); +#ifdef USE_SHUTTER + } +#endif +#ifdef USE_SONOFF_IFAN + } +#endif + } + WebGetArg("d0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("w0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + for (uint32_t j = 1; j <= pwm_channels; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } + WebGetArg("t0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("h0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + WebGetArg("n0", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } +#ifdef USE_SHUTTER + for (uint32_t j = 1; j <= shutters_present; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } + } +#endif +#ifdef USE_SONOFF_RF + WebGetArg("k", tmp, sizeof(tmp)); + if (strlen(tmp)) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); + ExecuteWebCommand(svalue, SRC_WEBGUI); + } +#endif + WSContentBegin(200, CT_HTML); + WSContentSend_P(PSTR("{t}")); + XsnsCall(FUNC_WEB_SENSOR); +#ifdef USE_SCRIPT_WEB_DISPLAY + XdrvCall(FUNC_WEB_SENSOR); +#endif + + WSContentSend_P(PSTR("")); + + if (devices_present) { + WSContentSend_P(PSTR("{t}")); + uint32_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan()) { + WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); + uint32_t fanspeed = GetFanspeed(); + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); + WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); + } else { +#endif + for (uint32_t idx = 1; idx <= devices_present; idx++) { + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); + WSContentSend_P(HTTP_DEVICE_STATE, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); + } +#ifdef USE_SONOFF_IFAN + } +#endif + WSContentSend_P(PSTR("")); + } + WSContentEnd(); + + return true; +} + +#ifdef USE_SHUTTER +int32_t IsShutterWebButton(uint32_t idx) { + + int32_t ShutterWebButton = 0; + if (Settings.flag3.shutter_mode) { + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + if (Settings.shutter_startrelay[i] && ((Settings.shutter_startrelay[i] == idx) || (Settings.shutter_startrelay[i] == (idx-1)))) { + ShutterWebButton = (Settings.shutter_startrelay[i] == idx) ? (i+1): (-1-i); + break; + } + } + } + return ShutterWebButton; +} +#endif + + + +#ifndef FIRMWARE_MINIMAL + +void HandleConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); + + WSContentStart_P(S_CONFIGURATION); + WSContentSendStyle(); + + WSContentButton(BUTTON_MODULE); + WSContentButton(BUTTON_WIFI); + + XdrvCall(FUNC_WEB_ADD_BUTTON); + XsnsCall(FUNC_WEB_ADD_BUTTON); + + WSContentButton(BUTTON_LOGGING); + WSContentButton(BUTTON_OTHER); + WSContentButton(BUTTON_TEMPLATE); + + WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); + WSContentButton(BUTTON_BACKUP); + WSContentButton(BUTTON_RESTORE); + + WSContentSpaceButton(BUTTON_MAIN); + WSContentStop(); +} + + + +void HandleTemplateConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + TemplateSaveSettings(); + WebRestart(1); + return; + } + + char stemp[30]; + + if (WebServer->hasArg("m")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { + uint32_t midx = pgm_read_byte(kModuleNiceList + i); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); + } + WSContentEnd(); + return; + } + + WebGetArg("t", stemp, sizeof(stemp)); + if (strlen(stemp)) { + uint32_t module = atoi(stemp); + uint32_t module_save = Settings.module; + Settings.module = module; + myio cmodule; + ModuleGpios(&cmodule); + gpio_flag flag = ModuleFlag(); + Settings.module = module_save; + + WSContentBegin(200, CT_PLAIN); + WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); + for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { + if (1 == i) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); + } + uint32_t midx = pgm_read_byte(kGpioNiceList + i); + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); + } + WSContentSend_P(PSTR("}1")); + + for (uint32_t i = 0; i < ADC0_END; i++) { + if (1 == i) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ADC0_USER, D_SENSOR_USER, ADC0_USER); + } + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, i, GetTextIndexed(stemp, sizeof(stemp), i, kAdc0Names), i); + } + WSContentSend_P(PSTR("}1")); + + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if ((i < 6) || ((i > 8) && (i != 11))) { + WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", cmodule.io[i]); + } + } + WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings.user_template_base); + WSContentEnd(); + return; + } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); + + WSContentStart_P(S_CONFIGURE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_TEMPLATE); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_TEMPLATE); + WSContentSend_P(HTTP_TABLE100); + WSContentSend_P(PSTR("" D_TEMPLATE_NAME "" + "" D_BASE_TYPE "" + "" + "
")); + WSContentSend_P(HTTP_TABLE100); + for (uint32_t i = 0; i < 17; i++) { + if ((i < 6) || ((i > 8) && (i != 11))) { + WSContentSend_P(PSTR("" D_GPIO "%d"), + ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i); + } + } + WSContentSend_P(PSTR("" D_ADC "0"), WebColor(COL_TEXT)); + WSContentSend_P(PSTR("")); + gpio_flag flag = ModuleFlag(); + if (flag.data > ADC0_USER) { + WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); + } + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void TemplateSaveSettings(void) +{ + char tmp[sizeof(Settings.user_template.name)]; + char webindex[5]; + char svalue[128]; + + WebGetArg("s1", tmp, sizeof(tmp)); + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); + + uint32_t j = 0; + for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { + if (6 == i) { j = 9; } + if (8 == i) { j = 12; } + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); + WebGetArg(webindex, tmp, sizeof(tmp)); + uint8_t gpio = atoi(tmp); + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio); + j++; + } + + WebGetArg("g17", tmp, sizeof(tmp)); + uint32_t flag = atoi(tmp); + for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { + snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); + uint32_t state = WebServer->hasArg(webindex) << i +4; + flag += state; + } + WebGetArg("g99", tmp, sizeof(tmp)); + uint32_t base = atoi(tmp) +1; + + snprintf_P(svalue, sizeof(svalue), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), svalue, flag, base); + ExecuteWebCommand(svalue, SRC_WEBGUI); +} + + + +void HandleModuleConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + ModuleSaveSettings(); + WebRestart(1); + return; + } + + char stemp[30]; + uint32_t midx; + myio cmodule; + ModuleGpios(&cmodule); + + if (WebServer->hasArg("m")) { + WSContentBegin(200, CT_PLAIN); + uint32_t vidx = 0; + for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { + if (0 == i) { + midx = USER_MODULE; + vidx = 0; + } else { + midx = pgm_read_byte(kModuleNiceList + i -1); + vidx = midx +1; + } + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx); + } + WSContentEnd(); + return; + } + + if (WebServer->hasArg("g")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t j = 0; j < sizeof(kGpioNiceList); j++) { + midx = pgm_read_byte(kGpioNiceList + j); + if (!GetUsedInModule(midx, cmodule.io)) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); + } + } + WSContentEnd(); + return; + } + +#ifndef USE_ADC_VCC + if (WebServer->hasArg("a")) { + WSContentBegin(200, CT_PLAIN); + for (uint32_t j = 0; j < ADC0_END; j++) { + WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j); + } + WSContentEnd(); + return; + } +#endif + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); + + WSContentStart_P(S_CONFIGURE_MODULE); + WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); + WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (ValidGPIO(i, cmodule.io[i])) { + WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); + } + } + WSContentSend_P(HTTP_SCRIPT_MODULE2, Settings.my_adc0); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (ValidGPIO(i, cmodule.io[i])) { + snprintf_P(stemp, 3, PINS_WEMOS +i*2); + char sesp8285[40]; + snprintf_P(sesp8285, sizeof(sesp8285), PSTR("ESP8285"), WebColor(COL_TEXT_WARNING)); + WSContentSend_P(PSTR("%s " D_GPIO "%d %s"), + (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i); + } + } +#ifndef USE_ADC_VCC + if (ValidAdc()) { + WSContentSend_P(PSTR("%s " D_ADC "0"), (WEMOS==my_module_type)?"A0":""); + } +#endif + WSContentSend_P(PSTR("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void ModuleSaveSettings(void) +{ + char tmp[8]; + char webindex[5]; + + WebGetArg("g99", tmp, sizeof(tmp)); + uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); + Settings.last_module = Settings.module; + Settings.module = new_module; + SetModuleType(); + myio cmodule; + ModuleGpios(&cmodule); + String gpios = ""; + for (uint32_t i = 0; i < sizeof(cmodule); i++) { + if (Settings.last_module != new_module) { + Settings.my_gp.io[i] = GPIO_NONE; + } else { + if (ValidGPIO(i, cmodule.io[i])) { + snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); + WebGetArg(webindex, tmp, sizeof(tmp)); + Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); + gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); + } + } + } +#ifndef USE_ADC_VCC + WebGetArg("g17", tmp, sizeof(tmp)); + Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp); + gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0); +#endif + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); +} + + + +const char kUnescapeCode[] = "&><\"\'"; +const char kEscapeCode[] PROGMEM = "&|>|<|"|'"; + +String HtmlEscape(const String unescaped) { + char escaped[10]; + size_t ulen = unescaped.length(); + String result = ""; + for (size_t i = 0; i < ulen; i++) { + char c = unescaped[i]; + char *p = strchr(kUnescapeCode, c); + if (p != nullptr) { + result += GetTextIndexed(escaped, sizeof(escaped), p - kUnescapeCode, kEscapeCode); + } else { + result += c; + } + } + return result; +} + + +const char kEncryptionType[] PROGMEM = "|||" D_WPA_PSK "||" D_WPA2_PSK "|" D_WEP "||" D_NONE "|" D_AUTO; + +void HandleWifiConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); + + if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { + WifiSaveSettings(); + WebRestart(2); + return; + } + + WSContentStart_P(S_CONFIGURE_WIFI, !WifiIsInManagerMode()); + WSContentSend_P(HTTP_SCRIPT_WIFI); + WSContentSendStyle(); + + if (HTTP_MANAGER_RESET_ONLY != Web.state) { + if (WebServer->hasArg("scan")) { +#ifdef USE_EMULATION + UdpDisconnect(); +#endif + int n = WiFi.scanNetworks(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); + + if (0 == n) { + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); + WSContentSend_P(S_NO_NETWORKS_FOUND); + WSContentSend_P(PSTR(". " D_REFRESH_TO_SCAN_AGAIN ".")); + } else { + + int indices[n]; + for (uint32_t i = 0; i < n; i++) { + indices[i] = i; + } + + + for (uint32_t i = 0; i < n; i++) { + for (uint32_t j = i + 1; j < n; j++) { + if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { + std::swap(indices[i], indices[j]); + } + } + } + + + String cssid; + for (uint32_t i = 0; i < n; i++) { + if (-1 == indices[i]) { continue; } + cssid = WiFi.SSID(indices[i]); + uint32_t cschn = WiFi.channel(indices[i]); + for (uint32_t j = i + 1; j < n; j++) { + if ((cssid == WiFi.SSID(indices[j])) && (cschn == WiFi.channel(indices[j]))) { + DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); + indices[j] = -1; + } + } + } + + + for (uint32_t i = 0; i < n; i++) { + if (-1 == indices[i]) { continue; } + int32_t rssi = WiFi.RSSI(indices[i]) + DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), + WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), rssi); + int quality = WifiGetRssiAsQuality(rssi); + int auth = WiFi.encryptionType(indices[i]); + char encryption[20]; + WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), + HtmlEscape(WiFi.SSID(indices[i])).c_str(), + WiFi.channel(indices[i]), + GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), + quality, rssi + ); + delay(0); + + } + WSContentSend_P(PSTR("
")); + } + } else { + WSContentSend_P(PSTR("
")); + } + + + WSContentSend_P(HTTP_FORM_WIFI, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS)); + WSContentSend_P(HTTP_FORM_END); + } + + if (WifiIsInManagerMode()) { +#ifndef FIRMWARE_MINIMAL + WSContentSpaceButton(BUTTON_RESTORE); + WSContentButton(BUTTON_RESET_CONFIGURATION); +#endif + WSContentSpaceButton(BUTTON_RESTART); + } else { + WSContentSpaceButton(BUTTON_CONFIGURATION); + } + WSContentStop(); +} + +void WifiSaveSettings(void) +{ + char tmp[TOPSZ]; + + WebGetArg("h", tmp, sizeof(tmp)); + SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); + if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { + SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); + } + WebGetArg("c", tmp, sizeof(tmp)); + SettingsUpdateText(SET_CORS, (!strlen(tmp)) ? CORS_DOMAIN : tmp); + WebGetArg("s1", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STASSID1, (!strlen(tmp)) ? STA_SSID1 : tmp); + WebGetArg("s2", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STASSID2, (!strlen(tmp)) ? STA_SSID2 : tmp); + WebGetArg("p1", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STAPWD1, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD1) : tmp); + WebGetArg("p2", tmp, sizeof(tmp)); + SettingsUpdateText(SET_STAPWD2, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD2) : tmp); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), + SettingsText(SET_HOSTNAME), SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), SettingsText(SET_CORS)); +} + + + +void HandleLoggingConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); + + if (WebServer->hasArg("save")) { + LoggingSaveSettings(); + HandleConfiguration(); + return; + } + + WSContentStart_P(S_CONFIGURE_LOGGING); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_LOG1); + char stemp1[45]; + char stemp2[32]; + uint8_t dlevel[4] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE, LOG_LEVEL_NONE }; + for (uint32_t idx = 0; idx < 4; idx++) { + if ((2==idx) && !Settings.flag.mqtt_enabled) { continue; } + uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:(2==idx)?Settings.mqttlog_level:Settings.syslog_level; + WSContentSend_P(PSTR("

%s (%s)

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

"), + i +1, + (i) ? stemp : "", + i, + (i) ? stemp : "", + SettingsText(SET_FRIENDLYNAME1 + i)); + } + +#ifdef USE_EMULATION + WSContentSend_P(PSTR("

 " D_EMULATION " 

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

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

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

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

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

" D_HOST " (" MQTT_HOST ")

" + "

" D_PORT " (" STR(MQTT_PORT) ")

" + "

" D_CLIENT " (%s)

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

" D_USER " (" MQTT_USER ")

" + "

" D_PASSWORD "

" + "

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

" + "

" D_FULL_TOPIC " (%s)

"; + +void HandleMqttConfiguration(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); + + if (WebServer->hasArg("save")) { + MqttSaveSettings(); + WebRestart(1); + return; + } + + char str[TOPSZ]; + + WSContentStart_P(S_CONFIGURE_MQTT); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_MQTT1, + SettingsText(SET_MQTT_HOST), + Settings.mqtt_port, + Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); + WSContentSend_P(HTTP_FORM_MQTT2, + (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), + Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC), + MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void MqttSaveSettings(void) +{ + char tmp[TOPSZ]; + char stemp[TOPSZ]; + char stemp2[TOPSZ]; + + WebGetArg("mt", tmp, sizeof(tmp)); + strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); + MakeValidMqtt(0, stemp); + WebGetArg("mf", tmp, sizeof(tmp)); + strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); + MakeValidMqtt(1, stemp2); + if ((strcmp(stemp, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) { + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, S_LWT, true); + } + SettingsUpdateText(SET_MQTT_TOPIC, stemp); + SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2); + WebGetArg("mh", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); + WebGetArg("ml", tmp, sizeof(tmp)); + Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); + WebGetArg("mc", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); +#else + WebGetArg("mu", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp); + WebGetArg("mp", tmp, sizeof(tmp)); + SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), + SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); +#endif +} +#endif + + + + + +bool Xdrv02(uint8_t function) +{ + bool result = false; + + if (Settings.flag.mqtt_enabled) { + switch (function) { + case FUNC_PRE_INIT: + MqttInit(); + break; + case FUNC_EVERY_50_MSECOND: + MqttClient.loop(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_MQTT); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); + break; +#endif + case FUNC_COMMAND: + result = DecodeCommand(kMqttCommands, MqttCommand); + break; + } + } + return result; +} +# 1 "S:/Development/Tasmota/tasmota/xdrv_03_energy.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_03_energy.ino" +#ifdef USE_ENERGY_SENSOR + + + + +#define XDRV_03 3 +#define XSNS_03 3 + + + + +#define ENERGY_NONE 0 +#define ENERGY_WATCHDOG 4 + +#include + +#define D_CMND_POWERCAL "PowerCal" +#define D_CMND_VOLTAGECAL "VoltageCal" +#define D_CMND_CURRENTCAL "CurrentCal" +#define D_CMND_TARIFF "Tariff" +#define D_CMND_MODULEADDRESS "ModuleAddress" + +enum EnergyCommands { + CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, + CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS }; + +const char kEnergyCommands[] PROGMEM = "|" + D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" + D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|" +#ifdef USE_ENERGY_MARGIN_DETECTION + D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" +#ifdef USE_ENERGY_POWER_LIMIT + D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|" + D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" + D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|" +#endif +#endif + D_CMND_ENERGYRESET "|" D_CMND_TARIFF ; + +void (* const EnergyCommand[])(void) PROGMEM = { + &CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, + &CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress, +#ifdef USE_ENERGY_MARGIN_DETECTION + &CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh, +#ifdef USE_ENERGY_POWER_LIMIT + &CmndMaxEnergy, &CmndMaxEnergyStart, + &CmndMaxPower, &CmndMaxPowerHold, &CmndMaxPowerWindow, + &CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow, +#endif +#endif + &CmndEnergyReset, &CmndTariff }; + +const char kEnergyPhases[] PROGMEM = "|%s / %s|%s / %s / %s||[%s,%s]|[%s,%s,%s]"; + +struct ENERGY { + float voltage[3] = { 0, 0, 0 }; + float current[3] = { 0, 0, 0 }; + float active_power[3] = { 0, 0, 0 }; + float apparent_power[3] = { NAN, NAN, NAN }; + float reactive_power[3] = { NAN, NAN, NAN }; + float power_factor[3] = { NAN, NAN, NAN }; + float frequency[3] = { NAN, NAN, NAN }; + + float start_energy = 0; + float daily = 0; + float total = 0; + float export_active = NAN; + + unsigned long kWhtoday_delta = 0; + unsigned long kWhtoday_offset = 0; + unsigned long kWhtoday; + unsigned long period = 0; + + uint8_t fifth_second = 0; + uint8_t command_code = 0; + uint8_t data_valid[3] = { 0, 0, 0 }; + + uint8_t phase_count = 1; + bool voltage_common = false; + + bool voltage_available = true; + bool current_available = true; + + bool type_dc = false; + bool power_on = true; + +#ifdef USE_ENERGY_MARGIN_DETECTION + uint16_t power_history[3] = { 0 }; + uint8_t power_steady_counter = 8; + bool power_delta = false; + bool min_power_flag = false; + bool max_power_flag = false; + bool min_voltage_flag = false; + bool max_voltage_flag = false; + bool min_current_flag = false; + bool max_current_flag = false; + +#ifdef USE_ENERGY_POWER_LIMIT + uint16_t mplh_counter = 0; + uint16_t mplw_counter = 0; + uint8_t mplr_counter = 0; + uint8_t max_energy_state = 0; +#endif +#endif +} Energy; + +Ticker ticker_energy; + + + +bool EnergyTariff1Active() +{ + uint8_t dst = 0; + if (IsDst() && (Settings.tariff[0][1] != Settings.tariff[1][1])) { + dst = 1; + } + if (Settings.tariff[0][dst] != Settings.tariff[1][dst]) { + if (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || + (RtcTime.day_of_week == 7))) { + return true; + } + uint32_t minutes = MinutesPastMidnight(); + if (Settings.tariff[0][dst] > Settings.tariff[1][dst]) { + + return ((minutes >= Settings.tariff[0][dst]) || (minutes < Settings.tariff[1][dst])); + } else { + + return ((minutes >= Settings.tariff[0][dst]) && (minutes < Settings.tariff[1][dst])); + } + } else { + return false; + } +} + +void EnergyUpdateToday(void) +{ + if (Energy.kWhtoday_delta > 1000) { + unsigned long delta = Energy.kWhtoday_delta / 1000; + Energy.kWhtoday_delta -= (delta * 1000); + Energy.kWhtoday += delta; + } + + RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday; + Energy.daily = (float)(RtcSettings.energy_kWhtoday) / 100000; + Energy.total = (float)(RtcSettings.energy_kWhtotal + RtcSettings.energy_kWhtoday) / 100000; + + if (RtcTime.valid){ + + uint32_t energy_diff = (uint32_t)(Energy.total * 100000) - RtcSettings.energy_usage.last_usage_kWhtotal; + RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 100000); + + uint32_t return_diff = 0; + if (!isnan(Energy.export_active)) { + return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; + RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000); + } + + if (EnergyTariff1Active()) { + RtcSettings.energy_usage.usage1_kWhtotal += energy_diff; + RtcSettings.energy_usage.return1_kWhtotal += return_diff; + } else { + RtcSettings.energy_usage.usage2_kWhtotal += energy_diff; + RtcSettings.energy_usage.return2_kWhtotal += return_diff; + } + } +} + +void EnergyUpdateTotal(float value, bool kwh) +{ + + + + + uint32_t multiplier = (kwh) ? 100000 : 100; + + if (0 == Energy.start_energy || (value < Energy.start_energy)) { + Energy.start_energy = value; + } + else if (value != Energy.start_energy) { + Energy.kWhtoday = (unsigned long)((value - Energy.start_energy) * multiplier); + } + + if ((Energy.total < (value - 0.01)) && + Settings.flag3.hardware_energy_total) { + RtcSettings.energy_kWhtotal = (unsigned long)((value * multiplier) - Energy.kWhtoday_offset - Energy.kWhtoday); + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; + Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); + + } + EnergyUpdateToday(); +} + + + +void Energy200ms(void) +{ + Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; + + Energy.fifth_second++; + if (5 == Energy.fifth_second) { + Energy.fifth_second = 0; + + XnrgCall(FUNC_ENERGY_EVERY_SECOND); + + if (RtcTime.valid) { + if (LocalTime() == Midnight()) { + Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; + + RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + Energy.kWhtoday = 0; + Energy.kWhtoday_offset = 0; + RtcSettings.energy_kWhtoday = 0; + Energy.start_energy = 0; + + Energy.kWhtoday_delta = 0; + Energy.period = Energy.kWhtoday; + EnergyUpdateToday(); +#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) + Energy.max_energy_state = 3; +#endif + } +#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) + if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == Energy.max_energy_state )) { + Energy.max_energy_state = 0; + } +#endif + + } + } + + XnrgCall(FUNC_EVERY_200_MSECOND); +} + +void EnergySaveState(void) +{ + Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; + + Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + + Settings.energy_usage = RtcSettings.energy_usage; +} + +#ifdef USE_ENERGY_MARGIN_DETECTION +bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) +{ + bool change; + + if (!margin) return false; + change = save_flag; + if (type) { + flag = (value > margin); + } else { + flag = (value < margin); + } + save_flag = flag; + return (change != save_flag); +} + +void EnergyMarginCheck(void) +{ + if (Energy.power_steady_counter) { + Energy.power_steady_counter--; + return; + } + + uint16_t energy_power_u = (uint16_t)(Energy.active_power[0]); + + if (Settings.energy_power_delta) { + uint16_t delta = abs(Energy.power_history[0] - energy_power_u); + if (delta > 0) { + if (Settings.energy_power_delta < 101) { + uint16_t min_power = (Energy.power_history[0] > energy_power_u) ? energy_power_u : Energy.power_history[0]; + if (0 == min_power) { min_power++; } + if (((delta * 100) / min_power) > Settings.energy_power_delta) { + Energy.power_delta = true; + } + } else { + if (delta > (Settings.energy_power_delta -100)) { + Energy.power_delta = true; + } + } + if (Energy.power_delta) { + Energy.power_history[1] = Energy.active_power[0]; + Energy.power_history[2] = Energy.active_power[0]; + } + } + } + Energy.power_history[0] = Energy.power_history[1]; + Energy.power_history[1] = Energy.power_history[2]; + Energy.power_history[2] = energy_power_u; + + if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { + uint16_t energy_voltage_u = (uint16_t)(Energy.voltage[0]); + uint16_t energy_current_u = (uint16_t)(Energy.current[0] * 1000); + + DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); + + Response_P(PSTR("{")); + bool flag; + bool jsonflg = false; + if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, Energy.max_power_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, Energy.min_current_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, Energy.max_current_flag)) { + ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); + jsonflg = true; + } + if (jsonflg) { + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); + EnergyMqttShow(); + } + } + +#ifdef USE_ENERGY_POWER_LIMIT + + if (Settings.energy_max_power_limit) { + if (Energy.active_power[0] > Settings.energy_max_power_limit) { + if (!Energy.mplh_counter) { + Energy.mplh_counter = Settings.energy_max_power_limit_hold; + } else { + Energy.mplh_counter--; + if (!Energy.mplh_counter) { + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":%d}"), energy_power_u); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); + if (!Energy.mplr_counter) { + Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; + } + Energy.mplw_counter = Settings.energy_max_power_limit_window; + } + } + } + else if (power && (energy_power_u <= Settings.energy_max_power_limit)) { + Energy.mplh_counter = 0; + Energy.mplr_counter = 0; + Energy.mplw_counter = 0; + } + if (!power) { + if (Energy.mplw_counter) { + Energy.mplw_counter--; + } else { + if (Energy.mplr_counter) { + Energy.mplr_counter--; + if (Energy.mplr_counter) { + ResponseTime_P(PSTR(",\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); + RestorePower(true, SRC_MAXPOWER); + } else { + ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); + } + } + } + } + } + + + if (Settings.energy_max_energy) { + uint16_t energy_daily_u = (uint16_t)(Energy.daily * 1000); + if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { + Energy.max_energy_state = 1; + ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); + RestorePower(true, SRC_MAXENERGY); + } + else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { + Energy.max_energy_state = 2; + char stemp[FLOATSZ]; + dtostrfd(Energy.daily, 3, stemp); + ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":%s}"), stemp); + MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); + EnergyMqttShow(); + SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); + } + } +#endif + + if (Energy.power_delta) { EnergyMqttShow(); } +} + +void EnergyMqttShow(void) +{ + + int tele_period_save = tele_period; + tele_period = 2; + mqtt_data[0] = '\0'; + ResponseAppendTime(); + EnergyShow(true); + tele_period = tele_period_save; + ResponseJsonEnd(); + MqttPublishTeleSensor(); + Energy.power_delta = false; +} +#endif + +void EnergyEverySecond(void) +{ + + if (global_update) { + if (power && (global_temperature != 9999) && (global_temperature > Settings.param[P_OVER_TEMP])) { + SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); + } + } + + + uint32_t data_valid = Energy.phase_count; + for (uint32_t i = 0; i < Energy.phase_count; i++) { + if (Energy.data_valid[i] <= ENERGY_WATCHDOG) { + Energy.data_valid[i]++; + if (Energy.data_valid[i] > ENERGY_WATCHDOG) { + + Energy.voltage[i] = 0; + Energy.current[i] = 0; + Energy.active_power[i] = 0; + if (!isnan(Energy.apparent_power[i])) { Energy.apparent_power[i] = 0; } + if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; } + if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; } + if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; } + + data_valid--; + } + } + } + if (!data_valid) { + if (!isnan(Energy.export_active)) { Energy.export_active = 0; } + Energy.start_energy = 0; + + XnrgCall(FUNC_ENERGY_RESET); + } + +#ifdef USE_ENERGY_MARGIN_DETECTION + EnergyMarginCheck(); +#endif +} + + + + + +void EnergyCommandCalResponse(uint32_t nvalue) +{ + snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); + ResponseCmndNumber(nvalue); +} + +void CmndEnergyReset(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { + char *p; + unsigned long lnum = strtoul(XdrvMailbox.data, &p, 10); + if (p != XdrvMailbox.data) { + switch (XdrvMailbox.index) { + case 1: + + Energy.kWhtoday_offset = lnum *100; + Energy.kWhtoday = 0; + Energy.kWhtoday_delta = 0; + Energy.start_energy = 0; + Energy.period = Energy.kWhtoday_offset; + Settings.energy_kWhtoday = Energy.kWhtoday_offset; + RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset; + Energy.daily = (float)Energy.kWhtoday_offset / 100000; + if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) { + Settings.energy_kWhtotal_time = LocalTime(); + } + break; + case 2: + + Settings.energy_kWhyesterday = lnum *100; + break; + case 3: + + RtcSettings.energy_kWhtotal = lnum *100; + Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; + + Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); + RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); + break; + } + } + } + else if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { + uint32_t values[2] = { 0 }; + uint32_t position = ParseParameters(2, values); + values[0] *= 100; + values[1] *= 100; + + switch (XdrvMailbox.index) + { + case 4: + + if (position > 0) { + RtcSettings.energy_usage.usage1_kWhtotal = values[0]; + } + if (position > 1) { + RtcSettings.energy_usage.usage2_kWhtotal = values[1]; + } + Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; + Settings.energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal; + break; + case 5: + + if (position > 0) { + RtcSettings.energy_usage.return1_kWhtotal = values[0]; + } + if (position > 1) { + RtcSettings.energy_usage.return2_kWhtotal = values[1]; + } + Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal; + Settings.energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal; + break; + } + } + + Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; + + char energy_total_chr[FLOATSZ]; + dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); + char energy_daily_chr[FLOATSZ]; + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); + char energy_yesterday_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + + char energy_usage1_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage1_chr); + char energy_usage2_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage2_chr); + char energy_return1_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return1_chr); + char energy_return2_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return2_chr); + + Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s,\"" D_JSON_USAGE "\":[%s,%s],\"" D_JSON_EXPORT "\":[%s,%s]}}"), + XdrvMailbox.command, energy_total_chr, energy_yesterday_chr, energy_daily_chr, energy_usage1_chr, energy_usage2_chr, energy_return1_chr, energy_return2_chr); +} + +void CmndTariff(void) +{ + + + + + + + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + uint32_t tariff = XdrvMailbox.index -1; + uint32_t time_type = 0; + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + while ((str != nullptr) && (time_type < 2)) { + char *q; + uint32_t value = strtol(str, &q, 10); + Settings.tariff[tariff][time_type] = value; + if (value < 24) { + Settings.tariff[tariff][time_type] *= 60; + char *minute = strtok_r(nullptr, ":", &q); + if (minute) { + value = strtol(minute, nullptr, 10); + if (value > 59) { + value = 59; + } + Settings.tariff[tariff][time_type] += value; + } + } + if (Settings.tariff[tariff][time_type] > 1439) { + Settings.tariff[tariff][time_type] = 1439; + } + str = strtok_r(nullptr, ", ", &p); + time_type++; + } + } + else if (XdrvMailbox.index == 9) { + Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; + } + Response_P(PSTR("{\"%s\":{\"Off-Peak\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Standard\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Weekend\":\"%s\"}}"), + XdrvMailbox.command, + GetMinuteTime(Settings.tariff[0][0]).c_str(),GetMinuteTime(Settings.tariff[0][1]).c_str(), + GetMinuteTime(Settings.tariff[1][0]).c_str(),GetMinuteTime(Settings.tariff[1][1]).c_str(), + GetStateText(Settings.flag3.energy_weekend)); +} + +void CmndPowerCal(void) +{ + Energy.command_code = CMND_POWERCAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_power_calibration = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_power_calibration); + } +} + +void CmndVoltageCal(void) +{ + Energy.command_code = CMND_VOLTAGECAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_voltage_calibration = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_voltage_calibration); + } +} + +void CmndCurrentCal(void) +{ + Energy.command_code = CMND_CURRENTCAL; + if (XnrgCall(FUNC_COMMAND)) { + if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { + Settings.energy_current_calibration = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_current_calibration); + } +} + +void CmndPowerSet(void) +{ + Energy.command_code = CMND_POWERSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_power_calibration); + } +} + +void CmndVoltageSet(void) +{ + Energy.command_code = CMND_VOLTAGESET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_voltage_calibration); + } +} + +void CmndCurrentSet(void) +{ + Energy.command_code = CMND_CURRENTSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_current_calibration); + } +} + +void CmndFrequencySet(void) +{ + Energy.command_code = CMND_FREQUENCYSET; + if (XnrgCall(FUNC_COMMAND)) { + EnergyCommandCalResponse(Settings.energy_frequency_calibration); + } +} + +void CmndModuleAddress(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) { + Energy.command_code = CMND_MODULEADDRESS; + if (XnrgCall(FUNC_COMMAND)) { + ResponseCmndDone(); + } + } +} + +#ifdef USE_ENERGY_MARGIN_DETECTION +void CmndPowerDelta(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { + Settings.energy_power_delta = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_power_delta); +} + +void CmndPowerLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_min_power = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_power); +} + +void CmndPowerHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power); +} + +void CmndVoltageLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { + Settings.energy_min_voltage = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_voltage); +} + +void CmndVoltageHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { + Settings.energy_max_voltage = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_voltage); +} + +void CmndCurrentLow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { + Settings.energy_min_current = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_min_current); +} + +void CmndCurrentHigh(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { + Settings.energy_max_current = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_current); +} + +#ifdef USE_ENERGY_POWER_LIMIT +void CmndMaxPower(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit); +} + +void CmndMaxPowerHold(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit_hold); +} + +void CmndMaxPowerWindow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_limit_window); +} + +void CmndSafePower(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_safe_limit = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit); +} + +void CmndSafePowerHold(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold); +} + +void CmndSafePowerWindow(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) { + Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_power_safe_limit_window); +} + +void CmndMaxEnergy(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.energy_max_energy = XdrvMailbox.payload; + Energy.max_energy_state = 3; + } + ResponseCmndNumber(Settings.energy_max_energy); +} + +void CmndMaxEnergyStart(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { + Settings.energy_max_energy_start = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.energy_max_energy_start); +} +#endif +#endif + +void EnergySnsInit(void) +{ + XnrgCall(FUNC_INIT); + + if (energy_flg) { + if (RtcSettingsValid()) { + Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; + } + else if (RtcTime.day_of_year == Settings.energy_kWhdoy) { + Energy.kWhtoday_offset = Settings.energy_kWhtoday; + } + else { + Energy.kWhtoday_offset = 0; + } + Energy.kWhtoday = 0; + Energy.kWhtoday_delta = 0; + Energy.period = Energy.kWhtoday_offset; + EnergyUpdateToday(); + ticker_energy.attach_ms(200, Energy200ms); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_SNS1[] PROGMEM = + "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" + "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" + "{s}" D_POWER_FACTOR "{m}%s{e}"; + +const char HTTP_ENERGY_SNS2[] PROGMEM = + "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; + +const char HTTP_ENERGY_SNS3[] PROGMEM = + "{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; +#endif + +char* EnergyFormatIndex(char* result, char* input, bool json, uint32_t index, bool single = false) +{ + char layout[16]; + GetTextIndexed(layout, sizeof(layout), (index -1) + (3 * json), kEnergyPhases); + switch (index) { + case 2: + snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ); + break; + case 3: + snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ, input + FLOATSZ + FLOATSZ); + break; + default: + snprintf_P(result, FLOATSZ *3, input); + } + return result; +} + +char* EnergyFormat(char* result, char* input, bool json, bool single = false) +{ + uint8_t index = (single) ? 1 : Energy.phase_count; + return EnergyFormatIndex(result, input, json, index, single); +} + +void EnergyShow(bool json) +{ + for (uint32_t i = 0; i < Energy.phase_count; i++) { + if (Energy.voltage_common) { + Energy.voltage[i] = Energy.voltage[0]; + } + } + + float power_factor_knx = Energy.power_factor[0]; + + char apparent_power_chr[Energy.phase_count][FLOATSZ]; + char reactive_power_chr[Energy.phase_count][FLOATSZ]; + char power_factor_chr[Energy.phase_count][FLOATSZ]; + char frequency_chr[Energy.phase_count][FLOATSZ]; + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + for (uint32_t i = 0; i < Energy.phase_count; i++) { + float apparent_power = Energy.apparent_power[i]; + if (isnan(apparent_power)) { + apparent_power = Energy.voltage[i] * Energy.current[i]; + } + if (apparent_power < Energy.active_power[i]) { + Energy.active_power[i] = apparent_power; + } + + float power_factor = Energy.power_factor[i]; + if (isnan(power_factor)) { + power_factor = (Energy.active_power[i] && apparent_power) ? Energy.active_power[i] / apparent_power : 0; + if (power_factor > 1) { + power_factor = 1; + } + } + if (0 == i) { power_factor_knx = power_factor; } + + float reactive_power = Energy.reactive_power[i]; + if (isnan(reactive_power)) { + reactive_power = 0; + uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(Energy.active_power[i] * 100)) / 10; + if ((Energy.current[i] > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { + + + reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(Energy.active_power[i] * Energy.active_power[i] * 100))) / 10; + } + } + + dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr[i]); + dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr[i]); + dtostrfd(power_factor, 2, power_factor_chr[i]); + } + } + for (uint32_t i = 0; i < Energy.phase_count; i++) { + float frequency = Energy.frequency[i]; + if (isnan(Energy.frequency[i])) { + frequency = 0; + } + dtostrfd(frequency, Settings.flag2.frequency_resolution, frequency_chr[i]); + } + } + + char voltage_chr[Energy.phase_count][FLOATSZ]; + char current_chr[Energy.phase_count][FLOATSZ]; + char active_power_chr[Energy.phase_count][FLOATSZ]; + for (uint32_t i = 0; i < Energy.phase_count; i++) { + dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]); + dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]); + dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]); + } + + char energy_daily_chr[FLOATSZ]; + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); + char energy_yesterday_chr[FLOATSZ]; + dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); + + char energy_total_chr[3][FLOATSZ]; + dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr[0]); + char export_active_chr[3][FLOATSZ]; + dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]); + uint8_t energy_total_fields = 1; + + if (Settings.tariff[0][0] != Settings.tariff[1][0]) { + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[2]); + energy_total_fields = 3; + } + + char value_chr[FLOATSZ *3]; + char value2_chr[FLOATSZ *3]; + char value3_chr[FLOATSZ *3]; + + if (json) { + bool show_energy_period = (0 == tele_period); + + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), + GetDateAndTime(DT_ENERGY).c_str(), + EnergyFormatIndex(value_chr, energy_total_chr[0], json, energy_total_fields), + energy_yesterday_chr, + energy_daily_chr); + + if (!isnan(Energy.export_active)) { + ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), + EnergyFormatIndex(value_chr, export_active_chr[0], json, energy_total_fields)); + } + + if (show_energy_period) { + float energy = 0; + if (Energy.period) { + energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100; + } + Energy.period = RtcSettings.energy_kWhtoday; + char energy_period_chr[FLOATSZ]; + dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); + ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); + } + ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"), + EnergyFormat(value_chr, active_power_chr[0], json)); + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"), + EnergyFormat(value_chr, apparent_power_chr[0], json), + EnergyFormat(value2_chr, reactive_power_chr[0], json), + EnergyFormat(value3_chr, power_factor_chr[0], json)); + } + if (!isnan(Energy.frequency[0])) { + ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), + EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); + } + } + if (Energy.voltage_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), + EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); + } + if (Energy.current_available) { + ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), + EnergyFormat(value_chr, current_chr[0], json)); + } + XnrgCall(FUNC_JSON_APPEND); + ResponseJsonEnd(); + +#ifdef USE_DOMOTICZ + if (show_energy_period) { + dtostrfd(Energy.total * 1000, 1, energy_total_chr[0]); + DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr[0]); + + dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_total_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_total_chr[2]); + dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, export_active_chr[1]); + dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, export_active_chr[2]); + DomoticzSensorP1SmartMeter(energy_total_chr[1], energy_total_chr[2], export_active_chr[1], export_active_chr[2], (int)Energy.active_power[0]); + + if (Energy.voltage_available) { + DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); + } + if (Energy.current_available) { + DomoticzSensor(DZ_CURRENT, current_chr[0]); + } + } +#endif +#ifdef USE_KNX + if (show_energy_period) { + if (Energy.voltage_available) { + KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage[0]); + } + if (Energy.current_available) { + KnxSensor(KNX_ENERGY_CURRENT, Energy.current[0]); + } + KnxSensor(KNX_ENERGY_POWER, Energy.active_power[0]); + if (!Energy.type_dc) { + KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor_knx); + } + KnxSensor(KNX_ENERGY_DAILY, Energy.daily); + KnxSensor(KNX_ENERGY_TOTAL, Energy.total); + KnxSensor(KNX_ENERGY_START, Energy.start_energy); + } +#endif +#ifdef USE_WEBSERVER + } else { + if (Energy.voltage_available) { + WSContentSend_PD(HTTP_SNS_VOLTAGE, EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); + } + if (Energy.current_available) { + WSContentSend_PD(HTTP_SNS_CURRENT, EnergyFormat(value_chr, current_chr[0], json)); + } + WSContentSend_PD(HTTP_SNS_POWER, EnergyFormat(value_chr, active_power_chr[0], json)); + if (!Energy.type_dc) { + if (Energy.current_available && Energy.voltage_available) { + WSContentSend_PD(HTTP_ENERGY_SNS1, EnergyFormat(value_chr, apparent_power_chr[0], json), + EnergyFormat(value2_chr, reactive_power_chr[0], json), + EnergyFormat(value3_chr, power_factor_chr[0], json)); + } + if (!isnan(Energy.frequency[0])) { + WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), + EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); + } + } + WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]); + if (!isnan(Energy.export_active)) { + WSContentSend_PD(HTTP_ENERGY_SNS3, export_active_chr[0]); + } + + XnrgCall(FUNC_WEB_SENSOR); +#endif + } +} + + + + + +bool Xdrv03(uint8_t function) +{ + bool result = false; + + if (FUNC_PRE_INIT == function) { + energy_flg = ENERGY_NONE; + XnrgCall(FUNC_PRE_INIT); + } + else if (energy_flg) { + switch (function) { + case FUNC_LOOP: + XnrgCall(FUNC_LOOP); + break; + case FUNC_EVERY_250_MSECOND: + XnrgCall(FUNC_EVERY_250_MSECOND); + break; + case FUNC_SERIAL: + result = XnrgCall(FUNC_SERIAL); + break; +#ifdef USE_ENERGY_MARGIN_DETECTION + case FUNC_SET_POWER: + Energy.power_steady_counter = 2; + break; +#endif + case FUNC_COMMAND: + result = DecodeCommand(kEnergyCommands, EnergyCommand); + break; + } + } + return result; +} + +bool Xsns03(uint8_t function) +{ + bool result = false; + + if (energy_flg) { + switch (function) { + case FUNC_EVERY_SECOND: + EnergyEverySecond(); + break; + case FUNC_JSON_APPEND: + EnergyShow(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + EnergyShow(false); + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + EnergySaveState(); + break; + case FUNC_INIT: + EnergySnsInit(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" +#ifdef USE_LIGHT +# 124 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" +#define XDRV_04 4 + + +enum LightSchemes { LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX }; + +const uint8_t LIGHT_COLOR_SIZE = 25; + +const char kLightCommands[] PROGMEM = "|" + D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" + D_CMND_RGBWWTABLE "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" + D_CMND_WHITE "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; + +void (* const LightCommand[])(void) PROGMEM = { + &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndDimmerRange, &CmndLedTable, &CmndFade, + &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, + &CmndWhite, &CmndChannel, &CmndHsbColor, &CmndUndocA }; + + +enum LightColorModes { + LCM_RGB = 1, LCM_CT = 2, LCM_BOTH = 3 }; + +struct LRgbColor { + uint8_t R, G, B; +}; +const uint8_t MAX_FIXED_COLOR = 12; +const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = + { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; + +struct LWColor { + uint8_t W; +}; +const uint8_t MAX_FIXED_WHITE = 4; +const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; + +struct LCwColor { + uint8_t C, W; +}; +const uint8_t MAX_FIXED_COLD_WARM = 4; +const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; + + +const uint16_t CT_MIN = 153; +const uint16_t CT_MAX = 500; + +const uint16_t CT_MIN_ALEXA = 200; +const uint16_t CT_MAX_ALEXA = 380; + + + + + + +typedef struct gamma_table_t { + uint16_t to_src; + uint16_t to_gamma; +} gamma_table_t; + +const gamma_table_t gamma_table[] = { + { 1, 1 }, + { 4, 1 }, + { 209, 13 }, + { 312, 41 }, + { 457, 106 }, + { 626, 261 }, + { 762, 450 }, + { 895, 703 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } +}; + + +const gamma_table_t gamma_table_fast[] = { + { 384, 192 }, + { 768, 576 }, + { 1023, 1023 }, + { 0xFFFF, 0xFFFF } +}; +# 248 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" +struct LIGHT { + uint32_t strip_timer_counter = 0; + power_t power = 0; + + uint16_t wakeup_counter = 0; + + uint8_t entry_color[LST_MAX]; + uint8_t current_color[LST_MAX]; + uint8_t new_color[LST_MAX]; + uint8_t last_color[LST_MAX]; + uint8_t color_remap[LST_MAX]; + + uint8_t wheel = 0; + uint8_t random = 0; + uint8_t subtype = 0; + uint8_t device = 0; + uint8_t old_power = 1; + uint8_t wakeup_active = 0; + uint8_t wakeup_dimmer = 0; + uint8_t fixed_color_index = 1; + uint8_t pwm_offset = 0; + uint8_t max_scheme = LS_MAX -1; + + bool update = true; + bool pwm_multi_channels = false; + + bool fade_initialized = false; + bool fade_running = false; + uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; + uint16_t fade_cur_10[LST_MAX]; + uint16_t fade_end_10[LST_MAX]; + uint16_t fade_duration = 0; + uint32_t fade_start = 0; +} Light; + +power_t LightPower(void) +{ + return Light.power; +} + + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +power_t LightPowerIRAM(void) ICACHE_RAM_ATTR; +#endif + +power_t LightPowerIRAM(void) +{ + return Light.power; +} + +uint8_t LightDevice(void) +{ + return Light.device; +} + +static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) { + return (a < b && a < c) ? a : (b < c) ? b : c; +} +# 344 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" +class LightStateClass { + private: + uint16_t _hue = 0; + uint8_t _sat = 255; + uint8_t _briRGB = 255; + + uint8_t _r = 255; + uint8_t _g = 255; + uint8_t _b = 255; + + uint8_t _subtype = 0; + uint16_t _ct = CT_MIN; + uint8_t _wc = 255; + uint8_t _ww = 0; + uint8_t _briCT = 255; + + uint8_t _color_mode = LCM_RGB; + + + + + + uint16_t _ct_min_range = CT_MIN; + uint16_t _ct_max_range = CT_MAX; + + public: + LightStateClass() { + + } + + void setSubType(uint8_t sub_type) { + _subtype = sub_type; + } +# 386 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" + uint8_t setColorMode(uint8_t cm) { + uint8_t prev_cm = _color_mode; + if (cm < LCM_RGB) { cm = LCM_RGB; } + if (cm > LCM_BOTH) { cm = LCM_BOTH; } + uint8_t maxbri = (_briRGB >= _briCT) ? _briRGB : _briCT; + + switch (_subtype) { + case LST_COLDWARM: + _color_mode = LCM_CT; + break; + + case LST_NONE: + case LST_SINGLE: + case LST_RGB: + default: + _color_mode = LCM_RGB; + break; + + case LST_RGBW: + case LST_RGBCW: + _color_mode = cm; + break; + } + if (LCM_RGB == _color_mode) { + _briCT = 0; + if (0 == _briRGB) { _briRGB = maxbri; } + } + if (LCM_CT == _color_mode) { + _briRGB = 0; + if (0 == _briCT) { _briCT = maxbri; } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setColorMode prev_cm (%d) req_cm (%d) new_cm (%d)", prev_cm, cm, _color_mode); +#endif + return prev_cm; + } + + inline uint8_t getColorMode() { + return _color_mode; + } + + void addRGBMode() { + setColorMode(_color_mode | LCM_RGB); + } + void addCTMode() { + setColorMode(_color_mode | LCM_CT); + } + + + void getRGB(uint8_t *r, uint8_t *g, uint8_t *b) { + if (r) { *r = _r; } + if (g) { *g = _g; } + if (b) { *b = _b; } + } + + + + void getCW(uint8_t *rc, uint8_t *rw) { + if (rc) { *rc = _wc; } + if (rw) { *rw = _ww; } + } + + + void getActualRGBCW(uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *c, uint8_t *w) { + bool rgb_channels_on = _color_mode & LCM_RGB; + bool ct_channels_on = _color_mode & LCM_CT; + + if (r) { *r = rgb_channels_on ? changeUIntScale(_r, 0, 255, 0, _briRGB) : 0; } + if (g) { *g = rgb_channels_on ? changeUIntScale(_g, 0, 255, 0, _briRGB) : 0; } + if (b) { *b = rgb_channels_on ? changeUIntScale(_b, 0, 255, 0, _briRGB) : 0; } + + if (c) { *c = ct_channels_on ? changeUIntScale(_wc, 0, 255, 0, _briCT) : 0; } + if (w) { *w = ct_channels_on ? changeUIntScale(_ww, 0, 255, 0, _briCT) : 0; } + } + + uint8_t getChannels(uint8_t *channels) { + getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); + } + + void getChannelsRaw(uint8_t *channels) { + channels[0] = _r; + channels[1] = _g; + channels[2] = _b; + channels[3] = _wc; + channels[4] = _ww; + } + + void getHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { + if (hue) { *hue = _hue; } + if (sat) { *sat = _sat; } + if (bri) { *bri = _briRGB; } + } + + + uint8_t getBri(void) { + + return (_briRGB >= _briCT) ? _briRGB : _briCT; + } + + + inline uint8_t getBriCT() { + return _briCT; + } + + static inline uint8_t DimmerToBri(uint8_t dimmer) { + return changeUIntScale(dimmer, 0, 100, 0, 255); + } + static uint8_t BriToDimmer(uint8_t bri) { + uint8_t dimmer = changeUIntScale(bri, 0, 255, 0, 100); + + if ((dimmer == 0) && (bri > 0)) { dimmer = 1; } + return dimmer; + } + + uint8_t getDimmer(uint32_t mode = 0) { + uint8_t bri; + switch (mode) { + case 1: + bri = getBriRGB(); + break; + case 2: + bri = getBriCT(); + break; + default: + bri = getBri(); + break; + } + return BriToDimmer(bri); + } + + inline uint16_t getCT() const { + return _ct; + } + + + uint16_t getCT10bits() const { + return changeUIntScale(_ct, _ct_min_range, _ct_max_range, 0, 1023); + } + + inline void setCTRange(uint16_t ct_min_range, uint16_t ct_max_range) { + _ct_min_range = ct_min_range; + _ct_max_range = ct_max_range; + } + + inline void getCTRange(uint16_t *ct_min_range, uint16_t *ct_max_range) const { + if (ct_min_range) { *ct_min_range = _ct_min_range; } + if (ct_max_range) { *ct_max_range = _ct_max_range; } + } + + + void getXY(float *x, float *y) { + RgbToXy(_r, _g, _b, x, y); + } + + + + void setBri(uint8_t bri) { + setBriRGB(_color_mode & LCM_RGB ? bri : 0); + setBriCT(_color_mode & LCM_CT ? bri : 0); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setBri RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + } + + + uint8_t setBriRGB(uint8_t bri_rgb) { + uint8_t prev_bri = _briRGB; + _briRGB = bri_rgb; + if (bri_rgb > 0) { addRGBMode(); } + return prev_bri; + } + + + uint8_t setBriCT(uint8_t bri_ct) { + uint8_t prev_bri = _briCT; + _briCT = bri_ct; + if (bri_ct > 0) { addCTMode(); } + return prev_bri; + } + + inline uint8_t getBriRGB() { + return _briRGB; + } + + void setDimmer(uint8_t dimmer) { + setBri(DimmerToBri(dimmer)); + } + + void setCT(uint16_t ct) { + if (0 == ct) { + + setColorMode(LCM_RGB); + } else { + ct = (ct < CT_MIN ? CT_MIN : (ct > CT_MAX ? CT_MAX : ct)); + _ww = changeUIntScale(ct, _ct_min_range, _ct_max_range, 0, 255); + _wc = 255 - _ww; + _ct = ct; + addCTMode(); + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCT RGB raw (%d %d %d) HS (%d %d) briRGB (%d) briCT (%d) CT (%d)", _r, _g, _b, _hue, _sat, _briRGB, _briCT, _ct); +#endif + } +# 604 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" + void setCW(uint8_t c, uint8_t w, bool free_range = false) { + uint16_t max = (w > c) ? w : c; + uint16_t sum = c + w; + + if (0 == max) { + _briCT = 0; + setColorMode(LCM_RGB); + } else { + if (!free_range) { + + _ww = changeUIntScale(w, 0, sum, 0, 255); + _wc = 255 - _ww; + } else { + _ww = changeUIntScale(w, 0, max, 0, 255); + _wc = changeUIntScale(c, 0, max, 0, 255); + } + _ct = changeUIntScale(w, 0, sum, _ct_min_range, _ct_max_range); + addCTMode(); + if (_color_mode & LCM_CT) { _briCT = free_range ? max : (sum > 255 ? 255 : sum); } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCW CW (%d %d) CT (%d) briCT (%d)", c, w, _ct, _briCT); +#endif + } + + + uint8_t setRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { + uint16_t hue; + uint8_t sat; +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB input (%d %d %d)", r, g, b); +#endif + + uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; + + if (0 == max) { + r = g = b = 255; + setColorMode(LCM_CT); + } else { + if (255 > max) { + + r = changeUIntScale(r, 0, max, 0, 255); + g = changeUIntScale(g, 0, max, 0, 255); + b = changeUIntScale(b, 0, max, 0, 255); + } + addRGBMode(); + } + if (!keep_bri) { + _briRGB = (_color_mode & LCM_RGB) ? max : 0; + } + + RgbToHsb(r, g, b, &hue, &sat, nullptr); + _r = r; + _g = g; + _b = b; + _hue = hue; + _sat = sat; +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + return max; + } + + void setHS(uint16_t hue, uint8_t sat) { + uint8_t r, g, b; + HsToRgb(hue, sat, &r, &g, &b); + _r = r; + _g = g; + _b = b; + _hue = hue; + _sat = sat; + addRGBMode(); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS HS (%d %d) rgb (%d %d %d)", hue, sat, r, g, b); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); +#endif + } + + + + void setChannelsRaw(uint8_t *channels) { + _r = channels[0]; + _g = channels[1]; + _b = channels[2]; + _wc = channels[3]; + _ww = channels[4]; +} + + + + + void setChannels(uint8_t *channels) { + setRGB(channels[0], channels[1], channels[2]); + setCW(channels[3], channels[4], true); +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels (%d %d %d %d %d)", + channels[0], channels[1], channels[2], channels[3], channels[4]); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels CT (%d) briRGB (%d) briCT (%d)", _ct, _briRGB, _briCT); +#endif + } + + + static void RgbToHsb(uint8_t r, uint8_t g, uint8_t b, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri); + static void HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); + static void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y); + static void XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb); + +}; +# 720 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" +void LightStateClass::RgbToHsb(uint8_t ir, uint8_t ig, uint8_t ib, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri) { + uint32_t r = ir; + uint32_t g = ig; + uint32_t b = ib; + uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; + uint32_t min = (r < g && r < b) ? r : (g < b) ? g : b; + uint32_t d = max - min; + + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = max; + + if (d != 0) { + sat = changeUIntScale(d, 0, max, 0, 255); + if (r == max) { + hue = (g > b) ? changeUIntScale(g-b,0,d,0,60) : 360 - changeUIntScale(b-g,0,d,0,60); + } else if (g == max) { + hue = (b > r) ? 120 + changeUIntScale(b-r,0,d,0,60) : 120 - changeUIntScale(r-b,0,d,0,60); + } else { + hue = (r > g) ? 240 + changeUIntScale(r-g,0,d,0,60) : 240 - changeUIntScale(g-r,0,d,0,60); + } + hue = hue % 360; + } + + if (r_hue) *r_hue = hue; + if (r_sat) *r_sat = sat; + if (r_bri) *r_bri = bri; + +} + +void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { + uint32_t r = 255; + uint32_t g = 255; + uint32_t b = 255; + + hue = hue % 360; + + if (sat > 0) { + uint32_t i = hue / 60; + uint32_t f = hue % 60; + uint32_t q = 255 - changeUIntScale(f, 0, 60, 0, sat); + uint32_t p = 255 - sat; + uint32_t t = 255 - changeUIntScale(60 - f, 0, 60, 0, sat); + + switch (i) { + case 0: + + g = t; + b = p; + break; + case 1: + r = q; + + b = p; + break; + case 2: + r = p; + + b = t; + break; + case 3: + r = p; + g = q; + + break; + case 4: + r = t; + g = p; + + break; + default: + + g = p; + b = q; + break; + } + } + if (r_r) *r_r = r; + if (r_g) *r_g = g; + if (r_b) *r_b = b; +} + +#define POW FastPrecisePowf + +void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) { + float x = 0.31271f; + float y = 0.32902f; + + if (i_r + i_b + i_g > 0) { + float r = (float)i_r / 255.0f; + float g = (float)i_g / 255.0f; + float b = (float)i_b / 255.0f; + + + r = (r > 0.04045f) ? POW((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f); + g = (g > 0.04045f) ? POW((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f); + b = (b > 0.04045f) ? POW((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f); + + + + float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; + float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; + float Z = r * 0.000000f + g * 0.053077f + b * 1.035763f; + + x = X / (X + Y + Z); + y = Y / (X + Y + Z); + + } + if (r_x) *r_x = x; + if (r_y) *r_y = y; +} + +void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb) +{ + x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x)); + y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y)); + float z = 1.0f - x - y; + + float X = x / y; + float Z = z / y; + + + + float r = X * 3.2406f - 1.5372f - Z * 0.4986f; + float g = -X * 0.9689f + 1.8758f + Z * 0.0415f; + float b = X * 0.0557f - 0.2040f + Z * 1.0570f; + float max = (r > g && r > b) ? r : (g > b) ? g : b; + r = r / max; + g = g / max; + b = b / max; + r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * POW(r, (1.0f / 2.4f)) - 0.055f; + g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * POW(g, (1.0f / 2.4f)) - 0.055f; + b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * POW(b, (1.0f / 2.4f)) - 0.055f; + + + + + + int32_t ir = r * 255.0f + 0.5f; + int32_t ig = g * 255.0f + 0.5f; + int32_t ib = b * 255.0f + 0.5f; + if (rr) { *rr = (ir > 255 ? 255: (ir < 0 ? 0 : ir)); } + if (rg) { *rg = (ig > 255 ? 255: (ig < 0 ? 0 : ig)); } + if (rb) { *rb = (ib > 255 ? 255: (ib < 0 ? 0 : ib)); } +} + +class LightControllerClass { +private: + LightStateClass *_state; + + + bool _ct_rgb_linked = true; + bool _pwm_multi_channels = false; + +public: + LightControllerClass(LightStateClass& state) { + _state = &state; + } + + void setSubType(uint8_t sub_type) { + _state->setSubType(sub_type); + } + + inline bool setCTRGBLinked(bool ct_rgb_linked) { + bool prev = _ct_rgb_linked; + if (_pwm_multi_channels) { + _ct_rgb_linked = false; + } else { + _ct_rgb_linked = ct_rgb_linked; + } + return prev; + } + + void setAlexaCTRange(bool alexa_ct_range) { + + if (alexa_ct_range) { + _state->setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA); + } else { + _state->setCTRange(CT_MIN, CT_MAX); + } + } + + inline bool isCTRGBLinked() { + return _ct_rgb_linked; + } + + inline bool setPWMMultiChannel(bool pwm_multi_channels) { + bool prev = _pwm_multi_channels; + _pwm_multi_channels = pwm_multi_channels; + if (pwm_multi_channels) setCTRGBLinked(false); + return prev; + } + + inline bool isPWMMultiChannel(void) { + return _pwm_multi_channels; + } + +#ifdef DEBUG_LIGHT + void debugLogs() { + uint8_t r,g,b,c,w; + _state->getActualRGBCW(&r,&g,&b,&c,&w); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs rgb (%d %d %d) cw (%d %d)", + r, g, b, c, w); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs lightCurrent (%d %d %d %d %d)", + Light.current_color[0], Light.current_color[1], Light.current_color[2], + Light.current_color[3], Light.current_color[4]); + } +#endif + + void loadSettings() { +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings Settings.light_color (%d %d %d %d %d - %d)", + Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], + Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", + light_type, Light.subtype); +#endif + if (_pwm_multi_channels) { + _state->setChannelsRaw(Settings.light_color); + } else { + + _state->setCW(Settings.light_color[3], Settings.light_color[4], true); + _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); + + + + uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); + if (Settings.light_color[0] + Settings.light_color[1] + Settings.light_color[2] > 0) { + + + if ( (DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) && + (DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) && + (DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) { + _state->setColorMode(LCM_RGB); + } + _state->setBriRGB(bri); + } else { + _state->setBriCT(bri); + } + } + } + + void changeCTB(uint16_t new_ct, uint8_t briCT) { + + + + + + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBW > Light.subtype)) { + return; + } + _state->setCT(new_ct); + _state->setBriCT(briCT); + if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } + saveSettings(); + calcLevels(); + + } + + void changeDimmer(uint8_t dimmer, uint32_t mode = 0) { + uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); + switch (mode) { + case 1: + changeBriRGB(bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + break; + case 2: + changeBriCT(bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } + break; + default: + changeBri(bri); + break; + } + } + + void changeBri(uint8_t bri) { + _state->setBri(bri); + saveSettings(); + calcLevels(); + } + + void changeBriRGB(uint8_t bri) { + _state->setBriRGB(bri); + saveSettings(); + calcLevels(); + } + + void changeBriCT(uint8_t bri) { + _state->setBriCT(bri); + saveSettings(); + calcLevels(); + } + + void changeRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { + _state->setRGB(r, g, b, keep_bri); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + saveSettings(); + calcLevels(); + } + + + + void calcLevels(uint8_t *current_color = nullptr) { + uint8_t r,g,b,c,w,briRGB,briCT; + if (current_color == nullptr) { current_color = Light.current_color; } + + if (_pwm_multi_channels) { + _state->getChannelsRaw(current_color); + return; + } + + _state->getActualRGBCW(&r,&g,&b,&c,&w); + briRGB = _state->getBriRGB(); + briCT = _state->getBriCT(); + + current_color[0] = current_color[1] = current_color[2] = 0; + current_color[3] = current_color[4] = 0; + switch (Light.subtype) { + case LST_NONE: + current_color[0] = 255; + break; + case LST_SINGLE: + current_color[0] = briRGB; + break; + case LST_COLDWARM: + current_color[0] = c; + current_color[1] = w; + break; + case LST_RGBW: + case LST_RGBCW: + if (LST_RGBCW == Light.subtype) { + current_color[3] = c; + current_color[4] = w; + } else { + current_color[3] = briCT; + } + + case LST_RGB: + current_color[0] = r; + current_color[1] = g; + current_color[2] = b; + break; + } + } + + void changeHSB(uint16_t hue, uint8_t sat, uint8_t briRGB) { + _state->setHS(hue, sat); + _state->setBriRGB(briRGB); + if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } + saveSettings(); + calcLevels(); + } + + + void saveSettings() { + if (Light.pwm_multi_channels) { + + _state->getChannelsRaw(Settings.light_color); + Settings.light_dimmer = 100; + } else { + uint8_t cm = _state->getColorMode(); + + memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); + if (LCM_RGB & cm) { + _state->getRGB(&Settings.light_color[0], &Settings.light_color[1], &Settings.light_color[2]); + Settings.light_dimmer = _state->BriToDimmer(_state->getBriRGB()); + + if (LCM_BOTH == cm) { + + _state->getActualRGBCW(nullptr, nullptr, nullptr, &Settings.light_color[3], &Settings.light_color[4]); + } + } else if (LCM_CT == cm) { + _state->getCW(&Settings.light_color[3], &Settings.light_color[4]); + Settings.light_dimmer = _state->BriToDimmer(_state->getBriCT()); + } + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::saveSettings Settings.light_color (%d %d %d %d %d - %d)", + Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], + Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); +#endif + } + + + + + void changeChannels(uint8_t *channels) { + if (Light.pwm_multi_channels) { + _state->setChannelsRaw(channels); + } else if (LST_COLDWARM == Light.subtype) { + + uint8_t remapped_channels[5] = {0,0,0,channels[0],channels[1]}; + _state->setChannels(remapped_channels); + } else { + _state->setChannels(channels); + } + + saveSettings(); + calcLevels(); + } +}; + + + +LightStateClass light_state = LightStateClass(); +LightControllerClass light_controller = LightControllerClass(light_state); + + + + + +uint16_t change8to10(uint8_t v) { + return changeUIntScale(v, 0, 255, 0, 1023); +} + +uint8_t change10to8(uint16_t v) { + return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); +} + + + + + +uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (v <= to_src) { + return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); + } + from_src = to_src; + from_gamma = to_gamma; + } +} + +uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) { + uint16_t from_src = 0; + uint16_t from_gamma = 0; + + for (const gamma_table_t *gt = gt_ptr; ; gt++) { + uint16_t to_src = gt->to_src; + uint16_t to_gamma = gt->to_gamma; + if (vg <= to_gamma) { + return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src); + } + from_src = to_src; + from_gamma = to_gamma; + } +} + + +uint16_t ledGamma10_10(uint16_t v) { + return ledGamma_internal(v, gamma_table); +} + +uint16_t ledGamma10(uint8_t v) { + return ledGamma10_10(change8to10(v)); +} + + +uint8_t ledGamma(uint8_t v) { + return change10to8(ledGamma10(v)); +} + + + +void LightPwmOffset(uint32_t offset) +{ + Light.pwm_offset = offset; +} + +bool LightModuleInit(void) +{ + light_type = LT_BASIC; + + if (Settings.flag.pwm_control) { + for (uint32_t i = 0; i < MAX_PWMS; i++) { + if (pin[GPIO_PWM1 +i] < 99) { light_type++; } + } + } + + light_flg = 0; + if (XlgtCall(FUNC_MODULE_INIT)) { + + } + else if (SONOFF_BN == my_module_type) { + light_type = LT_PWM1; + } + else if (SONOFF_LED == my_module_type) { + if (!my_module.io[4]) { + pinMode(4, OUTPUT); + digitalWrite(4, LOW); + } + if (!my_module.io[5]) { + pinMode(5, OUTPUT); + digitalWrite(5, LOW); + } + if (!my_module.io[14]) { + pinMode(14, OUTPUT); + digitalWrite(14, LOW); + } + light_type = LT_PWM2; + } + + if (light_type > LT_BASIC) { + devices_present++; + } + + + if (Settings.flag3.pwm_multi_channels) { + uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + if (0 == pwm_channels) { pwm_channels = 1; } + devices_present += pwm_channels - 1; + } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= (light_type & 7))) { + + devices_present++; + } + + return (light_type > LT_BASIC); +} + +void LightInit(void) +{ + Light.device = devices_present; + Light.subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); + Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; + + if (LST_RGBW <= Light.subtype) { + + + bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); + light_controller.setCTRGBLinked(ct_rgb_linked); + } + + if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) { + + light_controller.setPWMMultiChannel(true); + Light.device = devices_present - Light.subtype + 1; + } else if (!light_controller.isCTRGBLinked()) { + + Light.device--; + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", + Light.pwm_multi_channels, Light.subtype, Light.device, devices_present); +#endif + + light_controller.setSubType(Light.subtype); + light_controller.loadSettings(); + light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); + + if (LST_SINGLE == Light.subtype) { + Settings.light_color[0] = 255; + } + if (light_type < LT_PWM6) { + for (uint32_t i = 0; i < light_type; i++) { + Settings.pwm_value[i] = 0; + if (pin[GPIO_PWM1 +i] < 99) { + pinMode(pin[GPIO_PWM1 +i], OUTPUT); + } + } + if (pin[GPIO_ARIRFRCV] < 99) { + if (pin[GPIO_ARIRFSEL] < 99) { + pinMode(pin[GPIO_ARIRFSEL], OUTPUT); + digitalWrite(pin[GPIO_ARIRFSEL], 1); + } + } + } + + uint32_t max_scheme = Light.max_scheme; + if (Light.subtype < LST_RGB) { + max_scheme = LS_POWER; + } + if ((LS_WAKEUP == Settings.light_scheme) || (Settings.light_scheme > max_scheme)) { + Settings.light_scheme = LS_POWER; + } + Light.power = 0; + Light.update = true; + Light.wakeup_active = 0; + + LightUpdateColorMapping(); +} + +void LightUpdateColorMapping(void) +{ + uint8_t param = Settings.param[P_RGB_REMAP] & 127; + if (param > 119){ param = 0; } + + uint8_t tmp[] = {0,1,2,3,4}; + Light.color_remap[0] = tmp[param / 24]; + for (uint32_t i = param / 24; i<4; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 24; + Light.color_remap[1] = tmp[(param / 6)]; + for (uint32_t i = param / 6; i<3; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 6; + Light.color_remap[2] = tmp[(param / 2)]; + for (uint32_t i = param / 2; i<2; ++i){ + tmp[i] = tmp[i+1]; + } + param = param % 2; + Light.color_remap[3] = tmp[param]; + Light.color_remap[4] = tmp[1-param]; + + Light.update = true; + +} + +uint8_t LightGetDimmer(uint8_t dimmer) { + return light_state.getDimmer(dimmer); +} + +void LightSetDimmer(uint8_t dimmer) { + light_controller.changeDimmer(dimmer); +} + +void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { + light_state.getHSB(hue, sat, bri); +} + +void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { + light_state.HsToRgb(hue, sat, r_r, r_g, r_b); +} + + +uint8_t LightGetBri(uint8_t device) { + uint8_t bri = 254; + if (Light.pwm_multi_channels) { + if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { + bri = Light.current_color[device - Light.device]; + } + } else if (light_controller.isCTRGBLinked()) { + if (device == Light.device) { + bri = light_state.getBri(); + } + } else { + if (device == Light.device) { + bri = light_state.getBriRGB(); + } else if (device == Light.device + 1) { + bri = light_state.getBriCT(); + } + } + return bri; +} + + +void LightSetBri(uint8_t device, uint8_t bri) { + if (Light.pwm_multi_channels) { + if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { + Light.current_color[device - Light.device] = bri; + light_controller.changeChannels(Light.current_color); + } + } else if (light_controller.isCTRGBLinked()) { + if (device == Light.device) { + light_controller.changeBri(bri); + } + } else { + if (device == Light.device) { + light_controller.changeBriRGB(bri); + } else if (device == Light.device + 1) { + light_controller.changeBriCT(bri); + } + } +} + +void LightSetColorTemp(uint16_t ct) +{ + + + + + + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { + return; + } + light_controller.changeCTB(ct, light_state.getBriCT()); +} + +uint16_t LightGetColorTemp(void) +{ + + if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { + return 0; + } + return (light_state.getColorMode() & LCM_CT) ? light_state.getCT() : 0; +} + +void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) +{ + + + + if (Settings.flag.light_signal) { + uint16_t signal = changeUIntScale(value, lo, hi, 0, 255); + + light_controller.changeRGB(signal, 255 - signal, 0, true); + Settings.light_scheme = 0; + if (0 == light_state.getBri()) { + light_controller.changeBri(50); + } + } +} + + +char* LightGetColor(char* scolor, boolean force_hex = false) +{ + light_controller.calcLevels(); + scolor[0] = '\0'; + for (uint32_t i = 0; i < Light.subtype; i++) { + if (!force_hex && Settings.flag.decimal_text) { + snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Light.current_color[i]); + } else { + snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%02X"), scolor, Light.current_color[i]); + } + } + return scolor; +} + +void LightPowerOn(void) +{ + if (light_state.getBri() && !(Light.power)) { + ExecuteCommandPower(Light.device, POWER_ON, SRC_LIGHT); + } +} + +void LightState(uint8_t append) +{ + char scolor[LIGHT_COLOR_SIZE]; + char scommand[33]; + bool unlinked = !light_controller.isCTRGBLinked() && (Light.subtype >= LST_RGBW); + + if (append) { + ResponseAppend_P(PSTR(",")); + } else { + Response_P(PSTR("{")); + } + if (!Light.pwm_multi_channels) { + if (unlinked) { + + ResponseAppend_P(PSTR("\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d" + ",\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d"), + Light.device, GetStateText(Light.power & 1), Light.device, light_state.getDimmer(1), + Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), Light.device + 1, light_state.getDimmer(2)); + } else { + GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1), + light_state.getDimmer()); + } + + + if (Light.subtype > LST_SINGLE) { + ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); + if (LST_RGB <= Light.subtype) { + uint16_t hue; + uint8_t sat, bri; + light_state.getHSB(&hue, &sat, &bri); + sat = changeUIntScale(sat, 0, 255, 0, 100); + bri = changeUIntScale(bri, 0, 255, 0, 100); + + ResponseAppend_P(PSTR(",\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), hue,sat,bri); + } + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { + ResponseAppend_P(PSTR(",\"" D_CMND_WHITE "\":%d"), light_state.getDimmer(2)); + } + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), light_state.getCT()); + } + + ResponseAppend_P(PSTR(",\"" D_CMND_CHANNEL "\":[" )); + for (uint32_t i = 0; i < Light.subtype; i++) { + uint8_t channel_raw = Light.current_color[i]; + uint8_t channel = changeUIntScale(channel_raw,0,255,0,100); + + if ((0 == channel) && (channel_raw > 0)) { channel = 1; } + ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), channel); + } + ResponseAppend_P(PSTR("]")); + } + + if (append) { + if (Light.subtype >= LST_RGB) { + ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); + } + if (Light.max_scheme > LS_MAX) { + ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width); + } + ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), + GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); + } + } else { + for (uint32_t i = 0; i < Light.subtype; i++) { + GetPowerDevice(scommand, Light.device + i, sizeof(scommand), 1); + uint32_t light_power_masked = Light.power & (1 << i); + light_power_masked = light_power_masked ? 1 : 0; + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_CHANNEL "%d\":%d,"), scommand, GetStateText(light_power_masked), Light.device + i, + changeUIntScale(Light.current_color[i], 0, 255, 0, 100)); + } + ResponseAppend_P(PSTR("\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); + } + + if (!append) { + ResponseJsonEnd(); + } +} + +void LightPreparePower(power_t channels = 0xFFFFFFFF) { +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); +#endif + + if (Light.pwm_multi_channels) { + for (uint32_t i = 0; i < Light.subtype; i++) { + if (bitRead(channels, i)) { + + if ((Light.current_color[i]) && (!bitRead(Light.power, i))) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device + i, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else { + + if ((0 == Light.current_color[i]) && bitRead(Light.power, i)) { + ExecuteCommandPower(Light.device + i, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } + #ifdef USE_DOMOTICZ + DomoticzUpdatePowerState(Light.device + i); + #endif + } + } + } else { + if (light_controller.isCTRGBLinked()) { + if (light_state.getBri() && !(Light.power)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBri() && Light.power) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } else { + + if (channels & 1) { + if (light_state.getBriRGB() && !(Light.power & 1)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBriRGB() && (Light.power & 1)) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } + + if (channels & 2) { + if (light_state.getBriCT() && !(Light.power & 2)) { + if (!Settings.flag.not_power_linked) { + ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBriCT() && (Light.power & 2)) { + ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT); + } + } + } +#ifdef USE_DOMOTICZ + DomoticzUpdatePowerState(Light.device); +#endif + } + + if (Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } + +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); +#endif + Light.power = power >> (Light.device - 1); + LightState(0); +} + +void LightCycleColor(int8_t direction) +{ + if (Light.strip_timer_counter % (Settings.light_speed * 2)) { + return; + } + + if (0 == direction) { + if (Light.random == Light.wheel) { + Light.random = random(255); + + uint8_t my_dir = (Light.random < Light.wheel -128) ? 1 : + (Light.random < Light.wheel ) ? 0 : + (Light.random > Light.wheel +128) ? 0 : 1; + Light.random = (Light.random & 0xFE) | my_dir; + + + } + + direction = (Light.random &0x01) ? 1 : -1; + } + Light.wheel += direction; + uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); + + + + uint8_t sat; + light_state.getHSB(nullptr, &sat, nullptr); + light_state.setHS(hue, sat); + light_controller.calcLevels(Light.new_color); +} + +void LightSetPower(void) +{ + + Light.old_power = Light.power; + + uint32_t mask = 1; + if (Light.pwm_multi_channels) { + mask = (1 << Light.subtype) - 1; + } else if (!light_controller.isCTRGBLinked()) { + mask = 3; + } + uint32_t shift = Light.device - 1; + + + + + + Light.power = (XdrvMailbox.index & (mask << shift)) >> shift; + if (Light.wakeup_active) { + Light.wakeup_active--; + } +#ifdef DEBUG_LIGHT + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightSetPower XdrvMailbox.index=%d Light.old_power=%d Light.power=%d mask=%d shift=%d", + XdrvMailbox.index, Light.old_power, Light.power, mask, shift); +#endif + if (Light.power != Light.old_power) { + Light.update = true; + } + LightAnimate(); +} + + + + +void LightAnimate(void) +{ + uint16_t light_still_on = 0; + bool power_off = false; + + + light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); + Light.strip_timer_counter++; + + + + if (Light.power || Light.fade_running) { + if (Settings.sleep > PWM_MAX_SLEEP) { + sleep = PWM_MAX_SLEEP; + } else { + sleep = Settings.sleep; + } + } else { + sleep = Settings.sleep; + } + + if (!Light.power) { + Light.strip_timer_counter = 0; + if (Settings.light_scheme >= LS_MAX) { + power_off = true; + } + } else { + switch (Settings.light_scheme) { + case LS_POWER: + light_controller.calcLevels(Light.new_color); + break; + case LS_WAKEUP: + if (2 == Light.wakeup_active) { + Light.wakeup_active = 1; + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.new_color[i] = 0; + } + Light.wakeup_counter = 0; + Light.wakeup_dimmer = 0; + } + Light.wakeup_counter++; + if (Light.wakeup_counter > ((Settings.light_wakeup * STATES) / Settings.light_dimmer)) { + Light.wakeup_counter = 0; + Light.wakeup_dimmer++; + if (Light.wakeup_dimmer <= Settings.light_dimmer) { + light_state.setDimmer(Light.wakeup_dimmer); + light_controller.calcLevels(); + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.new_color[i] = Light.current_color[i]; + } + } else { + + + + + Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"")); + LightState(1); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); + XdrvRulesProcess(); + + Light.wakeup_active = 0; + Settings.light_scheme = LS_POWER; + } + } + break; + case LS_CYCLEUP: + LightCycleColor(1); + break; + case LS_CYCLEDN: + LightCycleColor(-1); + break; + case LS_RANDOM: + LightCycleColor(0); + break; + default: + XlgtCall(FUNC_SET_SCHEME); + } + } + + if ((Settings.light_scheme < LS_MAX) || power_off) { + + + LightApplyPower(Light.new_color, Light.power); + + + + + + + + if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { + Light.update = true; + } + if (Light.update) { +#ifdef USE_DEVICE_GROUPS + if (Light.power) LightSendDeviceGroupStatus(); +#endif + + uint16_t cur_col_10[LST_MAX]; + Light.update = false; + + + for (uint32_t i = 0; i < LST_MAX; i++) { + Light.last_color[i] = Light.new_color[i]; + + cur_col_10[i] = change8to10(Light.new_color[i]); + } + + if (Light.pwm_multi_channels) { + calcGammaMultiChannels(cur_col_10); + } else { + calcGammaBulbs(cur_col_10); + + + + if ((LST_RGBW <= Light.subtype) && (0 == Settings.rgbwwTable[4]) && (0 == cur_col_10[3]+cur_col_10[4])) { + uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); + for (uint32_t i=0; i<3; i++) { + + uint32_t adjust10 = change8to10(Settings.rgbwwTable[i]); + cur_col_10[i] = changeUIntScale(cur_col_10[i] - min_rgb_10, 0, 1023, 0, adjust10); + } + + + uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); + uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); + if (LST_RGBW == Light.subtype) { + + cur_col_10[3] = white_10; + } else { + + uint32_t ct = light_state.getCT10bits(); + cur_col_10[4] = changeUIntScale(ct, 0, 1023, 0, white_10); + cur_col_10[3] = white_10 - cur_col_10[4]; + } + } + } + + + if (0 != Settings.rgbwwTable[4]) { + for (uint32_t i = 0; i 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0; + } + + + uint16_t orig_col_10bits[LST_MAX]; + memcpy(orig_col_10bits, cur_col_10, sizeof(orig_col_10bits)); + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col_10[i] = orig_col_10bits[Light.color_remap[i]]; + } + + if (!Settings.light_fade || power_off || (!Light.fade_initialized)) { + + memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10)); + + LightSetOutputs(cur_col_10); + Light.fade_initialized = true; + } else { + if (Light.fade_running) { + + memcpy(Light.fade_start_10, Light.fade_cur_10, sizeof(Light.fade_start_10)); + } + memcpy(Light.fade_end_10, cur_col_10, sizeof(Light.fade_start_10)); + Light.fade_running = true; + Light.fade_duration = 0; + Light.fade_start = 0; + + } + } + if (Light.fade_running) { + if (LightApplyFade()) { + + + + LightSetOutputs(Light.fade_cur_10); + } + } + } +} + +bool isChannelGammaCorrected(uint32_t channel) { + if (!Settings.light_correction) { return false; } + if (channel >= Light.subtype) { return false; } + + if (PHILIPS == my_module_type) { + if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } + if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } + } + return true; +} + + +uint16_t fadeGamma(uint32_t channel, uint16_t v) { + if (isChannelGammaCorrected(channel)) { + return ledGamma_internal(v, gamma_table_fast); + } else { + return v; + } +} +uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg) { + if (isChannelGammaCorrected(channel)) { + return ledGammaReverse_internal(vg, gamma_table_fast); + } else { + return vg; + } +} + +bool LightApplyFade(void) { + static uint32_t last_millis = 0; + uint32_t now = millis(); + + if ((now - last_millis) <= 5) { + return false; + } + last_millis = now; + + + if (0 == Light.fade_duration) { + Light.fade_start = now; + + uint32_t distance = 0; + for (uint32_t i = 0; i < Light.subtype; i++) { + int32_t channel_distance = fadeGammaReverse(i, Light.fade_end_10[i]) - fadeGammaReverse(i, Light.fade_start_10[i]); + if (channel_distance < 0) { channel_distance = - channel_distance; } + if (channel_distance > distance) { distance = channel_distance; } + } + if (distance > 0) { + + + + Light.fade_duration = (distance * Settings.light_speed * 500) / 1023; + if (Settings.save_data) { + + uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; + + if (save_data_counter < delay_seconds) { + save_data_counter = delay_seconds; + } + } + } else { + + Light.fade_running = false; + } + } + + uint16_t fade_current = now - Light.fade_start; + if (fade_current <= Light.fade_duration) { + + for (uint32_t i = 0; i < Light.subtype; i++) { + Light.fade_cur_10[i] = fadeGamma(i, + changeUIntScale(fadeGammaReverse(i, fade_current), + 0, Light.fade_duration, + fadeGammaReverse(i, Light.fade_start_10[i]), + fadeGammaReverse(i, Light.fade_end_10[i]))); + + + + } + } else { + + + Light.fade_running = false; + Light.fade_start = 0; + Light.fade_duration = 0; + + memcpy(Light.fade_cur_10, Light.fade_end_10, sizeof(Light.fade_end_10)); + + memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10)); + } + return true; +} + + + +void LightApplyPower(uint8_t new_color[LST_MAX], power_t power) { + + if (Light.pwm_multi_channels) { + + for (uint32_t i = 0; i < LST_MAX; i++) { + if (0 == bitRead(power,i)) { + new_color[i] = 0; + } + } + + + + + + } else { + if (!light_controller.isCTRGBLinked()) { + + if (0 == (power & 1)) { + new_color[0] = new_color[1] = new_color[2] = 0; + } + if (0 == (power & 2)) { + new_color[3] = new_color[4] = 0; + } + } else if (!power) { + for (uint32_t i = 0; i < LST_MAX; i++) { + new_color[i] = 0; + } + } + } +} + +void LightSetOutputs(const uint16_t *cur_col_10) { + + if (light_type < LT_PWM6) { + for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { + if (pin[GPIO_PWM1 +i] < 99) { + + analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10[(i + Light.pwm_offset)] : cur_col_10[(i + Light.pwm_offset)]); + } + } + } + + + + + uint8_t cur_col[LST_MAX]; + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col[i] = change10to8(cur_col_10[i]); + } + + + uint8_t scale_col[3]; + uint32_t max = (cur_col[0] > cur_col[1] && cur_col[0] > cur_col[2]) ? cur_col[0] : (cur_col[1] > cur_col[2]) ? cur_col[1] : cur_col[2]; + for (uint32_t i = 0; i < 3; i++) { + scale_col[i] = (0 == max) ? 255 : (255 > max) ? changeUIntScale(cur_col[i], 0, max, 0, 255) : cur_col[i]; + } + + char *tmp_data = XdrvMailbox.data; + char *tmp_topic = XdrvMailbox.topic; + XdrvMailbox.data = (char*)cur_col; + XdrvMailbox.topic = (char*)scale_col; + if (XlgtCall(FUNC_SET_CHANNELS)) { } + else if (XdrvCall(FUNC_SET_CHANNELS)) { } + XdrvMailbox.data = tmp_data; + XdrvMailbox.topic = tmp_topic; +} + + +void calcGammaMultiChannels(uint16_t cur_col_10[5]) { + + if (Settings.light_correction) { + for (uint32_t i = 0; i < LST_MAX; i++) { + cur_col_10[i] = ledGamma10_10(cur_col_10[i]); + } + } +} + +void calcGammaBulbs(uint16_t cur_col_10[5]) { + + + + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + + uint32_t cw1 = Light.subtype - 1; + uint32_t cw0 = Light.subtype - 2; + uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; + uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; + + if (PHILIPS == my_module_type) { + + cur_col_10[cw1] = light_state.getCT10bits(); + + if (Settings.light_correction) { + cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); + } else { + cur_col_10[cw0] = white_bri10_1023; + } + } else if (Settings.light_correction) { + + if (white_bri10 <= 1031) { + + uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); + + cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); + cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); + } else { + cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); + cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); + } + } + } + + if (Settings.light_correction) { + + if (LST_RGB <= Light.subtype) { + for (uint32_t i = 0; i < 3; i++) { + cur_col_10[i] = ledGamma10_10(cur_col_10[i]); + } + } + + if ((LST_SINGLE == Light.subtype) || (LST_RGBW == Light.subtype)) { + cur_col_10[Light.subtype - 1] = ledGamma10_10(cur_col_10[Light.subtype - 1]); + } + } +} + +#ifdef USE_DEVICE_GROUPS +void LightSendDeviceGroupStatus() +{ + uint8_t channels[LST_MAX]; + light_state.getChannels(channels); + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme, DGR_ITEM_LIGHT_CHANNELS, channels, + DGR_ITEM_LIGHT_BRI, (power ? light_state.getBri() : 0)); +} + +void LightHandleDeviceGroupRequest() +{ + static bool send_state = false; + uint32_t value = XdrvMailbox.payload; + switch (XdrvMailbox.command_code) { + case DGR_ITEM_EOL: + LightAnimate(); + if (send_state && !(XdrvMailbox.index & DGR_FLAG_MORE_TO_COME)) { + light_controller.saveSettings(); + if (Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } + send_state = false; + } + break; + case DGR_ITEM_LIGHT_BRI: + if (light_state.getBri() != value) { + light_controller.changeBri(value); + send_state = true; + } + break; + case DGR_ITEM_LIGHT_SCHEME: + if (Settings.light_scheme != value) { + Settings.light_scheme = value; + send_state = true; + } + break; + case DGR_ITEM_LIGHT_CHANNELS: + light_controller.changeChannels((uint8_t *)XdrvMailbox.data); + send_state = true; + break; + case DGR_ITEM_LIGHT_FIXED_COLOR: + { + power_t save_power = Light.power; + if (value) { + bool save_decimal_text = Settings.flag.decimal_text; + char str[16]; + XdrvMailbox.index = 2; + XdrvMailbox.data_len = sprintf_P(str, PSTR("%u"), value); + XdrvMailbox.data = str; + CmndSupportColor(); + Settings.flag.decimal_text = save_decimal_text; + } + else { + Light.fixed_color_index = 0; + XdrvMailbox.index = 1; + XdrvMailbox.payload = light_state.BriToDimmer(light_state.getBri()); + CmndWhite(); + } + if (Light.power != save_power) { + XdrvMailbox.index = save_power; + LightSetPower(); + } + send_state = true; + } + break; + case DGR_ITEM_LIGHT_SPEED: + if (Settings.light_speed != value && value > 0 && value <= 40) { + Settings.light_speed = value; + send_state = true; + } + break; + case DGR_ITEM_STATUS: + SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, + DGR_ITEM_LIGHT_SPEED, Settings.light_speed); + LightSendDeviceGroupStatus(); + break; + } +} +#endif + + + + + +bool LightColorEntry(char *buffer, uint32_t buffer_length) +{ + char scolor[10]; + char *p; + char *str; + uint32_t entry_type = 0; + uint8_t value = Light.fixed_color_index; + + if (buffer[0] == '#') { + buffer++; + buffer_length--; + } + + if (Light.subtype >= LST_RGB) { + char option = (1 == buffer_length) ? buffer[0] : '\0'; + if (('+' == option) && (Light.fixed_color_index < MAX_FIXED_COLOR)) { + value++; + } + else if (('-' == option) && (Light.fixed_color_index > 1)) { + value--; + } else { + value = atoi(buffer); + } + } + + memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); + + while ((buffer_length > 0) && ('=' == buffer[buffer_length - 1])) { + buffer_length--; + memcpy(&Light.entry_color, &Light.current_color, sizeof(Light.entry_color)); + } + if (strstr(buffer, ",") != nullptr) { + int8_t i = 0; + for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) { + if (i < LST_MAX) { + Light.entry_color[i++] = atoi(str); + } + } + entry_type = 2; + } + else if (((2 * Light.subtype) == buffer_length) || (buffer_length > 3)) { + for (uint32_t i = 0; i < tmin((uint)(buffer_length / 2), sizeof(Light.entry_color)); i++) { + strlcpy(scolor, buffer + (i *2), 3); + Light.entry_color[i] = (uint8_t)strtol(scolor, &p, 16); + } + entry_type = 1; + } + else if ((Light.subtype >= LST_RGB) && (value > 0) && (value <= MAX_FIXED_COLOR)) { + Light.fixed_color_index = value; + memcpy_P(&Light.entry_color, &kFixedColor[value -1], 3); + entry_type = 1; + } + else if ((value > 199) && (value <= 199 + MAX_FIXED_COLD_WARM)) { + if (LST_RGBW == Light.subtype) { + memcpy_P(&Light.entry_color[3], &kFixedWhite[value -200], 1); + entry_type = 1; + } + else if (LST_COLDWARM == Light.subtype) { + memcpy_P(&Light.entry_color, &kFixedColdWarm[value -200], 2); + entry_type = 1; + } + else if (LST_RGBCW == Light.subtype) { + memcpy_P(&Light.entry_color[3], &kFixedColdWarm[value -200], 2); + entry_type = 1; + } + } + if (entry_type) { + Settings.flag.decimal_text = entry_type -1; + } + return (entry_type); +} + + + +void CmndSupportColor(void) +{ + bool valid_entry = false; + bool coldim = false; + + if (XdrvMailbox.data_len > 0) { + valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); + if (valid_entry) { + if (XdrvMailbox.index <= 2) { + uint32_t old_bri = light_state.getBri(); + + light_controller.changeChannels(Light.entry_color); + if (2 == XdrvMailbox.index) { + + light_controller.changeBri(old_bri); + } + + Settings.light_scheme = 0; + coldim = true; + } else { + for (uint32_t i = 0; i < LST_RGB; i++) { + Settings.ws_color[XdrvMailbox.index -3][i] = Light.entry_color[i]; + } + } + } + } + char scolor[LIGHT_COLOR_SIZE]; + if (!valid_entry && (XdrvMailbox.index <= 2)) { + ResponseCmndChar(LightGetColor(scolor)); + } + if (XdrvMailbox.index >= 3) { + scolor[0] = '\0'; + for (uint32_t i = 0; i < LST_RGB; i++) { + if (Settings.flag.decimal_text) { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.ws_color[XdrvMailbox.index -3][i]); + } else { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]); + } + } + ResponseCmndIdxChar(scolor); + } + if (coldim) { + LightPreparePower(); + } +} + +void CmndColor(void) +{ + + + + + + + + if ((Light.subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { + CmndSupportColor(); + } +} + +void CmndWhite(void) +{ + + + if (Light.pwm_multi_channels) { return; } + if ( ((Light.subtype >= LST_RGBW) || (LST_COLDWARM == Light.subtype)) && (XdrvMailbox.index == 1)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + light_controller.changeDimmer(XdrvMailbox.payload, 2); + LightPreparePower(2); + } else { + ResponseCmndNumber(light_state.getDimmer(2)); + } + } +} + +void CmndChannel(void) +{ + + + + + if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { + uint32_t light_index = XdrvMailbox.index - Light.device; + power_t coldim = 0; + + + if (1 == XdrvMailbox.data_len) { + uint8_t channel = changeUIntScale(Light.current_color[light_index],0,255,0,100); + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; + } else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (channel < 11) ? 1 : channel - 10; + } + } + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Light.current_color[light_index] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); + if (Light.pwm_multi_channels) { + coldim = 1 << light_index; + } else { + if (light_controller.isCTRGBLinked()) { + + if ((light_index < 3) && (light_controller.isCTRGBLinked())) { + Light.current_color[3] = Light.current_color[4] = 0; + } else { + Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; + } + coldim = 1; + } else { + if (light_index < 3) { coldim = 1; } + else { coldim = 2; } + } + } + light_controller.changeChannels(Light.current_color); + } + ResponseCmndIdxNumber(changeUIntScale(Light.current_color[light_index],0,255,0,100)); + if (coldim) { + LightPreparePower(coldim); + } + } +} + +void CmndHsbColor(void) +{ + + + + + + + + if (Light.subtype >= LST_RGB) { + if (XdrvMailbox.data_len > 0) { + uint16_t c_hue; + uint8_t c_sat; + light_state.getHSB(&c_hue, &c_sat, nullptr); + uint32_t HSB[3]; + HSB[0] = c_hue; + HSB[1] = c_sat; + HSB[2] = light_state.getBriRGB(); + if ((2 == XdrvMailbox.index) || (3 == XdrvMailbox.index)) { + if ((uint32_t)XdrvMailbox.payload > 100) { XdrvMailbox.payload = 100; } + HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); + } else { + uint32_t paramcount = ParseParameters(3, HSB); + if (HSB[0] > 360) { HSB[0] = 360; } + for (uint32_t i = 1; i < paramcount; i++) { + if (HSB[i] > 100) { HSB[i] == 100; } + HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); + } + } + light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); + LightPreparePower(1); + } else { + LightState(0); + } + } +} + +void CmndScheme(void) +{ + + + + + + if (Light.subtype >= LST_RGB) { + uint32_t max_scheme = Light.max_scheme; + + if (1 == XdrvMailbox.data_len) { + if (('+' == XdrvMailbox.data[0]) && (Settings.light_scheme < max_scheme)) { + XdrvMailbox.payload = Settings.light_scheme + ((0 == Settings.light_scheme) ? 2 : 1); + } + else if (('-' == XdrvMailbox.data[0]) && (Settings.light_scheme > 0)) { + XdrvMailbox.payload = Settings.light_scheme - ((2 == Settings.light_scheme) ? 2 : 1); + } + } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= max_scheme)) { + uint32_t parm[2]; + if (ParseParameters(2, parm) > 1) { + Light.wheel = parm[1]; + } + Settings.light_scheme = XdrvMailbox.payload; +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); +#endif + if (LS_WAKEUP == Settings.light_scheme) { + Light.wakeup_active = 3; + } + LightPowerOn(); + Light.strip_timer_counter = 0; + + if (Settings.flag3.hass_tele_on_power) { + MqttPublishTeleState(); + } + } + ResponseCmndNumber(Settings.light_scheme); + } +} + +void CmndWakeup(void) +{ + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + light_controller.changeDimmer(XdrvMailbox.payload); + } + Light.wakeup_active = 3; + Settings.light_scheme = LS_WAKEUP; + LightPowerOn(); + ResponseCmndChar(D_JSON_STARTED); +} + +void CmndColorTemperature(void) +{ + + + + + if (Light.pwm_multi_channels) { return; } + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { + uint32_t ct = light_state.getCT(); + if (1 == XdrvMailbox.data_len) { + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (ct > (CT_MAX-34)) ? CT_MAX : ct + 34; + } + else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (ct < (CT_MIN+34)) ? CT_MIN : ct - 34; + } + } + if ((XdrvMailbox.payload >= CT_MIN) && (XdrvMailbox.payload <= CT_MAX)) { + light_controller.changeCTB(XdrvMailbox.payload, light_state.getBriCT()); + LightPreparePower(2); + } else { + ResponseCmndNumber(ct); + } + } +} + +void CmndDimmer(void) +{ + + + + + + + uint32_t dimmer; + if (XdrvMailbox.index > 2) { XdrvMailbox.index = 1; } + + if ((light_controller.isCTRGBLinked()) || (0 == XdrvMailbox.index)) { + dimmer = light_state.getDimmer(); + } else { + dimmer = light_state.getDimmer(XdrvMailbox.index); + } + + if (1 == XdrvMailbox.data_len) { + if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (dimmer > 89) ? 100 : dimmer + 10; + } else if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (dimmer < 11) ? 1 : dimmer - 10; + } + } + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + if (light_controller.isCTRGBLinked()) { + + light_controller.changeDimmer(XdrvMailbox.payload); + LightPreparePower(); + } else { + if (0 != XdrvMailbox.index) { + light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); + LightPreparePower(1 << (XdrvMailbox.index - 1)); + } else { + + light_controller.changeDimmer(XdrvMailbox.payload, 1); + light_controller.changeDimmer(XdrvMailbox.payload, 2); + LightPreparePower(); + } + } + Light.update = true; + } else { + ResponseCmndNumber(dimmer); + } +} + +void CmndDimmerRange(void) +{ + + + if (XdrvMailbox.data_len > 0) { + uint32_t parm[2]; + parm[0] = Settings.dimmer_hw_min; + parm[1] = Settings.dimmer_hw_max; + ParseParameters(2, parm); + if (parm[0] < parm[1]) { + Settings.dimmer_hw_min = parm[0]; + Settings.dimmer_hw_max = parm[1]; + } else { + Settings.dimmer_hw_min = parm[1]; + Settings.dimmer_hw_max = parm[0]; + } + restart_flag = 2; + } + Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); +} + +void CmndLedTable(void) +{ + + + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + Settings.light_correction = XdrvMailbox.payload; + break; + case 2: + Settings.light_correction ^= 1; + break; + } + Light.update = true; + } + ResponseCmndStateText(Settings.light_correction); +} + +void CmndRgbwwTable(void) +{ + + + if ((XdrvMailbox.data_len > 0)) { + uint32_t parm[LST_RGBCW -1]; + uint32_t parmcount = ParseParameters(LST_RGBCW, parm); + for (uint32_t i = 0; i < parmcount; i++) { + Settings.rgbwwTable[i] = parm[i]; + } + Light.update = true; + } + char scolor[LIGHT_COLOR_SIZE]; + scolor[0] = '\0'; + for (uint32_t i = 0; i < LST_RGBCW; i++) { + snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); + } + ResponseCmndChar(scolor); +} + +void CmndFade(void) +{ + + + + + switch (XdrvMailbox.payload) { + case 0: + case 1: + Settings.light_fade = XdrvMailbox.payload; + break; + case 2: + Settings.light_fade ^= 1; + break; + } +#ifdef USE_DEVICE_GROUPS + if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade); +#endif + if (!Settings.light_fade) { Light.fade_running = false; } + ResponseCmndStateText(Settings.light_fade); +} + +void CmndSpeed(void) +{ + + + + + if (1 == XdrvMailbox.data_len) { + if (('+' == XdrvMailbox.data[0]) && (Settings.light_speed > 1)) { + XdrvMailbox.payload = Settings.light_speed - 1; + } + else if (('-' == XdrvMailbox.data[0]) && (Settings.light_speed < 40)) { + XdrvMailbox.payload = Settings.light_speed + 1; + } + } + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 40)) { + Settings.light_speed = XdrvMailbox.payload; +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SPEED, Settings.light_speed); +#endif + } + ResponseCmndNumber(Settings.light_speed); +} + +void CmndWakeupDuration(void) +{ + + + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { + Settings.light_wakeup = XdrvMailbox.payload; + Light.wakeup_active = 0; + } + ResponseCmndNumber(Settings.light_wakeup); +} + +void CmndUndocA(void) +{ + + char scolor[LIGHT_COLOR_SIZE]; + LightGetColor(scolor, true); + scolor[6] = '\0'; + Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); + MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); + mqtt_data[0] = '\0'; +} + + + + + +bool Xdrv04(uint8_t function) +{ + bool result = false; + + if (FUNC_MODULE_INIT == function) { + return LightModuleInit(); + } + else if (light_type) { + switch (function) { + case FUNC_SERIAL: + result = XlgtCall(FUNC_SERIAL); + break; + case FUNC_LOOP: + if (Light.fade_running) { + if (LightApplyFade()) { + LightSetOutputs(Light.fade_cur_10); + } + } + break; + case FUNC_EVERY_50_MSECOND: + LightAnimate(); + break; +#ifdef USE_DEVICE_GROUPS + case FUNC_DEVICE_GROUP_REQUEST: + LightHandleDeviceGroupRequest(); + break; +#endif + case FUNC_SET_POWER: + LightSetPower(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kLightCommands, LightCommand); + if (!result) { + result = XlgtCall(FUNC_COMMAND); + } + break; + case FUNC_PRE_INIT: + LightInit(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_05_irremote.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_05_irremote.ino" +#if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) + + + + +#define XDRV_05 5 + +#include + +enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND }; + +const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; + + +void (* const IrRemoteCommand[])(void) PROGMEM = { + &CmndIrSend }; + + +static const uint8_t MAX_STANDARD_IR = NEC; +const char kIrRemoteProtocols[] PROGMEM = "UNKNOWN|RC5|RC6|NEC"; + + + + + +#include + +IRsend *irsend = nullptr; +bool irsend_active = false; + +void IrSendInit(void) +{ + irsend = new IRsend(pin[GPIO_IRSEND]); + irsend->begin(); +} + +#ifdef USE_IR_RECEIVE + + + + +const bool IR_RCV_SAVE_BUFFER = false; +const uint32_t IR_TIME_AVOID_DUPLICATE = 500; + +#include + +IRrecv *irrecv = nullptr; + +unsigned long ir_lasttime = 0; + +void IrReceiveUpdateThreshold(void) +{ + if (irrecv != nullptr) { + if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + } +} + +void IrReceiveInit(void) +{ + + irrecv = new IRrecv(pin[GPIO_IRRECV], IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER); + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + irrecv->enableIRIn(); + + +} + +void IrReceiveCheck(void) +{ + char sirtype[8]; + int8_t iridx = 0; + + decode_results results; + + if (irrecv->decode(&results)) { + char hvalue[65]; + + iridx = results.decode_type; + if ((iridx < 0) || (iridx > MAX_STANDARD_IR)) { iridx = 0; } + + if (iridx) { + if (results.bits > 64) { + + uint32_t digits2 = results.bits / 8; + if (results.bits % 8) { digits2++; } + ToHex_P((unsigned char*)results.state, digits2, hvalue, sizeof(hvalue)); + } else { + Uint64toHex(results.value, hvalue, results.bits); + } + } else { + Uint64toHex(results.value, hvalue, 32); + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%s, Decode %d"), + irsend_active, results.rawlen, results.overflow, results.bits, hvalue, results.decode_type); + + unsigned long now = millis(); + + if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { + ir_lasttime = now; + + char svalue[64]; + if (Settings.flag.ir_receive_decimal) { + ulltoa(results.value, svalue, 10); + } else { + snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue); + } + ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d"), + GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits); + if (iridx) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_DATA "\":%s"), svalue); + } else { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_HASH "\":%s"), svalue); + } + + if (Settings.flag3.receive_raw) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); + uint16_t i; + for (i = 1; i < results.rawlen; i++) { + if (i > 1) { ResponseAppend_P(PSTR(",")); } + uint32_t usecs; + for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { + ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); + } + ResponseAppend_P(PSTR("%d"), usecs); + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } + } + uint16_t extended_length = results.rawlen - 1; + for (uint32_t j = 0; j < results.rawlen - 1; j++) { + uint32_t usecs = results.rawbuf[j] * kRawTick; + + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + if (iridx) { + unsigned long value = results.value | (iridx << 28); + DomoticzSensor(DZ_COUNT, value); + } +#endif + } + + irrecv->resume(); + } +} +#endif + + + + + +uint32_t IrRemoteCmndIrSendJson(void) +{ + + + + + char dataBufUc[XdrvMailbox.data_len + 1]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { + return IE_INVALID_JSON; + } + + StaticJsonBuffer<140> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (!root.success()) { + return IE_INVALID_JSON; + } + + + + char parm_uc[10]; + const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; + uint16_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; + uint64_t data = strtoull(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); + uint16_t repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT))]; + + if (XdrvMailbox.index > repeat + 1) { + repeat = XdrvMailbox.index - 1; + } + if (!(protocol && bits)) { + return IE_SYNTAX_IRSEND; + } + + char protocol_text[20]; + int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); + + char dvalue[64]; + char hvalue[20]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %s (0x%s), repeat %d, protocol_code %d"), + protocol_text, protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat, protocol_code); + + irsend_active = true; + switch (protocol_code) { +#ifdef USE_IR_SEND_RC5 + case RC5: + irsend->sendRC5(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_RC6 + case RC6: + irsend->sendRC6(data, bits, repeat); break; +#endif +#ifdef USE_IR_SEND_NEC + case NEC: + irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits, repeat); break; +#endif + default: + irsend_active = false; + ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); + } + + return IE_NO_ERROR; +} + +void CmndIrSend(void) +{ + uint8_t error = IE_SYNTAX_IRSEND; + + if (XdrvMailbox.data_len) { + + if (strstr(XdrvMailbox.data, "{") == nullptr) { + error = IE_INVALID_JSON; + } else { + error = IrRemoteCmndIrSendJson(); + } + } + IrRemoteCmndResponse(error); +} + +void IrRemoteCmndResponse(uint32_t error) +{ + switch (error) { + case IE_INVALID_RAWDATA: + ResponseCmndChar(D_JSON_INVALID_RAWDATA); + break; + case IE_INVALID_JSON: + ResponseCmndChar(D_JSON_INVALID_JSON); + break; + case IE_SYNTAX_IRSEND: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + break; + default: + ResponseCmndDone(); + } +} + + + + + +bool Xdrv05(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { + switch (function) { + case FUNC_PRE_INIT: + if (pin[GPIO_IRSEND] < 99) { + IrSendInit(); + } +#ifdef USE_IR_RECEIVE + if (pin[GPIO_IRRECV] < 99) { + IrReceiveInit(); + } +#endif + break; + case FUNC_EVERY_50_MSECOND: +#ifdef USE_IR_RECEIVE + if (pin[GPIO_IRRECV] < 99) { + IrReceiveCheck(); + } +#endif + irsend_active = false; + break; + case FUNC_COMMAND: + if (pin[GPIO_IRSEND] < 99) { + result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); + } + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_05_irremote_full.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_05_irremote_full.ino" +#ifdef USE_IR_REMOTE_FULL + + + + +#define XDRV_05 5 + +#include +#include +#include +#include +#include + +enum IrErrors { IE_RESPONSE_PROVIDED, IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC, + IE_UNSUPPORTED_HVAC, IE_UNSUPPORTED_PROTOCOL }; + +const char kIrRemoteCommands[] PROGMEM = "|" + D_CMND_IRHVAC "|" D_CMND_IRSEND ; + +void (* const IrRemoteCommand[])(void) PROGMEM = { + &CmndIrHvac, &CmndIrSend }; + + + + + +IRsend *irsend = nullptr; +bool irsend_active = false; + +void IrSendInit(void) +{ + irsend = new IRsend(pin[GPIO_IRSEND]); + irsend->begin(); +} + + + +uint8_t reverseBitsInByte(uint8_t b) { + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; +} + + +uint64_t reverseBitsInBytes64(uint64_t b) { + union { + uint8_t b[8]; + uint64_t i; + } a; + a.i = b; + for (uint32_t i=0; i<8; i++) { + a.b[i] = reverseBitsInByte(a.b[i]); + } + return a.i; +} + + + + + +const bool IR_FULL_RCV_SAVE_BUFFER = false; +const uint32_t IR_TIME_AVOID_DUPLICATE = 500; + + + + +const uint16_t IR_FULL_BUFFER_SIZE = 1024; + + + +const uint8_t IR__FULL_RCV_TIMEOUT = 50; + +IRrecv *irrecv = nullptr; + +unsigned long ir_lasttime = 0; + +void IrReceiveUpdateThreshold(void) +{ + if (irrecv != nullptr) { + if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + } +} + +void IrReceiveInit(void) +{ + + irrecv = new IRrecv(pin[GPIO_IRRECV], IR_FULL_BUFFER_SIZE, IR__FULL_RCV_TIMEOUT, IR_FULL_RCV_SAVE_BUFFER); + irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); + irrecv->enableIRIn(); +} + +String sendACJsonState(const stdAc::state_t &state) { + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + json[D_JSON_IRHVAC_VENDOR] = typeToString(state.protocol); + json[D_JSON_IRHVAC_MODEL] = state.model; + json[D_JSON_IRHVAC_POWER] = IRac::boolToString(state.power); + json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(state.mode); + + if (state.mode == stdAc::opmode_t::kOff || !state.power) { + json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff); + json[D_JSON_IRHVAC_POWER] = IRac::boolToString(false); + } + json[D_JSON_IRHVAC_CELSIUS] = IRac::boolToString(state.celsius); + if (floorf(state.degrees) == state.degrees) { + json[D_JSON_IRHVAC_TEMP] = floorf(state.degrees); + } else { + json[D_JSON_IRHVAC_TEMP] = RawJson(String(state.degrees, 1)); + } + json[D_JSON_IRHVAC_FANSPEED] = IRac::fanspeedToString(state.fanspeed); + json[D_JSON_IRHVAC_SWINGV] = IRac::swingvToString(state.swingv); + json[D_JSON_IRHVAC_SWINGH] = IRac::swinghToString(state.swingh); + json[D_JSON_IRHVAC_QUIET] = IRac::boolToString(state.quiet); + json[D_JSON_IRHVAC_TURBO] = IRac::boolToString(state.turbo); + json[D_JSON_IRHVAC_ECONO] = IRac::boolToString(state.econo); + json[D_JSON_IRHVAC_LIGHT] = IRac::boolToString(state.light); + json[D_JSON_IRHVAC_FILTER] = IRac::boolToString(state.filter); + json[D_JSON_IRHVAC_CLEAN] = IRac::boolToString(state.clean); + json[D_JSON_IRHVAC_BEEP] = IRac::boolToString(state.beep); + json[D_JSON_IRHVAC_SLEEP] = state.sleep; + + String payload = ""; + payload.reserve(200); + json.printTo(payload); + return payload; +} + +String sendIRJsonState(const struct decode_results &results) { + String json("{"); + json += "\"" D_JSON_IR_PROTOCOL "\":\""; + json += typeToString(results.decode_type); + json += "\",\"" D_JSON_IR_BITS "\":"; + json += results.bits; + + if (hasACState(results.decode_type)) { + json += ",\"" D_JSON_IR_DATA "\":\"0x"; + json += resultToHexidecimal(&results); + json += "\""; + } else { + if (UNKNOWN != results.decode_type) { + json += ",\"" D_JSON_IR_DATA "\":"; + } else { + json += ",\"" D_JSON_IR_HASH "\":"; + } + if (Settings.flag.ir_receive_decimal) { + char svalue[32]; + ulltoa(results.value, svalue, 10); + json += svalue; + } else { + char hvalue[64]; + if (UNKNOWN != results.decode_type) { + Uint64toHex(results.value, hvalue, results.bits); + json += "\"0x"; + json += hvalue; + json += "\",\"" D_JSON_IR_DATALSB "\":\"0x"; + Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); + json += hvalue; + json += "\""; + } else { + Uint64toHex(results.value, hvalue, 32); + json += "\"0x"; + json += hvalue; + json += "\""; + } + } + } + json += ",\"" D_JSON_IR_REPEAT "\":"; + json += results.repeat; + + stdAc::state_t ac_result; + if (IRAcUtils::decodeToState(&results, &ac_result, nullptr)) { + + json += ",\"" D_CMND_IRHVAC "\":"; + json += sendACJsonState(ac_result); + } + + return json; +} + +void IrReceiveCheck(void) +{ + decode_results results; + + if (irrecv->decode(&results)) { + uint32_t now = millis(); + + + if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { + ir_lasttime = now; + Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); + + if (Settings.flag3.receive_raw) { + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); + uint16_t i; + for (i = 1; i < results.rawlen; i++) { + if (i > 1) { ResponseAppend_P(PSTR(",")); } + uint32_t usecs; + for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { + ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); + } + ResponseAppend_P(PSTR("%d"), usecs); + if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } + } + uint16_t extended_length = results.rawlen - 1; + for (uint32_t j = 0; j < results.rawlen - 1; j++) { + uint32_t usecs = results.rawbuf[j] * kRawTick; + + extended_length += (usecs / (UINT16_MAX + 1)) * 2; + } + ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); + } + + ResponseJsonEndEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); + + XdrvRulesProcess(); + } + + irrecv->resume(); + } +} + + + + + + + +String listSupportedProtocols(bool hvac) { + String l(""); + bool first = true; + for (uint32_t i = UNUSED + 1; i <= kLastDecodeType; i++) { + bool found = false; + if (hvac) { + found = IRac::isProtocolSupported((decode_type_t)i); + } else { + found = (IRsend::defaultBits((decode_type_t)i) > 0) && (!IRac::isProtocolSupported((decode_type_t)i)); + } + if (found) { + if (first) { + first = false; + } else { + l += "|"; + } + l += typeToString((decode_type_t)i); + } + } + return l; +} + + +const stdAc::fanspeed_t IrHvacFanSpeed[] PROGMEM = { stdAc::fanspeed_t::kAuto, + stdAc::fanspeed_t::kMin, stdAc::fanspeed_t::kLow,stdAc::fanspeed_t::kMedium, + stdAc::fanspeed_t::kHigh, stdAc::fanspeed_t::kMax }; + +uint32_t IrRemoteCmndIrHvacJson(void) +{ + stdAc::state_t state, prev; + char parm_uc[12]; + + + char dataBufUc[XdrvMailbox.data_len + 1]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } + + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(dataBufUc); + if (!json.success()) { return IE_INVALID_JSON; } + + + state.protocol = decode_type_t::UNKNOWN; + state.model = 1; + state.mode = stdAc::opmode_t::kAuto; + state.power = false; + state.celsius = true; + state.degrees = 21.0f; + state.fanspeed = stdAc::fanspeed_t::kMedium; + state.swingv = stdAc::swingv_t::kOff; + state.swingh = stdAc::swingh_t::kOff; + state.light = false; + state.beep = false; + state.econo = false; + state.filter = false; + state.turbo = false; + state.quiet = false; + state.sleep = -1; + state.clean = false; + state.clock = -1; + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); + if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); + if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } + if (decode_type_t::UNKNOWN == state.protocol) { return IE_UNSUPPORTED_HVAC; } + if (!IRac::isProtocolSupported(state.protocol)) { return IE_UNSUPPORTED_HVAC; } + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED)); + if (json.containsKey(parm_uc)) { + uint32_t fan_speed = json[parm_uc]; + if ((fan_speed >= 1) && (fan_speed <= 5)) { + state.fanspeed = (stdAc::fanspeed_t) pgm_read_byte(&IrHvacFanSpeed[fan_speed]); + } else { + state.fanspeed = IRac::strToFanspeed(json[parm_uc]); + } + } + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODEL)); + if (json.containsKey(parm_uc)) { state.model = IRac::strToModel(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE)); + if (json.containsKey(parm_uc)) { state.mode = IRac::strToOpmode(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGV)); + if (json.containsKey(parm_uc)) { state.swingv = IRac::strToSwingV(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGH)); + if (json.containsKey(parm_uc)) { state.swingh = IRac::strToSwingH(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TEMP)); + if (json.containsKey(parm_uc)) { state.degrees = json[parm_uc]; } + + + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER)); + if (json.containsKey(parm_uc)) { state.power = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CELSIUS)); + if (json.containsKey(parm_uc)) { state.celsius = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_LIGHT)); + if (json.containsKey(parm_uc)) { state.light = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_BEEP)); + if (json.containsKey(parm_uc)) { state.beep = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_ECONO)); + if (json.containsKey(parm_uc)) { state.econo = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FILTER)); + if (json.containsKey(parm_uc)) { state.filter = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TURBO)); + if (json.containsKey(parm_uc)) { state.turbo = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_QUIET)); + if (json.containsKey(parm_uc)) { state.quiet = IRac::strToBool(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CLEAN)); + if (json.containsKey(parm_uc)) { state.clean = IRac::strToBool(json[parm_uc]); } + + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SLEEP)); + if (json[parm_uc]) { state.sleep = json[parm_uc]; } + + + IRac ac(pin[GPIO_IRSEND]); + bool success = ac.sendAc(state, &prev); + if (!success) { return IE_SYNTAX_IRHVAC; } + + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":%s}"), sendACJsonState(state).c_str()); + return IE_RESPONSE_PROVIDED; +} + +void CmndIrHvac(void) +{ + uint8_t error = IE_SYNTAX_IRHVAC; + + if (XdrvMailbox.data_len) { + error = IrRemoteCmndIrHvacJson(); + } + if (error != IE_RESPONSE_PROVIDED) { IrRemoteCmndResponse(error); } +} + + + + + +uint32_t IrRemoteCmndIrSendJson(void) +{ + char parm_uc[12]; + + + + char dataBufUc[XdrvMailbox.data_len + 1]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } + + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(dataBufUc); + if (!json.success()) { return IE_INVALID_JSON; } + + + + decode_type_t protocol = decode_type_t::UNKNOWN; + uint16_t bits = 0; + uint64_t data; + uint8_t repeat = 0; + + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); + if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } + UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); + if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } + if (decode_type_t::UNKNOWN == protocol) { return IE_UNSUPPORTED_PROTOCOL; } + + UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS)); + if (json.containsKey(parm_uc)) { bits = json[parm_uc]; } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT)); + if (json.containsKey(parm_uc)) { repeat = json[parm_uc]; } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATALSB)); + if (json.containsKey(parm_uc)) { data = reverseBitsInBytes64(strtoull(json[parm_uc], nullptr, 0)); } + UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA)); + if (json.containsKey(parm_uc)) { data = strtoull(json[parm_uc], nullptr, 0); } + if (0 == bits) { return IE_SYNTAX_IRSEND; } + + + if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; } + + char dvalue[32]; + char hvalue[32]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data 0x%s (%s), repeat %d"), + protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat); + + irsend_active = true; + bool success = irsend->send(protocol, data, bits, repeat); + + if (!success) { + irsend_active = false; + ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); + } + return IE_NO_ERROR; +} + +uint32_t IrRemoteCmndIrSendRaw(void) +{ + + + + + + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + if (p == nullptr) { + return IE_INVALID_RAWDATA; + } + + + uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; + + uint16_t freq = atoi(str); + if (!freq && (*str != '0')) { + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (count < 2) { + return IE_INVALID_RAWDATA; + } + + uint16_t parm[count]; + for (uint32_t i = 0; i < count; i++) { + parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + if (!parm[i]) { + if (!i) { + parm[0] = 38000; + } else { + return IE_INVALID_RAWDATA; + } + } + } + + uint16_t i = 0; + if (count < 4) { + + uint16_t mark = parm[1] *2; + if (3 == count) { + if (parm[2] < parm[1]) { + + mark = parm[1] * parm[2]; + } else { + + mark = parm[2]; + } + } + uint16_t raw_array[strlen(p)]; + for (; *p; *p++) { + if (*p == '0') { + raw_array[i++] = parm[1]; + } + else if (*p == '1') { + raw_array[i++] = mark; + } + } + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, i, parm[0]); + if (r < repeat) { + irsend->space(40000); + } + } + } + else if (6 == count) { + + uint16_t raw_array[strlen(p)*2+3]; + raw_array[i++] = parm[1]; + raw_array[i++] = parm[2]; + uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; + uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; + for (; *p; *p++) { + if (*p == '0') { + raw_array[i++] = parm[3]; + raw_array[i++] = parm[4]; + } + else if (*p == '1') { + raw_array[i++] = parm[3]; + raw_array[i++] = parm[5]; + } + } + raw_array[i++] = parm[3]; + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, i, parm[0]); + if (r < repeat) { + irsend->space(inter_message); + } + } + } + else { + return IE_INVALID_RAWDATA; + } + } else { + if (!freq) { freq = 38000; } + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (0 == count) { + return IE_INVALID_RAWDATA; + } + + + count++; + if (count < 200) { + uint16_t raw_array[count]; + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + } + + + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + } else { + uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); + if (raw_array == nullptr) { + return IE_INVALID_RAWDATA; + } + + for (uint32_t i = 0; i < count; i++) { + raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); + } + + + + irsend_active = true; + for (uint32_t r = 0; r <= repeat; r++) { + irsend->sendRaw(raw_array, count, freq); + } + free(raw_array); + } + } + + return IE_NO_ERROR; +} + +void CmndIrSend(void) +{ + uint8_t error = IE_SYNTAX_IRSEND; + + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, "{") == nullptr) { + error = IrRemoteCmndIrSendRaw(); + } else { + error = IrRemoteCmndIrSendJson(); + } + } + IrRemoteCmndResponse(error); +} + +void IrRemoteCmndResponse(uint32_t error) +{ + switch (error) { + case IE_INVALID_RAWDATA: + ResponseCmndChar(D_JSON_INVALID_RAWDATA); + break; + case IE_INVALID_JSON: + ResponseCmndChar(D_JSON_INVALID_JSON); + break; + case IE_SYNTAX_IRSEND: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + break; + case IE_SYNTAX_IRHVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + break; + case IE_UNSUPPORTED_HVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR " (%s)\"}"), listSupportedProtocols(true).c_str()); + break; + case IE_UNSUPPORTED_PROTOCOL: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_PROTOCOL " (%s)\"}"), listSupportedProtocols(false).c_str()); + break; + default: + ResponseCmndDone(); + } +} + + + + + +bool Xdrv05(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { + switch (function) { + case FUNC_PRE_INIT: + if (pin[GPIO_IRSEND] < 99) { + IrSendInit(); + } + if (pin[GPIO_IRRECV] < 99) { + IrReceiveInit(); + } + break; + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_IRRECV] < 99) { + IrReceiveCheck(); + } + irsend_active = false; + break; + case FUNC_COMMAND: + if (pin[GPIO_IRSEND] < 99) { + result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); + } + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_06_snfbridge.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_06_snfbridge.ino" +#ifdef USE_SONOFF_RF + + + + +#define XDRV_06 6 + +const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; + +enum SonoffBridgeCommands { + CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE }; + +const char kSonoffBridgeCommands[] PROGMEM = "|" + D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY "|" D_CMND_RFRAW; + +void (* const SonoffBridgeCommand[])(void) PROGMEM = { + &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfKey, &CmndRfRaw }; + +struct SONOFFBRIDGE { + uint32_t last_received_id = 0; + uint32_t last_send_code = 0; + uint32_t last_time = 0; + uint32_t last_learn_time = 0; + uint8_t receive_flag = 0; + uint8_t receive_raw_flag = 0; + uint8_t learn_key = 1; + uint8_t learn_active = 0; + uint8_t expected_bytes = 0; +} SnfBridge; + +#ifdef USE_RF_FLASH + + + + + + + +#include "ihx.h" +#include "c2.h" + +const ssize_t RF_RECORD_NO_START_FOUND = -1; +const ssize_t RF_RECORD_NO_END_FOUND = -2; + +ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) +{ + for (size_t i = 0; i < size; i++) { + if (buf[i] == ':') { + return i; + } + } + return RF_RECORD_NO_START_FOUND; +} + +ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size) +{ + for (size_t i = 0; i < size; i++) { + if (buf[i] == '\n') { + return i; + } + } + return RF_RECORD_NO_END_FOUND; +} + +ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len) +{ + ssize_t record_start; + ssize_t record_end; + ssize_t glue_record_sz; + uint8_t *glue_buf; + ssize_t result; + + if (remnant_data[0] != ':') { return -8; } + + + record_end = rf_find_hex_record_end(new_data, new_data_len); + record_start = rf_find_hex_record_start(new_data, new_data_len); + + + + + if ((record_start != RF_RECORD_NO_START_FOUND) && (record_start < record_end)) { + return -8; + } + + glue_record_sz = strlen((const char *) remnant_data) + record_end; + + glue_buf = (uint8_t *) malloc(glue_record_sz); + if (glue_buf == nullptr) { return -2; } + + + memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); + memcpy(glue_buf + strlen((const char *) remnant_data), new_data, record_end); + + result = rf_decode_and_write(glue_buf, glue_record_sz); + free(glue_buf); + return result; +} + +ssize_t rf_decode_and_write(uint8_t *record, size_t size) +{ + uint8_t err = ihx_decode(record, size); + if (err != IHX_SUCCESS) { return -13; } + + ihx_t *h = (ihx_t *) record; + if (h->record_type == IHX_RT_DATA) { + int retries = 5; + uint16_t address = h->address_high * 0x100 + h->address_low; + + do { + err = c2_programming_init(); + err = c2_block_write(address, h->data, h->len); + } while (err != C2_SUCCESS && retries--); + } else if (h->record_type == IHX_RT_END_OF_FILE) { + + err = c2_reset(); + } + + if (err != C2_SUCCESS) { return -12; } + + return 0; +} + +ssize_t rf_search_and_write(uint8_t *buf, size_t size) +{ + + ssize_t rec_end; + ssize_t rec_start; + ssize_t err; + + for (size_t i = 0; i < size; i++) { + + rec_start = rf_find_hex_record_start(buf + i, size - i); + if (rec_start == RF_RECORD_NO_START_FOUND) { + + return -8; + } + + + rec_start += i; + rec_end = rf_find_hex_record_end(buf + rec_start, size - rec_start); + if (rec_end == RF_RECORD_NO_END_FOUND) { + + return rec_start; + } + + + rec_end += rec_start; + + err = rf_decode_and_write(buf + rec_start, rec_end - rec_start); + if (err < 0) { return err; } + i = rec_end; + } + + return 0; +} + +uint8_t rf_erase_flash(void) +{ + uint8_t err; + + for (uint32_t i = 0; i < 4; i++) { + err = c2_programming_init(); + if (err != C2_SUCCESS) { + return 10; + } + err = c2_device_erase(); + if (err != C2_SUCCESS) { + if (i < 3) { + c2_reset(); + } else { + return 11; + } + } else { + break; + } + } + return 0; +} + +uint8_t SnfBrUpdateInit(void) +{ + pinMode(PIN_C2CK, OUTPUT); + pinMode(PIN_C2D, INPUT); + + return rf_erase_flash(); +} +#endif + + + +void SonoffBridgeReceivedRaw(void) +{ + + uint8_t buckets = 0; + + if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } + + ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); + for (uint32_t i = 0; i < serial_in_byte_counter; i++) { + ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); + if (0xB1 == serial_in_buffer[1]) { + if ((i > 3) && buckets) { buckets--; } + if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { + ResponseAppend_P(PSTR(" ")); + } + } + } + ResponseAppend_P(PSTR("\"}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); + + XdrvRulesProcess(); +} + + + +void SonoffBridgeLearnFailed(void) +{ + SnfBridge.learn_active = 0; + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARN_FAILED); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); +} + +void SonoffBridgeReceived(void) +{ + uint16_t sync_time = 0; + uint16_t low_time = 0; + uint16_t high_time = 0; + uint32_t received_id = 0; + char rfkey[8]; + char stemp[16]; + + AddLogSerial(LOG_LEVEL_DEBUG); + + if (0xA2 == serial_in_buffer[0]) { + SonoffBridgeLearnFailed(); + } + else if (0xA3 == serial_in_buffer[0]) { + SnfBridge.learn_active = 0; + low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; + high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; + if (low_time && high_time) { + for (uint32_t i = 0; i < 9; i++) { + Settings.rf_code[SnfBridge.learn_key][i] = serial_in_buffer[i +1]; + } + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); + } else { + SonoffBridgeLearnFailed(); + } + } + else if (0xA4 == serial_in_buffer[0]) { + if (SnfBridge.learn_active) { + SonoffBridgeLearnFailed(); + } else { + sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; + low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; + high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; + received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9]; + + unsigned long now = millis(); + if (!((received_id == SnfBridge.last_received_id) && (now - SnfBridge.last_time < SFB_TIME_AVOID_DUPLICATE))) { + SnfBridge.last_received_id = received_id; + SnfBridge.last_time = now; + strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey)); + for (uint32_t i = 1; i <= 16; i++) { + if (Settings.rf_code[i][0]) { + uint32_t send_id = Settings.rf_code[i][6] << 16 | Settings.rf_code[i][7] << 8 | Settings.rf_code[i][8]; + if (send_id == received_id) { + snprintf_P(rfkey, sizeof(rfkey), PSTR("%d"), i); + break; + } + } + } + if (Settings.flag.rf_receive_decimal) { + snprintf_P(stemp, sizeof(stemp), PSTR("%u"), received_id); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); + } + ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), + sync_time, low_time, high_time, stemp, rfkey); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); + #ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, received_id); + #endif + } + } + } +} + +bool SonoffBridgeSerialInput(void) +{ + + static int8_t receive_len = 0; + + if (SnfBridge.receive_flag) { + if (SnfBridge.receive_raw_flag) { + if (!serial_in_byte_counter) { + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (serial_in_byte_counter == 3) { + if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { + receive_len = serial_in_buffer[2] + 4; + } + } + if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { + SonoffBridgeReceivedRaw(); + SnfBridge.receive_flag = 0; + return 1; + } + } + else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { + if (0 == serial_in_byte_counter) { + SnfBridge.expected_bytes = 2; + if (serial_in_byte >= 0xA3) { + SnfBridge.expected_bytes = 11; + } + if (serial_in_byte == 0xA6) { + SnfBridge.expected_bytes = 0; + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + SnfBridge.receive_raw_flag = 1; + } + } + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if ((SnfBridge.expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { + SonoffBridgeReceived(); + SnfBridge.receive_flag = 0; + return 1; + } + } + serial_in_byte = 0; + } + if (0xAA == serial_in_byte) { + serial_in_byte_counter = 0; + serial_in_byte = 0; + SnfBridge.receive_flag = 1; + receive_len = 0; + } + return 0; +} + +void SonoffBridgeSendCommand(uint8_t code) +{ + Serial.write(0xAA); + Serial.write(code); + Serial.write(0x55); +} + +void SonoffBridgeSendAck(void) +{ + Serial.write(0xAA); + Serial.write(0xA0); + Serial.write(0x55); +} + +void SonoffBridgeSendCode(uint32_t code) +{ + Serial.write(0xAA); + Serial.write(0xA5); + for (uint32_t i = 0; i < 6; i++) { + Serial.write(Settings.rf_code[0][i]); + } + Serial.write((code >> 16) & 0xff); + Serial.write((code >> 8) & 0xff); + Serial.write(code & 0xff); + Serial.write(0x55); + Serial.flush(); +} + +void SonoffBridgeSend(uint8_t idx, uint8_t key) +{ + uint8_t code; + + key--; + Serial.write(0xAA); + Serial.write(0xA5); + for (uint32_t i = 0; i < 8; i++) { + Serial.write(Settings.rf_code[idx][i]); + } + if (0 == idx) { + code = (0x10 << (key >> 2)) | (1 << (key & 3)); + } else { + code = Settings.rf_code[idx][8]; + } + Serial.write(code); + Serial.write(0x55); + Serial.flush(); +#ifdef USE_DOMOTICZ + + +#endif +} + +void SonoffBridgeLearn(uint8_t key) +{ + SnfBridge.learn_key = key; + SnfBridge.learn_active = 1; + SnfBridge.last_learn_time = millis(); + Serial.write(0xAA); + Serial.write(0xA1); + Serial.write(0x55); +} + + + + + +void CmndRfBridge(void) +{ + char *p; + char stemp [10]; + uint32_t code = 0; + uint8_t radix = 10; + + uint32_t set_index = XdrvMailbox.command_code *2; + + if (XdrvMailbox.data[0] == '#') { + XdrvMailbox.data++; + XdrvMailbox.data_len--; + radix = 16; + } + + if (XdrvMailbox.data_len) { + code = strtol(XdrvMailbox.data, &p, radix); + if (code) { + if (CMND_RFCODE == XdrvMailbox.command_code) { + SnfBridge.last_send_code = code; + SonoffBridgeSendCode(code); + } else { + if (1 == XdrvMailbox.payload) { + code = pgm_read_byte(kDefaultRfCode + set_index) << 8 | pgm_read_byte(kDefaultRfCode + set_index +1); + } + uint8_t msb = code >> 8; + uint8_t lsb = code & 0xFF; + if ((code > 0) && (code < 0x7FFF) && (msb != 0x55) && (lsb != 0x55)) { + Settings.rf_code[0][set_index] = msb; + Settings.rf_code[0][set_index +1] = lsb; + } + } + } + } + if (CMND_RFCODE == XdrvMailbox.command_code) { + code = SnfBridge.last_send_code; + } else { + code = Settings.rf_code[0][set_index] << 8 | Settings.rf_code[0][set_index +1]; + } + if (10 == radix) { + snprintf_P(stemp, sizeof(stemp), PSTR("%d"), code); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"#%06X\""), code); + } + Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp); +} + +void CmndRfKey(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) { + unsigned long now = millis(); + if ((!SnfBridge.learn_active) || (now - SnfBridge.last_learn_time > 60100)) { + SnfBridge.learn_active = 0; + if (2 == XdrvMailbox.payload) { + SonoffBridgeLearn(XdrvMailbox.index); + ResponseCmndIdxChar(D_JSON_START_LEARNING); + } + else if (3 == XdrvMailbox.payload) { + Settings.rf_code[XdrvMailbox.index][0] = 0; + ResponseCmndIdxChar(D_JSON_SET_TO_DEFAULT); + } + else if (4 == XdrvMailbox.payload) { + for (uint32_t i = 0; i < 6; i++) { + Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i]; + } + Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff; + Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff; + Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff; + ResponseCmndIdxChar(D_JSON_SAVED); + } else if (5 == XdrvMailbox.payload) { + uint8_t key = XdrvMailbox.index; + uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; + uint16_t sync_time = (Settings.rf_code[index][0] << 8) | Settings.rf_code[index][1]; + uint16_t low_time = (Settings.rf_code[index][2] << 8) | Settings.rf_code[index][3]; + uint16_t high_time = (Settings.rf_code[index][4] << 8) | Settings.rf_code[index][5]; + uint32_t code = (Settings.rf_code[index][6] << 16) | (Settings.rf_code[index][7] << 8); + if (0 == index) { + key--; + code |= (uint8_t)((0x10 << (key >> 2)) | (1 << (key & 3))); + } else { + code |= Settings.rf_code[index][8]; + } + Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), + XdrvMailbox.command, XdrvMailbox.index, sync_time, low_time, high_time, code); + } else { + if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { + SonoffBridgeSend(0, XdrvMailbox.index); + ResponseCmndIdxChar(D_JSON_DEFAULT_SENT); + } else { + SonoffBridgeSend(XdrvMailbox.index, 0); + ResponseCmndIdxChar(D_JSON_LEARNED_SENT); + } + } + } else { + Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, SnfBridge.learn_key, D_JSON_LEARNING_ACTIVE); + } + } +} + +void CmndRfRaw(void) +{ + if (XdrvMailbox.data_len) { + if (XdrvMailbox.data_len < 6) { + switch (XdrvMailbox.payload) { + case 0: + SonoffBridgeSendCommand(0xA7); + case 1: + SnfBridge.receive_raw_flag = XdrvMailbox.payload; + break; + case 166: + case 167: + case 169: + case 176: + case 177: + case 255: + SonoffBridgeSendCommand(XdrvMailbox.payload); + SnfBridge.receive_raw_flag = 1; + break; + case 192: + char beep[] = "AAC000C055\0"; + SerialSendRaw(beep); + break; + } + } else { + SerialSendRaw(RemoveSpace(XdrvMailbox.data)); + SnfBridge.receive_raw_flag = 1; + } + } + ResponseCmndStateText(SnfBridge.receive_raw_flag); +} + + + + + +bool Xdrv06(uint8_t function) +{ + bool result = false; + + if (SONOFF_BRIDGE == my_module_type) { + switch (function) { + case FUNC_SERIAL: + result = SonoffBridgeSerialInput(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kSonoffBridgeCommands, SonoffBridgeCommand); + break; + case FUNC_INIT: + SnfBridge.receive_raw_flag = 0; + SonoffBridgeSendCommand(0xA7); + break; + case FUNC_PRE_INIT: + SetSerial(19200, TS_SERIAL_8N1); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_07_domoticz.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_07_domoticz.ino" +#ifdef USE_DOMOTICZ + +#define XDRV_07 7 + +#define D_PRFX_DOMOTICZ "Domoticz" +#define D_CMND_IDX "Idx" +#define D_CMND_KEYIDX "KeyIdx" +#define D_CMND_SWITCHIDX "SwitchIdx" +#define D_CMND_SENSORIDX "SensorIdx" +#define D_CMND_UPDATETIMER "UpdateTimer" + +const char kDomoticzCommands[] PROGMEM = D_PRFX_DOMOTICZ "|" + D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ; + +void (* const DomoticzCommand[])(void) PROGMEM = { + &CmndDomoticzIdx, &CmndDomoticzKeyIdx, &CmndDomoticzSwitchIdx, &CmndDomoticzSensorIdx, &CmndDomoticzUpdateTimer }; + +const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; + +#if MAX_DOMOTICZ_SNS_IDX < DZ_MAX_SENSORS + #error "Domoticz: Too many sensors or change settings.h layout" +#endif + +const char kDomoticzSensors[] PROGMEM = + D_DOMOTICZ_TEMP "|" D_DOMOTICZ_TEMP_HUM "|" D_DOMOTICZ_TEMP_HUM_BARO "|" D_DOMOTICZ_POWER_ENERGY "|" D_DOMOTICZ_ILLUMINANCE "|" + D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER "|" D_DOMOTICZ_SHUTTER ; + +char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; + +int domoticz_update_timer = 0; +uint32_t domoticz_fan_debounce = 0; +bool domoticz_subscribe = false; +bool domoticz_update_flag = true; + +#ifdef USE_SHUTTER +bool domoticz_is_shutter = false; +#endif + +int DomoticzBatteryQuality(void) +{ + + + + + int quality = 100; + +#ifdef USE_ADC_VCC + uint16_t voltage = ESP.getVcc(); + if (voltage <= 2600) { + quality = 0; + } else if (voltage >= 4600) { + quality = 200; + } else { + quality = (voltage - 2600) / 10; + } +#endif + return quality; +} + +int DomoticzRssiQuality(void) +{ + + + return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; +} + +#ifdef USE_SONOFF_IFAN +void MqttPublishDomoticzFanState(void) +{ + if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { + char svalue[8]; + + int fan_speed = GetFanspeed(); + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); + + domoticz_fan_debounce = millis(); + } +} + +void DomoticzUpdateFanState(void) +{ + if (domoticz_update_flag) { + MqttPublishDomoticzFanState(); + } + domoticz_update_flag = true; +} +#endif + +void MqttPublishDomoticzPowerState(uint8_t device) +{ + if (Settings.flag.mqtt_enabled) { + if ((device < 1) || (device > devices_present)) { device = 1; } + if (Settings.domoticz_relay_idx[device -1]) { +#ifdef USE_SHUTTER + if (domoticz_is_shutter) { + + } else { +#endif +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (device > 1)) { + + } else { +#endif + char svalue[8]; + + snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); + MqttPublish(domoticz_in_topic); +#ifdef USE_SONOFF_IFAN + } +#endif +#ifdef USE_SHUTTER + } +#endif + } + } +} + +void DomoticzUpdatePowerState(uint8_t device) +{ + if (domoticz_update_flag) { + MqttPublishDomoticzPowerState(device); + } + domoticz_update_flag = true; +} + +void DomoticzMqttUpdate(void) +{ + if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) { + domoticz_update_timer--; + if (domoticz_update_timer <= 0) { + domoticz_update_timer = Settings.domoticz_update_timer; + for (uint32_t i = 1; i <= devices_present; i++) { +#ifdef USE_SHUTTER + if (domoticz_is_shutter) + { + + break; + } +#endif +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (i > 1)) { + MqttPublishDomoticzFanState(); + break; + } else { +#endif + MqttPublishDomoticzPowerState(i); +#ifdef USE_SONOFF_IFAN + } +#endif + } + } + } +} + +void DomoticzMqttSubscribe(void) +{ + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (uint32_t i = 0; i < maxdev; i++) { + if (Settings.domoticz_relay_idx[i]) { + domoticz_subscribe = true; + } + } + + if (domoticz_subscribe) { + char stopic[TOPSZ]; + snprintf_P(stopic, sizeof(stopic), PSTR(DOMOTICZ_OUT_TOPIC "/#")); + MqttSubscribe(stopic); + } +} +# 219 "S:/Development/Tasmota/tasmota/xdrv_07_domoticz.ino" +bool DomoticzMqttData(void) +{ + domoticz_update_flag = true; + + if (strncasecmp_P(XdrvMailbox.topic, PSTR(DOMOTICZ_OUT_TOPIC), strlen(DOMOTICZ_OUT_TOPIC)) != 0) { + return false; + } + + + if (XdrvMailbox.data_len < 20) { + return true; + } + StaticJsonBuffer<400> jsonBuf; + JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data); + if (!domoticz.success()) { + return true; + } + + + + uint32_t idx = domoticz["idx"]; + int16_t nvalue = -1; + if (domoticz.containsKey("nvalue")) { + nvalue = domoticz["nvalue"]; + } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); + + bool found = false; + if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { + uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; + for (uint32_t i = 0; i < maxdev; i++) { + if (idx == Settings.domoticz_relay_idx[i]) { + bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; + bool isShutter = strcmp_P(domoticz["dtype"],PSTR("Light/Switch")) == 0 & strncmp_P(domoticz["switchType"],PSTR("Blinds"), 6) == 0; + + char stemp1[10]; + snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); +#ifdef USE_SONOFF_IFAN + if (IsModuleIfan() && (1 == i)) { + uint8_t svalue = 0; + if (domoticz.containsKey("svalue1")) { + svalue = domoticz["svalue1"]; + } else { + return true; + } + svalue = (nvalue == 2) ? svalue / 10 : 0; + if (GetFanspeed() == svalue) { + return true; + } + if (TimePassedSince(domoticz_fan_debounce) < 1000) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); + found = true; + } else +#endif +#ifdef USE_SHUTTER + if (isShutter) + { + if (domoticz.containsKey("nvalue")) { + nvalue = domoticz["nvalue"]; + } + + uint8_t position = 0; + if (domoticz.containsKey("svalue1")) { + position = domoticz["svalue1"]; + } + if (nvalue != 2) { + position = nvalue == 0 ? 0 : 100; + } + + snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); + XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); + + found = true; + } else +#endif +#ifdef USE_LIGHT + if (iscolordimmer && 10 == nvalue) { + + JsonObject& color = domoticz["Color"]; + uint16_t level = nvalue = domoticz["svalue1"]; + uint16_t r = color["r"]; r = r * level / 100; + uint16_t g = color["g"]; g = g * level / 100; + uint16_t b = color["b"]; b = b * level / 100; + uint16_t cw = color["cw"]; cw = cw * level / 100; + uint16_t ww = color["ww"]; ww = ww * level / 100; + uint16_t m = 0; + uint16_t t = 0; + if (color.containsKey("m")) { + m = color["m"]; + t = color["t"]; + } + if (2 == m) { + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_BACKLOG)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR(D_CMND_COLORTEMPERATURE " %d;" D_CMND_DIMMER " %d"), changeUIntScale(t, 0, 255, CT_MIN, CT_MAX), level); + } else { + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); + } + found = true; + } + else if ((!iscolordimmer && 2 == nvalue) || + (iscolordimmer && 15 == nvalue)) { + if (domoticz.containsKey("svalue1")) { + nvalue = domoticz["svalue1"]; + } else { + return true; + } + if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + found = true; + } else +#endif + if (1 == nvalue || 0 == nvalue) { + if (((power >> i) &1) == (power_t)nvalue) { + return true; + } + snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); + snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); + found = true; + } + break; + } + } + } + if (!found) { return true; } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); + + domoticz_update_flag = false; + return false; +} + + + +bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg) +{ + bool result = false; + + if (device <= MAX_DOMOTICZ_IDX) { + if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { + Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), + (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); + MqttPublish(domoticz_in_topic); + result = true; + } + } + return result; +} +# 393 "S:/Development/Tasmota/tasmota/xdrv_07_domoticz.ino" +uint8_t DomoticzHumidityState(char *hum) +{ + uint8_t h = atoi(hum); + return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; +} + +void DomoticzSensor(uint8_t idx, char *data) +{ + if (Settings.domoticz_sensor_idx[idx]) { + char dmess[128]; + + memcpy(dmess, mqtt_data, sizeof(dmess)); + if (DZ_AIRQUALITY == idx) { + Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), + Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + } else { + uint8_t nvalue = 0; +#ifdef USE_SHUTTER + if (DZ_SHUTTER == idx) { + uint8_t position = atoi(data); + nvalue = position < 2 ? 0 : (position == 100 ? 1 : 2); + } +#endif + Response_P(DOMOTICZ_MESSAGE, + Settings.domoticz_sensor_idx[idx], nvalue, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); + } + MqttPublish(domoticz_in_topic); + memcpy(mqtt_data, dmess, sizeof(dmess)); + } +} + +void DomoticzSensor(uint8_t idx, uint32_t value) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%d"), value); + DomoticzSensor(idx, data); +} + +void DomoticzTempHumSensor(char *temp, char *hum) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temp, hum, DomoticzHumidityState(hum)); + DomoticzSensor(DZ_TEMP_HUM, data); +} + +void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro) +{ + char data[32]; + snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temp, hum, DomoticzHumidityState(hum), baro); + DomoticzSensor(DZ_TEMP_HUM_BARO, data); +} + +void DomoticzSensorPowerEnergy(int power, char *energy) +{ + char data[16]; + snprintf_P(data, sizeof(data), PSTR("%d;%s"), power, energy); + DomoticzSensor(DZ_POWER_ENERGY, data); +} + +void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power) +{ + + + + + + int consumed = power; + int produced = 0; + if (power < 0) { + consumed = 0; + produced = -power; + } + char data[64]; + snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced); + DomoticzSensor(DZ_P1_SMART_METER, data); +} + + + + + +void CmndDomoticzIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + restart_flag = 2; + } + ResponseCmndIdxNumber(Settings.domoticz_relay_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzKeyIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_key_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzSwitchIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_switch_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzSensorIdx(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) { + if (XdrvMailbox.payload >= 0) { + Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); + } +} + +void CmndDomoticzUpdateTimer(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { + Settings.domoticz_update_timer = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.domoticz_update_timer); +} + + + + + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_DOMOTICZ "dm" + +const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; + +const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = + "

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

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


" + "



" + "

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

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

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

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

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

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

")); + WSContentSend_P(PSTR("

"),"/upl",D_UPL_DONE); + + WSContentStop(); +} + + + +void script_upload(void) { + + + + HTTPUpload& upload = WebServer->upload(); + if (upload.status == UPLOAD_FILE_START) { + char npath[48]; + sprintf(npath,"%s/%s",path,upload.filename.c_str()); + SD.remove(npath); + upload_file=SD.open(npath,FILE_WRITE); + if (!upload_file) Web.upload_error=1; + } else if(upload.status == UPLOAD_FILE_WRITE) { + if (upload_file) upload_file.write(upload.buf,upload.currentSize); + } else if(upload.status == UPLOAD_FILE_END) { + if (upload_file) upload_file.close(); + if (Web.upload_error) { + AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error")); + } + } else { + Web.upload_error=1; + WebServer->send(500, "text/plain", "500: couldn't create file"); + } +} + +uint8_t DownloadFile(char *file) { + File download_file; + WiFiClient download_Client; + + if (!SD.exists(file)) { + AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); + return 0; + } + + download_file=SD.open(file,FILE_READ); + if (!download_file) { + AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); + return 0; + } + + if (download_file.isDirectory()) { + download_file.close(); + return 1; + } + + uint32_t flen=download_file.size(); + + download_Client = WebServer->client(); + WebServer->setContentLength(flen); + + char attachment[100]; + char *cp; + for (uint8_t cnt=strlen(file); cnt>=0; cnt--) { + if (file[cnt]=='/') { + cp=&file[cnt+1]; + break; + } + } + snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp); + WebServer->sendHeader(F("Content-Disposition"), attachment); + WSSend(200, CT_STREAM, ""); + + uint8_t buff[512]; + uint16_t bread; + + + uint8_t cnt=0; + while (download_file.available()) { + bread=download_file.read(buff,sizeof(buff)); + uint16_t bw=download_Client.write((const char*)buff,bread); + if (!bw) break; + cnt++; + if (cnt>7) { + cnt=0; + if (glob_script_mem.script_loglevel&0x80) { + + loop(); + } + } + } + download_file.close(); + download_Client.stop(); + return 0; +} + +#endif + + +void HandleScriptTextareaConfiguration(void) { + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("save")) { + ScriptSaveSettings(); + HandleConfiguration(); + return; + } +} + +void HandleScriptConfiguration(void) { + + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT); + +#ifdef USE_SCRIPT_FATFS + if (WebServer->hasArg("d1")) { + DownloadFile(glob_script_mem.flink[0]); + } + if (WebServer->hasArg("d2")) { + DownloadFile(glob_script_mem.flink[1]); + } + if (WebServer->hasArg("upl")) { + Script_FileUploadConfiguration(); + } +#endif + + WSContentStart_P(S_CONFIGURE_SCRIPT); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_SCRIPT); + + +#ifdef xSCRIPT_STRIP_COMMENTS + uint16_t ssize=glob_script_mem.script_size; + if (bitRead(Settings.rule_enabled, 1)) ssize*=2; + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",ssize); +#else + WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); +#endif + + + if (glob_script_mem.script_ram[0]) { + _WSContentSend(glob_script_mem.script_ram); + } + WSContentSend_P(HTTP_FORM_SCRIPT1b); + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.script_sd_found) { + WSContentSend_P(HTTP_FORM_SCRIPT1d); + if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); + if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); + } +#endif + + WSContentSend_P(HTTP_SCRIPT_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); + } + + +void ScriptSaveSettings(void) { + + if (WebServer->hasArg("c1")) { + bitWrite(Settings.rule_enabled,0,1); + } else { + bitWrite(Settings.rule_enabled,0,0); + } + + + String str = WebServer->arg("t1"); + + if (*str.c_str()) { + + str.replace("\r\n","\n"); + str.replace("\r","\n"); + +#ifdef xSCRIPT_STRIP_COMMENTS + if (bitRead(Settings.rule_enabled, 1)) { + char *sp=(char*)str.c_str(); + char *sp1=sp; + char *dp=sp; + uint8_t flg=0; + while (*sp) { + while (*sp==' ') sp++; + sp1=sp; + sp=strchr(sp,'\n'); + if (!sp) { + flg=1; + } else { + *sp=0; + } + if (*sp1!=';') { + uint8_t slen=strlen(sp1); + if (slen) { + strcpy(dp,sp1); + dp+=slen; + *dp++='\n'; + } + } + if (flg) { + *dp=0; + break; + } + sp++; + } + } +#endif + + strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); + +#ifdef USE_24C256 +#ifndef USE_SCRIPT_FATFS + if (glob_script_mem.flags&1) { + EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); + } +#endif +#endif + +#ifdef USE_SCRIPT_FATFS + if (glob_script_mem.flags&1) { + SD.remove(FAT_SCRIPT_NAME); + File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE); + file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE); + file.close(); + } +#endif + + } + + if (glob_script_mem.script_mem) { + Scripter_save_pvars(); + free(glob_script_mem.script_mem); + glob_script_mem.script_mem=0; + glob_script_mem.script_mem_size=0; + } + + if (bitRead(Settings.rule_enabled, 0)) { + int16_t res=Init_Scripter(); + if (res) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); + return; + } + Run_Scripter(">B",2,0); + fast_script=Run_Scripter(">F",-2,0); + } +} + +#endif + + +#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) + + +#define HUE_DEV_MVNUM 5 +#define HUE_DEV_NSIZE 16 +struct HUE_SCRIPT { + char name[HUE_DEV_NSIZE]; + uint8_t type; + uint8_t index[HUE_DEV_MVNUM]; + uint8_t vindex[HUE_DEV_MVNUM]; +} hue_script[32]; + + +const char SCRIPT_HUE_LIGHTS_STATUS_JSON1[] PROGMEM = + "{\"state\":" + "{\"on\":{state}," + "{light_status}" + "\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":true}" + ",\"type\":\"{type}\"," + "\"name\":\"{j1\"," + "\"modelid\":\"{m1}\"," + "\"uniqueid\":\"{j2\"," + "\"swversion\":\"5.50.1.19085\"}"; +# 3624 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" +const char SCRIPT_HUE_LIGHTS_STATUS_JSON2[] PROGMEM = +"{\"state\":{" +"\"presence\":{state}," +"\"lastupdated\":\"2017-10-01T12:37:30\"" +"}," +"\"swupdate\":{" +"\"state\":\"noupdates\"," +"\"lastinstall\": null" +"}," +"\"config\":{" +"\"on\":true," +"\"battery\":100," +"\"reachable\":true," +"\"alert\":\"none\"," +"\"ledindication\":false," +"\"usertest\":false," +"\"sensitivity\":2," +"\"sensitivitymax\":2," +"\"pending\":[]" +"}," +"\"name\":\"{j1\"," +"\"type\":\"ZLLPresence\"," +"\"modelid\":\"SML001\"," +"\"manufacturername\":\"Philips\"," +"\"swversion\":\"6.1.0.18912\"," +"\"uniqueid\":\"{j2\"" +"}"; +# 3705 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" +void Script_HueStatus(String *response, uint16_t hue_devs) { + + if (hue_script[hue_devs].type=='p') { + *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON2); + response->replace("{j1",hue_script[hue_devs].name); + response->replace("{j2", GetHueDeviceId(hue_devs)); + uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + response->replace("{state}", (pwr ? "true" : "false")); + return; + } + + *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1); + uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; + response->replace("{state}", (pwr ? "true" : "false")); + String light_status = ""; + if (hue_script[hue_devs].index[1]>0) { + + light_status += "\"bri\":"; + uint32_t bri=glob_script_mem.fvars[hue_script[hue_devs].index[1]-1]; + if (bri > 254) bri = 254; + if (bri < 1) bri = 1; + light_status += String(bri); + light_status += ","; + } + if (hue_script[hue_devs].index[2]>0) { + + uint32_t hue=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1]; + + light_status += "\"hue\":"; + light_status += String(hue); + light_status += ","; + } + if (hue_script[hue_devs].index[3]>0) { + + uint32_t sat=glob_script_mem.fvars[hue_script[hue_devs].index[3]-1] ; + if (sat > 254) sat = 254; + if (sat < 1) sat = 1; + light_status += "\"sat\":"; + light_status += String(sat); + light_status += ","; + } + if (hue_script[hue_devs].index[4]>0) { + + uint32_t ct=glob_script_mem.fvars[hue_script[hue_devs].index[4]-1]; + light_status += "\"ct\":"; + light_status += String(ct); + light_status += ","; + } + + float temp; + switch (hue_script[hue_devs].type) { + case 'C': + response->replace("{type}","Color Ligh"); + response->replace("{m1","LST001"); + break; + case 'D': + response->replace("{type}","Dimmable Light"); + response->replace("{m1","LWB004"); + break; + case 'T': + response->replace("{type}","Color Temperature Light"); + response->replace("{m1","LTW011"); + break; + case 'E': + response->replace("{type}","Extended color light"); + response->replace("{m1","LCT007"); + break; + case 'S': + response->replace("{type}","On/Off light"); + response->replace("{m1","LCT007"); + break; + default: + response->replace("{type}","color light"); + response->replace("{m1","LST001"); + break; + } + + response->replace("{light_status}", light_status); + response->replace("{j1",hue_script[hue_devs].name); + response->replace("{j2", GetHueDeviceId(hue_devs)); + +} + +void Script_Check_Hue(String *response) { + if (!bitRead(Settings.rule_enabled, 0)) return; + + uint8_t hue_script_found=Run_Scripter(">H",-2,0); + if (hue_script_found!=99) return; + + char line[128]; + char tmp[128]; + uint8_t hue_devs=0; + uint8_t vindex=0; + char *cp; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + SCRIPT_SKIP_SPACES + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + cp=line; + for (uint32_t i=0; i0) *response+=",\""; + } + *response+=String(EncodeLightId(hue_devs+devices_present+1))+"\":"; + Script_HueStatus(response,hue_devs); + } + + hue_devs++; + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } +#if 0 + if (response) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs); + toLog(">>>>"); + toLog(response->c_str()); + toLog(response->c_str()+LOGSZ); + } +#endif +} + +const char sHUE_LIGHT_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; + +const char sHUE_SENSOR_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; + +const char sHUE_ERROR_JSON[] PROGMEM = + "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; + + + +void Script_Handle_Hue(String *path) { + String response; + int code = 200; + uint16_t tmp = 0; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint16_t ct = 0; + bool resp = false; + + uint8_t device = DecodeLightId(atoi(path->c_str())); + uint8_t index = device-devices_present-1; + + if (WebServer->args()) { + response = "["; + + StaticJsonBuffer<400> jsonBuffer; + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + if (hue_json.containsKey("on")) { + + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "on"); + + bool on = hue_json["on"]; + switch(on) + { + case false : glob_script_mem.fvars[hue_script[index].index[0]-1]=0; + response.replace("{re", "false"); + break; + case true : glob_script_mem.fvars[hue_script[index].index[0]-1]=1; + response.replace("{re", "true"); + break; + } + glob_script_mem.type[hue_script[index].vindex[0]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("bri")) { + tmp = hue_json["bri"]; + bri=tmp; + if (254 <= bri) { bri = 255; } + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "bri"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[1]-1]=bri; + glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("xy")) { + float x, y; + x = hue_json["xy"][0]; + y = hue_json["xy"][1]; + const String &x_str = hue_json["xy"][0]; + const String &y_str = hue_json["xy"][1]; + uint8_t rr,gg,bb; + LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); + LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "xy"); + response.replace("{re", "[" + x_str + "," + y_str + "]"); + glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; + glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; + glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; + glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; + resp = true; + } + + if (hue_json.containsKey("hue")) { + tmp = hue_json["hue"]; + + + hue=tmp; + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "hue"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; + glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("sat")) { + tmp = hue_json["sat"]; + sat=tmp; + if (254 <= sat) { sat = 255; } + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "sat"); + response.replace("{re", String(tmp)); + glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; + glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; + resp = true; + } + if (hue_json.containsKey("ct")) { + ct = hue_json["ct"]; + if (resp) { response += ","; } + response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "ct"); + response.replace("{re", String(ct)); + glob_script_mem.fvars[hue_script[index].index[4]-1]=ct; + glob_script_mem.type[hue_script[index].vindex[4]].bits.changed=1; + resp = true; + } + response += "]"; + + } else { + response = FPSTR(sHUE_ERROR_JSON); + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); + WSSend(code, CT_JSON, response); + if (resp) { + Run_Scripter(">E",2,0); + } +} +#endif + + +#ifdef USE_SCRIPT_SUB_COMMAND +bool Script_SubCmd(void) { + if (!bitRead(Settings.rule_enabled, 0)) return false; + + if (tasm_cmd_activ) return false; + + char command[CMDSZ]; + strlcpy(command,XdrvMailbox.topic,CMDSZ); + uint32_t pl=XdrvMailbox.payload; + char pld[64]; + strlcpy(pld,XdrvMailbox.data,sizeof(pld)); + + char cmdbuff[128]; + char *cp=cmdbuff; + *cp++='#'; + strcpy(cp,XdrvMailbox.topic); + uint8_t tlen=strlen(XdrvMailbox.topic); + cp+=tlen; + if (XdrvMailbox.index > 0) { + *cp++=XdrvMailbox.index|0x30; + tlen++; + } + if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) { + *cp++='('; + strncpy(cp,XdrvMailbox.data,XdrvMailbox.data_len); + cp+=XdrvMailbox.data_len; + *cp++=')'; + *cp=0; + } + + uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); + + if (res) return false; + else { + if (pl>=0) { + Response_P(S_JSON_COMMAND_NVALUE, command, pl); + } else { + Response_P(S_JSON_COMMAND_SVALUE, command, pld); + } + } + return true; +} +#endif + +void execute_script(char *script) { + char *svd_sp=glob_script_mem.scriptptr; + strcat(script,"\n#"); + glob_script_mem.scriptptr=script; + Run_Scripter(">",1,0); + glob_script_mem.scriptptr=svd_sp; +} +#define D_CMND_SCRIPT "Script" +#define D_CMND_SUBSCRIBE "Subscribe" +#define D_CMND_UNSUBSCRIBE "Unsubscribe" + +enum ScriptCommands { CMND_SCRIPT,CMND_SUBSCRIBE, CMND_UNSUBSCRIBE }; +const char kScriptCommands[] PROGMEM = D_CMND_SCRIPT "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE; + +bool ScriptCommand(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t index = XdrvMailbox.index; + + if (tasm_cmd_activ) return false; + + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); + if (-1 == command_code) { + serviced = false; + } + else if ((CMND_SCRIPT == command_code) && (index > 0)) { + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { + switch (XdrvMailbox.payload) { + case 0: + case 1: + bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); + break; +#ifdef xSCRIPT_STRIP_COMMENTS + case 2: + bitWrite(Settings.rule_enabled, 1,0); + break; + case 3: + bitWrite(Settings.rule_enabled, 1,1); + break; +#endif + } + } else { + if ('>' == XdrvMailbox.data[0]) { + + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),command,XdrvMailbox.data); + if (bitRead(Settings.rule_enabled, 0)) { + for (uint8_t count=0; count> 1; +} + +void dateTime(uint16_t* date, uint16_t* time) { + + *date = xFAT_DATE(RtcTime.year,RtcTime.month, RtcTime.day_of_month); + + *time = xFAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second); +} + +#endif + + + +#ifdef SUPPORT_MQTT_EVENT +# 4199 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" +bool ScriptMqttData(void) +{ + bool serviced = false; + + toLog(XdrvMailbox.data); + if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { + return false; + } + String sTopic = XdrvMailbox.topic; + String sData = XdrvMailbox.data; + + MQTT_Subscription event_item; + + for (uint32_t index = 0; index < subscriptions.size(); index++) { + event_item = subscriptions.get(index); + + + if (sTopic.startsWith(event_item.Topic)) { + + serviced = true; + String value; + String lkey; + if (event_item.Key.length() == 0) { + value = sData; + } else { + StaticJsonBuffer<400> jsonBuf; + JsonObject& jsonData = jsonBuf.parseObject(sData); + String key1 = event_item.Key; + String key2; + if (!jsonData.success()) break; + int dot; + if ((dot = key1.indexOf('.')) > 0) { + key2 = key1.substring(dot+1); + key1 = key1.substring(0, dot); + lkey=key2; + if (!jsonData[key1][key2].success()) break; + value = (const char *)jsonData[key1][key2]; + } else { + if (!jsonData[key1].success()) break; + value = (const char *)jsonData[key1]; + lkey=key1; + } + } + value.trim(); + char sbuffer[128]; + + if (!strncmp(lkey.c_str(),"Epoch",5)) { + uint32_t ep=atoi(value.c_str())-(uint32_t)EPOCH_OFFSET; + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(),ep); + } else { + snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); + } + + execute_script(sbuffer); + } + } + return serviced; +} +# 4274 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" +String ScriptSubscribe(const char *data, int data_len) +{ + MQTT_Subscription subscription_item; + String events; + if (data_len > 0) { + char parameters[data_len+1]; + memcpy(parameters, data, data_len); + parameters[data_len] = '\0'; + String event_name, topic, key; + + char * pos = strtok(parameters, ","); + if (pos) { + event_name = Trim(pos); + pos = strtok(nullptr, ","); + if (pos) { + topic = Trim(pos); + pos = strtok(nullptr, ","); + if (pos) { + key = Trim(pos); + } + } + } + + + if (event_name.length() > 0 && topic.length() > 0) { + + for (uint32_t index=0; index < subscriptions.size(); index++) { + if (subscriptions.get(index).Event.equals(event_name)) { + + String stopic = subscriptions.get(index).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(index); + break; + } + } + + if (!topic.endsWith("#")) { + if (topic.endsWith("/")) { + topic.concat("#"); + } else { + topic.concat("/#"); + } + } + + + subscription_item.Event = event_name; + subscription_item.Topic = topic.substring(0, topic.length() - 2); + subscription_item.Key = key; + subscriptions.add(subscription_item); + + MqttSubscribe(topic.c_str()); + events.concat(event_name + "," + topic + + (key.length()>0 ? "," : "") + + key); + } else { + events = D_JSON_WRONG_PARAMETERS; + } + } else { + + for (uint32_t index=0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + events.concat(subscription_item.Event + "," + subscription_item.Topic + + (subscription_item.Key.length()>0 ? "," : "") + + subscription_item.Key + "; "); + } + } + return events; +} +# 4354 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" +String ScriptUnsubscribe(const char * data, int data_len) +{ + MQTT_Subscription subscription_item; + String events; + if (data_len > 0) { + for (uint32_t index = 0; index < subscriptions.size(); index++) { + subscription_item = subscriptions.get(index); + if (subscription_item.Event.equalsIgnoreCase(data)) { + String stopic = subscription_item.Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + events = subscription_item.Event; + subscriptions.remove(index); + break; + } + } + } else { + + String stopic; + while (subscriptions.size() > 0) { + events.concat(subscriptions.get(0).Event + "; "); + stopic = subscriptions.get(0).Topic + "/#"; + MqttUnsubscribe(stopic.c_str()); + subscriptions.remove(0); + } + } + return events; +} +#endif + + + +#ifdef USE_SCRIPT_WEB_DISPLAY + +void Script_Check_HTML_Setvars(void) { + + if (!HttpCheckPriviledgedAccess()) { return; } + + if (WebServer->hasArg("sv")) { + String stmp = WebServer->arg("sv"); + char cmdbuf[64]; + memset(cmdbuf,0,sizeof(cmdbuf)); + char *cp=cmdbuf; + *cp++='>'; + strncpy(cp,stmp.c_str(),sizeof(cmdbuf)-1); + char *cp1=strchr(cp,'_'); + if (!cp1) return; + *cp1=0; + char vname[32]; + strncpy(vname,cp,sizeof(vname)); + *cp1='='; + cp1++; + + struct T_INDEX ind; + uint8_t vtype; + isvar(vname,&vtype,&ind,0,0,0); + if (vtype!=NUM_RES && vtype&STYPE) { + + uint8_t tlen=strlen(cp1); + memmove(cp1+1,cp1,tlen); + *cp1='\"'; + *(cp1+tlen+1)='\"'; + } + + + execute_script(cmdbuf); + Run_Scripter(">E",2,0); + } +} + + +const char SCRIPT_MSG_BUTTONa[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUTTONb[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUT_START[] PROGMEM = + "
"; +const char SCRIPT_MSG_BUT_START_TBL[] PROGMEM = + ""; + +const char SCRIPT_MSG_BUT_STOP[] PROGMEM = + ""; +const char SCRIPT_MSG_BUT_STOP_TBL[] PROGMEM = + "
"; + +const char SCRIPT_MSG_SLIDER[] PROGMEM = + "
%s
%s%s
" + "
"; + +const char SCRIPT_MSG_CHKBOX[] PROGMEM = + "
"; + +const char SCRIPT_MSG_TEXTINP[] PROGMEM = + "
"; + +const char SCRIPT_MSG_NUMINP[] PROGMEM = + "
"; + + +void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { +uint32_t cnt; + for (cnt=0;cntW",-2,0); + if (web_script==99) { + char line[128]; + char tmp[128]; + uint8_t optflg=0; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; i0) { + cp="checked='checked'"; + uval=0; + } else { + cp=""; + uval=1; + } + WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); + + } else if (!strncmp(lin,"bu(",3)) { + char *lp=lin+3; + uint8_t bcnt=0; + char *found=lin; + while (bcnt<4) { + found=strstr(found,"bu("); + if (!found) break; + found+=3; + bcnt++; + } + uint8_t proz=100/bcnt; + if (!optflg && bcnt>1) proz-=2; + if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); + else WSContentSend_PD(SCRIPT_MSG_BUT_START); + for (uint32_t cnt=0;cnt0) { + cp=ontxt; + uval=0; + } else { + cp=offtxt; + uval=1; + } + if (bcnt>1 && cnt==bcnt-1) { + if (!optflg) proz+=2; + } + if (!optflg) { + WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); + } else { + WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); + } + if (bcnt>1 && cnt%s
"),tmp); + } else { + WSContentSend_PD(PSTR("{s}%s{e}"),tmp); + } + } + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } +} +#endif + + +#ifdef USE_SENDMAIL +void script_send_email_body(BearSSL::WiFiClientSecure_light *client) { +uint8_t msect=Run_Scripter(">m",-2,0); + if (msect==99) { + char line[128]; + char tmp[128]; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; iprintln(tmp); + } + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + } else { + client->println("*"); + } +} +#endif + +#ifdef USE_SCRIPT_JSON_EXPORT +void ScriptJsonAppend(void) { + uint8_t web_script=Run_Scripter(">J",-2,0); + if (web_script==99) { + char line[128]; + char tmp[128]; + char *lp=glob_script_mem.section_ptr+2; + while (lp) { + while (*lp==SCRIPT_EOL) { + lp++; + } + if (!*lp || *lp=='#' || *lp=='>') { + break; + } + if (*lp!=';') { + + memcpy(line,lp,sizeof(line)); + line[sizeof(line)-1]=0; + char *cp=line; + for (uint32_t i=0; iB",2,0); + fast_script=Run_Scripter(">F",-2,0); +#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) + Script_Check_Hue(0); +#endif + } + break; + case FUNC_EVERY_100_MSECOND: + ScripterEvery100ms(); + break; + case FUNC_EVERY_SECOND: + ScriptEverySecond(); + break; + case FUNC_COMMAND: + result = ScriptCommand(); + break; + case FUNC_SET_POWER: +#ifdef SCRIPT_POWER_SECTION + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P",2,0); +#else + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,0); +#endif + break; + case FUNC_RULES_PROCESS: + if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_RULES); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); + WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); + +#ifdef USE_SCRIPT_FATFS + WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload); + WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess); + WebServer->on("/upl", HTTP_GET,Script_FileUploadConfiguration); +#endif + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + if (bitRead(Settings.rule_enabled, 0)) { + Run_Scripter(">R",2,0); + Scripter_save_pvars(); + } + break; +#ifdef SUPPORT_MQTT_EVENT + case FUNC_MQTT_DATA: + if (bitRead(Settings.rule_enabled, 0)) { + result = ScriptMqttData(); + } + break; +#endif +#ifdef USE_SCRIPT_WEB_DISPLAY + case FUNC_WEB_SENSOR: + if (bitRead(Settings.rule_enabled, 0)) { + ScriptWebShow(); + } + break; +#endif + +#ifdef USE_SCRIPT_JSON_EXPORT + case FUNC_JSON_APPEND: + if (bitRead(Settings.rule_enabled, 0)) { + ScriptJsonAppend(); + } + break; +#endif + +#ifdef USE_BUTTON_EVENT + case FUNC_BUTTON_PRESSED: + if (bitRead(Settings.rule_enabled, 0)) { + if ((script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) { + script_button[XdrvMailbox.index]=XdrvMailbox.payload; + Run_Scripter(">b",2,0); + } + } + break; +#endif + + } + return result; +} + + + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" +#ifdef USE_KNX +# 51 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" +#define XDRV_11 11 + +#include + +address_t KNX_physs_addr; +address_t KNX_addr; + +#define KNX_Empty 255 + +#define TOGGLE_INHIBIT_TIME 15 + +float last_temp; +float last_hum; +uint8_t toggle_inhibit; + +typedef struct __device_parameters +{ + uint8_t type; + + + + + bool show; + + bool last_state; + + callback_id_t CB_id; + + + + + +} device_parameters_t; + + +device_parameters_t device_param[] = { + { 1, false, false, KNX_Empty }, + { 2, false, false, KNX_Empty }, + { 3, false, false, KNX_Empty }, + { 4, false, false, KNX_Empty }, + { 5, false, false, KNX_Empty }, + { 6, false, false, KNX_Empty }, + { 7, false, false, KNX_Empty }, + { 8, false, false, KNX_Empty }, + { 9, false, false, KNX_Empty }, + { 10, false, false, KNX_Empty }, + { 11, false, false, KNX_Empty }, + { 12, false, false, KNX_Empty }, + { 13, false, false, KNX_Empty }, + { 14, false, false, KNX_Empty }, + { 15, false, false, KNX_Empty }, + { 16, false, false, KNX_Empty }, + { KNX_TEMPERATURE, false, false, KNX_Empty }, + { KNX_HUMIDITY , false, false, KNX_Empty }, + { KNX_ENERGY_VOLTAGE , false, false, KNX_Empty }, + { KNX_ENERGY_CURRENT , false, false, KNX_Empty }, + { KNX_ENERGY_POWER , false, false, KNX_Empty }, + { KNX_ENERGY_POWERFACTOR , false, false, KNX_Empty }, + { KNX_ENERGY_DAILY , false, false, KNX_Empty }, + { KNX_ENERGY_START , false, false, KNX_Empty }, + { KNX_ENERGY_TOTAL , false, false, KNX_Empty }, + { KNX_SLOT1 , false, false, KNX_Empty }, + { KNX_SLOT2 , false, false, KNX_Empty }, + { KNX_SLOT3 , false, false, KNX_Empty }, + { KNX_SLOT4 , false, false, KNX_Empty }, + { KNX_SLOT5 , false, false, KNX_Empty }, + { KNX_Empty, false, false, KNX_Empty} +}; + + +const char * device_param_ga[] = { + D_TIMER_OUTPUT " 1", + D_TIMER_OUTPUT " 2", + D_TIMER_OUTPUT " 3", + D_TIMER_OUTPUT " 4", + D_TIMER_OUTPUT " 5", + D_TIMER_OUTPUT " 6", + D_TIMER_OUTPUT " 7", + D_TIMER_OUTPUT " 8", + D_SENSOR_BUTTON " 1", + D_SENSOR_BUTTON " 2", + D_SENSOR_BUTTON " 3", + D_SENSOR_BUTTON " 4", + D_SENSOR_BUTTON " 5", + D_SENSOR_BUTTON " 6", + D_SENSOR_BUTTON " 7", + D_SENSOR_BUTTON " 8", + D_TEMPERATURE , + D_HUMIDITY , + D_VOLTAGE , + D_CURRENT , + D_POWERUSAGE , + D_POWER_FACTOR , + D_ENERGY_TODAY , + D_ENERGY_YESTERDAY , + D_ENERGY_TOTAL , + D_KNX_TX_SLOT " 1", + D_KNX_TX_SLOT " 2", + D_KNX_TX_SLOT " 3", + D_KNX_TX_SLOT " 4", + D_KNX_TX_SLOT " 5", + nullptr +}; + + +const char *device_param_cb[] = { + D_TIMER_OUTPUT " 1", + D_TIMER_OUTPUT " 2", + D_TIMER_OUTPUT " 3", + D_TIMER_OUTPUT " 4", + D_TIMER_OUTPUT " 5", + D_TIMER_OUTPUT " 6", + D_TIMER_OUTPUT " 7", + D_TIMER_OUTPUT " 8", + D_TIMER_OUTPUT " 1 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 2 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 3 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 4 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 5 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 6 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 7 " D_BUTTON_TOGGLE, + D_TIMER_OUTPUT " 8 " D_BUTTON_TOGGLE, + D_REPLY " " D_TEMPERATURE, + D_REPLY " " D_HUMIDITY, + D_REPLY " " D_VOLTAGE , + D_REPLY " " D_CURRENT , + D_REPLY " " D_POWERUSAGE , + D_REPLY " " D_POWER_FACTOR , + D_REPLY " " D_ENERGY_TODAY , + D_REPLY " " D_ENERGY_YESTERDAY , + D_REPLY " " D_ENERGY_TOTAL , + D_KNX_RX_SLOT " 1", + D_KNX_RX_SLOT " 2", + D_KNX_RX_SLOT " 3", + D_KNX_RX_SLOT " 4", + D_KNX_RX_SLOT " 5", + nullptr +}; + + +#define D_PRFX_KNX "Knx" +#define D_CMND_KNXTXCMND "Tx_Cmnd" +#define D_CMND_KNXTXVAL "Tx_Val" +#define D_CMND_KNX_ENABLED "_Enabled" +#define D_CMND_KNX_ENHANCED "_Enhanced" +#define D_CMND_KNX_PA "_PA" +#define D_CMND_KNX_GA "_GA" +#define D_CMND_KNX_CB "_CB" + +const char kKnxCommands[] PROGMEM = D_PRFX_KNX "|" + D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ; + +void (* const KnxCommand[])(void) PROGMEM = { + &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb }; + +uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 ) +{ + for (uint32_t i = start; i < Settings.knx_GA_registered; ++i) + { + if ( Settings.knx_GA_param[i] == param ) + { + if ( Settings.knx_GA_addr[i] != 0 ) + { + if ( i >= start ) { return i; } + } + } + } + return KNX_Empty; +} + + +uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 ) +{ + for (uint32_t i = start; i < Settings.knx_CB_registered; ++i) + { + if ( Settings.knx_CB_param[i] == param ) + { + if ( Settings.knx_CB_addr[i] != 0 ) + { + if ( i >= start ) { return i; } + } + } + } + return KNX_Empty; +} + + +void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ) +{ + + if ( Settings.knx_GA_registered >= MAX_KNX_GA ) { return; } + if ( GA_FNUM == 0 && GA_AREA == 0 && GA_FDEF == 0 ) { return; } + + + Settings.knx_GA_param[Settings.knx_GA_registered] = GAop; + KNX_addr.ga.area = GA_FNUM; + KNX_addr.ga.line = GA_AREA; + KNX_addr.ga.member = GA_FDEF; + Settings.knx_GA_addr[Settings.knx_GA_registered] = KNX_addr.value; + + Settings.knx_GA_registered++; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), + Settings.knx_GA_registered, + device_param_ga[GAop-1], + GA_FNUM, GA_AREA, GA_FDEF ); +} + + +void KNX_DEL_GA( uint8_t GAnum ) +{ + + uint8_t dest_offset = 0; + uint8_t src_offset = 0; + uint8_t len = 0; + + + Settings.knx_GA_param[GAnum-1] = 0; + + if (GAnum == 1) + { + + src_offset = 1; + + + + len = (Settings.knx_GA_registered - 1); + } + else if (GAnum == Settings.knx_GA_registered) + { + + } + else + { + + + + + dest_offset = GAnum -1 ; + src_offset = dest_offset + 1; + len = (Settings.knx_GA_registered - GAnum); + } + + if (len > 0) + { + memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(uint8_t)); + memmove(Settings.knx_GA_addr + dest_offset, Settings.knx_GA_addr + src_offset, len * sizeof(uint16_t)); + } + + Settings.knx_GA_registered--; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " GA #%d"), + GAnum ); +} + + +void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ) +{ + + if ( Settings.knx_CB_registered >= MAX_KNX_CB ) { return; } + if ( CB_FNUM == 0 && CB_AREA == 0 && CB_FDEF == 0 ) { return; } + + + if ( device_param[CBop-1].CB_id == KNX_Empty ) + { + + device_param[CBop-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[CBop-1]); + + + + + } + + Settings.knx_CB_param[Settings.knx_CB_registered] = CBop; + KNX_addr.ga.area = CB_FNUM; + KNX_addr.ga.line = CB_AREA; + KNX_addr.ga.member = CB_FDEF; + Settings.knx_CB_addr[Settings.knx_CB_registered] = KNX_addr.value; + + knx.callback_assign( device_param[CBop-1].CB_id, KNX_addr ); + + Settings.knx_CB_registered++; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"), + Settings.knx_CB_registered, + CB_FNUM, CB_AREA, CB_FDEF, + device_param_cb[CBop-1] ); +} + + +void KNX_DEL_CB( uint8_t CBnum ) +{ + uint8_t oldparam = Settings.knx_CB_param[CBnum-1]; + uint8_t dest_offset = 0; + uint8_t src_offset = 0; + uint8_t len = 0; + + + knx.callback_unassign(CBnum-1); + Settings.knx_CB_param[CBnum-1] = 0; + + if (CBnum == 1) + { + + src_offset = 1; + + + + len = (Settings.knx_CB_registered - 1); + } + else if (CBnum == Settings.knx_CB_registered) + { + + } + else + { + + + + + dest_offset = CBnum -1 ; + src_offset = dest_offset + 1; + len = (Settings.knx_CB_registered - CBnum); + } + + if (len > 0) + { + memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(uint8_t)); + memmove(Settings.knx_CB_addr + dest_offset, Settings.knx_CB_addr + src_offset, len * sizeof(uint16_t)); + } + + Settings.knx_CB_registered--; + + + if ( KNX_CB_Search( oldparam ) == KNX_Empty ) { + knx.callback_deregister( device_param[oldparam-1].CB_id ); + device_param[oldparam-1].CB_id = KNX_Empty; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " CB #%d"), CBnum ); +} + + +bool KNX_CONFIG_NOT_MATCH(void) +{ + + for (uint32_t i = 0; i < KNX_MAX_device_param; ++i) + { + if ( !device_param[i].show ) { + + + + if ( KNX_GA_Search(i+1) != KNX_Empty ) { return true; } + + if ( i < 8 ) + { + if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } + if ( KNX_CB_Search(i+9) != KNX_Empty ) { return true; } + } + + if ( i > 15 ) + { + if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } + } + } + } + + + for (uint32_t i = 0; i < Settings.knx_GA_registered; ++i) + { + if ( Settings.knx_GA_param[i] != 0 ) + { + if ( Settings.knx_GA_addr[i] == 0 ) + { + return true; + } + } + } + for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) + { + if ( Settings.knx_CB_param[i] != 0 ) + { + if ( Settings.knx_CB_addr[i] == 0 ) + { + return true; + } + } + } + + return false; +} + + +void KNXStart(void) +{ + knx.start(nullptr); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_START)); +} + + +void KNX_INIT(void) +{ + + if (Settings.knx_GA_registered > MAX_KNX_GA) { Settings.knx_GA_registered = MAX_KNX_GA; } + if (Settings.knx_CB_registered > MAX_KNX_CB) { Settings.knx_CB_registered = MAX_KNX_CB; } + + + KNX_physs_addr.value = Settings.knx_physsical_addr; + knx.physical_address_set( KNX_physs_addr ); +# 472 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" + for (uint32_t i = 0; i < devices_present; ++i) + { + device_param[i].show = true; + } + for (uint32_t i = GPIO_SWT1; i < GPIO_SWT4 + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } + } + for (uint32_t i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } + } + for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } + } + for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) + { + if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } + } + if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } +#ifdef USE_DS18x20 + if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } +#endif + if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } + +#if defined(USE_ENERGY_SENSOR) + + if ( energy_flg != ENERGY_NONE ) { + device_param[KNX_ENERGY_POWER-1].show = true; + device_param[KNX_ENERGY_DAILY-1].show = true; + device_param[KNX_ENERGY_START-1].show = true; + device_param[KNX_ENERGY_TOTAL-1].show = true; + device_param[KNX_ENERGY_VOLTAGE-1].show = true; + device_param[KNX_ENERGY_CURRENT-1].show = true; + device_param[KNX_ENERGY_POWERFACTOR-1].show = true; + } +#endif + +#ifdef USE_RULES + device_param[KNX_SLOT1-1].show = true; + device_param[KNX_SLOT2-1].show = true; + device_param[KNX_SLOT3-1].show = true; + device_param[KNX_SLOT4-1].show = true; + device_param[KNX_SLOT5-1].show = true; +#endif + + + if (KNX_CONFIG_NOT_MATCH()) { + Settings.knx_GA_registered = 0; + Settings.knx_CB_registered = 0; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS)); + } + + + + + uint8_t j; + for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) + { + j = Settings.knx_CB_param[i]; + if ( j > 0 ) + { + device_param[j-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[j-1]); + + + + KNX_addr.value = Settings.knx_CB_addr[i]; + knx.callback_assign( device_param[j-1].CB_id, KNX_addr ); + } + } +} + + +void KNX_CB_Action(message_t const &msg, void *arg) +{ + device_parameters_t *chan = (device_parameters_t *)arg; + if (!(Settings.flag.knx_enabled)) { return; } + + char tempchar[33]; + + if (msg.data_len == 1) { + + tempchar[0] = msg.data[0]; + tempchar[1] = '\0'; + } else { + + float tempvar = knx.data_to_2byte_float(msg.data); + dtostrfd(tempvar,2,tempchar); + } + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"), + msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, + (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, + tempchar, + device_param_cb[(chan->type)-1]); + + switch (msg.ct) + { + case KNX_CT_WRITE: + if (chan->type < 9) + { + ExecuteCommandPower(chan->type, msg.data[0], SRC_KNX); + } + else if (chan->type < 17) + { + if (!toggle_inhibit) { + ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#ifdef USE_RULES + else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) + { + if (!toggle_inhibit) { + char command[25]; + if (msg.data_len == 1) { + + snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]); + } else { + + snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar); + } + ExecuteCommand(command, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#endif + break; + + case KNX_CT_READ: + if (chan->type < 9) + { + knx.answer_1bit(msg.received_on, chan->last_state); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_1bit(msg.received_on, chan->last_state); + knx.answer_1bit(msg.received_on, chan->last_state); + } + } + else if (chan->type == KNX_TEMPERATURE) + { + knx.answer_2byte_float(msg.received_on, last_temp); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_2byte_float(msg.received_on, last_temp); + knx.answer_2byte_float(msg.received_on, last_temp); + } + } + else if (chan->type == KNX_HUMIDITY) + { + knx.answer_2byte_float(msg.received_on, last_hum); + if (Settings.flag.knx_enable_enhancement) { + knx.answer_2byte_float(msg.received_on, last_hum); + knx.answer_2byte_float(msg.received_on, last_hum); + } + } +#ifdef USE_RULES + else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) + { + if (!toggle_inhibit) { + char command[25]; + snprintf_P(command, sizeof(command), PSTR("event KNXRX_REQ%d"), ((chan->type) - KNX_SLOT1 + 1 ) ); + ExecuteCommand(command, SRC_KNX); + if (Settings.flag.knx_enable_enhancement) { + toggle_inhibit = TOGGLE_INHIBIT_TIME; + } + } + } +#endif + break; + } +} + + +void KnxUpdatePowerState(uint8_t device, power_t state) +{ + if (!(Settings.flag.knx_enabled)) { return; } + + device_param[device -1].last_state = bitRead(state, device -1); + + + uint8_t i = KNX_GA_Search(device); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + knx.write_1bit(KNX_addr, device_param[device -1].last_state); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[device -1], device_param[device -1].last_state, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(device, i + 1); + } +} + + +void KnxSendButtonPower(void) +{ + if (!(Settings.flag.knx_enabled)) { return; } + + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; + uint32_t device = XdrvMailbox.payload & 0xFF; + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; +# 693 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" + uint8_t i = KNX_GA_Search(device + 8); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, !(state == 0)); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, !(state == 0)); + knx.write_1bit(KNX_addr, !(state == 0)); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[device + 7], !(state == 0), + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(device + 8, i + 1); + } + +} + + +void KnxSensor(uint8_t sensor_type, float value) +{ + if (sensor_type == KNX_TEMPERATURE) + { + last_temp = value; + } else if (sensor_type == KNX_HUMIDITY) + { + last_hum = value; + } + + if (!(Settings.flag.knx_enabled)) { return; } + + uint8_t i = KNX_GA_Search(sensor_type); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_2byte_float(KNX_addr, value); + if (Settings.flag.knx_enable_enhancement) { + knx.write_2byte_float(KNX_addr, value); + knx.write_2byte_float(KNX_addr, value); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "), + device_param_ga[sensor_type -1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(sensor_type, i+1); + } +} + + + + + + +#ifdef USE_WEBSERVER +#ifdef USE_KNX_WEB_MENU +const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; + +const char HTTP_BTN_MENU_KNX[] PROGMEM = + "

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

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" + "" D_KNX_ENABLE "" D_KNX_ENHANCEMENT "

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

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

" + "
" + "" D_KNX_GROUP_ADDRESS_TO_READ "
"; + +const char HTTP_FORM_KNX4[] PROGMEM = + "-> -> ")); + WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_AREA", "GA_FDEF"); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); + for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) + { + if ( Settings.knx_GA_param[i] ) + { + KNX_addr.value = Settings.knx_GA_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1); + } + } + + WSContentSend_P(HTTP_FORM_KNX3); + WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_AREA", "CB_FDEF"); + WSContentSend_P(HTTP_FORM_KNX4); + + uint8_t j; + for (uint32_t i = 0; i < KNX_MAX_device_param ; i++) + { + + if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } + if ( i == 8 ) { j = 0; } + if ( device_param[j].show ) + { + WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); + } + } + WSContentSend_P(PSTR(" ")); + WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); + + for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) + { + if ( Settings.knx_CB_param[i] ) + { + KNX_addr.value = Settings.knx_CB_addr[i]; + WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); + } + } + WSContentSend_P(PSTR("
")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); + } + +} + + +void KNX_Save_Settings(void) +{ + String stmp; + address_t KNX_addr; + + Settings.flag.knx_enabled = WebServer->hasArg("b1"); + Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2"); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), + Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement ); + + stmp = WebServer->arg("area"); + KNX_addr.pa.area = stmp.toInt(); + stmp = WebServer->arg("line"); + KNX_addr.pa.line = stmp.toInt(); + stmp = WebServer->arg("member"); + KNX_addr.pa.member = stmp.toInt(); + Settings.knx_physsical_addr = KNX_addr.value; + knx.physical_address_set( KNX_addr ); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "), + KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA: %d"), + Settings.knx_GA_registered ); + for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) + { + KNX_addr.value = Settings.knx_GA_addr[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), + i+1, device_param_ga[Settings.knx_GA_param[i]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB: %d"), + Settings.knx_CB_registered ); + for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) + { + KNX_addr.value = Settings.knx_CB_addr[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), + i+1, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, + device_param_cb[Settings.knx_CB_param[i]-1] ); + } +} + +#endif +#endif + + + + + +void CmndKnxTxCmnd(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { + + + + uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + if (Settings.flag.knx_enable_enhancement) { + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), + device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], !(XdrvMailbox.payload == 0), + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); + } + ResponseCmndIdxChar (XdrvMailbox.data ); + } +} + +void CmndKnxTxVal(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { + + + + uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); + while ( i != KNX_Empty ) { + KNX_addr.value = Settings.knx_GA_addr[i]; + + float tempvar = CharToFloat(XdrvMailbox.data); + dtostrfd(tempvar,2,XdrvMailbox.data); + + knx.write_2byte_float(KNX_addr, tempvar); + if (Settings.flag.knx_enable_enhancement) { + knx.write_2byte_float(KNX_addr, tempvar); + knx.write_2byte_float(KNX_addr, tempvar); + } + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), + device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], XdrvMailbox.data, + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); + + i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); + } + ResponseCmndIdxChar (XdrvMailbox.data ); + } +} + +void CmndKnxEnabled(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag.knx_enabled = XdrvMailbox.payload; + } + ResponseCmndChar (GetStateText(Settings.flag.knx_enabled) ); +} + +void CmndKnxEnhanced(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + Settings.flag.knx_enable_enhancement = XdrvMailbox.payload; + } + ResponseCmndChar (GetStateText(Settings.flag.knx_enable_enhancement) ); +} + +void CmndKnxPa(void) +{ + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ".") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); + int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2)); + int pa_member = atoi(subStr(sub_string, XdrvMailbox.data, ".", 3)); + + if ( ((pa_area == 0) && (pa_line == 0) && (pa_member == 0)) + || (pa_area > 15) || (pa_line > 15) || (pa_member > 255) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.pa.area = pa_area; + KNX_addr.pa.line = pa_line; + KNX_addr.pa.member = pa_member; + Settings.knx_physsical_addr = KNX_addr.value; + } + } + KNX_addr.value = Settings.knx_physsical_addr; + Response_P (PSTR("{\"%s\":\"%d.%d.%d\"}"), + XdrvMailbox.command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); +} + +void CmndKnxGa(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_GA)) { + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + int ga_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + int ga_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + + if ( ((ga_area == 0) && (ga_line == 0) && (ga_member == 0)) + || (ga_area > 31) || (ga_line > 7) || (ga_member > 255) + || (ga_option < 0) || ((ga_option > KNX_MAX_device_param ) && (ga_option != KNX_Empty)) + || (!device_param[ga_option-1].show) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.ga.area = ga_area; + KNX_addr.ga.line = ga_line; + KNX_addr.ga.member = ga_member; + + if ( XdrvMailbox.index > Settings.knx_GA_registered ) { + Settings.knx_GA_registered ++; + XdrvMailbox.index = Settings.knx_GA_registered; + } + + Settings.knx_GA_addr[XdrvMailbox.index -1] = KNX_addr.value; + Settings.knx_GA_param[XdrvMailbox.index -1] = ga_option; + } else { + if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) { + XdrvMailbox.index = XdrvMailbox.payload; + } else { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + } + if ( XdrvMailbox.index <= Settings.knx_GA_registered ) { + KNX_addr.value = Settings.knx_GA_addr[XdrvMailbox.index -1]; + Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), + XdrvMailbox.command, XdrvMailbox.index, device_param_ga[Settings.knx_GA_param[XdrvMailbox.index-1]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + } + } else { + ResponseCmndNumber (Settings.knx_GA_registered ); + } + } +} + +void CmndKnxCb(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_CB)) { + if (XdrvMailbox.data_len) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len]; + + int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + int cb_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + int cb_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + + if ( ((cb_area == 0) && (cb_line == 0) && (cb_member == 0)) + || (cb_area > 31) || (cb_line > 7) || (cb_member > 255) + || (cb_option < 0) || ((cb_option > KNX_MAX_device_param ) && (cb_option != KNX_Empty)) + || (!device_param[cb_option-1].show) ) { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + + KNX_addr.ga.area = cb_area; + KNX_addr.ga.line = cb_line; + KNX_addr.ga.member = cb_member; + + if ( XdrvMailbox.index > Settings.knx_CB_registered ) { + Settings.knx_CB_registered ++; + XdrvMailbox.index = Settings.knx_CB_registered; + } + + Settings.knx_CB_addr[XdrvMailbox.index -1] = KNX_addr.value; + Settings.knx_CB_param[XdrvMailbox.index -1] = cb_option; + } else { + if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) { + XdrvMailbox.index = XdrvMailbox.payload; + } else { + Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); + return; + } + } + if ( XdrvMailbox.index <= Settings.knx_CB_registered ) { + KNX_addr.value = Settings.knx_CB_addr[XdrvMailbox.index -1]; + Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), + XdrvMailbox.command, XdrvMailbox.index, device_param_cb[Settings.knx_CB_param[XdrvMailbox.index-1]-1], + KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); + } + } else { + ResponseCmndNumber (Settings.knx_CB_registered ); + } + } +} + + + + + +bool Xdrv11(uint8_t function) +{ + bool result = false; + switch (function) { + case FUNC_LOOP: + if (!global_state.wifi_down) { knx.loop(); } + break; + case FUNC_EVERY_50_MSECOND: + if (toggle_inhibit) { + toggle_inhibit--; + } + break; + case FUNC_ANY_KEY: + KnxSendButtonPower(); + break; +#ifdef USE_WEBSERVER +#ifdef USE_KNX_WEB_MENU + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_KNX); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/kn", HandleKNXConfiguration); + break; +#endif +#endif + case FUNC_COMMAND: + result = DecodeCommand(kKnxCommands, KnxCommand); + break; + case FUNC_PRE_INIT: + KNX_INIT(); + break; + + + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_12_home_assistant.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_12_home_assistant.ino" +#ifdef USE_HOME_ASSISTANT + +#define XDRV_12 12 + + +const char kHAssJsonSensorTypes[] PROGMEM = + D_JSON_TEMPERATURE "|" D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" + D_JSON_APPARENT_POWERUSAGE "|Battery|" D_JSON_CURRENT "|" D_JSON_DISTANCE "|" D_JSON_FREQUENCY "|" D_JSON_HUMIDITY "|" D_JSON_ILLUMINANCE "|" + D_JSON_MOISTURE "|PB0.3|PB0.5|PB1|PB2.5|PB5|PB10|PM1|PM2.5|PM10|" D_JSON_POWERFACTOR "|" D_JSON_POWERUSAGE "|" + D_JSON_REACTIVE_POWERUSAGE "|" D_JSON_TODAY "|" D_JSON_TOTAL "|" D_JSON_VOLTAGE "|" D_JSON_WEIGHT "|" D_JSON_YESTERDAY; +const char kHAssJsonSensorUnits[] PROGMEM = + "|||" + "W|%|A|Cm|Hz|%|LX|" + "%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³||W|" + "W|KWh|KWh|V|Kg|KWh"; +const char kHAssJsonSensorDevCla[] PROGMEM = + "dev_cla\":\"temperature|dev_cla\":\"pressure|dev_cla\":\"pressure|" + "dev_cla\":\"power|dev_cla\":\"battery|ic\":\"mdi:alpha-a-circle-outline|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" + "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" + "ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|" + "dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power"; + + +const char HASS_DISCOVER_SENSOR[] PROGMEM = + ",\"unit_of_meas\":\"%s\",\"%s\"," + "\"frc_upd\":true," + "\"val_tpl\":\"{{value_json['%s']['%s']"; + +const char HASS_DISCOVER_BASE[] PROGMEM = + "{\"name\":\"%s\"," + "\"stat_t\":\"%s\"," + "\"avty_t\":\"%s\"," + "\"pl_avail\":\"" D_ONLINE "\"," + "\"pl_not_avail\":\"" D_OFFLINE "\""; + +const char HASS_DISCOVER_RELAY[] PROGMEM = + ",\"cmd_t\":\"%s\"," + "\"val_tpl\":\"{{value_json.%s}}\"," + "\"pl_off\":\"%s\"," + "\"pl_on\":\"%s\""; + +const char HASS_DISCOVER_BUTTON_TOGGLE[] PROGMEM = + ",\"value_template\":\"{%%if is_state(entity_id,\\\"off\\\")-%%}ON{%%-endif%%}\"," + "\"off_delay\":1"; + +const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = + ",\"value_template\":\"{{value_json.%s}}\"," + "\"frc_upd\":true," + "\"pl_on\":\"%s\"," + "\"pl_off\":\"%s\""; + +const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = + ",\"bri_cmd_t\":\"%s\"," + "\"bri_stat_t\":\"%s\"," + "\"bri_scl\":100," + "\"on_cmd_type\":\"%s\"," + "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; + +const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = + ",\"rgb_cmd_t\":\"%s2\"," + "\"rgb_stat_t\":\"%s\"," + "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; + +const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = + ",\"whit_val_cmd_t\":\"%s\"," + "\"whit_val_stat_t\":\"%s\"," + "\"white_value_scale\":100," + "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; + +const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = + ",\"clr_temp_cmd_t\":\"%s\"," + "\"clr_temp_stat_t\":\"%s\"," + "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; + +const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = + ",\"fx_cmd_t\":\"%s\"," + "\"fx_stat_t\":\"%s\"," + "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," + "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; + +const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = + ",\"json_attributes_topic\":\"%s\"," + "\"unit_of_meas\":\" \"," + "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"," + "\"ic\":\"mdi:information-outline\""; + +const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = + ",\"uniq_id\":\"%s\"," + "\"device\":{\"identifiers\":[\"%06X\"]," + "\"connections\":[[\"mac\",\"%s\"]]," + "\"name\":\"%s\"," + "\"model\":\"%s\"," + "\"sw_version\":\"%s%s\"," + "\"manufacturer\":\"Tasmota\"}"; + +const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = + ",\"uniq_id\":\"%s\"," + "\"device\":{\"identifiers\":[\"%06X\"]," + "\"connections\":[[\"mac\",\"%s\"]]}"; + +uint8_t hass_init_step = 0; +uint8_t hass_mode = 0; +int hass_tele_period = 0; + +void TryResponseAppend_P(const char *format, ...) +{ + va_list args; + va_start(args, format); + char dummy[2]; + int dlen = vsnprintf_P(dummy, 1, format, args); + + int mlen = strlen(mqtt_data); + int slen = sizeof(mqtt_data) - 1 - mlen; + if (dlen >= slen) + { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: MQTT discovery failed due to too long topic or friendly name. " + "Please shorten topic and friendly name. Failed to format(%u/%u):"), + dlen, slen); + va_start(args, format); + vsnprintf_P(log_data, sizeof(log_data), format, args); + AddLog(LOG_LEVEL_ERROR); + } + else + { + va_start(args, format); + vsnprintf_P(mqtt_data + mlen, slen, format, args); + } + va_end(args); +} + +void HAssAnnounceRelayLight(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char stemp3[TOPSZ]; + char unique_id[30]; + bool is_light = false; + bool is_topic_light = false; + + for (uint32_t i = 1; i <= MAX_RELAYS; i++) + { + is_light = ((i == devices_present) && (light_type)); + is_topic_light = Settings.flag.hass_light || is_light; + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), + (is_topic_light) ? "switch" : "light", unique_id); + MqttPublish(stopic, true); + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), + (is_topic_light) ? "light" : "switch", unique_id); + + if (Settings.flag.hass_discovery && (i <= devices_present)) + { + char name[33 + 2]; + char value_template[33]; + char prefix[TOPSZ]; + char *command_topic = stemp1; + char *state_topic = stemp2; + char *availability_topic = stemp3; + + if (i > MAX_FRIENDLYNAMES) + { + snprintf_P(name, sizeof(name), PSTR("%s %d"), SettingsText(SET_FRIENDLYNAME1), i); + } + else + { + snprintf_P(name, sizeof(name), SettingsText(SET_FRIENDLYNAME1 + i - 1)); + } + GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); + GetTopic_P(command_topic, CMND, mqtt_topic, value_template); + GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + +#ifdef USE_LIGHT + if (is_light) + { + char *brightness_command_topic = stemp1; + + GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); + strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic, stemp3); + + if (Light.subtype >= LST_RGB) + { + char *rgb_command_topic = stemp1; + + GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); + + char *effect_command_topic = stemp1; + GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); + } + if (LST_RGBW == Light.subtype) + { + char *white_temp_command_topic = stemp1; + + GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); + } + if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) + { + char *color_temp_command_topic = stemp1; + + GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); + } + } +#endif + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); + } +} + +void HAssAnnounceButtonSwitch(uint8_t device, char *topic, uint8_t present, uint8_t key, uint8_t toggle) +{ + + + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), key ? "SW" : "BTN", device + 1); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); + + if (Settings.flag.hass_discovery && present) + { + char name[33 + 6]; + char value_template[33]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + char jsoname[8]; + + snprintf_P(name, sizeof(name), PSTR("%s %s%d"), SettingsText(SET_FRIENDLYNAME1), key ? "Switch" : "Button", device + 1); + snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key ? "SWITCH" : "BUTTON", device + 1); + GetPowerDevice(value_template, device + 1, sizeof(value_template), + key + Settings.flag.device_index_enable); + GetTopic_P(state_topic, STAT, mqtt_topic, (PSTR("/'%s'"), jsoname)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + + if (toggle) { + if (!key) { + TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE); + } else { + TryResponseAppend_P(",\"value_template\":\"{%%if is_state(entity_id,\\\"on\\\")-%%}OFF{%%-else-%%}ON{%%-endif%%}\""); + } + } else { + TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2), SettingsText(SET_STATE_TXT1)); + } + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSwitches(void) +{ + char sw_topic[TOPSZ]; + + + char *tmp = SettingsText(SET_MQTT_SWITCH_TOPIC); + Format(sw_topic, tmp, sizeof(sw_topic)); + if (!strcmp_P(sw_topic, "0") || strlen(sw_topic) == 0) + { + for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) + { + uint8_t switch_present = 0; + uint8_t toggle = 1; + + if (pin[GPIO_SWT1 + switch_index] < 99) + { + switch_present = 1; + } + + + if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || + Settings.flag3.button_switch_force_local || + !strcmp(mqtt_topic, sw_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), sw_topic)) + { + toggle = 0; + } + HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 1, toggle); + } + } +} + +void HAssAnnounceButtons(void) +{ + char key_topic[TOPSZ]; + + + char *tmp = SettingsText(SET_MQTT_BUTTON_TOPIC); + Format(key_topic, tmp, sizeof(key_topic)); + if (!strcmp_P(key_topic, "0") || strlen(key_topic) == 0) + { + for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) + { + uint8_t button_present = 0; + uint8_t toggle = 1; + + if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) + { + button_present = 1; + } + else + { + if (pin[GPIO_KEY1 + button_index] < 99) + { + button_present = 1; + } + } + + + if (Settings.flag3.button_switch_force_local || + !strcmp(mqtt_topic, key_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) + { + toggle = 0; + } + HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 0, toggle); + } + } +} + +void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, uint8_t subidx) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + mqtt_data[0] = '\0'; + + char subname[20]; + NoAlNumToUnderscore(subname, MultiSubName); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subname); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);; + + if (Settings.flag.hass_discovery) + { + char name[33 + 42]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); + snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_FRIENDLYNAME1), sensorname, MultiSubName); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); + + char jname[32]; + int sensor_index = GetCommandCode(jname, sizeof(jname), subsensortype, kHAssJsonSensorTypes); + if (sensor_index > -1) { + char param1[20]; + GetTextIndexed(param1, sizeof(param1), sensor_index, kHAssJsonSensorUnits); + switch (sensor_index) { + case 0: + snprintf_P(param1, sizeof(param1), PSTR("°%c"),TempUnit()); + break; + case 1: + case 2: + snprintf_P(param1, sizeof(param1), PSTR("%s"), PressureUnit().c_str()); + break; + } + char param2[50]; + GetTextIndexed(param2, sizeof(param2), sensor_index, kHAssJsonSensorDevCla); + TryResponseAppend_P(HASS_DISCOVER_SENSOR, param1, param2, sensorname, subsensortype); + if (subidx) { + TryResponseAppend_P(PSTR("[%d]"), subqty -1); + } + } else { + TryResponseAppend_P(HASS_DISCOVER_SENSOR, " ", "ic\":\"mdi:eye", sensorname, subsensortype); + } + TryResponseAppend_P(PSTR("}}\"}")); + } + MqttPublish(stopic, true); +} + +void HAssAnnounceSensors(void) +{ + uint8_t hass_xsns_index = 0; + bool is_sensor = true; + uint8_t subqty = 0; + do + { + mqtt_data[0] = '\0'; + int tele_period_save = tele_period; + tele_period = 2; + XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); + tele_period = tele_period_save; + + char sensordata[512]; + strlcpy(sensordata, mqtt_data, sizeof(sensordata)); + + if (strlen(sensordata)) + { + sensordata[0] = '{'; + snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); + + + + StaticJsonBuffer<500> jsonBuffer; + JsonObject &root = jsonBuffer.parseObject(sensordata); + if (!root.success()) + { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: jsonBuffer failed to parse '%s'"), sensordata); + continue; + } + for (auto sensor : root) + { + const char *sensorname = sensor.key; + JsonObject &sensors = sensor.value.as(); + if (!sensors.success()) + { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: JsonObject failed to parse '%s'"), sensordata); + continue; + } + for (auto subsensor : sensors) + { + + if (subsensor.value.is()) { + JsonArray& subsensors = subsensor.value.as(); + subqty = subsensors.size(); + char MultiSubName[20]; + for (int i = 1; i <= subqty; i++) { + snprintf_P(MultiSubName, sizeof(MultiSubName), PSTR("%s %d"), subsensor.key, i); + HAssAnnounceSensor(sensorname, subsensor.key, MultiSubName, i, 1); + } + } else { HAssAnnounceSensor(sensorname, subsensor.key, subsensor.key, 0, 0);} + } + } + } + yield(); + } while (hass_xsns_index != 0); +} + +void HAssAnnounceStatusSensor(void) +{ + char stopic[TOPSZ]; + char stemp1[TOPSZ]; + char stemp2[TOPSZ]; + char unique_id[30]; + + + mqtt_data[0] = '\0'; + + + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP.getChipId()); + snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); + + if (Settings.flag.hass_discovery) + { + char name[33 + 7]; + char prefix[TOPSZ]; + char *state_topic = stemp1; + char *availability_topic = stemp2; + + snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_FRIENDLYNAME1)); + GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); + GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); + + Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(), + SettingsText(SET_FRIENDLYNAME1), ModuleName().c_str(), my_version, my_image); + + TryResponseAppend_P(PSTR("}")); + } + MqttPublish(stopic, true); +} + +void HAssPublishStatus(void) +{ + Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," + "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," + "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," + "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," + "\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_CMND_IPADDRESS "\":\"%s\"," + "\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), + my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getSdkVersion(), ModuleName().c_str(), + GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), + Settings.bootcount, Settings.save_flag, WiFi.localIP().toString().c_str(), + WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); +} + +void HAssDiscovery(void) +{ + + if (Settings.flag.hass_discovery) + { + Settings.flag.mqtt_response = 0; + Settings.flag.decimal_text = 1; + Settings.flag3.hass_tele_on_power = 1; + Settings.light_scheme = 0; + } + + if (Settings.flag.hass_discovery || (1 == hass_mode)) + { + + HAssAnnounceRelayLight(); + + + HAssAnnounceButtons(); + + + HAssAnnounceSwitches(); + + + HAssAnnounceSensors(); + + + HAssAnnounceStatusSensor(); + } +} + +void HAssDiscover(void) +{ + hass_mode = 1; + hass_init_step = 1; +} + +void HAssAnyKey(void) +{ + if (!Settings.flag.hass_discovery) + { + return; + } + + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; + uint32_t device = XdrvMailbox.payload & 0xFF; + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; + + char scommand[CMDSZ]; + snprintf_P(scommand, sizeof(scommand), PSTR("%s%d"), (key) ? "SWITCH" : "BUTTON", device); + char stopic[TOPSZ]; + + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P(S_JSON_COMMAND_SVALUE, PSTR(D_RSLT_STATE), GetStateText(state)); + MqttPublish(stopic); +} + + + + + +bool Xdrv12(uint8_t function) +{ + bool result = false; + + if (Settings.flag.mqtt_enabled) + { + switch (function) + { + case FUNC_EVERY_SECOND: + if (hass_init_step) + { + hass_init_step--; + if (!hass_init_step) + { + HAssDiscovery(); + } + } + else if (Settings.flag.hass_discovery && Settings.tele_period) + { + hass_tele_period++; + if (hass_tele_period >= Settings.tele_period) + { + hass_tele_period = 0; + + mqtt_data[0] = '\0'; + HAssPublishStatus(); + } + } + break; + case FUNC_ANY_KEY: + HAssAnyKey(); + break; + case FUNC_MQTT_INIT: + hass_mode = 0; + hass_init_step = 2; + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_13_display.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_13_display.ino" +#if defined(USE_I2C) || defined(USE_SPI) +#ifdef USE_DISPLAY + +#define XDRV_13 13 + +#include +#include + +Renderer *renderer; + +enum ColorType { COLOR_BW, COLOR_COLOR }; + +#ifndef MAXBUTTONS +#define MAXBUTTONS 16 +#endif + +#ifdef USE_TOUCH_BUTTONS +VButton *buttons[MAXBUTTONS]; +#endif + + + +uint16_t fg_color = 1; +uint16_t bg_color = 0; +uint8_t color_type = COLOR_BW; +uint8_t auto_draw=1; + +const uint8_t DISPLAY_MAX_DRIVERS = 16; +const uint8_t DISPLAY_MAX_COLS = 44; +const uint8_t DISPLAY_MAX_ROWS = 32; + +const uint8_t DISPLAY_LOG_ROWS = 32; + +#define D_PRFX_DISPLAY "Display" +#define D_CMND_DISP_ADDRESS "Address" +#define D_CMND_DISP_COLS "Cols" +#define D_CMND_DISP_DIMMER "Dimmer" +#define D_CMND_DISP_MODE "Mode" +#define D_CMND_DISP_MODEL "Model" +#define D_CMND_DISP_REFRESH "Refresh" +#define D_CMND_DISP_ROWS "Rows" +#define D_CMND_DISP_SIZE "Size" +#define D_CMND_DISP_FONT "Font" +#define D_CMND_DISP_ROTATE "Rotate" +#define D_CMND_DISP_TEXT "Text" +#define D_CMND_DISP_WIDTH "Width" +#define D_CMND_DISP_HEIGHT "Height" + +enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND, + FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER, + FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_DRAW_FRAME, + FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_LINE, + FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE, + FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE, + FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING, FUNC_DISPLAY_ONOFF }; + +enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; + +const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" + "|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" + D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" + D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; + +void (* const DisplayCommand[])(void) PROGMEM = { + &CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh, + &CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont, + &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress }; + +char *dsp_str; + +uint16_t dsp_x; +uint16_t dsp_y; +uint16_t dsp_x2; +uint16_t dsp_y2; +uint16_t dsp_rad; +uint16_t dsp_color; +int16_t dsp_len; +int16_t disp_xpos = 0; +int16_t disp_ypos = 0; + +uint8_t disp_power = 0; +uint8_t disp_device = 0; +uint8_t disp_refresh = 1; +uint8_t disp_autodraw = 1; +uint8_t dsp_init; +uint8_t dsp_font; +uint8_t dsp_flag; +uint8_t dsp_on; + +#ifdef USE_DISPLAY_MODES1TO5 + +char **disp_log_buffer; +char **disp_screen_buffer; +char disp_temp[2]; +char disp_pres[5]; + +uint8_t disp_log_buffer_cols = 0; +uint8_t disp_log_buffer_idx = 0; +uint8_t disp_log_buffer_ptr = 0; +uint8_t disp_screen_buffer_cols = 0; +uint8_t disp_screen_buffer_rows = 0; +bool disp_subscribed = false; + +#endif + + + +void DisplayInit(uint8_t mode) +{ + if (renderer) { + renderer->DisplayInit(mode, Settings.display_size, Settings.display_rotate, Settings.display_font); + } + else { + dsp_init = mode; + XdspCall(FUNC_DISPLAY_INIT); + } +} + +void DisplayClear(void) +{ + XdspCall(FUNC_DISPLAY_CLEAR); +} + +void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_len = len; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_HLINE); +} + +void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_len = len; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_VLINE); +} + +void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_LINE); +} + +void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_rad = rad; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_CIRCLE); +} + +void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_rad = rad; + dsp_color = color; + XdspCall(FUNC_DISPLAY_FILL_CIRCLE); +} + +void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_DRAW_RECTANGLE); +} + +void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) +{ + dsp_x = x; + dsp_y = y; + dsp_x2 = x2; + dsp_y2 = y2; + dsp_color = color; + XdspCall(FUNC_DISPLAY_FILL_RECTANGLE); +} + +void DisplayDrawFrame(void) +{ + XdspCall(FUNC_DISPLAY_DRAW_FRAME); +} + +void DisplaySetSize(uint8_t size) +{ + Settings.display_size = size &3; + XdspCall(FUNC_DISPLAY_TEXT_SIZE); +} + +void DisplaySetFont(uint8_t font) +{ + Settings.display_font = font &3; + XdspCall(FUNC_DISPLAY_FONT_SIZE); +} + +void DisplaySetRotation(uint8_t rotation) +{ + Settings.display_rotate = rotation &3; + XdspCall(FUNC_DISPLAY_ROTATION); +} + +void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + dsp_x = x; + dsp_y = y; + dsp_str = str; + dsp_color = color; + dsp_flag = flag; + XdspCall(FUNC_DISPLAY_DRAW_STRING); +} + +void DisplayOnOff(uint8_t on) +{ + dsp_on = on; + XdspCall(FUNC_DISPLAY_ONOFF); +} + + + + +uint8_t fatoiv(char *cp,float *res) { + uint8_t index=0; + *res=CharToFloat(cp); + while (*cp) { + if ((*cp>='0' && *cp<='9') || (*cp=='-') || (*cp=='.')) { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +uint8_t atoiv(char *cp, int16_t *res) +{ + uint8_t index = 0; + *res = atoi(cp); + while (*cp) { + if ((*cp>='0' && *cp<='9') || (*cp=='-')) { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +uint8_t atoiV(char *cp, uint16_t *res) +{ + uint8_t index = 0; + *res = atoi(cp); + while (*cp) { + if (*cp>='0' && *cp<='9') { + cp++; + index++; + } else { + break; + } + } + return index; +} + + +void alignright(char *string) { + uint16_t slen=strlen(string); + uint16_t len=slen; + while (len) { + + if (string[len-1]!=' ') { + break; + } + len--; + } + uint16_t diff=slen-len; + if (diff>0) { + + memmove(&string[diff],string,len); + memset(string,' ',diff); + } +} + +char *get_string(char *buff,uint8_t len,char *cp) { +uint8_t index=0; + while (*cp!=':') { + buff[index]=*cp++; + index++; + if (index>=len) break; + } + buff[index]=0; + cp++; + return cp; +} + +#define ESCAPE_CHAR '~' + + +uint32_t decode_te(char *line) { + uint32_t skip = 0; + char sbuf[3],*cp; + while (*line) { + if (*line==ESCAPE_CHAR) { + cp=line+1; + if (*cp!=0 && *cp==ESCAPE_CHAR) { + + memmove(cp,cp+1,strlen(cp)); + skip++; + } else { + + if (strlen(cp)<2) { + + return skip; + } + + sbuf[0]=*(cp); + sbuf[1]=*(cp+1); + sbuf[2]=0; + *line=strtol(sbuf,0,16); + + memmove(cp,cp+2,strlen(cp)-1); + skip += 2; + } + } + line++; + } + return skip; +} + + + +#define DISPLAY_BUFFER_COLS 128 + +void DisplayText(void) +{ + uint8_t lpos; + uint8_t escape = 0; + uint8_t var; + int16_t lin = 0; + int16_t col = 0; + int16_t fill = 0; + int16_t temp; + int16_t temp1; + float ftemp; + + char linebuf[DISPLAY_BUFFER_COLS]; + char *dp = linebuf; + char *cp = XdrvMailbox.data; + + memset(linebuf, ' ', sizeof(linebuf)); + linebuf[sizeof(linebuf)-1] = 0; + *dp = 0; + + while (*cp) { + if (!escape) { + + if (*cp == '[') { + escape = 1; + cp++; + + if ((uint32_t)dp - (uint32_t)linebuf) { + if (!fill) { *dp = 0; } + if (col > 0 && lin > 0) { + + if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); + else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); + } else { + + if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + } + memset(linebuf, ' ', sizeof(linebuf)); + linebuf[sizeof(linebuf)-1] = 0; + dp = linebuf; + } + } else { + + if (dp < (linebuf + DISPLAY_BUFFER_COLS)) { *dp++ = *cp++; } + } + } else { + + if (*cp == ']') { + escape = 0; + cp++; + } else { + + switch (*cp++) { + case 'z': + + if (!renderer) DisplayClear(); + else renderer->fillScreen(bg_color); + disp_xpos = 0; + disp_ypos = 0; + col = 0; + lin = 0; + break; + case 'i': + + DisplayInit(DISPLAY_INIT_PARTIAL); + break; + case 'I': + + DisplayInit(DISPLAY_INIT_FULL); + break; + case 'o': + if (!renderer) { + DisplayOnOff(0); + } else { + renderer->DisplayOnff(0); + } + break; + case 'O': + if (!renderer) { + DisplayOnOff(1); + } else { + renderer->DisplayOnff(1); + } + break; + case 'x': + + var = atoiv(cp, &disp_xpos); + cp += var; + break; + case 'y': + + var = atoiv(cp, &disp_ypos); + cp += var; + break; + case 'l': + + var = atoiv(cp, &lin); + cp += var; + + break; + case 'c': + + var = atoiv(cp, &col); + cp += var; + + break; + case 'C': + + if (*cp=='i') { + + cp++; + var = atoiv(cp, &temp); + if (renderer) ftemp=renderer->GetColorFromIndex(temp); + } else { + + var = fatoiv(cp,&ftemp); + } + fg_color=ftemp; + cp += var; + if (renderer) renderer->setTextColor(fg_color,bg_color); + break; + case 'B': + + if (*cp=='i') { + + cp++; + var = atoiv(cp, &temp); + if (renderer) ftemp=renderer->GetColorFromIndex(temp); + } else { + var = fatoiv(cp,&ftemp); + } + bg_color=ftemp; + cp += var; + if (renderer) renderer->setTextColor(fg_color,bg_color); + break; + case 'p': + + var = atoiv(cp, &fill); + cp += var; + linebuf[fill] = 0; + break; +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) + case 'P': + { char *ep=strchr(cp,':'); + if (ep) { + *ep=0; + ep++; + Draw_RGB_Bitmap(cp,disp_xpos,disp_ypos); + cp=ep; + } + } + break; +#endif + case 'h': + + var = atoiv(cp, &temp); + cp += var; + if (temp < 0) { + if (renderer) renderer->writeFastHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); + else DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); + } else { + if (renderer) renderer->writeFastHLine(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawHLine(disp_xpos, disp_ypos, temp, fg_color); + } + disp_xpos += temp; + break; + case 'v': + + var = atoiv(cp, &temp); + cp += var; + if (temp < 0) { + if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); + else DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); + } else { + if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawVLine(disp_xpos, disp_ypos, temp, fg_color); + } + disp_ypos += temp; + break; + case 'L': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->writeLine(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, fg_color); + disp_xpos += temp; + disp_ypos += temp1; + break; + case 'k': + + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->drawCircle(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawCircle(disp_xpos, disp_ypos, temp, fg_color); + break; + case 'K': + + var = atoiv(cp, &temp); + cp += var; + if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color); + else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color); + break; + case 'r': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->drawRect(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); + break; + case 'R': + + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + if (renderer) renderer->fillRect(disp_xpos, disp_ypos, temp, temp1, fg_color); + else DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); + break; + case 'u': + + { int16_t rad; + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + cp++; + var = atoiv(cp, &rad); + cp += var; + if (renderer) renderer->drawRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); + + } + break; + case 'U': + + { int16_t rad; + var = atoiv(cp, &temp); + cp += var; + cp++; + var = atoiv(cp, &temp1); + cp += var; + cp++; + var = atoiv(cp, &rad); + cp += var; + if (renderer) renderer->fillRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); + + } + break; + + case 't': + if (*cp=='S') { + cp++; + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { + snprintf_P(dp, 9, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + dp += 8; + } + } else { + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -5) { + snprintf_P(dp, 6, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute); + dp += 5; + } + } + break; + case 'T': + if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { + snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year%2000); + dp += 8; + } + break; + case 'd': + + if (renderer) renderer->Updateframe(); + else DisplayDrawFrame(); + break; + case 'D': + + auto_draw=*cp&3; + if (renderer) renderer->setDrawMode(auto_draw>>1); + cp += 1; + break; + case 's': + + if (renderer) renderer->setTextSize(*cp&7); + else DisplaySetSize(*cp&3); + cp += 1; + break; + case 'f': + + if (renderer) renderer->setTextFont(*cp&7); + else DisplaySetFont(*cp&7); + cp += 1; + break; + case 'a': + + if (renderer) renderer->setRotation(*cp&3); + else DisplaySetRotation(*cp&3); + cp+=1; + break; + +#ifdef USE_GRAPH + case 'G': + + if (*cp=='d') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + var=atoiv(cp,&temp1); + cp+=var; + RedrawGraph(temp,temp1); + break; + } +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) + if (*cp=='s') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + + char bbuff[128]; + cp=get_string(bbuff,sizeof(bbuff),cp); + Save_graph(temp,bbuff); + break; + } + if (*cp=='r') { + cp++; + var=atoiv(cp,&temp); + cp+=var; + cp++; + + char bbuff[128]; + cp=get_string(bbuff,sizeof(bbuff),cp); + Restore_graph(temp,bbuff); + break; + } +#endif + { int16_t num,gxp,gyp,gxs,gys,dec,icol; + float ymin,ymax; + var=atoiv(cp,&num); + cp+=var; + cp++; + var=atoiv(cp,&gxp); + cp+=var; + cp++; + var=atoiv(cp,&gyp); + cp+=var; + cp++; + var=atoiv(cp,&gxs); + cp+=var; + cp++; + var=atoiv(cp,&gys); + cp+=var; + cp++; + var=atoiv(cp,&dec); + cp+=var; + cp++; + var=fatoiv(cp,&ymin); + cp+=var; + cp++; + var=fatoiv(cp,&ymax); + cp+=var; + if (color_type==COLOR_COLOR) { + + cp++; + var=atoiv(cp,&icol); + cp+=var; + } else { + icol=0; + } + DefineGraph(num,gxp,gyp,gxs,gys,dec,ymin,ymax,icol); + } + break; + case 'g': + { float temp; + int16_t num; + var=atoiv(cp,&num); + cp+=var; + cp++; + var=fatoiv(cp,&temp); + cp+=var; + AddValue(num,temp); + } + break; +#endif + +#ifdef USE_AWATCH + case 'w': + var = atoiv(cp, &temp); + cp += var; + DrawAClock(temp); + break; +#endif + +#ifdef USE_TOUCH_BUTTONS + case 'b': + { int16_t num,gxp,gyp,gxs,gys,outline,fill,textcolor,textsize; + var=atoiv(cp,&num); + cp+=var; + cp++; + uint8_t bflags=num>>8; + num=num%MAXBUTTONS; + var=atoiv(cp,&gxp); + cp+=var; + cp++; + var=atoiv(cp,&gyp); + cp+=var; + cp++; + var=atoiv(cp,&gxs); + cp+=var; + cp++; + var=atoiv(cp,&gys); + cp+=var; + cp++; + var=atoiv(cp,&outline); + cp+=var; + cp++; + var=atoiv(cp,&fill); + cp+=var; + cp++; + var=atoiv(cp,&textcolor); + cp+=var; + cp++; + var=atoiv(cp,&textsize); + cp+=var; + cp++; + + char bbuff[32]; + cp=get_string(bbuff,sizeof(bbuff),cp); + + if (buttons[num]) { + delete buttons[num]; + } + if (renderer) { + buttons[num]= new VButton(); + if (buttons[num]) { + buttons[num]->vpower=bflags; + buttons[num]->initButtonUL(renderer,gxp,gyp,gxs,gys,renderer->GetColorFromIndex(outline),\ + renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); + if (!bflags) { + + buttons[num]->xdrawButton(bitRead(power,num)); + } else { + + buttons[num]->vpower&=0x7f; + buttons[num]->xdrawButton(buttons[num]->vpower&0x80); + } + } + } + } + break; +#endif + default: + + Response_P(PSTR("Unknown Escape")); + goto exit; + break; + } + } + } + } + exit: + + dp -= decode_te(linebuf); + if ((uint32_t)dp - (uint32_t)linebuf) { + if (!fill) { + *dp = 0; + } else { + linebuf[abs(fill)] = 0; + } + if (fill<0) { + + alignright(linebuf); + } + if (col > 0 && lin > 0) { + + if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); + else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); + } else { + + if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); + } + } + + if (auto_draw&1) { + if (renderer) renderer->Updateframe(); + else DisplayDrawFrame(); + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void DisplayClearScreenBuffer(void) +{ + if (disp_screen_buffer_cols) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + memset(disp_screen_buffer[i], 0, disp_screen_buffer_cols); + } + } +} + +void DisplayFreeScreenBuffer(void) +{ + if (disp_screen_buffer != nullptr) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + if (disp_screen_buffer[i] != nullptr) { free(disp_screen_buffer[i]); } + } + free(disp_screen_buffer); + disp_screen_buffer_cols = 0; + disp_screen_buffer_rows = 0; + } +} + +void DisplayAllocScreenBuffer(void) +{ + if (!disp_screen_buffer_cols) { + disp_screen_buffer_rows = Settings.display_rows; + disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); + if (disp_screen_buffer != nullptr) { + for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { + disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); + if (disp_screen_buffer[i] == nullptr) { + DisplayFreeScreenBuffer(); + break; + } + } + } + if (disp_screen_buffer != nullptr) { + disp_screen_buffer_cols = Settings.display_cols[0] +1; + DisplayClearScreenBuffer(); + } + } +} + +void DisplayReAllocScreenBuffer(void) +{ + DisplayFreeScreenBuffer(); + DisplayAllocScreenBuffer(); +} + +void DisplayFillScreen(uint32_t line) +{ + uint32_t len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]); + if (len) { + memset(disp_screen_buffer[line] + strlen(disp_screen_buffer[line]), 0x20, len); + disp_screen_buffer[line][disp_screen_buffer_cols -1] = 0; + } +} + + + +void DisplayClearLogBuffer(void) +{ + if (disp_log_buffer_cols) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + memset(disp_log_buffer[i], 0, disp_log_buffer_cols); + } + } +} + +void DisplayFreeLogBuffer(void) +{ + if (disp_log_buffer != nullptr) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + if (disp_log_buffer[i] != nullptr) { free(disp_log_buffer[i]); } + } + free(disp_log_buffer); + disp_log_buffer_cols = 0; + } +} + +void DisplayAllocLogBuffer(void) +{ + if (!disp_log_buffer_cols) { + disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); + if (disp_log_buffer != nullptr) { + for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { + disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); + if (disp_log_buffer[i] == nullptr) { + DisplayFreeLogBuffer(); + break; + } + } + } + if (disp_log_buffer != nullptr) { + disp_log_buffer_cols = Settings.display_cols[0] +1; + DisplayClearLogBuffer(); + } + } +} + +void DisplayReAllocLogBuffer(void) +{ + DisplayFreeLogBuffer(); + DisplayAllocLogBuffer(); +} + +void DisplayLogBufferAdd(char* txt) +{ + if (disp_log_buffer_cols) { + strlcpy(disp_log_buffer[disp_log_buffer_idx], txt, disp_log_buffer_cols); + disp_log_buffer_idx++; + if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) { disp_log_buffer_idx = 0; } + } +} + +char* DisplayLogBuffer(char temp_code) +{ + char* result = nullptr; + if (disp_log_buffer_cols) { + if (disp_log_buffer_idx != disp_log_buffer_ptr) { + result = disp_log_buffer[disp_log_buffer_ptr]; + disp_log_buffer_ptr++; + if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; } + + char *pch = strchr(result, '~'); + if (pch != nullptr) { result[pch - result] = temp_code; } + } + } + return result; +} + +void DisplayLogBufferInit(void) +{ + if (Settings.display_mode) { + disp_log_buffer_idx = 0; + disp_log_buffer_ptr = 0; + disp_refresh = Settings.display_refresh; + + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); + snprintf_P(disp_pres, sizeof(disp_pres), PressureUnit().c_str()); + + DisplayReAllocLogBuffer(); + + char buffer[40]; + snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), my_version, my_image); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); + DisplayLogBufferAdd(buffer); + + snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active)); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str()); + DisplayLogBufferAdd(buffer); + if (!global_state.wifi_down) { + snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), WiFi.localIP().toString().c_str()); + DisplayLogBufferAdd(buffer); + snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI())); + DisplayLogBufferAdd(buffer); + } + } +} + + + + + +enum SensorQuantity { + JSON_TEMPERATURE, + JSON_HUMIDITY, JSON_LIGHT, JSON_NOISE, JSON_AIRQUALITY, + JSON_PRESSURE, JSON_PRESSUREATSEALEVEL, + JSON_ILLUMINANCE, + JSON_GAS, + JSON_YESTERDAY, JSON_TOTAL, JSON_TODAY, + JSON_PERIOD, + JSON_POWERFACTOR, JSON_COUNTER, JSON_ANALOG_INPUT, JSON_UV_LEVEL, + JSON_CURRENT, + JSON_VOLTAGE, + JSON_POWERUSAGE, + JSON_CO2, + JSON_FREQUENCY }; +const char kSensorQuantity[] PROGMEM = + D_JSON_TEMPERATURE "|" + D_JSON_HUMIDITY "|" D_JSON_LIGHT "|" D_JSON_NOISE "|" D_JSON_AIRQUALITY "|" + D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" + D_JSON_ILLUMINANCE "|" + D_JSON_GAS "|" + D_JSON_YESTERDAY "|" D_JSON_TOTAL "|" D_JSON_TODAY "|" + D_JSON_PERIOD "|" + D_JSON_POWERFACTOR "|" D_JSON_COUNTER "|" D_JSON_ANALOG_INPUT "|" D_JSON_UV_LEVEL "|" + D_JSON_CURRENT "|" + D_JSON_VOLTAGE "|" + D_JSON_POWERUSAGE "|" + D_JSON_CO2 "|" + D_JSON_FREQUENCY ; + +void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value) +{ + char quantity[TOPSZ]; + char buffer[Settings.display_cols[0] +1]; + char spaces[Settings.display_cols[0]]; + char source[Settings.display_cols[0] - Settings.display_cols[1]]; + char svalue[Settings.display_cols[1] +1]; + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("DisplayJsonValue")); +#endif + + memset(spaces, 0x20, sizeof(spaces)); + spaces[sizeof(spaces) -1] = '\0'; + snprintf_P(source, sizeof(source), PSTR("%s%s%s%s"), topic, (strlen(topic))?"/":"", mkey, spaces); + + int quantity_code = GetCommandCode(quantity, sizeof(quantity), mkey, kSensorQuantity); + if ((-1 == quantity_code) || !strcmp_P(mkey, S_RSLT_POWER)) { + return; + } + if (JSON_TEMPERATURE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s~%s"), value, disp_temp); + } + else if ((quantity_code >= JSON_HUMIDITY) && (quantity_code <= JSON_AIRQUALITY)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s%%"), value); + } + else if ((quantity_code >= JSON_PRESSURE) && (quantity_code <= JSON_PRESSUREATSEALEVEL)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s%s"), value, disp_pres); + } + else if (JSON_ILLUMINANCE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_LUX), value); + } + else if (JSON_GAS == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOOHM), value); + } + else if ((quantity_code >= JSON_YESTERDAY) && (quantity_code <= JSON_TODAY)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOWATTHOUR), value); + } + else if (JSON_PERIOD == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATTHOUR), value); + } + else if ((quantity_code >= JSON_POWERFACTOR) && (quantity_code <= JSON_UV_LEVEL)) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s"), value); + } + else if (JSON_CURRENT == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_AMPERE), value); + } + else if (JSON_VOLTAGE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_VOLT), value); + } + else if (JSON_POWERUSAGE == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATT), value); + } + else if (JSON_CO2 == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value); + } + else if (JSON_FREQUENCY == quantity_code) { + snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_HERTZ), value); + } + snprintf_P(buffer, sizeof(buffer), PSTR("%s %s"), source, svalue); + + + + DisplayLogBufferAdd(buffer); +} + +void DisplayAnalyzeJson(char *topic, char *json) +{ +# 1145 "S:/Development/Tasmota/tasmota/xdrv_13_display.ino" + String jsonStr = json; + + StaticJsonBuffer<1024> jsonBuf; + JsonObject &root = jsonBuf.parseObject(jsonStr); + if (root.success()) { + + const char *unit; + unit = root[D_JSON_TEMPERATURE_UNIT]; + if (unit) { + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), unit); + } + unit = root[D_JSON_PRESSURE_UNIT]; + if (unit) { + snprintf_P(disp_pres, sizeof(disp_pres), PSTR("%s"), unit); + } + + for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) { + JsonVariant value = it->value; + if (value.is()) { + JsonObject& Object2 = value; + for (JsonObject::iterator it2 = Object2.begin(); it2 != Object2.end(); ++it2) { + JsonVariant value2 = it2->value; + if (value2.is()) { + JsonObject& Object3 = value2; + for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) { + const char* value = it3->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it3->key, value); + } + } + } else { + const char* value = it2->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it2->key, value); + } + } + } + } else { + const char* value = it->value; + if (value != nullptr) { + DisplayJsonValue(topic, it->key, it->key, value); + } + } + } + } +} + +void DisplayMqttSubscribe(void) +{ + + + + + + + if (Settings.display_model && (Settings.display_mode &0x04)) { + + char stopic[TOPSZ]; + char ntopic[TOPSZ]; + + ntopic[0] = '\0'; + strlcpy(stopic, SettingsText(SET_MQTT_FULLTOPIC), sizeof(stopic)); + char *tp = strtok(stopic, "/"); + while (tp != nullptr) { + if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { + break; + } + strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); + tp = strtok(nullptr, "/"); + } + strncat(ntopic, SettingsText(SET_MQTTPREFIX3), sizeof(ntopic) - strlen(ntopic) -1); + strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); + MqttSubscribe(ntopic); + disp_subscribed = true; + } else { + disp_subscribed = false; + } +} + +bool DisplayMqttData(void) +{ + if (disp_subscribed) { + char stopic[TOPSZ]; + + snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), SettingsText(SET_MQTTPREFIX3)); + char *tp = strstr(XdrvMailbox.topic, stopic); + if (tp) { + if (Settings.display_mode &0x04) { + tp = tp + strlen(stopic); + char *topic = strtok(tp, "/"); + DisplayAnalyzeJson(topic, XdrvMailbox.data); + } + return true; + } + } + return false; +} + +void DisplayLocalSensor(void) +{ + if ((Settings.display_mode &0x02) && (0 == tele_period)) { + char no_topic[1] = { 0 }; + + DisplayAnalyzeJson(no_topic, mqtt_data); + } +} + +#endif + + + + + +void DisplayInitDriver(void) +{ + XdspCall(FUNC_DISPLAY_INIT_DRIVER); + + if (renderer) { + renderer->setTextFont(Settings.display_font); + renderer->setTextSize(Settings.display_size); + } + + + + + if (Settings.display_model) { + devices_present++; + disp_device = devices_present; + +#ifndef USE_DISPLAY_MODES1TO5 + Settings.display_mode = 0; +#else + DisplayLogBufferInit(); +#endif + } +} + +void DisplaySetPower(void) +{ + disp_power = bitRead(XdrvMailbox.index, disp_device -1); + + + + if (Settings.display_model) { + if (!renderer) { + XdspCall(FUNC_DISPLAY_POWER); + } else { + renderer->DisplayOnff(disp_power); + } + } +} + + + + + +void CmndDisplay(void) +{ + Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\"" + D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" + D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), + Settings.display_model, Settings.display_width, Settings.display_height, + Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, + Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); +} + +void CmndDisplayModel(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) { + uint32_t last_display_model = Settings.display_model; + Settings.display_model = XdrvMailbox.payload; + if (XdspCall(FUNC_DISPLAY_MODEL)) { + restart_flag = 2; + } else { + Settings.display_model = last_display_model; + } + } + ResponseCmndNumber(Settings.display_model); +} + +void CmndDisplayWidth(void) +{ + if (XdrvMailbox.payload > 0) { + if (XdrvMailbox.payload != Settings.display_width) { + Settings.display_width = XdrvMailbox.payload; + restart_flag = 2; + } + } + ResponseCmndNumber(Settings.display_width); +} + +void CmndDisplayHeight(void) +{ + if (XdrvMailbox.payload > 0) { + if (XdrvMailbox.payload != Settings.display_height) { + Settings.display_height = XdrvMailbox.payload; + restart_flag = 2; + } + } + ResponseCmndNumber(Settings.display_height); +} + +void CmndDisplayMode(void) +{ +#ifdef USE_DISPLAY_MODES1TO5 + + + + + + + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { + uint32_t last_display_mode = Settings.display_mode; + Settings.display_mode = XdrvMailbox.payload; + + if (disp_subscribed != (Settings.display_mode &0x04)) { + restart_flag = 2; + } else { + if (last_display_mode && !Settings.display_mode) { + DisplayInit(DISPLAY_INIT_MODE); + if (renderer) renderer->fillScreen(bg_color); + else DisplayClear(); + } else { + DisplayLogBufferInit(); + DisplayInit(DISPLAY_INIT_MODE); + } + } + } +#endif + ResponseCmndNumber(Settings.display_mode); +} + +void CmndDisplayDimmer(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; + if (Settings.display_dimmer && !(disp_power)) { + ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY); + } + else if (!Settings.display_dimmer && disp_power) { + ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); + } + if (renderer) renderer->dim(Settings.display_dimmer); + } + ResponseCmndNumber(Settings.display_dimmer); +} + +void CmndDisplaySize(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { + Settings.display_size = XdrvMailbox.payload; + if (renderer) renderer->setTextSize(Settings.display_size); + else DisplaySetSize(Settings.display_size); + } + ResponseCmndNumber(Settings.display_size); +} + +void CmndDisplayFont(void) +{ + if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) { + Settings.display_font = XdrvMailbox.payload; + if (renderer) renderer->setTextFont(Settings.display_font); + else DisplaySetFont(Settings.display_font); + } + ResponseCmndNumber(Settings.display_font); +} + +void CmndDisplayRotate(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { + if (Settings.display_rotate != XdrvMailbox.payload) { +# 1428 "S:/Development/Tasmota/tasmota/xdrv_13_display.ino" + Settings.display_rotate = XdrvMailbox.payload; + DisplayInit(DISPLAY_INIT_MODE); +#ifdef USE_DISPLAY_MODES1TO5 + DisplayLogBufferInit(); +#endif + } + } + ResponseCmndNumber(Settings.display_rotate); +} + +void CmndDisplayText(void) +{ + if (disp_device && XdrvMailbox.data_len > 0) { +#ifndef USE_DISPLAY_MODES1TO5 + DisplayText(); +#else + if (!Settings.display_mode) { + DisplayText(); + } else { + DisplayLogBufferAdd(XdrvMailbox.data); + } +#endif + ResponseCmndChar(XdrvMailbox.data); + } +} + +void CmndDisplayAddress(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { + Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]); + } +} + +void CmndDisplayRefresh(void) +{ + if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { + Settings.display_refresh = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.display_refresh); +} + +void CmndDisplayColumns(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { + Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload; +#ifdef USE_DISPLAY_MODES1TO5 + if (1 == XdrvMailbox.index) { + DisplayLogBufferInit(); + DisplayReAllocScreenBuffer(); + } +#endif + } + ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]); + } +} + +void CmndDisplayRows(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { + Settings.display_rows = XdrvMailbox.payload; +#ifdef USE_DISPLAY_MODES1TO5 + DisplayLogBufferInit(); + DisplayReAllocScreenBuffer(); +#endif + } + ResponseCmndNumber(Settings.display_rows); +} + + + + + +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) +void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { + if (!renderer) return; + + + File fp; + fp=SD.open(file,FILE_READ); + if (!fp) return; + uint16_t xsize; + fp.read((uint8_t*)&xsize,2); + uint16_t ysize; + fp.read((uint8_t*)&ysize,2); + +#if 1 +#define XBUFF 128 + uint16_t xdiv=xsize/XBUFF; + renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); + for(int16_t j=0; j=2) renderer->pushColors(rgb,len/2,true); + } + OsWatchLoop(); + } + renderer->setAddrWindow(0,0,0,0); +#else + for(int16_t j=0; jwritePixel(xp+i,yp,rgb); + } + delay(0); + OsWatchLoop(); + yp++; + } +#endif + fp.close(); +} +#endif + +#ifdef USE_AWATCH +#define MINUTE_REDUCT 4 + +#ifndef pi +#define pi 3.14159265359 +#endif + + +void DrawAClock(uint16_t rad) { + if (!renderer) return; + float frad=rad; + uint16_t hred=frad/3.0; + renderer->fillCircle(disp_xpos, disp_ypos, rad, bg_color); + renderer->drawCircle(disp_xpos, disp_ypos, rad, fg_color); + renderer->fillCircle(disp_xpos, disp_ypos, 4, fg_color); + for (uint8_t count=0; count<60; count+=5) { + float p1=((float)count*(pi/30)-(pi/2)); + uint8_t len; + if ((count%15)==0) { + len=4; + } else { + len=2; + } + renderer->writeLine(disp_xpos+((float)(rad-len)*cosf(p1)), disp_ypos+((float)(rad-len)*sinf(p1)), disp_xpos+(frad*cosf(p1)), disp_ypos+(frad*sinf(p1)), fg_color); + } + + + float hour=((float)RtcTime.hour*60.0+(float)RtcTime.minute)/60.0; + float temp=(hour*(pi/6.0)-(pi/2.0)); + renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-hred)*cosf(temp),disp_ypos+(frad-hred)*sinf(temp), fg_color); + + + temp=((float)RtcTime.minute*(pi/30.0)-(pi/2.0)); + renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-MINUTE_REDUCT)*cosf(temp),disp_ypos+(frad-MINUTE_REDUCT)*sinf(temp), fg_color); +} +#endif + + +#ifdef USE_GRAPH + +typedef union { + uint8_t data; + struct { + uint8_t overlay : 1; + uint8_t draw : 1; + uint8_t nu3 : 1; + uint8_t nu4 : 1; + uint8_t nu5 : 1; + uint8_t nu6 : 1; + uint8_t nu7 : 1; + uint8_t nu8 : 1; + }; +} GFLAGS; + +struct GRAPH { + uint16_t xp; + uint16_t yp; + uint16_t xs; + uint16_t ys; + float ymin; + float ymax; + float range; + uint32_t x_time; + uint32_t last_ms; + uint32_t last_ms_redrawn; + int16_t decimation; + uint16_t dcnt; + uint32_t summ; + uint16_t xcnt; + uint8_t *values; + uint8_t xticks; + uint8_t yticks; + uint8_t last_val; + uint8_t color_index; + GFLAGS flags; +}; + + +struct GRAPH *graph[NUM_GRAPHS]; + +#define TICKLEN 4 +void ClrGraph(uint16_t num) { + struct GRAPH *gp=graph[num]; + + uint16_t xticks=gp->xticks; + uint16_t yticks=gp->yticks; + uint16_t count; + + + if (gp->flags.overlay) return; + + renderer->fillRect(gp->xp+1,gp->yp+1,gp->xs-2,gp->ys-2,bg_color); + + if (xticks) { + float cxp=gp->xp,xd=(float)gp->xs/(float)xticks; + for (count=0; countwriteFastVLine(cxp,gp->yp+gp->ys-TICKLEN,TICKLEN,fg_color); + cxp+=xd; + } + } + if (yticks) { + if (gp->ymin<0 && gp->ymax>0) { + + float cxp=0; + float czp=gp->yp+(gp->ymax/gp->range); + while (cxpxs) { + renderer->writeFastHLine(gp->xp+cxp,czp,2,fg_color); + cxp+=6.0; + } + + float cyp=0,yd=gp->ys/yticks; + for (count=0; countgp->yp) { + renderer->writeFastHLine(gp->xp,czp-cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp-cyp,TICKLEN,fg_color); + } + if ((czp+cyp)<(gp->yp+gp->ys)) { + renderer->writeFastHLine(gp->xp,czp+cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp+cyp,TICKLEN,fg_color); + } + cyp+=yd; + } + } else { + float cyp=gp->yp,yd=gp->ys/yticks; + for (count=0; countwriteFastHLine(gp->xp,cyp,TICKLEN,fg_color); + renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,cyp,TICKLEN,fg_color); + cyp+=yd; + } + } + } +} + + +void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol) { + if (!renderer) return; + uint8_t rflg=0; + if (xs<0) { + rflg=1; + xs=abs(xs); + } + struct GRAPH *gp; + uint16_t count; + uint16_t index=num%NUM_GRAPHS; + if (!graph[index]) { + gp=(struct GRAPH*)calloc(sizeof(struct GRAPH),1); + if (!gp) return; + graph[index]=gp; + } else { + gp=graph[index]; + if (rflg) { + RedrawGraph(index,1); + return; + } + } + + + gp->xticks=(num>>4)&0x3f; + gp->yticks=(num>>10)&0x3f; + gp->xp=xp; + gp->yp=yp; + gp->xs=xs; + gp->ys=ys; + if (!dec) dec=1; + gp->decimation=dec; + if (dec>0) { + + gp->x_time=((float)dec*60000.0)/(float)xs; + gp->last_ms=millis()+gp->x_time; + } + gp->ymin=ymin; + gp->ymax=ymax; + gp->range=(ymax-ymin)/ys; + gp->xcnt=0; + gp->dcnt=0; + gp->summ=0; + if (gp->values) free(gp->values); + gp->values=(uint8_t*) calloc(1,xs+2); + if (!gp->values) { + free(gp); + graph[index]=0; + return; + } + + gp->values[0]=0; + + gp->last_ms_redrawn=millis(); + + if (!icol) icol=1; + gp->color_index=icol; + gp->flags.overlay=0; + gp->flags.draw=1; + + + if (index>0) { + for (uint8_t count=0; countxp==gp1->xp) && (gp->yp==gp1->yp)) { + gp->flags.overlay=1; + break; + } + } + } + } + + + renderer->drawRect(xp,yp,xs,ys,fg_color); + + ClrGraph(index); + +} + + +void DisplayCheckGraph() { + int16_t count; + struct GRAPH *gp; + for (count=0;countdecimation>0) { + + while (millis()>gp->last_ms) { + gp->last_ms+=gp->x_time; + uint8_t val; + if (gp->dcnt) { + val=gp->summ/gp->dcnt; + gp->dcnt=0; + gp->summ=0; + gp->last_val=val; + } else { + val=gp->last_val; + } + AddGraph(count,val); + } + } + } + } +} + + +#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) +#include + +void Save_graph(uint8_t num, char *path) { + if (!renderer) return; + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + File fp; + SD.remove(path); + fp=SD.open(path,FILE_WRITE); + if (!fp) return; + char str[32]; + sprintf_P(str,PSTR("%d\t%d\t%d\t"),gp->xcnt,gp->xs,gp->ys); + fp.print(str); + dtostrfd(gp->ymin,2,str); + fp.print(str); + fp.print("\t"); + dtostrfd(gp->ymax,2,str); + fp.print(str); + fp.print("\t"); + for (uint32_t count=0;countxs;count++) { + dtostrfd(gp->values[count],0,str); + fp.print(str); + fp.print("\t"); + } + fp.print("\n"); + fp.close(); +} +void Restore_graph(uint8_t num, char *path) { + if (!renderer) return; + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + File fp; + fp=SD.open(path,FILE_READ); + if (!fp) return; + char vbuff[32]; + char *cp=vbuff; + uint8_t buf[2]; + uint8_t findex=0; + + for (uint32_t count=0;count<=gp->xs+4;count++) { + cp=vbuff; + findex=0; + while (fp.available()) { + fp.read(buf,1); + if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { + break; + } else { + *cp++=buf[0]; + findex++; + if (findex>=sizeof(vbuff)-1) break; + } + } + *cp=0; + if (count<=4) { + if (count==0) gp->xcnt=atoi(vbuff); + } else { + gp->values[count-5]=atoi(vbuff); + } + } + fp.close(); + RedrawGraph(num,1); +} +#endif + +void RedrawGraph(uint8_t num, uint8_t flags) { + uint16_t index=num%NUM_GRAPHS; + struct GRAPH *gp=graph[index]; + if (!gp) return; + if (!flags) { + gp->flags.draw=0; + return; + } + if (!renderer) return; + + gp->flags.draw=1; + uint16_t linecol=fg_color; + + if (color_type==COLOR_COLOR) { + linecol=renderer->GetColorFromIndex(gp->color_index); + } + + if (!gp->flags.overlay) { + + renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); + + ClrGraph(index); + } + + for (uint16_t count=0;countxs-1;count++) { + renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); + } +} + + +void AddGraph(uint8_t num,uint8_t val) { + struct GRAPH *gp=graph[num]; + if (!renderer) return; + + uint16_t linecol=fg_color; + if (color_type==COLOR_COLOR) { + linecol=renderer->GetColorFromIndex(gp->color_index); + } + gp->xcnt++; + if (gp->xcnt>gp->xs) { + gp->xcnt=gp->xs; + int16_t count; + + for (count=0;countxs-1;count++) { + gp->values[count]=gp->values[count+1]; + } + gp->values[gp->xcnt-1]=val; + + if (!gp->flags.draw) return; + + + if (millis()-gp->last_ms_redrawn>1000) { + gp->last_ms_redrawn=millis(); + + if (!gp->flags.overlay) { + + renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); + + ClrGraph(num); + } + + for (count=0;countxs-1;count++) { + renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); + } + } + } else { + + gp->values[gp->xcnt]=val; + if (!gp->flags.draw) return; + renderer->writeLine(gp->xp+gp->xcnt-1,gp->yp+gp->ys-gp->values[gp->xcnt-1]-1,gp->xp+gp->xcnt,gp->yp+gp->ys-gp->values[gp->xcnt]-1,linecol); + } +} + + + +void AddValue(uint8_t num,float fval) { + + num=num%NUM_GRAPHS; + struct GRAPH *gp=graph[num]; + if (!gp) return; + + if (fval>gp->ymax) fval=gp->ymax; + if (fvalymin) fval=gp->ymin; + + int16_t val; + val=(fval-gp->ymin)/gp->range; + + if (val>gp->ys-1) val=gp->ys-1; + if (val<0) val=0; + + + gp->summ+=val; + gp->dcnt++; + + + if (gp->decimation<0) { + if (gp->dcnt>=-gp->decimation) { + gp->dcnt=0; + + val=gp->summ/-gp->decimation; + gp->summ=0; + + AddGraph(num,val); + } + } +} +#endif + + + + + +bool Xdrv13(uint8_t function) +{ + bool result = false; + + if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { + switch (function) { + case FUNC_PRE_INIT: + DisplayInitDriver(); +#ifdef USE_GRAPH + for (uint8_t count=0;count + +TasmotaSerial *MP3Player; + + + + + +#define D_CMND_MP3 "MP3" + +const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; +const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; +const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device|Reset|DAC"; + + + + + +enum MP3_Commands { + CMND_MP3_TRACK, + CMND_MP3_PLAY, + CMND_MP3_PAUSE, + CMND_MP3_STOP, + CMND_MP3_VOLUME, + CMND_MP3_EQ, + CMND_MP3_DEVICE, + CMND_MP3_RESET, + CMND_MP3_DAC }; + + + + + + +#define MP3_CMD_RESET_VALUE 0 + +#define MP3_CMD_TRACK 0x03 +#define MP3_CMD_PLAY 0x0d +#define MP3_CMD_PAUSE 0x0e +#define MP3_CMD_STOP 0x16 +#define MP3_CMD_VOLUME 0x06 +#define MP3_CMD_EQ 0x07 +#define MP3_CMD_DEVICE 0x09 +#define MP3_CMD_RESET 0x0C +#define MP3_CMD_DAC 0x1A + + + + + + +uint16_t MP3_Checksum(uint8_t *array) +{ + uint16_t checksum = 0; + for (uint32_t i = 0; i < 6; i++) { + checksum += array[i]; + } + checksum = checksum^0xffff; + return (checksum+1); +} + + + + + + +void MP3PlayerInit(void) { + MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); + + if (MP3Player->begin(9600)) { + MP3Player->flush(); + delay(1000); + MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); + delay(3000); + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); + } + return; +} +# 159 "S:/Development/Tasmota/tasmota/xdrv_14_mp3.ino" +void MP3_CMD(uint8_t mp3cmd,uint16_t val) { + uint8_t i = 0; + uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; + cmd[3] = mp3cmd; + cmd[4] = 0; + cmd[5] = val>>8; + cmd[6] = val; + uint16_t chks = MP3_Checksum(&cmd[1]); + cmd[7] = chks>>8; + cmd[8] = chks; + MP3Player->write(cmd, sizeof(cmd)); + delay(1000); + if (mp3cmd == MP3_CMD_RESET) { + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); + } + return; +} + + + + + +bool MP3PlayerCmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_MP3); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); + + switch (command_code) { + case CMND_MP3_TRACK: + case CMND_MP3_VOLUME: + case CMND_MP3_EQ: + case CMND_MP3_DEVICE: + case CMND_MP3_DAC: + + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_MP3_TRACK) { MP3_CMD(MP3_CMD_TRACK, XdrvMailbox.payload); } + if (command_code == CMND_MP3_VOLUME) { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } + if (command_code == CMND_MP3_EQ) { MP3_CMD(MP3_CMD_EQ, XdrvMailbox.payload); } + if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } + if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } + } + Response_P(S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_MP3_PLAY: + case CMND_MP3_PAUSE: + case CMND_MP3_STOP: + case CMND_MP3_RESET: + + if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } + if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } + if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } + if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } + Response_P(S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); + break; + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + + +bool Xdrv14(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_MP3_DFR562] < 99) { + switch (function) { + case FUNC_PRE_INIT: + MP3PlayerInit(); + break; + case FUNC_COMMAND: + result = MP3PlayerCmd(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_15_pca9685.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_15_pca9685.ino" +#ifdef USE_I2C +#ifdef USE_PCA9685 + + + + + + +#define XDRV_15 15 +#define XI2C_01 1 + +#define PCA9685_REG_MODE1 0x00 +#define PCA9685_REG_LED0_ON_L 0x06 +#define PCA9685_REG_PRE_SCALE 0xFE + +#ifndef USE_PCA9685_ADDR + #define USE_PCA9685_ADDR 0x40 +#endif +#ifndef USE_PCA9685_FREQ + #define USE_PCA9685_FREQ 50 +#endif + +bool pca9685_detected = false; +uint16_t pca9685_freq = USE_PCA9685_FREQ; +uint16_t pca9685_pin_pwm_value[16]; + +void PCA9685_Detect(void) +{ + if (I2cActive(USE_PCA9685_ADDR)) { return; } + + uint8_t buffer; + if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x20); + if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { + if (0x20 == buffer) { + pca9685_detected = true; + I2cSetActiveFound(USE_PCA9685_ADDR, "PCA9685"); + PCA9685_Reset(); + } + } + } +} + +void PCA9685_Reset(void) +{ + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); + PCA9685_SetPWMfreq(USE_PCA9685_FREQ); + for (uint32_t pin=0;pin<16;pin++) { + PCA9685_SetPWM(pin,0,false); + pca9685_pin_pwm_value[pin] = 0; + } + Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); +} + +void PCA9685_SetPWMfreq(double freq) { + + + + + if (freq > 23 && freq < 1527) { + pca9685_freq=freq; + } else { + pca9685_freq=50; + } + uint8_t pre_scale_osc = round(25000000/(4096*pca9685_freq))-1; + if (1526 == pca9685_freq) pre_scale_osc=0xFF; + uint8_t current_mode1 = I2cRead8(USE_PCA9685_ADDR, PCA9685_REG_MODE1); + uint8_t sleep_mode1 = (current_mode1&0x7F) | 0x10; + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, sleep_mode1); + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_PRE_SCALE, pre_scale_osc); + I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, current_mode1 | 0xA0); +} + +void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off) { + uint8_t led_reg = PCA9685_REG_LED0_ON_L + 4 * pin; + uint32_t led_data = 0; + I2cWrite8(USE_PCA9685_ADDR, led_reg, on); + I2cWrite8(USE_PCA9685_ADDR, led_reg+1, (on >> 8)); + I2cWrite8(USE_PCA9685_ADDR, led_reg+2, off); + I2cWrite8(USE_PCA9685_ADDR, led_reg+3, (off >> 8)); +} + +void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { + if (4096 == pwm) { + PCA9685_SetPWM_Reg(pin, 4096, 0); + } else { + PCA9685_SetPWM_Reg(pin, 0, pwm); + } + pca9685_pin_pwm_value[pin] = pwm; +} + +bool PCA9685_Command(void) +{ + bool serviced = true; + bool validpin = false; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((new_freq >= 24) && (new_freq <= 1526)) { + PCA9685_SetPWMfreq(new_freq); + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); + return serviced; + } + } else { + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); + return serviced; + } + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWM")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (paramcount > 2) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { + PCA9685_SetPWM(pin, 4096, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); + serviced = true; + return serviced; + } + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { + PCA9685_SetPWM(pin, 0, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); + serviced = true; + return serviced; + } + uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { + PCA9685_SetPWM(pin, pwm, false); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); + serviced = true; + return serviced; + } + } + } + } + return serviced; +} + +void PCA9685_OutputTelemetry(bool telemetry) +{ + ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); + for (uint32_t pin=0;pin<16;pin++) { + ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); + } + ResponseAppend_P(PSTR("\"END\":1}}")); + if (telemetry) { + MqttPublishTeleSensor(); + } +} + +bool Xdrv15(uint8_t function) +{ + if (!I2cEnabled(XI2C_01)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + PCA9685_Detect(); + } + else if (pca9685_detected) { + switch (function) { + case FUNC_EVERY_SECOND: + if (tele_period == 0) { + PCA9685_OutputTelemetry(true); + } + break; + case FUNC_COMMAND_DRIVER: + if (XDRV_15 == XdrvMailbox.index) { + result = PCA9685_Command(); + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +#ifdef USE_LIGHT +#ifdef USE_TUYA_MCU + +#define XDRV_16 16 +#define XNRG_16 16 + +#ifndef TUYA_DIMMER_ID +#define TUYA_DIMMER_ID 0 +#endif + +#define TUYA_CMD_HEARTBEAT 0x00 +#define TUYA_CMD_QUERY_PRODUCT 0x01 +#define TUYA_CMD_MCU_CONF 0x02 +#define TUYA_CMD_WIFI_STATE 0x03 +#define TUYA_CMD_WIFI_RESET 0x04 +#define TUYA_CMD_WIFI_SELECT 0x05 +#define TUYA_CMD_SET_DP 0x06 +#define TUYA_CMD_STATE 0x07 +#define TUYA_CMD_QUERY_STATE 0x08 + +#define TUYA_LOW_POWER_CMD_WIFI_STATE 0x02 +#define TUYA_LOW_POWER_CMD_WIFI_RESET 0x03 +#define TUYA_LOW_POWER_CMD_WIFI_CONFIG 0x04 +#define TUYA_LOW_POWER_CMD_STATE 0x05 + +#define TUYA_TYPE_BOOL 0x01 +#define TUYA_TYPE_VALUE 0x02 +#define TUYA_TYPE_STRING 0x03 +#define TUYA_TYPE_ENUM 0x04 + +#define TUYA_BUFFER_SIZE 256 + +#include + +TasmotaSerial *TuyaSerial = nullptr; + +struct TUYA { + uint16_t new_dim = 0; + bool ignore_dim = false; + uint8_t cmd_status = 0; + uint8_t cmd_checksum = 0; + uint8_t data_len = 0; + uint8_t wifi_state = -2; + uint8_t heartbeat_timer = 0; +#ifdef USE_ENERGY_SENSOR + uint32_t lastPowerCheckTime = 0; +#endif + char *buffer = nullptr; + int byte_counter = 0; + bool low_power_mode = false; + bool send_success_next_second = false; +} Tuya; + + +enum TuyaSupportedFunctions { + TUYA_MCU_FUNC_NONE, + TUYA_MCU_FUNC_SWT1 = 1, + TUYA_MCU_FUNC_SWT2, + TUYA_MCU_FUNC_SWT3, + TUYA_MCU_FUNC_SWT4, + TUYA_MCU_FUNC_REL1 = 11, + TUYA_MCU_FUNC_REL2, + TUYA_MCU_FUNC_REL3, + TUYA_MCU_FUNC_REL4, + TUYA_MCU_FUNC_REL5, + TUYA_MCU_FUNC_REL6, + TUYA_MCU_FUNC_REL7, + TUYA_MCU_FUNC_REL8, + TUYA_MCU_FUNC_DIMMER = 21, + TUYA_MCU_FUNC_POWER = 31, + TUYA_MCU_FUNC_CURRENT, + TUYA_MCU_FUNC_VOLTAGE, + TUYA_MCU_FUNC_BATTERY_STATE, + TUYA_MCU_FUNC_BATTERY_PERCENTAGE, + TUYA_MCU_FUNC_REL1_INV = 41, + TUYA_MCU_FUNC_REL2_INV, + TUYA_MCU_FUNC_REL3_INV, + TUYA_MCU_FUNC_REL4_INV, + TUYA_MCU_FUNC_REL5_INV, + TUYA_MCU_FUNC_REL6_INV, + TUYA_MCU_FUNC_REL7_INV, + TUYA_MCU_FUNC_REL8_INV, + TUYA_MCU_FUNC_LOWPOWER_MODE = 51, + TUYA_MCU_FUNC_LAST = 255 +}; + +const char kTuyaCommand[] PROGMEM = "|" + D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE; + +void (* const TuyaCommand[])(void) PROGMEM = { + &CmndTuyaMcu, &CmndTuyaSend +}; +# 127 "S:/Development/Tasmota/tasmota/xdrv_16_tuyamcu.ino" +void CmndTuyaSend(void) { + if (XdrvMailbox.index > 4) { + return; + } + if (XdrvMailbox.index == 0) { + TuyaRequestState(); + } else { + if (XdrvMailbox.data_len > 0) { + char *p; + char *data; + uint8_t i = 0; + uint8_t dpId = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + if ( i == 0) { + dpId = strtoul(str, nullptr, 0); + } else { + data = str; + } + i++; + } + + if (1 == XdrvMailbox.index) { + TuyaSendBool(dpId, strtoul(data, nullptr, 0)); + } else if (2 == XdrvMailbox.index) { + TuyaSendValue(dpId, strtoull(data, nullptr, 0)); + } else if (3 == XdrvMailbox.index) { + TuyaSendString(dpId, data); + } else if (4 == XdrvMailbox.index) { + TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); + } + } + } + ResponseCmndDone(); +} + + + + + + + +void CmndTuyaMcu(void) { + if (XdrvMailbox.data_len > 0) { + char *p; + uint8_t i = 0; + uint8_t parm[3] = { 0 }; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { + parm[i] = strtoul(str, nullptr, 0); + i++; + } + + if (TuyaFuncIdValid(parm[0])) { + TuyaAddMcuFunc(parm[0], parm[1]); + restart_flag = 2; + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); + } + + } + + Response_P(PSTR("{\"" D_CMND_TUYA_MCU "\":[")); + bool added = false; + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].fnid != 0) { + if (added) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"fnId\":%d,\"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid); + added = true; + } + } + ResponseAppend_P(PSTR("]}")); +} + + + + + +void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { + bool added = false; + + if (fnId == 0 || dpId == 0) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) { + Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; + Settings.tuya_fnid_map[i].dpid = 0; + break; + } + } + } else { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) { + if (!added) { + Settings.tuya_fnid_map[i].fnid = fnId; + Settings.tuya_fnid_map[i].dpid = dpId; + added = true; + } else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { + Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; + Settings.tuya_fnid_map[i].dpid = 0; + } + } + } + } + UpdateDevices(); +} + +void UpdateDevices() { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + uint8_t fnId = Settings.tuya_fnid_map[i].fnid; + if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) { + + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { + bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1); + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { + bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); + } + + } + } +} + +inline bool TuyaFuncIdValid(uint8_t fnId) { + return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) || + (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || + fnId == TUYA_MCU_FUNC_DIMMER || + (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) || + (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) || + (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE); +} + +uint8_t TuyaGetFuncId(uint8_t dpid) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].dpid == dpid) { + return Settings.tuya_fnid_map[i].fnid; + } + } + return TUYA_MCU_FUNC_NONE; +} + +uint8_t TuyaGetDpId(uint8_t fnId) { + for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { + if (Settings.tuya_fnid_map[i].fnid == fnId) { + return Settings.tuya_fnid_map[i].dpid; + } + } + return 0; +} + +void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0) +{ + uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF)); + TuyaSerial->write(0x55); + TuyaSerial->write(0xAA); + TuyaSerial->write((uint8_t)0x00); + TuyaSerial->write(cmd); + TuyaSerial->write(payload_len >> 8); + TuyaSerial->write(payload_len & 0xFF); + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); + for (uint32_t i = 0; i < payload_len; ++i) { + TuyaSerial->write(payload[i]); + checksum += payload[i]; + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, payload[i]); + } + TuyaSerial->write(checksum); + TuyaSerial->flush(); + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x\""), log_data, checksum); + AddLog(LOG_LEVEL_DEBUG); +} + +void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value) +{ + uint16_t payload_len = 4; + uint8_t payload_buffer[8]; + payload_buffer[0] = id; + payload_buffer[1] = type; + switch (type) { + case TUYA_TYPE_BOOL: + case TUYA_TYPE_ENUM: + payload_len += 1; + payload_buffer[2] = 0x00; + payload_buffer[3] = 0x01; + payload_buffer[4] = value[0]; + break; + case TUYA_TYPE_VALUE: + payload_len += 4; + payload_buffer[2] = 0x00; + payload_buffer[3] = 0x04; + payload_buffer[4] = value[3]; + payload_buffer[5] = value[2]; + payload_buffer[6] = value[1]; + payload_buffer[7] = value[0]; + break; + + } + + TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +void TuyaSendBool(uint8_t id, bool value) +{ + TuyaSendState(id, TUYA_TYPE_BOOL, (uint8_t*)&value); +} + +void TuyaSendValue(uint8_t id, uint32_t value) +{ + TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); +} + +void TuyaSendEnum(uint8_t id, uint32_t value) +{ + TuyaSendState(id, TUYA_TYPE_ENUM, (uint8_t*)(&value)); +} + +void TuyaSendString(uint8_t id, char data[]) { + + uint16_t len = strlen(data); + uint16_t payload_len = 4 + len; + uint8_t payload_buffer[payload_len]; + payload_buffer[0] = id; + payload_buffer[1] = TUYA_TYPE_STRING; + payload_buffer[2] = len >> 8; + payload_buffer[3] = len & 0xFF; + + for (uint16_t i = 0; i < len; i++) { + payload_buffer[4+i] = data[i]; + } + + TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); +} + +bool TuyaSetPower(void) +{ + bool status = false; + + uint8_t rpower = XdrvMailbox.index; + int16_t source = XdrvMailbox.payload; + + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + active_device - 1); + if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + active_device - 1); + + if (source != SRC_SWITCH && TuyaSerial) { + TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); + status = true; + } + return status; +} + +bool TuyaSetChannels(void) +{ + LightSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); + delay(20); + return true; +} + +void LightSerialDuty(uint16_t duty) +{ + uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); + if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { + duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); + if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } + if (Tuya.new_dim != duty) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); + TuyaSendValue(dpid, duty); + } + } else if (dpid > 0) { + Tuya.ignore_dim = false; + duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); + } +} + +void TuyaRequestState(void) +{ + if (TuyaSerial) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Read MCU state")); + + TuyaSendCmd(TUYA_CMD_QUERY_STATE); + } +} + +void TuyaResetWifi(void) +{ + if (!Settings.flag.button_restrict) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); + ExecuteCommand(scmnd, SRC_BUTTON); + } +} + +void TuyaProcessStatePacket(void) { + char scmnd[20]; + uint8_t dpidStart = 6; + uint8_t fnId; + uint16_t dpDataLen; + + while (dpidStart + 4 < Tuya.byte_counter) { + dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; + fnId = TuyaGetFuncId(Tuya.buffer[dpidStart]); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[dpidStart]); + + if (Tuya.buffer[dpidStart + 1] == 1) { + + if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); + if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], SRC_SWITCH); + } + } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); + if (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { + ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4] ^ 1, SRC_SWITCH); + } + } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[dpidStart + 4], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); + + if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[dpidStart + 4]) { + SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[dpidStart + 4]); + SwitchHandler(1); + } + } + + } + else if (Tuya.buffer[dpidStart + 1] == 2) { + bool tuya_energy_enabled = (XNRG_16 == energy_flg); + uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; + if (fnId == TUYA_MCU_FUNC_DIMMER) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), packetValue); + Tuya.new_dim = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); + if ((power || Settings.flag3.tuya_apply_o20) && + (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { + Tuya.ignore_dim = true; + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + + #ifdef USE_ENERGY_SENSOR + else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { + Energy.voltage[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], packetValue); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { + Energy.current[0] = (float)packetValue / 1000; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], packetValue); + } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { + Energy.active_power[0] = (float)packetValue / 10; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], packetValue); + + if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { + Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; + EnergyUpdateToday(); + } + Tuya.lastPowerCheckTime = Rtc.utc_time; + } + #endif + + } + + + dpidStart += dpDataLen + 4; + } +} + +void TuyaLowPowerModePacketProcess(void) { + switch (Tuya.buffer[3]) { + case TUYA_CMD_QUERY_PRODUCT: + TuyaHandleProductInfoPacket(); + TuyaSetWifiLed(); + break; + + case TUYA_LOW_POWER_CMD_STATE: + TuyaProcessStatePacket(); + Tuya.send_success_next_second = true; + break; + } + +} + +void TuyaHandleProductInfoPacket(void) { + uint16_t dataLength = Tuya.buffer[4] << 8 | Tuya.buffer[5]; + char *data = &Tuya.buffer[6]; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: MCU Product ID: %.*s"), dataLength, data); +} + +void TuyaSendLowPowerSuccessIfNeeded(void) { + uint8_t success = 1; + + if (Tuya.send_success_next_second) { + TuyaSendCmd(TUYA_LOW_POWER_CMD_STATE, &success, 1); + Tuya.send_success_next_second = false; + } +} + +void TuyaNormalPowerModePacketProcess(void) +{ + switch (Tuya.buffer[3]) { + case TUYA_CMD_QUERY_PRODUCT: + TuyaHandleProductInfoPacket(); + TuyaSendCmd(TUYA_CMD_MCU_CONF); + break; + + case TUYA_CMD_HEARTBEAT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); + if (Tuya.buffer[6] == 0) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Detected MCU restart")); + Tuya.wifi_state = -2; + } + break; + + case TUYA_CMD_STATE: + TuyaProcessStatePacket(); + break; + + case TUYA_CMD_WIFI_RESET: + case TUYA_CMD_WIFI_SELECT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi Reset")); + TuyaResetWifi(); + break; + + case TUYA_CMD_WIFI_STATE: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi LED set ACK")); + Tuya.wifi_state = TuyaGetTuyaWifiState(); + break; + + case TUYA_CMD_MCU_CONF: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]); + + if (Tuya.buffer[5] == 2) { + uint8_t led1_gpio = Tuya.buffer[6]; + uint8_t key1_gpio = Tuya.buffer[7]; + bool key1_set = false; + bool led1_set = false; + for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { + if (Settings.my_gp.io[i] == GPIO_LED1) led1_set = true; + else if (Settings.my_gp.io[i] == GPIO_KEY1) key1_set = true; + } + if (!Settings.my_gp.io[led1_gpio] && !led1_set) { + Settings.my_gp.io[led1_gpio] = GPIO_LED1; + restart_flag = 2; + } + if (!Settings.my_gp.io[key1_gpio] && !key1_set) { + Settings.my_gp.io[key1_gpio] = GPIO_KEY1; + restart_flag = 2; + } + } + TuyaRequestState(); + break; + + default: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); + } +} + + + + + +bool TuyaModuleSelected(void) +{ + if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { + pin[GPIO_TUYA_TX] = 1; + pin[GPIO_TUYA_RX] = 3; + Settings.my_gp.io[1] = GPIO_TUYA_TX; + Settings.my_gp.io[3] = GPIO_TUYA_RX; + restart_flag = 2; + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); + } + + bool relaySet = false; + + for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) { + if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || + (Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { + relaySet = true; + devices_present++; + } + } + + if (!relaySet) { + TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); + devices_present++; + SettingsSaveAll(); + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { + light_type = LT_SERIAL1; + } else { + light_type = LT_BASIC; + } + + if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { + Tuya.low_power_mode = true; + Settings.flag3.fast_power_cycle_disable = true; + } + + UpdateDevices(); + return true; +} + +void TuyaInit(void) +{ + Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); + if (Tuya.buffer != nullptr) { + TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); + if (TuyaSerial->begin(9600)) { + if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration")); + + TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); + } + } + Tuya.heartbeat_timer = 0; +} + +void TuyaSerialInput(void) +{ + while (TuyaSerial->available()) { + yield(); + uint8_t serial_in_byte = TuyaSerial->read(); + + if (serial_in_byte == 0x55) { + Tuya.cmd_status = 1; + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + Tuya.cmd_checksum += serial_in_byte; + } + else if (Tuya.cmd_status == 1 && serial_in_byte == 0xAA) { + Tuya.cmd_status = 2; + + Tuya.byte_counter = 0; + Tuya.buffer[Tuya.byte_counter++] = 0x55; + Tuya.buffer[Tuya.byte_counter++] = 0xAA; + Tuya.cmd_checksum = 0xFF; + } + else if (Tuya.cmd_status == 2) { + if (Tuya.byte_counter == 5) { + Tuya.cmd_status = 3; + Tuya.data_len = serial_in_byte; + } + Tuya.cmd_checksum += serial_in_byte; + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + } + else if ((Tuya.cmd_status == 3) && (Tuya.byte_counter == (6 + Tuya.data_len)) && (Tuya.cmd_checksum == serial_in_byte)) { + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + + char hex_char[(Tuya.byte_counter * 2) + 2]; + uint16_t len = Tuya.buffer[4] << 8 | Tuya.buffer[5]; + Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":{\"Data\":\"%s\",\"Cmnd\":%d"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char)), Tuya.buffer[3]); + + if (len > 0) { + ResponseAppend_P(PSTR(",\"CmndData\":\"%s\""), ToHex_P((unsigned char*)&Tuya.buffer[6], len, hex_char, sizeof(hex_char))); + if (TUYA_CMD_STATE == Tuya.buffer[3]) { + + + uint8_t dpidStart = 6; + while (dpidStart + 4 < Tuya.byte_counter) { + uint8_t dpId = Tuya.buffer[dpidStart]; + uint8_t dpDataType = Tuya.buffer[dpidStart + 1]; + uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; + const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; + const char *dpHexData = ToHex_P(dpData, dpDataLen, hex_char, sizeof(hex_char)); + + if (TUYA_CMD_STATE == Tuya.buffer[3]) { + ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId); + if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("%u"), dpData[0]); + } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { + uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; + ResponseAppend_P(PSTR("%u"), dpValue); + } else if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); + } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { + ResponseAppend_P(PSTR("%u"), dpData[0]); + } else { + ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); + } + } + + ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), dpId, dpId, dpDataType, dpHexData); + if (TUYA_TYPE_STRING == dpDataType) { + ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, dpData); + } + ResponseAppend_P(PSTR("}")); + dpidStart += dpDataLen + 4; + } + } + } + + ResponseAppend_P(PSTR("}}")); + + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); + } else { + AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); + } + XdrvRulesProcess(); + + if (!Tuya.low_power_mode) { + TuyaNormalPowerModePacketProcess(); + } else { + TuyaLowPowerModePacketProcess(); + } + + Tuya.byte_counter = 0; + Tuya.cmd_status = 0; + Tuya.cmd_checksum = 0; + Tuya.data_len = 0; + } + else if (Tuya.byte_counter < TUYA_BUFFER_SIZE -1) { + Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; + Tuya.cmd_checksum += serial_in_byte; + } else { + Tuya.byte_counter = 0; + Tuya.cmd_status = 0; + Tuya.cmd_checksum = 0; + Tuya.data_len = 0; + } + } +} + +bool TuyaButtonPressed(void) +{ + if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == Button.last_state[XdrvMailbox.index]))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered")); + TuyaResetWifi(); + return true; + } + return false; +} + +uint8_t TuyaGetTuyaWifiState(void) { + + uint8_t wifi_state = 0x02; + switch(WifiState()){ + case WIFI_MANAGER: + wifi_state = 0x01; + break; + case WIFI_RESTART: + wifi_state = 0x03; + break; + } + + if (MqttIsConnected()) { + wifi_state = 0x04; + } + + return wifi_state; +} + +void TuyaSetWifiLed(void) +{ + Tuya.wifi_state = TuyaGetTuyaWifiState(); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), Tuya.wifi_state, WifiState()); + + if (Tuya.low_power_mode) { + TuyaSendCmd(TUYA_LOW_POWER_CMD_WIFI_STATE, &Tuya.wifi_state, 1); + } else { + TuyaSendCmd(TUYA_CMD_WIFI_STATE, &Tuya.wifi_state, 1); + } +} + +#ifdef USE_ENERGY_SENSOR + + + + +bool Xnrg16(uint8_t function) +{ + bool result = false; + + if (TUYA_DIMMER == my_module_type) { + if (FUNC_PRE_INIT == function) { + if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) { + if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) { + Energy.current_available = false; + } + if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) { + Energy.voltage_available = false; + } + energy_flg = XNRG_16; + } + } + } + return result; +} +#endif + + + + + +bool Xdrv16(uint8_t function) +{ + bool result = false; + + if (TUYA_DIMMER == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (TuyaSerial) { TuyaSerialInput(); } + break; + case FUNC_MODULE_INIT: + result = TuyaModuleSelected(); + break; + case FUNC_PRE_INIT: + TuyaInit(); + break; + case FUNC_SET_DEVICE_POWER: + result = TuyaSetPower(); + break; + case FUNC_BUTTON_PRESSED: + result = TuyaButtonPressed(); + break; + case FUNC_EVERY_SECOND: + if (TuyaSerial && Tuya.wifi_state != TuyaGetTuyaWifiState()) { TuyaSetWifiLed(); } + if (!Tuya.low_power_mode) { + Tuya.heartbeat_timer++; + if (Tuya.heartbeat_timer > 10) { + Tuya.heartbeat_timer = 0; + TuyaSendCmd(TUYA_CMD_HEARTBEAT); + } + } else { + TuyaSendLowPowerSuccessIfNeeded(); + } + break; + case FUNC_SET_CHANNELS: + result = TuyaSetChannels(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kTuyaCommand, TuyaCommand); + break; + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_17_rcswitch.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_17_rcswitch.ino" +#ifdef USE_RC_SWITCH + + + + +#define XDRV_17 17 + +#define D_JSON_RF_PROTOCOL "Protocol" +#define D_JSON_RF_BITS "Bits" +#define D_JSON_RF_DATA "Data" + +#define D_CMND_RFSEND "RFSend" +#define D_JSON_RF_PULSE "Pulse" +#define D_JSON_RF_REPEAT "Repeat" + +const char kRfSendCommands[] PROGMEM = "|" + D_CMND_RFSEND; + +void (* const RfSendCommand[])(void) PROGMEM = { + &CmndRfSend }; + +#include + +RCSwitch mySwitch = RCSwitch(); + +#define RF_TIME_AVOID_DUPLICATE 1000 + +uint32_t rf_lasttime = 0; + +void RfReceiveCheck(void) +{ + if (mySwitch.available()) { + + unsigned long data = mySwitch.getReceivedValue(); + unsigned int bits = mySwitch.getReceivedBitlength(); + int protocol = mySwitch.getReceivedProtocol(); + int delay = mySwitch.getReceivedDelay(); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data 0x%lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); + + uint32_t now = millis(); + if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) { + rf_lasttime = now; + + char stemp[16]; + if (Settings.flag.rf_receive_decimal) { + snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); + } + ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), + stemp, bits, protocol, delay); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, data); +#endif + } + mySwitch.resetAvailable(); + } +} + +void RfInit(void) +{ + if (pin[GPIO_RFSEND] < 99) { + mySwitch.enableTransmit(pin[GPIO_RFSEND]); + } + if (pin[GPIO_RFRECV] < 99) { + pinMode( pin[GPIO_RFRECV], INPUT); + mySwitch.enableReceive(pin[GPIO_RFRECV]); + } +} + + + + + +void CmndRfSend(void) +{ + bool error = false; + + if (XdrvMailbox.data_len) { + unsigned long data = 0; + unsigned int bits = 24; + int protocol = 1; + int repeat = 10; + int pulse = 350; + + char dataBufUc[XdrvMailbox.data_len + 1]; + UpperCase(dataBufUc, XdrvMailbox.data); + StaticJsonBuffer<150> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (root.success()) { + + char parm_uc[10]; + data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], nullptr, 0); + bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; + protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; + repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; + pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))]; + } else { + + char *p; + uint8_t i = 0; + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(nullptr, ", ", &p)) { + switch (i++) { + case 0: + data = strtoul(str, nullptr, 0); + break; + case 1: + bits = atoi(str); + break; + case 2: + protocol = atoi(str); + break; + case 3: + repeat = atoi(str); + break; + case 4: + pulse = atoi(str); + } + } + } + + if (!protocol) { protocol = 1; } + mySwitch.setProtocol(protocol); + if (!pulse) { pulse = 350; } + mySwitch.setPulseLength(pulse); + if (!repeat) { repeat = 10; } + mySwitch.setRepeatTransmit(repeat); + if (!bits) { bits = 24; } + if (data) { + mySwitch.send(data, bits); + ResponseCmndDone(); + } else { + error = true; + } + } else { + error = true; + } + if (error) { + Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); + } +} + + + + + +bool Xdrv17(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_RFRECV] < 99) { + RfReceiveCheck(); + } + break; + case FUNC_COMMAND: + if (pin[GPIO_RFSEND] < 99) { + result = DecodeCommand(kRfSendCommands, RfSendCommand); + } + break; + case FUNC_INIT: + RfInit(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" +#ifdef USE_LIGHT +#ifdef USE_ARMTRONIX_DIMMERS + + + + + + + +#define XDRV_18 18 + +#include + +TasmotaSerial *ArmtronixSerial = nullptr; + +struct ARMTRONIX { + bool ignore_dim = false; + int8_t wifi_state = -2; + int8_t dim_state[2]; + int8_t knob_state[2]; +} Armtronix; + + + + + +bool ArmtronixSetChannels(void) +{ + LightSerial2Duty(((uint8_t*)XdrvMailbox.data)[0], ((uint8_t*)XdrvMailbox.data)[1]); + return true; +} + +void LightSerial2Duty(uint8_t duty1, uint8_t duty2) +{ + if (ArmtronixSerial && !Armtronix.ignore_dim) { + duty1 = ((float)duty1)/2.575757; + duty2 = ((float)duty2)/2.575757; + Armtronix.dim_state[0] = duty1; + Armtronix.dim_state[1] = duty2; + ArmtronixSerial->print("Dimmer1:"); + ArmtronixSerial->print(duty1); + ArmtronixSerial->print("\nDimmer2:"); + ArmtronixSerial->println(duty2); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Serial Packet Dim Values=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); + + } else { + Armtronix.ignore_dim = false; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Dim Level skipped due to already set. Value=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); + + } +} + +void ArmtronixRequestState(void) +{ + if (ArmtronixSerial) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("ARM: Request MCU state")); + ArmtronixSerial->println("Status"); + + } +} + + + + + +bool ArmtronixModuleSelected(void) +{ + devices_present++; + light_type = LT_SERIAL2; + return true; +} + +void ArmtronixInit(void) +{ + Armtronix.dim_state[0] = -1; + Armtronix.dim_state[1] = -1; + Armtronix.knob_state[0] = -1; + Armtronix.knob_state[1] = -1; + ArmtronixSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (ArmtronixSerial->begin(115200)) { + if (ArmtronixSerial->hardwareSerial()) { ClaimSerial(); } + ArmtronixSerial->println("Status"); + } +} + +void ArmtronixSerialInput(void) +{ + String answer; + int8_t newDimState[2]; + uint8_t temp; + int commaIndex; + char scmnd[20]; + if (ArmtronixSerial->available()) { + yield(); + answer = ArmtronixSerial->readStringUntil('\n'); + if (answer.substring(0,7) == "Status:") { + commaIndex = 6; + for (uint32_t i =0; i<2; i++) { + newDimState[i] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + if (newDimState[i] != Armtronix.dim_state[i]) { + temp = ((float)newDimState[i])*1.01010101010101; + Armtronix.dim_state[i] = newDimState[i]; + Armtronix.ignore_dim = true; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "%d %d"),i+1, temp); + ExecuteCommand(scmnd,SRC_SWITCH); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); + } + commaIndex = answer.indexOf(',',commaIndex+1); + } + Armtronix.knob_state[0] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + commaIndex = answer.indexOf(',',commaIndex+1); + Armtronix.knob_state[1] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); + } + } +} + +void ArmtronixSetWifiLed(void) +{ + uint8_t wifi_state = 0x02; + + switch (WifiState()) { + case WIFI_MANAGER: + wifi_state = 0x01; + break; + case WIFI_RESTART: + wifi_state = 0x03; + break; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Set WiFi LED to state %d (%d)"), wifi_state, WifiState()); + + char state = '0' + ((wifi_state & 1) > 0); + ArmtronixSerial->print("Setled:"); + ArmtronixSerial->write(state); + ArmtronixSerial->write(','); + state = '0' + ((wifi_state & 2) > 0); + ArmtronixSerial->write(state); + ArmtronixSerial->write(10); + Armtronix.wifi_state = WifiState(); +} + + + + + +bool Xdrv18(uint8_t function) +{ + bool result = false; + + if (ARMTRONIX_DIMMERS == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (ArmtronixSerial) { ArmtronixSerialInput(); } + break; + case FUNC_MODULE_INIT: + result = ArmtronixModuleSelected(); + break; + case FUNC_INIT: + ArmtronixInit(); + break; + case FUNC_EVERY_SECOND: + if (ArmtronixSerial) { + if (Armtronix.wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } + if (uptime &1) { + ArmtronixSerial->println("Status"); + } + } + break; + case FUNC_SET_CHANNELS: + result = ArmtronixSetChannels(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" +#ifdef USE_LIGHT +#ifdef USE_PS_16_DZ + + + + +#define XDRV_19 19 + +#define PS16DZ_BUFFER_SIZE 80 + +#include + +TasmotaSerial *PS16DZSerial = nullptr; + +struct PS16DZ { + char *rx_buffer = nullptr; + int byte_counter = 0; + uint8_t dimmer = 0; +} Ps16dz; + + + + + +void PS16DZSerialSend(const char *tx_buffer) +{ + + + PS16DZSerial->print(tx_buffer); + PS16DZSerial->write(0x1B); + PS16DZSerial->flush(); +} + +void PS16DZSerialSendOk(void) +{ + char tx_buffer[16]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+SEND=ok")); + PS16DZSerialSend(tx_buffer); +} + + + + +void PS16DZSerialSendUpdateCommand(void) +{ + uint8_t light_state_dimmer = light_state.getDimmer(); + + light_state_dimmer = (light_state_dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : light_state_dimmer; + light_state_dimmer = (light_state_dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : light_state_dimmer; + + char tx_buffer[80]; + snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), + LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); + + PS16DZSerialSend(tx_buffer); +} + + + + + +void PS16DZSerialInput(void) +{ + char scmnd[20]; + while (PS16DZSerial->available()) { + yield(); + uint8_t serial_in_byte = PS16DZSerial->read(); + if (serial_in_byte != 0x1B) { + if (Ps16dz.byte_counter >= PS16DZ_BUFFER_SIZE - 1) { + memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); + Ps16dz.byte_counter = 0; + } + if (Ps16dz.byte_counter || (!Ps16dz.byte_counter && ('A' == serial_in_byte))) { + Ps16dz.rx_buffer[Ps16dz.byte_counter++] = serial_in_byte; + } + } else { + Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; + + + + + if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { + + } + else if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { + + char *end_str; + char *string = Ps16dz.rx_buffer+10; + char *token = strtok_r(string, ",", &end_str); + + bool is_switch_change = false; + bool is_brightness_change = false; + + while (token != nullptr) { + char* end_token; + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); + + if (!strncmp(token2, "\"switch\"", 8)) { + bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + + + is_switch_change = (switch_state != power); + if (is_switch_change) { + ExecuteCommandPower(1, switch_state, SRC_SWITCH); + } + } + else if (!strncmp(token2, "\"bright\"", 8)) { + Ps16dz.dimmer = atoi(token3); + + + + is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer; + if (power && (Ps16dz.dimmer > 0) && is_brightness_change) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Ps16dz.dimmer); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + else if (!strncmp(token2, "\"sequence\"", 10)) { + + + + } + token = strtok_r(nullptr, ",", &end_str); + } + + if (!is_brightness_change) { + + + + PS16DZSerialSendOk(); + } + } + else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) { + + + if (!Settings.flag.button_restrict) { + int state = WIFI_MANAGER; + if (!strncmp(Ps16dz.rx_buffer+10, "=exit", 5)) { state = WIFI_RETRY; } + if (state != Settings.sta_config) { + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " %d"), state); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + } + memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); + Ps16dz.byte_counter = 0; + } + } +} + +bool PS16DZSerialSendUpdateCommandIfRequired(void) +{ + if (!PS16DZSerial) { return true; } + + bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); + bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); + + if (is_switch_change || is_brightness_change) { + PS16DZSerialSendUpdateCommand(); + } + + return true; +} + +void PS16DZInit(void) +{ + Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); + if (Ps16dz.rx_buffer != nullptr) { + PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (PS16DZSerial->begin(19200)) { + if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } + } + } +} + +bool PS16DZModuleSelected(void) +{ + devices_present++; + light_type = LT_SERIAL1; + + return true; +} + + + + + +bool Xdrv19(uint8_t function) +{ + bool result = false; + + if (PS_16_DZ == my_module_type) { + switch (function) { + case FUNC_LOOP: + if (PS16DZSerial) { PS16DZSerialInput(); } + break; + case FUNC_SET_DEVICE_POWER: + case FUNC_SET_CHANNELS: + result = PS16DZSerialSendUpdateCommandIfRequired(); + break; + case FUNC_INIT: + PS16DZInit(); + break; + case FUNC_MODULE_INIT: + result = PS16DZModuleSelected(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_20_hue.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_20_hue.ino" +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) +# 31 "S:/Development/Tasmota/tasmota/xdrv_20_hue.ino" +#define XDRV_20 20 + +const char HUE_RESPONSE[] PROGMEM = + "HTTP/1.1 200 OK\r\n" + "HOST: 239.255.255.250:1900\r\n" + "CACHE-CONTROL: max-age=100\r\n" + "EXT:\r\n" + "LOCATION: http://%s:80/description.xml\r\n" + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.24.0\r\n" + "hue-bridgeid: %s\r\n"; +const char HUE_ST1[] PROGMEM = + "ST: upnp:rootdevice\r\n" + "USN: uuid:%s::upnp:rootdevice\r\n" + "\r\n"; +const char HUE_ST2[] PROGMEM = + "ST: uuid:%s\r\n" + "USN: uuid:%s\r\n" + "\r\n"; +const char HUE_ST3[] PROGMEM = + "ST: urn:schemas-upnp-org:device:basic:1\r\n" + "USN: uuid:%s\r\n" + "\r\n"; + +String HueBridgeId(void) +{ + String temp = WiFi.macAddress(); + temp.replace(":", ""); + String bridgeid = temp.substring(0, 6) + "FFFE" + temp.substring(6); + return bridgeid; +} + +String HueSerialnumber(void) +{ + String serial = WiFi.macAddress(); + serial.replace(":", ""); + serial.toLowerCase(); + return serial; +} + +String HueUuid(void) +{ + String uuid = F("f6543a06-da50-11ba-8d8f-"); + uuid += HueSerialnumber(); + return uuid; +} + +void HueRespondToMSearch(void) +{ + char message[TOPSZ]; + + TickerMSearch.detach(); + if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { + char response[320]; + snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); + int len = strlen(response); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST1, HueUuid().c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST2, HueUuid().c_str(), HueUuid().c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(response + len, sizeof(response) - len, HUE_ST3, HueUuid().c_str()); + PortUdp.write(response); + PortUdp.endPacket(); + + snprintf_P(message, sizeof(message), PSTR(D_3_RESPONSE_PACKETS_SENT)); + } else { + snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); + } + + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), + message, udp_remote_ip.toString().c_str(), udp_remote_port); + + udp_response_mutex = false; +} + + + + + +const char HUE_DESCRIPTION_XML[] PROGMEM = + "" + "" + "" + "1" + "0" + "" + + "http://{x1:80/" + "" + "urn:schemas-upnp-org:device:Basic:1" + "Amazon-Echo-HA-Bridge ({x1)" + + "Royal Philips Electronics" + "http://www.philips.com" + "Philips hue Personal Wireless Lighting" + "Philips hue bridge 2012" + "929000226503" + "{x3" + "uuid:{x2" + "" + "\r\n" + "\r\n"; +const char HUE_LIGHTS_STATUS_JSON1[] PROGMEM = + "{\"on\":{state}," + "{light_status}" + "\"alert\":\"none\"," + "\"effect\":\"none\"," + "\"reachable\":true}"; +const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = + ",\"type\":\"Extended color light\"," + "\"name\":\"{j1\"," + "\"modelid\":\"LCT007\"," + "\"uniqueid\":\"{j2\"," + "\"swversion\":\"5.50.1.19085\"}"; +const char HUE_GROUP0_STATUS_JSON[] PROGMEM = + "{\"name\":\"Group 0\"," + "\"lights\":[{l1]," + "\"type\":\"LightGroup\"," + "\"action\":"; + +const char HueConfigResponse_JSON[] PROGMEM = + "{\"name\":\"Philips hue\"," + "\"mac\":\"{ma\"," + "\"dhcp\":true," + "\"ipaddress\":\"{ip\"," + "\"netmask\":\"{ms\"," + "\"gateway\":\"{gw\"," + "\"proxyaddress\":\"none\"," + "\"proxyport\":0," + "\"bridgeid\":\"{br\"," + "\"UTC\":\"{dt\"," + "\"whitelist\":{\"{id\":{" + "\"last use date\":\"{dt\"," + "\"create date\":\"{dt\"," + "\"name\":\"Remote\"}}," + "\"swversion\":\"01041302\"," + "\"apiversion\":\"1.17.0\"," + "\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false}," + "\"linkbutton\":false," + "\"portalservices\":false" + "}"; +const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM = + "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; +const char HUE_ERROR_JSON[] PROGMEM = + "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; + + + +String GetHueDeviceId(uint8_t id) +{ + String deviceid = WiFi.macAddress() + F(":00:11-") + String(id); + deviceid.toLowerCase(); + return deviceid; +} + +String GetHueUserId(void) +{ + char userid[7]; + + snprintf_P(userid, sizeof(userid), PSTR("%03x"), ESP.getChipId()); + return String(userid); +} + +void HandleUpnpSetupHue(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_HUE_BRIDGE_SETUP)); + String description_xml = FPSTR(HUE_DESCRIPTION_XML); + description_xml.replace("{x1", WiFi.localIP().toString()); + description_xml.replace("{x2", HueUuid()); + description_xml.replace("{x3", HueSerialnumber()); + WSSend(200, CT_XML, description_xml); +} + +void HueNotImplemented(String *path) +{ + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); + + WSSend(200, CT_JSON, "{}"); +} + +void HueConfigResponse(String *response) +{ + *response += FPSTR(HueConfigResponse_JSON); + response->replace("{ma", WiFi.macAddress()); + response->replace("{ip", WiFi.localIP().toString()); + response->replace("{ms", WiFi.subnetMask().toString()); + response->replace("{gw", WiFi.gatewayIP().toString()); + response->replace("{br", HueBridgeId()); + response->replace("{dt", GetDateAndTime(DT_UTC)); + response->replace("{id", GetHueUserId()); +} + +void HueConfig(String *path) +{ + String response = ""; + HueConfigResponse(&response); + WSSend(200, CT_JSON, response); +} + + + +bool g_gotct = false; + + + + +uint16_t prev_hue = 0; +uint8_t prev_sat = 0; +uint8_t prev_bri = 254; +uint16_t prev_ct = 254; +char prev_x_str[24] = "\0"; +char prev_y_str[24] = "\0"; + +uint8_t getLocalLightSubtype(uint8_t device) { + if (light_type) { + if (device >= Light.device) { + if (Settings.flag3.pwm_multi_channels) { + return LST_SINGLE; + } else { + return Light.subtype; + } + } else { + return LST_NONE; + } + } else { + return LST_NONE; + } +} + +void HueLightStatus1(uint8_t device, String *response) +{ + uint16_t ct = 0; + uint8_t color_mode; + String light_status = ""; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint32_t echo_gen = findEchoGeneration(); + + + uint8_t local_light_subtype = getLocalLightSubtype(device); + + bri = LightGetBri(device); + if (bri > 254) bri = 254; + if (bri < 1) bri = 1; + +#ifdef USE_SHUTTER + if (ShutterState(device)) { + bri = (float)((Settings.shutter_options[device-1] & 1) ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; + } +#endif + + if (light_type) { + light_state.getHSB(&hue, &sat, nullptr); + + if ((bri > prev_bri ? bri - prev_bri : prev_bri - bri) < 1) + bri = prev_bri; + + if (sat > 254) sat = 254; + if ((sat > prev_sat ? sat - prev_sat : prev_sat - sat) < 1) { + sat = prev_sat; + } else { + prev_x_str[0] = prev_y_str[0] = 0; + } + + hue = changeUIntScale(hue, 0, 359, 0, 65535); + if ((hue > prev_hue ? hue - prev_hue : prev_hue - hue) < 400) { + hue = prev_hue; + } else { + prev_x_str[0] = prev_y_str[0] = 0; + } + + color_mode = light_state.getColorMode(); + ct = light_state.getCT(); + if (LCM_RGB == color_mode) { g_gotct = false; } + if (LCM_CT == color_mode) { g_gotct = true; } + + + + if ((ct > prev_ct ? ct - prev_ct : prev_ct - ct) < 1) + ct = prev_ct; + + + + } + + *response += FPSTR(HUE_LIGHTS_STATUS_JSON1); + response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); + + if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { + light_status += "\"bri\":"; + light_status += String(bri); + light_status += ","; + } + if (LST_COLDWARM <= local_light_subtype) { + light_status += F("\"colormode\":\""); + light_status += (g_gotct ? "ct" : "hs"); + light_status += "\","; + } + if (LST_RGB <= local_light_subtype) { + if (prev_x_str[0] && prev_y_str[0]) { + light_status += "\"xy\":["; + light_status += prev_x_str; + light_status += ","; + light_status += prev_y_str; + light_status += "],"; + } else { + float x, y; + light_state.getXY(&x, &y); + light_status += "\"xy\":["; + light_status += String(x, 5); + light_status += ","; + light_status += String(y, 5); + light_status += "],"; + } + light_status += "\"hue\":"; + light_status += String(hue); + light_status += ","; + + light_status += "\"sat\":"; + light_status += String(sat); + light_status += ","; + } + if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { + light_status += "\"ct\":"; + light_status += String(ct > 0 ? ct : 284); + light_status += ","; + } + response->replace("{light_status}", light_status); +} + + + +bool HueActive(uint8_t device) { + if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } + return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1); +} + +void HueLightStatus2(uint8_t device, String *response) +{ + *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); + if (device <= MAX_FRIENDLYNAMES) { + response->replace("{j1", SettingsText(SET_FRIENDLYNAME1 +device -1)); + } else { + char fname[33]; + strcpy(fname, SettingsText(SET_FRIENDLYNAME1 + MAX_FRIENDLYNAMES -1)); + uint32_t fname_len = strlen(fname); + if (fname_len > 30) { fname_len = 30; } + fname[fname_len++] = '-'; + if (device - MAX_FRIENDLYNAMES < 10) { + fname[fname_len++] = '0' + device - MAX_FRIENDLYNAMES; + } else { + fname[fname_len++] = 'A' + device - MAX_FRIENDLYNAMES - 10; + } + fname[fname_len] = 0x00; + + response->replace("{j1", fname); + } + response->replace("{j2", GetHueDeviceId(device)); +} + + + + +uint32_t EncodeLightId(uint8_t relay_id) +{ + uint8_t mac[6]; + WiFi.macAddress(mac); + uint32_t id = 0; + + if (relay_id >= 32) { + relay_id = 0; + } + if (relay_id > 15) { + id = (1 << 28); + } + + id |= (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (relay_id & 0xF); + return id; +} + + + +uint32_t DecodeLightId(uint32_t hue_id) { + uint8_t relay_id = hue_id & 0xF; + if (hue_id & (1 << 28)) { + relay_id += 16; + } + if (0 == relay_id) { + relay_id = 32; + } + return relay_id; +} + +static const char * FIRST_GEN_UA[] = { + "AEOBC", +}; + + +uint32_t findEchoGeneration(void) { + + String user_agent = WebServer->header("User-Agent"); + uint32_t gen = 2; + + for (uint32_t i = 0; i < sizeof(FIRST_GEN_UA)/sizeof(char*); i++) { + if (user_agent.indexOf(FIRST_GEN_UA[i]) >= 0) { + gen = 1; + break; + } + } + if (0 == user_agent.length()) { + gen = 1; + } + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, D_LOG_HTTP D_HUE " User-Agent: %s, gen=%d", user_agent.c_str(), gen); + + return gen; +} + +void HueGlobalConfig(String *path) { + String response; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + path->remove(0,1); + response = F("{\"lights\":{"); + bool appending = false; + for (uint32_t i = 1; i <= maxhue; i++) { + if (HueActive(i)) { + if (appending) { response += ","; } + response += "\""; + response += EncodeLightId(i); + response += F("\":{\"state\":"); + HueLightStatus1(i, &response); + HueLightStatus2(i, &response); + appending = true; + } + } + response += F("},\"groups\":{},\"schedules\":{},\"config\":"); + HueConfigResponse(&response); + response += "}"; + WSSend(200, CT_JSON, response); +} + +void HueAuthentication(String *path) +{ + char response[38]; + + snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); + WSSend(200, CT_JSON, response); +} + +void HueLights(String *path) +{ + + + + String response; + int code = 200; + uint16_t tmp = 0; + uint16_t hue = 0; + uint8_t sat = 0; + uint8_t bri = 254; + uint16_t ct = 0; + bool resp = false; + bool on = false; + bool change = false; + uint8_t device = 1; + uint8_t local_light_subtype = Light.subtype; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + path->remove(0,path->indexOf("/lights")); + if (path->endsWith("/lights")) { + response = "{"; + bool appending = false; + for (uint32_t i = 1; i <= maxhue; i++) { + if (HueActive(i)) { + if (appending) { response += ","; } + response += "\""; + response += EncodeLightId(i); + response += F("\":{\"state\":"); + HueLightStatus1(i, &response); + HueLightStatus2(i, &response); + appending = true; + } + } +#ifdef USE_SCRIPT_HUE + Script_Check_Hue(&response); +#endif + response += "}"; + } + else if (path->endsWith("/state")) { + path->remove(0,8); + path->remove(path->indexOf("/state")); + device = DecodeLightId(atoi(path->c_str())); + +#ifdef USE_SCRIPT_HUE + if (device>devices_present) { + return Script_Handle_Hue(path); + } +#endif + + if ((device < 1) || (device > maxhue)) { + device = 1; + } + local_light_subtype = getLocalLightSubtype(device); + + if (WebServer->args()) { + response = "["; + + StaticJsonBuffer<400> jsonBuffer; + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); + if (hue_json.containsKey("on")) { + + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(EncodeLightId(device))); + response.replace("{cm", "on"); + +#ifdef USE_SHUTTER + if (ShutterState(device)) { + if (!change) { + on = hue_json["on"]; + bri = on ? 1.0f : 0.0f; + change = true; + } + response.replace("{re", on ? "true" : "false"); + } else { +#endif + on = hue_json["on"]; + switch(on) + { + case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); + response.replace("{re", "false"); + break; + case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); + response.replace("{re", "true"); + break; + default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); + break; + } + resp = true; +#ifdef USE_SHUTTER + } +#endif + } + + if (light_type && (local_light_subtype >= LST_SINGLE)) { + if (!Settings.flag3.pwm_multi_channels) { + light_state.getHSB(&hue, &sat, nullptr); + bri = light_state.getBri(); + ct = light_state.getCT(); + uint8_t color_mode = light_state.getColorMode(); + if (LCM_RGB == color_mode) { g_gotct = false; } + if (LCM_CT == color_mode) { g_gotct = true; } + + } else { + bri = LightGetBri(device); + } + } + prev_x_str[0] = prev_y_str[0] = 0; + + if (hue_json.containsKey("bri")) { + tmp = hue_json["bri"]; + prev_bri = bri = tmp; + + if (254 <= bri) { bri = 255; } + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "bri"); + response.replace("{re", String(tmp)); + if (LST_SINGLE <= Light.subtype) { + change = true; + } + resp = true; + } + + + if (hue_json.containsKey("xy")) { + float x, y; + x = hue_json["xy"][0]; + y = hue_json["xy"][1]; + const String &x_str = hue_json["xy"][0]; + const String &y_str = hue_json["xy"][1]; + x_str.toCharArray(prev_x_str, sizeof(prev_x_str)); + y_str.toCharArray(prev_y_str, sizeof(prev_y_str)); + + uint8_t rr,gg,bb; + LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); + LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); + prev_hue = changeUIntScale(hue, 0, 359, 0, 65535); + prev_sat = (sat > 254 ? 254 : sat); + + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "xy"); + response.replace("{re", "[" + x_str + "," + y_str + "]"); + g_gotct = false; + resp = true; + change = true; + } + if (hue_json.containsKey("hue")) { + tmp = hue_json["hue"]; + prev_hue = tmp; + + hue = changeUIntScale(tmp, 0, 65535, 0, 359); + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "hue"); + response.replace("{re", String(tmp)); + if (LST_RGB <= Light.subtype) { + g_gotct = false; + change = true; + } + resp = true; + } + if (hue_json.containsKey("sat")) { + tmp = hue_json["sat"]; + prev_sat = sat = tmp; + + if (254 <= sat) { sat = 255; } + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "sat"); + response.replace("{re", String(tmp)); + if (LST_RGB <= Light.subtype) { + g_gotct = false; + change = true; + } + resp = true; + } + if (hue_json.containsKey("ct")) { + ct = hue_json["ct"]; + prev_ct = ct; + if (resp) { response += ","; } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id", String(device)); + response.replace("{cm", "ct"); + response.replace("{re", String(ct)); + if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { + g_gotct = true; + change = true; + } + resp = true; + } + if (change) { +#ifdef USE_SHUTTER + if (ShutterState(device)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_options[device-1] & 1); + ShutterSetPosition(device, bri * 100.0f ); + } else +#endif + if (light_type && (local_light_subtype > LST_NONE)) { + if (!Settings.flag3.pwm_multi_channels) { + if (g_gotct) { + light_controller.changeCTB(ct, bri); + } else { + light_controller.changeHSB(hue, sat, bri); + } + LightPreparePower(); + } else { + LightSetBri(device, bri); + } + if (LST_COLDWARM <= local_light_subtype) { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); + } else { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_DIMMER)); + } + XdrvRulesProcess(); + } + change = false; + } + response += "]"; + if (2 == response.length()) { + response = FPSTR(HUE_ERROR_JSON); + } + } + else { + response = FPSTR(HUE_ERROR_JSON); + } + } + else if(path->indexOf("/lights/") >= 0) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, "/lights path=%s", path->c_str()); + path->remove(0,8); + device = DecodeLightId(atoi(path->c_str())); + +#ifdef USE_SCRIPT_HUE + if (device>devices_present) { + Script_HueStatus(&response,device-devices_present-1); + goto exit; +} +#endif + + if ((device < 1) || (device > maxhue)) { + device = 1; + } + response += F("{\"state\":"); + HueLightStatus1(device, &response); + HueLightStatus2(device, &response); + } + else { + response = "{}"; + code = 406; + } + exit: + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); + WSSend(code, CT_JSON, response); +} + +void HueGroups(String *path) +{ + + + + String response = "{}"; + uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; + + if (path->endsWith("/0")) { + response = FPSTR(HUE_GROUP0_STATUS_JSON); + String lights = F("\"1\""); + for (uint32_t i = 2; i <= maxhue; i++) { + lights += ",\""; + lights += EncodeLightId(i); + lights += "\""; + } + response.replace("{l1", lights); + HueLightStatus1(1, &response); + response += F("}"); + } + + WSSend(200, CT_JSON, response); +} + +void HandleHueApi(String *path) +{ +# 784 "S:/Development/Tasmota/tasmota/xdrv_20_hue.ino" + uint8_t args = 0; + + path->remove(0, 4); + uint16_t apilen = path->length(); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); + for (args = 0; args < WebServer->args(); args++) { + String json = WebServer->arg(args); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); + } + + if (path->endsWith("/invalid/")) {} + else if (!apilen) HueAuthentication(path); + else if (path->endsWith("/")) HueAuthentication(path); + else if (path->endsWith("/config")) HueConfig(path); + else if (path->indexOf("/lights") >= 0) HueLights(path); + else if (path->indexOf("/groups") >= 0) HueGroups(path); + else if (path->endsWith("/schedules")) HueNotImplemented(path); + else if (path->endsWith("/sensors")) HueNotImplemented(path); + else if (path->endsWith("/scenes")) HueNotImplemented(path); + else if (path->endsWith("/rules")) HueNotImplemented(path); + else if (path->endsWith("/resourcelinks")) HueNotImplemented(path); + else HueGlobalConfig(path); +} + + + + + +bool Xdrv20(uint8_t function) +{ + bool result = false; + +#ifdef USE_SCRIPT_HUE + if ((EMUL_HUE == Settings.flag2.emulation)) { +#else + if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) { +#endif + switch (function) { + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/description.xml", HandleUpnpSetupHue); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_21_wemo.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_21_wemo.ino" +#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined (USE_EMULATION_WEMO) + + + + +#define XDRV_21 21 + +const char WEMO_MSEARCH[] PROGMEM = + "HTTP/1.1 200 OK\r\n" + "CACHE-CONTROL: max-age=86400\r\n" + "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" + "EXT:\r\n" + "LOCATION: http://%s:80/setup.xml\r\n" + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" + "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n" + "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n" + "ST: %s\r\n" + "USN: uuid:%s::%s\r\n" + "X-User-Agent: redsonic\r\n" + "\r\n"; + +String WemoSerialnumber(void) +{ + char serial[16]; + + snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId()); + return String(serial); +} + +String WemoUuid(void) +{ + char uuid[27]; + + snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str()); + return String(uuid); +} + +void WemoRespondToMSearch(int echo_type) +{ + char message[TOPSZ]; + + TickerMSearch.detach(); + if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { + char type[24]; + if (1 == echo_type) { + strcpy_P(type, URN_BELKIN_DEVICE_CAP); + } else { + strcpy_P(type, UPNP_ROOTDEVICE); + } + char response[400]; + snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); + PortUdp.write(response); + PortUdp.endPacket(); + snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); + } else { + snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); + } + + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), + echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); + + udp_response_mutex = false; +} + + + + + +const char WEMO_EVENTSERVICE_XML[] PROGMEM = + "" + "" + "" + "SetBinaryState" + "" + "" + "" + "BinaryState" + "BinaryState" + "in" + "" + "" + "" + "" + "GetBinaryState" + "" + "" + "" + "BinaryState" + "BinaryState" + "out" + "" + "" + "" + "" + "" + "" + "BinaryState" + "bool" + "0" + "" + "" + "level" + "string" + "0" + "" + "" + "\r\n\r\n"; + +const char WEMO_METASERVICE_XML[] PROGMEM = + "" + "" + "1" + "0" + "" + "" + "" + "GetMetaInfo" + "" + "" + "GetMetaInfo" + "MetaInfo" + "in" + "" + "" + "" + "" + "" + "MetaInfo" + "string" + "0" + "" + "" + "\r\n\r\n"; + +const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = + "" + "" + "" + "%d" + "" + "" + "\r\n"; + +const char WEMO_SETUP_XML[] PROGMEM = + "" + "" + "" + "urn:Belkin:device:controllee:1" + "{x1" + "Belkin International Inc." + "Socket" + "3.1415" + "uuid:{x2" + "{x3" + "0" + "" + "" + "urn:Belkin:service:basicevent:1" + "urn:Belkin:serviceId:basicevent1" + "/upnp/control/basicevent1" + "/upnp/event/basicevent1" + "/eventservice.xml" + "" + "" + "urn:Belkin:service:metainfo:1" + "urn:Belkin:serviceId:metainfo1" + "/upnp/control/metainfo1" + "/upnp/event/metainfo1" + "/metainfoservice.xml" + "" + "" + "" + "\r\n"; + + + +void HandleUpnpEvent(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); + + char event[500]; + strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); + + + + + char state = 'G'; + if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) { + state = 'S'; + uint8_t power = POWER_TOGGLE; + if (strstr_P(event, PSTR("State>10on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); + WebServer->on("/eventservice.xml", HandleUpnpService); + WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); + WebServer->on("/setup.xml", HandleUpnpSetupWemo); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" +#ifdef USE_SONOFF_IFAN + + + + +#define XDRV_22 22 + +const uint8_t MAX_FAN_SPEED = 4; + +const uint8_t kIFan02Speed[MAX_FAN_SPEED] = { 0x00, 0x01, 0x03, 0x05 }; +const uint8_t kIFan03Speed[MAX_FAN_SPEED +2] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x06 }; +const uint8_t kIFan03Sequence[MAX_FAN_SPEED][MAX_FAN_SPEED] = {{0, 2, 2, 2}, {0, 1, 2, 4}, {1, 1, 2, 5}, {4, 4, 5, 3}}; + +const char kSonoffIfanCommands[] PROGMEM = "|" + D_CMND_FANSPEED; + +void (* const SonoffIfanCommand[])(void) PROGMEM = { + &CmndFanspeed }; + +uint8_t ifan_fanspeed_timer = 0; +uint8_t ifan_fanspeed_goal = 0; +bool ifan_receive_flag = false; +bool ifan_restart_flag = true; + + + +bool IsModuleIfan(void) +{ + return ((SONOFF_IFAN02 == my_module_type) || (SONOFF_IFAN03 == my_module_type)); +} + +uint8_t MaxFanspeed(void) +{ + return MAX_FAN_SPEED; +} + +uint8_t GetFanspeed(void) +{ + if (ifan_fanspeed_timer) { + return ifan_fanspeed_goal; + } else { + + + + + + + uint8_t fanspeed = (uint8_t)(power &0xF) >> 1; + if (fanspeed) { fanspeed = (fanspeed >> 1) +1; } + return fanspeed; + } +} + + + +void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence) +{ + ifan_fanspeed_timer = 0; + ifan_fanspeed_goal = fanspeed; + + uint8_t fanspeed_now = GetFanspeed(); + + if (fanspeed == fanspeed_now) { return; } + + uint8_t fans = kIFan02Speed[fanspeed]; + if (SONOFF_IFAN03 == my_module_type) { + if (sequence) { + fanspeed = kIFan03Sequence[fanspeed_now][ifan_fanspeed_goal]; + if (fanspeed != ifan_fanspeed_goal) { + if (0 == fanspeed_now) { + ifan_fanspeed_timer = 20; + } else { + ifan_fanspeed_timer = 2; + } + } + } + fans = kIFan03Speed[fanspeed]; + } + for (uint32_t i = 2; i < 5; i++) { + uint8_t state = (fans &1) + POWER_OFF_NO_STATE; + ExecuteCommandPower(i, state, SRC_IGNORE); + fans >>= 1; + } + +#ifdef USE_DOMOTICZ + if (sequence) { DomoticzUpdateFanState(); } +#endif +} + + + +void SonoffIfanReceived(void) +{ + char svalue[32]; + + uint8_t mode = serial_in_buffer[3]; + uint8_t action = serial_in_buffer[6]; + + if (4 == mode) { + if (action < 4) { + + + + + if (action != GetFanspeed()) { + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), action); + ExecuteCommand(svalue, SRC_REMOTE); +#ifdef USE_BUZZER + BuzzerEnabledBeep((action) ? action : 1, (action) ? 1 : 4); +#endif + } + } else { + + ExecuteCommandPower(1, POWER_TOGGLE, SRC_REMOTE); + } + } + if (6 == mode) { + + Settings.flag3.buzzer_enable = !Settings.flag3.buzzer_enable; + } + if (7 == mode) { + +#ifdef USE_BUZZER + BuzzerEnabledBeep(4, 1); +#endif + } + + + + serial_in_buffer[5] = 0; + serial_in_buffer[6] = 0; + for (uint32_t i = 0; i < 7; i++) { + if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } + Serial.write(serial_in_buffer[i]); + } +} + +bool SonoffIfanSerialInput(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + if (0xAA == serial_in_byte) { + serial_in_byte_counter = 0; + ifan_receive_flag = true; + } + if (ifan_receive_flag) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (serial_in_byte_counter == 8) { +# 176 "S:/Development/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" + AddLogSerial(LOG_LEVEL_DEBUG); + uint8_t crc = 0; + for (uint32_t i = 2; i < 7; i++) { + crc += serial_in_buffer[i]; + } + if (crc == serial_in_buffer[7]) { + SonoffIfanReceived(); + ifan_receive_flag = false; + return true; + } + } + serial_in_byte = 0; + } + return false; + } +} + + + + + +void CmndFanspeed(void) +{ + if (XdrvMailbox.data_len > 0) { + if ('-' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = (int16_t)GetFanspeed() -1; + if (XdrvMailbox.payload < 0) { XdrvMailbox.payload = MAX_FAN_SPEED -1; } + } + else if ('+' == XdrvMailbox.data[0]) { + XdrvMailbox.payload = GetFanspeed() +1; + if (XdrvMailbox.payload > MAX_FAN_SPEED -1) { XdrvMailbox.payload = 0; } + } + } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_FAN_SPEED)) { + SonoffIFanSetFanspeed(XdrvMailbox.payload, true); + } + ResponseCmndNumber(GetFanspeed()); +} + + + +bool SonoffIfanInit(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + SetSerial(9600, TS_SERIAL_8N1); + } + return false; +} + +void SonoffIfanUpdate(void) +{ + if (SONOFF_IFAN03 == my_module_type) { + if (ifan_fanspeed_timer) { + ifan_fanspeed_timer--; + if (!ifan_fanspeed_timer) { + SonoffIFanSetFanspeed(ifan_fanspeed_goal, false); + } + } + } + + if (ifan_restart_flag && (4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { + ifan_restart_flag = false; + SetDevicePower(1, SRC_RETRY); + SetDevicePower(power, SRC_RETRY); + } +} + + + + + +bool Xdrv22(uint8_t function) +{ + bool result = false; + + if (IsModuleIfan()) { + switch (function) { + case FUNC_EVERY_250_MSECOND: + SonoffIfanUpdate(); + break; + case FUNC_SERIAL: + result = SonoffIfanSerialInput(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kSonoffIfanCommands, SonoffIfanCommand); + break; + case FUNC_MODULE_INIT: + result = SonoffIfanInit(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +#ifdef USE_ZIGBEE + +#define OCCUPANCY "Occupancy" + +typedef uint64_t Z_IEEEAddress; +typedef uint16_t Z_ShortAddress; + +enum ZnpCommandType { + Z_POLL = 0x00, + Z_SREQ = 0x20, + Z_AREQ = 0x40, + Z_SRSP = 0x60 +}; + +enum ZnpSubsystem { + Z_RPC_Error = 0x00, + Z_SYS = 0x01, + Z_MAC = 0x02, + Z_NWK = 0x03, + Z_AF = 0x04, + Z_ZDO = 0x05, + Z_SAPI = 0x06, + Z_UTIL = 0x07, + Z_DEBUG = 0x08, + Z_APP = 0x09 +}; + + +enum SysCommand { + SYS_RESET = 0x00, + SYS_PING = 0x01, + SYS_VERSION = 0x02, + SYS_SET_EXTADDR = 0x03, + SYS_GET_EXTADDR = 0x04, + SYS_RAM_READ = 0x05, + SYS_RAM_WRITE = 0x06, + SYS_OSAL_NV_ITEM_INIT = 0x07, + SYS_OSAL_NV_READ = 0x08, + SYS_OSAL_NV_WRITE = 0x09, + SYS_OSAL_START_TIMER = 0x0A, + SYS_OSAL_STOP_TIMER = 0x0B, + SYS_RANDOM = 0x0C, + SYS_ADC_READ = 0x0D, + SYS_GPIO = 0x0E, + SYS_STACK_TUNE = 0x0F, + SYS_SET_TIME = 0x10, + SYS_GET_TIME = 0x11, + SYS_OSAL_NV_DELETE = 0x12, + SYS_OSAL_NV_LENGTH = 0x13, + SYS_TEST_RF = 0x40, + SYS_TEST_LOOPBACK = 0x41, + SYS_RESET_IND = 0x80, + SYS_OSAL_TIMER_EXPIRED = 0x81, +}; + +enum SapiCommand { + SAPI_START_REQUEST = 0x00, + SAPI_BIND_DEVICE = 0x01, + SAPI_ALLOW_BIND = 0x02, + SAPI_SEND_DATA_REQUEST = 0x03, + SAPI_READ_CONFIGURATION = 0x04, + SAPI_WRITE_CONFIGURATION = 0x05, + SAPI_GET_DEVICE_INFO = 0x06, + SAPI_FIND_DEVICE_REQUEST = 0x07, + SAPI_PERMIT_JOINING_REQUEST = 0x08, + SAPI_SYSTEM_RESET = 0x09, + SAPI_START_CONFIRM = 0x80, + SAPI_BIND_CONFIRM = 0x81, + SAPI_ALLOW_BIND_CONFIRM = 0x82, + SAPI_SEND_DATA_CONFIRM = 0x83, + SAPI_FIND_DEVICE_CONFIRM = 0x85, + SAPI_RECEIVE_DATA_INDICATION = 0x87, +}; +enum Z_configuration { + CONF_EXTADDR = 0x01, + CONF_BOOTCOUNTER = 0x02, + CONF_STARTUP_OPTION = 0x03, + CONF_START_DELAY = 0x04, + CONF_NIB = 0x21, + CONF_DEVICE_LIST = 0x22, + CONF_ADDRMGR = 0x23, + CONF_POLL_RATE = 0x24, + CONF_QUEUED_POLL_RATE = 0x25, + CONF_RESPONSE_POLL_RATE = 0x26, + CONF_REJOIN_POLL_RATE = 0x27, + CONF_DATA_RETRIES = 0x28, + CONF_POLL_FAILURE_RETRIES = 0x29, + CONF_STACK_PROFILE = 0x2A, + CONF_INDIRECT_MSG_TIMEOUT = 0x2B, + CONF_ROUTE_EXPIRY_TIME = 0x2C, + CONF_EXTENDED_PAN_ID = 0x2D, + CONF_BCAST_RETRIES = 0x2E, + CONF_PASSIVE_ACK_TIMEOUT = 0x2F, + CONF_BCAST_DELIVERY_TIME = 0x30, + CONF_NWK_MODE = 0x31, + CONF_CONCENTRATOR_ENABLE = 0x32, + CONF_CONCENTRATOR_DISCOVERY = 0x33, + CONF_CONCENTRATOR_RADIUS = 0x34, + CONF_CONCENTRATOR_RC = 0x36, + CONF_NWK_MGR_MODE = 0x37, + CONF_SRC_RTG_EXPIRY_TIME = 0x38, + CONF_ROUTE_DISCOVERY_TIME = 0x39, + CONF_NWK_ACTIVE_KEY_INFO = 0x3A, + CONF_NWK_ALTERN_KEY_INFO = 0x3B, + CONF_ROUTER_OFF_ASSOC_CLEANUP = 0x3C, + CONF_NWK_LEAVE_REQ_ALLOWED = 0x3D, + CONF_NWK_CHILD_AGE_ENABLE = 0x3E, + CONF_DEVICE_LIST_KA_TIMEOUT = 0x3F, + CONF_BINDING_TABLE = 0x41, + CONF_GROUP_TABLE = 0x42, + CONF_APS_FRAME_RETRIES = 0x43, + CONF_APS_ACK_WAIT_DURATION = 0x44, + CONF_APS_ACK_WAIT_MULTIPLIER = 0x45, + CONF_BINDING_TIME = 0x46, + CONF_APS_USE_EXT_PANID = 0x47, + CONF_APS_USE_INSECURE_JOIN = 0x48, + CONF_COMMISSIONED_NWK_ADDR = 0x49, + CONF_APS_NONMEMBER_RADIUS = 0x4B, + CONF_APS_LINK_KEY_TABLE = 0x4C, + CONF_APS_DUPREJ_TIMEOUT_INC = 0x4D, + CONF_APS_DUPREJ_TIMEOUT_COUNT = 0x4E, + CONF_APS_DUPREJ_TABLE_SIZE = 0x4F, + CONF_DIAGNOSTIC_STATS = 0x50, + CONF_SECURITY_LEVEL = 0x61, + CONF_PRECFGKEY = 0x62, + CONF_PRECFGKEYS_ENABLE = 0x63, + CONF_SECURITY_MODE = 0x64, + CONF_SECURE_PERMIT_JOIN = 0x65, + CONF_APS_LINK_KEY_TYPE = 0x66, + CONF_APS_ALLOW_R19_SECURITY = 0x67, + CONF_IMPLICIT_CERTIFICATE = 0x69, + CONF_DEVICE_PRIVATE_KEY = 0x6A, + CONF_CA_PUBLIC_KEY = 0x6B, + CONF_KE_MAX_DEVICES = 0x6C, + CONF_USE_DEFAULT_TCLK = 0x6D, + CONF_RNG_COUNTER = 0x6F, + CONF_RANDOM_SEED = 0x70, + CONF_TRUSTCENTER_ADDR = 0x71, + CONF_USERDESC = 0x81, + CONF_NWKKEY = 0x82, + CONF_PANID = 0x83, + CONF_CHANLIST = 0x84, + CONF_LEAVE_CTRL = 0x85, + CONF_SCAN_DURATION = 0x86, + CONF_LOGICAL_TYPE = 0x87, + CONF_NWKMGR_MIN_TX = 0x88, + CONF_NWKMGR_ADDR = 0x89, + CONF_ZDO_DIRECT_CB = 0x8F, + CONF_TCLK_TABLE_START = 0x0101, + ZNP_HAS_CONFIGURED = 0xF00 +}; +# 210 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +enum Z_Status { + Z_Success = 0x00, + Z_Failure = 0x01, + Z_InvalidParameter = 0x02, + Z_MemError = 0x03, + Z_Created = 0x09, + Z_BufferFull = 0x11 +}; + +enum Z_App_Profiles { + Z_PROF_IPM = 0x0101, + Z_PROF_HA = 0x0104, + Z_PROF_CBA = 0x0105, + Z_PROF_TA = 0x0107, + Z_PROF_PHHC = 0x0108, + Z_PROF_AMI = 0x0109, +}; + +enum Z_Device_Ids { + Z_DEVID_CONF_TOOL = 0x0005, +# 262 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +}; +# 275 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" +enum AfCommand : uint8_t { + AF_REGISTER = 0x00, + AF_DATA_REQUEST = 0x01, + AF_DATA_REQUEST_EXT = 0x02, + AF_DATA_REQUEST_SRC_RTG = 0x03, + AF_INTER_PAN_CTL = 0x10, + AF_DATA_STORE = 0x11, + AF_DATA_RETRIEVE = 0x12, + AF_APSF_CONFIG_SET = 0x13, + AF_DATA_CONFIRM = 0x80, + AF_REFLECT_ERROR = 0x83, + AF_INCOMING_MSG = 0x81, + AF_INCOMING_MSG_EXT = 0x82 +}; + + +enum : uint8_t { + ZDO_NWK_ADDR_REQ = 0x00, + ZDO_IEEE_ADDR_REQ = 0x01, + ZDO_NODE_DESC_REQ = 0x02, + ZDO_POWER_DESC_REQ = 0x03, + ZDO_SIMPLE_DESC_REQ = 0x04, + ZDO_ACTIVE_EP_REQ = 0x05, + ZDO_MATCH_DESC_REQ = 0x06, + ZDO_COMPLEX_DESC_REQ = 0x07, + ZDO_USER_DESC_REQ = 0x08, + ZDO_DEVICE_ANNCE = 0x0A, + ZDO_USER_DESC_SET = 0x0B, + ZDO_SERVER_DISC_REQ = 0x0C, + ZDO_END_DEVICE_BIND_REQ = 0x20, + ZDO_BIND_REQ = 0x21, + ZDO_UNBIND_REQ = 0x22, + ZDO_SET_LINK_KEY = 0x23, + ZDO_REMOVE_LINK_KEY = 0x24, + ZDO_GET_LINK_KEY = 0x25, + ZDO_MGMT_NWK_DISC_REQ = 0x30, + ZDO_MGMT_LQI_REQ = 0x31, + ZDO_MGMT_RTQ_REQ = 0x32, + ZDO_MGMT_BIND_REQ = 0x33, + ZDO_MGMT_LEAVE_REQ = 0x34, + ZDO_MGMT_DIRECT_JOIN_REQ = 0x35, + ZDO_MGMT_PERMIT_JOIN_REQ = 0x36, + ZDO_MGMT_NWK_UPDATE_REQ = 0x37, + ZDO_MSG_CB_REGISTER = 0x3E, + ZDO_MGS_CB_REMOVE = 0x3F, + ZDO_STARTUP_FROM_APP = 0x40, + ZDO_AUTO_FIND_DESTINATION = 0x41, + ZDO_EXT_REMOVE_GROUP = 0x47, + ZDO_EXT_REMOVE_ALL_GROUP = 0x48, + ZDO_EXT_FIND_ALL_GROUPS_ENDPOINT = 0x49, + ZDO_EXT_FIND_GROUP = 0x4A, + ZDO_EXT_ADD_GROUP = 0x4B, + ZDO_EXT_COUNT_ALL_GROUPS = 0x4C, + ZDO_NWK_ADDR_RSP = 0x80, + ZDO_IEEE_ADDR_RSP = 0x81, + ZDO_NODE_DESC_RSP = 0x82, + ZDO_POWER_DESC_RSP = 0x83, + ZDO_SIMPLE_DESC_RSP = 0x84, + ZDO_ACTIVE_EP_RSP = 0x85, + ZDO_MATCH_DESC_RSP = 0x86, + ZDO_COMPLEX_DESC_RSP = 0x87, + ZDO_USER_DESC_RSP = 0x88, + ZDO_USER_DESC_CONF = 0x89, + ZDO_SERVER_DISC_RSP = 0x8A, + ZDO_END_DEVICE_BIND_RSP = 0xA0, + ZDO_BIND_RSP = 0xA1, + ZDO_UNBIND_RSP = 0xA2, + ZDO_MGMT_NWK_DISC_RSP = 0xB0, + ZDO_MGMT_LQI_RSP = 0xB1, + ZDO_MGMT_RTG_RSP = 0xB2, + ZDO_MGMT_BIND_RSP = 0xB3, + ZDO_MGMT_LEAVE_RSP = 0xB4, + ZDO_MGMT_DIRECT_JOIN_RSP = 0xB5, + ZDO_MGMT_PERMIT_JOIN_RSP = 0xB6, + ZDO_STATE_CHANGE_IND = 0xC0, + ZDO_END_DEVICE_ANNCE_IND = 0xC1, + ZDO_MATCH_DESC_RSP_SENT = 0xC2, + ZDO_STATUS_ERROR_RSP = 0xC3, + ZDO_SRC_RTG_IND = 0xC4, + ZDO_LEAVE_IND = 0xC9, + ZDO_TC_DEV_IND = 0xCA, + ZDO_PERMIT_JOIN_IND = 0xCB, + ZDO_MSG_CB_INCOMING = 0xFF +}; + + +enum ZdoStates { + ZDO_DEV_HOLD = 0x00, + ZDO_DEV_INIT = 0x01, + ZDO_DEV_NWK_DISC = 0x02, + ZDO_DEV_NWK_JOINING = 0x03, + ZDO_DEV_NWK_REJOIN = 0x04, + ZDO_DEV_END_DEVICE_UNAUTH = 0x05, + ZDO_DEV_END_DEVICE = 0x06, + ZDO_DEV_ROUTER = 0x07, + ZDO_DEV_COORD_STARTING = 0x08, + ZDO_DEV_ZB_COORD = 0x09, + ZDO_DEV_NWK_ORPHAN = 0x0A, +}; + + +enum Z_Util { + Z_UTIL_GET_DEVICE_INFO = 0x00, + Z_UTIL_GET_NV_INFO = 0x01, + Z_UTIL_SET_PANID = 0x02, + Z_UTIL_SET_CHANNELS = 0x03, + Z_UTIL_SET_SECLEVEL = 0x04, + Z_UTIL_SET_PRECFGKEY = 0x05, + Z_UTIL_CALLBACK_SUB_CMD = 0x06, + Z_UTIL_KEY_EVENT = 0x07, + Z_UTIL_TIME_ALIVE = 0x09, + Z_UTIL_LED_CONTROL = 0x0A, + Z_UTIL_TEST_LOOPBACK = 0x10, + Z_UTIL_DATA_REQ = 0x11, + Z_UTIL_SRC_MATCH_ENABLE = 0x20, + Z_UTIL_SRC_MATCH_ADD_ENTRY = 0x21, + Z_UTIL_SRC_MATCH_DEL_ENTRY = 0x22, + Z_UTIL_SRC_MATCH_CHECK_SRC_ADDR = 0x23, + Z_UTIL_SRC_MATCH_ACK_ALL_PENDING = 0x24, + Z_UTIL_SRC_MATCH_CHECK_ALL_PENDING = 0x25, + Z_UTIL_ADDRMGR_EXT_ADDR_LOOKUP = 0x40, + Z_UTIL_ADDRMGR_NWK_ADDR_LOOKUP = 0x41, + Z_UTIL_APSME_LINK_KEY_DATA_GET = 0x44, + Z_UTIL_APSME_LINK_KEY_NV_ID_GET = 0x45, + Z_UTIL_ASSOC_COUNT = 0x48, + Z_UTIL_ASSOC_FIND_DEVICE = 0x49, + Z_UTIL_ASSOC_GET_WITH_ADDRESS = 0x4A, + Z_UTIL_APSME_REQUEST_KEY_CMD = 0x4B, + Z_UTIL_ZCL_KEY_EST_INIT_EST = 0x80, + Z_UTIL_ZCL_KEY_EST_SIGN = 0x81, + Z_UTIL_UTIL_SYNC_REQ = 0xE0, + Z_UTIL_ZCL_KEY_ESTABLISH_IND = 0xE1 +}; + +enum ZCL_Global_Commands { + ZCL_READ_ATTRIBUTES = 0x00, + ZCL_READ_ATTRIBUTES_RESPONSE = 0x01, + ZCL_WRITE_ATTRIBUTES = 0x02, + ZCL_WRITE_ATTRIBUTES_UNDIVIDED = 0x03, + ZCL_WRITE_ATTRIBUTES_RESPONSE = 0x04, + ZCL_WRITE_ATTRIBUTES_NORESPONSE = 0x05, + ZCL_CONFIGURE_REPORTING = 0x06, + ZCL_CONFIGURE_REPORTING_RESPONSE = 0x07, + ZCL_READ_REPORTING_CONFIGURATION = 0x08, + ZCL_READ_REPORTING_CONFIGURATION_RESPONSE = 0x09, + ZCL_REPORT_ATTRIBUTES = 0x0a, + ZCL_DEFAULT_RESPONSE = 0x0b, + ZCL_DISCOVER_ATTRIBUTES = 0x0c, + ZCL_DISCOVER_ATTRIBUTES_RESPONSE = 0x0d + +}; + +const uint16_t Z_ProfileIds[] PROGMEM = { 0x0104, 0x0109, 0xA10E, 0xC05E }; +const char Z_ProfileNames[] PROGMEM = "ZigBee Home Automation|ZigBee Smart Energy|ZigBee Green Power|ZigBee Light Link"; + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" +#ifdef USE_ZIGBEE + + + +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId); + + + +JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { + + if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) { + return *(JsonVariant*)nullptr; + } + + for (auto kv : json) { + const char *key = kv.key; + JsonVariant &value = kv.value; + + if (0 == strcasecmp_P(key, needle)) { + return value; + } + } + + return *(JsonVariant*)nullptr; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +#ifdef USE_ZIGBEE + +#ifndef ZIGBEERECEIVED +#define ZIGBEERECEIVED 1 +#endif + +#include +#include + +#ifndef ZIGBEE_SAVE_DELAY_SECONDS +#define ZIGBEE_SAVE_DELAY_SECONDS 10; +#endif +const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; + +typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); + +typedef struct Z_Device { + uint16_t shortaddr; + uint64_t longaddr; + uint32_t firstSeen; + uint32_t lastSeen; + String manufacturerId; + String modelId; + String friendlyName; + std::vector endpoints; + std::vector clusters_in; + std::vector clusters_out; + + uint32_t timer; + uint16_t cluster; + uint16_t endpoint; + uint32_t value; + Z_DeviceTimer func; + + DynamicJsonBuffer *json_buffer; + JsonObject *json; + + uint8_t seqNumber; +} Z_Device; + + + + + + + +class Z_Devices { +public: + Z_Devices() {}; + + + + + + + uint16_t isKnownShortAddr(uint16_t shortaddr) const; + uint16_t isKnownLongAddr(uint64_t longaddr) const; + uint16_t isKnownIndex(uint32_t index) const; + uint16_t isKnownFriendlyName(const char * name) const; + + uint64_t getDeviceLongAddr(uint16_t shortaddr) const; + + + + void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); + + + void addEndoint(uint16_t shortaddr, uint8_t endpoint); + + + void addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId); + + + void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out); + + uint8_t findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster); + + void setManufId(uint16_t shortaddr, const char * str); + void setModelId(uint16_t shortaddr, const char * str); + void setFriendlyName(uint16_t shortaddr, const char * str); + const String * getFriendlyName(uint16_t) const; + + + void updateLastSeen(uint16_t shortaddr); + + + uint8_t getNextSeqNumber(uint16_t shortaddr); + + + String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; + + + void resetTimer(uint32_t shortaddr); + void setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func); + void runTimer(void); + + + void jsonClear(uint16_t shortaddr); + void jsonAppend(uint16_t shortaddr, const JsonObject &values); + const JsonObject *jsonGet(uint16_t shortaddr); + void jsonPublishFlush(uint16_t shortaddr); + bool jsonIsConflict(uint16_t shortaddr, const JsonObject &values); + void jsonPublishNow(uint16_t shortaddr, JsonObject &values); + + + size_t devicesSize(void) const { + return _devices.size(); + } + const Z_Device &devicesAt(size_t i) const { + return _devices.at(i); + } + + + bool removeDevice(uint16_t shortaddr); + + + void dirty(void); + void clean(void); + + + uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const; + +private: + std::vector _devices = {}; + uint32_t _saveTimer = 0; + uint8_t _seqNumber = 0; + + template < typename T> + static bool findInVector(const std::vector & vecOfElements, const T & element); + + template < typename T> + static int32_t findEndpointInVector(const std::vector & vecOfElements, uint8_t element); + + + static int32_t findClusterEndpoint(const std::vector & vecOfElements, uint16_t element); + + Z_Device & getShortAddr(uint16_t shortaddr); + const Z_Device & getShortAddrConst(uint16_t shortaddr) const ; + Z_Device & getLongAddr(uint64_t longaddr); + + int32_t findShortAddr(uint16_t shortaddr) const; + int32_t findLongAddr(uint64_t longaddr) const; + int32_t findFriendlyName(const char * name) const; + + void _updateLastSeen(Z_Device &device) { + if (&device != nullptr) { + device.lastSeen = Rtc.utc_time; + } + }; + + + Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0); +}; + +Z_Devices zigbee_devices = Z_Devices(); + + +uint64_t localIEEEAddr = 0; + + +template < typename T> +bool Z_Devices::findInVector(const std::vector & vecOfElements, const T & element) { + + auto it = std::find(vecOfElements.begin(), vecOfElements.end(), element); + + if (it != vecOfElements.end()) { + return true; + } else { + return false; + } +} + +template < typename T> +int32_t Z_Devices::findEndpointInVector(const std::vector & vecOfElements, uint8_t element) { + + + int32_t found = 0; + for (auto &elem : vecOfElements) { + if ( ((elem >> 16) & 0xFF) == element) { return found; } + found++; + } + + return -1; +} +# 214 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +int32_t Z_Devices::findClusterEndpoint(const std::vector & vecOfElements, uint16_t cluster) { + int32_t found = 0; + for (auto &elem : vecOfElements) { + if ((elem & 0xFFFF) == cluster) { return found; } + found++; + } + return -1; +} + + + + + +Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { + if (!shortaddr && !longaddr) { return *(Z_Device*) nullptr; } + Z_Device device = { shortaddr, longaddr, + Rtc.utc_time, Rtc.utc_time, + String(), + String(), + String(), + std::vector(), + std::vector(), + std::vector(), + 0,0,0,0, + nullptr, + nullptr, nullptr, + 0, + }; + device.json_buffer = new DynamicJsonBuffer(); + _devices.push_back(device); + dirty(); + return _devices.back(); +} +# 256 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +int32_t Z_Devices::findShortAddr(uint16_t shortaddr) const { + if (!shortaddr) { return -1; } + int32_t found = 0; + if (shortaddr) { + for (auto &elem : _devices) { + if (elem.shortaddr == shortaddr) { return found; } + found++; + } + } + return -1; +} +# 275 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +int32_t Z_Devices::findLongAddr(uint64_t longaddr) const { + if (!longaddr) { return -1; } + int32_t found = 0; + if (longaddr) { + for (auto &elem : _devices) { + if (elem.longaddr == longaddr) { return found; } + found++; + } + } + return -1; +} +# 294 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" +int32_t Z_Devices::findFriendlyName(const char * name) const { + if (!name) { return -1; } + size_t name_len = strlen(name); + int32_t found = 0; + if (name_len) { + for (auto &elem : _devices) { + if (elem.friendlyName == name) { return found; } + found++; + } + } + return -1; +} + + +uint16_t Z_Devices::isKnownShortAddr(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + return shortaddr; + } else { + return 0; + } +} + +uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const { + int32_t found = findLongAddr(longaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.shortaddr; + } else { + return 0; + } +} + +uint16_t Z_Devices::isKnownIndex(uint32_t index) const { + if (index < devicesSize()) { + const Z_Device & device = devicesAt(index); + return device.shortaddr; + } else { + return 0; + } +} + +uint16_t Z_Devices::isKnownFriendlyName(const char * name) const { + if ((!name) || (0 == strlen(name))) { return 0xFFFF; } + int32_t found = findFriendlyName(name); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + return device.shortaddr; + } else { + return 0; + } +} + +uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const { + const Z_Device & device = getShortAddrConst(shortaddr); + return device.longaddr; +} + + + + +Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) { + if (!shortaddr) { return *(Z_Device*) nullptr; } + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + return _devices[found]; + } + + return createDeviceEntry(shortaddr, 0); +} + +const Z_Device & Z_Devices::getShortAddrConst(uint16_t shortaddr) const { + if (!shortaddr) { return *(Z_Device*) nullptr; } + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + return _devices[found]; + } + return *((Z_Device*)nullptr); +} + + +Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) { + if (!longaddr) { return *(Z_Device*) nullptr; } + int32_t found = findLongAddr(longaddr); + if (found > 0) { + return _devices[found]; + } + return createDeviceEntry(0, longaddr); +} + + +bool Z_Devices::removeDevice(uint16_t shortaddr) { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + _devices.erase(_devices.begin() + found); + dirty(); + return true; + } + return false; +} + + + + + + +void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { + int32_t s_found = findShortAddr(shortaddr); + int32_t l_found = findLongAddr(longaddr); + + if ((s_found >= 0) && (l_found >= 0)) { + if (s_found == l_found) { + updateLastSeen(shortaddr); + } else { + + _devices[l_found].shortaddr = shortaddr; + + _devices.erase(_devices.begin() + s_found); + updateLastSeen(shortaddr); + dirty(); + } + } else if (s_found >= 0) { + + + _devices[s_found].longaddr = longaddr; + updateLastSeen(shortaddr); + dirty(); + } else if (l_found >= 0) { + + _devices[l_found].shortaddr = shortaddr; + dirty(); + } else { + + if (shortaddr || longaddr) { + createDeviceEntry(shortaddr, longaddr); + } + } +} + + + + +void Z_Devices::addEndoint(uint16_t shortaddr, uint8_t endpoint) { + if (!shortaddr) { return; } + uint32_t ep_profile = (endpoint << 16); + Z_Device &device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + if (findEndpointInVector(device.endpoints, endpoint) < 0) { + device.endpoints.push_back(ep_profile); + dirty(); + } +} + +void Z_Devices::addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId) { + if (!shortaddr) { return; } + uint32_t ep_profile = (endpoint << 16) | profileId; + Z_Device &device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + int32_t found = findEndpointInVector(device.endpoints, endpoint); + if (found < 0) { + device.endpoints.push_back(ep_profile); + dirty(); + } else { + if (device.endpoints[found] != ep_profile) { + device.endpoints[found] = ep_profile; + dirty(); + } + } +} + +void Z_Devices::addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out) { + if (!shortaddr) { return; } + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + uint32_t ep_cluster = (endpoint << 16) | cluster; + if (!out) { + if (!findInVector(device.clusters_in, ep_cluster)) { + device.clusters_in.push_back(ep_cluster); + dirty(); + } + } else { + if (!findInVector(device.clusters_out, ep_cluster)) { + device.clusters_out.push_back(ep_cluster); + dirty(); + } + } +} + + + +uint8_t Z_Devices::findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster){ + int32_t short_found = findShortAddr(shortaddr); + if (short_found < 0) return 0; + Z_Device &device = getShortAddr(shortaddr); + if (&device == nullptr) { return 0; } + int32_t found = findClusterEndpoint(device.clusters_in, cluster); + if (found >= 0) { + return (device.clusters_in[found] >> 16) & 0xFF; + } else { + return 0; + } +} + + +void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + if (!device.manufacturerId.equals(str)) { + dirty(); + } + device.manufacturerId = str; +} +void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + if (!device.modelId.equals(str)) { + dirty(); + } + device.modelId = str; +} +void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); + if (!device.friendlyName.equals(str)) { + dirty(); + } + device.friendlyName = str; +} + +const String * Z_Devices::getFriendlyName(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + if (device.friendlyName.length() > 0) { + return &device.friendlyName; + } + } + return nullptr; +} + + +void Z_Devices::updateLastSeen(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + _updateLastSeen(device); +} + + +uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) { + int32_t short_found = findShortAddr(shortaddr); + if (short_found >= 0) { + Z_Device &device = getShortAddr(shortaddr); + device.seqNumber += 1; + return device.seqNumber; + } else { + _seqNumber += 1; + return _seqNumber; + } +} + + + + +void Z_Devices::resetTimer(uint32_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + device.timer = 0; + device.func = nullptr; +} + + +void Z_Devices::setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + + device.cluster = cluster; + device.endpoint = endpoint; + device.value = value; + device.func = func; + device.timer = wait_ms + millis(); +} + + +void Z_Devices::runTimer(void) { + for (std::vector::iterator it = _devices.begin(); it != _devices.end(); ++it) { + Z_Device &device = *it; + uint16_t shortaddr = device.shortaddr; + + uint32_t timer = device.timer; + if ((timer) && TimeReached(timer)) { + device.timer = 0; + + (*device.func)(device.shortaddr, device.cluster, device.endpoint, device.value); + } + } + + if ((_saveTimer) && TimeReached(_saveTimer)) { + saveZigbeeDevices(); + _saveTimer = 0; + } +} + +void Z_Devices::jsonClear(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + + device.json = nullptr; + device.json_buffer->clear(); +} + +void CopyJsonVariant(JsonObject &to, const String &key, const JsonVariant &val) { + to.remove(key); + + if (val.is()) { + String sval = val.as(); + to.set(key, sval); + } else if (val.is()) { + JsonArray &nested_arr = to.createNestedArray(key); + CopyJsonArray(nested_arr, val.as()); + } else if (val.is()) { + JsonObject &nested_obj = to.createNestedObject(key); + CopyJsonObject(nested_obj, val.as()); + } else { + to.set(key, val); + } +} + +void CopyJsonArray(JsonArray &to, const JsonArray &arr) { + for (auto v : arr) { + if (v.is()) { + String sval = v.as(); + to.add(sval); + } else if (v.is()) { + } else if (v.is()) { + } else { + to.add(v); + } + } +} + +void CopyJsonObject(JsonObject &to, const JsonObject &from) { + for (auto kv : from) { + String key_string = kv.key; + JsonVariant &val = kv.value; + + CopyJsonVariant(to, key_string, val); + } +} + + +bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const JsonObject &values) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return false; } + if (&values == nullptr) { return false; } + + if (nullptr == device.json) { + return false; + } + + for (auto kv : values) { + String key_string = kv.key; + + if (strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_LINKQUALITY))) { + if (device.json->containsKey(kv.key)) { + return true; + } + } + } + return false; +} + +void Z_Devices::jsonAppend(uint16_t shortaddr, const JsonObject &values) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + if (&values == nullptr) { return; } + + if (nullptr == device.json) { + device.json = &(device.json_buffer->createObject()); + } + + char sa[8]; + snprintf_P(sa, sizeof(sa), PSTR("0x%04X"), shortaddr); + device.json->set(F(D_JSON_ZIGBEE_DEVICE), sa); + + const String * fname = zigbee_devices.getFriendlyName(shortaddr); + if (fname) { + device.json->set(F(D_JSON_ZIGBEE_NAME), (char*)fname->c_str()); + } + + + CopyJsonObject(*device.json, values); +} + +const JsonObject *Z_Devices::jsonGet(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return nullptr; } + return device.json; +} + +void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { + Z_Device & device = getShortAddr(shortaddr); + if (&device == nullptr) { return; } + JsonObject * json = device.json; + if (json == nullptr) { return; } + + const String * fname = zigbee_devices.getFriendlyName(shortaddr); + bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); +# 718 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" + if (use_fname) { + json->remove(F(D_JSON_ZIGBEE_NAME)); + } else { + json->remove(F(D_JSON_ZIGBEE_DEVICE)); + } + + String msg = ""; + json->printTo(msg); + zigbee_devices.jsonClear(shortaddr); + + if (use_fname) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); +#if ZIGBEERECEIVED + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); +#endif + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); +#if ZIGBEERECEIVED + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); +#endif + } + + +} + +void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { + jsonPublishFlush(shortaddr); + jsonAppend(shortaddr, values); + jsonPublishFlush(shortaddr); +} + +void Z_Devices::dirty(void) { + _saveTimer = kZigbeeSaveDelaySeconds * 1000 + millis(); +} +void Z_Devices::clean(void) { + _saveTimer = 0; +} + + + + + + +uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const { + if (nullptr == param) { return 0; } + size_t param_len = strlen(param); + char dataBuf[param_len + 1]; + strcpy(dataBuf, param); + RemoveSpace(dataBuf); + uint16_t shortaddr = 0; + + if (strlen(dataBuf) < 4) { + + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) { + shortaddr = zigbee_devices.isKnownIndex(XdrvMailbox.payload - 1); + } + } else if ((dataBuf[0] == '0') && (dataBuf[1] == 'x')) { + + if (strlen(dataBuf) < 18) { + + shortaddr = strtoull(dataBuf, nullptr, 0); + if (short_must_be_known) { + shortaddr = zigbee_devices.isKnownShortAddr(shortaddr); + } + + } else { + + uint64_t longaddr = strtoull(dataBuf, nullptr, 0); + shortaddr = zigbee_devices.isKnownLongAddr(longaddr); + } + } else { + + shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf); + } + + return shortaddr; +} + + + + + +String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { + DynamicJsonBuffer jsonBuffer; + JsonArray& json = jsonBuffer.createArray(); + JsonArray& devices = json; + + for (std::vector::const_iterator it = _devices.begin(); it != _devices.end(); ++it) { + const Z_Device& device = *it; + uint16_t shortaddr = device.shortaddr; + char hex[22]; + + + if ((status_shortaddr) && (status_shortaddr != shortaddr)) { continue; } + + JsonObject& dev = devices.createNestedObject(); + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); + dev[F(D_JSON_ZIGBEE_DEVICE)] = hex; + + if (device.friendlyName.length() > 0) { + dev[F(D_JSON_ZIGBEE_NAME)] = device.friendlyName; + } + + if (2 <= dump_mode) { + hex[0] = '0'; + hex[1] = 'x'; + Uint64toHex(device.longaddr, &hex[2], 64); + dev[F("IEEEAddr")] = hex; + if (device.modelId.length() > 0) { + dev[F(D_JSON_MODEL D_JSON_ID)] = device.modelId; + } + if (device.manufacturerId.length() > 0) { + dev[F("Manufacturer")] = device.manufacturerId; + } + } + + + if (3 <= dump_mode) { + JsonObject& dev_endpoints = dev.createNestedObject(F("Endpoints")); + for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { + uint32_t ep_profile = *ite; + uint8_t endpoint = (ep_profile >> 16) & 0xFF; + uint16_t profileId = ep_profile & 0xFFFF; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + JsonObject& ep = dev_endpoints.createNestedObject(hex); + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), profileId); + ep[F("ProfileId")] = hex; + + int32_t found = -1; + for (uint32_t i = 0; i < sizeof(Z_ProfileIds) / sizeof(Z_ProfileIds[0]); i++) { + if (pgm_read_word(&Z_ProfileIds[i]) == profileId) { + found = i; + break; + } + } + if (found > 0) { + GetTextIndexed(hex, sizeof(hex), found, Z_ProfileNames); + ep[F("ProfileIdName")] = hex; + } + + ep.createNestedArray(F("ClustersIn")); + ep.createNestedArray(F("ClustersOut")); + } + + for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t endpoint = (*itc >> 16) & 0xFF; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersIn")]; + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); + cluster_arr.add(hex); + } + + for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t endpoint = (*itc >> 16) & 0xFF; + + snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); + JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersOut")]; + + snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); + cluster_arr.add(hex); + } + } + } + String payload = ""; + payload.reserve(200); + json.printTo(payload); + return payload; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +#ifdef USE_ZIGBEE +# 50 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" +const static uint16_t z_spi_start_sector = 0xFF; +const static uint8_t* z_spi_start = (uint8_t*) 0x402FF000; +const static uint8_t* z_dev_start = z_spi_start + 0x0800; +const static size_t z_spi_len = 0x1000; +const static size_t z_block_offset = 0x0800; +const static size_t z_block_len = 0x0800; + +class z_flashdata_t { +public: + uint32_t name; + uint16_t len; + uint16_t reserved; +}; + +const static uint32_t ZIGB_NAME = 0x3167697A; +const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); + + +const uint16_t Z_ClusterNumber[] PROGMEM = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0100, 0x0101, 0x0102, + 0x0201, 0x0202, 0x0203, 0x0204, + 0x0300, 0x0301, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, + 0x0500, 0x0501, 0x0502, + 0x0700, 0x0701, 0x0702, + 0x0B00, 0x0B01, 0x0B02, 0x0B03, 0x0B04, 0x0B05, + 0x1000, + 0xFC0F, +}; + + +uint16_t fromClusterCode(uint8_t c) { + if (c >= sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0])) { + return 0xFFFF; + } + return pgm_read_word(&Z_ClusterNumber[c]); +} + + +uint8_t toClusterCode(uint16_t c) { + for (uint32_t i = 0; i < sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0]); i++) { + if (c == pgm_read_word(&Z_ClusterNumber[i])) { + return i; + } + } + return 0xFF; +} + +class SBuffer hibernateDevice(const struct Z_Device &device) { + SBuffer buf(128); + + buf.add8(0x00); + buf.add16(device.shortaddr); + buf.add64(device.longaddr); + uint32_t endpoints = device.endpoints.size(); + if (endpoints > 254) { endpoints = 254; } + buf.add8(endpoints); + + for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { + uint32_t ep_profile = *ite; + uint8_t endpoint = (ep_profile >> 16) & 0xFF; + uint16_t profileId = ep_profile & 0xFFFF; + + buf.add8(endpoint); + buf.add16(profileId); + for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t c_endpoint = (*itc >> 16) & 0xFF; + + if (endpoint == c_endpoint) { + uint8_t clusterCode = toClusterCode(cluster); + if (0xFF != clusterCode) { buf.add8(clusterCode); } + } + } + buf.add8(0xFF); + + for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { + uint16_t cluster = *itc & 0xFFFF; + uint8_t c_endpoint = (*itc >> 16) & 0xFF; + + if (endpoint == c_endpoint) { + uint8_t clusterCode = toClusterCode(cluster); + if (0xFF != clusterCode) { buf.add8(clusterCode); } + } + } + buf.add8(0xFF); + } + + + size_t model_len = device.modelId.length(); + if (model_len > 32) { model_len = 32; } + buf.addBuffer(device.modelId.c_str(), model_len); + buf.add8(0x00); + + + size_t manuf_len = device.manufacturerId.length(); + if (manuf_len > 32) {manuf_len = 32; } + buf.addBuffer(device.manufacturerId.c_str(), manuf_len); + buf.add8(0x00); + + + size_t frname_len = device.friendlyName.length(); + if (frname_len > 32) {frname_len = 32; } + buf.addBuffer(device.friendlyName.c_str(), frname_len); + buf.add8(0x00); + + + buf.set8(0, buf.len()); + + return buf; +} + +class SBuffer hibernateDevices(void) { + SBuffer buf(2048); + + size_t devices_size = zigbee_devices.devicesSize(); + if (devices_size > 32) { devices_size = 32; } + buf.add8(devices_size); + + for (uint32_t i = 0; i < devices_size; i++) { + const Z_Device & device = zigbee_devices.devicesAt(i); + const SBuffer buf_device = hibernateDevice(device); + buf.addBuffer(buf_device); + } + + size_t buf_len = buf.len(); + if (buf_len > 2040) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Devices list too big to fit in Flash (%d)"), buf_len); + } + + + char *hex_char = (char*) malloc((buf_len * 2) + 2); + if (hex_char) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbFlashStore %s"), + ToHex_P(buf.getBuffer(), buf_len, hex_char, (buf_len * 2) + 2)); + free(hex_char); + } + + return buf; +} + +void hidrateDevices(const SBuffer &buf) { + uint32_t buf_len = buf.len(); + if (buf_len <= 10) { return; } + + uint32_t k = 0; + uint32_t num_devices = buf.get8(k++); + + for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { + uint32_t dev_record_len = buf.get8(k); + + SBuffer buf_d = buf.subBuffer(k, dev_record_len); + + uint32_t d = 1; + uint16_t shortaddr = buf_d.get16(d); d += 2; + uint64_t longaddr = buf_d.get64(d); d += 8; + zigbee_devices.updateDevice(shortaddr, longaddr); + + uint32_t endpoints = buf_d.get8(d++); + for (uint32_t j = 0; j < endpoints; j++) { + uint8_t ep = buf_d.get8(d++); + uint16_t ep_profile = buf_d.get16(d); d += 2; + zigbee_devices.addEndointProfile(shortaddr, ep, ep_profile); + + + while (d < dev_record_len) { + uint8_t ep_cluster = buf_d.get8(d++); + if (0xFF == ep_cluster) { break; } + zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), false); + } + + while (d < dev_record_len) { + uint8_t ep_cluster = buf_d.get8(d++); + if (0xFF == ep_cluster) { break; } + zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), true); + } + } + + + char empty[] = ""; + + + uint32_t s_len = buf_d.strlen_s(d); + char *ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setModelId(shortaddr, ptr); + d += s_len + 1; + + + s_len = buf_d.strlen_s(d); + ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setManufId(shortaddr, ptr); + d += s_len + 1; + + + s_len = buf_d.strlen_s(d); + ptr = s_len ? buf_d.charptr(d) : empty; + zigbee_devices.setFriendlyName(shortaddr, ptr); + d += s_len + 1; + + + k += dev_record_len; + } +} + +void loadZigbeeDevices(void) { + z_flashdata_t flashdata; + memcpy_P(&flashdata, z_dev_start, sizeof(z_flashdata_t)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Zigbee signature in Flash: %08X - %d"), flashdata.name, flashdata.len); + + + if ((flashdata.name == ZIGB_NAME) && (flashdata.len > 0)) { + uint16_t buf_len = flashdata.len; + + SBuffer buf(buf_len); + buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); + hidrateDevices(buf); + zigbee_devices.clean(); + } else { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "No zigbee devices data in Flash")); + } +} + +void saveZigbeeDevices(void) { + SBuffer buf = hibernateDevices(); + size_t buf_len = buf.len(); + if (buf_len > Z_MAX_FLASH) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Buffer too big to fit in Flash (%d bytes)"), buf_len); + return; + } + + + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + + ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + + z_flashdata_t *flashdata = (z_flashdata_t*)(spi_buffer + z_block_offset); + flashdata->name = ZIGB_NAME; + flashdata->len = buf_len; + flashdata->reserved = 0; + + memcpy(spi_buffer + z_block_offset + sizeof(z_flashdata_t), buf.getBuffer(), buf_len); + + + if (ESP.flashEraseSector(z_spi_start_sector)) { + ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + + free(spi_buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data store in Flash (0x%08X - %d bytes)"), z_dev_start, buf_len); +} + + +void eraseZigbeeDevices(void) { + zigbee_devices.clean(); + + uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); + if (!spi_buffer) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); + return; + } + + ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + + + memset(spi_buffer + z_block_offset, 0xFF, z_block_len); + + + if (ESP.flashEraseSector(z_spi_start_sector)) { + ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); + } + + free(spi_buffer); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (0x%08X - %d bytes)"), z_dev_start, z_block_len); +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" +#ifdef USE_ZIGBEE + + + + + +typedef union ZCLHeaderFrameControl_t { + struct { + uint8_t frame_type : 2; + uint8_t manuf_specific : 1; + uint8_t direction : 1; + uint8_t disable_def_resp : 1; + uint8_t reserved : 3; + } b; + uint32_t d8; +} ZCLHeaderFrameControl_t; + + +class ZCLFrame { +public: + + ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id, + const char *buf, size_t buf_len, uint16_t clusterid, uint16_t groupid, + uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, + uint32_t timestamp): + _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), + _payload(buf_len ? buf_len : 250), + _cluster_id(clusterid), _group_id(groupid), + _srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast), + _linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber), + _timestamp(timestamp) + { + _frame_control.d8 = frame_control; + _payload.addBuffer(buf, buf_len); + }; + + + void log(void) { + char hex_char[_payload.len()*2+2]; + ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); + Response_P(PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" + "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," + "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," + "\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," + "\"timestamp\":%d," + "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," + "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), + _group_id, _cluster_id, _srcaddr, + _srcendpoint, _dstendpoint, _wasbroadcast, + _linkquality, _securityuse, _seqnumber, + _timestamp, + _frame_control, _manuf_code, _transact_seq, _cmd_id, + hex_char); + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); + } + } + + static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid, + uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, + uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, + uint32_t timestamp) { + uint32_t i = offset; + ZCLHeaderFrameControl_t frame_control; + uint16_t manuf_code = 0; + uint8_t transact_seq; + uint8_t cmd_id; + + frame_control.d8 = buf.get8(i++); + if (frame_control.b.manuf_specific) { + manuf_code = buf.get16(i); + i += 2; + } + transact_seq = buf.get8(i++); + cmd_id = buf.get8(i++); + ZCLFrame zcl_frame(frame_control.d8, manuf_code, transact_seq, cmd_id, + (const char *)(buf.buf() + i), len + offset - i, + clusterid, groupid, + srcaddr, srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp); + return zcl_frame; + } + + bool isClusterSpecificCommand(void) { + return _frame_control.b.frame_type & 1; + } + + static void generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len); + void parseRawAttributes(JsonObject& json, uint8_t offset = 0); + void parseReadAttributes(JsonObject& json, uint8_t offset = 0); + void parseClusterSpecificCommand(JsonObject& json, uint8_t offset = 0); + void postProcessAttributes(uint16_t shortaddr, JsonObject& json); + + inline void setGroupId(uint16_t groupid) { + _group_id = groupid; + } + + inline void setClusterId(uint16_t clusterid) { + _cluster_id = clusterid; + } + + inline uint8_t getCmdId(void) const { + return _cmd_id; + } + + inline uint16_t getClusterId(void) const { + return _cluster_id; + } + + inline uint16_t getSrcEndpoint(void) const { + return _srcendpoint; + } + + const SBuffer &getPayload(void) const { + return _payload; + } + + uint16_t getManufCode(void) const { + return _manuf_code; + } + +private: + ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; + uint16_t _manuf_code = 0; + uint8_t _transact_seq = 0; + uint8_t _cmd_id = 0; + uint16_t _cluster_id = 0; + uint16_t _group_id = 0; + SBuffer _payload; + + uint16_t _srcaddr; + uint8_t _srcendpoint; + uint8_t _dstendpoint; + uint8_t _wasbroadcast; + uint8_t _linkquality; + uint8_t _securityuse; + uint8_t _seqnumber; + uint32_t _timestamp; +}; + + + + + + +uint8_t toPercentageCR2032(uint32_t voltage) { + uint32_t percentage; + if (voltage < 2100) { + percentage = 0; + } else if (voltage < 2440) { + percentage = 6 - ((2440 - voltage) * 6) / 340; + } else if (voltage < 2740) { + percentage = 18 - ((2740 - voltage) * 12) / 300; + } else if (voltage < 2900) { + percentage = 42 - ((2900 - voltage) * 24) / 160; + } else if (voltage < 3000) { + percentage = 100 - ((3000 - voltage) * 58) / 100; + } else if (voltage >= 3000) { + percentage = 100; + } + return percentage; +} + + +uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, + uint32_t offset, uint32_t len) { + + uint32_t i = offset; + uint32_t attrtype = buf.get8(i++); + + + json[attrid_str] = (char*) nullptr; + + + switch (attrtype) { + case 0x00: + case 0xFF: + break; + case 0x10: + { + uint8_t val_bool = buf.get8(i++); + if (0xFF != val_bool) { + json[attrid_str] = (bool) (val_bool ? true : false); + } + } + break; + case 0x20: + { + uint8_t uint8_val = buf.get8(i); + i += 1; + if (0xFF != uint8_val) { + json[attrid_str] = uint8_val; + } + } + break; + case 0x21: + { + uint16_t uint16_val = buf.get16(i); + i += 2; + if (0xFFFF != uint16_val) { + json[attrid_str] = uint16_val; + } + } + break; + case 0x23: + { + uint32_t uint32_val = buf.get32(i); + i += 4; + if (0xFFFFFFFF != uint32_val) { + json[attrid_str] = uint32_val; + } + } + break; + + case 0x24: + case 0x25: + case 0x26: + case 0x27: + { + uint8_t len = attrtype - 0x1F; + + char hex[2*len+1]; + ToHex_P(buf.buf(i), len, hex, sizeof(hex)); + json[attrid_str] = hex; + i += len; + } + break; + case 0x28: + { + int8_t int8_val = buf.get8(i); + i += 1; + if (0x80 != int8_val) { + json[attrid_str] = int8_val; + } + } + break; + case 0x29: + { + int16_t int16_val = buf.get16(i); + i += 2; + if (0x8000 != int16_val) { + json[attrid_str] = int16_val; + } + } + break; + case 0x2B: + { + int32_t int32_val = buf.get32(i); + i += 4; + if (0x80000000 != int32_val) { + json[attrid_str] = int32_val; + } + } + break; + + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + { + uint8_t len = attrtype - 0x27; + + char hex[2*len+1]; + ToHex_P(buf.buf(i), len, hex, sizeof(hex)); + json[attrid_str] = hex; + i += len; + } + break; + + case 0x41: + case 0x42: + case 0x43: + case 0x44: + + { + bool parse_as_string = true; + uint32_t len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); + i += (attrtype <= 0x42) ? 1 : 2; + if (i + len > buf.len()) { + len = buf.len() - i; + } + + + if ((0x41 == attrtype) || (0x43 == attrtype)) { parse_as_string = false; } +# 318 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" + if (parse_as_string) { + char str[len+1]; + strncpy(str, buf.charptr(i), len); + str[len] = 0x00; + json[attrid_str] = str; + } else { + + char hex[2*len+1]; + ToHex_P(buf.buf(i), len, hex, sizeof(hex)); + json[attrid_str] = hex; + } + + i += len; + break; + } + i += buf.get8(i) + 1; + break; + + case 0x08: + case 0x18: + { + uint8_t uint8_val = buf.get8(i); + i += 1; + json[attrid_str] = uint8_val; + } + break; + case 0x09: + case 0x19: + { + uint16_t uint16_val = buf.get16(i); + i += 2; + json[attrid_str] = uint16_val; + } + break; + case 0x0B: + case 0x1B: + { + uint32_t uint32_val = buf.get32(i); + i += 4; + json[attrid_str] = uint32_val; + } + break; + + case 0x30: + case 0x31: + i += attrtype - 0x2F; + break; + + + case 0x39: + { + uint32_t uint32_val = buf.get32(i); + float * float_val = (float*) &uint32_val; + i += 4; + json[attrid_str] = *float_val; + } + break; + + case 0xE0: + case 0xE1: + case 0xE2: + i += 4; + break; + + case 0xE8: + case 0xE9: + i += 2; + break; + case 0xEA: + i += 4; + break; + + case 0xF0: + i += 8; + break; + case 0xF1: + i += 16; + break; + + + case 0x0A: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + i += attrtype - 0x07; + break; + + case 0x1A: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + i += attrtype - 0x17; + break; + + case 0x38: + i += 2; + break; + case 0x3A: + { + uint64_t uint64_val = buf.get64(i); + double * double_val = (double*) &uint64_val; + i += 8; + json[attrid_str] = *double_val; + } + break; + } + + + + + + + return i - offset; +} + + +void ZCLFrame::generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len) { + uint32_t suffix = 1; + + snprintf_P(key, key_len, PSTR("%04X/%04X"), cluster, attr); + while (json.containsKey(key)) { + suffix++; + snprintf_P(key, key_len, PSTR("%04X/%04X+%d"), cluster, attr, suffix); + } +} + + +void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { + uint32_t i = offset; + uint32_t len = _payload.len(); + + while (len >= i + 3) { + uint16_t attrid = _payload.get16(i); + i += 2; + + char key[16]; + generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); + + + if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { + if (0x42 == _payload.get8(i)) { + _payload.set8(i, 0x41); + } + } + i += parseSingleAttribute(json, key, _payload, i, len); + } +} + + +void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { + uint32_t i = offset; + uint32_t len = _payload.len(); + + while (len - i >= 4) { + uint16_t attrid = _payload.get16(i); + i += 2; + uint8_t status = _payload.get8(i++); + + if (0 == status) { + char key[16]; + generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); + + i += parseSingleAttribute(json, key, _payload, i, len); + } + } +} + + + +void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { + convertClusterSpecific(json, _cluster_id, _cmd_id, _frame_control.b.direction, _payload); +} + + + + +typedef int32_t (*Z_AttrConverter)(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); +typedef struct Z_AttributeConverter { + uint16_t cluster; + uint16_t attribute; + const char * name; + Z_AttrConverter func; +} Z_AttributeConverter; + + +const Z_AttributeConverter Z_PostProcess[] PROGMEM = { + { 0x0000, 0x0000, "ZCLVersion", &Z_Copy }, + { 0x0000, 0x0001, "AppVersion", &Z_Copy }, + { 0x0000, 0x0002, "StackVersion", &Z_Copy }, + { 0x0000, 0x0003, "HWVersion", &Z_Copy }, + { 0x0000, 0x0004, "Manufacturer", &Z_ManufKeep }, + { 0x0000, 0x0005, D_JSON_MODEL D_JSON_ID, &Z_ModelKeep }, + { 0x0000, 0x0006, "DateCode", &Z_Copy }, + { 0x0000, 0x0007, "PowerSource", &Z_Copy }, + { 0x0000, 0x4000, "SWBuildID", &Z_Copy }, + { 0x0000, 0xFFFF, nullptr, &Z_Remove }, + + { 0x0000, 0xFF01, nullptr, &Z_AqaraSensor }, + + + { 0x0001, 0x0000, "MainsVoltage", &Z_Copy }, + { 0x0001, 0x0001, "MainsFrequency", &Z_Copy }, + { 0x0001, 0x0020, "BatteryVoltage", &Z_Copy }, + { 0x0001, 0x0021, "BatteryPercentageRemaining",&Z_Copy }, + + + { 0x0002, 0x0000, "CurrentTemperature", &Z_Copy }, + { 0x0002, 0x0001, "MinTempExperienced", &Z_Copy }, + { 0x0002, 0x0002, "MaxTempExperienced", &Z_Copy }, + { 0x0002, 0x0003, "OverTempTotalDwell", &Z_Copy }, + + + { 0x0006, 0x0000, "Power", &Z_Copy }, + { 0x0006, 0x8000, "Power", &Z_Copy }, + + + { 0x0007, 0x0000, "SwitchType", &Z_Copy }, + + + { 0x0008, 0x0000, "Dimmer", &Z_Copy }, +# 548 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" + { 0x0009, 0x0000, "AlarmCount", &Z_Copy }, + + { 0x000A, 0x0000, "Time", &Z_Copy }, + { 0x000A, 0x0001, "TimeStatus", &Z_Copy }, + { 0x000A, 0x0002, "TimeZone", &Z_Copy }, + { 0x000A, 0x0003, "DstStart", &Z_Copy }, + { 0x000A, 0x0004, "DstStart", &Z_Copy }, + { 0x000A, 0x0005, "DstShift", &Z_Copy }, + { 0x000A, 0x0006, "StandardTime", &Z_Copy }, + { 0x000A, 0x0007, "LocalTime", &Z_Copy }, + { 0x000A, 0x0008, "LastSetTime", &Z_Copy }, + { 0x000A, 0x0009, "ValidUntilTime", &Z_Copy }, + + { 0x000B, 0x0000, "LocationType", &Z_Copy }, + { 0x000B, 0x0000, "LocationMethod", &Z_Copy }, + { 0x000B, 0x0000, "LocationAge", &Z_Copy }, + { 0x000B, 0x0000, "QualityMeasure", &Z_Copy }, + { 0x000B, 0x0000, "NumberOfDevices", &Z_Copy }, + + { 0x000C, 0x0004, "ActiveText", &Z_Copy }, + { 0x000C, 0x001C, "Description", &Z_Copy }, + { 0x000C, 0x002E, "InactiveText", &Z_Copy }, + { 0x000C, 0x0041, "MaxPresentValue", &Z_Copy }, + { 0x000C, 0x0045, "MinPresentValue", &Z_Copy }, + { 0x000C, 0x0051, "OutOfService", &Z_Copy }, + { 0x000C, 0x0055, "AqaraRotate", &Z_Copy }, + { 0x000C, 0x0057, "PriorityArray", &Z_Copy }, + { 0x000C, 0x0067, "Reliability", &Z_Copy }, + { 0x000C, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x000C, 0x006A, "Resolution", &Z_Copy }, + { 0x000C, 0x006F, "StatusFlags", &Z_Copy }, + { 0x000C, 0x0075, "EngineeringUnits", &Z_Copy }, + { 0x000C, 0x0100, "ApplicationType", &Z_Copy }, + { 0x000C, 0xFF05, "Aqara_FF05", &Z_Copy }, + + { 0x0010, 0x0004, "ActiveText", &Z_Copy }, + { 0x0010, 0x001C, "Description", &Z_Copy }, + { 0x0010, 0x002E, "InactiveText", &Z_Copy }, + { 0x0010, 0x0042, "MinimumOffTime", &Z_Copy }, + { 0x0010, 0x0043, "MinimumOnTime", &Z_Copy }, + { 0x0010, 0x0051, "OutOfService", &Z_Copy }, + { 0x0010, 0x0054, "Polarity", &Z_Copy }, + { 0x0010, 0x0055, "PresentValue", &Z_Copy }, + { 0x0010, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0010, 0x0067, "Reliability", &Z_Copy }, + { 0x0010, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0010, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0010, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x0011, 0x0004, "ActiveText", &Z_Copy }, + { 0x0011, 0x001C, "Description", &Z_Copy }, + { 0x0011, 0x002E, "InactiveText", &Z_Copy }, + { 0x0011, 0x0042, "MinimumOffTime", &Z_Copy }, + { 0x0011, 0x0043, "MinimumOnTime", &Z_Copy }, + { 0x0011, 0x0051, "OutOfService", &Z_Copy }, + { 0x0011, 0x0055, "PresentValue", &Z_Copy }, + { 0x0011, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0011, 0x0067, "Reliability", &Z_Copy }, + { 0x0011, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0011, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0011, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x0012, 0x000E, "StateText", &Z_Copy }, + { 0x0012, 0x001C, "Description", &Z_Copy }, + { 0x0012, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0012, 0x0051, "OutOfService", &Z_Copy }, + { 0x0012, 0x0055, "PresentValue", &Z_AqaraCube }, + { 0x0012, 0x0067, "Reliability", &Z_Copy }, + { 0x0012, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0012, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x0013, 0x000E, "StateText", &Z_Copy }, + { 0x0013, 0x001C, "Description", &Z_Copy }, + { 0x0013, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0013, 0x0051, "OutOfService", &Z_Copy }, + { 0x0013, 0x0055, "PresentValue", &Z_Copy }, + { 0x0013, 0x0057, "PriorityArray", &Z_Copy }, + { 0x0013, 0x0067, "Reliability", &Z_Copy }, + { 0x0013, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0013, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0013, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x0014, 0x000E, "StateText", &Z_Copy }, + { 0x0014, 0x001C, "Description", &Z_Copy }, + { 0x0014, 0x004A, "NumberOfStates", &Z_Copy }, + { 0x0014, 0x0051, "OutOfService", &Z_Copy }, + { 0x0014, 0x0055, "PresentValue", &Z_Copy }, + { 0x0014, 0x0067, "Reliability", &Z_Copy }, + { 0x0014, 0x0068, "RelinquishDefault", &Z_Copy }, + { 0x0014, 0x006F, "StatusFlags", &Z_Copy }, + { 0x0014, 0x0100, "ApplicationType", &Z_Copy }, + + { 0x001A, 0x0000, "TotalProfileNum", &Z_Copy }, + { 0x001A, 0x0001, "MultipleScheduling", &Z_Copy }, + { 0x001A, 0x0002, "EnergyFormatting", &Z_Copy }, + { 0x001A, 0x0003, "EnergyRemote", &Z_Copy }, + { 0x001A, 0x0004, "ScheduleMode", &Z_Copy }, + + { 0x0020, 0x0000, "CheckinInterval", &Z_Copy }, + { 0x0020, 0x0001, "LongPollInterval", &Z_Copy }, + { 0x0020, 0x0002, "ShortPollInterval", &Z_Copy }, + { 0x0020, 0x0003, "FastPollTimeout", &Z_Copy }, + { 0x0020, 0x0004, "CheckinIntervalMin", &Z_Copy }, + { 0x0020, 0x0005, "LongPollIntervalMin", &Z_Copy }, + { 0x0020, 0x0006, "FastPollTimeoutMax", &Z_Copy }, + + { 0x0100, 0x0000, "PhysicalClosedLimit", &Z_Copy }, + { 0x0100, 0x0001, "MotorStepSize", &Z_Copy }, + { 0x0100, 0x0002, "Status", &Z_Copy }, + { 0x0100, 0x0010, "ClosedLimit", &Z_Copy }, + { 0x0100, 0x0011, "Mode", &Z_Copy }, + + { 0x0101, 0x0000, "LockState", &Z_Copy }, + { 0x0101, 0x0001, "LockType", &Z_Copy }, + { 0x0101, 0x0002, "ActuatorEnabled", &Z_Copy }, + { 0x0101, 0x0003, "DoorState", &Z_Copy }, + { 0x0101, 0x0004, "DoorOpenEvents", &Z_Copy }, + { 0x0101, 0x0005, "DoorClosedEvents", &Z_Copy }, + { 0x0101, 0x0006, "OpenPeriod", &Z_Copy }, + + { 0x0101, 0x0055, "AqaraVibrationMode", &Z_AqaraVibration }, + { 0x0101, 0x0503, "AqaraVibrationsOrAngle", &Z_Copy }, + { 0x0101, 0x0505, "AqaraVibration505", &Z_Copy }, + { 0x0101, 0x0508, "AqaraAccelerometer", &Z_AqaraVibration }, + + { 0x0102, 0x0000, "WindowCoveringType", &Z_Copy }, + { 0x0102, 0x0001, "PhysicalClosedLimitLift",&Z_Copy }, + { 0x0102, 0x0002, "PhysicalClosedLimitTilt",&Z_Copy }, + { 0x0102, 0x0003, "CurrentPositionLift", &Z_Copy }, + { 0x0102, 0x0004, "CurrentPositionTilt", &Z_Copy }, + { 0x0102, 0x0005, "NumberofActuationsLift",&Z_Copy }, + { 0x0102, 0x0006, "NumberofActuationsTilt",&Z_Copy }, + { 0x0102, 0x0007, "ConfigStatus", &Z_Copy }, + { 0x0102, 0x0008, "CurrentPositionLiftPercentage",&Z_Copy }, + { 0x0102, 0x0009, "CurrentPositionTiltPercentage",&Z_Copy }, + { 0x0102, 0x0010, "InstalledOpenLimitLift",&Z_Copy }, + { 0x0102, 0x0011, "InstalledClosedLimitLift",&Z_Copy }, + { 0x0102, 0x0012, "InstalledOpenLimitTilt", &Z_Copy }, + { 0x0102, 0x0013, "InstalledClosedLimitTilt", &Z_Copy }, + { 0x0102, 0x0014, "VelocityLift",&Z_Copy }, + { 0x0102, 0x0015, "AccelerationTimeLift",&Z_Copy }, + { 0x0102, 0x0016, "DecelerationTimeLift", &Z_Copy }, + { 0x0102, 0x0017, "Mode",&Z_Copy }, + { 0x0102, 0x0018, "IntermediateSetpointsLift",&Z_Copy }, + { 0x0102, 0x0019, "IntermediateSetpointsTilt",&Z_Copy }, + + + { 0x0300, 0x0000, "Hue", &Z_Copy }, + { 0x0300, 0x0001, "Sat", &Z_Copy }, + { 0x0300, 0x0002, "RemainingTime", &Z_Copy }, + { 0x0300, 0x0003, "X", &Z_Copy }, + { 0x0300, 0x0004, "Y", &Z_Copy }, + { 0x0300, 0x0005, "DriftCompensation", &Z_Copy }, + { 0x0300, 0x0006, "CompensationText", &Z_Copy }, + { 0x0300, 0x0007, "CT", &Z_Copy }, + { 0x0300, 0x0008, "ColorMode", &Z_Copy }, + { 0x0300, 0x0010, "NumberOfPrimaries", &Z_Copy }, + { 0x0300, 0x0011, "Primary1X", &Z_Copy }, + { 0x0300, 0x0012, "Primary1Y", &Z_Copy }, + { 0x0300, 0x0013, "Primary1Intensity", &Z_Copy }, + { 0x0300, 0x0015, "Primary2X", &Z_Copy }, + { 0x0300, 0x0016, "Primary2Y", &Z_Copy }, + { 0x0300, 0x0017, "Primary2Intensity", &Z_Copy }, + { 0x0300, 0x0019, "Primary3X", &Z_Copy }, + { 0x0300, 0x001A, "Primary3Y", &Z_Copy }, + { 0x0300, 0x001B, "Primary3Intensity", &Z_Copy }, + { 0x0300, 0x0030, "WhitePointX", &Z_Copy }, + { 0x0300, 0x0031, "WhitePointY", &Z_Copy }, + { 0x0300, 0x0032, "ColorPointRX", &Z_Copy }, + { 0x0300, 0x0033, "ColorPointRY", &Z_Copy }, + { 0x0300, 0x0034, "ColorPointRIntensity", &Z_Copy }, + { 0x0300, 0x0036, "ColorPointGX", &Z_Copy }, + { 0x0300, 0x0037, "ColorPointGY", &Z_Copy }, + { 0x0300, 0x0038, "ColorPointGIntensity", &Z_Copy }, + { 0x0300, 0x003A, "ColorPointBX", &Z_Copy }, + { 0x0300, 0x003B, "ColorPointBY", &Z_Copy }, + { 0x0300, 0x003C, "ColorPointBIntensity", &Z_Copy }, + + + { 0x0400, 0x0000, D_JSON_ILLUMINANCE, &Z_Copy }, + { 0x0400, 0x0001, "MinMeasuredValue", &Z_Copy }, + { 0x0400, 0x0002, "MaxMeasuredValue", &Z_Copy }, + { 0x0400, 0x0003, "Tolerance", &Z_Copy }, + { 0x0400, 0x0004, "LightSensorType", &Z_Copy }, + { 0x0400, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0401, 0x0000, "LevelStatus", &Z_Copy }, + { 0x0401, 0x0001, "LightSensorType", &Z_Copy }, + { 0x0401, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0402, 0x0000, D_JSON_TEMPERATURE, &Z_FloatDiv100 }, + { 0x0402, 0x0001, "MinMeasuredValue", &Z_FloatDiv100 }, + { 0x0402, 0x0002, "MaxMeasuredValue", &Z_FloatDiv100 }, + { 0x0402, 0x0003, "Tolerance", &Z_FloatDiv100 }, + { 0x0402, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0403, 0x0000, D_JSON_PRESSURE_UNIT, &Z_AddPressureUnit }, + { 0x0403, 0x0000, D_JSON_PRESSURE, &Z_Copy }, + { 0x0403, 0x0001, "MinMeasuredValue", &Z_Copy }, + { 0x0403, 0x0002, "MaxMeasuredValue", &Z_Copy }, + { 0x0403, 0x0003, "Tolerance", &Z_Copy }, + { 0x0403, 0x0010, "ScaledValue", &Z_Copy }, + { 0x0403, 0x0011, "MinScaledValue", &Z_Copy }, + { 0x0403, 0x0012, "MaxScaledValue", &Z_Copy }, + { 0x0403, 0x0013, "ScaledTolerance", &Z_Copy }, + { 0x0403, 0x0014, "Scale", &Z_Copy }, + { 0x0403, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0404, 0x0000, D_JSON_FLOWRATE, &Z_FloatDiv10 }, + { 0x0404, 0x0001, "MinMeasuredValue", &Z_Copy }, + { 0x0404, 0x0002, "MaxMeasuredValue", &Z_Copy }, + { 0x0404, 0x0003, "Tolerance", &Z_Copy }, + { 0x0404, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0405, 0x0000, D_JSON_HUMIDITY, &Z_FloatDiv100 }, + { 0x0405, 0x0001, "MinMeasuredValue", &Z_Copy }, + { 0x0405, 0x0002, "MaxMeasuredValue", &Z_Copy }, + { 0x0405, 0x0003, "Tolerance", &Z_Copy }, + { 0x0405, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0406, 0x0000, OCCUPANCY, &Z_Copy }, + { 0x0406, 0x0001, "OccupancySensorType", &Z_Copy }, + { 0x0406, 0xFFFF, nullptr, &Z_Remove }, + + + { 0x0B01, 0x0000, "CompanyName", &Z_Copy }, + { 0x0B01, 0x0001, "MeterTypeID", &Z_Copy }, + { 0x0B01, 0x0004, "DataQualityID", &Z_Copy }, + { 0x0B01, 0x0005, "CustomerName", &Z_Copy }, + { 0x0B01, 0x0006, "Model", &Z_Copy }, + { 0x0B01, 0x0007, "PartNumber", &Z_Copy }, + { 0x0B01, 0x000A, "SoftwareRevision", &Z_Copy }, + { 0x0B01, 0x000C, "POD", &Z_Copy }, + { 0x0B01, 0x000D, "AvailablePower", &Z_Copy }, + { 0x0B01, 0x000E, "PowerThreshold", &Z_Copy }, + + + { 0x0B05, 0x0000, "NumberOfResets", &Z_Copy }, + { 0x0B05, 0x0001, "PersistentMemoryWrites",&Z_Copy }, + { 0x0B05, 0x011C, "LastMessageLQI", &Z_Copy }, + { 0x0B05, 0x011D, "LastMessageRSSI", &Z_Copy }, + +}; + + + +int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + zigbee_devices.setManufId(shortaddr, value.as()); + return 1; +} + +int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + zigbee_devices.setModelId(shortaddr, value.as()); + return 1; +} + + + +int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + return 1; +} + + +int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + return 1; +} + + +int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = F(D_UNIT_PRESSURE); + return 0; +} + + +int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = ((float)value) / 100.0f; + return 1; +} + +int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = ((float)value) / 10.0f; + return 1; +} + + +int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + json[F(OCCUPANCY)] = 0; + zigbee_devices.jsonPublishNow(shortaddr, json); +} + + +int32_t Z_AqaraCube(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = value; + int32_t val = value; + const __FlashStringHelper *aqara_cube = F("AqaraCube"); + const __FlashStringHelper *aqara_cube_side = F("AqaraCubeSide"); + const __FlashStringHelper *aqara_cube_from_side = F("AqaraCubeFromSide"); + + switch (val) { + case 0: + json[aqara_cube] = F("shake"); + break; + case 2: + json[aqara_cube] = F("wakeup"); + break; + case 3: + json[aqara_cube] = F("fall"); + break; + case 64 ... 127: + json[aqara_cube] = F("flip90"); + json[aqara_cube_side] = val % 8; + json[aqara_cube_from_side] = (val - 64) / 8; + break; + case 128 ... 132: + json[aqara_cube] = F("flip180"); + json[aqara_cube_side] = val - 128; + break; + case 256 ... 261: + json[aqara_cube] = F("slide"); + json[aqara_cube_side] = val - 256; + break; + case 512 ... 517: + json[aqara_cube] = F("tap"); + json[aqara_cube_side] = val - 512; + break; + } +# 905 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" + return 1; +} + + +int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + + switch (attr) { + case 0x0055: + { + int32_t ivalue = value; + const __FlashStringHelper * svalue; + switch (ivalue) { + case 1: svalue = F("vibrate"); break; + case 2: svalue = F("tilt"); break; + case 3: svalue = F("drop"); break; + default: svalue = F("unknown"); break; + } + json[new_name] = svalue; + } + break; + + + + + case 0x0508: + { + + + String hex = value; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + int16_t x, y, z; + z = buf2.get16(0); + y = buf2.get16(2); + x = buf2.get16(4); + JsonArray& xyz = json.createNestedArray(new_name); + xyz.add(x); + xyz.add(y); + xyz.add(z); + + float X = x; + float Y = y; + float Z = z; + int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; + int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; + int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; + + + + JsonArray& angles = json.createNestedArray(F("AqaraAngles")); + angles.add(Angle_X); + angles.add(Angle_Y); + angles.add(Angle_Z); + } + break; + } + return 1; +} + +int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + String hex = value; + SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); + uint32_t i = 0; + uint32_t len = buf2.len(); + char tmp[] = "tmp"; + + JsonVariant sub_value; + + while (len - i >= 2) { + uint8_t attrid = buf2.get8(i++); + + i += parseSingleAttribute(json, tmp, buf2, i, len); + float val = json[tmp]; + json.remove(tmp); + if (0x01 == attrid) { + json[F(D_JSON_VOLTAGE)] = val / 1000.0f; + json[F("Battery")] = toPercentageCR2032(val); + } else if (0 == zcl->getManufCode()) { + + if (0x64 == attrid) { + json[F(D_JSON_TEMPERATURE)] = val / 100.0f; + } else if (0x65 == attrid) { + json[F(D_JSON_HUMIDITY)] = val / 100.0f; + } else if (0x66 == attrid) { + json[F(D_JSON_PRESSURE)] = val / 100.0f; + json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); + } else if (0x01 == attrid) { + json[F(D_JSON_VOLTAGE)] = val / 1000.0f; + json[F("Battery")] = toPercentageCR2032(val); + } + } else if (0x115F == zcl->getManufCode()) { + + json[F("AqaraUnknown")] = val; + } + } + return 1; +} + + +void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { + + for (auto kv : json) { + String key_string = kv.key; + const char * key = key_string.c_str(); + JsonVariant& value = kv.value; + + char * delimiter = strchr(key, '/'); + char * delimiter2 = strchr(key, '+'); + if (delimiter) { + uint16_t attribute; + uint16_t suffix = 1; + uint16_t cluster = strtoul(key, &delimiter, 16); + if (!delimiter2) { + attribute = strtoul(delimiter+1, nullptr, 16); + } else { + attribute = strtoul(delimiter+1, &delimiter2, 16); + suffix = strtoul(delimiter2+1, nullptr, 10); + } + + + for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { + const Z_AttributeConverter *converter = &Z_PostProcess[i]; + uint16_t conv_cluster = pgm_read_word(&converter->cluster); + uint16_t conv_attribute = pgm_read_word(&converter->attribute); + + if ((conv_cluster == cluster) && + ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { + String new_name_str = converter->name; + if (suffix > 1) { new_name_str += suffix; } + int32_t drop = (*converter->func)(this, shortaddr, json, key, value, new_name_str, conv_cluster, conv_attribute); + if (drop) { + json.remove(key); + } + + } + } + } + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" +#ifdef USE_ZIGBEE + +typedef struct Z_CommandConverter { + const char * tasmota_cmd; + uint16_t cluster; + uint8_t cmd; + uint8_t direction; + const char * param; +} Z_CommandConverter; + +typedef struct Z_XYZ_Var { + uint32_t x = 0; + uint32_t y = 0; + uint32_t z = 0; + uint8_t x_type = 0; + uint8_t y_type = 0; + uint8_t z_type = 0; +} Z_XYZ_Var; + + +const Z_CommandConverter Z_Commands[] = { + + { "AddGroup", 0x0004, 0x00, 0x01, "xxxx00" }, + { "ViewGroup", 0x0004, 0x01, 0x01, "xxxx" }, + { "GetGroup", 0x0004, 0x02, 0x01, "01xxxx" }, + { "GetAllGroups", 0x0004, 0x02, 0x01, "00" }, + { "RemoveGroup", 0x0004, 0x03, 0x01, "xxxx" }, + { "RemoveAllGroups",0x0004, 0x04, 0x01, "" }, + + { "Power", 0x0006, 0xFF, 0x01, "" }, + { "Dimmer", 0x0008, 0x04, 0x01, "xx0A00" }, + { "Dimmer+", 0x0008, 0x06, 0x01, "001902" }, + { "Dimmer-", 0x0008, 0x06, 0x01, "011902" }, + { "DimmerStop", 0x0008, 0x03, 0x01, "" }, + { "ResetAlarm", 0x0009, 0x00, 0x01, "xxyyyy" }, + { "ResetAllAlarms", 0x0009, 0x01, 0x01, "" }, + { "Hue", 0x0300, 0x00, 0x01, "xx000A00" }, + { "Sat", 0x0300, 0x03, 0x01, "xx0A00" }, + { "HueSat", 0x0300, 0x06, 0x01, "xxyy0A00" }, + { "Color", 0x0300, 0x07, 0x01, "xxxxyyyy0A00" }, + { "CT", 0x0300, 0x0A, 0x01, "xxxx0A00" }, + { "ShutterOpen", 0x0102, 0x00, 0x01, "" }, + { "ShutterClose", 0x0102, 0x01, 0x01, "" }, + { "ShutterStop", 0x0102, 0x02, 0x01, "" }, + { "ShutterLift", 0x0102, 0x05, 0x01, "xx" }, + { "ShutterTilt", 0x0102, 0x08, 0x01, "xx" }, + { "Shutter", 0x0102, 0xFF, 0x01, "" }, + + { "Occupancy", 0xEF00, 0x01, 0x01, "xx"}, + + { "Dimmer", 0x0008, 0x00, 0x01, "xx" }, + { "DimmerMove", 0x0008, 0x01, 0x01, "xx0A" }, + { "DimmerStep", 0x0008, 0x02, 0x01, "xx190A00" }, + { "DimmerMove", 0x0008, 0x05, 0x01, "xx0A" }, + { "Dimmer+", 0x0008, 0x06, 0x01, "00" }, + { "Dimmer-", 0x0008, 0x06, 0x01, "01" }, + { "DimmerStop", 0x0008, 0x07, 0x01, "" }, + { "HueMove", 0x0300, 0x01, 0x01, "xx19" }, + { "HueStep", 0x0300, 0x02, 0x01, "xx190A00" }, + { "SatMove", 0x0300, 0x04, 0x01, "xx19" }, + { "SatStep", 0x0300, 0x05, 0x01, "xx190A" }, + { "ColorMove", 0x0300, 0x08, 0x01, "xxxxyyyy" }, + { "ColorStep", 0x0300, 0x09, 0x01, "xxxxyyyy0A00" }, + + { "ArrowClick", 0x0005, 0x07, 0x01, "xx" }, + { "ArrowHold", 0x0005, 0x08, 0x01, "xx" }, + { "ArrowRelease", 0x0005, 0x09, 0x01, "" }, + + { "ZoneStatusChange",0x0500, 0x00, 0x02, "xxxxyyzz" }, + + { "AddGroupResp", 0x0004, 0x00, 0x02, "xxyyyy" }, + { "ViewGroupResp", 0x0004, 0x01, 0x02, "xxyyyy" }, + { "GetGroupResp", 0x0004, 0x02, 0x02, "xxyyzzzz" }, + { "RemoveGroup", 0x0004, 0x03, 0x02, "xxyyyy" }, +}; + + +#define ZLE(x) ((x) & 0xFF), ((x) >> 8) + + +const uint8_t CLUSTER_0006[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; +const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007) }; + + +int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + size_t attrs_len = 0; + const uint8_t* attrs = nullptr; + + switch (cluster) { + case 0x0006: + attrs = CLUSTER_0006; + attrs_len = sizeof(CLUSTER_0006); + break; + case 0x0008: + attrs = CLUSTER_0008; + attrs_len = sizeof(CLUSTER_0008); + break; + case 0x0009: + attrs = CLUSTER_0009; + attrs_len = sizeof(CLUSTER_0009); + break; + case 0x0300: + attrs = CLUSTER_0300; + attrs_len = sizeof(CLUSTER_0300); + break; + } + if (attrs) { + ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true , zigbee_devices.getNextSeqNumber(shortaddr)); + } +} + + +void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint) { + uint32_t wait_ms = 0; + + switch (cluster) { + case 0x0006: + case 0x0009: + wait_ms = 200; + break; + case 0x0008: + case 0x0300: + wait_ms = 1050; + break; + case 0x0102: + wait_ms = 10000; + break; + } + if (wait_ms) { + zigbee_devices.setTimer(shortaddr, wait_ms, cluster, endpoint, 0 , &Z_ReadAttrCallback); + } +} + + +inline bool isXYZ(char c) { + return (c >= 'x') && (c <= 'z'); +} + + + + +inline int8_t hexValue(char c) { + if ((c >= '0') && (c <= '9')) { + return c - '0'; + } + if ((c >= 'A') && (c <= 'F')) { + return 10 + c - 'A'; + } + if ((c >= 'a') && (c <= 'f')) { + return 10 + c - 'a'; + } + return -1; +} + + +uint32_t parseHex_P(const char **data, size_t max_len = 8) { + uint32_t ret = 0; + for (uint32_t i = 0; i < max_len; i++) { + int8_t v = hexValue(pgm_read_byte(*data)); + if (v < 0) { break; } + ret = (ret << 4) | v; + *data += 1; + } + return ret; +} + + + + + +void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz) { + const char *p = model; + uint32_t v = 0; + char c = pgm_read_byte(p); + while (c) { + char c1 = pgm_read_byte(p+1); + if (!c1) { break; } + if (isXYZ(c) && (c == c1) && (v < payload.len())) { + uint8_t val = payload.get8(v); + switch (c) { + case 'x': + xyz->x = xyz->x | (val << (xyz->x_type * 8)); + xyz->x_type++; + break; + case 'y': + xyz->y = xyz->y | (val << (xyz->y_type * 8)); + xyz->y_type++; + break; + case 'z': + xyz->z = xyz->z | (val << (xyz->z_type * 8)); + xyz->z_type++; + break; + } + } + p += 2; + v++; + c = pgm_read_byte(p); + } +} +# 231 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" +void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, bool direction, const SBuffer &payload) { + size_t hex_char_len = payload.len()*2+2; + char *hex_char = (char*) malloc(hex_char_len); + if (!hex_char) { return; } + ToHex_P((unsigned char*)payload.getBuffer(), payload.len(), hex_char, hex_char_len); + + const __FlashStringHelper* command_name = nullptr; + Z_XYZ_Var xyz; + + + for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { + const Z_CommandConverter *conv = &Z_Commands[i]; + if (conv->cluster == cluster) { + + if ((0xFF == conv->cmd) || (cmd == conv->cmd)) { + + if ((direction && (conv->direction & 0x02)) || (!direction && (conv->direction & 0x01))) { + + + + + const char * p = conv->param; + + bool match = true; + for (uint8_t i = 0; i < payload.len(); i++) { + const char c1 = pgm_read_byte(p); + const char c2 = pgm_read_byte(p+1); + + if ((0x00 == c1) || isXYZ(c1)) { + break; + } + const char * p2 = p; + uint32_t nextbyte = parseHex_P(&p2, 2); + + if (nextbyte != payload.get8(i)) { + match = false; + break; + } + p += 2; + } + if (match) { + command_name = (const __FlashStringHelper*) conv->tasmota_cmd; + parseXYZ(conv->param, payload, &xyz); + if (0xFF == conv->cmd) { + + xyz.z = xyz.y; + xyz.z_type = xyz.y_type; + xyz.y = xyz.x; + xyz.y_type = xyz.x_type; + xyz.x = cmd; + xyz.x_type = 1; + } + break; + } + } + } + } + } + + + + + char attrid_str[12]; + snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); + json[attrid_str] = hex_char; + free(hex_char); + + if (command_name) { + if (0 == xyz.x_type) { + json[command_name] = true; + } else if (0 == xyz.y_type) { + json[command_name] = xyz.x; + } else { + + JsonArray &arr = json.createNestedArray(command_name); + arr.add(xyz.x); + arr.add(xyz.y); + if (xyz.z_type) { + arr.add(xyz.z); + } + } + } +} + + + + +const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd) { + for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { + const Z_CommandConverter *conv = &Z_Commands[i]; + if (0 == strcasecmp_P(command, conv->tasmota_cmd)) { + *cluster = conv->cluster; + *cmd = conv->cmd; + return (const __FlashStringHelper*) conv->param; + } + } + + return nullptr; +} + + +inline char hexDigit(uint32_t h) { + uint32_t nybble = h & 0x0F; + return (nybble > 9) ? 'A' - 10 + nybble : '0' + nybble; +} + + +String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z) { + size_t len = strlen_P(zcl_cmd_P); + char zcl_cmd[len+1]; + strcpy_P(zcl_cmd, zcl_cmd_P); + + char *p = zcl_cmd; + while (*p) { + if (isXYZ(*p) && (*p == *(p+1))) { + uint8_t val; + switch (*p) { + case 'x': + val = x & 0xFF; + x = x >> 8; + break; + case 'y': + val = y & 0xFF; + y = y >> 8; + break; + case 'z': + val = z & 0xFF; + z = z >> 8; + break; + } + *p = hexDigit(val >> 4); + *(p+1) = hexDigit(val); + p++; + } + p++; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SendZCLCommand_P: zcl_cmd = %s"), zcl_cmd); + + return String(zcl_cmd); +} + +const char kZ_Alias[] PROGMEM = "OFF|" D_OFF "|" D_FALSE "|" D_STOP "|" "OPEN" "|" + "ON|" D_ON "|" D_TRUE "|" D_START "|" "CLOSE" "|" + "TOGGLE|" D_TOGGLE "|" + "ALL" ; + +const uint8_t kZ_Numbers[] PROGMEM = { 0,0,0,0,0, + 1,1,1,1,1, + 2,2, + 255 }; + + +uint32_t ZigbeeAliasOrNumber(const char *state_text) { + char command[16]; + int state_number = GetCommandCode(command, sizeof(command), state_text, kZ_Alias); + if (state_number >= 0) { + + return pgm_read_byte(kZ_Numbers + state_number); + } else { + + return strtoul(state_text, nullptr, 0); + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +#ifdef USE_ZIGBEE + + + +const uint8_t ZIGBEE_STATUS_OK = 0; +const uint8_t ZIGBEE_STATUS_BOOT = 1; +const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; +const uint8_t ZIGBEE_STATUS_STARTING = 3; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_CLOSE = 20; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_60 = 21; +const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_XX = 22; +const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; +const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; +const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; +const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; +const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; +const uint8_t ZIGBEE_STATUS_DEVICE_IEEE = 35; +const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; +const uint8_t ZIGBEE_STATUS_CC_INFO = 51; +const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; +const uint8_t ZIGBEE_STATUS_ABORT = 99; + +typedef int32_t (*ZB_Func)(uint8_t value); +typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, const class SBuffer &buf); + +typedef union Zigbee_Instruction { + struct { + uint8_t i; + uint8_t d8; + uint16_t d16; + } i; + const void *p; + + + +} Zigbee_Instruction; + + + + +typedef struct Zigbee_Instruction_Type { + uint8_t instr; + uint8_t data; +} Zigbee_Instruction_Type; + +enum Zigbee_StateMachine_Instruction_Set { + + ZGB_INSTR_4_BYTES = 0, + ZGB_INSTR_NOOP = 0, + ZGB_INSTR_LABEL, + ZGB_INSTR_GOTO, + ZGB_INSTR_ON_ERROR_GOTO, + ZGB_INSTR_ON_TIMEOUT_GOTO, + ZGB_INSTR_WAIT, + ZGB_INSTR_WAIT_FOREVER, + ZGB_INSTR_STOP, + + + ZGB_INSTR_8_BYTES = 0x80, + ZGB_INSTR_CALL = 0x80, + ZGB_INSTR_LOG, + ZGB_INSTR_MQTT_STATE, + ZGB_INSTR_SEND, + ZGB_INSTR_WAIT_UNTIL, + ZGB_INSTR_WAIT_RECV, + ZGB_ON_RECV_UNEXPECTED, + + + ZGB_INSTR_12_BYTES = 0xF0, + ZGB_INSTR_WAIT_RECV_CALL, +}; + +#define ZI_NOOP() { .i = { ZGB_INSTR_NOOP, 0x00, 0x0000} }, +#define ZI_LABEL(x) { .i = { ZGB_INSTR_LABEL, (x), 0x0000} }, +#define ZI_GOTO(x) { .i = { ZGB_INSTR_GOTO, (x), 0x0000} }, +#define ZI_ON_ERROR_GOTO(x) { .i = { ZGB_INSTR_ON_ERROR_GOTO, (x), 0x0000} }, +#define ZI_ON_TIMEOUT_GOTO(x) { .i = { ZGB_INSTR_ON_TIMEOUT_GOTO, (x), 0x0000} }, +#define ZI_WAIT(x) { .i = { ZGB_INSTR_WAIT, 0x00, (x)} }, +#define ZI_WAIT_FOREVER() { .i = { ZGB_INSTR_WAIT_FOREVER, 0x00, 0x0000} }, +#define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, + +#define ZI_CALL(f,x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, +#define ZI_LOG(x,m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, +#define ZI_MQTT_STATE(x,m) { .i = { ZGB_INSTR_MQTT_STATE, (x), 0x0000 } }, { .p = ((const void*)(m)) }, +#define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, +#define ZI_SEND(m) { .i = { ZGB_INSTR_SEND, sizeof(m), 0x0000} }, { .p = (const void*)(m) }, +#define ZI_WAIT_RECV(x,m) { .i = { ZGB_INSTR_WAIT_RECV, sizeof(m), (x)} }, { .p = (const void*)(m) }, +#define ZI_WAIT_UNTIL(x,m) { .i = { ZGB_INSTR_WAIT_UNTIL, sizeof(m), (x)} }, { .p = (const void*)(m) }, +#define ZI_WAIT_RECV_FUNC(x,m,f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, + + +const uint8_t ZIGBEE_LABEL_START = 10; +const uint8_t ZIGBEE_LABEL_READY = 20; +const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; +const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; + +const uint8_t ZIGBEE_LABEL_ABORT = 99; +const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; + +struct ZigbeeStatus { + bool active = true; + bool state_machine = false; + bool state_waiting = false; + bool state_no_timeout = false; + bool ready = false; + uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; + uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; + int16_t pc = 0; + uint32_t next_timeout = 0; + + uint8_t *recv_filter = nullptr; + bool recv_until = false; + size_t recv_filter_len = 0; + ZB_RecvMsgFunc recv_func = nullptr; + ZB_RecvMsgFunc recv_unexpected = nullptr; + + bool init_phase = true; +}; +struct ZigbeeStatus zigbee; + +SBuffer *zigbee_buffer = nullptr; + + + + + +#define Z_B0(a) (uint8_t)( ((a) ) & 0xFF ) +#define Z_B1(a) (uint8_t)( ((a) >> 8) & 0xFF ) +#define Z_B2(a) (uint8_t)( ((a) >> 16) & 0xFF ) +#define Z_B3(a) (uint8_t)( ((a) >> 24) & 0xFF ) +#define Z_B4(a) (uint8_t)( ((a) >> 32) & 0xFF ) +#define Z_B5(a) (uint8_t)( ((a) >> 40) & 0xFF ) +#define Z_B6(a) (uint8_t)( ((a) >> 48) & 0xFF ) +#define Z_B7(a) (uint8_t)( ((a) >> 56) & 0xFF ) + +#define ZBM(n,x...) const uint8_t n[] PROGMEM = { x }; + +#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) + + + +ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) +ZBM(ZBR_RESET, Z_AREQ | Z_SYS, SYS_RESET_IND ) + +ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) +ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) + + +ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 ) +ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_Success, 0x01 , 0x55) + + +ZBM(ZBS_PAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PANID ) +ZBM(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PANID, 0x02 , + Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) + +ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) +ZBM(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_EXTENDED_PAN_ID, + 0x08 , + Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), + Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID), + ) + +ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) +ZBM(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_CHANLIST, + 0x04 , + Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), + ) + +ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) +ZBM(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEY, + 0x10 , + Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), + Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), + Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), + Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), + + ) + +ZBM(ZBS_PFGKEN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEYS_ENABLE ) +ZBM(ZBR_PFGKEN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEYS_ENABLE, + 0x01 , 0x00 ) + + + +ZBM(ZBR_W_OK, Z_SRSP | Z_SAPI, SAPI_WRITE_CONFIGURATION, Z_Success ) +ZBM(ZBR_WNV_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_WRITE, Z_Success ) + + +ZBM(ZBS_FACTRES, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x02 ) + +ZBM(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) + +ZBM(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , + Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), + Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID) + ) + +ZBM(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , + Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), + ) + +ZBM(ZBS_W_LOGTYP, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x00 ) + +ZBM(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, + 0x10 , + Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), + Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), + Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), + Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), + + ) + +ZBM(ZBS_W_PFGKEN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEYS_ENABLE, 0x01 , 0x00 ) + +ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_START), Z_B1(CONF_TCLK_TABLE_START), + 0x00 , 0x20 , + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, + 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + +ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_ZDO_DIRECT_CB, 0x01 , 0x01 ) + +ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, + 0x01, 0x00 , 0x01 , 0x00 ) + + +ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) + + +ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), + 0x00 , 0x01 , 0x55 ) + +ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 ) +ZBM(ZBR_STARTUPFROMAPP, Z_SRSP | Z_ZDO, ZDO_STARTUP_FROM_APP ) +ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) + +ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) +ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_Success ) +# 272 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +ZBM(ZBS_ZDO_NODEDESCREQ, Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, 0x00, 0x00 , 0x00, 0x00 ) +ZBM(ZBR_ZDO_NODEDESCREQ, Z_SRSP | Z_ZDO, ZDO_NODE_DESC_REQ, Z_Success ) + +ZBM(AREQ_ZDO_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) +# 290 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" +ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) +ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_Success) +ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, + 0x00, 0x00 , 0x00 ) +ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, + 0x00, 0x00 , 0x02 , 0x0B, 0x01 ) + + +ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , 0x00 , + 0x00 , 0x00 ) +ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_Success) +ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), + 0x05, 0x00 , 0x00 , 0x00 , + 0x00 , 0x00 ) + +ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 , + 0x00, 0x00 , 0x00 , 0x00 ) +ZBM(ZBS_PERMITJOINREQ_OPEN_60, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , + 0xFC, 0xFF , 60 , 0x00 ) +ZBM(ZBS_PERMITJOINREQ_OPEN_XX, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , + 0xFC, 0xFF , 0xFF , 0x00 ) +ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_Success) +ZBM(ZBR_PERMITJOIN_AREQ_CLOSE, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0x00 ) +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_60, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 60 ) +ZBM(ZBR_PERMITJOIN_AREQ_OPEN_FF, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0xFF ) +ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 , Z_Success ) + +static const Zigbee_Instruction zb_prog[] PROGMEM = { + ZI_LABEL(0) + ZI_NOOP() + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) + ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) + ZI_WAIT(10500) + ZI_ON_ERROR_GOTO(50) + + + + ZI_SEND(ZBS_RESET) + ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &Z_Reboot) + ZI_WAIT(100) + ZI_LOG(LOG_LEVEL_DEBUG, D_LOG_ZIGBEE "checking device configuration") + ZI_SEND(ZBS_ZNPHC) + ZI_WAIT_RECV(2000, ZBR_ZNPHC) + ZI_SEND(ZBS_VERSION) + ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) + ZI_SEND(ZBS_PAN) + ZI_WAIT_RECV(1000, ZBR_PAN) + ZI_SEND(ZBS_EXTPAN) + ZI_WAIT_RECV(1000, ZBR_EXTPAN) + ZI_SEND(ZBS_CHANN) + ZI_WAIT_RECV(1000, ZBR_CHANN) + ZI_SEND(ZBS_PFGK) + ZI_WAIT_RECV(1000, ZBR_PFGK) + ZI_SEND(ZBS_PFGKEN) + ZI_WAIT_RECV(1000, ZBR_PFGKEN) + + + + ZI_LABEL(ZIGBEE_LABEL_START) + ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, "Configured, starting coordinator") + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + + +ZI_SEND(ZBS_STARTUPFROMAPP) + ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) + ZI_WAIT_UNTIL(10000, AREQ_STARTUPFROMAPP) + ZI_SEND(ZBS_GETDEVICEINFO) + ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) + + ZI_SEND(ZBS_ZDO_NODEDESCREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) + ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP) + ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) + ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE) + ZI_SEND(ZBS_AF_REGISTER01) + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + ZI_SEND(ZBS_AF_REGISTER0B) + ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) + + + ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) + ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) + ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_OK) + ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) + + + + + + + ZI_LABEL(ZIGBEE_LABEL_READY) + ZI_MQTT_STATE(ZIGBEE_STATUS_OK, "Started") + ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "Zigbee started") + ZI_CALL(&Z_State_Ready, 1) + ZI_CALL(&Z_Load_Devices, 0) + ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) + ZI_WAIT_FOREVER() + ZI_GOTO(ZIGBEE_LABEL_READY) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE) + + ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60) + + ZI_SEND(ZBS_PERMITJOINREQ_OPEN_60) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX) + + ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) + ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) + + + ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) + + ZI_LABEL(50) + ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, "Reseting configuration") + + ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) + ZI_SEND(ZBS_FACTRES) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_RESET) + ZI_WAIT_RECV(5000, ZBR_RESET) + ZI_SEND(ZBS_W_PAN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_EXTPAN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_CHANN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_LOGTYP) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_PFGK) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_W_PFGKEN) + ZI_WAIT_RECV(1000, ZBR_W_OK) + ZI_SEND(ZBS_WNV_SECMODE) + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + ZI_SEND(ZBS_W_ZDODCB) + ZI_WAIT_RECV(1000, ZBR_W_OK) + + ZI_SEND(ZBS_WNV_INITZNPHC) + ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite) + ZI_SEND(ZBS_WNV_ZNPHC) + ZI_WAIT_RECV(1000, ZBR_WNV_OK) + + + ZI_GOTO(ZIGBEE_LABEL_START) + + ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) + ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, "Only ZNP 1.2 is currently supported") + ZI_GOTO(ZIGBEE_LABEL_ABORT) + + ZI_LABEL(ZIGBEE_LABEL_ABORT) + ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, "Abort") + ZI_LOG(LOG_LEVEL_ERROR, D_LOG_ZIGBEE "Abort") + ZI_STOP(ZIGBEE_LABEL_ABORT) +}; + +uint8_t ZigbeeGetInstructionSize(uint8_t instr) { + if (instr >= ZGB_INSTR_12_BYTES) { + return 3; + } else if (instr >= ZGB_INSTR_8_BYTES) { + return 2; + } else { + return 1; + } +} + +void ZigbeeGotoLabel(uint8_t label) { + + uint16_t goto_pc = 0xFFFF; + uint8_t cur_instr = 0; + uint8_t cur_d8 = 0; + uint8_t cur_instr_len = 1; + + for (uint32_t i = 0; i < sizeof(zb_prog)/sizeof(zb_prog[0]); i += cur_instr_len) { + const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; + cur_instr = pgm_read_byte(&cur_instr_line->i.i); + cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); + + + if (ZGB_INSTR_LABEL == cur_instr) { + + if (label == cur_d8) { + + zigbee.pc = i; + zigbee.state_machine = true; + zigbee.state_waiting = false; + return; + } + } + + cur_instr_len = ZigbeeGetInstructionSize(cur_instr); + } + + + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Goto label not found, label=%d pc=%d"), label, zigbee.pc); + if (ZIGBEE_LABEL_ABORT != label) { + + ZigbeeGotoLabel(ZIGBEE_LABEL_ABORT); + } else { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Label Abort (%d) not present, aborting Zigbee"), ZIGBEE_LABEL_ABORT); + zigbee.state_machine = false; + zigbee.active = false; + } +} + +void ZigbeeStateMachine_Run(void) { + uint8_t cur_instr = 0; + uint8_t cur_d8 = 0; + uint16_t cur_d16 = 0; + const void* cur_ptr1 = nullptr; + const void* cur_ptr2 = nullptr; + uint32_t now = millis(); + + if (zigbee.state_waiting) { + + if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { + + if (!zigbee.state_no_timeout) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "timeout, goto label %d"), zigbee.on_timeout_goto); + ZigbeeGotoLabel(zigbee.on_timeout_goto); + } else { + zigbee.state_waiting = false; + } + } + } + + while ((zigbee.state_machine) && (!zigbee.state_waiting)) { + + zigbee.recv_filter = nullptr; + zigbee.recv_func = nullptr; + zigbee.recv_until = false; + zigbee.state_no_timeout = false; + + if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Invalid pc: %d, aborting"), zigbee.pc); + zigbee.pc = -1; + } + if (zigbee.pc < 0) { + zigbee.state_machine = false; + return; + } + + + + const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; + cur_instr = pgm_read_byte(&cur_instr_line->i.i); + cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); + cur_d16 = pgm_read_word(&cur_instr_line->i.d16); + if (cur_instr >= ZGB_INSTR_8_BYTES) { + cur_instr_line++; + cur_ptr1 = cur_instr_line->p; + } + if (cur_instr >= ZGB_INSTR_12_BYTES) { + cur_instr_line++; + cur_ptr2 = cur_instr_line->p; + } + + zigbee.pc += ZigbeeGetInstructionSize(cur_instr); + + switch (cur_instr) { + case ZGB_INSTR_NOOP: + case ZGB_INSTR_LABEL: + break; + case ZGB_INSTR_GOTO: + ZigbeeGotoLabel(cur_d8); + break; + case ZGB_INSTR_ON_ERROR_GOTO: + zigbee.on_error_goto = cur_d8; + break; + case ZGB_INSTR_ON_TIMEOUT_GOTO: + zigbee.on_timeout_goto = cur_d8; + break; + case ZGB_INSTR_WAIT: + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + zigbee.state_no_timeout = true; + break; + case ZGB_INSTR_WAIT_FOREVER: + zigbee.next_timeout = 0; + zigbee.state_waiting = true; + + break; + case ZGB_INSTR_STOP: + zigbee.state_machine = false; + if (cur_d8) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Stopping (%d)"), cur_d8); + } + break; + case ZGB_INSTR_CALL: + if (cur_ptr1) { + uint32_t res; + res = (*((ZB_Func)cur_ptr1))(cur_d8); + if (res > 0) { + ZigbeeGotoLabel(res); + continue; + } else if (res == 0) { + + } else if (res == -1) { + + } else { + ZigbeeGotoLabel(zigbee.on_error_goto); + continue; + } + } + break; + case ZGB_INSTR_LOG: + AddLog_P(cur_d8, (char*) cur_ptr1); + break; + case ZGB_INSTR_MQTT_STATE: + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":%d,\"Message\":\"%s\"}}"), + cur_d8, (char*) cur_ptr1); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + break; + case ZGB_INSTR_SEND: + ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 ); + break; + case ZGB_INSTR_WAIT_UNTIL: + zigbee.recv_until = true; + case ZGB_INSTR_WAIT_RECV: + zigbee.recv_filter = (uint8_t *) cur_ptr1; + zigbee.recv_filter_len = cur_d8; + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + break; + case ZGB_ON_RECV_UNEXPECTED: + zigbee.recv_unexpected = (ZB_RecvMsgFunc) cur_ptr1; + break; + case ZGB_INSTR_WAIT_RECV_CALL: + zigbee.recv_filter = (uint8_t *) cur_ptr1; + zigbee.recv_filter_len = cur_d8; + zigbee.recv_func = (ZB_RecvMsgFunc) cur_ptr2; + zigbee.next_timeout = now + cur_d16; + zigbee.state_waiting = true; + break; + } + } +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" +#ifdef USE_ZIGBEE + +int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { + + + + + + + + Z_IEEEAddress long_adr = buf.get64(3); + Z_ShortAddress short_adr = buf.get16(11); + uint8_t device_type = buf.get8(13); + uint8_t device_state = buf.get8(14); + uint8_t device_associated = buf.get8(15); + + + localIEEEAddr = long_adr; + + char hex[20]; + Uint64toHex(long_adr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"DeviceType\":%d,\"DeviceState\":%d" + ",\"NumAssocDevices\":%d"), + ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, + device_associated); + + if (device_associated > 0) { + uint idx = 16; + ResponseAppend_P(PSTR(",\"AssocDevicesList\":[")); + for (uint32_t i = 0; i < device_associated; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(idx)); + idx += 2; + } + ResponseAppend_P(PSTR("]")); + } + + ResponseJsonEnd(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + + return res; +} + +int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { + + + + uint8_t status = buf.get8(2); + if ((0x00 == status) || (0x09 == status)) { + return 0; + } else { + return -2; + } +} + +const char Z_RebootReason[] PROGMEM = "Power-up|External|Watchdog"; + +int32_t Z_Reboot(int32_t res, class SBuffer &buf) { + + + + uint8_t reason = buf.get8(2); + uint8_t transport_rev = buf.get8(3); + uint8_t product_id = buf.get8(4); + uint8_t major_rel = buf.get8(5); + uint8_t minor_rel = buf.get8(6); + uint8_t hw_rev = buf.get8(7); + char reason_str[12]; + + if (reason > 3) { reason = 3; } + GetTextIndexed(reason_str, sizeof(reason_str), reason, Z_RebootReason); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Message\":\"%s\",\"RestartReason\":\"%s\"" + ",\"MajorRel\":%d,\"MinorRel\":%d}}"), + ZIGBEE_STATUS_BOOT, "CC2530 booted", reason_str, + major_rel, minor_rel); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + + if ((0x02 == major_rel) && (0x06 == minor_rel)) { + return 0; + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; + } +} + +int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { +# 122 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" + uint8_t major_rel = buf.get8(4); + uint8_t minor_rel = buf.get8(5); + uint8_t maint_rel = buf.get8(6); + uint32_t revision = buf.get32(7); + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" + ",\"MaintRel\":%d,\"Revision\":%d}}"), + ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, + maint_rel, revision); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + + if ((0x02 == major_rel) && (0x06 == minor_rel)) { + return 0; + } else { + return ZIGBEE_LABEL_UNSUPPORTED_VERSION; + } +} + +bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { + if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && + (pgm_read_byte(&match[1]) == buf.get8(1)) ) { + return true; + } else { + return false; + } +} + +int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { + + uint8_t duration = buf.get8(2); + uint8_t status_code; + const char* message; + + if (0xFF == duration) { + status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_XX; + message = PSTR("Enable Pairing mode until next boot"); + } else if (duration > 0) { + status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_60; + message = PSTR("Enable Pairing mode for %d seconds"); + } else { + status_code = ZIGBEE_STATUS_PERMITJOIN_CLOSE; + message = PSTR("Disable Pairing mode"); + } + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Message\":\""), + status_code); + ResponseAppend_P(message, duration); + ResponseAppend_P(PSTR("\"}}")); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); + XdrvRulesProcess(); + return -1; +} + + +void Z_SendIEEEAddrReq(uint16_t shortaddr) { + uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; + + ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq)); +} + + +void Z_SendActiveEpReq(uint16_t shortaddr) { + uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; + + ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); + + + + + +} + + +void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint) { + uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, + Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), + endpoint }; + + ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); +} + +const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" }; +int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { + + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t logicalType = buf.get8(7); + uint8_t apsFlags = buf.get8(8); + uint8_t MACCapabilityFlags = buf.get8(9); + uint16_t manufacturerCapabilities = buf.get16(10); + uint8_t maxBufferSize = buf.get8(12); + uint16_t maxInTransferSize = buf.get16(13); + uint16_t serverMask = buf.get16(15); + uint16_t maxOutTransferSize = buf.get16(17); + uint8_t descriptorCapabilities = buf.get8(19); + + if (0 == status) { + zigbee_devices.updateLastSeen(nwkAddr); + + uint8_t deviceType = logicalType & 0x7; + if (deviceType > 3) { deviceType = 3; } + bool complexDescriptorAvailable = (logicalType & 0x08) ? 1 : 0; + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"NodeType\":\"%s\",\"ComplexDesc\":%s}}"), + ZIGBEE_STATUS_NODE_DESC, Z_DeviceType[deviceType], + complexDescriptorAvailable ? "true" : "false" + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + } + + return -1; +} + +int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { + + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t activeEpCount = buf.get8(7); + uint8_t* activeEpList = (uint8_t*) buf.charptr(8); + + + for (uint32_t i = 0; i < activeEpCount; i++) { + zigbee_devices.addEndoint(nwkAddr, activeEpList[i]); + } + + for (uint32_t i = 0; i < activeEpCount; i++) { + Z_SendSimpleDescReq(nwkAddr, activeEpList[i]); + } + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"ActiveEndpoints\":["), + ZIGBEE_STATUS_ACTIVE_EP); + for (uint32_t i = 0; i < activeEpCount; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%02X\""), activeEpList[i]); + } + ResponseAppend_P(PSTR("]}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + return -1; +} + +void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusterid, uint8_t transacid) { + SBuffer buf(100); + buf.add8(Z_SREQ | Z_AF); + buf.add8(AF_DATA_REQUEST); + buf.add16(shortaddr); + buf.add8(endpoint); + buf.add8(0x01); + buf.add16(clusterid); + buf.add8(transacid); + buf.add8(0x30); + buf.add8(0x1E); + + buf.add8(3 + 2*sizeof(uint16_t)); + buf.add8(0x00); + buf.add8(transacid); + buf.add8(ZCL_READ_ATTRIBUTES); + buf.add16(0x0004); + buf.add16(0x0005); + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +} + + +int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { + + Z_ShortAddress srcAddr = buf.get16(2); + uint8_t status = buf.get8(4); + Z_ShortAddress nwkAddr = buf.get16(5); + uint8_t lenDescriptor = buf.get8(7); + uint8_t endpoint = buf.get8(8); + uint16_t profileId = buf.get16(9); + uint16_t deviceId = buf.get16(11); + uint8_t deviceVersion = buf.get8(13); + uint8_t numInCluster = buf.get8(14); + uint8_t numOutCluster = buf.get8(15 + numInCluster*2); + + if (0 == status) { + zigbee_devices.addEndointProfile(nwkAddr, endpoint, profileId); + for (uint32_t i = 0; i < numInCluster; i++) { + zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(15 + i*2), false); + } + for (uint32_t i = 0; i < numOutCluster; i++) { + zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(16 + numInCluster*2 + i*2), true); + } + + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"Endpoint\":\"0x%02X\"" + ",\"ProfileId\":\"0x%04X\",\"DeviceId\":\"0x%04X\",\"DeviceVersion\":%d" + "\"InClusters\":["), + ZIGBEE_STATUS_SIMPLE_DESC, endpoint, + profileId, deviceId, deviceVersion); + for (uint32_t i = 0; i < numInCluster; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(15 + i*2)); + } + ResponseAppend_P(PSTR("],\"OutClusters\":[")); + for (uint32_t i = 0; i < numOutCluster; i++) { + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(16 + numInCluster*2 + i*2)); + } + ResponseAppend_P(PSTR("]}}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + uint8_t cluster = zigbee_devices.findClusterEndpointIn(nwkAddr, 0x0000); + if (cluster) { + Z_SendAFInfoRequest(nwkAddr, cluster, 0x0000, 0x01); + } + } + return -1; +} + +int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { + uint8_t status = buf.get8(2); + Z_IEEEAddress ieeeAddr = buf.get64(3); + Z_ShortAddress nwkAddr = buf.get16(11); + + + + if (0 == status) { + zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + "}}"), + ZIGBEE_STATUS_DEVICE_IEEE, hex, nwkAddr + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + const String * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + if (friendlyName) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), nwkAddr, friendlyName->c_str()); + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"}}"), nwkAddr); + } + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + } + return -1; +} + +int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { + Z_ShortAddress srcAddr = buf.get16(2); + Z_ShortAddress nwkAddr = buf.get16(4); + Z_IEEEAddress ieeeAddr = buf.get64(6); + uint8_t capabilities = buf.get8(14); + + zigbee_devices.updateDevice(nwkAddr, ieeeAddr); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), + ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, + (capabilities & 0x04) ? "true" : "false", + (capabilities & 0x08) ? "true" : "false", + (capabilities & 0x40) ? "true" : "false" + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + Z_SendActiveEpReq(nwkAddr); + return -1; +} + + +int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { + Z_ShortAddress srcAddr = buf.get16(2); + Z_IEEEAddress ieeeAddr = buf.get64(4); + Z_ShortAddress parentNw = buf.get16(12); + + zigbee_devices.updateDevice(srcAddr, ieeeAddr); + + char hex[20]; + Uint64toHex(ieeeAddr, hex, 64); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + ",\"ParentNetwork\":\"0x%04X\"}}"), + ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw + ); + + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + return -1; +} + + + +const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; + +void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, const JsonObject *json) { + + const JsonVariant &val_endpoint = getCaseInsensitive(*json, PSTR(OCCUPANCY)); + if (nullptr != &val_endpoint) { + uint32_t occupancy = strToUInt(val_endpoint); + + if (occupancy) { + zigbee_devices.setTimer(shortaddr, OCCUPANCY_TIMEOUT, cluster, endpoint, 0, &Z_OccupancyCallback); + } + } +} + + + +int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { + const JsonObject *json = zigbee_devices.jsonGet(shortaddr); + if (json == nullptr) { return 0; } + + Z_AqaraOccupancy(shortaddr, cluster, endpoint, json); + + zigbee_devices.jsonPublishFlush(shortaddr); + return 1; +} + +int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { + uint16_t groupid = buf.get16(2); + uint16_t clusterid = buf.get16(4); + Z_ShortAddress srcaddr = buf.get16(6); + uint8_t srcendpoint = buf.get8(8); + uint8_t dstendpoint = buf.get8(9); + uint8_t wasbroadcast = buf.get8(10); + uint8_t linkquality = buf.get8(11); + uint8_t securityuse = buf.get8(12); + uint32_t timestamp = buf.get32(13); + uint8_t seqnumber = buf.get8(17); + + bool defer_attributes = false; + + zigbee_devices.updateLastSeen(srcaddr); + ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, + srcaddr, + srcendpoint, dstendpoint, wasbroadcast, + linkquality, securityuse, seqnumber, + timestamp); + zcl_received.log(); + char shortaddr[8]; + snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); + + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + + if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { + zcl_received.parseRawAttributes(json); + if (clusterid) { defer_attributes = true; } + } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { + zcl_received.parseReadAttributes(json); + } else if (zcl_received.isClusterSpecificCommand()) { + zcl_received.parseClusterSpecificCommand(json); + } + String msg(""); + msg.reserve(100); + json.printTo(msg); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); + + zcl_received.postProcessAttributes(srcaddr, json); + + json[F(D_CMND_ZIGBEE_ENDPOINT)] = srcendpoint; + + json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; + + if (defer_attributes) { + + if (zigbee_devices.jsonIsConflict(srcaddr, json)) { + + zigbee_devices.jsonPublishFlush(srcaddr); + } else { + zigbee_devices.jsonAppend(srcaddr, json); + zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); + } + } else { + + zigbee_devices.jsonPublishNow(srcaddr, json); + } + return -1; +} + +typedef struct Z_Dispatcher { + const uint8_t* match; + ZB_RecvMsgFunc func; +} Z_Dispatcher; + + +ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) +ZBM(AREQ_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) +ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) +ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) +ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) +ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) +ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) + +const Z_Dispatcher Z_DispatchTable[] PROGMEM = { + { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, + { AREQ_END_DEVICE_ANNCE_IND, &Z_ReceiveEndDeviceAnnonce }, + { AREQ_END_DEVICE_TC_DEV_IND, &Z_ReceiveTCDevInd }, + { AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus }, + { AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc }, + { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, + { AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc }, + { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, +}; + +int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { + + if (zigbee.init_phase) { + + return -1; + } else { + for (uint32_t i = 0; i < sizeof(Z_DispatchTable)/sizeof(Z_Dispatcher); i++) { + if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) { + (*Z_DispatchTable[i].func)(res, buf); + } + } + return -1; + } +} + +int32_t Z_Load_Devices(uint8_t value) { + + loadZigbeeDevices(); + return 0; +} + +int32_t Z_State_Ready(uint8_t value) { + zigbee.init_phase = false; + return 0; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" +#ifdef USE_ZIGBEE + +#define XDRV_23 23 + +const uint32_t ZIGBEE_BUFFER_SIZE = 256; +const uint8_t ZIGBEE_SOF = 0xFE; +const uint8_t ZIGBEE_SOF_ALT = 0xFF; + +#include +TasmotaSerial *ZigbeeSerial = nullptr; + + +const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" + D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" + D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" + D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" + D_CMND_ZIGBEE_PING ; + +const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" + D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" + D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" + D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" + D_CMND_ZIGBEE_PING ; + +void (* const ZigbeeCommand[])(void) PROGMEM = { + &CmndZbZNPSend, &CmndZbPermitJoin, + &CmndZbStatus, &CmndZbReset, &CmndZbSend, + &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, + &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, + &CmndZbPing, + }; + +int32_t ZigbeeProcessInput(class SBuffer &buf) { + if (!zigbee.state_machine) { return -1; } + + + bool recv_filter_match = true; + bool recv_prefix_match = false; + if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { + if (zigbee.recv_filter_len >= 2) { + recv_prefix_match = false; + if ( (pgm_read_byte(&zigbee.recv_filter[0]) == buf.get8(0)) && + (pgm_read_byte(&zigbee.recv_filter[1]) == buf.get8(1)) ) { + recv_prefix_match = true; + } + } + + for (uint32_t i = 0; i < zigbee.recv_filter_len; i++) { + if (pgm_read_byte(&zigbee.recv_filter[i]) != buf.get8(i)) { + recv_filter_match = false; + break; + } + } + + + } + + + int32_t res = -1; + + + + + + if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { + if (!recv_prefix_match) { + res = -1; + } else { + if (recv_filter_match) { + res = 0; + } else { + if (zigbee.recv_until) { + res = -1; + } else { + res = -2; + } + } + } + } else { + res = -1; + } + + if (recv_prefix_match) { + if (zigbee.recv_func) { + res = (*zigbee.recv_func)(res, buf); + } + } + if (-1 == res) { + + if (zigbee.recv_unexpected) { + res = (*zigbee.recv_unexpected)(res, buf); + } + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZbProcessInput: res = %d"), res); + + + if (0 == res) { + + zigbee.state_waiting = false; + } else if (res > 0) { + ZigbeeGotoLabel(res); + } else if (-1 == res) { + + + } else { + + ZigbeeGotoLabel(zigbee.on_error_goto); + } +} + +void ZigbeeInput(void) +{ + static uint32_t zigbee_polling_window = 0; + static uint8_t fcs = ZIGBEE_SOF; + static uint32_t zigbee_frame_len = 5; +# 145 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" + while (ZigbeeSerial->available()) { + yield(); + uint8_t zigbee_in_byte = ZigbeeSerial->read(); + + + if (0 == zigbee_buffer->len()) { + zigbee_frame_len = 5; + fcs = ZIGBEE_SOF; + + + + if (ZIGBEE_SOF_ALT == zigbee_in_byte) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput forgiven first byte %02X (only for statistics)"), zigbee_in_byte); + zigbee_in_byte = ZIGBEE_SOF; + } + } + + if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput discarding byte %02X"), zigbee_in_byte); + continue; + } + + if (zigbee_buffer->len() < zigbee_frame_len) { + zigbee_buffer->add8(zigbee_in_byte); + zigbee_polling_window = millis(); + fcs ^= zigbee_in_byte; + } + + if (zigbee_buffer->len() >= zigbee_frame_len) { + zigbee_polling_window = 0; + break; + } + + + if (02 == zigbee_buffer->len()) { + + uint8_t len_byte = zigbee_buffer->get8(1); + if (len_byte > 250) len_byte = 250; + + zigbee_frame_len = len_byte + 5; + } + } + + if (zigbee_buffer->len() && (millis() > (zigbee_polling_window + ZIGBEE_POLLING))) { + char hex_char[(zigbee_buffer->len() * 2) + 2]; + ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Bytes follow_read_metric = %0d"), ZigbeeSerial->getLoopReadMetric()); + + if (zigbee_buffer->len() != zigbee_frame_len) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received frame of wrong size %s, len %d, expected %d"), hex_char, zigbee_buffer->len(), zigbee_frame_len); + } else if (0x00 != fcs) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received bad FCS frame %s, %d"), hex_char, fcs); + } else { + + + + SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); + + ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char)); + Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); + if (Settings.flag3.tuya_serial_mqtt_publish) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); + XdrvRulesProcess(); + } else { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); + } + + ZigbeeProcessInput(znp_buffer); + } + zigbee_buffer->setLen(0); + } +} + + + +void ZigbeeInit(void) +{ + zigbee.active = false; + if ((pin[GPIO_ZIGBEE_RX] < 99) && (pin[GPIO_ZIGBEE_TX] < 99)) { + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); + + ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], seriallog_level ? 1 : 2, 0, 256); + ZigbeeSerial->begin(115200); + if (ZigbeeSerial->hardwareSerial()) { + ClaimSerial(); + uint32_t aligned_buffer = ((uint32_t)serial_in_buffer + 3) & ~3; + zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer) - 3, (char*) aligned_buffer); + } else { + zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); + } + zigbee.active = true; + zigbee.init_phase = true; + zigbee.state_machine = true; + ZigbeeSerial->flush(); + } +} + + + + + +uint32_t strToUInt(const JsonVariant &val) { + + if (val.is()) { + return val.as(); + } else { + if (val.is()) { + String sval = val.as(); + return strtoull(sval.c_str(), nullptr, 0); + } + } + return 0; +} + +const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = + { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x01 }; + + +void CmndZbReset(void) { + if (ZigbeeSerial) { + switch (XdrvMailbox.payload) { + case 1: + ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET)); + eraseZigbeeDevices(); + restart_flag = 2; + ResponseCmndChar(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING); + break; + default: + ResponseCmndChar(D_JSON_ONE_TO_RESET); + } + } +} + +void CmndZbZNPSendOrReceive(bool send) +{ + if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { + uint8_t code; + + char *codes = RemoveSpace(XdrvMailbox.data); + int32_t size = strlen(XdrvMailbox.data); + + SBuffer buf((size+1)/2); + + while (size > 1) { + char stemp[3]; + strlcpy(stemp, codes, sizeof(stemp)); + code = strtol(stemp, nullptr, 16); + buf.add8(code); + size -= 2; + codes += 2; + } + if (send) { + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + } else { + ZigbeeProcessInput(buf); + } + } + ResponseCmndDone(); +} + + +void CmndZbZNPReceive(void) +{ + CmndZbZNPSendOrReceive(false); +} + +void CmndZbZNPSend(void) +{ + CmndZbZNPSendOrReceive(true); +} + +void ZigbeeZNPSend(const uint8_t *msg, size_t len) { + if ((len < 2) || (len > 252)) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPSENT ": bad message len %d"), len); + return; + } + uint8_t data_len = len - 2; + + if (ZigbeeSerial) { + uint8_t fcs = data_len; + + ZigbeeSerial->write(ZIGBEE_SOF); + + ZigbeeSerial->write(data_len); + + for (uint32_t i = 0; i < len; i++) { + uint8_t b = pgm_read_byte(msg + i); + ZigbeeSerial->write(b); + fcs ^= b; + + } + ZigbeeSerial->write(fcs); + + } + + char hex_char[(len * 2) + 2]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"), + ToHex_P(msg, len, hex_char, sizeof(hex_char))); +} + +void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { + SBuffer buf(25+len); + buf.add8(Z_SREQ | Z_AF); + buf.add8(AF_DATA_REQUEST); + buf.add16(dtsAddr); + buf.add8(endpoint); + buf.add8(0x01); + buf.add16(clusterId); + buf.add8(transacId); + buf.add8(0x30); + buf.add8(0x1E); + + buf.add8(3 + len); + buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00)); + buf.add8(transacId); + buf.add8(cmdId); + if (len > 0) { + buf.addBuffer(msg, len); + } + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); +} + +void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, bool clusterSpecific, + uint16_t cluster, uint8_t cmd, const char *param) { + size_t size = param ? strlen(param) : 0; + SBuffer buf((size+2)/2); + + if (param) { + while (*param) { + uint8_t code = parseHex_P(¶m, 2); + buf.add8(code); + } + } + + if (0 == endpoint) { + + endpoint = zigbee_devices.findClusterEndpointIn(dstAddr, cluster); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: dstAddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), + dstAddr, cluster, endpoint, cmd, param); + + if (0 == endpoint) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); + return; + } + + + ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len(), false, zigbee_devices.getNextSeqNumber(dstAddr)); + + if (clusterSpecific) { + zigbeeSetCommandTimer(dstAddr, cluster, endpoint); + } + ResponseCmndDone(); +} + +void CmndZbSend(void) { +# 419 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + + static char delim[] = ", "; + uint16_t device = 0xFFFF; + uint8_t endpoint = 0x00; + + uint16_t cluster = 0; + uint8_t cmd = 0; + String cmd_str = ""; + + + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); + if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send")); + if (nullptr != &val_cmd) { + + + + if (val_cmd.is()) { + + JsonObject &cmd_obj = val_cmd.as(); + int32_t cmd_size = cmd_obj.size(); + if (cmd_size > 1) { + Response_P(PSTR("Only 1 command allowed (%d)"), cmd_size); + return; + } else if (1 == cmd_size) { + + JsonObject::iterator it = cmd_obj.begin(); + String key = it->key; + JsonVariant& value = it->value; + uint32_t x = 0, y = 0, z = 0; + uint16_t cmd_var; + + const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.c_str(), &cluster, &cmd_var); + if (tasmota_cmd) { + cmd_str = tasmota_cmd; + } else { + Response_P(PSTR("Unrecognized zigbee command: %s"), key.c_str()); + return; + } + + + if (value.is()) { + x = value.as() ? 1 : 0; + } else if (value.is()) { + x = value.as(); + } else { + + const char *s_const = value.as(); + if (s_const != nullptr) { + char s[strlen(s_const)+1]; + strcpy(s, s_const); + if ((nullptr != s) && (0x00 != *s)) { + char *sval = strtok(s, delim); + if (sval) { + x = ZigbeeAliasOrNumber(sval); + sval = strtok(nullptr, delim); + if (sval) { + y = ZigbeeAliasOrNumber(sval); + sval = strtok(nullptr, delim); + if (sval) { + z = ZigbeeAliasOrNumber(sval); + } + } + } + } + } + } + + + if (0xFF == cmd_var) { + cmd = x; + x = y; + y = z; + } else { + cmd = cmd_var; + } + cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); + + } else { + + } + } else if (val_cmd.is()) { + + cmd_str = val_cmd.as(); + } else { + + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%04X!%02X/%s\"}"), + device, endpoint, cluster, cmd, cmd_str.c_str()); + zigbeeZCLSendStr(device, endpoint, true, cluster, cmd, cmd_str.c_str()); + } else { + Response_P(PSTR("Missing zigbee 'Send'")); + return; + } + +} + +ZBM(ZBS_BIND_REQ, Z_SREQ | Z_ZDO, ZDO_BIND_REQ, + 0,0, + 0,0,0,0,0,0,0,0, + 0x00, + 0x00, 0x00, + 0x03, + 0,0,0,0,0,0,0,0, + 0x01 +) + +void CmndZbBind(void) { + + + + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + + + uint16_t device = 0xFFFF; + uint8_t endpoint = 0x00; + uint16_t cluster = 0; + uint32_t group = 0xFFFFFFFF; + + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); + if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); + if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } + + + + SBuffer buf(sizeof(ZBS_BIND_REQ)); + buf.add8(Z_SREQ | Z_ZDO); + buf.add8(ZDO_BIND_REQ); + buf.add16(device); + buf.add64(zigbee_devices.getDeviceLongAddr(device)); + buf.add8(endpoint); + buf.add16(cluster); + buf.add8(0x03); + buf.add64(localIEEEAddr); + buf.add8(0x01); + + ZigbeeZNPSend(buf.getBuffer(), buf.len()); + + ResponseCmndDone(); +} + + +void CmndZbProbe(void) { + CmndZbProbeOrPing(true); +} + +void CmndZbProbeOrPing(boolean probe) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + + Z_SendIEEEAddrReq(shortaddr); + if (probe) { + Z_SendActiveEpReq(shortaddr); + } + ResponseCmndDone(); +} + + +void CmndZbPing(void) { + CmndZbProbeOrPing(false); +} + + +void CmndZbName(void) { + + + + + + + + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + + + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + + + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + if (p == nullptr) { + const String * friendlyName = zigbee_devices.getFriendlyName(shortaddr); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName->c_str() : ""); + } else { + zigbee_devices.setFriendlyName(shortaddr, p); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p); + } +} + + +void CmndZbForget(void) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + + if (zigbee_devices.removeDevice(shortaddr)) { + ResponseCmndDone(); + } else { + ResponseCmndChar("Unknown device"); + } +} + + +void CmndZbSave(void) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + + saveZigbeeDevices(); + + ResponseCmndDone(); +} + + +void CmndZbRead(void) { + + + + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + DynamicJsonBuffer jsonBuf; + JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); + if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } + + + uint16_t device = 0xFFFF; + uint16_t cluster = 0x0000; + uint8_t endpoint = 0x00; + size_t attrs_len = 0; + uint8_t* attrs = nullptr; + + const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); + if (nullptr != &val_device) { + device = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + } + if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } + + const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); + if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } + const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); + if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + + const JsonVariant &val_attr = getCaseInsensitive(json, PSTR("Read")); + if (nullptr != &val_attr) { + uint16_t val = strToUInt(val_attr); + if (val_attr.is()) { + JsonArray& attr_arr = val_attr; + attrs_len = attr_arr.size() * 2; + attrs = new uint8_t[attrs_len]; + + uint32_t i = 0; + for (auto value : attr_arr) { + uint16_t val = strToUInt(value); + attrs[i++] = val & 0xFF; + attrs[i++] = val >> 8; + } + } else { + attrs_len = 2; + attrs = new uint8_t[attrs_len]; + attrs[0] = val & 0xFF; + attrs[1] = val >> 8; + } + } + + if (0 == endpoint) { + endpoint = zigbee_devices.findClusterEndpointIn(device, cluster); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); + } + + if ((0 != endpoint) && (attrs_len > 0)) { + ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true , zigbee_devices.getNextSeqNumber(device)); + ResponseCmndDone(); + } else { + ResponseCmndChar("Missing parameters"); + } + + if (attrs) { delete[] attrs; } +} + + +void CmndZbPermitJoin(void) +{ + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint32_t payload = XdrvMailbox.payload; + if (payload < 0) { payload = 0; } + if ((99 != payload) && (payload > 1)) { payload = 1; } + + if (1 == payload) { + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60); + } else if (99 == payload){ + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX); + } else { + ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE); + } + ResponseCmndDone(); +} + +void CmndZbStatus(void) { + if (ZigbeeSerial) { + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + if (XdrvMailbox.payload > 0) { + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + } + + String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr); + Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); + } +} + + + + + +bool Xdrv23(uint8_t function) +{ + bool result = false; + + if (zigbee.active) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (!zigbee.init_phase) { + zigbee_devices.runTimer(); + } + break; + case FUNC_LOOP: + if (ZigbeeSerial) { ZigbeeInput(); } + if (zigbee.state_machine) { + + ZigbeeStateMachine_Run(); + } + break; + case FUNC_PRE_INIT: + ZigbeeInit(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kZbCommands, ZigbeeCommand); + result = result || DecodeCommand(kZigbeeCommands, ZigbeeCommand); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_24_buzzer.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_24_buzzer.ino" +#ifdef USE_BUZZER + + + + +#define XDRV_24 24 + +struct BUZZER { + uint32_t tune = 0; + uint32_t tune_reload = 0; + bool active = true; + bool enable = false; + uint8_t inverted = 0; + uint8_t count = 0; + uint8_t mode = 0; + uint8_t set[2]; + uint8_t duration; + uint8_t state = 0; +} Buzzer; + + + +void BuzzerOff(void) +{ + DigitalWrite(GPIO_BUZZER, Buzzer.inverted); +} + + +void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) +{ + Buzzer.set[0] = off; + Buzzer.set[1] = on; + Buzzer.duration = 1; + Buzzer.tune_reload = 0; + Buzzer.mode = mode; + + if (tune) { + uint32_t tune1 = tune; + uint32_t tune2 = tune; + for (uint32_t i = 0; i < 32; i++) { + if (!(tune2 & 0x80000000)) { + tune2 <<= 1; + } else { + Buzzer.tune_reload <<= 1; + Buzzer.tune_reload |= tune1 & 1; + tune1 >>= 1; + } + } + Buzzer.tune = Buzzer.tune_reload; + } + Buzzer.count = count * 2; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, Buzzer.count, on, off, tune, Buzzer.tune); + + Buzzer.enable = (Buzzer.count > 0); + if (!Buzzer.enable) { + BuzzerOff(); + } +} + +void BuzzerSetStateToLed(uint32_t state) +{ + if (Buzzer.enable && (2 == Buzzer.mode)) { + Buzzer.state = (state != 0); + DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); + } +} + +void BuzzerBeep(uint32_t count) +{ + BuzzerBeep(count, 1, 1, 0, 0); +} + +void BuzzerEnabledBeep(uint32_t count, uint32_t duration) +{ + if (Settings.flag3.buzzer_enable) { + BuzzerBeep(count, duration, 1, 0, 0); + } +} + + + +bool BuzzerPinState(void) +{ + if (XdrvMailbox.index == GPIO_BUZZER_INV) { + Buzzer.inverted = 1; + XdrvMailbox.index -= (GPIO_BUZZER_INV - GPIO_BUZZER); + return true; + } + return false; +} + +void BuzzerInit(void) +{ + if (pin[GPIO_BUZZER] < 99) { + pinMode(pin[GPIO_BUZZER], OUTPUT); + BuzzerOff(); + } else { + Buzzer.active = false; + } +} + +void BuzzerEvery100mSec(void) +{ + if (Buzzer.enable && (Buzzer.mode != 2)) { + if (Buzzer.count) { + if (Buzzer.duration) { + Buzzer.duration--; + if (!Buzzer.duration) { + if (Buzzer.tune) { + Buzzer.state = Buzzer.tune & 1; + Buzzer.tune >>= 1; + } else { + Buzzer.tune = Buzzer.tune_reload; + Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1; + Buzzer.state = Buzzer.count & 1; + if (Buzzer.mode) { + Buzzer.count |= 2; + } + } + Buzzer.duration = Buzzer.set[Buzzer.state]; + } + } + DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); + } else { + Buzzer.enable = false; + } + } +} + + + + + +const char kBuzzerCommands[] PROGMEM = "|" + "Buzzer" ; + +void (* const BuzzerCommand[])(void) PROGMEM = { + &CmndBuzzer }; + +void CmndBuzzer(void) +{ +# 174 "S:/Development/Tasmota/tasmota/xdrv_24_buzzer.ino" + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload != 0) { + uint32_t parm[4] = { 0 }; + uint32_t mode = 0; + ParseParameters(4, parm); + if (XdrvMailbox.payload <= 0) { + parm[0] = 1; + mode = -XdrvMailbox.payload; + } + for (uint32_t i = 1; i < 3; i++) { + if (parm[i] < 1) { parm[i] = 1; } + } + BuzzerBeep(parm[0], parm[1], parm[2], parm[3], mode); + } else { + BuzzerBeep(0); + } + } else { + BuzzerBeep(1); + } + ResponseCmndDone(); +} + + + + + +bool Xdrv24(uint8_t function) +{ + bool result = false; + + if (Buzzer.active) { + switch (function) { + case FUNC_EVERY_100_MSECOND: + BuzzerEvery100mSec(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kBuzzerCommands, BuzzerCommand); + break; + case FUNC_PRE_INIT: + BuzzerInit(); + break; + case FUNC_PIN_STATE: + result = BuzzerPinState(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" +# 21 "S:/Development/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" +#ifdef USE_A4988_STEPPER + + + + +#define XDRV_25 25 + +#include + +short A4988_dir_pin = pin[GPIO_MAX]; +short A4988_stp_pin = pin[GPIO_MAX]; +short A4988_ms1_pin = pin[GPIO_MAX]; +short A4988_ms2_pin = pin[GPIO_MAX]; +short A4988_ms3_pin = pin[GPIO_MAX]; +short A4988_ena_pin = pin[GPIO_MAX]; +int A4988_spr = 0; +float A4988_rpm = 0; +short A4988_mis = 0; + +A4988_Stepper* myA4988 = nullptr; + +void A4988Init(void) +{ + A4988_dir_pin = pin[GPIO_A4988_DIR]; + A4988_stp_pin = pin[GPIO_A4988_STP]; + A4988_ena_pin = pin[GPIO_A4988_ENA]; + A4988_ms1_pin = pin[GPIO_A4988_MS1]; + A4988_ms2_pin = pin[GPIO_A4988_MS2]; + A4988_ms3_pin = pin[GPIO_A4988_MS3]; + A4988_spr = 200; + A4988_rpm = 30; + A4988_mis = 1; + + myA4988 = new A4988_Stepper( A4988_spr + , A4988_rpm + , A4988_mis + , A4988_dir_pin + , A4988_stp_pin + , A4988_ena_pin + , A4988_ms1_pin + , A4988_ms2_pin + , A4988_ms3_pin ); +} + +const char kA4988Commands[] PROGMEM = "Motor|" + "Move|Rotate|Turn|MIS|SPR|RPM"; + +void (* const A4988Command[])(void) PROGMEM = { + &CmndDoMove,&CmndDoRotate,&CmndDoTurn,&CmndSetMIS,&CmndSetSPR,&CmndSetRPM}; + +void CmndDoMove(void) { + if (XdrvMailbox.data_len > 0) { + long stepsPlease = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->doMove(stepsPlease); + ResponseCmndDone(); + } +} + +void CmndDoRotate(void) { + if (XdrvMailbox.data_len > 0) { + long degrsPlease = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->doRotate(degrsPlease); + ResponseCmndDone(); + } +} + +void CmndDoTurn(void) { + if (XdrvMailbox.data_len > 0) { + float turnsPlease = strtod(XdrvMailbox.data,nullptr); + myA4988->doTurn(turnsPlease); + ResponseCmndDone(); + } +} + +void CmndSetMIS(void) { + if ((pin[GPIO_A4988_MS1] < 99) && (pin[GPIO_A4988_MS2] < 99) && (pin[GPIO_A4988_MS3] < 99) && (XdrvMailbox.data_len > 0)) { + short newMIS = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setMIS(newMIS); + ResponseCmndDone(); + } +} + +void CmndSetSPR(void) { + if (XdrvMailbox.data_len > 0) { + int newSPR = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setSPR(newSPR); + ResponseCmndDone(); + } +} + +void CmndSetRPM(void) { + if (XdrvMailbox.data_len > 0) { + short newRPM = strtoul(XdrvMailbox.data,nullptr,10); + myA4988->setRPM(newRPM); + ResponseCmndDone(); + } +} + + + + +bool Xdrv25(uint8_t function) +{ + bool result = false; + if ((pin[GPIO_A4988_DIR] < 99) && (pin[GPIO_A4988_STP] < 99)) { + switch (function) { + case FUNC_INIT: + A4988Init(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kA4988Commands, A4988Command); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_26_ariluxrf.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_26_ariluxrf.ino" +#ifdef USE_LIGHT +#ifdef USE_ARILUX_RF + + + + +#define XDRV_26 26 + +const uint32_t ARILUX_RF_TIME_AVOID_DUPLICATE = 1000; + +const uint8_t ARILUX_RF_MAX_CHANGES = 51; +const uint32_t ARILUX_RF_SEPARATION_LIMIT = 4300; +const uint32_t ARILUX_RF_RECEIVE_TOLERANCE = 60; + +struct ARILUX { + unsigned int rf_timings[ARILUX_RF_MAX_CHANGES]; + + unsigned long rf_received_value = 0; + unsigned long rf_last_received_value = 0; + unsigned long rf_last_time = 0; + unsigned long rf_lasttime = 0; + + unsigned int rf_change_count = 0; + unsigned int rf_repeat_count = 0; + + uint8_t rf_toggle = 0; +} Arilux; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +#ifndef USE_WS2812_DMA +void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; +#endif +#endif + +void AriluxRfInterrupt(void) +{ + unsigned long time = micros(); + unsigned int duration = time - Arilux.rf_lasttime; + + if (duration > ARILUX_RF_SEPARATION_LIMIT) { + if (abs(duration - Arilux.rf_timings[0]) < 200) { + Arilux.rf_repeat_count++; + if (Arilux.rf_repeat_count == 2) { + unsigned long code = 0; + const unsigned int delay = Arilux.rf_timings[0] / 31; + const unsigned int delayTolerance = delay * ARILUX_RF_RECEIVE_TOLERANCE / 100; + for (unsigned int i = 1; i < Arilux.rf_change_count -1; i += 2) { + code <<= 1; + if (abs(Arilux.rf_timings[i] - (delay *3)) < delayTolerance && abs(Arilux.rf_timings[i +1] - delay) < delayTolerance) { + code |= 1; + } + } + if (Arilux.rf_change_count > 49) { + Arilux.rf_received_value = code; + } + Arilux.rf_repeat_count = 0; + } + } + Arilux.rf_change_count = 0; + } + if (Arilux.rf_change_count >= ARILUX_RF_MAX_CHANGES) { + Arilux.rf_change_count = 0; + Arilux.rf_repeat_count = 0; + } + Arilux.rf_timings[Arilux.rf_change_count++] = duration; + Arilux.rf_lasttime = time; +} + +void AriluxRfHandler(void) +{ + unsigned long now = millis(); + if (Arilux.rf_received_value && !((Arilux.rf_received_value == Arilux.rf_last_received_value) && (now - Arilux.rf_last_time < ARILUX_RF_TIME_AVOID_DUPLICATE))) { + Arilux.rf_last_received_value = Arilux.rf_received_value; + Arilux.rf_last_time = now; + + uint16_t hostcode = Arilux.rf_received_value >> 8 & 0xFFFF; + if (Settings.rf_code[1][6] == Settings.rf_code[1][7]) { + Settings.rf_code[1][6] = hostcode >> 8 & 0xFF; + Settings.rf_code[1][7] = hostcode & 0xFF; + } + uint16_t stored_hostcode = Settings.rf_code[1][6] << 8 | Settings.rf_code[1][7]; + + DEBUG_DRIVER_LOG(PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, Arilux.rf_received_value); + + if (hostcode == stored_hostcode) { + char command[33]; + char value = '-'; + command[0] = '\0'; + uint8_t keycode = Arilux.rf_received_value & 0xFF; + switch (keycode) { + case 1: + case 3: + snprintf_P(command, sizeof(command), PSTR(D_CMND_POWER " %d"), (1 == keycode) ? 1 : 0); + break; + case 2: + Arilux.rf_toggle++; + Arilux.rf_toggle &= 0x3; + snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), 200 + Arilux.rf_toggle); + break; + case 4: + value = '+'; + case 7: + snprintf_P(command, sizeof(command), PSTR(D_CMND_SPEED " %c"), value); + break; + case 5: + value = '+'; + case 8: + snprintf_P(command, sizeof(command), PSTR(D_CMND_SCHEME " %c"), value); + break; + case 6: + value = '+'; + case 9: + snprintf_P(command, sizeof(command), PSTR(D_CMND_DIMMER " %c"), value); + break; + default: { + if ((keycode >= 10) && (keycode <= 21)) { + snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), keycode -9); + } + } + } + if (strlen(command)) { + ExecuteCommand(command, SRC_LIGHT); + } + } + } + Arilux.rf_received_value = 0; +} + +void AriluxRfInit(void) +{ + if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { + if (Settings.last_module != Settings.module) { + Settings.rf_code[1][6] = 0; + Settings.rf_code[1][7] = 0; + Settings.last_module = Settings.module; + } + Arilux.rf_received_value = 0; + + digitalWrite(pin[GPIO_ARIRFSEL], 0); + attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE); + } +} + +void AriluxRfDisable(void) +{ + if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { + detachInterrupt(pin[GPIO_ARIRFRCV]); + digitalWrite(pin[GPIO_ARIRFSEL], 1); + } +} + + + + + +bool Xdrv26(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_ARIRFRCV] < 99) { AriluxRfHandler(); } + break; + case FUNC_EVERY_SECOND: + if (10 == uptime) { AriluxRfInit(); } + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_27_shutter.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_27_shutter.ino" +#ifdef USE_SHUTTER + + + + +#define XDRV_27 27 + +#define D_SHUTTER "SHUTTER" + +const uint16_t MOTOR_STOP_TIME = 500; +const uint8_t steps_per_second = 20; + +uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; +uint16_t messwerte[5] = {30,50,70,90,100}; +uint16_t last_execute_step; + +enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; +enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; + +const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" + D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" + D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" + D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" + D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME; + +void (* const ShutterCommand[])(void) PROGMEM = { + &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, + &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, + &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, + &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime}; + + const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}"; + const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; + +#include + +Ticker TickerShutter; + +struct SHUTTER { + power_t mask = 0; + power_t old_power = 0; + power_t switched_relay = 0; + uint32_t time[MAX_SHUTTERS]; + int32_t open_max[MAX_SHUTTERS]; + int32_t target_position[MAX_SHUTTERS]; + int32_t start_position[MAX_SHUTTERS]; + int32_t real_position[MAX_SHUTTERS]; + uint16_t open_time[MAX_SHUTTERS]; + uint16_t close_time[MAX_SHUTTERS]; + uint16_t close_velocity[MAX_SHUTTERS]; + int8_t direction[MAX_SHUTTERS]; + uint8_t mode = 0; + int16_t motordelay[MAX_SHUTTERS]; + int16_t pwm_frequency[MAX_SHUTTERS]; + uint16_t max_pwm_frequency = 1000; + uint16_t max_close_pwm_frequency[MAX_SHUTTERS]; + uint8_t skip_relay_change; + int32_t accelerator[MAX_SHUTTERS]; +} Shutter; + +void ShutterLogPos(uint32_t i) +{ + char stemp2[10]; + dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d"), + i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_frequency[i]); +} + +void ShutterRtc50mS(void) +{ + for (uint8_t i = 0; i < shutters_present; i++) { + Shutter.time[i]++; + if (Shutter.accelerator[i]) { + + Shutter.pwm_frequency[i] += Shutter.accelerator[i]; + Shutter.pwm_frequency[i] = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency[i])); + analogWriteFreq(Shutter.pwm_frequency[i]); + analogWrite(pin[GPIO_PWM1+i], 50); + } + } +} + +#define SHT_DIV_ROUND(__A,__B) (((__A) + (__B)/2) / (__B)) + +int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) +{ + if (Settings.shutter_set50percent[index] != 50) { + return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; + } else { + uint32_t realpos; + + for (uint32_t j = 0; j < 5; j++) { + if (0 == Settings.shuttercoeff[j][index]) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); + for (uint32_t k = 0; k < 5; k++) { + Settings.shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]); + } + } + } + for (uint32_t i = 0; i < 5; i++) { + if ((percent * 10) >= Settings.shuttercoeff[i][index]) { + realpos = SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i+1], 100); + + } else { + if (0 == i) { + realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter.open_max[index] * calibrate_pos[i+1], Settings.shuttercoeff[i][index]), 10); + } else { + + + realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]), Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), 100); + } + break; + } + } + return realpos; + } +} + +uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) +{ + if (Settings.shutter_set50percent[index] != 50) { + return (Settings.shuttercoeff[2][index] * 5 > realpos) ? SHT_DIV_ROUND(realpos, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos-Settings.shuttercoeff[0][index], Settings.shuttercoeff[1][index]); + } else { + uint16_t realpercent; + + for (uint32_t i = 0; i < 5; i++) { + if (realpos >= Shutter.open_max[index] * calibrate_pos[i+1] / 100) { + realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[i][index], 10); + + } else { + if (0 == i) { + realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * Settings.shuttercoeff[i][index], calibrate_pos[i+1]), Shutter.open_max[index]); + } else { + + + + realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), (calibrate_pos[i+1] - calibrate_pos[i])), Shutter.open_max[index]) ; + } + break; + } + } + return realpercent; + } +} + +void ShutterInit(void) +{ + shutters_present = 0; + Shutter.mask = 0; + + Shutter.old_power = power; + bool relay_in_interlock = false; + + + if (Settings.shutter_startrelay[MAX_SHUTTERS] == 0) { + Shutter.max_pwm_frequency = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : Shutter.max_pwm_frequency; + } + for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { + + Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]); + if (Settings.shutter_startrelay[i] && (Settings.shutter_startrelay[i] < 9)) { + shutters_present++; + + + Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1) ; + + for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { + + if (Settings.interlock[j] && (Settings.interlock[j] & Shutter.mask)) { + + relay_in_interlock = true; + } + } + if (relay_in_interlock) { + if (Settings.pulse_timer[i] > 0) { + Shutter.mode = SHT_PULSE_OPEN__PULSE_CLOSE; + } else { + Shutter.mode = SHT_OFF_OPEN__OFF_CLOSE; + } + } else { + Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; + if ((pin[GPIO_PWM1+i] < 99) && (pin[GPIO_CNTR1+i] < 99)) { + Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER; + Shutter.pwm_frequency[i] = 0; + Shutter.accelerator[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); + analogWrite(pin[GPIO_PWM1+i], 50); + } + } + + TickerShutter.attach_ms(50, ShutterRtc50mS ); + + Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] > 0) ? Settings.shutter_set50percent[i] : 50; + + + Shutter.open_time[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100; + Shutter.close_time[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100; + + + Shutter.open_max[i] = 200 * Shutter.open_time[i]; + Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ; + Shutter.max_close_pwm_frequency[i] = Shutter.max_pwm_frequency*Shutter.open_time[i] / Shutter.close_time[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Closefreq: %d"),i, Shutter.max_close_pwm_frequency[i]); + + + if (Settings.shutter_set50percent[i] != 50) { + Settings.shuttercoeff[1][i] = Shutter.open_max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; + Settings.shuttercoeff[0][i] = Shutter.open_max[i] - (Settings.shuttercoeff[1][i] * 100); + Settings.shuttercoeff[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5; + } + Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1); + + Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i); + + Shutter.start_position[i] = Shutter.target_position[i] = Shutter.real_position[i]; + Shutter.motordelay[i] = Settings.shutter_motordelay[i]; + + char shutter_open_chr[10]; + dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); + char shutter_close_chr[10]; + dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100, Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, is locked %d, end stop time enabled %d, shuttermode %d, motordelay %d"), + i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, + Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], + Shutter.mask, (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, Shutter.mode, Shutter.motordelay[i]); + + } else { + + break; + } + ShutterLimitRealAndTargetPositions(i); + Settings.shutter_accuracy = 1; + } +} + +void ShutterReportPosition(bool always) +{ + Response_P(PSTR("{")); + for (uint32_t i = 0; i < shutters_present; i++) { + + uint32_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); + if (Shutter.direction[i] != 0) { + rules_flag.shutter_moving = 1; + ShutterLogPos(i); + } + if (i) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i], ShutterRealToPercentPosition(Shutter.target_position[i], i)); + } + ResponseJsonEnd(); + if (always || (rules_flag.shutter_moving)) { + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); + XdrvRulesProcess(); + } + + +} + +void ShutterLimitRealAndTargetPositions(uint32_t i) { + if (Shutter.real_position[i]<0) Shutter.real_position[i] = 0; + if (Shutter.real_position[i]>Shutter.open_max[i]) Shutter.real_position[i] = Shutter.open_max[i]; + if (Shutter.target_position[i]<0) Shutter.target_position[i] = 0; + if (Shutter.target_position[i]>Shutter.open_max[i]) Shutter.target_position[i] = Shutter.open_max[i]; +} + +void ShutterUpdatePosition(void) +{ + + char scommand[CMDSZ]; + char stopic[TOPSZ]; + + for (uint32_t i = 0; i < shutters_present; i++) { + if (Shutter.direction[i] != 0) { + int32_t stop_position_delta = 20; + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { + + + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + + int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; + int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); + int32_t min_runtime_ms = Shutter.pwm_frequency[i]*1000 / max_freq_change_per_sec; + int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; + int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency[i] / max_frequency * Shutter.direction[i] ; + + int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; + stop_position_delta =200 * Shutter.pwm_frequency[i]/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); + + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, + Shutter.pwm_frequency[i],max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); + + if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { + + Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); + + } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency[i] == max_frequency) { + Shutter.accelerator[i] = 0; + } + } else { + Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + } + if ( Shutter.real_position[i] * Shutter.direction[i] + stop_position_delta >= Shutter.target_position[i] * Shutter.direction[i] ) { + + + uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; + int16_t missing_steps; + + switch (Shutter.mode) { + case SHT_PULSE_OPEN__PULSE_CLOSE: + + if (SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source) { + ExecuteCommandPower(cur_relay, 1, SRC_SHUTTER); + } else { + last_source = SRC_SHUTTER; + } + break; + case SHT_OFF_ON__OPEN_CLOSE_STEPPER: + missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency[i]); + Shutter.accelerator[i] = 0; + Shutter.pwm_frequency[i] = Shutter.pwm_frequency[i] > 250 ? 250 : Shutter.pwm_frequency[i]; + analogWriteFreq(Shutter.pwm_frequency[i]); + analogWrite(pin[GPIO_PWM1+i], 50); + Shutter.pwm_frequency[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); + while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { + delay(1); + } + analogWrite(pin[GPIO_PWM1+i], 0); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); + + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); + } + break; + case SHT_OFF_ON__OPEN_CLOSE: + if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); + } + break; + case SHT_OFF_OPEN__OFF_CLOSE: + + if ((1 << (cur_relay-1)) & power) { + + ExecuteCommandPower(cur_relay, 0, SRC_SHUTTER); + } + break; + } + ShutterLimitRealAndTargetPositions(i); + Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); + + ShutterLogPos(i); + + Shutter.start_position[i] = Shutter.real_position[i]; + + + snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); + GetTopic_P(stopic, STAT, mqtt_topic, scommand); + Response_P("%d", (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); + MqttPublish(stopic, Settings.flag.mqtt_power_retain); + + Shutter.direction[i] = 0; + ShutterReportPosition(true); + rules_flag.shutter_moved = 1; + XdrvRulesProcess(); + } + } + } +} + +bool ShutterState(uint32_t device) +{ + device--; + device &= 3; + return (Settings.flag3.shutter_mode && + (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) ); +} + +void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) +{ + + if ( ( (1 == direction) && ((Shutter.open_max[i] - Shutter.real_position[i]) / 100 <= 2) ) + || ( (-1 == direction) && (Shutter.real_position[i] / Shutter.close_velocity[i] <= 2)) ) { + Shutter.skip_relay_change = 1; + } else { + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { + Shutter.pwm_frequency[i] = 0; + analogWriteFreq(Shutter.pwm_frequency[i]); + analogWrite(pin[GPIO_PWM1+i], 0); + + if (pin[GPIO_CNTR1+i] < 99) { + RtcSettings.pulse_counter[i] = 0; + } + Shutter.accelerator[i] = Shutter.max_pwm_frequency / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Ramp up: %d"), Shutter.accelerator[i]); + } + Shutter.target_position[i] = target_pos; + Shutter.start_position[i] = Shutter.real_position[i]; + Shutter.time[i] = 0; + Shutter.skip_relay_change = 0; + Shutter.direction[i] = direction; + + } + +} + +void ShutterWaitForMotorStop(uint32_t i) +{ + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); + if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { + if (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode) { + + while (Shutter.pwm_frequency[i] > 0) { + + Shutter.pwm_frequency[i] = tmax(Shutter.pwm_frequency[i]-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); + + analogWriteFreq(Shutter.pwm_frequency[i]); + analogWrite(pin[GPIO_PWM1+i], 50); + delay(50); + } + analogWrite(pin[GPIO_PWM1+i], 0); + Shutter.real_position[i] = ShutterCounterBasedPosition(i); + } else { + ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); + delay(MOTOR_STOP_TIME); + } + } else { + delay(MOTOR_STOP_TIME); + } +} + +int32_t ShutterCounterBasedPosition(uint32_t i) +{ + return ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; +} + +void ShutterRelayChanged(void) +{ + + + + + char stemp1[10]; + + for (uint32_t i = 0; i < shutters_present; i++) { + power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; + + uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; + + if (manual_relays_changed) { + + ShutterLimitRealAndTargetPositions(i); + if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { + ShutterWaitForMotorStop(i); + switch (powerstate_local) { + case 1: + ShutterStartInit(i, 1, Shutter.open_max[i]); + break; + case 3: + ShutterStartInit(i, -1, 0); + break; + default: + + Shutter.target_position[i] = Shutter.real_position[i]; + } + } else { + if (Shutter.direction[i] != 0 && (!powerstate_local || (powerstate_local && Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE))) { + Shutter.target_position[i] = Shutter.real_position[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); + } else { + last_source = SRC_SHUTTER; + if (powerstate_local == 2) { + + ShutterWaitForMotorStop(i); + ShutterStartInit(i, -1, 0); + } else { + + ShutterWaitForMotorStop(i); + ShutterStartInit(i, 1, Shutter.open_max[i]); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter.target_position[i], powerstate_local); + } + } + } +} + +bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { + + uint32 min_shutterbutton_hold_timer = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) + min_shutterbutton_hold_timer = Button.hold_timer[i]; + } + return (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1)); +} + +void ShutterButtonHandler(void) +{ + uint8_t buttonState = SHT_NOT_PRESSED; + uint8_t button = XdrvMailbox.payload; + uint8_t press_index; + uint32_t button_index = XdrvMailbox.index; + uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; + + uint16_t loops_per_second = 1000 / Settings.button_debounce; + if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { + if (Settings.flag.button_single) { + buttonState = SHT_PRESSED_MULTI; + press_index = 1; + } else { + if ((Shutter.direction[shutter_index]) && (Button.press_counter[button_index]==0)) { + buttonState = SHT_PRESSED_IMMEDIATE; + press_index = 1; + Button.press_counter[button_index] = 99; + } else { + Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; + } + } + blinks = 201; + } + + if (NOT_PRESSED == button) { + Button.hold_timer[button_index] = 0; + } else { + Button.hold_timer[button_index]++; + if (!Settings.flag.button_single) { + if (Settings.param[P_HOLD_IGNORE] > 0) { + if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { + Button.hold_timer[button_index] = 0; + Button.press_counter[button_index] = 0; + } + } + if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { + + if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { + + for (uint32_t i = 0; i < MAX_KEYS; i++) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) + Button.press_counter[i] = 99; + press_index = 0; + buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS; + } + if (Button.press_counter[button_index]<99) { + press_index = 0; + buttonState = SHT_PRESSED_HOLD; + } + Button.press_counter[button_index] = 0; + } + if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { + + if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { + + press_index = 0; + buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; + } + } + } + } + + if (!Settings.flag.button_single) { + if (Button.window_timer[button_index]) { + Button.window_timer[button_index]--; + } else { + if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { + if (Button.press_counter[button_index]<99) { + + uint32 min_shutterbutton_press_counter = -1; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter); + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { + min_shutterbutton_press_counter = Button.press_counter[i]; + } + + } + if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:simultanous presss deteced")); + press_index = Button.press_counter[button_index]; + for (uint32_t i = 0; i < MAX_KEYS; i++) + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) + Button.press_counter[i] = 99; + buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; + } + if ((buttonState != SHT_PRESSED_MULTI_SIMULTANEOUS) && (Button.press_counter[button_index]<99)) { + + press_index = Button.press_counter[button_index]; + buttonState = SHT_PRESSED_MULTI; + } + } + Button.press_counter[button_index] = 0; + } + } + } + + if (buttonState != SHT_NOT_PRESSED) { + if (buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) { + if ((press_index>=5) && (press_index<=7) && (!Settings.flag.button_restrict)) { + + char scmnd[20]; + GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { + if (!Settings.flag.button_restrict) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } else if (buttonState <= SHT_PRESSED_IMMEDIATE) { + if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { + uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); + if (pos_press_index>3) pos_press_index=3; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); + XdrvMailbox.index = shutter_index +1; + last_source = SRC_BUTTON; + XdrvMailbox.data_len = 0; + char databuf[1] = ""; + XdrvMailbox.data = databuf; + XdrvMailbox.command = NULL; + if (buttonState == SHT_PRESSED_IMMEDIATE) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); + } else { + uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; + if (position) { + if (Shutter.direction[shutter_index]) { + XdrvMailbox.payload = XdrvMailbox.index; + CmndShutterStop(); + } else { + XdrvMailbox.payload = position = (position-1)<<1; + CmndShutterPosition(); + if (Settings.shutter_button[button_index] & ((0x01<<26)< 0) && (XdrvMailbox.index <= shutters_present)) { + if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { + if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { + XdrvMailbox.index = XdrvMailbox.payload; + } + uint32_t i = XdrvMailbox.index -1; + if (Shutter.direction[i] != 0) { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]); + + int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); + XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); + + last_source = SRC_WEBGUI; + CmndShutterPosition(); + } else { + if (XdrvMailbox.command) + ResponseCmndDone(); + } + } else { + if (XdrvMailbox.command) + ResponseCmndIdxChar("Locked"); + } + } +} + +void CmndShutterPosition(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { + uint32_t index = XdrvMailbox.index-1; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); + + + + if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { + + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { + CmndShutterOpen(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN))) { + CmndShutterClose(); + return; + } + if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN)))) { + XdrvMailbox.payload = -99; + CmndShutterStop(); + return; + } + } + + int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? (XdrvMailbox.payload == -99 ? ShutterRealToPercentPosition(Shutter.real_position[index], index) : 0) : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); + + target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; + if (XdrvMailbox.payload != -99) { + + Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); + } + if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { + if (Settings.shutter_options[index] & 4) { + if (0 == target_pos_percent) Shutter.target_position[index] -= 1 * 2000; + if (100 == target_pos_percent) Shutter.target_position[index] += 1 * 2000; + } + int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; + if (Shutter.direction[index] == -new_shutterdirection) { + + if (SHT_PULSE_OPEN__PULSE_CLOSE == Shutter.mode) { + + ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 0 : 1), 1, SRC_SHUTTER); + delay(100); + } else { + if (SHT_OFF_OPEN__OFF_CLOSE == Shutter.mode) { + ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 1 : 0), 0, SRC_SHUTTER); + ShutterWaitForMotorStop(index); + } + } + } + if (Shutter.direction[index] != new_shutterdirection) { + if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { + + ShutterWaitForMotorStop(index); + ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); + if (Shutter.skip_relay_change == 0) { + + ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); + + ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); + } + } else { + + AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start in dir %d"), Shutter.direction[index]); + ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); + if (Shutter.skip_relay_change == 0) { + ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); + } + + } + Shutter.switched_relay = 0; + } + } else { + target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); + ShutterReportPosition(true); + } + XdrvMailbox.index = index +1; + if (XdrvMailbox.command) + ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent); + } else { + ShutterReportPosition(true); + if (XdrvMailbox.command) + ResponseCmndIdxChar("Locked"); + } + } +} + +void CmndShutterOpenTime(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_opentime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index -1]) / 10, 1, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterCloseTime(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_closetime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index -1]) / 10, 1, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterMotorDelay(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(steps_per_second * CharToFloat(XdrvMailbox.data)); + ShutterInit(); + } + char time_chr[10]; + dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / steps_per_second, 2, time_chr); + ResponseCmndIdxChar(time_chr); + } +} + +void CmndShutterRelay(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) { + Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; + if (XdrvMailbox.payload > 0) { + Shutter.mask |= 3 << (XdrvMailbox.payload - 1); + } else { + Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1); + } + Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; + ShutterInit(); + + } + ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]); + } +} + +void CmndShutterButton(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + uint32_t setting = 0; +# 912 "S:/Development/Tasmota/tasmota/xdrv_27_shutter.ino" + if (XdrvMailbox.data_len > 0) { + uint32_t i = 0; + uint32_t button_index = 0; + bool done = false; + bool isShortCommand = false; + char *str_ptr; + + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); + + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) { + int field; + if (str[0] == '-') { + field = -1; + } else { + field = atoi(str); + } + switch (i) { + case 0: + if ((field >= -1) && (field<=4)) { + button_index = (field<=0)?(-1):field; + done = (button_index==-1); + } else + done = true; + break; + case 1: + if (!strcmp_P(str, PSTR("up"))) { + setting |= (((100>>1)+1)<<2) | (((50>>1)+1)<<8) | (((75>>1)+1)<<14) | (((100>>1)+1)<<20); + isShortCommand = true; + break; + } else if (!strcmp_P(str, PSTR("down"))) { + setting |= (((0>>1)+1)<<2) | (((50>>1)+1)<<8) | (((25>>1)+1)<<14) | (((0>>1)+1)<<20); + isShortCommand = true; + break; + } else if (!strcmp_P(str, PSTR("updown"))) { + setting |= (((100>>1)+1)<<2) | (((0>>1)+1)<<8) | (((50>>1)+1)<<14); + isShortCommand = true; + break; + } + case 2: + if (isShortCommand) { + if ((field==1) && (setting & (0x3F<<(2+6*3)))) + + setting |= (0x3<<29); + done = true; + break; + } + case 3: + case 4: + if ((field >= -1) && (field<=100)) + setting |= (((field>>1)+1)<<(i*6 + (2-6))); + break; + case 5: + case 6: + case 7: + case 8: + case 9: + if (field==1) + setting |= (1<<(i + (26-5))); + break; + } + if (done) break; + } + + if (button_index) { + if (button_index==-1) { + + for (uint32_t i=0 ; i < MAX_KEYS ; i++) + if ((Settings.shutter_button[i]&0x3) == (XdrvMailbox.index-1)) + Settings.shutter_button[i] = 0; + } else { + if (setting) { + + setting |= (1<<31); + setting |= (XdrvMailbox.index-1) & 0x3; + } + Settings.shutter_button[button_index-1] = setting; + } + } + } + char setting_chr[30*MAX_KEYS] = "-", *setting_chr_ptr = setting_chr; + for (uint32_t i=0 ; i < MAX_KEYS ; i++) { + setting = Settings.shutter_button[i]; + if ((setting&(1<<31)) && ((setting&0x3) == (XdrvMailbox.index-1))) { + if (*setting_chr_ptr == 0) + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR("|")); + setting_chr_ptr += snprintf_P(setting_chr_ptr, 2, PSTR("%d"), i+1); + + for (uint32_t j=0 ; j < 4 ; j++) { + int8_t pos = (((setting>> (2+6*j))&(0x3f))-1)<<1; + if (pos>=0) + setting_chr_ptr += snprintf_P(setting_chr_ptr, 5, PSTR(" %d"), pos); + else + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); + } + for (uint32_t j=0 ; j < 5 ; j++) { + bool mqtt = ((setting>>(26+j))&(0x01)!=0); + if (mqtt) + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" 1")); + else + setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); + } + } + } + ResponseCmndIdxChar(setting_chr); + } +} + +void CmndShutterSetHalfway(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { + Settings.shutter_set50percent[XdrvMailbox.index -1] = (Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; + ShutterInit(); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); + } +} + +void CmndShutterFrequency(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { + Shutter.max_pwm_frequency = XdrvMailbox.payload; + if (shutters_present < 4) { + Settings.shuttercoeff[4][3] = Shutter.max_pwm_frequency; + } + ShutterInit(); + ResponseCmndNumber(XdrvMailbox.payload); + } else { + ResponseCmndNumber(Shutter.max_pwm_frequency); + } +} + +void CmndShutterSetClose(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + Shutter.real_position[XdrvMailbox.index -1] = 0; + ShutterStartInit(XdrvMailbox.index -1, 0, 0); + Settings.shutter_position[XdrvMailbox.index -1] = 0; + ResponseCmndIdxChar(D_CONFIGURATION_RESET); + } +} + +void CmndShutterInvert(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(1); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (1); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 1 : 0); + } +} + +void CmndShutterCalibration(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.data_len > 0) { + uint32_t i = 0; + char *str_ptr; + + char data_copy[strlen(XdrvMailbox.data) +1]; + strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); + + for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 5; str = strtok_r(nullptr, " ", &str_ptr), i++) { + int field = atoi(str); + + + if ((field <= 0) || (field > 30000) || ( (i>0) && (field <= messwerte[i-1]) ) ) { + break; + } + messwerte[i] = field; + } + for (i = 0; i < 5; i++) { + Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); + } + ShutterInit(); + ResponseCmndIdxChar(XdrvMailbox.data); + } else { + char setting_chr[30] = "0"; + snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings.shuttercoeff[0][XdrvMailbox.index -1], Settings.shuttercoeff[1][XdrvMailbox.index -1], Settings.shuttercoeff[2][XdrvMailbox.index -1], Settings.shuttercoeff[3][XdrvMailbox.index -1], Settings.shuttercoeff[4][XdrvMailbox.index -1]); + ResponseCmndIdxChar(setting_chr); + } + } +} + +void CmndShutterLock(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(2); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (2); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 2) ? 1 : 0); + } +} + +void CmndShutterEnableEndStopTime(void) { + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { + if (XdrvMailbox.payload == 0) { + Settings.shutter_options[XdrvMailbox.index -1] &= ~(4); + } else if (XdrvMailbox.payload == 1) { + Settings.shutter_options[XdrvMailbox.index -1] |= (4); + } + ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 4) ? 1 : 0); + } +} + + + + + +bool Xdrv27(uint8_t function) +{ + bool result = false; + + if (Settings.flag3.shutter_mode) { + switch (function) { + case FUNC_PRE_INIT: + ShutterInit(); + break; + case FUNC_EVERY_50_MSECOND: + ShutterUpdatePosition(); + break; + case FUNC_EVERY_SECOND: + + ShutterReportPosition(false); + break; + + case FUNC_COMMAND: + result = DecodeCommand(kShutterCommands, ShutterCommand); + break; + case FUNC_JSON_APPEND: + for (uint8_t i = 0; i < shutters_present; i++) { + uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; + ResponseAppend_P(","); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_SHUTTER, position); + } +#endif + } + break; + case FUNC_SET_POWER: + char stemp1[10]; + + Shutter.switched_relay = XdrvMailbox.index ^ Shutter.old_power; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), Shutter.switched_relay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); + ShutterRelayChanged(); + Shutter.old_power = XdrvMailbox.index; + break; + case FUNC_SET_DEVICE_POWER: + if (Shutter.skip_relay_change ) { + uint8_t i; + for (i = 0; i < devices_present; i++) { + if (Shutter.switched_relay &1) { + break; + } + Shutter.switched_relay >>= 1; + } + + result = true; + Shutter.skip_relay_change = 0; + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"),i); + ExecuteCommandPower(i+1, 0, SRC_SHUTTER); + } + break; + case FUNC_BUTTON_PRESSED: + if (Settings.shutter_button[XdrvMailbox.index] & (1<<31)) { + ShutterButtonHandler(); + result = true; + } + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_28_pcf8574.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_28_pcf8574.ino" +#ifdef USE_I2C +#ifdef USE_PCF8574 + + + + + + + +#define XDRV_28 28 +#define XI2C_02 2 + +#define PCF8574_ADDR1 0x20 +#define PCF8574_ADDR2 0x38 + +struct PCF8574 { + int error; + uint8_t pin[64]; + uint8_t address[MAX_PCF8574]; + uint8_t pin_mask[MAX_PCF8574] = { 0 }; + uint8_t max_connected_ports = 0; + uint8_t max_devices = 0; + char stype[9]; + bool type = false; +} Pcf8574; + +void Pcf8574SwitchRelay(void) +{ + for (uint32_t i = 0; i < devices_present; i++) { + uint8_t relay_state = bitRead(XdrvMailbox.index, i); + + + + if (Pcf8574.max_devices > 0 && Pcf8574.pin[i] < 99) { + uint8_t board = Pcf8574.pin[i]>>3; + uint8_t oldpinmask = Pcf8574.pin_mask[board]; + uint8_t _val = bitRead(rel_inverted, i) ? !relay_state : relay_state; + + + + if (_val) { + Pcf8574.pin_mask[board] |= _val << (Pcf8574.pin[i]&0x7); + } else { + Pcf8574.pin_mask[board] &= ~(1 << (Pcf8574.pin[i]&0x7)); + } + if (oldpinmask != Pcf8574.pin_mask[board]) { + Wire.beginTransmission(Pcf8574.address[board]); + Wire.write(Pcf8574.pin_mask[board]); + Pcf8574.error = Wire.endTransmission(); + } + + } + } +} + +void Pcf8574Init(void) +{ + uint8_t pcf8574_address = PCF8574_ADDR1; + while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +8)) { + + + + if (I2cSetDevice(pcf8574_address)) { + Pcf8574.type = true; + + Pcf8574.address[Pcf8574.max_devices] = pcf8574_address; + Pcf8574.max_devices++; + + strcpy(Pcf8574.stype, "PCF8574"); + if (pcf8574_address >= PCF8574_ADDR2) { + strcpy(Pcf8574.stype, "PCF8574A"); + } + I2cSetActiveFound(pcf8574_address, Pcf8574.stype); + } + + pcf8574_address++; +#ifdef USE_MCP230xx_ADDR + if (USE_MCP230xx_ADDR == pcf8574_address) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Addr: 0x%x reserved for MCP320xx, skipping PCF8574 probe"), pcf8574_address); + pcf8574_address++; + } +#endif + if ((PCF8574_ADDR1 +7) == pcf8574_address) { + pcf8574_address = PCF8574_ADDR2 +1; + } + } + if (Pcf8574.type) { + for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { + Pcf8574.pin[i] = 99; + } + devices_present = devices_present - Pcf8574.max_connected_ports; + Pcf8574.max_connected_ports = 0; + for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Device %d config 0x%02x"), idx +1, Settings.pcf8574_config[idx]); + + for (uint32_t i = 0; i < 8; i++) { + uint8_t _result = Settings.pcf8574_config[idx] >> i &1; + + if (_result > 0) { + Pcf8574.pin[devices_present] = i + 8 * idx; + bitWrite(rel_inverted, devices_present, Settings.flag3.pcf8574_ports_inverted); + devices_present++; + Pcf8574.max_connected_ports++; + } + } + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Total devices %d, PCF8574 output ports %d"), Pcf8574.max_devices, Pcf8574.max_connected_ports); + } +} + + + + + +#ifdef USE_WEBSERVER + +#define WEB_HANDLE_PCF8574 "pcf" + +const char HTTP_BTN_MENU_PCF8574[] PROGMEM = + "

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

" D_INVERT_PORTS "


"; + +const char HTTP_FORM_I2C_PCF8574_2[] PROGMEM = + "" D_DEVICE " %d " D_PORT " %d"; + +void HandlePcf8574(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_PCF8574)); + + if (WebServer->hasArg("save")) { + Pcf8574SaveSettings(); + WebRestart(1); + return; + } + + WSContentStart_P(D_CONFIGURE_PCF8574); + WSContentSendStyle(); + WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? " checked" : ""); + WSContentSend_P(HTTP_TABLE100); + for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { + for (uint32_t idx2 = 0; idx2 < 8; idx2++) { + uint8_t helper = 1 << idx2; + WSContentSend_P(HTTP_FORM_I2C_PCF8574_2, + idx +1, idx2, + idx2 + 8*idx, + idx2 + 8*idx, + ((helper & Settings.pcf8574_config[idx]) >> idx2 == 0) ? " selected " : " ", + ((helper & Settings.pcf8574_config[idx]) >> idx2 == 1) ? " selected " : " " + ); + } + } + WSContentSend_P(PSTR("")); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void Pcf8574SaveSettings(void) +{ + char stemp[7]; + char tmp[100]; + + + + Settings.flag3.pcf8574_ports_inverted = WebServer->hasArg("b1"); + for (byte idx = 0; idx < Pcf8574.max_devices; idx++) { + byte count=0; + byte n = Settings.pcf8574_config[idx]; + while(n!=0) { + n = n&(n-1); + count++; + } + if (count <= devices_present) { + devices_present = devices_present - count; + } + for (byte i = 0; i < 8; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("i2cs%d"), i+8*idx); + WebGetArg(stemp, tmp, sizeof(tmp)); + byte _value = (!strlen(tmp)) ? 0 : atoi(tmp); + if (_value) { + Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] | 1 << i; + devices_present++; + Pcf8574.max_connected_ports++; + } else { + Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] & ~(1 << i ); + } + } + + + + } +} +#endif + + + + + +bool Xdrv28(uint8_t function) +{ + if (!I2cEnabled(XI2C_02)) { return false; } + + bool result = false; + + if (FUNC_PRE_INIT == function) { + Pcf8574Init(); + } + else if (Pcf8574.type) { + switch (function) { + case FUNC_SET_POWER: + Pcf8574SwitchRelay(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_PCF8574); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_PCF8574, HandlePcf8574); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_29_deepsleep.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_29_deepsleep.ino" +#ifdef USE_DEEPSLEEP +# 31 "S:/Development/Tasmota/tasmota/xdrv_29_deepsleep.ino" +#define XDRV_29 29 + +#define D_PRFX_DEEPSLEEP "DeepSleep" +#define D_CMND_DEEPSLEEP_TIME "Time" + +const uint32_t DEEPSLEEP_MAX = 10 * 366 * 24 * 60 * 60; +const uint32_t DEEPSLEEP_MAX_CYCLE = 60 * 60; +const uint32_t DEEPSLEEP_MIN_TIME = 5; +const uint32_t DEEPSLEEP_START_COUNTDOWN = 4; + +const char kDeepsleepCommands[] PROGMEM = D_PRFX_DEEPSLEEP "|" + D_CMND_DEEPSLEEP_TIME ; + +void (* const DeepsleepCommand[])(void) PROGMEM = { + &CmndDeepsleepTime }; + +uint32_t deepsleep_sleeptime = 0; +uint8_t deepsleep_flag = 0; + +bool DeepSleepEnabled(void) +{ + if ((Settings.deepsleep < 10) || (Settings.deepsleep > DEEPSLEEP_MAX)) { + Settings.deepsleep = 0; + return false; + } + + if (pin[GPIO_DEEPSLEEP] < 99) { + pinMode(pin[GPIO_DEEPSLEEP], INPUT_PULLUP); + return (digitalRead(pin[GPIO_DEEPSLEEP])); + } + + return true; +} + +void DeepSleepReInit(void) +{ + if ((ResetReason() == REASON_DEEP_SLEEP_AWAKE) && DeepSleepEnabled()) { + if ((RtcSettings.ultradeepsleep > DEEPSLEEP_MAX_CYCLE) && (RtcSettings.ultradeepsleep < 1700000000)) { + + RtcSettings.ultradeepsleep = RtcSettings.ultradeepsleep - DEEPSLEEP_MAX_CYCLE; + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Remain DeepSleep %d"), RtcSettings.ultradeepsleep); + RtcSettingsSave(); + RtcRebootReset(); + ESP.deepSleep(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep), WAKE_RF_DEFAULT); + yield(); + + } + } + + RtcSettings.ultradeepsleep = 0; +} + +void DeepSleepPrepare(void) +{ + + + + + if ((RtcSettings.nextwakeup == 0) || + (RtcSettings.deepsleep_slip < 9000) || + (RtcSettings.deepsleep_slip > 11000) || + (RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip ); + RtcSettings.nextwakeup = 0; + RtcSettings.deepsleep_slip = 10000; + } + + + + int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - UtcTime()) * 10; + + + + timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; + if (timeslip) { + RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5); + + RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); + RtcSettings.nextwakeup += Settings.deepsleep; + } + + + + if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) { + + RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep; + } + + String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); + + + deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_CYCLE ,RtcSettings.nextwakeup - UtcTime()); + + + Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATUS)); + + + +} + +void DeepSleepStart(void) +{ + AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Sleeping")); + + WifiShutdown(); + RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); + RtcSettingsSave(); + + ESP.deepSleep(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); + yield(); +} + +void DeepSleepEverySecond(void) +{ + if (!deepsleep_flag) { return; } + + if (DeepSleepEnabled()) { + if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { + SettingsSaveAll(); + DeepSleepPrepare(); + } + deepsleep_flag--; + if (deepsleep_flag <= 0) { + DeepSleepStart(); + } + } else { + deepsleep_flag = 0; + } +} + + + + + +void CmndDeepsleepTime(void) +{ + if ((0 == XdrvMailbox.payload) || + ((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < DEEPSLEEP_MAX))) { + Settings.deepsleep = XdrvMailbox.payload; + RtcSettings.nextwakeup = 0; + deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN; + if (deepsleep_flag) { + if (!Settings.tele_period) { + Settings.tele_period = TELE_PERIOD; + } + } + } + Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.deepsleep); +} + + + + + +bool Xdrv29(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_SECOND: + DeepSleepEverySecond(); + break; + case FUNC_AFTER_TELEPERIOD: + if (DeepSleepEnabled() && !deepsleep_flag && (Settings.tele_period == 10 || Settings.tele_period == 300 || UpTime() > Settings.tele_period)) { + deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kDeepsleepCommands, DeepsleepCommand); + break; + case FUNC_PRE_INIT: + DeepSleepReInit(); + break; + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" +#ifdef USE_LIGHT +#ifdef USE_EXS_DIMMER + + + + + + + +#define XDRV_30 30 + +#define EXS_GATE_1_ON 0x20 +#define EXS_GATE_1_OFF 0x21 +#define EXS_DIMM_1_ON 0x22 +#define EXS_DIMM_1_OFF 0x23 +#define EXS_DIMM_1_TBL 0x24 +#define EXS_DIMM_1_VAL 0x25 +#define EXS_GATE_2_ON 0x30 +#define EXS_GATE_2_OFF 0x31 +#define EXS_DIMM_2_ON 0x32 +#define EXS_DIMM_2_OFF 0x33 +#define EXS_DIMM_2_TBL 0x34 +#define EXS_DIMM_2_VAL 0x35 +#define EXS_GATES_ON 0x40 +#define EXS_GATES_OFF 0x41 +#define EXS_DIMMS_ON 0x50 +#define EXS_DIMMS_OFF 0x51 +#define EXS_CH_LOCK 0x60 +#define EXS_GET_VALUES 0xFA +#define EXS_WRITE_EE 0xFC +#define EXS_READ_EE 0xFD +#define EXS_GET_VERSION 0xFE +#define EXS_RESET 0xFF + +#define EXS_BUFFER_SIZE 256 +#define EXS_ACK_TIMEOUT 200 + +#include + +TasmotaSerial *ExsSerial = nullptr; + +typedef struct +{ + uint8_t on = 0; + uint8_t bright_tbl = 0; + uint8_t dimm = 0; + uint8_t impuls_start = 0; + uint32_t impuls_len = 0; +} CHANNEL; + +typedef struct +{ + uint8_t version_major = 0; + uint8_t version_minor = 0; + CHANNEL channel[2]; + uint8_t gate_lock = 0; +} DIMMER; + +struct EXS +{ + uint8_t *buffer = nullptr; + int byte_counter = 0; + int cmd_status = 0; + uint8_t power = 0; + uint8_t dimm[2] = {0, 0}; + DIMMER dimmer; +} Exs; + + + + + +uint8_t crc8(const uint8_t *p, uint8_t len) +{ + const uint8_t table[] = { + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, + 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D}; + + const uint8_t table_rev[] = { + 0x00, 0x70, 0xE0, 0x90, 0xC1, 0xB1, 0x21, 0x51, + 0x83, 0xF3, 0x63, 0x13, 0x42, 0x32, 0xA2, 0xD2}; + + uint8_t offset; + uint8_t temp, crc8_temp; + uint8_t crc8 = 0; + + for (int i = 0; i < len; i++) + { + temp = *(p + i); + offset = temp ^ crc8; + offset >>= 4; + crc8_temp = crc8 & 0x0f; + crc8 = crc8_temp ^ table_rev[offset]; + offset = crc8 ^ temp; + offset &= 0x0f; + crc8_temp = crc8 & 0xf0; + crc8 = crc8_temp ^ table[offset]; + } + return crc8 ^ 0x55; +} + +void ExsSerialSend(const uint8_t data[] = nullptr, uint16_t len = 0) +{ + int retries = 3; + char rc; + +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: Tx Packet: \"")); + for (uint32_t i = 0; i < len; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, data[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + while (retries) + { + retries--; + + ExsSerial->write(data, len); + ExsSerial->flush(); + + + uint32_t snd_time = millis(); + while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && + (!ExsSerial->available())) + ; + + if (!ExsSerial->available()) + { + +#ifdef EXS_DEBUG + AddLog_P(LOG_LEVEL_DEBUG, PSTR("ESX: serial send timeout")); +#endif + continue; + } + + rc = ExsSerial->read(); + if (rc == 0xFF) + break; + } +} + +void ExsSendCmd(uint8_t cmd, uint8_t value) +{ + uint8_t buffer[8]; + uint16_t len; + + buffer[0] = 0x7b; + buffer[3] = cmd; + + switch (cmd) + { + case EXS_GATE_1_ON: + case EXS_GATE_1_OFF: + case EXS_DIMM_1_ON: + case EXS_DIMM_1_OFF: + case EXS_GATE_2_ON: + case EXS_GATE_2_OFF: + case EXS_DIMM_2_ON: + case EXS_DIMM_2_OFF: + case EXS_GATES_ON: + case EXS_GATES_OFF: + case EXS_DIMMS_ON: + case EXS_DIMMS_OFF: + case EXS_GET_VALUES: + case EXS_GET_VERSION: + case EXS_RESET: + buffer[2] = 1; + len = 4; + break; + + case EXS_CH_LOCK: + case EXS_DIMM_1_TBL: + case EXS_DIMM_1_VAL: + case EXS_DIMM_2_TBL: + case EXS_DIMM_2_VAL: + buffer[2] = 2; + buffer[4] = value; + len = 5; + break; + } + buffer[1] = crc8(&buffer[3], buffer[2]); + + ExsSerialSend(buffer, len); +} + +uint8_t ExsSetPower(uint8_t device, uint8_t power) +{ + Exs.dimmer.channel[device].dimm = power; + ExsSendCmd(EXS_DIMM_1_ON + 0x10 * device + power ^ 1, 0); +} + +uint8_t ExsSetBri(uint8_t device, uint8_t bri) +{ + Exs.dimmer.channel[device].bright_tbl = bri; + ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * device, bri); +} + +uint8_t ExsSyncState(uint8_t device) +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Channel %d Power Want %d, Is %d"), + device, bitRead(Exs.power, device), Exs.dimmer.channel[device].dimm); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Set Channel %d Brightness Want %d, Is %d"), + device, Exs.dimm[device], Exs.dimmer.channel[device].bright_tbl); +#endif + + if (bitRead(Exs.power, device) && + Exs.dimm[device] != Exs.dimmer.channel[device].bright_tbl) { + ExsSetBri(device, Exs.dimm[device]); + } + + if (!Exs.dimm[device]) { + Exs.dimmer.channel[device].dimm = 0; + } else if (Exs.dimmer.channel[device].dimm != bitRead(Exs.power, device)) { + ExsSetPower(device, bitRead(Exs.power, device)); + } +} + +bool ExsSyncState() +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Serial %p, Cmd %d"), ExsSerial, Exs.cmd_status); +#endif + + if (!ExsSerial || Exs.cmd_status != 0) + return false; + + ExsSyncState(0); + ExsSyncState(1); +} + +void ExsDebugState() +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: MCU v%d.%d, c0: On:%d,Dim:%d,Tbl:%d(%d%%), c1: On:%d,Dim:%d,Tbl:%d(%d%%), ChLock: %d"), + Exs.dimmer.version_major, Exs.dimmer.version_minor, + Exs.dimmer.channel[0].on, Exs.dimmer.channel[0].dimm, + Exs.dimmer.channel[0].bright_tbl, + changeUIntScale(Exs.dimmer.channel[0].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.channel[1].on, Exs.dimmer.channel[1].dimm, + Exs.dimmer.channel[1].bright_tbl, + changeUIntScale(Exs.dimmer.channel[1].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.gate_lock); +#endif +} + +void ExsPacketProcess(void) +{ + uint8_t len = Exs.buffer[1]; + uint8_t cmd = Exs.buffer[2]; + + switch (cmd) + { + case EXS_GET_VALUES: +# 294 "S:/Development/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" + if (len > 9) + { + Exs.dimmer.version_major = Exs.buffer[3]; + Exs.dimmer.version_minor = Exs.buffer[4]; + + + Exs.dimmer.channel[0].on = Exs.buffer[6]; + Exs.dimmer.channel[0].dimm = Exs.buffer[6]; + Exs.dimmer.channel[0].bright_tbl = Exs.buffer[7]; + + + Exs.dimmer.channel[1].on = Exs.buffer[9]; + Exs.dimmer.channel[1].dimm = Exs.buffer[9]; + Exs.dimmer.channel[1].bright_tbl = Exs.buffer[10]; + + Exs.dimmer.gate_lock = Exs.buffer[11]; + } + else +# 327 "S:/Development/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" + { + Exs.dimmer.version_major = 1; + Exs.dimmer.version_minor = 0; + + + Exs.dimmer.channel[0].on = Exs.buffer[4] - 48; + Exs.dimmer.channel[0].dimm = Exs.buffer[4] - 48; + Exs.dimmer.channel[0].bright_tbl = Exs.buffer[5] - 48; + + + Exs.dimmer.channel[1].on = Exs.buffer[7] - 48; + Exs.dimmer.channel[1].dimm = Exs.buffer[7] - 48; + Exs.dimmer.channel[1].bright_tbl = Exs.buffer[8] - 48; + + Exs.dimmer.gate_lock = Exs.buffer[9] - 48; + } + + ExsDebugState(); + ExsSyncState(); + ExsDebugState(); + break; + default: + break; + } +} + + + +bool ExsModuleSelected(void) +{ + Settings.light_correction = 0; + Settings.flag.mqtt_serial = 0; + Settings.flag3.pwm_multi_channels = 1; + SetSeriallog(LOG_LEVEL_NONE); + + devices_present = +2; + light_type = LT_SERIAL2; + return true; +} + +bool ExsSetChannels(void) +{ +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: SetChannels: \"")); + for (int i = 0; i < XdrvMailbox.data_len; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, ((uint8_t *)XdrvMailbox.data)[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + Exs.dimm[0] = ((uint8_t *)XdrvMailbox.data)[0]; + Exs.dimm[1] = ((uint8_t *)XdrvMailbox.data)[1]; + return ExsSyncState(); +} + +bool ExsSetPower(void) +{ + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Set Power, Device %d, Power 0x%02x"), + active_device, XdrvMailbox.index); + + Exs.power = XdrvMailbox.index; + return ExsSyncState(); +} + +void EsxMcuStart(void) +{ + int retries = 3; + +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Request MCU configuration, PIN %d to Low"), pin[GPIO_EXS_ENABLE]); +#endif + + pinMode(pin[GPIO_EXS_ENABLE], OUTPUT); + digitalWrite(pin[GPIO_EXS_ENABLE], LOW); + + delay(1); + + while (ExsSerial->available()) + { + + ExsSerial->read(); + } +} + +void ExsInit(void) +{ +#ifdef EXS_DEBUG + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Starting Tx %d Rx %d"), pin[GPIO_TXD], pin[GPIO_RXD]); +#endif + + Exs.buffer = (uint8_t *)malloc(EXS_BUFFER_SIZE); + if (Exs.buffer != nullptr) + { + ExsSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); + if (ExsSerial->begin(9600)) + { + if (ExsSerial->hardwareSerial()) + { + ClaimSerial(); + } + ExsSerial->flush(); + EsxMcuStart(); + ExsSendCmd(EXS_CH_LOCK, 0); + ExsSendCmd(EXS_GET_VALUES, 0); + } + } +} + +void ExsSerialInput(void) +{ + while (ExsSerial->available()) + { + yield(); + uint8_t serial_in_byte = ExsSerial->read(); + + AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Serial In Byte 0x%02x"), serial_in_byte); + + if (Exs.cmd_status == 0 && + serial_in_byte == 0x7B) + { + Exs.cmd_status = 1; + Exs.byte_counter = 0; + } + else if (Exs.byte_counter >= EXS_BUFFER_SIZE) + { + Exs.cmd_status = 0; + } + else if (Exs.cmd_status == 1) + { + Exs.buffer[Exs.byte_counter++] = serial_in_byte; + + if (Exs.byte_counter > 2 && Exs.byte_counter == Exs.buffer[1] + 2) + { + uint8_t crc = crc8(&Exs.buffer[2], Exs.buffer[1]); + + + Exs.cmd_status = 0; + +#ifdef EXS_DEBUG + snprintf_P(log_data, sizeof(log_data), PSTR("EXS: RX Packet: \"")); + for (uint32_t i = 0; i < Exs.byte_counter; i++) + { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Exs.buffer[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\", CRC: 0x%02x"), log_data, crc); + AddLog(LOG_LEVEL_DEBUG_MORE); +#endif + + if (Exs.buffer[0] == crc) + { + ExsSerial->write(0xFF); + ExsPacketProcess(); + } + else + { + ExsSerial->write(0x00); + } + + } + } + } +} + + + + + +#ifdef EXS_MCU_CMNDS + +#define D_PRFX_EXS "Exs" +#define D_CMND_EXS_DIMM "Dimm" +#define D_CMND_EXS_DIMM_TBL "DimmTbl" +#define D_CMND_EXS_DIMM_VAL "DimmVal" +#define D_CMND_EXS_DIMMS "Dimms" +#define D_CMND_EXS_CH_LOCK "ChLock" +#define D_CMND_EXS_STATE "State" + +const char kExsCommands[] PROGMEM = D_PRFX_EXS "|" + D_CMND_EXS_DIMM "|" D_CMND_EXS_DIMM_TBL "|" D_CMND_EXS_DIMM_VAL "|" + D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" + D_CMND_EXS_STATE; + +void (* const ExsCommand[])(void) PROGMEM = { + &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, + &CmndExsDimms, &CmndExsChLock, + &CmndExsState }; + +void CmndExsDimm(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1)) { + ExsSendCmd(EXS_DIMM_1_ON + 0x10 * (XdrvMailbox.index - 1) + + XdrvMailbox.payload ^ 1, 0); + } + CmndExsState(); +} + +void CmndExsDimmTbl(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { + ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * (XdrvMailbox.index - 1), + XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsDimmVal(void) +{ + if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && + (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { + ExsSendCmd(EXS_DIMM_1_VAL + 0x10 * (XdrvMailbox.index - 1), + XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsDimms(void) +{ + if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { + ExsSendCmd(EXS_DIMMS_ON + XdrvMailbox.payload ^ 1, 0); + } + CmndExsState(); +} + +void CmndExsChLock(void) +{ + if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { + ExsSendCmd(EXS_CH_LOCK, XdrvMailbox.payload); + } + CmndExsState(); +} + +void CmndExsState(void) +{ + ExsSendCmd(EXS_GET_VALUES, 0); + + + uint32_t snd_time = millis(); + while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && + (!ExsSerial->available())) + ; + ExsSerialInput(); + + Response_P(PSTR("{\"" D_CMND_EXS_STATE "\":{")); + ResponseAppend_P(PSTR("\"McuVersion\":\"%d.%d\"," + "\"Channels\":["), + Exs.dimmer.version_major, Exs.dimmer.version_minor); + + for (uint32_t i = 0; i < 2; i++) { + if (i != 0) { + ResponseAppend_P(PSTR(",")); + } + ResponseAppend_P(PSTR("{\"On\":\"%d\"," + "\"BrightProz\":\"%d\"," + "\"BrightTab\":\"%d\"," + "\"Dimm\":\"%d\"}"), + Exs.dimmer.channel[i].on, + changeUIntScale(Exs.dimmer.channel[i].bright_tbl, 0, 255, 0, 100), + Exs.dimmer.channel[i].bright_tbl, + Exs.dimmer.channel[i].dimm); + } + ResponseAppend_P(PSTR("],")); + ResponseAppend_P(PSTR("\"GateLock\":\"%d\""), Exs.dimmer.gate_lock); + ResponseJsonEndEnd(); +} + +#endif + + + + + +bool Xdrv30(uint8_t function) +{ + bool result = false; + + if (EXS_DIMMER == my_module_type) + { + switch (function) + { + case FUNC_LOOP: + if (ExsSerial) + ExsSerialInput(); + break; + case FUNC_MODULE_INIT: + result = ExsModuleSelected(); + break; + case FUNC_INIT: + ExsInit(); + break; + case FUNC_SET_DEVICE_POWER: + result = ExsSetPower(); + break; + case FUNC_SET_CHANNELS: + result = ExsSetChannels(); + break; +#ifdef EXS_MCU_CMNDS + case FUNC_COMMAND: + result = DecodeCommand(kExsCommands, ExsCommand); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_31_tasmota_slave.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_31_tasmota_slave.ino" +#ifdef USE_TASMOTA_SLAVE + + + + +#define XDRV_31 31 + +#define CONST_STK_CRC_EOP 0x20 + +#define CMND_STK_GET_SYNC 0x30 +#define CMND_STK_SET_DEVICE 0x42 +#define CMND_STK_SET_DEVICE_EXT 0x45 +#define CMND_STK_ENTER_PROGMODE 0x50 +#define CMND_STK_LEAVE_PROGMODE 0x51 +#define CMND_STK_LOAD_ADDRESS 0x55 +#define CMND_STK_PROG_PAGE 0x64 + + + + + +#define CMND_START 0xFC +#define CMND_END 0xFD + +#define CMND_FEATURES 0x01 +#define CMND_JSON 0x02 +#define CMND_FUNC_EVERY_SECOND 0x03 +#define CMND_FUNC_EVERY_100_MSECOND 0x04 +#define CMND_SLAVE_SEND 0x05 +#define CMND_PUBLISH_TELE 0x06 +#define CMND_EXECUTE_CMND 0x07 + +#define PARAM_DATA_START 0xFE +#define PARAM_DATA_END 0xFF + +#include + + + + + +class SimpleHexParse { + public: + SimpleHexParse(void); + uint8_t parseLine(char *hexline); + uint8_t ptr_l = 0; + uint8_t ptr_h = 0; + bool PageIsReady = false; + bool firstrun = true; + bool EndOfFile = false; + uint8_t FlashPage[128]; + uint8_t FlashPageIdx = 0; + uint8_t layoverBuffer[16]; + uint8_t layoverIdx = 0; + uint8_t getByte(char *hexline, uint8_t idx); +}; + +SimpleHexParse::SimpleHexParse(void) +{ + +} + +uint8_t SimpleHexParse::parseLine(char *hexline) +{ + if (layoverIdx) { + memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx); + FlashPageIdx = layoverIdx; + layoverIdx = 0; + } + uint8_t len = getByte(hexline, 1); + uint8_t addr_h = getByte(hexline, 2); + uint8_t addr_l = getByte(hexline, 3); + uint8_t rectype = getByte(hexline, 4); + for (uint8_t idx = 0; idx < len; idx++) { + if (FlashPageIdx < 128) { + FlashPage[FlashPageIdx] = getByte(hexline, idx+5); + FlashPageIdx++; + } else { + layoverBuffer[layoverIdx] = getByte(hexline, idx+5); + layoverIdx++; + } + } + if (1 == rectype) { + EndOfFile = true; + while (FlashPageIdx < 128) { + FlashPage[FlashPageIdx] = 0xFF; + FlashPageIdx++; + } + } + if (FlashPageIdx == 128) { + if (firstrun) { + firstrun = false; + } else { + ptr_l += 0x40; + if (ptr_l == 0) { + ptr_l = 0; + ptr_h++; + } + } + firstrun = false; + PageIsReady = true; + } + return 0; +} + +uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) +{ + char buff[3]; + buff[3] = '\0'; + memcpy(&buff, &hexline[(idx*2)-1], 2); + return strtol(buff, 0, 16); +} + + + + + +struct TSLAVE { + uint32_t spi_hex_size = 0; + uint32_t spi_sector_counter = 0; + uint8_t spi_sector_cursor = 0; + uint8_t inverted = LOW; + bool type = false; + bool flashing = false; + bool SerialEnabled = false; + uint8_t waitstate = 0; + bool unsupported = false; +} TSlave; + +typedef union { + uint32_t data; + struct { + uint32_t func_json_append : 1; + uint32_t func_every_second : 1; + uint32_t func_every_100_msecond : 1; + uint32_t func_slave_send : 1; + uint32_t spare4 : 1; + uint32_t spare5 : 1; + uint32_t spare6 : 1; + uint32_t spare7 : 1; + uint32_t spare8 : 1; + uint32_t spare9 : 1; + uint32_t spare10 : 1; + uint32_t spare11 : 1; + uint32_t spare12 : 1; + uint32_t spare13 : 1; + uint32_t spare14 : 1; + uint32_t spare15 : 1; + uint32_t spare16 : 1; + uint32_t spare17 : 1; + uint32_t spare18 : 1; + uint32_t spare19 : 1; + uint32_t spare20 : 1; + uint32_t spare21 : 1; + uint32_t spare22 : 1; + uint32_t spare23 : 1; + uint32_t spare24 : 1; + uint32_t spare25 : 1; + uint32_t spare26 : 1; + uint32_t spare27 : 1; + uint32_t spare28 : 1; + uint32_t spare29 : 1; + uint32_t spare30 : 1; + uint32_t spare31 : 1; + }; +} TSlaveFeatureCfg; + + + + + + +struct TSLAVE_FEATURES { + uint32_t features_version; + TSlaveFeatureCfg features; +} TSlaveSettings; + +struct TSLAVE_COMMAND { + uint8_t command; + uint8_t parameter; + uint8_t unused2; + uint8_t unused3; +} TSlaveCommand; + +TasmotaSerial *TasmotaSlave_Serial; + +uint32_t TasmotaSlave_FlashStart(void) +{ + return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; +} + +uint8_t TasmotaSlave_UpdateInit(void) +{ + TSlave.spi_hex_size = 0; + TSlave.spi_sector_counter = TasmotaSlave_FlashStart(); + TSlave.spi_sector_cursor = 0; + return 0; +} + +void TasmotaSlave_Reset(void) +{ + if (TSlave.SerialEnabled) { + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); + delay(1); + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], TSlave.inverted); + delay(1); + digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); + delay(5); + } +} + +uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout) +{ + int timer = 0; + while (timer < timeout) { + if (TasmotaSlave_Serial->available() >= dataCount) { + return 1; + } + delay(1); + timer++; + } + return 0; +} + +uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count) +{ + TasmotaSlave_Serial->write(bytes, count); + TasmotaSlave_waitForSerialData(2, 250); + uint8_t sync = TasmotaSlave_Serial->read(); + uint8_t ok = TasmotaSlave_Serial->read(); + if ((sync == 0x14) && (ok == 0x10)) { + return 1; + } + return 0; +} + +uint8_t TasmotaSlave_execCmd(uint8_t cmd) +{ + uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP }; + return TasmotaSlave_sendBytes(bytes, 2); +} + +uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count) +{ + uint8_t bytes[32]; + bytes[0] = cmd; + int i = 0; + while (i < count) { + bytes[i + 1] = params[i]; + i++; + } + bytes[i + 1] = CONST_STK_CRC_EOP; + return TasmotaSlave_sendBytes(bytes, i + 2); +} + +uint8_t TasmotaSlave_exitProgMode(void) +{ + return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); +} + +uint8_t TasmotaSlave_SetupFlash(void) +{ + uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; + uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00}; + TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_FLASH_SPEED); + if (TasmotaSlave_Serial->hardwareSerial()) { + ClaimSerial(); + } + + TasmotaSlave_Reset(); + + uint8_t timeout = 0; + uint8_t no_error = 0; + while (50 > timeout) { + if (TasmotaSlave_execCmd(CMND_STK_GET_SYNC)) { + timeout = 200; + no_error = 1; + } + timeout++; + delay(1); + } + if (no_error) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Found bootloader")); + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Bootloader could not be found")); + } + if (no_error) { + if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (1)")); + } + } + if (no_error) { + if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (2)")); + } + } + if (no_error) { + if (TasmotaSlave_execCmd(CMND_STK_ENTER_PROGMODE)) { + } else { + no_error = 0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Failed to put bootloader into programming mode")); + } + } + return no_error; +} + +uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo) +{ + uint8_t params[] = { adrLo, adrHi }; + return TasmotaSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); +} + +void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) +{ + uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; + TasmotaSlave_loadAddress(addr_h, addr_l); + TasmotaSlave_Serial->write(Header, 4); + for (int i = 0; i < 128; i++) { + TasmotaSlave_Serial->write(data[i]); + } + TasmotaSlave_Serial->write(CONST_STK_CRC_EOP); + TasmotaSlave_waitForSerialData(2, 250); + TasmotaSlave_Serial->read(); + TasmotaSlave_Serial->read(); +} + +void TasmotaSlave_Flash(void) +{ + bool reading = true; + uint32_t read = 0; + uint32_t processed = 0; + char thishexline[50]; + uint8_t position = 0; + char* flash_buffer; + + SimpleHexParse hexParse = SimpleHexParse(); + + if (!TasmotaSlave_SetupFlash()) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flashing aborted!")); + TSlave.flashing = false; + restart_flag = 2; + return; + } + + flash_buffer = new char[SPI_FLASH_SEC_SIZE]; + uint32_t flash_start = TasmotaSlave_FlashStart() * SPI_FLASH_SEC_SIZE; + while (reading) { + ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); + read = read + SPI_FLASH_SEC_SIZE; + if (read >= TSlave.spi_hex_size) { + reading = false; + } + for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) { + processed++; + if ((processed <= TSlave.spi_hex_size) && (!hexParse.EndOfFile)) { + if (':' == flash_buffer[ca]) { + position = 0; + } + if (0x0D == flash_buffer[ca]) { + thishexline[position] = 0; + hexParse.parseLine(thishexline); + if (hexParse.PageIsReady) { + TasmotaSlave_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage); + hexParse.PageIsReady = false; + hexParse.FlashPageIdx = 0; + } + } else { + if (0x0A != flash_buffer[ca]) { + thishexline[position] = flash_buffer[ca]; + position++; + } + } + } + } + } + TasmotaSlave_exitProgMode(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flash done!")); + TSlave.flashing = false; + restart_flag = 2; +} + +void TasmotaSlave_SetFlagFlashing(bool value) +{ + TSlave.flashing = value; +} + +bool TasmotaSlave_GetFlagFlashing(void) +{ + return TSlave.flashing; +} + +void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size) +{ + if (0 == TSlave.spi_sector_cursor) { + ESP.flashEraseSector(TSlave.spi_sector_counter); + } + TSlave.spi_sector_cursor++; + ESP.flashWrite((TSlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TSlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size); + TSlave.spi_hex_size = TSlave.spi_hex_size + size; + if (2 == TSlave.spi_sector_cursor) { + TSlave.spi_sector_cursor = 0; + TSlave.spi_sector_counter++; + } +} + +void TasmotaSlave_Init(void) +{ + if (TSlave.type) { + return; + } + if (10 > TSlave.waitstate) { + TSlave.waitstate++; + return; + } + if (!TSlave.SerialEnabled) { + if ((pin[GPIO_TASMOTASLAVE_RXD] < 99) && (pin[GPIO_TASMOTASLAVE_TXD] < 99) && + ((pin[GPIO_TASMOTASLAVE_RST] < 99) || (pin[GPIO_TASMOTASLAVE_RST_INV] < 99))) { + TasmotaSlave_Serial = new TasmotaSerial(pin[GPIO_TASMOTASLAVE_RXD], pin[GPIO_TASMOTASLAVE_TXD], 1, 0, 200); + if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) { + if (TasmotaSlave_Serial->hardwareSerial()) { + ClaimSerial(); + } + TasmotaSlave_Serial->setTimeout(50); + if (pin[GPIO_TASMOTASLAVE_RST_INV] < 99) { + pin[GPIO_TASMOTASLAVE_RST] = pin[GPIO_TASMOTASLAVE_RST_INV]; + pin[GPIO_TASMOTASLAVE_RST_INV] = 99; + TSlave.inverted = HIGH; + } + pinMode(pin[GPIO_TASMOTASLAVE_RST], OUTPUT); + TSlave.SerialEnabled = true; + TasmotaSlave_Reset(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Enabled")); + } + } + } + if (TSlave.SerialEnabled) { + TasmotaSlave_sendCmnd(CMND_FEATURES, 0); + char buffer[32]; + TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); + uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); + memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings)); + if (20191129 == TSlaveSettings.features_version) { + TSlave.type = true; + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version); + } else { + if ((!TSlave.unsupported) && (TSlaveSettings.features_version > 0)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u not supported!"), TSlaveSettings.features_version); + TSlave.unsupported = true; + } + } + } +} + +void TasmotaSlave_Show(void) +{ + if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { + char buffer[100]; + TasmotaSlave_sendCmnd(CMND_JSON, 0); + TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); + uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1); + buffer[len] = '\0'; + ResponseAppend_P(PSTR(",\"TasmotaSlave\":%s"), buffer); + } +} + +void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param) +{ + TSlaveCommand.command = cmnd; + TSlaveCommand.parameter = param; + char buffer[sizeof(TSlaveCommand)+2]; + buffer[0] = CMND_START; + memcpy(&buffer[1], &TSlaveCommand, sizeof(TSlaveCommand)); + buffer[sizeof(TSlaveCommand)+1] = CMND_END; + for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { + TasmotaSlave_Serial->write(buffer[ca]); + } +} + +#define D_PRFX_SLAVE "Slave" +#define D_CMND_SLAVE_RESET "Reset" +#define D_CMND_SLAVE_SEND "Send" + +const char kTasmotaSlaveCommands[] PROGMEM = D_PRFX_SLAVE "|" + D_CMND_SLAVE_RESET "|" D_CMND_SLAVE_SEND; + +void (* const TasmotaSlaveCommand[])(void) PROGMEM = { + &CmndTasmotaSlaveReset, &CmndTasmotaSlaveSend }; + +void CmndTasmotaSlaveReset(void) +{ + TasmotaSlave_Reset(); + TSlave.type = false; + TSlave.waitstate = 7; + TSlave.unsupported = false; + ResponseCmndDone(); +} + +void CmndTasmotaSlaveSend(void) +{ + if (0 < XdrvMailbox.data_len) { + TasmotaSlave_sendCmnd(CMND_SLAVE_SEND, XdrvMailbox.data_len); + TasmotaSlave_Serial->write(char(PARAM_DATA_START)); + for (uint8_t idx = 0; idx < XdrvMailbox.data_len; idx++) { + TasmotaSlave_Serial->write(XdrvMailbox.data[idx]); + } + TasmotaSlave_Serial->write(char(PARAM_DATA_END)); + } + ResponseCmndDone(); +} + +void TasmotaSlave_ProcessIn(void) +{ + uint8_t cmnd = TasmotaSlave_Serial->read(); + switch (cmnd) { + case CMND_START: + TasmotaSlave_waitForSerialData(sizeof(TSlaveCommand),50); + uint8_t buffer[sizeof(TSlaveCommand)]; + for (uint8_t idx = 0; idx < sizeof(TSlaveCommand); idx++) { + buffer[idx] = TasmotaSlave_Serial->read(); + } + TasmotaSlave_Serial->read(); + memcpy(&TSlaveCommand, &buffer, sizeof(TSlaveCommand)); + char inbuf[TSlaveCommand.parameter+1]; + TasmotaSlave_waitForSerialData(TSlaveCommand.parameter, 50); + TasmotaSlave_Serial->read(); + for (uint8_t idx = 0; idx < TSlaveCommand.parameter; idx++) { + inbuf[idx] = TasmotaSlave_Serial->read(); + } + TasmotaSlave_Serial->read(); + inbuf[TSlaveCommand.parameter] = '\0'; + + if (CMND_PUBLISH_TELE == TSlaveCommand.command) { + Response_P(PSTR("{\"TasmotaSlave\":")); + ResponseAppend_P("%s", inbuf); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + XdrvRulesProcess(); + } + if (CMND_EXECUTE_CMND == TSlaveCommand.command) { + ExecuteCommand(inbuf, SRC_IGNORE); + } + break; + default: + break; + } +} + + + + + + +bool Xdrv31(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_100_MSECOND: + if (TSlave.type) { + if (TasmotaSlave_Serial->available()) { + TasmotaSlave_ProcessIn(); + } + if (TSlaveSettings.features.func_every_100_msecond) { + TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0); + } + } + break; + case FUNC_EVERY_SECOND: + if ((TSlave.type) && (TSlaveSettings.features.func_every_second)) { + TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_SECOND, 0); + } + TasmotaSlave_Init(); + break; + case FUNC_JSON_APPEND: + if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { + TasmotaSlave_Show(); + } + break; + case FUNC_COMMAND: + result = DecodeCommand(kTasmotaSlaveCommands, TasmotaSlaveCommand); + break; + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_32_hotplug.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_32_hotplug.ino" +#ifdef USE_HOTPLUG + + + + + + + +#define XDRV_32 32 + +const uint32_t HOTPLUG_MAX = 254; + +const char kHotPlugCommands[] PROGMEM = "|" + D_CMND_HOTPLUG; + +void (* const HotPlugCommand[])(void) PROGMEM = { + &CmndHotPlugTime }; + +struct { + + bool enabled = false; + uint8_t timeout = 0; +} Hotplug; + +void HotPlugInit(void) +{ + + if (Settings.hotplug_scan == 0xFF) { Settings.hotplug_scan = 0; } + if (Settings.hotplug_scan != 0) { + Hotplug.enabled = true; + Hotplug.timeout = 1; + } else + Hotplug.enabled = false; +} + +void HotPlugEverySecond(void) +{ + if (Hotplug.enabled) { + if (Hotplug.timeout == 0) { + XsnsCall(FUNC_HOTPLUG_SCAN); + Hotplug.timeout = Settings.hotplug_scan; + } + Hotplug.timeout--; + } +} + + + + + +void CmndHotPlugTime(void) +{ + if (XdrvMailbox.payload <= HOTPLUG_MAX) { + Settings.hotplug_scan = XdrvMailbox.payload; + HotPlugInit(); + } + ResponseCmndNumber(Settings.hotplug_scan); +} + + + + + +bool Xdrv32(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_SECOND: + HotPlugEverySecond(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kHotPlugCommands, HotPlugCommand); + break; + case FUNC_PRE_INIT: + HotPlugInit(); + break; + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_33_nrf24l01.ino" +# 30 "S:/Development/Tasmota/tasmota/xdrv_33_nrf24l01.ino" +#ifdef USE_SPI +#ifdef USE_NRF24 + + + + + + + +#define XDRV_33 33 + +#define MOSI 13 +#define MISO 12 +#define SCK 14 + +#include +#include + +const char NRF24type[] PROGMEM = "NRF24"; + +const char HTTP_NRF24[] PROGMEM = + "{s}%sL01%c: " "{m}started{e}"; + +struct { + uint8_t chipType = 0; +} NRF24; + + + +RF24 NRF24radio; + +bool NRF24initRadio() +{ + NRF24radio.begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_DC]); + NRF24radio.powerUp(); + + if(NRF24radio.isChipConnected()){ + DEBUG_DRIVER_LOG(PSTR("NRF24 chip connected")); + return true; + } + DEBUG_DRIVER_LOG(PSTR("NRF24 chip NOT !!!! connected")); + return false; +} + +bool NRF24Detect(void) +{ + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_DC]<99)){ + SPI.pins(SCK,MOSI,MISO,-1); + if(NRF24initRadio()){ + NRF24.chipType = 32; + AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01 initialized")); + if(NRF24radio.isPVariant()){ + NRF24.chipType = 43; + AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01+ detected")); + } + return true; + } + } + return false; +} + + + + + +bool Xdrv33(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + result = NRF24Detect(); + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" +#ifdef USE_I2C +#ifdef USE_WEMOS_MOTOR_V1 +# 45 "S:/Development/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" +#define XDRV_34 34 +#define XI2C_44 44 + +#ifndef WEMOS_MOTOR_V1_ADDR +#define WEMOS_MOTOR_V1_ADDR 0x30 +#endif +#ifndef WEMOS_MOTOR_V1_FREQ +#define WEMOS_MOTOR_V1_FREQ 1000 +#endif + +#define MOTOR_A 0 +#define MOTOR_B 1 + +#define SHORT_BRAKE 0 +#define CCW 1 +#define CW 2 +#define STOP 3 +#define STANDBY 4 + +struct WMOTORV1 { + bool detected = false; + uint8_t motor; +} WMotorV1; + +void WMotorV1Detect(void) +{ + if (I2cSetDevice(WEMOS_MOTOR_V1_ADDR)) { + WMotorV1.detected = true; + I2cSetActiveFound(WEMOS_MOTOR_V1_ADDR, "WEMOS_MOTOR_V1"); + WMotorV1Reset(); + } +} + +void WMotorV1Reset(void) +{ + + WMotorV1SetFrequency(WEMOS_MOTOR_V1_FREQ); +} + +void WMotorV1SetFrequency(uint32_t freq) +{ + Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); + Wire.write(((byte)(freq >> 16)) & (byte)0x0f); + Wire.write((byte)(freq >> 16)); + Wire.write((byte)(freq >> 8)); + Wire.write((byte)freq); + Wire.endTransmission(); + +} + +void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val) +{ + Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); + Wire.write(motor | (byte)0x10); + Wire.write(dir); + + uint16_t _pwm_val = uint16_t(pwm_val * 100); + if (_pwm_val > 10000) { + _pwm_val = 10000; + } + + Wire.write((byte)(_pwm_val >> 8)); + Wire.write((byte)_pwm_val); + Wire.endTransmission(); + +} + +bool WMotorV1Command(void) +{ + uint8_t args_count = 0; + + if (XdrvMailbox.data_len > 0) { + args_count = 1; + } else { + return false; + } + + for (uint32_t idx = 0; idx < XdrvMailbox.data_len; idx++) { + if (' ' == XdrvMailbox.data[idx]) { + XdrvMailbox.data[idx] = ','; + } + if (',' == XdrvMailbox.data[idx]) { + args_count++; + } + } + UpperCase(XdrvMailbox.data, XdrvMailbox.data); + + char *command = strtok(XdrvMailbox.data, ","); + + if (strcmp(command, "RESET") == 0) { + WMotorV1Reset(); + Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"RESET\":\"OK\"}}")); + return true; + } + + if (strcmp(command, "SETMOTOR") == 0) { + if (args_count >= 3) { + + int motor = atoi(strtok(NULL, ",")); + int dir = atoi(strtok(NULL, ",")); + int duty = 100; + if (args_count == 4) { + duty = atoi(strtok(NULL, ",")); + } + + WMotorV1SetMotor(motor, dir, duty); + Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"SETMOTOR\":\"OK\"}}")); + return true; + } + } + return false; +} + + + + + +bool Xdrv34(uint8_t function) +{ + if (!I2cEnabled(XI2C_44)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + WMotorV1Detect(); + } + else if (WMotorV1.detected) { + switch (function) { + case FUNC_COMMAND_DRIVER: + if (XI2C_44 == XdrvMailbox.index) { + result = WMotorV1Command(); + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" +# 22 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" +#ifdef DEBUG_THEO +#ifndef USE_DEBUG_DRIVER +#define USE_DEBUG_DRIVER +#endif +#endif + +#ifdef USE_DEBUG_DRIVER + + + + + + +#define XDRV_99 99 + +#ifndef CPU_LOAD_CHECK +#define CPU_LOAD_CHECK 1 +#endif + + + + + +#define D_CMND_CFGDUMP "CfgDump" +#define D_CMND_CFGPEEK "CfgPeek" +#define D_CMND_CFGPOKE "CfgPoke" +#define D_CMND_CFGSHOW "CfgShow" +#define D_CMND_CFGXOR "CfgXor" +#define D_CMND_CPUCHECK "CpuChk" +#define D_CMND_EXCEPTION "Exception" +#define D_CMND_FLASHDUMP "FlashDump" +#define D_CMND_FLASHMODE "FlashMode" +#define D_CMND_FREEMEM "FreeMem" +#define D_CMND_HELP "Help" +#define D_CMND_RTCDUMP "RtcDump" +#define D_CMND_SETSENSOR "SetSensor" +#define D_CMND_I2CWRITE "I2CWrite" +#define D_CMND_I2CREAD "I2CRead" +#define D_CMND_I2CSTRETCH "I2CStretch" +#define D_CMND_I2CCLOCK "I2CClock" + +const char kDebugCommands[] PROGMEM = "|" + D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" +#ifdef USE_WEBSERVER + D_CMND_CFGXOR "|" +#endif + D_CMND_CPUCHECK "|" +#ifdef DEBUG_THEO + D_CMND_EXCEPTION "|" +#endif + D_CMND_FLASHDUMP "|" D_CMND_FLASHMODE "|" D_CMND_FREEMEM"|" D_CMND_HELP "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|" +#ifdef USE_I2C + D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK +#endif + ; + +void (* const DebugCommand[])(void) PROGMEM = { + &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, +#ifdef USE_WEBSERVER + &CmndCfgXor, +#endif + &CmndCpuCheck, +#ifdef DEBUG_THEO + &CmndException, +#endif + &CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor, +#ifdef USE_I2C + &CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock +#endif + }; + +uint32_t CPU_loops = 0; +uint32_t CPU_last_millis = 0; +uint32_t CPU_last_loop_time = 0; +uint8_t CPU_load_check = 0; +uint8_t CPU_show_freemem = 0; + + + +#ifdef DEBUG_THEO +void ExceptionTest(uint8_t type) +{ +# 145 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" + if (1 == type) { + char svalue[10]; + snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); + } +# 159 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" + if (2 == type) { + while(1) delay(1000); + } +} + +#endif + + + +void CpuLoadLoop(void) +{ + CPU_last_loop_time = millis(); + if (CPU_load_check && CPU_last_millis) { + CPU_loops ++; + if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { +#if defined(F_CPU) && (F_CPU == 160000000L) + int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); + CPU_loops = CPU_loops / CPU_load_check; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); +#else + int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); + CPU_loops = CPU_loops / CPU_load_check; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); +#endif + CPU_last_millis = CPU_last_loop_time; + CPU_loops = 0; + } + } +} + + + +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) + + + +extern "C" { +#include + extern cont_t g_cont; +} + +void DebugFreeMem(void) +{ + register uint32_t *sp asm("a1"); + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); +} + +#else + + + + +extern "C" { +#include + extern cont_t* g_pcont; +} + +void DebugFreeMem(void) +{ + register uint32_t *sp asm("a1"); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); +} + +#endif + + + +void DebugRtcDump(char* parms) +{ + #define CFG_COLS 16 + + uint16_t idx; + uint16_t maxrow; + uint16_t row; + uint16_t col; + char *p; +# 246 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" + uint8_t buffer[768]; + + system_rtc_mem_read(0, (uint32_t*)&buffer, sizeof(buffer)); + + maxrow = ((sizeof(buffer)+CFG_COLS)/CFG_COLS); + + uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; + uint16_t mrow = strtol(p, &p, 10); + + + + if (0 == mrow) { + mrow = 8; + } + if (srow > maxrow) { + srow = maxrow - mrow; + } + if (mrow < (maxrow - srow)) { + maxrow = srow + mrow; + } + + for (row = srow; row < maxrow; row++) { + idx = row * CFG_COLS; + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + for (col = 0; col < CFG_COLS; col++) { + if (!(col%4)) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (col = 0; col < CFG_COLS; col++) { + + + + snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); + AddLog(LOG_LEVEL_INFO); + } +} + + + +void DebugCfgDump(char* parms) +{ + #define CFG_COLS 16 + + uint16_t idx; + uint16_t maxrow; + uint16_t row; + uint16_t col; + char *p; + + uint8_t *buffer = (uint8_t *) &Settings; + maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); + + uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; + uint16_t mrow = strtol(p, &p, 10); + + + + if (0 == mrow) { + mrow = 8; + } + if (srow > maxrow) { + srow = maxrow - mrow; + } + if (mrow < (maxrow - srow)) { + maxrow = srow + mrow; + } + + for (row = srow; row < maxrow; row++) { + idx = row * CFG_COLS; + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); + for (col = 0; col < CFG_COLS; col++) { + if (!(col%4)) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (col = 0; col < CFG_COLS; col++) { + + + + snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); + AddLog(LOG_LEVEL_INFO); + delay(1); + } +} + +void DebugCfgPeek(char* parms) +{ + char *p; + + uint16_t address = strtol(parms, &p, 16); + if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + address = (address >> 2) << 2; + + uint8_t *buffer = (uint8_t *) &Settings; + uint8_t data8 = buffer[address]; + uint16_t data16 = (buffer[address +1] << 8) + buffer[address]; + uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; + + snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); + for (uint32_t i = 0; i < 4; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); + for (uint32_t i = 0; i < 4; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); + AddLog(LOG_LEVEL_INFO); +} + +void DebugCfgPoke(char* parms) +{ + char *p; + + uint16_t address = strtol(parms, &p, 16); + if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + address = (address >> 2) << 2; + + uint32_t data = strtol(p, &p, 16); + + uint8_t *buffer = (uint8_t *) &Settings; + uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; + + uint8_t *nbuffer = (uint8_t *) &data; + for (uint32_t i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } + + uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; + + AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); +} + +void SetFlashMode(uint8_t mode) +{ + uint8_t *_buffer; + uint32_t address; + + address = 0; + _buffer = new uint8_t[FLASH_SECTOR_SIZE]; + + if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { + if (_buffer[2] != mode) { + _buffer[2] = mode; + if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { + ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); + } + } + } + delete[] _buffer; +} + + + + + +void CmndHelp(void) +{ + AddLog_P(LOG_LEVEL_INFO, PSTR("HLP: "), kDebugCommands); + ResponseCmndDone(); +} + +void CmndRtcDump(void) +{ + DebugRtcDump(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgDump(void) +{ + DebugCfgDump(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgPeek(void) +{ + DebugCfgPeek(XdrvMailbox.data); + ResponseCmndDone(); +} + +void CmndCfgPoke(void) +{ + DebugCfgPoke(XdrvMailbox.data); + ResponseCmndDone(); +} + +#ifdef USE_WEBSERVER +void CmndCfgXor(void) +{ + if (XdrvMailbox.data_len > 0) { + Web.config_xor_on_set = XdrvMailbox.payload; + } + ResponseCmndNumber(Web.config_xor_on_set); +} +#endif + +#ifdef DEBUG_THEO +void CmndException(void) +{ + if (XdrvMailbox.data_len > 0) { ExceptionTest(XdrvMailbox.payload); } + ResponseCmndDone(); +} +#endif + +void CmndCpuCheck(void) +{ + if (XdrvMailbox.data_len > 0) { + CPU_load_check = XdrvMailbox.payload; + CPU_last_millis = CPU_last_loop_time; + } + ResponseCmndNumber(CPU_load_check); +} + +void CmndFreemem(void) +{ + if (XdrvMailbox.data_len > 0) { + CPU_show_freemem = XdrvMailbox.payload; + } + ResponseCmndNumber(CPU_show_freemem); +} + +void CmndSetSensor(void) +{ + if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { + if (XdrvMailbox.payload >= 0) { + bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); + if (1 == XdrvMailbox.payload) { + restart_flag = 2; + } + } + Response_P(PSTR("{\"" D_CMND_SETSENSOR "\":")); + XsnsSensorState(); + ResponseJsonEnd(); + } +} + +void CmndFlashMode(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { + SetFlashMode(XdrvMailbox.payload); + } + ResponseCmndNumber(ESP.getFlashChipMode()); +} + +uint32_t DebugSwap32(uint32_t x) { + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} + +void CmndFlashDump(void) +{ + + + + const uint32_t flash_start = 0x40200000; + const uint8_t bytes_per_cols = 0x20; + const uint32_t max = (SPIFFS_END + 5) * SPI_FLASH_SEC_SIZE; + + uint32_t start = flash_start; + uint32_t rows = 8; + + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= (max - bytes_per_cols))) { + start += (XdrvMailbox.payload &0x7FFFFFFC); + + char *p; + uint32_t is_payload = strtol(XdrvMailbox.data, &p, 16); + rows = strtol(p, &p, 10); + if (0 == rows) { rows = 8; } + } + uint32_t end = start + (rows * bytes_per_cols); + if ((end - flash_start) > max) { + end = flash_start + max; + } + + for (uint32_t pos = start; pos < end; pos += bytes_per_cols) { + uint32_t* values = (uint32_t*)(pos); + AddLog_P2(LOG_LEVEL_INFO, PSTR("%06X: %08X %08X %08X %08X %08X %08X %08X %08X"), pos - flash_start, + DebugSwap32(values[0]), DebugSwap32(values[1]), DebugSwap32(values[2]), DebugSwap32(values[3]), + DebugSwap32(values[4]), DebugSwap32(values[5]), DebugSwap32(values[6]), DebugSwap32(values[7])); + } + ResponseCmndDone(); +} + +#ifdef USE_I2C +void CmndI2cWrite(void) +{ + + if (i2c_flg) { + char* parms = XdrvMailbox.data; + uint8_t buffer[100]; + uint32_t index = 0; + + char *p; + char *data = strtok_r(parms, " ,", &p); + while (data != NULL && index < sizeof(buffer)) { + buffer[index++] = strtol(data, nullptr, 16); + data = strtok_r(nullptr, " ,", &p); + } + + if (index > 1) { + AddLogBuffer(LOG_LEVEL_INFO, buffer, index); + + Wire.beginTransmission(buffer[0]); + for (uint32_t i = 1; i < index; i++) { + Wire.write(buffer[i]); + } + int result = Wire.endTransmission(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: Result %d"), result); + } + } + ResponseCmndDone(); +} + +void CmndI2cRead(void) +{ + + if (i2c_flg) { + char* parms = XdrvMailbox.data; + uint8_t buffer[100]; + uint32_t index = 0; + + char *p; + char *data = strtok_r(parms, " ,", &p); + while (data != NULL && index < sizeof(buffer)) { + buffer[index++] = strtol(data, nullptr, 16); + data = strtok_r(nullptr, " ,", &p); + } + + if (index > 0) { + uint8_t size = 1; + if (index > 1) { + size = buffer[1]; + } + Wire.requestFrom(buffer[0], size); + index = 0; + while (Wire.available() && index < sizeof(buffer)) { + buffer[index++] = Wire.read(); + } + if (index > 0) { + AddLogBuffer(LOG_LEVEL_INFO, buffer, index); + } + } + } + ResponseCmndDone(); +} + +void CmndI2cStretch(void) +{ + if (i2c_flg && (XdrvMailbox.payload > 0)) { + Wire.setClockStretchLimit(XdrvMailbox.payload); + } + ResponseCmndDone(); +} + +void CmndI2cClock(void) +{ + if (i2c_flg && (XdrvMailbox.payload > 0)) { + Wire.setClock(XdrvMailbox.payload); + } + ResponseCmndDone(); +} +#endif + + + + + +bool Xdrv99(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + CpuLoadLoop(); + break; + case FUNC_FREE_MEM: + if (CPU_show_freemem) { DebugFreeMem(); } + break; + case FUNC_PRE_INIT: + CPU_last_millis = millis(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kDebugCommands, DebugCommand); + break; + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xdrv_interface.ino" +# 20 "S:/Development/Tasmota/tasmota/xdrv_interface.ino" +#ifdef XFUNC_PTR_IN_ROM +bool (* const xdrv_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xdrv_func_ptr[])(uint8_t) = { +#endif + +#ifdef XDRV_01 + &Xdrv01, +#endif + +#ifdef XDRV_02 + &Xdrv02, +#endif + +#ifdef XDRV_03 + &Xdrv03, +#endif + +#ifdef XDRV_04 + &Xdrv04, +#endif + +#ifdef XDRV_05 + &Xdrv05, +#endif + +#ifdef XDRV_06 + &Xdrv06, +#endif + +#ifdef XDRV_07 + &Xdrv07, +#endif + +#ifdef XDRV_08 + &Xdrv08, +#endif + +#ifdef XDRV_09 + &Xdrv09, +#endif + +#ifdef XDRV_10 + &Xdrv10, +#endif + +#ifdef XDRV_11 + &Xdrv11, +#endif + +#ifdef XDRV_12 + &Xdrv12, +#endif + +#ifdef XDRV_13 + &Xdrv13, +#endif + +#ifdef XDRV_14 + &Xdrv14, +#endif + +#ifdef XDRV_15 + &Xdrv15, +#endif + +#ifdef XDRV_16 + &Xdrv16, +#endif + +#ifdef XDRV_17 + &Xdrv17, +#endif + +#ifdef XDRV_18 + &Xdrv18, +#endif + +#ifdef XDRV_19 + &Xdrv19, +#endif + +#ifdef XDRV_20 + &Xdrv20, +#endif + +#ifdef XDRV_21 + &Xdrv21, +#endif + +#ifdef XDRV_22 + &Xdrv22, +#endif + +#ifdef XDRV_23 + &Xdrv23, +#endif + +#ifdef XDRV_24 + &Xdrv24, +#endif + +#ifdef XDRV_25 + &Xdrv25, +#endif + +#ifdef XDRV_26 + &Xdrv26, +#endif + +#ifdef XDRV_27 + &Xdrv27, +#endif + +#ifdef XDRV_28 + &Xdrv28, +#endif + +#ifdef XDRV_29 + &Xdrv29, +#endif + +#ifdef XDRV_30 + &Xdrv30, +#endif + +#ifdef XDRV_31 + &Xdrv31, +#endif + +#ifdef XDRV_32 + &Xdrv32, +#endif + +#ifdef XDRV_33 + &Xdrv33, +#endif + +#ifdef XDRV_34 + &Xdrv34, +#endif + +#ifdef XDRV_35 + &Xdrv35, +#endif + +#ifdef XDRV_36 + &Xdrv36, +#endif + +#ifdef XDRV_37 + &Xdrv37, +#endif + +#ifdef XDRV_38 + &Xdrv38, +#endif + +#ifdef XDRV_39 + &Xdrv39, +#endif + +#ifdef XDRV_40 + &Xdrv40, +#endif + +#ifdef XDRV_41 + &Xdrv41, +#endif + +#ifdef XDRV_42 + &Xdrv42, +#endif + +#ifdef XDRV_43 + &Xdrv43, +#endif + +#ifdef XDRV_44 + &Xdrv44, +#endif + +#ifdef XDRV_45 + &Xdrv45, +#endif + +#ifdef XDRV_46 + &Xdrv46, +#endif + +#ifdef XDRV_47 + &Xdrv47, +#endif + +#ifdef XDRV_48 + &Xdrv48, +#endif + +#ifdef XDRV_49 + &Xdrv49, +#endif + +#ifdef XDRV_50 + &Xdrv50, +#endif + +#ifdef XDRV_51 + &Xdrv51, +#endif + +#ifdef XDRV_52 + &Xdrv52, +#endif + +#ifdef XDRV_53 + &Xdrv53, +#endif + +#ifdef XDRV_54 + &Xdrv54, +#endif + +#ifdef XDRV_55 + &Xdrv55, +#endif + +#ifdef XDRV_56 + &Xdrv56, +#endif + +#ifdef XDRV_57 + &Xdrv57, +#endif + +#ifdef XDRV_58 + &Xdrv58, +#endif + +#ifdef XDRV_59 + &Xdrv59, +#endif + +#ifdef XDRV_60 + &Xdrv60, +#endif + +#ifdef XDRV_61 + &Xdrv61, +#endif + +#ifdef XDRV_62 + &Xdrv62, +#endif + +#ifdef XDRV_63 + &Xdrv63, +#endif + +#ifdef XDRV_64 + &Xdrv64, +#endif + +#ifdef XDRV_65 + &Xdrv65, +#endif + +#ifdef XDRV_66 + &Xdrv66, +#endif + +#ifdef XDRV_67 + &Xdrv67, +#endif + +#ifdef XDRV_68 + &Xdrv68, +#endif + +#ifdef XDRV_69 + &Xdrv69, +#endif + +#ifdef XDRV_70 + &Xdrv70, +#endif + +#ifdef XDRV_71 + &Xdrv71, +#endif + +#ifdef XDRV_72 + &Xdrv72, +#endif + +#ifdef XDRV_73 + &Xdrv73, +#endif + +#ifdef XDRV_74 + &Xdrv74, +#endif + +#ifdef XDRV_75 + &Xdrv75, +#endif + +#ifdef XDRV_76 + &Xdrv76, +#endif + +#ifdef XDRV_77 + &Xdrv77, +#endif + +#ifdef XDRV_78 + &Xdrv78, +#endif + +#ifdef XDRV_79 + &Xdrv79, +#endif + +#ifdef XDRV_80 + &Xdrv80, +#endif + +#ifdef XDRV_81 + &Xdrv81, +#endif + +#ifdef XDRV_82 + &Xdrv82, +#endif + +#ifdef XDRV_83 + &Xdrv83, +#endif + +#ifdef XDRV_84 + &Xdrv84, +#endif + +#ifdef XDRV_85 + &Xdrv85, +#endif + +#ifdef XDRV_86 + &Xdrv86, +#endif + +#ifdef XDRV_87 + &Xdrv87, +#endif + +#ifdef XDRV_88 + &Xdrv88, +#endif + +#ifdef XDRV_89 + &Xdrv89, +#endif + +#ifdef XDRV_90 + &Xdrv90, +#endif + +#ifdef XDRV_91 + &Xdrv91, +#endif + +#ifdef XDRV_92 + &Xdrv92, +#endif + +#ifdef XDRV_93 + &Xdrv93, +#endif + +#ifdef XDRV_94 + &Xdrv94, +#endif + +#ifdef XDRV_95 + &Xdrv95, +#endif + +#ifdef XDRV_96 + &Xdrv96, +#endif + +#ifdef XDRV_97 + &Xdrv97, +#endif + +#ifdef XDRV_98 + &Xdrv98, +#endif + +#ifdef XDRV_99 + &Xdrv99 +#endif +}; + +const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); + + + + + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXdrvList[] PROGMEM = { +#else +const uint8_t kXdrvList[] = { +#endif + +#ifdef XDRV_01 + XDRV_01, +#endif + +#ifdef XDRV_02 + XDRV_02, +#endif + +#ifdef XDRV_03 + XDRV_03, +#endif + +#ifdef XDRV_04 + XDRV_04, +#endif + +#ifdef XDRV_05 + XDRV_05, +#endif + +#ifdef XDRV_06 + XDRV_06, +#endif + +#ifdef XDRV_07 + XDRV_07, +#endif + +#ifdef XDRV_08 + XDRV_08, +#endif + +#ifdef XDRV_09 + XDRV_09, +#endif + +#ifdef XDRV_10 + XDRV_10, +#endif + +#ifdef XDRV_11 + XDRV_11, +#endif + +#ifdef XDRV_12 + XDRV_12, +#endif + +#ifdef XDRV_13 + XDRV_13, +#endif + +#ifdef XDRV_14 + XDRV_14, +#endif + +#ifdef XDRV_15 + XDRV_15, +#endif + +#ifdef XDRV_16 + XDRV_16, +#endif + +#ifdef XDRV_17 + XDRV_17, +#endif + +#ifdef XDRV_18 + XDRV_18, +#endif + +#ifdef XDRV_19 + XDRV_19, +#endif + +#ifdef XDRV_20 + XDRV_20, +#endif + +#ifdef XDRV_21 + XDRV_21, +#endif + +#ifdef XDRV_22 + XDRV_22, +#endif + +#ifdef XDRV_23 + XDRV_23, +#endif + +#ifdef XDRV_24 + XDRV_24, +#endif + +#ifdef XDRV_25 + XDRV_25, +#endif + +#ifdef XDRV_26 + XDRV_26, +#endif + +#ifdef XDRV_27 + XDRV_27, +#endif + +#ifdef XDRV_28 + XDRV_28, +#endif + +#ifdef XDRV_29 + XDRV_29, +#endif + +#ifdef XDRV_30 + XDRV_30, +#endif + +#ifdef XDRV_31 + XDRV_31, +#endif + +#ifdef XDRV_32 + XDRV_32, +#endif + +#ifdef XDRV_33 + XDRV_33, +#endif + +#ifdef XDRV_34 + XDRV_34, +#endif + +#ifdef XDRV_35 + XDRV_35, +#endif + +#ifdef XDRV_36 + XDRV_36, +#endif + +#ifdef XDRV_37 + XDRV_37, +#endif + +#ifdef XDRV_38 + XDRV_38, +#endif + +#ifdef XDRV_39 + XDRV_39, +#endif + +#ifdef XDRV_40 + XDRV_40, +#endif + +#ifdef XDRV_41 + XDRV_41, +#endif + +#ifdef XDRV_42 + XDRV_42, +#endif + +#ifdef XDRV_43 + XDRV_43, +#endif + +#ifdef XDRV_44 + XDRV_44, +#endif + +#ifdef XDRV_45 + XDRV_45, +#endif + +#ifdef XDRV_46 + XDRV_46, +#endif + +#ifdef XDRV_47 + XDRV_47, +#endif + +#ifdef XDRV_48 + XDRV_48, +#endif + +#ifdef XDRV_49 + XDRV_49, +#endif + +#ifdef XDRV_50 + XDRV_50, +#endif + +#ifdef XDRV_51 + XDRV_51, +#endif + +#ifdef XDRV_52 + XDRV_52, +#endif + +#ifdef XDRV_53 + XDRV_53, +#endif + +#ifdef XDRV_54 + XDRV_54, +#endif + +#ifdef XDRV_55 + XDRV_55, +#endif + +#ifdef XDRV_56 + XDRV_56, +#endif + +#ifdef XDRV_57 + XDRV_57, +#endif + +#ifdef XDRV_58 + XDRV_58, +#endif + +#ifdef XDRV_59 + XDRV_59, +#endif + +#ifdef XDRV_60 + XDRV_60, +#endif + +#ifdef XDRV_61 + XDRV_61, +#endif + +#ifdef XDRV_62 + XDRV_62, +#endif + +#ifdef XDRV_63 + XDRV_63, +#endif + +#ifdef XDRV_64 + XDRV_64, +#endif + +#ifdef XDRV_65 + XDRV_65, +#endif + +#ifdef XDRV_66 + XDRV_66, +#endif + +#ifdef XDRV_67 + XDRV_67, +#endif + +#ifdef XDRV_68 + XDRV_68, +#endif + +#ifdef XDRV_69 + XDRV_69, +#endif + +#ifdef XDRV_70 + XDRV_70, +#endif + +#ifdef XDRV_71 + XDRV_71, +#endif + +#ifdef XDRV_72 + XDRV_72, +#endif + +#ifdef XDRV_73 + XDRV_73, +#endif + +#ifdef XDRV_74 + XDRV_74, +#endif + +#ifdef XDRV_75 + XDRV_75, +#endif + +#ifdef XDRV_76 + XDRV_76, +#endif + +#ifdef XDRV_77 + XDRV_77, +#endif + +#ifdef XDRV_78 + XDRV_78, +#endif + +#ifdef XDRV_79 + XDRV_79, +#endif + +#ifdef XDRV_80 + XDRV_80, +#endif + +#ifdef XDRV_81 + XDRV_81, +#endif + +#ifdef XDRV_82 + XDRV_82, +#endif + +#ifdef XDRV_83 + XDRV_83, +#endif + +#ifdef XDRV_84 + XDRV_84, +#endif + +#ifdef XDRV_85 + XDRV_85, +#endif + +#ifdef XDRV_86 + XDRV_86, +#endif + +#ifdef XDRV_87 + XDRV_87, +#endif + +#ifdef XDRV_88 + XDRV_88, +#endif + +#ifdef XDRV_89 + XDRV_89, +#endif + +#ifdef XDRV_90 + XDRV_90, +#endif + +#ifdef XDRV_91 + XDRV_91, +#endif + +#ifdef XDRV_92 + XDRV_92, +#endif + +#ifdef XDRV_93 + XDRV_93, +#endif + +#ifdef XDRV_94 + XDRV_94, +#endif + +#ifdef XDRV_95 + XDRV_95, +#endif + +#ifdef XDRV_96 + XDRV_96, +#endif + +#ifdef XDRV_97 + XDRV_97, +#endif + +#ifdef XDRV_98 + XDRV_98, +#endif + +#ifdef XDRV_99 + XDRV_99 +#endif +}; + + + +void XsnsDriverState(void) +{ + ResponseAppend_P(PSTR(",\"Drivers\":\"")); + for (uint32_t i = 0; i < sizeof(kXdrvList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t driverid = pgm_read_byte(kXdrvList + i); +#else + uint32_t driverid = kXdrvList[i]; +#endif + ResponseAppend_P(PSTR("%s%d"), (i) ? "," : "", driverid); + } + ResponseAppend_P(PSTR("\"")); +} + + + +bool XdrvRulesProcess(void) +{ + return XdrvCallDriver(10, FUNC_RULES_PROCESS); +} + +#ifdef USE_DEBUG_DRIVER +void ShowFreeMem(const char *where) +{ + char stemp[30]; + snprintf_P(stemp, sizeof(stemp), where); + XdrvMailbox.data = stemp; + XdrvCall(FUNC_FREE_MEM); +} +#endif + + + + + +bool XdrvCallDriver(uint32_t driver, uint8_t Function) +{ + for (uint32_t x = 0; x < xdrv_present; x++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t listed = pgm_read_byte(kXdrvList + x); +#else + uint32_t listed = kXdrvList[x]; +#endif + if (driver == listed) { + return xdrv_func_ptr[x](Function); + } + } + return false; +} + + + + + +bool XdrvCall(uint8_t Function) +{ + bool result = false; + + DEBUG_TRACE_LOG(PSTR("DRV: %d"), Function); + + for (uint32_t x = 0; x < xdrv_present; x++) { + result = xdrv_func_ptr[x](Function); + + if (result && ((FUNC_COMMAND == Function) || + (FUNC_COMMAND_DRIVER == Function) || + (FUNC_MQTT_DATA == Function) || + (FUNC_RULES_PROCESS == Function) || + (FUNC_BUTTON_PRESSED == Function) || + (FUNC_SERIAL == Function) || + (FUNC_MODULE_INIT == Function) || + (FUNC_SET_CHANNELS == Function) || + (FUNC_PIN_STATE == Function) || + (FUNC_SET_DEVICE_POWER == Function) + )) { + break; + } + } + + return result; +} +# 1 "S:/Development/Tasmota/tasmota/xdsp_01_lcd.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_01_lcd.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_LCD + +#define XDSP_01 1 +#define XI2C_03 3 + +#define LCD_ADDRESS1 0x27 +#define LCD_ADDRESS2 0x3F + +#include +#include + +LiquidCrystal_I2C *lcd; + + + +void LcdInitMode(void) +{ + lcd->init(); + lcd->clear(); +} + +void LcdInit(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + LcdInitMode(); +#ifdef USE_DISPLAY_MODES1TO5 + DisplayClearScreenBuffer(); +#endif + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void LcdInitDriver(void) +{ + if (!Settings.display_model) { + if (I2cSetDevice(LCD_ADDRESS1)) { + Settings.display_address[0] = LCD_ADDRESS1; + Settings.display_model = XDSP_01; + } + else if (I2cSetDevice(LCD_ADDRESS2)) { + Settings.display_address[0] = LCD_ADDRESS2; + Settings.display_model = XDSP_01; + } + } + + if (XDSP_01 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "LCD"); + + Settings.display_width = Settings.display_cols[0]; + Settings.display_height = Settings.display_rows; + lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows); + +#ifdef USE_DISPLAY_MODES1TO5 + DisplayAllocScreenBuffer(); +#endif + + LcdInitMode(); + } +} + +void LcdDrawStringAt(void) +{ + if (dsp_flag) { + dsp_x--; + dsp_y--; + } + lcd->setCursor(dsp_x, dsp_y); + lcd->print(dsp_str); +} + +void LcdDisplayOnOff(uint8_t on) +{ + if (on) { + lcd->backlight(); + } else { + lcd->noBacklight(); + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void LcdCenter(uint8_t row, char* txt) +{ + char line[Settings.display_cols[0] +2]; + + int len = strlen(txt); + int offset = 0; + if (len >= Settings.display_cols[0]) { + len = Settings.display_cols[0]; + } else { + offset = (Settings.display_cols[0] - len) / 2; + } + memset(line, 0x20, Settings.display_cols[0]); + line[Settings.display_cols[0]] = 0; + for (uint32_t i = 0; i < len; i++) { + line[offset +i] = txt[i]; + } + lcd->setCursor(0, row); + lcd->print(line); +} + +bool LcdPrintLog(void) +{ + bool result = false; + + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\337'); + if (txt != nullptr) { + uint8_t last_row = Settings.display_rows -1; + + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + lcd->setCursor(0, i); + lcd->print(disp_screen_buffer[i +1]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + lcd->setCursor(0, last_row); + lcd->print(disp_screen_buffer[last_row]); + + result = true; + } + } + return result; +} + +void LcdTime(void) +{ + char line[Settings.display_cols[0] +1]; + + snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + LcdCenter(0, line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + LcdCenter(1, line); +} + +void LcdRefresh(void) +{ + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + LcdTime(); + break; + case 2: + case 4: + LcdPrintLog(); + break; + case 3: + case 5: { + if (!LcdPrintLog()) { LcdTime(); } + break; + } + } + } +} + +#endif + + + + + +bool Xdsp01(uint8_t function) +{ + if (!I2cEnabled(XI2C_03)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + LcdInitDriver(); + } + else if (XDSP_01 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + LcdInit(dsp_init); + break; + case FUNC_DISPLAY_POWER: + LcdDisplayOnOff(disp_power); + break; + case FUNC_DISPLAY_CLEAR: + lcd->clear(); + break; +# 238 "S:/Development/Tasmota/tasmota/xdsp_01_lcd.ino" + case FUNC_DISPLAY_DRAW_STRING: + LcdDrawStringAt(); + break; + case FUNC_DISPLAY_ONOFF: + LcdDisplayOnOff(dsp_on); + break; + + +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + LcdRefresh(); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_02_ssd1306.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_02_ssd1306.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SSD1306 + +#define XDSP_02 2 +#define XI2C_04 4 + +#define OLED_RESET 4 + +#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); + +#define OLED_ADDRESS1 0x3C +#define OLED_ADDRESS2 0x3D + +#define OLED_BUFFER_COLS 40 +#define OLED_BUFFER_ROWS 16 + +#define OLED_FONT_WIDTH 6 +#define OLED_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_SSD1306 *oled1306; + +extern uint8_t *buffer; + + + +void SSD1306InitDriver(void) +{ + if (!Settings.display_model) { + if (I2cSetDevice(OLED_ADDRESS1)) { + Settings.display_address[0] = OLED_ADDRESS1; + Settings.display_model = XDSP_02; + } + else if (I2cSetDevice(OLED_ADDRESS2)) { + Settings.display_address[0] = OLED_ADDRESS2; + Settings.display_model = XDSP_02; + } + } + + if (XDSP_02 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "SSD1306"); + + if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) { + Settings.display_width = 128; + } + if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 48) && (Settings.display_height != 64)) { + Settings.display_height = 64; + } + + uint8_t reset_pin = -1; + if (pin[GPIO_OLED_RESET] < 99) { + reset_pin = pin[GPIO_OLED_RESET]; + } + + + if (buffer) { free(buffer); } + buffer = (unsigned char*)calloc((Settings.display_width * Settings.display_height) / 8,1); + if (!buffer) { return; } + + + + oled1306 = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, reset_pin); + oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], reset_pin >= 0); + renderer = oled1306; + renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + renderer->setTextFont(0); + renderer->setTextSize(2); + renderer->setCursor(20,20); + renderer->println(F("SSD1306")); + renderer->Updateframe(); + renderer->DisplayOnff(1); +#endif + + } +} + + +#ifdef USE_DISPLAY_MODES1TO5 + +void Ssd1306PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void Ssd1306Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setTextFont(Settings.display_font); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void Ssd1306Refresh(void) +{ + if (!renderer) return; + + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + Ssd1306Time(); + break; + case 2: + case 3: + case 4: + case 5: + Ssd1306PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp02(byte function) +{ + if (!I2cEnabled(XI2C_04)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SSD1306InitDriver(); + } + else if (XDSP_02 == Settings.display_model) { + switch (function) { +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + Ssd1306Refresh(); + break; +#endif + case FUNC_DISPLAY_MODEL: + result = true; + break; + } + } + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_03_matrix.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_03_matrix.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_MATRIX + +#define XDSP_03 3 +#define XI2C_05 5 + +#define MTX_MAX_SCREEN_BUFFER 80 + +#include +#include +#include + +Adafruit_8x8matrix *matrix[8]; +uint8_t mtx_matrices = 0; +uint8_t mtx_state = 0; +uint8_t mtx_counter = 0; +int16_t mtx_x = 0; +int16_t mtx_y = 0; + + +char *mtx_buffer = nullptr; + +uint8_t mtx_mode = 0; +uint8_t mtx_loop = 0; +uint8_t mtx_done = 0; + + + +void MatrixWrite(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->writeDisplay(); + } +} + +void MatrixClear(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + } + MatrixWrite(); +} + +void MatrixFixed(char* txt) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(-i *8, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); +} + +void MatrixCenter(char* txt) +{ + int offset; + + int len = strlen(txt); + offset = (len < 8) ? offset = ((mtx_matrices *8) - (len *6)) / 2 : 0; + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(-(i *8)+offset, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); +} + +void MatrixScrollLeft(char* txt, int loop) +{ + switch (mtx_state) { + case 1: + mtx_state = 2; + + mtx_x = 8 * mtx_matrices; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), txt); + + disp_refresh = Settings.display_refresh; + case 2: + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + matrix[i]->setCursor(mtx_x - i *8, 0); + matrix[i]->print(txt); + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); + + mtx_x--; + int16_t len = strlen(txt); + if (mtx_x < -(len *6)) { mtx_state = loop; } + } + break; + } +} + +void MatrixScrollUp(char* txt, int loop) +{ + int wordcounter = 0; + char tmpbuf[200]; + char *words[100]; + + + + char separators[] = " /"; + + switch (mtx_state) { + case 1: + mtx_state = 2; + + mtx_y = 8; + mtx_counter = 0; + disp_refresh = Settings.display_refresh; + case 2: + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + strlcpy(tmpbuf, txt, sizeof(tmpbuf)); + char *p = strtok(tmpbuf, separators); + while (p != nullptr && wordcounter < 40) { + words[wordcounter++] = p; + p = strtok(nullptr, separators); + } + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->clear(); + for (uint32_t j = 0; j < wordcounter; j++) { + matrix[i]->setCursor(-i *8, mtx_y + (j *8)); + matrix[i]->println(words[j]); + } + matrix[i]->setBrightness(Settings.display_dimmer); + } + MatrixWrite(); + if (((mtx_y %8) == 0) && mtx_counter) { + mtx_counter--; + } else { + mtx_y--; + mtx_counter = STATES * 1; + } + if (mtx_y < -(wordcounter *8)) { mtx_state = loop; } + } + break; + } +} + + + +void MatrixInitMode(void) +{ + for (uint32_t i = 0; i < mtx_matrices; i++) { + matrix[i]->setRotation(Settings.display_rotate); + matrix[i]->setBrightness(Settings.display_dimmer); + matrix[i]->blinkRate(0); + matrix[i]->setTextWrap(false); + + + matrix[i]->cp437(true); + } + MatrixClear(); +} + +void MatrixInit(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + MatrixInitMode(); + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void MatrixInitDriver(void) +{ + mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); + if (mtx_buffer != nullptr) { + if (!Settings.display_model) { + if (I2cSetDevice(Settings.display_address[1])) { + Settings.display_model = XDSP_03; + } + } + + if (XDSP_03 == Settings.display_model) { + mtx_state = 1; + for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) { + if (Settings.display_address[mtx_matrices]) { + I2cSetActiveFound(Settings.display_address[mtx_matrices], "8x8Matrix"); + matrix[mtx_matrices] = new Adafruit_8x8matrix(); + matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]); + } else { + break; + } + } + + Settings.display_width = mtx_matrices * 8; + Settings.display_height = 8; + + MatrixInitMode(); + } + } +} + +void MatrixOnOff(void) +{ + if (!disp_power) { MatrixClear(); } +} + +void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + strlcpy(mtx_buffer, str, MTX_MAX_SCREEN_BUFFER); + mtx_mode = x &1; + mtx_loop = y &1; + if (!mtx_state) { mtx_state = 1; } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void MatrixPrintLog(uint8_t direction) +{ + char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer; + if (txt != nullptr) { + if (!mtx_state) { mtx_state = 1; } + + if (!mtx_done) { + + uint8_t space = 0; + uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER; + mtx_buffer[0] = '\0'; + uint8_t i = 0; + while ((txt[i] != '\0') && (i < max_cols)) { + if (txt[i] == ' ') { + space++; + } else { + space = 0; + } + if (space < 2) { + strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < MTX_MAX_SCREEN_BUFFER -1) ? 1 : 0); + } + i++; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); + + mtx_done = 1; + } + + if (direction) { + MatrixScrollUp(mtx_buffer, 0); + } else { + MatrixScrollLeft(mtx_buffer, 0); + } + if (!mtx_state) { mtx_done = 0; } + } else { + char disp_time[9]; + + snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + MatrixFixed(disp_time); + } +} + +#endif + +void MatrixRefresh(void) +{ + if (disp_power) { + switch (Settings.display_mode) { + case 0: { + switch (mtx_mode) { + case 0: + MatrixScrollLeft(mtx_buffer, mtx_loop); + break; + case 1: + MatrixScrollUp(mtx_buffer, mtx_loop); + break; + } + break; + } +#ifdef USE_DISPLAY_MODES1TO5 + case 2: { + char disp_date[9]; + snprintf_P(disp_date, sizeof(disp_date), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); + MatrixFixed(disp_date); + break; + } + case 3: { + char disp_day[10]; + snprintf_P(disp_day, sizeof(disp_day), PSTR("%d %s"), RtcTime.day_of_month, RtcTime.name_of_month); + MatrixCenter(disp_day); + break; + } + case 4: + MatrixPrintLog(0); + break; + case 1: + case 5: + MatrixPrintLog(1); + break; +#endif + } + } +} + + + + + +bool Xdsp03(uint8_t function) +{ + if (!I2cEnabled(XI2C_05)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + MatrixInitDriver(); + } + else if (XDSP_03 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + MatrixInit(dsp_init); + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: + MatrixRefresh(); + break; + case FUNC_DISPLAY_POWER: + MatrixOnOff(); + break; + case FUNC_DISPLAY_DRAW_STRING: + MatrixDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; + } + } + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_04_ili9341.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_04_ili9341.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_ILI9341 + +#define XDSP_04 4 + +#define TFT_TOP 16 +#define TFT_BOTTOM 16 +#define TFT_FONT_WIDTH 6 +#define TFT_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_ILI9341 *tft; + +uint16_t tft_scroll; + + + +void Ili9341InitMode(void) +{ + tft->setRotation(Settings.display_rotate); + tft->invertDisplay(0); + tft->fillScreen(ILI9341_BLACK); + tft->setTextWrap(false); + tft->cp437(true); + if (!Settings.display_mode) { + tft->setCursor(0, 0); + tft->setTextColor(ILI9341_WHITE, ILI9341_BLACK); + tft->setTextSize(1); + } else { + tft->setScrollMargins(TFT_TOP, TFT_BOTTOM); + tft->setCursor(0, 0); + tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); + tft->setTextSize(2); + + + tft_scroll = TFT_TOP; + } +} + +void Ili9341Init(uint8_t mode) +{ + switch(mode) { + case DISPLAY_INIT_MODE: + Ili9341InitMode(); +#ifdef USE_DISPLAY_MODES1TO5 + if (Settings.display_rotate) { + DisplayClearScreenBuffer(); + } +#endif + break; + case DISPLAY_INIT_PARTIAL: + case DISPLAY_INIT_FULL: + break; + } +} + +void Ili9341InitDriver(void) +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_04; + } + + if (XDSP_04 == Settings.display_model) { + if (Settings.display_width != ILI9341_TFTWIDTH) { + Settings.display_width = ILI9341_TFTWIDTH; + } + if (Settings.display_height != ILI9341_TFTHEIGHT) { + Settings.display_height = ILI9341_TFTHEIGHT; + } + tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]); + tft->begin(); + +#ifdef USE_DISPLAY_MODES1TO5 + if (Settings.display_rotate) { + DisplayAllocScreenBuffer(); + } +#endif + + Ili9341InitMode(); + } +} + +void Ili9341Clear(void) +{ + tft->fillScreen(ILI9341_BLACK); + tft->setCursor(0, 0); +} + +void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + uint16_t active_color = ILI9341_WHITE; + + tft->setTextSize(Settings.display_size); + if (!flag) { + tft->setCursor(x, y); + } else { + tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size); + } + if (color) { active_color = color; } + tft->setTextColor(active_color, ILI9341_BLACK); + tft->println(str); +} + +void Ili9341DisplayOnOff(uint8_t on) +{ + + + if (pin[GPIO_BACKLIGHT] < 99) { + pinMode(pin[GPIO_BACKLIGHT], OUTPUT); + digitalWrite(pin[GPIO_BACKLIGHT], on); + } +} + +void Ili9341OnOff(void) +{ + Ili9341DisplayOnOff(disp_power); +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void Ili9341PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (Settings.display_rotate) { + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + } + + char* txt = DisplayLogBuffer('\370'); + if (txt != nullptr) { + uint8_t size = Settings.display_size; + uint16_t theight = size * TFT_FONT_HEIGTH; + + tft->setTextSize(size); + tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); + if (!Settings.display_rotate) { + tft->setCursor(0, tft_scroll); + tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); + tft->print(txt); + tft_scroll += theight; + if (tft_scroll >= (tft->height() - TFT_BOTTOM)) { + tft_scroll = TFT_TOP; + } + tft->scrollTo(tft_scroll); + } else { + uint8_t last_row = Settings.display_rows -1; + + tft_scroll = theight; + tft->setCursor(0, tft_scroll); + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + + tft->print(disp_screen_buffer[i]); + tft_scroll += theight; + tft->setCursor(0, tft_scroll); + delay(1); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + tft->print(disp_screen_buffer[last_row]); + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); + } + } +} + +void Ili9341Refresh(void) +{ + if (Settings.display_mode) { + char tftdt[Settings.display_cols[0] +1]; + char date4[11]; + char space[Settings.display_cols[0] - 17]; + char time[9]; + + tft->setTextSize(2); + tft->setTextColor(ILI9341_YELLOW, ILI9341_RED); + tft->setCursor(0, 0); + + snprintf_P(date4, sizeof(date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + memset(space, 0x20, sizeof(space)); + space[sizeof(space) -1] = '\0'; + snprintf_P(time, sizeof(time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + snprintf_P(tftdt, sizeof(tftdt), PSTR("%s%s%s"), date4, space, time); + + tft->print(tftdt); + + switch (Settings.display_mode) { + case 1: + case 2: + case 3: + case 4: + case 5: + Ili9341PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp04(uint8_t function) +{ + bool result = false; + + if (spi_flg) { + if (FUNC_DISPLAY_INIT_DRIVER == function) { + Ili9341InitDriver(); + } + else if (XDSP_04 == Settings.display_model) { + + if (!dsp_color) { dsp_color = ILI9341_WHITE; } + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_INIT: + Ili9341Init(dsp_init); + break; + case FUNC_DISPLAY_POWER: + Ili9341OnOff(); + break; + case FUNC_DISPLAY_CLEAR: + Ili9341Clear(); + break; + case FUNC_DISPLAY_DRAW_HLINE: + tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color); + break; + case FUNC_DISPLAY_DRAW_VLINE: + tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color); + break; + case FUNC_DISPLAY_DRAW_LINE: + tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + case FUNC_DISPLAY_DRAW_CIRCLE: + tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color); + break; + case FUNC_DISPLAY_FILL_CIRCLE: + tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color); + break; + case FUNC_DISPLAY_DRAW_RECTANGLE: + tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + case FUNC_DISPLAY_FILL_RECTANGLE: + tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); + break; + + + + case FUNC_DISPLAY_TEXT_SIZE: + tft->setTextSize(Settings.display_size); + break; + case FUNC_DISPLAY_FONT_SIZE: + + break; + case FUNC_DISPLAY_DRAW_STRING: + Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; + case FUNC_DISPLAY_ONOFF: + Ili9341DisplayOnOff(dsp_on); + break; + case FUNC_DISPLAY_ROTATION: + tft->setRotation(Settings.display_rotate); + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + Ili9341Refresh(); + break; +#endif + } + } + } + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_05_epaper_29.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_05_epaper_29.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_EPAPER_29 + +#define XDSP_05 5 + +#define EPD_TOP 12 +#define EPD_FONT_HEIGTH 12 + +#define COLORED 1 +#define UNCOLORED 0 + + + +#define USE_TINY_FONT + +#include +#include + + +extern uint8_t *buffer; +uint16_t epd_scroll; + +Epd *epd; + + + +void EpdInitDriver29() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_05; + } + + if (XDSP_05 == Settings.display_model) { + if (Settings.display_width != EPD_WIDTH) { + Settings.display_width = EPD_WIDTH; + } + if (Settings.display_height != EPD_HEIGHT) { + Settings.display_height = EPD_HEIGHT; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((EPD_WIDTH * EPD_HEIGHT) / 8,1); + if (!buffer) return; + + + epd = new Epd(EPD_WIDTH,EPD_HEIGHT); + + + if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) { + epd->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SPI_CS], pin[GPIO_SPI_CLK], pin[GPIO_SPI_MOSI]); + } + else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { + epd->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SSPI_CS], pin[GPIO_SSPI_SCLK], pin[GPIO_SSPI_MOSI]); + } else { + free(buffer); + return; + } + + renderer = epd; + epd->Init(DISPLAY_INIT_FULL); + epd->Init(DISPLAY_INIT_PARTIAL); + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(1); + renderer->DrawStringAt(50, 50, "Waveshare E-Paper Display!", COLORED,0); + renderer->Updateframe(); + delay(1000); + renderer->fillScreen(0); +#endif + + } +} + + + + + + + +#ifdef USE_DISPLAY_MODES1TO5 +#define EPD_FONT_HEIGTH 12 +void EpdPrintLog29(void) +{ + + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + + char* txt = DisplayLogBuffer('\040'); + if (txt != nullptr) { + uint8_t size = Settings.display_size; + uint16_t theight = size * EPD_FONT_HEIGTH; + + renderer->setTextFont(size); + uint8_t last_row = Settings.display_rows -1; + + + epd_scroll = 0; + for (uint32_t i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0); + epd_scroll += theight; + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0); + + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); + } + } +} + +void EpdRefresh29(void) +{ + if (Settings.display_mode) { + + if (!renderer) return; +# 165 "S:/Development/Tasmota/tasmota/xdsp_05_epaper_29.ino" + switch (Settings.display_mode) { + case 1: + case 2: + case 3: + case 4: + case 5: + EpdPrintLog29(); + renderer->Updateframe(); + break; + } + + + } +} + +#endif + + + + + +bool Xdsp05(uint8_t function) +{ + bool result = false; + if (FUNC_DISPLAY_INIT_DRIVER == function) { + EpdInitDriver29(); + } + else if (XDSP_05 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh29(); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_06_epaper_42.ino" +# 21 "S:/Development/Tasmota/tasmota/xdsp_06_epaper_42.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_EPAPER_42 + +#define XDSP_06 6 + +#define COLORED42 1 +#define UNCOLORED42 0 + + + +#define USE_TINY_FONT + +#include +#include + +extern uint8_t *buffer; + +Epd42 *epd42; + + + + +void EpdInitDriver42() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_06; + } + + if (XDSP_06 == Settings.display_model) { + + if (Settings.display_width != EPD_WIDTH42) { + Settings.display_width = EPD_WIDTH42; + } + if (Settings.display_height != EPD_HEIGHT42) { + Settings.display_height = EPD_HEIGHT42; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((EPD_WIDTH42 * EPD_HEIGHT42) / 8,1); + if (!buffer) return; + + + epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42); + + #ifdef USE_SPI + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)) { + epd42->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + } else { + free(buffer); + return; + } + #else + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { + epd42->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + } else { + free(buffer); + return; + } + #endif + + renderer = epd42; + + epd42->Init(); + + renderer->fillScreen(0); + + + epd42->Init(DISPLAY_INIT_FULL); + + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + + epd42->ClearFrame(); + renderer->Updateframe(); + delay(3000); + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->DrawStringAt(50, 140, "Waveshare E-Paper!", COLORED42,0); + renderer->Updateframe(); + delay(350); + renderer->fillScreen(0); +#endif + + } +} + + + + + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void EpdRefresh42() +{ + if (Settings.display_mode) { + + } +} + +#endif + + + + + + +bool Xdsp06(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + EpdInitDriver42(); + } + else if (XDSP_06 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh42(); + break; +#endif + } + } + return result; +} + + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_07_sh1106.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_07_sh1106.ino" +#ifdef USE_I2C +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SH1106 + +#define OLED_RESET 4 + +#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); + +extern uint8_t *buffer; + +#define XDSP_07 7 +#define XI2C_06 6 + +#define OLED_ADDRESS1 0x3C +#define OLED_ADDRESS2 0x3D + +#define OLED_BUFFER_COLS 40 +#define OLED_BUFFER_ROWS 16 + +#define OLED_FONT_WIDTH 6 +#define OLED_FONT_HEIGTH 8 + +#include +#include +#include + +Adafruit_SH1106 *oled1106; + + + + +void SH1106InitDriver() +{ + if (!Settings.display_model) { + if (I2cSetDevice(OLED_ADDRESS1)) { + Settings.display_address[0] = OLED_ADDRESS1; + Settings.display_model = XDSP_07; + } + else if (I2cSetDevice(OLED_ADDRESS2)) { + Settings.display_address[0] = OLED_ADDRESS2; + Settings.display_model = XDSP_07; + } + } + + if (XDSP_07 == Settings.display_model) { + I2cSetActiveFound(Settings.display_address[0], "SH1106"); + + if (Settings.display_width != SH1106_LCDWIDTH) { + Settings.display_width = SH1106_LCDWIDTH; + } + if (Settings.display_height != SH1106_LCDHEIGHT) { + Settings.display_height = SH1106_LCDHEIGHT; + } + + + if (buffer) free(buffer); + buffer=(unsigned char*)calloc((SH1106_LCDWIDTH * SH1106_LCDHEIGHT) / 8,1); + if (!buffer) return; + + + oled1106 = new Adafruit_SH1106(SH1106_LCDWIDTH,SH1106_LCDHEIGHT); + renderer=oled1106; + renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0); + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->setTextColor(1,0); + +#ifdef SHOW_SPLASH + renderer->setTextFont(0); + renderer->setTextSize(2); + renderer->setCursor(20,20); + renderer->println(F("SH1106")); + renderer->Updateframe(); + renderer->DisplayOnff(1); +#endif + } +} + + + +#ifdef USE_DISPLAY_MODES1TO5 + +void SH1106PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void SH1106Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setTextFont(Settings.display_font); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void SH1106Refresh(void) +{ + if (!renderer) return; + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + SH1106Time(); + break; + case 2: + case 3: + case 4: + case 5: + SH1106PrintLog(); + break; + } + } +} + +#endif + + + + + +bool Xdsp07(uint8_t function) +{ + if (!I2cEnabled(XI2C_06)) { return false; } + + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SH1106InitDriver(); + } + else if (XDSP_07 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + SH1106Refresh(); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_08_ILI9488.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_08_ILI9488.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_ILI9488 + +#define XDSP_08 8 +#define XI2C_38 38 + +#define COLORED 1 +#define UNCOLORED 0 + + +#define FT6236_address 0x38 + + + +#define USE_TINY_FONT + + +#include +#include + +TouchLocation ili9488_pLoc; +uint8_t ili9488_ctouch_counter = 0; + + +#define BACKPLANE_PIN 2 + +extern uint8_t *buffer; +extern uint8_t color_type; +ILI9488 *ili9488; + +#ifdef USE_TOUCH_BUTTONS +extern VButton *buttons[]; +#endif + +extern const uint16_t picture[]; +uint8_t FT6236_found; + + + +void ILI9488_InitDriver() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_08; + } + + if (XDSP_08 == Settings.display_model) { + + if (Settings.display_width != ILI9488_TFTWIDTH) { + Settings.display_width = ILI9488_TFTWIDTH; + } + if (Settings.display_height != ILI9488_TFTHEIGHT) { + Settings.display_height = ILI9488_TFTHEIGHT; + } + + + buffer=NULL; + + + fg_color = ILI9488_WHITE; + bg_color = ILI9488_BLACK; + + uint8_t bppin=BACKPLANE_PIN; + if (pin[GPIO_BACKLIGHT]<99) { + bppin=pin[GPIO_BACKLIGHT]; + } + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ + ili9488 = new ILI9488(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK],bppin); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { + ili9488 = new ILI9488(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK],bppin); + } else { + return; + } + } + + SPI.begin(); + ili9488->begin(); + renderer = ili9488; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(ILI9488_WHITE,ILI9488_BLACK); + renderer->DrawStringAt(50, 50, "ILI9488 TFT Display!", ILI9488_WHITE,0); + delay(1000); + + +#endif + + color_type = COLOR_COLOR; + + + if (I2cEnabled(XI2C_38) && I2cSetDevice(FT6236_address)) { + FT6236begin(FT6236_address); + FT6236_found=1; + I2cSetActiveFound(FT6236_address, "FT6236"); + } else { + FT6236_found=0; + } + + } +} + +#ifdef USE_TOUCH_BUTTONS +void ILI9488_MQTT(uint8_t count,const char *cp) { + ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); + MqttPublishTeleSensor(); +} + +void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower|=0x80; + else buttons[count]->vpower&=0x7f; +} + +void FT6236Check() { +uint16_t temp; +uint8_t rbutt=0,vbutt=0; +ili9488_ctouch_counter++; +if (2 == ili9488_ctouch_counter) { + + ili9488_ctouch_counter=0; + if (FT6236readTouchLocation(&ili9488_pLoc,1)) { + + if (renderer) { + uint8_t rot=renderer->getRotation(); + switch (rot) { + case 0: + temp=ili9488_pLoc.y; + ili9488_pLoc.y=renderer->height()-ili9488_pLoc.x; + ili9488_pLoc.x=temp; + break; + case 1: + break; + case 2: + break; + case 3: + temp=ili9488_pLoc.y; + ili9488_pLoc.y=ili9488_pLoc.x; + ili9488_pLoc.x=renderer->width()-temp; + break; + } + + for (uint8_t count=0; countvpower&0x7f; + if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) { + + buttons[count]->press(true); + if (buttons[count]->justPressed()) { + if (!bflags) { + uint8_t pwr=bitRead(power,rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + ILI9488_RDW_BUTT(count,!pwr); + } + } else { + + const char *cp; + if (bflags==1) { + + buttons[count]->vpower^=0x80; + cp="TBT"; + } else { + + buttons[count]->vpower|=0x80; + cp="PBT"; + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + ILI9488_MQTT(count,cp); + } + } + } + if (!bflags) { + rbutt++; + } else { + vbutt++; + } + } + } + } + } else { + + for (uint8_t count=0; countvpower&0x7f; + buttons[count]->press(false); + if (buttons[count]->justReleased()) { + uint8_t bflags=buttons[count]->vpower&0x7f; + if (bflags>0) { + if (bflags>1) { + + buttons[count]->vpower&=0x7f; + ILI9488_MQTT(count,"PBT"); + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + } + } + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; + if (pwr!=vpwr) { + ILI9488_RDW_BUTT(count,pwr); + } + rbutt++; + } + } + } + ili9488_pLoc.x=0; + ili9488_pLoc.y=0; + } +} +} +#endif + + + + +bool Xdsp08(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + ILI9488_InitDriver(); + } + else if (XDSP_08 == Settings.display_model) { + + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: +#ifdef USE_TOUCH_BUTTONS + if (FT6236_found) FT6236Check(); +#endif + break; + } + } + + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_09_SSD1351.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_09_SSD1351.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_SSD1351 + +#define XDSP_09 9 + +#define COLORED 1 +#define UNCOLORED 0 + + + + +#define USE_TINY_FONT + +#include + +extern uint8_t *buffer; +extern uint8_t color_type; +SSD1351 *ssd1351; + + + +void SSD1351_InitDriver() { + if (!Settings.display_model) { + Settings.display_model = XDSP_09; + } + + if (XDSP_09 == Settings.display_model) { + + if (Settings.display_width != SSD1351_WIDTH) { + Settings.display_width = SSD1351_WIDTH; + } + if (Settings.display_height != SSD1351_HEIGHT) { + Settings.display_height = SSD1351_HEIGHT; + } + + buffer=0; + + + fg_color = SSD1351_WHITE; + bg_color = SSD1351_BLACK; + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ + ssd1351 = new SSD1351(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)){ + ssd1351 = new SSD1351(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); + } else { + return; + } + } + + delay(100); + SPI.begin(); + ssd1351->begin(); + renderer = ssd1351; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->dim(Settings.display_dimmer); + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(SSD1351_WHITE,SSD1351_BLACK); + renderer->DrawStringAt(10, 60, "SSD1351", SSD1351_RED,0); + delay(1000); + +#endif + color_type = COLOR_COLOR; + } +} + +#ifdef USE_DISPLAY_MODES1TO5 + +void SSD1351PrintLog(void) +{ + disp_refresh--; + if (!disp_refresh) { + disp_refresh = Settings.display_refresh; + if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } + + char* txt = DisplayLogBuffer('\370'); + if (txt != NULL) { + uint8_t last_row = Settings.display_rows -1; + + renderer->clearDisplay(); + renderer->setTextSize(Settings.display_size); + renderer->setCursor(0,0); + for (byte i = 0; i < last_row; i++) { + strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); + renderer->println(disp_screen_buffer[i]); + } + strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); + DisplayFillScreen(last_row); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); + + renderer->println(disp_screen_buffer[last_row]); + renderer->Updateframe(); + } + } +} + +void SSD1351Time(void) +{ + char line[12]; + + renderer->clearDisplay(); + renderer->setTextSize(2); + renderer->setCursor(0, 0); + snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + renderer->println(line); + snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); + renderer->println(line); + renderer->Updateframe(); +} + +void SSD1351Refresh(void) +{ + if (Settings.display_mode) { + switch (Settings.display_mode) { + case 1: + SSD1351Time(); + break; + case 2: + case 3: + case 4: + case 5: + SSD1351PrintLog(); + break; + } + } +} + +#endif + + + + +bool Xdsp09(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + SSD1351_InitDriver(); + } + else if (XDSP_09 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + SSD1351Refresh(); + break; +#endif + } + } + return result; +} +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_10_RA8876.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_10_RA8876.ino" +#ifdef USE_SPI +#ifdef USE_DISPLAY +#ifdef USE_DISPLAY_RA8876 + +#define XDSP_10 10 +#define XI2C_39 39 + +#define COLORED 1 +#define UNCOLORED 0 + + +#define FT5316_address 0x38 + + + +#define USE_TINY_FONT + +#include +#include + +TouchLocation ra8876_pLoc; +uint8_t ra8876_ctouch_counter = 0; + +#ifdef USE_TOUCH_BUTTONS +extern VButton *buttons[]; +#endif + +extern uint8_t *buffer; +extern uint8_t color_type; +RA8876 *ra8876; + +uint8_t FT5316_found; + + +void RA8876_InitDriver() +{ + if (!Settings.display_model) { + Settings.display_model = XDSP_10; + } + + if (XDSP_10 == Settings.display_model) { + + if (Settings.display_width != RA8876_TFTWIDTH) { + Settings.display_width = RA8876_TFTWIDTH; + } + if (Settings.display_height != RA8876_TFTHEIGHT) { + Settings.display_height = RA8876_TFTHEIGHT; + } + buffer=0; + + + fg_color = RA8876_WHITE; + bg_color = RA8876_BLACK; + + + if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]==13) && (pin[GPIO_SSPI_MISO]==12) && (pin[GPIO_SSPI_SCLK]==14)) { + ra8876 = new RA8876(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_MISO],pin[GPIO_SSPI_SCLK],pin[GPIO_BACKLIGHT]); + } else { + if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]==13) && (pin[GPIO_SPI_MISO]==12) && (pin[GPIO_SPI_CLK]==14)) { + ra8876 = new RA8876(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_MISO],pin[GPIO_SPI_CLK],pin[GPIO_BACKLIGHT]); + } else { + return; + } + } + + ra8876->begin(); + renderer = ra8876; + renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); + renderer->dim(Settings.display_dimmer); + + +#ifdef SHOW_SPLASH + + renderer->setTextFont(2); + renderer->setTextColor(RA8876_WHITE,RA8876_BLACK); + renderer->DrawStringAt(600, 300, "RA8876", RA8876_RED,0); + delay(1000); + +#endif + color_type = COLOR_COLOR; + + if (I2cEnabled(XI2C_39) && I2cSetDevice(FT5316_address)) { + FT6236begin(FT5316_address); + FT5316_found=1; + I2cSetActiveFound(FT5316_address, "FT5316"); + } else { + FT5316_found=0; + } + + } +} + +#ifdef USE_TOUCH_BUTTONS +void RA8876_MQTT(uint8_t count,const char *cp) { + ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); + MqttPublishTeleSensor(); +} + +void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr) { + buttons[count]->xdrawButton(pwr); + if (pwr) buttons[count]->vpower|=0x80; + else buttons[count]->vpower&=0x7f; +} + + +void FT5316Check() { +uint16_t temp; +uint8_t rbutt=0,vbutt=0; +ra8876_ctouch_counter++; +if (2 == ra8876_ctouch_counter) { + + ra8876_ctouch_counter=0; + + if (FT6236readTouchLocation(&ra8876_pLoc,1)) { + ra8876_pLoc.x=ra8876_pLoc.x*RA8876_TFTWIDTH/800; + ra8876_pLoc.y=ra8876_pLoc.y*RA8876_TFTHEIGHT/480; + + + if (renderer) { + + + ra8876_pLoc.x=RA8876_TFTWIDTH-ra8876_pLoc.x; + ra8876_pLoc.y=RA8876_TFTHEIGHT-ra8876_pLoc.y; +# 170 "S:/Development/Tasmota/tasmota/xdsp_10_RA8876.ino" + for (uint8_t count=0; countvpower&0x7f; + if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) { + + buttons[count]->press(true); + if (buttons[count]->justPressed()) { + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { + ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); + RA8876_RDW_BUTT(count,!pwr); + } + } else { + + const char *cp; + if (bflags==1) { + + buttons[count]->vpower^=0x80; + cp="TBT"; + } else { + + buttons[count]->vpower|=0x80; + cp="PBT"; + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + RA8876_MQTT(count,cp); + } + } + } + if (!bflags) { + rbutt++; + } else { + vbutt++; + } + } + } + } + } else { + + for (uint8_t count=0; countvpower&0x7f; + buttons[count]->press(false); + if (buttons[count]->justReleased()) { + if (bflags>0) { + if (bflags>1) { + + buttons[count]->vpower&=0x7f; + RA8876_MQTT(count,"PBT"); + } + buttons[count]->xdrawButton(buttons[count]->vpower&0x80); + } + } + if (!bflags) { + + uint8_t pwr=bitRead(power,rbutt); + uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; + if (pwr!=vpwr) { + RA8876_RDW_BUTT(count,pwr); + } + rbutt++; + } + } + } + ra8876_pLoc.x=0; + ra8876_pLoc.y=0; + } +} +} +#endif +# 426 "S:/Development/Tasmota/tasmota/xdsp_10_RA8876.ino" +bool Xdsp10(uint8_t function) +{ + bool result = false; + + if (FUNC_DISPLAY_INIT_DRIVER == function) { + RA8876_InitDriver(); + } + else if (XDSP_10 == Settings.display_model) { + switch (function) { + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_EVERY_50_MSECOND: +#ifdef USE_TOUCH_BUTTONS + if (FT5316_found) FT5316Check(); +#endif + break; + } + } + return result; +} +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xdsp_interface.ino" +# 20 "S:/Development/Tasmota/tasmota/xdsp_interface.ino" +#ifdef USE_DISPLAY + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xdsp_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xdsp_func_ptr[])(uint8_t) = { +#endif + +#ifdef XDSP_01 + &Xdsp01, +#endif + +#ifdef XDSP_02 + &Xdsp02, +#endif + +#ifdef XDSP_03 + &Xdsp03, +#endif + +#ifdef XDSP_04 + &Xdsp04, +#endif + +#ifdef XDSP_05 + &Xdsp05, +#endif + +#ifdef XDSP_06 + &Xdsp06, +#endif + +#ifdef XDSP_07 + &Xdsp07, +#endif + +#ifdef XDSP_08 + &Xdsp08, +#endif + +#ifdef XDSP_09 + &Xdsp09, +#endif + +#ifdef XDSP_10 + &Xdsp10, +#endif + +#ifdef XDSP_11 + &Xdsp11, +#endif + +#ifdef XDSP_12 + &Xdsp12, +#endif + +#ifdef XDSP_13 + &Xdsp13, +#endif + +#ifdef XDSP_14 + &Xdsp14, +#endif + +#ifdef XDSP_15 + &Xdsp15, +#endif + +#ifdef XDSP_16 + &Xdsp16 +#endif +}; + +const uint8_t xdsp_present = sizeof(xdsp_func_ptr) / sizeof(xdsp_func_ptr[0]); +# 117 "S:/Development/Tasmota/tasmota/xdsp_interface.ino" +uint8_t XdspPresent(void) +{ + return xdsp_present; +} + +bool XdspCall(uint8_t Function) +{ + bool result = false; + + DEBUG_TRACE_LOG(PSTR("DSP: %d"), Function); + + for (uint32_t x = 0; x < xdsp_present; x++) { + result = xdsp_func_ptr[x](Function); + + if (result && (FUNC_DISPLAY_MODEL == Function)) { + break; + } + } + + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xlgt_01_ws2812.ino" +# 20 "S:/Development/Tasmota/tasmota/xlgt_01_ws2812.ino" +#ifdef USE_LIGHT +#ifdef USE_WS2812 +# 38 "S:/Development/Tasmota/tasmota/xlgt_01_ws2812.ino" +#define XLGT_01 1 + +const uint8_t WS2812_SCHEMES = 8; + +const char kWs2812Commands[] PROGMEM = "|" + D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH ; + +void (* const Ws2812Command[])(void) PROGMEM = { + &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth }; + +#include + +#if (USE_WS2812_CTYPE == NEO_GRB) + typedef NeoGrbFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_BRG) + typedef NeoBrgFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_RBG) + typedef NeoRbgFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_RGBW) + typedef NeoRgbwFeature selectedNeoFeatureType; +#elif (USE_WS2812_CTYPE == NEO_GRBW) + typedef NeoGrbwFeature selectedNeoFeatureType; +#else + typedef NeoRgbFeature selectedNeoFeatureType; +#endif + +#ifdef USE_WS2812_DMA + + +#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) + typedef NeoEsp8266DmaWs2812xMethod selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) + typedef NeoEsp8266DmaSk6812Method selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) + typedef NeoEsp8266DmaApa106Method selectedNeoSpeedType; +#else + typedef NeoEsp8266Dma800KbpsMethod selectedNeoSpeedType; +#endif + +#else + + +#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) + typedef NeoEsp8266BitBangWs2812xMethod selectedNeoSpeedType; +#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) + typedef NeoEsp8266BitBangSk6812Method selectedNeoSpeedType; +#else + typedef NeoEsp8266BitBang800KbpsMethod selectedNeoSpeedType; +#endif + +#endif + +NeoPixelBus *strip = nullptr; + +struct WsColor { + uint8_t red, green, blue; +}; + +struct ColorScheme { + WsColor* colors; + uint8_t count; +}; + +WsColor kIncandescent[2] = { 255,140,20, 0,0,0 }; +WsColor kRgb[3] = { 255,0,0, 0,255,0, 0,0,255 }; +WsColor kChristmas[2] = { 255,0,0, 0,255,0 }; +WsColor kHanukkah[2] = { 0,0,255, 255,255,255 }; +WsColor kwanzaa[3] = { 255,0,0, 0,0,0, 0,255,0 }; +WsColor kRainbow[7] = { 255,0,0, 255,128,0, 255,255,0, 0,255,0, 0,0,255, 128,0,255, 255,0,255 }; +WsColor kFire[3] = { 255,0,0, 255,102,0, 255,192,0 }; +ColorScheme kSchemes[WS2812_SCHEMES -1] = { + kIncandescent, 2, + kRgb, 3, + kChristmas, 2, + kHanukkah, 2, + kwanzaa, 3, + kRainbow, 7, + kFire, 3 }; + +uint8_t kWidth[5] = { + 1, + 2, + 4, + 8, + 255 }; +uint8_t kWsRepeat[5] = { + 8, + 6, + 4, + 2, + 1 }; + +struct WS2812 { + uint8_t show_next = 1; + uint8_t scheme_offset = 0; + bool suspend_update = false; +} Ws2812; + + + +void Ws2812StripShow(void) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; +#else + RgbColor c; +#endif + + if (Settings.light_correction) { + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + c = strip->GetPixelColor(i); + c.R = ledGamma(c.R); + c.G = ledGamma(c.G); + c.B = ledGamma(c.B); +#if (USE_WS2812_CTYPE > NEO_3LED) + c.W = ledGamma(c.W); +#endif + strip->SetPixelColor(i, c); + } + } + strip->Show(); +} + +int mod(int a, int b) +{ + int ret = a % b; + if (ret < 0) ret += b; + return ret; +} + +void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor color; +#else + RgbColor color; +#endif + + uint32_t mod_position = mod(position, (int)Settings.light_pixels); + + color = strip->GetPixelColor(mod_position); + float dimmer = 100 / (float)Settings.light_dimmer; + color.R = tmin(color.R + ((hand_color.red / dimmer) * offset), 255); + color.G = tmin(color.G + ((hand_color.green / dimmer) * offset), 255); + color.B = tmin(color.B + ((hand_color.blue / dimmer) * offset), 255); + strip->SetPixelColor(mod_position, color); +} + +void Ws2812UpdateHand(int position, uint32_t index) +{ + uint32_t width = Settings.light_width; + if (index < WS_MARKER) { width = Settings.ws_width[index]; } + if (!width) { return; } + + position = (position + Settings.light_rotation) % Settings.light_pixels; + + if (Settings.flag.ws_clock_reverse) { + position = Settings.light_pixels -position; + } + WsColor hand_color = { Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE] }; + + Ws2812UpdatePixelColor(position, hand_color, 1); + + uint32_t range = ((width -1) / 2) +1; + for (uint32_t h = 1; h < range; h++) { + float offset = (float)(range - h) / (float)range; + Ws2812UpdatePixelColor(position -h, hand_color, offset); + Ws2812UpdatePixelColor(position +h, hand_color, offset); + } +} + +void Ws2812Clock(void) +{ + strip->ClearTo(0); + int clksize = 60000 / (int)Settings.light_pixels; + + Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); + Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); + Ws2812UpdateHand((((RtcTime.hour % 12) * 5000) + ((RtcTime.minute * 1000) / 12 )) / clksize, WS_HOUR); + if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { + for (uint32_t i = 0; i < 12; i++) { + Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); + } + } + + Ws2812StripShow(); +} + +void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i) +{ + + + + + ColorScheme scheme = kSchemes[schemenr]; + uint32_t curRange = i / range; + uint32_t rangeIndex = i % range; + uint32_t colorIndex = rangeIndex / gradRange; + uint32_t start = colorIndex; + uint32_t end = colorIndex +1; + if (curRange % 2 != 0) { + start = (scheme.count -1) - start; + end = (scheme.count -1) - end; + } + float dimmer = 100 / (float)Settings.light_dimmer; + float fmyRed = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].red, scheme.colors[end].red) / dimmer; + float fmyGrn = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].green, scheme.colors[end].green) / dimmer; + float fmyBlu = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].blue, scheme.colors[end].blue) / dimmer; + mColor->red = (uint8_t)fmyRed; + mColor->green = (uint8_t)fmyGrn; + mColor->blue = (uint8_t)fmyBlu; +} + +void Ws2812Gradient(uint32_t schemenr) +{ + + + + + +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; + c.W = 0; +#else + RgbColor c; +#endif + + ColorScheme scheme = kSchemes[schemenr]; + if (scheme.count < 2) { return; } + + uint32_t repeat = kWsRepeat[Settings.light_width]; + uint32_t range = (uint32_t)ceil((float)Settings.light_pixels / (float)repeat); + uint32_t gradRange = (uint32_t)ceil((float)range / (float)(scheme.count - 1)); + uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); + uint32_t offset = speed > 0 ? Light.strip_timer_counter / speed : 0; + + WsColor oldColor, currentColor; + Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset); + currentColor = oldColor; + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + if (kWsRepeat[Settings.light_width] > 1) { + Ws2812GradientColor(schemenr, ¤tColor, range, gradRange, i +offset); + } + if (Settings.light_speed > 0) { + + c.R = map(Light.strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red); + c.G = map(Light.strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green); + c.B = map(Light.strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue); + } + else { + + c.R = currentColor.red; + c.G = currentColor.green; + c.B = currentColor.blue; + } + strip->SetPixelColor(i, c); + oldColor = currentColor; + } + Ws2812StripShow(); +} + +void Ws2812Bars(uint32_t schemenr) +{ + + + + + +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor c; + c.W = 0; +#else + RgbColor c; +#endif + + ColorScheme scheme = kSchemes[schemenr]; + + uint32_t maxSize = Settings.light_pixels / scheme.count; + if (kWidth[Settings.light_width] > maxSize) { maxSize = 0; } + + uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); + uint32_t offset = (speed > 0) ? Light.strip_timer_counter / speed : 0; + + WsColor mcolor[scheme.count]; + memcpy(mcolor, scheme.colors, sizeof(mcolor)); + float dimmer = 100 / (float)Settings.light_dimmer; + for (uint32_t i = 0; i < scheme.count; i++) { + float fmyRed = (float)mcolor[i].red / dimmer; + float fmyGrn = (float)mcolor[i].green / dimmer; + float fmyBlu = (float)mcolor[i].blue / dimmer; + mcolor[i].red = (uint8_t)fmyRed; + mcolor[i].green = (uint8_t)fmyGrn; + mcolor[i].blue = (uint8_t)fmyBlu; + } + uint32_t colorIndex = offset % scheme.count; + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + if (maxSize) { colorIndex = ((i + offset) % (scheme.count * kWidth[Settings.light_width])) / kWidth[Settings.light_width]; } + c.R = mcolor[colorIndex].red; + c.G = mcolor[colorIndex].green; + c.B = mcolor[colorIndex].blue; + strip->SetPixelColor(i, c); + } + Ws2812StripShow(); +} + +void Ws2812Clear(void) +{ + strip->ClearTo(0); + strip->Show(); + Ws2812.show_next = 1; +} + +void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) +{ +#if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor lcolor; + lcolor.W = white; +#else + RgbColor lcolor; +#endif + + lcolor.R = red; + lcolor.G = green; + lcolor.B = blue; + if (led) { + strip->SetPixelColor(led -1, lcolor); + } else { + + for (uint32_t i = 0; i < Settings.light_pixels; i++) { + strip->SetPixelColor(i, lcolor); + } + } + + if (!Ws2812.suspend_update) { + strip->Show(); + Ws2812.show_next = 1; + } +} + +char* Ws2812GetColor(uint32_t led, char* scolor) +{ + uint8_t sl_ledcolor[4]; + + #if (USE_WS2812_CTYPE > NEO_3LED) + RgbwColor lcolor = strip->GetPixelColor(led -1); + sl_ledcolor[3] = lcolor.W; + #else + RgbColor lcolor = strip->GetPixelColor(led -1); + #endif + sl_ledcolor[0] = lcolor.R; + sl_ledcolor[1] = lcolor.G; + sl_ledcolor[2] = lcolor.B; + scolor[0] = '\0'; + for (uint32_t i = 0; i < Light.subtype; i++) { + if (Settings.flag.decimal_text) { + snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", sl_ledcolor[i]); + } else { + snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, sl_ledcolor[i]); + } + } + return scolor; +} + + + + + +void Ws2812ForceSuspend (void) +{ + Ws2812.suspend_update = true; +} + +void Ws2812ForceUpdate (void) +{ + Ws2812.suspend_update = false; + strip->Show(); + Ws2812.show_next = 1; +} + + + +bool Ws2812SetChannels(void) +{ + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); + + return true; +} + +void Ws2812ShowScheme(void) +{ + uint32_t scheme = Settings.light_scheme - Ws2812.scheme_offset; + + switch (scheme) { + case 0: + if ((1 == state_250mS) || (Ws2812.show_next)) { + Ws2812Clock(); + Ws2812.show_next = 0; + } + break; + default: + if (1 == Settings.light_fade) { + Ws2812Gradient(scheme -1); + } else { + Ws2812Bars(scheme -1); + } + Ws2812.show_next = 1; + break; + } +} + +void Ws2812ModuleSelected(void) +{ + if (pin[GPIO_WS2812] < 99) { + + + strip = new NeoPixelBus(WS2812_MAX_LEDS, pin[GPIO_WS2812]); + strip->Begin(); + + Ws2812Clear(); + + Ws2812.scheme_offset = Light.max_scheme +1; + Light.max_scheme += WS2812_SCHEMES; + +#if (USE_WS2812_CTYPE > NEO_3LED) + light_type = LT_RGBW; +#else + light_type = LT_RGB; +#endif + light_flg = XLGT_01; + } +} + + + +void CmndLed(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) { + if (XdrvMailbox.data_len > 0) { + char *p; + uint16_t idx = XdrvMailbox.index; + Ws2812ForceSuspend(); + for (char *color = strtok_r(XdrvMailbox.data, " ", &p); color; color = strtok_r(nullptr, " ", &p)) { + if (LightColorEntry(color, strlen(color))) { + Ws2812SetColor(idx, Light.entry_color[0], Light.entry_color[1], Light.entry_color[2], Light.entry_color[3]); + idx++; + if (idx > Settings.light_pixels) { break; } + } else { + break; + } + } + Ws2812ForceUpdate(); + } + char scolor[LIGHT_COLOR_SIZE]; + ResponseCmndIdxChar(Ws2812GetColor(XdrvMailbox.index, scolor)); + } +} + +void CmndPixels(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { + Settings.light_pixels = XdrvMailbox.payload; + Settings.light_rotation = 0; + Ws2812Clear(); + Light.update = true; + } + ResponseCmndNumber(Settings.light_pixels); +} + +void CmndRotation(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { + Settings.light_rotation = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_rotation); +} + +void CmndWidth(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if (1 == XdrvMailbox.index) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { + Settings.light_width = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.light_width); + } else { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32)) { + Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload; + } + ResponseCmndIdxNumber(Settings.ws_width[XdrvMailbox.index -2]); + } + } +} + + + + + +bool Xlgt01(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Ws2812SetChannels(); + break; + case FUNC_SET_SCHEME: + Ws2812ShowScheme(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kWs2812Commands, Ws2812Command); + break; + case FUNC_MODULE_INIT: + Ws2812ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xlgt_02_my92x1.ino" +# 20 "S:/Development/Tasmota/tasmota/xlgt_02_my92x1.ino" +#ifdef USE_LIGHT +#ifdef USE_MY92X1 + + + + +#define XLGT_02 2 + +struct MY92X1 { + uint8_t pdi_pin = 0; + uint8_t pdcki_pin = 0; + uint8_t model = 0; +} My92x1; + +extern "C" { + void os_delay_us(unsigned int); +} + +void LightDiPulse(uint8_t times) +{ + for (uint32_t i = 0; i < times; i++) { + digitalWrite(My92x1.pdi_pin, HIGH); + digitalWrite(My92x1.pdi_pin, LOW); + } +} + +void LightDckiPulse(uint8_t times) +{ + for (uint32_t i = 0; i < times; i++) { + digitalWrite(My92x1.pdcki_pin, HIGH); + digitalWrite(My92x1.pdcki_pin, LOW); + } +} + +void LightMy92x1Write(uint8_t data) +{ + for (uint32_t i = 0; i < 4; i++) { + digitalWrite(My92x1.pdcki_pin, LOW); + digitalWrite(My92x1.pdi_pin, (data & 0x80)); + digitalWrite(My92x1.pdcki_pin, HIGH); + data = data << 1; + digitalWrite(My92x1.pdi_pin, (data & 0x80)); + digitalWrite(My92x1.pdcki_pin, LOW); + digitalWrite(My92x1.pdi_pin, LOW); + data = data << 1; + } +} + +void LightMy92x1Init(void) +{ + uint8_t chips[3] = { 1, 2, 2 }; + + LightDckiPulse(chips[My92x1.model] * 32); + os_delay_us(12); + + + LightDiPulse(12); + os_delay_us(12); + for (uint32_t n = 0; n < chips[My92x1.model]; n++) { + LightMy92x1Write(0x18); + } + os_delay_us(12); + + + LightDiPulse(16); + os_delay_us(12); +} + +void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) +{ + uint8_t channels[3] = { 4, 6, 6 }; + + uint8_t duty[3][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, + { duty_w, duty_c, 0, duty_g, duty_r, duty_b }, + { duty_r, duty_g, duty_b, duty_w, duty_w, duty_w }}; + + os_delay_us(12); + for (uint32_t channel = 0; channel < channels[My92x1.model]; channel++) { + LightMy92x1Write(duty[My92x1.model][channel]); + } + os_delay_us(12); + LightDiPulse(8); + os_delay_us(12); +} + + + +bool My92x1SetChannels(void) +{ + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); + + return true; +} + +void My92x1ModuleSelected(void) +{ + if ((pin[GPIO_DCKI] < 99) && (pin[GPIO_DI] < 99)) { + My92x1.pdi_pin = pin[GPIO_DI]; + My92x1.pdcki_pin = pin[GPIO_DCKI]; + + pinMode(My92x1.pdi_pin, OUTPUT); + pinMode(My92x1.pdcki_pin, OUTPUT); + digitalWrite(My92x1.pdi_pin, LOW); + digitalWrite(My92x1.pdcki_pin, LOW); + + My92x1.model = 2; + light_type = LT_RGBW; + if (AILIGHT == my_module_type) { + My92x1.model = 0; + + } + else if (SONOFF_B1 == my_module_type) { + My92x1.model = 1; + light_type = LT_RGBWC; + } + + LightMy92x1Init(); + + light_flg = XLGT_02; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: MY29x1 Found")); + } +} + + + + + +bool Xlgt02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = My92x1SetChannels(); + break; + case FUNC_MODULE_INIT: + My92x1ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" +# 20 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" +#ifdef USE_LIGHT +#ifdef USE_SM16716 + + + + + + + +#define XLGT_03 3 + +#define D_LOG_SM16716 "SM16716: " + +struct SM16716 { + uint8_t pin_clk = 0; + uint8_t pin_dat = 0; + uint8_t pin_sel = 0; + bool enabled = false; +} Sm16716; + +void SM16716_SendBit(uint8_t v) +{ + + + + + + digitalWrite(Sm16716.pin_dat, (v != 0) ? HIGH : LOW); + + digitalWrite(Sm16716.pin_clk, HIGH); + + digitalWrite(Sm16716.pin_clk, LOW); +} + +void SM16716_SendByte(uint8_t v) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) { + SM16716_SendBit(v & mask); + } +} + +void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) +{ + if (Sm16716.pin_sel < 99) { + bool should_enable = (duty_r | duty_g | duty_b); + if (!Sm16716.enabled && should_enable) { + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on")); + Sm16716.enabled = true; + digitalWrite(Sm16716.pin_sel, HIGH); + + + delayMicroseconds(1000); + SM16716_Init(); + } + else if (Sm16716.enabled && !should_enable) { + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off")); + Sm16716.enabled = false; + digitalWrite(Sm16716.pin_sel, LOW); + } + } + DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b); + + + SM16716_SendBit(1); + SM16716_SendByte(duty_r); + SM16716_SendByte(duty_g); + SM16716_SendByte(duty_b); + + + + + + SM16716_SendBit(0); + SM16716_SendByte(0); + SM16716_SendByte(0); + SM16716_SendByte(0); +} +# 111 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" +void SM16716_Init(void) +{ + for (uint32_t t_init = 0; t_init < 50; ++t_init) { + SM16716_SendBit(0); + } +} + + + +bool Sm16716SetChannels(void) +{ +# 132 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + + SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); + + return true; +} + +void Sm16716ModuleSelected(void) +{ + if ((pin[GPIO_SM16716_CLK] < 99) && (pin[GPIO_SM16716_DAT] < 99)) { + Sm16716.pin_clk = pin[GPIO_SM16716_CLK]; + Sm16716.pin_dat = pin[GPIO_SM16716_DAT]; + Sm16716.pin_sel = pin[GPIO_SM16716_SEL]; +# 157 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" + pinMode(Sm16716.pin_clk, OUTPUT); + digitalWrite(Sm16716.pin_clk, LOW); + + pinMode(Sm16716.pin_dat, OUTPUT); + digitalWrite(Sm16716.pin_dat, LOW); + + if (Sm16716.pin_sel < 99) { + pinMode(Sm16716.pin_sel, OUTPUT); + digitalWrite(Sm16716.pin_sel, LOW); + + } else { + + SM16716_Init(); + } + + LightPwmOffset(LST_RGB); + light_type += LST_RGB; + light_flg = XLGT_03; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM16716 Found")); + } +} + + + + + +bool Xlgt03(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Sm16716SetChannels(); + break; + case FUNC_MODULE_INIT: + Sm16716ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xlgt_04_sm2135.ino" +# 20 "S:/Development/Tasmota/tasmota/xlgt_04_sm2135.ino" +#ifdef USE_LIGHT +#ifdef USE_SM2135 + + + + + + +#define XLGT_04 4 + +#define SM2135_ADDR_MC 0xC0 +#define SM2135_ADDR_CH 0xC1 +#define SM2135_ADDR_R 0xC2 +#define SM2135_ADDR_G 0xC3 +#define SM2135_ADDR_B 0xC4 +#define SM2135_ADDR_C 0xC5 +#define SM2135_ADDR_W 0xC6 + +#define SM2135_RGB 0x00 +#define SM2135_CW 0x80 + +#define SM2135_10MA 0x00 +#define SM2135_15MA 0x01 +#define SM2135_20MA 0x02 +#define SM2135_25MA 0x03 +#define SM2135_30MA 0x04 +#define SM2135_35MA 0x05 +#define SM2135_40MA 0x06 +#define SM2135_45MA 0x07 +#define SM2135_50MA 0x08 +#define SM2135_55MA 0x09 +#define SM2135_60MA 0x0A + + +const uint8_t SM2135_CURRENT = (SM2135_20MA << 4) | SM2135_15MA; + +struct SM2135 { + uint8_t clk = 0; + uint8_t data = 0; +} Sm2135; + +uint8_t Sm2135Write(uint8_t data) +{ + for (uint32_t i = 0; i < 8; i++) { + digitalWrite(Sm2135.clk, LOW); + digitalWrite(Sm2135.data, (data & 0x80)); + digitalWrite(Sm2135.clk, HIGH); + data = data << 1; + } + digitalWrite(Sm2135.clk, LOW); + digitalWrite(Sm2135.data, HIGH); + pinMode(Sm2135.data, INPUT); + digitalWrite(Sm2135.clk, HIGH); + uint8_t ack = digitalRead(Sm2135.data); + pinMode(Sm2135.data, OUTPUT); + return ack; +} + +void Sm2135Send(uint8_t *buffer, uint8_t size) +{ + digitalWrite(Sm2135.data, LOW); + for (uint32_t i = 0; i < size; i++) { + Sm2135Write(buffer[i]); + } + digitalWrite(Sm2135.clk, LOW); + digitalWrite(Sm2135.clk, HIGH); + digitalWrite(Sm2135.data, HIGH); +} + + + +bool Sm2135SetChannels(void) +{ + uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; + uint8_t data[6]; + + if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) { +# 106 "S:/Development/Tasmota/tasmota/xlgt_04_sm2135.ino" + data[0] = SM2135_ADDR_MC; + data[1] = SM2135_CURRENT; + data[2] = SM2135_CW; + Sm2135Send(data, 3); + delay(1); + data[0] = SM2135_ADDR_C; + data[1] = cur_col[4]; + data[2] = cur_col[3]; + Sm2135Send(data, 3); + } else { + + + + + + + + data[0] = SM2135_ADDR_MC; + data[1] = SM2135_CURRENT; + data[2] = SM2135_RGB; + data[3] = cur_col[1]; + data[4] = cur_col[0]; + data[5] = cur_col[2]; + Sm2135Send(data, 6); + } + + return true; +} + +void Sm2135ModuleSelected(void) +{ + if ((pin[GPIO_SM2135_CLK] < 99) && (pin[GPIO_SM2135_DAT] < 99)) { + Sm2135.clk = pin[GPIO_SM2135_CLK]; + Sm2135.data = pin[GPIO_SM2135_DAT]; + + pinMode(Sm2135.data, OUTPUT); + digitalWrite(Sm2135.data, HIGH); + pinMode(Sm2135.clk, OUTPUT); + digitalWrite(Sm2135.clk, HIGH); + + light_type = LT_RGBWC; + light_flg = XLGT_04; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 Found")); + } +} + + + + + +bool Xlgt04(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SET_CHANNELS: + result = Sm2135SetChannels(); + break; + case FUNC_MODULE_INIT: + Sm2135ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" +# 20 "S:/Development/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" +#ifdef USE_LIGHT +#ifdef USE_SONOFF_L1 + + + + +#define XLGT_05 5 + +#define SONOFF_L1_BUFFER_SIZE 140 + +#define SONOFF_L1_MODE_COLORFUL 1 +#define SONOFF_L1_MODE_COLORFUL_GRADIENT 2 +#define SONOFF_L1_MODE_COLORFUL_BREATH 3 +#define SONOFF_L1_MODE_DIY_GRADIENT 4 +#define SONOFF_L1_MODE_DIY_PULSE 5 +#define SONOFF_L1_MODE_DIY_BREATH 6 +#define SONOFF_L1_MODE_DIY_STROBE 7 +#define SONOFF_L1_MODE_RGB_GRADIENT 8 +#define SONOFF_L1_MODE_RGB_PULSE 9 +#define SONOFF_L1_MODE_RGB_BREATH 10 +#define SONOFF_L1_MODE_RGB_STROBE 11 +#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 + +struct SNFL1 { + uint32_t unlock = 0; + bool receive_ready = true; +} Snfl1; + + + +void SnfL1Send(const char *buffer) +{ + + + Serial.print(buffer); + Serial.write(0x1B); + Serial.flush(); +} + +void SnfL1SerialSendOk(void) +{ + char buffer[16]; + snprintf_P(buffer, sizeof(buffer), PSTR("AT+SEND=ok")); + + SnfL1Send(buffer); +} + +bool SnfL1SerialInput(void) +{ + if (serial_in_byte != 0x1B) { + if (serial_in_byte_counter >= 140) { + serial_in_byte_counter = 0; + } + if (serial_in_byte_counter || (!serial_in_byte_counter && ('A' == serial_in_byte))) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + } else { + serial_in_buffer[serial_in_byte_counter++] = 0x00; + + + + + + + if (!strncmp(serial_in_buffer +3, "RESULT", 6)) { + Snfl1.receive_ready = true; + } + else if (!strncmp(serial_in_buffer +3, "UPDATE", 6)) { + char cmnd_dimmer[20]; + char cmnd_color[20]; + char *end_str; + char *string = serial_in_buffer +10; + char *token = strtok_r(string, ",", &end_str); + + bool color_updated[3] = { false, false, false }; + uint8_t current_color[3]; + memcpy(current_color, Settings.light_color, 3); + + bool switch_state = false; + bool is_power_change = false; + bool is_color_change = false; + bool is_brightness_change = false; + + while (token != nullptr) { + char* end_token; + char* token2 = strtok_r(token, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); + + if (!strncmp(token2, "\"sequence\"", 10)) { + + + + token = nullptr; + } + + else if (!strncmp(token2, "\"switch\"", 8)) { + switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; + + + + is_power_change = (switch_state != Light.power); + } + + else if (!strncmp(token2, "\"color", 6)) { + char color_channel_name = token2[6]; + int color_index; + switch(color_channel_name) + { + case 'R': color_index = 0; + break; + case 'G': color_index = 1; + break; + case 'B': color_index = 2; + break; + } + int color_value = atoi(token3); + current_color[color_index] = color_value; + color_updated[color_index] = true; + + bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; + if (all_color_channels_updated) { + + + + + + is_color_change = (Light.power && (memcmp(current_color, Settings.light_color, 3) != 0)); + } + snprintf_P(cmnd_color, sizeof(cmnd_color), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), current_color[0], current_color[1], current_color[2]); + } + + else if (!strncmp(token2, "\"bright\"", 8)) { + uint8_t dimmer = atoi(token3); + + + + is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings.light_dimmer)); + snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer); + } + + token = strtok_r(nullptr, ",", &end_str); + } + + if (is_power_change) { + if (Settings.light_scheme > 0) { + if (!switch_state) { + char cmnd_scheme[20]; + snprintf_P(cmnd_scheme, sizeof(cmnd_scheme), PSTR(D_CMND_SCHEME " 0")); + ExecuteCommand(cmnd_scheme, SRC_SWITCH); + } + } else { + ExecuteCommandPower(1, switch_state, SRC_SWITCH); + } + } + else if (is_brightness_change) { + ExecuteCommand(cmnd_dimmer, SRC_SWITCH); + } + else if (Light.power && is_color_change) { + if (0 == Settings.light_scheme) { + if (Settings.light_fade) { + char cmnd_fade[20]; + snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_FADE " 0")); + ExecuteCommand(cmnd_fade, SRC_SWITCH); + } + ExecuteCommand(cmnd_color, SRC_SWITCH); + } + } + } + + SnfL1SerialSendOk(); + + return true; + } + serial_in_byte = 0; + return false; +} + + + +bool SnfL1SetChannels(void) +{ + if (Snfl1.receive_ready || TimeReached(Snfl1.unlock)) { + + uint8_t *scale_col = (uint8_t*)XdrvMailbox.topic; + + char buffer[140]; + snprintf_P(buffer, sizeof(buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"light_type\":1,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"bright\":%d,\"mode\":%d"), + LocalTime(), millis()%1000, + Light.power ? "on" : "off", + scale_col[0], scale_col[1], scale_col[2], + light_state.getDimmer(), + SONOFF_L1_MODE_COLORFUL); + + SnfL1Send(buffer); + + Snfl1.unlock = millis() + 500; + Snfl1.receive_ready = false; + } + return true; +} + +void SnfL1ModuleSelected(void) +{ + if (SONOFF_L1 == my_module_type) { + if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { + SetSerial(19200, TS_SERIAL_8N1); + + light_type = LT_RGB; + light_flg = XLGT_05; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); + } + } +} + + + + + +bool Xlgt05(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_SERIAL: + result = SnfL1SerialInput(); + break; + case FUNC_SET_CHANNELS: + result = SnfL1SetChannels(); + break; + case FUNC_MODULE_INIT: + SnfL1ModuleSelected(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xlgt_interface.ino" +# 20 "S:/Development/Tasmota/tasmota/xlgt_interface.ino" +#ifdef USE_LIGHT + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xlgt_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xlgt_func_ptr[])(uint8_t) = { +#endif + +#ifdef XLGT_01 + &Xlgt01, +#endif + +#ifdef XLGT_02 + &Xlgt02, +#endif + +#ifdef XLGT_03 + &Xlgt03, +#endif + +#ifdef XLGT_04 + &Xlgt04, +#endif + +#ifdef XLGT_05 + &Xlgt05, +#endif + +#ifdef XLGT_06 + &Xlgt06, +#endif + +#ifdef XLGT_07 + &Xlgt07, +#endif + +#ifdef XLGT_08 + &Xlgt08, +#endif + +#ifdef XLGT_09 + &Xlgt09, +#endif + +#ifdef XLGT_10 + &Xlgt10, +#endif + +#ifdef XLGT_11 + &Xlgt11, +#endif + +#ifdef XLGT_12 + &Xlgt12, +#endif + +#ifdef XLGT_13 + &Xlgt13, +#endif + +#ifdef XLGT_14 + &Xlgt14, +#endif + +#ifdef XLGT_15 + &Xlgt15, +#endif + +#ifdef XLGT_16 + &Xlgt16 +#endif +}; + +const uint8_t xlgt_present = sizeof(xlgt_func_ptr) / sizeof(xlgt_func_ptr[0]); + +uint8_t xlgt_active = 0; + +bool XlgtCall(uint8_t function) +{ + DEBUG_TRACE_LOG(PSTR("LGT: %d"), function); + + if (FUNC_MODULE_INIT == function) { + for (uint32_t x = 0; x < xlgt_present; x++) { + xlgt_func_ptr[x](function); + if (light_flg) { + xlgt_active = x; + return true; + } + } + } + else if (light_flg) { + return xlgt_func_ptr[xlgt_active](function); + } + return false; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_01_hlw8012.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_01_hlw8012.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_HLW8012 + + + + + + +#define XNRG_01 1 + + +#define HLW_PREF 10000 +#define HLW_UREF 2200 +#define HLW_IREF 4545 + + +#define HJL_PREF 1362 +#define HJL_UREF 822 +#define HJL_IREF 3300 + +#define HLW_POWER_PROBE_TIME 10 +#define HLW_SAMPLE_COUNT 10 + + + +struct HLW { +#ifdef HLW_DEBUG + unsigned long debug[HLW_SAMPLE_COUNT]; +#endif + unsigned long cf_pulse_length = 0; + unsigned long cf_pulse_last_time = 0; + unsigned long cf_power_pulse_length = 0; + + unsigned long cf1_pulse_length = 0; + unsigned long cf1_pulse_last_time = 0; + unsigned long cf1_summed_pulse_length = 0; + unsigned long cf1_pulse_counter = 0; + unsigned long cf1_voltage_pulse_length = 0; + unsigned long cf1_current_pulse_length = 0; + + unsigned long energy_period_counter = 0; + + unsigned long power_ratio = 0; + unsigned long voltage_ratio = 0; + unsigned long current_ratio = 0; + + uint8_t model_type = 0; + uint8_t cf1_timer = 0; + uint8_t power_retry = 0; + bool select_ui_flag = false; + bool ui_flag = true; + bool load_off = true; +} Hlw; + + +#ifndef USE_WS2812_DMA +void HlwCfInterrupt(void) ICACHE_RAM_ATTR; +void HlwCf1Interrupt(void) ICACHE_RAM_ATTR; +#endif + +void HlwCfInterrupt(void) +{ + unsigned long us = micros(); + + if (Hlw.load_off) { + Hlw.cf_pulse_last_time = us; + Hlw.load_off = false; + } else { + Hlw.cf_pulse_length = us - Hlw.cf_pulse_last_time; + Hlw.cf_pulse_last_time = us; + Hlw.energy_period_counter++; + } + Energy.data_valid[0] = 0; +} + +void HlwCf1Interrupt(void) +{ + unsigned long us = micros(); + + Hlw.cf1_pulse_length = us - Hlw.cf1_pulse_last_time; + Hlw.cf1_pulse_last_time = us; + if ((Hlw.cf1_timer > 2) && (Hlw.cf1_timer < 8)) { + Hlw.cf1_summed_pulse_length += Hlw.cf1_pulse_length; +#ifdef HLW_DEBUG + Hlw.debug[Hlw.cf1_pulse_counter] = Hlw.cf1_pulse_length; +#endif + Hlw.cf1_pulse_counter++; + if (HLW_SAMPLE_COUNT == Hlw.cf1_pulse_counter) { + Hlw.cf1_timer = 8; + } + } + Energy.data_valid[0] = 0; +} + + + +void HlwEvery200ms(void) +{ + unsigned long cf1_pulse_length = 0; + unsigned long hlw_w = 0; + unsigned long hlw_u = 0; + unsigned long hlw_i = 0; + + if (micros() - Hlw.cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { + Hlw.cf_pulse_length = 0; + Hlw.load_off = true; + } + Hlw.cf_power_pulse_length = Hlw.cf_pulse_length; + + if (Hlw.cf_power_pulse_length && Energy.power_on && !Hlw.load_off) { + hlw_w = (Hlw.power_ratio * Settings.energy_power_calibration) / Hlw.cf_power_pulse_length ; + Energy.active_power[0] = (float)hlw_w / 10; + Hlw.power_retry = 1; + } else { + if (Hlw.power_retry) { + Hlw.power_retry--; + } else { + Energy.active_power[0] = 0; + } + } + + if (pin[GPIO_NRG_CF1] < 99) { + Hlw.cf1_timer++; + if (Hlw.cf1_timer >= 8) { + Hlw.cf1_timer = 0; + Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; + DigitalWrite(GPIO_NRG_SEL, Hlw.select_ui_flag); + + if (Hlw.cf1_pulse_counter) { + cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter; + } + +#ifdef HLW_DEBUG + + char stemp[100]; + stemp[0] = '\0'; + for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { + snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, Hlw.debug[i]); + } + for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { + for (uint32_t j = i + 1; j < Hlw.cf1_pulse_counter; j++) { + if (Hlw.debug[i] > Hlw.debug[j]) { + std::swap(Hlw.debug[i], Hlw.debug[j]); + } + } + } + unsigned long median = Hlw.debug[(Hlw.cf1_pulse_counter +1) / 2]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), + Hlw.cf_power_pulse_length , Hlw.select_ui_flag, Hlw.cf1_pulse_counter, stemp, Hlw.cf1_summed_pulse_length, cf1_pulse_length, median); +#endif + + if (Hlw.select_ui_flag == Hlw.ui_flag) { + Hlw.cf1_voltage_pulse_length = cf1_pulse_length; + + if (Hlw.cf1_voltage_pulse_length && Energy.power_on) { + hlw_u = (Hlw.voltage_ratio * Settings.energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; + Energy.voltage[0] = (float)hlw_u / 10; + } else { + Energy.voltage[0] = 0; + } + + } else { + Hlw.cf1_current_pulse_length = cf1_pulse_length; + + if (Hlw.cf1_current_pulse_length && Energy.active_power[0]) { + hlw_i = (Hlw.current_ratio * Settings.energy_current_calibration) / Hlw.cf1_current_pulse_length; + Energy.current[0] = (float)hlw_i / 1000; + } else { + Energy.current[0] = 0; + } + + } + Hlw.cf1_summed_pulse_length = 0; + Hlw.cf1_pulse_counter = 0; + } + } +} + +void HlwEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Hlw.cf1_voltage_pulse_length = 0; + Hlw.cf1_current_pulse_length = 0; + Hlw.cf_power_pulse_length = 0; + } else { + unsigned long hlw_len; + + if (Hlw.energy_period_counter) { + hlw_len = 10000 / Hlw.energy_period_counter; + Hlw.energy_period_counter = 0; + if (hlw_len) { + Energy.kWhtoday_delta += ((Hlw.power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; + EnergyUpdateToday(); + } + } + } +} + +void HlwSnsInit(void) +{ + if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { + Settings.energy_power_calibration = HLW_PREF_PULSE; + Settings.energy_voltage_calibration = HLW_UREF_PULSE; + Settings.energy_current_calibration = HLW_IREF_PULSE; + } + + if (Hlw.model_type) { + Hlw.power_ratio = HJL_PREF; + Hlw.voltage_ratio = HJL_UREF; + Hlw.current_ratio = HJL_IREF; + } else { + Hlw.power_ratio = HLW_PREF; + Hlw.voltage_ratio = HLW_UREF; + Hlw.current_ratio = HLW_IREF; + } + + if (pin[GPIO_NRG_SEL] < 99) { + pinMode(pin[GPIO_NRG_SEL], OUTPUT); + digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); + } + if (pin[GPIO_NRG_CF1] < 99) { + pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); + attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); + } + pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); + attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); +} + +void HlwDrvInit(void) +{ + Hlw.model_type = 0; + if (pin[GPIO_HJL_CF] < 99) { + pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF]; + pin[GPIO_HJL_CF] = 99; + Hlw.model_type = 1; + } + + if (pin[GPIO_HLW_CF] < 99) { + + Hlw.ui_flag = true; + if (pin[GPIO_NRG_SEL_INV] < 99) { + pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; + pin[GPIO_NRG_SEL_INV] = 99; + Hlw.ui_flag = false; + } + + if (pin[GPIO_NRG_CF1] < 99) { + if (99 == pin[GPIO_NRG_SEL]) { + Energy.current_available = false; + } + } else { + Energy.current_available = false; + Energy.voltage_available = false; + } + + energy_flg = XNRG_01; + } +} + +bool HlwCommand(void) +{ + bool serviced = true; + + if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) { + + } + else if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) { + Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio; + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) { + Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio; + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) { + Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg01(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_200_MSECOND: + HlwEvery200ms(); + break; + case FUNC_ENERGY_EVERY_SECOND: + HlwEverySecond(); + break; + case FUNC_COMMAND: + result = HlwCommand(); + break; + case FUNC_INIT: + HlwSnsInit(); + break; + case FUNC_PRE_INIT: + HlwDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_02_cse7766.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_02_cse7766.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_CSE7766 + + + + + + + +#define XNRG_02 2 + +#define CSE_MAX_INVALID_POWER 128 + +#define CSE_NOT_CALIBRATED 0xAA + +#define CSE_PULSES_NOT_INITIALIZED -1 + +#define CSE_PREF 1000 +#define CSE_UREF 100 + +#define CSE_BUFFER_SIZE 25 + +#include + +TasmotaSerial *CseSerial = nullptr; + +struct CSE { + long voltage_cycle = 0; + long current_cycle = 0; + long power_cycle = 0; + long power_cycle_first = 0; + long cf_pulses = 0; + long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + + int byte_counter = 0; + uint8_t *rx_buffer = nullptr; + uint8_t power_invalid = 0; + bool received = false; +} Cse; + +void CseReceived(void) +{ + + + + + + + uint8_t header = Cse.rx_buffer[0]; + if ((header & 0xFC) == 0xFC) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); + return; + } + + + if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { + long voltage_coefficient = 191200; + if (CSE_NOT_CALIBRATED != header) { + voltage_coefficient = Cse.rx_buffer[2] << 16 | Cse.rx_buffer[3] << 8 | Cse.rx_buffer[4]; + } + Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; + } + if (HLW_IREF_PULSE == Settings.energy_current_calibration) { + long current_coefficient = 16140; + if (CSE_NOT_CALIBRATED != header) { + current_coefficient = Cse.rx_buffer[8] << 16 | Cse.rx_buffer[9] << 8 | Cse.rx_buffer[10]; + } + Settings.energy_current_calibration = current_coefficient; + } + if (HLW_PREF_PULSE == Settings.energy_power_calibration) { + long power_coefficient = 5364000; + if (CSE_NOT_CALIBRATED != header) { + power_coefficient = Cse.rx_buffer[14] << 16 | Cse.rx_buffer[15] << 8 | Cse.rx_buffer[16]; + } + Settings.energy_power_calibration = power_coefficient / CSE_PREF; + } + + uint8_t adjustement = Cse.rx_buffer[20]; + Cse.voltage_cycle = Cse.rx_buffer[5] << 16 | Cse.rx_buffer[6] << 8 | Cse.rx_buffer[7]; + Cse.current_cycle = Cse.rx_buffer[11] << 16 | Cse.rx_buffer[12] << 8 | Cse.rx_buffer[13]; + Cse.power_cycle = Cse.rx_buffer[17] << 16 | Cse.rx_buffer[18] << 8 | Cse.rx_buffer[19]; + Cse.cf_pulses = Cse.rx_buffer[21] << 8 | Cse.rx_buffer[22]; + + if (Energy.power_on) { + if (adjustement & 0x40) { + Energy.voltage[0] = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle; + } + if (adjustement & 0x10) { + Cse.power_invalid = 0; + if ((header & 0xF2) == 0xF2) { + Energy.active_power[0] = 0; + } else { + if (0 == Cse.power_cycle_first) { Cse.power_cycle_first = Cse.power_cycle; } + if (Cse.power_cycle_first != Cse.power_cycle) { + Cse.power_cycle_first = -1; + Energy.active_power[0] = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle; + } else { + Energy.active_power[0] = 0; + } + } + } else { + if (Cse.power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { + Cse.power_invalid++; + } else { + Cse.power_cycle_first = 0; + Energy.active_power[0] = 0; + } + } + if (adjustement & 0x20) { + if (0 == Energy.active_power[0]) { + Energy.current[0] = 0; + } else { + Energy.current[0] = (float)Settings.energy_current_calibration / (float)Cse.current_cycle; + } + } + } else { + Cse.power_cycle_first = 0; + Energy.voltage[0] = 0; + Energy.active_power[0] = 0; + Energy.current[0] = 0; + } +} + +bool CseSerialInput(void) +{ + while (CseSerial->available()) { + yield(); + uint8_t serial_in_byte = CseSerial->read(); + + if (Cse.received) { + Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; + if (24 == Cse.byte_counter) { + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Cse.rx_buffer, 24); + + uint8_t checksum = 0; + for (uint32_t i = 2; i < 23; i++) { checksum += Cse.rx_buffer[i]; } + if (checksum == Cse.rx_buffer[23]) { + Energy.data_valid[0] = 0; + CseReceived(); + Cse.received = false; + return true; + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); + do { + memmove(Cse.rx_buffer, Cse.rx_buffer +1, 24); + Cse.byte_counter--; + } while ((Cse.byte_counter > 2) && (0x5A != Cse.rx_buffer[1])); + if (0x5A != Cse.rx_buffer[1]) { + Cse.received = false; + Cse.byte_counter = 0; + } + } + } + } else { + if ((0x5A == serial_in_byte) && (1 == Cse.byte_counter)) { + Cse.received = true; + } else { + Cse.byte_counter = 0; + } + Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; + } + } +} + + + +void CseEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Cse.voltage_cycle = 0; + Cse.current_cycle = 0; + Cse.power_cycle = 0; + } else { + long cf_frequency = 0; + + if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) { + Cse.cf_pulses_last_time = Cse.cf_pulses; + } else { + if (Cse.cf_pulses < Cse.cf_pulses_last_time) { + cf_frequency = (65536 - Cse.cf_pulses_last_time) + Cse.cf_pulses; + } else { + cf_frequency = Cse.cf_pulses - Cse.cf_pulses_last_time; + } + if (cf_frequency && Energy.active_power[0]) { + unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; + + + + if (delta <= (4000*100/36) * 10 ) { + Cse.cf_pulses_last_time = Cse.cf_pulses; + Energy.kWhtoday_delta += delta; + } + else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow")); + Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; + } + EnergyUpdateToday(); + } + } + } +} + +void CseSnsInit(void) +{ + + + CseSerial = new TasmotaSerial(pin[GPIO_CSE7766_RX], -1, 1); + if (CseSerial->begin(4800, 2)) { + if (CseSerial->hardwareSerial()) { + SetSerial(4800, TS_SERIAL_8E1); + ClaimSerial(); + } + if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { + Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; + } + Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER]; + } else { + energy_flg = ENERGY_NONE; + } +} + +void CseDrvInit(void) +{ + Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); + if (Cse.rx_buffer != nullptr) { + + if (pin[GPIO_CSE7766_RX] < 99) { + energy_flg = XNRG_02; + } + } +} + +bool CseCommand(void) +{ + bool serviced = true; + + if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.power_cycle) { + Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF; + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.voltage_cycle) { + Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF; + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Cse.current_cycle) { + Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + if (CseSerial) { CseSerialInput(); } + break; + case FUNC_ENERGY_EVERY_SECOND: + CseEverySecond(); + break; + case FUNC_COMMAND: + result = CseCommand(); + break; + case FUNC_INIT: + CseSnsInit(); + break; + case FUNC_PRE_INIT: + CseDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_03_pzem004t.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_03_pzem004t.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM004T +# 31 "S:/Development/Tasmota/tasmota/xnrg_03_pzem004t.ino" +#define XNRG_03 3 + +const uint32_t PZEM_STABILIZE = 30; + +#include + +TasmotaSerial *PzemSerial = nullptr; + +#define PZEM_VOLTAGE (uint8_t)0xB0 +#define RESP_VOLTAGE (uint8_t)0xA0 + +#define PZEM_CURRENT (uint8_t)0xB1 +#define RESP_CURRENT (uint8_t)0xA1 + +#define PZEM_POWER (uint8_t)0xB2 +#define RESP_POWER (uint8_t)0xA2 + +#define PZEM_ENERGY (uint8_t)0xB3 +#define RESP_ENERGY (uint8_t)0xA3 + +#define PZEM_SET_ADDRESS (uint8_t)0xB4 +#define RESP_SET_ADDRESS (uint8_t)0xA4 + +#define PZEM_POWER_ALARM (uint8_t)0xB5 +#define RESP_POWER_ALARM (uint8_t)0xA5 + +#define PZEM_DEFAULT_READ_TIMEOUT 500 + + + +struct PZEM { + float energy = 0; + float last_energy = 0; + uint8_t send_retry = 0; + uint8_t read_state = 0; + uint8_t phase = 0; + uint8_t address = 0; +} Pzem; + +struct PZEMCommand { + uint8_t command; + uint8_t addr[4]; + uint8_t data; + uint8_t crc; +}; + +uint8_t PzemCrc(uint8_t *data) +{ + uint16_t crc = 0; + for (uint32_t i = 0; i < sizeof(PZEMCommand) -1; i++) { + crc += *data++; + } + return (uint8_t)(crc & 0xFF); +} + +void PzemSend(uint8_t cmd) +{ + PZEMCommand pzem; + + pzem.command = cmd; + pzem.addr[0] = 192; + pzem.addr[1] = 168; + pzem.addr[2] = 1; + pzem.addr[3] = ((PZEM_SET_ADDRESS == cmd) && Pzem.address) ? Pzem.address : 1 + Pzem.phase; + pzem.data = 0; + + uint8_t *bytes = (uint8_t*)&pzem; + pzem.crc = PzemCrc(bytes); + + PzemSerial->flush(); + PzemSerial->write(bytes, sizeof(pzem)); + + Pzem.address = 0; +} + +bool PzemReceiveReady(void) +{ + return PzemSerial->available() >= (int)sizeof(PZEMCommand); +} + +bool PzemRecieve(uint8_t resp, float *data) +{ +# 124 "S:/Development/Tasmota/tasmota/xnrg_03_pzem004t.ino" + uint8_t buffer[sizeof(PZEMCommand)] = { 0 }; + + unsigned long start = millis(); + uint8_t len = 0; + while ((len < sizeof(PZEMCommand)) && (millis() - start < PZEM_DEFAULT_READ_TIMEOUT)) { + if (PzemSerial->available() > 0) { + uint8_t c = (uint8_t)PzemSerial->read(); + if (!len && ((c & 0xF8) != 0xA0)) { + continue; + } + buffer[len++] = c; + } + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, len); + + if (len != sizeof(PZEMCommand)) { + + return false; + } + if (buffer[6] != PzemCrc(buffer)) { + + return false; + } + if (buffer[0] != resp) { + + return false; + } + + switch (resp) { + case RESP_VOLTAGE: + *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 10.0); + break; + case RESP_CURRENT: + *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 100.0); + break; + case RESP_POWER: + *data = (float)(buffer[1] << 8) + buffer[2]; + break; + case RESP_ENERGY: + *data = (float)((uint32_t)buffer[1] << 16) + ((uint16_t)buffer[2] << 8) + buffer[3]; + break; + } + return true; +} + + + +const uint8_t pzem_commands[] { PZEM_SET_ADDRESS, PZEM_VOLTAGE, PZEM_CURRENT, PZEM_POWER, PZEM_ENERGY }; +const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, RESP_POWER, RESP_ENERGY }; + +void PzemEvery250ms(void) +{ + bool data_ready = PzemReceiveReady(); + + if (data_ready) { + float value = 0; + if (PzemRecieve(pzem_responses[Pzem.read_state], &value)) { + Energy.data_valid[Pzem.phase] = 0; + switch (Pzem.read_state) { + case 1: + Energy.voltage[Pzem.phase] = value; + break; + case 2: + Energy.current[Pzem.phase] = value; + break; + case 3: + Energy.active_power[Pzem.phase] = value; + break; + case 4: + Pzem.energy += value; + if (Pzem.phase == Energy.phase_count -1) { + if (Pzem.energy > Pzem.last_energy) { + if (uptime > PZEM_STABILIZE) { + EnergyUpdateTotal(Pzem.energy, false); + } + Pzem.last_energy = Pzem.energy; + } + Pzem.energy = 0; + } + break; + } + Pzem.read_state++; + if (5 == Pzem.read_state) { + Pzem.read_state = 1; + } + + + } + } + + if (0 == Pzem.send_retry || data_ready) { + if (1 == Pzem.read_state) { + if (0 == Pzem.phase) { + Pzem.phase = Energy.phase_count -1; + } else { + Pzem.phase--; + } + + + } + + if (Pzem.address) { + Pzem.read_state = 0; + } + + Pzem.send_retry = 5; + PzemSend(pzem_commands[Pzem.read_state]); + } + else { + Pzem.send_retry--; + if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < PZEM_STABILIZE)) { + Energy.phase_count--; + } + } +} + +void PzemSnsInit(void) +{ + + PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); + if (PzemSerial->begin(9600)) { + if (PzemSerial->hardwareSerial()) { + ClaimSerial(); + } + Energy.phase_count = 3; + Pzem.phase = 0; + Pzem.read_state = 1; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDrvInit(void) +{ + if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_03; + } +} + +bool PzemCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { + Pzem.address = XdrvMailbox.payload; + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg03(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (PzemSerial && (uptime > 4)) { PzemEvery250ms(); } + break; + case FUNC_COMMAND: + result = PzemCommand(); + break; + case FUNC_INIT: + PzemSnsInit(); + break; + case FUNC_PRE_INIT: + PzemDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_04_mcp39f501.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_04_mcp39f501.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_MCP39F501 + + + + + + + +#define XNRG_04 4 + +#define MCP_BAUDRATE 4800 +#define MCP_TIMEOUT 4 +#define MCP_CALIBRATION_TIMEOUT 2 + +#define MCP_CALIBRATE_POWER 0x001 +#define MCP_CALIBRATE_VOLTAGE 0x002 +#define MCP_CALIBRATE_CURRENT 0x004 +#define MCP_CALIBRATE_FREQUENCY 0x008 +#define MCP_SINGLE_WIRE_FLAG 0x100 + +#define MCP_START_FRAME 0xA5 +#define MCP_ACK_FRAME 0x06 +#define MCP_ERROR_NAK 0x15 +#define MCP_ERROR_CRC 0x51 + +#define MCP_SINGLE_WIRE 0xAB + +#define MCP_SET_ADDRESS 0x41 + +#define MCP_READ 0x4E +#define MCP_READ_16 0x52 +#define MCP_READ_32 0x44 + +#define MCP_WRITE 0x4D +#define MCP_WRITE_16 0x57 +#define MCP_WRITE_32 0x45 + +#define MCP_SAVE_REGISTERS 0x53 + +#define MCP_CALIBRATION_BASE 0x0028 +#define MCP_CALIBRATION_LEN 52 + +#define MCP_FREQUENCY_REF_BASE 0x0094 +#define MCP_FREQUENCY_GAIN_BASE 0x00AE +#define MCP_FREQUENCY_LEN 4 + +#define MCP_BUFFER_SIZE 60 + +#include +TasmotaSerial *McpSerial = nullptr; + +typedef struct mcp_cal_registers_type { + uint16_t gain_current_rms; + uint16_t gain_voltage_rms; + uint16_t gain_active_power; + uint16_t gain_reactive_power; + sint32_t offset_current_rms; + sint32_t offset_active_power; + sint32_t offset_reactive_power; + sint16_t dc_offset_current; + sint16_t phase_compensation; + uint16_t apparent_power_divisor; + + uint32_t system_configuration; + uint16_t dio_configuration; + uint32_t range; + + uint32_t calibration_current; + uint16_t calibration_voltage; + uint32_t calibration_active_power; + uint32_t calibration_reactive_power; + uint16_t accumulation_interval; +} mcp_cal_registers_type; + +char *mcp_buffer = nullptr; +unsigned long mcp_window = 0; +unsigned long mcp_kWhcounter = 0; +uint32_t mcp_system_configuration = 0x03000000; +uint32_t mcp_active_power; + + +uint32_t mcp_current_rms; +uint16_t mcp_voltage_rms; +uint16_t mcp_line_frequency; + +uint8_t mcp_address = 0; +uint8_t mcp_calibration_active = 0; +uint8_t mcp_init = 0; +uint8_t mcp_timeout = 0; +uint8_t mcp_calibrate = 0; +uint8_t mcp_byte_counter = 0; + + + + + + +uint8_t McpChecksum(uint8_t *data) +{ + uint8_t checksum = 0; + uint8_t offset = 0; + uint8_t len = data[1] -1; + + for (uint32_t i = offset; i < len; i++) { checksum += data[i]; } + return checksum; +} + +unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) +{ + unsigned long result = 0; + unsigned long pow = 1; + + for (uint32_t i = 0; i < size; i++) { + result = result + (uint8_t)data[offset + i] * pow; + pow = pow * 256; + } + return result; +} + +void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) +{ + for (uint32_t i = 0; i < size; i++) { + data[offset + i] = ((value >> (i * 8)) & 0xFF); + } +} + +void McpSend(uint8_t *data) +{ + if (mcp_timeout) { return; } + mcp_timeout = MCP_TIMEOUT; + + data[0] = MCP_START_FRAME; + data[data[1] -1] = McpChecksum(data); + + + + for (uint32_t i = 0; i < data[1]; i++) { + McpSerial->write(data[i]); + } +} + + + +void McpGetAddress(void) +{ + uint8_t data[] = { MCP_START_FRAME, 7, MCP_SET_ADDRESS, 0x00, 0x26, MCP_READ_16, 0x00 }; + + McpSend(data); +} + +void McpAddressReceive(void) +{ + + mcp_address = mcp_buffer[3]; +} + + + +void McpGetCalibration(void) +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; + + uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, (MCP_CALIBRATION_BASE >> 8) & 0xFF, MCP_CALIBRATION_BASE & 0xFF, MCP_READ, MCP_CALIBRATION_LEN, 0x00 }; + + McpSend(data); +} + +void McpParseCalibration(void) +{ + bool action = false; + mcp_cal_registers_type cal_registers; + + + cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); + cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); + cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); + cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); + cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); + cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); + cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); + cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); + cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); + cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); + + cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); + cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); + cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); + + cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); + cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); + cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); + cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); + cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); + + if (mcp_calibrate & MCP_CALIBRATE_POWER) { + cal_registers.calibration_active_power = Settings.energy_power_calibration; + if (McpCalibrationCalc(&cal_registers, 16)) { action = true; } + } + if (mcp_calibrate & MCP_CALIBRATE_VOLTAGE) { + cal_registers.calibration_voltage = Settings.energy_voltage_calibration; + if (McpCalibrationCalc(&cal_registers, 0)) { action = true; } + } + if (mcp_calibrate & MCP_CALIBRATE_CURRENT) { + cal_registers.calibration_current = Settings.energy_current_calibration; + if (McpCalibrationCalc(&cal_registers, 8)) { action = true; } + } + mcp_timeout = 0; + if (action) { McpSetCalibration(&cal_registers); } + + mcp_calibrate = 0; + + Settings.energy_power_calibration = cal_registers.calibration_active_power; + Settings.energy_voltage_calibration = cal_registers.calibration_voltage; + Settings.energy_current_calibration = cal_registers.calibration_current; + + mcp_system_configuration = cal_registers.system_configuration; + + if (mcp_system_configuration & MCP_SINGLE_WIRE_FLAG) { + mcp_system_configuration &= ~MCP_SINGLE_WIRE_FLAG; + McpSetSystemConfiguration(2); + } +} + +bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift) +{ + uint32_t measured; + uint32_t expected; + uint16_t *gain; + uint32_t new_gain; + + if (range_shift == 0) { + measured = mcp_voltage_rms; + expected = cal_registers->calibration_voltage; + gain = &(cal_registers->gain_voltage_rms); + } else if (range_shift == 8) { + measured = mcp_current_rms; + expected = cal_registers->calibration_current; + gain = &(cal_registers->gain_current_rms); + } else if (range_shift == 16) { + measured = mcp_active_power; + expected = cal_registers->calibration_active_power; + gain = &(cal_registers->gain_active_power); + } else { + return false; + } + + if (measured == 0) { + return false; + } + + uint32_t range = (cal_registers->range >> range_shift) & 0xFF; + +calc: + new_gain = (*gain) * expected / measured; + + if (new_gain < 25000) { + range++; + if (measured > 6) { + measured = measured / 2; + goto calc; + } + } + + if (new_gain > 55000) { + range--; + measured = measured * 2; + goto calc; + } + + *gain = new_gain; + uint32_t old_range = (cal_registers->range >> range_shift) & 0xFF; + cal_registers->range = cal_registers->range ^ (old_range << range_shift); + cal_registers->range = cal_registers->range | (range << range_shift); + + return true; +} + + + + + + +void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) +{ + uint8_t data[7 + MCP_CALIBRATION_LEN + 2 + 1]; + + data[1] = sizeof(data); + data[2] = MCP_SET_ADDRESS; + data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; + data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; + + data[5] = MCP_WRITE; + data[6] = MCP_CALIBRATION_LEN; + + McpSetInt(cal_registers->gain_current_rms, data, 0+7, 2); + McpSetInt(cal_registers->gain_voltage_rms, data, 2+7, 2); + McpSetInt(cal_registers->gain_active_power, data, 4+7, 2); + McpSetInt(cal_registers->gain_reactive_power, data, 6+7, 2); + McpSetInt(cal_registers->offset_current_rms, data, 8+7, 4); + McpSetInt(cal_registers->offset_active_power, data, 12+7, 4); + McpSetInt(cal_registers->offset_reactive_power, data, 16+7, 4); + McpSetInt(cal_registers->dc_offset_current, data, 20+7, 2); + McpSetInt(cal_registers->phase_compensation, data, 22+7, 2); + McpSetInt(cal_registers->apparent_power_divisor, data, 24+7, 2); + + McpSetInt(cal_registers->system_configuration, data, 26+7, 4); + McpSetInt(cal_registers->dio_configuration, data, 30+7, 2); + McpSetInt(cal_registers->range, data, 32+7, 4); + + McpSetInt(cal_registers->calibration_current, data, 36+7, 4); + McpSetInt(cal_registers->calibration_voltage, data, 40+7, 2); + McpSetInt(cal_registers->calibration_active_power, data, 42+7, 4); + McpSetInt(cal_registers->calibration_reactive_power, data, 46+7, 4); + McpSetInt(cal_registers->accumulation_interval, data, 50+7, 2); + + data[MCP_CALIBRATION_LEN+7] = MCP_SAVE_REGISTERS; + data[MCP_CALIBRATION_LEN+8] = mcp_address; + + McpSend(data); +} + + + +void McpSetSystemConfiguration(uint16 interval) +{ + + uint8_t data[17]; + + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; + data[ 3] = 0x00; + data[ 4] = 0x42; + data[ 5] = MCP_WRITE_32; + data[ 6] = (mcp_system_configuration >> 24) & 0xFF; + data[ 7] = (mcp_system_configuration >> 16) & 0xFF; + data[ 8] = (mcp_system_configuration >> 8) & 0xFF; + data[ 9] = (mcp_system_configuration >> 0) & 0xFF; + data[10] = MCP_SET_ADDRESS; + data[11] = 0x00; + data[12] = 0x5A; + data[13] = MCP_WRITE_16; + data[14] = (interval >> 8) & 0xFF; + data[15] = (interval >> 0) & 0xFF; + + McpSend(data); +} + + + +void McpGetFrequency(void) +{ + if (mcp_calibration_active) { return; } + mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; + + uint8_t data[] = { MCP_START_FRAME, 11, MCP_SET_ADDRESS, (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF, MCP_FREQUENCY_REF_BASE & 0xFF, MCP_READ_16, + MCP_SET_ADDRESS, (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF, MCP_FREQUENCY_GAIN_BASE & 0xFF, MCP_READ_16, 0x00 }; + + McpSend(data); +} + +void McpParseFrequency(void) +{ + + uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; + uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; + + if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { + line_frequency_ref = Settings.energy_frequency_calibration; + + if ((0xFFFF == mcp_line_frequency) || (0 == gain_line_frequency)) { + mcp_line_frequency = 50000; + gain_line_frequency = 0x8000; + } + gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_line_frequency; + + mcp_timeout = 0; + McpSetFrequency(line_frequency_ref, gain_line_frequency); + } + + Settings.energy_frequency_calibration = line_frequency_ref; + + mcp_calibrate = 0; +} + +void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) +{ + + uint8_t data[17]; + + data[ 1] = sizeof(data); + data[ 2] = MCP_SET_ADDRESS; + data[ 3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; + data[ 4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; + + data[ 5] = MCP_WRITE_16; + data[ 6] = (line_frequency_ref >> 8) & 0xFF; + data[ 7] = (line_frequency_ref >> 0) & 0xFF; + + data[ 8] = MCP_SET_ADDRESS; + data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; + data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; + + data[11] = MCP_WRITE_16; + data[12] = (gain_line_frequency >> 8) & 0xFF; + data[13] = (gain_line_frequency >> 0) & 0xFF; + + data[14] = MCP_SAVE_REGISTERS; + data[15] = mcp_address; + + McpSend(data); +} + + + +void McpGetData(void) +{ + uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, 0x00, 0x04, MCP_READ, 22, 0x00 }; + + McpSend(data); +} + +void McpParseData(void) +{ + + + + + + mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); + mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); + mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); + + + mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); + + if (Energy.power_on) { + Energy.data_valid[0] = 0; + Energy.frequency[0] = (float)mcp_line_frequency / 1000; + Energy.voltage[0] = (float)mcp_voltage_rms / 10; + Energy.active_power[0] = (float)mcp_active_power / 100; + if (0 == Energy.active_power[0]) { + Energy.current[0] = 0; + } else { + Energy.current[0] = (float)mcp_current_rms / 10000; + } + } else { + Energy.data_valid[0] = ENERGY_WATCHDOG; + } +} + + + +void McpSerialInput(void) +{ + while ((McpSerial->available()) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { + yield(); + mcp_buffer[mcp_byte_counter++] = McpSerial->read(); + mcp_window = millis(); + } + + + if ((mcp_byte_counter) && (millis() - mcp_window > (24000 / MCP_BAUDRATE) +1)) { + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); + + if (MCP_BUFFER_SIZE == mcp_byte_counter) { + + } + else if (1 == mcp_byte_counter) { + if (MCP_ERROR_CRC == mcp_buffer[0]) { + + mcp_timeout = 0; + } + else if (MCP_ERROR_NAK == mcp_buffer[0]) { + + mcp_timeout = 0; + } + } + else if (MCP_ACK_FRAME == mcp_buffer[0]) { + if (mcp_byte_counter == mcp_buffer[1]) { + + if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); + } else { + if (5 == mcp_buffer[1]) { McpAddressReceive(); } + if (25 == mcp_buffer[1]) { McpParseData(); } + if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } + if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } + } + + } + mcp_timeout = 0; + } + else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { + mcp_timeout = 0; + } + + mcp_byte_counter = 0; + McpSerial->flush(); + } +} + + + +void McpEverySecond(void) +{ + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + mcp_voltage_rms = 0; + mcp_current_rms = 0; + mcp_active_power = 0; + mcp_line_frequency = 0; + } + + if (mcp_active_power) { + Energy.kWhtoday_delta += ((mcp_active_power * 10) / 36); + EnergyUpdateToday(); + } + + if (mcp_timeout) { + mcp_timeout--; + } + else if (mcp_calibration_active) { + mcp_calibration_active--; + } + else if (mcp_init) { + if (2 == mcp_init) { + McpGetCalibration(); + } + else if (1 == mcp_init) { + McpGetFrequency(); + } + mcp_init--; + } + else if (!mcp_address) { + McpGetAddress(); + } + else { + McpGetData(); + } +} + +void McpSnsInit(void) +{ + + McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); + if (McpSerial->begin(MCP_BAUDRATE)) { + if (McpSerial->hardwareSerial()) { + ClaimSerial(); + mcp_buffer = serial_in_buffer; + } else { + mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); + } + DigitalWrite(GPIO_MCP39F5_RST, 1); + } else { + energy_flg = ENERGY_NONE; + } +} + +void McpDrvInit(void) +{ + if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { + if (pin[GPIO_MCP39F5_RST] < 99) { + pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); + digitalWrite(pin[GPIO_MCP39F5_RST], 0); + } + mcp_calibrate = 0; + mcp_timeout = 2; + mcp_init = 2; + energy_flg = XNRG_04; + } +} + +bool McpCommand(void) +{ + bool serviced = true; + unsigned long value = 0; + + if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_active_power) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100); + if ((value > 100) && (value < 200000)) { + Settings.energy_power_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_POWER; + McpGetCalibration(); + } + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_voltage_rms) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > 1000) && (value < 2600)) { + Settings.energy_voltage_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_VOLTAGE; + McpGetCalibration(); + } + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_current_rms) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); + if ((value > 100) && (value < 80000)) { + Settings.energy_current_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_CURRENT; + McpGetCalibration(); + } + } + } + else if (CMND_FREQUENCYSET == Energy.command_code) { + if (XdrvMailbox.data_len && mcp_line_frequency) { + value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000); + if ((value > 45000) && (value < 65000)) { + Settings.energy_frequency_calibration = value; + mcp_calibrate |= MCP_CALIBRATE_FREQUENCY; + McpGetFrequency(); + } + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg04(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + if (McpSerial) { McpSerialInput(); } + break; + case FUNC_ENERGY_EVERY_SECOND: + if (McpSerial) { McpEverySecond(); } + break; + case FUNC_COMMAND: + result = McpCommand(); + break; + case FUNC_INIT: + McpSnsInit(); + break; + case FUNC_PRE_INIT: + McpDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_AC +# 33 "S:/Development/Tasmota/tasmota/xnrg_05_pzem_ac.ino" +#define XNRG_05 5 + +const uint8_t PZEM_AC_DEVICE_ADDRESS = 0x01; +const uint32_t PZEM_AC_STABILIZE = 30; + +#include +TasmotaModbus *PzemAcModbus; + +struct PZEMAC { + float energy = 0; + float last_energy = 0; + uint8_t send_retry = 0; + uint8_t phase = 0; + uint8_t address = 0; + uint8_t address_step = ADDR_IDLE; +} PzemAc; + +void PzemAcEverySecond(void) +{ + bool data_ready = PzemAcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[30]; + + uint8_t registers = 10; + if (ADDR_RECEIVE == PzemAc.address_step) { + registers = 2; + PzemAc.address_step--; + } + uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, registers); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemAcModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAC: PzemAc %d error %d"), PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, error); + } else { + Energy.data_valid[PzemAc.phase] = 0; + if (10 == registers) { + + + + + + Energy.voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0; + Energy.current[PzemAc.phase] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; + Energy.active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; + Energy.frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0; + Energy.power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0; + + PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); + if (PzemAc.phase == Energy.phase_count -1) { + if (PzemAc.energy > PzemAc.last_energy) { + if (uptime > PZEM_AC_STABILIZE) { + EnergyUpdateTotal(PzemAc.energy, false); + } + PzemAc.last_energy = PzemAc.energy; + } + PzemAc.energy = 0; + } + + } + } + } + + if (0 == PzemAc.send_retry || data_ready) { + if (0 == PzemAc.phase) { + PzemAc.phase = Energy.phase_count -1; + } else { + PzemAc.phase--; + } + PzemAc.send_retry = ENERGY_WATCHDOG; + if (ADDR_SEND == PzemAc.address_step) { + PzemAcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemAc.address); + PzemAc.address_step--; + } else { + PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, 0x04, 0, 10); + } + } + else { + PzemAc.send_retry--; + if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < PZEM_AC_STABILIZE)) { + Energy.phase_count--; + } + } +} + +void PzemAcSnsInit(void) +{ + PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemAcModbus->Begin(9600); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.phase_count = 3; + PzemAc.phase = 0; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemAcDrvInit(void) +{ + if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_05; + } +} + +bool PzemAcCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + PzemAc.address = XdrvMailbox.payload; + PzemAc.address_step = ADDR_SEND; + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg05(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { PzemAcEverySecond(); } + break; + case FUNC_COMMAND: + result = PzemAcCommand(); + break; + case FUNC_INIT: + PzemAcSnsInit(); + break; + case FUNC_PRE_INIT: + PzemAcDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_DC +# 32 "S:/Development/Tasmota/tasmota/xnrg_06_pzem_dc.ino" +#define XNRG_06 6 + +const uint8_t PZEM_DC_DEVICE_ADDRESS = 0x01; +const uint32_t PZEM_DC_STABILIZE = 30; + +#include +TasmotaModbus *PzemDcModbus; + +struct PZEMDC { + float energy = 0; + float last_energy = 0; + uint8_t send_retry = 0; + uint8_t channel = 0; + uint8_t address = 0; + uint8_t address_step = ADDR_IDLE; +} PzemDc; + +void PzemDcEverySecond(void) +{ + bool data_ready = PzemDcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[26]; + + uint8_t registers = 8; + if (ADDR_RECEIVE == PzemDc.address_step) { + registers = 2; + PzemDc.address_step--; + } + uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, registers); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemDcModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PDC: PzemDc %d error %d"), PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, error); + } else { + Energy.data_valid[PzemDc.channel] = 0; + if (8 == registers) { + + + + + + Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; + Energy.current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0; + Energy.active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; + + PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); + if (PzemDc.channel == Energy.phase_count -1) { + if (PzemDc.energy > PzemDc.last_energy) { + if (uptime > PZEM_DC_STABILIZE) { + EnergyUpdateTotal(PzemDc.energy, false); + } + PzemDc.last_energy = PzemDc.energy; + } + PzemDc.energy = 0; + } + } + } + } + + if (0 == PzemDc.send_retry || data_ready) { + if (0 == PzemDc.channel) { + PzemDc.channel = Energy.phase_count -1; + } else { + PzemDc.channel--; + } + PzemDc.send_retry = ENERGY_WATCHDOG; + if (ADDR_SEND == PzemDc.address_step) { + PzemDcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemDc.address); + PzemDc.address_step--; + } else { + PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, 0x04, 0, 8); + } + } + else { + PzemDc.send_retry--; + if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < PZEM_DC_STABILIZE)) { + Energy.phase_count--; + } + } +} + +void PzemDcSnsInit(void) +{ + PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemDcModbus->Begin(9600, 2); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.type_dc = true; + Energy.phase_count = 3; + PzemDc.channel = 0; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDcDrvInit(void) +{ + if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_06; + } +} + +bool PzemDcCommand(void) +{ + bool serviced = true; + + if (CMND_MODULEADDRESS == Energy.command_code) { + PzemDc.address = XdrvMailbox.payload; + PzemDc.address_step = ADDR_SEND; + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg06(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { PzemDcEverySecond(); } + break; + case FUNC_COMMAND: + result = PzemDcCommand(); + break; + case FUNC_INIT: + PzemDcSnsInit(); + break; + case FUNC_PRE_INIT: + PzemDcDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_07_ade7953.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_07_ade7953.ino" +#ifdef USE_I2C +#ifdef USE_ENERGY_SENSOR +#ifdef USE_ADE7953 +# 31 "S:/Development/Tasmota/tasmota/xnrg_07_ade7953.ino" +#define XNRG_07 7 +#define XI2C_07 7 + +#define ADE7953_PREF 1540 +#define ADE7953_UREF 26000 +#define ADE7953_IREF 10000 + +#define ADE7953_ADDR 0x38 + +const uint16_t Ade7953Registers[] { + 0x31B, + 0x313, + 0x311, + 0x315, + 0x31A, + 0x312, + 0x310, + 0x314, + 0x31C, + 0x10E +}; + +struct Ade7953 { + uint32_t voltage_rms = 0; + uint32_t period = 0; + uint32_t current_rms[2] = { 0, 0 }; + uint32_t active_power[2] = { 0, 0 }; + uint8_t init_step = 0; +} Ade7953; + +int Ade7953RegSize(uint16_t reg) +{ + int size = 0; + switch ((reg >> 8) & 0x0F) { + case 0x03: + size++; + case 0x02: + size++; + case 0x01: + size++; + case 0x00: + case 0x07: + case 0x08: + size++; + } + return size; +} + +void Ade7953Write(uint16_t reg, uint32_t val) +{ + int size = Ade7953RegSize(reg); + if (size) { + Wire.beginTransmission(ADE7953_ADDR); + Wire.write((reg >> 8) & 0xFF); + Wire.write(reg & 0xFF); + while (size--) { + Wire.write((val >> (8 * size)) & 0xFF); + } + Wire.endTransmission(); + delayMicroseconds(5); + } +} + +int32_t Ade7953Read(uint16_t reg) +{ + uint32_t response = 0; + + int size = Ade7953RegSize(reg); + if (size) { + Wire.beginTransmission(ADE7953_ADDR); + Wire.write((reg >> 8) & 0xFF); + Wire.write(reg & 0xFF); + Wire.endTransmission(0); + Wire.requestFrom(ADE7953_ADDR, size); + if (size <= Wire.available()) { + for (uint32_t i = 0; i < size; i++) { + response = response << 8 | Wire.read(); + } + } + } + return response; +} + +void Ade7953Init(void) +{ + Ade7953Write(0x102, 0x0004); + Ade7953Write(0x0FE, 0x00AD); + Ade7953Write(0x120, 0x0030); +} + +void Ade7953GetData(void) +{ + int32_t reg[2][4]; + for (uint32_t i = 0; i < sizeof(Ade7953Registers)/sizeof(uint16_t); i++) { + int32_t value = Ade7953Read(Ade7953Registers[i]); + if (8 == i) { + Ade7953.voltage_rms = value; + } else if (9 == i) { + Ade7953.period = value; + } else { + reg[i >> 2][i &3] = value; + } + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"), + Ade7953.voltage_rms, Ade7953.period, + reg[0][0], reg[0][1], reg[0][2], reg[0][3], + reg[1][0], reg[1][1], reg[1][2], reg[1][3]); + + uint32_t apparent_power[2] = { 0, 0 }; + uint32_t reactive_power[2] = { 0, 0 }; + + for (uint32_t channel = 0; channel < 2; channel++) { + Ade7953.current_rms[channel] = reg[channel][0]; + if (Ade7953.current_rms[channel] < 2000) { + Ade7953.current_rms[channel] = 0; + Ade7953.active_power[channel] = 0; + } else { + Ade7953.active_power[channel] = abs(reg[channel][1]); + apparent_power[channel] = abs(reg[channel][2]); + reactive_power[channel] = abs(reg[channel][3]); + } + } + + uint32_t current_rms_sum = Ade7953.current_rms[0] + Ade7953.current_rms[1]; + uint32_t active_power_sum = Ade7953.active_power[0] + Ade7953.active_power[1]; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, C %d, I %d + %d = %d, P %d + %d = %d"), + Ade7953.voltage_rms, Ade7953.period, + Ade7953.current_rms[0], Ade7953.current_rms[1], current_rms_sum, + Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum); + + if (Energy.power_on) { + Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration; + Energy.frequency[0] = 223750.0f / ( (float)Ade7953.period + 1); + + for (uint32_t channel = 0; channel < 2; channel++) { + Energy.data_valid[channel] = 0; + Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings.energy_power_calibration / 10); + Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings.energy_power_calibration / 10); + Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings.energy_power_calibration / 10); + if (0 == Energy.active_power[channel]) { + Energy.current[channel] = 0; + } else { + Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings.energy_current_calibration * 10); + } + } + } else { + Energy.data_valid[0] = ENERGY_WATCHDOG; + Energy.data_valid[1] = ENERGY_WATCHDOG; + } + + if (active_power_sum) { + Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings.energy_power_calibration / 10))) / 3600); + EnergyUpdateToday(); + } +} + +void Ade7953EnergyEverySecond(void) +{ + if (Ade7953.init_step) { + if (1 == Ade7953.init_step) { + Ade7953Init(); + } + Ade7953.init_step--; + } else { + Ade7953GetData(); + } +} + +void Ade7953DrvInit(void) +{ + if (pin[GPIO_ADE7953_IRQ] < 99) { + delay(100); + if (I2cSetDevice(ADE7953_ADDR)) { + if (HLW_PREF_PULSE == Settings.energy_power_calibration) { + Settings.energy_power_calibration = ADE7953_PREF; + Settings.energy_voltage_calibration = ADE7953_UREF; + Settings.energy_current_calibration = ADE7953_IREF; + } + I2cSetActiveFound(ADE7953_ADDR, "ADE7953"); + Ade7953.init_step = 2; + + Energy.phase_count = 2; + Energy.voltage_common = true; + + energy_flg = XNRG_07; + } + } +} + +bool Ade7953Command(void) +{ + bool serviced = true; + + uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0; + uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); + + if (CMND_POWERCAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; } + + } + else if (CMND_VOLTAGECAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_UREF; } + + } + else if (CMND_CURRENTCAL == Energy.command_code) { + if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_IREF; } + + } + else if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.active_power[channel]) { + if ((value > 100) && (value < 200000)) { + Settings.energy_power_calibration = (Ade7953.active_power[channel] * 1000) / value; + } + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.voltage_rms) { + if ((value > 10000) && (value < 26000)) { + Settings.energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; + } + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) { + if ((value > 2000) && (value < 1000000)) { + Settings.energy_current_calibration = ((Ade7953.current_rms[channel] * 100) / value) * 100; + } + } + } + else serviced = false; + + return serviced; +} + + + + + +bool Xnrg07(uint8_t function) +{ + if (!I2cEnabled(XI2C_07)) { return false; } + + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + Ade7953EnergyEverySecond(); + break; + case FUNC_COMMAND: + result = Ade7953Command(); + break; + case FUNC_PRE_INIT: + Ade7953DrvInit(); + break; + } + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_08_sdm120.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_08_sdm120.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM120 + + + + + + +#define XNRG_08 8 + + +#ifndef SDM120_SPEED + #define SDM120_SPEED 2400 +#endif + +#ifndef SDM120_ADDR + #define SDM120_ADDR 1 +#endif + +#include +TasmotaModbus *Sdm120Modbus; + +const uint8_t sdm120_table = 8; +const uint8_t sdm220_table = 13; + +const uint16_t sdm120_start_addresses[] { + 0x0000, + 0x0006, + 0x000C, + 0x0012, + 0x0018, + 0x001E, + 0x0046, + 0x0156, + + 0X0048, + 0X004A, + 0X004C, + 0X004E, + 0X0024 +}; + +struct SDM120 { + float total_active = 0; + float import_active = NAN; + float import_reactive = 0; + float export_reactive = 0; + float phase_angle = 0; + uint8_t read_state = 0; + uint8_t send_retry = 0; + uint8_t start_address_count = sdm220_table; +} Sdm120; + + + +void SDM120Every250ms(void) +{ + bool data_ready = Sdm120Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm120Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM120 error %d"), error); + } else { + Energy.data_valid[0] = 0; + + + + + float value; + ((uint8_t*)&value)[3] = buffer[3]; + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Sdm120.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.current[0] = value; + break; + + case 2: + Energy.active_power[0] = value; + break; + + case 3: + Energy.apparent_power[0] = value; + break; + + case 4: + Energy.reactive_power[0] = value; + break; + + case 5: + Energy.power_factor[0] = value; + break; + + case 6: + Energy.frequency[0] = value; + break; + + case 7: + Sdm120.total_active = value; + break; + + case 8: + Sdm120.import_active = value; + break; + + case 9: + Energy.export_active = value; + break; + + case 10: + Sdm120.import_reactive = value; + break; + + case 11: + Sdm120.export_reactive = value; + break; + + case 12: + Sdm120.phase_angle = value; + break; + } + + Sdm120.read_state++; + if (Sdm120.read_state == Sdm120.start_address_count) { + Sdm120.read_state = 0; + + if (Sdm120.start_address_count > sdm120_table) { + if (!isnan(Sdm120.import_active)) { + Sdm120.total_active = Sdm120.import_active; + } else { + Sdm120.start_address_count = sdm120_table; + } + } + EnergyUpdateTotal(Sdm120.total_active, true); + } + } + } + + if (0 == Sdm120.send_retry || data_ready) { + Sdm120.send_retry = 5; + Sdm120Modbus->Send(SDM120_ADDR, 0x04, sdm120_start_addresses[Sdm120.read_state], 2); + } else { + Sdm120.send_retry--; + } +} + +void Sdm120SnsInit(void) +{ + Sdm120Modbus = new TasmotaModbus(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX]); + uint8_t result = Sdm120Modbus->Begin(SDM120_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Sdm120DrvInit(void) +{ + if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { + energy_flg = XNRG_08; + } +} + +void Sdm220Reset(void) +{ + if (isnan(Sdm120.import_active)) { return; } + + Sdm120.import_active = 0; + Sdm120.import_reactive = 0; + Sdm120.export_reactive = 0; + Sdm120.phase_angle = 0; +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_SDM220[] PROGMEM = + "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}"; +#endif + +void Sdm220Show(bool json) +{ + if (isnan(Sdm120.import_active)) { return; } + + char import_active_chr[FLOATSZ]; + dtostrfd(Sdm120.import_active, Settings.flag2.energy_resolution, import_active_chr); + char import_reactive_chr[FLOATSZ]; + dtostrfd(Sdm120.import_reactive, Settings.flag2.energy_resolution, import_reactive_chr); + char export_reactive_chr[FLOATSZ]; + dtostrfd(Sdm120.export_reactive, Settings.flag2.energy_resolution, export_reactive_chr); + char phase_angle_chr[FLOATSZ]; + dtostrfd(Sdm120.phase_angle, 2, phase_angle_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s"), + import_active_chr, import_reactive_chr, export_reactive_chr, phase_angle_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_ENERGY_SDM220, import_reactive_chr, export_reactive_chr, phase_angle_chr); +#endif + } +} + + + + + +bool Xnrg08(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { SDM120Every250ms(); } + break; + case FUNC_JSON_APPEND: + Sdm220Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sdm220Show(0); + break; +#endif + case FUNC_ENERGY_RESET: + Sdm220Reset(); + break; + case FUNC_INIT: + Sdm120SnsInit(); + break; + case FUNC_PRE_INIT: + Sdm120DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_09_dds2382.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_09_dds2382.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_DDS2382 + + + + + + +#define XNRG_09 9 + +#ifndef DDS2382_SPEED +#define DDS2382_SPEED 9600 +#endif +#ifndef DDS2382_ADDR +#define DDS2382_ADDR 1 +#endif + +#include +TasmotaModbus *Dds2382Modbus; + +uint8_t Dds2382_send_retry = 0; + +void Dds2382EverySecond(void) +{ + bool data_ready = Dds2382Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[46]; + + uint32_t error = Dds2382Modbus->ReceiveBuffer(buffer, 18); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Dds2382Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "DDS2382 response error %d"), error); + } else { + Energy.data_valid[0] = 0; +# 67 "S:/Development/Tasmota/tasmota/xnrg_09_dds2382.ino" + Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0; + Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0; + Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]); + Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]); + Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; + Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; + uint8_t offset = 11; + if (Settings.flag3.dds2382_model) { + offset = 19; + } + Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; + float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; + + EnergyUpdateTotal(import_active, true); + } + } + + if (0 == Dds2382_send_retry || data_ready) { + Dds2382_send_retry = 5; + Dds2382Modbus->Send(DDS2382_ADDR, 0x03, 0, 18); + } else { + Dds2382_send_retry--; + } +} + +void Dds2382SnsInit(void) +{ + Dds2382Modbus = new TasmotaModbus(pin[GPIO_DDS2382_RX], pin[GPIO_DDS2382_TX]); + uint8_t result = Dds2382Modbus->Begin(DDS2382_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Dds2382DrvInit(void) +{ + if ((pin[GPIO_DDS2382_RX] < 99) && (pin[GPIO_DDS2382_TX] < 99)) { + energy_flg = XNRG_09; + } +} + + + + + +bool Xnrg09(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_ENERGY_EVERY_SECOND: + if (uptime > 4) { Dds2382EverySecond(); } + break; + case FUNC_INIT: + Dds2382SnsInit(); + break; + case FUNC_PRE_INIT: + Dds2382DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_10_sdm630.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_10_sdm630.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM630 + + + + + + +#define XNRG_10 10 + + +#ifndef SDM630_SPEED + #define SDM630_SPEED 9600 +#endif + +#ifndef SDM630_ADDR + #define SDM630_ADDR 1 +#endif + +#include +TasmotaModbus *Sdm630Modbus; + +const uint16_t sdm630_start_addresses[] { + 0x0000, + 0x0002, + 0x0004, + 0x0006, + 0x0008, + 0x000A, + 0x000C, + 0x000E, + 0x0010, + 0x0018, + 0x001A, + 0x001C, + 0x001E, + 0x0020, + 0x0022, + 0x0156 +}; + +struct SDM630 { + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Sdm630; + + + +void SDM630Every250ms(void) +{ + bool data_ready = Sdm630Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Sdm630Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm630Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM630 error %d"), error); + } else { + Energy.data_valid[0] = 0; + Energy.data_valid[1] = 0; + Energy.data_valid[2] = 0; + + + + + float value; + ((uint8_t*)&value)[3] = buffer[3]; + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Sdm630.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.voltage[1] = value; + break; + + case 2: + Energy.voltage[2] = value; + break; + + case 3: + Energy.current[0] = value; + break; + + case 4: + Energy.current[1] = value; + break; + + case 5: + Energy.current[2] = value; + break; + + case 6: + Energy.active_power[0] = value; + break; + + case 7: + Energy.active_power[1] = value; + break; + + case 8: + Energy.active_power[2] = value; + break; + + case 9: + Energy.reactive_power[0] = value; + break; + + case 10: + Energy.reactive_power[1] = value; + break; + + case 11: + Energy.reactive_power[2] = value; + break; + + case 12: + Energy.power_factor[0] = value; + break; + + case 13: + Energy.power_factor[1] = value; + break; + + case 14: + Energy.power_factor[2] = value; + break; + + case 15: + EnergyUpdateTotal(value, true); + break; + } + + Sdm630.read_state++; + if (sizeof(sdm630_start_addresses)/2 == Sdm630.read_state) { + Sdm630.read_state = 0; + } + } + } + + if (0 == Sdm630.send_retry || data_ready) { + Sdm630.send_retry = 5; + Sdm630Modbus->Send(SDM630_ADDR, 0x04, sdm630_start_addresses[Sdm630.read_state], 2); + } else { + Sdm630.send_retry--; + } +} + +void Sdm630SnsInit(void) +{ + Sdm630Modbus = new TasmotaModbus(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX]); + uint8_t result = Sdm630Modbus->Begin(SDM630_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + Energy.phase_count = 3; + } else { + energy_flg = ENERGY_NONE; + } +} + +void Sdm630DrvInit(void) +{ + if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { + energy_flg = XNRG_10; + } +} + + + + + +bool Xnrg10(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { SDM630Every250ms(); } + break; + case FUNC_INIT: + Sdm630SnsInit(); + break; + case FUNC_PRE_INIT: + Sdm630DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_11_ddsu666.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_11_ddsu666.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_DDSU666 + + + + +#define XNRG_11 11 + + +#ifndef DDSU666_SPEED + #define DDSU666_SPEED 9600 +#endif + +#ifndef DDSU666_ADDR + #define DDSU666_ADDR 1 +#endif + +#include +TasmotaModbus *Ddsu666Modbus; + +const uint16_t Ddsu666_start_addresses[] { + 0x2000, + 0x2002, + 0x2004, + 0x2006, + 0x200A, + 0x200E, + 0X4000, + 0X400A, +}; + +struct DDSU666 { + float import_active = NAN; + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Ddsu666; + + + +void DDSU666Every250ms(void) +{ + bool data_ready = Ddsu666Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + + uint32_t error = Ddsu666Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Ddsu666Modbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: Ddsu666 error %d"), error); + } else { + Energy.data_valid[0] = 0; + + + + + float value; + ((uint8_t*)&value)[3] = buffer[3]; + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Ddsu666.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.current[0] = value; + break; + + case 2: + Energy.active_power[0] = value * 1000; + break; + + case 3: + Energy.reactive_power[0] = value * 1000; + break; + + case 4: + Energy.power_factor[0] = value; + break; + + case 5: + Energy.frequency[0] = value; + break; + + case 6: + Ddsu666.import_active = value; + break; + + case 7: + Energy.export_active = value; + break; + } + + Ddsu666.read_state++; + + if (Ddsu666.read_state == 8) { + Ddsu666.read_state = 0; + EnergyUpdateTotal(Ddsu666.import_active, true); + } + } + } + + if (0 == Ddsu666.send_retry || data_ready) { + Ddsu666.send_retry = 5; + Ddsu666Modbus->Send(DDSU666_ADDR, 0x04, Ddsu666_start_addresses[Ddsu666.read_state], 2); + } else { + Ddsu666.send_retry--; + } +} + +void Ddsu666SnsInit(void) +{ + Ddsu666Modbus = new TasmotaModbus(pin[GPIO_DDSU666_RX], pin[GPIO_DDSU666_TX]); + uint8_t result = Ddsu666Modbus->Begin(DDSU666_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Ddsu666DrvInit(void) +{ + if ((pin[GPIO_DDSU666_RX] < 99) && (pin[GPIO_DDSU666_TX] < 99)) { + energy_flg = XNRG_11; + } +} + + + + + +bool Xnrg11(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { DDSU666Every250ms(); } + break; + case FUNC_INIT: + Ddsu666SnsInit(); + break; + case FUNC_PRE_INIT: + Ddsu666DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_12_solaxX1.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_12_solaxX1.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SOLAX_X1 + + + + +#define XNRG_12 12 + +#ifndef SOLAXX1_SPEED +#define SOLAXX1_SPEED 9600 +#endif + +#define INVERTER_ADDRESS 0x0A + +#define D_SOLAX_X1 "SolaxX1" + +#include + +enum solaxX1_Error +{ + solaxX1_ERR_NO_ERROR, + solaxX1_ERR_CRC_ERROR +}; + +union { + uint32_t ErrMessage; + struct { + + uint8_t TzProtectFault:1; + uint8_t MainsLostFault:1; + uint8_t GridVoltFault:1; + uint8_t GridFreqFault:1; + uint8_t PLLLostFault:1; + uint8_t BusVoltFault:1; + uint8_t ErrBit06:1; + uint8_t OciFault:1; + + uint8_t Dci_OCP_Fault:1; + uint8_t ResidualCurrentFault:1; + uint8_t PvVoltFault:1; + uint8_t Ac10Mins_Voltage_Fault:1; + uint8_t IsolationFault:1; + uint8_t TemperatureOverFault:1; + uint8_t FanFault:1; + uint8_t ErrBit15:1; + + uint8_t SpiCommsFault:1; + uint8_t SciCommsFault:1; + uint8_t ErrBit18:1; + uint8_t InputConfigFault:1; + uint8_t EepromFault:1; + uint8_t RelayFault:1; + uint8_t SampleConsistenceFault:1; + uint8_t ResidualCurrent_DeviceFault:1; + + uint8_t ErrBit24:1; + uint8_t ErrBit25:1; + uint8_t ErrBit26:1; + uint8_t ErrBit27:1; + uint8_t ErrBit28:1; + uint8_t DCI_DeviceFault:1; + uint8_t OtherDeviceFault:1; + uint8_t ErrBit31:1; + }; +} ErrCode; + +const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; + +const char kSolaxError[] PROGMEM = + D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" + D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; + + + +TasmotaSerial *solaxX1Serial; + +uint8_t solaxX1_Init = 1; + +struct SOLAXX1 { + float temperature = 0; + float energy_today = 0; + float dc1_voltage = 0; + float dc2_voltage = 0; + float dc1_current = 0; + float dc2_current = 0; + float energy_total = 0; + float runtime_total = 0; + float dc1_power = 0; + float dc2_power = 0; + + uint8_t status = 0; + uint32_t errorCode = 0; +} solaxX1; + +union { + uint8_t status; + struct { + uint8_t freeBit7:1; + uint8_t freeBit6:1; + uint8_t freeBit5:1; + uint8_t queryOffline:1; + uint8_t queryOfflineSend:1; + uint8_t hasAddress:1; + uint8_t inverterAddressSend:1; + uint8_t inverterSnReceived:1; + }; +} protocolStatus; + +uint8_t header[2] = {0xAA, 0x55}; +uint8_t source[2] = {0x00, 0x00}; +uint8_t destination[2] = {0x00, 0x00}; +uint8_t controlCode[1] = {0x00}; +uint8_t functionCode[1] = {0x00}; +uint8_t dataLength[1] = {0x00}; +uint8_t data[16] = {0}; + +uint8_t message[30]; + + + +bool solaxX1_RS485ReceiveReady(void) +{ + return (solaxX1Serial->available() > 1); +} + +void solaxX1_RS485Send(uint16_t msgLen) +{ + memcpy(message, header, 2); + memcpy(message + 2, source, 2); + memcpy(message + 4, destination, 2); + memcpy(message + 6, controlCode, 1); + memcpy(message + 7, functionCode, 1); + memcpy(message + 8, dataLength, 1); + memcpy(message + 9, data, sizeof(data)); + uint16_t crc = solaxX1_calculateCRC(message, msgLen); + + while (solaxX1Serial->available() > 0) + { + solaxX1Serial->read(); + } + + solaxX1Serial->flush(); + solaxX1Serial->write(message, msgLen); + solaxX1Serial->write(highByte(crc)); + solaxX1Serial->write(lowByte(crc)); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen); +} + +uint8_t solaxX1_RS485Receive(uint8_t *value) +{ + uint8_t len = 0; + + while (solaxX1Serial->available() > 0) + { + value[len++] = (uint8_t)solaxX1Serial->read(); + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, value, len); + + uint16_t crc = solaxX1_calculateCRC(value, len - 2); + + if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) + { + return solaxX1_ERR_NO_ERROR; + } + else + { + return solaxX1_ERR_CRC_ERROR; + } +} + +uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) +{ + uint8_t i; + uint16_t wChkSum; + wChkSum = 0; + + for (i = 0; i < bLen; i++) + { + wChkSum = wChkSum + bExternTxPackage[i]; + } + return wChkSum; +} + +void solaxX1_SendInverterAddress(void) +{ + source[0] = 0x00; + destination[0] = 0x00; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x01; + dataLength[0] = 0x0F; + data[14] = INVERTER_ADDRESS; + solaxX1_RS485Send(24); +} + +void solaxX1_QueryLiveData(void) +{ + source[0] = 0x01; + destination[0] = 0x00; + destination[1] = INVERTER_ADDRESS; + controlCode[0] = 0x11; + functionCode[0] = 0x02; + dataLength[0] = 0x00; + solaxX1_RS485Send(9); +} + +uint8_t solaxX1_ParseErrorCode(uint32_t code){ + ErrCode.ErrMessage = code; + + if (code == 0) return 0; + if (ErrCode.MainsLostFault) return 1; + if (ErrCode.GridVoltFault) return 2; + if (ErrCode.GridFreqFault) return 3; + if (ErrCode.PvVoltFault) return 4; + if (ErrCode.IsolationFault) return 5; + if (ErrCode.TemperatureOverFault) return 6; + if (ErrCode.FanFault) return 7; + if (ErrCode.OtherDeviceFault) return 8; +} + + + +uint8_t solaxX1_send_retry = 0; +uint8_t solaxX1_nodata_count = 0; + +void solaxX1250MSecond(void) +{ + uint8_t value[61] = {0}; + bool data_ready = solaxX1_RS485ReceiveReady(); + + if (protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + if (data_ready) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); + } + else + { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 12; + Energy.data_valid[0] = 0; + + solaxX1.temperature = (float)((value[9] << 8) | value[10]); + solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; + solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; + solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; + solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; + solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; + Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; + Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; + Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; + Energy.active_power[0] = (float)((value[27] << 8) | value[28]); + + solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; + solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); + solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); + + + + + + + + solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); + + solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; + solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; + + solaxX1_QueryLiveData(); + EnergyUpdateTotal(solaxX1.energy_total, true); + } + } + + if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { + solaxX1_send_retry = 12; + solaxX1_QueryLiveData(); + } + + + + if (255 == solaxX1_nodata_count) { + solaxX1_nodata_count = 0; + solaxX1_send_retry = 12; + } + } + else + { + if ((solaxX1_nodata_count % 4) == 0) { DEBUG_SENSOR_LOG(PSTR("SX1: No Data count: %d"), solaxX1_nodata_count); } + if (solaxX1_nodata_count < 10 * 4) + { + solaxX1_nodata_count++; + } + else if (255 != solaxX1_nodata_count) + { + + solaxX1_nodata_count = 255; + solaxX1_send_retry = 12; + protocolStatus.status = 0b00001000; + Energy.data_valid[0] = ENERGY_WATCHDOG; + + solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0; + solaxX1.dc2_power = solaxX1.status = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; + + } + } + + if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) + { + if (data_ready) + { + + if (protocolStatus.inverterAddressSend) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error")); + } + else + { + if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Set hasAddress")); + protocolStatus.status = 0b00100000; + } + } + } + + + if (protocolStatus.queryOfflineSend) + { + uint8_t error = solaxX1_RS485Receive(value); + if (error) + { + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error")); + } + else + { + + if (value[6] == 0x10 && value[7] == 0x80 && protocolStatus.inverterSnReceived == false) + { + for (uint8_t i = 9; i <= 22; i++) + { + data[i - 9] = value[i]; + } + solaxX1_SendInverterAddress(); + protocolStatus.status = 0b1100000; + DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); + } + } + } + } + + if (solaxX1_send_retry == 0) + { + if (protocolStatus.queryOfflineSend) + { + protocolStatus.status = 0b00001000; + DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); + } + solaxX1_send_retry = 12; + } + + + if (protocolStatus.queryOffline) + { + + source[0] = 0x01; + destination[1] = 0x00; + controlCode[0] = 0x10; + functionCode[0] = 0x00; + dataLength[0] = 0x00; + solaxX1_RS485Send(9); + protocolStatus.status = 0b00010000; + DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); + } + } + + if (!data_ready) + solaxX1_send_retry--; +} + +void solaxX1SnsInit(void) +{ + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SX1: Solax X1 Inverter Init")); + DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); + protocolStatus.status = 0b00100000; + + solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); + if (solaxX1Serial->begin(SOLAXX1_SPEED)) { + if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void solaxX1DrvInit(void) +{ + if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) { + energy_flg = XNRG_12; + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; +#ifdef SOLAXX1_PV2 +const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; +#endif +const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = + "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}" + "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" + "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"; +#endif + +void solaxX1Show(bool json) +{ + char solar_power[33]; + dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings.flag2.wattage_resolution, solar_power); + char pv1_voltage[33]; + dtostrfd(solaxX1.dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); + char pv1_current[33]; + dtostrfd(solaxX1.dc1_current, Settings.flag2.current_resolution, pv1_current); + char pv1_power[33]; + dtostrfd(solaxX1.dc1_power, Settings.flag2.wattage_resolution, pv1_power); +#ifdef SOLAXX1_PV2 + char pv2_voltage[33]; + dtostrfd(solaxX1.dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); + char pv2_current[33]; + dtostrfd(solaxX1.dc2_current, Settings.flag2.current_resolution, pv2_current); + char pv2_power[33]; + dtostrfd(solaxX1.dc2_power, Settings.flag2.wattage_resolution, pv2_power); +#endif + char temperature[33]; + dtostrfd(solaxX1.temperature, Settings.flag2.temperature_resolution, temperature); + char runtime[33]; + dtostrfd(solaxX1.runtime_total, 0, runtime); + char status[33]; + GetTextIndexed(status, sizeof(status), solaxX1.status, kSolaxMode); + + if (json) + { + ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), + solar_power, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), + pv2_voltage, pv2_current, pv2_power); +#endif + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), + temperature, runtime, status, solaxX1.errorCode); + +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, solar_power, pv1_voltage, pv1_current, pv1_power); +#ifdef SOLAXX1_PV2 + WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); +#endif + WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); + char errorCodeString[33]; + WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, + GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); +#endif + } +} + + + + + +bool Xnrg12(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { solaxX1250MSecond(); } + break; + case FUNC_JSON_APPEND: + solaxX1Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + solaxX1Show(0); + break; +#endif + case FUNC_INIT: + solaxX1SnsInit(); + break; + case FUNC_PRE_INIT: + solaxX1DrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +#ifdef USE_ENERGY_SENSOR +#ifdef USE_LE01MR +# 71 "S:/Development/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" +#define XNRG_13 13 + + +#ifndef LE01MR_SPEED + #define LE01MR_SPEED 2400 +#endif + +#ifndef LE01MR_ADDR + #define LE01MR_ADDR 1 +#endif + +#include +TasmotaModbus *FifLEModbus; + +const uint8_t le01mr_table_sz = 9; + +const uint16_t le01mr_register_addresses[] { + + 0x0130, + 0x0131, + 0x0158, + 0x0139, + 0x0140, + 0x0148, + 0x0150, + 0xA000, + 0xA01E +}; + +struct LE01MR { + float total_active = 0; + float total_reactive = 0; + uint8_t read_state = 0; + uint8_t send_retry = 0; + uint8_t start_address_count = le01mr_table_sz; +} Le01mr; + + + +void FifLEEvery250ms(void) +{ + bool data_ready = FifLEModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; + uint8_t reg_count = 2; + if (Le01mr.read_state < 3) { + reg_count=1; + } + + uint32_t error = FifLEModbus->ReceiveBuffer(buffer, reg_count); + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, FifLEModbus->ReceiveCount()); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); + } else { + Energy.data_valid[0] = 0; +# 146 "S:/Development/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" + uint32_t value_buff = 0; + + if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { + value_buff = ((uint32_t)buffer[3])<<8 | buffer[4]; + } else { + value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; + } + + switch(Le01mr.read_state) { + case 0: + Energy.frequency[0] = value_buff * 0.01f; + break; + + case 1: + Energy.voltage[0] = value_buff * 0.01f; + break; + + case 2: + Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; + break; + + case 3: + Energy.current[0] = value_buff * 0.001f; + break; + + case 4: + Energy.active_power[0] = value_buff * 1.0f; + break; + + case 5: + Energy.reactive_power[0] = value_buff * 1.0f; + break; + + case 6: + Energy.apparent_power[0] = value_buff * 1.0f; + break; + + case 7: + Le01mr.total_active = value_buff * 0.01f; + break; + + case 8: + Le01mr.total_reactive = value_buff * 0.01f; + break; + } + + Le01mr.read_state++; + if (Le01mr.read_state == Le01mr.start_address_count) { + Le01mr.read_state = 0; + + EnergyUpdateTotal(Le01mr.total_active, true); + } + } + } + + if (0 == Le01mr.send_retry || data_ready) { + uint8_t reg_count = 2; + + Le01mr.send_retry = 5; + + if (Le01mr.read_state < 3) reg_count=1; + + FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); + } else { + Le01mr.send_retry--; + } +} + +void FifLESnsInit(void) +{ + FifLEModbus = new TasmotaModbus(pin[GPIO_LE01MR_RX], pin[GPIO_LE01MR_TX]); + uint8_t result = FifLEModbus->Begin(LE01MR_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void FifLEDrvInit(void) +{ + if ((pin[GPIO_LE01MR_RX] < 99) && (pin[GPIO_LE01MR_TX] < 99)) { + energy_flg = XNRG_13; + } +} + +void FifLEReset(void) +{ + Le01mr.total_active = 0; + Le01mr.total_reactive = 0; +} + +#ifdef USE_WEBSERVER +const char HTTP_ENERGY_LE01MR[] PROGMEM = + "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" + "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" + ; +#endif + +void FifLEShow(bool json) +{ + char total_reactive_chr[FLOATSZ]; + dtostrfd(Le01mr.total_reactive, Settings.flag2.energy_resolution, total_reactive_chr); + char total_active_chr[FLOATSZ]; + dtostrfd(Le01mr.total_active, Settings.flag2.energy_resolution, total_active_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"), + total_active_chr, total_reactive_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_ENERGY_LE01MR, total_active_chr, total_reactive_chr); +#endif + } +} + + + + + +bool Xnrg13(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { + FifLEEvery250ms(); + } + break; + case FUNC_JSON_APPEND: + FifLEShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + FifLEShow(0); + break; +#endif + case FUNC_ENERGY_RESET: + FifLEReset(); + break; + case FUNC_INIT: + FifLESnsInit(); + break; + case FUNC_PRE_INIT: + FifLEDrvInit(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xnrg_interface.ino" +# 20 "S:/Development/Tasmota/tasmota/xnrg_interface.ino" +#ifdef USE_ENERGY_SENSOR + +#ifdef XFUNC_PTR_IN_ROM +bool (* const xnrg_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xnrg_func_ptr[])(uint8_t) = { +#endif + +#ifdef XNRG_01 + &Xnrg01, +#endif + +#ifdef XNRG_02 + &Xnrg02, +#endif + +#ifdef XNRG_03 + &Xnrg03, +#endif + +#ifdef XNRG_04 + &Xnrg04, +#endif + +#ifdef XNRG_05 + &Xnrg05, +#endif + +#ifdef XNRG_06 + &Xnrg06, +#endif + +#ifdef XNRG_07 + &Xnrg07, +#endif + +#ifdef XNRG_08 + &Xnrg08, +#endif + +#ifdef XNRG_09 + &Xnrg09, +#endif + +#ifdef XNRG_10 + &Xnrg10, +#endif + +#ifdef XNRG_11 + &Xnrg11, +#endif + +#ifdef XNRG_12 + &Xnrg12, +#endif + +#ifdef XNRG_13 + &Xnrg13, +#endif + +#ifdef XNRG_14 + &Xnrg14, +#endif + +#ifdef XNRG_15 + &Xnrg15, +#endif + +#ifdef XNRG_16 + &Xnrg16 +#endif +}; + +const uint8_t xnrg_present = sizeof(xnrg_func_ptr) / sizeof(xnrg_func_ptr[0]); + +uint8_t xnrg_active = 0; + +bool XnrgCall(uint8_t function) +{ + DEBUG_TRACE_LOG(PSTR("NRG: %d"), function); + + if (FUNC_PRE_INIT == function) { + for (uint32_t x = 0; x < xnrg_present; x++) { + xnrg_func_ptr[x](function); + if (energy_flg) { + xnrg_active = x; + return true; + } + } + } + else if (energy_flg) { + return xnrg_func_ptr[xnrg_active](function); + } + return false; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_01_counter.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_01_counter.ino" +#ifdef USE_COUNTER + + + + +#define XSNS_01 1 + +#define D_PRFX_COUNTER "Counter" +#define D_CMND_COUNTERTYPE "Type" +#define D_CMND_COUNTERDEBOUNCE "Debounce" + +const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" + "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE ; + +void (* const CounterCommand[])(void) PROGMEM = { + &CmndCounter, &CmndCounterType, &CmndCounterDebounce }; + +struct COUNTER { + uint32_t timer[MAX_COUNTERS]; + uint8_t no_pullup = 0; + bool any_counter = false; +} Counter; + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +void CounterUpdate(uint8_t index) ICACHE_RAM_ATTR; +void CounterUpdate1(void) ICACHE_RAM_ATTR; +void CounterUpdate2(void) ICACHE_RAM_ATTR; +void CounterUpdate3(void) ICACHE_RAM_ATTR; +void CounterUpdate4(void) ICACHE_RAM_ATTR; +#endif + +void CounterUpdate(uint8_t index) +{ + uint32_t time = micros(); + uint32_t debounce_time = time - Counter.timer[index]; + if (debounce_time > Settings.pulse_counter_debounce * 1000) { + Counter.timer[index] = time; + if (bitRead(Settings.pulse_counter_type, index)) { + RtcSettings.pulse_counter[index] = debounce_time; + } else { + RtcSettings.pulse_counter[index]++; + } + } +} + +void CounterUpdate1(void) +{ + CounterUpdate(0); +} + +void CounterUpdate2(void) +{ + CounterUpdate(1); +} + +void CounterUpdate3(void) +{ + CounterUpdate(2); +} + +void CounterUpdate4(void) +{ + CounterUpdate(3); +} + + + +bool CounterPinState(void) +{ + if ((XdrvMailbox.index >= GPIO_CNTR1_NP) && (XdrvMailbox.index < (GPIO_CNTR1_NP + MAX_COUNTERS))) { + bitSet(Counter.no_pullup, XdrvMailbox.index - GPIO_CNTR1_NP); + XdrvMailbox.index -= (GPIO_CNTR1_NP - GPIO_CNTR1); + return true; + } + return false; +} + +void CounterInit(void) +{ + typedef void (*function) () ; + function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; + + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + Counter.any_counter = true; + pinMode(pin[GPIO_CNTR1 +i], bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP); + attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); + } + } +} + +void CounterEverySecond(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + if (bitRead(Settings.pulse_counter_type, i)) { + uint32_t time = micros() - Counter.timer[i]; + if (time > 4200000000) { + RtcSettings.pulse_counter[i] = 4200000000; + } + } + } + } +} + +void CounterSaveState(void) +{ + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; + } + } +} + +void CounterShow(bool json) +{ + bool header = false; + uint8_t dsxflg = 0; + for (uint32_t i = 0; i < MAX_COUNTERS; i++) { + if (pin[GPIO_CNTR1 +i] < 99) { + char counter[33]; + if (bitRead(Settings.pulse_counter_type, i)) { + dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); + } else { + dsxflg++; + snprintf_P(counter, sizeof(counter), PSTR("%lu"), RtcSettings.pulse_counter[i]); + } + + if (json) { + if (!header) { + ResponseAppend_P(PSTR(",\"COUNTER\":{")); + } + ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); + header = true; +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (1 == dsxflg)) { + DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); + dsxflg++; + } +#endif + if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { + RtcSettings.pulse_counter[i] = 0; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(PSTR("{s}" D_COUNTER "%d{m}%s%s{e}"), + i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); +#endif + } + } + } + if (header) { + ResponseJsonEnd(); + } +} + + + + + +void CmndCounter(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { + if ((XdrvMailbox.data_len > 0) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { + if ((XdrvMailbox.data[0] == '-') || (XdrvMailbox.data[0] == '+')) { + RtcSettings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; + Settings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; + } else { + RtcSettings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; + Settings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + } + ResponseCmndIdxNumber(RtcSettings.pulse_counter[XdrvMailbox.index -1]); + } +} + +void CmndCounterType(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { + bitWrite(Settings.pulse_counter_type, XdrvMailbox.index -1, XdrvMailbox.payload &1); + RtcSettings.pulse_counter[XdrvMailbox.index -1] = 0; + Settings.pulse_counter[XdrvMailbox.index -1] = 0; + } + ResponseCmndIdxNumber(bitRead(Settings.pulse_counter_type, XdrvMailbox.index -1)); + } +} + +void CmndCounterDebounce(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { + Settings.pulse_counter_debounce = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.pulse_counter_debounce); +} + + + + + +bool Xsns01(uint8_t function) +{ + bool result = false; + + if (Counter.any_counter) { + switch (function) { + case FUNC_EVERY_SECOND: + CounterEverySecond(); + break; + case FUNC_JSON_APPEND: + CounterShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + CounterShow(0); + break; +#endif + case FUNC_SAVE_BEFORE_RESTART: + case FUNC_SAVE_AT_MIDNIGHT: + CounterSaveState(); + break; + case FUNC_COMMAND: + result = DecodeCommand(kCounterCommands, CounterCommand); + break; + } + } else { + switch (function) { + case FUNC_INIT: + CounterInit(); + break; + case FUNC_PIN_STATE: + result = CounterPinState(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_02_analog.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_02_analog.ino" +#ifndef USE_ADC_VCC + + + + +#define XSNS_02 2 + +#define TO_CELSIUS(x) ((x) - 273.15) +#define TO_KELVIN(x) ((x) + 273.15) + + +#define ANALOG_V33 3.3 +#define ANALOG_T0 TO_KELVIN(25.0) + + + + + +#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 +#define ANALOG_NTC_RESISTANCE 10000 +#define ANALOG_NTC_B_COEFFICIENT 3350 + + + + + +#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 +#define ANALOG_LDR_LUX_CALC_SCALAR 12518931 +#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 +# 58 "S:/Development/Tasmota/tasmota/xsns_02_analog.ino" +#define ANALOG_CT_FLAGS 0 +#define ANALOG_CT_MULTIPLIER 2146 +#define ANALOG_CT_VOLTAGE 2300 + +#define CT_FLAG_ENERGY_RESET (1 << 0) + +struct { + float temperature = 0; + float current = 0; + float energy = 0; + uint32_t previous_millis = 0; + uint16_t last_value = 0; +} Adc; + +void AdcInit(void) +{ + if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000)) { + if (ADC0_TEMP == my_adc0) { + + Settings.adc_param_type = ADC0_TEMP; + Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_NTC_RESISTANCE; + Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000; + } + else if (ADC0_LIGHT == my_adc0) { + Settings.adc_param_type = ADC0_LIGHT; + Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; + Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; + } + else if (ADC0_RANGE == my_adc0) { + Settings.adc_param_type = ADC0_RANGE; + Settings.adc_param1 = 0; + Settings.adc_param2 = 1023; + Settings.adc_param3 = 0; + Settings.adc_param4 = 100; + } + else if (ADC0_CT_POWER == my_adc0) { + Settings.adc_param_type = ADC0_CT_POWER; + Settings.adc_param1 = ANALOG_CT_FLAGS; + Settings.adc_param2 = ANALOG_CT_MULTIPLIER; + Settings.adc_param3 = ANALOG_CT_VOLTAGE; + } + } +} + +uint16_t AdcRead(uint8_t factor) +{ + + + + + + uint8_t samples = 1 << factor; + uint16_t analog = 0; + for (uint32_t i = 0; i < samples; i++) { + analog += analogRead(A0); + delay(1); + } + analog >>= factor; + return analog; +} + +#ifdef USE_RULES +void AdcEvery250ms(void) +{ + if (ADC0_INPUT == my_adc0) { + uint16_t new_value = AdcRead(5); + if ((new_value < Adc.last_value -10) || (new_value > Adc.last_value +10)) { + Adc.last_value = new_value; + uint16_t value = Adc.last_value / 10; + Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); + XdrvRulesProcess(); + } + } +} +#endif + +uint16_t AdcGetLux(void) +{ + int adc = AdcRead(2); + + double resistorVoltage = ((double)adc / 1023) * ANALOG_V33; + double ldrVoltage = ANALOG_V33 - resistorVoltage; + double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1; + double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000); + + return (uint16_t)ldrLux; +} + +uint16_t AdcGetRange(void) +{ + + + + int adc = AdcRead(2); + double adcrange = ( ((double)Settings.adc_param2 - (double)adc) / ( ((double)Settings.adc_param2 - (double)Settings.adc_param1)) * ((double)Settings.adc_param3 - (double)Settings.adc_param4) + (double)Settings.adc_param4 ); + return (uint16_t)adcrange; +} + +void AdcGetCurrentPower(uint8_t factor) +{ + + + + + + uint8_t samples = 1 << factor; + uint16_t analog = 0; + uint16_t analog_min = 1023; + uint16_t analog_max = 0; + for (uint32_t i = 0; i < samples; i++) { + analog = analogRead(A0); + if (analog < analog_min) { + analog_min = analog; + } + if (analog > analog_max) { + analog_max = analog; + } + delay(1); + } + + Adc.current = (float)(analog_max-analog_min) * ((float)(Settings.adc_param2) / 100000); + float power = Adc.current * (float)(Settings.adc_param3) / 10; + uint32_t current_millis = millis(); + Adc.energy = Adc.energy + ((power * (current_millis - Adc.previous_millis)) / 3600000000); + Adc.previous_millis = current_millis; +} + +void AdcEverySecond(void) +{ + if (ADC0_TEMP == my_adc0) { + int adc = AdcRead(2); + + double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc); + double BC = (double)Settings.adc_param3 / 10000; + double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2)); + Adc.temperature = ConvertTemp(TO_CELSIUS(T)); + } + else if (ADC0_CT_POWER == my_adc0) { + AdcGetCurrentPower(5); + } +} + +void AdcShow(bool json) +{ + if (ADC0_INPUT == my_adc0) { + uint16_t analog = AdcRead(5); + + if (json) { + ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); +#endif + } + } + + else if (ADC0_TEMP == my_adc0) { + char temperature[33]; + dtostrfd(Adc.temperature, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMP, "ANALOG", temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, Adc.temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); +#endif + } + } + + else if (ADC0_LIGHT == my_adc0) { + uint16_t adc_light = AdcGetLux(); + + if (json) { + ResponseAppend_P(JSON_SNS_ILLUMINANCE, "ANALOG", adc_light); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, adc_light); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light); +#endif + } + } + + else if (ADC0_RANGE == my_adc0) { + uint16_t adc_range = AdcGetRange(); + + if (json) { + ResponseAppend_P(JSON_SNS_RANGE, "ANALOG", adc_range); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_RANGE, "", adc_range); +#endif + } + } + + else if (ADC0_CT_POWER == my_adc0) { + AdcGetCurrentPower(5); + + float voltage = (float)(Settings.adc_param3) / 10; + char voltage_chr[FLOATSZ]; + dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr); + char current_chr[FLOATSZ]; + dtostrfd(Adc.current, Settings.flag2.current_resolution, current_chr); + char power_chr[FLOATSZ]; + dtostrfd(voltage * Adc.current, Settings.flag2.wattage_resolution, power_chr); + char energy_chr[FLOATSZ]; + dtostrfd(Adc.energy, Settings.flag2.energy_resolution, energy_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"ANALOG\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), + energy_chr, power_chr, voltage_chr, current_chr); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_POWER_ENERGY, power_chr); + DomoticzSensor(DZ_VOLTAGE, voltage_chr); + DomoticzSensor(DZ_CURRENT, current_chr); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr); + WSContentSend_PD(HTTP_SNS_CURRENT, current_chr); + WSContentSend_PD(HTTP_SNS_POWER, power_chr); + WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr); +#endif + } + } + +} + + + + + +const char kAdcCommands[] PROGMEM = "|" + D_CMND_ADC "|" D_CMND_ADCS "|" D_CMND_ADCPARAM; + +void (* const AdcCommand[])(void) PROGMEM = { + &CmndAdc, &CmndAdcs, &CmndAdcParam }; + +void CmndAdc(void) +{ + if (ValidAdc() && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < ADC0_END)) { + Settings.my_adc0 = XdrvMailbox.payload; + restart_flag = 2; + } + char stemp1[TOPSZ]; + Response_P(PSTR("{\"" D_CMND_ADC "0\":{\"%d\":\"%s\"}}"), Settings.my_adc0, GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_adc0, kAdc0Names)); +} + +void CmndAdcs(void) +{ + Response_P(PSTR("{\"" D_CMND_ADCS "\":{")); + bool jsflg = false; + char stemp1[TOPSZ]; + for (uint32_t i = 0; i < ADC0_END; i++) { + if (jsflg) { + ResponseAppend_P(PSTR(",")); + } + jsflg = true; + ResponseAppend_P(PSTR("\"%d\":\"%s\""), i, GetTextIndexed(stemp1, sizeof(stemp1), i, kAdc0Names)); + } + ResponseJsonEndEnd(); +} + +void CmndAdcParam(void) +{ + if (XdrvMailbox.data_len) { + if ((ADC0_TEMP == XdrvMailbox.payload) || + (ADC0_LIGHT == XdrvMailbox.payload) || + (ADC0_RANGE == XdrvMailbox.payload) || + (ADC0_CT_POWER == XdrvMailbox.payload)) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { + char sub_string[XdrvMailbox.data_len +1]; + + + + Settings.adc_param_type = XdrvMailbox.payload; + Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); + if (ADC0_RANGE == XdrvMailbox.payload) { + Settings.adc_param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10)); + Settings.adc_param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10)); + } else { + Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); + } + if (ADC0_CT_POWER == XdrvMailbox.payload) { + if ((Settings.adc_param1 & CT_FLAG_ENERGY_RESET) > 0) { + Adc.energy = 0; + Settings.adc_param1 ^= CT_FLAG_ENERGY_RESET; + } + } + } else { + + + + + Settings.adc_param_type = 0; + AdcInit(); + } + } + } + + + Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2); + if (ADC0_RANGE == my_adc0) { + ResponseAppend_P(PSTR(",%d,%d"), Settings.adc_param3, Settings.adc_param4); + } else { + int value = Settings.adc_param3; + uint8_t precision; + for (precision = 4; precision > 0; precision--) { + if (value % 10) { break; } + value /= 10; + } + char param3[33]; + dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); + ResponseAppend_P(PSTR(",%s"), param3); + } + ResponseAppend_P(PSTR("]}")); +} + + + + + +bool Xsns02(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_COMMAND: + result = DecodeCommand(kAdcCommands, AdcCommand); + break; + default: + if ((ADC0_INPUT == my_adc0) || + (ADC0_TEMP == my_adc0) || + (ADC0_LIGHT == my_adc0) || + (ADC0_RANGE == my_adc0) || + (ADC0_CT_POWER == my_adc0)) { + switch (function) { +#ifdef USE_RULES + case FUNC_EVERY_250_MSECOND: + AdcEvery250ms(); + break; +#endif + case FUNC_EVERY_SECOND: + AdcEverySecond(); + break; + case FUNC_INIT: + AdcInit(); + break; + case FUNC_JSON_APPEND: + AdcShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AdcShow(0); + break; +#endif + } + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_04_snfsc.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_04_snfsc.ino" +#ifdef USE_SONOFF_SC +# 57 "S:/Development/Tasmota/tasmota/xsns_04_snfsc.ino" +#define XSNS_04 4 + +uint16_t sc_value[5] = { 0 }; + +void SonoffScSend(const char *data) +{ + Serial.write(data); + Serial.write('\x1B'); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data); +} + +void SonoffScInit(void) +{ + + SonoffScSend("AT+START"); + +} + +void SonoffScSerialInput(char *rcvstat) +{ + char *p; + char *str; + uint16_t value[5] = { 0 }; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat); + + if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { + int8_t i = -1; + for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(nullptr, ":", &p)) { + value[i++] = atoi(str); + } + if (value[0] > 0) { + for (uint32_t i = 0; i < 5; i++) { + sc_value[i] = value[i]; + } + sc_value[2] = (11 - sc_value[2]) * 10; + sc_value[3] *= 10; + sc_value[4] = (11 - sc_value[4]) * 10; + SonoffScSend("AT+SEND=ok"); + } else { + SonoffScSend("AT+SEND=fail"); + } + } + else if (!strcasecmp_P(rcvstat, PSTR("AT+STATUS?"))) { + SonoffScSend("AT+STATUS=4"); + } +} + + + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SCPLUS[] PROGMEM = + "{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; +#endif + +void SonoffScShow(bool json) +{ + if (sc_value[0] > 0) { + float t = ConvertTemp(sc_value[1]); + float h = ConvertHumidity(sc_value[0]); + + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), + temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); + DomoticzSensor(DZ_COUNT, sc_value[3]); + DomoticzSensor(DZ_AIRQUALITY, 500 + ((100 - sc_value[4]) * 20)); + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, t); + KnxSensor(KNX_HUMIDITY, h); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, "", humidity); + WSContentSend_PD(HTTP_SNS_SCPLUS, sc_value[2], sc_value[3], sc_value[4]); +#endif + } + } +} + + + + + +bool Xsns04(uint8_t function) +{ + bool result = false; + + if (SONOFF_SC == my_module_type) { + switch (function) { + case FUNC_JSON_APPEND: + SonoffScShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SonoffScShow(0); + break; +#endif + case FUNC_INIT: + SonoffScInit(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_05_ds18x20.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_05_ds18x20.ino" +#ifdef USE_DS18x20 + + + + +#define XSNS_05 5 + + + +#define DS18S20_CHIPID 0x10 +#define DS1822_CHIPID 0x22 +#define DS18B20_CHIPID 0x28 +#define MAX31850_CHIPID 0x3B + +#define W1_SKIP_ROM 0xCC +#define W1_CONVERT_TEMP 0x44 +#define W1_WRITE_EEPROM 0x48 +#define W1_WRITE_SCRATCHPAD 0x4E +#define W1_READ_SCRATCHPAD 0xBE + +#define DS18X20_MAX_SENSORS 8 + +const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; + +uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; + +struct DS18X20STRUCT { + uint8_t address[8]; + uint8_t index; + uint8_t valid; + float temperature; +} ds18x20_sensor[DS18X20_MAX_SENSORS]; +uint8_t ds18x20_sensors = 0; +uint8_t ds18x20_pin = 0; +uint8_t ds18x20_pin_out = 0; +bool ds18x20_dual_mode = false; +char ds18x20_types[12]; +#ifdef W1_PARASITE_POWER +uint8_t ds18x20_sensor_curr = 0; +unsigned long w1_power_until = 0; +#endif + + + + + +#define W1_MATCH_ROM 0x55 +#define W1_SEARCH_ROM 0xF0 + +uint8_t onewire_last_discrepancy = 0; +uint8_t onewire_last_family_discrepancy = 0; +bool onewire_last_device_flag = false; +unsigned char onewire_rom_id[8] = { 0 }; + + + +uint8_t OneWireReset(void) +{ + uint8_t retries = 125; + + if (!ds18x20_dual_mode) { + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + do { + if (--retries == 0) { + return 0; + } + delayMicroseconds(2); + } while (!digitalRead(ds18x20_pin)); + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(480); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + } else { + digitalWrite(ds18x20_pin_out, HIGH); + do { + if (--retries == 0) { + return 0; + } + delayMicroseconds(2); + } while (!digitalRead(ds18x20_pin)); + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(480); + digitalWrite(ds18x20_pin_out, HIGH); + } + delayMicroseconds(70); + uint8_t r = !digitalRead(ds18x20_pin); + delayMicroseconds(410); + return r; +} + +void OneWireWriteBit(uint8_t v) +{ + static const uint8_t delay_low[2] = { 65, 10 }; + static const uint8_t delay_high[2] = { 5, 55 }; + + v &= 1; + if (!ds18x20_dual_mode) { + digitalWrite(ds18x20_pin, LOW); + pinMode(ds18x20_pin, OUTPUT); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin, HIGH); + } else { + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(delay_low[v]); + digitalWrite(ds18x20_pin_out, HIGH); + } + delayMicroseconds(delay_high[v]); +} +# 150 "S:/Development/Tasmota/tasmota/xsns_05_ds18x20.ino" +void OneWireReadBit1(void) +{ + pinMode(ds18x20_pin, OUTPUT); + digitalWrite(ds18x20_pin, LOW); + delayMicroseconds(3); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); +} + +void OneWireReadBit2(void) +{ + digitalWrite(ds18x20_pin_out, LOW); + delayMicroseconds(3); + digitalWrite(ds18x20_pin_out, HIGH); +} + +uint8_t OneWireReadBit(void) +{ + if (!ds18x20_dual_mode) { + OneWireReadBit1(); + } else { + OneWireReadBit2(); + } + delayMicroseconds(10); + uint8_t r = digitalRead(ds18x20_pin); + delayMicroseconds(53); + return r; +} + + + +void OneWireWrite(uint8_t v) +{ + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + OneWireWriteBit((bit_mask & v) ? 1 : 0); + } +} + +uint8_t OneWireRead(void) +{ + uint8_t r = 0; + + for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { + if (OneWireReadBit()) { + r |= bit_mask; + } + } + return r; +} + +void OneWireSelect(const uint8_t rom[8]) +{ + OneWireWrite(W1_MATCH_ROM); + for (uint32_t i = 0; i < 8; i++) { + OneWireWrite(rom[i]); + } +} + +void OneWireResetSearch(void) +{ + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + for (uint32_t i = 0; i < 8; i++) { + onewire_rom_id[i] = 0; + } +} + +uint8_t OneWireSearch(uint8_t *newAddr) +{ + uint8_t id_bit_number = 1; + uint8_t last_zero = 0; + uint8_t rom_byte_number = 0; + uint8_t search_result = 0; + uint8_t id_bit; + uint8_t cmp_id_bit; + unsigned char rom_byte_mask = 1; + unsigned char search_direction; + + if (!onewire_last_device_flag) { + if (!OneWireReset()) { + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + return false; + } + OneWireWrite(W1_SEARCH_ROM); + do { + id_bit = OneWireReadBit(); + cmp_id_bit = OneWireReadBit(); + + if ((id_bit == 1) && (cmp_id_bit == 1)) { + break; + } else { + if (id_bit != cmp_id_bit) { + search_direction = id_bit; + } else { + if (id_bit_number < onewire_last_discrepancy) { + search_direction = ((onewire_rom_id[rom_byte_number] & rom_byte_mask) > 0); + } else { + search_direction = (id_bit_number == onewire_last_discrepancy); + } + if (search_direction == 0) { + last_zero = id_bit_number; + if (last_zero < 9) { + onewire_last_family_discrepancy = last_zero; + } + } + } + if (search_direction == 1) { + onewire_rom_id[rom_byte_number] |= rom_byte_mask; + } else { + onewire_rom_id[rom_byte_number] &= ~rom_byte_mask; + } + OneWireWriteBit(search_direction); + id_bit_number++; + rom_byte_mask <<= 1; + if (rom_byte_mask == 0) { + rom_byte_number++; + rom_byte_mask = 1; + } + } + } while (rom_byte_number < 8); + if (!(id_bit_number < 65)) { + onewire_last_discrepancy = last_zero; + if (onewire_last_discrepancy == 0) { + onewire_last_device_flag = true; + } + search_result = true; + } + } + if (!search_result || !onewire_rom_id[0]) { + onewire_last_discrepancy = 0; + onewire_last_device_flag = false; + onewire_last_family_discrepancy = 0; + search_result = false; + } + for (uint32_t i = 0; i < 8; i++) { + newAddr[i] = onewire_rom_id[i]; + } + return search_result; +} + +bool OneWireCrc8(uint8_t *addr) +{ + uint8_t crc = 0; + uint8_t len = 8; + + while (len--) { + uint8_t inbyte = *addr++; + for (uint32_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x01; + crc >>= 1; + if (mix) { + crc ^= 0x8C; + } + inbyte >>= 1; + } + } + return (crc == *addr); +} + + + +void Ds18x20Init(void) +{ + uint64_t ids[DS18X20_MAX_SENSORS]; + + ds18x20_pin = pin[GPIO_DSB]; + + if (pin[GPIO_DSB_OUT] < 99) { + ds18x20_pin_out = pin[GPIO_DSB_OUT]; + ds18x20_dual_mode = true; + pinMode(ds18x20_pin_out, OUTPUT); + pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); + } + + OneWireResetSearch(); + + ds18x20_sensors = 0; + while (ds18x20_sensors < DS18X20_MAX_SENSORS) { + if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { + break; + } + if (OneWireCrc8(ds18x20_sensor[ds18x20_sensors].address) && + ((ds18x20_sensor[ds18x20_sensors].address[0] == DS18S20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS1822_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == DS18B20_CHIPID) || + (ds18x20_sensor[ds18x20_sensors].address[0] == MAX31850_CHIPID))) { + ds18x20_sensor[ds18x20_sensors].index = ds18x20_sensors; + ids[ds18x20_sensors] = ds18x20_sensor[ds18x20_sensors].address[0]; + for (uint32_t j = 6; j > 0; j--) { + ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_sensor[ds18x20_sensors].address[j]; + } + ds18x20_sensors++; + } + } + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + for (uint32_t j = i + 1; j < ds18x20_sensors; j++) { + if (ids[ds18x20_sensor[i].index] > ids[ds18x20_sensor[j].index]) { + std::swap(ds18x20_sensor[i].index, ds18x20_sensor[j].index); + } + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); +} + +void Ds18x20Convert(void) +{ + OneWireReset(); +#ifdef W1_PARASITE_POWER + + if (++ds18x20_sensor_curr >= ds18x20_sensors) + ds18x20_sensor_curr = 0; + OneWireSelect(ds18x20_sensor[ds18x20_sensor_curr].address); +#else + OneWireWrite(W1_SKIP_ROM); +#endif + OneWireWrite(W1_CONVERT_TEMP); + +} + +bool Ds18x20Read(uint8_t sensor) +{ + uint8_t data[9]; + int8_t sign = 1; + + uint8_t index = ds18x20_sensor[sensor].index; + if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } + for (uint32_t retry = 0; retry < 3; retry++) { + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_READ_SCRATCHPAD); + for (uint32_t i = 0; i < 9; i++) { + data[i] = OneWireRead(); + } + if (OneWireCrc8(data)) { + switch(ds18x20_sensor[index].address[0]) { + case DS18S20_CHIPID: { + if (data[1] > 0x80) { + data[0] = (~data[0]) +1; + sign = -1; + } + float temp9 = (float)(data[0] >> 1) * sign; + ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + case DS1822_CHIPID: + case DS18B20_CHIPID: { + if (data[4] != 0x7F) { + data[4] = 0x7F; + OneWireReset(); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_SCRATCHPAD); + OneWireWrite(data[2]); + OneWireWrite(data[3]); + OneWireWrite(data[4]); + OneWireSelect(ds18x20_sensor[index].address); + OneWireWrite(W1_WRITE_EEPROM); +#ifdef W1_PARASITE_POWER + w1_power_until = millis() + 10; +#endif + } + uint16_t temp12 = (data[1] << 8) + data[0]; + if (temp12 > 2047) { + temp12 = (~temp12) +1; + sign = -1; + } + ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + case MAX31850_CHIPID: { + int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); + ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); + ds18x20_sensor[index].valid = SENSOR_MAX_MISS; + return true; + } + } + } + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); + return false; +} + +void Ds18x20Name(uint8_t sensor) +{ + uint8_t index = sizeof(ds18x20_chipids); + while (index) { + if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) { + break; + } + index--; + } + GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); + if (ds18x20_sensors > 1) { + snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), sensor +1); + } +} + + + +void Ds18x20EverySecond(void) +{ + if (!ds18x20_sensors) { return; } + +#ifdef W1_PARASITE_POWER + + unsigned long now = millis(); + if (now < w1_power_until) + return; +#endif + if (uptime & 1 +#ifdef W1_PARASITE_POWER + + || ds18x20_sensors >= 2 +#endif + ) { + + Ds18x20Convert(); + } else { + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + + if (!Ds18x20Read(i)) { + Ds18x20Name(i); + AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); +#ifdef USE_DS18x20_RECONFIGURE + if (!ds18x20_sensor[ds18x20_sensor[i].index].valid) { + memset(&ds18x20_sensor, 0, sizeof(ds18x20_sensor)); + Ds18x20Init(); + } +#endif + } + } + } +} + +void Ds18x20Show(bool json) +{ + for (uint32_t i = 0; i < ds18x20_sensors; i++) { + uint8_t index = ds18x20_sensor[i].index; + + if (ds18x20_sensor[index].valid) { + char temperature[33]; + dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); + + Ds18x20Name(i); + + if (json) { + char address[17]; + for (uint32_t j = 0; j < 6; j++) { + sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); + } + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); +#endif + } + } + } +} + + + + + +bool Xsns05(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_DSB] < 99) { + switch (function) { + case FUNC_INIT: + Ds18x20Init(); + break; + case FUNC_EVERY_SECOND: + Ds18x20EverySecond(); + break; + case FUNC_JSON_APPEND: + Ds18x20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ds18x20Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_old.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_old.ino" +#ifdef USE_DHT_OLD +# 29 "S:/Development/Tasmota/tasmota/xsns_06_dht_old.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint32_t dht_max_cycles; +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +void DhtReadPrep(void) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + if (!dht_dual_mode) { + digitalWrite(Dht[i].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + } +} + +int32_t DhtExpectPulse(uint8_t sensor, bool level) +{ + int32_t count = 0; + + while (digitalRead(Dht[sensor].pin) == level) { + if (count++ >= (int32_t)dht_max_cycles) { + return -1; + } + } + return count; +} + +bool DhtRead(uint8_t sensor) +{ + int32_t cycles[80]; + uint8_t error = 0; + + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + + + + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].lastresult = 0; + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delay(250); + } + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + if (GPIO_SI7021 == Dht[sensor].type) { + delayMicroseconds(500); + } else { + delay(20); + } + + noInterrupts(); + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + delayMicroseconds(40); + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + delayMicroseconds(40); + } + delayMicroseconds(10); + if (-1 == DhtExpectPulse(sensor, LOW)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + error = 1; + } + else if (-1 == DhtExpectPulse(sensor, HIGH)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); + error = 1; + } + else { + for (uint32_t i = 0; i < 80; i += 2) { + cycles[i] = DhtExpectPulse(sensor, LOW); + cycles[i+1] = DhtExpectPulse(sensor, HIGH); + } + } + interrupts(); + + if (error) { return false; } + + for (uint32_t i = 0; i < 40; ++i) { + int32_t lowCycles = cycles[2*i]; + int32_t highCycles = cycles[2*i+1]; + if ((-1 == lowCycles) || (-1 == highCycles)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); + return false; + } + dht_data[i/8] <<= 1; + if (highCycles > lowCycles) { + dht_data[i / 8] |= 1; + } + } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint8_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + dht_max_cycles = microsecondsToClockCycles(1000); + + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + + DhtReadPrep(); + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" +#ifdef USE_DHT_V2 +# 29 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint32_t dht_max_cycles; +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +void DhtReadPrep(void) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + if (!dht_dual_mode) { + digitalWrite(Dht[i].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + } +} + +int32_t DhtExpectPulse(uint8_t sensor, bool level) +{ + int32_t count = 0; + + while (digitalRead(Dht[sensor].pin) == level) { + if (count++ >= (int32_t)dht_max_cycles) { + return -1; + } + } + return count; +} + +bool DhtRead(uint8_t sensor) +{ + int32_t cycles[80]; + uint8_t error = 0; + + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].lastresult = 0; + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delay(250); + } + + + noInterrupts(); + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_SI7021: +# 114 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" + delayMicroseconds(500); + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delayMicroseconds(40); + break; + + case GPIO_DHT22: +# 133 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" + delayMicroseconds(1100); + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delayMicroseconds(30); + break; + + case GPIO_DHT11: +# 151 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" + default: + + delay(20); + if (!dht_dual_mode) { + digitalWrite(Dht[sensor].pin, HIGH); + } else { + digitalWrite(dht_pin_out, HIGH); + } + delayMicroseconds(30); + break; + } + + + pinMode(Dht[sensor].pin, INPUT_PULLUP); + + if (-1 == DhtExpectPulse(sensor, LOW)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + error = 1; + } + else if (-1 == DhtExpectPulse(sensor, HIGH)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); + error = 1; + } + else { + for (uint32_t i = 0; i < 80; i += 2) { + cycles[i] = DhtExpectPulse(sensor, LOW); + cycles[i+1] = DhtExpectPulse(sensor, HIGH); + } + } + interrupts(); + if (error) { return false; } + + + for (uint32_t i = 0; i < 40; ++i) { + int32_t lowCycles = cycles[2*i]; + int32_t highCycles = cycles[2*i+1]; + if ((-1 == lowCycles) || (-1 == highCycles)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); + return false; + } + dht_data[i/8] <<= 1; + if (highCycles > lowCycles) { + dht_data[i / 8] |= 1; + } + } + + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint8_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + dht_max_cycles = microsecondsToClockCycles(1000); + + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v2) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + + DhtReadPrep(); + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_v3.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_v3.ino" +#ifdef USE_DHT_V3 +# 30 "S:/Development/Tasmota/tasmota/xsns_06_dht_v3.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +bool DhtExpectPulse(uint8_t sensor, int level) +{ + unsigned long timeout = micros() + 100; + while (digitalRead(Dht[sensor].pin) != level) { + if (micros() > timeout) { return false; } + delayMicroseconds(1); + } + return true; +} + +int DhtReadDat(uint8_t sensor) +{ + uint8_t result = 0; + for (uint32_t i = 0; i < 8; i++) { + if (!DhtExpectPulse(sensor, HIGH)) { return -1; } + + delayMicroseconds(35); + if (digitalRead(Dht[sensor].pin)) { + result |= (1 << (7 - i)); + } + + if (!DhtExpectPulse(sensor, LOW)) { return -1; } + } + return result; +} + +bool DhtRead(uint8_t sensor) +{ + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + delay(19); + break; + case GPIO_DHT22: + delay(2); + break; + case GPIO_SI7021: + delayMicroseconds(500); + break; + } + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + case GPIO_DHT22: + delayMicroseconds(50); + break; + case GPIO_SI7021: + + delayMicroseconds(20); + break; + } + + noInterrupts(); + if (!DhtExpectPulse(sensor, LOW)) { + interrupts(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + return false; + } + if (!DhtExpectPulse(sensor, HIGH)) { + interrupts(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); + return false; + } + if (!DhtExpectPulse(sensor, LOW)) { + interrupts(); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); + return false; + } + + int data = 0; + for (uint32_t i = 0; i < 5; i++) { + data = DhtReadDat(sensor); + if (-1 == data) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); + break; + } + dht_data[i] = data; + } + interrupts(); + if (-1 == data) { return false; } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint8_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v3) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + + + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_v4.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_v4.ino" +#ifdef USE_DHT_V4 +# 30 "S:/Development/Tasmota/tasmota/xsns_06_dht_v4.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + char stype[12]; + uint32_t lastreadtime; + uint8_t lastresult; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +bool DhtExpectPulse(uint32_t sensor, uint32_t level) +{ + unsigned long timeout = micros() + 100; + while (digitalRead(Dht[sensor].pin) != level) { + if (micros() > timeout) { return false; } + delayMicroseconds(1); + } + return true; +} + +bool DhtRead(uint32_t sensor) +{ + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + delay(19); + break; + case GPIO_DHT22: + delay(2); + break; + case GPIO_SI7021: + delayMicroseconds(500); + break; + } + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + case GPIO_DHT22: + delayMicroseconds(50); + break; + case GPIO_SI7021: + delayMicroseconds(20); + break; + } + + uint32_t level = 9; + noInterrupts(); + for (uint32_t i = 0; i < 3; i++) { + level = i &1; + if (!DhtExpectPulse(sensor, level)) { break; } + level = 9; + } + if (9 == level) { + int data = 0; + for (uint32_t i = 0; i < 5; i++) { + data = 0; + for (uint32_t j = 0; j < 8; j++) { + level = 1; + if (!DhtExpectPulse(sensor, level)) { break; } + + delayMicroseconds(35); + if (digitalRead(Dht[sensor].pin)) { + data |= (1 << (7 - j)); + } + + level = 0; + if (!DhtExpectPulse(sensor, level)) { break; } + level = 9; + } + if (level < 2) { break; } + + dht_data[i] = data; + } + } + interrupts(); + if (level < 2) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), (0 == level) ? D_START_SIGNAL_LOW : D_START_SIGNAL_HIGH); + return false; + } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + return true; +} + +void DhtReadTempHum(uint32_t sensor) +{ + if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + if (DhtRead(sensor)) { + switch (Dht[sensor].type) { + case GPIO_DHT11: + Dht[sensor].h = dht_data[0]; + Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + Dht[sensor].t *= -1; + } + break; + } + Dht[sensor].t = ConvertTemp(Dht[sensor].t); + if (Dht[sensor].h > 100) { Dht[sensor].h = 100.0; } + if (Dht[sensor].h < 0) { Dht[sensor].h = 0.0; } + Dht[sensor].h = ConvertHumidity(Dht[sensor].h); + Dht[sensor].lastresult = 0; + } else { + Dht[sensor].lastresult++; + } +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastreadtime = 0; + Dht[i].lastresult = 0; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v4) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + } else { + for (uint32_t i = 0; i < dht_sensors; i++) { + + DhtReadTempHum(i); + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_v5.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_v5.ino" +#ifdef USE_DHT +# 30 "S:/Development/Tasmota/tasmota/xsns_06_dht_v5.ino" +#define XSNS_06 6 + +#define DHT_MAX_SENSORS 4 +#define DHT_MAX_RETRY 8 + +uint8_t dht_data[5]; +uint8_t dht_sensors = 0; +uint8_t dht_pin_out = 0; +bool dht_active = true; +bool dht_dual_mode = false; + +struct DHTSTRUCT { + uint8_t pin; + uint8_t type; + uint8_t lastresult; + char stype[12]; + float t = NAN; + float h = NAN; +} Dht[DHT_MAX_SENSORS]; + +bool DhtWaitState(uint32_t sensor, uint32_t level) +{ + unsigned long timeout = micros() + 100; + while (digitalRead(Dht[sensor].pin) != level) { + if (TimeReachedUsec(timeout)) { + PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), + (level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW); + return false; + } + delayMicroseconds(1); + } + return true; +} + +bool DhtRead(uint32_t sensor) +{ + dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, OUTPUT); + digitalWrite(Dht[sensor].pin, LOW); + } else { + digitalWrite(dht_pin_out, LOW); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + delay(19); + break; + case GPIO_DHT22: + delay(2); + break; + case GPIO_SI7021: + delayMicroseconds(500); + break; + } + + if (!dht_dual_mode) { + pinMode(Dht[sensor].pin, INPUT_PULLUP); + } else { + digitalWrite(dht_pin_out, HIGH); + } + + switch (Dht[sensor].type) { + case GPIO_DHT11: + case GPIO_DHT22: + delayMicroseconds(50); + break; + case GPIO_SI7021: + delayMicroseconds(20); + break; + } +# 133 "S:/Development/Tasmota/tasmota/xsns_06_dht_v5.ino" + uint32_t i = 0; + noInterrupts(); + if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { + for (i = 0; i < 40; i++) { + if (!DhtWaitState(sensor, 1)) { break; } + delayMicroseconds(35); + if (digitalRead(Dht[sensor].pin)) { + dht_data[i / 8] |= (1 << (7 - i % 8)); + } + if (!DhtWaitState(sensor, 0)) { break; } + } + } + interrupts(); + if (i < 40) { return false; } + + uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; + if (dht_data[4] != checksum) { + char hex_char[15]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), + ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); + return false; + } + + float temperature = NAN; + float humidity = NAN; + switch (Dht[sensor].type) { + case GPIO_DHT11: + humidity = dht_data[0]; + temperature = dht_data[2] + ((float)dht_data[3] * 0.1f); + break; + case GPIO_DHT22: + case GPIO_SI7021: + humidity = ((dht_data[0] << 8) | dht_data[1]) * 0.1; + temperature = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; + if (dht_data[2] & 0x80) { + temperature *= -1; + } + break; + } + if (isnan(temperature) || isnan(humidity)) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid NAN reading")); + return false; + } + + if (humidity > 100) { humidity = 100.0; } + if (humidity < 0) { humidity = 0.1; } + Dht[sensor].h = ConvertHumidity(humidity); + Dht[sensor].t = ConvertTemp(temperature); + Dht[sensor].lastresult = 0; + + return true; +} + + + +bool DhtPinState() +{ + if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { + if (dht_sensors < DHT_MAX_SENSORS) { + Dht[dht_sensors].pin = XdrvMailbox.payload; + Dht[dht_sensors].type = XdrvMailbox.index; + dht_sensors++; + XdrvMailbox.index = GPIO_DHT11; + } else { + XdrvMailbox.index = 0; + } + return true; + } + return false; +} + +void DhtInit(void) +{ + if (dht_sensors) { + if (pin[GPIO_DHT11_OUT] < 99) { + dht_pin_out = pin[GPIO_DHT11_OUT]; + dht_dual_mode = true; + dht_sensors = 1; + pinMode(dht_pin_out, OUTPUT); + } + + for (uint32_t i = 0; i < dht_sensors; i++) { + pinMode(Dht[i].pin, INPUT_PULLUP); + Dht[i].lastresult = DHT_MAX_RETRY; + GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); + if (dht_sensors > 1) { + snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); + } + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v5) " D_SENSORS_FOUND " %d"), dht_sensors); + } else { + dht_active = false; + } +} + +void DhtEverySecond(void) +{ + if (uptime &1) { + for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { + + if (!DhtRead(sensor)) { + Dht[sensor].lastresult++; + if (Dht[sensor].lastresult > DHT_MAX_RETRY) { + Dht[sensor].t = NAN; + Dht[sensor].h = NAN; + } + } + } + } +} + +void DhtShow(bool json) +{ + for (uint32_t i = 0; i < dht_sensors; i++) { + char temperature[33]; + dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if ((0 == tele_period) && (0 == i)) { + KnxSensor(KNX_TEMPERATURE, Dht[i].t); + KnxSensor(KNX_HUMIDITY, Dht[i].h); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); +#endif + } + } +} + + + + + +bool Xsns06(uint8_t function) +{ + bool result = false; + + if (dht_active) { + switch (function) { + case FUNC_EVERY_SECOND: + DhtEverySecond(); + break; + case FUNC_JSON_APPEND: + DhtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DhtShow(0); + break; +#endif + case FUNC_INIT: + DhtInit(); + break; + case FUNC_PIN_STATE: + result = DhtPinState(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_07_sht1x.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_07_sht1x.ino" +#ifdef USE_I2C +#ifdef USE_SHT +# 31 "S:/Development/Tasmota/tasmota/xsns_07_sht1x.ino" +#define XSNS_07 7 +#define XI2C_08 8 + +enum { + SHT1X_CMD_MEASURE_TEMP = B00000011, + SHT1X_CMD_MEASURE_RH = B00000101, + SHT1X_CMD_SOFT_RESET = B00011110 +}; + +uint8_t sht_sda_pin; +uint8_t sht_scl_pin; +uint8_t sht_type = 0; +char sht_types[] = "SHT1X"; +uint8_t sht_valid = 0; +float sht_temperature = 0; +float sht_humidity = 0; + +bool ShtReset(void) +{ + pinMode(sht_sda_pin, INPUT_PULLUP); + pinMode(sht_scl_pin, OUTPUT); + delay(11); + for (uint32_t i = 0; i < 9; i++) { + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + } + bool success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); + delay(11); + return success; +} + +bool ShtSendCommand(const uint8_t cmd) +{ + pinMode(sht_sda_pin, OUTPUT); + + digitalWrite(sht_sda_pin, HIGH); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_sda_pin, LOW); + digitalWrite(sht_scl_pin, LOW); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_sda_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + + shiftOut(sht_sda_pin, sht_scl_pin, MSBFIRST, cmd); + + bool ackerror = false; + digitalWrite(sht_scl_pin, HIGH); + pinMode(sht_sda_pin, INPUT_PULLUP); + if (digitalRead(sht_sda_pin) != LOW) { + ackerror = true; + } + digitalWrite(sht_scl_pin, LOW); + delayMicroseconds(1); + if (digitalRead(sht_sda_pin) != HIGH) { + ackerror = true; + } + if (ackerror) { + + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_DID_NOT_ACK_COMMAND)); + } + return (!ackerror); +} + +bool ShtAwaitResult(void) +{ + + for (uint32_t i = 0; i < 16; i++) { + if (LOW == digitalRead(sht_sda_pin)) { + return true; + } + delay(20); + } + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_BUSY)); + + return false; +} + +int ShtReadData(void) +{ + int val = 0; + + + val = shiftIn(sht_sda_pin, sht_scl_pin, 8); + val <<= 8; + + pinMode(sht_sda_pin, OUTPUT); + digitalWrite(sht_sda_pin, LOW); + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + pinMode(sht_sda_pin, INPUT_PULLUP); + + val |= shiftIn(sht_sda_pin, sht_scl_pin, 8); + + digitalWrite(sht_scl_pin, HIGH); + digitalWrite(sht_scl_pin, LOW); + return val; +} + +bool ShtRead(void) +{ + if (sht_valid) { sht_valid--; } + if (!ShtReset()) { return false; } + if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { return false; } + if (!ShtAwaitResult()) { return false; } + float tempRaw = ShtReadData(); + if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { return false; } + if (!ShtAwaitResult()) { return false; } + float humRaw = ShtReadData(); + + + const float d1 = -39.7; + const float d2 = 0.01; + sht_temperature = d1 + (tempRaw * d2); + const float c1 = -2.0468; + const float c2 = 0.0367; + const float c3 = -1.5955E-6; + const float t1 = 0.01; + const float t2 = 0.00008; + float rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; + sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear; + sht_temperature = ConvertTemp(sht_temperature); + ConvertHumidity(sht_humidity); + + sht_valid = SENSOR_MAX_MISS; + return true; +} + + + +void ShtDetect(void) +{ + sht_sda_pin = pin[GPIO_I2C_SDA]; + sht_scl_pin = pin[GPIO_I2C_SCL]; + if (ShtRead()) { + sht_type = 1; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); + } else { + Wire.begin(sht_sda_pin, sht_scl_pin); + sht_type = 0; + } +} + +void ShtEverySecond(void) +{ + if (!(uptime %4)) { + + if (!ShtRead()) { + AddLogMissed(sht_types, sht_valid); + } + } +} + +void ShtShow(bool json) +{ + if (sht_valid) { + char temperature[33]; + dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, sht_types, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, sht_temperature); + KnxSensor(KNX_HUMIDITY, sht_humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sht_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, sht_types, humidity); +#endif + } + } +} + + + + + +bool Xsns07(uint8_t function) +{ + if (!I2cEnabled(XI2C_08)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + ShtDetect(); + } + else if (sht_type) { + switch (function) { + case FUNC_EVERY_SECOND: + ShtEverySecond(); + break; + case FUNC_JSON_APPEND: + ShtShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + ShtShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_08_htu21.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_08_htu21.ino" +#ifdef USE_I2C +#ifdef USE_HTU +# 30 "S:/Development/Tasmota/tasmota/xsns_08_htu21.ino" +#define XSNS_08 8 +#define XI2C_09 9 + +#define HTU21_ADDR 0x40 + +#define SI7013_CHIPID 0x0D +#define SI7020_CHIPID 0x14 +#define SI7021_CHIPID 0x15 +#define HTU21_CHIPID 0x32 + +#define HTU21_READTEMP 0xE3 +#define HTU21_READHUM 0xE5 +#define HTU21_WRITEREG 0xE6 +#define HTU21_READREG 0xE7 +#define HTU21_RESET 0xFE +#define HTU21_HEATER_WRITE 0x51 +#define HTU21_HEATER_READ 0x11 +#define HTU21_SERIAL2_READ1 0xFC +#define HTU21_SERIAL2_READ2 0xC9 + +#define HTU21_HEATER_ON 0x04 +#define HTU21_HEATER_OFF 0xFB + +#define HTU21_RES_RH12_T14 0x00 +#define HTU21_RES_RH8_T12 0x01 +#define HTU21_RES_RH10_T13 0x80 +#define HTU21_RES_RH11_T11 0x81 + +#define HTU21_CRC8_POLYNOM 0x13100 + +const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?"; + +uint8_t htu_address; +uint8_t htu_type = 0; +uint8_t htu_delay_temp; +uint8_t htu_delay_humidity = 50; +uint8_t htu_valid = 0; +float htu_temperature = 0; +float htu_humidity = 0; +char htu_types[7]; + +uint8_t HtuCheckCrc8(uint16_t data) +{ + for (uint32_t bit = 0; bit < 16; bit++) { + if (data & 0x8000) { + data = (data << 1) ^ HTU21_CRC8_POLYNOM; + } else { + data <<= 1; + } + } + return data >>= 8; +} + +uint8_t HtuReadDeviceId(void) +{ + uint16_t deviceID = 0; + uint8_t checksum = 0; + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_SERIAL2_READ1); + Wire.write(HTU21_SERIAL2_READ2); + Wire.endTransmission(); + + Wire.requestFrom(HTU21_ADDR, 3); + deviceID = Wire.read() << 8; + deviceID |= Wire.read(); + checksum = Wire.read(); + if (HtuCheckCrc8(deviceID) == checksum) { + deviceID = deviceID >> 8; + } else { + deviceID = 0; + } + return (uint8_t)deviceID; +} + +void HtuSetResolution(uint8_t resolution) +{ + uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); + current &= 0x7E; + current |= resolution; + I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); +} + +void HtuReset(void) +{ + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_RESET); + Wire.endTransmission(); + delay(15); +} + +void HtuHeater(uint8_t heater) +{ + uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); + + switch(heater) + { + case HTU21_HEATER_ON : current |= heater; + break; + case HTU21_HEATER_OFF : current &= heater; + break; + default : current &= heater; + break; + } + I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); +} + +void HtuInit(void) +{ + HtuReset(); + HtuHeater(HTU21_HEATER_OFF); + HtuSetResolution(HTU21_RES_RH12_T14); +} + +bool HtuRead(void) +{ + uint8_t checksum = 0; + uint16_t sensorval = 0; + + if (htu_valid) { htu_valid--; } + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_READTEMP); + if (Wire.endTransmission() != 0) { return false; } + delay(htu_delay_temp); + + Wire.requestFrom(HTU21_ADDR, 3); + if (3 == Wire.available()) { + sensorval = Wire.read() << 8; + sensorval |= Wire.read(); + checksum = Wire.read(); + } + if (HtuCheckCrc8(sensorval) != checksum) { return false; } + + htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); + + Wire.beginTransmission(HTU21_ADDR); + Wire.write(HTU21_READHUM); + if (Wire.endTransmission() != 0) { return false; } + delay(htu_delay_humidity); + + Wire.requestFrom(HTU21_ADDR, 3); + if (3 <= Wire.available()) { + sensorval = Wire.read() << 8; + sensorval |= Wire.read(); + checksum = Wire.read(); + } + if (HtuCheckCrc8(sensorval) != checksum) { return false; } + + sensorval ^= 0x02; + htu_humidity = 0.001907 * (float)sensorval - 6; + if (htu_humidity > 100) { htu_humidity = 100.0; } + if (htu_humidity < 0) { htu_humidity = 0.01; } + + if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) { + htu_humidity = 0.0; + } + if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) { + htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity; + } + ConvertHumidity(htu_humidity); + + htu_valid = SENSOR_MAX_MISS; + return true; +} + + + +void HtuDetect(void) +{ + htu_address = HTU21_ADDR; + if (I2cActive(htu_address)) { return; } + + htu_type = HtuReadDeviceId(); + if (htu_type) { + uint8_t index = 0; + HtuInit(); + switch (htu_type) { + case HTU21_CHIPID: + htu_delay_temp = 50; + htu_delay_humidity = 16; + break; + case SI7021_CHIPID: + index++; + case SI7020_CHIPID: + index++; + case SI7013_CHIPID: + index++; + htu_delay_temp = 12; + htu_delay_humidity = 23; + break; + default: + index = 4; + htu_delay_temp = 50; + htu_delay_humidity = 23; + } + GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); + I2cSetActiveFound(htu_address, htu_types); + } +} + +void HtuEverySecond(void) +{ + if (uptime &1) { + + if (!HtuRead()) { + AddLogMissed(htu_types, htu_valid); + } + } +} + +void HtuShow(bool json) +{ + if (htu_valid) { + char temperature[33]; + dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, htu_types, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, htu_temperature); + KnxSensor(KNX_HUMIDITY, htu_humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, htu_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, htu_types, humidity); +#endif + } + } +} + + + + + +bool Xsns08(uint8_t function) +{ + if (!I2cEnabled(XI2C_09)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + HtuDetect(); + } + else if (htu_type) { + switch (function) { + case FUNC_EVERY_SECOND: + HtuEverySecond(); + break; + case FUNC_JSON_APPEND: + HtuShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HtuShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_09_bmp.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_09_bmp.ino" +#ifdef USE_I2C +#ifdef USE_BMP +# 30 "S:/Development/Tasmota/tasmota/xsns_09_bmp.ino" +#define XSNS_09 9 +#define XI2C_10 10 + +#define BMP_ADDR1 0x76 +#define BMP_ADDR2 0x77 + +#define BMP180_CHIPID 0x55 +#define BMP280_CHIPID 0x58 +#define BME280_CHIPID 0x60 +#define BME680_CHIPID 0x61 + +#define BMP_REGISTER_CHIPID 0xD0 + +#define BMP_REGISTER_RESET 0xE0 + +#define BMP_CMND_RESET 0xB6 + +#define BMP_MAX_SENSORS 2 + +const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; + +typedef struct { + uint8_t bmp_address; + char bmp_name[7]; + uint8_t bmp_type; + uint8_t bmp_model; +#ifdef USE_BME680 + uint8_t bme680_state; + float bmp_gas_resistance; +#endif + float bmp_temperature; + float bmp_pressure; + float bmp_humidity; +} bmp_sensors_t; + +uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; +uint8_t bmp_count = 0; +uint8_t bmp_once = 1; + +bmp_sensors_t *bmp_sensors = nullptr; + + + + + +#define BMP180_REG_CONTROL 0xF4 +#define BMP180_REG_RESULT 0xF6 +#define BMP180_TEMPERATURE 0x2E +#define BMP180_PRESSURE3 0xF4 + +#define BMP180_AC1 0xAA +#define BMP180_AC2 0xAC +#define BMP180_AC3 0xAE +#define BMP180_AC4 0xB0 +#define BMP180_AC5 0xB2 +#define BMP180_AC6 0xB4 +#define BMP180_VB1 0xB6 +#define BMP180_VB2 0xB8 +#define BMP180_MB 0xBA +#define BMP180_MC 0xBC +#define BMP180_MD 0xBE + +#define BMP180_OSS 3 + +typedef struct { + int16_t cal_ac1; + int16_t cal_ac2; + int16_t cal_ac3; + int16_t cal_b1; + int16_t cal_b2; + int16_t cal_mc; + int16_t cal_md; + uint16_t cal_ac4; + uint16_t cal_ac5; + uint16_t cal_ac6; +} bmp180_cal_data_t; + +bmp180_cal_data_t *bmp180_cal_data = nullptr; + +bool Bmp180Calibration(uint8_t bmp_idx) +{ + if (!bmp180_cal_data) { + bmp180_cal_data = (bmp180_cal_data_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp180_cal_data_t)); + } + if (!bmp180_cal_data) { return false; } + + bmp180_cal_data[bmp_idx].cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1); + bmp180_cal_data[bmp_idx].cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2); + bmp180_cal_data[bmp_idx].cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3); + bmp180_cal_data[bmp_idx].cal_ac4 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC4); + bmp180_cal_data[bmp_idx].cal_ac5 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC5); + bmp180_cal_data[bmp_idx].cal_ac6 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC6); + bmp180_cal_data[bmp_idx].cal_b1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB1); + bmp180_cal_data[bmp_idx].cal_b2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB2); + bmp180_cal_data[bmp_idx].cal_mc = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MC); + bmp180_cal_data[bmp_idx].cal_md = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MD); + + + if (!bmp180_cal_data[bmp_idx].cal_ac1 | + !bmp180_cal_data[bmp_idx].cal_ac2 | + !bmp180_cal_data[bmp_idx].cal_ac3 | + !bmp180_cal_data[bmp_idx].cal_ac4 | + !bmp180_cal_data[bmp_idx].cal_ac5 | + !bmp180_cal_data[bmp_idx].cal_ac6 | + !bmp180_cal_data[bmp_idx].cal_b1 | + !bmp180_cal_data[bmp_idx].cal_b2 | + !bmp180_cal_data[bmp_idx].cal_mc | + !bmp180_cal_data[bmp_idx].cal_md) { + return false; + } + + if ((bmp180_cal_data[bmp_idx].cal_ac1 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac2 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac3 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac4 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac5 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_ac6 == 0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_b1 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_b2 == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_mc == (int16_t)0xFFFF) | + (bmp180_cal_data[bmp_idx].cal_md == (int16_t)0xFFFF)) { + return false; + } + return true; +} + +void Bmp180Read(uint8_t bmp_idx) +{ + if (!bmp180_cal_data) { return; } + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); + delay(5); + int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); + int32_t xt1 = (ut - (int32_t)bmp180_cal_data[bmp_idx].cal_ac6) * ((int32_t)bmp180_cal_data[bmp_idx].cal_ac5) >> 15; + int32_t xt2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_mc << 11) / (xt1 + (int32_t)bmp180_cal_data[bmp_idx].cal_md); + int32_t bmp180_b5 = xt1 + xt2; + bmp_sensors[bmp_idx].bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); + delay(2 + (4 << BMP180_OSS)); + uint32_t up = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); + up >>= (8 - BMP180_OSS); + + int32_t b6 = bmp180_b5 - 4000; + int32_t x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b2 * ((b6 * b6) >> 12)) >> 11; + int32_t x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac2 * b6) >> 11; + int32_t x3 = x1 + x2; + int32_t b3 = ((((int32_t)bmp180_cal_data[bmp_idx].cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2; + + x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac3 * b6) >> 13; + x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b1 * ((b6 * b6) >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + uint32_t b4 = ((uint32_t)bmp180_cal_data[bmp_idx].cal_ac4 * (uint32_t)(x3 + 32768)) >> 15; + uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS); + + int32_t p; + if (b7 < 0x80000000) { + p = (b7 * 2) / b4; + } + else { + p = (b7 / b4) * 2; + } + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + p += ((x1 + x2 + (int32_t)3791) >> 4); + bmp_sensors[bmp_idx].bmp_pressure = (float)p / 100.0; +} + + + + + + + +#define BME280_REGISTER_CONTROLHUMID 0xF2 +#define BME280_REGISTER_CONTROL 0xF4 +#define BME280_REGISTER_CONFIG 0xF5 +#define BME280_REGISTER_PRESSUREDATA 0xF7 +#define BME280_REGISTER_TEMPDATA 0xFA +#define BME280_REGISTER_HUMIDDATA 0xFD + +#define BME280_REGISTER_DIG_T1 0x88 +#define BME280_REGISTER_DIG_T2 0x8A +#define BME280_REGISTER_DIG_T3 0x8C +#define BME280_REGISTER_DIG_P1 0x8E +#define BME280_REGISTER_DIG_P2 0x90 +#define BME280_REGISTER_DIG_P3 0x92 +#define BME280_REGISTER_DIG_P4 0x94 +#define BME280_REGISTER_DIG_P5 0x96 +#define BME280_REGISTER_DIG_P6 0x98 +#define BME280_REGISTER_DIG_P7 0x9A +#define BME280_REGISTER_DIG_P8 0x9C +#define BME280_REGISTER_DIG_P9 0x9E +#define BME280_REGISTER_DIG_H1 0xA1 +#define BME280_REGISTER_DIG_H2 0xE1 +#define BME280_REGISTER_DIG_H3 0xE3 +#define BME280_REGISTER_DIG_H4 0xE4 +#define BME280_REGISTER_DIG_H5 0xE5 +#define BME280_REGISTER_DIG_H6 0xE7 + +typedef struct { + uint16_t dig_T1; + int16_t dig_T2; + int16_t dig_T3; + uint16_t dig_P1; + int16_t dig_P2; + int16_t dig_P3; + int16_t dig_P4; + int16_t dig_P5; + int16_t dig_P6; + int16_t dig_P7; + int16_t dig_P8; + int16_t dig_P9; + int16_t dig_H2; + int16_t dig_H4; + int16_t dig_H5; + uint8_t dig_H1; + uint8_t dig_H3; + int8_t dig_H6; +} Bme280CalibrationData_t; + +Bme280CalibrationData_t *Bme280CalibrationData = nullptr; + +bool Bmx280Calibrate(uint8_t bmp_idx) +{ + + + if (!Bme280CalibrationData) { + Bme280CalibrationData = (Bme280CalibrationData_t*)malloc(BMP_MAX_SENSORS * sizeof(Bme280CalibrationData_t)); + } + if (!Bme280CalibrationData) { return false; } + + Bme280CalibrationData[bmp_idx].dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1); + Bme280CalibrationData[bmp_idx].dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2); + Bme280CalibrationData[bmp_idx].dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3); + Bme280CalibrationData[bmp_idx].dig_P1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P1); + Bme280CalibrationData[bmp_idx].dig_P2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P2); + Bme280CalibrationData[bmp_idx].dig_P3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P3); + Bme280CalibrationData[bmp_idx].dig_P4 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P4); + Bme280CalibrationData[bmp_idx].dig_P5 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P5); + Bme280CalibrationData[bmp_idx].dig_P6 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P6); + Bme280CalibrationData[bmp_idx].dig_P7 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P7); + Bme280CalibrationData[bmp_idx].dig_P8 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P8); + Bme280CalibrationData[bmp_idx].dig_P9 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P9); + if (BME280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { + Bme280CalibrationData[bmp_idx].dig_H1 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H1); + Bme280CalibrationData[bmp_idx].dig_H2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H2); + Bme280CalibrationData[bmp_idx].dig_H3 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H3); + Bme280CalibrationData[bmp_idx].dig_H4 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); + Bme280CalibrationData[bmp_idx].dig_H5 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5) >> 4); + Bme280CalibrationData[bmp_idx].dig_H6 = (int8_t)I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H6); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x00); + + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROLHUMID, 0x01); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONFIG, 0xA0); + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x27); + } else { + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0xB7); + } + + return true; +} + +void Bme280Read(uint8_t bmp_idx) +{ + if (!Bme280CalibrationData) { return; } + + int32_t adc_T = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_TEMPDATA); + adc_T >>= 4; + + int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1 << 1))) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_T2)) >> 11; + int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1))) >> 12) * + ((int32_t)Bme280CalibrationData[bmp_idx].dig_T3)) >> 14; + int32_t t_fine = vart1 + vart2; + float T = (t_fine * 5 + 128) >> 8; + bmp_sensors[bmp_idx].bmp_temperature = T / 100.0; + + int32_t adc_P = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_PRESSUREDATA); + adc_P >>= 4; + + int64_t var1 = ((int64_t)t_fine) - 128000; + int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P6; + var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P5) << 17); + var2 = var2 + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P4) << 35); + var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P2) << 12); + var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData[bmp_idx].dig_P1) >> 33; + if (0 == var1) { + return; + } + int64_t p = 1048576 - adc_P; + p = (((p << 31) - var2) * 3125) / var1; + var1 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P9) * (p >> 13) * (p >> 13)) >> 25; + var2 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P8) * p) >> 19; + p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P7) << 4); + bmp_sensors[bmp_idx].bmp_pressure = (float)p / 25600.0; + + if (BMP280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { return; } + + int32_t adc_H = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_HUMIDDATA); + + int32_t v_x1_u32r = (t_fine - ((int32_t)76800)); + v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H4) << 20) - + (((int32_t)Bme280CalibrationData[bmp_idx].dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * + (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H6)) >> 10) * + (((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + + ((int32_t)2097152)) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H2) + 8192) >> 14)); + v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * + ((int32_t)Bme280CalibrationData[bmp_idx].dig_H1)) >> 4)); + v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; + v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; + float h = (v_x1_u32r >> 12); + bmp_sensors[bmp_idx].bmp_humidity = h / 1024.0; +} + +#ifdef USE_BME680 + + + + +#include + +struct bme680_dev *gas_sensor = nullptr; + +static void BmeDelayMs(uint32_t ms) +{ + delay(ms); +} + +bool Bme680Init(uint8_t bmp_idx) +{ + if (!gas_sensor) { + gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); + } + if (!gas_sensor) { return false; } + + gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address; + gas_sensor[bmp_idx].intf = BME680_I2C_INTF; + gas_sensor[bmp_idx].read = &I2cReadBuffer; + gas_sensor[bmp_idx].write = &I2cWriteBuffer; + gas_sensor[bmp_idx].delay_ms = BmeDelayMs; + + + + gas_sensor[bmp_idx].amb_temp = 25; + + int8_t rslt = BME680_OK; + rslt = bme680_init(&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return false; } + + + gas_sensor[bmp_idx].tph_sett.os_hum = BME680_OS_2X; + gas_sensor[bmp_idx].tph_sett.os_pres = BME680_OS_4X; + gas_sensor[bmp_idx].tph_sett.os_temp = BME680_OS_8X; + gas_sensor[bmp_idx].tph_sett.filter = BME680_FILTER_SIZE_3; + + + gas_sensor[bmp_idx].gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; + + gas_sensor[bmp_idx].gas_sett.heatr_temp = 320; + gas_sensor[bmp_idx].gas_sett.heatr_dur = 150; + + + + gas_sensor[bmp_idx].power_mode = BME680_FORCED_MODE; + + + uint8_t set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; + + + rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return false; } + + bmp_sensors[bmp_idx].bme680_state = 0; + + return true; +} + +void Bme680Read(uint8_t bmp_idx) +{ + if (!gas_sensor) { return; } + + int8_t rslt = BME680_OK; + + if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { + if (0 == bmp_sensors[bmp_idx].bme680_state) { + + rslt = bme680_set_sensor_mode(&gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return; } + + + + + + + + bmp_sensors[bmp_idx].bme680_state = 1; + } else { + bmp_sensors[bmp_idx].bme680_state = 0; + + struct bme680_field_data data; + rslt = bme680_get_sensor_data(&data, &gas_sensor[bmp_idx]); + if (rslt != BME680_OK) { return; } + + bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; + bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; + bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; + + if (data.status & BME680_GASM_VALID_MSK) { + bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; + } else { + bmp_sensors[bmp_idx].bmp_gas_resistance = 0; + } + } + } + return; +} + +#endif + + + +void BmpDetect(void) +{ + int bmp_sensor_size = BMP_MAX_SENSORS * sizeof(bmp_sensors_t); + if (!bmp_sensors) { + bmp_sensors = (bmp_sensors_t*)malloc(bmp_sensor_size); + } + if (!bmp_sensors) { return; } + memset(bmp_sensors, 0, bmp_sensor_size); + + for (uint32_t i = 0; i < BMP_MAX_SENSORS; i++) { + if (I2cActive(bmp_addresses[i])) { continue; } + uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); + if (bmp_type) { + bmp_sensors[bmp_count].bmp_address = bmp_addresses[i]; + bmp_sensors[bmp_count].bmp_type = bmp_type; + bmp_sensors[bmp_count].bmp_model = 0; + + bool success = false; + switch (bmp_type) { + case BMP180_CHIPID: + success = Bmp180Calibration(bmp_count); + break; + case BME280_CHIPID: + bmp_sensors[bmp_count].bmp_model++; + case BMP280_CHIPID: + bmp_sensors[bmp_count].bmp_model++; + success = Bmx280Calibrate(bmp_count); + break; +#ifdef USE_BME680 + case BME680_CHIPID: + bmp_sensors[bmp_count].bmp_model = 3; + success = Bme680Init(bmp_count); + break; +#endif + } + if (success) { + GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); + I2cSetActiveFound(bmp_sensors[bmp_count].bmp_address, bmp_sensors[bmp_count].bmp_name); + bmp_count++; + } + } + } +} + +void BmpRead(void) +{ + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + switch (bmp_sensors[bmp_idx].bmp_type) { + case BMP180_CHIPID: + Bmp180Read(bmp_idx); + break; + case BMP280_CHIPID: + case BME280_CHIPID: + Bme280Read(bmp_idx); + break; +#ifdef USE_BME680 + case BME680_CHIPID: + Bme680Read(bmp_idx); + break; +#endif + } + } + ConvertTemp(bmp_sensors[0].bmp_temperature); + ConvertHumidity(bmp_sensors[0].bmp_humidity); +} + +void BmpShow(bool json) +{ + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + if (bmp_sensors[bmp_idx].bmp_type) { + float bmp_sealevel = 0.0; + if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { + bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; + bmp_sealevel = ConvertPressure(bmp_sealevel); + } + float bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); + float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); + + char name[10]; + strlcpy(name, bmp_sensors[bmp_idx].bmp_name, sizeof(name)); + if (bmp_count > 1) { + snprintf_P(name, sizeof(name), PSTR("%s%c%02X"), name, IndexSeparator(), bmp_sensors[bmp_idx].bmp_address); + } + + char temperature[33]; + dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); + char pressure[33]; + dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); + char sea_pressure[33]; + dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); + char humidity[33]; + dtostrfd(bmp_sensors[bmp_idx].bmp_humidity, Settings.flag2.humidity_resolution, humidity); +#ifdef USE_BME680 + char gas_resistance[33]; + dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); +#endif + + if (json) { + char json_humidity[40]; + snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + char json_sealevel[40]; + snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); +#ifdef USE_BME680 + char json_gas[40]; + snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); + + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), + name, + temperature, + (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", + pressure, + (Settings.altitude != 0) ? json_sealevel : "", + (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); +#else + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), + name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); +#endif + +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == bmp_idx)) { + DomoticzTempHumPressureSensor(temperature, humidity, pressure); +#ifdef USE_BME680 + if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } +#endif + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, bmp_temperature); + KnxSensor(KNX_HUMIDITY, bmp_sensors[bmp_idx].bmp_humidity); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, name, temperature, TempUnit()); + if (bmp_sensors[bmp_idx].bmp_model >= 2) { + WSContentSend_PD(HTTP_SNS_HUM, name, humidity); + } + WSContentSend_PD(HTTP_SNS_PRESSURE, name, pressure, PressureUnit().c_str()); + if (Settings.altitude != 0) { + WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sea_pressure, PressureUnit().c_str()); + } +#ifdef USE_BME680 + if (bmp_sensors[bmp_idx].bmp_model >= 3) { + WSContentSend_PD(PSTR("{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), name, gas_resistance); + } +#endif + +#endif + } + } + } +} + +#ifdef USE_DEEPSLEEP + +void BMP_EnterSleep(void) +{ + for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { + switch (bmp_sensors[bmp_idx].bmp_type) { + case BMP180_CHIPID: + case BMP280_CHIPID: + case BME280_CHIPID: + I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP_REGISTER_RESET, BMP_CMND_RESET); + break; + default: + break; + } + } +} + +#endif + + + + + +bool Xsns09(uint8_t function) +{ + if (!I2cEnabled(XI2C_10)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + BmpDetect(); + } + else if (bmp_count) { + switch (function) { + case FUNC_EVERY_SECOND: + BmpRead(); + break; + case FUNC_JSON_APPEND: + BmpShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + BmpShow(0); + break; +#endif +#ifdef USE_DEEPSLEEP + case FUNC_SAVE_BEFORE_RESTART: + BMP_EnterSleep(); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_10_bh1750.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_10_bh1750.ino" +#ifdef USE_I2C +#ifdef USE_BH1750 + + + + + + +#define XSNS_10 10 +#define XI2C_11 11 + +#define BH1750_ADDR1 0x23 +#define BH1750_ADDR2 0x5C + +#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 + +uint8_t bh1750_address; +uint8_t bh1750_addresses[] = { BH1750_ADDR1, BH1750_ADDR2 }; +uint8_t bh1750_type = 0; +uint8_t bh1750_valid = 0; +uint16_t bh1750_illuminance = 0; +char bh1750_types[] = "BH1750"; + +bool Bh1750Read(void) +{ + if (bh1750_valid) { bh1750_valid--; } + + if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } + uint8_t msb = Wire.read(); + uint8_t lsb = Wire.read(); + bh1750_illuminance = ((msb << 8) | lsb) / 1.2; + bh1750_valid = SENSOR_MAX_MISS; + return true; +} + + + +void Bh1750Detect(void) +{ + for (uint32_t i = 0; i < sizeof(bh1750_addresses); i++) { + bh1750_address = bh1750_addresses[i]; + if (I2cActive(bh1750_address)) { continue; } + Wire.beginTransmission(bh1750_address); + Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); + if (!Wire.endTransmission()) { + I2cSetActiveFound(bh1750_address, bh1750_types); + bh1750_type = 1; + break; + } + } +} + +void Bh1750EverySecond(void) +{ + + if (!Bh1750Read()) { + AddLogMissed(bh1750_types, bh1750_valid); + } +} + +void Bh1750Show(bool json) +{ + if (bh1750_valid) { + if (json) { + ResponseAppend_P(JSON_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); +#endif + } + } +} + + + + + +bool Xsns10(uint8_t function) +{ + if (!I2cEnabled(XI2C_11)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Bh1750Detect(); + } + else if (bh1750_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Bh1750EverySecond(); + break; + case FUNC_JSON_APPEND: + Bh1750Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Bh1750Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_11_veml6070.ino" +# 89 "S:/Development/Tasmota/tasmota/xsns_11_veml6070.ino" +#ifdef USE_I2C +#ifdef USE_VEML6070 + + + + + + +#define XSNS_11 11 +#define XI2C_12 12 + +#define VEML6070_ADDR_H 0x39 +#define VEML6070_ADDR_L 0x38 +#define VEML6070_INTEGRATION_TIME 3 +#define VEML6070_ENABLE 1 +#define VEML6070_DISABLE 0 +#define VEML6070_RSET_DEFAULT 270000 +#define VEML6070_UV_MAX_INDEX 15 +#define VEML6070_UV_MAX_DEFAULT 11 +#define VEML6070_POWER_COEFFCIENT 0.025 +#define VEML6070_TABLE_COEFFCIENT 32.86270591 + + + + + +const char kVemlTypes[] PROGMEM = "VEML6070"; +double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +double uvrisk = 0; +double uvpower = 0; +uint16_t uvlevel = 0; +uint8_t veml6070_addr_low = VEML6070_ADDR_L; +uint8_t veml6070_addr_high = VEML6070_ADDR_H; +uint8_t itime = VEML6070_INTEGRATION_TIME; +uint8_t veml6070_type = 0; +char veml6070_name[9]; +char str_uvrisk_text[10]; + + + +void Veml6070Detect(void) +{ + if (I2cActive(VEML6070_ADDR_L)) { return; } + + + Wire.beginTransmission(VEML6070_ADDR_L); + Wire.write((itime << 2) | 0x02); + uint8_t status = Wire.endTransmission(); + + if (!status) { + veml6070_type = 1; + Veml6070UvTableInit(); + uint8_t veml_model = 0; + GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); + I2cSetActiveFound(VEML6070_ADDR_L, veml6070_name); + } +} + + + +void Veml6070UvTableInit(void) +{ + + for (uint32_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { +#ifdef USE_VEML6070_RSET + if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { + uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + } else { + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); + } +#else + uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); +#endif + } +} + + + +void Veml6070EverySecond(void) +{ + + Veml6070ModeCmd(1); + uvlevel = Veml6070ReadUv(); + uvrisk = Veml6070UvRiskLevel(uvlevel); + uvpower = Veml6070UvPower(uvrisk); + Veml6070ModeCmd(0); +} + + + +void Veml6070ModeCmd(bool mode_cmd) +{ + + + Wire.beginTransmission(VEML6070_ADDR_L); + Wire.write((mode_cmd << 0) | 0x02 | (itime << 2)); + uint8_t status = Wire.endTransmission(); + + if (!status) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 mode_cmd")); + } +} + + + +uint16_t Veml6070ReadUv(void) +{ + uint16_t uv_raw = 0; + + if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { + return -1; + } + uv_raw = Wire.read(); + uv_raw <<= 8; + + if (Wire.requestFrom(VEML6070_ADDR_L, 1) != 1) { + return -1; + } + uv_raw |= Wire.read(); + + return uv_raw; +} + + + +double Veml6070UvRiskLevel(uint16_t uv_level) +{ + double risk = 0; + if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { + risk = (double)uv_level / uv_risk_map[0]; + + if ( (risk >= 0) && (risk <= 2.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_1); } + else if ( (risk >= 3.0) && (risk <= 5.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_2); } + else if ( (risk >= 6.0) && (risk <= 7.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_3); } + else if ( (risk >= 8.0) && (risk <= 10.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_4); } + else if ( (risk >= 11.0) && (risk <= 12.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_5); } + else if ( (risk >= 13.0) && (risk <= 25.0) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_6); } + else { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); } + return risk; + } else { + + snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); + return ( risk = 99 ); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); + } +} + + + +double Veml6070UvPower(double uvrisk) +{ + + double power = 0; + return ( power = VEML6070_POWER_COEFFCIENT * uvrisk ); +} + + + + +#ifdef USE_WEBSERVER + +#ifdef USE_VEML6070_SHOW_RAW + const char HTTP_SNS_UV_LEVEL[] PROGMEM = "{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; +#endif + + const char HTTP_SNS_UV_INDEX[] PROGMEM = "{s}VEML6070 " D_UV_INDEX "{m}%s %s{e}"; + const char HTTP_SNS_UV_POWER[] PROGMEM = "{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; +#endif + + + +void Veml6070Show(bool json) +{ + + char str_uvlevel[33]; + dtostrfd((double)uvlevel, 0, str_uvlevel); + char str_uvrisk[33]; + dtostrfd(uvrisk, 2, str_uvrisk); + char str_uvpower[33]; + dtostrfd(uvpower, 3, str_uvpower); + if (json) { +#ifdef USE_VEML6070_SHOW_RAW + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); +#else + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); +#endif +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } +#endif +#ifdef USE_WEBSERVER + } else { +#ifdef USE_VEML6070_SHOW_RAW + WSContentSend_PD(HTTP_SNS_UV_LEVEL, str_uvlevel); +#endif + WSContentSend_PD(HTTP_SNS_UV_INDEX, str_uvrisk, str_uvrisk_text); + WSContentSend_PD(HTTP_SNS_UV_POWER, str_uvpower); +#endif + } +} + + + + + +bool Xsns11(uint8_t function) +{ + if (!I2cEnabled(XI2C_12)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Veml6070Detect(); + } + else if (veml6070_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Veml6070EverySecond(); + break; + case FUNC_JSON_APPEND: + Veml6070Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Veml6070Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_12_ads1115.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_12_ads1115.ino" +#ifdef USE_I2C +#ifdef USE_ADS1115 +# 43 "S:/Development/Tasmota/tasmota/xsns_12_ads1115.ino" +#define XSNS_12 12 +#define XI2C_13 13 + +#define ADS1115_ADDRESS_ADDR_GND 0x48 +#define ADS1115_ADDRESS_ADDR_VDD 0x49 +#define ADS1115_ADDRESS_ADDR_SDA 0x4A +#define ADS1115_ADDRESS_ADDR_SCL 0x4B + +#define ADS1115_CONVERSIONDELAY (8) + + + + +#define ADS1115_REG_POINTER_MASK (0x03) +#define ADS1115_REG_POINTER_CONVERT (0x00) +#define ADS1115_REG_POINTER_CONFIG (0x01) +#define ADS1115_REG_POINTER_LOWTHRESH (0x02) +#define ADS1115_REG_POINTER_HITHRESH (0x03) + + + + +#define ADS1115_REG_CONFIG_OS_MASK (0x8000) +#define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) +#define ADS1115_REG_CONFIG_OS_BUSY (0x0000) +#define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) + +#define ADS1115_REG_CONFIG_MUX_MASK (0x7000) +#define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) +#define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) +#define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) +#define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) +#define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) + +#define ADS1115_REG_CONFIG_PGA_MASK (0x0E00) +#define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) +#define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) +#define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) +#define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) +#define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) +#define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) + +#define ADS1115_REG_CONFIG_MODE_MASK (0x0100) +#define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) +#define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) + +#define ADS1115_REG_CONFIG_DR_MASK (0x00E0) +#define ADS1115_REG_CONFIG_DR_128SPS (0x0000) +#define ADS1115_REG_CONFIG_DR_250SPS (0x0020) +#define ADS1115_REG_CONFIG_DR_490SPS (0x0040) +#define ADS1115_REG_CONFIG_DR_920SPS (0x0060) +#define ADS1115_REG_CONFIG_DR_1600SPS (0x0080) +#define ADS1115_REG_CONFIG_DR_2400SPS (0x00A0) +#define ADS1115_REG_CONFIG_DR_3300SPS (0x00C0) +#define ADS1115_REG_CONFIG_DR_6000SPS (0x00E0) + +#define ADS1115_REG_CONFIG_CMODE_MASK (0x0010) +#define ADS1115_REG_CONFIG_CMODE_TRAD (0x0000) +#define ADS1115_REG_CONFIG_CMODE_WINDOW (0x0010) + +#define ADS1115_REG_CONFIG_CPOL_MASK (0x0008) +#define ADS1115_REG_CONFIG_CPOL_ACTVLOW (0x0000) +#define ADS1115_REG_CONFIG_CPOL_ACTVHI (0x0008) + +#define ADS1115_REG_CONFIG_CLAT_MASK (0x0004) +#define ADS1115_REG_CONFIG_CLAT_NONLAT (0x0000) +#define ADS1115_REG_CONFIG_CLAT_LATCH (0x0004) + +#define ADS1115_REG_CONFIG_CQUE_MASK (0x0003) +#define ADS1115_REG_CONFIG_CQUE_1CONV (0x0000) +#define ADS1115_REG_CONFIG_CQUE_2CONV (0x0001) +#define ADS1115_REG_CONFIG_CQUE_4CONV (0x0002) +#define ADS1115_REG_CONFIG_CQUE_NONE (0x0003) + +struct ADS1115 { + uint8_t count = 0; + uint8_t address; + uint8_t addresses[4] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; + uint8_t found[4] = {false,false,false,false}; +} Ads1115; + + + +void Ads1115StartComparator(uint8_t channel, uint16_t mode) +{ + + uint16_t config = mode | + ADS1115_REG_CONFIG_CQUE_NONE | + ADS1115_REG_CONFIG_CLAT_NONLAT | + ADS1115_REG_CONFIG_PGA_6_144V | + ADS1115_REG_CONFIG_CPOL_ACTVLOW | + ADS1115_REG_CONFIG_CMODE_TRAD | + ADS1115_REG_CONFIG_DR_6000SPS; + + + config |= (ADS1115_REG_CONFIG_MUX_SINGLE_0 + (0x1000 * channel)); + + + I2cWrite16(Ads1115.address, ADS1115_REG_POINTER_CONFIG, config); +} + +int16_t Ads1115GetConversion(uint8_t channel) +{ + Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); + + delay(ADS1115_CONVERSIONDELAY); + + I2cRead16(Ads1115.address, ADS1115_REG_POINTER_CONVERT); + + Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); + delay(ADS1115_CONVERSIONDELAY); + + uint16_t res = I2cRead16(Ads1115.address, ADS1115_REG_POINTER_CONVERT); + return (int16_t)res; +} + + + +void Ads1115Detect(void) +{ + for (uint32_t i = 0; i < sizeof(Ads1115.addresses); i++) { + if (!Ads1115.found[i]) { + Ads1115.address = Ads1115.addresses[i]; + if (I2cActive(Ads1115.address)) { continue; } + uint16_t buffer; + if (I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONVERT) && + I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONFIG)) { + Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); + I2cSetActiveFound(Ads1115.address, "ADS1115"); + Ads1115.found[i] = 1; + Ads1115.count++; + } + } + } +} + +void Ads1115Show(bool json) +{ + int16_t values[4]; + + for (uint32_t t = 0; t < sizeof(Ads1115.addresses); t++) { + + if (Ads1115.found[t]) { + + uint8_t old_address = Ads1115.address; + Ads1115.address = Ads1115.addresses[t]; + for (uint32_t i = 0; i < 4; i++) { + values[i] = Ads1115GetConversion(i); + + } + Ads1115.address = old_address; + + char label[15]; + if (1 == Ads1115.count) { + + snprintf_P(label, sizeof(label), PSTR("ADS1115")); + } else { + + snprintf_P(label, sizeof(label), PSTR("ADS1115%c%02x"), IndexSeparator(), Ads1115.addresses[t]); + } + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{"), label); + for (uint32_t i = 0; i < 4; i++) { + ResponseAppend_P(PSTR("%s\"A%d\":%d"), (0 == i) ? "" : ",", i, values[i]); + } + ResponseJsonEnd(); + } +#ifdef USE_WEBSERVER + else { + for (uint32_t i = 0; i < 4; i++) { + WSContentSend_PD(HTTP_SNS_ANALOG, label, i, values[i]); + } + } +#endif + } + } +} + + + + + +bool Xsns12(uint8_t function) +{ + if (!I2cEnabled(XI2C_13)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Ads1115Detect(); + } + else if (Ads1115.count) { + switch (function) { + case FUNC_JSON_APPEND: + Ads1115Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ads1115Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_13_ina219.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_13_ina219.ino" +#ifdef USE_I2C +#ifdef USE_INA219 +# 30 "S:/Development/Tasmota/tasmota/xsns_13_ina219.ino" +#define XSNS_13 13 +#define XI2C_14 14 + +#define INA219_ADDRESS1 (0x40) +#define INA219_ADDRESS2 (0x41) +#define INA219_ADDRESS3 (0x44) +#define INA219_ADDRESS4 (0x45) + +#define INA219_READ (0x01) +#define INA219_REG_CONFIG (0x00) + +#define INA219_CONFIG_RESET (0x8000) + +#define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) +#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) +#define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) + +#define INA219_CONFIG_GAIN_MASK (0x1800) +#define INA219_CONFIG_GAIN_1_40MV (0x0000) +#define INA219_CONFIG_GAIN_2_80MV (0x0800) +#define INA219_CONFIG_GAIN_4_160MV (0x1000) +#define INA219_CONFIG_GAIN_8_320MV (0x1800) + +#define INA219_CONFIG_BADCRES_MASK (0x0780) +#define INA219_CONFIG_BADCRES_9BIT (0x0080) +#define INA219_CONFIG_BADCRES_10BIT (0x0100) +#define INA219_CONFIG_BADCRES_11BIT (0x0200) +#define INA219_CONFIG_BADCRES_12BIT (0x0400) + +#define INA219_CONFIG_SADCRES_MASK (0x0078) +#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) +#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) +#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) +#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) +#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) +#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) +#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) +#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) +#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) +#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) +#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) + +#define INA219_CONFIG_MODE_MASK (0x0007) +#define INA219_CONFIG_MODE_POWERDOWN (0x0000) +#define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001) +#define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002) +#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003) +#define INA219_CONFIG_MODE_ADCOFF (0x0004) +#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005) +#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006) +#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007) + +#define INA219_REG_SHUNTVOLTAGE (0x01) +#define INA219_REG_BUSVOLTAGE (0x02) +#define INA219_REG_POWER (0x03) +#define INA219_REG_CURRENT (0x04) +#define INA219_REG_CALIBRATION (0x05) + +uint8_t ina219_type[4] = {0,0,0,0}; +uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; + +uint32_t ina219_cal_value = 0; + +uint32_t ina219_current_divider_ma = 0; + +uint8_t ina219_valid[4] = {0,0,0,0}; +float ina219_voltage[4] = {0,0,0,0}; +float ina219_current[4] = {0,0,0,0}; +char ina219_types[] = "INA219"; +uint8_t ina219_count = 0; + +bool Ina219SetCalibration(uint8_t mode, uint16_t addr) +{ + uint16_t config = 0; + + switch (mode &3) { + case 0: + case 3: + ina219_cal_value = 4096; + ina219_current_divider_ma = 10; + config = INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + case 1: + ina219_cal_value = 10240; + ina219_current_divider_ma = 25; + config |= INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + case 2: + ina219_cal_value = 8192; + ina219_current_divider_ma = 20; + config |= INA219_CONFIG_BVOLTAGERANGE_16V | INA219_CONFIG_GAIN_1_40MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + break; + } + + bool success = I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); + if (success) { + + I2cWrite16(addr, INA219_REG_CONFIG, config); + } + return success; +} + +float Ina219GetShuntVoltage_mV(uint16_t addr) +{ + + int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); + + return value * 0.01; +} + +float Ina219GetBusVoltage_V(uint16_t addr) +{ + + + int16_t value = (int16_t)(((uint16_t)I2cReadS16(addr, INA219_REG_BUSVOLTAGE) >> 3) * 4); + + return value * 0.001; +} + +float Ina219GetCurrent_mA(uint16_t addr) +{ + + + + I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); + + + float value = I2cReadS16(addr, INA219_REG_CURRENT); + value /= ina219_current_divider_ma; + + return value; +} + +bool Ina219Read(void) +{ + for (int i=0; i= 0) && (XdrvMailbox.payload <= 2)) { + Settings.ina219_mode = XdrvMailbox.payload; + restart_flag = 2; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); + + return true; +} + + + +void Ina219Detect(void) +{ + for (uint32_t i = 0; i < sizeof(ina219_type); i++) { + uint16_t addr = ina219_addresses[i]; + if (I2cActive(addr)) { continue; } + if (Ina219SetCalibration(Settings.ina219_mode, addr)) { + I2cSetActiveFound(addr, ina219_types); + ina219_type[i] = 1; + ina219_count++; + } + } +} + +void Ina219EverySecond(void) +{ + + Ina219Read(); +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_INA219_DATA[] PROGMEM = + "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; +#endif + +void Ina219Show(bool json) +{ + int num_found=0; + for (int i=0; i1) + snprintf_P(name, sizeof(name), PSTR("%s%c%d"), ina219_types, IndexSeparator(), sensor_num); + else + snprintf_P(name, sizeof(name), PSTR("%s"), ina219_types); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + name, ina219_addresses[i], voltage, current, power); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, voltage); + DomoticzSensor(DZ_CURRENT, current); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_INA219_DATA, name, voltage, name, current, name, power); +#endif + } + } +} + + + + + +bool Xsns13(uint8_t function) +{ + if (!I2cEnabled(XI2C_14)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Ina219Detect(); + } + else if (ina219_count) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_13 == XdrvMailbox.index) { + result = Ina219CommandSensor(); + } + break; + case FUNC_EVERY_SECOND: + Ina219EverySecond(); + break; + case FUNC_JSON_APPEND: + Ina219Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ina219Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_14_sht3x.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_14_sht3x.ino" +#ifdef USE_I2C +#ifdef USE_SHT3X + + + + + + +#define XSNS_14 14 +#define XI2C_15 15 + +#define SHT3X_ADDR_GND 0x44 +#define SHT3X_ADDR_VDD 0x45 +#define SHTC3_ADDR 0x70 + +#define SHT3X_MAX_SENSORS 3 + +const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3"; +uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR }; + +uint8_t sht3x_count = 0; +struct SHT3XSTRUCT { + uint8_t address; + char types[6]; +} sht3x_sensors[SHT3X_MAX_SENSORS]; + +bool Sht3xRead(float &t, float &h, uint8_t sht3x_address) +{ + unsigned int data[6]; + + t = NAN; + h = NAN; + + Wire.beginTransmission(sht3x_address); + if (SHTC3_ADDR == sht3x_address) { + Wire.write(0x35); + Wire.write(0x17); + Wire.endTransmission(); + Wire.beginTransmission(sht3x_address); + Wire.write(0x78); + Wire.write(0x66); + } else { + Wire.write(0x2C); + Wire.write(0x06); + } + if (Wire.endTransmission() != 0) { + return false; + } + delay(30); + Wire.requestFrom(sht3x_address, (uint8_t)6); + for (uint32_t i = 0; i < 6; i++) { + data[i] = Wire.read(); + }; + t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45); + h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0)); + return (!isnan(t) && !isnan(h) && (h != 0)); +} + + + +void Sht3xDetect(void) +{ + for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { + if (I2cActive(sht3x_addresses[i])) { continue; } + float t; + float h; + if (Sht3xRead(t, h, sht3x_addresses[i])) { + sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; + GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); + I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types); + sht3x_count++; + } + } +} + +void Sht3xShow(bool json) +{ + for (uint32_t i = 0; i < sht3x_count; i++) { + float t; + float h; + if (Sht3xRead(t, h, sht3x_sensors[i].address)) { + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(h, Settings.flag2.humidity_resolution, humidity); + char types[11]; + snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, types, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && (0 == i)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif + +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, t); + KnxSensor(KNX_HUMIDITY, h); + } +#endif + +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, types, humidity); +#endif + } + } + } +} + + + + + +bool Xsns14(uint8_t function) +{ + if (!I2cEnabled(XI2C_15)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Sht3xDetect(); + } + else if (sht3x_count) { + switch (function) { + case FUNC_JSON_APPEND: + Sht3xShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sht3xShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" +#ifdef USE_MHZ19 +# 33 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" +#define XSNS_15 15 + +enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILTER_FAST, MHZ19_FILTER_MEDIUM, MHZ19_FILTER_SLOW}; + +#define MHZ19_FILTER_OPTION MHZ19_FILTER_FAST +# 58 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" +#include + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#define MHZ19_READ_TIMEOUT 400 +#define MHZ19_RETRY_COUNT 8 + +TasmotaSerial *MhzSerial; + +const char kMhzModels[] PROGMEM = "|B"; + +const char ABC_ENABLED[] = "ABC is Enabled"; +const char ABC_DISABLED[] = "ABC is Disabled"; + +enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; +const uint8_t kMhzCommands[][4] PROGMEM = { + + {0x86,0x00,0x00,0x00}, + {0x79,0xA0,0x00,0x00}, + {0x79,0x00,0x00,0x00}, + {0x87,0x00,0x00,0x00}, + {0x8D,0x00,0x00,0x00}, + {0x99,0x00,0x03,0xE8}, + {0x99,0x00,0x07,0xD0}, + {0x99,0x00,0x0B,0xB8}, + {0x99,0x00,0x13,0x88}}; + +uint8_t mhz_type = 1; +uint16_t mhz_last_ppm = 0; +uint8_t mhz_filter = MHZ19_FILTER_OPTION; +bool mhz_abc_must_apply = false; + +float mhz_temperature = 0; +uint8_t mhz_retry = MHZ19_RETRY_COUNT; +uint8_t mhz_received = 0; +uint8_t mhz_state = 0; + + + +uint8_t MhzCalculateChecksum(uint8_t *array) +{ + uint8_t checksum = 0; + for (uint32_t i = 1; i < 8; i++) { + checksum += array[i]; + } + checksum = 255 - checksum; + return (checksum +1); +} + +size_t MhzSendCmd(uint8_t command_id) +{ + uint8_t mhz_send[9] = { 0 }; + + mhz_send[0] = 0xFF; + mhz_send[1] = 0x01; + memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(uint16_t)); + + + + + memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); + mhz_send[8] = MhzCalculateChecksum(mhz_send); + + + + return MhzSerial->write(mhz_send, sizeof(mhz_send)); +} + + + +bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) +{ + if (1 == s) { + return false; + } + if (mhz_last_ppm < 400 || mhz_last_ppm > 5000) { + + + mhz_last_ppm = ppm; + return true; + } + int32_t difference = ppm - mhz_last_ppm; + if (s > 0 && s < 64 && mhz_filter != MHZ19_FILTER_OFF) { +# 154 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" + difference *= s; + difference /= 64; + } + if (MHZ19_FILTER_OFF == mhz_filter) { + if (s != 0 && s != 64) { + return false; + } + } else { + difference >>= (mhz_filter -1); + } + mhz_last_ppm = static_cast(mhz_last_ppm + difference); + return true; +} + +void MhzEverySecond(void) +{ + mhz_state++; + if (8 == mhz_state) { + mhz_state = 0; + + if (mhz_retry) { + mhz_retry--; + if (!mhz_retry) { + mhz_last_ppm = 0; + mhz_temperature = 0; + } + } + + MhzSerial->flush(); + MhzSendCmd(MHZ_CMND_READPPM); + mhz_received = 0; + } + + if ((mhz_state > 2) && !mhz_received) { + uint8_t mhz_response[9]; + + unsigned long start = millis(); + uint8_t counter = 0; + while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { + if (MhzSerial->available() > 0) { + mhz_response[counter++] = MhzSerial->read(); + } else { + delay(5); + } + } + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); + + if (counter < 9) { + + return; + } + + uint8_t crc = MhzCalculateChecksum(mhz_response); + if (mhz_response[8] != crc) { + + return; + } + if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { + + return; + } + + mhz_received = 1; + + uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; + if (15000 == u) { + if (Settings.SensorBits1.mhz19b_abc_disable) { + + + mhz_abc_must_apply = true; + } + } else { + uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; + mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); + uint8_t s = mhz_response[5]; + mhz_type = (s) ? 1 : 2; + if (MhzCheckAndApplyFilter(ppm, s)) { + mhz_retry = MHZ19_RETRY_COUNT; + LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); + + if (0 == s || 64 == s) { + if (mhz_abc_must_apply) { + mhz_abc_must_apply = false; + if (!Settings.SensorBits1.mhz19b_abc_disable) { + MhzSendCmd(MHZ_CMND_ABCENABLE); + } else { + MhzSendCmd(MHZ_CMND_ABCDISABLE); + } + } + } + + } + } + + } +} +# 266 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" +#define D_JSON_RANGE_1000 "1000 ppm range" +#define D_JSON_RANGE_2000 "2000 ppm range" +#define D_JSON_RANGE_3000 "3000 ppm range" +#define D_JSON_RANGE_5000 "5000 ppm range" + +bool MhzCommandSensor(void) +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + Settings.SensorBits1.mhz19b_abc_disable = true; + MhzSendCmd(MHZ_CMND_ABCDISABLE); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + break; + case 1: + Settings.SensorBits1.mhz19b_abc_disable = false; + MhzSendCmd(MHZ_CMND_ABCENABLE); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + break; + case 2: + MhzSendCmd(MHZ_CMND_ZEROPOINT); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); + break; + case 9: + MhzSendCmd(MHZ_CMND_RESET); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); + break; + case 1000: + MhzSendCmd(MHZ_CMND_RANGE_1000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); + break; + case 2000: + MhzSendCmd(MHZ_CMND_RANGE_2000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); + break; + case 3000: + MhzSendCmd(MHZ_CMND_RANGE_3000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); + break; + case 5000: + MhzSendCmd(MHZ_CMND_RANGE_5000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); + break; + default: + if (!Settings.SensorBits1.mhz19b_abc_disable) { + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + } else { + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + } + } + + return serviced; +} + + + +void MhzInit(void) +{ + mhz_type = 0; + if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { + MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD], 1); + if (MhzSerial->begin(9600)) { + if (MhzSerial->hardwareSerial()) { ClaimSerial(); } + mhz_type = 1; + } + + } +} + +void MhzShow(bool json) +{ + char types[7] = "MHZ19B"; + char temperature[33]; + dtostrfd(mhz_temperature, Settings.flag2.temperature_resolution, temperature); + char model[3]; + GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, types, mhz_last_ppm); + WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); +#endif + } +} + + + + + +bool Xsns15(uint8_t function) +{ + bool result = false; + + if (mhz_type) { + switch (function) { + case FUNC_INIT: + MhzInit(); + break; + case FUNC_EVERY_SECOND: + MhzEverySecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_15 == XdrvMailbox.index) { + result = MhzCommandSensor(); + } + break; + case FUNC_JSON_APPEND: + MhzShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MhzShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_16_tsl2561.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_16_tsl2561.ino" +#ifdef USE_I2C +#ifdef USE_TSL2561 +# 30 "S:/Development/Tasmota/tasmota/xsns_16_tsl2561.ino" +#define XSNS_16 16 +#define XI2C_16 16 + +#include + +Tsl2561 Tsl(Wire); + +uint8_t tsl2561_type = 0; +uint8_t tsl2561_valid = 0; +uint32_t tsl2561_milliLux = 0; +char tsl2561_types[] = "TSL2561"; + +bool Tsl2561Read(void) +{ + if (tsl2561_valid) { tsl2561_valid--; } + + uint8_t id; + bool gain; + Tsl2561::exposure_t exposure; + uint16_t scaledFull, scaledIr; + uint32_t full, ir; + + if (Tsl.on()) { + if (Tsl.id(id) + && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) + && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) + && Tsl2561Util::milliLux(full, ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { + } else{ + tsl2561_milliLux = 0; + } + } + tsl2561_valid = SENSOR_MAX_MISS; + return true; +} + +void Tsl2561Detect(void) +{ + if (I2cSetDevice(0x29) || I2cSetDevice(0x39) || I2cSetDevice(0x49)) { + uint8_t id; + Tsl.begin(); + if (!Tsl.id(id)) return; + if (Tsl.on()) { + tsl2561_type = 1; + I2cSetActiveFound(Tsl.address(), tsl2561_types); + } + } +} + +void Tsl2561EverySecond(void) +{ + if (!(uptime %2)) { + + if (!Tsl2561Read()) { + AddLogMissed(tsl2561_types, tsl2561_valid); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_TSL2561[] PROGMEM = + "{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; +#endif + +void Tsl2561Show(bool json) +{ + if (tsl2561_valid) { + if (json) { + ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), + tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TSL2561, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); +#endif + } + } +} + + + + + +bool Xsns16(uint8_t function) +{ + if (!I2cEnabled(XI2C_16)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Tsl2561Detect(); + } + else if (tsl2561_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Tsl2561EverySecond(); + break; + case FUNC_JSON_APPEND: + Tsl2561Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tsl2561Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_17_senseair.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_17_senseair.ino" +#ifdef USE_SENSEAIR +# 29 "S:/Development/Tasmota/tasmota/xsns_17_senseair.ino" +#define XSNS_17 17 + +#define SENSEAIR_MODBUS_SPEED 9600 +#define SENSEAIR_DEVICE_ADDRESS 0xFE +#define SENSEAIR_READ_REGISTER 0x04 + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#include +TasmotaModbus *SenseairModbus; + +const char kSenseairTypes[] PROGMEM = "Kx0|S8"; + +uint8_t senseair_type = 1; +char senseair_types[7]; + +uint16_t senseair_co2 = 0; +float senseair_temperature = 0; +float senseair_humidity = 0; + + + +const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; + +uint8_t senseair_read_state = 0; +uint8_t senseair_send_retry = 0; + +void Senseair250ms(void) +{ + + + + + uint16_t value = 0; + bool data_ready = SenseairModbus->ReceiveReady(); + + if (data_ready) { + uint8_t error = SenseairModbus->Receive16BitRegister(&value); + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); + } else { + switch(senseair_read_state) { + case 0: + senseair_type = 2; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir type id low %04X"), value); + break; + case 1: + if (value) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir error %04X"), value); + } + break; + case 2: + senseair_co2 = value; + LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); + break; + case 3: + senseair_temperature = ConvertTemp((float)value / 100); + break; + case 4: + senseair_humidity = ConvertHumidity((float)value / 100); + break; + case 5: + { + bool relay_state = value >> 8 & 1; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir relay state %d"), relay_state); + break; + } + case 6: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir temp adjustment %d"), value); + break; + } + } + senseair_read_state++; + if (2 == senseair_type) { + if (3 == senseair_read_state) { + senseair_read_state = 1; + } + } else { + if (sizeof(start_addresses) == senseair_read_state) { + senseair_read_state = 1; + } + } + } + + if (0 == senseair_send_retry || data_ready) { + senseair_send_retry = 5; + SenseairModbus->Send(SENSEAIR_DEVICE_ADDRESS, SENSEAIR_READ_REGISTER, (uint16_t)start_addresses[senseair_read_state], 1); + } else { + senseair_send_retry--; + } + + +} + + + +void SenseairInit(void) +{ + senseair_type = 0; + if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { + SenseairModbus = new TasmotaModbus(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX]); + uint8_t result = SenseairModbus->Begin(SENSEAIR_MODBUS_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + senseair_type = 1; + } + } +} + +void SenseairShow(bool json) +{ + char temperature[33]; + dtostrfd(senseair_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(senseair_humidity, Settings.flag2.temperature_resolution, humidity); + GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2); + if (senseair_type != 2) { + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); + } + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, senseair_types, senseair_co2); + if (senseair_type != 2) { + WSContentSend_PD(HTTP_SNS_TEMP, senseair_types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, senseair_types, humidity); + } +#endif + } +} + + + + + +bool Xsns17(uint8_t function) +{ + bool result = false; + + if (senseair_type) { + switch (function) { + case FUNC_INIT: + SenseairInit(); + break; + case FUNC_EVERY_250_MSECOND: + Senseair250ms(); + break; + case FUNC_JSON_APPEND: + SenseairShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SenseairShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_18_pms5003.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_18_pms5003.ino" +#ifdef USE_PMS5003 +# 31 "S:/Development/Tasmota/tasmota/xsns_18_pms5003.ino" +#define XSNS_18 18 + +#include + +TasmotaSerial *PmsSerial; + +uint8_t pms_type = 1; +uint8_t pms_valid = 0; + +struct pmsX003data { + uint16_t framelen; + uint16_t pm10_standard, pm25_standard, pm100_standard; + uint16_t pm10_env, pm25_env, pm100_env; +#ifdef PMS_MODEL_PMS3003 + uint16_t reserved1, reserved2, reserved3; +#else + uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um; + uint16_t unused; +#endif + uint16_t checksum; +} pms_data; + + + +bool PmsReadData(void) +{ + if (! PmsSerial->available()) { + return false; + } + while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { + PmsSerial->read(); + } +#ifdef PMS_MODEL_PMS3003 + if (PmsSerial->available() < 22) { +#else + if (PmsSerial->available() < 32) { +#endif + return false; + } + +#ifdef PMS_MODEL_PMS3003 + uint8_t buffer[22]; + PmsSerial->readBytes(buffer, 22); +#else + uint8_t buffer[32]; + PmsSerial->readBytes(buffer, 32); +#endif + uint16_t sum = 0; + PmsSerial->flush(); + +#ifdef PMS_MODEL_PMS3003 + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 22); +#else + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); +#endif + + +#ifdef PMS_MODEL_PMS3003 + for (uint32_t i = 0; i < 20; i++) { +#else + for (uint32_t i = 0; i < 30; i++) { +#endif + sum += buffer[i]; + } + +#ifdef PMS_MODEL_PMS3003 + uint16_t buffer_u16[10]; + for (uint32_t i = 0; i < 10; i++) { +#else + uint16_t buffer_u16[15]; + for (uint32_t i = 0; i < 15; i++) { +#endif + buffer_u16[i] = buffer[2 + i*2 + 1]; + buffer_u16[i] += (buffer[2 + i*2] << 8); + } +#ifdef PMS_MODEL_PMS3003 + if (sum != buffer_u16[9]) { +#else + if (sum != buffer_u16[14]) { +#endif + AddLog_P(LOG_LEVEL_DEBUG, PSTR("PMS: " D_CHECKSUM_FAILURE)); + return false; + } + +#ifdef PMS_MODEL_PMS3003 + memcpy((void *)&pms_data, (void *)buffer_u16, 20); +#else + memcpy((void *)&pms_data, (void *)buffer_u16, 30); +#endif + pms_valid = 10; + + return true; +} + + + +void PmsSecond(void) +{ + if (PmsReadData()) { + pms_valid = 10; + } else { + if (pms_valid) { + pms_valid--; + } + } +} + + + +void PmsInit(void) +{ + pms_type = 0; + if (pin[GPIO_PMS5003] < 99) { + PmsSerial = new TasmotaSerial(pin[GPIO_PMS5003], -1, 1); + if (PmsSerial->begin(9600)) { + if (PmsSerial->hardwareSerial()) { ClaimSerial(); } + pms_type = 1; + } + } +} + +#ifdef USE_WEBSERVER +#ifdef PMS_MODEL_PMS3003 +const char HTTP_PMS3003_SNS[] PROGMEM = + + + + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#else +const char HTTP_PMS5003_SNS[] PROGMEM = + + + + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 0.3 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 0.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" + "{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; +#endif +#endif + +void PmsShow(bool json) +{ + if (pms_valid) { + if (json) { +#ifdef PMS_MODEL_PMS3003 + ResponseAppend_P(PSTR(",\"PMS3003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d}"), + pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); +#else + ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), + pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, + pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); +#endif +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_COUNT, pms_data.pm10_env); + DomoticzSensor(DZ_VOLTAGE, pms_data.pm25_env); + DomoticzSensor(DZ_CURRENT, pms_data.pm100_env); + } +#endif +#ifdef USE_WEBSERVER + } else { + +#ifdef PMS_MODEL_PMS3003 + WSContentSend_PD(HTTP_PMS3003_SNS, + + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); +#else + WSContentSend_PD(HTTP_PMS5003_SNS, + + pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, + pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); +#endif +#endif + } + } +} + + + + + +bool Xsns18(uint8_t function) +{ + bool result = false; + + if (pms_type) { + switch (function) { + case FUNC_INIT: + PmsInit(); + break; + case FUNC_EVERY_SECOND: + PmsSecond(); + break; + case FUNC_JSON_APPEND: + PmsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + PmsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_19_mgs.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_19_mgs.ino" +#ifdef USE_I2C +#ifdef USE_MGS + + + + + + + +#define XSNS_19 19 +#define XI2C_17 17 + +#ifndef MGS_SENSOR_ADDR +#define MGS_SENSOR_ADDR 0x04 +#endif + +#include "MutichannelGasSensor.h" + +bool mgs_detected = false; + +void MGSInit(void) { + gas.begin(MGS_SENSOR_ADDR); +} + +void MGSPrepare(void) +{ + if (I2cActive(MGS_SENSOR_ADDR)) { return; } + + gas.begin(MGS_SENSOR_ADDR); + if (!gas.isError()) { + I2cSetActiveFound(MGS_SENSOR_ADDR, "MultiGas"); + mgs_detected = true; + } +} + +char* measure_gas(int gas_type, char* buffer) +{ + float f = gas.calcGas(gas_type); + dtostrfd(f, 2, buffer); + return buffer; +} + +#ifdef USE_WEBSERVER +const char HTTP_MGS_GAS[] PROGMEM = "{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; +#endif + +void MGSShow(bool json) +{ + char buffer[33]; + if (json) { + ResponseAppend_P(PSTR(",\"MGS\":{\"NH3\":%s"), measure_gas(NH3, buffer)); + ResponseAppend_P(PSTR(",\"CO\":%s"), measure_gas(CO, buffer)); + ResponseAppend_P(PSTR(",\"NO2\":%s"), measure_gas(NO2, buffer)); + ResponseAppend_P(PSTR(",\"C3H8\":%s"), measure_gas(C3H8, buffer)); + ResponseAppend_P(PSTR(",\"C4H10\":%s"), measure_gas(C4H10, buffer)); + ResponseAppend_P(PSTR(",\"CH4\":%s"), measure_gas(GAS_CH4, buffer)); + ResponseAppend_P(PSTR(",\"H2\":%s"), measure_gas(H2, buffer)); + ResponseAppend_P(PSTR(",\"C2H5OH\":%s}"), measure_gas(C2H5OH, buffer)); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "CO", measure_gas(CO, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "NO2", measure_gas(NO2, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C3H8", measure_gas(C3H8, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C4H10", measure_gas(C4H10, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "CH4", measure_gas(GAS_CH4, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "H2", measure_gas(H2, buffer)); + WSContentSend_PD(HTTP_MGS_GAS, "C2H5OH", measure_gas(C2H5OH, buffer)); +#endif + } +} + + + + + +bool Xsns19(uint8_t function) +{ + if (!I2cEnabled(XI2C_17)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MGSPrepare(); + } + else if (mgs_detected) { + switch (function) { + case FUNC_JSON_APPEND: + MGSShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MGSShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_20_novasds.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_20_novasds.ino" +#ifdef USE_NOVA_SDS +# 30 "S:/Development/Tasmota/tasmota/xsns_20_novasds.ino" +#define XSNS_20 20 + +#include + +#ifndef STARTING_OFFSET +#define STARTING_OFFSET 30 +#endif +#if STARTING_OFFSET < 10 +#error "Please set STARTING_OFFSET >= 10" +#endif +#ifndef NOVA_SDS_RECDATA_TIMEOUT +#define NOVA_SDS_RECDATA_TIMEOUT 150 +#endif +#ifndef NOVA_SDS_DEVICE_ID +#define NOVA_SDS_DEVICE_ID 0xFFFF +#endif + +TasmotaSerial *NovaSdsSerial; + +uint8_t novasds_type = 1; +uint8_t novasds_valid = 0; +uint8_t cont_mode = 1; + +struct sds011data { + uint16_t pm100; + uint16_t pm25; +} novasds_data; +uint16_t pm100_sum; +uint16_t pm25_sum; + + +#define NOVA_SDS_REPORTING_MODE 2 +#define NOVA_SDS_QUERY_DATA 4 +#define NOVA_SDS_SET_DEVICE_ID 5 +#define NOVA_SDS_SLEEP_AND_WORK 6 +#define NOVA_SDS_WORKING_PERIOD 8 +#define NOVA_SDS_CHECK_FIRMWARE_VER 7 + #define NOVA_SDS_QUERY_MODE 0 + #define NOVA_SDS_SET_MODE 1 + #define NOVA_SDS_REPORT_ACTIVE 0 + #define NOVA_SDS_REPORT_QUERY 1 + #define NOVA_SDS_SLEEP 0 + #define NOVA_SDS_WORK 1 + + +bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) +{ + uint8_t novasds_cmnd[19] = {0xAA, 0xB4, byte1, byte2, byte3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t)(sensorid & 0xFF), (uint8_t)((sensorid>>8) & 0xFF), 0x00, 0xAB}; + + + for (uint32_t i = 2; i < 17; i++) { + novasds_cmnd[17] += novasds_cmnd[i]; + } + + + + + + NovaSdsSerial->write(novasds_cmnd, sizeof(novasds_cmnd)); + NovaSdsSerial->flush(); + + + unsigned long cmndtime = millis(); + while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( ! NovaSdsSerial->available() ) ); + if ( ! NovaSdsSerial->available() ) { + + return false; + } + uint8_t recbuf[10]; + memset(recbuf, 0, sizeof(recbuf)); + + while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( NovaSdsSerial->available() > 0) && (0xAA != (recbuf[0] = NovaSdsSerial->read())) ); + if ( 0xAA != recbuf[0] ) { + + return false; + } + + + NovaSdsSerial->readBytes(&recbuf[1], 9); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); + + if ( nullptr != buffer ) { + + memcpy(buffer, recbuf, sizeof(recbuf)); + } + + + if ((0xAB != recbuf[9] ) || (recbuf[8] != ((recbuf[2] + recbuf[3] + recbuf[4] + recbuf[5] + recbuf[6] + recbuf[7]) & 0xFF))) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); + return false; + } + + return true; +} + +void NovaSdsSetWorkPeriod(void) +{ + + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, 0, NOVA_SDS_DEVICE_ID, nullptr); + + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); +} + +bool NovaSdsReadData(void) +{ + uint8_t d[10]; + if ( ! NovaSdsCommand(NOVA_SDS_QUERY_DATA, 0, 0, NOVA_SDS_DEVICE_ID, d) ) { + return false; + } + novasds_data.pm25 = (d[2] + 256 * d[3]); + novasds_data.pm100 = (d[4] + 256 * d[5]); + + return true; +} + + + +void NovaSdsSecond(void) +{ + if (!novasds_valid) + { + NovaSdsSetWorkPeriod(); + novasds_valid=1; + } + if((Settings.tele_period - Settings.novasds_startingoffset <= 0)) + { + if(!cont_mode) + { + cont_mode = 1; + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); + } + } + else + cont_mode = 0; + + if(tele_period == Settings.tele_period - Settings.novasds_startingoffset && !cont_mode) + { + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); + } + if(tele_period >= Settings.tele_period-5 && tele_period <= Settings.tele_period-2) + { + if(!(NovaSdsReadData())) novasds_valid=0; + pm100_sum += novasds_data.pm100; + pm25_sum += novasds_data.pm25; + } + if(tele_period == Settings.tele_period-1) + { + novasds_data.pm100 = pm100_sum >> 2; + novasds_data.pm25 = pm25_sum >> 2; + if(!cont_mode) + NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_SLEEP, NOVA_SDS_DEVICE_ID, nullptr); + pm100_sum = pm25_sum = 0; + } +} + + + + + + + +bool NovaSdsCommandSensor(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { + if( XdrvMailbox.payload < 10 ) Settings.novasds_startingoffset = 10; + else Settings.novasds_startingoffset = XdrvMailbox.payload; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_startingoffset); + + return true; +} + +void NovaSdsInit(void) +{ + novasds_type = 0; + if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { + NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); + if (NovaSdsSerial->begin(9600)) { + if (NovaSdsSerial->hardwareSerial()) { + ClaimSerial(); + } + novasds_type = 1; + NovaSdsSetWorkPeriod(); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SDS0X1_SNS[] PROGMEM = + "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#endif + +void NovaSdsShow(bool json) +{ + if (novasds_valid) { + float pm10f = (float)(novasds_data.pm100) / 10.0f; + float pm2_5f = (float)(novasds_data.pm25) / 10.0f; + char pm10[33]; + dtostrfd(pm10f, 1, pm10); + char pm2_5[33]; + dtostrfd(pm2_5f, 1, pm2_5); + if (json) { + ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, pm2_5); + DomoticzSensor(DZ_CURRENT, pm10); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SDS0X1_SNS, pm2_5, pm10); +#endif + } + } +} + + + + + +bool Xsns20(uint8_t function) +{ + bool result = false; + + if (novasds_type) { + switch (function) { + case FUNC_INIT: + NovaSdsInit(); + break; + case FUNC_EVERY_SECOND: + NovaSdsSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_20 == XdrvMailbox.index) { + result = NovaSdsCommandSensor(); + } + break; + case FUNC_JSON_APPEND: + NovaSdsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + NovaSdsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_21_sgp30.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_21_sgp30.ino" +#ifdef USE_I2C +#ifdef USE_SGP30 +# 30 "S:/Development/Tasmota/tasmota/xsns_21_sgp30.ino" +#define XSNS_21 21 +#define XI2C_18 18 + +#define SGP30_ADDRESS 0x58 + +#include "Adafruit_SGP30.h" +Adafruit_SGP30 sgp; + +bool sgp30_type = false; +bool sgp30_ready = false; +float sgp30_abshum; + + + +void sgp30_Init(void) +{ + if (I2cActive(SGP30_ADDRESS)) { return; } + + if (sgp.begin()) { + sgp30_type = true; + + I2cSetActiveFound(SGP30_ADDRESS, "SGP30"); + } +} + + +#define POW_FUNC FastPrecisePow + +float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit) { + + + + + + float temp = NAN; + const float mw = 18.01534; + const float r = 8.31447215; + + if (isnan(temperature) || isnan(humidity) ) { + return NAN; + } + + if (tempUnit != 'C') { + temperature = (temperature - 32.0) * (5.0 / 9.0); + } + + temp = POW_FUNC(2.718281828, (17.67 * temperature) / (temperature + 243.5)); + + + return (6.112 * temp * humidity * mw) / ((273.15 + temperature) * r); +} + +#define SAVE_PERIOD 30 + +void Sgp30Update(void) +{ + sgp30_ready = false; + if (!sgp.IAQmeasure()) { + return; + } + if (global_update && (global_humidity > 0) && (global_temperature != 9999)) { + + sgp30_abshum=sgp30_AbsoluteHumidity(global_temperature,global_humidity,TempUnit()); + sgp.setHumidity(sgp30_abshum*1000); + } + sgp30_ready = true; + + + if (!(uptime%SAVE_PERIOD)) { + + uint16_t TVOC_base; + uint16_t eCO2_base; + + if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; + + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SGP30[] PROGMEM = + "{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" + "{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; +const char HTTP_SNS_AHUM[] PROGMEM = "{s}SGP30 Abs Humidity{m}%s g/m3{e}"; +#endif + +#define D_JSON_AHUM "aHumidity" + +void Sgp30Show(bool json) +{ + if (sgp30_ready) { + char abs_hum[33]; + + if (json) { + ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); + if (global_update && global_humidity>0 && global_temperature!=9999) { + + dtostrfd(sgp30_abshum,4,abs_hum); + ResponseAppend_P(PSTR(",\"" D_JSON_AHUM "\":%s"),abs_hum); + } + ResponseJsonEnd(); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC); + if (global_update) { + WSContentSend_PD(HTTP_SNS_AHUM, abs_hum); + } +#endif + } + } +} + + + + + +bool Xsns21(uint8_t function) +{ + if (!I2cEnabled(XI2C_18)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + sgp30_Init(); + } + else if (sgp30_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Sgp30Update(); + break; + case FUNC_JSON_APPEND: + Sgp30Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sgp30Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_22_sr04.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_22_sr04.ino" +#ifdef USE_SR04 + +#include +#include +# 32 "S:/Development/Tasmota/tasmota/xsns_22_sr04.ino" +#define XSNS_22 22 + +uint8_t sr04_type = 1; +int sr04_echo_pin = 0; +int sr04_trig_pin = 0; +real64_t distance; + +NewPing* sonar = nullptr; +TasmotaSerial* sonar_serial = nullptr; + + + +uint8_t Sr04TModeDetect(void) +{ + sr04_type = 0; + if (pin[GPIO_SR04_ECHO]>=99) return sr04_type; + + sr04_echo_pin = pin[GPIO_SR04_ECHO]; + sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : -1; + sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); + + if (sonar_serial->begin(9600,1)) { + DEBUG_SENSOR_LOG(PSTR("SR04: Detect mode")); + + if (sr04_trig_pin!=-1) { + sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance())!=NO_ECHO)?3:1; + } else { + sr04_type = 2; + } + } else { + sr04_type = 1; + } + + if (sr04_type < 2) { + delete sonar_serial; + sonar_serial = nullptr; + sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); + } else { + if (sonar_serial->hardwareSerial()) { + ClaimSerial(); + } + } + + AddLog_P2(LOG_LEVEL_INFO,PSTR("SR04: Mode %d"), sr04_type); + return sr04_type; +} + +uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) +{ + uint16_t ret = first; + if (first > second) { + first = second; + second = ret; + } + + if (third < first) { + return first; + } else if (third > second) { + return second; + } else { + return third; + } +} + +uint16_t Sr04TMode3Distance() { + + sonar_serial->write(0x55); + sonar_serial->flush(); + + return Sr04TMode2Distance(); +} + +uint16_t Sr04TMode2Distance(void) +{ + sonar_serial->setTimeout(300); + const char startByte = 0xff; + + if (!sonar_serial->find(startByte)) { + + return NO_ECHO; + } + + delay(5); + + uint8_t crc = sonar_serial->read(); + + uint16_t distance = ((uint16_t)crc) << 8; + + + distance += sonar_serial->read(); + crc += distance & 0x00ff; + crc += 0x00FF; + + + if (crc != sonar_serial->read()) { + AddLog_P2(LOG_LEVEL_ERROR,PSTR("SR04: Reading CRC error.")); + return NO_ECHO; + } + + return distance; +} + +void Sr04TReading(void) { + + if (sonar_serial==nullptr && sonar==nullptr) { + Sr04TModeDetect(); + } + + switch (sr04_type) { + case 3: + distance = (real64_t)(Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance()))/ 10; + break; + case 2: + + while(sonar_serial->available()) sonar_serial->read(); + distance = (real64_t)(Sr04TMiddleValue(Sr04TMode2Distance(),Sr04TMode2Distance(),Sr04TMode2Distance()))/10; + break; + case 1: + distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; + break; + default: + distance = NO_ECHO; + } + + return; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_DISTANCE[] PROGMEM = + "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; +#endif + +void Sr04Show(bool json) +{ + + if (distance != 0) { + char distance_chr[33]; + dtostrfd(distance, 3, distance_chr); + + if(json) { + ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_COUNT, distance_chr); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_DISTANCE, distance_chr); +#endif + } + } +} + + + + + +bool Xsns22(uint8_t function) +{ + bool result = false; + + if (sr04_type) { + switch (function) { + case FUNC_INIT: + result = (pin[GPIO_SR04_ECHO]<99); + break; + case FUNC_EVERY_SECOND: + Sr04TReading(); + result = true; + break; + case FUNC_JSON_APPEND: + Sr04Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Sr04Show(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_24_si1145.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_24_si1145.ino" +#ifdef USE_I2C +#ifdef USE_SI1145 +# 30 "S:/Development/Tasmota/tasmota/xsns_24_si1145.ino" +#define XSNS_24 24 +#define XI2C_19 19 + +#define SI114X_ADDR 0X60 + + + +#define SI114X_QUERY 0X80 +#define SI114X_SET 0XA0 +#define SI114X_NOP 0X00 +#define SI114X_RESET 0X01 +#define SI114X_BUSADDR 0X02 +#define SI114X_PS_FORCE 0X05 +#define SI114X_GET_CAL 0X12 +#define SI114X_ALS_FORCE 0X06 +#define SI114X_PSALS_FORCE 0X07 +#define SI114X_PS_PAUSE 0X09 +#define SI114X_ALS_PAUSE 0X0A +#define SI114X_PSALS_PAUSE 0X0B +#define SI114X_PS_AUTO 0X0D +#define SI114X_ALS_AUTO 0X0E +#define SI114X_PSALS_AUTO 0X0F + + + +#define SI114X_PART_ID 0X00 +#define SI114X_REV_ID 0X01 +#define SI114X_SEQ_ID 0X02 +#define SI114X_INT_CFG 0X03 +#define SI114X_IRQ_ENABLE 0X04 +#define SI114X_IRQ_MODE1 0x05 +#define SI114X_IRQ_MODE2 0x06 +#define SI114X_HW_KEY 0X07 +#define SI114X_MEAS_RATE0 0X08 +#define SI114X_MEAS_RATE1 0X09 +#define SI114X_PS_RATE 0X0A +#define SI114X_PS_LED21 0X0F +#define SI114X_PS_LED3 0X10 +#define SI114X_UCOEFF0 0X13 +#define SI114X_UCOEFF1 0X14 +#define SI114X_UCOEFF2 0X15 +#define SI114X_UCOEFF3 0X16 +#define SI114X_WR 0X17 +#define SI114X_COMMAND 0X18 +#define SI114X_RESPONSE 0X20 +#define SI114X_IRQ_STATUS 0X21 +#define SI114X_ALS_VIS_DATA0 0X22 +#define SI114X_ALS_VIS_DATA1 0X23 +#define SI114X_ALS_IR_DATA0 0X24 +#define SI114X_ALS_IR_DATA1 0X25 +#define SI114X_PS1_DATA0 0X26 +#define SI114X_PS1_DATA1 0X27 +#define SI114X_PS2_DATA0 0X28 +#define SI114X_PS2_DATA1 0X29 +#define SI114X_PS3_DATA0 0X2A +#define SI114X_PS3_DATA1 0X2B +#define SI114X_AUX_DATA0_UVINDEX0 0X2C +#define SI114X_AUX_DATA1_UVINDEX1 0X2D +#define SI114X_RD 0X2E +#define SI114X_CHIP_STAT 0X30 + + + +#define SI114X_CHLIST 0X01 +#define SI114X_CHLIST_ENUV 0x80 +#define SI114X_CHLIST_ENAUX 0x40 +#define SI114X_CHLIST_ENALSIR 0x20 +#define SI114X_CHLIST_ENALSVIS 0x10 +#define SI114X_CHLIST_ENPS1 0x01 +#define SI114X_CHLIST_ENPS2 0x02 +#define SI114X_CHLIST_ENPS3 0x04 + +#define SI114X_PSLED12_SELECT 0X02 +#define SI114X_PSLED3_SELECT 0X03 + +#define SI114X_PS_ENCODE 0X05 +#define SI114X_ALS_ENCODE 0X06 + +#define SI114X_PS1_ADCMUX 0X07 +#define SI114X_PS2_ADCMUX 0X08 +#define SI114X_PS3_ADCMUX 0X09 + +#define SI114X_PS_ADC_COUNTER 0X0A +#define SI114X_PS_ADC_GAIN 0X0B +#define SI114X_PS_ADC_MISC 0X0C + +#define SI114X_ALS_IR_ADC_MUX 0X0E +#define SI114X_AUX_ADC_MUX 0X0F + +#define SI114X_ALS_VIS_ADC_COUNTER 0X10 +#define SI114X_ALS_VIS_ADC_GAIN 0X11 +#define SI114X_ALS_VIS_ADC_MISC 0X12 + +#define SI114X_LED_REC 0X1C + +#define SI114X_ALS_IR_ADC_COUNTER 0X1D +#define SI114X_ALS_IR_ADC_GAIN 0X1E +#define SI114X_ALS_IR_ADC_MISC 0X1F + + + + +#define SI114X_ADCMUX_SMALL_IR 0x00 +#define SI114X_ADCMUX_VISIABLE 0x02 +#define SI114X_ADCMUX_LARGE_IR 0x03 +#define SI114X_ADCMUX_NO 0x06 +#define SI114X_ADCMUX_GND 0x25 +#define SI114X_ADCMUX_TEMPERATURE 0x65 +#define SI114X_ADCMUX_VDD 0x75 + +#define SI114X_PSLED12_SELECT_PS1_NONE 0x00 +#define SI114X_PSLED12_SELECT_PS1_LED1 0x01 +#define SI114X_PSLED12_SELECT_PS1_LED2 0x02 +#define SI114X_PSLED12_SELECT_PS1_LED3 0x04 +#define SI114X_PSLED12_SELECT_PS2_NONE 0x00 +#define SI114X_PSLED12_SELECT_PS2_LED1 0x10 +#define SI114X_PSLED12_SELECT_PS2_LED2 0x20 +#define SI114X_PSLED12_SELECT_PS2_LED3 0x40 +#define SI114X_PSLED3_SELECT_PS2_NONE 0x00 +#define SI114X_PSLED3_SELECT_PS2_LED1 0x10 +#define SI114X_PSLED3_SELECT_PS2_LED2 0x20 +#define SI114X_PSLED3_SELECT_PS2_LED3 0x40 + +#define SI114X_ADC_GAIN_DIV1 0X00 +#define SI114X_ADC_GAIN_DIV2 0X01 +#define SI114X_ADC_GAIN_DIV4 0X02 +#define SI114X_ADC_GAIN_DIV8 0X03 +#define SI114X_ADC_GAIN_DIV16 0X04 +#define SI114X_ADC_GAIN_DIV32 0X05 + +#define SI114X_LED_CURRENT_5MA 0X01 +#define SI114X_LED_CURRENT_11MA 0X02 +#define SI114X_LED_CURRENT_22MA 0X03 +#define SI114X_LED_CURRENT_45MA 0X04 + +#define SI114X_ADC_COUNTER_1ADCCLK 0X00 +#define SI114X_ADC_COUNTER_7ADCCLK 0X01 +#define SI114X_ADC_COUNTER_15ADCCLK 0X02 +#define SI114X_ADC_COUNTER_31ADCCLK 0X03 +#define SI114X_ADC_COUNTER_63ADCCLK 0X04 +#define SI114X_ADC_COUNTER_127ADCCLK 0X05 +#define SI114X_ADC_COUNTER_255ADCCLK 0X06 +#define SI114X_ADC_COUNTER_511ADCCLK 0X07 + +#define SI114X_ADC_MISC_LOWRANGE 0X00 +#define SI114X_ADC_MISC_HIGHRANGE 0X20 +#define SI114X_ADC_MISC_ADC_NORMALPROXIMITY 0X00 +#define SI114X_ADC_MISC_ADC_RAWADC 0X04 + +#define SI114X_INT_CFG_INTOE 0X01 + +#define SI114X_IRQEN_ALS 0x01 +#define SI114X_IRQEN_PS1 0x04 +#define SI114X_IRQEN_PS2 0x08 +#define SI114X_IRQEN_PS3 0x10 + +uint16_t si1145_visible; +uint16_t si1145_infrared; +uint16_t si1145_uvindex; + +bool si1145_type = false; +uint8_t si1145_valid = 0; + + + +uint8_t Si1145ReadByte(uint8_t reg) +{ + return I2cRead8(SI114X_ADDR, reg); +} + +uint16_t Si1145ReadHalfWord(uint8_t reg) +{ + return I2cRead16LE(SI114X_ADDR, reg); +} + +bool Si1145WriteByte(uint8_t reg, uint16_t val) +{ + I2cWrite8(SI114X_ADDR, reg, val); +} + +uint8_t Si1145WriteParamData(uint8_t p, uint8_t v) +{ + Si1145WriteByte(SI114X_WR, v); + Si1145WriteByte(SI114X_COMMAND, p | SI114X_SET); + return Si1145ReadByte(SI114X_RD); +} + + + +bool Si1145Present(void) +{ + return (Si1145ReadByte(SI114X_PART_ID) == 0X45); +} + +void Si1145Reset(void) +{ + Si1145WriteByte(SI114X_MEAS_RATE0, 0); + Si1145WriteByte(SI114X_MEAS_RATE1, 0); + Si1145WriteByte(SI114X_IRQ_ENABLE, 0); + Si1145WriteByte(SI114X_IRQ_MODE1, 0); + Si1145WriteByte(SI114X_IRQ_MODE2, 0); + Si1145WriteByte(SI114X_INT_CFG, 0); + Si1145WriteByte(SI114X_IRQ_STATUS, 0xFF); + + Si1145WriteByte(SI114X_COMMAND, SI114X_RESET); + delay(10); + Si1145WriteByte(SI114X_HW_KEY, 0x17); + delay(10); +} + +void Si1145DeInit(void) +{ + + + Si1145WriteByte(SI114X_UCOEFF0, 0x29); + Si1145WriteByte(SI114X_UCOEFF1, 0x89); + Si1145WriteByte(SI114X_UCOEFF2, 0x02); + Si1145WriteByte(SI114X_UCOEFF3, 0x00); + Si1145WriteParamData(SI114X_CHLIST, SI114X_CHLIST_ENUV | SI114X_CHLIST_ENALSIR | SI114X_CHLIST_ENALSVIS | SI114X_CHLIST_ENPS1); + + + + Si1145WriteParamData(SI114X_PS1_ADCMUX, SI114X_ADCMUX_LARGE_IR); + Si1145WriteByte(SI114X_PS_LED21, SI114X_LED_CURRENT_22MA); + Si1145WriteParamData(SI114X_PSLED12_SELECT, SI114X_PSLED12_SELECT_PS1_LED1); + + + + Si1145WriteParamData(SI114X_PS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_PS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_PS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE | SI114X_ADC_MISC_ADC_RAWADC); + + + + Si1145WriteParamData(SI114X_ALS_VIS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_ALS_VIS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_ALS_VIS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); + + + + Si1145WriteParamData(SI114X_ALS_IR_ADC_GAIN, SI114X_ADC_GAIN_DIV1); + Si1145WriteParamData(SI114X_ALS_IR_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); + Si1145WriteParamData(SI114X_ALS_IR_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); + + + + Si1145WriteByte(SI114X_INT_CFG, SI114X_INT_CFG_INTOE); + Si1145WriteByte(SI114X_IRQ_ENABLE, SI114X_IRQEN_ALS); + + + + Si1145WriteByte(SI114X_MEAS_RATE0, 0xFF); + Si1145WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO); +} + +bool Si1145Begin(void) +{ + if (!Si1145Present()) { return false; } + + Si1145Reset(); + Si1145DeInit(); + return true; +} + + +uint16_t Si1145ReadUV(void) +{ + return Si1145ReadHalfWord(SI114X_AUX_DATA0_UVINDEX0); +} + + +uint16_t Si1145ReadVisible(void) +{ + return Si1145ReadHalfWord(SI114X_ALS_VIS_DATA0); +} + + +uint16_t Si1145ReadIR(void) +{ + return Si1145ReadHalfWord(SI114X_ALS_IR_DATA0); +} + + + +bool Si1145Read(void) +{ + if (si1145_valid) { si1145_valid--; } + + if (!Si1145Present()) { return false; } + + si1145_visible = Si1145ReadVisible(); + si1145_infrared = Si1145ReadIR(); + si1145_uvindex = Si1145ReadUV(); + si1145_valid = SENSOR_MAX_MISS; + return true; +} + +void Si1145Detect(void) +{ + if (I2cActive(SI114X_ADDR)) { return; } + + if (Si1145Begin()) { + si1145_type = true; + I2cSetActiveFound(SI114X_ADDR, "SI1145"); + } +} + +void Si1145Update(void) +{ + if (!Si1145Read()) { + AddLogMissed("SI1145", si1145_valid); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SI1145[] PROGMEM = + "{s}SI1145 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}" + "{s}SI1145 " D_INFRARED "{m}%d " D_UNIT_LUX "{e}" + "{s}SI1145 " D_UV_INDEX "{m}%d.%d{e}"; +#endif + +void Si1145Show(bool json) +{ + if (si1145_valid) { + if (json) { + ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), + si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, si1145_visible); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_SI1145, si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); +#endif + } + } +} + + + + + +bool Xsns24(uint8_t function) +{ + if (!I2cEnabled(XI2C_19)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Si1145Detect(); + } + else if (si1145_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Si1145Update(); + break; + case FUNC_JSON_APPEND: + Si1145Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Si1145Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_26_lm75ad.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_26_lm75ad.ino" +#ifdef USE_I2C +#ifdef USE_LM75AD +# 31 "S:/Development/Tasmota/tasmota/xsns_26_lm75ad.ino" +#define XSNS_26 26 +#define XI2C_20 20 + +#define LM75AD_ADDRESS1 0x48 +#define LM75AD_ADDRESS2 0x49 +#define LM75AD_ADDRESS3 0x4A +#define LM75AD_ADDRESS4 0x4B +#define LM75AD_ADDRESS5 0x4C +#define LM75AD_ADDRESS6 0x4D +#define LM75AD_ADDRESS7 0x4E +#define LM75AD_ADDRESS8 0x4F + +#define LM75_TEMP_REGISTER 0x00 +#define LM75_CONF_REGISTER 0x01 +#define LM75_THYST_REGISTER 0x02 +#define LM75_TOS_REGISTER 0x03 + +bool lm75ad_type = false; +uint8_t lm75ad_address; +uint8_t lm75ad_addresses[] = { LM75AD_ADDRESS1, LM75AD_ADDRESS2, LM75AD_ADDRESS3, LM75AD_ADDRESS4, LM75AD_ADDRESS5, LM75AD_ADDRESS6, LM75AD_ADDRESS7, LM75AD_ADDRESS8 }; + +void LM75ADDetect(void) +{ + for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { + lm75ad_address = lm75ad_addresses[i]; + if (I2cActive(lm75ad_address)) { + continue; } + if (!I2cSetDevice(lm75ad_address)) { + break; + } + uint16_t buffer; + if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { + if (buffer == 0x4B00) { + lm75ad_type = true; + I2cSetActiveFound(lm75ad_address, "LM75AD"); + break; + } + } + } +} + +float LM75ADGetTemp(void) +{ + int16_t sign = 1; + + uint16_t t = I2cRead16(lm75ad_address, LM75_TEMP_REGISTER); + if (t & 0x8000) { + t = (~t) +0x20; + sign = -1; + } + t = t >> 5; + return ConvertTemp(sign * t * 0.125); +} + +void LM75ADShow(bool json) +{ + float t = LM75ADGetTemp(); + char temperature[33]; + dtostrfd(t, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(PSTR(",\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), temperature); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "LM75AD", temperature, TempUnit()); +#endif + } +} + + + + + +bool Xsns26(uint8_t function) +{ + if (!I2cEnabled(XI2C_20)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + LM75ADDetect(); + } + else if (lm75ad_type) { + switch (function) { + case FUNC_JSON_APPEND: + LM75ADShow(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + LM75ADShow(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +# 28 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +#ifdef USE_I2C +#ifdef USE_APDS9960 +# 39 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +#define XSNS_27 27 +#define XI2C_21 21 + +#if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) + #warning **** Turned off conflicting drivers SHT and VEML6070 **** + #ifdef USE_SHT + #undef USE_SHT + #endif + #ifdef USE_VEML6070 + #undef USE_VEML6070 + #endif + #ifdef USE_TSL2561 + #undef USE_TSL2561 + #endif +#endif + +#define APDS9960_I2C_ADDR 0x39 + +#define APDS9960_CHIPID_1 0xAB +#define APDS9960_CHIPID_2 0x9C + +#define APDS9930_CHIPID_1 0x12 +#define APDS9930_CHIPID_2 0x39 + + +#define GESTURE_THRESHOLD_OUT 10 +#define GESTURE_SENSITIVITY_1 50 +#define GESTURE_SENSITIVITY_2 20 + +uint8_t APDS9960addr; +uint8_t APDS9960type = 0; +char APDS9960stype[] = "APDS9960"; +char currentGesture[6]; +uint8_t gesture_mode = 1; + + +volatile uint8_t recovery_loop_counter = 0; +#define APDS9960_LONG_RECOVERY 50 +#define APDS9960_MAX_GESTURE_CYCLES 50 +bool APDS9960_overload = false; + +#ifdef USE_WEBSERVER +const char HTTP_APDS_9960_SNS[] PROGMEM = + "{s}" "Red" "{m}%s{e}" + "{s}" "Green" "{m}%s{e}" + "{s}" "Blue" "{m}%s{e}" + "{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" + "{s}" "CCT" "{m}%s " "K" "{e}" + "{s}" "Proximity" "{m}%s{e}"; +#endif +# 97 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +#define FIFO_PAUSE_TIME 30 + + +#define APDS9960_ENABLE 0x80 +#define APDS9960_ATIME 0x81 +#define APDS9960_WTIME 0x83 +#define APDS9960_AILTL 0x84 +#define APDS9960_AILTH 0x85 +#define APDS9960_AIHTL 0x86 +#define APDS9960_AIHTH 0x87 +#define APDS9960_PILT 0x89 +#define APDS9960_PIHT 0x8B +#define APDS9960_PERS 0x8C +#define APDS9960_CONFIG1 0x8D +#define APDS9960_PPULSE 0x8E +#define APDS9960_CONTROL 0x8F +#define APDS9960_CONFIG2 0x90 +#define APDS9960_ID 0x92 +#define APDS9960_STATUS 0x93 +#define APDS9960_CDATAL 0x94 +#define APDS9960_CDATAH 0x95 +#define APDS9960_RDATAL 0x96 +#define APDS9960_RDATAH 0x97 +#define APDS9960_GDATAL 0x98 +#define APDS9960_GDATAH 0x99 +#define APDS9960_BDATAL 0x9A +#define APDS9960_BDATAH 0x9B +#define APDS9960_PDATA 0x9C +#define APDS9960_POFFSET_UR 0x9D +#define APDS9960_POFFSET_DL 0x9E +#define APDS9960_CONFIG3 0x9F +#define APDS9960_GPENTH 0xA0 +#define APDS9960_GEXTH 0xA1 +#define APDS9960_GCONF1 0xA2 +#define APDS9960_GCONF2 0xA3 +#define APDS9960_GOFFSET_U 0xA4 +#define APDS9960_GOFFSET_D 0xA5 +#define APDS9960_GOFFSET_L 0xA7 +#define APDS9960_GOFFSET_R 0xA9 +#define APDS9960_GPULSE 0xA6 +#define APDS9960_GCONF3 0xAA +#define APDS9960_GCONF4 0xAB +#define APDS9960_GFLVL 0xAE +#define APDS9960_GSTATUS 0xAF +#define APDS9960_IFORCE 0xE4 +#define APDS9960_PICLEAR 0xE5 +#define APDS9960_CICLEAR 0xE6 +#define APDS9960_AICLEAR 0xE7 +#define APDS9960_GFIFO_U 0xFC +#define APDS9960_GFIFO_D 0xFD +#define APDS9960_GFIFO_L 0xFE +#define APDS9960_GFIFO_R 0xFF + + +#define APDS9960_PON 0b00000001 +#define APDS9960_AEN 0b00000010 +#define APDS9960_PEN 0b00000100 +#define APDS9960_WEN 0b00001000 +#define APSD9960_AIEN 0b00010000 +#define APDS9960_PIEN 0b00100000 +#define APDS9960_GEN 0b01000000 +#define APDS9960_GVALID 0b00000001 + + +#define OFF 0 +#define ON 1 + + +#define POWER 0 +#define AMBIENT_LIGHT 1 +#define PROXIMITY 2 +#define WAIT 3 +#define AMBIENT_LIGHT_INT 4 +#define PROXIMITY_INT 5 +#define GESTURE 6 +#define ALL 7 + + +#define LED_DRIVE_100MA 0 +#define LED_DRIVE_50MA 1 +#define LED_DRIVE_25MA 2 +#define LED_DRIVE_12_5MA 3 + + +#define PGAIN_1X 0 +#define PGAIN_2X 1 +#define PGAIN_4X 2 +#define PGAIN_8X 3 + + +#define AGAIN_1X 0 +#define AGAIN_4X 1 +#define AGAIN_16X 2 +#define AGAIN_64X 3 + + +#define GGAIN_1X 0 +#define GGAIN_2X 1 +#define GGAIN_4X 2 +#define GGAIN_8X 3 + + +#define LED_BOOST_100 0 +#define LED_BOOST_150 1 +#define LED_BOOST_200 2 +#define LED_BOOST_300 3 + + +#define GWTIME_0MS 0 +#define GWTIME_2_8MS 1 +#define GWTIME_5_6MS 2 +#define GWTIME_8_4MS 3 +#define GWTIME_14_0MS 4 +#define GWTIME_22_4MS 5 +#define GWTIME_30_8MS 6 +#define GWTIME_39_2MS 7 + + +#define DEFAULT_ATIME 0xdb +#define DEFAULT_WTIME 246 +#define DEFAULT_PROX_PPULSE 0x87 +#define DEFAULT_GESTURE_PPULSE 0x89 +#define DEFAULT_POFFSET_UR 0 +#define DEFAULT_POFFSET_DL 0 +#define DEFAULT_CONFIG1 0x60 +#define DEFAULT_LDRIVE LED_DRIVE_100MA +#define DEFAULT_PGAIN PGAIN_4X +#define DEFAULT_AGAIN AGAIN_4X +#define DEFAULT_PILT 0 +#define DEFAULT_PIHT 50 +#define DEFAULT_AILT 0xFFFF +#define DEFAULT_AIHT 0 +#define DEFAULT_PERS 0x11 +#define DEFAULT_CONFIG2 0x01 +#define DEFAULT_CONFIG3 0 +#define DEFAULT_GPENTH 40 +#define DEFAULT_GEXTH 30 +#define DEFAULT_GCONF1 0x40 +#define DEFAULT_GGAIN GGAIN_4X +#define DEFAULT_GLDRIVE LED_DRIVE_100MA +#define DEFAULT_GWTIME GWTIME_2_8MS +#define DEFAULT_GOFFSET 0 +#define DEFAULT_GPULSE 0xC9 +#define DEFAULT_GCONF3 0 +#define DEFAULT_GIEN 0 + +#define ERROR 0xFF + + +enum { + DIR_NONE, + DIR_LEFT, + DIR_RIGHT, + DIR_UP, + DIR_DOWN, + DIR_ALL +}; + + +enum { + APDS9960_NA_STATE, + APDS9960_ALL_STATE +}; + + +typedef struct gesture_data_type { + uint8_t u_data[32]; + uint8_t d_data[32]; + uint8_t l_data[32]; + uint8_t r_data[32]; + uint8_t index; + uint8_t total_gestures; + uint8_t in_threshold; + uint8_t out_threshold; +} gesture_data_type; + + + gesture_data_type gesture_data_; + int16_t gesture_ud_delta_ = 0; + int16_t gesture_lr_delta_ = 0; + int16_t gesture_ud_count_ = 0; + int16_t gesture_lr_count_ = 0; + int16_t gesture_state_ = 0; + int16_t gesture_motion_ = DIR_NONE; + + typedef struct color_data_type { + uint16_t a; + uint16_t r; + uint16_t g; + uint16_t b; + uint8_t p; + uint16_t cct; + uint16_t lux; + } color_data_type; + + color_data_type color_data; + uint8_t APDS9960_aTime = DEFAULT_ATIME; +# 306 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + bool wireWriteByte(uint8_t val) + { + Wire.beginTransmission(APDS9960_I2C_ADDR); + Wire.write(val); + if( Wire.endTransmission() != 0 ) { + return false; + } + + return true; + } +# 325 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +int8_t wireReadDataBlock( uint8_t reg, + uint8_t *val, + uint16_t len) +{ + unsigned char i = 0; + + + if (!wireWriteByte(reg)) { + return -1; + } + + + Wire.requestFrom(APDS9960_I2C_ADDR, len); + while (Wire.available()) { + if (i >= len) { + return -1; + } + val[i] = Wire.read(); + i++; + } + + return i; +} + + + + + + + +void calculateColorTemperature(void) +{ + float X, Y, Z; + float xc, yc; + float n; + float cct; + + + + + + X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b); + Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); + Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b); + + + xc = (X) / (X + Y + Z); + yc = (Y) / (X + Y + Z); + + + n = (xc - 0.3320F) / (0.1858F - yc); + + + color_data.cct = (449.0F * FastPrecisePowf(n, 3)) + (3525.0F * FastPrecisePowf(n, 2)) + (6823.3F * n) + 5520.33F; + + return; +} +# 392 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getProxIntLowThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT) ; + return val; + } + + + + + + + void setProxIntLowThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); + } + + + + + + + uint8_t getProxIntHighThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; + return val; + } + + + + + + + + void setProxIntHighThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); + } +# 448 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getLEDDrive(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; + + val = (val >> 6) & 0b00000011; + + return val; + } +# 471 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void setLEDDrive(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + drive = drive << 6; + val &= 0b00111111; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 500 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getProximityGain(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; + + val = (val >> 2) & 0b00000011; + + return val; + } +# 523 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void setProximityGain(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + drive = drive << 2; + val &= 0b11110011; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 564 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void setAmbientLightGain(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); + + + drive &= 0b00000011; + val &= 0b11111100; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); + } +# 591 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getLEDBoost(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; + + + val = (val >> 4) & 0b00000011; + + return val; + } +# 615 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void setLEDBoost(uint8_t boost) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; + + boost &= 0b00000011; + boost = boost << 4; + val &= 0b11001111; + val |= boost; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, val) ; + } + + + + + + + uint8_t getProxGainCompEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + val = (val >> 5) & 0b00000001; + + return val; + } + + + + + + + void setProxGainCompEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; + } +# 683 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getProxPhotoMask(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + val &= 0b00001111; + + return val; + } +# 708 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void setProxPhotoMask(uint8_t mask) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; + + + mask &= 0b00001111; + val &= 0b11110000; + val |= mask; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; + } + + + + + + + uint8_t getGestureEnterThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH) ; + + return val; + } + + + + + + + void setGestureEnterThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold) ; + + } + + + + + + + uint8_t getGestureExitThresh(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GEXTH) ; + + return val; + } + + + + + + + void setGestureExitThresh(uint8_t threshold) + { + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold) ; + } +# 786 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getGestureGain(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val = (val >> 5) & 0b00000011; + + return val; + } +# 810 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void setGestureGain(uint8_t gain) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + gain &= 0b00000011; + gain = gain << 5; + val &= 0b10011111; + val |= gain; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } +# 838 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getGestureLEDDrive(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val = (val >> 3) & 0b00000011; + + return val; + } +# 862 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void setGestureLEDDrive(uint8_t drive) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + drive &= 0b00000011; + drive = drive << 3; + val &= 0b11100111; + val |= drive; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } +# 894 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + uint8_t getGestureWaitTime(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + val &= 0b00000111; + + return val; + } +# 922 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void setGestureWaitTime(uint8_t time) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; + + + time &= 0b00000111; + val &= 0b11111000; + val |= time; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; + } + + + + + + + void getLightIntLowThreshold(uint16_t &threshold) + { + uint8_t val_byte; + threshold = 0; + + + val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AILTL) ; + threshold = val_byte; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_byte) ; + threshold = threshold + ((uint16_t)val_byte << 8); + } + + + + + + + + void setLightIntLowThreshold(uint16_t threshold) + { + uint8_t val_low; + uint8_t val_high; + + + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTL, val_low) ; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_high) ; + + } + + + + + + + + void getLightIntHighThreshold(uint16_t &threshold) + { + uint8_t val_byte; + threshold = 0; + + + val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AIHTL); + threshold = val_byte; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_byte) ; + threshold = threshold + ((uint16_t)val_byte << 8); + } + + + + + + + void setLightIntHighThreshold(uint16_t threshold) + { + uint8_t val_low; + uint8_t val_high; + + + val_low = threshold & 0x00FF; + val_high = (threshold & 0xFF00) >> 8; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTL, val_low); + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_high) ; + } + + + + + + + + void getProximityIntLowThreshold(uint8_t &threshold) + { + threshold = 0; + + + threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); + + } + + + + + + + void setProximityIntLowThreshold(uint8_t threshold) + { + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold) ; + } +# 1055 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" + void getProximityIntHighThreshold(uint8_t &threshold) + { + threshold = 0; + + + threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; + + } + + + + + + + void setProximityIntHighThreshold(uint8_t threshold) + { + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold) ; + } + + + + + + + uint8_t getAmbientLightIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + val = (val >> 4) & 0b00000001; + + return val; + } + + + + + + + void setAmbientLightIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); + + + enable &= 0b00000001; + enable = enable << 4; + val &= 0b11101111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; + } + + + + + + + uint8_t getProximityIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + val = (val >> 5) & 0b00000001; + + return val; + } + + + + + + + void setProximityIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + + enable &= 0b00000001; + enable = enable << 5; + val &= 0b11011111; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; + } + + + + + + + uint8_t getGestureIntEnable(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + val = (val >> 1) & 0b00000001; + + return val; + } + + + + + + + void setGestureIntEnable(uint8_t enable) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + enable &= 0b00000001; + enable = enable << 1; + val &= 0b11111101; + val |= enable; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; + } + + + + + + void clearAmbientLightInt(void) + { + uint8_t throwaway; + throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); + } + + + + + + void clearProximityInt(void) + { + uint8_t throwaway; + throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR) ; + + } + + + + + + + uint8_t getGestureMode(void) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + val &= 0b00000001; + + return val; + } + + + + + + + void setGestureMode(uint8_t mode) + { + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; + + + mode &= 0b00000001; + val &= 0b11111110; + val |= mode; + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; + } + + +bool APDS9960_init(void) +{ + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, DEFAULT_WTIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG1, DEFAULT_CONFIG1) ; + + setLEDDrive(DEFAULT_LDRIVE); + + setProximityGain(DEFAULT_PGAIN); + + setAmbientLightGain(DEFAULT_AGAIN); + + setProxIntLowThresh(DEFAULT_PILT) ; + + setProxIntHighThresh(DEFAULT_PIHT); + + setLightIntLowThreshold(DEFAULT_AILT) ; + + setLightIntHighThreshold(DEFAULT_AIHT) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PERS, DEFAULT_PERS) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, DEFAULT_CONFIG2) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3) ; + + + setGestureEnterThresh(DEFAULT_GPENTH); + + setGestureExitThresh(DEFAULT_GEXTH) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF1, DEFAULT_GCONF1) ; + + setGestureGain(DEFAULT_GGAIN) ; + + setGestureLEDDrive(DEFAULT_GLDRIVE) ; + + setGestureWaitTime(DEFAULT_GWTIME) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPULSE, DEFAULT_GPULSE) ; + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3) ; + + setGestureIntEnable(DEFAULT_GIEN); + + disablePower(); + + return true; +} +# 1333 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +uint8_t getMode(void) +{ + uint8_t enable_value; + + + enable_value = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; + + return enable_value; +} + + + + + + + +void setMode(uint8_t mode, uint8_t enable) +{ + uint8_t reg_val; + + + reg_val = getMode(); + + + + enable = enable & 0x01; + if( mode >= 0 && mode <= 6 ) { + if (enable) { + reg_val |= (1 << mode); + } else { + reg_val &= ~(1 << mode); + } + } else if( mode == ALL ) { + if (enable) { + reg_val = 0x7F; + } else { + reg_val = 0x00; + } + } + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, reg_val) ; +} + + + + + + +void enableLightSensor(void) +{ + + setAmbientLightGain(DEFAULT_AGAIN); + setAmbientLightIntEnable(0); + enablePower() ; + setMode(AMBIENT_LIGHT, 1) ; +} + + + + + +void disableLightSensor(void) +{ + setAmbientLightIntEnable(0) ; + setMode(AMBIENT_LIGHT, 0) ; +} + + + + + + +void enableProximitySensor(void) +{ + + setProximityGain(DEFAULT_PGAIN); + setLEDDrive(DEFAULT_LDRIVE) ; + setProximityIntEnable(0) ; + enablePower(); + setMode(PROXIMITY, 1) ; +} + + + + + +void disableProximitySensor(void) +{ + setProximityIntEnable(0) ; + setMode(PROXIMITY, 0) ; +} + + + + + + +void enableGestureSensor(void) +{ + + + + + + + + resetGestureParameters(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ; + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ; + setLEDBoost(LED_BOOST_100); + setGestureIntEnable(0) ; + setGestureMode(1); + enablePower() ; + setMode(WAIT, 1) ; + setMode(PROXIMITY, 1) ; + setMode(GESTURE, 1); +} + + + + + +void disableGestureSensor(void) +{ + resetGestureParameters(); + setGestureIntEnable(0) ; + setGestureMode(0) ; + setMode(GESTURE, 0) ; +} + + + + + + +bool isGestureAvailable(void) +{ + uint8_t val; + + + val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS) ; + + + val &= APDS9960_GVALID; + + + if( val == 1) { + return true; + } else { + return false; + } +} + + + + + + +int16_t readGesture(void) +{ + uint8_t fifo_level = 0; + uint8_t bytes_read = 0; + uint8_t fifo_data[128]; + uint8_t gstatus; + uint16_t motion; + uint16_t i; + uint8_t gesture_loop_counter = 0; + + + if( !isGestureAvailable() || !(getMode() & 0b01000001) ) { + return DIR_NONE; + } + + + while(1) { + if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ + disableGestureSensor(); + APDS9960_overload = true; + AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); + } + gesture_loop_counter += 1; + + delay(FIFO_PAUSE_TIME); + + + gstatus = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); + + + if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { + + + fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ; + + + if( fifo_level > 0) { + bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, + (uint8_t*)fifo_data, + (fifo_level * 4) ); + if( bytes_read == -1 ) { + return ERROR; + } + + + if( bytes_read >= 4 ) { + for( i = 0; i < bytes_read; i += 4 ) { + gesture_data_.u_data[gesture_data_.index] = \ + fifo_data[i + 0]; + gesture_data_.d_data[gesture_data_.index] = \ + fifo_data[i + 1]; + gesture_data_.l_data[gesture_data_.index] = \ + fifo_data[i + 2]; + gesture_data_.r_data[gesture_data_.index] = \ + fifo_data[i + 3]; + gesture_data_.index++; + gesture_data_.total_gestures++; + } + + if( processGestureData() ) { + if( decodeGesture() ) { + + } + } + + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; + } + } + } else { + + + delay(FIFO_PAUSE_TIME); + decodeGesture(); + motion = gesture_motion_; + resetGestureParameters(); + return motion; + } + } +} + + + + + +void enablePower(void) +{ + setMode(POWER, 1) ; +} + + + + + +void disablePower(void) +{ + setMode(POWER, 0) ; +} +# 1600 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +void readAllColorAndProximityData(void) +{ + if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) + { + + + } +} +# 1616 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +void resetGestureParameters(void) +{ + gesture_data_.index = 0; + gesture_data_.total_gestures = 0; + + gesture_ud_delta_ = 0; + gesture_lr_delta_ = 0; + + gesture_ud_count_ = 0; + gesture_lr_count_ = 0; + + gesture_state_ = 0; + gesture_motion_ = DIR_NONE; +} + + + + + + +bool processGestureData(void) +{ + uint8_t u_first = 0; + uint8_t d_first = 0; + uint8_t l_first = 0; + uint8_t r_first = 0; + uint8_t u_last = 0; + uint8_t d_last = 0; + uint8_t l_last = 0; + uint8_t r_last = 0; + uint16_t ud_ratio_first; + uint16_t lr_ratio_first; + uint16_t ud_ratio_last; + uint16_t lr_ratio_last; + uint16_t ud_delta; + uint16_t lr_delta; + uint16_t i; + + + if( gesture_data_.total_gestures <= 4 ) { + return false; + } + + + if( (gesture_data_.total_gestures <= 32) && \ + (gesture_data_.total_gestures > 0) ) { + + + for( i = 0; i < gesture_data_.total_gestures; i++ ) { + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_first = gesture_data_.u_data[i]; + d_first = gesture_data_.d_data[i]; + l_first = gesture_data_.l_data[i]; + r_first = gesture_data_.r_data[i]; + break; + } + } + + + if( (u_first == 0) || (d_first == 0) || \ + (l_first == 0) || (r_first == 0) ) { + + return false; + } + + for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { + + if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && + (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { + + u_last = gesture_data_.u_data[i]; + d_last = gesture_data_.d_data[i]; + l_last = gesture_data_.l_data[i]; + r_last = gesture_data_.r_data[i]; + break; + } + } + } + + + ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); + lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); + ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); + lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); + + + ud_delta = ud_ratio_last - ud_ratio_first; + lr_delta = lr_ratio_last - lr_ratio_first; + + + gesture_ud_delta_ += ud_delta; + gesture_lr_delta_ += lr_delta; + + + if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = 1; + } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_ud_count_ = -1; + } else { + gesture_ud_count_ = 0; + } + + + if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = 1; + } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { + gesture_lr_count_ = -1; + } else { + gesture_lr_count_ = 0; + } + return false; +} + + + + + + +bool decodeGesture(void) +{ + + + if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_UP; + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { + gesture_motion_ = DIR_DOWN; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { + gesture_motion_ = DIR_RIGHT; + } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { + gesture_motion_ = DIR_LEFT; + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_UP; + } else { + gesture_motion_ = DIR_LEFT; + } + } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { + if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { + gesture_motion_ = DIR_DOWN; + } else { + gesture_motion_ = DIR_RIGHT; + } + } else { + return false; + } + + return true; +} + +void handleGesture(void) { + if (isGestureAvailable() ) { + switch (readGesture()) { + case DIR_UP: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("UP")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Up")); + break; + case DIR_DOWN: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("DOWN")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Down")); + break; + case DIR_LEFT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LEFT")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); + break; + case DIR_RIGHT: + AddLog_P(LOG_LEVEL_DEBUG, PSTR("RIGHT")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); + break; + default: + if(APDS9960_overload) + { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); + } + else{ + AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); + snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); + } + } + MqttPublishSensor(); + } +} + +void APDS9960_adjustATime(void) +{ + + I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); + + + if (color_data.a < (uint16_t)20){ + APDS9960_aTime = 0x40; + } + else if (color_data.a < (uint16_t)40){ + APDS9960_aTime = 0x80; + } + else if (color_data.a < (uint16_t)50){ + APDS9960_aTime = DEFAULT_ATIME; + } + else if (color_data.a < (uint16_t)70){ + APDS9960_aTime = 0xc0; + } + if (color_data.a < 200){ + APDS9960_aTime = 0xe9; + } + + + + else{ + APDS9960_aTime = 0xff; + } + + + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime); + enablePower(); + enableLightSensor(); + delay(20); +} + + +void APDS9960_loop(void) +{ + if (recovery_loop_counter > 0){ + recovery_loop_counter -= 1; + } + if (recovery_loop_counter == 1 && APDS9960_overload){ + enableGestureSensor(); + APDS9960_overload = false; + Response_P(PSTR("{\"Gesture\":\"On\"}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + gesture_mode = 1; + } + + if (gesture_mode) { + if (recovery_loop_counter == 0){ + handleGesture(); + + if (APDS9960_overload) + { + disableGestureSensor(); + recovery_loop_counter = APDS9960_LONG_RECOVERY; + Response_P(PSTR("{\"Gesture\":\"Off\"}")); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); + gesture_mode = 0; + } + } + } +} + +void APDS9960_detect(void) +{ + if (APDS9960type || I2cActive(APDS9960_I2C_ADDR)) { return; } + + APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); + if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2) { + if (APDS9960_init()) { + I2cSetActiveFound(APDS9960_I2C_ADDR, APDS9960stype); + + enableProximitySensor(); + enableGestureSensor(); + } else { + APDS9960type = 0; + } + } else { + APDS9960type = 0; + } + currentGesture[0] = '\0'; +} + + + + + +void APDS9960_show(bool json) +{ + if (!APDS9960type) { return; } + + if (!gesture_mode && !APDS9960_overload) { + char red_chr[10]; + char green_chr[10]; + char blue_chr[10]; + char ambient_chr[10]; + char cct_chr[10]; + char prox_chr[10]; + + readAllColorAndProximityData(); + + sprintf (ambient_chr, "%u", color_data.a/4); + sprintf (red_chr, "%u", color_data.r); + sprintf (green_chr, "%u", color_data.g); + sprintf (blue_chr, "%u", color_data.b ); + sprintf (prox_chr, "%u", color_data.p ); + + + + + + calculateColorTemperature(); + sprintf (cct_chr, "%u", color_data.cct); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), + APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); +#endif + } + } + else { + if (json && (currentGesture[0] != '\0' )) { + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); + currentGesture[0] = '\0'; + } + } +} +# 1961 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" +bool APDS9960CommandSensor(void) +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + disableGestureSensor(); + gesture_mode = 0; + enableLightSensor(); + APDS9960_overload = false; + break; + case 1: + if (APDS9960type) { + setGestureGain(DEFAULT_GGAIN); + setProximityGain(DEFAULT_PGAIN); + disableLightSensor(); + enableGestureSensor(); + gesture_mode = 1; + } + break; + case 2: + if (APDS9960type) { + setGestureGain(GGAIN_2X); + setProximityGain(PGAIN_2X); + disableLightSensor(); + enableGestureSensor(); + gesture_mode = 1; + } + break; + default: + int temp_aTime = (uint8_t)XdrvMailbox.payload; + if (temp_aTime > 2 && temp_aTime < 256){ + disablePower(); + I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, temp_aTime); + enablePower(); + enableLightSensor(); + } + break; + } + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); + + return serviced; +} + + + + + +bool Xsns27(uint8_t function) +{ + if (!I2cEnabled(XI2C_21)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + APDS9960_detect(); + } + else if (APDS9960type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + APDS9960_loop(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_27 == XdrvMailbox.index) { + result = APDS9960CommandSensor(); + } + break; + case FUNC_JSON_APPEND: + APDS9960_show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + APDS9960_show(0); + break; +#endif + } + } + return result; +} +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_28_tm1638.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_28_tm1638.ino" +#ifdef USE_TM1638 + + + + + + +#define XSNS_28 28 + +#define TM1638_COLOR_NONE 0 +#define TM1638_COLOR_RED 1 +#define TM1638_COLOR_GREEN 2 + +#define TM1638_CLOCK_DELAY 1 + +uint8_t tm1638_type = 1; +uint8_t tm1638_clock_pin = 0; +uint8_t tm1638_data_pin = 0; +uint8_t tm1638_strobe_pin = 0; +uint8_t tm1638_displays = 8; +uint8_t tm1638_active_display = 1; +uint8_t tm1638_intensity = 0; +uint8_t tm1638_state = 0; + + + + + + +void Tm16XXSend(uint8_t data) +{ + for (uint32_t i = 0; i < 8; i++) { + digitalWrite(tm1638_data_pin, !!(data & (1 << i))); + digitalWrite(tm1638_clock_pin, LOW); + delayMicroseconds(TM1638_CLOCK_DELAY); + digitalWrite(tm1638_clock_pin, HIGH); + } +} + +void Tm16XXSendCommand(uint8_t cmd) +{ + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(cmd); + digitalWrite(tm1638_strobe_pin, HIGH); +} + +void TM16XXSendData(uint8_t address, uint8_t data) +{ + Tm16XXSendCommand(0x44); + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0xC0 | address); + Tm16XXSend(data); + digitalWrite(tm1638_strobe_pin, HIGH); +} + +uint8_t Tm16XXReceive(void) +{ + uint8_t temp = 0; + + + pinMode(tm1638_data_pin, INPUT); + digitalWrite(tm1638_data_pin, HIGH); + + for (uint32_t i = 0; i < 8; ++i) { + digitalWrite(tm1638_clock_pin, LOW); + delayMicroseconds(TM1638_CLOCK_DELAY); + temp |= digitalRead(tm1638_data_pin) << i; + digitalWrite(tm1638_clock_pin, HIGH); + } + + + pinMode(tm1638_data_pin, OUTPUT); + digitalWrite(tm1638_data_pin, LOW); + + return temp; +} + + + +void Tm16XXClearDisplay(void) +{ + for (uint32_t i = 0; i < tm1638_displays; i++) { + TM16XXSendData(i << 1, 0); + } +} + +void Tm1638SetLED(uint8_t color, uint8_t pos) +{ + TM16XXSendData((pos << 1) + 1, color); +} + +void Tm1638SetLEDs(word leds) +{ + for (uint32_t i = 0; i < tm1638_displays; i++) { + uint8_t color = 0; + + if ((leds & (1 << i)) != 0) { + color |= TM1638_COLOR_RED; + } + + if ((leds & (1 << (i + 8))) != 0) { + color |= TM1638_COLOR_GREEN; + } + + Tm1638SetLED(color, i); + } +} + +uint8_t Tm1638GetButtons(void) +{ + uint8_t keys = 0; + + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0x42); + for (uint32_t i = 0; i < 4; i++) { + keys |= Tm16XXReceive() << i; + } + digitalWrite(tm1638_strobe_pin, HIGH); + + return keys; +} + + + +void TmInit(void) +{ + tm1638_type = 0; + if ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99)) { + tm1638_clock_pin = pin[GPIO_TM16CLK]; + tm1638_data_pin = pin[GPIO_TM16DIO]; + tm1638_strobe_pin = pin[GPIO_TM16STB]; + + pinMode(tm1638_data_pin, OUTPUT); + pinMode(tm1638_clock_pin, OUTPUT); + pinMode(tm1638_strobe_pin, OUTPUT); + + digitalWrite(tm1638_strobe_pin, HIGH); + digitalWrite(tm1638_clock_pin, HIGH); + + Tm16XXSendCommand(0x40); + Tm16XXSendCommand(0x80 | (tm1638_active_display ? 8 : 0) | tmin(7, tm1638_intensity)); + + digitalWrite(tm1638_strobe_pin, LOW); + Tm16XXSend(0xC0); + for (uint32_t i = 0; i < 16; i++) { + Tm16XXSend(0x00); + } + digitalWrite(tm1638_strobe_pin, HIGH); + + tm1638_type = 1; + tm1638_state = 1; + } +} + +void TmLoop(void) +{ + if (tm1638_state) { + uint8_t buttons = Tm1638GetButtons(); + for (uint32_t i = 0; i < MAX_SWITCHES; i++) { + SwitchSetVirtual(i, (buttons &1) ^1); + uint8_t color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; + Tm1638SetLED(color, i); + buttons >>= 1; + } + SwitchHandler(1); + } +} +# 201 "S:/Development/Tasmota/tasmota/xsns_28_tm1638.ino" +bool Xsns28(uint8_t function) +{ + bool result = false; + + if (tm1638_type) { + switch (function) { + case FUNC_INIT: + TmInit(); + break; + case FUNC_EVERY_50_MSECOND: + TmLoop(); + break; +# 223 "S:/Development/Tasmota/tasmota/xsns_28_tm1638.ino" + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_29_mcp230xx.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_29_mcp230xx.ino" +#ifdef USE_I2C +#ifdef USE_MCP230xx +# 31 "S:/Development/Tasmota/tasmota/xsns_29_mcp230xx.ino" +#define XSNS_29 29 +#define XI2C_22 22 + + + + + +uint8_t MCP230xx_IODIR = 0x00; +uint8_t MCP230xx_GPINTEN = 0x02; +uint8_t MCP230xx_IOCON = 0x05; +uint8_t MCP230xx_GPPU = 0x06; +uint8_t MCP230xx_INTF = 0x07; +uint8_t MCP230xx_INTCAP = 0x08; +uint8_t MCP230xx_GPIO = 0x09; + +uint8_t mcp230xx_type = 0; +uint8_t mcp230xx_pincount = 0; +uint8_t mcp230xx_int_en = 0; +uint8_t mcp230xx_int_prio_counter = 0; +uint8_t mcp230xx_int_counter_en = 0; +uint8_t mcp230xx_int_retainer_en = 0; +uint8_t mcp230xx_int_sec_counter = 0; + +uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +uint8_t mcp230xx_int_retainer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +unsigned long int_millis[16]; + +const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL_UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; + +const char MCP230XX_INTCFG_RESPONSE[] PROGMEM = "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + +#ifdef USE_MCP230xx_OUTPUT +const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; +#endif + +void MCP230xx_CheckForIntCounter(void) { + uint8_t en = 0; + for (uint32_t ca=0;ca<16;ca++) { + if (Settings.mcp230xx_config[ca].int_count_en) { + en=1; + } + } + if (!Settings.mcp230xx_int_timer) en=0; + mcp230xx_int_counter_en=en; + if (!mcp230xx_int_counter_en) { + for (uint32_t ca=0;ca<16;ca++) { + mcp230xx_int_counter[ca] = 0; + } + } +} + +void MCP230xx_CheckForIntRetainer(void) { + uint8_t en = 0; + for (uint32_t ca=0;ca<16;ca++) { + if (Settings.mcp230xx_config[ca].int_retain_flag) { + en=1; + } + } + mcp230xx_int_retainer_en=en; + if (!mcp230xx_int_retainer_en) { + for (uint32_t ca=0;ca<16;ca++) { + mcp230xx_int_retainer[ca] = 0; + } + } +} + +const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { +#ifdef USE_MCP230xx_OUTPUT +if ((6 == pinmod) && (statu < 2)) { statu = abs(statu-1); } +#endif + switch (statu) { + case 0: + return "OFF"; + break; + case 1: + return "ON"; + break; +#ifdef USE_MCP230xx_OUTPUT + case 2: + return "TOGGLE"; + break; +#endif + } + return ""; +} + +const char* IntModeTxt(uint8_t intmo) { + switch (intmo) { + case 0: + return "ALL"; + break; + case 1: + return "EVENT"; + break; + case 2: + return "TELE"; + break; + case 3: + return "DISABLED"; + break; + } + return ""; +} + +uint8_t MCP230xx_readGPIO(uint8_t port) { + return I2cRead8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port); +} + +void MCP230xx_ApplySettings(void) +{ + uint8_t int_en = 0; + for (uint32_t mcp230xx_port = 0; mcp230xx_port < mcp230xx_type; mcp230xx_port++) { + uint8_t reg_gppu = 0; + uint8_t reg_gpinten = 0; + uint8_t reg_iodir = 0xFF; +#ifdef USE_MCP230xx_OUTPUT + uint8_t reg_portpins = 0x00; +#endif + for (uint32_t idx = 0; idx < 8; idx++) { + switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { + case 0 ... 1: + reg_iodir |= (1 << idx); + break; + case 2 ... 4: + reg_iodir |= (1 << idx); + reg_gpinten |= (1 << idx); + int_en = 1; + break; +#ifdef USE_MCP230xx_OUTPUT + case 5 ... 6: + reg_iodir &= ~(1 << idx); + if (Settings.flag.save_state) { + reg_portpins |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); + } else { + if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { + reg_portpins |= (1 << idx); + } + } + break; +#endif + default: + break; + } +#ifdef USE_MCP230xx_OUTPUT + if ((Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { + reg_gppu |= (1 << idx); + } +#else + if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { + reg_gppu |= (1 << idx); + } +#endif + } + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPPU+mcp230xx_port, reg_gppu); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IODIR+mcp230xx_port, reg_iodir); +#ifdef USE_MCP230xx_OUTPUT + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); +#endif + } + for (uint32_t idx=0;idx 0) { + if (I2cValidRead8(&mcp230xx_intcap, USE_MCP230xx_ADDR, MCP230xx_INTCAP+mcp230xx_port)) { + for (uint32_t intp = 0; intp < 8; intp++) { + if ((intf >> intp) & 0x01) { + report_int = 0; + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode > 1) { + switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode) { + case 2: + report_int = 1; + break; + case 3: + if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; + break; + case 4: + if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; + break; + default: + break; + } + + if ((mcp230xx_int_counter_en) && (report_int)) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { + mcp230xx_int_counter[intp+(mcp230xx_port*8)]++; + } + } + + if (report_int) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { + mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]++; + if (mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)] >= Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { + mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]=0; + } else { + report_int = 0; + } + } + } + + if (report_int) { + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_retain_flag) { + mcp230xx_int_retainer[intp+(mcp230xx_port*8)] = 1; + report_int = 0; + } + } + if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { + report_int = 0; + } + if (report_int) { + bool int_tele = false; + bool int_event = false; + unsigned long millis_now = millis(); + unsigned long millis_since_last_int = millis_now - int_millis[intp+(mcp230xx_port*8)]; + int_millis[intp+(mcp230xx_port*8)]=millis_now; + switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_mode) { + case 0: + int_tele=true; + int_event=true; + break; + case 1: + int_event=true; + break; + case 2: + int_tele=true; + break; + } + if (int_tele) { + ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), + intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); + } + if (int_event) { + char command[19]; + sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); + ExecuteCommand(command, SRC_RULE); + } + } + } + } + } + } + } + } + } +} + +void MCP230xx_Show(bool json) +{ + if (json) { + uint8_t gpio = MCP230xx_readGPIO(0); + ResponseAppend_P(PSTR(",\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + if (2 == mcp230xx_type) { + gpio = MCP230xx_readGPIO(1); + ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + } + ResponseJsonEnd(); + } +} + +#ifdef USE_MCP230xx_OUTPUT + +void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { + uint8_t portpins; + uint8_t port = 0; + uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; + uint8_t interlock = Settings.flag.interlock; + int pinadd = (pin % 2)+1-(3*(pin % 2)); + char cmnd[7], stt[4]; + if (pin > 7) { port = 1; } + portpins = MCP230xx_readGPIO(port); + if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { + if (pinstate < 2) { + if (6 == pinmo) { + if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins |= (1 << (pin+pinadd-(port*8))),portpins &= ~(1 << (pin-(port*8))); + } else { + if (pinstate) portpins &= ~(1 << (pin+pinadd-(port*8))),portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); + } + } else { + if (6 == pinmo) { + portpins |= (1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); + } else { + portpins &= ~(1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); + } + } + } else { + if (pinstate < 2) { + if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); + } else { + portpins ^= (1 << (pin-(port*8))); + } + } + I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port, portpins); + if (Settings.flag.save_state) { + Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; + Settings.mcp230xx_config[pin+pinadd].saved_state=portpins>>(pin+pinadd-(port*8))&1; + } + sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); + sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); + if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { + char stt1[4]; + sprintf(stt1,ConvertNumTxt((portpins >> (pin+pinadd-(port*8))&1), pinmo)); + Response_P(PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); + } else { + Response_P(MCP230XX_CMND_RESPONSE, pin, cmnd, stt); + } +} + +#endif + +void MCP230xx_Reset(uint8_t pinmode) { + uint8_t pullup = 0; + if ((pinmode > 1) && (pinmode < 5)) { pullup=1; } + for (uint32_t pinx=0;pinx<16;pinx++) { + Settings.mcp230xx_config[pinx].pinmode=pinmode; + Settings.mcp230xx_config[pinx].pullup=pullup; + Settings.mcp230xx_config[pinx].saved_state=0; + if ((pinmode > 1) && (pinmode < 5)) { + Settings.mcp230xx_config[pinx].int_report_mode=0; + } else { + Settings.mcp230xx_config[pinx].int_report_mode=3; + } + Settings.mcp230xx_config[pinx].int_report_defer=0; + Settings.mcp230xx_config[pinx].int_count_en=0; + Settings.mcp230xx_config[pinx].int_retain_flag=0; + Settings.mcp230xx_config[pinx].spare13=0; + Settings.mcp230xx_config[pinx].spare14=0; + Settings.mcp230xx_config[pinx].spare15=0; + } + Settings.mcp230xx_int_prio = 0; + Settings.mcp230xx_int_timer = 0; + MCP230xx_ApplySettings(); + char pulluptxt[7]; + char intmodetxt[9]; + sprintf(pulluptxt,ConvertNumTxt(pullup)); + uint8_t intmode = 3; + if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } + sprintf(intmodetxt,IntModeTxt(intmode)); + Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); +} + +bool MCP230xx_Command(void) +{ + bool serviced = true; + bool validpin = false; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((intpri >= 0) && (intpri <= 20)) { + Settings.mcp230xx_int_prio = intpri; + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTTIMER")) { + if (paramcount > 1) { + uint8_t inttim = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if ((inttim >= 0) && (inttim <= 3600)) { + Settings.mcp230xx_int_timer = inttim; + MCP230xx_CheckForIntCounter(); + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTDEF")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t intdef = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((intdef >= 0) && (intdef <= 15)) { + Settings.mcp230xx_config[pin].int_report_defer=intdef; + if (Settings.mcp230xx_config[pin].int_count_en) { + Settings.mcp230xx_config[pin].int_count_en=0; + MCP230xx_CheckForIntCounter(); + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); + } + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTCNT")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t intcnt = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((intcnt >= 0) && (intcnt <= 1)) { + Settings.mcp230xx_config[pin].int_count_en=intcnt; + if (Settings.mcp230xx_config[pin].int_report_defer) { + Settings.mcp230xx_config[pin].int_report_defer=0; + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTDEF for pin D%i"),pin); + } + if (Settings.mcp230xx_config[pin].int_report_mode < 3) { + Settings.mcp230xx_config[pin].int_report_mode=3; + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled immediate interrupt/telemetry reporting for pin D%i"),pin); + } + if ((Settings.mcp230xx_config[pin].int_count_en) && (!Settings.mcp230xx_int_timer)) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); + } + MCP230xx_CheckForIntCounter(); + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTRETAIN")) { + if (paramcount > 1) { + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + if (pin < mcp230xx_pincount) { + if (pin == 0) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; + } else { + validpin = true; + } + } + if (validpin) { + if (paramcount > 2) { + uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + if ((int_retain >= 0) && (int_retain <= 1)) { + Settings.mcp230xx_config[pin].int_retain_flag=int_retain; + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + MCP230xx_CheckForIntRetainer(); + return serviced; + } else { + serviced=false; + return serviced; + } + } else { + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + return serviced; + } + } + serviced = false; + return serviced; + } else { + serviced = false; + return serviced; + } + } + + uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); + + if (pin < mcp230xx_pincount) { + if (0 == pin) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "0")) validpin=true; + } else { + validpin=true; + } + } + if (validpin && (paramcount > 1)) { + if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "?")) { + uint8_t port = 0; + if (pin > 7) { port = 1; } + uint8_t portdata = MCP230xx_readGPIO(port); + char pulluptxtr[7],pinstatustxtr[7]; + char intmodetxt[9]; + sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); + sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); +#ifdef USE_MCP230xx_OUTPUT + uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); +#else + sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); +#endif + return serviced; + } +#ifdef USE_MCP230xx_OUTPUT + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "1"))) { + MCP230xx_SetOutPin(pin,abs(pincmd-1)); + return serviced; + } + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0"))) { + MCP230xx_SetOutPin(pin,pincmd); + return serviced; + } + if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "2"))) { + MCP230xx_SetOutPin(pin,2); + return serviced; + } + } +#endif + uint8_t pinmode = 0; + uint8_t pullup = 0; + uint8_t intmode = 0; + if (paramcount > 1) { + pinmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); + } + if (paramcount > 2) { + pullup = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); + } + if (paramcount > 3) { + intmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); + } +#ifdef USE_MCP230xx_OUTPUT + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2) && (paramcount > 2)) { +#else + if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 2)) { +#endif + Settings.mcp230xx_config[pin].pinmode=pinmode; + Settings.mcp230xx_config[pin].pullup=pullup; + if ((pinmode > 1) && (pinmode < 5)) { + if ((intmode >= 0) && (intmode <= 3)) { + Settings.mcp230xx_config[pin].int_report_mode=intmode; + } + } else { + Settings.mcp230xx_config[pin].int_report_mode=3; + } + MCP230xx_ApplySettings(); + uint8_t port = 0; + if (pin > 7) { port = 1; } + uint8_t portdata = MCP230xx_readGPIO(port); + char pulluptxtc[7], pinstatustxtc[7]; + char intmodetxt[9]; + sprintf(pulluptxtc,ConvertNumTxt(pullup)); + sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); +#ifdef USE_MCP230xx_OUTPUT + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); +#else + sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); +#endif + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); + return serviced; + } + } else { + serviced=false; + return serviced; + } + return serviced; +} + +#ifdef USE_MCP230xx_DISPLAYOUTPUT + +const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; + +void MCP230xx_UpdateWebData(void) +{ + uint8_t gpio1 = MCP230xx_readGPIO(0); + uint8_t gpio2 = 0; + if (2 == mcp230xx_type) { + gpio2 = MCP230xx_readGPIO(1); + } + uint16_t gpio = (gpio2 << 8) + gpio1; + for (uint32_t pin = 0; pin < mcp230xx_pincount; pin++) { + if (Settings.mcp230xx_config[pin].pinmode >= 5) { + char stt[7]; + sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); + WSContentSend_PD(HTTP_SNS_MCP230xx_OUTPUT, pin, stt); + } + } +} + +#endif + +#ifdef USE_MCP230xx_OUTPUT + +void MCP230xx_OutputTelemetry(void) +{ + uint8_t outputcount = 0; + uint16_t gpiototal = 0; + uint8_t gpioa = 0; + uint8_t gpiob = 0; + gpioa=MCP230xx_readGPIO(0); + if (2 == mcp230xx_type) { gpiob=MCP230xx_readGPIO(1); } + gpiototal=((uint16_t)gpiob << 8) | gpioa; + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; + } + if (outputcount) { + char stt[7]; + ResponseTime_P(PSTR(",\"MCP230_OUT\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].pinmode >= 5) { + sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); + ResponseAppend_P(PSTR("\"OUT_D%i\":\"%s\","),pinx,stt); + } + } + ResponseAppend_P(PSTR("\"END\":1}}")); + MqttPublishTeleSensor(); + } +} + +#endif + +void MCP230xx_Interrupt_Counter_Report(void) { + ResponseTime_P(PSTR(",\"MCP230_INTTIMER\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].int_count_en) { + ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); + mcp230xx_int_counter[pinx]=0; + } + } + ResponseAppend_P(PSTR("\"END\":1}}")); + MqttPublishTeleSensor(); + mcp230xx_int_sec_counter = 0; +} + +void MCP230xx_Interrupt_Retain_Report(void) { + uint16_t retainresult = 0; + ResponseTime_P(PSTR(",\"MCP_INTRETAIN\":{")); + for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { + if (Settings.mcp230xx_config[pinx].int_retain_flag) { + ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); + retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); + mcp230xx_int_retainer[pinx]=0; + } + } + ResponseAppend_P(PSTR("\"Value\":%u}}"),retainresult); + MqttPublishTeleSensor(); +} + + + + + +bool Xsns29(uint8_t function) +{ + if (!I2cEnabled(XI2C_22)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MCP230xx_Detect(); + } + else if (mcp230xx_type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + if (mcp230xx_int_en) { + mcp230xx_int_prio_counter++; + if ((mcp230xx_int_prio_counter) >= (Settings.mcp230xx_int_prio)) { + MCP230xx_CheckForInterrupt(); + mcp230xx_int_prio_counter=0; + } + } + break; + case FUNC_EVERY_SECOND: + if (mcp230xx_int_counter_en) { + mcp230xx_int_sec_counter++; + if (mcp230xx_int_sec_counter >= Settings.mcp230xx_int_timer) { + MCP230xx_Interrupt_Counter_Report(); + } + } + if (tele_period == 0) { + if (mcp230xx_int_retainer_en) { + MCP230xx_Interrupt_Retain_Report(); + } +#ifdef USE_MCP230xx_OUTPUT + MCP230xx_OutputTelemetry(); +#endif + } + break; + case FUNC_JSON_APPEND: + MCP230xx_Show(1); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_29 == XdrvMailbox.index) { + result = MCP230xx_Command(); + } + break; +#ifdef USE_WEBSERVER +#ifdef USE_MCP230xx_OUTPUT +#ifdef USE_MCP230xx_DISPLAYOUTPUT + case FUNC_WEB_SENSOR: + MCP230xx_UpdateWebData(); + break; +#endif +#endif +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" +# 46 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" +#ifdef USE_I2C +#ifdef USE_MPR121 + + + + + +#define XSNS_30 30 +#define XI2C_23 23 + + + + + + + +#define MPR121_ELEX_REG 0x00 + + +#define MPR121_MHDR_REG 0x2B + + +#define MPR121_MHDR_VAL 0x01 + + +#define MPR121_NHDR_REG 0x2C + + +#define MPR121_NHDR_VAL 0x01 + + +#define MPR121_NCLR_REG 0x2D + + +#define MPR121_NCLR_VAL 0x0E + + +#define MPR121_MHDF_REG 0x2F + + +#define MPR121_MHDF_VAL 0x01 + + +#define MPR121_NHDF_REG 0x30 + + +#define MPR121_NHDF_VAL 0x05 + + +#define MPR121_NCLF_REG 0x31 + + +#define MPR121_NCLF_VAL 0x01 + + +#define MPR121_MHDPROXR_REG 0x36 + + +#define MPR121_MHDPROXR_VAL 0x3F + + +#define MPR121_NHDPROXR_REG 0x37 + + +#define MPR121_NHDPROXR_VAL 0x5F + + +#define MPR121_NCLPROXR_REG 0x38 + + +#define MPR121_NCLPROXR_VAL 0x04 + + +#define MPR121_FDLPROXR_REG 0x39 + + +#define MPR121_FDLPROXR_VAL 0x00 + + +#define MPR121_MHDPROXF_REG 0x3A + + +#define MPR121_MHDPROXF_VAL 0x01 + + +#define MPR121_NHDPROXF_REG 0x3B + + +#define MPR121_NHDPROXF_VAL 0x01 + + +#define MPR121_NCLPROXF_REG 0x3C + + +#define MPR121_NCLPROXF_VAL 0x1F + + +#define MPR121_FDLPROXF_REG 0x3D + + +#define MPR121_FDLPROXF_VAL 0x04 + + +#define MPR121_E0TTH_REG 0x41 + + +#define MPR121_E0TTH_VAL 12 + + +#define MPR121_E0RTH_REG 0x42 + + +#define MPR121_E0RTH_VAL 6 + + +#define MPR121_CDT_REG 0x5D + + +#define MPR121_CDT_VAL 0x20 + + +#define MPR121_ECR_REG 0x5E + + +#define MPR121_ECR_VAL 0x8F + + + +#define MPR121_SRST_REG 0x80 + + +#define MPR121_SRST_VAL 0x63 + + +#define BITC(sensor,position) ((pS->current[sensor] >> position) & 1) + + +#define BITP(sensor,position) ((pS->previous[sensor] >> position) & 1) +# 195 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" +typedef struct mpr121 mpr121; +struct mpr121 { + const uint8_t i2c_addr[4] = { 0x5A, 0x5B, 0x5C, 0x5D }; + const char id[4] = { 'A', 'B', 'C', 'D' }; + bool connected[4] = { false, false, false, false }; + bool running[4] = { false, false, false, false }; + uint16_t current[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; + uint16_t previous[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; +}; + +bool mpr21_found = false; +# 217 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" +void Mpr121Init(struct mpr121 *pS, bool initial) +{ + + for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { + + if (initial && I2cActive(pS->i2c_addr[i])) { continue; } + + + pS->connected[i] = (I2cWrite8(pS->i2c_addr[i], MPR121_SRST_REG, MPR121_SRST_VAL) + && (0x24 == I2cRead8(pS->i2c_addr[i], 0x5D))); + if (pS->connected[i]) { + + + mpr21_found = true; + char device_name[16]; + snprintf_P(device_name, sizeof(device_name), PSTR("MPR121(%c)"), pS->id[i]); + I2cSetActiveFound(pS->i2c_addr[i], device_name); + + + for (uint32_t j = 0; j < 13; j++) { + + + I2cWrite8(pS->i2c_addr[i], MPR121_E0TTH_REG + 2 * j, MPR121_E0TTH_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_E0RTH_REG + 2 * j, MPR121_E0RTH_VAL); + } + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDR_REG, MPR121_MHDR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDR_REG, MPR121_NHDR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLR_REG, MPR121_NCLR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDF_REG, MPR121_MHDF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDF_REG, MPR121_NHDF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLF_REG, MPR121_NCLF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXR_REG, MPR121_MHDPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXR_REG, MPR121_NHDPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXR_REG, MPR121_NCLPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXR_REG, MPR121_FDLPROXR_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXF_REG, MPR121_MHDPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXF_REG, MPR121_NHDPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXF_REG, MPR121_NCLPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXF_REG, MPR121_FDLPROXF_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_CDT_REG, MPR121_CDT_VAL); + + + I2cWrite8(pS->i2c_addr[i], MPR121_ECR_REG, MPR121_ECR_VAL); + + + pS->running[i] = (0x00 != I2cRead8(pS->i2c_addr[i], MPR121_ECR_REG)); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121%c: %sRunning"), pS->id[i], (pS->running[i]) ? "" : "NOT"); + + } else { + + + pS->running[i] = false; + } + } + + + if (!(pS->connected[0] || pS->connected[1] || pS->connected[2] + || pS->connected[3])) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C "MPR121: No sensors found")); + } +} +# 326 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" +void Mpr121Show(struct mpr121 *pS, uint8_t function) +{ + + + for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { + + + if (pS->connected[i]) { + + + if (!I2cValidRead16LE(&pS->current[i], pS->i2c_addr[i], MPR121_ELEX_REG)) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]); + Mpr121Init(pS, false); + return; + } + + if (BITC(i, 15)) { + + + I2cWrite8(pS->i2c_addr[i], MPR121_ELEX_REG, 0x00); + AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]); + Mpr121Init(pS, false); + return; + } + } + + if (pS->running[i]) { + + + if (FUNC_JSON_APPEND == function) { + ResponseAppend_P(PSTR(",\"MPR121%c\":{"), pS->id[i]); + } + + for (uint32_t j = 0; j < 13; j++) { + + + if ((FUNC_EVERY_50_MSECOND == function) + && (BITC(i, j) != BITP(i, j))) { + Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); + MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); + } + +#ifdef USE_WEBSERVER + if (FUNC_WEB_SENSOR == function) { + WSContentSend_PD(PSTR("{s}MPR121%c Button%d{m}%d{e}"), pS->id[i], j, BITC(i, j)); + } +#endif + + + if (FUNC_JSON_APPEND == function) { + ResponseAppend_P(PSTR("%s\"Button%i\":%i"), (j > 0 ? "," : ""), j, BITC(i, j)); + } + } + + + pS->previous[i] = pS->current[i]; + + + if (FUNC_JSON_APPEND == function) { + ResponseJsonEnd(); + } + } + } +} +# 410 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" +bool Xsns30(uint8_t function) +{ + if (!I2cEnabled(XI2C_23)) { return false; } + + bool result = false; + + + static struct mpr121 mpr121; + + if (FUNC_INIT == function) { + + Mpr121Init(&mpr121, true); + } + else if (mpr21_found) { + + switch (function) { + + + case FUNC_EVERY_50_MSECOND: + Mpr121Show(&mpr121, FUNC_EVERY_50_MSECOND); + break; + + + case FUNC_JSON_APPEND: + Mpr121Show(&mpr121, FUNC_JSON_APPEND); + break; + +#ifdef USE_WEBSERVER + + case FUNC_WEB_SENSOR: + Mpr121Show(&mpr121, FUNC_WEB_SENSOR); + break; +#endif + } + } + + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_31_ccs811.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_31_ccs811.ino" +#ifdef USE_I2C +#ifdef USE_CCS811 +# 30 "S:/Development/Tasmota/tasmota/xsns_31_ccs811.ino" +#define XSNS_31 31 +#define XI2C_24 24 + +#define EVERYNSECONDS 5 + +#include "Adafruit_CCS811.h" + +Adafruit_CCS811 ccs; +uint8_t CCS811_ready = 0; +uint8_t CCS811_type = 0;; +uint16_t eCO2; +uint16_t TVOC; +uint8_t tcnt = 0; +uint8_t ecnt = 0; + + + +void CCS811Detect(void) +{ + if (I2cActive(CCS811_ADDRESS)) { return; } + + if (!ccs.begin(CCS811_ADDRESS)) { + CCS811_type = 1; + I2cSetActiveFound(CCS811_ADDRESS, "CCS811"); + } +} + +void CCS811Update(void) +{ + tcnt++; + if (tcnt >= EVERYNSECONDS) { + tcnt = 0; + CCS811_ready = 0; + if (ccs.available()) { + if (!ccs.readData()){ + TVOC = ccs.getTVOC(); + eCO2 = ccs.geteCO2(); + CCS811_ready = 1; + if (global_update && global_humidity>0 && global_temperature!=9999) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); } + ecnt = 0; + } + } else { + + ecnt++; + if (ecnt > 6) { + + ccs.begin(CCS811_ADDRESS); + } + } + } +} + +const char HTTP_SNS_CCS811[] PROGMEM = + "{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" + "{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; + +void CCS811Show(bool json) +{ + if (CCS811_ready) { + if (json) { + ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CCS811, eCO2, TVOC); +#endif + } + } +} + + + + + +bool Xsns31(uint8_t function) +{ + if (!I2cEnabled(XI2C_24)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + CCS811Detect(); + } + else if (CCS811_type) { + switch (function) { + case FUNC_EVERY_SECOND: + CCS811Update(); + break; + case FUNC_JSON_APPEND: + CCS811Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + CCS811Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_32_mpu6050.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_32_mpu6050.ino" +#ifdef USE_I2C +#ifdef USE_MPU6050 +# 30 "S:/Development/Tasmota/tasmota/xsns_32_mpu6050.ino" +#define XSNS_32 32 +#define XI2C_25 25 + +#define D_SENSOR_MPU6050 "MPU6050" + +#define MPU_6050_ADDR_AD0_LOW 0x68 +#define MPU_6050_ADDR_AD0_HIGH 0x69 + +uint8_t MPU_6050_address; +uint8_t MPU_6050_addresses[] = { MPU_6050_ADDR_AD0_LOW, MPU_6050_ADDR_AD0_HIGH }; +uint8_t MPU_6050_found; + +int16_t MPU_6050_ax = 0, MPU_6050_ay = 0, MPU_6050_az = 0; +int16_t MPU_6050_gx = 0, MPU_6050_gy = 0, MPU_6050_gz = 0; +int16_t MPU_6050_temperature = 0; + +#ifdef USE_MPU6050_DMP + #include "MPU6050_6Axis_MotionApps20.h" + #include "I2Cdev.h" + #include + typedef struct MPU6050_DMP{ + uint8_t devStatus; + uint16_t packetSize; + uint16_t fifoCount; + uint8_t fifoBuffer[64]; + Quaternion q; + VectorInt16 aa; + VectorInt16 aaReal; + VectorFloat gravity; + float euler[3]; + float yawPitchRoll[3]; + } MPU6050_DMP; + + MPU6050_DMP MPU6050_dmp; +#else + #include +#endif +MPU6050 mpu6050; + +void MPU_6050PerformReading(void) +{ +#ifdef USE_MPU6050_DMP + mpu6050.resetFIFO(); + MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); + while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); + mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); + MPU6050_dmp.fifoCount -= MPU6050_dmp.packetSize; + + mpu6050.dmpGetQuaternion(&MPU6050_dmp.q, MPU6050_dmp.fifoBuffer); + mpu6050.dmpGetEuler(MPU6050_dmp.euler, &MPU6050_dmp.q); + mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); + mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); + mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); + mpu6050.dmpGetYawPitchRoll(MPU6050_dmp.yawPitchRoll, &MPU6050_dmp.q, &MPU6050_dmp.gravity); + MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; + MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; + MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; + MPU_6050_ax = MPU6050_dmp.aaReal.x; + MPU_6050_ay = MPU6050_dmp.aaReal.y; + MPU_6050_az = MPU6050_dmp.aaReal.z; +#else + mpu6050.getMotion6( + &MPU_6050_ax, + &MPU_6050_ay, + &MPU_6050_az, + &MPU_6050_gx, + &MPU_6050_gy, + &MPU_6050_gz + ); +#endif + MPU_6050_temperature = mpu6050.getTemperature(); +} +# 119 "S:/Development/Tasmota/tasmota/xsns_32_mpu6050.ino" +void MPU_6050Detect(void) +{ + for (uint32_t i = 0; i < sizeof(MPU_6050_addresses); i++) + { + MPU_6050_address = MPU_6050_addresses[i]; + if (!I2cSetDevice(MPU_6050_address)) { break; } + mpu6050.setAddr(MPU_6050_addresses[i]); + +#ifdef USE_MPU6050_DMP + MPU6050_dmp.devStatus = mpu6050.dmpInitialize(); + mpu6050.setXGyroOffset(220); + mpu6050.setYGyroOffset(76); + mpu6050.setZGyroOffset(-85); + mpu6050.setZAccelOffset(1788); + if (MPU6050_dmp.devStatus == 0) { + mpu6050.setDMPEnabled(true); + MPU6050_dmp.packetSize = mpu6050.dmpGetFIFOPacketSize(); + MPU_6050_found = true; + } +#else + mpu6050.initialize(); + MPU_6050_found = mpu6050.testConnection(); +#endif + Settings.flag2.axis_resolution = 2; + } + + if (MPU_6050_found) { + I2cSetActiveFound(MPU_6050_address, D_SENSOR_MPU6050); + } +} + +#define D_YAW "Yaw" +#define D_PITCH "Pitch" +#define D_ROLL "Roll" + +#ifdef USE_WEBSERVER +const char HTTP_SNS_AXIS[] PROGMEM = + "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_AY_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; +#ifdef USE_MPU6050_DMP +const char HTTP_SNS_YPR[] PROGMEM = + "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" + "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}"; +#endif +#endif + +#define D_JSON_AXIS_AX "AccelXAxis" +#define D_JSON_AXIS_AY "AccelYAxis" +#define D_JSON_AXIS_AZ "AccelZAxis" +#define D_JSON_AXIS_GX "GyroXAxis" +#define D_JSON_AXIS_GY "GyroYAxis" +#define D_JSON_AXIS_GZ "GyroZAxis" +#define D_JSON_YAW "Yaw" +#define D_JSON_PITCH "Pitch" +#define D_JSON_ROLL "Roll" + +void MPU_6050Show(bool json) +{ + MPU_6050PerformReading(); + + double tempConv = (MPU_6050_temperature / 340.0 + 35.53); + char temperature[33]; + dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature); + char axis_ax[33]; + dtostrfd(MPU_6050_ax, Settings.flag2.axis_resolution, axis_ax); + char axis_ay[33]; + dtostrfd(MPU_6050_ay, Settings.flag2.axis_resolution, axis_ay); + char axis_az[33]; + dtostrfd(MPU_6050_az, Settings.flag2.axis_resolution, axis_az); + char axis_gx[33]; + dtostrfd(MPU_6050_gx, Settings.flag2.axis_resolution, axis_gx); + char axis_gy[33]; + dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); + char axis_gz[33]; + dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); +#ifdef USE_MPU6050_DMP + char axis_yaw[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[0] / PI * 180.0, Settings.flag2.axis_resolution, axis_yaw); + char axis_pitch[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[1] / PI * 180.0, Settings.flag2.axis_resolution, axis_pitch); + char axis_roll[33]; + dtostrfd(MPU6050_dmp.yawPitchRoll[2] / PI * 180.0, Settings.flag2.axis_resolution, axis_roll); +#endif + + if (json) { + char json_axis_ax[25]; + snprintf_P(json_axis_ax, sizeof(json_axis_ax), PSTR(",\"" D_JSON_AXIS_AX "\":%s"), axis_ax); + char json_axis_ay[25]; + snprintf_P(json_axis_ay, sizeof(json_axis_ay), PSTR(",\"" D_JSON_AXIS_AY "\":%s"), axis_ay); + char json_axis_az[25]; + snprintf_P(json_axis_az, sizeof(json_axis_az), PSTR(",\"" D_JSON_AXIS_AZ "\":%s"), axis_az); + char json_axis_gx[25]; + snprintf_P(json_axis_gx, sizeof(json_axis_gx), PSTR(",\"" D_JSON_AXIS_GX "\":%s"), axis_gx); + char json_axis_gy[25]; + snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); + char json_axis_gz[25]; + snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); +#ifdef USE_MPU6050_DMP + char json_ypr_y[25]; + snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), axis_yaw); + char json_ypr_p[25]; + snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), axis_pitch); + char json_ypr_r[25]; + snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), axis_roll); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz, + json_ypr_y, json_ypr_p, json_ypr_r); +#else + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); +#endif +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); +#ifdef USE_MPU6050_DMP + WSContentSend_PD(HTTP_SNS_YPR, axis_yaw, axis_pitch, axis_roll); +#endif +#endif + } +} + + + + + +bool Xsns32(uint8_t function) +{ + if (!I2cEnabled(XI2C_25)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MPU_6050Detect(); + } + else if (MPU_6050_found) { + switch (function) { + case FUNC_EVERY_SECOND: + if (tele_period == Settings.tele_period -3) { + MPU_6050PerformReading(); + } + break; + case FUNC_JSON_APPEND: + MPU_6050Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MPU_6050Show(0); + MPU_6050PerformReading(); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_33_ds3231.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_33_ds3231.ino" +#ifdef USE_I2C +#ifdef USE_DS3231 +# 35 "S:/Development/Tasmota/tasmota/xsns_33_ds3231.ino" +#define XSNS_33 33 +#define XI2C_26 26 + + +#ifndef USE_RTC_ADDR +#define USE_RTC_ADDR 0x68 +#endif + + +#define RTC_SECONDS 0x00 +#define RTC_MINUTES 0x01 +#define RTC_HOURS 0x02 +#define RTC_DAY 0x03 +#define RTC_DATE 0x04 +#define RTC_MONTH 0x05 +#define RTC_YEAR 0x06 +#define RTC_CONTROL 0x0E +#define RTC_STATUS 0x0F + +#define OSF 7 +#define EOSC 7 +#define BBSQW 6 +#define CONV 5 +#define RS2 4 +#define RS1 3 +#define INTCN 2 + + +#define HR1224 6 +#define CENTURY 7 +#define DYDT 6 +bool ds3231ReadStatus = false; +bool ds3231WriteStatus = false; +bool DS3231chipDetected = false; + + + + +void DS3231Detect(void) +{ + if (I2cActive(USE_RTC_ADDR)) { return; } + + if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { + I2cSetActiveFound(USE_RTC_ADDR, "DS3231"); + DS3231chipDetected = true; + } +} + + + + +uint8_t bcd2dec(uint8_t n) +{ + return n - 6 * (n >> 4); +} + + + + +uint8_t dec2bcd(uint8_t n) +{ + return n + 6 * (n / 10); +} + + + + +uint32_t ReadFromDS3231(void) +{ + TIME_T tm; + tm.second = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_SECONDS)); + tm.minute = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MINUTES)); + tm.hour = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_HOURS) & ~_BV(HR1224)); + tm.day_of_week = I2cRead8(USE_RTC_ADDR, RTC_DAY); + tm.day_of_month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_DATE)); + tm.month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MONTH) & ~_BV(CENTURY)); + tm.year = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_YEAR)); + return MakeTime(tm); +} + + + +void SetDS3231Time (uint32_t epoch_time) { + TIME_T tm; + BreakTime(epoch_time, tm); + I2cWrite8(USE_RTC_ADDR, RTC_SECONDS, dec2bcd(tm.second)); + I2cWrite8(USE_RTC_ADDR, RTC_MINUTES, dec2bcd(tm.minute)); + I2cWrite8(USE_RTC_ADDR, RTC_HOURS, dec2bcd(tm.hour)); + I2cWrite8(USE_RTC_ADDR, RTC_DAY, tm.day_of_week); + I2cWrite8(USE_RTC_ADDR, RTC_DATE, dec2bcd(tm.day_of_month)); + I2cWrite8(USE_RTC_ADDR, RTC_MONTH, dec2bcd(tm.month)); + I2cWrite8(USE_RTC_ADDR, RTC_YEAR, dec2bcd(tm.year)); + I2cWrite8(USE_RTC_ADDR, RTC_STATUS, I2cRead8(USE_RTC_ADDR, RTC_STATUS) & ~_BV(OSF)); +} + +void DS3231EverySecond(void) +{ + TIME_T tmpTime; + if (!ds3231ReadStatus && Rtc.utc_time < START_VALID_TIME ) { + ntp_force_sync = true; + Rtc.utc_time = ReadFromDS3231(); + + + BreakTime(Rtc.utc_time, tmpTime); + if (Rtc.utc_time < START_VALID_TIME ) { + ds3231ReadStatus = true; + } + RtcTime.year = tmpTime.year + 1970; + Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); + Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); + AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); + if (Rtc.local_time < START_VALID_TIME) { + rules_flag.time_init = 1; + } else { + rules_flag.time_set = 1; + } + } + else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), + GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); + SetDS3231Time (Rtc.utc_time); + ds3231WriteStatus = true; + } +} + + + + + +bool Xsns33(uint8_t function) +{ + if (!I2cEnabled(XI2C_26)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + DS3231Detect(); + } + else if (DS3231chipDetected) { + switch (function) { + case FUNC_EVERY_SECOND: + DS3231EverySecond(); + break; + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_34_hx711.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_34_hx711.ino" +#ifdef USE_HX711 +# 35 "S:/Development/Tasmota/tasmota/xsns_34_hx711.ino" +#define XSNS_34 34 + +#ifndef HX_MAX_WEIGHT +#define HX_MAX_WEIGHT 20000 +#endif +#ifndef HX_REFERENCE +#define HX_REFERENCE 250 +#endif +#ifndef HX_SCALE +#define HX_SCALE 120 +#endif + +#define HX_TIMEOUT 120 +#define HX_SAMPLES 10 +#define HX_CAL_TIMEOUT 15 + +#define HX_GAIN_128 1 +#define HX_GAIN_32 2 +#define HX_GAIN_64 3 + +#define D_JSON_WEIGHT_REF "WeightRef" +#define D_JSON_WEIGHT_CAL "WeightCal" +#define D_JSON_WEIGHT_MAX "WeightMax" +#define D_JSON_WEIGHT_ITEM "WeightItem" +#define D_JSON_WEIGHT_CHANGE "WeightChange" +#define D_JSON_WEIGHT_RAW "WeightRaw" +#define D_JSON_WEIGHT_DELTA "WeightDelta" + +enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; + +const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE; + +struct HX { + long weight = 0; + long raw = 0; + long last_weight = 0; + long sum_weight = 0; + long sum_raw = 0; + long offset = 0; + long scale = 1; + long weight_diff = 0; + uint8_t type = 1; + uint8_t sample_count = 0; + uint8_t calibrate_step = HX_CAL_END; + uint8_t calibrate_timer = 0; + uint8_t calibrate_msg = 0; + uint8_t pin_sck; + uint8_t pin_dout; + bool tare_flg = false; + bool weight_changed = false; + uint16_t weight_delta = 4; +} Hx; + + + +bool HxIsReady(uint16_t timeout) +{ + + uint32_t start = millis(); + while ((digitalRead(Hx.pin_dout) == HIGH) && (millis() - start < timeout)) { yield(); } + return (digitalRead(Hx.pin_dout) == LOW); +} + +long HxRead(void) +{ + if (!HxIsReady(HX_TIMEOUT)) { return -1; } + + uint8_t data[3] = { 0 }; + uint8_t filler = 0x00; + + + data[2] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + data[1] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + data[0] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); + + + for (unsigned int i = 0; i < HX_GAIN_128; i++) { + digitalWrite(Hx.pin_sck, HIGH); + digitalWrite(Hx.pin_sck, LOW); + } + + + if (data[2] & 0x80) { filler = 0xFF; } + + + unsigned long value = ( static_cast(filler) << 24 + | static_cast(data[2]) << 16 + | static_cast(data[1]) << 8 + | static_cast(data[0]) ); + + return static_cast(value); +} + + + +void HxResetPart(void) +{ + Hx.tare_flg = true; + Hx.sum_weight = 0; + Hx.sample_count = 0; + Hx.last_weight = 0; +} + +void HxReset(void) +{ + HxResetPart(); + Settings.energy_frequency_calibration = 0; +} + +void HxCalibrationStateTextJson(uint8_t msg_id) +{ + char cal_text[30]; + + Hx.calibrate_msg = msg_id; + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); + + if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } +} + +void SetWeightDelta() +{ + + if (Settings.weight_change == 0) { + Hx.weight_delta = 4; + return; + } + + + if (Settings.weight_change > 100) { + Hx.weight_delta = (Settings.weight_change - 100) * 10 + 100; + return; + } + + + Hx.weight_delta = Settings.weight_change - 1; +} +# 192 "S:/Development/Tasmota/tasmota/xsns_34_hx711.ino" +bool HxCommand(void) +{ + bool serviced = true; + bool show_parms = false; + char sub_string[XdrvMailbox.data_len +1]; + + for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) { + if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; } + } + + switch (XdrvMailbox.payload) { + case 1: + HxReset(); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); + break; + case 2: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + Hx.scale = 1; + HxReset(); + Hx.calibrate_step = HX_CAL_START; + Hx.calibrate_timer = 1; + HxCalibrationStateTextJson(3); + break; + case 3: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + } + show_parms = true; + break; + case 4: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Hx.scale = Settings.weight_calibration; + } + show_parms = true; + break; + case 5: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000; + } + show_parms = true; + break; + case 6: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_item = (unsigned long)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); + } + show_parms = true; + break; + case 7: + Settings.energy_frequency_calibration = Hx.weight; + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE); + break; + case 8: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.SensorBits1.hx711_json_weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) & 1; + } + show_parms = true; + break; + case 9: + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + SetWeightDelta(); + } + show_parms = true; + break; + default: + show_parms = true; + } + + if (show_parms) { + char item[33]; + dtostrfd((float)Settings.weight_item / 10, 1, item); + Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" + D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":%s,\"" D_JSON_WEIGHT_DELTA "\":%d}}"), + Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, + item, GetStateText(Settings.SensorBits1.hx711_json_weight_change), Settings.weight_change); + } + + return serviced; +} + + + +long HxWeight(void) +{ + return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; +} + +void HxInit(void) +{ + Hx.type = 0; + if ((pin[GPIO_HX711_DAT] < 99) && (pin[GPIO_HX711_SCK] < 99)) { + Hx.pin_sck = pin[GPIO_HX711_SCK]; + Hx.pin_dout = pin[GPIO_HX711_DAT]; + + pinMode(Hx.pin_sck, OUTPUT); + pinMode(Hx.pin_dout, INPUT); + + digitalWrite(Hx.pin_sck, LOW); + + SetWeightDelta(); + + if (HxIsReady(8 * HX_TIMEOUT)) { + if (!Settings.weight_max) { Settings.weight_max = HX_MAX_WEIGHT / 1000; } + if (!Settings.weight_calibration) { Settings.weight_calibration = HX_SCALE; } + if (!Settings.weight_reference) { Settings.weight_reference = HX_REFERENCE; } + Hx.scale = Settings.weight_calibration; + HxRead(); + HxResetPart(); + Hx.type = 1; + } + } +} + +void HxEvery100mSecond(void) +{ + long raw = HxRead(); + Hx.sum_raw += raw; + Hx.sum_weight += raw; + + Hx.sample_count++; + if (HX_SAMPLES == Hx.sample_count) { + long average = Hx.sum_weight / Hx.sample_count; + long raw_average = Hx.sum_raw / Hx.sample_count; + long value = average - Hx.offset; + Hx.weight = value / Hx.scale; + Hx.raw = raw_average / Hx.scale; + if (Hx.weight < 0) { + if (Settings.energy_frequency_calibration) { + long difference = Settings.energy_frequency_calibration + Hx.weight; + Hx.last_weight = difference; + if (difference < 0) { HxReset(); } + } + Hx.weight = 0; + } else { + Hx.last_weight = Settings.energy_frequency_calibration; + } + + if (Hx.tare_flg) { + Hx.tare_flg = false; + Hx.offset = average; + } + + if (Hx.calibrate_step) { + Hx.calibrate_timer--; + + if (HX_CAL_START == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); + } + else if (HX_CAL_RESET == Hx.calibrate_step) { + if (Hx.calibrate_timer) { + if (Hx.weight < (long)Settings.weight_reference) { + Hx.calibrate_step--; + Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); + HxCalibrationStateTextJson(2); + } + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + else if (HX_CAL_FIRST == Hx.calibrate_step) { + if (Hx.calibrate_timer) { + if (Hx.weight > (long)Settings.weight_reference) { + Hx.calibrate_step--; + } + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + else if (HX_CAL_DONE == Hx.calibrate_step) { + if (Hx.weight > (long)Settings.weight_reference) { + Hx.calibrate_step = HX_CAL_FINISH; + Settings.weight_calibration = Hx.weight / Settings.weight_reference; + Hx.weight = 0; + HxCalibrationStateTextJson(1); + } else { + Hx.calibrate_step = HX_CAL_FAIL; + } + } + + if (HX_CAL_FAIL == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.tare_flg = true; + HxCalibrationStateTextJson(0); + } + if (HX_CAL_FINISH == Hx.calibrate_step) { + Hx.calibrate_step--; + Hx.calibrate_timer = 3 * (10 / HX_SAMPLES); + Hx.scale = Settings.weight_calibration; + } + + if (!Hx.calibrate_timer) { + Hx.calibrate_step = HX_CAL_END; + } + } else { + Hx.weight += Hx.last_weight; + + if (Settings.SensorBits1.hx711_json_weight_change) { + if (abs(Hx.weight - Hx.weight_diff) > Hx.weight_delta) { + Hx.weight_diff = Hx.weight; + Hx.weight_changed = true; + } + else if (Hx.weight_changed && (Hx.weight == Hx.weight_diff)) { + mqtt_data[0] = '\0'; + ResponseAppendTime(); + HxShow(true); + ResponseJsonEnd(); + MqttPublishTeleSensor(); + Hx.weight_changed = false; + } + } + } + + Hx.sum_weight = 0; + Hx.sum_raw = 0; + Hx.sample_count = 0; + } +} + +void HxSaveBeforeRestart(void) +{ + Settings.energy_frequency_calibration = Hx.weight; + Hx.sample_count = HX_SAMPLES +1; +} + +#ifdef USE_WEBSERVER +const char HTTP_HX711_WEIGHT[] PROGMEM = + "{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; +const char HTTP_HX711_COUNT[] PROGMEM = + "{s}HX711 " D_COUNT "{m}%d{e}"; +const char HTTP_HX711_CAL[] PROGMEM = + "{s}HX711 %s{m}{e}"; +#endif + +void HxShow(bool json) +{ + char scount[30] = { 0 }; + + uint16_t count = 0; + float weight = 0; + if (Hx.calibrate_step < HX_CAL_FAIL) { + if (Hx.weight && Settings.weight_item) { + count = (Hx.weight * 10) / Settings.weight_item; + if (count > 1) { + snprintf_P(scount, sizeof(scount), PSTR(",\"" D_JSON_COUNT "\":%d"), count); + } + } + weight = (float)Hx.weight / 1000; + } + char weight_chr[33]; + dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); + + if (json) { + ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s, \"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); + if (count > 1) { + WSContentSend_PD(HTTP_HX711_COUNT, count); + } + if (Hx.calibrate_step) { + char cal_text[30]; + WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); + } +#endif + } +} + +#ifdef USE_WEBSERVER +#ifdef USE_HX711_GUI + + + + +#define WEB_HANDLE_HX711 "s34" + +const char S_CONFIGURE_HX711[] PROGMEM = D_CONFIGURE_HX711; + +const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = + "

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

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

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" + "
" + "
" + "


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

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; + +void HandleHxAction(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); + + if (WebServer->hasArg("save")) { + HxSaveSettings(); + HandleConfiguration(); + return; + } + + char stemp1[20]; + + if (WebServer->hasArg("reset")) { + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); + ExecuteWebCommand(stemp1, SRC_WEBGUI); + + HandleRoot(); + return; + } + + if (WebServer->hasArg("calibrate")) { + WebGetArg("p1", stemp1, sizeof(stemp1)); + Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); + + HxLogUpdates(); + + snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); + ExecuteWebCommand(stemp1, SRC_WEBGUI); + + HandleRoot(); + return; + } + + WSContentStart_P(S_CONFIGURE_HX711); + WSContentSendStyle(); + dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); + char stemp2[20]; + dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); + WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); + WSContentSend_P(HTTP_FORM_END); + WSContentSpaceButton(BUTTON_CONFIGURATION); + WSContentStop(); +} + +void HxSaveSettings(void) +{ + char tmp[100]; + + WebGetArg("p2", tmp, sizeof(tmp)); + Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToFloat(tmp) * 10000); + + HxLogUpdates(); +} + +void HxLogUpdates(void) +{ + char weigth_ref_chr[33]; + dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); + char weigth_item_chr[33]; + dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), weigth_ref_chr, weigth_item_chr); +} + +#endif +#endif + + + + + +bool Xsns34(uint8_t function) +{ + bool result = false; + + if (Hx.type) { + switch (function) { + case FUNC_EVERY_100_MSECOND: + HxEvery100mSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_34 == XdrvMailbox.index) { + result = HxCommand(); + } + break; + case FUNC_JSON_APPEND: + HxShow(1); + break; + case FUNC_SAVE_BEFORE_RESTART: + HxSaveBeforeRestart(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HxShow(0); + break; +#ifdef USE_HX711_GUI + case FUNC_WEB_ADD_MAIN_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711); + break; + case FUNC_WEB_ADD_BUTTON: + WSContentSend_P(HTTP_BTN_MENU_HX711); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); + break; +#endif +#endif + case FUNC_INIT: + HxInit(); + break; + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_35_tx20.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_35_tx20.ino" +#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) +#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR) +#undef USE_TX20_WIND_SENSOR +#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled **** +#endif +# 41 "S:/Development/Tasmota/tasmota/xsns_35_tx20.ino" +#define XSNS_35 35 + +#define TX2X_BIT_TIME 1220 +#define TX2X_RESET_VALUES 60 + + + +extern "C" { +#include "gpio.h" +} + +#ifdef USE_TX20_WIND_SENSOR + #define D_TX2x_NAME "TX20" +#else + #define D_TX2x_NAME "TX23" +#endif + +#ifdef USE_WEBSERVER +const char HTTP_SNS_TX2X[] PROGMEM = + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s (%s°){e}"; +#endif + +const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" + D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST "|" + D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST "|" + D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; + +uint8_t tx2x_sa = 0; +uint8_t tx2x_sb = 0; +uint8_t tx2x_sd = 0; +uint8_t tx2x_se = 0; +uint16_t tx2x_sc = 0; +uint16_t tx2x_sf = 0; + +float tx2x_wind_speed_kmh = 0; +float tx2x_wind_speed_max = 0; +float tx2x_wind_speed_avg = 0; +float tx2x_wind_sum = 0; +int tx2x_count = 0; +uint8_t tx2x_wind_direction = 0; + +bool tx2x_available = false; + +#ifdef USE_TX23_WIND_SENSOR +uint8_t tx23_stage = 0; +#endif + +#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 +void TX2xStartRead(void) ICACHE_RAM_ATTR; +#endif + +void TX2xStartRead(void) +{ +# 135 "S:/Development/Tasmota/tasmota/xsns_35_tx20.ino" +#ifdef USE_TX23_WIND_SENSOR + if (0!=tx23_stage) + { + if ((2==tx23_stage) || (3==tx23_stage)) + { +#endif + tx2x_available = false; + + tx2x_sa = 0; + tx2x_sb = 0; + tx2x_sd = 0; + tx2x_se = 0; + tx2x_sc = 0; + tx2x_sf = 0; + + delayMicroseconds(TX2X_BIT_TIME / 2); + + for (int32_t bitcount = 41; bitcount > 0; bitcount--) { + uint8_t dpin = (digitalRead(pin[GPIO_TX2X_TXD_BLACK])); +#ifdef USE_TX23_WIND_SENSOR + if (bitcount > 41 - 5) { + + tx2x_sa = (tx2x_sa << 1) | (dpin); + } else if (bitcount > 41 - 5 - 4) { + + tx2x_sb = tx2x_sb >> 1 | ((dpin) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + + tx2x_sc = tx2x_sc >> 1 | ((dpin) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + + tx2x_sd = tx2x_sd >> 1 | ((dpin) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + + tx2x_se = tx2x_se >> 1 | ((dpin ^ 1) << 3); + } else { + + tx2x_sf = tx2x_sf >> 1 | ((dpin ^ 1) << 11); + } +#else + if (bitcount > 41 - 5) { + + tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1); + } else if (bitcount > 41 - 5 - 4) { + + tx2x_sb = tx2x_sb >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + + tx2x_sc = tx2x_sc >> 1 | ((dpin ^ 1) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + + tx2x_sd = tx2x_sd >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + + tx2x_se = tx2x_se >> 1 | (dpin << 3); + } else { + + tx2x_sf = tx2x_sf >> 1 | (dpin << 11); + } +#endif + delayMicroseconds(TX2X_BIT_TIME); + } + + uint8_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); + chk &= 0xf; + +#ifdef USE_TX23_WIND_SENSOR + + if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { + tx2x_available = true; + } +#else + if ((chk == tx2x_sd) && (tx2x_sc < 511)) { + tx2x_available = true; + } +#endif +#ifdef USE_TX23_WIND_SENSOR + } + tx23_stage++; + } +#endif + + + + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX2X_TXD_BLACK]); +} + +void Tx2xReset(void) +{ + tx2x_count = 0; + tx2x_wind_sum = 0; + tx2x_wind_speed_max = 0; +} + +void Tx2xRead(void) +{ +#ifdef USE_TX23_WIND_SENSOR + + + if ((uptime % 3)==0) { + + + tx23_stage = 0; + pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); + digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); + } else if ((uptime % 3)==1) { + + + tx23_stage = 1; + pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT_PULLUP); + } +#endif + if (0==Settings.tele_period && !(uptime % TX2X_RESET_VALUES)) { + Tx2xReset(); + } + else if (tx2x_available) { + + tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36; + if (tx2x_wind_speed_kmh > tx2x_wind_speed_max) { + tx2x_wind_speed_max = tx2x_wind_speed_kmh; + } + tx2x_count++; + tx2x_wind_sum += tx2x_wind_speed_kmh; + tx2x_wind_speed_avg = tx2x_wind_sum / tx2x_count; + tx2x_wind_direction = tx2x_sb; + } +} + +void Tx2xInit(void) +{ +#ifdef USE_TX23_WIND_SENSOR + tx23_stage = 0; + pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); + digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); +#else + pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT); +#endif + attachInterrupt(pin[GPIO_TX2X_TXD_BLACK], TX2xStartRead, RISING); +} + +void Tx2xShow(bool json) +{ + char wind_speed_string[33]; + dtostrfd(tx2x_wind_speed_kmh, 1, wind_speed_string); + char wind_speed_max_string[33]; + dtostrfd(tx2x_wind_speed_max, 1, wind_speed_max_string); + char wind_speed_avg_string[33]; + dtostrfd(tx2x_wind_speed_avg, 1, wind_speed_avg_string); + char wind_direction_string[4]; + GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx2x_wind_direction, kTx2xDirections); + char wind_direction_degree[33]; + dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_degree); + + if (json) { + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), + wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); + Tx2xReset(); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TX2X, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); +#endif + } +} + + + + + +bool Xsns35(uint8_t function) +{ + bool result = false; + + if (pin[GPIO_TX2X_TXD_BLACK] < 99) { + switch (function) { + case FUNC_INIT: + Tx2xInit(); + break; + case FUNC_EVERY_SECOND: + Tx2xRead(); + break; + case FUNC_JSON_APPEND: + Tx2xShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tx2xShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_36_mgc3130.ino" +# 22 "S:/Development/Tasmota/tasmota/xsns_36_mgc3130.ino" +#ifdef USE_I2C +#ifdef USE_MGC3130 +# 35 "S:/Development/Tasmota/tasmota/xsns_36_mgc3130.ino" +#define XSNS_36 36 +#define XI2C_27 27 + +#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** + +#define MGC3130_I2C_ADDR 0x42 + +#define MGC3130_xfer pin[GPIO_MGC3130_XFER] +#define MGC3130_reset pin[GPIO_MGC3130_RESET] + + +bool MGC3130_type = false; +char MGC3130stype[] = "MGC3130"; + + +#define MGC3130_SYSTEM_STATUS 0x15 +#define MGC3130_REQUEST_MSG 0x06 +#define MGC3130_FW_VERSION 0x83 +#define MGC3130_SET_RUNTIME 0xA2 +#define MGC3130_SENSOR_DATA 0x91 + + +#define MGC3130_GESTURE_GARBAGE 1 +#define MGC3130_FLICK_WEST_EAST 2 +#define MGC3130_FLICK_EAST_WEST 3 +#define MGC3130_FLICK_SOUTH_NORTH 4 +#define MGC3130_FLICK_NORTH_SOUTH 5 +#define MGC3130_CIRCLE_CLOCKWISE 6 +#define MGC3130_CIRCLE_CCLOCKWISE 7 + +#define MGC3130_MIN_ROTVALUE 0 +#define MGC3130_MAX_ROTVALUE 1023 +#define MGC3130_MIN_ZVALUE 32768 + + +#ifdef USE_WEBSERVER +const char HTTP_MGC_3130_SNS[] PROGMEM = + "{s}" "%s" "{m}%s{e}" + "{s}" "HwRev" "{m}%u.%u{e}" + "{s}" "loaderVer" "{m}%u.%u{e}" + "{s}" "platVer" "{m}%u{e}"; +#endif + + + + + + + +#pragma pack(1) +union MGC3130_Union{ + uint8_t buffer[132]; + struct + { + + uint8_t msgSize; + uint8_t flag; + uint8_t counter; + uint8_t id; + + struct { + uint8_t DSPStatus:1; + uint8_t gestureInfo:1; + uint8_t touchInfo:1; + uint8_t airWheelInfo:1; + uint8_t xyzPosition:1; + uint8_t noisePower:1; + uint8_t reserved:2; + uint8_t electrodeConfiguration:3; + uint8_t CICData:1; + uint8_t SDData:1; + uint16_t reserved2:3; + } outputConfigMask; + uint8_t timestamp; + struct { + uint8_t positionValid:1; + uint8_t airWheelValid:1; + uint8_t rawDataValid:1; + uint8_t noisePowerValid:1; + uint8_t environmentalNoise:1; + uint8_t clipping:1; + uint8_t reserved:1; + uint8_t DSPRunning:1; + } systemInfo; + uint16_t dspInfo; + struct { + uint8_t gestureCode:8; + uint8_t reserved:4; + uint8_t gestureType:4; + uint8_t edgeFlick:1; + uint16_t reserved2:14; + uint8_t gestureInProgress:1; + } gestureInfo; + struct { + uint8_t touchSouth:1; + uint8_t touchWest:1; + uint8_t touchNorth:1; + uint8_t touchEast:1; + uint8_t touchCentre:1; + uint8_t tapSouth:1; + uint8_t tapWest:1; + uint8_t tapNorth:1; + uint8_t tapEast :1; + uint8_t tapCentre:1; + uint8_t doubleTapSouth:1; + uint8_t doubleTapWest:1; + uint8_t doubleTapNorth:1; + uint8_t doubleTapEast:1; + uint8_t doubleTapCentre:1; + uint8_t reserved:1; + uint8_t touchCounter; + uint8_t reserved2; + } touchInfo; + int8_t airWheel; + uint8_t reserved; + uint16_t x; + uint16_t y; + uint16_t z; + float noisePower; + float CICData[4]; + float SDData[4]; + } out; + struct { + uint8_t header[3]; + + uint8_t valid; + uint8_t hwRev[2]; + uint8_t parameterStartAddr; + uint8_t loaderVersion[2]; + uint8_t loaderPlatform; + uint8_t fwStartAddr; + char fwVersion[120]; + } fw; + struct{ + uint8_t id; + uint8_t size; + uint16_t error; + uint32_t reserved; + uint32_t reserved1; + } status; +} MGC_data; +#pragma pack() + +char MGC3130_currentGesture[12]; + +int8_t MGC3130_delta, MGC3130_lastrotation = 0; +int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0; + +uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0; + +uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0; +char MGC3130_firmwareInfo[20]; + +uint8_t MGC3130_touchTimeout = 0; +uint16_t MGC3130_touchCounter = 1; +uint32_t MGC3130_touchTimeStamp = millis(); +bool MGC3130_triggeredByTouch = false; + +uint8_t MGC3130_mode = 1; + + + +uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; +uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; +uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; + +void MGC3130_handleSensorData(){ + if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ + if (MGC3130_handleTouch()){ + MGC3130_triggeredByTouch = true; + MqttPublishSensor(); + } + } + + if(MGC3130_mode == 1){ + if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ + MGC3130_handleGesture(); + MqttPublishSensor(); + } + } + if(MGC3130_mode == 2){ + if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ + MGC3130_handleAirWheel(); + MqttPublishSensor(); + } + } + if(MGC3130_mode == 3){ + if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ + MqttPublishSensor(); + } + } +} + +void MGC3130_sendMessage(uint8_t data[], uint8_t length){ + Wire.beginTransmission(MGC3130_I2C_ADDR); + Wire.write(data,length); + Wire.endTransmission(); + delay(2); + MGC3130_receiveMessage(); +} + + +void MGC3130_handleGesture(){ + + char edge[5]; + if (MGC_data.out.gestureInfo.edgeFlick){ + snprintf_P(edge, sizeof(edge), PSTR("ED_")); + } + else{ + snprintf_P(edge, sizeof(edge), PSTR("")); + } + switch(MGC_data.out.gestureInfo.gestureCode){ + case MGC3130_GESTURE_GARBAGE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE")); + break; + case MGC3130_FLICK_WEST_EAST: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge); + break; + case MGC3130_FLICK_EAST_WEST: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge); + break; + case MGC3130_FLICK_SOUTH_NORTH: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge); + break; + case MGC3130_FLICK_NORTH_SOUTH: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge); + break; + case MGC3130_CIRCLE_CLOCKWISE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW")); + break; + case MGC3130_CIRCLE_CCLOCKWISE: + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW")); + break; + } + +} + +bool MGC3130_handleTouch(){ + + bool success = false; + if (MGC_data.out.touchInfo.doubleTapCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.doubleTapSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S")); + MGC3130_touchTimeout = 5; + success = true; + MGC3130_touchCounter = 1; + } + if (MGC_data.out.touchInfo.tapCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.tapSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S")); + MGC3130_touchTimeout = 2; + success = true; + MGC3130_touchCounter = 1; + } + else if (MGC_data.out.touchInfo.touchCentre && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchEast && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchNorth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchWest && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W")); + success = true; + MGC3130_touchCounter++; + } + else if (MGC_data.out.touchInfo.touchSouth && !success){ + + snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S")); + success = true; + MGC3130_touchCounter++; + } + + return success; +} + +void MGC3130_handleAirWheel(){ + MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation; + MGC3130_lastrotation = MGC_data.out.airWheel; + + MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta; + if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){ + MGC3130_rotValue = MGC3130_MIN_ROTVALUE; + } + if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){ + MGC3130_rotValue = MGC3130_MAX_ROTVALUE; + } +} + +void MGC3130_handleSystemStatus(){ + +} + +bool MGC3130_receiveMessage(){ + if(MGC3130_readData()){ + switch(MGC_data.out.id){ + case MGC3130_SENSOR_DATA: + MGC3130_handleSensorData(); + break; + case MGC3130_SYSTEM_STATUS: + MGC3130_handleSystemStatus(); + break; + case MGC3130_FW_VERSION: + hwRev[0] = MGC_data.fw.hwRev[1]; + hwRev[1] = MGC_data.fw.hwRev[0]; + loaderVersion[0] = MGC_data.fw.loaderVersion[0]; + loaderVersion[1] = MGC_data.fw.loaderVersion[1]; + loaderPlatform = MGC_data.fw.loaderPlatform; + snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion); + MGC3130_firmwareInfo[20] = '\0'; + + break; + } + return true; + } + return false; +} + +bool MGC3130_readData() +{ + bool success = false; + if (!digitalRead(MGC3130_xfer)){ + pinMode(MGC3130_xfer, OUTPUT); + digitalWrite(MGC3130_xfer, LOW); + Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); + + MGC_data.buffer[0] = 4; + unsigned char i = 0; + while(Wire.available() && (i < MGC_data.buffer[0])){ + MGC_data.buffer[i] = Wire.read(); + i++; + } + digitalWrite(MGC3130_xfer, HIGH); + pinMode(MGC3130_xfer, INPUT); + success = true; + } + return success; +} + +void MGC3130_nextMode(){ + if (MGC3130_mode < 3){ + MGC3130_mode++; + } + else{ + MGC3130_mode = 1; + } + switch(MGC3130_mode){ + case 1: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } +} + +void MGC3130_loop() +{ + if(MGC3130_touchTimeout > 0){ + MGC3130_touchTimeout--; + } + MGC3130_receiveMessage(); +} + +void MGC3130_detect(void) +{ + if (MGC3130_type || I2cActive(MGC3130_I2C_ADDR)) { return; } + + pinMode(MGC3130_xfer, INPUT_PULLUP); + pinMode(MGC3130_reset, OUTPUT); + digitalWrite(MGC3130_reset, LOW); + delay(10); + digitalWrite(MGC3130_reset, HIGH); + delay(50); + + if (MGC3130_receiveMessage()) { + I2cSetActiveFound(MGC3130_I2C_ADDR, MGC3130stype); + MGC3130_currentGesture[0] = '\0'; + MGC3130_type = true; + } +} + + + + + +void MGC3130_show(bool json) +{ + if (!MGC3130_type) { return; } + + char status_chr[2]; + if (MGC_data.out.systemInfo.DSPRunning) { + sprintf (status_chr, "1"); + } + else{ + sprintf (status_chr, "0"); + } + + if (json) { + if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { + if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { + ResponseAppend_P(PSTR(",\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), + MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); + MGC3130_lastSentX = MGC_data.out.x; + MGC3130_lastSentY = MGC_data.out.y; + MGC3130_lastSentZ = MGC_data.out.z; + } + } + MGC3130_triggeredByTouch = false; + + if (MGC3130_mode == 2) { + if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { + ResponseAppend_P(PSTR(",\"%s\":{\"AW\":%i}"), MGC3130stype, MGC3130_rotValue); + MGC3130_lastSentRotValue = MGC3130_rotValue; + } + } + + if (MGC3130_currentGesture[0] != '\0') { + if (millis() - MGC3130_touchTimeStamp > 220 ) { + MGC3130_touchCounter = 1; + } + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); + MGC3130_currentGesture[0] = '\0'; + MGC3130_touchTimeStamp = millis(); + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); +#endif + } +} +# 557 "S:/Development/Tasmota/tasmota/xsns_36_mgc3130.ino" +bool MGC3130CommandSensor() +{ + bool serviced = true; + + switch (XdrvMailbox.payload) { + case 0: + MGC3130_nextMode(); + break; + case 1: + MGC3130_mode = 1; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + case 2: + MGC3130_mode = 2; + MGC3130_sendMessage(MGC3130enableAirwheel,16); + break; + case 3: + MGC3130_mode = 3; + MGC3130_sendMessage(MGC3130disableAirwheel,16); + break; + } + return serviced; +} + + + + + +bool Xsns36(uint8_t function) +{ + if (!I2cEnabled(XI2C_27)) { return false; } + + bool result = false; + + if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { + MGC3130_detect(); + } + else if (MGC3130_type) { + switch (function) { + case FUNC_EVERY_50_MSECOND: + MGC3130_loop(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_36 == XdrvMailbox.index) { + result = MGC3130CommandSensor(); + } + break; + case FUNC_JSON_APPEND: + MGC3130_show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MGC3130_show(0); + break; +#endif + } + } + return result; +} +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" +#ifdef USE_RF_SENSOR +# 33 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" +#define XSNS_37 37 + + + + +#define RFSNS_VALID_WINDOW 1800 + +#define RFSNS_LOOPS_PER_MILLI 1900 +#define RFSNS_RAW_BUFFER_SIZE 180 +#define RFSNS_MIN_RAW_PULSES 112 + +#define RFSNS_MIN_PULSE_LENGTH 300 +#define RFSNS_RAWSIGNAL_SAMPLE 50 +#define RFSNS_SIGNAL_TIMEOUT 10 +#define RFSNS_SIGNAL_REPEAT_TIME 500 + +typedef struct RawSignalStruct +{ + int Number; + uint8_t Repeats; + uint8_t Multiply; + unsigned long Time; + uint8_t Pulses[RFSNS_RAW_BUFFER_SIZE+2]; + +} raw_signal_t; + +raw_signal_t *rfsns_raw_signal = nullptr; +uint8_t rfsns_rf_bit; +uint8_t rfsns_rf_port; +uint8_t rfsns_any_sensor = 0; + + + + + +bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal) +{ + uint8_t Fbit = digitalPinToBitMask(DataPin); + uint8_t Fport = digitalPinToPort(DataPin); + uint8_t FstateMask = (StateSignal ? Fbit : 0); + + if ((*portInputRegister(Fport) & Fbit) == FstateMask) { + const unsigned long LoopsPerMilli = RFSNS_LOOPS_PER_MILLI; + + + + + + + unsigned long PulseLength = 0; + if (rfsns_raw_signal->Time) { + if (rfsns_raw_signal->Repeats && (rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) { + PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; + while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && (PulseLength > micros())) { + if ((*portInputRegister(Fport) & Fbit) == FstateMask) { + PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; + } + } + while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && ((*portInputRegister(Fport) & Fbit) != FstateMask)); + } + } + + int RawCodeLength = 1; + bool Ftoggle = false; + unsigned long numloops = 0; + unsigned long maxloops = RFSNS_SIGNAL_TIMEOUT * LoopsPerMilli; + rfsns_raw_signal->Multiply = RFSNS_RAWSIGNAL_SAMPLE; + do { + numloops = 0; + while(((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) { + if (numloops++ == maxloops) { break; } + } + PulseLength = (numloops *1000) / LoopsPerMilli; + if (PulseLength < RFSNS_MIN_PULSE_LENGTH) { break; } + Ftoggle = !Ftoggle; + rfsns_raw_signal->Pulses[RawCodeLength++] = PulseLength / (unsigned long)rfsns_raw_signal->Multiply; + } + while(RawCodeLength < RFSNS_RAW_BUFFER_SIZE && numloops <= maxloops); + + if ((RawCodeLength >= RFSNS_MIN_RAW_PULSES) && (RawCodeLength < RFSNS_RAW_BUFFER_SIZE -1)) { + rfsns_raw_signal->Repeats = 0; + rfsns_raw_signal->Number = RawCodeLength -1; + rfsns_raw_signal->Pulses[rfsns_raw_signal->Number] = 0; + rfsns_raw_signal->Time = millis(); + return true; + } + else + rfsns_raw_signal->Number = 0; + } + + return false; +} + +#ifdef USE_THEO_V2 +# 149 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" +#define RFSNS_THEOV2_MAX_CHANNEL 2 + +#define RFSNS_THEOV2_PULSECOUNT 114 +#define RFSNS_THEOV2_RF_PULSE_MID 1000 + +typedef struct { + uint32_t time; + int16_t temp; + uint16_t lux; + uint8_t volt; +} theo_v2_t1_t; + +typedef struct { + uint32_t time; + int16_t temp; + uint16_t hum; + uint8_t volt; +} theo_v2_t2_t; + +theo_v2_t1_t *rfsns_theo_v2_t1 = nullptr; +theo_v2_t2_t *rfsns_theo_v2_t2 = nullptr; + +void RfSnsInitTheoV2(void) +{ + rfsns_theo_v2_t1 = (theo_v2_t1_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t1_t)); + rfsns_theo_v2_t2 = (theo_v2_t2_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t2_t)); + rfsns_any_sensor++; +} + +void RfSnsAnalyzeTheov2(void) +{ + if (rfsns_raw_signal->Number != RFSNS_THEOV2_PULSECOUNT) { return; } + + uint8_t Checksum; + uint8_t Channel; + uint8_t Type; + uint8_t Voltage; + int Payload1; + int Payload2; + + uint8_t b, bytes, bits, id; + + uint8_t idx = 3; + uint8_t chksum = 0; + for (bytes = 0; bytes < 7; bytes++) { + b = 0; + for (bits = 0; bits <= 7; bits++) + { + if ((rfsns_raw_signal->Pulses[idx] * rfsns_raw_signal->Multiply) > RFSNS_THEOV2_RF_PULSE_MID) { + b |= 1 << bits; + } + idx += 2; + } + if (bytes > 0) { chksum += b; } + + switch (bytes) { + case 0: + Checksum = b; + break; + case 1: + id = b; + Channel = b & 0x7; + Type = (b >> 3) & 0x1f; + break; + case 2: + Voltage = b; + break; + case 3: + Payload1 = b; + break; + case 4: + Payload1 = (b << 8) | Payload1; + break; + case 5: + Payload2 = b; + break; + case 6: + Payload2 = (b << 8) | Payload2; + break; + } + } + + if (Checksum != chksum) { return; } + if ((Channel == 0) || (Channel > RFSNS_THEOV2_MAX_CHANNEL)) { return; } + Channel--; + + rfsns_raw_signal->Repeats = 1; + + int Payload3 = Voltage & 0x3f; + + switch (Type) { + case 1: + rfsns_theo_v2_t1[Channel].time = LocalTime(); + rfsns_theo_v2_t1[Channel].volt = Payload3; + rfsns_theo_v2_t1[Channel].temp = Payload1; + rfsns_theo_v2_t1[Channel].lux = Payload2; + break; + case 2: + rfsns_theo_v2_t2[Channel].time = LocalTime(); + rfsns_theo_v2_t2[Channel].volt = Payload3; + rfsns_theo_v2_t2[Channel].temp = Payload1; + rfsns_theo_v2_t2[Channel].hum = Payload2; + break; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), + chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2); +} + +void RfSnsTheoV2Show(bool json) +{ + bool sensor_once = false; + + for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { + if (rfsns_theo_v2_t1[i].time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1); + char voltage[33]; + dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage); + + if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); + } + } else { + char temperature[33]; + dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); +#ifdef USE_DOMOTICZ + if ((0 == tele_period) && !sensor_once) { + DomoticzSensor(DZ_TEMP, temperature); + DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux); + sensor_once = true; + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor, rfsns_theo_v2_t1[i].lux); +#endif + } + } + } + } + + sensor_once = false; + for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { + if (rfsns_theo_v2_t2[i].time) { + char sensor[10]; + snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1); + char voltage[33]; + dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage); + + if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); + } + } else { + float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); + float humi = ConvertHumidity((float)rfsns_theo_v2_t2[i].hum / 100); + char temperature[33]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, humidity, voltage); + if ((0 == tele_period) && !sensor_once) { +#ifdef USE_DOMOTICZ + DomoticzTempHumSensor(temperature, humidity); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, temp); + KnxSensor(KNX_HUMIDITY, humi); +#endif + sensor_once = true; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, sensor, humidity); +#endif + } + } + } + } +} + +#endif + +#ifdef USE_ALECTO_V2 +# 392 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" +#define RFSNS_DKW2012_PULSECOUNT 176 +#define RFSNS_ACH2010_MIN_PULSECOUNT 160 +#define RFSNS_ACH2010_MAX_PULSECOUNT 160 + +#define D_ALECTOV2 "AlectoV2" + +const char kAlectoV2Directions[] PROGMEM = D_TX20_NORTH "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" + D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST "|" + D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST "|" + D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; + +typedef struct { + uint32_t time; + float temp; + float rain; + float wind; + float gust; + uint8_t type; + uint8_t humi; + uint8_t wdir; +} alecto_v2_t; + +alecto_v2_t *rfsns_alecto_v2 = nullptr; +uint16_t rfsns_alecto_rain_base = 0; + +void RfSnsInitAlectoV2(void) +{ + rfsns_alecto_v2 = (alecto_v2_t*)malloc(sizeof(alecto_v2_t)); + rfsns_any_sensor++; +} + +void RfSnsAnalyzeAlectov2() +{ + if (!(((rfsns_raw_signal->Number >= RFSNS_ACH2010_MIN_PULSECOUNT) && + (rfsns_raw_signal->Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal->Number == RFSNS_DKW2012_PULSECOUNT))) { return; } + + uint8_t c = 0; + uint8_t rfbit; + uint8_t data[9] = { 0 }; + uint8_t msgtype = 0; + uint8_t rc = 0; + int temp; + uint8_t checksum = 0; + uint8_t checksumcalc = 0; + uint8_t maxidx = 8; + unsigned long atime; + float factor; + char buf1[16]; + + if (rfsns_raw_signal->Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; } + + uint8_t idx = maxidx; + for (uint32_t x = rfsns_raw_signal->Number; x > 0; x = x-2) { + if (rfsns_raw_signal->Pulses[x-1] * rfsns_raw_signal->Multiply < 0x300) { + rfbit = 0x80; + } else { + rfbit = 0; + } + data[idx] = (data[idx] >> 1) | rfbit; + c++; + if (c == 8) { + if (idx == 0) { break; } + c = 0; + idx--; + } + } + + checksum = data[maxidx]; + checksumcalc = RfSnsAlectoCRC8(data, maxidx); + + msgtype = (data[0] >> 4) & 0xf; + rc = (data[0] << 4) | (data[1] >> 4); + + if (checksum != checksumcalc) { return; } + if ((msgtype != 10) && (msgtype != 5)) { return; } + + rfsns_raw_signal->Repeats = 1; + + + + + + factor = 1.22; + + + + + + rfsns_alecto_v2->time = LocalTime(); + rfsns_alecto_v2->type = (RFSNS_DKW2012_PULSECOUNT == rfsns_raw_signal->Number); + rfsns_alecto_v2->temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10; + rfsns_alecto_v2->humi = data[3]; + uint16_t rain = (data[6] * 256) + data[7]; + + if (rain < rfsns_alecto_rain_base) { rfsns_alecto_rain_base = rain; } + if (rfsns_alecto_rain_base > 0) { + rfsns_alecto_v2->rain += ((float)rain - rfsns_alecto_rain_base) * 0.30; + } + rfsns_alecto_rain_base = rain; + rfsns_alecto_v2->wind = (float)data[4] * factor; + rfsns_alecto_v2->gust = (float)data[5] * factor; + if (rfsns_alecto_v2->type) { + rfsns_alecto_v2->wdir = data[8] & 0xf; + } + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), + checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); +} + +void RfSnsAlectoResetRain(void) +{ + if ((RtcTime.hour == 0) && (RtcTime.minute == 0) && (RtcTime.second == 5)) { + rfsns_alecto_v2->rain = 0; + } +} + + + + + + + +uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) +{ + uint8_t crc = 0; + while (len--) { + uint8_t inbyte = *addr++; + for (uint32_t i = 8; i; i--) { + uint8_t mix = (crc ^ inbyte) & 0x80; + crc <<= 1; + if (mix) { crc ^= 0x31; } + inbyte <<= 1; + } + } + return crc; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_ALECTOV2[] PROGMEM = + "{s}" D_ALECTOV2 " " D_RAIN "{m}%s " D_UNIT_MILLIMETER "{e}" + "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"; +const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = + "{s}" D_ALECTOV2 " " D_TX20_WIND_DIRECTION "{m}%s{e}"; +#endif + +void RfSnsAlectoV2Show(bool json) +{ + if (rfsns_alecto_v2->time) { + if (rfsns_alecto_v2->time < LocalTime() - RFSNS_VALID_WINDOW) { + if (json) { + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), GetDT(rfsns_alecto_v2->time).c_str()); + } + } else { + float temp = ConvertTemp(rfsns_alecto_v2->temp); + char temperature[33]; + dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); + float humi = ConvertHumidity((float)rfsns_alecto_v2->humi); + char humidity[33]; + dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); + char rain[33]; + dtostrfd(rfsns_alecto_v2->rain, 2, rain); + char wind[33]; + dtostrfd(rfsns_alecto_v2->wind, 2, wind); + char gust[33]; + dtostrfd(rfsns_alecto_v2->gust, 2, gust); + char wdir[4]; + char direction[20]; + if (rfsns_alecto_v2->type) { + GetTextIndexed(wdir, sizeof(wdir), rfsns_alecto_v2->wdir, kAlectoV2Directions); + snprintf_P(direction, sizeof(direction), PSTR(",\"Direction\":\"%s\""), wdir); + } + + if (json) { + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), + temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); + if (0 == tele_period) { +#ifdef USE_DOMOTICZ + + + + +#endif + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, D_ALECTOV2, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, D_ALECTOV2, humidity); + WSContentSend_PD(HTTP_SNS_ALECTOV2, rain, wind, gust); + if (rfsns_alecto_v2->type) { + WSContentSend_PD(HTTP_SNS_ALECTOV2_WDIR, wdir); + } +#endif + } + } + } +} +#endif + +void RfSnsInit(void) +{ + rfsns_raw_signal = (raw_signal_t*)(malloc(sizeof(raw_signal_t))); + if (rfsns_raw_signal) { + memset(rfsns_raw_signal, 0, sizeof(raw_signal_t)); +#ifdef USE_THEO_V2 + RfSnsInitTheoV2(); +#endif +#ifdef USE_ALECTO_V2 + RfSnsInitAlectoV2(); +#endif + if (rfsns_any_sensor) { + rfsns_rf_bit = digitalPinToBitMask(pin[GPIO_RF_SENSOR]); + rfsns_rf_port = digitalPinToPort(pin[GPIO_RF_SENSOR]); + pinMode(pin[GPIO_RF_SENSOR], INPUT); + } else { + free(rfsns_raw_signal); + rfsns_raw_signal = nullptr; + } + } +} + +void RfSnsAnalyzeRawSignal(void) +{ + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal->Number); + +#ifdef USE_THEO_V2 + RfSnsAnalyzeTheov2(); +#endif +#ifdef USE_ALECTO_V2 + RfSnsAnalyzeAlectov2(); +#endif +} + +void RfSnsEverySecond(void) +{ +#ifdef USE_ALECTO_V2 + RfSnsAlectoResetRain(); +#endif +} + +void RfSnsShow(bool json) +{ +#ifdef USE_THEO_V2 + RfSnsTheoV2Show(json); +#endif +#ifdef USE_ALECTO_V2 + RfSnsAlectoV2Show(json); +#endif +} + + + + + +bool Xsns37(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_RF_SENSOR] < 99) && (FUNC_INIT == function)) { + RfSnsInit(); + } + else if (rfsns_raw_signal) { + switch (function) { + case FUNC_LOOP: + if ((*portInputRegister(rfsns_rf_port) &rfsns_rf_bit) == rfsns_rf_bit) { + if (RfSnsFetchSignal(pin[GPIO_RF_SENSOR], HIGH)) { + RfSnsAnalyzeRawSignal(); + } + } + sleep = 0; + break; + case FUNC_EVERY_SECOND: + RfSnsEverySecond(); + break; + case FUNC_JSON_APPEND: + RfSnsShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + RfSnsShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_38_az7798.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_38_az7798.ino" +#ifdef USE_AZ7798 + +#define XSNS_38 38 +# 112 "S:/Development/Tasmota/tasmota/xsns_38_az7798.ino" +#include + +#ifndef CO2_LOW +#define CO2_LOW 800 +#endif +#ifndef CO2_HIGH +#define CO2_HIGH 1200 +#endif + +#define AZ_READ_TIMEOUT 400 + +#define AZ_CLOCK_UPDATE_INTERVAL (24UL * 60 * 60) +#define AZ_EPOCH (946684800UL) + +TasmotaSerial *AzSerial; + +const char ktype[] = "AZ7798"; +uint8_t az_type = 1; +uint16_t az_co2 = 0; +double az_temperature = 0; +double az_humidity = 0; +uint8_t az_received = 0; +uint8_t az_state = 0; +unsigned long az_clock_update = 10; + + + +void AzEverySecond(void) +{ + unsigned long start = millis(); + + az_state++; + if (5 == az_state) { + az_state = 0; + + AzSerial->flush(); + AzSerial->write(":\r", 2); + az_received = 0; + + uint8_t az_response[32]; + uint8_t counter = 0; + uint8_t i, j; + uint8_t response_substr[16]; + + do { + if (AzSerial->available() > 0) { + az_response[counter] = AzSerial->read(); + if(az_response[counter] == 0x0d) { az_received = 1; } + counter++; + } else { + delay(5); + } + } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received); + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, az_response, counter); + + if (!az_received) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout")); + return; + } + + i = 0; + while((az_response[i] != 'T') && (i < counter)) {i++;} + if(az_response[i] != 'T') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find start of response")); + return; + } + i++; + j = 0; + + while((az_response[i] != 'C') && (az_response[i] != 'F') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if((az_response[i] != 'C') && (az_response[i] != 'F')){ + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of temperature")); + return; + } + response_substr[j] = 0; + az_temperature = CharToFloat((char*)response_substr); + if(az_response[i] == 'C') { + az_temperature = ConvertTemp((float)az_temperature); + } else { + az_temperature = ConvertTemp((az_temperature - 32) / 1.8); + } + i++; + if(az_response[i] != ':') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error first delimiter")); + return; + } + i++; + if(az_response[i] != 'C') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of CO2")); + return; + } + i++; + j = 0; + + while((az_response[i] != 'p') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if(az_response[i] != 'p') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of CO2")); + return; + } + response_substr[j] = 0; + az_co2 = atoi((char*)response_substr); + LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); + i += 3; + if(az_response[i] != ':') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter")); + return; + } + i++; + if(az_response[i] != 'H') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of humidity")); + return; + } + i++; + j = 0; + + while((az_response[i] != '%') && (i < counter)) { + response_substr[j++] = az_response[i++]; + } + if(az_response[i] != '%') { + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of humidity")); + return; + } + response_substr[j] = 0; + az_humidity = ConvertHumidity(CharToFloat((char*)response_substr)); + } + + + if ((az_clock_update == 0) && (LocalTime() > AZ_EPOCH)) { + char tmpString[16]; + sprintf(tmpString, "C %d\r", (int)(LocalTime() - AZ_EPOCH)); + AzSerial->write(tmpString); + + do { + if (AzSerial->available() > 0) { + if(AzSerial->read() == 0x0d) { break; } + } else { + delay(5); + } + } while(((millis() - start) < AZ_READ_TIMEOUT)); + az_clock_update = AZ_CLOCK_UPDATE_INTERVAL; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 clock updated")); + } else { + az_clock_update--; + } +} + + + +void AzInit(void) +{ + az_type = 0; + if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) { + AzSerial = new TasmotaSerial(pin[GPIO_AZ_RXD], pin[GPIO_AZ_TXD], 1); + if (AzSerial->begin(9600)) { + if (AzSerial->hardwareSerial()) { ClaimSerial(); } + az_type = 1; + } + } +} + +void AzShow(bool json) +{ + char temperature[33]; + dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), ktype, az_co2, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2, ktype, az_co2); + WSContentSend_PD(HTTP_SNS_TEMP, ktype, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, ktype, humidity); +#endif + } +} + + + + + +bool Xsns38(uint8_t function) +{ + bool result = false; + + if(az_type){ + switch (function) { + case FUNC_INIT: + AzInit(); + break; + case FUNC_EVERY_SECOND: + AzEverySecond(); + break; + case FUNC_JSON_APPEND: + AzShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AzShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_39_max31855.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_39_max31855.ino" +#ifdef USE_MAX31855 + +#define XSNS_39 39 + +bool initialized = false; + +struct MAX31855_ResultStruct{ + uint8_t ErrorCode; + float ProbeTemperature; + float ReferenceTemperature; +} MAX31855_Result; + +void MAX31855_Init(void){ + if(initialized) + return; + + + pinMode(pin[GPIO_MAX31855CS], OUTPUT); + pinMode(pin[GPIO_MAX31855CLK], OUTPUT); + pinMode(pin[GPIO_MAX31855DO], INPUT); + + + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + + initialized = true; +} + + + + + +void MAX31855_GetResult(void){ + int32_t RawData = MAX31855_ShiftIn(32); + uint8_t probeerror = RawData & 0x7; + + MAX31855_Result.ErrorCode = probeerror; + MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); + if(probeerror) + MAX31855_Result.ProbeTemperature = NAN; + else + MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); +} + + + + + + +float MAX31855_GetProbeTemperature(int32_t RawData){ + if(RawData & 0x80000000) + RawData = (RawData >> 18) | 0xFFFFC000; + else + RawData >>= 18; + + float result = (RawData * 0.25); + + return ConvertTemp(result); +} + + + + + +float MAX31855_GetReferenceTemperature(int32_t RawData){ + if(RawData & 0x8000) + RawData = (RawData >> 4) | 0xFFFFF000; + else + RawData = (RawData >> 4) & 0x00000FFF; + + float result = (RawData * 0.0625); + + return ConvertTemp(result); +} + + + + + +int32_t MAX31855_ShiftIn(uint8_t Length){ + int32_t dataIn = 0; + + digitalWrite(pin[GPIO_MAX31855CS], LOW); + delayMicroseconds(1); + + for (uint32_t i = 0; i < Length; i++) + { + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + delayMicroseconds(1); + dataIn <<= 1; + if(digitalRead(pin[GPIO_MAX31855DO])) + dataIn |= 1; + digitalWrite(pin[GPIO_MAX31855CLK], HIGH); + delayMicroseconds(1); + } + + digitalWrite(pin[GPIO_MAX31855CS], HIGH); + digitalWrite(pin[GPIO_MAX31855CLK], LOW); + return dataIn; +} + +void MAX31855_Show(bool Json){ + char probetemp[33]; + char referencetemp[33]; + dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); + dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); + + if(Json){ + ResponseAppend_P(PSTR(",\"MAX31855\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + probetemp, referencetemp, MAX31855_Result.ErrorCode); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, probetemp); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, MAX31855_Result.ProbeTemperature); + } +#endif + } else { +#ifdef USE_WEBSERVER + WSContentSend_PD(HTTP_SNS_TEMP, "MAX31855", probetemp, TempUnit()); +#endif + } +} + + + + + +bool Xsns39(uint8_t function) +{ + bool result = false; + if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ + + switch (function) { + case FUNC_INIT: + MAX31855_Init(); + break; + case FUNC_EVERY_SECOND: + MAX31855_GetResult(); + break; + case FUNC_JSON_APPEND: + MAX31855_Show(true); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MAX31855_Show(false); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_40_pn532.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_40_pn532.ino" +#ifdef USE_PN532_HSU + +#define XSNS_40 40 + +#include + +TasmotaSerial *PN532_Serial; + +#define PN532_INVALID_ACK -1 +#define PN532_TIMEOUT -2 +#define PN532_INVALID_FRAME -3 +#define PN532_NO_SPACE -4 + +#define PN532_PREAMBLE 0x00 +#define PN532_STARTCODE1 0x00 +#define PN532_STARTCODE2 0xFF +#define PN532_POSTAMBLE 0x00 + +#define PN532_HOSTTOPN532 0xD4 +#define PN532_PN532TOHOST 0xD5 + +#define PN532_ACK_WAIT_TIME 0x0A + +#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 +#define PN532_COMMAND_SAMCONFIGURATION 0x14 +#define PN532_COMMAND_RFCONFIGURATION 0x32 +#define PN532_COMMAND_INDATAEXCHANGE 0x40 +#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A + +#define PN532_MIFARE_ISO14443A 0x00 +#define MIFARE_CMD_READ 0x30 +#define MIFARE_CMD_AUTH_A 0x60 +#define MIFARE_CMD_AUTH_B 0x61 +#define MIFARE_CMD_WRITE 0xA0 + +uint8_t pn532_model = 0; +uint8_t pn532_command = 0; +uint8_t pn532_scantimer = 0; + +uint8_t pn532_packetbuffer[64]; + +#ifdef USE_PN532_DATA_FUNCTION +uint8_t pn532_function = 0; +uint8_t pn532_newdata[16]; +uint8_t pn532_newdata_len = 0; +#endif + +void PN532_Init(void) +{ + if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) { + PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1); + if (PN532_Serial->begin(115200)) { + if (PN532_Serial->hardwareSerial()) { ClaimSerial(); } + PN532_wakeup(); + uint32_t ver = PN532_getFirmwareVersion(); + if (ver) { + PN532_setPassiveActivationRetries(0xFF); + PN532_SAMConfig(); + pn532_model = 1; + AddLog_P2(LOG_LEVEL_INFO,"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); + } + } + } +} + +int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout) +{ + int read_bytes = 0; + int ret; + unsigned long start_millis; + while (read_bytes < len) { + start_millis = millis(); + do { + ret = PN532_Serial->read(); + if (ret >= 0) { + break; + } + } while((timeout == 0) || ((millis()- start_millis ) < timeout)); + + if (ret < 0) { + if (read_bytes) { + return read_bytes; + } else { + return PN532_TIMEOUT; + } + } + buf[read_bytes] = (uint8_t)ret; + read_bytes++; + } + return read_bytes; +} + +int8_t PN532_readAckFrame(void) +{ + const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; + uint8_t ackBuf[sizeof(PN532_ACK)]; + + if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) { + return PN532_TIMEOUT; + } + + if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) { + return PN532_INVALID_ACK; + } + return 0; +} + +int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) +{ + + PN532_Serial->flush(); + + pn532_command = header[0]; + PN532_Serial->write((uint8_t)PN532_PREAMBLE); + PN532_Serial->write((uint8_t)PN532_STARTCODE1); + PN532_Serial->write(PN532_STARTCODE2); + + uint8_t length = hlen + blen + 1; + PN532_Serial->write(length); + PN532_Serial->write(~length + 1); + + PN532_Serial->write(PN532_HOSTTOPN532); + uint8_t sum = PN532_HOSTTOPN532; + + PN532_Serial->write(header, hlen); + for (uint32_t i = 0; i < hlen; i++) { + sum += header[i]; + } + + PN532_Serial->write(body, blen); + for (uint32_t i = 0; i < blen; i++) { + sum += body[i]; + } + + uint8_t checksum = ~sum + 1; + PN532_Serial->write(checksum); + PN532_Serial->write((uint8_t)PN532_POSTAMBLE); + + return PN532_readAckFrame(); +} + +int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50) +{ + uint8_t tmp[3]; + + + if (PN532_receive(tmp, 3, timeout)<=0) { + return PN532_TIMEOUT; + } + if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) { + return PN532_INVALID_FRAME; + } + + + uint8_t length[2]; + if (PN532_receive(length, 2, timeout) <= 0) { + return PN532_TIMEOUT; + } + + if (0 != (uint8_t)(length[0] + length[1])) { + return PN532_INVALID_FRAME; + } + length[0] -= 2; + if (length[0] > len) { + return PN532_NO_SPACE; + } + + + uint8_t cmd = pn532_command + 1; + if (PN532_receive(tmp, 2, timeout) <= 0) { + return PN532_TIMEOUT; + } + if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { + return PN532_INVALID_FRAME; + } + + if (PN532_receive(buf, length[0], timeout) != length[0]) { + return PN532_TIMEOUT; + } + + uint8_t sum = PN532_PN532TOHOST + cmd; + for (uint32_t i=0; i status) { + return 0; + } + + response = pn532_packetbuffer[0]; + response <<= 8; + response |= pn532_packetbuffer[1]; + response <<= 8; + response |= pn532_packetbuffer[2]; + response <<= 8; + response |= pn532_packetbuffer[3]; + + return response; +} + +void PN532_wakeup(void) +{ + uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 }; + PN532_Serial->write(wakeup,sizeof(wakeup)); + + + PN532_Serial->flush(); +} + +bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50) +{ + pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = cardbaudrate; + if (PN532_writeCommand(pn532_packetbuffer, 3)) { + return 0x0; + } + + if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { + return 0x0; + } +# 274 "S:/Development/Tasmota/tasmota/xsns_40_pn532.ino" + if (pn532_packetbuffer[0] != 1) { + return 0; + } + + uint16_t sens_res = pn532_packetbuffer[2]; + sens_res <<= 8; + sens_res |= pn532_packetbuffer[3]; + + + *uidLength = pn532_packetbuffer[5]; + + for (uint32_t i = 0; i < pn532_packetbuffer[5]; i++) { + uid[i] = pn532_packetbuffer[6 + i]; + } + + return 1; +} + +bool PN532_setPassiveActivationRetries(uint8_t maxRetries) +{ + pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; + pn532_packetbuffer[1] = 5; + pn532_packetbuffer[2] = 0xFF; + pn532_packetbuffer[3] = 0x01; + pn532_packetbuffer[4] = maxRetries; + if (PN532_writeCommand(pn532_packetbuffer, 5)) { + return 0; + } + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +bool PN532_SAMConfig(void) +{ + pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; + pn532_packetbuffer[1] = 0x01; + pn532_packetbuffer[2] = 0x14; + pn532_packetbuffer[3] = 0x00; + if (PN532_writeCommand(pn532_packetbuffer, 4)) { + return false; + } + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +#ifdef USE_PN532_DATA_FUNCTION + +uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) +{ + uint8_t i; + uint8_t _key[6]; + uint8_t _uid[7]; + uint8_t _uidLen; + + + memcpy(&_key, keyData, 6); + memcpy(&_uid, uid, uidLen); + _uidLen = uidLen; + + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; + pn532_packetbuffer[3] = blockNumber; + memcpy(&pn532_packetbuffer[4], &_key, 6); + for (i = 0; i < _uidLen; i++) { + pn532_packetbuffer[10 + i] = _uid[i]; + } + + if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; } + + + PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + + + + if (pn532_packetbuffer[0] != 0x00) { + + return 0; + } + + return 1; +} + +uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) +{ + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = MIFARE_CMD_READ; + pn532_packetbuffer[3] = blockNumber; + + + if (PN532_writeCommand(pn532_packetbuffer, 4)) { + return 0; + } + + + PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); + + + if (pn532_packetbuffer[0] != 0x00) { + return 0; + } + + + + memcpy (data, &pn532_packetbuffer[1], 16); + + return 1; +} + +uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) +{ + + pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; + pn532_packetbuffer[1] = 1; + pn532_packetbuffer[2] = MIFARE_CMD_WRITE; + pn532_packetbuffer[3] = blockNumber; + memcpy(&pn532_packetbuffer[4], data, 16); + + + if (PN532_writeCommand(pn532_packetbuffer, 20)) { + return 0; + } + + + return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); +} + +#endif + +void PN532_ScanForTag(void) +{ + if (!pn532_model) { return; } + uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; + uint8_t uid_len = 0; + uint8_t card_data[16]; + bool erase_success = false; + bool set_success = false; + if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { + char uids[15]; + +#ifdef USE_PN532_DATA_FUNCTION + char card_datas[34]; +#endif + + ToHex_P((unsigned char*)uid, uid_len, uids, sizeof(uids)); + +#ifdef USE_PN532_DATA_FUNCTION + if (uid_len == 4) { + uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { + if (mifareclassic_ReadDataBlock(1, card_data)) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_datas,&card_data,sizeof(card_data)); +#else + for (uint32_t i = 0;i < sizeof(card_data);i++) { + if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { + card_datas[i] = char(card_data[i]); + } else { + card_datas[i] = '\0'; + } + } +#endif + } + if (pn532_function == 1) { + for (uint32_t i = 0;i<16;i++) { + card_data[i] = 0x00; + } + if (mifareclassic_WriteDataBlock(1, card_data)) { + erase_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase success")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } + } + if (pn532_function == 2) { +#ifdef USE_PN532_DATA_RAW + memcpy(&card_data,&pn532_newdata,sizeof(card_data)); + if (mifareclassic_WriteDataBlock(1, card_data)) { + set_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } +#else + bool IsAlphaNumeric = true; + for (uint32_t i = 0;i < pn532_newdata_len;i++) { + if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) { + IsAlphaNumeric = false; + } + } + if (IsAlphaNumeric) { + memcpy(&card_data,&pn532_newdata,pn532_newdata_len); + card_data[pn532_newdata_len] = '\0'; + if (mifareclassic_WriteDataBlock(1, card_data)) { + set_success = true; + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); + memcpy(&card_datas,&card_data,sizeof(card_data)); + } + } else { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data must be alphanumeric")); + } +#endif + } + } else { + sprintf(card_datas,"AUTHFAIL"); + } + } + switch (pn532_function) { + case 0x01: + if (!erase_success) { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase fail - exiting erase mode")); + } + break; + case 0x02: + if (!set_success) { + AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Write failed - exiting set mode")); + } + default: + break; + } + pn532_function = 0; +#endif + +#ifdef USE_PN532_DATA_FUNCTION + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); +#else + ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); +#endif + + MqttPublishTeleSensor(); + +#ifdef USE_PN532_CAUSE_EVENTS + + char command[71]; +#ifdef USE_PN532_DATA_FUNCTION + sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); +#else + sprintf(command,"event PN532_UID=%s",uids); +#endif + ExecuteCommand(command, SRC_RULE); +#endif + + pn532_scantimer = 7; + } +} + +#ifdef USE_PN532_DATA_FUNCTION + +bool PN532_Command(void) +{ + bool serviced = true; + uint8_t paramcount = 0; + if (XdrvMailbox.data_len > 0) { + paramcount=1; + } else { + serviced = false; + return serviced; + } + char sub_string[XdrvMailbox.data_len]; + char sub_string_tmp[XdrvMailbox.data_len]; + for (uint32_t ca=0;ca 1) { + if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') { + serviced = false; + return serviced; + } + sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); + pn532_newdata_len = strlen(sub_string_tmp); + if (pn532_newdata_len > 15) { pn532_newdata_len = 15; } + memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len); + pn532_newdata[pn532_newdata_len] = 0x00; + pn532_function = 2; + AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); + ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}")); + return serviced; + } + } +} + +#endif + +bool Xsns40(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_INIT: + PN532_Init(); + result = true; + break; + case FUNC_EVERY_50_MSECOND: + break; + case FUNC_EVERY_100_MSECOND: + break; + case FUNC_EVERY_250_MSECOND: + if (pn532_scantimer > 0) { + pn532_scantimer--; + } else { + PN532_ScanForTag(); + } + break; + case FUNC_EVERY_SECOND: + break; +#ifdef USE_PN532_DATA_FUNCTION + case FUNC_COMMAND_SENSOR: + if (XSNS_40 == XdrvMailbox.index) { + result = PN532_Command(); + } + break; +#endif + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_41_max44009.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_41_max44009.ino" +#ifdef USE_I2C +#ifdef USE_MAX44009 + + + + + + +#define XSNS_41 41 +#define XI2C_28 28 + +#define MAX44009_ADDR1 0x4A +#define MAX44009_ADDR2 0x4B +#define MAX44009_NO_REGISTERS 8 +#define REG_CONFIG 0x02 +#define REG_LUMINANCE 0x03 +#define REG_LOWER_THRESHOLD 0x06 +#define REG_THRESHOLD_TIMER 0x07 + +#define MAX44009_CONTINUOUS_AUTO_MODE 0x80 + +uint8_t max44009_address; +uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2, 0 }; +uint8_t max44009_found = 0; +uint8_t max44009_valid = 0; +float max44009_illuminance = 0; +char max44009_types[] = "MAX44009"; + +bool Max4409Read_lum(void) +{ + max44009_valid = 0; + uint8_t regdata[2]; + + + if (I2cValidRead16((uint16_t *)®data, max44009_address, REG_LUMINANCE)) { + int exponent = (regdata[0] & 0xF0) >> 4; + int mantissa = ((regdata[0] & 0x0F) << 4) | (regdata[1] & 0x0F); + max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); + max44009_valid = 1; + return true; + } else { + return false; + } +} + + + +void Max4409Detect(void) +{ + uint8_t buffer1; + uint8_t buffer2; + for (uint32_t i = 0; 0 != max44009_addresses[i]; i++) { + + max44009_address = max44009_addresses[i]; + if (I2cActive(max44009_address)) { continue; } + + if ((I2cValidRead8(&buffer1, max44009_address, REG_LOWER_THRESHOLD)) && + (I2cValidRead8(&buffer2, max44009_address, REG_THRESHOLD_TIMER))) { + + if ((0x00 == buffer1) && + (0xFF == buffer2)) { + + + + Wire.beginTransmission(max44009_address); + + + Wire.write(REG_CONFIG); + Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); + if (0 == Wire.endTransmission()) { + I2cSetActiveFound(max44009_address, max44009_types); + max44009_found = 1; + break; + } + } + } + } +} + +void Max4409EverySecond(void) +{ + Max4409Read_lum(); +} + +void Max4409Show(bool json) +{ + char illum_str[8]; + + if (max44009_valid) { + + + + uint8_t prec = 0; + if (10 > max44009_illuminance ) { + prec = 3; + } else if (100 > max44009_illuminance) { + prec = 2; + } else if (1000 > max44009_illuminance) { + prec = 1; + } + dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_ILLUMINANCE, illum_str); + } +#endif +#ifdef USE_WEBSERVER + } else { + + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, max44009_types, (int)max44009_illuminance); +#endif + } + } +} + + + + + +bool Xsns41(uint8_t function) +{ + if (!I2cEnabled(XI2C_28)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Max4409Detect(); + } + else if (max44009_found) { + switch (function) { + case FUNC_EVERY_SECOND: + Max4409EverySecond(); + break; + case FUNC_JSON_APPEND: + Max4409Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Max4409Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_42_scd30.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_42_scd30.ino" +#ifdef USE_I2C +#ifdef USE_SCD30 + +#define XSNS_42 42 +#define XI2C_29 29 + + + +#define SCD30_ADDRESS 0x61 + +#define SCD30_MAX_MISSED_READS 3 +#define SCD30_STATE_NO_ERROR 0 +#define SCD30_STATE_ERROR_DATA_CRC 1 +#define SCD30_STATE_ERROR_READ_MEAS 2 +#define SCD30_STATE_ERROR_SOFT_RESET 3 +#define SCD30_STATE_ERROR_I2C_RESET 4 +#define SCD30_STATE_ERROR_UNKNOWN 5 + +#include "Arduino.h" +#include + +#define D_CMND_SCD30 "SCD30" + +const char S_JSON_SCD30_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d}"; +const char S_JSON_SCD30_COMMAND_NFW_VALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d.%d}"; +const char S_JSON_SCD30_COMMAND[] PROGMEM = "{\"" D_CMND_SCD30 "%s\"}"; +const char kSCD30_Commands[] PROGMEM = "Alt|Auto|Cal|FW|Int|Pres|TOff"; + + + + + +enum SCD30_Commands { + CMND_SCD30_ALTITUDE, + CMND_SCD30_AUTOMODE, + CMND_SCD30_CALIBRATE, + CMND_SCD30_FW, + CMND_SCD30_INTERVAL, + CMND_SCD30_PRESSURE, + CMND_SCD30_TEMPOFFSET +}; + +FrogmoreScd30 scd30; + +bool scd30Found = false; +bool scd30IsDataValid = false; +int scd30ErrorState = SCD30_STATE_NO_ERROR; +uint16_t scd30Interval_sec; +int scd30Loop_count = 0; +int scd30DataNotAvailable_count = 0; +int scd30GoodMeas_count = 0; +int scd30Reset_count = 0; +int scd30CrcError_count = 0; +int scd30Co2Zero_count = 0; +int i2cReset_count = 0; +uint16_t scd30_CO2 = 0; +uint16_t scd30_CO2EAvg = 0; +float scd30_Humid = 0.0; +float scd30_Temp = 0.0; + +void Scd30Detect(void) +{ + if (I2cActive(SCD30_ADDRESS)) { return; } + + scd30.begin(); + + uint8_t major = 0; + uint8_t minor = 0; + if (scd30.getFirmwareVersion(&major, &minor)) { return; } + uint16_t interval_sec; + if (scd30.getMeasurementInterval(&scd30Interval_sec)) { return; } + if (scd30.beginMeasuring()) { return; } + + I2cSetActiveFound(SCD30_ADDRESS, "SCD30"); + scd30Found = true; + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SCD: FW v%d.%d"), major, minor); +} + + +void Scd30Update(void) +{ + scd30Loop_count++; + if (scd30Loop_count > (scd30Interval_sec - 1)) { + int error = 0; + switch (scd30ErrorState) { + case SCD30_STATE_NO_ERROR: { + error = scd30.readMeasurement(&scd30_CO2, &scd30_CO2EAvg, &scd30_Temp, &scd30_Humid); + switch (error) { + case ERROR_SCD30_NO_ERROR: + scd30Loop_count = 0; + scd30IsDataValid = true; + scd30GoodMeas_count++; + break; + + case ERROR_SCD30_NO_DATA: + scd30DataNotAvailable_count++; + break; + + case ERROR_SCD30_CRC_ERROR: + scd30ErrorState = SCD30_STATE_ERROR_DATA_CRC; + scd30CrcError_count++; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), + scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); +#endif + break; + + case ERROR_SCD30_CO2_ZERO: + scd30Co2Zero_count++; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), + scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); +#endif + break; + + default: { + scd30ErrorState = SCD30_STATE_ERROR_READ_MEAS; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, scd30Loop_count); +#endif + return; + } + break; + } + } + break; + + case SCD30_STATE_ERROR_DATA_CRC: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: got CRC error, try again, counter: %ld"), scd30Loop_count); +#endif + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + break; + + case SCD30_STATE_ERROR_READ_MEAS: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: not answering, sending soft reset, counter: %ld"), scd30Loop_count); +#endif + scd30Reset_count++; + error = scd30.softReset(); + if (error) { +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: resetting got error: 0x%lX"), error); +#endif + error >>= 8; + if (error == 4) { + scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; + } else { + scd30ErrorState = SCD30_STATE_ERROR_UNKNOWN; + } + } else { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + case SCD30_STATE_ERROR_SOFT_RESET: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), + scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); + AddLog_P(LOG_LEVEL_ERROR, PSTR("SCD30: clearing i2c bus")); +#endif + i2cReset_count++; + error = scd30.clearI2CBus(); + if (error) { + scd30ErrorState = SCD30_STATE_ERROR_I2C_RESET; +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error clearing i2c bus: 0x%lX"), error); +#endif + } else { + scd30ErrorState = ERROR_SCD30_NO_ERROR; + } + } + break; + + default: { + +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: unknown error state: 0x%lX"), scd30ErrorState); +#endif + scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; + } + } + + if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) { + scd30IsDataValid = false; + } + } +} + + +int Scd30GetCommand(int command_code, uint16_t *pvalue) +{ + switch (command_code) + { + case CMND_SCD30_ALTITUDE: + return scd30.getAltitudeCompensation(pvalue); + break; + + case CMND_SCD30_AUTOMODE: + return scd30.getCalibrationType(pvalue); + break; + + case CMND_SCD30_CALIBRATE: + return scd30.getForcedRecalibrationFactor(pvalue); + break; + + case CMND_SCD30_INTERVAL: + return scd30.getMeasurementInterval(pvalue); + break; + + case CMND_SCD30_PRESSURE: + return scd30.getAmbientPressure(pvalue); + break; + + case CMND_SCD30_TEMPOFFSET: + return scd30.getTemperatureOffset(pvalue); + break; + + default: + + break; + } +} + +int Scd30SetCommand(int command_code, uint16_t value) +{ + switch (command_code) + { + case CMND_SCD30_ALTITUDE: + return scd30.setAltitudeCompensation(value); + break; + + case CMND_SCD30_AUTOMODE: + return scd30.setCalibrationType(value); + break; + + case CMND_SCD30_CALIBRATE: + return scd30.setForcedRecalibrationFactor(value); + break; + + case CMND_SCD30_INTERVAL: + { + int error = scd30.setMeasurementInterval(value); + if (!error) + { + scd30Interval_sec = value; + } + + return error; + } + break; + + case CMND_SCD30_PRESSURE: + return scd30.setAmbientPressure(value); + break; + + case CMND_SCD30_TEMPOFFSET: + return scd30.setTemperatureOffset(value); + break; + + default: + + break; + } +} + + + + + +bool Scd30CommandSensor() +{ + char command[CMDSZ]; + bool serviced = true; + uint8_t prefix_len = strlen(D_CMND_SCD30); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_SCD30), prefix_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + prefix_len, kSCD30_Commands); + + switch (command_code) { + case CMND_SCD30_ALTITUDE: + case CMND_SCD30_AUTOMODE: + case CMND_SCD30_CALIBRATE: + case CMND_SCD30_INTERVAL: + case CMND_SCD30_PRESSURE: + case CMND_SCD30_TEMPOFFSET: + { + uint16_t value = 0; + if (XdrvMailbox.data_len > 0) + { + value = XdrvMailbox.payload; + Scd30SetCommand(command_code, value); + } + else + { + Scd30GetCommand(command_code, &value); + } + + Response_P(S_JSON_SCD30_COMMAND_NVALUE, command, value); + } + break; + + case CMND_SCD30_FW: + { + uint8_t major = 0; + uint8_t minor = 0; + int error; + error = scd30.getFirmwareVersion(&major, &minor); + if (error) + { +#ifdef SCD30_DEBUG + AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error getting FW version: 0x%lX"), error); +#endif + serviced = false; + } + else + { + Response_P(S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); + } + } + break; + + default: + + serviced = false; + break; + } + } + return serviced; +} + +void Scd30Show(bool json) +{ + if (scd30IsDataValid) + { + char humidity[10]; + dtostrfd(ConvertHumidity(scd30_Humid), Settings.flag2.humidity_resolution, humidity); + char temperature[10]; + dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); + + if (json) { + + ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), + scd30_CO2, scd30_CO2EAvg, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) + { + DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); + WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); + WSContentSend_PD(HTTP_SNS_TEMP, "SCD30", temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, "SCD30", humidity); +#endif + } + } +} + + + + + +bool Xsns42(byte function) +{ + if (!I2cEnabled(XI2C_29)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Scd30Detect(); + } + else if (scd30Found) { + switch (function) { + case FUNC_EVERY_SECOND: + Scd30Update(); + break; + case FUNC_COMMAND: + result = Scd30CommandSensor(); + break; + case FUNC_JSON_APPEND: + Scd30Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Scd30Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_43_hre.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_43_hre.ino" +#ifdef USE_HRE +# 49 "S:/Development/Tasmota/tasmota/xsns_43_hre.ino" +#define XSNS_43 43 + +enum hre_states { + hre_idle, + hre_sync, + hre_syncing, + hre_read, + hre_reading, + hre_sleep, + hre_sleeping +}; + +hre_states hre_state = hre_idle; + +float hre_usage = 0; +float hre_rate = 0; +uint32_t hre_usage_time = 0; + +int hre_read_errors = 0; +bool hre_good = false; + + + +int hreReadBit() +{ + digitalWrite(pin[GPIO_HRE_CLOCK], HIGH); + delay(1); + int bit = digitalRead(pin[GPIO_HRE_DATA]); + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + delay(1); + return bit; +} + + + +char hreReadChar(int &parity_errors) +{ + + hreReadBit(); + + unsigned ch=0; + int sum=0; + for (uint32_t i=0; i<7; i++) + { + int b = hreReadBit(); + ch |= b << i; + sum += b; + } + + + if ( (sum & 0x1) != hreReadBit()) + parity_errors++; + + + hreReadBit(); + + return ch; +} + +void hreInit(void) +{ + hre_read_errors = 0; + hre_good = false; + + pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); + pinMode(pin[GPIO_HRE_DATA], INPUT); + + + + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + + hre_state = hre_sync; +} + + +void hreEvery50ms(void) +{ + static int sync_counter = 0; + static int sync_run = 0; + + static uint32_t curr_start = 0; + static int read_counter = 0; + static int parity_errors = 0; + static char buff[46]; + + static char ch; + static size_t i; + + switch (hre_state) + { + case hre_sync: + if (uptime < 10) + break; + sync_run = 0; + sync_counter = 0; + hre_state = hre_syncing; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); + break; + + case hre_syncing: + + + for (uint32_t i=0; i<20; i++) + { + if (hreReadBit()) + sync_run++; + else + sync_run = 0; + if (sync_run == 62) + { + hre_state = hre_read; + break; + } + sync_counter++; + } + + if (sync_counter > 1000) + { + hre_state = hre_sleep; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE D_ERROR)); + } + break; + + + case hre_read: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); + read_counter = 0; + parity_errors = 0; + curr_start = uptime; + memset(buff, 0, sizeof(buff)); + hre_state = hre_reading; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); + + + + + + case hre_reading: + + buff[read_counter++] = hreReadChar(parity_errors); + buff[read_counter++] = hreReadChar(parity_errors); + + if (read_counter == 46) + { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), + parity_errors, hre_read_errors, buff); + if (parity_errors == 0) + { + float curr_usage; + curr_usage = 0.01 * atol(buff+24); + if (hre_usage_time) + { + double dt = 1.666e-2 * (curr_start - hre_usage_time); + hre_rate = (curr_usage - hre_usage)/dt; + } + hre_usage = curr_usage; + hre_usage_time = curr_start; + hre_good = true; + + hre_state = hre_sleep; + } + else + { + hre_read_errors++; + hre_state = hre_sleep; + } + } + break; + + case hre_sleep: + hre_usage_time = curr_start; + hre_state = hre_sleeping; + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_sleeping")); + + case hre_sleeping: + + + if (uptime - hre_usage_time >= 27) + hre_state = hre_sync; + } +} + +void hreShow(boolean json) +{ + if (!hre_good) + return; + + const char *id = "HRE"; + + char usage[16]; + char rate[16]; + dtostrfd(hre_usage, 2, usage); + dtostrfd(hre_rate, 3, rate); + + if (json) + { + ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_GALLONS, id, usage); + WSContentSend_PD(HTTP_SNS_GPM, id, rate); +#endif + } +} + + + + + +bool Xsns43(byte function) +{ + + if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) + return false; + + switch (function) + { + case FUNC_INIT: + hreInit(); + break; + case FUNC_EVERY_50_MSECOND: + hreEvery50ms(); + break; + case FUNC_EVERY_SECOND: + break; + case FUNC_JSON_APPEND: + hreShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + hreShow(0); + break; +#endif + } + return false; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_44_sps30.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_44_sps30.ino" +#ifdef USE_I2C +#ifdef USE_SPS30 + +#define XSNS_44 44 +#define XI2C_30 30 + +#define SPS30_ADDR 0x69 + +#include +#include + +uint8_t sps30_ready = 0; +uint8_t sps30_running; + +struct SPS30 { + float PM1_0; + float PM2_5; + float PM4_0; + float PM10; + float NCPM0_5; + float NCPM1_0; + float NCPM2_5; + float NCPM4_0; + float NCPM10; + float TYPSIZ; +} sps30_result; + +#define SPS_CMD_START_MEASUREMENT 0x0010 +#define SPS_CMD_START_MEASUREMENT_ARG 0x0300 +#define SPS_CMD_STOP_MEASUREMENT 0x0104 +#define SPS_CMD_READ_MEASUREMENT 0x0300 +#define SPS_CMD_GET_DATA_READY 0x0202 +#define SPS_CMD_AUTOCLEAN_INTERVAL 0x8004 +#define SPS_CMD_CLEAN 0x5607 +#define SPS_CMD_GET_ACODE 0xd025 +#define SPS_CMD_GET_SERIAL 0xd033 +#define SPS_CMD_RESET 0xd304 +#define SPS_WRITE_DELAY_US 20000 +#define SPS_MAX_SERIAL_LEN 32 + +uint8_t sps30_calc_CRC(uint8_t *data) { + uint8_t crc = 0xFF; + for (uint32_t i = 0; i < 2; i++) { + crc ^= data[i]; + for (uint32_t bit = 8; bit > 0; --bit) { + if(crc & 0x80) { + crc = (crc << 1) ^ 0x31u; + } else { + crc = (crc << 1); + } + } + } + return crc; +} + +void CmdClean(void); + +unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop); + +void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen) { +unsigned char cmdb[2]; +uint8_t tmp[3]; +uint8_t index=0; +memset(data,0,dlen); +uint8_t twi_buff[64]; + + Wire.beginTransmission(SPS30_ADDR); + cmdb[0]=cmd>>8; + cmdb[1]=cmd; + Wire.write(cmdb,2); + Wire.endTransmission(); + + + dlen/=2; + dlen*=3; + + twi_readFrom(SPS30_ADDR,twi_buff,dlen,1); + + uint8_t bind=0; + while (bind>8; + cmdb[1]=cmd; + + if (cmd==SPS_CMD_START_MEASUREMENT) { + cmdb[2]=SPS_CMD_START_MEASUREMENT_ARG>>8; + cmdb[3]=SPS_CMD_START_MEASUREMENT_ARG&0xff; + cmdb[4]=sps30_calc_CRC(&cmdb[2]); + Wire.write(cmdb,5); + } else { + Wire.write(cmdb,2); + } + Wire.endTransmission(); +} + +void SPS30_Detect(void) +{ + if (!I2cSetDevice(SPS30_ADDR)) { return; } + I2cSetActiveFound(SPS30_ADDR, "SPS30"); + + uint8_t dcode[32]; + sps30_get_data(SPS_CMD_GET_SERIAL,dcode,sizeof(dcode)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("sps30 found with serial: %s"),dcode); + sps30_cmd(SPS_CMD_START_MEASUREMENT); + sps30_running = 1; + sps30_ready = 1; +} + +#define D_UNIT_PM "ug/m3" +#define D_UNIT_NCPM "#/m3" + +#ifdef USE_WEBSERVER +const char HTTP_SNS_SPS30_a[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_PM "{e}"; +const char HTTP_SNS_SPS30_b[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_NCPM "{e}"; +const char HTTP_SNS_SPS30_c[] PROGMEM ="{s}SPS30 " "TYPSIZ" "{m}%s " "um" "{e}"; +#endif + +#define PMDP 2 + +#define SPS30_HOURS Settings.sps30_inuse_hours + + + +void SPS30_Every_Second() { + if (!sps30_running) return; + + if (uptime%10==0) { + uint8_t vars[sizeof(float)*10]; + sps30_get_data(SPS_CMD_READ_MEASUREMENT,vars,sizeof(vars)); + float *fp=&sps30_result.PM1_0; + + typedef union { + uint8_t array[4]; + float value; + } ByteToFloat; + + ByteToFloat conv; + + for (uint32_t count=0; count<10; count++) { + for (uint32_t i = 0; i < 4; i++){ + conv.array[3-i] = vars[count*sizeof(float)+i]; + } + *fp++=conv.value; + } + } + + if (uptime%3600==0 && uptime>60) { + + + SPS30_HOURS++; + if (SPS30_HOURS>(7*24)) { + CmdClean(); + SPS30_HOURS=0; + } + } + +} + +void SPS30_Show(bool json) +{ + if (!sps30_running) { return; } + + char str[64]; + if (json) { + dtostrfd(sps30_result.PM1_0,PMDP,str); + ResponseAppend_P(PSTR(",\"SPS30\":{\"" "PM1_0" "\":%s"), str); + dtostrfd(sps30_result.PM2_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM2_5" "\":%s"), str); + dtostrfd(sps30_result.PM4_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM4_0" "\":%s"), str); + dtostrfd(sps30_result.PM10,PMDP,str); + ResponseAppend_P(PSTR(",\"" "PM10" "\":%s"), str); + dtostrfd(sps30_result.NCPM0_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM0_5" "\":%s"), str); + dtostrfd(sps30_result.NCPM1_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM1_0" "\":%s"), str); + dtostrfd(sps30_result.NCPM2_5,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM2_5" "\":%s"), str); + dtostrfd(sps30_result.NCPM4_0,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM4_0" "\":%s"), str); + dtostrfd(sps30_result.NCPM10,PMDP,str); + ResponseAppend_P(PSTR(",\"" "NCPM10" "\":%s"), str); + dtostrfd(sps30_result.TYPSIZ,PMDP,str); + ResponseAppend_P(PSTR(",\"" "TYPSIZ" "\":%s}"), str); + +#ifdef USE_WEBSERVER + } else { + dtostrfd(sps30_result.PM1_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 1.0",str); + dtostrfd(sps30_result.PM2_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 2.5",str); + dtostrfd(sps30_result.PM4_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 4.0",str); + dtostrfd(sps30_result.PM10,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 10",str); + dtostrfd(sps30_result.NCPM0_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 0.5",str); + dtostrfd(sps30_result.NCPM1_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 1.0",str); + dtostrfd(sps30_result.NCPM2_5,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 2.5",str); + dtostrfd(sps30_result.NCPM4_0,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 4.0",str); + dtostrfd(sps30_result.NCPM10,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 10",str); + dtostrfd(sps30_result.TYPSIZ,PMDP,str); + WSContentSend_PD(HTTP_SNS_SPS30_c,str); +#endif + } +} + +void CmdClean(void) +{ + sps30_cmd(SPS_CMD_CLEAN); + ResponseTime_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}")); + MqttPublishTeleSensor(); +} + +bool SPS30_cmd(void) +{ + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + char *cp=XdrvMailbox.data; + if (*cp=='c') { + + CmdClean(); + } else if (*cp=='0' || *cp=='1') { + sps30_running=*cp&1; + sps30_cmd(sps30_running?SPS_CMD_START_MEASUREMENT:SPS_CMD_STOP_MEASUREMENT); + } else { + serviced=false; + } + } + Response_P(PSTR("{\"SPS30\":\"%s\"}"), sps30_running?"running":"stopped"); + + return serviced; +} + + + + + +bool Xsns44(byte function) +{ + if (!I2cEnabled(XI2C_30)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + SPS30_Detect(); + } + else if (sps30_ready) { + switch (function) { + case FUNC_EVERY_SECOND: + SPS30_Every_Second(); + break; + case FUNC_JSON_APPEND: + SPS30_Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + SPS30_Show(0); + break; + #endif + case FUNC_COMMAND_SENSOR: + if (XSNS_44 == XdrvMailbox.index) { + result = SPS30_cmd(); + } + break; + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_45_vl53l0x.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_45_vl53l0x.ino" +#ifdef USE_I2C +#ifdef USE_VL53L0X + +#define XSNS_45 45 +#define XI2C_31 31 + +#include +#include "VL53L0X.h" +VL53L0X sensor; + +uint8_t vl53l0x_ready = 0; +uint16_t vl53l0x_distance; +uint16_t Vl53l0_buffer[5]; +uint8_t Vl53l0_index; + + + +void Vl53l0Detect(void) +{ + if (!I2cSetDevice(0x29)) { return; } + + if (!sensor.init()) { return; } + + I2cSetActiveFound(sensor.getAddress(), "VL53L0X"); + + sensor.setTimeout(500); + + + + + + sensor.startContinuous(); + vl53l0x_ready = 1; + + Vl53l0_index=0; +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_VL53L0X[] PROGMEM = + "{s}VL53L0X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; +#endif + +#define USE_VL_MEDIAN + +void Vl53l0Every_250MSecond(void) +{ + uint16_t tbuff[5],tmp; + uint8_t flag; + + + uint16_t dist = sensor.readRangeContinuousMillimeters(); + if (dist==0 || dist>2000) { + dist=9999; + } + +#ifdef USE_VL_MEDIAN + + Vl53l0_buffer[Vl53l0_index]=dist; + Vl53l0_index++; + if (Vl53l0_index>=5) Vl53l0_index=0; + + + memmove(tbuff,Vl53l0_buffer,sizeof(tbuff)); + for (byte ocnt=0; ocnt<5; ocnt++) { + flag=0; + for (byte count=0; count<4; count++) { + if (tbuff[count]>tbuff[count+1]) { + tmp=tbuff[count]; + tbuff[count]=tbuff[count+1]; + tbuff[count+1]=tmp; + flag=1; + } + } + if (!flag) break; + } + vl53l0x_distance=tbuff[2]; +#else + vl53l0x_distance=dist; +#endif +} + +void Vl53l0Show(boolean json) +{ + if (json) { + ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l0x_distance); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_VL53L0X, vl53l0x_distance); +#endif + } +} + + + + + +bool Xsns45(byte function) +{ + if (!I2cEnabled(XI2C_31)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Vl53l0Detect(); + } + else if (vl53l0x_ready) { + switch (function) { + case FUNC_EVERY_250_MSECOND: + Vl53l0Every_250MSecond(); + break; + case FUNC_JSON_APPEND: + Vl53l0Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Vl53l0Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_46_MLX90614.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_46_MLX90614.ino" +#ifdef USE_I2C +#ifdef USE_MLX90614 + +#define XSNS_46 46 +#define XI2C_32 32 + +#define I2_ADR_IRT 0x5a + +#define MLX90614_RAWIR1 0x04 +#define MLX90614_RAWIR2 0x05 +#define MLX90614_TA 0x06 +#define MLX90614_TOBJ1 0x07 +#define MLX90614_TOBJ2 0x08 + +struct { + union { + uint16_t value; + uint32_t i2c_buf; + }; + float obj_temp; + float amb_temp; + bool ready = false; +} mlx90614; + +void MLX90614_Init(void) +{ + if (!I2cSetDevice(I2_ADR_IRT)) { return; } + I2cSetActiveFound(I2_ADR_IRT, "MLX90614"); + mlx90614.ready = true; +} + +void MLX90614_Every_Second(void) +{ + mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT, MLX90614_TOBJ1); + if (mlx90614.value & 0x8000) { + mlx90614.obj_temp = -999; + } else { + mlx90614.obj_temp = ((float)mlx90614.value * 0.02) - 273.15; + } + mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT,MLX90614_TA); + if (mlx90614.value & 0x8000) { + mlx90614.amb_temp = -999; + } else { + mlx90614.amb_temp = ((float)mlx90614.value * 0.02) - 273.15; + } +} + +#ifdef USE_WEBSERVER + const char HTTP_IRTMP[] PROGMEM = + "{s}MXL90614 " "OBJ-" D_TEMPERATURE "{m}%s C" "{e}" + "{s}MXL90614 " "AMB-" D_TEMPERATURE "{m}%s C" "{e}"; +#endif + +void MLX90614_Show(uint8_t json) +{ + char obj_tstr[16]; + dtostrfd(mlx90614.obj_temp, Settings.flag2.temperature_resolution, obj_tstr); + char amb_tstr[16]; + dtostrfd(mlx90614.amb_temp, Settings.flag2.temperature_resolution, amb_tstr); + + if (json) { + ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr, amb_tstr); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_IRTMP, obj_tstr, amb_tstr); +#endif + } +} + + + + + +bool Xsns46(byte function) +{ + if (!I2cEnabled(XI2C_32)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + MLX90614_Init(); + } + else if (mlx90614.ready) { + switch (function) { + case FUNC_EVERY_SECOND: + MLX90614_Every_Second(); + break; + case FUNC_JSON_APPEND: + MLX90614_Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MLX90614_Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_47_max31865.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_47_max31865.ino" +#ifdef USE_MAX31865 + +#ifndef USE_SPI +#error "MAX31865 requires USE_SPI enabled" +#endif + +#include "Adafruit_MAX31865.h" + +#define XSNS_47 47 + +#if MAX31865_PTD_WIRES == 4 + #define PTD_WIRES MAX31865_4WIRE +#elif MAX31865_PTD_WIRES == 3 + #define PTD_WIRES MAX31865_3WIRE +#else + #define PTD_WIRES MAX31865_2WIRE +#endif + +int8_t init_status = 0; + +Adafruit_MAX31865 max31865; + +struct MAX31865_Result_Struct { + uint8_t ErrorCode; + uint16_t Rtd; + float PtdResistance; + float PtdTemp; +} MAX31865_Result; + +void MAX31865_Init(void){ + if(init_status) + return; + + max31865.setPins( + pin[GPIO_SSPI_CS], + pin[GPIO_SSPI_MOSI], + pin[GPIO_SSPI_MISO], + pin[GPIO_SSPI_SCLK] + ); + + if(max31865.begin(PTD_WIRES)) + init_status = 1; + else + init_status = -1; +} + + + + + +void MAX31865_GetResult(void){ + uint16_t rtd; + + rtd = max31865.readRTD(); + MAX31865_Result.Rtd = rtd; + MAX31865_Result.PtdResistance = max31865.rtd_to_resistance(rtd, MAX31865_REF_RES); + MAX31865_Result.PtdTemp = max31865.rtd_to_temperature(rtd, MAX31865_PTD_RES, MAX31865_REF_RES) + MAX31865_PTD_BIAS; +} + +void MAX31865_Show(bool Json){ + char temperature[33]; + char resistance[33]; + + dtostrfd(MAX31865_Result.PtdResistance, Settings.flag2.temperature_resolution, resistance); + dtostrfd(MAX31865_Result.PtdTemp, Settings.flag2.temperature_resolution, temperature); + + if(Json){ + ResponseAppend_P(PSTR(",\"MAX31865\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + temperature, resistance, MAX31865_Result.ErrorCode); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_TEMP, temperature); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, MAX31865_Result.PtdTemp); + } +#endif + } else { +#ifdef USE_WEBSERVER + WSContentSend_PD(HTTP_SNS_TEMP, "MAX31865", temperature, TempUnit()); +#endif + } +} + + + + + +bool Xsns47(uint8_t function) +{ + bool result = false; + if((pin[GPIO_SSPI_MISO] < 99) && (pin[GPIO_SSPI_MOSI] < 99) && + (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_CS] < 99)) { + + switch (function) { + case FUNC_INIT: + MAX31865_Init(); + break; + + case FUNC_EVERY_SECOND: + MAX31865_GetResult(); + break; + + case FUNC_JSON_APPEND: + MAX31865_Show(true); + break; + +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MAX31865_Show(false); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_48_chirp.ino" +# 35 "S:/Development/Tasmota/tasmota/xsns_48_chirp.ino" +#ifdef USE_I2C +#ifdef USE_CHIRP +# 47 "S:/Development/Tasmota/tasmota/xsns_48_chirp.ino" +#define XSNS_48 48 +#define XI2C_33 33 + +#define CHIRP_MAX_SENSOR_COUNT 3 + +#define CHIRP_ADDR_STANDARD 0x20 + + + + + +#define D_CMND_CHIRP "CHIRP" + +const char S_JSON_CHIRP_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_CHIRP "%s\":%d}"; +const char S_JSON_CHIRP_COMMAND[] PROGMEM = "{\"" D_CMND_CHIRP "%s\"}"; +const char kCHIRP_Commands[] PROGMEM = "Select|Set|Scan|Reset|Sleep|Wake"; + +const char kChirpTypes[] PROGMEM = "CHIRP"; + + + + + +enum CHIRP_Commands { + CMND_CHIRP_SELECT, + CMND_CHIRP_SET, + CMND_CHIRP_SCAN, + CMND_CHIRP_RESET, + CMND_CHIRP_SLEEP, + CMND_CHIRP_WAKE }; + + + + + + +#define CHIRP_GET_CAPACITANCE 0x00 +#define CHIRP_SET_ADDRESS 0x01 +#define CHIRP_GET_ADDRESS 0x02 +#define CHIRP_MEASURE_LIGHT 0x03 +#define CHIRP_GET_LIGHT 0x04 +#define CHIRP_GET_TEMPERATURE 0x05 +#define CHIRP_RESET 0x06 +#define CHIRP_GET_VERSION 0x07 +#define CHIRP_SLEEP 0x08 +#define CHIRP_GET_BUSY 0x09 + + + + + +void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg) { + Wire.beginTransmission(addr); + Wire.write(reg); + Wire.endTransmission(); +} + +uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr) { + Wire.requestFrom(addr,(uint8_t)2); + uint16_t t = Wire.read() << 8; + t = t | Wire.read(); + return t; +} + + + + + +uint8_t chirp_current = 0; +uint8_t chirp_found_sensors = 0; + +char chirp_name[7]; +uint8_t chirp_next_job = 0; +uint32_t chirp_timeout_count = 0; + +#pragma pack(1) +struct ChirpSensor_t{ + uint16_t moisture = 0; + uint16_t light = 0; + int16_t temperature = 0; + uint8_t version = 0; + uint8_t address:7; + uint8_t explicitSleep:1; +}; +#pragma pack() + +ChirpSensor_t chirp_sensor[CHIRP_MAX_SENSOR_COUNT]; + + + +void ChirpReset(uint8_t addr) { + ChirpWriteI2CRegister(addr, CHIRP_RESET); +} + + + +void ChirpResetAll(void) { + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version) { + ChirpReset(chirp_sensor[i].address); + } + } +} + + +void ChirpClockSet() { + Wire.setClockStretchLimit(4000); + Wire.setClock(50000); +} + + + +void ChirpSleep(uint8_t addr) { + ChirpWriteI2CRegister(addr, CHIRP_SLEEP); +} +# 185 "S:/Development/Tasmota/tasmota/xsns_48_chirp.ino" +void ChirpSelect(uint8_t sensor) { + if(sensor < chirp_found_sensors) { + chirp_current = sensor; + DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u now active."), chirp_current); + } + if (sensor == 255) { + DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u active at address 0x%x."), chirp_current, chirp_sensor[chirp_current].address); + } +} + + + +uint8_t ChirpReadVersion(uint8_t addr) { + return (I2cRead8(addr, CHIRP_GET_VERSION)); +} + + + +bool ChirpSet(uint8_t addr) { + if(addr < 128){ + if (I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr)){ + if(chirp_sensor[chirp_current].version>0x25 && chirp_sensor[chirp_current].version != 255){ + delay(5); + I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); + + } + DEBUG_SENSOR_LOG(PSTR("CHIRP: Wrote adress %u "), addr); + ChirpReset(chirp_sensor[chirp_current].address); + chirp_sensor[chirp_current].address = addr; + chirp_timeout_count = 10; + chirp_next_job = 0; + if(chirp_sensor[chirp_current].version == 255){ + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: wrote new address %u, please power off device"), addr); + chirp_sensor[chirp_current].version == 0; + } + return true; + } + } + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: address %u incorrect and not used"), addr); + return false; +} + + + +bool ChirpScan() +{ + ChirpClockSet(); + chirp_found_sensors = 0; + for (uint8_t address = 1; address <= 127; address++) { + chirp_sensor[chirp_found_sensors].version = 0; + chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); + delay(2); + chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); + if (chirp_sensor[chirp_found_sensors].version > 0) { + I2cSetActiveFound(address, "CHIRP"); + if (chirp_found_sensors 0); +} + + + +void ChirpDetect(void) +{ + if (chirp_next_job > 0) { return; } + + DEBUG_SENSOR_LOG(PSTR("CHIRP: scan will start ...")); + if (ChirpScan()) { + uint8_t chirp_model = 0; + GetTextIndexed(chirp_name, sizeof(chirp_name), chirp_model, kChirpTypes); + } +} + + +void ChirpServiceAllSensors(uint8_t job){ + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare for sensor at address 0x%x"), chirp_sensor[i].address); + switch(job){ + case 0: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_CAPACITANCE); + break; + case 1: + chirp_sensor[i].moisture = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + case 2: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_TEMPERATURE); + break; + case 3: + chirp_sensor[i].temperature = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + case 4: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_MEASURE_LIGHT); + break; + case 5: + ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_LIGHT); + break; + case 6: + chirp_sensor[i].light = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); + break; + default: + break; + } + } + } +} + + + +void ChirpEvery100MSecond(void) +{ + + if(chirp_timeout_count == 0) { + switch(chirp_next_job) { + case 0: + DEBUG_SENSOR_LOG(PSTR("CHIRP: reset all")); + ChirpResetAll(); + chirp_timeout_count = 10; + chirp_next_job++; + break; + case 1: + + + chirp_next_job++; + break; + case 2: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read")); + ChirpServiceAllSensors(0); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 3: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read")); + ChirpServiceAllSensors(1); + chirp_next_job++; + break; + case 4: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read - 2nd")); + ChirpServiceAllSensors(0); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 5: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read - 2nd")); + ChirpServiceAllSensors(1); + chirp_next_job++; + break; + case 6: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read")); + ChirpServiceAllSensors(2); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 7: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read")); + ChirpServiceAllSensors(3); + chirp_next_job++; + break; + case 8: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read - 2nd")); + ChirpServiceAllSensors(2); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 9: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read - 2nd")); + ChirpServiceAllSensors(3); + chirp_next_job++; + break; + case 10: + DEBUG_SENSOR_LOG(PSTR("CHIRP: start light measure process")); + ChirpServiceAllSensors(4); + chirp_timeout_count = 90; + chirp_next_job++; + break; + case 11: + DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare light read")); + ChirpServiceAllSensors(5); + chirp_timeout_count = 11; + chirp_next_job++; + break; + case 12: + DEBUG_SENSOR_LOG(PSTR("CHIRP: finish light read")); + ChirpServiceAllSensors(6); + chirp_next_job++; + break; + case 13: + DEBUG_SENSOR_LOG(PSTR("CHIRP: paused, waiting for TELE")); + break; + case 14: + if (Settings.tele_period > 16){ + chirp_timeout_count = (Settings.tele_period - 17) * 10; + DEBUG_SENSOR_LOG(PSTR("CHIRP: timeout 1/10 sec: %u, tele: %u"), chirp_timeout_count, Settings.tele_period); + } + else{ + AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: TELEPERIOD must be > 16 seconds !")); + + } + chirp_next_job = 1; + break; + } + } + else { + chirp_timeout_count--; + } +} + + + + +#ifdef USE_WEBSERVER + + +const char HTTP_SNS_DARKNESS[] PROGMEM = "{s} " D_JSON_DARKNESS "{m}%s %%{e}"; +const char HTTP_SNS_CHIRPVER[] PROGMEM = "{s} CHIRP-sensor %u at address{m}0x%x{e}" + "{s} FW-version{m}%s {e}"; ; +const char HTTP_SNS_CHIRPSLEEP[] PROGMEM = "{s} {m} is sleeping ...{e}"; +#endif + + + +void ChirpShow(bool json) +{ + for (uint32_t i = 0; i < chirp_found_sensors; i++) { + if (chirp_sensor[i].version) { + + char str_temperature[33]; + double t_temperature = ((double) chirp_sensor[i].temperature )/10.0; + dtostrfd(t_temperature, Settings.flag2.temperature_resolution, str_temperature); + char str_light[33]; + dtostrfd(chirp_sensor[i].light, 0, str_light); + char str_version[7]; + if(chirp_sensor[i].version == 0xff){ + strncpy_P(str_version, PSTR("Chirp!"), sizeof(str_version)); + } + else{ + sprintf(str_version, "%x", chirp_sensor[i].version); + } + + if (json) { + if(!chirp_sensor[i].explicitSleep) { + ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%d"), chirp_name, i, chirp_sensor[i].moisture); + if(chirp_sensor[i].temperature!=-1){ + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"),str_temperature); + } + ResponseAppend_P(PSTR(",\"" D_JSON_DARKNESS "\":%s}"),str_light); + } + else { + ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"),chirp_name, i); + } + #ifdef USE_DOMOTICZ + if (0 == tele_period) { + char str_moisture[33]; + dtostrfd(chirp_sensor[i].moisture, 0, str_moisture); + DomoticzTempHumSensor(str_temperature, str_moisture); + DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); + } + #endif + #ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_CHIRPVER, i, chirp_sensor[i].address, str_version); + if (chirp_sensor[i].explicitSleep){ + WSContentSend_PD(HTTP_SNS_CHIRPSLEEP); + } + else { + WSContentSend_PD(HTTP_SNS_MOISTURE, "", chirp_sensor[i].moisture); + WSContentSend_PD(HTTP_SNS_DARKNESS, str_light); + if (chirp_sensor[i].temperature!=-1) { + WSContentSend_PD(HTTP_SNS_TEMP, "", str_temperature, TempUnit()); + } + } + + #endif + } + } + } +} + + + + + +bool ChirpCmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_CHIRP); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_CHIRP), disp_len)) { + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kCHIRP_Commands); + + switch (command_code) { + case CMND_CHIRP_SELECT: + case CMND_CHIRP_SET: + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(XdrvMailbox.payload); } + if (command_code == CMND_CHIRP_SET) { ChirpSet((uint8_t)XdrvMailbox.payload); } + Response_P(S_JSON_CHIRP_COMMAND_NVALUE, command, XdrvMailbox.payload); + } + else { + if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(255); } + Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); + } + break; + case CMND_CHIRP_SCAN: + case CMND_CHIRP_SLEEP: + case CMND_CHIRP_WAKE: + case CMND_CHIRP_RESET: + if (command_code == CMND_CHIRP_SCAN) { chirp_next_job = 0; + ChirpDetect(); } + if (command_code == CMND_CHIRP_SLEEP) { chirp_sensor[chirp_current].explicitSleep = true; + ChirpSleep(chirp_sensor[chirp_current].address); } + if (command_code == CMND_CHIRP_WAKE) { chirp_sensor[chirp_current].explicitSleep = false; + ChirpReadVersion(chirp_sensor[chirp_current].address); } + if (command_code == CMND_CHIRP_RESET) { ChirpReset(chirp_sensor[chirp_current].address); } + Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); + break; + default: + + serviced = false; + break; + } + } + return serviced; +} + + + + + +bool Xsns48(uint8_t function) +{ + if (!I2cEnabled(XI2C_33)) { return false; } + + bool result = false; + + switch (function) { + case FUNC_EVERY_100_MSECOND: + if(chirp_found_sensors > 0){ + ChirpEvery100MSecond(); + } + break; + case FUNC_COMMAND: + result = ChirpCmd(); + break; + case FUNC_JSON_APPEND: + ChirpShow(1); + chirp_next_job = 14; + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + ChirpShow(0); + break; +#endif + case FUNC_INIT: + ChirpDetect(); + break; + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_50_paj7620.ino" +# 31 "S:/Development/Tasmota/tasmota/xsns_50_paj7620.ino" +#ifdef USE_I2C +#ifdef USE_PAJ7620 + + + + + + +#define XSNS_50 50 +#define XI2C_34 34 + +#define PAJ7620_ADDR 0x73 + +#define PAJ7620_BANK_SEL 0xEF + + + +#define PAJ7620_GET_GESTURE 0x43 +#define PAJ7620_PROXIMITY_AVG_Y 0x6c + +#define PAJ7620_OBJECT_CENTER_X 0xad +#define PAJ7620_OBJECT_CENTER_Y 0xaf + +#define PAJ7620_DOWN 1 +#define PAJ7620_UP 2 +#define PAJ7620_RIGHT 4 +#define PAJ7620_LEFT 8 +#define PAJ7620_NEAR 16 +#define PAJ7620_FAR 32 +#define PAJ7620_CW 64 +#define PAJ7620_CCW 128 + + + + +const uint8_t PAJ7620initRegisterArray[][2] PROGMEM = { + {0xEF,0x00}, + {0x32,0x29}, {0x33,0x01}, {0x34,0x00}, {0x35,0x01}, {0x36,0x00}, {0x37,0x07}, {0x38,0x17}, {0x39,0x06}, + {0x3A,0x12}, {0x3F,0x00}, {0x40,0x02}, {0x41,0xFF}, {0x42,0x01}, {0x46,0x2D}, {0x47,0x0F}, {0x48,0x3C}, + {0x49,0x00}, {0x4A,0x1E}, {0x4B,0x00}, {0x4C,0x20}, {0x4D,0x00}, {0x4E,0x1A}, {0x4F,0x14}, {0x50,0x00}, + {0x51,0x10}, {0x52,0x00}, {0x5C,0x02}, {0x5D,0x00}, {0x5E,0x10}, {0x5F,0x3F}, {0x60,0x27}, {0x61,0x28}, + {0x62,0x00}, {0x63,0x03}, {0x64,0xF7}, {0x65,0x03}, {0x66,0xD9}, {0x67,0x03}, {0x68,0x01}, {0x69,0xC8}, + {0x6A,0x40}, {0x6D,0x04}, {0x6E,0x00}, {0x6F,0x00}, {0x70,0x80}, {0x71,0x00}, {0x72,0x00}, {0x73,0x00}, + {0x74,0xF0}, {0x75,0x00}, {0x80,0x42}, {0x81,0x44}, {0x82,0x04}, {0x83,0x20}, {0x84,0x20}, {0x85,0x00}, + {0x86,0x10}, {0x87,0x00}, {0x88,0x05}, {0x89,0x18}, {0x8A,0x10}, {0x8B,0x01}, {0x8C,0x37}, {0x8D,0x00}, + {0x8E,0xF0}, {0x8F,0x81}, {0x90,0x06}, {0x91,0x06}, {0x92,0x1E}, {0x93,0x0D}, {0x94,0x0A}, {0x95,0x0A}, + {0x96,0x0C}, {0x97,0x05}, {0x98,0x0A}, {0x99,0x41}, {0x9A,0x14}, {0x9B,0x0A}, {0x9C,0x3F}, {0x9D,0x33}, + {0x9E,0xAE}, {0x9F,0xF9}, {0xA0,0x48}, {0xA1,0x13}, {0xA2,0x10}, {0xA3,0x08}, {0xA4,0x30}, {0xA5,0x19}, + {0xA6,0x10}, {0xA7,0x08}, {0xA8,0x24}, {0xA9,0x04}, {0xAA,0x1E}, {0xAB,0x1E}, {0xCC,0x19}, {0xCD,0x0B}, + {0xCE,0x13}, {0xCF,0x64}, {0xD0,0x21}, {0xD1,0x0F}, {0xD2,0x88}, {0xE0,0x01}, {0xE1,0x04}, {0xE2,0x41}, + {0xE3,0xD6}, {0xE4,0x00}, {0xE5,0x0C}, {0xE6,0x0A}, {0xE7,0x00}, {0xE8,0x00}, {0xE9,0x00}, {0xEE,0x07}, + {0xEF,0x01}, + {0x00,0x1E}, {0x01,0x1E}, {0x02,0x0F}, {0x03,0x10}, {0x04,0x02}, {0x05,0x00}, {0x06,0xB0}, {0x07,0x04}, + {0x08,0x0D}, {0x09,0x0E}, {0x0A,0x9C}, {0x0B,0x04}, {0x0C,0x05}, {0x0D,0x0F}, {0x0E,0x02}, {0x0F,0x12}, + {0x10,0x02}, {0x11,0x02}, {0x12,0x00}, {0x13,0x01}, {0x14,0x05}, {0x15,0x07}, {0x16,0x05}, {0x17,0x07}, + {0x18,0x01}, {0x19,0x04}, {0x1A,0x05}, {0x1B,0x0C}, {0x1C,0x2A}, {0x1D,0x01}, {0x1E,0x00}, {0x21,0x00}, + {0x22,0x00}, {0x23,0x00}, {0x25,0x01}, {0x26,0x00}, {0x27,0x39}, {0x28,0x7F}, {0x29,0x08}, {0x30,0x03}, + {0x31,0x00}, {0x32,0x1A}, {0x33,0x1A}, {0x34,0x07}, {0x35,0x07}, {0x36,0x01}, {0x37,0xFF}, {0x38,0x36}, + {0x39,0x07}, {0x3A,0x00}, {0x3E,0xFF}, {0x3F,0x00}, {0x40,0x77}, {0x41,0x40}, {0x42,0x00}, {0x43,0x30}, + {0x44,0xA0}, {0x45,0x5C}, {0x46,0x00}, {0x47,0x00}, {0x48,0x58}, {0x4A,0x1E}, {0x4B,0x1E}, {0x4C,0x00}, + {0x4D,0x00}, {0x4E,0xA0}, {0x4F,0x80}, {0x50,0x00}, {0x51,0x00}, {0x52,0x00}, {0x53,0x00}, {0x54,0x00}, + {0x57,0x80}, {0x59,0x10}, {0x5A,0x08}, {0x5B,0x94}, {0x5C,0xE8}, {0x5D,0x08}, {0x5E,0x3D}, {0x5F,0x99}, + {0x60,0x45}, {0x61,0x40}, {0x63,0x2D}, {0x64,0x02}, {0x65,0x96}, {0x66,0x00}, {0x67,0x97}, {0x68,0x01}, + {0x69,0xCD}, {0x6A,0x01}, {0x6B,0xB0}, {0x6C,0x04}, {0x6D,0x2C}, {0x6E,0x01}, {0x6F,0x32}, {0x71,0x00}, + {0x72,0x01}, {0x73,0x35}, {0x74,0x00}, {0x75,0x33}, {0x76,0x31}, {0x77,0x01}, {0x7C,0x84}, {0x7D,0x03}, + {0x7E,0x01}, + {0xEF,0x00} +}; + + + + + +const char kPaj7620Directions[] PROGMEM = "Down|Up|Right|Left|Near|Far|CW|CCW"; + +const uint8_t PAJ7620_PIN[]= {1,2,3,4}; + + + + + +char PAJ7620_name[] = "PAJ7620"; + +uint32_t PAJ7620_timeout_counter = 10; +uint32_t PAJ7620_next_job = 0; +uint32_t PAJ7620_mode = 1; + +struct { + uint8_t current; + uint8_t last; + uint8_t same; + uint8_t unfinished; +} PAJ7620_gesture; + +bool PAJ7620_finished_gesture = false; +char PAJ7620_currentGestureName[6]; + +struct{ + uint8_t x; + uint8_t y; + uint8_t last_x; + uint8_t last_y; + uint8_t proximity; + uint8_t last_proximity; + uint8_t corner; + struct { + uint8_t step:3; + uint8_t countdown:3; + uint8_t valid:1; + } PIN; +} PAJ7620_state; + + + + + +void PAJ7620SelectBank(uint8_t bank) +{ + I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, bank &1, 1); +} + + + +void PAJ7620DecodeGesture(void) +{ + uint32_t index = 0; + switch (PAJ7620_gesture.current) { + case PAJ7620_LEFT: + index++; + case PAJ7620_RIGHT: + index++; + case PAJ7620_UP: + index++; + case PAJ7620_DOWN: + if (PAJ7620_gesture.unfinished) { + PAJ7620_finished_gesture = true; + break; + } + PAJ7620_gesture.unfinished = PAJ7620_gesture.current; + PAJ7620_timeout_counter = 5; + break; + case PAJ7620_NEAR: + index = 4; + PAJ7620_finished_gesture = true; + PAJ7620_timeout_counter = 25; + break; + case PAJ7620_FAR: + index = 5; + PAJ7620_finished_gesture = true; + PAJ7620_timeout_counter = 25; + break; + case PAJ7620_CW: + index = 6; + PAJ7620_finished_gesture = true; + break; + case PAJ7620_CCW: + index = 7; + PAJ7620_finished_gesture = true; + break; + default: + index = 8; + if (PAJ7620_gesture.unfinished) { + PAJ7620_finished_gesture = true; + } + break; + } + if (index < 8) { + GetTextIndexed(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), index, kPaj7620Directions); + } + + if (PAJ7620_finished_gesture) { + if (PAJ7620_gesture.unfinished) { + if ((PAJ7620_gesture.current != PAJ7620_NEAR) && (PAJ7620_gesture.current != PAJ7620_FAR)) { + PAJ7620_gesture.current = PAJ7620_gesture.unfinished; + } + } + if (PAJ7620_gesture.current == PAJ7620_gesture.last) { + PAJ7620_gesture.same++; + } else { + PAJ7620_gesture.same = 1; + } + PAJ7620_gesture.last = PAJ7620_gesture.current; + PAJ7620_finished_gesture = false; + PAJ7620_gesture.unfinished = 0; + PAJ7620_timeout_counter += 3; + MqttPublishSensor(); + } +} + + + +void PAJ7620ReadGesture(void) +{ + switch (PAJ7620_mode) { + case 1: + PAJ7620_gesture.current = I2cRead8(PAJ7620_ADDR,PAJ7620_GET_GESTURE); + if ((PAJ7620_gesture.current > 0) || PAJ7620_gesture.unfinished) { + DEBUG_SENSOR_LOG(PSTR("PAJ: gesture: %u"), PAJ7620_gesture.current); + PAJ7620DecodeGesture(); + } + break; + case 2: + PAJ7620_state.proximity = I2cRead8(PAJ7620_ADDR, PAJ7620_PROXIMITY_AVG_Y); + if ((PAJ7620_state.proximity > 0) || (PAJ7620_state.last_proximity > 0)) { + if (PAJ7620_state.proximity != PAJ7620_state.last_proximity) { + PAJ7620_state.last_proximity = PAJ7620_state.proximity; + DEBUG_SENSOR_LOG(PSTR("PAJ: Proximity: %u"), PAJ7620_state.proximity); + MqttPublishSensor(); + } + } + break; + case 3: + case 4: + case 5: + PAJ7620_state.x = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_X); + PAJ7620_state.y = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_Y); + if ((PAJ7620_state.y > 0) && (PAJ7620_state.x > 0)) { + if ((PAJ7620_state.y != PAJ7620_state.last_y) || (PAJ7620_state.x != PAJ7620_state.last_x)) { + PAJ7620_state.last_y = PAJ7620_state.y; + PAJ7620_state.last_x = PAJ7620_state.x; + DEBUG_SENSOR_LOG(PSTR("PAJ: x: %u y: %u"), PAJ7620_state.x, PAJ7620_state.y); + + PAJ7620_state.corner = 0; + + + + switch (PAJ7620_state.y) { + case 0: case 1: case 2: case 3: case 4: case 5: + PAJ7620_state.corner = 3; + break; + case 9: case 10: case 11: case 12: case 13: case 14: + PAJ7620_state.corner = 1; + break; + } + if (PAJ7620_state.corner != 0) { + switch (PAJ7620_state.x) { + case 0: case 1: case 2: case 3: case 4: case 5: + break; + case 9: case 10: case 11: case 12: case 13: case 14: + PAJ7620_state.corner++; + break; + default: + PAJ7620_state.corner = 0; + break; + } + } + DEBUG_SENSOR_LOG(PSTR("PAJ: corner: %u"), PAJ7620_state.corner); + + if (PAJ7620_state.PIN.countdown == 0) { + PAJ7620_state.PIN.step = 0; + PAJ7620_state.PIN.valid = 0; + } + if (!PAJ7620_state.PIN.step) { + if (PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]) { + PAJ7620_state.PIN.step = 1; + PAJ7620_state.PIN.countdown = 7; + } + } else { + if (PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]) { + PAJ7620_state.PIN.step += 1; + PAJ7620_state.PIN.countdown = 7; + } else { + PAJ7620_state.PIN.countdown -= 1; + } + } + if (PAJ7620_state.PIN.step == 4) { + PAJ7620_state.PIN.valid = 1; + DEBUG_SENSOR_LOG(PSTR("PAJ: PIN valid!!")); + PAJ7620_state.PIN.countdown = 0; + } + MqttPublishSensor(); + } + } + break; + } +} + + + +void PAJ7620Detect(void) +{ + if (I2cActive(PAJ7620_ADDR)) { return; } + + PAJ7620SelectBank(0); + PAJ7620SelectBank(0); + uint16_t PAJ7620_id = I2cRead16LE(PAJ7620_ADDR,0); + uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); + if (0x7620 == PAJ7620_id) { + I2cSetActiveFound(PAJ7620_ADDR, PAJ7620_name); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ: ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); + PAJ7620_next_job = 1; + } + else { + DEBUG_SENSOR_LOG(PSTR("PAJ: sensor not found, false ID 0x%x"), PAJ7620_id); + } +} + + + +void PAJ7620Init(void) +{ + DEBUG_SENSOR_LOG(PSTR("PAJ: init sensor start %u"),millis()); + union{ + uint32_t raw; + uint8_t reg_val[4]; + } buf; + + for (uint32_t i = 0; i < (sizeof(PAJ7620initRegisterArray) / 2); i += 2) + { + buf.raw = pgm_read_dword(PAJ7620initRegisterArray + i); + DEBUG_SENSOR_LOG("PAJ: %x %x %x %x",buf.reg_val[0],buf.reg_val[1],buf.reg_val[2],buf.reg_val[3]); + I2cWrite(PAJ7620_ADDR, buf.reg_val[0], buf.reg_val[1], 1); + I2cWrite(PAJ7620_ADDR, buf.reg_val[2], buf.reg_val[3], 1); + } + DEBUG_SENSOR_LOG(PSTR("PAJ: init sensor done %u"),millis()); + PAJ7620_next_job = 2; +} + + + +void PAJ7620Loop(void) +{ + if (0 == PAJ7620_timeout_counter) { + switch (PAJ7620_next_job) { + case 1: + PAJ7620Init(); + break; + case 2: + if (PAJ7620_mode != 0) { + PAJ7620ReadGesture(); + } + break; + } + } else { + PAJ7620_timeout_counter--; + } +} + + + +void PAJ7620Show(bool json) +{ + if (json) { + if (PAJ7620_currentGestureName[0] != '\0' ) { + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), PAJ7620_name, PAJ7620_currentGestureName, PAJ7620_gesture.same); + PAJ7620_currentGestureName[0] = '\0'; + return; + } + switch (PAJ7620_mode) { + case 2: + ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), PAJ7620_name, PAJ7620_state.proximity); + break; + case 3: + if (PAJ7620_state.corner > 0) { + ResponseAppend_P(PSTR(",\"%s\":{\"Corner\":%u}"), PAJ7620_name, PAJ7620_state.corner); + } + break; + case 4: + if (PAJ7620_state.PIN.valid) { + ResponseAppend_P(PSTR(",\"%s\":{\"PIN\":%u}"), PAJ7620_name, 1); + PAJ7620_state.PIN.valid = 0; + } + break; + case 5: + ResponseAppend_P(PSTR(",\"%s\":{\"x\":%u,\"y\":%u}"), PAJ7620_name, PAJ7620_state.x, PAJ7620_state.y); + break; + } + } +} +# 411 "S:/Development/Tasmota/tasmota/xsns_50_paj7620.ino" +bool PAJ7620CommandSensor(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { + PAJ7620_mode = XdrvMailbox.payload; + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_50, PAJ7620_mode); + + return true; +} + + + + + +bool Xsns50(uint8_t function) +{ + if (!I2cEnabled(XI2C_34)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + PAJ7620Detect(); + } + else if (PAJ7620_next_job) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_50 == XdrvMailbox.index){ + result = PAJ7620CommandSensor(); + } + break; + case FUNC_EVERY_100_MSECOND: + PAJ7620Loop(); + break; + case FUNC_JSON_APPEND: + PAJ7620Show(1); + break; + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_51_rdm6300.ino" +# 21 "S:/Development/Tasmota/tasmota/xsns_51_rdm6300.ino" +#ifdef USE_RDM6300 + +#define XSNS_51 51 + +#define RDM6300_BAUDRATE 9600 + +#include + +#define RDM_TIMEOUT 100 +char rdm_uid_str[10]; + + +#define RDM6300_BLOCK 2*10 + +uint8_t rdm_blcnt; +TasmotaSerial *RDM6300_Serial = nullptr; + +void RDM6300_Init() { + if (pin[GPIO_RDM6300_RX] < 99) { + RDM6300_Serial = new TasmotaSerial(pin[GPIO_RDM6300_RX],-1,1); + if (RDM6300_Serial->begin(RDM6300_BAUDRATE)) { + if (RDM6300_Serial->hardwareSerial()) { + ClaimSerial(); + } + } + } + rdm_blcnt=0; +} + + +void RDM6300_ScanForTag() { + char rdm_buffer[14]; + uint8_t rdm_index; + uint8_t rdm_array[6]; + + if (!RDM6300_Serial) return; + + if (rdm_blcnt>0) { + rdm_blcnt--; + while (RDM6300_Serial->available()) RDM6300_Serial->read(); + return; + } + + if (RDM6300_Serial->available()) { + + char c=RDM6300_Serial->read(); + if (c!=2) return; + + + rdm_index=0; + uint32_t cmillis=millis(); + while (1) { + if (RDM6300_Serial->available()) { + char c=RDM6300_Serial->read(); + if (c==3) { + + break; + } + rdm_buffer[rdm_index++]=c; + if (rdm_index>13) { + + return; + } + } + if ((millis()-cmillis)>RDM_TIMEOUT) { + + return; + } + } + + + rdm_blcnt=RDM6300_BLOCK; + + + rm6300_hstring_to_array(rdm_array,sizeof(rdm_array),rdm_buffer); + uint8_t accu=0; + for (uint8_t count=0;count<5;count++) { + accu^=rdm_array[count]; + } + if (accu!=rdm_array[5]) { + + return; + } + + + memcpy(rdm_uid_str,&rdm_buffer[2],8); + rdm_uid_str[9]=0; + + ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); + MqttPublishTeleSensor(); + + + + + + } + + +} + +uint8_t rm6300_hexnibble(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { + rVal = chr - '0'; + } else { + if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; + } + return rVal; +} + + +void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]) +{ + char *cp=buffer; + for (uint8_t i = 0; i < len; i++) { + uint8_t val = rm6300_hexnibble(*cp++) << 4; + array[i]= val | rm6300_hexnibble(*cp++); + } +} + +#ifdef USE_WEBSERVER +const char HTTP_RDM6300[] PROGMEM = + "{s}RDM6300 " "UID" "{m}%s" "{e}"; + +void RDM6300_Show(void) { + if (!RDM6300_Serial) return; + if (!rdm_uid_str[0]) strcpy(rdm_uid_str,"????"); + WSContentSend_PD(HTTP_RDM6300,rdm_uid_str); +} +#endif + + + + + +bool Xsns51(byte function) +{ + bool result = false; + + switch (function) { + case FUNC_INIT: + RDM6300_Init(); + break; + case FUNC_EVERY_100_MSECOND: + RDM6300_ScanForTag(); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + RDM6300_Show(); + break; +#endif + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_52_ibeacon.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_52_ibeacon.ino" +#ifdef USE_IBEACON + + + +#define XSNS_52 52 + +#include + +#define HM17_BAUDRATE 9600 + +#define IBEACON_DEBUG + + +#define HM17_V110 + + + +#define IB_TIMEOUT_INTERVAL 30 + +#define IB_UPDATE_TIME_INTERVAL 10 + +TasmotaSerial *IBEACON_Serial = nullptr; + + +uint8_t hm17_found,hm17_cmd,hm17_flag; + +#ifdef IBEACON_DEBUG +uint8_t hm17_debug=0; +#endif + + + +#define HM17_BSIZ 128 +char hm17_sbuffer[HM17_BSIZ]; +uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting; +uint32_t hm17_lastms; +char ib_mac[14]; + + +#if 1 +uint8_t ib_upd_interval,ib_tout_interval; +#define IB_UPDATE_TIME ib_upd_interval +#define IB_TIMEOUT_TIME ib_tout_interval +#else +#undef IB_UPDATE_TIME +#undef IB_TIMEOUT_TIME +#define IB_UPDATE_TIME Settings.ib_upd_interval +#define IB_TIMEOUT_TIME Settings.ib_tout_interval +#endif + +enum {HM17_TEST,HM17_ROLE,HM17_IMME,HM17_DISI,HM17_IBEA,HM17_SCAN,HM17_DISC,HM17_RESET,HM17_RENEW,HM17_CON}; +#define HM17_SUCESS 99 + +struct IBEACON { + char FACID[8]; + char UID[32]; + char MAJOR[4]; + char MINOR[4]; + char PWR[2]; + char MAC[12]; + char RSSI[4]; +}; + +#define MAX_IBEACONS 16 + +struct IBEACON_UID { + char MAC[12]; + char RSSI[4]; + uint8_t FLAGS; + uint8_t TIME; +} ibeacons[MAX_IBEACONS]; + + +void IBEACON_Init() { + + hm17_found=0; + + + if ((pin[GPIO_IBEACON_RX] < 99) && (pin[GPIO_IBEACON_TX] < 99)) { + IBEACON_Serial = new TasmotaSerial(pin[GPIO_IBEACON_RX], pin[GPIO_IBEACON_TX],1); + if (IBEACON_Serial->begin(HM17_BAUDRATE)) { + if (IBEACON_Serial->hardwareSerial()) { + ClaimSerial(); + } + hm17_sendcmd(HM17_TEST); + hm17_lastms=millis(); + + IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; + IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; + } + } +} + +void hm17_every_second(void) { + if (!IBEACON_Serial) return; + + if (hm17_found) { + if (IB_UPDATE_TIME && (uptime%IB_UPDATE_TIME==0)) { + if (hm17_cmd!=99) { + if (hm17_flag&2) { + ib_sendbeep(); + } else { + if (!hm17_connecting) { + hm17_sendcmd(HM17_DISI); + } + } + } + } + for (uint32_t cnt=0;cntIB_TIMEOUT_TIME) { + ibeacons[cnt].FLAGS=0; + ibeacon_mqtt(ibeacons[cnt].MAC,"0000"); + } + } + } + } else { + if (uptime%20==0) { + hm17_sendcmd(HM17_TEST); + } + } +} + +void hm17_sbclr(void) { + memset(hm17_sbuffer,0,HM17_BSIZ); + hm17_sindex=0; + IBEACON_Serial->flush(); +} + +void hm17_sendcmd(uint8_t cmd) { + hm17_sbclr(); + hm17_cmd=cmd; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("hm17cmd %d"),cmd); +#endif + switch (cmd) { + case HM17_TEST: + IBEACON_Serial->write("AT"); + break; + case HM17_ROLE: + IBEACON_Serial->write("AT+ROLE1"); + break; + case HM17_IMME: + IBEACON_Serial->write("AT+IMME1"); + break; + case HM17_DISI: + IBEACON_Serial->write("AT+DISI?"); + hm17_scanning=1; + break; + case HM17_IBEA: + IBEACON_Serial->write("AT+IBEA1"); + break; + case HM17_RESET: + IBEACON_Serial->write("AT+RESET"); + break; + case HM17_RENEW: + IBEACON_Serial->write("AT+RENEW"); + break; + case HM17_SCAN: + IBEACON_Serial->write("AT+SCAN5"); + break; + case HM17_DISC: + IBEACON_Serial->write("AT+DISC?"); + hm17_scanning=1; + break; + case HM17_CON: + IBEACON_Serial->write((const uint8_t*)"AT+CON",6); + IBEACON_Serial->write((const uint8_t*)ib_mac,12); + hm17_connecting=1; + break; + } +} + +uint32_t ibeacon_add(struct IBEACON *ib) { + + if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { + for (uint32_t cnt=0;cntMAC,12)) { + + memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); + ibeacons[cnt].TIME=0; + return 1; + } + } + } + for (uint32_t cnt=0;cntMAC,12); + memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); + ibeacons[cnt].FLAGS=1; + ibeacons[cnt].TIME=0; + return 1; + } + } + } + return 0; +} + +void hm17_decode(void) { + struct IBEACON ib; + switch (hm17_cmd) { + case HM17_TEST: + if (!strncmp(hm17_sbuffer,"OK",2)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("AT OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + hm17_found=1; + } + break; + case HM17_ROLE: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("ROLE OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_IMME: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IMME OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_IBEA: + if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IBEA OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_SCAN: + if (!strncmp(hm17_sbuffer,"OK+Set:5",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("SCAN OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_RESET: + if (!strncmp(hm17_sbuffer,"OK+RESET",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RESET OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_RENEW: + if (!strncmp(hm17_sbuffer,"OK+RENEW",8)) { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RENEW OK")); +#endif + hm17_sbclr(); + hm17_result=HM17_SUCESS; + } + break; + case HM17_CON: + if (!strncmp(hm17_sbuffer,"OK+CONNA",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNA OK")); +#endif + hm17_connecting=2; + break; + } + if (!strncmp(hm17_sbuffer,"OK+CONNE",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNE ERROR")); +#endif + break; + } + if (!strncmp(hm17_sbuffer,"OK+CONNF",8)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNF ERROR")); +#endif + break; + } + if (hm17_connecting==2 && !strncmp(hm17_sbuffer,"OK+CONN",7)) { + hm17_sbclr(); +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONN OK")); +#endif + hm17_connecting=3; + hm17_sendcmd(HM17_TEST); + hm17_connecting=0; + break; + } + break; + + case HM17_DISI: + case HM17_DISC: + if (!strncmp(hm17_sbuffer,"OK+DISCS",8)) { + hm17_sbclr(); + hm17_result=1; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCS OK")); +#endif + break; + } + if (!strncmp(hm17_sbuffer,"OK+DISIS",8)) { + hm17_sbclr(); + hm17_result=1; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISIS OK")); +#endif + break; + } + if (!strncmp(hm17_sbuffer,"OK+DISCE",8)) { + hm17_sbclr(); + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCE OK")); +#endif + hm17_scanning=0; + break; + } + if (!strncmp(hm17_sbuffer,"OK+NAME:",8)) { + if (hm17_sbuffer[hm17_sindex-1]=='\n') { + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("NAME OK")); + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + hm17_sbclr(); + } + break; + } + if (!strncmp(hm17_sbuffer,"OK+DIS0:",8)) { + if (hm17_cmd==HM17_DISI) { +#ifdef HM17_V110 + goto hm17_v110; +#endif + } else { + if (hm17_sindex==20) { + hm17_result=HM17_SUCESS; +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("DIS0 OK")); + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + hm17_sbclr(); + } + } + break; + } + if (!strncmp(hm17_sbuffer,"OK+DISC:",8)) { +hm17_v110: + if (hm17_cmd==HM17_DISI) { + if (hm17_sindex==78) { +#ifdef IBEACON_DEBUG + if (hm17_debug) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("DISC: OK")); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); + } +#endif + memcpy(ib.FACID,&hm17_sbuffer[8],8); + memcpy(ib.UID,&hm17_sbuffer[8+8+1],32); + memcpy(ib.MAJOR,&hm17_sbuffer[8+8+1+32+1],4); + memcpy(ib.MINOR,&hm17_sbuffer[8+8+1+32+1+4],4); + memcpy(ib.PWR,&hm17_sbuffer[8+8+1+32+1+4+4],2); + memcpy(ib.MAC,&hm17_sbuffer[8+8+1+32+1+4+4+2+1],12); + memcpy(ib.RSSI,&hm17_sbuffer[8+8+1+32+1+4+4+2+1+12+1],4); + + if (ibeacon_add(&ib)) { + ibeacon_mqtt(ib.MAC,ib.RSSI); + } + hm17_sbclr(); + hm17_result=1; + } + } else { +#ifdef IBEACON_DEBUG + if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); +#endif + } + break; + } + } +} + +void IBEACON_loop() { + + if (!IBEACON_Serial) return; + +uint32_t difftime=millis()-hm17_lastms; + + while (IBEACON_Serial->available()) { + hm17_lastms=millis(); + + if (hm17_sindexread(); + hm17_sindex++; + hm17_decode(); + } else { + hm17_sindex=0; + break; + } + } + + if (hm17_cmd==99) { + if (hm17_sindex>=HM17_BSIZ-2 || (hm17_sindex && (difftime>100))) { + AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),hm17_sbuffer); + hm17_sbclr(); + } + } + +} + +#ifdef USE_WEBSERVER +const char HTTP_IBEACON[] PROGMEM = + "{s}IBEACON-UID : %s" " - RSSI : %s" "{m}{e}"; + +void IBEACON_Show(void) { +char mac[14]; +char rssi[6]; + + for (uint32_t cnt=0;cnt 0) { + char *cp=XdrvMailbox.data; + if (*cp>='0' && *cp<='8') { + hm17_sendcmd(*cp&7); + Response_P(S_JSON_IBEACON, XSNS_52,"hm17cmd",*cp&7); + } else if (*cp=='s') { + cp++; + len--; + while (*cp==' ') { + len--; + cp++; + } + IBEACON_Serial->write((uint8_t*)cp,len); + hm17_cmd=99; + Response_P(S_JSON_IBEACON1, XSNS_52,"hm17cmd",cp); + } else if (*cp=='u') { + cp++; + if (*cp) IB_UPDATE_TIME=atoi(cp); + Response_P(S_JSON_IBEACON, XSNS_52,"uintv",IB_UPDATE_TIME); + } else if (*cp=='t') { + cp++; + if (*cp) IB_TIMEOUT_TIME=atoi(cp); + Response_P(S_JSON_IBEACON, XSNS_52,"lintv",IB_TIMEOUT_TIME); + } else if (*cp=='c') { + for (uint32_t cnt=0;cnt + + +#define SPECIAL_SS + + + + + +#if MY_LANGUAGE==de-DE + +#define D_TPWRIN "Verbrauch" +#define D_TPWROUT "Einspeisung" +#define D_TPWRCURR "Aktueller Verbrauch" +#define D_TPWRCURR1 "Verbrauch P1" +#define D_TPWRCURR2 "Verbrauch P2" +#define D_TPWRCURR3 "Verbrauch P3" +#define D_Strom_L1 "Strom L1" +#define D_Strom_L2 "Strom L2" +#define D_Strom_L3 "Strom L3" +#define D_Spannung_L1 "Spannung L1" +#define D_Spannung_L2 "Spannung L2" +#define D_Spannung_L3 "Spannung L3" +#define D_METERNR "Zähler Nr" +#define D_METERSID "Service ID" +#define D_GasIN "Zählerstand" +#define D_H2oIN "Zählerstand" +#define D_StL1L2L3 "Ströme L1+L2+L3" +#define D_SpL1L2L3 "Spannung L1+L2+L3/3" + +#else + +#undef D_TPWRIN +#undef D_TPWROUT +#undef D_TPWRCURR +#undef D_TPWRCURR1 +#undef D_TPWRCURR2 +#undef D_TPWRCURR3 +#undef D_Strom_L1 +#undef D_Strom_L2 +#undef D_Strom_L3 +#undef D_Spannung_L1 +#undef D_Spannung_L2 +#undef D_Spannung_L3 +#undef D_METERNR +#undef D_METERSID +#undef D_GasIN +#undef D_H2oIN +#undef D_StL1L2L3 +#undef D_SpL1L2L3 + +#define D_TPWRIN "Total-In" +#define D_TPWROUT "Total-Out" +#define D_TPWRCURR "Current-In/Out" +#define D_TPWRCURR1 "Current-In p1" +#define D_TPWRCURR2 "Current-In p2" +#define D_TPWRCURR3 "Current-In p3" +#define D_Strom_L1 "Current L1" +#define D_Strom_L2 "Current L2" +#define D_Strom_L3 "Current L3" +#define D_Spannung_L1 "Voltage L1" +#define D_Spannung_L2 "Voltage L2" +#define D_Spannung_L3 "Voltage L3" +#define D_METERNR "Meter_number" +#define D_METERSID "Service ID" +#define D_GasIN "Counter" +#define D_H2oIN "Counter" +#define D_StL1L2L3 "Current L1+L2+L3" +#define D_SpL1L2L3 "Voltage L1+L2+L3/3" + +#endif + + + +#define DJ_TPWRIN "Total_in" +#define DJ_TPWROUT "Total_out" +#define DJ_TPWRCURR "Power_curr" +#define DJ_TPWRCURR1 "Power_p1" +#define DJ_TPWRCURR2 "Power_p2" +#define DJ_TPWRCURR3 "Power_p3" +#define DJ_CURR1 "Curr_p1" +#define DJ_CURR2 "Curr_p2" +#define DJ_CURR3 "Curr_p3" +#define DJ_VOLT1 "Volt_p1" +#define DJ_VOLT2 "Volt_p2" +#define DJ_VOLT3 "Volt_p3" +#define DJ_METERNR "Meter_number" +#define DJ_METERSID "Meter_id" +#define DJ_CSUM "Curr_summ" +#define DJ_VAVG "Volt_avg" +#define DJ_COUNTER "Count" + +struct METER_DESC { + uint8_t srcpin; + uint8_t type; + uint16_t flag; + int32_t params; + char prefix[8]; + int8_t trxpin; + uint8_t tsecs; + char *txmem; + uint8_t index; + uint8_t max_index; +}; + + + + + + +#define EHZ161_0 1 +#define EHZ161_1 2 +#define EHZ363 3 +#define EHZH 4 +#define EDL300 5 +#define Q3B 6 +#define COMBO3 7 +#define COMBO2 8 +#define COMBO3a 9 +#define Q3B_V1 10 +#define EHZ363_2 11 +#define COMBO3b 12 +#define WGS_COMBO 13 +#define EBZD_G 14 + + +#define METER EHZ161_1 + + +#if METER==EHZ161_0 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" +"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" +"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" +"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + + + +#if METER==EHZ161_1 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZ363 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZH +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + + + +#if METER==EDL300 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + +#if METER==EBZD_G +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"strom",-1,1,0}}; +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" + +"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100600100ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + + +#if METER==Q3B +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; +#endif + +#if METER==COMBO3 + +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, + [1]={14,'s',0,SML_BAUDRATE,"SML",-1,1,0}, + [2]={4,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; + + +const uint8_t meter[]= +"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" +"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" +"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" +"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"2,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"3,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + +#if METER==COMBO2 + +#undef METERS_USED +#define METERS_USED 2 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, + [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; + + +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" + +"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + +#if METER==COMBO3a +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, + [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}, + [2]={1,'o',0,SML_BAUDRATE,"OBIS3",-1,1,0}}; + + +const uint8_t meter[]= +"1,=h --- Zähler Nr 1 ---|" +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"2,=h --- Zähler Nr 2 ---|" +"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" +"3,=h --- Zähler Nr 3 ---|" +"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"3,=d 10 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; + +#endif + + + +#if METER==Q3B_V1 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ +[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; +#endif + + + +#if METER==EHZ363_2 +#undef METERS_USED +#define METERS_USED 1 +struct METER_DESC const meter_desc[METERS_USED]={ +[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + +"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" + +"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" + +"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" + +"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" + +"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" + +"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; +#endif + + +#if METER==COMBO3b +#undef METERS_USED +#define METERS_USED 3 +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, + [1]={14,'c',0,50,"Gas"}, + [2]={1,'c',0,10,"Wasser"}}; + + +const uint8_t meter[]= +"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" +"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" +"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" +"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" + + +"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",2|" + +"3,1-0:1.8.0*255(@100," D_H2oIN ",cbm," DJ_COUNTER ",2"; +#endif + + +#if METER==WGS_COMBO +#undef METERS_USED +#define METERS_USED 3 + +struct METER_DESC const meter_desc[METERS_USED]={ + [0]={1,'c',0,10,"H20",-1,1,0}, + [1]={4,'c',0,50,"GAS",-1,1,0}, + [2]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; + +const uint8_t meter[]= + + +"1,1-0:1.8.0*255(@10000," D_H2oIN ",cbm," DJ_COUNTER ",4|" + + +"2,=h==================|" +"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",3|" + +"3,=h==================|" + +"3,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",3|" +"3,=h==================|" + +"3,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",2|" +"3,=h -------------------------------|" +"3,=m 10+11+12 @100," D_StL1L2L3 ",A," DJ_CSUM ",2|" + +"3,=m 13+14+15/#3 @100," D_SpL1L2L3 ",V," DJ_VAVG ",2|" +"3,=h==================|" + +"3,77070100240700ff@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",2|" + +"3,77070100380700ff@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",2|" + +"3,770701004c0700ff@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",2|" +"3,=h -------------------------------|" + +"3,770701001f0700ff@100," D_Strom_L1 ",A," DJ_CURR1 ",2|" + +"3,77070100330700ff@100," D_Strom_L2 ",A," DJ_CURR2 ",2|" + +"3,77070100470700ff@100," D_Strom_L3 ",A," DJ_CURR3 ",2|" +"3,=h -------------------------------|" + +"3,77070100200700ff@100," D_Spannung_L1 ",V," DJ_VOLT1 ",2|" + +"3,77070100340700ff@100," D_Spannung_L2 ",V," DJ_VOLT2 ",2|" + +"3,77070100480700ff@100," D_Spannung_L3 ",V," DJ_VOLT3 ",2|" +"3,=h==================|" + +"3,77070100000009ff@#," D_METERSID ",," DJ_METERSID ",0|" +"3,=h--------------------------------"; +#endif +# 499 "S:/Development/Tasmota/tasmota/xsns_53_sml.ino" +#define USE_SML_MEDIAN_FILTER + + +#ifndef SML_MAX_VARS +#define SML_MAX_VARS 20 +#endif + + +#define MAX_METERS 5 +double meter_vars[SML_MAX_VARS]; + +#define MAX_DVARS MAX_METERS*2 +double dvalues[MAX_DVARS]; +uint32_t dtimes[MAX_DVARS]; +uint8_t meters_used; + +struct METER_DESC const *meter_desc_p; +const uint8_t *meter_p; +uint8_t meter_spos[MAX_METERS]; + + +TasmotaSerial *meter_ss[MAX_METERS]; + + +#define SML_BSIZ 48 +uint8_t smltbuf[MAX_METERS][SML_BSIZ]; + + +#define METER_ID_SIZE 24 +char meter_id[MAX_METERS][METER_ID_SIZE]; + +#define EBUS_SYNC 0xaa +#define EBUS_ESC 0xa9 + +uint8_t sml_send_blocks; +uint8_t sml_100ms_cnt; +uint8_t sml_desc_cnt; + +#ifdef USE_SML_MEDIAN_FILTER + +#define MEDIAN_SIZE 5 +struct SML_MEDIAN_FILTER { +double buffer[MEDIAN_SIZE]; +int8_t index; +} sml_mf[SML_MAX_VARS]; + +#ifndef FLT_MAX +#define FLT_MAX 99999999 +#endif + +double sml_median_array(double *array,uint8_t len) { + uint8_t ind[len]; + uint8_t mind=0,index=0,flg; + double min=FLT_MAX; + + for (uint8_t hcnt=0; hcntbuffer[mf->index]=in; + mf->index++; + if (mf->index>=MEDIAN_SIZE) mf->index=0; + + return sml_median_array(mf->buffer,MEDIAN_SIZE); +# 603 "S:/Development/Tasmota/tasmota/xsns_53_sml.ino" +} +#endif + +#ifdef ANALOG_OPTO_SENSOR + +uint8_t ads1115_up; + + +#define SAMPLE_BIT (0x8000) + +#define ADS1115_COMP_QUEUE_SHIFT 0 +#define ADS1115_COMP_LATCH_SHIFT 2 +#define ADS1115_COMP_POLARITY_SHIFT 3 +#define ADS1115_COMP_MODE_SHIFT 4 +#define ADS1115_DATA_RATE_SHIFT 5 +#define ADS1115_MODE_SHIFT 8 +#define ADS1115_PGA_SHIFT 9 +#define ADS1115_MUX_SHIFT 12 + +enum ads1115_comp_queue { + ADS1115_COMP_QUEUE_AFTER_ONE = 0, + ADS1115_COMP_QUEUE_AFTER_TWO = 0x1 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_AFTER_FOUR = 0x2 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_DISABLE = 0x3 << ADS1115_COMP_QUEUE_SHIFT, + ADS1115_COMP_QUEUE_MASK = 0x3 << ADS1115_COMP_QUEUE_SHIFT, +}; + +enum ads1115_comp_latch { + ADS1115_COMP_LATCH_NO = 0, + ADS1115_COMP_LATCH_YES = 1 << ADS1115_COMP_LATCH_SHIFT, + ADS1115_COMP_LATCH_MASK = 1 << ADS1115_COMP_LATCH_SHIFT, +}; + +enum ads1115_comp_polarity { + ADS1115_COMP_POLARITY_ACTIVE_LOW = 0, + ADS1115_COMP_POLARITY_ACTIVE_HIGH = 1 << ADS1115_COMP_POLARITY_SHIFT, + ADS1115_COMP_POLARITY_MASK = 1 << ADS1115_COMP_POLARITY_SHIFT, +}; + +enum ads1115_comp_mode { + ADS1115_COMP_MODE_WINDOW = 0, + ADS1115_COMP_MODE_HYSTERESIS = 1 << ADS1115_COMP_MODE_SHIFT, + ADS1115_COMP_MODE_MASK = 1 << ADS1115_COMP_MODE_SHIFT, +}; + +enum ads1115_data_rate { + ADS1115_DATA_RATE_8_SPS = 0, + ADS1115_DATA_RATE_16_SPS = 0x1 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_32_SPS = 0x2 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_64_SPS = 0x3 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_128_SPS = 0x4 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_250_SPS = 0x5 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_475_SPS = 0x6 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_860_SPS = 0x7 << ADS1115_DATA_RATE_SHIFT, + ADS1115_DATA_RATE_MASK = 0x7 << ADS1115_DATA_RATE_SHIFT, +}; + +enum ads1115_mode { + ADS1115_MODE_CONTINUOUS = 0, + ADS1115_MODE_SINGLE_SHOT = 1 << ADS1115_MODE_SHIFT, + ADS1115_MODE_MASK = 1 << ADS1115_MODE_SHIFT, +}; + +enum ads1115_pga { + ADS1115_PGA_TWO_THIRDS = 0, + ADS1115_PGA_ONE = 0x1 << ADS1115_PGA_SHIFT, + ADS1115_PGA_TWO = 0x2 << ADS1115_PGA_SHIFT, + ADS1115_PGA_FOUR = 0x3 << ADS1115_PGA_SHIFT, + ADS1115_PGA_EIGHT = 0x4 << ADS1115_PGA_SHIFT, + ADS1115_PGA_SIXTEEN = 0x5 << ADS1115_PGA_SHIFT, + ADS1115_PGA_MASK = 0x7 << ADS1115_PGA_SHIFT, +}; + + +enum ads1115_mux { + ADS1115_MUX_DIFF_AIN0_AIN1 = 0, + ADS1115_MUX_DIFF_AIN0_AIN3 = 0x1 << ADS1115_MUX_SHIFT, + ADS1115_MUX_DIFF_AIN1_AIN3 = 0x2 << ADS1115_MUX_SHIFT, + ADS1115_MUX_DIFF_AIN2_AIN3 = 0x3 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN0 = 0x4 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN1 = 0x5 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN2 = 0x6 << ADS1115_MUX_SHIFT, + ADS1115_MUX_GND_AIN3 = 0x7 << ADS1115_MUX_SHIFT, + ADS1115_MUX_MASK = 0x7 << ADS1115_MUX_SHIFT, +}; + +class ADS1115 { +public: + ADS1115(uint8_t address = 0x48); + + void begin(); + uint8_t trigger_sample(); + uint8_t reset(); + bool is_sample_in_progress(); + int16_t read_sample(); + float sample_to_float(int16_t val); + float read_sample_float(); + + void set_comp_queue(enum ads1115_comp_queue val) { set_config(val, ADS1115_COMP_QUEUE_MASK); } + void set_comp_latching(enum ads1115_comp_latch val) { set_config(val, ADS1115_COMP_LATCH_MASK); } + void set_comp_polarity(enum ads1115_comp_polarity val) { set_config(val, ADS1115_COMP_POLARITY_MASK); } + void set_comp_mode(enum ads1115_comp_mode val) { set_config(val, ADS1115_COMP_MODE_MASK); } + void set_data_rate(enum ads1115_data_rate val) { set_config(val, ADS1115_DATA_RATE_MASK); } + void set_mode(enum ads1115_mode val) { set_config(val, ADS1115_MODE_MASK); } + void set_pga(enum ads1115_pga val) { set_config(val, ADS1115_PGA_MASK); m_voltage_range = val >> ADS1115_PGA_SHIFT; } + void set_mux(enum ads1115_mux val) { set_config(val, ADS1115_MUX_MASK); } + +private: + void set_config(uint16_t val, uint16_t mask) { + m_config = (m_config & ~mask) | val; + } + + uint8_t write_register(uint8_t reg, uint16_t val); + uint16_t read_register(uint8_t reg); + + uint8_t m_address; + uint16_t m_config; + int m_voltage_range; +}; + + +enum ads1115_register { + ADS1115_REGISTER_CONVERSION = 0, + ADS1115_REGISTER_CONFIG = 1, + ADS1115_REGISTER_LOW_THRESH = 2, + ADS1115_REGISTER_HIGH_THRESH = 3, +}; + +#define FACTOR 32768.0 +static float ranges[] = { 6.144 / FACTOR, 4.096 / FACTOR, 2.048 / FACTOR, 1.024 / FACTOR, 0.512 / FACTOR, 0.256 / FACTOR}; + +ADS1115::ADS1115(uint8_t address) +{ + m_address = address; + m_config = ADS1115_COMP_QUEUE_AFTER_ONE | + ADS1115_COMP_LATCH_NO | + ADS1115_COMP_POLARITY_ACTIVE_LOW | + ADS1115_COMP_MODE_WINDOW | + ADS1115_DATA_RATE_128_SPS | + ADS1115_MODE_SINGLE_SHOT | + ADS1115_MUX_GND_AIN0; + set_pga(ADS1115_PGA_ONE); +} + +uint8_t ADS1115::write_register(uint8_t reg, uint16_t val) +{ + Wire.beginTransmission(m_address); + Wire.write(reg); + Wire.write(val>>8); + Wire.write(val & 0xFF); + return Wire.endTransmission(); +} + +uint16_t ADS1115::read_register(uint8_t reg) +{ + Wire.beginTransmission(m_address); + Wire.write(reg); + Wire.endTransmission(); + + uint8_t result = Wire.requestFrom((int)m_address, 2, 1); + if (result != 2) { + return 0; + } + + uint16_t val; + + val = Wire.read() << 8; + val |= Wire.read(); + return val; +} + +void ADS1115::begin() +{ + Wire.begin(); +} + +uint8_t ADS1115::trigger_sample() +{ + return write_register(ADS1115_REGISTER_CONFIG, m_config | SAMPLE_BIT); +} + +uint8_t ADS1115::reset() +{ + Wire.beginTransmission(0); + Wire.write(0x6); + return Wire.endTransmission(); +} + +bool ADS1115::is_sample_in_progress() +{ + uint16_t val = read_register(ADS1115_REGISTER_CONFIG); + return (val & SAMPLE_BIT) == 0; +} + +int16_t ADS1115::read_sample() +{ + return read_register(ADS1115_REGISTER_CONVERSION); +} + +float ADS1115::sample_to_float(int16_t val) +{ + return val * ranges[m_voltage_range]; +} + +float ADS1115::read_sample_float() +{ + return sample_to_float(read_sample()); +} + +ADS1115 adc; + +void ADS1115_init(void) { + + ads1115_up=0; + if (!i2c_flg) return; + + adc.begin(); + adc.set_data_rate(ADS1115_DATA_RATE_128_SPS); + adc.set_mode(ADS1115_MODE_CONTINUOUS); + adc.set_mux(ADS1115_MUX_DIFF_AIN0_AIN3); + adc.set_pga(ADS1115_PGA_TWO); + + int16_t val = adc.read_sample(); + ads1115_up=1; +} + +#endif + +char sml_start; +uint8_t dump2log=0; + +#define SML_SAVAILABLE Serial_available() +#define SML_SREAD Serial_read() +#define SML_SPEAK Serial_peek() + +bool Serial_available() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->available(); +} + +uint8_t Serial_read() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->read(); +} + +uint8_t Serial_peek() { + uint8_t num=dump2log&7; + if (num<1 || num>meters_used) num=1; + return meter_ss[num-1]->peek(); +} + +uint8_t sml_logindex; + +void Dump2log(void) { + +int16_t index=0,hcnt=0; +uint32_t d_lastms; +uint8_t dchars[16]; + + + + if (dump2log&8) { + + while (SML_SAVAILABLE) { + log_data[index]=':'; + index++; + log_data[index]=' '; + index++; + d_lastms=millis(); + while ((millis()-d_lastms)<40) { + if (SML_SAVAILABLE) { + uint8_t c=SML_SREAD; + sprintf(&log_data[index],"%02x ",c); + dchars[hcnt]=c; + index+=3; + hcnt++; + if (hcnt>15) { + + log_data[index]='='; + index++; + log_data[index]='>'; + index++; + log_data[index]=' '; + index++; + for (uint8_t ccnt=0; ccnt<16; ccnt++) { + if (isprint(dchars[ccnt])) { + log_data[index]=dchars[ccnt]; + } else { + log_data[index]=' '; + } + index++; + } + break; + } + } + } + if (index>0) { + log_data[index]=0; + AddLog(LOG_LEVEL_INFO); + index=0; + hcnt=0; + } + } + } else { + if (meter_desc_p[(dump2log&7)-1].type=='o') { + + while (SML_SAVAILABLE) { + char c=SML_SREAD&0x7f; + if (c=='\n' || c=='\r') { + log_data[sml_logindex]=0; + AddLog(LOG_LEVEL_INFO); + sml_logindex=2; + log_data[0]=':'; + log_data[1]=' '; + break; + } + log_data[sml_logindex]=c; + if (sml_logindex2) { + log_data[index]=0; + AddLog(LOG_LEVEL_INFO); + } + } + } +} + + +uint8_t *skip_sml(uint8_t *cp,int16_t *res) { + uint8_t len,len1,type; + len=*cp&0xf; + type=*cp&0x70; + if (type==0x70) { + + + cp++; + while (len--) { + len1=*cp&0x0f; + cp+=len1; + } + *res=0; + } else { + + *res=(signed char)*(cp+1); + cp+=len; + } + return cp; +} + + + +double sml_getvalue(unsigned char *cp,uint8_t index) { +uint8_t len,unit,type; +int16_t scaler,result; +int64_t value; +double dval; + + + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + + cp=skip_sml(cp,&result); + scaler=result; + + type=*cp&0x70; + len=*cp&0x0f; + cp++; + if (type==0x50 || type==0x60) { + + uint64_t uvalue=0; + uint8_t nlen=len; + while (--nlen) { + uvalue<<=8; + uvalue|=*cp++; + } + if (type==0x50) { + + switch (len-1) { + case 1: + + value=(signed char)uvalue; + break; + case 2: + +#ifdef DWS74_BUG + if (scaler==-2) { + value=(uint32_t)uvalue; + } else { + value=(int16_t)uvalue; + } +#else + value=(int16_t)uvalue; +#endif + break; + case 3: + case 4: + + value=(int32_t)uvalue; + break; + case 5: + case 6: + case 7: + case 8: + + value=(int64_t)uvalue; + break; + } + } else { + + value=uvalue; + } + + } else { + if (!(type&0xf0)) { + + + + if (len==9) { + + cp++; + uint32_t s1,s2; + s1=*cp<<16|*(cp+1)<<8|*(cp+2); + cp+=4; + s2=*cp<<16|*(cp+1)<<8|*(cp+2); + sprintf(&meter_id[index][0],"%u-%u",s1,s2); + } else { + + char *str=&meter_id[index][0]; + for (type=0; type= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + } + return rVal; +} + +uint8_t sb_counter; + + +double CharToDouble(const char *str) +{ + + char strbuf[24]; + + strlcpy(strbuf, str, sizeof(strbuf)); + char *pt = strbuf; + while ((*pt != '\0') && isblank(*pt)) { pt++; } + + signed char sign = 1; + if (*pt == '-') { sign = -1; } + if (*pt == '-' || *pt=='+') { pt++; } + + double left = 0; + if (*pt != '.') { + left = atoi(pt); + while (isdigit(*pt)) { pt++; } + } + + double right = 0; + if (*pt == '.') { + pt++; + right = atoi(pt); + while (isdigit(*pt)) { + pt++; + right /= 10.0; + } + } + + double result = left + right; + if (sign < 0) { + return -result; + } + return result; +} + + + +void ebus_esc(uint8_t *ebus_buffer, unsigned char len) { + short count,count1; + for (count=0; countavailable()) { + meter_ss[meters]->read(); + } +} + + +void sml_shift_in(uint32_t meters,uint32_t shard) { + uint32_t count; + if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p') { + + for (count=0; countread(); + + if (meter_desc_p[meters].type=='o') { + smltbuf[meters][SML_BSIZ-1]=iob&0x7f; + } else if (meter_desc_p[meters].type=='s') { + smltbuf[meters][SML_BSIZ-1]=iob; + } else if (meter_desc_p[meters].type=='r') { + smltbuf[meters][SML_BSIZ-1]=iob; + } else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M') { + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=9) { + SML_Decode(meters); + sml_empty_receiver(meters); + meter_spos[meters]=0; + } + } else if (meter_desc_p[meters].type=='p') { + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=7) { + SML_Decode(meters); + sml_empty_receiver(meters); + meter_spos[meters]=0; + } + } else { + if (iob==EBUS_SYNC) { + + + if (meter_spos[meters]>4+5) { + + uint8_t tlen=smltbuf[meters][4]+5; + + if (smltbuf[meters][tlen]=ebus_CalculateCRC(smltbuf[meters],tlen)) { + ebus_esc(smltbuf[meters],tlen); + SML_Decode(meters); + } else { + + + } + } + meter_spos[meters]=0; + return; + } + smltbuf[meters][meter_spos[meters]] = iob; + meter_spos[meters]++; + if (meter_spos[meters]>=SML_BSIZ) { + meter_spos[meters]=0; + } + } + sb_counter++; + if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p') SML_Decode(meters); +} + + + +void SML_Poll(void) { +uint32_t meters; + + for (meters=0; metersavailable()) { + sml_shift_in(meters,0); + } + } + } +} + + +void SML_Decode(uint8_t index) { + const char *mp=(const char*)meter_p; + int8_t mindex; + uint8_t *cp; + uint8_t dindex=0,vindex=0; + delay(0); + while (mp != NULL) { + + + + mindex=((*mp)&7)-1; + + if (mindex<0 || mindex>=meters_used) mindex=0; + mp+=2; + if (*mp=='=' && *(mp+1)=='h') { + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + + if (index!=mindex) goto nextsect; + + + cp=&smltbuf[mindex][0]; + + + if (*mp=='=') { + + mp++; + + if (*mp=='m' && !sb_counter) { + + + mp++; + while (*mp==' ') mp++; + + double dvar; + uint8_t opr; + uint32_t ind; + ind=atoi(mp); + while (*mp>='0' && *mp<='9') mp++; + if (ind<1 || ind>SML_MAX_VARS) ind=1; + dvar=meter_vars[ind-1]; + for (uint8_t p=0;p<5;p++) { + if (*mp=='@') { + + meter_vars[vindex]=dvar; + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + break; + } + opr=*mp; + mp++; + uint8_t iflg=0; + if (*mp=='#') { + iflg=1; + mp++; + } + ind=atoi(mp); + while (*mp>='0' && *mp<='9') mp++; + if (ind<1 || ind>SML_MAX_VARS) ind=1; + switch (opr) { + case '+': + if (iflg) dvar+=ind; + else dvar+=meter_vars[ind-1]; + break; + case '-': + if (iflg) dvar-=ind; + else dvar-=meter_vars[ind-1]; + break; + case '*': + if (iflg) dvar*=ind; + else dvar*=meter_vars[ind-1]; + break; + case '/': + if (iflg) dvar/=ind; + else dvar/=meter_vars[ind-1]; + break; + } + while (*mp==' ') mp++; + if (*mp=='@') { + + meter_vars[vindex]=dvar; + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + break; + } + } + } else if (*mp=='d') { + + if (dindex='0' && *mp<='9') mp++; + if (ind<1 || ind>SML_MAX_VARS) ind=1; + uint32_t delay=atoi(mp)*1000; + uint32_t dtime=millis()-dtimes[dindex]; + if (dtime>delay) { + + dtimes[dindex]=millis(); + double vdiff = meter_vars[ind-1]-dvalues[dindex]; + dvalues[dindex]=meter_vars[ind-1]; + meter_vars[vindex]=(double)360000.0*vdiff/((double)dtime/10000.0); + + mp=strchr(mp,'@'); + if (mp) { + mp++; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + } + } + dindex++; + } + } else if (*mp=='h') { + + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + } else { + + uint8_t found=1; + uint32_t ebus_dval=99; + float mbus_dval=99; + while (*mp!='@') { + if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') { + if (*mp++!=*cp++) { + found=0; + } + } else { + if (meter_desc_p[mindex].type=='s') { + + uint8_t val = hexnibble(*mp++) << 4; + val |= hexnibble(*mp++); + if (val!=*cp++) { + found=0; + } + } else { + + + if (*mp=='x' && *(mp+1)=='x') { + + mp+=2; + cp++; + } else if (!strncmp(mp,"UUuuUUuu",8)) { + uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + ebus_dval=val; + mbus_dval=val; + mp+=8; + cp+=4; + } else if (*mp=='U' && *(mp+1)=='U' && *(mp+2)=='u' && *(mp+3)=='u'){ + uint16_t val = cp[1]|(cp[0]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (!strncmp(mp,"SSssSSss",8)) { + int32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + ebus_dval=val; + mbus_dval=val; + mp+=8; + cp+=4; + } else if (*mp=='u' && *(mp+1)=='u' && *(mp+2)=='U' && *(mp+3)=='U'){ + uint16_t val = cp[0]|(cp[1]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (*mp=='u' && *(mp+1)=='u') { + uint8_t val = *cp++; + mbus_dval=val; + ebus_dval=val; + mp+=2; + } else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='S' && *(mp+3)=='S') { + int16_t val = *cp|(*(cp+1)<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } else if (*mp=='S' && *(mp+1)=='S' && *(mp+2)=='s' && *(mp+3)=='s') { + int16_t val = cp[1]|(cp[0]<<8); + mbus_dval=val; + ebus_dval=val; + mp+=4; + cp+=2; + } + else if (*mp=='s' && *(mp+1)=='s') { + int8_t val = *cp++; + mbus_dval=val; + ebus_dval=val; + mp+=2; + } + else if (!strncmp(mp,"ffffffff",8)) { + uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); + float *fp=(float*)&val; + ebus_dval=*fp; + mbus_dval=*fp; + mp+=8; + cp+=4; + } + else if (!strncmp(mp,"FFffFFff",8)) { + + uint32_t val= (cp[1]<<0)|(cp[0]<<8)|(cp[3]<<16)|(cp[2]<<24); + float *fp=(float*)&val; + ebus_dval=*fp; + mbus_dval=*fp; + mp+=8; + cp+=4; + } + else if (!strncmp(mp,"eeeeee",6)) { + uint32_t val=(cp[0]<<16)|(cp[1]<<8)|(cp[2]<<0); + mbus_dval=val; + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"vvvvvv",6)) { + mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/10.0); + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"cccccc",6)) { + mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/100.0); + mp+=6; + cp+=3; + } + else if (!strncmp(mp,"pppp",4)) { + mbus_dval=(float)((cp[0]<<8)|cp[1]); + mp+=4; + cp+=2; + } + else { + uint8_t val = hexnibble(*mp++) << 4; + val |= hexnibble(*mp++); + if (val!=*cp++) { + found=0; + } + } + } + } + } + if (found) { + + mp++; + if (*mp=='#') { + + mp++; + if (meter_desc_p[mindex].type=='o') { + for (uint8_t p=0;p>=shift; + ebus_dval&=1; + mp+=2; + } + if (*mp=='i') { + + mp++; + uint8_t mb_index=strtol((char*)mp,(char**)&mp,10); + if (mb_index!=meter_desc_p[mindex].index) { + goto nextsect; + } + uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7); + if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect; + if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect; + dval=mbus_dval; + + mp++; + } else { + if (meter_desc_p[mindex].type=='p') { + uint8_t crc = SML_PzemCrc(&smltbuf[mindex][0],6); + if (crc!=smltbuf[mindex][6]) goto nextsect; + dval=mbus_dval; + } else { + dval=ebus_dval; + } + } + + } +#ifdef USE_SML_MEDIAN_FILTER + if (meter_desc_p[mindex].flag&16) { + meter_vars[vindex]=sml_median(&sml_mf[vindex],dval); + } else { + meter_vars[vindex]=dval; + } +#else + meter_vars[vindex]=dval; +#endif + + + double fac=CharToDouble((char*)mp); + meter_vars[vindex]/=fac; + SML_Immediate_MQTT((const char*)mp,vindex,mindex); + } + } + } +nextsect: + + if (vindex=meters_used) lastmind=0; + while (mp != NULL) { + + mindex=((*mp)&7)-1; + if (mindex<0 || mindex>=meters_used) mindex=0; + mp+=2; + if (*mp=='=' && *(mp+1)=='h') { + mp+=2; + + if (json) { + mp = strchr(mp, '|'); + if (mp) mp++; + continue; + } + + uint8_t i; + for (i=0;isml_counters[index].sml_debounce) { + RtcSettings.pulse_counter[index]++; + InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]); + } + } else { + + sml_counters[index].sml_counter_ltime=millis(); + } +} + +void SML_CounterUpd1(void) { + SML_CounterUpd(0); +} + +void SML_CounterUpd2(void) { + SML_CounterUpd(1); +} + +void SML_CounterUpd3(void) { + SML_CounterUpd(2); +} + +void SML_CounterUpd4(void) { + SML_CounterUpd(3); +} + +#ifdef USE_SCRIPT +struct METER_DESC script_meter_desc[MAX_METERS]; +uint8_t *script_meter; +#endif + +#ifndef METER_DEF_SIZE +#define METER_DEF_SIZE 3000 +#endif + +bool Gpio_used(uint8_t gpiopin) { + for (uint16_t i=0;iM",-2,0); + if (meter_script==99) { + + if (script_meter) free(script_meter); + script_meter=0; + uint8_t *tp=0; + uint16_t index=0; + uint8_t section=0; + uint8_t srcpin=0; + char *lp=glob_script_mem.scriptptr; + sml_send_blocks=0; + while (lp) { + if (!section) { + if (*lp=='>' && *(lp+1)=='M') { + lp+=2; + meters_used=strtol(lp,0,10); + section=1; + uint32_t mlen=0; + for (uint32_t cnt=0;cnt') { + if (*(tp-1)=='|') *(tp-1)=0; + break; + } + if (*lp=='+') { + + + lp++; + index=*lp&7; + lp+=2; + if (index<1 || index>meters_used) goto next_line; + index--; + srcpin=strtol(lp,&lp,10); + if (Gpio_used(srcpin)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("gpio rx double define!")); +dddef_exit: + if (script_meter) free(script_meter); + script_meter=0; + meters_used=METERS_USED; + goto init10; + } + script_meter_desc[index].srcpin=srcpin; + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].type=*lp; + lp+=2; + script_meter_desc[index].flag=strtol(lp,&lp,10); + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].params=strtol(lp,&lp,10); + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].prefix[7]=0; + for (uint32_t cnt=0; cnt<8; cnt++) { + if (*lp==SCRIPT_EOL || *lp==',') { + script_meter_desc[index].prefix[cnt]=0; + break; + } + script_meter_desc[index].prefix[cnt]=*lp++; + } + if (*lp==',') { + lp++; + script_meter_desc[index].trxpin=strtol(lp,&lp,10); + if (Gpio_used(script_meter_desc[index].trxpin)) { + AddLog_P(LOG_LEVEL_INFO, PSTR("gpio tx double define!")); + goto dddef_exit; + } + if (*lp!=',') goto next_line; + lp++; + script_meter_desc[index].tsecs=strtol(lp,&lp,10); + if (*lp==',') { + lp++; + char txbuff[256]; + uint32_t txlen=0,tx_entries=1; + for (uint32_t cnt=0; cntmeters_used) goto next_line; + while (1) { + if (*lp==SCRIPT_EOL) { + if (*(tp-1)!='|') *tp++='|'; + goto next_line; + } + *tp++=*lp++; + index++; + if (index>=METER_DEF_SIZE) break; + } + } + + } + +next_line: + if (*lp==SCRIPT_EOL) { + lp++; + } else { + lp = strchr(lp, SCRIPT_EOL); + if (!lp) break; + lp++; + } + } + *tp=0; + meter_desc_p=script_meter_desc; + meter_p=script_meter; + } +#endif + +init10: + typedef void (*function)(); + function counter_callbacks[] = {SML_CounterUpd1,SML_CounterUpd2,SML_CounterUpd3,SML_CounterUpd4}; + uint8_t cindex=0; + + for (byte i = 0; i < MAX_COUNTERS; i++) { + RtcSettings.pulse_counter[i]=Settings.pulse_counter[i]; + sml_counters[i].sml_cnt_last_ts=millis(); + } + for (uint8_t meters=0; metersbegin(meter_desc_p[meters].params)) { + meter_ss[meters]->flush(); + } + if (meter_ss[meters]->hardwareSerial()) { + if (meter_desc_p[meters].type=='M') { + Serial.begin(meter_desc_p[meters].params, SERIAL_8E1); + } + ClaimSerial(); + } + + } + } + +} + + +#ifdef USE_SML_SCRIPT_CMD +uint32_t SML_SetBaud(uint32_t meter, uint32_t br) { + if (meter<1 || meter>meters_used) return 0; + meter--; + if (!meter_ss[meter]) return 0; + if (meter_ss[meter]->begin(br)) { + meter_ss[meter]->flush(); + } + if (meter_ss[meter]->hardwareSerial()) { + if (meter_desc_p[meter].type=='M') { + Serial.begin(br, SERIAL_8E1); + } + } + return 1; +} + +uint32_t SML_Write(uint32_t meter,char *hstr) { + if (meter<1 || meter>meters_used) return 0; + meter--; + if (!meter_ss[meter]) return 0; + SML_Send_Seq(meter,hstr); + return 1; +} +#endif + + +void SetDBGLed(uint8_t srcpin, uint8_t ledpin) { + pinMode(ledpin, OUTPUT); + if (digitalRead(srcpin)) { + digitalWrite(ledpin,LOW); + } else { + digitalWrite(ledpin,HIGH); + } +} + + +void SML_Counter_Poll(void) { +uint16_t meters,cindex=0; +uint32_t ctime=millis(); + + for (meters=0; meters0) { + if (ctime-sml_counters[cindex].sml_cnt_last_ts>meter_desc_p[meters].params) { + sml_counters[cindex].sml_cnt_last_ts=ctime; + + if (meter_desc_p[meters].flag&2) { + +#ifdef ANALOG_OPTO_SENSOR + if (ads1115_up) { + int16_t val = adc.read_sample(); + if (val>sml_counters[cindex].ana_max) sml_counters[cindex].ana_max=val; + if (val10) { + sml_counters[cindex].sml_cnt_last_ts=ctime; +#ifdef DEBUG_CNT_LED1 + if (cindex==0) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED1); +#endif +#ifdef DEBUG_CNT_LED2 + if (cindex==1) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED2); +#endif + } + } + cindex++; + } + } +} + +#ifdef USE_SCRIPT +char *SML_Get_Sequence(char *cp,uint32_t index) { + if (!index) return cp; + uint32_t cindex=0; + while (cp) { + cp=strchr(cp,','); + if (cp) { + cp++; + cindex++; + if (cindex==index) { + return cp; + } + } + } +} + +void SML_Check_Send(void) { + sml_100ms_cnt++; + char *cp; + for (uint32_t cnt=sml_desc_cnt; cnt=0 && script_meter_desc[cnt].txmem) { + if ((sml_100ms_cnt%script_meter_desc[cnt].tsecs)==0) { + if (script_meter_desc[cnt].max_index>1) { + script_meter_desc[cnt].index++; + if (script_meter_desc[cnt].index>=script_meter_desc[cnt].max_index) { + script_meter_desc[cnt].index=0; + sml_desc_cnt++; + } + cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index); + + } else { + cp=script_meter_desc[cnt].txmem; + + sml_desc_cnt++; + } + + SML_Send_Seq(cnt,cp); + if (sml_desc_cnt>=meters_used) { + sml_desc_cnt=0; + } + break; + } + } else { + sml_desc_cnt++; + } + + if (sml_desc_cnt>=meters_used) { + sml_desc_cnt=0; + } + } +} + +uint8_t sml_hexnibble(char chr) { + uint8_t rVal = 0; + if (isdigit(chr)) { + rVal = chr - '0'; + } else { + if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; + if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; + } + return rVal; +} + + +void SML_Send_Seq(uint32_t meter,char *seq) { + uint8_t sbuff[32]; + uint8_t *ucp=sbuff,slen=0; + char *cp=seq; + while (*cp) { + if (!*cp || !*(cp+1)) break; + if (*cp==',') break; + uint8_t iob=(sml_hexnibble(*cp) << 4) | sml_hexnibble(*(cp+1)); + cp+=2; + *ucp++=iob; + slen++; + if (slen>=sizeof(sbuff)) break; + } + if (script_meter_desc[meter].type=='m' || script_meter_desc[meter].type=='M') { + *ucp++=0; + *ucp++=2; + + uint16_t crc = MBUS_calculateCRC(sbuff,6); + *ucp++=lowByte(crc); + *ucp++=highByte(crc); + slen+=4; + } + if (script_meter_desc[meter].type=='o') { + for (uint32_t cnt=0;cntwrite(sbuff,slen); +} +#endif + +uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { + uint16_t crc, flag; + crc = 0xFFFF; + for (uint32_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint32_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + return crc; +} + +uint8_t SML_PzemCrc(uint8_t *data, uint8_t len) { + uint16_t crc = 0; + for (uint32_t i = 0; i < len; i++) crc += *data++; + return (uint8_t)(crc & 0xFF); +} + + +uint8_t CalcEvenParity(uint8_t data) { +uint8_t parity=0; + + while(data) { + parity^=(data &1); + data>>=1; + } + return parity; +} +# 2361 "S:/Development/Tasmota/tasmota/xsns_53_sml.ino" +bool XSNS_53_cmd(void) { + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + char *cp=XdrvMailbox.data; + if (*cp=='d') { + + cp++; + uint8_t index=atoi(cp); + if ((index&7)>meters_used) index=1; + if (index>0 && meter_desc_p[(index&7)-1].type=='c') { + index=0; + } + dump2log=index; + ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); + } else if (*cp=='c') { + + cp++; + uint8_t index=*cp&7; + if (index<1 || index>MAX_COUNTERS) index=1; + cp++; + while (*cp==' ') cp++; + if (isdigit(*cp)) { + uint32_t cval=atoi(cp); + while (isdigit(*cp)) cp++; + RtcSettings.pulse_counter[index-1]=cval; + uint8_t cindex=0; + for (uint8_t meters=0; metersaddress, INA226_REG_CALIBRATION, si->calibrationValue); + +} + + + + + + +bool Ina226TestPresence(uint8_t device) +{ + + + + uint16_t config = I2cRead16( slaveInfo[device].address, INA226_REG_CONFIG ); + + + if (config != slaveInfo[device].config) + return false; + + return true; + +} + +void Ina226ResetActive(void) +{ + Ina226SlaveInfo_t *p = slaveInfo; + + for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) { + p = &slaveInfo[i]; + + uint8_t addr = p->address; + if (addr) { + I2cResetActive(addr); + } + } +} + + + + + +void Ina226Init() +{ + uint32_t i; + + slavesFound = 0; + + Ina226SlaveInfo_t *p = slaveInfo; +# 215 "S:/Development/Tasmota/tasmota/xsns_54_ina226.ino" + for (i = 0; i < 4; i++){ + *p = {0}; + } + + + + + + for (i = 0; i < INA226_MAX_ADDRESSES; i++){ + uint8_t addr = pgm_read_byte(probeAddresses + i); + + if (I2cActive(addr)) { continue; } + + + + + if (!Settings.ina226_i_fs[i]) + continue; + + + + + + + if (!I2cWrite16( addr, INA226_REG_CONFIG, INA226_CONFIG_RESET)){ + + AddLog_P2( LOG_LEVEL_DEBUG, "No INA226 at address: %02X", addr); + continue; + } + + + + uint16_t config = I2cRead16( addr, INA226_REG_CONFIG ); + + + if (INA226_RES_CONFIG != config) + continue; + + + config = INA226_DEF_CONFIG; + + + if (!I2cWrite16( addr, INA226_REG_CONFIG, config)) + continue; + + + p = &slaveInfo[i]; + + p->address = addr; + + p->config = config; + + + p->i_lsb = (((float) Settings.ina226_i_fs[i])/10.0f)/32768.0f; + + + + uint32_t r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[i]); + + + + p->calibrationValue = ((uint16_t) (0.00512/(p->i_lsb * r_shunt_uohms/1000000.0f))); + + p->present = true; + + + Ina226SetCalibration(i); + + I2cSetActiveFound(addr, Ina226Str); + + slavesFound++; + } +} + + + + + +float Ina226ReadBus_v(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE); + + float result = ((float) reg_bus_v) * 0.00125f; + + return result; + +} + + + + + +float Ina226ReadShunt_i(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); + + float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb; + + return result; +} + + + + + +float Ina226ReadPower_w(uint8_t device) +{ + uint8_t addr = slaveInfo[device].address; + int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); + + float result = ((float) reg_shunt_i) * (slaveInfo[device].i_lsb * 25.0); + + return result; +} + + + + + + +void Ina226Read(uint8_t device) +{ + + voltages[device] = Ina226ReadBus_v(device); + currents[device] = Ina226ReadShunt_i(device); + powers[device] = Ina226ReadPower_w(device); + + + + +} + + + + + +void Ina226EverySecond() +{ + + for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){ + + if (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){ + Ina226Read(device); + } + else { + powers[device] = currents[device] = voltages[device] = 0.0f; + + + + + + + slaveInfo[device].present = false; + } + } +} + + + + + +bool Ina226CommandSensor() +{ + bool serviced = true; + bool show_config = false; + char param_str[64]; + char *cp, *params[4]; + uint8_t i, param_count, device, p1 = XdrvMailbox.payload; + uint32_t r_shunt_uohms; + uint16_t compact_r_shunt_uohms; + + + + + + if (XdrvMailbox.data_len > 62){ + return false; + } + + strncpy(param_str, XdrvMailbox.data, XdrvMailbox.data_len + 1); + param_str[XdrvMailbox.data_len] = 0; + + + for (cp = param_str, i = 0, param_count = 0; *cp && (i < XdrvMailbox.data_len + 1) && (param_count <= 3); i++) + if (param_str[i] == ' ' || param_str[i] == ',' || param_str[i] == 0){ + param_str[i] = 0; + params[param_count] = cp; + + param_count++; + cp = param_str + i + 1; + } + + + if (p1 < 10 || p1 >= 50){ + + switch (p1){ + case 1: + Ina226ResetActive(); + Ina226Init(); + Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound); + break; + + case 2: + restart_flag = 2; + Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag); + break; + + default: + serviced = false; + } + } + else if (p1 < 50){ + + device = (p1 / 10) - 1; + switch (p1 % 10){ + case 0: + show_config = true; + break; + + case 1: + r_shunt_uohms = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f); + + + + if (r_shunt_uohms > 32767){ + uint32_t r_shunt_mohms = r_shunt_uohms/1000UL; + Settings.ina226_r_shunt[device] = (uint16_t) (r_shunt_mohms | 0x8000); + } + else + Settings.ina226_r_shunt[device] = (uint16_t) r_shunt_uohms; + + + show_config = true; + break; + + case 2: + Settings.ina226_i_fs[device] = (uint16_t) ((CharToFloat(params[1])) * 10.0f); + + show_config = true; + break; + + + default: + serviced = false; + break; + } + } + else + serviced = false; + + if (show_config) { + char shunt_r_str[16]; + char fs_i_str[16]; + + + r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[device]); + dtostrfd(((float)r_shunt_uohms)/1000000.0f, 6, shunt_r_str); + + dtostrfd(((float)Settings.ina226_i_fs[device])/10.0f, 1, fs_i_str); + + Response_P(PSTR("{\"Sensor54-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"), + device + 1, shunt_r_str, fs_i_str); + } + + return serviced; +} + + + + + +#ifdef USE_WEBSERVER +const char HTTP_SNS_INA226_DATA[] PROGMEM = + "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" + "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" + "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; +#endif + +void Ina226Show(bool json) +{ + int i, num_found; + for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) { + + if (!slaveInfo[i].present) + continue; + + num_found++; + + char voltage[16]; + dtostrfd(voltages[i], Settings.flag2.voltage_resolution, voltage); + char current[16]; + dtostrfd(currents[i], Settings.flag2.current_resolution, current); + char power[16]; + dtostrfd(powers[i], Settings.flag2.wattage_resolution, power); + char name[16]; + snprintf_P(name, sizeof(name), PSTR("INA226%c%d"),IndexSeparator(), i + 1); + + + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%d,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + name, i, voltage, current, power); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, voltage); + DomoticzSensor(DZ_CURRENT, current); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_INA226_DATA, name, voltage, name, current, name, power); +#endif + } + + } + +} +# 546 "S:/Development/Tasmota/tasmota/xsns_54_ina226.ino" +bool Xsns54(byte callback_id) +{ + if (!I2cEnabled(XI2C_35)) { return false; } + + + bool result = false; + + + switch (callback_id) { + case FUNC_EVERY_SECOND: + Ina226EverySecond(); + break; + case FUNC_JSON_APPEND: + Ina226Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ina226Show(0); + break; +#endif + case FUNC_COMMAND_SENSOR: + if (XSNS_54 == XdrvMailbox.index) { + result = Ina226CommandSensor(); + } + break; + case FUNC_INIT: + Ina226Init(); + break; + } + + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_55_hih_series.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_55_hih_series.ino" +#ifdef USE_I2C +#ifdef USE_HIH6 +# 33 "S:/Development/Tasmota/tasmota/xsns_55_hih_series.ino" +#define XSNS_55 55 +#define XI2C_36 36 + +#define HIH6_ADDR 0x27 + +struct HIH6 { + float temperature = 0; + float humidity = 0; + uint8_t valid = 0; + uint8_t type = 0; + char types[4] = "HIH"; +} Hih6; + +bool Hih6Read(void) +{ + Wire.beginTransmission(HIH6_ADDR); + if (Wire.endTransmission() != 0) { return false; } + + delay(40); + + uint8_t data[4]; + Wire.requestFrom(HIH6_ADDR, 4); + if (4 == Wire.available()) { + data[0] = Wire.read(); + data[1] = Wire.read(); + data[2] = Wire.read(); + data[3] = Wire.read(); + } else { return false; } + + + + Hih6.humidity = ConvertHumidity(((float)(((data[0] & 0x3F) << 8) | data[1]) * 100.0) / 16383.0); + + int temp = ((data[2] << 8) | (data[3] & 0xFC)) / 4; + Hih6.temperature = ConvertTemp(((float)temp / 16384.0) * 165.0 - 40.0); + + Hih6.valid = SENSOR_MAX_MISS; + return true; +} + + + +void Hih6Detect(void) +{ + if (I2cActive(HIH6_ADDR)) { return; } + + if (uptime < 2) { delay(20); } + Hih6.type = Hih6Read(); + if (Hih6.type) { + I2cSetActiveFound(HIH6_ADDR, Hih6.types); + } +} + +void Hih6EverySecond(void) +{ + if (uptime &1) { + + if (!Hih6Read()) { + AddLogMissed(Hih6.types, Hih6.valid); + } + } +} + +void Hih6Show(bool json) +{ + if (Hih6.valid) { + char temperature[33]; + dtostrfd(Hih6.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Hih6.humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Hih6.types, temperature, humidity); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, Hih6.temperature); + KnxSensor(KNX_HUMIDITY, Hih6.humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Hih6.types, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Hih6.types, humidity); +#endif + } + } +} + + + + + +bool Xsns55(uint8_t function) +{ + if (!I2cEnabled(XI2C_36)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Hih6Detect(); + } + else if (Hih6.type) { + switch (function) { + case FUNC_EVERY_SECOND: + Hih6EverySecond(); + break; + case FUNC_JSON_APPEND: + Hih6Show(1); + break; + #ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Hih6Show(0); + break; + #endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_56_hpma.ino" +# 21 "S:/Development/Tasmota/tasmota/xsns_56_hpma.ino" +#ifdef USE_HPMA +# 31 "S:/Development/Tasmota/tasmota/xsns_56_hpma.ino" +#define XSNS_56 56 + +#include +#include + +TasmotaSerial *HpmaSerial; +HPMA115S0 *hpma115S0; + +uint8_t hpma_type = 1; +uint8_t hpma_valid = 0; + +struct hpmadata { + unsigned int pm10; + unsigned int pm2_5; +} hpma_data; + + + +void HpmaSecond(void) +{ + unsigned int pm2_5, pm10; + + + + + if (hpma115S0->ReadParticleMeasurement(&pm2_5, &pm10)) { + hpma_data.pm2_5 = pm2_5; + hpma_data.pm10 = pm10; + hpma_valid = 1; + } + +} + +void HpmaInit(void) +{ + hpma_type = 0; + if (pin[GPIO_HPMA_RX] < 99 && pin[GPIO_HPMA_TX] < 99) { + HpmaSerial = new TasmotaSerial(pin[GPIO_HPMA_RX], pin[GPIO_HPMA_TX], 1); + hpma115S0 = new HPMA115S0(*HpmaSerial); + + if (HpmaSerial->begin(9600)) { + if (HpmaSerial->hardwareSerial()) { + ClaimSerial(); + } + hpma_type = 1; + hpma115S0->Init(); + hpma115S0->StartParticleMeasurement(); + } + } +} + +#ifdef USE_WEBSERVER +const char HTTP_HPMA_SNS[] PROGMEM = + "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" + "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; +#endif + +void HpmaShow(bool json) +{ + if (hpma_valid) { + char pm10[33]; + snprintf_P(pm10, 33, PSTR("%d"), hpma_data.pm10); + char pm2_5[33]; + snprintf_P(pm2_5, 33, PSTR("%d"), hpma_data.pm2_5); + + if (json) { + ResponseAppend_P(PSTR(",\"HPMA\":{\"PM2.5\":%d,\"PM10\":%d}"), hpma_data.pm2_5, hpma_data.pm10); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { + DomoticzSensor(DZ_VOLTAGE, pm2_5); + DomoticzSensor(DZ_CURRENT, pm10); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_HPMA_SNS, pm2_5, pm10); +#endif + } + } +} + + + + + +bool Xsns56(uint8_t function) +{ + bool result = false; + + if (hpma_type) { + switch (function) { + case FUNC_INIT: + HpmaInit(); + break; + case FUNC_EVERY_SECOND: + HpmaSecond(); + break; + case FUNC_COMMAND_SENSOR: + if (XSNS_56 == XdrvMailbox.index) { + return true; + } + break; + case FUNC_JSON_APPEND: + HpmaShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HpmaShow(0); + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_57_tsl2591.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_57_tsl2591.ino" +#ifdef USE_I2C +#ifdef USE_TSL2591 + + + + + + + +#define XSNS_57 57 +#define XI2C_40 40 + +#define TSL2591_ADDRESS 0x29 + +#include + +Adafruit_TSL2591 tsl = Adafruit_TSL2591(); + +uint8_t tsl2591_type = 0; +uint8_t tsl2591_valid = 0; +float tsl2591_lux = 0; + +void Tsl2591Init(void) +{ + + if (I2cSetDevice(0x29)) { + if (tsl.begin()) { + tsl.setGain(TSL2591_GAIN_MED); + tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS); + tsl2591_type = 1; + I2cSetActiveFound(TSL2591_ADDRESS, "TSL2591"); + } + } +} + +bool Tsl2591Read(void) +{ + uint32_t lum = tsl.getFullLuminosity(); + uint16_t ir, full; + ir = lum >> 16; + full = lum & 0xFFFF; + tsl2591_lux = tsl.calculateLux(full, ir); + tsl2591_valid = 1; +} + +void Tsl2591EverySecond(void) +{ + Tsl2591Read(); +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_TSL2591[] PROGMEM = + "{s}TSL2591 " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; +#endif + +void Tsl2591Show(bool json) +{ + if (tsl2591_valid) { + char lux_str[10]; + dtostrf(tsl2591_lux, sizeof(lux_str)-1, 3, lux_str); + if (json) { + ResponseAppend_P(PSTR(",\"TSL2591\":{\"" D_JSON_ILLUMINANCE "\":%s}"), lux_str); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TSL2591, lux_str); +#endif + } + } +} + + + + + +bool Xsns57(uint8_t function) +{ + if (!I2cEnabled(XI2C_40)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Tsl2591Init(); + } + else if (tsl2591_type) { + switch (function) { + case FUNC_EVERY_SECOND: + Tsl2591EverySecond(); + break; + case FUNC_JSON_APPEND: + Tsl2591Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tsl2591Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_58_dht12.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_58_dht12.ino" +#ifdef USE_I2C +#ifdef USE_DHT12 + + + + + + +#define XSNS_58 58 +#define XI2C_41 41 + +#define DHT12_ADDR 0x5C + +struct DHT12 { + float temperature = NAN; + float humidity = NAN; + uint8_t valid = 0; + uint8_t count = 0; + char name[6] = "DHT12"; +} Dht12; + +bool Dht12Read(void) +{ + if (Dht12.valid) { Dht12.valid--; } + + Wire.beginTransmission(DHT12_ADDR); + Wire.write(0); + if (Wire.endTransmission() != 0) { return false; } + + delay(50); + + Wire.requestFrom(DHT12_ADDR, 5); + delay(5); + uint8_t humidity = Wire.read(); + uint8_t humidityTenth = Wire.read(); + uint8_t temp = Wire.read(); + uint8_t tempTenth = Wire.read(); + uint8_t checksum = Wire.read(); + + Dht12.humidity = ConvertHumidity( (float) humidity + (float) humidityTenth/(float) 10.0 ); + Dht12.temperature = ConvertTemp( (float) temp + (float) tempTenth/(float) 10.0 ); + + if (isnan(Dht12.temperature) || isnan(Dht12.humidity)) { return false; } + + Dht12.valid = SENSOR_MAX_MISS; + return true; +} + + + +void Dht12Detect(void) +{ + if (I2cActive(DHT12_ADDR)) { return; } + + if (Dht12Read()) { + I2cSetActiveFound(DHT12_ADDR, Dht12.name); + Dht12.count = 1; + } +} + +void Dht12EverySecond(void) +{ + if (uptime &1) { + + if (!Dht12Read()) { + AddLogMissed(Dht12.name, Dht12.valid); + } + } +} + +void Dht12Show(bool json) +{ + if (Dht12.valid) { + char temperature[33]; + dtostrfd(Dht12.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(Dht12.humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht12.name, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, Dht12.temperature); + KnxSensor(KNX_HUMIDITY, Dht12.humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, Dht12.name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, Dht12.name, humidity); +#endif + } + } +} + + + + + +bool Xsns58(uint8_t function) +{ + if (!I2cEnabled(XI2C_41)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Dht12Detect(); + } + else if (Dht12.count) { + switch (function) { + case FUNC_EVERY_SECOND: + Dht12EverySecond(); + break; + case FUNC_JSON_APPEND: + Dht12Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Dht12Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_59_ds1624.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_59_ds1624.ino" +#ifdef USE_I2C +#ifdef USE_DS1624 + + + + + + + +#define XSNS_59 59 +#define XI2C_42 42 + +#define DS1624_MEM_REGISTER 0x17 +#define DS1624_CONF_REGISTER 0xAC +#define DS1624_TEMP_REGISTER 0xAA +#define DS1624_START_REGISTER 0xEE +#define DS1624_STOP_REGISTER 0x22 + +#define DS1621_COUNTER_REGISTER 0xA8 +#define DS1621_SLOPE_REGISTER 0xA9 + +#define DS1621_CFG_1SHOT (1<<0) +#define DS1621_CFG_DONE (1<<7) + +enum { + DS1624_TYPE_DS1624, + DS1624_TYPE_DS1621 +}; + +#define DS1624_MAX_SENSORS 8 + +bool ds1624_init = false; + +struct { + float value; + uint8_t type; + int errcnt; + int misscnt; + bool valid; + char name[9]; +} ds1624_sns[DS1624_MAX_SENSORS]; + +uint32_t DS1624_Idx2Addr(uint32_t idx) { + return 0x48 + idx; +} + +int DS1624_Restart(uint8_t config, uint32_t idx) { + uint32_t addr = DS1624_Idx2Addr(idx); + if ((config & 1) == 1) { + config &= ~(DS1621_CFG_DONE|DS1621_CFG_1SHOT); + I2cWrite8(addr, DS1624_CONF_REGISTER, config); + delay(10); + AddLog_P2(LOG_LEVEL_ERROR, "%s addr %x is reset, reconfig: %x", ds1624_sns[idx].name, addr, config); + } + I2cValidRead(addr, DS1624_START_REGISTER, 1); +} + +void DS1624_HotPlugUp(uint32_t idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + + if (I2cActive(addr)) { return; } + if (!I2cSetDevice(addr)) { return; } + + uint8_t config; + if (I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { + uint8_t tmp; + ds1624_sns[idx].type = (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) ? DS1624_TYPE_DS1624 : DS1624_TYPE_DS1621; + + snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS162%c%c%d"), + (ds1624_sns[idx].type == DS1624_TYPE_DS1621) ? '1' : '4', IndexSeparator(), idx); + I2cSetActiveFound(addr, ds1624_sns[idx].name); + + ds1624_sns[idx].valid = true; + ds1624_sns[idx].errcnt = 0; + ds1624_sns[idx].misscnt = 0; + DS1624_Restart(config,idx); + AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); + } +} + +void DS1624_HotPlugDown(int idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + if (!I2cActive(addr)) { return; } + I2cResetActive(addr); + ds1624_sns[idx].valid = false; + AddLog_P2(LOG_LEVEL_INFO, "Hot UnPlug %s", ds1624_sns[idx].name); +} + +bool DS1624GetTemp(float *value, int idx) +{ + uint32_t addr = DS1624_Idx2Addr(idx); + + uint8_t config; + if (!I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { + ds1624_sns[idx].misscnt++; + AddLog_P2(LOG_LEVEL_INFO, "%s device missing (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].misscnt); + return false; + } + ds1624_sns[idx].misscnt=0; + if (config & (DS1621_CFG_1SHOT|DS1621_CFG_DONE)) { + ds1624_sns[idx].errcnt++; + AddLog_P2(LOG_LEVEL_INFO, "%s config error, restart... (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].errcnt); + DS1624_Restart(config, idx); + return false; + } + + uint16_t t; + if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { return false; } + if (ds1624_sns[idx].type == DS1624_TYPE_DS1624) { + *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; + } else { + + *value = ((float)(int8_t)(t>>8)); + uint8_t remain; + if (!I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)) { return true; } + uint8_t perc; + if (!I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)) { return true; } + float fix=(float)(perc - remain)/(float)perc; + *value+=fix; + } + ds1624_sns[idx].errcnt=0; + config &= ~(DS1621_CFG_DONE); + I2cWrite8(addr, DS1624_CONF_REGISTER, config); + return true; +} + +void DS1624HotPlugScan(void) +{ + uint16_t t; + + for (uint32_t idx = 0; idx < DS1624_MAX_SENSORS; idx++) { + uint32_t addr = DS1624_Idx2Addr(idx); + if (I2cActive(addr) && !ds1624_sns[idx].valid) { + continue; + } + if (ds1624_sns[idx].valid) { + if ((ds1624_sns[idx].misscnt>2)||(ds1624_sns[idx].errcnt>2)) { + DS1624_HotPlugDown(idx); + continue; + } + } + DS1624_HotPlugUp(idx); + } +} + +void DS1624EverySecond(void) +{ + float t; + for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { + if (!ds1624_sns[i].valid) { continue; } + if (!DS1624GetTemp(&t, i)) { continue; } + ds1624_sns[i].value = ConvertTemp(t); + } +} + +void DS1624Show(bool json) +{ + char temperature[33]; + bool once = true; + + for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { + if (!ds1624_sns[i].valid) { continue; } + + dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); + if (json) { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds1624_sns[i].name, temperature); + if ((0 == tele_period) && once) { +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, temperature); +#endif + once = false; + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, ds1624_sns[i].name, temperature, TempUnit()); +#endif + } + } +} + + + + + +bool Xsns59(uint8_t function) +{ + if (!I2cEnabled(XI2C_42)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + if (!ds1624_init) { + memset(ds1624_sns, 0, sizeof(ds1624_sns)); + ds1624_init = true; + DS1624HotPlugScan(); + } + } + switch (function) { + case FUNC_HOTPLUG_SCAN: + DS1624HotPlugScan(); + break; + case FUNC_EVERY_SECOND: + DS1624EverySecond(); + break; + case FUNC_JSON_APPEND: + DS1624Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + DS1624Show(0); + break; +#endif + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_60_GPS.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_60_GPS.ino" +#ifdef USE_GPS +# 113 "S:/Development/Tasmota/tasmota/xsns_60_GPS.ino" +#define XSNS_60 60 + +#include "NTPServer.h" +#include "NTPPacket.h" + + + + + +#define D_CMND_UBX "UBX" + +const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; + +const char kUBXTypes[] PROGMEM = "UBX"; + +#define UBX_LAT_LON_THRESHOLD 1000 + +#define UBX_SERIAL_BUFFER_SIZE 256 +#define UBX_TCP_PORT 1234 + + + + + +const char UBLOX_INIT[] PROGMEM = { + + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, + 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, + + + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, + + + + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, + 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, + + + + + + +}; + +char UBX_name[4]; + +struct UBX_t { + const char UBX_HEADER[2] = { 0xB5, 0x62 }; + const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; + const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; + const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; + + struct entry_t { + int32_t lat; + int32_t lon; + uint32_t time; + }; + + union { + entry_t values; + uint8_t bytes[sizeof(entry_t)]; + } rec_buffer; + + struct POLL_MSG { + uint8_t cls; + uint8_t id; + uint16_t zero; + }; + + struct NAV_POSLLH { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + int32_t lon; + int32_t lat; + int32_t alt; + int32_t hMSL; + uint32_t hAcc; + uint32_t vAcc; + }; + + struct NAV_STATUS { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint8_t gpsFix; + uint8_t flags; + uint8_t fixStat; + uint8_t flags2; + uint32_t ttff; + uint32_t msss; + }; + + struct NAV_TIME_UTC { + uint8_t cls; + uint8_t id; + uint16_t len; + uint32_t iTOW; + uint32_t tAcc; + int32_t nano; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + struct { + uint8_t UTC:1; + uint8_t WKN:1; + uint8_t TOW:1; + uint8_t padding:5; + } valid; + }; + + struct CFG_RATE { + uint8_t cls; + uint8_t id; + uint16_t len; + uint16_t measRate; + uint16_t navRate; + uint16_t timeRef; + char CK[2]; + }; + + struct { + uint32_t last_iTOW; + int32_t last_alt; + uint32_t last_hAcc; + uint32_t last_vAcc; + uint8_t gpsFix; + uint8_t non_empty_loops; + uint16_t log_interval; + } state; + + struct { + uint32_t init:1; + uint32_t filter_noise:1; + uint32_t send_when_new:1; + uint32_t send_UI_only:1; + uint32_t runningNTP:1; + uint32_t forceUTCupdate:1; + uint32_t runningVPort:1; + + } mode; + + union { + NAV_POSLLH navPosllh; + NAV_STATUS navStatus; + NAV_TIME_UTC navTime; + POLL_MSG pollMsg; + CFG_RATE cfgRate; + } Message; + + uint8_t TCPbuf[UBX_SERIAL_BUFFER_SIZE]; + size_t TCPbufSize; +} UBX; + +enum UBXMsgType { + MT_NONE, + MT_NAV_POSLLH, + MT_NAV_STATUS, + MT_NAV_TIME, + MT_POLL +}; + +#ifdef USE_FLOG +FLOG *Flog = nullptr; +#endif +TasmotaSerial *UBXSerial; + +NtpServer timeServer(PortUdp); + +WiFiServer vPortServer(UBX_TCP_PORT); +WiFiClient vPortClient; + + + + + +void UBXcalcChecksum(char* CK, size_t msgSize) +{ + memset(CK, 0, 2); + for (int i = 0; i < msgSize; i++) { + CK[0] += ((char*)(&UBX.Message))[i]; + CK[1] += CK[0]; + } +} + +bool UBXcompareMsgHeader(const char* msgHeader) +{ + char* ptr = (char*)(&UBX.Message); + return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; +} + +void UBXinitCFG(void) +{ + for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { + UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); + } + DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); +} + +void UBXTriggerTele(void) +{ + mqtt_data[0] = '\0'; + if (MqttShowSensor()) { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); +#ifdef USE_RULES + RulesTeleperiod(); +#endif + } +} + + + +void UBXDetect(void) +{ + UBX.mode.init = 0; + if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { + UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, UBX_SERIAL_BUFFER_SIZE); + if (UBXSerial->begin(9600)) { + DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); + if (UBXSerial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); + } + } + } + else { + return; + } + + UBXinitCFG(); + UBX.mode.init = 1; + +#ifdef USE_FLOG + if (!Flog) { + Flog = new FLOG; + Flog->init(); + } +#endif + + UBX.state.log_interval = 10; + UBX.mode.send_UI_only = true; + UBXTriggerTele(); +} + +uint32_t UBXprocessGPS() +{ + static uint32_t fpos = 0; + static char checksum[2]; + static uint8_t currentMsgType = MT_NONE; + static size_t payloadSize = sizeof(UBX.Message); + + + uint32_t data_bytes = 0; + while ( UBXSerial->available() ) { + data_bytes++; + byte c = UBXSerial->read(); + if (UBX.mode.runningVPort){ + UBX.TCPbuf[data_bytes-1] = c; + UBX.TCPbufSize = data_bytes; + } + if ( fpos < 2 ) { + + if ( c == UBX.UBX_HEADER[fpos] ) { + fpos++; + } else { + fpos = 0; + } + } else { + + + + + + if ( (fpos-2) < payloadSize ) { + ((char*)(&UBX.Message))[fpos-2] = c; + } + fpos++; + + if ( fpos == 4 ) { + + + if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { + currentMsgType = MT_NAV_POSLLH; + payloadSize = sizeof(UBX_t::NAV_POSLLH); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { + currentMsgType = MT_NAV_STATUS; + payloadSize = sizeof(UBX_t::NAV_STATUS); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); + } + else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { + currentMsgType = MT_NAV_TIME; + payloadSize = sizeof(UBX_t::NAV_TIME_UTC); + DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); + } + else { + + fpos = 0; + continue; + } + } + + if ( fpos == (payloadSize+2) ) { + + + UBXcalcChecksum(checksum, payloadSize); + } + else if ( fpos == (payloadSize+3) ) { + + + if ( c != checksum[0] ) { + + fpos = 0; + } + } + else if ( fpos == (payloadSize+4) ) { + + + fpos = 0; + if ( c == checksum[1] ) { + + return currentMsgType; + } + } + else if ( fpos > (payloadSize+4) ) { + + + fpos = 0; + } + } + } + + if (data_bytes!=0) { + UBX.state.non_empty_loops++; + DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); + } else { + UBX.state.non_empty_loops = 0; + } + return MT_NONE; +} + + + + + +#ifdef USE_FLOG +void UBXsendHeader(void) +{ + WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); + WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); + WSSend(200, CT_STREAM, F( + "\r\n" + "\r\n" + "\r\n\r\n")); +} + +void UBXsendRecord(uint8_t *buf) +{ + char record[100]; + char stime[32]; + UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; + snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); + char lat[12]; + char lon[12]; + dtostrfd((double)entry->lat/10000000.0f,7,lat); + dtostrfd((double)entry->lon/10000000.0f,7,lon); + snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); + + WebServer->sendContent_P(record); +} + +void UBXsendFooter(void) +{ + WebServer->sendContent(F("\n\n")); + WebServer->sendContent(""); + Rtc.user_time_entry = false; +} + + + +void UBXsendFile(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); +} +#endif + + + +void UBXSetRate(uint16_t interval) +{ + UBX.Message.cfgRate.cls = 0x06; + UBX.Message.cfgRate.id = 0x08; + UBX.Message.cfgRate.len = 6; + uint32_t measRate = (1000*(uint32_t)interval); + if (measRate > 0xffff) { + measRate = 0xffff; + } + UBX.Message.cfgRate.measRate = (uint16_t)measRate; + UBX.Message.cfgRate.navRate = 1; + UBX.Message.cfgRate.timeRef = 1; + UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); + DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); + UBXSerial->write(UBX.UBX_HEADER[0]); + UBXSerial->write(UBX.UBX_HEADER[1]); + for (uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); + DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); + } + UBX.state.log_interval = 10*interval; +} + +void UBXSelectMode(uint16_t mode) +{ + DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); + switch(mode){ +#ifdef USE_FLOG + case 0: + Flog->mode = 0; + break; + case 1: + Flog->mode = 1; + break; + case 2: + UBX.mode.filter_noise = true; + break; + case 3: + UBX.mode.filter_noise = false; + break; + case 4: + Flog->startRecording(true); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); + break; + case 5: + Flog->startRecording(false); + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); + break; + case 6: + if(Flog->recording == true){ + Flog->stopRecording(); + } + AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); + break; +#endif + case 7: + UBX.mode.send_when_new = 1; + break; + case 8: + UBX.mode.send_when_new = 0; + break; + case 9: + if (timeServer.beginListening()) { + UBX.mode.runningNTP = true; + } + break; + case 10: + UBX.mode.runningNTP = false; + break; + case 11: + UBX.mode.forceUTCupdate = true; + break; + case 12: + UBX.mode.forceUTCupdate = false; + break; + case 13: + Settings.latitude = UBX.rec_buffer.values.lat/10; + Settings.longitude = UBX.rec_buffer.values.lon/10; + break; + case 14: + vPortServer.begin(); + UBX.mode.runningVPort = 1; + break; + case 15: + + UBX.mode.runningVPort = 0; + break; + default: + if (mode>1000 && mode <1066) { + + UBXSetRate(mode-1000); + } + break; + } + UBX.mode.send_UI_only = true; + UBXTriggerTele(); +} + + + +bool UBXHandlePOSLLH() +{ + DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); + if (UBX.state.gpsFix>1) { + if (UBX.mode.filter_noise) { + if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat6) { + if(UBX.mode.runningVPort) return; + UBXinitCFG(); + AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); + UBXSerial->flush(); + UBX.state.non_empty_loops = 0; + } +} + + + +void UBXLoop50msec(void) +{ + + if (UBX.mode.runningVPort){ + if(!vPortClient.connected()) { + vPortClient = vPortServer.available(); + } + while(vPortClient.available()) { + byte _newByte = vPortClient.read(); + UBXSerial->write(_newByte); + } + + if (UBX.TCPbufSize!=0){ + vPortClient.write((char*)UBX.TCPbuf, UBX.TCPbufSize); + UBX.TCPbufSize = 0; + } + } + + if(UBX.mode.runningNTP){ + timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000); + } +} + +void UBXLoop(void) +{ + static uint16_t counter; + static bool new_position; + + uint32_t msgType = UBXprocessGPS(); + + switch(msgType){ + case MT_NAV_POSLLH: + new_position = UBXHandlePOSLLH(); + break; + case MT_NAV_STATUS: + UBXHandleSTATUS(); + break; + case MT_NAV_TIME: + UBXHandleTIME(); + break; + default: + UBXHandleOther(); + break; + } + +#ifdef USE_FLOG + if (counter>UBX.state.log_interval) { + if (Flog->recording && new_position) { + UBX.rec_buffer.values.time = Rtc.local_time; + Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); + counter = 0; + } + } +#endif + + counter++; +} + + + + +#ifdef USE_WEBSERVER + + +#ifdef USE_FLOG +#ifdef DEBUG_TASMOTA_SENSOR + const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" + "{s} FLOG next sector for REC: {m} %u {e}" + "{s} %u sector(s) with data at sector: {m} %u {e}"; + const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; +#endif + + const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; + const char kFLOG_STATE0[] PROGMEM = "ready"; + const char kFLOG_STATE1[] PROGMEM = "recording"; + const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; + + const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; + +#endif + const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; + + const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" + "{s} GPS longitude {m}%s{e}" + "{s} GPS altitude {m}%s m{e}" + "{s} GPS hor. Accuracy {m}%s m{e}" + "{s} GPS vert. Accuracy {m}%s m{e}" + "{s} GPS sat-fix status {m}%s{e}"; + + const char kGPSFix0[] PROGMEM = "no fix"; + const char kGPSFix1[] PROGMEM = "dead reckoning only"; + const char kGPSFix2[] PROGMEM = "2D-fix"; + const char kGPSFix3[] PROGMEM = "3D-fix"; + const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; + const char kGPSFix5[] PROGMEM = "Time only fix"; + const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; + + + + +#endif + + + +void UBXShow(bool json) +{ + char lat[12]; + char lon[12]; + char alt[12]; + char hAcc[12]; + char vAcc[12]; + dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); + dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); + dtostrfd((double)UBX.state.last_alt/1000.0f,3,alt); + dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); + dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); + + if (json) { + ResponseAppend_P(PSTR(",\"GPS\":{")); + if (UBX.mode.send_UI_only) { + uint32_t i = UBX.state.log_interval / 10; + ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); + } else { + ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"alt\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, alt, hAcc, vAcc); + } +#ifdef USE_FLOG + ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); +#endif + UBX.mode.send_UI_only = false; +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_GPS, lat, lon, alt, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); + +#ifdef DEBUG_TASMOTA_SENSOR +#ifdef USE_FLOG + WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); + if (Flog->recording) { + WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); + } +#endif +#endif +#ifdef USE_FLOG + if (Flog->ready) { + WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); + } + if (!Flog->recording && Flog->found_saved_data) { + WSContentSend_P(HTTP_BTN_FLOG_DL); + } +#endif + if (UBX.mode.runningNTP) { + WSContentSend_P(HTTP_SNS_NTPSERVER); + } +#endif + } +} + + + + + +bool UBXCmd(void) +{ + bool serviced = true; + if (XdrvMailbox.data_len > 0) { + UBXSelectMode(XdrvMailbox.payload); + Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); + } + return serviced; +} + + + + + +bool Xsns60(uint8_t function) +{ + bool result = false; + + if (FUNC_INIT == function) { + UBXDetect(); + } + + if (UBX.mode.init) { + switch (function) { + case FUNC_COMMAND_SENSOR: + if (XSNS_60 == XdrvMailbox.index) { + result = UBXCmd(); + } + break; + case FUNC_EVERY_50_MSECOND: + UBXLoop50msec(); + break; + case FUNC_EVERY_100_MSECOND: +#ifdef USE_FLOG + if (!Flog->running_download) +#endif + { + UBXLoop(); + } + break; +#ifdef USE_FLOG + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/UBX", UBXsendFile); + break; +#endif + case FUNC_JSON_APPEND: + UBXShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: +#ifdef USE_FLOG + if (!Flog->running_download) +#endif + { + UBXShow(0); + } + break; +#endif + } + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +# 38 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +#ifdef USE_SPI +#ifdef USE_NRF24 +#ifdef USE_MIBLE + +#ifdef DEBUG_TASMOTA_SENSOR + #define MINRF_LOG_BUFFER(x) MINRFshowBuffer(x); +#else + #define MINRF_LOG_BUFFER(x) +#endif +# 56 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +#define XSNS_61 61 + +#include + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03 4 +#define CGG1 5 + +const uint16_t kMINRFSlaveID[5]={ 0x0098, + 0x01aa, + 0x045b, + 0x055b, + 0x0347 + }; + +const char kMINRFSlaveType1[] PROGMEM = "Flora"; +const char kMINRFSlaveType2[] PROGMEM = "MJ_HT_V1"; +const char kMINRFSlaveType3[] PROGMEM = "LYWSD02"; +const char kMINRFSlaveType4[] PROGMEM = "LYWSD03"; +const char kMINRFSlaveType5[] PROGMEM = "CGG1"; +const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4,kMINRFSlaveType5}; + + +const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; +const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; +const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71da7646}; + +const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; +const uint32_t kMINRFCGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; + + +const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; +const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; + + +#pragma pack(1) +struct MJ_HT_V1Header_t { + uint8_t padding[3]; + uint8_t mesSize; + uint8_t padding2; + uint16_t uuid; + uint16_t type; + uint8_t padding3[2]; + uint8_t counter; + uint8_t serial[6]; + uint8_t mode; + uint8_t padding5; + uint8_t effectiveDataLength; + }; + +struct FlowerHeader_t { + uint8_t padding[4]; + uint8_t padding2; + uint16_t uuid; + uint8_t mesSize; + uint8_t padding22; + uint16_t uuid2; + uint16_t type; + uint8_t padding3[2]; + uint8_t counter; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + }; + +union floraPacket_t { + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t data; + } T; + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint32_t data:24; + } L; + struct { + uint8_t padding[3]; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint8_t data; + } M; + struct { + uint8_t padding[3]; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t data; + } F; +}; + +union MJ_HT_V1Packet_t { + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t temp; + uint16_t hum; + } TH; + struct { + uint8_t padding[3]; + uint8_t serial[6]; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint8_t battery; + } B; + +}; + +union LYWSD02Packet_t { + struct { + uint16_t idWord; + uint8_t padding; + uint8_t serial[6]; + uint8_t padding4; + uint8_t mode; + uint8_t valueTen; + uint8_t effectiveDataLength; + uint16_t data; + } TH; +}; + +struct bleAdvPacket_t { + uint8_t pduType; + uint8_t payloadSize; + uint8_t mac[6]; + union { + uint8_t payload[24]; + MJ_HT_V1Header_t header; + FlowerHeader_t flowerHeader; + struct { + uint8_t padding[21]; + uint16_t temp; + uint8_t hum_lb; + } TH; + struct { + uint8_t padding[21]; + uint16_t temp; + } T; + struct { + uint8_t padding[21]; + uint16_t hum; + } H; + struct { + uint8_t padding[21]; + uint8_t battery; + } B; + struct { + uint8_t padding[2]; + uint8_t mode; + uint16_t size; + uint16_t data; + } F_T; + struct { + uint8_t padding[2]; + uint8_t mode; + uint16_t size; + uint16_t data; + uint8_t data2; + } F_L; + struct { + uint8_t padding[2]; + uint8_t mode; + uint16_t size; + uint8_t data; + } F_M; + struct { + uint8_t padding[2]; + uint8_t mode; + uint16_t size; + uint16_t data; + } F_F; + }; +}; + +union FIFO_t{ + bleAdvPacket_t bleAdv; + floraPacket_t floraPacket; + MJ_HT_V1Packet_t MJ_HT_V1Packet; + LYWSD02Packet_t LYWSD02Packet; + uint8_t raw[32]; +}; + +#pragma pack(0) + +struct { + const uint8_t channel[3] = {37,38,39}; + const uint8_t frequency[3] = { 2,26,80}; + + uint16_t timer; + uint8_t currentChan=0; + FIFO_t buffer; + uint8_t packetMode; + +#ifdef DEBUG_TASMOTA_SENSOR + uint8_t streamBuffer[sizeof(buffer)]; + uint8_t lsfrBuffer[sizeof(buffer)]; +#endif + +} MINRF; + +struct mi_sensor_t{ + uint8_t type; + uint8_t serial[6]; + uint8_t showedUp; + float temp; + union { + struct { + float moisture; + float fertility; + uint32_t lux; + }; + struct { + float hum; + uint8_t bat; + }; + }; +}; + +std::vector MIBLEsensors; + + + + +bool MINRFinitBLE(uint8_t _mode) +{ + if (MINRF.timer%1000 == 0){ + NRF24radio.begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_DC]); + NRF24radio.setAutoAck(false); + NRF24radio.setDataRate(RF24_1MBPS); + NRF24radio.disableCRC(); + NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); + NRF24radio.setRetries(0,0); + NRF24radio.setPALevel(RF24_PA_MIN); + NRF24radio.setAddressWidth(4); + + + NRF24radio.powerUp(); + } + if(NRF24radio.isChipConnected()){ + + MINRFchangePacketModeTo(_mode); + return true; + } + + return false; +} + +void MINRFhopChannel() +{ + MINRF.currentChan++; + if(MINRF.currentChan >= sizeof(MINRF.channel)) { + MINRF.currentChan = 0; + } + NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); +} + + + + + + + +bool MINRFreceivePacket(void) +{ + if(!NRF24radio.available()) { + return false; + } + while(NRF24radio.available()) { + + + NRF24radio.read( &MINRF.buffer, sizeof(MINRF.buffer) ); +#ifdef DEBUG_TASMOTA_SENSOR + memcpy(&MINRF.streamBuffer, &MINRF.buffer, sizeof(MINRF.buffer)); +#endif + MINRFswapbuf( sizeof(MINRF.buffer) ); + + + + switch (MINRF.packetMode) { + case 0: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); + break; + case 1: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); + break; + case 2: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); + break; + case 3: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); + break; + case 4: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); + break; + case 5: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); + break; + } + + + } + + return true; +} + +#ifdef DEBUG_TASMOTA_SENSOR +void MINRFshowBuffer(uint8_t (&buf)[32]){ + + + + + DEBUG_SENSOR_LOG(PSTR("MINRF: Buffer: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x ") + ,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11], + buf[12],buf[13],buf[14],buf[15],buf[16],buf[17],buf[18],buf[19],buf[20],buf[21],buf[22],buf[23], + buf[24],buf[25],buf[26],buf[27],buf[28],buf[29],buf[30],buf[31] + ); +} +#endif + + + + + + +void MINRFswapbuf(uint8_t len) +{ + uint8_t* buf = (uint8_t*)&MINRF.buffer; + while(len--) { + uint8_t a = *buf; + uint8_t v = 0; + if (a & 0x80) v |= 0x01; + if (a & 0x40) v |= 0x02; + if (a & 0x20) v |= 0x04; + if (a & 0x10) v |= 0x08; + if (a & 0x08) v |= 0x10; + if (a & 0x04) v |= 0x20; + if (a & 0x02) v |= 0x40; + if (a & 0x01) v |= 0x80; + *(buf++) = v; + } +} +# 430 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr) +{ + while(len--) { + uint8_t res = 0; + + for (uint8_t i = 1; i; i <<= 1) { + if (lfsr & 0x01) { + lfsr ^= 0x88; + res |= i; + } + lfsr >>= 1; + } + *(buf++) ^= res; +#ifdef DEBUG_TASMOTA_SENSOR + MINRF.lsfrBuffer[31-len] = lfsr; +#endif + } +} + +void MINRFreverseMAC(uint8_t _mac[]){ + uint8_t _reversedMAC[6]; + for (uint8_t i=0; i<6; i++){ + _reversedMAC[5-i] = _mac[i]; + } + memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); +} + + + + + + +void MINRFchangePacketModeTo(uint8_t _mode) { + uint32_t (_nextchannel) = MINRF.currentChan+1; + if (_nextchannel>2) _nextchannel=0; + + switch(_mode){ + case 0: + NRF24radio.openReadingPipe(0,0x6B7D9171); + break; + case 1: + NRF24radio.openReadingPipe(0,kMINRFFloPDU[_nextchannel]); + break; + case 2: + NRF24radio.openReadingPipe(0,kMINRFMJPDU[_nextchannel]); + break; + case 3: + NRF24radio.openReadingPipe(0,kMINRFL2PDU[_nextchannel]); + break; + case 4: + if(kMINRFL3PDU[_nextchannel]==0xffffffff) break; + NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]); + break; + case 5: + NRF24radio.openReadingPipe(0,kMINRFCGPDU[_nextchannel]); + break; + } + + MINRF.packetMode = _mode; +} +# 498 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" +uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ + + DEBUG_SENSOR_LOG(PSTR("MINRF: will test ID-type: %x"), _type); + bool _success = false; + for (uint32_t i=0;i<5;i++){ + if(_type == kMINRFSlaveID[i]){ + DEBUG_SENSOR_LOG(PSTR("MINRF: ID is type %u"), i); + _type = i+1; + _success = true; + } + else { + DEBUG_SENSOR_LOG(PSTR("MINRF: ID-type is not: %x"),kMINRFSlaveID[i]); + } + } + if(!_success) return 0xff; + + DEBUG_SENSOR_LOG(PSTR("MINRF: vector size %u"), MIBLEsensors.size()); + for(uint32_t i=0; i6000){ + DEBUG_SENSOR_LOG(PSTR("MINRF: check for FAKE sensors")); + MINRFpurgeFakeSensors(); + MINRF.timer=0; + } + MINRF.timer++; + + if (!MINRFreceivePacket()){ + + } + + else if(MINRF.buffer.bleAdv.header.uuid==0xfe95){ + MINRF_LOG_BUFFER(MINRF.streamBuffer); + MINRF_LOG_BUFFER(MINRF.lsfrBuffer); + MINRF_LOG_BUFFER(MINRF.buffer.raw); + DEBUG_SENSOR_LOG(PSTR("MINRF: Type: %x"), MINRF.buffer.bleAdv.header.type); + switch(MINRF.buffer.bleAdv.header.type){ + case 0x2050: + DEBUG_SENSOR_LOG(PSTR("MINRF: MJ_HT_V1 Packet")); + break; + case 0x1613:case 0x1614:case 0x1615: + DEBUG_SENSOR_LOG(PSTR("MINRF: Flora Packet")); + break; + default: + DEBUG_SENSOR_LOG(PSTR("MINRF: unknown Packet")); + break; + } + } + else if (MINRF.packetMode == FLORA){ + MINRFhandleFloraPacket(); + } + else if (MINRF.packetMode == MJ_HT_V1){ + MINRFhandleMJ_HT_V1Packet(); + } + else if (MINRF.packetMode == LYWSD02){ + MINRFhandleLYWSD02Packet(); + } + else if (MINRF.packetMode == LYWSD03){ + MINRFhandleLYWSD03Packet(); + } + else if (MINRF.packetMode == CGG1){ + MINRFhandleCGG1Packet(); + } + if (MINRF.packetMode == CGG1){ + MINRFinitBLE(1); + } + else { + MINRFinitBLE(++MINRF.packetMode); + } + + MINRFhopChannel(); + NRF24radio.startListening(); +} + + + + +const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; +const char HTTP_MINRF_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; +const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; +const char HTTP_MINRF_HL[] PROGMEM = "{s}
{m}
{e}"; + +void MINRFShow(bool json) +{ + if (json) { + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if(MIBLEsensors.at(i).showedUp < 3){ + DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet")); + break; + } + char slave[33]; + sprintf_P(slave,"%s-%02x%02x%02x",kMINRFSlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + + ResponseAppend_P(PSTR(",\"%s\":{"),slave); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + if (MIBLEsensors.at(i).type==FLORA){ + char lux[33]; + char moisture[33]; + char fertility[33]; + dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); + dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + if(MIBLEsensors.at(i).lux!=0xffff){ + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ + ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ + ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); + } + } + if (MIBLEsensors.at(i).type>FLORA){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + if(MIBLEsensors.at(i).hum!=-1.0f){ + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); + } + } + ResponseAppend_P(PSTR("}")); + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_NRF24, NRF24type, NRF24.chipType); + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + if(MIBLEsensors.at(i).showedUp < 3){ + DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet")); + break; + } + WSContentSend_PD(HTTP_MINRF_HL); + WSContentSend_PD(HTTP_MINRF_MAC, kMINRFSlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + WSContentSend_PD(HTTP_SNS_TEMP, kMINRFSlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); + } + if (MIBLEsensors.at(i).type==FLORA){ + if(MIBLEsensors.at(i).lux!=0x00ffffff){ + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ + WSContentSend_PD(HTTP_SNS_MOISTURE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ + char fertility[33]; + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + WSContentSend_PD(HTTP_MINRF_FLORA_DATA, kMINRFSlaveType[MIBLEsensors.at(i).type-1], fertility); + } + } + if (MIBLEsensors.at(i).type>FLORA){ + if(MIBLEsensors.at(i).hum!=-1.0f){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + WSContentSend_PD(HTTP_SNS_HUM, kMINRFSlaveType[MIBLEsensors.at(i).type-1], humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + WSContentSend_PD(HTTP_BATTERY, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); + } + } + } +#endif + } +} + + + + + +bool Xsns61(uint8_t function) +{ + bool result = false; + + if (NRF24.chipType) { + switch (function) { + case FUNC_INIT: + MINRFinitBLE(1); + AddLog_P2(LOG_LEVEL_INFO,PSTR("MINRF: started")); + break; + case FUNC_EVERY_50_MSECOND: + MINRF_EVERY_50_MSECOND(); + break; + case FUNC_JSON_APPEND: + MINRFShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + MINRFShow(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_62_MI_HM10.ino" +# 30 "S:/Development/Tasmota/tasmota/xsns_62_MI_HM10.ino" +#ifdef USE_HM10 + +#define XSNS_62 62 + +#include +#include + +TasmotaSerial *HM10Serial; +#define HM10_BAUDRATE 115200 + +#define HM10_MAX_TASK_NUMBER 12 +uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; + +#define HM10_MAX_RX_BUF 512 +char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; + +struct { + uint8_t current_task_delay; + uint8_t last_command; + uint16_t firmware; + uint32_t period; + uint32_t serialSpeed; + union { + uint32_t time; + uint8_t timebuf[4]; + }; + struct { + uint32_t init:1; + uint32_t pending_task:1; + uint32_t connected:1; + uint32_t subscribed:1; + uint32_t awaitingHT:1; + uint32_t awaitingB:1; + + } mode; + struct { + uint8_t sensor; + + } state; +} HM10; + +#pragma pack(1) +struct { + uint16_t temp; + uint8_t hum; +} LYWSD0x_HT; +#pragma pack(0) + +struct mi_sensor_t{ + uint8_t type; + uint8_t serial[6]; + uint8_t showedUp; + float temp; + union { + struct { + float moisture; + float fertility; + uint16_t lux; + }; + struct { + float hum; + uint8_t bat; + }; + }; +}; + +std::vector MIBLEsensors; + + + + + +#define D_CMND_HM10 "HM10" + +const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; +const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}"; +const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time"; + +#define FLORA 1 +#define MJ_HT_V1 2 +#define LYWSD02 3 +#define LYWSD03MMC 4 + +uint8_t kHM10SlaveID[4][3] = { 0xC4,0x7C,0x8D, + 0x58,0x2D,0x34, + 0xE7,0x2E,0x00, + 0xA4,0xC1,0x38, + }; + +const char kHM10SlaveType1[] PROGMEM = "Flora"; +const char kHM10SlaveType2[] PROGMEM = "MJ_HT_V1"; +const char kHM10SlaveType3[] PROGMEM = "LYWSD02"; +const char kHM10SlaveType4[] PROGMEM = "LYWSD03"; +const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4}; + + + + + +enum HM10_Commands { + CMND_HM10_DISC_SCAN, + CMND_HM10_AT, + CMND_HM10_PERIOD, + CMND_HM10_BAUD, + CMND_HM10_TIME + }; + + + + + +#define TASK_HM10_NOTASK 0 +#define TASK_HM10_ROLE1 1 +#define TASK_HM10_IMME1 2 +#define TASK_HM10_RENEW 3 +#define TASK_HM10_RESET 4 +#define TASK_HM10_DISC 5 +#define TASK_HM10_CONN 6 +#define TASK_HM10_VERSION 7 +#define TASK_HM10_NAME 8 +#define TASK_HM10_FEEDBACK 9 +#define TASK_HM10_DISCONN 10 +#define TASK_HM10_SUB_L3 11 +#define TASK_HM10_READ_HT 12 +#define TASK_HM10_FINDALLCHARS 13 +#define TASK_HM10_UN_L3 14 +#define TASK_HM10_DELAY_SUB 15 +#define TASK_HM10_READ_BT_L3 16 +#define TASK_HM10_SUB_L2 17 +#define TASK_HM10_UN_L2 18 +#define TASK_HM10_READ_BT_L2 19 +#define TASK_HM10_TIME_L2 20 + +#define TASK_HM10_DONE 99 + + + + + +void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){ + HM10_TASK_LIST[slot][0] = task; + HM10_TASK_LIST[slot][1] = delay; + HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; + HM10.current_task_delay = HM10_TASK_LIST[0][1]; +} + +void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ + HM10.last_command = HM10_TASK_LIST[slot][0]; + HM10_TASK_LIST[slot][0] = task; +} + + + + + +void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); + HM10_Launchtask(TASK_HM10_ROLE1,1,1); + HM10_Launchtask(TASK_HM10_IMME1,2,1); + HM10_Launchtask(TASK_HM10_RESET,3,1); + HM10_Launchtask(TASK_HM10_VERSION,4,10); + HM10_Launchtask(TASK_HM10_DISC,5,50); + } + +void HM10_Discovery_Scan(void) { + HM10_Launchtask(TASK_HM10_DISCONN,0,1); + HM10_Launchtask(TASK_HM10_DISC,1,1); + } + +void HM10_Read_LYWSD03(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); + HM10_Launchtask(TASK_HM10_SUB_L3,2,20); + HM10_Launchtask(TASK_HM10_UN_L3,3,80); + HM10_Launchtask(TASK_HM10_READ_BT_L3,4,5); + HM10_Launchtask(TASK_HM10_DISCONN,5,5); + } + +void HM10_Read_LYWSD02(void) { + HM10_Launchtask(TASK_HM10_CONN,0,1); + HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); + HM10_Launchtask(TASK_HM10_SUB_L2,2,20); + HM10_Launchtask(TASK_HM10_UN_L2,3,80); + HM10_Launchtask(TASK_HM10_READ_BT_L2,4,5); + HM10_Launchtask(TASK_HM10_DISCONN,5,5); + } + +void HM10_Time_LYWSD02(void) { + HM10_Launchtask(TASK_HM10_DISCONN,0,0); + HM10_Launchtask(TASK_HM10_CONN,1,5); + HM10_Launchtask(TASK_HM10_FEEDBACK,2,35); + HM10_Launchtask(TASK_HM10_TIME_L2,3,20); + HM10_Launchtask(TASK_HM10_DISCONN,4,5); + } +# 231 "S:/Development/Tasmota/tasmota/xsns_62_MI_HM10.ino" +uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ + if(_type==0xff){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: will test MAC-type")); + for (uint32_t i=0;i<4;i++){ + if(memcmp(_serial,kHM10SlaveID+i,3)==0){ + DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC is type %u"), i); + _type = i+1; + } + else { + DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC-type is unknown")); + } + } + } + if(_type==0xff) return _type; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: vector size %u"), MIBLEsensors.size()); + for(uint32_t i=0; ibegin(HM10.serialSpeed)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start serial communication fixed to 115200 baud"),D_CMND_HM10); + if (HM10Serial->hardwareSerial()) { + ClaimSerial(); + DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); + } + HM10_Reset(); + HM10.mode.pending_task = 1; + HM10.mode.init = 1; + HM10.period = Settings.tele_period; + DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); + } + return; +} +# 315 "S:/Development/Tasmota/tasmota/xsns_62_MI_HM10.ino" +void HM10MACStringToBytes(const char* string, uint8_t _mac[]) { + uint32_t index = 0; + while (index < 12) { + char c = string[index]; + uint32_t value = 0; + if(c >= '0' && c <= '9') + value = (c - '0'); + else if (c >= 'A' && c <= 'F') + value = (10 + (c - 'A')); + _mac[(index/2)] += value << (((index + 1) % 2) * 4); + + index++; + } + DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_mac[0],_mac[1],_mac[2],_mac[3],_mac[4],_mac[5]); +} + + + + + + +void HM10ParseResponse(char *buf) { + if (!strncmp(buf,"OK",2)) { + DEBUG_SENSOR_LOG(PSTR("HM10: got OK")); + } + if (!strncmp(buf,"HMSoft",6)) { + const char* _fw = "000"; + memcpy((void *)_fw,(void *)(buf+8),3); + HM10.firmware = atoi(_fw); + DEBUG_SENSOR_LOG(PSTR("HM10: Firmware: %d"), HM10.firmware); + return; + } + char * _pos = strstr(buf, "IS0:"); + if(_pos) { + const char* _mac = "000000000000"; + memcpy((void *)_mac,(void *)(_pos+4),12); + DEBUG_SENSOR_LOG(PSTR("HM10: found Mac: %s"), _mac); + uint8_t _newMacArray[6] = {0}; + HM10MACStringToBytes(_mac, _newMacArray); + DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); + MIBLEgetSensorSlot(_newMacArray, 0xff); + } + if (strstr(buf, "LOST")){ + HM10.mode.connected = false; + } + else { + DEBUG_SENSOR_LOG(PSTR("HM10: empty response")); + } +} + +void HM10readTempHum(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0] != 0 && _buf[1] != 0){ + memcpy(&LYWSD0x_HT,(void *)_buf,3); + DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD0x_HT.temp,LYWSD0x_HT.hum); + uint32_t _slot = HM10.state.sensor; + + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + static float _tempFloat; + _tempFloat=(float)(LYWSD0x_HT.temp)/100.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).temp=_tempFloat; + HM10.mode.awaitingHT = false; + HM10.current_task_delay = 0; + } + _tempFloat=(float)LYWSD0x_HT.hum; + if(_tempFloat<100){ + MIBLEsensors.at(_slot).hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("LYWSD03: hum updated")); + } + } +} + +bool HM10readBat(char *_buf){ + DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); + if(_buf[0] != 0){ + DEBUG_SENSOR_LOG(PSTR("HM10: Battery: %u"),_buf[0]); + uint32_t _slot = HM10.state.sensor; + DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); + if(_buf[0]<101){ + MIBLEsensors.at(_slot).bat=_buf[0]; + return true; + } + } + return false; +} + + + + + +bool HM10SerialHandleFeedback(){ + bool success = false; + uint32_t i = 0; + char ret[HM10_MAX_RX_BUF] = {0}; + + + while(HM10Serial->available()) { + + if(iread(); + } + i++; + success = true; + } + if(HM10.mode.awaitingHT) { + if (HM10.mode.connected) HM10readTempHum(ret); + } + else if(HM10.mode.awaitingB) { + if (HM10.mode.connected) { + if (HM10readBat(ret)){ + HM10.mode.awaitingB = false; + HM10.current_task_delay = 0; + } + } + } + else if(success) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s response: %s"),D_CMND_HM10, (char *)ret); + HM10ParseResponse(ret); + } + else { + + } + return success; +} + + + + + +void HM10_TaskEvery100ms(){ + if (HM10.current_task_delay == 0) { + uint8_t i = 0; + bool runningTaskLoop = true; + while (runningTaskLoop) { + switch(HM10_TASK_LIST[i][0]) { + case TASK_HM10_ROLE1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+ROLE1"); + break; + case TASK_HM10_IMME1: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set imme to 1"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+IMME1"); + break; + case TASK_HM10_DISC: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start discovery"),D_CMND_HM10); + HM10.current_task_delay = 35; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+DISC?"); + break; + case TASK_HM10_VERSION: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read version"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+VERR?"); + break; + case TASK_HM10_NAME: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read name"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+NAME?"); + break; + case TASK_HM10_CONN: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s connect"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + char _con[20]; + sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors.at(HM10.state.sensor).serial[0],MIBLEsensors.at(HM10.state.sensor).serial[1],MIBLEsensors.at(HM10.state.sensor).serial[2],MIBLEsensors.at(HM10.state.sensor).serial[3],MIBLEsensors.at(HM10.state.sensor).serial[4],MIBLEsensors.at(HM10.state.sensor).serial[5]); + HM10Serial->write(_con); + HM10.mode.awaitingB = false; + HM10.mode.connected = true; + break; + case TASK_HM10_DISCONN: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s disconnect"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT"); + break; + case TASK_HM10_RESET: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10); + HM10Serial->write("AT+RESET"); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + break; + case TASK_HM10_SUB_L3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); + HM10.current_task_delay = 25; + HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); + runningTaskLoop = false; + HM10Serial->write("AT+NOTIFY_ON0037"); + break; + case TASK_HM10_UN_L3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaitingHT = false; + HM10Serial->write("AT+NOTIFYOFF0037"); + break; + case TASK_HM10_SUB_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); + HM10.current_task_delay = 25; + HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); + runningTaskLoop = false; + HM10Serial->write("AT+NOTIFY_ON003C"); + break; + case TASK_HM10_UN_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.mode.awaitingHT = false; + HM10Serial->write("AT+NOTIFYOFF003C"); + break; + case TASK_HM10_TIME_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set time"),D_CMND_HM10); + HM10.current_task_delay = 5; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10.time = Rtc.utc_time; + HM10Serial->write("AT+SEND_DATAWR002F"); + HM10Serial->write(HM10.timebuf,4); + HM10Serial->write(Rtc.time_timezone / 60); + AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60)); + break; + case TASK_HM10_READ_HT: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0036"),D_CMND_HM10); + HM10.current_task_delay = 0; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0036?"); + HM10.mode.awaitingHT = true; + break; + case TASK_HM10_READ_BT_L3: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 003A"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA003A?"); + HM10.mode.awaitingB = true; + break; + case TASK_HM10_READ_BT_L2: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0043"),D_CMND_HM10); + HM10.current_task_delay = 2; + HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); + runningTaskLoop = false; + HM10Serial->write("AT+READDATA0043?"); + HM10.mode.awaitingB = true; + break; + + + + + + + + case TASK_HM10_FEEDBACK: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10); + HM10SerialHandleFeedback(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; + runningTaskLoop = false; + break; + case TASK_HM10_DELAY_SUB: + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start reading"),D_CMND_HM10); + HM10SerialHandleFeedback(); + HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; + HM10_TASK_LIST[i][0] = TASK_HM10_DONE; + HM10.mode.awaitingHT = true; + runningTaskLoop = false; + break; + case TASK_HM10_DONE: + + + if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { + DEBUG_SENSOR_LOG(PSTR("%sno Tasks left"),D_CMND_HM10); + DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i); + for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { + DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j); + HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; + HM10_TASK_LIST[j][1] = 0; + } + runningTaskLoop = false; + HM10.mode.pending_task = 0; + break; + } + } + i++; + } + } + else { + HM10.current_task_delay--; + } +} + + + + + + +void HM10EverySecond(){ + if(HM10.firmware == 0) return; + if(HM10.mode.pending_task == 1) return; + if (MIBLEsensors.size()==0) return; + + static uint32_t _counter = 0; + static uint32_t _nextSensorSlot = 0; + if(_counter==0) { + HM10.state.sensor = _nextSensorSlot; + _nextSensorSlot++; + if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD03MMC) { + HM10.mode.pending_task = 1; + HM10_Read_LYWSD03(); + } + if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD02) { + HM10.mode.pending_task = 1; + HM10_Read_LYWSD02(); + } + if (HM10.state.sensor==MIBLEsensors.size()-1) { + _nextSensorSlot= 0; + _counter++; + } + DEBUG_SENSOR_LOG(PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); + } + else _counter++; + if (_counter>HM10.period) _counter = 0; +} + +bool HM10Cmd(void) { + char command[CMDSZ]; + bool serviced = true; + uint8_t disp_len = strlen(D_CMND_HM10); + + if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_HM10), disp_len)) { + uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kHM10_Commands); + switch (command_code) { + case CMND_HM10_PERIOD: + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_HM10_PERIOD) { HM10.period = XdrvMailbox.payload; } + } + else { + if (command_code == CMND_HM10_PERIOD) XdrvMailbox.payload = HM10.period; + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_BAUD: + if (XdrvMailbox.data_len > 0) { + if (command_code == CMND_HM10_BAUD) { + HM10.serialSpeed = XdrvMailbox.payload; + HM10Serial->begin(HM10.serialSpeed); + } + } + else { + if (command_code == CMND_HM10_BAUD) XdrvMailbox.payload = HM10.serialSpeed; + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_TIME: + if (XdrvMailbox.data_len > 0) { + if(MIBLEsensors.size()>XdrvMailbox.payload){ + if(MIBLEsensors.at(XdrvMailbox.payload).type == LYWSD02){ + HM10.state.sensor = XdrvMailbox.payload; + HM10_Time_LYWSD02(); + } + } + } + Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); + break; + case CMND_HM10_AT: + HM10Serial->write("AT"); + if (strlen(XdrvMailbox.data)!=0) { + HM10Serial->write("+"); + HM10Serial->write(XdrvMailbox.data); + Response_P(S_JSON_HM10_COMMAND, ":AT+",XdrvMailbox.data); + } + else Response_P(S_JSON_HM10_COMMAND, ":AT",XdrvMailbox.data); + break; + case CMND_HM10_DISC_SCAN: + if (command_code == CMND_HM10_DISC_SCAN) { HM10_Discovery_Scan(); } + Response_P(S_JSON_HM10_COMMAND, command, ""); + break; + default: + + serviced = false; + break; + } + } else { + return false; + } + return serviced; +} + + + + + + +const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}"; +const char HTTP_HM10_SERIAL[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; +const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; +const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; +const char HTTP_HM10_HL[] PROGMEM = "{s}
{m}
{e}"; + +void HM10Show(bool json) +{ + if (json) { + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + char slave[33]; + sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + + ResponseAppend_P(PSTR(",\"%s\":{"),slave); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); + } + if (MIBLEsensors.at(i).type==FLORA){ + char lux[33]; + char moisture[33]; + char fertility[33]; + dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); + dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + if(MIBLEsensors.at(i).lux!=0xffff){ + ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ + ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ + ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); + } + } + if (MIBLEsensors.at(i).type>FLORA){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + if(MIBLEsensors.at(i).hum!=-1.0f){ + ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); + } + } + ResponseAppend_P(PSTR("}")); + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_HM10, HM10.firmware); + for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { + WSContentSend_PD(HTTP_HM10_HL); + WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); + if(MIBLEsensors.at(i).temp!=-1000.0f){ + char temperature[33]; + dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); + WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); + } + if (MIBLEsensors.at(i).type==FLORA){ + if(MIBLEsensors.at(i).lux!=0xffff){ + WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); + } + if(MIBLEsensors.at(i).moisture!=-1000.0f){ + WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); + } + if(MIBLEsensors.at(i).fertility!=-1000.0f){ + char fertility[33]; + dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); + WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors.at(i).type-1], fertility); + } + } + if (MIBLEsensors.at(i).type>FLORA){ + if(MIBLEsensors.at(i).hum!=-1.0f){ + char humidity[33]; + dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); + WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); + } + if(MIBLEsensors.at(i).bat!=0xff){ + WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); + } + } + } +#endif + } +} + + + + + +bool Xsns62(uint8_t function) +{ + bool result = false; + + if ((pin[GPIO_HM10_RX] < 99) && (pin[GPIO_HM10_TX] < 99)) { + switch (function) { + case FUNC_INIT: + HM10SerialInit(); + break; + case FUNC_EVERY_50_MSECOND: + HM10SerialHandleFeedback(); + break; + case FUNC_EVERY_100_MSECOND: + if (HM10_TASK_LIST[0][0] != TASK_HM10_NOTASK) { + HM10_TaskEvery100ms(); + } + break; + case FUNC_EVERY_SECOND: + HM10EverySecond(); + break; + case FUNC_COMMAND: + result = HM10Cmd(); + break; + case FUNC_JSON_APPEND: + HM10Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HM10Show(0); + break; +#endif + } + } + return result; +} +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_63_aht1x.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_63_aht1x.ino" +#ifdef USE_I2C +#ifdef USE_AHT1x + + + + + + +#define XSNS_63 63 +#define XI2C_43 43 + +#define AHT10_ADDR 0x38 + +uint8_t eSensorCalibrateCmd[3] = {0xE1, 0x08, 0x00}; +uint8_t eSensorNormalCmd[3] = {0xA8, 0x00, 0x00}; +uint8_t eSensorMeasureCmd[3] = {0xAC, 0x33, 0x00}; +uint8_t eSensorResetCmd = 0xBA; + +struct AHT10 { + float humidity = NAN; + float temperature = NAN; + uint8_t valid = 0; + uint8_t count = 0; + char name[6] = "AHT1x"; +} AHT10; + +bool AHT10Read(void) +{ + if (AHT10.valid) { AHT10.valid--; } + + uint8_t data[6]; + + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorMeasureCmd, 3); + Wire.endTransmission(); + delay(100); + + Wire.requestFrom(AHT10_ADDR, 6); + for (uint32_t i = 0; Wire.available() > 0; i++) { + data[i] = Wire.read(); + } + + uint32_t result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; + uint32_t result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; + + float humidity = result_h * 100 / 1048576; + float temperature = ((200 * result_t) / 1048576) - 50; + + if (isnan(temperature) || isnan(humidity)) { return false; } + + AHT10.humidity = ConvertHumidity(humidity); + AHT10.temperature = ConvertTemp(temperature); + + AHT10.valid = SENSOR_MAX_MISS; + return true; +} + + + +bool AHT10Init(void) +{ + Wire.begin(AHT10_ADDR); + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorCalibrateCmd, 3); + Wire.endTransmission(); + + delay(500); + + return (0x08 == (AHT10ReadStatus() & 0x68)); +} + +uint8_t AHT10ReadStatus(void) +{ + Wire.requestFrom(AHT10_ADDR, 1); + uint8_t result = Wire.read(); + return result; +} + +void AHT10Reset(void) +{ + Wire.beginTransmission(AHT10_ADDR); + Wire.write(eSensorResetCmd); + Wire.endTransmission(); + delay(20); +} + + + +void AHT10Detect(void) +{ + if (I2cActive(AHT10_ADDR)) { return; } + + if (AHT10Init()) { + I2cSetActiveFound(AHT10_ADDR, AHT10.name); + AHT10.count = 1; + } +} + +void AHT10EverySecond(void) +{ + if (uptime &1) { + + if (!AHT10Read()) { + AddLogMissed(AHT10.name, AHT10.valid); + } + } +} + +void AHT10Show(bool json) +{ + if (AHT10.valid) { + char temperature[33]; + dtostrfd(AHT10.temperature, Settings.flag2.temperature_resolution, temperature); + char humidity[33]; + dtostrfd(AHT10.humidity, Settings.flag2.humidity_resolution, humidity); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMPHUM, AHT10.name, temperature, humidity); +#ifdef USE_DOMOTICZ + if ((0 == tele_period)) { + DomoticzTempHumSensor(temperature, humidity); + } +#endif +#ifdef USE_KNX + if (0 == tele_period) { + KnxSensor(KNX_TEMPERATURE, AHT10.temperature); + KnxSensor(KNX_HUMIDITY, AHT10.humidity); + } +#endif +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, AHT10.name, temperature, TempUnit()); + WSContentSend_PD(HTTP_SNS_HUM, AHT10.name, humidity); +#endif + } + } +} + + + + + +bool Xsns63(uint8_t function) +{ + if (!I2cEnabled(XI2C_43)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + AHT10Detect(); + } + else if (AHT10.count) { + switch (function) { + case FUNC_EVERY_SECOND: + AHT10EverySecond(); + break; + case FUNC_JSON_APPEND: + AHT10Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + AHT10Show(0); + break; +#endif + } + } + return result; +} + +#endif +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_91_prometheus.ino" +# 22 "S:/Development/Tasmota/tasmota/xsns_91_prometheus.ino" +#ifdef USE_PROMETHEUS + + + + +#define XSNS_91 91 + +void HandleMetrics(void) +{ + if (!HttpCheckPriviledgedAccess()) { return; } + + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR("Prometheus")); + + WSContentBegin(200, CT_PLAIN); + + + char parameter[FLOATSZ]; + + if (global_temperature != 9999) { + dtostrfd(global_temperature, Settings.flag2.temperature_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_temperature gauge\nglobal_temperature %s\n"), parameter); + } + if (global_humidity != 0) { + dtostrfd(global_humidity, Settings.flag2.humidity_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_humidity gauge\nglobal_humidity %s\n"), parameter); + } + if (global_pressure != 0) { + dtostrfd(global_pressure, Settings.flag2.pressure_resolution, parameter); + WSContentSend_P(PSTR("# TYPE global_pressure gauge\nglobal_pressure %s\n"), parameter); + } + +#ifdef USE_ENERGY_SENSOR + dtostrfd(Energy.voltage[0], Settings.flag2.voltage_resolution, parameter); + WSContentSend_P(PSTR("# TYPE voltage gauge\nvoltage %s\n"), parameter); + dtostrfd(Energy.current[0], Settings.flag2.current_resolution, parameter); + WSContentSend_P(PSTR("# TYPE current gauge\ncurrent %s\n"), parameter); + dtostrfd(Energy.active_power[0], Settings.flag2.wattage_resolution, parameter); + WSContentSend_P(PSTR("# TYPE active_power gauge\nactive_power %s\n"), parameter); + dtostrfd(Energy.daily, Settings.flag2.energy_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_daily gauge\nenergy_daily %s\n"), parameter); + dtostrfd(Energy.total, Settings.flag2.energy_resolution, parameter); + WSContentSend_P(PSTR("# TYPE energy_total counter\nenergy_total %s\n"), parameter); +#endif +# 80 "S:/Development/Tasmota/tasmota/xsns_91_prometheus.ino" + WSContentEnd(); +} + + + + + +bool Xsns91(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/metrics", HandleMetrics); + break; + } + return result; +} + +#endif +# 1 "S:/Development/Tasmota/tasmota/xsns_interface.ino" +# 20 "S:/Development/Tasmota/tasmota/xsns_interface.ino" +#ifdef XFUNC_PTR_IN_ROM +bool (* const xsns_func_ptr[])(uint8_t) PROGMEM = { +#else +bool (* const xsns_func_ptr[])(uint8_t) = { +#endif + +#ifdef XSNS_01 + &Xsns01, +#endif + +#ifdef XSNS_02 + &Xsns02, +#endif + +#ifdef XSNS_03 + &Xsns03, +#endif + +#ifdef XSNS_04 + &Xsns04, +#endif + +#ifdef XSNS_05 + &Xsns05, +#endif + +#ifdef XSNS_06 + &Xsns06, +#endif + +#ifdef XSNS_07 + &Xsns07, +#endif + +#ifdef XSNS_08 + &Xsns08, +#endif + +#ifdef XSNS_09 + &Xsns09, +#endif + +#ifdef XSNS_10 + &Xsns10, +#endif + +#ifdef XSNS_11 + &Xsns11, +#endif + +#ifdef XSNS_12 + &Xsns12, +#endif + +#ifdef XSNS_13 + &Xsns13, +#endif + +#ifdef XSNS_14 + &Xsns14, +#endif + +#ifdef XSNS_15 + &Xsns15, +#endif + +#ifdef XSNS_16 + &Xsns16, +#endif + +#ifdef XSNS_17 + &Xsns17, +#endif + +#ifdef XSNS_18 + &Xsns18, +#endif + +#ifdef XSNS_19 + &Xsns19, +#endif + +#ifdef XSNS_20 + &Xsns20, +#endif + +#ifdef XSNS_21 + &Xsns21, +#endif + +#ifdef XSNS_22 + &Xsns22, +#endif + +#ifdef XSNS_23 + &Xsns23, +#endif + +#ifdef XSNS_24 + &Xsns24, +#endif + +#ifdef XSNS_25 + &Xsns25, +#endif + +#ifdef XSNS_26 + &Xsns26, +#endif + +#ifdef XSNS_27 + &Xsns27, +#endif + +#ifdef XSNS_28 + &Xsns28, +#endif + +#ifdef XSNS_29 + &Xsns29, +#endif + +#ifdef XSNS_30 + &Xsns30, +#endif + +#ifdef XSNS_31 + &Xsns31, +#endif + +#ifdef XSNS_32 + &Xsns32, +#endif + +#ifdef XSNS_33 + &Xsns33, +#endif + +#ifdef XSNS_34 + &Xsns34, +#endif + +#ifdef XSNS_35 + &Xsns35, +#endif + +#ifdef XSNS_36 + &Xsns36, +#endif + +#ifdef XSNS_37 + &Xsns37, +#endif + +#ifdef XSNS_38 + &Xsns38, +#endif + +#ifdef XSNS_39 + &Xsns39, +#endif + +#ifdef XSNS_40 + &Xsns40, +#endif + +#ifdef XSNS_41 + &Xsns41, +#endif + +#ifdef XSNS_42 + &Xsns42, +#endif + +#ifdef XSNS_43 + &Xsns43, +#endif + +#ifdef XSNS_44 + &Xsns44, +#endif + +#ifdef XSNS_45 + &Xsns45, +#endif + +#ifdef XSNS_46 + &Xsns46, +#endif + +#ifdef XSNS_47 + &Xsns47, +#endif + +#ifdef XSNS_48 + &Xsns48, +#endif + +#ifdef XSNS_49 + &Xsns49, +#endif + +#ifdef XSNS_50 + &Xsns50, +#endif + +#ifdef XSNS_51 + &Xsns51, +#endif + +#ifdef XSNS_52 + &Xsns52, +#endif + +#ifdef XSNS_53 + &Xsns53, +#endif + +#ifdef XSNS_54 + &Xsns54, +#endif + +#ifdef XSNS_55 + &Xsns55, +#endif + +#ifdef XSNS_56 + &Xsns56, +#endif + +#ifdef XSNS_57 + &Xsns57, +#endif + +#ifdef XSNS_58 + &Xsns58, +#endif + +#ifdef XSNS_59 + &Xsns59, +#endif + +#ifdef XSNS_60 + &Xsns60, +#endif + +#ifdef XSNS_61 + &Xsns61, +#endif + +#ifdef XSNS_62 + &Xsns62, +#endif + +#ifdef XSNS_63 + &Xsns63, +#endif + +#ifdef XSNS_64 + &Xsns64, +#endif + +#ifdef XSNS_65 + &Xsns65, +#endif + +#ifdef XSNS_66 + &Xsns66, +#endif + +#ifdef XSNS_67 + &Xsns67, +#endif + +#ifdef XSNS_68 + &Xsns68, +#endif + +#ifdef XSNS_69 + &Xsns69, +#endif + +#ifdef XSNS_70 + &Xsns70, +#endif + +#ifdef XSNS_71 + &Xsns71, +#endif + +#ifdef XSNS_72 + &Xsns72, +#endif + +#ifdef XSNS_73 + &Xsns73, +#endif + +#ifdef XSNS_74 + &Xsns74, +#endif + +#ifdef XSNS_75 + &Xsns75, +#endif + +#ifdef XSNS_76 + &Xsns76, +#endif + +#ifdef XSNS_77 + &Xsns77, +#endif + +#ifdef XSNS_78 + &Xsns78, +#endif + +#ifdef XSNS_79 + &Xsns79, +#endif + +#ifdef XSNS_80 + &Xsns80, +#endif + +#ifdef XSNS_81 + &Xsns81, +#endif + +#ifdef XSNS_82 + &Xsns82, +#endif + +#ifdef XSNS_83 + &Xsns83, +#endif + +#ifdef XSNS_84 + &Xsns84, +#endif + +#ifdef XSNS_85 + &Xsns85, +#endif + +#ifdef XSNS_86 + &Xsns86, +#endif + +#ifdef XSNS_87 + &Xsns87, +#endif + +#ifdef XSNS_88 + &Xsns88, +#endif + +#ifdef XSNS_89 + &Xsns89, +#endif + +#ifdef XSNS_90 + &Xsns90, +#endif + +#ifdef XSNS_91 + &Xsns91, +#endif + +#ifdef XSNS_92 + &Xsns92, +#endif + +#ifdef XSNS_93 + &Xsns93, +#endif + +#ifdef XSNS_94 + &Xsns94, +#endif + +#ifdef XSNS_95 + &Xsns95, +#endif + +#ifdef XSNS_96 + &Xsns96, +#endif + +#ifdef XSNS_97 + &Xsns97, +#endif + +#ifdef XSNS_98 + &Xsns98, +#endif + +#ifdef XSNS_99 + &Xsns99 +#endif +}; + +const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); + + + + + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kXsnsList[] PROGMEM = { +#else +const uint8_t kXsnsList[] = { +#endif + +#ifdef XSNS_01 + XSNS_01, +#endif + +#ifdef XSNS_02 + XSNS_02, +#endif + +#ifdef XSNS_03 + XSNS_03, +#endif + +#ifdef XSNS_04 + XSNS_04, +#endif + +#ifdef XSNS_05 + XSNS_05, +#endif + +#ifdef XSNS_06 + XSNS_06, +#endif + +#ifdef XSNS_07 + XSNS_07, +#endif + +#ifdef XSNS_08 + XSNS_08, +#endif + +#ifdef XSNS_09 + XSNS_09, +#endif + +#ifdef XSNS_10 + XSNS_10, +#endif + +#ifdef XSNS_11 + XSNS_11, +#endif + +#ifdef XSNS_12 + XSNS_12, +#endif + +#ifdef XSNS_13 + XSNS_13, +#endif + +#ifdef XSNS_14 + XSNS_14, +#endif + +#ifdef XSNS_15 + XSNS_15, +#endif + +#ifdef XSNS_16 + XSNS_16, +#endif + +#ifdef XSNS_17 + XSNS_17, +#endif + +#ifdef XSNS_18 + XSNS_18, +#endif + +#ifdef XSNS_19 + XSNS_19, +#endif + +#ifdef XSNS_20 + XSNS_20, +#endif + +#ifdef XSNS_21 + XSNS_21, +#endif + +#ifdef XSNS_22 + XSNS_22, +#endif + +#ifdef XSNS_23 + XSNS_23, +#endif + +#ifdef XSNS_24 + XSNS_24, +#endif + +#ifdef XSNS_25 + XSNS_25, +#endif + +#ifdef XSNS_26 + XSNS_26, +#endif + +#ifdef XSNS_27 + XSNS_27, +#endif + +#ifdef XSNS_28 + XSNS_28, +#endif + +#ifdef XSNS_29 + XSNS_29, +#endif + +#ifdef XSNS_30 + XSNS_30, +#endif + +#ifdef XSNS_31 + XSNS_31, +#endif + +#ifdef XSNS_32 + XSNS_32, +#endif + +#ifdef XSNS_33 + XSNS_33, +#endif + +#ifdef XSNS_34 + XSNS_34, +#endif + +#ifdef XSNS_35 + XSNS_35, +#endif + +#ifdef XSNS_36 + XSNS_36, +#endif + +#ifdef XSNS_37 + XSNS_37, +#endif + +#ifdef XSNS_38 + XSNS_38, +#endif + +#ifdef XSNS_39 + XSNS_39, +#endif + +#ifdef XSNS_40 + XSNS_40, +#endif + +#ifdef XSNS_41 + XSNS_41, +#endif + +#ifdef XSNS_42 + XSNS_42, +#endif + +#ifdef XSNS_43 + XSNS_43, +#endif + +#ifdef XSNS_44 + XSNS_44, +#endif + +#ifdef XSNS_45 + XSNS_45, +#endif + +#ifdef XSNS_46 + XSNS_46, +#endif + +#ifdef XSNS_47 + XSNS_47, +#endif + +#ifdef XSNS_48 + XSNS_48, +#endif + +#ifdef XSNS_49 + XSNS_49, +#endif + +#ifdef XSNS_50 + XSNS_50, +#endif + +#ifdef XSNS_51 + XSNS_51, +#endif + +#ifdef XSNS_52 + XSNS_52, +#endif + +#ifdef XSNS_53 + XSNS_53, +#endif + +#ifdef XSNS_54 + XSNS_54, +#endif + +#ifdef XSNS_55 + XSNS_55, +#endif + +#ifdef XSNS_56 + XSNS_56, +#endif + +#ifdef XSNS_57 + XSNS_57, +#endif + +#ifdef XSNS_58 + XSNS_58, +#endif + +#ifdef XSNS_59 + XSNS_59, +#endif + +#ifdef XSNS_60 + XSNS_60, +#endif + +#ifdef XSNS_61 + XSNS_61, +#endif + +#ifdef XSNS_62 + XSNS_62, +#endif + +#ifdef XSNS_63 + XSNS_63, +#endif + +#ifdef XSNS_64 + XSNS_64, +#endif + +#ifdef XSNS_65 + XSNS_65, +#endif + +#ifdef XSNS_66 + XSNS_66, +#endif + +#ifdef XSNS_67 + XSNS_67, +#endif + +#ifdef XSNS_68 + XSNS_68, +#endif + +#ifdef XSNS_69 + XSNS_69, +#endif + +#ifdef XSNS_70 + XSNS_70, +#endif + +#ifdef XSNS_71 + XSNS_71, +#endif + +#ifdef XSNS_72 + XSNS_72, +#endif + +#ifdef XSNS_73 + XSNS_73, +#endif + +#ifdef XSNS_74 + XSNS_74, +#endif + +#ifdef XSNS_75 + XSNS_75, +#endif + +#ifdef XSNS_76 + XSNS_76, +#endif + +#ifdef XSNS_77 + XSNS_77, +#endif + +#ifdef XSNS_78 + XSNS_78, +#endif + +#ifdef XSNS_79 + XSNS_79, +#endif + +#ifdef XSNS_80 + XSNS_80, +#endif + +#ifdef XSNS_81 + XSNS_81, +#endif + +#ifdef XSNS_82 + XSNS_82, +#endif + +#ifdef XSNS_83 + XSNS_83, +#endif + +#ifdef XSNS_84 + XSNS_84, +#endif + +#ifdef XSNS_85 + XSNS_85, +#endif + +#ifdef XSNS_86 + XSNS_86, +#endif + +#ifdef XSNS_87 + XSNS_87, +#endif + +#ifdef XSNS_88 + XSNS_88, +#endif + +#ifdef XSNS_89 + XSNS_89, +#endif + +#ifdef XSNS_90 + XSNS_90, +#endif + +#ifdef XSNS_91 + XSNS_91, +#endif + +#ifdef XSNS_92 + XSNS_92, +#endif + +#ifdef XSNS_93 + XSNS_93, +#endif + +#ifdef XSNS_94 + XSNS_94, +#endif + +#ifdef XSNS_95 + XSNS_95, +#endif + +#ifdef XSNS_96 + XSNS_96, +#endif + +#ifdef XSNS_97 + XSNS_97, +#endif + +#ifdef XSNS_98 + XSNS_98, +#endif + +#ifdef XSNS_99 + XSNS_99 +#endif +}; + + + +bool XsnsEnabled(uint32_t sns_index) +{ + if (sns_index < sizeof(kXsnsList)) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t index = pgm_read_byte(kXsnsList + sns_index); +#else + uint32_t index = kXsnsList[sns_index]; +#endif + return bitRead(Settings.sensors[index / 32], index % 32); + } + return true; +} + +void XsnsSensorState(void) +{ + ResponseAppend_P(PSTR("\"")); + for (uint32_t i = 0; i < sizeof(kXsnsList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t sensorid = pgm_read_byte(kXsnsList + i); +#else + uint32_t sensorid = kXsnsList[i]; +#endif + bool disabled = false; + if (sensorid < MAX_XSNS_DRIVERS) { + disabled = !bitRead(Settings.sensors[sensorid / 32], sensorid % 32); + } + ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", sensorid); + } + ResponseAppend_P(PSTR("\"")); +} + + + + + +bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) +{ + xsns_index++; + if (xsns_index == xsns_present) { xsns_index = 0; } + +#ifndef USE_DEBUG_DRIVER + if (FUNC_WEB_SENSOR == Function) { +#endif + uint32_t max_disabled = xsns_present; + while (!XsnsEnabled(xsns_index) && max_disabled--) { + xsns_index++; + if (xsns_index == xsns_present) { xsns_index = 0; } + } +#ifndef USE_DEBUG_DRIVER + } +#endif + + return xsns_func_ptr[xsns_index](Function); +} + +bool XsnsCall(uint8_t Function) +{ + bool result = false; + + DEBUG_TRACE_LOG(PSTR("SNS: %d"), Function); + +#ifdef PROFILE_XSNS_EVERY_SECOND + uint32_t profile_start_millis = millis(); +#endif + + for (uint32_t x = 0; x < xsns_present; x++) { +#ifdef USE_DEBUG_DRIVER + if (XsnsEnabled(x)) { +#endif + + if ((FUNC_WEB_SENSOR == Function) && !XsnsEnabled(x)) { continue; } + +#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND + uint32_t profile_start_millis = millis(); +#endif + result = xsns_func_ptr[x](Function); + +#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); + } + } +#endif + + if (result && ((FUNC_COMMAND == Function) || + (FUNC_PIN_STATE == Function) || + (FUNC_COMMAND_SENSOR == Function) + )) { + break; + } +#ifdef USE_DEBUG_DRIVER + } +#endif + } + +#ifdef PROFILE_XSNS_EVERY_SECOND + uint32_t profile_millis = millis() - profile_start_millis; + if (profile_millis) { + if (FUNC_EVERY_SECOND == Function) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); + } + } +#endif + + return result; +} +# 1 "S:/Development/Tasmota/tasmota/xx2c_interface.ino" +# 20 "S:/Development/Tasmota/tasmota/xx2c_interface.ino" +#ifdef USE_I2C + +#ifdef XFUNC_PTR_IN_ROM +const uint8_t kI2cList[] PROGMEM = { +#else +const uint8_t kI2cList[] = { +#endif + +#ifdef XI2C_01 + XI2C_01, +#endif + +#ifdef XI2C_02 + XI2C_02, +#endif + +#ifdef XI2C_03 + XI2C_03, +#endif + +#ifdef XI2C_04 + XI2C_04, +#endif + +#ifdef XI2C_05 + XI2C_05, +#endif + +#ifdef XI2C_06 + XI2C_06, +#endif + +#ifdef XI2C_07 + XI2C_07, +#endif + +#ifdef XI2C_08 + XI2C_08, +#endif + +#ifdef XI2C_09 + XI2C_09, +#endif + +#ifdef XI2C_10 + XI2C_10, +#endif + +#ifdef XI2C_11 + XI2C_11, +#endif + +#ifdef XI2C_12 + XI2C_12, +#endif + +#ifdef XI2C_13 + XI2C_13, +#endif + +#ifdef XI2C_14 + XI2C_14, +#endif + +#ifdef XI2C_15 + XI2C_15, +#endif + +#ifdef XI2C_16 + XI2C_16, +#endif + +#ifdef XI2C_17 + XI2C_17, +#endif + +#ifdef XI2C_18 + XI2C_18, +#endif + +#ifdef XI2C_19 + XI2C_19, +#endif + +#ifdef XI2C_20 + XI2C_20, +#endif + +#ifdef XI2C_21 + XI2C_21, +#endif + +#ifdef XI2C_22 + XI2C_22, +#endif + +#ifdef XI2C_23 + XI2C_23, +#endif + +#ifdef XI2C_24 + XI2C_24, +#endif + +#ifdef XI2C_25 + XI2C_25, +#endif + +#ifdef XI2C_26 + XI2C_26, +#endif + +#ifdef XI2C_27 + XI2C_27, +#endif + +#ifdef XI2C_28 + XI2C_28, +#endif + +#ifdef XI2C_29 + XI2C_29, +#endif + +#ifdef XI2C_30 + XI2C_30, +#endif + +#ifdef XI2C_31 + XI2C_31, +#endif + +#ifdef XI2C_32 + XI2C_32, +#endif + +#ifdef XI2C_33 + XI2C_33, +#endif + +#ifdef XI2C_34 + XI2C_34, +#endif + +#ifdef XI2C_35 + XI2C_35, +#endif + +#ifdef XI2C_36 + XI2C_36, +#endif + +#ifdef XI2C_37 + XI2C_37, +#endif + +#ifdef XI2C_38 + XI2C_38, +#endif + +#ifdef XI2C_39 + XI2C_39, +#endif + +#ifdef XI2C_40 + XI2C_40, +#endif + +#ifdef XI2C_41 + XI2C_41, +#endif + +#ifdef XI2C_42 + XI2C_42, +#endif + +#ifdef XI2C_43 + XI2C_43, +#endif + +#ifdef XI2C_44 + XI2C_44, +#endif + +#ifdef XI2C_45 + XI2C_45, +#endif + +#ifdef XI2C_46 + XI2C_46, +#endif + +#ifdef XI2C_47 + XI2C_47, +#endif + +#ifdef XI2C_48 + XI2C_48, +#endif + +#ifdef XI2C_49 + XI2C_49, +#endif + +#ifdef XI2C_50 + XI2C_50, +#endif + +#ifdef XI2C_51 + XI2C_51, +#endif + +#ifdef XI2C_52 + XI2C_52, +#endif + +#ifdef XI2C_53 + XI2C_53, +#endif + +#ifdef XI2C_54 + XI2C_54, +#endif + +#ifdef XI2C_55 + XI2C_55, +#endif + +#ifdef XI2C_56 + XI2C_56, +#endif + +#ifdef XI2C_57 + XI2C_57, +#endif + +#ifdef XI2C_58 + XI2C_58, +#endif + +#ifdef XI2C_59 + XI2C_59, +#endif + +#ifdef XI2C_60 + XI2C_60, +#endif + +#ifdef XI2C_61 + XI2C_61, +#endif + +#ifdef XI2C_62 + XI2C_62, +#endif + +#ifdef XI2C_63 + XI2C_63, +#endif + +#ifdef XI2C_64 + XI2C_64, +#endif + +#ifdef XI2C_65 + XI2C_65, +#endif + +#ifdef XI2C_66 + XI2C_66, +#endif + +#ifdef XI2C_67 + XI2C_67, +#endif + +#ifdef XI2C_68 + XI2C_68, +#endif + +#ifdef XI2C_69 + XI2C_69, +#endif + +#ifdef XI2C_70 + XI2C_70, +#endif + +#ifdef XI2C_71 + XI2C_71, +#endif + +#ifdef XI2C_72 + XI2C_72, +#endif + +#ifdef XI2C_73 + XI2C_73, +#endif + +#ifdef XI2C_74 + XI2C_74, +#endif + +#ifdef XI2C_75 + XI2C_75, +#endif + +#ifdef XI2C_76 + XI2C_76, +#endif + +#ifdef XI2C_77 + XI2C_77, +#endif + +#ifdef XI2C_78 + XI2C_78, +#endif + +#ifdef XI2C_79 + XI2C_79, +#endif + +#ifdef XI2C_80 + XI2C_80, +#endif + +#ifdef XI2C_81 + XI2C_81, +#endif + +#ifdef XI2C_82 + XI2C_82, +#endif + +#ifdef XI2C_83 + XI2C_83, +#endif + +#ifdef XI2C_84 + XI2C_84, +#endif + +#ifdef XI2C_85 + XI2C_85, +#endif + +#ifdef XI2C_86 + XI2C_86, +#endif + +#ifdef XI2C_87 + XI2C_87, +#endif + +#ifdef XI2C_88 + XI2C_88, +#endif + +#ifdef XI2C_89 + XI2C_89, +#endif + +#ifdef XI2C_90 + XI2C_90, +#endif + +#ifdef XI2C_91 + XI2C_91, +#endif + +#ifdef XI2C_92 + XI2C_92, +#endif + +#ifdef XI2C_93 + XI2C_93, +#endif + +#ifdef XI2C_94 + XI2C_94, +#endif + +#ifdef XI2C_95 + XI2C_95, +#endif + +#ifdef XI2C_96 + XI2C_96 +#endif +}; + + + +bool I2cEnabled(uint32_t i2c_index) +{ + return (i2c_flg && bitRead(Settings.i2c_drivers[i2c_index / 32], i2c_index % 32)); +} + +void I2cDriverState(void) +{ + ResponseAppend_P(PSTR("\"")); + for (uint32_t i = 0; i < sizeof(kI2cList); i++) { +#ifdef XFUNC_PTR_IN_ROM + uint32_t i2c_driver_id = pgm_read_byte(kI2cList + i); +#else + uint32_t i2c_driver_id = kI2cList[i]; +#endif + bool disabled = false; + if (i2c_driver_id < MAX_I2C_DRIVERS) { + disabled = !bitRead(Settings.i2c_drivers[i2c_driver_id / 32], i2c_driver_id % 32); + } + ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", i2c_driver_id); + } + ResponseAppend_P(PSTR("\"")); +} + +#endif \ No newline at end of file From 13eaa3c814e9f41fad073ac86ae95d9492d3df95 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 19:10:57 -0600 Subject: [PATCH 474/559] Disable debugging --- tasmota/support_device_groups.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index 7036169e8..c94ea2f57 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -22,7 +22,7 @@ */ #ifdef USE_DEVICE_GROUPS -#define DEVICE_GROUPS_DEBUG +//#define DEVICE_GROUPS_DEBUG extern bool udp_connected; From 486354fd7313dedec43fba293f3ace93bb224f22 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 20:31:49 -0600 Subject: [PATCH 475/559] Remove tasmota.ino.cpp --- tasmota/tasmota.ino.cpp | 78659 -------------------------------------- 1 file changed, 78659 deletions(-) delete mode 100644 tasmota/tasmota.ino.cpp diff --git a/tasmota/tasmota.ino.cpp b/tasmota/tasmota.ino.cpp deleted file mode 100644 index 8f8387ba2..000000000 --- a/tasmota/tasmota.ino.cpp +++ /dev/null @@ -1,78659 +0,0 @@ -# 1 "C:\\Users\\pcdie\\AppData\\Local\\Temp\\tmpnb0ml5sg" -#include -# 1 "S:/Development/Tasmota/tasmota/tasmota.ino" -# 29 "S:/Development/Tasmota/tasmota/tasmota.ino" -#include -#include "tasmota_version.h" -#include "tasmota.h" -#include "my_user_config.h" -#ifdef USE_MQTT_TLS - #include -#endif -#include "tasmota_post.h" -#include "i18n.h" -#include "tasmota_template.h" - -#ifdef ARDUINO_ESP8266_RELEASE_2_4_0 -#include "lwip/init.h" -#if LWIP_VERSION_MAJOR != 1 - #error Please use stable lwIP v1.4 -#endif -#endif - - -#include -#include -#include -#include -#ifdef USE_ARDUINO_OTA - #include - #ifndef USE_DISCOVERY - #define USE_DISCOVERY - #endif -#endif -#ifdef USE_DISCOVERY - #include -#endif -#ifdef USE_I2C - #include -#endif -#ifdef USE_SPI - #include -#endif - - -#include "settings.h" - - - - - -WiFiUDP PortUdp; - -unsigned long feature_drv1; -unsigned long feature_drv2; -unsigned long feature_sns1; -unsigned long feature_sns2; -unsigned long feature5; -unsigned long feature6; -unsigned long serial_polling_window = 0; -unsigned long state_second = 0; -unsigned long state_50msecond = 0; -unsigned long state_100msecond = 0; -unsigned long state_250msecond = 0; -unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; -unsigned long blink_timer = 0; -unsigned long backlog_delay = 0; -power_t power = 0; -power_t last_power = 0; -power_t blink_power; -power_t blink_mask = 0; -power_t blink_powersave; -power_t latching_power = 0; -power_t rel_inverted = 0; -int serial_in_byte_counter = 0; -int ota_state_flag = 0; -int ota_result = 0; -int restart_flag = 0; -int wifi_state_flag = WIFI_RESTART; -int blinks = 201; -uint32_t uptime = 0; -uint32_t loop_load_avg = 0; -uint32_t global_update = 0; -uint32_t web_log_index = 1; -float global_temperature = 9999; -float global_humidity = 0; -float global_pressure = 0; -uint16_t tele_period = 9999; -uint16_t blink_counter = 0; -uint16_t seriallog_timer = 0; -uint16_t syslog_timer = 0; -int16_t save_data_counter; -RulesBitfield rules_flag; -uint8_t mqtt_cmnd_blocked = 0; -uint8_t mqtt_cmnd_blocked_reset = 0; -uint8_t state_250mS = 0; -uint8_t latching_relay_pulse = 0; -uint8_t sleep; -uint8_t blinkspeed = 1; -uint8_t pin[GPIO_MAX]; -uint8_t active_device = 1; -uint8_t leds_present = 0; -uint8_t led_inverted = 0; -uint8_t led_power = 0; -uint8_t ledlnk_inverted = 0; -uint8_t pwm_inverted = 0; -uint8_t energy_flg = 0; -uint8_t light_flg = 0; -uint8_t light_type = 0; -uint8_t serial_in_byte; -uint8_t ota_retry_counter = OTA_ATTEMPTS; -uint8_t devices_present = 0; -uint8_t seriallog_level; -uint8_t syslog_level; -uint8_t my_module_type; -uint8_t my_adc0; -uint8_t last_source = 0; -uint8_t shutters_present = 0; -uint8_t prepped_loglevel = 0; - -bool serial_local = false; -bool fallback_topic_flag = false; -bool backlog_mutex = false; -bool interlock_mutex = false; -bool stop_flash_rotate = false; -bool blinkstate = false; - -bool pwm_present = false; -bool i2c_flg = false; -bool spi_flg = false; -bool soft_spi_flg = false; -bool ntp_force_sync = false; -bool is_8285 = false; -myio my_module; -gpio_flag my_module_flag; -StateBitfield global_state; -char my_version[33]; -char my_image[33]; -char my_hostname[33]; -char mqtt_client[TOPSZ]; -char mqtt_topic[TOPSZ]; -char serial_in_buffer[INPUT_BUFFER_SIZE]; -char mqtt_data[MESSZ]; -char log_data[LOGSZ]; -char web_log[WEB_LOG_SIZE] = {'\0'}; -#ifdef SUPPORT_IF_STATEMENT - #include - LinkedList backlog; - #define BACKLOG_EMPTY (backlog.size() == 0) -#else - uint8_t backlog_index = 0; - uint8_t backlog_pointer = 0; - String backlog[MAX_BACKLOG]; - #define BACKLOG_EMPTY (backlog_pointer == backlog_index) -#endif -void setup(void); -void BacklogLoop(void); -void loop(void); -uint16_t SendMail(char *buffer); -uint32_t GetRtcSettingsCrc(void); -void RtcSettingsSave(void); -void RtcSettingsLoad(void); -bool RtcSettingsValid(void); -uint32_t GetRtcRebootCrc(void); -void RtcRebootSave(void); -void RtcRebootReset(void); -void RtcRebootLoad(void); -bool RtcRebootValid(void); -void SetFlashModeDout(void); -bool VersionCompatible(void); -void SettingsBufferFree(void); -bool SettingsBufferAlloc(void); -uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size); -uint16_t GetSettingsCrc(void); -uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size); -uint32_t GetSettingsCrc32(void); -void SettingsSaveAll(void); -void UpdateQuickPowerCycle(bool update); -uint32_t GetSettingsTextLen(void); -bool SettingsUpdateText(uint32_t index, const char* replace_me); -char* SettingsText(uint32_t index); -uint32_t GetSettingsAddress(void); -void SettingsSave(uint8_t rotate); -void SettingsLoad(void); -void EspErase(uint32_t start_sector, uint32_t end_sector); -void SettingsErase(uint8_t type); -void SettingsSdkErase(void); -void SettingsSdkWifiErase(void); -void SettingsDefault(void); -void SettingsDefaultSet1(void); -void SettingsDefaultSet2(void); -void SettingsResetStd(void); -void SettingsResetDst(void); -void SettingsDefaultWebColor(void); -void SettingsEnableAllI2cDrivers(void); -void SettingsDelta(void); -void OsWatchTicker(void); -void OsWatchInit(void); -void OsWatchLoop(void); -bool OsWatchBlockedLoop(void); -uint32_t ResetReason(void); -String GetResetReason(void); -size_t strchrspn(const char *str1, int character); -char* subStr(char* dest, char* str, const char *delim, int index); -float CharToFloat(const char *str); -int TextToInt(char *str); -char* ulltoa(unsigned long long value, char *str, int radix); -char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween); -char* Uint64toHex(uint64_t value, char *str, uint16_t bits); -char* dtostrfd(double number, unsigned char prec, char *s); -char* Unescape(char* buffer, uint32_t* size); -char* RemoveSpace(char* p); -char* ReplaceCommaWithDot(char* p); -char* LowerCase(char* dest, const char* source); -char* UpperCase(char* dest, const char* source); -char* UpperCase_P(char* dest, const char* source); -char* Trim(char* p); -char* RemoveAllSpaces(char* p); -char* NoAlNumToUnderscore(char* dest, const char* source); -char IndexSeparator(void); -void SetShortcutDefault(void); -uint8_t Shortcut(void); -bool ValidIpAddress(const char* str); -bool ParseIp(uint32_t* addr, const char* str); -uint32_t ParseParameters(uint32_t count, uint32_t *params); -bool NewerVersion(char* version_str); -char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option); -char* GetPowerDevice(char* dest, uint32_t idx, size_t size); -void GetEspHardwareType(void); -String GetDeviceHardware(void); -float ConvertTemp(float c); -float ConvertTempToCelsius(float c); -char TempUnit(void); -float ConvertHumidity(float h); -float ConvertPressure(float p); -String PressureUnit(void); -void ResetGlobalValues(void); -uint32_t SqrtInt(uint32_t num); -uint32_t RoundSqrtInt(uint32_t num); -char* GetTextIndexed(char* destination, size_t destination_size, uint32_t index, const char* haystack); -int GetCommandCode(char* destination, size_t destination_size, const char* needle, const char* haystack); -int GetStateNumber(char *state_text); -String GetSerialConfig(void); -void SetSerialBegin(); -void SetSerialConfig(uint32_t serial_config); -void SetSerialBaudrate(uint32_t baudrate); -void SetSerial(uint32_t baudrate, uint32_t serial_config); -void ClaimSerial(void); -void SerialSendRaw(char *codes); -uint32_t GetHash(const char *buffer, size_t size); -void ShowSource(uint32_t source); -void WebHexCode(uint32_t i, const char* code); -uint32_t WebColor(uint32_t i); -char* ResponseGetTime(uint32_t format, char* time_str); -int Response_P(const char* format, ...); -int ResponseTime_P(const char* format, ...); -int ResponseAppend_P(const char* format, ...); -int ResponseAppendTimeFormat(uint32_t format); -int ResponseAppendTime(void); -int ResponseJsonEnd(void); -int ResponseJsonEndEnd(void); -void DigitalWrite(uint32_t gpio_pin, uint32_t state); -uint8_t ModuleNr(void); -bool ValidTemplateModule(uint32_t index); -bool ValidModule(uint32_t index); -String AnyModuleName(uint32_t index); -String ModuleName(void); -void ModuleGpios(myio *gp); -gpio_flag ModuleFlag(void); -void ModuleDefault(uint32_t module); -void SetModuleType(void); -bool FlashPin(uint32_t pin); -uint8_t ValidPin(uint32_t pin, uint32_t gpio); -bool ValidGPIO(uint32_t pin, uint32_t gpio); -bool ValidAdc(void); -bool GetUsedInModule(uint32_t val, uint8_t *arr); -bool JsonTemplate(const char* dataBuf); -void TemplateJson(void); -inline int32_t TimeDifference(uint32_t prev, uint32_t next); -int32_t TimePassedSince(uint32_t timestamp); -bool TimeReached(uint32_t timer); -void SetNextTimeInterval(unsigned long& timer, const unsigned long step); -int32_t TimePassedSinceUsec(uint32_t timestamp); -bool TimeReachedUsec(uint32_t timer); -bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size); -bool I2cValidRead8(uint8_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead16(uint16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead16LE(uint16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg); -bool I2cValidRead24(int32_t *data, uint8_t addr, uint8_t reg); -uint8_t I2cRead8(uint8_t addr, uint8_t reg); -uint16_t I2cRead16(uint8_t addr, uint8_t reg); -int16_t I2cReadS16(uint8_t addr, uint8_t reg); -uint16_t I2cRead16LE(uint8_t addr, uint8_t reg); -int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg); -int32_t I2cRead24(uint8_t addr, uint8_t reg); -bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size); -bool I2cWrite8(uint8_t addr, uint8_t reg, uint16_t val); -bool I2cWrite16(uint8_t addr, uint8_t reg, uint16_t val); -int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len); -int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len); -void I2cScan(char *devs, unsigned int devs_len); -void I2cSetActiveFound(uint32_t addr, const char *types); -bool I2cActive(uint32_t addr); -bool I2cSetDevice(uint32_t addr); -void SetSeriallog(uint32_t loglevel); -void SetSyslog(uint32_t loglevel); -void GetLog(uint32_t idx, char** entry_pp, size_t* len_p); -void Syslog(void); -void AddLog(uint32_t loglevel); -void AddLog_P(uint32_t loglevel, const char *formatP); -void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2); -void PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...); -void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...); -void AddLog_Debug(PGM_P formatP, ...); -void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count); -void AddLogSerial(uint32_t loglevel); -void AddLogMissed(char *sensor, uint32_t misses); -void ButtonPullupFlag(uint8 button_bit); -void ButtonInvertFlag(uint8 button_bit); -void ButtonInit(void); -uint8_t ButtonSerial(uint8_t serial_in_byte); -void ButtonHandler(void); -void ButtonLoop(void); -void ResponseCmndNumber(int value); -void ResponseCmndFloat(float value, uint32_t decimals); -void ResponseCmndIdxNumber(int value); -void ResponseCmndChar(const char* value); -void ResponseCmndStateText(uint32_t value); -void ResponseCmndDone(void); -void ResponseCmndIdxChar(const char* value); -void ResponseCmndAll(uint32_t text_index, uint32_t count); -void ExecuteCommand(const char *cmnd, uint32_t source); -void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len); -void CmndBacklog(void); -void CmndDelay(void); -void CmndPower(void); -void CmndStatus(void); -void CmndState(void); -void CmndTempOffset(void); -void CmndSleep(void); -void CmndUpgrade(void); -void CmndOtaUrl(void); -void CmndSeriallog(void); -void CmndRestart(void); -void CmndPowerOnState(void); -void CmndPulsetime(void); -void CmndBlinktime(void); -void CmndBlinkcount(void); -void CmndSavedata(void); -void CmndSetoption(void); -void CmndTemperatureResolution(void); -void CmndHumidityResolution(void); -void CmndPressureResolution(void); -void CmndPowerResolution(void); -void CmndVoltageResolution(void); -void CmndFrequencyResolution(void); -void CmndCurrentResolution(void); -void CmndEnergyResolution(void); -void CmndWeightResolution(void); -void CmndModule(void); -void CmndModules(void); -void CmndGpio(void); -void CmndGpios(void); -void CmndTemplate(void); -void CmndPwm(void); -void CmndPwmfrequency(void); -void CmndPwmrange(void); -void CmndButtonDebounce(void); -void CmndSwitchDebounce(void); -void CmndBaudrate(void); -void CmndSerialConfig(void); -void CmndSerialSend(void); -void CmndSerialDelimiter(void); -void CmndSyslog(void); -void CmndLoghost(void); -void CmndLogport(void); -void CmndIpAddress(void); -void CmndNtpServer(void); -void CmndAp(void); -void CmndSsid(void); -void CmndPassword(void); -void CmndHostname(void); -void CmndWifiConfig(void); -void CmndFriendlyname(void); -void CmndSwitchMode(void); -void CmndInterlock(void); -void CmndTeleperiod(void); -void CmndReset(void); -void CmndTime(void); -void CmndTimezone(void); -void CmndTimeStdDst(uint32_t ts); -void CmndTimeStd(void); -void CmndTimeDst(void); -void CmndAltitude(void); -void CmndLedPower(void); -void CmndLedState(void); -void CmndLedMask(void); -void CmndWifiPower(void); -void CmndI2cScan(void); -void CmndI2cDriver(void); -void CmndDevGroupShare(void); -void CmndSensor(void); -void CmndDriver(void); -void CmndCrash(void); -void CmndWDT(void); -void CmndBlockedLoop(void); -void CrashDumpClear(void); -bool CrashFlag(void); -void CrashDump(void); -void DeviceGroupsInit(void); -bool DeviceGroupItemShared(bool incoming, uint8_t item); -void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * label); -void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...); -void ProcessDeviceGroupMessage(char * packet, int packet_length); -void DeviceGroupsLoop(void); -static bool spiflash_is_ready(void); -static void spi_write_enable(void); -bool EsptoolEraseSector(uint32_t sector); -void EsptoolErase(uint32_t start_sector, uint32_t end_sector); -void GetFeatures(void); -float fmodf(float x, float y); -double FastPrecisePow(double a, double b); -float FastPrecisePowf(const float x, const float y); -double TaylorLog(double x); -inline float sinf(float x); -inline float cosf(float x); -inline float tanf(float x); -inline float atanf(float x); -inline float asinf(float x); -inline float acosf(float x); -inline float sqrtf(float x); -inline float powf(float x, float y); -float cos_52s(float x); -float cos_52(float x); -float sin_52(float x); -float tan_56s(float x); -float tan_56(float x); -float atan_66s(float x); -float atan_66(float x); -float asinf1(float x); -float acosf1(float x); -float sqrt1(const float x); -uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, - uint16_t ito_min, uint16_t ito_max); -void* memchr(const void* ptr, int value, size_t num); -size_t strcspn(const char *str1, const char *str2); -char* strpbrk(const char *s1, const char *s2); -void* memmove_P(void *dest, const void *src, size_t n); -void update_rotary(void); -bool RotaryButtonPressed(void); -void RotaryInit(void); -void RotaryHandler(void); -void RotaryLoop(void); -uint32_t UtcTime(void); -uint32_t LocalTime(void); -uint32_t Midnight(void); -bool MidnightNow(void); -bool IsDst(void); -String GetBuildDateAndTime(void); -String GetMinuteTime(uint32_t minutes); -String GetTimeZone(void); -String GetDuration(uint32_t time); -String GetDT(uint32_t time); -String GetDateAndTime(uint8_t time_type); -uint32_t UpTime(void); -uint32_t MinutesUptime(void); -String GetUptime(void); -uint32_t MinutesPastMidnight(void); -void BreakTime(uint32_t time_input, TIME_T &tm); -uint32_t MakeTime(TIME_T &tm); -uint32_t RuleToTime(TimeRule r, int yr); -void RtcSecond(void); -void RtcSetTime(uint32_t epoch); -void RtcInit(void); -String GetStatistics(void); -String GetStatistics(void); -void SwitchPullupFlag(uint16 switch_bit); -void SwitchSetVirtual(uint32_t index, uint8_t state); -uint8_t SwitchGetVirtual(uint32_t index); -uint8_t SwitchLastState(uint32_t index); -bool SwitchState(uint32_t index); -void SwitchProbe(void); -void SwitchInit(void); -void SwitchHandler(uint8_t mode); -void SwitchLoop(void); -char* Format(char* output, const char* input, int size); -char* GetOtaUrl(char *otaurl, size_t otaurl_size); -char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic); -char* GetGroupTopic_P(char *stopic, const char* subtopic); -char* GetFallbackTopic_P(char *stopic, const char* subtopic); -char* GetStateText(uint32_t state); -void SetLatchingRelay(power_t lpower, uint32_t state); -void SetDevicePower(power_t rpower, uint32_t source); -void RestorePower(bool publish_power, uint32_t source); -void SetAllPower(uint32_t state, uint32_t source); -void SetPowerOnState(void); -void SetLedPowerIdx(uint32_t led, uint32_t state); -void SetLedPower(uint32_t state); -void SetLedPowerAll(uint32_t state); -void SetLedLink(uint32_t state); -void SetPulseTimer(uint32_t index, uint32_t time); -uint32_t GetPulseTimer(uint32_t index); -bool SendKey(uint32_t key, uint32_t device, uint32_t state); -void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source); -void StopAllPowerBlink(void); -void MqttShowPWMState(void); -void MqttShowState(void); -void MqttPublishTeleState(void); -bool MqttShowSensor(void); -void MqttPublishSensor(void); -void PerformEverySecond(void); -void Every100mSeconds(void); -void Every250mSeconds(void); -void ArduinoOTAInit(void); -void ArduinoOtaLoop(void); -void SerialInput(void); -void GpioInit(void); -bool UdpDisconnect(void); -bool UdpConnect(void); -void PollUdp(void); -int WifiGetRssiAsQuality(int rssi); -bool WifiConfigCounter(void); -void WifiConfig(uint8_t type); -void WifiSetMode(WiFiMode_t wifi_mode); -void WiFiSetSleepMode(void); -void WifiBegin(uint8_t flag, uint8_t channel); -void WifiBeginAfterScan(void); -uint16_t WifiLinkCount(void); -String WifiDowntime(void); -void WifiSetState(uint8_t state); -bool WifiCheckIPv6(void); -String WifiGetIPv6(void); -bool WifiCheckIPAddrStatus(void); -void WifiCheckIp(void); -void WifiCheck(uint8_t param); -int WifiState(void); -String WifiGetOutputPower(void); -void WifiSetOutputPower(void); -void WifiConnect(void); -void WifiDisconnect(void); -void WifiShutdown(void); -void EspRestart(void); -static void WebGetArg(const char* arg, char* out, size_t max); -static bool WifiIsInManagerMode(); -void ShowWebSource(uint32_t source); -void ExecuteWebCommand(char* svalue, uint32_t source); -void StartWebserver(int type, IPAddress ipweb); -void StopWebserver(void); -void WifiManagerBegin(bool reset_only); -void PollDnsWebserver(void); -bool WebAuthenticate(void); -void HttpHeaderCors(void); -void WSHeaderSend(void); -void WSSend(int code, int ctype, const String& content); -void WSContentBegin(int code, int ctype); -void _WSContentSend(const String& content); -void WSContentFlush(void); -void _WSContentSendBuffer(void); -void WSContentSend_P(const char* formatP, ...); -void WSContentSend_PD(const char* formatP, ...); -void WSContentStart_P(const char* title, bool auth); -void WSContentStart_P(const char* title); -void WSContentSendStyle_P(const char* formatP, ...); -void WSContentSendStyle(void); -void WSContentButton(uint32_t title_index); -void WSContentSpaceButton(uint32_t title_index); -void WSContentEnd(void); -void WSContentStop(void); -void WebRestart(uint32_t type); -void HandleWifiLogin(void); -void WebSliderColdWarm(void); -void HandleRoot(void); -bool HandleRootStatusRefresh(void); -int32_t IsShutterWebButton(uint32_t idx); -void HandleConfiguration(void); -void HandleTemplateConfiguration(void); -void TemplateSaveSettings(void); -void HandleModuleConfiguration(void); -void ModuleSaveSettings(void); -String HtmlEscape(const String unescaped); -void HandleWifiConfiguration(void); -void WifiSaveSettings(void); -void HandleLoggingConfiguration(void); -void LoggingSaveSettings(void); -void HandleOtherConfiguration(void); -void OtherSaveSettings(void); -void HandleBackupConfiguration(void); -void HandleResetConfiguration(void); -void HandleRestoreConfiguration(void); -void HandleInformation(void); -void HandleUpgradeFirmware(void); -void HandleUpgradeFirmwareStart(void); -void HandleUploadDone(void); -void HandleUploadLoop(void); -void HandlePreflightRequest(void); -void HandleHttpCommand(void); -void HandleConsole(void); -void HandleConsoleRefresh(void); -void HandleNotFound(void); -bool CaptivePortal(void); -String UrlEncode(const String& text); -int WebSend(char *buffer); -bool JsonWebColor(const char* dataBuf); -void CmndEmulation(void); -void CmndSendmail(void); -void CmndWebServer(void); -void CmndWebPassword(void); -void CmndWeblog(void); -void CmndWebRefresh(void); -void CmndWebSend(void); -void CmndWebColor(void); -void CmndWebSensor(void); -void CmndWebButton(void); -void CmndCors(void); -bool Xdrv01(uint8_t function); -bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value); -void MakeValidMqtt(uint32_t option, char* str); -void MqttDiscoverServer(void); -void MqttInit(void); -bool MqttIsConnected(void); -void MqttDisconnect(void); -void MqttSubscribeLib(const char *topic); -void MqttUnsubscribeLib(const char *topic); -bool MqttPublishLib(const char* topic, bool retained); -void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len); -void MqttRetryCounter(uint8_t value); -void MqttSubscribe(const char *topic); -void MqttUnsubscribe(const char *topic); -void MqttPublishLogging(const char *mxtime); -void MqttPublish(const char* topic, bool retained); -void MqttPublish(const char* topic); -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained); -void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic); -void MqttPublishTeleSensor(void); -void MqttPublishPowerState(uint32_t device); -void MqttPublishAllPowerState(void); -void MqttPublishPowerBlinkState(uint32_t device); -uint16_t MqttConnectCount(void); -void MqttDisconnected(int state); -void MqttConnected(void); -void MqttReconnect(void); -void MqttCheck(void); -void CmndMqttFingerprint(void); -void CmndMqttUser(void); -void CmndMqttPassword(void); -void CmndMqttlog(void); -void CmndMqttHost(void); -void CmndMqttPort(void); -void CmndMqttRetry(void); -void CmndStateText(void); -void CmndMqttClient(void); -void CmndFullTopic(void); -void CmndPrefix(void); -void CmndPublish(void); -void CmndGroupTopic(void); -void CmndTopic(void); -void CmndButtonTopic(void); -void CmndSwitchTopic(void); -void CmndButtonRetain(void); -void CmndSwitchRetain(void); -void CmndPowerRetain(void); -void CmndSensorRetain(void); -inline void TlsEraseBuffer(uint8_t *buffer); -void loadTlsDir(void); -void CmndTlsKey(void); -uint32_t bswap32(uint32_t x); -void CmndTlsDump(void); -void HandleMqttConfiguration(void); -void MqttSaveSettings(void); -bool Xdrv02(uint8_t function); -bool EnergyTariff1Active(); -void EnergyUpdateToday(void); -void EnergyUpdateTotal(float value, bool kwh); -void Energy200ms(void); -void EnergySaveState(void); -bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag); -void EnergyMarginCheck(void); -void EnergyMqttShow(void); -void EnergyEverySecond(void); -void EnergyCommandCalResponse(uint32_t nvalue); -void CmndEnergyReset(void); -void CmndTariff(void); -void CmndPowerCal(void); -void CmndVoltageCal(void); -void CmndCurrentCal(void); -void CmndPowerSet(void); -void CmndVoltageSet(void); -void CmndCurrentSet(void); -void CmndFrequencySet(void); -void CmndModuleAddress(void); -void CmndPowerDelta(void); -void CmndPowerLow(void); -void CmndPowerHigh(void); -void CmndVoltageLow(void); -void CmndVoltageHigh(void); -void CmndCurrentLow(void); -void CmndCurrentHigh(void); -void CmndMaxPower(void); -void CmndMaxPowerHold(void); -void CmndMaxPowerWindow(void); -void CmndSafePower(void); -void CmndSafePowerHold(void); -void CmndSafePowerWindow(void); -void CmndMaxEnergy(void); -void CmndMaxEnergyStart(void); -void EnergySnsInit(void); -void EnergyShow(bool json); -bool Xdrv03(uint8_t function); -bool Xsns03(uint8_t function); -power_t LightPower(void); -power_t LightPowerIRAM(void); -uint8_t LightDevice(void); -static uint32_t min3(uint32_t a, uint32_t b, uint32_t c); -uint16_t change8to10(uint8_t v); -uint8_t change10to8(uint16_t v); -uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr); -uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr); -uint16_t ledGamma10_10(uint16_t v); -uint16_t ledGamma10(uint8_t v); -uint8_t ledGamma(uint8_t v); -void LightPwmOffset(uint32_t offset); -bool LightModuleInit(void); -void LightInit(void); -void LightUpdateColorMapping(void); -uint8_t LightGetDimmer(uint8_t dimmer); -void LightSetDimmer(uint8_t dimmer); -void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri); -void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); -uint8_t LightGetBri(uint8_t device); -void LightSetBri(uint8_t device, uint8_t bri); -void LightSetColorTemp(uint16_t ct); -uint16_t LightGetColorTemp(void); -void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value); -void LightPowerOn(void); -void LightState(uint8_t append); -void LightCycleColor(int8_t direction); -void LightSetPower(void); -void LightAnimate(void); -bool isChannelGammaCorrected(uint32_t channel); -uint16_t fadeGamma(uint32_t channel, uint16_t v); -uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg); -bool LightApplyFade(void); -void LightApplyPower(uint8_t new_color[LST_MAX], power_t power); -void LightSetOutputs(const uint16_t *cur_col_10); -void calcGammaMultiChannels(uint16_t cur_col_10[5]); -void calcGammaBulbs(uint16_t cur_col_10[5]); -void LightSendDeviceGroupStatus(); -void LightHandleDeviceGroupRequest(); -bool LightColorEntry(char *buffer, uint32_t buffer_length); -void CmndSupportColor(void); -void CmndColor(void); -void CmndWhite(void); -void CmndChannel(void); -void CmndHsbColor(void); -void CmndScheme(void); -void CmndWakeup(void); -void CmndColorTemperature(void); -void CmndDimmer(void); -void CmndDimmerRange(void); -void CmndLedTable(void); -void CmndRgbwwTable(void); -void CmndFade(void); -void CmndSpeed(void); -void CmndWakeupDuration(void); -void CmndUndocA(void); -bool Xdrv04(uint8_t function); -void IrSendInit(void); -void IrReceiveUpdateThreshold(void); -void IrReceiveInit(void); -void IrReceiveCheck(void); -uint32_t IrRemoteCmndIrSendJson(void); -void CmndIrSend(void); -void IrRemoteCmndResponse(uint32_t error); -bool Xdrv05(uint8_t function); -void IrSendInit(void); -uint8_t reverseBitsInByte(uint8_t b); -uint64_t reverseBitsInBytes64(uint64_t b); -void IrReceiveUpdateThreshold(void); -void IrReceiveInit(void); -String sendIRJsonState(const struct decode_results &results); -void IrReceiveCheck(void); -String listSupportedProtocols(bool hvac); -uint32_t IrRemoteCmndIrHvacJson(void); -void CmndIrHvac(void); -uint32_t IrRemoteCmndIrSendJson(void); -uint32_t IrRemoteCmndIrSendRaw(void); -void CmndIrSend(void); -void IrRemoteCmndResponse(uint32_t error); -bool Xdrv05(uint8_t function); -ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size); -ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size); -ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len); -ssize_t rf_decode_and_write(uint8_t *record, size_t size); -ssize_t rf_search_and_write(uint8_t *buf, size_t size); -uint8_t rf_erase_flash(void); -uint8_t SnfBrUpdateInit(void); -void SonoffBridgeReceivedRaw(void); -void SonoffBridgeLearnFailed(void); -void SonoffBridgeReceived(void); -bool SonoffBridgeSerialInput(void); -void SonoffBridgeSendCommand(uint8_t code); -void SonoffBridgeSendAck(void); -void SonoffBridgeSendCode(uint32_t code); -void SonoffBridgeSend(uint8_t idx, uint8_t key); -void SonoffBridgeLearn(uint8_t key); -void CmndRfBridge(void); -void CmndRfKey(void); -void CmndRfRaw(void); -bool Xdrv06(uint8_t function); -int DomoticzBatteryQuality(void); -int DomoticzRssiQuality(void); -void MqttPublishDomoticzFanState(void); -void DomoticzUpdateFanState(void); -void MqttPublishDomoticzPowerState(uint8_t device); -void DomoticzUpdatePowerState(uint8_t device); -void DomoticzMqttUpdate(void); -void DomoticzMqttSubscribe(void); -bool DomoticzMqttData(void); -bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg); -uint8_t DomoticzHumidityState(char *hum); -void DomoticzSensor(uint8_t idx, char *data); -void DomoticzSensor(uint8_t idx, uint32_t value); -void DomoticzTempHumSensor(char *temp, char *hum); -void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro); -void DomoticzSensorPowerEnergy(int power, char *energy); -void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power); -void CmndDomoticzIdx(void); -void CmndDomoticzKeyIdx(void); -void CmndDomoticzSwitchIdx(void); -void CmndDomoticzSensorIdx(void); -void CmndDomoticzUpdateTimer(void); -void HandleDomoticzConfiguration(void); -void DomoticzSaveSettings(void); -bool Xdrv07(uint8_t function); -void SerialBridgeInput(void); -void SerialBridgeInit(void); -void CmndSSerialSend(void); -void CmndSBaudrate(void); -bool Xdrv08(uint8_t function); -float JulianischesDatum(void); -float InPi(float x); -float eps(float T); -float BerechneZeitgleichung(float *DK,float T); -void DuskTillDawn(uint8_t *hour_up,uint8_t *minute_up, uint8_t *hour_down, uint8_t *minute_down); -void ApplyTimerOffsets(Timer *duskdawn); -String GetSun(uint32_t dawn); -uint16_t SunMinutes(uint32_t dawn); -void TimerSetRandomWindow(uint32_t index); -void TimerSetRandomWindows(void); -void TimerEverySecond(void); -void PrepShowTimer(uint32_t index); -void CmndTimer(void); -void CmndTimers(void); -void CmndLongitude(void); -void CmndLatitude(void); -void HandleTimerConfiguration(void); -void TimerSaveSettings(void); -bool Xdrv09(uint8_t function); -bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule); -int8_t parseCompareExpression(String &expr, String &leftExpr, String &rightExpr); -void RulesVarReplace(String &commands, const String &sfind, const String &replace); -bool RuleSetProcess(uint8_t rule_set, String &event_saved); -bool RulesProcessEvent(char *json_event); -bool RulesProcess(void); -void RulesInit(void); -void RulesEvery50ms(void); -void RulesEvery100ms(void); -void RulesEverySecond(void); -void RulesSaveBeforeRestart(void); -void RulesSetPower(void); -void RulesTeleperiod(void); -bool RulesMqttData(void); -void CmndSubscribe(void); -void CmndUnsubscribe(void); -bool findNextNumber(char * &pNumber, float &value); -bool findNextVariableValue(char * &pVarname, float &value); -bool findNextObjectValue(char * &pointer, float &value); -bool findNextOperator(char * &pointer, int8_t &op); -float calculateTwoValues(float v1, float v2, uint8_t op); -float evaluateExpression(const char * expression, unsigned int len); -void CmndIf(void); -bool evaluateComparisonExpression(const char *expression, int len); -bool findNextLogicOperator(char * &pointer, int8_t &op); -bool findNextLogicObjectValue(char * &pointer, bool &value); -bool evaluateLogicalExpression(const char * expression, int len); -int8_t findIfBlock(char * &pointer, int &lenWord, int8_t block_type); -void ExecuteCommandBlock(const char * commands, int len); -void ProcessIfStatement(const char* statements); -void RulesPreprocessCommand(char *pCommands); -void CmndRule(void); -void CmndRuleTimer(void); -void CmndEvent(void); -void CmndVariable(void); -void CmndMemory(void); -void CmndCalcResolution(void); -void CmndAddition(void); -void CmndSubtract(void); -void CmndMultiply(void); -void CmndScale(void); -float map_double(float x, float in_min, float in_max, float out_min, float out_max); -bool Xdrv10(uint8_t function); -void ScriptEverySecond(void); -void RulesTeleperiod(void); -int16_t Init_Scripter(void); -void ws2812_set_array(float *array ,uint8_t len); -float median_array(float *array,uint8_t len); -float Get_MFVal(uint8_t index,uint8_t bind); -void Set_MFVal(uint8_t index,uint8_t bind,float val); -float Get_MFilter(uint8_t index); -void Set_MFilter(uint8_t index, float invar); -float DoMedian5(uint8_t index, float in); -uint32_t HSVToRGB(uint16_t hue, uint8_t saturation, uint8_t value); -uint16_t GetStack(void); -uint16_t GetStack(void); -void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize); -void toLog(const char *str); -void toLogN(const char *cp,uint8_t len); -void toLogEOL(const char *s1,const char *str); -void toSLog(const char *str); -int16_t Run_Scripter(const char *type, int8_t tlen, char *js); -void ScripterEvery100ms(void); -void Scripter_save_pvars(void); -void ListDir(char *path, uint8_t depth); -void Script_FileUploadConfiguration(void); -void ScriptFileUploadSuccess(void); -void script_upload(void); -uint8_t DownloadFile(char *file); -void HandleScriptTextareaConfiguration(void); -void HandleScriptConfiguration(void); -void ScriptSaveSettings(void); -void Script_HueStatus(String *response, uint16_t hue_devs); -void Script_Check_Hue(String *response); -void Script_Handle_Hue(String *path); -bool Script_SubCmd(void); -void execute_script(char *script); -bool ScriptCommand(void); -uint16_t xFAT_DATE(uint16_t year, uint8_t month, uint8_t day); -uint16_t xFAT_TIME(uint8_t hour, uint8_t minute, uint8_t second); -void dateTime(uint16_t* date, uint16_t* time); -bool ScriptMqttData(void); -String ScriptSubscribe(const char *data, int data_len); -String ScriptUnsubscribe(const char * data, int data_len); -void Script_Check_HTML_Setvars(void); -void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen); -void ScriptWebShow(void); -void ScriptJsonAppend(void); -bool Xdrv10(uint8_t function); -void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ); -void KNX_DEL_GA( uint8_t GAnum ); -void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ); -void KNX_DEL_CB( uint8_t CBnum ); -bool KNX_CONFIG_NOT_MATCH(void); -void KNXStart(void); -void KNX_INIT(void); -void KNX_CB_Action(message_t const &msg, void *arg); -void KnxUpdatePowerState(uint8_t device, power_t state); -void KnxSendButtonPower(void); -void KnxSensor(uint8_t sensor_type, float value); -void HandleKNXConfiguration(void); -void KNX_Save_Settings(void); -void CmndKnxTxCmnd(void); -void CmndKnxTxVal(void); -void CmndKnxEnabled(void); -void CmndKnxEnhanced(void); -void CmndKnxPa(void); -void CmndKnxGa(void); -void CmndKnxCb(void); -bool Xdrv11(uint8_t function); -void TryResponseAppend_P(const char *format, ...); -void HAssAnnounceRelayLight(void); -void HAssAnnounceButtonSwitch(uint8_t device, char *topic, uint8_t present, uint8_t key, uint8_t toggle); -void HAssAnnounceSwitches(void); -void HAssAnnounceButtons(void); -void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, uint8_t subidx); -void HAssAnnounceSensors(void); -void HAssAnnounceStatusSensor(void); -void HAssPublishStatus(void); -void HAssDiscovery(void); -void HAssDiscover(void); -void HAssAnyKey(void); -bool Xdrv12(uint8_t function); -void DisplayInit(uint8_t mode); -void DisplayClear(void); -void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color); -void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color); -void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color); -void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color); -void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color); -void DisplayDrawFrame(void); -void DisplaySetSize(uint8_t size); -void DisplaySetFont(uint8_t font); -void DisplaySetRotation(uint8_t rotation); -void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void DisplayOnOff(uint8_t on); -uint8_t fatoiv(char *cp,float *res); -uint8_t atoiv(char *cp, int16_t *res); -uint8_t atoiV(char *cp, uint16_t *res); -void alignright(char *string); -uint32_t decode_te(char *line); -void DisplayText(void); -void DisplayClearScreenBuffer(void); -void DisplayFreeScreenBuffer(void); -void DisplayAllocScreenBuffer(void); -void DisplayReAllocScreenBuffer(void); -void DisplayFillScreen(uint32_t line); -void DisplayClearLogBuffer(void); -void DisplayFreeLogBuffer(void); -void DisplayAllocLogBuffer(void); -void DisplayReAllocLogBuffer(void); -void DisplayLogBufferAdd(char* txt); -char* DisplayLogBuffer(char temp_code); -void DisplayLogBufferInit(void); -void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value); -void DisplayAnalyzeJson(char *topic, char *json); -void DisplayMqttSubscribe(void); -bool DisplayMqttData(void); -void DisplayLocalSensor(void); -void DisplayInitDriver(void); -void DisplaySetPower(void); -void CmndDisplay(void); -void CmndDisplayModel(void); -void CmndDisplayWidth(void); -void CmndDisplayHeight(void); -void CmndDisplayMode(void); -void CmndDisplayDimmer(void); -void CmndDisplaySize(void); -void CmndDisplayFont(void); -void CmndDisplayRotate(void); -void CmndDisplayText(void); -void CmndDisplayAddress(void); -void CmndDisplayRefresh(void); -void CmndDisplayColumns(void); -void CmndDisplayRows(void); -void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp); -void DrawAClock(uint16_t rad); -void ClrGraph(uint16_t num); -void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol); -void DisplayCheckGraph(); -void Save_graph(uint8_t num, char *path); -void Restore_graph(uint8_t num, char *path); -void RedrawGraph(uint8_t num, uint8_t flags); -void AddGraph(uint8_t num,uint8_t val); -void AddValue(uint8_t num,float fval); -bool Xdrv13(uint8_t function); -uint16_t MP3_Checksum(uint8_t *array); -void MP3PlayerInit(void); -void MP3_CMD(uint8_t mp3cmd,uint16_t val); -bool MP3PlayerCmd(void); -bool Xdrv14(uint8_t function); -void PCA9685_Detect(void); -void PCA9685_Reset(void); -void PCA9685_SetPWMfreq(double freq); -void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off); -void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted); -bool PCA9685_Command(void); -void PCA9685_OutputTelemetry(bool telemetry); -bool Xdrv15(uint8_t function); -void CmndTuyaSend(void); -void CmndTuyaMcu(void); -void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId); -void UpdateDevices(); -inline bool TuyaFuncIdValid(uint8_t fnId); -uint8_t TuyaGetFuncId(uint8_t dpid); -uint8_t TuyaGetDpId(uint8_t fnId); -void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value); -void TuyaSendBool(uint8_t id, bool value); -void TuyaSendValue(uint8_t id, uint32_t value); -void TuyaSendEnum(uint8_t id, uint32_t value); -void TuyaSendString(uint8_t id, char data[]); -bool TuyaSetPower(void); -bool TuyaSetChannels(void); -void LightSerialDuty(uint16_t duty); -void TuyaRequestState(void); -void TuyaResetWifi(void); -void TuyaProcessStatePacket(void); -void TuyaLowPowerModePacketProcess(void); -void TuyaHandleProductInfoPacket(void); -void TuyaSendLowPowerSuccessIfNeeded(void); -void TuyaNormalPowerModePacketProcess(void); -bool TuyaModuleSelected(void); -void TuyaInit(void); -void TuyaSerialInput(void); -bool TuyaButtonPressed(void); -uint8_t TuyaGetTuyaWifiState(void); -void TuyaSetWifiLed(void); -bool Xnrg16(uint8_t function); -bool Xdrv16(uint8_t function); -void RfReceiveCheck(void); -void RfInit(void); -void CmndRfSend(void); -bool Xdrv17(uint8_t function); -bool ArmtronixSetChannels(void); -void LightSerial2Duty(uint8_t duty1, uint8_t duty2); -void ArmtronixRequestState(void); -bool ArmtronixModuleSelected(void); -void ArmtronixInit(void); -void ArmtronixSerialInput(void); -void ArmtronixSetWifiLed(void); -bool Xdrv18(uint8_t function); -void PS16DZSerialSend(const char *tx_buffer); -void PS16DZSerialSendOk(void); -void PS16DZSerialSendUpdateCommand(void); -void PS16DZSerialInput(void); -bool PS16DZSerialSendUpdateCommandIfRequired(void); -void PS16DZInit(void); -bool PS16DZModuleSelected(void); -bool Xdrv19(uint8_t function); -String HueBridgeId(void); -String HueSerialnumber(void); -String HueUuid(void); -void HueRespondToMSearch(void); -String GetHueDeviceId(uint8_t id); -String GetHueUserId(void); -void HandleUpnpSetupHue(void); -void HueNotImplemented(String *path); -void HueConfigResponse(String *response); -void HueConfig(String *path); -uint8_t getLocalLightSubtype(uint8_t device); -void HueLightStatus1(uint8_t device, String *response); -bool HueActive(uint8_t device); -void HueLightStatus2(uint8_t device, String *response); -uint32_t EncodeLightId(uint8_t relay_id); -uint32_t DecodeLightId(uint32_t hue_id); -uint32_t findEchoGeneration(void); -void HueGlobalConfig(String *path); -void HueAuthentication(String *path); -void HueLights(String *path); -void HueGroups(String *path); -void HandleHueApi(String *path); -bool Xdrv20(uint8_t function); -String WemoSerialnumber(void); -String WemoUuid(void); -void WemoRespondToMSearch(int echo_type); -void HandleUpnpEvent(void); -void HandleUpnpService(void); -void HandleUpnpMetaService(void); -void HandleUpnpSetupWemo(void); -bool Xdrv21(uint8_t function); -bool IsModuleIfan(void); -uint8_t MaxFanspeed(void); -uint8_t GetFanspeed(void); -void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence); -void SonoffIfanReceived(void); -bool SonoffIfanSerialInput(void); -void CmndFanspeed(void); -bool SonoffIfanInit(void); -void SonoffIfanUpdate(void); -bool Xdrv22(uint8_t function); -void CopyJsonVariant(JsonObject &to, const String &key, const JsonVariant &val); -void CopyJsonArray(JsonArray &to, const JsonArray &arr); -void CopyJsonObject(JsonObject &to, const JsonObject &from); -uint16_t fromClusterCode(uint8_t c); -uint8_t toClusterCode(uint16_t c); -class SBuffer hibernateDevice(const struct Z_Device &device); -class SBuffer hibernateDevices(void); -void hidrateDevices(const SBuffer &buf); -void loadZigbeeDevices(void); -void saveZigbeeDevices(void); -void eraseZigbeeDevices(void); -uint8_t toPercentageCR2032(uint32_t voltage); -uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, - uint32_t offset, uint32_t len); -int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); -int32_t Z_AqaraCube(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); -void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint); -inline bool isXYZ(char c); -inline int8_t hexValue(char c); -void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz); -void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, bool direction, const SBuffer &payload); -const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd); -inline char hexDigit(uint32_t h); -String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z); -uint32_t ZigbeeAliasOrNumber(const char *state_text); -uint8_t ZigbeeGetInstructionSize(uint8_t instr); -void ZigbeeGotoLabel(uint8_t label); -void ZigbeeStateMachine_Run(void); -int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf); -int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf); -int32_t Z_Reboot(int32_t res, class SBuffer &buf); -int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf); -bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match); -int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf); -void Z_SendIEEEAddrReq(uint16_t shortaddr); -void Z_SendActiveEpReq(uint16_t shortaddr); -void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint); -int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf); -void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusterid, uint8_t transacid); -int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf); -int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf); -void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, const JsonObject *json); -int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); -int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf); -int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf); -int32_t Z_Load_Devices(uint8_t value); -int32_t Z_State_Ready(uint8_t value); -int32_t ZigbeeProcessInput(class SBuffer &buf); -void ZigbeeInput(void); -void ZigbeeInit(void); -uint32_t strToUInt(const JsonVariant &val); -void CmndZbReset(void); -void CmndZbZNPSendOrReceive(bool send); -void CmndZbZNPReceive(void); -void CmndZbZNPSend(void); -void ZigbeeZNPSend(const uint8_t *msg, size_t len); -void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, bool clusterSpecific, - uint16_t cluster, uint8_t cmd, const char *param); -void CmndZbSend(void); -void CmndZbBind(void); -void CmndZbProbe(void); -void CmndZbProbeOrPing(boolean probe); -void CmndZbPing(void); -void CmndZbName(void); -void CmndZbForget(void); -void CmndZbSave(void); -void CmndZbRead(void); -void CmndZbPermitJoin(void); -void CmndZbStatus(void); -bool Xdrv23(uint8_t function); -void BuzzerOff(void); -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode); -void BuzzerSetStateToLed(uint32_t state); -void BuzzerBeep(uint32_t count); -void BuzzerEnabledBeep(uint32_t count, uint32_t duration); -bool BuzzerPinState(void); -void BuzzerInit(void); -void BuzzerEvery100mSec(void); -void CmndBuzzer(void); -bool Xdrv24(uint8_t function); -void A4988Init(void); -void CmndDoMove(void); -void CmndDoRotate(void); -void CmndDoTurn(void); -void CmndSetMIS(void); -void CmndSetSPR(void); -void CmndSetRPM(void); -bool Xdrv25(uint8_t function); -void AriluxRfInterrupt(void); -void AriluxRfHandler(void); -void AriluxRfInit(void); -void AriluxRfDisable(void); -bool Xdrv26(uint8_t function); -void ShutterLogPos(uint32_t i); -void ShutterRtc50mS(void); -int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index); -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index); -void ShutterInit(void); -void ShutterReportPosition(bool always); -void ShutterLimitRealAndTargetPositions(uint32_t i); -void ShutterUpdatePosition(void); -bool ShutterState(uint32_t device); -void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos); -void ShutterWaitForMotorStop(uint32_t i); -int32_t ShutterCounterBasedPosition(uint32_t i); -void ShutterRelayChanged(void); -bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index); -void ShutterButtonHandler(void); -void ShutterSetPosition(uint32_t device, uint32_t position); -void CmndShutterOpen(void); -void CmndShutterClose(void); -void CmndShutterStop(void); -void CmndShutterPosition(void); -void CmndShutterOpenTime(void); -void CmndShutterCloseTime(void); -void CmndShutterMotorDelay(void); -void CmndShutterRelay(void); -void CmndShutterButton(void); -void CmndShutterSetHalfway(void); -void CmndShutterFrequency(void); -void CmndShutterSetClose(void); -void CmndShutterInvert(void); -void CmndShutterCalibration(void); -void CmndShutterLock(void); -void CmndShutterEnableEndStopTime(void); -bool Xdrv27(uint8_t function); -void Pcf8574SwitchRelay(void); -void Pcf8574Init(void); -void HandlePcf8574(void); -void Pcf8574SaveSettings(void); -bool Xdrv28(uint8_t function); -bool DeepSleepEnabled(void); -void DeepSleepReInit(void); -void DeepSleepPrepare(void); -void DeepSleepStart(void); -void DeepSleepEverySecond(void); -void CmndDeepsleepTime(void); -bool Xdrv29(uint8_t function); -uint8_t crc8(const uint8_t *p, uint8_t len); -void ExsSendCmd(uint8_t cmd, uint8_t value); -uint8_t ExsSetPower(uint8_t device, uint8_t power); -uint8_t ExsSetBri(uint8_t device, uint8_t bri); -uint8_t ExsSyncState(uint8_t device); -bool ExsSyncState(); -void ExsDebugState(); -void ExsPacketProcess(void); -bool ExsModuleSelected(void); -bool ExsSetChannels(void); -bool ExsSetPower(void); -void EsxMcuStart(void); -void ExsInit(void); -void ExsSerialInput(void); -void CmndExsDimm(void); -void CmndExsDimmTbl(void); -void CmndExsDimmVal(void); -void CmndExsDimms(void); -void CmndExsChLock(void); -void CmndExsState(void); -bool Xdrv30(uint8_t function); -uint32_t TasmotaSlave_FlashStart(void); -uint8_t TasmotaSlave_UpdateInit(void); -void TasmotaSlave_Reset(void); -uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout); -uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count); -uint8_t TasmotaSlave_execCmd(uint8_t cmd); -uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count); -uint8_t TasmotaSlave_exitProgMode(void); -uint8_t TasmotaSlave_SetupFlash(void); -uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo); -void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data); -void TasmotaSlave_Flash(void); -void TasmotaSlave_SetFlagFlashing(bool value); -bool TasmotaSlave_GetFlagFlashing(void); -void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size); -void TasmotaSlave_Init(void); -void TasmotaSlave_Show(void); -void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param); -void CmndTasmotaSlaveReset(void); -void CmndTasmotaSlaveSend(void); -void TasmotaSlave_ProcessIn(void); -bool Xdrv31(uint8_t function); -void HotPlugInit(void); -void HotPlugEverySecond(void); -void CmndHotPlugTime(void); -bool Xdrv32(uint8_t function); -bool NRF24initRadio(); -bool NRF24Detect(void); -bool Xdrv33(uint8_t function); -void WMotorV1Detect(void); -void WMotorV1Reset(void); -void WMotorV1SetFrequency(uint32_t freq); -void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val); -bool WMotorV1Command(void); -bool Xdrv34(uint8_t function); -void ExceptionTest(uint8_t type); -void CpuLoadLoop(void); -void DebugFreeMem(void); -void DebugFreeMem(void); -void DebugRtcDump(char* parms); -void DebugCfgDump(char* parms); -void DebugCfgPeek(char* parms); -void DebugCfgPoke(char* parms); -void SetFlashMode(uint8_t mode); -void CmndHelp(void); -void CmndRtcDump(void); -void CmndCfgDump(void); -void CmndCfgPeek(void); -void CmndCfgPoke(void); -void CmndCfgXor(void); -void CmndException(void); -void CmndCpuCheck(void); -void CmndFreemem(void); -void CmndSetSensor(void); -void CmndFlashMode(void); -uint32_t DebugSwap32(uint32_t x); -void CmndFlashDump(void); -void CmndI2cWrite(void); -void CmndI2cRead(void); -void CmndI2cStretch(void); -void CmndI2cClock(void); -bool Xdrv99(uint8_t function); -void XsnsDriverState(void); -bool XdrvRulesProcess(void); -void ShowFreeMem(const char *where); -bool XdrvCallDriver(uint32_t driver, uint8_t Function); -bool XdrvCall(uint8_t Function); -void LcdInitMode(void); -void LcdInit(uint8_t mode); -void LcdInitDriver(void); -void LcdDrawStringAt(void); -void LcdDisplayOnOff(uint8_t on); -void LcdCenter(uint8_t row, char* txt); -bool LcdPrintLog(void); -void LcdTime(void); -void LcdRefresh(void); -bool Xdsp01(uint8_t function); -void SSD1306InitDriver(void); -void Ssd1306PrintLog(void); -void Ssd1306Time(void); -void Ssd1306Refresh(void); -bool Xdsp02(byte function); -void MatrixWrite(void); -void MatrixClear(void); -void MatrixFixed(char* txt); -void MatrixCenter(char* txt); -void MatrixScrollLeft(char* txt, int loop); -void MatrixScrollUp(char* txt, int loop); -void MatrixInitMode(void); -void MatrixInit(uint8_t mode); -void MatrixInitDriver(void); -void MatrixOnOff(void); -void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void MatrixPrintLog(uint8_t direction); -void MatrixRefresh(void); -bool Xdsp03(uint8_t function); -void Ili9341InitMode(void); -void Ili9341Init(uint8_t mode); -void Ili9341InitDriver(void); -void Ili9341Clear(void); -void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag); -void Ili9341DisplayOnOff(uint8_t on); -void Ili9341OnOff(void); -void Ili9341PrintLog(void); -void Ili9341Refresh(void); -bool Xdsp04(uint8_t function); -void EpdInitDriver29(); -void EpdPrintLog29(void); -void EpdRefresh29(void); -bool Xdsp05(uint8_t function); -void EpdInitDriver42(); -void EpdRefresh42(); -bool Xdsp06(uint8_t function); -void SH1106InitDriver(); -void SH1106PrintLog(void); -void SH1106Time(void); -void SH1106Refresh(void); -bool Xdsp07(uint8_t function); -void ILI9488_InitDriver(); -void ILI9488_MQTT(uint8_t count,const char *cp); -void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr); -void FT6236Check(); -bool Xdsp08(uint8_t function); -void SSD1351_InitDriver(); -void SSD1351PrintLog(void); -void SSD1351Time(void); -void SSD1351Refresh(void); -bool Xdsp09(uint8_t function); -void RA8876_InitDriver(); -void RA8876_MQTT(uint8_t count,const char *cp); -void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr); -void FT5316Check(); -bool Xdsp10(uint8_t function); -uint8_t XdspPresent(void); -bool XdspCall(uint8_t Function); -void Ws2812StripShow(void); -int mod(int a, int b); -void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset); -void Ws2812UpdateHand(int position, uint32_t index); -void Ws2812Clock(void); -void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i); -void Ws2812Gradient(uint32_t schemenr); -void Ws2812Bars(uint32_t schemenr); -void Ws2812Clear(void); -void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white); -char* Ws2812GetColor(uint32_t led, char* scolor); -void Ws2812ForceSuspend (void); -void Ws2812ForceUpdate (void); -bool Ws2812SetChannels(void); -void Ws2812ShowScheme(void); -void Ws2812ModuleSelected(void); -void CmndLed(void); -void CmndPixels(void); -void CmndRotation(void); -void CmndWidth(void); -bool Xlgt01(uint8_t function); -void LightDiPulse(uint8_t times); -void LightDckiPulse(uint8_t times); -void LightMy92x1Write(uint8_t data); -void LightMy92x1Init(void); -void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c); -bool My92x1SetChannels(void); -void My92x1ModuleSelected(void); -bool Xlgt02(uint8_t function); -void SM16716_SendBit(uint8_t v); -void SM16716_SendByte(uint8_t v); -void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b); -void SM16716_Init(void); -bool Sm16716SetChannels(void); -void Sm16716ModuleSelected(void); -bool Xlgt03(uint8_t function); -uint8_t Sm2135Write(uint8_t data); -void Sm2135Send(uint8_t *buffer, uint8_t size); -bool Sm2135SetChannels(void); -void Sm2135ModuleSelected(void); -bool Xlgt04(uint8_t function); -void SnfL1Send(const char *buffer); -void SnfL1SerialSendOk(void); -bool SnfL1SerialInput(void); -bool SnfL1SetChannels(void); -void SnfL1ModuleSelected(void); -bool Xlgt05(uint8_t function); -bool XlgtCall(uint8_t function); -void HlwCfInterrupt(void); -void HlwCf1Interrupt(void); -void HlwEvery200ms(void); -void HlwEverySecond(void); -void HlwSnsInit(void); -void HlwDrvInit(void); -bool HlwCommand(void); -bool Xnrg01(uint8_t function); -void CseReceived(void); -bool CseSerialInput(void); -void CseEverySecond(void); -void CseSnsInit(void); -void CseDrvInit(void); -bool CseCommand(void); -bool Xnrg02(uint8_t function); -uint8_t PzemCrc(uint8_t *data); -void PzemSend(uint8_t cmd); -bool PzemReceiveReady(void); -bool PzemRecieve(uint8_t resp, float *data); -void PzemEvery250ms(void); -void PzemSnsInit(void); -void PzemDrvInit(void); -bool PzemCommand(void); -bool Xnrg03(uint8_t function); -uint8_t McpChecksum(uint8_t *data); -unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size); -void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size); -void McpSend(uint8_t *data); -void McpGetAddress(void); -void McpAddressReceive(void); -void McpGetCalibration(void); -void McpParseCalibration(void); -bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift); -void McpSetCalibration(struct mcp_cal_registers_type *cal_registers); -void McpSetSystemConfiguration(uint16 interval); -void McpGetFrequency(void); -void McpParseFrequency(void); -void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency); -void McpGetData(void); -void McpParseData(void); -void McpSerialInput(void); -void McpEverySecond(void); -void McpSnsInit(void); -void McpDrvInit(void); -bool McpCommand(void); -bool Xnrg04(uint8_t function); -void PzemAcEverySecond(void); -void PzemAcSnsInit(void); -void PzemAcDrvInit(void); -bool PzemAcCommand(void); -bool Xnrg05(uint8_t function); -void PzemDcEverySecond(void); -void PzemDcSnsInit(void); -void PzemDcDrvInit(void); -bool PzemDcCommand(void); -bool Xnrg06(uint8_t function); -int Ade7953RegSize(uint16_t reg); -void Ade7953Write(uint16_t reg, uint32_t val); -int32_t Ade7953Read(uint16_t reg); -void Ade7953Init(void); -void Ade7953GetData(void); -void Ade7953EnergyEverySecond(void); -void Ade7953DrvInit(void); -bool Ade7953Command(void); -bool Xnrg07(uint8_t function); -void SDM120Every250ms(void); -void Sdm120SnsInit(void); -void Sdm120DrvInit(void); -void Sdm220Reset(void); -void Sdm220Show(bool json); -bool Xnrg08(uint8_t function); -void Dds2382EverySecond(void); -void Dds2382SnsInit(void); -void Dds2382DrvInit(void); -bool Xnrg09(uint8_t function); -void SDM630Every250ms(void); -void Sdm630SnsInit(void); -void Sdm630DrvInit(void); -bool Xnrg10(uint8_t function); -void DDSU666Every250ms(void); -void Ddsu666SnsInit(void); -void Ddsu666DrvInit(void); -bool Xnrg11(uint8_t function); -bool solaxX1_RS485ReceiveReady(void); -void solaxX1_RS485Send(uint16_t msgLen); -uint8_t solaxX1_RS485Receive(uint8_t *value); -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen); -void solaxX1_SendInverterAddress(void); -void solaxX1_QueryLiveData(void); -uint8_t solaxX1_ParseErrorCode(uint32_t code); -void solaxX1250MSecond(void); -void solaxX1SnsInit(void); -void solaxX1DrvInit(void); -void solaxX1Show(bool json); -bool Xnrg12(uint8_t function); -void FifLEEvery250ms(void); -void FifLESnsInit(void); -void FifLEDrvInit(void); -void FifLEReset(void); -void FifLEShow(bool json); -bool Xnrg13(uint8_t function); -bool XnrgCall(uint8_t function); -void CounterUpdate(uint8_t index); -void CounterUpdate1(void); -void CounterUpdate2(void); -void CounterUpdate3(void); -void CounterUpdate4(void); -bool CounterPinState(void); -void CounterInit(void); -void CounterEverySecond(void); -void CounterSaveState(void); -void CounterShow(bool json); -void CmndCounter(void); -void CmndCounterType(void); -void CmndCounterDebounce(void); -bool Xsns01(uint8_t function); -void AdcInit(void); -uint16_t AdcRead(uint8_t factor); -void AdcEvery250ms(void); -uint16_t AdcGetLux(void); -uint16_t AdcGetRange(void); -void AdcGetCurrentPower(uint8_t factor); -void AdcEverySecond(void); -void AdcShow(bool json); -void CmndAdc(void); -void CmndAdcs(void); -void CmndAdcParam(void); -bool Xsns02(uint8_t function); -void SonoffScSend(const char *data); -void SonoffScInit(void); -void SonoffScSerialInput(char *rcvstat); -void SonoffScShow(bool json); -bool Xsns04(uint8_t function); -uint8_t OneWireReset(void); -void OneWireWriteBit(uint8_t v); -void OneWireReadBit1(void); -void OneWireReadBit2(void); -uint8_t OneWireReadBit(void); -void OneWireWrite(uint8_t v); -uint8_t OneWireRead(void); -void OneWireSelect(const uint8_t rom[8]); -void OneWireResetSearch(void); -uint8_t OneWireSearch(uint8_t *newAddr); -bool OneWireCrc8(uint8_t *addr); -void Ds18x20Init(void); -void Ds18x20Convert(void); -bool Ds18x20Read(uint8_t sensor); -void Ds18x20Name(uint8_t sensor); -void Ds18x20EverySecond(void); -void Ds18x20Show(bool json); -bool Xsns05(uint8_t function); -void DhtReadPrep(void); -int32_t DhtExpectPulse(uint8_t sensor, bool level); -bool DhtRead(uint8_t sensor); -void DhtReadTempHum(uint8_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -void DhtReadPrep(void); -int32_t DhtExpectPulse(uint8_t sensor, bool level); -bool DhtRead(uint8_t sensor); -void DhtReadTempHum(uint8_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool DhtExpectPulse(uint8_t sensor, int level); -int DhtReadDat(uint8_t sensor); -bool DhtRead(uint8_t sensor); -void DhtReadTempHum(uint8_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool DhtExpectPulse(uint32_t sensor, uint32_t level); -bool DhtRead(uint32_t sensor); -void DhtReadTempHum(uint32_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool DhtWaitState(uint32_t sensor, uint32_t level); -bool DhtRead(uint32_t sensor); -bool DhtPinState(); -void DhtInit(void); -void DhtEverySecond(void); -void DhtShow(bool json); -bool Xsns06(uint8_t function); -bool ShtReset(void); -bool ShtSendCommand(const uint8_t cmd); -bool ShtAwaitResult(void); -int ShtReadData(void); -bool ShtRead(void); -void ShtDetect(void); -void ShtEverySecond(void); -void ShtShow(bool json); -bool Xsns07(uint8_t function); -uint8_t HtuCheckCrc8(uint16_t data); -uint8_t HtuReadDeviceId(void); -void HtuSetResolution(uint8_t resolution); -void HtuReset(void); -void HtuHeater(uint8_t heater); -void HtuInit(void); -bool HtuRead(void); -void HtuDetect(void); -void HtuEverySecond(void); -void HtuShow(bool json); -bool Xsns08(uint8_t function); -bool Bmp180Calibration(uint8_t bmp_idx); -void Bmp180Read(uint8_t bmp_idx); -bool Bmx280Calibrate(uint8_t bmp_idx); -void Bme280Read(uint8_t bmp_idx); -static void BmeDelayMs(uint32_t ms); -bool Bme680Init(uint8_t bmp_idx); -void Bme680Read(uint8_t bmp_idx); -void BmpDetect(void); -void BmpRead(void); -void BmpShow(bool json); -void BMP_EnterSleep(void); -bool Xsns09(uint8_t function); -bool Bh1750Read(void); -void Bh1750Detect(void); -void Bh1750EverySecond(void); -void Bh1750Show(bool json); -bool Xsns10(uint8_t function); -void Veml6070Detect(void); -void Veml6070UvTableInit(void); -void Veml6070EverySecond(void); -void Veml6070ModeCmd(bool mode_cmd); -uint16_t Veml6070ReadUv(void); -double Veml6070UvRiskLevel(uint16_t uv_level); -double Veml6070UvPower(double uvrisk); -void Veml6070Show(bool json); -bool Xsns11(uint8_t function); -void Ads1115StartComparator(uint8_t channel, uint16_t mode); -int16_t Ads1115GetConversion(uint8_t channel); -void Ads1115Detect(void); -void Ads1115Show(bool json); -bool Xsns12(uint8_t function); -bool Ina219SetCalibration(uint8_t mode, uint16_t addr); -float Ina219GetShuntVoltage_mV(uint16_t addr); -float Ina219GetBusVoltage_V(uint16_t addr); -float Ina219GetCurrent_mA(uint16_t addr); -bool Ina219Read(void); -bool Ina219CommandSensor(void); -void Ina219Detect(void); -void Ina219EverySecond(void); -void Ina219Show(bool json); -bool Xsns13(uint8_t function); -bool Sht3xRead(float &t, float &h, uint8_t sht3x_address); -void Sht3xDetect(void); -void Sht3xShow(bool json); -bool Xsns14(uint8_t function); -uint8_t MhzCalculateChecksum(uint8_t *array); -size_t MhzSendCmd(uint8_t command_id); -bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s); -void MhzEverySecond(void); -bool MhzCommandSensor(void); -void MhzInit(void); -void MhzShow(bool json); -bool Xsns15(uint8_t function); -bool Tsl2561Read(void); -void Tsl2561Detect(void); -void Tsl2561EverySecond(void); -void Tsl2561Show(bool json); -bool Xsns16(uint8_t function); -void Senseair250ms(void); -void SenseairInit(void); -void SenseairShow(bool json); -bool Xsns17(uint8_t function); -bool PmsReadData(void); -void PmsSecond(void); -void PmsInit(void); -void PmsShow(bool json); -bool Xsns18(uint8_t function); -void MGSInit(void); -void MGSPrepare(void); -char* measure_gas(int gas_type, char* buffer); -void MGSShow(bool json); -bool Xsns19(uint8_t function); -bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer); -void NovaSdsSetWorkPeriod(void); -bool NovaSdsReadData(void); -void NovaSdsSecond(void); -bool NovaSdsCommandSensor(void); -void NovaSdsInit(void); -void NovaSdsShow(bool json); -bool Xsns20(uint8_t function); -void sgp30_Init(void); -float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit); -void Sgp30Update(void); -void Sgp30Show(bool json); -bool Xsns21(uint8_t function); -uint8_t Sr04TModeDetect(void); -uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third); -uint16_t Sr04TMode3Distance(); -uint16_t Sr04TMode2Distance(void); -void Sr04TReading(void); -void Sr04Show(bool json); -bool Xsns22(uint8_t function); -uint8_t Si1145ReadByte(uint8_t reg); -uint16_t Si1145ReadHalfWord(uint8_t reg); -bool Si1145WriteByte(uint8_t reg, uint16_t val); -uint8_t Si1145WriteParamData(uint8_t p, uint8_t v); -bool Si1145Present(void); -void Si1145Reset(void); -void Si1145DeInit(void); -bool Si1145Begin(void); -uint16_t Si1145ReadUV(void); -uint16_t Si1145ReadVisible(void); -uint16_t Si1145ReadIR(void); -bool Si1145Read(void); -void Si1145Detect(void); -void Si1145Update(void); -void Si1145Show(bool json); -bool Xsns24(uint8_t function); -void LM75ADDetect(void); -float LM75ADGetTemp(void); -void LM75ADShow(bool json); -bool Xsns26(uint8_t function); -int8_t wireReadDataBlock( uint8_t reg, - uint8_t *val, - uint16_t len); -void calculateColorTemperature(void); -bool APDS9960_init(void); -uint8_t getMode(void); -void setMode(uint8_t mode, uint8_t enable); -void enableLightSensor(void); -void disableLightSensor(void); -void enableProximitySensor(void); -void disableProximitySensor(void); -void enableGestureSensor(void); -void disableGestureSensor(void); -bool isGestureAvailable(void); -int16_t readGesture(void); -void enablePower(void); -void disablePower(void); -void readAllColorAndProximityData(void); -void resetGestureParameters(void); -bool processGestureData(void); -bool decodeGesture(void); -void handleGesture(void); -void APDS9960_adjustATime(void); -void APDS9960_loop(void); -void APDS9960_detect(void); -void APDS9960_show(bool json); -bool APDS9960CommandSensor(void); -bool Xsns27(uint8_t function); -void Tm16XXSend(uint8_t data); -void Tm16XXSendCommand(uint8_t cmd); -void TM16XXSendData(uint8_t address, uint8_t data); -uint8_t Tm16XXReceive(void); -void Tm16XXClearDisplay(void); -void Tm1638SetLED(uint8_t color, uint8_t pos); -void Tm1638SetLEDs(word leds); -uint8_t Tm1638GetButtons(void); -void TmInit(void); -void TmLoop(void); -bool Xsns28(uint8_t function); -void MCP230xx_CheckForIntCounter(void); -void MCP230xx_CheckForIntRetainer(void); -const char* IntModeTxt(uint8_t intmo); -uint8_t MCP230xx_readGPIO(uint8_t port); -void MCP230xx_ApplySettings(void); -void MCP230xx_Detect(void); -void MCP230xx_CheckForInterrupt(void); -void MCP230xx_Show(bool json); -void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate); -void MCP230xx_Reset(uint8_t pinmode); -bool MCP230xx_Command(void); -void MCP230xx_UpdateWebData(void); -void MCP230xx_OutputTelemetry(void); -void MCP230xx_Interrupt_Counter_Report(void); -void MCP230xx_Interrupt_Retain_Report(void); -bool Xsns29(uint8_t function); -void Mpr121Init(struct mpr121 *pS, bool initial); -void Mpr121Show(struct mpr121 *pS, uint8_t function); -bool Xsns30(uint8_t function); -void CCS811Detect(void); -void CCS811Update(void); -void CCS811Show(bool json); -bool Xsns31(uint8_t function); -void MPU_6050PerformReading(void); -void MPU_6050Detect(void); -void MPU_6050Show(bool json); -bool Xsns32(uint8_t function); -void DS3231Detect(void); -uint8_t bcd2dec(uint8_t n); -uint8_t dec2bcd(uint8_t n); -uint32_t ReadFromDS3231(void); -void SetDS3231Time (uint32_t epoch_time); -void DS3231EverySecond(void); -bool Xsns33(uint8_t function); -bool HxIsReady(uint16_t timeout); -long HxRead(void); -void HxResetPart(void); -void HxReset(void); -void HxCalibrationStateTextJson(uint8_t msg_id); -void SetWeightDelta(); -bool HxCommand(void); -long HxWeight(void); -void HxInit(void); -void HxEvery100mSecond(void); -void HxSaveBeforeRestart(void); -void HxShow(bool json); -void HandleHxAction(void); -void HxSaveSettings(void); -void HxLogUpdates(void); -bool Xsns34(uint8_t function); -void TX2xStartRead(void); -void Tx2xReset(void); -void Tx2xRead(void); -void Tx2xInit(void); -void Tx2xShow(bool json); -bool Xsns35(uint8_t function); -void MGC3130_handleSensorData(); -void MGC3130_sendMessage(uint8_t data[], uint8_t length); -void MGC3130_handleGesture(); -bool MGC3130_handleTouch(); -void MGC3130_handleAirWheel(); -void MGC3130_handleSystemStatus(); -bool MGC3130_receiveMessage(); -bool MGC3130_readData(); -void MGC3130_nextMode(); -void MGC3130_loop(); -void MGC3130_detect(void); -void MGC3130_show(bool json); -bool MGC3130CommandSensor(); -bool Xsns36(uint8_t function); -bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal); -void RfSnsInitTheoV2(void); -void RfSnsAnalyzeTheov2(void); -void RfSnsTheoV2Show(bool json); -void RfSnsInitAlectoV2(void); -void RfSnsAnalyzeAlectov2(); -void RfSnsAlectoResetRain(void); -uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len); -void RfSnsAlectoV2Show(bool json); -void RfSnsInit(void); -void RfSnsAnalyzeRawSignal(void); -void RfSnsEverySecond(void); -void RfSnsShow(bool json); -bool Xsns37(uint8_t function); -void AzEverySecond(void); -void AzInit(void); -void AzShow(bool json); -bool Xsns38(uint8_t function); -void MAX31855_Init(void); -void MAX31855_GetResult(void); -float MAX31855_GetProbeTemperature(int32_t RawData); -float MAX31855_GetReferenceTemperature(int32_t RawData); -int32_t MAX31855_ShiftIn(uint8_t Length); -void MAX31855_Show(bool Json); -bool Xsns39(uint8_t function); -void PN532_Init(void); -int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout); -int8_t PN532_readAckFrame(void); -uint32_t PN532_getFirmwareVersion(void); -void PN532_wakeup(void); -bool PN532_setPassiveActivationRetries(uint8_t maxRetries); -bool PN532_SAMConfig(void); -uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData); -uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data); -uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data); -void PN532_ScanForTag(void); -bool PN532_Command(void); -bool Xsns40(uint8_t function); -bool Max4409Read_lum(void); -void Max4409Detect(void); -void Max4409EverySecond(void); -void Max4409Show(bool json); -bool Xsns41(uint8_t function); -void Scd30Detect(void); -void Scd30Update(void); -int Scd30GetCommand(int command_code, uint16_t *pvalue); -int Scd30SetCommand(int command_code, uint16_t value); -bool Scd30CommandSensor(); -void Scd30Show(bool json); -bool Xsns42(byte function); -int hreReadBit(); -char hreReadChar(int &parity_errors); -void hreInit(void); -void hreEvery50ms(void); -void hreShow(boolean json); -bool Xsns43(byte function); -uint8_t sps30_calc_CRC(uint8_t *data); -void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen); -void sps30_cmd(uint16_t cmd); -void SPS30_Detect(void); -void SPS30_Every_Second(); -void SPS30_Show(bool json); -bool SPS30_cmd(void); -bool Xsns44(byte function); -void Vl53l0Detect(void); -void Vl53l0Every_250MSecond(void); -void Vl53l0Show(boolean json); -bool Xsns45(byte function); -void MLX90614_Init(void); -void MLX90614_Every_Second(void); -void MLX90614_Show(uint8_t json); -bool Xsns46(byte function); -void MAX31865_Init(void); -void MAX31865_GetResult(void); -void MAX31865_Show(bool Json); -bool Xsns47(uint8_t function); -void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg); -uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr); -void ChirpReset(uint8_t addr); -void ChirpResetAll(void); -void ChirpClockSet(); -void ChirpSleep(uint8_t addr); -void ChirpSelect(uint8_t sensor); -uint8_t ChirpReadVersion(uint8_t addr); -bool ChirpSet(uint8_t addr); -bool ChirpScan(); -void ChirpDetect(void); -void ChirpServiceAllSensors(uint8_t job); -void ChirpEvery100MSecond(void); -void ChirpShow(bool json); -bool ChirpCmd(void); -bool Xsns48(uint8_t function); -void PAJ7620SelectBank(uint8_t bank); -void PAJ7620DecodeGesture(void); -void PAJ7620ReadGesture(void); -void PAJ7620Detect(void); -void PAJ7620Init(void); -void PAJ7620Loop(void); -void PAJ7620Show(bool json); -bool PAJ7620CommandSensor(void); -bool Xsns50(uint8_t function); -void RDM6300_Init(); -void RDM6300_ScanForTag(); -uint8_t rm6300_hexnibble(char chr); -void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]); -void RDM6300_Show(void); -bool Xsns51(byte function); -void IBEACON_Init(); -void hm17_every_second(void); -void hm17_sbclr(void); -void hm17_sendcmd(uint8_t cmd); -uint32_t ibeacon_add(struct IBEACON *ib); -void hm17_decode(void); -void IBEACON_loop(); -void IBEACON_Show(void); -bool xsns52_cmd(void); -bool ibeacon_cmd(void); -void ib_sendbeep(void); -void ibeacon_mqtt(const char *mac,const char *rssi); -bool Xsns52(byte function); -double sml_median_array(double *array,uint8_t len); -double sml_median(struct SML_MEDIAN_FILTER* mf, double in); -void ADS1115_init(void); -bool Serial_available(); -uint8_t Serial_read(); -uint8_t Serial_peek(); -void Dump2log(void); -double sml_getvalue(unsigned char *cp,uint8_t index); -uint8_t hexnibble(char chr); -double CharToDouble(const char *str); -void ebus_esc(uint8_t *ebus_buffer, unsigned char len); -uint8_t ebus_crc8(uint8_t data, uint8_t crc_init); -uint8_t ebus_CalculateCRC( uint8_t *Data, uint16_t DataLen ); -void sml_empty_receiver(uint32_t meters); -void sml_shift_in(uint32_t meters,uint32_t shard); -void SML_Poll(void); -void SML_Decode(uint8_t index); -void SML_Immediate_MQTT(const char *mp,uint8_t index,uint8_t mindex); -void SML_Show(boolean json); -void SML_CounterUpd(uint8_t index); -void SML_CounterUpd1(void); -void SML_CounterUpd2(void); -void SML_CounterUpd3(void); -void SML_CounterUpd4(void); -bool Gpio_used(uint8_t gpiopin); -void SML_Init(void); -uint32_t SML_SetBaud(uint32_t meter, uint32_t br); -uint32_t SML_Write(uint32_t meter,char *hstr); -void SetDBGLed(uint8_t srcpin, uint8_t ledpin); -void SML_Counter_Poll(void); -void SML_Check_Send(void); -uint8_t sml_hexnibble(char chr); -void SML_Send_Seq(uint32_t meter,char *seq); -uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num); -uint8_t SML_PzemCrc(uint8_t *data, uint8_t len); -uint8_t CalcEvenParity(uint8_t data); -bool XSNS_53_cmd(void); -void InjektCounterValue(uint8_t meter,uint32_t counter); -void SML_CounterSaveState(void); -bool Xsns53(byte function); -static uint32_t _expand_r_shunt(uint16_t compact_r_shunt); -void Ina226SetCalibration(uint8_t slaveIndex); -bool Ina226TestPresence(uint8_t device); -void Ina226ResetActive(void); -void Ina226Init(); -float Ina226ReadBus_v(uint8_t device); -float Ina226ReadShunt_i(uint8_t device); -float Ina226ReadPower_w(uint8_t device); -void Ina226Read(uint8_t device); -void Ina226EverySecond(); -bool Ina226CommandSensor(); -void Ina226Show(bool json); -bool Xsns54(byte callback_id); -bool Hih6Read(void); -void Hih6Detect(void); -void Hih6EverySecond(void); -void Hih6Show(bool json); -bool Xsns55(uint8_t function); -void HpmaSecond(void); -void HpmaInit(void); -void HpmaShow(bool json); -bool Xsns56(uint8_t function); -void Tsl2591Init(void); -bool Tsl2591Read(void); -void Tsl2591EverySecond(void); -void Tsl2591Show(bool json); -bool Xsns57(uint8_t function); -bool Dht12Read(void); -void Dht12Detect(void); -void Dht12EverySecond(void); -void Dht12Show(bool json); -bool Xsns58(uint8_t function); -uint32_t DS1624_Idx2Addr(uint32_t idx); -int DS1624_Restart(uint8_t config, uint32_t idx); -void DS1624_HotPlugUp(uint32_t idx); -void DS1624_HotPlugDown(int idx); -bool DS1624GetTemp(float *value, int idx); -void DS1624HotPlugScan(void); -void DS1624EverySecond(void); -void DS1624Show(bool json); -bool Xsns59(uint8_t function); -void UBXcalcChecksum(char* CK, size_t msgSize); -bool UBXcompareMsgHeader(const char* msgHeader); -void UBXinitCFG(void); -void UBXTriggerTele(void); -void UBXDetect(void); -uint32_t UBXprocessGPS(); -void UBXsendHeader(void); -void UBXsendRecord(uint8_t *buf); -void UBXsendFooter(void); -void UBXsendFile(void); -void UBXSetRate(uint16_t interval); -void UBXSelectMode(uint16_t mode); -bool UBXHandlePOSLLH(); -void UBXHandleSTATUS(); -void UBXHandleTIME(); -void UBXHandleOther(void); -void UBXLoop50msec(void); -void UBXLoop(void); -void UBXShow(bool json); -bool UBXCmd(void); -bool Xsns60(uint8_t function); -bool MINRFinitBLE(uint8_t _mode); -void MINRFhopChannel(); -bool MINRFreceivePacket(void); -void MINRFswapbuf(uint8_t len); -void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr); -void MINRFreverseMAC(uint8_t _mac[]); -void MINRFchangePacketModeTo(uint8_t _mode); -void MINRFpurgeFakeSensors(void); -void MINRFhandleFloraPacket(void); -void MINRFhandleMJ_HT_V1Packet(void); -void MINRFhandleLYWSD02Packet(void); -void MINRFhandleLYWSD03Packet(void); -void MINRFhandleCGG1Packet(void); -void MINRF_EVERY_50_MSECOND(); -void MINRFShow(bool json); -bool Xsns61(uint8_t function); -void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay); -void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot); -void HM10_Reset(void); -void HM10_Discovery_Scan(void); -void HM10_Read_LYWSD03(void); -void HM10_Read_LYWSD02(void); -void HM10_Time_LYWSD02(void); -void HM10SerialInit(void); -void HM10MACStringToBytes(const char* string, uint8_t _mac[]); -void HM10ParseResponse(char *buf); -void HM10readTempHum(char *_buf); -bool HM10readBat(char *_buf); -bool HM10SerialHandleFeedback(); -void HM10_TaskEvery100ms(); -void HM10EverySecond(); -bool HM10Cmd(void); -void HM10Show(bool json); -bool Xsns62(uint8_t function); -bool AHT10Read(void); -bool AHT10Init(void); -uint8_t AHT10ReadStatus(void); -void AHT10Reset(void); -void AHT10Detect(void); -void AHT10EverySecond(void); -void AHT10Show(bool json); -bool Xsns63(uint8_t function); -void HandleMetrics(void); -bool Xsns91(uint8_t function); -bool XsnsEnabled(uint32_t sns_index); -void XsnsSensorState(void); -bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index); -bool XsnsCall(uint8_t Function); -bool I2cEnabled(uint32_t i2c_index); -void I2cDriverState(void); -#line 184 "S:/Development/Tasmota/tasmota/tasmota.ino" -void setup(void) -{ - global_state.data = 3; - - RtcRebootLoad(); - if (!RtcRebootValid()) { - RtcReboot.fast_reboot_count = 0; - } - RtcReboot.fast_reboot_count++; - RtcRebootSave(); - - Serial.begin(APP_BAUDRATE); - seriallog_level = LOG_LEVEL_INFO; - - snprintf_P(my_version, sizeof(my_version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff); - if (VERSION & 0xff) { - snprintf_P(my_version, sizeof(my_version), PSTR("%s.%d"), my_version, VERSION & 0xff); - } - - snprintf_P(my_image, sizeof(my_image), PSTR("(%s)"), CODE_IMAGE_STR); - - SettingsLoad(); - SettingsDelta(); - - OsWatchInit(); - - GetFeatures(); - - if (1 == RtcReboot.fast_reboot_count) { - UpdateQuickPowerCycle(true); - XdrvCall(FUNC_SETTINGS_OVERRIDE); - } - - - seriallog_level = Settings.seriallog_level; - seriallog_timer = SERIALLOG_TIMER; - syslog_level = Settings.syslog_level; - stop_flash_rotate = Settings.flag.stop_flash_rotate; - save_data_counter = Settings.save_data; - sleep = Settings.sleep; -#ifndef USE_EMULATION - Settings.flag2.emulation = 0; -#else -#ifndef USE_EMULATION_WEMO - if (EMUL_WEMO == Settings.flag2.emulation) { Settings.flag2.emulation = 0; } -#endif -#ifndef USE_EMULATION_HUE - if (EMUL_HUE == Settings.flag2.emulation) { Settings.flag2.emulation = 0; } -#endif -#endif - - if (Settings.param[P_BOOT_LOOP_OFFSET]) { - - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET]) { - Settings.flag3.user_esp8285_enable = 0; - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +1) { - for (uint32_t i = 0; i < MAX_RULE_SETS; i++) { - if (bitRead(Settings.rule_stop, i)) { - bitWrite(Settings.rule_enabled, i, 0); - } - } - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +2) { - Settings.rule_enabled = 0; - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } - Settings.my_adc0 = ADC0_NONE; - } - if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { - Settings.module = SONOFF_BASIC; - - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); - } - } - - Format(mqtt_client, SettingsText(SET_MQTT_CLIENT), sizeof(mqtt_client)); - Format(mqtt_topic, SettingsText(SET_MQTT_TOPIC), sizeof(mqtt_topic)); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME), mqtt_topic, ESP.getChipId() & 0x1FFF); - } else { - snprintf_P(my_hostname, sizeof(my_hostname)-1, SettingsText(SET_HOSTNAME)); - } - - GetEspHardwareType(); - GpioInit(); - - - - WifiConnect(); - - SetPowerOnState(); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE), PROJECT, SettingsText(SET_FRIENDLYNAME1), my_version, my_image); -#ifdef FIRMWARE_MINIMAL - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_WARNING_MINIMAL_VERSION)); -#endif - - memcpy_P(log_data, VERSION_MARKER, 1); - - RtcInit(); - -#ifdef USE_ARDUINO_OTA - ArduinoOTAInit(); -#endif - - XdrvCall(FUNC_INIT); - XsnsCall(FUNC_INIT); -} - -void BacklogLoop(void) -{ - if (TimeReached(backlog_delay)) { - if (!BACKLOG_EMPTY && !backlog_mutex) { -#ifdef SUPPORT_IF_STATEMENT - backlog_mutex = true; - String cmd = backlog.shift(); - backlog_mutex = false; - ExecuteCommand((char*)cmd.c_str(), SRC_BACKLOG); -#else - backlog_mutex = true; - ExecuteCommand((char*)backlog[backlog_pointer].c_str(), SRC_BACKLOG); - backlog_pointer++; - if (backlog_pointer >= MAX_BACKLOG) { backlog_pointer = 0; } - backlog_mutex = false; -#endif - } - } -} - -void loop(void) -{ - uint32_t my_sleep = millis(); - - XdrvCall(FUNC_LOOP); - XsnsCall(FUNC_LOOP); - - OsWatchLoop(); - - ButtonLoop(); - SwitchLoop(); -#ifdef ROTARY_V1 - RotaryLoop(); -#endif -#ifdef USE_DEVICE_GROUPS - DeviceGroupsLoop(); -#endif - BacklogLoop(); - - if (TimeReached(state_50msecond)) { - SetNextTimeInterval(state_50msecond, 50); - XdrvCall(FUNC_EVERY_50_MSECOND); - XsnsCall(FUNC_EVERY_50_MSECOND); - } - if (TimeReached(state_100msecond)) { - SetNextTimeInterval(state_100msecond, 100); - Every100mSeconds(); - XdrvCall(FUNC_EVERY_100_MSECOND); - XsnsCall(FUNC_EVERY_100_MSECOND); - } - if (TimeReached(state_250msecond)) { - SetNextTimeInterval(state_250msecond, 250); - Every250mSeconds(); - XdrvCall(FUNC_EVERY_250_MSECOND); - XsnsCall(FUNC_EVERY_250_MSECOND); - } - if (TimeReached(state_second)) { - SetNextTimeInterval(state_second, 1000); - PerformEverySecond(); - XdrvCall(FUNC_EVERY_SECOND); - XsnsCall(FUNC_EVERY_SECOND); - } - - if (!serial_local) { SerialInput(); } - -#ifdef USE_ARDUINO_OTA - ArduinoOtaLoop(); -#endif - - uint32_t my_activity = millis() - my_sleep; - - if (Settings.flag3.sleep_normal) { - - delay(sleep); - } else { - if (my_activity < (uint32_t)sleep) { - delay((uint32_t)sleep - my_activity); - } else { - if (global_state.wifi_down) { - delay(my_activity /2); - } - } - } - - if (!my_activity) { my_activity++; } - uint32_t loop_delay = sleep; - if (!loop_delay) { loop_delay++; } - uint32_t loops_per_second = 1000 / loop_delay; - uint32_t this_cycle_ratio = 100 * my_activity / loop_delay; - loop_load_avg = loop_load_avg - (loop_load_avg / loops_per_second) + (this_cycle_ratio / loops_per_second); -} -# 1 "S:/Development/Tasmota/tasmota/sendemail.ino" -#ifdef USE_SENDMAIL - -#include "sendemail.h" -# 25 "S:/Development/Tasmota/tasmota/sendemail.ino" -#ifndef SEND_MAIL_MINRAM -#define SEND_MAIL_MINRAM 12*1024 -#endif - -#define xPSTR(a) a - -uint16_t SendMail(char *buffer) { - char *params,*oparams; - const char *mserv; - uint16_t port; - const char *user; - const char *pstr; - const char *passwd; - const char *from; - const char *to; - const char *subject; - const char *cmd; - char auth=0; - uint16_t status=1; - SendEmail *mail=0; - uint16_t blen; - char *endcmd; - - - - uint16_t mem=ESP.getFreeHeap(); - if (memsend(from,to,subject,cmd); - delete mail; - if (result==true) status=0; - } - -exit: - if (oparams) free(oparams); - return status; -} - -void script_send_email_body(BearSSL::WiFiClientSecure_light *client); - - -SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) : - host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new BearSSL::WiFiClientSecure_light(1024,1024)) { -} - -String SendEmail::readClient() { - delay(0); - String r = client->readStringUntil('\n'); - - r.trim(); - while (client->available()) { - delay(0); - r += client->readString(); - } - return r; -} - -bool SendEmail::send(const String& from, const String& to, const String& subject, const char *msg) { -bool status=false; -String buffer; - - if (!host.length()) { - return status; - } - - client->setTimeout(timeout); - -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("Connecting: %s on port %d"),host.c_str(),port); -#endif - - if (!client->connect(host.c_str(), port)) { -#ifdef DEBUG_EMAIL_PORT - AddLog_P(LOG_LEVEL_INFO, PSTR("Connection failed")); -#endif - goto exit; - } - - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("220"))) { - goto exit; - } - - buffer = F("EHLO "); - buffer += client->localIP().toString(); - - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("250"))) { - goto exit; - } - if (user.length()>0 && passwd.length()>0 ) { - - buffer = F("AUTH LOGIN"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("334"))) - { - goto exit; - } - base64 b; - buffer = b.encode(user); - - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("334"))) { - goto exit; - } - buffer = b.encode(passwd); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("235"))) { - goto exit; - } - } - - - buffer = F("MAIL FROM:"); - buffer += from; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("250"))) { - goto exit; - } - buffer = F("RCPT TO:"); - buffer += to; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("250"))) { - goto exit; - } - - buffer = F("DATA"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = readClient(); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - if (!buffer.startsWith(F("354"))) { - goto exit; - } - buffer = F("From: "); - buffer += from; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = F("To: "); - buffer += to; - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - buffer = F("Subject: "); - buffer += subject; - buffer += F("\r\n"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - -#ifdef USE_SCRIPT - if (*msg=='*' && *(msg+1)==0) { - script_send_email_body(client); - } else { - client->println(msg); - } -#else - client->println(msg); -#endif - client->println('.'); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - - buffer = F("QUIT"); - client->println(buffer); -#ifdef DEBUG_EMAIL_PORT - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),buffer.c_str()); -#endif - - status=true; -exit: - - return status; -} - - -#endif -# 1 "S:/Development/Tasmota/tasmota/settings.ino" -# 20 "S:/Development/Tasmota/tasmota/settings.ino" -#ifndef DOMOTICZ_UPDATE_TIMER -#define DOMOTICZ_UPDATE_TIMER 0 -#endif - -#ifndef EMULATION -#define EMULATION EMUL_NONE -#endif - -#ifndef MTX_ADDRESS1 -#define MTX_ADDRESS1 0 -#endif -#ifndef MTX_ADDRESS2 -#define MTX_ADDRESS2 0 -#endif -#ifndef MTX_ADDRESS3 -#define MTX_ADDRESS3 0 -#endif -#ifndef MTX_ADDRESS4 -#define MTX_ADDRESS4 0 -#endif -#ifndef MTX_ADDRESS5 -#define MTX_ADDRESS5 0 -#endif -#ifndef MTX_ADDRESS6 -#define MTX_ADDRESS6 0 -#endif -#ifndef MTX_ADDRESS7 -#define MTX_ADDRESS7 0 -#endif -#ifndef MTX_ADDRESS8 -#define MTX_ADDRESS8 0 -#endif - -#ifndef HOME_ASSISTANT_DISCOVERY_ENABLE -#define HOME_ASSISTANT_DISCOVERY_ENABLE 0 -#endif - -#ifndef LATITUDE -#define LATITUDE 48.858360 -#endif -#ifndef LONGITUDE -#define LONGITUDE 2.294442 -#endif - -#ifndef WORKING_PERIOD -#define WORKING_PERIOD 5 -#endif - -#ifndef COLOR_TEXT -#define COLOR_TEXT "#000" -#endif -#ifndef COLOR_BACKGROUND -#define COLOR_BACKGROUND "#fff" -#endif -#ifndef COLOR_FORM -#define COLOR_FORM "#f2f2f2" -#endif -#ifndef COLOR_INPUT_TEXT -#define COLOR_INPUT_TEXT "#000" -#endif -#ifndef COLOR_INPUT -#define COLOR_INPUT "#fff" -#endif -#ifndef COLOR_CONSOLE_TEXT -#define COLOR_CONSOLE_TEXT "#000" -#endif -#ifndef COLOR_CONSOLE -#define COLOR_CONSOLE "#fff" -#endif -#ifndef COLOR_TEXT_WARNING -#define COLOR_TEXT_WARNING "#f00" -#endif -#ifndef COLOR_TEXT_SUCCESS -#define COLOR_TEXT_SUCCESS "#008000" -#endif -#ifndef COLOR_BUTTON_TEXT -#define COLOR_BUTTON_TEXT "#fff" -#endif -#ifndef COLOR_BUTTON -#define COLOR_BUTTON "#1fa3ec" -#endif -#ifndef COLOR_BUTTON_HOVER -#define COLOR_BUTTON_HOVER "#0e70a4" -#endif -#ifndef COLOR_BUTTON_RESET -#define COLOR_BUTTON_RESET "#d43535" -#endif -#ifndef COLOR_BUTTON_RESET_HOVER -#define COLOR_BUTTON_RESET_HOVER "#931f1f" -#endif -#ifndef COLOR_BUTTON_SAVE -#define COLOR_BUTTON_SAVE "#47c266" -#endif -#ifndef COLOR_BUTTON_SAVE_HOVER -#define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" -#endif -#ifndef COLOR_TIMER_TAB_TEXT -#define COLOR_TIMER_TAB_TEXT "#fff" -#endif -#ifndef COLOR_TIMER_TAB_BACKGROUND -#define COLOR_TIMER_TAB_BACKGROUND "#999" -#endif -#ifndef COLOR_TITLE_TEXT -#define COLOR_TITLE_TEXT COLOR_TEXT -#endif -#ifndef IR_RCV_MIN_UNKNOWN_SIZE -#define IR_RCV_MIN_UNKNOWN_SIZE 6 -#endif -#ifndef ENERGY_OVERTEMP -#define ENERGY_OVERTEMP 90 -#endif -#ifndef DEFAULT_DIMMER_MAX -#define DEFAULT_DIMMER_MAX 100 -#endif -#ifndef DEFAULT_DIMMER_MIN -#define DEFAULT_DIMMER_MIN 0 -#endif -#ifndef DEFAULT_LIGHT_DIMMER -#define DEFAULT_LIGHT_DIMMER 10 -#endif -#ifndef DEFAULT_LIGHT_COMPONENT -#define DEFAULT_LIGHT_COMPONENT 255 -#endif -#ifndef CORS_ENABLED_ALL -#define CORS_ENABLED_ALL "*" -#endif - - -enum WebColors { - COL_TEXT, COL_BACKGROUND, COL_FORM, - COL_INPUT_TEXT, COL_INPUT, COL_CONSOLE_TEXT, COL_CONSOLE, - COL_TEXT_WARNING, COL_TEXT_SUCCESS, - COL_BUTTON_TEXT, COL_BUTTON, COL_BUTTON_HOVER, COL_BUTTON_RESET, COL_BUTTON_RESET_HOVER, COL_BUTTON_SAVE, COL_BUTTON_SAVE_HOVER, - COL_TIMER_TAB_TEXT, COL_TIMER_TAB_BACKGROUND, COL_TITLE, - COL_LAST }; - -const char kWebColors[] PROGMEM = - COLOR_TEXT "|" COLOR_BACKGROUND "|" COLOR_FORM "|" - COLOR_INPUT_TEXT "|" COLOR_INPUT "|" COLOR_CONSOLE_TEXT "|" COLOR_CONSOLE "|" - COLOR_TEXT_WARNING "|" COLOR_TEXT_SUCCESS "|" - COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|" - COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT; - -enum TasmotaSerialConfig { - TS_SERIAL_5N1, TS_SERIAL_6N1, TS_SERIAL_7N1, TS_SERIAL_8N1, - TS_SERIAL_5N2, TS_SERIAL_6N2, TS_SERIAL_7N2, TS_SERIAL_8N2, - TS_SERIAL_5E1, TS_SERIAL_6E1, TS_SERIAL_7E1, TS_SERIAL_8E1, - TS_SERIAL_5E2, TS_SERIAL_6E2, TS_SERIAL_7E2, TS_SERIAL_8E2, - TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1, - TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 }; - -const uint8_t kTasmotaSerialConfig[] PROGMEM = { - SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1, - SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2, - SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1, - SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2, - SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1, - SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2 -}; - - - - - -const uint16_t RTC_MEM_VALID = 0xA55A; - -uint32_t rtc_settings_crc = 0; - -uint32_t GetRtcSettingsCrc(void) -{ - uint32_t crc = 0; - uint8_t *bytes = (uint8_t*)&RtcSettings; - - for (uint32_t i = 0; i < sizeof(RTCMEM); i++) { - crc += bytes[i]*(i+1); - } - return crc; -} - -void RtcSettingsSave(void) -{ - if (GetRtcSettingsCrc() != rtc_settings_crc) { - RtcSettings.valid = RTC_MEM_VALID; - ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); - rtc_settings_crc = GetRtcSettingsCrc(); - } -} - -void RtcSettingsLoad(void) -{ - ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); - if (RtcSettings.valid != RTC_MEM_VALID) { - memset(&RtcSettings, 0, sizeof(RTCMEM)); - RtcSettings.valid = RTC_MEM_VALID; - RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; - RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; - RtcSettings.energy_usage = Settings.energy_usage; - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; - } - RtcSettings.power = Settings.power; - RtcSettingsSave(); - } - rtc_settings_crc = GetRtcSettingsCrc(); -} - -bool RtcSettingsValid(void) -{ - return (RTC_MEM_VALID == RtcSettings.valid); -} - - - -uint32_t rtc_reboot_crc = 0; - -uint32_t GetRtcRebootCrc(void) -{ - uint32_t crc = 0; - uint8_t *bytes = (uint8_t*)&RtcReboot; - - for (uint32_t i = 0; i < sizeof(RTCRBT); i++) { - crc += bytes[i]*(i+1); - } - return crc; -} - -void RtcRebootSave(void) -{ - if (GetRtcRebootCrc() != rtc_reboot_crc) { - RtcReboot.valid = RTC_MEM_VALID; - ESP.rtcUserMemoryWrite(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); - rtc_reboot_crc = GetRtcRebootCrc(); - } -} - -void RtcRebootReset(void) -{ - RtcReboot.fast_reboot_count = 0; - RtcRebootSave(); -} - -void RtcRebootLoad(void) -{ - ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); - if (RtcReboot.valid != RTC_MEM_VALID) { - memset(&RtcReboot, 0, sizeof(RTCRBT)); - RtcReboot.valid = RTC_MEM_VALID; - - RtcRebootSave(); - } - rtc_reboot_crc = GetRtcRebootCrc(); -} - -bool RtcRebootValid(void) -{ - return (RTC_MEM_VALID == RtcReboot.valid); -} -# 299 "S:/Development/Tasmota/tasmota/settings.ino" -extern "C" { -#include "spi_flash.h" -} -#include "eboot_command.h" - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) - -extern "C" uint32_t _SPIFFS_end; - -const uint32_t SPIFFS_END = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; - -#else - -#if AUTOFLASHSIZE - -#include "flash_hal.h" - - -const uint32_t SPIFFS_END = (FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; - -#else - -extern "C" uint32_t _FS_end; - -const uint32_t SPIFFS_END = ((uint32_t)&_FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; - -#endif - -#endif - - -const uint32_t SETTINGS_LOCATION = SPIFFS_END; - -const uint8_t CFG_ROTATES = 8; - -uint32_t settings_location = SETTINGS_LOCATION; -uint32_t settings_crc32 = 0; -uint8_t *settings_buffer = nullptr; - - - - - -void SetFlashModeDout(void) -{ - uint8_t *_buffer; - uint32_t address; - - eboot_command ebcmd; - eboot_command_read(&ebcmd); - address = ebcmd.args[0]; - _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - - if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { - if (_buffer[2] != 3) { - _buffer[2] = 3; - if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { - ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); - } - } - } - delete[] _buffer; -} - -bool VersionCompatible(void) -{ - if (Settings.flag3.compatibility_check) { - return true; - } - - eboot_command ebcmd; - eboot_command_read(&ebcmd); - uint32_t start_address = ebcmd.args[0]; - uint32_t end_address = start_address + (ebcmd.args[2] & 0xFFFFF000) + FLASH_SECTOR_SIZE; - uint32_t* buffer = new uint32_t[FLASH_SECTOR_SIZE / 4]; - - uint32_t version[3] = { 0 }; - bool found = false; - for (uint32_t address = start_address; address < end_address; address = address + FLASH_SECTOR_SIZE) { - ESP.flashRead(address, (uint32_t*)buffer, FLASH_SECTOR_SIZE); - if ((address == start_address) && (0x1F == (buffer[0] & 0xFF))) { - version[1] = 0xFFFFFFFF; - found = true; - } else { - for (uint32_t i = 0; i < (FLASH_SECTOR_SIZE / 4); i++) { - version[0] = version[1]; - version[1] = version[2]; - version[2] = buffer[i]; - if ((MARKER_START == version[0]) && (MARKER_END == version[2])) { - found = true; - break; - } - } - } - if (found) { break; } - } - delete[] buffer; - - if (!found) { version[1] = 0; } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: Version 0x%08X, Compatible 0x%08X"), version[1], VERSION_COMPATIBLE); - - if (version[1] < VERSION_COMPATIBLE) { - uint32_t eboot_magic = 0; - ESP.rtcUserMemoryWrite(0, (uint32_t*)&eboot_magic, sizeof(eboot_magic)); - return false; - } - - return true; -} - -void SettingsBufferFree(void) -{ - if (settings_buffer != nullptr) { - free(settings_buffer); - settings_buffer = nullptr; - } -} - -bool SettingsBufferAlloc(void) -{ - SettingsBufferFree(); - if (!(settings_buffer = (uint8_t *)malloc(sizeof(Settings)))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_UPLOAD_ERR_2)); - return false; - } - return true; -} - -uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size) -{ - uint16_t crc = 0; - - for (uint32_t i = 0; i < size; i++) { - if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } - } - return crc; -} - -uint16_t GetSettingsCrc(void) -{ - - uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG); - return GetCfgCrc16((uint8_t*)&Settings, size); -} - -uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size) -{ - - uint32_t crc = 0; - - while (size--) { - crc ^= *bytes++; - for (uint32_t j = 0; j < 8; j++) { - crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); - } - } - return ~crc; -} - -uint32_t GetSettingsCrc32(void) -{ - return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); -} - -void SettingsSaveAll(void) -{ - if (Settings.flag.save_state) { - Settings.power = power; - } else { - Settings.power = 0; - } - XsnsCall(FUNC_SAVE_BEFORE_RESTART); - XdrvCall(FUNC_SAVE_BEFORE_RESTART); - SettingsSave(0); -} - - - - - -void UpdateQuickPowerCycle(bool update) -{ - if (Settings.flag3.fast_power_cycle_disable) { return; } - - uint32_t pc_register; - uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES; - - ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); - if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) { - uint32_t counter = ((pc_register & 0xF) << 1) & 0xF; - if (0 == counter) { - SettingsErase(3); - EspRestart(); - } else { - pc_register = 0xFFA55AB0 | counter; - ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter); - } - } - else if (pc_register != 0xFFA55ABF) { - pc_register = 0xFFA55ABF; - - if (ESP.flashEraseSector(pc_location)) { - ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset")); - } -} - - - - - -uint32_t GetSettingsTextLen(void) -{ - char* position = Settings.text_pool; - for (uint32_t size = 0; size < SET_MAX; size++) { - while (*position++ != '\0') { } - } - return position - Settings.text_pool; -} - -bool SettingsUpdateText(uint32_t index, const char* replace_me) -{ - if (index >= SET_MAX) { - return false; - } - - - uint32_t replace_len = strlen(replace_me); - char replace[replace_len +1]; - memcpy(replace, replace_me, sizeof(replace)); - - uint32_t start_pos = 0; - uint32_t end_pos = 0; - char* position = Settings.text_pool; - for (uint32_t size = 0; size < SET_MAX; size++) { - while (*position++ != '\0') { } - if (1 == index) { - start_pos = position - Settings.text_pool; - } - else if (0 == index) { - end_pos = position - Settings.text_pool -1; - } - index--; - } - uint32_t char_len = position - Settings.text_pool; - - uint32_t current_len = end_pos - start_pos; - int diff = replace_len - current_len; - - - - - int too_long = (char_len + diff) - settings_text_size; - if (too_long > 0) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_CONFIG "Text overflow by %d char(s)"), too_long); - return false; - } - - if (diff != 0) { - - memmove_P(Settings.text_pool + start_pos + replace_len, Settings.text_pool + end_pos, char_len - end_pos); - } - - memmove_P(Settings.text_pool + start_pos, replace, replace_len); - - memset(Settings.text_pool + char_len + diff, 0x00, settings_text_size - char_len - diff); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "CR %d/%d"), GetSettingsTextLen(), settings_text_size); - - return true; -} - -char* SettingsText(uint32_t index) -{ - char* position = Settings.text_pool; - - if (index >= SET_MAX) { - position += settings_text_size -1; - } else { - for (;index > 0; index--) { - while (*position++ != '\0') { } - } - } - return position; -} - - - - - -uint32_t GetSettingsAddress(void) -{ - return settings_location * SPI_FLASH_SEC_SIZE; -} - -void SettingsSave(uint8_t rotate) -{ -# 607 "S:/Development/Tasmota/tasmota/settings.ino" -#ifndef FIRMWARE_MINIMAL - if ((GetSettingsCrc32() != settings_crc32) || rotate) { - if (1 == rotate) { - stop_flash_rotate = 1; - } - if (2 == rotate) { - settings_location = SETTINGS_LOCATION +1; - } - if (stop_flash_rotate) { - settings_location = SETTINGS_LOCATION; - } else { - settings_location--; - if (settings_location <= (SETTINGS_LOCATION - CFG_ROTATES)) { - settings_location = SETTINGS_LOCATION; - } - } - - Settings.save_flag++; - if (UtcTime() > START_VALID_TIME) { - Settings.cfg_timestamp = UtcTime(); - } else { - Settings.cfg_timestamp++; - } - Settings.cfg_size = sizeof(SYSCFG); - Settings.cfg_crc = GetSettingsCrc(); - Settings.cfg_crc32 = GetSettingsCrc32(); - - if (ESP.flashEraseSector(settings_location)) { - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - } - - if (!stop_flash_rotate && rotate) { - for (uint32_t i = 1; i < CFG_ROTATES; i++) { - ESP.flashEraseSector(settings_location -i); - delay(1); - } - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); - - settings_crc32 = Settings.cfg_crc32; - } -#endif - RtcSettingsSave(); -} - -void SettingsLoad(void) -{ - - struct SYSCFGH { - uint16_t cfg_holder; - uint16_t cfg_size; - unsigned long save_flag; - } _SettingsH; - unsigned long save_flag = 0; - - settings_location = 0; - uint32_t flash_location = SETTINGS_LOCATION +1; - uint16_t cfg_holder = 0; - for (uint32_t i = 0; i < CFG_ROTATES; i++) { - flash_location--; - ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - - bool valid = false; - if (Settings.version > 0x06000000) { - bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32()); - if (Settings.version < 0x0606000B) { - almost_valid = (Settings.cfg_crc == GetSettingsCrc()); - } - - if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } - valid = (cfg_holder == Settings.cfg_holder); - } else { - ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); - valid = (Settings.cfg_holder == _SettingsH.cfg_holder); - } - if (valid) { - if (Settings.save_flag > save_flag) { - save_flag = Settings.save_flag; - settings_location = flash_location; - if (Settings.flag.stop_flash_rotate && (0 == i)) { - break; - } - } - } - - delay(1); - } - if (settings_location > 0) { - ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); - } - -#ifndef FIRMWARE_MINIMAL - if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { - SettingsDefault(); - } - settings_crc32 = GetSettingsCrc32(); -#endif - - RtcSettingsLoad(); -} - -void EspErase(uint32_t start_sector, uint32_t end_sector) -{ - bool serial_output = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); - for (uint32_t sector = start_sector; sector < end_sector; sector++) { - - bool result = ESP.flashEraseSector(sector); - - - - if (serial_output) { -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - Serial.printf(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n", sector, (result) ? D_OK : D_ERROR); -#else - Serial.printf_P(PSTR(D_LOG_APPLICATION D_ERASED_SECTOR " %d %s\n"), sector, (result) ? D_OK : D_ERROR); -#endif - delay(10); - } else { - yield(); - } - OsWatchLoop(); - } -} - -void SettingsErase(uint8_t type) -{ -# 750 "S:/Development/Tasmota/tasmota/settings.ino" -#ifndef FIRMWARE_MINIMAL - uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; - uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; - if (1 == type) { - - _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; - } - else if (2 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; - _sectorEnd = SETTINGS_LOCATION +1; - } - else if (3 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; - _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; - } -#ifdef USE_WIFI_SDK_ERASE - else if (4 == type) { - _sectorStart = SETTINGS_LOCATION +1; - _sectorEnd = _sectorStart +1; - } - else if (5 == type) { - _sectorStart = (ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE) -4; - _sectorEnd = _sectorStart +1; - } -#endif - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); - - - EsptoolErase(_sectorStart, _sectorEnd); -#endif -} - -void SettingsSdkErase(void) -{ - WiFi.disconnect(false); - SettingsErase(1); - delay(1000); -} - -#ifdef USE_WIFI_SDK_ERASE -void SettingsSdkWifiErase(void) -{ - WiFi.disconnect(false); - SettingsErase(4); - SettingsErase(5); - delay(200); -} -#endif - - - -void SettingsDefault(void) -{ - AddLog_P(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_USE_DEFAULTS)); - SettingsDefaultSet1(); - SettingsDefaultSet2(); - SettingsSave(2); -} - -void SettingsDefaultSet1(void) -{ - memset(&Settings, 0x00, sizeof(SYSCFG)); - - Settings.cfg_holder = (uint16_t)CFG_HOLDER; - Settings.cfg_size = sizeof(SYSCFG); - - Settings.version = VERSION; - - -} - -void SettingsDefaultSet2(void) -{ - memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); - - Settings.flag.stop_flash_rotate = APP_FLASH_CYCLE; - Settings.flag.global_state = APP_ENABLE_LEDLINK; - Settings.flag3.sleep_normal = APP_NORMAL_SLEEP; - Settings.flag3.no_power_feedback = APP_NO_RELAY_SCAN; - Settings.flag3.fast_power_cycle_disable = APP_DISABLE_POWERCYCLE; - Settings.flag3.bootcount_update = DEEPSLEEP_BOOTCOUNT; - Settings.flag3.compatibility_check = OTA_COMPATIBILITY; - Settings.save_data = SAVE_DATA; - Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; - Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; - Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; - Settings.sleep = APP_SLEEP; - if (Settings.sleep < 50) { - Settings.sleep = 50; - } - - - - Settings.interlock[0] = 0xFF; - Settings.module = MODULE; - ModuleDefault(WEMOS); - - SettingsUpdateText(SET_FRIENDLYNAME1, FRIENDLY_NAME); - SettingsUpdateText(SET_FRIENDLYNAME2, FRIENDLY_NAME"2"); - SettingsUpdateText(SET_FRIENDLYNAME3, FRIENDLY_NAME"3"); - SettingsUpdateText(SET_FRIENDLYNAME4, FRIENDLY_NAME"4"); - SettingsUpdateText(SET_OTAURL, OTA_URL); - - - Settings.flag.save_state = SAVE_STATE; - Settings.power = APP_POWER; - Settings.poweronstate = APP_POWERON_STATE; - Settings.blinktime = APP_BLINKTIME; - Settings.blinkcount = APP_BLINKCOUNT; - Settings.ledstate = APP_LEDSTATE; - Settings.ledmask = APP_LEDMASK; - Settings.pulse_timer[0] = APP_PULSETIME; - - - - Settings.serial_config = TS_SERIAL_8N1; - Settings.baudrate = APP_BAUDRATE / 300; - Settings.sbaudrate = SOFT_BAUDRATE / 300; - Settings.serial_delimiter = 0xff; - Settings.seriallog_level = SERIAL_LOG_LEVEL; - - - Settings.flag3.use_wifi_scan = WIFI_SCAN_AT_RESTART; - Settings.flag3.use_wifi_rescan = WIFI_SCAN_REGULARLY; - Settings.wifi_output_power = 170; - ParseIp(&Settings.ip_address[0], WIFI_IP_ADDRESS); - ParseIp(&Settings.ip_address[1], WIFI_GATEWAY); - ParseIp(&Settings.ip_address[2], WIFI_SUBNETMASK); - ParseIp(&Settings.ip_address[3], WIFI_DNS); - Settings.sta_config = WIFI_CONFIG_TOOL; - - SettingsUpdateText(SET_STASSID1, STA_SSID1); - SettingsUpdateText(SET_STASSID2, STA_SSID2); - SettingsUpdateText(SET_STAPWD1, STA_PASS1); - SettingsUpdateText(SET_STAPWD2, STA_PASS2); - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - - - SettingsUpdateText(SET_SYSLOG_HOST, SYS_LOG_HOST); - Settings.syslog_port = SYS_LOG_PORT; - Settings.syslog_level = SYS_LOG_LEVEL; - - - Settings.flag2.emulation = EMULATION; - Settings.flag3.gui_hostname_ip = GUI_SHOW_HOSTNAME; - Settings.flag3.mdns_enabled = MDNS_ENABLED; - Settings.webserver = WEB_SERVER; - Settings.weblog_level = WEB_LOG_LEVEL; - SettingsUpdateText(SET_WEBPWD, WEB_PASSWORD); - SettingsUpdateText(SET_CORS, CORS_DOMAIN); - - - Settings.flag.button_restrict = KEY_DISABLE_MULTIPRESS; - Settings.flag.button_swap = KEY_SWAP_DOUBLE_PRESS; - Settings.flag.button_single = KEY_ONLY_SINGLE_PRESS; - Settings.param[P_HOLD_TIME] = KEY_HOLD_TIME; - - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { Settings.switchmode[i] = SWITCH_MODE; } - - - Settings.flag.mqtt_enabled = MQTT_USE; - Settings.flag.mqtt_response = MQTT_RESULT_COMMAND; - Settings.flag.mqtt_offline = MQTT_LWT_MESSAGE; - Settings.flag.mqtt_power_retain = MQTT_POWER_RETAIN; - Settings.flag.mqtt_button_retain = MQTT_BUTTON_RETAIN; - Settings.flag.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - Settings.flag.mqtt_sensor_retain = MQTT_SENSOR_RETAIN; - - Settings.flag.device_index_enable = MQTT_POWER_FORMAT; - Settings.flag3.time_append_timezone = MQTT_APPEND_TIMEZONE; - Settings.flag3.button_switch_force_local = MQTT_BUTTON_SWITCH_FORCE_LOCAL; - Settings.flag3.no_hold_retain = MQTT_NO_HOLD_RETAIN; - Settings.flag3.use_underscore = MQTT_INDEX_SEPARATOR; - Settings.flag3.grouptopic_mode = MQTT_GROUPTOPIC_FORMAT; - SettingsUpdateText(SET_MQTT_HOST, MQTT_HOST); - Settings.mqtt_port = MQTT_PORT; - SettingsUpdateText(SET_MQTT_CLIENT, MQTT_CLIENT_ID); - SettingsUpdateText(SET_MQTT_USER, MQTT_USER); - SettingsUpdateText(SET_MQTT_PWD, MQTT_PASS); - SettingsUpdateText(SET_MQTT_TOPIC, MQTT_TOPIC); - SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, MQTT_BUTTON_TOPIC); - SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, MQTT_SWITCH_TOPIC); - SettingsUpdateText(SET_MQTT_GRP_TOPIC, MQTT_GRPTOPIC); - SettingsUpdateText(SET_MQTT_FULLTOPIC, MQTT_FULLTOPIC); - Settings.mqtt_retry = MQTT_RETRY_SECS; - SettingsUpdateText(SET_MQTTPREFIX1, SUB_PREFIX); - SettingsUpdateText(SET_MQTTPREFIX2, PUB_PREFIX); - SettingsUpdateText(SET_MQTTPREFIX3, PUB_PREFIX2); - SettingsUpdateText(SET_STATE_TXT1, MQTT_STATUS_OFF); - SettingsUpdateText(SET_STATE_TXT2, MQTT_STATUS_ON); - SettingsUpdateText(SET_STATE_TXT3, MQTT_CMND_TOGGLE); - SettingsUpdateText(SET_STATE_TXT4, MQTT_CMND_HOLD); - char fingerprint[60]; - strlcpy(fingerprint, MQTT_FINGERPRINT1, sizeof(fingerprint)); - char *p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[0][i] = strtol(p, &p, 16); - } - strlcpy(fingerprint, MQTT_FINGERPRINT2, sizeof(fingerprint)); - p = fingerprint; - for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[1][i] = strtol(p, &p, 16); - } - Settings.tele_period = TELE_PERIOD; - Settings.mqttlog_level = MQTT_LOG_LEVEL; - - - Settings.flag.no_power_on_check = ENERGY_VOLTAGE_ALWAYS; - Settings.flag2.current_resolution = 3; - - - Settings.flag2.energy_resolution = ENERGY_RESOLUTION; - Settings.flag3.dds2382_model = ENERGY_DDS2382_MODE; - Settings.flag3.hardware_energy_total = ENERGY_HARDWARE_TOTALS; - Settings.param[P_MAX_POWER_RETRY] = MAX_POWER_RETRY; - - Settings.energy_power_calibration = HLW_PREF_PULSE; - Settings.energy_voltage_calibration = HLW_UREF_PULSE; - Settings.energy_current_calibration = HLW_IREF_PULSE; -# 980 "S:/Development/Tasmota/tasmota/settings.ino" - Settings.energy_max_power_limit_hold = MAX_POWER_HOLD; - Settings.energy_max_power_limit_window = MAX_POWER_WINDOW; - - Settings.energy_max_power_safe_limit_hold = SAFE_POWER_HOLD; - Settings.energy_max_power_safe_limit_window = SAFE_POWER_WINDOW; - - - - RtcSettings.energy_kWhtotal = 0; - - memset((char*)&RtcSettings.energy_usage, 0x00, sizeof(RtcSettings.energy_usage)); - Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; - - - Settings.flag.ir_receive_decimal = IR_DATA_RADIX; - Settings.flag3.receive_raw = IR_ADD_RAW_DATA; - Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; - - - Settings.flag.rf_receive_decimal = RF_DATA_RADIX; - - memcpy_P(Settings.rf_code[0], kDefaultRfCode, 9); - - - Settings.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; -# 1015 "S:/Development/Tasmota/tasmota/settings.ino" - Settings.flag.temperature_conversion = TEMP_CONVERSION; - Settings.flag.pressure_conversion = PRESSURE_CONVERSION; - Settings.flag2.pressure_resolution = PRESSURE_RESOLUTION; - Settings.flag2.humidity_resolution = HUMIDITY_RESOLUTION; - Settings.flag2.temperature_resolution = TEMP_RESOLUTION; - Settings.flag3.ds18x20_internal_pullup = DS18X20_PULL_UP; - Settings.flag3.counter_reset_on_tele = COUNTER_RESET; - - - - - - - Settings.flag2.calc_resolution = CALC_RESOLUTION; - - - Settings.flag3.timers_enable = TIMERS_ENABLED; - - - Settings.flag.hass_light = HASS_AS_LIGHT; - Settings.flag.hass_discovery = HOME_ASSISTANT_DISCOVERY_ENABLE; - Settings.flag3.hass_tele_on_power = TELE_ON_POWER; - - - Settings.flag.knx_enabled = KNX_ENABLED; - Settings.flag.knx_enable_enhancement = KNX_ENHANCED; - - - Settings.flag.pwm_control = LIGHT_MODE; - Settings.flag.ws_clock_reverse = LIGHT_CLOCK_DIRECTION; - Settings.flag.light_signal = LIGHT_PAIRS_CO2; - Settings.flag.not_power_linked = LIGHT_POWER_CONTROL; - Settings.flag.decimal_text = LIGHT_COLOR_RADIX; - Settings.flag3.pwm_multi_channels = LIGHT_CHANNEL_MODE; - Settings.flag3.slider_dimmer_stay_on = LIGHT_SLIDER_POWER; - Settings.flag4.alexa_ct_range = LIGHT_ALEXA_CT_RANGE; - - Settings.pwm_frequency = PWM_FREQ; - Settings.pwm_range = PWM_RANGE; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - Settings.light_color[i] = DEFAULT_LIGHT_COMPONENT; - - } - Settings.light_correction = 1; - Settings.light_dimmer = DEFAULT_LIGHT_DIMMER; - - Settings.light_speed = 1; - - Settings.light_width = 1; - - Settings.light_pixels = WS2812_LEDS; - - Settings.ws_width[WS_SECOND] = 1; - Settings.ws_color[WS_SECOND][WS_RED] = 255; - - Settings.ws_color[WS_SECOND][WS_BLUE] = 255; - Settings.ws_width[WS_MINUTE] = 3; - - Settings.ws_color[WS_MINUTE][WS_GREEN] = 255; - - Settings.ws_width[WS_HOUR] = 5; - Settings.ws_color[WS_HOUR][WS_RED] = 255; - - - - Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; - Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; - - - - Settings.display_mode = 1; - Settings.display_refresh = 2; - Settings.display_rows = 2; - Settings.display_cols[0] = 16; - Settings.display_cols[1] = 8; - Settings.display_dimmer = 1; - Settings.display_size = 1; - Settings.display_font = 1; - - Settings.display_address[0] = MTX_ADDRESS1; - Settings.display_address[1] = MTX_ADDRESS2; - Settings.display_address[2] = MTX_ADDRESS3; - Settings.display_address[3] = MTX_ADDRESS4; - Settings.display_address[4] = MTX_ADDRESS5; - Settings.display_address[5] = MTX_ADDRESS6; - Settings.display_address[6] = MTX_ADDRESS7; - Settings.display_address[7] = MTX_ADDRESS8; - - - if (((APP_TIMEZONE > -14) && (APP_TIMEZONE < 15)) || (99 == APP_TIMEZONE)) { - Settings.timezone = APP_TIMEZONE; - Settings.timezone_minutes = 0; - } else { - Settings.timezone = APP_TIMEZONE / 60; - Settings.timezone_minutes = abs(APP_TIMEZONE % 60); - } - SettingsUpdateText(SET_NTPSERVER1, NTP_SERVER1); - SettingsUpdateText(SET_NTPSERVER2, NTP_SERVER2); - SettingsUpdateText(SET_NTPSERVER3, NTP_SERVER3); - for (uint32_t i = 0; i < MAX_NTP_SERVERS; i++) { - SettingsUpdateText(SET_NTPSERVER1 +i, ReplaceCommaWithDot(SettingsText(SET_NTPSERVER1 +i))); - } - Settings.latitude = (int)((double)LATITUDE * 1000000); - Settings.longitude = (int)((double)LONGITUDE * 1000000); - SettingsResetStd(); - SettingsResetDst(); - - Settings.button_debounce = KEY_DEBOUNCE_TIME; - Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; - - for (uint32_t j = 0; j < 5; j++) { - Settings.rgbwwTable[j] = 255; - } - - Settings.novasds_startingoffset = STARTING_OFFSET; - - SettingsDefaultWebColor(); - - memset(&Settings.monitors, 0xFF, 20); - SettingsEnableAllI2cDrivers(); - - - Settings.flag3.tuya_apply_o20 = TUYA_SETOPTION_20; - Settings.flag3.tuya_serial_mqtt_publish = MQTT_TUYA_RECEIVED; - - Settings.flag3.buzzer_enable = BUZZER_ENABLE; - Settings.flag3.shutter_mode = SHUTTER_SUPPORT; - Settings.flag3.pcf8574_ports_inverted = PCF8574_INVERT_PORTS; - Settings.flag4.zigbee_use_names = ZIGBEE_FRIENDLY_NAMES; -} - - - -void SettingsResetStd(void) -{ - Settings.tflag[0].hemis = TIME_STD_HEMISPHERE; - Settings.tflag[0].week = TIME_STD_WEEK; - Settings.tflag[0].dow = TIME_STD_DAY; - Settings.tflag[0].month = TIME_STD_MONTH; - Settings.tflag[0].hour = TIME_STD_HOUR; - Settings.toffset[0] = TIME_STD_OFFSET; -} - -void SettingsResetDst(void) -{ - Settings.tflag[1].hemis = TIME_DST_HEMISPHERE; - Settings.tflag[1].week = TIME_DST_WEEK; - Settings.tflag[1].dow = TIME_DST_DAY; - Settings.tflag[1].month = TIME_DST_MONTH; - Settings.tflag[1].hour = TIME_DST_HOUR; - Settings.toffset[1] = TIME_DST_OFFSET; -} - -void SettingsDefaultWebColor(void) -{ - char scolor[10]; - for (uint32_t i = 0; i < COL_LAST; i++) { - WebHexCode(i, GetTextIndexed(scolor, sizeof(scolor), i, kWebColors)); - } -} - -void SettingsEnableAllI2cDrivers(void) -{ - Settings.i2c_drivers[0] = 0xFFFFFFFF; - Settings.i2c_drivers[1] = 0xFFFFFFFF; - Settings.i2c_drivers[2] = 0xFFFFFFFF; -} - - - -void SettingsDelta(void) -{ - if (Settings.version != VERSION) { - if (Settings.version < 0x06000000) { - Settings.cfg_size = sizeof(SYSCFG); - Settings.cfg_crc = GetSettingsCrc(); - } - if (Settings.version < 0x06000002) { - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if (i < 4) { - Settings.switchmode[i] = Settings.interlock[i]; - } else { - Settings.switchmode[i] = SWITCH_MODE; - } - } - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (Settings.my_gp.io[i] >= GPIO_SWT5) { - Settings.my_gp.io[i] += 4; - } - } - } - if (Settings.version < 0x06000003) { - Settings.flag.mqtt_serial_raw = 0; - Settings.flag.pressure_conversion = 0; - Settings.flag3.data = 0; - } - if (Settings.version < 0x06010103) { - Settings.flag3.timers_enable = 1; - } - if (Settings.version < 0x0601010C) { - Settings.button_debounce = KEY_DEBOUNCE_TIME; - Settings.switch_debounce = SWITCH_DEBOUNCE_TIME; - } - if (Settings.version < 0x0602010A) { - for (uint32_t j = 0; j < 5; j++) { - Settings.rgbwwTable[j] = 255; - } - } - if (Settings.version < 0x06030002) { - Settings.timezone_minutes = 0; - } - if (Settings.version < 0x06030004) { - memset(&Settings.monitors, 0xFF, 20); - } - if (Settings.version < 0x0603000E) { - Settings.flag2.calc_resolution = CALC_RESOLUTION; - } - if (Settings.version < 0x0603000F) { - if (Settings.sleep < 50) { - Settings.sleep = 50; - } - } - if (Settings.version < 0x06040105) { - Settings.flag3.mdns_enabled = MDNS_ENABLED; - Settings.param[P_MDNS_DELAYED_START] = 0; - } - if (Settings.version < 0x0604010B) { - Settings.interlock[0] = 0xFF; - for (uint32_t i = 1; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } - } - if (Settings.version < 0x0604010D) { - Settings.param[P_BOOT_LOOP_OFFSET] = BOOT_LOOP_OFFSET; - } - if (Settings.version < 0x06040110) { - ModuleDefault(WEMOS); - } - if (Settings.version < 0x06040113) { - Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; - } - if (Settings.version < 0x06050003) { - Settings.novasds_startingoffset = STARTING_OFFSET; - } - if (Settings.version < 0x06050006) { - SettingsDefaultWebColor(); - } - if (Settings.version < 0x06050007) { - Settings.ledmask = APP_LEDMASK; - } - if (Settings.version < 0x0605000A) { - Settings.my_adc0 = ADC0_NONE; - } - if (Settings.version < 0x0605000D) { - Settings.param[P_IR_UNKNOW_THRESHOLD] = IR_RCV_MIN_UNKNOWN_SIZE; - } - if (Settings.version < 0x06060001) { - Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; - } - if (Settings.version < 0x06060007) { - memset((char*)&Settings +0xE00, 0x00, sizeof(SYSCFG) -0xE00); - } - if (Settings.version < 0x06060008) { - - if (Settings.flag3.tuya_serial_mqtt_publish) { - Settings.param[P_ex_DIMMER_MAX] = 100; - } else { - Settings.param[P_ex_DIMMER_MAX] = 255; - } - } - if (Settings.version < 0x06060009) { - Settings.baudrate = APP_BAUDRATE / 300; - Settings.sbaudrate = SOFT_BAUDRATE / 300; - } - if (Settings.version < 0x0606000A) { - uint8_t tuyaindex = 0; - if (Settings.param[P_BACKLOG_DELAY] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 21; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_BACKLOG_DELAY]; - tuyaindex++; - } else if (Settings.flag3.fast_power_cycle_disable == 1) { - Settings.tuya_fnid_map[tuyaindex].fnid = 11; - Settings.tuya_fnid_map[tuyaindex].dpid = 1; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_RELAYS] > 0) { - for (uint8_t i = 0 ; i < Settings.param[P_ex_TUYA_RELAYS]; i++) { - Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; - Settings.tuya_fnid_map[tuyaindex].dpid = i + 2; - tuyaindex++; - } - } - if (Settings.param[P_ex_TUYA_POWER_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 31; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_POWER_ID]; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_VOLTAGE_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 33; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_VOLTAGE_ID]; - tuyaindex++; - } - if (Settings.param[P_ex_TUYA_CURRENT_ID] > 0) { - Settings.tuya_fnid_map[tuyaindex].fnid = 32; - Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_CURRENT_ID]; - } - } - if (Settings.version < 0x0606000C) { - memset((char*)&Settings +0x1D6, 0x00, 16); - } - if (Settings.version < 0x0606000F) { - Settings.ex_shutter_accuracy = 0; - Settings.ex_mqttlog_level = MQTT_LOG_LEVEL; - } - if (Settings.version < 0x06060011) { - Settings.param[P_BACKLOG_DELAY] = MIN_BACKLOG_DELAY; - } - if (Settings.version < 0x06060012) { - Settings.dimmer_hw_min = DEFAULT_DIMMER_MIN; - Settings.dimmer_hw_max = DEFAULT_DIMMER_MAX; - if (TUYA_DIMMER == Settings.module) { - if (Settings.flag3.ex_tuya_dimmer_min_limit) { - Settings.dimmer_hw_min = 25; - } else { - Settings.dimmer_hw_min = 1; - } - Settings.dimmer_hw_max = Settings.param[P_ex_DIMMER_MAX]; - } - else if (PS_16_DZ == Settings.module) { - Settings.dimmer_hw_min = 10; - Settings.dimmer_hw_max = Settings.param[P_ex_DIMMER_MAX]; - } - } - if (Settings.version < 0x06060014) { -# 1359 "S:/Development/Tasmota/tasmota/settings.ino" - Settings.flag3.fast_power_cycle_disable = 0; - Settings.energy_power_delta = Settings.ex_energy_power_delta; - Settings.ex_energy_power_delta = 0; - } - if (Settings.version < 0x06060015) { - if ((EX_WIFI_SMARTCONFIG == Settings.ex_sta_config) || (EX_WIFI_WPSCONFIG == Settings.ex_sta_config)) { - Settings.ex_sta_config = WIFI_MANAGER; - } - } - - if (Settings.version < 0x07000002) { - Settings.web_color2[0][0] = Settings.web_color[0][0]; - Settings.web_color2[0][1] = Settings.web_color[0][1]; - Settings.web_color2[0][2] = Settings.web_color[0][2]; - } - if (Settings.version < 0x07000003) { - SettingsEnableAllI2cDrivers(); - } - if (Settings.version < 0x07000004) { - Settings.ex_wifi_output_power = 170; - } - if (Settings.version < 0x07010202) { - Settings.ex_serial_config = TS_SERIAL_8N1; - } - if (Settings.version < 0x07010204) { - if (Settings.flag3.ex_cors_enabled == 1) { - strlcpy(Settings.ex_cors_domain, CORS_ENABLED_ALL, sizeof(Settings.ex_cors_domain)); - } else { - Settings.ex_cors_domain[0] = 0; - } - } - if (Settings.version < 0x07010205) { - Settings.seriallog_level = Settings.ex_seriallog_level; - Settings.sta_config = Settings.ex_sta_config; - Settings.sta_active = Settings.ex_sta_active; - memcpy((char*)&Settings.rule_stop, (char*)&Settings.ex_rule_stop, 47); - } - if (Settings.version < 0x07010206) { - Settings.flag4 = Settings.ex_flag4; - Settings.mqtt_port = Settings.ex_mqtt_port; - memcpy((char*)&Settings.serial_config, (char*)&Settings.ex_serial_config, 5); - } - - if (Settings.version < 0x08000000) { - char temp[strlen(Settings.text_pool) +1]; strncpy(temp, Settings.text_pool, sizeof(temp)); - char temp21[strlen(Settings.ex_mqtt_prefix[0]) +1]; strncpy(temp21, Settings.ex_mqtt_prefix[0], sizeof(temp21)); - char temp22[strlen(Settings.ex_mqtt_prefix[1]) +1]; strncpy(temp22, Settings.ex_mqtt_prefix[1], sizeof(temp22)); - char temp23[strlen(Settings.ex_mqtt_prefix[2]) +1]; strncpy(temp23, Settings.ex_mqtt_prefix[2], sizeof(temp23)); - char temp31[strlen(Settings.ex_sta_ssid[0]) +1]; strncpy(temp31, Settings.ex_sta_ssid[0], sizeof(temp31)); - char temp32[strlen(Settings.ex_sta_ssid[1]) +1]; strncpy(temp32, Settings.ex_sta_ssid[1], sizeof(temp32)); - char temp41[strlen(Settings.ex_sta_pwd[0]) +1]; strncpy(temp41, Settings.ex_sta_pwd[0], sizeof(temp41)); - char temp42[strlen(Settings.ex_sta_pwd[1]) +1]; strncpy(temp42, Settings.ex_sta_pwd[1], sizeof(temp42)); - char temp5[strlen(Settings.ex_hostname) +1]; strncpy(temp5, Settings.ex_hostname, sizeof(temp5)); - char temp6[strlen(Settings.ex_syslog_host) +1]; strncpy(temp6, Settings.ex_syslog_host, sizeof(temp6)); - char temp7[strlen(Settings.ex_mqtt_host) +1]; strncpy(temp7, Settings.ex_mqtt_host, sizeof(temp7)); - char temp8[strlen(Settings.ex_mqtt_client) +1]; strncpy(temp8, Settings.ex_mqtt_client, sizeof(temp8)); - char temp9[strlen(Settings.ex_mqtt_user) +1]; strncpy(temp9, Settings.ex_mqtt_user, sizeof(temp9)); - char temp10[strlen(Settings.ex_mqtt_pwd) +1]; strncpy(temp10, Settings.ex_mqtt_pwd, sizeof(temp10)); - char temp11[strlen(Settings.ex_mqtt_topic) +1]; strncpy(temp11, Settings.ex_mqtt_topic, sizeof(temp11)); - char temp12[strlen(Settings.ex_button_topic) +1]; strncpy(temp12, Settings.ex_button_topic, sizeof(temp12)); - char temp13[strlen(Settings.ex_mqtt_grptopic) +1]; strncpy(temp13, Settings.ex_mqtt_grptopic, sizeof(temp13)); - - memset(Settings.text_pool, 0x00, settings_text_size); - SettingsUpdateText(SET_OTAURL, temp); - SettingsUpdateText(SET_MQTTPREFIX1, temp21); - SettingsUpdateText(SET_MQTTPREFIX2, temp22); - SettingsUpdateText(SET_MQTTPREFIX3, temp23); - SettingsUpdateText(SET_STASSID1, temp31); - SettingsUpdateText(SET_STASSID2, temp32); - SettingsUpdateText(SET_STAPWD1, temp41); - SettingsUpdateText(SET_STAPWD2, temp42); - SettingsUpdateText(SET_HOSTNAME, temp5); - SettingsUpdateText(SET_SYSLOG_HOST, temp6); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if (!strlen(Settings.ex_mqtt_user)) { - SettingsUpdateText(SET_MQTT_HOST, temp7); - SettingsUpdateText(SET_MQTT_USER, temp9); - } else { - char aws_mqtt_host[66]; - snprintf_P(aws_mqtt_host, sizeof(aws_mqtt_host), PSTR("%s%s"), temp9, temp7); - SettingsUpdateText(SET_MQTT_HOST, aws_mqtt_host); - SettingsUpdateText(SET_MQTT_USER, ""); - } -#else - SettingsUpdateText(SET_MQTT_HOST, temp7); - SettingsUpdateText(SET_MQTT_USER, temp9); -#endif - SettingsUpdateText(SET_MQTT_CLIENT, temp8); - SettingsUpdateText(SET_MQTT_PWD, temp10); - SettingsUpdateText(SET_MQTT_TOPIC, temp11); - SettingsUpdateText(SET_MQTT_BUTTON_TOPIC, temp12); - SettingsUpdateText(SET_MQTT_GRP_TOPIC, temp13); - - SettingsUpdateText(SET_WEBPWD, Settings.ex_web_password); - SettingsUpdateText(SET_CORS, Settings.ex_cors_domain); - SettingsUpdateText(SET_MQTT_FULLTOPIC, Settings.ex_mqtt_fulltopic); - SettingsUpdateText(SET_MQTT_SWITCH_TOPIC, Settings.ex_switch_topic); - SettingsUpdateText(SET_STATE_TXT1, Settings.ex_state_text[0]); - SettingsUpdateText(SET_STATE_TXT2, Settings.ex_state_text[1]); - SettingsUpdateText(SET_STATE_TXT3, Settings.ex_state_text[2]); - SettingsUpdateText(SET_STATE_TXT4, Settings.ex_state_text[3]); - SettingsUpdateText(SET_NTPSERVER1, Settings.ex_ntp_server[0]); - SettingsUpdateText(SET_NTPSERVER2, Settings.ex_ntp_server[1]); - SettingsUpdateText(SET_NTPSERVER3, Settings.ex_ntp_server[2]); - SettingsUpdateText(SET_MEM1, Settings.script_pram[0]); - SettingsUpdateText(SET_MEM2, Settings.script_pram[1]); - SettingsUpdateText(SET_MEM3, Settings.script_pram[2]); - SettingsUpdateText(SET_MEM4, Settings.script_pram[3]); - SettingsUpdateText(SET_MEM5, Settings.script_pram[4]); - SettingsUpdateText(SET_FRIENDLYNAME1, Settings.ex_friendlyname[0]); - SettingsUpdateText(SET_FRIENDLYNAME2, Settings.ex_friendlyname[1]); - SettingsUpdateText(SET_FRIENDLYNAME3, Settings.ex_friendlyname[2]); - SettingsUpdateText(SET_FRIENDLYNAME4, Settings.ex_friendlyname[3]); - } - - Settings.version = VERSION; - SettingsSave(1); - } -} -# 1 "S:/Development/Tasmota/tasmota/support.ino" -# 20 "S:/Development/Tasmota/tasmota/support.ino" -IPAddress syslog_host_addr; -uint32_t syslog_host_hash = 0; - -extern "C" { -extern struct rst_info resetInfo; -} - - - - - -#include - -Ticker tickerOSWatch; - -const uint32_t OSWATCH_RESET_TIME = 120; - -static unsigned long oswatch_last_loop_time; -uint8_t oswatch_blocked_loop = 0; - -#ifndef USE_WS2812_DMA - -#endif - -#ifdef USE_KNX -bool knx_started = false; -#endif - -void OsWatchTicker(void) -{ - uint32_t t = millis(); - uint32_t last_run = abs(t - oswatch_last_loop_time); - -#ifdef DEBUG_THEO - int32_t rssi = WiFi.RSSI(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_OSWATCH " FreeRam %d, rssi %d %% (%d dBm), last_run %d"), ESP.getFreeHeap(), WifiGetRssiAsQuality(rssi), rssi, last_run); -#endif - if (last_run >= (OSWATCH_RESET_TIME * 1000)) { - - RtcSettings.oswatch_blocked_loop = 1; - RtcSettingsSave(); - - - - - - volatile uint32_t dummy; - dummy = *((uint32_t*) 0x00000000); - } -} - -void OsWatchInit(void) -{ - oswatch_blocked_loop = RtcSettings.oswatch_blocked_loop; - RtcSettings.oswatch_blocked_loop = 0; - oswatch_last_loop_time = millis(); - tickerOSWatch.attach_ms(((OSWATCH_RESET_TIME / 3) * 1000), OsWatchTicker); -} - -void OsWatchLoop(void) -{ - oswatch_last_loop_time = millis(); - -} - -bool OsWatchBlockedLoop(void) -{ - return oswatch_blocked_loop; -} - -uint32_t ResetReason(void) -{ -# 102 "S:/Development/Tasmota/tasmota/support.ino" - return resetInfo.reason; -} - -String GetResetReason(void) -{ - if (oswatch_blocked_loop) { - char buff[32]; - strncpy_P(buff, PSTR(D_JSON_BLOCKED_LOOP), sizeof(buff)); - return String(buff); - } else { - return ESP.getResetReason(); - } -} - - - - - - -size_t strchrspn(const char *str1, int character) -{ - size_t ret = 0; - char *start = (char*)str1; - char *end = strchr(str1, character); - if (end) ret = end - start; - return ret; -} - - -char* subStr(char* dest, char* str, const char *delim, int index) -{ - char *act; - char *sub = nullptr; - char *ptr; - int i; - - - strncpy(dest, str, strlen(str)+1); - for (i = 1, act = dest; i <= index; i++, act = nullptr) { - sub = strtok_r(act, delim, &ptr); - if (sub == nullptr) break; - } - sub = Trim(sub); - return sub; -} - -float CharToFloat(const char *str) -{ - - char strbuf[24]; - - strlcpy(strbuf, str, sizeof(strbuf)); - char *pt = strbuf; - while ((*pt != '\0') && isblank(*pt)) { pt++; } - - signed char sign = 1; - if (*pt == '-') { sign = -1; } - if (*pt == '-' || *pt=='+') { pt++; } - - float left = 0; - if (*pt != '.') { - left = atoi(pt); - while (isdigit(*pt)) { pt++; } - } - - float right = 0; - if (*pt == '.') { - pt++; - right = atoi(pt); - while (isdigit(*pt)) { - pt++; - right /= 10.0f; - } - } - - float result = left + right; - if (sign < 0) { - return -result; - } - return result; -} - -int TextToInt(char *str) -{ - char *p; - uint8_t radix = 10; - if ('#' == str[0]) { - radix = 16; - str++; - } - return strtol(str, &p, radix); -} - -char* ulltoa(unsigned long long value, char *str, int radix) -{ - char digits[64]; - char *dst = str; - int i = 0; - - - - do { - int n = value % radix; - digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; - value /= radix; - } while (value != 0); - - while (i > 0) { *dst++ = digits[--i]; } - - *dst = 0; - return str; -} - - - -char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween) -{ - - - - static const char * hex = "0123456789ABCDEF"; - int between = (inbetween) ? 3 : 2; - const unsigned char * pin = in; - char * pout = out; - for (; pin < in+insz; pout += between, pin++) { - pout[0] = hex[(pgm_read_byte(pin)>>4) & 0xF]; - pout[1] = hex[ pgm_read_byte(pin) & 0xF]; - if (inbetween) { pout[2] = inbetween; } - if (pout + 3 - out > outsz) { break; } - } - pout[(inbetween && insz) ? -1 : 0] = 0; - return out; -} - -char* Uint64toHex(uint64_t value, char *str, uint16_t bits) -{ - ulltoa(value, str, 16); - - int fill = 8; - if ((bits > 3) && (bits < 65)) { - fill = bits / 4; - if (bits % 4) { fill++; } - } - int len = strlen(str); - fill -= len; - if (fill > 0) { - memmove(str + fill, str, len +1); - memset(str, '0', fill); - } - return str; -} - -char* dtostrfd(double number, unsigned char prec, char *s) -{ - if ((isnan(number)) || (isinf(number))) { - strcpy(s, "null"); - return s; - } else { - return dtostrf(number, 1, prec, s); - } -} - -char* Unescape(char* buffer, uint32_t* size) -{ - uint8_t* read = (uint8_t*)buffer; - uint8_t* write = (uint8_t*)buffer; - int32_t start_size = *size; - int32_t end_size = *size; - uint8_t che = 0; - - - - while (start_size > 0) { - uint8_t ch = *read++; - start_size--; - if (ch != '\\') { - *write++ = ch; - } else { - if (start_size > 0) { - uint8_t chi = *read++; - start_size--; - end_size--; - switch (chi) { - case '\\': che = '\\'; break; - case 'a': che = '\a'; break; - case 'b': che = '\b'; break; - case 'e': che = '\e'; break; - case 'f': che = '\f'; break; - case 'n': che = '\n'; break; - case 'r': che = '\r'; break; - case 's': che = ' '; break; - case 't': che = '\t'; break; - case 'v': che = '\v'; break; - case 'x': { - uint8_t* start = read; - che = (uint8_t)strtol((const char*)read, (char**)&read, 16); - start_size -= (uint16_t)(read - start); - end_size -= (uint16_t)(read - start); - break; - } - case '"': che = '\"'; break; - - default : { - che = chi; - *write++ = ch; - end_size++; - } - } - *write++ = che; - } - } - } - *size = end_size; - *write++ = 0; - - - return buffer; -} - -char* RemoveSpace(char* p) -{ - char* write = p; - char* read = p; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - if (!isspace(ch)) { - *write++ = ch; - } - } - - return p; -} - -char* ReplaceCommaWithDot(char* p) -{ - char* write = (char*)p; - char* read = (char*)p; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - if (ch == ',') { - ch = '.'; - } - *write++ = ch; - } - return p; -} - -char* LowerCase(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = tolower(ch); - } - return dest; -} - -char* UpperCase(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = toupper(ch); - } - return dest; -} - -char* UpperCase_P(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = pgm_read_byte(read++); - *write++ = toupper(ch); - } - return dest; -} - -char* Trim(char* p) -{ - while ((*p != '\0') && isblank(*p)) { p++; } - char* q = p + strlen(p) -1; - while ((q >= p) && isblank(*q)) { q--; } - q++; - *q = '\0'; - return p; -} - -char* RemoveAllSpaces(char* p) -{ - - char *cursor = p; - uint32_t offset = 0; - while (1) { - *cursor = *(cursor + offset); - if ((' ' == *cursor) || ('\t' == *cursor) || ('\n' == *cursor)) { - offset++; - } else { - if (0 == *cursor) { break; } - cursor++; - } - } - return p; -} - -char* NoAlNumToUnderscore(char* dest, const char* source) -{ - char* write = dest; - const char* read = source; - char ch = '.'; - - while (ch != '\0') { - ch = *read++; - *write++ = (isalnum(ch) || ('\0' == ch)) ? ch : '_'; - } - return dest; -} - -char IndexSeparator(void) -{ - - - - - - - if (Settings.flag3.use_underscore) { - return '_'; - } else { - return '-'; - } -} - -void SetShortcutDefault(void) -{ - if ('\0' != XdrvMailbox.data[0]) { - XdrvMailbox.data[0] = '0' + SC_DEFAULT; - XdrvMailbox.data[1] = '\0'; - } -} - -uint8_t Shortcut(void) -{ - uint8_t result = 10; - - if ('\0' == XdrvMailbox.data[1]) { - if (('"' == XdrvMailbox.data[0]) || ('0' == XdrvMailbox.data[0])) { - result = SC_CLEAR; - } else { - result = atoi(XdrvMailbox.data); - if (0 == result) { - result = 10; - } - } - } - return result; -} - -bool ValidIpAddress(const char* str) -{ - const char* p = str; - - while (*p && ((*p == '.') || ((*p >= '0') && (*p <= '9')))) { p++; } - return (*p == '\0'); -} - -bool ParseIp(uint32_t* addr, const char* str) -{ - uint8_t *part = (uint8_t*)addr; - uint8_t i; - - *addr = 0; - for (i = 0; i < 4; i++) { - part[i] = strtoul(str, nullptr, 10); - str = strchr(str, '.'); - if (str == nullptr || *str == '\0') { - break; - } - str++; - } - return (3 == i); -} - -uint32_t ParseParameters(uint32_t count, uint32_t *params) -{ - char *p; - uint32_t i = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p), i++) { - params[i] = strtoul(str, nullptr, 0); - } - return i; -} - - -bool NewerVersion(char* version_str) -{ - uint32_t version = 0; - uint32_t i = 0; - char *str_ptr; - - char version_dup[strlen(version_str) +1]; - strncpy(version_dup, version_str, sizeof(version_dup)); - - for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(nullptr, ".", &str_ptr), i++) { - int field = atoi(str); - - if ((field < 0) || (field > 255)) { - return false; - } - - version = (version << 8) + field; - - if ((2 == i) && isalpha(str[strlen(str)-1])) { - field = str[strlen(str)-1] & 0x1f; - version = (version << 8) + field; - i++; - } - } - - - if ((i < 2) || (i > sizeof(VERSION))) { - return false; - } - - - while (i < sizeof(VERSION)) { - version <<= 8; - i++; - } - - return (version > VERSION); -} - -char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option) -{ - strncpy_P(dest, S_RSLT_POWER, size); - if ((devices_present + option) > 1) { - char sidx[8]; - snprintf_P(sidx, sizeof(sidx), PSTR("%d"), idx); - strncat(dest, sidx, size - strlen(dest) -1); - } - return dest; -} - -char* GetPowerDevice(char* dest, uint32_t idx, size_t size) -{ - return GetPowerDevice(dest, idx, size, 0); -} - -void GetEspHardwareType(void) -{ - - uint32_t efuse1 = *(uint32_t*)(0x3FF00050); - uint32_t efuse2 = *(uint32_t*)(0x3FF00054); - - - - is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) ); - if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) { - is_8285 = false; - } -} - -String GetDeviceHardware(void) -{ - char buff[10]; - if (is_8285) { - strcpy_P(buff, PSTR("ESP8285")); - } else { - strcpy_P(buff, PSTR("ESP8266EX")); - } - return String(buff); -} - -float ConvertTemp(float c) -{ - float result = c; - - global_update = uptime; - global_temperature = c; - - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = c * 1.8 + 32; - } - result = result + (0.1 * Settings.temp_comp); - return result; -} - -float ConvertTempToCelsius(float c) -{ - float result = c; - - if (!isnan(c) && Settings.flag.temperature_conversion) { - result = (c - 32) / 1.8; - } - result = result + (0.1 * Settings.temp_comp); - return result; -} - -char TempUnit(void) -{ - return (Settings.flag.temperature_conversion) ? 'F' : 'C'; -} - -float ConvertHumidity(float h) -{ - global_update = uptime; - global_humidity = h; - - return h; -} - -float ConvertPressure(float p) -{ - float result = p; - - global_update = uptime; - global_pressure = p; - - if (!isnan(p) && Settings.flag.pressure_conversion) { - result = p * 0.75006375541921; - } - return result; -} - -String PressureUnit(void) -{ - return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); -} - -void ResetGlobalValues(void) -{ - if ((uptime - global_update) > GLOBAL_VALUES_VALID) { - global_update = 0; - global_temperature = 9999; - global_humidity = 0; - global_pressure = 0; - } -} - -uint32_t SqrtInt(uint32_t num) -{ - if (num <= 1) { - return num; - } - - uint32_t x = num / 2; - uint32_t y; - do { - y = (x + num / x) / 2; - if (y >= x) { - return x; - } - x = y; - } while (true); -} - -uint32_t RoundSqrtInt(uint32_t num) -{ - uint32_t s = SqrtInt(4 * num); - if (s & 1) { - s++; - } - return s / 2; -} - -char* GetTextIndexed(char* destination, size_t destination_size, uint32_t index, const char* haystack) -{ - - - char* write = destination; - const char* read = haystack; - - index++; - while (index--) { - size_t size = destination_size -1; - write = destination; - char ch = '.'; - while ((ch != '\0') && (ch != '|')) { - ch = pgm_read_byte(read++); - if (size && (ch != '|')) { - *write++ = ch; - size--; - } - } - if (0 == ch) { - if (index) { - write = destination; - } - break; - } - } - *write = '\0'; - return destination; -} - -int GetCommandCode(char* destination, size_t destination_size, const char* needle, const char* haystack) -{ - - - int result = -1; - const char* read = haystack; - char* write = destination; - - while (true) { - result++; - size_t size = destination_size -1; - write = destination; - char ch = '.'; - while ((ch != '\0') && (ch != '|')) { - ch = pgm_read_byte(read++); - if (size && (ch != '|')) { - *write++ = ch; - size--; - } - } - *write = '\0'; - if (!strcasecmp(needle, destination)) { - break; - } - if (0 == ch) { - result = -1; - break; - } - } - return result; -} - -bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void)) -{ - GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); - int prefix_length = strlen(XdrvMailbox.command); - if (prefix_length) { - char prefix[prefix_length +1]; - snprintf_P(prefix, sizeof(prefix), XdrvMailbox.topic); - if (strcasecmp(prefix, XdrvMailbox.command)) { - return false; - } - } - int command_code = GetCommandCode(XdrvMailbox.command + prefix_length, CMDSZ, XdrvMailbox.topic + prefix_length, haystack); - if (command_code > 0) { - XdrvMailbox.command_code = command_code -1; - MyCommand[XdrvMailbox.command_code](); - return true; - } - return false; -} - -const char kOptions[] PROGMEM = "OFF|" D_OFF "|FALSE|" D_FALSE "|STOP|" D_STOP "|" D_CELSIUS "|" - "ON|" D_ON "|TRUE|" D_TRUE "|START|" D_START "|" D_FAHRENHEIT "|" D_USER "|" - "TOGGLE|" D_TOGGLE "|" D_ADMIN "|" - "BLINK|" D_BLINK "|" - "BLINKOFF|" D_BLINKOFF "|" - "ALL" ; - -const uint8_t sNumbers[] PROGMEM = { 0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1, - 2,2,2, - 3,3, - 4,4, - 255 }; - -int GetStateNumber(char *state_text) -{ - char command[CMDSZ]; - int state_number = GetCommandCode(command, sizeof(command), state_text, kOptions); - if (state_number >= 0) { - state_number = pgm_read_byte(sNumbers + state_number); - } - return state_number; -} - -String GetSerialConfig(void) -{ - - - - - - const char kParity[] = "NEOI"; - - char config[4]; - config[0] = '5' + (Settings.serial_config & 0x3); - config[1] = kParity[(Settings.serial_config >> 3) & 0x3]; - config[2] = '1' + ((Settings.serial_config >> 2) & 0x1); - config[3] = '\0'; - return String(config); -} - -void SetSerialBegin() -{ - uint32_t baudrate = Settings.baudrate * 300; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_SERIAL "Set to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); - Serial.flush(); - Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); -} - -void SetSerialConfig(uint32_t serial_config) -{ - if (serial_config > TS_SERIAL_8O2) { - serial_config = TS_SERIAL_8N1; - } - if (serial_config != Settings.serial_config) { - Settings.serial_config = serial_config; - SetSerialBegin(); - } -} - -void SetSerialBaudrate(uint32_t baudrate) -{ - Settings.baudrate = baudrate / 300; - if (Serial.baudRate() != baudrate) { - SetSerialBegin(); - } -} - -void SetSerial(uint32_t baudrate, uint32_t serial_config) -{ - Settings.flag.mqtt_serial = 0; - Settings.serial_config = serial_config; - Settings.baudrate = baudrate / 300; - SetSeriallog(LOG_LEVEL_NONE); - SetSerialBegin(); -} - -void ClaimSerial(void) -{ - serial_local = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial")); - SetSeriallog(LOG_LEVEL_NONE); - Settings.baudrate = Serial.baudRate() / 300; -} - -void SerialSendRaw(char *codes) -{ - char *p; - char stemp[3]; - uint8_t code; - - int size = strlen(codes); - - while (size > 1) { - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, &p, 16); - Serial.write(code); - size -= 2; - codes += 2; - } -} - -uint32_t GetHash(const char *buffer, size_t size) -{ - uint32_t hash = 0; - for (uint32_t i = 0; i <= size; i++) { - hash += (uint8_t)*buffer++ * (i +1); - } - return hash; -} - -void ShowSource(uint32_t source) -{ - if ((source > 0) && (source < SRC_MAX)) { - char stemp1[20]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SRC: %s"), GetTextIndexed(stemp1, sizeof(stemp1), source, kCommandSource)); - } -} - -void WebHexCode(uint32_t i, const char* code) -{ - char scolor[10]; - - strlcpy(scolor, code, sizeof(scolor)); - char* p = scolor; - if ('#' == p[0]) { p++; } - - if (3 == strlen(p)) { - p[6] = p[3]; - p[5] = p[2]; - p[4] = p[2]; - p[3] = p[1]; - p[2] = p[1]; - p[1] = p[0]; - } - - uint32_t color = strtol(p, nullptr, 16); - - - - - - - uint32_t j = sizeof(Settings.web_color) / 3; -# 917 "S:/Development/Tasmota/tasmota/support.ino" - if (i >= j) { - - i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); - } - Settings.web_color[i][0] = (color >> 16) & 0xFF; - Settings.web_color[i][1] = (color >> 8) & 0xFF; - Settings.web_color[i][2] = color & 0xFF; -} - -uint32_t WebColor(uint32_t i) -{ - uint32_t j = sizeof(Settings.web_color) / 3; - - - - - if (i >= j) { - - i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j); - } - uint32_t tcolor = (Settings.web_color[i][0] << 16) | (Settings.web_color[i][1] << 8) | Settings.web_color[i][2]; - - return tcolor; -} - - - - - -const uint16_t TIMESZ = 100; - -char* ResponseGetTime(uint32_t format, char* time_str) -{ - switch (format) { - case 1: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime()); - break; - case 2: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":%u"), UtcTime()); - break; - default: - snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - } - return time_str; -} - -int Response_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), format, args); - va_end(args); - return len; -} - -int ResponseTime_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - - ResponseGetTime(Settings.flag2.time_format, mqtt_data); - - int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); - va_end(args); - return len + mlen; -} - -int ResponseAppend_P(const char* format, ...) -{ - - va_list args; - va_start(args, format); - int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); - va_end(args); - return len + mlen; -} - -int ResponseAppendTimeFormat(uint32_t format) -{ - char time_str[TIMESZ]; - return ResponseAppend_P(ResponseGetTime(format, time_str)); -} - -int ResponseAppendTime(void) -{ - return ResponseAppendTimeFormat(Settings.flag2.time_format); -} - -int ResponseJsonEnd(void) -{ - return ResponseAppend_P(PSTR("}")); -} - -int ResponseJsonEndEnd(void) -{ - return ResponseAppend_P(PSTR("}}")); -} - - - - - -void DigitalWrite(uint32_t gpio_pin, uint32_t state) -{ - if (pin[gpio_pin] < 99) { - digitalWrite(pin[gpio_pin], state &1); - } -} - -uint8_t ModuleNr(void) -{ - - - return (USER_MODULE == Settings.module) ? 0 : Settings.module +1; -} - -bool ValidTemplateModule(uint32_t index) -{ - for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { - if (index == pgm_read_byte(kModuleNiceList + i)) { - return true; - } - } - return false; -} - -bool ValidModule(uint32_t index) -{ - if (index == USER_MODULE) { return true; } - return ValidTemplateModule(index); -} - -String AnyModuleName(uint32_t index) -{ - if (USER_MODULE == index) { - return String(Settings.user_template.name); - } else { - return FPSTR(kModules[index].name); - } -} - -String ModuleName(void) -{ - return AnyModuleName(Settings.module); -} - -void ModuleGpios(myio *gp) -{ - uint8_t *dest = (uint8_t *)gp; - memset(dest, GPIO_NONE, sizeof(myio)); - - uint8_t src[sizeof(mycfgio)]; - if (USER_MODULE == Settings.module) { - memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio)); - } else { - memcpy_P(&src, &kModules[Settings.module].gp, sizeof(mycfgio)); - } - - - - - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - dest[j] = src[i]; - j++; - } - - - -} - -gpio_flag ModuleFlag(void) -{ - gpio_flag flag; - - if (USER_MODULE == Settings.module) { - flag = Settings.user_template.flag; - } else { - memcpy_P(&flag, &kModules[Settings.module].flag, sizeof(gpio_flag)); - } - - return flag; -} - -void ModuleDefault(uint32_t module) -{ - if (USER_MODULE == module) { module = WEMOS; } - Settings.user_template_base = module; - memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt)); -} - -void SetModuleType(void) -{ - my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module; -} - -bool FlashPin(uint32_t pin) -{ - return (((pin > 5) && (pin < 9)) || (11 == pin)); -} - -uint8_t ValidPin(uint32_t pin, uint32_t gpio) -{ - if (FlashPin(pin)) { - return GPIO_NONE; - } - - - if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { - if ((pin == 9) || (pin == 10)) { - return GPIO_NONE; - } - } - - return gpio; -} - -bool ValidGPIO(uint32_t pin, uint32_t gpio) -{ - return (GPIO_USER == ValidPin(pin, gpio)); -} - -bool ValidAdc(void) -{ - gpio_flag flag = ModuleFlag(); - uint32_t template_adc0 = flag.data &15; - return (ADC0_USER == template_adc0); -} - -bool GetUsedInModule(uint32_t val, uint8_t *arr) -{ - int offset = 0; - - if (!val) { return false; } - - if ((val >= GPIO_KEY1) && (val < GPIO_KEY1 + MAX_KEYS)) { - offset = (GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_NP) && (val < GPIO_KEY1_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_NP - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV) && (val < GPIO_KEY1_INV + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV - GPIO_KEY1); - } - if ((val >= GPIO_KEY1_INV_NP) && (val < GPIO_KEY1_INV_NP + MAX_KEYS)) { - offset = -(GPIO_KEY1_INV_NP - GPIO_KEY1); - } - - if ((val >= GPIO_SWT1) && (val < GPIO_SWT1 + MAX_SWITCHES)) { - offset = (GPIO_SWT1_NP - GPIO_SWT1); - } - if ((val >= GPIO_SWT1_NP) && (val < GPIO_SWT1_NP + MAX_SWITCHES)) { - offset = -(GPIO_SWT1_NP - GPIO_SWT1); - } - - if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { - offset = (GPIO_REL1_INV - GPIO_REL1); - } - if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) { - offset = -(GPIO_REL1_INV - GPIO_REL1); - } - - if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) { - offset = (GPIO_LED1_INV - GPIO_LED1); - } - if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) { - offset = -(GPIO_LED1_INV - GPIO_LED1); - } - - if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) { - offset = (GPIO_PWM1_INV - GPIO_PWM1); - } - if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) { - offset = -(GPIO_PWM1_INV - GPIO_PWM1); - } - - if ((val >= GPIO_CNTR1) && (val < GPIO_CNTR1 + MAX_COUNTERS)) { - offset = (GPIO_CNTR1_NP - GPIO_CNTR1); - } - if ((val >= GPIO_CNTR1_NP) && (val < GPIO_CNTR1_NP + MAX_COUNTERS)) { - offset = -(GPIO_CNTR1_NP - GPIO_CNTR1); - } - - for (uint32_t i = 0; i < MAX_GPIO_PIN; i++) { - if (arr[i] == val) { return true; } - if (arr[i] == val + offset) { return true; } - } - return false; -} - -bool JsonTemplate(const char* dataBuf) -{ - - - if (strlen(dataBuf) < 9) { return false; } - - StaticJsonBuffer<350> jb; - JsonObject& obj = jb.parseObject(dataBuf); - if (!obj.success()) { return false; } - - - const char* name = obj[D_JSON_NAME]; - if (name != nullptr) { - strlcpy(Settings.user_template.name, name, sizeof(Settings.user_template.name)); - } - if (obj[D_JSON_GPIO].success()) { - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0; - } - } - if (obj[D_JSON_FLAG].success()) { - uint8_t flag = obj[D_JSON_FLAG] | 0; - memcpy(&Settings.user_template.flag, &flag, sizeof(gpio_flag)); - } - if (obj[D_JSON_BASE].success()) { - uint8_t base = obj[D_JSON_BASE]; - if ((0 == base) || !ValidTemplateModule(base -1)) { base = 18; } - Settings.user_template_base = base -1; - } - return true; -} - -void TemplateJson(void) -{ - Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); - } - ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); -} - - - - - -inline int32_t TimeDifference(uint32_t prev, uint32_t next) -{ - return ((int32_t) (next - prev)); -} - -int32_t TimePassedSince(uint32_t timestamp) -{ - - - return TimeDifference(timestamp, millis()); -} - -bool TimeReached(uint32_t timer) -{ - - const long passed = TimePassedSince(timer); - return (passed >= 0); -} - -void SetNextTimeInterval(unsigned long& timer, const unsigned long step) -{ - timer += step; - const long passed = TimePassedSince(timer); - if (passed < 0) { return; } - if (static_cast(passed) > step) { - - timer = millis() + step; - return; - } - - timer = millis() + (step - passed); -} - -int32_t TimePassedSinceUsec(uint32_t timestamp) -{ - return TimeDifference(timestamp, micros()); -} - -bool TimeReachedUsec(uint32_t timer) -{ - - const long passed = TimePassedSinceUsec(timer); - return (passed >= 0); -} - - - - - -#ifdef USE_I2C -const uint8_t I2C_RETRY_COUNTER = 3; - -uint32_t i2c_active[4] = { 0 }; -uint32_t i2c_buffer = 0; - -bool I2cValidRead(uint8_t addr, uint8_t reg, uint8_t size) -{ - uint8_t retry = I2C_RETRY_COUNTER; - bool status = false; - - i2c_buffer = 0; - while (!status && retry) { - Wire.beginTransmission(addr); - Wire.write(reg); - if (0 == Wire.endTransmission(false)) { - Wire.requestFrom((int)addr, (int)size); - if (Wire.available() == size) { - for (uint32_t i = 0; i < size; i++) { - i2c_buffer = i2c_buffer << 8 | Wire.read(); - } - status = true; - } - } - retry--; - } - return status; -} - -bool I2cValidRead8(uint8_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 1); - *data = (uint8_t)i2c_buffer; - return status; -} - -bool I2cValidRead16(uint16_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 2); - *data = (uint16_t)i2c_buffer; - return status; -} - -bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 2); - *data = (int16_t)i2c_buffer; - return status; -} - -bool I2cValidRead16LE(uint16_t *data, uint8_t addr, uint8_t reg) -{ - uint16_t ldata; - bool status = I2cValidRead16(&ldata, addr, reg); - *data = (ldata >> 8) | (ldata << 8); - return status; -} - -bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg) -{ - uint16_t ldata; - bool status = I2cValidRead16LE(&ldata, addr, reg); - *data = (int16_t)ldata; - return status; -} - -bool I2cValidRead24(int32_t *data, uint8_t addr, uint8_t reg) -{ - bool status = I2cValidRead(addr, reg, 3); - *data = i2c_buffer; - return status; -} - -uint8_t I2cRead8(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 1); - return (uint8_t)i2c_buffer; -} - -uint16_t I2cRead16(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - return (uint16_t)i2c_buffer; -} - -int16_t I2cReadS16(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - return (int16_t)i2c_buffer; -} - -uint16_t I2cRead16LE(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 2); - uint16_t temp = (uint16_t)i2c_buffer; - return (temp >> 8) | (temp << 8); -} - -int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg) -{ - return (int16_t)I2cRead16LE(addr, reg); -} - -int32_t I2cRead24(uint8_t addr, uint8_t reg) -{ - I2cValidRead(addr, reg, 3); - return i2c_buffer; -} - -bool I2cWrite(uint8_t addr, uint8_t reg, uint32_t val, uint8_t size) -{ - uint8_t x = I2C_RETRY_COUNTER; - - do { - Wire.beginTransmission((uint8_t)addr); - Wire.write(reg); - uint8_t bytes = size; - while (bytes--) { - Wire.write((val >> (8 * bytes)) & 0xFF); - } - x--; - } while (Wire.endTransmission(true) != 0 && x != 0); - return (x); -} - -bool I2cWrite8(uint8_t addr, uint8_t reg, uint16_t val) -{ - return I2cWrite(addr, reg, val, 1); -} - -bool I2cWrite16(uint8_t addr, uint8_t reg, uint16_t val) -{ - return I2cWrite(addr, reg, val, 2); -} - -int8_t I2cReadBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) -{ - Wire.beginTransmission((uint8_t)addr); - Wire.write((uint8_t)reg); - Wire.endTransmission(); - if (len != Wire.requestFrom((uint8_t)addr, (uint8_t)len)) { - return 1; - } - while (len--) { - *reg_data = (uint8_t)Wire.read(); - reg_data++; - } - return 0; -} - -int8_t I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len) -{ - Wire.beginTransmission((uint8_t)addr); - Wire.write((uint8_t)reg); - while (len--) { - Wire.write(*reg_data); - reg_data++; - } - Wire.endTransmission(); - return 0; -} - -void I2cScan(char *devs, unsigned int devs_len) -{ - - - - - - - - uint8_t error = 0; - uint8_t address = 0; - uint8_t any = 0; - - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_DEVICES_FOUND_AT)); - for (address = 1; address <= 127; address++) { - Wire.beginTransmission(address); - error = Wire.endTransmission(); - if (0 == error) { - any = 1; - snprintf_P(devs, devs_len, PSTR("%s 0x%02x"), devs, address); - } - else if (error != 2) { - any = 2; - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"Error %d at 0x%02x"), error, address); - break; - } - } - if (any) { - strncat(devs, "\"}", devs_len - strlen(devs) -1); - } - else { - snprintf_P(devs, devs_len, PSTR("{\"" D_CMND_I2CSCAN "\":\"" D_JSON_I2CSCAN_NO_DEVICES_FOUND "\"}")); - } -} - -void I2cResetActive(uint32_t addr, uint32_t count = 1) -{ - addr &= 0x7F; - count &= 0x7F; - while (count-- && (addr < 128)) { - i2c_active[addr / 32] &= ~(1 << (addr % 32)); - addr++; - } - -} - -void I2cSetActive(uint32_t addr, uint32_t count = 1) -{ - addr &= 0x7F; - count &= 0x7F; - while (count-- && (addr < 128)) { - i2c_active[addr / 32] |= (1 << (addr % 32)); - addr++; - } - -} - -void I2cSetActiveFound(uint32_t addr, const char *types) -{ - I2cSetActive(addr); - AddLog_P2(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, types, addr); -} - -bool I2cActive(uint32_t addr) -{ - addr &= 0x7F; - if (i2c_active[addr / 32] & (1 << (addr % 32))) { - return true; - } - return false; -} - -bool I2cSetDevice(uint32_t addr) -{ - addr &= 0x7F; - if (I2cActive(addr)) { - return false; - } - Wire.beginTransmission((uint8_t)addr); - return (0 == Wire.endTransmission()); -} -#endif -# 1560 "S:/Development/Tasmota/tasmota/support.ino" -void SetSeriallog(uint32_t loglevel) -{ - Settings.seriallog_level = loglevel; - seriallog_level = loglevel; - seriallog_timer = 0; -} - -void SetSyslog(uint32_t loglevel) -{ - Settings.syslog_level = loglevel; - syslog_level = loglevel; - syslog_timer = 0; -} - -#ifdef USE_WEBSERVER -void GetLog(uint32_t idx, char** entry_pp, size_t* len_p) -{ - char* entry_p = nullptr; - size_t len = 0; - - if (idx) { - char* it = web_log; - do { - uint32_t cur_idx = *it; - it++; - size_t tmp = strchrspn(it, '\1'); - tmp++; - if (cur_idx == idx) { - len = tmp; - entry_p = it; - break; - } - it += tmp; - } while (it < web_log + WEB_LOG_SIZE && *it != '\0'); - } - *entry_pp = entry_p; - *len_p = len; -} -#endif - -void Syslog(void) -{ - - - uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST))); - if (syslog_host_hash != current_hash) { - syslog_host_hash = current_hash; - WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); - } - if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { - char syslog_preamble[64]; - snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), my_hostname); - memmove(log_data + strlen(syslog_preamble), log_data, sizeof(log_data) - strlen(syslog_preamble)); - log_data[sizeof(log_data) -1] = '\0'; - memcpy(log_data, syslog_preamble, strlen(syslog_preamble)); - PortUdp.write(log_data, strlen(log_data)); - PortUdp.endPacket(); - delay(1); - } else { - syslog_level = 0; - syslog_timer = SYSLOG_TIMER; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER); - } -} - -void AddLog(uint32_t loglevel) -{ - char mxtime[10]; - - snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d "), RtcTime.hour, RtcTime.minute, RtcTime.second); - - if (loglevel <= seriallog_level) { - Serial.printf("%s%s\r\n", mxtime, log_data); - } -#ifdef USE_WEBSERVER - if (Settings.webserver && (loglevel <= Settings.weblog_level)) { - - - web_log_index &= 0xFF; - if (!web_log_index) web_log_index++; - while (web_log_index == web_log[0] || - strlen(web_log) + strlen(log_data) + 13 > WEB_LOG_SIZE) - { - char* it = web_log; - it++; - it += strchrspn(it, '\1'); - it++; - memmove(web_log, it, WEB_LOG_SIZE -(it-web_log)); - } - snprintf_P(web_log, sizeof(web_log), PSTR("%s%c%s%s\1"), web_log, web_log_index++, mxtime, log_data); - web_log_index &= 0xFF; - if (!web_log_index) web_log_index++; - } -#endif - if (Settings.flag.mqtt_enabled && - !global_state.mqtt_down && - (loglevel <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); } - - if (!global_state.wifi_down && - (loglevel <= syslog_level)) { Syslog(); } -} - -void AddLog_P(uint32_t loglevel, const char *formatP) -{ - snprintf_P(log_data, sizeof(log_data), formatP); - AddLog(loglevel); -} - -void AddLog_P(uint32_t loglevel, const char *formatP, const char *formatP2) -{ - char message[sizeof(log_data)]; - - snprintf_P(log_data, sizeof(log_data), formatP); - snprintf_P(message, sizeof(message), formatP2); - strncat(log_data, message, sizeof(log_data) - strlen(log_data) -1); - AddLog(loglevel); -} - -void PrepLog_P2(uint32_t loglevel, PGM_P formatP, ...) -{ - va_list arg; - va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); - va_end(arg); - - prepped_loglevel = loglevel; -} - -void AddLog_P2(uint32_t loglevel, PGM_P formatP, ...) -{ - va_list arg; - va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); - va_end(arg); - - AddLog(loglevel); -} - -void AddLog_Debug(PGM_P formatP, ...) -{ - va_list arg; - va_start(arg, formatP); - vsnprintf_P(log_data, sizeof(log_data), formatP, arg); - va_end(arg); - - AddLog(LOG_LEVEL_DEBUG); -} - -void AddLogBuffer(uint32_t loglevel, uint8_t *buffer, uint32_t count) -{ -# 1722 "S:/Development/Tasmota/tasmota/support.ino" - char hex_char[(count * 3) + 2]; - AddLog_P2(loglevel, PSTR("DMP: %s"), ToHex_P(buffer, count, hex_char, sizeof(hex_char), ' ')); -} - -void AddLogSerial(uint32_t loglevel) -{ - AddLogBuffer(loglevel, (uint8_t*)serial_in_buffer, serial_in_byte_counter); -} - -void AddLogMissed(char *sensor, uint32_t misses) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); -} -# 1 "S:/Development/Tasmota/tasmota/support_button.ino" -# 20 "S:/Development/Tasmota/tasmota/support_button.ino" -#define BUTTON_V1 -#ifdef BUTTON_V1 - - - - -#define MAX_BUTTON_COMMANDS 5 -const char kCommands[] PROGMEM = - D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_WIFICONFIG " 2|" D_CMND_RESTART " 1|" D_CMND_UPGRADE " 1"; - -struct BUTTON { - unsigned long debounce = 0; - uint16_t hold_timer[MAX_KEYS] = { 0 }; - uint16_t dual_code = 0; - - uint8_t last_state[MAX_KEYS] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; - uint8_t window_timer[MAX_KEYS] = { 0 }; - uint8_t press_counter[MAX_KEYS] = { 0 }; - - uint8_t dual_receive_count = 0; - uint8_t no_pullup_mask = 0; - uint8_t inverted_mask = 0; - uint8_t present = 0; - uint8_t adc = 99; -} Button; - - - -void ButtonPullupFlag(uint8 button_bit) -{ - bitSet(Button.no_pullup_mask, button_bit); -} - -void ButtonInvertFlag(uint8 button_bit) -{ - bitSet(Button.inverted_mask, button_bit); -} - -void ButtonInit(void) -{ - Button.present = 0; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if (pin[GPIO_KEY1 +i] < 99) { - Button.present++; - pinMode(pin[GPIO_KEY1 +i], bitRead(Button.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_KEY1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); - } -#ifndef USE_ADC_VCC - else if ((99 == Button.adc) && ((ADC0_BUTTON == my_adc0) || (ADC0_BUTTON_INV == my_adc0))) { - Button.present++; - Button.adc = i; - } -#endif - } -} - -uint8_t ButtonSerial(uint8_t serial_in_byte) -{ - if (Button.dual_receive_count) { - Button.dual_receive_count--; - if (Button.dual_receive_count) { - Button.dual_code = (Button.dual_code << 8) | serial_in_byte; - serial_in_byte = 0; - } else { - if (serial_in_byte != 0xA1) { - Button.dual_code = 0; - } - } - } - if (0xA0 == serial_in_byte) { - serial_in_byte = 0; - Button.dual_code = 0; - Button.dual_receive_count = 3; - } - - return serial_in_byte; -} -# 108 "S:/Development/Tasmota/tasmota/support_button.ino" -void ButtonHandler(void) -{ - if (uptime < 4) { return; } - - uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; - uint16_t loops_per_second = 1000 / Settings.button_debounce; - char scmnd[20]; - - - - for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { - uint8_t button = NOT_PRESSED; - uint8_t button_present = 0; - - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) { - button_present = 1; - if (Button.dual_code) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code); - button = PRESSED; - if (0xF500 == Button.dual_code) { - Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; - hold_time_extent = 1; - } - Button.dual_code = 0; - } - } - else if (pin[GPIO_KEY1 +button_index] < 99) { - button_present = 1; - button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(Button.inverted_mask, button_index)); - } -#ifndef USE_ADC_VCC - if (Button.adc == button_index) { - button_present = 1; - if (ADC0_BUTTON_INV == my_adc0) { - button = (AdcRead(1) < 128); - } - else if (ADC0_BUTTON == my_adc0) { - button = (AdcRead(1) > 128); - } - } -#endif - - if (button_present) { - XdrvMailbox.index = button_index; - XdrvMailbox.payload = button; - if (XdrvCall(FUNC_BUTTON_PRESSED)) { - - } - else if (SONOFF_4CHPRO == my_module_type) { - if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; } - - bool button_pressed = false; - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), button_index +1); - Button.hold_timer[button_index] = loops_per_second; - button_pressed = true; - } - if ((NOT_PRESSED == button) && (PRESSED == Button.last_state[button_index])) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_01), button_index +1); - if (!Button.hold_timer[button_index]) { button_pressed = true; } - } - if (button_pressed) { - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); - } - } - } - else { - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - if (Settings.flag.button_single) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); - if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { - ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); - } - } else { - Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_MULTI_PRESS " %d"), button_index +1, Button.press_counter[button_index]); - Button.window_timer[button_index] = loops_per_second / 2; - } - blinks = 201; - } - - if (NOT_PRESSED == button) { - Button.hold_timer[button_index] = 0; - } else { - Button.hold_timer[button_index]++; - if (Settings.flag.button_single) { - if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } else { - if (Settings.flag.button_restrict) { - if (Settings.param[P_HOLD_IGNORE] > 0) { - if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { - Button.hold_timer[button_index] = 0; - Button.press_counter[button_index] = 0; - DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]); - } - } - if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { - Button.press_counter[button_index] = 0; - SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); - } - } else { - if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { - Button.press_counter[button_index] = 0; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } - } - - if (!Settings.flag.button_single) { - if (Button.window_timer[button_index]) { - Button.window_timer[button_index]--; - } else { - if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS +3)) { - bool single_press = false; - if (Button.press_counter[button_index] < 3) { - if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - single_press = true; - } else { - single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); - if ((1 == Button.present) && (2 == devices_present)) { - if (Settings.flag.button_swap) { - Button.press_counter[button_index] = (single_press) ? 1 : 2; - } - } else { - Button.press_counter[button_index] = 1; - } - } - } -#if defined(USE_LIGHT) && defined(ROTARY_V1) - if (!((0 == button_index) && RotaryButtonPressed())) { -#endif - if (single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { - - } else { - if (Button.press_counter[button_index] < 3) { - if (WifiState() > WIFI_RESTART) { - restart_flag = 1; - } else { - ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON); - } - } else { - if (!Settings.flag.button_restrict) { - GetTextIndexed(scmnd, sizeof(scmnd), Button.press_counter[button_index] -3, kCommands); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } -#if defined(USE_LIGHT) && defined(ROTARY_V1) - } -#endif - Button.press_counter[button_index] = 0; - } - } - } - } - } - Button.last_state[button_index] = button; - } -} - -void ButtonLoop(void) -{ - if (Button.present) { - if (TimeReached(Button.debounce)) { - SetNextTimeInterval(Button.debounce, Settings.button_debounce); - ButtonHandler(); - } - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/support_command.ino" -# 20 "S:/Development/Tasmota/tasmota/support_command.ino" -const char kTasmotaCommands[] PROGMEM = "|" - D_CMND_BACKLOG "|" D_CMND_DELAY "|" D_CMND_POWER "|" D_CMND_STATUS "|" D_CMND_STATE "|" D_CMND_SLEEP "|" D_CMND_UPGRADE "|" D_CMND_UPLOAD "|" D_CMND_OTAURL "|" - D_CMND_SERIALLOG "|" D_CMND_RESTART "|" D_CMND_POWERONSTATE "|" D_CMND_PULSETIME "|" D_CMND_BLINKTIME "|" D_CMND_BLINKCOUNT "|" D_CMND_SAVEDATA "|" - D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" - D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" - D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" - D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|" - D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" - D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" - D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" -#ifdef USE_I2C - D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" -#endif -#ifdef USE_DEVICE_GROUPS - D_CMND_DEVGROUP_SHARE "|" -#endif - D_CMND_SENSOR "|" D_CMND_DRIVER; - -void (* const TasmotaCommand[])(void) PROGMEM = { - &CmndBacklog, &CmndDelay, &CmndPower, &CmndStatus, &CmndState, &CmndSleep, &CmndUpgrade, &CmndUpgrade, &CmndOtaUrl, - &CmndSeriallog, &CmndRestart, &CmndPowerOnState, &CmndPulsetime, &CmndBlinktime, &CmndBlinkcount, &CmndSavedata, - &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, - &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, - &CmndModule, &CmndModules, &CmndGpio, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange, - &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig, - &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, - &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, - &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, -#ifdef USE_I2C - &CmndI2cScan, CmndI2cDriver, -#endif -#ifdef USE_DEVICE_GROUPS - &CmndDevGroupShare, -#endif - &CmndSensor, &CmndDriver }; - -const char kWifiConfig[] PROGMEM = - D_WCFG_0_RESTART "||" D_WCFG_2_WIFIMANAGER "||" D_WCFG_4_RETRY "|" D_WCFG_5_WAIT "|" D_WCFG_6_SERIAL "|" D_WCFG_7_WIFIMANAGER_RESET_ONLY; - - - -void ResponseCmndNumber(int value) -{ - Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, value); -} - -void ResponseCmndFloat(float value, uint32_t decimals) -{ - char stemp1[TOPSZ]; - dtostrfd(value, decimals, stemp1); - Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp1); -} - -void ResponseCmndIdxNumber(int value) -{ - Response_P(S_JSON_COMMAND_INDEX_NVALUE, XdrvMailbox.command, XdrvMailbox.index, value); -} - -void ResponseCmndChar(const char* value) -{ - Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, value); -} - -void ResponseCmndStateText(uint32_t value) -{ - ResponseCmndChar(GetStateText(value)); -} - -void ResponseCmndDone(void) -{ - ResponseCmndChar(D_JSON_DONE); -} - -void ResponseCmndIdxChar(const char* value) -{ - Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, value); -} - -void ResponseCmndAll(uint32_t text_index, uint32_t count) -{ - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < count; i++) { - ResponseAppend_P(PSTR("%c\"%s%d\":\"%s\""), (i) ? ',' : '{', XdrvMailbox.command, i +1, SettingsText(text_index +i)); - } - ResponseJsonEnd(); -} - - - -void ExecuteCommand(const char *cmnd, uint32_t source) -{ - - - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("ExecuteCommand")); -#endif - ShowSource(source); - - const char *pos = cmnd; - while (*pos && isspace(*pos)) { - pos++; - } - - const char *start = pos; - - while (*pos && (isalpha(*pos) || isdigit(*pos) || '_' == *pos || '/' == *pos)) { - if ('/' == *pos) { - start = pos + 1; - } - pos++; - } - if ('\0' == *start || pos <= start) { - return; - } - - uint32_t size = pos - start; - char stopic[size + 2]; - stopic[0] = '/'; - memcpy(stopic+1, start, size); - stopic[size+1] = '\0'; - - char svalue[strlen(pos) +1]; - strlcpy(svalue, pos, sizeof(svalue)); - CommandHandler(stopic, svalue, strlen(svalue)); -} -# 154 "S:/Development/Tasmota/tasmota/support_command.ino" -void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len) -{ -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("CommandHandler")); -#endif - - while (*dataBuf && isspace(*dataBuf)) { - dataBuf++; - data_len--; - } - - bool grpflg = (strstr(topicBuf, SettingsText(SET_MQTT_GRP_TOPIC)) != nullptr); - - char stemp1[TOPSZ]; - GetFallbackTopic_P(stemp1, ""); - fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); - - char *type = strrchr(topicBuf, '/'); - - uint32_t index = 1; - bool user_index = false; - if (type != nullptr) { - type++; - uint32_t i; - for (i = 0; i < strlen(type); i++) { - type[i] = toupper(type[i]); - } - while (isdigit(type[i-1])) { - i--; - } - if (i < strlen(type)) { - index = atoi(type +i); - user_index = true; - } - type[i] = '\0'; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf); - - if (type != nullptr) { - Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); - - if (Settings.ledstate &0x02) { blinks++; } - - if (!strcmp(dataBuf,"?")) { data_len = 0; } - - char *p; - int32_t payload = strtol(dataBuf, &p, 0); - if (p == dataBuf) { payload = -99; } - int temp_payload = GetStateNumber(dataBuf); - if (temp_payload > -1) { payload = temp_payload; } - - DEBUG_CORE_LOG(PSTR("CMD: Payload %d"), payload); - - - backlog_delay = millis() + Settings.param[P_BACKLOG_DELAY]; - - char command[CMDSZ] = { 0 }; - XdrvMailbox.command = command; - XdrvMailbox.index = index; - XdrvMailbox.data_len = data_len; - XdrvMailbox.payload = payload; - XdrvMailbox.grpflg = grpflg; - XdrvMailbox.usridx = user_index; - XdrvMailbox.topic = type; - XdrvMailbox.data = dataBuf; - -#ifdef USE_SCRIPT_SUB_COMMAND - - if (!Script_SubCmd()) { - if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { - if (!XdrvCall(FUNC_COMMAND)) { - if (!XsnsCall(FUNC_COMMAND)) { - type = nullptr; - } - } - } - } -#else - if (!DecodeCommand(kTasmotaCommands, TasmotaCommand)) { - if (!XdrvCall(FUNC_COMMAND)) { - if (!XsnsCall(FUNC_COMMAND)) { - type = nullptr; - } - } - } -#endif - - } - - if (type == nullptr) { - blinks = 201; - snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_COMMAND)); - Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); - type = (char*)stemp1; - } - - if (mqtt_data[0] != '\0') { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); - XdrvRulesProcess(); - } - fallback_topic_flag = false; -} - - - -void CmndBacklog(void) -{ - if (XdrvMailbox.data_len) { - -#ifdef SUPPORT_IF_STATEMENT - char *blcommand = strtok(XdrvMailbox.data, ";"); - while ((blcommand != nullptr) && (backlog.size() < MAX_BACKLOG)) -#else - uint32_t bl_pointer = (!backlog_pointer) ? MAX_BACKLOG -1 : backlog_pointer; - bl_pointer--; - char *blcommand = strtok(XdrvMailbox.data, ";"); - while ((blcommand != nullptr) && (backlog_index != bl_pointer)) -#endif - { - while(true) { - blcommand = Trim(blcommand); - if (!strncasecmp_P(blcommand, PSTR(D_CMND_BACKLOG), strlen(D_CMND_BACKLOG))) { - blcommand += strlen(D_CMND_BACKLOG); - } else { - break; - } - } - if (*blcommand != '\0') { -#ifdef SUPPORT_IF_STATEMENT - if (backlog.size() < MAX_BACKLOG) { - backlog.add(blcommand); - } -#else - backlog[backlog_index] = String(blcommand); - backlog_index++; - if (backlog_index >= MAX_BACKLOG) backlog_index = 0; -#endif - } - blcommand = strtok(nullptr, ";"); - } - - mqtt_data[0] = '\0'; - } else { - bool blflag = BACKLOG_EMPTY; -#ifdef SUPPORT_IF_STATEMENT - backlog.clear(); -#else - backlog_pointer = backlog_index; -#endif - ResponseCmndChar(blflag ? D_JSON_EMPTY : D_JSON_ABORTED); - } -} - -void CmndDelay(void) -{ - if ((XdrvMailbox.payload >= (MIN_BACKLOG_DELAY / 100)) && (XdrvMailbox.payload <= 3600)) { - backlog_delay = millis() + (100 * XdrvMailbox.payload); - } - uint32_t bl_delay = 0; - long bl_delta = TimePassedSince(backlog_delay); - if (bl_delta < 0) { bl_delay = (bl_delta *-1) / 100; } - ResponseCmndNumber(bl_delay); -} - -void CmndPower(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) { - if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_BLINK_STOP)) { - XdrvMailbox.payload = POWER_SHOW_STATE; - } - - ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE); - mqtt_data[0] = '\0'; - } - else if (0 == XdrvMailbox.index) { - if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_TOGGLE)) { - XdrvMailbox.payload = POWER_SHOW_STATE; - } - SetAllPower(XdrvMailbox.payload, SRC_IGNORE); - mqtt_data[0] = '\0'; - } -} - -void CmndStatus(void) -{ - uint32_t payload = ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > MAX_STATUS)) ? 99 : XdrvMailbox.payload; - - uint32_t option = STAT; - char stemp[200]; - char stemp2[TOPSZ]; - - - - - - if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } - if (!energy_flg && (9 == payload)) { payload = 99; } - if (!CrashFlag() && (12 == payload)) { payload = 99; } - - if ((0 == payload) || (99 == payload)) { - uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { maxfn = 1; } -#endif - stemp[0] = '\0'; - for (uint32_t i = 0; i < maxfn; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s%s\"%s\"" ), stemp, (i > 0 ? "," : ""), SettingsText(SET_FRIENDLYNAME1 +i)); - } - stemp2[0] = '\0'; - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); - } - Response_P(PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d,\"" D_CMND_FRIENDLYNAME "\":[%s],\"" D_CMND_TOPIC "\":\"%s\",\"" - D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" - D_CMND_LEDMASK "\":\"%04X\",\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" - D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), - ModuleNr(), stemp, mqtt_topic, - SettingsText(SET_MQTT_BUTTON_TOPIC), power, Settings.poweronstate, Settings.ledstate, - Settings.ledmask, Settings.save_data, - Settings.flag.save_state, - SettingsText(SET_MQTT_SWITCH_TOPIC), - stemp2, - Settings.flag.mqtt_button_retain, - Settings.flag.mqtt_switch_retain, - Settings.flag.mqtt_sensor_retain, - Settings.flag.mqtt_power_retain); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); - } - - if ((0 == payload) || (1 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_SERIALCONFIG "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" - D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" - D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"BCResetTime\":\"%s\",\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), - Settings.baudrate * 300, GetSerialConfig().c_str(), SettingsText(SET_MQTT_GRP_TOPIC), SettingsText(SET_OTAURL), - GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, - Settings.cfg_holder, Settings.bootcount, GetDateAndTime(DT_BOOTCOUNT).c_str(), Settings.save_flag, GetSettingsAddress()); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); - } - - if ((0 == payload) || (2 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" - D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," - "\"Hardware\":\"%s\"" - "%s}}"), - my_version, my_image, GetBuildDateAndTime().c_str(), - ESP.getBootVersion(), ESP.getSdkVersion(), - GetDeviceHardware().c_str(), - GetStatistics().c_str()); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); - } - - if ((0 == payload) || (3 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" - D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" - D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\"]}}"), - Settings.seriallog_level, Settings.weblog_level, Settings.mqttlog_level, Settings.syslog_level, - SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), Settings.tele_period, - Settings.flag2.data, Settings.flag.data, ToHex_P((unsigned char*)Settings.param, PARAM8_SIZE, stemp2, sizeof(stemp2)), - Settings.flag3.data, Settings.flag4.data); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3")); - } - - if ((0 == payload) || (4 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" - D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" - D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"), - ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, - ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(), - LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6); - XsnsDriverState(); - ResponseAppend_P(PSTR(",\"Sensors\":")); - XsnsSensorState(); - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4")); - } - - if ((0 == payload) || (5 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\"" - D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" - D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d,\"" D_CMND_WIFIPOWER "\":%s}}"), - my_hostname, WiFi.localIP().toString().c_str(), IPAddress(Settings.ip_address[1]).toString().c_str(), - IPAddress(Settings.ip_address[2]).toString().c_str(), IPAddress(Settings.ip_address[3]).toString().c_str(), WiFi.macAddress().c_str(), - Settings.webserver, Settings.sta_config, WifiGetOutputPower().c_str()); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "5")); - } - - if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" - D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), - mqtt_client, SettingsText(SET_MQTT_USER), MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); - } - - if ((0 == payload) || (7 == payload)) { - if (99 == Settings.timezone) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d" ), Settings.timezone); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"%s\"" ), GetTimeZone().c_str()); - } -#if defined(USE_TIMERS) && defined(USE_SUNRISE) - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" - D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), - GetDateAndTime(DT_STD).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); -#else - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" - D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_LOCALNOTZ).c_str(), GetDateAndTime(DT_DST).c_str(), - GetDateAndTime(DT_STD).c_str(), stemp); -#endif - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); - } - -#if defined(USE_ENERGY_SENSOR) && defined(USE_ENERGY_MARGIN_DETECTION) - if (energy_flg) { - if ((0 == payload) || (9 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":%d,\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" - D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), - Settings.energy_power_delta, Settings.energy_min_power, Settings.energy_max_power, - Settings.energy_min_voltage, Settings.energy_max_voltage, Settings.energy_min_current, Settings.energy_max_current); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "9")); - } - } -#endif - - if ((0 == payload) || (8 == payload) || (10 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); - MqttShowSensor(); - ResponseJsonEnd(); - if (8 == payload) { - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "8")); - } else { - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "10")); - } - } - - if ((0 == payload) || (11 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); - MqttShowState(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); - } - - if (CrashFlag()) { - if ((0 == payload) || (12 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); - CrashDump(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); - } - } - -#ifdef USE_SCRIPT_STATUS - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">U",2,mqtt_data); -#endif - mqtt_data[0] = '\0'; -} - -void CmndState(void) -{ - mqtt_data[0] = '\0'; - MqttShowState(); - if (Settings.flag3.hass_tele_on_power) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); - } -#ifdef USE_HOME_ASSISTANT - if (Settings.flag.hass_discovery) { - HAssPublishStatus(); - } -#endif -} - -void CmndTempOffset(void) -{ - if (XdrvMailbox.data_len > 0) { - int value = (int)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > -127) && (value < 127)) { - Settings.temp_comp = value; - } - } - ResponseCmndFloat((float)(Settings.temp_comp) / 10, 1); -} - -void CmndSleep(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) { - Settings.sleep = XdrvMailbox.payload; - sleep = XdrvMailbox.payload; - WiFiSetSleepMode(); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, sleep); - -} - -void CmndUpgrade(void) -{ - - - - - if (((1 == XdrvMailbox.data_len) && (1 == XdrvMailbox.payload)) || ((XdrvMailbox.data_len >= 3) && NewerVersion(XdrvMailbox.data))) { - ota_state_flag = 3; - char stemp1[TOPSZ]; - Response_P(PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), XdrvMailbox.command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); - } else { - Response_P(PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), XdrvMailbox.command, my_version); - } -} - -void CmndOtaUrl(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_OTAURL, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_OTAURL)); -} - -void CmndSeriallog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - Settings.flag.mqtt_serial = 0; - SetSeriallog(XdrvMailbox.payload); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.seriallog_level, seriallog_level); -} - -void CmndRestart(void) -{ - switch (XdrvMailbox.payload) { - case 1: - restart_flag = 2; - ResponseCmndChar(D_JSON_RESTARTING); - break; - case -1: - CmndCrash(); - break; - case -2: - CmndWDT(); - break; - case -3: - CmndBlockedLoop(); - break; - case 99: - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - EspRestart(); - break; - default: - ResponseCmndChar(D_JSON_ONE_TO_RESTART); - } -} - -void CmndPowerOnState(void) -{ - if (my_module_type != MOTOR) { - - - - - - - - if ((XdrvMailbox.payload >= POWER_ALL_OFF) && (XdrvMailbox.payload <= POWER_ALL_OFF_PULSETIME_ON)) { - Settings.poweronstate = XdrvMailbox.payload; - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - for (uint32_t i = 1; i <= devices_present; i++) { - ExecuteCommandPower(i, POWER_ON, SRC_IGNORE); - } - } - } - ResponseCmndNumber(Settings.poweronstate); - } -} - -void CmndPulsetime(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PULSETIMERS)) { - uint32_t items = 1; - if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { - items = MAX_PULSETIMERS; - } else { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { - Settings.pulse_timer[XdrvMailbox.index -1] = XdrvMailbox.payload; - SetPulseTimer(XdrvMailbox.index -1, XdrvMailbox.payload); - } - } - mqtt_data[0] = '\0'; - for (uint32_t i = 0; i < items; i++) { - uint32_t index = (1 == items) ? XdrvMailbox.index : i +1; - ResponseAppend_P(PSTR("%c\"%s%d\":{\"" D_JSON_SET "\":%d,\"" D_JSON_REMAINING "\":%d}"), - (i) ? ',' : '{', - XdrvMailbox.command, index, - Settings.pulse_timer[index -1], GetPulseTimer(index -1)); - } - ResponseJsonEnd(); - } -} - -void CmndBlinktime(void) -{ - if ((XdrvMailbox.payload > 1) && (XdrvMailbox.payload <= 3600)) { - Settings.blinktime = XdrvMailbox.payload; - if (blink_timer > 0) { blink_timer = millis() + (100 * XdrvMailbox.payload); } - } - ResponseCmndNumber(Settings.blinktime); -} - -void CmndBlinkcount(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 65536)) { - Settings.blinkcount = XdrvMailbox.payload; - if (blink_counter) { blink_counter = Settings.blinkcount *2; } - } - ResponseCmndNumber(Settings.blinkcount); -} - -void CmndSavedata(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3600)) { - Settings.save_data = XdrvMailbox.payload; - save_data_counter = Settings.save_data; - } - SettingsSaveAll(); - char stemp1[TOPSZ]; - if (Settings.save_data > 1) { - snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_EVERY " %d " D_UNIT_SECOND), Settings.save_data); - } - ResponseCmndChar((Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); -} - -void CmndSetoption(void) -{ - if (XdrvMailbox.index < 114) { - uint32_t ptype; - uint32_t pindex; - if (XdrvMailbox.index <= 31) { - ptype = 2; - pindex = XdrvMailbox.index; - } - else if (XdrvMailbox.index <= 49) { - ptype = 1; - pindex = XdrvMailbox.index -32; - } - else if (XdrvMailbox.index <= 81) { - ptype = 3; - pindex = XdrvMailbox.index -50; - } - else { - ptype = 4; - pindex = XdrvMailbox.index -82; - } - - if (XdrvMailbox.payload >= 0) { - if (1 == ptype) { - uint32_t param_low = 0; - uint32_t param_high = 255; - switch (pindex) { - case P_HOLD_TIME: - case P_MAX_POWER_RETRY: - param_low = 1; - param_high = 250; - break; - } - if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) { - Settings.param[pindex] = XdrvMailbox.payload; -#ifdef USE_LIGHT - if (P_RGB_REMAP == pindex) { - LightUpdateColorMapping(); - restart_flag = 2; - } -#endif -#if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) - if (P_IR_UNKNOW_THRESHOLD == pindex) { - IrReceiveUpdateThreshold(); - } -#endif - } else { - ptype = 99; - } - } else { - if (XdrvMailbox.payload <= 1) { - if (2 == ptype) { - switch (pindex) { - case 5: - case 6: - case 7: - case 9: - case 14: - case 22: - case 23: - case 25: - case 27: - ptype = 99; - break; - case 3: - case 15: - restart_flag = 2; - default: - bitWrite(Settings.flag.data, pindex, XdrvMailbox.payload); - } - if (12 == pindex) { - stop_flash_rotate = XdrvMailbox.payload; - SettingsSave(2); - } - #ifdef USE_HOME_ASSISTANT - if ((19 == pindex) || (30 == pindex)) { - HAssDiscover(); - } - #endif - } - else if (3 == ptype) { - bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload); - switch (pindex) { - case 5: - if (0 == XdrvMailbox.payload) { - restart_flag = 2; - } - break; - case 10: - WiFiSetSleepMode(); - break; - case 18: - case 25: - restart_flag = 2; - break; - } - } - else if (4 == ptype) { - bitWrite(Settings.flag4.data, pindex, XdrvMailbox.payload); - } - } else { - ptype = 99; - } - } - } - - if (ptype < 99) { - if (1 == ptype) { - ResponseCmndIdxNumber(Settings.param[pindex]); - } else { - uint32_t flag = Settings.flag.data; - if (3 == ptype) { - flag = Settings.flag3.data; - } - else if (4 == ptype) { - flag = Settings.flag4.data; - } - ResponseCmndIdxChar(GetStateText(bitRead(flag, pindex))); - } - } - } -} - -void CmndTemperatureResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.temperature_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.temperature_resolution); -} - -void CmndHumidityResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.humidity_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.humidity_resolution); -} - -void CmndPressureResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.pressure_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.pressure_resolution); -} - -void CmndPowerResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.wattage_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.wattage_resolution); -} - -void CmndVoltageResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.voltage_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.voltage_resolution); -} - -void CmndFrequencyResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.frequency_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.frequency_resolution); -} - -void CmndCurrentResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.current_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.current_resolution); -} - -void CmndEnergyResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - Settings.flag2.energy_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.energy_resolution); -} - -void CmndWeightResolution(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - Settings.flag2.weight_resolution = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.flag2.weight_resolution); -} - -void CmndModule(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAXMODULE)) { - bool present = false; - if (0 == XdrvMailbox.payload) { - XdrvMailbox.payload = USER_MODULE; - present = true; - } else { - XdrvMailbox.payload--; - present = ValidTemplateModule(XdrvMailbox.payload); - } - if (present) { - Settings.last_module = Settings.module; - Settings.module = XdrvMailbox.payload; - SetModuleType(); - if (Settings.last_module != XdrvMailbox.payload) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } - } - restart_flag = 2; - } - } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, ModuleNr(), ModuleName().c_str()); -} - -void CmndModules(void) -{ - uint32_t midx = USER_MODULE; - uint32_t lines = 1; - bool jsflg = false; - for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { - if (i > 0) { midx = pgm_read_byte(kModuleNiceList + i -1); } - if (!jsflg) { - Response_P(PSTR("{\"" D_CMND_MODULES "%d\":{"), lines); - } else { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - uint32_t j = i ? midx +1 : 0; - if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), j, AnyModuleName(midx).c_str()) > (LOGSZ - TOPSZ)) || (i == sizeof(kModuleNiceList))) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command)); - jsflg = false; - lines++; - } - } - mqtt_data[0] = '\0'; -} - -void CmndGpio(void) -{ - if (XdrvMailbox.index < sizeof(Settings.my_gp)) { - myio cmodule; - ModuleGpios(&cmodule); - if (ValidGPIO(XdrvMailbox.index, cmodule.io[XdrvMailbox.index]) && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < GPIO_SENSOR_END)) { - bool present = false; - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - uint32_t midx = pgm_read_byte(kGpioNiceList + i); - if (midx == XdrvMailbox.payload) { present = true; } - } - if (present) { - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (ValidGPIO(i, cmodule.io[i]) && (Settings.my_gp.io[i] == XdrvMailbox.payload)) { - Settings.my_gp.io[i] = GPIO_NONE; - } - } - Settings.my_gp.io[XdrvMailbox.index] = XdrvMailbox.payload; - restart_flag = 2; - } - } - Response_P(PSTR("{")); - bool jsflg = false; - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (ValidGPIO(i, cmodule.io[i]) || ((GPIO_USER == XdrvMailbox.payload) && !FlashPin(i))) { - if (jsflg) { ResponseAppend_P(PSTR(",")); } - jsflg = true; - uint8_t sensor_type = Settings.my_gp.io[i]; - if (!ValidGPIO(i, cmodule.io[i])) { - sensor_type = cmodule.io[i]; - if (GPIO_USER == sensor_type) { - sensor_type = GPIO_NONE; - } - } - uint8_t sensor_name_idx = sensor_type; - const char *sensor_names = kSensorNames; - if (sensor_type > GPIO_FIX_START) { - sensor_name_idx = sensor_type - GPIO_FIX_START -1; - sensor_names = kSensorNamesFixed; - } - char stemp1[TOPSZ]; - ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s\"}"), - i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names)); - } - } - if (jsflg) { - ResponseJsonEnd(); - } else { - ResponseCmndChar(D_JSON_NOT_SUPPORTED); - } - } -} - -void CmndGpios(void) -{ - myio cmodule; - ModuleGpios(&cmodule); - uint32_t lines = 1; - bool jsflg = false; - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - uint32_t midx = pgm_read_byte(kGpioNiceList + i); - if ((XdrvMailbox.payload != 255) && GetUsedInModule(midx, cmodule.io)) { continue; } - if (!jsflg) { - Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":{"), lines); - } else { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - char stemp1[TOPSZ]; - if ((ResponseAppend_P(PSTR("\"%d\":\"%s\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, UpperCase(XdrvMailbox.command, XdrvMailbox.command)); - jsflg = false; - lines++; - } - } - mqtt_data[0] = '\0'; -} - -void CmndTemplate(void) -{ - - bool error = false; - - if (strstr(XdrvMailbox.data, "{") == nullptr) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= MAXMODULE)) { - XdrvMailbox.payload--; - if (ValidTemplateModule(XdrvMailbox.payload)) { - ModuleDefault(XdrvMailbox.payload); - if (USER_MODULE == Settings.module) { restart_flag = 2; } - } - } - else if (0 == XdrvMailbox.payload) { - if (Settings.module != USER_MODULE) { - ModuleDefault(Settings.module); - } - } - else if (255 == XdrvMailbox.payload) { - if (Settings.module != USER_MODULE) { - ModuleDefault(Settings.module); - } - snprintf_P(Settings.user_template.name, sizeof(Settings.user_template.name), PSTR("Merged")); - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(mycfgio); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - if (my_module.io[j] > GPIO_NONE) { - Settings.user_template.gp.io[i] = my_module.io[j]; - } - j++; - } - } - } - else { - if (JsonTemplate(XdrvMailbox.data)) { - if (USER_MODULE == Settings.module) { restart_flag = 2; } - } else { - ResponseCmndChar(D_JSON_INVALID_JSON); - error = true; - } - } - if (!error) { TemplateJson(); } -} - -void CmndPwm(void) -{ - if (pwm_present && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_PWMS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= Settings.pwm_range) && (pin[GPIO_PWM1 + XdrvMailbox.index -1] < 99)) { - Settings.pwm_value[XdrvMailbox.index -1] = XdrvMailbox.payload; - analogWrite(pin[GPIO_PWM1 + XdrvMailbox.index -1], bitRead(pwm_inverted, XdrvMailbox.index -1) ? Settings.pwm_range - XdrvMailbox.payload : XdrvMailbox.payload); - } - Response_P(PSTR("{")); - MqttShowPWMState(); - ResponseJsonEnd(); - } -} - -void CmndPwmfrequency(void) -{ - if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload >= PWM_MIN) && (XdrvMailbox.payload <= PWM_MAX))) { - Settings.pwm_frequency = (1 == XdrvMailbox.payload) ? PWM_FREQ : XdrvMailbox.payload; - analogWriteFreq(Settings.pwm_frequency); - } - ResponseCmndNumber(Settings.pwm_frequency); -} - -void CmndPwmrange(void) -{ - if ((1 == XdrvMailbox.payload) || ((XdrvMailbox.payload > 254) && (XdrvMailbox.payload < 1024))) { - Settings.pwm_range = (1 == XdrvMailbox.payload) ? PWM_RANGE : XdrvMailbox.payload; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (Settings.pwm_value[i] > Settings.pwm_range) { - Settings.pwm_value[i] = Settings.pwm_range; - } - } - analogWriteRange(Settings.pwm_range); - } - ResponseCmndNumber(Settings.pwm_range); -} - -void CmndButtonDebounce(void) -{ - if ((XdrvMailbox.payload > 39) && (XdrvMailbox.payload < 1001)) { - Settings.button_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.button_debounce); -} - -void CmndSwitchDebounce(void) -{ - if ((XdrvMailbox.payload > 39) && (XdrvMailbox.payload < 1001)) { - Settings.switch_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.switch_debounce); -} - -void CmndBaudrate(void) -{ - if (XdrvMailbox.payload >= 300) { - XdrvMailbox.payload /= 300; - uint32_t baudrate = (XdrvMailbox.payload & 0xFFFF) * 300; - SetSerialBaudrate(baudrate); - } - ResponseCmndNumber(Settings.baudrate * 300); -} - -void CmndSerialConfig(void) -{ - - - - - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.data_len < 3) { - if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) { - SetSerialConfig(XdrvMailbox.payload); - } - } - else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { - uint8_t serial_config = XdrvMailbox.payload -5; - - bool valid = true; - char parity = (XdrvMailbox.data[1] & 0xdf); - if ('E' == parity) { - serial_config += 0x08; - } - else if ('O' == parity) { - serial_config += 0x10; - } - else if ('N' != parity) { - valid = false; - } - - if ('2' == XdrvMailbox.data[2]) { - serial_config += 0x04; - } - else if ('1' != XdrvMailbox.data[2]) { - valid = false; - } - - if (valid) { - SetSerialConfig(serial_config); - } - } - } - ResponseCmndChar(GetSerialConfig().c_str()); -} - -void CmndSerialSend(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { - SetSeriallog(LOG_LEVEL_NONE); - Settings.flag.mqtt_serial = 1; - Settings.flag.mqtt_serial_raw = (XdrvMailbox.index > 3) ? 1 : 0; - if (XdrvMailbox.data_len > 0) { - if (1 == XdrvMailbox.index) { - Serial.printf("%s\n", XdrvMailbox.data); - } - else if (2 == XdrvMailbox.index || 4 == XdrvMailbox.index) { - for (uint32_t i = 0; i < XdrvMailbox.data_len; i++) { - Serial.write(XdrvMailbox.data[i]); - } - } - else if (3 == XdrvMailbox.index) { - uint32_t dat_len = XdrvMailbox.data_len; - Serial.printf("%s", Unescape(XdrvMailbox.data, &dat_len)); - } - else if (5 == XdrvMailbox.index) { - SerialSendRaw(RemoveSpace(XdrvMailbox.data)); - } - ResponseCmndDone(); - } - } -} - -void CmndSerialDelimiter(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.payload < 256)) { - if (XdrvMailbox.payload > 0) { - Settings.serial_delimiter = XdrvMailbox.payload; - } else { - uint32_t dat_len = XdrvMailbox.data_len; - Unescape(XdrvMailbox.data, &dat_len); - Settings.serial_delimiter = XdrvMailbox.data[0]; - } - } - ResponseCmndNumber(Settings.serial_delimiter); -} - -void CmndSyslog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - SetSyslog(XdrvMailbox.payload); - } - Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.syslog_level, syslog_level); -} - -void CmndLoghost(void) -{ - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_SYSLOG_HOST, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data); - } - ResponseCmndChar(SettingsText(SET_SYSLOG_HOST)); -} - -void CmndLogport(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { - Settings.syslog_port = (1 == XdrvMailbox.payload) ? SYS_LOG_PORT : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.syslog_port); -} - -void CmndIpAddress(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - uint32_t address; - if (ParseIp(&address, XdrvMailbox.data)) { - Settings.ip_address[XdrvMailbox.index -1] = address; - - } - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); - Response_P(S_JSON_COMMAND_INDEX_SVALUE_SVALUE, XdrvMailbox.command, XdrvMailbox.index, IPAddress(Settings.ip_address[XdrvMailbox.index -1]).toString().c_str(), (1 == XdrvMailbox.index) ? stemp1:""); - } -} - -void CmndNtpServer(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_NTP_SERVERS)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_NTPSERVER1, MAX_NTP_SERVERS); - } else { - uint32_t ntp_server = SET_NTPSERVER1 + XdrvMailbox.index -1; - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(ntp_server, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? NTP_SERVER1 : (2 == XdrvMailbox.index) ? NTP_SERVER2 : NTP_SERVER3 : XdrvMailbox.data); - SettingsUpdateText(ntp_server, ReplaceCommaWithDot(SettingsText(ntp_server))); - - ntp_force_sync = true; - } - ResponseCmndIdxChar(SettingsText(ntp_server)); - } - } -} - -void CmndAp(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - switch (XdrvMailbox.payload) { - case 0: - Settings.sta_active ^= 1; - break; - case 1: - case 2: - Settings.sta_active = XdrvMailbox.payload -1; - } - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active)); -} - -void CmndSsid(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SSIDS)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_STASSID1, MAX_SSIDS); - } else { - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_STASSID1 + XdrvMailbox.index -1, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; - } - ResponseCmndIdxChar(SettingsText(SET_STASSID1 + XdrvMailbox.index -1)); - } - } -} - -void CmndPassword(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.data_len > 4) || (SC_CLEAR == Shortcut()) || (SC_DEFAULT == Shortcut())) { - SettingsUpdateText(SET_STAPWD1 + XdrvMailbox.index -1, - (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data); - Settings.sta_active = XdrvMailbox.index -1; - restart_flag = 2; - ResponseCmndIdxChar(SettingsText(SET_STAPWD1 + XdrvMailbox.index -1)); - } else { - Response_P(S_JSON_COMMAND_INDEX_ASTERISK, XdrvMailbox.command, XdrvMailbox.index); - } - } -} - -void CmndHostname(void) -{ - if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0)) { - SettingsUpdateText(SET_HOSTNAME, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - } - restart_flag = 2; - } - ResponseCmndChar(SettingsText(SET_HOSTNAME)); -} - -void CmndWifiConfig(void) -{ - if ((XdrvMailbox.payload >= WIFI_RESTART) && (XdrvMailbox.payload < MAX_WIFI_OPTION)) { - if ((EX_WIFI_SMARTCONFIG == XdrvMailbox.payload) || (EX_WIFI_WPSCONFIG == XdrvMailbox.payload)) { - XdrvMailbox.payload = WIFI_MANAGER; - } - Settings.sta_config = XdrvMailbox.payload; - wifi_state_flag = Settings.sta_config; - if (WifiState() > WIFI_RESTART) { - restart_flag = 2; - } - } - char stemp1[TOPSZ]; - Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings.sta_config, GetTextIndexed(stemp1, sizeof(stemp1), Settings.sta_config, kWifiConfig)); -} - -void CmndFriendlyname(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_FRIENDLYNAMES)) { - if (!XdrvMailbox.usridx) { - ResponseCmndAll(SET_FRIENDLYNAME1, MAX_FRIENDLYNAMES); - } else { - if (XdrvMailbox.data_len > 0) { - char stemp1[TOPSZ]; - if (1 == XdrvMailbox.index) { - snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME)); - } else { - snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); - } - SettingsUpdateText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data); - } - ResponseCmndIdxChar(SettingsText(SET_FRIENDLYNAME1 + XdrvMailbox.index -1)); - } - } -} - -void CmndSwitchMode(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SWITCHES)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_SWITCH_OPTION)) { - Settings.switchmode[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.switchmode[XdrvMailbox.index-1]); - } -} - -void CmndInterlock(void) -{ - - uint32_t max_relays = devices_present; - if (light_type) { max_relays--; } - if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; } - if (max_relays > 1) { - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } - char *group; - char *q; - uint32_t group_index = 0; - power_t relay_mask = 0; - for (group = strtok_r(XdrvMailbox.data, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(nullptr, " ", &q)) { - char *str; - char *p; - for (str = strtok_r(group, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { - int pbit = atoi(str); - if ((pbit > 0) && (pbit <= max_relays)) { - pbit--; - if (!bitRead(relay_mask, pbit)) { - bitSet(relay_mask, pbit); - bitSet(Settings.interlock[group_index], pbit); - } - } - } - group_index++; - } - for (uint32_t i = 0; i < group_index; i++) { - uint32_t minimal_bits = 0; - for (uint32_t j = 0; j < max_relays; j++) { - if (bitRead(Settings.interlock[i], j)) { minimal_bits++; } - } - if (minimal_bits < 2) { Settings.interlock[i] = 0; } - } - } else { - Settings.flag.interlock = XdrvMailbox.payload &1; - if (Settings.flag.interlock) { - SetDevicePower(power, SRC_IGNORE); - } - } -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - ShutterInit(); - } -#endif - } - Response_P(PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); - uint32_t anygroup = 0; - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - if (Settings.interlock[i]) { - anygroup++; - ResponseAppend_P(PSTR("%s"), (anygroup > 1) ? " " : ""); - uint32_t anybit = 0; - power_t mask = 1; - for (uint32_t j = 0; j < max_relays; j++) { - if (Settings.interlock[i] & mask) { - anybit++; - ResponseAppend_P(PSTR("%s%d"), (anybit > 1) ? "," : "", j +1); - } - mask <<= 1; - } - } - } - if (!anygroup) { - for (uint32_t j = 1; j <= max_relays; j++) { - ResponseAppend_P(PSTR("%s%d"), (j > 1) ? "," : "", j); - } - } - ResponseAppend_P(PSTR("\"}")); - } else { - Settings.flag.interlock = 0; - ResponseCmndStateText(Settings.flag.interlock); - } -} - -void CmndTeleperiod(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.tele_period = (1 == XdrvMailbox.payload) ? TELE_PERIOD : XdrvMailbox.payload; - if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; - tele_period = Settings.tele_period; - } - ResponseCmndNumber(Settings.tele_period); -} - -void CmndReset(void) -{ - switch (XdrvMailbox.payload) { - case 1: - restart_flag = 211; - ResponseCmndChar(D_JSON_RESET_AND_RESTARTING); - break; - case 2 ... 6: - restart_flag = 210 + XdrvMailbox.payload; - Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); - break; - case 99: - Settings.bootcount = 0; - Settings.bootcount_reset_time = 0; - ResponseCmndDone(); - break; - default: - ResponseCmndChar(D_JSON_ONE_TO_RESET); - } -} - -void CmndTime(void) -{ - - - - - - - - uint32_t format = Settings.flag2.time_format; - if (XdrvMailbox.data_len > 0) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { - Settings.flag2.time_format = XdrvMailbox.payload -1; - format = Settings.flag2.time_format; - } else { - format = 1; - RtcSetTime(XdrvMailbox.payload); - } - } - mqtt_data[0] = '\0'; - ResponseAppendTimeFormat(format); - ResponseJsonEnd(); -} - -void CmndTimezone(void) -{ - if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.payload >= -13)) { - Settings.timezone = XdrvMailbox.payload; - Settings.timezone_minutes = 0; - if (XdrvMailbox.payload < 15) { - char *p = strtok (XdrvMailbox.data, ":"); - if (p) { - p = strtok (nullptr, ":"); - if (p) { - Settings.timezone_minutes = strtol(p, nullptr, 10); - if (Settings.timezone_minutes > 59) { Settings.timezone_minutes = 59; } - } - } - } else { - Settings.timezone = 99; - } - ntp_force_sync = true; - } - if (99 == Settings.timezone) { - ResponseCmndNumber(Settings.timezone); - } else { - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%+03d:%02d"), Settings.timezone, Settings.timezone_minutes); - ResponseCmndChar(stemp1); - } -} - -void CmndTimeStdDst(uint32_t ts) -{ - - if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - uint32_t tpos = 0; - int value = 0; - char *p = XdrvMailbox.data; - char *q = p; - while (p && (tpos < 7)) { - if (p > q) { - if (1 == tpos) { Settings.tflag[ts].hemis = value &1; } - if (2 == tpos) { Settings.tflag[ts].week = (value < 0) ? 0 : (value > 4) ? 4 : value; } - if (3 == tpos) { Settings.tflag[ts].month = (value < 1) ? 1 : (value > 12) ? 12 : value; } - if (4 == tpos) { Settings.tflag[ts].dow = (value < 1) ? 1 : (value > 7) ? 7 : value; } - if (5 == tpos) { Settings.tflag[ts].hour = (value < 0) ? 0 : (value > 23) ? 23 : value; } - if (6 == tpos) { Settings.toffset[ts] = (value < -900) ? -900 : (value > 900) ? 900 : value; } - } - p = Trim(p); - if (tpos && (*p == ',')) { p++; } - p = Trim(p); - q = p; - value = strtol(p, &p, 10); - tpos++; - } - ntp_force_sync = true; - } else { - if (0 == XdrvMailbox.payload) { - if (0 == ts) { - SettingsResetStd(); - } else { - SettingsResetDst(); - } - } - ntp_force_sync = true; - } - } - Response_P(PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), - XdrvMailbox.command, Settings.tflag[ts].hemis, Settings.tflag[ts].week, Settings.tflag[ts].month, Settings.tflag[ts].dow, Settings.tflag[ts].hour, Settings.toffset[ts]); -} - -void CmndTimeStd(void) -{ - CmndTimeStdDst(0); -} - -void CmndTimeDst(void) -{ - CmndTimeStdDst(1); -} - -void CmndAltitude(void) -{ - if ((XdrvMailbox.data_len > 0) && ((XdrvMailbox.payload >= -30000) && (XdrvMailbox.payload <= 30000))) { - Settings.altitude = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.altitude); -} - -void CmndLedPower(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { - if (99 == pin[GPIO_LEDLNK]) { XdrvMailbox.index = 1; } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - Settings.ledstate &= 8; - uint32_t mask = 1 << (XdrvMailbox.index -1); - switch (XdrvMailbox.payload) { - case 0: - led_power &= (0xFF ^ mask); - Settings.ledstate = 0; - break; - case 1: - led_power |= mask; - Settings.ledstate = 8; - break; - case 2: - led_power ^= mask; - Settings.ledstate ^= 8; - break; - } - blinks = 0; - if (99 == pin[GPIO_LEDLNK]) { - SetLedPower(Settings.ledstate &8); - } else { - SetLedPowerIdx(XdrvMailbox.index -1, (led_power & mask)); - } - } - bool state = bitRead(led_power, XdrvMailbox.index -1); - if (99 == pin[GPIO_LEDLNK]) { - state = bitRead(Settings.ledstate, 3); - } - ResponseCmndIdxChar(GetStateText(state)); - } -} - -void CmndLedState(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_LED_OPTION)) { - Settings.ledstate = XdrvMailbox.payload; - if (!Settings.ledstate) { - SetLedPowerAll(0); - SetLedLink(0); - } - } - ResponseCmndNumber(Settings.ledstate); -} - -void CmndLedMask(void) -{ - if (XdrvMailbox.data_len > 0) { - Settings.ledmask = XdrvMailbox.payload; - } - char stemp1[TOPSZ]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d (0x%04X)"), Settings.ledmask, Settings.ledmask); - ResponseCmndChar(stemp1); -} - -void CmndWifiPower(void) -{ - if (XdrvMailbox.data_len > 0) { - Settings.wifi_output_power = (uint8_t)(CharToFloat(XdrvMailbox.data) * 10); - if (Settings.wifi_output_power > 205) { - Settings.wifi_output_power = 205; - } - WifiSetOutputPower(); - } - ResponseCmndChar(WifiGetOutputPower().c_str()); -} - -#ifdef USE_I2C -void CmndI2cScan(void) -{ - if (i2c_flg) { - I2cScan(mqtt_data, sizeof(mqtt_data)); - } -} - -void CmndI2cDriver(void) -{ - if (XdrvMailbox.index < MAX_I2C_DRIVERS) { - if (XdrvMailbox.payload >= 0) { - bitWrite(Settings.i2c_drivers[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - restart_flag = 2; - } - } - Response_P(PSTR("{\"" D_CMND_I2CDRIVER "\":")); - I2cDriverState(); - ResponseJsonEnd(); -} -#endif - -#ifdef USE_DEVICE_GROUPS -void CmndDevGroupShare(void) -{ - uint32_t parm[2] = { Settings.device_group_share_in, Settings.device_group_share_out }; - ParseParameters(2, parm); - Settings.device_group_share_in = parm[0]; - Settings.device_group_share_out = parm[1]; - Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":%x,\"Out\":%x}}"), Settings.device_group_share_in, Settings.device_group_share_out); -} -#endif - -void CmndSensor(void) -{ - XsnsCall(FUNC_COMMAND_SENSOR); -} - -void CmndDriver(void) -{ - XdrvCall(FUNC_COMMAND_DRIVER); -} -# 1 "S:/Development/Tasmota/tasmota/support_crash_recorder.ino" -# 20 "S:/Development/Tasmota/tasmota/support_crash_recorder.ino" -const uint32_t crash_magic = 0x53415400; -const uint32_t crash_rtc_offset = 32; -const uint32_t crash_dump_max_len = 31; - - - - - - -extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) -{ - uint32_t addr_written = 0; - uint32_t value; - - for (uint32_t i = stack; i < stack_end; i += 4) { - value = *((uint32_t*) i); - if ((value >= 0x40000000) && (value < 0x40300000)) { - ESP.rtcUserMemoryWrite(crash_rtc_offset + addr_written, (uint32_t*)&value, sizeof(value)); - addr_written++; - if (addr_written >= crash_dump_max_len) { break; } - } - } - value = crash_magic + addr_written; - ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); -} - - -void CmndCrash(void) -{ - volatile uint32_t dummy; - dummy = *((uint32_t*) 0x00000000); -} - - -void CmndWDT(void) -{ - volatile uint32_t dummy = 0; - while (1) { - dummy++; - } -} - - -void CmndBlockedLoop(void) -{ - while (1) { - delay(1000); - } -} - - -void CrashDumpClear(void) -{ - uint32_t value = 0; - ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); -} - - - - - -bool CrashFlag(void) -{ - return ((ResetReason() == REASON_EXCEPTION_RST) || (ResetReason() == REASON_SOFT_WDT_RST) || oswatch_blocked_loop); -} - -void CrashDump(void) -{ - ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""), - resetInfo.exccause, - GetResetReason().c_str(), - resetInfo.epc1, - resetInfo.epc2, - resetInfo.epc3, - resetInfo.excvaddr, - resetInfo.depc); - - uint32_t value; - ESP.rtcUserMemoryRead(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); - if (crash_magic == (value & 0xFFFFFF00)) { - ResponseAppend_P(PSTR(",\"CallChain\":[")); - uint32_t count = value & 0x3F; - for (uint32_t i = 0; i < count; i++) { - ESP.rtcUserMemoryRead(crash_rtc_offset +i, (uint32_t*)&value, sizeof(value)); - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"%08x\""), value); - } - ResponseAppend_P(PSTR("]")); - } - - ResponseJsonEnd(); -} -# 1 "S:/Development/Tasmota/tasmota/support_device_groups.ino" -# 23 "S:/Development/Tasmota/tasmota/support_device_groups.ino" -#ifdef USE_DEVICE_GROUPS - - - -extern bool udp_connected; - -struct device_group_member { - struct device_group_member * flink; - IPAddress ip_address; - uint32_t timeout_time; - uint16_t received_sequence; - uint16_t acked_sequence; -}; - -struct device_group { - uint32_t next_ack_check_time; - uint16_t last_full_status_sequence; - uint16_t message_length; - uint8_t message_header_length; - uint8_t initial_status_requests_remaining; - bool local; - char group_name[TOPSZ]; - char message[128]; - uint8_t group_member_count; - struct device_group_member * device_group_members; -}; - -struct device_group * device_groups; -uint16_t outgoing_sequence = 0; -bool device_groups_initialized = false; -bool device_groups_initialization_failed = false; -bool building_status_message = false; -bool processing_remote_device_message = false; -bool waiting_for_acks; -bool udp_was_connected = false; - -void DeviceGroupsInit(void) -{ - - device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group)); - if (device_groups == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count); - device_groups_initialization_failed = true; - return; - } - - for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { - struct device_group * device_group = &device_groups[device_group_index]; - strcpy(device_group->group_name, SettingsText((device_group_index == 0 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + device_group_index - 1))); - device_group->message_header_length = sprintf_P(device_group->message, PSTR("%s%s HTTP/1.1\n\n"), kDeviceGroupMessage, device_group->group_name); - device_group->last_full_status_sequence = -1; - } - - device_groups[0].local = true; - - - if (!Settings.device_group_share_in && !Settings.device_group_share_out) { - Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff; - } - - device_groups_initialized = true; -} - -char * IPAddressToString(const IPAddress& ip_address) -{ - static char buffer[16]; - sprintf_P(buffer, PSTR("%u.%u.%u.%u"), ip_address[0], ip_address[1], ip_address[2], ip_address[3]); - return buffer; -} - - -bool DeviceGroupItemShared(bool incoming, uint8_t item) -{ - uint8_t mask = 0; - switch (item) { - case DGR_ITEM_LIGHT_BRI: - mask = DGR_SHARE_LIGHT_BRI; - break; - case DGR_ITEM_POWER: - mask = DGR_SHARE_POWER; - break; - case DGR_ITEM_LIGHT_SCHEME: - mask = DGR_SHARE_LIGHT_SCHEME; - break; - case DGR_ITEM_LIGHT_FIXED_COLOR: - case DGR_ITEM_LIGHT_CHANNELS: - mask = DGR_SHARE_LIGHT_COLOR; - break; - case DGR_ITEM_LIGHT_FADE: - case DGR_ITEM_LIGHT_SPEED: - mask = DGR_SHARE_LIGHT_FADE; - break; - case DGR_ITEM_BRI_MIN: - mask = DGR_SHARE_BRI_MIN; - break; - } - return (!mask || ((incoming ? Settings.device_group_share_in : Settings.device_group_share_out) & mask)); -} - -void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * label) -{ - for (int attempt = 1; attempt <= 5; attempt++) { - if (PortUdp.beginPacket(ip, 1900)) { - PortUdp.write(packet, len); - if (PortUdp.endPacket()) return; - } - delay(10); - } - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error sending %s packet"), label); -} - -void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...) -{ - - if (!Settings.flag4.device_groups_enabled) return; - - - if (!udp_connected) return; - - - if (processing_remote_device_message) return; - - - device_group * device_group = &device_groups[device_group_index]; - - - if (device_group->initial_status_requests_remaining) return; - - - - - char * message_ptr = &device_group->message[device_group->message_header_length]; - if (message_type == DGR_MSGTYP_FULL_STATUS) { - - - - building_status_message = true; - - - if (!++outgoing_sequence) outgoing_sequence = 1; -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s full status packet"), device_group->group_name); -#endif - device_group->message_length = 0; - SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power); - XdrvMailbox.command_code = DGR_ITEM_STATUS; - XdrvCall(FUNC_DEVICE_GROUP_REQUEST); - building_status_message = false; - - - if (!device_group->message_length) { - if (!--outgoing_sequence) outgoing_sequence = -1; - return; - } - device_group->last_full_status_sequence = outgoing_sequence; - - - *(message_ptr + 2) |= DGR_FLAG_FULL_STATUS; - } - - else { - bool shared; - uint8_t item; - uint32_t value; - uint8_t * value_ptr; - va_list ap; - -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Building device group %s packet"), device_group->group_name); -#endif - uint16_t original_sequence = outgoing_sequence; - if (!building_status_message && message_type != DGR_MSGTYP_PARTIAL_UPDATE && !++outgoing_sequence) outgoing_sequence = 1; - *message_ptr++ = outgoing_sequence & 0xff; - *message_ptr++ = outgoing_sequence >> 8; - - value = 0; - if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) - value |= DGR_FLAG_MORE_TO_COME; - else if (message_type == DGR_MSGTYP_UPDATE_DIRECT) - value |= DGR_FLAG_DIRECT; -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">sequence=%u, flags=%u"), outgoing_sequence, value); -#endif - *message_ptr++ = value & 0xff; - *message_ptr++ = value >> 8; - char * first_item_ptr = message_ptr; - - - - - - if (device_group->message_length) { - uint8_t item_array[32]; - int item_index = 0; - int kept_item_count = 0; - - - va_start(ap, message_type); - while ((item = va_arg(ap, int))) { - item_array[item_index++] = item; - if (item <= DGR_ITEM_MAX_32BIT) - va_arg(ap, int); - else if (item <= DGR_ITEM_MAX_STRING) - va_arg(ap, char *); - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: - va_arg(ap, uint8_t *) ; - break; - } - } - } - va_end(ap); - item_array[item_index] = 0; - - - - char * previous_message_ptr = message_ptr; - while (item = *previous_message_ptr++) { - - - for (item_index = 0; item_array[item_index]; item_index++) { - if (item_array[item_index] == item) break; - } - - - if (item_array[item_index]) { - if (item <= DGR_ITEM_MAX_32BIT) { - previous_message_ptr++; - if (item > DGR_ITEM_MAX_8BIT) { - previous_message_ptr++; - if (item > DGR_ITEM_MAX_16BIT) { - previous_message_ptr++; - previous_message_ptr++; - } - } - } - else if (item <= DGR_ITEM_MAX_STRING) - previous_message_ptr += *previous_message_ptr++; - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: - previous_message_ptr += 5; - break; - } - } - } - - - else { - *message_ptr++ = item; - if (item <= DGR_ITEM_MAX_32BIT) { - *message_ptr++ = *previous_message_ptr++; - if (item > DGR_ITEM_MAX_8BIT) { - *message_ptr++ = *previous_message_ptr++; - if (item > DGR_ITEM_MAX_16BIT) { - *message_ptr++ = *previous_message_ptr++; - *message_ptr++ = *previous_message_ptr++; - } - } - } - else if (item <= DGR_ITEM_MAX_STRING) { - *message_ptr++ = value = *previous_message_ptr++; - memmove(message_ptr, previous_message_ptr, value); - previous_message_ptr += value; - message_ptr += value; - } - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: - memmove(message_ptr, previous_message_ptr, 5); - previous_message_ptr += 5; - message_ptr += 5; - break; - } - } - kept_item_count++; - } - } -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%u items carried over from previous update"), kept_item_count); -#endif - } - - - va_start(ap, message_type); - while ((item = va_arg(ap, int))) { - shared = DeviceGroupItemShared(false, item); - if (shared) *message_ptr++ = item; - if (item <= DGR_ITEM_MAX_32BIT) { - value = va_arg(ap, int); - if (shared) { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u"), item, value); -#endif - *message_ptr++ = value & 0xff; - if (item > DGR_ITEM_MAX_8BIT) { - value >>= 8; - *message_ptr++ = value & 0xff; - } - if (item > DGR_ITEM_MAX_16BIT) { - value >>= 8; - *message_ptr++ = value & 0xff; - *message_ptr++ = value >> 8; - } - } - } - else if (item <= DGR_ITEM_MAX_STRING) { - value_ptr = va_arg(ap, uint8_t *); - if (shared) { - value = strlen((const char *)value_ptr); -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%s"), item, value_ptr); -#endif - *message_ptr++ = value; - memcpy(message_ptr, value_ptr, value); - message_ptr += value; - } - } - else { - switch (item) { - case DGR_ITEM_LIGHT_CHANNELS: - value_ptr = va_arg(ap, uint8_t *); - if (shared) { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(">item=%u, value=%u,%u,%u,%u,%u"), item, *value_ptr, *(value_ptr + 1), *(value_ptr + 2), *(value_ptr + 3), *(value_ptr + 4)); -#endif - memmove(message_ptr, value_ptr, 5); - message_ptr += 5; - } - break; - } - } - } - va_end(ap); - - - - if (message_ptr == first_item_ptr) { - outgoing_sequence = original_sequence; - return; - } - - - *message_ptr++ = 0; - device_group->message_length = message_ptr - device_group->message; - - - if (building_status_message || message_type == DGR_MSGTYP_PARTIAL_UPDATE) return; - } - - -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8); -#endif - SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, PSTR("Multicast")); - device_group->next_ack_check_time = millis() + 100; - - if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) { - for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member != nullptr; device_group_member = device_group_member->flink) { - device_group_member->acked_sequence = outgoing_sequence; - } - } - else { - waiting_for_acks = true; - } -} - -void ProcessDeviceGroupMessage(char * packet, int packet_length) -{ - - char * message_group_name = packet + sizeof(DEVICE_GROUP_MESSAGE) - 1; - char * message_ptr = strchr(message_group_name, ' '); - if (message_ptr == nullptr) return; - *message_ptr = 0; - - - struct device_group * device_group; - uint32_t device_group_index = 0; - for (;;) { - device_group = &device_groups[device_group_index]; - if (!strcmp(message_group_name, device_group->group_name)) break; - if (++device_group_index >= device_group_count) return; - } - *message_ptr++ = ' '; - - - IPAddress remote_ip = PortUdp.remoteIP(); - struct device_group_member * * flink = &device_group->device_group_members; - struct device_group_member * device_group_member; - for (;;) { - device_group_member = *flink; - if (!device_group_member) { - device_group_member = (struct device_group_member *)calloc(1, sizeof(struct device_group_member)); - if (device_group_member == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating device group member block")); - return; - } -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: adding member %s (%p)"), IPAddressToString(remote_ip), device_group_member); -#endif - device_group_member->ip_address = remote_ip; - *flink = device_group_member; - break; - } - else if (device_group_member->ip_address == remote_ip) { - break; - } - flink = &device_group_member->flink; - } - - - message_ptr = strstr_P(message_ptr, PSTR("\n\n")); - if (message_ptr == nullptr) return; - message_ptr += 2; - - bool light_fade; - uint16_t flags; - uint16_t item; - uint16_t message_sequence; - int32_t value; - - - if (packet_length - (message_ptr - packet) < 4) goto badmsg; - message_sequence = *message_ptr++; - message_sequence |= *message_ptr++ << 8; - flags = *message_ptr++; - flags |= *message_ptr++ << 8; -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Received device group %s packet from %s: sequence=%u, flags=%u"), device_group->group_name, IPAddressToString(remote_ip), message_sequence, flags); -#endif - - - - if (flags == DGR_FLAG_ACK) { - if (message_sequence > device_group_member->acked_sequence || device_group_member->acked_sequence - message_sequence < 64536) { - device_group_member->acked_sequence = message_sequence; - } - device_group_member->timeout_time = 0; -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("acked_sequence != device_group->last_full_status_sequence) { - _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); - } -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("received_sequence && device_group_member->received_sequence - message_sequence > 64536) { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("received_sequence = message_sequence; - - - - processing_remote_device_message = true; -# 512 "S:/Development/Tasmota/tasmota/support_device_groups.ino" - XdrvMailbox.command = nullptr; - XdrvMailbox.index = flags; - light_fade = Settings.light_fade; - if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) Settings.light_fade = false; - - for (;;) { - if (packet_length - (message_ptr - packet) < 1) goto badmsg; - item = *message_ptr++; - if (!item) break; - -#ifdef DEVICE_GROUPS_DEBUG - switch (item) { - case DGR_ITEM_LIGHT_FADE: - case DGR_ITEM_LIGHT_SPEED: - case DGR_ITEM_LIGHT_BRI: - case DGR_ITEM_LIGHT_SCHEME: - case DGR_ITEM_LIGHT_FIXED_COLOR: - case DGR_ITEM_BRI_MIN: - case DGR_ITEM_BRI_PRESET_LOW: - case DGR_ITEM_BRI_PRESET_HIGH: - case DGR_ITEM_BRI_POWER_ON: - case DGR_ITEM_POWER: - case DGR_ITEM_LIGHT_CHANNELS: - break; - default: - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip)); - } -#endif - - XdrvMailbox.command_code = item; - if (item <= DGR_ITEM_LAST_32BIT) { - value = *message_ptr++; - if (item > DGR_ITEM_MAX_8BIT) { - value |= *message_ptr++ << 8; - if (item > DGR_ITEM_MAX_16BIT) { - value |= *message_ptr++ << 16; - value |= *message_ptr++ << 24; - } - } - else if (item == DGR_ITEM_LIGHT_FADE) { - light_fade = value; - } -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("= packet_length - (message_ptr - packet)) goto badmsg; -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("message[device_group->message_header_length]; - if (!++outgoing_sequence) outgoing_sequence = 1; - *message_ptr++ = outgoing_sequence & 0xff; - *message_ptr++ = outgoing_sequence >> 8; - *message_ptr++ = DGR_FLAG_RESET | DGR_FLAG_STATUS_REQUEST; - *message_ptr++ = 0; - device_group->message_length = message_ptr - device_group->message; - device_group->initial_status_requests_remaining = 5; - device_group->next_ack_check_time = millis() + 1000; - } - - waiting_for_acks = true; - } - - if (device_groups_initialization_failed) return; - - if (waiting_for_acks) { - uint32_t now = millis(); - waiting_for_acks = false; - for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) { - device_group * device_group = &device_groups[device_group_index]; - if (device_group->next_ack_check_time) { - if (device_group->next_ack_check_time <= now) { - if (device_group->initial_status_requests_remaining) { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending initial status request for group %s"), device_group->group_name); -#endif - if (--device_group->initial_status_requests_remaining) { - SendDeviceGroupPacket(IPAddress(239,255,255,250), device_group->message, device_group->message_length, PSTR("Initial")); - device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; - device_group->next_ack_check_time = now + 200; - waiting_for_acks = true; - } - else { - device_group->next_ack_check_time = 0; - _SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_FULL_STATUS); - } - } - else { - bool acked = true; - struct device_group_member ** flink = &device_group->device_group_members; - struct device_group_member * device_group_member; - while ((device_group_member = *flink)) { - if (device_group_member->acked_sequence != outgoing_sequence) { - - if (device_group_member->timeout_time && device_group_member->timeout_time < now) { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: removing member %s (%p)"), IPAddressToString(device_group_member->ip_address), device_group_member); -#endif - *flink = device_group_member->flink; - free(device_group_member); - } - else { -#ifdef DEVICE_GROUPS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via unicast to %s, sequence %u, last message acked=%u"), device_group->message_length, device_group->group_name, IPAddressToString(device_group_member->ip_address), outgoing_sequence, device_group_member->acked_sequence); -#endif - SendDeviceGroupPacket(device_group_member->ip_address, device_group->message, device_group->message_length, PSTR("Unicast")); - if (!device_group_member->timeout_time) device_group_member->timeout_time = now + 15000; - acked = false; - flink = &device_group_member->flink; - } - } - else { - flink = &device_group_member->flink; - } - } - if (acked) { - device_group->next_ack_check_time = 0; - device_group->message_length = 0; - } - else { - device_group->next_ack_check_time = now + 500; - waiting_for_acks = true; - } - } - } - else { - waiting_for_acks = true; - } - } - } - } - } - else { - udp_was_connected = false; - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/support_esptool.ino" -# 20 "S:/Development/Tasmota/tasmota/support_esptool.ino" -#define USE_ESPTOOL -#ifdef USE_ESPTOOL - - - - - - - -#define READ_REG(REG) (*((volatile uint32_t *)(REG))) -#define WRITE_REG(REG,VAL) *((volatile uint32_t *)(REG)) = (VAL) -#define REG_SET_MASK(reg,mask) WRITE_REG((reg), (READ_REG(reg)|(mask))) - -#define SPI_BASE_REG 0x60000200 - -#define SPI_CMD_REG (SPI_BASE_REG + 0x00) -#define SPI_FLASH_RDSR (1<<27) -#define SPI_FLASH_SE (1<<24) -#define SPI_FLASH_BE (1<<23) -#define SPI_FLASH_WREN (1<<30) - -#define SPI_ADDR_REG (SPI_BASE_REG + 0x04) -#define SPI_CTRL_REG (SPI_BASE_REG + 0x08) -#define SPI_RD_STATUS_REG (SPI_BASE_REG + 0x10) -#define SPI_W0_REG (SPI_BASE_REG + 0x40) -#define SPI_EXT2_REG (SPI_BASE_REG + 0xF8) - -#define SPI_ST 0x7 - - -#define SECTORS_PER_BLOCK (FLASH_BLOCK_SIZE / SPI_FLASH_SEC_SIZE) - - -static const uint32_t STATUS_WIP_BIT = (1 << 0); - - -inline static void spi_wait_ready(void) -{ - while((READ_REG(SPI_EXT2_REG) & SPI_ST)) { } -} - - - -static bool spiflash_is_ready(void) -{ - spi_wait_ready(); - WRITE_REG(SPI_RD_STATUS_REG, 0); - WRITE_REG(SPI_CMD_REG, SPI_FLASH_RDSR); - while(READ_REG(SPI_CMD_REG) != 0) { } - uint32_t status_value = READ_REG(SPI_RD_STATUS_REG); - return (status_value & STATUS_WIP_BIT) == 0; -} - -static void spi_write_enable(void) -{ - while(!spiflash_is_ready()) { } - WRITE_REG(SPI_CMD_REG, SPI_FLASH_WREN); - while(READ_REG(SPI_CMD_REG) != 0) { } -} - -bool EsptoolEraseSector(uint32_t sector) -{ - spi_write_enable(); - spi_wait_ready(); - - WRITE_REG(SPI_ADDR_REG, (sector * SPI_FLASH_SEC_SIZE) & 0xffffff); - WRITE_REG(SPI_CMD_REG, SPI_FLASH_SE); - while(READ_REG(SPI_CMD_REG) != 0) { } - while(!spiflash_is_ready()) { } - - return true; -} - -void EsptoolErase(uint32_t start_sector, uint32_t end_sector) -{ - int next_erase_sector = start_sector; - int remaining_erase_sector = end_sector - start_sector; - - while (remaining_erase_sector > 0) { - spi_write_enable(); - - uint32_t command = SPI_FLASH_SE; - uint32_t sectors_to_erase = 1; - if (remaining_erase_sector >= SECTORS_PER_BLOCK && - next_erase_sector % SECTORS_PER_BLOCK == 0) { - command = SPI_FLASH_BE; - sectors_to_erase = SECTORS_PER_BLOCK; - } - uint32_t addr = next_erase_sector * SPI_FLASH_SEC_SIZE; - - spi_wait_ready(); - WRITE_REG(SPI_ADDR_REG, addr & 0xffffff); - WRITE_REG(SPI_CMD_REG, command); - while(READ_REG(SPI_CMD_REG) != 0) { } - remaining_erase_sector -= sectors_to_erase; - next_erase_sector += sectors_to_erase; - - while (!spiflash_is_ready()) { } - yield(); - OsWatchLoop(); - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/support_features.ino" -# 24 "S:/Development/Tasmota/tasmota/support_features.ino" -void GetFeatures(void) -{ - feature_drv1 = 0x00000000; - -#ifdef USE_ENERGY_MARGIN_DETECTION - feature_drv1 |= 0x00000001; -#endif -#ifdef USE_LIGHT - feature_drv1 |= 0x00000002; -#endif -#ifdef USE_I2C - feature_drv1 |= 0x00000004; -#endif -#ifdef USE_SPI - feature_drv1 |= 0x00000008; -#endif -#ifdef USE_DISCOVERY - feature_drv1 |= 0x00000010; -#endif -#ifdef USE_ARDUINO_OTA - feature_drv1 |= 0x00000020; -#endif -#ifdef USE_MQTT_TLS - feature_drv1 |= 0x00000040; -#endif -#ifdef USE_WEBSERVER - feature_drv1 |= 0x00000080; -#endif -#ifdef WEBSERVER_ADVERTISE - feature_drv1 |= 0x00000100; -#endif -#ifdef USE_EMULATION_HUE - feature_drv1 |= 0x00000200; -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) - feature_drv1 |= 0x00000400; -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) - -#endif -#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) - -#endif -#ifdef MQTT_HOST_DISCOVERY - feature_drv1 |= 0x00002000; -#endif -#ifdef USE_ARILUX_RF - feature_drv1 |= 0x00004000; -#endif -#if defined(USE_LIGHT) && defined(USE_WS2812) - feature_drv1 |= 0x00008000; -#endif -#ifdef USE_WS2812_DMA - feature_drv1 |= 0x00010000; -#endif -#if defined(USE_IR_REMOTE) || defined(USE_IR_REMOTE_FULL) - feature_drv1 |= 0x00020000; -#endif -#ifdef USE_IR_HVAC - feature_drv1 |= 0x00040000; -#endif -#ifdef USE_IR_RECEIVE - feature_drv1 |= 0x00080000; -#endif -#ifdef USE_DOMOTICZ - feature_drv1 |= 0x00100000; -#endif -#ifdef USE_DISPLAY - feature_drv1 |= 0x00200000; -#endif -#ifdef USE_HOME_ASSISTANT - feature_drv1 |= 0x00400000; -#endif -#ifdef USE_SERIAL_BRIDGE - feature_drv1 |= 0x00800000; -#endif -#ifdef USE_TIMERS - feature_drv1 |= 0x01000000; -#endif -#ifdef USE_SUNRISE - feature_drv1 |= 0x02000000; -#endif -#ifdef USE_TIMERS_WEB - feature_drv1 |= 0x04000000; -#endif -#ifdef USE_RULES - feature_drv1 |= 0x08000000; -#endif -#ifdef USE_KNX - feature_drv1 |= 0x10000000; -#endif -#ifdef USE_WPS - feature_drv1 |= 0x20000000; -#endif -#ifdef USE_SMARTCONFIG - feature_drv1 |= 0x40000000; -#endif -#ifdef USE_ENERGY_POWER_LIMIT - feature_drv1 |= 0x80000000; -#endif - - - - feature_drv2 = 0x00000000; - -#ifdef USE_CONFIG_OVERRIDE - feature_drv2 |= 0x00000001; -#endif -#ifdef FIRMWARE_MINIMAL - feature_drv2 |= 0x00000002; -#endif -#ifdef FIRMWARE_SENSORS - feature_drv2 |= 0x00000004; -#endif -#ifdef FIRMWARE_CLASSIC - feature_drv2 |= 0x00000008; -#endif -#ifdef FIRMWARE_KNX_NO_EMULATION - feature_drv2 |= 0x00000010; -#endif -#ifdef USE_DISPLAY_MODES1TO5 - feature_drv2 |= 0x00000020; -#endif -#ifdef USE_DISPLAY_GRAPH - feature_drv2 |= 0x00000040; -#endif -#ifdef USE_DISPLAY_LCD - feature_drv2 |= 0x00000080; -#endif -#ifdef USE_DISPLAY_SSD1306 - feature_drv2 |= 0x00000100; -#endif -#ifdef USE_DISPLAY_MATRIX - feature_drv2 |= 0x00000200; -#endif -#ifdef USE_DISPLAY_ILI9341 - feature_drv2 |= 0x00000400; -#endif -#ifdef USE_DISPLAY_EPAPER_29 - feature_drv2 |= 0x00000800; -#endif -#ifdef USE_DISPLAY_SH1106 - feature_drv2 |= 0x00001000; -#endif -#ifdef USE_MP3_PLAYER - feature_drv2 |= 0x00002000; -#endif -#ifdef USE_PCA9685 - feature_drv2 |= 0x00004000; -#endif -#if defined(USE_LIGHT) && defined(USE_TUYA_MCU) - feature_drv2 |= 0x00008000; -#endif -#ifdef USE_RC_SWITCH - feature_drv2 |= 0x00010000; -#endif -#if defined(USE_LIGHT) && defined(USE_ARMTRONIX_DIMMERS) - feature_drv2 |= 0x00020000; -#endif -#if defined(USE_LIGHT) && defined(USE_SM16716) - feature_drv2 |= 0x00040000; -#endif -#ifdef USE_SCRIPT - feature_drv2 |= 0x00080000; -#endif -#ifdef USE_EMULATION_WEMO - feature_drv2 |= 0x00100000; -#endif -#ifdef USE_SONOFF_IFAN - feature_drv2 |= 0x00200000; -#endif -#ifdef USE_ZIGBEE - feature_drv2 |= 0x00400000; -#endif -#ifdef NO_EXTRA_4K_HEAP - feature_drv2 |= 0x00800000; -#endif -#ifdef VTABLES_IN_IRAM - feature_drv2 |= 0x01000000; -#endif -#ifdef VTABLES_IN_DRAM - feature_drv2 |= 0x02000000; -#endif -#ifdef VTABLES_IN_FLASH - feature_drv2 |= 0x04000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH - feature_drv2 |= 0x08000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY - feature_drv2 |= 0x10000000; -#endif -#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH - feature_drv2 |= 0x20000000; -#endif -#ifdef DEBUG_THEO - feature_drv2 |= 0x40000000; -#endif -#ifdef USE_DEBUG_DRIVER - feature_drv2 |= 0x80000000; -#endif - - - - feature_sns1 = 0x00000000; - -#ifdef USE_COUNTER - feature_sns1 |= 0x00000001; -#endif -#ifdef USE_ADC_VCC - feature_sns1 |= 0x00000002; -#endif -#ifdef USE_ENERGY_SENSOR - feature_sns1 |= 0x00000004; -#endif -#ifdef USE_PZEM004T - feature_sns1 |= 0x00000008; -#endif -#ifdef USE_DS18B20 - feature_sns1 |= 0x00000010; -#endif -#ifdef USE_DS18x20_LEGACY - feature_sns1 |= 0x00000020; -#endif -#ifdef USE_DS18x20 - feature_sns1 |= 0x00000040; -#endif -#ifdef USE_DHT - feature_sns1 |= 0x00000080; -#endif -#ifdef USE_SHT - feature_sns1 |= 0x00000100; -#endif -#ifdef USE_HTU - feature_sns1 |= 0x00000200; -#endif -#ifdef USE_BMP - feature_sns1 |= 0x00000400; -#endif -#ifdef USE_BME680 - feature_sns1 |= 0x00000800; -#endif -#ifdef USE_BH1750 - feature_sns1 |= 0x00001000; -#endif -#ifdef USE_VEML6070 - feature_sns1 |= 0x00002000; -#endif -#ifdef USE_ADS1115_I2CDEV - feature_sns1 |= 0x00004000; -#endif -#ifdef USE_ADS1115 - feature_sns1 |= 0x00008000; -#endif -#ifdef USE_INA219 - feature_sns1 |= 0x00010000; -#endif -#ifdef USE_SHT3X - feature_sns1 |= 0x00020000; -#endif -#ifdef USE_MHZ19 - feature_sns1 |= 0x00040000; -#endif -#ifdef USE_TSL2561 - feature_sns1 |= 0x00080000; -#endif -#ifdef USE_SENSEAIR - feature_sns1 |= 0x00100000; -#endif -#ifdef USE_PMS5003 - feature_sns1 |= 0x00200000; -#endif -#ifdef USE_MGS - feature_sns1 |= 0x00400000; -#endif -#ifdef USE_NOVA_SDS - feature_sns1 |= 0x00800000; -#endif -#ifdef USE_SGP30 - feature_sns1 |= 0x01000000; -#endif -#ifdef USE_SR04 - feature_sns1 |= 0x02000000; -#endif -#ifdef USE_SDM120 - feature_sns1 |= 0x04000000; -#endif -#ifdef USE_SI1145 - feature_sns1 |= 0x08000000; -#endif -#ifdef USE_SDM630 - feature_sns1 |= 0x10000000; -#endif -#ifdef USE_LM75AD - feature_sns1 |= 0x20000000; -#endif -#ifdef USE_APDS9960 - feature_sns1 |= 0x40000000; -#endif -#ifdef USE_TM1638 - feature_sns1 |= 0x80000000; -#endif - - - - feature_sns2 = 0x00000000; - -#ifdef USE_MCP230xx - feature_sns2 |= 0x00000001; -#endif -#ifdef USE_MPR121 - feature_sns2 |= 0x00000002; -#endif -#ifdef USE_CCS811 - feature_sns2 |= 0x00000004; -#endif -#ifdef USE_MPU6050 - feature_sns2 |= 0x00000008; -#endif -#ifdef USE_MCP230xx_OUTPUT - feature_sns2 |= 0x00000010; -#endif -#ifdef USE_MCP230xx_DISPLAYOUTPUT - feature_sns2 |= 0x00000020; -#endif -#ifdef USE_HLW8012 - feature_sns2 |= 0x00000040; -#endif -#ifdef USE_CSE7766 - feature_sns2 |= 0x00000080; -#endif -#ifdef USE_MCP39F501 - feature_sns2 |= 0x00000100; -#endif -#ifdef USE_PZEM_AC - feature_sns2 |= 0x00000200; -#endif -#ifdef USE_DS3231 - feature_sns2 |= 0x00000400; -#endif -#ifdef USE_HX711 - feature_sns2 |= 0x00000800; -#endif -#ifdef USE_PZEM_DC - feature_sns2 |= 0x00001000; -#endif -#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) - feature_sns2 |= 0x00002000; -#endif -#ifdef USE_MGC3130 - feature_sns2 |= 0x00004000; -#endif -#ifdef USE_RF_SENSOR - feature_sns2 |= 0x00008000; -#endif -#ifdef USE_THEO_V2 - feature_sns2 |= 0x00010000; -#endif -#ifdef USE_ALECTO_V2 - feature_sns2 |= 0x00020000; -#endif -#ifdef USE_AZ7798 - feature_sns2 |= 0x00040000; -#endif -#ifdef USE_MAX31855 - feature_sns2 |= 0x00080000; -#endif -#ifdef USE_PN532_HSU - feature_sns2 |= 0x00100000; -#endif -#ifdef USE_MAX44009 - feature_sns2 |= 0x00200000; -#endif -#ifdef USE_SCD30 - feature_sns2 |= 0x00400000; -#endif -#ifdef USE_HRE - feature_sns2 |= 0x00800000; -#endif -#ifdef USE_ADE7953 - feature_sns2 |= 0x01000000; -#endif -#ifdef USE_SPS30 - feature_sns2 |= 0x02000000; -#endif -#ifdef USE_VL53L0X - feature_sns2 |= 0x04000000; -#endif -#ifdef USE_MLX90614 - feature_sns2 |= 0x08000000; -#endif -#ifdef USE_MAX31865 - feature_sns2 |= 0x10000000; -#endif -#ifdef USE_CHIRP - feature_sns2 |= 0x20000000; -#endif -#ifdef USE_SOLAX_X1 - feature_sns2 |= 0x40000000; -#endif -#ifdef USE_PAJ7620 - feature_sns2 |= 0x80000000; -#endif - - - - feature5 = 0x00000000; - -#ifdef USE_BUZZER - feature5 |= 0x00000001; -#endif -#ifdef USE_RDM6300 - feature5 |= 0x00000002; -#endif -#ifdef USE_IBEACON - feature5 |= 0x00000004; -#endif -#ifdef USE_SML_M - feature5 |= 0x00000008; -#endif -#ifdef USE_INA226 - feature5 |= 0x00000010; -#endif -#ifdef USE_A4988_STEPPER - feature5 |= 0x00000020; -#endif -#ifdef USE_DDS2382 - feature5 |= 0x00000040; -#endif -#ifdef USE_SM2135 - feature5 |= 0x00000080; -#endif -#ifdef USE_SHUTTER - feature5 |= 0x00000100; -#endif -#ifdef USE_PCF8574 - feature5 |= 0x00000200; -#endif -#ifdef USE_DDSU666 - feature5 |= 0x00000400; -#endif -#ifdef USE_DEEPSLEEP - feature5 |= 0x00000800; -#endif -#ifdef USE_SONOFF_SC - feature5 |= 0x00001000; -#endif -#ifdef USE_SONOFF_RF - feature5 |= 0x00002000; -#endif -#ifdef USE_SONOFF_L1 - feature5 |= 0x00004000; -#endif -#ifdef USE_EXS_DIMMER - feature5 |= 0x00008000; -#endif -#ifdef USE_ARDUINO_SLAVE - feature5 |= 0x00010000; -#endif -#ifdef USE_HIH6 - feature5 |= 0x00020000; -#endif -#ifdef USE_HPMA - feature5 |= 0x00040000; -#endif -#ifdef USE_TSL2591 - feature5 |= 0x00080000; -#endif -#ifdef USE_DHT12 - feature5 |= 0x00100000; -#endif -#ifdef USE_DS1624 - feature5 |= 0x00200000; -#endif -#ifdef USE_GPS - feature5 |= 0x00400000; -#endif -#ifdef USE_HOTPLUG - feature5 |= 0x00800000; -#endif -#ifdef USE_NRF24 - feature5 |= 0x01000000; -#endif -#ifdef USE_MIBLE - feature5 |= 0x02000000; -#endif -#ifdef USE_HM10 - feature5 |= 0x04000000; -#endif -#ifdef USE_LE01MR - feature5 |= 0x08000000; -#endif -#ifdef USE_AHT1x - feature5 |= 0x10000000; -#endif -#ifdef USE_WEMOS_MOTOR_V1 - feature5 |= 0x20000000; -#endif - - - - - - - feature6 = 0x00000000; -# 570 "S:/Development/Tasmota/tasmota/support_features.ino" -} -# 1 "S:/Development/Tasmota/tasmota/support_flash_log.ino" -# 39 "S:/Development/Tasmota/tasmota/support_flash_log.ino" -#ifdef USE_FLOG - -class FLOG - -#define MAGIC_WORD_FL 0x464c - -{ - -struct header_t{ - uint16_t magic_word; - uint16_t padding; - uint32_t physical_start_sector:10; - uint32_t number:10; - uint32_t buf_pointer:12; - }; - -private: -void _readSector(uint8_t one_sector); -void _eraseSector(uint8_t one_sector); -void _writeSector(uint8_t one_sector); -void _clearBuffer(void); -void _searchSaves(void); -void _findFirstErasedSector(void); -void _showBuffer(void); -void _initBuffer(void); -void _saveBufferToSector(void); -header_t _saved_header; - -public: - uint32_t size; - uint32_t start; - uint32_t end; - uint16_t num_sectors; - - uint16_t first_erased_sector; - uint16_t current_sector; - - uint16_t bytes_left; - uint16_t sectors_left; - - uint8_t mode = 0; - bool found_saved_data = false; - bool ready = false; - bool running_download = false; - bool recording = false; - - union sector_t{ - uint32_t dword_buffer[FLASH_SECTOR_SIZE/4]; - uint8_t byte_buffer[FLASH_SECTOR_SIZE]; - header_t header; - } sector; - - void init(void); - void addToBuffer(uint8_t src[], uint32_t size); - void startRecording(bool append); - void stopRecording(void); - - typedef void (*CallbackNoArgs) (); - typedef void (*CallbackWithArgs) (uint8_t *_record); - - void startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter); -}; - -extern "C" uint32_t _SPIFFS_start; -extern "C" uint32_t _FS_start; - - - - -void FLOG::init(void) -{ -DEBUG_SENSOR_LOG(PSTR("FLOG: init ...")); -size = ESP.getSketchSize(); - -start = (size + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1)); -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) -end = (uint32_t)&_SPIFFS_start - 0x40200000; -#else -end = (uint32_t)&_FS_start - 0x40200000; -#endif -num_sectors = (end - start)/FLASH_SECTOR_SIZE; -DEBUG_SENSOR_LOG(PSTR("FLOG: size: 0x%lx, start: 0x%lx, end: 0x%lx, num_sectors(dec): %lu"), size, start, end, num_sectors ); -_findFirstErasedSector(); -if(first_erased_sector == 0xffff){ - _eraseSector(0); - first_erased_sector = 0; -} -_searchSaves(); -_initBuffer(); -ready = true; -} -# 142 "S:/Development/Tasmota/tasmota/support_flash_log.ino" -void FLOG::_readSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: read sector number: %u" ), one_sector); - ESP.flashRead(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); -} - - - - - -void FLOG::_eraseSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: erasing sector number: %u" ), one_sector); - ESP.flashEraseSector((start/FLASH_SECTOR_SIZE)+one_sector); -} - - - - - -void FLOG::_writeSector(uint8_t one_sector){ - DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to sector number: %u" ), one_sector); - ESP.flashWrite(start+(one_sector * FLASH_SECTOR_SIZE),(uint32_t *)§or.dword_buffer, FLASH_SECTOR_SIZE); -} - - - - -void FLOG::_clearBuffer(){ - for (uint32_t i = sizeof(sector.header)/4; i<(sizeof(sector.dword_buffer)/4); i++){ - sector.dword_buffer[i] = 0; - } - sector.header.buf_pointer = sizeof(sector.header); - -} - - - - -void FLOG::_saveBufferToSector(){ - DEBUG_SENSOR_LOG(PSTR("FLOG: write buffer to current sector: %u" ),current_sector); - _writeSector(current_sector); - if(current_sector == num_sectors){ - current_sector = 0; - } - else{ - current_sector++; - } - _eraseSector(current_sector); - _clearBuffer(); - sector.header.number++; - DEBUG_SENSOR_LOG(PSTR("FLOG: new sector header number: %u" ),sector.header.number); -} - - - - - -void FLOG::_findFirstErasedSector(){ - for (uint32_t i = 0; i3){ - break; - } - } -} - - - - - - - -void FLOG::addToBuffer(uint8_t src[], uint32_t size){ - if(mode == 0){ - if(sector.header.number == num_sectors && !ready){ - return; - } - } - if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ - - - - memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); - sector.header.buf_pointer+=size; - - } - else{ - DEBUG_SENSOR_LOG(PSTR("FLOG: save buffer to flash sector: %u"), current_sector); - DEBUG_SENSOR_LOG(PSTR("FLOG: current buf_pointer: %u"), sector.header.buf_pointer); - _saveBufferToSector(); - sectors_left++; - - if((FLASH_SECTOR_SIZE-sector.header.buf_pointer-sizeof(sector.header))>size){ - memcpy(sector.byte_buffer + sector.header.buf_pointer, src, size); - sector.header.buf_pointer+=size; - } - } -} - - - - - - -void FLOG::startRecording(bool append){ - if(recording){ - DEBUG_SENSOR_LOG(PSTR("FLOG: already recording")); - return; - } - recording = true; - DEBUG_SENSOR_LOG(PSTR("FLOG: start recording")); - _initBuffer(); - if(!found_saved_data) { - append = false; - } - if(append){ - sector.header.number = _saved_header.number+1; - sector.header.physical_start_sector = _saved_header.physical_start_sector; - } - else{ - sector.header.physical_start_sector = (uint16_t)first_erased_sector; - found_saved_data = false; - sectors_left = 0; - } - } - - - - - -void FLOG::stopRecording(void){ - _saveBufferToSector(); - _findFirstErasedSector(); - _searchSaves(); - _initBuffer(); - recording = false; - found_saved_data = true; - } -# 381 "S:/Development/Tasmota/tasmota/support_flash_log.ino" - void FLOG::startDownload(size_t size, CallbackNoArgs sendHeader, CallbackWithArgs sendRecord, CallbackNoArgs sendFooter){ - - _readSector(sector.header.physical_start_sector); - uint32_t next_sector = sector.header.physical_start_sector; - bytes_left = sector.header.buf_pointer - sizeof(sector.header); - DEBUG_SENSOR_LOG(PSTR("FLOG: create file for download, will process %u bytes"), bytes_left); - running_download = true; - - sendHeader(); - - while(sectors_left){ - DEBUG_SENSOR_LOG(PSTR("FLOG: next sector: %u"), next_sector); - - uint32_t k = sizeof(sector.header); - while(bytes_left){ - - uint8_t *_record_start = (uint8_t*)§or.byte_buffer[k]; - - sendRecord(_record_start); - if(k%128 == 0){ - - OsWatchLoop(); - delay(sleep); - } - k+=size; - if(bytes_left>7){ - bytes_left-=size; - } - else{ - bytes_left = 0; - DEBUG_SENSOR_LOG(PSTR("FLOG: Flog->bytes_left not dividable by 8 ??????")); - } - } - next_sector++; - if(next_sector>num_sectors){ - next_sector = 0; - } - sectors_left--; - _readSector(next_sector); - bytes_left = sector.header.buf_pointer - sizeof(sector.header); - OsWatchLoop(); - delay(sleep); - } - running_download = false; - - sendFooter(); - - _searchSaves(); - _initBuffer(); - } - - #endif -# 1 "S:/Development/Tasmota/tasmota/support_float.ino" -# 23 "S:/Development/Tasmota/tasmota/support_float.ino" -float fmodf(float x, float y) -{ - - union {float f; uint32_t i;} ux = {x}, uy = {y}; - int ex = ux.i>>23 & 0xff; - int ey = uy.i>>23 & 0xff; - uint32_t sx = ux.i & 0x80000000; - uint32_t i; - uint32_t uxi = ux.i; - - if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) - return (x*y)/(x*y); - if (uxi<<1 <= uy.i<<1) { - if (uxi<<1 == uy.i<<1) - return 0*x; - return x; - } - - - if (!ex) { - for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); - uxi <<= -ex + 1; - } else { - uxi &= -1U >> 9; - uxi |= 1U << 23; - } - if (!ey) { - for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); - uy.i <<= -ey + 1; - } else { - uy.i &= -1U >> 9; - uy.i |= 1U << 23; - } - - - for (; ex > ey; ex--) { - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - uxi <<= 1; - } - i = uxi - uy.i; - if (i >> 31 == 0) { - if (i == 0) - return 0*x; - uxi = i; - } - for (; uxi>>23 == 0; uxi <<= 1, ex--); - - - if (ex > 0) { - uxi -= 1U << 23; - uxi |= (uint32_t)ex << 23; - } else { - uxi >>= -ex + 1; - } - uxi |= sx; - ux.i = uxi; - return ux.f; -} - - -double FastPrecisePow(double a, double b) -{ - - - int e = abs((int)b); - union { - double d; - int x[2]; - } u = { a }; - u.x[1] = (int)((b - e) * (u.x[1] - 1072632447) + 1072632447); - u.x[0] = 0; - - - double r = 1.0; - while (e) { - if (e & 1) { - r *= a; - } - a *= a; - e >>= 1; - } - return r * u.d; -} - -float FastPrecisePowf(const float x, const float y) -{ - - return (float)FastPrecisePow(x, y); -} - -double TaylorLog(double x) -{ - - - if (x <= 0.0) { return NAN; } - double z = (x + 1) / (x - 1); - double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); - double totalValue = 0; - double powe = 1; - for (uint32_t count = 0; count < 10; count++) { - z *= step; - double y = (1 / powe) * z; - totalValue = totalValue + y; - powe = powe + 2; - } - totalValue *= 2; -# 144 "S:/Development/Tasmota/tasmota/support_float.ino" - return totalValue; -} -# 154 "S:/Development/Tasmota/tasmota/support_float.ino" -inline float sinf(float x) { return sin_52(x); } -inline float cosf(float x) { return cos_52(x); } -inline float tanf(float x) { return tan_56(x); } -inline float atanf(float x) { return atan_66(x); } -inline float asinf(float x) { return asinf1(x); } -inline float acosf(float x) { return acosf1(x); } -inline float sqrtf(float x) { return sqrt1(x); } -inline float powf(float x, float y) { return FastPrecisePow(x, y); } - - -double const f_pi = 3.1415926535897932384626433; -double const f_twopi = 2.0 * f_pi; -double const f_two_over_pi = 2.0 / f_pi; -double const f_halfpi = f_pi / 2.0; -double const f_threehalfpi = 3.0 * f_pi / 2.0; -double const f_four_over_pi = 4.0 / f_pi; -double const f_qtrpi = f_pi / 4.0; -double const f_sixthpi = f_pi / 6.0; -double const f_tansixthpi = tan(f_sixthpi); -double const f_twelfthpi = f_pi / 12.0; -double const f_tantwelfthpi = tan(f_twelfthpi); -float const f_180pi = 180 / f_pi; -# 194 "S:/Development/Tasmota/tasmota/support_float.ino" -float cos_52s(float x) -{ - const float c1 = 0.9999932946; - const float c2 = -0.4999124376; - const float c3 = 0.0414877472; - const float c4 = -0.0012712095; - - float x2 = x * x; - return (c1 + x2 * (c2 + x2 * (c3 + c4 * x2))); -} - - - - - - -float cos_52(float x) -{ - x = fmodf(x, f_twopi); - if (x < 0) { x = -x; } - int quad = int(x * (float)f_two_over_pi); - switch (quad) { - case 0: return cos_52s(x); - case 1: return -cos_52s((float)f_pi - x); - case 2: return -cos_52s(x-(float)f_pi); - case 3: return cos_52s((float)f_twopi - x); - } -} - - - - -float sin_52(float x) -{ - return cos_52((float)f_halfpi - x); -} -# 247 "S:/Development/Tasmota/tasmota/support_float.ino" -float tan_56s(float x) -{ - const float c1 = -3.16783027; - const float c2 = 0.134516124; - const float c3 = -4.033321984; - - float x2 = x * x; - return (x * (c1 + c2 * x2) / (c3 + x2)); -} -# 267 "S:/Development/Tasmota/tasmota/support_float.ino" -float tan_56(float x) -{ - x = fmodf(x, (float)f_twopi); - int octant = int(x * (float)f_four_over_pi); - switch (octant){ - case 0: return tan_56s(x * (float)f_four_over_pi); - case 1: return 1.0f / tan_56s(((float)f_halfpi - x) * (float)f_four_over_pi); - case 2: return -1.0f / tan_56s((x-(float)f_halfpi) * (float)f_four_over_pi); - case 3: return - tan_56s(((float)f_pi - x) * (float)f_four_over_pi); - case 4: return tan_56s((x-(float)f_pi) * (float)f_four_over_pi); - case 5: return 1.0f / tan_56s(((float)f_threehalfpi - x) * (float)f_four_over_pi); - case 6: return -1.0f / tan_56s((x-(float)f_threehalfpi) * (float)f_four_over_pi); - case 7: return - tan_56s(((float)f_twopi - x) * (float)f_four_over_pi); - } -} -# 296 "S:/Development/Tasmota/tasmota/support_float.ino" -float atan_66s(float x) -{ - const float c1 = 1.6867629106; - const float c2 = 0.4378497304; - const float c3 = 1.6867633134; - - float x2 = x * x; - return (x * (c1 + x2 * c2) / (c3 + x2)); -} - - - - - -float atan_66(float x) -{ - float y; - bool complement= false; - bool region= false; - bool sign= false; - - if (x < 0) { - x = -x; - sign = true; - } - if (x > 1.0) { - x = 1.0 / x; - complement = true; - } - if (x > (float)f_tantwelfthpi) { - x = (x - (float)f_tansixthpi) / (1 + (float)f_tansixthpi * x); - region = true; - } - - y = atan_66s(x); - if (region) { y += (float)f_sixthpi; } - if (complement) { y = (float)f_halfpi-y; } - if (sign) { y = -y; } - return (y); -} - -float asinf1(float x) -{ - float d = 1.0f - x * x; - if (d < 0.0f) { return NAN; } - return 2 * atan_66(x / (1 + sqrt1(d))); -} - -float acosf1(float x) -{ - float d = 1.0f - x * x; - if (d < 0.0f) { return NAN; } - float y = asinf1(sqrt1(d)); - if (x >= 0.0f) { - return y; - } else { - return (float)f_pi - y; - } -} - - -float sqrt1(const float x) -{ - union { - int i; - float x; - } u; - u.x = x; - u.i = (1 << 29) + (u.i >> 1) - (1 << 22); - - - - - u.x = u.x + x / u.x; - u.x = 0.25f * u.x + x / u.x; - - return u.x; -} -# 387 "S:/Development/Tasmota/tasmota/support_float.ino" -uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, - uint16_t ito_min, uint16_t ito_max) { - - if (ifrom_min >= ifrom_max) { - if (ito_min > ito_max) { - return ito_max; - } else { - return ito_min; - } - } - - uint32_t num = inum; - uint32_t from_min = ifrom_min; - uint32_t from_max = ifrom_max; - uint32_t to_min = ito_min; - uint32_t to_max = ito_max; - - - num = (num > from_max ? from_max : (num < from_min ? from_min : num)); - - - if (to_min > to_max) { - - num = (from_max - num) + from_min; - to_min = ito_max; - to_max = ito_min; - } - - uint32_t numerator = (num - from_min) * (to_max - to_min); - uint32_t result; - if (numerator >= 0x80000000L) { - - result = numerator / (from_max - from_min) + to_min; - } else { - result = (((numerator * 2) / (from_max - from_min)) + 1) / 2 + to_min; - } - return (uint32_t) (result > to_max ? to_max : (result < to_min ? to_min : result)); -} -# 1 "S:/Development/Tasmota/tasmota/support_legacy_cores.ino" -# 20 "S:/Development/Tasmota/tasmota/support_legacy_cores.ino" -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - - - - - -void* memchr(const void* ptr, int value, size_t num) -{ - unsigned char *p = (unsigned char*)ptr; - while (num--) { - if (*p != (unsigned char)value) { - p++; - } else { - return p; - } - } - return 0; -} - - - -size_t strcspn(const char *str1, const char *str2) -{ - size_t ret = 0; - while (*str1) { - if (strchr(str2, *str1)) { - return ret; - } else { - str1++; - ret++; - } - } - return ret; -} - - - -char* strpbrk(const char *s1, const char *s2) -{ - while(*s1) { - if (strchr(s2, *s1++)) { - return (char*)--s1; - } - } - return 0; -} - - - -#ifndef __LONG_LONG_MAX__ -#define __LONG_LONG_MAX__ 9223372036854775807LL -#endif -#ifndef ULLONG_MAX -#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) -#endif - -unsigned long long strtoull(const char *__restrict nptr, char **__restrict endptr, int base) -{ - const char *s = nptr; - char c; - do { c = *s++; } while (isspace((unsigned char)c)); - - int neg = 0; - if (c == '-') { - neg = 1; - c = *s++; - } else { - if (c == '+') { - c = *s++; - } - } - - if ((base == 0 || base == 16) && (c == '0') && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) { base = (c == '0') ? 8 : 10; } - - unsigned long long acc = 0; - int any = 0; - if (base > 1 && base < 37) { - unsigned long long cutoff = ULLONG_MAX / base; - int cutlim = ULLONG_MAX % base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - - if (c >= base) - break; - - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULLONG_MAX; - } - else if (any && neg) { - acc = -acc; - } - } - - if (endptr != nullptr) { *endptr = (char *)(any ? s - 1 : nptr); } - - return acc; -} - -#endif - - - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2) - - - - - -void* memmove_P(void *dest, const void *src, size_t n) -{ - if (src > (void*)0x40000000) { - return memcpy_P(dest, src, n); - } else { - return memmove(dest, src, n); - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/support_rotary.ino" -# 20 "S:/Development/Tasmota/tasmota/support_rotary.ino" -#ifdef USE_LIGHT - -#ifdef ROTARY_V1 - - - - -struct ROTARY { - unsigned long debounce = 0; - uint8_t present = 0; - uint8_t state = 0; - uint8_t position = 128; - uint8_t last_position = 128; - uint8_t interrupts_in_use_count = 0; - uint8_t changed = 0; -} Rotary; - - - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void update_rotary(void) ICACHE_RAM_ATTR; -#endif - -void update_rotary(void) -{ - if (MI_DESK_LAMP == my_module_type) { - if (LightPowerIRAM()) { - - - - - uint8_t s = Rotary.state & 3; - if (digitalRead(pin[GPIO_ROT1A])) { s |= 4; } - if (digitalRead(pin[GPIO_ROT1B])) { s |= 8; } - switch (s) { - case 0: case 5: case 10: case 15: - break; - case 1: case 7: case 8: case 14: - Rotary.position++; break; - case 2: case 4: case 11: case 13: - Rotary.position--; break; - case 3: case 12: - Rotary.position = Rotary.position + 2; break; - default: - Rotary.position = Rotary.position - 2; break; - } - Rotary.state = (s >> 2); - } - } -} - -bool RotaryButtonPressed(void) -{ - if ((MI_DESK_LAMP == my_module_type) && (Rotary.changed) && LightPower()) { - Rotary.changed = 0; - return true; - } - return false; -} - -void RotaryInit(void) -{ - Rotary.present = 0; - if ((pin[GPIO_ROT1A] < 99) && (pin[GPIO_ROT1B] < 99)) { - Rotary.present++; - pinMode(pin[GPIO_ROT1A], INPUT_PULLUP); - pinMode(pin[GPIO_ROT1B], INPUT_PULLUP); - - - - - if ((pin[GPIO_ROT1A] < 6) || (pin[GPIO_ROT1A] > 11)) { - attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1A]), update_rotary, CHANGE); - Rotary.interrupts_in_use_count++; - } - if ((pin[GPIO_ROT1B] < 6) || (pin[GPIO_ROT1B] > 11)) { - attachInterrupt(digitalPinToInterrupt(pin[GPIO_ROT1B]), update_rotary, CHANGE); - Rotary.interrupts_in_use_count++; - } - } -} - - - - - -void RotaryHandler(void) -{ - if (Rotary.interrupts_in_use_count < 2) { - noInterrupts(); - update_rotary(); - } else { - noInterrupts(); - } - if (Rotary.last_position != Rotary.position) { - if (MI_DESK_LAMP == my_module_type) { - if (Button.hold_timer[0]) { - Rotary.changed = 1; - - int16_t t = LightGetColorTemp(); - t = t + (Rotary.position - Rotary.last_position); - if (t < 153) { - t = 153; - } - if (t > 500) { - t = 500; - } - DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_COLORTEMPERATURE " %d"), Rotary.position - Rotary.last_position); - LightSetColorTemp((uint16_t)t); - } else { - int8_t d = Settings.light_dimmer; - d = d + (Rotary.position - Rotary.last_position); - if (d < 1) { - d = 1; - } - if (d > 100) { - d = 100; - } - DEBUG_CORE_LOG(PSTR("ROT: " D_CMND_DIMMER " %d"), Rotary.position - Rotary.last_position); - - LightSetDimmer((uint8_t)d); - Settings.light_dimmer = d; - } - } - Rotary.last_position = 128; - Rotary.position = 128; - } - interrupts(); -} - -void RotaryLoop(void) -{ - if (Rotary.present) { - if (TimeReached(Rotary.debounce)) { - SetNextTimeInterval(Rotary.debounce, Settings.button_debounce); - RotaryHandler(); - } - } -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/support_rtc.ino" -# 25 "S:/Development/Tasmota/tasmota/support_rtc.ino" -const uint32_t SECS_PER_MIN = 60UL; -const uint32_t SECS_PER_HOUR = 3600UL; -const uint32_t SECS_PER_DAY = SECS_PER_HOUR * 24UL; -const uint32_t MINS_PER_HOUR = 60UL; - -#define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) - -extern "C" { -#include "sntp.h" -} -#include - -Ticker TickerRtc; - -static const uint8_t kDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -static const char kMonthNamesEnglish[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; - -struct RTC { - uint32_t utc_time = 0; - uint32_t local_time = 0; - uint32_t daylight_saving_time = 0; - uint32_t standard_time = 0; - uint32_t ntp_time = 0; - uint32_t midnight = 0; - uint32_t restart_time = 0; - int32_t time_timezone = 0; - uint8_t ntp_sync_minute = 0; - bool midnight_now = false; - bool user_time_entry = false; -} Rtc; - -uint32_t UtcTime(void) -{ - return Rtc.utc_time; -} - -uint32_t LocalTime(void) -{ - return Rtc.local_time; -} - -uint32_t Midnight(void) -{ - return Rtc.midnight; -} - -bool MidnightNow(void) -{ - if (Rtc.midnight_now) { - Rtc.midnight_now = false; - return true; - } - return false; -} - -bool IsDst(void) -{ - if (Rtc.time_timezone == Settings.toffset[1]) { - return true; - } - return false; -} - -String GetBuildDateAndTime(void) -{ - - char bdt[21]; - char *p; - char mdate[] = __DATE__; - char *smonth = mdate; - int day = 0; - int year = 0; - - - uint8_t i = 0; - for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(nullptr, " ", &p)) { - switch (i++) { - case 0: - smonth = str; - break; - case 1: - day = atoi(str); - break; - case 2: - year = atoi(str); - } - } - int month = (strstr(kMonthNamesEnglish, smonth) -kMonthNamesEnglish) /3 +1; - snprintf_P(bdt, sizeof(bdt), PSTR("%d" D_YEAR_MONTH_SEPARATOR "%02d" D_MONTH_DAY_SEPARATOR "%02d" D_DATE_TIME_SEPARATOR "%s"), year, month, day, __TIME__); - return String(bdt); -} - -String GetMinuteTime(uint32_t minutes) -{ - char tm[6]; - snprintf_P(tm, sizeof(tm), PSTR("%02d:%02d"), minutes / 60, minutes % 60); - - return String(tm); -} - -String GetTimeZone(void) -{ - char tz[7]; - snprintf_P(tz, sizeof(tz), PSTR("%+03d:%02d"), Rtc.time_timezone / 60, abs(Rtc.time_timezone % 60)); - - return String(tz); -} - -String GetDuration(uint32_t time) -{ - char dt[16]; - - TIME_T ut; - BreakTime(time, ut); - - - - - - - snprintf_P(dt, sizeof(dt), PSTR("%dT%02d:%02d:%02d"), ut.days, ut.hour, ut.minute, ut.second); - - return String(dt); -} - -String GetDT(uint32_t time) -{ - - - char dt[20]; - TIME_T tmpTime; - - BreakTime(time, tmpTime); - snprintf_P(dt, sizeof(dt), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"), - tmpTime.year +1970, tmpTime.month, tmpTime.day_of_month, tmpTime.hour, tmpTime.minute, tmpTime.second); - - return String(dt); -} -# 175 "S:/Development/Tasmota/tasmota/support_rtc.ino" -String GetDateAndTime(uint8_t time_type) -{ - - uint32_t time = Rtc.local_time; - - switch (time_type) { - case DT_UTC: - time = Rtc.utc_time; - break; - - - - case DT_DST: - time = Rtc.daylight_saving_time; - break; - case DT_STD: - time = Rtc.standard_time; - break; - case DT_RESTART: - if (Rtc.restart_time == 0) { - return ""; - } - time = Rtc.restart_time; - break; - case DT_ENERGY: - time = Settings.energy_kWhtotal_time; - break; - case DT_BOOTCOUNT: - time = Settings.bootcount_reset_time; - break; - } - String dt = GetDT(time); - if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { - dt += GetTimeZone(); - } - return dt; -} - -uint32_t UpTime(void) -{ - if (Rtc.restart_time) { - return Rtc.utc_time - Rtc.restart_time; - } else { - return uptime; - } -} - -uint32_t MinutesUptime(void) -{ - return (UpTime() / 60); -} - -String GetUptime(void) -{ - return GetDuration(UpTime()); -} - -uint32_t MinutesPastMidnight(void) -{ - uint32_t minutes = 0; - - if (RtcTime.valid) { - minutes = (RtcTime.hour *60) + RtcTime.minute; - } - return minutes; -} - -void BreakTime(uint32_t time_input, TIME_T &tm) -{ - - - - - uint8_t year; - uint8_t month; - uint8_t month_length; - uint32_t time; - unsigned long days; - - time = time_input; - tm.second = time % 60; - time /= 60; - tm.minute = time % 60; - time /= 60; - tm.hour = time % 24; - time /= 24; - tm.days = time; - tm.day_of_week = ((time + 4) % 7) + 1; - - year = 0; - days = 0; - while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { - year++; - } - tm.year = year; - - days -= LEAP_YEAR(year) ? 366 : 365; - time -= days; - tm.day_of_year = time; - - for (month = 0; month < 12; month++) { - if (1 == month) { - if (LEAP_YEAR(year)) { - month_length = 29; - } else { - month_length = 28; - } - } else { - month_length = kDaysInMonth[month]; - } - - if (time >= month_length) { - time -= month_length; - } else { - break; - } - } - strlcpy(tm.name_of_month, kMonthNames + (month *3), 4); - tm.month = month + 1; - tm.day_of_month = time + 1; - tm.valid = (time_input > START_VALID_TIME); -} - -uint32_t MakeTime(TIME_T &tm) -{ - - - - int i; - uint32_t seconds; - - - seconds = tm.year * (SECS_PER_DAY * 365); - for (i = 0; i < tm.year; i++) { - if (LEAP_YEAR(i)) { - seconds += SECS_PER_DAY; - } - } - - - for (i = 1; i < tm.month; i++) { - if ((2 == i) && LEAP_YEAR(tm.year)) { - seconds += SECS_PER_DAY * 29; - } else { - seconds += SECS_PER_DAY * kDaysInMonth[i-1]; - } - } - seconds+= (tm.day_of_month - 1) * SECS_PER_DAY; - seconds+= tm.hour * SECS_PER_HOUR; - seconds+= tm.minute * SECS_PER_MIN; - seconds+= tm.second; - return seconds; -} - -uint32_t RuleToTime(TimeRule r, int yr) -{ - TIME_T tm; - uint32_t t; - uint8_t m; - uint8_t w; - - m = r.month; - w = r.week; - if (0 == w) { - if (++m > 12) { - m = 1; - yr++; - } - w = 1; - } - - tm.hour = r.hour; - tm.minute = 0; - tm.second = 0; - tm.day_of_month = 1; - tm.month = m; - tm.year = yr - 1970; - t = MakeTime(tm); - BreakTime(t, tm); - t += (7 * (w - 1) + (r.dow - tm.day_of_week + 7) % 7) * SECS_PER_DAY; - if (0 == r.week) { - t -= 7 * SECS_PER_DAY; - } - return t; -} - -void RtcSecond(void) -{ - TIME_T tmpTime; - - if (!Rtc.user_time_entry && !global_state.wifi_down) { - uint8_t uptime_minute = (uptime / 60) % 60; - if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) { - Rtc.ntp_sync_minute = 1; - } - uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; - if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || - (Rtc.ntp_sync_minute == uptime_minute))) || - ntp_force_sync ) ) { - Rtc.ntp_time = sntp_get_current_timestamp(); - if (Rtc.ntp_time > START_VALID_TIME) { - ntp_force_sync = false; - Rtc.utc_time = Rtc.ntp_time; - Rtc.ntp_sync_minute = 60; - if (Rtc.restart_time == 0) { - Rtc.restart_time = Rtc.utc_time - uptime; - } - BreakTime(Rtc.utc_time, tmpTime); - RtcTime.year = tmpTime.year + 1970; - Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); - Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - - - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR("NTP: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); - - if (Rtc.local_time < START_VALID_TIME) { - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } else { - Rtc.ntp_sync_minute++; - } - } - } - - Rtc.utc_time++; - Rtc.local_time = Rtc.utc_time; - if (Rtc.local_time > START_VALID_TIME) { - int16_t timezone_minutes = Settings.timezone_minutes; - if (Settings.timezone < 0) { timezone_minutes *= -1; } - Rtc.time_timezone = (Settings.timezone * SECS_PER_HOUR) + (timezone_minutes * SECS_PER_MIN); - if (99 == Settings.timezone) { - int32_t dstoffset = Settings.toffset[1] * SECS_PER_MIN; - int32_t stdoffset = Settings.toffset[0] * SECS_PER_MIN; - if (Settings.tflag[1].hemis) { - - if ((Rtc.utc_time >= (Rtc.standard_time - dstoffset)) && (Rtc.utc_time < (Rtc.daylight_saving_time - stdoffset))) { - Rtc.time_timezone = stdoffset; - } else { - Rtc.time_timezone = dstoffset; - } - } else { - - if ((Rtc.utc_time >= (Rtc.daylight_saving_time - stdoffset)) && (Rtc.utc_time < (Rtc.standard_time - dstoffset))) { - Rtc.time_timezone = dstoffset; - } else { - Rtc.time_timezone = stdoffset; - } - } - } - Rtc.local_time += Rtc.time_timezone; - Rtc.time_timezone /= 60; - if (!Settings.energy_kWhtotal_time) { - Settings.energy_kWhtotal_time = Rtc.local_time; - } - if (Settings.bootcount_reset_time < START_VALID_TIME) { - Settings.bootcount_reset_time = Rtc.local_time; - } - } - - BreakTime(Rtc.local_time, RtcTime); - if (RtcTime.valid) { - if (!Rtc.midnight) { - Rtc.midnight = Rtc.local_time - (RtcTime.hour * 3600) - (RtcTime.minute * 60) - RtcTime.second; - } - if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { - Rtc.midnight = Rtc.local_time; - Rtc.midnight_now = true; - } - } - - RtcTime.year += 1970; -} - -void RtcSetTime(uint32_t epoch) -{ - if (epoch < START_VALID_TIME) { - Rtc.user_time_entry = false; - ntp_force_sync = true; - sntp_init(); - } else { - sntp_stop(); - Rtc.user_time_entry = true; - Rtc.utc_time = epoch -1; - } - RtcSecond(); -} - -void RtcInit(void) -{ - sntp_setservername(0, SettingsText(SET_NTPSERVER1)); - sntp_setservername(1, SettingsText(SET_NTPSERVER2)); - sntp_setservername(2, SettingsText(SET_NTPSERVER3)); - sntp_stop(); - sntp_set_timezone(0); - sntp_init(); - Rtc.utc_time = 0; - BreakTime(Rtc.utc_time, RtcTime); - TickerRtc.attach(1, RtcSecond); -} -# 1 "S:/Development/Tasmota/tasmota/support_static_buffer.ino" -# 20 "S:/Development/Tasmota/tasmota/support_static_buffer.ino" -typedef struct SBuffer_impl { - uint16_t size; - uint16_t len; - uint8_t buf[]; -} SBuffer_impl; - - - -typedef class SBuffer { - -protected: - SBuffer(void) { - - } - -public: - SBuffer(const size_t size) { - _buf = (SBuffer_impl*) new char[size+4]; - _buf->size = size; - _buf->len = 0; - - } - - inline size_t getSize(void) const { return _buf->size; } - inline size_t size(void) const { return _buf->size; } - inline size_t getLen(void) const { return _buf->len; } - inline size_t len(void) const { return _buf->len; } - inline uint8_t *getBuffer(void) const { return _buf->buf; } - inline uint8_t *buf(size_t i = 0) const { return &_buf->buf[i]; } - inline char *charptr(size_t i = 0) const { return (char*) &_buf->buf[i]; } - - virtual ~SBuffer(void) { - delete[] _buf; - } - - inline void setLen(const size_t len) { - uint16_t old_len = _buf->len; - _buf->len = (len <= _buf->size) ? len : _buf->size; - if (old_len < _buf->len) { - memset((void*) &_buf->buf[old_len], 0, _buf->len - old_len); - } - } - - void set8(const size_t offset, const uint8_t data) { - if (offset < _buf->len) { - _buf->buf[offset] = data; - } - } - - size_t add8(const uint8_t data) { - if (_buf->len < _buf->size) { - _buf->buf[_buf->len++] = data; - } - return _buf->len; - } - size_t add16(const uint16_t data) { - if (_buf->len < _buf->size - 1) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - } - return _buf->len; - } - size_t add32(const uint32_t data) { - if (_buf->len < _buf->size - 3) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - _buf->buf[_buf->len++] = data >> 16; - _buf->buf[_buf->len++] = data >> 24; - } - return _buf->len; - } - size_t add64(const uint64_t data) { - if (_buf->len < _buf->size - 7) { - _buf->buf[_buf->len++] = data; - _buf->buf[_buf->len++] = data >> 8; - _buf->buf[_buf->len++] = data >> 16; - _buf->buf[_buf->len++] = data >> 24; - _buf->buf[_buf->len++] = data >> 32; - _buf->buf[_buf->len++] = data >> 40; - _buf->buf[_buf->len++] = data >> 48; - _buf->buf[_buf->len++] = data >> 56; - } - return _buf->len; - } - - size_t addBuffer(const SBuffer &buf2) { - if (len() + buf2.len() <= size()) { - for (uint32_t i = 0; i < buf2.len(); i++) { - _buf->buf[_buf->len++] = buf2.buf()[i]; - } - } - return _buf->len; - } - - size_t addBuffer(const uint8_t *buf2, size_t len2) { - if (len() + len2 <= size()) { - for (uint32_t i = 0; i < len2; i++) { - _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); - } - } - return _buf->len; - } - - size_t addBuffer(const char *buf2, size_t len2) { - if (len() + len2 <= size()) { - for (uint32_t i = 0; i < len2; i++) { - _buf->buf[_buf->len++] = pgm_read_byte(&buf2[i]); - } - } - return _buf->len; - } - - uint8_t get8(size_t offset) const { - if (offset < _buf->len) { - return _buf->buf[offset]; - } else { - return 0; - } - } - uint8_t read8(const size_t offset) const { - if (offset < len()) { - return _buf->buf[offset]; - } - return 0; - } - uint16_t get16(const size_t offset) const { - if (offset < len() - 1) { - return _buf->buf[offset] | (_buf->buf[offset+1] << 8); - } - return 0; - } - uint32_t get32(const size_t offset) const { - if (offset < len() - 3) { - return _buf->buf[offset] | (_buf->buf[offset+1] << 8) | - (_buf->buf[offset+2] << 16) | (_buf->buf[offset+3] << 24); - } - return 0; - } - uint64_t get64(const size_t offset) const { - if (offset < len() - 7) { - return (uint64_t)_buf->buf[offset] | ((uint64_t)_buf->buf[offset+1] << 8) | - ((uint64_t)_buf->buf[offset+2] << 16) | ((uint64_t)_buf->buf[offset+3] << 24) | - ((uint64_t)_buf->buf[offset+4] << 32) | ((uint64_t)_buf->buf[offset+5] << 40) | - ((uint64_t)_buf->buf[offset+6] << 48) | ((uint64_t)_buf->buf[offset+7] << 56); - } - return 0; - } - - - inline size_t strlen(const size_t offset) const { - return strnlen((const char*) &_buf->buf[offset], len() - offset); - } - - size_t strlen_s(const size_t offset) const { - size_t slen = this->strlen(offset); - if (slen == len() - offset) { - return 0; - } else { - return slen; - } - } - - SBuffer subBuffer(const size_t start, size_t len) const { - if (start >= _buf->len) { - len = 0; - } else if (start + len > _buf->len) { - len = _buf->len - start; - } - - SBuffer buf2(len); - memcpy(buf2.buf(), buf()+start, len); - buf2._buf->len = len; - return buf2; - } - - static SBuffer SBufferFromHex(const char *hex, size_t len) { - size_t buf_len = (len + 3) / 2; - SBuffer buf2(buf_len); - uint8_t val; - - for (; len > 1; len -= 2) { - val = asc2byte(*hex++) << 4; - val |= asc2byte(*hex++); - buf2.add8(val); - } - return buf2; - } - -protected: - - static uint8_t asc2byte(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { rVal = chr - '0'; } - else if (chr >= 'A' && chr <= 'F') { rVal = chr + 10 - 'A'; } - else if (chr >= 'a' && chr <= 'f') { rVal = chr + 10 - 'a'; } - return rVal; - } - - static void unHex(const char* in, uint8_t *out, size_t len) { - } - -protected: - SBuffer_impl * _buf; - -} SBuffer; - -typedef class PreAllocatedSBuffer : public SBuffer { - -public: - PreAllocatedSBuffer(const size_t size, void * buffer) { - _buf = (SBuffer_impl*) buffer; - _buf->size = size - 4; - _buf->len = 0; - } - - ~PreAllocatedSBuffer(void) { - - _buf = nullptr; - } -} PreAllocatedSBuffer; -# 1 "S:/Development/Tasmota/tasmota/support_statistics.ino" -# 20 "S:/Development/Tasmota/tasmota/support_statistics.ino" -#define USE_STATS_CODE - -#ifdef USE_STATS_CODE - - - - -String GetStatistics(void) -{ - char data[40]; - snprintf_P(data, sizeof(data), PSTR(",\"CR\":\"%d/%d\""), GetSettingsTextLen(), settings_text_size); - return String(data); -} - -#else - -String GetStatistics(void) -{ - return String(""); -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/support_switch.ino" -# 20 "S:/Development/Tasmota/tasmota/support_switch.ino" -#define SWITCH_V2 -#ifdef SWITCH_V2 - - - - - - -const uint8_t SWITCH_PROBE_INTERVAL = 10; - -#include - -Ticker TickerSwitch; - -struct SWITCH { - unsigned long debounce = 0; - uint16_t no_pullup_mask = 0; - uint8_t state[MAX_SWITCHES] = { 0 }; - uint8_t last_state[MAX_SWITCHES]; - uint8_t hold_timer[MAX_SWITCHES] = { 0 }; - uint8_t virtual_state[MAX_SWITCHES]; - uint8_t present = 0; -} Switch; - - - -void SwitchPullupFlag(uint16 switch_bit) -{ - bitSet(Switch.no_pullup_mask, switch_bit); -} - -void SwitchSetVirtual(uint32_t index, uint8_t state) -{ - Switch.virtual_state[index] = state; -} - -uint8_t SwitchGetVirtual(uint32_t index) -{ - return Switch.virtual_state[index]; -} - -uint8_t SwitchLastState(uint32_t index) -{ - return Switch.last_state[index]; -} - -bool SwitchState(uint32_t index) -{ - uint32_t switchmode = Settings.switchmode[index]; - return ((FOLLOW_INV == switchmode) || - (PUSHBUTTON_INV == switchmode) || - (PUSHBUTTONHOLD_INV == switchmode) || - (FOLLOWMULTI_INV == switchmode) || - (PUSHHOLDMULTI_INV == switchmode) - ) ^ Switch.last_state[index]; -} - - - -void SwitchProbe(void) -{ - if (uptime < 4) { return; } - - uint8_t state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; - uint8_t force_high = (Settings.switch_debounce % 50) &1; - uint8_t force_low = (Settings.switch_debounce % 50) &2; - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if (pin[GPIO_SWT1 +i] < 99) { - - if (1 == digitalRead(pin[GPIO_SWT1 +i])) { - - if (force_high) { - if (1 == Switch.virtual_state[i]) { - Switch.state[i] = state_filter; - } - } - - if (Switch.state[i] < state_filter) { - Switch.state[i]++; - if (state_filter == Switch.state[i]) { - Switch.virtual_state[i] = 1; - } - } - } else { - - if (force_low) { - if (0 == Switch.virtual_state[i]) { - Switch.state[i] = 0; - } - } - - if (Switch.state[i] > 0) { - Switch.state[i]--; - if (0 == Switch.state[i]) { - Switch.virtual_state[i] = 0; - } - } - } - } - } - TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); -} - -void SwitchInit(void) -{ - Switch.present = 0; - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - Switch.last_state[i] = 1; - if (pin[GPIO_SWT1 +i] < 99) { - Switch.present++; - pinMode(pin[GPIO_SWT1 +i], bitRead(Switch.no_pullup_mask, i) ? INPUT : ((16 == pin[GPIO_SWT1 +i]) ? INPUT_PULLDOWN_16 : INPUT_PULLUP)); - Switch.last_state[i] = digitalRead(pin[GPIO_SWT1 +i]); - } - Switch.virtual_state[i] = Switch.last_state[i]; - } - if (Switch.present) { TickerSwitch.attach_ms(SWITCH_PROBE_INTERVAL, SwitchProbe); } -} - - - - - -void SwitchHandler(uint8_t mode) -{ - if (uptime < 4) { return; } - - uint16_t loops_per_second = 1000 / Settings.switch_debounce; - - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - if ((pin[GPIO_SWT1 +i] < 99) || (mode)) { - uint8_t button = Switch.virtual_state[i]; - uint8_t switchflag = POWER_TOGGLE +1; - - if (Switch.hold_timer[i]) { - Switch.hold_timer[i]--; - if (0 == Switch.hold_timer[i]) { - - switch (Settings.switchmode[i]) { - case TOGGLEMULTI: - switchflag = POWER_TOGGLE; - break; - case FOLLOWMULTI: - switchflag = button &1; - break; - case FOLLOWMULTI_INV: - switchflag = ~button &1; - break; - case PUSHHOLDMULTI: - if (NOT_PRESSED == button){ - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); - } - else - SendKey(KEY_SWITCH, i +1, POWER_CLEAR); - break; - case PUSHHOLDMULTI_INV: - if (PRESSED == button){ - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25; - SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); - } - else - SendKey(KEY_SWITCH, i +1, POWER_CLEAR); - break; - default: - SendKey(KEY_SWITCH, i +1, POWER_HOLD); - break; - } - } - } - - - - if (button != Switch.last_state[i]) { - switch (Settings.switchmode[i]) { - case TOGGLE: - case PUSHBUTTON_TOGGLE: - switchflag = POWER_TOGGLE; - break; - case FOLLOW: - switchflag = button &1; - break; - case FOLLOW_INV: - switchflag = ~button &1; - break; - case PUSHBUTTON: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTON_INV: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTONHOLD: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; - } - break; - case PUSHBUTTONHOLD_INV: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; - } - break; - case TOGGLEMULTI: - case FOLLOWMULTI: - case FOLLOWMULTI_INV: - if (Switch.hold_timer[i]) { - Switch.hold_timer[i] = 0; - SendKey(KEY_SWITCH, i +1, POWER_HOLD); - } else { - Switch.hold_timer[i] = loops_per_second / 2; - } - break; - case PUSHHOLDMULTI: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - if(Switch.hold_timer[i]!=0) - SendKey(KEY_SWITCH, i +1, POWER_INV); - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) - switchflag = POWER_TOGGLE; - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - break; - case PUSHHOLDMULTI_INV: - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - if(Switch.hold_timer[i]!=0) - SendKey(KEY_SWITCH, i +1, POWER_INV); - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - if(Switch.hold_timer[i] > loops_per_second * Settings.param[P_HOLD_TIME] / 25) - switchflag = POWER_TOGGLE; - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; - } - break; - } - Switch.last_state[i] = button; - } - if (switchflag <= POWER_TOGGLE) { - if (!SendKey(KEY_SWITCH, i +1, switchflag)) { - ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); - } - } - } - } -} - -void SwitchLoop(void) -{ - if (Switch.present) { - if (TimeReached(Switch.debounce)) { - SetNextTimeInterval(Switch.debounce, Settings.switch_debounce); - SwitchHandler(0); - } - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/support_tasmota.ino" -# 20 "S:/Development/Tasmota/tasmota/support_tasmota.ino" -const char kSleepMode[] PROGMEM = "Dynamic|Normal"; -const char kPrefixes[] PROGMEM = D_CMND "|" D_STAT "|" D_TELE; - -char* Format(char* output, const char* input, int size) -{ - char *token; - uint32_t digits = 0; - - if (strstr(input, "%") != nullptr) { - strlcpy(output, input, size); - token = strtok(output, "%"); - if (strstr(input, "%") == input) { - output[0] = '\0'; - } else { - token = strtok(nullptr, ""); - } - if (token != nullptr) { - digits = atoi(token); - if (digits) { - char tmp[size]; - if (strchr(token, 'd')) { - snprintf_P(tmp, size, PSTR("%s%c0%dd"), output, '%', digits); - snprintf_P(output, size, tmp, ESP.getChipId() & 0x1fff); - } else { - snprintf_P(tmp, size, PSTR("%s%c0%dX"), output, '%', digits); - snprintf_P(output, size, tmp, ESP.getChipId()); - } - } else { - if (strchr(token, 'd')) { - snprintf_P(output, size, PSTR("%s%d"), output, ESP.getChipId()); - digits = 8; - } - } - } - } - if (!digits) { - strlcpy(output, input, size); - } - return output; -} - -char* GetOtaUrl(char *otaurl, size_t otaurl_size) -{ - if (strstr(SettingsText(SET_OTAURL), "%04d") != nullptr) { - snprintf(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId() & 0x1fff); - } - else if (strstr(SettingsText(SET_OTAURL), "%d") != nullptr) { - snprintf_P(otaurl, otaurl_size, SettingsText(SET_OTAURL), ESP.getChipId()); - } - else { - strlcpy(otaurl, SettingsText(SET_OTAURL), otaurl_size); - } - - return otaurl; -} - -char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic) -{ -# 88 "S:/Development/Tasmota/tasmota/support_tasmota.ino" - char romram[CMDSZ]; - String fulltopic; - - snprintf_P(romram, sizeof(romram), subtopic); - if (fallback_topic_flag || (prefix > 3)) { - bool fallback = (prefix < 8); - prefix &= 3; - char stemp[11]; - fulltopic = GetTextIndexed(stemp, sizeof(stemp), prefix, kPrefixes); - fulltopic += F("/"); - if (fallback) { - fulltopic += mqtt_client; - fulltopic += F("_fb"); - } else { - fulltopic += topic; - } - } else { - fulltopic = SettingsText(SET_MQTT_FULLTOPIC); - if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { - fulltopic += F("/"); - fulltopic += FPSTR(MQTT_TOKEN_PREFIX); - } - for (uint32_t i = 0; i < MAX_MQTT_PREFIXES; i++) { - if (!strlen(SettingsText(SET_MQTTPREFIX1 + i))) { - char temp[TOPSZ]; - SettingsUpdateText(SET_MQTTPREFIX1 + i, GetTextIndexed(temp, sizeof(temp), i, kPrefixes)); - } - } - fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), SettingsText(SET_MQTTPREFIX1 + prefix)); - - fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); - fulltopic.replace(F("%hostname%"), my_hostname); - String token_id = WiFi.macAddress(); - token_id.replace(":", ""); - fulltopic.replace(F("%id%"), token_id); - } - fulltopic.replace(F("#"), ""); - fulltopic.replace(F("//"), "/"); - if (!fulltopic.endsWith("/")) { - fulltopic += "/"; - } - snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram); - return stopic; -} - -char* GetGroupTopic_P(char *stopic, const char* subtopic) -{ - - - return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(SET_MQTT_GRP_TOPIC), subtopic); -} - -char* GetFallbackTopic_P(char *stopic, const char* subtopic) -{ - return GetTopic_P(stopic, CMND +4, nullptr, subtopic); -} - -char* GetStateText(uint32_t state) -{ - if (state >= MAX_STATE_TEXT) { - state = 1; - } - return SettingsText(SET_STATE_TXT1 + state); -} - - - -void SetLatchingRelay(power_t lpower, uint32_t state) -{ - - - - - - if (state && !latching_relay_pulse) { - latching_power = lpower; - latching_relay_pulse = 2; - } - - for (uint32_t i = 0; i < devices_present; i++) { - uint32_t port = (i << 1) + ((latching_power >> i) &1); - DigitalWrite(GPIO_REL1 +port, bitRead(rel_inverted, port) ? !state : state); - } -} - -void SetDevicePower(power_t rpower, uint32_t source) -{ - ShowSource(source); - last_source = source; - - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - power = (1 << devices_present) -1; - rpower = power; - } - - if (Settings.flag.interlock) { - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - power_t mask = 1; - uint32_t count = 0; - for (uint32_t j = 0; j < devices_present; j++) { - if ((Settings.interlock[i] & mask) && (rpower & mask)) { - count++; - } - mask <<= 1; - } - if (count > 1) { - mask = ~Settings.interlock[i]; - power &= mask; - rpower &= mask; - } - } - } - - if (rpower) { - last_power = rpower; - } - - XdrvMailbox.index = rpower; - XdrvCall(FUNC_SET_POWER); - - XdrvMailbox.index = rpower; - XdrvMailbox.payload = source; - if (XdrvCall(FUNC_SET_DEVICE_POWER)) { - - } - else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - Serial.write(0xA0); - Serial.write(0x04); - Serial.write(rpower &0xFF); - Serial.write(0xA1); - Serial.write('\n'); - Serial.flush(); - } - else if (EXS_RELAY == my_module_type) { - SetLatchingRelay(rpower, 1); - } - else { - for (uint32_t i = 0; i < devices_present; i++) { - power_t state = rpower &1; - if (i < MAX_RELAYS) { - DigitalWrite(GPIO_REL1 +i, bitRead(rel_inverted, i) ? !state : state); - } - rpower >>= 1; - } - } -} - -void RestorePower(bool publish_power, uint32_t source) -{ - if (power != last_power) { - power = last_power; - SetDevicePower(power, source); - if (publish_power) { - MqttPublishAllPowerState(); - } - } -} - -void SetAllPower(uint32_t state, uint32_t source) -{ -# 256 "S:/Development/Tasmota/tasmota/support_tasmota.ino" - bool publish_power = true; - if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { - state &= 3; - publish_power = false; - } - if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) { - power_t all_on = (1 << devices_present) -1; - switch (state) { - case POWER_OFF: - power = 0; - break; - case POWER_ON: - power = all_on; - break; - case POWER_TOGGLE: - power ^= all_on; - } - SetDevicePower(power, source); - } - if (publish_power) { - MqttPublishAllPowerState(); - } -} - -void SetPowerOnState(void) -{ - if (MOTOR == my_module_type) { - Settings.poweronstate = POWER_ALL_ON; - } - if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { - SetDevicePower(1, SRC_RESTART); - } else { - if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == REASON_EXT_SYS_RST)) { - switch (Settings.poweronstate) { - case POWER_ALL_OFF: - case POWER_ALL_OFF_PULSETIME_ON: - power = 0; - SetDevicePower(power, SRC_RESTART); - break; - case POWER_ALL_ON: - power = (1 << devices_present) -1; - SetDevicePower(power, SRC_RESTART); - break; - case POWER_ALL_SAVED_TOGGLE: - power = (Settings.power & ((1 << devices_present) -1)) ^ POWER_MASK; - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - break; - case POWER_ALL_SAVED: - power = Settings.power & ((1 << devices_present) -1); - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - break; - } - } else { - power = Settings.power & ((1 << devices_present) -1); - if (Settings.flag.save_state) { - SetDevicePower(power, SRC_RESTART); - } - } - } - - - for (uint32_t i = 0; i < devices_present; i++) { - if (!Settings.flag3.no_power_feedback) { - if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) { - bitWrite(power, i, digitalRead(pin[GPIO_REL1 +i]) ^ bitRead(rel_inverted, i)); - } - } - if ((i < MAX_PULSETIMERS) && (bitRead(power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate))) { - SetPulseTimer(i, Settings.pulse_timer[i]); - } - } - blink_powersave = power; -} - -void SetLedPowerIdx(uint32_t led, uint32_t state) -{ - if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { - if (pin[GPIO_LED2] < 99) { - led = 1; - } - } - if (pin[GPIO_LED1 + led] < 99) { - uint32_t mask = 1 << led; - if (state) { - state = 1; - led_power |= mask; - } else { - led_power &= (0xFF ^ mask); - } - DigitalWrite(GPIO_LED1 + led, bitRead(led_inverted, led) ? !state : state); - } -#ifdef USE_BUZZER - if (led == 0) { - BuzzerSetStateToLed(state); - } -#endif -} - -void SetLedPower(uint32_t state) -{ - if (99 == pin[GPIO_LEDLNK]) { - SetLedPowerIdx(0, state); - } else { - power_t mask = 1; - for (uint32_t i = 0; i < leds_present; i++) { - bool tstate = (power & mask); - SetLedPowerIdx(i, tstate); - mask <<= 1; - } - } -} - -void SetLedPowerAll(uint32_t state) -{ - for (uint32_t i = 0; i < leds_present; i++) { - SetLedPowerIdx(i, state); - } -} - -void SetLedLink(uint32_t state) -{ - uint32_t led_pin = pin[GPIO_LEDLNK]; - uint32_t led_inv = ledlnk_inverted; - if (99 == led_pin) { - led_pin = pin[GPIO_LED1]; - led_inv = bitRead(led_inverted, 0); - } - if (led_pin < 99) { - if (state) { state = 1; } - digitalWrite(led_pin, (led_inv) ? !state : state); - } -#ifdef USE_BUZZER - BuzzerSetStateToLed(state); -#endif -} - -void SetPulseTimer(uint32_t index, uint32_t time) -{ - pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L; -} - -uint32_t GetPulseTimer(uint32_t index) -{ - long time = TimePassedSince(pulse_timer[index]); - if (time < 0) { - time *= -1; - return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0; - } - return 0; -} - - - -bool SendKey(uint32_t key, uint32_t device, uint32_t state) -{ -# 423 "S:/Development/Tasmota/tasmota/support_tasmota.ino" - char stopic[TOPSZ]; - char scommand[CMDSZ]; - char key_topic[TOPSZ]; - bool result = false; - - char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_BUTTON_TOPIC); - Format(key_topic, tmp, sizeof(key_topic)); - if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { - if (!key && (device > devices_present)) { - device = 1; - } - GetTopic_P(stopic, CMND, key_topic, - GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); - if (CLEAR_RETAIN == state) { - mqtt_data[0] = '\0'; - } else { - if ((Settings.flag3.button_switch_force_local || - !strcmp(mqtt_topic, key_topic) || - !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) && - (POWER_TOGGLE == state)) { - state = ~(power >> (device -1)) &1; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state)); - } -#ifdef USE_DOMOTICZ - if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) { -#endif - MqttPublish(stopic, ((key) ? Settings.flag.mqtt_switch_retain - : Settings.flag.mqtt_button_retain) && - (state != POWER_HOLD || !Settings.flag3.no_hold_retain)); -#ifdef USE_DOMOTICZ - } -#endif - result = !Settings.flag3.button_switch_force_local; - } else { - Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); - result = XdrvRulesProcess(); - } - int32_t payload_save = XdrvMailbox.payload; - XdrvMailbox.payload = key << 16 | state << 8 | device; - XdrvCall(FUNC_ANY_KEY); - XdrvMailbox.payload = payload_save; - return result; -} - -void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source) -{ -# 483 "S:/Development/Tasmota/tasmota/support_tasmota.ino" -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - blink_mask &= 1; - Settings.flag.interlock = 0; - Settings.pulse_timer[1] = 0; - Settings.pulse_timer[2] = 0; - Settings.pulse_timer[3] = 0; - } -#endif - - bool publish_power = true; - if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) { - state &= 3; - publish_power = false; - } - - if ((device < 1) || (device > devices_present)) { - device = 1; - } - active_device = device; - - if (device <= MAX_PULSETIMERS) { - SetPulseTimer(device -1, 0); - } - power_t mask = 1 << (device -1); - if (state <= POWER_TOGGLE) { - if ((blink_mask & mask)) { - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(device); - } - - if (Settings.flag.interlock && - !interlock_mutex && - ((POWER_ON == state) || ((POWER_TOGGLE == state) && !(power & mask))) - ) { - interlock_mutex = true; - for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) { - if (Settings.interlock[i] & mask) { - for (uint32_t j = 0; j < devices_present; j++) { - power_t imask = 1 << j; - if ((Settings.interlock[i] & imask) && (power & imask) && (mask != imask)) { - ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE); - delay(50); - } - } - break; - } - } - interlock_mutex = false; - } - - switch (state) { - case POWER_OFF: { - power &= (POWER_MASK ^ mask); - break; } - case POWER_ON: - power |= mask; - break; - case POWER_TOGGLE: - power ^= mask; - } -#ifdef USE_DEVICE_GROUPS - if (SRC_REMOTE != source && SRC_RETRY != source) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, power); -#endif - SetDevicePower(power, source); -#ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(device); -#endif -#ifdef USE_KNX - KnxUpdatePowerState(device, power); -#endif - if (publish_power && Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - if (device <= MAX_PULSETIMERS) { - SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0); - } - } - else if (POWER_BLINK == state) { - if (!(blink_mask & mask)) { - blink_powersave = (blink_powersave & (POWER_MASK ^ mask)) | (power & mask); - blink_power = (power >> (device -1))&1; - } - blink_timer = millis() + 100; - blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1; - blink_mask |= mask; - MqttPublishPowerBlinkState(device); - return; - } - else if (POWER_BLINK_STOP == state) { - bool flag = (blink_mask & mask); - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(device); - if (flag) { - ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); - } - return; - } - if (publish_power) { - MqttPublishPowerState(device); - } -} - -void StopAllPowerBlink(void) -{ - power_t mask; - - for (uint32_t i = 1; i <= devices_present; i++) { - mask = 1 << (i -1); - if (blink_mask & mask) { - blink_mask &= (POWER_MASK ^ mask); - MqttPublishPowerBlinkState(i); - ExecuteCommandPower(i, (blink_powersave >> (i -1))&1, SRC_IGNORE); - } - } -} - -void MqttShowPWMState(void) -{ - ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); - bool first = true; - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 + i] < 99) { - ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); - first = false; - } - } - ResponseJsonEnd(); -} - -void MqttShowState(void) -{ - char stemp1[TOPSZ]; - - ResponseAppendTime(); - ResponseAppend_P(PSTR(",\"" D_JSON_UPTIME "\":\"%s\",\"UptimeSec\":%u"), GetUptime().c_str(), UpTime()); - -#ifdef USE_ADC_VCC - dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); - ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); -#endif - - ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"), - ESP.getFreeHeap()/1024, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), - sleep, loop_load_avg, MqttConnectCount()); - - for (uint32_t i = 1; i <= devices_present; i++) { -#ifdef USE_LIGHT - if ((LightDevice()) && (i >= LightDevice())) { - if (i == LightDevice()) { LightState(1); } - } else { -#endif - ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), - GetStateText(bitRead(power, i-1))); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); - break; - } -#endif -#ifdef USE_LIGHT - } -#endif - } - - if (pwm_present) { - ResponseAppend_P(PSTR(",")); - MqttShowPWMState(); - } - - int32_t rssi = WiFi.RSSI(); - ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WiFi.BSSIDstr().c_str(), WiFi.channel(), - WifiGetRssiAsQuality(rssi), rssi, WifiLinkCount(), WifiDowntime().c_str()); -} - -void MqttPublishTeleState(void) -{ - mqtt_data[0] = '\0'; - MqttShowState(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), MQTT_TELE_RETAIN); -#if defined(USE_RULES) || defined(USE_SCRIPT) - RulesTeleperiod(); -#endif -} - -bool MqttShowSensor(void) -{ - ResponseAppendTime(); - - int json_data_start = strlen(mqtt_data); - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { -#ifdef USE_TM1638 - if ((pin[GPIO_SWT1 +i] < 99) || ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99))) { -#else - if (pin[GPIO_SWT1 +i] < 99) { -#endif - ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(SwitchState(i))); - } - } - XsnsCall(FUNC_JSON_APPEND); - XdrvCall(FUNC_JSON_APPEND); - - bool json_data_available = (strlen(mqtt_data) - json_data_start); - if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { - ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); - } - if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); - } - ResponseJsonEnd(); - - if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } - return json_data_available; -} - -void MqttPublishSensor(void) -{ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishTeleSensor(); - } -} -# 714 "S:/Development/Tasmota/tasmota/support_tasmota.ino" -void PerformEverySecond(void) -{ - uptime++; - - if (POWER_CYCLE_TIME == uptime) { - UpdateQuickPowerCycle(false); - } - - if (BOOT_LOOP_TIME == uptime) { - RtcRebootReset(); - -#ifdef USE_DEEPSLEEP - if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { -#endif - Settings.bootcount++; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount); -#ifdef USE_DEEPSLEEP - } -#endif - } - - if (mqtt_cmnd_blocked_reset) { - mqtt_cmnd_blocked_reset--; - if (!mqtt_cmnd_blocked_reset) { - mqtt_cmnd_blocked = 0; - } - } - - if (seriallog_timer) { - seriallog_timer--; - if (!seriallog_timer) { - if (seriallog_level) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED)); - } - seriallog_level = 0; - } - } - - if (syslog_timer) { - syslog_timer--; - if (!syslog_timer) { - syslog_level = Settings.syslog_level; - if (Settings.syslog_level) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); - } - } - } - - ResetGlobalValues(); - - if (Settings.tele_period) { - if (tele_period >= 9999) { - if (!global_state.wifi_down) { - tele_period = 0; - } - } else { - tele_period++; - if (tele_period >= Settings.tele_period) { - tele_period = 0; - - MqttPublishTeleState(); - - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#if defined(USE_RULES) || defined(USE_SCRIPT) - RulesTeleperiod(); -#endif - } - - XdrvCall(FUNC_AFTER_TELEPERIOD); - } - } - } -} - - - - - -void Every100mSeconds(void) -{ - - power_t power_now; - - if (prepped_loglevel) { - AddLog(prepped_loglevel); - prepped_loglevel = 0; - } - - if (latching_relay_pulse) { - latching_relay_pulse--; - if (!latching_relay_pulse) SetLatchingRelay(0, 0); - } - - for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if (pulse_timer[i] != 0L) { - if (TimeReached(pulse_timer[i])) { - pulse_timer[i] = 0L; - ExecuteCommandPower(i +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER); - } - } - } - - if (blink_mask) { - if (TimeReached(blink_timer)) { - SetNextTimeInterval(blink_timer, 100 * Settings.blinktime); - blink_counter--; - if (!blink_counter) { - StopAllPowerBlink(); - } else { - blink_power ^= 1; - power_now = (power & (POWER_MASK ^ blink_mask)) | ((blink_power) ? blink_mask : 0); - SetDevicePower(power_now, SRC_IGNORE); - } - } - } -} - - - - - -void Every250mSeconds(void) -{ - - - uint32_t blinkinterval = 1; - - state_250mS++; - state_250mS &= 0x3; - - if (!Settings.flag.global_state) { - if (global_state.data) { - if (global_state.mqtt_down) { blinkinterval = 7; } - if (global_state.wifi_down) { blinkinterval = 3; } - blinks = 201; - } - } - if (blinks || restart_flag || ota_state_flag) { - if (restart_flag || ota_state_flag) { - blinkstate = true; - } else { - blinkspeed--; - if (!blinkspeed) { - blinkspeed = blinkinterval; - blinkstate ^= 1; - } - } - if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (blinks > 200) || (blinkstate))) { - SetLedLink(blinkstate); - } - if (!blinkstate) { - blinks--; - if (200 == blinks) blinks = 0; - } - } - if (Settings.ledstate &1 && (pin[GPIO_LEDLNK] < 99 || !(blinks || restart_flag || ota_state_flag)) ) { - bool tstate = power & Settings.ledmask; - if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) { - tstate = (!power) ? 1 : 0; - } - SetLedPower(tstate); - } - - - - - - switch (state_250mS) { - case 0: - if (ota_state_flag && BACKLOG_EMPTY) { - ota_state_flag--; - if (2 == ota_state_flag) { - RtcSettings.ota_loader = 0; - ota_retry_counter = OTA_ATTEMPTS; - ESPhttpUpdate.rebootOnUpdate(false); - SettingsSave(1); - } - if (ota_state_flag <= 0) { -#ifdef USE_WEBSERVER - if (Settings.webserver) StopWebserver(); -#endif -#ifdef USE_ARILUX_RF - AriluxRfDisable(); -#endif - ota_state_flag = 92; - ota_result = 0; - ota_retry_counter--; - if (ota_retry_counter) { - strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data)); -#ifndef FIRMWARE_MINIMAL - if (RtcSettings.ota_loader) { -# 919 "S:/Development/Tasmota/tasmota/support_tasmota.ino" - char *bch = strrchr(mqtt_data, '/'); - if (bch == nullptr) { bch = mqtt_data; } - - char *ech = strrchr(bch, '.'); - if ((ech != nullptr) && (0 == strncasecmp_P(ech, PSTR(".GZ"), 3))) { - char *fch = ech; - *fch = '\0'; - ech = strrchr(bch, '.'); - *fch = '.'; - } - if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } - char ota_url_type[strlen(ech) +1]; - strncpy(ota_url_type, ech, sizeof(ota_url_type)); - - char *pch = strrchr(bch, '-'); - if (pch == nullptr) { pch = ech; } - *pch = '\0'; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ota_url_type); - } -#endif - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s"), mqtt_data); -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); -#else - - WiFiClient OTAclient; - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); -#endif - if (!ota_result) { -#ifndef FIRMWARE_MINIMAL - int ota_error = ESPhttpUpdate.getLastError(); - DEBUG_CORE_LOG(PSTR("OTA: Error %d"), ota_error); - if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) { - RtcSettings.ota_loader = 1; - } -#endif - ota_state_flag = 2; - } - } - } - if (90 == ota_state_flag) { - ota_state_flag = 0; - Response_P(PSTR("{\"" D_CMND_UPGRADE "\":\"")); - if (ota_result) { - - if (!VersionCompatible()) { - ResponseAppend_P(PSTR(D_JSON_FAILED " " D_UPLOAD_ERR_14)); - } else { - ResponseAppend_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); - restart_flag = 2; - } - } else { - ResponseAppend_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); - } - ResponseAppend_P(PSTR("\"}")); - - MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); - } - } - break; - case 1: - if (MidnightNow()) { - XsnsCall(FUNC_SAVE_AT_MIDNIGHT); - } - if (save_data_counter && BACKLOG_EMPTY) { - save_data_counter--; - if (save_data_counter <= 0) { - if (Settings.flag.save_state) { - power_t mask = POWER_MASK; - for (uint32_t i = 0; i < MAX_PULSETIMERS; i++) { - if ((Settings.pulse_timer[i] > 0) && (Settings.pulse_timer[i] < 30)) { - mask &= ~(1 << i); - } - } - if (!((Settings.power &mask) == (power &mask))) { - Settings.power = power; - } - } else { - Settings.power = 0; - } - SettingsSave(0); - save_data_counter = Settings.save_data; - } - } - if (restart_flag && BACKLOG_EMPTY) { - if ((214 == restart_flag) || (215 == restart_flag) || (216 == restart_flag)) { - - char storage_ssid1[strlen(SettingsText(SET_STASSID1)) +1]; - strncpy(storage_ssid1, SettingsText(SET_STASSID1), sizeof(storage_ssid1)); - char storage_ssid2[strlen(SettingsText(SET_STASSID2)) +1]; - strncpy(storage_ssid2, SettingsText(SET_STASSID2), sizeof(storage_ssid2)); - char storage_pass1[strlen(SettingsText(SET_STAPWD1)) +1]; - strncpy(storage_pass1, SettingsText(SET_STAPWD1), sizeof(storage_pass1)); - char storage_pass2[strlen(SettingsText(SET_STAPWD2)) +1]; - strncpy(storage_pass2, SettingsText(SET_STAPWD2), sizeof(storage_pass2)); - - char storage_mqtthost[strlen(SettingsText(SET_MQTT_HOST)) +1]; - strncpy(storage_mqtthost, SettingsText(SET_MQTT_HOST), sizeof(storage_mqtthost)); - char storage_mqttuser[strlen(SettingsText(SET_MQTT_USER)) +1]; - strncpy(storage_mqttuser, SettingsText(SET_MQTT_USER), sizeof(storage_mqttuser)); - char storage_mqttpwd[strlen(SettingsText(SET_MQTT_PWD)) +1]; - strncpy(storage_mqttpwd, SettingsText(SET_MQTT_PWD), sizeof(storage_mqttpwd)); - char storage_mqtttopic[strlen(SettingsText(SET_MQTT_TOPIC)) +1]; - strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic)); - uint16_t mqtt_port = Settings.mqtt_port; - - - - - if ((215 == restart_flag) || (216 == restart_flag)) { - SettingsErase(0); - } - SettingsDefault(); - - SettingsUpdateText(SET_STASSID1, storage_ssid1); - SettingsUpdateText(SET_STASSID2, storage_ssid2); - SettingsUpdateText(SET_STAPWD1, storage_pass1); - SettingsUpdateText(SET_STAPWD2, storage_pass2); - if (216 == restart_flag) { - - SettingsUpdateText(SET_MQTT_HOST, storage_mqtthost); - SettingsUpdateText(SET_MQTT_USER, storage_mqttuser); - SettingsUpdateText(SET_MQTT_PWD, storage_mqttpwd); - SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic); - Settings.mqtt_port = mqtt_port; - } - restart_flag = 2; - } - else if (213 == restart_flag) { - SettingsSdkErase(); - restart_flag = 2; - } - else if (212 == restart_flag) { - SettingsErase(0); - restart_flag = 211; - } - if (211 == restart_flag) { - SettingsDefault(); - restart_flag = 2; - } - if (2 == restart_flag) { - SettingsSaveAll(); - } - restart_flag--; - if (restart_flag <= 0) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); - EspRestart(); - } - } - break; - case 2: - WifiCheck(wifi_state_flag); - wifi_state_flag = WIFI_RESTART; - break; - case 3: - if (!global_state.wifi_down) { MqttCheck(); } - break; - } -} - -#ifdef USE_ARDUINO_OTA - - - - - - - -bool arduino_ota_triggered = false; -uint16_t arduino_ota_progress_dot_count = 0; - -void ArduinoOTAInit(void) -{ - ArduinoOTA.setPort(8266); - ArduinoOTA.setHostname(my_hostname); - if (strlen(SettingsText(SET_WEBPWD))) { - ArduinoOTA.setPassword(SettingsText(SET_WEBPWD)); - } - - ArduinoOTA.onStart([]() - { - SettingsSave(1); -#ifdef USE_WEBSERVER - if (Settings.webserver) { StopWebserver(); } -#endif -#ifdef USE_ARILUX_RF - AriluxRfDisable(); -#endif - if (Settings.flag.mqtt_enabled) { - MqttDisconnect(); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED)); - arduino_ota_triggered = true; - arduino_ota_progress_dot_count = 0; - delay(100); - }); - - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) - { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { - arduino_ota_progress_dot_count++; - Serial.printf("."); - if (!(arduino_ota_progress_dot_count % 80)) { Serial.println(); } - } - }); - - ArduinoOTA.onError([](ota_error_t error) - { - - - - - char error_str[100]; - - if ((LOG_LEVEL_DEBUG <= seriallog_level) && arduino_ota_progress_dot_count) { Serial.println(); } - switch (error) { - case OTA_BEGIN_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_2), sizeof(error_str)); break; - case OTA_RECEIVE_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_5), sizeof(error_str)); break; - case OTA_END_ERROR: strncpy_P(error_str, PSTR(D_UPLOAD_ERR_7), sizeof(error_str)); break; - default: - snprintf_P(error_str, sizeof(error_str), PSTR(D_UPLOAD_ERROR_CODE " %d"), error); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA %s. " D_RESTARTING), error_str); - EspRestart(); - }); - - ArduinoOTA.onEnd([]() - { - if ((LOG_LEVEL_DEBUG <= seriallog_level)) { Serial.println(); } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_SUCCESSFUL ". " D_RESTARTING)); - EspRestart(); - }); - - ArduinoOTA.begin(); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_ENABLED " " D_PORT " 8266")); -} - -void ArduinoOtaLoop(void) -{ - MDNS.update(); - ArduinoOTA.handle(); - - while (arduino_ota_triggered) { ArduinoOTA.handle(); } -} -#endif - - - -void SerialInput(void) -{ - while (Serial.available()) { - - delay(0); - serial_in_byte = Serial.read(); - - - - - if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) { - serial_in_byte = ButtonSerial(serial_in_byte); - } - - - - if (XdrvCall(FUNC_SERIAL)) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - - - - if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - if (!Settings.flag.mqtt_serial) { - if (isprint(serial_in_byte)) { - if (serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } else { - serial_in_byte_counter = 0; - } - } - } else { - if (serial_in_byte || Settings.flag.mqtt_serial_raw) { - if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && - ((isprint(serial_in_byte) && (128 == Settings.serial_delimiter)) || - ((serial_in_byte != Settings.serial_delimiter) && (128 != Settings.serial_delimiter)) || - Settings.flag.mqtt_serial_raw)) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - serial_polling_window = millis(); - } else { - serial_polling_window = 0; - break; - } - } - } - -#ifdef USE_SONOFF_SC - - - - if (SONOFF_SC == my_module_type) { - if (serial_in_byte == '\x1B') { - serial_in_buffer[serial_in_byte_counter] = 0; - SonoffScSerialInput(serial_in_buffer); - serial_in_byte_counter = 0; - Serial.flush(); - return; - } - } else -#endif - - - if (!Settings.flag.mqtt_serial && (serial_in_byte == '\n')) { - serial_in_buffer[serial_in_byte_counter] = 0; - seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), serial_in_buffer); - ExecuteCommand(serial_in_buffer, SRC_SERIAL); - serial_in_byte_counter = 0; - serial_polling_window = 0; - Serial.flush(); - return; - } - } - - if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { - serial_in_buffer[serial_in_byte_counter] = 0; - char hex_char[(serial_in_byte_counter * 2) + 2]; - bool assume_json = (!Settings.flag.mqtt_serial_raw && (serial_in_buffer[0] == '{')); - Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":%s%s%s}"), - (assume_json) ? "" : """", - (Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer, - (assume_json) ? "" : """"); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); - XdrvRulesProcess(); - serial_in_byte_counter = 0; - } -} - - - -void GpioInit(void) -{ - uint32_t mpin; - - if (!ValidModule(Settings.module)) { - uint32_t module = MODULE; - if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } - Settings.module = module; - Settings.last_module = module; - } - SetModuleType(); - - if (Settings.module != Settings.last_module) { - Settings.baudrate = APP_BAUDRATE / 300; - Settings.serial_config = TS_SERIAL_8N1; - } - - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - if ((Settings.user_template.gp.io[i] >= GPIO_SENSOR_END) && (Settings.user_template.gp.io[i] < GPIO_USER)) { - Settings.user_template.gp.io[i] = GPIO_USER; - } - } - - myio def_gp; - ModuleGpios(&def_gp); - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if ((Settings.my_gp.io[i] >= GPIO_SENSOR_END) && (Settings.my_gp.io[i] < GPIO_USER)) { - Settings.my_gp.io[i] = GPIO_NONE; - } - else if (Settings.my_gp.io[i] > GPIO_NONE) { - my_module.io[i] = Settings.my_gp.io[i]; - } - if ((def_gp.io[i] > GPIO_NONE) && (def_gp.io[i] < GPIO_USER)) { - my_module.io[i] = def_gp.io[i]; - } - } - if ((Settings.my_adc0 >= ADC0_END) && (Settings.my_adc0 < ADC0_USER)) { - Settings.my_adc0 = ADC0_NONE; - } - else if (Settings.my_adc0 > ADC0_NONE) { - my_adc0 = Settings.my_adc0; - } - my_module_flag = ModuleFlag(); - uint32_t template_adc0 = my_module_flag.data &15; - if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) { - my_adc0 = template_adc0; - } - - for (uint32_t i = 0; i < GPIO_MAX; i++) { - pin[i] = 99; - } - for (uint32_t i = 0; i < sizeof(my_module.io); i++) { - mpin = ValidPin(i, my_module.io[i]); - - DEBUG_CORE_LOG(PSTR("INI: gpio pin %d, mpin %d"), i, mpin); - - if (mpin) { - XdrvMailbox.index = mpin; - XdrvMailbox.payload = i; - - if ((mpin >= GPIO_SWT1_NP) && (mpin < (GPIO_SWT1_NP + MAX_SWITCHES))) { - SwitchPullupFlag(mpin - GPIO_SWT1_NP); - mpin -= (GPIO_SWT1_NP - GPIO_SWT1); - } - else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_NP); - mpin -= (GPIO_KEY1_NP - GPIO_KEY1); - } - else if ((mpin >= GPIO_KEY1_INV) && (mpin < (GPIO_KEY1_INV + MAX_KEYS))) { - ButtonInvertFlag(mpin - GPIO_KEY1_INV); - mpin -= (GPIO_KEY1_INV - GPIO_KEY1); - } - else if ((mpin >= GPIO_KEY1_INV_NP) && (mpin < (GPIO_KEY1_INV_NP + MAX_KEYS))) { - ButtonPullupFlag(mpin - GPIO_KEY1_INV_NP); - ButtonInvertFlag(mpin - GPIO_KEY1_INV_NP); - mpin -= (GPIO_KEY1_INV_NP - GPIO_KEY1); - } - else if ((mpin >= GPIO_REL1_INV) && (mpin < (GPIO_REL1_INV + MAX_RELAYS))) { - bitSet(rel_inverted, mpin - GPIO_REL1_INV); - mpin -= (GPIO_REL1_INV - GPIO_REL1); - } - else if ((mpin >= GPIO_LED1_INV) && (mpin < (GPIO_LED1_INV + MAX_LEDS))) { - bitSet(led_inverted, mpin - GPIO_LED1_INV); - mpin -= (GPIO_LED1_INV - GPIO_LED1); - } - else if (mpin == GPIO_LEDLNK_INV) { - ledlnk_inverted = 1; - mpin -= (GPIO_LEDLNK_INV - GPIO_LEDLNK); - } - else if ((mpin >= GPIO_PWM1_INV) && (mpin < (GPIO_PWM1_INV + MAX_PWMS))) { - bitSet(pwm_inverted, mpin - GPIO_PWM1_INV); - mpin -= (GPIO_PWM1_INV - GPIO_PWM1); - } - else if (XdrvCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - } - else if (XsnsCall(FUNC_PIN_STATE)) { - mpin = XdrvMailbox.index; - }; - } - if (mpin) pin[mpin] = i; - } - - if ((2 == pin[GPIO_TXD]) || (H801 == my_module_type)) { Serial.set_tx(2); } - - analogWriteRange(Settings.pwm_range); - analogWriteFreq(Settings.pwm_frequency); - -#ifdef USE_SPI - spi_flg = ((((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CS] > 14)) || (pin[GPIO_SPI_CS] < 12)) || (((pin[GPIO_SPI_DC] < 99) && (pin[GPIO_SPI_DC] > 14)) || (pin[GPIO_SPI_DC] < 12))); - if (spi_flg) { - for (uint32_t i = 0; i < GPIO_MAX; i++) { - if ((pin[i] >= 12) && (pin[i] <=14)) pin[i] = 99; - } - my_module.io[12] = GPIO_SPI_MISO; - pin[GPIO_SPI_MISO] = 12; - my_module.io[13] = GPIO_SPI_MOSI; - pin[GPIO_SPI_MOSI] = 13; - my_module.io[14] = GPIO_SPI_CLK; - pin[GPIO_SPI_CLK] = 14; - } - soft_spi_flg = ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && ((pin[GPIO_SSPI_MOSI] < 99) || (pin[GPIO_SSPI_MOSI] < 99))); -#endif - -#ifdef USE_I2C - i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99)); - if (i2c_flg) { - Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]); - } -#endif - - devices_present = 0; - light_type = LT_BASIC; - if (XdrvCall(FUNC_MODULE_INIT)) { - - } - else if (YTF_IR_BRIDGE == my_module_type) { - ClaimSerial(); - - } - else if (SONOFF_DUAL == my_module_type) { - devices_present = 2; - SetSerial(19200, TS_SERIAL_8N1); - } - else if (CH4 == my_module_type) { - devices_present = 4; - SetSerial(19200, TS_SERIAL_8N1); - } -#ifdef USE_SONOFF_SC - else if (SONOFF_SC == my_module_type) { - SetSerial(19200, TS_SERIAL_8N1); - } -#endif - - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 +i] < 99) { - pinMode(pin[GPIO_PWM1 +i], OUTPUT); - if (light_type) { - - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range : 0); - } else { - pwm_present = true; - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]); - } - } - } - - for (uint32_t i = 0; i < MAX_RELAYS; i++) { - if (pin[GPIO_REL1 +i] < 99) { - pinMode(pin[GPIO_REL1 +i], OUTPUT); - devices_present++; - if (EXS_RELAY == my_module_type) { - digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0); - if (i &1) { devices_present--; } - } - } - } - - for (uint32_t i = 0; i < MAX_LEDS; i++) { - if (pin[GPIO_LED1 +i] < 99) { -#ifdef USE_ARILUX_RF - if ((3 == i) && (leds_present < 2) && (99 == pin[GPIO_ARIRFSEL])) { - pin[GPIO_ARIRFSEL] = pin[GPIO_LED4]; - pin[GPIO_LED4] = 99; - } else { -#endif - pinMode(pin[GPIO_LED1 +i], OUTPUT); - leds_present++; - digitalWrite(pin[GPIO_LED1 +i], bitRead(led_inverted, i)); -#ifdef USE_ARILUX_RF - } -#endif - } - } - if (pin[GPIO_LEDLNK] < 99) { - pinMode(pin[GPIO_LEDLNK], OUTPUT); - digitalWrite(pin[GPIO_LEDLNK], ledlnk_inverted); - } - - ButtonInit(); - SwitchInit(); -#ifdef ROTARY_V1 - RotaryInit(); -#endif - - SetLedPower(Settings.ledstate &8); - SetLedLink(Settings.ledstate &8); - - XdrvCall(FUNC_PRE_INIT); -} -# 1 "S:/Development/Tasmota/tasmota/support_udp.ino" -# 20 "S:/Development/Tasmota/tasmota/support_udp.ino" -#ifdef USE_EMULATION - -#define UDP_BUFFER_SIZE 200 -#define UDP_MSEARCH_SEND_DELAY 1500 - -#include -Ticker TickerMSearch; - -IPAddress udp_remote_ip; -uint16_t udp_remote_port; - -bool udp_connected = false; -bool udp_response_mutex = false; - - - - - -const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**"; -const char URN_BELKIN_DEVICE_CAP[] PROGMEM = "urn:Belkin:device:**"; -const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice"; -const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all"; -const char SSDP_ALL[] PROGMEM = "ssdp:all"; - - - - - -bool UdpDisconnect(void) -{ - if (udp_connected) { - PortUdp.flush(); - WiFiUDP::stopAll(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); - udp_connected = false; - } - return udp_connected; -} - -bool UdpConnect(void) -{ - if (!udp_connected) { - - if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); - udp_response_mutex = false; - udp_connected = true; - } else { - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_JOIN_FAILED)); - udp_connected = false; - } - } - return udp_connected; -} - -void PollUdp(void) -{ - if (udp_connected) { - while (PortUdp.parsePacket()) { - char packet_buffer[UDP_BUFFER_SIZE]; - - int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); - packet_buffer[len] = 0; - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); - - - - if (Settings.flag2.emulation) { -#ifdef USE_SCRIPT_HUE - if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { -#else - if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { -#endif - udp_response_mutex = true; - - udp_remote_ip = PortUdp.remoteIP(); - udp_remote_port = PortUdp.remotePort(); - - - - - uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); - - LowerCase(packet_buffer, packet_buffer); - RemoveSpace(packet_buffer); - -#ifdef USE_EMULATION_WEMO - if (EMUL_WEMO == Settings.flag2.emulation) { - if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { - TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); - return; - } - else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || - (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || - (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { - TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); - return; - } - } -#endif - -#ifdef USE_EMULATION_HUE - if (EMUL_HUE == Settings.flag2.emulation) { - if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || - (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || - (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || - (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { - TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); - return; - } - } -#endif - - udp_response_mutex = false; - continue; - } - } - -#ifdef USE_DEVICE_GROUPS - if (Settings.flag4.device_groups_enabled && !strncmp_P(packet_buffer, kDeviceGroupMessage, sizeof(DEVICE_GROUP_MESSAGE) - 1)) { - ProcessDeviceGroupMessage(packet_buffer, len); - } -#endif - } - optimistic_yield(100); - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/support_wifi.ino" -# 24 "S:/Development/Tasmota/tasmota/support_wifi.ino" -#ifndef WIFI_RSSI_THRESHOLD -#define WIFI_RSSI_THRESHOLD 10 -#endif -#ifndef WIFI_RESCAN_MINUTES -#define WIFI_RESCAN_MINUTES 44 -#endif - -const uint8_t WIFI_CONFIG_SEC = 180; -const uint8_t WIFI_CHECK_SEC = 20; -const uint8_t WIFI_RETRY_OFFSET_SEC = 20; - -#include -#if LWIP_IPV6 -#include -#endif - -struct WIFI { - uint32_t last_event = 0; - uint32_t downtime = 0; - uint16_t link_count = 0; - uint8_t counter; - uint8_t retry_init; - uint8_t retry; - uint8_t status; - uint8_t config_type = 0; - uint8_t config_counter = 0; - uint8_t mdns_begun = 0; - uint8_t scan_state; - uint8_t bssid[6]; - int8_t best_network_db; -} Wifi; - -int WifiGetRssiAsQuality(int rssi) -{ - int quality = 0; - - if (rssi <= -100) { - quality = 0; - } else if (rssi >= -50) { - quality = 100; - } else { - quality = 2 * (rssi + 100); - } - return quality; -} - -bool WifiConfigCounter(void) -{ - if (Wifi.config_counter) { - Wifi.config_counter = WIFI_CONFIG_SEC; - } - return (Wifi.config_counter); -} - -void WifiConfig(uint8_t type) -{ - if (!Wifi.config_type) { - if ((WIFI_RETRY == type) || (WIFI_WAIT == type)) { return; } -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - WiFi.disconnect(); - Wifi.config_type = type; - -#ifndef USE_WEBSERVER - if (WIFI_MANAGER == Wifi.config_type) { - Wifi.config_type = WIFI_SERIAL; - } -#endif - - Wifi.config_counter = WIFI_CONFIG_SEC; - Wifi.counter = Wifi.config_counter +5; - blinks = 1999; - if (WIFI_RESTART == Wifi.config_type) { - restart_flag = 2; - } - else if (WIFI_SERIAL == Wifi.config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_6_SERIAL " " D_ACTIVE_FOR_3_MINUTES)); - } -#ifdef USE_WEBSERVER - else if (WIFI_MANAGER == Wifi.config_type || WIFI_MANAGER_RESET_ONLY == Wifi.config_type) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_WCFG_2_WIFIMANAGER " " D_ACTIVE_FOR_3_MINUTES)); - WifiManagerBegin(WIFI_MANAGER_RESET_ONLY == Wifi.config_type); - } -#endif - } -} - -void WifiSetMode(WiFiMode_t wifi_mode) -{ - if (WiFi.getMode() == wifi_mode) { return; } - - if (wifi_mode != WIFI_OFF) { - - WiFi.forceSleepWake(); - delay(100); - } - - uint32_t retry = 2; - while (!WiFi.mode(wifi_mode) && retry--) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR("Retry set Mode...")); - delay(100); - } - - if (wifi_mode == WIFI_OFF) { - delay(1000); - WiFi.forceSleepBegin(); - delay(1); - } else { - delay(30); - } -} - -void WiFiSetSleepMode(void) -{ -# 152 "S:/Development/Tasmota/tasmota/support_wifi.ino" -#if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) -#else - if (sleep && Settings.flag3.sleep_normal) { - WiFi.setSleepMode(WIFI_LIGHT_SLEEP); - } else { - WiFi.setSleepMode(WIFI_MODEM_SLEEP); - } -#endif - WifiSetOutputPower(); -} - -void WifiBegin(uint8_t flag, uint8_t channel) -{ - const char kWifiPhyMode[] = " BGN"; - -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - -#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_PATCH_ISSUE_2186)); - - WifiSetMode(WIFI_OFF); -#endif - - WiFi.persistent(false); - WiFi.disconnect(true); - delay(200); - - WifiSetMode(WIFI_STA); - WiFiSetSleepMode(); - - - if (!WiFi.getAutoConnect()) { WiFi.setAutoConnect(true); } - - switch (flag) { - case 0: - case 1: - Settings.sta_active = flag; - break; - case 2: - Settings.sta_active ^= 1; - } - if (!strlen(SettingsText(SET_STASSID1 + Settings.sta_active))) { - Settings.sta_active ^= 1; - } - if (Settings.ip_address[0]) { - WiFi.config(Settings.ip_address[0], Settings.ip_address[1], Settings.ip_address[2], Settings.ip_address[3]); - } - WiFi.hostname(my_hostname); - - char stemp[40] = { 0 }; - if (channel) { - WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid); - - char hex_char[18]; - snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s"), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':')); - } else { - WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active)); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."), - Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, kWifiPhyMode[WiFi.getPhyMode() & 0x3], my_hostname); - -#if LWIP_IPV6 - for (bool configured = false; !configured;) { - uint16_t cfgcnt = 0; - for (auto addr : addrList) { - if ((configured = !addr.isLocal() && addr.isV6()) || cfgcnt==30) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI "Got IPv6 global address %s"), addr.toString().c_str()); - break; - } - delay(500); - cfgcnt++; - } - } -#endif -} - -void WifiBeginAfterScan(void) -{ - - if (0 == Wifi.scan_state) { return; } - - if (1 == Wifi.scan_state) { - memset((void*) &Wifi.bssid, 0, sizeof(Wifi.bssid)); - Wifi.best_network_db = -127; - Wifi.scan_state = 3; - } - - if (2 == Wifi.scan_state) { - uint8_t* bssid = WiFi.BSSID(); - memcpy((void*) &Wifi.bssid, (void*) bssid, sizeof(Wifi.bssid)); - Wifi.best_network_db = WiFi.RSSI(); - if (Wifi.best_network_db < -WIFI_RSSI_THRESHOLD) { - Wifi.best_network_db += WIFI_RSSI_THRESHOLD; - } - Wifi.scan_state = 3; - } - - if (3 == Wifi.scan_state) { - if (WiFi.scanComplete() != WIFI_SCAN_RUNNING) { - WiFi.scanNetworks(true); - Wifi.scan_state++; - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR("Network (re)scan started...")); - return; - } - } - int8_t wifi_scan_result = WiFi.scanComplete(); - - if (4 == Wifi.scan_state) { - if (wifi_scan_result != WIFI_SCAN_RUNNING) { - Wifi.scan_state++; - } - } - - if (5 == Wifi.scan_state) { - int32_t channel = 0; - int8_t ap = 3; - uint8_t last_bssid[6]; - memcpy((void*) &last_bssid, (void*) &Wifi.bssid, sizeof(last_bssid)); - - if (wifi_scan_result > 0) { - - for (uint32_t i = 0; i < wifi_scan_result; ++i) { - - String ssid_scan; - int32_t rssi_scan; - uint8_t sec_scan; - uint8_t* bssid_scan; - int32_t chan_scan; - bool hidden_scan; - - WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, bssid_scan, chan_scan, hidden_scan); - - bool known = false; - uint32_t j; - for (j = 0; j < MAX_SSIDS; j++) { - if (ssid_scan == SettingsText(SET_STASSID1 + j)) { - known = true; - if (rssi_scan > Wifi.best_network_db) { - if (sec_scan == ENC_TYPE_NONE || SettingsText(SET_STAPWD1 + j)) { - Wifi.best_network_db = (int8_t)rssi_scan; - channel = chan_scan; - ap = j; - memcpy((void*) &Wifi.bssid, (void*) bssid_scan, sizeof(Wifi.bssid)); - } - } - break; - } - } - char hex_char[18]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Network %d, AP%c, SSId %s, Channel %d, BSSId %s, RSSI %d, Encryption %d"), - i, - (known) ? (j) ? '2' : '1' : '-', - ssid_scan.c_str(), - chan_scan, - ToHex_P((unsigned char*)bssid_scan, 6, hex_char, sizeof(hex_char), ':'), - rssi_scan, - (sec_scan == ENC_TYPE_NONE) ? 0 : 1); - delay(0); - } - WiFi.scanDelete(); - delay(0); - } - Wifi.scan_state = 0; - - for (uint32_t i = 0; i < sizeof(Wifi.bssid); i++) { - if (last_bssid[i] != Wifi.bssid[i]) { - WifiBegin(ap, channel); - break; - } - } - } -} - -uint16_t WifiLinkCount(void) -{ - return Wifi.link_count; -} - -String WifiDowntime(void) -{ - return GetDuration(Wifi.downtime); -} - -void WifiSetState(uint8_t state) -{ - if (state == global_state.wifi_down) { - if (state) { - rules_flag.wifi_connected = 1; - Wifi.link_count++; - Wifi.downtime += UpTime() - Wifi.last_event; - } else { - rules_flag.wifi_disconnected = 1; - Wifi.last_event = UpTime(); - } - } - global_state.wifi_down = state ^1; -} - -#if LWIP_IPV6 -bool WifiCheckIPv6(void) -{ - bool ipv6_global=false; - - for (auto a : addrList) { - if(!a.isLocal() && a.isV6()) ipv6_global=true; - } - return ipv6_global; -} - -String WifiGetIPv6(void) -{ - for (auto a : addrList) { - if(!a.isLocal() && a.isV6()) return a.toString(); - } - return ""; -} - -bool WifiCheckIPAddrStatus(void) -{ - bool ip_global=false; - - for (auto a : addrList) { - if(!a.isLocal()) ip_global=true; - } - return ip_global; -} -#endif - -void WifiCheckIp(void) -{ -#if LWIP_IPV6 - if(WifiCheckIPAddrStatus()) { - Wifi.status = WL_CONNECTED; -#else - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0)) { -#endif - WifiSetState(1); - Wifi.counter = WIFI_CHECK_SEC; - Wifi.retry = Wifi.retry_init; - if (Wifi.status != WL_CONNECTED) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECTED)); - - Settings.ip_address[1] = (uint32_t)WiFi.gatewayIP(); - Settings.ip_address[2] = (uint32_t)WiFi.subnetMask(); - Settings.ip_address[3] = (uint32_t)WiFi.dnsIP(); - } - Wifi.status = WL_CONNECTED; -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - if (2 == Wifi.mdns_begun) { - MDNS.update(); - AddLog_P(LOG_LEVEL_DEBUG_MORE, D_LOG_MDNS, "MDNS.update"); - } -#endif -#endif - } else { - WifiSetState(0); - uint8_t wifi_config_tool = Settings.sta_config; - Wifi.status = WiFi.status(); - switch (Wifi.status) { - case WL_CONNECTED: - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_NO_IP_ADDRESS)); - Wifi.status = 0; - Wifi.retry = Wifi.retry_init; - break; - case WL_NO_SSID_AVAIL: - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_NOT_REACHED)); - if (WIFI_WAIT == Settings.sta_config) { - Wifi.retry = Wifi.retry_init; - } else { - if (Wifi.retry > (Wifi.retry_init / 2)) { - Wifi.retry = Wifi.retry_init / 2; - } - else if (Wifi.retry) { - Wifi.retry = 0; - } - } - break; - case WL_CONNECT_FAILED: - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_WRONG_PASSWORD)); - if (Wifi.retry > (Wifi.retry_init / 2)) { - Wifi.retry = Wifi.retry_init / 2; - } - else if (Wifi.retry) { - Wifi.retry = 0; - } - break; - default: - if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) { - AddLog_P(LOG_LEVEL_INFO, S_LOG_WIFI, PSTR(D_CONNECT_FAILED_AP_TIMEOUT)); - } else { - if (!strlen(SettingsText(SET_STASSID1)) && !strlen(SettingsText(SET_STASSID2))) { - wifi_config_tool = WIFI_MANAGER; - Wifi.retry = 0; - } else { - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, PSTR(D_ATTEMPTING_CONNECTION)); - } - } - } - if (Wifi.retry) { - if (Settings.flag3.use_wifi_scan) { - if (Wifi.retry_init == Wifi.retry) { - Wifi.scan_state = 1; - } - } else { - if (Wifi.retry_init == Wifi.retry) { - WifiBegin(3, 0); - } - if ((Settings.sta_config != WIFI_WAIT) && ((Wifi.retry_init / 2) == Wifi.retry)) { - WifiBegin(2, 0); - } - } - Wifi.counter = 1; - Wifi.retry--; - } else { - WifiConfig(wifi_config_tool); - Wifi.counter = 1; - Wifi.retry = Wifi.retry_init; - } - } -} - -void WifiCheck(uint8_t param) -{ - Wifi.counter--; - switch (param) { - case WIFI_SERIAL: - case WIFI_MANAGER: - WifiConfig(param); - break; - default: - if (Wifi.config_counter) { - Wifi.config_counter--; - Wifi.counter = Wifi.config_counter +5; - if (Wifi.config_counter) { - if (!Wifi.config_counter) { - if (strlen(WiFi.SSID().c_str())) { - SettingsUpdateText(SET_STASSID1, WiFi.SSID().c_str()); - } - if (strlen(WiFi.psk().c_str())) { - SettingsUpdateText(SET_STAPWD1, WiFi.psk().c_str()); - } - Settings.sta_active = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), SettingsText(SET_STASSID1)); - } - } - if (!Wifi.config_counter) { - - restart_flag = 2; - } - } else { - if (Wifi.scan_state) { WifiBeginAfterScan(); } - - if (Wifi.counter <= 0) { - AddLog_P(LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CHECKING_CONNECTION)); - Wifi.counter = WIFI_CHECK_SEC; - WifiCheckIp(); - } -#if LWIP_IPV6 - if (WifiCheckIPAddrStatus()) { -#else - if ((WL_CONNECTED == WiFi.status()) && (static_cast(WiFi.localIP()) != 0) && !Wifi.config_type) { -#endif - WifiSetState(1); - - if (Settings.flag3.use_wifi_rescan) { - if (!(uptime % (60 * WIFI_RESCAN_MINUTES))) { - Wifi.scan_state = 2; - } - } - -#ifdef FIRMWARE_MINIMAL - if (1 == RtcSettings.ota_loader) { - RtcSettings.ota_loader = 0; - ota_state_flag = 3; - } -#endif - -#ifdef USE_DISCOVERY - if (Settings.flag3.mdns_enabled) { - if (!Wifi.mdns_begun) { - - - - - - Wifi.mdns_begun = (uint8_t)MDNS.begin(my_hostname); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Wifi.mdns_begun) ? D_INITIALIZED : D_FAILED); - - } - } -#endif - -#ifdef USE_WEBSERVER - if (Settings.webserver) { - StartWebserver(Settings.webserver, WiFi.localIP()); -#ifdef USE_DISCOVERY -#ifdef WEBSERVER_ADVERTISE - if (1 == Wifi.mdns_begun) { - Wifi.mdns_begun = 2; - MDNS.addService("http", "tcp", WEB_PORT); - } -#endif -#endif - } else { - StopWebserver(); - } -#ifdef USE_EMULATION -#ifdef USE_DEVICE_GROUPS - if (Settings.flag2.emulation || Settings.flag4.device_groups_enabled) { UdpConnect(); } -#else - if (Settings.flag2.emulation) { UdpConnect(); } -#endif -#endif -#endif - -#ifdef USE_KNX - if (!knx_started && Settings.flag.knx_enabled) { - KNXStart(); - knx_started = true; - } -#endif - - } else { - WifiSetState(0); -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - Wifi.mdns_begun = 0; -#ifdef USE_KNX - knx_started = false; -#endif - } - } - } -} - -int WifiState(void) -{ - int state = -1; - - if (!global_state.wifi_down) { state = WIFI_RESTART; } - if (Wifi.config_type) { state = Wifi.config_type; } - return state; -} - -String WifiGetOutputPower(void) -{ - char stemp1[TOPSZ]; - dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1); - return String(stemp1); -} - -void WifiSetOutputPower(void) -{ - WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); -} - -void WifiConnect(void) -{ - WifiSetState(0); - WifiSetOutputPower(); - WiFi.persistent(false); - Wifi.status = 0; - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); - Wifi.retry = Wifi.retry_init; - Wifi.counter = 1; -} - - - -void WifiDisconnect(void) -{ -#ifdef USE_WIFI_SDK_ERASE - SettingsSdkWifiErase(); -#else - - WiFi.persistent(true); - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); - ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); - delay(100); -#endif -} - -void WifiShutdown(void) -{ - delay(100); - if (Settings.flag.mqtt_enabled) { - MqttDisconnect(); - } - WifiDisconnect(); -} - -void EspRestart(void) -{ - WifiShutdown(); - CrashDumpClear(); - - ESP.reset(); -} -# 1 "S:/Development/Tasmota/tasmota/tasmota_ca.ino" -# 24 "S:/Development/Tasmota/tasmota/tasmota_ca.ino" -#ifdef USE_MQTT_TLS_CA_CERT - -#ifndef USE_MQTT_AWS_IOT -# 38 "S:/Development/Tasmota/tasmota/tasmota_ca.ino" -static const unsigned char PROGMEM TA0_DN[] = { - 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, - 0x79, 0x20, 0x58, 0x33 -}; - -static const unsigned char PROGMEM TA0_RSA_N[] = { - 0x9C, 0xD3, 0x0C, 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, 0x37, - 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, 0x35, 0x26, 0x19, 0x25, 0xE1, - 0xBD, 0xBE, 0x35, 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, 0x05, - 0xAB, 0xA9, 0x9E, 0x35, 0x08, 0x58, 0xEC, 0xB1, 0x2A, 0xC4, 0x68, 0x87, - 0x0B, 0xA3, 0xE3, 0x75, 0xE4, 0xE6, 0xF3, 0xA7, 0x62, 0x71, 0xBA, 0x79, - 0x81, 0x60, 0x1F, 0xD7, 0x91, 0x9A, 0x9F, 0xF3, 0xD0, 0x78, 0x67, 0x71, - 0xC8, 0x69, 0x0E, 0x95, 0x91, 0xCF, 0xFE, 0xE6, 0x99, 0xE9, 0x60, 0x3C, - 0x48, 0xCC, 0x7E, 0xCA, 0x4D, 0x77, 0x12, 0x24, 0x9D, 0x47, 0x1B, 0x5A, - 0xEB, 0xB9, 0xEC, 0x1E, 0x37, 0x00, 0x1C, 0x9C, 0xAC, 0x7B, 0xA7, 0x05, - 0xEA, 0xCE, 0x4A, 0xEB, 0xBD, 0x41, 0xE5, 0x36, 0x98, 0xB9, 0xCB, 0xFD, - 0x6D, 0x3C, 0x96, 0x68, 0xDF, 0x23, 0x2A, 0x42, 0x90, 0x0C, 0x86, 0x74, - 0x67, 0xC8, 0x7F, 0xA5, 0x9A, 0xB8, 0x52, 0x61, 0x14, 0x13, 0x3F, 0x65, - 0xE9, 0x82, 0x87, 0xCB, 0xDB, 0xFA, 0x0E, 0x56, 0xF6, 0x86, 0x89, 0xF3, - 0x85, 0x3F, 0x97, 0x86, 0xAF, 0xB0, 0xDC, 0x1A, 0xEF, 0x6B, 0x0D, 0x95, - 0x16, 0x7D, 0xC4, 0x2B, 0xA0, 0x65, 0xB2, 0x99, 0x04, 0x36, 0x75, 0x80, - 0x6B, 0xAC, 0x4A, 0xF3, 0x1B, 0x90, 0x49, 0x78, 0x2F, 0xA2, 0x96, 0x4F, - 0x2A, 0x20, 0x25, 0x29, 0x04, 0xC6, 0x74, 0xC0, 0xD0, 0x31, 0xCD, 0x8F, - 0x31, 0x38, 0x95, 0x16, 0xBA, 0xA8, 0x33, 0xB8, 0x43, 0xF1, 0xB1, 0x1F, - 0xC3, 0x30, 0x7F, 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, 0xE3, - 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, - 0x1D, 0x64, 0x16, 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, 0xC0, - 0xD8, 0x7D, 0xC3, 0x93 -}; - -static const unsigned char TA0_RSA_E[] = { - 0x01, 0x00, 0x01 -}; - -static const br_x509_trust_anchor PROGMEM LetsEncryptX3CrossSigned_TA = { - { (unsigned char *)TA0_DN, sizeof TA0_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, - (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, - } } - } -}; - -#define TAs_NUM 1 - -#endif - -#ifdef USE_MQTT_AWS_IOT -# 106 "S:/Development/Tasmota/tasmota/tasmota_ca.ino" -const unsigned char PROGMEM TA0_DN[] = { - 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, - 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, - 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, - 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 -}; - -const unsigned char PROGMEM TA0_RSA_N[] = { - 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, - 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, - 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, - 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, - 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, - 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, - 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, - 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, - 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, - 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, - 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, - 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, - 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, - 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, - 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, - 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, - 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, - 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, - 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, - 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, - 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, - 0x9A, 0xC8, 0xAA, 0x0D -}; - -static const unsigned char PROGMEM TA0_RSA_E[] = { - 0x01, 0x00, 0x01 -}; - -const br_x509_trust_anchor PROGMEM AmazonRootCA1_TA = { - { (unsigned char *)TA0_DN, sizeof TA0_DN }, - BR_X509_TA_CA, - { - BR_KEYTYPE_RSA, - { .rsa = { - (unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N, - (unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E, - } } - } -}; - -#define TAs_NUM 1 - -#endif - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_01_webserver.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_01_webserver.ino" -#ifdef USE_WEBSERVER - - - - - - - -#define XDRV_01 1 - -#ifndef WIFI_SOFT_AP_CHANNEL -#define WIFI_SOFT_AP_CHANNEL 1 -#endif - -const uint16_t CHUNKED_BUFFER_SIZE = 400; - -const uint16_t HTTP_REFRESH_TIME = 2345; -#define HTTP_RESTART_RECONNECT_TIME 9000 -#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 - -#include -#include - -#ifdef USE_RF_FLASH -uint8_t *efm8bb1_update = nullptr; -#endif - -enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTASLAVE }; - -static const char * HEADER_KEYS[] = { "User-Agent", }; - -const char HTTP_HEADER[] PROGMEM = - "" - "" - "" - "" - "%s - %s" - - ""; - -const char HTTP_HEAD_STYLE1[] PROGMEM = - "" - - "" - "" - "
" -#ifdef FIRMWARE_MINIMAL - "

" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "

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

" D_MODULE " %s

" -#else - "

%s " D_MODULE "

" -#endif - "

%s

"; - -const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM = - "
" - "" - "
"; -const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = - "
" D_CLOSE "" D_OPEN "
" - "
"; - -const char HTTP_MSG_RSTRT[] PROGMEM = - "
" D_DEVICE_WILL_RESTART "

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

" D_USER "

" - "

" D_PASSWORD "

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

" - "
 " D_TEMPLATE_FLAGS " 

" - - "

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

" D_MODULE_TYPE " (%s)

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

" D_AP1_SSID " (" STA_SSID1 ")

" - "

" D_AP1_PASSWORD "

" - "

" D_AP2_SSID " (" STA_SSID2 ")

" - "

" D_AP2_PASSWORD "

" - "

" D_HOSTNAME " (%s)

" - "

" D_CORS_DOMAIN "

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

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" - "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" - "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

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

" - "
 " D_TEMPLATE " " - "

" - "

" D_ACTIVATE "

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

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

" - "
" - "


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

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


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

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

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

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

"), - GetTextIndexed(action, sizeof(action), title_index, kButtonAction), - GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); - } -} - -void WSContentSpaceButton(uint32_t title_index) -{ - WSContentSend_P(PSTR("
")); - WSContentButton(title_index); -} - -void WSContentEnd(void) -{ - WSContentFlush(); - _WSContentSend(""); - WebServer->client().stop(); -} - -void WSContentStop(void) -{ - if (WifiIsInManagerMode()) { - if (WifiConfigCounter()) { - WSContentSend_P(HTTP_COUNTER); - } - } - WSContentSend_P(HTTP_END, my_version); - WSContentEnd(); -} - - - -void WebRestart(uint32_t type) -{ - - - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_RESTART); - - bool reset_only = (HTTP_MANAGER_RESET_ONLY == Web.state); - - WSContentStart_P((type) ? S_SAVE_CONFIGURATION : S_RESTART, !reset_only); - WSContentSend_P(HTTP_SCRIPT_RELOAD); - WSContentSendStyle(); - if (type) { - WSContentSend_P(PSTR("
" D_CONFIGURATION_SAVED "
")); - if (2 == type) { - WSContentSend_P(PSTR("
" D_TRYING_TO_CONNECT "
")); - } - WSContentSend_P(PSTR("
")); - } - WSContentSend_P(HTTP_MSG_RSTRT); - if (HTTP_MANAGER == Web.state || reset_only) { - Web.state = HTTP_ADMIN; - } else { - WSContentSpaceButton(BUTTON_MAIN); - } - WSContentStop(); - - ShowWebSource(SRC_WEBGUI); - restart_flag = 2; -} - - - -void HandleWifiLogin(void) -{ - WSContentStart_P(S_CONFIGURE_WIFI, false); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_LOGIN); - - if (HTTP_MANAGER_RESET_ONLY == Web.state) { - WSContentSpaceButton(BUTTON_RESTART); -#ifndef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); -#endif - } - - WSContentStop(); -} - -void WebSliderColdWarm(void) -{ - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "a", - "#fff", "#ff0", - 1, - 153, 500, - LightGetColorTemp(), - 't', 0); -} - -void HandleRoot(void) -{ - if (CaptivePortal()) { return; } - - if (WebServer->hasArg("rst")) { - WebRestart(0); - return; - } - - if (WifiIsInManagerMode()) { -#ifndef FIRMWARE_MINIMAL - if (strlen(SettingsText(SET_WEBPWD)) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1")) && HTTP_MANAGER_RESET_ONLY != Web.state) { - HandleWifiLogin(); - } else { - if (!strlen(SettingsText(SET_WEBPWD)) || (((WebServer->arg("USER1") == WEB_USERNAME ) && (WebServer->arg("PASS1") == SettingsText(SET_WEBPWD) )) || HTTP_MANAGER_RESET_ONLY == Web.state)) { - HandleWifiConfiguration(); - } else { - - HandleWifiLogin(); - } - } -#endif - return; - } - - if (HandleRootStatusRefresh()) { - return; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU); - - char stemp[33]; - - WSContentStart_P(S_MAIN_MENU); -#ifdef USE_SCRIPT_WEB_DISPLAY - WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh, Settings.web_refresh); -#else - WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh); -#endif - WSContentSend_P(HTTP_SCRIPT_ROOT_PART2); - - WSContentSendStyle(); - - WSContentSend_P(PSTR("
")); - if (devices_present) { -#ifdef USE_LIGHT - if (light_type) { - uint8_t light_subtype = light_type &7; - if (!Settings.flag3.pwm_multi_channels) { - bool split_white = ((LST_RGBW <= light_subtype) && (devices_present > 1)); - - if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) { - WebSliderColdWarm(); - } - - if (light_subtype > 2) { - uint16_t hue; - uint8_t sat; - LightGetHSB(&hue, &sat, nullptr); - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "b", - "#800", "#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800", - 2, - 1, 359, - hue, - 'h', 0); - - uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255); - char scolor[8]; - snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); - uint8_t red, green, blue; - LightHsToRgb(hue, 255, &red, &green, &blue); - snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "s", - scolor, stemp, - 3, - 0, 100, - changeUIntScale(sat, 0, 255, 0, 100), - 'n', 0); - } - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "c", - "#000", "#fff", - 4, - Settings.flag3.slider_dimmer_stay_on, 100, - Settings.light_dimmer, - 'd', 0); - - if (split_white) { - if (LST_RGBCW == light_subtype) { - WebSliderColdWarm(); - } - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - "f", - "#000", "#fff", - 5, - Settings.flag3.slider_dimmer_stay_on, 100, - LightGetDimmer(2), - 'w', 0); - } - } else { - uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; - stemp[0] = 'e'; stemp[1] = '0'; stemp[2] = '\0'; - for (uint32_t i = 0; i < pwm_channels; i++) { - stemp[1]++; - - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, - stemp, - "#000", "#fff", - i+1, - 1, 100, - changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), - 'e', i+1); - } - } - } -#endif -#ifdef USE_SHUTTER - if (Settings.flag3.shutter_mode) { - for (uint32_t i = 0; i < shutters_present; i++) { - WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1); - } - } -#endif - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("
")); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1, - (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : D_BUTTON_TOGGLE, - ""); - for (uint32_t i = 0; i < MaxFanspeed(); i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i); - WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2, - (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp, - ""); - } - } else { -#endif - for (uint32_t idx = 1; idx <= devices_present; idx++) { - bool set_button = ((idx <= MAX_BUTTON_TEXT) && strlen(SettingsText(SET_BUTTON1 + idx -1))); -#ifdef USE_SHUTTER - int32_t ShutterWebButton; - if (ShutterWebButton = IsShutterWebButton(idx)) { - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) ? "-" : ((ShutterWebButton>0) ? "▲" : "▼")), - ""); - continue; - } -#endif - snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx); - WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / devices_present, idx, - (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : (devices_present < 5) ? D_BUTTON_TOGGLE : "", - (set_button) ? "" : (devices_present > 1) ? stemp : ""); - } -#ifdef USE_SONOFF_IFAN - } -#endif - WSContentSend_P(PSTR("
%s
")); - } -#ifdef USE_SONOFF_RF - if (SONOFF_BRIDGE == my_module_type) { - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("")); - uint32_t idx = 0; - for (uint32_t i = 0; i < 4; i++) { - if (idx > 0) { WSContentSend_P(PSTR("")); } - for (uint32_t j = 0; j < 4; j++) { - idx++; - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), idx); - WSContentSend_P(PSTR(""), idx, - (strlen(SettingsText(SET_BUTTON1 + idx -1))) ? SettingsText(SET_BUTTON1 + idx -1) : stemp); - } - } - WSContentSend_P(PSTR("")); - } -#endif - -#ifndef FIRMWARE_MINIMAL - XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); - XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); -#endif - - if (HTTP_ADMIN == Web.state) { -#ifdef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_FIRMWARE_UPGRADE); -#else - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentButton(BUTTON_INFORMATION); - WSContentButton(BUTTON_FIRMWARE_UPGRADE); -#endif - WSContentButton(BUTTON_CONSOLE); - WSContentButton(BUTTON_RESTART); - } - WSContentStop(); -} - -bool HandleRootStatusRefresh(void) -{ - if (!WebAuthenticate()) { - WebServer->requestAuthentication(); - return true; - } - - if (!WebServer->hasArg("m")) { - return false; - } - - #ifdef USE_SCRIPT_WEB_DISPLAY - Script_Check_HTML_Setvars(); - #endif - - char tmp[8]; - char svalue[32]; - char webindex[5]; - - WebGetArg("o", tmp, sizeof(tmp)); - if (strlen(tmp)) { - ShowWebSource(SRC_WEBGUI); - uint32_t device = atoi(tmp); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - if (device < 2) { - ExecuteCommandPower(1, POWER_TOGGLE, SRC_IGNORE); - } else { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), device -2); - ExecuteCommand(svalue, SRC_WEBGUI); - } - } else { -#endif -#ifdef USE_SHUTTER - int32_t ShutterWebButton; - if (ShutterWebButton = IsShutterWebButton(device)) { - snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_TOGGLEUP) : PSTR(D_CMND_SHUTTER_TOGGLEDOWN)); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } else { -#endif - ExecuteCommandPower(device, POWER_TOGGLE, SRC_IGNORE); -#ifdef USE_SHUTTER - } -#endif -#ifdef USE_SONOFF_IFAN - } -#endif - } - WebGetArg("d0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("w0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - for (uint32_t j = 1; j <= pwm_channels; j++) { - snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j); - WebGetArg(webindex, tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j, tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - } - WebGetArg("t0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("h0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - WebGetArg("n0", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } -#ifdef USE_SHUTTER - for (uint32_t j = 1; j <= shutters_present; j++) { - snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); - WebGetArg(webindex, tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } - } -#endif -#ifdef USE_SONOFF_RF - WebGetArg("k", tmp, sizeof(tmp)); - if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp); - ExecuteWebCommand(svalue, SRC_WEBGUI); - } -#endif - WSContentBegin(200, CT_HTML); - WSContentSend_P(PSTR("{t}")); - XsnsCall(FUNC_WEB_SENSOR); -#ifdef USE_SCRIPT_WEB_DISPLAY - XdrvCall(FUNC_WEB_SENSOR); -#endif - - WSContentSend_P(PSTR("")); - - if (devices_present) { - WSContentSend_P(PSTR("{t}")); - uint32_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { - WSContentSend_P(HTTP_DEVICE_STATE, 36, (bitRead(power, 0)) ? "bold" : "normal", 54, GetStateText(bitRead(power, 0))); - uint32_t fanspeed = GetFanspeed(); - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fanspeed); - WSContentSend_P(HTTP_DEVICE_STATE, 64, (fanspeed) ? "bold" : "normal", 54, (fanspeed) ? svalue : GetStateText(0)); - } else { -#endif - for (uint32_t idx = 1; idx <= devices_present; idx++) { - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1)); - WSContentSend_P(HTTP_DEVICE_STATE, 100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue); - } -#ifdef USE_SONOFF_IFAN - } -#endif - WSContentSend_P(PSTR("")); - } - WSContentEnd(); - - return true; -} - -#ifdef USE_SHUTTER -int32_t IsShutterWebButton(uint32_t idx) { - - int32_t ShutterWebButton = 0; - if (Settings.flag3.shutter_mode) { - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - if (Settings.shutter_startrelay[i] && ((Settings.shutter_startrelay[i] == idx) || (Settings.shutter_startrelay[i] == (idx-1)))) { - ShutterWebButton = (Settings.shutter_startrelay[i] == idx) ? (i+1): (-1-i); - break; - } - } - } - return ShutterWebButton; -} -#endif - - - -#ifndef FIRMWARE_MINIMAL - -void HandleConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURATION); - - WSContentStart_P(S_CONFIGURATION); - WSContentSendStyle(); - - WSContentButton(BUTTON_MODULE); - WSContentButton(BUTTON_WIFI); - - XdrvCall(FUNC_WEB_ADD_BUTTON); - XsnsCall(FUNC_WEB_ADD_BUTTON); - - WSContentButton(BUTTON_LOGGING); - WSContentButton(BUTTON_OTHER); - WSContentButton(BUTTON_TEMPLATE); - - WSContentSpaceButton(BUTTON_RESET_CONFIGURATION); - WSContentButton(BUTTON_BACKUP); - WSContentButton(BUTTON_RESTORE); - - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} - - - -void HandleTemplateConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - TemplateSaveSettings(); - WebRestart(1); - return; - } - - char stemp[30]; - - if (WebServer->hasArg("m")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { - uint32_t midx = pgm_read_byte(kModuleNiceList + i); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); - } - WSContentEnd(); - return; - } - - WebGetArg("t", stemp, sizeof(stemp)); - if (strlen(stemp)) { - uint32_t module = atoi(stemp); - uint32_t module_save = Settings.module; - Settings.module = module; - myio cmodule; - ModuleGpios(&cmodule); - gpio_flag flag = ModuleFlag(); - Settings.module = module_save; - - WSContentBegin(200, CT_PLAIN); - WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); - for (uint32_t i = 0; i < sizeof(kGpioNiceList); i++) { - if (1 == i) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, 255, D_SENSOR_USER, 255); - } - uint32_t midx = pgm_read_byte(kGpioNiceList + i); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); - } - WSContentSend_P(PSTR("}1")); - - for (uint32_t i = 0; i < ADC0_END; i++) { - if (1 == i) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, ADC0_USER, D_SENSOR_USER, ADC0_USER); - } - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, i, GetTextIndexed(stemp, sizeof(stemp), i, kAdc0Names), i); - } - WSContentSend_P(PSTR("}1")); - - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if ((i < 6) || ((i > 8) && (i != 11))) { - WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", cmodule.io[i]); - } - } - WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings.user_template_base); - WSContentEnd(); - return; - } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TEMPLATE); - - WSContentStart_P(S_CONFIGURE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_TEMPLATE); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_TEMPLATE); - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("" D_TEMPLATE_NAME "" - "" D_BASE_TYPE "" - "" - "
")); - WSContentSend_P(HTTP_TABLE100); - for (uint32_t i = 0; i < 17; i++) { - if ((i < 6) || ((i > 8) && (i != 11))) { - WSContentSend_P(PSTR("" D_GPIO "%d"), - ((9==i)||(10==i)) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? " style='width:200px'" : "", i); - } - } - WSContentSend_P(PSTR("" D_ADC "0"), WebColor(COL_TEXT)); - WSContentSend_P(PSTR("")); - gpio_flag flag = ModuleFlag(); - if (flag.data > ADC0_USER) { - WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); - } - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void TemplateSaveSettings(void) -{ - char tmp[sizeof(Settings.user_template.name)]; - char webindex[5]; - char svalue[128]; - - WebGetArg("s1", tmp, sizeof(tmp)); - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); - - uint32_t j = 0; - for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), j); - WebGetArg(webindex, tmp, sizeof(tmp)); - uint8_t gpio = atoi(tmp); - snprintf_P(svalue, sizeof(svalue), PSTR("%s%s%d"), svalue, (i>0)?",":"", gpio); - j++; - } - - WebGetArg("g17", tmp, sizeof(tmp)); - uint32_t flag = atoi(tmp); - for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { - snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); - uint32_t state = WebServer->hasArg(webindex) << i +4; - flag += state; - } - WebGetArg("g99", tmp, sizeof(tmp)); - uint32_t base = atoi(tmp) +1; - - snprintf_P(svalue, sizeof(svalue), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), svalue, flag, base); - ExecuteWebCommand(svalue, SRC_WEBGUI); -} - - - -void HandleModuleConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - ModuleSaveSettings(); - WebRestart(1); - return; - } - - char stemp[30]; - uint32_t midx; - myio cmodule; - ModuleGpios(&cmodule); - - if (WebServer->hasArg("m")) { - WSContentBegin(200, CT_PLAIN); - uint32_t vidx = 0; - for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { - if (0 == i) { - midx = USER_MODULE; - vidx = 0; - } else { - midx = pgm_read_byte(kModuleNiceList + i -1); - vidx = midx +1; - } - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), vidx); - } - WSContentEnd(); - return; - } - - if (WebServer->hasArg("g")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t j = 0; j < sizeof(kGpioNiceList); j++) { - midx = pgm_read_byte(kGpioNiceList + j); - if (!GetUsedInModule(midx, cmodule.io)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames), midx); - } - } - WSContentEnd(); - return; - } - -#ifndef USE_ADC_VCC - if (WebServer->hasArg("a")) { - WSContentBegin(200, CT_PLAIN); - for (uint32_t j = 0; j < ADC0_END; j++) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, j, GetTextIndexed(stemp, sizeof(stemp), j, kAdc0Names), j); - } - WSContentEnd(); - return; - } -#endif - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MODULE); - - WSContentStart_P(S_CONFIGURE_MODULE); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - WSContentSend_P(HTTP_SCRIPT_MODULE1, Settings.module); - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - WSContentSend_P(PSTR("sk(%d,%d);"), my_module.io[i], i); - } - } - WSContentSend_P(HTTP_SCRIPT_MODULE2, Settings.my_adc0); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(stemp, 3, PINS_WEMOS +i*2); - char sesp8285[40]; - snprintf_P(sesp8285, sizeof(sesp8285), PSTR("ESP8285"), WebColor(COL_TEXT_WARNING)); - WSContentSend_P(PSTR("%s " D_GPIO "%d %s"), - (WEMOS==my_module_type)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :((9==i)||(10==i))? sesp8285 :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i); - } - } -#ifndef USE_ADC_VCC - if (ValidAdc()) { - WSContentSend_P(PSTR("%s " D_ADC "0"), (WEMOS==my_module_type)?"A0":""); - } -#endif - WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void ModuleSaveSettings(void) -{ - char tmp[8]; - char webindex[5]; - - WebGetArg("g99", tmp, sizeof(tmp)); - uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); - Settings.last_module = Settings.module; - Settings.module = new_module; - SetModuleType(); - myio cmodule; - ModuleGpios(&cmodule); - String gpios = ""; - for (uint32_t i = 0; i < sizeof(cmodule); i++) { - if (Settings.last_module != new_module) { - Settings.my_gp.io[i] = GPIO_NONE; - } else { - if (ValidGPIO(i, cmodule.io[i])) { - snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); - WebGetArg(webindex, tmp, sizeof(tmp)); - Settings.my_gp.io[i] = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_GPIO ); gpios += String(i); gpios += F(" "); gpios += String(Settings.my_gp.io[i]); - } - } - } -#ifndef USE_ADC_VCC - WebGetArg("g17", tmp, sizeof(tmp)); - Settings.my_adc0 = (!strlen(tmp)) ? 0 : atoi(tmp); - gpios += F(", " D_ADC "0 "); gpios += String(Settings.my_adc0); -#endif - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MODULE "%s " D_CMND_MODULE "%s"), ModuleName().c_str(), gpios.c_str()); -} - - - -const char kUnescapeCode[] = "&><\"\'"; -const char kEscapeCode[] PROGMEM = "&|>|<|"|'"; - -String HtmlEscape(const String unescaped) { - char escaped[10]; - size_t ulen = unescaped.length(); - String result = ""; - for (size_t i = 0; i < ulen; i++) { - char c = unescaped[i]; - char *p = strchr(kUnescapeCode, c); - if (p != nullptr) { - result += GetTextIndexed(escaped, sizeof(escaped), p - kUnescapeCode, kEscapeCode); - } else { - result += c; - } - } - return result; -} - - -const char kEncryptionType[] PROGMEM = "|||" D_WPA_PSK "||" D_WPA2_PSK "|" D_WEP "||" D_NONE "|" D_AUTO; - -void HandleWifiConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_WIFI); - - if (WebServer->hasArg("save") && HTTP_MANAGER_RESET_ONLY != Web.state) { - WifiSaveSettings(); - WebRestart(2); - return; - } - - WSContentStart_P(S_CONFIGURE_WIFI, !WifiIsInManagerMode()); - WSContentSend_P(HTTP_SCRIPT_WIFI); - WSContentSendStyle(); - - if (HTTP_MANAGER_RESET_ONLY != Web.state) { - if (WebServer->hasArg("scan")) { -#ifdef USE_EMULATION - UdpDisconnect(); -#endif - int n = WiFi.scanNetworks(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI D_SCAN_DONE)); - - if (0 == n) { - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_WIFI, S_NO_NETWORKS_FOUND); - WSContentSend_P(S_NO_NETWORKS_FOUND); - WSContentSend_P(PSTR(". " D_REFRESH_TO_SCAN_AGAIN ".")); - } else { - - int indices[n]; - for (uint32_t i = 0; i < n; i++) { - indices[i] = i; - } - - - for (uint32_t i = 0; i < n; i++) { - for (uint32_t j = i + 1; j < n; j++) { - if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { - std::swap(indices[i], indices[j]); - } - } - } - - - String cssid; - for (uint32_t i = 0; i < n; i++) { - if (-1 == indices[i]) { continue; } - cssid = WiFi.SSID(indices[i]); - uint32_t cschn = WiFi.channel(indices[i]); - for (uint32_t j = i + 1; j < n; j++) { - if ((cssid == WiFi.SSID(indices[j])) && (cschn == WiFi.channel(indices[j]))) { - DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_DUPLICATE_ACCESSPOINT " %s"), WiFi.SSID(indices[j]).c_str()); - indices[j] = -1; - } - } - } - - - for (uint32_t i = 0; i < n; i++) { - if (-1 == indices[i]) { continue; } - int32_t rssi = WiFi.RSSI(indices[i]) - DEBUG_CORE_LOG(PSTR(D_LOG_WIFI D_SSID " %s, " D_BSSID " %s, " D_CHANNEL " %d, " D_RSSI " %d"), - WiFi.SSID(indices[i]).c_str(), WiFi.BSSIDstr(indices[i]).c_str(), WiFi.channel(indices[i]), rssi); - int quality = WifiGetRssiAsQuality(rssi); - int auth = WiFi.encryptionType(indices[i]); - char encryption[20]; - WSContentSend_P(PSTR("
%s (%d) %s %d%% (%d dBm)
"), - HtmlEscape(WiFi.SSID(indices[i])).c_str(), - WiFi.channel(indices[i]), - GetTextIndexed(encryption, sizeof(encryption), auth +1, kEncryptionType), - quality, rssi - ); - delay(0); - - } - WSContentSend_P(PSTR("
")); - } - } else { - WSContentSend_P(PSTR("
")); - } - - - WSContentSend_P(HTTP_FORM_WIFI, SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS)); - WSContentSend_P(HTTP_FORM_END); - } - - if (WifiIsInManagerMode()) { -#ifndef FIRMWARE_MINIMAL - WSContentSpaceButton(BUTTON_RESTORE); - WSContentButton(BUTTON_RESET_CONFIGURATION); -#endif - WSContentSpaceButton(BUTTON_RESTART); - } else { - WSContentSpaceButton(BUTTON_CONFIGURATION); - } - WSContentStop(); -} - -void WifiSaveSettings(void) -{ - char tmp[TOPSZ]; - - WebGetArg("h", tmp, sizeof(tmp)); - SettingsUpdateText(SET_HOSTNAME, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp); - if (strstr(SettingsText(SET_HOSTNAME), "%") != nullptr) { - SettingsUpdateText(SET_HOSTNAME, WIFI_HOSTNAME); - } - WebGetArg("c", tmp, sizeof(tmp)); - SettingsUpdateText(SET_CORS, (!strlen(tmp)) ? CORS_DOMAIN : tmp); - WebGetArg("s1", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STASSID1, (!strlen(tmp)) ? STA_SSID1 : tmp); - WebGetArg("s2", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STASSID2, (!strlen(tmp)) ? STA_SSID2 : tmp); - WebGetArg("p1", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STAPWD1, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD1) : tmp); - WebGetArg("p2", tmp, sizeof(tmp)); - SettingsUpdateText(SET_STAPWD2, (!strlen(tmp)) ? "" : (strlen(tmp) < 5) ? SettingsText(SET_STAPWD2) : tmp); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_HOSTNAME " %s, " D_CMND_SSID "1 %s, " D_CMND_SSID "2 %s, " D_CMND_CORS " %s"), - SettingsText(SET_HOSTNAME), SettingsText(SET_STASSID1), SettingsText(SET_STASSID2), SettingsText(SET_CORS)); -} - - - -void HandleLoggingConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_LOGGING); - - if (WebServer->hasArg("save")) { - LoggingSaveSettings(); - HandleConfiguration(); - return; - } - - WSContentStart_P(S_CONFIGURE_LOGGING); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_LOG1); - char stemp1[45]; - char stemp2[32]; - uint8_t dlevel[4] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE, LOG_LEVEL_NONE }; - for (uint32_t idx = 0; idx < 4; idx++) { - if ((2==idx) && !Settings.flag.mqtt_enabled) { continue; } - uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:(2==idx)?Settings.mqttlog_level:Settings.syslog_level; - WSContentSend_P(PSTR("

%s (%s)

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

"), - i +1, - (i) ? stemp : "", - i, - (i) ? stemp : "", - SettingsText(SET_FRIENDLYNAME1 + i)); - } - -#ifdef USE_EMULATION - WSContentSend_P(PSTR("

 " D_EMULATION " 

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

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

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

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

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

" D_HOST " (" MQTT_HOST ")

" - "

" D_PORT " (" STR(MQTT_PORT) ")

" - "

" D_CLIENT " (%s)

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

" D_USER " (" MQTT_USER ")

" - "

" D_PASSWORD "

" - "

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

" - "

" D_FULL_TOPIC " (%s)

"; - -void HandleMqttConfiguration(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT); - - if (WebServer->hasArg("save")) { - MqttSaveSettings(); - WebRestart(1); - return; - } - - char str[TOPSZ]; - - WSContentStart_P(S_CONFIGURE_MQTT); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MQTT1, - SettingsText(SET_MQTT_HOST), - Settings.mqtt_port, - Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, SettingsText(SET_MQTT_CLIENT)); - WSContentSend_P(HTTP_FORM_MQTT2, - (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER), - Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, SettingsText(SET_MQTT_TOPIC), - MQTT_FULLTOPIC, MQTT_FULLTOPIC, SettingsText(SET_MQTT_FULLTOPIC)); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void MqttSaveSettings(void) -{ - char tmp[TOPSZ]; - char stemp[TOPSZ]; - char stemp2[TOPSZ]; - - WebGetArg("mt", tmp, sizeof(tmp)); - strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp)); - MakeValidMqtt(0, stemp); - WebGetArg("mf", tmp, sizeof(tmp)); - strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); - MakeValidMqtt(1, stemp2); - if ((strcmp(stemp, SettingsText(SET_MQTT_TOPIC))) || (strcmp(stemp2, SettingsText(SET_MQTT_FULLTOPIC)))) { - Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, S_LWT, true); - } - SettingsUpdateText(SET_MQTT_TOPIC, stemp); - SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp2); - WebGetArg("mh", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_HOST, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp); - WebGetArg("ml", tmp, sizeof(tmp)); - Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp); - WebGetArg("mc", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_CLIENT, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp); -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); -#else - WebGetArg("mu", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_USER, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp); - WebGetArg("mp", tmp, sizeof(tmp)); - SettingsUpdateText(SET_MQTT_PWD, (!strlen(tmp)) ? "" : (!strcmp(tmp, D_ASTERISK_PWD)) ? SettingsText(SET_MQTT_PWD) : tmp); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"), - SettingsText(SET_MQTT_HOST), Settings.mqtt_port, SettingsText(SET_MQTT_CLIENT), SettingsText(SET_MQTT_USER), SettingsText(SET_MQTT_TOPIC), SettingsText(SET_MQTT_FULLTOPIC)); -#endif -} -#endif - - - - - -bool Xdrv02(uint8_t function) -{ - bool result = false; - - if (Settings.flag.mqtt_enabled) { - switch (function) { - case FUNC_PRE_INIT: - MqttInit(); - break; - case FUNC_EVERY_50_MSECOND: - MqttClient.loop(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_MQTT); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); - break; -#endif - case FUNC_COMMAND: - result = DecodeCommand(kMqttCommands, MqttCommand); - break; - } - } - return result; -} -# 1 "S:/Development/Tasmota/tasmota/xdrv_03_energy.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_03_energy.ino" -#ifdef USE_ENERGY_SENSOR - - - - -#define XDRV_03 3 -#define XSNS_03 3 - - - - -#define ENERGY_NONE 0 -#define ENERGY_WATCHDOG 4 - -#include - -#define D_CMND_POWERCAL "PowerCal" -#define D_CMND_VOLTAGECAL "VoltageCal" -#define D_CMND_CURRENTCAL "CurrentCal" -#define D_CMND_TARIFF "Tariff" -#define D_CMND_MODULEADDRESS "ModuleAddress" - -enum EnergyCommands { - CMND_POWERCAL, CMND_VOLTAGECAL, CMND_CURRENTCAL, - CMND_POWERSET, CMND_VOLTAGESET, CMND_CURRENTSET, CMND_FREQUENCYSET, CMND_MODULEADDRESS }; - -const char kEnergyCommands[] PROGMEM = "|" - D_CMND_POWERCAL "|" D_CMND_VOLTAGECAL "|" D_CMND_CURRENTCAL "|" - D_CMND_POWERSET "|" D_CMND_VOLTAGESET "|" D_CMND_CURRENTSET "|" D_CMND_FREQUENCYSET "|" D_CMND_MODULEADDRESS "|" -#ifdef USE_ENERGY_MARGIN_DETECTION - D_CMND_POWERDELTA "|" D_CMND_POWERLOW "|" D_CMND_POWERHIGH "|" D_CMND_VOLTAGELOW "|" D_CMND_VOLTAGEHIGH "|" D_CMND_CURRENTLOW "|" D_CMND_CURRENTHIGH "|" -#ifdef USE_ENERGY_POWER_LIMIT - D_CMND_MAXENERGY "|" D_CMND_MAXENERGYSTART "|" - D_CMND_MAXPOWER "|" D_CMND_MAXPOWERHOLD "|" D_CMND_MAXPOWERWINDOW "|" - D_CMND_SAFEPOWER "|" D_CMND_SAFEPOWERHOLD "|" D_CMND_SAFEPOWERWINDOW "|" -#endif -#endif - D_CMND_ENERGYRESET "|" D_CMND_TARIFF ; - -void (* const EnergyCommand[])(void) PROGMEM = { - &CmndPowerCal, &CmndVoltageCal, &CmndCurrentCal, - &CmndPowerSet, &CmndVoltageSet, &CmndCurrentSet, &CmndFrequencySet, &CmndModuleAddress, -#ifdef USE_ENERGY_MARGIN_DETECTION - &CmndPowerDelta, &CmndPowerLow, &CmndPowerHigh, &CmndVoltageLow, &CmndVoltageHigh, &CmndCurrentLow, &CmndCurrentHigh, -#ifdef USE_ENERGY_POWER_LIMIT - &CmndMaxEnergy, &CmndMaxEnergyStart, - &CmndMaxPower, &CmndMaxPowerHold, &CmndMaxPowerWindow, - &CmndSafePower, &CmndSafePowerHold, &CmndSafePowerWindow, -#endif -#endif - &CmndEnergyReset, &CmndTariff }; - -const char kEnergyPhases[] PROGMEM = "|%s / %s|%s / %s / %s||[%s,%s]|[%s,%s,%s]"; - -struct ENERGY { - float voltage[3] = { 0, 0, 0 }; - float current[3] = { 0, 0, 0 }; - float active_power[3] = { 0, 0, 0 }; - float apparent_power[3] = { NAN, NAN, NAN }; - float reactive_power[3] = { NAN, NAN, NAN }; - float power_factor[3] = { NAN, NAN, NAN }; - float frequency[3] = { NAN, NAN, NAN }; - - float start_energy = 0; - float daily = 0; - float total = 0; - float export_active = NAN; - - unsigned long kWhtoday_delta = 0; - unsigned long kWhtoday_offset = 0; - unsigned long kWhtoday; - unsigned long period = 0; - - uint8_t fifth_second = 0; - uint8_t command_code = 0; - uint8_t data_valid[3] = { 0, 0, 0 }; - - uint8_t phase_count = 1; - bool voltage_common = false; - - bool voltage_available = true; - bool current_available = true; - - bool type_dc = false; - bool power_on = true; - -#ifdef USE_ENERGY_MARGIN_DETECTION - uint16_t power_history[3] = { 0 }; - uint8_t power_steady_counter = 8; - bool power_delta = false; - bool min_power_flag = false; - bool max_power_flag = false; - bool min_voltage_flag = false; - bool max_voltage_flag = false; - bool min_current_flag = false; - bool max_current_flag = false; - -#ifdef USE_ENERGY_POWER_LIMIT - uint16_t mplh_counter = 0; - uint16_t mplw_counter = 0; - uint8_t mplr_counter = 0; - uint8_t max_energy_state = 0; -#endif -#endif -} Energy; - -Ticker ticker_energy; - - - -bool EnergyTariff1Active() -{ - uint8_t dst = 0; - if (IsDst() && (Settings.tariff[0][1] != Settings.tariff[1][1])) { - dst = 1; - } - if (Settings.tariff[0][dst] != Settings.tariff[1][dst]) { - if (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || - (RtcTime.day_of_week == 7))) { - return true; - } - uint32_t minutes = MinutesPastMidnight(); - if (Settings.tariff[0][dst] > Settings.tariff[1][dst]) { - - return ((minutes >= Settings.tariff[0][dst]) || (minutes < Settings.tariff[1][dst])); - } else { - - return ((minutes >= Settings.tariff[0][dst]) && (minutes < Settings.tariff[1][dst])); - } - } else { - return false; - } -} - -void EnergyUpdateToday(void) -{ - if (Energy.kWhtoday_delta > 1000) { - unsigned long delta = Energy.kWhtoday_delta / 1000; - Energy.kWhtoday_delta -= (delta * 1000); - Energy.kWhtoday += delta; - } - - RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday; - Energy.daily = (float)(RtcSettings.energy_kWhtoday) / 100000; - Energy.total = (float)(RtcSettings.energy_kWhtotal + RtcSettings.energy_kWhtoday) / 100000; - - if (RtcTime.valid){ - - uint32_t energy_diff = (uint32_t)(Energy.total * 100000) - RtcSettings.energy_usage.last_usage_kWhtotal; - RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 100000); - - uint32_t return_diff = 0; - if (!isnan(Energy.export_active)) { - return_diff = (uint32_t)(Energy.export_active * 100000) - RtcSettings.energy_usage.last_return_kWhtotal; - RtcSettings.energy_usage.last_return_kWhtotal = (uint32_t)(Energy.export_active * 100000); - } - - if (EnergyTariff1Active()) { - RtcSettings.energy_usage.usage1_kWhtotal += energy_diff; - RtcSettings.energy_usage.return1_kWhtotal += return_diff; - } else { - RtcSettings.energy_usage.usage2_kWhtotal += energy_diff; - RtcSettings.energy_usage.return2_kWhtotal += return_diff; - } - } -} - -void EnergyUpdateTotal(float value, bool kwh) -{ - - - - - uint32_t multiplier = (kwh) ? 100000 : 100; - - if (0 == Energy.start_energy || (value < Energy.start_energy)) { - Energy.start_energy = value; - } - else if (value != Energy.start_energy) { - Energy.kWhtoday = (unsigned long)((value - Energy.start_energy) * multiplier); - } - - if ((Energy.total < (value - 0.01)) && - Settings.flag3.hardware_energy_total) { - RtcSettings.energy_kWhtotal = (unsigned long)((value * multiplier) - Energy.kWhtoday_offset - Energy.kWhtoday); - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; - Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); - - } - EnergyUpdateToday(); -} - - - -void Energy200ms(void) -{ - Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; - - Energy.fifth_second++; - if (5 == Energy.fifth_second) { - Energy.fifth_second = 0; - - XnrgCall(FUNC_ENERGY_EVERY_SECOND); - - if (RtcTime.valid) { - if (LocalTime() == Midnight()) { - Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday; - - RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - Energy.kWhtoday = 0; - Energy.kWhtoday_offset = 0; - RtcSettings.energy_kWhtoday = 0; - Energy.start_energy = 0; - - Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday; - EnergyUpdateToday(); -#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) - Energy.max_energy_state = 3; -#endif - } -#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT) - if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == Energy.max_energy_state )) { - Energy.max_energy_state = 0; - } -#endif - - } - } - - XnrgCall(FUNC_EVERY_200_MSECOND); -} - -void EnergySaveState(void) -{ - Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; - - Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - - Settings.energy_usage = RtcSettings.energy_usage; -} - -#ifdef USE_ENERGY_MARGIN_DETECTION -bool EnergyMargin(bool type, uint16_t margin, uint16_t value, bool &flag, bool &save_flag) -{ - bool change; - - if (!margin) return false; - change = save_flag; - if (type) { - flag = (value > margin); - } else { - flag = (value < margin); - } - save_flag = flag; - return (change != save_flag); -} - -void EnergyMarginCheck(void) -{ - if (Energy.power_steady_counter) { - Energy.power_steady_counter--; - return; - } - - uint16_t energy_power_u = (uint16_t)(Energy.active_power[0]); - - if (Settings.energy_power_delta) { - uint16_t delta = abs(Energy.power_history[0] - energy_power_u); - if (delta > 0) { - if (Settings.energy_power_delta < 101) { - uint16_t min_power = (Energy.power_history[0] > energy_power_u) ? energy_power_u : Energy.power_history[0]; - if (0 == min_power) { min_power++; } - if (((delta * 100) / min_power) > Settings.energy_power_delta) { - Energy.power_delta = true; - } - } else { - if (delta > (Settings.energy_power_delta -100)) { - Energy.power_delta = true; - } - } - if (Energy.power_delta) { - Energy.power_history[1] = Energy.active_power[0]; - Energy.power_history[2] = Energy.active_power[0]; - } - } - } - Energy.power_history[0] = Energy.power_history[1]; - Energy.power_history[1] = Energy.power_history[2]; - Energy.power_history[2] = energy_power_u; - - if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) { - uint16_t energy_voltage_u = (uint16_t)(Energy.voltage[0]); - uint16_t energy_current_u = (uint16_t)(Energy.current[0] * 1000); - - DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); - - Response_P(PSTR("{")); - bool flag; - bool jsonflg = false; - if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, Energy.max_power_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, Energy.min_current_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, Energy.max_current_flag)) { - ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); - jsonflg = true; - } - if (jsonflg) { - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); - EnergyMqttShow(); - } - } - -#ifdef USE_ENERGY_POWER_LIMIT - - if (Settings.energy_max_power_limit) { - if (Energy.active_power[0] > Settings.energy_max_power_limit) { - if (!Energy.mplh_counter) { - Energy.mplh_counter = Settings.energy_max_power_limit_hold; - } else { - Energy.mplh_counter--; - if (!Energy.mplh_counter) { - ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":%d}"), energy_power_u); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); - if (!Energy.mplr_counter) { - Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; - } - Energy.mplw_counter = Settings.energy_max_power_limit_window; - } - } - } - else if (power && (energy_power_u <= Settings.energy_max_power_limit)) { - Energy.mplh_counter = 0; - Energy.mplr_counter = 0; - Energy.mplw_counter = 0; - } - if (!power) { - if (Energy.mplw_counter) { - Energy.mplw_counter--; - } else { - if (Energy.mplr_counter) { - Energy.mplr_counter--; - if (Energy.mplr_counter) { - ResponseTime_P(PSTR(",\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); - RestorePower(true, SRC_MAXPOWER); - } else { - ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER); - } - } - } - } - } - - - if (Settings.energy_max_energy) { - uint16_t energy_daily_u = (uint16_t)(Energy.daily * 1000); - if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { - Energy.max_energy_state = 1; - ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); - RestorePower(true, SRC_MAXENERGY); - } - else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) { - Energy.max_energy_state = 2; - char stemp[FLOATSZ]; - dtostrfd(Energy.daily, 3, stemp); - ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":%s}"), stemp); - MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); - EnergyMqttShow(); - SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY); - } - } -#endif - - if (Energy.power_delta) { EnergyMqttShow(); } -} - -void EnergyMqttShow(void) -{ - - int tele_period_save = tele_period; - tele_period = 2; - mqtt_data[0] = '\0'; - ResponseAppendTime(); - EnergyShow(true); - tele_period = tele_period_save; - ResponseJsonEnd(); - MqttPublishTeleSensor(); - Energy.power_delta = false; -} -#endif - -void EnergyEverySecond(void) -{ - - if (global_update) { - if (power && (global_temperature != 9999) && (global_temperature > Settings.param[P_OVER_TEMP])) { - SetAllPower(POWER_ALL_OFF, SRC_OVERTEMP); - } - } - - - uint32_t data_valid = Energy.phase_count; - for (uint32_t i = 0; i < Energy.phase_count; i++) { - if (Energy.data_valid[i] <= ENERGY_WATCHDOG) { - Energy.data_valid[i]++; - if (Energy.data_valid[i] > ENERGY_WATCHDOG) { - - Energy.voltage[i] = 0; - Energy.current[i] = 0; - Energy.active_power[i] = 0; - if (!isnan(Energy.apparent_power[i])) { Energy.apparent_power[i] = 0; } - if (!isnan(Energy.reactive_power[i])) { Energy.reactive_power[i] = 0; } - if (!isnan(Energy.frequency[i])) { Energy.frequency[i] = 0; } - if (!isnan(Energy.power_factor[i])) { Energy.power_factor[i] = 0; } - - data_valid--; - } - } - } - if (!data_valid) { - if (!isnan(Energy.export_active)) { Energy.export_active = 0; } - Energy.start_energy = 0; - - XnrgCall(FUNC_ENERGY_RESET); - } - -#ifdef USE_ENERGY_MARGIN_DETECTION - EnergyMarginCheck(); -#endif -} - - - - - -void EnergyCommandCalResponse(uint32_t nvalue) -{ - snprintf_P(XdrvMailbox.command, CMDSZ, PSTR("%sCal"), XdrvMailbox.command); - ResponseCmndNumber(nvalue); -} - -void CmndEnergyReset(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { - char *p; - unsigned long lnum = strtoul(XdrvMailbox.data, &p, 10); - if (p != XdrvMailbox.data) { - switch (XdrvMailbox.index) { - case 1: - - Energy.kWhtoday_offset = lnum *100; - Energy.kWhtoday = 0; - Energy.kWhtoday_delta = 0; - Energy.start_energy = 0; - Energy.period = Energy.kWhtoday_offset; - Settings.energy_kWhtoday = Energy.kWhtoday_offset; - RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset; - Energy.daily = (float)Energy.kWhtoday_offset / 100000; - if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) { - Settings.energy_kWhtotal_time = LocalTime(); - } - break; - case 2: - - Settings.energy_kWhyesterday = lnum *100; - break; - case 3: - - RtcSettings.energy_kWhtotal = lnum *100; - Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal; - - Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight(); - RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000); - break; - } - } - } - else if ((XdrvMailbox.index > 3) && (XdrvMailbox.index <= 5)) { - uint32_t values[2] = { 0 }; - uint32_t position = ParseParameters(2, values); - values[0] *= 100; - values[1] *= 100; - - switch (XdrvMailbox.index) - { - case 4: - - if (position > 0) { - RtcSettings.energy_usage.usage1_kWhtotal = values[0]; - } - if (position > 1) { - RtcSettings.energy_usage.usage2_kWhtotal = values[1]; - } - Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal; - Settings.energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal; - break; - case 5: - - if (position > 0) { - RtcSettings.energy_usage.return1_kWhtotal = values[0]; - } - if (position > 1) { - RtcSettings.energy_usage.return2_kWhtotal = values[1]; - } - Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal; - Settings.energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal; - break; - } - } - - Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000; - - char energy_total_chr[FLOATSZ]; - dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr); - char energy_daily_chr[FLOATSZ]; - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); - char energy_yesterday_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - - char energy_usage1_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage1_chr); - char energy_usage2_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage2_chr); - char energy_return1_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return1_chr); - char energy_return2_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return2_chr); - - Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s,\"" D_JSON_USAGE "\":[%s,%s],\"" D_JSON_EXPORT "\":[%s,%s]}}"), - XdrvMailbox.command, energy_total_chr, energy_yesterday_chr, energy_daily_chr, energy_usage1_chr, energy_usage2_chr, energy_return1_chr, energy_return2_chr); -} - -void CmndTariff(void) -{ - - - - - - - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - uint32_t tariff = XdrvMailbox.index -1; - uint32_t time_type = 0; - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - while ((str != nullptr) && (time_type < 2)) { - char *q; - uint32_t value = strtol(str, &q, 10); - Settings.tariff[tariff][time_type] = value; - if (value < 24) { - Settings.tariff[tariff][time_type] *= 60; - char *minute = strtok_r(nullptr, ":", &q); - if (minute) { - value = strtol(minute, nullptr, 10); - if (value > 59) { - value = 59; - } - Settings.tariff[tariff][time_type] += value; - } - } - if (Settings.tariff[tariff][time_type] > 1439) { - Settings.tariff[tariff][time_type] = 1439; - } - str = strtok_r(nullptr, ", ", &p); - time_type++; - } - } - else if (XdrvMailbox.index == 9) { - Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; - } - Response_P(PSTR("{\"%s\":{\"Off-Peak\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Standard\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Weekend\":\"%s\"}}"), - XdrvMailbox.command, - GetMinuteTime(Settings.tariff[0][0]).c_str(),GetMinuteTime(Settings.tariff[0][1]).c_str(), - GetMinuteTime(Settings.tariff[1][0]).c_str(),GetMinuteTime(Settings.tariff[1][1]).c_str(), - GetStateText(Settings.flag3.energy_weekend)); -} - -void CmndPowerCal(void) -{ - Energy.command_code = CMND_POWERCAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_power_calibration = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_power_calibration); - } -} - -void CmndVoltageCal(void) -{ - Energy.command_code = CMND_VOLTAGECAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_voltage_calibration = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_voltage_calibration); - } -} - -void CmndCurrentCal(void) -{ - Energy.command_code = CMND_CURRENTCAL; - if (XnrgCall(FUNC_COMMAND)) { - if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload < 32001)) { - Settings.energy_current_calibration = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_current_calibration); - } -} - -void CmndPowerSet(void) -{ - Energy.command_code = CMND_POWERSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_power_calibration); - } -} - -void CmndVoltageSet(void) -{ - Energy.command_code = CMND_VOLTAGESET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_voltage_calibration); - } -} - -void CmndCurrentSet(void) -{ - Energy.command_code = CMND_CURRENTSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_current_calibration); - } -} - -void CmndFrequencySet(void) -{ - Energy.command_code = CMND_FREQUENCYSET; - if (XnrgCall(FUNC_COMMAND)) { - EnergyCommandCalResponse(Settings.energy_frequency_calibration); - } -} - -void CmndModuleAddress(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4) && (1 == Energy.phase_count)) { - Energy.command_code = CMND_MODULEADDRESS; - if (XnrgCall(FUNC_COMMAND)) { - ResponseCmndDone(); - } - } -} - -#ifdef USE_ENERGY_MARGIN_DETECTION -void CmndPowerDelta(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) { - Settings.energy_power_delta = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_power_delta); -} - -void CmndPowerLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_min_power = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_power); -} - -void CmndPowerHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power); -} - -void CmndVoltageLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { - Settings.energy_min_voltage = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_voltage); -} - -void CmndVoltageHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) { - Settings.energy_max_voltage = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_voltage); -} - -void CmndCurrentLow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { - Settings.energy_min_current = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_min_current); -} - -void CmndCurrentHigh(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) { - Settings.energy_max_current = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_current); -} - -#ifdef USE_ENERGY_POWER_LIMIT -void CmndMaxPower(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit); -} - -void CmndMaxPowerHold(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit_hold); -} - -void CmndMaxPowerWindow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_limit_window); -} - -void CmndSafePower(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_safe_limit = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit); -} - -void CmndSafePowerHold(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold); -} - -void CmndSafePowerWindow(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) { - Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_power_safe_limit_window); -} - -void CmndMaxEnergy(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.energy_max_energy = XdrvMailbox.payload; - Energy.max_energy_state = 3; - } - ResponseCmndNumber(Settings.energy_max_energy); -} - -void CmndMaxEnergyStart(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) { - Settings.energy_max_energy_start = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.energy_max_energy_start); -} -#endif -#endif - -void EnergySnsInit(void) -{ - XnrgCall(FUNC_INIT); - - if (energy_flg) { - if (RtcSettingsValid()) { - Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday; - } - else if (RtcTime.day_of_year == Settings.energy_kWhdoy) { - Energy.kWhtoday_offset = Settings.energy_kWhtoday; - } - else { - Energy.kWhtoday_offset = 0; - } - Energy.kWhtoday = 0; - Energy.kWhtoday_delta = 0; - Energy.period = Energy.kWhtoday_offset; - EnergyUpdateToday(); - ticker_energy.attach_ms(200, Energy200ms); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_SNS1[] PROGMEM = - "{s}" D_POWERUSAGE_APPARENT "{m}%s " D_UNIT_VA "{e}" - "{s}" D_POWERUSAGE_REACTIVE "{m}%s " D_UNIT_VAR "{e}" - "{s}" D_POWER_FACTOR "{m}%s{e}"; - -const char HTTP_ENERGY_SNS2[] PROGMEM = - "{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; - -const char HTTP_ENERGY_SNS3[] PROGMEM = - "{s}" D_EXPORT_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; -#endif - -char* EnergyFormatIndex(char* result, char* input, bool json, uint32_t index, bool single = false) -{ - char layout[16]; - GetTextIndexed(layout, sizeof(layout), (index -1) + (3 * json), kEnergyPhases); - switch (index) { - case 2: - snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ); - break; - case 3: - snprintf_P(result, FLOATSZ *3, layout, input, input + FLOATSZ, input + FLOATSZ + FLOATSZ); - break; - default: - snprintf_P(result, FLOATSZ *3, input); - } - return result; -} - -char* EnergyFormat(char* result, char* input, bool json, bool single = false) -{ - uint8_t index = (single) ? 1 : Energy.phase_count; - return EnergyFormatIndex(result, input, json, index, single); -} - -void EnergyShow(bool json) -{ - for (uint32_t i = 0; i < Energy.phase_count; i++) { - if (Energy.voltage_common) { - Energy.voltage[i] = Energy.voltage[0]; - } - } - - float power_factor_knx = Energy.power_factor[0]; - - char apparent_power_chr[Energy.phase_count][FLOATSZ]; - char reactive_power_chr[Energy.phase_count][FLOATSZ]; - char power_factor_chr[Energy.phase_count][FLOATSZ]; - char frequency_chr[Energy.phase_count][FLOATSZ]; - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - for (uint32_t i = 0; i < Energy.phase_count; i++) { - float apparent_power = Energy.apparent_power[i]; - if (isnan(apparent_power)) { - apparent_power = Energy.voltage[i] * Energy.current[i]; - } - if (apparent_power < Energy.active_power[i]) { - Energy.active_power[i] = apparent_power; - } - - float power_factor = Energy.power_factor[i]; - if (isnan(power_factor)) { - power_factor = (Energy.active_power[i] && apparent_power) ? Energy.active_power[i] / apparent_power : 0; - if (power_factor > 1) { - power_factor = 1; - } - } - if (0 == i) { power_factor_knx = power_factor; } - - float reactive_power = Energy.reactive_power[i]; - if (isnan(reactive_power)) { - reactive_power = 0; - uint32_t difference = ((uint32_t)(apparent_power * 100) - (uint32_t)(Energy.active_power[i] * 100)) / 10; - if ((Energy.current[i] > 0.005) && ((difference > 15) || (difference > (uint32_t)(apparent_power * 100 / 1000)))) { - - - reactive_power = (float)(RoundSqrtInt((uint32_t)(apparent_power * apparent_power * 100) - (uint32_t)(Energy.active_power[i] * Energy.active_power[i] * 100))) / 10; - } - } - - dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr[i]); - dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr[i]); - dtostrfd(power_factor, 2, power_factor_chr[i]); - } - } - for (uint32_t i = 0; i < Energy.phase_count; i++) { - float frequency = Energy.frequency[i]; - if (isnan(Energy.frequency[i])) { - frequency = 0; - } - dtostrfd(frequency, Settings.flag2.frequency_resolution, frequency_chr[i]); - } - } - - char voltage_chr[Energy.phase_count][FLOATSZ]; - char current_chr[Energy.phase_count][FLOATSZ]; - char active_power_chr[Energy.phase_count][FLOATSZ]; - for (uint32_t i = 0; i < Energy.phase_count; i++) { - dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]); - dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]); - dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]); - } - - char energy_daily_chr[FLOATSZ]; - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr); - char energy_yesterday_chr[FLOATSZ]; - dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - - char energy_total_chr[3][FLOATSZ]; - dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr[0]); - char export_active_chr[3][FLOATSZ]; - dtostrfd(Energy.export_active, Settings.flag2.energy_resolution, export_active_chr[0]); - uint8_t energy_total_fields = 1; - - if (Settings.tariff[0][0] != Settings.tariff[1][0]) { - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_total_chr[2]); - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, export_active_chr[2]); - energy_total_fields = 3; - } - - char value_chr[FLOATSZ *3]; - char value2_chr[FLOATSZ *3]; - char value3_chr[FLOATSZ *3]; - - if (json) { - bool show_energy_period = (0 == tele_period); - - ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s"), - GetDateAndTime(DT_ENERGY).c_str(), - EnergyFormatIndex(value_chr, energy_total_chr[0], json, energy_total_fields), - energy_yesterday_chr, - energy_daily_chr); - - if (!isnan(Energy.export_active)) { - ResponseAppend_P(PSTR(",\"" D_JSON_EXPORT_ACTIVE "\":%s"), - EnergyFormatIndex(value_chr, export_active_chr[0], json, energy_total_fields)); - } - - if (show_energy_period) { - float energy = 0; - if (Energy.period) { - energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100; - } - Energy.period = RtcSettings.energy_kWhtoday; - char energy_period_chr[FLOATSZ]; - dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr); - ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr); - } - ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"), - EnergyFormat(value_chr, active_power_chr[0], json)); - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s"), - EnergyFormat(value_chr, apparent_power_chr[0], json), - EnergyFormat(value2_chr, reactive_power_chr[0], json), - EnergyFormat(value3_chr, power_factor_chr[0], json)); - } - if (!isnan(Energy.frequency[0])) { - ResponseAppend_P(PSTR(",\"" D_JSON_FREQUENCY "\":%s"), - EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); - } - } - if (Energy.voltage_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s"), - EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); - } - if (Energy.current_available) { - ResponseAppend_P(PSTR(",\"" D_JSON_CURRENT "\":%s"), - EnergyFormat(value_chr, current_chr[0], json)); - } - XnrgCall(FUNC_JSON_APPEND); - ResponseJsonEnd(); - -#ifdef USE_DOMOTICZ - if (show_energy_period) { - dtostrfd(Energy.total * 1000, 1, energy_total_chr[0]); - DomoticzSensorPowerEnergy((int)Energy.active_power[0], energy_total_chr[0]); - - dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100, 1, energy_total_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100, 1, energy_total_chr[2]); - dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100, 1, export_active_chr[1]); - dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100, 1, export_active_chr[2]); - DomoticzSensorP1SmartMeter(energy_total_chr[1], energy_total_chr[2], export_active_chr[1], export_active_chr[2], (int)Energy.active_power[0]); - - if (Energy.voltage_available) { - DomoticzSensor(DZ_VOLTAGE, voltage_chr[0]); - } - if (Energy.current_available) { - DomoticzSensor(DZ_CURRENT, current_chr[0]); - } - } -#endif -#ifdef USE_KNX - if (show_energy_period) { - if (Energy.voltage_available) { - KnxSensor(KNX_ENERGY_VOLTAGE, Energy.voltage[0]); - } - if (Energy.current_available) { - KnxSensor(KNX_ENERGY_CURRENT, Energy.current[0]); - } - KnxSensor(KNX_ENERGY_POWER, Energy.active_power[0]); - if (!Energy.type_dc) { - KnxSensor(KNX_ENERGY_POWERFACTOR, power_factor_knx); - } - KnxSensor(KNX_ENERGY_DAILY, Energy.daily); - KnxSensor(KNX_ENERGY_TOTAL, Energy.total); - KnxSensor(KNX_ENERGY_START, Energy.start_energy); - } -#endif -#ifdef USE_WEBSERVER - } else { - if (Energy.voltage_available) { - WSContentSend_PD(HTTP_SNS_VOLTAGE, EnergyFormat(value_chr, voltage_chr[0], json, Energy.voltage_common)); - } - if (Energy.current_available) { - WSContentSend_PD(HTTP_SNS_CURRENT, EnergyFormat(value_chr, current_chr[0], json)); - } - WSContentSend_PD(HTTP_SNS_POWER, EnergyFormat(value_chr, active_power_chr[0], json)); - if (!Energy.type_dc) { - if (Energy.current_available && Energy.voltage_available) { - WSContentSend_PD(HTTP_ENERGY_SNS1, EnergyFormat(value_chr, apparent_power_chr[0], json), - EnergyFormat(value2_chr, reactive_power_chr[0], json), - EnergyFormat(value3_chr, power_factor_chr[0], json)); - } - if (!isnan(Energy.frequency[0])) { - WSContentSend_PD(PSTR("{s}" D_FREQUENCY "{m}%s " D_UNIT_HERTZ "{e}"), - EnergyFormat(value_chr, frequency_chr[0], json, Energy.voltage_common)); - } - } - WSContentSend_PD(HTTP_ENERGY_SNS2, energy_daily_chr, energy_yesterday_chr, energy_total_chr[0]); - if (!isnan(Energy.export_active)) { - WSContentSend_PD(HTTP_ENERGY_SNS3, export_active_chr[0]); - } - - XnrgCall(FUNC_WEB_SENSOR); -#endif - } -} - - - - - -bool Xdrv03(uint8_t function) -{ - bool result = false; - - if (FUNC_PRE_INIT == function) { - energy_flg = ENERGY_NONE; - XnrgCall(FUNC_PRE_INIT); - } - else if (energy_flg) { - switch (function) { - case FUNC_LOOP: - XnrgCall(FUNC_LOOP); - break; - case FUNC_EVERY_250_MSECOND: - XnrgCall(FUNC_EVERY_250_MSECOND); - break; - case FUNC_SERIAL: - result = XnrgCall(FUNC_SERIAL); - break; -#ifdef USE_ENERGY_MARGIN_DETECTION - case FUNC_SET_POWER: - Energy.power_steady_counter = 2; - break; -#endif - case FUNC_COMMAND: - result = DecodeCommand(kEnergyCommands, EnergyCommand); - break; - } - } - return result; -} - -bool Xsns03(uint8_t function) -{ - bool result = false; - - if (energy_flg) { - switch (function) { - case FUNC_EVERY_SECOND: - EnergyEverySecond(); - break; - case FUNC_JSON_APPEND: - EnergyShow(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - EnergyShow(false); - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - EnergySaveState(); - break; - case FUNC_INIT: - EnergySnsInit(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" -#ifdef USE_LIGHT -# 124 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" -#define XDRV_04 4 - - -enum LightSchemes { LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX }; - -const uint8_t LIGHT_COLOR_SIZE = 25; - -const char kLightCommands[] PROGMEM = "|" - D_CMND_COLOR "|" D_CMND_COLORTEMPERATURE "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" D_CMND_LEDTABLE "|" D_CMND_FADE "|" - D_CMND_RGBWWTABLE "|" D_CMND_SCHEME "|" D_CMND_SPEED "|" D_CMND_WAKEUP "|" D_CMND_WAKEUPDURATION "|" - D_CMND_WHITE "|" D_CMND_CHANNEL "|" D_CMND_HSBCOLOR "|UNDOCA" ; - -void (* const LightCommand[])(void) PROGMEM = { - &CmndColor, &CmndColorTemperature, &CmndDimmer, &CmndDimmerRange, &CmndLedTable, &CmndFade, - &CmndRgbwwTable, &CmndScheme, &CmndSpeed, &CmndWakeup, &CmndWakeupDuration, - &CmndWhite, &CmndChannel, &CmndHsbColor, &CmndUndocA }; - - -enum LightColorModes { - LCM_RGB = 1, LCM_CT = 2, LCM_BOTH = 3 }; - -struct LRgbColor { - uint8_t R, G, B; -}; -const uint8_t MAX_FIXED_COLOR = 12; -const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = - { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; - -struct LWColor { - uint8_t W; -}; -const uint8_t MAX_FIXED_WHITE = 4; -const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; - -struct LCwColor { - uint8_t C, W; -}; -const uint8_t MAX_FIXED_COLD_WARM = 4; -const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; - - -const uint16_t CT_MIN = 153; -const uint16_t CT_MAX = 500; - -const uint16_t CT_MIN_ALEXA = 200; -const uint16_t CT_MAX_ALEXA = 380; - - - - - - -typedef struct gamma_table_t { - uint16_t to_src; - uint16_t to_gamma; -} gamma_table_t; - -const gamma_table_t gamma_table[] = { - { 1, 1 }, - { 4, 1 }, - { 209, 13 }, - { 312, 41 }, - { 457, 106 }, - { 626, 261 }, - { 762, 450 }, - { 895, 703 }, - { 1023, 1023 }, - { 0xFFFF, 0xFFFF } -}; - - -const gamma_table_t gamma_table_fast[] = { - { 384, 192 }, - { 768, 576 }, - { 1023, 1023 }, - { 0xFFFF, 0xFFFF } -}; -# 248 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" -struct LIGHT { - uint32_t strip_timer_counter = 0; - power_t power = 0; - - uint16_t wakeup_counter = 0; - - uint8_t entry_color[LST_MAX]; - uint8_t current_color[LST_MAX]; - uint8_t new_color[LST_MAX]; - uint8_t last_color[LST_MAX]; - uint8_t color_remap[LST_MAX]; - - uint8_t wheel = 0; - uint8_t random = 0; - uint8_t subtype = 0; - uint8_t device = 0; - uint8_t old_power = 1; - uint8_t wakeup_active = 0; - uint8_t wakeup_dimmer = 0; - uint8_t fixed_color_index = 1; - uint8_t pwm_offset = 0; - uint8_t max_scheme = LS_MAX -1; - - bool update = true; - bool pwm_multi_channels = false; - - bool fade_initialized = false; - bool fade_running = false; - uint16_t fade_start_10[LST_MAX] = {0,0,0,0,0}; - uint16_t fade_cur_10[LST_MAX]; - uint16_t fade_end_10[LST_MAX]; - uint16_t fade_duration = 0; - uint32_t fade_start = 0; -} Light; - -power_t LightPower(void) -{ - return Light.power; -} - - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -power_t LightPowerIRAM(void) ICACHE_RAM_ATTR; -#endif - -power_t LightPowerIRAM(void) -{ - return Light.power; -} - -uint8_t LightDevice(void) -{ - return Light.device; -} - -static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) { - return (a < b && a < c) ? a : (b < c) ? b : c; -} -# 344 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" -class LightStateClass { - private: - uint16_t _hue = 0; - uint8_t _sat = 255; - uint8_t _briRGB = 255; - - uint8_t _r = 255; - uint8_t _g = 255; - uint8_t _b = 255; - - uint8_t _subtype = 0; - uint16_t _ct = CT_MIN; - uint8_t _wc = 255; - uint8_t _ww = 0; - uint8_t _briCT = 255; - - uint8_t _color_mode = LCM_RGB; - - - - - - uint16_t _ct_min_range = CT_MIN; - uint16_t _ct_max_range = CT_MAX; - - public: - LightStateClass() { - - } - - void setSubType(uint8_t sub_type) { - _subtype = sub_type; - } -# 386 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" - uint8_t setColorMode(uint8_t cm) { - uint8_t prev_cm = _color_mode; - if (cm < LCM_RGB) { cm = LCM_RGB; } - if (cm > LCM_BOTH) { cm = LCM_BOTH; } - uint8_t maxbri = (_briRGB >= _briCT) ? _briRGB : _briCT; - - switch (_subtype) { - case LST_COLDWARM: - _color_mode = LCM_CT; - break; - - case LST_NONE: - case LST_SINGLE: - case LST_RGB: - default: - _color_mode = LCM_RGB; - break; - - case LST_RGBW: - case LST_RGBCW: - _color_mode = cm; - break; - } - if (LCM_RGB == _color_mode) { - _briCT = 0; - if (0 == _briRGB) { _briRGB = maxbri; } - } - if (LCM_CT == _color_mode) { - _briRGB = 0; - if (0 == _briCT) { _briCT = maxbri; } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setColorMode prev_cm (%d) req_cm (%d) new_cm (%d)", prev_cm, cm, _color_mode); -#endif - return prev_cm; - } - - inline uint8_t getColorMode() { - return _color_mode; - } - - void addRGBMode() { - setColorMode(_color_mode | LCM_RGB); - } - void addCTMode() { - setColorMode(_color_mode | LCM_CT); - } - - - void getRGB(uint8_t *r, uint8_t *g, uint8_t *b) { - if (r) { *r = _r; } - if (g) { *g = _g; } - if (b) { *b = _b; } - } - - - - void getCW(uint8_t *rc, uint8_t *rw) { - if (rc) { *rc = _wc; } - if (rw) { *rw = _ww; } - } - - - void getActualRGBCW(uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *c, uint8_t *w) { - bool rgb_channels_on = _color_mode & LCM_RGB; - bool ct_channels_on = _color_mode & LCM_CT; - - if (r) { *r = rgb_channels_on ? changeUIntScale(_r, 0, 255, 0, _briRGB) : 0; } - if (g) { *g = rgb_channels_on ? changeUIntScale(_g, 0, 255, 0, _briRGB) : 0; } - if (b) { *b = rgb_channels_on ? changeUIntScale(_b, 0, 255, 0, _briRGB) : 0; } - - if (c) { *c = ct_channels_on ? changeUIntScale(_wc, 0, 255, 0, _briCT) : 0; } - if (w) { *w = ct_channels_on ? changeUIntScale(_ww, 0, 255, 0, _briCT) : 0; } - } - - uint8_t getChannels(uint8_t *channels) { - getActualRGBCW(&channels[0], &channels[1], &channels[2], &channels[3], &channels[4]); - } - - void getChannelsRaw(uint8_t *channels) { - channels[0] = _r; - channels[1] = _g; - channels[2] = _b; - channels[3] = _wc; - channels[4] = _ww; - } - - void getHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { - if (hue) { *hue = _hue; } - if (sat) { *sat = _sat; } - if (bri) { *bri = _briRGB; } - } - - - uint8_t getBri(void) { - - return (_briRGB >= _briCT) ? _briRGB : _briCT; - } - - - inline uint8_t getBriCT() { - return _briCT; - } - - static inline uint8_t DimmerToBri(uint8_t dimmer) { - return changeUIntScale(dimmer, 0, 100, 0, 255); - } - static uint8_t BriToDimmer(uint8_t bri) { - uint8_t dimmer = changeUIntScale(bri, 0, 255, 0, 100); - - if ((dimmer == 0) && (bri > 0)) { dimmer = 1; } - return dimmer; - } - - uint8_t getDimmer(uint32_t mode = 0) { - uint8_t bri; - switch (mode) { - case 1: - bri = getBriRGB(); - break; - case 2: - bri = getBriCT(); - break; - default: - bri = getBri(); - break; - } - return BriToDimmer(bri); - } - - inline uint16_t getCT() const { - return _ct; - } - - - uint16_t getCT10bits() const { - return changeUIntScale(_ct, _ct_min_range, _ct_max_range, 0, 1023); - } - - inline void setCTRange(uint16_t ct_min_range, uint16_t ct_max_range) { - _ct_min_range = ct_min_range; - _ct_max_range = ct_max_range; - } - - inline void getCTRange(uint16_t *ct_min_range, uint16_t *ct_max_range) const { - if (ct_min_range) { *ct_min_range = _ct_min_range; } - if (ct_max_range) { *ct_max_range = _ct_max_range; } - } - - - void getXY(float *x, float *y) { - RgbToXy(_r, _g, _b, x, y); - } - - - - void setBri(uint8_t bri) { - setBriRGB(_color_mode & LCM_RGB ? bri : 0); - setBriCT(_color_mode & LCM_CT ? bri : 0); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setBri RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - } - - - uint8_t setBriRGB(uint8_t bri_rgb) { - uint8_t prev_bri = _briRGB; - _briRGB = bri_rgb; - if (bri_rgb > 0) { addRGBMode(); } - return prev_bri; - } - - - uint8_t setBriCT(uint8_t bri_ct) { - uint8_t prev_bri = _briCT; - _briCT = bri_ct; - if (bri_ct > 0) { addCTMode(); } - return prev_bri; - } - - inline uint8_t getBriRGB() { - return _briRGB; - } - - void setDimmer(uint8_t dimmer) { - setBri(DimmerToBri(dimmer)); - } - - void setCT(uint16_t ct) { - if (0 == ct) { - - setColorMode(LCM_RGB); - } else { - ct = (ct < CT_MIN ? CT_MIN : (ct > CT_MAX ? CT_MAX : ct)); - _ww = changeUIntScale(ct, _ct_min_range, _ct_max_range, 0, 255); - _wc = 255 - _ww; - _ct = ct; - addCTMode(); - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCT RGB raw (%d %d %d) HS (%d %d) briRGB (%d) briCT (%d) CT (%d)", _r, _g, _b, _hue, _sat, _briRGB, _briCT, _ct); -#endif - } -# 604 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" - void setCW(uint8_t c, uint8_t w, bool free_range = false) { - uint16_t max = (w > c) ? w : c; - uint16_t sum = c + w; - - if (0 == max) { - _briCT = 0; - setColorMode(LCM_RGB); - } else { - if (!free_range) { - - _ww = changeUIntScale(w, 0, sum, 0, 255); - _wc = 255 - _ww; - } else { - _ww = changeUIntScale(w, 0, max, 0, 255); - _wc = changeUIntScale(c, 0, max, 0, 255); - } - _ct = changeUIntScale(w, 0, sum, _ct_min_range, _ct_max_range); - addCTMode(); - if (_color_mode & LCM_CT) { _briCT = free_range ? max : (sum > 255 ? 255 : sum); } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setCW CW (%d %d) CT (%d) briCT (%d)", c, w, _ct, _briCT); -#endif - } - - - uint8_t setRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { - uint16_t hue; - uint8_t sat; -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB input (%d %d %d)", r, g, b); -#endif - - uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; - - if (0 == max) { - r = g = b = 255; - setColorMode(LCM_CT); - } else { - if (255 > max) { - - r = changeUIntScale(r, 0, max, 0, 255); - g = changeUIntScale(g, 0, max, 0, 255); - b = changeUIntScale(b, 0, max, 0, 255); - } - addRGBMode(); - } - if (!keep_bri) { - _briRGB = (_color_mode & LCM_RGB) ? max : 0; - } - - RgbToHsb(r, g, b, &hue, &sat, nullptr); - _r = r; - _g = g; - _b = b; - _hue = hue; - _sat = sat; -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setRGB RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - return max; - } - - void setHS(uint16_t hue, uint8_t sat) { - uint8_t r, g, b; - HsToRgb(hue, sat, &r, &g, &b); - _r = r; - _g = g; - _b = b; - _hue = hue; - _sat = sat; - addRGBMode(); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS HS (%d %d) rgb (%d %d %d)", hue, sat, r, g, b); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setHS RGB raw (%d %d %d) HS (%d %d) bri (%d)", _r, _g, _b, _hue, _sat, _briRGB); -#endif - } - - - - void setChannelsRaw(uint8_t *channels) { - _r = channels[0]; - _g = channels[1]; - _b = channels[2]; - _wc = channels[3]; - _ww = channels[4]; -} - - - - - void setChannels(uint8_t *channels) { - setRGB(channels[0], channels[1], channels[2]); - setCW(channels[3], channels[4], true); -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels (%d %d %d %d %d)", - channels[0], channels[1], channels[2], channels[3], channels[4]); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightStateClass::setChannels CT (%d) briRGB (%d) briCT (%d)", _ct, _briRGB, _briCT); -#endif - } - - - static void RgbToHsb(uint8_t r, uint8_t g, uint8_t b, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri); - static void HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b); - static void RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y); - static void XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb); - -}; -# 720 "S:/Development/Tasmota/tasmota/xdrv_04_light.ino" -void LightStateClass::RgbToHsb(uint8_t ir, uint8_t ig, uint8_t ib, uint16_t *r_hue, uint8_t *r_sat, uint8_t *r_bri) { - uint32_t r = ir; - uint32_t g = ig; - uint32_t b = ib; - uint32_t max = (r > g && r > b) ? r : (g > b) ? g : b; - uint32_t min = (r < g && r < b) ? r : (g < b) ? g : b; - uint32_t d = max - min; - - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = max; - - if (d != 0) { - sat = changeUIntScale(d, 0, max, 0, 255); - if (r == max) { - hue = (g > b) ? changeUIntScale(g-b,0,d,0,60) : 360 - changeUIntScale(b-g,0,d,0,60); - } else if (g == max) { - hue = (b > r) ? 120 + changeUIntScale(b-r,0,d,0,60) : 120 - changeUIntScale(r-b,0,d,0,60); - } else { - hue = (r > g) ? 240 + changeUIntScale(r-g,0,d,0,60) : 240 - changeUIntScale(g-r,0,d,0,60); - } - hue = hue % 360; - } - - if (r_hue) *r_hue = hue; - if (r_sat) *r_sat = sat; - if (r_bri) *r_bri = bri; - -} - -void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { - uint32_t r = 255; - uint32_t g = 255; - uint32_t b = 255; - - hue = hue % 360; - - if (sat > 0) { - uint32_t i = hue / 60; - uint32_t f = hue % 60; - uint32_t q = 255 - changeUIntScale(f, 0, 60, 0, sat); - uint32_t p = 255 - sat; - uint32_t t = 255 - changeUIntScale(60 - f, 0, 60, 0, sat); - - switch (i) { - case 0: - - g = t; - b = p; - break; - case 1: - r = q; - - b = p; - break; - case 2: - r = p; - - b = t; - break; - case 3: - r = p; - g = q; - - break; - case 4: - r = t; - g = p; - - break; - default: - - g = p; - b = q; - break; - } - } - if (r_r) *r_r = r; - if (r_g) *r_g = g; - if (r_b) *r_b = b; -} - -#define POW FastPrecisePowf - -void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) { - float x = 0.31271f; - float y = 0.32902f; - - if (i_r + i_b + i_g > 0) { - float r = (float)i_r / 255.0f; - float g = (float)i_g / 255.0f; - float b = (float)i_b / 255.0f; - - - r = (r > 0.04045f) ? POW((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f); - g = (g > 0.04045f) ? POW((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f); - b = (b > 0.04045f) ? POW((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f); - - - - float X = r * 0.649926f + g * 0.103455f + b * 0.197109f; - float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f; - float Z = r * 0.000000f + g * 0.053077f + b * 1.035763f; - - x = X / (X + Y + Z); - y = Y / (X + Y + Z); - - } - if (r_x) *r_x = x; - if (r_y) *r_y = y; -} - -void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb) -{ - x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x)); - y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y)); - float z = 1.0f - x - y; - - float X = x / y; - float Z = z / y; - - - - float r = X * 3.2406f - 1.5372f - Z * 0.4986f; - float g = -X * 0.9689f + 1.8758f + Z * 0.0415f; - float b = X * 0.0557f - 0.2040f + Z * 1.0570f; - float max = (r > g && r > b) ? r : (g > b) ? g : b; - r = r / max; - g = g / max; - b = b / max; - r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * POW(r, (1.0f / 2.4f)) - 0.055f; - g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * POW(g, (1.0f / 2.4f)) - 0.055f; - b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * POW(b, (1.0f / 2.4f)) - 0.055f; - - - - - - int32_t ir = r * 255.0f + 0.5f; - int32_t ig = g * 255.0f + 0.5f; - int32_t ib = b * 255.0f + 0.5f; - if (rr) { *rr = (ir > 255 ? 255: (ir < 0 ? 0 : ir)); } - if (rg) { *rg = (ig > 255 ? 255: (ig < 0 ? 0 : ig)); } - if (rb) { *rb = (ib > 255 ? 255: (ib < 0 ? 0 : ib)); } -} - -class LightControllerClass { -private: - LightStateClass *_state; - - - bool _ct_rgb_linked = true; - bool _pwm_multi_channels = false; - -public: - LightControllerClass(LightStateClass& state) { - _state = &state; - } - - void setSubType(uint8_t sub_type) { - _state->setSubType(sub_type); - } - - inline bool setCTRGBLinked(bool ct_rgb_linked) { - bool prev = _ct_rgb_linked; - if (_pwm_multi_channels) { - _ct_rgb_linked = false; - } else { - _ct_rgb_linked = ct_rgb_linked; - } - return prev; - } - - void setAlexaCTRange(bool alexa_ct_range) { - - if (alexa_ct_range) { - _state->setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA); - } else { - _state->setCTRange(CT_MIN, CT_MAX); - } - } - - inline bool isCTRGBLinked() { - return _ct_rgb_linked; - } - - inline bool setPWMMultiChannel(bool pwm_multi_channels) { - bool prev = _pwm_multi_channels; - _pwm_multi_channels = pwm_multi_channels; - if (pwm_multi_channels) setCTRGBLinked(false); - return prev; - } - - inline bool isPWMMultiChannel(void) { - return _pwm_multi_channels; - } - -#ifdef DEBUG_LIGHT - void debugLogs() { - uint8_t r,g,b,c,w; - _state->getActualRGBCW(&r,&g,&b,&c,&w); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs rgb (%d %d %d) cw (%d %d)", - r, g, b, c, w); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::debugLogs lightCurrent (%d %d %d %d %d)", - Light.current_color[0], Light.current_color[1], Light.current_color[2], - Light.current_color[3], Light.current_color[4]); - } -#endif - - void loadSettings() { -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings Settings.light_color (%d %d %d %d %d - %d)", - Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], - Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)", - light_type, Light.subtype); -#endif - if (_pwm_multi_channels) { - _state->setChannelsRaw(Settings.light_color); - } else { - - _state->setCW(Settings.light_color[3], Settings.light_color[4], true); - _state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); - - - - uint8_t bri = _state->DimmerToBri(Settings.light_dimmer); - if (Settings.light_color[0] + Settings.light_color[1] + Settings.light_color[2] > 0) { - - - if ( (DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) && - (DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) && - (DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) { - _state->setColorMode(LCM_RGB); - } - _state->setBriRGB(bri); - } else { - _state->setBriCT(bri); - } - } - } - - void changeCTB(uint16_t new_ct, uint8_t briCT) { - - - - - - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBW > Light.subtype)) { - return; - } - _state->setCT(new_ct); - _state->setBriCT(briCT); - if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } - saveSettings(); - calcLevels(); - - } - - void changeDimmer(uint8_t dimmer, uint32_t mode = 0) { - uint8_t bri = changeUIntScale(dimmer, 0, 100, 0, 255); - switch (mode) { - case 1: - changeBriRGB(bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - break; - case 2: - changeBriCT(bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_CT); } - break; - default: - changeBri(bri); - break; - } - } - - void changeBri(uint8_t bri) { - _state->setBri(bri); - saveSettings(); - calcLevels(); - } - - void changeBriRGB(uint8_t bri) { - _state->setBriRGB(bri); - saveSettings(); - calcLevels(); - } - - void changeBriCT(uint8_t bri) { - _state->setBriCT(bri); - saveSettings(); - calcLevels(); - } - - void changeRGB(uint8_t r, uint8_t g, uint8_t b, bool keep_bri = false) { - _state->setRGB(r, g, b, keep_bri); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - saveSettings(); - calcLevels(); - } - - - - void calcLevels(uint8_t *current_color = nullptr) { - uint8_t r,g,b,c,w,briRGB,briCT; - if (current_color == nullptr) { current_color = Light.current_color; } - - if (_pwm_multi_channels) { - _state->getChannelsRaw(current_color); - return; - } - - _state->getActualRGBCW(&r,&g,&b,&c,&w); - briRGB = _state->getBriRGB(); - briCT = _state->getBriCT(); - - current_color[0] = current_color[1] = current_color[2] = 0; - current_color[3] = current_color[4] = 0; - switch (Light.subtype) { - case LST_NONE: - current_color[0] = 255; - break; - case LST_SINGLE: - current_color[0] = briRGB; - break; - case LST_COLDWARM: - current_color[0] = c; - current_color[1] = w; - break; - case LST_RGBW: - case LST_RGBCW: - if (LST_RGBCW == Light.subtype) { - current_color[3] = c; - current_color[4] = w; - } else { - current_color[3] = briCT; - } - - case LST_RGB: - current_color[0] = r; - current_color[1] = g; - current_color[2] = b; - break; - } - } - - void changeHSB(uint16_t hue, uint8_t sat, uint8_t briRGB) { - _state->setHS(hue, sat); - _state->setBriRGB(briRGB); - if (_ct_rgb_linked) { _state->setColorMode(LCM_RGB); } - saveSettings(); - calcLevels(); - } - - - void saveSettings() { - if (Light.pwm_multi_channels) { - - _state->getChannelsRaw(Settings.light_color); - Settings.light_dimmer = 100; - } else { - uint8_t cm = _state->getColorMode(); - - memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); - if (LCM_RGB & cm) { - _state->getRGB(&Settings.light_color[0], &Settings.light_color[1], &Settings.light_color[2]); - Settings.light_dimmer = _state->BriToDimmer(_state->getBriRGB()); - - if (LCM_BOTH == cm) { - - _state->getActualRGBCW(nullptr, nullptr, nullptr, &Settings.light_color[3], &Settings.light_color[4]); - } - } else if (LCM_CT == cm) { - _state->getCW(&Settings.light_color[3], &Settings.light_color[4]); - Settings.light_dimmer = _state->BriToDimmer(_state->getBriCT()); - } - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::saveSettings Settings.light_color (%d %d %d %d %d - %d)", - Settings.light_color[0], Settings.light_color[1], Settings.light_color[2], - Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer); -#endif - } - - - - - void changeChannels(uint8_t *channels) { - if (Light.pwm_multi_channels) { - _state->setChannelsRaw(channels); - } else if (LST_COLDWARM == Light.subtype) { - - uint8_t remapped_channels[5] = {0,0,0,channels[0],channels[1]}; - _state->setChannels(remapped_channels); - } else { - _state->setChannels(channels); - } - - saveSettings(); - calcLevels(); - } -}; - - - -LightStateClass light_state = LightStateClass(); -LightControllerClass light_controller = LightControllerClass(light_state); - - - - - -uint16_t change8to10(uint8_t v) { - return changeUIntScale(v, 0, 255, 0, 1023); -} - -uint8_t change10to8(uint16_t v) { - return (0 == v) ? 0 : changeUIntScale(v, 4, 1023, 1, 255); -} - - - - - -uint16_t ledGamma_internal(uint16_t v, const struct gamma_table_t *gt_ptr) { - uint16_t from_src = 0; - uint16_t from_gamma = 0; - - for (const gamma_table_t *gt = gt_ptr; ; gt++) { - uint16_t to_src = gt->to_src; - uint16_t to_gamma = gt->to_gamma; - if (v <= to_src) { - return changeUIntScale(v, from_src, to_src, from_gamma, to_gamma); - } - from_src = to_src; - from_gamma = to_gamma; - } -} - -uint16_t ledGammaReverse_internal(uint16_t vg, const struct gamma_table_t *gt_ptr) { - uint16_t from_src = 0; - uint16_t from_gamma = 0; - - for (const gamma_table_t *gt = gt_ptr; ; gt++) { - uint16_t to_src = gt->to_src; - uint16_t to_gamma = gt->to_gamma; - if (vg <= to_gamma) { - return changeUIntScale(vg, from_gamma, to_gamma, from_src, to_src); - } - from_src = to_src; - from_gamma = to_gamma; - } -} - - -uint16_t ledGamma10_10(uint16_t v) { - return ledGamma_internal(v, gamma_table); -} - -uint16_t ledGamma10(uint8_t v) { - return ledGamma10_10(change8to10(v)); -} - - -uint8_t ledGamma(uint8_t v) { - return change10to8(ledGamma10(v)); -} - - - -void LightPwmOffset(uint32_t offset) -{ - Light.pwm_offset = offset; -} - -bool LightModuleInit(void) -{ - light_type = LT_BASIC; - - if (Settings.flag.pwm_control) { - for (uint32_t i = 0; i < MAX_PWMS; i++) { - if (pin[GPIO_PWM1 +i] < 99) { light_type++; } - } - } - - light_flg = 0; - if (XlgtCall(FUNC_MODULE_INIT)) { - - } - else if (SONOFF_BN == my_module_type) { - light_type = LT_PWM1; - } - else if (SONOFF_LED == my_module_type) { - if (!my_module.io[4]) { - pinMode(4, OUTPUT); - digitalWrite(4, LOW); - } - if (!my_module.io[5]) { - pinMode(5, OUTPUT); - digitalWrite(5, LOW); - } - if (!my_module.io[14]) { - pinMode(14, OUTPUT); - digitalWrite(14, LOW); - } - light_type = LT_PWM2; - } - - if (light_type > LT_BASIC) { - devices_present++; - } - - - if (Settings.flag3.pwm_multi_channels) { - uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - if (0 == pwm_channels) { pwm_channels = 1; } - devices_present += pwm_channels - 1; - } else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= (light_type & 7))) { - - devices_present++; - } - - return (light_type > LT_BASIC); -} - -void LightInit(void) -{ - Light.device = devices_present; - Light.subtype = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; - - if (LST_RGBW <= Light.subtype) { - - - bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); - light_controller.setCTRGBLinked(ct_rgb_linked); - } - - if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) { - - light_controller.setPWMMultiChannel(true); - Light.device = devices_present - Light.subtype + 1; - } else if (!light_controller.isCTRGBLinked()) { - - Light.device--; - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightInit Light.pwm_multi_channels=%d Light.subtype=%d Light.device=%d devices_present=%d", - Light.pwm_multi_channels, Light.subtype, Light.device, devices_present); -#endif - - light_controller.setSubType(Light.subtype); - light_controller.loadSettings(); - light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); - - if (LST_SINGLE == Light.subtype) { - Settings.light_color[0] = 255; - } - if (light_type < LT_PWM6) { - for (uint32_t i = 0; i < light_type; i++) { - Settings.pwm_value[i] = 0; - if (pin[GPIO_PWM1 +i] < 99) { - pinMode(pin[GPIO_PWM1 +i], OUTPUT); - } - } - if (pin[GPIO_ARIRFRCV] < 99) { - if (pin[GPIO_ARIRFSEL] < 99) { - pinMode(pin[GPIO_ARIRFSEL], OUTPUT); - digitalWrite(pin[GPIO_ARIRFSEL], 1); - } - } - } - - uint32_t max_scheme = Light.max_scheme; - if (Light.subtype < LST_RGB) { - max_scheme = LS_POWER; - } - if ((LS_WAKEUP == Settings.light_scheme) || (Settings.light_scheme > max_scheme)) { - Settings.light_scheme = LS_POWER; - } - Light.power = 0; - Light.update = true; - Light.wakeup_active = 0; - - LightUpdateColorMapping(); -} - -void LightUpdateColorMapping(void) -{ - uint8_t param = Settings.param[P_RGB_REMAP] & 127; - if (param > 119){ param = 0; } - - uint8_t tmp[] = {0,1,2,3,4}; - Light.color_remap[0] = tmp[param / 24]; - for (uint32_t i = param / 24; i<4; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 24; - Light.color_remap[1] = tmp[(param / 6)]; - for (uint32_t i = param / 6; i<3; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 6; - Light.color_remap[2] = tmp[(param / 2)]; - for (uint32_t i = param / 2; i<2; ++i){ - tmp[i] = tmp[i+1]; - } - param = param % 2; - Light.color_remap[3] = tmp[param]; - Light.color_remap[4] = tmp[1-param]; - - Light.update = true; - -} - -uint8_t LightGetDimmer(uint8_t dimmer) { - return light_state.getDimmer(dimmer); -} - -void LightSetDimmer(uint8_t dimmer) { - light_controller.changeDimmer(dimmer); -} - -void LightGetHSB(uint16_t *hue, uint8_t *sat, uint8_t *bri) { - light_state.getHSB(hue, sat, bri); -} - -void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { - light_state.HsToRgb(hue, sat, r_r, r_g, r_b); -} - - -uint8_t LightGetBri(uint8_t device) { - uint8_t bri = 254; - if (Light.pwm_multi_channels) { - if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { - bri = Light.current_color[device - Light.device]; - } - } else if (light_controller.isCTRGBLinked()) { - if (device == Light.device) { - bri = light_state.getBri(); - } - } else { - if (device == Light.device) { - bri = light_state.getBriRGB(); - } else if (device == Light.device + 1) { - bri = light_state.getBriCT(); - } - } - return bri; -} - - -void LightSetBri(uint8_t device, uint8_t bri) { - if (Light.pwm_multi_channels) { - if ((device >= Light.device) && (device < Light.device + LST_MAX) && (device <= devices_present)) { - Light.current_color[device - Light.device] = bri; - light_controller.changeChannels(Light.current_color); - } - } else if (light_controller.isCTRGBLinked()) { - if (device == Light.device) { - light_controller.changeBri(bri); - } - } else { - if (device == Light.device) { - light_controller.changeBriRGB(bri); - } else if (device == Light.device + 1) { - light_controller.changeBriCT(bri); - } - } -} - -void LightSetColorTemp(uint16_t ct) -{ - - - - - - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { - return; - } - light_controller.changeCTB(ct, light_state.getBriCT()); -} - -uint16_t LightGetColorTemp(void) -{ - - if ((LST_COLDWARM != Light.subtype) && (LST_RGBCW != Light.subtype)) { - return 0; - } - return (light_state.getColorMode() & LCM_CT) ? light_state.getCT() : 0; -} - -void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value) -{ - - - - if (Settings.flag.light_signal) { - uint16_t signal = changeUIntScale(value, lo, hi, 0, 255); - - light_controller.changeRGB(signal, 255 - signal, 0, true); - Settings.light_scheme = 0; - if (0 == light_state.getBri()) { - light_controller.changeBri(50); - } - } -} - - -char* LightGetColor(char* scolor, boolean force_hex = false) -{ - light_controller.calcLevels(); - scolor[0] = '\0'; - for (uint32_t i = 0; i < Light.subtype; i++) { - if (!force_hex && Settings.flag.decimal_text) { - snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Light.current_color[i]); - } else { - snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%02X"), scolor, Light.current_color[i]); - } - } - return scolor; -} - -void LightPowerOn(void) -{ - if (light_state.getBri() && !(Light.power)) { - ExecuteCommandPower(Light.device, POWER_ON, SRC_LIGHT); - } -} - -void LightState(uint8_t append) -{ - char scolor[LIGHT_COLOR_SIZE]; - char scommand[33]; - bool unlinked = !light_controller.isCTRGBLinked() && (Light.subtype >= LST_RGBW); - - if (append) { - ResponseAppend_P(PSTR(",")); - } else { - Response_P(PSTR("{")); - } - if (!Light.pwm_multi_channels) { - if (unlinked) { - - ResponseAppend_P(PSTR("\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d" - ",\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d"), - Light.device, GetStateText(Light.power & 1), Light.device, light_state.getDimmer(1), - Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), Light.device + 1, light_state.getDimmer(2)); - } else { - GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); - ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1), - light_state.getDimmer()); - } - - - if (Light.subtype > LST_SINGLE) { - ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); - if (LST_RGB <= Light.subtype) { - uint16_t hue; - uint8_t sat, bri; - light_state.getHSB(&hue, &sat, &bri); - sat = changeUIntScale(sat, 0, 255, 0, 100); - bri = changeUIntScale(bri, 0, 255, 0, 100); - - ResponseAppend_P(PSTR(",\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), hue,sat,bri); - } - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { - ResponseAppend_P(PSTR(",\"" D_CMND_WHITE "\":%d"), light_state.getDimmer(2)); - } - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), light_state.getCT()); - } - - ResponseAppend_P(PSTR(",\"" D_CMND_CHANNEL "\":[" )); - for (uint32_t i = 0; i < Light.subtype; i++) { - uint8_t channel_raw = Light.current_color[i]; - uint8_t channel = changeUIntScale(channel_raw,0,255,0,100); - - if ((0 == channel) && (channel_raw > 0)) { channel = 1; } - ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), channel); - } - ResponseAppend_P(PSTR("]")); - } - - if (append) { - if (Light.subtype >= LST_RGB) { - ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); - } - if (Light.max_scheme > LS_MAX) { - ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width); - } - ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), - GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); - } - } else { - for (uint32_t i = 0; i < Light.subtype; i++) { - GetPowerDevice(scommand, Light.device + i, sizeof(scommand), 1); - uint32_t light_power_masked = Light.power & (1 << i); - light_power_masked = light_power_masked ? 1 : 0; - ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_CHANNEL "%d\":%d,"), scommand, GetStateText(light_power_masked), Light.device + i, - changeUIntScale(Light.current_color[i], 0, 255, 0, 100)); - } - ResponseAppend_P(PSTR("\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); - } - - if (!append) { - ResponseJsonEnd(); - } -} - -void LightPreparePower(power_t channels = 0xFFFFFFFF) { -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); -#endif - - if (Light.pwm_multi_channels) { - for (uint32_t i = 0; i < Light.subtype; i++) { - if (bitRead(channels, i)) { - - if ((Light.current_color[i]) && (!bitRead(Light.power, i))) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device + i, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else { - - if ((0 == Light.current_color[i]) && bitRead(Light.power, i)) { - ExecuteCommandPower(Light.device + i, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } - #ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(Light.device + i); - #endif - } - } - } else { - if (light_controller.isCTRGBLinked()) { - if (light_state.getBri() && !(Light.power)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else if (!light_state.getBri() && Light.power) { - ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } else { - - if (channels & 1) { - if (light_state.getBriRGB() && !(Light.power & 1)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else if (!light_state.getBriRGB() && (Light.power & 1)) { - ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } - - if (channels & 2) { - if (light_state.getBriCT() && !(Light.power & 2)) { - if (!Settings.flag.not_power_linked) { - ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); - } - } else if (!light_state.getBriCT() && (Light.power & 2)) { - ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT); - } - } - } -#ifdef USE_DOMOTICZ - DomoticzUpdatePowerState(Light.device); -#endif - } - - if (Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower End power=%d Light.power=%d", power, Light.power); -#endif - Light.power = power >> (Light.device - 1); - LightState(0); -} - -void LightCycleColor(int8_t direction) -{ - if (Light.strip_timer_counter % (Settings.light_speed * 2)) { - return; - } - - if (0 == direction) { - if (Light.random == Light.wheel) { - Light.random = random(255); - - uint8_t my_dir = (Light.random < Light.wheel -128) ? 1 : - (Light.random < Light.wheel ) ? 0 : - (Light.random > Light.wheel +128) ? 0 : 1; - Light.random = (Light.random & 0xFE) | my_dir; - - - } - - direction = (Light.random &0x01) ? 1 : -1; - } - Light.wheel += direction; - uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); - - - - uint8_t sat; - light_state.getHSB(nullptr, &sat, nullptr); - light_state.setHS(hue, sat); - light_controller.calcLevels(Light.new_color); -} - -void LightSetPower(void) -{ - - Light.old_power = Light.power; - - uint32_t mask = 1; - if (Light.pwm_multi_channels) { - mask = (1 << Light.subtype) - 1; - } else if (!light_controller.isCTRGBLinked()) { - mask = 3; - } - uint32_t shift = Light.device - 1; - - - - - - Light.power = (XdrvMailbox.index & (mask << shift)) >> shift; - if (Light.wakeup_active) { - Light.wakeup_active--; - } -#ifdef DEBUG_LIGHT - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "LightSetPower XdrvMailbox.index=%d Light.old_power=%d Light.power=%d mask=%d shift=%d", - XdrvMailbox.index, Light.old_power, Light.power, mask, shift); -#endif - if (Light.power != Light.old_power) { - Light.update = true; - } - LightAnimate(); -} - - - - -void LightAnimate(void) -{ - uint16_t light_still_on = 0; - bool power_off = false; - - - light_controller.setAlexaCTRange(Settings.flag4.alexa_ct_range); - Light.strip_timer_counter++; - - - - if (Light.power || Light.fade_running) { - if (Settings.sleep > PWM_MAX_SLEEP) { - sleep = PWM_MAX_SLEEP; - } else { - sleep = Settings.sleep; - } - } else { - sleep = Settings.sleep; - } - - if (!Light.power) { - Light.strip_timer_counter = 0; - if (Settings.light_scheme >= LS_MAX) { - power_off = true; - } - } else { - switch (Settings.light_scheme) { - case LS_POWER: - light_controller.calcLevels(Light.new_color); - break; - case LS_WAKEUP: - if (2 == Light.wakeup_active) { - Light.wakeup_active = 1; - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.new_color[i] = 0; - } - Light.wakeup_counter = 0; - Light.wakeup_dimmer = 0; - } - Light.wakeup_counter++; - if (Light.wakeup_counter > ((Settings.light_wakeup * STATES) / Settings.light_dimmer)) { - Light.wakeup_counter = 0; - Light.wakeup_dimmer++; - if (Light.wakeup_dimmer <= Settings.light_dimmer) { - light_state.setDimmer(Light.wakeup_dimmer); - light_controller.calcLevels(); - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.new_color[i] = Light.current_color[i]; - } - } else { - - - - - Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"")); - LightState(1); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_WAKEUP)); - XdrvRulesProcess(); - - Light.wakeup_active = 0; - Settings.light_scheme = LS_POWER; - } - } - break; - case LS_CYCLEUP: - LightCycleColor(1); - break; - case LS_CYCLEDN: - LightCycleColor(-1); - break; - case LS_RANDOM: - LightCycleColor(0); - break; - default: - XlgtCall(FUNC_SET_SCHEME); - } - } - - if ((Settings.light_scheme < LS_MAX) || power_off) { - - - LightApplyPower(Light.new_color, Light.power); - - - - - - - - if (memcmp(Light.last_color, Light.new_color, Light.subtype)) { - Light.update = true; - } - if (Light.update) { -#ifdef USE_DEVICE_GROUPS - if (Light.power) LightSendDeviceGroupStatus(); -#endif - - uint16_t cur_col_10[LST_MAX]; - Light.update = false; - - - for (uint32_t i = 0; i < LST_MAX; i++) { - Light.last_color[i] = Light.new_color[i]; - - cur_col_10[i] = change8to10(Light.new_color[i]); - } - - if (Light.pwm_multi_channels) { - calcGammaMultiChannels(cur_col_10); - } else { - calcGammaBulbs(cur_col_10); - - - - if ((LST_RGBW <= Light.subtype) && (0 == Settings.rgbwwTable[4]) && (0 == cur_col_10[3]+cur_col_10[4])) { - uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]); - for (uint32_t i=0; i<3; i++) { - - uint32_t adjust10 = change8to10(Settings.rgbwwTable[i]); - cur_col_10[i] = changeUIntScale(cur_col_10[i] - min_rgb_10, 0, 1023, 0, adjust10); - } - - - uint32_t adjust_w_10 = changeUIntScale(Settings.rgbwwTable[3], 0, 255, 0, 1023); - uint32_t white_10 = changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); - if (LST_RGBW == Light.subtype) { - - cur_col_10[3] = white_10; - } else { - - uint32_t ct = light_state.getCT10bits(); - cur_col_10[4] = changeUIntScale(ct, 0, 1023, 0, white_10); - cur_col_10[3] = white_10 - cur_col_10[4]; - } - } - } - - - if (0 != Settings.rgbwwTable[4]) { - for (uint32_t i = 0; i 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0; - } - - - uint16_t orig_col_10bits[LST_MAX]; - memcpy(orig_col_10bits, cur_col_10, sizeof(orig_col_10bits)); - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col_10[i] = orig_col_10bits[Light.color_remap[i]]; - } - - if (!Settings.light_fade || power_off || (!Light.fade_initialized)) { - - memcpy(Light.fade_start_10, cur_col_10, sizeof(Light.fade_start_10)); - - LightSetOutputs(cur_col_10); - Light.fade_initialized = true; - } else { - if (Light.fade_running) { - - memcpy(Light.fade_start_10, Light.fade_cur_10, sizeof(Light.fade_start_10)); - } - memcpy(Light.fade_end_10, cur_col_10, sizeof(Light.fade_start_10)); - Light.fade_running = true; - Light.fade_duration = 0; - Light.fade_start = 0; - - } - } - if (Light.fade_running) { - if (LightApplyFade()) { - - - - LightSetOutputs(Light.fade_cur_10); - } - } - } -} - -bool isChannelGammaCorrected(uint32_t channel) { - if (!Settings.light_correction) { return false; } - if (channel >= Light.subtype) { return false; } - - if (PHILIPS == my_module_type) { - if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } - if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } - } - return true; -} - - -uint16_t fadeGamma(uint32_t channel, uint16_t v) { - if (isChannelGammaCorrected(channel)) { - return ledGamma_internal(v, gamma_table_fast); - } else { - return v; - } -} -uint16_t fadeGammaReverse(uint32_t channel, uint16_t vg) { - if (isChannelGammaCorrected(channel)) { - return ledGammaReverse_internal(vg, gamma_table_fast); - } else { - return vg; - } -} - -bool LightApplyFade(void) { - static uint32_t last_millis = 0; - uint32_t now = millis(); - - if ((now - last_millis) <= 5) { - return false; - } - last_millis = now; - - - if (0 == Light.fade_duration) { - Light.fade_start = now; - - uint32_t distance = 0; - for (uint32_t i = 0; i < Light.subtype; i++) { - int32_t channel_distance = fadeGammaReverse(i, Light.fade_end_10[i]) - fadeGammaReverse(i, Light.fade_start_10[i]); - if (channel_distance < 0) { channel_distance = - channel_distance; } - if (channel_distance > distance) { distance = channel_distance; } - } - if (distance > 0) { - - - - Light.fade_duration = (distance * Settings.light_speed * 500) / 1023; - if (Settings.save_data) { - - uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; - - if (save_data_counter < delay_seconds) { - save_data_counter = delay_seconds; - } - } - } else { - - Light.fade_running = false; - } - } - - uint16_t fade_current = now - Light.fade_start; - if (fade_current <= Light.fade_duration) { - - for (uint32_t i = 0; i < Light.subtype; i++) { - Light.fade_cur_10[i] = fadeGamma(i, - changeUIntScale(fadeGammaReverse(i, fade_current), - 0, Light.fade_duration, - fadeGammaReverse(i, Light.fade_start_10[i]), - fadeGammaReverse(i, Light.fade_end_10[i]))); - - - - } - } else { - - - Light.fade_running = false; - Light.fade_start = 0; - Light.fade_duration = 0; - - memcpy(Light.fade_cur_10, Light.fade_end_10, sizeof(Light.fade_end_10)); - - memcpy(Light.fade_start_10, Light.fade_end_10, sizeof(Light.fade_start_10)); - } - return true; -} - - - -void LightApplyPower(uint8_t new_color[LST_MAX], power_t power) { - - if (Light.pwm_multi_channels) { - - for (uint32_t i = 0; i < LST_MAX; i++) { - if (0 == bitRead(power,i)) { - new_color[i] = 0; - } - } - - - - - - } else { - if (!light_controller.isCTRGBLinked()) { - - if (0 == (power & 1)) { - new_color[0] = new_color[1] = new_color[2] = 0; - } - if (0 == (power & 2)) { - new_color[3] = new_color[4] = 0; - } - } else if (!power) { - for (uint32_t i = 0; i < LST_MAX; i++) { - new_color[i] = 0; - } - } - } -} - -void LightSetOutputs(const uint16_t *cur_col_10) { - - if (light_type < LT_PWM6) { - for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) { - if (pin[GPIO_PWM1 +i] < 99) { - - analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10[(i + Light.pwm_offset)] : cur_col_10[(i + Light.pwm_offset)]); - } - } - } - - - - - uint8_t cur_col[LST_MAX]; - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col[i] = change10to8(cur_col_10[i]); - } - - - uint8_t scale_col[3]; - uint32_t max = (cur_col[0] > cur_col[1] && cur_col[0] > cur_col[2]) ? cur_col[0] : (cur_col[1] > cur_col[2]) ? cur_col[1] : cur_col[2]; - for (uint32_t i = 0; i < 3; i++) { - scale_col[i] = (0 == max) ? 255 : (255 > max) ? changeUIntScale(cur_col[i], 0, max, 0, 255) : cur_col[i]; - } - - char *tmp_data = XdrvMailbox.data; - char *tmp_topic = XdrvMailbox.topic; - XdrvMailbox.data = (char*)cur_col; - XdrvMailbox.topic = (char*)scale_col; - if (XlgtCall(FUNC_SET_CHANNELS)) { } - else if (XdrvCall(FUNC_SET_CHANNELS)) { } - XdrvMailbox.data = tmp_data; - XdrvMailbox.topic = tmp_topic; -} - - -void calcGammaMultiChannels(uint16_t cur_col_10[5]) { - - if (Settings.light_correction) { - for (uint32_t i = 0; i < LST_MAX; i++) { - cur_col_10[i] = ledGamma10_10(cur_col_10[i]); - } - } -} - -void calcGammaBulbs(uint16_t cur_col_10[5]) { - - - - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - - uint32_t cw1 = Light.subtype - 1; - uint32_t cw0 = Light.subtype - 2; - uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; - uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; - - if (PHILIPS == my_module_type) { - - cur_col_10[cw1] = light_state.getCT10bits(); - - if (Settings.light_correction) { - cur_col_10[cw0] = ledGamma10_10(white_bri10_1023); - } else { - cur_col_10[cw0] = white_bri10_1023; - } - } else if (Settings.light_correction) { - - if (white_bri10 <= 1031) { - - uint16_t white_bri_gamma10 = ledGamma10_10(white_bri10_1023); - - cur_col_10[cw0] = changeUIntScale(cur_col_10[cw0], 0, white_bri10_1023, 0, white_bri_gamma10); - cur_col_10[cw1] = changeUIntScale(cur_col_10[cw1], 0, white_bri10_1023, 0, white_bri_gamma10); - } else { - cur_col_10[cw0] = ledGamma10_10(cur_col_10[cw0]); - cur_col_10[cw1] = ledGamma10_10(cur_col_10[cw1]); - } - } - } - - if (Settings.light_correction) { - - if (LST_RGB <= Light.subtype) { - for (uint32_t i = 0; i < 3; i++) { - cur_col_10[i] = ledGamma10_10(cur_col_10[i]); - } - } - - if ((LST_SINGLE == Light.subtype) || (LST_RGBW == Light.subtype)) { - cur_col_10[Light.subtype - 1] = ledGamma10_10(cur_col_10[Light.subtype - 1]); - } - } -} - -#ifdef USE_DEVICE_GROUPS -void LightSendDeviceGroupStatus() -{ - uint8_t channels[LST_MAX]; - light_state.getChannels(channels); - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme, DGR_ITEM_LIGHT_CHANNELS, channels, - DGR_ITEM_LIGHT_BRI, (power ? light_state.getBri() : 0)); -} - -void LightHandleDeviceGroupRequest() -{ - static bool send_state = false; - uint32_t value = XdrvMailbox.payload; - switch (XdrvMailbox.command_code) { - case DGR_ITEM_EOL: - LightAnimate(); - if (send_state && !(XdrvMailbox.index & DGR_FLAG_MORE_TO_COME)) { - light_controller.saveSettings(); - if (Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - send_state = false; - } - break; - case DGR_ITEM_LIGHT_BRI: - if (light_state.getBri() != value) { - light_controller.changeBri(value); - send_state = true; - } - break; - case DGR_ITEM_LIGHT_SCHEME: - if (Settings.light_scheme != value) { - Settings.light_scheme = value; - send_state = true; - } - break; - case DGR_ITEM_LIGHT_CHANNELS: - light_controller.changeChannels((uint8_t *)XdrvMailbox.data); - send_state = true; - break; - case DGR_ITEM_LIGHT_FIXED_COLOR: - { - power_t save_power = Light.power; - if (value) { - bool save_decimal_text = Settings.flag.decimal_text; - char str[16]; - XdrvMailbox.index = 2; - XdrvMailbox.data_len = sprintf_P(str, PSTR("%u"), value); - XdrvMailbox.data = str; - CmndSupportColor(); - Settings.flag.decimal_text = save_decimal_text; - } - else { - Light.fixed_color_index = 0; - XdrvMailbox.index = 1; - XdrvMailbox.payload = light_state.BriToDimmer(light_state.getBri()); - CmndWhite(); - } - if (Light.power != save_power) { - XdrvMailbox.index = save_power; - LightSetPower(); - } - send_state = true; - } - break; - case DGR_ITEM_LIGHT_SPEED: - if (Settings.light_speed != value && value > 0 && value <= 40) { - Settings.light_speed = value; - send_state = true; - } - break; - case DGR_ITEM_STATUS: - SendLocalDeviceGroupMessage(DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, - DGR_ITEM_LIGHT_SPEED, Settings.light_speed); - LightSendDeviceGroupStatus(); - break; - } -} -#endif - - - - - -bool LightColorEntry(char *buffer, uint32_t buffer_length) -{ - char scolor[10]; - char *p; - char *str; - uint32_t entry_type = 0; - uint8_t value = Light.fixed_color_index; - - if (buffer[0] == '#') { - buffer++; - buffer_length--; - } - - if (Light.subtype >= LST_RGB) { - char option = (1 == buffer_length) ? buffer[0] : '\0'; - if (('+' == option) && (Light.fixed_color_index < MAX_FIXED_COLOR)) { - value++; - } - else if (('-' == option) && (Light.fixed_color_index > 1)) { - value--; - } else { - value = atoi(buffer); - } - } - - memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); - - while ((buffer_length > 0) && ('=' == buffer[buffer_length - 1])) { - buffer_length--; - memcpy(&Light.entry_color, &Light.current_color, sizeof(Light.entry_color)); - } - if (strstr(buffer, ",") != nullptr) { - int8_t i = 0; - for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) { - if (i < LST_MAX) { - Light.entry_color[i++] = atoi(str); - } - } - entry_type = 2; - } - else if (((2 * Light.subtype) == buffer_length) || (buffer_length > 3)) { - for (uint32_t i = 0; i < tmin((uint)(buffer_length / 2), sizeof(Light.entry_color)); i++) { - strlcpy(scolor, buffer + (i *2), 3); - Light.entry_color[i] = (uint8_t)strtol(scolor, &p, 16); - } - entry_type = 1; - } - else if ((Light.subtype >= LST_RGB) && (value > 0) && (value <= MAX_FIXED_COLOR)) { - Light.fixed_color_index = value; - memcpy_P(&Light.entry_color, &kFixedColor[value -1], 3); - entry_type = 1; - } - else if ((value > 199) && (value <= 199 + MAX_FIXED_COLD_WARM)) { - if (LST_RGBW == Light.subtype) { - memcpy_P(&Light.entry_color[3], &kFixedWhite[value -200], 1); - entry_type = 1; - } - else if (LST_COLDWARM == Light.subtype) { - memcpy_P(&Light.entry_color, &kFixedColdWarm[value -200], 2); - entry_type = 1; - } - else if (LST_RGBCW == Light.subtype) { - memcpy_P(&Light.entry_color[3], &kFixedColdWarm[value -200], 2); - entry_type = 1; - } - } - if (entry_type) { - Settings.flag.decimal_text = entry_type -1; - } - return (entry_type); -} - - - -void CmndSupportColor(void) -{ - bool valid_entry = false; - bool coldim = false; - - if (XdrvMailbox.data_len > 0) { - valid_entry = LightColorEntry(XdrvMailbox.data, XdrvMailbox.data_len); - if (valid_entry) { - if (XdrvMailbox.index <= 2) { - uint32_t old_bri = light_state.getBri(); - - light_controller.changeChannels(Light.entry_color); - if (2 == XdrvMailbox.index) { - - light_controller.changeBri(old_bri); - } - - Settings.light_scheme = 0; - coldim = true; - } else { - for (uint32_t i = 0; i < LST_RGB; i++) { - Settings.ws_color[XdrvMailbox.index -3][i] = Light.entry_color[i]; - } - } - } - } - char scolor[LIGHT_COLOR_SIZE]; - if (!valid_entry && (XdrvMailbox.index <= 2)) { - ResponseCmndChar(LightGetColor(scolor)); - } - if (XdrvMailbox.index >= 3) { - scolor[0] = '\0'; - for (uint32_t i = 0; i < LST_RGB; i++) { - if (Settings.flag.decimal_text) { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.ws_color[XdrvMailbox.index -3][i]); - } else { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]); - } - } - ResponseCmndIdxChar(scolor); - } - if (coldim) { - LightPreparePower(); - } -} - -void CmndColor(void) -{ - - - - - - - - if ((Light.subtype > LST_SINGLE) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 6)) { - CmndSupportColor(); - } -} - -void CmndWhite(void) -{ - - - if (Light.pwm_multi_channels) { return; } - if ( ((Light.subtype >= LST_RGBW) || (LST_COLDWARM == Light.subtype)) && (XdrvMailbox.index == 1)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - light_controller.changeDimmer(XdrvMailbox.payload, 2); - LightPreparePower(2); - } else { - ResponseCmndNumber(light_state.getDimmer(2)); - } - } -} - -void CmndChannel(void) -{ - - - - - if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { - uint32_t light_index = XdrvMailbox.index - Light.device; - power_t coldim = 0; - - - if (1 == XdrvMailbox.data_len) { - uint8_t channel = changeUIntScale(Light.current_color[light_index],0,255,0,100); - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; - } else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (channel < 11) ? 1 : channel - 10; - } - } - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Light.current_color[light_index] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); - if (Light.pwm_multi_channels) { - coldim = 1 << light_index; - } else { - if (light_controller.isCTRGBLinked()) { - - if ((light_index < 3) && (light_controller.isCTRGBLinked())) { - Light.current_color[3] = Light.current_color[4] = 0; - } else { - Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; - } - coldim = 1; - } else { - if (light_index < 3) { coldim = 1; } - else { coldim = 2; } - } - } - light_controller.changeChannels(Light.current_color); - } - ResponseCmndIdxNumber(changeUIntScale(Light.current_color[light_index],0,255,0,100)); - if (coldim) { - LightPreparePower(coldim); - } - } -} - -void CmndHsbColor(void) -{ - - - - - - - - if (Light.subtype >= LST_RGB) { - if (XdrvMailbox.data_len > 0) { - uint16_t c_hue; - uint8_t c_sat; - light_state.getHSB(&c_hue, &c_sat, nullptr); - uint32_t HSB[3]; - HSB[0] = c_hue; - HSB[1] = c_sat; - HSB[2] = light_state.getBriRGB(); - if ((2 == XdrvMailbox.index) || (3 == XdrvMailbox.index)) { - if ((uint32_t)XdrvMailbox.payload > 100) { XdrvMailbox.payload = 100; } - HSB[XdrvMailbox.index-1] = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 255); - } else { - uint32_t paramcount = ParseParameters(3, HSB); - if (HSB[0] > 360) { HSB[0] = 360; } - for (uint32_t i = 1; i < paramcount; i++) { - if (HSB[i] > 100) { HSB[i] == 100; } - HSB[i] = changeUIntScale(HSB[i], 0, 100, 0, 255); - } - } - light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); - LightPreparePower(1); - } else { - LightState(0); - } - } -} - -void CmndScheme(void) -{ - - - - - - if (Light.subtype >= LST_RGB) { - uint32_t max_scheme = Light.max_scheme; - - if (1 == XdrvMailbox.data_len) { - if (('+' == XdrvMailbox.data[0]) && (Settings.light_scheme < max_scheme)) { - XdrvMailbox.payload = Settings.light_scheme + ((0 == Settings.light_scheme) ? 2 : 1); - } - else if (('-' == XdrvMailbox.data[0]) && (Settings.light_scheme > 0)) { - XdrvMailbox.payload = Settings.light_scheme - ((2 == Settings.light_scheme) ? 2 : 1); - } - } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= max_scheme)) { - uint32_t parm[2]; - if (ParseParameters(2, parm) > 1) { - Light.wheel = parm[1]; - } - Settings.light_scheme = XdrvMailbox.payload; -#ifdef USE_DEVICE_GROUPS - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme); -#endif - if (LS_WAKEUP == Settings.light_scheme) { - Light.wakeup_active = 3; - } - LightPowerOn(); - Light.strip_timer_counter = 0; - - if (Settings.flag3.hass_tele_on_power) { - MqttPublishTeleState(); - } - } - ResponseCmndNumber(Settings.light_scheme); - } -} - -void CmndWakeup(void) -{ - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - light_controller.changeDimmer(XdrvMailbox.payload); - } - Light.wakeup_active = 3; - Settings.light_scheme = LS_WAKEUP; - LightPowerOn(); - ResponseCmndChar(D_JSON_STARTED); -} - -void CmndColorTemperature(void) -{ - - - - - if (Light.pwm_multi_channels) { return; } - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) { - uint32_t ct = light_state.getCT(); - if (1 == XdrvMailbox.data_len) { - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (ct > (CT_MAX-34)) ? CT_MAX : ct + 34; - } - else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (ct < (CT_MIN+34)) ? CT_MIN : ct - 34; - } - } - if ((XdrvMailbox.payload >= CT_MIN) && (XdrvMailbox.payload <= CT_MAX)) { - light_controller.changeCTB(XdrvMailbox.payload, light_state.getBriCT()); - LightPreparePower(2); - } else { - ResponseCmndNumber(ct); - } - } -} - -void CmndDimmer(void) -{ - - - - - - - uint32_t dimmer; - if (XdrvMailbox.index > 2) { XdrvMailbox.index = 1; } - - if ((light_controller.isCTRGBLinked()) || (0 == XdrvMailbox.index)) { - dimmer = light_state.getDimmer(); - } else { - dimmer = light_state.getDimmer(XdrvMailbox.index); - } - - if (1 == XdrvMailbox.data_len) { - if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (dimmer > 89) ? 100 : dimmer + 10; - } else if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (dimmer < 11) ? 1 : dimmer - 10; - } - } - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - if (light_controller.isCTRGBLinked()) { - - light_controller.changeDimmer(XdrvMailbox.payload); - LightPreparePower(); - } else { - if (0 != XdrvMailbox.index) { - light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); - LightPreparePower(1 << (XdrvMailbox.index - 1)); - } else { - - light_controller.changeDimmer(XdrvMailbox.payload, 1); - light_controller.changeDimmer(XdrvMailbox.payload, 2); - LightPreparePower(); - } - } - Light.update = true; - } else { - ResponseCmndNumber(dimmer); - } -} - -void CmndDimmerRange(void) -{ - - - if (XdrvMailbox.data_len > 0) { - uint32_t parm[2]; - parm[0] = Settings.dimmer_hw_min; - parm[1] = Settings.dimmer_hw_max; - ParseParameters(2, parm); - if (parm[0] < parm[1]) { - Settings.dimmer_hw_min = parm[0]; - Settings.dimmer_hw_max = parm[1]; - } else { - Settings.dimmer_hw_min = parm[1]; - Settings.dimmer_hw_max = parm[0]; - } - restart_flag = 2; - } - Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); -} - -void CmndLedTable(void) -{ - - - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - Settings.light_correction = XdrvMailbox.payload; - break; - case 2: - Settings.light_correction ^= 1; - break; - } - Light.update = true; - } - ResponseCmndStateText(Settings.light_correction); -} - -void CmndRgbwwTable(void) -{ - - - if ((XdrvMailbox.data_len > 0)) { - uint32_t parm[LST_RGBCW -1]; - uint32_t parmcount = ParseParameters(LST_RGBCW, parm); - for (uint32_t i = 0; i < parmcount; i++) { - Settings.rgbwwTable[i] = parm[i]; - } - Light.update = true; - } - char scolor[LIGHT_COLOR_SIZE]; - scolor[0] = '\0'; - for (uint32_t i = 0; i < LST_RGBCW; i++) { - snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); - } - ResponseCmndChar(scolor); -} - -void CmndFade(void) -{ - - - - - switch (XdrvMailbox.payload) { - case 0: - case 1: - Settings.light_fade = XdrvMailbox.payload; - break; - case 2: - Settings.light_fade ^= 1; - break; - } -#ifdef USE_DEVICE_GROUPS - if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade); -#endif - if (!Settings.light_fade) { Light.fade_running = false; } - ResponseCmndStateText(Settings.light_fade); -} - -void CmndSpeed(void) -{ - - - - - if (1 == XdrvMailbox.data_len) { - if (('+' == XdrvMailbox.data[0]) && (Settings.light_speed > 1)) { - XdrvMailbox.payload = Settings.light_speed - 1; - } - else if (('-' == XdrvMailbox.data[0]) && (Settings.light_speed < 40)) { - XdrvMailbox.payload = Settings.light_speed + 1; - } - } - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 40)) { - Settings.light_speed = XdrvMailbox.payload; -#ifdef USE_DEVICE_GROUPS - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SPEED, Settings.light_speed); -#endif - } - ResponseCmndNumber(Settings.light_speed); -} - -void CmndWakeupDuration(void) -{ - - - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { - Settings.light_wakeup = XdrvMailbox.payload; - Light.wakeup_active = 0; - } - ResponseCmndNumber(Settings.light_wakeup); -} - -void CmndUndocA(void) -{ - - char scolor[LIGHT_COLOR_SIZE]; - LightGetColor(scolor, true); - scolor[6] = '\0'; - Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); - MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); - mqtt_data[0] = '\0'; -} - - - - - -bool Xdrv04(uint8_t function) -{ - bool result = false; - - if (FUNC_MODULE_INIT == function) { - return LightModuleInit(); - } - else if (light_type) { - switch (function) { - case FUNC_SERIAL: - result = XlgtCall(FUNC_SERIAL); - break; - case FUNC_LOOP: - if (Light.fade_running) { - if (LightApplyFade()) { - LightSetOutputs(Light.fade_cur_10); - } - } - break; - case FUNC_EVERY_50_MSECOND: - LightAnimate(); - break; -#ifdef USE_DEVICE_GROUPS - case FUNC_DEVICE_GROUP_REQUEST: - LightHandleDeviceGroupRequest(); - break; -#endif - case FUNC_SET_POWER: - LightSetPower(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kLightCommands, LightCommand); - if (!result) { - result = XlgtCall(FUNC_COMMAND); - } - break; - case FUNC_PRE_INIT: - LightInit(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_05_irremote.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_05_irremote.ino" -#if defined(USE_IR_REMOTE) && !defined(USE_IR_REMOTE_FULL) - - - - -#define XDRV_05 5 - -#include - -enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND }; - -const char kIrRemoteCommands[] PROGMEM = "|" D_CMND_IRSEND ; - - -void (* const IrRemoteCommand[])(void) PROGMEM = { - &CmndIrSend }; - - -static const uint8_t MAX_STANDARD_IR = NEC; -const char kIrRemoteProtocols[] PROGMEM = "UNKNOWN|RC5|RC6|NEC"; - - - - - -#include - -IRsend *irsend = nullptr; -bool irsend_active = false; - -void IrSendInit(void) -{ - irsend = new IRsend(pin[GPIO_IRSEND]); - irsend->begin(); -} - -#ifdef USE_IR_RECEIVE - - - - -const bool IR_RCV_SAVE_BUFFER = false; -const uint32_t IR_TIME_AVOID_DUPLICATE = 500; - -#include - -IRrecv *irrecv = nullptr; - -unsigned long ir_lasttime = 0; - -void IrReceiveUpdateThreshold(void) -{ - if (irrecv != nullptr) { - if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - } -} - -void IrReceiveInit(void) -{ - - irrecv = new IRrecv(pin[GPIO_IRRECV], IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER); - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - irrecv->enableIRIn(); - - -} - -void IrReceiveCheck(void) -{ - char sirtype[8]; - int8_t iridx = 0; - - decode_results results; - - if (irrecv->decode(&results)) { - char hvalue[65]; - - iridx = results.decode_type; - if ((iridx < 0) || (iridx > MAX_STANDARD_IR)) { iridx = 0; } - - if (iridx) { - if (results.bits > 64) { - - uint32_t digits2 = results.bits / 8; - if (results.bits % 8) { digits2++; } - ToHex_P((unsigned char*)results.state, digits2, hvalue, sizeof(hvalue)); - } else { - Uint64toHex(results.value, hvalue, results.bits); - } - } else { - Uint64toHex(results.value, hvalue, 32); - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%s, Decode %d"), - irsend_active, results.rawlen, results.overflow, results.bits, hvalue, results.decode_type); - - unsigned long now = millis(); - - if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { - ir_lasttime = now; - - char svalue[64]; - if (Settings.flag.ir_receive_decimal) { - ulltoa(results.value, svalue, 10); - } else { - snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue); - } - ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d"), - GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits); - if (iridx) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_DATA "\":%s"), svalue); - } else { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_HASH "\":%s"), svalue); - } - - if (Settings.flag3.receive_raw) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); - uint16_t i; - for (i = 1; i < results.rawlen; i++) { - if (i > 1) { ResponseAppend_P(PSTR(",")); } - uint32_t usecs; - for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); - } - ResponseAppend_P(PSTR("%d"), usecs); - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } - } - uint16_t extended_length = results.rawlen - 1; - for (uint32_t j = 0; j < results.rawlen - 1; j++) { - uint32_t usecs = results.rawbuf[j] * kRawTick; - - extended_length += (usecs / (UINT16_MAX + 1)) * 2; - } - ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - - XdrvRulesProcess(); -#ifdef USE_DOMOTICZ - if (iridx) { - unsigned long value = results.value | (iridx << 28); - DomoticzSensor(DZ_COUNT, value); - } -#endif - } - - irrecv->resume(); - } -} -#endif - - - - - -uint32_t IrRemoteCmndIrSendJson(void) -{ - - - - - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { - return IE_INVALID_JSON; - } - - StaticJsonBuffer<140> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); - if (!root.success()) { - return IE_INVALID_JSON; - } - - - - char parm_uc[10]; - const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; - uint16_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint64_t data = strtoull(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); - uint16_t repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT))]; - - if (XdrvMailbox.index > repeat + 1) { - repeat = XdrvMailbox.index - 1; - } - if (!(protocol && bits)) { - return IE_SYNTAX_IRSEND; - } - - char protocol_text[20]; - int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - - char dvalue[64]; - char hvalue[20]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %s (0x%s), repeat %d, protocol_code %d"), - protocol_text, protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat, protocol_code); - - irsend_active = true; - switch (protocol_code) { -#ifdef USE_IR_SEND_RC5 - case RC5: - irsend->sendRC5(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_RC6 - case RC6: - irsend->sendRC6(data, bits, repeat); break; -#endif -#ifdef USE_IR_SEND_NEC - case NEC: - irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits, repeat); break; -#endif - default: - irsend_active = false; - ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); - } - - return IE_NO_ERROR; -} - -void CmndIrSend(void) -{ - uint8_t error = IE_SYNTAX_IRSEND; - - if (XdrvMailbox.data_len) { - - if (strstr(XdrvMailbox.data, "{") == nullptr) { - error = IE_INVALID_JSON; - } else { - error = IrRemoteCmndIrSendJson(); - } - } - IrRemoteCmndResponse(error); -} - -void IrRemoteCmndResponse(uint32_t error) -{ - switch (error) { - case IE_INVALID_RAWDATA: - ResponseCmndChar(D_JSON_INVALID_RAWDATA); - break; - case IE_INVALID_JSON: - ResponseCmndChar(D_JSON_INVALID_JSON); - break; - case IE_SYNTAX_IRSEND: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); - break; - default: - ResponseCmndDone(); - } -} - - - - - -bool Xdrv05(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { - switch (function) { - case FUNC_PRE_INIT: - if (pin[GPIO_IRSEND] < 99) { - IrSendInit(); - } -#ifdef USE_IR_RECEIVE - if (pin[GPIO_IRRECV] < 99) { - IrReceiveInit(); - } -#endif - break; - case FUNC_EVERY_50_MSECOND: -#ifdef USE_IR_RECEIVE - if (pin[GPIO_IRRECV] < 99) { - IrReceiveCheck(); - } -#endif - irsend_active = false; - break; - case FUNC_COMMAND: - if (pin[GPIO_IRSEND] < 99) { - result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); - } - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_05_irremote_full.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_05_irremote_full.ino" -#ifdef USE_IR_REMOTE_FULL - - - - -#define XDRV_05 5 - -#include -#include -#include -#include -#include - -enum IrErrors { IE_RESPONSE_PROVIDED, IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC, - IE_UNSUPPORTED_HVAC, IE_UNSUPPORTED_PROTOCOL }; - -const char kIrRemoteCommands[] PROGMEM = "|" - D_CMND_IRHVAC "|" D_CMND_IRSEND ; - -void (* const IrRemoteCommand[])(void) PROGMEM = { - &CmndIrHvac, &CmndIrSend }; - - - - - -IRsend *irsend = nullptr; -bool irsend_active = false; - -void IrSendInit(void) -{ - irsend = new IRsend(pin[GPIO_IRSEND]); - irsend->begin(); -} - - - -uint8_t reverseBitsInByte(uint8_t b) { - b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; - b = (b & 0xCC) >> 2 | (b & 0x33) << 2; - b = (b & 0xAA) >> 1 | (b & 0x55) << 1; - return b; -} - - -uint64_t reverseBitsInBytes64(uint64_t b) { - union { - uint8_t b[8]; - uint64_t i; - } a; - a.i = b; - for (uint32_t i=0; i<8; i++) { - a.b[i] = reverseBitsInByte(a.b[i]); - } - return a.i; -} - - - - - -const bool IR_FULL_RCV_SAVE_BUFFER = false; -const uint32_t IR_TIME_AVOID_DUPLICATE = 500; - - - - -const uint16_t IR_FULL_BUFFER_SIZE = 1024; - - - -const uint8_t IR__FULL_RCV_TIMEOUT = 50; - -IRrecv *irrecv = nullptr; - -unsigned long ir_lasttime = 0; - -void IrReceiveUpdateThreshold(void) -{ - if (irrecv != nullptr) { - if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; } - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - } -} - -void IrReceiveInit(void) -{ - - irrecv = new IRrecv(pin[GPIO_IRRECV], IR_FULL_BUFFER_SIZE, IR__FULL_RCV_TIMEOUT, IR_FULL_RCV_SAVE_BUFFER); - irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]); - irrecv->enableIRIn(); -} - -String sendACJsonState(const stdAc::state_t &state) { - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); - json[D_JSON_IRHVAC_VENDOR] = typeToString(state.protocol); - json[D_JSON_IRHVAC_MODEL] = state.model; - json[D_JSON_IRHVAC_POWER] = IRac::boolToString(state.power); - json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(state.mode); - - if (state.mode == stdAc::opmode_t::kOff || !state.power) { - json[D_JSON_IRHVAC_MODE] = IRac::opmodeToString(stdAc::opmode_t::kOff); - json[D_JSON_IRHVAC_POWER] = IRac::boolToString(false); - } - json[D_JSON_IRHVAC_CELSIUS] = IRac::boolToString(state.celsius); - if (floorf(state.degrees) == state.degrees) { - json[D_JSON_IRHVAC_TEMP] = floorf(state.degrees); - } else { - json[D_JSON_IRHVAC_TEMP] = RawJson(String(state.degrees, 1)); - } - json[D_JSON_IRHVAC_FANSPEED] = IRac::fanspeedToString(state.fanspeed); - json[D_JSON_IRHVAC_SWINGV] = IRac::swingvToString(state.swingv); - json[D_JSON_IRHVAC_SWINGH] = IRac::swinghToString(state.swingh); - json[D_JSON_IRHVAC_QUIET] = IRac::boolToString(state.quiet); - json[D_JSON_IRHVAC_TURBO] = IRac::boolToString(state.turbo); - json[D_JSON_IRHVAC_ECONO] = IRac::boolToString(state.econo); - json[D_JSON_IRHVAC_LIGHT] = IRac::boolToString(state.light); - json[D_JSON_IRHVAC_FILTER] = IRac::boolToString(state.filter); - json[D_JSON_IRHVAC_CLEAN] = IRac::boolToString(state.clean); - json[D_JSON_IRHVAC_BEEP] = IRac::boolToString(state.beep); - json[D_JSON_IRHVAC_SLEEP] = state.sleep; - - String payload = ""; - payload.reserve(200); - json.printTo(payload); - return payload; -} - -String sendIRJsonState(const struct decode_results &results) { - String json("{"); - json += "\"" D_JSON_IR_PROTOCOL "\":\""; - json += typeToString(results.decode_type); - json += "\",\"" D_JSON_IR_BITS "\":"; - json += results.bits; - - if (hasACState(results.decode_type)) { - json += ",\"" D_JSON_IR_DATA "\":\"0x"; - json += resultToHexidecimal(&results); - json += "\""; - } else { - if (UNKNOWN != results.decode_type) { - json += ",\"" D_JSON_IR_DATA "\":"; - } else { - json += ",\"" D_JSON_IR_HASH "\":"; - } - if (Settings.flag.ir_receive_decimal) { - char svalue[32]; - ulltoa(results.value, svalue, 10); - json += svalue; - } else { - char hvalue[64]; - if (UNKNOWN != results.decode_type) { - Uint64toHex(results.value, hvalue, results.bits); - json += "\"0x"; - json += hvalue; - json += "\",\"" D_JSON_IR_DATALSB "\":\"0x"; - Uint64toHex(reverseBitsInBytes64(results.value), hvalue, results.bits); - json += hvalue; - json += "\""; - } else { - Uint64toHex(results.value, hvalue, 32); - json += "\"0x"; - json += hvalue; - json += "\""; - } - } - } - json += ",\"" D_JSON_IR_REPEAT "\":"; - json += results.repeat; - - stdAc::state_t ac_result; - if (IRAcUtils::decodeToState(&results, &ac_result, nullptr)) { - - json += ",\"" D_CMND_IRHVAC "\":"; - json += sendACJsonState(ac_result); - } - - return json; -} - -void IrReceiveCheck(void) -{ - decode_results results; - - if (irrecv->decode(&results)) { - uint32_t now = millis(); - - - if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) { - ir_lasttime = now; - Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str()); - - if (Settings.flag3.receive_raw) { - ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); - uint16_t i; - for (i = 1; i < results.rawlen; i++) { - if (i > 1) { ResponseAppend_P(PSTR(",")); } - uint32_t usecs; - for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); - } - ResponseAppend_P(PSTR("%d"), usecs); - if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } - } - uint16_t extended_length = results.rawlen - 1; - for (uint32_t j = 0; j < results.rawlen - 1; j++) { - uint32_t usecs = results.rawbuf[j] * kRawTick; - - extended_length += (usecs / (UINT16_MAX + 1)) * 2; - } - ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); - } - - ResponseJsonEndEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); - - XdrvRulesProcess(); - } - - irrecv->resume(); - } -} - - - - - - - -String listSupportedProtocols(bool hvac) { - String l(""); - bool first = true; - for (uint32_t i = UNUSED + 1; i <= kLastDecodeType; i++) { - bool found = false; - if (hvac) { - found = IRac::isProtocolSupported((decode_type_t)i); - } else { - found = (IRsend::defaultBits((decode_type_t)i) > 0) && (!IRac::isProtocolSupported((decode_type_t)i)); - } - if (found) { - if (first) { - first = false; - } else { - l += "|"; - } - l += typeToString((decode_type_t)i); - } - } - return l; -} - - -const stdAc::fanspeed_t IrHvacFanSpeed[] PROGMEM = { stdAc::fanspeed_t::kAuto, - stdAc::fanspeed_t::kMin, stdAc::fanspeed_t::kLow,stdAc::fanspeed_t::kMedium, - stdAc::fanspeed_t::kHigh, stdAc::fanspeed_t::kMax }; - -uint32_t IrRemoteCmndIrHvacJson(void) -{ - stdAc::state_t state, prev; - char parm_uc[12]; - - - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } - - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(dataBufUc); - if (!json.success()) { return IE_INVALID_JSON; } - - - state.protocol = decode_type_t::UNKNOWN; - state.model = 1; - state.mode = stdAc::opmode_t::kAuto; - state.power = false; - state.celsius = true; - state.degrees = 21.0f; - state.fanspeed = stdAc::fanspeed_t::kMedium; - state.swingv = stdAc::swingv_t::kOff; - state.swingh = stdAc::swingh_t::kOff; - state.light = false; - state.beep = false; - state.econo = false; - state.filter = false; - state.turbo = false; - state.quiet = false; - state.sleep = -1; - state.clean = false; - state.clock = -1; - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); - if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); - if (json.containsKey(parm_uc)) { state.protocol = strToDecodeType(json[parm_uc]); } - if (decode_type_t::UNKNOWN == state.protocol) { return IE_UNSUPPORTED_HVAC; } - if (!IRac::isProtocolSupported(state.protocol)) { return IE_UNSUPPORTED_HVAC; } - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FANSPEED)); - if (json.containsKey(parm_uc)) { - uint32_t fan_speed = json[parm_uc]; - if ((fan_speed >= 1) && (fan_speed <= 5)) { - state.fanspeed = (stdAc::fanspeed_t) pgm_read_byte(&IrHvacFanSpeed[fan_speed]); - } else { - state.fanspeed = IRac::strToFanspeed(json[parm_uc]); - } - } - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODEL)); - if (json.containsKey(parm_uc)) { state.model = IRac::strToModel(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_MODE)); - if (json.containsKey(parm_uc)) { state.mode = IRac::strToOpmode(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGV)); - if (json.containsKey(parm_uc)) { state.swingv = IRac::strToSwingV(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SWINGH)); - if (json.containsKey(parm_uc)) { state.swingh = IRac::strToSwingH(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TEMP)); - if (json.containsKey(parm_uc)) { state.degrees = json[parm_uc]; } - - - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_POWER)); - if (json.containsKey(parm_uc)) { state.power = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CELSIUS)); - if (json.containsKey(parm_uc)) { state.celsius = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_LIGHT)); - if (json.containsKey(parm_uc)) { state.light = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_BEEP)); - if (json.containsKey(parm_uc)) { state.beep = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_ECONO)); - if (json.containsKey(parm_uc)) { state.econo = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_FILTER)); - if (json.containsKey(parm_uc)) { state.filter = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_TURBO)); - if (json.containsKey(parm_uc)) { state.turbo = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_QUIET)); - if (json.containsKey(parm_uc)) { state.quiet = IRac::strToBool(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_CLEAN)); - if (json.containsKey(parm_uc)) { state.clean = IRac::strToBool(json[parm_uc]); } - - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_SLEEP)); - if (json[parm_uc]) { state.sleep = json[parm_uc]; } - - - IRac ac(pin[GPIO_IRSEND]); - bool success = ac.sendAc(state, &prev); - if (!success) { return IE_SYNTAX_IRHVAC; } - - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":%s}"), sendACJsonState(state).c_str()); - return IE_RESPONSE_PROVIDED; -} - -void CmndIrHvac(void) -{ - uint8_t error = IE_SYNTAX_IRHVAC; - - if (XdrvMailbox.data_len) { - error = IrRemoteCmndIrHvacJson(); - } - if (error != IE_RESPONSE_PROVIDED) { IrRemoteCmndResponse(error); } -} - - - - - -uint32_t IrRemoteCmndIrSendJson(void) -{ - char parm_uc[12]; - - - - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - RemoveSpace(dataBufUc); - if (strlen(dataBufUc) < 8) { return IE_INVALID_JSON; } - - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(dataBufUc); - if (!json.success()) { return IE_INVALID_JSON; } - - - - decode_type_t protocol = decode_type_t::UNKNOWN; - uint16_t bits = 0; - uint64_t data; - uint8_t repeat = 0; - - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_VENDOR)); - if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } - UpperCase_P(parm_uc, PSTR(D_JSON_IRHVAC_PROTOCOL)); - if (json.containsKey(parm_uc)) { protocol = strToDecodeType(json[parm_uc]); } - if (decode_type_t::UNKNOWN == protocol) { return IE_UNSUPPORTED_PROTOCOL; } - - UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS)); - if (json.containsKey(parm_uc)) { bits = json[parm_uc]; } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_REPEAT)); - if (json.containsKey(parm_uc)) { repeat = json[parm_uc]; } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATALSB)); - if (json.containsKey(parm_uc)) { data = reverseBitsInBytes64(strtoull(json[parm_uc], nullptr, 0)); } - UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA)); - if (json.containsKey(parm_uc)) { data = strtoull(json[parm_uc], nullptr, 0); } - if (0 == bits) { return IE_SYNTAX_IRSEND; } - - - if (XdrvMailbox.index > repeat + 1) { repeat = XdrvMailbox.index - 1; } - - char dvalue[32]; - char hvalue[32]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol %d, bits %d, data 0x%s (%s), repeat %d"), - protocol, bits, ulltoa(data, dvalue, 10), Uint64toHex(data, hvalue, bits), repeat); - - irsend_active = true; - bool success = irsend->send(protocol, data, bits, repeat); - - if (!success) { - irsend_active = false; - ResponseCmndChar(D_JSON_PROTOCOL_NOT_SUPPORTED); - } - return IE_NO_ERROR; -} - -uint32_t IrRemoteCmndIrSendRaw(void) -{ - - - - - - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - if (p == nullptr) { - return IE_INVALID_RAWDATA; - } - - - uint16_t repeat = XdrvMailbox.index > 0 ? XdrvMailbox.index - 1 : 0; - - uint16_t freq = atoi(str); - if (!freq && (*str != '0')) { - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (count < 2) { - return IE_INVALID_RAWDATA; - } - - uint16_t parm[count]; - for (uint32_t i = 0; i < count; i++) { - parm[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - if (!parm[i]) { - if (!i) { - parm[0] = 38000; - } else { - return IE_INVALID_RAWDATA; - } - } - } - - uint16_t i = 0; - if (count < 4) { - - uint16_t mark = parm[1] *2; - if (3 == count) { - if (parm[2] < parm[1]) { - - mark = parm[1] * parm[2]; - } else { - - mark = parm[2]; - } - } - uint16_t raw_array[strlen(p)]; - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[1]; - } - else if (*p == '1') { - raw_array[i++] = mark; - } - } - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { - irsend->space(40000); - } - } - } - else if (6 == count) { - - uint16_t raw_array[strlen(p)*2+3]; - raw_array[i++] = parm[1]; - raw_array[i++] = parm[2]; - uint32_t inter_message_32 = (parm[1] + parm[2]) * 3; - uint16_t inter_message = (inter_message_32 > 65000) ? 65000 : inter_message_32; - for (; *p; *p++) { - if (*p == '0') { - raw_array[i++] = parm[3]; - raw_array[i++] = parm[4]; - } - else if (*p == '1') { - raw_array[i++] = parm[3]; - raw_array[i++] = parm[5]; - } - } - raw_array[i++] = parm[3]; - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, i, parm[0]); - if (r < repeat) { - irsend->space(inter_message); - } - } - } - else { - return IE_INVALID_RAWDATA; - } - } else { - if (!freq) { freq = 38000; } - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (0 == count) { - return IE_INVALID_RAWDATA; - } - - - count++; - if (count < 200) { - uint16_t raw_array[count]; - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - } - - - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - } else { - uint16_t *raw_array = reinterpret_cast(malloc(count * sizeof(uint16_t))); - if (raw_array == nullptr) { - return IE_INVALID_RAWDATA; - } - - for (uint32_t i = 0; i < count; i++) { - raw_array[i] = strtol(strtok_r(nullptr, ", ", &p), nullptr, 0); - } - - - - irsend_active = true; - for (uint32_t r = 0; r <= repeat; r++) { - irsend->sendRaw(raw_array, count, freq); - } - free(raw_array); - } - } - - return IE_NO_ERROR; -} - -void CmndIrSend(void) -{ - uint8_t error = IE_SYNTAX_IRSEND; - - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, "{") == nullptr) { - error = IrRemoteCmndIrSendRaw(); - } else { - error = IrRemoteCmndIrSendJson(); - } - } - IrRemoteCmndResponse(error); -} - -void IrRemoteCmndResponse(uint32_t error) -{ - switch (error) { - case IE_INVALID_RAWDATA: - ResponseCmndChar(D_JSON_INVALID_RAWDATA); - break; - case IE_INVALID_JSON: - ResponseCmndChar(D_JSON_INVALID_JSON); - break; - case IE_SYNTAX_IRSEND: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); - break; - case IE_SYNTAX_IRHVAC: - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); - break; - case IE_UNSUPPORTED_HVAC: - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR " (%s)\"}"), listSupportedProtocols(true).c_str()); - break; - case IE_UNSUPPORTED_PROTOCOL: - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_PROTOCOL " (%s)\"}"), listSupportedProtocols(false).c_str()); - break; - default: - ResponseCmndDone(); - } -} - - - - - -bool Xdrv05(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_IRSEND] < 99) || (pin[GPIO_IRRECV] < 99)) { - switch (function) { - case FUNC_PRE_INIT: - if (pin[GPIO_IRSEND] < 99) { - IrSendInit(); - } - if (pin[GPIO_IRRECV] < 99) { - IrReceiveInit(); - } - break; - case FUNC_EVERY_50_MSECOND: - if (pin[GPIO_IRRECV] < 99) { - IrReceiveCheck(); - } - irsend_active = false; - break; - case FUNC_COMMAND: - if (pin[GPIO_IRSEND] < 99) { - result = DecodeCommand(kIrRemoteCommands, IrRemoteCommand); - } - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_06_snfbridge.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_06_snfbridge.ino" -#ifdef USE_SONOFF_RF - - - - -#define XDRV_06 6 - -const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; - -enum SonoffBridgeCommands { - CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE }; - -const char kSonoffBridgeCommands[] PROGMEM = "|" - D_CMND_RFSYNC "|" D_CMND_RFLOW "|" D_CMND_RFHIGH "|" D_CMND_RFHOST "|" D_CMND_RFCODE "|" D_CMND_RFKEY "|" D_CMND_RFRAW; - -void (* const SonoffBridgeCommand[])(void) PROGMEM = { - &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfBridge, &CmndRfKey, &CmndRfRaw }; - -struct SONOFFBRIDGE { - uint32_t last_received_id = 0; - uint32_t last_send_code = 0; - uint32_t last_time = 0; - uint32_t last_learn_time = 0; - uint8_t receive_flag = 0; - uint8_t receive_raw_flag = 0; - uint8_t learn_key = 1; - uint8_t learn_active = 0; - uint8_t expected_bytes = 0; -} SnfBridge; - -#ifdef USE_RF_FLASH - - - - - - - -#include "ihx.h" -#include "c2.h" - -const ssize_t RF_RECORD_NO_START_FOUND = -1; -const ssize_t RF_RECORD_NO_END_FOUND = -2; - -ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) -{ - for (size_t i = 0; i < size; i++) { - if (buf[i] == ':') { - return i; - } - } - return RF_RECORD_NO_START_FOUND; -} - -ssize_t rf_find_hex_record_end(uint8_t *buf, size_t size) -{ - for (size_t i = 0; i < size; i++) { - if (buf[i] == '\n') { - return i; - } - } - return RF_RECORD_NO_END_FOUND; -} - -ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uint8_t *new_data, size_t new_data_len) -{ - ssize_t record_start; - ssize_t record_end; - ssize_t glue_record_sz; - uint8_t *glue_buf; - ssize_t result; - - if (remnant_data[0] != ':') { return -8; } - - - record_end = rf_find_hex_record_end(new_data, new_data_len); - record_start = rf_find_hex_record_start(new_data, new_data_len); - - - - - if ((record_start != RF_RECORD_NO_START_FOUND) && (record_start < record_end)) { - return -8; - } - - glue_record_sz = strlen((const char *) remnant_data) + record_end; - - glue_buf = (uint8_t *) malloc(glue_record_sz); - if (glue_buf == nullptr) { return -2; } - - - memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); - memcpy(glue_buf + strlen((const char *) remnant_data), new_data, record_end); - - result = rf_decode_and_write(glue_buf, glue_record_sz); - free(glue_buf); - return result; -} - -ssize_t rf_decode_and_write(uint8_t *record, size_t size) -{ - uint8_t err = ihx_decode(record, size); - if (err != IHX_SUCCESS) { return -13; } - - ihx_t *h = (ihx_t *) record; - if (h->record_type == IHX_RT_DATA) { - int retries = 5; - uint16_t address = h->address_high * 0x100 + h->address_low; - - do { - err = c2_programming_init(); - err = c2_block_write(address, h->data, h->len); - } while (err != C2_SUCCESS && retries--); - } else if (h->record_type == IHX_RT_END_OF_FILE) { - - err = c2_reset(); - } - - if (err != C2_SUCCESS) { return -12; } - - return 0; -} - -ssize_t rf_search_and_write(uint8_t *buf, size_t size) -{ - - ssize_t rec_end; - ssize_t rec_start; - ssize_t err; - - for (size_t i = 0; i < size; i++) { - - rec_start = rf_find_hex_record_start(buf + i, size - i); - if (rec_start == RF_RECORD_NO_START_FOUND) { - - return -8; - } - - - rec_start += i; - rec_end = rf_find_hex_record_end(buf + rec_start, size - rec_start); - if (rec_end == RF_RECORD_NO_END_FOUND) { - - return rec_start; - } - - - rec_end += rec_start; - - err = rf_decode_and_write(buf + rec_start, rec_end - rec_start); - if (err < 0) { return err; } - i = rec_end; - } - - return 0; -} - -uint8_t rf_erase_flash(void) -{ - uint8_t err; - - for (uint32_t i = 0; i < 4; i++) { - err = c2_programming_init(); - if (err != C2_SUCCESS) { - return 10; - } - err = c2_device_erase(); - if (err != C2_SUCCESS) { - if (i < 3) { - c2_reset(); - } else { - return 11; - } - } else { - break; - } - } - return 0; -} - -uint8_t SnfBrUpdateInit(void) -{ - pinMode(PIN_C2CK, OUTPUT); - pinMode(PIN_C2D, INPUT); - - return rf_erase_flash(); -} -#endif - - - -void SonoffBridgeReceivedRaw(void) -{ - - uint8_t buckets = 0; - - if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } - - ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); - for (uint32_t i = 0; i < serial_in_byte_counter; i++) { - ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); - if (0xB1 == serial_in_buffer[1]) { - if ((i > 3) && buckets) { buckets--; } - if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { - ResponseAppend_P(PSTR(" ")); - } - } - } - ResponseAppend_P(PSTR("\"}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); - - XdrvRulesProcess(); -} - - - -void SonoffBridgeLearnFailed(void) -{ - SnfBridge.learn_active = 0; - Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARN_FAILED); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); -} - -void SonoffBridgeReceived(void) -{ - uint16_t sync_time = 0; - uint16_t low_time = 0; - uint16_t high_time = 0; - uint32_t received_id = 0; - char rfkey[8]; - char stemp[16]; - - AddLogSerial(LOG_LEVEL_DEBUG); - - if (0xA2 == serial_in_buffer[0]) { - SonoffBridgeLearnFailed(); - } - else if (0xA3 == serial_in_buffer[0]) { - SnfBridge.learn_active = 0; - low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; - high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; - if (low_time && high_time) { - for (uint32_t i = 0; i < 9; i++) { - Settings.rf_code[SnfBridge.learn_key][i] = serial_in_buffer[i +1]; - } - Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); - } else { - SonoffBridgeLearnFailed(); - } - } - else if (0xA4 == serial_in_buffer[0]) { - if (SnfBridge.learn_active) { - SonoffBridgeLearnFailed(); - } else { - sync_time = serial_in_buffer[1] << 8 | serial_in_buffer[2]; - low_time = serial_in_buffer[3] << 8 | serial_in_buffer[4]; - high_time = serial_in_buffer[5] << 8 | serial_in_buffer[6]; - received_id = serial_in_buffer[7] << 16 | serial_in_buffer[8] << 8 | serial_in_buffer[9]; - - unsigned long now = millis(); - if (!((received_id == SnfBridge.last_received_id) && (now - SnfBridge.last_time < SFB_TIME_AVOID_DUPLICATE))) { - SnfBridge.last_received_id = received_id; - SnfBridge.last_time = now; - strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey)); - for (uint32_t i = 1; i <= 16; i++) { - if (Settings.rf_code[i][0]) { - uint32_t send_id = Settings.rf_code[i][6] << 16 | Settings.rf_code[i][7] << 8 | Settings.rf_code[i][8]; - if (send_id == received_id) { - snprintf_P(rfkey, sizeof(rfkey), PSTR("%d"), i); - break; - } - } - } - if (Settings.flag.rf_receive_decimal) { - snprintf_P(stemp, sizeof(stemp), PSTR("%u"), received_id); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); - } - ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), - sync_time, low_time, high_time, stemp, rfkey); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); - XdrvRulesProcess(); - #ifdef USE_DOMOTICZ - DomoticzSensor(DZ_COUNT, received_id); - #endif - } - } - } -} - -bool SonoffBridgeSerialInput(void) -{ - - static int8_t receive_len = 0; - - if (SnfBridge.receive_flag) { - if (SnfBridge.receive_raw_flag) { - if (!serial_in_byte_counter) { - serial_in_buffer[serial_in_byte_counter++] = 0xAA; - } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 3) { - if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { - receive_len = serial_in_buffer[2] + 4; - } - } - if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { - SonoffBridgeReceivedRaw(); - SnfBridge.receive_flag = 0; - return 1; - } - } - else if (!((0 == serial_in_byte_counter) && (0 == serial_in_byte))) { - if (0 == serial_in_byte_counter) { - SnfBridge.expected_bytes = 2; - if (serial_in_byte >= 0xA3) { - SnfBridge.expected_bytes = 11; - } - if (serial_in_byte == 0xA6) { - SnfBridge.expected_bytes = 0; - serial_in_buffer[serial_in_byte_counter++] = 0xAA; - SnfBridge.receive_raw_flag = 1; - } - } - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if ((SnfBridge.expected_bytes == serial_in_byte_counter) && (0x55 == serial_in_byte)) { - SonoffBridgeReceived(); - SnfBridge.receive_flag = 0; - return 1; - } - } - serial_in_byte = 0; - } - if (0xAA == serial_in_byte) { - serial_in_byte_counter = 0; - serial_in_byte = 0; - SnfBridge.receive_flag = 1; - receive_len = 0; - } - return 0; -} - -void SonoffBridgeSendCommand(uint8_t code) -{ - Serial.write(0xAA); - Serial.write(code); - Serial.write(0x55); -} - -void SonoffBridgeSendAck(void) -{ - Serial.write(0xAA); - Serial.write(0xA0); - Serial.write(0x55); -} - -void SonoffBridgeSendCode(uint32_t code) -{ - Serial.write(0xAA); - Serial.write(0xA5); - for (uint32_t i = 0; i < 6; i++) { - Serial.write(Settings.rf_code[0][i]); - } - Serial.write((code >> 16) & 0xff); - Serial.write((code >> 8) & 0xff); - Serial.write(code & 0xff); - Serial.write(0x55); - Serial.flush(); -} - -void SonoffBridgeSend(uint8_t idx, uint8_t key) -{ - uint8_t code; - - key--; - Serial.write(0xAA); - Serial.write(0xA5); - for (uint32_t i = 0; i < 8; i++) { - Serial.write(Settings.rf_code[idx][i]); - } - if (0 == idx) { - code = (0x10 << (key >> 2)) | (1 << (key & 3)); - } else { - code = Settings.rf_code[idx][8]; - } - Serial.write(code); - Serial.write(0x55); - Serial.flush(); -#ifdef USE_DOMOTICZ - - -#endif -} - -void SonoffBridgeLearn(uint8_t key) -{ - SnfBridge.learn_key = key; - SnfBridge.learn_active = 1; - SnfBridge.last_learn_time = millis(); - Serial.write(0xAA); - Serial.write(0xA1); - Serial.write(0x55); -} - - - - - -void CmndRfBridge(void) -{ - char *p; - char stemp [10]; - uint32_t code = 0; - uint8_t radix = 10; - - uint32_t set_index = XdrvMailbox.command_code *2; - - if (XdrvMailbox.data[0] == '#') { - XdrvMailbox.data++; - XdrvMailbox.data_len--; - radix = 16; - } - - if (XdrvMailbox.data_len) { - code = strtol(XdrvMailbox.data, &p, radix); - if (code) { - if (CMND_RFCODE == XdrvMailbox.command_code) { - SnfBridge.last_send_code = code; - SonoffBridgeSendCode(code); - } else { - if (1 == XdrvMailbox.payload) { - code = pgm_read_byte(kDefaultRfCode + set_index) << 8 | pgm_read_byte(kDefaultRfCode + set_index +1); - } - uint8_t msb = code >> 8; - uint8_t lsb = code & 0xFF; - if ((code > 0) && (code < 0x7FFF) && (msb != 0x55) && (lsb != 0x55)) { - Settings.rf_code[0][set_index] = msb; - Settings.rf_code[0][set_index +1] = lsb; - } - } - } - } - if (CMND_RFCODE == XdrvMailbox.command_code) { - code = SnfBridge.last_send_code; - } else { - code = Settings.rf_code[0][set_index] << 8 | Settings.rf_code[0][set_index +1]; - } - if (10 == radix) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), code); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"#%06X\""), code); - } - Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp); -} - -void CmndRfKey(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) { - unsigned long now = millis(); - if ((!SnfBridge.learn_active) || (now - SnfBridge.last_learn_time > 60100)) { - SnfBridge.learn_active = 0; - if (2 == XdrvMailbox.payload) { - SonoffBridgeLearn(XdrvMailbox.index); - ResponseCmndIdxChar(D_JSON_START_LEARNING); - } - else if (3 == XdrvMailbox.payload) { - Settings.rf_code[XdrvMailbox.index][0] = 0; - ResponseCmndIdxChar(D_JSON_SET_TO_DEFAULT); - } - else if (4 == XdrvMailbox.payload) { - for (uint32_t i = 0; i < 6; i++) { - Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i]; - } - Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff; - Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff; - Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff; - ResponseCmndIdxChar(D_JSON_SAVED); - } else if (5 == XdrvMailbox.payload) { - uint8_t key = XdrvMailbox.index; - uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; - uint16_t sync_time = (Settings.rf_code[index][0] << 8) | Settings.rf_code[index][1]; - uint16_t low_time = (Settings.rf_code[index][2] << 8) | Settings.rf_code[index][3]; - uint16_t high_time = (Settings.rf_code[index][4] << 8) | Settings.rf_code[index][5]; - uint32_t code = (Settings.rf_code[index][6] << 16) | (Settings.rf_code[index][7] << 8); - if (0 == index) { - key--; - code |= (uint8_t)((0x10 << (key >> 2)) | (1 << (key & 3))); - } else { - code |= Settings.rf_code[index][8]; - } - Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), - XdrvMailbox.command, XdrvMailbox.index, sync_time, low_time, high_time, code); - } else { - if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { - SonoffBridgeSend(0, XdrvMailbox.index); - ResponseCmndIdxChar(D_JSON_DEFAULT_SENT); - } else { - SonoffBridgeSend(XdrvMailbox.index, 0); - ResponseCmndIdxChar(D_JSON_LEARNED_SENT); - } - } - } else { - Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, SnfBridge.learn_key, D_JSON_LEARNING_ACTIVE); - } - } -} - -void CmndRfRaw(void) -{ - if (XdrvMailbox.data_len) { - if (XdrvMailbox.data_len < 6) { - switch (XdrvMailbox.payload) { - case 0: - SonoffBridgeSendCommand(0xA7); - case 1: - SnfBridge.receive_raw_flag = XdrvMailbox.payload; - break; - case 166: - case 167: - case 169: - case 176: - case 177: - case 255: - SonoffBridgeSendCommand(XdrvMailbox.payload); - SnfBridge.receive_raw_flag = 1; - break; - case 192: - char beep[] = "AAC000C055\0"; - SerialSendRaw(beep); - break; - } - } else { - SerialSendRaw(RemoveSpace(XdrvMailbox.data)); - SnfBridge.receive_raw_flag = 1; - } - } - ResponseCmndStateText(SnfBridge.receive_raw_flag); -} - - - - - -bool Xdrv06(uint8_t function) -{ - bool result = false; - - if (SONOFF_BRIDGE == my_module_type) { - switch (function) { - case FUNC_SERIAL: - result = SonoffBridgeSerialInput(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kSonoffBridgeCommands, SonoffBridgeCommand); - break; - case FUNC_INIT: - SnfBridge.receive_raw_flag = 0; - SonoffBridgeSendCommand(0xA7); - break; - case FUNC_PRE_INIT: - SetSerial(19200, TS_SERIAL_8N1); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_07_domoticz.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_07_domoticz.ino" -#ifdef USE_DOMOTICZ - -#define XDRV_07 7 - -#define D_PRFX_DOMOTICZ "Domoticz" -#define D_CMND_IDX "Idx" -#define D_CMND_KEYIDX "KeyIdx" -#define D_CMND_SWITCHIDX "SwitchIdx" -#define D_CMND_SENSORIDX "SensorIdx" -#define D_CMND_UPDATETIMER "UpdateTimer" - -const char kDomoticzCommands[] PROGMEM = D_PRFX_DOMOTICZ "|" - D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ; - -void (* const DomoticzCommand[])(void) PROGMEM = { - &CmndDomoticzIdx, &CmndDomoticzKeyIdx, &CmndDomoticzSwitchIdx, &CmndDomoticzSensorIdx, &CmndDomoticzUpdateTimer }; - -const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}"; - -#if MAX_DOMOTICZ_SNS_IDX < DZ_MAX_SENSORS - #error "Domoticz: Too many sensors or change settings.h layout" -#endif - -const char kDomoticzSensors[] PROGMEM = - D_DOMOTICZ_TEMP "|" D_DOMOTICZ_TEMP_HUM "|" D_DOMOTICZ_TEMP_HUM_BARO "|" D_DOMOTICZ_POWER_ENERGY "|" D_DOMOTICZ_ILLUMINANCE "|" - D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER "|" D_DOMOTICZ_SHUTTER ; - -char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC; - -int domoticz_update_timer = 0; -uint32_t domoticz_fan_debounce = 0; -bool domoticz_subscribe = false; -bool domoticz_update_flag = true; - -#ifdef USE_SHUTTER -bool domoticz_is_shutter = false; -#endif - -int DomoticzBatteryQuality(void) -{ - - - - - int quality = 100; - -#ifdef USE_ADC_VCC - uint16_t voltage = ESP.getVcc(); - if (voltage <= 2600) { - quality = 0; - } else if (voltage >= 4600) { - quality = 200; - } else { - quality = (voltage - 2600) / 10; - } -#endif - return quality; -} - -int DomoticzRssiQuality(void) -{ - - - return WifiGetRssiAsQuality(WiFi.RSSI()) / 10; -} - -#ifdef USE_SONOFF_IFAN -void MqttPublishDomoticzFanState(void) -{ - if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { - char svalue[8]; - - int fan_speed = GetFanspeed(); - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); - Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); - MqttPublish(domoticz_in_topic); - - domoticz_fan_debounce = millis(); - } -} - -void DomoticzUpdateFanState(void) -{ - if (domoticz_update_flag) { - MqttPublishDomoticzFanState(); - } - domoticz_update_flag = true; -} -#endif - -void MqttPublishDomoticzPowerState(uint8_t device) -{ - if (Settings.flag.mqtt_enabled) { - if ((device < 1) || (device > devices_present)) { device = 1; } - if (Settings.domoticz_relay_idx[device -1]) { -#ifdef USE_SHUTTER - if (domoticz_is_shutter) { - - } else { -#endif -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (device > 1)) { - - } else { -#endif - char svalue[8]; - - snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); - Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); - MqttPublish(domoticz_in_topic); -#ifdef USE_SONOFF_IFAN - } -#endif -#ifdef USE_SHUTTER - } -#endif - } - } -} - -void DomoticzUpdatePowerState(uint8_t device) -{ - if (domoticz_update_flag) { - MqttPublishDomoticzPowerState(device); - } - domoticz_update_flag = true; -} - -void DomoticzMqttUpdate(void) -{ - if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) { - domoticz_update_timer--; - if (domoticz_update_timer <= 0) { - domoticz_update_timer = Settings.domoticz_update_timer; - for (uint32_t i = 1; i <= devices_present; i++) { -#ifdef USE_SHUTTER - if (domoticz_is_shutter) - { - - break; - } -#endif -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (i > 1)) { - MqttPublishDomoticzFanState(); - break; - } else { -#endif - MqttPublishDomoticzPowerState(i); -#ifdef USE_SONOFF_IFAN - } -#endif - } - } - } -} - -void DomoticzMqttSubscribe(void) -{ - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (uint32_t i = 0; i < maxdev; i++) { - if (Settings.domoticz_relay_idx[i]) { - domoticz_subscribe = true; - } - } - - if (domoticz_subscribe) { - char stopic[TOPSZ]; - snprintf_P(stopic, sizeof(stopic), PSTR(DOMOTICZ_OUT_TOPIC "/#")); - MqttSubscribe(stopic); - } -} -# 219 "S:/Development/Tasmota/tasmota/xdrv_07_domoticz.ino" -bool DomoticzMqttData(void) -{ - domoticz_update_flag = true; - - if (strncasecmp_P(XdrvMailbox.topic, PSTR(DOMOTICZ_OUT_TOPIC), strlen(DOMOTICZ_OUT_TOPIC)) != 0) { - return false; - } - - - if (XdrvMailbox.data_len < 20) { - return true; - } - StaticJsonBuffer<400> jsonBuf; - JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data); - if (!domoticz.success()) { - return true; - } - - - - uint32_t idx = domoticz["idx"]; - int16_t nvalue = -1; - if (domoticz.containsKey("nvalue")) { - nvalue = domoticz["nvalue"]; - } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue); - - bool found = false; - if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) { - uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present; - for (uint32_t i = 0; i < maxdev; i++) { - if (idx == Settings.domoticz_relay_idx[i]) { - bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0; - bool isShutter = strcmp_P(domoticz["dtype"],PSTR("Light/Switch")) == 0 & strncmp_P(domoticz["switchType"],PSTR("Blinds"), 6) == 0; - - char stemp1[10]; - snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan() && (1 == i)) { - uint8_t svalue = 0; - if (domoticz.containsKey("svalue1")) { - svalue = domoticz["svalue1"]; - } else { - return true; - } - svalue = (nvalue == 2) ? svalue / 10 : 0; - if (GetFanspeed() == svalue) { - return true; - } - if (TimePassedSince(domoticz_fan_debounce) < 1000) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue); - found = true; - } else -#endif -#ifdef USE_SHUTTER - if (isShutter) - { - if (domoticz.containsKey("nvalue")) { - nvalue = domoticz["nvalue"]; - } - - uint8_t position = 0; - if (domoticz.containsKey("svalue1")) { - position = domoticz["svalue1"]; - } - if (nvalue != 2) { - position = nvalue == 0 ? 0 : 100; - } - - snprintf_P(XdrvMailbox.topic, TOPSZ, PSTR("/" D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), position); - XdrvMailbox.data_len = position > 99 ? 3 : (position > 9 ? 2 : 1); - - found = true; - } else -#endif -#ifdef USE_LIGHT - if (iscolordimmer && 10 == nvalue) { - - JsonObject& color = domoticz["Color"]; - uint16_t level = nvalue = domoticz["svalue1"]; - uint16_t r = color["r"]; r = r * level / 100; - uint16_t g = color["g"]; g = g * level / 100; - uint16_t b = color["b"]; b = b * level / 100; - uint16_t cw = color["cw"]; cw = cw * level / 100; - uint16_t ww = color["ww"]; ww = ww * level / 100; - uint16_t m = 0; - uint16_t t = 0; - if (color.containsKey("m")) { - m = color["m"]; - t = color["t"]; - } - if (2 == m) { - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_BACKLOG)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR(D_CMND_COLORTEMPERATURE " %d;" D_CMND_DIMMER " %d"), changeUIntScale(t, 0, 255, CT_MIN, CT_MAX), level); - } else { - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww); - } - found = true; - } - else if ((!iscolordimmer && 2 == nvalue) || - (iscolordimmer && 15 == nvalue)) { - if (domoticz.containsKey("svalue1")) { - nvalue = domoticz["svalue1"]; - } else { - return true; - } - if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER)); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } else -#endif - if (1 == nvalue || 0 == nvalue) { - if (((power >> i) &1) == (power_t)nvalue) { - return true; - } - snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : ""); - snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue); - found = true; - } - break; - } - } - } - if (!found) { return true; } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data); - - domoticz_update_flag = false; - return false; -} - - - -bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg) -{ - bool result = false; - - if (device <= MAX_DOMOTICZ_IDX) { - if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { - Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), - (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off"); - MqttPublish(domoticz_in_topic); - result = true; - } - } - return result; -} -# 393 "S:/Development/Tasmota/tasmota/xdrv_07_domoticz.ino" -uint8_t DomoticzHumidityState(char *hum) -{ - uint8_t h = atoi(hum); - return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1; -} - -void DomoticzSensor(uint8_t idx, char *data) -{ - if (Settings.domoticz_sensor_idx[idx]) { - char dmess[128]; - - memcpy(dmess, mqtt_data, sizeof(dmess)); - if (DZ_AIRQUALITY == idx) { - Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), - Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); - } else { - uint8_t nvalue = 0; -#ifdef USE_SHUTTER - if (DZ_SHUTTER == idx) { - uint8_t position = atoi(data); - nvalue = position < 2 ? 0 : (position == 100 ? 1 : 2); - } -#endif - Response_P(DOMOTICZ_MESSAGE, - Settings.domoticz_sensor_idx[idx], nvalue, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); - } - MqttPublish(domoticz_in_topic); - memcpy(mqtt_data, dmess, sizeof(dmess)); - } -} - -void DomoticzSensor(uint8_t idx, uint32_t value) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%d"), value); - DomoticzSensor(idx, data); -} - -void DomoticzTempHumSensor(char *temp, char *hum) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temp, hum, DomoticzHumidityState(hum)); - DomoticzSensor(DZ_TEMP_HUM, data); -} - -void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro) -{ - char data[32]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temp, hum, DomoticzHumidityState(hum), baro); - DomoticzSensor(DZ_TEMP_HUM_BARO, data); -} - -void DomoticzSensorPowerEnergy(int power, char *energy) -{ - char data[16]; - snprintf_P(data, sizeof(data), PSTR("%d;%s"), power, energy); - DomoticzSensor(DZ_POWER_ENERGY, data); -} - -void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power) -{ - - - - - - int consumed = power; - int produced = 0; - if (power < 0) { - consumed = 0; - produced = -power; - } - char data[64]; - snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced); - DomoticzSensor(DZ_P1_SMART_METER, data); -} - - - - - -void CmndDomoticzIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - restart_flag = 2; - } - ResponseCmndIdxNumber(Settings.domoticz_relay_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzKeyIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_key_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzSwitchIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_switch_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzSensorIdx(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) { - if (XdrvMailbox.payload >= 0) { - Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); - } -} - -void CmndDomoticzUpdateTimer(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { - Settings.domoticz_update_timer = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.domoticz_update_timer); -} - - - - - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_DOMOTICZ "dm" - -const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ; - -const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM = - "

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

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


" - "



" - "

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

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

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

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

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

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

")); - WSContentSend_P(PSTR("

"),"/upl",D_UPL_DONE); - - WSContentStop(); -} - - - -void script_upload(void) { - - - - HTTPUpload& upload = WebServer->upload(); - if (upload.status == UPLOAD_FILE_START) { - char npath[48]; - sprintf(npath,"%s/%s",path,upload.filename.c_str()); - SD.remove(npath); - upload_file=SD.open(npath,FILE_WRITE); - if (!upload_file) Web.upload_error=1; - } else if(upload.status == UPLOAD_FILE_WRITE) { - if (upload_file) upload_file.write(upload.buf,upload.currentSize); - } else if(upload.status == UPLOAD_FILE_END) { - if (upload_file) upload_file.close(); - if (Web.upload_error) { - AddLog_P(LOG_LEVEL_INFO, PSTR("HTP: upload error")); - } - } else { - Web.upload_error=1; - WebServer->send(500, "text/plain", "500: couldn't create file"); - } -} - -uint8_t DownloadFile(char *file) { - File download_file; - WiFiClient download_Client; - - if (!SD.exists(file)) { - AddLog_P(LOG_LEVEL_INFO,PSTR("file not found")); - return 0; - } - - download_file=SD.open(file,FILE_READ); - if (!download_file) { - AddLog_P(LOG_LEVEL_INFO,PSTR("could not open file")); - return 0; - } - - if (download_file.isDirectory()) { - download_file.close(); - return 1; - } - - uint32_t flen=download_file.size(); - - download_Client = WebServer->client(); - WebServer->setContentLength(flen); - - char attachment[100]; - char *cp; - for (uint8_t cnt=strlen(file); cnt>=0; cnt--) { - if (file[cnt]=='/') { - cp=&file[cnt+1]; - break; - } - } - snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=%s"),cp); - WebServer->sendHeader(F("Content-Disposition"), attachment); - WSSend(200, CT_STREAM, ""); - - uint8_t buff[512]; - uint16_t bread; - - - uint8_t cnt=0; - while (download_file.available()) { - bread=download_file.read(buff,sizeof(buff)); - uint16_t bw=download_Client.write((const char*)buff,bread); - if (!bw) break; - cnt++; - if (cnt>7) { - cnt=0; - if (glob_script_mem.script_loglevel&0x80) { - - loop(); - } - } - } - download_file.close(); - download_Client.stop(); - return 0; -} - -#endif - - -void HandleScriptTextareaConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("save")) { - ScriptSaveSettings(); - HandleConfiguration(); - return; - } -} - -void HandleScriptConfiguration(void) { - - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_SCRIPT); - -#ifdef USE_SCRIPT_FATFS - if (WebServer->hasArg("d1")) { - DownloadFile(glob_script_mem.flink[0]); - } - if (WebServer->hasArg("d2")) { - DownloadFile(glob_script_mem.flink[1]); - } - if (WebServer->hasArg("upl")) { - Script_FileUploadConfiguration(); - } -#endif - - WSContentStart_P(S_CONFIGURE_SCRIPT); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_SCRIPT); - - -#ifdef xSCRIPT_STRIP_COMMENTS - uint16_t ssize=glob_script_mem.script_size; - if (bitRead(Settings.rule_enabled, 1)) ssize*=2; - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",ssize); -#else - WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? " checked" : "",glob_script_mem.script_size); -#endif - - - if (glob_script_mem.script_ram[0]) { - _WSContentSend(glob_script_mem.script_ram); - } - WSContentSend_P(HTTP_FORM_SCRIPT1b); - -#ifdef USE_SCRIPT_FATFS - if (glob_script_mem.script_sd_found) { - WSContentSend_P(HTTP_FORM_SCRIPT1d); - if (glob_script_mem.flink[0][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,1,glob_script_mem.flink[0]); - if (glob_script_mem.flink[1][0]) WSContentSend_P(HTTP_FORM_SCRIPT1c,2,glob_script_mem.flink[1]); - } -#endif - - WSContentSend_P(HTTP_SCRIPT_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); - } - - -void ScriptSaveSettings(void) { - - if (WebServer->hasArg("c1")) { - bitWrite(Settings.rule_enabled,0,1); - } else { - bitWrite(Settings.rule_enabled,0,0); - } - - - String str = WebServer->arg("t1"); - - if (*str.c_str()) { - - str.replace("\r\n","\n"); - str.replace("\r","\n"); - -#ifdef xSCRIPT_STRIP_COMMENTS - if (bitRead(Settings.rule_enabled, 1)) { - char *sp=(char*)str.c_str(); - char *sp1=sp; - char *dp=sp; - uint8_t flg=0; - while (*sp) { - while (*sp==' ') sp++; - sp1=sp; - sp=strchr(sp,'\n'); - if (!sp) { - flg=1; - } else { - *sp=0; - } - if (*sp1!=';') { - uint8_t slen=strlen(sp1); - if (slen) { - strcpy(dp,sp1); - dp+=slen; - *dp++='\n'; - } - } - if (flg) { - *dp=0; - break; - } - sp++; - } - } -#endif - - strlcpy(glob_script_mem.script_ram,str.c_str(), glob_script_mem.script_size); - -#ifdef USE_24C256 -#ifndef USE_SCRIPT_FATFS - if (glob_script_mem.flags&1) { - EEP_WRITE(0,EEP_SCRIPT_SIZE,glob_script_mem.script_ram); - } -#endif -#endif - -#ifdef USE_SCRIPT_FATFS - if (glob_script_mem.flags&1) { - SD.remove(FAT_SCRIPT_NAME); - File file=SD.open(FAT_SCRIPT_NAME,FILE_WRITE); - file.write(glob_script_mem.script_ram,FAT_SCRIPT_SIZE); - file.close(); - } -#endif - - } - - if (glob_script_mem.script_mem) { - Scripter_save_pvars(); - free(glob_script_mem.script_mem); - glob_script_mem.script_mem=0; - glob_script_mem.script_mem_size=0; - } - - if (bitRead(Settings.rule_enabled, 0)) { - int16_t res=Init_Scripter(); - if (res) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("script init error: %d"), res); - return; - } - Run_Scripter(">B",2,0); - fast_script=Run_Scripter(">F",-2,0); - } -} - -#endif - - -#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) - - -#define HUE_DEV_MVNUM 5 -#define HUE_DEV_NSIZE 16 -struct HUE_SCRIPT { - char name[HUE_DEV_NSIZE]; - uint8_t type; - uint8_t index[HUE_DEV_MVNUM]; - uint8_t vindex[HUE_DEV_MVNUM]; -} hue_script[32]; - - -const char SCRIPT_HUE_LIGHTS_STATUS_JSON1[] PROGMEM = - "{\"state\":" - "{\"on\":{state}," - "{light_status}" - "\"alert\":\"none\"," - "\"effect\":\"none\"," - "\"reachable\":true}" - ",\"type\":\"{type}\"," - "\"name\":\"{j1\"," - "\"modelid\":\"{m1}\"," - "\"uniqueid\":\"{j2\"," - "\"swversion\":\"5.50.1.19085\"}"; -# 3624 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" -const char SCRIPT_HUE_LIGHTS_STATUS_JSON2[] PROGMEM = -"{\"state\":{" -"\"presence\":{state}," -"\"lastupdated\":\"2017-10-01T12:37:30\"" -"}," -"\"swupdate\":{" -"\"state\":\"noupdates\"," -"\"lastinstall\": null" -"}," -"\"config\":{" -"\"on\":true," -"\"battery\":100," -"\"reachable\":true," -"\"alert\":\"none\"," -"\"ledindication\":false," -"\"usertest\":false," -"\"sensitivity\":2," -"\"sensitivitymax\":2," -"\"pending\":[]" -"}," -"\"name\":\"{j1\"," -"\"type\":\"ZLLPresence\"," -"\"modelid\":\"SML001\"," -"\"manufacturername\":\"Philips\"," -"\"swversion\":\"6.1.0.18912\"," -"\"uniqueid\":\"{j2\"" -"}"; -# 3705 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" -void Script_HueStatus(String *response, uint16_t hue_devs) { - - if (hue_script[hue_devs].type=='p') { - *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON2); - response->replace("{j1",hue_script[hue_devs].name); - response->replace("{j2", GetHueDeviceId(hue_devs)); - uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; - response->replace("{state}", (pwr ? "true" : "false")); - return; - } - - *response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1); - uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1]; - response->replace("{state}", (pwr ? "true" : "false")); - String light_status = ""; - if (hue_script[hue_devs].index[1]>0) { - - light_status += "\"bri\":"; - uint32_t bri=glob_script_mem.fvars[hue_script[hue_devs].index[1]-1]; - if (bri > 254) bri = 254; - if (bri < 1) bri = 1; - light_status += String(bri); - light_status += ","; - } - if (hue_script[hue_devs].index[2]>0) { - - uint32_t hue=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1]; - - light_status += "\"hue\":"; - light_status += String(hue); - light_status += ","; - } - if (hue_script[hue_devs].index[3]>0) { - - uint32_t sat=glob_script_mem.fvars[hue_script[hue_devs].index[3]-1] ; - if (sat > 254) sat = 254; - if (sat < 1) sat = 1; - light_status += "\"sat\":"; - light_status += String(sat); - light_status += ","; - } - if (hue_script[hue_devs].index[4]>0) { - - uint32_t ct=glob_script_mem.fvars[hue_script[hue_devs].index[4]-1]; - light_status += "\"ct\":"; - light_status += String(ct); - light_status += ","; - } - - float temp; - switch (hue_script[hue_devs].type) { - case 'C': - response->replace("{type}","Color Ligh"); - response->replace("{m1","LST001"); - break; - case 'D': - response->replace("{type}","Dimmable Light"); - response->replace("{m1","LWB004"); - break; - case 'T': - response->replace("{type}","Color Temperature Light"); - response->replace("{m1","LTW011"); - break; - case 'E': - response->replace("{type}","Extended color light"); - response->replace("{m1","LCT007"); - break; - case 'S': - response->replace("{type}","On/Off light"); - response->replace("{m1","LCT007"); - break; - default: - response->replace("{type}","color light"); - response->replace("{m1","LST001"); - break; - } - - response->replace("{light_status}", light_status); - response->replace("{j1",hue_script[hue_devs].name); - response->replace("{j2", GetHueDeviceId(hue_devs)); - -} - -void Script_Check_Hue(String *response) { - if (!bitRead(Settings.rule_enabled, 0)) return; - - uint8_t hue_script_found=Run_Scripter(">H",-2,0); - if (hue_script_found!=99) return; - - char line[128]; - char tmp[128]; - uint8_t hue_devs=0; - uint8_t vindex=0; - char *cp; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - SCRIPT_SKIP_SPACES - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - cp=line; - for (uint32_t i=0; i0) *response+=",\""; - } - *response+=String(EncodeLightId(hue_devs+devices_present+1))+"\":"; - Script_HueStatus(response,hue_devs); - } - - hue_devs++; - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } -#if 0 - if (response) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs); - toLog(">>>>"); - toLog(response->c_str()); - toLog(response->c_str()+LOGSZ); - } -#endif -} - -const char sHUE_LIGHT_RESPONSE_JSON[] PROGMEM = - "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; - -const char sHUE_SENSOR_RESPONSE_JSON[] PROGMEM = - "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; - -const char sHUE_ERROR_JSON[] PROGMEM = - "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; - - - -void Script_Handle_Hue(String *path) { - String response; - int code = 200; - uint16_t tmp = 0; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint16_t ct = 0; - bool resp = false; - - uint8_t device = DecodeLightId(atoi(path->c_str())); - uint8_t index = device-devices_present-1; - - if (WebServer->args()) { - response = "["; - - StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); - if (hue_json.containsKey("on")) { - - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "on"); - - bool on = hue_json["on"]; - switch(on) - { - case false : glob_script_mem.fvars[hue_script[index].index[0]-1]=0; - response.replace("{re", "false"); - break; - case true : glob_script_mem.fvars[hue_script[index].index[0]-1]=1; - response.replace("{re", "true"); - break; - } - glob_script_mem.type[hue_script[index].vindex[0]].bits.changed=1; - resp = true; - } - if (hue_json.containsKey("bri")) { - tmp = hue_json["bri"]; - bri=tmp; - if (254 <= bri) { bri = 255; } - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "bri"); - response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[1]-1]=bri; - glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1; - resp = true; - } - if (hue_json.containsKey("xy")) { - float x, y; - x = hue_json["xy"][0]; - y = hue_json["xy"][1]; - const String &x_str = hue_json["xy"][0]; - const String &y_str = hue_json["xy"][1]; - uint8_t rr,gg,bb; - LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); - LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "xy"); - response.replace("{re", "[" + x_str + "," + y_str + "]"); - glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; - glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; - glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; - glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; - resp = true; - } - - if (hue_json.containsKey("hue")) { - tmp = hue_json["hue"]; - - - hue=tmp; - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "hue"); - response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[2]-1]=hue; - glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1; - resp = true; - } - if (hue_json.containsKey("sat")) { - tmp = hue_json["sat"]; - sat=tmp; - if (254 <= sat) { sat = 255; } - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "sat"); - response.replace("{re", String(tmp)); - glob_script_mem.fvars[hue_script[index].index[3]-1]=sat; - glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1; - resp = true; - } - if (hue_json.containsKey("ct")) { - ct = hue_json["ct"]; - if (resp) { response += ","; } - response += FPSTR(sHUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "ct"); - response.replace("{re", String(ct)); - glob_script_mem.fvars[hue_script[index].index[4]-1]=ct; - glob_script_mem.type[hue_script[index].vindex[4]].bits.changed=1; - resp = true; - } - response += "]"; - - } else { - response = FPSTR(sHUE_ERROR_JSON); - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); - WSSend(code, CT_JSON, response); - if (resp) { - Run_Scripter(">E",2,0); - } -} -#endif - - -#ifdef USE_SCRIPT_SUB_COMMAND -bool Script_SubCmd(void) { - if (!bitRead(Settings.rule_enabled, 0)) return false; - - if (tasm_cmd_activ) return false; - - char command[CMDSZ]; - strlcpy(command,XdrvMailbox.topic,CMDSZ); - uint32_t pl=XdrvMailbox.payload; - char pld[64]; - strlcpy(pld,XdrvMailbox.data,sizeof(pld)); - - char cmdbuff[128]; - char *cp=cmdbuff; - *cp++='#'; - strcpy(cp,XdrvMailbox.topic); - uint8_t tlen=strlen(XdrvMailbox.topic); - cp+=tlen; - if (XdrvMailbox.index > 0) { - *cp++=XdrvMailbox.index|0x30; - tlen++; - } - if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) { - *cp++='('; - strncpy(cp,XdrvMailbox.data,XdrvMailbox.data_len); - cp+=XdrvMailbox.data_len; - *cp++=')'; - *cp=0; - } - - uint32_t res=Run_Scripter(cmdbuff,tlen+1,0); - - if (res) return false; - else { - if (pl>=0) { - Response_P(S_JSON_COMMAND_NVALUE, command, pl); - } else { - Response_P(S_JSON_COMMAND_SVALUE, command, pld); - } - } - return true; -} -#endif - -void execute_script(char *script) { - char *svd_sp=glob_script_mem.scriptptr; - strcat(script,"\n#"); - glob_script_mem.scriptptr=script; - Run_Scripter(">",1,0); - glob_script_mem.scriptptr=svd_sp; -} -#define D_CMND_SCRIPT "Script" -#define D_CMND_SUBSCRIBE "Subscribe" -#define D_CMND_UNSUBSCRIBE "Unsubscribe" - -enum ScriptCommands { CMND_SCRIPT,CMND_SUBSCRIBE, CMND_UNSUBSCRIBE }; -const char kScriptCommands[] PROGMEM = D_CMND_SCRIPT "|" D_CMND_SUBSCRIBE "|" D_CMND_UNSUBSCRIBE; - -bool ScriptCommand(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t index = XdrvMailbox.index; - - if (tasm_cmd_activ) return false; - - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kScriptCommands); - if (-1 == command_code) { - serviced = false; - } - else if ((CMND_SCRIPT == command_code) && (index > 0)) { - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { - switch (XdrvMailbox.payload) { - case 0: - case 1: - bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload); - break; -#ifdef xSCRIPT_STRIP_COMMENTS - case 2: - bitWrite(Settings.rule_enabled, 1,0); - break; - case 3: - bitWrite(Settings.rule_enabled, 1,1); - break; -#endif - } - } else { - if ('>' == XdrvMailbox.data[0]) { - - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),command,XdrvMailbox.data); - if (bitRead(Settings.rule_enabled, 0)) { - for (uint8_t count=0; count> 1; -} - -void dateTime(uint16_t* date, uint16_t* time) { - - *date = xFAT_DATE(RtcTime.year,RtcTime.month, RtcTime.day_of_month); - - *time = xFAT_TIME(RtcTime.hour,RtcTime.minute,RtcTime.second); -} - -#endif - - - -#ifdef SUPPORT_MQTT_EVENT -# 4199 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" -bool ScriptMqttData(void) -{ - bool serviced = false; - - toLog(XdrvMailbox.data); - if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) { - return false; - } - String sTopic = XdrvMailbox.topic; - String sData = XdrvMailbox.data; - - MQTT_Subscription event_item; - - for (uint32_t index = 0; index < subscriptions.size(); index++) { - event_item = subscriptions.get(index); - - - if (sTopic.startsWith(event_item.Topic)) { - - serviced = true; - String value; - String lkey; - if (event_item.Key.length() == 0) { - value = sData; - } else { - StaticJsonBuffer<400> jsonBuf; - JsonObject& jsonData = jsonBuf.parseObject(sData); - String key1 = event_item.Key; - String key2; - if (!jsonData.success()) break; - int dot; - if ((dot = key1.indexOf('.')) > 0) { - key2 = key1.substring(dot+1); - key1 = key1.substring(0, dot); - lkey=key2; - if (!jsonData[key1][key2].success()) break; - value = (const char *)jsonData[key1][key2]; - } else { - if (!jsonData[key1].success()) break; - value = (const char *)jsonData[key1]; - lkey=key1; - } - } - value.trim(); - char sbuffer[128]; - - if (!strncmp(lkey.c_str(),"Epoch",5)) { - uint32_t ep=atoi(value.c_str())-(uint32_t)EPOCH_OFFSET; - snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=%d\n"), event_item.Event.c_str(),ep); - } else { - snprintf_P(sbuffer, sizeof(sbuffer), PSTR(">%s=\"%s\"\n"), event_item.Event.c_str(), value.c_str()); - } - - execute_script(sbuffer); - } - } - return serviced; -} -# 4274 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" -String ScriptSubscribe(const char *data, int data_len) -{ - MQTT_Subscription subscription_item; - String events; - if (data_len > 0) { - char parameters[data_len+1]; - memcpy(parameters, data, data_len); - parameters[data_len] = '\0'; - String event_name, topic, key; - - char * pos = strtok(parameters, ","); - if (pos) { - event_name = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - topic = Trim(pos); - pos = strtok(nullptr, ","); - if (pos) { - key = Trim(pos); - } - } - } - - - if (event_name.length() > 0 && topic.length() > 0) { - - for (uint32_t index=0; index < subscriptions.size(); index++) { - if (subscriptions.get(index).Event.equals(event_name)) { - - String stopic = subscriptions.get(index).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(index); - break; - } - } - - if (!topic.endsWith("#")) { - if (topic.endsWith("/")) { - topic.concat("#"); - } else { - topic.concat("/#"); - } - } - - - subscription_item.Event = event_name; - subscription_item.Topic = topic.substring(0, topic.length() - 2); - subscription_item.Key = key; - subscriptions.add(subscription_item); - - MqttSubscribe(topic.c_str()); - events.concat(event_name + "," + topic - + (key.length()>0 ? "," : "") - + key); - } else { - events = D_JSON_WRONG_PARAMETERS; - } - } else { - - for (uint32_t index=0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - events.concat(subscription_item.Event + "," + subscription_item.Topic - + (subscription_item.Key.length()>0 ? "," : "") - + subscription_item.Key + "; "); - } - } - return events; -} -# 4354 "S:/Development/Tasmota/tasmota/xdrv_10_scripter.ino" -String ScriptUnsubscribe(const char * data, int data_len) -{ - MQTT_Subscription subscription_item; - String events; - if (data_len > 0) { - for (uint32_t index = 0; index < subscriptions.size(); index++) { - subscription_item = subscriptions.get(index); - if (subscription_item.Event.equalsIgnoreCase(data)) { - String stopic = subscription_item.Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - events = subscription_item.Event; - subscriptions.remove(index); - break; - } - } - } else { - - String stopic; - while (subscriptions.size() > 0) { - events.concat(subscriptions.get(0).Event + "; "); - stopic = subscriptions.get(0).Topic + "/#"; - MqttUnsubscribe(stopic.c_str()); - subscriptions.remove(0); - } - } - return events; -} -#endif - - - -#ifdef USE_SCRIPT_WEB_DISPLAY - -void Script_Check_HTML_Setvars(void) { - - if (!HttpCheckPriviledgedAccess()) { return; } - - if (WebServer->hasArg("sv")) { - String stmp = WebServer->arg("sv"); - char cmdbuf[64]; - memset(cmdbuf,0,sizeof(cmdbuf)); - char *cp=cmdbuf; - *cp++='>'; - strncpy(cp,stmp.c_str(),sizeof(cmdbuf)-1); - char *cp1=strchr(cp,'_'); - if (!cp1) return; - *cp1=0; - char vname[32]; - strncpy(vname,cp,sizeof(vname)); - *cp1='='; - cp1++; - - struct T_INDEX ind; - uint8_t vtype; - isvar(vname,&vtype,&ind,0,0,0); - if (vtype!=NUM_RES && vtype&STYPE) { - - uint8_t tlen=strlen(cp1); - memmove(cp1+1,cp1,tlen); - *cp1='\"'; - *(cp1+tlen+1)='\"'; - } - - - execute_script(cmdbuf); - Run_Scripter(">E",2,0); - } -} - - -const char SCRIPT_MSG_BUTTONa[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUTTONb[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUT_START[] PROGMEM = - "
"; -const char SCRIPT_MSG_BUT_START_TBL[] PROGMEM = - ""; - -const char SCRIPT_MSG_BUT_STOP[] PROGMEM = - ""; -const char SCRIPT_MSG_BUT_STOP_TBL[] PROGMEM = - "
"; - -const char SCRIPT_MSG_SLIDER[] PROGMEM = - "
%s
%s%s
" - "
"; - -const char SCRIPT_MSG_CHKBOX[] PROGMEM = - "
"; - -const char SCRIPT_MSG_TEXTINP[] PROGMEM = - "
"; - -const char SCRIPT_MSG_NUMINP[] PROGMEM = - "
"; - - -void ScriptGetVarname(char *nbuf,char *sp, uint32_t blen) { -uint32_t cnt; - for (cnt=0;cntW",-2,0); - if (web_script==99) { - char line[128]; - char tmp[128]; - uint8_t optflg=0; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; i0) { - cp="checked='checked'"; - uval=0; - } else { - cp=""; - uval=1; - } - WSContentSend_PD(SCRIPT_MSG_CHKBOX,label,(char*)cp,uval,vname); - - } else if (!strncmp(lin,"bu(",3)) { - char *lp=lin+3; - uint8_t bcnt=0; - char *found=lin; - while (bcnt<4) { - found=strstr(found,"bu("); - if (!found) break; - found+=3; - bcnt++; - } - uint8_t proz=100/bcnt; - if (!optflg && bcnt>1) proz-=2; - if (optflg) WSContentSend_PD(SCRIPT_MSG_BUT_START_TBL); - else WSContentSend_PD(SCRIPT_MSG_BUT_START); - for (uint32_t cnt=0;cnt0) { - cp=ontxt; - uval=0; - } else { - cp=offtxt; - uval=1; - } - if (bcnt>1 && cnt==bcnt-1) { - if (!optflg) proz+=2; - } - if (!optflg) { - WSContentSend_PD(SCRIPT_MSG_BUTTONa,proz,uval,vname,cp); - } else { - WSContentSend_PD(SCRIPT_MSG_BUTTONa_TBL,proz,uval,vname,cp); - } - if (bcnt>1 && cnt%s
"),tmp); - } else { - WSContentSend_PD(PSTR("{s}%s{e}"),tmp); - } - } - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - } -} -#endif - - -#ifdef USE_SENDMAIL -void script_send_email_body(BearSSL::WiFiClientSecure_light *client) { -uint8_t msect=Run_Scripter(">m",-2,0); - if (msect==99) { - char line[128]; - char tmp[128]; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; iprintln(tmp); - } - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - } else { - client->println("*"); - } -} -#endif - -#ifdef USE_SCRIPT_JSON_EXPORT -void ScriptJsonAppend(void) { - uint8_t web_script=Run_Scripter(">J",-2,0); - if (web_script==99) { - char line[128]; - char tmp[128]; - char *lp=glob_script_mem.section_ptr+2; - while (lp) { - while (*lp==SCRIPT_EOL) { - lp++; - } - if (!*lp || *lp=='#' || *lp=='>') { - break; - } - if (*lp!=';') { - - memcpy(line,lp,sizeof(line)); - line[sizeof(line)-1]=0; - char *cp=line; - for (uint32_t i=0; iB",2,0); - fast_script=Run_Scripter(">F",-2,0); -#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) - Script_Check_Hue(0); -#endif - } - break; - case FUNC_EVERY_100_MSECOND: - ScripterEvery100ms(); - break; - case FUNC_EVERY_SECOND: - ScriptEverySecond(); - break; - case FUNC_COMMAND: - result = ScriptCommand(); - break; - case FUNC_SET_POWER: -#ifdef SCRIPT_POWER_SECTION - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P",2,0); -#else - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,0); -#endif - break; - case FUNC_RULES_PROCESS: - if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E",2,mqtt_data); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_RULES); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_SCRIPT, HandleScriptConfiguration); - WebServer->on("/ta",HTTP_POST, HandleScriptTextareaConfiguration); - -#ifdef USE_SCRIPT_FATFS - WebServer->on("/u3", HTTP_POST,[]() { WebServer->sendHeader("Location","/u3");WebServer->send(303);},script_upload); - WebServer->on("/u3", HTTP_GET,ScriptFileUploadSuccess); - WebServer->on("/upl", HTTP_GET,Script_FileUploadConfiguration); -#endif - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - if (bitRead(Settings.rule_enabled, 0)) { - Run_Scripter(">R",2,0); - Scripter_save_pvars(); - } - break; -#ifdef SUPPORT_MQTT_EVENT - case FUNC_MQTT_DATA: - if (bitRead(Settings.rule_enabled, 0)) { - result = ScriptMqttData(); - } - break; -#endif -#ifdef USE_SCRIPT_WEB_DISPLAY - case FUNC_WEB_SENSOR: - if (bitRead(Settings.rule_enabled, 0)) { - ScriptWebShow(); - } - break; -#endif - -#ifdef USE_SCRIPT_JSON_EXPORT - case FUNC_JSON_APPEND: - if (bitRead(Settings.rule_enabled, 0)) { - ScriptJsonAppend(); - } - break; -#endif - -#ifdef USE_BUTTON_EVENT - case FUNC_BUTTON_PRESSED: - if (bitRead(Settings.rule_enabled, 0)) { - if ((script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) { - script_button[XdrvMailbox.index]=XdrvMailbox.payload; - Run_Scripter(">b",2,0); - } - } - break; -#endif - - } - return result; -} - - - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" -#ifdef USE_KNX -# 51 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" -#define XDRV_11 11 - -#include - -address_t KNX_physs_addr; -address_t KNX_addr; - -#define KNX_Empty 255 - -#define TOGGLE_INHIBIT_TIME 15 - -float last_temp; -float last_hum; -uint8_t toggle_inhibit; - -typedef struct __device_parameters -{ - uint8_t type; - - - - - bool show; - - bool last_state; - - callback_id_t CB_id; - - - - - -} device_parameters_t; - - -device_parameters_t device_param[] = { - { 1, false, false, KNX_Empty }, - { 2, false, false, KNX_Empty }, - { 3, false, false, KNX_Empty }, - { 4, false, false, KNX_Empty }, - { 5, false, false, KNX_Empty }, - { 6, false, false, KNX_Empty }, - { 7, false, false, KNX_Empty }, - { 8, false, false, KNX_Empty }, - { 9, false, false, KNX_Empty }, - { 10, false, false, KNX_Empty }, - { 11, false, false, KNX_Empty }, - { 12, false, false, KNX_Empty }, - { 13, false, false, KNX_Empty }, - { 14, false, false, KNX_Empty }, - { 15, false, false, KNX_Empty }, - { 16, false, false, KNX_Empty }, - { KNX_TEMPERATURE, false, false, KNX_Empty }, - { KNX_HUMIDITY , false, false, KNX_Empty }, - { KNX_ENERGY_VOLTAGE , false, false, KNX_Empty }, - { KNX_ENERGY_CURRENT , false, false, KNX_Empty }, - { KNX_ENERGY_POWER , false, false, KNX_Empty }, - { KNX_ENERGY_POWERFACTOR , false, false, KNX_Empty }, - { KNX_ENERGY_DAILY , false, false, KNX_Empty }, - { KNX_ENERGY_START , false, false, KNX_Empty }, - { KNX_ENERGY_TOTAL , false, false, KNX_Empty }, - { KNX_SLOT1 , false, false, KNX_Empty }, - { KNX_SLOT2 , false, false, KNX_Empty }, - { KNX_SLOT3 , false, false, KNX_Empty }, - { KNX_SLOT4 , false, false, KNX_Empty }, - { KNX_SLOT5 , false, false, KNX_Empty }, - { KNX_Empty, false, false, KNX_Empty} -}; - - -const char * device_param_ga[] = { - D_TIMER_OUTPUT " 1", - D_TIMER_OUTPUT " 2", - D_TIMER_OUTPUT " 3", - D_TIMER_OUTPUT " 4", - D_TIMER_OUTPUT " 5", - D_TIMER_OUTPUT " 6", - D_TIMER_OUTPUT " 7", - D_TIMER_OUTPUT " 8", - D_SENSOR_BUTTON " 1", - D_SENSOR_BUTTON " 2", - D_SENSOR_BUTTON " 3", - D_SENSOR_BUTTON " 4", - D_SENSOR_BUTTON " 5", - D_SENSOR_BUTTON " 6", - D_SENSOR_BUTTON " 7", - D_SENSOR_BUTTON " 8", - D_TEMPERATURE , - D_HUMIDITY , - D_VOLTAGE , - D_CURRENT , - D_POWERUSAGE , - D_POWER_FACTOR , - D_ENERGY_TODAY , - D_ENERGY_YESTERDAY , - D_ENERGY_TOTAL , - D_KNX_TX_SLOT " 1", - D_KNX_TX_SLOT " 2", - D_KNX_TX_SLOT " 3", - D_KNX_TX_SLOT " 4", - D_KNX_TX_SLOT " 5", - nullptr -}; - - -const char *device_param_cb[] = { - D_TIMER_OUTPUT " 1", - D_TIMER_OUTPUT " 2", - D_TIMER_OUTPUT " 3", - D_TIMER_OUTPUT " 4", - D_TIMER_OUTPUT " 5", - D_TIMER_OUTPUT " 6", - D_TIMER_OUTPUT " 7", - D_TIMER_OUTPUT " 8", - D_TIMER_OUTPUT " 1 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 2 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 3 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 4 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 5 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 6 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 7 " D_BUTTON_TOGGLE, - D_TIMER_OUTPUT " 8 " D_BUTTON_TOGGLE, - D_REPLY " " D_TEMPERATURE, - D_REPLY " " D_HUMIDITY, - D_REPLY " " D_VOLTAGE , - D_REPLY " " D_CURRENT , - D_REPLY " " D_POWERUSAGE , - D_REPLY " " D_POWER_FACTOR , - D_REPLY " " D_ENERGY_TODAY , - D_REPLY " " D_ENERGY_YESTERDAY , - D_REPLY " " D_ENERGY_TOTAL , - D_KNX_RX_SLOT " 1", - D_KNX_RX_SLOT " 2", - D_KNX_RX_SLOT " 3", - D_KNX_RX_SLOT " 4", - D_KNX_RX_SLOT " 5", - nullptr -}; - - -#define D_PRFX_KNX "Knx" -#define D_CMND_KNXTXCMND "Tx_Cmnd" -#define D_CMND_KNXTXVAL "Tx_Val" -#define D_CMND_KNX_ENABLED "_Enabled" -#define D_CMND_KNX_ENHANCED "_Enhanced" -#define D_CMND_KNX_PA "_PA" -#define D_CMND_KNX_GA "_GA" -#define D_CMND_KNX_CB "_CB" - -const char kKnxCommands[] PROGMEM = D_PRFX_KNX "|" - D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ; - -void (* const KnxCommand[])(void) PROGMEM = { - &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb }; - -uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 ) -{ - for (uint32_t i = start; i < Settings.knx_GA_registered; ++i) - { - if ( Settings.knx_GA_param[i] == param ) - { - if ( Settings.knx_GA_addr[i] != 0 ) - { - if ( i >= start ) { return i; } - } - } - } - return KNX_Empty; -} - - -uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 ) -{ - for (uint32_t i = start; i < Settings.knx_CB_registered; ++i) - { - if ( Settings.knx_CB_param[i] == param ) - { - if ( Settings.knx_CB_addr[i] != 0 ) - { - if ( i >= start ) { return i; } - } - } - } - return KNX_Empty; -} - - -void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF ) -{ - - if ( Settings.knx_GA_registered >= MAX_KNX_GA ) { return; } - if ( GA_FNUM == 0 && GA_AREA == 0 && GA_FDEF == 0 ) { return; } - - - Settings.knx_GA_param[Settings.knx_GA_registered] = GAop; - KNX_addr.ga.area = GA_FNUM; - KNX_addr.ga.line = GA_AREA; - KNX_addr.ga.member = GA_FDEF; - Settings.knx_GA_addr[Settings.knx_GA_registered] = KNX_addr.value; - - Settings.knx_GA_registered++; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"), - Settings.knx_GA_registered, - device_param_ga[GAop-1], - GA_FNUM, GA_AREA, GA_FDEF ); -} - - -void KNX_DEL_GA( uint8_t GAnum ) -{ - - uint8_t dest_offset = 0; - uint8_t src_offset = 0; - uint8_t len = 0; - - - Settings.knx_GA_param[GAnum-1] = 0; - - if (GAnum == 1) - { - - src_offset = 1; - - - - len = (Settings.knx_GA_registered - 1); - } - else if (GAnum == Settings.knx_GA_registered) - { - - } - else - { - - - - - dest_offset = GAnum -1 ; - src_offset = dest_offset + 1; - len = (Settings.knx_GA_registered - GAnum); - } - - if (len > 0) - { - memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(uint8_t)); - memmove(Settings.knx_GA_addr + dest_offset, Settings.knx_GA_addr + src_offset, len * sizeof(uint16_t)); - } - - Settings.knx_GA_registered--; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " GA #%d"), - GAnum ); -} - - -void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF ) -{ - - if ( Settings.knx_CB_registered >= MAX_KNX_CB ) { return; } - if ( CB_FNUM == 0 && CB_AREA == 0 && CB_FDEF == 0 ) { return; } - - - if ( device_param[CBop-1].CB_id == KNX_Empty ) - { - - device_param[CBop-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[CBop-1]); - - - - - } - - Settings.knx_CB_param[Settings.knx_CB_registered] = CBop; - KNX_addr.ga.area = CB_FNUM; - KNX_addr.ga.line = CB_AREA; - KNX_addr.ga.member = CB_FDEF; - Settings.knx_CB_addr[Settings.knx_CB_registered] = KNX_addr.value; - - knx.callback_assign( device_param[CBop-1].CB_id, KNX_addr ); - - Settings.knx_CB_registered++; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"), - Settings.knx_CB_registered, - CB_FNUM, CB_AREA, CB_FDEF, - device_param_cb[CBop-1] ); -} - - -void KNX_DEL_CB( uint8_t CBnum ) -{ - uint8_t oldparam = Settings.knx_CB_param[CBnum-1]; - uint8_t dest_offset = 0; - uint8_t src_offset = 0; - uint8_t len = 0; - - - knx.callback_unassign(CBnum-1); - Settings.knx_CB_param[CBnum-1] = 0; - - if (CBnum == 1) - { - - src_offset = 1; - - - - len = (Settings.knx_CB_registered - 1); - } - else if (CBnum == Settings.knx_CB_registered) - { - - } - else - { - - - - - dest_offset = CBnum -1 ; - src_offset = dest_offset + 1; - len = (Settings.knx_CB_registered - CBnum); - } - - if (len > 0) - { - memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(uint8_t)); - memmove(Settings.knx_CB_addr + dest_offset, Settings.knx_CB_addr + src_offset, len * sizeof(uint16_t)); - } - - Settings.knx_CB_registered--; - - - if ( KNX_CB_Search( oldparam ) == KNX_Empty ) { - knx.callback_deregister( device_param[oldparam-1].CB_id ); - device_param[oldparam-1].CB_id = KNX_Empty; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " CB #%d"), CBnum ); -} - - -bool KNX_CONFIG_NOT_MATCH(void) -{ - - for (uint32_t i = 0; i < KNX_MAX_device_param; ++i) - { - if ( !device_param[i].show ) { - - - - if ( KNX_GA_Search(i+1) != KNX_Empty ) { return true; } - - if ( i < 8 ) - { - if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } - if ( KNX_CB_Search(i+9) != KNX_Empty ) { return true; } - } - - if ( i > 15 ) - { - if ( KNX_CB_Search(i+1) != KNX_Empty ) { return true; } - } - } - } - - - for (uint32_t i = 0; i < Settings.knx_GA_registered; ++i) - { - if ( Settings.knx_GA_param[i] != 0 ) - { - if ( Settings.knx_GA_addr[i] == 0 ) - { - return true; - } - } - } - for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) - { - if ( Settings.knx_CB_param[i] != 0 ) - { - if ( Settings.knx_CB_addr[i] == 0 ) - { - return true; - } - } - } - - return false; -} - - -void KNXStart(void) -{ - knx.start(nullptr); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_START)); -} - - -void KNX_INIT(void) -{ - - if (Settings.knx_GA_registered > MAX_KNX_GA) { Settings.knx_GA_registered = MAX_KNX_GA; } - if (Settings.knx_CB_registered > MAX_KNX_CB) { Settings.knx_CB_registered = MAX_KNX_CB; } - - - KNX_physs_addr.value = Settings.knx_physsical_addr; - knx.physical_address_set( KNX_physs_addr ); -# 472 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" - for (uint32_t i = 0; i < devices_present; ++i) - { - device_param[i].show = true; - } - for (uint32_t i = GPIO_SWT1; i < GPIO_SWT4 + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1 + 8].show = true; } - } - for (uint32_t i = GPIO_KEY1; i < GPIO_KEY4 + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1 + 8].show = true; } - } - for (uint32_t i = GPIO_SWT1_NP; i < GPIO_SWT4_NP + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_SWT1_NP + 8].show = true; } - } - for (uint32_t i = GPIO_KEY1_NP; i < GPIO_KEY4_NP + 1; ++i) - { - if (GetUsedInModule(i, my_module.io)) { device_param[i - GPIO_KEY1_NP + 8].show = true; } - } - if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } -#ifdef USE_DS18x20 - if (GetUsedInModule(GPIO_DSB, my_module.io)) { device_param[KNX_TEMPERATURE-1].show = true; } -#endif - if (GetUsedInModule(GPIO_DHT11, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_DHT22, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - if (GetUsedInModule(GPIO_SI7021, my_module.io)) { device_param[KNX_HUMIDITY-1].show = true; } - -#if defined(USE_ENERGY_SENSOR) - - if ( energy_flg != ENERGY_NONE ) { - device_param[KNX_ENERGY_POWER-1].show = true; - device_param[KNX_ENERGY_DAILY-1].show = true; - device_param[KNX_ENERGY_START-1].show = true; - device_param[KNX_ENERGY_TOTAL-1].show = true; - device_param[KNX_ENERGY_VOLTAGE-1].show = true; - device_param[KNX_ENERGY_CURRENT-1].show = true; - device_param[KNX_ENERGY_POWERFACTOR-1].show = true; - } -#endif - -#ifdef USE_RULES - device_param[KNX_SLOT1-1].show = true; - device_param[KNX_SLOT2-1].show = true; - device_param[KNX_SLOT3-1].show = true; - device_param[KNX_SLOT4-1].show = true; - device_param[KNX_SLOT5-1].show = true; -#endif - - - if (KNX_CONFIG_NOT_MATCH()) { - Settings.knx_GA_registered = 0; - Settings.knx_CB_registered = 0; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS)); - } - - - - - uint8_t j; - for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i) - { - j = Settings.knx_CB_param[i]; - if ( j > 0 ) - { - device_param[j-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[j-1]); - - - - KNX_addr.value = Settings.knx_CB_addr[i]; - knx.callback_assign( device_param[j-1].CB_id, KNX_addr ); - } - } -} - - -void KNX_CB_Action(message_t const &msg, void *arg) -{ - device_parameters_t *chan = (device_parameters_t *)arg; - if (!(Settings.flag.knx_enabled)) { return; } - - char tempchar[33]; - - if (msg.data_len == 1) { - - tempchar[0] = msg.data[0]; - tempchar[1] = '\0'; - } else { - - float tempvar = knx.data_to_2byte_float(msg.data); - dtostrfd(tempvar,2,tempchar); - } - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"), - msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member, - (msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER, - tempchar, - device_param_cb[(chan->type)-1]); - - switch (msg.ct) - { - case KNX_CT_WRITE: - if (chan->type < 9) - { - ExecuteCommandPower(chan->type, msg.data[0], SRC_KNX); - } - else if (chan->type < 17) - { - if (!toggle_inhibit) { - ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#ifdef USE_RULES - else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) - { - if (!toggle_inhibit) { - char command[25]; - if (msg.data_len == 1) { - - snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]); - } else { - - snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar); - } - ExecuteCommand(command, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#endif - break; - - case KNX_CT_READ: - if (chan->type < 9) - { - knx.answer_1bit(msg.received_on, chan->last_state); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_1bit(msg.received_on, chan->last_state); - knx.answer_1bit(msg.received_on, chan->last_state); - } - } - else if (chan->type == KNX_TEMPERATURE) - { - knx.answer_2byte_float(msg.received_on, last_temp); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_2byte_float(msg.received_on, last_temp); - knx.answer_2byte_float(msg.received_on, last_temp); - } - } - else if (chan->type == KNX_HUMIDITY) - { - knx.answer_2byte_float(msg.received_on, last_hum); - if (Settings.flag.knx_enable_enhancement) { - knx.answer_2byte_float(msg.received_on, last_hum); - knx.answer_2byte_float(msg.received_on, last_hum); - } - } -#ifdef USE_RULES - else if ((chan->type >= KNX_SLOT1) && (chan->type <= KNX_SLOT5)) - { - if (!toggle_inhibit) { - char command[25]; - snprintf_P(command, sizeof(command), PSTR("event KNXRX_REQ%d"), ((chan->type) - KNX_SLOT1 + 1 ) ); - ExecuteCommand(command, SRC_KNX); - if (Settings.flag.knx_enable_enhancement) { - toggle_inhibit = TOGGLE_INHIBIT_TIME; - } - } - } -#endif - break; - } -} - - -void KnxUpdatePowerState(uint8_t device, power_t state) -{ - if (!(Settings.flag.knx_enabled)) { return; } - - device_param[device -1].last_state = bitRead(state, device -1); - - - uint8_t i = KNX_GA_Search(device); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - knx.write_1bit(KNX_addr, device_param[device -1].last_state); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[device -1], device_param[device -1].last_state, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(device, i + 1); - } -} - - -void KnxSendButtonPower(void) -{ - if (!(Settings.flag.knx_enabled)) { return; } - - uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; - uint32_t device = XdrvMailbox.payload & 0xFF; - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; -# 693 "S:/Development/Tasmota/tasmota/xdrv_11_knx.ino" - uint8_t i = KNX_GA_Search(device + 8); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, !(state == 0)); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, !(state == 0)); - knx.write_1bit(KNX_addr, !(state == 0)); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[device + 7], !(state == 0), - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(device + 8, i + 1); - } - -} - - -void KnxSensor(uint8_t sensor_type, float value) -{ - if (sensor_type == KNX_TEMPERATURE) - { - last_temp = value; - } else if (sensor_type == KNX_HUMIDITY) - { - last_hum = value; - } - - if (!(Settings.flag.knx_enabled)) { return; } - - uint8_t i = KNX_GA_Search(sensor_type); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_2byte_float(KNX_addr, value); - if (Settings.flag.knx_enable_enhancement) { - knx.write_2byte_float(KNX_addr, value); - knx.write_2byte_float(KNX_addr, value); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "), - device_param_ga[sensor_type -1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(sensor_type, i+1); - } -} - - - - - - -#ifdef USE_WEBSERVER -#ifdef USE_KNX_WEB_MENU -const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX; - -const char HTTP_BTN_MENU_KNX[] PROGMEM = - "

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

" D_KNX_PHYSICAL_ADDRESS_NOTE "

" - "" D_KNX_ENABLE "" D_KNX_ENHANCEMENT "

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

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

" - "
" - "" D_KNX_GROUP_ADDRESS_TO_READ "
"; - -const char HTTP_FORM_KNX4[] PROGMEM = - "-> -> ")); - WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_AREA", "GA_FDEF"); - WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1); - for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) - { - if ( Settings.knx_GA_param[i] ) - { - KNX_addr.value = Settings.knx_GA_addr[i]; - WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1); - } - } - - WSContentSend_P(HTTP_FORM_KNX3); - WSContentSend_P(HTTP_FORM_KNX_GA, "CB_FNUM", "CB_AREA", "CB_FDEF"); - WSContentSend_P(HTTP_FORM_KNX4); - - uint8_t j; - for (uint32_t i = 0; i < KNX_MAX_device_param ; i++) - { - - if ( (i > 8) && (i < 16) ) { j=i-8; } else { j=i; } - if ( i == 8 ) { j = 0; } - if ( device_param[j].show ) - { - WSContentSend_P(HTTP_FORM_KNX_OPT, device_param[i].type, device_param_cb[i]); - } - } - WSContentSend_P(PSTR(" ")); - WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2); - - for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) - { - if ( Settings.knx_CB_param[i] ) - { - KNX_addr.value = Settings.knx_CB_addr[i]; - WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1); - } - } - WSContentSend_P(PSTR("
")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); - } - -} - - -void KNX_Save_Settings(void) -{ - String stmp; - address_t KNX_addr; - - Settings.flag.knx_enabled = WebServer->hasArg("b1"); - Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2"); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"), - Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement ); - - stmp = WebServer->arg("area"); - KNX_addr.pa.area = stmp.toInt(); - stmp = WebServer->arg("line"); - KNX_addr.pa.line = stmp.toInt(); - stmp = WebServer->arg("member"); - KNX_addr.pa.member = stmp.toInt(); - Settings.knx_physsical_addr = KNX_addr.value; - knx.physical_address_set( KNX_addr ); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "), - KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA: %d"), - Settings.knx_GA_registered ); - for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i) - { - KNX_addr.value = Settings.knx_GA_addr[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"), - i+1, device_param_ga[Settings.knx_GA_param[i]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB: %d"), - Settings.knx_CB_registered ); - for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i) - { - KNX_addr.value = Settings.knx_CB_addr[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"), - i+1, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, - device_param_cb[Settings.knx_CB_param[i]-1] ); - } -} - -#endif -#endif - - - - - -void CmndKnxTxCmnd(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { - - - - uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - if (Settings.flag.knx_enable_enhancement) { - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0)); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"), - device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], !(XdrvMailbox.payload == 0), - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); - } - ResponseCmndIdxChar (XdrvMailbox.data ); - } -} - -void CmndKnxTxVal(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) { - - - - uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1); - while ( i != KNX_Empty ) { - KNX_addr.value = Settings.knx_GA_addr[i]; - - float tempvar = CharToFloat(XdrvMailbox.data); - dtostrfd(tempvar,2,XdrvMailbox.data); - - knx.write_2byte_float(KNX_addr, tempvar); - if (Settings.flag.knx_enable_enhancement) { - knx.write_2byte_float(KNX_addr, tempvar); - knx.write_2byte_float(KNX_addr, tempvar); - } - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"), - device_param_ga[XdrvMailbox.index + KNX_SLOT1 -2], XdrvMailbox.data, - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member); - - i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1, i + 1); - } - ResponseCmndIdxChar (XdrvMailbox.data ); - } -} - -void CmndKnxEnabled(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag.knx_enabled = XdrvMailbox.payload; - } - ResponseCmndChar (GetStateText(Settings.flag.knx_enabled) ); -} - -void CmndKnxEnhanced(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { - Settings.flag.knx_enable_enhancement = XdrvMailbox.payload; - } - ResponseCmndChar (GetStateText(Settings.flag.knx_enable_enhancement) ); -} - -void CmndKnxPa(void) -{ - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ".") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); - int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2)); - int pa_member = atoi(subStr(sub_string, XdrvMailbox.data, ".", 3)); - - if ( ((pa_area == 0) && (pa_line == 0) && (pa_member == 0)) - || (pa_area > 15) || (pa_line > 15) || (pa_member > 255) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.pa.area = pa_area; - KNX_addr.pa.line = pa_line; - KNX_addr.pa.member = pa_member; - Settings.knx_physsical_addr = KNX_addr.value; - } - } - KNX_addr.value = Settings.knx_physsical_addr; - Response_P (PSTR("{\"%s\":\"%d.%d.%d\"}"), - XdrvMailbox.command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member ); -} - -void CmndKnxGa(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_GA)) { - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - int ga_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - int ga_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - - if ( ((ga_area == 0) && (ga_line == 0) && (ga_member == 0)) - || (ga_area > 31) || (ga_line > 7) || (ga_member > 255) - || (ga_option < 0) || ((ga_option > KNX_MAX_device_param ) && (ga_option != KNX_Empty)) - || (!device_param[ga_option-1].show) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.ga.area = ga_area; - KNX_addr.ga.line = ga_line; - KNX_addr.ga.member = ga_member; - - if ( XdrvMailbox.index > Settings.knx_GA_registered ) { - Settings.knx_GA_registered ++; - XdrvMailbox.index = Settings.knx_GA_registered; - } - - Settings.knx_GA_addr[XdrvMailbox.index -1] = KNX_addr.value; - Settings.knx_GA_param[XdrvMailbox.index -1] = ga_option; - } else { - if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) { - XdrvMailbox.index = XdrvMailbox.payload; - } else { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - } - if ( XdrvMailbox.index <= Settings.knx_GA_registered ) { - KNX_addr.value = Settings.knx_GA_addr[XdrvMailbox.index -1]; - Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), - XdrvMailbox.command, XdrvMailbox.index, device_param_ga[Settings.knx_GA_param[XdrvMailbox.index-1]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - } - } else { - ResponseCmndNumber (Settings.knx_GA_registered ); - } - } -} - -void CmndKnxCb(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNX_CB)) { - if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len]; - - int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - int cb_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - int cb_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - - if ( ((cb_area == 0) && (cb_line == 0) && (cb_member == 0)) - || (cb_area > 31) || (cb_line > 7) || (cb_member > 255) - || (cb_option < 0) || ((cb_option > KNX_MAX_device_param ) && (cb_option != KNX_Empty)) - || (!device_param[cb_option-1].show) ) { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - - KNX_addr.ga.area = cb_area; - KNX_addr.ga.line = cb_line; - KNX_addr.ga.member = cb_member; - - if ( XdrvMailbox.index > Settings.knx_CB_registered ) { - Settings.knx_CB_registered ++; - XdrvMailbox.index = Settings.knx_CB_registered; - } - - Settings.knx_CB_addr[XdrvMailbox.index -1] = KNX_addr.value; - Settings.knx_CB_param[XdrvMailbox.index -1] = cb_option; - } else { - if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) { - XdrvMailbox.index = XdrvMailbox.payload; - } else { - Response_P (PSTR("{\"%s\":\"" D_ERROR "\"}"), XdrvMailbox.command ); - return; - } - } - if ( XdrvMailbox.index <= Settings.knx_CB_registered ) { - KNX_addr.value = Settings.knx_CB_addr[XdrvMailbox.index -1]; - Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"), - XdrvMailbox.command, XdrvMailbox.index, device_param_cb[Settings.knx_CB_param[XdrvMailbox.index-1]-1], - KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member ); - } - } else { - ResponseCmndNumber (Settings.knx_CB_registered ); - } - } -} - - - - - -bool Xdrv11(uint8_t function) -{ - bool result = false; - switch (function) { - case FUNC_LOOP: - if (!global_state.wifi_down) { knx.loop(); } - break; - case FUNC_EVERY_50_MSECOND: - if (toggle_inhibit) { - toggle_inhibit--; - } - break; - case FUNC_ANY_KEY: - KnxSendButtonPower(); - break; -#ifdef USE_WEBSERVER -#ifdef USE_KNX_WEB_MENU - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_KNX); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/kn", HandleKNXConfiguration); - break; -#endif -#endif - case FUNC_COMMAND: - result = DecodeCommand(kKnxCommands, KnxCommand); - break; - case FUNC_PRE_INIT: - KNX_INIT(); - break; - - - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_12_home_assistant.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_12_home_assistant.ino" -#ifdef USE_HOME_ASSISTANT - -#define XDRV_12 12 - - -const char kHAssJsonSensorTypes[] PROGMEM = - D_JSON_TEMPERATURE "|" D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" - D_JSON_APPARENT_POWERUSAGE "|Battery|" D_JSON_CURRENT "|" D_JSON_DISTANCE "|" D_JSON_FREQUENCY "|" D_JSON_HUMIDITY "|" D_JSON_ILLUMINANCE "|" - D_JSON_MOISTURE "|PB0.3|PB0.5|PB1|PB2.5|PB5|PB10|PM1|PM2.5|PM10|" D_JSON_POWERFACTOR "|" D_JSON_POWERUSAGE "|" - D_JSON_REACTIVE_POWERUSAGE "|" D_JSON_TODAY "|" D_JSON_TOTAL "|" D_JSON_VOLTAGE "|" D_JSON_WEIGHT "|" D_JSON_YESTERDAY; -const char kHAssJsonSensorUnits[] PROGMEM = - "|||" - "W|%|A|Cm|Hz|%|LX|" - "%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³||W|" - "W|KWh|KWh|V|Kg|KWh"; -const char kHAssJsonSensorDevCla[] PROGMEM = - "dev_cla\":\"temperature|dev_cla\":\"pressure|dev_cla\":\"pressure|" - "dev_cla\":\"power|dev_cla\":\"battery|ic\":\"mdi:alpha-a-circle-outline|ic\":\"mdi:leak|ic\":\"mdi:current-ac|dev_cla\":\"humidity|dev_cla\":\"illuminance|" - "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" - "ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|" - "dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power"; - - -const char HASS_DISCOVER_SENSOR[] PROGMEM = - ",\"unit_of_meas\":\"%s\",\"%s\"," - "\"frc_upd\":true," - "\"val_tpl\":\"{{value_json['%s']['%s']"; - -const char HASS_DISCOVER_BASE[] PROGMEM = - "{\"name\":\"%s\"," - "\"stat_t\":\"%s\"," - "\"avty_t\":\"%s\"," - "\"pl_avail\":\"" D_ONLINE "\"," - "\"pl_not_avail\":\"" D_OFFLINE "\""; - -const char HASS_DISCOVER_RELAY[] PROGMEM = - ",\"cmd_t\":\"%s\"," - "\"val_tpl\":\"{{value_json.%s}}\"," - "\"pl_off\":\"%s\"," - "\"pl_on\":\"%s\""; - -const char HASS_DISCOVER_BUTTON_TOGGLE[] PROGMEM = - ",\"value_template\":\"{%%if is_state(entity_id,\\\"off\\\")-%%}ON{%%-endif%%}\"," - "\"off_delay\":1"; - -const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = - ",\"value_template\":\"{{value_json.%s}}\"," - "\"frc_upd\":true," - "\"pl_on\":\"%s\"," - "\"pl_off\":\"%s\""; - -const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = - ",\"bri_cmd_t\":\"%s\"," - "\"bri_stat_t\":\"%s\"," - "\"bri_scl\":100," - "\"on_cmd_type\":\"%s\"," - "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; - -const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = - ",\"rgb_cmd_t\":\"%s2\"," - "\"rgb_stat_t\":\"%s\"," - "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; - -const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = - ",\"whit_val_cmd_t\":\"%s\"," - "\"whit_val_stat_t\":\"%s\"," - "\"white_value_scale\":100," - "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; - -const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = - ",\"clr_temp_cmd_t\":\"%s\"," - "\"clr_temp_stat_t\":\"%s\"," - "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; - -const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = - ",\"fx_cmd_t\":\"%s\"," - "\"fx_stat_t\":\"%s\"," - "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," - "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; - -const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = - ",\"json_attributes_topic\":\"%s\"," - "\"unit_of_meas\":\" \"," - "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"," - "\"ic\":\"mdi:information-outline\""; - -const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = - ",\"uniq_id\":\"%s\"," - "\"device\":{\"identifiers\":[\"%06X\"]," - "\"connections\":[[\"mac\",\"%s\"]]," - "\"name\":\"%s\"," - "\"model\":\"%s\"," - "\"sw_version\":\"%s%s\"," - "\"manufacturer\":\"Tasmota\"}"; - -const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = - ",\"uniq_id\":\"%s\"," - "\"device\":{\"identifiers\":[\"%06X\"]," - "\"connections\":[[\"mac\",\"%s\"]]}"; - -uint8_t hass_init_step = 0; -uint8_t hass_mode = 0; -int hass_tele_period = 0; - -void TryResponseAppend_P(const char *format, ...) -{ - va_list args; - va_start(args, format); - char dummy[2]; - int dlen = vsnprintf_P(dummy, 1, format, args); - - int mlen = strlen(mqtt_data); - int slen = sizeof(mqtt_data) - 1 - mlen; - if (dlen >= slen) - { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: MQTT discovery failed due to too long topic or friendly name. " - "Please shorten topic and friendly name. Failed to format(%u/%u):"), - dlen, slen); - va_start(args, format); - vsnprintf_P(log_data, sizeof(log_data), format, args); - AddLog(LOG_LEVEL_ERROR); - } - else - { - va_start(args, format); - vsnprintf_P(mqtt_data + mlen, slen, format, args); - } - va_end(args); -} - -void HAssAnnounceRelayLight(void) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char stemp3[TOPSZ]; - char unique_id[30]; - bool is_light = false; - bool is_topic_light = false; - - for (uint32_t i = 1; i <= MAX_RELAYS; i++) - { - is_light = ((i == devices_present) && (light_type)); - is_topic_light = Settings.flag.hass_light || is_light; - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), - (is_topic_light) ? "switch" : "light", unique_id); - MqttPublish(stopic, true); - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), - (is_topic_light) ? "light" : "switch", unique_id); - - if (Settings.flag.hass_discovery && (i <= devices_present)) - { - char name[33 + 2]; - char value_template[33]; - char prefix[TOPSZ]; - char *command_topic = stemp1; - char *state_topic = stemp2; - char *availability_topic = stemp3; - - if (i > MAX_FRIENDLYNAMES) - { - snprintf_P(name, sizeof(name), PSTR("%s %d"), SettingsText(SET_FRIENDLYNAME1), i); - } - else - { - snprintf_P(name, sizeof(name), SettingsText(SET_FRIENDLYNAME1 + i - 1)); - } - GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); - GetTopic_P(command_topic, CMND, mqtt_topic, value_template); - GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - -#ifdef USE_LIGHT - if (is_light) - { - char *brightness_command_topic = stemp1; - - GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); - strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic, stemp3); - - if (Light.subtype >= LST_RGB) - { - char *rgb_command_topic = stemp1; - - GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); - - char *effect_command_topic = stemp1; - GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); - } - if (LST_RGBW == Light.subtype) - { - char *white_temp_command_topic = stemp1; - - GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); - } - if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) - { - char *color_temp_command_topic = stemp1; - - GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); - TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); - } - } -#endif - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); - } -} - -void HAssAnnounceButtonSwitch(uint8_t device, char *topic, uint8_t present, uint8_t key, uint8_t toggle) -{ - - - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), key ? "SW" : "BTN", device + 1); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id); - - if (Settings.flag.hass_discovery && present) - { - char name[33 + 6]; - char value_template[33]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - char jsoname[8]; - - snprintf_P(name, sizeof(name), PSTR("%s %s%d"), SettingsText(SET_FRIENDLYNAME1), key ? "Switch" : "Button", device + 1); - snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key ? "SWITCH" : "BUTTON", device + 1); - GetPowerDevice(value_template, device + 1, sizeof(value_template), - key + Settings.flag.device_index_enable); - GetTopic_P(state_topic, STAT, mqtt_topic, (PSTR("/'%s'"), jsoname)); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - - if (toggle) { - if (!key) { - TryResponseAppend_P(HASS_DISCOVER_BUTTON_TOGGLE); - } else { - TryResponseAppend_P(",\"value_template\":\"{%%if is_state(entity_id,\\\"on\\\")-%%}OFF{%%-else-%%}ON{%%-endif%%}\""); - } - } else { - TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2), SettingsText(SET_STATE_TXT1)); - } - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); -} - -void HAssAnnounceSwitches(void) -{ - char sw_topic[TOPSZ]; - - - char *tmp = SettingsText(SET_MQTT_SWITCH_TOPIC); - Format(sw_topic, tmp, sizeof(sw_topic)); - if (!strcmp_P(sw_topic, "0") || strlen(sw_topic) == 0) - { - for (uint32_t switch_index = 0; switch_index < MAX_SWITCHES; switch_index++) - { - uint8_t switch_present = 0; - uint8_t toggle = 1; - - if (pin[GPIO_SWT1 + switch_index] < 99) - { - switch_present = 1; - } - - - if (Settings.switchmode[switch_index] == FOLLOW || Settings.switchmode[switch_index] == FOLLOW_INV || - Settings.flag3.button_switch_force_local || - !strcmp(mqtt_topic, sw_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), sw_topic)) - { - toggle = 0; - } - HAssAnnounceButtonSwitch(switch_index, sw_topic, switch_present, 1, toggle); - } - } -} - -void HAssAnnounceButtons(void) -{ - char key_topic[TOPSZ]; - - - char *tmp = SettingsText(SET_MQTT_BUTTON_TOPIC); - Format(key_topic, tmp, sizeof(key_topic)); - if (!strcmp_P(key_topic, "0") || strlen(key_topic) == 0) - { - for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) - { - uint8_t button_present = 0; - uint8_t toggle = 1; - - if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) - { - button_present = 1; - } - else - { - if (pin[GPIO_KEY1 + button_index] < 99) - { - button_present = 1; - } - } - - - if (Settings.flag3.button_switch_force_local || - !strcmp(mqtt_topic, key_topic) || !strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) - { - toggle = 0; - } - HAssAnnounceButtonSwitch(button_index, key_topic, button_present, 0, toggle); - } - } -} - -void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char *MultiSubName, uint8_t subqty, uint8_t subidx) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - mqtt_data[0] = '\0'; - - char subname[20]; - NoAlNumToUnderscore(subname, MultiSubName); - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subname); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);; - - if (Settings.flag.hass_discovery) - { - char name[33 + 42]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); - snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_FRIENDLYNAME1), sensorname, MultiSubName); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId(), WiFi.macAddress().c_str()); - - char jname[32]; - int sensor_index = GetCommandCode(jname, sizeof(jname), subsensortype, kHAssJsonSensorTypes); - if (sensor_index > -1) { - char param1[20]; - GetTextIndexed(param1, sizeof(param1), sensor_index, kHAssJsonSensorUnits); - switch (sensor_index) { - case 0: - snprintf_P(param1, sizeof(param1), PSTR("°%c"),TempUnit()); - break; - case 1: - case 2: - snprintf_P(param1, sizeof(param1), PSTR("%s"), PressureUnit().c_str()); - break; - } - char param2[50]; - GetTextIndexed(param2, sizeof(param2), sensor_index, kHAssJsonSensorDevCla); - TryResponseAppend_P(HASS_DISCOVER_SENSOR, param1, param2, sensorname, subsensortype); - if (subidx) { - TryResponseAppend_P(PSTR("[%d]"), subqty -1); - } - } else { - TryResponseAppend_P(HASS_DISCOVER_SENSOR, " ", "ic\":\"mdi:eye", sensorname, subsensortype); - } - TryResponseAppend_P(PSTR("}}\"}")); - } - MqttPublish(stopic, true); -} - -void HAssAnnounceSensors(void) -{ - uint8_t hass_xsns_index = 0; - bool is_sensor = true; - uint8_t subqty = 0; - do - { - mqtt_data[0] = '\0'; - int tele_period_save = tele_period; - tele_period = 2; - XsnsNextCall(FUNC_JSON_APPEND, hass_xsns_index); - tele_period = tele_period_save; - - char sensordata[512]; - strlcpy(sensordata, mqtt_data, sizeof(sensordata)); - - if (strlen(sensordata)) - { - sensordata[0] = '{'; - snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); - - - - StaticJsonBuffer<500> jsonBuffer; - JsonObject &root = jsonBuffer.parseObject(sensordata); - if (!root.success()) - { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: jsonBuffer failed to parse '%s'"), sensordata); - continue; - } - for (auto sensor : root) - { - const char *sensorname = sensor.key; - JsonObject &sensors = sensor.value.as(); - if (!sensors.success()) - { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: JsonObject failed to parse '%s'"), sensordata); - continue; - } - for (auto subsensor : sensors) - { - - if (subsensor.value.is()) { - JsonArray& subsensors = subsensor.value.as(); - subqty = subsensors.size(); - char MultiSubName[20]; - for (int i = 1; i <= subqty; i++) { - snprintf_P(MultiSubName, sizeof(MultiSubName), PSTR("%s %d"), subsensor.key, i); - HAssAnnounceSensor(sensorname, subsensor.key, MultiSubName, i, 1); - } - } else { HAssAnnounceSensor(sensorname, subsensor.key, subsensor.key, 0, 0);} - } - } - } - yield(); - } while (hass_xsns_index != 0); -} - -void HAssAnnounceStatusSensor(void) -{ - char stopic[TOPSZ]; - char stemp1[TOPSZ]; - char stemp2[TOPSZ]; - char unique_id[30]; - - - mqtt_data[0] = '\0'; - - - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP.getChipId()); - snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); - - if (Settings.flag.hass_discovery) - { - char name[33 + 7]; - char prefix[TOPSZ]; - char *state_topic = stemp1; - char *availability_topic = stemp2; - - snprintf_P(name, sizeof(name), PSTR("%s status"), SettingsText(SET_FRIENDLYNAME1)); - GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); - GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); - - Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); - TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); - TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(), - SettingsText(SET_FRIENDLYNAME1), ModuleName().c_str(), my_version, my_image); - - TryResponseAppend_P(PSTR("}")); - } - MqttPublish(stopic, true); -} - -void HAssPublishStatus(void) -{ - Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," - "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," - "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," - "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," - "\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_CMND_IPADDRESS "\":\"%s\"," - "\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"), - my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getSdkVersion(), ModuleName().c_str(), - GetResetReason().c_str(), GetUptime().c_str(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), - Settings.bootcount, Settings.save_flag, WiFi.localIP().toString().c_str(), - WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); -} - -void HAssDiscovery(void) -{ - - if (Settings.flag.hass_discovery) - { - Settings.flag.mqtt_response = 0; - Settings.flag.decimal_text = 1; - Settings.flag3.hass_tele_on_power = 1; - Settings.light_scheme = 0; - } - - if (Settings.flag.hass_discovery || (1 == hass_mode)) - { - - HAssAnnounceRelayLight(); - - - HAssAnnounceButtons(); - - - HAssAnnounceSwitches(); - - - HAssAnnounceSensors(); - - - HAssAnnounceStatusSensor(); - } -} - -void HAssDiscover(void) -{ - hass_mode = 1; - hass_init_step = 1; -} - -void HAssAnyKey(void) -{ - if (!Settings.flag.hass_discovery) - { - return; - } - - uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; - uint32_t device = XdrvMailbox.payload & 0xFF; - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; - - char scommand[CMDSZ]; - snprintf_P(scommand, sizeof(scommand), PSTR("%s%d"), (key) ? "SWITCH" : "BUTTON", device); - char stopic[TOPSZ]; - - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P(S_JSON_COMMAND_SVALUE, PSTR(D_RSLT_STATE), GetStateText(state)); - MqttPublish(stopic); -} - - - - - -bool Xdrv12(uint8_t function) -{ - bool result = false; - - if (Settings.flag.mqtt_enabled) - { - switch (function) - { - case FUNC_EVERY_SECOND: - if (hass_init_step) - { - hass_init_step--; - if (!hass_init_step) - { - HAssDiscovery(); - } - } - else if (Settings.flag.hass_discovery && Settings.tele_period) - { - hass_tele_period++; - if (hass_tele_period >= Settings.tele_period) - { - hass_tele_period = 0; - - mqtt_data[0] = '\0'; - HAssPublishStatus(); - } - } - break; - case FUNC_ANY_KEY: - HAssAnyKey(); - break; - case FUNC_MQTT_INIT: - hass_mode = 0; - hass_init_step = 2; - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_13_display.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_13_display.ino" -#if defined(USE_I2C) || defined(USE_SPI) -#ifdef USE_DISPLAY - -#define XDRV_13 13 - -#include -#include - -Renderer *renderer; - -enum ColorType { COLOR_BW, COLOR_COLOR }; - -#ifndef MAXBUTTONS -#define MAXBUTTONS 16 -#endif - -#ifdef USE_TOUCH_BUTTONS -VButton *buttons[MAXBUTTONS]; -#endif - - - -uint16_t fg_color = 1; -uint16_t bg_color = 0; -uint8_t color_type = COLOR_BW; -uint8_t auto_draw=1; - -const uint8_t DISPLAY_MAX_DRIVERS = 16; -const uint8_t DISPLAY_MAX_COLS = 44; -const uint8_t DISPLAY_MAX_ROWS = 32; - -const uint8_t DISPLAY_LOG_ROWS = 32; - -#define D_PRFX_DISPLAY "Display" -#define D_CMND_DISP_ADDRESS "Address" -#define D_CMND_DISP_COLS "Cols" -#define D_CMND_DISP_DIMMER "Dimmer" -#define D_CMND_DISP_MODE "Mode" -#define D_CMND_DISP_MODEL "Model" -#define D_CMND_DISP_REFRESH "Refresh" -#define D_CMND_DISP_ROWS "Rows" -#define D_CMND_DISP_SIZE "Size" -#define D_CMND_DISP_FONT "Font" -#define D_CMND_DISP_ROTATE "Rotate" -#define D_CMND_DISP_TEXT "Text" -#define D_CMND_DISP_WIDTH "Width" -#define D_CMND_DISP_HEIGHT "Height" - -enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND, - FUNC_DISPLAY_MODEL, FUNC_DISPLAY_MODE, FUNC_DISPLAY_POWER, - FUNC_DISPLAY_CLEAR, FUNC_DISPLAY_DRAW_FRAME, - FUNC_DISPLAY_DRAW_HLINE, FUNC_DISPLAY_DRAW_VLINE, FUNC_DISPLAY_DRAW_LINE, - FUNC_DISPLAY_DRAW_CIRCLE, FUNC_DISPLAY_FILL_CIRCLE, - FUNC_DISPLAY_DRAW_RECTANGLE, FUNC_DISPLAY_FILL_RECTANGLE, - FUNC_DISPLAY_TEXT_SIZE, FUNC_DISPLAY_FONT_SIZE, FUNC_DISPLAY_ROTATION, FUNC_DISPLAY_DRAW_STRING, FUNC_DISPLAY_ONOFF }; - -enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; - -const char kDisplayCommands[] PROGMEM = D_PRFX_DISPLAY "|" - "|" D_CMND_DISP_MODEL "|" D_CMND_DISP_WIDTH "|" D_CMND_DISP_HEIGHT "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" - D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" D_CMND_DISP_SIZE "|" D_CMND_DISP_FONT "|" - D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; - -void (* const DisplayCommand[])(void) PROGMEM = { - &CmndDisplay, &CmndDisplayModel, &CmndDisplayWidth, &CmndDisplayHeight, &CmndDisplayMode, &CmndDisplayRefresh, - &CmndDisplayDimmer, &CmndDisplayColumns, &CmndDisplayRows, &CmndDisplaySize, &CmndDisplayFont, - &CmndDisplayRotate, &CmndDisplayText, &CmndDisplayAddress }; - -char *dsp_str; - -uint16_t dsp_x; -uint16_t dsp_y; -uint16_t dsp_x2; -uint16_t dsp_y2; -uint16_t dsp_rad; -uint16_t dsp_color; -int16_t dsp_len; -int16_t disp_xpos = 0; -int16_t disp_ypos = 0; - -uint8_t disp_power = 0; -uint8_t disp_device = 0; -uint8_t disp_refresh = 1; -uint8_t disp_autodraw = 1; -uint8_t dsp_init; -uint8_t dsp_font; -uint8_t dsp_flag; -uint8_t dsp_on; - -#ifdef USE_DISPLAY_MODES1TO5 - -char **disp_log_buffer; -char **disp_screen_buffer; -char disp_temp[2]; -char disp_pres[5]; - -uint8_t disp_log_buffer_cols = 0; -uint8_t disp_log_buffer_idx = 0; -uint8_t disp_log_buffer_ptr = 0; -uint8_t disp_screen_buffer_cols = 0; -uint8_t disp_screen_buffer_rows = 0; -bool disp_subscribed = false; - -#endif - - - -void DisplayInit(uint8_t mode) -{ - if (renderer) { - renderer->DisplayInit(mode, Settings.display_size, Settings.display_rotate, Settings.display_font); - } - else { - dsp_init = mode; - XdspCall(FUNC_DISPLAY_INIT); - } -} - -void DisplayClear(void) -{ - XdspCall(FUNC_DISPLAY_CLEAR); -} - -void DisplayDrawHLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_len = len; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_HLINE); -} - -void DisplayDrawVLine(uint16_t x, uint16_t y, int16_t len, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_len = len; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_VLINE); -} - -void DisplayDrawLine(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_LINE); -} - -void DisplayDrawCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_rad = rad; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_CIRCLE); -} - -void DisplayDrawFilledCircle(uint16_t x, uint16_t y, uint16_t rad, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_rad = rad; - dsp_color = color; - XdspCall(FUNC_DISPLAY_FILL_CIRCLE); -} - -void DisplayDrawRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_DRAW_RECTANGLE); -} - -void DisplayDrawFilledRectangle(uint16_t x, uint16_t y, uint16_t x2, uint16_t y2, uint16_t color) -{ - dsp_x = x; - dsp_y = y; - dsp_x2 = x2; - dsp_y2 = y2; - dsp_color = color; - XdspCall(FUNC_DISPLAY_FILL_RECTANGLE); -} - -void DisplayDrawFrame(void) -{ - XdspCall(FUNC_DISPLAY_DRAW_FRAME); -} - -void DisplaySetSize(uint8_t size) -{ - Settings.display_size = size &3; - XdspCall(FUNC_DISPLAY_TEXT_SIZE); -} - -void DisplaySetFont(uint8_t font) -{ - Settings.display_font = font &3; - XdspCall(FUNC_DISPLAY_FONT_SIZE); -} - -void DisplaySetRotation(uint8_t rotation) -{ - Settings.display_rotate = rotation &3; - XdspCall(FUNC_DISPLAY_ROTATION); -} - -void DisplayDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - dsp_x = x; - dsp_y = y; - dsp_str = str; - dsp_color = color; - dsp_flag = flag; - XdspCall(FUNC_DISPLAY_DRAW_STRING); -} - -void DisplayOnOff(uint8_t on) -{ - dsp_on = on; - XdspCall(FUNC_DISPLAY_ONOFF); -} - - - - -uint8_t fatoiv(char *cp,float *res) { - uint8_t index=0; - *res=CharToFloat(cp); - while (*cp) { - if ((*cp>='0' && *cp<='9') || (*cp=='-') || (*cp=='.')) { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -uint8_t atoiv(char *cp, int16_t *res) -{ - uint8_t index = 0; - *res = atoi(cp); - while (*cp) { - if ((*cp>='0' && *cp<='9') || (*cp=='-')) { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -uint8_t atoiV(char *cp, uint16_t *res) -{ - uint8_t index = 0; - *res = atoi(cp); - while (*cp) { - if (*cp>='0' && *cp<='9') { - cp++; - index++; - } else { - break; - } - } - return index; -} - - -void alignright(char *string) { - uint16_t slen=strlen(string); - uint16_t len=slen; - while (len) { - - if (string[len-1]!=' ') { - break; - } - len--; - } - uint16_t diff=slen-len; - if (diff>0) { - - memmove(&string[diff],string,len); - memset(string,' ',diff); - } -} - -char *get_string(char *buff,uint8_t len,char *cp) { -uint8_t index=0; - while (*cp!=':') { - buff[index]=*cp++; - index++; - if (index>=len) break; - } - buff[index]=0; - cp++; - return cp; -} - -#define ESCAPE_CHAR '~' - - -uint32_t decode_te(char *line) { - uint32_t skip = 0; - char sbuf[3],*cp; - while (*line) { - if (*line==ESCAPE_CHAR) { - cp=line+1; - if (*cp!=0 && *cp==ESCAPE_CHAR) { - - memmove(cp,cp+1,strlen(cp)); - skip++; - } else { - - if (strlen(cp)<2) { - - return skip; - } - - sbuf[0]=*(cp); - sbuf[1]=*(cp+1); - sbuf[2]=0; - *line=strtol(sbuf,0,16); - - memmove(cp,cp+2,strlen(cp)-1); - skip += 2; - } - } - line++; - } - return skip; -} - - - -#define DISPLAY_BUFFER_COLS 128 - -void DisplayText(void) -{ - uint8_t lpos; - uint8_t escape = 0; - uint8_t var; - int16_t lin = 0; - int16_t col = 0; - int16_t fill = 0; - int16_t temp; - int16_t temp1; - float ftemp; - - char linebuf[DISPLAY_BUFFER_COLS]; - char *dp = linebuf; - char *cp = XdrvMailbox.data; - - memset(linebuf, ' ', sizeof(linebuf)); - linebuf[sizeof(linebuf)-1] = 0; - *dp = 0; - - while (*cp) { - if (!escape) { - - if (*cp == '[') { - escape = 1; - cp++; - - if ((uint32_t)dp - (uint32_t)linebuf) { - if (!fill) { *dp = 0; } - if (col > 0 && lin > 0) { - - if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); - else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); - } else { - - if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - } - memset(linebuf, ' ', sizeof(linebuf)); - linebuf[sizeof(linebuf)-1] = 0; - dp = linebuf; - } - } else { - - if (dp < (linebuf + DISPLAY_BUFFER_COLS)) { *dp++ = *cp++; } - } - } else { - - if (*cp == ']') { - escape = 0; - cp++; - } else { - - switch (*cp++) { - case 'z': - - if (!renderer) DisplayClear(); - else renderer->fillScreen(bg_color); - disp_xpos = 0; - disp_ypos = 0; - col = 0; - lin = 0; - break; - case 'i': - - DisplayInit(DISPLAY_INIT_PARTIAL); - break; - case 'I': - - DisplayInit(DISPLAY_INIT_FULL); - break; - case 'o': - if (!renderer) { - DisplayOnOff(0); - } else { - renderer->DisplayOnff(0); - } - break; - case 'O': - if (!renderer) { - DisplayOnOff(1); - } else { - renderer->DisplayOnff(1); - } - break; - case 'x': - - var = atoiv(cp, &disp_xpos); - cp += var; - break; - case 'y': - - var = atoiv(cp, &disp_ypos); - cp += var; - break; - case 'l': - - var = atoiv(cp, &lin); - cp += var; - - break; - case 'c': - - var = atoiv(cp, &col); - cp += var; - - break; - case 'C': - - if (*cp=='i') { - - cp++; - var = atoiv(cp, &temp); - if (renderer) ftemp=renderer->GetColorFromIndex(temp); - } else { - - var = fatoiv(cp,&ftemp); - } - fg_color=ftemp; - cp += var; - if (renderer) renderer->setTextColor(fg_color,bg_color); - break; - case 'B': - - if (*cp=='i') { - - cp++; - var = atoiv(cp, &temp); - if (renderer) ftemp=renderer->GetColorFromIndex(temp); - } else { - var = fatoiv(cp,&ftemp); - } - bg_color=ftemp; - cp += var; - if (renderer) renderer->setTextColor(fg_color,bg_color); - break; - case 'p': - - var = atoiv(cp, &fill); - cp += var; - linebuf[fill] = 0; - break; -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) - case 'P': - { char *ep=strchr(cp,':'); - if (ep) { - *ep=0; - ep++; - Draw_RGB_Bitmap(cp,disp_xpos,disp_ypos); - cp=ep; - } - } - break; -#endif - case 'h': - - var = atoiv(cp, &temp); - cp += var; - if (temp < 0) { - if (renderer) renderer->writeFastHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); - else DisplayDrawHLine(disp_xpos + temp, disp_ypos, -temp, fg_color); - } else { - if (renderer) renderer->writeFastHLine(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawHLine(disp_xpos, disp_ypos, temp, fg_color); - } - disp_xpos += temp; - break; - case 'v': - - var = atoiv(cp, &temp); - cp += var; - if (temp < 0) { - if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); - else DisplayDrawVLine(disp_xpos, disp_ypos + temp, -temp, fg_color); - } else { - if (renderer) renderer->writeFastVLine(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawVLine(disp_xpos, disp_ypos, temp, fg_color); - } - disp_ypos += temp; - break; - case 'L': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->writeLine(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawLine(disp_xpos, disp_ypos, temp, temp1, fg_color); - disp_xpos += temp; - disp_ypos += temp1; - break; - case 'k': - - var = atoiv(cp, &temp); - cp += var; - if (renderer) renderer->drawCircle(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawCircle(disp_xpos, disp_ypos, temp, fg_color); - break; - case 'K': - - var = atoiv(cp, &temp); - cp += var; - if (renderer) renderer->fillCircle(disp_xpos, disp_ypos, temp, fg_color); - else DisplayDrawFilledCircle(disp_xpos, disp_ypos, temp, fg_color); - break; - case 'r': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->drawRect(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); - break; - case 'R': - - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - if (renderer) renderer->fillRect(disp_xpos, disp_ypos, temp, temp1, fg_color); - else DisplayDrawFilledRectangle(disp_xpos, disp_ypos, temp, temp1, fg_color); - break; - case 'u': - - { int16_t rad; - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - cp++; - var = atoiv(cp, &rad); - cp += var; - if (renderer) renderer->drawRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); - - } - break; - case 'U': - - { int16_t rad; - var = atoiv(cp, &temp); - cp += var; - cp++; - var = atoiv(cp, &temp1); - cp += var; - cp++; - var = atoiv(cp, &rad); - cp += var; - if (renderer) renderer->fillRoundRect(disp_xpos, disp_ypos, temp, temp1, rad, fg_color); - - } - break; - - case 't': - if (*cp=='S') { - cp++; - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { - snprintf_P(dp, 9, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - dp += 8; - } - } else { - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -5) { - snprintf_P(dp, 6, PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute); - dp += 5; - } - } - break; - case 'T': - if (dp < (linebuf + DISPLAY_BUFFER_COLS) -8) { - snprintf_P(dp, 9, PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year%2000); - dp += 8; - } - break; - case 'd': - - if (renderer) renderer->Updateframe(); - else DisplayDrawFrame(); - break; - case 'D': - - auto_draw=*cp&3; - if (renderer) renderer->setDrawMode(auto_draw>>1); - cp += 1; - break; - case 's': - - if (renderer) renderer->setTextSize(*cp&7); - else DisplaySetSize(*cp&3); - cp += 1; - break; - case 'f': - - if (renderer) renderer->setTextFont(*cp&7); - else DisplaySetFont(*cp&7); - cp += 1; - break; - case 'a': - - if (renderer) renderer->setRotation(*cp&3); - else DisplaySetRotation(*cp&3); - cp+=1; - break; - -#ifdef USE_GRAPH - case 'G': - - if (*cp=='d') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - var=atoiv(cp,&temp1); - cp+=var; - RedrawGraph(temp,temp1); - break; - } -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) - if (*cp=='s') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - - char bbuff[128]; - cp=get_string(bbuff,sizeof(bbuff),cp); - Save_graph(temp,bbuff); - break; - } - if (*cp=='r') { - cp++; - var=atoiv(cp,&temp); - cp+=var; - cp++; - - char bbuff[128]; - cp=get_string(bbuff,sizeof(bbuff),cp); - Restore_graph(temp,bbuff); - break; - } -#endif - { int16_t num,gxp,gyp,gxs,gys,dec,icol; - float ymin,ymax; - var=atoiv(cp,&num); - cp+=var; - cp++; - var=atoiv(cp,&gxp); - cp+=var; - cp++; - var=atoiv(cp,&gyp); - cp+=var; - cp++; - var=atoiv(cp,&gxs); - cp+=var; - cp++; - var=atoiv(cp,&gys); - cp+=var; - cp++; - var=atoiv(cp,&dec); - cp+=var; - cp++; - var=fatoiv(cp,&ymin); - cp+=var; - cp++; - var=fatoiv(cp,&ymax); - cp+=var; - if (color_type==COLOR_COLOR) { - - cp++; - var=atoiv(cp,&icol); - cp+=var; - } else { - icol=0; - } - DefineGraph(num,gxp,gyp,gxs,gys,dec,ymin,ymax,icol); - } - break; - case 'g': - { float temp; - int16_t num; - var=atoiv(cp,&num); - cp+=var; - cp++; - var=fatoiv(cp,&temp); - cp+=var; - AddValue(num,temp); - } - break; -#endif - -#ifdef USE_AWATCH - case 'w': - var = atoiv(cp, &temp); - cp += var; - DrawAClock(temp); - break; -#endif - -#ifdef USE_TOUCH_BUTTONS - case 'b': - { int16_t num,gxp,gyp,gxs,gys,outline,fill,textcolor,textsize; - var=atoiv(cp,&num); - cp+=var; - cp++; - uint8_t bflags=num>>8; - num=num%MAXBUTTONS; - var=atoiv(cp,&gxp); - cp+=var; - cp++; - var=atoiv(cp,&gyp); - cp+=var; - cp++; - var=atoiv(cp,&gxs); - cp+=var; - cp++; - var=atoiv(cp,&gys); - cp+=var; - cp++; - var=atoiv(cp,&outline); - cp+=var; - cp++; - var=atoiv(cp,&fill); - cp+=var; - cp++; - var=atoiv(cp,&textcolor); - cp+=var; - cp++; - var=atoiv(cp,&textsize); - cp+=var; - cp++; - - char bbuff[32]; - cp=get_string(bbuff,sizeof(bbuff),cp); - - if (buttons[num]) { - delete buttons[num]; - } - if (renderer) { - buttons[num]= new VButton(); - if (buttons[num]) { - buttons[num]->vpower=bflags; - buttons[num]->initButtonUL(renderer,gxp,gyp,gxs,gys,renderer->GetColorFromIndex(outline),\ - renderer->GetColorFromIndex(fill),renderer->GetColorFromIndex(textcolor),bbuff,textsize); - if (!bflags) { - - buttons[num]->xdrawButton(bitRead(power,num)); - } else { - - buttons[num]->vpower&=0x7f; - buttons[num]->xdrawButton(buttons[num]->vpower&0x80); - } - } - } - } - break; -#endif - default: - - Response_P(PSTR("Unknown Escape")); - goto exit; - break; - } - } - } - } - exit: - - dp -= decode_te(linebuf); - if ((uint32_t)dp - (uint32_t)linebuf) { - if (!fill) { - *dp = 0; - } else { - linebuf[abs(fill)] = 0; - } - if (fill<0) { - - alignright(linebuf); - } - if (col > 0 && lin > 0) { - - if (!renderer) DisplayDrawStringAt(col, lin, linebuf, fg_color, 1); - else renderer->DrawStringAt(col, lin, linebuf, fg_color, 1); - } else { - - if (!renderer) DisplayDrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - else renderer->DrawStringAt(disp_xpos, disp_ypos, linebuf, fg_color, 0); - } - } - - if (auto_draw&1) { - if (renderer) renderer->Updateframe(); - else DisplayDrawFrame(); - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void DisplayClearScreenBuffer(void) -{ - if (disp_screen_buffer_cols) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - memset(disp_screen_buffer[i], 0, disp_screen_buffer_cols); - } - } -} - -void DisplayFreeScreenBuffer(void) -{ - if (disp_screen_buffer != nullptr) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - if (disp_screen_buffer[i] != nullptr) { free(disp_screen_buffer[i]); } - } - free(disp_screen_buffer); - disp_screen_buffer_cols = 0; - disp_screen_buffer_rows = 0; - } -} - -void DisplayAllocScreenBuffer(void) -{ - if (!disp_screen_buffer_cols) { - disp_screen_buffer_rows = Settings.display_rows; - disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); - if (disp_screen_buffer != nullptr) { - for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) { - disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_screen_buffer[i] == nullptr) { - DisplayFreeScreenBuffer(); - break; - } - } - } - if (disp_screen_buffer != nullptr) { - disp_screen_buffer_cols = Settings.display_cols[0] +1; - DisplayClearScreenBuffer(); - } - } -} - -void DisplayReAllocScreenBuffer(void) -{ - DisplayFreeScreenBuffer(); - DisplayAllocScreenBuffer(); -} - -void DisplayFillScreen(uint32_t line) -{ - uint32_t len = disp_screen_buffer_cols - strlen(disp_screen_buffer[line]); - if (len) { - memset(disp_screen_buffer[line] + strlen(disp_screen_buffer[line]), 0x20, len); - disp_screen_buffer[line][disp_screen_buffer_cols -1] = 0; - } -} - - - -void DisplayClearLogBuffer(void) -{ - if (disp_log_buffer_cols) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - memset(disp_log_buffer[i], 0, disp_log_buffer_cols); - } - } -} - -void DisplayFreeLogBuffer(void) -{ - if (disp_log_buffer != nullptr) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - if (disp_log_buffer[i] != nullptr) { free(disp_log_buffer[i]); } - } - free(disp_log_buffer); - disp_log_buffer_cols = 0; - } -} - -void DisplayAllocLogBuffer(void) -{ - if (!disp_log_buffer_cols) { - disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); - if (disp_log_buffer != nullptr) { - for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_log_buffer[i] == nullptr) { - DisplayFreeLogBuffer(); - break; - } - } - } - if (disp_log_buffer != nullptr) { - disp_log_buffer_cols = Settings.display_cols[0] +1; - DisplayClearLogBuffer(); - } - } -} - -void DisplayReAllocLogBuffer(void) -{ - DisplayFreeLogBuffer(); - DisplayAllocLogBuffer(); -} - -void DisplayLogBufferAdd(char* txt) -{ - if (disp_log_buffer_cols) { - strlcpy(disp_log_buffer[disp_log_buffer_idx], txt, disp_log_buffer_cols); - disp_log_buffer_idx++; - if (DISPLAY_LOG_ROWS == disp_log_buffer_idx) { disp_log_buffer_idx = 0; } - } -} - -char* DisplayLogBuffer(char temp_code) -{ - char* result = nullptr; - if (disp_log_buffer_cols) { - if (disp_log_buffer_idx != disp_log_buffer_ptr) { - result = disp_log_buffer[disp_log_buffer_ptr]; - disp_log_buffer_ptr++; - if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; } - - char *pch = strchr(result, '~'); - if (pch != nullptr) { result[pch - result] = temp_code; } - } - } - return result; -} - -void DisplayLogBufferInit(void) -{ - if (Settings.display_mode) { - disp_log_buffer_idx = 0; - disp_log_buffer_ptr = 0; - disp_refresh = Settings.display_refresh; - - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); - snprintf_P(disp_pres, sizeof(disp_pres), PressureUnit().c_str()); - - DisplayReAllocLogBuffer(); - - char buffer[40]; - snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), my_version, my_image); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode); - DisplayLogBufferAdd(buffer); - - snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), my_hostname); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active)); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_MAC " %s"), WiFi.macAddress().c_str()); - DisplayLogBufferAdd(buffer); - if (!global_state.wifi_down) { - snprintf_P(buffer, sizeof(buffer), PSTR("IP %s"), WiFi.localIP().toString().c_str()); - DisplayLogBufferAdd(buffer); - snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI())); - DisplayLogBufferAdd(buffer); - } - } -} - - - - - -enum SensorQuantity { - JSON_TEMPERATURE, - JSON_HUMIDITY, JSON_LIGHT, JSON_NOISE, JSON_AIRQUALITY, - JSON_PRESSURE, JSON_PRESSUREATSEALEVEL, - JSON_ILLUMINANCE, - JSON_GAS, - JSON_YESTERDAY, JSON_TOTAL, JSON_TODAY, - JSON_PERIOD, - JSON_POWERFACTOR, JSON_COUNTER, JSON_ANALOG_INPUT, JSON_UV_LEVEL, - JSON_CURRENT, - JSON_VOLTAGE, - JSON_POWERUSAGE, - JSON_CO2, - JSON_FREQUENCY }; -const char kSensorQuantity[] PROGMEM = - D_JSON_TEMPERATURE "|" - D_JSON_HUMIDITY "|" D_JSON_LIGHT "|" D_JSON_NOISE "|" D_JSON_AIRQUALITY "|" - D_JSON_PRESSURE "|" D_JSON_PRESSUREATSEALEVEL "|" - D_JSON_ILLUMINANCE "|" - D_JSON_GAS "|" - D_JSON_YESTERDAY "|" D_JSON_TOTAL "|" D_JSON_TODAY "|" - D_JSON_PERIOD "|" - D_JSON_POWERFACTOR "|" D_JSON_COUNTER "|" D_JSON_ANALOG_INPUT "|" D_JSON_UV_LEVEL "|" - D_JSON_CURRENT "|" - D_JSON_VOLTAGE "|" - D_JSON_POWERUSAGE "|" - D_JSON_CO2 "|" - D_JSON_FREQUENCY ; - -void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value) -{ - char quantity[TOPSZ]; - char buffer[Settings.display_cols[0] +1]; - char spaces[Settings.display_cols[0]]; - char source[Settings.display_cols[0] - Settings.display_cols[1]]; - char svalue[Settings.display_cols[1] +1]; - -#ifdef USE_DEBUG_DRIVER - ShowFreeMem(PSTR("DisplayJsonValue")); -#endif - - memset(spaces, 0x20, sizeof(spaces)); - spaces[sizeof(spaces) -1] = '\0'; - snprintf_P(source, sizeof(source), PSTR("%s%s%s%s"), topic, (strlen(topic))?"/":"", mkey, spaces); - - int quantity_code = GetCommandCode(quantity, sizeof(quantity), mkey, kSensorQuantity); - if ((-1 == quantity_code) || !strcmp_P(mkey, S_RSLT_POWER)) { - return; - } - if (JSON_TEMPERATURE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s~%s"), value, disp_temp); - } - else if ((quantity_code >= JSON_HUMIDITY) && (quantity_code <= JSON_AIRQUALITY)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s%%"), value); - } - else if ((quantity_code >= JSON_PRESSURE) && (quantity_code <= JSON_PRESSUREATSEALEVEL)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s%s"), value, disp_pres); - } - else if (JSON_ILLUMINANCE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_LUX), value); - } - else if (JSON_GAS == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOOHM), value); - } - else if ((quantity_code >= JSON_YESTERDAY) && (quantity_code <= JSON_TODAY)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_KILOWATTHOUR), value); - } - else if (JSON_PERIOD == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATTHOUR), value); - } - else if ((quantity_code >= JSON_POWERFACTOR) && (quantity_code <= JSON_UV_LEVEL)) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), value); - } - else if (JSON_CURRENT == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_AMPERE), value); - } - else if (JSON_VOLTAGE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_VOLT), value); - } - else if (JSON_POWERUSAGE == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_WATT), value); - } - else if (JSON_CO2 == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_PARTS_PER_MILLION), value); - } - else if (JSON_FREQUENCY == quantity_code) { - snprintf_P(svalue, sizeof(svalue), PSTR("%s" D_UNIT_HERTZ), value); - } - snprintf_P(buffer, sizeof(buffer), PSTR("%s %s"), source, svalue); - - - - DisplayLogBufferAdd(buffer); -} - -void DisplayAnalyzeJson(char *topic, char *json) -{ -# 1145 "S:/Development/Tasmota/tasmota/xdrv_13_display.ino" - String jsonStr = json; - - StaticJsonBuffer<1024> jsonBuf; - JsonObject &root = jsonBuf.parseObject(jsonStr); - if (root.success()) { - - const char *unit; - unit = root[D_JSON_TEMPERATURE_UNIT]; - if (unit) { - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%s"), unit); - } - unit = root[D_JSON_PRESSURE_UNIT]; - if (unit) { - snprintf_P(disp_pres, sizeof(disp_pres), PSTR("%s"), unit); - } - - for (JsonObject::iterator it = root.begin(); it != root.end(); ++it) { - JsonVariant value = it->value; - if (value.is()) { - JsonObject& Object2 = value; - for (JsonObject::iterator it2 = Object2.begin(); it2 != Object2.end(); ++it2) { - JsonVariant value2 = it2->value; - if (value2.is()) { - JsonObject& Object3 = value2; - for (JsonObject::iterator it3 = Object3.begin(); it3 != Object3.end(); ++it3) { - const char* value = it3->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it3->key, value); - } - } - } else { - const char* value = it2->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it2->key, value); - } - } - } - } else { - const char* value = it->value; - if (value != nullptr) { - DisplayJsonValue(topic, it->key, it->key, value); - } - } - } - } -} - -void DisplayMqttSubscribe(void) -{ - - - - - - - if (Settings.display_model && (Settings.display_mode &0x04)) { - - char stopic[TOPSZ]; - char ntopic[TOPSZ]; - - ntopic[0] = '\0'; - strlcpy(stopic, SettingsText(SET_MQTT_FULLTOPIC), sizeof(stopic)); - char *tp = strtok(stopic, "/"); - while (tp != nullptr) { - if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { - break; - } - strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); - tp = strtok(nullptr, "/"); - } - strncat(ntopic, SettingsText(SET_MQTTPREFIX3), sizeof(ntopic) - strlen(ntopic) -1); - strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); - MqttSubscribe(ntopic); - disp_subscribed = true; - } else { - disp_subscribed = false; - } -} - -bool DisplayMqttData(void) -{ - if (disp_subscribed) { - char stopic[TOPSZ]; - - snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), SettingsText(SET_MQTTPREFIX3)); - char *tp = strstr(XdrvMailbox.topic, stopic); - if (tp) { - if (Settings.display_mode &0x04) { - tp = tp + strlen(stopic); - char *topic = strtok(tp, "/"); - DisplayAnalyzeJson(topic, XdrvMailbox.data); - } - return true; - } - } - return false; -} - -void DisplayLocalSensor(void) -{ - if ((Settings.display_mode &0x02) && (0 == tele_period)) { - char no_topic[1] = { 0 }; - - DisplayAnalyzeJson(no_topic, mqtt_data); - } -} - -#endif - - - - - -void DisplayInitDriver(void) -{ - XdspCall(FUNC_DISPLAY_INIT_DRIVER); - - if (renderer) { - renderer->setTextFont(Settings.display_font); - renderer->setTextSize(Settings.display_size); - } - - - - - if (Settings.display_model) { - devices_present++; - disp_device = devices_present; - -#ifndef USE_DISPLAY_MODES1TO5 - Settings.display_mode = 0; -#else - DisplayLogBufferInit(); -#endif - } -} - -void DisplaySetPower(void) -{ - disp_power = bitRead(XdrvMailbox.index, disp_device -1); - - - - if (Settings.display_model) { - if (!renderer) { - XdspCall(FUNC_DISPLAY_POWER); - } else { - renderer->DisplayOnff(disp_power); - } - } -} - - - - - -void CmndDisplay(void) -{ - Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\"" - D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" - D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), - Settings.display_model, Settings.display_width, Settings.display_height, - Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, - Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); -} - -void CmndDisplayModel(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) { - uint32_t last_display_model = Settings.display_model; - Settings.display_model = XdrvMailbox.payload; - if (XdspCall(FUNC_DISPLAY_MODEL)) { - restart_flag = 2; - } else { - Settings.display_model = last_display_model; - } - } - ResponseCmndNumber(Settings.display_model); -} - -void CmndDisplayWidth(void) -{ - if (XdrvMailbox.payload > 0) { - if (XdrvMailbox.payload != Settings.display_width) { - Settings.display_width = XdrvMailbox.payload; - restart_flag = 2; - } - } - ResponseCmndNumber(Settings.display_width); -} - -void CmndDisplayHeight(void) -{ - if (XdrvMailbox.payload > 0) { - if (XdrvMailbox.payload != Settings.display_height) { - Settings.display_height = XdrvMailbox.payload; - restart_flag = 2; - } - } - ResponseCmndNumber(Settings.display_height); -} - -void CmndDisplayMode(void) -{ -#ifdef USE_DISPLAY_MODES1TO5 - - - - - - - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - uint32_t last_display_mode = Settings.display_mode; - Settings.display_mode = XdrvMailbox.payload; - - if (disp_subscribed != (Settings.display_mode &0x04)) { - restart_flag = 2; - } else { - if (last_display_mode && !Settings.display_mode) { - DisplayInit(DISPLAY_INIT_MODE); - if (renderer) renderer->fillScreen(bg_color); - else DisplayClear(); - } else { - DisplayLogBufferInit(); - DisplayInit(DISPLAY_INIT_MODE); - } - } - } -#endif - ResponseCmndNumber(Settings.display_mode); -} - -void CmndDisplayDimmer(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; - if (Settings.display_dimmer && !(disp_power)) { - ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY); - } - else if (!Settings.display_dimmer && disp_power) { - ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); - } - if (renderer) renderer->dim(Settings.display_dimmer); - } - ResponseCmndNumber(Settings.display_dimmer); -} - -void CmndDisplaySize(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { - Settings.display_size = XdrvMailbox.payload; - if (renderer) renderer->setTextSize(Settings.display_size); - else DisplaySetSize(Settings.display_size); - } - ResponseCmndNumber(Settings.display_size); -} - -void CmndDisplayFont(void) -{ - if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) { - Settings.display_font = XdrvMailbox.payload; - if (renderer) renderer->setTextFont(Settings.display_font); - else DisplaySetFont(Settings.display_font); - } - ResponseCmndNumber(Settings.display_font); -} - -void CmndDisplayRotate(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { - if (Settings.display_rotate != XdrvMailbox.payload) { -# 1428 "S:/Development/Tasmota/tasmota/xdrv_13_display.ino" - Settings.display_rotate = XdrvMailbox.payload; - DisplayInit(DISPLAY_INIT_MODE); -#ifdef USE_DISPLAY_MODES1TO5 - DisplayLogBufferInit(); -#endif - } - } - ResponseCmndNumber(Settings.display_rotate); -} - -void CmndDisplayText(void) -{ - if (disp_device && XdrvMailbox.data_len > 0) { -#ifndef USE_DISPLAY_MODES1TO5 - DisplayText(); -#else - if (!Settings.display_mode) { - DisplayText(); - } else { - DisplayLogBufferAdd(XdrvMailbox.data); - } -#endif - ResponseCmndChar(XdrvMailbox.data); - } -} - -void CmndDisplayAddress(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { - Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]); - } -} - -void CmndDisplayRefresh(void) -{ - if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { - Settings.display_refresh = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.display_refresh); -} - -void CmndDisplayColumns(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { - Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload; -#ifdef USE_DISPLAY_MODES1TO5 - if (1 == XdrvMailbox.index) { - DisplayLogBufferInit(); - DisplayReAllocScreenBuffer(); - } -#endif - } - ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]); - } -} - -void CmndDisplayRows(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { - Settings.display_rows = XdrvMailbox.payload; -#ifdef USE_DISPLAY_MODES1TO5 - DisplayLogBufferInit(); - DisplayReAllocScreenBuffer(); -#endif - } - ResponseCmndNumber(Settings.display_rows); -} - - - - - -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) -void Draw_RGB_Bitmap(char *file,uint16_t xp, uint16_t yp) { - if (!renderer) return; - - - File fp; - fp=SD.open(file,FILE_READ); - if (!fp) return; - uint16_t xsize; - fp.read((uint8_t*)&xsize,2); - uint16_t ysize; - fp.read((uint8_t*)&ysize,2); - -#if 1 -#define XBUFF 128 - uint16_t xdiv=xsize/XBUFF; - renderer->setAddrWindow(xp,yp,xp+xsize,yp+ysize); - for(int16_t j=0; j=2) renderer->pushColors(rgb,len/2,true); - } - OsWatchLoop(); - } - renderer->setAddrWindow(0,0,0,0); -#else - for(int16_t j=0; jwritePixel(xp+i,yp,rgb); - } - delay(0); - OsWatchLoop(); - yp++; - } -#endif - fp.close(); -} -#endif - -#ifdef USE_AWATCH -#define MINUTE_REDUCT 4 - -#ifndef pi -#define pi 3.14159265359 -#endif - - -void DrawAClock(uint16_t rad) { - if (!renderer) return; - float frad=rad; - uint16_t hred=frad/3.0; - renderer->fillCircle(disp_xpos, disp_ypos, rad, bg_color); - renderer->drawCircle(disp_xpos, disp_ypos, rad, fg_color); - renderer->fillCircle(disp_xpos, disp_ypos, 4, fg_color); - for (uint8_t count=0; count<60; count+=5) { - float p1=((float)count*(pi/30)-(pi/2)); - uint8_t len; - if ((count%15)==0) { - len=4; - } else { - len=2; - } - renderer->writeLine(disp_xpos+((float)(rad-len)*cosf(p1)), disp_ypos+((float)(rad-len)*sinf(p1)), disp_xpos+(frad*cosf(p1)), disp_ypos+(frad*sinf(p1)), fg_color); - } - - - float hour=((float)RtcTime.hour*60.0+(float)RtcTime.minute)/60.0; - float temp=(hour*(pi/6.0)-(pi/2.0)); - renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-hred)*cosf(temp),disp_ypos+(frad-hred)*sinf(temp), fg_color); - - - temp=((float)RtcTime.minute*(pi/30.0)-(pi/2.0)); - renderer->writeLine(disp_xpos, disp_ypos,disp_xpos+(frad-MINUTE_REDUCT)*cosf(temp),disp_ypos+(frad-MINUTE_REDUCT)*sinf(temp), fg_color); -} -#endif - - -#ifdef USE_GRAPH - -typedef union { - uint8_t data; - struct { - uint8_t overlay : 1; - uint8_t draw : 1; - uint8_t nu3 : 1; - uint8_t nu4 : 1; - uint8_t nu5 : 1; - uint8_t nu6 : 1; - uint8_t nu7 : 1; - uint8_t nu8 : 1; - }; -} GFLAGS; - -struct GRAPH { - uint16_t xp; - uint16_t yp; - uint16_t xs; - uint16_t ys; - float ymin; - float ymax; - float range; - uint32_t x_time; - uint32_t last_ms; - uint32_t last_ms_redrawn; - int16_t decimation; - uint16_t dcnt; - uint32_t summ; - uint16_t xcnt; - uint8_t *values; - uint8_t xticks; - uint8_t yticks; - uint8_t last_val; - uint8_t color_index; - GFLAGS flags; -}; - - -struct GRAPH *graph[NUM_GRAPHS]; - -#define TICKLEN 4 -void ClrGraph(uint16_t num) { - struct GRAPH *gp=graph[num]; - - uint16_t xticks=gp->xticks; - uint16_t yticks=gp->yticks; - uint16_t count; - - - if (gp->flags.overlay) return; - - renderer->fillRect(gp->xp+1,gp->yp+1,gp->xs-2,gp->ys-2,bg_color); - - if (xticks) { - float cxp=gp->xp,xd=(float)gp->xs/(float)xticks; - for (count=0; countwriteFastVLine(cxp,gp->yp+gp->ys-TICKLEN,TICKLEN,fg_color); - cxp+=xd; - } - } - if (yticks) { - if (gp->ymin<0 && gp->ymax>0) { - - float cxp=0; - float czp=gp->yp+(gp->ymax/gp->range); - while (cxpxs) { - renderer->writeFastHLine(gp->xp+cxp,czp,2,fg_color); - cxp+=6.0; - } - - float cyp=0,yd=gp->ys/yticks; - for (count=0; countgp->yp) { - renderer->writeFastHLine(gp->xp,czp-cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp-cyp,TICKLEN,fg_color); - } - if ((czp+cyp)<(gp->yp+gp->ys)) { - renderer->writeFastHLine(gp->xp,czp+cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,czp+cyp,TICKLEN,fg_color); - } - cyp+=yd; - } - } else { - float cyp=gp->yp,yd=gp->ys/yticks; - for (count=0; countwriteFastHLine(gp->xp,cyp,TICKLEN,fg_color); - renderer->writeFastHLine(gp->xp+gp->xs-TICKLEN,cyp,TICKLEN,fg_color); - cyp+=yd; - } - } - } -} - - -void DefineGraph(uint16_t num,uint16_t xp,uint16_t yp,int16_t xs,uint16_t ys,int16_t dec,float ymin, float ymax,uint8_t icol) { - if (!renderer) return; - uint8_t rflg=0; - if (xs<0) { - rflg=1; - xs=abs(xs); - } - struct GRAPH *gp; - uint16_t count; - uint16_t index=num%NUM_GRAPHS; - if (!graph[index]) { - gp=(struct GRAPH*)calloc(sizeof(struct GRAPH),1); - if (!gp) return; - graph[index]=gp; - } else { - gp=graph[index]; - if (rflg) { - RedrawGraph(index,1); - return; - } - } - - - gp->xticks=(num>>4)&0x3f; - gp->yticks=(num>>10)&0x3f; - gp->xp=xp; - gp->yp=yp; - gp->xs=xs; - gp->ys=ys; - if (!dec) dec=1; - gp->decimation=dec; - if (dec>0) { - - gp->x_time=((float)dec*60000.0)/(float)xs; - gp->last_ms=millis()+gp->x_time; - } - gp->ymin=ymin; - gp->ymax=ymax; - gp->range=(ymax-ymin)/ys; - gp->xcnt=0; - gp->dcnt=0; - gp->summ=0; - if (gp->values) free(gp->values); - gp->values=(uint8_t*) calloc(1,xs+2); - if (!gp->values) { - free(gp); - graph[index]=0; - return; - } - - gp->values[0]=0; - - gp->last_ms_redrawn=millis(); - - if (!icol) icol=1; - gp->color_index=icol; - gp->flags.overlay=0; - gp->flags.draw=1; - - - if (index>0) { - for (uint8_t count=0; countxp==gp1->xp) && (gp->yp==gp1->yp)) { - gp->flags.overlay=1; - break; - } - } - } - } - - - renderer->drawRect(xp,yp,xs,ys,fg_color); - - ClrGraph(index); - -} - - -void DisplayCheckGraph() { - int16_t count; - struct GRAPH *gp; - for (count=0;countdecimation>0) { - - while (millis()>gp->last_ms) { - gp->last_ms+=gp->x_time; - uint8_t val; - if (gp->dcnt) { - val=gp->summ/gp->dcnt; - gp->dcnt=0; - gp->summ=0; - gp->last_val=val; - } else { - val=gp->last_val; - } - AddGraph(count,val); - } - } - } - } -} - - -#if defined(USE_SCRIPT_FATFS) && defined(USE_SCRIPT) -#include - -void Save_graph(uint8_t num, char *path) { - if (!renderer) return; - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - File fp; - SD.remove(path); - fp=SD.open(path,FILE_WRITE); - if (!fp) return; - char str[32]; - sprintf_P(str,PSTR("%d\t%d\t%d\t"),gp->xcnt,gp->xs,gp->ys); - fp.print(str); - dtostrfd(gp->ymin,2,str); - fp.print(str); - fp.print("\t"); - dtostrfd(gp->ymax,2,str); - fp.print(str); - fp.print("\t"); - for (uint32_t count=0;countxs;count++) { - dtostrfd(gp->values[count],0,str); - fp.print(str); - fp.print("\t"); - } - fp.print("\n"); - fp.close(); -} -void Restore_graph(uint8_t num, char *path) { - if (!renderer) return; - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - File fp; - fp=SD.open(path,FILE_READ); - if (!fp) return; - char vbuff[32]; - char *cp=vbuff; - uint8_t buf[2]; - uint8_t findex=0; - - for (uint32_t count=0;count<=gp->xs+4;count++) { - cp=vbuff; - findex=0; - while (fp.available()) { - fp.read(buf,1); - if (buf[0]=='\t' || buf[0]==',' || buf[0]=='\n' || buf[0]=='\r') { - break; - } else { - *cp++=buf[0]; - findex++; - if (findex>=sizeof(vbuff)-1) break; - } - } - *cp=0; - if (count<=4) { - if (count==0) gp->xcnt=atoi(vbuff); - } else { - gp->values[count-5]=atoi(vbuff); - } - } - fp.close(); - RedrawGraph(num,1); -} -#endif - -void RedrawGraph(uint8_t num, uint8_t flags) { - uint16_t index=num%NUM_GRAPHS; - struct GRAPH *gp=graph[index]; - if (!gp) return; - if (!flags) { - gp->flags.draw=0; - return; - } - if (!renderer) return; - - gp->flags.draw=1; - uint16_t linecol=fg_color; - - if (color_type==COLOR_COLOR) { - linecol=renderer->GetColorFromIndex(gp->color_index); - } - - if (!gp->flags.overlay) { - - renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); - - ClrGraph(index); - } - - for (uint16_t count=0;countxs-1;count++) { - renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); - } -} - - -void AddGraph(uint8_t num,uint8_t val) { - struct GRAPH *gp=graph[num]; - if (!renderer) return; - - uint16_t linecol=fg_color; - if (color_type==COLOR_COLOR) { - linecol=renderer->GetColorFromIndex(gp->color_index); - } - gp->xcnt++; - if (gp->xcnt>gp->xs) { - gp->xcnt=gp->xs; - int16_t count; - - for (count=0;countxs-1;count++) { - gp->values[count]=gp->values[count+1]; - } - gp->values[gp->xcnt-1]=val; - - if (!gp->flags.draw) return; - - - if (millis()-gp->last_ms_redrawn>1000) { - gp->last_ms_redrawn=millis(); - - if (!gp->flags.overlay) { - - renderer->drawRect(gp->xp,gp->yp,gp->xs,gp->ys,fg_color); - - ClrGraph(num); - } - - for (count=0;countxs-1;count++) { - renderer->writeLine(gp->xp+count,gp->yp+gp->ys-gp->values[count]-1,gp->xp+count+1,gp->yp+gp->ys-gp->values[count+1]-1,linecol); - } - } - } else { - - gp->values[gp->xcnt]=val; - if (!gp->flags.draw) return; - renderer->writeLine(gp->xp+gp->xcnt-1,gp->yp+gp->ys-gp->values[gp->xcnt-1]-1,gp->xp+gp->xcnt,gp->yp+gp->ys-gp->values[gp->xcnt]-1,linecol); - } -} - - - -void AddValue(uint8_t num,float fval) { - - num=num%NUM_GRAPHS; - struct GRAPH *gp=graph[num]; - if (!gp) return; - - if (fval>gp->ymax) fval=gp->ymax; - if (fvalymin) fval=gp->ymin; - - int16_t val; - val=(fval-gp->ymin)/gp->range; - - if (val>gp->ys-1) val=gp->ys-1; - if (val<0) val=0; - - - gp->summ+=val; - gp->dcnt++; - - - if (gp->decimation<0) { - if (gp->dcnt>=-gp->decimation) { - gp->dcnt=0; - - val=gp->summ/-gp->decimation; - gp->summ=0; - - AddGraph(num,val); - } - } -} -#endif - - - - - -bool Xdrv13(uint8_t function) -{ - bool result = false; - - if ((i2c_flg || spi_flg || soft_spi_flg) && XdspPresent()) { - switch (function) { - case FUNC_PRE_INIT: - DisplayInitDriver(); -#ifdef USE_GRAPH - for (uint8_t count=0;count - -TasmotaSerial *MP3Player; - - - - - -#define D_CMND_MP3 "MP3" - -const char S_JSON_MP3_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MP3 "%s\":%d}"; -const char S_JSON_MP3_COMMAND[] PROGMEM = "{\"" D_CMND_MP3 "%s\"}"; -const char kMP3_Commands[] PROGMEM = "Track|Play|Pause|Stop|Volume|EQ|Device|Reset|DAC"; - - - - - -enum MP3_Commands { - CMND_MP3_TRACK, - CMND_MP3_PLAY, - CMND_MP3_PAUSE, - CMND_MP3_STOP, - CMND_MP3_VOLUME, - CMND_MP3_EQ, - CMND_MP3_DEVICE, - CMND_MP3_RESET, - CMND_MP3_DAC }; - - - - - - -#define MP3_CMD_RESET_VALUE 0 - -#define MP3_CMD_TRACK 0x03 -#define MP3_CMD_PLAY 0x0d -#define MP3_CMD_PAUSE 0x0e -#define MP3_CMD_STOP 0x16 -#define MP3_CMD_VOLUME 0x06 -#define MP3_CMD_EQ 0x07 -#define MP3_CMD_DEVICE 0x09 -#define MP3_CMD_RESET 0x0C -#define MP3_CMD_DAC 0x1A - - - - - - -uint16_t MP3_Checksum(uint8_t *array) -{ - uint16_t checksum = 0; - for (uint32_t i = 0; i < 6; i++) { - checksum += array[i]; - } - checksum = checksum^0xffff; - return (checksum+1); -} - - - - - - -void MP3PlayerInit(void) { - MP3Player = new TasmotaSerial(-1, pin[GPIO_MP3_DFR562]); - - if (MP3Player->begin(9600)) { - MP3Player->flush(); - delay(1000); - MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); - delay(3000); - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); - } - return; -} -# 159 "S:/Development/Tasmota/tasmota/xdrv_14_mp3.ino" -void MP3_CMD(uint8_t mp3cmd,uint16_t val) { - uint8_t i = 0; - uint8_t cmd[10] = {0x7e,0xff,6,0,0,0,0,0,0,0xef}; - cmd[3] = mp3cmd; - cmd[4] = 0; - cmd[5] = val>>8; - cmd[6] = val; - uint16_t chks = MP3_Checksum(&cmd[1]); - cmd[7] = chks>>8; - cmd[8] = chks; - MP3Player->write(cmd, sizeof(cmd)); - delay(1000); - if (mp3cmd == MP3_CMD_RESET) { - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); - } - return; -} - - - - - -bool MP3PlayerCmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_MP3); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MP3), disp_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMP3_Commands); - - switch (command_code) { - case CMND_MP3_TRACK: - case CMND_MP3_VOLUME: - case CMND_MP3_EQ: - case CMND_MP3_DEVICE: - case CMND_MP3_DAC: - - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_MP3_TRACK) { MP3_CMD(MP3_CMD_TRACK, XdrvMailbox.payload); } - if (command_code == CMND_MP3_VOLUME) { MP3_CMD(MP3_CMD_VOLUME, XdrvMailbox.payload * 30 / 100); } - if (command_code == CMND_MP3_EQ) { MP3_CMD(MP3_CMD_EQ, XdrvMailbox.payload); } - if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } - if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } - } - Response_P(S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_MP3_PLAY: - case CMND_MP3_PAUSE: - case CMND_MP3_STOP: - case CMND_MP3_RESET: - - if (command_code == CMND_MP3_PLAY) { MP3_CMD(MP3_CMD_PLAY, 0); } - if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } - if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } - if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } - Response_P(S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); - break; - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - - -bool Xdrv14(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_MP3_DFR562] < 99) { - switch (function) { - case FUNC_PRE_INIT: - MP3PlayerInit(); - break; - case FUNC_COMMAND: - result = MP3PlayerCmd(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_15_pca9685.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_15_pca9685.ino" -#ifdef USE_I2C -#ifdef USE_PCA9685 - - - - - - -#define XDRV_15 15 -#define XI2C_01 1 - -#define PCA9685_REG_MODE1 0x00 -#define PCA9685_REG_LED0_ON_L 0x06 -#define PCA9685_REG_PRE_SCALE 0xFE - -#ifndef USE_PCA9685_ADDR - #define USE_PCA9685_ADDR 0x40 -#endif -#ifndef USE_PCA9685_FREQ - #define USE_PCA9685_FREQ 50 -#endif - -bool pca9685_detected = false; -uint16_t pca9685_freq = USE_PCA9685_FREQ; -uint16_t pca9685_pin_pwm_value[16]; - -void PCA9685_Detect(void) -{ - if (I2cActive(USE_PCA9685_ADDR)) { return; } - - uint8_t buffer; - if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x20); - if (I2cValidRead8(&buffer, USE_PCA9685_ADDR, PCA9685_REG_MODE1)) { - if (0x20 == buffer) { - pca9685_detected = true; - I2cSetActiveFound(USE_PCA9685_ADDR, "PCA9685"); - PCA9685_Reset(); - } - } - } -} - -void PCA9685_Reset(void) -{ - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, 0x80); - PCA9685_SetPWMfreq(USE_PCA9685_FREQ); - for (uint32_t pin=0;pin<16;pin++) { - PCA9685_SetPWM(pin,0,false); - pca9685_pin_pwm_value[pin] = 0; - } - Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); -} - -void PCA9685_SetPWMfreq(double freq) { - - - - - if (freq > 23 && freq < 1527) { - pca9685_freq=freq; - } else { - pca9685_freq=50; - } - uint8_t pre_scale_osc = round(25000000/(4096*pca9685_freq))-1; - if (1526 == pca9685_freq) pre_scale_osc=0xFF; - uint8_t current_mode1 = I2cRead8(USE_PCA9685_ADDR, PCA9685_REG_MODE1); - uint8_t sleep_mode1 = (current_mode1&0x7F) | 0x10; - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, sleep_mode1); - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_PRE_SCALE, pre_scale_osc); - I2cWrite8(USE_PCA9685_ADDR, PCA9685_REG_MODE1, current_mode1 | 0xA0); -} - -void PCA9685_SetPWM_Reg(uint8_t pin, uint16_t on, uint16_t off) { - uint8_t led_reg = PCA9685_REG_LED0_ON_L + 4 * pin; - uint32_t led_data = 0; - I2cWrite8(USE_PCA9685_ADDR, led_reg, on); - I2cWrite8(USE_PCA9685_ADDR, led_reg+1, (on >> 8)); - I2cWrite8(USE_PCA9685_ADDR, led_reg+2, off); - I2cWrite8(USE_PCA9685_ADDR, led_reg+3, (off >> 8)); -} - -void PCA9685_SetPWM(uint8_t pin, uint16_t pwm, bool inverted) { - if (4096 == pwm) { - PCA9685_SetPWM_Reg(pin, 4096, 0); - } else { - PCA9685_SetPWM_Reg(pin, 0, pwm); - } - pca9685_pin_pwm_value[pin] = pwm; -} - -bool PCA9685_Command(void) -{ - bool serviced = true; - bool validpin = false; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((new_freq >= 24) && (new_freq <= 1526)) { - PCA9685_SetPWMfreq(new_freq); - Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); - return serviced; - } - } else { - Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); - return serviced; - } - } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"PWM")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (paramcount > 2) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { - PCA9685_SetPWM(pin, 4096, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); - serviced = true; - return serviced; - } - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { - PCA9685_SetPWM(pin, 0, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); - serviced = true; - return serviced; - } - uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { - PCA9685_SetPWM(pin, pwm, false); - Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); - serviced = true; - return serviced; - } - } - } - } - return serviced; -} - -void PCA9685_OutputTelemetry(bool telemetry) -{ - ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq); - for (uint32_t pin=0;pin<16;pin++) { - ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); - } - ResponseAppend_P(PSTR("\"END\":1}}")); - if (telemetry) { - MqttPublishTeleSensor(); - } -} - -bool Xdrv15(uint8_t function) -{ - if (!I2cEnabled(XI2C_01)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - PCA9685_Detect(); - } - else if (pca9685_detected) { - switch (function) { - case FUNC_EVERY_SECOND: - if (tele_period == 0) { - PCA9685_OutputTelemetry(true); - } - break; - case FUNC_COMMAND_DRIVER: - if (XDRV_15 == XdrvMailbox.index) { - result = PCA9685_Command(); - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -#ifdef USE_LIGHT -#ifdef USE_TUYA_MCU - -#define XDRV_16 16 -#define XNRG_16 16 - -#ifndef TUYA_DIMMER_ID -#define TUYA_DIMMER_ID 0 -#endif - -#define TUYA_CMD_HEARTBEAT 0x00 -#define TUYA_CMD_QUERY_PRODUCT 0x01 -#define TUYA_CMD_MCU_CONF 0x02 -#define TUYA_CMD_WIFI_STATE 0x03 -#define TUYA_CMD_WIFI_RESET 0x04 -#define TUYA_CMD_WIFI_SELECT 0x05 -#define TUYA_CMD_SET_DP 0x06 -#define TUYA_CMD_STATE 0x07 -#define TUYA_CMD_QUERY_STATE 0x08 - -#define TUYA_LOW_POWER_CMD_WIFI_STATE 0x02 -#define TUYA_LOW_POWER_CMD_WIFI_RESET 0x03 -#define TUYA_LOW_POWER_CMD_WIFI_CONFIG 0x04 -#define TUYA_LOW_POWER_CMD_STATE 0x05 - -#define TUYA_TYPE_BOOL 0x01 -#define TUYA_TYPE_VALUE 0x02 -#define TUYA_TYPE_STRING 0x03 -#define TUYA_TYPE_ENUM 0x04 - -#define TUYA_BUFFER_SIZE 256 - -#include - -TasmotaSerial *TuyaSerial = nullptr; - -struct TUYA { - uint16_t new_dim = 0; - bool ignore_dim = false; - uint8_t cmd_status = 0; - uint8_t cmd_checksum = 0; - uint8_t data_len = 0; - uint8_t wifi_state = -2; - uint8_t heartbeat_timer = 0; -#ifdef USE_ENERGY_SENSOR - uint32_t lastPowerCheckTime = 0; -#endif - char *buffer = nullptr; - int byte_counter = 0; - bool low_power_mode = false; - bool send_success_next_second = false; -} Tuya; - - -enum TuyaSupportedFunctions { - TUYA_MCU_FUNC_NONE, - TUYA_MCU_FUNC_SWT1 = 1, - TUYA_MCU_FUNC_SWT2, - TUYA_MCU_FUNC_SWT3, - TUYA_MCU_FUNC_SWT4, - TUYA_MCU_FUNC_REL1 = 11, - TUYA_MCU_FUNC_REL2, - TUYA_MCU_FUNC_REL3, - TUYA_MCU_FUNC_REL4, - TUYA_MCU_FUNC_REL5, - TUYA_MCU_FUNC_REL6, - TUYA_MCU_FUNC_REL7, - TUYA_MCU_FUNC_REL8, - TUYA_MCU_FUNC_DIMMER = 21, - TUYA_MCU_FUNC_POWER = 31, - TUYA_MCU_FUNC_CURRENT, - TUYA_MCU_FUNC_VOLTAGE, - TUYA_MCU_FUNC_BATTERY_STATE, - TUYA_MCU_FUNC_BATTERY_PERCENTAGE, - TUYA_MCU_FUNC_REL1_INV = 41, - TUYA_MCU_FUNC_REL2_INV, - TUYA_MCU_FUNC_REL3_INV, - TUYA_MCU_FUNC_REL4_INV, - TUYA_MCU_FUNC_REL5_INV, - TUYA_MCU_FUNC_REL6_INV, - TUYA_MCU_FUNC_REL7_INV, - TUYA_MCU_FUNC_REL8_INV, - TUYA_MCU_FUNC_LOWPOWER_MODE = 51, - TUYA_MCU_FUNC_LAST = 255 -}; - -const char kTuyaCommand[] PROGMEM = "|" - D_CMND_TUYA_MCU "|" D_CMND_TUYA_MCU_SEND_STATE; - -void (* const TuyaCommand[])(void) PROGMEM = { - &CmndTuyaMcu, &CmndTuyaSend -}; -# 127 "S:/Development/Tasmota/tasmota/xdrv_16_tuyamcu.ino" -void CmndTuyaSend(void) { - if (XdrvMailbox.index > 4) { - return; - } - if (XdrvMailbox.index == 0) { - TuyaRequestState(); - } else { - if (XdrvMailbox.data_len > 0) { - char *p; - char *data; - uint8_t i = 0; - uint8_t dpId = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { - if ( i == 0) { - dpId = strtoul(str, nullptr, 0); - } else { - data = str; - } - i++; - } - - if (1 == XdrvMailbox.index) { - TuyaSendBool(dpId, strtoul(data, nullptr, 0)); - } else if (2 == XdrvMailbox.index) { - TuyaSendValue(dpId, strtoull(data, nullptr, 0)); - } else if (3 == XdrvMailbox.index) { - TuyaSendString(dpId, data); - } else if (4 == XdrvMailbox.index) { - TuyaSendEnum(dpId, strtoul(data, nullptr, 0)); - } - } - } - ResponseCmndDone(); -} - - - - - - - -void CmndTuyaMcu(void) { - if (XdrvMailbox.data_len > 0) { - char *p; - uint8_t i = 0; - uint8_t parm[3] = { 0 }; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) { - parm[i] = strtoul(str, nullptr, 0); - i++; - } - - if (TuyaFuncIdValid(parm[0])) { - TuyaAddMcuFunc(parm[0], parm[1]); - restart_flag = 2; - } else { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]); - } - - } - - Response_P(PSTR("{\"" D_CMND_TUYA_MCU "\":[")); - bool added = false; - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].fnid != 0) { - if (added) { - ResponseAppend_P(PSTR(",")); - } - ResponseAppend_P(PSTR("{\"fnId\":%d,\"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid); - added = true; - } - } - ResponseAppend_P(PSTR("]}")); -} - - - - - -void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) { - bool added = false; - - if (fnId == 0 || dpId == 0) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) { - Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; - Settings.tuya_fnid_map[i].dpid = 0; - break; - } - } - } else { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) { - if (!added) { - Settings.tuya_fnid_map[i].fnid = fnId; - Settings.tuya_fnid_map[i].dpid = dpId; - added = true; - } else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { - Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE; - Settings.tuya_fnid_map[i].dpid = 0; - } - } - } - } - UpdateDevices(); -} - -void UpdateDevices() { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - uint8_t fnId = Settings.tuya_fnid_map[i].fnid; - if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) { - - if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1); - } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { - bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV); - } - - } - } -} - -inline bool TuyaFuncIdValid(uint8_t fnId) { - return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) || - (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) || - fnId == TUYA_MCU_FUNC_DIMMER || - (fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) || - (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) || - (fnId == TUYA_MCU_FUNC_LOWPOWER_MODE); -} - -uint8_t TuyaGetFuncId(uint8_t dpid) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].dpid == dpid) { - return Settings.tuya_fnid_map[i].fnid; - } - } - return TUYA_MCU_FUNC_NONE; -} - -uint8_t TuyaGetDpId(uint8_t fnId) { - for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) { - if (Settings.tuya_fnid_map[i].fnid == fnId) { - return Settings.tuya_fnid_map[i].dpid; - } - } - return 0; -} - -void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0) -{ - uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF)); - TuyaSerial->write(0x55); - TuyaSerial->write(0xAA); - TuyaSerial->write((uint8_t)0x00); - TuyaSerial->write(cmd); - TuyaSerial->write(payload_len >> 8); - TuyaSerial->write(payload_len & 0xFF); - snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send \"55aa00%02x%02x%02x"), cmd, payload_len >> 8, payload_len & 0xFF); - for (uint32_t i = 0; i < payload_len; ++i) { - TuyaSerial->write(payload[i]); - checksum += payload[i]; - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, payload[i]); - } - TuyaSerial->write(checksum); - TuyaSerial->flush(); - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x\""), log_data, checksum); - AddLog(LOG_LEVEL_DEBUG); -} - -void TuyaSendState(uint8_t id, uint8_t type, uint8_t* value) -{ - uint16_t payload_len = 4; - uint8_t payload_buffer[8]; - payload_buffer[0] = id; - payload_buffer[1] = type; - switch (type) { - case TUYA_TYPE_BOOL: - case TUYA_TYPE_ENUM: - payload_len += 1; - payload_buffer[2] = 0x00; - payload_buffer[3] = 0x01; - payload_buffer[4] = value[0]; - break; - case TUYA_TYPE_VALUE: - payload_len += 4; - payload_buffer[2] = 0x00; - payload_buffer[3] = 0x04; - payload_buffer[4] = value[3]; - payload_buffer[5] = value[2]; - payload_buffer[6] = value[1]; - payload_buffer[7] = value[0]; - break; - - } - - TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); -} - -void TuyaSendBool(uint8_t id, bool value) -{ - TuyaSendState(id, TUYA_TYPE_BOOL, (uint8_t*)&value); -} - -void TuyaSendValue(uint8_t id, uint32_t value) -{ - TuyaSendState(id, TUYA_TYPE_VALUE, (uint8_t*)(&value)); -} - -void TuyaSendEnum(uint8_t id, uint32_t value) -{ - TuyaSendState(id, TUYA_TYPE_ENUM, (uint8_t*)(&value)); -} - -void TuyaSendString(uint8_t id, char data[]) { - - uint16_t len = strlen(data); - uint16_t payload_len = 4 + len; - uint8_t payload_buffer[payload_len]; - payload_buffer[0] = id; - payload_buffer[1] = TUYA_TYPE_STRING; - payload_buffer[2] = len >> 8; - payload_buffer[3] = len & 0xFF; - - for (uint16_t i = 0; i < len; i++) { - payload_buffer[4+i] = data[i]; - } - - TuyaSendCmd(TUYA_CMD_SET_DP, payload_buffer, payload_len); -} - -bool TuyaSetPower(void) -{ - bool status = false; - - uint8_t rpower = XdrvMailbox.index; - int16_t source = XdrvMailbox.payload; - - uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1 + active_device - 1); - if (dpid == 0) dpid = TuyaGetDpId(TUYA_MCU_FUNC_REL1_INV + active_device - 1); - - if (source != SRC_SWITCH && TuyaSerial) { - TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); - status = true; - } - return status; -} - -bool TuyaSetChannels(void) -{ - LightSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); - delay(20); - return true; -} - -void LightSerialDuty(uint16_t duty) -{ - uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER); - if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) { - duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); - if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } - if (Tuya.new_dim != duty) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); - TuyaSendValue(dpid, duty); - } - } else if (dpid > 0) { - Tuya.ignore_dim = false; - duty = changeUIntScale(duty, 0, 255, 0, Settings.dimmer_hw_max); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); - } -} - -void TuyaRequestState(void) -{ - if (TuyaSerial) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Read MCU state")); - - TuyaSendCmd(TUYA_CMD_QUERY_STATE); - } -} - -void TuyaResetWifi(void) -{ - if (!Settings.flag.button_restrict) { - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); - ExecuteCommand(scmnd, SRC_BUTTON); - } -} - -void TuyaProcessStatePacket(void) { - char scmnd[20]; - uint8_t dpidStart = 6; - uint8_t fnId; - uint16_t dpDataLen; - - while (dpidStart + 4 < Tuya.byte_counter) { - dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - fnId = TuyaGetFuncId(Tuya.buffer[dpidStart]); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: fnId=%d is set for dpId=%d"), fnId, Tuya.buffer[dpidStart]); - - if (Tuya.buffer[dpidStart + 1] == 1) { - - if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off"); - if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], SRC_SWITCH); - } - } else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On"); - if (Tuya.buffer[dpidStart + 4] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) { - ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[dpidStart + 4] ^ 1, SRC_SWITCH); - } - } else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[dpidStart + 4], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1)); - - if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[dpidStart + 4]) { - SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[dpidStart + 4]); - SwitchHandler(1); - } - } - - } - else if (Tuya.buffer[dpidStart + 1] == 2) { - bool tuya_energy_enabled = (XNRG_16 == energy_flg); - uint16_t packetValue = Tuya.buffer[dpidStart + 6] << 8 | Tuya.buffer[dpidStart + 7]; - if (fnId == TUYA_MCU_FUNC_DIMMER) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), packetValue); - Tuya.new_dim = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); - if ((power || Settings.flag3.tuya_apply_o20) && - (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { - Tuya.ignore_dim = true; - - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - - #ifdef USE_ENERGY_SENSOR - else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_VOLTAGE) { - Energy.voltage[0] = (float)packetValue / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[dpidStart], packetValue); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_CURRENT) { - Energy.current[0] = (float)packetValue / 1000; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[dpidStart], packetValue); - } else if (tuya_energy_enabled && fnId == TUYA_MCU_FUNC_POWER) { - Energy.active_power[0] = (float)packetValue / 10; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[dpidStart], packetValue); - - if (Tuya.lastPowerCheckTime != 0 && Energy.active_power[0] > 0) { - Energy.kWhtoday += (float)Energy.active_power[0] * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36; - EnergyUpdateToday(); - } - Tuya.lastPowerCheckTime = Rtc.utc_time; - } - #endif - - } - - - dpidStart += dpDataLen + 4; - } -} - -void TuyaLowPowerModePacketProcess(void) { - switch (Tuya.buffer[3]) { - case TUYA_CMD_QUERY_PRODUCT: - TuyaHandleProductInfoPacket(); - TuyaSetWifiLed(); - break; - - case TUYA_LOW_POWER_CMD_STATE: - TuyaProcessStatePacket(); - Tuya.send_success_next_second = true; - break; - } - -} - -void TuyaHandleProductInfoPacket(void) { - uint16_t dataLength = Tuya.buffer[4] << 8 | Tuya.buffer[5]; - char *data = &Tuya.buffer[6]; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TYA: MCU Product ID: %.*s"), dataLength, data); -} - -void TuyaSendLowPowerSuccessIfNeeded(void) { - uint8_t success = 1; - - if (Tuya.send_success_next_second) { - TuyaSendCmd(TUYA_LOW_POWER_CMD_STATE, &success, 1); - Tuya.send_success_next_second = false; - } -} - -void TuyaNormalPowerModePacketProcess(void) -{ - switch (Tuya.buffer[3]) { - case TUYA_CMD_QUERY_PRODUCT: - TuyaHandleProductInfoPacket(); - TuyaSendCmd(TUYA_CMD_MCU_CONF); - break; - - case TUYA_CMD_HEARTBEAT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); - if (Tuya.buffer[6] == 0) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Detected MCU restart")); - Tuya.wifi_state = -2; - } - break; - - case TUYA_CMD_STATE: - TuyaProcessStatePacket(); - break; - - case TUYA_CMD_WIFI_RESET: - case TUYA_CMD_WIFI_SELECT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi Reset")); - TuyaResetWifi(); - break; - - case TUYA_CMD_WIFI_STATE: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX WiFi LED set ACK")); - Tuya.wifi_state = TuyaGetTuyaWifiState(); - break; - - case TUYA_CMD_MCU_CONF: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]); - - if (Tuya.buffer[5] == 2) { - uint8_t led1_gpio = Tuya.buffer[6]; - uint8_t key1_gpio = Tuya.buffer[7]; - bool key1_set = false; - bool led1_set = false; - for (uint32_t i = 0; i < sizeof(Settings.my_gp); i++) { - if (Settings.my_gp.io[i] == GPIO_LED1) led1_set = true; - else if (Settings.my_gp.io[i] == GPIO_KEY1) key1_set = true; - } - if (!Settings.my_gp.io[led1_gpio] && !led1_set) { - Settings.my_gp.io[led1_gpio] = GPIO_LED1; - restart_flag = 2; - } - if (!Settings.my_gp.io[key1_gpio] && !key1_set) { - Settings.my_gp.io[key1_gpio] = GPIO_KEY1; - restart_flag = 2; - } - } - TuyaRequestState(); - break; - - default: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX unknown command")); - } -} - - - - - -bool TuyaModuleSelected(void) -{ - if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { - pin[GPIO_TUYA_TX] = 1; - pin[GPIO_TUYA_RX] = 3; - Settings.my_gp.io[1] = GPIO_TUYA_TX; - Settings.my_gp.io[3] = GPIO_TUYA_RX; - restart_flag = 2; - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) { - TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID); - } - - bool relaySet = false; - - for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) { - if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || - (Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { - relaySet = true; - devices_present++; - } - } - - if (!relaySet) { - TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); - devices_present++; - SettingsSaveAll(); - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) { - light_type = LT_SERIAL1; - } else { - light_type = LT_BASIC; - } - - if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) { - Tuya.low_power_mode = true; - Settings.flag3.fast_power_cycle_disable = true; - } - - UpdateDevices(); - return true; -} - -void TuyaInit(void) -{ - Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); - if (Tuya.buffer != nullptr) { - TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); - if (TuyaSerial->begin(9600)) { - if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Request MCU configuration")); - - TuyaSendCmd(TUYA_CMD_QUERY_PRODUCT); - } - } - Tuya.heartbeat_timer = 0; -} - -void TuyaSerialInput(void) -{ - while (TuyaSerial->available()) { - yield(); - uint8_t serial_in_byte = TuyaSerial->read(); - - if (serial_in_byte == 0x55) { - Tuya.cmd_status = 1; - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - Tuya.cmd_checksum += serial_in_byte; - } - else if (Tuya.cmd_status == 1 && serial_in_byte == 0xAA) { - Tuya.cmd_status = 2; - - Tuya.byte_counter = 0; - Tuya.buffer[Tuya.byte_counter++] = 0x55; - Tuya.buffer[Tuya.byte_counter++] = 0xAA; - Tuya.cmd_checksum = 0xFF; - } - else if (Tuya.cmd_status == 2) { - if (Tuya.byte_counter == 5) { - Tuya.cmd_status = 3; - Tuya.data_len = serial_in_byte; - } - Tuya.cmd_checksum += serial_in_byte; - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - } - else if ((Tuya.cmd_status == 3) && (Tuya.byte_counter == (6 + Tuya.data_len)) && (Tuya.cmd_checksum == serial_in_byte)) { - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - - char hex_char[(Tuya.byte_counter * 2) + 2]; - uint16_t len = Tuya.buffer[4] << 8 | Tuya.buffer[5]; - Response_P(PSTR("{\"" D_JSON_TUYA_MCU_RECEIVED "\":{\"Data\":\"%s\",\"Cmnd\":%d"), ToHex_P((unsigned char*)Tuya.buffer, Tuya.byte_counter, hex_char, sizeof(hex_char)), Tuya.buffer[3]); - - if (len > 0) { - ResponseAppend_P(PSTR(",\"CmndData\":\"%s\""), ToHex_P((unsigned char*)&Tuya.buffer[6], len, hex_char, sizeof(hex_char))); - if (TUYA_CMD_STATE == Tuya.buffer[3]) { - - - uint8_t dpidStart = 6; - while (dpidStart + 4 < Tuya.byte_counter) { - uint8_t dpId = Tuya.buffer[dpidStart]; - uint8_t dpDataType = Tuya.buffer[dpidStart + 1]; - uint16_t dpDataLen = Tuya.buffer[dpidStart + 2] << 8 | Tuya.buffer[dpidStart + 3]; - const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4]; - const char *dpHexData = ToHex_P(dpData, dpDataLen, hex_char, sizeof(hex_char)); - - if (TUYA_CMD_STATE == Tuya.buffer[3]) { - ResponseAppend_P(PSTR(",\"DpType%uId%u\":"), dpDataType, dpId); - if (TUYA_TYPE_BOOL == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("%u"), dpData[0]); - } else if (TUYA_TYPE_VALUE == dpDataType && dpDataLen == 4) { - uint32_t dpValue = (uint32_t)dpData[0] << 24 | (uint32_t)dpData[1] << 16 | (uint32_t)dpData[2] << 8 | (uint32_t)dpData[3] << 0; - ResponseAppend_P(PSTR("%u"), dpValue); - } else if (TUYA_TYPE_STRING == dpDataType) { - ResponseAppend_P(PSTR("\"%.*s\""), dpDataLen, dpData); - } else if (TUYA_TYPE_ENUM == dpDataType && dpDataLen == 1) { - ResponseAppend_P(PSTR("%u"), dpData[0]); - } else { - ResponseAppend_P(PSTR("\"0x%s\""), dpHexData); - } - } - - ResponseAppend_P(PSTR(",\"%d\":{\"DpId\":%d,\"DpIdType\":%d,\"DpIdData\":\"%s\""), dpId, dpId, dpDataType, dpHexData); - if (TUYA_TYPE_STRING == dpDataType) { - ResponseAppend_P(PSTR(",\"Type3Data\":\"%.*s\""), dpDataLen, dpData); - } - ResponseAppend_P(PSTR("}")); - dpidStart += dpDataLen + 4; - } - } - } - - ResponseAppend_P(PSTR("}}")); - - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED)); - } else { - AddLog_P(LOG_LEVEL_DEBUG, mqtt_data); - } - XdrvRulesProcess(); - - if (!Tuya.low_power_mode) { - TuyaNormalPowerModePacketProcess(); - } else { - TuyaLowPowerModePacketProcess(); - } - - Tuya.byte_counter = 0; - Tuya.cmd_status = 0; - Tuya.cmd_checksum = 0; - Tuya.data_len = 0; - } - else if (Tuya.byte_counter < TUYA_BUFFER_SIZE -1) { - Tuya.buffer[Tuya.byte_counter++] = serial_in_byte; - Tuya.cmd_checksum += serial_in_byte; - } else { - Tuya.byte_counter = 0; - Tuya.cmd_status = 0; - Tuya.cmd_checksum = 0; - Tuya.data_len = 0; - } - } -} - -bool TuyaButtonPressed(void) -{ - if (!XdrvMailbox.index && ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == Button.last_state[XdrvMailbox.index]))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Reset GPIO triggered")); - TuyaResetWifi(); - return true; - } - return false; -} - -uint8_t TuyaGetTuyaWifiState(void) { - - uint8_t wifi_state = 0x02; - switch(WifiState()){ - case WIFI_MANAGER: - wifi_state = 0x01; - break; - case WIFI_RESTART: - wifi_state = 0x03; - break; - } - - if (MqttIsConnected()) { - wifi_state = 0x04; - } - - return wifi_state; -} - -void TuyaSetWifiLed(void) -{ - Tuya.wifi_state = TuyaGetTuyaWifiState(); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Set WiFi LED %d (%d)"), Tuya.wifi_state, WifiState()); - - if (Tuya.low_power_mode) { - TuyaSendCmd(TUYA_LOW_POWER_CMD_WIFI_STATE, &Tuya.wifi_state, 1); - } else { - TuyaSendCmd(TUYA_CMD_WIFI_STATE, &Tuya.wifi_state, 1); - } -} - -#ifdef USE_ENERGY_SENSOR - - - - -bool Xnrg16(uint8_t function) -{ - bool result = false; - - if (TUYA_DIMMER == my_module_type) { - if (FUNC_PRE_INIT == function) { - if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) { - if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) { - Energy.current_available = false; - } - if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) { - Energy.voltage_available = false; - } - energy_flg = XNRG_16; - } - } - } - return result; -} -#endif - - - - - -bool Xdrv16(uint8_t function) -{ - bool result = false; - - if (TUYA_DIMMER == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (TuyaSerial) { TuyaSerialInput(); } - break; - case FUNC_MODULE_INIT: - result = TuyaModuleSelected(); - break; - case FUNC_PRE_INIT: - TuyaInit(); - break; - case FUNC_SET_DEVICE_POWER: - result = TuyaSetPower(); - break; - case FUNC_BUTTON_PRESSED: - result = TuyaButtonPressed(); - break; - case FUNC_EVERY_SECOND: - if (TuyaSerial && Tuya.wifi_state != TuyaGetTuyaWifiState()) { TuyaSetWifiLed(); } - if (!Tuya.low_power_mode) { - Tuya.heartbeat_timer++; - if (Tuya.heartbeat_timer > 10) { - Tuya.heartbeat_timer = 0; - TuyaSendCmd(TUYA_CMD_HEARTBEAT); - } - } else { - TuyaSendLowPowerSuccessIfNeeded(); - } - break; - case FUNC_SET_CHANNELS: - result = TuyaSetChannels(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kTuyaCommand, TuyaCommand); - break; - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_17_rcswitch.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_17_rcswitch.ino" -#ifdef USE_RC_SWITCH - - - - -#define XDRV_17 17 - -#define D_JSON_RF_PROTOCOL "Protocol" -#define D_JSON_RF_BITS "Bits" -#define D_JSON_RF_DATA "Data" - -#define D_CMND_RFSEND "RFSend" -#define D_JSON_RF_PULSE "Pulse" -#define D_JSON_RF_REPEAT "Repeat" - -const char kRfSendCommands[] PROGMEM = "|" - D_CMND_RFSEND; - -void (* const RfSendCommand[])(void) PROGMEM = { - &CmndRfSend }; - -#include - -RCSwitch mySwitch = RCSwitch(); - -#define RF_TIME_AVOID_DUPLICATE 1000 - -uint32_t rf_lasttime = 0; - -void RfReceiveCheck(void) -{ - if (mySwitch.available()) { - - unsigned long data = mySwitch.getReceivedValue(); - unsigned int bits = mySwitch.getReceivedBitlength(); - int protocol = mySwitch.getReceivedProtocol(); - int delay = mySwitch.getReceivedDelay(); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFR: Data 0x%lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay); - - uint32_t now = millis(); - if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) { - rf_lasttime = now; - - char stemp[16]; - if (Settings.flag.rf_receive_decimal) { - snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data); - } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); - } - ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), - stemp, bits, protocol, delay); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); - XdrvRulesProcess(); -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_COUNT, data); -#endif - } - mySwitch.resetAvailable(); - } -} - -void RfInit(void) -{ - if (pin[GPIO_RFSEND] < 99) { - mySwitch.enableTransmit(pin[GPIO_RFSEND]); - } - if (pin[GPIO_RFRECV] < 99) { - pinMode( pin[GPIO_RFRECV], INPUT); - mySwitch.enableReceive(pin[GPIO_RFRECV]); - } -} - - - - - -void CmndRfSend(void) -{ - bool error = false; - - if (XdrvMailbox.data_len) { - unsigned long data = 0; - unsigned int bits = 24; - int protocol = 1; - int repeat = 10; - int pulse = 350; - - char dataBufUc[XdrvMailbox.data_len + 1]; - UpperCase(dataBufUc, XdrvMailbox.data); - StaticJsonBuffer<150> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); - if (root.success()) { - - char parm_uc[10]; - data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], nullptr, 0); - bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; - protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; - repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; - pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))]; - } else { - - char *p; - uint8_t i = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(nullptr, ", ", &p)) { - switch (i++) { - case 0: - data = strtoul(str, nullptr, 0); - break; - case 1: - bits = atoi(str); - break; - case 2: - protocol = atoi(str); - break; - case 3: - repeat = atoi(str); - break; - case 4: - pulse = atoi(str); - } - } - } - - if (!protocol) { protocol = 1; } - mySwitch.setProtocol(protocol); - if (!pulse) { pulse = 350; } - mySwitch.setPulseLength(pulse); - if (!repeat) { repeat = 10; } - mySwitch.setRepeatTransmit(repeat); - if (!bits) { bits = 24; } - if (data) { - mySwitch.send(data, bits); - ResponseCmndDone(); - } else { - error = true; - } - } else { - error = true; - } - if (error) { - Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); - } -} - - - - - -bool Xdrv17(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (pin[GPIO_RFRECV] < 99) { - RfReceiveCheck(); - } - break; - case FUNC_COMMAND: - if (pin[GPIO_RFSEND] < 99) { - result = DecodeCommand(kRfSendCommands, RfSendCommand); - } - break; - case FUNC_INIT: - RfInit(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_18_armtronix_dimmers.ino" -#ifdef USE_LIGHT -#ifdef USE_ARMTRONIX_DIMMERS - - - - - - - -#define XDRV_18 18 - -#include - -TasmotaSerial *ArmtronixSerial = nullptr; - -struct ARMTRONIX { - bool ignore_dim = false; - int8_t wifi_state = -2; - int8_t dim_state[2]; - int8_t knob_state[2]; -} Armtronix; - - - - - -bool ArmtronixSetChannels(void) -{ - LightSerial2Duty(((uint8_t*)XdrvMailbox.data)[0], ((uint8_t*)XdrvMailbox.data)[1]); - return true; -} - -void LightSerial2Duty(uint8_t duty1, uint8_t duty2) -{ - if (ArmtronixSerial && !Armtronix.ignore_dim) { - duty1 = ((float)duty1)/2.575757; - duty2 = ((float)duty2)/2.575757; - Armtronix.dim_state[0] = duty1; - Armtronix.dim_state[1] = duty2; - ArmtronixSerial->print("Dimmer1:"); - ArmtronixSerial->print(duty1); - ArmtronixSerial->print("\nDimmer2:"); - ArmtronixSerial->println(duty2); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Serial Packet Dim Values=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); - - } else { - Armtronix.ignore_dim = false; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send Dim Level skipped due to already set. Value=%d,%d"), Armtronix.dim_state[0],Armtronix.dim_state[1]); - - } -} - -void ArmtronixRequestState(void) -{ - if (ArmtronixSerial) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR("ARM: Request MCU state")); - ArmtronixSerial->println("Status"); - - } -} - - - - - -bool ArmtronixModuleSelected(void) -{ - devices_present++; - light_type = LT_SERIAL2; - return true; -} - -void ArmtronixInit(void) -{ - Armtronix.dim_state[0] = -1; - Armtronix.dim_state[1] = -1; - Armtronix.knob_state[0] = -1; - Armtronix.knob_state[1] = -1; - ArmtronixSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (ArmtronixSerial->begin(115200)) { - if (ArmtronixSerial->hardwareSerial()) { ClaimSerial(); } - ArmtronixSerial->println("Status"); - } -} - -void ArmtronixSerialInput(void) -{ - String answer; - int8_t newDimState[2]; - uint8_t temp; - int commaIndex; - char scmnd[20]; - if (ArmtronixSerial->available()) { - yield(); - answer = ArmtronixSerial->readStringUntil('\n'); - if (answer.substring(0,7) == "Status:") { - commaIndex = 6; - for (uint32_t i =0; i<2; i++) { - newDimState[i] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - if (newDimState[i] != Armtronix.dim_state[i]) { - temp = ((float)newDimState[i])*1.01010101010101; - Armtronix.dim_state[i] = newDimState[i]; - Armtronix.ignore_dim = true; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "%d %d"),i+1, temp); - ExecuteCommand(scmnd,SRC_SWITCH); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Send CMND_CHANNEL=%s"), scmnd ); - } - commaIndex = answer.indexOf(',',commaIndex+1); - } - Armtronix.knob_state[0] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - commaIndex = answer.indexOf(',',commaIndex+1); - Armtronix.knob_state[1] = answer.substring(commaIndex+1,answer.indexOf(',',commaIndex+1)).toInt(); - } - } -} - -void ArmtronixSetWifiLed(void) -{ - uint8_t wifi_state = 0x02; - - switch (WifiState()) { - case WIFI_MANAGER: - wifi_state = 0x01; - break; - case WIFI_RESTART: - wifi_state = 0x03; - break; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ARM: Set WiFi LED to state %d (%d)"), wifi_state, WifiState()); - - char state = '0' + ((wifi_state & 1) > 0); - ArmtronixSerial->print("Setled:"); - ArmtronixSerial->write(state); - ArmtronixSerial->write(','); - state = '0' + ((wifi_state & 2) > 0); - ArmtronixSerial->write(state); - ArmtronixSerial->write(10); - Armtronix.wifi_state = WifiState(); -} - - - - - -bool Xdrv18(uint8_t function) -{ - bool result = false; - - if (ARMTRONIX_DIMMERS == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (ArmtronixSerial) { ArmtronixSerialInput(); } - break; - case FUNC_MODULE_INIT: - result = ArmtronixModuleSelected(); - break; - case FUNC_INIT: - ArmtronixInit(); - break; - case FUNC_EVERY_SECOND: - if (ArmtronixSerial) { - if (Armtronix.wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } - if (uptime &1) { - ArmtronixSerial->println("Status"); - } - } - break; - case FUNC_SET_CHANNELS: - result = ArmtronixSetChannels(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_19_ps16dz_dimmer.ino" -#ifdef USE_LIGHT -#ifdef USE_PS_16_DZ - - - - -#define XDRV_19 19 - -#define PS16DZ_BUFFER_SIZE 80 - -#include - -TasmotaSerial *PS16DZSerial = nullptr; - -struct PS16DZ { - char *rx_buffer = nullptr; - int byte_counter = 0; - uint8_t dimmer = 0; -} Ps16dz; - - - - - -void PS16DZSerialSend(const char *tx_buffer) -{ - - - PS16DZSerial->print(tx_buffer); - PS16DZSerial->write(0x1B); - PS16DZSerial->flush(); -} - -void PS16DZSerialSendOk(void) -{ - char tx_buffer[16]; - snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+SEND=ok")); - PS16DZSerialSend(tx_buffer); -} - - - - -void PS16DZSerialSendUpdateCommand(void) -{ - uint8_t light_state_dimmer = light_state.getDimmer(); - - light_state_dimmer = (light_state_dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : light_state_dimmer; - light_state_dimmer = (light_state_dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : light_state_dimmer; - - char tx_buffer[80]; - snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"), - LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer); - - PS16DZSerialSend(tx_buffer); -} - - - - - -void PS16DZSerialInput(void) -{ - char scmnd[20]; - while (PS16DZSerial->available()) { - yield(); - uint8_t serial_in_byte = PS16DZSerial->read(); - if (serial_in_byte != 0x1B) { - if (Ps16dz.byte_counter >= PS16DZ_BUFFER_SIZE - 1) { - memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); - Ps16dz.byte_counter = 0; - } - if (Ps16dz.byte_counter || (!Ps16dz.byte_counter && ('A' == serial_in_byte))) { - Ps16dz.rx_buffer[Ps16dz.byte_counter++] = serial_in_byte; - } - } else { - Ps16dz.rx_buffer[Ps16dz.byte_counter++] = 0x00; - - - - - if (!strncmp(Ps16dz.rx_buffer+3, "RESULT", 6)) { - - } - else if (!strncmp(Ps16dz.rx_buffer+3, "UPDATE", 6)) { - - char *end_str; - char *string = Ps16dz.rx_buffer+10; - char *token = strtok_r(string, ",", &end_str); - - bool is_switch_change = false; - bool is_brightness_change = false; - - while (token != nullptr) { - char* end_token; - char* token2 = strtok_r(token, ":", &end_token); - char* token3 = strtok_r(nullptr, ":", &end_token); - - if (!strncmp(token2, "\"switch\"", 8)) { - bool switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - - - - is_switch_change = (switch_state != power); - if (is_switch_change) { - ExecuteCommandPower(1, switch_state, SRC_SWITCH); - } - } - else if (!strncmp(token2, "\"bright\"", 8)) { - Ps16dz.dimmer = atoi(token3); - - - - is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer; - if (power && (Ps16dz.dimmer > 0) && is_brightness_change) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Ps16dz.dimmer); - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - else if (!strncmp(token2, "\"sequence\"", 10)) { - - - - } - token = strtok_r(nullptr, ",", &end_str); - } - - if (!is_brightness_change) { - - - - PS16DZSerialSendOk(); - } - } - else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) { - - - if (!Settings.flag.button_restrict) { - int state = WIFI_MANAGER; - if (!strncmp(Ps16dz.rx_buffer+10, "=exit", 5)) { state = WIFI_RETRY; } - if (state != Settings.sta_config) { - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " %d"), state); - ExecuteCommand(scmnd, SRC_BUTTON); - } - } - } - memset(Ps16dz.rx_buffer, 0, PS16DZ_BUFFER_SIZE); - Ps16dz.byte_counter = 0; - } - } -} - -bool PS16DZSerialSendUpdateCommandIfRequired(void) -{ - if (!PS16DZSerial) { return true; } - - bool is_switch_change = (XdrvMailbox.payload != SRC_SWITCH); - bool is_brightness_change = (light_state.getDimmer() != Ps16dz.dimmer); - - if (is_switch_change || is_brightness_change) { - PS16DZSerialSendUpdateCommand(); - } - - return true; -} - -void PS16DZInit(void) -{ - Ps16dz.rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (Ps16dz.rx_buffer != nullptr) { - PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (PS16DZSerial->begin(19200)) { - if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } - } - } -} - -bool PS16DZModuleSelected(void) -{ - devices_present++; - light_type = LT_SERIAL1; - - return true; -} - - - - - -bool Xdrv19(uint8_t function) -{ - bool result = false; - - if (PS_16_DZ == my_module_type) { - switch (function) { - case FUNC_LOOP: - if (PS16DZSerial) { PS16DZSerialInput(); } - break; - case FUNC_SET_DEVICE_POWER: - case FUNC_SET_CHANNELS: - result = PS16DZSerialSendUpdateCommandIfRequired(); - break; - case FUNC_INIT: - PS16DZInit(); - break; - case FUNC_MODULE_INIT: - result = PS16DZModuleSelected(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_20_hue.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_20_hue.ino" -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT) -# 31 "S:/Development/Tasmota/tasmota/xdrv_20_hue.ino" -#define XDRV_20 20 - -const char HUE_RESPONSE[] PROGMEM = - "HTTP/1.1 200 OK\r\n" - "HOST: 239.255.255.250:1900\r\n" - "CACHE-CONTROL: max-age=100\r\n" - "EXT:\r\n" - "LOCATION: http://%s:80/description.xml\r\n" - "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.24.0\r\n" - "hue-bridgeid: %s\r\n"; -const char HUE_ST1[] PROGMEM = - "ST: upnp:rootdevice\r\n" - "USN: uuid:%s::upnp:rootdevice\r\n" - "\r\n"; -const char HUE_ST2[] PROGMEM = - "ST: uuid:%s\r\n" - "USN: uuid:%s\r\n" - "\r\n"; -const char HUE_ST3[] PROGMEM = - "ST: urn:schemas-upnp-org:device:basic:1\r\n" - "USN: uuid:%s\r\n" - "\r\n"; - -String HueBridgeId(void) -{ - String temp = WiFi.macAddress(); - temp.replace(":", ""); - String bridgeid = temp.substring(0, 6) + "FFFE" + temp.substring(6); - return bridgeid; -} - -String HueSerialnumber(void) -{ - String serial = WiFi.macAddress(); - serial.replace(":", ""); - serial.toLowerCase(); - return serial; -} - -String HueUuid(void) -{ - String uuid = F("f6543a06-da50-11ba-8d8f-"); - uuid += HueSerialnumber(); - return uuid; -} - -void HueRespondToMSearch(void) -{ - char message[TOPSZ]; - - TickerMSearch.detach(); - if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - char response[320]; - snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); - int len = strlen(response); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST1, HueUuid().c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST2, HueUuid().c_str(), HueUuid().c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(response + len, sizeof(response) - len, HUE_ST3, HueUuid().c_str()); - PortUdp.write(response); - PortUdp.endPacket(); - - snprintf_P(message, sizeof(message), PSTR(D_3_RESPONSE_PACKETS_SENT)); - } else { - snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); - } - - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"), - message, udp_remote_ip.toString().c_str(), udp_remote_port); - - udp_response_mutex = false; -} - - - - - -const char HUE_DESCRIPTION_XML[] PROGMEM = - "" - "" - "" - "1" - "0" - "" - - "http://{x1:80/" - "" - "urn:schemas-upnp-org:device:Basic:1" - "Amazon-Echo-HA-Bridge ({x1)" - - "Royal Philips Electronics" - "http://www.philips.com" - "Philips hue Personal Wireless Lighting" - "Philips hue bridge 2012" - "929000226503" - "{x3" - "uuid:{x2" - "" - "\r\n" - "\r\n"; -const char HUE_LIGHTS_STATUS_JSON1[] PROGMEM = - "{\"on\":{state}," - "{light_status}" - "\"alert\":\"none\"," - "\"effect\":\"none\"," - "\"reachable\":true}"; -const char HUE_LIGHTS_STATUS_JSON2[] PROGMEM = - ",\"type\":\"Extended color light\"," - "\"name\":\"{j1\"," - "\"modelid\":\"LCT007\"," - "\"uniqueid\":\"{j2\"," - "\"swversion\":\"5.50.1.19085\"}"; -const char HUE_GROUP0_STATUS_JSON[] PROGMEM = - "{\"name\":\"Group 0\"," - "\"lights\":[{l1]," - "\"type\":\"LightGroup\"," - "\"action\":"; - -const char HueConfigResponse_JSON[] PROGMEM = - "{\"name\":\"Philips hue\"," - "\"mac\":\"{ma\"," - "\"dhcp\":true," - "\"ipaddress\":\"{ip\"," - "\"netmask\":\"{ms\"," - "\"gateway\":\"{gw\"," - "\"proxyaddress\":\"none\"," - "\"proxyport\":0," - "\"bridgeid\":\"{br\"," - "\"UTC\":\"{dt\"," - "\"whitelist\":{\"{id\":{" - "\"last use date\":\"{dt\"," - "\"create date\":\"{dt\"," - "\"name\":\"Remote\"}}," - "\"swversion\":\"01041302\"," - "\"apiversion\":\"1.17.0\"," - "\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false}," - "\"linkbutton\":false," - "\"portalservices\":false" - "}"; -const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM = - "{\"success\":{\"/lights/{id/state/{cm\":{re}}"; -const char HUE_ERROR_JSON[] PROGMEM = - "[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]"; - - - -String GetHueDeviceId(uint8_t id) -{ - String deviceid = WiFi.macAddress() + F(":00:11-") + String(id); - deviceid.toLowerCase(); - return deviceid; -} - -String GetHueUserId(void) -{ - char userid[7]; - - snprintf_P(userid, sizeof(userid), PSTR("%03x"), ESP.getChipId()); - return String(userid); -} - -void HandleUpnpSetupHue(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_HUE_BRIDGE_SETUP)); - String description_xml = FPSTR(HUE_DESCRIPTION_XML); - description_xml.replace("{x1", WiFi.localIP().toString()); - description_xml.replace("{x2", HueUuid()); - description_xml.replace("{x3", HueSerialnumber()); - WSSend(200, CT_XML, description_xml); -} - -void HueNotImplemented(String *path) -{ - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API_NOT_IMPLEMENTED " (%s)"), path->c_str()); - - WSSend(200, CT_JSON, "{}"); -} - -void HueConfigResponse(String *response) -{ - *response += FPSTR(HueConfigResponse_JSON); - response->replace("{ma", WiFi.macAddress()); - response->replace("{ip", WiFi.localIP().toString()); - response->replace("{ms", WiFi.subnetMask().toString()); - response->replace("{gw", WiFi.gatewayIP().toString()); - response->replace("{br", HueBridgeId()); - response->replace("{dt", GetDateAndTime(DT_UTC)); - response->replace("{id", GetHueUserId()); -} - -void HueConfig(String *path) -{ - String response = ""; - HueConfigResponse(&response); - WSSend(200, CT_JSON, response); -} - - - -bool g_gotct = false; - - - - -uint16_t prev_hue = 0; -uint8_t prev_sat = 0; -uint8_t prev_bri = 254; -uint16_t prev_ct = 254; -char prev_x_str[24] = "\0"; -char prev_y_str[24] = "\0"; - -uint8_t getLocalLightSubtype(uint8_t device) { - if (light_type) { - if (device >= Light.device) { - if (Settings.flag3.pwm_multi_channels) { - return LST_SINGLE; - } else { - return Light.subtype; - } - } else { - return LST_NONE; - } - } else { - return LST_NONE; - } -} - -void HueLightStatus1(uint8_t device, String *response) -{ - uint16_t ct = 0; - uint8_t color_mode; - String light_status = ""; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint32_t echo_gen = findEchoGeneration(); - - - uint8_t local_light_subtype = getLocalLightSubtype(device); - - bri = LightGetBri(device); - if (bri > 254) bri = 254; - if (bri < 1) bri = 1; - -#ifdef USE_SHUTTER - if (ShutterState(device)) { - bri = (float)((Settings.shutter_options[device-1] & 1) ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100; - } -#endif - - if (light_type) { - light_state.getHSB(&hue, &sat, nullptr); - - if ((bri > prev_bri ? bri - prev_bri : prev_bri - bri) < 1) - bri = prev_bri; - - if (sat > 254) sat = 254; - if ((sat > prev_sat ? sat - prev_sat : prev_sat - sat) < 1) { - sat = prev_sat; - } else { - prev_x_str[0] = prev_y_str[0] = 0; - } - - hue = changeUIntScale(hue, 0, 359, 0, 65535); - if ((hue > prev_hue ? hue - prev_hue : prev_hue - hue) < 400) { - hue = prev_hue; - } else { - prev_x_str[0] = prev_y_str[0] = 0; - } - - color_mode = light_state.getColorMode(); - ct = light_state.getCT(); - if (LCM_RGB == color_mode) { g_gotct = false; } - if (LCM_CT == color_mode) { g_gotct = true; } - - - - if ((ct > prev_ct ? ct - prev_ct : prev_ct - ct) < 1) - ct = prev_ct; - - - - } - - *response += FPSTR(HUE_LIGHTS_STATUS_JSON1); - response->replace("{state}", (power & (1 << (device-1))) ? "true" : "false"); - - if ((1 == echo_gen) || (LST_SINGLE <= local_light_subtype)) { - light_status += "\"bri\":"; - light_status += String(bri); - light_status += ","; - } - if (LST_COLDWARM <= local_light_subtype) { - light_status += F("\"colormode\":\""); - light_status += (g_gotct ? "ct" : "hs"); - light_status += "\","; - } - if (LST_RGB <= local_light_subtype) { - if (prev_x_str[0] && prev_y_str[0]) { - light_status += "\"xy\":["; - light_status += prev_x_str; - light_status += ","; - light_status += prev_y_str; - light_status += "],"; - } else { - float x, y; - light_state.getXY(&x, &y); - light_status += "\"xy\":["; - light_status += String(x, 5); - light_status += ","; - light_status += String(y, 5); - light_status += "],"; - } - light_status += "\"hue\":"; - light_status += String(hue); - light_status += ","; - - light_status += "\"sat\":"; - light_status += String(sat); - light_status += ","; - } - if (LST_COLDWARM == local_light_subtype || LST_RGBW <= local_light_subtype) { - light_status += "\"ct\":"; - light_status += String(ct > 0 ? ct : 284); - light_status += ","; - } - response->replace("{light_status}", light_status); -} - - - -bool HueActive(uint8_t device) { - if (device > MAX_FRIENDLYNAMES) { device = MAX_FRIENDLYNAMES; } - return '$' != *SettingsText(SET_FRIENDLYNAME1 +device -1); -} - -void HueLightStatus2(uint8_t device, String *response) -{ - *response += FPSTR(HUE_LIGHTS_STATUS_JSON2); - if (device <= MAX_FRIENDLYNAMES) { - response->replace("{j1", SettingsText(SET_FRIENDLYNAME1 +device -1)); - } else { - char fname[33]; - strcpy(fname, SettingsText(SET_FRIENDLYNAME1 + MAX_FRIENDLYNAMES -1)); - uint32_t fname_len = strlen(fname); - if (fname_len > 30) { fname_len = 30; } - fname[fname_len++] = '-'; - if (device - MAX_FRIENDLYNAMES < 10) { - fname[fname_len++] = '0' + device - MAX_FRIENDLYNAMES; - } else { - fname[fname_len++] = 'A' + device - MAX_FRIENDLYNAMES - 10; - } - fname[fname_len] = 0x00; - - response->replace("{j1", fname); - } - response->replace("{j2", GetHueDeviceId(device)); -} - - - - -uint32_t EncodeLightId(uint8_t relay_id) -{ - uint8_t mac[6]; - WiFi.macAddress(mac); - uint32_t id = 0; - - if (relay_id >= 32) { - relay_id = 0; - } - if (relay_id > 15) { - id = (1 << 28); - } - - id |= (mac[3] << 20) | (mac[4] << 12) | (mac[5] << 4) | (relay_id & 0xF); - return id; -} - - - -uint32_t DecodeLightId(uint32_t hue_id) { - uint8_t relay_id = hue_id & 0xF; - if (hue_id & (1 << 28)) { - relay_id += 16; - } - if (0 == relay_id) { - relay_id = 32; - } - return relay_id; -} - -static const char * FIRST_GEN_UA[] = { - "AEOBC", -}; - - -uint32_t findEchoGeneration(void) { - - String user_agent = WebServer->header("User-Agent"); - uint32_t gen = 2; - - for (uint32_t i = 0; i < sizeof(FIRST_GEN_UA)/sizeof(char*); i++) { - if (user_agent.indexOf(FIRST_GEN_UA[i]) >= 0) { - gen = 1; - break; - } - } - if (0 == user_agent.length()) { - gen = 1; - } - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, D_LOG_HTTP D_HUE " User-Agent: %s, gen=%d", user_agent.c_str(), gen); - - return gen; -} - -void HueGlobalConfig(String *path) { - String response; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - path->remove(0,1); - response = F("{\"lights\":{"); - bool appending = false; - for (uint32_t i = 1; i <= maxhue; i++) { - if (HueActive(i)) { - if (appending) { response += ","; } - response += "\""; - response += EncodeLightId(i); - response += F("\":{\"state\":"); - HueLightStatus1(i, &response); - HueLightStatus2(i, &response); - appending = true; - } - } - response += F("},\"groups\":{},\"schedules\":{},\"config\":"); - HueConfigResponse(&response); - response += "}"; - WSSend(200, CT_JSON, response); -} - -void HueAuthentication(String *path) -{ - char response[38]; - - snprintf_P(response, sizeof(response), PSTR("[{\"success\":{\"username\":\"%s\"}}]"), GetHueUserId().c_str()); - WSSend(200, CT_JSON, response); -} - -void HueLights(String *path) -{ - - - - String response; - int code = 200; - uint16_t tmp = 0; - uint16_t hue = 0; - uint8_t sat = 0; - uint8_t bri = 254; - uint16_t ct = 0; - bool resp = false; - bool on = false; - bool change = false; - uint8_t device = 1; - uint8_t local_light_subtype = Light.subtype; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - path->remove(0,path->indexOf("/lights")); - if (path->endsWith("/lights")) { - response = "{"; - bool appending = false; - for (uint32_t i = 1; i <= maxhue; i++) { - if (HueActive(i)) { - if (appending) { response += ","; } - response += "\""; - response += EncodeLightId(i); - response += F("\":{\"state\":"); - HueLightStatus1(i, &response); - HueLightStatus2(i, &response); - appending = true; - } - } -#ifdef USE_SCRIPT_HUE - Script_Check_Hue(&response); -#endif - response += "}"; - } - else if (path->endsWith("/state")) { - path->remove(0,8); - path->remove(path->indexOf("/state")); - device = DecodeLightId(atoi(path->c_str())); - -#ifdef USE_SCRIPT_HUE - if (device>devices_present) { - return Script_Handle_Hue(path); - } -#endif - - if ((device < 1) || (device > maxhue)) { - device = 1; - } - local_light_subtype = getLocalLightSubtype(device); - - if (WebServer->args()) { - response = "["; - - StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); - if (hue_json.containsKey("on")) { - - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(EncodeLightId(device))); - response.replace("{cm", "on"); - -#ifdef USE_SHUTTER - if (ShutterState(device)) { - if (!change) { - on = hue_json["on"]; - bri = on ? 1.0f : 0.0f; - change = true; - } - response.replace("{re", on ? "true" : "false"); - } else { -#endif - on = hue_json["on"]; - switch(on) - { - case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE); - response.replace("{re", "false"); - break; - case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE); - response.replace("{re", "true"); - break; - default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false"); - break; - } - resp = true; -#ifdef USE_SHUTTER - } -#endif - } - - if (light_type && (local_light_subtype >= LST_SINGLE)) { - if (!Settings.flag3.pwm_multi_channels) { - light_state.getHSB(&hue, &sat, nullptr); - bri = light_state.getBri(); - ct = light_state.getCT(); - uint8_t color_mode = light_state.getColorMode(); - if (LCM_RGB == color_mode) { g_gotct = false; } - if (LCM_CT == color_mode) { g_gotct = true; } - - } else { - bri = LightGetBri(device); - } - } - prev_x_str[0] = prev_y_str[0] = 0; - - if (hue_json.containsKey("bri")) { - tmp = hue_json["bri"]; - prev_bri = bri = tmp; - - if (254 <= bri) { bri = 255; } - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "bri"); - response.replace("{re", String(tmp)); - if (LST_SINGLE <= Light.subtype) { - change = true; - } - resp = true; - } - - - if (hue_json.containsKey("xy")) { - float x, y; - x = hue_json["xy"][0]; - y = hue_json["xy"][1]; - const String &x_str = hue_json["xy"][0]; - const String &y_str = hue_json["xy"][1]; - x_str.toCharArray(prev_x_str, sizeof(prev_x_str)); - y_str.toCharArray(prev_y_str, sizeof(prev_y_str)); - - uint8_t rr,gg,bb; - LightStateClass::XyToRgb(x, y, &rr, &gg, &bb); - LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr); - prev_hue = changeUIntScale(hue, 0, 359, 0, 65535); - prev_sat = (sat > 254 ? 254 : sat); - - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "xy"); - response.replace("{re", "[" + x_str + "," + y_str + "]"); - g_gotct = false; - resp = true; - change = true; - } - if (hue_json.containsKey("hue")) { - tmp = hue_json["hue"]; - prev_hue = tmp; - - hue = changeUIntScale(tmp, 0, 65535, 0, 359); - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "hue"); - response.replace("{re", String(tmp)); - if (LST_RGB <= Light.subtype) { - g_gotct = false; - change = true; - } - resp = true; - } - if (hue_json.containsKey("sat")) { - tmp = hue_json["sat"]; - prev_sat = sat = tmp; - - if (254 <= sat) { sat = 255; } - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "sat"); - response.replace("{re", String(tmp)); - if (LST_RGB <= Light.subtype) { - g_gotct = false; - change = true; - } - resp = true; - } - if (hue_json.containsKey("ct")) { - ct = hue_json["ct"]; - prev_ct = ct; - if (resp) { response += ","; } - response += FPSTR(HUE_LIGHT_RESPONSE_JSON); - response.replace("{id", String(device)); - response.replace("{cm", "ct"); - response.replace("{re", String(ct)); - if ((LST_COLDWARM == Light.subtype) || (LST_RGBW <= Light.subtype)) { - g_gotct = true; - change = true; - } - resp = true; - } - if (change) { -#ifdef USE_SHUTTER - if (ShutterState(device)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_options[device-1] & 1); - ShutterSetPosition(device, bri * 100.0f ); - } else -#endif - if (light_type && (local_light_subtype > LST_NONE)) { - if (!Settings.flag3.pwm_multi_channels) { - if (g_gotct) { - light_controller.changeCTB(ct, bri); - } else { - light_controller.changeHSB(hue, sat, bri); - } - LightPreparePower(); - } else { - LightSetBri(device, bri); - } - if (LST_COLDWARM <= local_light_subtype) { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); - } else { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_DIMMER)); - } - XdrvRulesProcess(); - } - change = false; - } - response += "]"; - if (2 == response.length()) { - response = FPSTR(HUE_ERROR_JSON); - } - } - else { - response = FPSTR(HUE_ERROR_JSON); - } - } - else if(path->indexOf("/lights/") >= 0) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, "/lights path=%s", path->c_str()); - path->remove(0,8); - device = DecodeLightId(atoi(path->c_str())); - -#ifdef USE_SCRIPT_HUE - if (device>devices_present) { - Script_HueStatus(&response,device-devices_present-1); - goto exit; -} -#endif - - if ((device < 1) || (device > maxhue)) { - device = 1; - } - response += F("{\"state\":"); - HueLightStatus1(device, &response); - HueLightStatus2(device, &response); - } - else { - response = "{}"; - code = 406; - } - exit: - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE " Result (%s)"), response.c_str()); - WSSend(code, CT_JSON, response); -} - -void HueGroups(String *path) -{ - - - - String response = "{}"; - uint8_t maxhue = (devices_present > MAX_HUE_DEVICES) ? MAX_HUE_DEVICES : devices_present; - - if (path->endsWith("/0")) { - response = FPSTR(HUE_GROUP0_STATUS_JSON); - String lights = F("\"1\""); - for (uint32_t i = 2; i <= maxhue; i++) { - lights += ",\""; - lights += EncodeLightId(i); - lights += "\""; - } - response.replace("{l1", lights); - HueLightStatus1(1, &response); - response += F("}"); - } - - WSSend(200, CT_JSON, response); -} - -void HandleHueApi(String *path) -{ -# 784 "S:/Development/Tasmota/tasmota/xdrv_20_hue.ino" - uint8_t args = 0; - - path->remove(0, 4); - uint16_t apilen = path->length(); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_API " (%s)"), path->c_str()); - for (args = 0; args < WebServer->args(); args++) { - String json = WebServer->arg(args); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP D_HUE_POST_ARGS " (%s)"), json.c_str()); - } - - if (path->endsWith("/invalid/")) {} - else if (!apilen) HueAuthentication(path); - else if (path->endsWith("/")) HueAuthentication(path); - else if (path->endsWith("/config")) HueConfig(path); - else if (path->indexOf("/lights") >= 0) HueLights(path); - else if (path->indexOf("/groups") >= 0) HueGroups(path); - else if (path->endsWith("/schedules")) HueNotImplemented(path); - else if (path->endsWith("/sensors")) HueNotImplemented(path); - else if (path->endsWith("/scenes")) HueNotImplemented(path); - else if (path->endsWith("/rules")) HueNotImplemented(path); - else if (path->endsWith("/resourcelinks")) HueNotImplemented(path); - else HueGlobalConfig(path); -} - - - - - -bool Xdrv20(uint8_t function) -{ - bool result = false; - -#ifdef USE_SCRIPT_HUE - if ((EMUL_HUE == Settings.flag2.emulation)) { -#else - if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) { -#endif - switch (function) { - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/description.xml", HandleUpnpSetupHue); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_21_wemo.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_21_wemo.ino" -#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined (USE_EMULATION_WEMO) - - - - -#define XDRV_21 21 - -const char WEMO_MSEARCH[] PROGMEM = - "HTTP/1.1 200 OK\r\n" - "CACHE-CONTROL: max-age=86400\r\n" - "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" - "EXT:\r\n" - "LOCATION: http://%s:80/setup.xml\r\n" - "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" - "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n" - "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n" - "ST: %s\r\n" - "USN: uuid:%s::%s\r\n" - "X-User-Agent: redsonic\r\n" - "\r\n"; - -String WemoSerialnumber(void) -{ - char serial[16]; - - snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId()); - return String(serial); -} - -String WemoUuid(void) -{ - char uuid[27]; - - snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str()); - return String(uuid); -} - -void WemoRespondToMSearch(int echo_type) -{ - char message[TOPSZ]; - - TickerMSearch.detach(); - if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - char type[24]; - if (1 == echo_type) { - strcpy_P(type, URN_BELKIN_DEVICE_CAP); - } else { - strcpy_P(type, UPNP_ROOTDEVICE); - } - char response[400]; - snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); - PortUdp.write(response); - PortUdp.endPacket(); - snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); - } else { - snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE)); - } - - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"), - echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port); - - udp_response_mutex = false; -} - - - - - -const char WEMO_EVENTSERVICE_XML[] PROGMEM = - "" - "" - "" - "SetBinaryState" - "" - "" - "" - "BinaryState" - "BinaryState" - "in" - "" - "" - "" - "" - "GetBinaryState" - "" - "" - "" - "BinaryState" - "BinaryState" - "out" - "" - "" - "" - "" - "" - "" - "BinaryState" - "bool" - "0" - "" - "" - "level" - "string" - "0" - "" - "" - "\r\n\r\n"; - -const char WEMO_METASERVICE_XML[] PROGMEM = - "" - "" - "1" - "0" - "" - "" - "" - "GetMetaInfo" - "" - "" - "GetMetaInfo" - "MetaInfo" - "in" - "" - "" - "" - "" - "" - "MetaInfo" - "string" - "0" - "" - "" - "\r\n\r\n"; - -const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = - "" - "" - "" - "%d" - "" - "" - "\r\n"; - -const char WEMO_SETUP_XML[] PROGMEM = - "" - "" - "" - "urn:Belkin:device:controllee:1" - "{x1" - "Belkin International Inc." - "Socket" - "3.1415" - "uuid:{x2" - "{x3" - "0" - "" - "" - "urn:Belkin:service:basicevent:1" - "urn:Belkin:serviceId:basicevent1" - "/upnp/control/basicevent1" - "/upnp/event/basicevent1" - "/eventservice.xml" - "" - "" - "urn:Belkin:service:metainfo:1" - "urn:Belkin:serviceId:metainfo1" - "/upnp/control/metainfo1" - "/upnp/event/metainfo1" - "/metainfoservice.xml" - "" - "" - "" - "\r\n"; - - - -void HandleUpnpEvent(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); - - char event[500]; - strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); - - - - - char state = 'G'; - if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) { - state = 'S'; - uint8_t power = POWER_TOGGLE; - if (strstr_P(event, PSTR("State>10on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); - WebServer->on("/eventservice.xml", HandleUpnpService); - WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); - WebServer->on("/setup.xml", HandleUpnpSetupWemo); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" -#ifdef USE_SONOFF_IFAN - - - - -#define XDRV_22 22 - -const uint8_t MAX_FAN_SPEED = 4; - -const uint8_t kIFan02Speed[MAX_FAN_SPEED] = { 0x00, 0x01, 0x03, 0x05 }; -const uint8_t kIFan03Speed[MAX_FAN_SPEED +2] = { 0x00, 0x01, 0x03, 0x04, 0x05, 0x06 }; -const uint8_t kIFan03Sequence[MAX_FAN_SPEED][MAX_FAN_SPEED] = {{0, 2, 2, 2}, {0, 1, 2, 4}, {1, 1, 2, 5}, {4, 4, 5, 3}}; - -const char kSonoffIfanCommands[] PROGMEM = "|" - D_CMND_FANSPEED; - -void (* const SonoffIfanCommand[])(void) PROGMEM = { - &CmndFanspeed }; - -uint8_t ifan_fanspeed_timer = 0; -uint8_t ifan_fanspeed_goal = 0; -bool ifan_receive_flag = false; -bool ifan_restart_flag = true; - - - -bool IsModuleIfan(void) -{ - return ((SONOFF_IFAN02 == my_module_type) || (SONOFF_IFAN03 == my_module_type)); -} - -uint8_t MaxFanspeed(void) -{ - return MAX_FAN_SPEED; -} - -uint8_t GetFanspeed(void) -{ - if (ifan_fanspeed_timer) { - return ifan_fanspeed_goal; - } else { - - - - - - - uint8_t fanspeed = (uint8_t)(power &0xF) >> 1; - if (fanspeed) { fanspeed = (fanspeed >> 1) +1; } - return fanspeed; - } -} - - - -void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence) -{ - ifan_fanspeed_timer = 0; - ifan_fanspeed_goal = fanspeed; - - uint8_t fanspeed_now = GetFanspeed(); - - if (fanspeed == fanspeed_now) { return; } - - uint8_t fans = kIFan02Speed[fanspeed]; - if (SONOFF_IFAN03 == my_module_type) { - if (sequence) { - fanspeed = kIFan03Sequence[fanspeed_now][ifan_fanspeed_goal]; - if (fanspeed != ifan_fanspeed_goal) { - if (0 == fanspeed_now) { - ifan_fanspeed_timer = 20; - } else { - ifan_fanspeed_timer = 2; - } - } - } - fans = kIFan03Speed[fanspeed]; - } - for (uint32_t i = 2; i < 5; i++) { - uint8_t state = (fans &1) + POWER_OFF_NO_STATE; - ExecuteCommandPower(i, state, SRC_IGNORE); - fans >>= 1; - } - -#ifdef USE_DOMOTICZ - if (sequence) { DomoticzUpdateFanState(); } -#endif -} - - - -void SonoffIfanReceived(void) -{ - char svalue[32]; - - uint8_t mode = serial_in_buffer[3]; - uint8_t action = serial_in_buffer[6]; - - if (4 == mode) { - if (action < 4) { - - - - - if (action != GetFanspeed()) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_FANSPEED " %d"), action); - ExecuteCommand(svalue, SRC_REMOTE); -#ifdef USE_BUZZER - BuzzerEnabledBeep((action) ? action : 1, (action) ? 1 : 4); -#endif - } - } else { - - ExecuteCommandPower(1, POWER_TOGGLE, SRC_REMOTE); - } - } - if (6 == mode) { - - Settings.flag3.buzzer_enable = !Settings.flag3.buzzer_enable; - } - if (7 == mode) { - -#ifdef USE_BUZZER - BuzzerEnabledBeep(4, 1); -#endif - } - - - - serial_in_buffer[5] = 0; - serial_in_buffer[6] = 0; - for (uint32_t i = 0; i < 7; i++) { - if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } - Serial.write(serial_in_buffer[i]); - } -} - -bool SonoffIfanSerialInput(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - if (0xAA == serial_in_byte) { - serial_in_byte_counter = 0; - ifan_receive_flag = true; - } - if (ifan_receive_flag) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 8) { -# 176 "S:/Development/Tasmota/tasmota/xdrv_22_sonoff_ifan.ino" - AddLogSerial(LOG_LEVEL_DEBUG); - uint8_t crc = 0; - for (uint32_t i = 2; i < 7; i++) { - crc += serial_in_buffer[i]; - } - if (crc == serial_in_buffer[7]) { - SonoffIfanReceived(); - ifan_receive_flag = false; - return true; - } - } - serial_in_byte = 0; - } - return false; - } -} - - - - - -void CmndFanspeed(void) -{ - if (XdrvMailbox.data_len > 0) { - if ('-' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = (int16_t)GetFanspeed() -1; - if (XdrvMailbox.payload < 0) { XdrvMailbox.payload = MAX_FAN_SPEED -1; } - } - else if ('+' == XdrvMailbox.data[0]) { - XdrvMailbox.payload = GetFanspeed() +1; - if (XdrvMailbox.payload > MAX_FAN_SPEED -1) { XdrvMailbox.payload = 0; } - } - } - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < MAX_FAN_SPEED)) { - SonoffIFanSetFanspeed(XdrvMailbox.payload, true); - } - ResponseCmndNumber(GetFanspeed()); -} - - - -bool SonoffIfanInit(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - SetSerial(9600, TS_SERIAL_8N1); - } - return false; -} - -void SonoffIfanUpdate(void) -{ - if (SONOFF_IFAN03 == my_module_type) { - if (ifan_fanspeed_timer) { - ifan_fanspeed_timer--; - if (!ifan_fanspeed_timer) { - SonoffIFanSetFanspeed(ifan_fanspeed_goal, false); - } - } - } - - if (ifan_restart_flag && (4 == uptime) && (SONOFF_IFAN02 == my_module_type)) { - ifan_restart_flag = false; - SetDevicePower(1, SRC_RETRY); - SetDevicePower(power, SRC_RETRY); - } -} - - - - - -bool Xdrv22(uint8_t function) -{ - bool result = false; - - if (IsModuleIfan()) { - switch (function) { - case FUNC_EVERY_250_MSECOND: - SonoffIfanUpdate(); - break; - case FUNC_SERIAL: - result = SonoffIfanSerialInput(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kSonoffIfanCommands, SonoffIfanCommand); - break; - case FUNC_MODULE_INIT: - result = SonoffIfanInit(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -#ifdef USE_ZIGBEE - -#define OCCUPANCY "Occupancy" - -typedef uint64_t Z_IEEEAddress; -typedef uint16_t Z_ShortAddress; - -enum ZnpCommandType { - Z_POLL = 0x00, - Z_SREQ = 0x20, - Z_AREQ = 0x40, - Z_SRSP = 0x60 -}; - -enum ZnpSubsystem { - Z_RPC_Error = 0x00, - Z_SYS = 0x01, - Z_MAC = 0x02, - Z_NWK = 0x03, - Z_AF = 0x04, - Z_ZDO = 0x05, - Z_SAPI = 0x06, - Z_UTIL = 0x07, - Z_DEBUG = 0x08, - Z_APP = 0x09 -}; - - -enum SysCommand { - SYS_RESET = 0x00, - SYS_PING = 0x01, - SYS_VERSION = 0x02, - SYS_SET_EXTADDR = 0x03, - SYS_GET_EXTADDR = 0x04, - SYS_RAM_READ = 0x05, - SYS_RAM_WRITE = 0x06, - SYS_OSAL_NV_ITEM_INIT = 0x07, - SYS_OSAL_NV_READ = 0x08, - SYS_OSAL_NV_WRITE = 0x09, - SYS_OSAL_START_TIMER = 0x0A, - SYS_OSAL_STOP_TIMER = 0x0B, - SYS_RANDOM = 0x0C, - SYS_ADC_READ = 0x0D, - SYS_GPIO = 0x0E, - SYS_STACK_TUNE = 0x0F, - SYS_SET_TIME = 0x10, - SYS_GET_TIME = 0x11, - SYS_OSAL_NV_DELETE = 0x12, - SYS_OSAL_NV_LENGTH = 0x13, - SYS_TEST_RF = 0x40, - SYS_TEST_LOOPBACK = 0x41, - SYS_RESET_IND = 0x80, - SYS_OSAL_TIMER_EXPIRED = 0x81, -}; - -enum SapiCommand { - SAPI_START_REQUEST = 0x00, - SAPI_BIND_DEVICE = 0x01, - SAPI_ALLOW_BIND = 0x02, - SAPI_SEND_DATA_REQUEST = 0x03, - SAPI_READ_CONFIGURATION = 0x04, - SAPI_WRITE_CONFIGURATION = 0x05, - SAPI_GET_DEVICE_INFO = 0x06, - SAPI_FIND_DEVICE_REQUEST = 0x07, - SAPI_PERMIT_JOINING_REQUEST = 0x08, - SAPI_SYSTEM_RESET = 0x09, - SAPI_START_CONFIRM = 0x80, - SAPI_BIND_CONFIRM = 0x81, - SAPI_ALLOW_BIND_CONFIRM = 0x82, - SAPI_SEND_DATA_CONFIRM = 0x83, - SAPI_FIND_DEVICE_CONFIRM = 0x85, - SAPI_RECEIVE_DATA_INDICATION = 0x87, -}; -enum Z_configuration { - CONF_EXTADDR = 0x01, - CONF_BOOTCOUNTER = 0x02, - CONF_STARTUP_OPTION = 0x03, - CONF_START_DELAY = 0x04, - CONF_NIB = 0x21, - CONF_DEVICE_LIST = 0x22, - CONF_ADDRMGR = 0x23, - CONF_POLL_RATE = 0x24, - CONF_QUEUED_POLL_RATE = 0x25, - CONF_RESPONSE_POLL_RATE = 0x26, - CONF_REJOIN_POLL_RATE = 0x27, - CONF_DATA_RETRIES = 0x28, - CONF_POLL_FAILURE_RETRIES = 0x29, - CONF_STACK_PROFILE = 0x2A, - CONF_INDIRECT_MSG_TIMEOUT = 0x2B, - CONF_ROUTE_EXPIRY_TIME = 0x2C, - CONF_EXTENDED_PAN_ID = 0x2D, - CONF_BCAST_RETRIES = 0x2E, - CONF_PASSIVE_ACK_TIMEOUT = 0x2F, - CONF_BCAST_DELIVERY_TIME = 0x30, - CONF_NWK_MODE = 0x31, - CONF_CONCENTRATOR_ENABLE = 0x32, - CONF_CONCENTRATOR_DISCOVERY = 0x33, - CONF_CONCENTRATOR_RADIUS = 0x34, - CONF_CONCENTRATOR_RC = 0x36, - CONF_NWK_MGR_MODE = 0x37, - CONF_SRC_RTG_EXPIRY_TIME = 0x38, - CONF_ROUTE_DISCOVERY_TIME = 0x39, - CONF_NWK_ACTIVE_KEY_INFO = 0x3A, - CONF_NWK_ALTERN_KEY_INFO = 0x3B, - CONF_ROUTER_OFF_ASSOC_CLEANUP = 0x3C, - CONF_NWK_LEAVE_REQ_ALLOWED = 0x3D, - CONF_NWK_CHILD_AGE_ENABLE = 0x3E, - CONF_DEVICE_LIST_KA_TIMEOUT = 0x3F, - CONF_BINDING_TABLE = 0x41, - CONF_GROUP_TABLE = 0x42, - CONF_APS_FRAME_RETRIES = 0x43, - CONF_APS_ACK_WAIT_DURATION = 0x44, - CONF_APS_ACK_WAIT_MULTIPLIER = 0x45, - CONF_BINDING_TIME = 0x46, - CONF_APS_USE_EXT_PANID = 0x47, - CONF_APS_USE_INSECURE_JOIN = 0x48, - CONF_COMMISSIONED_NWK_ADDR = 0x49, - CONF_APS_NONMEMBER_RADIUS = 0x4B, - CONF_APS_LINK_KEY_TABLE = 0x4C, - CONF_APS_DUPREJ_TIMEOUT_INC = 0x4D, - CONF_APS_DUPREJ_TIMEOUT_COUNT = 0x4E, - CONF_APS_DUPREJ_TABLE_SIZE = 0x4F, - CONF_DIAGNOSTIC_STATS = 0x50, - CONF_SECURITY_LEVEL = 0x61, - CONF_PRECFGKEY = 0x62, - CONF_PRECFGKEYS_ENABLE = 0x63, - CONF_SECURITY_MODE = 0x64, - CONF_SECURE_PERMIT_JOIN = 0x65, - CONF_APS_LINK_KEY_TYPE = 0x66, - CONF_APS_ALLOW_R19_SECURITY = 0x67, - CONF_IMPLICIT_CERTIFICATE = 0x69, - CONF_DEVICE_PRIVATE_KEY = 0x6A, - CONF_CA_PUBLIC_KEY = 0x6B, - CONF_KE_MAX_DEVICES = 0x6C, - CONF_USE_DEFAULT_TCLK = 0x6D, - CONF_RNG_COUNTER = 0x6F, - CONF_RANDOM_SEED = 0x70, - CONF_TRUSTCENTER_ADDR = 0x71, - CONF_USERDESC = 0x81, - CONF_NWKKEY = 0x82, - CONF_PANID = 0x83, - CONF_CHANLIST = 0x84, - CONF_LEAVE_CTRL = 0x85, - CONF_SCAN_DURATION = 0x86, - CONF_LOGICAL_TYPE = 0x87, - CONF_NWKMGR_MIN_TX = 0x88, - CONF_NWKMGR_ADDR = 0x89, - CONF_ZDO_DIRECT_CB = 0x8F, - CONF_TCLK_TABLE_START = 0x0101, - ZNP_HAS_CONFIGURED = 0xF00 -}; -# 210 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -enum Z_Status { - Z_Success = 0x00, - Z_Failure = 0x01, - Z_InvalidParameter = 0x02, - Z_MemError = 0x03, - Z_Created = 0x09, - Z_BufferFull = 0x11 -}; - -enum Z_App_Profiles { - Z_PROF_IPM = 0x0101, - Z_PROF_HA = 0x0104, - Z_PROF_CBA = 0x0105, - Z_PROF_TA = 0x0107, - Z_PROF_PHHC = 0x0108, - Z_PROF_AMI = 0x0109, -}; - -enum Z_Device_Ids { - Z_DEVID_CONF_TOOL = 0x0005, -# 262 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -}; -# 275 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_0_constants.ino" -enum AfCommand : uint8_t { - AF_REGISTER = 0x00, - AF_DATA_REQUEST = 0x01, - AF_DATA_REQUEST_EXT = 0x02, - AF_DATA_REQUEST_SRC_RTG = 0x03, - AF_INTER_PAN_CTL = 0x10, - AF_DATA_STORE = 0x11, - AF_DATA_RETRIEVE = 0x12, - AF_APSF_CONFIG_SET = 0x13, - AF_DATA_CONFIRM = 0x80, - AF_REFLECT_ERROR = 0x83, - AF_INCOMING_MSG = 0x81, - AF_INCOMING_MSG_EXT = 0x82 -}; - - -enum : uint8_t { - ZDO_NWK_ADDR_REQ = 0x00, - ZDO_IEEE_ADDR_REQ = 0x01, - ZDO_NODE_DESC_REQ = 0x02, - ZDO_POWER_DESC_REQ = 0x03, - ZDO_SIMPLE_DESC_REQ = 0x04, - ZDO_ACTIVE_EP_REQ = 0x05, - ZDO_MATCH_DESC_REQ = 0x06, - ZDO_COMPLEX_DESC_REQ = 0x07, - ZDO_USER_DESC_REQ = 0x08, - ZDO_DEVICE_ANNCE = 0x0A, - ZDO_USER_DESC_SET = 0x0B, - ZDO_SERVER_DISC_REQ = 0x0C, - ZDO_END_DEVICE_BIND_REQ = 0x20, - ZDO_BIND_REQ = 0x21, - ZDO_UNBIND_REQ = 0x22, - ZDO_SET_LINK_KEY = 0x23, - ZDO_REMOVE_LINK_KEY = 0x24, - ZDO_GET_LINK_KEY = 0x25, - ZDO_MGMT_NWK_DISC_REQ = 0x30, - ZDO_MGMT_LQI_REQ = 0x31, - ZDO_MGMT_RTQ_REQ = 0x32, - ZDO_MGMT_BIND_REQ = 0x33, - ZDO_MGMT_LEAVE_REQ = 0x34, - ZDO_MGMT_DIRECT_JOIN_REQ = 0x35, - ZDO_MGMT_PERMIT_JOIN_REQ = 0x36, - ZDO_MGMT_NWK_UPDATE_REQ = 0x37, - ZDO_MSG_CB_REGISTER = 0x3E, - ZDO_MGS_CB_REMOVE = 0x3F, - ZDO_STARTUP_FROM_APP = 0x40, - ZDO_AUTO_FIND_DESTINATION = 0x41, - ZDO_EXT_REMOVE_GROUP = 0x47, - ZDO_EXT_REMOVE_ALL_GROUP = 0x48, - ZDO_EXT_FIND_ALL_GROUPS_ENDPOINT = 0x49, - ZDO_EXT_FIND_GROUP = 0x4A, - ZDO_EXT_ADD_GROUP = 0x4B, - ZDO_EXT_COUNT_ALL_GROUPS = 0x4C, - ZDO_NWK_ADDR_RSP = 0x80, - ZDO_IEEE_ADDR_RSP = 0x81, - ZDO_NODE_DESC_RSP = 0x82, - ZDO_POWER_DESC_RSP = 0x83, - ZDO_SIMPLE_DESC_RSP = 0x84, - ZDO_ACTIVE_EP_RSP = 0x85, - ZDO_MATCH_DESC_RSP = 0x86, - ZDO_COMPLEX_DESC_RSP = 0x87, - ZDO_USER_DESC_RSP = 0x88, - ZDO_USER_DESC_CONF = 0x89, - ZDO_SERVER_DISC_RSP = 0x8A, - ZDO_END_DEVICE_BIND_RSP = 0xA0, - ZDO_BIND_RSP = 0xA1, - ZDO_UNBIND_RSP = 0xA2, - ZDO_MGMT_NWK_DISC_RSP = 0xB0, - ZDO_MGMT_LQI_RSP = 0xB1, - ZDO_MGMT_RTG_RSP = 0xB2, - ZDO_MGMT_BIND_RSP = 0xB3, - ZDO_MGMT_LEAVE_RSP = 0xB4, - ZDO_MGMT_DIRECT_JOIN_RSP = 0xB5, - ZDO_MGMT_PERMIT_JOIN_RSP = 0xB6, - ZDO_STATE_CHANGE_IND = 0xC0, - ZDO_END_DEVICE_ANNCE_IND = 0xC1, - ZDO_MATCH_DESC_RSP_SENT = 0xC2, - ZDO_STATUS_ERROR_RSP = 0xC3, - ZDO_SRC_RTG_IND = 0xC4, - ZDO_LEAVE_IND = 0xC9, - ZDO_TC_DEV_IND = 0xCA, - ZDO_PERMIT_JOIN_IND = 0xCB, - ZDO_MSG_CB_INCOMING = 0xFF -}; - - -enum ZdoStates { - ZDO_DEV_HOLD = 0x00, - ZDO_DEV_INIT = 0x01, - ZDO_DEV_NWK_DISC = 0x02, - ZDO_DEV_NWK_JOINING = 0x03, - ZDO_DEV_NWK_REJOIN = 0x04, - ZDO_DEV_END_DEVICE_UNAUTH = 0x05, - ZDO_DEV_END_DEVICE = 0x06, - ZDO_DEV_ROUTER = 0x07, - ZDO_DEV_COORD_STARTING = 0x08, - ZDO_DEV_ZB_COORD = 0x09, - ZDO_DEV_NWK_ORPHAN = 0x0A, -}; - - -enum Z_Util { - Z_UTIL_GET_DEVICE_INFO = 0x00, - Z_UTIL_GET_NV_INFO = 0x01, - Z_UTIL_SET_PANID = 0x02, - Z_UTIL_SET_CHANNELS = 0x03, - Z_UTIL_SET_SECLEVEL = 0x04, - Z_UTIL_SET_PRECFGKEY = 0x05, - Z_UTIL_CALLBACK_SUB_CMD = 0x06, - Z_UTIL_KEY_EVENT = 0x07, - Z_UTIL_TIME_ALIVE = 0x09, - Z_UTIL_LED_CONTROL = 0x0A, - Z_UTIL_TEST_LOOPBACK = 0x10, - Z_UTIL_DATA_REQ = 0x11, - Z_UTIL_SRC_MATCH_ENABLE = 0x20, - Z_UTIL_SRC_MATCH_ADD_ENTRY = 0x21, - Z_UTIL_SRC_MATCH_DEL_ENTRY = 0x22, - Z_UTIL_SRC_MATCH_CHECK_SRC_ADDR = 0x23, - Z_UTIL_SRC_MATCH_ACK_ALL_PENDING = 0x24, - Z_UTIL_SRC_MATCH_CHECK_ALL_PENDING = 0x25, - Z_UTIL_ADDRMGR_EXT_ADDR_LOOKUP = 0x40, - Z_UTIL_ADDRMGR_NWK_ADDR_LOOKUP = 0x41, - Z_UTIL_APSME_LINK_KEY_DATA_GET = 0x44, - Z_UTIL_APSME_LINK_KEY_NV_ID_GET = 0x45, - Z_UTIL_ASSOC_COUNT = 0x48, - Z_UTIL_ASSOC_FIND_DEVICE = 0x49, - Z_UTIL_ASSOC_GET_WITH_ADDRESS = 0x4A, - Z_UTIL_APSME_REQUEST_KEY_CMD = 0x4B, - Z_UTIL_ZCL_KEY_EST_INIT_EST = 0x80, - Z_UTIL_ZCL_KEY_EST_SIGN = 0x81, - Z_UTIL_UTIL_SYNC_REQ = 0xE0, - Z_UTIL_ZCL_KEY_ESTABLISH_IND = 0xE1 -}; - -enum ZCL_Global_Commands { - ZCL_READ_ATTRIBUTES = 0x00, - ZCL_READ_ATTRIBUTES_RESPONSE = 0x01, - ZCL_WRITE_ATTRIBUTES = 0x02, - ZCL_WRITE_ATTRIBUTES_UNDIVIDED = 0x03, - ZCL_WRITE_ATTRIBUTES_RESPONSE = 0x04, - ZCL_WRITE_ATTRIBUTES_NORESPONSE = 0x05, - ZCL_CONFIGURE_REPORTING = 0x06, - ZCL_CONFIGURE_REPORTING_RESPONSE = 0x07, - ZCL_READ_REPORTING_CONFIGURATION = 0x08, - ZCL_READ_REPORTING_CONFIGURATION_RESPONSE = 0x09, - ZCL_REPORT_ATTRIBUTES = 0x0a, - ZCL_DEFAULT_RESPONSE = 0x0b, - ZCL_DISCOVER_ATTRIBUTES = 0x0c, - ZCL_DISCOVER_ATTRIBUTES_RESPONSE = 0x0d - -}; - -const uint16_t Z_ProfileIds[] PROGMEM = { 0x0104, 0x0109, 0xA10E, 0xC05E }; -const char Z_ProfileNames[] PROGMEM = "ZigBee Home Automation|ZigBee Smart Energy|ZigBee Green Power|ZigBee Light Link"; - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_1_headers.ino" -#ifdef USE_ZIGBEE - - - -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId); - - - -JsonVariant &getCaseInsensitive(const JsonObject &json, const char *needle) { - - if ((nullptr == &json) || (nullptr == needle) || (0 == pgm_read_byte(needle))) { - return *(JsonVariant*)nullptr; - } - - for (auto kv : json) { - const char *key = kv.key; - JsonVariant &value = kv.value; - - if (0 == strcasecmp_P(key, needle)) { - return value; - } - } - - return *(JsonVariant*)nullptr; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -#ifdef USE_ZIGBEE - -#ifndef ZIGBEERECEIVED -#define ZIGBEERECEIVED 1 -#endif - -#include -#include - -#ifndef ZIGBEE_SAVE_DELAY_SECONDS -#define ZIGBEE_SAVE_DELAY_SECONDS 10; -#endif -const uint16_t kZigbeeSaveDelaySeconds = ZIGBEE_SAVE_DELAY_SECONDS; - -typedef int32_t (*Z_DeviceTimer)(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value); - -typedef struct Z_Device { - uint16_t shortaddr; - uint64_t longaddr; - uint32_t firstSeen; - uint32_t lastSeen; - String manufacturerId; - String modelId; - String friendlyName; - std::vector endpoints; - std::vector clusters_in; - std::vector clusters_out; - - uint32_t timer; - uint16_t cluster; - uint16_t endpoint; - uint32_t value; - Z_DeviceTimer func; - - DynamicJsonBuffer *json_buffer; - JsonObject *json; - - uint8_t seqNumber; -} Z_Device; - - - - - - - -class Z_Devices { -public: - Z_Devices() {}; - - - - - - - uint16_t isKnownShortAddr(uint16_t shortaddr) const; - uint16_t isKnownLongAddr(uint64_t longaddr) const; - uint16_t isKnownIndex(uint32_t index) const; - uint16_t isKnownFriendlyName(const char * name) const; - - uint64_t getDeviceLongAddr(uint16_t shortaddr) const; - - - - void updateDevice(uint16_t shortaddr, uint64_t longaddr = 0); - - - void addEndoint(uint16_t shortaddr, uint8_t endpoint); - - - void addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId); - - - void addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out); - - uint8_t findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster); - - void setManufId(uint16_t shortaddr, const char * str); - void setModelId(uint16_t shortaddr, const char * str); - void setFriendlyName(uint16_t shortaddr, const char * str); - const String * getFriendlyName(uint16_t) const; - - - void updateLastSeen(uint16_t shortaddr); - - - uint8_t getNextSeqNumber(uint16_t shortaddr); - - - String dump(uint32_t dump_mode, uint16_t status_shortaddr = 0) const; - - - void resetTimer(uint32_t shortaddr); - void setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func); - void runTimer(void); - - - void jsonClear(uint16_t shortaddr); - void jsonAppend(uint16_t shortaddr, const JsonObject &values); - const JsonObject *jsonGet(uint16_t shortaddr); - void jsonPublishFlush(uint16_t shortaddr); - bool jsonIsConflict(uint16_t shortaddr, const JsonObject &values); - void jsonPublishNow(uint16_t shortaddr, JsonObject &values); - - - size_t devicesSize(void) const { - return _devices.size(); - } - const Z_Device &devicesAt(size_t i) const { - return _devices.at(i); - } - - - bool removeDevice(uint16_t shortaddr); - - - void dirty(void); - void clean(void); - - - uint16_t parseDeviceParam(const char * param, bool short_must_be_known = false) const; - -private: - std::vector _devices = {}; - uint32_t _saveTimer = 0; - uint8_t _seqNumber = 0; - - template < typename T> - static bool findInVector(const std::vector & vecOfElements, const T & element); - - template < typename T> - static int32_t findEndpointInVector(const std::vector & vecOfElements, uint8_t element); - - - static int32_t findClusterEndpoint(const std::vector & vecOfElements, uint16_t element); - - Z_Device & getShortAddr(uint16_t shortaddr); - const Z_Device & getShortAddrConst(uint16_t shortaddr) const ; - Z_Device & getLongAddr(uint64_t longaddr); - - int32_t findShortAddr(uint16_t shortaddr) const; - int32_t findLongAddr(uint64_t longaddr) const; - int32_t findFriendlyName(const char * name) const; - - void _updateLastSeen(Z_Device &device) { - if (&device != nullptr) { - device.lastSeen = Rtc.utc_time; - } - }; - - - Z_Device & createDeviceEntry(uint16_t shortaddr, uint64_t longaddr = 0); -}; - -Z_Devices zigbee_devices = Z_Devices(); - - -uint64_t localIEEEAddr = 0; - - -template < typename T> -bool Z_Devices::findInVector(const std::vector & vecOfElements, const T & element) { - - auto it = std::find(vecOfElements.begin(), vecOfElements.end(), element); - - if (it != vecOfElements.end()) { - return true; - } else { - return false; - } -} - -template < typename T> -int32_t Z_Devices::findEndpointInVector(const std::vector & vecOfElements, uint8_t element) { - - - int32_t found = 0; - for (auto &elem : vecOfElements) { - if ( ((elem >> 16) & 0xFF) == element) { return found; } - found++; - } - - return -1; -} -# 214 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -int32_t Z_Devices::findClusterEndpoint(const std::vector & vecOfElements, uint16_t cluster) { - int32_t found = 0; - for (auto &elem : vecOfElements) { - if ((elem & 0xFFFF) == cluster) { return found; } - found++; - } - return -1; -} - - - - - -Z_Device & Z_Devices::createDeviceEntry(uint16_t shortaddr, uint64_t longaddr) { - if (!shortaddr && !longaddr) { return *(Z_Device*) nullptr; } - Z_Device device = { shortaddr, longaddr, - Rtc.utc_time, Rtc.utc_time, - String(), - String(), - String(), - std::vector(), - std::vector(), - std::vector(), - 0,0,0,0, - nullptr, - nullptr, nullptr, - 0, - }; - device.json_buffer = new DynamicJsonBuffer(); - _devices.push_back(device); - dirty(); - return _devices.back(); -} -# 256 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -int32_t Z_Devices::findShortAddr(uint16_t shortaddr) const { - if (!shortaddr) { return -1; } - int32_t found = 0; - if (shortaddr) { - for (auto &elem : _devices) { - if (elem.shortaddr == shortaddr) { return found; } - found++; - } - } - return -1; -} -# 275 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -int32_t Z_Devices::findLongAddr(uint64_t longaddr) const { - if (!longaddr) { return -1; } - int32_t found = 0; - if (longaddr) { - for (auto &elem : _devices) { - if (elem.longaddr == longaddr) { return found; } - found++; - } - } - return -1; -} -# 294 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" -int32_t Z_Devices::findFriendlyName(const char * name) const { - if (!name) { return -1; } - size_t name_len = strlen(name); - int32_t found = 0; - if (name_len) { - for (auto &elem : _devices) { - if (elem.friendlyName == name) { return found; } - found++; - } - } - return -1; -} - - -uint16_t Z_Devices::isKnownShortAddr(uint16_t shortaddr) const { - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - return shortaddr; - } else { - return 0; - } -} - -uint16_t Z_Devices::isKnownLongAddr(uint64_t longaddr) const { - int32_t found = findLongAddr(longaddr); - if (found >= 0) { - const Z_Device & device = devicesAt(found); - return device.shortaddr; - } else { - return 0; - } -} - -uint16_t Z_Devices::isKnownIndex(uint32_t index) const { - if (index < devicesSize()) { - const Z_Device & device = devicesAt(index); - return device.shortaddr; - } else { - return 0; - } -} - -uint16_t Z_Devices::isKnownFriendlyName(const char * name) const { - if ((!name) || (0 == strlen(name))) { return 0xFFFF; } - int32_t found = findFriendlyName(name); - if (found >= 0) { - const Z_Device & device = devicesAt(found); - return device.shortaddr; - } else { - return 0; - } -} - -uint64_t Z_Devices::getDeviceLongAddr(uint16_t shortaddr) const { - const Z_Device & device = getShortAddrConst(shortaddr); - return device.longaddr; -} - - - - -Z_Device & Z_Devices::getShortAddr(uint16_t shortaddr) { - if (!shortaddr) { return *(Z_Device*) nullptr; } - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - return _devices[found]; - } - - return createDeviceEntry(shortaddr, 0); -} - -const Z_Device & Z_Devices::getShortAddrConst(uint16_t shortaddr) const { - if (!shortaddr) { return *(Z_Device*) nullptr; } - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - return _devices[found]; - } - return *((Z_Device*)nullptr); -} - - -Z_Device & Z_Devices::getLongAddr(uint64_t longaddr) { - if (!longaddr) { return *(Z_Device*) nullptr; } - int32_t found = findLongAddr(longaddr); - if (found > 0) { - return _devices[found]; - } - return createDeviceEntry(0, longaddr); -} - - -bool Z_Devices::removeDevice(uint16_t shortaddr) { - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - _devices.erase(_devices.begin() + found); - dirty(); - return true; - } - return false; -} - - - - - - -void Z_Devices::updateDevice(uint16_t shortaddr, uint64_t longaddr) { - int32_t s_found = findShortAddr(shortaddr); - int32_t l_found = findLongAddr(longaddr); - - if ((s_found >= 0) && (l_found >= 0)) { - if (s_found == l_found) { - updateLastSeen(shortaddr); - } else { - - _devices[l_found].shortaddr = shortaddr; - - _devices.erase(_devices.begin() + s_found); - updateLastSeen(shortaddr); - dirty(); - } - } else if (s_found >= 0) { - - - _devices[s_found].longaddr = longaddr; - updateLastSeen(shortaddr); - dirty(); - } else if (l_found >= 0) { - - _devices[l_found].shortaddr = shortaddr; - dirty(); - } else { - - if (shortaddr || longaddr) { - createDeviceEntry(shortaddr, longaddr); - } - } -} - - - - -void Z_Devices::addEndoint(uint16_t shortaddr, uint8_t endpoint) { - if (!shortaddr) { return; } - uint32_t ep_profile = (endpoint << 16); - Z_Device &device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - if (findEndpointInVector(device.endpoints, endpoint) < 0) { - device.endpoints.push_back(ep_profile); - dirty(); - } -} - -void Z_Devices::addEndointProfile(uint16_t shortaddr, uint8_t endpoint, uint16_t profileId) { - if (!shortaddr) { return; } - uint32_t ep_profile = (endpoint << 16) | profileId; - Z_Device &device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - int32_t found = findEndpointInVector(device.endpoints, endpoint); - if (found < 0) { - device.endpoints.push_back(ep_profile); - dirty(); - } else { - if (device.endpoints[found] != ep_profile) { - device.endpoints[found] = ep_profile; - dirty(); - } - } -} - -void Z_Devices::addCluster(uint16_t shortaddr, uint8_t endpoint, uint16_t cluster, bool out) { - if (!shortaddr) { return; } - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - uint32_t ep_cluster = (endpoint << 16) | cluster; - if (!out) { - if (!findInVector(device.clusters_in, ep_cluster)) { - device.clusters_in.push_back(ep_cluster); - dirty(); - } - } else { - if (!findInVector(device.clusters_out, ep_cluster)) { - device.clusters_out.push_back(ep_cluster); - dirty(); - } - } -} - - - -uint8_t Z_Devices::findClusterEndpointIn(uint16_t shortaddr, uint16_t cluster){ - int32_t short_found = findShortAddr(shortaddr); - if (short_found < 0) return 0; - Z_Device &device = getShortAddr(shortaddr); - if (&device == nullptr) { return 0; } - int32_t found = findClusterEndpoint(device.clusters_in, cluster); - if (found >= 0) { - return (device.clusters_in[found] >> 16) & 0xFF; - } else { - return 0; - } -} - - -void Z_Devices::setManufId(uint16_t shortaddr, const char * str) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - if (!device.manufacturerId.equals(str)) { - dirty(); - } - device.manufacturerId = str; -} -void Z_Devices::setModelId(uint16_t shortaddr, const char * str) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - if (!device.modelId.equals(str)) { - dirty(); - } - device.modelId = str; -} -void Z_Devices::setFriendlyName(uint16_t shortaddr, const char * str) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); - if (!device.friendlyName.equals(str)) { - dirty(); - } - device.friendlyName = str; -} - -const String * Z_Devices::getFriendlyName(uint16_t shortaddr) const { - int32_t found = findShortAddr(shortaddr); - if (found >= 0) { - const Z_Device & device = devicesAt(found); - if (device.friendlyName.length() > 0) { - return &device.friendlyName; - } - } - return nullptr; -} - - -void Z_Devices::updateLastSeen(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - _updateLastSeen(device); -} - - -uint8_t Z_Devices::getNextSeqNumber(uint16_t shortaddr) { - int32_t short_found = findShortAddr(shortaddr); - if (short_found >= 0) { - Z_Device &device = getShortAddr(shortaddr); - device.seqNumber += 1; - return device.seqNumber; - } else { - _seqNumber += 1; - return _seqNumber; - } -} - - - - -void Z_Devices::resetTimer(uint32_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - device.timer = 0; - device.func = nullptr; -} - - -void Z_Devices::setTimer(uint32_t shortaddr, uint32_t wait_ms, uint16_t cluster, uint16_t endpoint, uint32_t value, Z_DeviceTimer func) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - - device.cluster = cluster; - device.endpoint = endpoint; - device.value = value; - device.func = func; - device.timer = wait_ms + millis(); -} - - -void Z_Devices::runTimer(void) { - for (std::vector::iterator it = _devices.begin(); it != _devices.end(); ++it) { - Z_Device &device = *it; - uint16_t shortaddr = device.shortaddr; - - uint32_t timer = device.timer; - if ((timer) && TimeReached(timer)) { - device.timer = 0; - - (*device.func)(device.shortaddr, device.cluster, device.endpoint, device.value); - } - } - - if ((_saveTimer) && TimeReached(_saveTimer)) { - saveZigbeeDevices(); - _saveTimer = 0; - } -} - -void Z_Devices::jsonClear(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - - device.json = nullptr; - device.json_buffer->clear(); -} - -void CopyJsonVariant(JsonObject &to, const String &key, const JsonVariant &val) { - to.remove(key); - - if (val.is()) { - String sval = val.as(); - to.set(key, sval); - } else if (val.is()) { - JsonArray &nested_arr = to.createNestedArray(key); - CopyJsonArray(nested_arr, val.as()); - } else if (val.is()) { - JsonObject &nested_obj = to.createNestedObject(key); - CopyJsonObject(nested_obj, val.as()); - } else { - to.set(key, val); - } -} - -void CopyJsonArray(JsonArray &to, const JsonArray &arr) { - for (auto v : arr) { - if (v.is()) { - String sval = v.as(); - to.add(sval); - } else if (v.is()) { - } else if (v.is()) { - } else { - to.add(v); - } - } -} - -void CopyJsonObject(JsonObject &to, const JsonObject &from) { - for (auto kv : from) { - String key_string = kv.key; - JsonVariant &val = kv.value; - - CopyJsonVariant(to, key_string, val); - } -} - - -bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const JsonObject &values) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return false; } - if (&values == nullptr) { return false; } - - if (nullptr == device.json) { - return false; - } - - for (auto kv : values) { - String key_string = kv.key; - - if (strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_LINKQUALITY))) { - if (device.json->containsKey(kv.key)) { - return true; - } - } - } - return false; -} - -void Z_Devices::jsonAppend(uint16_t shortaddr, const JsonObject &values) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - if (&values == nullptr) { return; } - - if (nullptr == device.json) { - device.json = &(device.json_buffer->createObject()); - } - - char sa[8]; - snprintf_P(sa, sizeof(sa), PSTR("0x%04X"), shortaddr); - device.json->set(F(D_JSON_ZIGBEE_DEVICE), sa); - - const String * fname = zigbee_devices.getFriendlyName(shortaddr); - if (fname) { - device.json->set(F(D_JSON_ZIGBEE_NAME), (char*)fname->c_str()); - } - - - CopyJsonObject(*device.json, values); -} - -const JsonObject *Z_Devices::jsonGet(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return nullptr; } - return device.json; -} - -void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { - Z_Device & device = getShortAddr(shortaddr); - if (&device == nullptr) { return; } - JsonObject * json = device.json; - if (json == nullptr) { return; } - - const String * fname = zigbee_devices.getFriendlyName(shortaddr); - bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); -# 718 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_3_devices.ino" - if (use_fname) { - json->remove(F(D_JSON_ZIGBEE_NAME)); - } else { - json->remove(F(D_JSON_ZIGBEE_DEVICE)); - } - - String msg = ""; - json->printTo(msg); - zigbee_devices.jsonClear(shortaddr); - - if (use_fname) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); -#if ZIGBEERECEIVED - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); -#endif - } else { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); -#if ZIGBEERECEIVED - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); -#endif - } - - -} - -void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { - jsonPublishFlush(shortaddr); - jsonAppend(shortaddr, values); - jsonPublishFlush(shortaddr); -} - -void Z_Devices::dirty(void) { - _saveTimer = kZigbeeSaveDelaySeconds * 1000 + millis(); -} -void Z_Devices::clean(void) { - _saveTimer = 0; -} - - - - - - -uint16_t Z_Devices::parseDeviceParam(const char * param, bool short_must_be_known) const { - if (nullptr == param) { return 0; } - size_t param_len = strlen(param); - char dataBuf[param_len + 1]; - strcpy(dataBuf, param); - RemoveSpace(dataBuf); - uint16_t shortaddr = 0; - - if (strlen(dataBuf) < 4) { - - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 99)) { - shortaddr = zigbee_devices.isKnownIndex(XdrvMailbox.payload - 1); - } - } else if ((dataBuf[0] == '0') && (dataBuf[1] == 'x')) { - - if (strlen(dataBuf) < 18) { - - shortaddr = strtoull(dataBuf, nullptr, 0); - if (short_must_be_known) { - shortaddr = zigbee_devices.isKnownShortAddr(shortaddr); - } - - } else { - - uint64_t longaddr = strtoull(dataBuf, nullptr, 0); - shortaddr = zigbee_devices.isKnownLongAddr(longaddr); - } - } else { - - shortaddr = zigbee_devices.isKnownFriendlyName(dataBuf); - } - - return shortaddr; -} - - - - - -String Z_Devices::dump(uint32_t dump_mode, uint16_t status_shortaddr) const { - DynamicJsonBuffer jsonBuffer; - JsonArray& json = jsonBuffer.createArray(); - JsonArray& devices = json; - - for (std::vector::const_iterator it = _devices.begin(); it != _devices.end(); ++it) { - const Z_Device& device = *it; - uint16_t shortaddr = device.shortaddr; - char hex[22]; - - - if ((status_shortaddr) && (status_shortaddr != shortaddr)) { continue; } - - JsonObject& dev = devices.createNestedObject(); - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), shortaddr); - dev[F(D_JSON_ZIGBEE_DEVICE)] = hex; - - if (device.friendlyName.length() > 0) { - dev[F(D_JSON_ZIGBEE_NAME)] = device.friendlyName; - } - - if (2 <= dump_mode) { - hex[0] = '0'; - hex[1] = 'x'; - Uint64toHex(device.longaddr, &hex[2], 64); - dev[F("IEEEAddr")] = hex; - if (device.modelId.length() > 0) { - dev[F(D_JSON_MODEL D_JSON_ID)] = device.modelId; - } - if (device.manufacturerId.length() > 0) { - dev[F("Manufacturer")] = device.manufacturerId; - } - } - - - if (3 <= dump_mode) { - JsonObject& dev_endpoints = dev.createNestedObject(F("Endpoints")); - for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { - uint32_t ep_profile = *ite; - uint8_t endpoint = (ep_profile >> 16) & 0xFF; - uint16_t profileId = ep_profile & 0xFFFF; - - snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonObject& ep = dev_endpoints.createNestedObject(hex); - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), profileId); - ep[F("ProfileId")] = hex; - - int32_t found = -1; - for (uint32_t i = 0; i < sizeof(Z_ProfileIds) / sizeof(Z_ProfileIds[0]); i++) { - if (pgm_read_word(&Z_ProfileIds[i]) == profileId) { - found = i; - break; - } - } - if (found > 0) { - GetTextIndexed(hex, sizeof(hex), found, Z_ProfileNames); - ep[F("ProfileIdName")] = hex; - } - - ep.createNestedArray(F("ClustersIn")); - ep.createNestedArray(F("ClustersOut")); - } - - for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t endpoint = (*itc >> 16) & 0xFF; - - snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersIn")]; - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); - cluster_arr.add(hex); - } - - for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t endpoint = (*itc >> 16) & 0xFF; - - snprintf_P(hex, sizeof(hex), PSTR("0x%02X"), endpoint); - JsonArray &cluster_arr = dev_endpoints[hex][F("ClustersOut")]; - - snprintf_P(hex, sizeof(hex), PSTR("0x%04X"), cluster); - cluster_arr.add(hex); - } - } - } - String payload = ""; - payload.reserve(200); - json.printTo(payload); - return payload; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -#ifdef USE_ZIGBEE -# 50 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_4_persistence.ino" -const static uint16_t z_spi_start_sector = 0xFF; -const static uint8_t* z_spi_start = (uint8_t*) 0x402FF000; -const static uint8_t* z_dev_start = z_spi_start + 0x0800; -const static size_t z_spi_len = 0x1000; -const static size_t z_block_offset = 0x0800; -const static size_t z_block_len = 0x0800; - -class z_flashdata_t { -public: - uint32_t name; - uint16_t len; - uint16_t reserved; -}; - -const static uint32_t ZIGB_NAME = 0x3167697A; -const static size_t Z_MAX_FLASH = z_block_len - sizeof(z_flashdata_t); - - -const uint16_t Z_ClusterNumber[] PROGMEM = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0100, 0x0101, 0x0102, - 0x0201, 0x0202, 0x0203, 0x0204, - 0x0300, 0x0301, - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, - 0x0500, 0x0501, 0x0502, - 0x0700, 0x0701, 0x0702, - 0x0B00, 0x0B01, 0x0B02, 0x0B03, 0x0B04, 0x0B05, - 0x1000, - 0xFC0F, -}; - - -uint16_t fromClusterCode(uint8_t c) { - if (c >= sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0])) { - return 0xFFFF; - } - return pgm_read_word(&Z_ClusterNumber[c]); -} - - -uint8_t toClusterCode(uint16_t c) { - for (uint32_t i = 0; i < sizeof(Z_ClusterNumber)/sizeof(Z_ClusterNumber[0]); i++) { - if (c == pgm_read_word(&Z_ClusterNumber[i])) { - return i; - } - } - return 0xFF; -} - -class SBuffer hibernateDevice(const struct Z_Device &device) { - SBuffer buf(128); - - buf.add8(0x00); - buf.add16(device.shortaddr); - buf.add64(device.longaddr); - uint32_t endpoints = device.endpoints.size(); - if (endpoints > 254) { endpoints = 254; } - buf.add8(endpoints); - - for (std::vector::const_iterator ite = device.endpoints.begin() ; ite != device.endpoints.end(); ++ite) { - uint32_t ep_profile = *ite; - uint8_t endpoint = (ep_profile >> 16) & 0xFF; - uint16_t profileId = ep_profile & 0xFFFF; - - buf.add8(endpoint); - buf.add16(profileId); - for (std::vector::const_iterator itc = device.clusters_in.begin() ; itc != device.clusters_in.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t c_endpoint = (*itc >> 16) & 0xFF; - - if (endpoint == c_endpoint) { - uint8_t clusterCode = toClusterCode(cluster); - if (0xFF != clusterCode) { buf.add8(clusterCode); } - } - } - buf.add8(0xFF); - - for (std::vector::const_iterator itc = device.clusters_out.begin() ; itc != device.clusters_out.end(); ++itc) { - uint16_t cluster = *itc & 0xFFFF; - uint8_t c_endpoint = (*itc >> 16) & 0xFF; - - if (endpoint == c_endpoint) { - uint8_t clusterCode = toClusterCode(cluster); - if (0xFF != clusterCode) { buf.add8(clusterCode); } - } - } - buf.add8(0xFF); - } - - - size_t model_len = device.modelId.length(); - if (model_len > 32) { model_len = 32; } - buf.addBuffer(device.modelId.c_str(), model_len); - buf.add8(0x00); - - - size_t manuf_len = device.manufacturerId.length(); - if (manuf_len > 32) {manuf_len = 32; } - buf.addBuffer(device.manufacturerId.c_str(), manuf_len); - buf.add8(0x00); - - - size_t frname_len = device.friendlyName.length(); - if (frname_len > 32) {frname_len = 32; } - buf.addBuffer(device.friendlyName.c_str(), frname_len); - buf.add8(0x00); - - - buf.set8(0, buf.len()); - - return buf; -} - -class SBuffer hibernateDevices(void) { - SBuffer buf(2048); - - size_t devices_size = zigbee_devices.devicesSize(); - if (devices_size > 32) { devices_size = 32; } - buf.add8(devices_size); - - for (uint32_t i = 0; i < devices_size; i++) { - const Z_Device & device = zigbee_devices.devicesAt(i); - const SBuffer buf_device = hibernateDevice(device); - buf.addBuffer(buf_device); - } - - size_t buf_len = buf.len(); - if (buf_len > 2040) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Devices list too big to fit in Flash (%d)"), buf_len); - } - - - char *hex_char = (char*) malloc((buf_len * 2) + 2); - if (hex_char) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "ZbFlashStore %s"), - ToHex_P(buf.getBuffer(), buf_len, hex_char, (buf_len * 2) + 2)); - free(hex_char); - } - - return buf; -} - -void hidrateDevices(const SBuffer &buf) { - uint32_t buf_len = buf.len(); - if (buf_len <= 10) { return; } - - uint32_t k = 0; - uint32_t num_devices = buf.get8(k++); - - for (uint32_t i = 0; (i < num_devices) && (k < buf_len); i++) { - uint32_t dev_record_len = buf.get8(k); - - SBuffer buf_d = buf.subBuffer(k, dev_record_len); - - uint32_t d = 1; - uint16_t shortaddr = buf_d.get16(d); d += 2; - uint64_t longaddr = buf_d.get64(d); d += 8; - zigbee_devices.updateDevice(shortaddr, longaddr); - - uint32_t endpoints = buf_d.get8(d++); - for (uint32_t j = 0; j < endpoints; j++) { - uint8_t ep = buf_d.get8(d++); - uint16_t ep_profile = buf_d.get16(d); d += 2; - zigbee_devices.addEndointProfile(shortaddr, ep, ep_profile); - - - while (d < dev_record_len) { - uint8_t ep_cluster = buf_d.get8(d++); - if (0xFF == ep_cluster) { break; } - zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), false); - } - - while (d < dev_record_len) { - uint8_t ep_cluster = buf_d.get8(d++); - if (0xFF == ep_cluster) { break; } - zigbee_devices.addCluster(shortaddr, ep, fromClusterCode(ep_cluster), true); - } - } - - - char empty[] = ""; - - - uint32_t s_len = buf_d.strlen_s(d); - char *ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setModelId(shortaddr, ptr); - d += s_len + 1; - - - s_len = buf_d.strlen_s(d); - ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setManufId(shortaddr, ptr); - d += s_len + 1; - - - s_len = buf_d.strlen_s(d); - ptr = s_len ? buf_d.charptr(d) : empty; - zigbee_devices.setFriendlyName(shortaddr, ptr); - d += s_len + 1; - - - k += dev_record_len; - } -} - -void loadZigbeeDevices(void) { - z_flashdata_t flashdata; - memcpy_P(&flashdata, z_dev_start, sizeof(z_flashdata_t)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "Zigbee signature in Flash: %08X - %d"), flashdata.name, flashdata.len); - - - if ((flashdata.name == ZIGB_NAME) && (flashdata.len > 0)) { - uint16_t buf_len = flashdata.len; - - SBuffer buf(buf_len); - buf.addBuffer(z_dev_start + sizeof(z_flashdata_t), buf_len); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee devices data in Flash (%d bytes)"), buf_len); - hidrateDevices(buf); - zigbee_devices.clean(); - } else { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "No zigbee devices data in Flash")); - } -} - -void saveZigbeeDevices(void) { - SBuffer buf = hibernateDevices(); - size_t buf_len = buf.len(); - if (buf_len > Z_MAX_FLASH) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Buffer too big to fit in Flash (%d bytes)"), buf_len); - return; - } - - - uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); - if (!spi_buffer) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); - return; - } - - ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - - z_flashdata_t *flashdata = (z_flashdata_t*)(spi_buffer + z_block_offset); - flashdata->name = ZIGB_NAME; - flashdata->len = buf_len; - flashdata->reserved = 0; - - memcpy(spi_buffer + z_block_offset + sizeof(z_flashdata_t), buf.getBuffer(), buf_len); - - - if (ESP.flashEraseSector(z_spi_start_sector)) { - ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - } - - free(spi_buffer); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data store in Flash (0x%08X - %d bytes)"), z_dev_start, buf_len); -} - - -void eraseZigbeeDevices(void) { - zigbee_devices.clean(); - - uint8_t *spi_buffer = (uint8_t*) malloc(z_spi_len); - if (!spi_buffer) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer")); - return; - } - - ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - - - memset(spi_buffer + z_block_offset, 0xFF, z_block_len); - - - if (ESP.flashEraseSector(z_spi_start_sector)) { - ESP.flashWrite(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE); - } - - free(spi_buffer); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (0x%08X - %d bytes)"), z_dev_start, z_block_len); -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" -#ifdef USE_ZIGBEE - - - - - -typedef union ZCLHeaderFrameControl_t { - struct { - uint8_t frame_type : 2; - uint8_t manuf_specific : 1; - uint8_t direction : 1; - uint8_t disable_def_resp : 1; - uint8_t reserved : 3; - } b; - uint32_t d8; -} ZCLHeaderFrameControl_t; - - -class ZCLFrame { -public: - - ZCLFrame(uint8_t frame_control, uint16_t manuf_code, uint8_t transact_seq, uint8_t cmd_id, - const char *buf, size_t buf_len, uint16_t clusterid, uint16_t groupid, - uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, - uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, - uint32_t timestamp): - _cmd_id(cmd_id), _manuf_code(manuf_code), _transact_seq(transact_seq), - _payload(buf_len ? buf_len : 250), - _cluster_id(clusterid), _group_id(groupid), - _srcaddr(srcaddr), _srcendpoint(srcendpoint), _dstendpoint(dstendpoint), _wasbroadcast(wasbroadcast), - _linkquality(linkquality), _securityuse(securityuse), _seqnumber(seqnumber), - _timestamp(timestamp) - { - _frame_control.d8 = frame_control; - _payload.addBuffer(buf, buf_len); - }; - - - void log(void) { - char hex_char[_payload.len()*2+2]; - ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZCL_RECEIVED "\":{" - "\"groupid\":%d," "\"clusterid\":%d," "\"srcaddr\":\"0x%04X\"," - "\"srcendpoint\":%d," "\"dstendpoint\":%d," "\"wasbroadcast\":%d," - "\"" D_CMND_ZIGBEE_LINKQUALITY "\":%d," "\"securityuse\":%d," "\"seqnumber\":%d," - "\"timestamp\":%d," - "\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d," - "\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"), - _group_id, _cluster_id, _srcaddr, - _srcendpoint, _dstendpoint, _wasbroadcast, - _linkquality, _securityuse, _seqnumber, - _timestamp, - _frame_control, _manuf_code, _transact_seq, _cmd_id, - hex_char); - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); - } - } - - static ZCLFrame parseRawFrame(const SBuffer &buf, uint8_t offset, uint8_t len, uint16_t clusterid, uint16_t groupid, - uint16_t srcaddr, uint8_t srcendpoint, uint8_t dstendpoint, uint8_t wasbroadcast, - uint8_t linkquality, uint8_t securityuse, uint8_t seqnumber, - uint32_t timestamp) { - uint32_t i = offset; - ZCLHeaderFrameControl_t frame_control; - uint16_t manuf_code = 0; - uint8_t transact_seq; - uint8_t cmd_id; - - frame_control.d8 = buf.get8(i++); - if (frame_control.b.manuf_specific) { - manuf_code = buf.get16(i); - i += 2; - } - transact_seq = buf.get8(i++); - cmd_id = buf.get8(i++); - ZCLFrame zcl_frame(frame_control.d8, manuf_code, transact_seq, cmd_id, - (const char *)(buf.buf() + i), len + offset - i, - clusterid, groupid, - srcaddr, srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp); - return zcl_frame; - } - - bool isClusterSpecificCommand(void) { - return _frame_control.b.frame_type & 1; - } - - static void generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len); - void parseRawAttributes(JsonObject& json, uint8_t offset = 0); - void parseReadAttributes(JsonObject& json, uint8_t offset = 0); - void parseClusterSpecificCommand(JsonObject& json, uint8_t offset = 0); - void postProcessAttributes(uint16_t shortaddr, JsonObject& json); - - inline void setGroupId(uint16_t groupid) { - _group_id = groupid; - } - - inline void setClusterId(uint16_t clusterid) { - _cluster_id = clusterid; - } - - inline uint8_t getCmdId(void) const { - return _cmd_id; - } - - inline uint16_t getClusterId(void) const { - return _cluster_id; - } - - inline uint16_t getSrcEndpoint(void) const { - return _srcendpoint; - } - - const SBuffer &getPayload(void) const { - return _payload; - } - - uint16_t getManufCode(void) const { - return _manuf_code; - } - -private: - ZCLHeaderFrameControl_t _frame_control = { .d8 = 0 }; - uint16_t _manuf_code = 0; - uint8_t _transact_seq = 0; - uint8_t _cmd_id = 0; - uint16_t _cluster_id = 0; - uint16_t _group_id = 0; - SBuffer _payload; - - uint16_t _srcaddr; - uint8_t _srcendpoint; - uint8_t _dstendpoint; - uint8_t _wasbroadcast; - uint8_t _linkquality; - uint8_t _securityuse; - uint8_t _seqnumber; - uint32_t _timestamp; -}; - - - - - - -uint8_t toPercentageCR2032(uint32_t voltage) { - uint32_t percentage; - if (voltage < 2100) { - percentage = 0; - } else if (voltage < 2440) { - percentage = 6 - ((2440 - voltage) * 6) / 340; - } else if (voltage < 2740) { - percentage = 18 - ((2740 - voltage) * 12) / 300; - } else if (voltage < 2900) { - percentage = 42 - ((2900 - voltage) * 24) / 160; - } else if (voltage < 3000) { - percentage = 100 - ((3000 - voltage) * 58) / 100; - } else if (voltage >= 3000) { - percentage = 100; - } - return percentage; -} - - -uint32_t parseSingleAttribute(JsonObject& json, char *attrid_str, class SBuffer &buf, - uint32_t offset, uint32_t len) { - - uint32_t i = offset; - uint32_t attrtype = buf.get8(i++); - - - json[attrid_str] = (char*) nullptr; - - - switch (attrtype) { - case 0x00: - case 0xFF: - break; - case 0x10: - { - uint8_t val_bool = buf.get8(i++); - if (0xFF != val_bool) { - json[attrid_str] = (bool) (val_bool ? true : false); - } - } - break; - case 0x20: - { - uint8_t uint8_val = buf.get8(i); - i += 1; - if (0xFF != uint8_val) { - json[attrid_str] = uint8_val; - } - } - break; - case 0x21: - { - uint16_t uint16_val = buf.get16(i); - i += 2; - if (0xFFFF != uint16_val) { - json[attrid_str] = uint16_val; - } - } - break; - case 0x23: - { - uint32_t uint32_val = buf.get32(i); - i += 4; - if (0xFFFFFFFF != uint32_val) { - json[attrid_str] = uint32_val; - } - } - break; - - case 0x24: - case 0x25: - case 0x26: - case 0x27: - { - uint8_t len = attrtype - 0x1F; - - char hex[2*len+1]; - ToHex_P(buf.buf(i), len, hex, sizeof(hex)); - json[attrid_str] = hex; - i += len; - } - break; - case 0x28: - { - int8_t int8_val = buf.get8(i); - i += 1; - if (0x80 != int8_val) { - json[attrid_str] = int8_val; - } - } - break; - case 0x29: - { - int16_t int16_val = buf.get16(i); - i += 2; - if (0x8000 != int16_val) { - json[attrid_str] = int16_val; - } - } - break; - case 0x2B: - { - int32_t int32_val = buf.get32(i); - i += 4; - if (0x80000000 != int32_val) { - json[attrid_str] = int32_val; - } - } - break; - - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - { - uint8_t len = attrtype - 0x27; - - char hex[2*len+1]; - ToHex_P(buf.buf(i), len, hex, sizeof(hex)); - json[attrid_str] = hex; - i += len; - } - break; - - case 0x41: - case 0x42: - case 0x43: - case 0x44: - - { - bool parse_as_string = true; - uint32_t len = (attrtype <= 0x42) ? buf.get8(i) : buf.get16(i); - i += (attrtype <= 0x42) ? 1 : 2; - if (i + len > buf.len()) { - len = buf.len() - i; - } - - - if ((0x41 == attrtype) || (0x43 == attrtype)) { parse_as_string = false; } -# 318 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" - if (parse_as_string) { - char str[len+1]; - strncpy(str, buf.charptr(i), len); - str[len] = 0x00; - json[attrid_str] = str; - } else { - - char hex[2*len+1]; - ToHex_P(buf.buf(i), len, hex, sizeof(hex)); - json[attrid_str] = hex; - } - - i += len; - break; - } - i += buf.get8(i) + 1; - break; - - case 0x08: - case 0x18: - { - uint8_t uint8_val = buf.get8(i); - i += 1; - json[attrid_str] = uint8_val; - } - break; - case 0x09: - case 0x19: - { - uint16_t uint16_val = buf.get16(i); - i += 2; - json[attrid_str] = uint16_val; - } - break; - case 0x0B: - case 0x1B: - { - uint32_t uint32_val = buf.get32(i); - i += 4; - json[attrid_str] = uint32_val; - } - break; - - case 0x30: - case 0x31: - i += attrtype - 0x2F; - break; - - - case 0x39: - { - uint32_t uint32_val = buf.get32(i); - float * float_val = (float*) &uint32_val; - i += 4; - json[attrid_str] = *float_val; - } - break; - - case 0xE0: - case 0xE1: - case 0xE2: - i += 4; - break; - - case 0xE8: - case 0xE9: - i += 2; - break; - case 0xEA: - i += 4; - break; - - case 0xF0: - i += 8; - break; - case 0xF1: - i += 16; - break; - - - case 0x0A: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - i += attrtype - 0x07; - break; - - case 0x1A: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - i += attrtype - 0x17; - break; - - case 0x38: - i += 2; - break; - case 0x3A: - { - uint64_t uint64_val = buf.get64(i); - double * double_val = (double*) &uint64_val; - i += 8; - json[attrid_str] = *double_val; - } - break; - } - - - - - - - return i - offset; -} - - -void ZCLFrame::generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len) { - uint32_t suffix = 1; - - snprintf_P(key, key_len, PSTR("%04X/%04X"), cluster, attr); - while (json.containsKey(key)) { - suffix++; - snprintf_P(key, key_len, PSTR("%04X/%04X+%d"), cluster, attr, suffix); - } -} - - -void ZCLFrame::parseRawAttributes(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - - while (len >= i + 3) { - uint16_t attrid = _payload.get16(i); - i += 2; - - char key[16]; - generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); - - - if ((0x0000 == _cluster_id) && (0xFF01 == attrid)) { - if (0x42 == _payload.get8(i)) { - _payload.set8(i, 0x41); - } - } - i += parseSingleAttribute(json, key, _payload, i, len); - } -} - - -void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { - uint32_t i = offset; - uint32_t len = _payload.len(); - - while (len - i >= 4) { - uint16_t attrid = _payload.get16(i); - i += 2; - uint8_t status = _payload.get8(i++); - - if (0 == status) { - char key[16]; - generateAttributeName(json, _cluster_id, attrid, key, sizeof(key)); - - i += parseSingleAttribute(json, key, _payload, i, len); - } - } -} - - - -void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { - convertClusterSpecific(json, _cluster_id, _cmd_id, _frame_control.b.direction, _payload); -} - - - - -typedef int32_t (*Z_AttrConverter)(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr); -typedef struct Z_AttributeConverter { - uint16_t cluster; - uint16_t attribute; - const char * name; - Z_AttrConverter func; -} Z_AttributeConverter; - - -const Z_AttributeConverter Z_PostProcess[] PROGMEM = { - { 0x0000, 0x0000, "ZCLVersion", &Z_Copy }, - { 0x0000, 0x0001, "AppVersion", &Z_Copy }, - { 0x0000, 0x0002, "StackVersion", &Z_Copy }, - { 0x0000, 0x0003, "HWVersion", &Z_Copy }, - { 0x0000, 0x0004, "Manufacturer", &Z_ManufKeep }, - { 0x0000, 0x0005, D_JSON_MODEL D_JSON_ID, &Z_ModelKeep }, - { 0x0000, 0x0006, "DateCode", &Z_Copy }, - { 0x0000, 0x0007, "PowerSource", &Z_Copy }, - { 0x0000, 0x4000, "SWBuildID", &Z_Copy }, - { 0x0000, 0xFFFF, nullptr, &Z_Remove }, - - { 0x0000, 0xFF01, nullptr, &Z_AqaraSensor }, - - - { 0x0001, 0x0000, "MainsVoltage", &Z_Copy }, - { 0x0001, 0x0001, "MainsFrequency", &Z_Copy }, - { 0x0001, 0x0020, "BatteryVoltage", &Z_Copy }, - { 0x0001, 0x0021, "BatteryPercentageRemaining",&Z_Copy }, - - - { 0x0002, 0x0000, "CurrentTemperature", &Z_Copy }, - { 0x0002, 0x0001, "MinTempExperienced", &Z_Copy }, - { 0x0002, 0x0002, "MaxTempExperienced", &Z_Copy }, - { 0x0002, 0x0003, "OverTempTotalDwell", &Z_Copy }, - - - { 0x0006, 0x0000, "Power", &Z_Copy }, - { 0x0006, 0x8000, "Power", &Z_Copy }, - - - { 0x0007, 0x0000, "SwitchType", &Z_Copy }, - - - { 0x0008, 0x0000, "Dimmer", &Z_Copy }, -# 548 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" - { 0x0009, 0x0000, "AlarmCount", &Z_Copy }, - - { 0x000A, 0x0000, "Time", &Z_Copy }, - { 0x000A, 0x0001, "TimeStatus", &Z_Copy }, - { 0x000A, 0x0002, "TimeZone", &Z_Copy }, - { 0x000A, 0x0003, "DstStart", &Z_Copy }, - { 0x000A, 0x0004, "DstStart", &Z_Copy }, - { 0x000A, 0x0005, "DstShift", &Z_Copy }, - { 0x000A, 0x0006, "StandardTime", &Z_Copy }, - { 0x000A, 0x0007, "LocalTime", &Z_Copy }, - { 0x000A, 0x0008, "LastSetTime", &Z_Copy }, - { 0x000A, 0x0009, "ValidUntilTime", &Z_Copy }, - - { 0x000B, 0x0000, "LocationType", &Z_Copy }, - { 0x000B, 0x0000, "LocationMethod", &Z_Copy }, - { 0x000B, 0x0000, "LocationAge", &Z_Copy }, - { 0x000B, 0x0000, "QualityMeasure", &Z_Copy }, - { 0x000B, 0x0000, "NumberOfDevices", &Z_Copy }, - - { 0x000C, 0x0004, "ActiveText", &Z_Copy }, - { 0x000C, 0x001C, "Description", &Z_Copy }, - { 0x000C, 0x002E, "InactiveText", &Z_Copy }, - { 0x000C, 0x0041, "MaxPresentValue", &Z_Copy }, - { 0x000C, 0x0045, "MinPresentValue", &Z_Copy }, - { 0x000C, 0x0051, "OutOfService", &Z_Copy }, - { 0x000C, 0x0055, "AqaraRotate", &Z_Copy }, - { 0x000C, 0x0057, "PriorityArray", &Z_Copy }, - { 0x000C, 0x0067, "Reliability", &Z_Copy }, - { 0x000C, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x000C, 0x006A, "Resolution", &Z_Copy }, - { 0x000C, 0x006F, "StatusFlags", &Z_Copy }, - { 0x000C, 0x0075, "EngineeringUnits", &Z_Copy }, - { 0x000C, 0x0100, "ApplicationType", &Z_Copy }, - { 0x000C, 0xFF05, "Aqara_FF05", &Z_Copy }, - - { 0x0010, 0x0004, "ActiveText", &Z_Copy }, - { 0x0010, 0x001C, "Description", &Z_Copy }, - { 0x0010, 0x002E, "InactiveText", &Z_Copy }, - { 0x0010, 0x0042, "MinimumOffTime", &Z_Copy }, - { 0x0010, 0x0043, "MinimumOnTime", &Z_Copy }, - { 0x0010, 0x0051, "OutOfService", &Z_Copy }, - { 0x0010, 0x0054, "Polarity", &Z_Copy }, - { 0x0010, 0x0055, "PresentValue", &Z_Copy }, - { 0x0010, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0010, 0x0067, "Reliability", &Z_Copy }, - { 0x0010, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0010, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0010, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x0011, 0x0004, "ActiveText", &Z_Copy }, - { 0x0011, 0x001C, "Description", &Z_Copy }, - { 0x0011, 0x002E, "InactiveText", &Z_Copy }, - { 0x0011, 0x0042, "MinimumOffTime", &Z_Copy }, - { 0x0011, 0x0043, "MinimumOnTime", &Z_Copy }, - { 0x0011, 0x0051, "OutOfService", &Z_Copy }, - { 0x0011, 0x0055, "PresentValue", &Z_Copy }, - { 0x0011, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0011, 0x0067, "Reliability", &Z_Copy }, - { 0x0011, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0011, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0011, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x0012, 0x000E, "StateText", &Z_Copy }, - { 0x0012, 0x001C, "Description", &Z_Copy }, - { 0x0012, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0012, 0x0051, "OutOfService", &Z_Copy }, - { 0x0012, 0x0055, "PresentValue", &Z_AqaraCube }, - { 0x0012, 0x0067, "Reliability", &Z_Copy }, - { 0x0012, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0012, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x0013, 0x000E, "StateText", &Z_Copy }, - { 0x0013, 0x001C, "Description", &Z_Copy }, - { 0x0013, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0013, 0x0051, "OutOfService", &Z_Copy }, - { 0x0013, 0x0055, "PresentValue", &Z_Copy }, - { 0x0013, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0013, 0x0067, "Reliability", &Z_Copy }, - { 0x0013, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0013, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0013, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x0014, 0x000E, "StateText", &Z_Copy }, - { 0x0014, 0x001C, "Description", &Z_Copy }, - { 0x0014, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0014, 0x0051, "OutOfService", &Z_Copy }, - { 0x0014, 0x0055, "PresentValue", &Z_Copy }, - { 0x0014, 0x0067, "Reliability", &Z_Copy }, - { 0x0014, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0014, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0014, 0x0100, "ApplicationType", &Z_Copy }, - - { 0x001A, 0x0000, "TotalProfileNum", &Z_Copy }, - { 0x001A, 0x0001, "MultipleScheduling", &Z_Copy }, - { 0x001A, 0x0002, "EnergyFormatting", &Z_Copy }, - { 0x001A, 0x0003, "EnergyRemote", &Z_Copy }, - { 0x001A, 0x0004, "ScheduleMode", &Z_Copy }, - - { 0x0020, 0x0000, "CheckinInterval", &Z_Copy }, - { 0x0020, 0x0001, "LongPollInterval", &Z_Copy }, - { 0x0020, 0x0002, "ShortPollInterval", &Z_Copy }, - { 0x0020, 0x0003, "FastPollTimeout", &Z_Copy }, - { 0x0020, 0x0004, "CheckinIntervalMin", &Z_Copy }, - { 0x0020, 0x0005, "LongPollIntervalMin", &Z_Copy }, - { 0x0020, 0x0006, "FastPollTimeoutMax", &Z_Copy }, - - { 0x0100, 0x0000, "PhysicalClosedLimit", &Z_Copy }, - { 0x0100, 0x0001, "MotorStepSize", &Z_Copy }, - { 0x0100, 0x0002, "Status", &Z_Copy }, - { 0x0100, 0x0010, "ClosedLimit", &Z_Copy }, - { 0x0100, 0x0011, "Mode", &Z_Copy }, - - { 0x0101, 0x0000, "LockState", &Z_Copy }, - { 0x0101, 0x0001, "LockType", &Z_Copy }, - { 0x0101, 0x0002, "ActuatorEnabled", &Z_Copy }, - { 0x0101, 0x0003, "DoorState", &Z_Copy }, - { 0x0101, 0x0004, "DoorOpenEvents", &Z_Copy }, - { 0x0101, 0x0005, "DoorClosedEvents", &Z_Copy }, - { 0x0101, 0x0006, "OpenPeriod", &Z_Copy }, - - { 0x0101, 0x0055, "AqaraVibrationMode", &Z_AqaraVibration }, - { 0x0101, 0x0503, "AqaraVibrationsOrAngle", &Z_Copy }, - { 0x0101, 0x0505, "AqaraVibration505", &Z_Copy }, - { 0x0101, 0x0508, "AqaraAccelerometer", &Z_AqaraVibration }, - - { 0x0102, 0x0000, "WindowCoveringType", &Z_Copy }, - { 0x0102, 0x0001, "PhysicalClosedLimitLift",&Z_Copy }, - { 0x0102, 0x0002, "PhysicalClosedLimitTilt",&Z_Copy }, - { 0x0102, 0x0003, "CurrentPositionLift", &Z_Copy }, - { 0x0102, 0x0004, "CurrentPositionTilt", &Z_Copy }, - { 0x0102, 0x0005, "NumberofActuationsLift",&Z_Copy }, - { 0x0102, 0x0006, "NumberofActuationsTilt",&Z_Copy }, - { 0x0102, 0x0007, "ConfigStatus", &Z_Copy }, - { 0x0102, 0x0008, "CurrentPositionLiftPercentage",&Z_Copy }, - { 0x0102, 0x0009, "CurrentPositionTiltPercentage",&Z_Copy }, - { 0x0102, 0x0010, "InstalledOpenLimitLift",&Z_Copy }, - { 0x0102, 0x0011, "InstalledClosedLimitLift",&Z_Copy }, - { 0x0102, 0x0012, "InstalledOpenLimitTilt", &Z_Copy }, - { 0x0102, 0x0013, "InstalledClosedLimitTilt", &Z_Copy }, - { 0x0102, 0x0014, "VelocityLift",&Z_Copy }, - { 0x0102, 0x0015, "AccelerationTimeLift",&Z_Copy }, - { 0x0102, 0x0016, "DecelerationTimeLift", &Z_Copy }, - { 0x0102, 0x0017, "Mode",&Z_Copy }, - { 0x0102, 0x0018, "IntermediateSetpointsLift",&Z_Copy }, - { 0x0102, 0x0019, "IntermediateSetpointsTilt",&Z_Copy }, - - - { 0x0300, 0x0000, "Hue", &Z_Copy }, - { 0x0300, 0x0001, "Sat", &Z_Copy }, - { 0x0300, 0x0002, "RemainingTime", &Z_Copy }, - { 0x0300, 0x0003, "X", &Z_Copy }, - { 0x0300, 0x0004, "Y", &Z_Copy }, - { 0x0300, 0x0005, "DriftCompensation", &Z_Copy }, - { 0x0300, 0x0006, "CompensationText", &Z_Copy }, - { 0x0300, 0x0007, "CT", &Z_Copy }, - { 0x0300, 0x0008, "ColorMode", &Z_Copy }, - { 0x0300, 0x0010, "NumberOfPrimaries", &Z_Copy }, - { 0x0300, 0x0011, "Primary1X", &Z_Copy }, - { 0x0300, 0x0012, "Primary1Y", &Z_Copy }, - { 0x0300, 0x0013, "Primary1Intensity", &Z_Copy }, - { 0x0300, 0x0015, "Primary2X", &Z_Copy }, - { 0x0300, 0x0016, "Primary2Y", &Z_Copy }, - { 0x0300, 0x0017, "Primary2Intensity", &Z_Copy }, - { 0x0300, 0x0019, "Primary3X", &Z_Copy }, - { 0x0300, 0x001A, "Primary3Y", &Z_Copy }, - { 0x0300, 0x001B, "Primary3Intensity", &Z_Copy }, - { 0x0300, 0x0030, "WhitePointX", &Z_Copy }, - { 0x0300, 0x0031, "WhitePointY", &Z_Copy }, - { 0x0300, 0x0032, "ColorPointRX", &Z_Copy }, - { 0x0300, 0x0033, "ColorPointRY", &Z_Copy }, - { 0x0300, 0x0034, "ColorPointRIntensity", &Z_Copy }, - { 0x0300, 0x0036, "ColorPointGX", &Z_Copy }, - { 0x0300, 0x0037, "ColorPointGY", &Z_Copy }, - { 0x0300, 0x0038, "ColorPointGIntensity", &Z_Copy }, - { 0x0300, 0x003A, "ColorPointBX", &Z_Copy }, - { 0x0300, 0x003B, "ColorPointBY", &Z_Copy }, - { 0x0300, 0x003C, "ColorPointBIntensity", &Z_Copy }, - - - { 0x0400, 0x0000, D_JSON_ILLUMINANCE, &Z_Copy }, - { 0x0400, 0x0001, "MinMeasuredValue", &Z_Copy }, - { 0x0400, 0x0002, "MaxMeasuredValue", &Z_Copy }, - { 0x0400, 0x0003, "Tolerance", &Z_Copy }, - { 0x0400, 0x0004, "LightSensorType", &Z_Copy }, - { 0x0400, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0401, 0x0000, "LevelStatus", &Z_Copy }, - { 0x0401, 0x0001, "LightSensorType", &Z_Copy }, - { 0x0401, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0402, 0x0000, D_JSON_TEMPERATURE, &Z_FloatDiv100 }, - { 0x0402, 0x0001, "MinMeasuredValue", &Z_FloatDiv100 }, - { 0x0402, 0x0002, "MaxMeasuredValue", &Z_FloatDiv100 }, - { 0x0402, 0x0003, "Tolerance", &Z_FloatDiv100 }, - { 0x0402, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0403, 0x0000, D_JSON_PRESSURE_UNIT, &Z_AddPressureUnit }, - { 0x0403, 0x0000, D_JSON_PRESSURE, &Z_Copy }, - { 0x0403, 0x0001, "MinMeasuredValue", &Z_Copy }, - { 0x0403, 0x0002, "MaxMeasuredValue", &Z_Copy }, - { 0x0403, 0x0003, "Tolerance", &Z_Copy }, - { 0x0403, 0x0010, "ScaledValue", &Z_Copy }, - { 0x0403, 0x0011, "MinScaledValue", &Z_Copy }, - { 0x0403, 0x0012, "MaxScaledValue", &Z_Copy }, - { 0x0403, 0x0013, "ScaledTolerance", &Z_Copy }, - { 0x0403, 0x0014, "Scale", &Z_Copy }, - { 0x0403, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0404, 0x0000, D_JSON_FLOWRATE, &Z_FloatDiv10 }, - { 0x0404, 0x0001, "MinMeasuredValue", &Z_Copy }, - { 0x0404, 0x0002, "MaxMeasuredValue", &Z_Copy }, - { 0x0404, 0x0003, "Tolerance", &Z_Copy }, - { 0x0404, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0405, 0x0000, D_JSON_HUMIDITY, &Z_FloatDiv100 }, - { 0x0405, 0x0001, "MinMeasuredValue", &Z_Copy }, - { 0x0405, 0x0002, "MaxMeasuredValue", &Z_Copy }, - { 0x0405, 0x0003, "Tolerance", &Z_Copy }, - { 0x0405, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0406, 0x0000, OCCUPANCY, &Z_Copy }, - { 0x0406, 0x0001, "OccupancySensorType", &Z_Copy }, - { 0x0406, 0xFFFF, nullptr, &Z_Remove }, - - - { 0x0B01, 0x0000, "CompanyName", &Z_Copy }, - { 0x0B01, 0x0001, "MeterTypeID", &Z_Copy }, - { 0x0B01, 0x0004, "DataQualityID", &Z_Copy }, - { 0x0B01, 0x0005, "CustomerName", &Z_Copy }, - { 0x0B01, 0x0006, "Model", &Z_Copy }, - { 0x0B01, 0x0007, "PartNumber", &Z_Copy }, - { 0x0B01, 0x000A, "SoftwareRevision", &Z_Copy }, - { 0x0B01, 0x000C, "POD", &Z_Copy }, - { 0x0B01, 0x000D, "AvailablePower", &Z_Copy }, - { 0x0B01, 0x000E, "PowerThreshold", &Z_Copy }, - - - { 0x0B05, 0x0000, "NumberOfResets", &Z_Copy }, - { 0x0B05, 0x0001, "PersistentMemoryWrites",&Z_Copy }, - { 0x0B05, 0x011C, "LastMessageLQI", &Z_Copy }, - { 0x0B05, 0x011D, "LastMessageRSSI", &Z_Copy }, - -}; - - - -int32_t Z_ManufKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - zigbee_devices.setManufId(shortaddr, value.as()); - return 1; -} - -int32_t Z_ModelKeep(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - zigbee_devices.setModelId(shortaddr, value.as()); - return 1; -} - - - -int32_t Z_Remove(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - return 1; -} - - -int32_t Z_Copy(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - return 1; -} - - -int32_t Z_AddPressureUnit(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = F(D_UNIT_PRESSURE); - return 0; -} - - -int32_t Z_FloatDiv100(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = ((float)value) / 100.0f; - return 1; -} - -int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = ((float)value) / 10.0f; - return 1; -} - - -int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); - json[F(OCCUPANCY)] = 0; - zigbee_devices.jsonPublishNow(shortaddr, json); -} - - -int32_t Z_AqaraCube(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - json[new_name] = value; - int32_t val = value; - const __FlashStringHelper *aqara_cube = F("AqaraCube"); - const __FlashStringHelper *aqara_cube_side = F("AqaraCubeSide"); - const __FlashStringHelper *aqara_cube_from_side = F("AqaraCubeFromSide"); - - switch (val) { - case 0: - json[aqara_cube] = F("shake"); - break; - case 2: - json[aqara_cube] = F("wakeup"); - break; - case 3: - json[aqara_cube] = F("fall"); - break; - case 64 ... 127: - json[aqara_cube] = F("flip90"); - json[aqara_cube_side] = val % 8; - json[aqara_cube_from_side] = (val - 64) / 8; - break; - case 128 ... 132: - json[aqara_cube] = F("flip180"); - json[aqara_cube_side] = val - 128; - break; - case 256 ... 261: - json[aqara_cube] = F("slide"); - json[aqara_cube_side] = val - 256; - break; - case 512 ... 517: - json[aqara_cube] = F("tap"); - json[aqara_cube_side] = val - 512; - break; - } -# 905 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_5_converters.ino" - return 1; -} - - -int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - - switch (attr) { - case 0x0055: - { - int32_t ivalue = value; - const __FlashStringHelper * svalue; - switch (ivalue) { - case 1: svalue = F("vibrate"); break; - case 2: svalue = F("tilt"); break; - case 3: svalue = F("drop"); break; - default: svalue = F("unknown"); break; - } - json[new_name] = svalue; - } - break; - - - - - case 0x0508: - { - - - String hex = value; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - int16_t x, y, z; - z = buf2.get16(0); - y = buf2.get16(2); - x = buf2.get16(4); - JsonArray& xyz = json.createNestedArray(new_name); - xyz.add(x); - xyz.add(y); - xyz.add(z); - - float X = x; - float Y = y; - float Z = z; - int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; - int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; - int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; - - - - JsonArray& angles = json.createNestedArray(F("AqaraAngles")); - angles.add(Angle_X); - angles.add(Angle_Y); - angles.add(Angle_Z); - } - break; - } - return 1; -} - -int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { - String hex = value; - SBuffer buf2 = SBuffer::SBufferFromHex(hex.c_str(), hex.length()); - uint32_t i = 0; - uint32_t len = buf2.len(); - char tmp[] = "tmp"; - - JsonVariant sub_value; - - while (len - i >= 2) { - uint8_t attrid = buf2.get8(i++); - - i += parseSingleAttribute(json, tmp, buf2, i, len); - float val = json[tmp]; - json.remove(tmp); - if (0x01 == attrid) { - json[F(D_JSON_VOLTAGE)] = val / 1000.0f; - json[F("Battery")] = toPercentageCR2032(val); - } else if (0 == zcl->getManufCode()) { - - if (0x64 == attrid) { - json[F(D_JSON_TEMPERATURE)] = val / 100.0f; - } else if (0x65 == attrid) { - json[F(D_JSON_HUMIDITY)] = val / 100.0f; - } else if (0x66 == attrid) { - json[F(D_JSON_PRESSURE)] = val / 100.0f; - json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); - } else if (0x01 == attrid) { - json[F(D_JSON_VOLTAGE)] = val / 1000.0f; - json[F("Battery")] = toPercentageCR2032(val); - } - } else if (0x115F == zcl->getManufCode()) { - - json[F("AqaraUnknown")] = val; - } - } - return 1; -} - - -void ZCLFrame::postProcessAttributes(uint16_t shortaddr, JsonObject& json) { - - for (auto kv : json) { - String key_string = kv.key; - const char * key = key_string.c_str(); - JsonVariant& value = kv.value; - - char * delimiter = strchr(key, '/'); - char * delimiter2 = strchr(key, '+'); - if (delimiter) { - uint16_t attribute; - uint16_t suffix = 1; - uint16_t cluster = strtoul(key, &delimiter, 16); - if (!delimiter2) { - attribute = strtoul(delimiter+1, nullptr, 16); - } else { - attribute = strtoul(delimiter+1, &delimiter2, 16); - suffix = strtoul(delimiter2+1, nullptr, 10); - } - - - for (uint32_t i = 0; i < sizeof(Z_PostProcess) / sizeof(Z_PostProcess[0]); i++) { - const Z_AttributeConverter *converter = &Z_PostProcess[i]; - uint16_t conv_cluster = pgm_read_word(&converter->cluster); - uint16_t conv_attribute = pgm_read_word(&converter->attribute); - - if ((conv_cluster == cluster) && - ((conv_attribute == attribute) || (conv_attribute == 0xFFFF)) ) { - String new_name_str = converter->name; - if (suffix > 1) { new_name_str += suffix; } - int32_t drop = (*converter->func)(this, shortaddr, json, key, value, new_name_str, conv_cluster, conv_attribute); - if (drop) { - json.remove(key); - } - - } - } - } - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" -#ifdef USE_ZIGBEE - -typedef struct Z_CommandConverter { - const char * tasmota_cmd; - uint16_t cluster; - uint8_t cmd; - uint8_t direction; - const char * param; -} Z_CommandConverter; - -typedef struct Z_XYZ_Var { - uint32_t x = 0; - uint32_t y = 0; - uint32_t z = 0; - uint8_t x_type = 0; - uint8_t y_type = 0; - uint8_t z_type = 0; -} Z_XYZ_Var; - - -const Z_CommandConverter Z_Commands[] = { - - { "AddGroup", 0x0004, 0x00, 0x01, "xxxx00" }, - { "ViewGroup", 0x0004, 0x01, 0x01, "xxxx" }, - { "GetGroup", 0x0004, 0x02, 0x01, "01xxxx" }, - { "GetAllGroups", 0x0004, 0x02, 0x01, "00" }, - { "RemoveGroup", 0x0004, 0x03, 0x01, "xxxx" }, - { "RemoveAllGroups",0x0004, 0x04, 0x01, "" }, - - { "Power", 0x0006, 0xFF, 0x01, "" }, - { "Dimmer", 0x0008, 0x04, 0x01, "xx0A00" }, - { "Dimmer+", 0x0008, 0x06, 0x01, "001902" }, - { "Dimmer-", 0x0008, 0x06, 0x01, "011902" }, - { "DimmerStop", 0x0008, 0x03, 0x01, "" }, - { "ResetAlarm", 0x0009, 0x00, 0x01, "xxyyyy" }, - { "ResetAllAlarms", 0x0009, 0x01, 0x01, "" }, - { "Hue", 0x0300, 0x00, 0x01, "xx000A00" }, - { "Sat", 0x0300, 0x03, 0x01, "xx0A00" }, - { "HueSat", 0x0300, 0x06, 0x01, "xxyy0A00" }, - { "Color", 0x0300, 0x07, 0x01, "xxxxyyyy0A00" }, - { "CT", 0x0300, 0x0A, 0x01, "xxxx0A00" }, - { "ShutterOpen", 0x0102, 0x00, 0x01, "" }, - { "ShutterClose", 0x0102, 0x01, 0x01, "" }, - { "ShutterStop", 0x0102, 0x02, 0x01, "" }, - { "ShutterLift", 0x0102, 0x05, 0x01, "xx" }, - { "ShutterTilt", 0x0102, 0x08, 0x01, "xx" }, - { "Shutter", 0x0102, 0xFF, 0x01, "" }, - - { "Occupancy", 0xEF00, 0x01, 0x01, "xx"}, - - { "Dimmer", 0x0008, 0x00, 0x01, "xx" }, - { "DimmerMove", 0x0008, 0x01, 0x01, "xx0A" }, - { "DimmerStep", 0x0008, 0x02, 0x01, "xx190A00" }, - { "DimmerMove", 0x0008, 0x05, 0x01, "xx0A" }, - { "Dimmer+", 0x0008, 0x06, 0x01, "00" }, - { "Dimmer-", 0x0008, 0x06, 0x01, "01" }, - { "DimmerStop", 0x0008, 0x07, 0x01, "" }, - { "HueMove", 0x0300, 0x01, 0x01, "xx19" }, - { "HueStep", 0x0300, 0x02, 0x01, "xx190A00" }, - { "SatMove", 0x0300, 0x04, 0x01, "xx19" }, - { "SatStep", 0x0300, 0x05, 0x01, "xx190A" }, - { "ColorMove", 0x0300, 0x08, 0x01, "xxxxyyyy" }, - { "ColorStep", 0x0300, 0x09, 0x01, "xxxxyyyy0A00" }, - - { "ArrowClick", 0x0005, 0x07, 0x01, "xx" }, - { "ArrowHold", 0x0005, 0x08, 0x01, "xx" }, - { "ArrowRelease", 0x0005, 0x09, 0x01, "" }, - - { "ZoneStatusChange",0x0500, 0x00, 0x02, "xxxxyyzz" }, - - { "AddGroupResp", 0x0004, 0x00, 0x02, "xxyyyy" }, - { "ViewGroupResp", 0x0004, 0x01, 0x02, "xxyyyy" }, - { "GetGroupResp", 0x0004, 0x02, 0x02, "xxyyzzzz" }, - { "RemoveGroup", 0x0004, 0x03, 0x02, "xxyyyy" }, -}; - - -#define ZLE(x) ((x) & 0xFF), ((x) >> 8) - - -const uint8_t CLUSTER_0006[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0008[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0009[] = { ZLE(0x0000) }; -const uint8_t CLUSTER_0300[] = { ZLE(0x0000), ZLE(0x0001), ZLE(0x0003), ZLE(0x0004), ZLE(0x0007) }; - - -int32_t Z_ReadAttrCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { - size_t attrs_len = 0; - const uint8_t* attrs = nullptr; - - switch (cluster) { - case 0x0006: - attrs = CLUSTER_0006; - attrs_len = sizeof(CLUSTER_0006); - break; - case 0x0008: - attrs = CLUSTER_0008; - attrs_len = sizeof(CLUSTER_0008); - break; - case 0x0009: - attrs = CLUSTER_0009; - attrs_len = sizeof(CLUSTER_0009); - break; - case 0x0300: - attrs = CLUSTER_0300; - attrs_len = sizeof(CLUSTER_0300); - break; - } - if (attrs) { - ZigbeeZCLSend(shortaddr, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true , zigbee_devices.getNextSeqNumber(shortaddr)); - } -} - - -void zigbeeSetCommandTimer(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint) { - uint32_t wait_ms = 0; - - switch (cluster) { - case 0x0006: - case 0x0009: - wait_ms = 200; - break; - case 0x0008: - case 0x0300: - wait_ms = 1050; - break; - case 0x0102: - wait_ms = 10000; - break; - } - if (wait_ms) { - zigbee_devices.setTimer(shortaddr, wait_ms, cluster, endpoint, 0 , &Z_ReadAttrCallback); - } -} - - -inline bool isXYZ(char c) { - return (c >= 'x') && (c <= 'z'); -} - - - - -inline int8_t hexValue(char c) { - if ((c >= '0') && (c <= '9')) { - return c - '0'; - } - if ((c >= 'A') && (c <= 'F')) { - return 10 + c - 'A'; - } - if ((c >= 'a') && (c <= 'f')) { - return 10 + c - 'a'; - } - return -1; -} - - -uint32_t parseHex_P(const char **data, size_t max_len = 8) { - uint32_t ret = 0; - for (uint32_t i = 0; i < max_len; i++) { - int8_t v = hexValue(pgm_read_byte(*data)); - if (v < 0) { break; } - ret = (ret << 4) | v; - *data += 1; - } - return ret; -} - - - - - -void parseXYZ(const char *model, const SBuffer &payload, struct Z_XYZ_Var *xyz) { - const char *p = model; - uint32_t v = 0; - char c = pgm_read_byte(p); - while (c) { - char c1 = pgm_read_byte(p+1); - if (!c1) { break; } - if (isXYZ(c) && (c == c1) && (v < payload.len())) { - uint8_t val = payload.get8(v); - switch (c) { - case 'x': - xyz->x = xyz->x | (val << (xyz->x_type * 8)); - xyz->x_type++; - break; - case 'y': - xyz->y = xyz->y | (val << (xyz->y_type * 8)); - xyz->y_type++; - break; - case 'z': - xyz->z = xyz->z | (val << (xyz->z_type * 8)); - xyz->z_type++; - break; - } - } - p += 2; - v++; - c = pgm_read_byte(p); - } -} -# 231 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_6_commands.ino" -void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, bool direction, const SBuffer &payload) { - size_t hex_char_len = payload.len()*2+2; - char *hex_char = (char*) malloc(hex_char_len); - if (!hex_char) { return; } - ToHex_P((unsigned char*)payload.getBuffer(), payload.len(), hex_char, hex_char_len); - - const __FlashStringHelper* command_name = nullptr; - Z_XYZ_Var xyz; - - - for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { - const Z_CommandConverter *conv = &Z_Commands[i]; - if (conv->cluster == cluster) { - - if ((0xFF == conv->cmd) || (cmd == conv->cmd)) { - - if ((direction && (conv->direction & 0x02)) || (!direction && (conv->direction & 0x01))) { - - - - - const char * p = conv->param; - - bool match = true; - for (uint8_t i = 0; i < payload.len(); i++) { - const char c1 = pgm_read_byte(p); - const char c2 = pgm_read_byte(p+1); - - if ((0x00 == c1) || isXYZ(c1)) { - break; - } - const char * p2 = p; - uint32_t nextbyte = parseHex_P(&p2, 2); - - if (nextbyte != payload.get8(i)) { - match = false; - break; - } - p += 2; - } - if (match) { - command_name = (const __FlashStringHelper*) conv->tasmota_cmd; - parseXYZ(conv->param, payload, &xyz); - if (0xFF == conv->cmd) { - - xyz.z = xyz.y; - xyz.z_type = xyz.y_type; - xyz.y = xyz.x; - xyz.y_type = xyz.x_type; - xyz.x = cmd; - xyz.x_type = 1; - } - break; - } - } - } - } - } - - - - - char attrid_str[12]; - snprintf_P(attrid_str, sizeof(attrid_str), PSTR("%04X%c%02X"), cluster, direction ? '<' : '!', cmd); - json[attrid_str] = hex_char; - free(hex_char); - - if (command_name) { - if (0 == xyz.x_type) { - json[command_name] = true; - } else if (0 == xyz.y_type) { - json[command_name] = xyz.x; - } else { - - JsonArray &arr = json.createNestedArray(command_name); - arr.add(xyz.x); - arr.add(xyz.y); - if (xyz.z_type) { - arr.add(xyz.z); - } - } - } -} - - - - -const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd) { - for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { - const Z_CommandConverter *conv = &Z_Commands[i]; - if (0 == strcasecmp_P(command, conv->tasmota_cmd)) { - *cluster = conv->cluster; - *cmd = conv->cmd; - return (const __FlashStringHelper*) conv->param; - } - } - - return nullptr; -} - - -inline char hexDigit(uint32_t h) { - uint32_t nybble = h & 0x0F; - return (nybble > 9) ? 'A' - 10 + nybble : '0' + nybble; -} - - -String zigbeeCmdAddParams(const char *zcl_cmd_P, uint32_t x, uint32_t y, uint32_t z) { - size_t len = strlen_P(zcl_cmd_P); - char zcl_cmd[len+1]; - strcpy_P(zcl_cmd, zcl_cmd_P); - - char *p = zcl_cmd; - while (*p) { - if (isXYZ(*p) && (*p == *(p+1))) { - uint8_t val; - switch (*p) { - case 'x': - val = x & 0xFF; - x = x >> 8; - break; - case 'y': - val = y & 0xFF; - y = y >> 8; - break; - case 'z': - val = z & 0xFF; - z = z >> 8; - break; - } - *p = hexDigit(val >> 4); - *(p+1) = hexDigit(val); - p++; - } - p++; - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SendZCLCommand_P: zcl_cmd = %s"), zcl_cmd); - - return String(zcl_cmd); -} - -const char kZ_Alias[] PROGMEM = "OFF|" D_OFF "|" D_FALSE "|" D_STOP "|" "OPEN" "|" - "ON|" D_ON "|" D_TRUE "|" D_START "|" "CLOSE" "|" - "TOGGLE|" D_TOGGLE "|" - "ALL" ; - -const uint8_t kZ_Numbers[] PROGMEM = { 0,0,0,0,0, - 1,1,1,1,1, - 2,2, - 255 }; - - -uint32_t ZigbeeAliasOrNumber(const char *state_text) { - char command[16]; - int state_number = GetCommandCode(command, sizeof(command), state_text, kZ_Alias); - if (state_number >= 0) { - - return pgm_read_byte(kZ_Numbers + state_number); - } else { - - return strtoul(state_text, nullptr, 0); - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -#ifdef USE_ZIGBEE - - - -const uint8_t ZIGBEE_STATUS_OK = 0; -const uint8_t ZIGBEE_STATUS_BOOT = 1; -const uint8_t ZIGBEE_STATUS_RESET_CONF = 2; -const uint8_t ZIGBEE_STATUS_STARTING = 3; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_CLOSE = 20; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_60 = 21; -const uint8_t ZIGBEE_STATUS_PERMITJOIN_OPEN_XX = 22; -const uint8_t ZIGBEE_STATUS_DEVICE_ANNOUNCE = 30; -const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; -const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; -const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; -const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; -const uint8_t ZIGBEE_STATUS_DEVICE_IEEE = 35; -const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; -const uint8_t ZIGBEE_STATUS_CC_INFO = 51; -const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; -const uint8_t ZIGBEE_STATUS_ABORT = 99; - -typedef int32_t (*ZB_Func)(uint8_t value); -typedef int32_t (*ZB_RecvMsgFunc)(int32_t res, const class SBuffer &buf); - -typedef union Zigbee_Instruction { - struct { - uint8_t i; - uint8_t d8; - uint16_t d16; - } i; - const void *p; - - - -} Zigbee_Instruction; - - - - -typedef struct Zigbee_Instruction_Type { - uint8_t instr; - uint8_t data; -} Zigbee_Instruction_Type; - -enum Zigbee_StateMachine_Instruction_Set { - - ZGB_INSTR_4_BYTES = 0, - ZGB_INSTR_NOOP = 0, - ZGB_INSTR_LABEL, - ZGB_INSTR_GOTO, - ZGB_INSTR_ON_ERROR_GOTO, - ZGB_INSTR_ON_TIMEOUT_GOTO, - ZGB_INSTR_WAIT, - ZGB_INSTR_WAIT_FOREVER, - ZGB_INSTR_STOP, - - - ZGB_INSTR_8_BYTES = 0x80, - ZGB_INSTR_CALL = 0x80, - ZGB_INSTR_LOG, - ZGB_INSTR_MQTT_STATE, - ZGB_INSTR_SEND, - ZGB_INSTR_WAIT_UNTIL, - ZGB_INSTR_WAIT_RECV, - ZGB_ON_RECV_UNEXPECTED, - - - ZGB_INSTR_12_BYTES = 0xF0, - ZGB_INSTR_WAIT_RECV_CALL, -}; - -#define ZI_NOOP() { .i = { ZGB_INSTR_NOOP, 0x00, 0x0000} }, -#define ZI_LABEL(x) { .i = { ZGB_INSTR_LABEL, (x), 0x0000} }, -#define ZI_GOTO(x) { .i = { ZGB_INSTR_GOTO, (x), 0x0000} }, -#define ZI_ON_ERROR_GOTO(x) { .i = { ZGB_INSTR_ON_ERROR_GOTO, (x), 0x0000} }, -#define ZI_ON_TIMEOUT_GOTO(x) { .i = { ZGB_INSTR_ON_TIMEOUT_GOTO, (x), 0x0000} }, -#define ZI_WAIT(x) { .i = { ZGB_INSTR_WAIT, 0x00, (x)} }, -#define ZI_WAIT_FOREVER() { .i = { ZGB_INSTR_WAIT_FOREVER, 0x00, 0x0000} }, -#define ZI_STOP(x) { .i = { ZGB_INSTR_STOP, (x), 0x0000} }, - -#define ZI_CALL(f,x) { .i = { ZGB_INSTR_CALL, (x), 0x0000} }, { .p = (const void*)(f) }, -#define ZI_LOG(x,m) { .i = { ZGB_INSTR_LOG, (x), 0x0000 } }, { .p = ((const void*)(m)) }, -#define ZI_MQTT_STATE(x,m) { .i = { ZGB_INSTR_MQTT_STATE, (x), 0x0000 } }, { .p = ((const void*)(m)) }, -#define ZI_ON_RECV_UNEXPECTED(f) { .i = { ZGB_ON_RECV_UNEXPECTED, 0x00, 0x0000} }, { .p = (const void*)(f) }, -#define ZI_SEND(m) { .i = { ZGB_INSTR_SEND, sizeof(m), 0x0000} }, { .p = (const void*)(m) }, -#define ZI_WAIT_RECV(x,m) { .i = { ZGB_INSTR_WAIT_RECV, sizeof(m), (x)} }, { .p = (const void*)(m) }, -#define ZI_WAIT_UNTIL(x,m) { .i = { ZGB_INSTR_WAIT_UNTIL, sizeof(m), (x)} }, { .p = (const void*)(m) }, -#define ZI_WAIT_RECV_FUNC(x,m,f) { .i = { ZGB_INSTR_WAIT_RECV_CALL, sizeof(m), (x)} }, { .p = (const void*)(m) }, { .p = (const void*)(f) }, - - -const uint8_t ZIGBEE_LABEL_START = 10; -const uint8_t ZIGBEE_LABEL_READY = 20; -const uint8_t ZIGBEE_LABEL_MAIN_LOOP = 21; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_CLOSE = 30; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60 = 31; -const uint8_t ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX = 32; - -const uint8_t ZIGBEE_LABEL_ABORT = 99; -const uint8_t ZIGBEE_LABEL_UNSUPPORTED_VERSION = 98; - -struct ZigbeeStatus { - bool active = true; - bool state_machine = false; - bool state_waiting = false; - bool state_no_timeout = false; - bool ready = false; - uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; - uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; - int16_t pc = 0; - uint32_t next_timeout = 0; - - uint8_t *recv_filter = nullptr; - bool recv_until = false; - size_t recv_filter_len = 0; - ZB_RecvMsgFunc recv_func = nullptr; - ZB_RecvMsgFunc recv_unexpected = nullptr; - - bool init_phase = true; -}; -struct ZigbeeStatus zigbee; - -SBuffer *zigbee_buffer = nullptr; - - - - - -#define Z_B0(a) (uint8_t)( ((a) ) & 0xFF ) -#define Z_B1(a) (uint8_t)( ((a) >> 8) & 0xFF ) -#define Z_B2(a) (uint8_t)( ((a) >> 16) & 0xFF ) -#define Z_B3(a) (uint8_t)( ((a) >> 24) & 0xFF ) -#define Z_B4(a) (uint8_t)( ((a) >> 32) & 0xFF ) -#define Z_B5(a) (uint8_t)( ((a) >> 40) & 0xFF ) -#define Z_B6(a) (uint8_t)( ((a) >> 48) & 0xFF ) -#define Z_B7(a) (uint8_t)( ((a) >> 56) & 0xFF ) - -#define ZBM(n,x...) const uint8_t n[] PROGMEM = { x }; - -#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) - - - -ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) -ZBM(ZBR_RESET, Z_AREQ | Z_SYS, SYS_RESET_IND ) - -ZBM(ZBS_VERSION, Z_SREQ | Z_SYS, SYS_VERSION ) -ZBM(ZBR_VERSION, Z_SRSP | Z_SYS, SYS_VERSION ) - - -ZBM(ZBS_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_READ, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, 0x00 ) -ZBM(ZBR_ZNPHC, Z_SRSP | Z_SYS, SYS_OSAL_NV_READ, Z_Success, 0x01 , 0x55) - - -ZBM(ZBS_PAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PANID ) -ZBM(ZBR_PAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PANID, 0x02 , - Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) - -ZBM(ZBS_EXTPAN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_EXTENDED_PAN_ID ) -ZBM(ZBR_EXTPAN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_EXTENDED_PAN_ID, - 0x08 , - Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), - Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID), - ) - -ZBM(ZBS_CHANN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_CHANLIST ) -ZBM(ZBR_CHANN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_CHANLIST, - 0x04 , - Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), - ) - -ZBM(ZBS_PFGK, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEY ) -ZBM(ZBR_PFGK, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEY, - 0x10 , - Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), - Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), - Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), - Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), - - ) - -ZBM(ZBS_PFGKEN, Z_SREQ | Z_SAPI, SAPI_READ_CONFIGURATION, CONF_PRECFGKEYS_ENABLE ) -ZBM(ZBR_PFGKEN, Z_SRSP | Z_SAPI, SAPI_READ_CONFIGURATION, Z_Success, CONF_PRECFGKEYS_ENABLE, - 0x01 , 0x00 ) - - - -ZBM(ZBR_W_OK, Z_SRSP | Z_SAPI, SAPI_WRITE_CONFIGURATION, Z_Success ) -ZBM(ZBR_WNV_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_WRITE, Z_Success ) - - -ZBM(ZBS_FACTRES, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x02 ) - -ZBM(ZBS_W_PAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PANID, 0x02 , Z_B0(USE_ZIGBEE_PANID), Z_B1(USE_ZIGBEE_PANID) ) - -ZBM(ZBS_W_EXTPAN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_EXTENDED_PAN_ID, 0x08 , - Z_B0(USE_ZIGBEE_EXTPANID), Z_B1(USE_ZIGBEE_EXTPANID), Z_B2(USE_ZIGBEE_EXTPANID), Z_B3(USE_ZIGBEE_EXTPANID), - Z_B4(USE_ZIGBEE_EXTPANID), Z_B5(USE_ZIGBEE_EXTPANID), Z_B6(USE_ZIGBEE_EXTPANID), Z_B7(USE_ZIGBEE_EXTPANID) - ) - -ZBM(ZBS_W_CHANN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_CHANLIST, 0x04 , - Z_B0(USE_ZIGBEE_CHANNEL_MASK), Z_B1(USE_ZIGBEE_CHANNEL_MASK), Z_B2(USE_ZIGBEE_CHANNEL_MASK), Z_B3(USE_ZIGBEE_CHANNEL_MASK), - ) - -ZBM(ZBS_W_LOGTYP, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_LOGICAL_TYPE, 0x01 , 0x00 ) - -ZBM(ZBS_W_PFGK, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEY, - 0x10 , - Z_B0(USE_ZIGBEE_PRECFGKEY_L), Z_B1(USE_ZIGBEE_PRECFGKEY_L), Z_B2(USE_ZIGBEE_PRECFGKEY_L), Z_B3(USE_ZIGBEE_PRECFGKEY_L), - Z_B4(USE_ZIGBEE_PRECFGKEY_L), Z_B5(USE_ZIGBEE_PRECFGKEY_L), Z_B6(USE_ZIGBEE_PRECFGKEY_L), Z_B7(USE_ZIGBEE_PRECFGKEY_L), - Z_B0(USE_ZIGBEE_PRECFGKEY_H), Z_B1(USE_ZIGBEE_PRECFGKEY_H), Z_B2(USE_ZIGBEE_PRECFGKEY_H), Z_B3(USE_ZIGBEE_PRECFGKEY_H), - Z_B4(USE_ZIGBEE_PRECFGKEY_H), Z_B5(USE_ZIGBEE_PRECFGKEY_H), Z_B6(USE_ZIGBEE_PRECFGKEY_H), Z_B7(USE_ZIGBEE_PRECFGKEY_H), - - ) - -ZBM(ZBS_W_PFGKEN, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_PRECFGKEYS_ENABLE, 0x01 , 0x00 ) - -ZBM(ZBS_WNV_SECMODE, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(CONF_TCLK_TABLE_START), Z_B1(CONF_TCLK_TABLE_START), - 0x00 , 0x20 , - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x5a, 0x69, 0x67, 0x42, 0x65, 0x65, 0x41, 0x6c, - 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x39, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) - -ZBM(ZBS_W_ZDODCB, Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_ZDO_DIRECT_CB, 0x01 , 0x01 ) - -ZBM(ZBS_WNV_INITZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_ITEM_INIT, ZNP_HAS_CONFIGURED & 0xFF, ZNP_HAS_CONFIGURED >> 8, - 0x01, 0x00 , 0x01 , 0x00 ) - - -ZBM(ZBR_WNV_INIT_OK, Z_SRSP | Z_SYS, SYS_OSAL_NV_ITEM_INIT ) - - -ZBM(ZBS_WNV_ZNPHC, Z_SREQ | Z_SYS, SYS_OSAL_NV_WRITE, Z_B0(ZNP_HAS_CONFIGURED), Z_B1(ZNP_HAS_CONFIGURED), - 0x00 , 0x01 , 0x55 ) - -ZBM(ZBS_STARTUPFROMAPP, Z_SREQ | Z_ZDO, ZDO_STARTUP_FROM_APP, 100, 0 ) -ZBM(ZBR_STARTUPFROMAPP, Z_SRSP | Z_ZDO, ZDO_STARTUP_FROM_APP ) -ZBM(AREQ_STARTUPFROMAPP, Z_AREQ | Z_ZDO, ZDO_STATE_CHANGE_IND, ZDO_DEV_ZB_COORD ) - -ZBM(ZBS_GETDEVICEINFO, Z_SREQ | Z_UTIL, Z_UTIL_GET_DEVICE_INFO ) -ZBM(ZBR_GETDEVICEINFO, Z_SRSP | Z_UTIL, Z_UTIL_GET_DEVICE_INFO, Z_Success ) -# 272 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -ZBM(ZBS_ZDO_NODEDESCREQ, Z_SREQ | Z_ZDO, ZDO_NODE_DESC_REQ, 0x00, 0x00 , 0x00, 0x00 ) -ZBM(ZBR_ZDO_NODEDESCREQ, Z_SRSP | Z_ZDO, ZDO_NODE_DESC_REQ, Z_Success ) - -ZBM(AREQ_ZDO_NODEDESCRSP, Z_AREQ | Z_ZDO, ZDO_NODE_DESC_RSP) -# 290 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_7_statemachine.ino" -ZBM(ZBS_ZDO_ACTIVEEPREQ, Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, 0x00, 0x00, 0x00, 0x00) -ZBM(ZBR_ZDO_ACTIVEEPREQ, Z_SRSP | Z_ZDO, ZDO_ACTIVE_EP_REQ, Z_Success) -ZBM(ZBR_ZDO_ACTIVEEPRSP_NONE, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, - 0x00, 0x00 , 0x00 ) -ZBM(ZBR_ZDO_ACTIVEEPRSP_OK, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP, 0x00, 0x00 , Z_Success, - 0x00, 0x00 , 0x02 , 0x0B, 0x01 ) - - -ZBM(ZBS_AF_REGISTER01, Z_SREQ | Z_AF, AF_REGISTER, 0x01 , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , 0x00 , - 0x00 , 0x00 ) -ZBM(ZBR_AF_REGISTER, Z_SRSP | Z_AF, AF_REGISTER, Z_Success) -ZBM(ZBS_AF_REGISTER0B, Z_SREQ | Z_AF, AF_REGISTER, 0x0B , Z_B0(Z_PROF_HA), Z_B1(Z_PROF_HA), - 0x05, 0x00 , 0x00 , 0x00 , - 0x00 , 0x00 ) - -ZBM(ZBS_PERMITJOINREQ_CLOSE, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x02 , - 0x00, 0x00 , 0x00 , 0x00 ) -ZBM(ZBS_PERMITJOINREQ_OPEN_60, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , - 0xFC, 0xFF , 60 , 0x00 ) -ZBM(ZBS_PERMITJOINREQ_OPEN_XX, Z_SREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, 0x0F , - 0xFC, 0xFF , 0xFF , 0x00 ) -ZBM(ZBR_PERMITJOINREQ, Z_SRSP | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_REQ, Z_Success) -ZBM(ZBR_PERMITJOIN_AREQ_CLOSE, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0x00 ) -ZBM(ZBR_PERMITJOIN_AREQ_OPEN_60, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 60 ) -ZBM(ZBR_PERMITJOIN_AREQ_OPEN_FF, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND, 0xFF ) -ZBM(ZBR_PERMITJOIN_AREQ_RSP, Z_AREQ | Z_ZDO, ZDO_MGMT_PERMIT_JOIN_RSP, 0x00, 0x00 , Z_Success ) - -static const Zigbee_Instruction zb_prog[] PROGMEM = { - ZI_LABEL(0) - ZI_NOOP() - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT) - ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default) - ZI_WAIT(10500) - ZI_ON_ERROR_GOTO(50) - - - - ZI_SEND(ZBS_RESET) - ZI_WAIT_RECV_FUNC(5000, ZBR_RESET, &Z_Reboot) - ZI_WAIT(100) - ZI_LOG(LOG_LEVEL_DEBUG, D_LOG_ZIGBEE "checking device configuration") - ZI_SEND(ZBS_ZNPHC) - ZI_WAIT_RECV(2000, ZBR_ZNPHC) - ZI_SEND(ZBS_VERSION) - ZI_WAIT_RECV_FUNC(2000, ZBR_VERSION, &Z_ReceiveCheckVersion) - ZI_SEND(ZBS_PAN) - ZI_WAIT_RECV(1000, ZBR_PAN) - ZI_SEND(ZBS_EXTPAN) - ZI_WAIT_RECV(1000, ZBR_EXTPAN) - ZI_SEND(ZBS_CHANN) - ZI_WAIT_RECV(1000, ZBR_CHANN) - ZI_SEND(ZBS_PFGK) - ZI_WAIT_RECV(1000, ZBR_PFGK) - ZI_SEND(ZBS_PFGKEN) - ZI_WAIT_RECV(1000, ZBR_PFGKEN) - - - - ZI_LABEL(ZIGBEE_LABEL_START) - ZI_MQTT_STATE(ZIGBEE_STATUS_STARTING, "Configured, starting coordinator") - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - - -ZI_SEND(ZBS_STARTUPFROMAPP) - ZI_WAIT_RECV(2000, ZBR_STARTUPFROMAPP) - ZI_WAIT_UNTIL(10000, AREQ_STARTUPFROMAPP) - ZI_SEND(ZBS_GETDEVICEINFO) - ZI_WAIT_RECV_FUNC(2000, ZBR_GETDEVICEINFO, &Z_ReceiveDeviceInfo) - - ZI_SEND(ZBS_ZDO_NODEDESCREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_NODEDESCREQ) - ZI_WAIT_UNTIL(5000, AREQ_ZDO_NODEDESCRSP) - ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) - ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_NONE) - ZI_SEND(ZBS_AF_REGISTER01) - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - ZI_SEND(ZBS_AF_REGISTER0B) - ZI_WAIT_RECV(1000, ZBR_AF_REGISTER) - - - ZI_SEND(ZBS_ZDO_ACTIVEEPREQ) - ZI_WAIT_RECV(1000, ZBR_ZDO_ACTIVEEPREQ) - ZI_WAIT_UNTIL(1000, ZBR_ZDO_ACTIVEEPRSP_OK) - ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - ZI_WAIT_UNTIL(1000, ZBR_PERMITJOIN_AREQ_RSP) - - - - - - - ZI_LABEL(ZIGBEE_LABEL_READY) - ZI_MQTT_STATE(ZIGBEE_STATUS_OK, "Started") - ZI_LOG(LOG_LEVEL_INFO, D_LOG_ZIGBEE "Zigbee started") - ZI_CALL(&Z_State_Ready, 1) - ZI_CALL(&Z_Load_Devices, 0) - ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP) - ZI_WAIT_FOREVER() - ZI_GOTO(ZIGBEE_LABEL_READY) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE) - - ZI_SEND(ZBS_PERMITJOINREQ_CLOSE) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60) - - ZI_SEND(ZBS_PERMITJOINREQ_OPEN_60) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX) - - ZI_SEND(ZBS_PERMITJOINREQ_OPEN_XX) - ZI_WAIT_RECV(1000, ZBR_PERMITJOINREQ) - - - ZI_GOTO(ZIGBEE_LABEL_MAIN_LOOP) - - ZI_LABEL(50) - ZI_MQTT_STATE(ZIGBEE_STATUS_RESET_CONF, "Reseting configuration") - - ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT) - ZI_SEND(ZBS_FACTRES) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_RESET) - ZI_WAIT_RECV(5000, ZBR_RESET) - ZI_SEND(ZBS_W_PAN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_EXTPAN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_CHANN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_LOGTYP) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_PFGK) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_W_PFGKEN) - ZI_WAIT_RECV(1000, ZBR_W_OK) - ZI_SEND(ZBS_WNV_SECMODE) - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - ZI_SEND(ZBS_W_ZDODCB) - ZI_WAIT_RECV(1000, ZBR_W_OK) - - ZI_SEND(ZBS_WNV_INITZNPHC) - ZI_WAIT_RECV_FUNC(1000, ZBR_WNV_INIT_OK, &Z_CheckNVWrite) - ZI_SEND(ZBS_WNV_ZNPHC) - ZI_WAIT_RECV(1000, ZBR_WNV_OK) - - - ZI_GOTO(ZIGBEE_LABEL_START) - - ZI_LABEL(ZIGBEE_LABEL_UNSUPPORTED_VERSION) - ZI_MQTT_STATE(ZIGBEE_STATUS_UNSUPPORTED_VERSION, "Only ZNP 1.2 is currently supported") - ZI_GOTO(ZIGBEE_LABEL_ABORT) - - ZI_LABEL(ZIGBEE_LABEL_ABORT) - ZI_MQTT_STATE(ZIGBEE_STATUS_ABORT, "Abort") - ZI_LOG(LOG_LEVEL_ERROR, D_LOG_ZIGBEE "Abort") - ZI_STOP(ZIGBEE_LABEL_ABORT) -}; - -uint8_t ZigbeeGetInstructionSize(uint8_t instr) { - if (instr >= ZGB_INSTR_12_BYTES) { - return 3; - } else if (instr >= ZGB_INSTR_8_BYTES) { - return 2; - } else { - return 1; - } -} - -void ZigbeeGotoLabel(uint8_t label) { - - uint16_t goto_pc = 0xFFFF; - uint8_t cur_instr = 0; - uint8_t cur_d8 = 0; - uint8_t cur_instr_len = 1; - - for (uint32_t i = 0; i < sizeof(zb_prog)/sizeof(zb_prog[0]); i += cur_instr_len) { - const Zigbee_Instruction *cur_instr_line = &zb_prog[i]; - cur_instr = pgm_read_byte(&cur_instr_line->i.i); - cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); - - - if (ZGB_INSTR_LABEL == cur_instr) { - - if (label == cur_d8) { - - zigbee.pc = i; - zigbee.state_machine = true; - zigbee.state_waiting = false; - return; - } - } - - cur_instr_len = ZigbeeGetInstructionSize(cur_instr); - } - - - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Goto label not found, label=%d pc=%d"), label, zigbee.pc); - if (ZIGBEE_LABEL_ABORT != label) { - - ZigbeeGotoLabel(ZIGBEE_LABEL_ABORT); - } else { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Label Abort (%d) not present, aborting Zigbee"), ZIGBEE_LABEL_ABORT); - zigbee.state_machine = false; - zigbee.active = false; - } -} - -void ZigbeeStateMachine_Run(void) { - uint8_t cur_instr = 0; - uint8_t cur_d8 = 0; - uint16_t cur_d16 = 0; - const void* cur_ptr1 = nullptr; - const void* cur_ptr2 = nullptr; - uint32_t now = millis(); - - if (zigbee.state_waiting) { - - if ((zigbee.next_timeout) && (now > zigbee.next_timeout)) { - - if (!zigbee.state_no_timeout) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "timeout, goto label %d"), zigbee.on_timeout_goto); - ZigbeeGotoLabel(zigbee.on_timeout_goto); - } else { - zigbee.state_waiting = false; - } - } - } - - while ((zigbee.state_machine) && (!zigbee.state_waiting)) { - - zigbee.recv_filter = nullptr; - zigbee.recv_func = nullptr; - zigbee.recv_until = false; - zigbee.state_no_timeout = false; - - if (zigbee.pc > (sizeof(zb_prog)/sizeof(zb_prog[0]))) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Invalid pc: %d, aborting"), zigbee.pc); - zigbee.pc = -1; - } - if (zigbee.pc < 0) { - zigbee.state_machine = false; - return; - } - - - - const Zigbee_Instruction *cur_instr_line = &zb_prog[zigbee.pc]; - cur_instr = pgm_read_byte(&cur_instr_line->i.i); - cur_d8 = pgm_read_byte(&cur_instr_line->i.d8); - cur_d16 = pgm_read_word(&cur_instr_line->i.d16); - if (cur_instr >= ZGB_INSTR_8_BYTES) { - cur_instr_line++; - cur_ptr1 = cur_instr_line->p; - } - if (cur_instr >= ZGB_INSTR_12_BYTES) { - cur_instr_line++; - cur_ptr2 = cur_instr_line->p; - } - - zigbee.pc += ZigbeeGetInstructionSize(cur_instr); - - switch (cur_instr) { - case ZGB_INSTR_NOOP: - case ZGB_INSTR_LABEL: - break; - case ZGB_INSTR_GOTO: - ZigbeeGotoLabel(cur_d8); - break; - case ZGB_INSTR_ON_ERROR_GOTO: - zigbee.on_error_goto = cur_d8; - break; - case ZGB_INSTR_ON_TIMEOUT_GOTO: - zigbee.on_timeout_goto = cur_d8; - break; - case ZGB_INSTR_WAIT: - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - zigbee.state_no_timeout = true; - break; - case ZGB_INSTR_WAIT_FOREVER: - zigbee.next_timeout = 0; - zigbee.state_waiting = true; - - break; - case ZGB_INSTR_STOP: - zigbee.state_machine = false; - if (cur_d8) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Stopping (%d)"), cur_d8); - } - break; - case ZGB_INSTR_CALL: - if (cur_ptr1) { - uint32_t res; - res = (*((ZB_Func)cur_ptr1))(cur_d8); - if (res > 0) { - ZigbeeGotoLabel(res); - continue; - } else if (res == 0) { - - } else if (res == -1) { - - } else { - ZigbeeGotoLabel(zigbee.on_error_goto); - continue; - } - } - break; - case ZGB_INSTR_LOG: - AddLog_P(cur_d8, (char*) cur_ptr1); - break; - case ZGB_INSTR_MQTT_STATE: - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{\"Status\":%d,\"Message\":\"%s\"}}"), - cur_d8, (char*) cur_ptr1); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - break; - case ZGB_INSTR_SEND: - ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 ); - break; - case ZGB_INSTR_WAIT_UNTIL: - zigbee.recv_until = true; - case ZGB_INSTR_WAIT_RECV: - zigbee.recv_filter = (uint8_t *) cur_ptr1; - zigbee.recv_filter_len = cur_d8; - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - break; - case ZGB_ON_RECV_UNEXPECTED: - zigbee.recv_unexpected = (ZB_RecvMsgFunc) cur_ptr1; - break; - case ZGB_INSTR_WAIT_RECV_CALL: - zigbee.recv_filter = (uint8_t *) cur_ptr1; - zigbee.recv_filter_len = cur_d8; - zigbee.recv_func = (ZB_RecvMsgFunc) cur_ptr2; - zigbee.next_timeout = now + cur_d16; - zigbee.state_waiting = true; - break; - } - } -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" -#ifdef USE_ZIGBEE - -int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { - - - - - - - - Z_IEEEAddress long_adr = buf.get64(3); - Z_ShortAddress short_adr = buf.get16(11); - uint8_t device_type = buf.get8(13); - uint8_t device_state = buf.get8(14); - uint8_t device_associated = buf.get8(15); - - - localIEEEAddr = long_adr; - - char hex[20]; - Uint64toHex(long_adr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"DeviceType\":%d,\"DeviceState\":%d" - ",\"NumAssocDevices\":%d"), - ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, - device_associated); - - if (device_associated > 0) { - uint idx = 16; - ResponseAppend_P(PSTR(",\"AssocDevicesList\":[")); - for (uint32_t i = 0; i < device_associated; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(idx)); - idx += 2; - } - ResponseAppend_P(PSTR("]")); - } - - ResponseJsonEnd(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - - return res; -} - -int32_t Z_CheckNVWrite(int32_t res, class SBuffer &buf) { - - - - uint8_t status = buf.get8(2); - if ((0x00 == status) || (0x09 == status)) { - return 0; - } else { - return -2; - } -} - -const char Z_RebootReason[] PROGMEM = "Power-up|External|Watchdog"; - -int32_t Z_Reboot(int32_t res, class SBuffer &buf) { - - - - uint8_t reason = buf.get8(2); - uint8_t transport_rev = buf.get8(3); - uint8_t product_id = buf.get8(4); - uint8_t major_rel = buf.get8(5); - uint8_t minor_rel = buf.get8(6); - uint8_t hw_rev = buf.get8(7); - char reason_str[12]; - - if (reason > 3) { reason = 3; } - GetTextIndexed(reason_str, sizeof(reason_str), reason, Z_RebootReason); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Message\":\"%s\",\"RestartReason\":\"%s\"" - ",\"MajorRel\":%d,\"MinorRel\":%d}}"), - ZIGBEE_STATUS_BOOT, "CC2530 booted", reason_str, - major_rel, minor_rel); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - - if ((0x02 == major_rel) && (0x06 == minor_rel)) { - return 0; - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; - } -} - -int32_t Z_ReceiveCheckVersion(int32_t res, class SBuffer &buf) { -# 122 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_8_parsers.ino" - uint8_t major_rel = buf.get8(4); - uint8_t minor_rel = buf.get8(5); - uint8_t maint_rel = buf.get8(6); - uint32_t revision = buf.get32(7); - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"MajorRel\":%d,\"MinorRel\":%d" - ",\"MaintRel\":%d,\"Revision\":%d}}"), - ZIGBEE_STATUS_CC_VERSION, major_rel, minor_rel, - maint_rel, revision); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - - if ((0x02 == major_rel) && (0x06 == minor_rel)) { - return 0; - } else { - return ZIGBEE_LABEL_UNSUPPORTED_VERSION; - } -} - -bool Z_ReceiveMatchPrefix(const class SBuffer &buf, const uint8_t *match) { - if ( (pgm_read_byte(&match[0]) == buf.get8(0)) && - (pgm_read_byte(&match[1]) == buf.get8(1)) ) { - return true; - } else { - return false; - } -} - -int32_t Z_ReceivePermitJoinStatus(int32_t res, const class SBuffer &buf) { - - uint8_t duration = buf.get8(2); - uint8_t status_code; - const char* message; - - if (0xFF == duration) { - status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_XX; - message = PSTR("Enable Pairing mode until next boot"); - } else if (duration > 0) { - status_code = ZIGBEE_STATUS_PERMITJOIN_OPEN_60; - message = PSTR("Enable Pairing mode for %d seconds"); - } else { - status_code = ZIGBEE_STATUS_PERMITJOIN_CLOSE; - message = PSTR("Disable Pairing mode"); - } - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Message\":\""), - status_code); - ResponseAppend_P(message, duration); - ResponseAppend_P(PSTR("\"}}")); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_STATE)); - XdrvRulesProcess(); - return -1; -} - - -void Z_SendIEEEAddrReq(uint16_t shortaddr) { - uint8_t IEEEAddrReq[] = { Z_SREQ | Z_ZDO, ZDO_IEEE_ADDR_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), 0x00, 0x00 }; - - ZigbeeZNPSend(IEEEAddrReq, sizeof(IEEEAddrReq)); -} - - -void Z_SendActiveEpReq(uint16_t shortaddr) { - uint8_t ActiveEpReq[] = { Z_SREQ | Z_ZDO, ZDO_ACTIVE_EP_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr) }; - - ZigbeeZNPSend(ActiveEpReq, sizeof(ActiveEpReq)); - - - - - -} - - -void Z_SendSimpleDescReq(uint16_t shortaddr, uint8_t endpoint) { - uint8_t SimpleDescReq[] = { Z_SREQ | Z_ZDO, ZDO_SIMPLE_DESC_REQ, - Z_B0(shortaddr), Z_B1(shortaddr), Z_B0(shortaddr), Z_B1(shortaddr), - endpoint }; - - ZigbeeZNPSend(SimpleDescReq, sizeof(SimpleDescReq)); -} - -const char* Z_DeviceType[] = { "Coordinator", "Router", "End Device", "Unknown" }; -int32_t Z_ReceiveNodeDesc(int32_t res, const class SBuffer &buf) { - - Z_ShortAddress srcAddr = buf.get16(2); - uint8_t status = buf.get8(4); - Z_ShortAddress nwkAddr = buf.get16(5); - uint8_t logicalType = buf.get8(7); - uint8_t apsFlags = buf.get8(8); - uint8_t MACCapabilityFlags = buf.get8(9); - uint16_t manufacturerCapabilities = buf.get16(10); - uint8_t maxBufferSize = buf.get8(12); - uint16_t maxInTransferSize = buf.get16(13); - uint16_t serverMask = buf.get16(15); - uint16_t maxOutTransferSize = buf.get16(17); - uint8_t descriptorCapabilities = buf.get8(19); - - if (0 == status) { - zigbee_devices.updateLastSeen(nwkAddr); - - uint8_t deviceType = logicalType & 0x7; - if (deviceType > 3) { deviceType = 3; } - bool complexDescriptorAvailable = (logicalType & 0x08) ? 1 : 0; - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"NodeType\":\"%s\",\"ComplexDesc\":%s}}"), - ZIGBEE_STATUS_NODE_DESC, Z_DeviceType[deviceType], - complexDescriptorAvailable ? "true" : "false" - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - } - - return -1; -} - -int32_t Z_ReceiveActiveEp(int32_t res, const class SBuffer &buf) { - - Z_ShortAddress srcAddr = buf.get16(2); - uint8_t status = buf.get8(4); - Z_ShortAddress nwkAddr = buf.get16(5); - uint8_t activeEpCount = buf.get8(7); - uint8_t* activeEpList = (uint8_t*) buf.charptr(8); - - - for (uint32_t i = 0; i < activeEpCount; i++) { - zigbee_devices.addEndoint(nwkAddr, activeEpList[i]); - } - - for (uint32_t i = 0; i < activeEpCount; i++) { - Z_SendSimpleDescReq(nwkAddr, activeEpList[i]); - } - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"ActiveEndpoints\":["), - ZIGBEE_STATUS_ACTIVE_EP); - for (uint32_t i = 0; i < activeEpCount; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%02X\""), activeEpList[i]); - } - ResponseAppend_P(PSTR("]}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - return -1; -} - -void Z_SendAFInfoRequest(uint16_t shortaddr, uint8_t endpoint, uint16_t clusterid, uint8_t transacid) { - SBuffer buf(100); - buf.add8(Z_SREQ | Z_AF); - buf.add8(AF_DATA_REQUEST); - buf.add16(shortaddr); - buf.add8(endpoint); - buf.add8(0x01); - buf.add16(clusterid); - buf.add8(transacid); - buf.add8(0x30); - buf.add8(0x1E); - - buf.add8(3 + 2*sizeof(uint16_t)); - buf.add8(0x00); - buf.add8(transacid); - buf.add8(ZCL_READ_ATTRIBUTES); - buf.add16(0x0004); - buf.add16(0x0005); - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -} - - -int32_t Z_ReceiveSimpleDesc(int32_t res, const class SBuffer &buf) { - - Z_ShortAddress srcAddr = buf.get16(2); - uint8_t status = buf.get8(4); - Z_ShortAddress nwkAddr = buf.get16(5); - uint8_t lenDescriptor = buf.get8(7); - uint8_t endpoint = buf.get8(8); - uint16_t profileId = buf.get16(9); - uint16_t deviceId = buf.get16(11); - uint8_t deviceVersion = buf.get8(13); - uint8_t numInCluster = buf.get8(14); - uint8_t numOutCluster = buf.get8(15 + numInCluster*2); - - if (0 == status) { - zigbee_devices.addEndointProfile(nwkAddr, endpoint, profileId); - for (uint32_t i = 0; i < numInCluster; i++) { - zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(15 + i*2), false); - } - for (uint32_t i = 0; i < numOutCluster; i++) { - zigbee_devices.addCluster(nwkAddr, endpoint, buf.get16(16 + numInCluster*2 + i*2), true); - } - - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"Endpoint\":\"0x%02X\"" - ",\"ProfileId\":\"0x%04X\",\"DeviceId\":\"0x%04X\",\"DeviceVersion\":%d" - "\"InClusters\":["), - ZIGBEE_STATUS_SIMPLE_DESC, endpoint, - profileId, deviceId, deviceVersion); - for (uint32_t i = 0; i < numInCluster; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(15 + i*2)); - } - ResponseAppend_P(PSTR("],\"OutClusters\":[")); - for (uint32_t i = 0; i < numOutCluster; i++) { - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"0x%04X\""), buf.get16(16 + numInCluster*2 + i*2)); - } - ResponseAppend_P(PSTR("]}}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - - uint8_t cluster = zigbee_devices.findClusterEndpointIn(nwkAddr, 0x0000); - if (cluster) { - Z_SendAFInfoRequest(nwkAddr, cluster, 0x0000, 0x01); - } - } - return -1; -} - -int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { - uint8_t status = buf.get8(2); - Z_IEEEAddress ieeeAddr = buf.get64(3); - Z_ShortAddress nwkAddr = buf.get16(11); - - - - if (0 == status) { - zigbee_devices.updateDevice(nwkAddr, ieeeAddr); - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - "}}"), - ZIGBEE_STATUS_DEVICE_IEEE, hex, nwkAddr - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - - const String * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); - if (friendlyName) { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" - ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), nwkAddr, friendlyName->c_str()); - } else { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"}}"), nwkAddr); - } - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - } - return -1; -} - -int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { - Z_ShortAddress srcAddr = buf.get16(2); - Z_ShortAddress nwkAddr = buf.get16(4); - Z_IEEEAddress ieeeAddr = buf.get64(6); - uint8_t capabilities = buf.get8(14); - - zigbee_devices.updateDevice(nwkAddr, ieeeAddr); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"PowerSource\":%s,\"ReceiveWhenIdle\":%s,\"Security\":%s}}"), - ZIGBEE_STATUS_DEVICE_ANNOUNCE, hex, nwkAddr, - (capabilities & 0x04) ? "true" : "false", - (capabilities & 0x08) ? "true" : "false", - (capabilities & 0x40) ? "true" : "false" - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - Z_SendActiveEpReq(nwkAddr); - return -1; -} - - -int32_t Z_ReceiveTCDevInd(int32_t res, const class SBuffer &buf) { - Z_ShortAddress srcAddr = buf.get16(2); - Z_IEEEAddress ieeeAddr = buf.get64(4); - Z_ShortAddress parentNw = buf.get16(12); - - zigbee_devices.updateDevice(srcAddr, ieeeAddr); - - char hex[20]; - Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - ",\"ParentNetwork\":\"0x%04X\"}}"), - ZIGBEE_STATUS_DEVICE_INDICATION, hex, srcAddr, parentNw - ); - - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); - - return -1; -} - - - -const uint32_t OCCUPANCY_TIMEOUT = 90 * 1000; - -void Z_AqaraOccupancy(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, const JsonObject *json) { - - const JsonVariant &val_endpoint = getCaseInsensitive(*json, PSTR(OCCUPANCY)); - if (nullptr != &val_endpoint) { - uint32_t occupancy = strToUInt(val_endpoint); - - if (occupancy) { - zigbee_devices.setTimer(shortaddr, OCCUPANCY_TIMEOUT, cluster, endpoint, 0, &Z_OccupancyCallback); - } - } -} - - - -int32_t Z_PublishAttributes(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { - const JsonObject *json = zigbee_devices.jsonGet(shortaddr); - if (json == nullptr) { return 0; } - - Z_AqaraOccupancy(shortaddr, cluster, endpoint, json); - - zigbee_devices.jsonPublishFlush(shortaddr); - return 1; -} - -int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { - uint16_t groupid = buf.get16(2); - uint16_t clusterid = buf.get16(4); - Z_ShortAddress srcaddr = buf.get16(6); - uint8_t srcendpoint = buf.get8(8); - uint8_t dstendpoint = buf.get8(9); - uint8_t wasbroadcast = buf.get8(10); - uint8_t linkquality = buf.get8(11); - uint8_t securityuse = buf.get8(12); - uint32_t timestamp = buf.get32(13); - uint8_t seqnumber = buf.get8(17); - - bool defer_attributes = false; - - zigbee_devices.updateLastSeen(srcaddr); - ZCLFrame zcl_received = ZCLFrame::parseRawFrame(buf, 19, buf.get8(18), clusterid, groupid, - srcaddr, - srcendpoint, dstendpoint, wasbroadcast, - linkquality, securityuse, seqnumber, - timestamp); - zcl_received.log(); - char shortaddr[8]; - snprintf_P(shortaddr, sizeof(shortaddr), PSTR("0x%04X"), srcaddr); - - DynamicJsonBuffer jsonBuffer; - JsonObject& json = jsonBuffer.createObject(); - - if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { - zcl_received.parseRawAttributes(json); - if (clusterid) { defer_attributes = true; } - } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { - zcl_received.parseReadAttributes(json); - } else if (zcl_received.isClusterSpecificCommand()) { - zcl_received.parseClusterSpecificCommand(json); - } - String msg(""); - msg.reserve(100); - json.printTo(msg); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); - - zcl_received.postProcessAttributes(srcaddr, json); - - json[F(D_CMND_ZIGBEE_ENDPOINT)] = srcendpoint; - - json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; - - if (defer_attributes) { - - if (zigbee_devices.jsonIsConflict(srcaddr, json)) { - - zigbee_devices.jsonPublishFlush(srcaddr); - } else { - zigbee_devices.jsonAppend(srcaddr, json); - zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); - } - } else { - - zigbee_devices.jsonPublishNow(srcaddr, json); - } - return -1; -} - -typedef struct Z_Dispatcher { - const uint8_t* match; - ZB_RecvMsgFunc func; -} Z_Dispatcher; - - -ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) -ZBM(AREQ_END_DEVICE_ANNCE_IND, Z_AREQ | Z_ZDO, ZDO_END_DEVICE_ANNCE_IND) -ZBM(AREQ_END_DEVICE_TC_DEV_IND, Z_AREQ | Z_ZDO, ZDO_TC_DEV_IND) -ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) -ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) -ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) -ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) - -const Z_Dispatcher Z_DispatchTable[] PROGMEM = { - { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, - { AREQ_END_DEVICE_ANNCE_IND, &Z_ReceiveEndDeviceAnnonce }, - { AREQ_END_DEVICE_TC_DEV_IND, &Z_ReceiveTCDevInd }, - { AREQ_PERMITJOIN_OPEN_XX, &Z_ReceivePermitJoinStatus }, - { AREQ_ZDO_NODEDESCRSP, &Z_ReceiveNodeDesc }, - { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, - { AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc }, - { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, -}; - -int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { - - if (zigbee.init_phase) { - - return -1; - } else { - for (uint32_t i = 0; i < sizeof(Z_DispatchTable)/sizeof(Z_Dispatcher); i++) { - if (Z_ReceiveMatchPrefix(buf, Z_DispatchTable[i].match)) { - (*Z_DispatchTable[i].func)(res, buf); - } - } - return -1; - } -} - -int32_t Z_Load_Devices(uint8_t value) { - - loadZigbeeDevices(); - return 0; -} - -int32_t Z_State_Ready(uint8_t value) { - zigbee.init_phase = false; - return 0; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" -#ifdef USE_ZIGBEE - -#define XDRV_23 23 - -const uint32_t ZIGBEE_BUFFER_SIZE = 256; -const uint8_t ZIGBEE_SOF = 0xFE; -const uint8_t ZIGBEE_SOF_ALT = 0xFF; - -#include -TasmotaSerial *ZigbeeSerial = nullptr; - - -const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" - D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" - D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" - D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" - D_CMND_ZIGBEE_PING ; - -const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" - D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" - D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" - D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" - D_CMND_ZIGBEE_PING ; - -void (* const ZigbeeCommand[])(void) PROGMEM = { - &CmndZbZNPSend, &CmndZbPermitJoin, - &CmndZbStatus, &CmndZbReset, &CmndZbSend, - &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, - &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, - &CmndZbPing, - }; - -int32_t ZigbeeProcessInput(class SBuffer &buf) { - if (!zigbee.state_machine) { return -1; } - - - bool recv_filter_match = true; - bool recv_prefix_match = false; - if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { - if (zigbee.recv_filter_len >= 2) { - recv_prefix_match = false; - if ( (pgm_read_byte(&zigbee.recv_filter[0]) == buf.get8(0)) && - (pgm_read_byte(&zigbee.recv_filter[1]) == buf.get8(1)) ) { - recv_prefix_match = true; - } - } - - for (uint32_t i = 0; i < zigbee.recv_filter_len; i++) { - if (pgm_read_byte(&zigbee.recv_filter[i]) != buf.get8(i)) { - recv_filter_match = false; - break; - } - } - - - } - - - int32_t res = -1; - - - - - - if ((zigbee.recv_filter) && (zigbee.recv_filter_len > 0)) { - if (!recv_prefix_match) { - res = -1; - } else { - if (recv_filter_match) { - res = 0; - } else { - if (zigbee.recv_until) { - res = -1; - } else { - res = -2; - } - } - } - } else { - res = -1; - } - - if (recv_prefix_match) { - if (zigbee.recv_func) { - res = (*zigbee.recv_func)(res, buf); - } - } - if (-1 == res) { - - if (zigbee.recv_unexpected) { - res = (*zigbee.recv_unexpected)(res, buf); - } - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "ZbProcessInput: res = %d"), res); - - - if (0 == res) { - - zigbee.state_waiting = false; - } else if (res > 0) { - ZigbeeGotoLabel(res); - } else if (-1 == res) { - - - } else { - - ZigbeeGotoLabel(zigbee.on_error_goto); - } -} - -void ZigbeeInput(void) -{ - static uint32_t zigbee_polling_window = 0; - static uint8_t fcs = ZIGBEE_SOF; - static uint32_t zigbee_frame_len = 5; -# 145 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" - while (ZigbeeSerial->available()) { - yield(); - uint8_t zigbee_in_byte = ZigbeeSerial->read(); - - - if (0 == zigbee_buffer->len()) { - zigbee_frame_len = 5; - fcs = ZIGBEE_SOF; - - - - if (ZIGBEE_SOF_ALT == zigbee_in_byte) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput forgiven first byte %02X (only for statistics)"), zigbee_in_byte); - zigbee_in_byte = ZIGBEE_SOF; - } - } - - if ((0 == zigbee_buffer->len()) && (ZIGBEE_SOF != zigbee_in_byte)) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbInput discarding byte %02X"), zigbee_in_byte); - continue; - } - - if (zigbee_buffer->len() < zigbee_frame_len) { - zigbee_buffer->add8(zigbee_in_byte); - zigbee_polling_window = millis(); - fcs ^= zigbee_in_byte; - } - - if (zigbee_buffer->len() >= zigbee_frame_len) { - zigbee_polling_window = 0; - break; - } - - - if (02 == zigbee_buffer->len()) { - - uint8_t len_byte = zigbee_buffer->get8(1); - if (len_byte > 250) len_byte = 250; - - zigbee_frame_len = len_byte + 5; - } - } - - if (zigbee_buffer->len() && (millis() > (zigbee_polling_window + ZIGBEE_POLLING))) { - char hex_char[(zigbee_buffer->len() * 2) + 2]; - ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char)); - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Bytes follow_read_metric = %0d"), ZigbeeSerial->getLoopReadMetric()); - - if (zigbee_buffer->len() != zigbee_frame_len) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received frame of wrong size %s, len %d, expected %d"), hex_char, zigbee_buffer->len(), zigbee_frame_len); - } else if (0x00 != fcs) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEEZNPRECEIVED ": received bad FCS frame %s, %d"), hex_char, fcs); - } else { - - - - SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); - - ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char)); - Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char); - if (Settings.flag3.tuya_serial_mqtt_publish) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); - } else { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); - } - - ZigbeeProcessInput(znp_buffer); - } - zigbee_buffer->setLen(0); - } -} - - - -void ZigbeeInit(void) -{ - zigbee.active = false; - if ((pin[GPIO_ZIGBEE_RX] < 99) && (pin[GPIO_ZIGBEE_TX] < 99)) { - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "GPIOs Rx:%d Tx:%d"), pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX]); - - ZigbeeSerial = new TasmotaSerial(pin[GPIO_ZIGBEE_RX], pin[GPIO_ZIGBEE_TX], seriallog_level ? 1 : 2, 0, 256); - ZigbeeSerial->begin(115200); - if (ZigbeeSerial->hardwareSerial()) { - ClaimSerial(); - uint32_t aligned_buffer = ((uint32_t)serial_in_buffer + 3) & ~3; - zigbee_buffer = new PreAllocatedSBuffer(sizeof(serial_in_buffer) - 3, (char*) aligned_buffer); - } else { - zigbee_buffer = new SBuffer(ZIGBEE_BUFFER_SIZE); - } - zigbee.active = true; - zigbee.init_phase = true; - zigbee.state_machine = true; - ZigbeeSerial->flush(); - } -} - - - - - -uint32_t strToUInt(const JsonVariant &val) { - - if (val.is()) { - return val.as(); - } else { - if (val.is()) { - String sval = val.as(); - return strtoull(sval.c_str(), nullptr, 0); - } - } - return 0; -} - -const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = - { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 , 0x01 }; - - -void CmndZbReset(void) { - if (ZigbeeSerial) { - switch (XdrvMailbox.payload) { - case 1: - ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET)); - eraseZigbeeDevices(); - restart_flag = 2; - ResponseCmndChar(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING); - break; - default: - ResponseCmndChar(D_JSON_ONE_TO_RESET); - } - } -} - -void CmndZbZNPSendOrReceive(bool send) -{ - if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) { - uint8_t code; - - char *codes = RemoveSpace(XdrvMailbox.data); - int32_t size = strlen(XdrvMailbox.data); - - SBuffer buf((size+1)/2); - - while (size > 1) { - char stemp[3]; - strlcpy(stemp, codes, sizeof(stemp)); - code = strtol(stemp, nullptr, 16); - buf.add8(code); - size -= 2; - codes += 2; - } - if (send) { - ZigbeeZNPSend(buf.getBuffer(), buf.len()); - } else { - ZigbeeProcessInput(buf); - } - } - ResponseCmndDone(); -} - - -void CmndZbZNPReceive(void) -{ - CmndZbZNPSendOrReceive(false); -} - -void CmndZbZNPSend(void) -{ - CmndZbZNPSendOrReceive(true); -} - -void ZigbeeZNPSend(const uint8_t *msg, size_t len) { - if ((len < 2) || (len > 252)) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPSENT ": bad message len %d"), len); - return; - } - uint8_t data_len = len - 2; - - if (ZigbeeSerial) { - uint8_t fcs = data_len; - - ZigbeeSerial->write(ZIGBEE_SOF); - - ZigbeeSerial->write(data_len); - - for (uint32_t i = 0; i < len; i++) { - uint8_t b = pgm_read_byte(msg + i); - ZigbeeSerial->write(b); - fcs ^= b; - - } - ZigbeeSerial->write(fcs); - - } - - char hex_char[(len * 2) + 2]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"), - ToHex_P(msg, len, hex_char, sizeof(hex_char))); -} - -void ZigbeeZCLSend(uint16_t dtsAddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { - SBuffer buf(25+len); - buf.add8(Z_SREQ | Z_AF); - buf.add8(AF_DATA_REQUEST); - buf.add16(dtsAddr); - buf.add8(endpoint); - buf.add8(0x01); - buf.add16(clusterId); - buf.add8(transacId); - buf.add8(0x30); - buf.add8(0x1E); - - buf.add8(3 + len); - buf.add8((needResponse ? 0x00 : 0x10) | (clusterSpecific ? 0x01 : 0x00)); - buf.add8(transacId); - buf.add8(cmdId); - if (len > 0) { - buf.addBuffer(msg, len); - } - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); -} - -void zigbeeZCLSendStr(uint16_t dstAddr, uint8_t endpoint, bool clusterSpecific, - uint16_t cluster, uint8_t cmd, const char *param) { - size_t size = param ? strlen(param) : 0; - SBuffer buf((size+2)/2); - - if (param) { - while (*param) { - uint8_t code = parseHex_P(¶m, 2); - buf.add8(code); - } - } - - if (0 == endpoint) { - - endpoint = zigbee_devices.findClusterEndpointIn(dstAddr, cluster); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: dstAddr 0x%04X, cluster 0x%04X, endpoint 0x%02X, cmd 0x%02X, data %s"), - dstAddr, cluster, endpoint, cmd, param); - - if (0 == endpoint) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("ZbSend: unspecified endpoint")); - return; - } - - - ZigbeeZCLSend(dstAddr, cluster, endpoint, cmd, clusterSpecific, buf.getBuffer(), buf.len(), false, zigbee_devices.getNextSeqNumber(dstAddr)); - - if (clusterSpecific) { - zigbeeSetCommandTimer(dstAddr, cluster, endpoint); - } - ResponseCmndDone(); -} - -void CmndZbSend(void) { -# 419 "S:/Development/Tasmota/tasmota/xdrv_23_zigbee_9_impl.ino" - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); - if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } - - - static char delim[] = ", "; - uint16_t device = 0xFFFF; - uint8_t endpoint = 0x00; - - uint16_t cluster = 0; - uint8_t cmd = 0; - String cmd_str = ""; - - - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } - } - if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } - - const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); - if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } - const JsonVariant &val_cmd = getCaseInsensitive(json, PSTR("Send")); - if (nullptr != &val_cmd) { - - - - if (val_cmd.is()) { - - JsonObject &cmd_obj = val_cmd.as(); - int32_t cmd_size = cmd_obj.size(); - if (cmd_size > 1) { - Response_P(PSTR("Only 1 command allowed (%d)"), cmd_size); - return; - } else if (1 == cmd_size) { - - JsonObject::iterator it = cmd_obj.begin(); - String key = it->key; - JsonVariant& value = it->value; - uint32_t x = 0, y = 0, z = 0; - uint16_t cmd_var; - - const __FlashStringHelper* tasmota_cmd = zigbeeFindCommand(key.c_str(), &cluster, &cmd_var); - if (tasmota_cmd) { - cmd_str = tasmota_cmd; - } else { - Response_P(PSTR("Unrecognized zigbee command: %s"), key.c_str()); - return; - } - - - if (value.is()) { - x = value.as() ? 1 : 0; - } else if (value.is()) { - x = value.as(); - } else { - - const char *s_const = value.as(); - if (s_const != nullptr) { - char s[strlen(s_const)+1]; - strcpy(s, s_const); - if ((nullptr != s) && (0x00 != *s)) { - char *sval = strtok(s, delim); - if (sval) { - x = ZigbeeAliasOrNumber(sval); - sval = strtok(nullptr, delim); - if (sval) { - y = ZigbeeAliasOrNumber(sval); - sval = strtok(nullptr, delim); - if (sval) { - z = ZigbeeAliasOrNumber(sval); - } - } - } - } - } - } - - - if (0xFF == cmd_var) { - cmd = x; - x = y; - y = z; - } else { - cmd = cmd_var; - } - cmd_str = zigbeeCmdAddParams(cmd_str.c_str(), x, y, z); - - } else { - - } - } else if (val_cmd.is()) { - - cmd_str = val_cmd.as(); - } else { - - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbCmd_actual: ZigbeeZCLSend {\"device\":\"0x%04X\",\"endpoint\":%d,\"send\":\"%04X!%02X/%s\"}"), - device, endpoint, cluster, cmd, cmd_str.c_str()); - zigbeeZCLSendStr(device, endpoint, true, cluster, cmd, cmd_str.c_str()); - } else { - Response_P(PSTR("Missing zigbee 'Send'")); - return; - } - -} - -ZBM(ZBS_BIND_REQ, Z_SREQ | Z_ZDO, ZDO_BIND_REQ, - 0,0, - 0,0,0,0,0,0,0,0, - 0x00, - 0x00, 0x00, - 0x03, - 0,0,0,0,0,0,0,0, - 0x01 -) - -void CmndZbBind(void) { - - - - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); - if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } - - - - uint16_t device = 0xFFFF; - uint8_t endpoint = 0x00; - uint16_t cluster = 0; - uint32_t group = 0xFFFFFFFF; - - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } - } - if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } - - const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); - if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } - const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); - if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } - - - - SBuffer buf(sizeof(ZBS_BIND_REQ)); - buf.add8(Z_SREQ | Z_ZDO); - buf.add8(ZDO_BIND_REQ); - buf.add16(device); - buf.add64(zigbee_devices.getDeviceLongAddr(device)); - buf.add8(endpoint); - buf.add16(cluster); - buf.add8(0x03); - buf.add64(localIEEEAddr); - buf.add8(0x01); - - ZigbeeZNPSend(buf.getBuffer(), buf.len()); - - ResponseCmndDone(); -} - - -void CmndZbProbe(void) { - CmndZbProbeOrPing(true); -} - -void CmndZbProbeOrPing(boolean probe) { - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } - if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } - - - Z_SendIEEEAddrReq(shortaddr); - if (probe) { - Z_SendActiveEpReq(shortaddr); - } - ResponseCmndDone(); -} - - -void CmndZbPing(void) { - CmndZbProbeOrPing(false); -} - - -void CmndZbName(void) { - - - - - - - - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - - - char *p; - char *str = strtok_r(XdrvMailbox.data, ", ", &p); - - - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); - if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } - if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } - - if (p == nullptr) { - const String * friendlyName = zigbee_devices.getFriendlyName(shortaddr); - Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, friendlyName ? friendlyName->c_str() : ""); - } else { - zigbee_devices.setFriendlyName(shortaddr, p); - Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), shortaddr, p); - } -} - - -void CmndZbForget(void) { - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } - if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } - - - if (zigbee_devices.removeDevice(shortaddr)) { - ResponseCmndDone(); - } else { - ResponseCmndChar("Unknown device"); - } -} - - -void CmndZbSave(void) { - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - - saveZigbeeDevices(); - - ResponseCmndDone(); -} - - -void CmndZbRead(void) { - - - - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - DynamicJsonBuffer jsonBuf; - JsonObject &json = jsonBuf.parseObject(XdrvMailbox.data); - if (!json.success()) { ResponseCmndChar(D_JSON_INVALID_JSON); return; } - - - uint16_t device = 0xFFFF; - uint16_t cluster = 0x0000; - uint8_t endpoint = 0x00; - size_t attrs_len = 0; - uint8_t* attrs = nullptr; - - const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); - if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } - } - if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } - - const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); - if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } - const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); - if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } - - const JsonVariant &val_attr = getCaseInsensitive(json, PSTR("Read")); - if (nullptr != &val_attr) { - uint16_t val = strToUInt(val_attr); - if (val_attr.is()) { - JsonArray& attr_arr = val_attr; - attrs_len = attr_arr.size() * 2; - attrs = new uint8_t[attrs_len]; - - uint32_t i = 0; - for (auto value : attr_arr) { - uint16_t val = strToUInt(value); - attrs[i++] = val & 0xFF; - attrs[i++] = val >> 8; - } - } else { - attrs_len = 2; - attrs = new uint8_t[attrs_len]; - attrs[0] = val & 0xFF; - attrs[1] = val >> 8; - } - } - - if (0 == endpoint) { - endpoint = zigbee_devices.findClusterEndpointIn(device, cluster); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ZbSend: guessing endpoint 0x%02X"), endpoint); - } - - if ((0 != endpoint) && (attrs_len > 0)) { - ZigbeeZCLSend(device, cluster, endpoint, ZCL_READ_ATTRIBUTES, false, attrs, attrs_len, true , zigbee_devices.getNextSeqNumber(device)); - ResponseCmndDone(); - } else { - ResponseCmndChar("Missing parameters"); - } - - if (attrs) { delete[] attrs; } -} - - -void CmndZbPermitJoin(void) -{ - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - uint32_t payload = XdrvMailbox.payload; - if (payload < 0) { payload = 0; } - if ((99 != payload) && (payload > 1)) { payload = 1; } - - if (1 == payload) { - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_60); - } else if (99 == payload){ - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_OPEN_XX); - } else { - ZigbeeGotoLabel(ZIGBEE_LABEL_PERMIT_JOIN_CLOSE); - } - ResponseCmndDone(); -} - -void CmndZbStatus(void) { - if (ZigbeeSerial) { - if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } - uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); - if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } - if (XdrvMailbox.payload > 0) { - if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } - } - - String dump = zigbee_devices.dump(XdrvMailbox.index, shortaddr); - Response_P(PSTR("{\"%s%d\":%s}"), XdrvMailbox.command, XdrvMailbox.index, dump.c_str()); - } -} - - - - - -bool Xdrv23(uint8_t function) -{ - bool result = false; - - if (zigbee.active) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (!zigbee.init_phase) { - zigbee_devices.runTimer(); - } - break; - case FUNC_LOOP: - if (ZigbeeSerial) { ZigbeeInput(); } - if (zigbee.state_machine) { - - ZigbeeStateMachine_Run(); - } - break; - case FUNC_PRE_INIT: - ZigbeeInit(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kZbCommands, ZigbeeCommand); - result = result || DecodeCommand(kZigbeeCommands, ZigbeeCommand); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_24_buzzer.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_24_buzzer.ino" -#ifdef USE_BUZZER - - - - -#define XDRV_24 24 - -struct BUZZER { - uint32_t tune = 0; - uint32_t tune_reload = 0; - bool active = true; - bool enable = false; - uint8_t inverted = 0; - uint8_t count = 0; - uint8_t mode = 0; - uint8_t set[2]; - uint8_t duration; - uint8_t state = 0; -} Buzzer; - - - -void BuzzerOff(void) -{ - DigitalWrite(GPIO_BUZZER, Buzzer.inverted); -} - - -void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32_t mode) -{ - Buzzer.set[0] = off; - Buzzer.set[1] = on; - Buzzer.duration = 1; - Buzzer.tune_reload = 0; - Buzzer.mode = mode; - - if (tune) { - uint32_t tune1 = tune; - uint32_t tune2 = tune; - for (uint32_t i = 0; i < 32; i++) { - if (!(tune2 & 0x80000000)) { - tune2 <<= 1; - } else { - Buzzer.tune_reload <<= 1; - Buzzer.tune_reload |= tune1 & 1; - tune1 >>= 1; - } - } - Buzzer.tune = Buzzer.tune_reload; - } - Buzzer.count = count * 2; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BUZ: %d(%d),%d,%d,0x%08X(0x%08X)"), count, Buzzer.count, on, off, tune, Buzzer.tune); - - Buzzer.enable = (Buzzer.count > 0); - if (!Buzzer.enable) { - BuzzerOff(); - } -} - -void BuzzerSetStateToLed(uint32_t state) -{ - if (Buzzer.enable && (2 == Buzzer.mode)) { - Buzzer.state = (state != 0); - DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); - } -} - -void BuzzerBeep(uint32_t count) -{ - BuzzerBeep(count, 1, 1, 0, 0); -} - -void BuzzerEnabledBeep(uint32_t count, uint32_t duration) -{ - if (Settings.flag3.buzzer_enable) { - BuzzerBeep(count, duration, 1, 0, 0); - } -} - - - -bool BuzzerPinState(void) -{ - if (XdrvMailbox.index == GPIO_BUZZER_INV) { - Buzzer.inverted = 1; - XdrvMailbox.index -= (GPIO_BUZZER_INV - GPIO_BUZZER); - return true; - } - return false; -} - -void BuzzerInit(void) -{ - if (pin[GPIO_BUZZER] < 99) { - pinMode(pin[GPIO_BUZZER], OUTPUT); - BuzzerOff(); - } else { - Buzzer.active = false; - } -} - -void BuzzerEvery100mSec(void) -{ - if (Buzzer.enable && (Buzzer.mode != 2)) { - if (Buzzer.count) { - if (Buzzer.duration) { - Buzzer.duration--; - if (!Buzzer.duration) { - if (Buzzer.tune) { - Buzzer.state = Buzzer.tune & 1; - Buzzer.tune >>= 1; - } else { - Buzzer.tune = Buzzer.tune_reload; - Buzzer.count -= (Buzzer.tune_reload) ? 2 : 1; - Buzzer.state = Buzzer.count & 1; - if (Buzzer.mode) { - Buzzer.count |= 2; - } - } - Buzzer.duration = Buzzer.set[Buzzer.state]; - } - } - DigitalWrite(GPIO_BUZZER, (Buzzer.inverted) ? !Buzzer.state : Buzzer.state); - } else { - Buzzer.enable = false; - } - } -} - - - - - -const char kBuzzerCommands[] PROGMEM = "|" - "Buzzer" ; - -void (* const BuzzerCommand[])(void) PROGMEM = { - &CmndBuzzer }; - -void CmndBuzzer(void) -{ -# 174 "S:/Development/Tasmota/tasmota/xdrv_24_buzzer.ino" - if (XdrvMailbox.data_len > 0) { - if (XdrvMailbox.payload != 0) { - uint32_t parm[4] = { 0 }; - uint32_t mode = 0; - ParseParameters(4, parm); - if (XdrvMailbox.payload <= 0) { - parm[0] = 1; - mode = -XdrvMailbox.payload; - } - for (uint32_t i = 1; i < 3; i++) { - if (parm[i] < 1) { parm[i] = 1; } - } - BuzzerBeep(parm[0], parm[1], parm[2], parm[3], mode); - } else { - BuzzerBeep(0); - } - } else { - BuzzerBeep(1); - } - ResponseCmndDone(); -} - - - - - -bool Xdrv24(uint8_t function) -{ - bool result = false; - - if (Buzzer.active) { - switch (function) { - case FUNC_EVERY_100_MSECOND: - BuzzerEvery100mSec(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kBuzzerCommands, BuzzerCommand); - break; - case FUNC_PRE_INIT: - BuzzerInit(); - break; - case FUNC_PIN_STATE: - result = BuzzerPinState(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" -# 21 "S:/Development/Tasmota/tasmota/xdrv_25_A4988_Stepper.ino" -#ifdef USE_A4988_STEPPER - - - - -#define XDRV_25 25 - -#include - -short A4988_dir_pin = pin[GPIO_MAX]; -short A4988_stp_pin = pin[GPIO_MAX]; -short A4988_ms1_pin = pin[GPIO_MAX]; -short A4988_ms2_pin = pin[GPIO_MAX]; -short A4988_ms3_pin = pin[GPIO_MAX]; -short A4988_ena_pin = pin[GPIO_MAX]; -int A4988_spr = 0; -float A4988_rpm = 0; -short A4988_mis = 0; - -A4988_Stepper* myA4988 = nullptr; - -void A4988Init(void) -{ - A4988_dir_pin = pin[GPIO_A4988_DIR]; - A4988_stp_pin = pin[GPIO_A4988_STP]; - A4988_ena_pin = pin[GPIO_A4988_ENA]; - A4988_ms1_pin = pin[GPIO_A4988_MS1]; - A4988_ms2_pin = pin[GPIO_A4988_MS2]; - A4988_ms3_pin = pin[GPIO_A4988_MS3]; - A4988_spr = 200; - A4988_rpm = 30; - A4988_mis = 1; - - myA4988 = new A4988_Stepper( A4988_spr - , A4988_rpm - , A4988_mis - , A4988_dir_pin - , A4988_stp_pin - , A4988_ena_pin - , A4988_ms1_pin - , A4988_ms2_pin - , A4988_ms3_pin ); -} - -const char kA4988Commands[] PROGMEM = "Motor|" - "Move|Rotate|Turn|MIS|SPR|RPM"; - -void (* const A4988Command[])(void) PROGMEM = { - &CmndDoMove,&CmndDoRotate,&CmndDoTurn,&CmndSetMIS,&CmndSetSPR,&CmndSetRPM}; - -void CmndDoMove(void) { - if (XdrvMailbox.data_len > 0) { - long stepsPlease = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->doMove(stepsPlease); - ResponseCmndDone(); - } -} - -void CmndDoRotate(void) { - if (XdrvMailbox.data_len > 0) { - long degrsPlease = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->doRotate(degrsPlease); - ResponseCmndDone(); - } -} - -void CmndDoTurn(void) { - if (XdrvMailbox.data_len > 0) { - float turnsPlease = strtod(XdrvMailbox.data,nullptr); - myA4988->doTurn(turnsPlease); - ResponseCmndDone(); - } -} - -void CmndSetMIS(void) { - if ((pin[GPIO_A4988_MS1] < 99) && (pin[GPIO_A4988_MS2] < 99) && (pin[GPIO_A4988_MS3] < 99) && (XdrvMailbox.data_len > 0)) { - short newMIS = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setMIS(newMIS); - ResponseCmndDone(); - } -} - -void CmndSetSPR(void) { - if (XdrvMailbox.data_len > 0) { - int newSPR = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setSPR(newSPR); - ResponseCmndDone(); - } -} - -void CmndSetRPM(void) { - if (XdrvMailbox.data_len > 0) { - short newRPM = strtoul(XdrvMailbox.data,nullptr,10); - myA4988->setRPM(newRPM); - ResponseCmndDone(); - } -} - - - - -bool Xdrv25(uint8_t function) -{ - bool result = false; - if ((pin[GPIO_A4988_DIR] < 99) && (pin[GPIO_A4988_STP] < 99)) { - switch (function) { - case FUNC_INIT: - A4988Init(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kA4988Commands, A4988Command); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_26_ariluxrf.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_26_ariluxrf.ino" -#ifdef USE_LIGHT -#ifdef USE_ARILUX_RF - - - - -#define XDRV_26 26 - -const uint32_t ARILUX_RF_TIME_AVOID_DUPLICATE = 1000; - -const uint8_t ARILUX_RF_MAX_CHANGES = 51; -const uint32_t ARILUX_RF_SEPARATION_LIMIT = 4300; -const uint32_t ARILUX_RF_RECEIVE_TOLERANCE = 60; - -struct ARILUX { - unsigned int rf_timings[ARILUX_RF_MAX_CHANGES]; - - unsigned long rf_received_value = 0; - unsigned long rf_last_received_value = 0; - unsigned long rf_last_time = 0; - unsigned long rf_lasttime = 0; - - unsigned int rf_change_count = 0; - unsigned int rf_repeat_count = 0; - - uint8_t rf_toggle = 0; -} Arilux; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -#ifndef USE_WS2812_DMA -void AriluxRfInterrupt(void) ICACHE_RAM_ATTR; -#endif -#endif - -void AriluxRfInterrupt(void) -{ - unsigned long time = micros(); - unsigned int duration = time - Arilux.rf_lasttime; - - if (duration > ARILUX_RF_SEPARATION_LIMIT) { - if (abs(duration - Arilux.rf_timings[0]) < 200) { - Arilux.rf_repeat_count++; - if (Arilux.rf_repeat_count == 2) { - unsigned long code = 0; - const unsigned int delay = Arilux.rf_timings[0] / 31; - const unsigned int delayTolerance = delay * ARILUX_RF_RECEIVE_TOLERANCE / 100; - for (unsigned int i = 1; i < Arilux.rf_change_count -1; i += 2) { - code <<= 1; - if (abs(Arilux.rf_timings[i] - (delay *3)) < delayTolerance && abs(Arilux.rf_timings[i +1] - delay) < delayTolerance) { - code |= 1; - } - } - if (Arilux.rf_change_count > 49) { - Arilux.rf_received_value = code; - } - Arilux.rf_repeat_count = 0; - } - } - Arilux.rf_change_count = 0; - } - if (Arilux.rf_change_count >= ARILUX_RF_MAX_CHANGES) { - Arilux.rf_change_count = 0; - Arilux.rf_repeat_count = 0; - } - Arilux.rf_timings[Arilux.rf_change_count++] = duration; - Arilux.rf_lasttime = time; -} - -void AriluxRfHandler(void) -{ - unsigned long now = millis(); - if (Arilux.rf_received_value && !((Arilux.rf_received_value == Arilux.rf_last_received_value) && (now - Arilux.rf_last_time < ARILUX_RF_TIME_AVOID_DUPLICATE))) { - Arilux.rf_last_received_value = Arilux.rf_received_value; - Arilux.rf_last_time = now; - - uint16_t hostcode = Arilux.rf_received_value >> 8 & 0xFFFF; - if (Settings.rf_code[1][6] == Settings.rf_code[1][7]) { - Settings.rf_code[1][6] = hostcode >> 8 & 0xFF; - Settings.rf_code[1][7] = hostcode & 0xFF; - } - uint16_t stored_hostcode = Settings.rf_code[1][6] << 8 | Settings.rf_code[1][7]; - - DEBUG_DRIVER_LOG(PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, Arilux.rf_received_value); - - if (hostcode == stored_hostcode) { - char command[33]; - char value = '-'; - command[0] = '\0'; - uint8_t keycode = Arilux.rf_received_value & 0xFF; - switch (keycode) { - case 1: - case 3: - snprintf_P(command, sizeof(command), PSTR(D_CMND_POWER " %d"), (1 == keycode) ? 1 : 0); - break; - case 2: - Arilux.rf_toggle++; - Arilux.rf_toggle &= 0x3; - snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), 200 + Arilux.rf_toggle); - break; - case 4: - value = '+'; - case 7: - snprintf_P(command, sizeof(command), PSTR(D_CMND_SPEED " %c"), value); - break; - case 5: - value = '+'; - case 8: - snprintf_P(command, sizeof(command), PSTR(D_CMND_SCHEME " %c"), value); - break; - case 6: - value = '+'; - case 9: - snprintf_P(command, sizeof(command), PSTR(D_CMND_DIMMER " %c"), value); - break; - default: { - if ((keycode >= 10) && (keycode <= 21)) { - snprintf_P(command, sizeof(command), PSTR(D_CMND_COLOR " %d"), keycode -9); - } - } - } - if (strlen(command)) { - ExecuteCommand(command, SRC_LIGHT); - } - } - } - Arilux.rf_received_value = 0; -} - -void AriluxRfInit(void) -{ - if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { - if (Settings.last_module != Settings.module) { - Settings.rf_code[1][6] = 0; - Settings.rf_code[1][7] = 0; - Settings.last_module = Settings.module; - } - Arilux.rf_received_value = 0; - - digitalWrite(pin[GPIO_ARIRFSEL], 0); - attachInterrupt(pin[GPIO_ARIRFRCV], AriluxRfInterrupt, CHANGE); - } -} - -void AriluxRfDisable(void) -{ - if ((pin[GPIO_ARIRFRCV] < 99) && (pin[GPIO_ARIRFSEL] < 99)) { - detachInterrupt(pin[GPIO_ARIRFRCV]); - digitalWrite(pin[GPIO_ARIRFSEL], 1); - } -} - - - - - -bool Xdrv26(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (pin[GPIO_ARIRFRCV] < 99) { AriluxRfHandler(); } - break; - case FUNC_EVERY_SECOND: - if (10 == uptime) { AriluxRfInit(); } - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_27_shutter.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_27_shutter.ino" -#ifdef USE_SHUTTER - - - - -#define XDRV_27 27 - -#define D_SHUTTER "SHUTTER" - -const uint16_t MOTOR_STOP_TIME = 500; -const uint8_t steps_per_second = 20; - -uint8_t calibrate_pos[6] = {0,30,50,70,90,100}; -uint16_t messwerte[5] = {30,50,70,90,100}; -uint16_t last_execute_step; - -enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; -enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; - -const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" - D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" - D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|" - D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" - D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME; - -void (* const ShutterCommand[])(void) PROGMEM = { - &CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition, - &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, - &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, - &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime}; - - const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}"; - const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; - -#include - -Ticker TickerShutter; - -struct SHUTTER { - power_t mask = 0; - power_t old_power = 0; - power_t switched_relay = 0; - uint32_t time[MAX_SHUTTERS]; - int32_t open_max[MAX_SHUTTERS]; - int32_t target_position[MAX_SHUTTERS]; - int32_t start_position[MAX_SHUTTERS]; - int32_t real_position[MAX_SHUTTERS]; - uint16_t open_time[MAX_SHUTTERS]; - uint16_t close_time[MAX_SHUTTERS]; - uint16_t close_velocity[MAX_SHUTTERS]; - int8_t direction[MAX_SHUTTERS]; - uint8_t mode = 0; - int16_t motordelay[MAX_SHUTTERS]; - int16_t pwm_frequency[MAX_SHUTTERS]; - uint16_t max_pwm_frequency = 1000; - uint16_t max_close_pwm_frequency[MAX_SHUTTERS]; - uint8_t skip_relay_change; - int32_t accelerator[MAX_SHUTTERS]; -} Shutter; - -void ShutterLogPos(uint32_t i) -{ - char stemp2[10]; - dtostrfd((float)Shutter.time[i] / steps_per_second, 2, stemp2); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter%d Real %d, Start %d, Stop %d, Dir %d, Delay %d, Rtc %s [s], Freq %d"), - i+1, Shutter.real_position[i], Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i], Shutter.motordelay[i], stemp2, Shutter.pwm_frequency[i]); -} - -void ShutterRtc50mS(void) -{ - for (uint8_t i = 0; i < shutters_present; i++) { - Shutter.time[i]++; - if (Shutter.accelerator[i]) { - - Shutter.pwm_frequency[i] += Shutter.accelerator[i]; - Shutter.pwm_frequency[i] = tmax(0,tmin(Shutter.direction[i]==1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i],Shutter.pwm_frequency[i])); - analogWriteFreq(Shutter.pwm_frequency[i]); - analogWrite(pin[GPIO_PWM1+i], 50); - } - } -} - -#define SHT_DIV_ROUND(__A,__B) (((__A) + (__B)/2) / (__B)) - -int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index) -{ - if (Settings.shutter_set50percent[index] != 50) { - return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; - } else { - uint32_t realpos; - - for (uint32_t j = 0; j < 5; j++) { - if (0 == Settings.shuttercoeff[j][index]) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0")); - for (uint32_t k = 0; k < 5; k++) { - Settings.shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]); - } - } - } - for (uint32_t i = 0; i < 5; i++) { - if ((percent * 10) >= Settings.shuttercoeff[i][index]) { - realpos = SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i+1], 100); - - } else { - if (0 == i) { - realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter.open_max[index] * calibrate_pos[i+1], Settings.shuttercoeff[i][index]), 10); - } else { - - - realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter.open_max[index] * (calibrate_pos[i+1] - calibrate_pos[i]), Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), 100); - } - break; - } - } - return realpos; - } -} - -uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index) -{ - if (Settings.shutter_set50percent[index] != 50) { - return (Settings.shuttercoeff[2][index] * 5 > realpos) ? SHT_DIV_ROUND(realpos, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos-Settings.shuttercoeff[0][index], Settings.shuttercoeff[1][index]); - } else { - uint16_t realpercent; - - for (uint32_t i = 0; i < 5; i++) { - if (realpos >= Shutter.open_max[index] * calibrate_pos[i+1] / 100) { - realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[i][index], 10); - - } else { - if (0 == i) { - realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * Settings.shuttercoeff[i][index], calibrate_pos[i+1]), Shutter.open_max[index]); - } else { - - - - realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter.open_max[index] * calibrate_pos[i], 100)) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]), (calibrate_pos[i+1] - calibrate_pos[i])), Shutter.open_max[index]) ; - } - break; - } - } - return realpercent; - } -} - -void ShutterInit(void) -{ - shutters_present = 0; - Shutter.mask = 0; - - Shutter.old_power = power; - bool relay_in_interlock = false; - - - if (Settings.shutter_startrelay[MAX_SHUTTERS] == 0) { - Shutter.max_pwm_frequency = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : Shutter.max_pwm_frequency; - } - for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { - - Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]); - if (Settings.shutter_startrelay[i] && (Settings.shutter_startrelay[i] < 9)) { - shutters_present++; - - - Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1) ; - - for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { - - if (Settings.interlock[j] && (Settings.interlock[j] & Shutter.mask)) { - - relay_in_interlock = true; - } - } - if (relay_in_interlock) { - if (Settings.pulse_timer[i] > 0) { - Shutter.mode = SHT_PULSE_OPEN__PULSE_CLOSE; - } else { - Shutter.mode = SHT_OFF_OPEN__OFF_CLOSE; - } - } else { - Shutter.mode = SHT_OFF_ON__OPEN_CLOSE; - if ((pin[GPIO_PWM1+i] < 99) && (pin[GPIO_CNTR1+i] < 99)) { - Shutter.mode = SHT_OFF_ON__OPEN_CLOSE_STEPPER; - Shutter.pwm_frequency[i] = 0; - Shutter.accelerator[i] = 0; - analogWriteFreq(Shutter.pwm_frequency[i]); - analogWrite(pin[GPIO_PWM1+i], 50); - } - } - - TickerShutter.attach_ms(50, ShutterRtc50mS ); - - Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] > 0) ? Settings.shutter_set50percent[i] : 50; - - - Shutter.open_time[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100; - Shutter.close_time[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100; - - - Shutter.open_max[i] = 200 * Shutter.open_time[i]; - Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ; - Shutter.max_close_pwm_frequency[i] = Shutter.max_pwm_frequency*Shutter.open_time[i] / Shutter.close_time[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d Closefreq: %d"),i, Shutter.max_close_pwm_frequency[i]); - - - if (Settings.shutter_set50percent[i] != 50) { - Settings.shuttercoeff[1][i] = Shutter.open_max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; - Settings.shuttercoeff[0][i] = Shutter.open_max[i] - (Settings.shuttercoeff[1][i] * 100); - Settings.shuttercoeff[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5; - } - Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1); - - Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i); - - Shutter.start_position[i] = Shutter.target_position[i] = Shutter.real_position[i]; - Shutter.motordelay[i] = Settings.shutter_motordelay[i]; - - char shutter_open_chr[10]; - dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr); - char shutter_close_chr[10]; - dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr); - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100, Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoeffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, is locked %d, end stop time enabled %d, shuttermode %d, motordelay %d"), - i+1, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr, - Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i], - Shutter.mask, (Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, Shutter.mode, Shutter.motordelay[i]); - - } else { - - break; - } - ShutterLimitRealAndTargetPositions(i); - Settings.shutter_accuracy = 1; - } -} - -void ShutterReportPosition(bool always) -{ - Response_P(PSTR("{")); - for (uint32_t i = 0; i < shutters_present; i++) { - - uint32_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); - if (Shutter.direction[i] != 0) { - rules_flag.shutter_moving = 1; - ShutterLogPos(i); - } - if (i) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i], ShutterRealToPercentPosition(Shutter.target_position[i], i)); - } - ResponseJsonEnd(); - if (always || (rules_flag.shutter_moving)) { - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); - XdrvRulesProcess(); - } - - -} - -void ShutterLimitRealAndTargetPositions(uint32_t i) { - if (Shutter.real_position[i]<0) Shutter.real_position[i] = 0; - if (Shutter.real_position[i]>Shutter.open_max[i]) Shutter.real_position[i] = Shutter.open_max[i]; - if (Shutter.target_position[i]<0) Shutter.target_position[i] = 0; - if (Shutter.target_position[i]>Shutter.open_max[i]) Shutter.target_position[i] = Shutter.open_max[i]; -} - -void ShutterUpdatePosition(void) -{ - - char scommand[CMDSZ]; - char stopic[TOPSZ]; - - for (uint32_t i = 0; i < shutters_present; i++) { - if (Shutter.direction[i] != 0) { - int32_t stop_position_delta = 20; - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { - - - Shutter.real_position[i] = ShutterCounterBasedPosition(i); - - int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; - int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); - int32_t min_runtime_ms = Shutter.pwm_frequency[i]*1000 / max_freq_change_per_sec; - int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; - int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency[i] / max_frequency * Shutter.direction[i] ; - - int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; - stop_position_delta =200 * Shutter.pwm_frequency[i]/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); - - - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, - Shutter.pwm_frequency[i],max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); - - if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { - - Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); - - } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency[i] == max_frequency) { - Shutter.accelerator[i] = 0; - } - } else { - Shutter.real_position[i] = Shutter.start_position[i] + ( (Shutter.time[i] - Shutter.motordelay[i]) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); - } - if ( Shutter.real_position[i] * Shutter.direction[i] + stop_position_delta >= Shutter.target_position[i] * Shutter.direction[i] ) { - - - uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ; - int16_t missing_steps; - - switch (Shutter.mode) { - case SHT_PULSE_OPEN__PULSE_CLOSE: - - if (SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source) { - ExecuteCommandPower(cur_relay, 1, SRC_SHUTTER); - } else { - last_source = SRC_SHUTTER; - } - break; - case SHT_OFF_ON__OPEN_CLOSE_STEPPER: - missing_steps = ((Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) - RtcSettings.pulse_counter[i]; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Remain steps %d, counter %d, freq %d"), missing_steps, RtcSettings.pulse_counter[i] ,Shutter.pwm_frequency[i]); - Shutter.accelerator[i] = 0; - Shutter.pwm_frequency[i] = Shutter.pwm_frequency[i] > 250 ? 250 : Shutter.pwm_frequency[i]; - analogWriteFreq(Shutter.pwm_frequency[i]); - analogWrite(pin[GPIO_PWM1+i], 50); - Shutter.pwm_frequency[i] = 0; - analogWriteFreq(Shutter.pwm_frequency[i]); - while (RtcSettings.pulse_counter[i] < (uint32_t)(Shutter.target_position[i]-Shutter.start_position[i])*Shutter.direction[i]*Shutter.max_pwm_frequency/2000) { - delay(1); - } - analogWrite(pin[GPIO_PWM1+i], 0); - Shutter.real_position[i] = ShutterCounterBasedPosition(i); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); - - if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { - ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); - ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); - } - break; - case SHT_OFF_ON__OPEN_CLOSE: - if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { - ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); - ExecuteCommandPower(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER); - } - break; - case SHT_OFF_OPEN__OFF_CLOSE: - - if ((1 << (cur_relay-1)) & power) { - - ExecuteCommandPower(cur_relay, 0, SRC_SHUTTER); - } - break; - } - ShutterLimitRealAndTargetPositions(i); - Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter.real_position[i], i); - - ShutterLogPos(i); - - Shutter.start_position[i] = Shutter.real_position[i]; - - - snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); - GetTopic_P(stopic, STAT, mqtt_topic, scommand); - Response_P("%d", (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); - MqttPublish(stopic, Settings.flag.mqtt_power_retain); - - Shutter.direction[i] = 0; - ShutterReportPosition(true); - rules_flag.shutter_moved = 1; - XdrvRulesProcess(); - } - } - } -} - -bool ShutterState(uint32_t device) -{ - device--; - device &= 3; - return (Settings.flag3.shutter_mode && - (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) ); -} - -void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) -{ - - if ( ( (1 == direction) && ((Shutter.open_max[i] - Shutter.real_position[i]) / 100 <= 2) ) - || ( (-1 == direction) && (Shutter.real_position[i] / Shutter.close_velocity[i] <= 2)) ) { - Shutter.skip_relay_change = 1; - } else { - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { - Shutter.pwm_frequency[i] = 0; - analogWriteFreq(Shutter.pwm_frequency[i]); - analogWrite(pin[GPIO_PWM1+i], 0); - - if (pin[GPIO_CNTR1+i] < 99) { - RtcSettings.pulse_counter[i] = 0; - } - Shutter.accelerator[i] = Shutter.max_pwm_frequency / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Ramp up: %d"), Shutter.accelerator[i]); - } - Shutter.target_position[i] = target_pos; - Shutter.start_position[i] = Shutter.real_position[i]; - Shutter.time[i] = 0; - Shutter.skip_relay_change = 0; - Shutter.direction[i] = direction; - - } - -} - -void ShutterWaitForMotorStop(uint32_t i) -{ - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop..")); - if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { - if (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode) { - - while (Shutter.pwm_frequency[i] > 0) { - - Shutter.pwm_frequency[i] = tmax(Shutter.pwm_frequency[i]-((Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i])/(Shutter.motordelay[i]+1)) , 0); - - analogWriteFreq(Shutter.pwm_frequency[i]); - analogWrite(pin[GPIO_PWM1+i], 50); - delay(50); - } - analogWrite(pin[GPIO_PWM1+i], 0); - Shutter.real_position[i] = ShutterCounterBasedPosition(i); - } else { - ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); - delay(MOTOR_STOP_TIME); - } - } else { - delay(MOTOR_STOP_TIME); - } -} - -int32_t ShutterCounterBasedPosition(uint32_t i) -{ - return ((int32_t)RtcSettings.pulse_counter[i]*Shutter.direction[i]*2000 / Shutter.max_pwm_frequency)+Shutter.start_position[i]; -} - -void ShutterRelayChanged(void) -{ - - - - - char stemp1[10]; - - for (uint32_t i = 0; i < shutters_present; i++) { - power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; - - uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; - - if (manual_relays_changed) { - - ShutterLimitRealAndTargetPositions(i); - if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE || Shutter.mode == SHT_OFF_ON__OPEN_CLOSE_STEPPER) { - ShutterWaitForMotorStop(i); - switch (powerstate_local) { - case 1: - ShutterStartInit(i, 1, Shutter.open_max[i]); - break; - case 3: - ShutterStartInit(i, -1, 0); - break; - default: - - Shutter.target_position[i] = Shutter.real_position[i]; - } - } else { - if (Shutter.direction[i] != 0 && (!powerstate_local || (powerstate_local && Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE))) { - Shutter.target_position[i] = Shutter.real_position[i]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i+1, Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed); - } else { - last_source = SRC_SHUTTER; - if (powerstate_local == 2) { - - ShutterWaitForMotorStop(i); - ShutterStartInit(i, -1, 0); - } else { - - ShutterWaitForMotorStop(i); - ShutterStartInit(i, 1, Shutter.open_max[i]); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i+1, Shutter.target_position[i], powerstate_local); - } - } - } -} - -bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { - - uint32 min_shutterbutton_hold_timer = -1; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) - min_shutterbutton_hold_timer = Button.hold_timer[i]; - } - return (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1)); -} - -void ShutterButtonHandler(void) -{ - uint8_t buttonState = SHT_NOT_PRESSED; - uint8_t button = XdrvMailbox.payload; - uint8_t press_index; - uint32_t button_index = XdrvMailbox.index; - uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; - - uint16_t loops_per_second = 1000 / Settings.button_debounce; - if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { - if (Settings.flag.button_single) { - buttonState = SHT_PRESSED_MULTI; - press_index = 1; - } else { - if ((Shutter.direction[shutter_index]) && (Button.press_counter[button_index]==0)) { - buttonState = SHT_PRESSED_IMMEDIATE; - press_index = 1; - Button.press_counter[button_index] = 99; - } else { - Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - } - } - blinks = 201; - } - - if (NOT_PRESSED == button) { - Button.hold_timer[button_index] = 0; - } else { - Button.hold_timer[button_index]++; - if (!Settings.flag.button_single) { - if (Settings.param[P_HOLD_IGNORE] > 0) { - if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) { - Button.hold_timer[button_index] = 0; - Button.press_counter[button_index] = 0; - } - } - if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { - - if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { - - for (uint32_t i = 0; i < MAX_KEYS; i++) - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) - Button.press_counter[i] = 99; - press_index = 0; - buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS; - } - if (Button.press_counter[button_index]<99) { - press_index = 0; - buttonState = SHT_PRESSED_HOLD; - } - Button.press_counter[button_index] = 0; - } - if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { - - if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { - - press_index = 0; - buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; - } - } - } - } - - if (!Settings.flag.button_single) { - if (Button.window_timer[button_index]) { - Button.window_timer[button_index]--; - } else { - if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { - if (Button.press_counter[button_index]<99) { - - uint32 min_shutterbutton_press_counter = -1; - for (uint32_t i = 0; i < MAX_KEYS; i++) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter); - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { - min_shutterbutton_press_counter = Button.press_counter[i]; - } - - } - if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:simultanous presss deteced")); - press_index = Button.press_counter[button_index]; - for (uint32_t i = 0; i < MAX_KEYS; i++) - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) - Button.press_counter[i] = 99; - buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS; - } - if ((buttonState != SHT_PRESSED_MULTI_SIMULTANEOUS) && (Button.press_counter[button_index]<99)) { - - press_index = Button.press_counter[button_index]; - buttonState = SHT_PRESSED_MULTI; - } - } - Button.press_counter[button_index] = 0; - } - } - } - - if (buttonState != SHT_NOT_PRESSED) { - if (buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) { - if ((press_index>=5) && (press_index<=7) && (!Settings.flag.button_restrict)) { - - char scmnd[20]; - GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } - } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { - if (!Settings.flag.button_restrict) { - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } - } else if (buttonState <= SHT_PRESSED_IMMEDIATE) { - if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { - uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); - if (pos_press_index>3) pos_press_index=3; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d, button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1); - XdrvMailbox.index = shutter_index +1; - last_source = SRC_BUTTON; - XdrvMailbox.data_len = 0; - char databuf[1] = ""; - XdrvMailbox.data = databuf; - XdrvMailbox.command = NULL; - if (buttonState == SHT_PRESSED_IMMEDIATE) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } else { - uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f; - if (position) { - if (Shutter.direction[shutter_index]) { - XdrvMailbox.payload = XdrvMailbox.index; - CmndShutterStop(); - } else { - XdrvMailbox.payload = position = (position-1)<<1; - CmndShutterPosition(); - if (Settings.shutter_button[button_index] & ((0x01<<26)< 0) && (XdrvMailbox.index <= shutters_present)) { - if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { - if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) { - XdrvMailbox.index = XdrvMailbox.payload; - } - uint32_t i = XdrvMailbox.index -1; - if (Shutter.direction[i] != 0) { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter.direction[i]); - - int32_t temp_realpos = Shutter.start_position[i] + ( (Shutter.time[i]+10) * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i])); - XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i); - - last_source = SRC_WEBGUI; - CmndShutterPosition(); - } else { - if (XdrvMailbox.command) - ResponseCmndDone(); - } - } else { - if (XdrvMailbox.command) - ResponseCmndIdxChar("Locked"); - } - } -} - -void CmndShutterPosition(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) { - uint32_t index = XdrvMailbox.index-1; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, last_source ); - - - - if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) { - - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) { - CmndShutterOpen(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN))) { - CmndShutterClose(); - return; - } - if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN)))) { - XdrvMailbox.payload = -99; - CmndShutterStop(); - return; - } - } - - int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? (XdrvMailbox.payload == -99 ? ShutterRealToPercentPosition(Shutter.real_position[index], index) : 0) : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload); - - target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != last_source)) ? 100 - target_pos_percent : target_pos_percent; - if (XdrvMailbox.payload != -99) { - - Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index); - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent); - } - if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) { - if (Settings.shutter_options[index] & 4) { - if (0 == target_pos_percent) Shutter.target_position[index] -= 1 * 2000; - if (100 == target_pos_percent) Shutter.target_position[index] += 1 * 2000; - } - int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1; - if (Shutter.direction[index] == -new_shutterdirection) { - - if (SHT_PULSE_OPEN__PULSE_CLOSE == Shutter.mode) { - - ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 0 : 1), 1, SRC_SHUTTER); - delay(100); - } else { - if (SHT_OFF_OPEN__OFF_CLOSE == Shutter.mode) { - ExecuteCommandPower(Settings.shutter_startrelay[index] + ((new_shutterdirection == 1) ? 1 : 0), 0, SRC_SHUTTER); - ShutterWaitForMotorStop(index); - } - } - } - if (Shutter.direction[index] != new_shutterdirection) { - if ((SHT_OFF_ON__OPEN_CLOSE == Shutter.mode) || (SHT_OFF_ON__OPEN_CLOSE_STEPPER == Shutter.mode)) { - - ShutterWaitForMotorStop(index); - ExecuteCommandPower(Settings.shutter_startrelay[index], 0, SRC_SHUTTER); - ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - if (Shutter.skip_relay_change == 0) { - - ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); - - ExecuteCommandPower(Settings.shutter_startrelay[index], 1, SRC_SHUTTER); - } - } else { - - AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start in dir %d"), Shutter.direction[index]); - ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]); - if (Shutter.skip_relay_change == 0) { - ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); - } - - } - Shutter.switched_relay = 0; - } - } else { - target_pos_percent = ShutterRealToPercentPosition(Shutter.real_position[index], index); - ShutterReportPosition(true); - } - XdrvMailbox.index = index +1; - if (XdrvMailbox.command) - ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent); - } else { - ShutterReportPosition(true); - if (XdrvMailbox.command) - ResponseCmndIdxChar("Locked"); - } - } -} - -void CmndShutterOpenTime(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - Settings.shutter_opentime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); - ShutterInit(); - } - char time_chr[10]; - dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index -1]) / 10, 1, time_chr); - ResponseCmndIdxChar(time_chr); - } -} - -void CmndShutterCloseTime(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - Settings.shutter_closetime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data)); - ShutterInit(); - } - char time_chr[10]; - dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index -1]) / 10, 1, time_chr); - ResponseCmndIdxChar(time_chr); - } -} - -void CmndShutterMotorDelay(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(steps_per_second * CharToFloat(XdrvMailbox.data)); - ShutterInit(); - } - char time_chr[10]; - dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / steps_per_second, 2, time_chr); - ResponseCmndIdxChar(time_chr); - } -} - -void CmndShutterRelay(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) { - Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; - if (XdrvMailbox.payload > 0) { - Shutter.mask |= 3 << (XdrvMailbox.payload - 1); - } else { - Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1); - } - Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; - ShutterInit(); - - } - ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]); - } -} - -void CmndShutterButton(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) { - uint32_t setting = 0; -# 912 "S:/Development/Tasmota/tasmota/xdrv_27_shutter.ino" - if (XdrvMailbox.data_len > 0) { - uint32_t i = 0; - uint32_t button_index = 0; - bool done = false; - bool isShortCommand = false; - char *str_ptr; - - char data_copy[strlen(XdrvMailbox.data) +1]; - strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); - - for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) { - int field; - if (str[0] == '-') { - field = -1; - } else { - field = atoi(str); - } - switch (i) { - case 0: - if ((field >= -1) && (field<=4)) { - button_index = (field<=0)?(-1):field; - done = (button_index==-1); - } else - done = true; - break; - case 1: - if (!strcmp_P(str, PSTR("up"))) { - setting |= (((100>>1)+1)<<2) | (((50>>1)+1)<<8) | (((75>>1)+1)<<14) | (((100>>1)+1)<<20); - isShortCommand = true; - break; - } else if (!strcmp_P(str, PSTR("down"))) { - setting |= (((0>>1)+1)<<2) | (((50>>1)+1)<<8) | (((25>>1)+1)<<14) | (((0>>1)+1)<<20); - isShortCommand = true; - break; - } else if (!strcmp_P(str, PSTR("updown"))) { - setting |= (((100>>1)+1)<<2) | (((0>>1)+1)<<8) | (((50>>1)+1)<<14); - isShortCommand = true; - break; - } - case 2: - if (isShortCommand) { - if ((field==1) && (setting & (0x3F<<(2+6*3)))) - - setting |= (0x3<<29); - done = true; - break; - } - case 3: - case 4: - if ((field >= -1) && (field<=100)) - setting |= (((field>>1)+1)<<(i*6 + (2-6))); - break; - case 5: - case 6: - case 7: - case 8: - case 9: - if (field==1) - setting |= (1<<(i + (26-5))); - break; - } - if (done) break; - } - - if (button_index) { - if (button_index==-1) { - - for (uint32_t i=0 ; i < MAX_KEYS ; i++) - if ((Settings.shutter_button[i]&0x3) == (XdrvMailbox.index-1)) - Settings.shutter_button[i] = 0; - } else { - if (setting) { - - setting |= (1<<31); - setting |= (XdrvMailbox.index-1) & 0x3; - } - Settings.shutter_button[button_index-1] = setting; - } - } - } - char setting_chr[30*MAX_KEYS] = "-", *setting_chr_ptr = setting_chr; - for (uint32_t i=0 ; i < MAX_KEYS ; i++) { - setting = Settings.shutter_button[i]; - if ((setting&(1<<31)) && ((setting&0x3) == (XdrvMailbox.index-1))) { - if (*setting_chr_ptr == 0) - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR("|")); - setting_chr_ptr += snprintf_P(setting_chr_ptr, 2, PSTR("%d"), i+1); - - for (uint32_t j=0 ; j < 4 ; j++) { - int8_t pos = (((setting>> (2+6*j))&(0x3f))-1)<<1; - if (pos>=0) - setting_chr_ptr += snprintf_P(setting_chr_ptr, 5, PSTR(" %d"), pos); - else - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); - } - for (uint32_t j=0 ; j < 5 ; j++) { - bool mqtt = ((setting>>(26+j))&(0x01)!=0); - if (mqtt) - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" 1")); - else - setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -")); - } - } - } - ResponseCmndIdxChar(setting_chr); - } -} - -void CmndShutterSetHalfway(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Settings.shutter_set50percent[XdrvMailbox.index -1] = (Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload; - ShutterInit(); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]); - } -} - -void CmndShutterFrequency(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) { - Shutter.max_pwm_frequency = XdrvMailbox.payload; - if (shutters_present < 4) { - Settings.shuttercoeff[4][3] = Shutter.max_pwm_frequency; - } - ShutterInit(); - ResponseCmndNumber(XdrvMailbox.payload); - } else { - ResponseCmndNumber(Shutter.max_pwm_frequency); - } -} - -void CmndShutterSetClose(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - Shutter.real_position[XdrvMailbox.index -1] = 0; - ShutterStartInit(XdrvMailbox.index -1, 0, 0); - Settings.shutter_position[XdrvMailbox.index -1] = 0; - ResponseCmndIdxChar(D_CONFIGURATION_RESET); - } -} - -void CmndShutterInvert(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.payload == 0) { - Settings.shutter_options[XdrvMailbox.index -1] &= ~(1); - } else if (XdrvMailbox.payload == 1) { - Settings.shutter_options[XdrvMailbox.index -1] |= (1); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 1 : 0); - } -} - -void CmndShutterCalibration(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.data_len > 0) { - uint32_t i = 0; - char *str_ptr; - - char data_copy[strlen(XdrvMailbox.data) +1]; - strncpy(data_copy, XdrvMailbox.data, sizeof(data_copy)); - - for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < 5; str = strtok_r(nullptr, " ", &str_ptr), i++) { - int field = atoi(str); - - - if ((field <= 0) || (field > 30000) || ( (i>0) && (field <= messwerte[i-1]) ) ) { - break; - } - messwerte[i] = field; - } - for (i = 0; i < 5; i++) { - Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Settings.shuttercoeff: %d, i: %d, value: %d, messwert %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]); - } - ShutterInit(); - ResponseCmndIdxChar(XdrvMailbox.data); - } else { - char setting_chr[30] = "0"; - snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings.shuttercoeff[0][XdrvMailbox.index -1], Settings.shuttercoeff[1][XdrvMailbox.index -1], Settings.shuttercoeff[2][XdrvMailbox.index -1], Settings.shuttercoeff[3][XdrvMailbox.index -1], Settings.shuttercoeff[4][XdrvMailbox.index -1]); - ResponseCmndIdxChar(setting_chr); - } - } -} - -void CmndShutterLock(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.payload == 0) { - Settings.shutter_options[XdrvMailbox.index -1] &= ~(2); - } else if (XdrvMailbox.payload == 1) { - Settings.shutter_options[XdrvMailbox.index -1] |= (2); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 2) ? 1 : 0); - } -} - -void CmndShutterEnableEndStopTime(void) { - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { - if (XdrvMailbox.payload == 0) { - Settings.shutter_options[XdrvMailbox.index -1] &= ~(4); - } else if (XdrvMailbox.payload == 1) { - Settings.shutter_options[XdrvMailbox.index -1] |= (4); - } - ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 4) ? 1 : 0); - } -} - - - - - -bool Xdrv27(uint8_t function) -{ - bool result = false; - - if (Settings.flag3.shutter_mode) { - switch (function) { - case FUNC_PRE_INIT: - ShutterInit(); - break; - case FUNC_EVERY_50_MSECOND: - ShutterUpdatePosition(); - break; - case FUNC_EVERY_SECOND: - - ShutterReportPosition(false); - break; - - case FUNC_COMMAND: - result = DecodeCommand(kShutterCommands, ShutterCommand); - break; - case FUNC_JSON_APPEND: - for (uint8_t i = 0; i < shutters_present; i++) { - uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; - ResponseAppend_P(","); - ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzSensor(DZ_SHUTTER, position); - } -#endif - } - break; - case FUNC_SET_POWER: - char stemp1[10]; - - Shutter.switched_relay = XdrvMailbox.index ^ Shutter.old_power; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), Shutter.switched_relay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); - ShutterRelayChanged(); - Shutter.old_power = XdrvMailbox.index; - break; - case FUNC_SET_DEVICE_POWER: - if (Shutter.skip_relay_change ) { - uint8_t i; - for (i = 0; i < devices_present; i++) { - if (Shutter.switched_relay &1) { - break; - } - Shutter.switched_relay >>= 1; - } - - result = true; - Shutter.skip_relay_change = 0; - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Skipping switch off relay %d"),i); - ExecuteCommandPower(i+1, 0, SRC_SHUTTER); - } - break; - case FUNC_BUTTON_PRESSED: - if (Settings.shutter_button[XdrvMailbox.index] & (1<<31)) { - ShutterButtonHandler(); - result = true; - } - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_28_pcf8574.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_28_pcf8574.ino" -#ifdef USE_I2C -#ifdef USE_PCF8574 - - - - - - - -#define XDRV_28 28 -#define XI2C_02 2 - -#define PCF8574_ADDR1 0x20 -#define PCF8574_ADDR2 0x38 - -struct PCF8574 { - int error; - uint8_t pin[64]; - uint8_t address[MAX_PCF8574]; - uint8_t pin_mask[MAX_PCF8574] = { 0 }; - uint8_t max_connected_ports = 0; - uint8_t max_devices = 0; - char stype[9]; - bool type = false; -} Pcf8574; - -void Pcf8574SwitchRelay(void) -{ - for (uint32_t i = 0; i < devices_present; i++) { - uint8_t relay_state = bitRead(XdrvMailbox.index, i); - - - - if (Pcf8574.max_devices > 0 && Pcf8574.pin[i] < 99) { - uint8_t board = Pcf8574.pin[i]>>3; - uint8_t oldpinmask = Pcf8574.pin_mask[board]; - uint8_t _val = bitRead(rel_inverted, i) ? !relay_state : relay_state; - - - - if (_val) { - Pcf8574.pin_mask[board] |= _val << (Pcf8574.pin[i]&0x7); - } else { - Pcf8574.pin_mask[board] &= ~(1 << (Pcf8574.pin[i]&0x7)); - } - if (oldpinmask != Pcf8574.pin_mask[board]) { - Wire.beginTransmission(Pcf8574.address[board]); - Wire.write(Pcf8574.pin_mask[board]); - Pcf8574.error = Wire.endTransmission(); - } - - } - } -} - -void Pcf8574Init(void) -{ - uint8_t pcf8574_address = PCF8574_ADDR1; - while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +8)) { - - - - if (I2cSetDevice(pcf8574_address)) { - Pcf8574.type = true; - - Pcf8574.address[Pcf8574.max_devices] = pcf8574_address; - Pcf8574.max_devices++; - - strcpy(Pcf8574.stype, "PCF8574"); - if (pcf8574_address >= PCF8574_ADDR2) { - strcpy(Pcf8574.stype, "PCF8574A"); - } - I2cSetActiveFound(pcf8574_address, Pcf8574.stype); - } - - pcf8574_address++; -#ifdef USE_MCP230xx_ADDR - if (USE_MCP230xx_ADDR == pcf8574_address) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Addr: 0x%x reserved for MCP320xx, skipping PCF8574 probe"), pcf8574_address); - pcf8574_address++; - } -#endif - if ((PCF8574_ADDR1 +7) == pcf8574_address) { - pcf8574_address = PCF8574_ADDR2 +1; - } - } - if (Pcf8574.type) { - for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { - Pcf8574.pin[i] = 99; - } - devices_present = devices_present - Pcf8574.max_connected_ports; - Pcf8574.max_connected_ports = 0; - for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PCF: Device %d config 0x%02x"), idx +1, Settings.pcf8574_config[idx]); - - for (uint32_t i = 0; i < 8; i++) { - uint8_t _result = Settings.pcf8574_config[idx] >> i &1; - - if (_result > 0) { - Pcf8574.pin[devices_present] = i + 8 * idx; - bitWrite(rel_inverted, devices_present, Settings.flag3.pcf8574_ports_inverted); - devices_present++; - Pcf8574.max_connected_ports++; - } - } - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("PCF: Total devices %d, PCF8574 output ports %d"), Pcf8574.max_devices, Pcf8574.max_connected_ports); - } -} - - - - - -#ifdef USE_WEBSERVER - -#define WEB_HANDLE_PCF8574 "pcf" - -const char HTTP_BTN_MENU_PCF8574[] PROGMEM = - "

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

" D_INVERT_PORTS "


"; - -const char HTTP_FORM_I2C_PCF8574_2[] PROGMEM = - "" D_DEVICE " %d " D_PORT " %d"; - -void HandlePcf8574(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_PCF8574)); - - if (WebServer->hasArg("save")) { - Pcf8574SaveSettings(); - WebRestart(1); - return; - } - - WSContentStart_P(D_CONFIGURE_PCF8574); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? " checked" : ""); - WSContentSend_P(HTTP_TABLE100); - for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { - for (uint32_t idx2 = 0; idx2 < 8; idx2++) { - uint8_t helper = 1 << idx2; - WSContentSend_P(HTTP_FORM_I2C_PCF8574_2, - idx +1, idx2, - idx2 + 8*idx, - idx2 + 8*idx, - ((helper & Settings.pcf8574_config[idx]) >> idx2 == 0) ? " selected " : " ", - ((helper & Settings.pcf8574_config[idx]) >> idx2 == 1) ? " selected " : " " - ); - } - } - WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void Pcf8574SaveSettings(void) -{ - char stemp[7]; - char tmp[100]; - - - - Settings.flag3.pcf8574_ports_inverted = WebServer->hasArg("b1"); - for (byte idx = 0; idx < Pcf8574.max_devices; idx++) { - byte count=0; - byte n = Settings.pcf8574_config[idx]; - while(n!=0) { - n = n&(n-1); - count++; - } - if (count <= devices_present) { - devices_present = devices_present - count; - } - for (byte i = 0; i < 8; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("i2cs%d"), i+8*idx); - WebGetArg(stemp, tmp, sizeof(tmp)); - byte _value = (!strlen(tmp)) ? 0 : atoi(tmp); - if (_value) { - Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] | 1 << i; - devices_present++; - Pcf8574.max_connected_ports++; - } else { - Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] & ~(1 << i ); - } - } - - - - } -} -#endif - - - - - -bool Xdrv28(uint8_t function) -{ - if (!I2cEnabled(XI2C_02)) { return false; } - - bool result = false; - - if (FUNC_PRE_INIT == function) { - Pcf8574Init(); - } - else if (Pcf8574.type) { - switch (function) { - case FUNC_SET_POWER: - Pcf8574SwitchRelay(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_PCF8574); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_PCF8574, HandlePcf8574); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_29_deepsleep.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_29_deepsleep.ino" -#ifdef USE_DEEPSLEEP -# 31 "S:/Development/Tasmota/tasmota/xdrv_29_deepsleep.ino" -#define XDRV_29 29 - -#define D_PRFX_DEEPSLEEP "DeepSleep" -#define D_CMND_DEEPSLEEP_TIME "Time" - -const uint32_t DEEPSLEEP_MAX = 10 * 366 * 24 * 60 * 60; -const uint32_t DEEPSLEEP_MAX_CYCLE = 60 * 60; -const uint32_t DEEPSLEEP_MIN_TIME = 5; -const uint32_t DEEPSLEEP_START_COUNTDOWN = 4; - -const char kDeepsleepCommands[] PROGMEM = D_PRFX_DEEPSLEEP "|" - D_CMND_DEEPSLEEP_TIME ; - -void (* const DeepsleepCommand[])(void) PROGMEM = { - &CmndDeepsleepTime }; - -uint32_t deepsleep_sleeptime = 0; -uint8_t deepsleep_flag = 0; - -bool DeepSleepEnabled(void) -{ - if ((Settings.deepsleep < 10) || (Settings.deepsleep > DEEPSLEEP_MAX)) { - Settings.deepsleep = 0; - return false; - } - - if (pin[GPIO_DEEPSLEEP] < 99) { - pinMode(pin[GPIO_DEEPSLEEP], INPUT_PULLUP); - return (digitalRead(pin[GPIO_DEEPSLEEP])); - } - - return true; -} - -void DeepSleepReInit(void) -{ - if ((ResetReason() == REASON_DEEP_SLEEP_AWAKE) && DeepSleepEnabled()) { - if ((RtcSettings.ultradeepsleep > DEEPSLEEP_MAX_CYCLE) && (RtcSettings.ultradeepsleep < 1700000000)) { - - RtcSettings.ultradeepsleep = RtcSettings.ultradeepsleep - DEEPSLEEP_MAX_CYCLE; - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Remain DeepSleep %d"), RtcSettings.ultradeepsleep); - RtcSettingsSave(); - RtcRebootReset(); - ESP.deepSleep(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep), WAKE_RF_DEFAULT); - yield(); - - } - } - - RtcSettings.ultradeepsleep = 0; -} - -void DeepSleepPrepare(void) -{ - - - - - if ((RtcSettings.nextwakeup == 0) || - (RtcSettings.deepsleep_slip < 9000) || - (RtcSettings.deepsleep_slip > 11000) || - (RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip ); - RtcSettings.nextwakeup = 0; - RtcSettings.deepsleep_slip = 10000; - } - - - - int16_t timeslip = (int16_t)(RtcSettings.nextwakeup + millis() / 1000 - UtcTime()) * 10; - - - - timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1; - if (timeslip) { - RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5); - - RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000); - RtcSettings.nextwakeup += Settings.deepsleep; - } - - - - if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) { - - RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep; - } - - String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); - - - deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_CYCLE ,RtcSettings.nextwakeup - UtcTime()); - - - Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_STATUS)); - - - -} - -void DeepSleepStart(void) -{ - AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Sleeping")); - - WifiShutdown(); - RtcSettings.ultradeepsleep = RtcSettings.nextwakeup - UtcTime(); - RtcSettingsSave(); - - ESP.deepSleep(100 * RtcSettings.deepsleep_slip * deepsleep_sleeptime); - yield(); -} - -void DeepSleepEverySecond(void) -{ - if (!deepsleep_flag) { return; } - - if (DeepSleepEnabled()) { - if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { - SettingsSaveAll(); - DeepSleepPrepare(); - } - deepsleep_flag--; - if (deepsleep_flag <= 0) { - DeepSleepStart(); - } - } else { - deepsleep_flag = 0; - } -} - - - - - -void CmndDeepsleepTime(void) -{ - if ((0 == XdrvMailbox.payload) || - ((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < DEEPSLEEP_MAX))) { - Settings.deepsleep = XdrvMailbox.payload; - RtcSettings.nextwakeup = 0; - deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN; - if (deepsleep_flag) { - if (!Settings.tele_period) { - Settings.tele_period = TELE_PERIOD; - } - } - } - Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.deepsleep); -} - - - - - -bool Xdrv29(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_SECOND: - DeepSleepEverySecond(); - break; - case FUNC_AFTER_TELEPERIOD: - if (DeepSleepEnabled() && !deepsleep_flag && (Settings.tele_period == 10 || Settings.tele_period == 300 || UpTime() > Settings.tele_period)) { - deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kDeepsleepCommands, DeepsleepCommand); - break; - case FUNC_PRE_INIT: - DeepSleepReInit(); - break; - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" -#ifdef USE_LIGHT -#ifdef USE_EXS_DIMMER - - - - - - - -#define XDRV_30 30 - -#define EXS_GATE_1_ON 0x20 -#define EXS_GATE_1_OFF 0x21 -#define EXS_DIMM_1_ON 0x22 -#define EXS_DIMM_1_OFF 0x23 -#define EXS_DIMM_1_TBL 0x24 -#define EXS_DIMM_1_VAL 0x25 -#define EXS_GATE_2_ON 0x30 -#define EXS_GATE_2_OFF 0x31 -#define EXS_DIMM_2_ON 0x32 -#define EXS_DIMM_2_OFF 0x33 -#define EXS_DIMM_2_TBL 0x34 -#define EXS_DIMM_2_VAL 0x35 -#define EXS_GATES_ON 0x40 -#define EXS_GATES_OFF 0x41 -#define EXS_DIMMS_ON 0x50 -#define EXS_DIMMS_OFF 0x51 -#define EXS_CH_LOCK 0x60 -#define EXS_GET_VALUES 0xFA -#define EXS_WRITE_EE 0xFC -#define EXS_READ_EE 0xFD -#define EXS_GET_VERSION 0xFE -#define EXS_RESET 0xFF - -#define EXS_BUFFER_SIZE 256 -#define EXS_ACK_TIMEOUT 200 - -#include - -TasmotaSerial *ExsSerial = nullptr; - -typedef struct -{ - uint8_t on = 0; - uint8_t bright_tbl = 0; - uint8_t dimm = 0; - uint8_t impuls_start = 0; - uint32_t impuls_len = 0; -} CHANNEL; - -typedef struct -{ - uint8_t version_major = 0; - uint8_t version_minor = 0; - CHANNEL channel[2]; - uint8_t gate_lock = 0; -} DIMMER; - -struct EXS -{ - uint8_t *buffer = nullptr; - int byte_counter = 0; - int cmd_status = 0; - uint8_t power = 0; - uint8_t dimm[2] = {0, 0}; - DIMMER dimmer; -} Exs; - - - - - -uint8_t crc8(const uint8_t *p, uint8_t len) -{ - const uint8_t table[] = { - 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, - 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D}; - - const uint8_t table_rev[] = { - 0x00, 0x70, 0xE0, 0x90, 0xC1, 0xB1, 0x21, 0x51, - 0x83, 0xF3, 0x63, 0x13, 0x42, 0x32, 0xA2, 0xD2}; - - uint8_t offset; - uint8_t temp, crc8_temp; - uint8_t crc8 = 0; - - for (int i = 0; i < len; i++) - { - temp = *(p + i); - offset = temp ^ crc8; - offset >>= 4; - crc8_temp = crc8 & 0x0f; - crc8 = crc8_temp ^ table_rev[offset]; - offset = crc8 ^ temp; - offset &= 0x0f; - crc8_temp = crc8 & 0xf0; - crc8 = crc8_temp ^ table[offset]; - } - return crc8 ^ 0x55; -} - -void ExsSerialSend(const uint8_t data[] = nullptr, uint16_t len = 0) -{ - int retries = 3; - char rc; - -#ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: Tx Packet: \"")); - for (uint32_t i = 0; i < len; i++) - { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, data[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); - AddLog(LOG_LEVEL_DEBUG_MORE); -#endif - - while (retries) - { - retries--; - - ExsSerial->write(data, len); - ExsSerial->flush(); - - - uint32_t snd_time = millis(); - while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && - (!ExsSerial->available())) - ; - - if (!ExsSerial->available()) - { - -#ifdef EXS_DEBUG - AddLog_P(LOG_LEVEL_DEBUG, PSTR("ESX: serial send timeout")); -#endif - continue; - } - - rc = ExsSerial->read(); - if (rc == 0xFF) - break; - } -} - -void ExsSendCmd(uint8_t cmd, uint8_t value) -{ - uint8_t buffer[8]; - uint16_t len; - - buffer[0] = 0x7b; - buffer[3] = cmd; - - switch (cmd) - { - case EXS_GATE_1_ON: - case EXS_GATE_1_OFF: - case EXS_DIMM_1_ON: - case EXS_DIMM_1_OFF: - case EXS_GATE_2_ON: - case EXS_GATE_2_OFF: - case EXS_DIMM_2_ON: - case EXS_DIMM_2_OFF: - case EXS_GATES_ON: - case EXS_GATES_OFF: - case EXS_DIMMS_ON: - case EXS_DIMMS_OFF: - case EXS_GET_VALUES: - case EXS_GET_VERSION: - case EXS_RESET: - buffer[2] = 1; - len = 4; - break; - - case EXS_CH_LOCK: - case EXS_DIMM_1_TBL: - case EXS_DIMM_1_VAL: - case EXS_DIMM_2_TBL: - case EXS_DIMM_2_VAL: - buffer[2] = 2; - buffer[4] = value; - len = 5; - break; - } - buffer[1] = crc8(&buffer[3], buffer[2]); - - ExsSerialSend(buffer, len); -} - -uint8_t ExsSetPower(uint8_t device, uint8_t power) -{ - Exs.dimmer.channel[device].dimm = power; - ExsSendCmd(EXS_DIMM_1_ON + 0x10 * device + power ^ 1, 0); -} - -uint8_t ExsSetBri(uint8_t device, uint8_t bri) -{ - Exs.dimmer.channel[device].bright_tbl = bri; - ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * device, bri); -} - -uint8_t ExsSyncState(uint8_t device) -{ -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Channel %d Power Want %d, Is %d"), - device, bitRead(Exs.power, device), Exs.dimmer.channel[device].dimm); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Set Channel %d Brightness Want %d, Is %d"), - device, Exs.dimm[device], Exs.dimmer.channel[device].bright_tbl); -#endif - - if (bitRead(Exs.power, device) && - Exs.dimm[device] != Exs.dimmer.channel[device].bright_tbl) { - ExsSetBri(device, Exs.dimm[device]); - } - - if (!Exs.dimm[device]) { - Exs.dimmer.channel[device].dimm = 0; - } else if (Exs.dimmer.channel[device].dimm != bitRead(Exs.power, device)) { - ExsSetPower(device, bitRead(Exs.power, device)); - } -} - -bool ExsSyncState() -{ -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Serial %p, Cmd %d"), ExsSerial, Exs.cmd_status); -#endif - - if (!ExsSerial || Exs.cmd_status != 0) - return false; - - ExsSyncState(0); - ExsSyncState(1); -} - -void ExsDebugState() -{ -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: MCU v%d.%d, c0: On:%d,Dim:%d,Tbl:%d(%d%%), c1: On:%d,Dim:%d,Tbl:%d(%d%%), ChLock: %d"), - Exs.dimmer.version_major, Exs.dimmer.version_minor, - Exs.dimmer.channel[0].on, Exs.dimmer.channel[0].dimm, - Exs.dimmer.channel[0].bright_tbl, - changeUIntScale(Exs.dimmer.channel[0].bright_tbl, 0, 255, 0, 100), - Exs.dimmer.channel[1].on, Exs.dimmer.channel[1].dimm, - Exs.dimmer.channel[1].bright_tbl, - changeUIntScale(Exs.dimmer.channel[1].bright_tbl, 0, 255, 0, 100), - Exs.dimmer.gate_lock); -#endif -} - -void ExsPacketProcess(void) -{ - uint8_t len = Exs.buffer[1]; - uint8_t cmd = Exs.buffer[2]; - - switch (cmd) - { - case EXS_GET_VALUES: -# 294 "S:/Development/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" - if (len > 9) - { - Exs.dimmer.version_major = Exs.buffer[3]; - Exs.dimmer.version_minor = Exs.buffer[4]; - - - Exs.dimmer.channel[0].on = Exs.buffer[6]; - Exs.dimmer.channel[0].dimm = Exs.buffer[6]; - Exs.dimmer.channel[0].bright_tbl = Exs.buffer[7]; - - - Exs.dimmer.channel[1].on = Exs.buffer[9]; - Exs.dimmer.channel[1].dimm = Exs.buffer[9]; - Exs.dimmer.channel[1].bright_tbl = Exs.buffer[10]; - - Exs.dimmer.gate_lock = Exs.buffer[11]; - } - else -# 327 "S:/Development/Tasmota/tasmota/xdrv_30_exs_dimmer.ino" - { - Exs.dimmer.version_major = 1; - Exs.dimmer.version_minor = 0; - - - Exs.dimmer.channel[0].on = Exs.buffer[4] - 48; - Exs.dimmer.channel[0].dimm = Exs.buffer[4] - 48; - Exs.dimmer.channel[0].bright_tbl = Exs.buffer[5] - 48; - - - Exs.dimmer.channel[1].on = Exs.buffer[7] - 48; - Exs.dimmer.channel[1].dimm = Exs.buffer[7] - 48; - Exs.dimmer.channel[1].bright_tbl = Exs.buffer[8] - 48; - - Exs.dimmer.gate_lock = Exs.buffer[9] - 48; - } - - ExsDebugState(); - ExsSyncState(); - ExsDebugState(); - break; - default: - break; - } -} - - - -bool ExsModuleSelected(void) -{ - Settings.light_correction = 0; - Settings.flag.mqtt_serial = 0; - Settings.flag3.pwm_multi_channels = 1; - SetSeriallog(LOG_LEVEL_NONE); - - devices_present = +2; - light_type = LT_SERIAL2; - return true; -} - -bool ExsSetChannels(void) -{ -#ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: SetChannels: \"")); - for (int i = 0; i < XdrvMailbox.data_len; i++) - { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, ((uint8_t *)XdrvMailbox.data)[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); - AddLog(LOG_LEVEL_DEBUG_MORE); -#endif - - Exs.dimm[0] = ((uint8_t *)XdrvMailbox.data)[0]; - Exs.dimm[1] = ((uint8_t *)XdrvMailbox.data)[1]; - return ExsSyncState(); -} - -bool ExsSetPower(void) -{ - AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Set Power, Device %d, Power 0x%02x"), - active_device, XdrvMailbox.index); - - Exs.power = XdrvMailbox.index; - return ExsSyncState(); -} - -void EsxMcuStart(void) -{ - int retries = 3; - -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EXS: Request MCU configuration, PIN %d to Low"), pin[GPIO_EXS_ENABLE]); -#endif - - pinMode(pin[GPIO_EXS_ENABLE], OUTPUT); - digitalWrite(pin[GPIO_EXS_ENABLE], LOW); - - delay(1); - - while (ExsSerial->available()) - { - - ExsSerial->read(); - } -} - -void ExsInit(void) -{ -#ifdef EXS_DEBUG - AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Starting Tx %d Rx %d"), pin[GPIO_TXD], pin[GPIO_RXD]); -#endif - - Exs.buffer = (uint8_t *)malloc(EXS_BUFFER_SIZE); - if (Exs.buffer != nullptr) - { - ExsSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); - if (ExsSerial->begin(9600)) - { - if (ExsSerial->hardwareSerial()) - { - ClaimSerial(); - } - ExsSerial->flush(); - EsxMcuStart(); - ExsSendCmd(EXS_CH_LOCK, 0); - ExsSendCmd(EXS_GET_VALUES, 0); - } - } -} - -void ExsSerialInput(void) -{ - while (ExsSerial->available()) - { - yield(); - uint8_t serial_in_byte = ExsSerial->read(); - - AddLog_P2(LOG_LEVEL_INFO, PSTR("EXS: Serial In Byte 0x%02x"), serial_in_byte); - - if (Exs.cmd_status == 0 && - serial_in_byte == 0x7B) - { - Exs.cmd_status = 1; - Exs.byte_counter = 0; - } - else if (Exs.byte_counter >= EXS_BUFFER_SIZE) - { - Exs.cmd_status = 0; - } - else if (Exs.cmd_status == 1) - { - Exs.buffer[Exs.byte_counter++] = serial_in_byte; - - if (Exs.byte_counter > 2 && Exs.byte_counter == Exs.buffer[1] + 2) - { - uint8_t crc = crc8(&Exs.buffer[2], Exs.buffer[1]); - - - Exs.cmd_status = 0; - -#ifdef EXS_DEBUG - snprintf_P(log_data, sizeof(log_data), PSTR("EXS: RX Packet: \"")); - for (uint32_t i = 0; i < Exs.byte_counter; i++) - { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, Exs.buffer[i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s\", CRC: 0x%02x"), log_data, crc); - AddLog(LOG_LEVEL_DEBUG_MORE); -#endif - - if (Exs.buffer[0] == crc) - { - ExsSerial->write(0xFF); - ExsPacketProcess(); - } - else - { - ExsSerial->write(0x00); - } - - } - } - } -} - - - - - -#ifdef EXS_MCU_CMNDS - -#define D_PRFX_EXS "Exs" -#define D_CMND_EXS_DIMM "Dimm" -#define D_CMND_EXS_DIMM_TBL "DimmTbl" -#define D_CMND_EXS_DIMM_VAL "DimmVal" -#define D_CMND_EXS_DIMMS "Dimms" -#define D_CMND_EXS_CH_LOCK "ChLock" -#define D_CMND_EXS_STATE "State" - -const char kExsCommands[] PROGMEM = D_PRFX_EXS "|" - D_CMND_EXS_DIMM "|" D_CMND_EXS_DIMM_TBL "|" D_CMND_EXS_DIMM_VAL "|" - D_CMND_EXS_DIMMS "|" D_CMND_EXS_CH_LOCK "|" - D_CMND_EXS_STATE; - -void (* const ExsCommand[])(void) PROGMEM = { - &CmndExsDimm, &CmndExsDimmTbl, &CmndExsDimmVal, - &CmndExsDimms, &CmndExsChLock, - &CmndExsState }; - -void CmndExsDimm(void) -{ - if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && - (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1)) { - ExsSendCmd(EXS_DIMM_1_ON + 0x10 * (XdrvMailbox.index - 1) + - XdrvMailbox.payload ^ 1, 0); - } - CmndExsState(); -} - -void CmndExsDimmTbl(void) -{ - if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && - (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { - ExsSendCmd(EXS_DIMM_1_TBL + 0x10 * (XdrvMailbox.index - 1), - XdrvMailbox.payload); - } - CmndExsState(); -} - -void CmndExsDimmVal(void) -{ - if ((XdrvMailbox.index == 1 || XdrvMailbox.index == 2) && - (XdrvMailbox.payload > 0 || XdrvMailbox.payload <= 255)) { - ExsSendCmd(EXS_DIMM_1_VAL + 0x10 * (XdrvMailbox.index - 1), - XdrvMailbox.payload); - } - CmndExsState(); -} - -void CmndExsDimms(void) -{ - if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { - ExsSendCmd(EXS_DIMMS_ON + XdrvMailbox.payload ^ 1, 0); - } - CmndExsState(); -} - -void CmndExsChLock(void) -{ - if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1) { - ExsSendCmd(EXS_CH_LOCK, XdrvMailbox.payload); - } - CmndExsState(); -} - -void CmndExsState(void) -{ - ExsSendCmd(EXS_GET_VALUES, 0); - - - uint32_t snd_time = millis(); - while ((TimePassedSince(snd_time) < EXS_ACK_TIMEOUT) && - (!ExsSerial->available())) - ; - ExsSerialInput(); - - Response_P(PSTR("{\"" D_CMND_EXS_STATE "\":{")); - ResponseAppend_P(PSTR("\"McuVersion\":\"%d.%d\"," - "\"Channels\":["), - Exs.dimmer.version_major, Exs.dimmer.version_minor); - - for (uint32_t i = 0; i < 2; i++) { - if (i != 0) { - ResponseAppend_P(PSTR(",")); - } - ResponseAppend_P(PSTR("{\"On\":\"%d\"," - "\"BrightProz\":\"%d\"," - "\"BrightTab\":\"%d\"," - "\"Dimm\":\"%d\"}"), - Exs.dimmer.channel[i].on, - changeUIntScale(Exs.dimmer.channel[i].bright_tbl, 0, 255, 0, 100), - Exs.dimmer.channel[i].bright_tbl, - Exs.dimmer.channel[i].dimm); - } - ResponseAppend_P(PSTR("],")); - ResponseAppend_P(PSTR("\"GateLock\":\"%d\""), Exs.dimmer.gate_lock); - ResponseJsonEndEnd(); -} - -#endif - - - - - -bool Xdrv30(uint8_t function) -{ - bool result = false; - - if (EXS_DIMMER == my_module_type) - { - switch (function) - { - case FUNC_LOOP: - if (ExsSerial) - ExsSerialInput(); - break; - case FUNC_MODULE_INIT: - result = ExsModuleSelected(); - break; - case FUNC_INIT: - ExsInit(); - break; - case FUNC_SET_DEVICE_POWER: - result = ExsSetPower(); - break; - case FUNC_SET_CHANNELS: - result = ExsSetChannels(); - break; -#ifdef EXS_MCU_CMNDS - case FUNC_COMMAND: - result = DecodeCommand(kExsCommands, ExsCommand); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_31_tasmota_slave.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_31_tasmota_slave.ino" -#ifdef USE_TASMOTA_SLAVE - - - - -#define XDRV_31 31 - -#define CONST_STK_CRC_EOP 0x20 - -#define CMND_STK_GET_SYNC 0x30 -#define CMND_STK_SET_DEVICE 0x42 -#define CMND_STK_SET_DEVICE_EXT 0x45 -#define CMND_STK_ENTER_PROGMODE 0x50 -#define CMND_STK_LEAVE_PROGMODE 0x51 -#define CMND_STK_LOAD_ADDRESS 0x55 -#define CMND_STK_PROG_PAGE 0x64 - - - - - -#define CMND_START 0xFC -#define CMND_END 0xFD - -#define CMND_FEATURES 0x01 -#define CMND_JSON 0x02 -#define CMND_FUNC_EVERY_SECOND 0x03 -#define CMND_FUNC_EVERY_100_MSECOND 0x04 -#define CMND_SLAVE_SEND 0x05 -#define CMND_PUBLISH_TELE 0x06 -#define CMND_EXECUTE_CMND 0x07 - -#define PARAM_DATA_START 0xFE -#define PARAM_DATA_END 0xFF - -#include - - - - - -class SimpleHexParse { - public: - SimpleHexParse(void); - uint8_t parseLine(char *hexline); - uint8_t ptr_l = 0; - uint8_t ptr_h = 0; - bool PageIsReady = false; - bool firstrun = true; - bool EndOfFile = false; - uint8_t FlashPage[128]; - uint8_t FlashPageIdx = 0; - uint8_t layoverBuffer[16]; - uint8_t layoverIdx = 0; - uint8_t getByte(char *hexline, uint8_t idx); -}; - -SimpleHexParse::SimpleHexParse(void) -{ - -} - -uint8_t SimpleHexParse::parseLine(char *hexline) -{ - if (layoverIdx) { - memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx); - FlashPageIdx = layoverIdx; - layoverIdx = 0; - } - uint8_t len = getByte(hexline, 1); - uint8_t addr_h = getByte(hexline, 2); - uint8_t addr_l = getByte(hexline, 3); - uint8_t rectype = getByte(hexline, 4); - for (uint8_t idx = 0; idx < len; idx++) { - if (FlashPageIdx < 128) { - FlashPage[FlashPageIdx] = getByte(hexline, idx+5); - FlashPageIdx++; - } else { - layoverBuffer[layoverIdx] = getByte(hexline, idx+5); - layoverIdx++; - } - } - if (1 == rectype) { - EndOfFile = true; - while (FlashPageIdx < 128) { - FlashPage[FlashPageIdx] = 0xFF; - FlashPageIdx++; - } - } - if (FlashPageIdx == 128) { - if (firstrun) { - firstrun = false; - } else { - ptr_l += 0x40; - if (ptr_l == 0) { - ptr_l = 0; - ptr_h++; - } - } - firstrun = false; - PageIsReady = true; - } - return 0; -} - -uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) -{ - char buff[3]; - buff[3] = '\0'; - memcpy(&buff, &hexline[(idx*2)-1], 2); - return strtol(buff, 0, 16); -} - - - - - -struct TSLAVE { - uint32_t spi_hex_size = 0; - uint32_t spi_sector_counter = 0; - uint8_t spi_sector_cursor = 0; - uint8_t inverted = LOW; - bool type = false; - bool flashing = false; - bool SerialEnabled = false; - uint8_t waitstate = 0; - bool unsupported = false; -} TSlave; - -typedef union { - uint32_t data; - struct { - uint32_t func_json_append : 1; - uint32_t func_every_second : 1; - uint32_t func_every_100_msecond : 1; - uint32_t func_slave_send : 1; - uint32_t spare4 : 1; - uint32_t spare5 : 1; - uint32_t spare6 : 1; - uint32_t spare7 : 1; - uint32_t spare8 : 1; - uint32_t spare9 : 1; - uint32_t spare10 : 1; - uint32_t spare11 : 1; - uint32_t spare12 : 1; - uint32_t spare13 : 1; - uint32_t spare14 : 1; - uint32_t spare15 : 1; - uint32_t spare16 : 1; - uint32_t spare17 : 1; - uint32_t spare18 : 1; - uint32_t spare19 : 1; - uint32_t spare20 : 1; - uint32_t spare21 : 1; - uint32_t spare22 : 1; - uint32_t spare23 : 1; - uint32_t spare24 : 1; - uint32_t spare25 : 1; - uint32_t spare26 : 1; - uint32_t spare27 : 1; - uint32_t spare28 : 1; - uint32_t spare29 : 1; - uint32_t spare30 : 1; - uint32_t spare31 : 1; - }; -} TSlaveFeatureCfg; - - - - - - -struct TSLAVE_FEATURES { - uint32_t features_version; - TSlaveFeatureCfg features; -} TSlaveSettings; - -struct TSLAVE_COMMAND { - uint8_t command; - uint8_t parameter; - uint8_t unused2; - uint8_t unused3; -} TSlaveCommand; - -TasmotaSerial *TasmotaSlave_Serial; - -uint32_t TasmotaSlave_FlashStart(void) -{ - return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; -} - -uint8_t TasmotaSlave_UpdateInit(void) -{ - TSlave.spi_hex_size = 0; - TSlave.spi_sector_counter = TasmotaSlave_FlashStart(); - TSlave.spi_sector_cursor = 0; - return 0; -} - -void TasmotaSlave_Reset(void) -{ - if (TSlave.SerialEnabled) { - digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); - delay(1); - digitalWrite(pin[GPIO_TASMOTASLAVE_RST], TSlave.inverted); - delay(1); - digitalWrite(pin[GPIO_TASMOTASLAVE_RST], !TSlave.inverted); - delay(5); - } -} - -uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout) -{ - int timer = 0; - while (timer < timeout) { - if (TasmotaSlave_Serial->available() >= dataCount) { - return 1; - } - delay(1); - timer++; - } - return 0; -} - -uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count) -{ - TasmotaSlave_Serial->write(bytes, count); - TasmotaSlave_waitForSerialData(2, 250); - uint8_t sync = TasmotaSlave_Serial->read(); - uint8_t ok = TasmotaSlave_Serial->read(); - if ((sync == 0x14) && (ok == 0x10)) { - return 1; - } - return 0; -} - -uint8_t TasmotaSlave_execCmd(uint8_t cmd) -{ - uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP }; - return TasmotaSlave_sendBytes(bytes, 2); -} - -uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count) -{ - uint8_t bytes[32]; - bytes[0] = cmd; - int i = 0; - while (i < count) { - bytes[i + 1] = params[i]; - i++; - } - bytes[i + 1] = CONST_STK_CRC_EOP; - return TasmotaSlave_sendBytes(bytes, i + 2); -} - -uint8_t TasmotaSlave_exitProgMode(void) -{ - return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); -} - -uint8_t TasmotaSlave_SetupFlash(void) -{ - uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00}; - uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00}; - TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_FLASH_SPEED); - if (TasmotaSlave_Serial->hardwareSerial()) { - ClaimSerial(); - } - - TasmotaSlave_Reset(); - - uint8_t timeout = 0; - uint8_t no_error = 0; - while (50 > timeout) { - if (TasmotaSlave_execCmd(CMND_STK_GET_SYNC)) { - timeout = 200; - no_error = 1; - } - timeout++; - delay(1); - } - if (no_error) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Found bootloader")); - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Bootloader could not be found")); - } - if (no_error) { - if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (1)")); - } - } - if (no_error) { - if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (2)")); - } - } - if (no_error) { - if (TasmotaSlave_execCmd(CMND_STK_ENTER_PROGMODE)) { - } else { - no_error = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Failed to put bootloader into programming mode")); - } - } - return no_error; -} - -uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo) -{ - uint8_t params[] = { adrLo, adrHi }; - return TasmotaSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params)); -} - -void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) -{ - uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46}; - TasmotaSlave_loadAddress(addr_h, addr_l); - TasmotaSlave_Serial->write(Header, 4); - for (int i = 0; i < 128; i++) { - TasmotaSlave_Serial->write(data[i]); - } - TasmotaSlave_Serial->write(CONST_STK_CRC_EOP); - TasmotaSlave_waitForSerialData(2, 250); - TasmotaSlave_Serial->read(); - TasmotaSlave_Serial->read(); -} - -void TasmotaSlave_Flash(void) -{ - bool reading = true; - uint32_t read = 0; - uint32_t processed = 0; - char thishexline[50]; - uint8_t position = 0; - char* flash_buffer; - - SimpleHexParse hexParse = SimpleHexParse(); - - if (!TasmotaSlave_SetupFlash()) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flashing aborted!")); - TSlave.flashing = false; - restart_flag = 2; - return; - } - - flash_buffer = new char[SPI_FLASH_SEC_SIZE]; - uint32_t flash_start = TasmotaSlave_FlashStart() * SPI_FLASH_SEC_SIZE; - while (reading) { - ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE); - read = read + SPI_FLASH_SEC_SIZE; - if (read >= TSlave.spi_hex_size) { - reading = false; - } - for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) { - processed++; - if ((processed <= TSlave.spi_hex_size) && (!hexParse.EndOfFile)) { - if (':' == flash_buffer[ca]) { - position = 0; - } - if (0x0D == flash_buffer[ca]) { - thishexline[position] = 0; - hexParse.parseLine(thishexline); - if (hexParse.PageIsReady) { - TasmotaSlave_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage); - hexParse.PageIsReady = false; - hexParse.FlashPageIdx = 0; - } - } else { - if (0x0A != flash_buffer[ca]) { - thishexline[position] = flash_buffer[ca]; - position++; - } - } - } - } - } - TasmotaSlave_exitProgMode(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flash done!")); - TSlave.flashing = false; - restart_flag = 2; -} - -void TasmotaSlave_SetFlagFlashing(bool value) -{ - TSlave.flashing = value; -} - -bool TasmotaSlave_GetFlagFlashing(void) -{ - return TSlave.flashing; -} - -void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size) -{ - if (0 == TSlave.spi_sector_cursor) { - ESP.flashEraseSector(TSlave.spi_sector_counter); - } - TSlave.spi_sector_cursor++; - ESP.flashWrite((TSlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TSlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size); - TSlave.spi_hex_size = TSlave.spi_hex_size + size; - if (2 == TSlave.spi_sector_cursor) { - TSlave.spi_sector_cursor = 0; - TSlave.spi_sector_counter++; - } -} - -void TasmotaSlave_Init(void) -{ - if (TSlave.type) { - return; - } - if (10 > TSlave.waitstate) { - TSlave.waitstate++; - return; - } - if (!TSlave.SerialEnabled) { - if ((pin[GPIO_TASMOTASLAVE_RXD] < 99) && (pin[GPIO_TASMOTASLAVE_TXD] < 99) && - ((pin[GPIO_TASMOTASLAVE_RST] < 99) || (pin[GPIO_TASMOTASLAVE_RST_INV] < 99))) { - TasmotaSlave_Serial = new TasmotaSerial(pin[GPIO_TASMOTASLAVE_RXD], pin[GPIO_TASMOTASLAVE_TXD], 1, 0, 200); - if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) { - if (TasmotaSlave_Serial->hardwareSerial()) { - ClaimSerial(); - } - TasmotaSlave_Serial->setTimeout(50); - if (pin[GPIO_TASMOTASLAVE_RST_INV] < 99) { - pin[GPIO_TASMOTASLAVE_RST] = pin[GPIO_TASMOTASLAVE_RST_INV]; - pin[GPIO_TASMOTASLAVE_RST_INV] = 99; - TSlave.inverted = HIGH; - } - pinMode(pin[GPIO_TASMOTASLAVE_RST], OUTPUT); - TSlave.SerialEnabled = true; - TasmotaSlave_Reset(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Enabled")); - } - } - } - if (TSlave.SerialEnabled) { - TasmotaSlave_sendCmnd(CMND_FEATURES, 0); - char buffer[32]; - TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)); - uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)); - memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings)); - if (20191129 == TSlaveSettings.features_version) { - TSlave.type = true; - AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version); - } else { - if ((!TSlave.unsupported) && (TSlaveSettings.features_version > 0)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u not supported!"), TSlaveSettings.features_version); - TSlave.unsupported = true; - } - } - } -} - -void TasmotaSlave_Show(void) -{ - if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { - char buffer[100]; - TasmotaSlave_sendCmnd(CMND_JSON, 0); - TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1); - uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1); - buffer[len] = '\0'; - ResponseAppend_P(PSTR(",\"TasmotaSlave\":%s"), buffer); - } -} - -void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param) -{ - TSlaveCommand.command = cmnd; - TSlaveCommand.parameter = param; - char buffer[sizeof(TSlaveCommand)+2]; - buffer[0] = CMND_START; - memcpy(&buffer[1], &TSlaveCommand, sizeof(TSlaveCommand)); - buffer[sizeof(TSlaveCommand)+1] = CMND_END; - for (uint8_t ca = 0; ca < sizeof(buffer); ca++) { - TasmotaSlave_Serial->write(buffer[ca]); - } -} - -#define D_PRFX_SLAVE "Slave" -#define D_CMND_SLAVE_RESET "Reset" -#define D_CMND_SLAVE_SEND "Send" - -const char kTasmotaSlaveCommands[] PROGMEM = D_PRFX_SLAVE "|" - D_CMND_SLAVE_RESET "|" D_CMND_SLAVE_SEND; - -void (* const TasmotaSlaveCommand[])(void) PROGMEM = { - &CmndTasmotaSlaveReset, &CmndTasmotaSlaveSend }; - -void CmndTasmotaSlaveReset(void) -{ - TasmotaSlave_Reset(); - TSlave.type = false; - TSlave.waitstate = 7; - TSlave.unsupported = false; - ResponseCmndDone(); -} - -void CmndTasmotaSlaveSend(void) -{ - if (0 < XdrvMailbox.data_len) { - TasmotaSlave_sendCmnd(CMND_SLAVE_SEND, XdrvMailbox.data_len); - TasmotaSlave_Serial->write(char(PARAM_DATA_START)); - for (uint8_t idx = 0; idx < XdrvMailbox.data_len; idx++) { - TasmotaSlave_Serial->write(XdrvMailbox.data[idx]); - } - TasmotaSlave_Serial->write(char(PARAM_DATA_END)); - } - ResponseCmndDone(); -} - -void TasmotaSlave_ProcessIn(void) -{ - uint8_t cmnd = TasmotaSlave_Serial->read(); - switch (cmnd) { - case CMND_START: - TasmotaSlave_waitForSerialData(sizeof(TSlaveCommand),50); - uint8_t buffer[sizeof(TSlaveCommand)]; - for (uint8_t idx = 0; idx < sizeof(TSlaveCommand); idx++) { - buffer[idx] = TasmotaSlave_Serial->read(); - } - TasmotaSlave_Serial->read(); - memcpy(&TSlaveCommand, &buffer, sizeof(TSlaveCommand)); - char inbuf[TSlaveCommand.parameter+1]; - TasmotaSlave_waitForSerialData(TSlaveCommand.parameter, 50); - TasmotaSlave_Serial->read(); - for (uint8_t idx = 0; idx < TSlaveCommand.parameter; idx++) { - inbuf[idx] = TasmotaSlave_Serial->read(); - } - TasmotaSlave_Serial->read(); - inbuf[TSlaveCommand.parameter] = '\0'; - - if (CMND_PUBLISH_TELE == TSlaveCommand.command) { - Response_P(PSTR("{\"TasmotaSlave\":")); - ResponseAppend_P("%s", inbuf); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - XdrvRulesProcess(); - } - if (CMND_EXECUTE_CMND == TSlaveCommand.command) { - ExecuteCommand(inbuf, SRC_IGNORE); - } - break; - default: - break; - } -} - - - - - - -bool Xdrv31(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_100_MSECOND: - if (TSlave.type) { - if (TasmotaSlave_Serial->available()) { - TasmotaSlave_ProcessIn(); - } - if (TSlaveSettings.features.func_every_100_msecond) { - TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0); - } - } - break; - case FUNC_EVERY_SECOND: - if ((TSlave.type) && (TSlaveSettings.features.func_every_second)) { - TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_SECOND, 0); - } - TasmotaSlave_Init(); - break; - case FUNC_JSON_APPEND: - if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) { - TasmotaSlave_Show(); - } - break; - case FUNC_COMMAND: - result = DecodeCommand(kTasmotaSlaveCommands, TasmotaSlaveCommand); - break; - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_32_hotplug.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_32_hotplug.ino" -#ifdef USE_HOTPLUG - - - - - - - -#define XDRV_32 32 - -const uint32_t HOTPLUG_MAX = 254; - -const char kHotPlugCommands[] PROGMEM = "|" - D_CMND_HOTPLUG; - -void (* const HotPlugCommand[])(void) PROGMEM = { - &CmndHotPlugTime }; - -struct { - - bool enabled = false; - uint8_t timeout = 0; -} Hotplug; - -void HotPlugInit(void) -{ - - if (Settings.hotplug_scan == 0xFF) { Settings.hotplug_scan = 0; } - if (Settings.hotplug_scan != 0) { - Hotplug.enabled = true; - Hotplug.timeout = 1; - } else - Hotplug.enabled = false; -} - -void HotPlugEverySecond(void) -{ - if (Hotplug.enabled) { - if (Hotplug.timeout == 0) { - XsnsCall(FUNC_HOTPLUG_SCAN); - Hotplug.timeout = Settings.hotplug_scan; - } - Hotplug.timeout--; - } -} - - - - - -void CmndHotPlugTime(void) -{ - if (XdrvMailbox.payload <= HOTPLUG_MAX) { - Settings.hotplug_scan = XdrvMailbox.payload; - HotPlugInit(); - } - ResponseCmndNumber(Settings.hotplug_scan); -} - - - - - -bool Xdrv32(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_SECOND: - HotPlugEverySecond(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kHotPlugCommands, HotPlugCommand); - break; - case FUNC_PRE_INIT: - HotPlugInit(); - break; - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_33_nrf24l01.ino" -# 30 "S:/Development/Tasmota/tasmota/xdrv_33_nrf24l01.ino" -#ifdef USE_SPI -#ifdef USE_NRF24 - - - - - - - -#define XDRV_33 33 - -#define MOSI 13 -#define MISO 12 -#define SCK 14 - -#include -#include - -const char NRF24type[] PROGMEM = "NRF24"; - -const char HTTP_NRF24[] PROGMEM = - "{s}%sL01%c: " "{m}started{e}"; - -struct { - uint8_t chipType = 0; -} NRF24; - - - -RF24 NRF24radio; - -bool NRF24initRadio() -{ - NRF24radio.begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_DC]); - NRF24radio.powerUp(); - - if(NRF24radio.isChipConnected()){ - DEBUG_DRIVER_LOG(PSTR("NRF24 chip connected")); - return true; - } - DEBUG_DRIVER_LOG(PSTR("NRF24 chip NOT !!!! connected")); - return false; -} - -bool NRF24Detect(void) -{ - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_DC]<99)){ - SPI.pins(SCK,MOSI,MISO,-1); - if(NRF24initRadio()){ - NRF24.chipType = 32; - AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01 initialized")); - if(NRF24radio.isPVariant()){ - NRF24.chipType = 43; - AddLog_P2(LOG_LEVEL_INFO,PSTR("NRF24L01+ detected")); - } - return true; - } - } - return false; -} - - - - - -bool Xdrv33(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - result = NRF24Detect(); - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" -#ifdef USE_I2C -#ifdef USE_WEMOS_MOTOR_V1 -# 45 "S:/Development/Tasmota/tasmota/xdrv_34_wemos_motor_v1.ino" -#define XDRV_34 34 -#define XI2C_44 44 - -#ifndef WEMOS_MOTOR_V1_ADDR -#define WEMOS_MOTOR_V1_ADDR 0x30 -#endif -#ifndef WEMOS_MOTOR_V1_FREQ -#define WEMOS_MOTOR_V1_FREQ 1000 -#endif - -#define MOTOR_A 0 -#define MOTOR_B 1 - -#define SHORT_BRAKE 0 -#define CCW 1 -#define CW 2 -#define STOP 3 -#define STANDBY 4 - -struct WMOTORV1 { - bool detected = false; - uint8_t motor; -} WMotorV1; - -void WMotorV1Detect(void) -{ - if (I2cSetDevice(WEMOS_MOTOR_V1_ADDR)) { - WMotorV1.detected = true; - I2cSetActiveFound(WEMOS_MOTOR_V1_ADDR, "WEMOS_MOTOR_V1"); - WMotorV1Reset(); - } -} - -void WMotorV1Reset(void) -{ - - WMotorV1SetFrequency(WEMOS_MOTOR_V1_FREQ); -} - -void WMotorV1SetFrequency(uint32_t freq) -{ - Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); - Wire.write(((byte)(freq >> 16)) & (byte)0x0f); - Wire.write((byte)(freq >> 16)); - Wire.write((byte)(freq >> 8)); - Wire.write((byte)freq); - Wire.endTransmission(); - -} - -void WMotorV1SetMotor(uint8_t motor, uint8_t dir, float pwm_val) -{ - Wire.beginTransmission(WEMOS_MOTOR_V1_ADDR); - Wire.write(motor | (byte)0x10); - Wire.write(dir); - - uint16_t _pwm_val = uint16_t(pwm_val * 100); - if (_pwm_val > 10000) { - _pwm_val = 10000; - } - - Wire.write((byte)(_pwm_val >> 8)); - Wire.write((byte)_pwm_val); - Wire.endTransmission(); - -} - -bool WMotorV1Command(void) -{ - uint8_t args_count = 0; - - if (XdrvMailbox.data_len > 0) { - args_count = 1; - } else { - return false; - } - - for (uint32_t idx = 0; idx < XdrvMailbox.data_len; idx++) { - if (' ' == XdrvMailbox.data[idx]) { - XdrvMailbox.data[idx] = ','; - } - if (',' == XdrvMailbox.data[idx]) { - args_count++; - } - } - UpperCase(XdrvMailbox.data, XdrvMailbox.data); - - char *command = strtok(XdrvMailbox.data, ","); - - if (strcmp(command, "RESET") == 0) { - WMotorV1Reset(); - Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"RESET\":\"OK\"}}")); - return true; - } - - if (strcmp(command, "SETMOTOR") == 0) { - if (args_count >= 3) { - - int motor = atoi(strtok(NULL, ",")); - int dir = atoi(strtok(NULL, ",")); - int duty = 100; - if (args_count == 4) { - duty = atoi(strtok(NULL, ",")); - } - - WMotorV1SetMotor(motor, dir, duty); - Response_P(PSTR("{\"WEMOS_MOTOR_V1\":{\"SETMOTOR\":\"OK\"}}")); - return true; - } - } - return false; -} - - - - - -bool Xdrv34(uint8_t function) -{ - if (!I2cEnabled(XI2C_44)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - WMotorV1Detect(); - } - else if (WMotorV1.detected) { - switch (function) { - case FUNC_COMMAND_DRIVER: - if (XI2C_44 == XdrvMailbox.index) { - result = WMotorV1Command(); - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" -# 22 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" -#ifdef DEBUG_THEO -#ifndef USE_DEBUG_DRIVER -#define USE_DEBUG_DRIVER -#endif -#endif - -#ifdef USE_DEBUG_DRIVER - - - - - - -#define XDRV_99 99 - -#ifndef CPU_LOAD_CHECK -#define CPU_LOAD_CHECK 1 -#endif - - - - - -#define D_CMND_CFGDUMP "CfgDump" -#define D_CMND_CFGPEEK "CfgPeek" -#define D_CMND_CFGPOKE "CfgPoke" -#define D_CMND_CFGSHOW "CfgShow" -#define D_CMND_CFGXOR "CfgXor" -#define D_CMND_CPUCHECK "CpuChk" -#define D_CMND_EXCEPTION "Exception" -#define D_CMND_FLASHDUMP "FlashDump" -#define D_CMND_FLASHMODE "FlashMode" -#define D_CMND_FREEMEM "FreeMem" -#define D_CMND_HELP "Help" -#define D_CMND_RTCDUMP "RtcDump" -#define D_CMND_SETSENSOR "SetSensor" -#define D_CMND_I2CWRITE "I2CWrite" -#define D_CMND_I2CREAD "I2CRead" -#define D_CMND_I2CSTRETCH "I2CStretch" -#define D_CMND_I2CCLOCK "I2CClock" - -const char kDebugCommands[] PROGMEM = "|" - D_CMND_CFGDUMP "|" D_CMND_CFGPEEK "|" D_CMND_CFGPOKE "|" -#ifdef USE_WEBSERVER - D_CMND_CFGXOR "|" -#endif - D_CMND_CPUCHECK "|" -#ifdef DEBUG_THEO - D_CMND_EXCEPTION "|" -#endif - D_CMND_FLASHDUMP "|" D_CMND_FLASHMODE "|" D_CMND_FREEMEM"|" D_CMND_HELP "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|" -#ifdef USE_I2C - D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK -#endif - ; - -void (* const DebugCommand[])(void) PROGMEM = { - &CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke, -#ifdef USE_WEBSERVER - &CmndCfgXor, -#endif - &CmndCpuCheck, -#ifdef DEBUG_THEO - &CmndException, -#endif - &CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor, -#ifdef USE_I2C - &CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock -#endif - }; - -uint32_t CPU_loops = 0; -uint32_t CPU_last_millis = 0; -uint32_t CPU_last_loop_time = 0; -uint8_t CPU_load_check = 0; -uint8_t CPU_show_freemem = 0; - - - -#ifdef DEBUG_THEO -void ExceptionTest(uint8_t type) -{ -# 145 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" - if (1 == type) { - char svalue[10]; - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), 7); - } -# 159 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" - if (2 == type) { - while(1) delay(1000); - } -} - -#endif - - - -void CpuLoadLoop(void) -{ - CPU_last_loop_time = millis(); - if (CPU_load_check && CPU_last_millis) { - CPU_loops ++; - if ((CPU_last_millis + (CPU_load_check *1000)) <= CPU_last_loop_time) { -#if defined(F_CPU) && (F_CPU == 160000000L) - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *800) ); - CPU_loops = CPU_loops / CPU_load_check; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(160MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); -#else - int CPU_load = 100 - ( (CPU_loops*(1 + 30*sleep)) / (CPU_load_check *400) ); - CPU_loops = CPU_loops / CPU_load_check; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, CPU %d%%(80MHz), Loops/sec %d"), ESP.getFreeHeap(), CPU_load, CPU_loops); -#endif - CPU_last_millis = CPU_last_loop_time; - CPU_loops = 0; - } - } -} - - - -#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) - - - -extern "C" { -#include - extern cont_t g_cont; -} - -void DebugFreeMem(void) -{ - register uint32_t *sp asm("a1"); - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_cont.stack), XdrvMailbox.data); -} - -#else - - - - -extern "C" { -#include - extern cont_t* g_pcont; -} - -void DebugFreeMem(void) -{ - register uint32_t *sp asm("a1"); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "FreeRam %d, FreeStack %d (%s)"), ESP.getFreeHeap(), 4 * (sp - g_pcont->stack), XdrvMailbox.data); -} - -#endif - - - -void DebugRtcDump(char* parms) -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; -# 246 "S:/Development/Tasmota/tasmota/xdrv_99_debug.ino" - uint8_t buffer[768]; - - system_rtc_mem_read(0, (uint32_t*)&buffer, sizeof(buffer)); - - maxrow = ((sizeof(buffer)+CFG_COLS)/CFG_COLS); - - uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; - uint16_t mrow = strtol(p, &p, 10); - - - - if (0 == mrow) { - mrow = 8; - } - if (srow > maxrow) { - srow = maxrow - mrow; - } - if (mrow < (maxrow - srow)) { - maxrow = srow + mrow; - } - - for (row = srow; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { - - - - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); - AddLog(LOG_LEVEL_INFO); - } -} - - - -void DebugCfgDump(char* parms) -{ - #define CFG_COLS 16 - - uint16_t idx; - uint16_t maxrow; - uint16_t row; - uint16_t col; - char *p; - - uint8_t *buffer = (uint8_t *) &Settings; - maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); - - uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; - uint16_t mrow = strtol(p, &p, 10); - - - - if (0 == mrow) { - mrow = 8; - } - if (srow > maxrow) { - srow = maxrow - mrow; - } - if (mrow < (maxrow - srow)) { - maxrow = srow + mrow; - } - - for (row = srow; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s "), log_data); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[idx + col]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (col = 0; col < CFG_COLS; col++) { - - - - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s|"), log_data); - AddLog(LOG_LEVEL_INFO); - delay(1); - } -} - -void DebugCfgPeek(char* parms) -{ - char *p; - - uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; - address = (address >> 2) << 2; - - uint8_t *buffer = (uint8_t *) &Settings; - uint8_t data8 = buffer[address]; - uint16_t data16 = (buffer[address +1] << 8) + buffer[address]; - uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16; - - snprintf_P(log_data, sizeof(log_data), PSTR("%03X:"), address); - for (uint32_t i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s %02X"), log_data, buffer[address +i]); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s |"), log_data); - for (uint32_t i = 0; i < 4; i++) { - snprintf_P(log_data, sizeof(log_data), PSTR("%s%c"), log_data, ((buffer[address +i] > 0x20) && (buffer[address +i] < 0x7F)) ? (char)buffer[address +i] : ' '); - } - snprintf_P(log_data, sizeof(log_data), PSTR("%s| 0x%02X (%d), 0x%04X (%d), 0x%0LX (%lu)"), log_data, data8, data8, data16, data16, data32, data32); - AddLog(LOG_LEVEL_INFO); -} - -void DebugCfgPoke(char* parms) -{ - char *p; - - uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; - address = (address >> 2) << 2; - - uint32_t data = strtol(p, &p, 16); - - uint8_t *buffer = (uint8_t *) &Settings; - uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - - uint8_t *nbuffer = (uint8_t *) &data; - for (uint32_t i = 0; i < 4; i++) { buffer[address +i] = nbuffer[+i]; } - - uint32_t ndata32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address]; - - AddLog_P2(LOG_LEVEL_INFO, PSTR("%03X: 0x%0LX (%lu) poked to 0x%0LX (%lu)"), address, data32, data32, ndata32, ndata32); -} - -void SetFlashMode(uint8_t mode) -{ - uint8_t *_buffer; - uint32_t address; - - address = 0; - _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - - if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) { - if (_buffer[2] != mode) { - _buffer[2] = mode; - if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) { - ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); - } - } - } - delete[] _buffer; -} - - - - - -void CmndHelp(void) -{ - AddLog_P(LOG_LEVEL_INFO, PSTR("HLP: "), kDebugCommands); - ResponseCmndDone(); -} - -void CmndRtcDump(void) -{ - DebugRtcDump(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgDump(void) -{ - DebugCfgDump(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgPeek(void) -{ - DebugCfgPeek(XdrvMailbox.data); - ResponseCmndDone(); -} - -void CmndCfgPoke(void) -{ - DebugCfgPoke(XdrvMailbox.data); - ResponseCmndDone(); -} - -#ifdef USE_WEBSERVER -void CmndCfgXor(void) -{ - if (XdrvMailbox.data_len > 0) { - Web.config_xor_on_set = XdrvMailbox.payload; - } - ResponseCmndNumber(Web.config_xor_on_set); -} -#endif - -#ifdef DEBUG_THEO -void CmndException(void) -{ - if (XdrvMailbox.data_len > 0) { ExceptionTest(XdrvMailbox.payload); } - ResponseCmndDone(); -} -#endif - -void CmndCpuCheck(void) -{ - if (XdrvMailbox.data_len > 0) { - CPU_load_check = XdrvMailbox.payload; - CPU_last_millis = CPU_last_loop_time; - } - ResponseCmndNumber(CPU_load_check); -} - -void CmndFreemem(void) -{ - if (XdrvMailbox.data_len > 0) { - CPU_show_freemem = XdrvMailbox.payload; - } - ResponseCmndNumber(CPU_show_freemem); -} - -void CmndSetSensor(void) -{ - if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { - if (XdrvMailbox.payload >= 0) { - bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); - if (1 == XdrvMailbox.payload) { - restart_flag = 2; - } - } - Response_P(PSTR("{\"" D_CMND_SETSENSOR "\":")); - XsnsSensorState(); - ResponseJsonEnd(); - } -} - -void CmndFlashMode(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { - SetFlashMode(XdrvMailbox.payload); - } - ResponseCmndNumber(ESP.getFlashChipMode()); -} - -uint32_t DebugSwap32(uint32_t x) { - return ((x << 24) & 0xff000000 ) | - ((x << 8) & 0x00ff0000 ) | - ((x >> 8) & 0x0000ff00 ) | - ((x >> 24) & 0x000000ff ); -} - -void CmndFlashDump(void) -{ - - - - const uint32_t flash_start = 0x40200000; - const uint8_t bytes_per_cols = 0x20; - const uint32_t max = (SPIFFS_END + 5) * SPI_FLASH_SEC_SIZE; - - uint32_t start = flash_start; - uint32_t rows = 8; - - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= (max - bytes_per_cols))) { - start += (XdrvMailbox.payload &0x7FFFFFFC); - - char *p; - uint32_t is_payload = strtol(XdrvMailbox.data, &p, 16); - rows = strtol(p, &p, 10); - if (0 == rows) { rows = 8; } - } - uint32_t end = start + (rows * bytes_per_cols); - if ((end - flash_start) > max) { - end = flash_start + max; - } - - for (uint32_t pos = start; pos < end; pos += bytes_per_cols) { - uint32_t* values = (uint32_t*)(pos); - AddLog_P2(LOG_LEVEL_INFO, PSTR("%06X: %08X %08X %08X %08X %08X %08X %08X %08X"), pos - flash_start, - DebugSwap32(values[0]), DebugSwap32(values[1]), DebugSwap32(values[2]), DebugSwap32(values[3]), - DebugSwap32(values[4]), DebugSwap32(values[5]), DebugSwap32(values[6]), DebugSwap32(values[7])); - } - ResponseCmndDone(); -} - -#ifdef USE_I2C -void CmndI2cWrite(void) -{ - - if (i2c_flg) { - char* parms = XdrvMailbox.data; - uint8_t buffer[100]; - uint32_t index = 0; - - char *p; - char *data = strtok_r(parms, " ,", &p); - while (data != NULL && index < sizeof(buffer)) { - buffer[index++] = strtol(data, nullptr, 16); - data = strtok_r(nullptr, " ,", &p); - } - - if (index > 1) { - AddLogBuffer(LOG_LEVEL_INFO, buffer, index); - - Wire.beginTransmission(buffer[0]); - for (uint32_t i = 1; i < index; i++) { - Wire.write(buffer[i]); - } - int result = Wire.endTransmission(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("I2C: Result %d"), result); - } - } - ResponseCmndDone(); -} - -void CmndI2cRead(void) -{ - - if (i2c_flg) { - char* parms = XdrvMailbox.data; - uint8_t buffer[100]; - uint32_t index = 0; - - char *p; - char *data = strtok_r(parms, " ,", &p); - while (data != NULL && index < sizeof(buffer)) { - buffer[index++] = strtol(data, nullptr, 16); - data = strtok_r(nullptr, " ,", &p); - } - - if (index > 0) { - uint8_t size = 1; - if (index > 1) { - size = buffer[1]; - } - Wire.requestFrom(buffer[0], size); - index = 0; - while (Wire.available() && index < sizeof(buffer)) { - buffer[index++] = Wire.read(); - } - if (index > 0) { - AddLogBuffer(LOG_LEVEL_INFO, buffer, index); - } - } - } - ResponseCmndDone(); -} - -void CmndI2cStretch(void) -{ - if (i2c_flg && (XdrvMailbox.payload > 0)) { - Wire.setClockStretchLimit(XdrvMailbox.payload); - } - ResponseCmndDone(); -} - -void CmndI2cClock(void) -{ - if (i2c_flg && (XdrvMailbox.payload > 0)) { - Wire.setClock(XdrvMailbox.payload); - } - ResponseCmndDone(); -} -#endif - - - - - -bool Xdrv99(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - CpuLoadLoop(); - break; - case FUNC_FREE_MEM: - if (CPU_show_freemem) { DebugFreeMem(); } - break; - case FUNC_PRE_INIT: - CPU_last_millis = millis(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kDebugCommands, DebugCommand); - break; - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xdrv_interface.ino" -# 20 "S:/Development/Tasmota/tasmota/xdrv_interface.ino" -#ifdef XFUNC_PTR_IN_ROM -bool (* const xdrv_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xdrv_func_ptr[])(uint8_t) = { -#endif - -#ifdef XDRV_01 - &Xdrv01, -#endif - -#ifdef XDRV_02 - &Xdrv02, -#endif - -#ifdef XDRV_03 - &Xdrv03, -#endif - -#ifdef XDRV_04 - &Xdrv04, -#endif - -#ifdef XDRV_05 - &Xdrv05, -#endif - -#ifdef XDRV_06 - &Xdrv06, -#endif - -#ifdef XDRV_07 - &Xdrv07, -#endif - -#ifdef XDRV_08 - &Xdrv08, -#endif - -#ifdef XDRV_09 - &Xdrv09, -#endif - -#ifdef XDRV_10 - &Xdrv10, -#endif - -#ifdef XDRV_11 - &Xdrv11, -#endif - -#ifdef XDRV_12 - &Xdrv12, -#endif - -#ifdef XDRV_13 - &Xdrv13, -#endif - -#ifdef XDRV_14 - &Xdrv14, -#endif - -#ifdef XDRV_15 - &Xdrv15, -#endif - -#ifdef XDRV_16 - &Xdrv16, -#endif - -#ifdef XDRV_17 - &Xdrv17, -#endif - -#ifdef XDRV_18 - &Xdrv18, -#endif - -#ifdef XDRV_19 - &Xdrv19, -#endif - -#ifdef XDRV_20 - &Xdrv20, -#endif - -#ifdef XDRV_21 - &Xdrv21, -#endif - -#ifdef XDRV_22 - &Xdrv22, -#endif - -#ifdef XDRV_23 - &Xdrv23, -#endif - -#ifdef XDRV_24 - &Xdrv24, -#endif - -#ifdef XDRV_25 - &Xdrv25, -#endif - -#ifdef XDRV_26 - &Xdrv26, -#endif - -#ifdef XDRV_27 - &Xdrv27, -#endif - -#ifdef XDRV_28 - &Xdrv28, -#endif - -#ifdef XDRV_29 - &Xdrv29, -#endif - -#ifdef XDRV_30 - &Xdrv30, -#endif - -#ifdef XDRV_31 - &Xdrv31, -#endif - -#ifdef XDRV_32 - &Xdrv32, -#endif - -#ifdef XDRV_33 - &Xdrv33, -#endif - -#ifdef XDRV_34 - &Xdrv34, -#endif - -#ifdef XDRV_35 - &Xdrv35, -#endif - -#ifdef XDRV_36 - &Xdrv36, -#endif - -#ifdef XDRV_37 - &Xdrv37, -#endif - -#ifdef XDRV_38 - &Xdrv38, -#endif - -#ifdef XDRV_39 - &Xdrv39, -#endif - -#ifdef XDRV_40 - &Xdrv40, -#endif - -#ifdef XDRV_41 - &Xdrv41, -#endif - -#ifdef XDRV_42 - &Xdrv42, -#endif - -#ifdef XDRV_43 - &Xdrv43, -#endif - -#ifdef XDRV_44 - &Xdrv44, -#endif - -#ifdef XDRV_45 - &Xdrv45, -#endif - -#ifdef XDRV_46 - &Xdrv46, -#endif - -#ifdef XDRV_47 - &Xdrv47, -#endif - -#ifdef XDRV_48 - &Xdrv48, -#endif - -#ifdef XDRV_49 - &Xdrv49, -#endif - -#ifdef XDRV_50 - &Xdrv50, -#endif - -#ifdef XDRV_51 - &Xdrv51, -#endif - -#ifdef XDRV_52 - &Xdrv52, -#endif - -#ifdef XDRV_53 - &Xdrv53, -#endif - -#ifdef XDRV_54 - &Xdrv54, -#endif - -#ifdef XDRV_55 - &Xdrv55, -#endif - -#ifdef XDRV_56 - &Xdrv56, -#endif - -#ifdef XDRV_57 - &Xdrv57, -#endif - -#ifdef XDRV_58 - &Xdrv58, -#endif - -#ifdef XDRV_59 - &Xdrv59, -#endif - -#ifdef XDRV_60 - &Xdrv60, -#endif - -#ifdef XDRV_61 - &Xdrv61, -#endif - -#ifdef XDRV_62 - &Xdrv62, -#endif - -#ifdef XDRV_63 - &Xdrv63, -#endif - -#ifdef XDRV_64 - &Xdrv64, -#endif - -#ifdef XDRV_65 - &Xdrv65, -#endif - -#ifdef XDRV_66 - &Xdrv66, -#endif - -#ifdef XDRV_67 - &Xdrv67, -#endif - -#ifdef XDRV_68 - &Xdrv68, -#endif - -#ifdef XDRV_69 - &Xdrv69, -#endif - -#ifdef XDRV_70 - &Xdrv70, -#endif - -#ifdef XDRV_71 - &Xdrv71, -#endif - -#ifdef XDRV_72 - &Xdrv72, -#endif - -#ifdef XDRV_73 - &Xdrv73, -#endif - -#ifdef XDRV_74 - &Xdrv74, -#endif - -#ifdef XDRV_75 - &Xdrv75, -#endif - -#ifdef XDRV_76 - &Xdrv76, -#endif - -#ifdef XDRV_77 - &Xdrv77, -#endif - -#ifdef XDRV_78 - &Xdrv78, -#endif - -#ifdef XDRV_79 - &Xdrv79, -#endif - -#ifdef XDRV_80 - &Xdrv80, -#endif - -#ifdef XDRV_81 - &Xdrv81, -#endif - -#ifdef XDRV_82 - &Xdrv82, -#endif - -#ifdef XDRV_83 - &Xdrv83, -#endif - -#ifdef XDRV_84 - &Xdrv84, -#endif - -#ifdef XDRV_85 - &Xdrv85, -#endif - -#ifdef XDRV_86 - &Xdrv86, -#endif - -#ifdef XDRV_87 - &Xdrv87, -#endif - -#ifdef XDRV_88 - &Xdrv88, -#endif - -#ifdef XDRV_89 - &Xdrv89, -#endif - -#ifdef XDRV_90 - &Xdrv90, -#endif - -#ifdef XDRV_91 - &Xdrv91, -#endif - -#ifdef XDRV_92 - &Xdrv92, -#endif - -#ifdef XDRV_93 - &Xdrv93, -#endif - -#ifdef XDRV_94 - &Xdrv94, -#endif - -#ifdef XDRV_95 - &Xdrv95, -#endif - -#ifdef XDRV_96 - &Xdrv96, -#endif - -#ifdef XDRV_97 - &Xdrv97, -#endif - -#ifdef XDRV_98 - &Xdrv98, -#endif - -#ifdef XDRV_99 - &Xdrv99 -#endif -}; - -const uint8_t xdrv_present = sizeof(xdrv_func_ptr) / sizeof(xdrv_func_ptr[0]); - - - - - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXdrvList[] PROGMEM = { -#else -const uint8_t kXdrvList[] = { -#endif - -#ifdef XDRV_01 - XDRV_01, -#endif - -#ifdef XDRV_02 - XDRV_02, -#endif - -#ifdef XDRV_03 - XDRV_03, -#endif - -#ifdef XDRV_04 - XDRV_04, -#endif - -#ifdef XDRV_05 - XDRV_05, -#endif - -#ifdef XDRV_06 - XDRV_06, -#endif - -#ifdef XDRV_07 - XDRV_07, -#endif - -#ifdef XDRV_08 - XDRV_08, -#endif - -#ifdef XDRV_09 - XDRV_09, -#endif - -#ifdef XDRV_10 - XDRV_10, -#endif - -#ifdef XDRV_11 - XDRV_11, -#endif - -#ifdef XDRV_12 - XDRV_12, -#endif - -#ifdef XDRV_13 - XDRV_13, -#endif - -#ifdef XDRV_14 - XDRV_14, -#endif - -#ifdef XDRV_15 - XDRV_15, -#endif - -#ifdef XDRV_16 - XDRV_16, -#endif - -#ifdef XDRV_17 - XDRV_17, -#endif - -#ifdef XDRV_18 - XDRV_18, -#endif - -#ifdef XDRV_19 - XDRV_19, -#endif - -#ifdef XDRV_20 - XDRV_20, -#endif - -#ifdef XDRV_21 - XDRV_21, -#endif - -#ifdef XDRV_22 - XDRV_22, -#endif - -#ifdef XDRV_23 - XDRV_23, -#endif - -#ifdef XDRV_24 - XDRV_24, -#endif - -#ifdef XDRV_25 - XDRV_25, -#endif - -#ifdef XDRV_26 - XDRV_26, -#endif - -#ifdef XDRV_27 - XDRV_27, -#endif - -#ifdef XDRV_28 - XDRV_28, -#endif - -#ifdef XDRV_29 - XDRV_29, -#endif - -#ifdef XDRV_30 - XDRV_30, -#endif - -#ifdef XDRV_31 - XDRV_31, -#endif - -#ifdef XDRV_32 - XDRV_32, -#endif - -#ifdef XDRV_33 - XDRV_33, -#endif - -#ifdef XDRV_34 - XDRV_34, -#endif - -#ifdef XDRV_35 - XDRV_35, -#endif - -#ifdef XDRV_36 - XDRV_36, -#endif - -#ifdef XDRV_37 - XDRV_37, -#endif - -#ifdef XDRV_38 - XDRV_38, -#endif - -#ifdef XDRV_39 - XDRV_39, -#endif - -#ifdef XDRV_40 - XDRV_40, -#endif - -#ifdef XDRV_41 - XDRV_41, -#endif - -#ifdef XDRV_42 - XDRV_42, -#endif - -#ifdef XDRV_43 - XDRV_43, -#endif - -#ifdef XDRV_44 - XDRV_44, -#endif - -#ifdef XDRV_45 - XDRV_45, -#endif - -#ifdef XDRV_46 - XDRV_46, -#endif - -#ifdef XDRV_47 - XDRV_47, -#endif - -#ifdef XDRV_48 - XDRV_48, -#endif - -#ifdef XDRV_49 - XDRV_49, -#endif - -#ifdef XDRV_50 - XDRV_50, -#endif - -#ifdef XDRV_51 - XDRV_51, -#endif - -#ifdef XDRV_52 - XDRV_52, -#endif - -#ifdef XDRV_53 - XDRV_53, -#endif - -#ifdef XDRV_54 - XDRV_54, -#endif - -#ifdef XDRV_55 - XDRV_55, -#endif - -#ifdef XDRV_56 - XDRV_56, -#endif - -#ifdef XDRV_57 - XDRV_57, -#endif - -#ifdef XDRV_58 - XDRV_58, -#endif - -#ifdef XDRV_59 - XDRV_59, -#endif - -#ifdef XDRV_60 - XDRV_60, -#endif - -#ifdef XDRV_61 - XDRV_61, -#endif - -#ifdef XDRV_62 - XDRV_62, -#endif - -#ifdef XDRV_63 - XDRV_63, -#endif - -#ifdef XDRV_64 - XDRV_64, -#endif - -#ifdef XDRV_65 - XDRV_65, -#endif - -#ifdef XDRV_66 - XDRV_66, -#endif - -#ifdef XDRV_67 - XDRV_67, -#endif - -#ifdef XDRV_68 - XDRV_68, -#endif - -#ifdef XDRV_69 - XDRV_69, -#endif - -#ifdef XDRV_70 - XDRV_70, -#endif - -#ifdef XDRV_71 - XDRV_71, -#endif - -#ifdef XDRV_72 - XDRV_72, -#endif - -#ifdef XDRV_73 - XDRV_73, -#endif - -#ifdef XDRV_74 - XDRV_74, -#endif - -#ifdef XDRV_75 - XDRV_75, -#endif - -#ifdef XDRV_76 - XDRV_76, -#endif - -#ifdef XDRV_77 - XDRV_77, -#endif - -#ifdef XDRV_78 - XDRV_78, -#endif - -#ifdef XDRV_79 - XDRV_79, -#endif - -#ifdef XDRV_80 - XDRV_80, -#endif - -#ifdef XDRV_81 - XDRV_81, -#endif - -#ifdef XDRV_82 - XDRV_82, -#endif - -#ifdef XDRV_83 - XDRV_83, -#endif - -#ifdef XDRV_84 - XDRV_84, -#endif - -#ifdef XDRV_85 - XDRV_85, -#endif - -#ifdef XDRV_86 - XDRV_86, -#endif - -#ifdef XDRV_87 - XDRV_87, -#endif - -#ifdef XDRV_88 - XDRV_88, -#endif - -#ifdef XDRV_89 - XDRV_89, -#endif - -#ifdef XDRV_90 - XDRV_90, -#endif - -#ifdef XDRV_91 - XDRV_91, -#endif - -#ifdef XDRV_92 - XDRV_92, -#endif - -#ifdef XDRV_93 - XDRV_93, -#endif - -#ifdef XDRV_94 - XDRV_94, -#endif - -#ifdef XDRV_95 - XDRV_95, -#endif - -#ifdef XDRV_96 - XDRV_96, -#endif - -#ifdef XDRV_97 - XDRV_97, -#endif - -#ifdef XDRV_98 - XDRV_98, -#endif - -#ifdef XDRV_99 - XDRV_99 -#endif -}; - - - -void XsnsDriverState(void) -{ - ResponseAppend_P(PSTR(",\"Drivers\":\"")); - for (uint32_t i = 0; i < sizeof(kXdrvList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t driverid = pgm_read_byte(kXdrvList + i); -#else - uint32_t driverid = kXdrvList[i]; -#endif - ResponseAppend_P(PSTR("%s%d"), (i) ? "," : "", driverid); - } - ResponseAppend_P(PSTR("\"")); -} - - - -bool XdrvRulesProcess(void) -{ - return XdrvCallDriver(10, FUNC_RULES_PROCESS); -} - -#ifdef USE_DEBUG_DRIVER -void ShowFreeMem(const char *where) -{ - char stemp[30]; - snprintf_P(stemp, sizeof(stemp), where); - XdrvMailbox.data = stemp; - XdrvCall(FUNC_FREE_MEM); -} -#endif - - - - - -bool XdrvCallDriver(uint32_t driver, uint8_t Function) -{ - for (uint32_t x = 0; x < xdrv_present; x++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t listed = pgm_read_byte(kXdrvList + x); -#else - uint32_t listed = kXdrvList[x]; -#endif - if (driver == listed) { - return xdrv_func_ptr[x](Function); - } - } - return false; -} - - - - - -bool XdrvCall(uint8_t Function) -{ - bool result = false; - - DEBUG_TRACE_LOG(PSTR("DRV: %d"), Function); - - for (uint32_t x = 0; x < xdrv_present; x++) { - result = xdrv_func_ptr[x](Function); - - if (result && ((FUNC_COMMAND == Function) || - (FUNC_COMMAND_DRIVER == Function) || - (FUNC_MQTT_DATA == Function) || - (FUNC_RULES_PROCESS == Function) || - (FUNC_BUTTON_PRESSED == Function) || - (FUNC_SERIAL == Function) || - (FUNC_MODULE_INIT == Function) || - (FUNC_SET_CHANNELS == Function) || - (FUNC_PIN_STATE == Function) || - (FUNC_SET_DEVICE_POWER == Function) - )) { - break; - } - } - - return result; -} -# 1 "S:/Development/Tasmota/tasmota/xdsp_01_lcd.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_01_lcd.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_LCD - -#define XDSP_01 1 -#define XI2C_03 3 - -#define LCD_ADDRESS1 0x27 -#define LCD_ADDRESS2 0x3F - -#include -#include - -LiquidCrystal_I2C *lcd; - - - -void LcdInitMode(void) -{ - lcd->init(); - lcd->clear(); -} - -void LcdInit(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - LcdInitMode(); -#ifdef USE_DISPLAY_MODES1TO5 - DisplayClearScreenBuffer(); -#endif - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void LcdInitDriver(void) -{ - if (!Settings.display_model) { - if (I2cSetDevice(LCD_ADDRESS1)) { - Settings.display_address[0] = LCD_ADDRESS1; - Settings.display_model = XDSP_01; - } - else if (I2cSetDevice(LCD_ADDRESS2)) { - Settings.display_address[0] = LCD_ADDRESS2; - Settings.display_model = XDSP_01; - } - } - - if (XDSP_01 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "LCD"); - - Settings.display_width = Settings.display_cols[0]; - Settings.display_height = Settings.display_rows; - lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows); - -#ifdef USE_DISPLAY_MODES1TO5 - DisplayAllocScreenBuffer(); -#endif - - LcdInitMode(); - } -} - -void LcdDrawStringAt(void) -{ - if (dsp_flag) { - dsp_x--; - dsp_y--; - } - lcd->setCursor(dsp_x, dsp_y); - lcd->print(dsp_str); -} - -void LcdDisplayOnOff(uint8_t on) -{ - if (on) { - lcd->backlight(); - } else { - lcd->noBacklight(); - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void LcdCenter(uint8_t row, char* txt) -{ - char line[Settings.display_cols[0] +2]; - - int len = strlen(txt); - int offset = 0; - if (len >= Settings.display_cols[0]) { - len = Settings.display_cols[0]; - } else { - offset = (Settings.display_cols[0] - len) / 2; - } - memset(line, 0x20, Settings.display_cols[0]); - line[Settings.display_cols[0]] = 0; - for (uint32_t i = 0; i < len; i++) { - line[offset +i] = txt[i]; - } - lcd->setCursor(0, row); - lcd->print(line); -} - -bool LcdPrintLog(void) -{ - bool result = false; - - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\337'); - if (txt != nullptr) { - uint8_t last_row = Settings.display_rows -1; - - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - lcd->setCursor(0, i); - lcd->print(disp_screen_buffer[i +1]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - lcd->setCursor(0, last_row); - lcd->print(disp_screen_buffer[last_row]); - - result = true; - } - } - return result; -} - -void LcdTime(void) -{ - char line[Settings.display_cols[0] +1]; - - snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - LcdCenter(0, line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - LcdCenter(1, line); -} - -void LcdRefresh(void) -{ - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - LcdTime(); - break; - case 2: - case 4: - LcdPrintLog(); - break; - case 3: - case 5: { - if (!LcdPrintLog()) { LcdTime(); } - break; - } - } - } -} - -#endif - - - - - -bool Xdsp01(uint8_t function) -{ - if (!I2cEnabled(XI2C_03)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - LcdInitDriver(); - } - else if (XDSP_01 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - LcdInit(dsp_init); - break; - case FUNC_DISPLAY_POWER: - LcdDisplayOnOff(disp_power); - break; - case FUNC_DISPLAY_CLEAR: - lcd->clear(); - break; -# 238 "S:/Development/Tasmota/tasmota/xdsp_01_lcd.ino" - case FUNC_DISPLAY_DRAW_STRING: - LcdDrawStringAt(); - break; - case FUNC_DISPLAY_ONOFF: - LcdDisplayOnOff(dsp_on); - break; - - -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - LcdRefresh(); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_02_ssd1306.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_02_ssd1306.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SSD1306 - -#define XDSP_02 2 -#define XI2C_04 4 - -#define OLED_RESET 4 - -#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); - -#define OLED_ADDRESS1 0x3C -#define OLED_ADDRESS2 0x3D - -#define OLED_BUFFER_COLS 40 -#define OLED_BUFFER_ROWS 16 - -#define OLED_FONT_WIDTH 6 -#define OLED_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_SSD1306 *oled1306; - -extern uint8_t *buffer; - - - -void SSD1306InitDriver(void) -{ - if (!Settings.display_model) { - if (I2cSetDevice(OLED_ADDRESS1)) { - Settings.display_address[0] = OLED_ADDRESS1; - Settings.display_model = XDSP_02; - } - else if (I2cSetDevice(OLED_ADDRESS2)) { - Settings.display_address[0] = OLED_ADDRESS2; - Settings.display_model = XDSP_02; - } - } - - if (XDSP_02 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "SSD1306"); - - if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) { - Settings.display_width = 128; - } - if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 48) && (Settings.display_height != 64)) { - Settings.display_height = 64; - } - - uint8_t reset_pin = -1; - if (pin[GPIO_OLED_RESET] < 99) { - reset_pin = pin[GPIO_OLED_RESET]; - } - - - if (buffer) { free(buffer); } - buffer = (unsigned char*)calloc((Settings.display_width * Settings.display_height) / 8,1); - if (!buffer) { return; } - - - - oled1306 = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, reset_pin); - oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], reset_pin >= 0); - renderer = oled1306; - renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font); - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - renderer->setTextFont(0); - renderer->setTextSize(2); - renderer->setCursor(20,20); - renderer->println(F("SSD1306")); - renderer->Updateframe(); - renderer->DisplayOnff(1); -#endif - - } -} - - -#ifdef USE_DISPLAY_MODES1TO5 - -void Ssd1306PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void Ssd1306Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setTextFont(Settings.display_font); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void Ssd1306Refresh(void) -{ - if (!renderer) return; - - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - Ssd1306Time(); - break; - case 2: - case 3: - case 4: - case 5: - Ssd1306PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp02(byte function) -{ - if (!I2cEnabled(XI2C_04)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SSD1306InitDriver(); - } - else if (XDSP_02 == Settings.display_model) { - switch (function) { -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - Ssd1306Refresh(); - break; -#endif - case FUNC_DISPLAY_MODEL: - result = true; - break; - } - } - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_03_matrix.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_03_matrix.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_MATRIX - -#define XDSP_03 3 -#define XI2C_05 5 - -#define MTX_MAX_SCREEN_BUFFER 80 - -#include -#include -#include - -Adafruit_8x8matrix *matrix[8]; -uint8_t mtx_matrices = 0; -uint8_t mtx_state = 0; -uint8_t mtx_counter = 0; -int16_t mtx_x = 0; -int16_t mtx_y = 0; - - -char *mtx_buffer = nullptr; - -uint8_t mtx_mode = 0; -uint8_t mtx_loop = 0; -uint8_t mtx_done = 0; - - - -void MatrixWrite(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->writeDisplay(); - } -} - -void MatrixClear(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - } - MatrixWrite(); -} - -void MatrixFixed(char* txt) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(-i *8, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); -} - -void MatrixCenter(char* txt) -{ - int offset; - - int len = strlen(txt); - offset = (len < 8) ? offset = ((mtx_matrices *8) - (len *6)) / 2 : 0; - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(-(i *8)+offset, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); -} - -void MatrixScrollLeft(char* txt, int loop) -{ - switch (mtx_state) { - case 1: - mtx_state = 2; - - mtx_x = 8 * mtx_matrices; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), txt); - - disp_refresh = Settings.display_refresh; - case 2: - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->setCursor(mtx_x - i *8, 0); - matrix[i]->print(txt); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); - - mtx_x--; - int16_t len = strlen(txt); - if (mtx_x < -(len *6)) { mtx_state = loop; } - } - break; - } -} - -void MatrixScrollUp(char* txt, int loop) -{ - int wordcounter = 0; - char tmpbuf[200]; - char *words[100]; - - - - char separators[] = " /"; - - switch (mtx_state) { - case 1: - mtx_state = 2; - - mtx_y = 8; - mtx_counter = 0; - disp_refresh = Settings.display_refresh; - case 2: - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - strlcpy(tmpbuf, txt, sizeof(tmpbuf)); - char *p = strtok(tmpbuf, separators); - while (p != nullptr && wordcounter < 40) { - words[wordcounter++] = p; - p = strtok(nullptr, separators); - } - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - for (uint32_t j = 0; j < wordcounter; j++) { - matrix[i]->setCursor(-i *8, mtx_y + (j *8)); - matrix[i]->println(words[j]); - } - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); - if (((mtx_y %8) == 0) && mtx_counter) { - mtx_counter--; - } else { - mtx_y--; - mtx_counter = STATES * 1; - } - if (mtx_y < -(wordcounter *8)) { mtx_state = loop; } - } - break; - } -} - - - -void MatrixInitMode(void) -{ - for (uint32_t i = 0; i < mtx_matrices; i++) { - matrix[i]->setRotation(Settings.display_rotate); - matrix[i]->setBrightness(Settings.display_dimmer); - matrix[i]->blinkRate(0); - matrix[i]->setTextWrap(false); - - - matrix[i]->cp437(true); - } - MatrixClear(); -} - -void MatrixInit(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - MatrixInitMode(); - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void MatrixInitDriver(void) -{ - mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); - if (mtx_buffer != nullptr) { - if (!Settings.display_model) { - if (I2cSetDevice(Settings.display_address[1])) { - Settings.display_model = XDSP_03; - } - } - - if (XDSP_03 == Settings.display_model) { - mtx_state = 1; - for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) { - if (Settings.display_address[mtx_matrices]) { - I2cSetActiveFound(Settings.display_address[mtx_matrices], "8x8Matrix"); - matrix[mtx_matrices] = new Adafruit_8x8matrix(); - matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]); - } else { - break; - } - } - - Settings.display_width = mtx_matrices * 8; - Settings.display_height = 8; - - MatrixInitMode(); - } - } -} - -void MatrixOnOff(void) -{ - if (!disp_power) { MatrixClear(); } -} - -void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - strlcpy(mtx_buffer, str, MTX_MAX_SCREEN_BUFFER); - mtx_mode = x &1; - mtx_loop = y &1; - if (!mtx_state) { mtx_state = 1; } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void MatrixPrintLog(uint8_t direction) -{ - char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer; - if (txt != nullptr) { - if (!mtx_state) { mtx_state = 1; } - - if (!mtx_done) { - - uint8_t space = 0; - uint8_t max_cols = (disp_log_buffer_cols < MTX_MAX_SCREEN_BUFFER) ? disp_log_buffer_cols : MTX_MAX_SCREEN_BUFFER; - mtx_buffer[0] = '\0'; - uint8_t i = 0; - while ((txt[i] != '\0') && (i < max_cols)) { - if (txt[i] == ' ') { - space++; - } else { - space = 0; - } - if (space < 2) { - strncat(mtx_buffer, (const char*)txt +i, (strlen(mtx_buffer) < MTX_MAX_SCREEN_BUFFER -1) ? 1 : 0); - } - i++; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), mtx_buffer); - - mtx_done = 1; - } - - if (direction) { - MatrixScrollUp(mtx_buffer, 0); - } else { - MatrixScrollLeft(mtx_buffer, 0); - } - if (!mtx_state) { mtx_done = 0; } - } else { - char disp_time[9]; - - snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - MatrixFixed(disp_time); - } -} - -#endif - -void MatrixRefresh(void) -{ - if (disp_power) { - switch (Settings.display_mode) { - case 0: { - switch (mtx_mode) { - case 0: - MatrixScrollLeft(mtx_buffer, mtx_loop); - break; - case 1: - MatrixScrollUp(mtx_buffer, mtx_loop); - break; - } - break; - } -#ifdef USE_DISPLAY_MODES1TO5 - case 2: { - char disp_date[9]; - snprintf_P(disp_date, sizeof(disp_date), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); - MatrixFixed(disp_date); - break; - } - case 3: { - char disp_day[10]; - snprintf_P(disp_day, sizeof(disp_day), PSTR("%d %s"), RtcTime.day_of_month, RtcTime.name_of_month); - MatrixCenter(disp_day); - break; - } - case 4: - MatrixPrintLog(0); - break; - case 1: - case 5: - MatrixPrintLog(1); - break; -#endif - } - } -} - - - - - -bool Xdsp03(uint8_t function) -{ - if (!I2cEnabled(XI2C_05)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - MatrixInitDriver(); - } - else if (XDSP_03 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - MatrixInit(dsp_init); - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: - MatrixRefresh(); - break; - case FUNC_DISPLAY_POWER: - MatrixOnOff(); - break; - case FUNC_DISPLAY_DRAW_STRING: - MatrixDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); - break; - } - } - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_04_ili9341.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_04_ili9341.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9341 - -#define XDSP_04 4 - -#define TFT_TOP 16 -#define TFT_BOTTOM 16 -#define TFT_FONT_WIDTH 6 -#define TFT_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_ILI9341 *tft; - -uint16_t tft_scroll; - - - -void Ili9341InitMode(void) -{ - tft->setRotation(Settings.display_rotate); - tft->invertDisplay(0); - tft->fillScreen(ILI9341_BLACK); - tft->setTextWrap(false); - tft->cp437(true); - if (!Settings.display_mode) { - tft->setCursor(0, 0); - tft->setTextColor(ILI9341_WHITE, ILI9341_BLACK); - tft->setTextSize(1); - } else { - tft->setScrollMargins(TFT_TOP, TFT_BOTTOM); - tft->setCursor(0, 0); - tft->setTextColor(ILI9341_YELLOW, ILI9341_BLACK); - tft->setTextSize(2); - - - tft_scroll = TFT_TOP; - } -} - -void Ili9341Init(uint8_t mode) -{ - switch(mode) { - case DISPLAY_INIT_MODE: - Ili9341InitMode(); -#ifdef USE_DISPLAY_MODES1TO5 - if (Settings.display_rotate) { - DisplayClearScreenBuffer(); - } -#endif - break; - case DISPLAY_INIT_PARTIAL: - case DISPLAY_INIT_FULL: - break; - } -} - -void Ili9341InitDriver(void) -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_04; - } - - if (XDSP_04 == Settings.display_model) { - if (Settings.display_width != ILI9341_TFTWIDTH) { - Settings.display_width = ILI9341_TFTWIDTH; - } - if (Settings.display_height != ILI9341_TFTHEIGHT) { - Settings.display_height = ILI9341_TFTHEIGHT; - } - tft = new Adafruit_ILI9341(pin[GPIO_SPI_CS], pin[GPIO_SPI_DC]); - tft->begin(); - -#ifdef USE_DISPLAY_MODES1TO5 - if (Settings.display_rotate) { - DisplayAllocScreenBuffer(); - } -#endif - - Ili9341InitMode(); - } -} - -void Ili9341Clear(void) -{ - tft->fillScreen(ILI9341_BLACK); - tft->setCursor(0, 0); -} - -void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - uint16_t active_color = ILI9341_WHITE; - - tft->setTextSize(Settings.display_size); - if (!flag) { - tft->setCursor(x, y); - } else { - tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size); - } - if (color) { active_color = color; } - tft->setTextColor(active_color, ILI9341_BLACK); - tft->println(str); -} - -void Ili9341DisplayOnOff(uint8_t on) -{ - - - if (pin[GPIO_BACKLIGHT] < 99) { - pinMode(pin[GPIO_BACKLIGHT], OUTPUT); - digitalWrite(pin[GPIO_BACKLIGHT], on); - } -} - -void Ili9341OnOff(void) -{ - Ili9341DisplayOnOff(disp_power); -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void Ili9341PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (Settings.display_rotate) { - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - } - - char* txt = DisplayLogBuffer('\370'); - if (txt != nullptr) { - uint8_t size = Settings.display_size; - uint16_t theight = size * TFT_FONT_HEIGTH; - - tft->setTextSize(size); - tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); - if (!Settings.display_rotate) { - tft->setCursor(0, tft_scroll); - tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); - tft->print(txt); - tft_scroll += theight; - if (tft_scroll >= (tft->height() - TFT_BOTTOM)) { - tft_scroll = TFT_TOP; - } - tft->scrollTo(tft_scroll); - } else { - uint8_t last_row = Settings.display_rows -1; - - tft_scroll = theight; - tft->setCursor(0, tft_scroll); - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - - tft->print(disp_screen_buffer[i]); - tft_scroll += theight; - tft->setCursor(0, tft_scroll); - delay(1); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - tft->print(disp_screen_buffer[last_row]); - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); - } - } -} - -void Ili9341Refresh(void) -{ - if (Settings.display_mode) { - char tftdt[Settings.display_cols[0] +1]; - char date4[11]; - char space[Settings.display_cols[0] - 17]; - char time[9]; - - tft->setTextSize(2); - tft->setTextColor(ILI9341_YELLOW, ILI9341_RED); - tft->setCursor(0, 0); - - snprintf_P(date4, sizeof(date4), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - memset(space, 0x20, sizeof(space)); - space[sizeof(space) -1] = '\0'; - snprintf_P(time, sizeof(time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - snprintf_P(tftdt, sizeof(tftdt), PSTR("%s%s%s"), date4, space, time); - - tft->print(tftdt); - - switch (Settings.display_mode) { - case 1: - case 2: - case 3: - case 4: - case 5: - Ili9341PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp04(uint8_t function) -{ - bool result = false; - - if (spi_flg) { - if (FUNC_DISPLAY_INIT_DRIVER == function) { - Ili9341InitDriver(); - } - else if (XDSP_04 == Settings.display_model) { - - if (!dsp_color) { dsp_color = ILI9341_WHITE; } - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_INIT: - Ili9341Init(dsp_init); - break; - case FUNC_DISPLAY_POWER: - Ili9341OnOff(); - break; - case FUNC_DISPLAY_CLEAR: - Ili9341Clear(); - break; - case FUNC_DISPLAY_DRAW_HLINE: - tft->writeFastHLine(dsp_x, dsp_y, dsp_len, dsp_color); - break; - case FUNC_DISPLAY_DRAW_VLINE: - tft->writeFastVLine(dsp_x, dsp_y, dsp_len, dsp_color); - break; - case FUNC_DISPLAY_DRAW_LINE: - tft->writeLine(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - case FUNC_DISPLAY_DRAW_CIRCLE: - tft->drawCircle(dsp_x, dsp_y, dsp_rad, dsp_color); - break; - case FUNC_DISPLAY_FILL_CIRCLE: - tft->fillCircle(dsp_x, dsp_y, dsp_rad, dsp_color); - break; - case FUNC_DISPLAY_DRAW_RECTANGLE: - tft->drawRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - case FUNC_DISPLAY_FILL_RECTANGLE: - tft->fillRect(dsp_x, dsp_y, dsp_x2, dsp_y2, dsp_color); - break; - - - - case FUNC_DISPLAY_TEXT_SIZE: - tft->setTextSize(Settings.display_size); - break; - case FUNC_DISPLAY_FONT_SIZE: - - break; - case FUNC_DISPLAY_DRAW_STRING: - Ili9341DrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); - break; - case FUNC_DISPLAY_ONOFF: - Ili9341DisplayOnOff(dsp_on); - break; - case FUNC_DISPLAY_ROTATION: - tft->setRotation(Settings.display_rotate); - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - Ili9341Refresh(); - break; -#endif - } - } - } - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_05_epaper_29.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_05_epaper_29.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_EPAPER_29 - -#define XDSP_05 5 - -#define EPD_TOP 12 -#define EPD_FONT_HEIGTH 12 - -#define COLORED 1 -#define UNCOLORED 0 - - - -#define USE_TINY_FONT - -#include -#include - - -extern uint8_t *buffer; -uint16_t epd_scroll; - -Epd *epd; - - - -void EpdInitDriver29() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_05; - } - - if (XDSP_05 == Settings.display_model) { - if (Settings.display_width != EPD_WIDTH) { - Settings.display_width = EPD_WIDTH; - } - if (Settings.display_height != EPD_HEIGHT) { - Settings.display_height = EPD_HEIGHT; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((EPD_WIDTH * EPD_HEIGHT) / 8,1); - if (!buffer) return; - - - epd = new Epd(EPD_WIDTH,EPD_HEIGHT); - - - if ((pin[GPIO_SPI_CS] < 99) && (pin[GPIO_SPI_CLK] < 99) && (pin[GPIO_SPI_MOSI] < 99)) { - epd->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: HardSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SPI_CS], pin[GPIO_SPI_CLK], pin[GPIO_SPI_MOSI]); - } - else if ((pin[GPIO_SSPI_CS] < 99) && (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_MOSI] < 99)) { - epd->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("EPD: SoftSPI CS %d, CLK %d, MOSI %d"),pin[GPIO_SSPI_CS], pin[GPIO_SSPI_SCLK], pin[GPIO_SSPI_MOSI]); - } else { - free(buffer); - return; - } - - renderer = epd; - epd->Init(DISPLAY_INIT_FULL); - epd->Init(DISPLAY_INIT_PARTIAL); - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(1); - renderer->DrawStringAt(50, 50, "Waveshare E-Paper Display!", COLORED,0); - renderer->Updateframe(); - delay(1000); - renderer->fillScreen(0); -#endif - - } -} - - - - - - - -#ifdef USE_DISPLAY_MODES1TO5 -#define EPD_FONT_HEIGTH 12 -void EpdPrintLog29(void) -{ - - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - - char* txt = DisplayLogBuffer('\040'); - if (txt != nullptr) { - uint8_t size = Settings.display_size; - uint16_t theight = size * EPD_FONT_HEIGTH; - - renderer->setTextFont(size); - uint8_t last_row = Settings.display_rows -1; - - - epd_scroll = 0; - for (uint32_t i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[i], COLORED, 0); - epd_scroll += theight; - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - renderer->DrawStringAt(0, epd_scroll, disp_screen_buffer[last_row], COLORED, 0); - - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "[%s]"), txt); - } - } -} - -void EpdRefresh29(void) -{ - if (Settings.display_mode) { - - if (!renderer) return; -# 165 "S:/Development/Tasmota/tasmota/xdsp_05_epaper_29.ino" - switch (Settings.display_mode) { - case 1: - case 2: - case 3: - case 4: - case 5: - EpdPrintLog29(); - renderer->Updateframe(); - break; - } - - - } -} - -#endif - - - - - -bool Xdsp05(uint8_t function) -{ - bool result = false; - if (FUNC_DISPLAY_INIT_DRIVER == function) { - EpdInitDriver29(); - } - else if (XDSP_05 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh29(); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_06_epaper_42.ino" -# 21 "S:/Development/Tasmota/tasmota/xdsp_06_epaper_42.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_EPAPER_42 - -#define XDSP_06 6 - -#define COLORED42 1 -#define UNCOLORED42 0 - - - -#define USE_TINY_FONT - -#include -#include - -extern uint8_t *buffer; - -Epd42 *epd42; - - - - -void EpdInitDriver42() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_06; - } - - if (XDSP_06 == Settings.display_model) { - - if (Settings.display_width != EPD_WIDTH42) { - Settings.display_width = EPD_WIDTH42; - } - if (Settings.display_height != EPD_HEIGHT42) { - Settings.display_height = EPD_HEIGHT42; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((EPD_WIDTH42 * EPD_HEIGHT42) / 8,1); - if (!buffer) return; - - - epd42 = new Epd42(EPD_WIDTH42,EPD_HEIGHT42); - - #ifdef USE_SPI - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)) { - epd42->Begin(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - } else { - free(buffer); - return; - } - #else - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { - epd42->Begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - } else { - free(buffer); - return; - } - #endif - - renderer = epd42; - - epd42->Init(); - - renderer->fillScreen(0); - - - epd42->Init(DISPLAY_INIT_FULL); - - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - - epd42->ClearFrame(); - renderer->Updateframe(); - delay(3000); - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->DrawStringAt(50, 140, "Waveshare E-Paper!", COLORED42,0); - renderer->Updateframe(); - delay(350); - renderer->fillScreen(0); -#endif - - } -} - - - - - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void EpdRefresh42() -{ - if (Settings.display_mode) { - - } -} - -#endif - - - - - - -bool Xdsp06(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - EpdInitDriver42(); - } - else if (XDSP_06 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh42(); - break; -#endif - } - } - return result; -} - - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_07_sh1106.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_07_sh1106.ino" -#ifdef USE_I2C -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SH1106 - -#define OLED_RESET 4 - -#define SPRINT(A) char str[32];sprintf(str,"val: %d ",A);Serial.println((char*)str); - -extern uint8_t *buffer; - -#define XDSP_07 7 -#define XI2C_06 6 - -#define OLED_ADDRESS1 0x3C -#define OLED_ADDRESS2 0x3D - -#define OLED_BUFFER_COLS 40 -#define OLED_BUFFER_ROWS 16 - -#define OLED_FONT_WIDTH 6 -#define OLED_FONT_HEIGTH 8 - -#include -#include -#include - -Adafruit_SH1106 *oled1106; - - - - -void SH1106InitDriver() -{ - if (!Settings.display_model) { - if (I2cSetDevice(OLED_ADDRESS1)) { - Settings.display_address[0] = OLED_ADDRESS1; - Settings.display_model = XDSP_07; - } - else if (I2cSetDevice(OLED_ADDRESS2)) { - Settings.display_address[0] = OLED_ADDRESS2; - Settings.display_model = XDSP_07; - } - } - - if (XDSP_07 == Settings.display_model) { - I2cSetActiveFound(Settings.display_address[0], "SH1106"); - - if (Settings.display_width != SH1106_LCDWIDTH) { - Settings.display_width = SH1106_LCDWIDTH; - } - if (Settings.display_height != SH1106_LCDHEIGHT) { - Settings.display_height = SH1106_LCDHEIGHT; - } - - - if (buffer) free(buffer); - buffer=(unsigned char*)calloc((SH1106_LCDWIDTH * SH1106_LCDHEIGHT) / 8,1); - if (!buffer) return; - - - oled1106 = new Adafruit_SH1106(SH1106_LCDWIDTH,SH1106_LCDHEIGHT); - renderer=oled1106; - renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0); - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->setTextColor(1,0); - -#ifdef SHOW_SPLASH - renderer->setTextFont(0); - renderer->setTextSize(2); - renderer->setCursor(20,20); - renderer->println(F("SH1106")); - renderer->Updateframe(); - renderer->DisplayOnff(1); -#endif - } -} - - - -#ifdef USE_DISPLAY_MODES1TO5 - -void SH1106PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void SH1106Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setTextFont(Settings.display_font); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void SH1106Refresh(void) -{ - if (!renderer) return; - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - SH1106Time(); - break; - case 2: - case 3: - case 4: - case 5: - SH1106PrintLog(); - break; - } - } -} - -#endif - - - - - -bool Xdsp07(uint8_t function) -{ - if (!I2cEnabled(XI2C_06)) { return false; } - - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SH1106InitDriver(); - } - else if (XDSP_07 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - SH1106Refresh(); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_08_ILI9488.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_08_ILI9488.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_ILI9488 - -#define XDSP_08 8 -#define XI2C_38 38 - -#define COLORED 1 -#define UNCOLORED 0 - - -#define FT6236_address 0x38 - - - -#define USE_TINY_FONT - - -#include -#include - -TouchLocation ili9488_pLoc; -uint8_t ili9488_ctouch_counter = 0; - - -#define BACKPLANE_PIN 2 - -extern uint8_t *buffer; -extern uint8_t color_type; -ILI9488 *ili9488; - -#ifdef USE_TOUCH_BUTTONS -extern VButton *buttons[]; -#endif - -extern const uint16_t picture[]; -uint8_t FT6236_found; - - - -void ILI9488_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_08; - } - - if (XDSP_08 == Settings.display_model) { - - if (Settings.display_width != ILI9488_TFTWIDTH) { - Settings.display_width = ILI9488_TFTWIDTH; - } - if (Settings.display_height != ILI9488_TFTHEIGHT) { - Settings.display_height = ILI9488_TFTHEIGHT; - } - - - buffer=NULL; - - - fg_color = ILI9488_WHITE; - bg_color = ILI9488_BLACK; - - uint8_t bppin=BACKPLANE_PIN; - if (pin[GPIO_BACKLIGHT]<99) { - bppin=pin[GPIO_BACKLIGHT]; - } - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ - ili9488 = new ILI9488(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK],bppin); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)) { - ili9488 = new ILI9488(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK],bppin); - } else { - return; - } - } - - SPI.begin(); - ili9488->begin(); - renderer = ili9488; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(ILI9488_WHITE,ILI9488_BLACK); - renderer->DrawStringAt(50, 50, "ILI9488 TFT Display!", ILI9488_WHITE,0); - delay(1000); - - -#endif - - color_type = COLOR_COLOR; - - - if (I2cEnabled(XI2C_38) && I2cSetDevice(FT6236_address)) { - FT6236begin(FT6236_address); - FT6236_found=1; - I2cSetActiveFound(FT6236_address, "FT6236"); - } else { - FT6236_found=0; - } - - } -} - -#ifdef USE_TOUCH_BUTTONS -void ILI9488_MQTT(uint8_t count,const char *cp) { - ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); - MqttPublishTeleSensor(); -} - -void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr) { - buttons[count]->xdrawButton(pwr); - if (pwr) buttons[count]->vpower|=0x80; - else buttons[count]->vpower&=0x7f; -} - -void FT6236Check() { -uint16_t temp; -uint8_t rbutt=0,vbutt=0; -ili9488_ctouch_counter++; -if (2 == ili9488_ctouch_counter) { - - ili9488_ctouch_counter=0; - if (FT6236readTouchLocation(&ili9488_pLoc,1)) { - - if (renderer) { - uint8_t rot=renderer->getRotation(); - switch (rot) { - case 0: - temp=ili9488_pLoc.y; - ili9488_pLoc.y=renderer->height()-ili9488_pLoc.x; - ili9488_pLoc.x=temp; - break; - case 1: - break; - case 2: - break; - case 3: - temp=ili9488_pLoc.y; - ili9488_pLoc.y=ili9488_pLoc.x; - ili9488_pLoc.x=renderer->width()-temp; - break; - } - - for (uint8_t count=0; countvpower&0x7f; - if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) { - - buttons[count]->press(true); - if (buttons[count]->justPressed()) { - if (!bflags) { - uint8_t pwr=bitRead(power,rbutt); - if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { - ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); - ILI9488_RDW_BUTT(count,!pwr); - } - } else { - - const char *cp; - if (bflags==1) { - - buttons[count]->vpower^=0x80; - cp="TBT"; - } else { - - buttons[count]->vpower|=0x80; - cp="PBT"; - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - ILI9488_MQTT(count,cp); - } - } - } - if (!bflags) { - rbutt++; - } else { - vbutt++; - } - } - } - } - } else { - - for (uint8_t count=0; countvpower&0x7f; - buttons[count]->press(false); - if (buttons[count]->justReleased()) { - uint8_t bflags=buttons[count]->vpower&0x7f; - if (bflags>0) { - if (bflags>1) { - - buttons[count]->vpower&=0x7f; - ILI9488_MQTT(count,"PBT"); - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - } - } - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; - if (pwr!=vpwr) { - ILI9488_RDW_BUTT(count,pwr); - } - rbutt++; - } - } - } - ili9488_pLoc.x=0; - ili9488_pLoc.y=0; - } -} -} -#endif - - - - -bool Xdsp08(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - ILI9488_InitDriver(); - } - else if (XDSP_08 == Settings.display_model) { - - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_TOUCH_BUTTONS - if (FT6236_found) FT6236Check(); -#endif - break; - } - } - - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_09_SSD1351.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_09_SSD1351.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_SSD1351 - -#define XDSP_09 9 - -#define COLORED 1 -#define UNCOLORED 0 - - - - -#define USE_TINY_FONT - -#include - -extern uint8_t *buffer; -extern uint8_t color_type; -SSD1351 *ssd1351; - - - -void SSD1351_InitDriver() { - if (!Settings.display_model) { - Settings.display_model = XDSP_09; - } - - if (XDSP_09 == Settings.display_model) { - - if (Settings.display_width != SSD1351_WIDTH) { - Settings.display_width = SSD1351_WIDTH; - } - if (Settings.display_height != SSD1351_HEIGHT) { - Settings.display_height = SSD1351_HEIGHT; - } - - buffer=0; - - - fg_color = SSD1351_WHITE; - bg_color = SSD1351_BLACK; - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]<99) && (pin[GPIO_SSPI_SCLK]<99)){ - ssd1351 = new SSD1351(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_SCLK]); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]<99) && (pin[GPIO_SPI_CLK]<99)){ - ssd1351 = new SSD1351(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_CLK]); - } else { - return; - } - } - - delay(100); - SPI.begin(); - ssd1351->begin(); - renderer = ssd1351; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->dim(Settings.display_dimmer); - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(SSD1351_WHITE,SSD1351_BLACK); - renderer->DrawStringAt(10, 60, "SSD1351", SSD1351_RED,0); - delay(1000); - -#endif - color_type = COLOR_COLOR; - } -} - -#ifdef USE_DISPLAY_MODES1TO5 - -void SSD1351PrintLog(void) -{ - disp_refresh--; - if (!disp_refresh) { - disp_refresh = Settings.display_refresh; - if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } - - char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { - uint8_t last_row = Settings.display_rows -1; - - renderer->clearDisplay(); - renderer->setTextSize(Settings.display_size); - renderer->setCursor(0,0); - for (byte i = 0; i < last_row; i++) { - strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols); - renderer->println(disp_screen_buffer[i]); - } - strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols); - DisplayFillScreen(last_row); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), disp_screen_buffer[last_row]); - - renderer->println(disp_screen_buffer[last_row]); - renderer->Updateframe(); - } - } -} - -void SSD1351Time(void) -{ - char line[12]; - - renderer->clearDisplay(); - renderer->setTextSize(2); - renderer->setCursor(0, 0); - snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - renderer->println(line); - snprintf_P(line, sizeof(line), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%04d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year); - renderer->println(line); - renderer->Updateframe(); -} - -void SSD1351Refresh(void) -{ - if (Settings.display_mode) { - switch (Settings.display_mode) { - case 1: - SSD1351Time(); - break; - case 2: - case 3: - case 4: - case 5: - SSD1351PrintLog(); - break; - } - } -} - -#endif - - - - -bool Xdsp09(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - SSD1351_InitDriver(); - } - else if (XDSP_09 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; -#ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - SSD1351Refresh(); - break; -#endif - } - } - return result; -} -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_10_RA8876.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_10_RA8876.ino" -#ifdef USE_SPI -#ifdef USE_DISPLAY -#ifdef USE_DISPLAY_RA8876 - -#define XDSP_10 10 -#define XI2C_39 39 - -#define COLORED 1 -#define UNCOLORED 0 - - -#define FT5316_address 0x38 - - - -#define USE_TINY_FONT - -#include -#include - -TouchLocation ra8876_pLoc; -uint8_t ra8876_ctouch_counter = 0; - -#ifdef USE_TOUCH_BUTTONS -extern VButton *buttons[]; -#endif - -extern uint8_t *buffer; -extern uint8_t color_type; -RA8876 *ra8876; - -uint8_t FT5316_found; - - -void RA8876_InitDriver() -{ - if (!Settings.display_model) { - Settings.display_model = XDSP_10; - } - - if (XDSP_10 == Settings.display_model) { - - if (Settings.display_width != RA8876_TFTWIDTH) { - Settings.display_width = RA8876_TFTWIDTH; - } - if (Settings.display_height != RA8876_TFTHEIGHT) { - Settings.display_height = RA8876_TFTHEIGHT; - } - buffer=0; - - - fg_color = RA8876_WHITE; - bg_color = RA8876_BLACK; - - - if ((pin[GPIO_SSPI_CS]<99) && (pin[GPIO_SSPI_MOSI]==13) && (pin[GPIO_SSPI_MISO]==12) && (pin[GPIO_SSPI_SCLK]==14)) { - ra8876 = new RA8876(pin[GPIO_SSPI_CS],pin[GPIO_SSPI_MOSI],pin[GPIO_SSPI_MISO],pin[GPIO_SSPI_SCLK],pin[GPIO_BACKLIGHT]); - } else { - if ((pin[GPIO_SPI_CS]<99) && (pin[GPIO_SPI_MOSI]==13) && (pin[GPIO_SPI_MISO]==12) && (pin[GPIO_SPI_CLK]==14)) { - ra8876 = new RA8876(pin[GPIO_SPI_CS],pin[GPIO_SPI_MOSI],pin[GPIO_SPI_MISO],pin[GPIO_SPI_CLK],pin[GPIO_BACKLIGHT]); - } else { - return; - } - } - - ra8876->begin(); - renderer = ra8876; - renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font); - renderer->dim(Settings.display_dimmer); - - -#ifdef SHOW_SPLASH - - renderer->setTextFont(2); - renderer->setTextColor(RA8876_WHITE,RA8876_BLACK); - renderer->DrawStringAt(600, 300, "RA8876", RA8876_RED,0); - delay(1000); - -#endif - color_type = COLOR_COLOR; - - if (I2cEnabled(XI2C_39) && I2cSetDevice(FT5316_address)) { - FT6236begin(FT5316_address); - FT5316_found=1; - I2cSetActiveFound(FT5316_address, "FT5316"); - } else { - FT5316_found=0; - } - - } -} - -#ifdef USE_TOUCH_BUTTONS -void RA8876_MQTT(uint8_t count,const char *cp) { - ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7); - MqttPublishTeleSensor(); -} - -void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr) { - buttons[count]->xdrawButton(pwr); - if (pwr) buttons[count]->vpower|=0x80; - else buttons[count]->vpower&=0x7f; -} - - -void FT5316Check() { -uint16_t temp; -uint8_t rbutt=0,vbutt=0; -ra8876_ctouch_counter++; -if (2 == ra8876_ctouch_counter) { - - ra8876_ctouch_counter=0; - - if (FT6236readTouchLocation(&ra8876_pLoc,1)) { - ra8876_pLoc.x=ra8876_pLoc.x*RA8876_TFTWIDTH/800; - ra8876_pLoc.y=ra8876_pLoc.y*RA8876_TFTHEIGHT/480; - - - if (renderer) { - - - ra8876_pLoc.x=RA8876_TFTWIDTH-ra8876_pLoc.x; - ra8876_pLoc.y=RA8876_TFTHEIGHT-ra8876_pLoc.y; -# 170 "S:/Development/Tasmota/tasmota/xdsp_10_RA8876.ino" - for (uint8_t count=0; countvpower&0x7f; - if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) { - - buttons[count]->press(true); - if (buttons[count]->justPressed()) { - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) { - ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON); - RA8876_RDW_BUTT(count,!pwr); - } - } else { - - const char *cp; - if (bflags==1) { - - buttons[count]->vpower^=0x80; - cp="TBT"; - } else { - - buttons[count]->vpower|=0x80; - cp="PBT"; - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - RA8876_MQTT(count,cp); - } - } - } - if (!bflags) { - rbutt++; - } else { - vbutt++; - } - } - } - } - } else { - - for (uint8_t count=0; countvpower&0x7f; - buttons[count]->press(false); - if (buttons[count]->justReleased()) { - if (bflags>0) { - if (bflags>1) { - - buttons[count]->vpower&=0x7f; - RA8876_MQTT(count,"PBT"); - } - buttons[count]->xdrawButton(buttons[count]->vpower&0x80); - } - } - if (!bflags) { - - uint8_t pwr=bitRead(power,rbutt); - uint8_t vpwr=(buttons[count]->vpower&0x80)>>7; - if (pwr!=vpwr) { - RA8876_RDW_BUTT(count,pwr); - } - rbutt++; - } - } - } - ra8876_pLoc.x=0; - ra8876_pLoc.y=0; - } -} -} -#endif -# 426 "S:/Development/Tasmota/tasmota/xdsp_10_RA8876.ino" -bool Xdsp10(uint8_t function) -{ - bool result = false; - - if (FUNC_DISPLAY_INIT_DRIVER == function) { - RA8876_InitDriver(); - } - else if (XDSP_10 == Settings.display_model) { - switch (function) { - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_EVERY_50_MSECOND: -#ifdef USE_TOUCH_BUTTONS - if (FT5316_found) FT5316Check(); -#endif - break; - } - } - return result; -} -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xdsp_interface.ino" -# 20 "S:/Development/Tasmota/tasmota/xdsp_interface.ino" -#ifdef USE_DISPLAY - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xdsp_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xdsp_func_ptr[])(uint8_t) = { -#endif - -#ifdef XDSP_01 - &Xdsp01, -#endif - -#ifdef XDSP_02 - &Xdsp02, -#endif - -#ifdef XDSP_03 - &Xdsp03, -#endif - -#ifdef XDSP_04 - &Xdsp04, -#endif - -#ifdef XDSP_05 - &Xdsp05, -#endif - -#ifdef XDSP_06 - &Xdsp06, -#endif - -#ifdef XDSP_07 - &Xdsp07, -#endif - -#ifdef XDSP_08 - &Xdsp08, -#endif - -#ifdef XDSP_09 - &Xdsp09, -#endif - -#ifdef XDSP_10 - &Xdsp10, -#endif - -#ifdef XDSP_11 - &Xdsp11, -#endif - -#ifdef XDSP_12 - &Xdsp12, -#endif - -#ifdef XDSP_13 - &Xdsp13, -#endif - -#ifdef XDSP_14 - &Xdsp14, -#endif - -#ifdef XDSP_15 - &Xdsp15, -#endif - -#ifdef XDSP_16 - &Xdsp16 -#endif -}; - -const uint8_t xdsp_present = sizeof(xdsp_func_ptr) / sizeof(xdsp_func_ptr[0]); -# 117 "S:/Development/Tasmota/tasmota/xdsp_interface.ino" -uint8_t XdspPresent(void) -{ - return xdsp_present; -} - -bool XdspCall(uint8_t Function) -{ - bool result = false; - - DEBUG_TRACE_LOG(PSTR("DSP: %d"), Function); - - for (uint32_t x = 0; x < xdsp_present; x++) { - result = xdsp_func_ptr[x](Function); - - if (result && (FUNC_DISPLAY_MODEL == Function)) { - break; - } - } - - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xlgt_01_ws2812.ino" -# 20 "S:/Development/Tasmota/tasmota/xlgt_01_ws2812.ino" -#ifdef USE_LIGHT -#ifdef USE_WS2812 -# 38 "S:/Development/Tasmota/tasmota/xlgt_01_ws2812.ino" -#define XLGT_01 1 - -const uint8_t WS2812_SCHEMES = 8; - -const char kWs2812Commands[] PROGMEM = "|" - D_CMND_LED "|" D_CMND_PIXELS "|" D_CMND_ROTATION "|" D_CMND_WIDTH ; - -void (* const Ws2812Command[])(void) PROGMEM = { - &CmndLed, &CmndPixels, &CmndRotation, &CmndWidth }; - -#include - -#if (USE_WS2812_CTYPE == NEO_GRB) - typedef NeoGrbFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_BRG) - typedef NeoBrgFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_RBG) - typedef NeoRbgFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_RGBW) - typedef NeoRgbwFeature selectedNeoFeatureType; -#elif (USE_WS2812_CTYPE == NEO_GRBW) - typedef NeoGrbwFeature selectedNeoFeatureType; -#else - typedef NeoRgbFeature selectedNeoFeatureType; -#endif - -#ifdef USE_WS2812_DMA - - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266DmaWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266DmaSk6812Method selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_APA106) - typedef NeoEsp8266DmaApa106Method selectedNeoSpeedType; -#else - typedef NeoEsp8266Dma800KbpsMethod selectedNeoSpeedType; -#endif - -#else - - -#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X) - typedef NeoEsp8266BitBangWs2812xMethod selectedNeoSpeedType; -#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812) - typedef NeoEsp8266BitBangSk6812Method selectedNeoSpeedType; -#else - typedef NeoEsp8266BitBang800KbpsMethod selectedNeoSpeedType; -#endif - -#endif - -NeoPixelBus *strip = nullptr; - -struct WsColor { - uint8_t red, green, blue; -}; - -struct ColorScheme { - WsColor* colors; - uint8_t count; -}; - -WsColor kIncandescent[2] = { 255,140,20, 0,0,0 }; -WsColor kRgb[3] = { 255,0,0, 0,255,0, 0,0,255 }; -WsColor kChristmas[2] = { 255,0,0, 0,255,0 }; -WsColor kHanukkah[2] = { 0,0,255, 255,255,255 }; -WsColor kwanzaa[3] = { 255,0,0, 0,0,0, 0,255,0 }; -WsColor kRainbow[7] = { 255,0,0, 255,128,0, 255,255,0, 0,255,0, 0,0,255, 128,0,255, 255,0,255 }; -WsColor kFire[3] = { 255,0,0, 255,102,0, 255,192,0 }; -ColorScheme kSchemes[WS2812_SCHEMES -1] = { - kIncandescent, 2, - kRgb, 3, - kChristmas, 2, - kHanukkah, 2, - kwanzaa, 3, - kRainbow, 7, - kFire, 3 }; - -uint8_t kWidth[5] = { - 1, - 2, - 4, - 8, - 255 }; -uint8_t kWsRepeat[5] = { - 8, - 6, - 4, - 2, - 1 }; - -struct WS2812 { - uint8_t show_next = 1; - uint8_t scheme_offset = 0; - bool suspend_update = false; -} Ws2812; - - - -void Ws2812StripShow(void) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; -#else - RgbColor c; -#endif - - if (Settings.light_correction) { - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - c = strip->GetPixelColor(i); - c.R = ledGamma(c.R); - c.G = ledGamma(c.G); - c.B = ledGamma(c.B); -#if (USE_WS2812_CTYPE > NEO_3LED) - c.W = ledGamma(c.W); -#endif - strip->SetPixelColor(i, c); - } - } - strip->Show(); -} - -int mod(int a, int b) -{ - int ret = a % b; - if (ret < 0) ret += b; - return ret; -} - -void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offset) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor color; -#else - RgbColor color; -#endif - - uint32_t mod_position = mod(position, (int)Settings.light_pixels); - - color = strip->GetPixelColor(mod_position); - float dimmer = 100 / (float)Settings.light_dimmer; - color.R = tmin(color.R + ((hand_color.red / dimmer) * offset), 255); - color.G = tmin(color.G + ((hand_color.green / dimmer) * offset), 255); - color.B = tmin(color.B + ((hand_color.blue / dimmer) * offset), 255); - strip->SetPixelColor(mod_position, color); -} - -void Ws2812UpdateHand(int position, uint32_t index) -{ - uint32_t width = Settings.light_width; - if (index < WS_MARKER) { width = Settings.ws_width[index]; } - if (!width) { return; } - - position = (position + Settings.light_rotation) % Settings.light_pixels; - - if (Settings.flag.ws_clock_reverse) { - position = Settings.light_pixels -position; - } - WsColor hand_color = { Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE] }; - - Ws2812UpdatePixelColor(position, hand_color, 1); - - uint32_t range = ((width -1) / 2) +1; - for (uint32_t h = 1; h < range; h++) { - float offset = (float)(range - h) / (float)range; - Ws2812UpdatePixelColor(position -h, hand_color, offset); - Ws2812UpdatePixelColor(position +h, hand_color, offset); - } -} - -void Ws2812Clock(void) -{ - strip->ClearTo(0); - int clksize = 60000 / (int)Settings.light_pixels; - - Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND); - Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE); - Ws2812UpdateHand((((RtcTime.hour % 12) * 5000) + ((RtcTime.minute * 1000) / 12 )) / clksize, WS_HOUR); - if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) { - for (uint32_t i = 0; i < 12; i++) { - Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER); - } - } - - Ws2812StripShow(); -} - -void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t range, uint32_t gradRange, uint32_t i) -{ - - - - - ColorScheme scheme = kSchemes[schemenr]; - uint32_t curRange = i / range; - uint32_t rangeIndex = i % range; - uint32_t colorIndex = rangeIndex / gradRange; - uint32_t start = colorIndex; - uint32_t end = colorIndex +1; - if (curRange % 2 != 0) { - start = (scheme.count -1) - start; - end = (scheme.count -1) - end; - } - float dimmer = 100 / (float)Settings.light_dimmer; - float fmyRed = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].red, scheme.colors[end].red) / dimmer; - float fmyGrn = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].green, scheme.colors[end].green) / dimmer; - float fmyBlu = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].blue, scheme.colors[end].blue) / dimmer; - mColor->red = (uint8_t)fmyRed; - mColor->green = (uint8_t)fmyGrn; - mColor->blue = (uint8_t)fmyBlu; -} - -void Ws2812Gradient(uint32_t schemenr) -{ - - - - - -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; - c.W = 0; -#else - RgbColor c; -#endif - - ColorScheme scheme = kSchemes[schemenr]; - if (scheme.count < 2) { return; } - - uint32_t repeat = kWsRepeat[Settings.light_width]; - uint32_t range = (uint32_t)ceil((float)Settings.light_pixels / (float)repeat); - uint32_t gradRange = (uint32_t)ceil((float)range / (float)(scheme.count - 1)); - uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); - uint32_t offset = speed > 0 ? Light.strip_timer_counter / speed : 0; - - WsColor oldColor, currentColor; - Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset); - currentColor = oldColor; - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - if (kWsRepeat[Settings.light_width] > 1) { - Ws2812GradientColor(schemenr, ¤tColor, range, gradRange, i +offset); - } - if (Settings.light_speed > 0) { - - c.R = map(Light.strip_timer_counter % speed, 0, speed, oldColor.red, currentColor.red); - c.G = map(Light.strip_timer_counter % speed, 0, speed, oldColor.green, currentColor.green); - c.B = map(Light.strip_timer_counter % speed, 0, speed, oldColor.blue, currentColor.blue); - } - else { - - c.R = currentColor.red; - c.G = currentColor.green; - c.B = currentColor.blue; - } - strip->SetPixelColor(i, c); - oldColor = currentColor; - } - Ws2812StripShow(); -} - -void Ws2812Bars(uint32_t schemenr) -{ - - - - - -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor c; - c.W = 0; -#else - RgbColor c; -#endif - - ColorScheme scheme = kSchemes[schemenr]; - - uint32_t maxSize = Settings.light_pixels / scheme.count; - if (kWidth[Settings.light_width] > maxSize) { maxSize = 0; } - - uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10); - uint32_t offset = (speed > 0) ? Light.strip_timer_counter / speed : 0; - - WsColor mcolor[scheme.count]; - memcpy(mcolor, scheme.colors, sizeof(mcolor)); - float dimmer = 100 / (float)Settings.light_dimmer; - for (uint32_t i = 0; i < scheme.count; i++) { - float fmyRed = (float)mcolor[i].red / dimmer; - float fmyGrn = (float)mcolor[i].green / dimmer; - float fmyBlu = (float)mcolor[i].blue / dimmer; - mcolor[i].red = (uint8_t)fmyRed; - mcolor[i].green = (uint8_t)fmyGrn; - mcolor[i].blue = (uint8_t)fmyBlu; - } - uint32_t colorIndex = offset % scheme.count; - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - if (maxSize) { colorIndex = ((i + offset) % (scheme.count * kWidth[Settings.light_width])) / kWidth[Settings.light_width]; } - c.R = mcolor[colorIndex].red; - c.G = mcolor[colorIndex].green; - c.B = mcolor[colorIndex].blue; - strip->SetPixelColor(i, c); - } - Ws2812StripShow(); -} - -void Ws2812Clear(void) -{ - strip->ClearTo(0); - strip->Show(); - Ws2812.show_next = 1; -} - -void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint8_t white) -{ -#if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor lcolor; - lcolor.W = white; -#else - RgbColor lcolor; -#endif - - lcolor.R = red; - lcolor.G = green; - lcolor.B = blue; - if (led) { - strip->SetPixelColor(led -1, lcolor); - } else { - - for (uint32_t i = 0; i < Settings.light_pixels; i++) { - strip->SetPixelColor(i, lcolor); - } - } - - if (!Ws2812.suspend_update) { - strip->Show(); - Ws2812.show_next = 1; - } -} - -char* Ws2812GetColor(uint32_t led, char* scolor) -{ - uint8_t sl_ledcolor[4]; - - #if (USE_WS2812_CTYPE > NEO_3LED) - RgbwColor lcolor = strip->GetPixelColor(led -1); - sl_ledcolor[3] = lcolor.W; - #else - RgbColor lcolor = strip->GetPixelColor(led -1); - #endif - sl_ledcolor[0] = lcolor.R; - sl_ledcolor[1] = lcolor.G; - sl_ledcolor[2] = lcolor.B; - scolor[0] = '\0'; - for (uint32_t i = 0; i < Light.subtype; i++) { - if (Settings.flag.decimal_text) { - snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", sl_ledcolor[i]); - } else { - snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, sl_ledcolor[i]); - } - } - return scolor; -} - - - - - -void Ws2812ForceSuspend (void) -{ - Ws2812.suspend_update = true; -} - -void Ws2812ForceUpdate (void) -{ - Ws2812.suspend_update = false; - strip->Show(); - Ws2812.show_next = 1; -} - - - -bool Ws2812SetChannels(void) -{ - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]); - - return true; -} - -void Ws2812ShowScheme(void) -{ - uint32_t scheme = Settings.light_scheme - Ws2812.scheme_offset; - - switch (scheme) { - case 0: - if ((1 == state_250mS) || (Ws2812.show_next)) { - Ws2812Clock(); - Ws2812.show_next = 0; - } - break; - default: - if (1 == Settings.light_fade) { - Ws2812Gradient(scheme -1); - } else { - Ws2812Bars(scheme -1); - } - Ws2812.show_next = 1; - break; - } -} - -void Ws2812ModuleSelected(void) -{ - if (pin[GPIO_WS2812] < 99) { - - - strip = new NeoPixelBus(WS2812_MAX_LEDS, pin[GPIO_WS2812]); - strip->Begin(); - - Ws2812Clear(); - - Ws2812.scheme_offset = Light.max_scheme +1; - Light.max_scheme += WS2812_SCHEMES; - -#if (USE_WS2812_CTYPE > NEO_3LED) - light_type = LT_RGBW; -#else - light_type = LT_RGB; -#endif - light_flg = XLGT_01; - } -} - - - -void CmndLed(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) { - if (XdrvMailbox.data_len > 0) { - char *p; - uint16_t idx = XdrvMailbox.index; - Ws2812ForceSuspend(); - for (char *color = strtok_r(XdrvMailbox.data, " ", &p); color; color = strtok_r(nullptr, " ", &p)) { - if (LightColorEntry(color, strlen(color))) { - Ws2812SetColor(idx, Light.entry_color[0], Light.entry_color[1], Light.entry_color[2], Light.entry_color[3]); - idx++; - if (idx > Settings.light_pixels) { break; } - } else { - break; - } - } - Ws2812ForceUpdate(); - } - char scolor[LIGHT_COLOR_SIZE]; - ResponseCmndIdxChar(Ws2812GetColor(XdrvMailbox.index, scolor)); - } -} - -void CmndPixels(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { - Settings.light_pixels = XdrvMailbox.payload; - Settings.light_rotation = 0; - Ws2812Clear(); - Light.update = true; - } - ResponseCmndNumber(Settings.light_pixels); -} - -void CmndRotation(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { - Settings.light_rotation = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_rotation); -} - -void CmndWidth(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { - if (1 == XdrvMailbox.index) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { - Settings.light_width = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.light_width); - } else { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32)) { - Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload; - } - ResponseCmndIdxNumber(Settings.ws_width[XdrvMailbox.index -2]); - } - } -} - - - - - -bool Xlgt01(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Ws2812SetChannels(); - break; - case FUNC_SET_SCHEME: - Ws2812ShowScheme(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kWs2812Commands, Ws2812Command); - break; - case FUNC_MODULE_INIT: - Ws2812ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xlgt_02_my92x1.ino" -# 20 "S:/Development/Tasmota/tasmota/xlgt_02_my92x1.ino" -#ifdef USE_LIGHT -#ifdef USE_MY92X1 - - - - -#define XLGT_02 2 - -struct MY92X1 { - uint8_t pdi_pin = 0; - uint8_t pdcki_pin = 0; - uint8_t model = 0; -} My92x1; - -extern "C" { - void os_delay_us(unsigned int); -} - -void LightDiPulse(uint8_t times) -{ - for (uint32_t i = 0; i < times; i++) { - digitalWrite(My92x1.pdi_pin, HIGH); - digitalWrite(My92x1.pdi_pin, LOW); - } -} - -void LightDckiPulse(uint8_t times) -{ - for (uint32_t i = 0; i < times; i++) { - digitalWrite(My92x1.pdcki_pin, HIGH); - digitalWrite(My92x1.pdcki_pin, LOW); - } -} - -void LightMy92x1Write(uint8_t data) -{ - for (uint32_t i = 0; i < 4; i++) { - digitalWrite(My92x1.pdcki_pin, LOW); - digitalWrite(My92x1.pdi_pin, (data & 0x80)); - digitalWrite(My92x1.pdcki_pin, HIGH); - data = data << 1; - digitalWrite(My92x1.pdi_pin, (data & 0x80)); - digitalWrite(My92x1.pdcki_pin, LOW); - digitalWrite(My92x1.pdi_pin, LOW); - data = data << 1; - } -} - -void LightMy92x1Init(void) -{ - uint8_t chips[3] = { 1, 2, 2 }; - - LightDckiPulse(chips[My92x1.model] * 32); - os_delay_us(12); - - - LightDiPulse(12); - os_delay_us(12); - for (uint32_t n = 0; n < chips[My92x1.model]; n++) { - LightMy92x1Write(0x18); - } - os_delay_us(12); - - - LightDiPulse(16); - os_delay_us(12); -} - -void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) -{ - uint8_t channels[3] = { 4, 6, 6 }; - - uint8_t duty[3][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, - { duty_w, duty_c, 0, duty_g, duty_r, duty_b }, - { duty_r, duty_g, duty_b, duty_w, duty_w, duty_w }}; - - os_delay_us(12); - for (uint32_t channel = 0; channel < channels[My92x1.model]; channel++) { - LightMy92x1Write(duty[My92x1.model][channel]); - } - os_delay_us(12); - LightDiPulse(8); - os_delay_us(12); -} - - - -bool My92x1SetChannels(void) -{ - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); - - return true; -} - -void My92x1ModuleSelected(void) -{ - if ((pin[GPIO_DCKI] < 99) && (pin[GPIO_DI] < 99)) { - My92x1.pdi_pin = pin[GPIO_DI]; - My92x1.pdcki_pin = pin[GPIO_DCKI]; - - pinMode(My92x1.pdi_pin, OUTPUT); - pinMode(My92x1.pdcki_pin, OUTPUT); - digitalWrite(My92x1.pdi_pin, LOW); - digitalWrite(My92x1.pdcki_pin, LOW); - - My92x1.model = 2; - light_type = LT_RGBW; - if (AILIGHT == my_module_type) { - My92x1.model = 0; - - } - else if (SONOFF_B1 == my_module_type) { - My92x1.model = 1; - light_type = LT_RGBWC; - } - - LightMy92x1Init(); - - light_flg = XLGT_02; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: MY29x1 Found")); - } -} - - - - - -bool Xlgt02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = My92x1SetChannels(); - break; - case FUNC_MODULE_INIT: - My92x1ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" -# 20 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" -#ifdef USE_LIGHT -#ifdef USE_SM16716 - - - - - - - -#define XLGT_03 3 - -#define D_LOG_SM16716 "SM16716: " - -struct SM16716 { - uint8_t pin_clk = 0; - uint8_t pin_dat = 0; - uint8_t pin_sel = 0; - bool enabled = false; -} Sm16716; - -void SM16716_SendBit(uint8_t v) -{ - - - - - - digitalWrite(Sm16716.pin_dat, (v != 0) ? HIGH : LOW); - - digitalWrite(Sm16716.pin_clk, HIGH); - - digitalWrite(Sm16716.pin_clk, LOW); -} - -void SM16716_SendByte(uint8_t v) -{ - uint8_t mask; - - for (mask = 0x80; mask; mask >>= 1) { - SM16716_SendBit(v & mask); - } -} - -void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b) -{ - if (Sm16716.pin_sel < 99) { - bool should_enable = (duty_r | duty_g | duty_b); - if (!Sm16716.enabled && should_enable) { - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on")); - Sm16716.enabled = true; - digitalWrite(Sm16716.pin_sel, HIGH); - - - delayMicroseconds(1000); - SM16716_Init(); - } - else if (Sm16716.enabled && !should_enable) { - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off")); - Sm16716.enabled = false; - digitalWrite(Sm16716.pin_sel, LOW); - } - } - DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b); - - - SM16716_SendBit(1); - SM16716_SendByte(duty_r); - SM16716_SendByte(duty_g); - SM16716_SendByte(duty_b); - - - - - - SM16716_SendBit(0); - SM16716_SendByte(0); - SM16716_SendByte(0); - SM16716_SendByte(0); -} -# 111 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" -void SM16716_Init(void) -{ - for (uint32_t t_init = 0; t_init < 50; ++t_init) { - SM16716_SendBit(0); - } -} - - - -bool Sm16716SetChannels(void) -{ -# 132 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - - SM16716_Update(cur_col[0], cur_col[1], cur_col[2]); - - return true; -} - -void Sm16716ModuleSelected(void) -{ - if ((pin[GPIO_SM16716_CLK] < 99) && (pin[GPIO_SM16716_DAT] < 99)) { - Sm16716.pin_clk = pin[GPIO_SM16716_CLK]; - Sm16716.pin_dat = pin[GPIO_SM16716_DAT]; - Sm16716.pin_sel = pin[GPIO_SM16716_SEL]; -# 157 "S:/Development/Tasmota/tasmota/xlgt_03_sm16716.ino" - pinMode(Sm16716.pin_clk, OUTPUT); - digitalWrite(Sm16716.pin_clk, LOW); - - pinMode(Sm16716.pin_dat, OUTPUT); - digitalWrite(Sm16716.pin_dat, LOW); - - if (Sm16716.pin_sel < 99) { - pinMode(Sm16716.pin_sel, OUTPUT); - digitalWrite(Sm16716.pin_sel, LOW); - - } else { - - SM16716_Init(); - } - - LightPwmOffset(LST_RGB); - light_type += LST_RGB; - light_flg = XLGT_03; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM16716 Found")); - } -} - - - - - -bool Xlgt03(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Sm16716SetChannels(); - break; - case FUNC_MODULE_INIT: - Sm16716ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xlgt_04_sm2135.ino" -# 20 "S:/Development/Tasmota/tasmota/xlgt_04_sm2135.ino" -#ifdef USE_LIGHT -#ifdef USE_SM2135 - - - - - - -#define XLGT_04 4 - -#define SM2135_ADDR_MC 0xC0 -#define SM2135_ADDR_CH 0xC1 -#define SM2135_ADDR_R 0xC2 -#define SM2135_ADDR_G 0xC3 -#define SM2135_ADDR_B 0xC4 -#define SM2135_ADDR_C 0xC5 -#define SM2135_ADDR_W 0xC6 - -#define SM2135_RGB 0x00 -#define SM2135_CW 0x80 - -#define SM2135_10MA 0x00 -#define SM2135_15MA 0x01 -#define SM2135_20MA 0x02 -#define SM2135_25MA 0x03 -#define SM2135_30MA 0x04 -#define SM2135_35MA 0x05 -#define SM2135_40MA 0x06 -#define SM2135_45MA 0x07 -#define SM2135_50MA 0x08 -#define SM2135_55MA 0x09 -#define SM2135_60MA 0x0A - - -const uint8_t SM2135_CURRENT = (SM2135_20MA << 4) | SM2135_15MA; - -struct SM2135 { - uint8_t clk = 0; - uint8_t data = 0; -} Sm2135; - -uint8_t Sm2135Write(uint8_t data) -{ - for (uint32_t i = 0; i < 8; i++) { - digitalWrite(Sm2135.clk, LOW); - digitalWrite(Sm2135.data, (data & 0x80)); - digitalWrite(Sm2135.clk, HIGH); - data = data << 1; - } - digitalWrite(Sm2135.clk, LOW); - digitalWrite(Sm2135.data, HIGH); - pinMode(Sm2135.data, INPUT); - digitalWrite(Sm2135.clk, HIGH); - uint8_t ack = digitalRead(Sm2135.data); - pinMode(Sm2135.data, OUTPUT); - return ack; -} - -void Sm2135Send(uint8_t *buffer, uint8_t size) -{ - digitalWrite(Sm2135.data, LOW); - for (uint32_t i = 0; i < size; i++) { - Sm2135Write(buffer[i]); - } - digitalWrite(Sm2135.clk, LOW); - digitalWrite(Sm2135.clk, HIGH); - digitalWrite(Sm2135.data, HIGH); -} - - - -bool Sm2135SetChannels(void) -{ - uint8_t *cur_col = (uint8_t*)XdrvMailbox.data; - uint8_t data[6]; - - if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) { -# 106 "S:/Development/Tasmota/tasmota/xlgt_04_sm2135.ino" - data[0] = SM2135_ADDR_MC; - data[1] = SM2135_CURRENT; - data[2] = SM2135_CW; - Sm2135Send(data, 3); - delay(1); - data[0] = SM2135_ADDR_C; - data[1] = cur_col[4]; - data[2] = cur_col[3]; - Sm2135Send(data, 3); - } else { - - - - - - - - data[0] = SM2135_ADDR_MC; - data[1] = SM2135_CURRENT; - data[2] = SM2135_RGB; - data[3] = cur_col[1]; - data[4] = cur_col[0]; - data[5] = cur_col[2]; - Sm2135Send(data, 6); - } - - return true; -} - -void Sm2135ModuleSelected(void) -{ - if ((pin[GPIO_SM2135_CLK] < 99) && (pin[GPIO_SM2135_DAT] < 99)) { - Sm2135.clk = pin[GPIO_SM2135_CLK]; - Sm2135.data = pin[GPIO_SM2135_DAT]; - - pinMode(Sm2135.data, OUTPUT); - digitalWrite(Sm2135.data, HIGH); - pinMode(Sm2135.clk, OUTPUT); - digitalWrite(Sm2135.clk, HIGH); - - light_type = LT_RGBWC; - light_flg = XLGT_04; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 Found")); - } -} - - - - - -bool Xlgt04(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SET_CHANNELS: - result = Sm2135SetChannels(); - break; - case FUNC_MODULE_INIT: - Sm2135ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" -# 20 "S:/Development/Tasmota/tasmota/xlgt_05_sonoff_l1.ino" -#ifdef USE_LIGHT -#ifdef USE_SONOFF_L1 - - - - -#define XLGT_05 5 - -#define SONOFF_L1_BUFFER_SIZE 140 - -#define SONOFF_L1_MODE_COLORFUL 1 -#define SONOFF_L1_MODE_COLORFUL_GRADIENT 2 -#define SONOFF_L1_MODE_COLORFUL_BREATH 3 -#define SONOFF_L1_MODE_DIY_GRADIENT 4 -#define SONOFF_L1_MODE_DIY_PULSE 5 -#define SONOFF_L1_MODE_DIY_BREATH 6 -#define SONOFF_L1_MODE_DIY_STROBE 7 -#define SONOFF_L1_MODE_RGB_GRADIENT 8 -#define SONOFF_L1_MODE_RGB_PULSE 9 -#define SONOFF_L1_MODE_RGB_BREATH 10 -#define SONOFF_L1_MODE_RGB_STROBE 11 -#define SONOFF_L1_MODE_SYNC_TO_MUSIC 12 - -struct SNFL1 { - uint32_t unlock = 0; - bool receive_ready = true; -} Snfl1; - - - -void SnfL1Send(const char *buffer) -{ - - - Serial.print(buffer); - Serial.write(0x1B); - Serial.flush(); -} - -void SnfL1SerialSendOk(void) -{ - char buffer[16]; - snprintf_P(buffer, sizeof(buffer), PSTR("AT+SEND=ok")); - - SnfL1Send(buffer); -} - -bool SnfL1SerialInput(void) -{ - if (serial_in_byte != 0x1B) { - if (serial_in_byte_counter >= 140) { - serial_in_byte_counter = 0; - } - if (serial_in_byte_counter || (!serial_in_byte_counter && ('A' == serial_in_byte))) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - } - } else { - serial_in_buffer[serial_in_byte_counter++] = 0x00; - - - - - - - if (!strncmp(serial_in_buffer +3, "RESULT", 6)) { - Snfl1.receive_ready = true; - } - else if (!strncmp(serial_in_buffer +3, "UPDATE", 6)) { - char cmnd_dimmer[20]; - char cmnd_color[20]; - char *end_str; - char *string = serial_in_buffer +10; - char *token = strtok_r(string, ",", &end_str); - - bool color_updated[3] = { false, false, false }; - uint8_t current_color[3]; - memcpy(current_color, Settings.light_color, 3); - - bool switch_state = false; - bool is_power_change = false; - bool is_color_change = false; - bool is_brightness_change = false; - - while (token != nullptr) { - char* end_token; - char* token2 = strtok_r(token, ":", &end_token); - char* token3 = strtok_r(nullptr, ":", &end_token); - - if (!strncmp(token2, "\"sequence\"", 10)) { - - - - token = nullptr; - } - - else if (!strncmp(token2, "\"switch\"", 8)) { - switch_state = !strncmp(token3, "\"on\"", 4) ? true : false; - - - - is_power_change = (switch_state != Light.power); - } - - else if (!strncmp(token2, "\"color", 6)) { - char color_channel_name = token2[6]; - int color_index; - switch(color_channel_name) - { - case 'R': color_index = 0; - break; - case 'G': color_index = 1; - break; - case 'B': color_index = 2; - break; - } - int color_value = atoi(token3); - current_color[color_index] = color_value; - color_updated[color_index] = true; - - bool all_color_channels_updated = color_updated[0] && color_updated[1] && color_updated[2]; - if (all_color_channels_updated) { - - - - - - is_color_change = (Light.power && (memcmp(current_color, Settings.light_color, 3) != 0)); - } - snprintf_P(cmnd_color, sizeof(cmnd_color), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), current_color[0], current_color[1], current_color[2]); - } - - else if (!strncmp(token2, "\"bright\"", 8)) { - uint8_t dimmer = atoi(token3); - - - - is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings.light_dimmer)); - snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer); - } - - token = strtok_r(nullptr, ",", &end_str); - } - - if (is_power_change) { - if (Settings.light_scheme > 0) { - if (!switch_state) { - char cmnd_scheme[20]; - snprintf_P(cmnd_scheme, sizeof(cmnd_scheme), PSTR(D_CMND_SCHEME " 0")); - ExecuteCommand(cmnd_scheme, SRC_SWITCH); - } - } else { - ExecuteCommandPower(1, switch_state, SRC_SWITCH); - } - } - else if (is_brightness_change) { - ExecuteCommand(cmnd_dimmer, SRC_SWITCH); - } - else if (Light.power && is_color_change) { - if (0 == Settings.light_scheme) { - if (Settings.light_fade) { - char cmnd_fade[20]; - snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_FADE " 0")); - ExecuteCommand(cmnd_fade, SRC_SWITCH); - } - ExecuteCommand(cmnd_color, SRC_SWITCH); - } - } - } - - SnfL1SerialSendOk(); - - return true; - } - serial_in_byte = 0; - return false; -} - - - -bool SnfL1SetChannels(void) -{ - if (Snfl1.receive_ready || TimeReached(Snfl1.unlock)) { - - uint8_t *scale_col = (uint8_t*)XdrvMailbox.topic; - - char buffer[140]; - snprintf_P(buffer, sizeof(buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"light_type\":1,\"colorR\":%d,\"colorG\":%d,\"colorB\":%d,\"bright\":%d,\"mode\":%d"), - LocalTime(), millis()%1000, - Light.power ? "on" : "off", - scale_col[0], scale_col[1], scale_col[2], - light_state.getDimmer(), - SONOFF_L1_MODE_COLORFUL); - - SnfL1Send(buffer); - - Snfl1.unlock = millis() + 500; - Snfl1.receive_ready = false; - } - return true; -} - -void SnfL1ModuleSelected(void) -{ - if (SONOFF_L1 == my_module_type) { - if ((pin[GPIO_RXD] < 99) && (pin[GPIO_TXD] < 99)) { - SetSerial(19200, TS_SERIAL_8N1); - - light_type = LT_RGB; - light_flg = XLGT_05; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("LGT: Sonoff L1 Found")); - } - } -} - - - - - -bool Xlgt05(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_SERIAL: - result = SnfL1SerialInput(); - break; - case FUNC_SET_CHANNELS: - result = SnfL1SetChannels(); - break; - case FUNC_MODULE_INIT: - SnfL1ModuleSelected(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xlgt_interface.ino" -# 20 "S:/Development/Tasmota/tasmota/xlgt_interface.ino" -#ifdef USE_LIGHT - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xlgt_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xlgt_func_ptr[])(uint8_t) = { -#endif - -#ifdef XLGT_01 - &Xlgt01, -#endif - -#ifdef XLGT_02 - &Xlgt02, -#endif - -#ifdef XLGT_03 - &Xlgt03, -#endif - -#ifdef XLGT_04 - &Xlgt04, -#endif - -#ifdef XLGT_05 - &Xlgt05, -#endif - -#ifdef XLGT_06 - &Xlgt06, -#endif - -#ifdef XLGT_07 - &Xlgt07, -#endif - -#ifdef XLGT_08 - &Xlgt08, -#endif - -#ifdef XLGT_09 - &Xlgt09, -#endif - -#ifdef XLGT_10 - &Xlgt10, -#endif - -#ifdef XLGT_11 - &Xlgt11, -#endif - -#ifdef XLGT_12 - &Xlgt12, -#endif - -#ifdef XLGT_13 - &Xlgt13, -#endif - -#ifdef XLGT_14 - &Xlgt14, -#endif - -#ifdef XLGT_15 - &Xlgt15, -#endif - -#ifdef XLGT_16 - &Xlgt16 -#endif -}; - -const uint8_t xlgt_present = sizeof(xlgt_func_ptr) / sizeof(xlgt_func_ptr[0]); - -uint8_t xlgt_active = 0; - -bool XlgtCall(uint8_t function) -{ - DEBUG_TRACE_LOG(PSTR("LGT: %d"), function); - - if (FUNC_MODULE_INIT == function) { - for (uint32_t x = 0; x < xlgt_present; x++) { - xlgt_func_ptr[x](function); - if (light_flg) { - xlgt_active = x; - return true; - } - } - } - else if (light_flg) { - return xlgt_func_ptr[xlgt_active](function); - } - return false; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_01_hlw8012.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_01_hlw8012.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_HLW8012 - - - - - - -#define XNRG_01 1 - - -#define HLW_PREF 10000 -#define HLW_UREF 2200 -#define HLW_IREF 4545 - - -#define HJL_PREF 1362 -#define HJL_UREF 822 -#define HJL_IREF 3300 - -#define HLW_POWER_PROBE_TIME 10 -#define HLW_SAMPLE_COUNT 10 - - - -struct HLW { -#ifdef HLW_DEBUG - unsigned long debug[HLW_SAMPLE_COUNT]; -#endif - unsigned long cf_pulse_length = 0; - unsigned long cf_pulse_last_time = 0; - unsigned long cf_power_pulse_length = 0; - - unsigned long cf1_pulse_length = 0; - unsigned long cf1_pulse_last_time = 0; - unsigned long cf1_summed_pulse_length = 0; - unsigned long cf1_pulse_counter = 0; - unsigned long cf1_voltage_pulse_length = 0; - unsigned long cf1_current_pulse_length = 0; - - unsigned long energy_period_counter = 0; - - unsigned long power_ratio = 0; - unsigned long voltage_ratio = 0; - unsigned long current_ratio = 0; - - uint8_t model_type = 0; - uint8_t cf1_timer = 0; - uint8_t power_retry = 0; - bool select_ui_flag = false; - bool ui_flag = true; - bool load_off = true; -} Hlw; - - -#ifndef USE_WS2812_DMA -void HlwCfInterrupt(void) ICACHE_RAM_ATTR; -void HlwCf1Interrupt(void) ICACHE_RAM_ATTR; -#endif - -void HlwCfInterrupt(void) -{ - unsigned long us = micros(); - - if (Hlw.load_off) { - Hlw.cf_pulse_last_time = us; - Hlw.load_off = false; - } else { - Hlw.cf_pulse_length = us - Hlw.cf_pulse_last_time; - Hlw.cf_pulse_last_time = us; - Hlw.energy_period_counter++; - } - Energy.data_valid[0] = 0; -} - -void HlwCf1Interrupt(void) -{ - unsigned long us = micros(); - - Hlw.cf1_pulse_length = us - Hlw.cf1_pulse_last_time; - Hlw.cf1_pulse_last_time = us; - if ((Hlw.cf1_timer > 2) && (Hlw.cf1_timer < 8)) { - Hlw.cf1_summed_pulse_length += Hlw.cf1_pulse_length; -#ifdef HLW_DEBUG - Hlw.debug[Hlw.cf1_pulse_counter] = Hlw.cf1_pulse_length; -#endif - Hlw.cf1_pulse_counter++; - if (HLW_SAMPLE_COUNT == Hlw.cf1_pulse_counter) { - Hlw.cf1_timer = 8; - } - } - Energy.data_valid[0] = 0; -} - - - -void HlwEvery200ms(void) -{ - unsigned long cf1_pulse_length = 0; - unsigned long hlw_w = 0; - unsigned long hlw_u = 0; - unsigned long hlw_i = 0; - - if (micros() - Hlw.cf_pulse_last_time > (HLW_POWER_PROBE_TIME * 1000000)) { - Hlw.cf_pulse_length = 0; - Hlw.load_off = true; - } - Hlw.cf_power_pulse_length = Hlw.cf_pulse_length; - - if (Hlw.cf_power_pulse_length && Energy.power_on && !Hlw.load_off) { - hlw_w = (Hlw.power_ratio * Settings.energy_power_calibration) / Hlw.cf_power_pulse_length ; - Energy.active_power[0] = (float)hlw_w / 10; - Hlw.power_retry = 1; - } else { - if (Hlw.power_retry) { - Hlw.power_retry--; - } else { - Energy.active_power[0] = 0; - } - } - - if (pin[GPIO_NRG_CF1] < 99) { - Hlw.cf1_timer++; - if (Hlw.cf1_timer >= 8) { - Hlw.cf1_timer = 0; - Hlw.select_ui_flag = (Hlw.select_ui_flag) ? false : true; - DigitalWrite(GPIO_NRG_SEL, Hlw.select_ui_flag); - - if (Hlw.cf1_pulse_counter) { - cf1_pulse_length = Hlw.cf1_summed_pulse_length / Hlw.cf1_pulse_counter; - } - -#ifdef HLW_DEBUG - - char stemp[100]; - stemp[0] = '\0'; - for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%s %d"), stemp, Hlw.debug[i]); - } - for (uint32_t i = 0; i < Hlw.cf1_pulse_counter; i++) { - for (uint32_t j = i + 1; j < Hlw.cf1_pulse_counter; j++) { - if (Hlw.debug[i] > Hlw.debug[j]) { - std::swap(Hlw.debug[i], Hlw.debug[j]); - } - } - } - unsigned long median = Hlw.debug[(Hlw.cf1_pulse_counter +1) / 2]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: power %d, ui %d, cnt %d, smpl%s, sum %d, mean %d, median %d"), - Hlw.cf_power_pulse_length , Hlw.select_ui_flag, Hlw.cf1_pulse_counter, stemp, Hlw.cf1_summed_pulse_length, cf1_pulse_length, median); -#endif - - if (Hlw.select_ui_flag == Hlw.ui_flag) { - Hlw.cf1_voltage_pulse_length = cf1_pulse_length; - - if (Hlw.cf1_voltage_pulse_length && Energy.power_on) { - hlw_u = (Hlw.voltage_ratio * Settings.energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; - Energy.voltage[0] = (float)hlw_u / 10; - } else { - Energy.voltage[0] = 0; - } - - } else { - Hlw.cf1_current_pulse_length = cf1_pulse_length; - - if (Hlw.cf1_current_pulse_length && Energy.active_power[0]) { - hlw_i = (Hlw.current_ratio * Settings.energy_current_calibration) / Hlw.cf1_current_pulse_length; - Energy.current[0] = (float)hlw_i / 1000; - } else { - Energy.current[0] = 0; - } - - } - Hlw.cf1_summed_pulse_length = 0; - Hlw.cf1_pulse_counter = 0; - } - } -} - -void HlwEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - Hlw.cf1_voltage_pulse_length = 0; - Hlw.cf1_current_pulse_length = 0; - Hlw.cf_power_pulse_length = 0; - } else { - unsigned long hlw_len; - - if (Hlw.energy_period_counter) { - hlw_len = 10000 / Hlw.energy_period_counter; - Hlw.energy_period_counter = 0; - if (hlw_len) { - Energy.kWhtoday_delta += ((Hlw.power_ratio * Settings.energy_power_calibration) / hlw_len) / 36; - EnergyUpdateToday(); - } - } - } -} - -void HlwSnsInit(void) -{ - if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) { - Settings.energy_power_calibration = HLW_PREF_PULSE; - Settings.energy_voltage_calibration = HLW_UREF_PULSE; - Settings.energy_current_calibration = HLW_IREF_PULSE; - } - - if (Hlw.model_type) { - Hlw.power_ratio = HJL_PREF; - Hlw.voltage_ratio = HJL_UREF; - Hlw.current_ratio = HJL_IREF; - } else { - Hlw.power_ratio = HLW_PREF; - Hlw.voltage_ratio = HLW_UREF; - Hlw.current_ratio = HLW_IREF; - } - - if (pin[GPIO_NRG_SEL] < 99) { - pinMode(pin[GPIO_NRG_SEL], OUTPUT); - digitalWrite(pin[GPIO_NRG_SEL], Hlw.select_ui_flag); - } - if (pin[GPIO_NRG_CF1] < 99) { - pinMode(pin[GPIO_NRG_CF1], INPUT_PULLUP); - attachInterrupt(pin[GPIO_NRG_CF1], HlwCf1Interrupt, FALLING); - } - pinMode(pin[GPIO_HLW_CF], INPUT_PULLUP); - attachInterrupt(pin[GPIO_HLW_CF], HlwCfInterrupt, FALLING); -} - -void HlwDrvInit(void) -{ - Hlw.model_type = 0; - if (pin[GPIO_HJL_CF] < 99) { - pin[GPIO_HLW_CF] = pin[GPIO_HJL_CF]; - pin[GPIO_HJL_CF] = 99; - Hlw.model_type = 1; - } - - if (pin[GPIO_HLW_CF] < 99) { - - Hlw.ui_flag = true; - if (pin[GPIO_NRG_SEL_INV] < 99) { - pin[GPIO_NRG_SEL] = pin[GPIO_NRG_SEL_INV]; - pin[GPIO_NRG_SEL_INV] = 99; - Hlw.ui_flag = false; - } - - if (pin[GPIO_NRG_CF1] < 99) { - if (99 == pin[GPIO_NRG_SEL]) { - Energy.current_available = false; - } - } else { - Energy.current_available = false; - Energy.voltage_available = false; - } - - energy_flg = XNRG_01; - } -} - -bool HlwCommand(void) -{ - bool serviced = true; - - if ((CMND_POWERCAL == Energy.command_code) || (CMND_VOLTAGECAL == Energy.command_code) || (CMND_CURRENTCAL == Energy.command_code)) { - - } - else if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) { - Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio; - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) { - Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio; - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) { - Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg01(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_200_MSECOND: - HlwEvery200ms(); - break; - case FUNC_ENERGY_EVERY_SECOND: - HlwEverySecond(); - break; - case FUNC_COMMAND: - result = HlwCommand(); - break; - case FUNC_INIT: - HlwSnsInit(); - break; - case FUNC_PRE_INIT: - HlwDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_02_cse7766.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_02_cse7766.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_CSE7766 - - - - - - - -#define XNRG_02 2 - -#define CSE_MAX_INVALID_POWER 128 - -#define CSE_NOT_CALIBRATED 0xAA - -#define CSE_PULSES_NOT_INITIALIZED -1 - -#define CSE_PREF 1000 -#define CSE_UREF 100 - -#define CSE_BUFFER_SIZE 25 - -#include - -TasmotaSerial *CseSerial = nullptr; - -struct CSE { - long voltage_cycle = 0; - long current_cycle = 0; - long power_cycle = 0; - long power_cycle_first = 0; - long cf_pulses = 0; - long cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; - - int byte_counter = 0; - uint8_t *rx_buffer = nullptr; - uint8_t power_invalid = 0; - bool received = false; -} Cse; - -void CseReceived(void) -{ - - - - - - - uint8_t header = Cse.rx_buffer[0]; - if ((header & 0xFC) == 0xFC) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Abnormal hardware")); - return; - } - - - if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { - long voltage_coefficient = 191200; - if (CSE_NOT_CALIBRATED != header) { - voltage_coefficient = Cse.rx_buffer[2] << 16 | Cse.rx_buffer[3] << 8 | Cse.rx_buffer[4]; - } - Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF; - } - if (HLW_IREF_PULSE == Settings.energy_current_calibration) { - long current_coefficient = 16140; - if (CSE_NOT_CALIBRATED != header) { - current_coefficient = Cse.rx_buffer[8] << 16 | Cse.rx_buffer[9] << 8 | Cse.rx_buffer[10]; - } - Settings.energy_current_calibration = current_coefficient; - } - if (HLW_PREF_PULSE == Settings.energy_power_calibration) { - long power_coefficient = 5364000; - if (CSE_NOT_CALIBRATED != header) { - power_coefficient = Cse.rx_buffer[14] << 16 | Cse.rx_buffer[15] << 8 | Cse.rx_buffer[16]; - } - Settings.energy_power_calibration = power_coefficient / CSE_PREF; - } - - uint8_t adjustement = Cse.rx_buffer[20]; - Cse.voltage_cycle = Cse.rx_buffer[5] << 16 | Cse.rx_buffer[6] << 8 | Cse.rx_buffer[7]; - Cse.current_cycle = Cse.rx_buffer[11] << 16 | Cse.rx_buffer[12] << 8 | Cse.rx_buffer[13]; - Cse.power_cycle = Cse.rx_buffer[17] << 16 | Cse.rx_buffer[18] << 8 | Cse.rx_buffer[19]; - Cse.cf_pulses = Cse.rx_buffer[21] << 8 | Cse.rx_buffer[22]; - - if (Energy.power_on) { - if (adjustement & 0x40) { - Energy.voltage[0] = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle; - } - if (adjustement & 0x10) { - Cse.power_invalid = 0; - if ((header & 0xF2) == 0xF2) { - Energy.active_power[0] = 0; - } else { - if (0 == Cse.power_cycle_first) { Cse.power_cycle_first = Cse.power_cycle; } - if (Cse.power_cycle_first != Cse.power_cycle) { - Cse.power_cycle_first = -1; - Energy.active_power[0] = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle; - } else { - Energy.active_power[0] = 0; - } - } - } else { - if (Cse.power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { - Cse.power_invalid++; - } else { - Cse.power_cycle_first = 0; - Energy.active_power[0] = 0; - } - } - if (adjustement & 0x20) { - if (0 == Energy.active_power[0]) { - Energy.current[0] = 0; - } else { - Energy.current[0] = (float)Settings.energy_current_calibration / (float)Cse.current_cycle; - } - } - } else { - Cse.power_cycle_first = 0; - Energy.voltage[0] = 0; - Energy.active_power[0] = 0; - Energy.current[0] = 0; - } -} - -bool CseSerialInput(void) -{ - while (CseSerial->available()) { - yield(); - uint8_t serial_in_byte = CseSerial->read(); - - if (Cse.received) { - Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; - if (24 == Cse.byte_counter) { - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Cse.rx_buffer, 24); - - uint8_t checksum = 0; - for (uint32_t i = 2; i < 23; i++) { checksum += Cse.rx_buffer[i]; } - if (checksum == Cse.rx_buffer[23]) { - Energy.data_valid[0] = 0; - CseReceived(); - Cse.received = false; - return true; - } else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: " D_CHECKSUM_FAILURE)); - do { - memmove(Cse.rx_buffer, Cse.rx_buffer +1, 24); - Cse.byte_counter--; - } while ((Cse.byte_counter > 2) && (0x5A != Cse.rx_buffer[1])); - if (0x5A != Cse.rx_buffer[1]) { - Cse.received = false; - Cse.byte_counter = 0; - } - } - } - } else { - if ((0x5A == serial_in_byte) && (1 == Cse.byte_counter)) { - Cse.received = true; - } else { - Cse.byte_counter = 0; - } - Cse.rx_buffer[Cse.byte_counter++] = serial_in_byte; - } - } -} - - - -void CseEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - Cse.voltage_cycle = 0; - Cse.current_cycle = 0; - Cse.power_cycle = 0; - } else { - long cf_frequency = 0; - - if (CSE_PULSES_NOT_INITIALIZED == Cse.cf_pulses_last_time) { - Cse.cf_pulses_last_time = Cse.cf_pulses; - } else { - if (Cse.cf_pulses < Cse.cf_pulses_last_time) { - cf_frequency = (65536 - Cse.cf_pulses_last_time) + Cse.cf_pulses; - } else { - cf_frequency = Cse.cf_pulses - Cse.cf_pulses_last_time; - } - if (cf_frequency && Energy.active_power[0]) { - unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; - - - - if (delta <= (4000*100/36) * 10 ) { - Cse.cf_pulses_last_time = Cse.cf_pulses; - Energy.kWhtoday_delta += delta; - } - else { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("CSE: Load overflow")); - Cse.cf_pulses_last_time = CSE_PULSES_NOT_INITIALIZED; - } - EnergyUpdateToday(); - } - } - } -} - -void CseSnsInit(void) -{ - - - CseSerial = new TasmotaSerial(pin[GPIO_CSE7766_RX], -1, 1); - if (CseSerial->begin(4800, 2)) { - if (CseSerial->hardwareSerial()) { - SetSerial(4800, TS_SERIAL_8E1); - ClaimSerial(); - } - if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { - Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; - } - Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER]; - } else { - energy_flg = ENERGY_NONE; - } -} - -void CseDrvInit(void) -{ - Cse.rx_buffer = (uint8_t*)(malloc(CSE_BUFFER_SIZE)); - if (Cse.rx_buffer != nullptr) { - - if (pin[GPIO_CSE7766_RX] < 99) { - energy_flg = XNRG_02; - } - } -} - -bool CseCommand(void) -{ - bool serviced = true; - - if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.power_cycle) { - Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF; - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.voltage_cycle) { - Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF; - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Cse.current_cycle) { - Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - if (CseSerial) { CseSerialInput(); } - break; - case FUNC_ENERGY_EVERY_SECOND: - CseEverySecond(); - break; - case FUNC_COMMAND: - result = CseCommand(); - break; - case FUNC_INIT: - CseSnsInit(); - break; - case FUNC_PRE_INIT: - CseDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_03_pzem004t.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_03_pzem004t.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM004T -# 31 "S:/Development/Tasmota/tasmota/xnrg_03_pzem004t.ino" -#define XNRG_03 3 - -const uint32_t PZEM_STABILIZE = 30; - -#include - -TasmotaSerial *PzemSerial = nullptr; - -#define PZEM_VOLTAGE (uint8_t)0xB0 -#define RESP_VOLTAGE (uint8_t)0xA0 - -#define PZEM_CURRENT (uint8_t)0xB1 -#define RESP_CURRENT (uint8_t)0xA1 - -#define PZEM_POWER (uint8_t)0xB2 -#define RESP_POWER (uint8_t)0xA2 - -#define PZEM_ENERGY (uint8_t)0xB3 -#define RESP_ENERGY (uint8_t)0xA3 - -#define PZEM_SET_ADDRESS (uint8_t)0xB4 -#define RESP_SET_ADDRESS (uint8_t)0xA4 - -#define PZEM_POWER_ALARM (uint8_t)0xB5 -#define RESP_POWER_ALARM (uint8_t)0xA5 - -#define PZEM_DEFAULT_READ_TIMEOUT 500 - - - -struct PZEM { - float energy = 0; - float last_energy = 0; - uint8_t send_retry = 0; - uint8_t read_state = 0; - uint8_t phase = 0; - uint8_t address = 0; -} Pzem; - -struct PZEMCommand { - uint8_t command; - uint8_t addr[4]; - uint8_t data; - uint8_t crc; -}; - -uint8_t PzemCrc(uint8_t *data) -{ - uint16_t crc = 0; - for (uint32_t i = 0; i < sizeof(PZEMCommand) -1; i++) { - crc += *data++; - } - return (uint8_t)(crc & 0xFF); -} - -void PzemSend(uint8_t cmd) -{ - PZEMCommand pzem; - - pzem.command = cmd; - pzem.addr[0] = 192; - pzem.addr[1] = 168; - pzem.addr[2] = 1; - pzem.addr[3] = ((PZEM_SET_ADDRESS == cmd) && Pzem.address) ? Pzem.address : 1 + Pzem.phase; - pzem.data = 0; - - uint8_t *bytes = (uint8_t*)&pzem; - pzem.crc = PzemCrc(bytes); - - PzemSerial->flush(); - PzemSerial->write(bytes, sizeof(pzem)); - - Pzem.address = 0; -} - -bool PzemReceiveReady(void) -{ - return PzemSerial->available() >= (int)sizeof(PZEMCommand); -} - -bool PzemRecieve(uint8_t resp, float *data) -{ -# 124 "S:/Development/Tasmota/tasmota/xnrg_03_pzem004t.ino" - uint8_t buffer[sizeof(PZEMCommand)] = { 0 }; - - unsigned long start = millis(); - uint8_t len = 0; - while ((len < sizeof(PZEMCommand)) && (millis() - start < PZEM_DEFAULT_READ_TIMEOUT)) { - if (PzemSerial->available() > 0) { - uint8_t c = (uint8_t)PzemSerial->read(); - if (!len && ((c & 0xF8) != 0xA0)) { - continue; - } - buffer[len++] = c; - } - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, len); - - if (len != sizeof(PZEMCommand)) { - - return false; - } - if (buffer[6] != PzemCrc(buffer)) { - - return false; - } - if (buffer[0] != resp) { - - return false; - } - - switch (resp) { - case RESP_VOLTAGE: - *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 10.0); - break; - case RESP_CURRENT: - *data = (float)(buffer[1] << 8) + buffer[2] + (buffer[3] / 100.0); - break; - case RESP_POWER: - *data = (float)(buffer[1] << 8) + buffer[2]; - break; - case RESP_ENERGY: - *data = (float)((uint32_t)buffer[1] << 16) + ((uint16_t)buffer[2] << 8) + buffer[3]; - break; - } - return true; -} - - - -const uint8_t pzem_commands[] { PZEM_SET_ADDRESS, PZEM_VOLTAGE, PZEM_CURRENT, PZEM_POWER, PZEM_ENERGY }; -const uint8_t pzem_responses[] { RESP_SET_ADDRESS, RESP_VOLTAGE, RESP_CURRENT, RESP_POWER, RESP_ENERGY }; - -void PzemEvery250ms(void) -{ - bool data_ready = PzemReceiveReady(); - - if (data_ready) { - float value = 0; - if (PzemRecieve(pzem_responses[Pzem.read_state], &value)) { - Energy.data_valid[Pzem.phase] = 0; - switch (Pzem.read_state) { - case 1: - Energy.voltage[Pzem.phase] = value; - break; - case 2: - Energy.current[Pzem.phase] = value; - break; - case 3: - Energy.active_power[Pzem.phase] = value; - break; - case 4: - Pzem.energy += value; - if (Pzem.phase == Energy.phase_count -1) { - if (Pzem.energy > Pzem.last_energy) { - if (uptime > PZEM_STABILIZE) { - EnergyUpdateTotal(Pzem.energy, false); - } - Pzem.last_energy = Pzem.energy; - } - Pzem.energy = 0; - } - break; - } - Pzem.read_state++; - if (5 == Pzem.read_state) { - Pzem.read_state = 1; - } - - - } - } - - if (0 == Pzem.send_retry || data_ready) { - if (1 == Pzem.read_state) { - if (0 == Pzem.phase) { - Pzem.phase = Energy.phase_count -1; - } else { - Pzem.phase--; - } - - - } - - if (Pzem.address) { - Pzem.read_state = 0; - } - - Pzem.send_retry = 5; - PzemSend(pzem_commands[Pzem.read_state]); - } - else { - Pzem.send_retry--; - if ((Energy.phase_count > 1) && (0 == Pzem.send_retry) && (uptime < PZEM_STABILIZE)) { - Energy.phase_count--; - } - } -} - -void PzemSnsInit(void) -{ - - PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); - if (PzemSerial->begin(9600)) { - if (PzemSerial->hardwareSerial()) { - ClaimSerial(); - } - Energy.phase_count = 3; - Pzem.phase = 0; - Pzem.read_state = 1; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemDrvInit(void) -{ - if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_03; - } -} - -bool PzemCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) { - Pzem.address = XdrvMailbox.payload; - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg03(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (PzemSerial && (uptime > 4)) { PzemEvery250ms(); } - break; - case FUNC_COMMAND: - result = PzemCommand(); - break; - case FUNC_INIT: - PzemSnsInit(); - break; - case FUNC_PRE_INIT: - PzemDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_04_mcp39f501.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_04_mcp39f501.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_MCP39F501 - - - - - - - -#define XNRG_04 4 - -#define MCP_BAUDRATE 4800 -#define MCP_TIMEOUT 4 -#define MCP_CALIBRATION_TIMEOUT 2 - -#define MCP_CALIBRATE_POWER 0x001 -#define MCP_CALIBRATE_VOLTAGE 0x002 -#define MCP_CALIBRATE_CURRENT 0x004 -#define MCP_CALIBRATE_FREQUENCY 0x008 -#define MCP_SINGLE_WIRE_FLAG 0x100 - -#define MCP_START_FRAME 0xA5 -#define MCP_ACK_FRAME 0x06 -#define MCP_ERROR_NAK 0x15 -#define MCP_ERROR_CRC 0x51 - -#define MCP_SINGLE_WIRE 0xAB - -#define MCP_SET_ADDRESS 0x41 - -#define MCP_READ 0x4E -#define MCP_READ_16 0x52 -#define MCP_READ_32 0x44 - -#define MCP_WRITE 0x4D -#define MCP_WRITE_16 0x57 -#define MCP_WRITE_32 0x45 - -#define MCP_SAVE_REGISTERS 0x53 - -#define MCP_CALIBRATION_BASE 0x0028 -#define MCP_CALIBRATION_LEN 52 - -#define MCP_FREQUENCY_REF_BASE 0x0094 -#define MCP_FREQUENCY_GAIN_BASE 0x00AE -#define MCP_FREQUENCY_LEN 4 - -#define MCP_BUFFER_SIZE 60 - -#include -TasmotaSerial *McpSerial = nullptr; - -typedef struct mcp_cal_registers_type { - uint16_t gain_current_rms; - uint16_t gain_voltage_rms; - uint16_t gain_active_power; - uint16_t gain_reactive_power; - sint32_t offset_current_rms; - sint32_t offset_active_power; - sint32_t offset_reactive_power; - sint16_t dc_offset_current; - sint16_t phase_compensation; - uint16_t apparent_power_divisor; - - uint32_t system_configuration; - uint16_t dio_configuration; - uint32_t range; - - uint32_t calibration_current; - uint16_t calibration_voltage; - uint32_t calibration_active_power; - uint32_t calibration_reactive_power; - uint16_t accumulation_interval; -} mcp_cal_registers_type; - -char *mcp_buffer = nullptr; -unsigned long mcp_window = 0; -unsigned long mcp_kWhcounter = 0; -uint32_t mcp_system_configuration = 0x03000000; -uint32_t mcp_active_power; - - -uint32_t mcp_current_rms; -uint16_t mcp_voltage_rms; -uint16_t mcp_line_frequency; - -uint8_t mcp_address = 0; -uint8_t mcp_calibration_active = 0; -uint8_t mcp_init = 0; -uint8_t mcp_timeout = 0; -uint8_t mcp_calibrate = 0; -uint8_t mcp_byte_counter = 0; - - - - - - -uint8_t McpChecksum(uint8_t *data) -{ - uint8_t checksum = 0; - uint8_t offset = 0; - uint8_t len = data[1] -1; - - for (uint32_t i = offset; i < len; i++) { checksum += data[i]; } - return checksum; -} - -unsigned long McpExtractInt(char *data, uint8_t offset, uint8_t size) -{ - unsigned long result = 0; - unsigned long pow = 1; - - for (uint32_t i = 0; i < size; i++) { - result = result + (uint8_t)data[offset + i] * pow; - pow = pow * 256; - } - return result; -} - -void McpSetInt(unsigned long value, uint8_t *data, uint8_t offset, size_t size) -{ - for (uint32_t i = 0; i < size; i++) { - data[offset + i] = ((value >> (i * 8)) & 0xFF); - } -} - -void McpSend(uint8_t *data) -{ - if (mcp_timeout) { return; } - mcp_timeout = MCP_TIMEOUT; - - data[0] = MCP_START_FRAME; - data[data[1] -1] = McpChecksum(data); - - - - for (uint32_t i = 0; i < data[1]; i++) { - McpSerial->write(data[i]); - } -} - - - -void McpGetAddress(void) -{ - uint8_t data[] = { MCP_START_FRAME, 7, MCP_SET_ADDRESS, 0x00, 0x26, MCP_READ_16, 0x00 }; - - McpSend(data); -} - -void McpAddressReceive(void) -{ - - mcp_address = mcp_buffer[3]; -} - - - -void McpGetCalibration(void) -{ - if (mcp_calibration_active) { return; } - mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; - - uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, (MCP_CALIBRATION_BASE >> 8) & 0xFF, MCP_CALIBRATION_BASE & 0xFF, MCP_READ, MCP_CALIBRATION_LEN, 0x00 }; - - McpSend(data); -} - -void McpParseCalibration(void) -{ - bool action = false; - mcp_cal_registers_type cal_registers; - - - cal_registers.gain_current_rms = McpExtractInt(mcp_buffer, 2, 2); - cal_registers.gain_voltage_rms = McpExtractInt(mcp_buffer, 4, 2); - cal_registers.gain_active_power = McpExtractInt(mcp_buffer, 6, 2); - cal_registers.gain_reactive_power = McpExtractInt(mcp_buffer, 8, 2); - cal_registers.offset_current_rms = McpExtractInt(mcp_buffer, 10, 4); - cal_registers.offset_active_power = McpExtractInt(mcp_buffer, 14, 4); - cal_registers.offset_reactive_power = McpExtractInt(mcp_buffer, 18, 4); - cal_registers.dc_offset_current = McpExtractInt(mcp_buffer, 22, 2); - cal_registers.phase_compensation = McpExtractInt(mcp_buffer, 24, 2); - cal_registers.apparent_power_divisor = McpExtractInt(mcp_buffer, 26, 2); - - cal_registers.system_configuration = McpExtractInt(mcp_buffer, 28, 4); - cal_registers.dio_configuration = McpExtractInt(mcp_buffer, 32, 2); - cal_registers.range = McpExtractInt(mcp_buffer, 34, 4); - - cal_registers.calibration_current = McpExtractInt(mcp_buffer, 38, 4); - cal_registers.calibration_voltage = McpExtractInt(mcp_buffer, 42, 2); - cal_registers.calibration_active_power = McpExtractInt(mcp_buffer, 44, 4); - cal_registers.calibration_reactive_power = McpExtractInt(mcp_buffer, 48, 4); - cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2); - - if (mcp_calibrate & MCP_CALIBRATE_POWER) { - cal_registers.calibration_active_power = Settings.energy_power_calibration; - if (McpCalibrationCalc(&cal_registers, 16)) { action = true; } - } - if (mcp_calibrate & MCP_CALIBRATE_VOLTAGE) { - cal_registers.calibration_voltage = Settings.energy_voltage_calibration; - if (McpCalibrationCalc(&cal_registers, 0)) { action = true; } - } - if (mcp_calibrate & MCP_CALIBRATE_CURRENT) { - cal_registers.calibration_current = Settings.energy_current_calibration; - if (McpCalibrationCalc(&cal_registers, 8)) { action = true; } - } - mcp_timeout = 0; - if (action) { McpSetCalibration(&cal_registers); } - - mcp_calibrate = 0; - - Settings.energy_power_calibration = cal_registers.calibration_active_power; - Settings.energy_voltage_calibration = cal_registers.calibration_voltage; - Settings.energy_current_calibration = cal_registers.calibration_current; - - mcp_system_configuration = cal_registers.system_configuration; - - if (mcp_system_configuration & MCP_SINGLE_WIRE_FLAG) { - mcp_system_configuration &= ~MCP_SINGLE_WIRE_FLAG; - McpSetSystemConfiguration(2); - } -} - -bool McpCalibrationCalc(struct mcp_cal_registers_type *cal_registers, uint8_t range_shift) -{ - uint32_t measured; - uint32_t expected; - uint16_t *gain; - uint32_t new_gain; - - if (range_shift == 0) { - measured = mcp_voltage_rms; - expected = cal_registers->calibration_voltage; - gain = &(cal_registers->gain_voltage_rms); - } else if (range_shift == 8) { - measured = mcp_current_rms; - expected = cal_registers->calibration_current; - gain = &(cal_registers->gain_current_rms); - } else if (range_shift == 16) { - measured = mcp_active_power; - expected = cal_registers->calibration_active_power; - gain = &(cal_registers->gain_active_power); - } else { - return false; - } - - if (measured == 0) { - return false; - } - - uint32_t range = (cal_registers->range >> range_shift) & 0xFF; - -calc: - new_gain = (*gain) * expected / measured; - - if (new_gain < 25000) { - range++; - if (measured > 6) { - measured = measured / 2; - goto calc; - } - } - - if (new_gain > 55000) { - range--; - measured = measured * 2; - goto calc; - } - - *gain = new_gain; - uint32_t old_range = (cal_registers->range >> range_shift) & 0xFF; - cal_registers->range = cal_registers->range ^ (old_range << range_shift); - cal_registers->range = cal_registers->range | (range << range_shift); - - return true; -} - - - - - - -void McpSetCalibration(struct mcp_cal_registers_type *cal_registers) -{ - uint8_t data[7 + MCP_CALIBRATION_LEN + 2 + 1]; - - data[1] = sizeof(data); - data[2] = MCP_SET_ADDRESS; - data[3] = (MCP_CALIBRATION_BASE >> 8) & 0xFF; - data[4] = (MCP_CALIBRATION_BASE >> 0) & 0xFF; - - data[5] = MCP_WRITE; - data[6] = MCP_CALIBRATION_LEN; - - McpSetInt(cal_registers->gain_current_rms, data, 0+7, 2); - McpSetInt(cal_registers->gain_voltage_rms, data, 2+7, 2); - McpSetInt(cal_registers->gain_active_power, data, 4+7, 2); - McpSetInt(cal_registers->gain_reactive_power, data, 6+7, 2); - McpSetInt(cal_registers->offset_current_rms, data, 8+7, 4); - McpSetInt(cal_registers->offset_active_power, data, 12+7, 4); - McpSetInt(cal_registers->offset_reactive_power, data, 16+7, 4); - McpSetInt(cal_registers->dc_offset_current, data, 20+7, 2); - McpSetInt(cal_registers->phase_compensation, data, 22+7, 2); - McpSetInt(cal_registers->apparent_power_divisor, data, 24+7, 2); - - McpSetInt(cal_registers->system_configuration, data, 26+7, 4); - McpSetInt(cal_registers->dio_configuration, data, 30+7, 2); - McpSetInt(cal_registers->range, data, 32+7, 4); - - McpSetInt(cal_registers->calibration_current, data, 36+7, 4); - McpSetInt(cal_registers->calibration_voltage, data, 40+7, 2); - McpSetInt(cal_registers->calibration_active_power, data, 42+7, 4); - McpSetInt(cal_registers->calibration_reactive_power, data, 46+7, 4); - McpSetInt(cal_registers->accumulation_interval, data, 50+7, 2); - - data[MCP_CALIBRATION_LEN+7] = MCP_SAVE_REGISTERS; - data[MCP_CALIBRATION_LEN+8] = mcp_address; - - McpSend(data); -} - - - -void McpSetSystemConfiguration(uint16 interval) -{ - - uint8_t data[17]; - - data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; - data[ 3] = 0x00; - data[ 4] = 0x42; - data[ 5] = MCP_WRITE_32; - data[ 6] = (mcp_system_configuration >> 24) & 0xFF; - data[ 7] = (mcp_system_configuration >> 16) & 0xFF; - data[ 8] = (mcp_system_configuration >> 8) & 0xFF; - data[ 9] = (mcp_system_configuration >> 0) & 0xFF; - data[10] = MCP_SET_ADDRESS; - data[11] = 0x00; - data[12] = 0x5A; - data[13] = MCP_WRITE_16; - data[14] = (interval >> 8) & 0xFF; - data[15] = (interval >> 0) & 0xFF; - - McpSend(data); -} - - - -void McpGetFrequency(void) -{ - if (mcp_calibration_active) { return; } - mcp_calibration_active = MCP_CALIBRATION_TIMEOUT; - - uint8_t data[] = { MCP_START_FRAME, 11, MCP_SET_ADDRESS, (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF, MCP_FREQUENCY_REF_BASE & 0xFF, MCP_READ_16, - MCP_SET_ADDRESS, (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF, MCP_FREQUENCY_GAIN_BASE & 0xFF, MCP_READ_16, 0x00 }; - - McpSend(data); -} - -void McpParseFrequency(void) -{ - - uint16_t line_frequency_ref = mcp_buffer[2] * 256 + mcp_buffer[3]; - uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5]; - - if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) { - line_frequency_ref = Settings.energy_frequency_calibration; - - if ((0xFFFF == mcp_line_frequency) || (0 == gain_line_frequency)) { - mcp_line_frequency = 50000; - gain_line_frequency = 0x8000; - } - gain_line_frequency = gain_line_frequency * line_frequency_ref / mcp_line_frequency; - - mcp_timeout = 0; - McpSetFrequency(line_frequency_ref, gain_line_frequency); - } - - Settings.energy_frequency_calibration = line_frequency_ref; - - mcp_calibrate = 0; -} - -void McpSetFrequency(uint16_t line_frequency_ref, uint16_t gain_line_frequency) -{ - - uint8_t data[17]; - - data[ 1] = sizeof(data); - data[ 2] = MCP_SET_ADDRESS; - data[ 3] = (MCP_FREQUENCY_REF_BASE >> 8) & 0xFF; - data[ 4] = (MCP_FREQUENCY_REF_BASE >> 0) & 0xFF; - - data[ 5] = MCP_WRITE_16; - data[ 6] = (line_frequency_ref >> 8) & 0xFF; - data[ 7] = (line_frequency_ref >> 0) & 0xFF; - - data[ 8] = MCP_SET_ADDRESS; - data[ 9] = (MCP_FREQUENCY_GAIN_BASE >> 8) & 0xFF; - data[10] = (MCP_FREQUENCY_GAIN_BASE >> 0) & 0xFF; - - data[11] = MCP_WRITE_16; - data[12] = (gain_line_frequency >> 8) & 0xFF; - data[13] = (gain_line_frequency >> 0) & 0xFF; - - data[14] = MCP_SAVE_REGISTERS; - data[15] = mcp_address; - - McpSend(data); -} - - - -void McpGetData(void) -{ - uint8_t data[] = { MCP_START_FRAME, 8, MCP_SET_ADDRESS, 0x00, 0x04, MCP_READ, 22, 0x00 }; - - McpSend(data); -} - -void McpParseData(void) -{ - - - - - - mcp_current_rms = McpExtractInt(mcp_buffer, 2, 4); - mcp_voltage_rms = McpExtractInt(mcp_buffer, 6, 2); - mcp_active_power = McpExtractInt(mcp_buffer, 8, 4); - - - mcp_line_frequency = McpExtractInt(mcp_buffer, 22, 2); - - if (Energy.power_on) { - Energy.data_valid[0] = 0; - Energy.frequency[0] = (float)mcp_line_frequency / 1000; - Energy.voltage[0] = (float)mcp_voltage_rms / 10; - Energy.active_power[0] = (float)mcp_active_power / 100; - if (0 == Energy.active_power[0]) { - Energy.current[0] = 0; - } else { - Energy.current[0] = (float)mcp_current_rms / 10000; - } - } else { - Energy.data_valid[0] = ENERGY_WATCHDOG; - } -} - - - -void McpSerialInput(void) -{ - while ((McpSerial->available()) && (mcp_byte_counter < MCP_BUFFER_SIZE)) { - yield(); - mcp_buffer[mcp_byte_counter++] = McpSerial->read(); - mcp_window = millis(); - } - - - if ((mcp_byte_counter) && (millis() - mcp_window > (24000 / MCP_BAUDRATE) +1)) { - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter); - - if (MCP_BUFFER_SIZE == mcp_byte_counter) { - - } - else if (1 == mcp_byte_counter) { - if (MCP_ERROR_CRC == mcp_buffer[0]) { - - mcp_timeout = 0; - } - else if (MCP_ERROR_NAK == mcp_buffer[0]) { - - mcp_timeout = 0; - } - } - else if (MCP_ACK_FRAME == mcp_buffer[0]) { - if (mcp_byte_counter == mcp_buffer[1]) { - - if (McpChecksum((uint8_t *)mcp_buffer) != mcp_buffer[mcp_byte_counter -1]) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: " D_CHECKSUM_FAILURE)); - } else { - if (5 == mcp_buffer[1]) { McpAddressReceive(); } - if (25 == mcp_buffer[1]) { McpParseData(); } - if (MCP_CALIBRATION_LEN + 3 == mcp_buffer[1]) { McpParseCalibration(); } - if (MCP_FREQUENCY_LEN + 3 == mcp_buffer[1]) { McpParseFrequency(); } - } - - } - mcp_timeout = 0; - } - else if (MCP_SINGLE_WIRE == mcp_buffer[0]) { - mcp_timeout = 0; - } - - mcp_byte_counter = 0; - McpSerial->flush(); - } -} - - - -void McpEverySecond(void) -{ - if (Energy.data_valid[0] > ENERGY_WATCHDOG) { - mcp_voltage_rms = 0; - mcp_current_rms = 0; - mcp_active_power = 0; - mcp_line_frequency = 0; - } - - if (mcp_active_power) { - Energy.kWhtoday_delta += ((mcp_active_power * 10) / 36); - EnergyUpdateToday(); - } - - if (mcp_timeout) { - mcp_timeout--; - } - else if (mcp_calibration_active) { - mcp_calibration_active--; - } - else if (mcp_init) { - if (2 == mcp_init) { - McpGetCalibration(); - } - else if (1 == mcp_init) { - McpGetFrequency(); - } - mcp_init--; - } - else if (!mcp_address) { - McpGetAddress(); - } - else { - McpGetData(); - } -} - -void McpSnsInit(void) -{ - - McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1); - if (McpSerial->begin(MCP_BAUDRATE)) { - if (McpSerial->hardwareSerial()) { - ClaimSerial(); - mcp_buffer = serial_in_buffer; - } else { - mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE)); - } - DigitalWrite(GPIO_MCP39F5_RST, 1); - } else { - energy_flg = ENERGY_NONE; - } -} - -void McpDrvInit(void) -{ - if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) { - if (pin[GPIO_MCP39F5_RST] < 99) { - pinMode(pin[GPIO_MCP39F5_RST], OUTPUT); - digitalWrite(pin[GPIO_MCP39F5_RST], 0); - } - mcp_calibrate = 0; - mcp_timeout = 2; - mcp_init = 2; - energy_flg = XNRG_04; - } -} - -bool McpCommand(void) -{ - bool serviced = true; - unsigned long value = 0; - - if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_active_power) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100); - if ((value > 100) && (value < 200000)) { - Settings.energy_power_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_POWER; - McpGetCalibration(); - } - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_voltage_rms) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > 1000) && (value < 2600)) { - Settings.energy_voltage_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_VOLTAGE; - McpGetCalibration(); - } - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_current_rms) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10); - if ((value > 100) && (value < 80000)) { - Settings.energy_current_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_CURRENT; - McpGetCalibration(); - } - } - } - else if (CMND_FREQUENCYSET == Energy.command_code) { - if (XdrvMailbox.data_len && mcp_line_frequency) { - value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000); - if ((value > 45000) && (value < 65000)) { - Settings.energy_frequency_calibration = value; - mcp_calibrate |= MCP_CALIBRATE_FREQUENCY; - McpGetFrequency(); - } - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg04(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_LOOP: - if (McpSerial) { McpSerialInput(); } - break; - case FUNC_ENERGY_EVERY_SECOND: - if (McpSerial) { McpEverySecond(); } - break; - case FUNC_COMMAND: - result = McpCommand(); - break; - case FUNC_INIT: - McpSnsInit(); - break; - case FUNC_PRE_INIT: - McpDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM_AC -# 33 "S:/Development/Tasmota/tasmota/xnrg_05_pzem_ac.ino" -#define XNRG_05 5 - -const uint8_t PZEM_AC_DEVICE_ADDRESS = 0x01; -const uint32_t PZEM_AC_STABILIZE = 30; - -#include -TasmotaModbus *PzemAcModbus; - -struct PZEMAC { - float energy = 0; - float last_energy = 0; - uint8_t send_retry = 0; - uint8_t phase = 0; - uint8_t address = 0; - uint8_t address_step = ADDR_IDLE; -} PzemAc; - -void PzemAcEverySecond(void) -{ - bool data_ready = PzemAcModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[30]; - - uint8_t registers = 10; - if (ADDR_RECEIVE == PzemAc.address_step) { - registers = 2; - PzemAc.address_step--; - } - uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, registers); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemAcModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAC: PzemAc %d error %d"), PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, error); - } else { - Energy.data_valid[PzemAc.phase] = 0; - if (10 == registers) { - - - - - - Energy.voltage[PzemAc.phase] = (float)((buffer[3] << 8) + buffer[4]) / 10.0; - Energy.current[PzemAc.phase] = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; - Energy.active_power[PzemAc.phase] = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; - Energy.frequency[PzemAc.phase] = (float)((buffer[17] << 8) + buffer[18]) / 10.0; - Energy.power_factor[PzemAc.phase] = (float)((buffer[19] << 8) + buffer[20]) / 100.0; - - PzemAc.energy += (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); - if (PzemAc.phase == Energy.phase_count -1) { - if (PzemAc.energy > PzemAc.last_energy) { - if (uptime > PZEM_AC_STABILIZE) { - EnergyUpdateTotal(PzemAc.energy, false); - } - PzemAc.last_energy = PzemAc.energy; - } - PzemAc.energy = 0; - } - - } - } - } - - if (0 == PzemAc.send_retry || data_ready) { - if (0 == PzemAc.phase) { - PzemAc.phase = Energy.phase_count -1; - } else { - PzemAc.phase--; - } - PzemAc.send_retry = ENERGY_WATCHDOG; - if (ADDR_SEND == PzemAc.address_step) { - PzemAcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemAc.address); - PzemAc.address_step--; - } else { - PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS + PzemAc.phase, 0x04, 0, 10); - } - } - else { - PzemAc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemAc.send_retry) && (uptime < PZEM_AC_STABILIZE)) { - Energy.phase_count--; - } - } -} - -void PzemAcSnsInit(void) -{ - PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); - uint8_t result = PzemAcModbus->Begin(9600); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.phase_count = 3; - PzemAc.phase = 0; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemAcDrvInit(void) -{ - if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_05; - } -} - -bool PzemAcCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - PzemAc.address = XdrvMailbox.payload; - PzemAc.address_step = ADDR_SEND; - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg05(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { PzemAcEverySecond(); } - break; - case FUNC_COMMAND: - result = PzemAcCommand(); - break; - case FUNC_INIT: - PzemAcSnsInit(); - break; - case FUNC_PRE_INIT: - PzemAcDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM_DC -# 32 "S:/Development/Tasmota/tasmota/xnrg_06_pzem_dc.ino" -#define XNRG_06 6 - -const uint8_t PZEM_DC_DEVICE_ADDRESS = 0x01; -const uint32_t PZEM_DC_STABILIZE = 30; - -#include -TasmotaModbus *PzemDcModbus; - -struct PZEMDC { - float energy = 0; - float last_energy = 0; - uint8_t send_retry = 0; - uint8_t channel = 0; - uint8_t address = 0; - uint8_t address_step = ADDR_IDLE; -} PzemDc; - -void PzemDcEverySecond(void) -{ - bool data_ready = PzemDcModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[26]; - - uint8_t registers = 8; - if (ADDR_RECEIVE == PzemDc.address_step) { - registers = 2; - PzemDc.address_step--; - } - uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, registers); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, PzemDcModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PDC: PzemDc %d error %d"), PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, error); - } else { - Energy.data_valid[PzemDc.channel] = 0; - if (8 == registers) { - - - - - - Energy.voltage[PzemDc.channel] = (float)((buffer[3] << 8) + buffer[4]) / 100.0; - Energy.current[PzemDc.channel] = (float)((buffer[5] << 8) + buffer[6]) / 100.0; - Energy.active_power[PzemDc.channel] = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; - - PzemDc.energy += (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); - if (PzemDc.channel == Energy.phase_count -1) { - if (PzemDc.energy > PzemDc.last_energy) { - if (uptime > PZEM_DC_STABILIZE) { - EnergyUpdateTotal(PzemDc.energy, false); - } - PzemDc.last_energy = PzemDc.energy; - } - PzemDc.energy = 0; - } - } - } - } - - if (0 == PzemDc.send_retry || data_ready) { - if (0 == PzemDc.channel) { - PzemDc.channel = Energy.phase_count -1; - } else { - PzemDc.channel--; - } - PzemDc.send_retry = ENERGY_WATCHDOG; - if (ADDR_SEND == PzemDc.address_step) { - PzemDcModbus->Send(0xF8, 0x06, 0x0002, (uint16_t)PzemDc.address); - PzemDc.address_step--; - } else { - PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS + PzemDc.channel, 0x04, 0, 8); - } - } - else { - PzemDc.send_retry--; - if ((Energy.phase_count > 1) && (0 == PzemDc.send_retry) && (uptime < PZEM_DC_STABILIZE)) { - Energy.phase_count--; - } - } -} - -void PzemDcSnsInit(void) -{ - PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); - uint8_t result = PzemDcModbus->Begin(9600, 2); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.type_dc = true; - Energy.phase_count = 3; - PzemDc.channel = 0; - } else { - energy_flg = ENERGY_NONE; - } -} - -void PzemDcDrvInit(void) -{ - if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { - energy_flg = XNRG_06; - } -} - -bool PzemDcCommand(void) -{ - bool serviced = true; - - if (CMND_MODULEADDRESS == Energy.command_code) { - PzemDc.address = XdrvMailbox.payload; - PzemDc.address_step = ADDR_SEND; - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg06(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { PzemDcEverySecond(); } - break; - case FUNC_COMMAND: - result = PzemDcCommand(); - break; - case FUNC_INIT: - PzemDcSnsInit(); - break; - case FUNC_PRE_INIT: - PzemDcDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_07_ade7953.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_07_ade7953.ino" -#ifdef USE_I2C -#ifdef USE_ENERGY_SENSOR -#ifdef USE_ADE7953 -# 31 "S:/Development/Tasmota/tasmota/xnrg_07_ade7953.ino" -#define XNRG_07 7 -#define XI2C_07 7 - -#define ADE7953_PREF 1540 -#define ADE7953_UREF 26000 -#define ADE7953_IREF 10000 - -#define ADE7953_ADDR 0x38 - -const uint16_t Ade7953Registers[] { - 0x31B, - 0x313, - 0x311, - 0x315, - 0x31A, - 0x312, - 0x310, - 0x314, - 0x31C, - 0x10E -}; - -struct Ade7953 { - uint32_t voltage_rms = 0; - uint32_t period = 0; - uint32_t current_rms[2] = { 0, 0 }; - uint32_t active_power[2] = { 0, 0 }; - uint8_t init_step = 0; -} Ade7953; - -int Ade7953RegSize(uint16_t reg) -{ - int size = 0; - switch ((reg >> 8) & 0x0F) { - case 0x03: - size++; - case 0x02: - size++; - case 0x01: - size++; - case 0x00: - case 0x07: - case 0x08: - size++; - } - return size; -} - -void Ade7953Write(uint16_t reg, uint32_t val) -{ - int size = Ade7953RegSize(reg); - if (size) { - Wire.beginTransmission(ADE7953_ADDR); - Wire.write((reg >> 8) & 0xFF); - Wire.write(reg & 0xFF); - while (size--) { - Wire.write((val >> (8 * size)) & 0xFF); - } - Wire.endTransmission(); - delayMicroseconds(5); - } -} - -int32_t Ade7953Read(uint16_t reg) -{ - uint32_t response = 0; - - int size = Ade7953RegSize(reg); - if (size) { - Wire.beginTransmission(ADE7953_ADDR); - Wire.write((reg >> 8) & 0xFF); - Wire.write(reg & 0xFF); - Wire.endTransmission(0); - Wire.requestFrom(ADE7953_ADDR, size); - if (size <= Wire.available()) { - for (uint32_t i = 0; i < size; i++) { - response = response << 8 | Wire.read(); - } - } - } - return response; -} - -void Ade7953Init(void) -{ - Ade7953Write(0x102, 0x0004); - Ade7953Write(0x0FE, 0x00AD); - Ade7953Write(0x120, 0x0030); -} - -void Ade7953GetData(void) -{ - int32_t reg[2][4]; - for (uint32_t i = 0; i < sizeof(Ade7953Registers)/sizeof(uint16_t); i++) { - int32_t value = Ade7953Read(Ade7953Registers[i]); - if (8 == i) { - Ade7953.voltage_rms = value; - } else if (9 == i) { - Ade7953.period = value; - } else { - reg[i >> 2][i &3] = value; - } - } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ADE: %d, %d, [%d, %d, %d, %d], [%d, %d, %d, %d]"), - Ade7953.voltage_rms, Ade7953.period, - reg[0][0], reg[0][1], reg[0][2], reg[0][3], - reg[1][0], reg[1][1], reg[1][2], reg[1][3]); - - uint32_t apparent_power[2] = { 0, 0 }; - uint32_t reactive_power[2] = { 0, 0 }; - - for (uint32_t channel = 0; channel < 2; channel++) { - Ade7953.current_rms[channel] = reg[channel][0]; - if (Ade7953.current_rms[channel] < 2000) { - Ade7953.current_rms[channel] = 0; - Ade7953.active_power[channel] = 0; - } else { - Ade7953.active_power[channel] = abs(reg[channel][1]); - apparent_power[channel] = abs(reg[channel][2]); - reactive_power[channel] = abs(reg[channel][3]); - } - } - - uint32_t current_rms_sum = Ade7953.current_rms[0] + Ade7953.current_rms[1]; - uint32_t active_power_sum = Ade7953.active_power[0] + Ade7953.active_power[1]; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ADE: U %d, C %d, I %d + %d = %d, P %d + %d = %d"), - Ade7953.voltage_rms, Ade7953.period, - Ade7953.current_rms[0], Ade7953.current_rms[1], current_rms_sum, - Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum); - - if (Energy.power_on) { - Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration; - Energy.frequency[0] = 223750.0f / ( (float)Ade7953.period + 1); - - for (uint32_t channel = 0; channel < 2; channel++) { - Energy.data_valid[channel] = 0; - Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings.energy_power_calibration / 10); - Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings.energy_power_calibration / 10); - Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings.energy_power_calibration / 10); - if (0 == Energy.active_power[channel]) { - Energy.current[channel] = 0; - } else { - Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings.energy_current_calibration * 10); - } - } - } else { - Energy.data_valid[0] = ENERGY_WATCHDOG; - Energy.data_valid[1] = ENERGY_WATCHDOG; - } - - if (active_power_sum) { - Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings.energy_power_calibration / 10))) / 3600); - EnergyUpdateToday(); - } -} - -void Ade7953EnergyEverySecond(void) -{ - if (Ade7953.init_step) { - if (1 == Ade7953.init_step) { - Ade7953Init(); - } - Ade7953.init_step--; - } else { - Ade7953GetData(); - } -} - -void Ade7953DrvInit(void) -{ - if (pin[GPIO_ADE7953_IRQ] < 99) { - delay(100); - if (I2cSetDevice(ADE7953_ADDR)) { - if (HLW_PREF_PULSE == Settings.energy_power_calibration) { - Settings.energy_power_calibration = ADE7953_PREF; - Settings.energy_voltage_calibration = ADE7953_UREF; - Settings.energy_current_calibration = ADE7953_IREF; - } - I2cSetActiveFound(ADE7953_ADDR, "ADE7953"); - Ade7953.init_step = 2; - - Energy.phase_count = 2; - Energy.voltage_common = true; - - energy_flg = XNRG_07; - } - } -} - -bool Ade7953Command(void) -{ - bool serviced = true; - - uint32_t channel = (2 == XdrvMailbox.index) ? 1 : 0; - uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); - - if (CMND_POWERCAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; } - - } - else if (CMND_VOLTAGECAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_UREF; } - - } - else if (CMND_CURRENTCAL == Energy.command_code) { - if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_IREF; } - - } - else if (CMND_POWERSET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.active_power[channel]) { - if ((value > 100) && (value < 200000)) { - Settings.energy_power_calibration = (Ade7953.active_power[channel] * 1000) / value; - } - } - } - else if (CMND_VOLTAGESET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.voltage_rms) { - if ((value > 10000) && (value < 26000)) { - Settings.energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; - } - } - } - else if (CMND_CURRENTSET == Energy.command_code) { - if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) { - if ((value > 2000) && (value < 1000000)) { - Settings.energy_current_calibration = ((Ade7953.current_rms[channel] * 100) / value) * 100; - } - } - } - else serviced = false; - - return serviced; -} - - - - - -bool Xnrg07(uint8_t function) -{ - if (!I2cEnabled(XI2C_07)) { return false; } - - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - Ade7953EnergyEverySecond(); - break; - case FUNC_COMMAND: - result = Ade7953Command(); - break; - case FUNC_PRE_INIT: - Ade7953DrvInit(); - break; - } - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_08_sdm120.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_08_sdm120.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM120 - - - - - - -#define XNRG_08 8 - - -#ifndef SDM120_SPEED - #define SDM120_SPEED 2400 -#endif - -#ifndef SDM120_ADDR - #define SDM120_ADDR 1 -#endif - -#include -TasmotaModbus *Sdm120Modbus; - -const uint8_t sdm120_table = 8; -const uint8_t sdm220_table = 13; - -const uint16_t sdm120_start_addresses[] { - 0x0000, - 0x0006, - 0x000C, - 0x0012, - 0x0018, - 0x001E, - 0x0046, - 0x0156, - - 0X0048, - 0X004A, - 0X004C, - 0X004E, - 0X0024 -}; - -struct SDM120 { - float total_active = 0; - float import_active = NAN; - float import_reactive = 0; - float export_reactive = 0; - float phase_angle = 0; - uint8_t read_state = 0; - uint8_t send_retry = 0; - uint8_t start_address_count = sdm220_table; -} Sdm120; - - - -void SDM120Every250ms(void) -{ - bool data_ready = Sdm120Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm120Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM120 error %d"), error); - } else { - Energy.data_valid[0] = 0; - - - - - float value; - ((uint8_t*)&value)[3] = buffer[3]; - ((uint8_t*)&value)[2] = buffer[4]; - ((uint8_t*)&value)[1] = buffer[5]; - ((uint8_t*)&value)[0] = buffer[6]; - - switch(Sdm120.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.current[0] = value; - break; - - case 2: - Energy.active_power[0] = value; - break; - - case 3: - Energy.apparent_power[0] = value; - break; - - case 4: - Energy.reactive_power[0] = value; - break; - - case 5: - Energy.power_factor[0] = value; - break; - - case 6: - Energy.frequency[0] = value; - break; - - case 7: - Sdm120.total_active = value; - break; - - case 8: - Sdm120.import_active = value; - break; - - case 9: - Energy.export_active = value; - break; - - case 10: - Sdm120.import_reactive = value; - break; - - case 11: - Sdm120.export_reactive = value; - break; - - case 12: - Sdm120.phase_angle = value; - break; - } - - Sdm120.read_state++; - if (Sdm120.read_state == Sdm120.start_address_count) { - Sdm120.read_state = 0; - - if (Sdm120.start_address_count > sdm120_table) { - if (!isnan(Sdm120.import_active)) { - Sdm120.total_active = Sdm120.import_active; - } else { - Sdm120.start_address_count = sdm120_table; - } - } - EnergyUpdateTotal(Sdm120.total_active, true); - } - } - } - - if (0 == Sdm120.send_retry || data_ready) { - Sdm120.send_retry = 5; - Sdm120Modbus->Send(SDM120_ADDR, 0x04, sdm120_start_addresses[Sdm120.read_state], 2); - } else { - Sdm120.send_retry--; - } -} - -void Sdm120SnsInit(void) -{ - Sdm120Modbus = new TasmotaModbus(pin[GPIO_SDM120_RX], pin[GPIO_SDM120_TX]); - uint8_t result = Sdm120Modbus->Begin(SDM120_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Sdm120DrvInit(void) -{ - if ((pin[GPIO_SDM120_RX] < 99) && (pin[GPIO_SDM120_TX] < 99)) { - energy_flg = XNRG_08; - } -} - -void Sdm220Reset(void) -{ - if (isnan(Sdm120.import_active)) { return; } - - Sdm120.import_active = 0; - Sdm120.import_reactive = 0; - Sdm120.export_reactive = 0; - Sdm120.phase_angle = 0; -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_SDM220[] PROGMEM = - "{s}" D_IMPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}" D_EXPORT_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - "{s}" D_PHASE_ANGLE "{m}%s " D_UNIT_ANGLE "{e}"; -#endif - -void Sdm220Show(bool json) -{ - if (isnan(Sdm120.import_active)) { return; } - - char import_active_chr[FLOATSZ]; - dtostrfd(Sdm120.import_active, Settings.flag2.energy_resolution, import_active_chr); - char import_reactive_chr[FLOATSZ]; - dtostrfd(Sdm120.import_reactive, Settings.flag2.energy_resolution, import_reactive_chr); - char export_reactive_chr[FLOATSZ]; - dtostrfd(Sdm120.export_reactive, Settings.flag2.energy_resolution, export_reactive_chr); - char phase_angle_chr[FLOATSZ]; - dtostrfd(Sdm120.phase_angle, 2, phase_angle_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s"), - import_active_chr, import_reactive_chr, export_reactive_chr, phase_angle_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_ENERGY_SDM220, import_reactive_chr, export_reactive_chr, phase_angle_chr); -#endif - } -} - - - - - -bool Xnrg08(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { SDM120Every250ms(); } - break; - case FUNC_JSON_APPEND: - Sdm220Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sdm220Show(0); - break; -#endif - case FUNC_ENERGY_RESET: - Sdm220Reset(); - break; - case FUNC_INIT: - Sdm120SnsInit(); - break; - case FUNC_PRE_INIT: - Sdm120DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_09_dds2382.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_09_dds2382.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_DDS2382 - - - - - - -#define XNRG_09 9 - -#ifndef DDS2382_SPEED -#define DDS2382_SPEED 9600 -#endif -#ifndef DDS2382_ADDR -#define DDS2382_ADDR 1 -#endif - -#include -TasmotaModbus *Dds2382Modbus; - -uint8_t Dds2382_send_retry = 0; - -void Dds2382EverySecond(void) -{ - bool data_ready = Dds2382Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[46]; - - uint32_t error = Dds2382Modbus->ReceiveBuffer(buffer, 18); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Dds2382Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "DDS2382 response error %d"), error); - } else { - Energy.data_valid[0] = 0; -# 67 "S:/Development/Tasmota/tasmota/xnrg_09_dds2382.ino" - Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0; - Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0; - Energy.active_power[0] = (float)((buffer[31] << 8) + buffer[32]); - Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]); - Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; - Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; - uint8_t offset = 11; - if (Settings.flag3.dds2382_model) { - offset = 19; - } - Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; - float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; - - EnergyUpdateTotal(import_active, true); - } - } - - if (0 == Dds2382_send_retry || data_ready) { - Dds2382_send_retry = 5; - Dds2382Modbus->Send(DDS2382_ADDR, 0x03, 0, 18); - } else { - Dds2382_send_retry--; - } -} - -void Dds2382SnsInit(void) -{ - Dds2382Modbus = new TasmotaModbus(pin[GPIO_DDS2382_RX], pin[GPIO_DDS2382_TX]); - uint8_t result = Dds2382Modbus->Begin(DDS2382_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Dds2382DrvInit(void) -{ - if ((pin[GPIO_DDS2382_RX] < 99) && (pin[GPIO_DDS2382_TX] < 99)) { - energy_flg = XNRG_09; - } -} - - - - - -bool Xnrg09(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_ENERGY_EVERY_SECOND: - if (uptime > 4) { Dds2382EverySecond(); } - break; - case FUNC_INIT: - Dds2382SnsInit(); - break; - case FUNC_PRE_INIT: - Dds2382DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_10_sdm630.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_10_sdm630.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SDM630 - - - - - - -#define XNRG_10 10 - - -#ifndef SDM630_SPEED - #define SDM630_SPEED 9600 -#endif - -#ifndef SDM630_ADDR - #define SDM630_ADDR 1 -#endif - -#include -TasmotaModbus *Sdm630Modbus; - -const uint16_t sdm630_start_addresses[] { - 0x0000, - 0x0002, - 0x0004, - 0x0006, - 0x0008, - 0x000A, - 0x000C, - 0x000E, - 0x0010, - 0x0018, - 0x001A, - 0x001C, - 0x001E, - 0x0020, - 0x0022, - 0x0156 -}; - -struct SDM630 { - uint8_t read_state = 0; - uint8_t send_retry = 0; -} Sdm630; - - - -void SDM630Every250ms(void) -{ - bool data_ready = Sdm630Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Sdm630Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Sdm630Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM630 error %d"), error); - } else { - Energy.data_valid[0] = 0; - Energy.data_valid[1] = 0; - Energy.data_valid[2] = 0; - - - - - float value; - ((uint8_t*)&value)[3] = buffer[3]; - ((uint8_t*)&value)[2] = buffer[4]; - ((uint8_t*)&value)[1] = buffer[5]; - ((uint8_t*)&value)[0] = buffer[6]; - - switch(Sdm630.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.voltage[1] = value; - break; - - case 2: - Energy.voltage[2] = value; - break; - - case 3: - Energy.current[0] = value; - break; - - case 4: - Energy.current[1] = value; - break; - - case 5: - Energy.current[2] = value; - break; - - case 6: - Energy.active_power[0] = value; - break; - - case 7: - Energy.active_power[1] = value; - break; - - case 8: - Energy.active_power[2] = value; - break; - - case 9: - Energy.reactive_power[0] = value; - break; - - case 10: - Energy.reactive_power[1] = value; - break; - - case 11: - Energy.reactive_power[2] = value; - break; - - case 12: - Energy.power_factor[0] = value; - break; - - case 13: - Energy.power_factor[1] = value; - break; - - case 14: - Energy.power_factor[2] = value; - break; - - case 15: - EnergyUpdateTotal(value, true); - break; - } - - Sdm630.read_state++; - if (sizeof(sdm630_start_addresses)/2 == Sdm630.read_state) { - Sdm630.read_state = 0; - } - } - } - - if (0 == Sdm630.send_retry || data_ready) { - Sdm630.send_retry = 5; - Sdm630Modbus->Send(SDM630_ADDR, 0x04, sdm630_start_addresses[Sdm630.read_state], 2); - } else { - Sdm630.send_retry--; - } -} - -void Sdm630SnsInit(void) -{ - Sdm630Modbus = new TasmotaModbus(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX]); - uint8_t result = Sdm630Modbus->Begin(SDM630_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - Energy.phase_count = 3; - } else { - energy_flg = ENERGY_NONE; - } -} - -void Sdm630DrvInit(void) -{ - if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { - energy_flg = XNRG_10; - } -} - - - - - -bool Xnrg10(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { SDM630Every250ms(); } - break; - case FUNC_INIT: - Sdm630SnsInit(); - break; - case FUNC_PRE_INIT: - Sdm630DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_11_ddsu666.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_11_ddsu666.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_DDSU666 - - - - -#define XNRG_11 11 - - -#ifndef DDSU666_SPEED - #define DDSU666_SPEED 9600 -#endif - -#ifndef DDSU666_ADDR - #define DDSU666_ADDR 1 -#endif - -#include -TasmotaModbus *Ddsu666Modbus; - -const uint16_t Ddsu666_start_addresses[] { - 0x2000, - 0x2002, - 0x2004, - 0x2006, - 0x200A, - 0x200E, - 0X4000, - 0X400A, -}; - -struct DDSU666 { - float import_active = NAN; - uint8_t read_state = 0; - uint8_t send_retry = 0; -} Ddsu666; - - - -void DDSU666Every250ms(void) -{ - bool data_ready = Ddsu666Modbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - - uint32_t error = Ddsu666Modbus->ReceiveBuffer(buffer, 2); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, Ddsu666Modbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: Ddsu666 error %d"), error); - } else { - Energy.data_valid[0] = 0; - - - - - float value; - ((uint8_t*)&value)[3] = buffer[3]; - ((uint8_t*)&value)[2] = buffer[4]; - ((uint8_t*)&value)[1] = buffer[5]; - ((uint8_t*)&value)[0] = buffer[6]; - - switch(Ddsu666.read_state) { - case 0: - Energy.voltage[0] = value; - break; - - case 1: - Energy.current[0] = value; - break; - - case 2: - Energy.active_power[0] = value * 1000; - break; - - case 3: - Energy.reactive_power[0] = value * 1000; - break; - - case 4: - Energy.power_factor[0] = value; - break; - - case 5: - Energy.frequency[0] = value; - break; - - case 6: - Ddsu666.import_active = value; - break; - - case 7: - Energy.export_active = value; - break; - } - - Ddsu666.read_state++; - - if (Ddsu666.read_state == 8) { - Ddsu666.read_state = 0; - EnergyUpdateTotal(Ddsu666.import_active, true); - } - } - } - - if (0 == Ddsu666.send_retry || data_ready) { - Ddsu666.send_retry = 5; - Ddsu666Modbus->Send(DDSU666_ADDR, 0x04, Ddsu666_start_addresses[Ddsu666.read_state], 2); - } else { - Ddsu666.send_retry--; - } -} - -void Ddsu666SnsInit(void) -{ - Ddsu666Modbus = new TasmotaModbus(pin[GPIO_DDSU666_RX], pin[GPIO_DDSU666_TX]); - uint8_t result = Ddsu666Modbus->Begin(DDSU666_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Ddsu666DrvInit(void) -{ - if ((pin[GPIO_DDSU666_RX] < 99) && (pin[GPIO_DDSU666_TX] < 99)) { - energy_flg = XNRG_11; - } -} - - - - - -bool Xnrg11(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { DDSU666Every250ms(); } - break; - case FUNC_INIT: - Ddsu666SnsInit(); - break; - case FUNC_PRE_INIT: - Ddsu666DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_12_solaxX1.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_12_solaxX1.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_SOLAX_X1 - - - - -#define XNRG_12 12 - -#ifndef SOLAXX1_SPEED -#define SOLAXX1_SPEED 9600 -#endif - -#define INVERTER_ADDRESS 0x0A - -#define D_SOLAX_X1 "SolaxX1" - -#include - -enum solaxX1_Error -{ - solaxX1_ERR_NO_ERROR, - solaxX1_ERR_CRC_ERROR -}; - -union { - uint32_t ErrMessage; - struct { - - uint8_t TzProtectFault:1; - uint8_t MainsLostFault:1; - uint8_t GridVoltFault:1; - uint8_t GridFreqFault:1; - uint8_t PLLLostFault:1; - uint8_t BusVoltFault:1; - uint8_t ErrBit06:1; - uint8_t OciFault:1; - - uint8_t Dci_OCP_Fault:1; - uint8_t ResidualCurrentFault:1; - uint8_t PvVoltFault:1; - uint8_t Ac10Mins_Voltage_Fault:1; - uint8_t IsolationFault:1; - uint8_t TemperatureOverFault:1; - uint8_t FanFault:1; - uint8_t ErrBit15:1; - - uint8_t SpiCommsFault:1; - uint8_t SciCommsFault:1; - uint8_t ErrBit18:1; - uint8_t InputConfigFault:1; - uint8_t EepromFault:1; - uint8_t RelayFault:1; - uint8_t SampleConsistenceFault:1; - uint8_t ResidualCurrent_DeviceFault:1; - - uint8_t ErrBit24:1; - uint8_t ErrBit25:1; - uint8_t ErrBit26:1; - uint8_t ErrBit27:1; - uint8_t ErrBit28:1; - uint8_t DCI_DeviceFault:1; - uint8_t OtherDeviceFault:1; - uint8_t ErrBit31:1; - }; -} ErrCode; - -const char kSolaxMode[] PROGMEM = D_WAITING "|" D_CHECKING "|" D_WORKING "|" D_FAILURE; - -const char kSolaxError[] PROGMEM = - D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|" - D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8; - - - -TasmotaSerial *solaxX1Serial; - -uint8_t solaxX1_Init = 1; - -struct SOLAXX1 { - float temperature = 0; - float energy_today = 0; - float dc1_voltage = 0; - float dc2_voltage = 0; - float dc1_current = 0; - float dc2_current = 0; - float energy_total = 0; - float runtime_total = 0; - float dc1_power = 0; - float dc2_power = 0; - - uint8_t status = 0; - uint32_t errorCode = 0; -} solaxX1; - -union { - uint8_t status; - struct { - uint8_t freeBit7:1; - uint8_t freeBit6:1; - uint8_t freeBit5:1; - uint8_t queryOffline:1; - uint8_t queryOfflineSend:1; - uint8_t hasAddress:1; - uint8_t inverterAddressSend:1; - uint8_t inverterSnReceived:1; - }; -} protocolStatus; - -uint8_t header[2] = {0xAA, 0x55}; -uint8_t source[2] = {0x00, 0x00}; -uint8_t destination[2] = {0x00, 0x00}; -uint8_t controlCode[1] = {0x00}; -uint8_t functionCode[1] = {0x00}; -uint8_t dataLength[1] = {0x00}; -uint8_t data[16] = {0}; - -uint8_t message[30]; - - - -bool solaxX1_RS485ReceiveReady(void) -{ - return (solaxX1Serial->available() > 1); -} - -void solaxX1_RS485Send(uint16_t msgLen) -{ - memcpy(message, header, 2); - memcpy(message + 2, source, 2); - memcpy(message + 4, destination, 2); - memcpy(message + 6, controlCode, 1); - memcpy(message + 7, functionCode, 1); - memcpy(message + 8, dataLength, 1); - memcpy(message + 9, data, sizeof(data)); - uint16_t crc = solaxX1_calculateCRC(message, msgLen); - - while (solaxX1Serial->available() > 0) - { - solaxX1Serial->read(); - } - - solaxX1Serial->flush(); - solaxX1Serial->write(message, msgLen); - solaxX1Serial->write(highByte(crc)); - solaxX1Serial->write(lowByte(crc)); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen); -} - -uint8_t solaxX1_RS485Receive(uint8_t *value) -{ - uint8_t len = 0; - - while (solaxX1Serial->available() > 0) - { - value[len++] = (uint8_t)solaxX1Serial->read(); - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, value, len); - - uint16_t crc = solaxX1_calculateCRC(value, len - 2); - - if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc)) - { - return solaxX1_ERR_NO_ERROR; - } - else - { - return solaxX1_ERR_CRC_ERROR; - } -} - -uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen) -{ - uint8_t i; - uint16_t wChkSum; - wChkSum = 0; - - for (i = 0; i < bLen; i++) - { - wChkSum = wChkSum + bExternTxPackage[i]; - } - return wChkSum; -} - -void solaxX1_SendInverterAddress(void) -{ - source[0] = 0x00; - destination[0] = 0x00; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x01; - dataLength[0] = 0x0F; - data[14] = INVERTER_ADDRESS; - solaxX1_RS485Send(24); -} - -void solaxX1_QueryLiveData(void) -{ - source[0] = 0x01; - destination[0] = 0x00; - destination[1] = INVERTER_ADDRESS; - controlCode[0] = 0x11; - functionCode[0] = 0x02; - dataLength[0] = 0x00; - solaxX1_RS485Send(9); -} - -uint8_t solaxX1_ParseErrorCode(uint32_t code){ - ErrCode.ErrMessage = code; - - if (code == 0) return 0; - if (ErrCode.MainsLostFault) return 1; - if (ErrCode.GridVoltFault) return 2; - if (ErrCode.GridFreqFault) return 3; - if (ErrCode.PvVoltFault) return 4; - if (ErrCode.IsolationFault) return 5; - if (ErrCode.TemperatureOverFault) return 6; - if (ErrCode.FanFault) return 7; - if (ErrCode.OtherDeviceFault) return 8; -} - - - -uint8_t solaxX1_send_retry = 0; -uint8_t solaxX1_nodata_count = 0; - -void solaxX1250MSecond(void) -{ - uint8_t value[61] = {0}; - bool data_ready = solaxX1_RS485ReceiveReady(); - - if (protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - if (data_ready) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error")); - } - else - { - solaxX1_nodata_count = 0; - solaxX1_send_retry = 12; - Energy.data_valid[0] = 0; - - solaxX1.temperature = (float)((value[9] << 8) | value[10]); - solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; - solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; - solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; - solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; - solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; - Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; - Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; - Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; - Energy.active_power[0] = (float)((value[27] << 8) | value[28]); - - solaxX1.energy_total = (float)((value[31] << 8) | (value[32] << 8) | (value[33] << 8) | value[34]) * 0.1f; - solaxX1.runtime_total = (float)((value[35] << 8) | (value[36] << 8) | (value[37] << 8) | value[38]); - solaxX1.status = (uint8_t)((value[39] << 8) | value[40]); - - - - - - - - solaxX1.errorCode = (uint32_t)((value[58] << 8) | (value[57] << 8) | (value[56] << 8) | value[55]); - - solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current; - solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current; - - solaxX1_QueryLiveData(); - EnergyUpdateTotal(solaxX1.energy_total, true); - } - } - - if (0 == solaxX1_send_retry && 255 != solaxX1_nodata_count) { - solaxX1_send_retry = 12; - solaxX1_QueryLiveData(); - } - - - - if (255 == solaxX1_nodata_count) { - solaxX1_nodata_count = 0; - solaxX1_send_retry = 12; - } - } - else - { - if ((solaxX1_nodata_count % 4) == 0) { DEBUG_SENSOR_LOG(PSTR("SX1: No Data count: %d"), solaxX1_nodata_count); } - if (solaxX1_nodata_count < 10 * 4) - { - solaxX1_nodata_count++; - } - else if (255 != solaxX1_nodata_count) - { - - solaxX1_nodata_count = 255; - solaxX1_send_retry = 12; - protocolStatus.status = 0b00001000; - Energy.data_valid[0] = ENERGY_WATCHDOG; - - solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0; - solaxX1.dc2_power = solaxX1.status = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0; - - } - } - - if (!protocolStatus.hasAddress && (data_ready || solaxX1_send_retry == 0)) - { - if (data_ready) - { - - if (protocolStatus.inverterAddressSend) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error")); - } - else - { - if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Set hasAddress")); - protocolStatus.status = 0b00100000; - } - } - } - - - if (protocolStatus.queryOfflineSend) - { - uint8_t error = solaxX1_RS485Receive(value); - if (error) - { - DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error")); - } - else - { - - if (value[6] == 0x10 && value[7] == 0x80 && protocolStatus.inverterSnReceived == false) - { - for (uint8_t i = 9; i <= 22; i++) - { - data[i - 9] = value[i]; - } - solaxX1_SendInverterAddress(); - protocolStatus.status = 0b1100000; - DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend")); - } - } - } - } - - if (solaxX1_send_retry == 0) - { - if (protocolStatus.queryOfflineSend) - { - protocolStatus.status = 0b00001000; - DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline")); - } - solaxX1_send_retry = 12; - } - - - if (protocolStatus.queryOffline) - { - - source[0] = 0x01; - destination[1] = 0x00; - controlCode[0] = 0x10; - functionCode[0] = 0x00; - dataLength[0] = 0x00; - solaxX1_RS485Send(9); - protocolStatus.status = 0b00010000; - DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send")); - } - } - - if (!data_ready) - solaxX1_send_retry--; -} - -void solaxX1SnsInit(void) -{ - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SX1: Solax X1 Inverter Init")); - DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX]); - protocolStatus.status = 0b00100000; - - solaxX1Serial = new TasmotaSerial(pin[GPIO_SOLAXX1_RX], pin[GPIO_SOLAXX1_TX], 1); - if (solaxX1Serial->begin(SOLAXX1_SPEED)) { - if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void solaxX1DrvInit(void) -{ - if ((pin[GPIO_SOLAXX1_RX] < 99) && (pin[GPIO_SOLAXX1_TX] < 99)) { - energy_flg = XNRG_12; - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_solaxX1_DATA1[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_SOLAR_POWER "{m}%s " D_UNIT_WATT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV1_POWER "{m}%s " D_UNIT_WATT "{e}"; -#ifdef SOLAXX1_PV2 -const char HTTP_SNS_solaxX1_DATA2[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_PV2_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}"; -#endif -const char HTTP_SNS_solaxX1_DATA3[] PROGMEM = - "{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}" - "{s}" D_SOLAX_X1 " " D_STATUS "{m}%s" - "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"; -#endif - -void solaxX1Show(bool json) -{ - char solar_power[33]; - dtostrfd(solaxX1.dc1_power + solaxX1.dc2_power, Settings.flag2.wattage_resolution, solar_power); - char pv1_voltage[33]; - dtostrfd(solaxX1.dc1_voltage, Settings.flag2.voltage_resolution, pv1_voltage); - char pv1_current[33]; - dtostrfd(solaxX1.dc1_current, Settings.flag2.current_resolution, pv1_current); - char pv1_power[33]; - dtostrfd(solaxX1.dc1_power, Settings.flag2.wattage_resolution, pv1_power); -#ifdef SOLAXX1_PV2 - char pv2_voltage[33]; - dtostrfd(solaxX1.dc2_voltage, Settings.flag2.voltage_resolution, pv2_voltage); - char pv2_current[33]; - dtostrfd(solaxX1.dc2_current, Settings.flag2.current_resolution, pv2_current); - char pv2_power[33]; - dtostrfd(solaxX1.dc2_power, Settings.flag2.wattage_resolution, pv2_power); -#endif - char temperature[33]; - dtostrfd(solaxX1.temperature, Settings.flag2.temperature_resolution, temperature); - char runtime[33]; - dtostrfd(solaxX1.runtime_total, 0, runtime); - char status[33]; - GetTextIndexed(status, sizeof(status), solaxX1.status, kSolaxMode); - - if (json) - { - ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"), - solar_power, pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"), - pv2_voltage, pv2_current, pv2_power); -#endif - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"), - temperature, runtime, status, solaxX1.errorCode); - -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_solaxX1_DATA1, solar_power, pv1_voltage, pv1_current, pv1_power); -#ifdef SOLAXX1_PV2 - WSContentSend_PD(HTTP_SNS_solaxX1_DATA2, pv2_voltage, pv2_current, pv2_power); -#endif - WSContentSend_PD(HTTP_SNS_TEMP, D_SOLAX_X1, temperature, TempUnit()); - char errorCodeString[33]; - WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status, - GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError)); -#endif - } -} - - - - - -bool Xnrg12(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { solaxX1250MSecond(); } - break; - case FUNC_JSON_APPEND: - solaxX1Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - solaxX1Show(0); - break; -#endif - case FUNC_INIT: - solaxX1SnsInit(); - break; - case FUNC_PRE_INIT: - solaxX1DrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -#ifdef USE_ENERGY_SENSOR -#ifdef USE_LE01MR -# 71 "S:/Development/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" -#define XNRG_13 13 - - -#ifndef LE01MR_SPEED - #define LE01MR_SPEED 2400 -#endif - -#ifndef LE01MR_ADDR - #define LE01MR_ADDR 1 -#endif - -#include -TasmotaModbus *FifLEModbus; - -const uint8_t le01mr_table_sz = 9; - -const uint16_t le01mr_register_addresses[] { - - 0x0130, - 0x0131, - 0x0158, - 0x0139, - 0x0140, - 0x0148, - 0x0150, - 0xA000, - 0xA01E -}; - -struct LE01MR { - float total_active = 0; - float total_reactive = 0; - uint8_t read_state = 0; - uint8_t send_retry = 0; - uint8_t start_address_count = le01mr_table_sz; -} Le01mr; - - - -void FifLEEvery250ms(void) -{ - bool data_ready = FifLEModbus->ReceiveReady(); - - if (data_ready) { - uint8_t buffer[14]; - uint8_t reg_count = 2; - if (Le01mr.read_state < 3) { - reg_count=1; - } - - uint32_t error = FifLEModbus->ReceiveBuffer(buffer, reg_count); - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, FifLEModbus->ReceiveCount()); - - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FiF-LE: LE01MR Modbus error %d"), error); - } else { - Energy.data_valid[0] = 0; -# 146 "S:/Development/Tasmota/tasmota/xnrg_13_fif_le01mr.ino" - uint32_t value_buff = 0; - - if (Le01mr.read_state >= 0 && Le01mr.read_state < 3) { - value_buff = ((uint32_t)buffer[3])<<8 | buffer[4]; - } else { - value_buff = ((uint32_t)buffer[3])<<24 | ((uint32_t)buffer[4])<<16 | ((uint32_t)buffer[5])<<8 | buffer[6]; - } - - switch(Le01mr.read_state) { - case 0: - Energy.frequency[0] = value_buff * 0.01f; - break; - - case 1: - Energy.voltage[0] = value_buff * 0.01f; - break; - - case 2: - Energy.power_factor[0] = ((int16_t)value_buff) * 0.001f; - break; - - case 3: - Energy.current[0] = value_buff * 0.001f; - break; - - case 4: - Energy.active_power[0] = value_buff * 1.0f; - break; - - case 5: - Energy.reactive_power[0] = value_buff * 1.0f; - break; - - case 6: - Energy.apparent_power[0] = value_buff * 1.0f; - break; - - case 7: - Le01mr.total_active = value_buff * 0.01f; - break; - - case 8: - Le01mr.total_reactive = value_buff * 0.01f; - break; - } - - Le01mr.read_state++; - if (Le01mr.read_state == Le01mr.start_address_count) { - Le01mr.read_state = 0; - - EnergyUpdateTotal(Le01mr.total_active, true); - } - } - } - - if (0 == Le01mr.send_retry || data_ready) { - uint8_t reg_count = 2; - - Le01mr.send_retry = 5; - - if (Le01mr.read_state < 3) reg_count=1; - - FifLEModbus->Send(LE01MR_ADDR, 0x03, le01mr_register_addresses[Le01mr.read_state], reg_count); - } else { - Le01mr.send_retry--; - } -} - -void FifLESnsInit(void) -{ - FifLEModbus = new TasmotaModbus(pin[GPIO_LE01MR_RX], pin[GPIO_LE01MR_TX]); - uint8_t result = FifLEModbus->Begin(LE01MR_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void FifLEDrvInit(void) -{ - if ((pin[GPIO_LE01MR_RX] < 99) && (pin[GPIO_LE01MR_TX] < 99)) { - energy_flg = XNRG_13; - } -} - -void FifLEReset(void) -{ - Le01mr.total_active = 0; - Le01mr.total_reactive = 0; -} - -#ifdef USE_WEBSERVER -const char HTTP_ENERGY_LE01MR[] PROGMEM = - "{s}" D_TOTAL_ACTIVE "{m}%s " D_UNIT_KILOWATTHOUR "{e}" - "{s}" D_TOTAL_REACTIVE "{m}%s " D_UNIT_KWARH "{e}" - ; -#endif - -void FifLEShow(bool json) -{ - char total_reactive_chr[FLOATSZ]; - dtostrfd(Le01mr.total_reactive, Settings.flag2.energy_resolution, total_reactive_chr); - char total_active_chr[FLOATSZ]; - dtostrfd(Le01mr.total_active, Settings.flag2.energy_resolution, total_active_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_JSON_TOTAL_ACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s"), - total_active_chr, total_reactive_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_ENERGY_LE01MR, total_active_chr, total_reactive_chr); -#endif - } -} - - - - - -bool Xnrg13(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_EVERY_250_MSECOND: - if (uptime > 4) { - FifLEEvery250ms(); - } - break; - case FUNC_JSON_APPEND: - FifLEShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - FifLEShow(0); - break; -#endif - case FUNC_ENERGY_RESET: - FifLEReset(); - break; - case FUNC_INIT: - FifLESnsInit(); - break; - case FUNC_PRE_INIT: - FifLEDrvInit(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xnrg_interface.ino" -# 20 "S:/Development/Tasmota/tasmota/xnrg_interface.ino" -#ifdef USE_ENERGY_SENSOR - -#ifdef XFUNC_PTR_IN_ROM -bool (* const xnrg_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xnrg_func_ptr[])(uint8_t) = { -#endif - -#ifdef XNRG_01 - &Xnrg01, -#endif - -#ifdef XNRG_02 - &Xnrg02, -#endif - -#ifdef XNRG_03 - &Xnrg03, -#endif - -#ifdef XNRG_04 - &Xnrg04, -#endif - -#ifdef XNRG_05 - &Xnrg05, -#endif - -#ifdef XNRG_06 - &Xnrg06, -#endif - -#ifdef XNRG_07 - &Xnrg07, -#endif - -#ifdef XNRG_08 - &Xnrg08, -#endif - -#ifdef XNRG_09 - &Xnrg09, -#endif - -#ifdef XNRG_10 - &Xnrg10, -#endif - -#ifdef XNRG_11 - &Xnrg11, -#endif - -#ifdef XNRG_12 - &Xnrg12, -#endif - -#ifdef XNRG_13 - &Xnrg13, -#endif - -#ifdef XNRG_14 - &Xnrg14, -#endif - -#ifdef XNRG_15 - &Xnrg15, -#endif - -#ifdef XNRG_16 - &Xnrg16 -#endif -}; - -const uint8_t xnrg_present = sizeof(xnrg_func_ptr) / sizeof(xnrg_func_ptr[0]); - -uint8_t xnrg_active = 0; - -bool XnrgCall(uint8_t function) -{ - DEBUG_TRACE_LOG(PSTR("NRG: %d"), function); - - if (FUNC_PRE_INIT == function) { - for (uint32_t x = 0; x < xnrg_present; x++) { - xnrg_func_ptr[x](function); - if (energy_flg) { - xnrg_active = x; - return true; - } - } - } - else if (energy_flg) { - return xnrg_func_ptr[xnrg_active](function); - } - return false; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_01_counter.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_01_counter.ino" -#ifdef USE_COUNTER - - - - -#define XSNS_01 1 - -#define D_PRFX_COUNTER "Counter" -#define D_CMND_COUNTERTYPE "Type" -#define D_CMND_COUNTERDEBOUNCE "Debounce" - -const char kCounterCommands[] PROGMEM = D_PRFX_COUNTER "|" - "|" D_CMND_COUNTERTYPE "|" D_CMND_COUNTERDEBOUNCE ; - -void (* const CounterCommand[])(void) PROGMEM = { - &CmndCounter, &CmndCounterType, &CmndCounterDebounce }; - -struct COUNTER { - uint32_t timer[MAX_COUNTERS]; - uint8_t no_pullup = 0; - bool any_counter = false; -} Counter; - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void CounterUpdate(uint8_t index) ICACHE_RAM_ATTR; -void CounterUpdate1(void) ICACHE_RAM_ATTR; -void CounterUpdate2(void) ICACHE_RAM_ATTR; -void CounterUpdate3(void) ICACHE_RAM_ATTR; -void CounterUpdate4(void) ICACHE_RAM_ATTR; -#endif - -void CounterUpdate(uint8_t index) -{ - uint32_t time = micros(); - uint32_t debounce_time = time - Counter.timer[index]; - if (debounce_time > Settings.pulse_counter_debounce * 1000) { - Counter.timer[index] = time; - if (bitRead(Settings.pulse_counter_type, index)) { - RtcSettings.pulse_counter[index] = debounce_time; - } else { - RtcSettings.pulse_counter[index]++; - } - } -} - -void CounterUpdate1(void) -{ - CounterUpdate(0); -} - -void CounterUpdate2(void) -{ - CounterUpdate(1); -} - -void CounterUpdate3(void) -{ - CounterUpdate(2); -} - -void CounterUpdate4(void) -{ - CounterUpdate(3); -} - - - -bool CounterPinState(void) -{ - if ((XdrvMailbox.index >= GPIO_CNTR1_NP) && (XdrvMailbox.index < (GPIO_CNTR1_NP + MAX_COUNTERS))) { - bitSet(Counter.no_pullup, XdrvMailbox.index - GPIO_CNTR1_NP); - XdrvMailbox.index -= (GPIO_CNTR1_NP - GPIO_CNTR1); - return true; - } - return false; -} - -void CounterInit(void) -{ - typedef void (*function) () ; - function counter_callbacks[] = { CounterUpdate1, CounterUpdate2, CounterUpdate3, CounterUpdate4 }; - - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - Counter.any_counter = true; - pinMode(pin[GPIO_CNTR1 +i], bitRead(Counter.no_pullup, i) ? INPUT : INPUT_PULLUP); - attachInterrupt(pin[GPIO_CNTR1 +i], counter_callbacks[i], FALLING); - } - } -} - -void CounterEverySecond(void) -{ - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - if (bitRead(Settings.pulse_counter_type, i)) { - uint32_t time = micros() - Counter.timer[i]; - if (time > 4200000000) { - RtcSettings.pulse_counter[i] = 4200000000; - } - } - } - } -} - -void CounterSaveState(void) -{ - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - Settings.pulse_counter[i] = RtcSettings.pulse_counter[i]; - } - } -} - -void CounterShow(bool json) -{ - bool header = false; - uint8_t dsxflg = 0; - for (uint32_t i = 0; i < MAX_COUNTERS; i++) { - if (pin[GPIO_CNTR1 +i] < 99) { - char counter[33]; - if (bitRead(Settings.pulse_counter_type, i)) { - dtostrfd((double)RtcSettings.pulse_counter[i] / 1000000, 6, counter); - } else { - dsxflg++; - snprintf_P(counter, sizeof(counter), PSTR("%lu"), RtcSettings.pulse_counter[i]); - } - - if (json) { - if (!header) { - ResponseAppend_P(PSTR(",\"COUNTER\":{")); - } - ResponseAppend_P(PSTR("%s\"C%d\":%s"), (header)?",":"", i +1, counter); - header = true; -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (1 == dsxflg)) { - DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]); - dsxflg++; - } -#endif - if ((0 == tele_period ) && (Settings.flag3.counter_reset_on_tele)) { - RtcSettings.pulse_counter[i] = 0; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(PSTR("{s}" D_COUNTER "%d{m}%s%s{e}"), - i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : ""); -#endif - } - } - } - if (header) { - ResponseJsonEnd(); - } -} - - - - - -void CmndCounter(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { - if ((XdrvMailbox.data_len > 0) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { - if ((XdrvMailbox.data[0] == '-') || (XdrvMailbox.data[0] == '+')) { - RtcSettings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; - Settings.pulse_counter[XdrvMailbox.index -1] += XdrvMailbox.payload; - } else { - RtcSettings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; - Settings.pulse_counter[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - } - ResponseCmndIdxNumber(RtcSettings.pulse_counter[XdrvMailbox.index -1]); - } -} - -void CmndCounterType(void) -{ - if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_COUNTERS)) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1) && (pin[GPIO_CNTR1 + XdrvMailbox.index -1] < 99)) { - bitWrite(Settings.pulse_counter_type, XdrvMailbox.index -1, XdrvMailbox.payload &1); - RtcSettings.pulse_counter[XdrvMailbox.index -1] = 0; - Settings.pulse_counter[XdrvMailbox.index -1] = 0; - } - ResponseCmndIdxNumber(bitRead(Settings.pulse_counter_type, XdrvMailbox.index -1)); - } -} - -void CmndCounterDebounce(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32001)) { - Settings.pulse_counter_debounce = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings.pulse_counter_debounce); -} - - - - - -bool Xsns01(uint8_t function) -{ - bool result = false; - - if (Counter.any_counter) { - switch (function) { - case FUNC_EVERY_SECOND: - CounterEverySecond(); - break; - case FUNC_JSON_APPEND: - CounterShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - CounterShow(0); - break; -#endif - case FUNC_SAVE_BEFORE_RESTART: - case FUNC_SAVE_AT_MIDNIGHT: - CounterSaveState(); - break; - case FUNC_COMMAND: - result = DecodeCommand(kCounterCommands, CounterCommand); - break; - } - } else { - switch (function) { - case FUNC_INIT: - CounterInit(); - break; - case FUNC_PIN_STATE: - result = CounterPinState(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_02_analog.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_02_analog.ino" -#ifndef USE_ADC_VCC - - - - -#define XSNS_02 2 - -#define TO_CELSIUS(x) ((x) - 273.15) -#define TO_KELVIN(x) ((x) + 273.15) - - -#define ANALOG_V33 3.3 -#define ANALOG_T0 TO_KELVIN(25.0) - - - - - -#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 -#define ANALOG_NTC_RESISTANCE 10000 -#define ANALOG_NTC_B_COEFFICIENT 3350 - - - - - -#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 -#define ANALOG_LDR_LUX_CALC_SCALAR 12518931 -#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 -# 58 "S:/Development/Tasmota/tasmota/xsns_02_analog.ino" -#define ANALOG_CT_FLAGS 0 -#define ANALOG_CT_MULTIPLIER 2146 -#define ANALOG_CT_VOLTAGE 2300 - -#define CT_FLAG_ENERGY_RESET (1 << 0) - -struct { - float temperature = 0; - float current = 0; - float energy = 0; - uint32_t previous_millis = 0; - uint16_t last_value = 0; -} Adc; - -void AdcInit(void) -{ - if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000)) { - if (ADC0_TEMP == my_adc0) { - - Settings.adc_param_type = ADC0_TEMP; - Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE; - Settings.adc_param2 = ANALOG_NTC_RESISTANCE; - Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000; - } - else if (ADC0_LIGHT == my_adc0) { - Settings.adc_param_type = ADC0_LIGHT; - Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE; - Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; - Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; - } - else if (ADC0_RANGE == my_adc0) { - Settings.adc_param_type = ADC0_RANGE; - Settings.adc_param1 = 0; - Settings.adc_param2 = 1023; - Settings.adc_param3 = 0; - Settings.adc_param4 = 100; - } - else if (ADC0_CT_POWER == my_adc0) { - Settings.adc_param_type = ADC0_CT_POWER; - Settings.adc_param1 = ANALOG_CT_FLAGS; - Settings.adc_param2 = ANALOG_CT_MULTIPLIER; - Settings.adc_param3 = ANALOG_CT_VOLTAGE; - } - } -} - -uint16_t AdcRead(uint8_t factor) -{ - - - - - - uint8_t samples = 1 << factor; - uint16_t analog = 0; - for (uint32_t i = 0; i < samples; i++) { - analog += analogRead(A0); - delay(1); - } - analog >>= factor; - return analog; -} - -#ifdef USE_RULES -void AdcEvery250ms(void) -{ - if (ADC0_INPUT == my_adc0) { - uint16_t new_value = AdcRead(5); - if ((new_value < Adc.last_value -10) || (new_value > Adc.last_value +10)) { - Adc.last_value = new_value; - uint16_t value = Adc.last_value / 10; - Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); - XdrvRulesProcess(); - } - } -} -#endif - -uint16_t AdcGetLux(void) -{ - int adc = AdcRead(2); - - double resistorVoltage = ((double)adc / 1023) * ANALOG_V33; - double ldrVoltage = ANALOG_V33 - resistorVoltage; - double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1; - double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000); - - return (uint16_t)ldrLux; -} - -uint16_t AdcGetRange(void) -{ - - - - int adc = AdcRead(2); - double adcrange = ( ((double)Settings.adc_param2 - (double)adc) / ( ((double)Settings.adc_param2 - (double)Settings.adc_param1)) * ((double)Settings.adc_param3 - (double)Settings.adc_param4) + (double)Settings.adc_param4 ); - return (uint16_t)adcrange; -} - -void AdcGetCurrentPower(uint8_t factor) -{ - - - - - - uint8_t samples = 1 << factor; - uint16_t analog = 0; - uint16_t analog_min = 1023; - uint16_t analog_max = 0; - for (uint32_t i = 0; i < samples; i++) { - analog = analogRead(A0); - if (analog < analog_min) { - analog_min = analog; - } - if (analog > analog_max) { - analog_max = analog; - } - delay(1); - } - - Adc.current = (float)(analog_max-analog_min) * ((float)(Settings.adc_param2) / 100000); - float power = Adc.current * (float)(Settings.adc_param3) / 10; - uint32_t current_millis = millis(); - Adc.energy = Adc.energy + ((power * (current_millis - Adc.previous_millis)) / 3600000000); - Adc.previous_millis = current_millis; -} - -void AdcEverySecond(void) -{ - if (ADC0_TEMP == my_adc0) { - int adc = AdcRead(2); - - double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc); - double BC = (double)Settings.adc_param3 / 10000; - double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2)); - Adc.temperature = ConvertTemp(TO_CELSIUS(T)); - } - else if (ADC0_CT_POWER == my_adc0) { - AdcGetCurrentPower(5); - } -} - -void AdcShow(bool json) -{ - if (ADC0_INPUT == my_adc0) { - uint16_t analog = AdcRead(5); - - if (json) { - ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); -#endif - } - } - - else if (ADC0_TEMP == my_adc0) { - char temperature[33]; - dtostrfd(Adc.temperature, Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMP, "ANALOG", temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, Adc.temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); -#endif - } - } - - else if (ADC0_LIGHT == my_adc0) { - uint16_t adc_light = AdcGetLux(); - - if (json) { - ResponseAppend_P(JSON_SNS_ILLUMINANCE, "ANALOG", adc_light); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, adc_light); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", adc_light); -#endif - } - } - - else if (ADC0_RANGE == my_adc0) { - uint16_t adc_range = AdcGetRange(); - - if (json) { - ResponseAppend_P(JSON_SNS_RANGE, "ANALOG", adc_range); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_RANGE, "", adc_range); -#endif - } - } - - else if (ADC0_CT_POWER == my_adc0) { - AdcGetCurrentPower(5); - - float voltage = (float)(Settings.adc_param3) / 10; - char voltage_chr[FLOATSZ]; - dtostrfd(voltage, Settings.flag2.voltage_resolution, voltage_chr); - char current_chr[FLOATSZ]; - dtostrfd(Adc.current, Settings.flag2.current_resolution, current_chr); - char power_chr[FLOATSZ]; - dtostrfd(voltage * Adc.current, Settings.flag2.wattage_resolution, power_chr); - char energy_chr[FLOATSZ]; - dtostrfd(Adc.energy, Settings.flag2.energy_resolution, energy_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"ANALOG\":{\"" D_JSON_ENERGY "\":%s,\"" D_JSON_POWERUSAGE "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), - energy_chr, power_chr, voltage_chr, current_chr); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_POWER_ENERGY, power_chr); - DomoticzSensor(DZ_VOLTAGE, voltage_chr); - DomoticzSensor(DZ_CURRENT, current_chr); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_VOLTAGE, voltage_chr); - WSContentSend_PD(HTTP_SNS_CURRENT, current_chr); - WSContentSend_PD(HTTP_SNS_POWER, power_chr); - WSContentSend_PD(HTTP_SNS_ENERGY_TOTAL, energy_chr); -#endif - } - } - -} - - - - - -const char kAdcCommands[] PROGMEM = "|" - D_CMND_ADC "|" D_CMND_ADCS "|" D_CMND_ADCPARAM; - -void (* const AdcCommand[])(void) PROGMEM = { - &CmndAdc, &CmndAdcs, &CmndAdcParam }; - -void CmndAdc(void) -{ - if (ValidAdc() && (XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < ADC0_END)) { - Settings.my_adc0 = XdrvMailbox.payload; - restart_flag = 2; - } - char stemp1[TOPSZ]; - Response_P(PSTR("{\"" D_CMND_ADC "0\":{\"%d\":\"%s\"}}"), Settings.my_adc0, GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_adc0, kAdc0Names)); -} - -void CmndAdcs(void) -{ - Response_P(PSTR("{\"" D_CMND_ADCS "\":{")); - bool jsflg = false; - char stemp1[TOPSZ]; - for (uint32_t i = 0; i < ADC0_END; i++) { - if (jsflg) { - ResponseAppend_P(PSTR(",")); - } - jsflg = true; - ResponseAppend_P(PSTR("\"%d\":\"%s\""), i, GetTextIndexed(stemp1, sizeof(stemp1), i, kAdc0Names)); - } - ResponseJsonEndEnd(); -} - -void CmndAdcParam(void) -{ - if (XdrvMailbox.data_len) { - if ((ADC0_TEMP == XdrvMailbox.payload) || - (ADC0_LIGHT == XdrvMailbox.payload) || - (ADC0_RANGE == XdrvMailbox.payload) || - (ADC0_CT_POWER == XdrvMailbox.payload)) { - if (strstr(XdrvMailbox.data, ",") != nullptr) { - char sub_string[XdrvMailbox.data_len +1]; - - - - Settings.adc_param_type = XdrvMailbox.payload; - Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); - if (ADC0_RANGE == XdrvMailbox.payload) { - Settings.adc_param3 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 4), nullptr, 10)); - Settings.adc_param4 = abs(strtol(subStr(sub_string, XdrvMailbox.data, ",", 5), nullptr, 10)); - } else { - Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); - } - if (ADC0_CT_POWER == XdrvMailbox.payload) { - if ((Settings.adc_param1 & CT_FLAG_ENERGY_RESET) > 0) { - Adc.energy = 0; - Settings.adc_param1 ^= CT_FLAG_ENERGY_RESET; - } - } - } else { - - - - - Settings.adc_param_type = 0; - AdcInit(); - } - } - } - - - Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d"), Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2); - if (ADC0_RANGE == my_adc0) { - ResponseAppend_P(PSTR(",%d,%d"), Settings.adc_param3, Settings.adc_param4); - } else { - int value = Settings.adc_param3; - uint8_t precision; - for (precision = 4; precision > 0; precision--) { - if (value % 10) { break; } - value /= 10; - } - char param3[33]; - dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); - ResponseAppend_P(PSTR(",%s"), param3); - } - ResponseAppend_P(PSTR("]}")); -} - - - - - -bool Xsns02(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_COMMAND: - result = DecodeCommand(kAdcCommands, AdcCommand); - break; - default: - if ((ADC0_INPUT == my_adc0) || - (ADC0_TEMP == my_adc0) || - (ADC0_LIGHT == my_adc0) || - (ADC0_RANGE == my_adc0) || - (ADC0_CT_POWER == my_adc0)) { - switch (function) { -#ifdef USE_RULES - case FUNC_EVERY_250_MSECOND: - AdcEvery250ms(); - break; -#endif - case FUNC_EVERY_SECOND: - AdcEverySecond(); - break; - case FUNC_INIT: - AdcInit(); - break; - case FUNC_JSON_APPEND: - AdcShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AdcShow(0); - break; -#endif - } - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_04_snfsc.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_04_snfsc.ino" -#ifdef USE_SONOFF_SC -# 57 "S:/Development/Tasmota/tasmota/xsns_04_snfsc.ino" -#define XSNS_04 4 - -uint16_t sc_value[5] = { 0 }; - -void SonoffScSend(const char *data) -{ - Serial.write(data); - Serial.write('\x1B'); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data); -} - -void SonoffScInit(void) -{ - - SonoffScSend("AT+START"); - -} - -void SonoffScSerialInput(char *rcvstat) -{ - char *p; - char *str; - uint16_t value[5] = { 0 }; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat); - - if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { - int8_t i = -1; - for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(nullptr, ":", &p)) { - value[i++] = atoi(str); - } - if (value[0] > 0) { - for (uint32_t i = 0; i < 5; i++) { - sc_value[i] = value[i]; - } - sc_value[2] = (11 - sc_value[2]) * 10; - sc_value[3] *= 10; - sc_value[4] = (11 - sc_value[4]) * 10; - SonoffScSend("AT+SEND=ok"); - } else { - SonoffScSend("AT+SEND=fail"); - } - } - else if (!strcasecmp_P(rcvstat, PSTR("AT+STATUS?"))) { - SonoffScSend("AT+STATUS=4"); - } -} - - - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SCPLUS[] PROGMEM = - "{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; -#endif - -void SonoffScShow(bool json) -{ - if (sc_value[0] > 0) { - float t = ConvertTemp(sc_value[1]); - float h = ConvertHumidity(sc_value[0]); - - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), - temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]); - DomoticzSensor(DZ_COUNT, sc_value[3]); - DomoticzSensor(DZ_AIRQUALITY, 500 + ((100 - sc_value[4]) * 20)); - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, "", humidity); - WSContentSend_PD(HTTP_SNS_SCPLUS, sc_value[2], sc_value[3], sc_value[4]); -#endif - } - } -} - - - - - -bool Xsns04(uint8_t function) -{ - bool result = false; - - if (SONOFF_SC == my_module_type) { - switch (function) { - case FUNC_JSON_APPEND: - SonoffScShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SonoffScShow(0); - break; -#endif - case FUNC_INIT: - SonoffScInit(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_05_ds18x20.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_05_ds18x20.ino" -#ifdef USE_DS18x20 - - - - -#define XSNS_05 5 - - - -#define DS18S20_CHIPID 0x10 -#define DS1822_CHIPID 0x22 -#define DS18B20_CHIPID 0x28 -#define MAX31850_CHIPID 0x3B - -#define W1_SKIP_ROM 0xCC -#define W1_CONVERT_TEMP 0x44 -#define W1_WRITE_EEPROM 0x48 -#define W1_WRITE_SCRATCHPAD 0x4E -#define W1_READ_SCRATCHPAD 0xBE - -#define DS18X20_MAX_SENSORS 8 - -const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850"; - -uint8_t ds18x20_chipids[] = { 0, DS18S20_CHIPID, DS1822_CHIPID, DS18B20_CHIPID, MAX31850_CHIPID }; - -struct DS18X20STRUCT { - uint8_t address[8]; - uint8_t index; - uint8_t valid; - float temperature; -} ds18x20_sensor[DS18X20_MAX_SENSORS]; -uint8_t ds18x20_sensors = 0; -uint8_t ds18x20_pin = 0; -uint8_t ds18x20_pin_out = 0; -bool ds18x20_dual_mode = false; -char ds18x20_types[12]; -#ifdef W1_PARASITE_POWER -uint8_t ds18x20_sensor_curr = 0; -unsigned long w1_power_until = 0; -#endif - - - - - -#define W1_MATCH_ROM 0x55 -#define W1_SEARCH_ROM 0xF0 - -uint8_t onewire_last_discrepancy = 0; -uint8_t onewire_last_family_discrepancy = 0; -bool onewire_last_device_flag = false; -unsigned char onewire_rom_id[8] = { 0 }; - - - -uint8_t OneWireReset(void) -{ - uint8_t retries = 125; - - if (!ds18x20_dual_mode) { - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - do { - if (--retries == 0) { - return 0; - } - delayMicroseconds(2); - } while (!digitalRead(ds18x20_pin)); - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(480); - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - } else { - digitalWrite(ds18x20_pin_out, HIGH); - do { - if (--retries == 0) { - return 0; - } - delayMicroseconds(2); - } while (!digitalRead(ds18x20_pin)); - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(480); - digitalWrite(ds18x20_pin_out, HIGH); - } - delayMicroseconds(70); - uint8_t r = !digitalRead(ds18x20_pin); - delayMicroseconds(410); - return r; -} - -void OneWireWriteBit(uint8_t v) -{ - static const uint8_t delay_low[2] = { 65, 10 }; - static const uint8_t delay_high[2] = { 5, 55 }; - - v &= 1; - if (!ds18x20_dual_mode) { - digitalWrite(ds18x20_pin, LOW); - pinMode(ds18x20_pin, OUTPUT); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin, HIGH); - } else { - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(delay_low[v]); - digitalWrite(ds18x20_pin_out, HIGH); - } - delayMicroseconds(delay_high[v]); -} -# 150 "S:/Development/Tasmota/tasmota/xsns_05_ds18x20.ino" -void OneWireReadBit1(void) -{ - pinMode(ds18x20_pin, OUTPUT); - digitalWrite(ds18x20_pin, LOW); - delayMicroseconds(3); - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); -} - -void OneWireReadBit2(void) -{ - digitalWrite(ds18x20_pin_out, LOW); - delayMicroseconds(3); - digitalWrite(ds18x20_pin_out, HIGH); -} - -uint8_t OneWireReadBit(void) -{ - if (!ds18x20_dual_mode) { - OneWireReadBit1(); - } else { - OneWireReadBit2(); - } - delayMicroseconds(10); - uint8_t r = digitalRead(ds18x20_pin); - delayMicroseconds(53); - return r; -} - - - -void OneWireWrite(uint8_t v) -{ - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - OneWireWriteBit((bit_mask & v) ? 1 : 0); - } -} - -uint8_t OneWireRead(void) -{ - uint8_t r = 0; - - for (uint8_t bit_mask = 0x01; bit_mask; bit_mask <<= 1) { - if (OneWireReadBit()) { - r |= bit_mask; - } - } - return r; -} - -void OneWireSelect(const uint8_t rom[8]) -{ - OneWireWrite(W1_MATCH_ROM); - for (uint32_t i = 0; i < 8; i++) { - OneWireWrite(rom[i]); - } -} - -void OneWireResetSearch(void) -{ - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - for (uint32_t i = 0; i < 8; i++) { - onewire_rom_id[i] = 0; - } -} - -uint8_t OneWireSearch(uint8_t *newAddr) -{ - uint8_t id_bit_number = 1; - uint8_t last_zero = 0; - uint8_t rom_byte_number = 0; - uint8_t search_result = 0; - uint8_t id_bit; - uint8_t cmp_id_bit; - unsigned char rom_byte_mask = 1; - unsigned char search_direction; - - if (!onewire_last_device_flag) { - if (!OneWireReset()) { - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - return false; - } - OneWireWrite(W1_SEARCH_ROM); - do { - id_bit = OneWireReadBit(); - cmp_id_bit = OneWireReadBit(); - - if ((id_bit == 1) && (cmp_id_bit == 1)) { - break; - } else { - if (id_bit != cmp_id_bit) { - search_direction = id_bit; - } else { - if (id_bit_number < onewire_last_discrepancy) { - search_direction = ((onewire_rom_id[rom_byte_number] & rom_byte_mask) > 0); - } else { - search_direction = (id_bit_number == onewire_last_discrepancy); - } - if (search_direction == 0) { - last_zero = id_bit_number; - if (last_zero < 9) { - onewire_last_family_discrepancy = last_zero; - } - } - } - if (search_direction == 1) { - onewire_rom_id[rom_byte_number] |= rom_byte_mask; - } else { - onewire_rom_id[rom_byte_number] &= ~rom_byte_mask; - } - OneWireWriteBit(search_direction); - id_bit_number++; - rom_byte_mask <<= 1; - if (rom_byte_mask == 0) { - rom_byte_number++; - rom_byte_mask = 1; - } - } - } while (rom_byte_number < 8); - if (!(id_bit_number < 65)) { - onewire_last_discrepancy = last_zero; - if (onewire_last_discrepancy == 0) { - onewire_last_device_flag = true; - } - search_result = true; - } - } - if (!search_result || !onewire_rom_id[0]) { - onewire_last_discrepancy = 0; - onewire_last_device_flag = false; - onewire_last_family_discrepancy = 0; - search_result = false; - } - for (uint32_t i = 0; i < 8; i++) { - newAddr[i] = onewire_rom_id[i]; - } - return search_result; -} - -bool OneWireCrc8(uint8_t *addr) -{ - uint8_t crc = 0; - uint8_t len = 8; - - while (len--) { - uint8_t inbyte = *addr++; - for (uint32_t i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x01; - crc >>= 1; - if (mix) { - crc ^= 0x8C; - } - inbyte >>= 1; - } - } - return (crc == *addr); -} - - - -void Ds18x20Init(void) -{ - uint64_t ids[DS18X20_MAX_SENSORS]; - - ds18x20_pin = pin[GPIO_DSB]; - - if (pin[GPIO_DSB_OUT] < 99) { - ds18x20_pin_out = pin[GPIO_DSB_OUT]; - ds18x20_dual_mode = true; - pinMode(ds18x20_pin_out, OUTPUT); - pinMode(ds18x20_pin, Settings.flag3.ds18x20_internal_pullup ? INPUT_PULLUP : INPUT); - } - - OneWireResetSearch(); - - ds18x20_sensors = 0; - while (ds18x20_sensors < DS18X20_MAX_SENSORS) { - if (!OneWireSearch(ds18x20_sensor[ds18x20_sensors].address)) { - break; - } - if (OneWireCrc8(ds18x20_sensor[ds18x20_sensors].address) && - ((ds18x20_sensor[ds18x20_sensors].address[0] == DS18S20_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == DS1822_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == DS18B20_CHIPID) || - (ds18x20_sensor[ds18x20_sensors].address[0] == MAX31850_CHIPID))) { - ds18x20_sensor[ds18x20_sensors].index = ds18x20_sensors; - ids[ds18x20_sensors] = ds18x20_sensor[ds18x20_sensors].address[0]; - for (uint32_t j = 6; j > 0; j--) { - ids[ds18x20_sensors] = ids[ds18x20_sensors] << 8 | ds18x20_sensor[ds18x20_sensors].address[j]; - } - ds18x20_sensors++; - } - } - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - for (uint32_t j = i + 1; j < ds18x20_sensors; j++) { - if (ids[ds18x20_sensor[i].index] > ids[ds18x20_sensor[j].index]) { - std::swap(ds18x20_sensor[i].index, ds18x20_sensor[j].index); - } - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSORS_FOUND " %d"), ds18x20_sensors); -} - -void Ds18x20Convert(void) -{ - OneWireReset(); -#ifdef W1_PARASITE_POWER - - if (++ds18x20_sensor_curr >= ds18x20_sensors) - ds18x20_sensor_curr = 0; - OneWireSelect(ds18x20_sensor[ds18x20_sensor_curr].address); -#else - OneWireWrite(W1_SKIP_ROM); -#endif - OneWireWrite(W1_CONVERT_TEMP); - -} - -bool Ds18x20Read(uint8_t sensor) -{ - uint8_t data[9]; - int8_t sign = 1; - - uint8_t index = ds18x20_sensor[sensor].index; - if (ds18x20_sensor[index].valid) { ds18x20_sensor[index].valid--; } - for (uint32_t retry = 0; retry < 3; retry++) { - OneWireReset(); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_READ_SCRATCHPAD); - for (uint32_t i = 0; i < 9; i++) { - data[i] = OneWireRead(); - } - if (OneWireCrc8(data)) { - switch(ds18x20_sensor[index].address[0]) { - case DS18S20_CHIPID: { - if (data[1] > 0x80) { - data[0] = (~data[0]) +1; - sign = -1; - } - float temp9 = (float)(data[0] >> 1) * sign; - ds18x20_sensor[index].temperature = ConvertTemp((temp9 - 0.25) + ((16.0 - data[6]) / 16.0)); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - case DS1822_CHIPID: - case DS18B20_CHIPID: { - if (data[4] != 0x7F) { - data[4] = 0x7F; - OneWireReset(); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_WRITE_SCRATCHPAD); - OneWireWrite(data[2]); - OneWireWrite(data[3]); - OneWireWrite(data[4]); - OneWireSelect(ds18x20_sensor[index].address); - OneWireWrite(W1_WRITE_EEPROM); -#ifdef W1_PARASITE_POWER - w1_power_until = millis() + 10; -#endif - } - uint16_t temp12 = (data[1] << 8) + data[0]; - if (temp12 > 2047) { - temp12 = (~temp12) +1; - sign = -1; - } - ds18x20_sensor[index].temperature = ConvertTemp(sign * temp12 * 0.0625); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - case MAX31850_CHIPID: { - int16_t temp14 = (data[1] << 8) + (data[0] & 0xFC); - ds18x20_sensor[index].temperature = ConvertTemp(temp14 * 0.0625); - ds18x20_sensor[index].valid = SENSOR_MAX_MISS; - return true; - } - } - } - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DSB D_SENSOR_CRC_ERROR)); - return false; -} - -void Ds18x20Name(uint8_t sensor) -{ - uint8_t index = sizeof(ds18x20_chipids); - while (index) { - if (ds18x20_sensor[ds18x20_sensor[sensor].index].address[0] == ds18x20_chipids[index]) { - break; - } - index--; - } - GetTextIndexed(ds18x20_types, sizeof(ds18x20_types), index, kDs18x20Types); - if (ds18x20_sensors > 1) { - snprintf_P(ds18x20_types, sizeof(ds18x20_types), PSTR("%s%c%d"), ds18x20_types, IndexSeparator(), sensor +1); - } -} - - - -void Ds18x20EverySecond(void) -{ - if (!ds18x20_sensors) { return; } - -#ifdef W1_PARASITE_POWER - - unsigned long now = millis(); - if (now < w1_power_until) - return; -#endif - if (uptime & 1 -#ifdef W1_PARASITE_POWER - - || ds18x20_sensors >= 2 -#endif - ) { - - Ds18x20Convert(); - } else { - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - - if (!Ds18x20Read(i)) { - Ds18x20Name(i); - AddLogMissed(ds18x20_types, ds18x20_sensor[ds18x20_sensor[i].index].valid); -#ifdef USE_DS18x20_RECONFIGURE - if (!ds18x20_sensor[ds18x20_sensor[i].index].valid) { - memset(&ds18x20_sensor, 0, sizeof(ds18x20_sensor)); - Ds18x20Init(); - } -#endif - } - } - } -} - -void Ds18x20Show(bool json) -{ - for (uint32_t i = 0; i < ds18x20_sensors; i++) { - uint8_t index = ds18x20_sensor[i].index; - - if (ds18x20_sensor[index].valid) { - char temperature[33]; - dtostrfd(ds18x20_sensor[index].temperature, Settings.flag2.temperature_resolution, temperature); - - Ds18x20Name(i); - - if (json) { - char address[17]; - for (uint32_t j = 0; j < 6; j++) { - sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); - } - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, ds18x20_sensor[index].temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, ds18x20_types, temperature, TempUnit()); -#endif - } - } - } -} - - - - - -bool Xsns05(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_DSB] < 99) { - switch (function) { - case FUNC_INIT: - Ds18x20Init(); - break; - case FUNC_EVERY_SECOND: - Ds18x20EverySecond(); - break; - case FUNC_JSON_APPEND: - Ds18x20Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ds18x20Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_old.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_old.ino" -#ifdef USE_DHT_OLD -# 29 "S:/Development/Tasmota/tasmota/xsns_06_dht_old.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint32_t dht_max_cycles; -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -void DhtReadPrep(void) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - if (!dht_dual_mode) { - digitalWrite(Dht[i].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - } -} - -int32_t DhtExpectPulse(uint8_t sensor, bool level) -{ - int32_t count = 0; - - while (digitalRead(Dht[sensor].pin) == level) { - if (count++ >= (int32_t)dht_max_cycles) { - return -1; - } - } - return count; -} - -bool DhtRead(uint8_t sensor) -{ - int32_t cycles[80]; - uint8_t error = 0; - - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - - - - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { - Dht[sensor].lastresult = 0; - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delay(250); - } - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - if (GPIO_SI7021 == Dht[sensor].type) { - delayMicroseconds(500); - } else { - delay(20); - } - - noInterrupts(); - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - delayMicroseconds(40); - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - delayMicroseconds(40); - } - delayMicroseconds(10); - if (-1 == DhtExpectPulse(sensor, LOW)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - error = 1; - } - else if (-1 == DhtExpectPulse(sensor, HIGH)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - error = 1; - } - else { - for (uint32_t i = 0; i < 80; i += 2) { - cycles[i] = DhtExpectPulse(sensor, LOW); - cycles[i+1] = DhtExpectPulse(sensor, HIGH); - } - } - interrupts(); - - if (error) { return false; } - - for (uint32_t i = 0; i < 40; ++i) { - int32_t lowCycles = cycles[2*i]; - int32_t highCycles = cycles[2*i+1]; - if ((-1 == lowCycles) || (-1 == highCycles)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - return false; - } - dht_data[i/8] <<= 1; - if (highCycles > lowCycles) { - dht_data[i / 8] |= 1; - } - } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint8_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - dht_max_cycles = microsecondsToClockCycles(1000); - - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - - DhtReadPrep(); - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" -#ifdef USE_DHT_V2 -# 29 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint32_t dht_max_cycles; -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -void DhtReadPrep(void) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - if (!dht_dual_mode) { - digitalWrite(Dht[i].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - } -} - -int32_t DhtExpectPulse(uint8_t sensor, bool level) -{ - int32_t count = 0; - - while (digitalRead(Dht[sensor].pin) == level) { - if (count++ >= (int32_t)dht_max_cycles) { - return -1; - } - } - return count; -} - -bool DhtRead(uint8_t sensor) -{ - int32_t cycles[80]; - uint8_t error = 0; - - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { - Dht[sensor].lastresult = 0; - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delay(250); - } - - - noInterrupts(); - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_SI7021: -# 114 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" - delayMicroseconds(500); - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delayMicroseconds(40); - break; - - case GPIO_DHT22: -# 133 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" - delayMicroseconds(1100); - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delayMicroseconds(30); - break; - - case GPIO_DHT11: -# 151 "S:/Development/Tasmota/tasmota/xsns_06_dht_v2.ino" - default: - - delay(20); - if (!dht_dual_mode) { - digitalWrite(Dht[sensor].pin, HIGH); - } else { - digitalWrite(dht_pin_out, HIGH); - } - delayMicroseconds(30); - break; - } - - - pinMode(Dht[sensor].pin, INPUT_PULLUP); - - if (-1 == DhtExpectPulse(sensor, LOW)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - error = 1; - } - else if (-1 == DhtExpectPulse(sensor, HIGH)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - error = 1; - } - else { - for (uint32_t i = 0; i < 80; i += 2) { - cycles[i] = DhtExpectPulse(sensor, LOW); - cycles[i+1] = DhtExpectPulse(sensor, HIGH); - } - } - interrupts(); - if (error) { return false; } - - - for (uint32_t i = 0; i < 40; ++i) { - int32_t lowCycles = cycles[2*i]; - int32_t highCycles = cycles[2*i+1]; - if ((-1 == lowCycles) || (-1 == highCycles)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - return false; - } - dht_data[i/8] <<= 1; - if (highCycles > lowCycles) { - dht_data[i / 8] |= 1; - } - } - - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint8_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - dht_max_cycles = microsecondsToClockCycles(1000); - - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v2) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - - DhtReadPrep(); - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_v3.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_v3.ino" -#ifdef USE_DHT_V3 -# 30 "S:/Development/Tasmota/tasmota/xsns_06_dht_v3.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -bool DhtExpectPulse(uint8_t sensor, int level) -{ - unsigned long timeout = micros() + 100; - while (digitalRead(Dht[sensor].pin) != level) { - if (micros() > timeout) { return false; } - delayMicroseconds(1); - } - return true; -} - -int DhtReadDat(uint8_t sensor) -{ - uint8_t result = 0; - for (uint32_t i = 0; i < 8; i++) { - if (!DhtExpectPulse(sensor, HIGH)) { return -1; } - - delayMicroseconds(35); - if (digitalRead(Dht[sensor].pin)) { - result |= (1 << (7 - i)); - } - - if (!DhtExpectPulse(sensor, LOW)) { return -1; } - } - return result; -} - -bool DhtRead(uint8_t sensor) -{ - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - delay(19); - break; - case GPIO_DHT22: - delay(2); - break; - case GPIO_SI7021: - delayMicroseconds(500); - break; - } - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - case GPIO_DHT22: - delayMicroseconds(50); - break; - case GPIO_SI7021: - - delayMicroseconds(20); - break; - } - - noInterrupts(); - if (!DhtExpectPulse(sensor, LOW)) { - interrupts(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - return false; - } - if (!DhtExpectPulse(sensor, HIGH)) { - interrupts(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_HIGH " " D_PULSE)); - return false; - } - if (!DhtExpectPulse(sensor, LOW)) { - interrupts(); - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_START_SIGNAL_LOW " " D_PULSE)); - return false; - } - - int data = 0; - for (uint32_t i = 0; i < 5; i++) { - data = DhtReadDat(sensor); - if (-1 == data) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " " D_PULSE)); - break; - } - dht_data[i] = data; - } - interrupts(); - if (-1 == data) { return false; } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint8_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v3) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - - - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_v4.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_v4.ino" -#ifdef USE_DHT_V4 -# 30 "S:/Development/Tasmota/tasmota/xsns_06_dht_v4.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - char stype[12]; - uint32_t lastreadtime; - uint8_t lastresult; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -bool DhtExpectPulse(uint32_t sensor, uint32_t level) -{ - unsigned long timeout = micros() + 100; - while (digitalRead(Dht[sensor].pin) != level) { - if (micros() > timeout) { return false; } - delayMicroseconds(1); - } - return true; -} - -bool DhtRead(uint32_t sensor) -{ - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - delay(19); - break; - case GPIO_DHT22: - delay(2); - break; - case GPIO_SI7021: - delayMicroseconds(500); - break; - } - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - case GPIO_DHT22: - delayMicroseconds(50); - break; - case GPIO_SI7021: - delayMicroseconds(20); - break; - } - - uint32_t level = 9; - noInterrupts(); - for (uint32_t i = 0; i < 3; i++) { - level = i &1; - if (!DhtExpectPulse(sensor, level)) { break; } - level = 9; - } - if (9 == level) { - int data = 0; - for (uint32_t i = 0; i < 5; i++) { - data = 0; - for (uint32_t j = 0; j < 8; j++) { - level = 1; - if (!DhtExpectPulse(sensor, level)) { break; } - - delayMicroseconds(35); - if (digitalRead(Dht[sensor].pin)) { - data |= (1 << (7 - j)); - } - - level = 0; - if (!DhtExpectPulse(sensor, level)) { break; } - level = 9; - } - if (level < 2) { break; } - - dht_data[i] = data; - } - } - interrupts(); - if (level < 2) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), (0 == level) ? D_START_SIGNAL_LOW : D_START_SIGNAL_HIGH); - return false; - } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - return true; -} - -void DhtReadTempHum(uint32_t sensor) -{ - if ((NAN == Dht[sensor].h) || (Dht[sensor].lastresult > DHT_MAX_RETRY)) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - if (DhtRead(sensor)) { - switch (Dht[sensor].type) { - case GPIO_DHT11: - Dht[sensor].h = dht_data[0]; - Dht[sensor].t = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - Dht[sensor].h = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - Dht[sensor].t = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - Dht[sensor].t *= -1; - } - break; - } - Dht[sensor].t = ConvertTemp(Dht[sensor].t); - if (Dht[sensor].h > 100) { Dht[sensor].h = 100.0; } - if (Dht[sensor].h < 0) { Dht[sensor].h = 0.0; } - Dht[sensor].h = ConvertHumidity(Dht[sensor].h); - Dht[sensor].lastresult = 0; - } else { - Dht[sensor].lastresult++; - } -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastreadtime = 0; - Dht[i].lastresult = 0; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v4) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - } else { - for (uint32_t i = 0; i < dht_sensors; i++) { - - DhtReadTempHum(i); - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_06_dht_v5.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_06_dht_v5.ino" -#ifdef USE_DHT -# 30 "S:/Development/Tasmota/tasmota/xsns_06_dht_v5.ino" -#define XSNS_06 6 - -#define DHT_MAX_SENSORS 4 -#define DHT_MAX_RETRY 8 - -uint8_t dht_data[5]; -uint8_t dht_sensors = 0; -uint8_t dht_pin_out = 0; -bool dht_active = true; -bool dht_dual_mode = false; - -struct DHTSTRUCT { - uint8_t pin; - uint8_t type; - uint8_t lastresult; - char stype[12]; - float t = NAN; - float h = NAN; -} Dht[DHT_MAX_SENSORS]; - -bool DhtWaitState(uint32_t sensor, uint32_t level) -{ - unsigned long timeout = micros() + 100; - while (digitalRead(Dht[sensor].pin) != level) { - if (TimeReachedUsec(timeout)) { - PrepLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE), - (level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW); - return false; - } - delayMicroseconds(1); - } - return true; -} - -bool DhtRead(uint32_t sensor) -{ - dht_data[0] = dht_data[1] = dht_data[2] = dht_data[3] = dht_data[4] = 0; - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, OUTPUT); - digitalWrite(Dht[sensor].pin, LOW); - } else { - digitalWrite(dht_pin_out, LOW); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - delay(19); - break; - case GPIO_DHT22: - delay(2); - break; - case GPIO_SI7021: - delayMicroseconds(500); - break; - } - - if (!dht_dual_mode) { - pinMode(Dht[sensor].pin, INPUT_PULLUP); - } else { - digitalWrite(dht_pin_out, HIGH); - } - - switch (Dht[sensor].type) { - case GPIO_DHT11: - case GPIO_DHT22: - delayMicroseconds(50); - break; - case GPIO_SI7021: - delayMicroseconds(20); - break; - } -# 133 "S:/Development/Tasmota/tasmota/xsns_06_dht_v5.ino" - uint32_t i = 0; - noInterrupts(); - if (DhtWaitState(sensor, 0) && DhtWaitState(sensor, 1) && DhtWaitState(sensor, 0)) { - for (i = 0; i < 40; i++) { - if (!DhtWaitState(sensor, 1)) { break; } - delayMicroseconds(35); - if (digitalRead(Dht[sensor].pin)) { - dht_data[i / 8] |= (1 << (7 - i % 8)); - } - if (!DhtWaitState(sensor, 0)) { break; } - } - } - interrupts(); - if (i < 40) { return false; } - - uint8_t checksum = (dht_data[0] + dht_data[1] + dht_data[2] + dht_data[3]) & 0xFF; - if (dht_data[4] != checksum) { - char hex_char[15]; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_CHECKSUM_FAILURE " %s =? %02X"), - ToHex_P(dht_data, 5, hex_char, sizeof(hex_char), ' '), checksum); - return false; - } - - float temperature = NAN; - float humidity = NAN; - switch (Dht[sensor].type) { - case GPIO_DHT11: - humidity = dht_data[0]; - temperature = dht_data[2] + ((float)dht_data[3] * 0.1f); - break; - case GPIO_DHT22: - case GPIO_SI7021: - humidity = ((dht_data[0] << 8) | dht_data[1]) * 0.1; - temperature = (((dht_data[2] & 0x7F) << 8 ) | dht_data[3]) * 0.1; - if (dht_data[2] & 0x80) { - temperature *= -1; - } - break; - } - if (isnan(temperature) || isnan(humidity)) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "Invalid NAN reading")); - return false; - } - - if (humidity > 100) { humidity = 100.0; } - if (humidity < 0) { humidity = 0.1; } - Dht[sensor].h = ConvertHumidity(humidity); - Dht[sensor].t = ConvertTemp(temperature); - Dht[sensor].lastresult = 0; - - return true; -} - - - -bool DhtPinState() -{ - if ((XdrvMailbox.index >= GPIO_DHT11) && (XdrvMailbox.index <= GPIO_SI7021)) { - if (dht_sensors < DHT_MAX_SENSORS) { - Dht[dht_sensors].pin = XdrvMailbox.payload; - Dht[dht_sensors].type = XdrvMailbox.index; - dht_sensors++; - XdrvMailbox.index = GPIO_DHT11; - } else { - XdrvMailbox.index = 0; - } - return true; - } - return false; -} - -void DhtInit(void) -{ - if (dht_sensors) { - if (pin[GPIO_DHT11_OUT] < 99) { - dht_pin_out = pin[GPIO_DHT11_OUT]; - dht_dual_mode = true; - dht_sensors = 1; - pinMode(dht_pin_out, OUTPUT); - } - - for (uint32_t i = 0; i < dht_sensors; i++) { - pinMode(Dht[i].pin, INPUT_PULLUP); - Dht[i].lastresult = DHT_MAX_RETRY; - GetTextIndexed(Dht[i].stype, sizeof(Dht[i].stype), Dht[i].type, kSensorNames); - if (dht_sensors > 1) { - snprintf_P(Dht[i].stype, sizeof(Dht[i].stype), PSTR("%s%c%02d"), Dht[i].stype, IndexSeparator(), Dht[i].pin); - } - } - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT "(v5) " D_SENSORS_FOUND " %d"), dht_sensors); - } else { - dht_active = false; - } -} - -void DhtEverySecond(void) -{ - if (uptime &1) { - for (uint32_t sensor = 0; sensor < dht_sensors; sensor++) { - - if (!DhtRead(sensor)) { - Dht[sensor].lastresult++; - if (Dht[sensor].lastresult > DHT_MAX_RETRY) { - Dht[sensor].t = NAN; - Dht[sensor].h = NAN; - } - } - } - } -} - -void DhtShow(bool json) -{ - for (uint32_t i = 0; i < dht_sensors; i++) { - char temperature[33]; - dtostrfd(Dht[i].t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if ((0 == tele_period) && (0 == i)) { - KnxSensor(KNX_TEMPERATURE, Dht[i].t); - KnxSensor(KNX_HUMIDITY, Dht[i].h); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht[i].stype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht[i].stype, humidity); -#endif - } - } -} - - - - - -bool Xsns06(uint8_t function) -{ - bool result = false; - - if (dht_active) { - switch (function) { - case FUNC_EVERY_SECOND: - DhtEverySecond(); - break; - case FUNC_JSON_APPEND: - DhtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DhtShow(0); - break; -#endif - case FUNC_INIT: - DhtInit(); - break; - case FUNC_PIN_STATE: - result = DhtPinState(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_07_sht1x.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_07_sht1x.ino" -#ifdef USE_I2C -#ifdef USE_SHT -# 31 "S:/Development/Tasmota/tasmota/xsns_07_sht1x.ino" -#define XSNS_07 7 -#define XI2C_08 8 - -enum { - SHT1X_CMD_MEASURE_TEMP = B00000011, - SHT1X_CMD_MEASURE_RH = B00000101, - SHT1X_CMD_SOFT_RESET = B00011110 -}; - -uint8_t sht_sda_pin; -uint8_t sht_scl_pin; -uint8_t sht_type = 0; -char sht_types[] = "SHT1X"; -uint8_t sht_valid = 0; -float sht_temperature = 0; -float sht_humidity = 0; - -bool ShtReset(void) -{ - pinMode(sht_sda_pin, INPUT_PULLUP); - pinMode(sht_scl_pin, OUTPUT); - delay(11); - for (uint32_t i = 0; i < 9; i++) { - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - } - bool success = ShtSendCommand(SHT1X_CMD_SOFT_RESET); - delay(11); - return success; -} - -bool ShtSendCommand(const uint8_t cmd) -{ - pinMode(sht_sda_pin, OUTPUT); - - digitalWrite(sht_sda_pin, HIGH); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_sda_pin, LOW); - digitalWrite(sht_scl_pin, LOW); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_sda_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - - shiftOut(sht_sda_pin, sht_scl_pin, MSBFIRST, cmd); - - bool ackerror = false; - digitalWrite(sht_scl_pin, HIGH); - pinMode(sht_sda_pin, INPUT_PULLUP); - if (digitalRead(sht_sda_pin) != LOW) { - ackerror = true; - } - digitalWrite(sht_scl_pin, LOW); - delayMicroseconds(1); - if (digitalRead(sht_sda_pin) != HIGH) { - ackerror = true; - } - if (ackerror) { - - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_DID_NOT_ACK_COMMAND)); - } - return (!ackerror); -} - -bool ShtAwaitResult(void) -{ - - for (uint32_t i = 0; i < 16; i++) { - if (LOW == digitalRead(sht_sda_pin)) { - return true; - } - delay(20); - } - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_SHT1 D_SENSOR_BUSY)); - - return false; -} - -int ShtReadData(void) -{ - int val = 0; - - - val = shiftIn(sht_sda_pin, sht_scl_pin, 8); - val <<= 8; - - pinMode(sht_sda_pin, OUTPUT); - digitalWrite(sht_sda_pin, LOW); - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - pinMode(sht_sda_pin, INPUT_PULLUP); - - val |= shiftIn(sht_sda_pin, sht_scl_pin, 8); - - digitalWrite(sht_scl_pin, HIGH); - digitalWrite(sht_scl_pin, LOW); - return val; -} - -bool ShtRead(void) -{ - if (sht_valid) { sht_valid--; } - if (!ShtReset()) { return false; } - if (!ShtSendCommand(SHT1X_CMD_MEASURE_TEMP)) { return false; } - if (!ShtAwaitResult()) { return false; } - float tempRaw = ShtReadData(); - if (!ShtSendCommand(SHT1X_CMD_MEASURE_RH)) { return false; } - if (!ShtAwaitResult()) { return false; } - float humRaw = ShtReadData(); - - - const float d1 = -39.7; - const float d2 = 0.01; - sht_temperature = d1 + (tempRaw * d2); - const float c1 = -2.0468; - const float c2 = 0.0367; - const float c3 = -1.5955E-6; - const float t1 = 0.01; - const float t2 = 0.00008; - float rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw; - sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear; - sht_temperature = ConvertTemp(sht_temperature); - ConvertHumidity(sht_humidity); - - sht_valid = SENSOR_MAX_MISS; - return true; -} - - - -void ShtDetect(void) -{ - sht_sda_pin = pin[GPIO_I2C_SDA]; - sht_scl_pin = pin[GPIO_I2C_SCL]; - if (ShtRead()) { - sht_type = 1; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C D_SHT1X_FOUND)); - } else { - Wire.begin(sht_sda_pin, sht_scl_pin); - sht_type = 0; - } -} - -void ShtEverySecond(void) -{ - if (!(uptime %4)) { - - if (!ShtRead()) { - AddLogMissed(sht_types, sht_valid); - } - } -} - -void ShtShow(bool json) -{ - if (sht_valid) { - char temperature[33]; - dtostrfd(sht_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, sht_types, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, sht_temperature); - KnxSensor(KNX_HUMIDITY, sht_humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sht_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, sht_types, humidity); -#endif - } - } -} - - - - - -bool Xsns07(uint8_t function) -{ - if (!I2cEnabled(XI2C_08)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - ShtDetect(); - } - else if (sht_type) { - switch (function) { - case FUNC_EVERY_SECOND: - ShtEverySecond(); - break; - case FUNC_JSON_APPEND: - ShtShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - ShtShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_08_htu21.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_08_htu21.ino" -#ifdef USE_I2C -#ifdef USE_HTU -# 30 "S:/Development/Tasmota/tasmota/xsns_08_htu21.ino" -#define XSNS_08 8 -#define XI2C_09 9 - -#define HTU21_ADDR 0x40 - -#define SI7013_CHIPID 0x0D -#define SI7020_CHIPID 0x14 -#define SI7021_CHIPID 0x15 -#define HTU21_CHIPID 0x32 - -#define HTU21_READTEMP 0xE3 -#define HTU21_READHUM 0xE5 -#define HTU21_WRITEREG 0xE6 -#define HTU21_READREG 0xE7 -#define HTU21_RESET 0xFE -#define HTU21_HEATER_WRITE 0x51 -#define HTU21_HEATER_READ 0x11 -#define HTU21_SERIAL2_READ1 0xFC -#define HTU21_SERIAL2_READ2 0xC9 - -#define HTU21_HEATER_ON 0x04 -#define HTU21_HEATER_OFF 0xFB - -#define HTU21_RES_RH12_T14 0x00 -#define HTU21_RES_RH8_T12 0x01 -#define HTU21_RES_RH10_T13 0x80 -#define HTU21_RES_RH11_T11 0x81 - -#define HTU21_CRC8_POLYNOM 0x13100 - -const char kHtuTypes[] PROGMEM = "HTU21|SI7013|SI7020|SI7021|T/RH?"; - -uint8_t htu_address; -uint8_t htu_type = 0; -uint8_t htu_delay_temp; -uint8_t htu_delay_humidity = 50; -uint8_t htu_valid = 0; -float htu_temperature = 0; -float htu_humidity = 0; -char htu_types[7]; - -uint8_t HtuCheckCrc8(uint16_t data) -{ - for (uint32_t bit = 0; bit < 16; bit++) { - if (data & 0x8000) { - data = (data << 1) ^ HTU21_CRC8_POLYNOM; - } else { - data <<= 1; - } - } - return data >>= 8; -} - -uint8_t HtuReadDeviceId(void) -{ - uint16_t deviceID = 0; - uint8_t checksum = 0; - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_SERIAL2_READ1); - Wire.write(HTU21_SERIAL2_READ2); - Wire.endTransmission(); - - Wire.requestFrom(HTU21_ADDR, 3); - deviceID = Wire.read() << 8; - deviceID |= Wire.read(); - checksum = Wire.read(); - if (HtuCheckCrc8(deviceID) == checksum) { - deviceID = deviceID >> 8; - } else { - deviceID = 0; - } - return (uint8_t)deviceID; -} - -void HtuSetResolution(uint8_t resolution) -{ - uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); - current &= 0x7E; - current |= resolution; - I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); -} - -void HtuReset(void) -{ - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_RESET); - Wire.endTransmission(); - delay(15); -} - -void HtuHeater(uint8_t heater) -{ - uint8_t current = I2cRead8(HTU21_ADDR, HTU21_READREG); - - switch(heater) - { - case HTU21_HEATER_ON : current |= heater; - break; - case HTU21_HEATER_OFF : current &= heater; - break; - default : current &= heater; - break; - } - I2cWrite8(HTU21_ADDR, HTU21_WRITEREG, current); -} - -void HtuInit(void) -{ - HtuReset(); - HtuHeater(HTU21_HEATER_OFF); - HtuSetResolution(HTU21_RES_RH12_T14); -} - -bool HtuRead(void) -{ - uint8_t checksum = 0; - uint16_t sensorval = 0; - - if (htu_valid) { htu_valid--; } - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_READTEMP); - if (Wire.endTransmission() != 0) { return false; } - delay(htu_delay_temp); - - Wire.requestFrom(HTU21_ADDR, 3); - if (3 == Wire.available()) { - sensorval = Wire.read() << 8; - sensorval |= Wire.read(); - checksum = Wire.read(); - } - if (HtuCheckCrc8(sensorval) != checksum) { return false; } - - htu_temperature = ConvertTemp(0.002681 * (float)sensorval - 46.85); - - Wire.beginTransmission(HTU21_ADDR); - Wire.write(HTU21_READHUM); - if (Wire.endTransmission() != 0) { return false; } - delay(htu_delay_humidity); - - Wire.requestFrom(HTU21_ADDR, 3); - if (3 <= Wire.available()) { - sensorval = Wire.read() << 8; - sensorval |= Wire.read(); - checksum = Wire.read(); - } - if (HtuCheckCrc8(sensorval) != checksum) { return false; } - - sensorval ^= 0x02; - htu_humidity = 0.001907 * (float)sensorval - 6; - if (htu_humidity > 100) { htu_humidity = 100.0; } - if (htu_humidity < 0) { htu_humidity = 0.01; } - - if ((0.00 == htu_humidity) && (0.00 == htu_temperature)) { - htu_humidity = 0.0; - } - if ((htu_temperature > 0.00) && (htu_temperature < 80.00)) { - htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity; - } - ConvertHumidity(htu_humidity); - - htu_valid = SENSOR_MAX_MISS; - return true; -} - - - -void HtuDetect(void) -{ - htu_address = HTU21_ADDR; - if (I2cActive(htu_address)) { return; } - - htu_type = HtuReadDeviceId(); - if (htu_type) { - uint8_t index = 0; - HtuInit(); - switch (htu_type) { - case HTU21_CHIPID: - htu_delay_temp = 50; - htu_delay_humidity = 16; - break; - case SI7021_CHIPID: - index++; - case SI7020_CHIPID: - index++; - case SI7013_CHIPID: - index++; - htu_delay_temp = 12; - htu_delay_humidity = 23; - break; - default: - index = 4; - htu_delay_temp = 50; - htu_delay_humidity = 23; - } - GetTextIndexed(htu_types, sizeof(htu_types), index, kHtuTypes); - I2cSetActiveFound(htu_address, htu_types); - } -} - -void HtuEverySecond(void) -{ - if (uptime &1) { - - if (!HtuRead()) { - AddLogMissed(htu_types, htu_valid); - } - } -} - -void HtuShow(bool json) -{ - if (htu_valid) { - char temperature[33]; - dtostrfd(htu_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, htu_types, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, htu_temperature); - KnxSensor(KNX_HUMIDITY, htu_humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, htu_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, htu_types, humidity); -#endif - } - } -} - - - - - -bool Xsns08(uint8_t function) -{ - if (!I2cEnabled(XI2C_09)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - HtuDetect(); - } - else if (htu_type) { - switch (function) { - case FUNC_EVERY_SECOND: - HtuEverySecond(); - break; - case FUNC_JSON_APPEND: - HtuShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HtuShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_09_bmp.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_09_bmp.ino" -#ifdef USE_I2C -#ifdef USE_BMP -# 30 "S:/Development/Tasmota/tasmota/xsns_09_bmp.ino" -#define XSNS_09 9 -#define XI2C_10 10 - -#define BMP_ADDR1 0x76 -#define BMP_ADDR2 0x77 - -#define BMP180_CHIPID 0x55 -#define BMP280_CHIPID 0x58 -#define BME280_CHIPID 0x60 -#define BME680_CHIPID 0x61 - -#define BMP_REGISTER_CHIPID 0xD0 - -#define BMP_REGISTER_RESET 0xE0 - -#define BMP_CMND_RESET 0xB6 - -#define BMP_MAX_SENSORS 2 - -const char kBmpTypes[] PROGMEM = "BMP180|BMP280|BME280|BME680"; - -typedef struct { - uint8_t bmp_address; - char bmp_name[7]; - uint8_t bmp_type; - uint8_t bmp_model; -#ifdef USE_BME680 - uint8_t bme680_state; - float bmp_gas_resistance; -#endif - float bmp_temperature; - float bmp_pressure; - float bmp_humidity; -} bmp_sensors_t; - -uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; -uint8_t bmp_count = 0; -uint8_t bmp_once = 1; - -bmp_sensors_t *bmp_sensors = nullptr; - - - - - -#define BMP180_REG_CONTROL 0xF4 -#define BMP180_REG_RESULT 0xF6 -#define BMP180_TEMPERATURE 0x2E -#define BMP180_PRESSURE3 0xF4 - -#define BMP180_AC1 0xAA -#define BMP180_AC2 0xAC -#define BMP180_AC3 0xAE -#define BMP180_AC4 0xB0 -#define BMP180_AC5 0xB2 -#define BMP180_AC6 0xB4 -#define BMP180_VB1 0xB6 -#define BMP180_VB2 0xB8 -#define BMP180_MB 0xBA -#define BMP180_MC 0xBC -#define BMP180_MD 0xBE - -#define BMP180_OSS 3 - -typedef struct { - int16_t cal_ac1; - int16_t cal_ac2; - int16_t cal_ac3; - int16_t cal_b1; - int16_t cal_b2; - int16_t cal_mc; - int16_t cal_md; - uint16_t cal_ac4; - uint16_t cal_ac5; - uint16_t cal_ac6; -} bmp180_cal_data_t; - -bmp180_cal_data_t *bmp180_cal_data = nullptr; - -bool Bmp180Calibration(uint8_t bmp_idx) -{ - if (!bmp180_cal_data) { - bmp180_cal_data = (bmp180_cal_data_t*)malloc(BMP_MAX_SENSORS * sizeof(bmp180_cal_data_t)); - } - if (!bmp180_cal_data) { return false; } - - bmp180_cal_data[bmp_idx].cal_ac1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC1); - bmp180_cal_data[bmp_idx].cal_ac2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC2); - bmp180_cal_data[bmp_idx].cal_ac3 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC3); - bmp180_cal_data[bmp_idx].cal_ac4 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC4); - bmp180_cal_data[bmp_idx].cal_ac5 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC5); - bmp180_cal_data[bmp_idx].cal_ac6 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_AC6); - bmp180_cal_data[bmp_idx].cal_b1 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB1); - bmp180_cal_data[bmp_idx].cal_b2 = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_VB2); - bmp180_cal_data[bmp_idx].cal_mc = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MC); - bmp180_cal_data[bmp_idx].cal_md = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_MD); - - - if (!bmp180_cal_data[bmp_idx].cal_ac1 | - !bmp180_cal_data[bmp_idx].cal_ac2 | - !bmp180_cal_data[bmp_idx].cal_ac3 | - !bmp180_cal_data[bmp_idx].cal_ac4 | - !bmp180_cal_data[bmp_idx].cal_ac5 | - !bmp180_cal_data[bmp_idx].cal_ac6 | - !bmp180_cal_data[bmp_idx].cal_b1 | - !bmp180_cal_data[bmp_idx].cal_b2 | - !bmp180_cal_data[bmp_idx].cal_mc | - !bmp180_cal_data[bmp_idx].cal_md) { - return false; - } - - if ((bmp180_cal_data[bmp_idx].cal_ac1 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac2 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac3 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac4 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac5 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_ac6 == 0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_b1 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_b2 == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_mc == (int16_t)0xFFFF) | - (bmp180_cal_data[bmp_idx].cal_md == (int16_t)0xFFFF)) { - return false; - } - return true; -} - -void Bmp180Read(uint8_t bmp_idx) -{ - if (!bmp180_cal_data) { return; } - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_TEMPERATURE); - delay(5); - int ut = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); - int32_t xt1 = (ut - (int32_t)bmp180_cal_data[bmp_idx].cal_ac6) * ((int32_t)bmp180_cal_data[bmp_idx].cal_ac5) >> 15; - int32_t xt2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_mc << 11) / (xt1 + (int32_t)bmp180_cal_data[bmp_idx].cal_md); - int32_t bmp180_b5 = xt1 + xt2; - bmp_sensors[bmp_idx].bmp_temperature = ((bmp180_b5 + 8) >> 4) / 10.0; - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_CONTROL, BMP180_PRESSURE3); - delay(2 + (4 << BMP180_OSS)); - uint32_t up = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BMP180_REG_RESULT); - up >>= (8 - BMP180_OSS); - - int32_t b6 = bmp180_b5 - 4000; - int32_t x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b2 * ((b6 * b6) >> 12)) >> 11; - int32_t x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac2 * b6) >> 11; - int32_t x3 = x1 + x2; - int32_t b3 = ((((int32_t)bmp180_cal_data[bmp_idx].cal_ac1 * 4 + x3) << BMP180_OSS) + 2) >> 2; - - x1 = ((int32_t)bmp180_cal_data[bmp_idx].cal_ac3 * b6) >> 13; - x2 = ((int32_t)bmp180_cal_data[bmp_idx].cal_b1 * ((b6 * b6) >> 12)) >> 16; - x3 = ((x1 + x2) + 2) >> 2; - uint32_t b4 = ((uint32_t)bmp180_cal_data[bmp_idx].cal_ac4 * (uint32_t)(x3 + 32768)) >> 15; - uint32_t b7 = ((uint32_t)up - b3) * (uint32_t)(50000UL >> BMP180_OSS); - - int32_t p; - if (b7 < 0x80000000) { - p = (b7 * 2) / b4; - } - else { - p = (b7 / b4) * 2; - } - x1 = (p >> 8) * (p >> 8); - x1 = (x1 * 3038) >> 16; - x2 = (-7357 * p) >> 16; - p += ((x1 + x2 + (int32_t)3791) >> 4); - bmp_sensors[bmp_idx].bmp_pressure = (float)p / 100.0; -} - - - - - - - -#define BME280_REGISTER_CONTROLHUMID 0xF2 -#define BME280_REGISTER_CONTROL 0xF4 -#define BME280_REGISTER_CONFIG 0xF5 -#define BME280_REGISTER_PRESSUREDATA 0xF7 -#define BME280_REGISTER_TEMPDATA 0xFA -#define BME280_REGISTER_HUMIDDATA 0xFD - -#define BME280_REGISTER_DIG_T1 0x88 -#define BME280_REGISTER_DIG_T2 0x8A -#define BME280_REGISTER_DIG_T3 0x8C -#define BME280_REGISTER_DIG_P1 0x8E -#define BME280_REGISTER_DIG_P2 0x90 -#define BME280_REGISTER_DIG_P3 0x92 -#define BME280_REGISTER_DIG_P4 0x94 -#define BME280_REGISTER_DIG_P5 0x96 -#define BME280_REGISTER_DIG_P6 0x98 -#define BME280_REGISTER_DIG_P7 0x9A -#define BME280_REGISTER_DIG_P8 0x9C -#define BME280_REGISTER_DIG_P9 0x9E -#define BME280_REGISTER_DIG_H1 0xA1 -#define BME280_REGISTER_DIG_H2 0xE1 -#define BME280_REGISTER_DIG_H3 0xE3 -#define BME280_REGISTER_DIG_H4 0xE4 -#define BME280_REGISTER_DIG_H5 0xE5 -#define BME280_REGISTER_DIG_H6 0xE7 - -typedef struct { - uint16_t dig_T1; - int16_t dig_T2; - int16_t dig_T3; - uint16_t dig_P1; - int16_t dig_P2; - int16_t dig_P3; - int16_t dig_P4; - int16_t dig_P5; - int16_t dig_P6; - int16_t dig_P7; - int16_t dig_P8; - int16_t dig_P9; - int16_t dig_H2; - int16_t dig_H4; - int16_t dig_H5; - uint8_t dig_H1; - uint8_t dig_H3; - int8_t dig_H6; -} Bme280CalibrationData_t; - -Bme280CalibrationData_t *Bme280CalibrationData = nullptr; - -bool Bmx280Calibrate(uint8_t bmp_idx) -{ - - - if (!Bme280CalibrationData) { - Bme280CalibrationData = (Bme280CalibrationData_t*)malloc(BMP_MAX_SENSORS * sizeof(Bme280CalibrationData_t)); - } - if (!Bme280CalibrationData) { return false; } - - Bme280CalibrationData[bmp_idx].dig_T1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T1); - Bme280CalibrationData[bmp_idx].dig_T2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T2); - Bme280CalibrationData[bmp_idx].dig_T3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_T3); - Bme280CalibrationData[bmp_idx].dig_P1 = I2cRead16LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P1); - Bme280CalibrationData[bmp_idx].dig_P2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P2); - Bme280CalibrationData[bmp_idx].dig_P3 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P3); - Bme280CalibrationData[bmp_idx].dig_P4 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P4); - Bme280CalibrationData[bmp_idx].dig_P5 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P5); - Bme280CalibrationData[bmp_idx].dig_P6 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P6); - Bme280CalibrationData[bmp_idx].dig_P7 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P7); - Bme280CalibrationData[bmp_idx].dig_P8 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P8); - Bme280CalibrationData[bmp_idx].dig_P9 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_P9); - if (BME280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { - Bme280CalibrationData[bmp_idx].dig_H1 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H1); - Bme280CalibrationData[bmp_idx].dig_H2 = I2cReadS16_LE(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H2); - Bme280CalibrationData[bmp_idx].dig_H3 = I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H3); - Bme280CalibrationData[bmp_idx].dig_H4 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H4 + 1) & 0xF); - Bme280CalibrationData[bmp_idx].dig_H5 = (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5 + 1) << 4) | (I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H5) >> 4); - Bme280CalibrationData[bmp_idx].dig_H6 = (int8_t)I2cRead8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_DIG_H6); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x00); - - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROLHUMID, 0x01); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONFIG, 0xA0); - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0x27); - } else { - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_CONTROL, 0xB7); - } - - return true; -} - -void Bme280Read(uint8_t bmp_idx) -{ - if (!Bme280CalibrationData) { return; } - - int32_t adc_T = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_TEMPDATA); - adc_T >>= 4; - - int32_t vart1 = ((((adc_T >> 3) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1 << 1))) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_T2)) >> 11; - int32_t vart2 = (((((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1)) * ((adc_T >> 4) - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T1))) >> 12) * - ((int32_t)Bme280CalibrationData[bmp_idx].dig_T3)) >> 14; - int32_t t_fine = vart1 + vart2; - float T = (t_fine * 5 + 128) >> 8; - bmp_sensors[bmp_idx].bmp_temperature = T / 100.0; - - int32_t adc_P = I2cRead24(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_PRESSUREDATA); - adc_P >>= 4; - - int64_t var1 = ((int64_t)t_fine) - 128000; - int64_t var2 = var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P6; - var2 = var2 + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P5) << 17); - var2 = var2 + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P4) << 35); - var1 = ((var1 * var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P3) >> 8) + ((var1 * (int64_t)Bme280CalibrationData[bmp_idx].dig_P2) << 12); - var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)Bme280CalibrationData[bmp_idx].dig_P1) >> 33; - if (0 == var1) { - return; - } - int64_t p = 1048576 - adc_P; - p = (((p << 31) - var2) * 3125) / var1; - var1 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P9) * (p >> 13) * (p >> 13)) >> 25; - var2 = (((int64_t)Bme280CalibrationData[bmp_idx].dig_P8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((int64_t)Bme280CalibrationData[bmp_idx].dig_P7) << 4); - bmp_sensors[bmp_idx].bmp_pressure = (float)p / 25600.0; - - if (BMP280_CHIPID == bmp_sensors[bmp_idx].bmp_type) { return; } - - int32_t adc_H = I2cRead16(bmp_sensors[bmp_idx].bmp_address, BME280_REGISTER_HUMIDDATA); - - int32_t v_x1_u32r = (t_fine - ((int32_t)76800)); - v_x1_u32r = (((((adc_H << 14) - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H4) << 20) - - (((int32_t)Bme280CalibrationData[bmp_idx].dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * - (((((((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H6)) >> 10) * - (((v_x1_u32r * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + - ((int32_t)2097152)) * ((int32_t)Bme280CalibrationData[bmp_idx].dig_H2) + 8192) >> 14)); - v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * - ((int32_t)Bme280CalibrationData[bmp_idx].dig_H1)) >> 4)); - v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; - v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; - float h = (v_x1_u32r >> 12); - bmp_sensors[bmp_idx].bmp_humidity = h / 1024.0; -} - -#ifdef USE_BME680 - - - - -#include - -struct bme680_dev *gas_sensor = nullptr; - -static void BmeDelayMs(uint32_t ms) -{ - delay(ms); -} - -bool Bme680Init(uint8_t bmp_idx) -{ - if (!gas_sensor) { - gas_sensor = (bme680_dev*)malloc(BMP_MAX_SENSORS * sizeof(bme680_dev)); - } - if (!gas_sensor) { return false; } - - gas_sensor[bmp_idx].dev_id = bmp_sensors[bmp_idx].bmp_address; - gas_sensor[bmp_idx].intf = BME680_I2C_INTF; - gas_sensor[bmp_idx].read = &I2cReadBuffer; - gas_sensor[bmp_idx].write = &I2cWriteBuffer; - gas_sensor[bmp_idx].delay_ms = BmeDelayMs; - - - - gas_sensor[bmp_idx].amb_temp = 25; - - int8_t rslt = BME680_OK; - rslt = bme680_init(&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return false; } - - - gas_sensor[bmp_idx].tph_sett.os_hum = BME680_OS_2X; - gas_sensor[bmp_idx].tph_sett.os_pres = BME680_OS_4X; - gas_sensor[bmp_idx].tph_sett.os_temp = BME680_OS_8X; - gas_sensor[bmp_idx].tph_sett.filter = BME680_FILTER_SIZE_3; - - - gas_sensor[bmp_idx].gas_sett.run_gas = BME680_ENABLE_GAS_MEAS; - - gas_sensor[bmp_idx].gas_sett.heatr_temp = 320; - gas_sensor[bmp_idx].gas_sett.heatr_dur = 150; - - - - gas_sensor[bmp_idx].power_mode = BME680_FORCED_MODE; - - - uint8_t set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; - - - rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return false; } - - bmp_sensors[bmp_idx].bme680_state = 0; - - return true; -} - -void Bme680Read(uint8_t bmp_idx) -{ - if (!gas_sensor) { return; } - - int8_t rslt = BME680_OK; - - if (BME680_CHIPID == bmp_sensors[bmp_idx].bmp_type) { - if (0 == bmp_sensors[bmp_idx].bme680_state) { - - rslt = bme680_set_sensor_mode(&gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return; } - - - - - - - - bmp_sensors[bmp_idx].bme680_state = 1; - } else { - bmp_sensors[bmp_idx].bme680_state = 0; - - struct bme680_field_data data; - rslt = bme680_get_sensor_data(&data, &gas_sensor[bmp_idx]); - if (rslt != BME680_OK) { return; } - - bmp_sensors[bmp_idx].bmp_temperature = data.temperature / 100.0; - bmp_sensors[bmp_idx].bmp_humidity = data.humidity / 1000.0; - bmp_sensors[bmp_idx].bmp_pressure = data.pressure / 100.0; - - if (data.status & BME680_GASM_VALID_MSK) { - bmp_sensors[bmp_idx].bmp_gas_resistance = data.gas_resistance / 1000.0; - } else { - bmp_sensors[bmp_idx].bmp_gas_resistance = 0; - } - } - } - return; -} - -#endif - - - -void BmpDetect(void) -{ - int bmp_sensor_size = BMP_MAX_SENSORS * sizeof(bmp_sensors_t); - if (!bmp_sensors) { - bmp_sensors = (bmp_sensors_t*)malloc(bmp_sensor_size); - } - if (!bmp_sensors) { return; } - memset(bmp_sensors, 0, bmp_sensor_size); - - for (uint32_t i = 0; i < BMP_MAX_SENSORS; i++) { - if (I2cActive(bmp_addresses[i])) { continue; } - uint8_t bmp_type = I2cRead8(bmp_addresses[i], BMP_REGISTER_CHIPID); - if (bmp_type) { - bmp_sensors[bmp_count].bmp_address = bmp_addresses[i]; - bmp_sensors[bmp_count].bmp_type = bmp_type; - bmp_sensors[bmp_count].bmp_model = 0; - - bool success = false; - switch (bmp_type) { - case BMP180_CHIPID: - success = Bmp180Calibration(bmp_count); - break; - case BME280_CHIPID: - bmp_sensors[bmp_count].bmp_model++; - case BMP280_CHIPID: - bmp_sensors[bmp_count].bmp_model++; - success = Bmx280Calibrate(bmp_count); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - bmp_sensors[bmp_count].bmp_model = 3; - success = Bme680Init(bmp_count); - break; -#endif - } - if (success) { - GetTextIndexed(bmp_sensors[bmp_count].bmp_name, sizeof(bmp_sensors[bmp_count].bmp_name), bmp_sensors[bmp_count].bmp_model, kBmpTypes); - I2cSetActiveFound(bmp_sensors[bmp_count].bmp_address, bmp_sensors[bmp_count].bmp_name); - bmp_count++; - } - } - } -} - -void BmpRead(void) -{ - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - switch (bmp_sensors[bmp_idx].bmp_type) { - case BMP180_CHIPID: - Bmp180Read(bmp_idx); - break; - case BMP280_CHIPID: - case BME280_CHIPID: - Bme280Read(bmp_idx); - break; -#ifdef USE_BME680 - case BME680_CHIPID: - Bme680Read(bmp_idx); - break; -#endif - } - } - ConvertTemp(bmp_sensors[0].bmp_temperature); - ConvertHumidity(bmp_sensors[0].bmp_humidity); -} - -void BmpShow(bool json) -{ - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - if (bmp_sensors[bmp_idx].bmp_type) { - float bmp_sealevel = 0.0; - if (bmp_sensors[bmp_idx].bmp_pressure != 0.0) { - bmp_sealevel = (bmp_sensors[bmp_idx].bmp_pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0), 5.255)) - 21.6; - bmp_sealevel = ConvertPressure(bmp_sealevel); - } - float bmp_temperature = ConvertTemp(bmp_sensors[bmp_idx].bmp_temperature); - float bmp_pressure = ConvertPressure(bmp_sensors[bmp_idx].bmp_pressure); - - char name[10]; - strlcpy(name, bmp_sensors[bmp_idx].bmp_name, sizeof(name)); - if (bmp_count > 1) { - snprintf_P(name, sizeof(name), PSTR("%s%c%02X"), name, IndexSeparator(), bmp_sensors[bmp_idx].bmp_address); - } - - char temperature[33]; - dtostrfd(bmp_temperature, Settings.flag2.temperature_resolution, temperature); - char pressure[33]; - dtostrfd(bmp_pressure, Settings.flag2.pressure_resolution, pressure); - char sea_pressure[33]; - dtostrfd(bmp_sealevel, Settings.flag2.pressure_resolution, sea_pressure); - char humidity[33]; - dtostrfd(bmp_sensors[bmp_idx].bmp_humidity, Settings.flag2.humidity_resolution, humidity); -#ifdef USE_BME680 - char gas_resistance[33]; - dtostrfd(bmp_sensors[bmp_idx].bmp_gas_resistance, 2, gas_resistance); -#endif - - if (json) { - char json_humidity[40]; - snprintf_P(json_humidity, sizeof(json_humidity), PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - char json_sealevel[40]; - snprintf_P(json_sealevel, sizeof(json_sealevel), PSTR(",\"" D_JSON_PRESSUREATSEALEVEL "\":%s"), sea_pressure); -#ifdef USE_BME680 - char json_gas[40]; - snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); - - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), - name, - temperature, - (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", - pressure, - (Settings.altitude != 0) ? json_sealevel : "", - (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); -#else - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), - name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); -#endif - -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == bmp_idx)) { - DomoticzTempHumPressureSensor(temperature, humidity, pressure); -#ifdef USE_BME680 - if (bmp_sensors[bmp_idx].bmp_model >= 3) { DomoticzSensor(DZ_AIRQUALITY, (uint32_t)bmp_sensors[bmp_idx].bmp_gas_resistance); } -#endif - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, bmp_temperature); - KnxSensor(KNX_HUMIDITY, bmp_sensors[bmp_idx].bmp_humidity); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, name, temperature, TempUnit()); - if (bmp_sensors[bmp_idx].bmp_model >= 2) { - WSContentSend_PD(HTTP_SNS_HUM, name, humidity); - } - WSContentSend_PD(HTTP_SNS_PRESSURE, name, pressure, PressureUnit().c_str()); - if (Settings.altitude != 0) { - WSContentSend_PD(HTTP_SNS_SEAPRESSURE, name, sea_pressure, PressureUnit().c_str()); - } -#ifdef USE_BME680 - if (bmp_sensors[bmp_idx].bmp_model >= 3) { - WSContentSend_PD(PSTR("{s}%s " D_GAS "{m}%s " D_UNIT_KILOOHM "{e}"), name, gas_resistance); - } -#endif - -#endif - } - } - } -} - -#ifdef USE_DEEPSLEEP - -void BMP_EnterSleep(void) -{ - for (uint32_t bmp_idx = 0; bmp_idx < bmp_count; bmp_idx++) { - switch (bmp_sensors[bmp_idx].bmp_type) { - case BMP180_CHIPID: - case BMP280_CHIPID: - case BME280_CHIPID: - I2cWrite8(bmp_sensors[bmp_idx].bmp_address, BMP_REGISTER_RESET, BMP_CMND_RESET); - break; - default: - break; - } - } -} - -#endif - - - - - -bool Xsns09(uint8_t function) -{ - if (!I2cEnabled(XI2C_10)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - BmpDetect(); - } - else if (bmp_count) { - switch (function) { - case FUNC_EVERY_SECOND: - BmpRead(); - break; - case FUNC_JSON_APPEND: - BmpShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - BmpShow(0); - break; -#endif -#ifdef USE_DEEPSLEEP - case FUNC_SAVE_BEFORE_RESTART: - BMP_EnterSleep(); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_10_bh1750.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_10_bh1750.ino" -#ifdef USE_I2C -#ifdef USE_BH1750 - - - - - - -#define XSNS_10 10 -#define XI2C_11 11 - -#define BH1750_ADDR1 0x23 -#define BH1750_ADDR2 0x5C - -#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 - -uint8_t bh1750_address; -uint8_t bh1750_addresses[] = { BH1750_ADDR1, BH1750_ADDR2 }; -uint8_t bh1750_type = 0; -uint8_t bh1750_valid = 0; -uint16_t bh1750_illuminance = 0; -char bh1750_types[] = "BH1750"; - -bool Bh1750Read(void) -{ - if (bh1750_valid) { bh1750_valid--; } - - if (2 != Wire.requestFrom(bh1750_address, (uint8_t)2)) { return false; } - uint8_t msb = Wire.read(); - uint8_t lsb = Wire.read(); - bh1750_illuminance = ((msb << 8) | lsb) / 1.2; - bh1750_valid = SENSOR_MAX_MISS; - return true; -} - - - -void Bh1750Detect(void) -{ - for (uint32_t i = 0; i < sizeof(bh1750_addresses); i++) { - bh1750_address = bh1750_addresses[i]; - if (I2cActive(bh1750_address)) { continue; } - Wire.beginTransmission(bh1750_address); - Wire.write(BH1750_CONTINUOUS_HIGH_RES_MODE); - if (!Wire.endTransmission()) { - I2cSetActiveFound(bh1750_address, bh1750_types); - bh1750_type = 1; - break; - } - } -} - -void Bh1750EverySecond(void) -{ - - if (!Bh1750Read()) { - AddLogMissed(bh1750_types, bh1750_valid); - } -} - -void Bh1750Show(bool json) -{ - if (bh1750_valid) { - if (json) { - ResponseAppend_P(JSON_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, bh1750_types, bh1750_illuminance); -#endif - } - } -} - - - - - -bool Xsns10(uint8_t function) -{ - if (!I2cEnabled(XI2C_11)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Bh1750Detect(); - } - else if (bh1750_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Bh1750EverySecond(); - break; - case FUNC_JSON_APPEND: - Bh1750Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Bh1750Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_11_veml6070.ino" -# 89 "S:/Development/Tasmota/tasmota/xsns_11_veml6070.ino" -#ifdef USE_I2C -#ifdef USE_VEML6070 - - - - - - -#define XSNS_11 11 -#define XI2C_12 12 - -#define VEML6070_ADDR_H 0x39 -#define VEML6070_ADDR_L 0x38 -#define VEML6070_INTEGRATION_TIME 3 -#define VEML6070_ENABLE 1 -#define VEML6070_DISABLE 0 -#define VEML6070_RSET_DEFAULT 270000 -#define VEML6070_UV_MAX_INDEX 15 -#define VEML6070_UV_MAX_DEFAULT 11 -#define VEML6070_POWER_COEFFCIENT 0.025 -#define VEML6070_TABLE_COEFFCIENT 32.86270591 - - - - - -const char kVemlTypes[] PROGMEM = "VEML6070"; -double uv_risk_map[VEML6070_UV_MAX_INDEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -double uvrisk = 0; -double uvpower = 0; -uint16_t uvlevel = 0; -uint8_t veml6070_addr_low = VEML6070_ADDR_L; -uint8_t veml6070_addr_high = VEML6070_ADDR_H; -uint8_t itime = VEML6070_INTEGRATION_TIME; -uint8_t veml6070_type = 0; -char veml6070_name[9]; -char str_uvrisk_text[10]; - - - -void Veml6070Detect(void) -{ - if (I2cActive(VEML6070_ADDR_L)) { return; } - - - Wire.beginTransmission(VEML6070_ADDR_L); - Wire.write((itime << 2) | 0x02); - uint8_t status = Wire.endTransmission(); - - if (!status) { - veml6070_type = 1; - Veml6070UvTableInit(); - uint8_t veml_model = 0; - GetTextIndexed(veml6070_name, sizeof(veml6070_name), veml_model, kVemlTypes); - I2cSetActiveFound(VEML6070_ADDR_L, veml6070_name); - } -} - - - -void Veml6070UvTableInit(void) -{ - - for (uint32_t i = 0; i < VEML6070_UV_MAX_INDEX; i++) { -#ifdef USE_VEML6070_RSET - if ( (USE_VEML6070_RSET >= 220000) && (USE_VEML6070_RSET <= 1000000) ) { - uv_risk_map[i] = ( (USE_VEML6070_RSET / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - } else { - uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor error %d"), USE_VEML6070_RSET); - } -#else - uv_risk_map[i] = ( (VEML6070_RSET_DEFAULT / VEML6070_TABLE_COEFFCIENT) / VEML6070_UV_MAX_DEFAULT ) * (i+1); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 resistor default used %d"), VEML6070_RSET_DEFAULT); -#endif - } -} - - - -void Veml6070EverySecond(void) -{ - - Veml6070ModeCmd(1); - uvlevel = Veml6070ReadUv(); - uvrisk = Veml6070UvRiskLevel(uvlevel); - uvpower = Veml6070UvPower(uvrisk); - Veml6070ModeCmd(0); -} - - - -void Veml6070ModeCmd(bool mode_cmd) -{ - - - Wire.beginTransmission(VEML6070_ADDR_L); - Wire.write((mode_cmd << 0) | 0x02 | (itime << 2)); - uint8_t status = Wire.endTransmission(); - - if (!status) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 mode_cmd")); - } -} - - - -uint16_t Veml6070ReadUv(void) -{ - uint16_t uv_raw = 0; - - if (Wire.requestFrom(VEML6070_ADDR_H, 1) != 1) { - return -1; - } - uv_raw = Wire.read(); - uv_raw <<= 8; - - if (Wire.requestFrom(VEML6070_ADDR_L, 1) != 1) { - return -1; - } - uv_raw |= Wire.read(); - - return uv_raw; -} - - - -double Veml6070UvRiskLevel(uint16_t uv_level) -{ - double risk = 0; - if (uv_level < uv_risk_map[VEML6070_UV_MAX_INDEX-1]) { - risk = (double)uv_level / uv_risk_map[0]; - - if ( (risk >= 0) && (risk <= 2.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_1); } - else if ( (risk >= 3.0) && (risk <= 5.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_2); } - else if ( (risk >= 6.0) && (risk <= 7.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_3); } - else if ( (risk >= 8.0) && (risk <= 10.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_4); } - else if ( (risk >= 11.0) && (risk <= 12.9) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_5); } - else if ( (risk >= 13.0) && (risk <= 25.0) ) { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_6); } - else { snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); } - return risk; - } else { - - snprintf_P(str_uvrisk_text, sizeof(str_uvrisk_text), D_UV_INDEX_7); - return ( risk = 99 ); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "VEML6070 out of range %d"), risk); - } -} - - - -double Veml6070UvPower(double uvrisk) -{ - - double power = 0; - return ( power = VEML6070_POWER_COEFFCIENT * uvrisk ); -} - - - - -#ifdef USE_WEBSERVER - -#ifdef USE_VEML6070_SHOW_RAW - const char HTTP_SNS_UV_LEVEL[] PROGMEM = "{s}VEML6070 " D_UV_LEVEL "{m}%s " D_UNIT_INCREMENTS "{e}"; -#endif - - const char HTTP_SNS_UV_INDEX[] PROGMEM = "{s}VEML6070 " D_UV_INDEX "{m}%s %s{e}"; - const char HTTP_SNS_UV_POWER[] PROGMEM = "{s}VEML6070 " D_UV_POWER "{m}%s " D_UNIT_WATT_METER_QUADRAT "{e}"; -#endif - - - -void Veml6070Show(bool json) -{ - - char str_uvlevel[33]; - dtostrfd((double)uvlevel, 0, str_uvlevel); - char str_uvrisk[33]; - dtostrfd(uvrisk, 2, str_uvrisk); - char str_uvpower[33]; - dtostrfd(uvpower, 3, str_uvpower); - if (json) { -#ifdef USE_VEML6070_SHOW_RAW - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); -#else - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); -#endif -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } -#endif -#ifdef USE_WEBSERVER - } else { -#ifdef USE_VEML6070_SHOW_RAW - WSContentSend_PD(HTTP_SNS_UV_LEVEL, str_uvlevel); -#endif - WSContentSend_PD(HTTP_SNS_UV_INDEX, str_uvrisk, str_uvrisk_text); - WSContentSend_PD(HTTP_SNS_UV_POWER, str_uvpower); -#endif - } -} - - - - - -bool Xsns11(uint8_t function) -{ - if (!I2cEnabled(XI2C_12)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Veml6070Detect(); - } - else if (veml6070_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Veml6070EverySecond(); - break; - case FUNC_JSON_APPEND: - Veml6070Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Veml6070Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_12_ads1115.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_12_ads1115.ino" -#ifdef USE_I2C -#ifdef USE_ADS1115 -# 43 "S:/Development/Tasmota/tasmota/xsns_12_ads1115.ino" -#define XSNS_12 12 -#define XI2C_13 13 - -#define ADS1115_ADDRESS_ADDR_GND 0x48 -#define ADS1115_ADDRESS_ADDR_VDD 0x49 -#define ADS1115_ADDRESS_ADDR_SDA 0x4A -#define ADS1115_ADDRESS_ADDR_SCL 0x4B - -#define ADS1115_CONVERSIONDELAY (8) - - - - -#define ADS1115_REG_POINTER_MASK (0x03) -#define ADS1115_REG_POINTER_CONVERT (0x00) -#define ADS1115_REG_POINTER_CONFIG (0x01) -#define ADS1115_REG_POINTER_LOWTHRESH (0x02) -#define ADS1115_REG_POINTER_HITHRESH (0x03) - - - - -#define ADS1115_REG_CONFIG_OS_MASK (0x8000) -#define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) -#define ADS1115_REG_CONFIG_OS_BUSY (0x0000) -#define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) - -#define ADS1115_REG_CONFIG_MUX_MASK (0x7000) -#define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) -#define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) -#define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) -#define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) -#define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) - -#define ADS1115_REG_CONFIG_PGA_MASK (0x0E00) -#define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) -#define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) -#define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) -#define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) -#define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) -#define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) - -#define ADS1115_REG_CONFIG_MODE_MASK (0x0100) -#define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) -#define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) - -#define ADS1115_REG_CONFIG_DR_MASK (0x00E0) -#define ADS1115_REG_CONFIG_DR_128SPS (0x0000) -#define ADS1115_REG_CONFIG_DR_250SPS (0x0020) -#define ADS1115_REG_CONFIG_DR_490SPS (0x0040) -#define ADS1115_REG_CONFIG_DR_920SPS (0x0060) -#define ADS1115_REG_CONFIG_DR_1600SPS (0x0080) -#define ADS1115_REG_CONFIG_DR_2400SPS (0x00A0) -#define ADS1115_REG_CONFIG_DR_3300SPS (0x00C0) -#define ADS1115_REG_CONFIG_DR_6000SPS (0x00E0) - -#define ADS1115_REG_CONFIG_CMODE_MASK (0x0010) -#define ADS1115_REG_CONFIG_CMODE_TRAD (0x0000) -#define ADS1115_REG_CONFIG_CMODE_WINDOW (0x0010) - -#define ADS1115_REG_CONFIG_CPOL_MASK (0x0008) -#define ADS1115_REG_CONFIG_CPOL_ACTVLOW (0x0000) -#define ADS1115_REG_CONFIG_CPOL_ACTVHI (0x0008) - -#define ADS1115_REG_CONFIG_CLAT_MASK (0x0004) -#define ADS1115_REG_CONFIG_CLAT_NONLAT (0x0000) -#define ADS1115_REG_CONFIG_CLAT_LATCH (0x0004) - -#define ADS1115_REG_CONFIG_CQUE_MASK (0x0003) -#define ADS1115_REG_CONFIG_CQUE_1CONV (0x0000) -#define ADS1115_REG_CONFIG_CQUE_2CONV (0x0001) -#define ADS1115_REG_CONFIG_CQUE_4CONV (0x0002) -#define ADS1115_REG_CONFIG_CQUE_NONE (0x0003) - -struct ADS1115 { - uint8_t count = 0; - uint8_t address; - uint8_t addresses[4] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL }; - uint8_t found[4] = {false,false,false,false}; -} Ads1115; - - - -void Ads1115StartComparator(uint8_t channel, uint16_t mode) -{ - - uint16_t config = mode | - ADS1115_REG_CONFIG_CQUE_NONE | - ADS1115_REG_CONFIG_CLAT_NONLAT | - ADS1115_REG_CONFIG_PGA_6_144V | - ADS1115_REG_CONFIG_CPOL_ACTVLOW | - ADS1115_REG_CONFIG_CMODE_TRAD | - ADS1115_REG_CONFIG_DR_6000SPS; - - - config |= (ADS1115_REG_CONFIG_MUX_SINGLE_0 + (0x1000 * channel)); - - - I2cWrite16(Ads1115.address, ADS1115_REG_POINTER_CONFIG, config); -} - -int16_t Ads1115GetConversion(uint8_t channel) -{ - Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE); - - delay(ADS1115_CONVERSIONDELAY); - - I2cRead16(Ads1115.address, ADS1115_REG_POINTER_CONVERT); - - Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN); - delay(ADS1115_CONVERSIONDELAY); - - uint16_t res = I2cRead16(Ads1115.address, ADS1115_REG_POINTER_CONVERT); - return (int16_t)res; -} - - - -void Ads1115Detect(void) -{ - for (uint32_t i = 0; i < sizeof(Ads1115.addresses); i++) { - if (!Ads1115.found[i]) { - Ads1115.address = Ads1115.addresses[i]; - if (I2cActive(Ads1115.address)) { continue; } - uint16_t buffer; - if (I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONVERT) && - I2cValidRead16(&buffer, Ads1115.address, ADS1115_REG_POINTER_CONFIG)) { - Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN); - I2cSetActiveFound(Ads1115.address, "ADS1115"); - Ads1115.found[i] = 1; - Ads1115.count++; - } - } - } -} - -void Ads1115Show(bool json) -{ - int16_t values[4]; - - for (uint32_t t = 0; t < sizeof(Ads1115.addresses); t++) { - - if (Ads1115.found[t]) { - - uint8_t old_address = Ads1115.address; - Ads1115.address = Ads1115.addresses[t]; - for (uint32_t i = 0; i < 4; i++) { - values[i] = Ads1115GetConversion(i); - - } - Ads1115.address = old_address; - - char label[15]; - if (1 == Ads1115.count) { - - snprintf_P(label, sizeof(label), PSTR("ADS1115")); - } else { - - snprintf_P(label, sizeof(label), PSTR("ADS1115%c%02x"), IndexSeparator(), Ads1115.addresses[t]); - } - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{"), label); - for (uint32_t i = 0; i < 4; i++) { - ResponseAppend_P(PSTR("%s\"A%d\":%d"), (0 == i) ? "" : ",", i, values[i]); - } - ResponseJsonEnd(); - } -#ifdef USE_WEBSERVER - else { - for (uint32_t i = 0; i < 4; i++) { - WSContentSend_PD(HTTP_SNS_ANALOG, label, i, values[i]); - } - } -#endif - } - } -} - - - - - -bool Xsns12(uint8_t function) -{ - if (!I2cEnabled(XI2C_13)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Ads1115Detect(); - } - else if (Ads1115.count) { - switch (function) { - case FUNC_JSON_APPEND: - Ads1115Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ads1115Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_13_ina219.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_13_ina219.ino" -#ifdef USE_I2C -#ifdef USE_INA219 -# 30 "S:/Development/Tasmota/tasmota/xsns_13_ina219.ino" -#define XSNS_13 13 -#define XI2C_14 14 - -#define INA219_ADDRESS1 (0x40) -#define INA219_ADDRESS2 (0x41) -#define INA219_ADDRESS3 (0x44) -#define INA219_ADDRESS4 (0x45) - -#define INA219_READ (0x01) -#define INA219_REG_CONFIG (0x00) - -#define INA219_CONFIG_RESET (0x8000) - -#define INA219_CONFIG_BVOLTAGERANGE_MASK (0x2000) -#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) -#define INA219_CONFIG_BVOLTAGERANGE_32V (0x2000) - -#define INA219_CONFIG_GAIN_MASK (0x1800) -#define INA219_CONFIG_GAIN_1_40MV (0x0000) -#define INA219_CONFIG_GAIN_2_80MV (0x0800) -#define INA219_CONFIG_GAIN_4_160MV (0x1000) -#define INA219_CONFIG_GAIN_8_320MV (0x1800) - -#define INA219_CONFIG_BADCRES_MASK (0x0780) -#define INA219_CONFIG_BADCRES_9BIT (0x0080) -#define INA219_CONFIG_BADCRES_10BIT (0x0100) -#define INA219_CONFIG_BADCRES_11BIT (0x0200) -#define INA219_CONFIG_BADCRES_12BIT (0x0400) - -#define INA219_CONFIG_SADCRES_MASK (0x0078) -#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) -#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) -#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) -#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) -#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) -#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) -#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) -#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) -#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) -#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) -#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) - -#define INA219_CONFIG_MODE_MASK (0x0007) -#define INA219_CONFIG_MODE_POWERDOWN (0x0000) -#define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001) -#define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002) -#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003) -#define INA219_CONFIG_MODE_ADCOFF (0x0004) -#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005) -#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006) -#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007) - -#define INA219_REG_SHUNTVOLTAGE (0x01) -#define INA219_REG_BUSVOLTAGE (0x02) -#define INA219_REG_POWER (0x03) -#define INA219_REG_CURRENT (0x04) -#define INA219_REG_CALIBRATION (0x05) - -uint8_t ina219_type[4] = {0,0,0,0}; -uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; - -uint32_t ina219_cal_value = 0; - -uint32_t ina219_current_divider_ma = 0; - -uint8_t ina219_valid[4] = {0,0,0,0}; -float ina219_voltage[4] = {0,0,0,0}; -float ina219_current[4] = {0,0,0,0}; -char ina219_types[] = "INA219"; -uint8_t ina219_count = 0; - -bool Ina219SetCalibration(uint8_t mode, uint16_t addr) -{ - uint16_t config = 0; - - switch (mode &3) { - case 0: - case 3: - ina219_cal_value = 4096; - ina219_current_divider_ma = 10; - config = INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - case 1: - ina219_cal_value = 10240; - ina219_current_divider_ma = 25; - config |= INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - case 2: - ina219_cal_value = 8192; - ina219_current_divider_ma = 20; - config |= INA219_CONFIG_BVOLTAGERANGE_16V | INA219_CONFIG_GAIN_1_40MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - } - - bool success = I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); - if (success) { - - I2cWrite16(addr, INA219_REG_CONFIG, config); - } - return success; -} - -float Ina219GetShuntVoltage_mV(uint16_t addr) -{ - - int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); - - return value * 0.01; -} - -float Ina219GetBusVoltage_V(uint16_t addr) -{ - - - int16_t value = (int16_t)(((uint16_t)I2cReadS16(addr, INA219_REG_BUSVOLTAGE) >> 3) * 4); - - return value * 0.001; -} - -float Ina219GetCurrent_mA(uint16_t addr) -{ - - - - I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); - - - float value = I2cReadS16(addr, INA219_REG_CURRENT); - value /= ina219_current_divider_ma; - - return value; -} - -bool Ina219Read(void) -{ - for (int i=0; i= 0) && (XdrvMailbox.payload <= 2)) { - Settings.ina219_mode = XdrvMailbox.payload; - restart_flag = 2; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); - - return true; -} - - - -void Ina219Detect(void) -{ - for (uint32_t i = 0; i < sizeof(ina219_type); i++) { - uint16_t addr = ina219_addresses[i]; - if (I2cActive(addr)) { continue; } - if (Ina219SetCalibration(Settings.ina219_mode, addr)) { - I2cSetActiveFound(addr, ina219_types); - ina219_type[i] = 1; - ina219_count++; - } - } -} - -void Ina219EverySecond(void) -{ - - Ina219Read(); -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_INA219_DATA[] PROGMEM = - "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; -#endif - -void Ina219Show(bool json) -{ - int num_found=0; - for (int i=0; i1) - snprintf_P(name, sizeof(name), PSTR("%s%c%d"), ina219_types, IndexSeparator(), sensor_num); - else - snprintf_P(name, sizeof(name), PSTR("%s"), ina219_types); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - name, ina219_addresses[i], voltage, current, power); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_INA219_DATA, name, voltage, name, current, name, power); -#endif - } - } -} - - - - - -bool Xsns13(uint8_t function) -{ - if (!I2cEnabled(XI2C_14)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Ina219Detect(); - } - else if (ina219_count) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_13 == XdrvMailbox.index) { - result = Ina219CommandSensor(); - } - break; - case FUNC_EVERY_SECOND: - Ina219EverySecond(); - break; - case FUNC_JSON_APPEND: - Ina219Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ina219Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_14_sht3x.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_14_sht3x.ino" -#ifdef USE_I2C -#ifdef USE_SHT3X - - - - - - -#define XSNS_14 14 -#define XI2C_15 15 - -#define SHT3X_ADDR_GND 0x44 -#define SHT3X_ADDR_VDD 0x45 -#define SHTC3_ADDR 0x70 - -#define SHT3X_MAX_SENSORS 3 - -const char kShtTypes[] PROGMEM = "SHT3X|SHT3X|SHTC3"; -uint8_t sht3x_addresses[] = { SHT3X_ADDR_GND, SHT3X_ADDR_VDD, SHTC3_ADDR }; - -uint8_t sht3x_count = 0; -struct SHT3XSTRUCT { - uint8_t address; - char types[6]; -} sht3x_sensors[SHT3X_MAX_SENSORS]; - -bool Sht3xRead(float &t, float &h, uint8_t sht3x_address) -{ - unsigned int data[6]; - - t = NAN; - h = NAN; - - Wire.beginTransmission(sht3x_address); - if (SHTC3_ADDR == sht3x_address) { - Wire.write(0x35); - Wire.write(0x17); - Wire.endTransmission(); - Wire.beginTransmission(sht3x_address); - Wire.write(0x78); - Wire.write(0x66); - } else { - Wire.write(0x2C); - Wire.write(0x06); - } - if (Wire.endTransmission() != 0) { - return false; - } - delay(30); - Wire.requestFrom(sht3x_address, (uint8_t)6); - for (uint32_t i = 0; i < 6; i++) { - data[i] = Wire.read(); - }; - t = ConvertTemp((float)((((data[0] << 8) | data[1]) * 175) / 65535.0) - 45); - h = ConvertHumidity((float)((((data[3] << 8) | data[4]) * 100) / 65535.0)); - return (!isnan(t) && !isnan(h) && (h != 0)); -} - - - -void Sht3xDetect(void) -{ - for (uint32_t i = 0; i < SHT3X_MAX_SENSORS; i++) { - if (I2cActive(sht3x_addresses[i])) { continue; } - float t; - float h; - if (Sht3xRead(t, h, sht3x_addresses[i])) { - sht3x_sensors[sht3x_count].address = sht3x_addresses[i]; - GetTextIndexed(sht3x_sensors[sht3x_count].types, sizeof(sht3x_sensors[sht3x_count].types), i, kShtTypes); - I2cSetActiveFound(sht3x_sensors[sht3x_count].address, sht3x_sensors[sht3x_count].types); - sht3x_count++; - } - } -} - -void Sht3xShow(bool json) -{ - for (uint32_t i = 0; i < sht3x_count; i++) { - float t; - float h; - if (Sht3xRead(t, h, sht3x_sensors[i].address)) { - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(h, Settings.flag2.humidity_resolution, humidity); - char types[11]; - snprintf_P(types, sizeof(types), PSTR("%s%c0x%02X"), sht3x_sensors[i].types, IndexSeparator(), sht3x_sensors[i].address); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, types, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && (0 == i)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif - -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, t); - KnxSensor(KNX_HUMIDITY, h); - } -#endif - -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, types, humidity); -#endif - } - } - } -} - - - - - -bool Xsns14(uint8_t function) -{ - if (!I2cEnabled(XI2C_15)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Sht3xDetect(); - } - else if (sht3x_count) { - switch (function) { - case FUNC_JSON_APPEND: - Sht3xShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sht3xShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" -#ifdef USE_MHZ19 -# 33 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" -#define XSNS_15 15 - -enum MhzFilterOptions {MHZ19_FILTER_OFF, MHZ19_FILTER_OFF_ALLSAMPLES, MHZ19_FILTER_FAST, MHZ19_FILTER_MEDIUM, MHZ19_FILTER_SLOW}; - -#define MHZ19_FILTER_OPTION MHZ19_FILTER_FAST -# 58 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" -#include - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#define MHZ19_READ_TIMEOUT 400 -#define MHZ19_RETRY_COUNT 8 - -TasmotaSerial *MhzSerial; - -const char kMhzModels[] PROGMEM = "|B"; - -const char ABC_ENABLED[] = "ABC is Enabled"; -const char ABC_DISABLED[] = "ABC is Disabled"; - -enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; -const uint8_t kMhzCommands[][4] PROGMEM = { - - {0x86,0x00,0x00,0x00}, - {0x79,0xA0,0x00,0x00}, - {0x79,0x00,0x00,0x00}, - {0x87,0x00,0x00,0x00}, - {0x8D,0x00,0x00,0x00}, - {0x99,0x00,0x03,0xE8}, - {0x99,0x00,0x07,0xD0}, - {0x99,0x00,0x0B,0xB8}, - {0x99,0x00,0x13,0x88}}; - -uint8_t mhz_type = 1; -uint16_t mhz_last_ppm = 0; -uint8_t mhz_filter = MHZ19_FILTER_OPTION; -bool mhz_abc_must_apply = false; - -float mhz_temperature = 0; -uint8_t mhz_retry = MHZ19_RETRY_COUNT; -uint8_t mhz_received = 0; -uint8_t mhz_state = 0; - - - -uint8_t MhzCalculateChecksum(uint8_t *array) -{ - uint8_t checksum = 0; - for (uint32_t i = 1; i < 8; i++) { - checksum += array[i]; - } - checksum = 255 - checksum; - return (checksum +1); -} - -size_t MhzSendCmd(uint8_t command_id) -{ - uint8_t mhz_send[9] = { 0 }; - - mhz_send[0] = 0xFF; - mhz_send[1] = 0x01; - memcpy_P(&mhz_send[2], kMhzCommands[command_id], sizeof(uint16_t)); - - - - - memcpy_P(&mhz_send[6], kMhzCommands[command_id] + sizeof(uint16_t), sizeof(uint16_t)); - mhz_send[8] = MhzCalculateChecksum(mhz_send); - - - - return MhzSerial->write(mhz_send, sizeof(mhz_send)); -} - - - -bool MhzCheckAndApplyFilter(uint16_t ppm, uint8_t s) -{ - if (1 == s) { - return false; - } - if (mhz_last_ppm < 400 || mhz_last_ppm > 5000) { - - - mhz_last_ppm = ppm; - return true; - } - int32_t difference = ppm - mhz_last_ppm; - if (s > 0 && s < 64 && mhz_filter != MHZ19_FILTER_OFF) { -# 154 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" - difference *= s; - difference /= 64; - } - if (MHZ19_FILTER_OFF == mhz_filter) { - if (s != 0 && s != 64) { - return false; - } - } else { - difference >>= (mhz_filter -1); - } - mhz_last_ppm = static_cast(mhz_last_ppm + difference); - return true; -} - -void MhzEverySecond(void) -{ - mhz_state++; - if (8 == mhz_state) { - mhz_state = 0; - - if (mhz_retry) { - mhz_retry--; - if (!mhz_retry) { - mhz_last_ppm = 0; - mhz_temperature = 0; - } - } - - MhzSerial->flush(); - MhzSendCmd(MHZ_CMND_READPPM); - mhz_received = 0; - } - - if ((mhz_state > 2) && !mhz_received) { - uint8_t mhz_response[9]; - - unsigned long start = millis(); - uint8_t counter = 0; - while (((millis() - start) < MHZ19_READ_TIMEOUT) && (counter < 9)) { - if (MhzSerial->available() > 0) { - mhz_response[counter++] = MhzSerial->read(); - } else { - delay(5); - } - } - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, mhz_response, counter); - - if (counter < 9) { - - return; - } - - uint8_t crc = MhzCalculateChecksum(mhz_response); - if (mhz_response[8] != crc) { - - return; - } - if (0xFF != mhz_response[0] || 0x86 != mhz_response[1]) { - - return; - } - - mhz_received = 1; - - uint16_t u = (mhz_response[6] << 8) | mhz_response[7]; - if (15000 == u) { - if (Settings.SensorBits1.mhz19b_abc_disable) { - - - mhz_abc_must_apply = true; - } - } else { - uint16_t ppm = (mhz_response[2] << 8) | mhz_response[3]; - mhz_temperature = ConvertTemp((float)mhz_response[4] - 40); - uint8_t s = mhz_response[5]; - mhz_type = (s) ? 1 : 2; - if (MhzCheckAndApplyFilter(ppm, s)) { - mhz_retry = MHZ19_RETRY_COUNT; - LightSetSignal(CO2_LOW, CO2_HIGH, mhz_last_ppm); - - if (0 == s || 64 == s) { - if (mhz_abc_must_apply) { - mhz_abc_must_apply = false; - if (!Settings.SensorBits1.mhz19b_abc_disable) { - MhzSendCmd(MHZ_CMND_ABCENABLE); - } else { - MhzSendCmd(MHZ_CMND_ABCDISABLE); - } - } - } - - } - } - - } -} -# 266 "S:/Development/Tasmota/tasmota/xsns_15_mhz19.ino" -#define D_JSON_RANGE_1000 "1000 ppm range" -#define D_JSON_RANGE_2000 "2000 ppm range" -#define D_JSON_RANGE_3000 "3000 ppm range" -#define D_JSON_RANGE_5000 "5000 ppm range" - -bool MhzCommandSensor(void) -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - Settings.SensorBits1.mhz19b_abc_disable = true; - MhzSendCmd(MHZ_CMND_ABCDISABLE); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); - break; - case 1: - Settings.SensorBits1.mhz19b_abc_disable = false; - MhzSendCmd(MHZ_CMND_ABCENABLE); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); - break; - case 2: - MhzSendCmd(MHZ_CMND_ZEROPOINT); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); - break; - case 9: - MhzSendCmd(MHZ_CMND_RESET); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); - break; - case 1000: - MhzSendCmd(MHZ_CMND_RANGE_1000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); - break; - case 2000: - MhzSendCmd(MHZ_CMND_RANGE_2000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); - break; - case 3000: - MhzSendCmd(MHZ_CMND_RANGE_3000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); - break; - case 5000: - MhzSendCmd(MHZ_CMND_RANGE_5000); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); - break; - default: - if (!Settings.SensorBits1.mhz19b_abc_disable) { - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); - } else { - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); - } - } - - return serviced; -} - - - -void MhzInit(void) -{ - mhz_type = 0; - if ((pin[GPIO_MHZ_RXD] < 99) && (pin[GPIO_MHZ_TXD] < 99)) { - MhzSerial = new TasmotaSerial(pin[GPIO_MHZ_RXD], pin[GPIO_MHZ_TXD], 1); - if (MhzSerial->begin(9600)) { - if (MhzSerial->hardwareSerial()) { ClaimSerial(); } - mhz_type = 1; - } - - } -} - -void MhzShow(bool json) -{ - char types[7] = "MHZ19B"; - char temperature[33]; - dtostrfd(mhz_temperature, Settings.flag2.temperature_resolution, temperature); - char model[3]; - GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, types, mhz_last_ppm); - WSContentSend_PD(HTTP_SNS_TEMP, types, temperature, TempUnit()); -#endif - } -} - - - - - -bool Xsns15(uint8_t function) -{ - bool result = false; - - if (mhz_type) { - switch (function) { - case FUNC_INIT: - MhzInit(); - break; - case FUNC_EVERY_SECOND: - MhzEverySecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_15 == XdrvMailbox.index) { - result = MhzCommandSensor(); - } - break; - case FUNC_JSON_APPEND: - MhzShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MhzShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_16_tsl2561.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_16_tsl2561.ino" -#ifdef USE_I2C -#ifdef USE_TSL2561 -# 30 "S:/Development/Tasmota/tasmota/xsns_16_tsl2561.ino" -#define XSNS_16 16 -#define XI2C_16 16 - -#include - -Tsl2561 Tsl(Wire); - -uint8_t tsl2561_type = 0; -uint8_t tsl2561_valid = 0; -uint32_t tsl2561_milliLux = 0; -char tsl2561_types[] = "TSL2561"; - -bool Tsl2561Read(void) -{ - if (tsl2561_valid) { tsl2561_valid--; } - - uint8_t id; - bool gain; - Tsl2561::exposure_t exposure; - uint16_t scaledFull, scaledIr; - uint32_t full, ir; - - if (Tsl.on()) { - if (Tsl.id(id) - && Tsl2561Util::autoGain(Tsl, gain, exposure, scaledFull, scaledIr) - && Tsl2561Util::normalizedLuminosity(gain, exposure, full = scaledFull, ir = scaledIr) - && Tsl2561Util::milliLux(full, ir, tsl2561_milliLux, Tsl2561::packageCS(id))) { - } else{ - tsl2561_milliLux = 0; - } - } - tsl2561_valid = SENSOR_MAX_MISS; - return true; -} - -void Tsl2561Detect(void) -{ - if (I2cSetDevice(0x29) || I2cSetDevice(0x39) || I2cSetDevice(0x49)) { - uint8_t id; - Tsl.begin(); - if (!Tsl.id(id)) return; - if (Tsl.on()) { - tsl2561_type = 1; - I2cSetActiveFound(Tsl.address(), tsl2561_types); - } - } -} - -void Tsl2561EverySecond(void) -{ - if (!(uptime %2)) { - - if (!Tsl2561Read()) { - AddLogMissed(tsl2561_types, tsl2561_valid); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_TSL2561[] PROGMEM = - "{s}TSL2561 " D_ILLUMINANCE "{m}%u.%03u " D_UNIT_LUX "{e}"; -#endif - -void Tsl2561Show(bool json) -{ - if (tsl2561_valid) { - if (json) { - ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), - tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TSL2561, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); -#endif - } - } -} - - - - - -bool Xsns16(uint8_t function) -{ - if (!I2cEnabled(XI2C_16)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Tsl2561Detect(); - } - else if (tsl2561_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Tsl2561EverySecond(); - break; - case FUNC_JSON_APPEND: - Tsl2561Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tsl2561Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_17_senseair.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_17_senseair.ino" -#ifdef USE_SENSEAIR -# 29 "S:/Development/Tasmota/tasmota/xsns_17_senseair.ino" -#define XSNS_17 17 - -#define SENSEAIR_MODBUS_SPEED 9600 -#define SENSEAIR_DEVICE_ADDRESS 0xFE -#define SENSEAIR_READ_REGISTER 0x04 - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#include -TasmotaModbus *SenseairModbus; - -const char kSenseairTypes[] PROGMEM = "Kx0|S8"; - -uint8_t senseair_type = 1; -char senseair_types[7]; - -uint16_t senseair_co2 = 0; -float senseair_temperature = 0; -float senseair_humidity = 0; - - - -const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; - -uint8_t senseair_read_state = 0; -uint8_t senseair_send_retry = 0; - -void Senseair250ms(void) -{ - - - - - uint16_t value = 0; - bool data_ready = SenseairModbus->ReceiveReady(); - - if (data_ready) { - uint8_t error = SenseairModbus->Receive16BitRegister(&value); - if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); - } else { - switch(senseair_read_state) { - case 0: - senseair_type = 2; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir type id low %04X"), value); - break; - case 1: - if (value) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir error %04X"), value); - } - break; - case 2: - senseair_co2 = value; - LightSetSignal(CO2_LOW, CO2_HIGH, senseair_co2); - break; - case 3: - senseair_temperature = ConvertTemp((float)value / 100); - break; - case 4: - senseair_humidity = ConvertHumidity((float)value / 100); - break; - case 5: - { - bool relay_state = value >> 8 & 1; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir relay state %d"), relay_state); - break; - } - case 6: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SenseAir temp adjustment %d"), value); - break; - } - } - senseair_read_state++; - if (2 == senseair_type) { - if (3 == senseair_read_state) { - senseair_read_state = 1; - } - } else { - if (sizeof(start_addresses) == senseair_read_state) { - senseair_read_state = 1; - } - } - } - - if (0 == senseair_send_retry || data_ready) { - senseair_send_retry = 5; - SenseairModbus->Send(SENSEAIR_DEVICE_ADDRESS, SENSEAIR_READ_REGISTER, (uint16_t)start_addresses[senseair_read_state], 1); - } else { - senseair_send_retry--; - } - - -} - - - -void SenseairInit(void) -{ - senseair_type = 0; - if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { - SenseairModbus = new TasmotaModbus(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX]); - uint8_t result = SenseairModbus->Begin(SENSEAIR_MODBUS_SPEED); - if (result) { - if (2 == result) { ClaimSerial(); } - senseair_type = 1; - } - } -} - -void SenseairShow(bool json) -{ - char temperature[33]; - dtostrfd(senseair_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(senseair_humidity, Settings.flag2.temperature_resolution, humidity); - GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2); - if (senseair_type != 2) { - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); - } - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, senseair_types, senseair_co2); - if (senseair_type != 2) { - WSContentSend_PD(HTTP_SNS_TEMP, senseair_types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, senseair_types, humidity); - } -#endif - } -} - - - - - -bool Xsns17(uint8_t function) -{ - bool result = false; - - if (senseair_type) { - switch (function) { - case FUNC_INIT: - SenseairInit(); - break; - case FUNC_EVERY_250_MSECOND: - Senseair250ms(); - break; - case FUNC_JSON_APPEND: - SenseairShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SenseairShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_18_pms5003.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_18_pms5003.ino" -#ifdef USE_PMS5003 -# 31 "S:/Development/Tasmota/tasmota/xsns_18_pms5003.ino" -#define XSNS_18 18 - -#include - -TasmotaSerial *PmsSerial; - -uint8_t pms_type = 1; -uint8_t pms_valid = 0; - -struct pmsX003data { - uint16_t framelen; - uint16_t pm10_standard, pm25_standard, pm100_standard; - uint16_t pm10_env, pm25_env, pm100_env; -#ifdef PMS_MODEL_PMS3003 - uint16_t reserved1, reserved2, reserved3; -#else - uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um; - uint16_t unused; -#endif - uint16_t checksum; -} pms_data; - - - -bool PmsReadData(void) -{ - if (! PmsSerial->available()) { - return false; - } - while ((PmsSerial->peek() != 0x42) && PmsSerial->available()) { - PmsSerial->read(); - } -#ifdef PMS_MODEL_PMS3003 - if (PmsSerial->available() < 22) { -#else - if (PmsSerial->available() < 32) { -#endif - return false; - } - -#ifdef PMS_MODEL_PMS3003 - uint8_t buffer[22]; - PmsSerial->readBytes(buffer, 22); -#else - uint8_t buffer[32]; - PmsSerial->readBytes(buffer, 32); -#endif - uint16_t sum = 0; - PmsSerial->flush(); - -#ifdef PMS_MODEL_PMS3003 - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 22); -#else - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, 32); -#endif - - -#ifdef PMS_MODEL_PMS3003 - for (uint32_t i = 0; i < 20; i++) { -#else - for (uint32_t i = 0; i < 30; i++) { -#endif - sum += buffer[i]; - } - -#ifdef PMS_MODEL_PMS3003 - uint16_t buffer_u16[10]; - for (uint32_t i = 0; i < 10; i++) { -#else - uint16_t buffer_u16[15]; - for (uint32_t i = 0; i < 15; i++) { -#endif - buffer_u16[i] = buffer[2 + i*2 + 1]; - buffer_u16[i] += (buffer[2 + i*2] << 8); - } -#ifdef PMS_MODEL_PMS3003 - if (sum != buffer_u16[9]) { -#else - if (sum != buffer_u16[14]) { -#endif - AddLog_P(LOG_LEVEL_DEBUG, PSTR("PMS: " D_CHECKSUM_FAILURE)); - return false; - } - -#ifdef PMS_MODEL_PMS3003 - memcpy((void *)&pms_data, (void *)buffer_u16, 20); -#else - memcpy((void *)&pms_data, (void *)buffer_u16, 30); -#endif - pms_valid = 10; - - return true; -} - - - -void PmsSecond(void) -{ - if (PmsReadData()) { - pms_valid = 10; - } else { - if (pms_valid) { - pms_valid--; - } - } -} - - - -void PmsInit(void) -{ - pms_type = 0; - if (pin[GPIO_PMS5003] < 99) { - PmsSerial = new TasmotaSerial(pin[GPIO_PMS5003], -1, 1); - if (PmsSerial->begin(9600)) { - if (PmsSerial->hardwareSerial()) { ClaimSerial(); } - pms_type = 1; - } - } -} - -#ifdef USE_WEBSERVER -#ifdef PMS_MODEL_PMS3003 -const char HTTP_PMS3003_SNS[] PROGMEM = - - - - "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS3003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; -#else -const char HTTP_PMS5003_SNS[] PROGMEM = - - - - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 0.3 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 0.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 1 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 2.5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 5 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}" - "{s}PMS5003 " D_PARTICALS_BEYOND " 10 " D_UNIT_MICROMETER "{m}%d " D_UNIT_PARTS_PER_DECILITER "{e}"; -#endif -#endif - -void PmsShow(bool json) -{ - if (pms_valid) { - if (json) { -#ifdef PMS_MODEL_PMS3003 - ResponseAppend_P(PSTR(",\"PMS3003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d}"), - pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); -#else - ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), - pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, - pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); -#endif -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_COUNT, pms_data.pm10_env); - DomoticzSensor(DZ_VOLTAGE, pms_data.pm25_env); - DomoticzSensor(DZ_CURRENT, pms_data.pm100_env); - } -#endif -#ifdef USE_WEBSERVER - } else { - -#ifdef PMS_MODEL_PMS3003 - WSContentSend_PD(HTTP_PMS3003_SNS, - - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env); -#else - WSContentSend_PD(HTTP_PMS5003_SNS, - - pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, - pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); -#endif -#endif - } - } -} - - - - - -bool Xsns18(uint8_t function) -{ - bool result = false; - - if (pms_type) { - switch (function) { - case FUNC_INIT: - PmsInit(); - break; - case FUNC_EVERY_SECOND: - PmsSecond(); - break; - case FUNC_JSON_APPEND: - PmsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - PmsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_19_mgs.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_19_mgs.ino" -#ifdef USE_I2C -#ifdef USE_MGS - - - - - - - -#define XSNS_19 19 -#define XI2C_17 17 - -#ifndef MGS_SENSOR_ADDR -#define MGS_SENSOR_ADDR 0x04 -#endif - -#include "MutichannelGasSensor.h" - -bool mgs_detected = false; - -void MGSInit(void) { - gas.begin(MGS_SENSOR_ADDR); -} - -void MGSPrepare(void) -{ - if (I2cActive(MGS_SENSOR_ADDR)) { return; } - - gas.begin(MGS_SENSOR_ADDR); - if (!gas.isError()) { - I2cSetActiveFound(MGS_SENSOR_ADDR, "MultiGas"); - mgs_detected = true; - } -} - -char* measure_gas(int gas_type, char* buffer) -{ - float f = gas.calcGas(gas_type); - dtostrfd(f, 2, buffer); - return buffer; -} - -#ifdef USE_WEBSERVER -const char HTTP_MGS_GAS[] PROGMEM = "{s}MGS %s{m}%s " D_UNIT_PARTS_PER_MILLION "{e}"; -#endif - -void MGSShow(bool json) -{ - char buffer[33]; - if (json) { - ResponseAppend_P(PSTR(",\"MGS\":{\"NH3\":%s"), measure_gas(NH3, buffer)); - ResponseAppend_P(PSTR(",\"CO\":%s"), measure_gas(CO, buffer)); - ResponseAppend_P(PSTR(",\"NO2\":%s"), measure_gas(NO2, buffer)); - ResponseAppend_P(PSTR(",\"C3H8\":%s"), measure_gas(C3H8, buffer)); - ResponseAppend_P(PSTR(",\"C4H10\":%s"), measure_gas(C4H10, buffer)); - ResponseAppend_P(PSTR(",\"CH4\":%s"), measure_gas(GAS_CH4, buffer)); - ResponseAppend_P(PSTR(",\"H2\":%s"), measure_gas(H2, buffer)); - ResponseAppend_P(PSTR(",\"C2H5OH\":%s}"), measure_gas(C2H5OH, buffer)); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "CO", measure_gas(CO, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "NO2", measure_gas(NO2, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C3H8", measure_gas(C3H8, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C4H10", measure_gas(C4H10, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "CH4", measure_gas(GAS_CH4, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "H2", measure_gas(H2, buffer)); - WSContentSend_PD(HTTP_MGS_GAS, "C2H5OH", measure_gas(C2H5OH, buffer)); -#endif - } -} - - - - - -bool Xsns19(uint8_t function) -{ - if (!I2cEnabled(XI2C_17)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MGSPrepare(); - } - else if (mgs_detected) { - switch (function) { - case FUNC_JSON_APPEND: - MGSShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MGSShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_20_novasds.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_20_novasds.ino" -#ifdef USE_NOVA_SDS -# 30 "S:/Development/Tasmota/tasmota/xsns_20_novasds.ino" -#define XSNS_20 20 - -#include - -#ifndef STARTING_OFFSET -#define STARTING_OFFSET 30 -#endif -#if STARTING_OFFSET < 10 -#error "Please set STARTING_OFFSET >= 10" -#endif -#ifndef NOVA_SDS_RECDATA_TIMEOUT -#define NOVA_SDS_RECDATA_TIMEOUT 150 -#endif -#ifndef NOVA_SDS_DEVICE_ID -#define NOVA_SDS_DEVICE_ID 0xFFFF -#endif - -TasmotaSerial *NovaSdsSerial; - -uint8_t novasds_type = 1; -uint8_t novasds_valid = 0; -uint8_t cont_mode = 1; - -struct sds011data { - uint16_t pm100; - uint16_t pm25; -} novasds_data; -uint16_t pm100_sum; -uint16_t pm25_sum; - - -#define NOVA_SDS_REPORTING_MODE 2 -#define NOVA_SDS_QUERY_DATA 4 -#define NOVA_SDS_SET_DEVICE_ID 5 -#define NOVA_SDS_SLEEP_AND_WORK 6 -#define NOVA_SDS_WORKING_PERIOD 8 -#define NOVA_SDS_CHECK_FIRMWARE_VER 7 - #define NOVA_SDS_QUERY_MODE 0 - #define NOVA_SDS_SET_MODE 1 - #define NOVA_SDS_REPORT_ACTIVE 0 - #define NOVA_SDS_REPORT_QUERY 1 - #define NOVA_SDS_SLEEP 0 - #define NOVA_SDS_WORK 1 - - -bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensorid, uint8_t *buffer) -{ - uint8_t novasds_cmnd[19] = {0xAA, 0xB4, byte1, byte2, byte3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (uint8_t)(sensorid & 0xFF), (uint8_t)((sensorid>>8) & 0xFF), 0x00, 0xAB}; - - - for (uint32_t i = 2; i < 17; i++) { - novasds_cmnd[17] += novasds_cmnd[i]; - } - - - - - - NovaSdsSerial->write(novasds_cmnd, sizeof(novasds_cmnd)); - NovaSdsSerial->flush(); - - - unsigned long cmndtime = millis(); - while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( ! NovaSdsSerial->available() ) ); - if ( ! NovaSdsSerial->available() ) { - - return false; - } - uint8_t recbuf[10]; - memset(recbuf, 0, sizeof(recbuf)); - - while ( (TimePassedSince(cmndtime) < NOVA_SDS_RECDATA_TIMEOUT) && ( NovaSdsSerial->available() > 0) && (0xAA != (recbuf[0] = NovaSdsSerial->read())) ); - if ( 0xAA != recbuf[0] ) { - - return false; - } - - - NovaSdsSerial->readBytes(&recbuf[1], 9); - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); - - if ( nullptr != buffer ) { - - memcpy(buffer, recbuf, sizeof(recbuf)); - } - - - if ((0xAB != recbuf[9] ) || (recbuf[8] != ((recbuf[2] + recbuf[3] + recbuf[4] + recbuf[5] + recbuf[6] + recbuf[7]) & 0xFF))) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("SDS: " D_CHECKSUM_FAILURE)); - return false; - } - - return true; -} - -void NovaSdsSetWorkPeriod(void) -{ - - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, 0, NOVA_SDS_DEVICE_ID, nullptr); - - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); -} - -bool NovaSdsReadData(void) -{ - uint8_t d[10]; - if ( ! NovaSdsCommand(NOVA_SDS_QUERY_DATA, 0, 0, NOVA_SDS_DEVICE_ID, d) ) { - return false; - } - novasds_data.pm25 = (d[2] + 256 * d[3]); - novasds_data.pm100 = (d[4] + 256 * d[5]); - - return true; -} - - - -void NovaSdsSecond(void) -{ - if (!novasds_valid) - { - NovaSdsSetWorkPeriod(); - novasds_valid=1; - } - if((Settings.tele_period - Settings.novasds_startingoffset <= 0)) - { - if(!cont_mode) - { - cont_mode = 1; - NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); - } - } - else - cont_mode = 0; - - if(tele_period == Settings.tele_period - Settings.novasds_startingoffset && !cont_mode) - { - NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_WORK, NOVA_SDS_DEVICE_ID, nullptr); - } - if(tele_period >= Settings.tele_period-5 && tele_period <= Settings.tele_period-2) - { - if(!(NovaSdsReadData())) novasds_valid=0; - pm100_sum += novasds_data.pm100; - pm25_sum += novasds_data.pm25; - } - if(tele_period == Settings.tele_period-1) - { - novasds_data.pm100 = pm100_sum >> 2; - novasds_data.pm25 = pm25_sum >> 2; - if(!cont_mode) - NovaSdsCommand(NOVA_SDS_SLEEP_AND_WORK, NOVA_SDS_SET_MODE, NOVA_SDS_SLEEP, NOVA_SDS_DEVICE_ID, nullptr); - pm100_sum = pm25_sum = 0; - } -} - - - - - - - -bool NovaSdsCommandSensor(void) -{ - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { - if( XdrvMailbox.payload < 10 ) Settings.novasds_startingoffset = 10; - else Settings.novasds_startingoffset = XdrvMailbox.payload; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_startingoffset); - - return true; -} - -void NovaSdsInit(void) -{ - novasds_type = 0; - if (pin[GPIO_SDS0X1_RX] < 99 && pin[GPIO_SDS0X1_TX] < 99) { - NovaSdsSerial = new TasmotaSerial(pin[GPIO_SDS0X1_RX], pin[GPIO_SDS0X1_TX], 1); - if (NovaSdsSerial->begin(9600)) { - if (NovaSdsSerial->hardwareSerial()) { - ClaimSerial(); - } - novasds_type = 1; - NovaSdsSetWorkPeriod(); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SDS0X1_SNS[] PROGMEM = - "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}SDS0X1 " D_ENVIRONMENTAL_CONCENTRATION " 10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; -#endif - -void NovaSdsShow(bool json) -{ - if (novasds_valid) { - float pm10f = (float)(novasds_data.pm100) / 10.0f; - float pm2_5f = (float)(novasds_data.pm25) / 10.0f; - char pm10[33]; - dtostrfd(pm10f, 1, pm10); - char pm2_5[33]; - dtostrfd(pm2_5f, 1, pm2_5); - if (json) { - ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, pm2_5); - DomoticzSensor(DZ_CURRENT, pm10); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SDS0X1_SNS, pm2_5, pm10); -#endif - } - } -} - - - - - -bool Xsns20(uint8_t function) -{ - bool result = false; - - if (novasds_type) { - switch (function) { - case FUNC_INIT: - NovaSdsInit(); - break; - case FUNC_EVERY_SECOND: - NovaSdsSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_20 == XdrvMailbox.index) { - result = NovaSdsCommandSensor(); - } - break; - case FUNC_JSON_APPEND: - NovaSdsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - NovaSdsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_21_sgp30.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_21_sgp30.ino" -#ifdef USE_I2C -#ifdef USE_SGP30 -# 30 "S:/Development/Tasmota/tasmota/xsns_21_sgp30.ino" -#define XSNS_21 21 -#define XI2C_18 18 - -#define SGP30_ADDRESS 0x58 - -#include "Adafruit_SGP30.h" -Adafruit_SGP30 sgp; - -bool sgp30_type = false; -bool sgp30_ready = false; -float sgp30_abshum; - - - -void sgp30_Init(void) -{ - if (I2cActive(SGP30_ADDRESS)) { return; } - - if (sgp.begin()) { - sgp30_type = true; - - I2cSetActiveFound(SGP30_ADDRESS, "SGP30"); - } -} - - -#define POW_FUNC FastPrecisePow - -float sgp30_AbsoluteHumidity(float temperature, float humidity,char tempUnit) { - - - - - - float temp = NAN; - const float mw = 18.01534; - const float r = 8.31447215; - - if (isnan(temperature) || isnan(humidity) ) { - return NAN; - } - - if (tempUnit != 'C') { - temperature = (temperature - 32.0) * (5.0 / 9.0); - } - - temp = POW_FUNC(2.718281828, (17.67 * temperature) / (temperature + 243.5)); - - - return (6.112 * temp * humidity * mw) / ((273.15 + temperature) * r); -} - -#define SAVE_PERIOD 30 - -void Sgp30Update(void) -{ - sgp30_ready = false; - if (!sgp.IAQmeasure()) { - return; - } - if (global_update && (global_humidity > 0) && (global_temperature != 9999)) { - - sgp30_abshum=sgp30_AbsoluteHumidity(global_temperature,global_humidity,TempUnit()); - sgp.setHumidity(sgp30_abshum*1000); - } - sgp30_ready = true; - - - if (!(uptime%SAVE_PERIOD)) { - - uint16_t TVOC_base; - uint16_t eCO2_base; - - if (!sgp.getIAQBaseline(&eCO2_base, &TVOC_base)) return; - - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SGP30[] PROGMEM = - "{s}SGP30 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" - "{s}SGP30 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; -const char HTTP_SNS_AHUM[] PROGMEM = "{s}SGP30 Abs Humidity{m}%s g/m3{e}"; -#endif - -#define D_JSON_AHUM "aHumidity" - -void Sgp30Show(bool json) -{ - if (sgp30_ready) { - char abs_hum[33]; - - if (json) { - ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d"), sgp.eCO2, sgp.TVOC); - if (global_update && global_humidity>0 && global_temperature!=9999) { - - dtostrfd(sgp30_abshum,4,abs_hum); - ResponseAppend_P(PSTR(",\"" D_JSON_AHUM "\":%s"),abs_hum); - } - ResponseJsonEnd(); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SGP30, sgp.eCO2, sgp.TVOC); - if (global_update) { - WSContentSend_PD(HTTP_SNS_AHUM, abs_hum); - } -#endif - } - } -} - - - - - -bool Xsns21(uint8_t function) -{ - if (!I2cEnabled(XI2C_18)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - sgp30_Init(); - } - else if (sgp30_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Sgp30Update(); - break; - case FUNC_JSON_APPEND: - Sgp30Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sgp30Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_22_sr04.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_22_sr04.ino" -#ifdef USE_SR04 - -#include -#include -# 32 "S:/Development/Tasmota/tasmota/xsns_22_sr04.ino" -#define XSNS_22 22 - -uint8_t sr04_type = 1; -int sr04_echo_pin = 0; -int sr04_trig_pin = 0; -real64_t distance; - -NewPing* sonar = nullptr; -TasmotaSerial* sonar_serial = nullptr; - - - -uint8_t Sr04TModeDetect(void) -{ - sr04_type = 0; - if (pin[GPIO_SR04_ECHO]>=99) return sr04_type; - - sr04_echo_pin = pin[GPIO_SR04_ECHO]; - sr04_trig_pin = (pin[GPIO_SR04_TRIG] < 99) ? pin[GPIO_SR04_TRIG] : -1; - sonar_serial = new TasmotaSerial(sr04_echo_pin, sr04_trig_pin, 1); - - if (sonar_serial->begin(9600,1)) { - DEBUG_SENSOR_LOG(PSTR("SR04: Detect mode")); - - if (sr04_trig_pin!=-1) { - sr04_type = (Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance())!=NO_ECHO)?3:1; - } else { - sr04_type = 2; - } - } else { - sr04_type = 1; - } - - if (sr04_type < 2) { - delete sonar_serial; - sonar_serial = nullptr; - sonar = new NewPing(sr04_trig_pin, sr04_echo_pin, 300); - } else { - if (sonar_serial->hardwareSerial()) { - ClaimSerial(); - } - } - - AddLog_P2(LOG_LEVEL_INFO,PSTR("SR04: Mode %d"), sr04_type); - return sr04_type; -} - -uint16_t Sr04TMiddleValue(uint16_t first, uint16_t second, uint16_t third) -{ - uint16_t ret = first; - if (first > second) { - first = second; - second = ret; - } - - if (third < first) { - return first; - } else if (third > second) { - return second; - } else { - return third; - } -} - -uint16_t Sr04TMode3Distance() { - - sonar_serial->write(0x55); - sonar_serial->flush(); - - return Sr04TMode2Distance(); -} - -uint16_t Sr04TMode2Distance(void) -{ - sonar_serial->setTimeout(300); - const char startByte = 0xff; - - if (!sonar_serial->find(startByte)) { - - return NO_ECHO; - } - - delay(5); - - uint8_t crc = sonar_serial->read(); - - uint16_t distance = ((uint16_t)crc) << 8; - - - distance += sonar_serial->read(); - crc += distance & 0x00ff; - crc += 0x00FF; - - - if (crc != sonar_serial->read()) { - AddLog_P2(LOG_LEVEL_ERROR,PSTR("SR04: Reading CRC error.")); - return NO_ECHO; - } - - return distance; -} - -void Sr04TReading(void) { - - if (sonar_serial==nullptr && sonar==nullptr) { - Sr04TModeDetect(); - } - - switch (sr04_type) { - case 3: - distance = (real64_t)(Sr04TMiddleValue(Sr04TMode3Distance(),Sr04TMode3Distance(),Sr04TMode3Distance()))/ 10; - break; - case 2: - - while(sonar_serial->available()) sonar_serial->read(); - distance = (real64_t)(Sr04TMiddleValue(Sr04TMode2Distance(),Sr04TMode2Distance(),Sr04TMode2Distance()))/10; - break; - case 1: - distance = (real64_t)(sonar->ping_median(5))/ US_ROUNDTRIP_CM; - break; - default: - distance = NO_ECHO; - } - - return; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_DISTANCE[] PROGMEM = - "{s}SR04 " D_DISTANCE "{m}%s" D_UNIT_CENTIMETER "{e}"; -#endif - -void Sr04Show(bool json) -{ - - if (distance != 0) { - char distance_chr[33]; - dtostrfd(distance, 3, distance_chr); - - if(json) { - ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_COUNT, distance_chr); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_DISTANCE, distance_chr); -#endif - } - } -} - - - - - -bool Xsns22(uint8_t function) -{ - bool result = false; - - if (sr04_type) { - switch (function) { - case FUNC_INIT: - result = (pin[GPIO_SR04_ECHO]<99); - break; - case FUNC_EVERY_SECOND: - Sr04TReading(); - result = true; - break; - case FUNC_JSON_APPEND: - Sr04Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Sr04Show(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_24_si1145.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_24_si1145.ino" -#ifdef USE_I2C -#ifdef USE_SI1145 -# 30 "S:/Development/Tasmota/tasmota/xsns_24_si1145.ino" -#define XSNS_24 24 -#define XI2C_19 19 - -#define SI114X_ADDR 0X60 - - - -#define SI114X_QUERY 0X80 -#define SI114X_SET 0XA0 -#define SI114X_NOP 0X00 -#define SI114X_RESET 0X01 -#define SI114X_BUSADDR 0X02 -#define SI114X_PS_FORCE 0X05 -#define SI114X_GET_CAL 0X12 -#define SI114X_ALS_FORCE 0X06 -#define SI114X_PSALS_FORCE 0X07 -#define SI114X_PS_PAUSE 0X09 -#define SI114X_ALS_PAUSE 0X0A -#define SI114X_PSALS_PAUSE 0X0B -#define SI114X_PS_AUTO 0X0D -#define SI114X_ALS_AUTO 0X0E -#define SI114X_PSALS_AUTO 0X0F - - - -#define SI114X_PART_ID 0X00 -#define SI114X_REV_ID 0X01 -#define SI114X_SEQ_ID 0X02 -#define SI114X_INT_CFG 0X03 -#define SI114X_IRQ_ENABLE 0X04 -#define SI114X_IRQ_MODE1 0x05 -#define SI114X_IRQ_MODE2 0x06 -#define SI114X_HW_KEY 0X07 -#define SI114X_MEAS_RATE0 0X08 -#define SI114X_MEAS_RATE1 0X09 -#define SI114X_PS_RATE 0X0A -#define SI114X_PS_LED21 0X0F -#define SI114X_PS_LED3 0X10 -#define SI114X_UCOEFF0 0X13 -#define SI114X_UCOEFF1 0X14 -#define SI114X_UCOEFF2 0X15 -#define SI114X_UCOEFF3 0X16 -#define SI114X_WR 0X17 -#define SI114X_COMMAND 0X18 -#define SI114X_RESPONSE 0X20 -#define SI114X_IRQ_STATUS 0X21 -#define SI114X_ALS_VIS_DATA0 0X22 -#define SI114X_ALS_VIS_DATA1 0X23 -#define SI114X_ALS_IR_DATA0 0X24 -#define SI114X_ALS_IR_DATA1 0X25 -#define SI114X_PS1_DATA0 0X26 -#define SI114X_PS1_DATA1 0X27 -#define SI114X_PS2_DATA0 0X28 -#define SI114X_PS2_DATA1 0X29 -#define SI114X_PS3_DATA0 0X2A -#define SI114X_PS3_DATA1 0X2B -#define SI114X_AUX_DATA0_UVINDEX0 0X2C -#define SI114X_AUX_DATA1_UVINDEX1 0X2D -#define SI114X_RD 0X2E -#define SI114X_CHIP_STAT 0X30 - - - -#define SI114X_CHLIST 0X01 -#define SI114X_CHLIST_ENUV 0x80 -#define SI114X_CHLIST_ENAUX 0x40 -#define SI114X_CHLIST_ENALSIR 0x20 -#define SI114X_CHLIST_ENALSVIS 0x10 -#define SI114X_CHLIST_ENPS1 0x01 -#define SI114X_CHLIST_ENPS2 0x02 -#define SI114X_CHLIST_ENPS3 0x04 - -#define SI114X_PSLED12_SELECT 0X02 -#define SI114X_PSLED3_SELECT 0X03 - -#define SI114X_PS_ENCODE 0X05 -#define SI114X_ALS_ENCODE 0X06 - -#define SI114X_PS1_ADCMUX 0X07 -#define SI114X_PS2_ADCMUX 0X08 -#define SI114X_PS3_ADCMUX 0X09 - -#define SI114X_PS_ADC_COUNTER 0X0A -#define SI114X_PS_ADC_GAIN 0X0B -#define SI114X_PS_ADC_MISC 0X0C - -#define SI114X_ALS_IR_ADC_MUX 0X0E -#define SI114X_AUX_ADC_MUX 0X0F - -#define SI114X_ALS_VIS_ADC_COUNTER 0X10 -#define SI114X_ALS_VIS_ADC_GAIN 0X11 -#define SI114X_ALS_VIS_ADC_MISC 0X12 - -#define SI114X_LED_REC 0X1C - -#define SI114X_ALS_IR_ADC_COUNTER 0X1D -#define SI114X_ALS_IR_ADC_GAIN 0X1E -#define SI114X_ALS_IR_ADC_MISC 0X1F - - - - -#define SI114X_ADCMUX_SMALL_IR 0x00 -#define SI114X_ADCMUX_VISIABLE 0x02 -#define SI114X_ADCMUX_LARGE_IR 0x03 -#define SI114X_ADCMUX_NO 0x06 -#define SI114X_ADCMUX_GND 0x25 -#define SI114X_ADCMUX_TEMPERATURE 0x65 -#define SI114X_ADCMUX_VDD 0x75 - -#define SI114X_PSLED12_SELECT_PS1_NONE 0x00 -#define SI114X_PSLED12_SELECT_PS1_LED1 0x01 -#define SI114X_PSLED12_SELECT_PS1_LED2 0x02 -#define SI114X_PSLED12_SELECT_PS1_LED3 0x04 -#define SI114X_PSLED12_SELECT_PS2_NONE 0x00 -#define SI114X_PSLED12_SELECT_PS2_LED1 0x10 -#define SI114X_PSLED12_SELECT_PS2_LED2 0x20 -#define SI114X_PSLED12_SELECT_PS2_LED3 0x40 -#define SI114X_PSLED3_SELECT_PS2_NONE 0x00 -#define SI114X_PSLED3_SELECT_PS2_LED1 0x10 -#define SI114X_PSLED3_SELECT_PS2_LED2 0x20 -#define SI114X_PSLED3_SELECT_PS2_LED3 0x40 - -#define SI114X_ADC_GAIN_DIV1 0X00 -#define SI114X_ADC_GAIN_DIV2 0X01 -#define SI114X_ADC_GAIN_DIV4 0X02 -#define SI114X_ADC_GAIN_DIV8 0X03 -#define SI114X_ADC_GAIN_DIV16 0X04 -#define SI114X_ADC_GAIN_DIV32 0X05 - -#define SI114X_LED_CURRENT_5MA 0X01 -#define SI114X_LED_CURRENT_11MA 0X02 -#define SI114X_LED_CURRENT_22MA 0X03 -#define SI114X_LED_CURRENT_45MA 0X04 - -#define SI114X_ADC_COUNTER_1ADCCLK 0X00 -#define SI114X_ADC_COUNTER_7ADCCLK 0X01 -#define SI114X_ADC_COUNTER_15ADCCLK 0X02 -#define SI114X_ADC_COUNTER_31ADCCLK 0X03 -#define SI114X_ADC_COUNTER_63ADCCLK 0X04 -#define SI114X_ADC_COUNTER_127ADCCLK 0X05 -#define SI114X_ADC_COUNTER_255ADCCLK 0X06 -#define SI114X_ADC_COUNTER_511ADCCLK 0X07 - -#define SI114X_ADC_MISC_LOWRANGE 0X00 -#define SI114X_ADC_MISC_HIGHRANGE 0X20 -#define SI114X_ADC_MISC_ADC_NORMALPROXIMITY 0X00 -#define SI114X_ADC_MISC_ADC_RAWADC 0X04 - -#define SI114X_INT_CFG_INTOE 0X01 - -#define SI114X_IRQEN_ALS 0x01 -#define SI114X_IRQEN_PS1 0x04 -#define SI114X_IRQEN_PS2 0x08 -#define SI114X_IRQEN_PS3 0x10 - -uint16_t si1145_visible; -uint16_t si1145_infrared; -uint16_t si1145_uvindex; - -bool si1145_type = false; -uint8_t si1145_valid = 0; - - - -uint8_t Si1145ReadByte(uint8_t reg) -{ - return I2cRead8(SI114X_ADDR, reg); -} - -uint16_t Si1145ReadHalfWord(uint8_t reg) -{ - return I2cRead16LE(SI114X_ADDR, reg); -} - -bool Si1145WriteByte(uint8_t reg, uint16_t val) -{ - I2cWrite8(SI114X_ADDR, reg, val); -} - -uint8_t Si1145WriteParamData(uint8_t p, uint8_t v) -{ - Si1145WriteByte(SI114X_WR, v); - Si1145WriteByte(SI114X_COMMAND, p | SI114X_SET); - return Si1145ReadByte(SI114X_RD); -} - - - -bool Si1145Present(void) -{ - return (Si1145ReadByte(SI114X_PART_ID) == 0X45); -} - -void Si1145Reset(void) -{ - Si1145WriteByte(SI114X_MEAS_RATE0, 0); - Si1145WriteByte(SI114X_MEAS_RATE1, 0); - Si1145WriteByte(SI114X_IRQ_ENABLE, 0); - Si1145WriteByte(SI114X_IRQ_MODE1, 0); - Si1145WriteByte(SI114X_IRQ_MODE2, 0); - Si1145WriteByte(SI114X_INT_CFG, 0); - Si1145WriteByte(SI114X_IRQ_STATUS, 0xFF); - - Si1145WriteByte(SI114X_COMMAND, SI114X_RESET); - delay(10); - Si1145WriteByte(SI114X_HW_KEY, 0x17); - delay(10); -} - -void Si1145DeInit(void) -{ - - - Si1145WriteByte(SI114X_UCOEFF0, 0x29); - Si1145WriteByte(SI114X_UCOEFF1, 0x89); - Si1145WriteByte(SI114X_UCOEFF2, 0x02); - Si1145WriteByte(SI114X_UCOEFF3, 0x00); - Si1145WriteParamData(SI114X_CHLIST, SI114X_CHLIST_ENUV | SI114X_CHLIST_ENALSIR | SI114X_CHLIST_ENALSVIS | SI114X_CHLIST_ENPS1); - - - - Si1145WriteParamData(SI114X_PS1_ADCMUX, SI114X_ADCMUX_LARGE_IR); - Si1145WriteByte(SI114X_PS_LED21, SI114X_LED_CURRENT_22MA); - Si1145WriteParamData(SI114X_PSLED12_SELECT, SI114X_PSLED12_SELECT_PS1_LED1); - - - - Si1145WriteParamData(SI114X_PS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_PS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_PS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE | SI114X_ADC_MISC_ADC_RAWADC); - - - - Si1145WriteParamData(SI114X_ALS_VIS_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_ALS_VIS_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_ALS_VIS_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); - - - - Si1145WriteParamData(SI114X_ALS_IR_ADC_GAIN, SI114X_ADC_GAIN_DIV1); - Si1145WriteParamData(SI114X_ALS_IR_ADC_COUNTER, SI114X_ADC_COUNTER_511ADCCLK); - Si1145WriteParamData(SI114X_ALS_IR_ADC_MISC, SI114X_ADC_MISC_HIGHRANGE); - - - - Si1145WriteByte(SI114X_INT_CFG, SI114X_INT_CFG_INTOE); - Si1145WriteByte(SI114X_IRQ_ENABLE, SI114X_IRQEN_ALS); - - - - Si1145WriteByte(SI114X_MEAS_RATE0, 0xFF); - Si1145WriteByte(SI114X_COMMAND, SI114X_PSALS_AUTO); -} - -bool Si1145Begin(void) -{ - if (!Si1145Present()) { return false; } - - Si1145Reset(); - Si1145DeInit(); - return true; -} - - -uint16_t Si1145ReadUV(void) -{ - return Si1145ReadHalfWord(SI114X_AUX_DATA0_UVINDEX0); -} - - -uint16_t Si1145ReadVisible(void) -{ - return Si1145ReadHalfWord(SI114X_ALS_VIS_DATA0); -} - - -uint16_t Si1145ReadIR(void) -{ - return Si1145ReadHalfWord(SI114X_ALS_IR_DATA0); -} - - - -bool Si1145Read(void) -{ - if (si1145_valid) { si1145_valid--; } - - if (!Si1145Present()) { return false; } - - si1145_visible = Si1145ReadVisible(); - si1145_infrared = Si1145ReadIR(); - si1145_uvindex = Si1145ReadUV(); - si1145_valid = SENSOR_MAX_MISS; - return true; -} - -void Si1145Detect(void) -{ - if (I2cActive(SI114X_ADDR)) { return; } - - if (Si1145Begin()) { - si1145_type = true; - I2cSetActiveFound(SI114X_ADDR, "SI1145"); - } -} - -void Si1145Update(void) -{ - if (!Si1145Read()) { - AddLogMissed("SI1145", si1145_valid); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SI1145[] PROGMEM = - "{s}SI1145 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}" - "{s}SI1145 " D_INFRARED "{m}%d " D_UNIT_LUX "{e}" - "{s}SI1145 " D_UV_INDEX "{m}%d.%d{e}"; -#endif - -void Si1145Show(bool json) -{ - if (si1145_valid) { - if (json) { - ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), - si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, si1145_visible); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_SI1145, si1145_visible, si1145_infrared, si1145_uvindex /100, si1145_uvindex %100); -#endif - } - } -} - - - - - -bool Xsns24(uint8_t function) -{ - if (!I2cEnabled(XI2C_19)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Si1145Detect(); - } - else if (si1145_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Si1145Update(); - break; - case FUNC_JSON_APPEND: - Si1145Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Si1145Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_26_lm75ad.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_26_lm75ad.ino" -#ifdef USE_I2C -#ifdef USE_LM75AD -# 31 "S:/Development/Tasmota/tasmota/xsns_26_lm75ad.ino" -#define XSNS_26 26 -#define XI2C_20 20 - -#define LM75AD_ADDRESS1 0x48 -#define LM75AD_ADDRESS2 0x49 -#define LM75AD_ADDRESS3 0x4A -#define LM75AD_ADDRESS4 0x4B -#define LM75AD_ADDRESS5 0x4C -#define LM75AD_ADDRESS6 0x4D -#define LM75AD_ADDRESS7 0x4E -#define LM75AD_ADDRESS8 0x4F - -#define LM75_TEMP_REGISTER 0x00 -#define LM75_CONF_REGISTER 0x01 -#define LM75_THYST_REGISTER 0x02 -#define LM75_TOS_REGISTER 0x03 - -bool lm75ad_type = false; -uint8_t lm75ad_address; -uint8_t lm75ad_addresses[] = { LM75AD_ADDRESS1, LM75AD_ADDRESS2, LM75AD_ADDRESS3, LM75AD_ADDRESS4, LM75AD_ADDRESS5, LM75AD_ADDRESS6, LM75AD_ADDRESS7, LM75AD_ADDRESS8 }; - -void LM75ADDetect(void) -{ - for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { - lm75ad_address = lm75ad_addresses[i]; - if (I2cActive(lm75ad_address)) { - continue; } - if (!I2cSetDevice(lm75ad_address)) { - break; - } - uint16_t buffer; - if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { - if (buffer == 0x4B00) { - lm75ad_type = true; - I2cSetActiveFound(lm75ad_address, "LM75AD"); - break; - } - } - } -} - -float LM75ADGetTemp(void) -{ - int16_t sign = 1; - - uint16_t t = I2cRead16(lm75ad_address, LM75_TEMP_REGISTER); - if (t & 0x8000) { - t = (~t) +0x20; - sign = -1; - } - t = t >> 5; - return ConvertTemp(sign * t * 0.125); -} - -void LM75ADShow(bool json) -{ - float t = LM75ADGetTemp(); - char temperature[33]; - dtostrfd(t, Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(PSTR(",\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), temperature); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, "LM75AD", temperature, TempUnit()); -#endif - } -} - - - - - -bool Xsns26(uint8_t function) -{ - if (!I2cEnabled(XI2C_20)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - LM75ADDetect(); - } - else if (lm75ad_type) { - switch (function) { - case FUNC_JSON_APPEND: - LM75ADShow(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - LM75ADShow(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -# 28 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -#ifdef USE_I2C -#ifdef USE_APDS9960 -# 39 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -#define XSNS_27 27 -#define XI2C_21 21 - -#if defined(USE_SHT) || defined(USE_VEML6070) || defined(USE_TSL2561) - #warning **** Turned off conflicting drivers SHT and VEML6070 **** - #ifdef USE_SHT - #undef USE_SHT - #endif - #ifdef USE_VEML6070 - #undef USE_VEML6070 - #endif - #ifdef USE_TSL2561 - #undef USE_TSL2561 - #endif -#endif - -#define APDS9960_I2C_ADDR 0x39 - -#define APDS9960_CHIPID_1 0xAB -#define APDS9960_CHIPID_2 0x9C - -#define APDS9930_CHIPID_1 0x12 -#define APDS9930_CHIPID_2 0x39 - - -#define GESTURE_THRESHOLD_OUT 10 -#define GESTURE_SENSITIVITY_1 50 -#define GESTURE_SENSITIVITY_2 20 - -uint8_t APDS9960addr; -uint8_t APDS9960type = 0; -char APDS9960stype[] = "APDS9960"; -char currentGesture[6]; -uint8_t gesture_mode = 1; - - -volatile uint8_t recovery_loop_counter = 0; -#define APDS9960_LONG_RECOVERY 50 -#define APDS9960_MAX_GESTURE_CYCLES 50 -bool APDS9960_overload = false; - -#ifdef USE_WEBSERVER -const char HTTP_APDS_9960_SNS[] PROGMEM = - "{s}" "Red" "{m}%s{e}" - "{s}" "Green" "{m}%s{e}" - "{s}" "Blue" "{m}%s{e}" - "{s}" "Ambient" "{m}%s " D_UNIT_LUX "{e}" - "{s}" "CCT" "{m}%s " "K" "{e}" - "{s}" "Proximity" "{m}%s{e}"; -#endif -# 97 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -#define FIFO_PAUSE_TIME 30 - - -#define APDS9960_ENABLE 0x80 -#define APDS9960_ATIME 0x81 -#define APDS9960_WTIME 0x83 -#define APDS9960_AILTL 0x84 -#define APDS9960_AILTH 0x85 -#define APDS9960_AIHTL 0x86 -#define APDS9960_AIHTH 0x87 -#define APDS9960_PILT 0x89 -#define APDS9960_PIHT 0x8B -#define APDS9960_PERS 0x8C -#define APDS9960_CONFIG1 0x8D -#define APDS9960_PPULSE 0x8E -#define APDS9960_CONTROL 0x8F -#define APDS9960_CONFIG2 0x90 -#define APDS9960_ID 0x92 -#define APDS9960_STATUS 0x93 -#define APDS9960_CDATAL 0x94 -#define APDS9960_CDATAH 0x95 -#define APDS9960_RDATAL 0x96 -#define APDS9960_RDATAH 0x97 -#define APDS9960_GDATAL 0x98 -#define APDS9960_GDATAH 0x99 -#define APDS9960_BDATAL 0x9A -#define APDS9960_BDATAH 0x9B -#define APDS9960_PDATA 0x9C -#define APDS9960_POFFSET_UR 0x9D -#define APDS9960_POFFSET_DL 0x9E -#define APDS9960_CONFIG3 0x9F -#define APDS9960_GPENTH 0xA0 -#define APDS9960_GEXTH 0xA1 -#define APDS9960_GCONF1 0xA2 -#define APDS9960_GCONF2 0xA3 -#define APDS9960_GOFFSET_U 0xA4 -#define APDS9960_GOFFSET_D 0xA5 -#define APDS9960_GOFFSET_L 0xA7 -#define APDS9960_GOFFSET_R 0xA9 -#define APDS9960_GPULSE 0xA6 -#define APDS9960_GCONF3 0xAA -#define APDS9960_GCONF4 0xAB -#define APDS9960_GFLVL 0xAE -#define APDS9960_GSTATUS 0xAF -#define APDS9960_IFORCE 0xE4 -#define APDS9960_PICLEAR 0xE5 -#define APDS9960_CICLEAR 0xE6 -#define APDS9960_AICLEAR 0xE7 -#define APDS9960_GFIFO_U 0xFC -#define APDS9960_GFIFO_D 0xFD -#define APDS9960_GFIFO_L 0xFE -#define APDS9960_GFIFO_R 0xFF - - -#define APDS9960_PON 0b00000001 -#define APDS9960_AEN 0b00000010 -#define APDS9960_PEN 0b00000100 -#define APDS9960_WEN 0b00001000 -#define APSD9960_AIEN 0b00010000 -#define APDS9960_PIEN 0b00100000 -#define APDS9960_GEN 0b01000000 -#define APDS9960_GVALID 0b00000001 - - -#define OFF 0 -#define ON 1 - - -#define POWER 0 -#define AMBIENT_LIGHT 1 -#define PROXIMITY 2 -#define WAIT 3 -#define AMBIENT_LIGHT_INT 4 -#define PROXIMITY_INT 5 -#define GESTURE 6 -#define ALL 7 - - -#define LED_DRIVE_100MA 0 -#define LED_DRIVE_50MA 1 -#define LED_DRIVE_25MA 2 -#define LED_DRIVE_12_5MA 3 - - -#define PGAIN_1X 0 -#define PGAIN_2X 1 -#define PGAIN_4X 2 -#define PGAIN_8X 3 - - -#define AGAIN_1X 0 -#define AGAIN_4X 1 -#define AGAIN_16X 2 -#define AGAIN_64X 3 - - -#define GGAIN_1X 0 -#define GGAIN_2X 1 -#define GGAIN_4X 2 -#define GGAIN_8X 3 - - -#define LED_BOOST_100 0 -#define LED_BOOST_150 1 -#define LED_BOOST_200 2 -#define LED_BOOST_300 3 - - -#define GWTIME_0MS 0 -#define GWTIME_2_8MS 1 -#define GWTIME_5_6MS 2 -#define GWTIME_8_4MS 3 -#define GWTIME_14_0MS 4 -#define GWTIME_22_4MS 5 -#define GWTIME_30_8MS 6 -#define GWTIME_39_2MS 7 - - -#define DEFAULT_ATIME 0xdb -#define DEFAULT_WTIME 246 -#define DEFAULT_PROX_PPULSE 0x87 -#define DEFAULT_GESTURE_PPULSE 0x89 -#define DEFAULT_POFFSET_UR 0 -#define DEFAULT_POFFSET_DL 0 -#define DEFAULT_CONFIG1 0x60 -#define DEFAULT_LDRIVE LED_DRIVE_100MA -#define DEFAULT_PGAIN PGAIN_4X -#define DEFAULT_AGAIN AGAIN_4X -#define DEFAULT_PILT 0 -#define DEFAULT_PIHT 50 -#define DEFAULT_AILT 0xFFFF -#define DEFAULT_AIHT 0 -#define DEFAULT_PERS 0x11 -#define DEFAULT_CONFIG2 0x01 -#define DEFAULT_CONFIG3 0 -#define DEFAULT_GPENTH 40 -#define DEFAULT_GEXTH 30 -#define DEFAULT_GCONF1 0x40 -#define DEFAULT_GGAIN GGAIN_4X -#define DEFAULT_GLDRIVE LED_DRIVE_100MA -#define DEFAULT_GWTIME GWTIME_2_8MS -#define DEFAULT_GOFFSET 0 -#define DEFAULT_GPULSE 0xC9 -#define DEFAULT_GCONF3 0 -#define DEFAULT_GIEN 0 - -#define ERROR 0xFF - - -enum { - DIR_NONE, - DIR_LEFT, - DIR_RIGHT, - DIR_UP, - DIR_DOWN, - DIR_ALL -}; - - -enum { - APDS9960_NA_STATE, - APDS9960_ALL_STATE -}; - - -typedef struct gesture_data_type { - uint8_t u_data[32]; - uint8_t d_data[32]; - uint8_t l_data[32]; - uint8_t r_data[32]; - uint8_t index; - uint8_t total_gestures; - uint8_t in_threshold; - uint8_t out_threshold; -} gesture_data_type; - - - gesture_data_type gesture_data_; - int16_t gesture_ud_delta_ = 0; - int16_t gesture_lr_delta_ = 0; - int16_t gesture_ud_count_ = 0; - int16_t gesture_lr_count_ = 0; - int16_t gesture_state_ = 0; - int16_t gesture_motion_ = DIR_NONE; - - typedef struct color_data_type { - uint16_t a; - uint16_t r; - uint16_t g; - uint16_t b; - uint8_t p; - uint16_t cct; - uint16_t lux; - } color_data_type; - - color_data_type color_data; - uint8_t APDS9960_aTime = DEFAULT_ATIME; -# 306 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - bool wireWriteByte(uint8_t val) - { - Wire.beginTransmission(APDS9960_I2C_ADDR); - Wire.write(val); - if( Wire.endTransmission() != 0 ) { - return false; - } - - return true; - } -# 325 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -int8_t wireReadDataBlock( uint8_t reg, - uint8_t *val, - uint16_t len) -{ - unsigned char i = 0; - - - if (!wireWriteByte(reg)) { - return -1; - } - - - Wire.requestFrom(APDS9960_I2C_ADDR, len); - while (Wire.available()) { - if (i >= len) { - return -1; - } - val[i] = Wire.read(); - i++; - } - - return i; -} - - - - - - - -void calculateColorTemperature(void) -{ - float X, Y, Z; - float xc, yc; - float n; - float cct; - - - - - - X = (-0.14282F * color_data.r) + (1.54924F * color_data.g) + (-0.95641F * color_data.b); - Y = (-0.32466F * color_data.r) + (1.57837F * color_data.g) + (-0.73191F * color_data.b); - Z = (-0.68202F * color_data.r) + (0.77073F * color_data.g) + ( 0.56332F * color_data.b); - - - xc = (X) / (X + Y + Z); - yc = (Y) / (X + Y + Z); - - - n = (xc - 0.3320F) / (0.1858F - yc); - - - color_data.cct = (449.0F * FastPrecisePowf(n, 3)) + (3525.0F * FastPrecisePowf(n, 2)) + (6823.3F * n) + 5520.33F; - - return; -} -# 392 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getProxIntLowThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT) ; - return val; - } - - - - - - - void setProxIntLowThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold); - } - - - - - - - uint8_t getProxIntHighThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; - return val; - } - - - - - - - - void setProxIntHighThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold); - } -# 448 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getLEDDrive(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; - - val = (val >> 6) & 0b00000011; - - return val; - } -# 471 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void setLEDDrive(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - drive = drive << 6; - val &= 0b00111111; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 500 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getProximityGain(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL) ; - - val = (val >> 2) & 0b00000011; - - return val; - } -# 523 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void setProximityGain(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - drive = drive << 2; - val &= 0b11110011; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 564 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void setAmbientLightGain(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONTROL); - - - drive &= 0b00000011; - val &= 0b11111100; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONTROL, val); - } -# 591 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getLEDBoost(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; - - - val = (val >> 4) & 0b00000011; - - return val; - } -# 615 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void setLEDBoost(uint8_t boost) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG2) ; - - boost &= 0b00000011; - boost = boost << 4; - val &= 0b11001111; - val |= boost; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, val) ; - } - - - - - - - uint8_t getProxGainCompEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - val = (val >> 5) & 0b00000001; - - return val; - } - - - - - - - void setProxGainCompEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - enable &= 0b00000001; - enable = enable << 5; - val &= 0b11011111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; - } -# 683 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getProxPhotoMask(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - val &= 0b00001111; - - return val; - } -# 708 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void setProxPhotoMask(uint8_t mask) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_CONFIG3) ; - - - mask &= 0b00001111; - val &= 0b11110000; - val |= mask; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, val) ; - } - - - - - - - uint8_t getGestureEnterThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GPENTH) ; - - return val; - } - - - - - - - void setGestureEnterThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPENTH, threshold) ; - - } - - - - - - - uint8_t getGestureExitThresh(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GEXTH) ; - - return val; - } - - - - - - - void setGestureExitThresh(uint8_t threshold) - { - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GEXTH, threshold) ; - } -# 786 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getGestureGain(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val = (val >> 5) & 0b00000011; - - return val; - } -# 810 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void setGestureGain(uint8_t gain) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - gain &= 0b00000011; - gain = gain << 5; - val &= 0b10011111; - val |= gain; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } -# 838 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getGestureLEDDrive(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val = (val >> 3) & 0b00000011; - - return val; - } -# 862 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void setGestureLEDDrive(uint8_t drive) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - drive &= 0b00000011; - drive = drive << 3; - val &= 0b11100111; - val |= drive; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } -# 894 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - uint8_t getGestureWaitTime(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - val &= 0b00000111; - - return val; - } -# 922 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void setGestureWaitTime(uint8_t time) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF2) ; - - - time &= 0b00000111; - val &= 0b11111000; - val |= time; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF2, val) ; - } - - - - - - - void getLightIntLowThreshold(uint16_t &threshold) - { - uint8_t val_byte; - threshold = 0; - - - val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AILTL) ; - threshold = val_byte; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_byte) ; - threshold = threshold + ((uint16_t)val_byte << 8); - } - - - - - - - - void setLightIntLowThreshold(uint16_t threshold) - { - uint8_t val_low; - uint8_t val_high; - - - val_low = threshold & 0x00FF; - val_high = (threshold & 0xFF00) >> 8; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTL, val_low) ; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AILTH, val_high) ; - - } - - - - - - - - void getLightIntHighThreshold(uint16_t &threshold) - { - uint8_t val_byte; - threshold = 0; - - - val_byte = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AIHTL); - threshold = val_byte; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_byte) ; - threshold = threshold + ((uint16_t)val_byte << 8); - } - - - - - - - void setLightIntHighThreshold(uint16_t threshold) - { - uint8_t val_low; - uint8_t val_high; - - - val_low = threshold & 0x00FF; - val_high = (threshold & 0xFF00) >> 8; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTL, val_low); - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_AIHTH, val_high) ; - } - - - - - - - - void getProximityIntLowThreshold(uint8_t &threshold) - { - threshold = 0; - - - threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PILT); - - } - - - - - - - void setProximityIntLowThreshold(uint8_t threshold) - { - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PILT, threshold) ; - } -# 1055 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" - void getProximityIntHighThreshold(uint8_t &threshold) - { - threshold = 0; - - - threshold = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PIHT) ; - - } - - - - - - - void setProximityIntHighThreshold(uint8_t threshold) - { - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PIHT, threshold) ; - } - - - - - - - uint8_t getAmbientLightIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - val = (val >> 4) & 0b00000001; - - return val; - } - - - - - - - void setAmbientLightIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE); - - - enable &= 0b00000001; - enable = enable << 4; - val &= 0b11101111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; - } - - - - - - - uint8_t getProximityIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - val = (val >> 5) & 0b00000001; - - return val; - } - - - - - - - void setProximityIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - - enable &= 0b00000001; - enable = enable << 5; - val &= 0b11011111; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, val) ; - } - - - - - - - uint8_t getGestureIntEnable(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - val = (val >> 1) & 0b00000001; - - return val; - } - - - - - - - void setGestureIntEnable(uint8_t enable) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - enable &= 0b00000001; - enable = enable << 1; - val &= 0b11111101; - val |= enable; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; - } - - - - - - void clearAmbientLightInt(void) - { - uint8_t throwaway; - throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_AICLEAR); - } - - - - - - void clearProximityInt(void) - { - uint8_t throwaway; - throwaway = I2cRead8(APDS9960_I2C_ADDR, APDS9960_PICLEAR) ; - - } - - - - - - - uint8_t getGestureMode(void) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - val &= 0b00000001; - - return val; - } - - - - - - - void setGestureMode(uint8_t mode) - { - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GCONF4) ; - - - mode &= 0b00000001; - val &= 0b11111110; - val |= mode; - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF4, val) ; - } - - -bool APDS9960_init(void) -{ - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, DEFAULT_ATIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, DEFAULT_WTIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_PROX_PPULSE) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_UR, DEFAULT_POFFSET_UR) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_POFFSET_DL, DEFAULT_POFFSET_DL) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG1, DEFAULT_CONFIG1) ; - - setLEDDrive(DEFAULT_LDRIVE); - - setProximityGain(DEFAULT_PGAIN); - - setAmbientLightGain(DEFAULT_AGAIN); - - setProxIntLowThresh(DEFAULT_PILT) ; - - setProxIntHighThresh(DEFAULT_PIHT); - - setLightIntLowThreshold(DEFAULT_AILT) ; - - setLightIntHighThreshold(DEFAULT_AIHT) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PERS, DEFAULT_PERS) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG2, DEFAULT_CONFIG2) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_CONFIG3, DEFAULT_CONFIG3) ; - - - setGestureEnterThresh(DEFAULT_GPENTH); - - setGestureExitThresh(DEFAULT_GEXTH) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF1, DEFAULT_GCONF1) ; - - setGestureGain(DEFAULT_GGAIN) ; - - setGestureLEDDrive(DEFAULT_GLDRIVE) ; - - setGestureWaitTime(DEFAULT_GWTIME) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_U, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_D, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_L, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GOFFSET_R, DEFAULT_GOFFSET) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GPULSE, DEFAULT_GPULSE) ; - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_GCONF3, DEFAULT_GCONF3) ; - - setGestureIntEnable(DEFAULT_GIEN); - - disablePower(); - - return true; -} -# 1333 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -uint8_t getMode(void) -{ - uint8_t enable_value; - - - enable_value = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ENABLE) ; - - return enable_value; -} - - - - - - - -void setMode(uint8_t mode, uint8_t enable) -{ - uint8_t reg_val; - - - reg_val = getMode(); - - - - enable = enable & 0x01; - if( mode >= 0 && mode <= 6 ) { - if (enable) { - reg_val |= (1 << mode); - } else { - reg_val &= ~(1 << mode); - } - } else if( mode == ALL ) { - if (enable) { - reg_val = 0x7F; - } else { - reg_val = 0x00; - } - } - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ENABLE, reg_val) ; -} - - - - - - -void enableLightSensor(void) -{ - - setAmbientLightGain(DEFAULT_AGAIN); - setAmbientLightIntEnable(0); - enablePower() ; - setMode(AMBIENT_LIGHT, 1) ; -} - - - - - -void disableLightSensor(void) -{ - setAmbientLightIntEnable(0) ; - setMode(AMBIENT_LIGHT, 0) ; -} - - - - - - -void enableProximitySensor(void) -{ - - setProximityGain(DEFAULT_PGAIN); - setLEDDrive(DEFAULT_LDRIVE) ; - setProximityIntEnable(0) ; - enablePower(); - setMode(PROXIMITY, 1) ; -} - - - - - -void disableProximitySensor(void) -{ - setProximityIntEnable(0) ; - setMode(PROXIMITY, 0) ; -} - - - - - - -void enableGestureSensor(void) -{ - - - - - - - - resetGestureParameters(); - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_WTIME, 0xFF) ; - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_PPULSE, DEFAULT_GESTURE_PPULSE) ; - setLEDBoost(LED_BOOST_100); - setGestureIntEnable(0) ; - setGestureMode(1); - enablePower() ; - setMode(WAIT, 1) ; - setMode(PROXIMITY, 1) ; - setMode(GESTURE, 1); -} - - - - - -void disableGestureSensor(void) -{ - resetGestureParameters(); - setGestureIntEnable(0) ; - setGestureMode(0) ; - setMode(GESTURE, 0) ; -} - - - - - - -bool isGestureAvailable(void) -{ - uint8_t val; - - - val = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS) ; - - - val &= APDS9960_GVALID; - - - if( val == 1) { - return true; - } else { - return false; - } -} - - - - - - -int16_t readGesture(void) -{ - uint8_t fifo_level = 0; - uint8_t bytes_read = 0; - uint8_t fifo_data[128]; - uint8_t gstatus; - uint16_t motion; - uint16_t i; - uint8_t gesture_loop_counter = 0; - - - if( !isGestureAvailable() || !(getMode() & 0b01000001) ) { - return DIR_NONE; - } - - - while(1) { - if (gesture_loop_counter == APDS9960_MAX_GESTURE_CYCLES){ - disableGestureSensor(); - APDS9960_overload = true; - AddLog_P(LOG_LEVEL_DEBUG, PSTR("Sensor overload")); - } - gesture_loop_counter += 1; - - delay(FIFO_PAUSE_TIME); - - - gstatus = I2cRead8(APDS9960_I2C_ADDR, APDS9960_GSTATUS); - - - if( (gstatus & APDS9960_GVALID) == APDS9960_GVALID ) { - - - fifo_level = I2cRead8(APDS9960_I2C_ADDR,APDS9960_GFLVL) ; - - - if( fifo_level > 0) { - bytes_read = wireReadDataBlock( APDS9960_GFIFO_U, - (uint8_t*)fifo_data, - (fifo_level * 4) ); - if( bytes_read == -1 ) { - return ERROR; - } - - - if( bytes_read >= 4 ) { - for( i = 0; i < bytes_read; i += 4 ) { - gesture_data_.u_data[gesture_data_.index] = \ - fifo_data[i + 0]; - gesture_data_.d_data[gesture_data_.index] = \ - fifo_data[i + 1]; - gesture_data_.l_data[gesture_data_.index] = \ - fifo_data[i + 2]; - gesture_data_.r_data[gesture_data_.index] = \ - fifo_data[i + 3]; - gesture_data_.index++; - gesture_data_.total_gestures++; - } - - if( processGestureData() ) { - if( decodeGesture() ) { - - } - } - - gesture_data_.index = 0; - gesture_data_.total_gestures = 0; - } - } - } else { - - - delay(FIFO_PAUSE_TIME); - decodeGesture(); - motion = gesture_motion_; - resetGestureParameters(); - return motion; - } - } -} - - - - - -void enablePower(void) -{ - setMode(POWER, 1) ; -} - - - - - -void disablePower(void) -{ - setMode(POWER, 0) ; -} -# 1600 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -void readAllColorAndProximityData(void) -{ - if (I2cReadBuffer(APDS9960_I2C_ADDR, APDS9960_CDATAL, (uint8_t *) &color_data, (uint16_t)9)) - { - - - } -} -# 1616 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -void resetGestureParameters(void) -{ - gesture_data_.index = 0; - gesture_data_.total_gestures = 0; - - gesture_ud_delta_ = 0; - gesture_lr_delta_ = 0; - - gesture_ud_count_ = 0; - gesture_lr_count_ = 0; - - gesture_state_ = 0; - gesture_motion_ = DIR_NONE; -} - - - - - - -bool processGestureData(void) -{ - uint8_t u_first = 0; - uint8_t d_first = 0; - uint8_t l_first = 0; - uint8_t r_first = 0; - uint8_t u_last = 0; - uint8_t d_last = 0; - uint8_t l_last = 0; - uint8_t r_last = 0; - uint16_t ud_ratio_first; - uint16_t lr_ratio_first; - uint16_t ud_ratio_last; - uint16_t lr_ratio_last; - uint16_t ud_delta; - uint16_t lr_delta; - uint16_t i; - - - if( gesture_data_.total_gestures <= 4 ) { - return false; - } - - - if( (gesture_data_.total_gestures <= 32) && \ - (gesture_data_.total_gestures > 0) ) { - - - for( i = 0; i < gesture_data_.total_gestures; i++ ) { - if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { - - u_first = gesture_data_.u_data[i]; - d_first = gesture_data_.d_data[i]; - l_first = gesture_data_.l_data[i]; - r_first = gesture_data_.r_data[i]; - break; - } - } - - - if( (u_first == 0) || (d_first == 0) || \ - (l_first == 0) || (r_first == 0) ) { - - return false; - } - - for( i = gesture_data_.total_gestures - 1; i >= 0; i-- ) { - - if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && - (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) { - - u_last = gesture_data_.u_data[i]; - d_last = gesture_data_.d_data[i]; - l_last = gesture_data_.l_data[i]; - r_last = gesture_data_.r_data[i]; - break; - } - } - } - - - ud_ratio_first = ((u_first - d_first) * 100) / (u_first + d_first); - lr_ratio_first = ((l_first - r_first) * 100) / (l_first + r_first); - ud_ratio_last = ((u_last - d_last) * 100) / (u_last + d_last); - lr_ratio_last = ((l_last - r_last) * 100) / (l_last + r_last); - - - ud_delta = ud_ratio_last - ud_ratio_first; - lr_delta = lr_ratio_last - lr_ratio_first; - - - gesture_ud_delta_ += ud_delta; - gesture_lr_delta_ += lr_delta; - - - if( gesture_ud_delta_ >= GESTURE_SENSITIVITY_1 ) { - gesture_ud_count_ = 1; - } else if( gesture_ud_delta_ <= -GESTURE_SENSITIVITY_1 ) { - gesture_ud_count_ = -1; - } else { - gesture_ud_count_ = 0; - } - - - if( gesture_lr_delta_ >= GESTURE_SENSITIVITY_1 ) { - gesture_lr_count_ = 1; - } else if( gesture_lr_delta_ <= -GESTURE_SENSITIVITY_1 ) { - gesture_lr_count_ = -1; - } else { - gesture_lr_count_ = 0; - } - return false; -} - - - - - - -bool decodeGesture(void) -{ - - - if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 0) ) { - gesture_motion_ = DIR_UP; - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 0) ) { - gesture_motion_ = DIR_DOWN; - } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == 1) ) { - gesture_motion_ = DIR_RIGHT; - } else if( (gesture_ud_count_ == 0) && (gesture_lr_count_ == -1) ) { - gesture_motion_ = DIR_LEFT; - } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == 1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_UP; - } else { - gesture_motion_ = DIR_RIGHT; - } - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == -1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_DOWN; - } else { - gesture_motion_ = DIR_LEFT; - } - } else if( (gesture_ud_count_ == -1) && (gesture_lr_count_ == -1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_UP; - } else { - gesture_motion_ = DIR_LEFT; - } - } else if( (gesture_ud_count_ == 1) && (gesture_lr_count_ == 1) ) { - if( abs(gesture_ud_delta_) > abs(gesture_lr_delta_) ) { - gesture_motion_ = DIR_DOWN; - } else { - gesture_motion_ = DIR_RIGHT; - } - } else { - return false; - } - - return true; -} - -void handleGesture(void) { - if (isGestureAvailable() ) { - switch (readGesture()) { - case DIR_UP: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("UP")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Up")); - break; - case DIR_DOWN: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("DOWN")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Down")); - break; - case DIR_LEFT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("LEFT")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Left")); - break; - case DIR_RIGHT: - AddLog_P(LOG_LEVEL_DEBUG, PSTR("RIGHT")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Right")); - break; - default: - if(APDS9960_overload) - { - AddLog_P(LOG_LEVEL_DEBUG, PSTR("LONG")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("Long")); - } - else{ - AddLog_P(LOG_LEVEL_DEBUG, PSTR("NONE")); - snprintf_P(currentGesture, sizeof(currentGesture), PSTR("None")); - } - } - MqttPublishSensor(); - } -} - -void APDS9960_adjustATime(void) -{ - - I2cValidRead16LE(&color_data.a, APDS9960_I2C_ADDR, APDS9960_CDATAL); - - - if (color_data.a < (uint16_t)20){ - APDS9960_aTime = 0x40; - } - else if (color_data.a < (uint16_t)40){ - APDS9960_aTime = 0x80; - } - else if (color_data.a < (uint16_t)50){ - APDS9960_aTime = DEFAULT_ATIME; - } - else if (color_data.a < (uint16_t)70){ - APDS9960_aTime = 0xc0; - } - if (color_data.a < 200){ - APDS9960_aTime = 0xe9; - } - - - - else{ - APDS9960_aTime = 0xff; - } - - - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, APDS9960_aTime); - enablePower(); - enableLightSensor(); - delay(20); -} - - -void APDS9960_loop(void) -{ - if (recovery_loop_counter > 0){ - recovery_loop_counter -= 1; - } - if (recovery_loop_counter == 1 && APDS9960_overload){ - enableGestureSensor(); - APDS9960_overload = false; - Response_P(PSTR("{\"Gesture\":\"On\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - gesture_mode = 1; - } - - if (gesture_mode) { - if (recovery_loop_counter == 0){ - handleGesture(); - - if (APDS9960_overload) - { - disableGestureSensor(); - recovery_loop_counter = APDS9960_LONG_RECOVERY; - Response_P(PSTR("{\"Gesture\":\"Off\"}")); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); - gesture_mode = 0; - } - } - } -} - -void APDS9960_detect(void) -{ - if (APDS9960type || I2cActive(APDS9960_I2C_ADDR)) { return; } - - APDS9960type = I2cRead8(APDS9960_I2C_ADDR, APDS9960_ID); - if (APDS9960type == APDS9960_CHIPID_1 || APDS9960type == APDS9960_CHIPID_2) { - if (APDS9960_init()) { - I2cSetActiveFound(APDS9960_I2C_ADDR, APDS9960stype); - - enableProximitySensor(); - enableGestureSensor(); - } else { - APDS9960type = 0; - } - } else { - APDS9960type = 0; - } - currentGesture[0] = '\0'; -} - - - - - -void APDS9960_show(bool json) -{ - if (!APDS9960type) { return; } - - if (!gesture_mode && !APDS9960_overload) { - char red_chr[10]; - char green_chr[10]; - char blue_chr[10]; - char ambient_chr[10]; - char cct_chr[10]; - char prox_chr[10]; - - readAllColorAndProximityData(); - - sprintf (ambient_chr, "%u", color_data.a/4); - sprintf (red_chr, "%u", color_data.r); - sprintf (green_chr, "%u", color_data.g); - sprintf (blue_chr, "%u", color_data.b ); - sprintf (prox_chr, "%u", color_data.p ); - - - - - - calculateColorTemperature(); - sprintf (cct_chr, "%u", color_data.cct); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), - APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); -#endif - } - } - else { - if (json && (currentGesture[0] != '\0' )) { - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); - currentGesture[0] = '\0'; - } - } -} -# 1961 "S:/Development/Tasmota/tasmota/xsns_27_apds9960.ino" -bool APDS9960CommandSensor(void) -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - disableGestureSensor(); - gesture_mode = 0; - enableLightSensor(); - APDS9960_overload = false; - break; - case 1: - if (APDS9960type) { - setGestureGain(DEFAULT_GGAIN); - setProximityGain(DEFAULT_PGAIN); - disableLightSensor(); - enableGestureSensor(); - gesture_mode = 1; - } - break; - case 2: - if (APDS9960type) { - setGestureGain(GGAIN_2X); - setProximityGain(PGAIN_2X); - disableLightSensor(); - enableGestureSensor(); - gesture_mode = 1; - } - break; - default: - int temp_aTime = (uint8_t)XdrvMailbox.payload; - if (temp_aTime > 2 && temp_aTime < 256){ - disablePower(); - I2cWrite8(APDS9960_I2C_ADDR, APDS9960_ATIME, temp_aTime); - enablePower(); - enableLightSensor(); - } - break; - } - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); - - return serviced; -} - - - - - -bool Xsns27(uint8_t function) -{ - if (!I2cEnabled(XI2C_21)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - APDS9960_detect(); - } - else if (APDS9960type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - APDS9960_loop(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_27 == XdrvMailbox.index) { - result = APDS9960CommandSensor(); - } - break; - case FUNC_JSON_APPEND: - APDS9960_show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - APDS9960_show(0); - break; -#endif - } - } - return result; -} -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_28_tm1638.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_28_tm1638.ino" -#ifdef USE_TM1638 - - - - - - -#define XSNS_28 28 - -#define TM1638_COLOR_NONE 0 -#define TM1638_COLOR_RED 1 -#define TM1638_COLOR_GREEN 2 - -#define TM1638_CLOCK_DELAY 1 - -uint8_t tm1638_type = 1; -uint8_t tm1638_clock_pin = 0; -uint8_t tm1638_data_pin = 0; -uint8_t tm1638_strobe_pin = 0; -uint8_t tm1638_displays = 8; -uint8_t tm1638_active_display = 1; -uint8_t tm1638_intensity = 0; -uint8_t tm1638_state = 0; - - - - - - -void Tm16XXSend(uint8_t data) -{ - for (uint32_t i = 0; i < 8; i++) { - digitalWrite(tm1638_data_pin, !!(data & (1 << i))); - digitalWrite(tm1638_clock_pin, LOW); - delayMicroseconds(TM1638_CLOCK_DELAY); - digitalWrite(tm1638_clock_pin, HIGH); - } -} - -void Tm16XXSendCommand(uint8_t cmd) -{ - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(cmd); - digitalWrite(tm1638_strobe_pin, HIGH); -} - -void TM16XXSendData(uint8_t address, uint8_t data) -{ - Tm16XXSendCommand(0x44); - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0xC0 | address); - Tm16XXSend(data); - digitalWrite(tm1638_strobe_pin, HIGH); -} - -uint8_t Tm16XXReceive(void) -{ - uint8_t temp = 0; - - - pinMode(tm1638_data_pin, INPUT); - digitalWrite(tm1638_data_pin, HIGH); - - for (uint32_t i = 0; i < 8; ++i) { - digitalWrite(tm1638_clock_pin, LOW); - delayMicroseconds(TM1638_CLOCK_DELAY); - temp |= digitalRead(tm1638_data_pin) << i; - digitalWrite(tm1638_clock_pin, HIGH); - } - - - pinMode(tm1638_data_pin, OUTPUT); - digitalWrite(tm1638_data_pin, LOW); - - return temp; -} - - - -void Tm16XXClearDisplay(void) -{ - for (uint32_t i = 0; i < tm1638_displays; i++) { - TM16XXSendData(i << 1, 0); - } -} - -void Tm1638SetLED(uint8_t color, uint8_t pos) -{ - TM16XXSendData((pos << 1) + 1, color); -} - -void Tm1638SetLEDs(word leds) -{ - for (uint32_t i = 0; i < tm1638_displays; i++) { - uint8_t color = 0; - - if ((leds & (1 << i)) != 0) { - color |= TM1638_COLOR_RED; - } - - if ((leds & (1 << (i + 8))) != 0) { - color |= TM1638_COLOR_GREEN; - } - - Tm1638SetLED(color, i); - } -} - -uint8_t Tm1638GetButtons(void) -{ - uint8_t keys = 0; - - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0x42); - for (uint32_t i = 0; i < 4; i++) { - keys |= Tm16XXReceive() << i; - } - digitalWrite(tm1638_strobe_pin, HIGH); - - return keys; -} - - - -void TmInit(void) -{ - tm1638_type = 0; - if ((pin[GPIO_TM16CLK] < 99) && (pin[GPIO_TM16DIO] < 99) && (pin[GPIO_TM16STB] < 99)) { - tm1638_clock_pin = pin[GPIO_TM16CLK]; - tm1638_data_pin = pin[GPIO_TM16DIO]; - tm1638_strobe_pin = pin[GPIO_TM16STB]; - - pinMode(tm1638_data_pin, OUTPUT); - pinMode(tm1638_clock_pin, OUTPUT); - pinMode(tm1638_strobe_pin, OUTPUT); - - digitalWrite(tm1638_strobe_pin, HIGH); - digitalWrite(tm1638_clock_pin, HIGH); - - Tm16XXSendCommand(0x40); - Tm16XXSendCommand(0x80 | (tm1638_active_display ? 8 : 0) | tmin(7, tm1638_intensity)); - - digitalWrite(tm1638_strobe_pin, LOW); - Tm16XXSend(0xC0); - for (uint32_t i = 0; i < 16; i++) { - Tm16XXSend(0x00); - } - digitalWrite(tm1638_strobe_pin, HIGH); - - tm1638_type = 1; - tm1638_state = 1; - } -} - -void TmLoop(void) -{ - if (tm1638_state) { - uint8_t buttons = Tm1638GetButtons(); - for (uint32_t i = 0; i < MAX_SWITCHES; i++) { - SwitchSetVirtual(i, (buttons &1) ^1); - uint8_t color = (SwitchGetVirtual(i)) ? TM1638_COLOR_NONE : TM1638_COLOR_RED; - Tm1638SetLED(color, i); - buttons >>= 1; - } - SwitchHandler(1); - } -} -# 201 "S:/Development/Tasmota/tasmota/xsns_28_tm1638.ino" -bool Xsns28(uint8_t function) -{ - bool result = false; - - if (tm1638_type) { - switch (function) { - case FUNC_INIT: - TmInit(); - break; - case FUNC_EVERY_50_MSECOND: - TmLoop(); - break; -# 223 "S:/Development/Tasmota/tasmota/xsns_28_tm1638.ino" - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_29_mcp230xx.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_29_mcp230xx.ino" -#ifdef USE_I2C -#ifdef USE_MCP230xx -# 31 "S:/Development/Tasmota/tasmota/xsns_29_mcp230xx.ino" -#define XSNS_29 29 -#define XI2C_22 22 - - - - - -uint8_t MCP230xx_IODIR = 0x00; -uint8_t MCP230xx_GPINTEN = 0x02; -uint8_t MCP230xx_IOCON = 0x05; -uint8_t MCP230xx_GPPU = 0x06; -uint8_t MCP230xx_INTF = 0x07; -uint8_t MCP230xx_INTCAP = 0x08; -uint8_t MCP230xx_GPIO = 0x09; - -uint8_t mcp230xx_type = 0; -uint8_t mcp230xx_pincount = 0; -uint8_t mcp230xx_int_en = 0; -uint8_t mcp230xx_int_prio_counter = 0; -uint8_t mcp230xx_int_counter_en = 0; -uint8_t mcp230xx_int_retainer_en = 0; -uint8_t mcp230xx_int_sec_counter = 0; - -uint8_t mcp230xx_int_report_defer_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -uint16_t mcp230xx_int_counter[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -uint8_t mcp230xx_int_retainer[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -unsigned long int_millis[16]; - -const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29_D%i\":{\"MODE\":%i,\"PULL_UP\":\"%s\",\"INT_MODE\":\"%s\",\"STATE\":\"%s\"}}"; - -const char MCP230XX_INTCFG_RESPONSE[] PROGMEM = "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; - -#ifdef USE_MCP230xx_OUTPUT -const char MCP230XX_CMND_RESPONSE[] PROGMEM = "{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"}}"; -#endif - -void MCP230xx_CheckForIntCounter(void) { - uint8_t en = 0; - for (uint32_t ca=0;ca<16;ca++) { - if (Settings.mcp230xx_config[ca].int_count_en) { - en=1; - } - } - if (!Settings.mcp230xx_int_timer) en=0; - mcp230xx_int_counter_en=en; - if (!mcp230xx_int_counter_en) { - for (uint32_t ca=0;ca<16;ca++) { - mcp230xx_int_counter[ca] = 0; - } - } -} - -void MCP230xx_CheckForIntRetainer(void) { - uint8_t en = 0; - for (uint32_t ca=0;ca<16;ca++) { - if (Settings.mcp230xx_config[ca].int_retain_flag) { - en=1; - } - } - mcp230xx_int_retainer_en=en; - if (!mcp230xx_int_retainer_en) { - for (uint32_t ca=0;ca<16;ca++) { - mcp230xx_int_retainer[ca] = 0; - } - } -} - -const char* ConvertNumTxt(uint8_t statu, uint8_t pinmod=0) { -#ifdef USE_MCP230xx_OUTPUT -if ((6 == pinmod) && (statu < 2)) { statu = abs(statu-1); } -#endif - switch (statu) { - case 0: - return "OFF"; - break; - case 1: - return "ON"; - break; -#ifdef USE_MCP230xx_OUTPUT - case 2: - return "TOGGLE"; - break; -#endif - } - return ""; -} - -const char* IntModeTxt(uint8_t intmo) { - switch (intmo) { - case 0: - return "ALL"; - break; - case 1: - return "EVENT"; - break; - case 2: - return "TELE"; - break; - case 3: - return "DISABLED"; - break; - } - return ""; -} - -uint8_t MCP230xx_readGPIO(uint8_t port) { - return I2cRead8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port); -} - -void MCP230xx_ApplySettings(void) -{ - uint8_t int_en = 0; - for (uint32_t mcp230xx_port = 0; mcp230xx_port < mcp230xx_type; mcp230xx_port++) { - uint8_t reg_gppu = 0; - uint8_t reg_gpinten = 0; - uint8_t reg_iodir = 0xFF; -#ifdef USE_MCP230xx_OUTPUT - uint8_t reg_portpins = 0x00; -#endif - for (uint32_t idx = 0; idx < 8; idx++) { - switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) { - case 0 ... 1: - reg_iodir |= (1 << idx); - break; - case 2 ... 4: - reg_iodir |= (1 << idx); - reg_gpinten |= (1 << idx); - int_en = 1; - break; -#ifdef USE_MCP230xx_OUTPUT - case 5 ... 6: - reg_iodir &= ~(1 << idx); - if (Settings.flag.save_state) { - reg_portpins |= (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].saved_state << idx); - } else { - if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { - reg_portpins |= (1 << idx); - } - } - break; -#endif - default: - break; - } -#ifdef USE_MCP230xx_OUTPUT - if ((Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) && (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode < 5)) { - reg_gppu |= (1 << idx); - } -#else - if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) { - reg_gppu |= (1 << idx); - } -#endif - } - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPPU+mcp230xx_port, reg_gppu); - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten); - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_IODIR+mcp230xx_port, reg_iodir); -#ifdef USE_MCP230xx_OUTPUT - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO+mcp230xx_port, reg_portpins); -#endif - } - for (uint32_t idx=0;idx 0) { - if (I2cValidRead8(&mcp230xx_intcap, USE_MCP230xx_ADDR, MCP230xx_INTCAP+mcp230xx_port)) { - for (uint32_t intp = 0; intp < 8; intp++) { - if ((intf >> intp) & 0x01) { - report_int = 0; - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode > 1) { - switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode) { - case 2: - report_int = 1; - break; - case 3: - if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; - break; - case 4: - if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; - break; - default: - break; - } - - if ((mcp230xx_int_counter_en) && (report_int)) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { - mcp230xx_int_counter[intp+(mcp230xx_port*8)]++; - } - } - - if (report_int) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { - mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]++; - if (mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)] >= Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_defer) { - mcp230xx_int_report_defer_counter[intp+(mcp230xx_port*8)]=0; - } else { - report_int = 0; - } - } - } - - if (report_int) { - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_retain_flag) { - mcp230xx_int_retainer[intp+(mcp230xx_port*8)] = 1; - report_int = 0; - } - } - if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_count_en) { - report_int = 0; - } - if (report_int) { - bool int_tele = false; - bool int_event = false; - unsigned long millis_now = millis(); - unsigned long millis_since_last_int = millis_now - int_millis[intp+(mcp230xx_port*8)]; - int_millis[intp+(mcp230xx_port*8)]=millis_now; - switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].int_report_mode) { - case 0: - int_tele=true; - int_event=true; - break; - case 1: - int_event=true; - break; - case 2: - int_tele=true; - break; - } - if (int_tele) { - ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), - intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); - } - if (int_event) { - char command[19]; - sprintf(command,"event MCPINT_D%i=%i",intp+(mcp230xx_port*8),((mcp230xx_intcap >> intp) & 0x01)); - ExecuteCommand(command, SRC_RULE); - } - } - } - } - } - } - } - } - } -} - -void MCP230xx_Show(bool json) -{ - if (json) { - uint8_t gpio = MCP230xx_readGPIO(0); - ResponseAppend_P(PSTR(",\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), - (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); - if (2 == mcp230xx_type) { - gpio = MCP230xx_readGPIO(1); - ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), - (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); - } - ResponseJsonEnd(); - } -} - -#ifdef USE_MCP230xx_OUTPUT - -void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { - uint8_t portpins; - uint8_t port = 0; - uint8_t pinmo = Settings.mcp230xx_config[pin].pinmode; - uint8_t interlock = Settings.flag.interlock; - int pinadd = (pin % 2)+1-(3*(pin % 2)); - char cmnd[7], stt[4]; - if (pin > 7) { port = 1; } - portpins = MCP230xx_readGPIO(port); - if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { - if (pinstate < 2) { - if (6 == pinmo) { - if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins |= (1 << (pin+pinadd-(port*8))),portpins &= ~(1 << (pin-(port*8))); - } else { - if (pinstate) portpins &= ~(1 << (pin+pinadd-(port*8))),portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); - } - } else { - if (6 == pinmo) { - portpins |= (1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); - } else { - portpins &= ~(1 << (pin+pinadd-(port*8))),portpins ^= (1 << (pin-(port*8))); - } - } - } else { - if (pinstate < 2) { - if (pinstate) portpins |= (1 << (pin-(port*8))); else portpins &= ~(1 << (pin-(port*8))); - } else { - portpins ^= (1 << (pin-(port*8))); - } - } - I2cWrite8(USE_MCP230xx_ADDR, MCP230xx_GPIO + port, portpins); - if (Settings.flag.save_state) { - Settings.mcp230xx_config[pin].saved_state=portpins>>(pin-(port*8))&1; - Settings.mcp230xx_config[pin+pinadd].saved_state=portpins>>(pin+pinadd-(port*8))&1; - } - sprintf(cmnd,ConvertNumTxt(pinstate, pinmo)); - sprintf(stt,ConvertNumTxt((portpins >> (pin-(port*8))&1), pinmo)); - if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { - char stt1[4]; - sprintf(stt1,ConvertNumTxt((portpins >> (pin+pinadd-(port*8))&1), pinmo)); - Response_P(PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); - } else { - Response_P(MCP230XX_CMND_RESPONSE, pin, cmnd, stt); - } -} - -#endif - -void MCP230xx_Reset(uint8_t pinmode) { - uint8_t pullup = 0; - if ((pinmode > 1) && (pinmode < 5)) { pullup=1; } - for (uint32_t pinx=0;pinx<16;pinx++) { - Settings.mcp230xx_config[pinx].pinmode=pinmode; - Settings.mcp230xx_config[pinx].pullup=pullup; - Settings.mcp230xx_config[pinx].saved_state=0; - if ((pinmode > 1) && (pinmode < 5)) { - Settings.mcp230xx_config[pinx].int_report_mode=0; - } else { - Settings.mcp230xx_config[pinx].int_report_mode=3; - } - Settings.mcp230xx_config[pinx].int_report_defer=0; - Settings.mcp230xx_config[pinx].int_count_en=0; - Settings.mcp230xx_config[pinx].int_retain_flag=0; - Settings.mcp230xx_config[pinx].spare13=0; - Settings.mcp230xx_config[pinx].spare14=0; - Settings.mcp230xx_config[pinx].spare15=0; - } - Settings.mcp230xx_int_prio = 0; - Settings.mcp230xx_int_timer = 0; - MCP230xx_ApplySettings(); - char pulluptxt[7]; - char intmodetxt[9]; - sprintf(pulluptxt,ConvertNumTxt(pullup)); - uint8_t intmode = 3; - if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } - sprintf(intmodetxt,IntModeTxt(intmode)); - Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); -} - -bool MCP230xx_Command(void) -{ - bool serviced = true; - bool validpin = false; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((intpri >= 0) && (intpri <= 20)) { - Settings.mcp230xx_int_prio = intpri; - Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTTIMER")) { - if (paramcount > 1) { - uint8_t inttim = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if ((inttim >= 0) && (inttim <= 3600)) { - Settings.mcp230xx_int_timer = inttim; - MCP230xx_CheckForIntCounter(); - Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTDEF")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t intdef = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((intdef >= 0) && (intdef <= 15)) { - Settings.mcp230xx_config[pin].int_report_defer=intdef; - if (Settings.mcp230xx_config[pin].int_count_en) { - Settings.mcp230xx_config[pin].int_count_en=0; - MCP230xx_CheckForIntCounter(); - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); - } - Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTCNT")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t intcnt = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((intcnt >= 0) && (intcnt <= 1)) { - Settings.mcp230xx_config[pin].int_count_en=intcnt; - if (Settings.mcp230xx_config[pin].int_report_defer) { - Settings.mcp230xx_config[pin].int_report_defer=0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTDEF for pin D%i"),pin); - } - if (Settings.mcp230xx_config[pin].int_report_mode < 3) { - Settings.mcp230xx_config[pin].int_report_mode=3; - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled immediate interrupt/telemetry reporting for pin D%i"),pin); - } - if ((Settings.mcp230xx_config[pin].int_count_en) && (!Settings.mcp230xx_int_timer)) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); - } - MCP230xx_CheckForIntCounter(); - Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"INTRETAIN")) { - if (paramcount > 1) { - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - if (pin < mcp230xx_pincount) { - if (pin == 0) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0")) validpin=true; - } else { - validpin = true; - } - } - if (validpin) { - if (paramcount > 2) { - uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - if ((int_retain >= 0) && (int_retain <= 1)) { - Settings.mcp230xx_config[pin].int_retain_flag=int_retain; - Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); - MCP230xx_CheckForIntRetainer(); - return serviced; - } else { - serviced=false; - return serviced; - } - } else { - Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); - return serviced; - } - } - serviced = false; - return serviced; - } else { - serviced = false; - return serviced; - } - } - - uint8_t pin = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); - - if (pin < mcp230xx_pincount) { - if (0 == pin) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1), "0")) validpin=true; - } else { - validpin=true; - } - } - if (validpin && (paramcount > 1)) { - if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "?")) { - uint8_t port = 0; - if (pin > 7) { port = 1; } - uint8_t portdata = MCP230xx_readGPIO(port); - char pulluptxtr[7],pinstatustxtr[7]; - char intmodetxt[9]; - sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); - sprintf(pulluptxtr,ConvertNumTxt(Settings.mcp230xx_config[pin].pullup)); -#ifdef USE_MCP230xx_OUTPUT - uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; - sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); - Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); -#else - sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); - Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); -#endif - return serviced; - } -#ifdef USE_MCP230xx_OUTPUT - if (Settings.mcp230xx_config[pin].pinmode >= 5) { - uint8_t pincmd = Settings.mcp230xx_config[pin].pinmode - 5; - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "ON")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "1"))) { - MCP230xx_SetOutPin(pin,abs(pincmd-1)); - return serviced; - } - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "OFF")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "0"))) { - MCP230xx_SetOutPin(pin,pincmd); - return serviced; - } - if ((!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "T")) || (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 2), "2"))) { - MCP230xx_SetOutPin(pin,2); - return serviced; - } - } -#endif - uint8_t pinmode = 0; - uint8_t pullup = 0; - uint8_t intmode = 0; - if (paramcount > 1) { - pinmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); - } - if (paramcount > 2) { - pullup = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); - } - if (paramcount > 3) { - intmode = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4)); - } -#ifdef USE_MCP230xx_OUTPUT - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 7) && (pullup < 2) && (paramcount > 2)) { -#else - if ((pin < mcp230xx_pincount) && (pinmode > 0) && (pinmode < 5) && (pullup < 2) && (paramcount > 2)) { -#endif - Settings.mcp230xx_config[pin].pinmode=pinmode; - Settings.mcp230xx_config[pin].pullup=pullup; - if ((pinmode > 1) && (pinmode < 5)) { - if ((intmode >= 0) && (intmode <= 3)) { - Settings.mcp230xx_config[pin].int_report_mode=intmode; - } - } else { - Settings.mcp230xx_config[pin].int_report_mode=3; - } - MCP230xx_ApplySettings(); - uint8_t port = 0; - if (pin > 7) { port = 1; } - uint8_t portdata = MCP230xx_readGPIO(port); - char pulluptxtc[7], pinstatustxtc[7]; - char intmodetxt[9]; - sprintf(pulluptxtc,ConvertNumTxt(pullup)); - sprintf(intmodetxt,IntModeTxt(Settings.mcp230xx_config[pin].int_report_mode)); -#ifdef USE_MCP230xx_OUTPUT - sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1,Settings.mcp230xx_config[pin].pinmode)); -#else - sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); -#endif - Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); - return serviced; - } - } else { - serviced=false; - return serviced; - } - return serviced; -} - -#ifdef USE_MCP230xx_DISPLAYOUTPUT - -const char HTTP_SNS_MCP230xx_OUTPUT[] PROGMEM = "{s}MCP230XX D%d{m}%s{e}"; - -void MCP230xx_UpdateWebData(void) -{ - uint8_t gpio1 = MCP230xx_readGPIO(0); - uint8_t gpio2 = 0; - if (2 == mcp230xx_type) { - gpio2 = MCP230xx_readGPIO(1); - } - uint16_t gpio = (gpio2 << 8) + gpio1; - for (uint32_t pin = 0; pin < mcp230xx_pincount; pin++) { - if (Settings.mcp230xx_config[pin].pinmode >= 5) { - char stt[7]; - sprintf(stt,ConvertNumTxt((gpio>>pin)&1,Settings.mcp230xx_config[pin].pinmode)); - WSContentSend_PD(HTTP_SNS_MCP230xx_OUTPUT, pin, stt); - } - } -} - -#endif - -#ifdef USE_MCP230xx_OUTPUT - -void MCP230xx_OutputTelemetry(void) -{ - uint8_t outputcount = 0; - uint16_t gpiototal = 0; - uint8_t gpioa = 0; - uint8_t gpiob = 0; - gpioa=MCP230xx_readGPIO(0); - if (2 == mcp230xx_type) { gpiob=MCP230xx_readGPIO(1); } - gpiototal=((uint16_t)gpiob << 8) | gpioa; - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode >= 5) outputcount++; - } - if (outputcount) { - char stt[7]; - ResponseTime_P(PSTR(",\"MCP230_OUT\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].pinmode >= 5) { - sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); - ResponseAppend_P(PSTR("\"OUT_D%i\":\"%s\","),pinx,stt); - } - } - ResponseAppend_P(PSTR("\"END\":1}}")); - MqttPublishTeleSensor(); - } -} - -#endif - -void MCP230xx_Interrupt_Counter_Report(void) { - ResponseTime_P(PSTR(",\"MCP230_INTTIMER\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].int_count_en) { - ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); - mcp230xx_int_counter[pinx]=0; - } - } - ResponseAppend_P(PSTR("\"END\":1}}")); - MqttPublishTeleSensor(); - mcp230xx_int_sec_counter = 0; -} - -void MCP230xx_Interrupt_Retain_Report(void) { - uint16_t retainresult = 0; - ResponseTime_P(PSTR(",\"MCP_INTRETAIN\":{")); - for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { - if (Settings.mcp230xx_config[pinx].int_retain_flag) { - ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); - retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); - mcp230xx_int_retainer[pinx]=0; - } - } - ResponseAppend_P(PSTR("\"Value\":%u}}"),retainresult); - MqttPublishTeleSensor(); -} - - - - - -bool Xsns29(uint8_t function) -{ - if (!I2cEnabled(XI2C_22)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MCP230xx_Detect(); - } - else if (mcp230xx_type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - if (mcp230xx_int_en) { - mcp230xx_int_prio_counter++; - if ((mcp230xx_int_prio_counter) >= (Settings.mcp230xx_int_prio)) { - MCP230xx_CheckForInterrupt(); - mcp230xx_int_prio_counter=0; - } - } - break; - case FUNC_EVERY_SECOND: - if (mcp230xx_int_counter_en) { - mcp230xx_int_sec_counter++; - if (mcp230xx_int_sec_counter >= Settings.mcp230xx_int_timer) { - MCP230xx_Interrupt_Counter_Report(); - } - } - if (tele_period == 0) { - if (mcp230xx_int_retainer_en) { - MCP230xx_Interrupt_Retain_Report(); - } -#ifdef USE_MCP230xx_OUTPUT - MCP230xx_OutputTelemetry(); -#endif - } - break; - case FUNC_JSON_APPEND: - MCP230xx_Show(1); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_29 == XdrvMailbox.index) { - result = MCP230xx_Command(); - } - break; -#ifdef USE_WEBSERVER -#ifdef USE_MCP230xx_OUTPUT -#ifdef USE_MCP230xx_DISPLAYOUTPUT - case FUNC_WEB_SENSOR: - MCP230xx_UpdateWebData(); - break; -#endif -#endif -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" -# 46 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" -#ifdef USE_I2C -#ifdef USE_MPR121 - - - - - -#define XSNS_30 30 -#define XI2C_23 23 - - - - - - - -#define MPR121_ELEX_REG 0x00 - - -#define MPR121_MHDR_REG 0x2B - - -#define MPR121_MHDR_VAL 0x01 - - -#define MPR121_NHDR_REG 0x2C - - -#define MPR121_NHDR_VAL 0x01 - - -#define MPR121_NCLR_REG 0x2D - - -#define MPR121_NCLR_VAL 0x0E - - -#define MPR121_MHDF_REG 0x2F - - -#define MPR121_MHDF_VAL 0x01 - - -#define MPR121_NHDF_REG 0x30 - - -#define MPR121_NHDF_VAL 0x05 - - -#define MPR121_NCLF_REG 0x31 - - -#define MPR121_NCLF_VAL 0x01 - - -#define MPR121_MHDPROXR_REG 0x36 - - -#define MPR121_MHDPROXR_VAL 0x3F - - -#define MPR121_NHDPROXR_REG 0x37 - - -#define MPR121_NHDPROXR_VAL 0x5F - - -#define MPR121_NCLPROXR_REG 0x38 - - -#define MPR121_NCLPROXR_VAL 0x04 - - -#define MPR121_FDLPROXR_REG 0x39 - - -#define MPR121_FDLPROXR_VAL 0x00 - - -#define MPR121_MHDPROXF_REG 0x3A - - -#define MPR121_MHDPROXF_VAL 0x01 - - -#define MPR121_NHDPROXF_REG 0x3B - - -#define MPR121_NHDPROXF_VAL 0x01 - - -#define MPR121_NCLPROXF_REG 0x3C - - -#define MPR121_NCLPROXF_VAL 0x1F - - -#define MPR121_FDLPROXF_REG 0x3D - - -#define MPR121_FDLPROXF_VAL 0x04 - - -#define MPR121_E0TTH_REG 0x41 - - -#define MPR121_E0TTH_VAL 12 - - -#define MPR121_E0RTH_REG 0x42 - - -#define MPR121_E0RTH_VAL 6 - - -#define MPR121_CDT_REG 0x5D - - -#define MPR121_CDT_VAL 0x20 - - -#define MPR121_ECR_REG 0x5E - - -#define MPR121_ECR_VAL 0x8F - - - -#define MPR121_SRST_REG 0x80 - - -#define MPR121_SRST_VAL 0x63 - - -#define BITC(sensor,position) ((pS->current[sensor] >> position) & 1) - - -#define BITP(sensor,position) ((pS->previous[sensor] >> position) & 1) -# 195 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" -typedef struct mpr121 mpr121; -struct mpr121 { - const uint8_t i2c_addr[4] = { 0x5A, 0x5B, 0x5C, 0x5D }; - const char id[4] = { 'A', 'B', 'C', 'D' }; - bool connected[4] = { false, false, false, false }; - bool running[4] = { false, false, false, false }; - uint16_t current[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; - uint16_t previous[4] = { 0x0000, 0x0000, 0x0000, 0x0000 }; -}; - -bool mpr21_found = false; -# 217 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" -void Mpr121Init(struct mpr121 *pS, bool initial) -{ - - for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { - - if (initial && I2cActive(pS->i2c_addr[i])) { continue; } - - - pS->connected[i] = (I2cWrite8(pS->i2c_addr[i], MPR121_SRST_REG, MPR121_SRST_VAL) - && (0x24 == I2cRead8(pS->i2c_addr[i], 0x5D))); - if (pS->connected[i]) { - - - mpr21_found = true; - char device_name[16]; - snprintf_P(device_name, sizeof(device_name), PSTR("MPR121(%c)"), pS->id[i]); - I2cSetActiveFound(pS->i2c_addr[i], device_name); - - - for (uint32_t j = 0; j < 13; j++) { - - - I2cWrite8(pS->i2c_addr[i], MPR121_E0TTH_REG + 2 * j, MPR121_E0TTH_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_E0RTH_REG + 2 * j, MPR121_E0RTH_VAL); - } - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDR_REG, MPR121_MHDR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDR_REG, MPR121_NHDR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLR_REG, MPR121_NCLR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDF_REG, MPR121_MHDF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDF_REG, MPR121_NHDF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLF_REG, MPR121_NCLF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXR_REG, MPR121_MHDPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXR_REG, MPR121_NHDPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXR_REG, MPR121_NCLPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXR_REG, MPR121_FDLPROXR_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_MHDPROXF_REG, MPR121_MHDPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NHDPROXF_REG, MPR121_NHDPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_NCLPROXF_REG, MPR121_NCLPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_FDLPROXF_REG, MPR121_FDLPROXF_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_CDT_REG, MPR121_CDT_VAL); - - - I2cWrite8(pS->i2c_addr[i], MPR121_ECR_REG, MPR121_ECR_VAL); - - - pS->running[i] = (0x00 != I2cRead8(pS->i2c_addr[i], MPR121_ECR_REG)); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_I2C "MPR121%c: %sRunning"), pS->id[i], (pS->running[i]) ? "" : "NOT"); - - } else { - - - pS->running[i] = false; - } - } - - - if (!(pS->connected[0] || pS->connected[1] || pS->connected[2] - || pS->connected[3])) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_I2C "MPR121: No sensors found")); - } -} -# 326 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" -void Mpr121Show(struct mpr121 *pS, uint8_t function) -{ - - - for (uint32_t i = 0; i < sizeof(pS->i2c_addr[i]); i++) { - - - if (pS->connected[i]) { - - - if (!I2cValidRead16LE(&pS->current[i], pS->i2c_addr[i], MPR121_ELEX_REG)) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Cannot read data!"), pS->id[i]); - Mpr121Init(pS, false); - return; - } - - if (BITC(i, 15)) { - - - I2cWrite8(pS->i2c_addr[i], MPR121_ELEX_REG, 0x00); - AddLog_P2(LOG_LEVEL_ERROR, PSTR(D_LOG_I2C "MPR121%c: ERROR: Excess current detected! Fix circuits if it happens repeatedly! Soft-resetting MPR121 ..."), pS->id[i]); - Mpr121Init(pS, false); - return; - } - } - - if (pS->running[i]) { - - - if (FUNC_JSON_APPEND == function) { - ResponseAppend_P(PSTR(",\"MPR121%c\":{"), pS->id[i]); - } - - for (uint32_t j = 0; j < 13; j++) { - - - if ((FUNC_EVERY_50_MSECOND == function) - && (BITC(i, j) != BITP(i, j))) { - Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); - MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); - } - -#ifdef USE_WEBSERVER - if (FUNC_WEB_SENSOR == function) { - WSContentSend_PD(PSTR("{s}MPR121%c Button%d{m}%d{e}"), pS->id[i], j, BITC(i, j)); - } -#endif - - - if (FUNC_JSON_APPEND == function) { - ResponseAppend_P(PSTR("%s\"Button%i\":%i"), (j > 0 ? "," : ""), j, BITC(i, j)); - } - } - - - pS->previous[i] = pS->current[i]; - - - if (FUNC_JSON_APPEND == function) { - ResponseJsonEnd(); - } - } - } -} -# 410 "S:/Development/Tasmota/tasmota/xsns_30_mpr121.ino" -bool Xsns30(uint8_t function) -{ - if (!I2cEnabled(XI2C_23)) { return false; } - - bool result = false; - - - static struct mpr121 mpr121; - - if (FUNC_INIT == function) { - - Mpr121Init(&mpr121, true); - } - else if (mpr21_found) { - - switch (function) { - - - case FUNC_EVERY_50_MSECOND: - Mpr121Show(&mpr121, FUNC_EVERY_50_MSECOND); - break; - - - case FUNC_JSON_APPEND: - Mpr121Show(&mpr121, FUNC_JSON_APPEND); - break; - -#ifdef USE_WEBSERVER - - case FUNC_WEB_SENSOR: - Mpr121Show(&mpr121, FUNC_WEB_SENSOR); - break; -#endif - } - } - - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_31_ccs811.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_31_ccs811.ino" -#ifdef USE_I2C -#ifdef USE_CCS811 -# 30 "S:/Development/Tasmota/tasmota/xsns_31_ccs811.ino" -#define XSNS_31 31 -#define XI2C_24 24 - -#define EVERYNSECONDS 5 - -#include "Adafruit_CCS811.h" - -Adafruit_CCS811 ccs; -uint8_t CCS811_ready = 0; -uint8_t CCS811_type = 0;; -uint16_t eCO2; -uint16_t TVOC; -uint8_t tcnt = 0; -uint8_t ecnt = 0; - - - -void CCS811Detect(void) -{ - if (I2cActive(CCS811_ADDRESS)) { return; } - - if (!ccs.begin(CCS811_ADDRESS)) { - CCS811_type = 1; - I2cSetActiveFound(CCS811_ADDRESS, "CCS811"); - } -} - -void CCS811Update(void) -{ - tcnt++; - if (tcnt >= EVERYNSECONDS) { - tcnt = 0; - CCS811_ready = 0; - if (ccs.available()) { - if (!ccs.readData()){ - TVOC = ccs.getTVOC(); - eCO2 = ccs.geteCO2(); - CCS811_ready = 1; - if (global_update && global_humidity>0 && global_temperature!=9999) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); } - ecnt = 0; - } - } else { - - ecnt++; - if (ecnt > 6) { - - ccs.begin(CCS811_ADDRESS); - } - } - } -} - -const char HTTP_SNS_CCS811[] PROGMEM = - "{s}CCS811 " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" - "{s}CCS811 " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}"; - -void CCS811Show(bool json) -{ - if (CCS811_ready) { - if (json) { - ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CCS811, eCO2, TVOC); -#endif - } - } -} - - - - - -bool Xsns31(uint8_t function) -{ - if (!I2cEnabled(XI2C_24)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - CCS811Detect(); - } - else if (CCS811_type) { - switch (function) { - case FUNC_EVERY_SECOND: - CCS811Update(); - break; - case FUNC_JSON_APPEND: - CCS811Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - CCS811Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_32_mpu6050.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_32_mpu6050.ino" -#ifdef USE_I2C -#ifdef USE_MPU6050 -# 30 "S:/Development/Tasmota/tasmota/xsns_32_mpu6050.ino" -#define XSNS_32 32 -#define XI2C_25 25 - -#define D_SENSOR_MPU6050 "MPU6050" - -#define MPU_6050_ADDR_AD0_LOW 0x68 -#define MPU_6050_ADDR_AD0_HIGH 0x69 - -uint8_t MPU_6050_address; -uint8_t MPU_6050_addresses[] = { MPU_6050_ADDR_AD0_LOW, MPU_6050_ADDR_AD0_HIGH }; -uint8_t MPU_6050_found; - -int16_t MPU_6050_ax = 0, MPU_6050_ay = 0, MPU_6050_az = 0; -int16_t MPU_6050_gx = 0, MPU_6050_gy = 0, MPU_6050_gz = 0; -int16_t MPU_6050_temperature = 0; - -#ifdef USE_MPU6050_DMP - #include "MPU6050_6Axis_MotionApps20.h" - #include "I2Cdev.h" - #include - typedef struct MPU6050_DMP{ - uint8_t devStatus; - uint16_t packetSize; - uint16_t fifoCount; - uint8_t fifoBuffer[64]; - Quaternion q; - VectorInt16 aa; - VectorInt16 aaReal; - VectorFloat gravity; - float euler[3]; - float yawPitchRoll[3]; - } MPU6050_DMP; - - MPU6050_DMP MPU6050_dmp; -#else - #include -#endif -MPU6050 mpu6050; - -void MPU_6050PerformReading(void) -{ -#ifdef USE_MPU6050_DMP - mpu6050.resetFIFO(); - MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); - while (MPU6050_dmp.fifoCount < MPU6050_dmp.packetSize) MPU6050_dmp.fifoCount = mpu6050.getFIFOCount(); - mpu6050.getFIFOBytes(MPU6050_dmp.fifoBuffer, MPU6050_dmp.packetSize); - MPU6050_dmp.fifoCount -= MPU6050_dmp.packetSize; - - mpu6050.dmpGetQuaternion(&MPU6050_dmp.q, MPU6050_dmp.fifoBuffer); - mpu6050.dmpGetEuler(MPU6050_dmp.euler, &MPU6050_dmp.q); - mpu6050.dmpGetAccel(&MPU6050_dmp.aa, MPU6050_dmp.fifoBuffer); - mpu6050.dmpGetGravity(&MPU6050_dmp.gravity, &MPU6050_dmp.q); - mpu6050.dmpGetLinearAccel(&MPU6050_dmp.aaReal, &MPU6050_dmp.aa, &MPU6050_dmp.gravity); - mpu6050.dmpGetYawPitchRoll(MPU6050_dmp.yawPitchRoll, &MPU6050_dmp.q, &MPU6050_dmp.gravity); - MPU_6050_gx = MPU6050_dmp.euler[0] * 180/M_PI; - MPU_6050_gy = MPU6050_dmp.euler[1] * 180/M_PI; - MPU_6050_gz = MPU6050_dmp.euler[2] * 180/M_PI; - MPU_6050_ax = MPU6050_dmp.aaReal.x; - MPU_6050_ay = MPU6050_dmp.aaReal.y; - MPU_6050_az = MPU6050_dmp.aaReal.z; -#else - mpu6050.getMotion6( - &MPU_6050_ax, - &MPU_6050_ay, - &MPU_6050_az, - &MPU_6050_gx, - &MPU_6050_gy, - &MPU_6050_gz - ); -#endif - MPU_6050_temperature = mpu6050.getTemperature(); -} -# 119 "S:/Development/Tasmota/tasmota/xsns_32_mpu6050.ino" -void MPU_6050Detect(void) -{ - for (uint32_t i = 0; i < sizeof(MPU_6050_addresses); i++) - { - MPU_6050_address = MPU_6050_addresses[i]; - if (!I2cSetDevice(MPU_6050_address)) { break; } - mpu6050.setAddr(MPU_6050_addresses[i]); - -#ifdef USE_MPU6050_DMP - MPU6050_dmp.devStatus = mpu6050.dmpInitialize(); - mpu6050.setXGyroOffset(220); - mpu6050.setYGyroOffset(76); - mpu6050.setZGyroOffset(-85); - mpu6050.setZAccelOffset(1788); - if (MPU6050_dmp.devStatus == 0) { - mpu6050.setDMPEnabled(true); - MPU6050_dmp.packetSize = mpu6050.dmpGetFIFOPacketSize(); - MPU_6050_found = true; - } -#else - mpu6050.initialize(); - MPU_6050_found = mpu6050.testConnection(); -#endif - Settings.flag2.axis_resolution = 2; - } - - if (MPU_6050_found) { - I2cSetActiveFound(MPU_6050_address, D_SENSOR_MPU6050); - } -} - -#define D_YAW "Yaw" -#define D_PITCH "Pitch" -#define D_ROLL "Roll" - -#ifdef USE_WEBSERVER -const char HTTP_SNS_AXIS[] PROGMEM = - "{s}" D_SENSOR_MPU6050 " " D_AX_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_AY_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_AZ_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GX_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GY_AXIS "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_GZ_AXIS "{m}%s{e}"; -#ifdef USE_MPU6050_DMP -const char HTTP_SNS_YPR[] PROGMEM = - "{s}" D_SENSOR_MPU6050 " " D_YAW "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_PITCH "{m}%s{e}" - "{s}" D_SENSOR_MPU6050 " " D_ROLL "{m}%s{e}"; -#endif -#endif - -#define D_JSON_AXIS_AX "AccelXAxis" -#define D_JSON_AXIS_AY "AccelYAxis" -#define D_JSON_AXIS_AZ "AccelZAxis" -#define D_JSON_AXIS_GX "GyroXAxis" -#define D_JSON_AXIS_GY "GyroYAxis" -#define D_JSON_AXIS_GZ "GyroZAxis" -#define D_JSON_YAW "Yaw" -#define D_JSON_PITCH "Pitch" -#define D_JSON_ROLL "Roll" - -void MPU_6050Show(bool json) -{ - MPU_6050PerformReading(); - - double tempConv = (MPU_6050_temperature / 340.0 + 35.53); - char temperature[33]; - dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature); - char axis_ax[33]; - dtostrfd(MPU_6050_ax, Settings.flag2.axis_resolution, axis_ax); - char axis_ay[33]; - dtostrfd(MPU_6050_ay, Settings.flag2.axis_resolution, axis_ay); - char axis_az[33]; - dtostrfd(MPU_6050_az, Settings.flag2.axis_resolution, axis_az); - char axis_gx[33]; - dtostrfd(MPU_6050_gx, Settings.flag2.axis_resolution, axis_gx); - char axis_gy[33]; - dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy); - char axis_gz[33]; - dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz); -#ifdef USE_MPU6050_DMP - char axis_yaw[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[0] / PI * 180.0, Settings.flag2.axis_resolution, axis_yaw); - char axis_pitch[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[1] / PI * 180.0, Settings.flag2.axis_resolution, axis_pitch); - char axis_roll[33]; - dtostrfd(MPU6050_dmp.yawPitchRoll[2] / PI * 180.0, Settings.flag2.axis_resolution, axis_roll); -#endif - - if (json) { - char json_axis_ax[25]; - snprintf_P(json_axis_ax, sizeof(json_axis_ax), PSTR(",\"" D_JSON_AXIS_AX "\":%s"), axis_ax); - char json_axis_ay[25]; - snprintf_P(json_axis_ay, sizeof(json_axis_ay), PSTR(",\"" D_JSON_AXIS_AY "\":%s"), axis_ay); - char json_axis_az[25]; - snprintf_P(json_axis_az, sizeof(json_axis_az), PSTR(",\"" D_JSON_AXIS_AZ "\":%s"), axis_az); - char json_axis_gx[25]; - snprintf_P(json_axis_gx, sizeof(json_axis_gx), PSTR(",\"" D_JSON_AXIS_GX "\":%s"), axis_gx); - char json_axis_gy[25]; - snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); - char json_axis_gz[25]; - snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); -#ifdef USE_MPU6050_DMP - char json_ypr_y[25]; - snprintf_P(json_ypr_y, sizeof(json_ypr_y), PSTR(",\"" D_JSON_YAW "\":%s"), axis_yaw); - char json_ypr_p[25]; - snprintf_P(json_ypr_p, sizeof(json_ypr_p), PSTR(",\"" D_JSON_PITCH "\":%s"), axis_pitch); - char json_ypr_r[25]; - snprintf_P(json_ypr_r, sizeof(json_ypr_r), PSTR(",\"" D_JSON_ROLL "\":%s"), axis_roll); - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s%s%s%s}"), - D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz, - json_ypr_y, json_ypr_p, json_ypr_r); -#else - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), - D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); -#endif -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, D_SENSOR_MPU6050, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_AXIS, axis_ax, axis_ay, axis_az, axis_gx, axis_gy, axis_gz); -#ifdef USE_MPU6050_DMP - WSContentSend_PD(HTTP_SNS_YPR, axis_yaw, axis_pitch, axis_roll); -#endif -#endif - } -} - - - - - -bool Xsns32(uint8_t function) -{ - if (!I2cEnabled(XI2C_25)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MPU_6050Detect(); - } - else if (MPU_6050_found) { - switch (function) { - case FUNC_EVERY_SECOND: - if (tele_period == Settings.tele_period -3) { - MPU_6050PerformReading(); - } - break; - case FUNC_JSON_APPEND: - MPU_6050Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MPU_6050Show(0); - MPU_6050PerformReading(); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_33_ds3231.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_33_ds3231.ino" -#ifdef USE_I2C -#ifdef USE_DS3231 -# 35 "S:/Development/Tasmota/tasmota/xsns_33_ds3231.ino" -#define XSNS_33 33 -#define XI2C_26 26 - - -#ifndef USE_RTC_ADDR -#define USE_RTC_ADDR 0x68 -#endif - - -#define RTC_SECONDS 0x00 -#define RTC_MINUTES 0x01 -#define RTC_HOURS 0x02 -#define RTC_DAY 0x03 -#define RTC_DATE 0x04 -#define RTC_MONTH 0x05 -#define RTC_YEAR 0x06 -#define RTC_CONTROL 0x0E -#define RTC_STATUS 0x0F - -#define OSF 7 -#define EOSC 7 -#define BBSQW 6 -#define CONV 5 -#define RS2 4 -#define RS1 3 -#define INTCN 2 - - -#define HR1224 6 -#define CENTURY 7 -#define DYDT 6 -bool ds3231ReadStatus = false; -bool ds3231WriteStatus = false; -bool DS3231chipDetected = false; - - - - -void DS3231Detect(void) -{ - if (I2cActive(USE_RTC_ADDR)) { return; } - - if (I2cValidRead(USE_RTC_ADDR, RTC_STATUS, 1)) { - I2cSetActiveFound(USE_RTC_ADDR, "DS3231"); - DS3231chipDetected = true; - } -} - - - - -uint8_t bcd2dec(uint8_t n) -{ - return n - 6 * (n >> 4); -} - - - - -uint8_t dec2bcd(uint8_t n) -{ - return n + 6 * (n / 10); -} - - - - -uint32_t ReadFromDS3231(void) -{ - TIME_T tm; - tm.second = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_SECONDS)); - tm.minute = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MINUTES)); - tm.hour = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_HOURS) & ~_BV(HR1224)); - tm.day_of_week = I2cRead8(USE_RTC_ADDR, RTC_DAY); - tm.day_of_month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_DATE)); - tm.month = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_MONTH) & ~_BV(CENTURY)); - tm.year = bcd2dec(I2cRead8(USE_RTC_ADDR, RTC_YEAR)); - return MakeTime(tm); -} - - - -void SetDS3231Time (uint32_t epoch_time) { - TIME_T tm; - BreakTime(epoch_time, tm); - I2cWrite8(USE_RTC_ADDR, RTC_SECONDS, dec2bcd(tm.second)); - I2cWrite8(USE_RTC_ADDR, RTC_MINUTES, dec2bcd(tm.minute)); - I2cWrite8(USE_RTC_ADDR, RTC_HOURS, dec2bcd(tm.hour)); - I2cWrite8(USE_RTC_ADDR, RTC_DAY, tm.day_of_week); - I2cWrite8(USE_RTC_ADDR, RTC_DATE, dec2bcd(tm.day_of_month)); - I2cWrite8(USE_RTC_ADDR, RTC_MONTH, dec2bcd(tm.month)); - I2cWrite8(USE_RTC_ADDR, RTC_YEAR, dec2bcd(tm.year)); - I2cWrite8(USE_RTC_ADDR, RTC_STATUS, I2cRead8(USE_RTC_ADDR, RTC_STATUS) & ~_BV(OSF)); -} - -void DS3231EverySecond(void) -{ - TIME_T tmpTime; - if (!ds3231ReadStatus && Rtc.utc_time < START_VALID_TIME ) { - ntp_force_sync = true; - Rtc.utc_time = ReadFromDS3231(); - - - BreakTime(Rtc.utc_time, tmpTime); - if (Rtc.utc_time < START_VALID_TIME ) { - ds3231ReadStatus = true; - } - RtcTime.year = tmpTime.year + 1970; - Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year); - Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year); - AddLog_P2(LOG_LEVEL_INFO, PSTR("Set time from DS3231 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); - if (Rtc.local_time < START_VALID_TIME) { - rules_flag.time_init = 1; - } else { - rules_flag.time_set = 1; - } - } - else if (!ds3231WriteStatus && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - ReadFromDS3231()) > 60) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("Write Time TO DS3231 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"), - GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str()); - SetDS3231Time (Rtc.utc_time); - ds3231WriteStatus = true; - } -} - - - - - -bool Xsns33(uint8_t function) -{ - if (!I2cEnabled(XI2C_26)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - DS3231Detect(); - } - else if (DS3231chipDetected) { - switch (function) { - case FUNC_EVERY_SECOND: - DS3231EverySecond(); - break; - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_34_hx711.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_34_hx711.ino" -#ifdef USE_HX711 -# 35 "S:/Development/Tasmota/tasmota/xsns_34_hx711.ino" -#define XSNS_34 34 - -#ifndef HX_MAX_WEIGHT -#define HX_MAX_WEIGHT 20000 -#endif -#ifndef HX_REFERENCE -#define HX_REFERENCE 250 -#endif -#ifndef HX_SCALE -#define HX_SCALE 120 -#endif - -#define HX_TIMEOUT 120 -#define HX_SAMPLES 10 -#define HX_CAL_TIMEOUT 15 - -#define HX_GAIN_128 1 -#define HX_GAIN_32 2 -#define HX_GAIN_64 3 - -#define D_JSON_WEIGHT_REF "WeightRef" -#define D_JSON_WEIGHT_CAL "WeightCal" -#define D_JSON_WEIGHT_MAX "WeightMax" -#define D_JSON_WEIGHT_ITEM "WeightItem" -#define D_JSON_WEIGHT_CHANGE "WeightChange" -#define D_JSON_WEIGHT_RAW "WeightRaw" -#define D_JSON_WEIGHT_DELTA "WeightDelta" - -enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; - -const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE; - -struct HX { - long weight = 0; - long raw = 0; - long last_weight = 0; - long sum_weight = 0; - long sum_raw = 0; - long offset = 0; - long scale = 1; - long weight_diff = 0; - uint8_t type = 1; - uint8_t sample_count = 0; - uint8_t calibrate_step = HX_CAL_END; - uint8_t calibrate_timer = 0; - uint8_t calibrate_msg = 0; - uint8_t pin_sck; - uint8_t pin_dout; - bool tare_flg = false; - bool weight_changed = false; - uint16_t weight_delta = 4; -} Hx; - - - -bool HxIsReady(uint16_t timeout) -{ - - uint32_t start = millis(); - while ((digitalRead(Hx.pin_dout) == HIGH) && (millis() - start < timeout)) { yield(); } - return (digitalRead(Hx.pin_dout) == LOW); -} - -long HxRead(void) -{ - if (!HxIsReady(HX_TIMEOUT)) { return -1; } - - uint8_t data[3] = { 0 }; - uint8_t filler = 0x00; - - - data[2] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - data[1] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - data[0] = shiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); - - - for (unsigned int i = 0; i < HX_GAIN_128; i++) { - digitalWrite(Hx.pin_sck, HIGH); - digitalWrite(Hx.pin_sck, LOW); - } - - - if (data[2] & 0x80) { filler = 0xFF; } - - - unsigned long value = ( static_cast(filler) << 24 - | static_cast(data[2]) << 16 - | static_cast(data[1]) << 8 - | static_cast(data[0]) ); - - return static_cast(value); -} - - - -void HxResetPart(void) -{ - Hx.tare_flg = true; - Hx.sum_weight = 0; - Hx.sample_count = 0; - Hx.last_weight = 0; -} - -void HxReset(void) -{ - HxResetPart(); - Settings.energy_frequency_calibration = 0; -} - -void HxCalibrationStateTextJson(uint8_t msg_id) -{ - char cal_text[30]; - - Hx.calibrate_msg = msg_id; - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); - - if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } -} - -void SetWeightDelta() -{ - - if (Settings.weight_change == 0) { - Hx.weight_delta = 4; - return; - } - - - if (Settings.weight_change > 100) { - Hx.weight_delta = (Settings.weight_change - 100) * 10 + 100; - return; - } - - - Hx.weight_delta = Settings.weight_change - 1; -} -# 192 "S:/Development/Tasmota/tasmota/xsns_34_hx711.ino" -bool HxCommand(void) -{ - bool serviced = true; - bool show_parms = false; - char sub_string[XdrvMailbox.data_len +1]; - - for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) { - if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; } - } - - switch (XdrvMailbox.payload) { - case 1: - HxReset(); - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); - break; - case 2: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - Hx.scale = 1; - HxReset(); - Hx.calibrate_step = HX_CAL_START; - Hx.calibrate_timer = 1; - HxCalibrationStateTextJson(3); - break; - case 3: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - } - show_parms = true; - break; - case 4: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - Hx.scale = Settings.weight_calibration; - } - show_parms = true; - break; - case 5: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000; - } - show_parms = true; - break; - case 6: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_item = (unsigned long)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); - } - show_parms = true; - break; - case 7: - Settings.energy_frequency_calibration = Hx.weight; - Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, D_JSON_DONE); - break; - case 8: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.SensorBits1.hx711_json_weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) & 1; - } - show_parms = true; - break; - case 9: - if (strstr(XdrvMailbox.data, ",") != nullptr) { - Settings.weight_change = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); - SetWeightDelta(); - } - show_parms = true; - break; - default: - show_parms = true; - } - - if (show_parms) { - char item[33]; - dtostrfd((float)Settings.weight_item / 10, 1, item); - Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" - D_JSON_WEIGHT_ITEM "\":%s,\"" D_JSON_WEIGHT_CHANGE "\":%s,\"" D_JSON_WEIGHT_DELTA "\":%d}}"), - Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, - item, GetStateText(Settings.SensorBits1.hx711_json_weight_change), Settings.weight_change); - } - - return serviced; -} - - - -long HxWeight(void) -{ - return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; -} - -void HxInit(void) -{ - Hx.type = 0; - if ((pin[GPIO_HX711_DAT] < 99) && (pin[GPIO_HX711_SCK] < 99)) { - Hx.pin_sck = pin[GPIO_HX711_SCK]; - Hx.pin_dout = pin[GPIO_HX711_DAT]; - - pinMode(Hx.pin_sck, OUTPUT); - pinMode(Hx.pin_dout, INPUT); - - digitalWrite(Hx.pin_sck, LOW); - - SetWeightDelta(); - - if (HxIsReady(8 * HX_TIMEOUT)) { - if (!Settings.weight_max) { Settings.weight_max = HX_MAX_WEIGHT / 1000; } - if (!Settings.weight_calibration) { Settings.weight_calibration = HX_SCALE; } - if (!Settings.weight_reference) { Settings.weight_reference = HX_REFERENCE; } - Hx.scale = Settings.weight_calibration; - HxRead(); - HxResetPart(); - Hx.type = 1; - } - } -} - -void HxEvery100mSecond(void) -{ - long raw = HxRead(); - Hx.sum_raw += raw; - Hx.sum_weight += raw; - - Hx.sample_count++; - if (HX_SAMPLES == Hx.sample_count) { - long average = Hx.sum_weight / Hx.sample_count; - long raw_average = Hx.sum_raw / Hx.sample_count; - long value = average - Hx.offset; - Hx.weight = value / Hx.scale; - Hx.raw = raw_average / Hx.scale; - if (Hx.weight < 0) { - if (Settings.energy_frequency_calibration) { - long difference = Settings.energy_frequency_calibration + Hx.weight; - Hx.last_weight = difference; - if (difference < 0) { HxReset(); } - } - Hx.weight = 0; - } else { - Hx.last_weight = Settings.energy_frequency_calibration; - } - - if (Hx.tare_flg) { - Hx.tare_flg = false; - Hx.offset = average; - } - - if (Hx.calibrate_step) { - Hx.calibrate_timer--; - - if (HX_CAL_START == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); - } - else if (HX_CAL_RESET == Hx.calibrate_step) { - if (Hx.calibrate_timer) { - if (Hx.weight < (long)Settings.weight_reference) { - Hx.calibrate_step--; - Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); - HxCalibrationStateTextJson(2); - } - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - else if (HX_CAL_FIRST == Hx.calibrate_step) { - if (Hx.calibrate_timer) { - if (Hx.weight > (long)Settings.weight_reference) { - Hx.calibrate_step--; - } - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - else if (HX_CAL_DONE == Hx.calibrate_step) { - if (Hx.weight > (long)Settings.weight_reference) { - Hx.calibrate_step = HX_CAL_FINISH; - Settings.weight_calibration = Hx.weight / Settings.weight_reference; - Hx.weight = 0; - HxCalibrationStateTextJson(1); - } else { - Hx.calibrate_step = HX_CAL_FAIL; - } - } - - if (HX_CAL_FAIL == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.tare_flg = true; - HxCalibrationStateTextJson(0); - } - if (HX_CAL_FINISH == Hx.calibrate_step) { - Hx.calibrate_step--; - Hx.calibrate_timer = 3 * (10 / HX_SAMPLES); - Hx.scale = Settings.weight_calibration; - } - - if (!Hx.calibrate_timer) { - Hx.calibrate_step = HX_CAL_END; - } - } else { - Hx.weight += Hx.last_weight; - - if (Settings.SensorBits1.hx711_json_weight_change) { - if (abs(Hx.weight - Hx.weight_diff) > Hx.weight_delta) { - Hx.weight_diff = Hx.weight; - Hx.weight_changed = true; - } - else if (Hx.weight_changed && (Hx.weight == Hx.weight_diff)) { - mqtt_data[0] = '\0'; - ResponseAppendTime(); - HxShow(true); - ResponseJsonEnd(); - MqttPublishTeleSensor(); - Hx.weight_changed = false; - } - } - } - - Hx.sum_weight = 0; - Hx.sum_raw = 0; - Hx.sample_count = 0; - } -} - -void HxSaveBeforeRestart(void) -{ - Settings.energy_frequency_calibration = Hx.weight; - Hx.sample_count = HX_SAMPLES +1; -} - -#ifdef USE_WEBSERVER -const char HTTP_HX711_WEIGHT[] PROGMEM = - "{s}HX711 " D_WEIGHT "{m}%s " D_UNIT_KILOGRAM "{e}"; -const char HTTP_HX711_COUNT[] PROGMEM = - "{s}HX711 " D_COUNT "{m}%d{e}"; -const char HTTP_HX711_CAL[] PROGMEM = - "{s}HX711 %s{m}{e}"; -#endif - -void HxShow(bool json) -{ - char scount[30] = { 0 }; - - uint16_t count = 0; - float weight = 0; - if (Hx.calibrate_step < HX_CAL_FAIL) { - if (Hx.weight && Settings.weight_item) { - count = (Hx.weight * 10) / Settings.weight_item; - if (count > 1) { - snprintf_P(scount, sizeof(scount), PSTR(",\"" D_JSON_COUNT "\":%d"), count); - } - } - weight = (float)Hx.weight / 1000; - } - char weight_chr[33]; - dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); - - if (json) { - ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s, \"" D_JSON_WEIGHT_RAW "\":%d}"), weight_chr, scount, Hx.raw); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); - if (count > 1) { - WSContentSend_PD(HTTP_HX711_COUNT, count); - } - if (Hx.calibrate_step) { - char cal_text[30]; - WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); - } -#endif - } -} - -#ifdef USE_WEBSERVER -#ifdef USE_HX711_GUI - - - - -#define WEB_HANDLE_HX711 "s34" - -const char S_CONFIGURE_HX711[] PROGMEM = D_CONFIGURE_HX711; - -const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = - "

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

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

" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" - "
" - "
" - "


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

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; - -void HandleHxAction(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); - - if (WebServer->hasArg("save")) { - HxSaveSettings(); - HandleConfiguration(); - return; - } - - char stemp1[20]; - - if (WebServer->hasArg("reset")) { - snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 1")); - ExecuteWebCommand(stemp1, SRC_WEBGUI); - - HandleRoot(); - return; - } - - if (WebServer->hasArg("calibrate")) { - WebGetArg("p1", stemp1, sizeof(stemp1)); - Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); - - HxLogUpdates(); - - snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2")); - ExecuteWebCommand(stemp1, SRC_WEBGUI); - - HandleRoot(); - return; - } - - WSContentStart_P(S_CONFIGURE_HX711); - WSContentSendStyle(); - dtostrfd((float)Settings.weight_reference / 1000, 3, stemp1); - char stemp2[20]; - dtostrfd((float)Settings.weight_item / 10000, 4, stemp2); - WSContentSend_P(HTTP_FORM_HX711, stemp1, stemp2); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void HxSaveSettings(void) -{ - char tmp[100]; - - WebGetArg("p2", tmp, sizeof(tmp)); - Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToFloat(tmp) * 10000); - - HxLogUpdates(); -} - -void HxLogUpdates(void) -{ - char weigth_ref_chr[33]; - dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); - char weigth_item_chr[33]; - dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), weigth_ref_chr, weigth_item_chr); -} - -#endif -#endif - - - - - -bool Xsns34(uint8_t function) -{ - bool result = false; - - if (Hx.type) { - switch (function) { - case FUNC_EVERY_100_MSECOND: - HxEvery100mSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_34 == XdrvMailbox.index) { - result = HxCommand(); - } - break; - case FUNC_JSON_APPEND: - HxShow(1); - break; - case FUNC_SAVE_BEFORE_RESTART: - HxSaveBeforeRestart(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HxShow(0); - break; -#ifdef USE_HX711_GUI - case FUNC_WEB_ADD_MAIN_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_MAIN_HX711); - break; - case FUNC_WEB_ADD_BUTTON: - WSContentSend_P(HTTP_BTN_MENU_HX711); - break; - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); - break; -#endif -#endif - case FUNC_INIT: - HxInit(); - break; - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_35_tx20.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_35_tx20.ino" -#if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) -#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR) -#undef USE_TX20_WIND_SENSOR -#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled **** -#endif -# 41 "S:/Development/Tasmota/tasmota/xsns_35_tx20.ino" -#define XSNS_35 35 - -#define TX2X_BIT_TIME 1220 -#define TX2X_RESET_VALUES 60 - - - -extern "C" { -#include "gpio.h" -} - -#ifdef USE_TX20_WIND_SENSOR - #define D_TX2x_NAME "TX20" -#else - #define D_TX2x_NAME "TX23" -#endif - -#ifdef USE_WEBSERVER -const char HTTP_SNS_TX2X[] PROGMEM = - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s (%s°){e}"; -#endif - -const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" - D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST "|" - D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST "|" - D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; - -uint8_t tx2x_sa = 0; -uint8_t tx2x_sb = 0; -uint8_t tx2x_sd = 0; -uint8_t tx2x_se = 0; -uint16_t tx2x_sc = 0; -uint16_t tx2x_sf = 0; - -float tx2x_wind_speed_kmh = 0; -float tx2x_wind_speed_max = 0; -float tx2x_wind_speed_avg = 0; -float tx2x_wind_sum = 0; -int tx2x_count = 0; -uint8_t tx2x_wind_direction = 0; - -bool tx2x_available = false; - -#ifdef USE_TX23_WIND_SENSOR -uint8_t tx23_stage = 0; -#endif - -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -void TX2xStartRead(void) ICACHE_RAM_ATTR; -#endif - -void TX2xStartRead(void) -{ -# 135 "S:/Development/Tasmota/tasmota/xsns_35_tx20.ino" -#ifdef USE_TX23_WIND_SENSOR - if (0!=tx23_stage) - { - if ((2==tx23_stage) || (3==tx23_stage)) - { -#endif - tx2x_available = false; - - tx2x_sa = 0; - tx2x_sb = 0; - tx2x_sd = 0; - tx2x_se = 0; - tx2x_sc = 0; - tx2x_sf = 0; - - delayMicroseconds(TX2X_BIT_TIME / 2); - - for (int32_t bitcount = 41; bitcount > 0; bitcount--) { - uint8_t dpin = (digitalRead(pin[GPIO_TX2X_TXD_BLACK])); -#ifdef USE_TX23_WIND_SENSOR - if (bitcount > 41 - 5) { - - tx2x_sa = (tx2x_sa << 1) | (dpin); - } else if (bitcount > 41 - 5 - 4) { - - tx2x_sb = tx2x_sb >> 1 | ((dpin) << 3); - } else if (bitcount > 41 - 5 - 4 - 12) { - - tx2x_sc = tx2x_sc >> 1 | ((dpin) << 11); - } else if (bitcount > 41 - 5 - 4 - 12 - 4) { - - tx2x_sd = tx2x_sd >> 1 | ((dpin) << 3); - } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { - - tx2x_se = tx2x_se >> 1 | ((dpin ^ 1) << 3); - } else { - - tx2x_sf = tx2x_sf >> 1 | ((dpin ^ 1) << 11); - } -#else - if (bitcount > 41 - 5) { - - tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1); - } else if (bitcount > 41 - 5 - 4) { - - tx2x_sb = tx2x_sb >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12) { - - tx2x_sc = tx2x_sc >> 1 | ((dpin ^ 1) << 11); - } else if (bitcount > 41 - 5 - 4 - 12 - 4) { - - tx2x_sd = tx2x_sd >> 1 | ((dpin ^ 1) << 3); - } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { - - tx2x_se = tx2x_se >> 1 | (dpin << 3); - } else { - - tx2x_sf = tx2x_sf >> 1 | (dpin << 11); - } -#endif - delayMicroseconds(TX2X_BIT_TIME); - } - - uint8_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); - chk &= 0xf; - -#ifdef USE_TX23_WIND_SENSOR - - if ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { - tx2x_available = true; - } -#else - if ((chk == tx2x_sd) && (tx2x_sc < 511)) { - tx2x_available = true; - } -#endif -#ifdef USE_TX23_WIND_SENSOR - } - tx23_stage++; - } -#endif - - - - GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX2X_TXD_BLACK]); -} - -void Tx2xReset(void) -{ - tx2x_count = 0; - tx2x_wind_sum = 0; - tx2x_wind_speed_max = 0; -} - -void Tx2xRead(void) -{ -#ifdef USE_TX23_WIND_SENSOR - - - if ((uptime % 3)==0) { - - - tx23_stage = 0; - pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); - digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); - } else if ((uptime % 3)==1) { - - - tx23_stage = 1; - pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT_PULLUP); - } -#endif - if (0==Settings.tele_period && !(uptime % TX2X_RESET_VALUES)) { - Tx2xReset(); - } - else if (tx2x_available) { - - tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36; - if (tx2x_wind_speed_kmh > tx2x_wind_speed_max) { - tx2x_wind_speed_max = tx2x_wind_speed_kmh; - } - tx2x_count++; - tx2x_wind_sum += tx2x_wind_speed_kmh; - tx2x_wind_speed_avg = tx2x_wind_sum / tx2x_count; - tx2x_wind_direction = tx2x_sb; - } -} - -void Tx2xInit(void) -{ -#ifdef USE_TX23_WIND_SENSOR - tx23_stage = 0; - pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); - digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); -#else - pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT); -#endif - attachInterrupt(pin[GPIO_TX2X_TXD_BLACK], TX2xStartRead, RISING); -} - -void Tx2xShow(bool json) -{ - char wind_speed_string[33]; - dtostrfd(tx2x_wind_speed_kmh, 1, wind_speed_string); - char wind_speed_max_string[33]; - dtostrfd(tx2x_wind_speed_max, 1, wind_speed_max_string); - char wind_speed_avg_string[33]; - dtostrfd(tx2x_wind_speed_avg, 1, wind_speed_avg_string); - char wind_direction_string[4]; - GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx2x_wind_direction, kTx2xDirections); - char wind_direction_degree[33]; - dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_degree); - - if (json) { - ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), - wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); - Tx2xReset(); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TX2X, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); -#endif - } -} - - - - - -bool Xsns35(uint8_t function) -{ - bool result = false; - - if (pin[GPIO_TX2X_TXD_BLACK] < 99) { - switch (function) { - case FUNC_INIT: - Tx2xInit(); - break; - case FUNC_EVERY_SECOND: - Tx2xRead(); - break; - case FUNC_JSON_APPEND: - Tx2xShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tx2xShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_36_mgc3130.ino" -# 22 "S:/Development/Tasmota/tasmota/xsns_36_mgc3130.ino" -#ifdef USE_I2C -#ifdef USE_MGC3130 -# 35 "S:/Development/Tasmota/tasmota/xsns_36_mgc3130.ino" -#define XSNS_36 36 -#define XI2C_27 27 - -#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers **** - -#define MGC3130_I2C_ADDR 0x42 - -#define MGC3130_xfer pin[GPIO_MGC3130_XFER] -#define MGC3130_reset pin[GPIO_MGC3130_RESET] - - -bool MGC3130_type = false; -char MGC3130stype[] = "MGC3130"; - - -#define MGC3130_SYSTEM_STATUS 0x15 -#define MGC3130_REQUEST_MSG 0x06 -#define MGC3130_FW_VERSION 0x83 -#define MGC3130_SET_RUNTIME 0xA2 -#define MGC3130_SENSOR_DATA 0x91 - - -#define MGC3130_GESTURE_GARBAGE 1 -#define MGC3130_FLICK_WEST_EAST 2 -#define MGC3130_FLICK_EAST_WEST 3 -#define MGC3130_FLICK_SOUTH_NORTH 4 -#define MGC3130_FLICK_NORTH_SOUTH 5 -#define MGC3130_CIRCLE_CLOCKWISE 6 -#define MGC3130_CIRCLE_CCLOCKWISE 7 - -#define MGC3130_MIN_ROTVALUE 0 -#define MGC3130_MAX_ROTVALUE 1023 -#define MGC3130_MIN_ZVALUE 32768 - - -#ifdef USE_WEBSERVER -const char HTTP_MGC_3130_SNS[] PROGMEM = - "{s}" "%s" "{m}%s{e}" - "{s}" "HwRev" "{m}%u.%u{e}" - "{s}" "loaderVer" "{m}%u.%u{e}" - "{s}" "platVer" "{m}%u{e}"; -#endif - - - - - - - -#pragma pack(1) -union MGC3130_Union{ - uint8_t buffer[132]; - struct - { - - uint8_t msgSize; - uint8_t flag; - uint8_t counter; - uint8_t id; - - struct { - uint8_t DSPStatus:1; - uint8_t gestureInfo:1; - uint8_t touchInfo:1; - uint8_t airWheelInfo:1; - uint8_t xyzPosition:1; - uint8_t noisePower:1; - uint8_t reserved:2; - uint8_t electrodeConfiguration:3; - uint8_t CICData:1; - uint8_t SDData:1; - uint16_t reserved2:3; - } outputConfigMask; - uint8_t timestamp; - struct { - uint8_t positionValid:1; - uint8_t airWheelValid:1; - uint8_t rawDataValid:1; - uint8_t noisePowerValid:1; - uint8_t environmentalNoise:1; - uint8_t clipping:1; - uint8_t reserved:1; - uint8_t DSPRunning:1; - } systemInfo; - uint16_t dspInfo; - struct { - uint8_t gestureCode:8; - uint8_t reserved:4; - uint8_t gestureType:4; - uint8_t edgeFlick:1; - uint16_t reserved2:14; - uint8_t gestureInProgress:1; - } gestureInfo; - struct { - uint8_t touchSouth:1; - uint8_t touchWest:1; - uint8_t touchNorth:1; - uint8_t touchEast:1; - uint8_t touchCentre:1; - uint8_t tapSouth:1; - uint8_t tapWest:1; - uint8_t tapNorth:1; - uint8_t tapEast :1; - uint8_t tapCentre:1; - uint8_t doubleTapSouth:1; - uint8_t doubleTapWest:1; - uint8_t doubleTapNorth:1; - uint8_t doubleTapEast:1; - uint8_t doubleTapCentre:1; - uint8_t reserved:1; - uint8_t touchCounter; - uint8_t reserved2; - } touchInfo; - int8_t airWheel; - uint8_t reserved; - uint16_t x; - uint16_t y; - uint16_t z; - float noisePower; - float CICData[4]; - float SDData[4]; - } out; - struct { - uint8_t header[3]; - - uint8_t valid; - uint8_t hwRev[2]; - uint8_t parameterStartAddr; - uint8_t loaderVersion[2]; - uint8_t loaderPlatform; - uint8_t fwStartAddr; - char fwVersion[120]; - } fw; - struct{ - uint8_t id; - uint8_t size; - uint16_t error; - uint32_t reserved; - uint32_t reserved1; - } status; -} MGC_data; -#pragma pack() - -char MGC3130_currentGesture[12]; - -int8_t MGC3130_delta, MGC3130_lastrotation = 0; -int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0; - -uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0; - -uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0; -char MGC3130_firmwareInfo[20]; - -uint8_t MGC3130_touchTimeout = 0; -uint16_t MGC3130_touchCounter = 1; -uint32_t MGC3130_touchTimeStamp = millis(); -bool MGC3130_triggeredByTouch = false; - -uint8_t MGC3130_mode = 1; - - - -uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; -uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; -uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; - -void MGC3130_handleSensorData(){ - if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){ - if (MGC3130_handleTouch()){ - MGC3130_triggeredByTouch = true; - MqttPublishSensor(); - } - } - - if(MGC3130_mode == 1){ - if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){ - MGC3130_handleGesture(); - MqttPublishSensor(); - } - } - if(MGC3130_mode == 2){ - if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){ - MGC3130_handleAirWheel(); - MqttPublishSensor(); - } - } - if(MGC3130_mode == 3){ - if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){ - MqttPublishSensor(); - } - } -} - -void MGC3130_sendMessage(uint8_t data[], uint8_t length){ - Wire.beginTransmission(MGC3130_I2C_ADDR); - Wire.write(data,length); - Wire.endTransmission(); - delay(2); - MGC3130_receiveMessage(); -} - - -void MGC3130_handleGesture(){ - - char edge[5]; - if (MGC_data.out.gestureInfo.edgeFlick){ - snprintf_P(edge, sizeof(edge), PSTR("ED_")); - } - else{ - snprintf_P(edge, sizeof(edge), PSTR("")); - } - switch(MGC_data.out.gestureInfo.gestureCode){ - case MGC3130_GESTURE_GARBAGE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE")); - break; - case MGC3130_FLICK_WEST_EAST: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge); - break; - case MGC3130_FLICK_EAST_WEST: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge); - break; - case MGC3130_FLICK_SOUTH_NORTH: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge); - break; - case MGC3130_FLICK_NORTH_SOUTH: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge); - break; - case MGC3130_CIRCLE_CLOCKWISE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW")); - break; - case MGC3130_CIRCLE_CCLOCKWISE: - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW")); - break; - } - -} - -bool MGC3130_handleTouch(){ - - bool success = false; - if (MGC_data.out.touchInfo.doubleTapCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.doubleTapSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S")); - MGC3130_touchTimeout = 5; - success = true; - MGC3130_touchCounter = 1; - } - if (MGC_data.out.touchInfo.tapCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.tapSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S")); - MGC3130_touchTimeout = 2; - success = true; - MGC3130_touchCounter = 1; - } - else if (MGC_data.out.touchInfo.touchCentre && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchEast && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchNorth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchWest && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W")); - success = true; - MGC3130_touchCounter++; - } - else if (MGC_data.out.touchInfo.touchSouth && !success){ - - snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S")); - success = true; - MGC3130_touchCounter++; - } - - return success; -} - -void MGC3130_handleAirWheel(){ - MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation; - MGC3130_lastrotation = MGC_data.out.airWheel; - - MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta; - if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){ - MGC3130_rotValue = MGC3130_MIN_ROTVALUE; - } - if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){ - MGC3130_rotValue = MGC3130_MAX_ROTVALUE; - } -} - -void MGC3130_handleSystemStatus(){ - -} - -bool MGC3130_receiveMessage(){ - if(MGC3130_readData()){ - switch(MGC_data.out.id){ - case MGC3130_SENSOR_DATA: - MGC3130_handleSensorData(); - break; - case MGC3130_SYSTEM_STATUS: - MGC3130_handleSystemStatus(); - break; - case MGC3130_FW_VERSION: - hwRev[0] = MGC_data.fw.hwRev[1]; - hwRev[1] = MGC_data.fw.hwRev[0]; - loaderVersion[0] = MGC_data.fw.loaderVersion[0]; - loaderVersion[1] = MGC_data.fw.loaderVersion[1]; - loaderPlatform = MGC_data.fw.loaderPlatform; - snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion); - MGC3130_firmwareInfo[20] = '\0'; - - break; - } - return true; - } - return false; -} - -bool MGC3130_readData() -{ - bool success = false; - if (!digitalRead(MGC3130_xfer)){ - pinMode(MGC3130_xfer, OUTPUT); - digitalWrite(MGC3130_xfer, LOW); - Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); - - MGC_data.buffer[0] = 4; - unsigned char i = 0; - while(Wire.available() && (i < MGC_data.buffer[0])){ - MGC_data.buffer[i] = Wire.read(); - i++; - } - digitalWrite(MGC3130_xfer, HIGH); - pinMode(MGC3130_xfer, INPUT); - success = true; - } - return success; -} - -void MGC3130_nextMode(){ - if (MGC3130_mode < 3){ - MGC3130_mode++; - } - else{ - MGC3130_mode = 1; - } - switch(MGC3130_mode){ - case 1: - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - case 2: - MGC3130_sendMessage(MGC3130enableAirwheel,16); - break; - case 3: - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - } -} - -void MGC3130_loop() -{ - if(MGC3130_touchTimeout > 0){ - MGC3130_touchTimeout--; - } - MGC3130_receiveMessage(); -} - -void MGC3130_detect(void) -{ - if (MGC3130_type || I2cActive(MGC3130_I2C_ADDR)) { return; } - - pinMode(MGC3130_xfer, INPUT_PULLUP); - pinMode(MGC3130_reset, OUTPUT); - digitalWrite(MGC3130_reset, LOW); - delay(10); - digitalWrite(MGC3130_reset, HIGH); - delay(50); - - if (MGC3130_receiveMessage()) { - I2cSetActiveFound(MGC3130_I2C_ADDR, MGC3130stype); - MGC3130_currentGesture[0] = '\0'; - MGC3130_type = true; - } -} - - - - - -void MGC3130_show(bool json) -{ - if (!MGC3130_type) { return; } - - char status_chr[2]; - if (MGC_data.out.systemInfo.DSPRunning) { - sprintf (status_chr, "1"); - } - else{ - sprintf (status_chr, "0"); - } - - if (json) { - if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { - if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { - ResponseAppend_P(PSTR(",\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), - MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); - MGC3130_lastSentX = MGC_data.out.x; - MGC3130_lastSentY = MGC_data.out.y; - MGC3130_lastSentZ = MGC_data.out.z; - } - } - MGC3130_triggeredByTouch = false; - - if (MGC3130_mode == 2) { - if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { - ResponseAppend_P(PSTR(",\"%s\":{\"AW\":%i}"), MGC3130stype, MGC3130_rotValue); - MGC3130_lastSentRotValue = MGC3130_rotValue; - } - } - - if (MGC3130_currentGesture[0] != '\0') { - if (millis() - MGC3130_touchTimeStamp > 220 ) { - MGC3130_touchCounter = 1; - } - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); - MGC3130_currentGesture[0] = '\0'; - MGC3130_touchTimeStamp = millis(); - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform ); -#endif - } -} -# 557 "S:/Development/Tasmota/tasmota/xsns_36_mgc3130.ino" -bool MGC3130CommandSensor() -{ - bool serviced = true; - - switch (XdrvMailbox.payload) { - case 0: - MGC3130_nextMode(); - break; - case 1: - MGC3130_mode = 1; - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - case 2: - MGC3130_mode = 2; - MGC3130_sendMessage(MGC3130enableAirwheel,16); - break; - case 3: - MGC3130_mode = 3; - MGC3130_sendMessage(MGC3130disableAirwheel,16); - break; - } - return serviced; -} - - - - - -bool Xsns36(uint8_t function) -{ - if (!I2cEnabled(XI2C_27)) { return false; } - - bool result = false; - - if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) { - MGC3130_detect(); - } - else if (MGC3130_type) { - switch (function) { - case FUNC_EVERY_50_MSECOND: - MGC3130_loop(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_36 == XdrvMailbox.index) { - result = MGC3130CommandSensor(); - } - break; - case FUNC_JSON_APPEND: - MGC3130_show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MGC3130_show(0); - break; -#endif - } - } - return result; -} -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" -#ifdef USE_RF_SENSOR -# 33 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" -#define XSNS_37 37 - - - - -#define RFSNS_VALID_WINDOW 1800 - -#define RFSNS_LOOPS_PER_MILLI 1900 -#define RFSNS_RAW_BUFFER_SIZE 180 -#define RFSNS_MIN_RAW_PULSES 112 - -#define RFSNS_MIN_PULSE_LENGTH 300 -#define RFSNS_RAWSIGNAL_SAMPLE 50 -#define RFSNS_SIGNAL_TIMEOUT 10 -#define RFSNS_SIGNAL_REPEAT_TIME 500 - -typedef struct RawSignalStruct -{ - int Number; - uint8_t Repeats; - uint8_t Multiply; - unsigned long Time; - uint8_t Pulses[RFSNS_RAW_BUFFER_SIZE+2]; - -} raw_signal_t; - -raw_signal_t *rfsns_raw_signal = nullptr; -uint8_t rfsns_rf_bit; -uint8_t rfsns_rf_port; -uint8_t rfsns_any_sensor = 0; - - - - - -bool RfSnsFetchSignal(uint8_t DataPin, bool StateSignal) -{ - uint8_t Fbit = digitalPinToBitMask(DataPin); - uint8_t Fport = digitalPinToPort(DataPin); - uint8_t FstateMask = (StateSignal ? Fbit : 0); - - if ((*portInputRegister(Fport) & Fbit) == FstateMask) { - const unsigned long LoopsPerMilli = RFSNS_LOOPS_PER_MILLI; - - - - - - - unsigned long PulseLength = 0; - if (rfsns_raw_signal->Time) { - if (rfsns_raw_signal->Repeats && (rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) { - PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; - while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && (PulseLength > micros())) { - if ((*portInputRegister(Fport) & Fbit) == FstateMask) { - PulseLength = micros() + RFSNS_SIGNAL_TIMEOUT *1000; - } - } - while (((rfsns_raw_signal->Time + RFSNS_SIGNAL_REPEAT_TIME) > millis()) && ((*portInputRegister(Fport) & Fbit) != FstateMask)); - } - } - - int RawCodeLength = 1; - bool Ftoggle = false; - unsigned long numloops = 0; - unsigned long maxloops = RFSNS_SIGNAL_TIMEOUT * LoopsPerMilli; - rfsns_raw_signal->Multiply = RFSNS_RAWSIGNAL_SAMPLE; - do { - numloops = 0; - while(((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) { - if (numloops++ == maxloops) { break; } - } - PulseLength = (numloops *1000) / LoopsPerMilli; - if (PulseLength < RFSNS_MIN_PULSE_LENGTH) { break; } - Ftoggle = !Ftoggle; - rfsns_raw_signal->Pulses[RawCodeLength++] = PulseLength / (unsigned long)rfsns_raw_signal->Multiply; - } - while(RawCodeLength < RFSNS_RAW_BUFFER_SIZE && numloops <= maxloops); - - if ((RawCodeLength >= RFSNS_MIN_RAW_PULSES) && (RawCodeLength < RFSNS_RAW_BUFFER_SIZE -1)) { - rfsns_raw_signal->Repeats = 0; - rfsns_raw_signal->Number = RawCodeLength -1; - rfsns_raw_signal->Pulses[rfsns_raw_signal->Number] = 0; - rfsns_raw_signal->Time = millis(); - return true; - } - else - rfsns_raw_signal->Number = 0; - } - - return false; -} - -#ifdef USE_THEO_V2 -# 149 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" -#define RFSNS_THEOV2_MAX_CHANNEL 2 - -#define RFSNS_THEOV2_PULSECOUNT 114 -#define RFSNS_THEOV2_RF_PULSE_MID 1000 - -typedef struct { - uint32_t time; - int16_t temp; - uint16_t lux; - uint8_t volt; -} theo_v2_t1_t; - -typedef struct { - uint32_t time; - int16_t temp; - uint16_t hum; - uint8_t volt; -} theo_v2_t2_t; - -theo_v2_t1_t *rfsns_theo_v2_t1 = nullptr; -theo_v2_t2_t *rfsns_theo_v2_t2 = nullptr; - -void RfSnsInitTheoV2(void) -{ - rfsns_theo_v2_t1 = (theo_v2_t1_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t1_t)); - rfsns_theo_v2_t2 = (theo_v2_t2_t*)malloc(RFSNS_THEOV2_MAX_CHANNEL * sizeof(theo_v2_t2_t)); - rfsns_any_sensor++; -} - -void RfSnsAnalyzeTheov2(void) -{ - if (rfsns_raw_signal->Number != RFSNS_THEOV2_PULSECOUNT) { return; } - - uint8_t Checksum; - uint8_t Channel; - uint8_t Type; - uint8_t Voltage; - int Payload1; - int Payload2; - - uint8_t b, bytes, bits, id; - - uint8_t idx = 3; - uint8_t chksum = 0; - for (bytes = 0; bytes < 7; bytes++) { - b = 0; - for (bits = 0; bits <= 7; bits++) - { - if ((rfsns_raw_signal->Pulses[idx] * rfsns_raw_signal->Multiply) > RFSNS_THEOV2_RF_PULSE_MID) { - b |= 1 << bits; - } - idx += 2; - } - if (bytes > 0) { chksum += b; } - - switch (bytes) { - case 0: - Checksum = b; - break; - case 1: - id = b; - Channel = b & 0x7; - Type = (b >> 3) & 0x1f; - break; - case 2: - Voltage = b; - break; - case 3: - Payload1 = b; - break; - case 4: - Payload1 = (b << 8) | Payload1; - break; - case 5: - Payload2 = b; - break; - case 6: - Payload2 = (b << 8) | Payload2; - break; - } - } - - if (Checksum != chksum) { return; } - if ((Channel == 0) || (Channel > RFSNS_THEOV2_MAX_CHANNEL)) { return; } - Channel--; - - rfsns_raw_signal->Repeats = 1; - - int Payload3 = Voltage & 0x3f; - - switch (Type) { - case 1: - rfsns_theo_v2_t1[Channel].time = LocalTime(); - rfsns_theo_v2_t1[Channel].volt = Payload3; - rfsns_theo_v2_t1[Channel].temp = Payload1; - rfsns_theo_v2_t1[Channel].lux = Payload2; - break; - case 2: - rfsns_theo_v2_t2[Channel].time = LocalTime(); - rfsns_theo_v2_t2[Channel].volt = Payload3; - rfsns_theo_v2_t2[Channel].temp = Payload1; - rfsns_theo_v2_t2[Channel].hum = Payload2; - break; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: TheoV2, ChkCalc %d, Chksum %d, id %d, Type %d, Ch %d, Volt %d, BattLo %d, Pld1 %d, Pld2 %d"), - chksum, Checksum, id, Type, Channel +1, Payload3, (Voltage & 0x80) >> 7, Payload1, Payload2); -} - -void RfSnsTheoV2Show(bool json) -{ - bool sensor_once = false; - - for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { - if (rfsns_theo_v2_t1[i].time) { - char sensor[10]; - snprintf_P(sensor, sizeof(sensor), PSTR("TV2T1C%d"), i +1); - char voltage[33]; - dtostrfd((float)rfsns_theo_v2_t1[i].volt / 10, 1, voltage); - - if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); - } - } else { - char temperature[33]; - dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), - sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); -#ifdef USE_DOMOTICZ - if ((0 == tele_period) && !sensor_once) { - DomoticzSensor(DZ_TEMP, temperature); - DomoticzSensor(DZ_ILLUMINANCE, rfsns_theo_v2_t1[i].lux); - sensor_once = true; - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, sensor, rfsns_theo_v2_t1[i].lux); -#endif - } - } - } - } - - sensor_once = false; - for (uint32_t i = 0; i < RFSNS_THEOV2_MAX_CHANNEL; i++) { - if (rfsns_theo_v2_t2[i].time) { - char sensor[10]; - snprintf_P(sensor, sizeof(sensor), PSTR("TV2T2C%d"), i +1); - char voltage[33]; - dtostrfd((float)rfsns_theo_v2_t2[i].volt / 10, 1, voltage); - - if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); - } - } else { - float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); - float humi = ConvertHumidity((float)rfsns_theo_v2_t2[i].hum / 100); - char temperature[33]; - dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), - sensor, temperature, humidity, voltage); - if ((0 == tele_period) && !sensor_once) { -#ifdef USE_DOMOTICZ - DomoticzTempHumSensor(temperature, humidity); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, temp); - KnxSensor(KNX_HUMIDITY, humi); -#endif - sensor_once = true; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, sensor, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, sensor, humidity); -#endif - } - } - } - } -} - -#endif - -#ifdef USE_ALECTO_V2 -# 392 "S:/Development/Tasmota/tasmota/xsns_37_rfsensor.ino" -#define RFSNS_DKW2012_PULSECOUNT 176 -#define RFSNS_ACH2010_MIN_PULSECOUNT 160 -#define RFSNS_ACH2010_MAX_PULSECOUNT 160 - -#define D_ALECTOV2 "AlectoV2" - -const char kAlectoV2Directions[] PROGMEM = D_TX20_NORTH "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" - D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" - D_TX20_EAST "|" - D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" - D_TX20_SOUTH "|" - D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" - D_TX20_WEST "|" - D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_WEST "|" - D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; - -typedef struct { - uint32_t time; - float temp; - float rain; - float wind; - float gust; - uint8_t type; - uint8_t humi; - uint8_t wdir; -} alecto_v2_t; - -alecto_v2_t *rfsns_alecto_v2 = nullptr; -uint16_t rfsns_alecto_rain_base = 0; - -void RfSnsInitAlectoV2(void) -{ - rfsns_alecto_v2 = (alecto_v2_t*)malloc(sizeof(alecto_v2_t)); - rfsns_any_sensor++; -} - -void RfSnsAnalyzeAlectov2() -{ - if (!(((rfsns_raw_signal->Number >= RFSNS_ACH2010_MIN_PULSECOUNT) && - (rfsns_raw_signal->Number <= RFSNS_ACH2010_MAX_PULSECOUNT)) || (rfsns_raw_signal->Number == RFSNS_DKW2012_PULSECOUNT))) { return; } - - uint8_t c = 0; - uint8_t rfbit; - uint8_t data[9] = { 0 }; - uint8_t msgtype = 0; - uint8_t rc = 0; - int temp; - uint8_t checksum = 0; - uint8_t checksumcalc = 0; - uint8_t maxidx = 8; - unsigned long atime; - float factor; - char buf1[16]; - - if (rfsns_raw_signal->Number > RFSNS_ACH2010_MAX_PULSECOUNT) { maxidx = 9; } - - uint8_t idx = maxidx; - for (uint32_t x = rfsns_raw_signal->Number; x > 0; x = x-2) { - if (rfsns_raw_signal->Pulses[x-1] * rfsns_raw_signal->Multiply < 0x300) { - rfbit = 0x80; - } else { - rfbit = 0; - } - data[idx] = (data[idx] >> 1) | rfbit; - c++; - if (c == 8) { - if (idx == 0) { break; } - c = 0; - idx--; - } - } - - checksum = data[maxidx]; - checksumcalc = RfSnsAlectoCRC8(data, maxidx); - - msgtype = (data[0] >> 4) & 0xf; - rc = (data[0] << 4) | (data[1] >> 4); - - if (checksum != checksumcalc) { return; } - if ((msgtype != 10) && (msgtype != 5)) { return; } - - rfsns_raw_signal->Repeats = 1; - - - - - - factor = 1.22; - - - - - - rfsns_alecto_v2->time = LocalTime(); - rfsns_alecto_v2->type = (RFSNS_DKW2012_PULSECOUNT == rfsns_raw_signal->Number); - rfsns_alecto_v2->temp = (float)(((data[1] & 0x3) * 256 + data[2]) - 400) / 10; - rfsns_alecto_v2->humi = data[3]; - uint16_t rain = (data[6] * 256) + data[7]; - - if (rain < rfsns_alecto_rain_base) { rfsns_alecto_rain_base = rain; } - if (rfsns_alecto_rain_base > 0) { - rfsns_alecto_v2->rain += ((float)rain - rfsns_alecto_rain_base) * 0.30; - } - rfsns_alecto_rain_base = rain; - rfsns_alecto_v2->wind = (float)data[4] * factor; - rfsns_alecto_v2->gust = (float)data[5] * factor; - if (rfsns_alecto_v2->type) { - rfsns_alecto_v2->wdir = data[8] & 0xf; - } - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: " D_ALECTOV2 ", ChkCalc %d, Chksum %d, rc %d, Temp %d, Hum %d, Rain %d, Wind %d, Gust %d, Dir %d, Factor %s"), - checksumcalc, checksum, rc, ((data[1] & 0x3) * 256 + data[2]) - 400, data[3], (data[6] * 256) + data[7], data[4], data[5], data[8] & 0xf, dtostrfd(factor, 3, buf1)); -} - -void RfSnsAlectoResetRain(void) -{ - if ((RtcTime.hour == 0) && (RtcTime.minute == 0) && (RtcTime.second == 5)) { - rfsns_alecto_v2->rain = 0; - } -} - - - - - - - -uint8_t RfSnsAlectoCRC8(uint8_t *addr, uint8_t len) -{ - uint8_t crc = 0; - while (len--) { - uint8_t inbyte = *addr++; - for (uint32_t i = 8; i; i--) { - uint8_t mix = (crc ^ inbyte) & 0x80; - crc <<= 1; - if (mix) { crc ^= 0x31; } - inbyte <<= 1; - } - } - return crc; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_ALECTOV2[] PROGMEM = - "{s}" D_ALECTOV2 " " D_RAIN "{m}%s " D_UNIT_MILLIMETER "{e}" - "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_ALECTOV2 " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}"; -const char HTTP_SNS_ALECTOV2_WDIR[] PROGMEM = - "{s}" D_ALECTOV2 " " D_TX20_WIND_DIRECTION "{m}%s{e}"; -#endif - -void RfSnsAlectoV2Show(bool json) -{ - if (rfsns_alecto_v2->time) { - if (rfsns_alecto_v2->time < LocalTime() - RFSNS_VALID_WINDOW) { - if (json) { - ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), GetDT(rfsns_alecto_v2->time).c_str()); - } - } else { - float temp = ConvertTemp(rfsns_alecto_v2->temp); - char temperature[33]; - dtostrfd(temp, Settings.flag2.temperature_resolution, temperature); - float humi = ConvertHumidity((float)rfsns_alecto_v2->humi); - char humidity[33]; - dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); - char rain[33]; - dtostrfd(rfsns_alecto_v2->rain, 2, rain); - char wind[33]; - dtostrfd(rfsns_alecto_v2->wind, 2, wind); - char gust[33]; - dtostrfd(rfsns_alecto_v2->gust, 2, gust); - char wdir[4]; - char direction[20]; - if (rfsns_alecto_v2->type) { - GetTextIndexed(wdir, sizeof(wdir), rfsns_alecto_v2->wdir, kAlectoV2Directions); - snprintf_P(direction, sizeof(direction), PSTR(",\"Direction\":\"%s\""), wdir); - } - - if (json) { - ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), - temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); - if (0 == tele_period) { -#ifdef USE_DOMOTICZ - - - - -#endif - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, D_ALECTOV2, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, D_ALECTOV2, humidity); - WSContentSend_PD(HTTP_SNS_ALECTOV2, rain, wind, gust); - if (rfsns_alecto_v2->type) { - WSContentSend_PD(HTTP_SNS_ALECTOV2_WDIR, wdir); - } -#endif - } - } - } -} -#endif - -void RfSnsInit(void) -{ - rfsns_raw_signal = (raw_signal_t*)(malloc(sizeof(raw_signal_t))); - if (rfsns_raw_signal) { - memset(rfsns_raw_signal, 0, sizeof(raw_signal_t)); -#ifdef USE_THEO_V2 - RfSnsInitTheoV2(); -#endif -#ifdef USE_ALECTO_V2 - RfSnsInitAlectoV2(); -#endif - if (rfsns_any_sensor) { - rfsns_rf_bit = digitalPinToBitMask(pin[GPIO_RF_SENSOR]); - rfsns_rf_port = digitalPinToPort(pin[GPIO_RF_SENSOR]); - pinMode(pin[GPIO_RF_SENSOR], INPUT); - } else { - free(rfsns_raw_signal); - rfsns_raw_signal = nullptr; - } - } -} - -void RfSnsAnalyzeRawSignal(void) -{ - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RFS: Pulses %d"), (int)rfsns_raw_signal->Number); - -#ifdef USE_THEO_V2 - RfSnsAnalyzeTheov2(); -#endif -#ifdef USE_ALECTO_V2 - RfSnsAnalyzeAlectov2(); -#endif -} - -void RfSnsEverySecond(void) -{ -#ifdef USE_ALECTO_V2 - RfSnsAlectoResetRain(); -#endif -} - -void RfSnsShow(bool json) -{ -#ifdef USE_THEO_V2 - RfSnsTheoV2Show(json); -#endif -#ifdef USE_ALECTO_V2 - RfSnsAlectoV2Show(json); -#endif -} - - - - - -bool Xsns37(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_RF_SENSOR] < 99) && (FUNC_INIT == function)) { - RfSnsInit(); - } - else if (rfsns_raw_signal) { - switch (function) { - case FUNC_LOOP: - if ((*portInputRegister(rfsns_rf_port) &rfsns_rf_bit) == rfsns_rf_bit) { - if (RfSnsFetchSignal(pin[GPIO_RF_SENSOR], HIGH)) { - RfSnsAnalyzeRawSignal(); - } - } - sleep = 0; - break; - case FUNC_EVERY_SECOND: - RfSnsEverySecond(); - break; - case FUNC_JSON_APPEND: - RfSnsShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - RfSnsShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_38_az7798.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_38_az7798.ino" -#ifdef USE_AZ7798 - -#define XSNS_38 38 -# 112 "S:/Development/Tasmota/tasmota/xsns_38_az7798.ino" -#include - -#ifndef CO2_LOW -#define CO2_LOW 800 -#endif -#ifndef CO2_HIGH -#define CO2_HIGH 1200 -#endif - -#define AZ_READ_TIMEOUT 400 - -#define AZ_CLOCK_UPDATE_INTERVAL (24UL * 60 * 60) -#define AZ_EPOCH (946684800UL) - -TasmotaSerial *AzSerial; - -const char ktype[] = "AZ7798"; -uint8_t az_type = 1; -uint16_t az_co2 = 0; -double az_temperature = 0; -double az_humidity = 0; -uint8_t az_received = 0; -uint8_t az_state = 0; -unsigned long az_clock_update = 10; - - - -void AzEverySecond(void) -{ - unsigned long start = millis(); - - az_state++; - if (5 == az_state) { - az_state = 0; - - AzSerial->flush(); - AzSerial->write(":\r", 2); - az_received = 0; - - uint8_t az_response[32]; - uint8_t counter = 0; - uint8_t i, j; - uint8_t response_substr[16]; - - do { - if (AzSerial->available() > 0) { - az_response[counter] = AzSerial->read(); - if(az_response[counter] == 0x0d) { az_received = 1; } - counter++; - } else { - delay(5); - } - } while(((millis() - start) < AZ_READ_TIMEOUT) && (counter < sizeof(az_response)) && !az_received); - - AddLogBuffer(LOG_LEVEL_DEBUG_MORE, az_response, counter); - - if (!az_received) { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 comms timeout")); - return; - } - - i = 0; - while((az_response[i] != 'T') && (i < counter)) {i++;} - if(az_response[i] != 'T') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find start of response")); - return; - } - i++; - j = 0; - - while((az_response[i] != 'C') && (az_response[i] != 'F') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if((az_response[i] != 'C') && (az_response[i] != 'F')){ - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of temperature")); - return; - } - response_substr[j] = 0; - az_temperature = CharToFloat((char*)response_substr); - if(az_response[i] == 'C') { - az_temperature = ConvertTemp((float)az_temperature); - } else { - az_temperature = ConvertTemp((az_temperature - 32) / 1.8); - } - i++; - if(az_response[i] != ':') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error first delimiter")); - return; - } - i++; - if(az_response[i] != 'C') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of CO2")); - return; - } - i++; - j = 0; - - while((az_response[i] != 'p') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if(az_response[i] != 'p') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of CO2")); - return; - } - response_substr[j] = 0; - az_co2 = atoi((char*)response_substr); - LightSetSignal(CO2_LOW, CO2_HIGH, az_co2); - i += 3; - if(az_response[i] != ':') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error second delimiter")); - return; - } - i++; - if(az_response[i] != 'H') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 error start of humidity")); - return; - } - i++; - j = 0; - - while((az_response[i] != '%') && (i < counter)) { - response_substr[j++] = az_response[i++]; - } - if(az_response[i] != '%') { - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 failed to find end of humidity")); - return; - } - response_substr[j] = 0; - az_humidity = ConvertHumidity(CharToFloat((char*)response_substr)); - } - - - if ((az_clock_update == 0) && (LocalTime() > AZ_EPOCH)) { - char tmpString[16]; - sprintf(tmpString, "C %d\r", (int)(LocalTime() - AZ_EPOCH)); - AzSerial->write(tmpString); - - do { - if (AzSerial->available() > 0) { - if(AzSerial->read() == 0x0d) { break; } - } else { - delay(5); - } - } while(((millis() - start) < AZ_READ_TIMEOUT)); - az_clock_update = AZ_CLOCK_UPDATE_INTERVAL; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "AZ7798 clock updated")); - } else { - az_clock_update--; - } -} - - - -void AzInit(void) -{ - az_type = 0; - if ((pin[GPIO_AZ_RXD] < 99) && (pin[GPIO_AZ_TXD] < 99)) { - AzSerial = new TasmotaSerial(pin[GPIO_AZ_RXD], pin[GPIO_AZ_TXD], 1); - if (AzSerial->begin(9600)) { - if (AzSerial->hardwareSerial()) { ClaimSerial(); } - az_type = 1; - } - } -} - -void AzShow(bool json) -{ - char temperature[33]; - dtostrfd(az_temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), ktype, az_co2, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2, ktype, az_co2); - WSContentSend_PD(HTTP_SNS_TEMP, ktype, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, ktype, humidity); -#endif - } -} - - - - - -bool Xsns38(uint8_t function) -{ - bool result = false; - - if(az_type){ - switch (function) { - case FUNC_INIT: - AzInit(); - break; - case FUNC_EVERY_SECOND: - AzEverySecond(); - break; - case FUNC_JSON_APPEND: - AzShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AzShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_39_max31855.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_39_max31855.ino" -#ifdef USE_MAX31855 - -#define XSNS_39 39 - -bool initialized = false; - -struct MAX31855_ResultStruct{ - uint8_t ErrorCode; - float ProbeTemperature; - float ReferenceTemperature; -} MAX31855_Result; - -void MAX31855_Init(void){ - if(initialized) - return; - - - pinMode(pin[GPIO_MAX31855CS], OUTPUT); - pinMode(pin[GPIO_MAX31855CLK], OUTPUT); - pinMode(pin[GPIO_MAX31855DO], INPUT); - - - digitalWrite(pin[GPIO_MAX31855CS], HIGH); - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - - initialized = true; -} - - - - - -void MAX31855_GetResult(void){ - int32_t RawData = MAX31855_ShiftIn(32); - uint8_t probeerror = RawData & 0x7; - - MAX31855_Result.ErrorCode = probeerror; - MAX31855_Result.ReferenceTemperature = MAX31855_GetReferenceTemperature(RawData); - if(probeerror) - MAX31855_Result.ProbeTemperature = NAN; - else - MAX31855_Result.ProbeTemperature = MAX31855_GetProbeTemperature(RawData); -} - - - - - - -float MAX31855_GetProbeTemperature(int32_t RawData){ - if(RawData & 0x80000000) - RawData = (RawData >> 18) | 0xFFFFC000; - else - RawData >>= 18; - - float result = (RawData * 0.25); - - return ConvertTemp(result); -} - - - - - -float MAX31855_GetReferenceTemperature(int32_t RawData){ - if(RawData & 0x8000) - RawData = (RawData >> 4) | 0xFFFFF000; - else - RawData = (RawData >> 4) & 0x00000FFF; - - float result = (RawData * 0.0625); - - return ConvertTemp(result); -} - - - - - -int32_t MAX31855_ShiftIn(uint8_t Length){ - int32_t dataIn = 0; - - digitalWrite(pin[GPIO_MAX31855CS], LOW); - delayMicroseconds(1); - - for (uint32_t i = 0; i < Length; i++) - { - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - delayMicroseconds(1); - dataIn <<= 1; - if(digitalRead(pin[GPIO_MAX31855DO])) - dataIn |= 1; - digitalWrite(pin[GPIO_MAX31855CLK], HIGH); - delayMicroseconds(1); - } - - digitalWrite(pin[GPIO_MAX31855CS], HIGH); - digitalWrite(pin[GPIO_MAX31855CLK], LOW); - return dataIn; -} - -void MAX31855_Show(bool Json){ - char probetemp[33]; - char referencetemp[33]; - dtostrfd(MAX31855_Result.ProbeTemperature, Settings.flag2.temperature_resolution, probetemp); - dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); - - if(Json){ - ResponseAppend_P(PSTR(",\"MAX31855\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - probetemp, referencetemp, MAX31855_Result.ErrorCode); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, probetemp); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, MAX31855_Result.ProbeTemperature); - } -#endif - } else { -#ifdef USE_WEBSERVER - WSContentSend_PD(HTTP_SNS_TEMP, "MAX31855", probetemp, TempUnit()); -#endif - } -} - - - - - -bool Xsns39(uint8_t function) -{ - bool result = false; - if((pin[GPIO_MAX31855CS] < 99) && (pin[GPIO_MAX31855CLK] < 99) && (pin[GPIO_MAX31855DO] < 99)){ - - switch (function) { - case FUNC_INIT: - MAX31855_Init(); - break; - case FUNC_EVERY_SECOND: - MAX31855_GetResult(); - break; - case FUNC_JSON_APPEND: - MAX31855_Show(true); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MAX31855_Show(false); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_40_pn532.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_40_pn532.ino" -#ifdef USE_PN532_HSU - -#define XSNS_40 40 - -#include - -TasmotaSerial *PN532_Serial; - -#define PN532_INVALID_ACK -1 -#define PN532_TIMEOUT -2 -#define PN532_INVALID_FRAME -3 -#define PN532_NO_SPACE -4 - -#define PN532_PREAMBLE 0x00 -#define PN532_STARTCODE1 0x00 -#define PN532_STARTCODE2 0xFF -#define PN532_POSTAMBLE 0x00 - -#define PN532_HOSTTOPN532 0xD4 -#define PN532_PN532TOHOST 0xD5 - -#define PN532_ACK_WAIT_TIME 0x0A - -#define PN532_COMMAND_GETFIRMWAREVERSION 0x02 -#define PN532_COMMAND_SAMCONFIGURATION 0x14 -#define PN532_COMMAND_RFCONFIGURATION 0x32 -#define PN532_COMMAND_INDATAEXCHANGE 0x40 -#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A - -#define PN532_MIFARE_ISO14443A 0x00 -#define MIFARE_CMD_READ 0x30 -#define MIFARE_CMD_AUTH_A 0x60 -#define MIFARE_CMD_AUTH_B 0x61 -#define MIFARE_CMD_WRITE 0xA0 - -uint8_t pn532_model = 0; -uint8_t pn532_command = 0; -uint8_t pn532_scantimer = 0; - -uint8_t pn532_packetbuffer[64]; - -#ifdef USE_PN532_DATA_FUNCTION -uint8_t pn532_function = 0; -uint8_t pn532_newdata[16]; -uint8_t pn532_newdata_len = 0; -#endif - -void PN532_Init(void) -{ - if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) { - PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1); - if (PN532_Serial->begin(115200)) { - if (PN532_Serial->hardwareSerial()) { ClaimSerial(); } - PN532_wakeup(); - uint32_t ver = PN532_getFirmwareVersion(); - if (ver) { - PN532_setPassiveActivationRetries(0xFF); - PN532_SAMConfig(); - pn532_model = 1; - AddLog_P2(LOG_LEVEL_INFO,"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF); - } - } - } -} - -int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout) -{ - int read_bytes = 0; - int ret; - unsigned long start_millis; - while (read_bytes < len) { - start_millis = millis(); - do { - ret = PN532_Serial->read(); - if (ret >= 0) { - break; - } - } while((timeout == 0) || ((millis()- start_millis ) < timeout)); - - if (ret < 0) { - if (read_bytes) { - return read_bytes; - } else { - return PN532_TIMEOUT; - } - } - buf[read_bytes] = (uint8_t)ret; - read_bytes++; - } - return read_bytes; -} - -int8_t PN532_readAckFrame(void) -{ - const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0}; - uint8_t ackBuf[sizeof(PN532_ACK)]; - - if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) { - return PN532_TIMEOUT; - } - - if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) { - return PN532_INVALID_ACK; - } - return 0; -} - -int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0) -{ - - PN532_Serial->flush(); - - pn532_command = header[0]; - PN532_Serial->write((uint8_t)PN532_PREAMBLE); - PN532_Serial->write((uint8_t)PN532_STARTCODE1); - PN532_Serial->write(PN532_STARTCODE2); - - uint8_t length = hlen + blen + 1; - PN532_Serial->write(length); - PN532_Serial->write(~length + 1); - - PN532_Serial->write(PN532_HOSTTOPN532); - uint8_t sum = PN532_HOSTTOPN532; - - PN532_Serial->write(header, hlen); - for (uint32_t i = 0; i < hlen; i++) { - sum += header[i]; - } - - PN532_Serial->write(body, blen); - for (uint32_t i = 0; i < blen; i++) { - sum += body[i]; - } - - uint8_t checksum = ~sum + 1; - PN532_Serial->write(checksum); - PN532_Serial->write((uint8_t)PN532_POSTAMBLE); - - return PN532_readAckFrame(); -} - -int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50) -{ - uint8_t tmp[3]; - - - if (PN532_receive(tmp, 3, timeout)<=0) { - return PN532_TIMEOUT; - } - if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) { - return PN532_INVALID_FRAME; - } - - - uint8_t length[2]; - if (PN532_receive(length, 2, timeout) <= 0) { - return PN532_TIMEOUT; - } - - if (0 != (uint8_t)(length[0] + length[1])) { - return PN532_INVALID_FRAME; - } - length[0] -= 2; - if (length[0] > len) { - return PN532_NO_SPACE; - } - - - uint8_t cmd = pn532_command + 1; - if (PN532_receive(tmp, 2, timeout) <= 0) { - return PN532_TIMEOUT; - } - if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { - return PN532_INVALID_FRAME; - } - - if (PN532_receive(buf, length[0], timeout) != length[0]) { - return PN532_TIMEOUT; - } - - uint8_t sum = PN532_PN532TOHOST + cmd; - for (uint32_t i=0; i status) { - return 0; - } - - response = pn532_packetbuffer[0]; - response <<= 8; - response |= pn532_packetbuffer[1]; - response <<= 8; - response |= pn532_packetbuffer[2]; - response <<= 8; - response |= pn532_packetbuffer[3]; - - return response; -} - -void PN532_wakeup(void) -{ - uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 }; - PN532_Serial->write(wakeup,sizeof(wakeup)); - - - PN532_Serial->flush(); -} - -bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50) -{ - pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = cardbaudrate; - if (PN532_writeCommand(pn532_packetbuffer, 3)) { - return 0x0; - } - - if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) { - return 0x0; - } -# 274 "S:/Development/Tasmota/tasmota/xsns_40_pn532.ino" - if (pn532_packetbuffer[0] != 1) { - return 0; - } - - uint16_t sens_res = pn532_packetbuffer[2]; - sens_res <<= 8; - sens_res |= pn532_packetbuffer[3]; - - - *uidLength = pn532_packetbuffer[5]; - - for (uint32_t i = 0; i < pn532_packetbuffer[5]; i++) { - uid[i] = pn532_packetbuffer[6 + i]; - } - - return 1; -} - -bool PN532_setPassiveActivationRetries(uint8_t maxRetries) -{ - pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION; - pn532_packetbuffer[1] = 5; - pn532_packetbuffer[2] = 0xFF; - pn532_packetbuffer[3] = 0x01; - pn532_packetbuffer[4] = maxRetries; - if (PN532_writeCommand(pn532_packetbuffer, 5)) { - return 0; - } - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -bool PN532_SAMConfig(void) -{ - pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION; - pn532_packetbuffer[1] = 0x01; - pn532_packetbuffer[2] = 0x14; - pn532_packetbuffer[3] = 0x00; - if (PN532_writeCommand(pn532_packetbuffer, 4)) { - return false; - } - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -#ifdef USE_PN532_DATA_FUNCTION - -uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData) -{ - uint8_t i; - uint8_t _key[6]; - uint8_t _uid[7]; - uint8_t _uidLen; - - - memcpy(&_key, keyData, 6); - memcpy(&_uid, uid, uidLen); - _uidLen = uidLen; - - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A; - pn532_packetbuffer[3] = blockNumber; - memcpy(&pn532_packetbuffer[4], &_key, 6); - for (i = 0; i < _uidLen; i++) { - pn532_packetbuffer[10 + i] = _uid[i]; - } - - if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; } - - - PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); - - - - - if (pn532_packetbuffer[0] != 0x00) { - - return 0; - } - - return 1; -} - -uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data) -{ - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = MIFARE_CMD_READ; - pn532_packetbuffer[3] = blockNumber; - - - if (PN532_writeCommand(pn532_packetbuffer, 4)) { - return 0; - } - - - PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)); - - - if (pn532_packetbuffer[0] != 0x00) { - return 0; - } - - - - memcpy (data, &pn532_packetbuffer[1], 16); - - return 1; -} - -uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data) -{ - - pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; - pn532_packetbuffer[1] = 1; - pn532_packetbuffer[2] = MIFARE_CMD_WRITE; - pn532_packetbuffer[3] = blockNumber; - memcpy(&pn532_packetbuffer[4], data, 16); - - - if (PN532_writeCommand(pn532_packetbuffer, 20)) { - return 0; - } - - - return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer))); -} - -#endif - -void PN532_ScanForTag(void) -{ - if (!pn532_model) { return; } - uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; - uint8_t uid_len = 0; - uint8_t card_data[16]; - bool erase_success = false; - bool set_success = false; - if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) { - char uids[15]; - -#ifdef USE_PN532_DATA_FUNCTION - char card_datas[34]; -#endif - - ToHex_P((unsigned char*)uid, uid_len, uids, sizeof(uids)); - -#ifdef USE_PN532_DATA_FUNCTION - if (uid_len == 4) { - uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) { - if (mifareclassic_ReadDataBlock(1, card_data)) { -#ifdef USE_PN532_DATA_RAW - memcpy(&card_datas,&card_data,sizeof(card_data)); -#else - for (uint32_t i = 0;i < sizeof(card_data);i++) { - if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) { - card_datas[i] = char(card_data[i]); - } else { - card_datas[i] = '\0'; - } - } -#endif - } - if (pn532_function == 1) { - for (uint32_t i = 0;i<16;i++) { - card_data[i] = 0x00; - } - if (mifareclassic_WriteDataBlock(1, card_data)) { - erase_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase success")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } - } - if (pn532_function == 2) { -#ifdef USE_PN532_DATA_RAW - memcpy(&card_data,&pn532_newdata,sizeof(card_data)); - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } -#else - bool IsAlphaNumeric = true; - for (uint32_t i = 0;i < pn532_newdata_len;i++) { - if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) { - IsAlphaNumeric = false; - } - } - if (IsAlphaNumeric) { - memcpy(&card_data,&pn532_newdata,pn532_newdata_len); - card_data[pn532_newdata_len] = '\0'; - if (mifareclassic_WriteDataBlock(1, card_data)) { - set_success = true; - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data write successful")); - memcpy(&card_datas,&card_data,sizeof(card_data)); - } - } else { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Data must be alphanumeric")); - } -#endif - } - } else { - sprintf(card_datas,"AUTHFAIL"); - } - } - switch (pn532_function) { - case 0x01: - if (!erase_success) { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Erase fail - exiting erase mode")); - } - break; - case 0x02: - if (!set_success) { - AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Write failed - exiting set mode")); - } - default: - break; - } - pn532_function = 0; -#endif - -#ifdef USE_PN532_DATA_FUNCTION - ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); -#else - ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); -#endif - - MqttPublishTeleSensor(); - -#ifdef USE_PN532_CAUSE_EVENTS - - char command[71]; -#ifdef USE_PN532_DATA_FUNCTION - sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas); -#else - sprintf(command,"event PN532_UID=%s",uids); -#endif - ExecuteCommand(command, SRC_RULE); -#endif - - pn532_scantimer = 7; - } -} - -#ifdef USE_PN532_DATA_FUNCTION - -bool PN532_Command(void) -{ - bool serviced = true; - uint8_t paramcount = 0; - if (XdrvMailbox.data_len > 0) { - paramcount=1; - } else { - serviced = false; - return serviced; - } - char sub_string[XdrvMailbox.data_len]; - char sub_string_tmp[XdrvMailbox.data_len]; - for (uint32_t ca=0;ca 1) { - if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') { - serviced = false; - return serviced; - } - sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2)); - pn532_newdata_len = strlen(sub_string_tmp); - if (pn532_newdata_len > 15) { pn532_newdata_len = 15; } - memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len); - pn532_newdata[pn532_newdata_len] = 0x00; - pn532_function = 2; - AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); - ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}")); - return serviced; - } - } -} - -#endif - -bool Xsns40(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_INIT: - PN532_Init(); - result = true; - break; - case FUNC_EVERY_50_MSECOND: - break; - case FUNC_EVERY_100_MSECOND: - break; - case FUNC_EVERY_250_MSECOND: - if (pn532_scantimer > 0) { - pn532_scantimer--; - } else { - PN532_ScanForTag(); - } - break; - case FUNC_EVERY_SECOND: - break; -#ifdef USE_PN532_DATA_FUNCTION - case FUNC_COMMAND_SENSOR: - if (XSNS_40 == XdrvMailbox.index) { - result = PN532_Command(); - } - break; -#endif - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_41_max44009.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_41_max44009.ino" -#ifdef USE_I2C -#ifdef USE_MAX44009 - - - - - - -#define XSNS_41 41 -#define XI2C_28 28 - -#define MAX44009_ADDR1 0x4A -#define MAX44009_ADDR2 0x4B -#define MAX44009_NO_REGISTERS 8 -#define REG_CONFIG 0x02 -#define REG_LUMINANCE 0x03 -#define REG_LOWER_THRESHOLD 0x06 -#define REG_THRESHOLD_TIMER 0x07 - -#define MAX44009_CONTINUOUS_AUTO_MODE 0x80 - -uint8_t max44009_address; -uint8_t max44009_addresses[] = { MAX44009_ADDR1, MAX44009_ADDR2, 0 }; -uint8_t max44009_found = 0; -uint8_t max44009_valid = 0; -float max44009_illuminance = 0; -char max44009_types[] = "MAX44009"; - -bool Max4409Read_lum(void) -{ - max44009_valid = 0; - uint8_t regdata[2]; - - - if (I2cValidRead16((uint16_t *)®data, max44009_address, REG_LUMINANCE)) { - int exponent = (regdata[0] & 0xF0) >> 4; - int mantissa = ((regdata[0] & 0x0F) << 4) | (regdata[1] & 0x0F); - max44009_illuminance = (float)(((0x00000001 << exponent) * (float)mantissa) * 0.045); - max44009_valid = 1; - return true; - } else { - return false; - } -} - - - -void Max4409Detect(void) -{ - uint8_t buffer1; - uint8_t buffer2; - for (uint32_t i = 0; 0 != max44009_addresses[i]; i++) { - - max44009_address = max44009_addresses[i]; - if (I2cActive(max44009_address)) { continue; } - - if ((I2cValidRead8(&buffer1, max44009_address, REG_LOWER_THRESHOLD)) && - (I2cValidRead8(&buffer2, max44009_address, REG_THRESHOLD_TIMER))) { - - if ((0x00 == buffer1) && - (0xFF == buffer2)) { - - - - Wire.beginTransmission(max44009_address); - - - Wire.write(REG_CONFIG); - Wire.write(MAX44009_CONTINUOUS_AUTO_MODE); - if (0 == Wire.endTransmission()) { - I2cSetActiveFound(max44009_address, max44009_types); - max44009_found = 1; - break; - } - } - } - } -} - -void Max4409EverySecond(void) -{ - Max4409Read_lum(); -} - -void Max4409Show(bool json) -{ - char illum_str[8]; - - if (max44009_valid) { - - - - uint8_t prec = 0; - if (10 > max44009_illuminance ) { - prec = 3; - } else if (100 > max44009_illuminance) { - prec = 2; - } else if (1000 > max44009_illuminance) { - prec = 1; - } - dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_ILLUMINANCE, illum_str); - } -#endif -#ifdef USE_WEBSERVER - } else { - - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, max44009_types, (int)max44009_illuminance); -#endif - } - } -} - - - - - -bool Xsns41(uint8_t function) -{ - if (!I2cEnabled(XI2C_28)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Max4409Detect(); - } - else if (max44009_found) { - switch (function) { - case FUNC_EVERY_SECOND: - Max4409EverySecond(); - break; - case FUNC_JSON_APPEND: - Max4409Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Max4409Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_42_scd30.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_42_scd30.ino" -#ifdef USE_I2C -#ifdef USE_SCD30 - -#define XSNS_42 42 -#define XI2C_29 29 - - - -#define SCD30_ADDRESS 0x61 - -#define SCD30_MAX_MISSED_READS 3 -#define SCD30_STATE_NO_ERROR 0 -#define SCD30_STATE_ERROR_DATA_CRC 1 -#define SCD30_STATE_ERROR_READ_MEAS 2 -#define SCD30_STATE_ERROR_SOFT_RESET 3 -#define SCD30_STATE_ERROR_I2C_RESET 4 -#define SCD30_STATE_ERROR_UNKNOWN 5 - -#include "Arduino.h" -#include - -#define D_CMND_SCD30 "SCD30" - -const char S_JSON_SCD30_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d}"; -const char S_JSON_SCD30_COMMAND_NFW_VALUE[] PROGMEM = "{\"" D_CMND_SCD30 "%s\":%d.%d}"; -const char S_JSON_SCD30_COMMAND[] PROGMEM = "{\"" D_CMND_SCD30 "%s\"}"; -const char kSCD30_Commands[] PROGMEM = "Alt|Auto|Cal|FW|Int|Pres|TOff"; - - - - - -enum SCD30_Commands { - CMND_SCD30_ALTITUDE, - CMND_SCD30_AUTOMODE, - CMND_SCD30_CALIBRATE, - CMND_SCD30_FW, - CMND_SCD30_INTERVAL, - CMND_SCD30_PRESSURE, - CMND_SCD30_TEMPOFFSET -}; - -FrogmoreScd30 scd30; - -bool scd30Found = false; -bool scd30IsDataValid = false; -int scd30ErrorState = SCD30_STATE_NO_ERROR; -uint16_t scd30Interval_sec; -int scd30Loop_count = 0; -int scd30DataNotAvailable_count = 0; -int scd30GoodMeas_count = 0; -int scd30Reset_count = 0; -int scd30CrcError_count = 0; -int scd30Co2Zero_count = 0; -int i2cReset_count = 0; -uint16_t scd30_CO2 = 0; -uint16_t scd30_CO2EAvg = 0; -float scd30_Humid = 0.0; -float scd30_Temp = 0.0; - -void Scd30Detect(void) -{ - if (I2cActive(SCD30_ADDRESS)) { return; } - - scd30.begin(); - - uint8_t major = 0; - uint8_t minor = 0; - if (scd30.getFirmwareVersion(&major, &minor)) { return; } - uint16_t interval_sec; - if (scd30.getMeasurementInterval(&scd30Interval_sec)) { return; } - if (scd30.beginMeasuring()) { return; } - - I2cSetActiveFound(SCD30_ADDRESS, "SCD30"); - scd30Found = true; - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SCD: FW v%d.%d"), major, minor); -} - - -void Scd30Update(void) -{ - scd30Loop_count++; - if (scd30Loop_count > (scd30Interval_sec - 1)) { - int error = 0; - switch (scd30ErrorState) { - case SCD30_STATE_NO_ERROR: { - error = scd30.readMeasurement(&scd30_CO2, &scd30_CO2EAvg, &scd30_Temp, &scd30_Humid); - switch (error) { - case ERROR_SCD30_NO_ERROR: - scd30Loop_count = 0; - scd30IsDataValid = true; - scd30GoodMeas_count++; - break; - - case ERROR_SCD30_NO_DATA: - scd30DataNotAvailable_count++; - break; - - case ERROR_SCD30_CRC_ERROR: - scd30ErrorState = SCD30_STATE_ERROR_DATA_CRC; - scd30CrcError_count++; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CRC error, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), - scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); -#endif - break; - - case ERROR_SCD30_CO2_ZERO: - scd30Co2Zero_count++; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: CO2 zero, CRC error: %ld, CO2 zero: %ld, good: %ld, no data: %ld, sc30_reset: %ld, i2c_reset: %ld"), - scd30CrcError_count, scd30Co2Zero_count, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); -#endif - break; - - default: { - scd30ErrorState = SCD30_STATE_ERROR_READ_MEAS; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: Update: ReadMeasurement error: 0x%lX, counter: %ld"), error, scd30Loop_count); -#endif - return; - } - break; - } - } - break; - - case SCD30_STATE_ERROR_DATA_CRC: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: got CRC error, try again, counter: %ld"), scd30Loop_count); -#endif - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - break; - - case SCD30_STATE_ERROR_READ_MEAS: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: not answering, sending soft reset, counter: %ld"), scd30Loop_count); -#endif - scd30Reset_count++; - error = scd30.softReset(); - if (error) { -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: resetting got error: 0x%lX"), error); -#endif - error >>= 8; - if (error == 4) { - scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; - } else { - scd30ErrorState = SCD30_STATE_ERROR_UNKNOWN; - } - } else { - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - } - break; - - case SCD30_STATE_ERROR_SOFT_RESET: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: in error state: %d, good: %ld, no data: %ld, sc30 reset: %ld, i2c reset: %ld"), - scd30ErrorState, scd30GoodMeas_count, scd30DataNotAvailable_count, scd30Reset_count, i2cReset_count); - AddLog_P(LOG_LEVEL_ERROR, PSTR("SCD30: clearing i2c bus")); -#endif - i2cReset_count++; - error = scd30.clearI2CBus(); - if (error) { - scd30ErrorState = SCD30_STATE_ERROR_I2C_RESET; -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error clearing i2c bus: 0x%lX"), error); -#endif - } else { - scd30ErrorState = ERROR_SCD30_NO_ERROR; - } - } - break; - - default: { - -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: unknown error state: 0x%lX"), scd30ErrorState); -#endif - scd30ErrorState = SCD30_STATE_ERROR_SOFT_RESET; - } - } - - if (scd30Loop_count > (SCD30_MAX_MISSED_READS * scd30Interval_sec)) { - scd30IsDataValid = false; - } - } -} - - -int Scd30GetCommand(int command_code, uint16_t *pvalue) -{ - switch (command_code) - { - case CMND_SCD30_ALTITUDE: - return scd30.getAltitudeCompensation(pvalue); - break; - - case CMND_SCD30_AUTOMODE: - return scd30.getCalibrationType(pvalue); - break; - - case CMND_SCD30_CALIBRATE: - return scd30.getForcedRecalibrationFactor(pvalue); - break; - - case CMND_SCD30_INTERVAL: - return scd30.getMeasurementInterval(pvalue); - break; - - case CMND_SCD30_PRESSURE: - return scd30.getAmbientPressure(pvalue); - break; - - case CMND_SCD30_TEMPOFFSET: - return scd30.getTemperatureOffset(pvalue); - break; - - default: - - break; - } -} - -int Scd30SetCommand(int command_code, uint16_t value) -{ - switch (command_code) - { - case CMND_SCD30_ALTITUDE: - return scd30.setAltitudeCompensation(value); - break; - - case CMND_SCD30_AUTOMODE: - return scd30.setCalibrationType(value); - break; - - case CMND_SCD30_CALIBRATE: - return scd30.setForcedRecalibrationFactor(value); - break; - - case CMND_SCD30_INTERVAL: - { - int error = scd30.setMeasurementInterval(value); - if (!error) - { - scd30Interval_sec = value; - } - - return error; - } - break; - - case CMND_SCD30_PRESSURE: - return scd30.setAmbientPressure(value); - break; - - case CMND_SCD30_TEMPOFFSET: - return scd30.setTemperatureOffset(value); - break; - - default: - - break; - } -} - - - - - -bool Scd30CommandSensor() -{ - char command[CMDSZ]; - bool serviced = true; - uint8_t prefix_len = strlen(D_CMND_SCD30); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_SCD30), prefix_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + prefix_len, kSCD30_Commands); - - switch (command_code) { - case CMND_SCD30_ALTITUDE: - case CMND_SCD30_AUTOMODE: - case CMND_SCD30_CALIBRATE: - case CMND_SCD30_INTERVAL: - case CMND_SCD30_PRESSURE: - case CMND_SCD30_TEMPOFFSET: - { - uint16_t value = 0; - if (XdrvMailbox.data_len > 0) - { - value = XdrvMailbox.payload; - Scd30SetCommand(command_code, value); - } - else - { - Scd30GetCommand(command_code, &value); - } - - Response_P(S_JSON_SCD30_COMMAND_NVALUE, command, value); - } - break; - - case CMND_SCD30_FW: - { - uint8_t major = 0; - uint8_t minor = 0; - int error; - error = scd30.getFirmwareVersion(&major, &minor); - if (error) - { -#ifdef SCD30_DEBUG - AddLog_P2(LOG_LEVEL_ERROR, PSTR("SCD30: error getting FW version: 0x%lX"), error); -#endif - serviced = false; - } - else - { - Response_P(S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); - } - } - break; - - default: - - serviced = false; - break; - } - } - return serviced; -} - -void Scd30Show(bool json) -{ - if (scd30IsDataValid) - { - char humidity[10]; - dtostrfd(ConvertHumidity(scd30_Humid), Settings.flag2.humidity_resolution, humidity); - char temperature[10]; - dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); - - if (json) { - - ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), - scd30_CO2, scd30_CO2EAvg, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) - { - DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CO2EAVG, "SCD30", scd30_CO2EAvg); - WSContentSend_PD(HTTP_SNS_CO2, "SCD30", scd30_CO2); - WSContentSend_PD(HTTP_SNS_TEMP, "SCD30", temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, "SCD30", humidity); -#endif - } - } -} - - - - - -bool Xsns42(byte function) -{ - if (!I2cEnabled(XI2C_29)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Scd30Detect(); - } - else if (scd30Found) { - switch (function) { - case FUNC_EVERY_SECOND: - Scd30Update(); - break; - case FUNC_COMMAND: - result = Scd30CommandSensor(); - break; - case FUNC_JSON_APPEND: - Scd30Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Scd30Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_43_hre.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_43_hre.ino" -#ifdef USE_HRE -# 49 "S:/Development/Tasmota/tasmota/xsns_43_hre.ino" -#define XSNS_43 43 - -enum hre_states { - hre_idle, - hre_sync, - hre_syncing, - hre_read, - hre_reading, - hre_sleep, - hre_sleeping -}; - -hre_states hre_state = hre_idle; - -float hre_usage = 0; -float hre_rate = 0; -uint32_t hre_usage_time = 0; - -int hre_read_errors = 0; -bool hre_good = false; - - - -int hreReadBit() -{ - digitalWrite(pin[GPIO_HRE_CLOCK], HIGH); - delay(1); - int bit = digitalRead(pin[GPIO_HRE_DATA]); - digitalWrite(pin[GPIO_HRE_CLOCK], LOW); - delay(1); - return bit; -} - - - -char hreReadChar(int &parity_errors) -{ - - hreReadBit(); - - unsigned ch=0; - int sum=0; - for (uint32_t i=0; i<7; i++) - { - int b = hreReadBit(); - ch |= b << i; - sum += b; - } - - - if ( (sum & 0x1) != hreReadBit()) - parity_errors++; - - - hreReadBit(); - - return ch; -} - -void hreInit(void) -{ - hre_read_errors = 0; - hre_good = false; - - pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); - pinMode(pin[GPIO_HRE_DATA], INPUT); - - - - digitalWrite(pin[GPIO_HRE_CLOCK], LOW); - - hre_state = hre_sync; -} - - -void hreEvery50ms(void) -{ - static int sync_counter = 0; - static int sync_run = 0; - - static uint32_t curr_start = 0; - static int read_counter = 0; - static int parity_errors = 0; - static char buff[46]; - - static char ch; - static size_t i; - - switch (hre_state) - { - case hre_sync: - if (uptime < 10) - break; - sync_run = 0; - sync_counter = 0; - hre_state = hre_syncing; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); - break; - - case hre_syncing: - - - for (uint32_t i=0; i<20; i++) - { - if (hreReadBit()) - sync_run++; - else - sync_run = 0; - if (sync_run == 62) - { - hre_state = hre_read; - break; - } - sync_counter++; - } - - if (sync_counter > 1000) - { - hre_state = hre_sleep; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE D_ERROR)); - } - break; - - - case hre_read: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); - read_counter = 0; - parity_errors = 0; - curr_start = uptime; - memset(buff, 0, sizeof(buff)); - hre_state = hre_reading; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); - - - - - - case hre_reading: - - buff[read_counter++] = hreReadChar(parity_errors); - buff[read_counter++] = hreReadChar(parity_errors); - - if (read_counter == 46) - { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), - parity_errors, hre_read_errors, buff); - if (parity_errors == 0) - { - float curr_usage; - curr_usage = 0.01 * atol(buff+24); - if (hre_usage_time) - { - double dt = 1.666e-2 * (curr_start - hre_usage_time); - hre_rate = (curr_usage - hre_usage)/dt; - } - hre_usage = curr_usage; - hre_usage_time = curr_start; - hre_good = true; - - hre_state = hre_sleep; - } - else - { - hre_read_errors++; - hre_state = hre_sleep; - } - } - break; - - case hre_sleep: - hre_usage_time = curr_start; - hre_state = hre_sleeping; - AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_sleeping")); - - case hre_sleeping: - - - if (uptime - hre_usage_time >= 27) - hre_state = hre_sync; - } -} - -void hreShow(boolean json) -{ - if (!hre_good) - return; - - const char *id = "HRE"; - - char usage[16]; - char rate[16]; - dtostrfd(hre_usage, 2, usage); - dtostrfd(hre_rate, 3, rate); - - if (json) - { - ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); -#ifdef USE_WEBSERVER - } - else - { - WSContentSend_PD(HTTP_SNS_GALLONS, id, usage); - WSContentSend_PD(HTTP_SNS_GPM, id, rate); -#endif - } -} - - - - - -bool Xsns43(byte function) -{ - - if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) - return false; - - switch (function) - { - case FUNC_INIT: - hreInit(); - break; - case FUNC_EVERY_50_MSECOND: - hreEvery50ms(); - break; - case FUNC_EVERY_SECOND: - break; - case FUNC_JSON_APPEND: - hreShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - hreShow(0); - break; -#endif - } - return false; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_44_sps30.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_44_sps30.ino" -#ifdef USE_I2C -#ifdef USE_SPS30 - -#define XSNS_44 44 -#define XI2C_30 30 - -#define SPS30_ADDR 0x69 - -#include -#include - -uint8_t sps30_ready = 0; -uint8_t sps30_running; - -struct SPS30 { - float PM1_0; - float PM2_5; - float PM4_0; - float PM10; - float NCPM0_5; - float NCPM1_0; - float NCPM2_5; - float NCPM4_0; - float NCPM10; - float TYPSIZ; -} sps30_result; - -#define SPS_CMD_START_MEASUREMENT 0x0010 -#define SPS_CMD_START_MEASUREMENT_ARG 0x0300 -#define SPS_CMD_STOP_MEASUREMENT 0x0104 -#define SPS_CMD_READ_MEASUREMENT 0x0300 -#define SPS_CMD_GET_DATA_READY 0x0202 -#define SPS_CMD_AUTOCLEAN_INTERVAL 0x8004 -#define SPS_CMD_CLEAN 0x5607 -#define SPS_CMD_GET_ACODE 0xd025 -#define SPS_CMD_GET_SERIAL 0xd033 -#define SPS_CMD_RESET 0xd304 -#define SPS_WRITE_DELAY_US 20000 -#define SPS_MAX_SERIAL_LEN 32 - -uint8_t sps30_calc_CRC(uint8_t *data) { - uint8_t crc = 0xFF; - for (uint32_t i = 0; i < 2; i++) { - crc ^= data[i]; - for (uint32_t bit = 8; bit > 0; --bit) { - if(crc & 0x80) { - crc = (crc << 1) ^ 0x31u; - } else { - crc = (crc << 1); - } - } - } - return crc; -} - -void CmdClean(void); - -unsigned char twi_readFrom(unsigned char address, unsigned char* buf, unsigned int len, unsigned char sendStop); - -void sps30_get_data(uint16_t cmd, uint8_t *data, uint8_t dlen) { -unsigned char cmdb[2]; -uint8_t tmp[3]; -uint8_t index=0; -memset(data,0,dlen); -uint8_t twi_buff[64]; - - Wire.beginTransmission(SPS30_ADDR); - cmdb[0]=cmd>>8; - cmdb[1]=cmd; - Wire.write(cmdb,2); - Wire.endTransmission(); - - - dlen/=2; - dlen*=3; - - twi_readFrom(SPS30_ADDR,twi_buff,dlen,1); - - uint8_t bind=0; - while (bind>8; - cmdb[1]=cmd; - - if (cmd==SPS_CMD_START_MEASUREMENT) { - cmdb[2]=SPS_CMD_START_MEASUREMENT_ARG>>8; - cmdb[3]=SPS_CMD_START_MEASUREMENT_ARG&0xff; - cmdb[4]=sps30_calc_CRC(&cmdb[2]); - Wire.write(cmdb,5); - } else { - Wire.write(cmdb,2); - } - Wire.endTransmission(); -} - -void SPS30_Detect(void) -{ - if (!I2cSetDevice(SPS30_ADDR)) { return; } - I2cSetActiveFound(SPS30_ADDR, "SPS30"); - - uint8_t dcode[32]; - sps30_get_data(SPS_CMD_GET_SERIAL,dcode,sizeof(dcode)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("sps30 found with serial: %s"),dcode); - sps30_cmd(SPS_CMD_START_MEASUREMENT); - sps30_running = 1; - sps30_ready = 1; -} - -#define D_UNIT_PM "ug/m3" -#define D_UNIT_NCPM "#/m3" - -#ifdef USE_WEBSERVER -const char HTTP_SNS_SPS30_a[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_PM "{e}"; -const char HTTP_SNS_SPS30_b[] PROGMEM ="{s}SPS30 " "%s" "{m}%s " D_UNIT_NCPM "{e}"; -const char HTTP_SNS_SPS30_c[] PROGMEM ="{s}SPS30 " "TYPSIZ" "{m}%s " "um" "{e}"; -#endif - -#define PMDP 2 - -#define SPS30_HOURS Settings.sps30_inuse_hours - - - -void SPS30_Every_Second() { - if (!sps30_running) return; - - if (uptime%10==0) { - uint8_t vars[sizeof(float)*10]; - sps30_get_data(SPS_CMD_READ_MEASUREMENT,vars,sizeof(vars)); - float *fp=&sps30_result.PM1_0; - - typedef union { - uint8_t array[4]; - float value; - } ByteToFloat; - - ByteToFloat conv; - - for (uint32_t count=0; count<10; count++) { - for (uint32_t i = 0; i < 4; i++){ - conv.array[3-i] = vars[count*sizeof(float)+i]; - } - *fp++=conv.value; - } - } - - if (uptime%3600==0 && uptime>60) { - - - SPS30_HOURS++; - if (SPS30_HOURS>(7*24)) { - CmdClean(); - SPS30_HOURS=0; - } - } - -} - -void SPS30_Show(bool json) -{ - if (!sps30_running) { return; } - - char str[64]; - if (json) { - dtostrfd(sps30_result.PM1_0,PMDP,str); - ResponseAppend_P(PSTR(",\"SPS30\":{\"" "PM1_0" "\":%s"), str); - dtostrfd(sps30_result.PM2_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM2_5" "\":%s"), str); - dtostrfd(sps30_result.PM4_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM4_0" "\":%s"), str); - dtostrfd(sps30_result.PM10,PMDP,str); - ResponseAppend_P(PSTR(",\"" "PM10" "\":%s"), str); - dtostrfd(sps30_result.NCPM0_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM0_5" "\":%s"), str); - dtostrfd(sps30_result.NCPM1_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM1_0" "\":%s"), str); - dtostrfd(sps30_result.NCPM2_5,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM2_5" "\":%s"), str); - dtostrfd(sps30_result.NCPM4_0,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM4_0" "\":%s"), str); - dtostrfd(sps30_result.NCPM10,PMDP,str); - ResponseAppend_P(PSTR(",\"" "NCPM10" "\":%s"), str); - dtostrfd(sps30_result.TYPSIZ,PMDP,str); - ResponseAppend_P(PSTR(",\"" "TYPSIZ" "\":%s}"), str); - -#ifdef USE_WEBSERVER - } else { - dtostrfd(sps30_result.PM1_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 1.0",str); - dtostrfd(sps30_result.PM2_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 2.5",str); - dtostrfd(sps30_result.PM4_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 4.0",str); - dtostrfd(sps30_result.PM10,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_a,"PM 10",str); - dtostrfd(sps30_result.NCPM0_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 0.5",str); - dtostrfd(sps30_result.NCPM1_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 1.0",str); - dtostrfd(sps30_result.NCPM2_5,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 2.5",str); - dtostrfd(sps30_result.NCPM4_0,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 4.0",str); - dtostrfd(sps30_result.NCPM10,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_b,"NCPM 10",str); - dtostrfd(sps30_result.TYPSIZ,PMDP,str); - WSContentSend_PD(HTTP_SNS_SPS30_c,str); -#endif - } -} - -void CmdClean(void) -{ - sps30_cmd(SPS_CMD_CLEAN); - ResponseTime_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}")); - MqttPublishTeleSensor(); -} - -bool SPS30_cmd(void) -{ - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - char *cp=XdrvMailbox.data; - if (*cp=='c') { - - CmdClean(); - } else if (*cp=='0' || *cp=='1') { - sps30_running=*cp&1; - sps30_cmd(sps30_running?SPS_CMD_START_MEASUREMENT:SPS_CMD_STOP_MEASUREMENT); - } else { - serviced=false; - } - } - Response_P(PSTR("{\"SPS30\":\"%s\"}"), sps30_running?"running":"stopped"); - - return serviced; -} - - - - - -bool Xsns44(byte function) -{ - if (!I2cEnabled(XI2C_30)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - SPS30_Detect(); - } - else if (sps30_ready) { - switch (function) { - case FUNC_EVERY_SECOND: - SPS30_Every_Second(); - break; - case FUNC_JSON_APPEND: - SPS30_Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - SPS30_Show(0); - break; - #endif - case FUNC_COMMAND_SENSOR: - if (XSNS_44 == XdrvMailbox.index) { - result = SPS30_cmd(); - } - break; - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_45_vl53l0x.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_45_vl53l0x.ino" -#ifdef USE_I2C -#ifdef USE_VL53L0X - -#define XSNS_45 45 -#define XI2C_31 31 - -#include -#include "VL53L0X.h" -VL53L0X sensor; - -uint8_t vl53l0x_ready = 0; -uint16_t vl53l0x_distance; -uint16_t Vl53l0_buffer[5]; -uint8_t Vl53l0_index; - - - -void Vl53l0Detect(void) -{ - if (!I2cSetDevice(0x29)) { return; } - - if (!sensor.init()) { return; } - - I2cSetActiveFound(sensor.getAddress(), "VL53L0X"); - - sensor.setTimeout(500); - - - - - - sensor.startContinuous(); - vl53l0x_ready = 1; - - Vl53l0_index=0; -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_VL53L0X[] PROGMEM = - "{s}VL53L0X " D_DISTANCE "{m}%d" D_UNIT_MILLIMETER "{e}"; -#endif - -#define USE_VL_MEDIAN - -void Vl53l0Every_250MSecond(void) -{ - uint16_t tbuff[5],tmp; - uint8_t flag; - - - uint16_t dist = sensor.readRangeContinuousMillimeters(); - if (dist==0 || dist>2000) { - dist=9999; - } - -#ifdef USE_VL_MEDIAN - - Vl53l0_buffer[Vl53l0_index]=dist; - Vl53l0_index++; - if (Vl53l0_index>=5) Vl53l0_index=0; - - - memmove(tbuff,Vl53l0_buffer,sizeof(tbuff)); - for (byte ocnt=0; ocnt<5; ocnt++) { - flag=0; - for (byte count=0; count<4; count++) { - if (tbuff[count]>tbuff[count+1]) { - tmp=tbuff[count]; - tbuff[count]=tbuff[count+1]; - tbuff[count+1]=tmp; - flag=1; - } - } - if (!flag) break; - } - vl53l0x_distance=tbuff[2]; -#else - vl53l0x_distance=dist; -#endif -} - -void Vl53l0Show(boolean json) -{ - if (json) { - ResponseAppend_P(PSTR(",\"VL53L0X\":{\"" D_JSON_DISTANCE "\":%d}"), vl53l0x_distance); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_VL53L0X, vl53l0x_distance); -#endif - } -} - - - - - -bool Xsns45(byte function) -{ - if (!I2cEnabled(XI2C_31)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Vl53l0Detect(); - } - else if (vl53l0x_ready) { - switch (function) { - case FUNC_EVERY_250_MSECOND: - Vl53l0Every_250MSecond(); - break; - case FUNC_JSON_APPEND: - Vl53l0Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Vl53l0Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_46_MLX90614.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_46_MLX90614.ino" -#ifdef USE_I2C -#ifdef USE_MLX90614 - -#define XSNS_46 46 -#define XI2C_32 32 - -#define I2_ADR_IRT 0x5a - -#define MLX90614_RAWIR1 0x04 -#define MLX90614_RAWIR2 0x05 -#define MLX90614_TA 0x06 -#define MLX90614_TOBJ1 0x07 -#define MLX90614_TOBJ2 0x08 - -struct { - union { - uint16_t value; - uint32_t i2c_buf; - }; - float obj_temp; - float amb_temp; - bool ready = false; -} mlx90614; - -void MLX90614_Init(void) -{ - if (!I2cSetDevice(I2_ADR_IRT)) { return; } - I2cSetActiveFound(I2_ADR_IRT, "MLX90614"); - mlx90614.ready = true; -} - -void MLX90614_Every_Second(void) -{ - mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT, MLX90614_TOBJ1); - if (mlx90614.value & 0x8000) { - mlx90614.obj_temp = -999; - } else { - mlx90614.obj_temp = ((float)mlx90614.value * 0.02) - 273.15; - } - mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT,MLX90614_TA); - if (mlx90614.value & 0x8000) { - mlx90614.amb_temp = -999; - } else { - mlx90614.amb_temp = ((float)mlx90614.value * 0.02) - 273.15; - } -} - -#ifdef USE_WEBSERVER - const char HTTP_IRTMP[] PROGMEM = - "{s}MXL90614 " "OBJ-" D_TEMPERATURE "{m}%s C" "{e}" - "{s}MXL90614 " "AMB-" D_TEMPERATURE "{m}%s C" "{e}"; -#endif - -void MLX90614_Show(uint8_t json) -{ - char obj_tstr[16]; - dtostrfd(mlx90614.obj_temp, Settings.flag2.temperature_resolution, obj_tstr); - char amb_tstr[16]; - dtostrfd(mlx90614.amb_temp, Settings.flag2.temperature_resolution, amb_tstr); - - if (json) { - ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr, amb_tstr); -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_IRTMP, obj_tstr, amb_tstr); -#endif - } -} - - - - - -bool Xsns46(byte function) -{ - if (!I2cEnabled(XI2C_32)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - MLX90614_Init(); - } - else if (mlx90614.ready) { - switch (function) { - case FUNC_EVERY_SECOND: - MLX90614_Every_Second(); - break; - case FUNC_JSON_APPEND: - MLX90614_Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MLX90614_Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_47_max31865.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_47_max31865.ino" -#ifdef USE_MAX31865 - -#ifndef USE_SPI -#error "MAX31865 requires USE_SPI enabled" -#endif - -#include "Adafruit_MAX31865.h" - -#define XSNS_47 47 - -#if MAX31865_PTD_WIRES == 4 - #define PTD_WIRES MAX31865_4WIRE -#elif MAX31865_PTD_WIRES == 3 - #define PTD_WIRES MAX31865_3WIRE -#else - #define PTD_WIRES MAX31865_2WIRE -#endif - -int8_t init_status = 0; - -Adafruit_MAX31865 max31865; - -struct MAX31865_Result_Struct { - uint8_t ErrorCode; - uint16_t Rtd; - float PtdResistance; - float PtdTemp; -} MAX31865_Result; - -void MAX31865_Init(void){ - if(init_status) - return; - - max31865.setPins( - pin[GPIO_SSPI_CS], - pin[GPIO_SSPI_MOSI], - pin[GPIO_SSPI_MISO], - pin[GPIO_SSPI_SCLK] - ); - - if(max31865.begin(PTD_WIRES)) - init_status = 1; - else - init_status = -1; -} - - - - - -void MAX31865_GetResult(void){ - uint16_t rtd; - - rtd = max31865.readRTD(); - MAX31865_Result.Rtd = rtd; - MAX31865_Result.PtdResistance = max31865.rtd_to_resistance(rtd, MAX31865_REF_RES); - MAX31865_Result.PtdTemp = max31865.rtd_to_temperature(rtd, MAX31865_PTD_RES, MAX31865_REF_RES) + MAX31865_PTD_BIAS; -} - -void MAX31865_Show(bool Json){ - char temperature[33]; - char resistance[33]; - - dtostrfd(MAX31865_Result.PtdResistance, Settings.flag2.temperature_resolution, resistance); - dtostrfd(MAX31865_Result.PtdTemp, Settings.flag2.temperature_resolution, temperature); - - if(Json){ - ResponseAppend_P(PSTR(",\"MAX31865\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_RESISTANCE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - temperature, resistance, MAX31865_Result.ErrorCode); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_TEMP, temperature); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, MAX31865_Result.PtdTemp); - } -#endif - } else { -#ifdef USE_WEBSERVER - WSContentSend_PD(HTTP_SNS_TEMP, "MAX31865", temperature, TempUnit()); -#endif - } -} - - - - - -bool Xsns47(uint8_t function) -{ - bool result = false; - if((pin[GPIO_SSPI_MISO] < 99) && (pin[GPIO_SSPI_MOSI] < 99) && - (pin[GPIO_SSPI_SCLK] < 99) && (pin[GPIO_SSPI_CS] < 99)) { - - switch (function) { - case FUNC_INIT: - MAX31865_Init(); - break; - - case FUNC_EVERY_SECOND: - MAX31865_GetResult(); - break; - - case FUNC_JSON_APPEND: - MAX31865_Show(true); - break; - -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MAX31865_Show(false); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_48_chirp.ino" -# 35 "S:/Development/Tasmota/tasmota/xsns_48_chirp.ino" -#ifdef USE_I2C -#ifdef USE_CHIRP -# 47 "S:/Development/Tasmota/tasmota/xsns_48_chirp.ino" -#define XSNS_48 48 -#define XI2C_33 33 - -#define CHIRP_MAX_SENSOR_COUNT 3 - -#define CHIRP_ADDR_STANDARD 0x20 - - - - - -#define D_CMND_CHIRP "CHIRP" - -const char S_JSON_CHIRP_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_CHIRP "%s\":%d}"; -const char S_JSON_CHIRP_COMMAND[] PROGMEM = "{\"" D_CMND_CHIRP "%s\"}"; -const char kCHIRP_Commands[] PROGMEM = "Select|Set|Scan|Reset|Sleep|Wake"; - -const char kChirpTypes[] PROGMEM = "CHIRP"; - - - - - -enum CHIRP_Commands { - CMND_CHIRP_SELECT, - CMND_CHIRP_SET, - CMND_CHIRP_SCAN, - CMND_CHIRP_RESET, - CMND_CHIRP_SLEEP, - CMND_CHIRP_WAKE }; - - - - - - -#define CHIRP_GET_CAPACITANCE 0x00 -#define CHIRP_SET_ADDRESS 0x01 -#define CHIRP_GET_ADDRESS 0x02 -#define CHIRP_MEASURE_LIGHT 0x03 -#define CHIRP_GET_LIGHT 0x04 -#define CHIRP_GET_TEMPERATURE 0x05 -#define CHIRP_RESET 0x06 -#define CHIRP_GET_VERSION 0x07 -#define CHIRP_SLEEP 0x08 -#define CHIRP_GET_BUSY 0x09 - - - - - -void ChirpWriteI2CRegister(uint8_t addr, uint8_t reg) { - Wire.beginTransmission(addr); - Wire.write(reg); - Wire.endTransmission(); -} - -uint16_t ChirpFinishReadI2CRegister16bit(uint8_t addr) { - Wire.requestFrom(addr,(uint8_t)2); - uint16_t t = Wire.read() << 8; - t = t | Wire.read(); - return t; -} - - - - - -uint8_t chirp_current = 0; -uint8_t chirp_found_sensors = 0; - -char chirp_name[7]; -uint8_t chirp_next_job = 0; -uint32_t chirp_timeout_count = 0; - -#pragma pack(1) -struct ChirpSensor_t{ - uint16_t moisture = 0; - uint16_t light = 0; - int16_t temperature = 0; - uint8_t version = 0; - uint8_t address:7; - uint8_t explicitSleep:1; -}; -#pragma pack() - -ChirpSensor_t chirp_sensor[CHIRP_MAX_SENSOR_COUNT]; - - - -void ChirpReset(uint8_t addr) { - ChirpWriteI2CRegister(addr, CHIRP_RESET); -} - - - -void ChirpResetAll(void) { - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version) { - ChirpReset(chirp_sensor[i].address); - } - } -} - - -void ChirpClockSet() { - Wire.setClockStretchLimit(4000); - Wire.setClock(50000); -} - - - -void ChirpSleep(uint8_t addr) { - ChirpWriteI2CRegister(addr, CHIRP_SLEEP); -} -# 185 "S:/Development/Tasmota/tasmota/xsns_48_chirp.ino" -void ChirpSelect(uint8_t sensor) { - if(sensor < chirp_found_sensors) { - chirp_current = sensor; - DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u now active."), chirp_current); - } - if (sensor == 255) { - DEBUG_SENSOR_LOG(PSTR("CHIRP: Sensor %u active at address 0x%x."), chirp_current, chirp_sensor[chirp_current].address); - } -} - - - -uint8_t ChirpReadVersion(uint8_t addr) { - return (I2cRead8(addr, CHIRP_GET_VERSION)); -} - - - -bool ChirpSet(uint8_t addr) { - if(addr < 128){ - if (I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr)){ - if(chirp_sensor[chirp_current].version>0x25 && chirp_sensor[chirp_current].version != 255){ - delay(5); - I2cWrite8(chirp_sensor[chirp_current].address, CHIRP_SET_ADDRESS, addr); - - } - DEBUG_SENSOR_LOG(PSTR("CHIRP: Wrote adress %u "), addr); - ChirpReset(chirp_sensor[chirp_current].address); - chirp_sensor[chirp_current].address = addr; - chirp_timeout_count = 10; - chirp_next_job = 0; - if(chirp_sensor[chirp_current].version == 255){ - AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: wrote new address %u, please power off device"), addr); - chirp_sensor[chirp_current].version == 0; - } - return true; - } - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: address %u incorrect and not used"), addr); - return false; -} - - - -bool ChirpScan() -{ - ChirpClockSet(); - chirp_found_sensors = 0; - for (uint8_t address = 1; address <= 127; address++) { - chirp_sensor[chirp_found_sensors].version = 0; - chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); - delay(2); - chirp_sensor[chirp_found_sensors].version = ChirpReadVersion(address); - if (chirp_sensor[chirp_found_sensors].version > 0) { - I2cSetActiveFound(address, "CHIRP"); - if (chirp_found_sensors 0); -} - - - -void ChirpDetect(void) -{ - if (chirp_next_job > 0) { return; } - - DEBUG_SENSOR_LOG(PSTR("CHIRP: scan will start ...")); - if (ChirpScan()) { - uint8_t chirp_model = 0; - GetTextIndexed(chirp_name, sizeof(chirp_name), chirp_model, kChirpTypes); - } -} - - -void ChirpServiceAllSensors(uint8_t job){ - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version && !chirp_sensor[i].explicitSleep) { - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare for sensor at address 0x%x"), chirp_sensor[i].address); - switch(job){ - case 0: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_CAPACITANCE); - break; - case 1: - chirp_sensor[i].moisture = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - case 2: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_TEMPERATURE); - break; - case 3: - chirp_sensor[i].temperature = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - case 4: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_MEASURE_LIGHT); - break; - case 5: - ChirpWriteI2CRegister(chirp_sensor[i].address, CHIRP_GET_LIGHT); - break; - case 6: - chirp_sensor[i].light = ChirpFinishReadI2CRegister16bit(chirp_sensor[i].address); - break; - default: - break; - } - } - } -} - - - -void ChirpEvery100MSecond(void) -{ - - if(chirp_timeout_count == 0) { - switch(chirp_next_job) { - case 0: - DEBUG_SENSOR_LOG(PSTR("CHIRP: reset all")); - ChirpResetAll(); - chirp_timeout_count = 10; - chirp_next_job++; - break; - case 1: - - - chirp_next_job++; - break; - case 2: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read")); - ChirpServiceAllSensors(0); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 3: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read")); - ChirpServiceAllSensors(1); - chirp_next_job++; - break; - case 4: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare moisture read - 2nd")); - ChirpServiceAllSensors(0); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 5: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish moisture read - 2nd")); - ChirpServiceAllSensors(1); - chirp_next_job++; - break; - case 6: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read")); - ChirpServiceAllSensors(2); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 7: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read")); - ChirpServiceAllSensors(3); - chirp_next_job++; - break; - case 8: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare temperature read - 2nd")); - ChirpServiceAllSensors(2); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 9: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish temperature read - 2nd")); - ChirpServiceAllSensors(3); - chirp_next_job++; - break; - case 10: - DEBUG_SENSOR_LOG(PSTR("CHIRP: start light measure process")); - ChirpServiceAllSensors(4); - chirp_timeout_count = 90; - chirp_next_job++; - break; - case 11: - DEBUG_SENSOR_LOG(PSTR("CHIRP: prepare light read")); - ChirpServiceAllSensors(5); - chirp_timeout_count = 11; - chirp_next_job++; - break; - case 12: - DEBUG_SENSOR_LOG(PSTR("CHIRP: finish light read")); - ChirpServiceAllSensors(6); - chirp_next_job++; - break; - case 13: - DEBUG_SENSOR_LOG(PSTR("CHIRP: paused, waiting for TELE")); - break; - case 14: - if (Settings.tele_period > 16){ - chirp_timeout_count = (Settings.tele_period - 17) * 10; - DEBUG_SENSOR_LOG(PSTR("CHIRP: timeout 1/10 sec: %u, tele: %u"), chirp_timeout_count, Settings.tele_period); - } - else{ - AddLog_P2(LOG_LEVEL_INFO, PSTR("CHIRP: TELEPERIOD must be > 16 seconds !")); - - } - chirp_next_job = 1; - break; - } - } - else { - chirp_timeout_count--; - } -} - - - - -#ifdef USE_WEBSERVER - - -const char HTTP_SNS_DARKNESS[] PROGMEM = "{s} " D_JSON_DARKNESS "{m}%s %%{e}"; -const char HTTP_SNS_CHIRPVER[] PROGMEM = "{s} CHIRP-sensor %u at address{m}0x%x{e}" - "{s} FW-version{m}%s {e}"; ; -const char HTTP_SNS_CHIRPSLEEP[] PROGMEM = "{s} {m} is sleeping ...{e}"; -#endif - - - -void ChirpShow(bool json) -{ - for (uint32_t i = 0; i < chirp_found_sensors; i++) { - if (chirp_sensor[i].version) { - - char str_temperature[33]; - double t_temperature = ((double) chirp_sensor[i].temperature )/10.0; - dtostrfd(t_temperature, Settings.flag2.temperature_resolution, str_temperature); - char str_light[33]; - dtostrfd(chirp_sensor[i].light, 0, str_light); - char str_version[7]; - if(chirp_sensor[i].version == 0xff){ - strncpy_P(str_version, PSTR("Chirp!"), sizeof(str_version)); - } - else{ - sprintf(str_version, "%x", chirp_sensor[i].version); - } - - if (json) { - if(!chirp_sensor[i].explicitSleep) { - ResponseAppend_P(PSTR(",\"%s%u\":{\"" D_JSON_MOISTURE "\":%d"), chirp_name, i, chirp_sensor[i].moisture); - if(chirp_sensor[i].temperature!=-1){ - ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%s"),str_temperature); - } - ResponseAppend_P(PSTR(",\"" D_JSON_DARKNESS "\":%s}"),str_light); - } - else { - ResponseAppend_P(PSTR(",\"%s%u\":{\"sleeping\"}"),chirp_name, i); - } - #ifdef USE_DOMOTICZ - if (0 == tele_period) { - char str_moisture[33]; - dtostrfd(chirp_sensor[i].moisture, 0, str_moisture); - DomoticzTempHumSensor(str_temperature, str_moisture); - DomoticzSensor(DZ_ILLUMINANCE,chirp_sensor[i].light); - } - #endif - #ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_CHIRPVER, i, chirp_sensor[i].address, str_version); - if (chirp_sensor[i].explicitSleep){ - WSContentSend_PD(HTTP_SNS_CHIRPSLEEP); - } - else { - WSContentSend_PD(HTTP_SNS_MOISTURE, "", chirp_sensor[i].moisture); - WSContentSend_PD(HTTP_SNS_DARKNESS, str_light); - if (chirp_sensor[i].temperature!=-1) { - WSContentSend_PD(HTTP_SNS_TEMP, "", str_temperature, TempUnit()); - } - } - - #endif - } - } - } -} - - - - - -bool ChirpCmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_CHIRP); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_CHIRP), disp_len)) { - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kCHIRP_Commands); - - switch (command_code) { - case CMND_CHIRP_SELECT: - case CMND_CHIRP_SET: - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(XdrvMailbox.payload); } - if (command_code == CMND_CHIRP_SET) { ChirpSet((uint8_t)XdrvMailbox.payload); } - Response_P(S_JSON_CHIRP_COMMAND_NVALUE, command, XdrvMailbox.payload); - } - else { - if (command_code == CMND_CHIRP_SELECT) { ChirpSelect(255); } - Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); - } - break; - case CMND_CHIRP_SCAN: - case CMND_CHIRP_SLEEP: - case CMND_CHIRP_WAKE: - case CMND_CHIRP_RESET: - if (command_code == CMND_CHIRP_SCAN) { chirp_next_job = 0; - ChirpDetect(); } - if (command_code == CMND_CHIRP_SLEEP) { chirp_sensor[chirp_current].explicitSleep = true; - ChirpSleep(chirp_sensor[chirp_current].address); } - if (command_code == CMND_CHIRP_WAKE) { chirp_sensor[chirp_current].explicitSleep = false; - ChirpReadVersion(chirp_sensor[chirp_current].address); } - if (command_code == CMND_CHIRP_RESET) { ChirpReset(chirp_sensor[chirp_current].address); } - Response_P(S_JSON_CHIRP_COMMAND, command, XdrvMailbox.payload); - break; - default: - - serviced = false; - break; - } - } - return serviced; -} - - - - - -bool Xsns48(uint8_t function) -{ - if (!I2cEnabled(XI2C_33)) { return false; } - - bool result = false; - - switch (function) { - case FUNC_EVERY_100_MSECOND: - if(chirp_found_sensors > 0){ - ChirpEvery100MSecond(); - } - break; - case FUNC_COMMAND: - result = ChirpCmd(); - break; - case FUNC_JSON_APPEND: - ChirpShow(1); - chirp_next_job = 14; - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - ChirpShow(0); - break; -#endif - case FUNC_INIT: - ChirpDetect(); - break; - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_50_paj7620.ino" -# 31 "S:/Development/Tasmota/tasmota/xsns_50_paj7620.ino" -#ifdef USE_I2C -#ifdef USE_PAJ7620 - - - - - - -#define XSNS_50 50 -#define XI2C_34 34 - -#define PAJ7620_ADDR 0x73 - -#define PAJ7620_BANK_SEL 0xEF - - - -#define PAJ7620_GET_GESTURE 0x43 -#define PAJ7620_PROXIMITY_AVG_Y 0x6c - -#define PAJ7620_OBJECT_CENTER_X 0xad -#define PAJ7620_OBJECT_CENTER_Y 0xaf - -#define PAJ7620_DOWN 1 -#define PAJ7620_UP 2 -#define PAJ7620_RIGHT 4 -#define PAJ7620_LEFT 8 -#define PAJ7620_NEAR 16 -#define PAJ7620_FAR 32 -#define PAJ7620_CW 64 -#define PAJ7620_CCW 128 - - - - -const uint8_t PAJ7620initRegisterArray[][2] PROGMEM = { - {0xEF,0x00}, - {0x32,0x29}, {0x33,0x01}, {0x34,0x00}, {0x35,0x01}, {0x36,0x00}, {0x37,0x07}, {0x38,0x17}, {0x39,0x06}, - {0x3A,0x12}, {0x3F,0x00}, {0x40,0x02}, {0x41,0xFF}, {0x42,0x01}, {0x46,0x2D}, {0x47,0x0F}, {0x48,0x3C}, - {0x49,0x00}, {0x4A,0x1E}, {0x4B,0x00}, {0x4C,0x20}, {0x4D,0x00}, {0x4E,0x1A}, {0x4F,0x14}, {0x50,0x00}, - {0x51,0x10}, {0x52,0x00}, {0x5C,0x02}, {0x5D,0x00}, {0x5E,0x10}, {0x5F,0x3F}, {0x60,0x27}, {0x61,0x28}, - {0x62,0x00}, {0x63,0x03}, {0x64,0xF7}, {0x65,0x03}, {0x66,0xD9}, {0x67,0x03}, {0x68,0x01}, {0x69,0xC8}, - {0x6A,0x40}, {0x6D,0x04}, {0x6E,0x00}, {0x6F,0x00}, {0x70,0x80}, {0x71,0x00}, {0x72,0x00}, {0x73,0x00}, - {0x74,0xF0}, {0x75,0x00}, {0x80,0x42}, {0x81,0x44}, {0x82,0x04}, {0x83,0x20}, {0x84,0x20}, {0x85,0x00}, - {0x86,0x10}, {0x87,0x00}, {0x88,0x05}, {0x89,0x18}, {0x8A,0x10}, {0x8B,0x01}, {0x8C,0x37}, {0x8D,0x00}, - {0x8E,0xF0}, {0x8F,0x81}, {0x90,0x06}, {0x91,0x06}, {0x92,0x1E}, {0x93,0x0D}, {0x94,0x0A}, {0x95,0x0A}, - {0x96,0x0C}, {0x97,0x05}, {0x98,0x0A}, {0x99,0x41}, {0x9A,0x14}, {0x9B,0x0A}, {0x9C,0x3F}, {0x9D,0x33}, - {0x9E,0xAE}, {0x9F,0xF9}, {0xA0,0x48}, {0xA1,0x13}, {0xA2,0x10}, {0xA3,0x08}, {0xA4,0x30}, {0xA5,0x19}, - {0xA6,0x10}, {0xA7,0x08}, {0xA8,0x24}, {0xA9,0x04}, {0xAA,0x1E}, {0xAB,0x1E}, {0xCC,0x19}, {0xCD,0x0B}, - {0xCE,0x13}, {0xCF,0x64}, {0xD0,0x21}, {0xD1,0x0F}, {0xD2,0x88}, {0xE0,0x01}, {0xE1,0x04}, {0xE2,0x41}, - {0xE3,0xD6}, {0xE4,0x00}, {0xE5,0x0C}, {0xE6,0x0A}, {0xE7,0x00}, {0xE8,0x00}, {0xE9,0x00}, {0xEE,0x07}, - {0xEF,0x01}, - {0x00,0x1E}, {0x01,0x1E}, {0x02,0x0F}, {0x03,0x10}, {0x04,0x02}, {0x05,0x00}, {0x06,0xB0}, {0x07,0x04}, - {0x08,0x0D}, {0x09,0x0E}, {0x0A,0x9C}, {0x0B,0x04}, {0x0C,0x05}, {0x0D,0x0F}, {0x0E,0x02}, {0x0F,0x12}, - {0x10,0x02}, {0x11,0x02}, {0x12,0x00}, {0x13,0x01}, {0x14,0x05}, {0x15,0x07}, {0x16,0x05}, {0x17,0x07}, - {0x18,0x01}, {0x19,0x04}, {0x1A,0x05}, {0x1B,0x0C}, {0x1C,0x2A}, {0x1D,0x01}, {0x1E,0x00}, {0x21,0x00}, - {0x22,0x00}, {0x23,0x00}, {0x25,0x01}, {0x26,0x00}, {0x27,0x39}, {0x28,0x7F}, {0x29,0x08}, {0x30,0x03}, - {0x31,0x00}, {0x32,0x1A}, {0x33,0x1A}, {0x34,0x07}, {0x35,0x07}, {0x36,0x01}, {0x37,0xFF}, {0x38,0x36}, - {0x39,0x07}, {0x3A,0x00}, {0x3E,0xFF}, {0x3F,0x00}, {0x40,0x77}, {0x41,0x40}, {0x42,0x00}, {0x43,0x30}, - {0x44,0xA0}, {0x45,0x5C}, {0x46,0x00}, {0x47,0x00}, {0x48,0x58}, {0x4A,0x1E}, {0x4B,0x1E}, {0x4C,0x00}, - {0x4D,0x00}, {0x4E,0xA0}, {0x4F,0x80}, {0x50,0x00}, {0x51,0x00}, {0x52,0x00}, {0x53,0x00}, {0x54,0x00}, - {0x57,0x80}, {0x59,0x10}, {0x5A,0x08}, {0x5B,0x94}, {0x5C,0xE8}, {0x5D,0x08}, {0x5E,0x3D}, {0x5F,0x99}, - {0x60,0x45}, {0x61,0x40}, {0x63,0x2D}, {0x64,0x02}, {0x65,0x96}, {0x66,0x00}, {0x67,0x97}, {0x68,0x01}, - {0x69,0xCD}, {0x6A,0x01}, {0x6B,0xB0}, {0x6C,0x04}, {0x6D,0x2C}, {0x6E,0x01}, {0x6F,0x32}, {0x71,0x00}, - {0x72,0x01}, {0x73,0x35}, {0x74,0x00}, {0x75,0x33}, {0x76,0x31}, {0x77,0x01}, {0x7C,0x84}, {0x7D,0x03}, - {0x7E,0x01}, - {0xEF,0x00} -}; - - - - - -const char kPaj7620Directions[] PROGMEM = "Down|Up|Right|Left|Near|Far|CW|CCW"; - -const uint8_t PAJ7620_PIN[]= {1,2,3,4}; - - - - - -char PAJ7620_name[] = "PAJ7620"; - -uint32_t PAJ7620_timeout_counter = 10; -uint32_t PAJ7620_next_job = 0; -uint32_t PAJ7620_mode = 1; - -struct { - uint8_t current; - uint8_t last; - uint8_t same; - uint8_t unfinished; -} PAJ7620_gesture; - -bool PAJ7620_finished_gesture = false; -char PAJ7620_currentGestureName[6]; - -struct{ - uint8_t x; - uint8_t y; - uint8_t last_x; - uint8_t last_y; - uint8_t proximity; - uint8_t last_proximity; - uint8_t corner; - struct { - uint8_t step:3; - uint8_t countdown:3; - uint8_t valid:1; - } PIN; -} PAJ7620_state; - - - - - -void PAJ7620SelectBank(uint8_t bank) -{ - I2cWrite(PAJ7620_ADDR, PAJ7620_BANK_SEL, bank &1, 1); -} - - - -void PAJ7620DecodeGesture(void) -{ - uint32_t index = 0; - switch (PAJ7620_gesture.current) { - case PAJ7620_LEFT: - index++; - case PAJ7620_RIGHT: - index++; - case PAJ7620_UP: - index++; - case PAJ7620_DOWN: - if (PAJ7620_gesture.unfinished) { - PAJ7620_finished_gesture = true; - break; - } - PAJ7620_gesture.unfinished = PAJ7620_gesture.current; - PAJ7620_timeout_counter = 5; - break; - case PAJ7620_NEAR: - index = 4; - PAJ7620_finished_gesture = true; - PAJ7620_timeout_counter = 25; - break; - case PAJ7620_FAR: - index = 5; - PAJ7620_finished_gesture = true; - PAJ7620_timeout_counter = 25; - break; - case PAJ7620_CW: - index = 6; - PAJ7620_finished_gesture = true; - break; - case PAJ7620_CCW: - index = 7; - PAJ7620_finished_gesture = true; - break; - default: - index = 8; - if (PAJ7620_gesture.unfinished) { - PAJ7620_finished_gesture = true; - } - break; - } - if (index < 8) { - GetTextIndexed(PAJ7620_currentGestureName, sizeof(PAJ7620_currentGestureName), index, kPaj7620Directions); - } - - if (PAJ7620_finished_gesture) { - if (PAJ7620_gesture.unfinished) { - if ((PAJ7620_gesture.current != PAJ7620_NEAR) && (PAJ7620_gesture.current != PAJ7620_FAR)) { - PAJ7620_gesture.current = PAJ7620_gesture.unfinished; - } - } - if (PAJ7620_gesture.current == PAJ7620_gesture.last) { - PAJ7620_gesture.same++; - } else { - PAJ7620_gesture.same = 1; - } - PAJ7620_gesture.last = PAJ7620_gesture.current; - PAJ7620_finished_gesture = false; - PAJ7620_gesture.unfinished = 0; - PAJ7620_timeout_counter += 3; - MqttPublishSensor(); - } -} - - - -void PAJ7620ReadGesture(void) -{ - switch (PAJ7620_mode) { - case 1: - PAJ7620_gesture.current = I2cRead8(PAJ7620_ADDR,PAJ7620_GET_GESTURE); - if ((PAJ7620_gesture.current > 0) || PAJ7620_gesture.unfinished) { - DEBUG_SENSOR_LOG(PSTR("PAJ: gesture: %u"), PAJ7620_gesture.current); - PAJ7620DecodeGesture(); - } - break; - case 2: - PAJ7620_state.proximity = I2cRead8(PAJ7620_ADDR, PAJ7620_PROXIMITY_AVG_Y); - if ((PAJ7620_state.proximity > 0) || (PAJ7620_state.last_proximity > 0)) { - if (PAJ7620_state.proximity != PAJ7620_state.last_proximity) { - PAJ7620_state.last_proximity = PAJ7620_state.proximity; - DEBUG_SENSOR_LOG(PSTR("PAJ: Proximity: %u"), PAJ7620_state.proximity); - MqttPublishSensor(); - } - } - break; - case 3: - case 4: - case 5: - PAJ7620_state.x = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_X); - PAJ7620_state.y = I2cRead8(PAJ7620_ADDR, PAJ7620_OBJECT_CENTER_Y); - if ((PAJ7620_state.y > 0) && (PAJ7620_state.x > 0)) { - if ((PAJ7620_state.y != PAJ7620_state.last_y) || (PAJ7620_state.x != PAJ7620_state.last_x)) { - PAJ7620_state.last_y = PAJ7620_state.y; - PAJ7620_state.last_x = PAJ7620_state.x; - DEBUG_SENSOR_LOG(PSTR("PAJ: x: %u y: %u"), PAJ7620_state.x, PAJ7620_state.y); - - PAJ7620_state.corner = 0; - - - - switch (PAJ7620_state.y) { - case 0: case 1: case 2: case 3: case 4: case 5: - PAJ7620_state.corner = 3; - break; - case 9: case 10: case 11: case 12: case 13: case 14: - PAJ7620_state.corner = 1; - break; - } - if (PAJ7620_state.corner != 0) { - switch (PAJ7620_state.x) { - case 0: case 1: case 2: case 3: case 4: case 5: - break; - case 9: case 10: case 11: case 12: case 13: case 14: - PAJ7620_state.corner++; - break; - default: - PAJ7620_state.corner = 0; - break; - } - } - DEBUG_SENSOR_LOG(PSTR("PAJ: corner: %u"), PAJ7620_state.corner); - - if (PAJ7620_state.PIN.countdown == 0) { - PAJ7620_state.PIN.step = 0; - PAJ7620_state.PIN.valid = 0; - } - if (!PAJ7620_state.PIN.step) { - if (PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]) { - PAJ7620_state.PIN.step = 1; - PAJ7620_state.PIN.countdown = 7; - } - } else { - if (PAJ7620_state.corner == PAJ7620_PIN[PAJ7620_state.PIN.step]) { - PAJ7620_state.PIN.step += 1; - PAJ7620_state.PIN.countdown = 7; - } else { - PAJ7620_state.PIN.countdown -= 1; - } - } - if (PAJ7620_state.PIN.step == 4) { - PAJ7620_state.PIN.valid = 1; - DEBUG_SENSOR_LOG(PSTR("PAJ: PIN valid!!")); - PAJ7620_state.PIN.countdown = 0; - } - MqttPublishSensor(); - } - } - break; - } -} - - - -void PAJ7620Detect(void) -{ - if (I2cActive(PAJ7620_ADDR)) { return; } - - PAJ7620SelectBank(0); - PAJ7620SelectBank(0); - uint16_t PAJ7620_id = I2cRead16LE(PAJ7620_ADDR,0); - uint8_t PAJ7620_ver = I2cRead8(PAJ7620_ADDR,2); - if (0x7620 == PAJ7620_id) { - I2cSetActiveFound(PAJ7620_ADDR, PAJ7620_name); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PAJ: ID: 0x%x and VER: %u"), PAJ7620_id, PAJ7620_ver); - PAJ7620_next_job = 1; - } - else { - DEBUG_SENSOR_LOG(PSTR("PAJ: sensor not found, false ID 0x%x"), PAJ7620_id); - } -} - - - -void PAJ7620Init(void) -{ - DEBUG_SENSOR_LOG(PSTR("PAJ: init sensor start %u"),millis()); - union{ - uint32_t raw; - uint8_t reg_val[4]; - } buf; - - for (uint32_t i = 0; i < (sizeof(PAJ7620initRegisterArray) / 2); i += 2) - { - buf.raw = pgm_read_dword(PAJ7620initRegisterArray + i); - DEBUG_SENSOR_LOG("PAJ: %x %x %x %x",buf.reg_val[0],buf.reg_val[1],buf.reg_val[2],buf.reg_val[3]); - I2cWrite(PAJ7620_ADDR, buf.reg_val[0], buf.reg_val[1], 1); - I2cWrite(PAJ7620_ADDR, buf.reg_val[2], buf.reg_val[3], 1); - } - DEBUG_SENSOR_LOG(PSTR("PAJ: init sensor done %u"),millis()); - PAJ7620_next_job = 2; -} - - - -void PAJ7620Loop(void) -{ - if (0 == PAJ7620_timeout_counter) { - switch (PAJ7620_next_job) { - case 1: - PAJ7620Init(); - break; - case 2: - if (PAJ7620_mode != 0) { - PAJ7620ReadGesture(); - } - break; - } - } else { - PAJ7620_timeout_counter--; - } -} - - - -void PAJ7620Show(bool json) -{ - if (json) { - if (PAJ7620_currentGestureName[0] != '\0' ) { - ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), PAJ7620_name, PAJ7620_currentGestureName, PAJ7620_gesture.same); - PAJ7620_currentGestureName[0] = '\0'; - return; - } - switch (PAJ7620_mode) { - case 2: - ResponseAppend_P(PSTR(",\"%s\":{\"Proximity\":%u}"), PAJ7620_name, PAJ7620_state.proximity); - break; - case 3: - if (PAJ7620_state.corner > 0) { - ResponseAppend_P(PSTR(",\"%s\":{\"Corner\":%u}"), PAJ7620_name, PAJ7620_state.corner); - } - break; - case 4: - if (PAJ7620_state.PIN.valid) { - ResponseAppend_P(PSTR(",\"%s\":{\"PIN\":%u}"), PAJ7620_name, 1); - PAJ7620_state.PIN.valid = 0; - } - break; - case 5: - ResponseAppend_P(PSTR(",\"%s\":{\"x\":%u,\"y\":%u}"), PAJ7620_name, PAJ7620_state.x, PAJ7620_state.y); - break; - } - } -} -# 411 "S:/Development/Tasmota/tasmota/xsns_50_paj7620.ino" -bool PAJ7620CommandSensor(void) -{ - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) { - PAJ7620_mode = XdrvMailbox.payload; - } - Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_50, PAJ7620_mode); - - return true; -} - - - - - -bool Xsns50(uint8_t function) -{ - if (!I2cEnabled(XI2C_34)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - PAJ7620Detect(); - } - else if (PAJ7620_next_job) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_50 == XdrvMailbox.index){ - result = PAJ7620CommandSensor(); - } - break; - case FUNC_EVERY_100_MSECOND: - PAJ7620Loop(); - break; - case FUNC_JSON_APPEND: - PAJ7620Show(1); - break; - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_51_rdm6300.ino" -# 21 "S:/Development/Tasmota/tasmota/xsns_51_rdm6300.ino" -#ifdef USE_RDM6300 - -#define XSNS_51 51 - -#define RDM6300_BAUDRATE 9600 - -#include - -#define RDM_TIMEOUT 100 -char rdm_uid_str[10]; - - -#define RDM6300_BLOCK 2*10 - -uint8_t rdm_blcnt; -TasmotaSerial *RDM6300_Serial = nullptr; - -void RDM6300_Init() { - if (pin[GPIO_RDM6300_RX] < 99) { - RDM6300_Serial = new TasmotaSerial(pin[GPIO_RDM6300_RX],-1,1); - if (RDM6300_Serial->begin(RDM6300_BAUDRATE)) { - if (RDM6300_Serial->hardwareSerial()) { - ClaimSerial(); - } - } - } - rdm_blcnt=0; -} - - -void RDM6300_ScanForTag() { - char rdm_buffer[14]; - uint8_t rdm_index; - uint8_t rdm_array[6]; - - if (!RDM6300_Serial) return; - - if (rdm_blcnt>0) { - rdm_blcnt--; - while (RDM6300_Serial->available()) RDM6300_Serial->read(); - return; - } - - if (RDM6300_Serial->available()) { - - char c=RDM6300_Serial->read(); - if (c!=2) return; - - - rdm_index=0; - uint32_t cmillis=millis(); - while (1) { - if (RDM6300_Serial->available()) { - char c=RDM6300_Serial->read(); - if (c==3) { - - break; - } - rdm_buffer[rdm_index++]=c; - if (rdm_index>13) { - - return; - } - } - if ((millis()-cmillis)>RDM_TIMEOUT) { - - return; - } - } - - - rdm_blcnt=RDM6300_BLOCK; - - - rm6300_hstring_to_array(rdm_array,sizeof(rdm_array),rdm_buffer); - uint8_t accu=0; - for (uint8_t count=0;count<5;count++) { - accu^=rdm_array[count]; - } - if (accu!=rdm_array[5]) { - - return; - } - - - memcpy(rdm_uid_str,&rdm_buffer[2],8); - rdm_uid_str[9]=0; - - ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str); - MqttPublishTeleSensor(); - - - - - - } - - -} - -uint8_t rm6300_hexnibble(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { - rVal = chr - '0'; - } else { - if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; - } - return rVal; -} - - -void rm6300_hstring_to_array(uint8_t array[], uint8_t len, char buffer[]) -{ - char *cp=buffer; - for (uint8_t i = 0; i < len; i++) { - uint8_t val = rm6300_hexnibble(*cp++) << 4; - array[i]= val | rm6300_hexnibble(*cp++); - } -} - -#ifdef USE_WEBSERVER -const char HTTP_RDM6300[] PROGMEM = - "{s}RDM6300 " "UID" "{m}%s" "{e}"; - -void RDM6300_Show(void) { - if (!RDM6300_Serial) return; - if (!rdm_uid_str[0]) strcpy(rdm_uid_str,"????"); - WSContentSend_PD(HTTP_RDM6300,rdm_uid_str); -} -#endif - - - - - -bool Xsns51(byte function) -{ - bool result = false; - - switch (function) { - case FUNC_INIT: - RDM6300_Init(); - break; - case FUNC_EVERY_100_MSECOND: - RDM6300_ScanForTag(); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - RDM6300_Show(); - break; -#endif - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_52_ibeacon.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_52_ibeacon.ino" -#ifdef USE_IBEACON - - - -#define XSNS_52 52 - -#include - -#define HM17_BAUDRATE 9600 - -#define IBEACON_DEBUG - - -#define HM17_V110 - - - -#define IB_TIMEOUT_INTERVAL 30 - -#define IB_UPDATE_TIME_INTERVAL 10 - -TasmotaSerial *IBEACON_Serial = nullptr; - - -uint8_t hm17_found,hm17_cmd,hm17_flag; - -#ifdef IBEACON_DEBUG -uint8_t hm17_debug=0; -#endif - - - -#define HM17_BSIZ 128 -char hm17_sbuffer[HM17_BSIZ]; -uint8_t hm17_sindex,hm17_result,hm17_scanning,hm17_connecting; -uint32_t hm17_lastms; -char ib_mac[14]; - - -#if 1 -uint8_t ib_upd_interval,ib_tout_interval; -#define IB_UPDATE_TIME ib_upd_interval -#define IB_TIMEOUT_TIME ib_tout_interval -#else -#undef IB_UPDATE_TIME -#undef IB_TIMEOUT_TIME -#define IB_UPDATE_TIME Settings.ib_upd_interval -#define IB_TIMEOUT_TIME Settings.ib_tout_interval -#endif - -enum {HM17_TEST,HM17_ROLE,HM17_IMME,HM17_DISI,HM17_IBEA,HM17_SCAN,HM17_DISC,HM17_RESET,HM17_RENEW,HM17_CON}; -#define HM17_SUCESS 99 - -struct IBEACON { - char FACID[8]; - char UID[32]; - char MAJOR[4]; - char MINOR[4]; - char PWR[2]; - char MAC[12]; - char RSSI[4]; -}; - -#define MAX_IBEACONS 16 - -struct IBEACON_UID { - char MAC[12]; - char RSSI[4]; - uint8_t FLAGS; - uint8_t TIME; -} ibeacons[MAX_IBEACONS]; - - -void IBEACON_Init() { - - hm17_found=0; - - - if ((pin[GPIO_IBEACON_RX] < 99) && (pin[GPIO_IBEACON_TX] < 99)) { - IBEACON_Serial = new TasmotaSerial(pin[GPIO_IBEACON_RX], pin[GPIO_IBEACON_TX],1); - if (IBEACON_Serial->begin(HM17_BAUDRATE)) { - if (IBEACON_Serial->hardwareSerial()) { - ClaimSerial(); - } - hm17_sendcmd(HM17_TEST); - hm17_lastms=millis(); - - IB_UPDATE_TIME=IB_UPDATE_TIME_INTERVAL; - IB_TIMEOUT_TIME=IB_TIMEOUT_INTERVAL; - } - } -} - -void hm17_every_second(void) { - if (!IBEACON_Serial) return; - - if (hm17_found) { - if (IB_UPDATE_TIME && (uptime%IB_UPDATE_TIME==0)) { - if (hm17_cmd!=99) { - if (hm17_flag&2) { - ib_sendbeep(); - } else { - if (!hm17_connecting) { - hm17_sendcmd(HM17_DISI); - } - } - } - } - for (uint32_t cnt=0;cntIB_TIMEOUT_TIME) { - ibeacons[cnt].FLAGS=0; - ibeacon_mqtt(ibeacons[cnt].MAC,"0000"); - } - } - } - } else { - if (uptime%20==0) { - hm17_sendcmd(HM17_TEST); - } - } -} - -void hm17_sbclr(void) { - memset(hm17_sbuffer,0,HM17_BSIZ); - hm17_sindex=0; - IBEACON_Serial->flush(); -} - -void hm17_sendcmd(uint8_t cmd) { - hm17_sbclr(); - hm17_cmd=cmd; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("hm17cmd %d"),cmd); -#endif - switch (cmd) { - case HM17_TEST: - IBEACON_Serial->write("AT"); - break; - case HM17_ROLE: - IBEACON_Serial->write("AT+ROLE1"); - break; - case HM17_IMME: - IBEACON_Serial->write("AT+IMME1"); - break; - case HM17_DISI: - IBEACON_Serial->write("AT+DISI?"); - hm17_scanning=1; - break; - case HM17_IBEA: - IBEACON_Serial->write("AT+IBEA1"); - break; - case HM17_RESET: - IBEACON_Serial->write("AT+RESET"); - break; - case HM17_RENEW: - IBEACON_Serial->write("AT+RENEW"); - break; - case HM17_SCAN: - IBEACON_Serial->write("AT+SCAN5"); - break; - case HM17_DISC: - IBEACON_Serial->write("AT+DISC?"); - hm17_scanning=1; - break; - case HM17_CON: - IBEACON_Serial->write((const uint8_t*)"AT+CON",6); - IBEACON_Serial->write((const uint8_t*)ib_mac,12); - hm17_connecting=1; - break; - } -} - -uint32_t ibeacon_add(struct IBEACON *ib) { - - if (!strncmp(ib->MAC,"FFFF",4) || strncmp(ib->FACID,"00000000",8)) { - for (uint32_t cnt=0;cntMAC,12)) { - - memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); - ibeacons[cnt].TIME=0; - return 1; - } - } - } - for (uint32_t cnt=0;cntMAC,12); - memcpy(ibeacons[cnt].RSSI,ib->RSSI,4); - ibeacons[cnt].FLAGS=1; - ibeacons[cnt].TIME=0; - return 1; - } - } - } - return 0; -} - -void hm17_decode(void) { - struct IBEACON ib; - switch (hm17_cmd) { - case HM17_TEST: - if (!strncmp(hm17_sbuffer,"OK",2)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("AT OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - hm17_found=1; - } - break; - case HM17_ROLE: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("ROLE OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_IMME: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IMME OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_IBEA: - if (!strncmp(hm17_sbuffer,"OK+Set:1",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("IBEA OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_SCAN: - if (!strncmp(hm17_sbuffer,"OK+Set:5",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("SCAN OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_RESET: - if (!strncmp(hm17_sbuffer,"OK+RESET",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RESET OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_RENEW: - if (!strncmp(hm17_sbuffer,"OK+RENEW",8)) { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("RENEW OK")); -#endif - hm17_sbclr(); - hm17_result=HM17_SUCESS; - } - break; - case HM17_CON: - if (!strncmp(hm17_sbuffer,"OK+CONNA",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNA OK")); -#endif - hm17_connecting=2; - break; - } - if (!strncmp(hm17_sbuffer,"OK+CONNE",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNE ERROR")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+CONNF",8)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONNF ERROR")); -#endif - break; - } - if (hm17_connecting==2 && !strncmp(hm17_sbuffer,"OK+CONN",7)) { - hm17_sbclr(); -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("CONN OK")); -#endif - hm17_connecting=3; - hm17_sendcmd(HM17_TEST); - hm17_connecting=0; - break; - } - break; - - case HM17_DISI: - case HM17_DISC: - if (!strncmp(hm17_sbuffer,"OK+DISCS",8)) { - hm17_sbclr(); - hm17_result=1; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCS OK")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISIS",8)) { - hm17_sbclr(); - hm17_result=1; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISIS OK")); -#endif - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISCE",8)) { - hm17_sbclr(); - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR("DISCE OK")); -#endif - hm17_scanning=0; - break; - } - if (!strncmp(hm17_sbuffer,"OK+NAME:",8)) { - if (hm17_sbuffer[hm17_sindex-1]=='\n') { - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("NAME OK")); - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - hm17_sbclr(); - } - break; - } - if (!strncmp(hm17_sbuffer,"OK+DIS0:",8)) { - if (hm17_cmd==HM17_DISI) { -#ifdef HM17_V110 - goto hm17_v110; -#endif - } else { - if (hm17_sindex==20) { - hm17_result=HM17_SUCESS; -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("DIS0 OK")); - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - hm17_sbclr(); - } - } - break; - } - if (!strncmp(hm17_sbuffer,"OK+DISC:",8)) { -hm17_v110: - if (hm17_cmd==HM17_DISI) { - if (hm17_sindex==78) { -#ifdef IBEACON_DEBUG - if (hm17_debug) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("DISC: OK")); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); - } -#endif - memcpy(ib.FACID,&hm17_sbuffer[8],8); - memcpy(ib.UID,&hm17_sbuffer[8+8+1],32); - memcpy(ib.MAJOR,&hm17_sbuffer[8+8+1+32+1],4); - memcpy(ib.MINOR,&hm17_sbuffer[8+8+1+32+1+4],4); - memcpy(ib.PWR,&hm17_sbuffer[8+8+1+32+1+4+4],2); - memcpy(ib.MAC,&hm17_sbuffer[8+8+1+32+1+4+4+2+1],12); - memcpy(ib.RSSI,&hm17_sbuffer[8+8+1+32+1+4+4+2+1+12+1],4); - - if (ibeacon_add(&ib)) { - ibeacon_mqtt(ib.MAC,ib.RSSI); - } - hm17_sbclr(); - hm17_result=1; - } - } else { -#ifdef IBEACON_DEBUG - if (hm17_debug) AddLog_P2(LOG_LEVEL_INFO, PSTR(">>%s"),&hm17_sbuffer[8]); -#endif - } - break; - } - } -} - -void IBEACON_loop() { - - if (!IBEACON_Serial) return; - -uint32_t difftime=millis()-hm17_lastms; - - while (IBEACON_Serial->available()) { - hm17_lastms=millis(); - - if (hm17_sindexread(); - hm17_sindex++; - hm17_decode(); - } else { - hm17_sindex=0; - break; - } - } - - if (hm17_cmd==99) { - if (hm17_sindex>=HM17_BSIZ-2 || (hm17_sindex && (difftime>100))) { - AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),hm17_sbuffer); - hm17_sbclr(); - } - } - -} - -#ifdef USE_WEBSERVER -const char HTTP_IBEACON[] PROGMEM = - "{s}IBEACON-UID : %s" " - RSSI : %s" "{m}{e}"; - -void IBEACON_Show(void) { -char mac[14]; -char rssi[6]; - - for (uint32_t cnt=0;cnt 0) { - char *cp=XdrvMailbox.data; - if (*cp>='0' && *cp<='8') { - hm17_sendcmd(*cp&7); - Response_P(S_JSON_IBEACON, XSNS_52,"hm17cmd",*cp&7); - } else if (*cp=='s') { - cp++; - len--; - while (*cp==' ') { - len--; - cp++; - } - IBEACON_Serial->write((uint8_t*)cp,len); - hm17_cmd=99; - Response_P(S_JSON_IBEACON1, XSNS_52,"hm17cmd",cp); - } else if (*cp=='u') { - cp++; - if (*cp) IB_UPDATE_TIME=atoi(cp); - Response_P(S_JSON_IBEACON, XSNS_52,"uintv",IB_UPDATE_TIME); - } else if (*cp=='t') { - cp++; - if (*cp) IB_TIMEOUT_TIME=atoi(cp); - Response_P(S_JSON_IBEACON, XSNS_52,"lintv",IB_TIMEOUT_TIME); - } else if (*cp=='c') { - for (uint32_t cnt=0;cnt - - -#define SPECIAL_SS - - - - - -#if MY_LANGUAGE==de-DE - -#define D_TPWRIN "Verbrauch" -#define D_TPWROUT "Einspeisung" -#define D_TPWRCURR "Aktueller Verbrauch" -#define D_TPWRCURR1 "Verbrauch P1" -#define D_TPWRCURR2 "Verbrauch P2" -#define D_TPWRCURR3 "Verbrauch P3" -#define D_Strom_L1 "Strom L1" -#define D_Strom_L2 "Strom L2" -#define D_Strom_L3 "Strom L3" -#define D_Spannung_L1 "Spannung L1" -#define D_Spannung_L2 "Spannung L2" -#define D_Spannung_L3 "Spannung L3" -#define D_METERNR "Zähler Nr" -#define D_METERSID "Service ID" -#define D_GasIN "Zählerstand" -#define D_H2oIN "Zählerstand" -#define D_StL1L2L3 "Ströme L1+L2+L3" -#define D_SpL1L2L3 "Spannung L1+L2+L3/3" - -#else - -#undef D_TPWRIN -#undef D_TPWROUT -#undef D_TPWRCURR -#undef D_TPWRCURR1 -#undef D_TPWRCURR2 -#undef D_TPWRCURR3 -#undef D_Strom_L1 -#undef D_Strom_L2 -#undef D_Strom_L3 -#undef D_Spannung_L1 -#undef D_Spannung_L2 -#undef D_Spannung_L3 -#undef D_METERNR -#undef D_METERSID -#undef D_GasIN -#undef D_H2oIN -#undef D_StL1L2L3 -#undef D_SpL1L2L3 - -#define D_TPWRIN "Total-In" -#define D_TPWROUT "Total-Out" -#define D_TPWRCURR "Current-In/Out" -#define D_TPWRCURR1 "Current-In p1" -#define D_TPWRCURR2 "Current-In p2" -#define D_TPWRCURR3 "Current-In p3" -#define D_Strom_L1 "Current L1" -#define D_Strom_L2 "Current L2" -#define D_Strom_L3 "Current L3" -#define D_Spannung_L1 "Voltage L1" -#define D_Spannung_L2 "Voltage L2" -#define D_Spannung_L3 "Voltage L3" -#define D_METERNR "Meter_number" -#define D_METERSID "Service ID" -#define D_GasIN "Counter" -#define D_H2oIN "Counter" -#define D_StL1L2L3 "Current L1+L2+L3" -#define D_SpL1L2L3 "Voltage L1+L2+L3/3" - -#endif - - - -#define DJ_TPWRIN "Total_in" -#define DJ_TPWROUT "Total_out" -#define DJ_TPWRCURR "Power_curr" -#define DJ_TPWRCURR1 "Power_p1" -#define DJ_TPWRCURR2 "Power_p2" -#define DJ_TPWRCURR3 "Power_p3" -#define DJ_CURR1 "Curr_p1" -#define DJ_CURR2 "Curr_p2" -#define DJ_CURR3 "Curr_p3" -#define DJ_VOLT1 "Volt_p1" -#define DJ_VOLT2 "Volt_p2" -#define DJ_VOLT3 "Volt_p3" -#define DJ_METERNR "Meter_number" -#define DJ_METERSID "Meter_id" -#define DJ_CSUM "Curr_summ" -#define DJ_VAVG "Volt_avg" -#define DJ_COUNTER "Count" - -struct METER_DESC { - uint8_t srcpin; - uint8_t type; - uint16_t flag; - int32_t params; - char prefix[8]; - int8_t trxpin; - uint8_t tsecs; - char *txmem; - uint8_t index; - uint8_t max_index; -}; - - - - - - -#define EHZ161_0 1 -#define EHZ161_1 2 -#define EHZ363 3 -#define EHZH 4 -#define EDL300 5 -#define Q3B 6 -#define COMBO3 7 -#define COMBO2 8 -#define COMBO3a 9 -#define Q3B_V1 10 -#define EHZ363_2 11 -#define COMBO3b 12 -#define WGS_COMBO 13 -#define EBZD_G 14 - - -#define METER EHZ161_1 - - -#if METER==EHZ161_0 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" -"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" -"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" -"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - - - -#if METER==EHZ161_1 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZ363 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZH -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - - - -#if METER==EDL300 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,770701000f0700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - -#if METER==EBZD_G -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"strom",-1,1,0}}; -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" - -"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100600100ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - - -#if METER==Q3B -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020801ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0"; -#endif - -#if METER==COMBO3 - -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, - [1]={14,'s',0,SML_BAUDRATE,"SML",-1,1,0}, - [2]={4,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; - - -const uint8_t meter[]= -"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,1-0:21.7.0*255(@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",0|" -"1,1-0:41.7.0*255(@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",0|" -"1,1-0:61.7.0*255(@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",0|" -"1,=m 3+4+5 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"2,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"3,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - -#if METER==COMBO2 - -#undef METERS_USED -#define METERS_USED 2 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, - [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; - - -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" - -"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - -#if METER==COMBO3a -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, - [1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}, - [2]={1,'o',0,SML_BAUDRATE,"OBIS3",-1,1,0}}; - - -const uint8_t meter[]= -"1,=h --- Zähler Nr 1 ---|" -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"2,=h --- Zähler Nr 2 ---|" -"2,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"2,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"2,=d 6 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"2,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" -"3,=h --- Zähler Nr 3 ---|" -"3,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"3,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"3,=d 10 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"3,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; - -#endif - - - -#if METER==Q3B_V1 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ -[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}}; -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0"; -#endif - - - -#if METER==EHZ363_2 -#undef METERS_USED -#define METERS_USED 1 -struct METER_DESC const meter_desc[METERS_USED]={ -[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - -"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" - -"1,77070100020800ff@1000," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" - -"1,77070100010801ff@1000," D_TPWRCURR1 ",KWh," DJ_TPWRCURR1 ",4|" - -"1,77070100010802ff@1000," D_TPWRCURR2 ",KWh," DJ_TPWRCURR2 ",4|" - -"1,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" - -"1,77070100000009ff@#," D_METERNR ",," DJ_METERNR ",0"; -#endif - - -#if METER==COMBO3b -#undef METERS_USED -#define METERS_USED 3 -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, - [1]={14,'c',0,50,"Gas"}, - [2]={1,'c',0,10,"Wasser"}}; - - -const uint8_t meter[]= -"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|" -"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|" -"1,=d 2 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|" -"1,1-0:0.0.0*255(@#)," D_METERNR ",," DJ_METERNR ",0|" - - -"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",2|" - -"3,1-0:1.8.0*255(@100," D_H2oIN ",cbm," DJ_COUNTER ",2"; -#endif - - -#if METER==WGS_COMBO -#undef METERS_USED -#define METERS_USED 3 - -struct METER_DESC const meter_desc[METERS_USED]={ - [0]={1,'c',0,10,"H20",-1,1,0}, - [1]={4,'c',0,50,"GAS",-1,1,0}, - [2]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; - -const uint8_t meter[]= - - -"1,1-0:1.8.0*255(@10000," D_H2oIN ",cbm," DJ_COUNTER ",4|" - - -"2,=h==================|" -"2,1-0:1.8.0*255(@100," D_GasIN ",cbm," DJ_COUNTER ",3|" - -"3,=h==================|" - -"3,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",3|" -"3,=h==================|" - -"3,77070100100700ff@1," D_TPWRCURR ",W," DJ_TPWRCURR ",2|" -"3,=h -------------------------------|" -"3,=m 10+11+12 @100," D_StL1L2L3 ",A," DJ_CSUM ",2|" - -"3,=m 13+14+15/#3 @100," D_SpL1L2L3 ",V," DJ_VAVG ",2|" -"3,=h==================|" - -"3,77070100240700ff@1," D_TPWRCURR1 ",W," DJ_TPWRCURR1 ",2|" - -"3,77070100380700ff@1," D_TPWRCURR2 ",W," DJ_TPWRCURR2 ",2|" - -"3,770701004c0700ff@1," D_TPWRCURR3 ",W," DJ_TPWRCURR3 ",2|" -"3,=h -------------------------------|" - -"3,770701001f0700ff@100," D_Strom_L1 ",A," DJ_CURR1 ",2|" - -"3,77070100330700ff@100," D_Strom_L2 ",A," DJ_CURR2 ",2|" - -"3,77070100470700ff@100," D_Strom_L3 ",A," DJ_CURR3 ",2|" -"3,=h -------------------------------|" - -"3,77070100200700ff@100," D_Spannung_L1 ",V," DJ_VOLT1 ",2|" - -"3,77070100340700ff@100," D_Spannung_L2 ",V," DJ_VOLT2 ",2|" - -"3,77070100480700ff@100," D_Spannung_L3 ",V," DJ_VOLT3 ",2|" -"3,=h==================|" - -"3,77070100000009ff@#," D_METERSID ",," DJ_METERSID ",0|" -"3,=h--------------------------------"; -#endif -# 499 "S:/Development/Tasmota/tasmota/xsns_53_sml.ino" -#define USE_SML_MEDIAN_FILTER - - -#ifndef SML_MAX_VARS -#define SML_MAX_VARS 20 -#endif - - -#define MAX_METERS 5 -double meter_vars[SML_MAX_VARS]; - -#define MAX_DVARS MAX_METERS*2 -double dvalues[MAX_DVARS]; -uint32_t dtimes[MAX_DVARS]; -uint8_t meters_used; - -struct METER_DESC const *meter_desc_p; -const uint8_t *meter_p; -uint8_t meter_spos[MAX_METERS]; - - -TasmotaSerial *meter_ss[MAX_METERS]; - - -#define SML_BSIZ 48 -uint8_t smltbuf[MAX_METERS][SML_BSIZ]; - - -#define METER_ID_SIZE 24 -char meter_id[MAX_METERS][METER_ID_SIZE]; - -#define EBUS_SYNC 0xaa -#define EBUS_ESC 0xa9 - -uint8_t sml_send_blocks; -uint8_t sml_100ms_cnt; -uint8_t sml_desc_cnt; - -#ifdef USE_SML_MEDIAN_FILTER - -#define MEDIAN_SIZE 5 -struct SML_MEDIAN_FILTER { -double buffer[MEDIAN_SIZE]; -int8_t index; -} sml_mf[SML_MAX_VARS]; - -#ifndef FLT_MAX -#define FLT_MAX 99999999 -#endif - -double sml_median_array(double *array,uint8_t len) { - uint8_t ind[len]; - uint8_t mind=0,index=0,flg; - double min=FLT_MAX; - - for (uint8_t hcnt=0; hcntbuffer[mf->index]=in; - mf->index++; - if (mf->index>=MEDIAN_SIZE) mf->index=0; - - return sml_median_array(mf->buffer,MEDIAN_SIZE); -# 603 "S:/Development/Tasmota/tasmota/xsns_53_sml.ino" -} -#endif - -#ifdef ANALOG_OPTO_SENSOR - -uint8_t ads1115_up; - - -#define SAMPLE_BIT (0x8000) - -#define ADS1115_COMP_QUEUE_SHIFT 0 -#define ADS1115_COMP_LATCH_SHIFT 2 -#define ADS1115_COMP_POLARITY_SHIFT 3 -#define ADS1115_COMP_MODE_SHIFT 4 -#define ADS1115_DATA_RATE_SHIFT 5 -#define ADS1115_MODE_SHIFT 8 -#define ADS1115_PGA_SHIFT 9 -#define ADS1115_MUX_SHIFT 12 - -enum ads1115_comp_queue { - ADS1115_COMP_QUEUE_AFTER_ONE = 0, - ADS1115_COMP_QUEUE_AFTER_TWO = 0x1 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_AFTER_FOUR = 0x2 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_DISABLE = 0x3 << ADS1115_COMP_QUEUE_SHIFT, - ADS1115_COMP_QUEUE_MASK = 0x3 << ADS1115_COMP_QUEUE_SHIFT, -}; - -enum ads1115_comp_latch { - ADS1115_COMP_LATCH_NO = 0, - ADS1115_COMP_LATCH_YES = 1 << ADS1115_COMP_LATCH_SHIFT, - ADS1115_COMP_LATCH_MASK = 1 << ADS1115_COMP_LATCH_SHIFT, -}; - -enum ads1115_comp_polarity { - ADS1115_COMP_POLARITY_ACTIVE_LOW = 0, - ADS1115_COMP_POLARITY_ACTIVE_HIGH = 1 << ADS1115_COMP_POLARITY_SHIFT, - ADS1115_COMP_POLARITY_MASK = 1 << ADS1115_COMP_POLARITY_SHIFT, -}; - -enum ads1115_comp_mode { - ADS1115_COMP_MODE_WINDOW = 0, - ADS1115_COMP_MODE_HYSTERESIS = 1 << ADS1115_COMP_MODE_SHIFT, - ADS1115_COMP_MODE_MASK = 1 << ADS1115_COMP_MODE_SHIFT, -}; - -enum ads1115_data_rate { - ADS1115_DATA_RATE_8_SPS = 0, - ADS1115_DATA_RATE_16_SPS = 0x1 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_32_SPS = 0x2 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_64_SPS = 0x3 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_128_SPS = 0x4 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_250_SPS = 0x5 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_475_SPS = 0x6 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_860_SPS = 0x7 << ADS1115_DATA_RATE_SHIFT, - ADS1115_DATA_RATE_MASK = 0x7 << ADS1115_DATA_RATE_SHIFT, -}; - -enum ads1115_mode { - ADS1115_MODE_CONTINUOUS = 0, - ADS1115_MODE_SINGLE_SHOT = 1 << ADS1115_MODE_SHIFT, - ADS1115_MODE_MASK = 1 << ADS1115_MODE_SHIFT, -}; - -enum ads1115_pga { - ADS1115_PGA_TWO_THIRDS = 0, - ADS1115_PGA_ONE = 0x1 << ADS1115_PGA_SHIFT, - ADS1115_PGA_TWO = 0x2 << ADS1115_PGA_SHIFT, - ADS1115_PGA_FOUR = 0x3 << ADS1115_PGA_SHIFT, - ADS1115_PGA_EIGHT = 0x4 << ADS1115_PGA_SHIFT, - ADS1115_PGA_SIXTEEN = 0x5 << ADS1115_PGA_SHIFT, - ADS1115_PGA_MASK = 0x7 << ADS1115_PGA_SHIFT, -}; - - -enum ads1115_mux { - ADS1115_MUX_DIFF_AIN0_AIN1 = 0, - ADS1115_MUX_DIFF_AIN0_AIN3 = 0x1 << ADS1115_MUX_SHIFT, - ADS1115_MUX_DIFF_AIN1_AIN3 = 0x2 << ADS1115_MUX_SHIFT, - ADS1115_MUX_DIFF_AIN2_AIN3 = 0x3 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN0 = 0x4 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN1 = 0x5 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN2 = 0x6 << ADS1115_MUX_SHIFT, - ADS1115_MUX_GND_AIN3 = 0x7 << ADS1115_MUX_SHIFT, - ADS1115_MUX_MASK = 0x7 << ADS1115_MUX_SHIFT, -}; - -class ADS1115 { -public: - ADS1115(uint8_t address = 0x48); - - void begin(); - uint8_t trigger_sample(); - uint8_t reset(); - bool is_sample_in_progress(); - int16_t read_sample(); - float sample_to_float(int16_t val); - float read_sample_float(); - - void set_comp_queue(enum ads1115_comp_queue val) { set_config(val, ADS1115_COMP_QUEUE_MASK); } - void set_comp_latching(enum ads1115_comp_latch val) { set_config(val, ADS1115_COMP_LATCH_MASK); } - void set_comp_polarity(enum ads1115_comp_polarity val) { set_config(val, ADS1115_COMP_POLARITY_MASK); } - void set_comp_mode(enum ads1115_comp_mode val) { set_config(val, ADS1115_COMP_MODE_MASK); } - void set_data_rate(enum ads1115_data_rate val) { set_config(val, ADS1115_DATA_RATE_MASK); } - void set_mode(enum ads1115_mode val) { set_config(val, ADS1115_MODE_MASK); } - void set_pga(enum ads1115_pga val) { set_config(val, ADS1115_PGA_MASK); m_voltage_range = val >> ADS1115_PGA_SHIFT; } - void set_mux(enum ads1115_mux val) { set_config(val, ADS1115_MUX_MASK); } - -private: - void set_config(uint16_t val, uint16_t mask) { - m_config = (m_config & ~mask) | val; - } - - uint8_t write_register(uint8_t reg, uint16_t val); - uint16_t read_register(uint8_t reg); - - uint8_t m_address; - uint16_t m_config; - int m_voltage_range; -}; - - -enum ads1115_register { - ADS1115_REGISTER_CONVERSION = 0, - ADS1115_REGISTER_CONFIG = 1, - ADS1115_REGISTER_LOW_THRESH = 2, - ADS1115_REGISTER_HIGH_THRESH = 3, -}; - -#define FACTOR 32768.0 -static float ranges[] = { 6.144 / FACTOR, 4.096 / FACTOR, 2.048 / FACTOR, 1.024 / FACTOR, 0.512 / FACTOR, 0.256 / FACTOR}; - -ADS1115::ADS1115(uint8_t address) -{ - m_address = address; - m_config = ADS1115_COMP_QUEUE_AFTER_ONE | - ADS1115_COMP_LATCH_NO | - ADS1115_COMP_POLARITY_ACTIVE_LOW | - ADS1115_COMP_MODE_WINDOW | - ADS1115_DATA_RATE_128_SPS | - ADS1115_MODE_SINGLE_SHOT | - ADS1115_MUX_GND_AIN0; - set_pga(ADS1115_PGA_ONE); -} - -uint8_t ADS1115::write_register(uint8_t reg, uint16_t val) -{ - Wire.beginTransmission(m_address); - Wire.write(reg); - Wire.write(val>>8); - Wire.write(val & 0xFF); - return Wire.endTransmission(); -} - -uint16_t ADS1115::read_register(uint8_t reg) -{ - Wire.beginTransmission(m_address); - Wire.write(reg); - Wire.endTransmission(); - - uint8_t result = Wire.requestFrom((int)m_address, 2, 1); - if (result != 2) { - return 0; - } - - uint16_t val; - - val = Wire.read() << 8; - val |= Wire.read(); - return val; -} - -void ADS1115::begin() -{ - Wire.begin(); -} - -uint8_t ADS1115::trigger_sample() -{ - return write_register(ADS1115_REGISTER_CONFIG, m_config | SAMPLE_BIT); -} - -uint8_t ADS1115::reset() -{ - Wire.beginTransmission(0); - Wire.write(0x6); - return Wire.endTransmission(); -} - -bool ADS1115::is_sample_in_progress() -{ - uint16_t val = read_register(ADS1115_REGISTER_CONFIG); - return (val & SAMPLE_BIT) == 0; -} - -int16_t ADS1115::read_sample() -{ - return read_register(ADS1115_REGISTER_CONVERSION); -} - -float ADS1115::sample_to_float(int16_t val) -{ - return val * ranges[m_voltage_range]; -} - -float ADS1115::read_sample_float() -{ - return sample_to_float(read_sample()); -} - -ADS1115 adc; - -void ADS1115_init(void) { - - ads1115_up=0; - if (!i2c_flg) return; - - adc.begin(); - adc.set_data_rate(ADS1115_DATA_RATE_128_SPS); - adc.set_mode(ADS1115_MODE_CONTINUOUS); - adc.set_mux(ADS1115_MUX_DIFF_AIN0_AIN3); - adc.set_pga(ADS1115_PGA_TWO); - - int16_t val = adc.read_sample(); - ads1115_up=1; -} - -#endif - -char sml_start; -uint8_t dump2log=0; - -#define SML_SAVAILABLE Serial_available() -#define SML_SREAD Serial_read() -#define SML_SPEAK Serial_peek() - -bool Serial_available() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->available(); -} - -uint8_t Serial_read() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->read(); -} - -uint8_t Serial_peek() { - uint8_t num=dump2log&7; - if (num<1 || num>meters_used) num=1; - return meter_ss[num-1]->peek(); -} - -uint8_t sml_logindex; - -void Dump2log(void) { - -int16_t index=0,hcnt=0; -uint32_t d_lastms; -uint8_t dchars[16]; - - - - if (dump2log&8) { - - while (SML_SAVAILABLE) { - log_data[index]=':'; - index++; - log_data[index]=' '; - index++; - d_lastms=millis(); - while ((millis()-d_lastms)<40) { - if (SML_SAVAILABLE) { - uint8_t c=SML_SREAD; - sprintf(&log_data[index],"%02x ",c); - dchars[hcnt]=c; - index+=3; - hcnt++; - if (hcnt>15) { - - log_data[index]='='; - index++; - log_data[index]='>'; - index++; - log_data[index]=' '; - index++; - for (uint8_t ccnt=0; ccnt<16; ccnt++) { - if (isprint(dchars[ccnt])) { - log_data[index]=dchars[ccnt]; - } else { - log_data[index]=' '; - } - index++; - } - break; - } - } - } - if (index>0) { - log_data[index]=0; - AddLog(LOG_LEVEL_INFO); - index=0; - hcnt=0; - } - } - } else { - if (meter_desc_p[(dump2log&7)-1].type=='o') { - - while (SML_SAVAILABLE) { - char c=SML_SREAD&0x7f; - if (c=='\n' || c=='\r') { - log_data[sml_logindex]=0; - AddLog(LOG_LEVEL_INFO); - sml_logindex=2; - log_data[0]=':'; - log_data[1]=' '; - break; - } - log_data[sml_logindex]=c; - if (sml_logindex2) { - log_data[index]=0; - AddLog(LOG_LEVEL_INFO); - } - } - } -} - - -uint8_t *skip_sml(uint8_t *cp,int16_t *res) { - uint8_t len,len1,type; - len=*cp&0xf; - type=*cp&0x70; - if (type==0x70) { - - - cp++; - while (len--) { - len1=*cp&0x0f; - cp+=len1; - } - *res=0; - } else { - - *res=(signed char)*(cp+1); - cp+=len; - } - return cp; -} - - - -double sml_getvalue(unsigned char *cp,uint8_t index) { -uint8_t len,unit,type; -int16_t scaler,result; -int64_t value; -double dval; - - - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - - cp=skip_sml(cp,&result); - scaler=result; - - type=*cp&0x70; - len=*cp&0x0f; - cp++; - if (type==0x50 || type==0x60) { - - uint64_t uvalue=0; - uint8_t nlen=len; - while (--nlen) { - uvalue<<=8; - uvalue|=*cp++; - } - if (type==0x50) { - - switch (len-1) { - case 1: - - value=(signed char)uvalue; - break; - case 2: - -#ifdef DWS74_BUG - if (scaler==-2) { - value=(uint32_t)uvalue; - } else { - value=(int16_t)uvalue; - } -#else - value=(int16_t)uvalue; -#endif - break; - case 3: - case 4: - - value=(int32_t)uvalue; - break; - case 5: - case 6: - case 7: - case 8: - - value=(int64_t)uvalue; - break; - } - } else { - - value=uvalue; - } - - } else { - if (!(type&0xf0)) { - - - - if (len==9) { - - cp++; - uint32_t s1,s2; - s1=*cp<<16|*(cp+1)<<8|*(cp+2); - cp+=4; - s2=*cp<<16|*(cp+1)<<8|*(cp+2); - sprintf(&meter_id[index][0],"%u-%u",s1,s2); - } else { - - char *str=&meter_id[index][0]; - for (type=0; type= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - } - return rVal; -} - -uint8_t sb_counter; - - -double CharToDouble(const char *str) -{ - - char strbuf[24]; - - strlcpy(strbuf, str, sizeof(strbuf)); - char *pt = strbuf; - while ((*pt != '\0') && isblank(*pt)) { pt++; } - - signed char sign = 1; - if (*pt == '-') { sign = -1; } - if (*pt == '-' || *pt=='+') { pt++; } - - double left = 0; - if (*pt != '.') { - left = atoi(pt); - while (isdigit(*pt)) { pt++; } - } - - double right = 0; - if (*pt == '.') { - pt++; - right = atoi(pt); - while (isdigit(*pt)) { - pt++; - right /= 10.0; - } - } - - double result = left + right; - if (sign < 0) { - return -result; - } - return result; -} - - - -void ebus_esc(uint8_t *ebus_buffer, unsigned char len) { - short count,count1; - for (count=0; countavailable()) { - meter_ss[meters]->read(); - } -} - - -void sml_shift_in(uint32_t meters,uint32_t shard) { - uint32_t count; - if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p') { - - for (count=0; countread(); - - if (meter_desc_p[meters].type=='o') { - smltbuf[meters][SML_BSIZ-1]=iob&0x7f; - } else if (meter_desc_p[meters].type=='s') { - smltbuf[meters][SML_BSIZ-1]=iob; - } else if (meter_desc_p[meters].type=='r') { - smltbuf[meters][SML_BSIZ-1]=iob; - } else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M') { - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=9) { - SML_Decode(meters); - sml_empty_receiver(meters); - meter_spos[meters]=0; - } - } else if (meter_desc_p[meters].type=='p') { - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=7) { - SML_Decode(meters); - sml_empty_receiver(meters); - meter_spos[meters]=0; - } - } else { - if (iob==EBUS_SYNC) { - - - if (meter_spos[meters]>4+5) { - - uint8_t tlen=smltbuf[meters][4]+5; - - if (smltbuf[meters][tlen]=ebus_CalculateCRC(smltbuf[meters],tlen)) { - ebus_esc(smltbuf[meters],tlen); - SML_Decode(meters); - } else { - - - } - } - meter_spos[meters]=0; - return; - } - smltbuf[meters][meter_spos[meters]] = iob; - meter_spos[meters]++; - if (meter_spos[meters]>=SML_BSIZ) { - meter_spos[meters]=0; - } - } - sb_counter++; - if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p') SML_Decode(meters); -} - - - -void SML_Poll(void) { -uint32_t meters; - - for (meters=0; metersavailable()) { - sml_shift_in(meters,0); - } - } - } -} - - -void SML_Decode(uint8_t index) { - const char *mp=(const char*)meter_p; - int8_t mindex; - uint8_t *cp; - uint8_t dindex=0,vindex=0; - delay(0); - while (mp != NULL) { - - - - mindex=((*mp)&7)-1; - - if (mindex<0 || mindex>=meters_used) mindex=0; - mp+=2; - if (*mp=='=' && *(mp+1)=='h') { - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - - if (index!=mindex) goto nextsect; - - - cp=&smltbuf[mindex][0]; - - - if (*mp=='=') { - - mp++; - - if (*mp=='m' && !sb_counter) { - - - mp++; - while (*mp==' ') mp++; - - double dvar; - uint8_t opr; - uint32_t ind; - ind=atoi(mp); - while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>SML_MAX_VARS) ind=1; - dvar=meter_vars[ind-1]; - for (uint8_t p=0;p<5;p++) { - if (*mp=='@') { - - meter_vars[vindex]=dvar; - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - break; - } - opr=*mp; - mp++; - uint8_t iflg=0; - if (*mp=='#') { - iflg=1; - mp++; - } - ind=atoi(mp); - while (*mp>='0' && *mp<='9') mp++; - if (ind<1 || ind>SML_MAX_VARS) ind=1; - switch (opr) { - case '+': - if (iflg) dvar+=ind; - else dvar+=meter_vars[ind-1]; - break; - case '-': - if (iflg) dvar-=ind; - else dvar-=meter_vars[ind-1]; - break; - case '*': - if (iflg) dvar*=ind; - else dvar*=meter_vars[ind-1]; - break; - case '/': - if (iflg) dvar/=ind; - else dvar/=meter_vars[ind-1]; - break; - } - while (*mp==' ') mp++; - if (*mp=='@') { - - meter_vars[vindex]=dvar; - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - break; - } - } - } else if (*mp=='d') { - - if (dindex='0' && *mp<='9') mp++; - if (ind<1 || ind>SML_MAX_VARS) ind=1; - uint32_t delay=atoi(mp)*1000; - uint32_t dtime=millis()-dtimes[dindex]; - if (dtime>delay) { - - dtimes[dindex]=millis(); - double vdiff = meter_vars[ind-1]-dvalues[dindex]; - dvalues[dindex]=meter_vars[ind-1]; - meter_vars[vindex]=(double)360000.0*vdiff/((double)dtime/10000.0); - - mp=strchr(mp,'@'); - if (mp) { - mp++; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - } - } - dindex++; - } - } else if (*mp=='h') { - - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - } else { - - uint8_t found=1; - uint32_t ebus_dval=99; - float mbus_dval=99; - while (*mp!='@') { - if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') { - if (*mp++!=*cp++) { - found=0; - } - } else { - if (meter_desc_p[mindex].type=='s') { - - uint8_t val = hexnibble(*mp++) << 4; - val |= hexnibble(*mp++); - if (val!=*cp++) { - found=0; - } - } else { - - - if (*mp=='x' && *(mp+1)=='x') { - - mp+=2; - cp++; - } else if (!strncmp(mp,"UUuuUUuu",8)) { - uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); - ebus_dval=val; - mbus_dval=val; - mp+=8; - cp+=4; - } else if (*mp=='U' && *(mp+1)=='U' && *(mp+2)=='u' && *(mp+3)=='u'){ - uint16_t val = cp[1]|(cp[0]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (!strncmp(mp,"SSssSSss",8)) { - int32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); - ebus_dval=val; - mbus_dval=val; - mp+=8; - cp+=4; - } else if (*mp=='u' && *(mp+1)=='u' && *(mp+2)=='U' && *(mp+3)=='U'){ - uint16_t val = cp[0]|(cp[1]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (*mp=='u' && *(mp+1)=='u') { - uint8_t val = *cp++; - mbus_dval=val; - ebus_dval=val; - mp+=2; - } else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='S' && *(mp+3)=='S') { - int16_t val = *cp|(*(cp+1)<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } else if (*mp=='S' && *(mp+1)=='S' && *(mp+2)=='s' && *(mp+3)=='s') { - int16_t val = cp[1]|(cp[0]<<8); - mbus_dval=val; - ebus_dval=val; - mp+=4; - cp+=2; - } - else if (*mp=='s' && *(mp+1)=='s') { - int8_t val = *cp++; - mbus_dval=val; - ebus_dval=val; - mp+=2; - } - else if (!strncmp(mp,"ffffffff",8)) { - uint32_t val= (cp[0]<<24)|(cp[1]<<16)|(cp[2]<<8)|(cp[3]<<0); - float *fp=(float*)&val; - ebus_dval=*fp; - mbus_dval=*fp; - mp+=8; - cp+=4; - } - else if (!strncmp(mp,"FFffFFff",8)) { - - uint32_t val= (cp[1]<<0)|(cp[0]<<8)|(cp[3]<<16)|(cp[2]<<24); - float *fp=(float*)&val; - ebus_dval=*fp; - mbus_dval=*fp; - mp+=8; - cp+=4; - } - else if (!strncmp(mp,"eeeeee",6)) { - uint32_t val=(cp[0]<<16)|(cp[1]<<8)|(cp[2]<<0); - mbus_dval=val; - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"vvvvvv",6)) { - mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/10.0); - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"cccccc",6)) { - mbus_dval=(float)((cp[0]<<8)|(cp[1])) + ((float)cp[2]/100.0); - mp+=6; - cp+=3; - } - else if (!strncmp(mp,"pppp",4)) { - mbus_dval=(float)((cp[0]<<8)|cp[1]); - mp+=4; - cp+=2; - } - else { - uint8_t val = hexnibble(*mp++) << 4; - val |= hexnibble(*mp++); - if (val!=*cp++) { - found=0; - } - } - } - } - } - if (found) { - - mp++; - if (*mp=='#') { - - mp++; - if (meter_desc_p[mindex].type=='o') { - for (uint8_t p=0;p>=shift; - ebus_dval&=1; - mp+=2; - } - if (*mp=='i') { - - mp++; - uint8_t mb_index=strtol((char*)mp,(char**)&mp,10); - if (mb_index!=meter_desc_p[mindex].index) { - goto nextsect; - } - uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7); - if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect; - if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect; - dval=mbus_dval; - - mp++; - } else { - if (meter_desc_p[mindex].type=='p') { - uint8_t crc = SML_PzemCrc(&smltbuf[mindex][0],6); - if (crc!=smltbuf[mindex][6]) goto nextsect; - dval=mbus_dval; - } else { - dval=ebus_dval; - } - } - - } -#ifdef USE_SML_MEDIAN_FILTER - if (meter_desc_p[mindex].flag&16) { - meter_vars[vindex]=sml_median(&sml_mf[vindex],dval); - } else { - meter_vars[vindex]=dval; - } -#else - meter_vars[vindex]=dval; -#endif - - - double fac=CharToDouble((char*)mp); - meter_vars[vindex]/=fac; - SML_Immediate_MQTT((const char*)mp,vindex,mindex); - } - } - } -nextsect: - - if (vindex=meters_used) lastmind=0; - while (mp != NULL) { - - mindex=((*mp)&7)-1; - if (mindex<0 || mindex>=meters_used) mindex=0; - mp+=2; - if (*mp=='=' && *(mp+1)=='h') { - mp+=2; - - if (json) { - mp = strchr(mp, '|'); - if (mp) mp++; - continue; - } - - uint8_t i; - for (i=0;isml_counters[index].sml_debounce) { - RtcSettings.pulse_counter[index]++; - InjektCounterValue(sml_counters[index].sml_cnt_old_state,RtcSettings.pulse_counter[index]); - } - } else { - - sml_counters[index].sml_counter_ltime=millis(); - } -} - -void SML_CounterUpd1(void) { - SML_CounterUpd(0); -} - -void SML_CounterUpd2(void) { - SML_CounterUpd(1); -} - -void SML_CounterUpd3(void) { - SML_CounterUpd(2); -} - -void SML_CounterUpd4(void) { - SML_CounterUpd(3); -} - -#ifdef USE_SCRIPT -struct METER_DESC script_meter_desc[MAX_METERS]; -uint8_t *script_meter; -#endif - -#ifndef METER_DEF_SIZE -#define METER_DEF_SIZE 3000 -#endif - -bool Gpio_used(uint8_t gpiopin) { - for (uint16_t i=0;iM",-2,0); - if (meter_script==99) { - - if (script_meter) free(script_meter); - script_meter=0; - uint8_t *tp=0; - uint16_t index=0; - uint8_t section=0; - uint8_t srcpin=0; - char *lp=glob_script_mem.scriptptr; - sml_send_blocks=0; - while (lp) { - if (!section) { - if (*lp=='>' && *(lp+1)=='M') { - lp+=2; - meters_used=strtol(lp,0,10); - section=1; - uint32_t mlen=0; - for (uint32_t cnt=0;cnt') { - if (*(tp-1)=='|') *(tp-1)=0; - break; - } - if (*lp=='+') { - - - lp++; - index=*lp&7; - lp+=2; - if (index<1 || index>meters_used) goto next_line; - index--; - srcpin=strtol(lp,&lp,10); - if (Gpio_used(srcpin)) { - AddLog_P(LOG_LEVEL_INFO, PSTR("gpio rx double define!")); -dddef_exit: - if (script_meter) free(script_meter); - script_meter=0; - meters_used=METERS_USED; - goto init10; - } - script_meter_desc[index].srcpin=srcpin; - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].type=*lp; - lp+=2; - script_meter_desc[index].flag=strtol(lp,&lp,10); - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].params=strtol(lp,&lp,10); - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].prefix[7]=0; - for (uint32_t cnt=0; cnt<8; cnt++) { - if (*lp==SCRIPT_EOL || *lp==',') { - script_meter_desc[index].prefix[cnt]=0; - break; - } - script_meter_desc[index].prefix[cnt]=*lp++; - } - if (*lp==',') { - lp++; - script_meter_desc[index].trxpin=strtol(lp,&lp,10); - if (Gpio_used(script_meter_desc[index].trxpin)) { - AddLog_P(LOG_LEVEL_INFO, PSTR("gpio tx double define!")); - goto dddef_exit; - } - if (*lp!=',') goto next_line; - lp++; - script_meter_desc[index].tsecs=strtol(lp,&lp,10); - if (*lp==',') { - lp++; - char txbuff[256]; - uint32_t txlen=0,tx_entries=1; - for (uint32_t cnt=0; cntmeters_used) goto next_line; - while (1) { - if (*lp==SCRIPT_EOL) { - if (*(tp-1)!='|') *tp++='|'; - goto next_line; - } - *tp++=*lp++; - index++; - if (index>=METER_DEF_SIZE) break; - } - } - - } - -next_line: - if (*lp==SCRIPT_EOL) { - lp++; - } else { - lp = strchr(lp, SCRIPT_EOL); - if (!lp) break; - lp++; - } - } - *tp=0; - meter_desc_p=script_meter_desc; - meter_p=script_meter; - } -#endif - -init10: - typedef void (*function)(); - function counter_callbacks[] = {SML_CounterUpd1,SML_CounterUpd2,SML_CounterUpd3,SML_CounterUpd4}; - uint8_t cindex=0; - - for (byte i = 0; i < MAX_COUNTERS; i++) { - RtcSettings.pulse_counter[i]=Settings.pulse_counter[i]; - sml_counters[i].sml_cnt_last_ts=millis(); - } - for (uint8_t meters=0; metersbegin(meter_desc_p[meters].params)) { - meter_ss[meters]->flush(); - } - if (meter_ss[meters]->hardwareSerial()) { - if (meter_desc_p[meters].type=='M') { - Serial.begin(meter_desc_p[meters].params, SERIAL_8E1); - } - ClaimSerial(); - } - - } - } - -} - - -#ifdef USE_SML_SCRIPT_CMD -uint32_t SML_SetBaud(uint32_t meter, uint32_t br) { - if (meter<1 || meter>meters_used) return 0; - meter--; - if (!meter_ss[meter]) return 0; - if (meter_ss[meter]->begin(br)) { - meter_ss[meter]->flush(); - } - if (meter_ss[meter]->hardwareSerial()) { - if (meter_desc_p[meter].type=='M') { - Serial.begin(br, SERIAL_8E1); - } - } - return 1; -} - -uint32_t SML_Write(uint32_t meter,char *hstr) { - if (meter<1 || meter>meters_used) return 0; - meter--; - if (!meter_ss[meter]) return 0; - SML_Send_Seq(meter,hstr); - return 1; -} -#endif - - -void SetDBGLed(uint8_t srcpin, uint8_t ledpin) { - pinMode(ledpin, OUTPUT); - if (digitalRead(srcpin)) { - digitalWrite(ledpin,LOW); - } else { - digitalWrite(ledpin,HIGH); - } -} - - -void SML_Counter_Poll(void) { -uint16_t meters,cindex=0; -uint32_t ctime=millis(); - - for (meters=0; meters0) { - if (ctime-sml_counters[cindex].sml_cnt_last_ts>meter_desc_p[meters].params) { - sml_counters[cindex].sml_cnt_last_ts=ctime; - - if (meter_desc_p[meters].flag&2) { - -#ifdef ANALOG_OPTO_SENSOR - if (ads1115_up) { - int16_t val = adc.read_sample(); - if (val>sml_counters[cindex].ana_max) sml_counters[cindex].ana_max=val; - if (val10) { - sml_counters[cindex].sml_cnt_last_ts=ctime; -#ifdef DEBUG_CNT_LED1 - if (cindex==0) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED1); -#endif -#ifdef DEBUG_CNT_LED2 - if (cindex==1) SetDBGLed(meter_desc_p[meters].srcpin,DEBUG_CNT_LED2); -#endif - } - } - cindex++; - } - } -} - -#ifdef USE_SCRIPT -char *SML_Get_Sequence(char *cp,uint32_t index) { - if (!index) return cp; - uint32_t cindex=0; - while (cp) { - cp=strchr(cp,','); - if (cp) { - cp++; - cindex++; - if (cindex==index) { - return cp; - } - } - } -} - -void SML_Check_Send(void) { - sml_100ms_cnt++; - char *cp; - for (uint32_t cnt=sml_desc_cnt; cnt=0 && script_meter_desc[cnt].txmem) { - if ((sml_100ms_cnt%script_meter_desc[cnt].tsecs)==0) { - if (script_meter_desc[cnt].max_index>1) { - script_meter_desc[cnt].index++; - if (script_meter_desc[cnt].index>=script_meter_desc[cnt].max_index) { - script_meter_desc[cnt].index=0; - sml_desc_cnt++; - } - cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index); - - } else { - cp=script_meter_desc[cnt].txmem; - - sml_desc_cnt++; - } - - SML_Send_Seq(cnt,cp); - if (sml_desc_cnt>=meters_used) { - sml_desc_cnt=0; - } - break; - } - } else { - sml_desc_cnt++; - } - - if (sml_desc_cnt>=meters_used) { - sml_desc_cnt=0; - } - } -} - -uint8_t sml_hexnibble(char chr) { - uint8_t rVal = 0; - if (isdigit(chr)) { - rVal = chr - '0'; - } else { - if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A'; - if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a'; - } - return rVal; -} - - -void SML_Send_Seq(uint32_t meter,char *seq) { - uint8_t sbuff[32]; - uint8_t *ucp=sbuff,slen=0; - char *cp=seq; - while (*cp) { - if (!*cp || !*(cp+1)) break; - if (*cp==',') break; - uint8_t iob=(sml_hexnibble(*cp) << 4) | sml_hexnibble(*(cp+1)); - cp+=2; - *ucp++=iob; - slen++; - if (slen>=sizeof(sbuff)) break; - } - if (script_meter_desc[meter].type=='m' || script_meter_desc[meter].type=='M') { - *ucp++=0; - *ucp++=2; - - uint16_t crc = MBUS_calculateCRC(sbuff,6); - *ucp++=lowByte(crc); - *ucp++=highByte(crc); - slen+=4; - } - if (script_meter_desc[meter].type=='o') { - for (uint32_t cnt=0;cntwrite(sbuff,slen); -} -#endif - -uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) { - uint16_t crc, flag; - crc = 0xFFFF; - for (uint32_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint32_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { - crc >>= 1; - crc ^= 0xA001; - } else { - crc >>= 1; - } - } - } - return crc; -} - -uint8_t SML_PzemCrc(uint8_t *data, uint8_t len) { - uint16_t crc = 0; - for (uint32_t i = 0; i < len; i++) crc += *data++; - return (uint8_t)(crc & 0xFF); -} - - -uint8_t CalcEvenParity(uint8_t data) { -uint8_t parity=0; - - while(data) { - parity^=(data &1); - data>>=1; - } - return parity; -} -# 2361 "S:/Development/Tasmota/tasmota/xsns_53_sml.ino" -bool XSNS_53_cmd(void) { - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - char *cp=XdrvMailbox.data; - if (*cp=='d') { - - cp++; - uint8_t index=atoi(cp); - if ((index&7)>meters_used) index=1; - if (index>0 && meter_desc_p[(index&7)-1].type=='c') { - index=0; - } - dump2log=index; - ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log); - } else if (*cp=='c') { - - cp++; - uint8_t index=*cp&7; - if (index<1 || index>MAX_COUNTERS) index=1; - cp++; - while (*cp==' ') cp++; - if (isdigit(*cp)) { - uint32_t cval=atoi(cp); - while (isdigit(*cp)) cp++; - RtcSettings.pulse_counter[index-1]=cval; - uint8_t cindex=0; - for (uint8_t meters=0; metersaddress, INA226_REG_CALIBRATION, si->calibrationValue); - -} - - - - - - -bool Ina226TestPresence(uint8_t device) -{ - - - - uint16_t config = I2cRead16( slaveInfo[device].address, INA226_REG_CONFIG ); - - - if (config != slaveInfo[device].config) - return false; - - return true; - -} - -void Ina226ResetActive(void) -{ - Ina226SlaveInfo_t *p = slaveInfo; - - for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) { - p = &slaveInfo[i]; - - uint8_t addr = p->address; - if (addr) { - I2cResetActive(addr); - } - } -} - - - - - -void Ina226Init() -{ - uint32_t i; - - slavesFound = 0; - - Ina226SlaveInfo_t *p = slaveInfo; -# 215 "S:/Development/Tasmota/tasmota/xsns_54_ina226.ino" - for (i = 0; i < 4; i++){ - *p = {0}; - } - - - - - - for (i = 0; i < INA226_MAX_ADDRESSES; i++){ - uint8_t addr = pgm_read_byte(probeAddresses + i); - - if (I2cActive(addr)) { continue; } - - - - - if (!Settings.ina226_i_fs[i]) - continue; - - - - - - - if (!I2cWrite16( addr, INA226_REG_CONFIG, INA226_CONFIG_RESET)){ - - AddLog_P2( LOG_LEVEL_DEBUG, "No INA226 at address: %02X", addr); - continue; - } - - - - uint16_t config = I2cRead16( addr, INA226_REG_CONFIG ); - - - if (INA226_RES_CONFIG != config) - continue; - - - config = INA226_DEF_CONFIG; - - - if (!I2cWrite16( addr, INA226_REG_CONFIG, config)) - continue; - - - p = &slaveInfo[i]; - - p->address = addr; - - p->config = config; - - - p->i_lsb = (((float) Settings.ina226_i_fs[i])/10.0f)/32768.0f; - - - - uint32_t r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[i]); - - - - p->calibrationValue = ((uint16_t) (0.00512/(p->i_lsb * r_shunt_uohms/1000000.0f))); - - p->present = true; - - - Ina226SetCalibration(i); - - I2cSetActiveFound(addr, Ina226Str); - - slavesFound++; - } -} - - - - - -float Ina226ReadBus_v(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE); - - float result = ((float) reg_bus_v) * 0.00125f; - - return result; - -} - - - - - -float Ina226ReadShunt_i(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); - - float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb; - - return result; -} - - - - - -float Ina226ReadPower_w(uint8_t device) -{ - uint8_t addr = slaveInfo[device].address; - int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); - - float result = ((float) reg_shunt_i) * (slaveInfo[device].i_lsb * 25.0); - - return result; -} - - - - - - -void Ina226Read(uint8_t device) -{ - - voltages[device] = Ina226ReadBus_v(device); - currents[device] = Ina226ReadShunt_i(device); - powers[device] = Ina226ReadPower_w(device); - - - - -} - - - - - -void Ina226EverySecond() -{ - - for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){ - - if (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){ - Ina226Read(device); - } - else { - powers[device] = currents[device] = voltages[device] = 0.0f; - - - - - - - slaveInfo[device].present = false; - } - } -} - - - - - -bool Ina226CommandSensor() -{ - bool serviced = true; - bool show_config = false; - char param_str[64]; - char *cp, *params[4]; - uint8_t i, param_count, device, p1 = XdrvMailbox.payload; - uint32_t r_shunt_uohms; - uint16_t compact_r_shunt_uohms; - - - - - - if (XdrvMailbox.data_len > 62){ - return false; - } - - strncpy(param_str, XdrvMailbox.data, XdrvMailbox.data_len + 1); - param_str[XdrvMailbox.data_len] = 0; - - - for (cp = param_str, i = 0, param_count = 0; *cp && (i < XdrvMailbox.data_len + 1) && (param_count <= 3); i++) - if (param_str[i] == ' ' || param_str[i] == ',' || param_str[i] == 0){ - param_str[i] = 0; - params[param_count] = cp; - - param_count++; - cp = param_str + i + 1; - } - - - if (p1 < 10 || p1 >= 50){ - - switch (p1){ - case 1: - Ina226ResetActive(); - Ina226Init(); - Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound); - break; - - case 2: - restart_flag = 2; - Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag); - break; - - default: - serviced = false; - } - } - else if (p1 < 50){ - - device = (p1 / 10) - 1; - switch (p1 % 10){ - case 0: - show_config = true; - break; - - case 1: - r_shunt_uohms = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f); - - - - if (r_shunt_uohms > 32767){ - uint32_t r_shunt_mohms = r_shunt_uohms/1000UL; - Settings.ina226_r_shunt[device] = (uint16_t) (r_shunt_mohms | 0x8000); - } - else - Settings.ina226_r_shunt[device] = (uint16_t) r_shunt_uohms; - - - show_config = true; - break; - - case 2: - Settings.ina226_i_fs[device] = (uint16_t) ((CharToFloat(params[1])) * 10.0f); - - show_config = true; - break; - - - default: - serviced = false; - break; - } - } - else - serviced = false; - - if (show_config) { - char shunt_r_str[16]; - char fs_i_str[16]; - - - r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[device]); - dtostrfd(((float)r_shunt_uohms)/1000000.0f, 6, shunt_r_str); - - dtostrfd(((float)Settings.ina226_i_fs[device])/10.0f, 1, fs_i_str); - - Response_P(PSTR("{\"Sensor54-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"), - device + 1, shunt_r_str, fs_i_str); - } - - return serviced; -} - - - - - -#ifdef USE_WEBSERVER -const char HTTP_SNS_INA226_DATA[] PROGMEM = - "{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}" - "{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}" - "{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"; -#endif - -void Ina226Show(bool json) -{ - int i, num_found; - for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) { - - if (!slaveInfo[i].present) - continue; - - num_found++; - - char voltage[16]; - dtostrfd(voltages[i], Settings.flag2.voltage_resolution, voltage); - char current[16]; - dtostrfd(currents[i], Settings.flag2.current_resolution, current); - char power[16]; - dtostrfd(powers[i], Settings.flag2.wattage_resolution, power); - char name[16]; - snprintf_P(name, sizeof(name), PSTR("INA226%c%d"),IndexSeparator(), i + 1); - - - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%d,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - name, i, voltage, current, power); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, voltage); - DomoticzSensor(DZ_CURRENT, current); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_INA226_DATA, name, voltage, name, current, name, power); -#endif - } - - } - -} -# 546 "S:/Development/Tasmota/tasmota/xsns_54_ina226.ino" -bool Xsns54(byte callback_id) -{ - if (!I2cEnabled(XI2C_35)) { return false; } - - - bool result = false; - - - switch (callback_id) { - case FUNC_EVERY_SECOND: - Ina226EverySecond(); - break; - case FUNC_JSON_APPEND: - Ina226Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Ina226Show(0); - break; -#endif - case FUNC_COMMAND_SENSOR: - if (XSNS_54 == XdrvMailbox.index) { - result = Ina226CommandSensor(); - } - break; - case FUNC_INIT: - Ina226Init(); - break; - } - - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_55_hih_series.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_55_hih_series.ino" -#ifdef USE_I2C -#ifdef USE_HIH6 -# 33 "S:/Development/Tasmota/tasmota/xsns_55_hih_series.ino" -#define XSNS_55 55 -#define XI2C_36 36 - -#define HIH6_ADDR 0x27 - -struct HIH6 { - float temperature = 0; - float humidity = 0; - uint8_t valid = 0; - uint8_t type = 0; - char types[4] = "HIH"; -} Hih6; - -bool Hih6Read(void) -{ - Wire.beginTransmission(HIH6_ADDR); - if (Wire.endTransmission() != 0) { return false; } - - delay(40); - - uint8_t data[4]; - Wire.requestFrom(HIH6_ADDR, 4); - if (4 == Wire.available()) { - data[0] = Wire.read(); - data[1] = Wire.read(); - data[2] = Wire.read(); - data[3] = Wire.read(); - } else { return false; } - - - - Hih6.humidity = ConvertHumidity(((float)(((data[0] & 0x3F) << 8) | data[1]) * 100.0) / 16383.0); - - int temp = ((data[2] << 8) | (data[3] & 0xFC)) / 4; - Hih6.temperature = ConvertTemp(((float)temp / 16384.0) * 165.0 - 40.0); - - Hih6.valid = SENSOR_MAX_MISS; - return true; -} - - - -void Hih6Detect(void) -{ - if (I2cActive(HIH6_ADDR)) { return; } - - if (uptime < 2) { delay(20); } - Hih6.type = Hih6Read(); - if (Hih6.type) { - I2cSetActiveFound(HIH6_ADDR, Hih6.types); - } -} - -void Hih6EverySecond(void) -{ - if (uptime &1) { - - if (!Hih6Read()) { - AddLogMissed(Hih6.types, Hih6.valid); - } - } -} - -void Hih6Show(bool json) -{ - if (Hih6.valid) { - char temperature[33]; - dtostrfd(Hih6.temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Hih6.humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Hih6.types, temperature, humidity); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, Hih6.temperature); - KnxSensor(KNX_HUMIDITY, Hih6.humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Hih6.types, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Hih6.types, humidity); -#endif - } - } -} - - - - - -bool Xsns55(uint8_t function) -{ - if (!I2cEnabled(XI2C_36)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Hih6Detect(); - } - else if (Hih6.type) { - switch (function) { - case FUNC_EVERY_SECOND: - Hih6EverySecond(); - break; - case FUNC_JSON_APPEND: - Hih6Show(1); - break; - #ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Hih6Show(0); - break; - #endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_56_hpma.ino" -# 21 "S:/Development/Tasmota/tasmota/xsns_56_hpma.ino" -#ifdef USE_HPMA -# 31 "S:/Development/Tasmota/tasmota/xsns_56_hpma.ino" -#define XSNS_56 56 - -#include -#include - -TasmotaSerial *HpmaSerial; -HPMA115S0 *hpma115S0; - -uint8_t hpma_type = 1; -uint8_t hpma_valid = 0; - -struct hpmadata { - unsigned int pm10; - unsigned int pm2_5; -} hpma_data; - - - -void HpmaSecond(void) -{ - unsigned int pm2_5, pm10; - - - - - if (hpma115S0->ReadParticleMeasurement(&pm2_5, &pm10)) { - hpma_data.pm2_5 = pm2_5; - hpma_data.pm10 = pm10; - hpma_valid = 1; - } - -} - -void HpmaInit(void) -{ - hpma_type = 0; - if (pin[GPIO_HPMA_RX] < 99 && pin[GPIO_HPMA_TX] < 99) { - HpmaSerial = new TasmotaSerial(pin[GPIO_HPMA_RX], pin[GPIO_HPMA_TX], 1); - hpma115S0 = new HPMA115S0(*HpmaSerial); - - if (HpmaSerial->begin(9600)) { - if (HpmaSerial->hardwareSerial()) { - ClaimSerial(); - } - hpma_type = 1; - hpma115S0->Init(); - hpma115S0->StartParticleMeasurement(); - } - } -} - -#ifdef USE_WEBSERVER -const char HTTP_HPMA_SNS[] PROGMEM = - "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "2.5 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}" - "{s}HPMA " D_ENVIRONMENTAL_CONCENTRATION "10 " D_UNIT_MICROMETER "{m}%s " D_UNIT_MICROGRAM_PER_CUBIC_METER "{e}"; -#endif - -void HpmaShow(bool json) -{ - if (hpma_valid) { - char pm10[33]; - snprintf_P(pm10, 33, PSTR("%d"), hpma_data.pm10); - char pm2_5[33]; - snprintf_P(pm2_5, 33, PSTR("%d"), hpma_data.pm2_5); - - if (json) { - ResponseAppend_P(PSTR(",\"HPMA\":{\"PM2.5\":%d,\"PM10\":%d}"), hpma_data.pm2_5, hpma_data.pm10); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { - DomoticzSensor(DZ_VOLTAGE, pm2_5); - DomoticzSensor(DZ_CURRENT, pm10); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_HPMA_SNS, pm2_5, pm10); -#endif - } - } -} - - - - - -bool Xsns56(uint8_t function) -{ - bool result = false; - - if (hpma_type) { - switch (function) { - case FUNC_INIT: - HpmaInit(); - break; - case FUNC_EVERY_SECOND: - HpmaSecond(); - break; - case FUNC_COMMAND_SENSOR: - if (XSNS_56 == XdrvMailbox.index) { - return true; - } - break; - case FUNC_JSON_APPEND: - HpmaShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HpmaShow(0); - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_57_tsl2591.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_57_tsl2591.ino" -#ifdef USE_I2C -#ifdef USE_TSL2591 - - - - - - - -#define XSNS_57 57 -#define XI2C_40 40 - -#define TSL2591_ADDRESS 0x29 - -#include - -Adafruit_TSL2591 tsl = Adafruit_TSL2591(); - -uint8_t tsl2591_type = 0; -uint8_t tsl2591_valid = 0; -float tsl2591_lux = 0; - -void Tsl2591Init(void) -{ - - if (I2cSetDevice(0x29)) { - if (tsl.begin()) { - tsl.setGain(TSL2591_GAIN_MED); - tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS); - tsl2591_type = 1; - I2cSetActiveFound(TSL2591_ADDRESS, "TSL2591"); - } - } -} - -bool Tsl2591Read(void) -{ - uint32_t lum = tsl.getFullLuminosity(); - uint16_t ir, full; - ir = lum >> 16; - full = lum & 0xFFFF; - tsl2591_lux = tsl.calculateLux(full, ir); - tsl2591_valid = 1; -} - -void Tsl2591EverySecond(void) -{ - Tsl2591Read(); -} - -#ifdef USE_WEBSERVER -const char HTTP_SNS_TSL2591[] PROGMEM = - "{s}TSL2591 " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; -#endif - -void Tsl2591Show(bool json) -{ - if (tsl2591_valid) { - char lux_str[10]; - dtostrf(tsl2591_lux, sizeof(lux_str)-1, 3, lux_str); - if (json) { - ResponseAppend_P(PSTR(",\"TSL2591\":{\"" D_JSON_ILLUMINANCE "\":%s}"), lux_str); -#ifdef USE_DOMOTICZ - if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TSL2591, lux_str); -#endif - } - } -} - - - - - -bool Xsns57(uint8_t function) -{ - if (!I2cEnabled(XI2C_40)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Tsl2591Init(); - } - else if (tsl2591_type) { - switch (function) { - case FUNC_EVERY_SECOND: - Tsl2591EverySecond(); - break; - case FUNC_JSON_APPEND: - Tsl2591Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Tsl2591Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_58_dht12.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_58_dht12.ino" -#ifdef USE_I2C -#ifdef USE_DHT12 - - - - - - -#define XSNS_58 58 -#define XI2C_41 41 - -#define DHT12_ADDR 0x5C - -struct DHT12 { - float temperature = NAN; - float humidity = NAN; - uint8_t valid = 0; - uint8_t count = 0; - char name[6] = "DHT12"; -} Dht12; - -bool Dht12Read(void) -{ - if (Dht12.valid) { Dht12.valid--; } - - Wire.beginTransmission(DHT12_ADDR); - Wire.write(0); - if (Wire.endTransmission() != 0) { return false; } - - delay(50); - - Wire.requestFrom(DHT12_ADDR, 5); - delay(5); - uint8_t humidity = Wire.read(); - uint8_t humidityTenth = Wire.read(); - uint8_t temp = Wire.read(); - uint8_t tempTenth = Wire.read(); - uint8_t checksum = Wire.read(); - - Dht12.humidity = ConvertHumidity( (float) humidity + (float) humidityTenth/(float) 10.0 ); - Dht12.temperature = ConvertTemp( (float) temp + (float) tempTenth/(float) 10.0 ); - - if (isnan(Dht12.temperature) || isnan(Dht12.humidity)) { return false; } - - Dht12.valid = SENSOR_MAX_MISS; - return true; -} - - - -void Dht12Detect(void) -{ - if (I2cActive(DHT12_ADDR)) { return; } - - if (Dht12Read()) { - I2cSetActiveFound(DHT12_ADDR, Dht12.name); - Dht12.count = 1; - } -} - -void Dht12EverySecond(void) -{ - if (uptime &1) { - - if (!Dht12Read()) { - AddLogMissed(Dht12.name, Dht12.valid); - } - } -} - -void Dht12Show(bool json) -{ - if (Dht12.valid) { - char temperature[33]; - dtostrfd(Dht12.temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(Dht12.humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, Dht12.name, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, Dht12.temperature); - KnxSensor(KNX_HUMIDITY, Dht12.humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, Dht12.name, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, Dht12.name, humidity); -#endif - } - } -} - - - - - -bool Xsns58(uint8_t function) -{ - if (!I2cEnabled(XI2C_41)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - Dht12Detect(); - } - else if (Dht12.count) { - switch (function) { - case FUNC_EVERY_SECOND: - Dht12EverySecond(); - break; - case FUNC_JSON_APPEND: - Dht12Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - Dht12Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_59_ds1624.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_59_ds1624.ino" -#ifdef USE_I2C -#ifdef USE_DS1624 - - - - - - - -#define XSNS_59 59 -#define XI2C_42 42 - -#define DS1624_MEM_REGISTER 0x17 -#define DS1624_CONF_REGISTER 0xAC -#define DS1624_TEMP_REGISTER 0xAA -#define DS1624_START_REGISTER 0xEE -#define DS1624_STOP_REGISTER 0x22 - -#define DS1621_COUNTER_REGISTER 0xA8 -#define DS1621_SLOPE_REGISTER 0xA9 - -#define DS1621_CFG_1SHOT (1<<0) -#define DS1621_CFG_DONE (1<<7) - -enum { - DS1624_TYPE_DS1624, - DS1624_TYPE_DS1621 -}; - -#define DS1624_MAX_SENSORS 8 - -bool ds1624_init = false; - -struct { - float value; - uint8_t type; - int errcnt; - int misscnt; - bool valid; - char name[9]; -} ds1624_sns[DS1624_MAX_SENSORS]; - -uint32_t DS1624_Idx2Addr(uint32_t idx) { - return 0x48 + idx; -} - -int DS1624_Restart(uint8_t config, uint32_t idx) { - uint32_t addr = DS1624_Idx2Addr(idx); - if ((config & 1) == 1) { - config &= ~(DS1621_CFG_DONE|DS1621_CFG_1SHOT); - I2cWrite8(addr, DS1624_CONF_REGISTER, config); - delay(10); - AddLog_P2(LOG_LEVEL_ERROR, "%s addr %x is reset, reconfig: %x", ds1624_sns[idx].name, addr, config); - } - I2cValidRead(addr, DS1624_START_REGISTER, 1); -} - -void DS1624_HotPlugUp(uint32_t idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - - if (I2cActive(addr)) { return; } - if (!I2cSetDevice(addr)) { return; } - - uint8_t config; - if (I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { - uint8_t tmp; - ds1624_sns[idx].type = (I2cValidRead8(&tmp, addr, DS1624_MEM_REGISTER)) ? DS1624_TYPE_DS1624 : DS1624_TYPE_DS1621; - - snprintf_P(ds1624_sns[idx].name, sizeof(ds1624_sns[idx].name), PSTR("DS162%c%c%d"), - (ds1624_sns[idx].type == DS1624_TYPE_DS1621) ? '1' : '4', IndexSeparator(), idx); - I2cSetActiveFound(addr, ds1624_sns[idx].name); - - ds1624_sns[idx].valid = true; - ds1624_sns[idx].errcnt = 0; - ds1624_sns[idx].misscnt = 0; - DS1624_Restart(config,idx); - AddLog_P2(LOG_LEVEL_INFO, "Hot Plug %s addr %x config: %x", ds1624_sns[idx].name, addr, config); - } -} - -void DS1624_HotPlugDown(int idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - if (!I2cActive(addr)) { return; } - I2cResetActive(addr); - ds1624_sns[idx].valid = false; - AddLog_P2(LOG_LEVEL_INFO, "Hot UnPlug %s", ds1624_sns[idx].name); -} - -bool DS1624GetTemp(float *value, int idx) -{ - uint32_t addr = DS1624_Idx2Addr(idx); - - uint8_t config; - if (!I2cValidRead8(&config, addr, DS1624_CONF_REGISTER)) { - ds1624_sns[idx].misscnt++; - AddLog_P2(LOG_LEVEL_INFO, "%s device missing (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].misscnt); - return false; - } - ds1624_sns[idx].misscnt=0; - if (config & (DS1621_CFG_1SHOT|DS1621_CFG_DONE)) { - ds1624_sns[idx].errcnt++; - AddLog_P2(LOG_LEVEL_INFO, "%s config error, restart... (errors: %i)", ds1624_sns[idx].name, ds1624_sns[idx].errcnt); - DS1624_Restart(config, idx); - return false; - } - - uint16_t t; - if (!I2cValidRead16(&t, DS1624_Idx2Addr(idx), DS1624_TEMP_REGISTER)) { return false; } - if (ds1624_sns[idx].type == DS1624_TYPE_DS1624) { - *value = ((float)(int8_t)(t>>8)) + ((t>>4)&0xf)*0.0625; - } else { - - *value = ((float)(int8_t)(t>>8)); - uint8_t remain; - if (!I2cValidRead8(&remain, addr, DS1621_COUNTER_REGISTER)) { return true; } - uint8_t perc; - if (!I2cValidRead8(&perc, addr, DS1621_SLOPE_REGISTER)) { return true; } - float fix=(float)(perc - remain)/(float)perc; - *value+=fix; - } - ds1624_sns[idx].errcnt=0; - config &= ~(DS1621_CFG_DONE); - I2cWrite8(addr, DS1624_CONF_REGISTER, config); - return true; -} - -void DS1624HotPlugScan(void) -{ - uint16_t t; - - for (uint32_t idx = 0; idx < DS1624_MAX_SENSORS; idx++) { - uint32_t addr = DS1624_Idx2Addr(idx); - if (I2cActive(addr) && !ds1624_sns[idx].valid) { - continue; - } - if (ds1624_sns[idx].valid) { - if ((ds1624_sns[idx].misscnt>2)||(ds1624_sns[idx].errcnt>2)) { - DS1624_HotPlugDown(idx); - continue; - } - } - DS1624_HotPlugUp(idx); - } -} - -void DS1624EverySecond(void) -{ - float t; - for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { - if (!ds1624_sns[i].valid) { continue; } - if (!DS1624GetTemp(&t, i)) { continue; } - ds1624_sns[i].value = ConvertTemp(t); - } -} - -void DS1624Show(bool json) -{ - char temperature[33]; - bool once = true; - - for (uint32_t i = 0; i < DS1624_MAX_SENSORS; i++) { - if (!ds1624_sns[i].valid) { continue; } - - dtostrfd(ds1624_sns[i].value, Settings.flag2.temperature_resolution, temperature); - if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds1624_sns[i].name, temperature); - if ((0 == tele_period) && once) { -#ifdef USE_DOMOTICZ - DomoticzSensor(DZ_TEMP, temperature); -#endif -#ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, temperature); -#endif - once = false; - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, ds1624_sns[i].name, temperature, TempUnit()); -#endif - } - } -} - - - - - -bool Xsns59(uint8_t function) -{ - if (!I2cEnabled(XI2C_42)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - if (!ds1624_init) { - memset(ds1624_sns, 0, sizeof(ds1624_sns)); - ds1624_init = true; - DS1624HotPlugScan(); - } - } - switch (function) { - case FUNC_HOTPLUG_SCAN: - DS1624HotPlugScan(); - break; - case FUNC_EVERY_SECOND: - DS1624EverySecond(); - break; - case FUNC_JSON_APPEND: - DS1624Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - DS1624Show(0); - break; -#endif - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_60_GPS.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_60_GPS.ino" -#ifdef USE_GPS -# 113 "S:/Development/Tasmota/tasmota/xsns_60_GPS.ino" -#define XSNS_60 60 - -#include "NTPServer.h" -#include "NTPPacket.h" - - - - - -#define D_CMND_UBX "UBX" - -const char S_JSON_UBX_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_UBX "%s\":%d}"; - -const char kUBXTypes[] PROGMEM = "UBX"; - -#define UBX_LAT_LON_THRESHOLD 1000 - -#define UBX_SERIAL_BUFFER_SIZE 256 -#define UBX_TCP_PORT 1234 - - - - - -const char UBLOX_INIT[] PROGMEM = { - - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, - 0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, - - - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x92, - - - - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5, - 0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x21,0x00,0x01,0x00,0x00,0x00,0x00,0x32,0x97, - - - - - - -}; - -char UBX_name[4]; - -struct UBX_t { - const char UBX_HEADER[2] = { 0xB5, 0x62 }; - const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; - const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; - const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; - - struct entry_t { - int32_t lat; - int32_t lon; - uint32_t time; - }; - - union { - entry_t values; - uint8_t bytes[sizeof(entry_t)]; - } rec_buffer; - - struct POLL_MSG { - uint8_t cls; - uint8_t id; - uint16_t zero; - }; - - struct NAV_POSLLH { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - int32_t lon; - int32_t lat; - int32_t alt; - int32_t hMSL; - uint32_t hAcc; - uint32_t vAcc; - }; - - struct NAV_STATUS { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - uint8_t gpsFix; - uint8_t flags; - uint8_t fixStat; - uint8_t flags2; - uint32_t ttff; - uint32_t msss; - }; - - struct NAV_TIME_UTC { - uint8_t cls; - uint8_t id; - uint16_t len; - uint32_t iTOW; - uint32_t tAcc; - int32_t nano; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; - struct { - uint8_t UTC:1; - uint8_t WKN:1; - uint8_t TOW:1; - uint8_t padding:5; - } valid; - }; - - struct CFG_RATE { - uint8_t cls; - uint8_t id; - uint16_t len; - uint16_t measRate; - uint16_t navRate; - uint16_t timeRef; - char CK[2]; - }; - - struct { - uint32_t last_iTOW; - int32_t last_alt; - uint32_t last_hAcc; - uint32_t last_vAcc; - uint8_t gpsFix; - uint8_t non_empty_loops; - uint16_t log_interval; - } state; - - struct { - uint32_t init:1; - uint32_t filter_noise:1; - uint32_t send_when_new:1; - uint32_t send_UI_only:1; - uint32_t runningNTP:1; - uint32_t forceUTCupdate:1; - uint32_t runningVPort:1; - - } mode; - - union { - NAV_POSLLH navPosllh; - NAV_STATUS navStatus; - NAV_TIME_UTC navTime; - POLL_MSG pollMsg; - CFG_RATE cfgRate; - } Message; - - uint8_t TCPbuf[UBX_SERIAL_BUFFER_SIZE]; - size_t TCPbufSize; -} UBX; - -enum UBXMsgType { - MT_NONE, - MT_NAV_POSLLH, - MT_NAV_STATUS, - MT_NAV_TIME, - MT_POLL -}; - -#ifdef USE_FLOG -FLOG *Flog = nullptr; -#endif -TasmotaSerial *UBXSerial; - -NtpServer timeServer(PortUdp); - -WiFiServer vPortServer(UBX_TCP_PORT); -WiFiClient vPortClient; - - - - - -void UBXcalcChecksum(char* CK, size_t msgSize) -{ - memset(CK, 0, 2); - for (int i = 0; i < msgSize; i++) { - CK[0] += ((char*)(&UBX.Message))[i]; - CK[1] += CK[0]; - } -} - -bool UBXcompareMsgHeader(const char* msgHeader) -{ - char* ptr = (char*)(&UBX.Message); - return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; -} - -void UBXinitCFG(void) -{ - for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { - UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); - } - DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); -} - -void UBXTriggerTele(void) -{ - mqtt_data[0] = '\0'; - if (MqttShowSensor()) { - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); -#ifdef USE_RULES - RulesTeleperiod(); -#endif - } -} - - - -void UBXDetect(void) -{ - UBX.mode.init = 0; - if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { - UBXSerial = new TasmotaSerial(pin[GPIO_GPS_RX], pin[GPIO_GPS_TX], 1, 0, UBX_SERIAL_BUFFER_SIZE); - if (UBXSerial->begin(9600)) { - DEBUG_SENSOR_LOG(PSTR("UBX: started serial")); - if (UBXSerial->hardwareSerial()) { - ClaimSerial(); - DEBUG_SENSOR_LOG(PSTR("UBX: claim HW")); - } - } - } - else { - return; - } - - UBXinitCFG(); - UBX.mode.init = 1; - -#ifdef USE_FLOG - if (!Flog) { - Flog = new FLOG; - Flog->init(); - } -#endif - - UBX.state.log_interval = 10; - UBX.mode.send_UI_only = true; - UBXTriggerTele(); -} - -uint32_t UBXprocessGPS() -{ - static uint32_t fpos = 0; - static char checksum[2]; - static uint8_t currentMsgType = MT_NONE; - static size_t payloadSize = sizeof(UBX.Message); - - - uint32_t data_bytes = 0; - while ( UBXSerial->available() ) { - data_bytes++; - byte c = UBXSerial->read(); - if (UBX.mode.runningVPort){ - UBX.TCPbuf[data_bytes-1] = c; - UBX.TCPbufSize = data_bytes; - } - if ( fpos < 2 ) { - - if ( c == UBX.UBX_HEADER[fpos] ) { - fpos++; - } else { - fpos = 0; - } - } else { - - - - - - if ( (fpos-2) < payloadSize ) { - ((char*)(&UBX.Message))[fpos-2] = c; - } - fpos++; - - if ( fpos == 4 ) { - - - if ( UBXcompareMsgHeader(UBX.NAV_POSLLH_HEADER) ) { - currentMsgType = MT_NAV_POSLLH; - payloadSize = sizeof(UBX_t::NAV_POSLLH); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_POSLLH")); - } - else if ( UBXcompareMsgHeader(UBX.NAV_STATUS_HEADER) ) { - currentMsgType = MT_NAV_STATUS; - payloadSize = sizeof(UBX_t::NAV_STATUS); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_STATUS")); - } - else if ( UBXcompareMsgHeader(UBX.NAV_TIME_HEADER) ) { - currentMsgType = MT_NAV_TIME; - payloadSize = sizeof(UBX_t::NAV_TIME_UTC); - DEBUG_SENSOR_LOG(PSTR("UBX: got NAV_TIME_UTC")); - } - else { - - fpos = 0; - continue; - } - } - - if ( fpos == (payloadSize+2) ) { - - - UBXcalcChecksum(checksum, payloadSize); - } - else if ( fpos == (payloadSize+3) ) { - - - if ( c != checksum[0] ) { - - fpos = 0; - } - } - else if ( fpos == (payloadSize+4) ) { - - - fpos = 0; - if ( c == checksum[1] ) { - - return currentMsgType; - } - } - else if ( fpos > (payloadSize+4) ) { - - - fpos = 0; - } - } - } - - if (data_bytes!=0) { - UBX.state.non_empty_loops++; - DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); - } else { - UBX.state.non_empty_loops = 0; - } - return MT_NONE; -} - - - - - -#ifdef USE_FLOG -void UBXsendHeader(void) -{ - WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); - WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); - WSSend(200, CT_STREAM, F( - "\r\n" - "\r\n" - "\r\n\r\n")); -} - -void UBXsendRecord(uint8_t *buf) -{ - char record[100]; - char stime[32]; - UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; - snprintf_P(stime, sizeof(stime), GetDT(entry->time).c_str()); - char lat[12]; - char lon[12]; - dtostrfd((double)entry->lat/10000000.0f,7,lat); - dtostrfd((double)entry->lon/10000000.0f,7,lon); - snprintf_P(record, sizeof(record),PSTR("\n\t\n\n"),lat ,lon, stime); - - WebServer->sendContent_P(record); -} - -void UBXsendFooter(void) -{ - WebServer->sendContent(F("\n\n")); - WebServer->sendContent(""); - Rtc.user_time_entry = false; -} - - - -void UBXsendFile(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); -} -#endif - - - -void UBXSetRate(uint16_t interval) -{ - UBX.Message.cfgRate.cls = 0x06; - UBX.Message.cfgRate.id = 0x08; - UBX.Message.cfgRate.len = 6; - uint32_t measRate = (1000*(uint32_t)interval); - if (measRate > 0xffff) { - measRate = 0xffff; - } - UBX.Message.cfgRate.measRate = (uint16_t)measRate; - UBX.Message.cfgRate.navRate = 1; - UBX.Message.cfgRate.timeRef = 1; - UBXcalcChecksum(UBX.Message.cfgRate.CK, sizeof(UBX.Message.cfgRate)-sizeof(UBX.Message.cfgRate.CK)); - DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); - UBXSerial->write(UBX.UBX_HEADER[0]); - UBXSerial->write(UBX.UBX_HEADER[1]); - for (uint32_t i =0; iwrite(((uint8_t*)(&UBX.Message.cfgRate))[i]); - DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); - } - UBX.state.log_interval = 10*interval; -} - -void UBXSelectMode(uint16_t mode) -{ - DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); - switch(mode){ -#ifdef USE_FLOG - case 0: - Flog->mode = 0; - break; - case 1: - Flog->mode = 1; - break; - case 2: - UBX.mode.filter_noise = true; - break; - case 3: - UBX.mode.filter_noise = false; - break; - case 4: - Flog->startRecording(true); - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - appending")); - break; - case 5: - Flog->startRecording(false); - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: start recording - new log")); - break; - case 6: - if(Flog->recording == true){ - Flog->stopRecording(); - } - AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: stop recording")); - break; -#endif - case 7: - UBX.mode.send_when_new = 1; - break; - case 8: - UBX.mode.send_when_new = 0; - break; - case 9: - if (timeServer.beginListening()) { - UBX.mode.runningNTP = true; - } - break; - case 10: - UBX.mode.runningNTP = false; - break; - case 11: - UBX.mode.forceUTCupdate = true; - break; - case 12: - UBX.mode.forceUTCupdate = false; - break; - case 13: - Settings.latitude = UBX.rec_buffer.values.lat/10; - Settings.longitude = UBX.rec_buffer.values.lon/10; - break; - case 14: - vPortServer.begin(); - UBX.mode.runningVPort = 1; - break; - case 15: - - UBX.mode.runningVPort = 0; - break; - default: - if (mode>1000 && mode <1066) { - - UBXSetRate(mode-1000); - } - break; - } - UBX.mode.send_UI_only = true; - UBXTriggerTele(); -} - - - -bool UBXHandlePOSLLH() -{ - DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); - if (UBX.state.gpsFix>1) { - if (UBX.mode.filter_noise) { - if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat6) { - if(UBX.mode.runningVPort) return; - UBXinitCFG(); - AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); - UBXSerial->flush(); - UBX.state.non_empty_loops = 0; - } -} - - - -void UBXLoop50msec(void) -{ - - if (UBX.mode.runningVPort){ - if(!vPortClient.connected()) { - vPortClient = vPortServer.available(); - } - while(vPortClient.available()) { - byte _newByte = vPortClient.read(); - UBXSerial->write(_newByte); - } - - if (UBX.TCPbufSize!=0){ - vPortClient.write((char*)UBX.TCPbuf, UBX.TCPbufSize); - UBX.TCPbufSize = 0; - } - } - - if(UBX.mode.runningNTP){ - timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000); - } -} - -void UBXLoop(void) -{ - static uint16_t counter; - static bool new_position; - - uint32_t msgType = UBXprocessGPS(); - - switch(msgType){ - case MT_NAV_POSLLH: - new_position = UBXHandlePOSLLH(); - break; - case MT_NAV_STATUS: - UBXHandleSTATUS(); - break; - case MT_NAV_TIME: - UBXHandleTIME(); - break; - default: - UBXHandleOther(); - break; - } - -#ifdef USE_FLOG - if (counter>UBX.state.log_interval) { - if (Flog->recording && new_position) { - UBX.rec_buffer.values.time = Rtc.local_time; - Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); - counter = 0; - } - } -#endif - - counter++; -} - - - - -#ifdef USE_WEBSERVER - - -#ifdef USE_FLOG -#ifdef DEBUG_TASMOTA_SENSOR - const char HTTP_SNS_FLOGVER[] PROGMEM = "{s}
{m}
{e}{s} FLOG with %u sectors: {m}%u bytes{e}" - "{s} FLOG next sector for REC: {m} %u {e}" - "{s} %u sector(s) with data at sector: {m} %u {e}"; - const char HTTP_SNS_FLOGREC[] PROGMEM = "{s} RECORDING (bytes in buffer) {m}%u{e}"; -#endif - - const char HTTP_SNS_FLOG[] PROGMEM = "{s}
{m}
{e}{s} Flash-Log {m} %s{e}"; - const char kFLOG_STATE0[] PROGMEM = "ready"; - const char kFLOG_STATE1[] PROGMEM = "recording"; - const char * kFLOG_STATE[] ={kFLOG_STATE0, kFLOG_STATE1}; - - const char HTTP_BTN_FLOG_DL[] PROGMEM = ""; - -#endif - const char HTTP_SNS_NTPSERVER[] PROGMEM = "{s} NTP server {m}active{e}"; - - const char HTTP_SNS_GPS[] PROGMEM = "{s} GPS latitude {m}%s{e}" - "{s} GPS longitude {m}%s{e}" - "{s} GPS altitude {m}%s m{e}" - "{s} GPS hor. Accuracy {m}%s m{e}" - "{s} GPS vert. Accuracy {m}%s m{e}" - "{s} GPS sat-fix status {m}%s{e}"; - - const char kGPSFix0[] PROGMEM = "no fix"; - const char kGPSFix1[] PROGMEM = "dead reckoning only"; - const char kGPSFix2[] PROGMEM = "2D-fix"; - const char kGPSFix3[] PROGMEM = "3D-fix"; - const char kGPSFix4[] PROGMEM = "GPS + dead reckoning combined"; - const char kGPSFix5[] PROGMEM = "Time only fix"; - const char * kGPSFix[] PROGMEM ={kGPSFix0, kGPSFix1, kGPSFix2, kGPSFix3, kGPSFix4, kGPSFix5}; - - - - -#endif - - - -void UBXShow(bool json) -{ - char lat[12]; - char lon[12]; - char alt[12]; - char hAcc[12]; - char vAcc[12]; - dtostrfd((double)UBX.rec_buffer.values.lat/10000000.0f,7,lat); - dtostrfd((double)UBX.rec_buffer.values.lon/10000000.0f,7,lon); - dtostrfd((double)UBX.state.last_alt/1000.0f,3,alt); - dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); - dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); - - if (json) { - ResponseAppend_P(PSTR(",\"GPS\":{")); - if (UBX.mode.send_UI_only) { - uint32_t i = UBX.state.log_interval / 10; - ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i); - } else { - ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"alt\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, alt, hAcc, vAcc); - } -#ifdef USE_FLOG - ResponseAppend_P(PSTR(",\"FLOG\":{\"rec\":%u,\"mode\":%u,\"sec\":%u}"), Flog->recording, Flog->mode, Flog->sectors_left); -#endif - UBX.mode.send_UI_only = false; -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_GPS, lat, lon, alt, hAcc, vAcc, kGPSFix[UBX.state.gpsFix]); - -#ifdef DEBUG_TASMOTA_SENSOR -#ifdef USE_FLOG - WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); - if (Flog->recording) { - WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); - } -#endif -#endif -#ifdef USE_FLOG - if (Flog->ready) { - WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); - } - if (!Flog->recording && Flog->found_saved_data) { - WSContentSend_P(HTTP_BTN_FLOG_DL); - } -#endif - if (UBX.mode.runningNTP) { - WSContentSend_P(HTTP_SNS_NTPSERVER); - } -#endif - } -} - - - - - -bool UBXCmd(void) -{ - bool serviced = true; - if (XdrvMailbox.data_len > 0) { - UBXSelectMode(XdrvMailbox.payload); - Response_P(S_JSON_UBX_COMMAND_NVALUE, XdrvMailbox.command, XdrvMailbox.payload); - } - return serviced; -} - - - - - -bool Xsns60(uint8_t function) -{ - bool result = false; - - if (FUNC_INIT == function) { - UBXDetect(); - } - - if (UBX.mode.init) { - switch (function) { - case FUNC_COMMAND_SENSOR: - if (XSNS_60 == XdrvMailbox.index) { - result = UBXCmd(); - } - break; - case FUNC_EVERY_50_MSECOND: - UBXLoop50msec(); - break; - case FUNC_EVERY_100_MSECOND: -#ifdef USE_FLOG - if (!Flog->running_download) -#endif - { - UBXLoop(); - } - break; -#ifdef USE_FLOG - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/UBX", UBXsendFile); - break; -#endif - case FUNC_JSON_APPEND: - UBXShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: -#ifdef USE_FLOG - if (!Flog->running_download) -#endif - { - UBXShow(0); - } - break; -#endif - } - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -# 38 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -#ifdef USE_SPI -#ifdef USE_NRF24 -#ifdef USE_MIBLE - -#ifdef DEBUG_TASMOTA_SENSOR - #define MINRF_LOG_BUFFER(x) MINRFshowBuffer(x); -#else - #define MINRF_LOG_BUFFER(x) -#endif -# 56 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -#define XSNS_61 61 - -#include - -#define FLORA 1 -#define MJ_HT_V1 2 -#define LYWSD02 3 -#define LYWSD03 4 -#define CGG1 5 - -const uint16_t kMINRFSlaveID[5]={ 0x0098, - 0x01aa, - 0x045b, - 0x055b, - 0x0347 - }; - -const char kMINRFSlaveType1[] PROGMEM = "Flora"; -const char kMINRFSlaveType2[] PROGMEM = "MJ_HT_V1"; -const char kMINRFSlaveType3[] PROGMEM = "LYWSD02"; -const char kMINRFSlaveType4[] PROGMEM = "LYWSD03"; -const char kMINRFSlaveType5[] PROGMEM = "CGG1"; -const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4,kMINRFSlaveType5}; - - -const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; -const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; -const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71da7646}; - -const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; -const uint32_t kMINRFCGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; - - -const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; -const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; - - -#pragma pack(1) -struct MJ_HT_V1Header_t { - uint8_t padding[3]; - uint8_t mesSize; - uint8_t padding2; - uint16_t uuid; - uint16_t type; - uint8_t padding3[2]; - uint8_t counter; - uint8_t serial[6]; - uint8_t mode; - uint8_t padding5; - uint8_t effectiveDataLength; - }; - -struct FlowerHeader_t { - uint8_t padding[4]; - uint8_t padding2; - uint16_t uuid; - uint8_t mesSize; - uint8_t padding22; - uint16_t uuid2; - uint16_t type; - uint8_t padding3[2]; - uint8_t counter; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - }; - -union floraPacket_t { - struct { - uint16_t idWord; - uint8_t padding; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint16_t data; - } T; - struct { - uint16_t idWord; - uint8_t padding; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint32_t data:24; - } L; - struct { - uint8_t padding[3]; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint8_t data; - } M; - struct { - uint8_t padding[3]; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint16_t data; - } F; -}; - -union MJ_HT_V1Packet_t { - struct { - uint16_t idWord; - uint8_t padding; - uint8_t serial[6]; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint16_t temp; - uint16_t hum; - } TH; - struct { - uint8_t padding[3]; - uint8_t serial[6]; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint8_t battery; - } B; - -}; - -union LYWSD02Packet_t { - struct { - uint16_t idWord; - uint8_t padding; - uint8_t serial[6]; - uint8_t padding4; - uint8_t mode; - uint8_t valueTen; - uint8_t effectiveDataLength; - uint16_t data; - } TH; -}; - -struct bleAdvPacket_t { - uint8_t pduType; - uint8_t payloadSize; - uint8_t mac[6]; - union { - uint8_t payload[24]; - MJ_HT_V1Header_t header; - FlowerHeader_t flowerHeader; - struct { - uint8_t padding[21]; - uint16_t temp; - uint8_t hum_lb; - } TH; - struct { - uint8_t padding[21]; - uint16_t temp; - } T; - struct { - uint8_t padding[21]; - uint16_t hum; - } H; - struct { - uint8_t padding[21]; - uint8_t battery; - } B; - struct { - uint8_t padding[2]; - uint8_t mode; - uint16_t size; - uint16_t data; - } F_T; - struct { - uint8_t padding[2]; - uint8_t mode; - uint16_t size; - uint16_t data; - uint8_t data2; - } F_L; - struct { - uint8_t padding[2]; - uint8_t mode; - uint16_t size; - uint8_t data; - } F_M; - struct { - uint8_t padding[2]; - uint8_t mode; - uint16_t size; - uint16_t data; - } F_F; - }; -}; - -union FIFO_t{ - bleAdvPacket_t bleAdv; - floraPacket_t floraPacket; - MJ_HT_V1Packet_t MJ_HT_V1Packet; - LYWSD02Packet_t LYWSD02Packet; - uint8_t raw[32]; -}; - -#pragma pack(0) - -struct { - const uint8_t channel[3] = {37,38,39}; - const uint8_t frequency[3] = { 2,26,80}; - - uint16_t timer; - uint8_t currentChan=0; - FIFO_t buffer; - uint8_t packetMode; - -#ifdef DEBUG_TASMOTA_SENSOR - uint8_t streamBuffer[sizeof(buffer)]; - uint8_t lsfrBuffer[sizeof(buffer)]; -#endif - -} MINRF; - -struct mi_sensor_t{ - uint8_t type; - uint8_t serial[6]; - uint8_t showedUp; - float temp; - union { - struct { - float moisture; - float fertility; - uint32_t lux; - }; - struct { - float hum; - uint8_t bat; - }; - }; -}; - -std::vector MIBLEsensors; - - - - -bool MINRFinitBLE(uint8_t _mode) -{ - if (MINRF.timer%1000 == 0){ - NRF24radio.begin(pin[GPIO_SPI_CS],pin[GPIO_SPI_DC]); - NRF24radio.setAutoAck(false); - NRF24radio.setDataRate(RF24_1MBPS); - NRF24radio.disableCRC(); - NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); - NRF24radio.setRetries(0,0); - NRF24radio.setPALevel(RF24_PA_MIN); - NRF24radio.setAddressWidth(4); - - - NRF24radio.powerUp(); - } - if(NRF24radio.isChipConnected()){ - - MINRFchangePacketModeTo(_mode); - return true; - } - - return false; -} - -void MINRFhopChannel() -{ - MINRF.currentChan++; - if(MINRF.currentChan >= sizeof(MINRF.channel)) { - MINRF.currentChan = 0; - } - NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] ); -} - - - - - - - -bool MINRFreceivePacket(void) -{ - if(!NRF24radio.available()) { - return false; - } - while(NRF24radio.available()) { - - - NRF24radio.read( &MINRF.buffer, sizeof(MINRF.buffer) ); -#ifdef DEBUG_TASMOTA_SENSOR - memcpy(&MINRF.streamBuffer, &MINRF.buffer, sizeof(MINRF.buffer)); -#endif - MINRFswapbuf( sizeof(MINRF.buffer) ); - - - - switch (MINRF.packetMode) { - case 0: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40); - break; - case 1: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); - break; - case 2: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); - break; - case 3: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_A[MINRF.currentChan]); - break; - case 4: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); - break; - case 5: - MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); - break; - } - - - } - - return true; -} - -#ifdef DEBUG_TASMOTA_SENSOR -void MINRFshowBuffer(uint8_t (&buf)[32]){ - - - - - DEBUG_SENSOR_LOG(PSTR("MINRF: Buffer: %02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x ") - ,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11], - buf[12],buf[13],buf[14],buf[15],buf[16],buf[17],buf[18],buf[19],buf[20],buf[21],buf[22],buf[23], - buf[24],buf[25],buf[26],buf[27],buf[28],buf[29],buf[30],buf[31] - ); -} -#endif - - - - - - -void MINRFswapbuf(uint8_t len) -{ - uint8_t* buf = (uint8_t*)&MINRF.buffer; - while(len--) { - uint8_t a = *buf; - uint8_t v = 0; - if (a & 0x80) v |= 0x01; - if (a & 0x40) v |= 0x02; - if (a & 0x20) v |= 0x04; - if (a & 0x10) v |= 0x08; - if (a & 0x08) v |= 0x10; - if (a & 0x04) v |= 0x20; - if (a & 0x02) v |= 0x40; - if (a & 0x01) v |= 0x80; - *(buf++) = v; - } -} -# 430 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr) -{ - while(len--) { - uint8_t res = 0; - - for (uint8_t i = 1; i; i <<= 1) { - if (lfsr & 0x01) { - lfsr ^= 0x88; - res |= i; - } - lfsr >>= 1; - } - *(buf++) ^= res; -#ifdef DEBUG_TASMOTA_SENSOR - MINRF.lsfrBuffer[31-len] = lfsr; -#endif - } -} - -void MINRFreverseMAC(uint8_t _mac[]){ - uint8_t _reversedMAC[6]; - for (uint8_t i=0; i<6; i++){ - _reversedMAC[5-i] = _mac[i]; - } - memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); -} - - - - - - -void MINRFchangePacketModeTo(uint8_t _mode) { - uint32_t (_nextchannel) = MINRF.currentChan+1; - if (_nextchannel>2) _nextchannel=0; - - switch(_mode){ - case 0: - NRF24radio.openReadingPipe(0,0x6B7D9171); - break; - case 1: - NRF24radio.openReadingPipe(0,kMINRFFloPDU[_nextchannel]); - break; - case 2: - NRF24radio.openReadingPipe(0,kMINRFMJPDU[_nextchannel]); - break; - case 3: - NRF24radio.openReadingPipe(0,kMINRFL2PDU[_nextchannel]); - break; - case 4: - if(kMINRFL3PDU[_nextchannel]==0xffffffff) break; - NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]); - break; - case 5: - NRF24radio.openReadingPipe(0,kMINRFCGPDU[_nextchannel]); - break; - } - - MINRF.packetMode = _mode; -} -# 498 "S:/Development/Tasmota/tasmota/xsns_61_MI_NRF24.ino" -uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ - - DEBUG_SENSOR_LOG(PSTR("MINRF: will test ID-type: %x"), _type); - bool _success = false; - for (uint32_t i=0;i<5;i++){ - if(_type == kMINRFSlaveID[i]){ - DEBUG_SENSOR_LOG(PSTR("MINRF: ID is type %u"), i); - _type = i+1; - _success = true; - } - else { - DEBUG_SENSOR_LOG(PSTR("MINRF: ID-type is not: %x"),kMINRFSlaveID[i]); - } - } - if(!_success) return 0xff; - - DEBUG_SENSOR_LOG(PSTR("MINRF: vector size %u"), MIBLEsensors.size()); - for(uint32_t i=0; i6000){ - DEBUG_SENSOR_LOG(PSTR("MINRF: check for FAKE sensors")); - MINRFpurgeFakeSensors(); - MINRF.timer=0; - } - MINRF.timer++; - - if (!MINRFreceivePacket()){ - - } - - else if(MINRF.buffer.bleAdv.header.uuid==0xfe95){ - MINRF_LOG_BUFFER(MINRF.streamBuffer); - MINRF_LOG_BUFFER(MINRF.lsfrBuffer); - MINRF_LOG_BUFFER(MINRF.buffer.raw); - DEBUG_SENSOR_LOG(PSTR("MINRF: Type: %x"), MINRF.buffer.bleAdv.header.type); - switch(MINRF.buffer.bleAdv.header.type){ - case 0x2050: - DEBUG_SENSOR_LOG(PSTR("MINRF: MJ_HT_V1 Packet")); - break; - case 0x1613:case 0x1614:case 0x1615: - DEBUG_SENSOR_LOG(PSTR("MINRF: Flora Packet")); - break; - default: - DEBUG_SENSOR_LOG(PSTR("MINRF: unknown Packet")); - break; - } - } - else if (MINRF.packetMode == FLORA){ - MINRFhandleFloraPacket(); - } - else if (MINRF.packetMode == MJ_HT_V1){ - MINRFhandleMJ_HT_V1Packet(); - } - else if (MINRF.packetMode == LYWSD02){ - MINRFhandleLYWSD02Packet(); - } - else if (MINRF.packetMode == LYWSD03){ - MINRFhandleLYWSD03Packet(); - } - else if (MINRF.packetMode == CGG1){ - MINRFhandleCGG1Packet(); - } - if (MINRF.packetMode == CGG1){ - MINRFinitBLE(1); - } - else { - MINRFinitBLE(++MINRF.packetMode); - } - - MINRFhopChannel(); - NRF24radio.startListening(); -} - - - - -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; -const char HTTP_MINRF_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; -const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; -const char HTTP_MINRF_HL[] PROGMEM = "{s}
{m}
{e}"; - -void MINRFShow(bool json) -{ - if (json) { - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - if(MIBLEsensors.at(i).showedUp < 3){ - DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet")); - break; - } - char slave[33]; - sprintf_P(slave,"%s-%02x%02x%02x",kMINRFSlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - - ResponseAppend_P(PSTR(",\"%s\":{"),slave); - if(MIBLEsensors.at(i).temp!=-1000.0f){ - ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); - } - if (MIBLEsensors.at(i).type==FLORA){ - char lux[33]; - char moisture[33]; - char fertility[33]; - dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); - dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); - dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - if(MIBLEsensors.at(i).lux!=0xffff){ - ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); - } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ - ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); - } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ - ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); - } - } - if (MIBLEsensors.at(i).type>FLORA){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - if(MIBLEsensors.at(i).hum!=-1.0f){ - ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - } - if(MIBLEsensors.at(i).bat!=0xff){ - ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); - } - } - ResponseAppend_P(PSTR("}")); - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_NRF24, NRF24type, NRF24.chipType); - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - if(MIBLEsensors.at(i).showedUp < 3){ - DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet")); - break; - } - WSContentSend_PD(HTTP_MINRF_HL); - WSContentSend_PD(HTTP_MINRF_MAC, kMINRFSlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - if(MIBLEsensors.at(i).temp!=-1000.0f){ - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - WSContentSend_PD(HTTP_SNS_TEMP, kMINRFSlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); - } - if (MIBLEsensors.at(i).type==FLORA){ - if(MIBLEsensors.at(i).lux!=0x00ffffff){ - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); - } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ - WSContentSend_PD(HTTP_SNS_MOISTURE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); - } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ - char fertility[33]; - dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - WSContentSend_PD(HTTP_MINRF_FLORA_DATA, kMINRFSlaveType[MIBLEsensors.at(i).type-1], fertility); - } - } - if (MIBLEsensors.at(i).type>FLORA){ - if(MIBLEsensors.at(i).hum!=-1.0f){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - WSContentSend_PD(HTTP_SNS_HUM, kMINRFSlaveType[MIBLEsensors.at(i).type-1], humidity); - } - if(MIBLEsensors.at(i).bat!=0xff){ - WSContentSend_PD(HTTP_BATTERY, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); - } - } - } -#endif - } -} - - - - - -bool Xsns61(uint8_t function) -{ - bool result = false; - - if (NRF24.chipType) { - switch (function) { - case FUNC_INIT: - MINRFinitBLE(1); - AddLog_P2(LOG_LEVEL_INFO,PSTR("MINRF: started")); - break; - case FUNC_EVERY_50_MSECOND: - MINRF_EVERY_50_MSECOND(); - break; - case FUNC_JSON_APPEND: - MINRFShow(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - MINRFShow(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_62_MI_HM10.ino" -# 30 "S:/Development/Tasmota/tasmota/xsns_62_MI_HM10.ino" -#ifdef USE_HM10 - -#define XSNS_62 62 - -#include -#include - -TasmotaSerial *HM10Serial; -#define HM10_BAUDRATE 115200 - -#define HM10_MAX_TASK_NUMBER 12 -uint8_t HM10_TASK_LIST[HM10_MAX_TASK_NUMBER+1][2]; - -#define HM10_MAX_RX_BUF 512 -char HM10_RX_STRING[HM10_MAX_RX_BUF] = {0}; - -struct { - uint8_t current_task_delay; - uint8_t last_command; - uint16_t firmware; - uint32_t period; - uint32_t serialSpeed; - union { - uint32_t time; - uint8_t timebuf[4]; - }; - struct { - uint32_t init:1; - uint32_t pending_task:1; - uint32_t connected:1; - uint32_t subscribed:1; - uint32_t awaitingHT:1; - uint32_t awaitingB:1; - - } mode; - struct { - uint8_t sensor; - - } state; -} HM10; - -#pragma pack(1) -struct { - uint16_t temp; - uint8_t hum; -} LYWSD0x_HT; -#pragma pack(0) - -struct mi_sensor_t{ - uint8_t type; - uint8_t serial[6]; - uint8_t showedUp; - float temp; - union { - struct { - float moisture; - float fertility; - uint16_t lux; - }; - struct { - float hum; - uint8_t bat; - }; - }; -}; - -std::vector MIBLEsensors; - - - - - -#define D_CMND_HM10 "HM10" - -const char S_JSON_HM10_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_HM10 "%s\":%d}"; -const char S_JSON_HM10_COMMAND[] PROGMEM = "{\"" D_CMND_HM10 "%s%s\"}"; -const char kHM10_Commands[] PROGMEM = "Scan|AT|Period|Baud|Time"; - -#define FLORA 1 -#define MJ_HT_V1 2 -#define LYWSD02 3 -#define LYWSD03MMC 4 - -uint8_t kHM10SlaveID[4][3] = { 0xC4,0x7C,0x8D, - 0x58,0x2D,0x34, - 0xE7,0x2E,0x00, - 0xA4,0xC1,0x38, - }; - -const char kHM10SlaveType1[] PROGMEM = "Flora"; -const char kHM10SlaveType2[] PROGMEM = "MJ_HT_V1"; -const char kHM10SlaveType3[] PROGMEM = "LYWSD02"; -const char kHM10SlaveType4[] PROGMEM = "LYWSD03"; -const char * kHM10SlaveType[] PROGMEM = {kHM10SlaveType1,kHM10SlaveType2,kHM10SlaveType3,kHM10SlaveType4}; - - - - - -enum HM10_Commands { - CMND_HM10_DISC_SCAN, - CMND_HM10_AT, - CMND_HM10_PERIOD, - CMND_HM10_BAUD, - CMND_HM10_TIME - }; - - - - - -#define TASK_HM10_NOTASK 0 -#define TASK_HM10_ROLE1 1 -#define TASK_HM10_IMME1 2 -#define TASK_HM10_RENEW 3 -#define TASK_HM10_RESET 4 -#define TASK_HM10_DISC 5 -#define TASK_HM10_CONN 6 -#define TASK_HM10_VERSION 7 -#define TASK_HM10_NAME 8 -#define TASK_HM10_FEEDBACK 9 -#define TASK_HM10_DISCONN 10 -#define TASK_HM10_SUB_L3 11 -#define TASK_HM10_READ_HT 12 -#define TASK_HM10_FINDALLCHARS 13 -#define TASK_HM10_UN_L3 14 -#define TASK_HM10_DELAY_SUB 15 -#define TASK_HM10_READ_BT_L3 16 -#define TASK_HM10_SUB_L2 17 -#define TASK_HM10_UN_L2 18 -#define TASK_HM10_READ_BT_L2 19 -#define TASK_HM10_TIME_L2 20 - -#define TASK_HM10_DONE 99 - - - - - -void HM10_Launchtask(uint8_t task, uint8_t slot, uint8_t delay){ - HM10_TASK_LIST[slot][0] = task; - HM10_TASK_LIST[slot][1] = delay; - HM10_TASK_LIST[slot+1][0] = TASK_HM10_NOTASK; - HM10.current_task_delay = HM10_TASK_LIST[0][1]; -} - -void HM10_TaskReplaceInSlot(uint8_t task, uint8_t slot){ - HM10.last_command = HM10_TASK_LIST[slot][0]; - HM10_TASK_LIST[slot][0] = task; -} - - - - - -void HM10_Reset(void) { HM10_Launchtask(TASK_HM10_DISCONN,0,1); - HM10_Launchtask(TASK_HM10_ROLE1,1,1); - HM10_Launchtask(TASK_HM10_IMME1,2,1); - HM10_Launchtask(TASK_HM10_RESET,3,1); - HM10_Launchtask(TASK_HM10_VERSION,4,10); - HM10_Launchtask(TASK_HM10_DISC,5,50); - } - -void HM10_Discovery_Scan(void) { - HM10_Launchtask(TASK_HM10_DISCONN,0,1); - HM10_Launchtask(TASK_HM10_DISC,1,1); - } - -void HM10_Read_LYWSD03(void) { - HM10_Launchtask(TASK_HM10_CONN,0,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); - HM10_Launchtask(TASK_HM10_SUB_L3,2,20); - HM10_Launchtask(TASK_HM10_UN_L3,3,80); - HM10_Launchtask(TASK_HM10_READ_BT_L3,4,5); - HM10_Launchtask(TASK_HM10_DISCONN,5,5); - } - -void HM10_Read_LYWSD02(void) { - HM10_Launchtask(TASK_HM10_CONN,0,1); - HM10_Launchtask(TASK_HM10_FEEDBACK,1,35); - HM10_Launchtask(TASK_HM10_SUB_L2,2,20); - HM10_Launchtask(TASK_HM10_UN_L2,3,80); - HM10_Launchtask(TASK_HM10_READ_BT_L2,4,5); - HM10_Launchtask(TASK_HM10_DISCONN,5,5); - } - -void HM10_Time_LYWSD02(void) { - HM10_Launchtask(TASK_HM10_DISCONN,0,0); - HM10_Launchtask(TASK_HM10_CONN,1,5); - HM10_Launchtask(TASK_HM10_FEEDBACK,2,35); - HM10_Launchtask(TASK_HM10_TIME_L2,3,20); - HM10_Launchtask(TASK_HM10_DISCONN,4,5); - } -# 231 "S:/Development/Tasmota/tasmota/xsns_62_MI_HM10.ino" -uint32_t MIBLEgetSensorSlot(uint8_t (&_serial)[6], uint8_t _type){ - if(_type==0xff){ - DEBUG_SENSOR_LOG(PSTR("MIBLE: will test MAC-type")); - for (uint32_t i=0;i<4;i++){ - if(memcmp(_serial,kHM10SlaveID+i,3)==0){ - DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC is type %u"), i); - _type = i+1; - } - else { - DEBUG_SENSOR_LOG(PSTR("MIBLE: MAC-type is unknown")); - } - } - } - if(_type==0xff) return _type; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: vector size %u"), MIBLEsensors.size()); - for(uint32_t i=0; ibegin(HM10.serialSpeed)) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start serial communication fixed to 115200 baud"),D_CMND_HM10); - if (HM10Serial->hardwareSerial()) { - ClaimSerial(); - DEBUG_SENSOR_LOG(PSTR("HM10: claim HW")); - } - HM10_Reset(); - HM10.mode.pending_task = 1; - HM10.mode.init = 1; - HM10.period = Settings.tele_period; - DEBUG_SENSOR_LOG(PSTR("%s_TASK_LIST initialized, now return to main loop"),D_CMND_HM10); - } - return; -} -# 315 "S:/Development/Tasmota/tasmota/xsns_62_MI_HM10.ino" -void HM10MACStringToBytes(const char* string, uint8_t _mac[]) { - uint32_t index = 0; - while (index < 12) { - char c = string[index]; - uint32_t value = 0; - if(c >= '0' && c <= '9') - value = (c - '0'); - else if (c >= 'A' && c <= 'F') - value = (10 + (c - 'A')); - _mac[(index/2)] += value << (((index + 1) % 2) * 4); - - index++; - } - DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_mac[0],_mac[1],_mac[2],_mac[3],_mac[4],_mac[5]); -} - - - - - - -void HM10ParseResponse(char *buf) { - if (!strncmp(buf,"OK",2)) { - DEBUG_SENSOR_LOG(PSTR("HM10: got OK")); - } - if (!strncmp(buf,"HMSoft",6)) { - const char* _fw = "000"; - memcpy((void *)_fw,(void *)(buf+8),3); - HM10.firmware = atoi(_fw); - DEBUG_SENSOR_LOG(PSTR("HM10: Firmware: %d"), HM10.firmware); - return; - } - char * _pos = strstr(buf, "IS0:"); - if(_pos) { - const char* _mac = "000000000000"; - memcpy((void *)_mac,(void *)(_pos+4),12); - DEBUG_SENSOR_LOG(PSTR("HM10: found Mac: %s"), _mac); - uint8_t _newMacArray[6] = {0}; - HM10MACStringToBytes(_mac, _newMacArray); - DEBUG_SENSOR_LOG(PSTR("HM10: MAC-array: %x%x%x%x%x%x"),_newMacArray[0],_newMacArray[1],_newMacArray[2],_newMacArray[3],_newMacArray[4],_newMacArray[5]); - MIBLEgetSensorSlot(_newMacArray, 0xff); - } - if (strstr(buf, "LOST")){ - HM10.mode.connected = false; - } - else { - DEBUG_SENSOR_LOG(PSTR("HM10: empty response")); - } -} - -void HM10readTempHum(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0] != 0 && _buf[1] != 0){ - memcpy(&LYWSD0x_HT,(void *)_buf,3); - DEBUG_SENSOR_LOG(PSTR("HM10: Temperature * 100: %u, Humidity: %u"),LYWSD0x_HT.temp,LYWSD0x_HT.hum); - uint32_t _slot = HM10.state.sensor; - - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - static float _tempFloat; - _tempFloat=(float)(LYWSD0x_HT.temp)/100.0f; - if(_tempFloat<60){ - MIBLEsensors.at(_slot).temp=_tempFloat; - HM10.mode.awaitingHT = false; - HM10.current_task_delay = 0; - } - _tempFloat=(float)LYWSD0x_HT.hum; - if(_tempFloat<100){ - MIBLEsensors.at(_slot).hum = _tempFloat; - DEBUG_SENSOR_LOG(PSTR("LYWSD03: hum updated")); - } - } -} - -bool HM10readBat(char *_buf){ - DEBUG_SENSOR_LOG(PSTR("HM10: raw data: %x%x%x%x%x%x%x"),_buf[0],_buf[1],_buf[2],_buf[3],_buf[4],_buf[5],_buf[6]); - if(_buf[0] != 0){ - DEBUG_SENSOR_LOG(PSTR("HM10: Battery: %u"),_buf[0]); - uint32_t _slot = HM10.state.sensor; - DEBUG_SENSOR_LOG(PSTR("MIBLE: Sensor slot: %u"), _slot); - if(_buf[0]<101){ - MIBLEsensors.at(_slot).bat=_buf[0]; - return true; - } - } - return false; -} - - - - - -bool HM10SerialHandleFeedback(){ - bool success = false; - uint32_t i = 0; - char ret[HM10_MAX_RX_BUF] = {0}; - - - while(HM10Serial->available()) { - - if(iread(); - } - i++; - success = true; - } - if(HM10.mode.awaitingHT) { - if (HM10.mode.connected) HM10readTempHum(ret); - } - else if(HM10.mode.awaitingB) { - if (HM10.mode.connected) { - if (HM10readBat(ret)){ - HM10.mode.awaitingB = false; - HM10.current_task_delay = 0; - } - } - } - else if(success) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s response: %s"),D_CMND_HM10, (char *)ret); - HM10ParseResponse(ret); - } - else { - - } - return success; -} - - - - - -void HM10_TaskEvery100ms(){ - if (HM10.current_task_delay == 0) { - uint8_t i = 0; - bool runningTaskLoop = true; - while (runningTaskLoop) { - switch(HM10_TASK_LIST[i][0]) { - case TASK_HM10_ROLE1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set role to 1"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+ROLE1"); - break; - case TASK_HM10_IMME1: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set imme to 1"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+IMME1"); - break; - case TASK_HM10_DISC: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start discovery"),D_CMND_HM10); - HM10.current_task_delay = 35; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+DISC?"); - break; - case TASK_HM10_VERSION: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read version"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+VERR?"); - break; - case TASK_HM10_NAME: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read name"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+NAME?"); - break; - case TASK_HM10_CONN: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s connect"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - char _con[20]; - sprintf_P(_con,"AT+CON%02x%02x%02x%02x%02x%02x",MIBLEsensors.at(HM10.state.sensor).serial[0],MIBLEsensors.at(HM10.state.sensor).serial[1],MIBLEsensors.at(HM10.state.sensor).serial[2],MIBLEsensors.at(HM10.state.sensor).serial[3],MIBLEsensors.at(HM10.state.sensor).serial[4],MIBLEsensors.at(HM10.state.sensor).serial[5]); - HM10Serial->write(_con); - HM10.mode.awaitingB = false; - HM10.mode.connected = true; - break; - case TASK_HM10_DISCONN: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s disconnect"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT"); - break; - case TASK_HM10_RESET: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s Reset Device"),D_CMND_HM10); - HM10Serial->write("AT+RESET"); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - break; - case TASK_HM10_SUB_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); - HM10.current_task_delay = 25; - HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); - runningTaskLoop = false; - HM10Serial->write("AT+NOTIFY_ON0037"); - break; - case TASK_HM10_UN_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaitingHT = false; - HM10Serial->write("AT+NOTIFYOFF0037"); - break; - case TASK_HM10_SUB_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s subscribe"),D_CMND_HM10); - HM10.current_task_delay = 25; - HM10_TaskReplaceInSlot(TASK_HM10_DELAY_SUB,i); - runningTaskLoop = false; - HM10Serial->write("AT+NOTIFY_ON003C"); - break; - case TASK_HM10_UN_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s un-subscribe"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.mode.awaitingHT = false; - HM10Serial->write("AT+NOTIFYOFF003C"); - break; - case TASK_HM10_TIME_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s set time"),D_CMND_HM10); - HM10.current_task_delay = 5; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10.time = Rtc.utc_time; - HM10Serial->write("AT+SEND_DATAWR002F"); - HM10Serial->write(HM10.timebuf,4); - HM10Serial->write(Rtc.time_timezone / 60); - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s Time-string: %x%x%x%x%x"),D_CMND_HM10, HM10.timebuf[0],HM10.timebuf[1],HM10.timebuf[2],HM10.timebuf[3],(Rtc.time_timezone /60)); - break; - case TASK_HM10_READ_HT: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0036"),D_CMND_HM10); - HM10.current_task_delay = 0; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA0036?"); - HM10.mode.awaitingHT = true; - break; - case TASK_HM10_READ_BT_L3: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 003A"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA003A?"); - HM10.mode.awaitingB = true; - break; - case TASK_HM10_READ_BT_L2: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s read handle 0043"),D_CMND_HM10); - HM10.current_task_delay = 2; - HM10_TaskReplaceInSlot(TASK_HM10_FEEDBACK,i); - runningTaskLoop = false; - HM10Serial->write("AT+READDATA0043?"); - HM10.mode.awaitingB = true; - break; - - - - - - - - case TASK_HM10_FEEDBACK: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s get response"),D_CMND_HM10); - HM10SerialHandleFeedback(); - HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; - HM10_TASK_LIST[i][0] = TASK_HM10_DONE; - runningTaskLoop = false; - break; - case TASK_HM10_DELAY_SUB: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("%s start reading"),D_CMND_HM10); - HM10SerialHandleFeedback(); - HM10.current_task_delay = HM10_TASK_LIST[i+1][1];; - HM10_TASK_LIST[i][0] = TASK_HM10_DONE; - HM10.mode.awaitingHT = true; - runningTaskLoop = false; - break; - case TASK_HM10_DONE: - - - if(HM10_TASK_LIST[i+1][0] == TASK_HM10_NOTASK) { - DEBUG_SENSOR_LOG(PSTR("%sno Tasks left"),D_CMND_HM10); - DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK_DONE current slot %u"),D_CMND_HM10, i); - for (uint8_t j = 0; j < HM10_MAX_TASK_NUMBER+1; j++) { - DEBUG_SENSOR_LOG(PSTR("%sHM10_TASK cleanup slot %u"),D_CMND_HM10, j); - HM10_TASK_LIST[j][0] = TASK_HM10_NOTASK; - HM10_TASK_LIST[j][1] = 0; - } - runningTaskLoop = false; - HM10.mode.pending_task = 0; - break; - } - } - i++; - } - } - else { - HM10.current_task_delay--; - } -} - - - - - - -void HM10EverySecond(){ - if(HM10.firmware == 0) return; - if(HM10.mode.pending_task == 1) return; - if (MIBLEsensors.size()==0) return; - - static uint32_t _counter = 0; - static uint32_t _nextSensorSlot = 0; - if(_counter==0) { - HM10.state.sensor = _nextSensorSlot; - _nextSensorSlot++; - if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD03MMC) { - HM10.mode.pending_task = 1; - HM10_Read_LYWSD03(); - } - if(MIBLEsensors.at(HM10.state.sensor).type==LYWSD02) { - HM10.mode.pending_task = 1; - HM10_Read_LYWSD02(); - } - if (HM10.state.sensor==MIBLEsensors.size()-1) { - _nextSensorSlot= 0; - _counter++; - } - DEBUG_SENSOR_LOG(PSTR("%s active sensor now: %u"),D_CMND_HM10, HM10.state.sensor); - } - else _counter++; - if (_counter>HM10.period) _counter = 0; -} - -bool HM10Cmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_HM10); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_HM10), disp_len)) { - uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kHM10_Commands); - switch (command_code) { - case CMND_HM10_PERIOD: - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_HM10_PERIOD) { HM10.period = XdrvMailbox.payload; } - } - else { - if (command_code == CMND_HM10_PERIOD) XdrvMailbox.payload = HM10.period; - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_BAUD: - if (XdrvMailbox.data_len > 0) { - if (command_code == CMND_HM10_BAUD) { - HM10.serialSpeed = XdrvMailbox.payload; - HM10Serial->begin(HM10.serialSpeed); - } - } - else { - if (command_code == CMND_HM10_BAUD) XdrvMailbox.payload = HM10.serialSpeed; - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_TIME: - if (XdrvMailbox.data_len > 0) { - if(MIBLEsensors.size()>XdrvMailbox.payload){ - if(MIBLEsensors.at(XdrvMailbox.payload).type == LYWSD02){ - HM10.state.sensor = XdrvMailbox.payload; - HM10_Time_LYWSD02(); - } - } - } - Response_P(S_JSON_HM10_COMMAND_NVALUE, command, XdrvMailbox.payload); - break; - case CMND_HM10_AT: - HM10Serial->write("AT"); - if (strlen(XdrvMailbox.data)!=0) { - HM10Serial->write("+"); - HM10Serial->write(XdrvMailbox.data); - Response_P(S_JSON_HM10_COMMAND, ":AT+",XdrvMailbox.data); - } - else Response_P(S_JSON_HM10_COMMAND, ":AT",XdrvMailbox.data); - break; - case CMND_HM10_DISC_SCAN: - if (command_code == CMND_HM10_DISC_SCAN) { HM10_Discovery_Scan(); } - Response_P(S_JSON_HM10_COMMAND, command, ""); - break; - default: - - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - - - - - - -const char HTTP_HM10[] PROGMEM = "{s}HM10" " Firmware " "{m}%u{e}"; -const char HTTP_HM10_SERIAL[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}"; -const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}"; -const char HTTP_HM10_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}"; -const char HTTP_HM10_HL[] PROGMEM = "{s}
{m}
{e}"; - -void HM10Show(bool json) -{ - if (json) { - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - char slave[33]; - sprintf_P(slave,"%s-%02x%02x%02x",kHM10SlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - - ResponseAppend_P(PSTR(",\"%s\":{"),slave); - if(MIBLEsensors.at(i).temp!=-1000.0f){ - ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature); - } - if (MIBLEsensors.at(i).type==FLORA){ - char lux[33]; - char moisture[33]; - char fertility[33]; - dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux); - dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture); - dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - if(MIBLEsensors.at(i).lux!=0xffff){ - ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux); - } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ - ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture); - } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ - ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility); - } - } - if (MIBLEsensors.at(i).type>FLORA){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - if(MIBLEsensors.at(i).hum!=-1.0f){ - ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); - } - if(MIBLEsensors.at(i).bat!=0xff){ - ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); - } - } - ResponseAppend_P(PSTR("}")); - } -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_HM10, HM10.firmware); - for (uint32_t i = 0; i < MIBLEsensors.size(); i++) { - WSContentSend_PD(HTTP_HM10_HL); - WSContentSend_PD(HTTP_HM10_SERIAL, kHM10SlaveType[MIBLEsensors.at(i).type-1], D_MAC_ADDRESS, MIBLEsensors.at(i).serial[0], MIBLEsensors.at(i).serial[1],MIBLEsensors.at(i).serial[2],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]); - if(MIBLEsensors.at(i).temp!=-1000.0f){ - char temperature[33]; - dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature); - WSContentSend_PD(HTTP_SNS_TEMP, kHM10SlaveType[MIBLEsensors.at(i).type-1], temperature, TempUnit()); - } - if (MIBLEsensors.at(i).type==FLORA){ - if(MIBLEsensors.at(i).lux!=0xffff){ - WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux); - } - if(MIBLEsensors.at(i).moisture!=-1000.0f){ - WSContentSend_PD(HTTP_SNS_MOISTURE, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture); - } - if(MIBLEsensors.at(i).fertility!=-1000.0f){ - char fertility[33]; - dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility); - WSContentSend_PD(HTTP_HM10_FLORA_DATA, kHM10SlaveType[MIBLEsensors.at(i).type-1], fertility); - } - } - if (MIBLEsensors.at(i).type>FLORA){ - if(MIBLEsensors.at(i).hum!=-1.0f){ - char humidity[33]; - dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); - WSContentSend_PD(HTTP_SNS_HUM, kHM10SlaveType[MIBLEsensors.at(i).type-1], humidity); - } - if(MIBLEsensors.at(i).bat!=0xff){ - WSContentSend_PD(HTTP_BATTERY, kHM10SlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); - } - } - } -#endif - } -} - - - - - -bool Xsns62(uint8_t function) -{ - bool result = false; - - if ((pin[GPIO_HM10_RX] < 99) && (pin[GPIO_HM10_TX] < 99)) { - switch (function) { - case FUNC_INIT: - HM10SerialInit(); - break; - case FUNC_EVERY_50_MSECOND: - HM10SerialHandleFeedback(); - break; - case FUNC_EVERY_100_MSECOND: - if (HM10_TASK_LIST[0][0] != TASK_HM10_NOTASK) { - HM10_TaskEvery100ms(); - } - break; - case FUNC_EVERY_SECOND: - HM10EverySecond(); - break; - case FUNC_COMMAND: - result = HM10Cmd(); - break; - case FUNC_JSON_APPEND: - HM10Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - HM10Show(0); - break; -#endif - } - } - return result; -} -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_63_aht1x.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_63_aht1x.ino" -#ifdef USE_I2C -#ifdef USE_AHT1x - - - - - - -#define XSNS_63 63 -#define XI2C_43 43 - -#define AHT10_ADDR 0x38 - -uint8_t eSensorCalibrateCmd[3] = {0xE1, 0x08, 0x00}; -uint8_t eSensorNormalCmd[3] = {0xA8, 0x00, 0x00}; -uint8_t eSensorMeasureCmd[3] = {0xAC, 0x33, 0x00}; -uint8_t eSensorResetCmd = 0xBA; - -struct AHT10 { - float humidity = NAN; - float temperature = NAN; - uint8_t valid = 0; - uint8_t count = 0; - char name[6] = "AHT1x"; -} AHT10; - -bool AHT10Read(void) -{ - if (AHT10.valid) { AHT10.valid--; } - - uint8_t data[6]; - - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorMeasureCmd, 3); - Wire.endTransmission(); - delay(100); - - Wire.requestFrom(AHT10_ADDR, 6); - for (uint32_t i = 0; Wire.available() > 0; i++) { - data[i] = Wire.read(); - } - - uint32_t result_h = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4; - uint32_t result_t = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]; - - float humidity = result_h * 100 / 1048576; - float temperature = ((200 * result_t) / 1048576) - 50; - - if (isnan(temperature) || isnan(humidity)) { return false; } - - AHT10.humidity = ConvertHumidity(humidity); - AHT10.temperature = ConvertTemp(temperature); - - AHT10.valid = SENSOR_MAX_MISS; - return true; -} - - - -bool AHT10Init(void) -{ - Wire.begin(AHT10_ADDR); - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorCalibrateCmd, 3); - Wire.endTransmission(); - - delay(500); - - return (0x08 == (AHT10ReadStatus() & 0x68)); -} - -uint8_t AHT10ReadStatus(void) -{ - Wire.requestFrom(AHT10_ADDR, 1); - uint8_t result = Wire.read(); - return result; -} - -void AHT10Reset(void) -{ - Wire.beginTransmission(AHT10_ADDR); - Wire.write(eSensorResetCmd); - Wire.endTransmission(); - delay(20); -} - - - -void AHT10Detect(void) -{ - if (I2cActive(AHT10_ADDR)) { return; } - - if (AHT10Init()) { - I2cSetActiveFound(AHT10_ADDR, AHT10.name); - AHT10.count = 1; - } -} - -void AHT10EverySecond(void) -{ - if (uptime &1) { - - if (!AHT10Read()) { - AddLogMissed(AHT10.name, AHT10.valid); - } - } -} - -void AHT10Show(bool json) -{ - if (AHT10.valid) { - char temperature[33]; - dtostrfd(AHT10.temperature, Settings.flag2.temperature_resolution, temperature); - char humidity[33]; - dtostrfd(AHT10.humidity, Settings.flag2.humidity_resolution, humidity); - - if (json) { - ResponseAppend_P(JSON_SNS_TEMPHUM, AHT10.name, temperature, humidity); -#ifdef USE_DOMOTICZ - if ((0 == tele_period)) { - DomoticzTempHumSensor(temperature, humidity); - } -#endif -#ifdef USE_KNX - if (0 == tele_period) { - KnxSensor(KNX_TEMPERATURE, AHT10.temperature); - KnxSensor(KNX_HUMIDITY, AHT10.humidity); - } -#endif -#ifdef USE_WEBSERVER - } else { - WSContentSend_PD(HTTP_SNS_TEMP, AHT10.name, temperature, TempUnit()); - WSContentSend_PD(HTTP_SNS_HUM, AHT10.name, humidity); -#endif - } - } -} - - - - - -bool Xsns63(uint8_t function) -{ - if (!I2cEnabled(XI2C_43)) { return false; } - - bool result = false; - - if (FUNC_INIT == function) { - AHT10Detect(); - } - else if (AHT10.count) { - switch (function) { - case FUNC_EVERY_SECOND: - AHT10EverySecond(); - break; - case FUNC_JSON_APPEND: - AHT10Show(1); - break; -#ifdef USE_WEBSERVER - case FUNC_WEB_SENSOR: - AHT10Show(0); - break; -#endif - } - } - return result; -} - -#endif -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_91_prometheus.ino" -# 22 "S:/Development/Tasmota/tasmota/xsns_91_prometheus.ino" -#ifdef USE_PROMETHEUS - - - - -#define XSNS_91 91 - -void HandleMetrics(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR("Prometheus")); - - WSContentBegin(200, CT_PLAIN); - - - char parameter[FLOATSZ]; - - if (global_temperature != 9999) { - dtostrfd(global_temperature, Settings.flag2.temperature_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_temperature gauge\nglobal_temperature %s\n"), parameter); - } - if (global_humidity != 0) { - dtostrfd(global_humidity, Settings.flag2.humidity_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_humidity gauge\nglobal_humidity %s\n"), parameter); - } - if (global_pressure != 0) { - dtostrfd(global_pressure, Settings.flag2.pressure_resolution, parameter); - WSContentSend_P(PSTR("# TYPE global_pressure gauge\nglobal_pressure %s\n"), parameter); - } - -#ifdef USE_ENERGY_SENSOR - dtostrfd(Energy.voltage[0], Settings.flag2.voltage_resolution, parameter); - WSContentSend_P(PSTR("# TYPE voltage gauge\nvoltage %s\n"), parameter); - dtostrfd(Energy.current[0], Settings.flag2.current_resolution, parameter); - WSContentSend_P(PSTR("# TYPE current gauge\ncurrent %s\n"), parameter); - dtostrfd(Energy.active_power[0], Settings.flag2.wattage_resolution, parameter); - WSContentSend_P(PSTR("# TYPE active_power gauge\nactive_power %s\n"), parameter); - dtostrfd(Energy.daily, Settings.flag2.energy_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_daily gauge\nenergy_daily %s\n"), parameter); - dtostrfd(Energy.total, Settings.flag2.energy_resolution, parameter); - WSContentSend_P(PSTR("# TYPE energy_total counter\nenergy_total %s\n"), parameter); -#endif -# 80 "S:/Development/Tasmota/tasmota/xsns_91_prometheus.ino" - WSContentEnd(); -} - - - - - -bool Xsns91(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_WEB_ADD_HANDLER: - WebServer->on("/metrics", HandleMetrics); - break; - } - return result; -} - -#endif -# 1 "S:/Development/Tasmota/tasmota/xsns_interface.ino" -# 20 "S:/Development/Tasmota/tasmota/xsns_interface.ino" -#ifdef XFUNC_PTR_IN_ROM -bool (* const xsns_func_ptr[])(uint8_t) PROGMEM = { -#else -bool (* const xsns_func_ptr[])(uint8_t) = { -#endif - -#ifdef XSNS_01 - &Xsns01, -#endif - -#ifdef XSNS_02 - &Xsns02, -#endif - -#ifdef XSNS_03 - &Xsns03, -#endif - -#ifdef XSNS_04 - &Xsns04, -#endif - -#ifdef XSNS_05 - &Xsns05, -#endif - -#ifdef XSNS_06 - &Xsns06, -#endif - -#ifdef XSNS_07 - &Xsns07, -#endif - -#ifdef XSNS_08 - &Xsns08, -#endif - -#ifdef XSNS_09 - &Xsns09, -#endif - -#ifdef XSNS_10 - &Xsns10, -#endif - -#ifdef XSNS_11 - &Xsns11, -#endif - -#ifdef XSNS_12 - &Xsns12, -#endif - -#ifdef XSNS_13 - &Xsns13, -#endif - -#ifdef XSNS_14 - &Xsns14, -#endif - -#ifdef XSNS_15 - &Xsns15, -#endif - -#ifdef XSNS_16 - &Xsns16, -#endif - -#ifdef XSNS_17 - &Xsns17, -#endif - -#ifdef XSNS_18 - &Xsns18, -#endif - -#ifdef XSNS_19 - &Xsns19, -#endif - -#ifdef XSNS_20 - &Xsns20, -#endif - -#ifdef XSNS_21 - &Xsns21, -#endif - -#ifdef XSNS_22 - &Xsns22, -#endif - -#ifdef XSNS_23 - &Xsns23, -#endif - -#ifdef XSNS_24 - &Xsns24, -#endif - -#ifdef XSNS_25 - &Xsns25, -#endif - -#ifdef XSNS_26 - &Xsns26, -#endif - -#ifdef XSNS_27 - &Xsns27, -#endif - -#ifdef XSNS_28 - &Xsns28, -#endif - -#ifdef XSNS_29 - &Xsns29, -#endif - -#ifdef XSNS_30 - &Xsns30, -#endif - -#ifdef XSNS_31 - &Xsns31, -#endif - -#ifdef XSNS_32 - &Xsns32, -#endif - -#ifdef XSNS_33 - &Xsns33, -#endif - -#ifdef XSNS_34 - &Xsns34, -#endif - -#ifdef XSNS_35 - &Xsns35, -#endif - -#ifdef XSNS_36 - &Xsns36, -#endif - -#ifdef XSNS_37 - &Xsns37, -#endif - -#ifdef XSNS_38 - &Xsns38, -#endif - -#ifdef XSNS_39 - &Xsns39, -#endif - -#ifdef XSNS_40 - &Xsns40, -#endif - -#ifdef XSNS_41 - &Xsns41, -#endif - -#ifdef XSNS_42 - &Xsns42, -#endif - -#ifdef XSNS_43 - &Xsns43, -#endif - -#ifdef XSNS_44 - &Xsns44, -#endif - -#ifdef XSNS_45 - &Xsns45, -#endif - -#ifdef XSNS_46 - &Xsns46, -#endif - -#ifdef XSNS_47 - &Xsns47, -#endif - -#ifdef XSNS_48 - &Xsns48, -#endif - -#ifdef XSNS_49 - &Xsns49, -#endif - -#ifdef XSNS_50 - &Xsns50, -#endif - -#ifdef XSNS_51 - &Xsns51, -#endif - -#ifdef XSNS_52 - &Xsns52, -#endif - -#ifdef XSNS_53 - &Xsns53, -#endif - -#ifdef XSNS_54 - &Xsns54, -#endif - -#ifdef XSNS_55 - &Xsns55, -#endif - -#ifdef XSNS_56 - &Xsns56, -#endif - -#ifdef XSNS_57 - &Xsns57, -#endif - -#ifdef XSNS_58 - &Xsns58, -#endif - -#ifdef XSNS_59 - &Xsns59, -#endif - -#ifdef XSNS_60 - &Xsns60, -#endif - -#ifdef XSNS_61 - &Xsns61, -#endif - -#ifdef XSNS_62 - &Xsns62, -#endif - -#ifdef XSNS_63 - &Xsns63, -#endif - -#ifdef XSNS_64 - &Xsns64, -#endif - -#ifdef XSNS_65 - &Xsns65, -#endif - -#ifdef XSNS_66 - &Xsns66, -#endif - -#ifdef XSNS_67 - &Xsns67, -#endif - -#ifdef XSNS_68 - &Xsns68, -#endif - -#ifdef XSNS_69 - &Xsns69, -#endif - -#ifdef XSNS_70 - &Xsns70, -#endif - -#ifdef XSNS_71 - &Xsns71, -#endif - -#ifdef XSNS_72 - &Xsns72, -#endif - -#ifdef XSNS_73 - &Xsns73, -#endif - -#ifdef XSNS_74 - &Xsns74, -#endif - -#ifdef XSNS_75 - &Xsns75, -#endif - -#ifdef XSNS_76 - &Xsns76, -#endif - -#ifdef XSNS_77 - &Xsns77, -#endif - -#ifdef XSNS_78 - &Xsns78, -#endif - -#ifdef XSNS_79 - &Xsns79, -#endif - -#ifdef XSNS_80 - &Xsns80, -#endif - -#ifdef XSNS_81 - &Xsns81, -#endif - -#ifdef XSNS_82 - &Xsns82, -#endif - -#ifdef XSNS_83 - &Xsns83, -#endif - -#ifdef XSNS_84 - &Xsns84, -#endif - -#ifdef XSNS_85 - &Xsns85, -#endif - -#ifdef XSNS_86 - &Xsns86, -#endif - -#ifdef XSNS_87 - &Xsns87, -#endif - -#ifdef XSNS_88 - &Xsns88, -#endif - -#ifdef XSNS_89 - &Xsns89, -#endif - -#ifdef XSNS_90 - &Xsns90, -#endif - -#ifdef XSNS_91 - &Xsns91, -#endif - -#ifdef XSNS_92 - &Xsns92, -#endif - -#ifdef XSNS_93 - &Xsns93, -#endif - -#ifdef XSNS_94 - &Xsns94, -#endif - -#ifdef XSNS_95 - &Xsns95, -#endif - -#ifdef XSNS_96 - &Xsns96, -#endif - -#ifdef XSNS_97 - &Xsns97, -#endif - -#ifdef XSNS_98 - &Xsns98, -#endif - -#ifdef XSNS_99 - &Xsns99 -#endif -}; - -const uint8_t xsns_present = sizeof(xsns_func_ptr) / sizeof(xsns_func_ptr[0]); - - - - - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kXsnsList[] PROGMEM = { -#else -const uint8_t kXsnsList[] = { -#endif - -#ifdef XSNS_01 - XSNS_01, -#endif - -#ifdef XSNS_02 - XSNS_02, -#endif - -#ifdef XSNS_03 - XSNS_03, -#endif - -#ifdef XSNS_04 - XSNS_04, -#endif - -#ifdef XSNS_05 - XSNS_05, -#endif - -#ifdef XSNS_06 - XSNS_06, -#endif - -#ifdef XSNS_07 - XSNS_07, -#endif - -#ifdef XSNS_08 - XSNS_08, -#endif - -#ifdef XSNS_09 - XSNS_09, -#endif - -#ifdef XSNS_10 - XSNS_10, -#endif - -#ifdef XSNS_11 - XSNS_11, -#endif - -#ifdef XSNS_12 - XSNS_12, -#endif - -#ifdef XSNS_13 - XSNS_13, -#endif - -#ifdef XSNS_14 - XSNS_14, -#endif - -#ifdef XSNS_15 - XSNS_15, -#endif - -#ifdef XSNS_16 - XSNS_16, -#endif - -#ifdef XSNS_17 - XSNS_17, -#endif - -#ifdef XSNS_18 - XSNS_18, -#endif - -#ifdef XSNS_19 - XSNS_19, -#endif - -#ifdef XSNS_20 - XSNS_20, -#endif - -#ifdef XSNS_21 - XSNS_21, -#endif - -#ifdef XSNS_22 - XSNS_22, -#endif - -#ifdef XSNS_23 - XSNS_23, -#endif - -#ifdef XSNS_24 - XSNS_24, -#endif - -#ifdef XSNS_25 - XSNS_25, -#endif - -#ifdef XSNS_26 - XSNS_26, -#endif - -#ifdef XSNS_27 - XSNS_27, -#endif - -#ifdef XSNS_28 - XSNS_28, -#endif - -#ifdef XSNS_29 - XSNS_29, -#endif - -#ifdef XSNS_30 - XSNS_30, -#endif - -#ifdef XSNS_31 - XSNS_31, -#endif - -#ifdef XSNS_32 - XSNS_32, -#endif - -#ifdef XSNS_33 - XSNS_33, -#endif - -#ifdef XSNS_34 - XSNS_34, -#endif - -#ifdef XSNS_35 - XSNS_35, -#endif - -#ifdef XSNS_36 - XSNS_36, -#endif - -#ifdef XSNS_37 - XSNS_37, -#endif - -#ifdef XSNS_38 - XSNS_38, -#endif - -#ifdef XSNS_39 - XSNS_39, -#endif - -#ifdef XSNS_40 - XSNS_40, -#endif - -#ifdef XSNS_41 - XSNS_41, -#endif - -#ifdef XSNS_42 - XSNS_42, -#endif - -#ifdef XSNS_43 - XSNS_43, -#endif - -#ifdef XSNS_44 - XSNS_44, -#endif - -#ifdef XSNS_45 - XSNS_45, -#endif - -#ifdef XSNS_46 - XSNS_46, -#endif - -#ifdef XSNS_47 - XSNS_47, -#endif - -#ifdef XSNS_48 - XSNS_48, -#endif - -#ifdef XSNS_49 - XSNS_49, -#endif - -#ifdef XSNS_50 - XSNS_50, -#endif - -#ifdef XSNS_51 - XSNS_51, -#endif - -#ifdef XSNS_52 - XSNS_52, -#endif - -#ifdef XSNS_53 - XSNS_53, -#endif - -#ifdef XSNS_54 - XSNS_54, -#endif - -#ifdef XSNS_55 - XSNS_55, -#endif - -#ifdef XSNS_56 - XSNS_56, -#endif - -#ifdef XSNS_57 - XSNS_57, -#endif - -#ifdef XSNS_58 - XSNS_58, -#endif - -#ifdef XSNS_59 - XSNS_59, -#endif - -#ifdef XSNS_60 - XSNS_60, -#endif - -#ifdef XSNS_61 - XSNS_61, -#endif - -#ifdef XSNS_62 - XSNS_62, -#endif - -#ifdef XSNS_63 - XSNS_63, -#endif - -#ifdef XSNS_64 - XSNS_64, -#endif - -#ifdef XSNS_65 - XSNS_65, -#endif - -#ifdef XSNS_66 - XSNS_66, -#endif - -#ifdef XSNS_67 - XSNS_67, -#endif - -#ifdef XSNS_68 - XSNS_68, -#endif - -#ifdef XSNS_69 - XSNS_69, -#endif - -#ifdef XSNS_70 - XSNS_70, -#endif - -#ifdef XSNS_71 - XSNS_71, -#endif - -#ifdef XSNS_72 - XSNS_72, -#endif - -#ifdef XSNS_73 - XSNS_73, -#endif - -#ifdef XSNS_74 - XSNS_74, -#endif - -#ifdef XSNS_75 - XSNS_75, -#endif - -#ifdef XSNS_76 - XSNS_76, -#endif - -#ifdef XSNS_77 - XSNS_77, -#endif - -#ifdef XSNS_78 - XSNS_78, -#endif - -#ifdef XSNS_79 - XSNS_79, -#endif - -#ifdef XSNS_80 - XSNS_80, -#endif - -#ifdef XSNS_81 - XSNS_81, -#endif - -#ifdef XSNS_82 - XSNS_82, -#endif - -#ifdef XSNS_83 - XSNS_83, -#endif - -#ifdef XSNS_84 - XSNS_84, -#endif - -#ifdef XSNS_85 - XSNS_85, -#endif - -#ifdef XSNS_86 - XSNS_86, -#endif - -#ifdef XSNS_87 - XSNS_87, -#endif - -#ifdef XSNS_88 - XSNS_88, -#endif - -#ifdef XSNS_89 - XSNS_89, -#endif - -#ifdef XSNS_90 - XSNS_90, -#endif - -#ifdef XSNS_91 - XSNS_91, -#endif - -#ifdef XSNS_92 - XSNS_92, -#endif - -#ifdef XSNS_93 - XSNS_93, -#endif - -#ifdef XSNS_94 - XSNS_94, -#endif - -#ifdef XSNS_95 - XSNS_95, -#endif - -#ifdef XSNS_96 - XSNS_96, -#endif - -#ifdef XSNS_97 - XSNS_97, -#endif - -#ifdef XSNS_98 - XSNS_98, -#endif - -#ifdef XSNS_99 - XSNS_99 -#endif -}; - - - -bool XsnsEnabled(uint32_t sns_index) -{ - if (sns_index < sizeof(kXsnsList)) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t index = pgm_read_byte(kXsnsList + sns_index); -#else - uint32_t index = kXsnsList[sns_index]; -#endif - return bitRead(Settings.sensors[index / 32], index % 32); - } - return true; -} - -void XsnsSensorState(void) -{ - ResponseAppend_P(PSTR("\"")); - for (uint32_t i = 0; i < sizeof(kXsnsList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t sensorid = pgm_read_byte(kXsnsList + i); -#else - uint32_t sensorid = kXsnsList[i]; -#endif - bool disabled = false; - if (sensorid < MAX_XSNS_DRIVERS) { - disabled = !bitRead(Settings.sensors[sensorid / 32], sensorid % 32); - } - ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", sensorid); - } - ResponseAppend_P(PSTR("\"")); -} - - - - - -bool XsnsNextCall(uint8_t Function, uint8_t &xsns_index) -{ - xsns_index++; - if (xsns_index == xsns_present) { xsns_index = 0; } - -#ifndef USE_DEBUG_DRIVER - if (FUNC_WEB_SENSOR == Function) { -#endif - uint32_t max_disabled = xsns_present; - while (!XsnsEnabled(xsns_index) && max_disabled--) { - xsns_index++; - if (xsns_index == xsns_present) { xsns_index = 0; } - } -#ifndef USE_DEBUG_DRIVER - } -#endif - - return xsns_func_ptr[xsns_index](Function); -} - -bool XsnsCall(uint8_t Function) -{ - bool result = false; - - DEBUG_TRACE_LOG(PSTR("SNS: %d"), Function); - -#ifdef PROFILE_XSNS_EVERY_SECOND - uint32_t profile_start_millis = millis(); -#endif - - for (uint32_t x = 0; x < xsns_present; x++) { -#ifdef USE_DEBUG_DRIVER - if (XsnsEnabled(x)) { -#endif - - if ((FUNC_WEB_SENSOR == Function) && !XsnsEnabled(x)) { continue; } - -#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND - uint32_t profile_start_millis = millis(); -#endif - result = xsns_func_ptr[x](Function); - -#ifdef PROFILE_XSNS_SENSOR_EVERY_SECOND - uint32_t profile_millis = millis() - profile_start_millis; - if (profile_millis) { - if (FUNC_EVERY_SECOND == Function) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d to Sensor %d took %u mS"), uptime, Function, x, profile_millis); - } - } -#endif - - if (result && ((FUNC_COMMAND == Function) || - (FUNC_PIN_STATE == Function) || - (FUNC_COMMAND_SENSOR == Function) - )) { - break; - } -#ifdef USE_DEBUG_DRIVER - } -#endif - } - -#ifdef PROFILE_XSNS_EVERY_SECOND - uint32_t profile_millis = millis() - profile_start_millis; - if (profile_millis) { - if (FUNC_EVERY_SECOND == Function) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PRF: At %08u XsnsCall %d took %u mS"), uptime, Function, profile_millis); - } - } -#endif - - return result; -} -# 1 "S:/Development/Tasmota/tasmota/xx2c_interface.ino" -# 20 "S:/Development/Tasmota/tasmota/xx2c_interface.ino" -#ifdef USE_I2C - -#ifdef XFUNC_PTR_IN_ROM -const uint8_t kI2cList[] PROGMEM = { -#else -const uint8_t kI2cList[] = { -#endif - -#ifdef XI2C_01 - XI2C_01, -#endif - -#ifdef XI2C_02 - XI2C_02, -#endif - -#ifdef XI2C_03 - XI2C_03, -#endif - -#ifdef XI2C_04 - XI2C_04, -#endif - -#ifdef XI2C_05 - XI2C_05, -#endif - -#ifdef XI2C_06 - XI2C_06, -#endif - -#ifdef XI2C_07 - XI2C_07, -#endif - -#ifdef XI2C_08 - XI2C_08, -#endif - -#ifdef XI2C_09 - XI2C_09, -#endif - -#ifdef XI2C_10 - XI2C_10, -#endif - -#ifdef XI2C_11 - XI2C_11, -#endif - -#ifdef XI2C_12 - XI2C_12, -#endif - -#ifdef XI2C_13 - XI2C_13, -#endif - -#ifdef XI2C_14 - XI2C_14, -#endif - -#ifdef XI2C_15 - XI2C_15, -#endif - -#ifdef XI2C_16 - XI2C_16, -#endif - -#ifdef XI2C_17 - XI2C_17, -#endif - -#ifdef XI2C_18 - XI2C_18, -#endif - -#ifdef XI2C_19 - XI2C_19, -#endif - -#ifdef XI2C_20 - XI2C_20, -#endif - -#ifdef XI2C_21 - XI2C_21, -#endif - -#ifdef XI2C_22 - XI2C_22, -#endif - -#ifdef XI2C_23 - XI2C_23, -#endif - -#ifdef XI2C_24 - XI2C_24, -#endif - -#ifdef XI2C_25 - XI2C_25, -#endif - -#ifdef XI2C_26 - XI2C_26, -#endif - -#ifdef XI2C_27 - XI2C_27, -#endif - -#ifdef XI2C_28 - XI2C_28, -#endif - -#ifdef XI2C_29 - XI2C_29, -#endif - -#ifdef XI2C_30 - XI2C_30, -#endif - -#ifdef XI2C_31 - XI2C_31, -#endif - -#ifdef XI2C_32 - XI2C_32, -#endif - -#ifdef XI2C_33 - XI2C_33, -#endif - -#ifdef XI2C_34 - XI2C_34, -#endif - -#ifdef XI2C_35 - XI2C_35, -#endif - -#ifdef XI2C_36 - XI2C_36, -#endif - -#ifdef XI2C_37 - XI2C_37, -#endif - -#ifdef XI2C_38 - XI2C_38, -#endif - -#ifdef XI2C_39 - XI2C_39, -#endif - -#ifdef XI2C_40 - XI2C_40, -#endif - -#ifdef XI2C_41 - XI2C_41, -#endif - -#ifdef XI2C_42 - XI2C_42, -#endif - -#ifdef XI2C_43 - XI2C_43, -#endif - -#ifdef XI2C_44 - XI2C_44, -#endif - -#ifdef XI2C_45 - XI2C_45, -#endif - -#ifdef XI2C_46 - XI2C_46, -#endif - -#ifdef XI2C_47 - XI2C_47, -#endif - -#ifdef XI2C_48 - XI2C_48, -#endif - -#ifdef XI2C_49 - XI2C_49, -#endif - -#ifdef XI2C_50 - XI2C_50, -#endif - -#ifdef XI2C_51 - XI2C_51, -#endif - -#ifdef XI2C_52 - XI2C_52, -#endif - -#ifdef XI2C_53 - XI2C_53, -#endif - -#ifdef XI2C_54 - XI2C_54, -#endif - -#ifdef XI2C_55 - XI2C_55, -#endif - -#ifdef XI2C_56 - XI2C_56, -#endif - -#ifdef XI2C_57 - XI2C_57, -#endif - -#ifdef XI2C_58 - XI2C_58, -#endif - -#ifdef XI2C_59 - XI2C_59, -#endif - -#ifdef XI2C_60 - XI2C_60, -#endif - -#ifdef XI2C_61 - XI2C_61, -#endif - -#ifdef XI2C_62 - XI2C_62, -#endif - -#ifdef XI2C_63 - XI2C_63, -#endif - -#ifdef XI2C_64 - XI2C_64, -#endif - -#ifdef XI2C_65 - XI2C_65, -#endif - -#ifdef XI2C_66 - XI2C_66, -#endif - -#ifdef XI2C_67 - XI2C_67, -#endif - -#ifdef XI2C_68 - XI2C_68, -#endif - -#ifdef XI2C_69 - XI2C_69, -#endif - -#ifdef XI2C_70 - XI2C_70, -#endif - -#ifdef XI2C_71 - XI2C_71, -#endif - -#ifdef XI2C_72 - XI2C_72, -#endif - -#ifdef XI2C_73 - XI2C_73, -#endif - -#ifdef XI2C_74 - XI2C_74, -#endif - -#ifdef XI2C_75 - XI2C_75, -#endif - -#ifdef XI2C_76 - XI2C_76, -#endif - -#ifdef XI2C_77 - XI2C_77, -#endif - -#ifdef XI2C_78 - XI2C_78, -#endif - -#ifdef XI2C_79 - XI2C_79, -#endif - -#ifdef XI2C_80 - XI2C_80, -#endif - -#ifdef XI2C_81 - XI2C_81, -#endif - -#ifdef XI2C_82 - XI2C_82, -#endif - -#ifdef XI2C_83 - XI2C_83, -#endif - -#ifdef XI2C_84 - XI2C_84, -#endif - -#ifdef XI2C_85 - XI2C_85, -#endif - -#ifdef XI2C_86 - XI2C_86, -#endif - -#ifdef XI2C_87 - XI2C_87, -#endif - -#ifdef XI2C_88 - XI2C_88, -#endif - -#ifdef XI2C_89 - XI2C_89, -#endif - -#ifdef XI2C_90 - XI2C_90, -#endif - -#ifdef XI2C_91 - XI2C_91, -#endif - -#ifdef XI2C_92 - XI2C_92, -#endif - -#ifdef XI2C_93 - XI2C_93, -#endif - -#ifdef XI2C_94 - XI2C_94, -#endif - -#ifdef XI2C_95 - XI2C_95, -#endif - -#ifdef XI2C_96 - XI2C_96 -#endif -}; - - - -bool I2cEnabled(uint32_t i2c_index) -{ - return (i2c_flg && bitRead(Settings.i2c_drivers[i2c_index / 32], i2c_index % 32)); -} - -void I2cDriverState(void) -{ - ResponseAppend_P(PSTR("\"")); - for (uint32_t i = 0; i < sizeof(kI2cList); i++) { -#ifdef XFUNC_PTR_IN_ROM - uint32_t i2c_driver_id = pgm_read_byte(kI2cList + i); -#else - uint32_t i2c_driver_id = kI2cList[i]; -#endif - bool disabled = false; - if (i2c_driver_id < MAX_I2C_DRIVERS) { - disabled = !bitRead(Settings.i2c_drivers[i2c_driver_id / 32], i2c_driver_id % 32); - } - ResponseAppend_P(PSTR("%s%s%d"), (i) ? "," : "", (disabled) ? "!" : "", i2c_driver_id); - } - ResponseAppend_P(PSTR("\"")); -} - -#endif \ No newline at end of file From 631d9045f136c7fcde3525021ac73ce19b24401f Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 20:52:06 -0600 Subject: [PATCH 476/559] Deal with late device group initializaton --- tasmota/xdrv_35_pwm_dimmer.ino | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index ea3211563..fca67efe6 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -80,7 +80,6 @@ bool button_hold_sent[3]; bool button_pressed[3] = { false, false, false }; #ifdef USE_PWM_DIMMER_REMOTE struct remote_pwm_dimmer * remote_pwm_dimmers; -struct device_group * active_device_group; struct remote_pwm_dimmer * active_remote_pwm_dimmer; uint8_t buttons_pressed = 0; bool active_device_is_local; @@ -136,13 +135,12 @@ void PWMDimmerInit(void) if (Settings.flag3.remote_device_mode) { if (device_group_count > 1) { if ((remote_pwm_dimmers = (struct remote_pwm_dimmer *) calloc(device_group_count - 1, sizeof(struct remote_pwm_dimmer))) == nullptr) { - AddLog_P2(LOG_LEVEL_ERROR, "PWMDimmer: error allocating PWM dimmer array"); + AddLog_P2(LOG_LEVEL_ERROR, PSTR("PWMDimmer: error allocating PWM dimmer array")); Settings.flag3.remote_device_mode = false; } } } - active_device_group = &device_groups[0]; active_device_is_local = true; #endif // USE_PWM_DIMMER_REMOTE } @@ -220,7 +218,6 @@ void PWMDimmerAnimate(bool no_fade) if (relay_is_on != (current_bri > 0)) { bool power_is_on = ((power & 1) != 0); if (power_is_on == relay_is_on) { -AddLog_P2(LOG_LEVEL_DEBUG, "****************** ExecuteCommandPower(1, %d, SRC_SWITCH)", (relay_is_on ? 0 : 1)); ExecuteCommandPower(1, (relay_is_on ? POWER_OFF : POWER_ON), SRC_SWITCH); } @@ -377,8 +374,7 @@ void PWMDimmerHandleButton() power_button_index = button_index; up_button_index = (button_index == 2 ? 1 : 2); down_button_index = (button_index ? 0 : 1); - active_device_group = &device_groups[power_button_index]; - active_device_is_local = active_device_group->local; + active_device_is_local = device_groups[power_button_index].local; if (!active_device_is_local) active_remote_pwm_dimmer = &remote_pwm_dimmers[power_button_index - 1]; } if (button_index == power_button_index) { @@ -553,11 +549,11 @@ void PWMDimmerHandleButton() // Publish MQTT Event SwitchTrigger#. char topic[TOPSZ]; #ifdef USE_PWM_DIMMER_REMOTE - snprintf(topic, sizeof(topic), "%s/cmnd/Event", active_device_group->group_name); + snprintf_P(topic, sizeof(topic), PSTR("%s/cmnd/Event"), device_groups[power_button_index].group_name); #else // USE_PWM_DIMMER_REMOTE - snprintf(topic, sizeof(topic), "%s/cmnd/Event", SettingsText(SET_MQTT_GRP_TOPIC)); + snprintf_P(topic, sizeof(topic), PSTR("%s/cmnd/Event"), SettingsText(SET_MQTT_GRP_TOPIC)); #endif // USE_PWM_DIMMER_REMOTE - sprintf(mqtt_data, "SwitchTrigger%u", (down_button_is_held ? 1 : 2)); + sprintf_P(mqtt_data, PSTR("SwitchTrigger%u"), (down_button_is_held ? 1 : 2)); MqttPublish(topic); } break; From 66ce8399e56dbad4dd305997bf246c9e8d49ee6e Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Mon, 24 Feb 2020 21:09:38 -0600 Subject: [PATCH 477/559] Update enable option --- Device_Groups.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Device_Groups.md b/Device_Groups.md index 3384132b4..4f2e9530e 100644 --- a/Device_Groups.md +++ b/Device_Groups.md @@ -6,7 +6,7 @@ UDP multicasts, followed by UDP unicasts if necessary, are used to send updates To include device groups support in the build, define USE_DEVICE_GROUPS in your user_config_override. This adds 3.5K to the code size. All devices in a group must be running firmware with device group support and have device groups enabled. -To enable device groups, set Option16 to 1 and **restart the device**. +To enable device groups, set Option85 to 1. ## Device Groups Operation From 4df7f9fe10aeb2659e37541efeae102d6bf2c95c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Feb 2020 11:08:47 +0100 Subject: [PATCH 478/559] Disable for now --- tasmota/my_user_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 836fbeb10..264c548de 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -415,7 +415,7 @@ //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug -#define USE_DEVICE_GROUPS // Add support for device groups (+4k code) +//#define USE_DEVICE_GROUPS // Add support for device groups (+4k code) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // From 78991578711a3be78f692ad62f1cdaa851ad3376 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 25 Feb 2020 11:44:09 +0100 Subject: [PATCH 479/559] Using Arduino ESP8266 commit abdd2bd... for Tasmota stage freezed builds --- platformio_override_sample.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 0c63c6e8f..814c1e75c 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -180,7 +180,7 @@ build_flags = ${esp82xx_defaults.build_flags} [tasmota_core_stage] ; *** Esp8266 core for Arduino version stable beta platform = espressif8266@2.3.3 -platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#6be561617f645f6a2ae82b8211f6af8c43e834cf +platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#abdd2bdbb6a5caf31807d82ebd7b447947a9c360 build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC ; NONOSDK221 From 0475289532b7e23411e1de3bd18b9ff0f63896ae Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Feb 2020 11:52:52 +0100 Subject: [PATCH 480/559] Fix compilation when no emulation is selected Fix compilation when no emulation is selected (#7790) --- tasmota/xdrv_01_webserver.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index e8c728024..33efee99b 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2824,6 +2824,7 @@ void (* const WebCommand[])(void) PROGMEM = { #ifdef USE_EMULATION void CmndEmulation(void) { +#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) #if defined(USE_EMULATION_WEMO) && defined(USE_EMULATION_HUE) if ((XdrvMailbox.payload >= EMUL_NONE) && (XdrvMailbox.payload < EMUL_MAX)) { #else @@ -2837,6 +2838,7 @@ void CmndEmulation(void) Settings.flag2.emulation = XdrvMailbox.payload; restart_flag = 2; } +#endif ResponseCmndNumber(Settings.flag2.emulation); } #endif // USE_EMULATION From 9962b311d595d4f4f903a12035ace1dbcc188c5d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Feb 2020 12:13:49 +0100 Subject: [PATCH 481/559] Add support for UDP Group commands Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) --- RELEASENOTES.md | 2 ++ tasmota/CHANGELOG.md | 3 ++- tasmota/my_user_config.h | 2 +- tasmota/support_command.ino | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index e5e08674c..1c4197a19 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -105,3 +105,5 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add another new DHT driver based on ESPEasy. The old driver can still be used using define USE_DHT_OLD. The previous new driver can be used with define USE_DHT_V2 (#7717) - Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) +- Add Zigbee enhanced commands decoding, added ``ZbPing`` +- Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index ef9ce17f4..fc1538101 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,10 +3,11 @@ ### 8.1.0.9 20200220 - Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) +- Fix Zigbee auto-increment transaction number (#7757) - Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) -- Fix Zigbee auto-increment transaction number (#7757) - Add Zigbee enhanced commands decoding, added ``ZbPing`` +- Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) ### 8.1.0.8 20200212 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 264c548de..29cb700ab 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -415,7 +415,7 @@ //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug -//#define USE_DEVICE_GROUPS // Add support for device groups (+4k code) +//#define USE_DEVICE_GROUPS // Add support for device groups (+5k6 code) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 59d6b11d5..ac44b9850 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -1677,7 +1677,7 @@ void CmndDevGroupShare(void) ParseParameters(2, parm); Settings.device_group_share_in = parm[0]; Settings.device_group_share_out = parm[1]; - Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":%x,\"Out\":%x}}"), Settings.device_group_share_in, Settings.device_group_share_out); + Response_P(PSTR("{\"" D_CMND_DEVGROUP_SHARE "\":{\"In\":\"%X\",\"Out\":\"%X\"}}"), Settings.device_group_share_in, Settings.device_group_share_out); } #endif // USE_DEVICE_GROUPS From 3146bcf23aee09a940a7e72c0f266990f1844813 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Feb 2020 16:49:19 +0100 Subject: [PATCH 482/559] Add some wifi debug options --- tasmota/settings.h | 2 +- tasmota/settings.ino | 16 ++------ tasmota/support_wifi.ino | 80 ++++++++++++++++++++++++++++++---------- tasmota/tasmota_post.h | 4 +- 4 files changed, 67 insertions(+), 35 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 7952dd9cf..ec81d5345 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -132,7 +132,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t spare28 : 1; uint32_t spare29 : 1; uint32_t spare30 : 1; - uint32_t spare31 : 1; + uint32_t force_sdk_erase : 1; // bit 31 (v8.1.0.9) - SetOption113 - Force erase of SDK wifi calibrate secore on restart }; } SysBitfield4; diff --git a/tasmota/settings.ino b/tasmota/settings.ino index c2ddc6607..1563897b0 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -745,6 +745,7 @@ void SettingsErase(uint8_t type) 1 = Erase 16k SDK parameter area near end of flash as seen by SDK (0x0xFCxxx - 0x0xFFFFF) solving possible wifi errors 2 = Erase Tasmota parameter area (0x0xF3xxx - 0x0xFBFFF) 3 = Erase Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) + 4 = Erase SDK parameter area used for wifi calibration (0x0FCxxx - 0x0FCFFF) */ #ifndef FIRMWARE_MINIMAL @@ -762,16 +763,17 @@ void SettingsErase(uint8_t type) _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; // Flash size as seen by SDK } -#ifdef USE_WIFI_SDK_ERASE else if (4 == type) { +// _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; // SDK phy area and Core calibration sector (0x0FC000) _sectorStart = SETTINGS_LOCATION +1; // SDK phy area and Core calibration sector (0x0FC000) _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0x0FCFFF) } +/* else if (5 == type) { _sectorStart = (ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE) -4; // SDK phy area and Core calibration sector (0xxFC000) _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0xxFCFFF) } -#endif // USE_WIFI_SDK_ERASE +*/ AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); // EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK @@ -786,16 +788,6 @@ void SettingsSdkErase(void) delay(1000); } -#ifdef USE_WIFI_SDK_ERASE -void SettingsSdkWifiErase(void) -{ - WiFi.disconnect(false); // Delete SDK wifi config - SettingsErase(4); - SettingsErase(5); - delay(200); -} -#endif // USE_WIFI_SDK_ERASE - /********************************************************************************************/ void SettingsDefault(void) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index dd8d2441c..93dba06a9 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -21,6 +21,10 @@ * Wifi \*********************************************************************************************/ +// Enable only one of two below debug options +//#define WIFI_RF_MODE_RF_CAL // Set RF_MODE to RF_CAL for restart and deepsleep during user_rf_pre_init +#define WIFI_RF_PRE_INIT // Set RF_MODE to RF_CAL for restart, deepsleep and power on during user_rf_pre_init + #ifndef WIFI_RSSI_THRESHOLD #define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network #endif @@ -609,6 +613,32 @@ void WifiSetOutputPower(void) WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); } +/* + See Esp.h, core_esp8266_phy.cpp and test_overrides.ino + RF_DEFAULT = 0, // RF_CAL or not after deep-sleep wake up, depends on init data byte 108. + RF_CAL = 1, // RF_CAL after deep-sleep wake up, there will be large current. + RF_NO_CAL = 2, // no RF_CAL after deep-sleep wake up, there will only be small current. + RF_DISABLED = 4 // disable RF after deep-sleep wake up, just like modem sleep, there will be the smallest current. +*/ +#ifdef WIFI_RF_MODE_RF_CAL +#ifndef USE_DEEPSLEEP +RF_MODE(RF_CAL); +#endif // USE_DEEPSLEEP +#endif // WIFI_RF_MODE_RF_CAL + +#ifdef WIFI_RF_PRE_INIT +bool rf_pre_init_flag = false; +RF_PRE_INIT() +{ +#ifndef USE_DEEPSLEEP + system_deep_sleep_set_option(1); // The option is 1 by default. + system_phy_set_rfoption(RF_CAL); +#endif // USE_DEEPSLEEP + system_phy_set_powerup_option(3); // 3: RF initialization will do the whole RF calibration which will take about 200ms; this increases the current consumption. + rf_pre_init_flag = true; +} +#endif // WIFI_RF_PRE_INIT + void WifiConnect(void) { WifiSetState(0); @@ -618,37 +648,47 @@ void WifiConnect(void) Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); Wifi.retry = Wifi.retry_init; Wifi.counter = 1; + +#ifdef WIFI_RF_PRE_INIT + if (rf_pre_init_flag) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Pre-init done")); + } +#endif // WIFI_RF_PRE_INIT } -// Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 -// Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset -void WifiDisconnect(void) -{ -#ifdef USE_WIFI_SDK_ERASE // Do not enable with DeepSleep as it will wear out flash - SettingsSdkWifiErase(); -#else - // Courtesy of EspEasy - WiFi.persistent(true); // use SDK storage of SSID/WPA parameters - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage - ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters - delay(100); // Flush anything in the network buffers. -#endif // USE_WIFI_SDK_ERASE -} - -void WifiShutdown(void) +void WifiShutdown(bool option = false) { + // option = false - Legacy disconnect also used by DeepSleep + // option = true - Disconnect with SDK wifi calibrate sector erase delay(100); // Allow time for message xfer - disabled v6.1.0b + +#ifdef USE_EMULATION + UdpDisconnect(); +#endif // USE_EMULATION + if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT MqttDisconnect(); } - WifiDisconnect(); + + if (option && Settings.flag4.force_sdk_erase) { // SetOption113 - Force erase of SDK wifi calibrate sector on restart + WiFi.disconnect(false); // Disconnect wifi + SettingsErase(4); // Delete SDK wifi config and calibrate data + } else { + // Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 + // Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset + // Courtesy of EspEasy + WiFi.persistent(true); // use SDK storage of SSID/WPA parameters + ETS_UART_INTR_DISABLE(); + wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage + ETS_UART_INTR_ENABLE(); + WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters + } + delay(100); // Flush anything in the network buffers. } void EspRestart(void) { - WifiShutdown(); + WifiShutdown(true); CrashDumpClear(); // Clear the stack dump in RTC // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 ESP.reset(); diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index e27213b5a..448fcc6b2 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -694,11 +694,11 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #endif #ifndef MESSZ -//#define MESSZ 1040 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1200) +//#define MESSZ 1040 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1200) #define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string #endif -//#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) +//#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) #ifndef ARDUINO_ESP8266_RELEASE #define ARDUINO_ESP8266_RELEASE "STAGE" #endif From ec161d5810fc7cc1ed7b8cdb7fefcd4ca5b1ebf4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Feb 2020 16:52:07 +0100 Subject: [PATCH 483/559] Restore default wifi functionality --- tasmota/support_wifi.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 93dba06a9..8f7de0f96 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -23,7 +23,7 @@ // Enable only one of two below debug options //#define WIFI_RF_MODE_RF_CAL // Set RF_MODE to RF_CAL for restart and deepsleep during user_rf_pre_init -#define WIFI_RF_PRE_INIT // Set RF_MODE to RF_CAL for restart, deepsleep and power on during user_rf_pre_init +//#define WIFI_RF_PRE_INIT // Set RF_MODE to RF_CAL for restart, deepsleep and power on during user_rf_pre_init #ifndef WIFI_RSSI_THRESHOLD #define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network From 78e707e73699a19b741b2178d7053069fa7938ee Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 25 Feb 2020 17:55:45 +0100 Subject: [PATCH 484/559] minor bug fixes and enhancements - fix bug in multi-push from last commit - remove rules execution every second. only at start and stop - enable rules for Shutter#Button - tbd: How to correctly detect a simultaneous button push --- tasmota/xdrv_27_shutter.ino | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 6f4d711d7..1131a5f70 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -255,6 +255,7 @@ void ShutterInit(void) void ShutterReportPosition(bool always) { Response_P(PSTR("{")); + rules_flag.shutter_moving = 0; for (uint32_t i = 0; i < shutters_present; i++) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d"), i+1,Shutter.real_position[i]); uint32_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); @@ -268,7 +269,6 @@ void ShutterReportPosition(bool always) ResponseJsonEnd(); if (always || (rules_flag.shutter_moving)) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); - XdrvRulesProcess(); } //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); @@ -299,18 +299,23 @@ void ShutterUpdatePosition(void) int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); int32_t min_runtime_ms = Shutter.pwm_frequency[i]*1000 / max_freq_change_per_sec; int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; - int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency[i] / max_frequency * Shutter.direction[i] ; + int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency[i] / max_frequency * Shutter.direction[i] ; int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; stop_position_delta =200 * Shutter.pwm_frequency[i]/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); + if (Shutter.time[i] == 1) { + ShutterReportPosition(true); + rules_flag.shutter_moving = 1; + XdrvRulesProcess(); + } //Shutter.accelerator[i] = tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); //int32_t act_freq_change = max_freq_change_per_sec/20; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, Shutter.pwm_frequency[i],max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); - if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { + if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > (Shutter.target_position[i]- (100 * Shutter.direction[i])) * Shutter.direction[i] ) { - Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); + Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]); } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency[i] == max_frequency) { Shutter.accelerator[i] = 0; @@ -348,7 +353,7 @@ void ShutterUpdatePosition(void) } analogWrite(pin[GPIO_PWM1+i], 0); Shutter.real_position[i] = ShutterCounterBasedPosition(i); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); @@ -422,6 +427,8 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter.time[i] = 0; Shutter.skip_relay_change = 0; Shutter.direction[i] = direction; + rules_flag.shutter_moving = 1; + rules_flag.shutter_moved = 0; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); } //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), i, Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i]); @@ -538,6 +545,7 @@ void ShutterButtonHandler(void) Button.press_counter[button_index] = 99; // Remember to discard further action for press & hold within button timings } else { Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; + Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window } } blinks = 201; @@ -590,15 +598,16 @@ void ShutterButtonHandler(void) // check for simultaneous shutter button press uint32 min_shutterbutton_press_counter = -1; for (uint32_t i = 0; i < MAX_KEYS; i++) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter); - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d, i %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i); + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { min_shutterbutton_press_counter = Button.press_counter[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: min_shutterbutton_press_counter %d"), min_shutterbutton_press_counter); } } if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { // simultaneous shutter button press detected - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:simultanous presss deteced")); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: simultanous presss deteced")); press_index = Button.press_counter[button_index]; for (uint32_t i = 0; i < MAX_KEYS; i++) if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) @@ -678,6 +687,7 @@ void ShutterButtonHandler(void) ResponseJsonEnd(); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); XdrvRulesProcess(); + } } From 91dfc7aa0ba518e8a70b9792b5ff615d4821b1d3 Mon Sep 17 00:00:00 2001 From: "he.so" Date: Tue, 25 Feb 2020 20:47:48 +0100 Subject: [PATCH 485/559] Send the calculated command bitstream twice, to be more robust against missed commands on the receiving side. --- tasmota/xdrv_35_keeloq.ino | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/tasmota/xdrv_35_keeloq.ino b/tasmota/xdrv_35_keeloq.ino index c360fdb8e..2ead3b904 100644 --- a/tasmota/xdrv_35_keeloq.ino +++ b/tasmota/xdrv_35_keeloq.ino @@ -69,15 +69,15 @@ void CmdSet(void) Settings.keeloq_master_lsb = param[1]; Settings.keeloq_serial = param[2]; Settings.keeloq_count = param[3]; - + jaroliftDevice.serial = param[2]; jaroliftDevice.count = param[3]; - + GenerateDeviceCryptKey(); ResponseCmndDone(); } else { AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("no payload")); - } + } } else { AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("no param")); } @@ -88,7 +88,7 @@ void GenerateDeviceCryptKey() Keeloq k(Settings.keeloq_master_msb, Settings.keeloq_master_lsb); jaroliftDevice.device_key_msb = k.decrypt(jaroliftDevice.serial | 0x60000000L); jaroliftDevice.device_key_lsb = k.decrypt(jaroliftDevice.serial | 0x20000000L); - + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("device keys: %08x %08x"), jaroliftDevice.device_key_msb, jaroliftDevice.device_key_lsb); } @@ -96,7 +96,7 @@ void CmdSendButton(void) { noInterrupts(); entertx(); - + if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.payload > 0) @@ -107,24 +107,27 @@ void CmdSendButton(void) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("count: %08x"), jaroliftDevice.count); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("serial: %08x"), jaroliftDevice.serial); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("disc: %08x"), jaroliftDevice.disc); - + CreateKeeloqPacket(); jaroliftDevice.count++; Settings.keeloq_count = jaroliftDevice.count; - AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("sync frame")); - digitalWrite(TX_PORT, LOW); // CC1101 in TX Mode+ - delayMicroseconds(1150); - SendSyncPreamble(13); - delayMicroseconds(3500); - for(int i=72; i>0; i--) + for(int repeat = 0; repeat <= 1; repeat++) { - SendBit(jaroliftDevice.pack & 0x0000000000000001); - jaroliftDevice.pack >>= 1; + AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("sync frame")); + digitalWrite(TX_PORT, LOW); // CC1101 in TX Mode+ + delayMicroseconds(1150); + SendSyncPreamble(13); + delayMicroseconds(3500); + for(int i=72; i>0; i--) + { + SendBit(jaroliftDevice.pack & 0x0000000000000001); + jaroliftDevice.pack >>= 1; + } + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); + + delay(16); // delay in loop context is save for wdt } - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); - - delay(16); // delay in loop context is save for wdt } } @@ -157,7 +160,7 @@ void CmndSendRaw(void) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("cmd send called at %d"), micros()); noInterrupts(); entertx(); - for(int repeat = 0; repeat < 1; repeat++) + for(int repeat = 0; repeat <= 1; repeat++) { if (XdrvMailbox.data_len > 0) { @@ -172,7 +175,7 @@ void CmndSendRaw(void) SendBit(XdrvMailbox.data[i] == '1'); } AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); - + delay(16); // delay in loop context is save for wdt } interrupts(); @@ -190,11 +193,8 @@ void enterrx() { { if (micros() - rx_time > 50000) break; // Quit when marcState does not change... } -} // void enterrx +} -//#################################################################### -// put CC1101 to send mode -//#################################################################### void entertx() { unsigned char marcState = 0; cc1101.setTxState(); @@ -204,7 +204,7 @@ void entertx() { { if (micros() - rx_time > 50000) break; // Quit when marcState does not change... } -} // void entertx +} void SendSyncPreamble(int l) { @@ -257,7 +257,7 @@ void InitKeeloq() bool Xdrv35(uint8_t function) { bool result = false; - + switch (function) { case FUNC_INIT: InitKeeloq(); From 407334be6b2450bc64ee5b19fecd87ec9f872ab7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 26 Feb 2020 13:45:46 +0100 Subject: [PATCH 486/559] Clean up wifi connection / disconnection --- tasmota/settings.h | 2 +- tasmota/settings.ino | 4 ++++ tasmota/support_wifi.ino | 22 ++++++++++++++-------- tasmota/xdrv_01_webserver.ino | 4 ++++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index ec81d5345..886fe7ccf 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -132,7 +132,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t spare28 : 1; uint32_t spare29 : 1; uint32_t spare30 : 1; - uint32_t force_sdk_erase : 1; // bit 31 (v8.1.0.9) - SetOption113 - Force erase of SDK wifi calibrate secore on restart + uint32_t spare31 : 1; // bit 31 }; } SysBitfield4; diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 1563897b0..5ebf970d4 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -774,6 +774,10 @@ void SettingsErase(uint8_t type) _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0xxFCFFF) } */ + else { + return; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); // EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 8f7de0f96..c98bdc226 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -21,7 +21,8 @@ * Wifi \*********************************************************************************************/ -// Enable only one of two below debug options +// Enable one of three below options for wifi re-connection debugging +//#define WIFI_FORCE_RF_CAL_ERASE // Erase rf calibration sector on restart only //#define WIFI_RF_MODE_RF_CAL // Set RF_MODE to RF_CAL for restart and deepsleep during user_rf_pre_init //#define WIFI_RF_PRE_INIT // Set RF_MODE to RF_CAL for restart, deepsleep and power on during user_rf_pre_init @@ -34,7 +35,7 @@ const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart const uint8_t WIFI_CHECK_SEC = 20; // seconds -const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds +const uint8_t WIFI_RETRY_OFFSET_SEC = 12; // seconds #include // Wifi, MQTT, Ota, WifiManager #if LWIP_IPV6 @@ -645,7 +646,7 @@ void WifiConnect(void) WifiSetOutputPower(); WiFi.persistent(false); // Solve possible wifi init errors Wifi.status = 0; - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); + Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP.getChipId() & 0xF); // Add extra delay to stop overrun by simultanous re-connects Wifi.retry = Wifi.retry_init; Wifi.counter = 1; @@ -659,29 +660,34 @@ void WifiConnect(void) void WifiShutdown(bool option = false) { // option = false - Legacy disconnect also used by DeepSleep - // option = true - Disconnect with SDK wifi calibrate sector erase + // option = true - Disconnect with SDK wifi calibrate sector erase when WIFI_FORCE_RF_CAL_ERASE enabled delay(100); // Allow time for message xfer - disabled v6.1.0b #ifdef USE_EMULATION UdpDisconnect(); + delay(100); // Flush anything in the network buffers. #endif // USE_EMULATION if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT MqttDisconnect(); + delay(100); // Flush anything in the network buffers. } - if (option && Settings.flag4.force_sdk_erase) { // SetOption113 - Force erase of SDK wifi calibrate sector on restart +#ifdef WIFI_FORCE_RF_CAL_ERASE + if (option) { WiFi.disconnect(false); // Disconnect wifi SettingsErase(4); // Delete SDK wifi config and calibrate data - } else { + } else +#endif // WIFI_FORCE_RF_CAL_ERASE + { // Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 // Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset // Courtesy of EspEasy - WiFi.persistent(true); // use SDK storage of SSID/WPA parameters + WiFi.persistent(true); // use SDK storage of SSID/WPA parameters ETS_UART_INTR_DISABLE(); wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters + WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters } delay(100); // Flush anything in the network buffers. } diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 33efee99b..3b408cf66 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1882,6 +1882,7 @@ void HandleOtherConfiguration(void) } #ifdef USE_EMULATION +#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) WSContentSend_P(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
for (uint32_t i = 0; i < EMUL_MAX; i++) { #ifndef USE_EMULATION_WEMO @@ -1899,6 +1900,7 @@ void HandleOtherConfiguration(void) } } WSContentSend_P(PSTR("

")); +#endif // USE_EMULATION_WEMO || USE_EMULATION_HUE #endif // USE_EMULATION WSContentSend_P(HTTP_FORM_END); @@ -1917,8 +1919,10 @@ void OtherSaveSettings(void) SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp); Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); // SetOption3 - Enable MQTT #ifdef USE_EMULATION +#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) WebGetArg("b2", tmp, sizeof(tmp)); Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); +#endif // USE_EMULATION_WEMO || USE_EMULATION_HUE #endif // USE_EMULATION snprintf_P(message, sizeof(message), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); From f57a4d217cea3baee93bee60c667545f79cb15c4 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 26 Feb 2020 14:39:27 +0100 Subject: [PATCH 487/559] Prepare for PWM Dimmer Prepare for PWM Dimmer (#7791) --- tasmota/settings.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 886fe7ccf..20000aa9f 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -105,9 +105,9 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t zigbee_use_names : 1; // bit 1 (v8.1.0.4) - SetOption83 - Use FriendlyNames instead of ShortAddresses when possible uint32_t awsiot_shadow : 1; // bit 2 (v8.1.0.5) - SetOption84 - (AWS IoT) publish MQTT state to a device shadow uint32_t device_groups_enabled : 1; // bit 3 (v8.1.0.9) - SetOption85 - Enable Device Groups - uint32_t spare04 : 1; - uint32_t spare05 : 1; - uint32_t spare06 : 1; + uint32_t led_timeout : 1; // bit 4 (v8.1.0.9) - SetOption86 - Turn brightness LED's off 5 seconds after last change + uint32_t powered_off_led : 1; // bit 5 (v8.1.0.9) - SetOption87 - Turn red LED on when powered off + uint32_t remote_device_mode : 1; // bit 6 (v8.1.0.9) - SetOption88 - Buttons control remote devices uint32_t spare07 : 1; uint32_t spare08 : 1; uint32_t spare09 : 1; @@ -465,9 +465,13 @@ struct SYSCFG { uint8_t mqttlog_level; // F01 uint8_t sps30_inuse_hours; // F02 uint8_t hotplug_scan; // F03 - uint8_t reserved1; // F04 - reserved for s-hadinger + uint8_t bri_power_on; // F04 + uint8_t bri_min; // F05 + uint8_t bri_preset_low; // F06 + uint8_t bri_preset_high; // F07 + uint8_t button_devices; // F08 - uint8_t free_f05[199]; // F05 + uint8_t free_f05[195]; // F09 uint32_t device_group_share_in; // FCC - Bitmask of device group items imported uint32_t device_group_share_out; // FD0 - Bitmask of device group items exported From 8dbfa7d6b539869835685563c62b1f8e1ba11386 Mon Sep 17 00:00:00 2001 From: "he.so" Date: Wed, 26 Feb 2020 19:46:44 +0100 Subject: [PATCH 488/559] fixed repeated sending of code --- tasmota/xdrv_35_keeloq.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_35_keeloq.ino b/tasmota/xdrv_35_keeloq.ino index c1fec39fe..ce6185923 100644 --- a/tasmota/xdrv_35_keeloq.ino +++ b/tasmota/xdrv_35_keeloq.ino @@ -113,14 +113,15 @@ void CmdSendButton(void) for(int repeat = 0; repeat <= 1; repeat++) { - digitalWrite(TX_PORT, LOW); // CC1101 in TX Mode+ + uint64_t bitsToSend = jaroliftDevice.pack; + digitalWrite(TX_PORT, LOW); delayMicroseconds(1150); SendSyncPreamble(13); delayMicroseconds(3500); for(int i=72; i>0; i--) { - SendBit(jaroliftDevice.pack & 0x0000000000000001); - jaroliftDevice.pack >>= 1; + SendBit(bitsToSend & 0x0000000000000001); + bitsToSend >>= 1; } DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("finished sending bits at %d"), micros()); From 71340dc8b6204f18e546f11df0895719f1182937 Mon Sep 17 00:00:00 2001 From: "he.so" Date: Wed, 26 Feb 2020 20:10:29 +0100 Subject: [PATCH 489/559] push travis, since it had an environment issue during last build --- tasmota/settings.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index 37f23a085..6ce07c30e 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -470,8 +470,7 @@ struct SYSCFG { uint8_t bri_preset_low; // F06 uint8_t bri_preset_high; // F07 uint8_t button_devices; // F08 - - uint8_t free_f05[179]; // F09 + uint8_t free_f09[179]; // F09 uint32_t keeloq_master_msb; // FBC uint32_t keeloq_master_lsb; // FC0 From 5d54356a25d851696b7210ddda406a6a1ee40c79 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Wed, 26 Feb 2020 21:43:46 +0100 Subject: [PATCH 490/559] Remove code with no effect --- tasmota/support_wifi.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index c98bdc226..f4e88a49d 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -683,11 +683,11 @@ void WifiShutdown(bool option = false) // Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 // Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset // Courtesy of EspEasy - WiFi.persistent(true); // use SDK storage of SSID/WPA parameters + // WiFi.persistent(true); // use SDK storage of SSID/WPA parameters ETS_UART_INTR_DISABLE(); wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters + // WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters } delay(100); // Flush anything in the network buffers. } From 792f5cfb19e7c2c0561843b30093999662ea9ee0 Mon Sep 17 00:00:00 2001 From: Barbudor Date: Wed, 26 Feb 2020 22:14:08 +0100 Subject: [PATCH 491/559] Allow Sensor13 to define customer value for shunt resistor, including code refactoring --- tasmota/xsns_13_ina219.ino | 148 +++++++++++++++++++++++-------------- 1 file changed, 94 insertions(+), 54 deletions(-) diff --git a/tasmota/xsns_13_ina219.ino b/tasmota/xsns_13_ina219.ino index e1177e35f..f5539cf31 100644 --- a/tasmota/xsns_13_ina219.ino +++ b/tasmota/xsns_13_ina219.ino @@ -51,23 +51,30 @@ #define INA219_CONFIG_GAIN_8_320MV (0x1800) // Gain 8, 320mV Range #define INA219_CONFIG_BADCRES_MASK (0x0780) // Bus ADC Resolution Mask -#define INA219_CONFIG_BADCRES_9BIT (0x0080) // 9-bit bus res = 0..511 -#define INA219_CONFIG_BADCRES_10BIT (0x0100) // 10-bit bus res = 0..1023 -#define INA219_CONFIG_BADCRES_11BIT (0x0200) // 11-bit bus res = 0..2047 -#define INA219_CONFIG_BADCRES_12BIT (0x0400) // 12-bit bus res = 0..4097 +#define INA219_CONFIG_BADCRES_9BIT_1S_84US (0x0<<7) // 9-bit bus res = 0..511 +#define INA219_CONFIG_BADCRES_10BIT_1S_148US (0x1<<7) // 10-bit bus res = 0..1023 +#define INA219_CONFIG_BADCRES_11BIT_1S_276US (0x2<<7) // 11-bit bus res = 0..2047 +#define INA219_CONFIG_BADCRES_12BIT_1S_532US (0x3<<7) // 12-bit bus res = 0..4097 +#define INA219_CONFIG_BADCRES_12BIT_2S_1060US (0x9<<7) // 2 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_4S_2130US (0xA<<7) // 4 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_8S_4260US (0xB<<7) // 8 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_16S_8510US (0xC<<7) // 16 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_32S_17MS (0xD<<7) // 32 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_64S_34MS (0xE<<7) // 64 x 12-bit bus samples averaged together +#define INA219_CONFIG_BADCRES_12BIT_128S_69MS (0xF<<7) // 128 x 12-bit bus samples averaged together #define INA219_CONFIG_SADCRES_MASK (0x0078) // Shunt ADC Resolution and Averaging Mask -#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) // 1 x 9-bit shunt sample -#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) // 1 x 10-bit shunt sample -#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) // 1 x 11-bit shunt sample -#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) // 1 x 12-bit shunt sample -#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) // 2 x 12-bit shunt samples averaged together -#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) // 4 x 12-bit shunt samples averaged together -#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) // 8 x 12-bit shunt samples averaged together -#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) // 16 x 12-bit shunt samples averaged together -#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) // 32 x 12-bit shunt samples averaged together -#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) // 64 x 12-bit shunt samples averaged together -#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) // 128 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0<<3) // 1 x 9-bit shunt sample +#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x1<<3) // 1 x 10-bit shunt sample +#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x2<<3) // 1 x 11-bit shunt sample +#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x3<<3) // 1 x 12-bit shunt sample +#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x9<<3) // 2 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0xA<<3) // 4 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0xB<<3) // 8 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0xC<<3) // 16 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0xD<<3) // 32 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0xE<<3) // 64 x 12-bit shunt samples averaged together +#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0xF<<3) // 128 x 12-bit shunt samples averaged together #define INA219_CONFIG_MODE_MASK (0x0007) // Operating Mode Mask #define INA219_CONFIG_MODE_POWERDOWN (0x0000) @@ -85,12 +92,20 @@ #define INA219_REG_CURRENT (0x04) #define INA219_REG_CALIBRATION (0x05) +#define INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS (100.0) // 0.1 Ohm + uint8_t ina219_type[4] = {0,0,0,0}; uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; -uint32_t ina219_cal_value = 0; -// The following multiplier is used to convert raw current values to mA, taking into account the current config settings -uint32_t ina219_current_divider_ma = 0; +#define __DEBUG__(a) + +__DEBUG__(char __dbg1[20];) +__DEBUG__(char __dbg2[20];) + +// The following multiplier is used to convert shunt voltage (in mV) to current (in A) +// Current_A = ShuntVoltage_mV / ShuntResistor_milliOhms = ShuntVoltage_mV * ina219_current_multiplier +// ina219_current_multiplier = 1 / ShuntResistor_milliOhms +float ina219_current_multiplier; uint8_t ina219_valid[4] = {0,0,0,0}; float ina219_voltage[4] = {0,0,0,0}; @@ -98,54 +113,71 @@ float ina219_current[4] = {0,0,0,0}; char ina219_types[] = "INA219"; uint8_t ina219_count = 0; +/*********************************************************************************************\ + * Calculate current multiplier depending on the selected mode + * For mode = 0, 1, 2 : legacy modes simplified as Vmax: 32V, Imax: 3.2A range + * For mode = 10..255 : specify Rshunt encoded as RRM where resistor value is RR * 10^M milliOhms + * Vmax: 32V, Imax: 0.320 / Rshunt + * Exemple: + * 10: Rshunt = 1 * 10^0 = 1 millOhms => Max current = 320A ! + * 11: Rshunt = 1 * 10^1 = 10 milliOhms => Max current = 32A + * 21: Rshunt = 2 * 10^1 = 20 milliOhms => Max current = 16A + * 12: Rshunt = 1 * 10^2 = 100 milliOhms => Max current = 3.2A == mode 0,1,2 + * 13: Rshunt = 1 * 10^3 = 1 Ohms => Max current = 320mA + * Note that some shunt values can be represented by 2 different encoded values such as + * 11 or 100 both present 10 milliOhms + * Because it is difficult to make a range check on such encoded value, none is performed +\*********************************************************************************************/ bool Ina219SetCalibration(uint8_t mode, uint16_t addr) { uint16_t config = 0; - switch (mode &3) { - case 0: // 32V 2A - case 3: - ina219_cal_value = 4096; - ina219_current_divider_ma = 10; // Current LSB = 100uA per bit (1000/100 = 10) - config = INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - case 1: // 32V 1A - ina219_cal_value = 10240; - ina219_current_divider_ma = 25; // Current LSB = 40uA per bit (1000/40 = 25) - config |= INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; - case 2: // 16V 0.4A - ina219_cal_value = 8192; - ina219_current_divider_ma = 20; // Current LSB = 50uA per bit (1000/50 = 20) - config |= INA219_CONFIG_BVOLTAGERANGE_16V | INA219_CONFIG_GAIN_1_40MV | INA219_CONFIG_BADCRES_12BIT | INA219_CONFIG_SADCRES_12BIT_1S_532US | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; - break; + __DEBUG__(printf("mode = %d\n",mode);) + if (mode < 5) + { + // All legacy modes 0..2 are handled the same and consider default 0.1 shunt resistor + ina219_current_multiplier = 1.0 / INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS; + __DEBUG__(dtostrfd(ina219_current_multiplier,5,__dbg1);) + __DEBUG__(printf("cur_mul=%s\n",__dbg1);) } - // Set Calibration register to 'Cal' calculated above - bool success = I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); - if (success) { - // Set Config register to take into account the settings above - I2cWrite16(addr, INA219_REG_CONFIG, config); + else if (mode >= 10) + { + int mult = mode % 10; + int shunt_milliOhms = mode / 10; + for ( ; mult > 0 ; mult-- ) + shunt_milliOhms *= 10; + ina219_current_multiplier = 1.0 / shunt_milliOhms; + __DEBUG__(dtostrfd(ina219_current_multiplier,5,__dbg1);) + __DEBUG__(printf("shunt = %dmO => cur_mul=%s\n",shunt_milliOhms,__dbg1);) } - return success; + config = INA219_CONFIG_BVOLTAGERANGE_32V + | INA219_CONFIG_GAIN_8_320MV // Use max scale + | INA219_CONFIG_BADCRES_12BIT_16S_8510US // use averaging to improve accuracy + | INA219_CONFIG_SADCRES_12BIT_16S_8510US // use averaging to improve accuracy + | INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + // Set Config register to take into account the settings above + return I2cWrite16(addr, INA219_REG_CONFIG, config); } float Ina219GetShuntVoltage_mV(uint16_t addr) { // raw shunt voltage (16-bit signed integer, so +-32767) int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); - // shunt voltage in mV (so +-327mV) + __DEBUG__(printf("ShR = 0x%04X\n",value);) + // convert to shunt voltage in mV (so +-327mV) (LSB=10µV=0.01mV) return value * 0.01; } float Ina219GetBusVoltage_V(uint16_t addr) { - // Shift to the right 3 to drop CNVR and OVF and multiply by LSB - // raw bus voltage (16-bit signed integer, so +-32767) - int16_t value = (int16_t)(((uint16_t)I2cReadS16(addr, INA219_REG_BUSVOLTAGE) >> 3) * 4); - // bus voltage in volts - return value * 0.001; + // Shift 3 to the right to drop CNVR and OVF as unsigned + uint16_t value = I2cRead16(addr, INA219_REG_BUSVOLTAGE) >> 3; + __DEBUG__(printf("BusR = 0x%04X\n",value);) + // and multiply by LSB raw bus voltage to return bus voltage in volts (LSB=4mV=0.004V) + return value * 0.004; } +/* float Ina219GetCurrent_mA(uint16_t addr) { // Sometimes a sharp load will reset the INA219, which will reset the cal register, @@ -159,14 +191,25 @@ float Ina219GetCurrent_mA(uint16_t addr) // current value in mA, taking into account the config settings and current LSB return value; } +*/ bool Ina219Read(void) { for (int i=0; i= 0) && (XdrvMailbox.payload <= 2)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { Settings.ina219_mode = XdrvMailbox.payload; restart_flag = 2; } @@ -201,6 +240,7 @@ void Ina219Detect(void) if (I2cActive(addr)) { continue; } if (Ina219SetCalibration(Settings.ina219_mode, addr)) { I2cSetActiveFound(addr, ina219_types); + __DEBUG__(printf("found INA#%d @ 0x%02X\n",i,addr);) ina219_type[i] = 1; ina219_count++; } From b3d918f46595579ecb58e2e4599bdd5779c4d9e9 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Tue, 25 Feb 2020 06:19:12 -0600 Subject: [PATCH 492/559] Add MQTT commands --- PWM_Dimmer.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md index 528b3f9fb..172a7663a 100644 --- a/PWM_Dimmer.md +++ b/PWM_Dimmer.md @@ -97,6 +97,8 @@ Holding the power button, pressing the down/up buttons a given number of times a Holding any button for over 10 seconds executes the WiFiConfig 2 command. +Pressing and releasing a button publishes an MQTT TOGGLE command. Holding a button publishes an MQTT HOLD command followed by an MQTT OFF command when the button is released. + When Device Groups are enabled, the PWM Dimmer minimum brightness and brightness presets are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. From 1655c1b3aa94055d58535f539081a6b91c0a5e3d Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Feb 2020 16:49:19 +0100 Subject: [PATCH 493/559] Add some wifi debug options --- tasmota/settings.h | 2 +- tasmota/settings.ino | 16 ++------ tasmota/support_wifi.ino | 80 ++++++++++++++++++++++++++++++---------- tasmota/tasmota_post.h | 4 +- 4 files changed, 67 insertions(+), 35 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index fe7c31549..d2570d9ba 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -132,7 +132,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t spare28 : 1; uint32_t spare29 : 1; uint32_t spare30 : 1; - uint32_t spare31 : 1; + uint32_t force_sdk_erase : 1; // bit 31 (v8.1.0.9) - SetOption113 - Force erase of SDK wifi calibrate secore on restart }; } SysBitfield4; diff --git a/tasmota/settings.ino b/tasmota/settings.ino index c2ddc6607..1563897b0 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -745,6 +745,7 @@ void SettingsErase(uint8_t type) 1 = Erase 16k SDK parameter area near end of flash as seen by SDK (0x0xFCxxx - 0x0xFFFFF) solving possible wifi errors 2 = Erase Tasmota parameter area (0x0xF3xxx - 0x0xFBFFF) 3 = Erase Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) + 4 = Erase SDK parameter area used for wifi calibration (0x0FCxxx - 0x0FCFFF) */ #ifndef FIRMWARE_MINIMAL @@ -762,16 +763,17 @@ void SettingsErase(uint8_t type) _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF) _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; // Flash size as seen by SDK } -#ifdef USE_WIFI_SDK_ERASE else if (4 == type) { +// _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; // SDK phy area and Core calibration sector (0x0FC000) _sectorStart = SETTINGS_LOCATION +1; // SDK phy area and Core calibration sector (0x0FC000) _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0x0FCFFF) } +/* else if (5 == type) { _sectorStart = (ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE) -4; // SDK phy area and Core calibration sector (0xxFC000) _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0xxFCFFF) } -#endif // USE_WIFI_SDK_ERASE +*/ AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); // EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK @@ -786,16 +788,6 @@ void SettingsSdkErase(void) delay(1000); } -#ifdef USE_WIFI_SDK_ERASE -void SettingsSdkWifiErase(void) -{ - WiFi.disconnect(false); // Delete SDK wifi config - SettingsErase(4); - SettingsErase(5); - delay(200); -} -#endif // USE_WIFI_SDK_ERASE - /********************************************************************************************/ void SettingsDefault(void) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index dd8d2441c..93dba06a9 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -21,6 +21,10 @@ * Wifi \*********************************************************************************************/ +// Enable only one of two below debug options +//#define WIFI_RF_MODE_RF_CAL // Set RF_MODE to RF_CAL for restart and deepsleep during user_rf_pre_init +#define WIFI_RF_PRE_INIT // Set RF_MODE to RF_CAL for restart, deepsleep and power on during user_rf_pre_init + #ifndef WIFI_RSSI_THRESHOLD #define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network #endif @@ -609,6 +613,32 @@ void WifiSetOutputPower(void) WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10); } +/* + See Esp.h, core_esp8266_phy.cpp and test_overrides.ino + RF_DEFAULT = 0, // RF_CAL or not after deep-sleep wake up, depends on init data byte 108. + RF_CAL = 1, // RF_CAL after deep-sleep wake up, there will be large current. + RF_NO_CAL = 2, // no RF_CAL after deep-sleep wake up, there will only be small current. + RF_DISABLED = 4 // disable RF after deep-sleep wake up, just like modem sleep, there will be the smallest current. +*/ +#ifdef WIFI_RF_MODE_RF_CAL +#ifndef USE_DEEPSLEEP +RF_MODE(RF_CAL); +#endif // USE_DEEPSLEEP +#endif // WIFI_RF_MODE_RF_CAL + +#ifdef WIFI_RF_PRE_INIT +bool rf_pre_init_flag = false; +RF_PRE_INIT() +{ +#ifndef USE_DEEPSLEEP + system_deep_sleep_set_option(1); // The option is 1 by default. + system_phy_set_rfoption(RF_CAL); +#endif // USE_DEEPSLEEP + system_phy_set_powerup_option(3); // 3: RF initialization will do the whole RF calibration which will take about 200ms; this increases the current consumption. + rf_pre_init_flag = true; +} +#endif // WIFI_RF_PRE_INIT + void WifiConnect(void) { WifiSetState(0); @@ -618,37 +648,47 @@ void WifiConnect(void) Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); Wifi.retry = Wifi.retry_init; Wifi.counter = 1; + +#ifdef WIFI_RF_PRE_INIT + if (rf_pre_init_flag) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_WIFI "Pre-init done")); + } +#endif // WIFI_RF_PRE_INIT } -// Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 -// Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset -void WifiDisconnect(void) -{ -#ifdef USE_WIFI_SDK_ERASE // Do not enable with DeepSleep as it will wear out flash - SettingsSdkWifiErase(); -#else - // Courtesy of EspEasy - WiFi.persistent(true); // use SDK storage of SSID/WPA parameters - ETS_UART_INTR_DISABLE(); - wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage - ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters - delay(100); // Flush anything in the network buffers. -#endif // USE_WIFI_SDK_ERASE -} - -void WifiShutdown(void) +void WifiShutdown(bool option = false) { + // option = false - Legacy disconnect also used by DeepSleep + // option = true - Disconnect with SDK wifi calibrate sector erase delay(100); // Allow time for message xfer - disabled v6.1.0b + +#ifdef USE_EMULATION + UdpDisconnect(); +#endif // USE_EMULATION + if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT MqttDisconnect(); } - WifiDisconnect(); + + if (option && Settings.flag4.force_sdk_erase) { // SetOption113 - Force erase of SDK wifi calibrate sector on restart + WiFi.disconnect(false); // Disconnect wifi + SettingsErase(4); // Delete SDK wifi config and calibrate data + } else { + // Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 + // Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset + // Courtesy of EspEasy + WiFi.persistent(true); // use SDK storage of SSID/WPA parameters + ETS_UART_INTR_DISABLE(); + wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage + ETS_UART_INTR_ENABLE(); + WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters + } + delay(100); // Flush anything in the network buffers. } void EspRestart(void) { - WifiShutdown(); + WifiShutdown(true); CrashDumpClear(); // Clear the stack dump in RTC // ESP.restart(); // This results in exception 3 on restarts on core 2.3.0 ESP.reset(); diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 5f031a2f9..d8a8ea5d1 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -708,11 +708,11 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #endif #ifndef MESSZ -//#define MESSZ 1040 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1200) +//#define MESSZ 1040 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1200) #define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string #endif -//#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) +//#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) #ifndef ARDUINO_ESP8266_RELEASE #define ARDUINO_ESP8266_RELEASE "STAGE" #endif From 8ca95996f98d64e868945097a023d5d66ac1526c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 25 Feb 2020 16:52:07 +0100 Subject: [PATCH 494/559] Restore default wifi functionality --- tasmota/support_wifi.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 93dba06a9..8f7de0f96 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -23,7 +23,7 @@ // Enable only one of two below debug options //#define WIFI_RF_MODE_RF_CAL // Set RF_MODE to RF_CAL for restart and deepsleep during user_rf_pre_init -#define WIFI_RF_PRE_INIT // Set RF_MODE to RF_CAL for restart, deepsleep and power on during user_rf_pre_init +//#define WIFI_RF_PRE_INIT // Set RF_MODE to RF_CAL for restart, deepsleep and power on during user_rf_pre_init #ifndef WIFI_RSSI_THRESHOLD #define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network From 344187cf94d03464408c9f15dd8cdd126e44f065 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Tue, 25 Feb 2020 17:55:45 +0100 Subject: [PATCH 495/559] minor bug fixes and enhancements - fix bug in multi-push from last commit - remove rules execution every second. only at start and stop - enable rules for Shutter#Button - tbd: How to correctly detect a simultaneous button push --- tasmota/xdrv_27_shutter.ino | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 6f4d711d7..1131a5f70 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -255,6 +255,7 @@ void ShutterInit(void) void ShutterReportPosition(bool always) { Response_P(PSTR("{")); + rules_flag.shutter_moving = 0; for (uint32_t i = 0; i < shutters_present; i++) { //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d"), i+1,Shutter.real_position[i]); uint32_t position = ShutterRealToPercentPosition(Shutter.real_position[i], i); @@ -268,7 +269,6 @@ void ShutterReportPosition(bool always) ResponseJsonEnd(); if (always || (rules_flag.shutter_moving)) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); - XdrvRulesProcess(); } //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); @@ -299,18 +299,23 @@ void ShutterUpdatePosition(void) int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); int32_t min_runtime_ms = Shutter.pwm_frequency[i]*1000 / max_freq_change_per_sec; int32_t velocity = Shutter.direction[i] == 1 ? 100 : Shutter.close_velocity[i]; - int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency[i] / max_frequency * Shutter.direction[i] ; + int32_t minstopway = min_runtime_ms * velocity / 100 * Shutter.pwm_frequency[i] / max_frequency * Shutter.direction[i] ; int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; stop_position_delta =200 * Shutter.pwm_frequency[i]/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); + if (Shutter.time[i] == 1) { + ShutterReportPosition(true); + rules_flag.shutter_moving = 1; + XdrvRulesProcess(); + } //Shutter.accelerator[i] = tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); //int32_t act_freq_change = max_freq_change_per_sec/20; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, Shutter.pwm_frequency[i],max_frequency, Shutter.accelerator[i],min_runtime_ms,Shutter.real_position[i], next_possible_stop,Shutter.target_position[i]); - if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > Shutter.target_position[i] * Shutter.direction[i] ) { + if (Shutter.accelerator[i] < 0 || next_possible_stop * Shutter.direction[i] > (Shutter.target_position[i]- (100 * Shutter.direction[i])) * Shutter.direction[i] ) { - Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*12/200); + Shutter.accelerator[i] = - tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Ramp down: acc: %d"), Shutter.accelerator[i]); } else if ( Shutter.accelerator[i] > 0 && Shutter.pwm_frequency[i] == max_frequency) { Shutter.accelerator[i] = 0; @@ -348,7 +353,7 @@ void ShutterUpdatePosition(void) } analogWrite(pin[GPIO_PWM1+i], 0); Shutter.real_position[i] = ShutterCounterBasedPosition(i); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Real %d, pulsecount %d, start %d"), Shutter.real_position[i],RtcSettings.pulse_counter[i], Shutter.start_position[i]); if ((1 << (Settings.shutter_startrelay[i]-1)) & power) { ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER); @@ -422,6 +427,8 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter.time[i] = 0; Shutter.skip_relay_change = 0; Shutter.direction[i] = direction; + rules_flag.shutter_moving = 1; + rules_flag.shutter_moved = 0; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); } //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), i, Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i]); @@ -538,6 +545,7 @@ void ShutterButtonHandler(void) Button.press_counter[button_index] = 99; // Remember to discard further action for press & hold within button timings } else { Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; + Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window } } blinks = 201; @@ -590,15 +598,16 @@ void ShutterButtonHandler(void) // check for simultaneous shutter button press uint32 min_shutterbutton_press_counter = -1; for (uint32_t i = 0; i < MAX_KEYS; i++) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter); - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d, i %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i); + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { min_shutterbutton_press_counter = Button.press_counter[i]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: min_shutterbutton_press_counter %d"), min_shutterbutton_press_counter); } } if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { // simultaneous shutter button press detected - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT:simultanous presss deteced")); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: simultanous presss deteced")); press_index = Button.press_counter[button_index]; for (uint32_t i = 0; i < MAX_KEYS; i++) if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index)) @@ -678,6 +687,7 @@ void ShutterButtonHandler(void) ResponseJsonEnd(); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); XdrvRulesProcess(); + } } From f2074932f7113b7143d375539cc89324b7d12493 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 26 Feb 2020 13:45:46 +0100 Subject: [PATCH 496/559] Clean up wifi connection / disconnection --- tasmota/settings.h | 2 +- tasmota/settings.ino | 4 ++++ tasmota/support_wifi.ino | 22 ++++++++++++++-------- tasmota/xdrv_01_webserver.ino | 4 ++++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index d2570d9ba..be9e7bf40 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -132,7 +132,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t spare28 : 1; uint32_t spare29 : 1; uint32_t spare30 : 1; - uint32_t force_sdk_erase : 1; // bit 31 (v8.1.0.9) - SetOption113 - Force erase of SDK wifi calibrate secore on restart + uint32_t spare31 : 1; // bit 31 }; } SysBitfield4; diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 1563897b0..5ebf970d4 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -774,6 +774,10 @@ void SettingsErase(uint8_t type) _sectorEnd = _sectorStart +1; // SDK end of phy area and Core calibration sector (0xxFCFFF) } */ + else { + return; + } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " from 0x%08X to 0x%08X"), _sectorStart * SPI_FLASH_SEC_SIZE, (_sectorEnd * SPI_FLASH_SEC_SIZE) -1); // EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK diff --git a/tasmota/support_wifi.ino b/tasmota/support_wifi.ino index 8f7de0f96..c98bdc226 100644 --- a/tasmota/support_wifi.ino +++ b/tasmota/support_wifi.ino @@ -21,7 +21,8 @@ * Wifi \*********************************************************************************************/ -// Enable only one of two below debug options +// Enable one of three below options for wifi re-connection debugging +//#define WIFI_FORCE_RF_CAL_ERASE // Erase rf calibration sector on restart only //#define WIFI_RF_MODE_RF_CAL // Set RF_MODE to RF_CAL for restart and deepsleep during user_rf_pre_init //#define WIFI_RF_PRE_INIT // Set RF_MODE to RF_CAL for restart, deepsleep and power on during user_rf_pre_init @@ -34,7 +35,7 @@ const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart const uint8_t WIFI_CHECK_SEC = 20; // seconds -const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds +const uint8_t WIFI_RETRY_OFFSET_SEC = 12; // seconds #include // Wifi, MQTT, Ota, WifiManager #if LWIP_IPV6 @@ -645,7 +646,7 @@ void WifiConnect(void) WifiSetOutputPower(); WiFi.persistent(false); // Solve possible wifi init errors Wifi.status = 0; - Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + ((ESP.getChipId() & 0xF) * 2); + Wifi.retry_init = WIFI_RETRY_OFFSET_SEC + (ESP.getChipId() & 0xF); // Add extra delay to stop overrun by simultanous re-connects Wifi.retry = Wifi.retry_init; Wifi.counter = 1; @@ -659,29 +660,34 @@ void WifiConnect(void) void WifiShutdown(bool option = false) { // option = false - Legacy disconnect also used by DeepSleep - // option = true - Disconnect with SDK wifi calibrate sector erase + // option = true - Disconnect with SDK wifi calibrate sector erase when WIFI_FORCE_RF_CAL_ERASE enabled delay(100); // Allow time for message xfer - disabled v6.1.0b #ifdef USE_EMULATION UdpDisconnect(); + delay(100); // Flush anything in the network buffers. #endif // USE_EMULATION if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT MqttDisconnect(); + delay(100); // Flush anything in the network buffers. } - if (option && Settings.flag4.force_sdk_erase) { // SetOption113 - Force erase of SDK wifi calibrate sector on restart +#ifdef WIFI_FORCE_RF_CAL_ERASE + if (option) { WiFi.disconnect(false); // Disconnect wifi SettingsErase(4); // Delete SDK wifi config and calibrate data - } else { + } else +#endif // WIFI_FORCE_RF_CAL_ERASE + { // Enable from 6.0.0a until 6.1.0a - disabled due to possible cause of bad wifi connect on core 2.3.0 // Re-enabled from 6.3.0.7 with ESP.restart replaced by ESP.reset // Courtesy of EspEasy - WiFi.persistent(true); // use SDK storage of SSID/WPA parameters + WiFi.persistent(true); // use SDK storage of SSID/WPA parameters ETS_UART_INTR_DISABLE(); wifi_station_disconnect(); // this will store empty ssid/wpa into sdk storage ETS_UART_INTR_ENABLE(); - WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters + WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters } delay(100); // Flush anything in the network buffers. } diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 705bd4a15..7e7292a8c 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1893,6 +1893,7 @@ void HandleOtherConfiguration(void) } #ifdef USE_EMULATION +#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) WSContentSend_P(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
for (uint32_t i = 0; i < EMUL_MAX; i++) { #ifndef USE_EMULATION_WEMO @@ -1910,6 +1911,7 @@ void HandleOtherConfiguration(void) } } WSContentSend_P(PSTR("

")); +#endif // USE_EMULATION_WEMO || USE_EMULATION_HUE #endif // USE_EMULATION WSContentSend_P(HTTP_FORM_END); @@ -1928,8 +1930,10 @@ void OtherSaveSettings(void) SettingsUpdateText(SET_WEBPWD, (!strlen(tmp)) ? "" : (strchr(tmp,'*')) ? SettingsText(SET_WEBPWD) : tmp); Settings.flag.mqtt_enabled = WebServer->hasArg("b1"); // SetOption3 - Enable MQTT #ifdef USE_EMULATION +#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) WebGetArg("b2", tmp, sizeof(tmp)); Settings.flag2.emulation = (!strlen(tmp)) ? 0 : atoi(tmp); +#endif // USE_EMULATION_WEMO || USE_EMULATION_HUE #endif // USE_EMULATION snprintf_P(message, sizeof(message), PSTR(D_LOG_OTHER D_MQTT_ENABLE " %s, " D_CMND_EMULATION " %d, " D_CMND_FRIENDLYNAME), GetStateText(Settings.flag.mqtt_enabled), Settings.flag2.emulation); From 878d93ebdbd45e47b0704adc4ff23d4508b12630 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 26 Feb 2020 14:39:27 +0100 Subject: [PATCH 497/559] Prepare for PWM Dimmer Prepare for PWM Dimmer (#7791) --- tasmota/settings.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index be9e7bf40..13b4d03a1 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -105,9 +105,9 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t zigbee_use_names : 1; // bit 1 (v8.1.0.4) - SetOption83 - Use FriendlyNames instead of ShortAddresses when possible uint32_t awsiot_shadow : 1; // bit 2 (v8.1.0.5) - SetOption84 - (AWS IoT) publish MQTT state to a device shadow uint32_t device_groups_enabled : 1; // bit 3 (v8.1.0.9) - SetOption85 - Enable Device Groups - uint32_t spare04 : 1; - uint32_t spare05 : 1; - uint32_t spare06 : 1; + uint32_t led_timeout : 1; // bit 4 (v8.1.0.9) - SetOption86 - Turn brightness LED's off 5 seconds after last change + uint32_t powered_off_led : 1; // bit 5 (v8.1.0.9) - SetOption87 - Turn red LED on when powered off + uint32_t remote_device_mode : 1; // bit 6 (v8.1.0.9) - SetOption88 - Buttons control remote devices uint32_t spare07 : 1; uint32_t spare08 : 1; uint32_t spare09 : 1; @@ -465,9 +465,13 @@ struct SYSCFG { uint8_t mqttlog_level; // F01 uint8_t sps30_inuse_hours; // F02 uint8_t hotplug_scan; // F03 - uint8_t reserved1; // F04 - reserved for s-hadinger + uint8_t bri_power_on; // F04 + uint8_t bri_min; // F05 + uint8_t bri_preset_low; // F06 + uint8_t bri_preset_high; // F07 + uint8_t button_devices; // F08 - uint8_t free_f05[199]; // F05 + uint8_t free_f05[195]; // F09 uint32_t device_group_share_in; // FCC - Bitmask of device group items imported uint32_t device_group_share_out; // FD0 - Bitmask of device group items exported From 1f1c956b26a79511929dfa535b820c844010f2a5 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Wed, 26 Feb 2020 21:27:09 -0600 Subject: [PATCH 498/559] Use newly allocated settings and flags --- tasmota/my_user_config.h | 4 +- tasmota/settings.h | 17 +-------- tasmota/xdrv_35_pwm_dimmer.ino | 68 +++++++++++++++++----------------- 3 files changed, 37 insertions(+), 52 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 0aedea795..0ae6d4663 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -415,9 +415,9 @@ //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug -//#define USE_DEVICE_GROUPS // Add support for device groups (+3k5 code) +#define USE_DEVICE_GROUPS // Add support for device groups (+3k5 code) #define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) -//#define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) +#define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/settings.h b/tasmota/settings.h index 13b4d03a1..da8da2f29 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -469,9 +469,8 @@ struct SYSCFG { uint8_t bri_min; // F05 uint8_t bri_preset_low; // F06 uint8_t bri_preset_high; // F07 - uint8_t button_devices; // F08 - uint8_t free_f05[195]; // F09 + uint8_t free_f05[196]; // F08 uint32_t device_group_share_in; // FCC - Bitmask of device group items imported uint32_t device_group_share_out; // FD0 - Bitmask of device group items exported @@ -579,18 +578,4 @@ typedef union { ADC_MODE(ADC_VCC); // Set ADC input for Power Supply Voltage usage #endif -// Settings re-purposed for the PWM_DIMMER module -#ifdef USE_PWM_DIMMER -#define led_timeout light_signal // SetOption18 - Turn brightness LED's off 5 seconds after last change -#define powered_off_led buzzer_enable // SetOption67 - Turn red LED on when powered off -#define bri_power_on pcf8574_config[0] // Brightness when next powered-on -#define bri_min pcf8574_config[1] // Minimum brightness -#define bri_preset_low pcf8574_config[2] // Bri preset low -#define bri_preset_high pcf8574_config[3] // Bri preset high -#define button_devices pcf8574_config[4] // Button-device map -#ifdef USE_PWM_DIMMER_REMOTE -#define remote_device_mode dds2382_model // SetOption71 - Buttons control remote devices -#endif // USE_PWM_DIMMER_REMOTE -#endif // USE_PWM_DIMMER - #endif // _SETTINGS_H_ diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index fca67efe6..94bc4ea38 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -48,10 +48,10 @@ void (* const PWMDimmerCommand[])(void) PROGMEM = { struct remote_pwm_dimmer { power_t power; uint8_t light_speed; - uint8_t x_bri_power_on; - uint8_t x_bri_min; - uint8_t x_bri_preset_low; - uint8_t x_bri_preset_high; + uint8_t bri_power_on; + uint8_t bri_min; + uint8_t bri_preset_low; + uint8_t bri_preset_high; uint8_t fixed_color_index; uint8_t bri; bool power_button_increases_bri; @@ -98,14 +98,14 @@ void PWMModuleInit() Settings.flag.pwm_control = 0; // Use basic PWM control instead of Light if (Settings.last_module != Settings.module) { - Settings.bri_min = 8; + Settings.bri_min = 25; Settings.bri_power_on = 50; - Settings.bri_preset_low = 8; + Settings.bri_preset_low = 25; Settings.bri_preset_high = 255; Settings.last_module = Settings.module; } else { - if (Settings.bri_min < 1) Settings.bri_min = 8; + if (Settings.bri_min < 1) Settings.bri_min = 25; PWMDimmerCheckBri(&Settings.bri_power_on); PWMDimmerCheckBri(&Settings.bri_preset_low); PWMDimmerCheckBri(&Settings.bri_preset_high); @@ -132,11 +132,11 @@ void PWMModuleInit() void PWMDimmerInit(void) { #ifdef USE_PWM_DIMMER_REMOTE - if (Settings.flag3.remote_device_mode) { + if (Settings.flag4.remote_device_mode) { if (device_group_count > 1) { if ((remote_pwm_dimmers = (struct remote_pwm_dimmer *) calloc(device_group_count - 1, sizeof(struct remote_pwm_dimmer))) == nullptr) { AddLog_P2(LOG_LEVEL_ERROR, PSTR("PWMDimmer: error allocating PWM dimmer array")); - Settings.flag3.remote_device_mode = false; + Settings.flag4.remote_device_mode = false; } } } @@ -166,7 +166,7 @@ void PWMDimmerSetBrightnessLeds(int32_t operation) } // If enabled, set the LED timeout. - if (!operation) led_timeout_time = (current_bri && Settings.flag.led_timeout ? millis() + 5000 : 0); + if (!operation) led_timeout_time = (current_bri && Settings.flag4.led_timeout ? millis() + 5000 : 0); } } @@ -174,7 +174,7 @@ void PWMDimmerSetPoweredOffLed(void) { // Set the powered-off LED state. if (pin[GPIO_LEDLNK] < 99) { - bool power_off_led_on = !power && Settings.flag3.powered_off_led; + bool power_off_led_on = !power && Settings.flag4.powered_off_led; if (ledlnk_inverted) power_off_led_on ^= 1; digitalWrite(pin[GPIO_LEDLNK], power_off_led_on); } @@ -370,7 +370,7 @@ void PWMDimmerHandleButton() // If there are no other buttons pressed right now and remote mode is enabled, make the device // associated with this button the device we're going to control. - if (buttons_pressed == 1 && Settings.flag3.remote_device_mode) { + if (buttons_pressed == 1 && Settings.flag4.remote_device_mode) { power_button_index = button_index; up_button_index = (button_index == 2 ? 1 : 2); down_button_index = (button_index ? 0 : 1); @@ -439,7 +439,7 @@ void PWMDimmerHandleButton() else { #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) { - active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->x_bri_preset_low; + active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_preset_low; active_remote_pwm_dimmer->power_button_increases_bri = true; } else { @@ -496,7 +496,7 @@ void PWMDimmerHandleButton() else { #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) - active_remote_pwm_dimmer->bri = (down_button_is_held ? active_remote_pwm_dimmer->x_bri_preset_low : active_remote_pwm_dimmer->x_bri_preset_high); + active_remote_pwm_dimmer->bri = (down_button_is_held ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); else #endif // USE_PWM_DIMMER_REMOTE target_bri = (down_button_is_held ? Settings.bri_preset_low : Settings.bri_preset_high); @@ -563,7 +563,7 @@ void PWMDimmerHandleButton() // Decrease/increase the minimum brightness. #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) - uint8_value = active_remote_pwm_dimmer->x_bri_min; + uint8_value = active_remote_pwm_dimmer->bri_min; else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.bri_min; @@ -575,8 +575,8 @@ void PWMDimmerHandleButton() } #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) { - active_remote_pwm_dimmer->x_bri_min = uint8_value; - if (active_remote_pwm_dimmer->x_bri_power_on < uint8_value) active_remote_pwm_dimmer->x_bri_power_on = uint8_value; + active_remote_pwm_dimmer->bri_min = uint8_value; + if (active_remote_pwm_dimmer->bri_power_on < uint8_value) active_remote_pwm_dimmer->bri_power_on = uint8_value; } else { #endif // USE_PWM_DIMMER_REMOTE @@ -618,8 +618,8 @@ void PWMDimmerHandleButton() // Decrease/increase the low brightness preset. #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) { - uint8_value = active_remote_pwm_dimmer->x_bri_preset_low; - min_uint8_value =active_remote_pwm_dimmer->x_bri_min; + uint8_value = active_remote_pwm_dimmer->bri_preset_low; + min_uint8_value =active_remote_pwm_dimmer->bri_min; } else { #endif // USE_PWM_DIMMER_REMOTE @@ -636,7 +636,7 @@ void PWMDimmerHandleButton() } #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) - active_remote_pwm_dimmer->x_bri_preset_low = uint8_value; + active_remote_pwm_dimmer->bri_preset_low = uint8_value; else #endif // USE_PWM_DIMMER_REMOTE Settings.bri_preset_low = uint8_value; @@ -647,7 +647,7 @@ void PWMDimmerHandleButton() // Decrease/increase the high brightness preset. #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) - uint8_value = active_remote_pwm_dimmer->x_bri_preset_high; + uint8_value = active_remote_pwm_dimmer->bri_preset_high; else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.bri_preset_high; @@ -659,7 +659,7 @@ void PWMDimmerHandleButton() } #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) - active_remote_pwm_dimmer->x_bri_preset_high = uint8_value; + active_remote_pwm_dimmer->bri_preset_high = uint8_value; else #endif // USE_PWM_DIMMER_REMOTE Settings.bri_preset_high = uint8_value; @@ -714,7 +714,7 @@ void PWMDimmerHandleButton() #endif // USE_DEVICE_GROUPS #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) - active_remote_pwm_dimmer->x_bri_power_on = active_remote_pwm_dimmer->bri = new_bri; + active_remote_pwm_dimmer->bri_power_on = active_remote_pwm_dimmer->bri = new_bri; else { #endif // USE_PWM_DIMMER_REMOTE Settings.bri_power_on = target_bri = new_bri; @@ -772,7 +772,7 @@ void PWMDimmerHandleButton() #ifdef USE_PWM_DIMMER_REMOTE if (active_device_is_local) { #endif // USE_PWM_DIMMER_REMOTE - Settings.flag3.powered_off_led ^= 1; + Settings.flag4.powered_off_led ^= 1; PWMDimmerSetPoweredOffLed(); #ifdef USE_PWM_DIMMER_REMOTE } @@ -803,8 +803,8 @@ void PWMDimmerHandleButton() #ifdef USE_PWM_DIMMER_REMOTE if (active_device_is_local) { #endif // USE_PWM_DIMMER_REMOTE - Settings.flag.led_timeout ^= 1; - if (relay_is_on) PWMDimmerSetBrightnessLeds(Settings.flag.led_timeout ? -1 : 0); + Settings.flag4.led_timeout ^= 1; + if (relay_is_on) PWMDimmerSetBrightnessLeds(Settings.flag4.led_timeout ? -1 : 0); #ifdef USE_PWM_DIMMER_REMOTE } #endif // USE_PWM_DIMMER_REMOTE @@ -818,7 +818,7 @@ void PWMDimmerHandleButton() else { #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) - active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->x_bri_power_on; + active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_power_on; else #endif // USE_PWM_DIMMER_REMOTE target_bri = Settings.bri_power_on; @@ -1021,14 +1021,14 @@ void CmndLedTimeout(void) switch (XdrvMailbox.payload) { case 0: // Off case 1: // On - Settings.flag.led_timeout = XdrvMailbox.payload; + Settings.flag4.led_timeout = XdrvMailbox.payload; break; case 2: // Toggle - Settings.flag.led_timeout ^= 1; + Settings.flag4.led_timeout ^= 1; break; } if (relay_is_on) PWMDimmerSetBrightnessLeds(0); - ResponseCmndStateText(Settings.flag.led_timeout); + ResponseCmndStateText(Settings.flag4.led_timeout); } void CmndPoweredOffLed(void) @@ -1037,14 +1037,14 @@ void CmndPoweredOffLed(void) switch (XdrvMailbox.payload) { case 0: // Off case 1: // On - Settings.flag3.powered_off_led = XdrvMailbox.payload; + Settings.flag4.powered_off_led = XdrvMailbox.payload; break; case 2: // Toggle - Settings.flag3.powered_off_led ^= 1; + Settings.flag4.powered_off_led ^= 1; break; } PWMDimmerSetPoweredOffLed(); - ResponseCmndStateText(Settings.flag3.powered_off_led); + ResponseCmndStateText(Settings.flag4.powered_off_led); } /*********************************************************************************************\ @@ -1118,7 +1118,7 @@ bool Xdrv35(uint8_t function) #ifdef USE_PWM_DIMMER_REMOTE // If remote device mode is enabled, set the device group count to the number of buttons // present. - if (Settings.flag3.remote_device_mode) { + if (Settings.flag4.remote_device_mode) { for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) { if (pin[GPIO_KEY1 + button_index] < 99) device_group_count++; } From d8fcb396f6da31187fe2dc9179e5826b3f977202 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Wed, 26 Feb 2020 21:30:30 -0600 Subject: [PATCH 499/559] Doc update --- PWM_Dimmer.md | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md index 172a7663a..cc45466a3 100644 --- a/PWM_Dimmer.md +++ b/PWM_Dimmer.md @@ -11,7 +11,7 @@ To enable PWM dimmer operation, select the PWM Dimmer module. Pressing and releasing the power button toggles the power on/off. If the toggle turns the power on, the load is returned to the last brightness it was adjusted to. If Fade is enabled, the load is faded on/off at the rate defined by the Speed setting. -When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster as higher brightnesses. The BriMin command defines the lowest value the brightness can be decreased to. +When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster at higher brightnesses. The BriMin command defines the lowest value the brightness can be decreased to. The brightness can also be changed using just the power button. When the power is on, holding the power button alternately increases or decreases the brightness. Initially, holding the power button increases the brightness. Releasing and then holding the power button again decreases the brightness. @@ -99,7 +99,7 @@ Holding any button for over 10 seconds executes the WiFiConfig 2 command. Pressing and releasing a button publishes an MQTT TOGGLE command. Holding a button publishes an MQTT HOLD command followed by an MQTT OFF command when the button is released. -When Device Groups are enabled, the PWM Dimmer minimum brightness and brightness presets are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. +When Device Groups are enabled, the PWM Dimmer minimum brightness, brightness presets, fade and speed settings are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. ### Commands @@ -125,7 +125,7 @@ When Device Groups are enabled, the PWM Dimmer minimum brightness and brightness BriPreset - ,<high> = set brightness low and high presets + <low>,<high> = set brightness low and high presets

1..255 = set brightness preset

@@ -178,6 +178,36 @@ When Device Groups are enabled, the PWM Dimmer minimum brightness and brightness - = decrease speed + + SetOption86 + + Set brightness LED timeout +

+0 = disable timeout (default) +

+1 = enable timeout + + + + SetOption87 + + Set powered-off LED (nightlight) +

+0 = disable powered-off LED (default) +

+1 = enable powered-off LED + + + + SetOption88 + + Set remote device mode +

+0 = disable remote device mode(default) +

+1 = enable remote device mode + + From 33a6f28ae3c8f63893631d809fd952186643b4c3 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Wed, 26 Feb 2020 21:46:09 -0600 Subject: [PATCH 500/559] Doc update --- PWM_Dimmer.md | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md index 172a7663a..cc45466a3 100644 --- a/PWM_Dimmer.md +++ b/PWM_Dimmer.md @@ -11,7 +11,7 @@ To enable PWM dimmer operation, select the PWM Dimmer module. Pressing and releasing the power button toggles the power on/off. If the toggle turns the power on, the load is returned to the last brightness it was adjusted to. If Fade is enabled, the load is faded on/off at the rate defined by the Speed setting. -When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster as higher brightnesses. The BriMin command defines the lowest value the brightness can be decreased to. +When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster at higher brightnesses. The BriMin command defines the lowest value the brightness can be decreased to. The brightness can also be changed using just the power button. When the power is on, holding the power button alternately increases or decreases the brightness. Initially, holding the power button increases the brightness. Releasing and then holding the power button again decreases the brightness. @@ -99,7 +99,7 @@ Holding any button for over 10 seconds executes the WiFiConfig 2 command. Pressing and releasing a button publishes an MQTT TOGGLE command. Holding a button publishes an MQTT HOLD command followed by an MQTT OFF command when the button is released. -When Device Groups are enabled, the PWM Dimmer minimum brightness and brightness presets are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. +When Device Groups are enabled, the PWM Dimmer minimum brightness, brightness presets, fade and speed settings are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. ### Commands @@ -125,7 +125,7 @@ When Device Groups are enabled, the PWM Dimmer minimum brightness and brightness BriPreset - ,<high> = set brightness low and high presets + <low>,<high> = set brightness low and high presets

1..255 = set brightness preset

@@ -178,6 +178,36 @@ When Device Groups are enabled, the PWM Dimmer minimum brightness and brightness - = decrease speed + + SetOption86 + + Set brightness LED timeout +

+0 = disable timeout (default) +

+1 = enable timeout + + + + SetOption87 + + Set powered-off LED (nightlight) +

+0 = disable powered-off LED (default) +

+1 = enable powered-off LED + + + + SetOption88 + + Set remote device mode +

+0 = disable remote device mode(default) +

+1 = enable remote device mode + + From 47925c6f6281ed1f47f85b7b82543c92d2b50228 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Wed, 26 Feb 2020 21:47:08 -0600 Subject: [PATCH 501/559] Correct remote device mode option in doc --- PWM_Dimmer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md index cc45466a3..da687bcf2 100644 --- a/PWM_Dimmer.md +++ b/PWM_Dimmer.md @@ -218,7 +218,7 @@ Remote device mode allows PWM Dimmer switches to control remote devices. With re To include remote device mode support in the build, define USE_PWM_DIMMER_REMOTE in your user_config_override. Remote device mode support requires device group support so USE_DEVICE_GROUPS is automatically defined if USE_PWM_DIMMER_REMOTE is defined. Remote device mode support adds 0.7K to the code size in addition to the code size required for device groups support. -To enable remote device mode, set Option71 to 1. Each remote device must be running firmware with device group support and have remote device support enabled. The remote devices do not need to be built with PWM dimmer support nor do they need to be switches. +To enable remote device mode, set Option88 to 1. Each remote device must be running firmware with device group support and have remote device support enabled. The remote devices do not need to be built with PWM dimmer support nor do they need to be switches. If a remote device is a PWM dimmer, the device acts like a 3-way dimmer switch would and may or may not have a load connected to it. It’s also possible to use a PWM dimmer switch without a load to act as a wall switch to control the power, brightness and color of one or more smart lights with Tasmota with device group support loaded on them. From edf223e4ac47ddc82d5e87913856ecf7b989cbb2 Mon Sep 17 00:00:00 2001 From: stefanbode Date: Thu, 27 Feb 2020 08:32:05 +0100 Subject: [PATCH 502/559] Ensure rule execution at start - fix report of TARGET in Teleperiod message - enhance Rules support to ensure rule is triggered at start ALWAYS and not crashes on complex rules - Fixes wong TARGET on shutterinvert=1 --- tasmota/xdrv_27_shutter.ino | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 1131a5f70..96d9ccf5c 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -75,6 +75,7 @@ struct SHUTTER { uint16_t max_close_pwm_frequency[MAX_SHUTTERS];// maximum of PWM frequency for closeing the shutter. depend on the motor and drivers uint8_t skip_relay_change; // avoid overrun at endstops int32_t accelerator[MAX_SHUTTERS]; // speed of ramp-up, ramp down of shutter + uint8_t start_reported = 0; } Shutter; void ShutterLogPos(uint32_t i) @@ -264,12 +265,15 @@ void ShutterReportPosition(bool always) ShutterLogPos(i); } if (i) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i], ShutterRealToPercentPosition(Shutter.target_position[i], i)); + uint32_t target = ShutterRealToPercentPosition(Shutter.target_position[i], i); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter.direction[i],(Settings.shutter_options[i] & 1) ? 100-target : target ); } ResponseJsonEnd(); if (always || (rules_flag.shutter_moving)) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); + //XdrvRulesProcess(); //removed because to many exceptions and reboots. } + //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); } @@ -294,6 +298,11 @@ void ShutterUpdatePosition(void) // Calculate position with counter. Much more accurate and no need for motordelay workaround // adding some steps to stop early Shutter.real_position[i] = ShutterCounterBasedPosition(i); + if (!Shutter.start_reported) { + ShutterReportPosition(true); + XdrvRulesProcess(); + Shutter.start_reported = 1; + } int32_t max_frequency = Shutter.direction[i] == 1 ? Shutter.max_pwm_frequency : Shutter.max_close_pwm_frequency[i]; int32_t max_freq_change_per_sec = Shutter.max_pwm_frequency*steps_per_second / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); @@ -303,11 +312,7 @@ void ShutterUpdatePosition(void) int32_t next_possible_stop = Shutter.real_position[i] + minstopway ; stop_position_delta =200 * Shutter.pwm_frequency[i]/max_frequency + Shutter.direction[i] * (next_possible_stop - Shutter.target_position[i]); - if (Shutter.time[i] == 1) { - ShutterReportPosition(true); - rules_flag.shutter_moving = 1; - XdrvRulesProcess(); - } + //Shutter.accelerator[i] = tmin(tmax(max_freq_change_per_sec*(100-(Shutter.direction[i]*(Shutter.target_position[i]-next_possible_stop) ))/2000 , max_freq_change_per_sec*9/200), max_freq_change_per_sec*11/200); //int32_t act_freq_change = max_freq_change_per_sec/20; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: time: %d, velocity %d, minstopway %d,cur_freq %d, max_frequency %d, act_freq_change %d, min_runtime_ms %d, act.pos %d, next_stop %d, target: %d"),Shutter.time[i],velocity,minstopway, @@ -415,10 +420,7 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter.pwm_frequency[i] = 0; analogWriteFreq(Shutter.pwm_frequency[i]); analogWrite(pin[GPIO_PWM1+i], 0); - // can be operated without counter, but then not that acurate. - if (pin[GPIO_CNTR1+i] < 99) { - RtcSettings.pulse_counter[i] = 0; - } + RtcSettings.pulse_counter[i] = 0; Shutter.accelerator[i] = Shutter.max_pwm_frequency / (Shutter.motordelay[i]>0 ? Shutter.motordelay[i] : 1); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Ramp up: %d"), Shutter.accelerator[i]); } @@ -429,6 +431,7 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) Shutter.direction[i] = direction; rules_flag.shutter_moving = 1; rules_flag.shutter_moved = 0; + Shutter.start_reported = 0; //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: real %d, start %d, counter %d, max_freq %d, dir %d, freq %d"),Shutter.real_position[i], Shutter.start_position[i] ,RtcSettings.pulse_counter[i],Shutter.max_pwm_frequency , Shutter.direction[i] ,Shutter.max_pwm_frequency ); } //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), i, Shutter.start_position[i], Shutter.target_position[i], Shutter.direction[i]); @@ -1155,9 +1158,11 @@ bool Xdrv27(uint8_t function) break; case FUNC_JSON_APPEND: for (uint8_t i = 0; i < shutters_present; i++) { - uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; + uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i] : Settings.shutter_position[i]; + uint8_t target = (Settings.shutter_options[i] & 1) ? 100 - ShutterRealToPercentPosition(Shutter.target_position[i], i) : ShutterRealToPercentPosition(Shutter.target_position[i], i); + ResponseAppend_P(","); - ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]); + ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i],target); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (0 == i)) { DomoticzSensor(DZ_SHUTTER, position); From b4b5eb878cf5735523084f9dd10228ee498aad03 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 27 Feb 2020 11:16:38 +0100 Subject: [PATCH 503/559] Add support for PWM dimmer Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/my_user_config.h | 8 ++++---- tasmota/tasmota_post.h | 8 ++++++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1c4197a19..40de48d5f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -107,3 +107,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) - Add Zigbee enhanced commands decoding, added ``ZbPing`` - Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) +- Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index fc1538101..17da327d6 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) - Add Zigbee enhanced commands decoding, added ``ZbPing`` - Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) +- Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) ### 8.1.0.8 20200212 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 0ae6d4663..50b988201 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -413,11 +413,11 @@ //#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+11k code) #define USE_DEEPSLEEP // Add support for deepsleep (+1k code) //#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) -// #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) +// #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug -#define USE_DEVICE_GROUPS // Add support for device groups (+3k5 code) -#define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) -#define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) +//#define USE_DEVICE_GROUPS // Add support for device groups (+5k6 code) +#define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) +// #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index d8a8ea5d1..e4834331d 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -76,9 +76,9 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #ifdef USE_PWM_DIMMER_REMOTE #ifdef USE_PWM_DIMMER #ifndef USE_DEVICE_GROUPS -#define USE_DEVICE_GROUPS +#define USE_DEVICE_GROUPS #endif // USE_DEVICE_GROUPS -#else // USE_PWM_DIMMER +#else // USE_PWM_DIMMER #undef USE_PWM_DIMMER_REMOTE #endif // USE_PWM_DIMMER #endif // USE_PWM_DIMMER_REMOTE @@ -115,6 +115,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_DEEPSLEEP // Add support for deepsleep (+1k code) #define USE_EXS_DIMMER // Add support for EX-Store WiFi Dimmer #define USE_HOTPLUG // Add support for sensor HotPlug +#define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) // -- Optional light modules ---------------------- #define USE_LIGHT // Add Dimmer/Light support @@ -299,6 +300,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #undef USE_HOTPLUG // Disable support for HotPlug #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) +#undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer #undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) @@ -377,6 +379,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #undef USE_HOTPLUG // Disable support for HotPlug #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) +#undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer // -- Optional light modules ---------------------- @@ -600,6 +603,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #undef USE_HOTPLUG // Disable support for HotPlug #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) +#undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer // -- Optional light modules ---------------------- From 5cfe247611ee4b674e2fc3292bc7cff9696c9ae3 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 27 Feb 2020 15:10:42 +0100 Subject: [PATCH 504/559] Change default my_user_config.h driver and sensor support Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers --- BUILDS.md | 34 ++++++++++++++++++---------------- RELEASENOTES.md | 3 ++- tasmota/CHANGELOG.md | 4 ++++ tasmota/my_user_config.h | 32 ++++++++++++++++---------------- tasmota/settings.h | 6 +++--- tasmota/support_features.ino | 9 ++++++--- tasmota/tasmota_post.h | 20 ++++++++++++-------- tasmota/tasmota_version.h | 2 +- tools/decode-status.py | 9 ++++++--- 9 files changed, 68 insertions(+), 51 deletions(-) diff --git a/BUILDS.md b/BUILDS.md index 88ee58cd0..d2ca20438 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -32,16 +32,18 @@ | ROTARY_V1 | - | - | - | - | - | - | - | | USE_SONOFF_RF | - | - | x | x | x | - | - | | USE_RF_FLASH | - | - | x | x | x | - | - | -| USE_SONOFF_SC | - | - | x | - | x | - | - | +| USE_SONOFF_SC | - | - | x | x | x | - | - | | USE_TUYA_MCU | - | x | x | x | x | - | x | | USE_ARMTRONIX_DIMMERS | - | - | x | x | - | - | - | | USE_PS_16_DZ | - | - | x | x | x | - | - | | USE_SONOFF_IFAN | - | - | x | x | x | - | - | | USE_BUZZER | - | - | x | x | x | - | - | | USE_ARILUX_RF | - | - | x | x | x | - | - | -| USE_SHUTTER | - | - | - | - | - | - | - | +| USE_SHUTTER | - | - | x | x | - | - | - | | USE_DEEPSLEEP | - | - | x | - | x | - | - | | USE_EXS_DIMMER | - | - | x | x | - | - | - | +| USE_DEVICE_GROUPS | - | - | x | - | - | - | - | +| USE_PWM_DIMMER | - | - | x | x | - | - | - | | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_LIGHT | - | x | x | x | x | x | x | @@ -73,28 +75,28 @@ | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_I2C | - | - | x | x | x | - | x | -| USE_SHT | - | - | x | x | x | - | x | -| USE_HTU | - | - | x | x | x | - | x | -| USE_BMP | - | - | x | x | x | - | x | +| USE_SHT | - | - | - | - | x | - | - | +| USE_HTU | - | - | - | - | x | - | - | +| USE_BMP | - | - | - | - | x | - | - | | USE_BME680 | - | - | - | - | x | - | - | -| USE_BH1750 | - | - | x | x | x | - | x | +| USE_BH1750 | - | - | - | - | x | - | - | | USE_VEML6070 | - | - | - | - | x | - | - | | USE_ADS1115 | - | - | - | - | x | - | - | | USE_ADS1115_I2CDEV | - | - | - | - | - | - | - | | USE_INA219 | - | - | - | - | x | - | - | | USE_INA226 | - | - | - | - | - | - | - | -| USE_SHT3X | - | - | x | x | x | - | x | +| USE_SHT3X | - | - | - | - | x | - | - | | USE_TSL2561 | - | - | - | - | x | - | - | | USE_TSL2591 | - | - | - | - | - | - | - | | USE_MGS | - | - | - | - | x | - | - | -| USE_SGP30 | - | - | x | x | x | - | x | +| USE_SGP30 | - | - | - | - | x | - | - | | USE_SI1145 | - | - | - | - | - | - | - | -| USE_LM75AD | - | - | x | x | x | - | x | +| USE_LM75AD | - | - | - | - | x | - | - | | USE_APDS9960 | - | - | - | - | - | - | - | | USE_MCP230xx | - | - | - | - | - | - | - | | USE_PCA9685 | - | - | - | - | - | - | - | | USE_MPR121 | - | - | - | - | - | - | - | -| USE_CCS811 | - | - | - | - | - | - | - | +| USE_CCS811 | - | - | - | - | x | - | - | | USE_MPU6050 | - | - | - | - | - | - | - | | USE_DS3231 | - | - | - | - | - | - | - | | USE_MGC3130 | - | - | - | - | - | - | - | @@ -115,10 +117,10 @@ | | | | | | | | | | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | USE_SPI | - | - | - | - | - | - | x | -| USE_MHZ19 | - | - | x | x | x | - | x | -| USE_SENSEAIR | - | - | x | x | x | - | x | -| USE_PMS5003 | - | - | x | x | x | - | x | -| USE_NOVA_SDS | - | - | x | x | x | - | x | +| USE_MHZ19 | - | - | - | - | x | - | - | +| USE_SENSEAIR | - | - | - | - | x | - | - | +| USE_PMS5003 | - | - | - | - | x | - | - | +| USE_NOVA_SDS | - | - | - | - | x | - | - | | USE_HPMA | - | - | - | - | x | - | - | | USE_SERIAL_BRIDGE | - | - | x | x | x | - | x | | USE_MP3_PLAYER | - | - | - | - | x | - | - | @@ -137,9 +139,9 @@ | USE_IR_RECEIVE | - | - | x | x | x | x | x | | USE_IR_REMOTE_FULL | - | - | - | - | - | x | - | Enable ALL protocols | | | | | | | | | -| USE_SR04 | - | - | x | x | x | - | x | +| USE_SR04 | - | - | - | - | x | - | - | | USE_TM1638 | - | - | - | - | x | - | - | -| USE_HX711 | - | - | x | x | x | - | x | +| USE_HX711 | - | - | - | - | x | - | - | | USE_TX20_WIND_SENSOR | - | - | - | - | x | - | - | | USE_RC_SWITCH | - | - | - | - | x | - | - | | USE_RF_SENSOR | - | - | - | - | x | - | - | AlectoV2 only diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 40de48d5f..c06ce9fd9 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -52,8 +52,9 @@ The following binary downloads have been compiled with ESP8266/Arduino library c ## Changelog -### Version 8.1.0.9 +### Version 8.1.0.10 +- Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers - Change Lights: simplified gamma correction and 10 bits internal computation - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items - Change IRremoteESP8266 library updated to v2.7.3 diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 17da327d6..da6df2e37 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 8.1.0.10 20200227 + +- Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers + ### 8.1.0.9 20200220 - Revert most wifi connectivity changes introduced in 8.1.0.5 (#7746, #7602, #7621) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 50b988201..2bd4c6d7c 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -410,14 +410,14 @@ #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) #define USE_BUZZER // Add support for a buzzer (+0k6 code) #define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) -//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+11k code) +#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+11k code) #define USE_DEEPSLEEP // Add support for deepsleep (+1k code) -//#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) +#define USE_EXS_DIMMER // Add support for ES-Store WiFi Dimmer (+1k5 code) // #define EXS_MCU_CMNDS // Add command to send MCU commands (+0k8 code) //#define USE_HOTPLUG // Add support for sensor HotPlug -//#define USE_DEVICE_GROUPS // Add support for device groups (+5k6 code) +#define USE_DEVICE_GROUPS // Add support for device groups (+5k6 code) #define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) -// #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) + #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // @@ -443,25 +443,25 @@ #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #ifdef USE_I2C - #define USE_SHT // [I2cDriver8] Enable SHT1X sensor (+1k4 code) - #define USE_HTU // [I2cDriver9] Enable HTU21/SI7013/SI7020/SI7021 sensor (I2C address 0x40) (+1k5 code) - #define USE_BMP // [I2cDriver10] Enable BMP085/BMP180/BMP280/BME280 sensors (I2C addresses 0x76 and 0x77) (+4k4 code) +// #define USE_SHT // [I2cDriver8] Enable SHT1X sensor (+1k4 code) +// #define USE_HTU // [I2cDriver9] Enable HTU21/SI7013/SI7020/SI7021 sensor (I2C address 0x40) (+1k5 code) +// #define USE_BMP // [I2cDriver10] Enable BMP085/BMP180/BMP280/BME280 sensors (I2C addresses 0x76 and 0x77) (+4k4 code) // #define USE_BME680 // Enable support for BME680 sensor using Bosch BME680 library (+4k code) - #define USE_BH1750 // [I2cDriver11] Enable BH1750 sensor (I2C address 0x23 or 0x5C) (+0k5 code) +// #define USE_BH1750 // [I2cDriver11] Enable BH1750 sensor (I2C address 0x23 or 0x5C) (+0k5 code) // #define USE_VEML6070 // [I2cDriver12] Enable VEML6070 sensor (I2C addresses 0x38 and 0x39) (+1k5 code) #define USE_VEML6070_RSET 270000 // VEML6070, Rset in Ohm used on PCB board, default 270K = 270000ohm, range for this sensor: 220K ... 1Meg #define USE_VEML6070_SHOW_RAW // VEML6070, shows the raw value of UV-A // #define USE_ADS1115 // [I2cDriver13] Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) based on Adafruit ADS1x15 library (no library needed) (+0k7 code) // #define USE_INA219 // [I2cDriver14] Enable INA219 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+1k code) // #define USE_INA226 // [I2cDriver35] Enable INA226 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+2k3 code) - #define USE_SHT3X // [I2cDriver15] Enable SHT3x (I2C address 0x44 or 0x45) or SHTC3 (I2C address 0x70) sensor (+0k7 code) +// #define USE_SHT3X // [I2cDriver15] Enable SHT3x (I2C address 0x44 or 0x45) or SHTC3 (I2C address 0x70) sensor (+0k7 code) // #define USE_TSL2561 // [I2cDriver16] Enable TSL2561 sensor (I2C address 0x29, 0x39 or 0x49) using library Joba_Tsl2561 (+2k3 code) // #define USE_TSL2591 // [I2cDriver40] Enable TSL2591 sensor (I2C address 0x29) using library Adafruit_TSL2591 (+1k6 code) // #define USE_MGS // [I2cDriver17] Enable Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code) #define MGS_SENSOR_ADDR 0x04 // Default Mutichannel Gas sensor i2c address // #define USE_SGP30 // [I2cDriver18] Enable SGP30 sensor (I2C address 0x58) (+1k1 code) // #define USE_SI1145 // [I2cDriver19] Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code) - #define USE_LM75AD // [I2cDriver20] Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code) +// #define USE_LM75AD // [I2cDriver20] Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code) // #define USE_APDS9960 // [I2cDriver21] Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code) // #define USE_MCP230xx // [I2cDriver22] Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x26 - set according to your wired setup) @@ -530,13 +530,13 @@ #endif // USE_SPI // -- Serial sensors ------------------------------ -#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) -#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) +//#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) +//#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) #define CO2_LOW 800 // Below this CO2 value show green light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) #define CO2_HIGH 1200 // Above this CO2 value show red light (needs PWM or WS2812 RG(B) led and enable with SetOption18 1) -#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) +//#define USE_PMS5003 // Add support for PMS5003 and PMS7003 particle concentration sensor (+1k3 code) //#define PMS_MODEL_PMS3003 // Enable support of PMS3003 instead of PMS5003/PMS7003 (needs the USE_PMS5003 above) -#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+1k5 code) +//#define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+1k5 code) #define STARTING_OFFSET 30 // Turn on NovaSDS XX-seconds before tele_period is reached //#define USE_HPMA // Add support for Honeywell HPMA115S0 particle concentration sensor (+1k4) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) @@ -618,10 +618,10 @@ // -- Other sensors/drivers ----------------------- -#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) +//#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) //#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) -#define USE_HX711 // Add support for HX711 load cell (+1k5 code) +//#define USE_HX711 // Add support for HX711 load cell (+1k5 code) // #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) // Select none or only one of the below defines diff --git a/tasmota/settings.h b/tasmota/settings.h index da8da2f29..0a200ead5 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -105,9 +105,9 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t zigbee_use_names : 1; // bit 1 (v8.1.0.4) - SetOption83 - Use FriendlyNames instead of ShortAddresses when possible uint32_t awsiot_shadow : 1; // bit 2 (v8.1.0.5) - SetOption84 - (AWS IoT) publish MQTT state to a device shadow uint32_t device_groups_enabled : 1; // bit 3 (v8.1.0.9) - SetOption85 - Enable Device Groups - uint32_t led_timeout : 1; // bit 4 (v8.1.0.9) - SetOption86 - Turn brightness LED's off 5 seconds after last change - uint32_t powered_off_led : 1; // bit 5 (v8.1.0.9) - SetOption87 - Turn red LED on when powered off - uint32_t remote_device_mode : 1; // bit 6 (v8.1.0.9) - SetOption88 - Buttons control remote devices + uint32_t led_timeout : 1; // bit 4 (v8.1.0.9) - SetOption86 - PWM Dimmer Turn brightness LED's off 5 seconds after last change + uint32_t powered_off_led : 1; // bit 5 (v8.1.0.9) - SetOption87 - PWM Dimmer Turn red LED on when powered off + uint32_t remote_device_mode : 1; // bit 6 (v8.1.0.9) - SetOption88 - PWM Dimmer Buttons control remote devices uint32_t spare07 : 1; uint32_t spare08 : 1; uint32_t spare09 : 1; diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index b6101b1cf..6cb81522a 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -519,9 +519,12 @@ void GetFeatures(void) #ifdef USE_WEMOS_MOTOR_V1 feature5 |= 0x20000000; // xdrv_34_wemos_motor_v1.ino #endif - -// feature5 |= 0x40000000; -// feature5 |= 0x80000000; +#ifdef USE_DEVICE_GROUPS + feature5 |= 0x40000000; // support_device_groups.ino +#endif +#ifdef USE_PWM_DIMMER + feature5 |= 0x80000000; // xdrv_35_pwm_dimmer +#endif /*********************************************************************************************/ diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index e4834331d..8a7c45bbe 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -106,16 +106,17 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #ifndef TUYA_DIMMER_ID #define TUYA_DIMMER_ID 0 // Default dimmer Id #endif -//#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) +#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer (+2k code) #define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code) #define USE_BUZZER // Add support for a buzzer (+0k6 code) #define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0)) -//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code) +#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code) #define USE_DEEPSLEEP // Add support for deepsleep (+1k code) -#define USE_EXS_DIMMER // Add support for EX-Store WiFi Dimmer +#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #define USE_HOTPLUG // Add support for sensor HotPlug -#define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) +#undef USE_DEVICE_GROUPS // Disable support for device groups (+5k6 code) +#undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) // -- Optional light modules ---------------------- #define USE_LIGHT // Add Dimmer/Light support @@ -153,8 +154,6 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code) //#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code) #define USE_LM75AD // Add I2C code for LM75AD sensor (+0k5 code) -#define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0k7 code) -#define USE_DS1624 // Add I2C code for DS1624, DS1621 sensor //#define USE_APDS9960 // Add I2C code for APDS9960 Proximity Sensor. Disables SHT and VEML6070 (+4k7 code) //#define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code) // #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup) @@ -164,7 +163,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack // #define USE_PCA9685_ADDR 0x40 // Enable PCA9685 I2C Address to use (Must be within range 0x40 through 0x47 - set according to your wired setup) // #define USE_PCA9685_FREQ 50 // Define default PWM frequency in Hz to be used (must be within 24 to 1526) - If other value is used, it will rever to 50Hz //#define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code) -//#define USE_CCS811 // Add I2C code for CCS811 sensor (+2k2 code) +#define USE_CCS811 // Add I2C code for CCS811 sensor (+2k2 code) //#define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) //#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code) //#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem) @@ -178,6 +177,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack //#define USE_PAJ7620 // Enable PAJ7620 gesture sensor (I2C address 0x73) (+2.5k code) //#define USE_PCF8574 // Enable PCF8574 I/O Expander (I2C addresses 0x20 - 0x26 and 0x39 - 0x3F) (+1k9 code) #define USE_HIH6 // Enable Honywell HIH Humidity and Temperature sensor (I2C address 0x27) (+0k6) +#define USE_DHT12 // Add I2C code for DHT12 temperature and humidity sensor (+0k7 code) +#define USE_DS1624 // Add I2C code for DS1624, DS1621 sensor //#define USE_AHT1x // Enable AHT10/15 humidity and temperature sensor (I2C address 0x38) (+0k8 code) #define USE_WEMOS_MOTOR_V1 // Enable Wemos motor driver V1 (I2C addresses 0x2D - 0x30) (+0k7 code) #define WEMOS_MOTOR_V1_ADDR 0x30 // Default I2C address 0x30 @@ -260,8 +261,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) #undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common) #undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) +#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) -#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_KNX_NO_EMULATION @@ -488,6 +489,9 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer #undef USE_HOTPLUG // Disable support for HotPlug +#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) +#undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) +#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer // -- Optional light modules ---------------------- //#undef USE_LIGHT // Also disable all Dimmer/Light support diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index b1e4eba9f..b9b08b46e 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,7 +20,7 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x08010009; +const uint32_t VERSION = 0x0801000A; // Lowest compatible version const uint32_t VERSION_COMPATIBLE = 0x07010006; diff --git a/tools/decode-status.py b/tools/decode-status.py index 3838d8faf..192696ad8 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -139,13 +139,16 @@ a_setoption = [[ "Reduced CT range for Alexa", "Use FriendlyNames instead of ShortAddresses when possible", "(AWS IoT) publish MQTT state to a device shadow", + "Enable Device Groups", + "PWM Dimmer Turn brightness LED's off 5 seconds after last change", + "PWM Dimmer Turn red LED on when powered off", + "PWM Dimmer Buttons control remote devices", "", "","","","", "","","","", "","","","", "","","","", "","","","", - "","","","", "","","","" ]] @@ -193,7 +196,7 @@ a_features = [[ "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", "USE_DHT12","USE_DS1624","USE_GPS","USE_HOTPLUG", "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", - "USE_AHT1x","USE_WEMOS_MOTOR_V1","","" + "USE_AHT1x","USE_WEMOS_MOTOR_V1","USE_DEVICE_GROUPS","USE_PWM_DIMMER" ],[ "","","","", "","","","", @@ -236,7 +239,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200222 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200227 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From 714ee878a7d5c2bc98ce2ab8a364d34d211d11c0 Mon Sep 17 00:00:00 2001 From: "he.so" Date: Thu, 27 Feb 2020 17:28:29 +0100 Subject: [PATCH 505/559] advanced keeloq driver number to 36 --- tasmota/{xdrv_35_keeloq.ino => xdrv_36_keeloq.ino} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename tasmota/{xdrv_35_keeloq.ino => xdrv_36_keeloq.ino} (99%) diff --git a/tasmota/xdrv_35_keeloq.ino b/tasmota/xdrv_36_keeloq.ino similarity index 99% rename from tasmota/xdrv_35_keeloq.ino rename to tasmota/xdrv_36_keeloq.ino index ce6185923..f961a2454 100644 --- a/tasmota/xdrv_35_keeloq.ino +++ b/tasmota/xdrv_36_keeloq.ino @@ -1,5 +1,5 @@ /* - xdrv_35 + xdrv_36 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ #ifdef USE_KEELOQ -#define XDRV_35 35 +#define XDRV_36 36 #include "cc1101.h" #include @@ -252,7 +252,7 @@ void InitKeeloq() /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool Xdrv35(uint8_t function) +bool Xdrv36(uint8_t function) { bool result = false; From 92442a7a8f2e46dfc9594d6ad0d1c7e2cfec3671 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 27 Feb 2020 17:35:42 +0100 Subject: [PATCH 506/559] Fix KNX compilation --- tasmota/tasmota_post.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 8a7c45bbe..8f5038387 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -263,6 +263,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common) #undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code) #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) +#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_KNX_NO_EMULATION From 1973bb2474fb4f04d0a4cf68eed5c9a0acbeb646 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 27 Feb 2020 17:48:27 +0100 Subject: [PATCH 507/559] Add support for Jarolift rollers by Keeloq algorithm Add support for Jarolift rollers by Keeloq algorithm --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/my_user_config.h | 2 +- tasmota/settings.h | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index c06ce9fd9..d07bb254a 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -109,3 +109,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add Zigbee enhanced commands decoding, added ``ZbPing`` - Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) - Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) +- Add support for Jarolift rollers by Keeloq algorithm diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index da6df2e37..b304bf95b 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,6 +3,7 @@ ### 8.1.0.10 20200227 - Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers +- Add support for Jarolift rollers by Keeloq algorithm ### 8.1.0.9 20200220 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index b752bbfde..5b0282481 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -418,7 +418,7 @@ #define USE_DEVICE_GROUPS // Add support for device groups (+5k6 code) #define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) -//#define USE_KEELOQ // Add support for controling Jarolift rollers by Keeloq algorithm +//#define USE_KEELOQ // Add support for Jarolift rollers by Keeloq algorithm (+4k5 code) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/settings.h b/tasmota/settings.h index 3dff66f8d..be108ac33 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -469,6 +469,7 @@ struct SYSCFG { uint8_t bri_min; // F05 uint8_t bri_preset_low; // F06 uint8_t bri_preset_high; // F07 + uint8_t free_f08[180]; // F08 uint32_t keeloq_master_msb; // FBC From fb87a03dbccbfd12f37179497311b43e1a1b2ab1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 27 Feb 2020 17:52:27 +0100 Subject: [PATCH 508/559] Prep for Sonoff D1 --- tasmota/tasmota_template.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 6f5aa0f8c..cb603d602 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -419,6 +419,7 @@ enum SupportedModules { SONOFF_IFAN03, EXS_DIMMER, PWM_DIMMER, + SONOFF_D1, MAXMODULE}; #define USER_MODULE 255 @@ -808,6 +809,9 @@ const uint8_t kModuleNiceList[] PROGMEM = { SONOFF_T11, SONOFF_T12, SONOFF_T13, +#ifdef USE_SONOFF_D1 + SONOFF_D1, // Sonoff D1 +#endif SONOFF_LED, // Sonoff Light Devices SONOFF_BN, #ifdef USE_SONOFF_L1 @@ -2235,6 +2239,21 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_KEY1_INV, // GPIO15 Power button GPIO_REL1_INV, // GPIO16 Power relay/Level 1 LED 0 + }, + { "Sonoff D1", // SONOFF_D1 - Sonoff D1 RF Dimmer 433 (ESP8285) + GPIO_USER, // GPIO00 Pad + GPIO_TXD, // GPIO01 D1 control + 0, // GPIO02 + GPIO_RXD, // GPIO03 D1 control + 0, // GPIO04 DEBUG_RX + 0, // GPIO05 DEBUG_TX + // GPIO06 (SD_CLK Flash) + // GPIO07 (SD_DATA0 Flash QIO/DIO/DOUT) + // GPIO08 (SD_DATA1 Flash QIO/DIO/DOUT) + 0, // GPIO09 + 0, // GPIO10 + // GPIO11 (SD_CMD Flash) + 0, 0, 0, 0, 0, 0 } }; From a9626627437420be9190071381b588425f65c200 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Thu, 27 Feb 2020 13:38:33 -0600 Subject: [PATCH 509/559] Rescale Bri to DimmerRange, Remove BriMin, LedTimeout and PoweredOffLed commands --- PWM_Dimmer.md | 84 +++---------- tasmota/i18n.h | 2 - tasmota/support_device_groups.ino | 4 +- tasmota/tasmota.h | 6 +- tasmota/xdrv_04_light.ino | 9 +- tasmota/xdrv_35_pwm_dimmer.ino | 199 +++++++----------------------- 6 files changed, 75 insertions(+), 229 deletions(-) diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md index da687bcf2..a89b0e752 100644 --- a/PWM_Dimmer.md +++ b/PWM_Dimmer.md @@ -11,7 +11,7 @@ To enable PWM dimmer operation, select the PWM Dimmer module. Pressing and releasing the power button toggles the power on/off. If the toggle turns the power on, the load is returned to the last brightness it was adjusted to. If Fade is enabled, the load is faded on/off at the rate defined by the Speed setting. -When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster at higher brightnesses. The BriMin command defines the lowest value the brightness can be decreased to. +When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster at higher brightnesses. The DimmerRange command set the minimum and maximum PWM values. Brightness values (0 - 255) are scaled to dimmerMin to dimmerMax. Typically, dimmerMin would be set to the lowest value at which the lights show visible light and dimmerMax would be set 1023. If you want to increase the lowest brightness level and/or decrease the highest brightness level, set higher dimmerMin and/or lower dimmerMax values. The brightness can also be changed using just the power button. When the power is on, holding the power button alternately increases or decreases the brightness. Initially, holding the power button increases the brightness. Releasing and then holding the power button again decreases the brightness. @@ -99,7 +99,7 @@ Holding any button for over 10 seconds executes the WiFiConfig 2 command. Pressing and releasing a button publishes an MQTT TOGGLE command. Holding a button publishes an MQTT HOLD command followed by an MQTT OFF command when the button is released. -When Device Groups are enabled, the PWM Dimmer minimum brightness, brightness presets, fade and speed settings are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. +When Device Groups are enabled, the PWM Dimmer brightness presets, dimmer minimum and maximum values, fade and speed settings are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group. ### Commands @@ -112,99 +112,43 @@ When Device Groups are enabled, the PWM Dimmer minimum brightness, brightness pr Parameters - - BriMin - - 1..255 = set minimum brightness -

-+ = increase minimum brightness -

-- = decrease minimum brightness - - BriPreset - <low>,<high> = set brightness low and high presets -

-1..255 = set brightness preset -

-+ = increase brightness preset -

+ <low>,<high> = set brightness low and high presets
+1..255 = set brightness preset
++ = increase brightness preset
- = decrease brightness preset - Dimmer + DimmerRange - 0..100 = set dimmer value from 0 to 100% -

-+ = increase by 10 -

-- = decrease by 10 - - - - Fade - - 0 = do not use fade (default) -

-1 = use fade - - - - LedTimeout - - 0 = disable LED timeout -

-1 = enable LED timeout - - - - PoweredOffLed - - 0 = disable powered-off LED -

-1 = disable powered-off LED - - - - Speed - - 1..20 = set fade speed from fast 1 to very slow 20 -

-+ = increase speed -

-- = decrease speed + Change dimming range
+, = set minimum and maximum PWM values. Dimmer/brightness is scaled to this range.
SetOption86 - Set brightness LED timeout -

-0 = disable timeout (default) -

+ Set brightness LED timeout
+0 = disable timeout (default)
1 = enable timeout SetOption87 - Set powered-off LED (nightlight) -

-0 = disable powered-off LED (default) -

+ Set powered-off LED (nightlight)
+0 = disable powered-off LED (default)
1 = enable powered-off LED SetOption88 - Set remote device mode -

-0 = disable remote device mode(default) -

+ Set remote device mode
+0 = disable remote device mode(default)
1 = enable remote device mode diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 1e1e6b909..903224c99 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -539,8 +539,6 @@ #ifdef USE_PWM_DIMMER #define D_CMND_BRI_MIN "BriMin" #define D_CMND_BRI_PRESET "BriPreset" -#define D_CMND_LED_TIMEOUT "LedTimeout" -#define D_CMND_POWERED_OFF_LED "PoweredOffLed" #endif // Commands xsns_02_analog.ino diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index c94ea2f57..faf3e0b6d 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -112,8 +112,8 @@ bool DeviceGroupItemShared(bool incoming, uint8_t item) case DGR_ITEM_LIGHT_SPEED: mask = DGR_SHARE_LIGHT_FADE; break; - case DGR_ITEM_BRI_MIN: - mask = DGR_SHARE_BRI_MIN; + case DGR_ITEM_DIMMER_RANGE: + mask = DGR_SHARE_DIMMER_RANGE; break; } return (!mask || ((incoming ? Settings.device_group_share_in : Settings.device_group_share_out) & mask)); diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 5745ff9c6..a9ff6f57f 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -309,14 +309,14 @@ enum DeviceGroupMessageFlag { DGR_FLAG_RESET = 1, DGR_FLAG_STATUS_REQUEST = 2, D enum DeviceGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS, DGR_ITEM_LIGHT_FADE, DGR_ITEM_LIGHT_SPEED, DGR_ITEM_LIGHT_BRI, DGR_ITEM_LIGHT_SCHEME, DGR_ITEM_LIGHT_FIXED_COLOR, - DGR_ITEM_BRI_MIN, DGR_ITEM_BRI_PRESET_LOW, DGR_ITEM_BRI_PRESET_HIGH, DGR_ITEM_BRI_POWER_ON, + DGR_ITEM_BRI_PRESET_LOW, DGR_ITEM_BRI_PRESET_HIGH, DGR_ITEM_BRI_POWER_ON, // Add new 8-bit items before this line DGR_ITEM_LAST_8BIT, DGR_ITEM_MAX_8BIT = 63, DGR_ITEM_ACK, DGR_ITEM_ANALOG1, DGR_ITEM_ANALOG2, DGR_ITEM_ANALOG3, DGR_ITEM_ANALOG4, DGR_ITEM_ANALOG5, // Add new 16-bit items before this line DGR_ITEM_LAST_16BIT, DGR_ITEM_MAX_16BIT = 127, - DGR_ITEM_POWER, + DGR_ITEM_POWER, DGR_ITEM_DIMMER_RANGE, // Add new 32-bit items before this line DGR_ITEM_LAST_32BIT, DGR_ITEM_MAX_32BIT = 191, // Add new string items before this line @@ -324,7 +324,7 @@ enum DeviceGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS, DGR_ITEM_LIGHT_CHANNELS }; enum DeviceGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE_LIGHT_FADE = 4, DGR_SHARE_LIGHT_SCHEME = 8, - DGR_SHARE_LIGHT_COLOR = 16, DGR_SHARE_BRI_MIN = 32 }; + DGR_SHARE_LIGHT_COLOR = 16, DGR_SHARE_DIMMER_RANGE = 32 }; enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER, SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER, diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index d54598077..d46ae7eef 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2526,6 +2526,8 @@ void CmndDimmer(void) } } +#endif // USE_LIGHT +#if defined(USE_LIGHT) || defined(USE_PWM_DIMMER) void CmndDimmerRange(void) { // DimmerRange - Show current dimmer range as used by Tuya and PS16DZ Dimmers @@ -2542,10 +2544,15 @@ void CmndDimmerRange(void) Settings.dimmer_hw_min = parm[1]; Settings.dimmer_hw_max = parm[0]; } - restart_flag = 2; +#ifdef USE_DEVICE_GROUPS + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_DIMMER_RANGE, Settings.dimmer_hw_min | Settings.dimmer_hw_max << 16); +#endif // USE_DEVICE_GROUPS + if (PWM_DIMMER != my_module_type) restart_flag = 2; } Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max); } +#endif // #if defined(USE_LIGHT) || defined(USE_PWM_DIMMER) +#ifdef USE_LIGHT void CmndLedTable(void) { diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index 94bc4ea38..c1269ccc3 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -36,20 +36,19 @@ #define MAX_FIXED_COLOR 12 #endif // MAX_FIXED_COLOR +// Note: CmndFade and CmndSpeed are in xdrv_04_light. const char kPWMDimmerCommands[] PROGMEM = "|" // No prefix - D_CMND_BRI_MIN "|" D_CMND_BRI_PRESET "|" D_CMND_DIMMER "|" D_CMND_FADE "|" D_CMND_LED_TIMEOUT "|" - D_CMND_POWERED_OFF_LED "|" D_CMND_SPEED; + D_CMND_BRI_PRESET "|" D_CMND_DIMMER "|" D_CMND_DIMMER_RANGE "|" D_CMND_FADE "|" D_CMND_SPEED; void (* const PWMDimmerCommand[])(void) PROGMEM = { - &CmndBriMin, &CmndBriPreset, &PWMDmmerCmndDimmer, &CmndFade, &CmndLedTimeout, - &CmndPoweredOffLed, &CmndSpeed }; + CmndBriPreset, &PWMDmmerCmndDimmer, &CmndDimmerRange, &CmndFade, &CmndSpeed }; #ifdef USE_PWM_DIMMER_REMOTE struct remote_pwm_dimmer { power_t power; + uint32_t dimmer_range; uint8_t light_speed; uint8_t bri_power_on; - uint8_t bri_min; uint8_t bri_preset_low; uint8_t bri_preset_high; uint8_t fixed_color_index; @@ -85,11 +84,6 @@ uint8_t buttons_pressed = 0; bool active_device_is_local; #endif // USE_PWM_DIMMER_REMOTE -void PWMDimmerCheckBri(uint8_t * value_ptr) -{ - if (*value_ptr < Settings.bri_min) *value_ptr = Settings.bri_min; -} - void PWMModuleInit() { Settings.seriallog_level = 0; @@ -98,28 +92,22 @@ void PWMModuleInit() Settings.flag.pwm_control = 0; // Use basic PWM control instead of Light if (Settings.last_module != Settings.module) { - Settings.bri_min = 25; + Settings.dimmer_hw_min = 102; + Settings.dimmer_hw_max = 1023; Settings.bri_power_on = 50; Settings.bri_preset_low = 25; Settings.bri_preset_high = 255; Settings.last_module = Settings.module; } - else { - if (Settings.bri_min < 1) Settings.bri_min = 25; - PWMDimmerCheckBri(&Settings.bri_power_on); - PWMDimmerCheckBri(&Settings.bri_preset_low); - PWMDimmerCheckBri(&Settings.bri_preset_high); - } if (Settings.light_speed < 1) Settings.light_speed = 1; target_bri = ((Settings.power & 1) ? changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255) : 0); - PWMDimmerCheckBri(&target_bri); current_bri = target_bri; if (pin[GPIO_PWM1] < 99) { - uint32_t pwm_value = changeUIntScale(current_bri, 0, 255, 0, Settings.pwm_range); - analogWrite(pin[GPIO_PWM1], bitRead(pwm_inverted, 0) ? Settings.pwm_range - pwm_value : pwm_value); + uint32_t pwm_value = (current_bri ? changeUIntScale(current_bri, 1, 255, Settings.dimmer_hw_min, Settings.dimmer_hw_max) : 0); + analogWrite(pin[GPIO_PWM1], bitRead(pwm_inverted, 0) ? Settings.dimmer_hw_max - pwm_value : pwm_value); } relay_is_on = (current_bri > 0); @@ -149,7 +137,7 @@ void PWMDimmerInit(void) void PWMDimmerSetBrightnessLeds(int32_t operation) { if (leds_present) { - uint32_t step = (!operation ? (255 - Settings.bri_min) / (leds_present + 1) : operation < 0 ? 255 : 0); + uint32_t step = (!operation ? 256 / (leds_present + 1) : operation < 0 ? 255 : 0); uint32_t level = step; SetLedPowerIdx(0, current_bri >= level); if (leds_present > 1) { @@ -188,30 +176,23 @@ void PWMDimmerAnimate(bool no_fade) // Advance the current brightness towards the target. if (!no_fade && Settings.light_fade) { - if (current_bri < Settings.bri_min) { - current_bri = Settings.bri_min; - } - else { - uint8_t offset = current_bri / Settings.light_speed / 5 + 1; - uint8_t max_offset = abs(target_bri - current_bri); - if (offset > max_offset) offset = max_offset; - if (current_bri < target_bri) - current_bri += offset; - else - current_bri -= offset; - } + uint8_t offset = current_bri / Settings.light_speed / 5 + 1; + uint8_t max_offset = abs(target_bri - current_bri); + if (offset > max_offset) offset = max_offset; + if (current_bri < target_bri) + current_bri += offset; + else + current_bri -= offset; } else { current_bri = target_bri; } - // If the current brightness is now < bri_min, set the current and target brightness to 0. - if (current_bri < Settings.bri_min) current_bri = target_bri = 0; - - // Sset the new PWM value. + // Set the new PWM value. if (pin[GPIO_PWM1] < 99) { - uint32_t pwm_value = changeUIntScale(current_bri, 0, 255, 0, Settings.pwm_range); - analogWrite(pin[GPIO_PWM1], bitRead(pwm_inverted, 0) ? Settings.pwm_range - pwm_value : pwm_value); + uint32_t pwm_value = (current_bri ? changeUIntScale(current_bri, 1, 255, Settings.dimmer_hw_min, Settings.dimmer_hw_max) : 0); +//AddLog_P2(LOG_LEVEL_INFO, PSTR("PWMDimmerAnimate: current_bri=%u, pwm_value =%u"), current_bri, pwm_value); + analogWrite(pin[GPIO_PWM1], bitRead(pwm_inverted, 0) ? Settings.dimmer_hw_max - pwm_value : pwm_value); } // Handle a power state change. @@ -236,7 +217,6 @@ void PWMDimmerSetBri(uint8_t bri) { if (bri == target_bri) return; target_bri = bri; - if (target_bri && target_bri < Settings.bri_min) target_bri = Settings.bri_min; Settings.bri_power_on = target_bri; Settings.light_dimmer = changeUIntScale(target_bri, 0, 255, 0, 100); if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT @@ -249,20 +229,7 @@ void PWMDimmerSetBri(uint8_t bri) void PWMDimmerHandleDeviceGroupRequest() { static bool send_state = false; - uint8_t value = XdrvMailbox.payload; - switch (XdrvMailbox.command_code) { - case DGR_ITEM_BRI_MIN: - Settings.bri_min = 1; - case DGR_ITEM_BRI_PRESET_LOW: - case DGR_ITEM_BRI_PRESET_HIGH: - case DGR_ITEM_BRI_POWER_ON: - PWMDimmerCheckBri(&value); - break; - case DGR_ITEM_LIGHT_BRI: - if (value) PWMDimmerCheckBri(&value); - break; - } - + uint32_t value = XdrvMailbox.payload; switch (XdrvMailbox.command_code) { case DGR_ITEM_EOL: if (send_state && !(XdrvMailbox.index & DGR_FLAG_MORE_TO_COME)) { @@ -284,11 +251,9 @@ void PWMDimmerHandleDeviceGroupRequest() send_state = true; } break; - case DGR_ITEM_BRI_MIN: - if (Settings.bri_min != value) { - Settings.bri_min = value; - send_state = true; - } + case DGR_ITEM_DIMMER_RANGE: + Settings.dimmer_hw_min = value & 0xffff; + Settings.dimmer_hw_max = value >> 16; break; case DGR_ITEM_BRI_PRESET_LOW: if (Settings.bri_preset_low != value) { @@ -311,8 +276,9 @@ void PWMDimmerHandleDeviceGroupRequest() case DGR_ITEM_STATUS: SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_BRI, target_bri, - DGR_ITEM_BRI_MIN, Settings.bri_min, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, - DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); + DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high, + DGR_ITEM_DIMMER_RANGE, Settings.dimmer_hw_min | Settings.dimmer_hw_max << 16, + DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); break; } } @@ -473,12 +439,12 @@ void PWMDimmerHandleButton() if (active_device_is_local == !button_pressed[power_button_index]) { #endif // USE_PWM_DIMMER_REMOTE if (button_hold_time[button_index] < now) { - uint8_t uint8_value; - uint8_t min_uint8_value; bool down_button_is_held = (button_index == down_button_index); bool down_button_was_tapped = (button_press_count[down_button_index] > 0); uint8_t tap_count = (down_button_was_tapped ? button_press_count[down_button_index] : button_press_count[up_button_index]); + uint16_t uint16_value; + switch (tap_count) { case 0: // If the power is on, adjust the brightness. Set the direction based on which button is @@ -563,30 +529,29 @@ void PWMDimmerHandleButton() // Decrease/increase the minimum brightness. #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) - uint8_value = active_remote_pwm_dimmer->bri_min; + uint16_value = active_remote_pwm_dimmer->dimmer_range & 0xffff; else #endif // USE_PWM_DIMMER_REMOTE - uint8_value = Settings.bri_min; + uint16_value = Settings.dimmer_hw_min; if (down_button_is_held) { - if (uint8_value > 4) uint8_value--; + if (uint16_value > 0) uint16_value--; } - else if (uint8_value < 255) { - uint8_value++; + else if (uint16_value < 65535) { + uint16_value++; } #ifdef USE_PWM_DIMMER_REMOTE + dgr_item = DGR_ITEM_DIMMER_RANGE; if (!active_device_is_local) { - active_remote_pwm_dimmer->bri_min = uint8_value; - if (active_remote_pwm_dimmer->bri_power_on < uint8_value) active_remote_pwm_dimmer->bri_power_on = uint8_value; + active_remote_pwm_dimmer->dimmer_range &= 0xffff0000 | uint16_value; + dgr_value = active_remote_pwm_dimmer->dimmer_range; } else { #endif // USE_PWM_DIMMER_REMOTE - Settings.bri_min = uint8_value; - if (Settings.bri_power_on < uint8_value) Settings.bri_power_on = uint8_value; + Settings.dimmer_hw_min = uint16_value; + dgr_value = Settings.dimmer_hw_min | Settings.dimmer_hw_max << 16; #ifdef USE_PWM_DIMMER_REMOTE } #endif // USE_PWM_DIMMER_REMOTE - dgr_item = DGR_ITEM_BRI_MIN; - dgr_value = uint8_value; } else { // Decrease/increase the fade speed. @@ -617,19 +582,13 @@ void PWMDimmerHandleButton() if (down_button_was_tapped) { // Decrease/increase the low brightness preset. #ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) { + if (!active_device_is_local) uint8_value = active_remote_pwm_dimmer->bri_preset_low; - min_uint8_value =active_remote_pwm_dimmer->bri_min; - } - else { + else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.bri_preset_low; - min_uint8_value = Settings.bri_min; -#ifdef USE_PWM_DIMMER_REMOTE - } -#endif // USE_PWM_DIMMER_REMOTE if (down_button_is_held) { - if (uint8_value > min_uint8_value) uint8_value--; + if (uint8_value > 3) uint8_value--; } else if (uint8_value < 255) { uint8_value++; @@ -652,7 +611,7 @@ void PWMDimmerHandleButton() #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.bri_preset_high; if (down_button_is_held) { - if (uint8_value > 4) uint8_value--; + if (uint8_value > 3) uint8_value--; } else if (uint8_value < 255) { uint8_value++; @@ -706,7 +665,7 @@ void PWMDimmerHandleButton() } else { new_bri = bri - offset; - if (new_bri < Settings.bri_min) new_bri = Settings.bri_min; + if (new_bri < 3) new_bri = 3; } if (new_bri != bri) { #ifdef USE_DEVICE_GROUPS @@ -917,36 +876,6 @@ void PWMDimmerHandleButton() * Commands \*********************************************************************************************/ -void CmndBriMin(void) -{ - uint8_t new_bri_min = Settings.bri_min; - if (XdrvMailbox.payload > 0 && XdrvMailbox.payload <= 255) { - new_bri_min = (XdrvMailbox.payload < 4 ? 4 : XdrvMailbox.payload); - } - else if (1 == XdrvMailbox.data_len) { - if ('-' == XdrvMailbox.data[0]) { - if (new_bri_min > 4) new_bri_min--; - } - else if ('+' == XdrvMailbox.data[0] && new_bri_min < 255) - new_bri_min++; - } - - if (new_bri_min != Settings.bri_min) { - Settings.bri_min = new_bri_min; - PWMDimmerCheckBri(&Settings.bri_power_on); - PWMDimmerCheckBri(&Settings.bri_preset_low); - PWMDimmerCheckBri(&Settings.bri_preset_high); - -#ifdef DEVICE_GROUPS - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_MIN, Settings.bri_min, - DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, - DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); -#endif // DEVICE_GROUPS - } - - ResponseCmndNumber(Settings.bri_min); -} - void CmndBriPreset(void) { if (XdrvMailbox.data_len > 0) { @@ -962,7 +891,7 @@ void CmndBriPreset(void) if (parm[i] < 255) parm[i]++; } else if (*ptr == '-') { - if (parm[i] > Settings.bri_min) parm[i]--; + if (parm[i] > 0) parm[i]--; } else { value = strtoul(ptr, &ptr, 0); @@ -971,7 +900,7 @@ void CmndBriPreset(void) break; } parm[i] = value; - PWMDimmerCheckBri(&parm[i]); + if (*ptr != ',') break; } ptr++; @@ -985,9 +914,9 @@ void CmndBriPreset(void) Settings.bri_preset_low = parm[1]; Settings.bri_preset_high = parm[0]; } -#ifdef DEVICE_GROUPS +#ifdef USE_DEVICE_GROUPS SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high); -#endif // DEVICE_GROUPS +#endif // USE_DEVICE_GROUPS } } Response_P(PSTR("{\"" D_CMND_BRI_PRESET "\":{\"Low\":%d,\"High\":%d}}"), Settings.bri_preset_low, Settings.bri_preset_high); @@ -1015,38 +944,6 @@ void PWMDmmerCmndDimmer(void) ResponseCmndNumber(Settings.light_dimmer); } -void CmndLedTimeout(void) -{ - // Set the brightness LED timeout state. - switch (XdrvMailbox.payload) { - case 0: // Off - case 1: // On - Settings.flag4.led_timeout = XdrvMailbox.payload; - break; - case 2: // Toggle - Settings.flag4.led_timeout ^= 1; - break; - } - if (relay_is_on) PWMDimmerSetBrightnessLeds(0); - ResponseCmndStateText(Settings.flag4.led_timeout); -} - -void CmndPoweredOffLed(void) -{ - // Set the powered-off LED state. - switch (XdrvMailbox.payload) { - case 0: // Off - case 1: // On - Settings.flag4.powered_off_led = XdrvMailbox.payload; - break; - case 2: // Toggle - Settings.flag4.powered_off_led ^= 1; - break; - } - PWMDimmerSetPoweredOffLed(); - ResponseCmndStateText(Settings.flag4.powered_off_led); -} - /*********************************************************************************************\ * Interface \*********************************************************************************************/ From 23ca2ff36d238ad368169f6c1c856e49f9884bd0 Mon Sep 17 00:00:00 2001 From: "he.so" Date: Thu, 27 Feb 2020 21:03:05 +0100 Subject: [PATCH 510/559] user pin selection for CC1101 gpios --- tasmota/tasmota_template.h | 7 ++++++- tasmota/xdrv_36_keeloq.ino | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index cb603d602..3c85707df 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -222,6 +222,8 @@ enum UserSelectablePins { GPIO_HM10_TX, // HM10-BLE-Mijia-bridge serial interface GPIO_LE01MR_RX, // F&F LE-01MR energy meter GPIO_LE01MR_TX, // F&F LE-01MR energy meter + GPIO_CC1101_GDO0, // CC1101 pin for RX + GPIO_CC1101_GDO2, // CC1101 pin for RX GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -790,7 +792,10 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_DEEPSLEEP GPIO_DEEPSLEEP, #endif - +#ifdef USE_KEELOQ + GPIO_CC1101_GDO0, // CC1101 pin for RX + GPIO_CC1101_GDO2, // CC1101 pin for RX +#endif }; const uint8_t kModuleNiceList[] PROGMEM = { diff --git a/tasmota/xdrv_36_keeloq.ino b/tasmota/xdrv_36_keeloq.ino index f961a2454..edac0ee23 100644 --- a/tasmota/xdrv_36_keeloq.ino +++ b/tasmota/xdrv_36_keeloq.ino @@ -27,8 +27,8 @@ #define Lowpulse 400 #define Highpulse 800 -#define TX_PORT 4 // Outputport for transmission -#define RX_PORT 5 // Inputport for reception +#define TX_PORT pin[GPIO_CC1101_GDO2] // Outputport for transmission +#define RX_PORT pin[GPIO_CC1101_GDO0] // Inputport for reception const char kJaroliftCommands[] PROGMEM = "Keeloq|" // prefix "SendRaw|SendButton|Set"; From cc8dfc22a83cb6cb22f3de51469bae32b93d8d9d Mon Sep 17 00:00:00 2001 From: "he.so" Date: Thu, 27 Feb 2020 21:31:19 +0100 Subject: [PATCH 511/559] define language keys for CC1101 pins --- tasmota/language/bg-BG.h | 2 ++ tasmota/language/cs-CZ.h | 2 ++ tasmota/language/de-DE.h | 2 ++ tasmota/language/el-GR.h | 2 ++ tasmota/language/en-GB.h | 2 ++ tasmota/language/es-ES.h | 2 ++ tasmota/language/fr-FR.h | 2 ++ tasmota/language/he-HE.h | 2 ++ tasmota/language/hu-HU.h | 2 ++ tasmota/language/it-IT.h | 2 ++ tasmota/language/ko-KO.h | 2 ++ tasmota/language/nl-NL.h | 2 ++ tasmota/language/pl-PL.h | 2 ++ tasmota/language/pt-BR.h | 2 ++ tasmota/language/pt-PT.h | 2 ++ tasmota/language/ru-RU.h | 2 ++ tasmota/language/sk-SK.h | 2 ++ tasmota/language/sv-SE.h | 2 ++ tasmota/language/tr-TR.h | 2 ++ tasmota/language/uk-UA.h | 2 ++ tasmota/language/zh-CN.h | 2 ++ tasmota/language/zh-TW.h | 2 ++ tasmota/tasmota_template.h | 3 ++- 23 files changed, 46 insertions(+), 1 deletion(-) diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 8acbff8e1..9a6ce8abc 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index 2d15ac443..d98361640 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index e87624bfa..05835a49c 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index dbeb71a68..0ddd43918 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index 792c2b597..b175cc193 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 77e7c6047..12e732bc2 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index a63955ab7..e9c31da46 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index 86af3c35a..f836a92b9 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index d9348dde1..da313caaa 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index e5ee2f1aa..efaecc1a5 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index f8cd83e99..794b97e84 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index bc9b1876e..288da67d5 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index 9cc522fa7..e15ccbbc2 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 4909fc08c..9b24d05c8 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 1e49c449c..9565fc7a5 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index a312000b7..700958875 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index f5041901a..dbee001e9 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index 7741c8937..a8e5aa6a8 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 51f0a3ddb..430289372 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index a7bcfa5da..2b4873e7a 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 53e05b1f4..5a71e95dc 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "安" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 2e9994046..9883972f1 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -641,6 +641,8 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" // Units #define D_UNIT_AMPERE "安" diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 3c85707df..5494fbcf3 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -307,7 +307,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|" D_SENSOR_DS18X20 "o|" D_SENSOR_DHT11 "o|" D_SENSOR_HM10_RX "|" D_SENSOR_HM10_TX "|" - D_SENSOR_LE01MR_RX "|" D_SENSOR_LE01MR_TX + D_SENSOR_LE01MR_RX "|" D_SENSOR_LE01MR_TX "|" + D_SENSOR_CC1101_GDO0 "|" D_SENSOR_CC1101_GDO2 ; const char kSensorNamesFixed[] PROGMEM = From 0083e1d9960c45ca6736f807993c2fe1bd793399 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Thu, 27 Feb 2020 22:08:31 +0100 Subject: [PATCH 512/559] Zigbee fix skipped attributes --- tasmota/xdrv_23_zigbee_3_devices.ino | 7 ++++++- tasmota/xdrv_23_zigbee_8_parsers.ino | 5 ++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index 71752f4e3..c7c1f2d11 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -659,7 +659,12 @@ bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const JsonObject &values) { for (auto kv : values) { String key_string = kv.key; - if (strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_LINKQUALITY))) { // exception = ignore duplicates for LinkQuality + if (0 == strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_ENDPOINT))) { + // attribute "Endpoint" + if (kv.value.as() != device.json->get(kv.key)) { + return true; + } + } else if (strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_LINKQUALITY))) { // exception = ignore duplicates for LinkQuality if (device.json->containsKey(kv.key)) { return true; // conflict! } diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index b67add374..9e336d0c1 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -504,10 +504,9 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { if (zigbee_devices.jsonIsConflict(srcaddr, json)) { // there is conflicting values, force a publish of the previous message now and don't coalesce zigbee_devices.jsonPublishFlush(srcaddr); - } else { - zigbee_devices.jsonAppend(srcaddr, json); - zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); } + zigbee_devices.jsonAppend(srcaddr, json); + zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); } else { // Publish immediately zigbee_devices.jsonPublishNow(srcaddr, json); From 25556be8d301536d6319a2cb609d5fc178afd205 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Thu, 27 Feb 2020 20:41:29 -0600 Subject: [PATCH 513/559] Handle remote switch updates, Make tap/hold functions available only when power is off --- PWM_Dimmer.md | 6 +- tasmota/support_device_groups.ino | 7 +- tasmota/xdrv_35_pwm_dimmer.ino | 164 ++++++++++++++++++++---------- 3 files changed, 116 insertions(+), 61 deletions(-) diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md index a89b0e752..5ba143fec 100644 --- a/PWM_Dimmer.md +++ b/PWM_Dimmer.md @@ -11,17 +11,17 @@ To enable PWM dimmer operation, select the PWM Dimmer module. Pressing and releasing the power button toggles the power on/off. If the toggle turns the power on, the load is returned to the last brightness it was adjusted to. If Fade is enabled, the load is faded on/off at the rate defined by the Speed setting. -When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster at higher brightnesses. The DimmerRange command set the minimum and maximum PWM values. Brightness values (0 - 255) are scaled to dimmerMin to dimmerMax. Typically, dimmerMin would be set to the lowest value at which the lights show visible light and dimmerMax would be set 1023. If you want to increase the lowest brightness level and/or decrease the highest brightness level, set higher dimmerMin and/or lower dimmerMax values. +When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster at higher brightnesses. The DimmerRange command sets the minimum and maximum PWM values. Brightness values (0 through 255) are scaled to dimmerMin through dimmerMax. Typically, dimmerMin would be set to the lowest value at which the lights show visible light and dimmerMax would be set 1023. If you want to increase the lowest brightness level and/or decrease the highest brightness level, set higher dimmerMin and/or lower dimmerMax values. The brightness can also be changed using just the power button. When the power is on, holding the power button alternately increases or decreases the brightness. Initially, holding the power button increases the brightness. Releasing and then holding the power button again decreases the brightness. -When the power is off, holding the down or up button turns the power on at a temporary brightness of the low/high levels set by the BriPreset command (default =10,255). Turning the power on at the low preset can also be accomplished by holding the power button while the power is off. The brightness presets are intended to enable quickly turning on a light to a dim or bright level without changing the normal desired brightness. Turning the power on to a preset does not change the brightness the load will be set to when the switch is turned on the next time. For example, if the light is on and you adjust the brightness to 80 and then turn the light off, when you turn it back on, the brightness will return to 80. If you turn the power off again and then press the down button, the light will be turned on with a brightness of the low preset. If you then turn the light off and on again, the brightness will return to 80. +When the power is off, pressing the down or up button turns the power on at a temporary brightness of the low/high levels set by the BriPreset command (default =10,255). Turning the power on at the low preset can also be accomplished by holding the power button while the power is off. The brightness presets are intended to enable quickly turning on a light to a dim or bright level without changing the normal desired brightness. Turning the power on to a preset does not change the brightness the load will be set to when the switch is turned on the next time. For example, if the light is on and you adjust the brightness to 80 and then turn the light off, when you turn it back on, the brightness will return to 80. If you turn the power off again and then press the down button, the light will be turned on with a brightness of the low preset. If you then turn the light off and on again, the brightness will return to 80. If there are LED’s defined in the template, they are turned on to indicate the current brightness. More LEDs are turned on at higher brightnesses. The LedTimeout command enables/disables an LED timeout. If LED timeout is enabled, the LED’s turn off five seconds after the last change in brightness. Note that the lowest LED and the blue power LED are always on when the power is on. The LEDLink LED can be used as a nightlight/powered-off indicator. The PoweredOffLed command enables/disables turning the LEDLink LED on when the power is off. -Tapping (pressing and releasing quickly) the down or up buttons a given number of times and then holding the down or up button decreases or increases settings according to the table below. For example, tapping the down button once and then holding the up button sets all RGB lights in the device group to the next fixed color. Tapping the up button three times and then holding the down button decreases the high brightness preset. +When the power is on, tapping (pressing and releasing quickly) the down or up buttons a given number of times and then holding the down or up button decreases or increases settings according to the table below. For example, tapping the down button once and then holding the up button sets all RGB lights in the device group to the next fixed color. Tapping the up button three times and then holding the down button decreases the high brightness preset. diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index faf3e0b6d..01404b1cb 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -502,7 +502,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) bool grpflg bool usridx uint16_t command_code Item code - uint32_t index Flags + uint32_t index 0:15 Flags, 16:23 Device group index uint32_t data_len String item value length int32_t payload Integer item value char *topic @@ -510,7 +510,8 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) char *command nullptr */ XdrvMailbox.command = nullptr; // Indicates the source is a device group update - XdrvMailbox.index = flags; + XdrvMailbox.index = flags | device_group_index << 16; + light_fade = Settings.light_fade; if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) Settings.light_fade = false; @@ -526,12 +527,12 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) case DGR_ITEM_LIGHT_BRI: case DGR_ITEM_LIGHT_SCHEME: case DGR_ITEM_LIGHT_FIXED_COLOR: - case DGR_ITEM_BRI_MIN: case DGR_ITEM_BRI_PRESET_LOW: case DGR_ITEM_BRI_PRESET_HIGH: case DGR_ITEM_BRI_POWER_ON: case DGR_ITEM_POWER: case DGR_ITEM_LIGHT_CHANNELS: + case DGR_ITEM_DIMMER_RANGE: break; default: AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip)); diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index c1269ccc3..4365b9774 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -230,6 +230,12 @@ void PWMDimmerHandleDeviceGroupRequest() { static bool send_state = false; uint32_t value = XdrvMailbox.payload; +#ifdef USE_PWM_DIMMER_REMOTE + uint8_t device_group_index = XdrvMailbox.index >> 16 & 0xff; + bool device_is_local = device_groups[device_group_index].local; + struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index]; +#endif // USE_PWM_DIMMER_REMOTE + switch (XdrvMailbox.command_code) { case DGR_ITEM_EOL: if (send_state && !(XdrvMailbox.index & DGR_FLAG_MORE_TO_COME)) { @@ -240,45 +246,92 @@ void PWMDimmerHandleDeviceGroupRequest() } break; case DGR_ITEM_LIGHT_BRI: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) { + remote_pwm_dimmer->bri = value; + } + else +#endif // USE_PWM_DIMMER_REMOTE if (target_bri != value) { PWMDimmerSetBri(value); send_state = true; } break; case DGR_ITEM_LIGHT_SPEED: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) { + remote_pwm_dimmer->light_speed = value; + } + else +#endif // USE_PWM_DIMMER_REMOTE if (Settings.light_speed != value && value > 0 && value <= 40) { Settings.light_speed = value; send_state = true; } break; + case DGR_ITEM_LIGHT_FIXED_COLOR: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) { + remote_pwm_dimmer->fixed_color_index = value; + } + else +#endif // USE_PWM_DIMMER_REMOTE + fixed_color_index = value; + break; case DGR_ITEM_DIMMER_RANGE: - Settings.dimmer_hw_min = value & 0xffff; - Settings.dimmer_hw_max = value >> 16; +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) + remote_pwm_dimmer->dimmer_range = value; + else { +#endif // USE_PWM_DIMMER_REMOTE + Settings.dimmer_hw_min = value & 0xffff; + Settings.dimmer_hw_max = value >> 16; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE break; case DGR_ITEM_BRI_PRESET_LOW: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) + remote_pwm_dimmer->bri_preset_low = value; + else +#endif // USE_PWM_DIMMER_REMOTE if (Settings.bri_preset_low != value) { Settings.bri_preset_low = value; send_state = true; } break; case DGR_ITEM_BRI_PRESET_HIGH: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) + remote_pwm_dimmer->bri_preset_high = value; + else +#endif // USE_PWM_DIMMER_REMOTE if (Settings.bri_preset_high != value) { Settings.bri_preset_high = value; send_state = true; } break; case DGR_ITEM_BRI_POWER_ON: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) + remote_pwm_dimmer->bri_power_on = value; + else +#endif // USE_PWM_DIMMER_REMOTE if (Settings.bri_power_on != value) { Settings.bri_power_on = value; send_state = true; } break; case DGR_ITEM_STATUS: - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, - DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_BRI, target_bri, - DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high, - DGR_ITEM_DIMMER_RANGE, Settings.dimmer_hw_min | Settings.dimmer_hw_max << 16, - DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); +#ifdef USE_PWM_DIMMER_REMOTE + if (device_is_local) +#endif // USE_PWM_DIMMER_REMOTE + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, + DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_BRI, target_bri, + DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high, + DGR_ITEM_DIMMER_RANGE, Settings.dimmer_hw_min | Settings.dimmer_hw_max << 16, + DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); break; } } @@ -356,7 +409,7 @@ void PWMDimmerHandleButton() // If this is not about the power button, load the new hold time. Note that the hold time for // the power button is longer than the hold time for the other buttons. - button_hold_time[button_index] = now + 250; + button_hold_time[button_index] = now + 100; } // If the button is being held, send a button hold. @@ -432,50 +485,50 @@ void PWMDimmerHandleButton() ignore_power_button_release = ignore_power_button_hold = true; } - // If the active device is local or the power button if also pressed, then if the down/up - // button has been held, handle the action based on the number of times the down or up button - // was pressed and released before holding it. + // If the active device is local or the power button if also pressed, ... #ifdef USE_PWM_DIMMER_REMOTE if (active_device_is_local == !button_pressed[power_button_index]) { #endif // USE_PWM_DIMMER_REMOTE - if (button_hold_time[button_index] < now) { + bool is_down_button = (button_index == down_button_index); + + // If the power is not on, turn it on using a temporary brightness of bri_preset_low if the + // down button is pressed or bri_preset_low if the up button is pressed. +#ifdef USE_PWM_DIMMER_REMOTE + if ((!active_device_is_local ? !active_remote_pwm_dimmer->power : !power)) { +#else // USE_PWM_DIMMER_REMOTE + if (!power) { +#endif // USE_PWM_DIMMER_REMOTE +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->bri = (is_down_button ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); + else +#endif // USE_PWM_DIMMER_REMOTE + target_bri = (is_down_button ? Settings.bri_preset_low : Settings.bri_preset_high); + toggle_power = true; + button_hold_time[button_index] = now + 500; + + // If the power button is also pressed, set the power button hold dimmer direction + // so holding the power switch adjusts the brightness away from the brightness we + // just set. +#ifdef USE_PWM_DIMMER_REMOTE + if (button_pressed[power_button_index]) active_remote_pwm_dimmer->power_button_increases_bri = is_down_button; +#endif // USE_PWM_DIMMER_REMOTE + } + + // If the power is on and the down/up button has been held, handle the action based on the + // number of times the down or up button was pressed and released before holding it. + else if (button_hold_time[button_index] < now) { uint8_t uint8_value; - bool down_button_is_held = (button_index == down_button_index); + bool is_down_button = (button_index == down_button_index); bool down_button_was_tapped = (button_press_count[down_button_index] > 0); uint8_t tap_count = (down_button_was_tapped ? button_press_count[down_button_index] : button_press_count[up_button_index]); uint16_t uint16_value; switch (tap_count) { case 0: - // If the power is on, adjust the brightness. Set the direction based on which button is - // pressed. The new brightness will be calculated below. -#ifdef USE_PWM_DIMMER_REMOTE - if ((!active_device_is_local ? active_remote_pwm_dimmer->power : power)) { -#else // USE_PWM_DIMMER_REMOTE - if (power) { -#endif // USE_PWM_DIMMER_REMOTE - bri_direction = (down_button_is_held ? -1 : 1); - } - - // If the power is not on, turn it on using a temporary brightness of bri_preset_low if - // the down button is pressed or bri_preset_low if the up button is pressed. - else { -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) - active_remote_pwm_dimmer->bri = (down_button_is_held ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); - else -#endif // USE_PWM_DIMMER_REMOTE - target_bri = (down_button_is_held ? Settings.bri_preset_low : Settings.bri_preset_high); - toggle_power = true; - button_hold_time[button_index] = now + 1000; - - // If the power button is also pressed, set the power button hold dimmer direction - // so holding the power switch adjusts the brightness away from the brightness we - // just set. -#ifdef USE_PWM_DIMMER_REMOTE - if (button_pressed[power_button_index]) active_remote_pwm_dimmer->power_button_increases_bri = down_button_is_held; -#endif // USE_PWM_DIMMER_REMOTE - } + // Adjust the brightness. Set the direction based on which button is pressed. The new + // brightness will be calculated below. + bri_direction = (is_down_button ? -1 : 1); break; case 1: @@ -488,7 +541,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint8_value = fixed_color_index; - if (down_button_is_held) { + if (is_down_button) { if (uint8_value) uint8_value--; else @@ -519,7 +572,7 @@ void PWMDimmerHandleButton() #else // USE_PWM_DIMMER_REMOTE snprintf_P(topic, sizeof(topic), PSTR("%s/cmnd/Event"), SettingsText(SET_MQTT_GRP_TOPIC)); #endif // USE_PWM_DIMMER_REMOTE - sprintf_P(mqtt_data, PSTR("SwitchTrigger%u"), (down_button_is_held ? 1 : 2)); + sprintf_P(mqtt_data, PSTR("SwitchTrigger%u"), (is_down_button ? 1 : 2)); MqttPublish(topic); } break; @@ -533,7 +586,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint16_value = Settings.dimmer_hw_min; - if (down_button_is_held) { + if (is_down_button) { if (uint16_value > 0) uint16_value--; } else if (uint16_value < 65535) { @@ -561,7 +614,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.light_speed; - if (down_button_is_held) { + if (is_down_button) { if (uint8_value > 1) uint8_value--; } else if (uint8_value < 40) { @@ -587,7 +640,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.bri_preset_low; - if (down_button_is_held) { + if (is_down_button) { if (uint8_value > 3) uint8_value--; } else if (uint8_value < 255) { @@ -610,7 +663,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.bri_preset_high; - if (down_button_is_held) { + if (is_down_button) { if (uint8_value > 3) uint8_value--; } else if (uint8_value < 255) { @@ -630,18 +683,14 @@ void PWMDimmerHandleButton() button_was_held = true; - // If the button was tapped before it was held, reset the button hold time to one second and - // turn all the brightness LEDs on for 250ms. + // If the button was tapped before it was held, reset the button hold time to 1/2 second + // and turn all the brightness LEDs on for 250ms. if (tap_count > 0) { - button_hold_time[button_index] = now + 1000; + button_hold_time[button_index] = now + 500; turn_off_brightness_leds_time = now + 250; PWMDimmerSetBrightnessLeds(1); } } - else if (turn_off_brightness_leds_time && turn_off_brightness_leds_time < millis()) { - turn_off_brightness_leds_time = 0; - PWMDimmerSetBrightnessLeds(-1); - } #ifdef USE_PWM_DIMMER_REMOTE } #endif // USE_PWM_DIMMER_REMOTE @@ -870,6 +919,11 @@ void PWMDimmerHandleButton() MqttPublishTeleState(); } } + + if (turn_off_brightness_leds_time && turn_off_brightness_leds_time < millis()) { + turn_off_brightness_leds_time = 0; + PWMDimmerSetBrightnessLeds(-1); + } } /*********************************************************************************************\ From 248288d549b6d1c7e1c10ef82c0151c258e898f6 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Thu, 27 Feb 2020 20:41:29 -0600 Subject: [PATCH 514/559] Handle remote switch updates, Make tap/hold functions available only when power is on --- PWM_Dimmer.md | 6 +- tasmota/support_device_groups.ino | 7 +- tasmota/xdrv_35_pwm_dimmer.ino | 164 ++++++++++++++++++++---------- 3 files changed, 116 insertions(+), 61 deletions(-) diff --git a/PWM_Dimmer.md b/PWM_Dimmer.md index a89b0e752..5ba143fec 100644 --- a/PWM_Dimmer.md +++ b/PWM_Dimmer.md @@ -11,17 +11,17 @@ To enable PWM dimmer operation, select the PWM Dimmer module. Pressing and releasing the power button toggles the power on/off. If the toggle turns the power on, the load is returned to the last brightness it was adjusted to. If Fade is enabled, the load is faded on/off at the rate defined by the Speed setting. -When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster at higher brightnesses. The DimmerRange command set the minimum and maximum PWM values. Brightness values (0 - 255) are scaled to dimmerMin to dimmerMax. Typically, dimmerMin would be set to the lowest value at which the lights show visible light and dimmerMax would be set 1023. If you want to increase the lowest brightness level and/or decrease the highest brightness level, set higher dimmerMin and/or lower dimmerMax values. +When the power is on, holding the down or up button decreases/increases the brightness (PWM value). The brightness is changed faster at higher brightnesses. The DimmerRange command sets the minimum and maximum PWM values. Brightness values (0 through 255) are scaled to dimmerMin through dimmerMax. Typically, dimmerMin would be set to the lowest value at which the lights show visible light and dimmerMax would be set 1023. If you want to increase the lowest brightness level and/or decrease the highest brightness level, set higher dimmerMin and/or lower dimmerMax values. The brightness can also be changed using just the power button. When the power is on, holding the power button alternately increases or decreases the brightness. Initially, holding the power button increases the brightness. Releasing and then holding the power button again decreases the brightness. -When the power is off, holding the down or up button turns the power on at a temporary brightness of the low/high levels set by the BriPreset command (default =10,255). Turning the power on at the low preset can also be accomplished by holding the power button while the power is off. The brightness presets are intended to enable quickly turning on a light to a dim or bright level without changing the normal desired brightness. Turning the power on to a preset does not change the brightness the load will be set to when the switch is turned on the next time. For example, if the light is on and you adjust the brightness to 80 and then turn the light off, when you turn it back on, the brightness will return to 80. If you turn the power off again and then press the down button, the light will be turned on with a brightness of the low preset. If you then turn the light off and on again, the brightness will return to 80. +When the power is off, pressing the down or up button turns the power on at a temporary brightness of the low/high levels set by the BriPreset command (default =10,255). Turning the power on at the low preset can also be accomplished by holding the power button while the power is off. The brightness presets are intended to enable quickly turning on a light to a dim or bright level without changing the normal desired brightness. Turning the power on to a preset does not change the brightness the load will be set to when the switch is turned on the next time. For example, if the light is on and you adjust the brightness to 80 and then turn the light off, when you turn it back on, the brightness will return to 80. If you turn the power off again and then press the down button, the light will be turned on with a brightness of the low preset. If you then turn the light off and on again, the brightness will return to 80. If there are LED’s defined in the template, they are turned on to indicate the current brightness. More LEDs are turned on at higher brightnesses. The LedTimeout command enables/disables an LED timeout. If LED timeout is enabled, the LED’s turn off five seconds after the last change in brightness. Note that the lowest LED and the blue power LED are always on when the power is on. The LEDLink LED can be used as a nightlight/powered-off indicator. The PoweredOffLed command enables/disables turning the LEDLink LED on when the power is off. -Tapping (pressing and releasing quickly) the down or up buttons a given number of times and then holding the down or up button decreases or increases settings according to the table below. For example, tapping the down button once and then holding the up button sets all RGB lights in the device group to the next fixed color. Tapping the up button three times and then holding the down button decreases the high brightness preset. +When the power is on, tapping (pressing and releasing quickly) the down or up buttons a given number of times and then holding the down or up button decreases or increases settings according to the table below. For example, tapping the down button once and then holding the up button sets all RGB lights in the device group to the next fixed color. Tapping the up button three times and then holding the down button decreases the high brightness preset.
diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index faf3e0b6d..01404b1cb 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -502,7 +502,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) bool grpflg bool usridx uint16_t command_code Item code - uint32_t index Flags + uint32_t index 0:15 Flags, 16:23 Device group index uint32_t data_len String item value length int32_t payload Integer item value char *topic @@ -510,7 +510,8 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) char *command nullptr */ XdrvMailbox.command = nullptr; // Indicates the source is a device group update - XdrvMailbox.index = flags; + XdrvMailbox.index = flags | device_group_index << 16; + light_fade = Settings.light_fade; if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) Settings.light_fade = false; @@ -526,12 +527,12 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) case DGR_ITEM_LIGHT_BRI: case DGR_ITEM_LIGHT_SCHEME: case DGR_ITEM_LIGHT_FIXED_COLOR: - case DGR_ITEM_BRI_MIN: case DGR_ITEM_BRI_PRESET_LOW: case DGR_ITEM_BRI_PRESET_HIGH: case DGR_ITEM_BRI_POWER_ON: case DGR_ITEM_POWER: case DGR_ITEM_LIGHT_CHANNELS: + case DGR_ITEM_DIMMER_RANGE: break; default: AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: ********** invalid item=%u received from device group %s member %s"), item, device_group->group_name, IPAddressToString(remote_ip)); diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index c1269ccc3..4365b9774 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -230,6 +230,12 @@ void PWMDimmerHandleDeviceGroupRequest() { static bool send_state = false; uint32_t value = XdrvMailbox.payload; +#ifdef USE_PWM_DIMMER_REMOTE + uint8_t device_group_index = XdrvMailbox.index >> 16 & 0xff; + bool device_is_local = device_groups[device_group_index].local; + struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index]; +#endif // USE_PWM_DIMMER_REMOTE + switch (XdrvMailbox.command_code) { case DGR_ITEM_EOL: if (send_state && !(XdrvMailbox.index & DGR_FLAG_MORE_TO_COME)) { @@ -240,45 +246,92 @@ void PWMDimmerHandleDeviceGroupRequest() } break; case DGR_ITEM_LIGHT_BRI: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) { + remote_pwm_dimmer->bri = value; + } + else +#endif // USE_PWM_DIMMER_REMOTE if (target_bri != value) { PWMDimmerSetBri(value); send_state = true; } break; case DGR_ITEM_LIGHT_SPEED: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) { + remote_pwm_dimmer->light_speed = value; + } + else +#endif // USE_PWM_DIMMER_REMOTE if (Settings.light_speed != value && value > 0 && value <= 40) { Settings.light_speed = value; send_state = true; } break; + case DGR_ITEM_LIGHT_FIXED_COLOR: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) { + remote_pwm_dimmer->fixed_color_index = value; + } + else +#endif // USE_PWM_DIMMER_REMOTE + fixed_color_index = value; + break; case DGR_ITEM_DIMMER_RANGE: - Settings.dimmer_hw_min = value & 0xffff; - Settings.dimmer_hw_max = value >> 16; +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) + remote_pwm_dimmer->dimmer_range = value; + else { +#endif // USE_PWM_DIMMER_REMOTE + Settings.dimmer_hw_min = value & 0xffff; + Settings.dimmer_hw_max = value >> 16; +#ifdef USE_PWM_DIMMER_REMOTE + } +#endif // USE_PWM_DIMMER_REMOTE break; case DGR_ITEM_BRI_PRESET_LOW: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) + remote_pwm_dimmer->bri_preset_low = value; + else +#endif // USE_PWM_DIMMER_REMOTE if (Settings.bri_preset_low != value) { Settings.bri_preset_low = value; send_state = true; } break; case DGR_ITEM_BRI_PRESET_HIGH: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) + remote_pwm_dimmer->bri_preset_high = value; + else +#endif // USE_PWM_DIMMER_REMOTE if (Settings.bri_preset_high != value) { Settings.bri_preset_high = value; send_state = true; } break; case DGR_ITEM_BRI_POWER_ON: +#ifdef USE_PWM_DIMMER_REMOTE + if (!device_is_local) + remote_pwm_dimmer->bri_power_on = value; + else +#endif // USE_PWM_DIMMER_REMOTE if (Settings.bri_power_on != value) { Settings.bri_power_on = value; send_state = true; } break; case DGR_ITEM_STATUS: - SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, - DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_BRI, target_bri, - DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high, - DGR_ITEM_DIMMER_RANGE, Settings.dimmer_hw_min | Settings.dimmer_hw_max << 16, - DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); +#ifdef USE_PWM_DIMMER_REMOTE + if (device_is_local) +#endif // USE_PWM_DIMMER_REMOTE + SendLocalDeviceGroupMessage(DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade, + DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_BRI, target_bri, + DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high, + DGR_ITEM_DIMMER_RANGE, Settings.dimmer_hw_min | Settings.dimmer_hw_max << 16, + DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on); break; } } @@ -356,7 +409,7 @@ void PWMDimmerHandleButton() // If this is not about the power button, load the new hold time. Note that the hold time for // the power button is longer than the hold time for the other buttons. - button_hold_time[button_index] = now + 250; + button_hold_time[button_index] = now + 100; } // If the button is being held, send a button hold. @@ -432,50 +485,50 @@ void PWMDimmerHandleButton() ignore_power_button_release = ignore_power_button_hold = true; } - // If the active device is local or the power button if also pressed, then if the down/up - // button has been held, handle the action based on the number of times the down or up button - // was pressed and released before holding it. + // If the active device is local or the power button if also pressed, ... #ifdef USE_PWM_DIMMER_REMOTE if (active_device_is_local == !button_pressed[power_button_index]) { #endif // USE_PWM_DIMMER_REMOTE - if (button_hold_time[button_index] < now) { + bool is_down_button = (button_index == down_button_index); + + // If the power is not on, turn it on using a temporary brightness of bri_preset_low if the + // down button is pressed or bri_preset_low if the up button is pressed. +#ifdef USE_PWM_DIMMER_REMOTE + if ((!active_device_is_local ? !active_remote_pwm_dimmer->power : !power)) { +#else // USE_PWM_DIMMER_REMOTE + if (!power) { +#endif // USE_PWM_DIMMER_REMOTE +#ifdef USE_PWM_DIMMER_REMOTE + if (!active_device_is_local) + active_remote_pwm_dimmer->bri = (is_down_button ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); + else +#endif // USE_PWM_DIMMER_REMOTE + target_bri = (is_down_button ? Settings.bri_preset_low : Settings.bri_preset_high); + toggle_power = true; + button_hold_time[button_index] = now + 500; + + // If the power button is also pressed, set the power button hold dimmer direction + // so holding the power switch adjusts the brightness away from the brightness we + // just set. +#ifdef USE_PWM_DIMMER_REMOTE + if (button_pressed[power_button_index]) active_remote_pwm_dimmer->power_button_increases_bri = is_down_button; +#endif // USE_PWM_DIMMER_REMOTE + } + + // If the power is on and the down/up button has been held, handle the action based on the + // number of times the down or up button was pressed and released before holding it. + else if (button_hold_time[button_index] < now) { uint8_t uint8_value; - bool down_button_is_held = (button_index == down_button_index); + bool is_down_button = (button_index == down_button_index); bool down_button_was_tapped = (button_press_count[down_button_index] > 0); uint8_t tap_count = (down_button_was_tapped ? button_press_count[down_button_index] : button_press_count[up_button_index]); uint16_t uint16_value; switch (tap_count) { case 0: - // If the power is on, adjust the brightness. Set the direction based on which button is - // pressed. The new brightness will be calculated below. -#ifdef USE_PWM_DIMMER_REMOTE - if ((!active_device_is_local ? active_remote_pwm_dimmer->power : power)) { -#else // USE_PWM_DIMMER_REMOTE - if (power) { -#endif // USE_PWM_DIMMER_REMOTE - bri_direction = (down_button_is_held ? -1 : 1); - } - - // If the power is not on, turn it on using a temporary brightness of bri_preset_low if - // the down button is pressed or bri_preset_low if the up button is pressed. - else { -#ifdef USE_PWM_DIMMER_REMOTE - if (!active_device_is_local) - active_remote_pwm_dimmer->bri = (down_button_is_held ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high); - else -#endif // USE_PWM_DIMMER_REMOTE - target_bri = (down_button_is_held ? Settings.bri_preset_low : Settings.bri_preset_high); - toggle_power = true; - button_hold_time[button_index] = now + 1000; - - // If the power button is also pressed, set the power button hold dimmer direction - // so holding the power switch adjusts the brightness away from the brightness we - // just set. -#ifdef USE_PWM_DIMMER_REMOTE - if (button_pressed[power_button_index]) active_remote_pwm_dimmer->power_button_increases_bri = down_button_is_held; -#endif // USE_PWM_DIMMER_REMOTE - } + // Adjust the brightness. Set the direction based on which button is pressed. The new + // brightness will be calculated below. + bri_direction = (is_down_button ? -1 : 1); break; case 1: @@ -488,7 +541,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint8_value = fixed_color_index; - if (down_button_is_held) { + if (is_down_button) { if (uint8_value) uint8_value--; else @@ -519,7 +572,7 @@ void PWMDimmerHandleButton() #else // USE_PWM_DIMMER_REMOTE snprintf_P(topic, sizeof(topic), PSTR("%s/cmnd/Event"), SettingsText(SET_MQTT_GRP_TOPIC)); #endif // USE_PWM_DIMMER_REMOTE - sprintf_P(mqtt_data, PSTR("SwitchTrigger%u"), (down_button_is_held ? 1 : 2)); + sprintf_P(mqtt_data, PSTR("SwitchTrigger%u"), (is_down_button ? 1 : 2)); MqttPublish(topic); } break; @@ -533,7 +586,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint16_value = Settings.dimmer_hw_min; - if (down_button_is_held) { + if (is_down_button) { if (uint16_value > 0) uint16_value--; } else if (uint16_value < 65535) { @@ -561,7 +614,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.light_speed; - if (down_button_is_held) { + if (is_down_button) { if (uint8_value > 1) uint8_value--; } else if (uint8_value < 40) { @@ -587,7 +640,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.bri_preset_low; - if (down_button_is_held) { + if (is_down_button) { if (uint8_value > 3) uint8_value--; } else if (uint8_value < 255) { @@ -610,7 +663,7 @@ void PWMDimmerHandleButton() else #endif // USE_PWM_DIMMER_REMOTE uint8_value = Settings.bri_preset_high; - if (down_button_is_held) { + if (is_down_button) { if (uint8_value > 3) uint8_value--; } else if (uint8_value < 255) { @@ -630,18 +683,14 @@ void PWMDimmerHandleButton() button_was_held = true; - // If the button was tapped before it was held, reset the button hold time to one second and - // turn all the brightness LEDs on for 250ms. + // If the button was tapped before it was held, reset the button hold time to 1/2 second + // and turn all the brightness LEDs on for 250ms. if (tap_count > 0) { - button_hold_time[button_index] = now + 1000; + button_hold_time[button_index] = now + 500; turn_off_brightness_leds_time = now + 250; PWMDimmerSetBrightnessLeds(1); } } - else if (turn_off_brightness_leds_time && turn_off_brightness_leds_time < millis()) { - turn_off_brightness_leds_time = 0; - PWMDimmerSetBrightnessLeds(-1); - } #ifdef USE_PWM_DIMMER_REMOTE } #endif // USE_PWM_DIMMER_REMOTE @@ -870,6 +919,11 @@ void PWMDimmerHandleButton() MqttPublishTeleState(); } } + + if (turn_off_brightness_leds_time && turn_off_brightness_leds_time < millis()) { + turn_off_brightness_leds_time = 0; + PWMDimmerSetBrightnessLeds(-1); + } } /*********************************************************************************************\ From 5f5becfac61e5fc7665ebc45943372e9e1796a43 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Thu, 27 Feb 2020 21:35:13 -0600 Subject: [PATCH 515/559] Fix up/down release after power on --- tasmota/xdrv_35_pwm_dimmer.ino | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index 4365b9774..103b2a2ee 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -72,6 +72,7 @@ uint8_t button_press_count[3] = { 0, 0, 0 }; bool relay_is_on = false; bool ignore_power_button_hold; bool ignore_power_button_release; +bool ignore_up_down_button_release = false; bool button_was_held = false; bool power_button_increases_bri = true; bool invert_power_button_bri_direction = false; @@ -506,6 +507,7 @@ void PWMDimmerHandleButton() target_bri = (is_down_button ? Settings.bri_preset_low : Settings.bri_preset_high); toggle_power = true; button_hold_time[button_index] = now + 500; + ignore_up_down_button_release = true; // If the power button is also pressed, set the power button hold dimmer direction // so holding the power switch adjusts the brightness away from the brightness we @@ -519,7 +521,6 @@ void PWMDimmerHandleButton() // number of times the down or up button was pressed and released before holding it. else if (button_hold_time[button_index] < now) { uint8_t uint8_value; - bool is_down_button = (button_index == down_button_index); bool down_button_was_tapped = (button_press_count[down_button_index] > 0); uint8_t tap_count = (down_button_was_tapped ? button_press_count[down_button_index] : button_press_count[up_button_index]); uint16_t uint16_value; @@ -864,8 +865,13 @@ void PWMDimmerHandleButton() button_press_count[button_index] = 0; } - // If the button was tapped (pressed and released quickly), increment the count of how many - // times this button has been pressed. + // If the power was off and we turned it on with the down or up button, ignore it's release. + if (ignore_up_down_button_release) { + ignore_up_down_button_release = false; + } + + // If the button was tapped (pressed and released quickly) and the power is on, increment the + // count of how many times this button has been pressed. else if (button_hold_time[button_index] >= now) { button_press_count[button_index]++; } @@ -899,7 +905,7 @@ void PWMDimmerHandleButton() SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_BRI, new_bri, DGR_ITEM_POWER, new_power); else SendDeviceGroupMessage(power_button_index, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, new_power); -#endif // USE_DEVICE_GROUPS +#endif //0 USE_DEVICE_GROUPS #ifdef USE_PWM_DIMMER_REMOTE // The target brightness has already been set. Execute the toggle power command with a source of From b27b18a8e62fe663c8a5716de8c79508d3c6fe96 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Thu, 27 Feb 2020 23:38:55 -0600 Subject: [PATCH 516/559] Add button press count timeout --- tasmota/xdrv_04_light.ino | 3 +++ tasmota/xdrv_35_pwm_dimmer.ino | 30 +++++++++++++----------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index d46ae7eef..fc684f5f7 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -2123,7 +2123,9 @@ void LightHandleDeviceGroupRequest() break; case DGR_ITEM_LIGHT_FIXED_COLOR: { + struct XDRVMAILBOX save_XdrvMailbox; power_t save_power = Light.power; + if (value) { bool save_decimal_text = Settings.flag.decimal_text; char str[16]; @@ -2143,6 +2145,7 @@ void LightHandleDeviceGroupRequest() XdrvMailbox.index = save_power; LightSetPower(); } + XdrvMailbox = save_XdrvMailbox; send_state = true; } break; diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino index 103b2a2ee..cf7dee97a 100644 --- a/tasmota/xdrv_35_pwm_dimmer.ino +++ b/tasmota/xdrv_35_pwm_dimmer.ino @@ -60,6 +60,7 @@ struct remote_pwm_dimmer { uint32_t led_timeout_time = 0; uint32_t turn_off_brightness_leds_time = 0; +uint32_t button_press_count_timeout = 0; uint32_t button_hold_time[3]; uint8_t current_bri; uint8_t target_bri; @@ -68,6 +69,7 @@ uint8_t power_button_index = 0; uint8_t down_button_index = 1; uint8_t up_button_index = 2; uint8_t fixed_color_index; +uint8_t buttons_pressed = 0; uint8_t button_press_count[3] = { 0, 0, 0 }; bool relay_is_on = false; bool ignore_power_button_hold; @@ -81,7 +83,6 @@ bool button_pressed[3] = { false, false, false }; #ifdef USE_PWM_DIMMER_REMOTE struct remote_pwm_dimmer * remote_pwm_dimmers; struct remote_pwm_dimmer * active_remote_pwm_dimmer; -uint8_t buttons_pressed = 0; bool active_device_is_local; #endif // USE_PWM_DIMMER_REMOTE @@ -378,15 +379,13 @@ void PWMDimmerHandleButton() if (!XdrvMailbox.payload) { int8_t bri_direction = 0; - // If the button was just pressed, reset the press count if it was released for longer than 1 - // second, flag the button as pressed, clear the hold sent flag and increment the buttons - // pressed count. + // If the button was just pressed, flag the button as pressed, clear the hold sent flag and + // increment the buttons pressed count. if (!button_pressed[button_index]) { - if (now > button_hold_time[button_index] && now - button_hold_time[button_index] > 1000) button_press_count[button_index] = 0; button_pressed[button_index] = true; button_hold_sent[button_index] = false; -#ifdef USE_PWM_DIMMER_REMOTE buttons_pressed++; +#ifdef USE_PWM_DIMMER_REMOTE // If there are no other buttons pressed right now and remote mode is enabled, make the device // associated with this button the device we're going to control. @@ -410,7 +409,7 @@ void PWMDimmerHandleButton() // If this is not about the power button, load the new hold time. Note that the hold time for // the power button is longer than the hold time for the other buttons. - button_hold_time[button_index] = now + 100; + button_hold_time[button_index] = now + 500; } // If the button is being held, send a button hold. @@ -842,16 +841,9 @@ void PWMDimmerHandleButton() if (button_was_held) { button_was_held = false; - // If the button was tapped before it was held, we used the brightness LEDs to inidcate the - // operation so reset the brightness LEDs. - if (button_press_count[down_button_index] > 0 || button_press_count[up_button_index]) { - turn_off_brightness_leds_time = 0; - PWMDimmerSetBrightnessLeds(0); - } - // If the button was not tapped before it was held, we changed the brightness and sent // updates with the more-to-come message type. Send a final update. - else { + if (button_press_count[down_button_index] == 0 && button_press_count[up_button_index == 0]) { dgr_item = DGR_ITEM_LIGHT_BRI; #ifdef USE_PWM_DIMMER_REMOTE if (!active_device_is_local) @@ -879,9 +871,13 @@ void PWMDimmerHandleButton() // Flag the button as released. button_pressed[button_index] = false; -#ifdef USE_PWM_DIMMER_REMOTE buttons_pressed--; -#endif // USE_PWM_DIMMER_REMOTE + button_press_count_timeout = now + 500; + } + + // If + else if (buttons_pressed == 0 && button_press_count_timeout && button_press_count_timeout < now) { + button_press_count[0] = button_press_count[1] = button_press_count[2] = 0; } if (toggle_power) { From 94f5321db45f0254620e0ea505108ee05d51a683 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Feb 2020 16:35:19 +0100 Subject: [PATCH 517/559] Fix keeloq functionality --- tasmota/support_features.ino | 4 ++- tasmota/xdrv_36_keeloq.ino | 54 +++++++++++++++++++++++------------- tools/decode-status.py | 4 +-- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 6cb81522a..6a13573c1 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -530,7 +530,9 @@ void GetFeatures(void) feature6 = 0x00000000; -// feature6 |= 0x00000001; +#ifdef USE_KEELOQ + feature6 |= 0x00000001; // xdrv_36keeloq.ino +#endif // feature6 |= 0x00000002; // feature6 |= 0x00000004; // feature6 |= 0x00000008; diff --git a/tasmota/xdrv_36_keeloq.ino b/tasmota/xdrv_36_keeloq.ino index edac0ee23..d975a5a79 100644 --- a/tasmota/xdrv_36_keeloq.ino +++ b/tasmota/xdrv_36_keeloq.ino @@ -1,5 +1,7 @@ /* - xdrv_36 + xdrv_36_keeloq.ino - Jarolift Keeloq shutter support for Tasmota + + Copyright (C) 2020 he-so 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 @@ -16,6 +18,14 @@ */ #ifdef USE_KEELOQ +/*********************************************************************************************\ + * Keeloq shutter support + * + * Uses hardware SPI and two user configurable GPIO's (CC1101 GDO0 and CC1101 GDO2) + * + * Considering the implementation these two user GPIO's are fake. + * Only CC1101 GDO0 is used and must always be GPIO05 dictated by the used CC1101 library. +\*********************************************************************************************/ #define XDRV_36 36 @@ -27,9 +37,6 @@ #define Lowpulse 400 #define Highpulse 800 -#define TX_PORT pin[GPIO_CC1101_GDO2] // Outputport for transmission -#define RX_PORT pin[GPIO_CC1101_GDO0] // Inputport for reception - const char kJaroliftCommands[] PROGMEM = "Keeloq|" // prefix "SendRaw|SendButton|Set"; @@ -47,6 +54,8 @@ struct JAROLIFT_DEVICE { uint64_t pack = 0; // Contains data to send. int count = 0; uint32_t serial = 0x0; + uint8_t port_tx; + uint8_t port_rx; } jaroliftDevice; void CmdSet(void) @@ -75,7 +84,7 @@ void CmdSet(void) GenerateDeviceCryptKey(); ResponseCmndDone(); } else { - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("no payload")); + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("no payload")); } } else { DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("no param")); @@ -114,7 +123,7 @@ void CmdSendButton(void) for(int repeat = 0; repeat <= 1; repeat++) { uint64_t bitsToSend = jaroliftDevice.pack; - digitalWrite(TX_PORT, LOW); + digitalWrite(jaroliftDevice.port_tx, LOW); delayMicroseconds(1150); SendSyncPreamble(13); delayMicroseconds(3500); @@ -140,16 +149,16 @@ void SendBit(byte bitToSend) { if (bitToSend==1) { - digitalWrite(TX_PORT, LOW); // Simple encoding of bit state 1 + digitalWrite(jaroliftDevice.port_tx, LOW); // Simple encoding of bit state 1 delayMicroseconds(Lowpulse); - digitalWrite(TX_PORT, HIGH); + digitalWrite(jaroliftDevice.port_tx, HIGH); delayMicroseconds(Highpulse); } else { - digitalWrite(TX_PORT, LOW); // Simple encoding of bit state 0 + digitalWrite(jaroliftDevice.port_tx, LOW); // Simple encoding of bit state 0 delayMicroseconds(Highpulse); - digitalWrite(TX_PORT, HIGH); + digitalWrite(jaroliftDevice.port_tx, HIGH); delayMicroseconds(Lowpulse); } } @@ -163,7 +172,7 @@ void CmndSendRaw(void) { if (XdrvMailbox.data_len > 0) { - digitalWrite(TX_PORT, LOW); + digitalWrite(jaroliftDevice.port_tx, LOW); delayMicroseconds(1150); SendSyncPreamble(13); delayMicroseconds(3500); @@ -208,9 +217,9 @@ void SendSyncPreamble(int l) { for (int i = 0; i < l; ++i) { - digitalWrite(TX_PORT, LOW); + digitalWrite(jaroliftDevice.port_tx, LOW); delayMicroseconds(400); - digitalWrite(TX_PORT, HIGH); + digitalWrite(jaroliftDevice.port_tx, HIGH); delayMicroseconds(380); } } @@ -231,8 +240,11 @@ void CreateKeeloqPacket() AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("pack low: %08x"), jaroliftDevice.pack); } -void InitKeeloq() +void KeeloqInit() { + jaroliftDevice.port_tx = pin[GPIO_CC1101_GDO2]; // Output port for transmission + jaroliftDevice.port_rx = pin[GPIO_CC1101_GDO0]; // Input port for reception + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("cc1101.init()")); delay(100); cc1101.init(); @@ -241,8 +253,8 @@ void InitKeeloq() cc1101.setCarrierFreq(CFREQ_433); cc1101.disableAddressCheck(); - pinMode(TX_PORT, OUTPUT); - pinMode(RX_PORT, INPUT_PULLUP); + pinMode(jaroliftDevice.port_tx, OUTPUT); + pinMode(jaroliftDevice.port_rx, INPUT_PULLUP); jaroliftDevice.serial = Settings.keeloq_serial; jaroliftDevice.count = Settings.keeloq_count; @@ -254,17 +266,19 @@ void InitKeeloq() \*********************************************************************************************/ bool Xdrv36(uint8_t function) { + if ((99 == pin[GPIO_CC1101_GDO0]) || (99 == pin[GPIO_CC1101_GDO2])) { return false; } + bool result = false; switch (function) { - case FUNC_INIT: - InitKeeloq(); - DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("init done.")); - break; case FUNC_COMMAND: AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("calling command")); result = DecodeCommand(kJaroliftCommands, jaroliftCommand); break; + case FUNC_INIT: + KeeloqInit(); + DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("init done.")); + break; } return result; diff --git a/tools/decode-status.py b/tools/decode-status.py index 192696ad8..126b050aa 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -198,7 +198,7 @@ a_features = [[ "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", "USE_AHT1x","USE_WEMOS_MOTOR_V1","USE_DEVICE_GROUPS","USE_PWM_DIMMER" ],[ - "","","","", + "USE_KEELOQ","","","", "","","","", "","","","", "","","","", @@ -239,7 +239,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200227 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200228 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From 1ef284cdf2d82a64e36d8011f9d14325e78ae15c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Feb 2020 18:09:23 +0100 Subject: [PATCH 518/559] Experimental support Sonoff D1 Experimental support Sonoff D1 (#7598) --- tasmota/xdrv_39_sonoff_d1.ino | 217 ++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 tasmota/xdrv_39_sonoff_d1.ino diff --git a/tasmota/xdrv_39_sonoff_d1.ino b/tasmota/xdrv_39_sonoff_d1.ino new file mode 100644 index 000000000..c30bea290 --- /dev/null +++ b/tasmota/xdrv_39_sonoff_d1.ino @@ -0,0 +1,217 @@ +/* + xdrv_39_sonoff_d1.ino - sonoff D1 dimmer support for Tasmota + + Copyright (C) 2020 Theo Arends and robbz23 (protocol analysis) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +//#define USE_SONOFF_D1 + +#ifdef USE_SONOFF_D1 +/*********************************************************************************************\ + * Sonoff D1 dimmer 433 + * + * 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 + * AA 55 - Header + * 01 04 - Version? + * 00 0A - Following data length (10 bytes) + * 01 - Power state (00 = off, 01 = on, FF = ignore) + * 64 - Dimmer percentage (01 to 64 = 1 to 100%) + * FF FF FF FF FF FF FF FF - Not used + * 6C - CRC over bytes 2 to F (Addition) + * + * Based on Gravitate1: + * When I switch the light ON via the app, I get: + * AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C + * + * When I switch it OFF, I get: + * AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B + * + * When I set it to 1%, I get: + * AA 55 01 04 00 0A FF 01 FF FF FF FF FF FF FF FF 07 + * AB 55 FD F7 FF FF F5 01 FF FF FF FF FF FF FF FF 09 + * + * When I set it to 6%, I get: + * AA 55 01 04 00 0A FF 06 FF FF FF FF FF FF FF FF 0C + * AB 55 FD F7 FF FF F5 06 FF FF FF FF FF FF FF FF 0E + * + * When I set it to 100%, I get: + * AA 55 01 04 00 0A FF 64 FF FF FF FF FF FF FF FF 6A + * AB 55 FD F7 FF FF F5 64 FF FF FF FF FF FF FF FF 6C + * + * Based on robbz23: + * 00:17:59 CMD: Baudrate 9600 + * 00:17:59 SER: Set to 8N1 9600 bit/s + * 00:17:59 RSL: stat/tasmota_D9E56D/RESULT = {"Baudrate":9600} + * + * 00:25:32 CMD: SerialSend5 aa 55 01 04 00 0a 01 22 ffffffffffffffff 29 + * 00:25:32 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} + * + * 00:26:35 CMD: SerialSend5 aa 55 01 04 00 0a 01 22 ffffffffffffffff 2a + * 00:26:35 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} + * 00:26:35 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 00 05} + * + * 00:28:58 CMD: SerialSend5 aa 55 01 04 00 0a 01 01 ffffffffffffffff 09 + * 00:28:58 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} + * 00:28:58 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 00 05} + * + * 00:29:12 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 3C FF FF FF FF FF FF FF FF 44} + * 00:29:43 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 01 FF FF FF FF FF FF FF FF 09} + * 00:29:53 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C} + * + * 00:30:02 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A FF 1E FF FF FF FF FF FF FF FF 24} +\*********************************************************************************************/ + +#define XDRV_39 39 + +struct SONOFFD1 { + uint8_t receive_flag = 0; + uint8_t dimmer; +} SnfD1; + +/********************************************************************************************/ + +void SonoffD1Received(void) +{ + char svalue[32]; + + uint8_t action = serial_in_buffer[6]; + uint8_t dimmer = serial_in_buffer[7]; + + if (action < 2) { + // AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C - Power On, Dimmer 100% + // AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B - Power Off, Dimmer 100% + bool is_switch_change = (action != power); + if (is_switch_change) { + ExecuteCommandPower(1, action, SRC_SWITCH); + } + } + else if (0xFF == action) { + SnfD1.dimmer = dimmer; + bool is_brightness_change = SnfD1.dimmer != Settings.light_dimmer; + if (power && (SnfD1.dimmer > 0) && is_brightness_change) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), SnfD1.dimmer); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + + // Send Acknowledge - Copy first 5 bytes, reset byte 6 and store crc in byte 7 + // AA 55 01 04 00 00 05 + serial_in_buffer[5] = 0; // Ack + serial_in_buffer[6] = 0; // Crc + for (uint32_t i = 0; i < 7; i++) { + if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } + Serial.write(serial_in_buffer[i]); + } +} + +bool SonoffD1SerialInput(void) +{ + uint8_t packet_length = 0; + + if (0xAA == serial_in_byte) { // 0xAA - Start of text + serial_in_byte_counter = 0; + SnfD1.receive_flag = true; + } + if (SnfD1.receive_flag) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (serial_in_byte_counter == 5) { + packet_length = 7 + serial_in_byte; // 8 or 17 + } + if (serial_in_byte_counter == packet_length) { + + // Sonoff D1 codes + // AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C - Power On, Dimmer 100% + // AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B - Power Off, Dimmer 100% + // AA 55 01 04 00 0A FF 01 FF FF FF FF FF FF FF FF 07 - Power ignore, Dimmer 1% + // AB 55 FD F7 FF FF F5 01 FF FF FF FF FF FF FF FF 09 - Response 2 + // AA 55 01 04 00 0A FF 06 FF FF FF FF FF FF FF FF 0C - Power ignore, Dimmer 6% + // AB 55 FD F7 FF FF F5 06 FF FF FF FF FF FF FF FF 0E - Response 2 + // AA 55 01 04 00 0A FF 64 FF FF FF FF FF FF FF FF 6A - Power ignore, Dimmer 100% + // AB 55 FD F7 FF FF F5 64 FF FF FF FF FF FF FF FF 6C - Response 2 + + AddLogSerial(LOG_LEVEL_DEBUG); + uint8_t crc = 0; + for (uint32_t i = 2; i < packet_length -1; i++) { + crc += serial_in_buffer[i]; + } + if (crc == serial_in_buffer[packet_length -1]) { + SonoffD1Received(); + SnfD1.receive_flag = false; + return true; + } + } + serial_in_byte = 0; + } + return false; +} + +/********************************************************************************************/ + +bool SonoffD1SendPower(void) +{ + uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; + + buffer[6] = XdrvMailbox.payload; + + for (uint32_t i = 0; i < sizeof(buffer); i++) { + if ((i > 1) && (i < sizeof(buffer) -1)) { serial_in_buffer[16] += serial_in_buffer[i]; } + Serial.write(serial_in_buffer[i]); + } + return true; +} + +bool SonoffD1SendDimmer(void) +{ + uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; + + buffer[7] = light_state.getDimmer(); + + for (uint32_t i = 0; i < sizeof(buffer); i++) { + if ((i > 1) && (i < sizeof(buffer) -1)) { serial_in_buffer[16] += serial_in_buffer[i]; } + Serial.write(serial_in_buffer[i]); + } + return true; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv39(uint8_t function) +{ + bool result = false; + + if (SONOFF_D1 == my_module_type) { + switch (function) { + case FUNC_SERIAL: + result = SonoffD1SerialInput(); + break; + case FUNC_SET_DEVICE_POWER: + result = SonoffD1SendPower(); + break; + case FUNC_SET_CHANNELS: + result = SonoffD1SendDimmer(); + break; + case FUNC_MODULE_INIT: + SetSerial(9600, TS_SERIAL_8N1); + break; + } + } + return result; +} + +#endif // USE_SONOFF_D1 From 6d79d569565fd1711205cf1aaa52216de6ca2fdc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 28 Feb 2020 18:15:04 +0100 Subject: [PATCH 519/559] Experimental support Sonoff D1 Experimental support Sonoff D1 (#7598) --- tasmota/my_user_config.h | 1 + tasmota/xdrv_39_sonoff_d1.ino | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 5b0282481..8fc58ac4d 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -419,6 +419,7 @@ #define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) //#define USE_KEELOQ // Add support for Jarolift rollers by Keeloq algorithm (+4k5 code) +//#define USE_SONOFF_D1 // Add support for Sonoff D1 // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/xdrv_39_sonoff_d1.ino b/tasmota/xdrv_39_sonoff_d1.ino index c30bea290..9d58f3782 100644 --- a/tasmota/xdrv_39_sonoff_d1.ino +++ b/tasmota/xdrv_39_sonoff_d1.ino @@ -17,8 +17,6 @@ along with this program. If not, see . */ -//#define USE_SONOFF_D1 - #ifdef USE_SONOFF_D1 /*********************************************************************************************\ * Sonoff D1 dimmer 433 From a8585bdba7bf8c8a40a2a21155bb044bf22a1ca9 Mon Sep 17 00:00:00 2001 From: Barbudor Date: Fri, 28 Feb 2020 23:37:35 +0100 Subject: [PATCH 520/559] Use DEBUG_SENSOR macros for debug messages --- tasmota/xsns_13_ina219.ino | 46 ++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/tasmota/xsns_13_ina219.ino b/tasmota/xsns_13_ina219.ino index f5539cf31..854cca5cd 100644 --- a/tasmota/xsns_13_ina219.ino +++ b/tasmota/xsns_13_ina219.ino @@ -97,10 +97,11 @@ uint8_t ina219_type[4] = {0,0,0,0}; uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; -#define __DEBUG__(a) - -__DEBUG__(char __dbg1[20];) -__DEBUG__(char __dbg2[20];) +#ifdef DEBUG_TASMOTA_SENSOR +// temporary strings for floating point in debug messages +char __ina219_dbg1[10]; +char __ina219_dbg2[10]; +#endif // The following multiplier is used to convert shunt voltage (in mV) to current (in A) // Current_A = ShuntVoltage_mV / ShuntResistor_milliOhms = ShuntVoltage_mV * ina219_current_multiplier @@ -132,13 +133,15 @@ bool Ina219SetCalibration(uint8_t mode, uint16_t addr) { uint16_t config = 0; - __DEBUG__(printf("mode = %d\n",mode);) + DEBUG_SENSOR_LOG("Ina219SetCalibration: mode=%d",mode); if (mode < 5) { // All legacy modes 0..2 are handled the same and consider default 0.1 shunt resistor ina219_current_multiplier = 1.0 / INA219_DEFAULT_SHUNT_RESISTOR_MILLIOHMS; - __DEBUG__(dtostrfd(ina219_current_multiplier,5,__dbg1);) - __DEBUG__(printf("cur_mul=%s\n",__dbg1);) + #ifdef DEBUG_TASMOTA_SENSOR + dtostrfd(ina219_current_multiplier,5,__ina219_dbg1); + DEBUG_SENSOR_LOG("Ina219SetCalibration: cur_mul=%s",__ina219_dbg1); + #endif } else if (mode >= 10) { @@ -147,8 +150,10 @@ bool Ina219SetCalibration(uint8_t mode, uint16_t addr) for ( ; mult > 0 ; mult-- ) shunt_milliOhms *= 10; ina219_current_multiplier = 1.0 / shunt_milliOhms; - __DEBUG__(dtostrfd(ina219_current_multiplier,5,__dbg1);) - __DEBUG__(printf("shunt = %dmO => cur_mul=%s\n",shunt_milliOhms,__dbg1);) + #ifdef DEBUG_TASMOTA_SENSOR + dtostrfd(ina219_current_multiplier,5,__ina219_dbg1); + DEBUG_SENSOR_LOG("Ina219SetCalibration: shunt=%dmO => cur_mul=%s",shunt_milliOhms,__ina219_dbg1); + #endif } config = INA219_CONFIG_BVOLTAGERANGE_32V | INA219_CONFIG_GAIN_8_320MV // Use max scale @@ -163,7 +168,7 @@ float Ina219GetShuntVoltage_mV(uint16_t addr) { // raw shunt voltage (16-bit signed integer, so +-32767) int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); - __DEBUG__(printf("ShR = 0x%04X\n",value);) + DEBUG_SENSOR_LOG("Ina219GetShuntVoltage_mV: ShReg = 0x%04X",value); // convert to shunt voltage in mV (so +-327mV) (LSB=10µV=0.01mV) return value * 0.01; } @@ -172,12 +177,12 @@ float Ina219GetBusVoltage_V(uint16_t addr) { // Shift 3 to the right to drop CNVR and OVF as unsigned uint16_t value = I2cRead16(addr, INA219_REG_BUSVOLTAGE) >> 3; - __DEBUG__(printf("BusR = 0x%04X\n",value);) + DEBUG_SENSOR_LOG("Ina219GetBusVoltage_V: BusReg = 0x%04X",value); // and multiply by LSB raw bus voltage to return bus voltage in volts (LSB=4mV=0.004V) return value * 0.004; } -/* +/* Not used any more float Ina219GetCurrent_mA(uint16_t addr) { // Sometimes a sharp load will reset the INA219, which will reset the cal register, @@ -200,16 +205,20 @@ bool Ina219Read(void) uint16_t addr = ina219_addresses[i]; float bus_voltage_V = Ina219GetBusVoltage_V(addr); float shunt_voltage_mV = Ina219GetShuntVoltage_mV(addr); - __DEBUG__(dtostrfd(bus_voltage_V,5,__dbg1);) - __DEBUG__(dtostrfd(shunt_voltage_mV,5,__dbg2);) - __DEBUG__(printf("bV=%sV, sV=%smV\n",__dbg1,__dbg2);) + #ifdef DEBUG_TASMOTA_SENSOR + dtostrfd(bus_voltage_V,5,__ina219_dbg1); + dtostrfd(shunt_voltage_mV,5,__ina219_dbg2); + DEBUG_SENSOR_LOG("Ina219Read: bV=%sV, sV=%smV",__ina219_dbg1,__ina219_dbg2); + #endif // we return the power-supply-side voltage (as bus_voltage register provides the load-side voltage) ina219_voltage[i] = bus_voltage_V + (shunt_voltage_mV / 1000); // current is simply calculted from shunt voltage using pre-calculated multiplier ina219_current[i] = shunt_voltage_mV * ina219_current_multiplier; - __DEBUG__(dtostrfd(ina219_voltage[i],5,__dbg1);) - __DEBUG__(dtostrfd(ina219_current[i],5,__dbg2);) - __DEBUG__(printf("V=%sV, I=%smA\n",__dbg1,__dbg2);) + #ifdef DEBUG_TASMOTA_SENSOR + dtostrfd(ina219_voltage[i],5,__ina219_dbg1); + dtostrfd(ina219_current[i],5,__ina219_dbg2); + DEBUG_SENSOR_LOG("Ina219Read: V=%sV, I=%smA",__ina219_dbg1,__ina219_dbg2); + #endif ina219_valid[i] = SENSOR_MAX_MISS; // AddLogMissed(ina219_types, ina219_valid); } @@ -240,7 +249,6 @@ void Ina219Detect(void) if (I2cActive(addr)) { continue; } if (Ina219SetCalibration(Settings.ina219_mode, addr)) { I2cSetActiveFound(addr, ina219_types); - __DEBUG__(printf("found INA#%d @ 0x%02X\n",i,addr);) ina219_type[i] = 1; ina219_count++; } From c7ac3c833ceaa76f2d486d01b060ffd849cab21b Mon Sep 17 00:00:00 2001 From: Jon Little Date: Thu, 27 Feb 2020 18:28:06 -0600 Subject: [PATCH 521/559] Adding support for MaxBotix HRXL line of sonar ranging sensors --- tasmota/language/bg-BG.h | 1 + tasmota/language/cs-CZ.h | 1 + tasmota/language/de-DE.h | 1 + tasmota/language/el-GR.h | 1 + tasmota/language/en-GB.h | 1 + tasmota/language/es-ES.h | 1 + tasmota/language/fr-FR.h | 1 + tasmota/language/he-HE.h | 1 + tasmota/language/hu-HU.h | 1 + tasmota/language/it-IT.h | 1 + tasmota/language/ko-KO.h | 1 + tasmota/language/nl-NL.h | 1 + tasmota/language/pl-PL.h | 1 + tasmota/language/pt-BR.h | 1 + tasmota/language/pt-PT.h | 1 + tasmota/language/ru-RU.h | 1 + tasmota/language/sk-SK.h | 1 + tasmota/language/sv-SE.h | 1 + tasmota/language/tr-TR.h | 1 + tasmota/language/uk-UA.h | 1 + tasmota/language/zh-CN.h | 1 + tasmota/language/zh-TW.h | 1 + tasmota/tasmota_template.h | 7 ++- tasmota/xsns_64_hrxl.ino | 126 +++++++++++++++++++++++++++++++++++++ 24 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 tasmota/xsns_64_hrxl.ino diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 9a6ce8abc..16bf2f2c0 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index d98361640..5f066e2fc 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 05835a49c..ed8d7b612 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index 0ddd43918..215d42733 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index b175cc193..783c6e343 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 12e732bc2..3b68654c5 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index e9c31da46..15b9b06fb 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index f836a92b9..32e114af9 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index da313caaa..74143fac2 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index efaecc1a5..7297a9b74 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 794b97e84..a32ec4b10 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 288da67d5..f78f63a8b 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index e15ccbbc2..2424fecdb 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 9b24d05c8..f6526e5f1 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 9565fc7a5..5a0903b9d 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 700958875..d1f1a975c 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index dbee001e9..a5d98e87a 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index a8e5aa6a8..403416835 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 430289372..6303befea 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "A" diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index 2b4873e7a..ee335b8e5 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "А" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 5a71e95dc..8c409882e 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 9883972f1..5ca55679a 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -643,6 +643,7 @@ #define D_SENSOR_LE01MR_TX "LE-01MR Tx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" // Units #define D_UNIT_AMPERE "安" diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 5494fbcf3..cdc976bb0 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -224,6 +224,7 @@ enum UserSelectablePins { GPIO_LE01MR_TX, // F&F LE-01MR energy meter GPIO_CC1101_GDO0, // CC1101 pin for RX GPIO_CC1101_GDO2, // CC1101 pin for RX + GPIO_HRXL_RX, // Data from MaxBotix HRXL sonar range sensor GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -308,7 +309,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_DS18X20 "o|" D_SENSOR_DHT11 "o|" D_SENSOR_HM10_RX "|" D_SENSOR_HM10_TX "|" D_SENSOR_LE01MR_RX "|" D_SENSOR_LE01MR_TX "|" - D_SENSOR_CC1101_GDO0 "|" D_SENSOR_CC1101_GDO2 + D_SENSOR_CC1101_GDO0 "|" D_SENSOR_CC1101_GDO2 "|" + D_SENSOR_HRXL_RX ; const char kSensorNamesFixed[] PROGMEM = @@ -797,6 +799,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_CC1101_GDO0, // CC1101 pin for RX GPIO_CC1101_GDO2, // CC1101 pin for RX #endif +#ifdef USE_HRXL + GPIO_HRXL_RX, +#endif }; const uint8_t kModuleNiceList[] PROGMEM = { diff --git a/tasmota/xsns_64_hrxl.ino b/tasmota/xsns_64_hrxl.ino new file mode 100644 index 000000000..a82134c94 --- /dev/null +++ b/tasmota/xsns_64_hrxl.ino @@ -0,0 +1,126 @@ +/* + xsns_64_hrxl.ino - MaxBotix HRXL serial interface + + Copyright (C) 2020 Jon Little + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_HRXL +/*********************************************************************************************\ + * MaxBotix HRXL-MaxSonar ultrasonic range finders + * Source: https://www.maxbotix.com/documents/HRXL-MaxSonar-WR_Datasheet.pdf + * + * Hardware Serial will be selected if GPIO1 = [HRXL Rx] +\*********************************************************************************************/ + +#define XSNS_64 64 + +#include + +#define HRXL_READ_TIMEOUT 400 // us; enough for 6 bytes@9600bps + +TasmotaSerial *HRXLSerial = nullptr; + +uint32_t hrxl_distance_mm = 0; // distance, mm +bool hrxl_found = false; + +/*********************************************************************************************/ + +void HRXLInit(void) +{ + hrxl_found = false; + if ((pin[GPIO_HRXL_RX] < 99)) + { + HRXLSerial = new TasmotaSerial(pin[GPIO_HRXL_RX], -1, 1); + if (HRXLSerial->begin(9600)) + { + if (HRXLSerial->hardwareSerial()) + ClaimSerial(); + hrxl_found = true; + HRXLSerial->setTimeout(HRXL_READ_TIMEOUT); + } + } +} + +void HRXLEverySecond(void) +{ + if (!hrxl_found) + return; + + int num_read=0; + int sum=0; + while (HRXLSerial->available()>5) + { + if (HRXLSerial->read() != 'R') + continue; + + int d = HRXLSerial->parseInt(); + if (d >= 30 && d<=5000) + { + sum += d; + num_read++; + } + } + if (num_read>1) + hrxl_distance_mm = int(sum / num_read); + +} + + +void HRXLShow(bool json) +{ + char types[5] = "HRXL"; + if (json) + { + ResponseAppend_P(PSTR(",\"%s\":{\"" D_DISTANCE "\":%d}"), types, hrxl_distance_mm); +#ifdef USE_WEBSERVER + } + else + { + WSContentSend_PD(HTTP_SNS_RANGE, types, hrxl_distance_mm); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns64(uint8_t function) +{ + if (pin[GPIO_HRXL_RX] >= 99) + return false; + + switch (function) + { + case FUNC_INIT: + HRXLInit(); + break; + case FUNC_EVERY_SECOND: + HRXLEverySecond(); + break; + case FUNC_JSON_APPEND: + HRXLShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + HRXLShow(0); + break; +#endif // USE_WEBSERVER + } + return false; +} + +#endif // USE_HRXL From 4008b9ed3eb65c2f5ae644ef1a93b92835d5240e Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sat, 29 Feb 2020 13:51:16 +0100 Subject: [PATCH 522/559] Change IRremoteESP8266 library updated to v2.7.4 --- .../CPPLINT.cfg | 0 .../LICENSE.txt | 0 .../README.md | 4 +- .../README_fr.md | 4 +- .../ReleaseNotes.md | 20 + .../SupportedProtocols.md | 7 +- .../CommonAcControl/CommonAcControl.ino | 0 .../examples/CommonAcControl/platformio.ini | 0 .../ControlSamsungAC/ControlSamsungAC.ino | 0 .../examples/ControlSamsungAC/platformio.ini | 0 .../DumbIRRepeater/DumbIRRepeater.ino | 0 .../examples/DumbIRRepeater/platformio.ini | 0 .../examples/IRGCSendDemo/IRGCSendDemo.ino | 0 .../examples/IRGCSendDemo/platformio.ini | 0 .../examples/IRGCTCPServer/IRGCTCPServer.ino | 0 .../examples/IRGCTCPServer/platformio.ini | 0 .../examples/IRMQTTServer/IRMQTTServer.h | 2 +- .../examples/IRMQTTServer/IRMQTTServer.ino | 26 +- .../examples/IRMQTTServer/platformio.ini | 0 .../examples/IRServer/IRServer.ino | 0 .../examples/IRServer/platformio.ini | 0 .../examples/IRrecvDemo/IRrecvDemo.ino | 0 .../examples/IRrecvDemo/platformio.ini | 0 .../examples/IRrecvDump/IRrecvDump.ino | 0 .../examples/IRrecvDump/platformio.ini | 0 .../examples/IRrecvDumpV2/IRrecvDumpV2.ino | 2 +- .../examples/IRrecvDumpV2/platformio.ini | 0 .../examples/IRsendDemo/IRsendDemo.ino | 0 .../examples/IRsendDemo/platformio.ini | 0 .../IRsendProntoDemo/IRsendProntoDemo.ino | 0 .../examples/IRsendProntoDemo/platformio.ini | 0 .../JVCPanasonicSendDemo.ino | 0 .../JVCPanasonicSendDemo/platformio.ini | 0 .../examples/LGACSend/LGACSend.ino | 0 .../examples/LGACSend/platformio.ini | 0 .../SmartIRRepeater/SmartIRRepeater.ino | 0 .../examples/SmartIRRepeater/platformio.ini | 0 .../examples/TurnOnArgoAC/TurnOnArgoAC.ino | 0 .../examples/TurnOnArgoAC/platformio.ini | 0 .../TurnOnDaikinAC/TurnOnDaikinAC.ino | 0 .../examples/TurnOnDaikinAC/platformio.ini | 0 .../TurnOnFujitsuAC/TurnOnFujitsuAC.ino | 0 .../examples/TurnOnFujitsuAC/platformio.ini | 0 .../TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino | 0 .../TurnOnKelvinatorAC/platformio.ini | 0 .../TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino | 0 .../TurnOnMitsubishiAC/platformio.ini | 0 .../TurnOnMitsubishiHeavyAc.ino | 0 .../TurnOnMitsubishiHeavyAc/platformio.ini | 0 .../TurnOnPanasonicAC/TurnOnPanasonicAC.ino | 0 .../examples/TurnOnPanasonicAC/platformio.ini | 0 .../TurnOnToshibaAC/TurnOnToshibaAC.ino | 0 .../examples/TurnOnToshibaAC/platformio.ini | 0 .../TurnOnTrotecAC/TurnOnTrotecAC.ino | 0 .../examples/TurnOnTrotecAC/platformio.ini | 0 .../examples/Web-AC-control/README.md | 0 .../Web-AC-control/Web-AC-control.ino | 0 .../examples/Web-AC-control/platformio.ini | 0 .../examples/Web-AC-control/printscreen.png | Bin .../Web-AC-control/upload/favicon.ico | Bin .../Web-AC-control/upload/level_1_off.svg | 0 .../Web-AC-control/upload/level_1_on.svg | 0 .../Web-AC-control/upload/level_2_off.svg | 0 .../Web-AC-control/upload/level_2_on.svg | 0 .../Web-AC-control/upload/level_3_off.svg | 0 .../Web-AC-control/upload/level_3_on.svg | 0 .../Web-AC-control/upload/level_4_off.svg | 0 .../Web-AC-control/upload/level_4_on.svg | 0 .../examples/Web-AC-control/upload/ui.html | 0 .../examples/Web-AC-control/upload/ui.js | 0 .../keywords.txt | 19 + .../library.json | 2 +- .../library.properties | 4 +- .../pylintrc | 0 .../src/CPPLINT.cfg | 0 .../src/IRac.cpp | 33 +- .../src/IRac.h | 7 +- .../src/IRrecv.cpp | 455 +++++++++++------- .../src/IRrecv.h | 237 +++++---- .../src/IRremoteESP8266.h | 30 +- .../src/IRsend.cpp | 11 +- .../src/IRsend.h | 7 +- .../src/IRtext.cpp | 0 .../src/IRtext.h | 0 .../src/IRtimer.cpp | 0 .../src/IRtimer.h | 0 .../src/IRutils.cpp | 5 + .../src/IRutils.h | 0 .../src/i18n.h | 0 .../src/ir_Aiwa.cpp | 8 +- .../src/ir_Amcor.cpp | 10 +- .../src/ir_Amcor.h | 0 .../src/ir_Argo.cpp | 7 +- .../src/ir_Argo.h | 0 .../src/ir_Carrier.cpp | 9 +- .../src/ir_Coolix.cpp | 10 +- .../src/ir_Coolix.h | 0 .../src/ir_Daikin.cpp | 64 +-- .../src/ir_Daikin.h | 0 .../src/ir_Denon.cpp | 11 +- .../src/ir_Dish.cpp | 8 +- .../src/ir_Electra.cpp | 45 +- .../src/ir_Electra.h | 23 +- lib/IRremoteESP8266-2.7.4/src/ir_Epson.cpp | 114 +++++ .../src/ir_Fujitsu.cpp | 13 +- .../src/ir_Fujitsu.h | 0 .../src/ir_GICable.cpp | 7 +- .../src/ir_GlobalCache.cpp | 0 .../src/ir_Goodweather.cpp | 7 +- .../src/ir_Goodweather.h | 0 .../src/ir_Gree.cpp | 13 +- .../src/ir_Gree.h | 0 .../src/ir_Haier.cpp | 18 +- .../src/ir_Haier.h | 0 .../src/ir_Hitachi.cpp | 20 +- .../src/ir_Hitachi.h | 0 .../src/ir_Inax.cpp | 7 +- .../src/ir_JVC.cpp | 8 +- .../src/ir_Kelvinator.cpp | 13 +- .../src/ir_Kelvinator.h | 0 .../src/ir_LG.cpp | 14 +- .../src/ir_LG.h | 0 .../src/ir_Lasertag.cpp | 9 +- .../src/ir_Lego.cpp | 8 +- .../src/ir_Lutron.cpp | 9 +- .../src/ir_MWM.cpp | 8 +- .../src/ir_Magiquest.cpp | 11 +- .../src/ir_Magiquest.h | 0 .../src/ir_Midea.cpp | 10 +- .../src/ir_Midea.h | 0 .../src/ir_Mitsubishi.cpp | 51 +- .../src/ir_Mitsubishi.h | 0 .../src/ir_MitsubishiHeavy.cpp | 9 +- .../src/ir_MitsubishiHeavy.h | 0 .../src/ir_NEC.cpp | 18 +- .../src/ir_NEC.h | 0 .../src/ir_Neoclima.cpp | 7 +- .../src/ir_Neoclima.h | 0 .../src/ir_Nikai.cpp | 6 +- .../src/ir_Panasonic.cpp | 20 +- .../src/ir_Panasonic.h | 0 .../src/ir_Pioneer.cpp | 9 +- .../src/ir_Pronto.cpp | 0 .../src/ir_RC5_RC6.cpp | 20 +- .../src/ir_RCMM.cpp | 8 +- .../src/ir_Samsung.cpp | 52 +- .../src/ir_Samsung.h | 10 + .../src/ir_Sanyo.cpp | 10 +- .../src/ir_Sharp.cpp | 24 +- .../src/ir_Sharp.h | 0 .../src/ir_Sherwood.cpp | 0 .../src/ir_Sony.cpp | 8 +- .../src/ir_Tcl.cpp | 0 .../src/ir_Tcl.h | 0 .../src/ir_Teco.cpp | 5 +- .../src/ir_Teco.h | 0 .../src/ir_Toshiba.cpp | 8 +- .../src/ir_Toshiba.h | 0 .../src/ir_Trotec.cpp | 9 +- .../src/ir_Trotec.h | 0 .../src/ir_Vestel.cpp | 7 +- .../src/ir_Vestel.h | 0 .../src/ir_Whirlpool.cpp | 11 +- .../src/ir_Whirlpool.h | 0 .../src/ir_Whynter.cpp | 9 +- .../src/locale/README.md | 0 .../src/locale/de-CH.h | 0 .../src/locale/de-DE.h | 0 .../src/locale/defaults.h | 0 .../src/locale/en-AU.h | 0 .../src/locale/en-IE.h | 0 .../src/locale/en-UK.h | 0 .../src/locale/en-US.h | 0 .../src/locale/es-ES.h | 0 .../src/locale/fr-FR.h | 0 lib/IRremoteESP8266-2.7.4/src/locale/it-IT.h | 157 ++++++ .../test/IRac_test.cpp | 92 +++- .../test/IRrecv_test.cpp | 347 ++++++++++++- .../test/IRrecv_test.h | 0 .../test/IRsend_test.cpp | 2 +- .../test/IRsend_test.h | 0 .../test/IRutils_test.cpp | 0 .../test/Makefile | 13 +- .../test/ir_Aiwa_test.cpp | 55 ++- .../test/ir_Amcor_test.cpp | 0 .../test/ir_Argo_test.cpp | 0 .../test/ir_Carrier_test.cpp | 6 +- .../test/ir_Coolix_test.cpp | 78 ++- .../test/ir_Daikin_test.cpp | 36 ++ .../test/ir_Denon_test.cpp | 24 +- .../test/ir_Dish_test.cpp | 27 +- .../test/ir_Electra_test.cpp | 121 ++++- .../test/ir_Epson_test.cpp | 159 ++++++ .../test/ir_Fujitsu_test.cpp | 0 .../test/ir_GICable_test.cpp | 0 .../test/ir_GlobalCache_test.cpp | 0 .../test/ir_Goodweather_test.cpp | 0 .../test/ir_Gree_test.cpp | 0 .../test/ir_Haier_test.cpp | 3 +- .../test/ir_Hitachi_test.cpp | 0 .../test/ir_Inax_test.cpp | 0 .../test/ir_JVC_test.cpp | 34 +- .../test/ir_Kelvinator_test.cpp | 0 .../test/ir_LG_test.cpp | 60 +-- .../test/ir_Lasertag_test.cpp | 0 .../test/ir_Lego_test.cpp | 0 .../test/ir_Lutron_test.cpp | 0 .../test/ir_MWM_test.cpp | 0 .../test/ir_Magiquest_test.cpp | 9 +- .../test/ir_Midea_test.cpp | 40 +- .../test/ir_MitsubishiHeavy_test.cpp | 0 .../test/ir_Mitsubishi_test.cpp | 56 ++- .../test/ir_NEC_test.cpp | 18 +- .../test/ir_Neoclima_test.cpp | 0 .../test/ir_Nikai_test.cpp | 27 +- .../test/ir_Panasonic_test.cpp | 57 ++- .../test/ir_Pioneer_test.cpp | 0 .../test/ir_Pronto_test.cpp | 25 + .../test/ir_RC5_RC6_test.cpp | 101 ++-- .../test/ir_RCMM_test.cpp | 30 +- .../test/ir_Samsung_test.cpp | 114 +++-- .../test/ir_Sanyo_test.cpp | 47 +- .../test/ir_Sharp_test.cpp | 35 +- .../test/ir_Sherwood_test.cpp | 0 .../test/ir_Sony_test.cpp | 73 ++- .../test/ir_Tcl_test.cpp | 0 .../test/ir_Teco_test.cpp | 3 +- .../test/ir_Toshiba_test.cpp | 0 .../test/ir_Trotec_test.cpp | 0 .../test/ir_Vestel_test.cpp | 3 +- .../test/ir_Whirlpool_test.cpp | 0 .../test/ir_Whynter_test.cpp | 19 +- .../tools/Makefile | 5 +- .../tools/RawToGlobalCache.sh | 0 .../tools/auto_analyse_raw_data.py | 0 .../tools/auto_analyse_raw_data_test.py | 0 .../tools/gc_decode.cpp | 27 +- .../tools/generate_irtext_h.sh | 0 .../tools/mkkeywords | 0 .../tools/mode2_decode.cpp | 0 .../tools/scrape_supported_devices.py | 0 tasmota/CHANGELOG.md | 1 + 242 files changed, 2623 insertions(+), 941 deletions(-) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/LICENSE.txt (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/README.md (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/README_fr.md (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/ReleaseNotes.md (96%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/SupportedProtocols.md (95%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/CommonAcControl/CommonAcControl.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/CommonAcControl/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/ControlSamsungAC/ControlSamsungAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/ControlSamsungAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/DumbIRRepeater/DumbIRRepeater.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/DumbIRRepeater/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRGCSendDemo/IRGCSendDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRGCSendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRGCTCPServer/IRGCTCPServer.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRGCTCPServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRMQTTServer/IRMQTTServer.h (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRMQTTServer/IRMQTTServer.ino (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRMQTTServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRServer/IRServer.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRServer/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRrecvDemo/IRrecvDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRrecvDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRrecvDump/IRrecvDump.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRrecvDump/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRrecvDumpV2/IRrecvDumpV2.ino (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRrecvDumpV2/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRsendDemo/IRsendDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRsendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRsendProntoDemo/IRsendProntoDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/IRsendProntoDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/JVCPanasonicSendDemo/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/LGACSend/LGACSend.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/LGACSend/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/SmartIRRepeater/SmartIRRepeater.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/SmartIRRepeater/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnArgoAC/TurnOnArgoAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnArgoAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnDaikinAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnFujitsuAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnKelvinatorAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnMitsubishiAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnMitsubishiHeavyAc/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnPanasonicAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnToshibaAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/TurnOnTrotecAC/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/README.md (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/Web-AC-control.ino (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/platformio.ini (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/printscreen.png (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/favicon.ico (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/level_1_off.svg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/level_1_on.svg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/level_2_off.svg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/level_2_on.svg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/level_3_off.svg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/level_3_on.svg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/level_4_off.svg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/level_4_on.svg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/ui.html (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/examples/Web-AC-control/upload/ui.js (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/keywords.txt (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/library.json (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/library.properties (83%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/pylintrc (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/CPPLINT.cfg (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRac.cpp (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRac.h (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRrecv.cpp (72%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRrecv.h (63%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRremoteESP8266.h (96%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRsend.cpp (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRsend.h (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRtext.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRtext.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRtimer.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRtimer.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRutils.cpp (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/IRutils.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/i18n.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Aiwa.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Amcor.cpp (96%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Amcor.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Argo.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Argo.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Carrier.cpp (92%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Coolix.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Coolix.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Daikin.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Daikin.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Denon.cpp (89%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Dish.cpp (93%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Electra.cpp (88%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Electra.h (81%) create mode 100644 lib/IRremoteESP8266-2.7.4/src/ir_Epson.cpp rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Fujitsu.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Fujitsu.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_GICable.cpp (92%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_GlobalCache.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Goodweather.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Goodweather.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Gree.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Gree.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Haier.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Haier.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Hitachi.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Hitachi.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Inax.cpp (90%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_JVC.cpp (93%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Kelvinator.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Kelvinator.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_LG.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_LG.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Lasertag.cpp (90%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Lego.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Lutron.cpp (93%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_MWM.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Magiquest.cpp (92%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Magiquest.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Midea.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Midea.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Mitsubishi.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Mitsubishi.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_MitsubishiHeavy.cpp (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_MitsubishiHeavy.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_NEC.cpp (89%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_NEC.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Neoclima.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Neoclima.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Nikai.cpp (90%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Panasonic.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Panasonic.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Pioneer.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Pronto.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_RC5_RC6.cpp (95%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_RCMM.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Samsung.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Samsung.h (93%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Sanyo.cpp (96%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Sharp.cpp (96%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Sharp.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Sherwood.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Sony.cpp (95%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Tcl.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Tcl.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Teco.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Teco.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Toshiba.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Toshiba.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Trotec.cpp (96%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Trotec.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Vestel.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Vestel.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Whirlpool.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Whirlpool.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/ir_Whynter.cpp (91%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/README.md (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/de-CH.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/de-DE.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/defaults.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/en-AU.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/en-IE.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/en-UK.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/en-US.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/es-ES.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/src/locale/fr-FR.h (100%) create mode 100644 lib/IRremoteESP8266-2.7.4/src/locale/it-IT.h rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/IRac_test.cpp (95%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/IRrecv_test.cpp (74%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/IRrecv_test.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/IRsend_test.cpp (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/IRsend_test.h (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/IRutils_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/Makefile (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Aiwa_test.cpp (83%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Amcor_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Argo_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Carrier_test.cpp (97%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Coolix_test.cpp (91%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Daikin_test.cpp (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Denon_test.cpp (92%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Dish_test.cpp (92%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Electra_test.cpp (69%) create mode 100644 lib/IRremoteESP8266-2.7.4/test/ir_Epson_test.cpp rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Fujitsu_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_GICable_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_GlobalCache_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Goodweather_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Gree_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Haier_test.cpp (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Hitachi_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Inax_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_JVC_test.cpp (88%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Kelvinator_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_LG_test.cpp (92%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Lasertag_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Lego_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Lutron_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_MWM_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Magiquest_test.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Midea_test.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_MitsubishiHeavy_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Mitsubishi_test.cpp (96%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_NEC_test.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Neoclima_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Nikai_test.cpp (87%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Panasonic_test.cpp (95%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Pioneer_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Pronto_test.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_RC5_RC6_test.cpp (88%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_RCMM_test.cpp (86%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Samsung_test.cpp (93%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Sanyo_test.cpp (81%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Sharp_test.cpp (94%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Sherwood_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Sony_test.cpp (88%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Tcl_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Teco_test.cpp (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Toshiba_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Trotec_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Vestel_test.cpp (99%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Whirlpool_test.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/test/ir_Whynter_test.cpp (92%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/Makefile (98%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/RawToGlobalCache.sh (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/auto_analyse_raw_data.py (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/auto_analyse_raw_data_test.py (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/gc_decode.cpp (84%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/generate_irtext_h.sh (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/mkkeywords (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/mode2_decode.cpp (100%) rename lib/{IRremoteESP8266-2.7.3 => IRremoteESP8266-2.7.4}/tools/scrape_supported_devices.py (100%) diff --git a/lib/IRremoteESP8266-2.7.3/CPPLINT.cfg b/lib/IRremoteESP8266-2.7.4/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/CPPLINT.cfg rename to lib/IRremoteESP8266-2.7.4/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.7.3/LICENSE.txt b/lib/IRremoteESP8266-2.7.4/LICENSE.txt similarity index 100% rename from lib/IRremoteESP8266-2.7.3/LICENSE.txt rename to lib/IRremoteESP8266-2.7.4/LICENSE.txt diff --git a/lib/IRremoteESP8266-2.7.3/README.md b/lib/IRremoteESP8266-2.7.4/README.md similarity index 98% rename from lib/IRremoteESP8266-2.7.3/README.md rename to lib/IRremoteESP8266-2.7.4/README.md index 9ca606af8..093b15cc1 100644 --- a/lib/IRremoteESP8266-2.7.3/README.md +++ b/lib/IRremoteESP8266-2.7.4/README.md @@ -9,8 +9,8 @@ This library enables you to **send _and_ receive** infra-red signals on an [ESP8266](https://github.com/esp8266/Arduino) or an [ESP32](https://github.com/espressif/arduino-esp32) using the [Arduino framework](https://www.arduino.cc/) using common 940nm IR LEDs and common IR receiver modules. e.g. TSOP{17,22,24,36,38,44,48}* demodulators etc. -## v2.7.3 Now Available -Version 2.7.3 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. +## v2.7.4 Now Available +Version 2.7.4 of the library is now [available](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). You can view the [Release Notes](ReleaseNotes.md) for all the significant changes. #### Upgrading from pre-v2.0 Usage of the library has been slightly changed in v2.0. You will need to change your usage to work with v2.0 and beyond. You can read more about the changes required on our [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/IRremoteESP8266-2.7.3/README_fr.md b/lib/IRremoteESP8266-2.7.4/README_fr.md similarity index 98% rename from lib/IRremoteESP8266-2.7.3/README_fr.md rename to lib/IRremoteESP8266-2.7.4/README_fr.md index ca31b3b7b..f95bcc945 100644 --- a/lib/IRremoteESP8266-2.7.3/README_fr.md +++ b/lib/IRremoteESP8266-2.7.4/README_fr.md @@ -9,8 +9,8 @@ Cette librairie vous permetra de **recevoir et d'envoyer des signaux** infrarouge sur le protocole [ESP8266](https://github.com/esp8266/Arduino) ou sur le protocole [ESP32](https://github.com/espressif/arduino-esp32) en utilisant le [Arduino framework](https://www.arduino.cc/) qui utilise la norme 940nm IR LEDs et le module basique de reception d'onde IR. Exemple : TSOP{17,22,24,36,38,44,48}* modules etc. -## v2.7.3 disponible -Version 2.7.3 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. +## v2.7.4 disponible +Version 2.7.4 de la libraire est maintenant [disponible](https://github.com/crankyoldgit/IRremoteESP8266/releases/latest). Vous pouvez voir le [Release Notes](ReleaseNotes.md) pour tous les changements importants. #### mise à jour depuis pre-v2.0 L'utilisation de la librairie à un peu changer depuis la version in v2.0. Si vous voulez l'utiliser vous devrez changer votre utilisation aussi. Vous pouvez vous renseigner sur les précondition d'utilisation ici : [Upgrade to v2.0](https://github.com/crankyoldgit/IRremoteESP8266/wiki/Upgrading-to-v2.0) page. diff --git a/lib/IRremoteESP8266-2.7.3/ReleaseNotes.md b/lib/IRremoteESP8266-2.7.4/ReleaseNotes.md similarity index 96% rename from lib/IRremoteESP8266-2.7.3/ReleaseNotes.md rename to lib/IRremoteESP8266-2.7.4/ReleaseNotes.md index a7218fc07..4c6b1a967 100644 --- a/lib/IRremoteESP8266-2.7.3/ReleaseNotes.md +++ b/lib/IRremoteESP8266-2.7.4/ReleaseNotes.md @@ -1,5 +1,25 @@ # Release Notes +## _v2.7.4 (20200226)_ + +**[Bug Fixes]** +- IRMQTTServer: Fix bug when receiving an IR A/C message and not re-transmitting it. (#1035, #1038) +- Coolix: `setRaw()` doesn't update power state. (#1040, #1041) + +**[Features]** +- Electra: Add improved feature support. (#1033, #1051) +- Add support for Epson protocol. (#1034, #1050) +- Add options to `decode()` to aid detection. Improve NEC detection. (#1042, #1046) +- SamsungAc: Add support for Light & Ion (VirusDoctor). (#1045, #1048, #1049) +- Add Italian (it-IT) locale/language support. (#1047) (kudos @egueli) +- gc_decode: Add repeat support for pronto codes. (#1034, #1043) + +**[Misc]** +- Update supported SamsungAc devices (#1045) +- Coolix: Subtle protocol timing adjustments (#1036, #1037) +- Add supported Electra device model info (#1033) + + ## _v2.7.3 (20200130)_ **[Features]** diff --git a/lib/IRremoteESP8266-2.7.3/SupportedProtocols.md b/lib/IRremoteESP8266-2.7.4/SupportedProtocols.md similarity index 95% rename from lib/IRremoteESP8266-2.7.3/SupportedProtocols.md rename to lib/IRremoteESP8266-2.7.4/SupportedProtocols.md index c9b2f85c7..04661c3bb 100644 --- a/lib/IRremoteESP8266-2.7.3/SupportedProtocols.md +++ b/lib/IRremoteESP8266-2.7.4/SupportedProtocols.md @@ -1,6 +1,6 @@ + Last generated: Wed Feb 26 16:31:08 2020 ---> # IR Protocols supported by this library | Protocol | Brand | Model | A/C Model | Detailed A/C Support | @@ -16,6 +16,8 @@ | [Denon](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Denon.cpp) | **Unknown** | | | - | | [Dish](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Dish.cpp) | **DISH NETWORK** | echostar 301 | | - | | [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[AUX](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | KFR-35GW/BpNFW=3 A/C
YKR-T/011 remote | | Yes | +| [Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.cpp) | **[Electra](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Electra.h)** | Classic INV 17 / AXW12DCS A/C
YKR-M/003E remote | | Yes | +| [Epson](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Epson.cpp) | **Unknown** | | | - | | [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AGTV14LAC A/C
AR-DB1 remote
AR-DL10 remote
AR-RAC1E remote
AR-RAE1E remote
AR-RAH2E remote
AR-REB1E remote
AR-RY4 remote
AST9RSGCW A/C
ASTB09LBC A/C
ASU30C1 A/C
ASYG30LFCA A/C
ASYG7LMCA A/C | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARRY4 | Yes | | [Fujitsu](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.cpp) | **[Fujitsu General](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Fujitsu.h)** | AR-JW2 remote | ARDB1
ARJW2
ARRAH2E
ARREB1E
ARRY4 | Yes | | [GICable](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_GICable.cpp) | **Unknown** | | | - | @@ -54,7 +56,7 @@ | [Pronto](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Pronto.cpp) | **Unknown** | | | - | | [RC5_RC6](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp) | **Unknown** | | | - | | [RCMM](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_RCMM.cpp) | **Microsoft** | XBOX 360 | | - | -| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AR12HSSDBWKNEU A/C
AR12KSFPEWQNET A/C
IEC-R03 remote
UA55H6300 TV | | Yes | +| [Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.cpp) | **[Samsung](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Samsung.h)** | AR09FSSDAWKNFA A/C
AR12HSSDBWKNEU A/C
AR12KSFPEWQNET A/C
DB63-03556X003 remote
IEC-R03 remote
UA55H6300 TV | | Yes | | [Sanyo](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sanyo.cpp) | **Unknown** | | | - | | [Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.cpp) | **[Sharp](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sharp.h)** | AY-ZP40KR A/C
LC-52D62U TV | | Yes | | [Sherwood](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_Sherwood.cpp) | **Sherwood** | RC-138 remote
RD6505(B) Receiver | | - | @@ -94,6 +96,7 @@ - DENON - DISH - ELECTRA_AC +- EPSON - FUJITSU_AC - GICABLE - GOODWEATHER diff --git a/lib/IRremoteESP8266-2.7.3/examples/CommonAcControl/CommonAcControl.ino b/lib/IRremoteESP8266-2.7.4/examples/CommonAcControl/CommonAcControl.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/CommonAcControl/CommonAcControl.ino rename to lib/IRremoteESP8266-2.7.4/examples/CommonAcControl/CommonAcControl.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/CommonAcControl/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/CommonAcControl/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/CommonAcControl/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/CommonAcControl/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/ControlSamsungAC/ControlSamsungAC.ino b/lib/IRremoteESP8266-2.7.4/examples/ControlSamsungAC/ControlSamsungAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/ControlSamsungAC/ControlSamsungAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/ControlSamsungAC/ControlSamsungAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/ControlSamsungAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/ControlSamsungAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/ControlSamsungAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/ControlSamsungAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/DumbIRRepeater.ino b/lib/IRremoteESP8266-2.7.4/examples/DumbIRRepeater/DumbIRRepeater.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/DumbIRRepeater.ino rename to lib/IRremoteESP8266-2.7.4/examples/DumbIRRepeater/DumbIRRepeater.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/DumbIRRepeater/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/DumbIRRepeater/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/DumbIRRepeater/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRGCSendDemo/IRGCSendDemo.ino b/lib/IRremoteESP8266-2.7.4/examples/IRGCSendDemo/IRGCSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRGCSendDemo/IRGCSendDemo.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRGCSendDemo/IRGCSendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRGCSendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRGCSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRGCSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRGCSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRGCTCPServer/IRGCTCPServer.ino b/lib/IRremoteESP8266-2.7.4/examples/IRGCTCPServer/IRGCTCPServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRGCTCPServer/IRGCTCPServer.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRGCTCPServer/IRGCTCPServer.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRGCTCPServer/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRGCTCPServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRGCTCPServer/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRGCTCPServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.h b/lib/IRremoteESP8266-2.7.4/examples/IRMQTTServer/IRMQTTServer.h similarity index 99% rename from lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.h rename to lib/IRremoteESP8266-2.7.4/examples/IRMQTTServer/IRMQTTServer.h index 0693a4908..b363d98b9 100644 --- a/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.h +++ b/lib/IRremoteESP8266-2.7.4/examples/IRMQTTServer/IRMQTTServer.h @@ -239,7 +239,7 @@ const uint16_t kJsonAcStateMaxSize = 1024; // Bytes // ----------------- End of User Configuration Section ------------------------- // Constants -#define _MY_VERSION_ "v1.4.5" +#define _MY_VERSION_ "v1.4.6" const uint8_t kRebootTime = 15; // Seconds const uint8_t kQuickDisplayTime = 2; // Seconds diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.ino b/lib/IRremoteESP8266-2.7.4/examples/IRMQTTServer/IRMQTTServer.ino similarity index 99% rename from lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRMQTTServer/IRMQTTServer.ino index 1824c660a..efcf25431 100644 --- a/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/IRMQTTServer.ino +++ b/lib/IRremoteESP8266-2.7.4/examples/IRMQTTServer/IRMQTTServer.ino @@ -2679,7 +2679,7 @@ uint64_t getUInt64fromHex(char const *str) { // code: Numeric payload of the IR message. Most protocols use this. // code_str: The unparsed code to be sent. Used by complex protocol encodings. // bits: Nr. of bits in the protocol. 0 means use the protocol's default. -// repeat: Nr. of times the message is to be repeated. (Not all protcols.) +// repeat: Nr. of times the message is to be repeated. (Not all protocols.) // Returns: // bool: Successfully sent or not. bool sendIRCode(IRsend *irsend, decode_type_t const ir_type, @@ -3071,6 +3071,10 @@ bool sendClimate(const String topic_prefix, const bool retain, lastClimateIr.reset(); irClimateCounter++; } + // Mark the "next" value as old/previous. + if (ac != NULL) { + ac->markAsSent(); + } return success; } @@ -3098,20 +3102,20 @@ bool decodeCommonAc(const decode_results *decode) { } #if IGNORE_DECODED_AC_PROTOCOL if (climate[0]->next.protocol != decode_type_t::UNKNOWN) { - // Use the previous protcol/model if set. + // Use the previous protocol/model if set. state.protocol = climate[0]->next.protocol; state.model = climate[0]->next.model; } #endif // IGNORE_DECODED_AC_PROTOCOL -// Continue to use the previously prefered temperature units. -// i.e. Keep using Celsius or Fahrenheit. -if (climate[0]->next.celsius != state.celsius) { - // We've got a mismatch, so we need to convert. - state.degrees = climate[0]->next.celsius ? fahrenheitToCelsius(state.degrees) - : celsiusToFahrenheit(state.degrees); - state.celsius = climate[0]->next.celsius; -} -climate[0]->next = state; // Copy over the new climate state. + // Continue to use the previously prefered temperature units. + // i.e. Keep using Celsius or Fahrenheit. + if (climate[0]->next.celsius != state.celsius) { + // We've got a mismatch, so we need to convert. + state.degrees = climate[0]->next.celsius ? + fahrenheitToCelsius(state.degrees) : celsiusToFahrenheit(state.degrees); + state.celsius = climate[0]->next.celsius; + } + climate[0]->next = state; // Copy over the new climate state. #if MQTT_ENABLE sendClimate(genStatTopic(0), true, false, REPLAY_DECODED_AC_MESSAGE, REPLAY_DECODED_AC_MESSAGE, climate[0]); diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRMQTTServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRMQTTServer/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRMQTTServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRServer/IRServer.ino b/lib/IRremoteESP8266-2.7.4/examples/IRServer/IRServer.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRServer/IRServer.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRServer/IRServer.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRServer/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRServer/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRServer/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRServer/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/IRrecvDemo.ino b/lib/IRremoteESP8266-2.7.4/examples/IRrecvDemo/IRrecvDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/IRrecvDemo.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRrecvDemo/IRrecvDemo.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRrecvDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRrecvDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRrecvDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRrecvDump/IRrecvDump.ino b/lib/IRremoteESP8266-2.7.4/examples/IRrecvDump/IRrecvDump.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRrecvDump/IRrecvDump.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRrecvDump/IRrecvDump.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRrecvDump/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRrecvDump/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRrecvDump/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRrecvDump/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/lib/IRremoteESP8266-2.7.4/examples/IRrecvDumpV2/IRrecvDumpV2.ino similarity index 99% rename from lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/IRrecvDumpV2.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRrecvDumpV2/IRrecvDumpV2.ino index beed6c746..8ea98b687 100644 --- a/lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ b/lib/IRremoteESP8266-2.7.4/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -17,7 +17,7 @@ * Version 0.4 July, 2018 * - Minor improvements and more A/C unit support. * Version 0.3 November, 2017 - * - Support for A/C decoding for some protcols. + * - Support for A/C decoding for some protocols. * Version 0.2 April, 2017 * - Decode from a copy of the data so we can start capturing faster thus * reduce the likelihood of miscaptures. diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRrecvDumpV2/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRrecvDumpV2/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRrecvDumpV2/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRsendDemo/IRsendDemo.ino b/lib/IRremoteESP8266-2.7.4/examples/IRsendDemo/IRsendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRsendDemo/IRsendDemo.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRsendDemo/IRsendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRsendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRsendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRsendDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRsendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRsendProntoDemo/IRsendProntoDemo.ino b/lib/IRremoteESP8266-2.7.4/examples/IRsendProntoDemo/IRsendProntoDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRsendProntoDemo/IRsendProntoDemo.ino rename to lib/IRremoteESP8266-2.7.4/examples/IRsendProntoDemo/IRsendProntoDemo.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/IRsendProntoDemo/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/IRsendProntoDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/IRsendProntoDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/IRsendProntoDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino b/lib/IRremoteESP8266-2.7.4/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino rename to lib/IRremoteESP8266-2.7.4/examples/JVCPanasonicSendDemo/JVCPanasonicSendDemo.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/JVCPanasonicSendDemo/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/JVCPanasonicSendDemo/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/JVCPanasonicSendDemo/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/JVCPanasonicSendDemo/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/LGACSend/LGACSend.ino b/lib/IRremoteESP8266-2.7.4/examples/LGACSend/LGACSend.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/LGACSend/LGACSend.ino rename to lib/IRremoteESP8266-2.7.4/examples/LGACSend/LGACSend.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/LGACSend/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/LGACSend/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/LGACSend/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/LGACSend/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/SmartIRRepeater.ino b/lib/IRremoteESP8266-2.7.4/examples/SmartIRRepeater/SmartIRRepeater.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/SmartIRRepeater.ino rename to lib/IRremoteESP8266-2.7.4/examples/SmartIRRepeater/SmartIRRepeater.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/SmartIRRepeater/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/SmartIRRepeater/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/SmartIRRepeater/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnArgoAC/TurnOnArgoAC.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnArgoAC/TurnOnArgoAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnArgoAC/TurnOnArgoAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnArgoAC/TurnOnArgoAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnArgoAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnArgoAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnArgoAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnArgoAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnDaikinAC/TurnOnDaikinAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnDaikinAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnDaikinAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnDaikinAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnDaikinAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnFujitsuAC/TurnOnFujitsuAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnFujitsuAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnFujitsuAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnFujitsuAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnFujitsuAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnKelvinatorAC/TurnOnKelvinatorAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnKelvinatorAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnKelvinatorAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnKelvinatorAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnKelvinatorAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnMitsubishiAC/TurnOnMitsubishiAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnMitsubishiAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnMitsubishiAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnMitsubishiHeavyAc/TurnOnMitsubishiHeavyAc.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiHeavyAc/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnMitsubishiHeavyAc/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnMitsubishiHeavyAc/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnMitsubishiHeavyAc/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnPanasonicAC/TurnOnPanasonicAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnPanasonicAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnPanasonicAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnPanasonicAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnPanasonicAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnToshibaAC/TurnOnToshibaAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnToshibaAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnToshibaAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnToshibaAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnToshibaAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino b/lib/IRremoteESP8266-2.7.4/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnTrotecAC/TurnOnTrotecAC.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/TurnOnTrotecAC/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/TurnOnTrotecAC/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/TurnOnTrotecAC/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/TurnOnTrotecAC/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/README.md b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/README.md similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/README.md rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/README.md diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/Web-AC-control.ino b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/Web-AC-control.ino similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/Web-AC-control.ino rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/Web-AC-control.ino diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/platformio.ini b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/platformio.ini similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/platformio.ini rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/platformio.ini diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/printscreen.png b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/printscreen.png similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/printscreen.png rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/printscreen.png diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/favicon.ico b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/favicon.ico similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/favicon.ico rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/favicon.ico diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_1_off.svg b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_1_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_1_off.svg rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_1_off.svg diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_1_on.svg b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_1_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_1_on.svg rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_1_on.svg diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_2_off.svg b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_2_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_2_off.svg rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_2_off.svg diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_2_on.svg b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_2_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_2_on.svg rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_2_on.svg diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_3_off.svg b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_3_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_3_off.svg rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_3_off.svg diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_3_on.svg b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_3_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_3_on.svg rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_3_on.svg diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_4_off.svg b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_4_off.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_4_off.svg rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_4_off.svg diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_4_on.svg b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_4_on.svg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/level_4_on.svg rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/level_4_on.svg diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/ui.html b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/ui.html similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/ui.html rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/ui.html diff --git a/lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/ui.js b/lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/ui.js similarity index 100% rename from lib/IRremoteESP8266-2.7.3/examples/Web-AC-control/upload/ui.js rename to lib/IRremoteESP8266-2.7.4/examples/Web-AC-control/upload/ui.js diff --git a/lib/IRremoteESP8266-2.7.3/keywords.txt b/lib/IRremoteESP8266-2.7.4/keywords.txt similarity index 99% rename from lib/IRremoteESP8266-2.7.3/keywords.txt rename to lib/IRremoteESP8266-2.7.4/keywords.txt index 65b0d8b2e..077c0bc74 100644 --- a/lib/IRremoteESP8266-2.7.3/keywords.txt +++ b/lib/IRremoteESP8266-2.7.4/keywords.txt @@ -133,6 +133,7 @@ convertSwingV KEYWORD2 coolix KEYWORD2 copyIrParams KEYWORD2 countBits KEYWORD2 +crudeNoiseFilter KEYWORD2 daikin KEYWORD2 daikin128 KEYWORD2 daikin152 KEYWORD2 @@ -156,6 +157,7 @@ decodeDaikin2 KEYWORD2 decodeDaikin216 KEYWORD2 decodeDenon KEYWORD2 decodeElectraAC KEYWORD2 +decodeEpson KEYWORD2 decodeFujitsuAC KEYWORD2 decodeGICable KEYWORD2 decodeGoodweather KEYWORD2 @@ -252,6 +254,7 @@ getCorrectedRawLength KEYWORD2 getCurrTime KEYWORD2 getCurrentDay KEYWORD2 getCurrentTime KEYWORD2 +getDisplay KEYWORD2 getEcono KEYWORD2 getEye KEYWORD2 getEyeAuto KEYWORD2 @@ -355,6 +358,7 @@ ledOff KEYWORD2 ledOn KEYWORD2 lg KEYWORD2 mark KEYWORD2 +markAsSent KEYWORD2 match KEYWORD2 matchAtLeast KEYWORD2 matchBytes KEYWORD2 @@ -406,6 +410,7 @@ sendDaikin216 KEYWORD2 sendData KEYWORD2 sendDenon KEYWORD2 sendElectraAC KEYWORD2 +sendEpson KEYWORD2 sendExtended KEYWORD2 sendFujitsuAC KEYWORD2 sendGC KEYWORD2 @@ -484,6 +489,7 @@ setCommand KEYWORD2 setCurrTime KEYWORD2 setCurrentDay KEYWORD2 setCurrentTime KEYWORD2 +setDisplay KEYWORD2 setEcono KEYWORD2 setEye KEYWORD2 setEyeAuto KEYWORD2 @@ -666,6 +672,7 @@ DECODE_DAIKIN216 LITERAL1 DECODE_DENON LITERAL1 DECODE_DISH LITERAL1 DECODE_ELECTRA_AC LITERAL1 +DECODE_EPSON LITERAL1 DECODE_FUJITSU_AC LITERAL1 DECODE_GICABLE LITERAL1 DECODE_GLOBALCACHE LITERAL1 @@ -728,6 +735,8 @@ DG11J191 LITERAL1 DISH LITERAL1 DISH_BITS LITERAL1 ELECTRA_AC LITERAL1 +ENABLE_NOISE_FILTER_OPTION LITERAL1 +EPSON LITERAL1 FUJITSU_AC LITERAL1 FUJITSU_AC_BITS LITERAL1 FUJITSU_AC_CMD_STAY_ON LITERAL1 @@ -964,6 +973,7 @@ SEND_DAIKIN216 LITERAL1 SEND_DENON LITERAL1 SEND_DISH LITERAL1 SEND_ELECTRA_AC LITERAL1 +SEND_EPSON LITERAL1 SEND_FUJITSU_AC LITERAL1 SEND_GICABLE LITERAL1 SEND_GLOBALCACHE LITERAL1 @@ -1634,6 +1644,7 @@ kEconoStr LITERAL1 kElectraAcAuto LITERAL1 kElectraAcBitMark LITERAL1 kElectraAcBits LITERAL1 +kElectraAcCleanOffset LITERAL1 kElectraAcCool LITERAL1 kElectraAcDry LITERAL1 kElectraAcFan LITERAL1 @@ -1646,6 +1657,9 @@ kElectraAcFanSize LITERAL1 kElectraAcHdrMark LITERAL1 kElectraAcHdrSpace LITERAL1 kElectraAcHeat LITERAL1 +kElectraAcLightToggleMask LITERAL1 +kElectraAcLightToggleOff LITERAL1 +kElectraAcLightToggleOn LITERAL1 kElectraAcMaxTemp LITERAL1 kElectraAcMessageGap LITERAL1 kElectraAcMinRepeat LITERAL1 @@ -1662,7 +1676,10 @@ kElectraAcSwingVOffset LITERAL1 kElectraAcTempDelta LITERAL1 kElectraAcTempOffset LITERAL1 kElectraAcTempSize LITERAL1 +kElectraAcTurboOffset LITERAL1 kElectraAcZeroSpace LITERAL1 +kEpsonBits LITERAL1 +kEpsonMinRepeat LITERAL1 kEyeAutoStr LITERAL1 kEyeStr LITERAL1 kFalseStr LITERAL1 @@ -2763,6 +2780,7 @@ kSamsungAcClean10Offset LITERAL1 kSamsungAcClean11Offset LITERAL1 kSamsungAcCool LITERAL1 kSamsungAcDefaultRepeat LITERAL1 +kSamsungAcDisplayOffset LITERAL1 kSamsungAcDry LITERAL1 kSamsungAcExtendedBits LITERAL1 kSamsungAcExtendedStateLength LITERAL1 @@ -2778,6 +2796,7 @@ kSamsungAcFanTurbo LITERAL1 kSamsungAcHdrMark LITERAL1 kSamsungAcHdrSpace LITERAL1 kSamsungAcHeat LITERAL1 +kSamsungAcIonOffset LITERAL1 kSamsungAcMaxTemp LITERAL1 kSamsungAcMinTemp LITERAL1 kSamsungAcModeOffset LITERAL1 diff --git a/lib/IRremoteESP8266-2.7.3/library.json b/lib/IRremoteESP8266-2.7.4/library.json similarity index 97% rename from lib/IRremoteESP8266-2.7.3/library.json rename to lib/IRremoteESP8266-2.7.4/library.json index b28b1b218..f135c19e7 100644 --- a/lib/IRremoteESP8266-2.7.3/library.json +++ b/lib/IRremoteESP8266-2.7.4/library.json @@ -1,6 +1,6 @@ { "name": "IRremoteESP8266", - "version": "2.7.3", + "version": "2.7.4", "keywords": "infrared, ir, remote, esp8266, esp32", "description": "Send and receive infrared signals with multiple protocols (ESP8266/ESP32)", "repository": diff --git a/lib/IRremoteESP8266-2.7.3/library.properties b/lib/IRremoteESP8266-2.7.4/library.properties similarity index 83% rename from lib/IRremoteESP8266-2.7.3/library.properties rename to lib/IRremoteESP8266-2.7.4/library.properties index b22e7f8cc..e98cd3f3b 100644 --- a/lib/IRremoteESP8266-2.7.3/library.properties +++ b/lib/IRremoteESP8266-2.7.4/library.properties @@ -1,7 +1,7 @@ name=IRremoteESP8266 -version=2.7.3 +version=2.7.4 author=David Conran, Sebastien Warin, Mark Szabo, Ken Shirriff -maintainer=Mark Szabo, David Conran, Sebastien Warin, Roi Dayan, Massimiliano Pinto +maintainer=David Conran, Mark Szabo, Sebastien Warin, Roi Dayan, Massimiliano Pinto sentence=Send and receive infrared signals with multiple protocols (ESP8266/ESP32) paragraph=This library enables you to send and receive infra-red signals on an ESP8266 or an ESP32. category=Device Control diff --git a/lib/IRremoteESP8266-2.7.3/pylintrc b/lib/IRremoteESP8266-2.7.4/pylintrc similarity index 100% rename from lib/IRremoteESP8266-2.7.3/pylintrc rename to lib/IRremoteESP8266-2.7.4/pylintrc diff --git a/lib/IRremoteESP8266-2.7.3/src/CPPLINT.cfg b/lib/IRremoteESP8266-2.7.4/src/CPPLINT.cfg similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/CPPLINT.cfg rename to lib/IRremoteESP8266-2.7.4/src/CPPLINT.cfg diff --git a/lib/IRremoteESP8266-2.7.3/src/IRac.cpp b/lib/IRremoteESP8266-2.7.4/src/IRac.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.3/src/IRac.cpp rename to lib/IRremoteESP8266-2.7.4/src/IRac.cpp index b2dc6f63e..d3be30b80 100644 --- a/lib/IRremoteESP8266-2.7.3/src/IRac.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/IRac.cpp @@ -45,7 +45,7 @@ IRac::IRac(const uint16_t pin, const bool inverted, const bool use_modulation) { _inverted = inverted; _modulation = use_modulation; initState(&next); - _prev = next; + this->markAsSent(); } void IRac::initState(stdAc::state_t *state, @@ -466,7 +466,8 @@ void IRac::electra(IRElectraAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, - const stdAc::swingh_t swingh) { + const stdAc::swingh_t swingh, const bool turbo, + const bool lighttoggle, const bool clean) { ac->begin(); ac->setPower(on); ac->setMode(ac->convertMode(mode)); @@ -475,11 +476,12 @@ void IRac::electra(IRElectraAc *ac, ac->setSwingV(swingv != stdAc::swingv_t::kOff); ac->setSwingH(swingh != stdAc::swingh_t::kOff); // No Quiet setting available. - // No Turbo setting available. + ac->setTurbo(turbo); + ac->setLightToggle(lighttoggle); // No Light setting available. // No Econo setting available. // No Filter setting available. - // No Clean setting available. + ac->setClean(clean); // No Beep setting available. // No Sleep setting available. // No Clock setting available. @@ -968,7 +970,8 @@ void IRac::samsung(IRSamsungAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, - const bool quiet, const bool turbo, const bool clean, + const bool quiet, const bool turbo, const bool light, + const bool filter, const bool clean, const bool beep, const bool prevpower, const bool forcepower) { ac->begin(); @@ -981,9 +984,9 @@ void IRac::samsung(IRSamsungAc *ac, // No Horizontal swing setting available. ac->setQuiet(quiet); ac->setPowerful(turbo); - // No Light setting available. + ac->setDisplay(light); // No Econo setting available. - // No Filter setting available. + ac->setIon(filter); ac->setClean(clean); ac->setBeep(beep); // No Sleep setting available. @@ -1219,6 +1222,9 @@ stdAc::state_t IRac::handleToggles(const stdAc::state_t desired, result.power = desired.power ^ prev->power; result.light = desired.light ^ prev->light; break; + case decode_type_t::ELECTRA_AC: + result.light = desired.light ^ prev->light; + break; case decode_type_t::MIDEA: case decode_type_t::HITACHI_AC424: if ((desired.swingv == stdAc::swingv_t::kOff) ^ @@ -1389,7 +1395,7 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { { IRElectraAc ac(_pin, _inverted, _modulation); electra(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv, - send.swingh); + send.swingh, send.turbo, send.light, send.clean); break; } #endif // SEND_ELECTRA_AC @@ -1557,7 +1563,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { { IRSamsungAc ac(_pin, _inverted, _modulation); samsung(&ac, send.power, send.mode, degC, send.fanspeed, send.swingv, - send.quiet, send.turbo, send.clean, send.beep, prev->power); + send.quiet, send.turbo, send.light, send.filter, send.clean, + send.beep, prev->power); break; } #endif // SEND_SAMSUNG_AC @@ -1628,13 +1635,18 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) { return true; // Success. } +// Update the previous state to the current one. +void IRac::markAsSent(void) { + _prev = next; +} + // Send an A/C message based soley on our internal state. // // Returns: // boolean: True, if accepted/converted/attempted. False, if unsupported. bool IRac::sendAc(void) { bool success = this->sendAc(next, &_prev); - _prev = next; + if (success) this->markAsSent(); return success; } @@ -2232,7 +2244,6 @@ namespace IRAcUtils { #if DECODE_COOLIX case decode_type_t::COOLIX: { IRCoolixAC ac(kGpioUnused); - ac.on(); ac.setRaw(decode->value); // Uses value instead of state. *result = ac.toCommon(prev); break; diff --git a/lib/IRremoteESP8266-2.7.3/src/IRac.h b/lib/IRremoteESP8266-2.7.4/src/IRac.h similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/IRac.h rename to lib/IRremoteESP8266-2.7.4/src/IRac.h index 4945bfac9..f38865e50 100644 --- a/lib/IRremoteESP8266-2.7.3/src/IRac.h +++ b/lib/IRremoteESP8266-2.7.4/src/IRac.h @@ -54,6 +54,7 @@ class IRac { const bool beep, const int16_t sleep, const int16_t clock); static void initState(stdAc::state_t *state); + void markAsSent(void); bool sendAc(void); bool sendAc(const stdAc::state_t desired, const stdAc::state_t *prev = NULL); bool sendAc(const decode_type_t vendor, const int16_t model, @@ -170,7 +171,8 @@ void electra(IRElectraAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, - const stdAc::swingh_t swingh); + const stdAc::swingh_t swingh, const bool turbo, + const bool lighttoggle, const bool clean); #endif // SEND_ELECTRA_AC #if SEND_FUJITSU_AC void fujitsu(IRFujitsuAC *ac, const fujitsu_ac_remote_model_t model, @@ -299,7 +301,8 @@ void electra(IRElectraAc *ac, void samsung(IRSamsungAc *ac, const bool on, const stdAc::opmode_t mode, const float degrees, const stdAc::fanspeed_t fan, const stdAc::swingv_t swingv, - const bool quiet, const bool turbo, const bool clean, + const bool quiet, const bool turbo, const bool light, + const bool filter, const bool clean, const bool beep, const bool prevpower = true, const bool forcepower = true); #endif // SEND_SAMSUNG_AC diff --git a/lib/IRremoteESP8266-2.7.3/src/IRrecv.cpp b/lib/IRremoteESP8266-2.7.4/src/IRrecv.cpp similarity index 72% rename from lib/IRremoteESP8266-2.7.3/src/IRrecv.cpp rename to lib/IRremoteESP8266-2.7.4/src/IRrecv.cpp index c2c1b5394..e629fc218 100644 --- a/lib/IRremoteESP8266-2.7.3/src/IRrecv.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/IRrecv.cpp @@ -307,6 +307,37 @@ void IRrecv::setTolerance(const uint8_t percent) { // Get the base tolerance percentage for matching incoming IR messages. uint8_t IRrecv::getTolerance(void) { return _tolerance; } +#if ENABLE_NOISE_FILTER_OPTION +// Remove or merge pulses in the capture buffer that are too short. +// Args: +// results: Ptr to the decode_results we are going to filter/modify. +// floor: Only allow values in the buffer large than this. (in micro seconds) +void IRrecv::crudeNoiseFilter(decode_results *results, const uint16_t floor) { + if (floor == 0) return; // Nothing to do. + const uint16_t kTickFloor = floor / kRawTick; + const uint16_t kBufSize = getBufSize(); + uint16_t offset = kStartOffset; + while (offset < results->rawlen && offset + 2 < kBufSize) { + uint16_t curr = results->rawbuf[offset]; + uint16_t next = results->rawbuf[offset + 1]; + uint16_t addition = curr + next; + if (curr < kTickFloor) { // Is it too short? + // Shuffle the buffer down. i.e. Remove the mark & space pair. + // Note: `memcpy()` can't be used as rawbuf is `volatile`. + for (uint16_t i = offset + 2; i <= results->rawlen && i < kBufSize; i++) + results->rawbuf[i - 2] = results->rawbuf[i]; + if (offset > 1) { // There is a previous pair we can add to. + // Merge this pair into into the previous space. + results->rawbuf[offset - 1] += addition; + } + results->rawlen -= 2; // Adjust the length. + } else { + offset++; // Move along. + } + } +} +#endif // ENABLE_NOISE_FILTER_OPTION + // Decodes the received IR message. // If the interrupt state is saved, we will immediately resume waiting // for the next IR message to avoid missing messages. @@ -317,9 +348,41 @@ uint8_t IRrecv::getTolerance(void) { return _tolerance; } // results: A pointer to where the decoded IR message will be stored. // save: A pointer to an irparams_t instance in which to save // the interrupt's memory/state. NULL means don't save it. +// max_skip: Maximum Nr. of pulses at the begining of a capture we can skip +// when attempting to find a protocol we can successfully decode. +// This parameter can dramatically improve detection of protocols +// when there is light IR interference just before an incoming IR +// message, however, it comes at a steep performace price. +// CAUTION: Increasing this value will dramatically (linnearly) +// increase the cpu time & usage to decode protocols. +// e.g. 0 -> 1 will be a 2x increase in cpu usage/time. +// 0 -> 2 will be a 3x increase etc. +// If you are going to do this, consider disabling +// protocol decoding for protocols you are not expecting. +// (Default is 0. No skipping.) +// noise_floor: Pulses below this size (in usecs) will be removed or merged +// prior to any decoding. This is to try to remove noise/poor +// readings & slighly increase the chances of a successful +// decode but at the cost of data fidelity & integrity. +// (Defaults to 0 usecs. i.e. Don't filter; which is safe!) +// DANGER: **Here Be Dragons!** +// If you set the `filter_floor` value too high, it **WILL** +// break decoding of some protocols. You have been warned! +// **Any** non-zero value has the potential to **cook** the +// captured raw data. i.e. The data is going to lie to you. +// It may obscure hardware, circuit, & environment issues thus +// making it impossible to support you accurately or +// confidently. +// Values of <= 50 usecs will probably be safe. +// 51 - 100 usecs **might** be okay. +// 100 - 150 usecs is "Danger, Will Robinson!". +// 150 - 200 usecs expect broken protocols. +// At 200+ usecs, you **have** protocols you can't decode!! +// // Returns: // A boolean indicating if an IR message is ready or not. -bool IRrecv::decode(decode_results *results, irparams_t *save) { +bool IRrecv::decode(decode_results *results, irparams_t *save, + uint8_t max_skip, uint16_t noise_floor) { // Proceed only if an IR message been received. #ifndef UNIT_TEST if (irparams.rcvstate != kStopState) return false; @@ -365,320 +428,342 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) { results->command = 0; results->repeat = false; +#if ENABLE_NOISE_FILTER_OPTION + crudeNoiseFilter(results, noise_floor); +#endif // ENABLE_NOISE_FILTER_OPTION + // Keep looking for protocols until we've run out of entries to skip or we + // find a valid protocol message. + for (uint16_t offset = kStartOffset; + offset <= (max_skip * 2) + kStartOffset; + offset += 2) { #if DECODE_AIWA_RC_T501 - DPRINTLN("Attempting Aiwa RC T501 decode"); - // Try decodeAiwaRCT501() before decodeSanyoLC7461() & decodeNEC() - // because the protocols are similar. This protocol is more specific than - // those ones, so should got before them. - if (decodeAiwaRCT501(results)) return true; + DPRINTLN("Attempting Aiwa RC T501 decode"); + // Try decodeAiwaRCT501() before decodeSanyoLC7461() & decodeNEC() + // because the protocols are similar. This protocol is more specific than + // those ones, so should go before them. + if (decodeAiwaRCT501(results, offset)) return true; #endif #if DECODE_SANYO - DPRINTLN("Attempting Sanyo LC7461 decode"); - // Try decodeSanyoLC7461() before decodeNEC() because the protocols are - // similar in timings & structure, but the Sanyo one is much longer than the - // NEC protocol (42 vs 32 bits) so this one should be tried first to try to - // reduce false detection as a NEC packet. - if (decodeSanyoLC7461(results)) return true; + DPRINTLN("Attempting Sanyo LC7461 decode"); + // Try decodeSanyoLC7461() before decodeNEC() because the protocols are + // similar in timings & structure, but the Sanyo one is much longer than the + // NEC protocol (42 vs 32 bits) so this one should be tried first to try to + // reduce false detection as a NEC packet. + if (decodeSanyoLC7461(results, offset)) return true; #endif #if DECODE_CARRIER_AC - DPRINTLN("Attempting Carrier AC decode"); - // Try decodeCarrierAC() before decodeNEC() because the protocols are - // similar in timings & structure, but the Carrier one is much longer than the - // NEC protocol (3x32 bits vs 1x32 bits) so this one should be tried first to - // try to reduce false detection as a NEC packet. - if (decodeCarrierAC(results)) return true; + DPRINTLN("Attempting Carrier AC decode"); + // Try decodeCarrierAC() before decodeNEC() because the protocols are + // similar in timings & structure, but the Carrier one is much longer than + // the NEC protocol (3x32 bits vs 1x32 bits) so this one should be tried + // first to try to reduce false detection as a NEC packet. + if (decodeCarrierAC(results, offset)) return true; #endif #if DECODE_PIONEER - DPRINTLN("Attempting Pioneer decode"); - // Try decodePioneer() before decodeNEC() because the protocols are - // similar in timings & structure, but the Pioneer one is much longer than the - // NEC protocol (2x32 bits vs 1x32 bits) so this one should be tried first to - // try to reduce false detection as a NEC packet. - if (decodePioneer(results)) return true; + DPRINTLN("Attempting Pioneer decode"); + // Try decodePioneer() before decodeNEC() because the protocols are + // similar in timings & structure, but the Pioneer one is much longer than + // the NEC protocol (2x32 bits vs 1x32 bits) so this one should be tried + // first to try to reduce false detection as a NEC packet. + if (decodePioneer(results, offset)) return true; +#endif +#if DECODE_EPSON + DPRINTLN("Attempting Epson decode"); + // Try decodeEpson() before decodeNEC() because the protocols are + // similar in timings & structure, but the Epson one is much longer than the + // NEC protocol (3x32 identical bits vs 1x32 bits) so this one should be tried + // first to try to reduce false detection as a NEC packet. + if (decodeEpson(results, offset)) return true; #endif #if DECODE_NEC - DPRINTLN("Attempting NEC decode"); - if (decodeNEC(results)) return true; + DPRINTLN("Attempting NEC decode"); + if (decodeNEC(results, offset)) return true; #endif #if DECODE_SONY - DPRINTLN("Attempting Sony decode"); - if (decodeSony(results)) return true; + DPRINTLN("Attempting Sony decode"); + if (decodeSony(results, offset)) return true; #endif #if DECODE_MITSUBISHI - DPRINTLN("Attempting Mitsubishi decode"); - if (decodeMitsubishi(results)) return true; + DPRINTLN("Attempting Mitsubishi decode"); + if (decodeMitsubishi(results, offset)) return true; #endif #if DECODE_MITSUBISHI_AC - DPRINTLN("Attempting Mitsubishi AC decode"); - if (decodeMitsubishiAC(results)) return true; + DPRINTLN("Attempting Mitsubishi AC decode"); + if (decodeMitsubishiAC(results, offset)) return true; #endif #if DECODE_MITSUBISHI2 - DPRINTLN("Attempting Mitsubishi2 decode"); - if (decodeMitsubishi2(results)) return true; + DPRINTLN("Attempting Mitsubishi2 decode"); + if (decodeMitsubishi2(results, offset)) return true; #endif #if DECODE_RC5 - DPRINTLN("Attempting RC5 decode"); - if (decodeRC5(results)) return true; + DPRINTLN("Attempting RC5 decode"); + if (decodeRC5(results, offset)) return true; #endif #if DECODE_RC6 - DPRINTLN("Attempting RC6 decode"); - if (decodeRC6(results)) return true; + DPRINTLN("Attempting RC6 decode"); + if (decodeRC6(results, offset)) return true; #endif #if DECODE_RCMM - DPRINTLN("Attempting RC-MM decode"); - if (decodeRCMM(results)) return true; + DPRINTLN("Attempting RC-MM decode"); + if (decodeRCMM(results, offset)) return true; #endif #if DECODE_FUJITSU_AC - // Fujitsu A/C needs to precede Panasonic and Denon as it has a short - // message which looks exactly the same as a Panasonic/Denon message. - DPRINTLN("Attempting Fujitsu A/C decode"); - if (decodeFujitsuAC(results)) return true; + // Fujitsu A/C needs to precede Panasonic and Denon as it has a short + // message which looks exactly the same as a Panasonic/Denon message. + DPRINTLN("Attempting Fujitsu A/C decode"); + if (decodeFujitsuAC(results, offset)) return true; #endif #if DECODE_DENON - // Denon needs to precede Panasonic as it is a special case of Panasonic. - DPRINTLN("Attempting Denon decode"); - if (decodeDenon(results, kDenon48Bits) || decodeDenon(results, kDenonBits) || - decodeDenon(results, kDenonLegacyBits)) - return true; + // Denon needs to precede Panasonic as it is a special case of Panasonic. + DPRINTLN("Attempting Denon decode"); + if (decodeDenon(results, offset, kDenon48Bits) || + decodeDenon(results, offset, kDenonBits) || + decodeDenon(results, offset, kDenonLegacyBits)) + return true; #endif #if DECODE_PANASONIC - DPRINTLN("Attempting Panasonic decode"); - if (decodePanasonic(results)) return true; + DPRINTLN("Attempting Panasonic decode"); + if (decodePanasonic(results, offset)) return true; #endif #if DECODE_LG - DPRINTLN("Attempting LG (28-bit) decode"); - if (decodeLG(results, kLgBits, true)) return true; - DPRINTLN("Attempting LG (32-bit) decode"); - // LG32 should be tried before Samsung - if (decodeLG(results, kLg32Bits, true)) return true; + DPRINTLN("Attempting LG (28-bit) decode"); + if (decodeLG(results, offset, kLgBits, true)) return true; + DPRINTLN("Attempting LG (32-bit) decode"); + // LG32 should be tried before Samsung + if (decodeLG(results, offset, kLg32Bits, true)) return true; #endif #if DECODE_GICABLE - // Note: Needs to happen before JVC decode, because it looks similar except - // with a required NEC-like repeat code. - DPRINTLN("Attempting GICable decode"); - if (decodeGICable(results)) return true; + // Note: Needs to happen before JVC decode, because it looks similar except + // with a required NEC-like repeat code. + DPRINTLN("Attempting GICable decode"); + if (decodeGICable(results, offset)) return true; #endif #if DECODE_JVC - DPRINTLN("Attempting JVC decode"); - if (decodeJVC(results)) return true; + DPRINTLN("Attempting JVC decode"); + if (decodeJVC(results, offset)) return true; #endif #if DECODE_SAMSUNG - DPRINTLN("Attempting SAMSUNG decode"); - if (decodeSAMSUNG(results)) return true; + DPRINTLN("Attempting SAMSUNG decode"); + if (decodeSAMSUNG(results, offset)) return true; #endif #if DECODE_SAMSUNG36 - DPRINTLN("Attempting Samsung36 decode"); - if (decodeSamsung36(results)) return true; + DPRINTLN("Attempting Samsung36 decode"); + if (decodeSamsung36(results, offset)) return true; #endif #if DECODE_WHYNTER - DPRINTLN("Attempting Whynter decode"); - if (decodeWhynter(results)) return true; + DPRINTLN("Attempting Whynter decode"); + if (decodeWhynter(results, offset)) return true; #endif #if DECODE_DISH - DPRINTLN("Attempting DISH decode"); - if (decodeDISH(results)) return true; + DPRINTLN("Attempting DISH decode"); + if (decodeDISH(results, offset)) return true; #endif #if DECODE_SHARP - DPRINTLN("Attempting Sharp decode"); - if (decodeSharp(results)) return true; + DPRINTLN("Attempting Sharp decode"); + if (decodeSharp(results, offset)) return true; #endif #if DECODE_COOLIX - DPRINTLN("Attempting Coolix decode"); - if (decodeCOOLIX(results)) return true; + DPRINTLN("Attempting Coolix decode"); + if (decodeCOOLIX(results, offset)) return true; #endif #if DECODE_NIKAI - DPRINTLN("Attempting Nikai decode"); - if (decodeNikai(results)) return true; + DPRINTLN("Attempting Nikai decode"); + if (decodeNikai(results, offset)) return true; #endif #if DECODE_KELVINATOR - // Kelvinator based-devices use a similar code to Gree ones, to avoid false - // matches this needs to happen before decodeGree(). - DPRINTLN("Attempting Kelvinator decode"); - if (decodeKelvinator(results)) return true; + // Kelvinator based-devices use a similar code to Gree ones, to avoid false + // matches this needs to happen before decodeGree(). + DPRINTLN("Attempting Kelvinator decode"); + if (decodeKelvinator(results, offset)) return true; #endif #if DECODE_DAIKIN - DPRINTLN("Attempting Daikin decode"); - if (decodeDaikin(results)) return true; + DPRINTLN("Attempting Daikin decode"); + if (decodeDaikin(results, offset)) return true; #endif #if DECODE_DAIKIN2 - DPRINTLN("Attempting Daikin2 decode"); - if (decodeDaikin2(results)) return true; + DPRINTLN("Attempting Daikin2 decode"); + if (decodeDaikin2(results, offset)) return true; #endif #if DECODE_DAIKIN216 - DPRINTLN("Attempting Daikin216 decode"); - if (decodeDaikin216(results)) return true; + DPRINTLN("Attempting Daikin216 decode"); + if (decodeDaikin216(results, offset)) return true; #endif #if DECODE_TOSHIBA_AC - DPRINTLN("Attempting Toshiba AC decode"); - if (decodeToshibaAC(results)) return true; + DPRINTLN("Attempting Toshiba AC decode"); + if (decodeToshibaAC(results, offset)) return true; #endif #if DECODE_MIDEA - DPRINTLN("Attempting Midea decode"); - if (decodeMidea(results)) return true; + DPRINTLN("Attempting Midea decode"); + if (decodeMidea(results, offset)) return true; #endif #if DECODE_MAGIQUEST - DPRINTLN("Attempting Magiquest decode"); - if (decodeMagiQuest(results)) return true; + DPRINTLN("Attempting Magiquest decode"); + if (decodeMagiQuest(results, offset)) return true; #endif -/* NOTE: Disabled due to poor quality. + /* NOTE: Disabled due to poor quality. #if DECODE_SANYO - // The Sanyo S866500B decoder is very poor quality & depricated. - // *IF* you are going to enable it, do it near last to avoid false positive - // matches. - DPRINTLN("Attempting Sanyo SA8650B decode"); - if (decodeSanyo(results)) - return true; + // The Sanyo S866500B decoder is very poor quality & depricated. + // *IF* you are going to enable it, do it near last to avoid false positive + // matches. + DPRINTLN("Attempting Sanyo SA8650B decode"); + if (decodeSanyo(results, offset)) + return true; #endif -*/ + */ #if DECODE_NEC - // Some devices send NEC-like codes that don't follow the true NEC spec. - // This should detect those. e.g. Apple TV remote etc. - // This needs to be done after all other codes that use strict and some - // other protocols that are NEC-like as well, as turning off strict may - // cause this to match other valid protocols. - DPRINTLN("Attempting NEC (non-strict) decode"); - if (decodeNEC(results, kNECBits, false)) { - results->decode_type = NEC_LIKE; - return true; - } + // Some devices send NEC-like codes that don't follow the true NEC spec. + // This should detect those. e.g. Apple TV remote etc. + // This needs to be done after all other codes that use strict and some + // other protocols that are NEC-like as well, as turning off strict may + // cause this to match other valid protocols. + DPRINTLN("Attempting NEC (non-strict) decode"); + if (decodeNEC(results, offset, kNECBits, false)) { + results->decode_type = NEC_LIKE; + return true; + } #endif #if DECODE_LASERTAG - DPRINTLN("Attempting Lasertag decode"); - if (decodeLasertag(results)) return true; + DPRINTLN("Attempting Lasertag decode"); + if (decodeLasertag(results, offset)) return true; #endif #if DECODE_GREE - // Gree based-devices use a similar code to Kelvinator ones, to avoid false - // matches this needs to happen after decodeKelvinator(). - DPRINTLN("Attempting Gree decode"); - if (decodeGree(results)) return true; + // Gree based-devices use a similar code to Kelvinator ones, to avoid false + // matches this needs to happen after decodeKelvinator(). + DPRINTLN("Attempting Gree decode"); + if (decodeGree(results, offset)) return true; #endif #if DECODE_HAIER_AC - DPRINTLN("Attempting Haier AC decode"); - if (decodeHaierAC(results)) return true; + DPRINTLN("Attempting Haier AC decode"); + if (decodeHaierAC(results, offset)) return true; #endif #if DECODE_HAIER_AC_YRW02 - DPRINTLN("Attempting Haier AC YR-W02 decode"); - if (decodeHaierACYRW02(results)) return true; + DPRINTLN("Attempting Haier AC YR-W02 decode"); + if (decodeHaierACYRW02(results, offset)) return true; #endif #if DECODE_HITACHI_AC424 - // HitachiAc424 should be checked before HitachiAC & HitachiAC2 - DPRINTLN("Attempting Hitachi AC 424 decode"); - if (decodeHitachiAc424(results, kHitachiAc424Bits)) return true; + // HitachiAc424 should be checked before HitachiAC & HitachiAC2 + DPRINTLN("Attempting Hitachi AC 424 decode"); + if (decodeHitachiAc424(results, offset, kHitachiAc424Bits)) return true; #endif // DECODE_HITACHI_AC2 #if DECODE_HITACHI_AC2 - // HitachiAC2 should be checked before HitachiAC - DPRINTLN("Attempting Hitachi AC2 decode"); - if (decodeHitachiAC(results, kHitachiAc2Bits)) return true; + // HitachiAC2 should be checked before HitachiAC + DPRINTLN("Attempting Hitachi AC2 decode"); + if (decodeHitachiAC(results, offset, kHitachiAc2Bits)) return true; #endif // DECODE_HITACHI_AC2 #if DECODE_HITACHI_AC - DPRINTLN("Attempting Hitachi AC decode"); - if (decodeHitachiAC(results, kHitachiAcBits)) return true; + DPRINTLN("Attempting Hitachi AC decode"); + if (decodeHitachiAC(results, offset, kHitachiAcBits)) return true; #endif #if DECODE_HITACHI_AC1 - DPRINTLN("Attempting Hitachi AC1 decode"); - if (decodeHitachiAC(results, kHitachiAc1Bits)) return true; + DPRINTLN("Attempting Hitachi AC1 decode"); + if (decodeHitachiAC(results, offset, kHitachiAc1Bits)) return true; #endif #if DECODE_WHIRLPOOL_AC - DPRINTLN("Attempting Whirlpool AC decode"); - if (decodeWhirlpoolAC(results)) return true; + DPRINTLN("Attempting Whirlpool AC decode"); + if (decodeWhirlpoolAC(results, offset)) return true; #endif #if DECODE_SAMSUNG_AC - DPRINTLN("Attempting Samsung AC (extended) decode"); - // Check the extended size first, as it should fail fast due to longer length. - if (decodeSamsungAC(results, kSamsungAcExtendedBits, false)) return true; - // Now check for the more common length. - DPRINTLN("Attempting Samsung AC decode"); - if (decodeSamsungAC(results, kSamsungAcBits)) return true; + DPRINTLN("Attempting Samsung AC (extended) decode"); + // Check the extended size first, as it should fail fast due to longer + // length. + if (decodeSamsungAC(results, offset, kSamsungAcExtendedBits, false)) + return true; + // Now check for the more common length. + DPRINTLN("Attempting Samsung AC decode"); + if (decodeSamsungAC(results, offset, kSamsungAcBits)) return true; #endif #if DECODE_ELECTRA_AC - DPRINTLN("Attempting Electra AC decode"); - if (decodeElectraAC(results)) return true; + DPRINTLN("Attempting Electra AC decode"); + if (decodeElectraAC(results, offset)) return true; #endif #if DECODE_PANASONIC_AC - DPRINTLN("Attempting Panasonic AC decode"); - if (decodePanasonicAC(results)) return true; - DPRINTLN("Attempting Panasonic AC short decode"); - if (decodePanasonicAC(results, kPanasonicAcShortBits)) return true; + DPRINTLN("Attempting Panasonic AC decode"); + if (decodePanasonicAC(results, offset)) return true; + DPRINTLN("Attempting Panasonic AC short decode"); + if (decodePanasonicAC(results, offset, kPanasonicAcShortBits)) return true; #endif #if DECODE_LUTRON - DPRINTLN("Attempting Lutron decode"); - if (decodeLutron(results)) return true; + DPRINTLN("Attempting Lutron decode"); + if (decodeLutron(results, offset)) return true; #endif #if DECODE_MWM - DPRINTLN("Attempting MWM decode"); - if (decodeMWM(results)) return true; + DPRINTLN("Attempting MWM decode"); + if (decodeMWM(results, offset)) return true; #endif #if DECODE_VESTEL_AC - DPRINTLN("Attempting Vestel AC decode"); - if (decodeVestelAc(results)) return true; + DPRINTLN("Attempting Vestel AC decode"); + if (decodeVestelAc(results, offset)) return true; #endif #if DECODE_MITSUBISHI112 || DECODE_TCL112AC - // Mitsubish112 and Tcl112 share the same decoder. - DPRINTLN("Attempting Mitsubishi112/TCL112AC decode"); - if (decodeMitsubishi112(results)) return true; + // Mitsubish112 and Tcl112 share the same decoder. + DPRINTLN("Attempting Mitsubishi112/TCL112AC decode"); + if (decodeMitsubishi112(results, offset)) return true; #endif // DECODE_MITSUBISHI112 || DECODE_TCL112AC #if DECODE_TECO - DPRINTLN("Attempting Teco decode"); - if (decodeTeco(results)) return true; + DPRINTLN("Attempting Teco decode"); + if (decodeTeco(results, offset)) return true; #endif #if DECODE_LEGOPF - DPRINTLN("Attempting LEGOPF decode"); - if (decodeLegoPf(results)) return true; + DPRINTLN("Attempting LEGOPF decode"); + if (decodeLegoPf(results, offset)) return true; #endif #if DECODE_MITSUBISHIHEAVY - DPRINTLN("Attempting MITSUBISHIHEAVY (152 bit) decode"); - if (decodeMitsubishiHeavy(results, kMitsubishiHeavy152Bits)) return true; - DPRINTLN("Attempting MITSUBISHIHEAVY (88 bit) decode"); - if (decodeMitsubishiHeavy(results, kMitsubishiHeavy88Bits)) return true; + DPRINTLN("Attempting MITSUBISHIHEAVY (152 bit) decode"); + if (decodeMitsubishiHeavy(results, offset, kMitsubishiHeavy152Bits)) + return true; + DPRINTLN("Attempting MITSUBISHIHEAVY (88 bit) decode"); + if (decodeMitsubishiHeavy(results, offset, kMitsubishiHeavy88Bits)) + return true; #endif #if DECODE_ARGO - DPRINTLN("Attempting Argo decode"); - if (decodeArgo(results)) return true; + DPRINTLN("Attempting Argo decode"); + if (decodeArgo(results, offset)) return true; #endif // DECODE_ARGO #if DECODE_SHARP_AC - DPRINTLN("Attempting SHARP_AC decode"); - if (decodeSharpAc(results)) return true; + DPRINTLN("Attempting SHARP_AC decode"); + if (decodeSharpAc(results, offset)) return true; #endif #if DECODE_GOODWEATHER - DPRINTLN("Attempting GOODWEATHER decode"); - if (decodeGoodweather(results)) return true; + DPRINTLN("Attempting GOODWEATHER decode"); + if (decodeGoodweather(results, offset)) return true; #endif // DECODE_GOODWEATHER #if DECODE_INAX - DPRINTLN("Attempting Inax decode"); - if (decodeInax(results)) return true; + DPRINTLN("Attempting Inax decode"); + if (decodeInax(results, offset)) return true; #endif // DECODE_INAX #if DECODE_TROTEC - DPRINTLN("Attempting Trotec decode"); - if (decodeTrotec(results)) return true; + DPRINTLN("Attempting Trotec decode"); + if (decodeTrotec(results, offset)) return true; #endif // DECODE_TROTEC #if DECODE_DAIKIN160 - DPRINTLN("Attempting Daikin160 decode"); - if (decodeDaikin160(results)) return true; + DPRINTLN("Attempting Daikin160 decode"); + if (decodeDaikin160(results, offset)) return true; #endif // DECODE_DAIKIN160 #if DECODE_NEOCLIMA - DPRINTLN("Attempting Neoclima decode"); - if (decodeNeoclima(results)) return true; + DPRINTLN("Attempting Neoclima decode"); + if (decodeNeoclima(results, offset)) return true; #endif // DECODE_NEOCLIMA #if DECODE_DAIKIN176 - DPRINTLN("Attempting Daikin176 decode"); - if (decodeDaikin176(results)) return true; + DPRINTLN("Attempting Daikin176 decode"); + if (decodeDaikin176(results, offset)) return true; #endif // DECODE_DAIKIN176 #if DECODE_DAIKIN128 - DPRINTLN("Attempting Daikin128 decode"); - if (decodeDaikin128(results)) return true; + DPRINTLN("Attempting Daikin128 decode"); + if (decodeDaikin128(results, offset)) return true; #endif // DECODE_DAIKIN128 #if DECODE_AMCOR - DPRINTLN("Attempting Amcor decode"); - if (decodeAmcor(results)) return true; + DPRINTLN("Attempting Amcor decode"); + if (decodeAmcor(results, offset)) return true; #endif // DECODE_AMCOR #if DECODE_DAIKIN152 - DPRINTLN("Attempting Daikin152 decode"); - if (decodeDaikin152(results)) return true; + DPRINTLN("Attempting Daikin152 decode"); + if (decodeDaikin152(results, offset)) return true; #endif // DECODE_DAIKIN152 #if DECODE_MITSUBISHI136 - DPRINTLN("Attempting Mitsubishi136 decode"); - if (decodeMitsubishi136(results)) return true; + DPRINTLN("Attempting Mitsubishi136 decode"); + if (decodeMitsubishi136(results, offset)) return true; #endif // DECODE_MITSUBISHI136 + } // Typically new protocols are added above this line. #if DECODE_HASH // decodeHash returns a hash on any input. diff --git a/lib/IRremoteESP8266-2.7.3/src/IRrecv.h b/lib/IRremoteESP8266-2.7.4/src/IRrecv.h similarity index 63% rename from lib/IRremoteESP8266-2.7.3/src/IRrecv.h rename to lib/IRremoteESP8266-2.7.4/src/IRrecv.h index 2424f0463..60559981c 100644 --- a/lib/IRremoteESP8266-2.7.3/src/IRrecv.h +++ b/lib/IRremoteESP8266-2.7.4/src/IRrecv.h @@ -125,7 +125,8 @@ class IRrecv { ~IRrecv(void); // Destructor void setTolerance(const uint8_t percent = kTolerance); uint8_t getTolerance(void); - bool decode(decode_results *results, irparams_t *save = NULL); + bool decode(decode_results *results, irparams_t *save = NULL, + uint8_t max_skip = 0, uint16_t noise_floor = 0); void enableIRIn(const bool pullup = false); void disableIRIn(void); void resume(void); @@ -220,52 +221,64 @@ class IRrecv { const uint8_t tolerance = kUseDefTol, const int16_t excess = kMarkExcess, const bool MSBfirst = true); + void crudeNoiseFilter(decode_results *results, const uint16_t floor = 0); bool decodeHash(decode_results *results); #if (DECODE_NEC || DECODE_SHERWOOD || DECODE_AIWA_RC_T501 || SEND_SANYO) - bool decodeNEC(decode_results *results, uint16_t nbits = kNECBits, - bool strict = true); + bool decodeNEC(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kNECBits, const bool strict = true); #endif #if DECODE_ARGO - bool decodeArgo(decode_results *results, const uint16_t nbits = kArgoBits, - const bool strict = true); + bool decodeArgo(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kArgoBits, const bool strict = true); #endif // DECODE_ARGO #if DECODE_SONY - bool decodeSony(decode_results *results, uint16_t nbits = kSonyMinBits, - bool strict = false); + bool decodeSony(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kSonyMinBits, + const bool strict = false); #endif #if DECODE_SANYO // DISABLED due to poor quality. - // bool decodeSanyo(decode_results *results, + // bool decodeSanyo(decode_results *results, uint16_t offset = kStartOffset, // uint16_t nbits = kSanyoSA8650BBits, // bool strict = false); bool decodeSanyoLC7461(decode_results *results, - uint16_t nbits = kSanyoLC7461Bits, bool strict = true); + uint16_t offset = kStartOffset, + const uint16_t nbits = kSanyoLC7461Bits, + bool strict = true); #endif #if DECODE_MITSUBISHI - bool decodeMitsubishi(decode_results *results, - uint16_t nbits = kMitsubishiBits, bool strict = true); + bool decodeMitsubishi(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kMitsubishiBits, + const bool strict = true); #endif #if DECODE_MITSUBISHI2 bool decodeMitsubishi2(decode_results *results, - uint16_t nbits = kMitsubishiBits, bool strict = true); + uint16_t offset = kStartOffset, + const uint16_t nbits = kMitsubishiBits, + const bool strict = true); #endif #if DECODE_MITSUBISHI_AC bool decodeMitsubishiAC(decode_results *results, - uint16_t nbits = kMitsubishiACBits, - bool strict = false); + uint16_t offset = kStartOffset, + const uint16_t nbits = kMitsubishiACBits, + const bool strict = false); #endif #if DECODE_MITSUBISHI136 bool decodeMitsubishi136(decode_results *results, + uint16_t offset = kStartOffset, const uint16_t nbits = kMitsubishi136Bits, const bool strict = true); #endif #if DECODE_MITSUBISHI112 bool decodeMitsubishi112(decode_results *results, + uint16_t offset = kStartOffset, const uint16_t nbits = kMitsubishi112Bits, const bool strict = true); #endif #if DECODE_MITSUBISHIHEAVY - bool decodeMitsubishiHeavy(decode_results *results, const uint16_t nbits, + bool decodeMitsubishiHeavy(decode_results *results, + uint16_t offset = kStartOffset, + const uint16_t nbits = kMitsubishiHeavy152Bits, const bool strict = true); #endif #if (DECODE_RC5 || DECODE_R6 || DECODE_LASERTAG || DECODE_MWM) @@ -275,236 +288,276 @@ class IRrecv { uint8_t maxwidth = 3); #endif #if DECODE_RC5 - bool decodeRC5(decode_results *results, uint16_t nbits = kRC5XBits, - bool strict = true); + bool decodeRC5(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kRC5XBits, + const bool strict = true); #endif #if DECODE_RC6 - bool decodeRC6(decode_results *results, uint16_t nbits = kRC6Mode0Bits, - bool strict = false); + bool decodeRC6(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kRC6Mode0Bits, + const bool strict = false); #endif #if DECODE_RCMM - bool decodeRCMM(decode_results *results, uint16_t nbits = kRCMMBits, - bool strict = false); + bool decodeRCMM(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kRCMMBits, + const bool strict = false); #endif #if (DECODE_PANASONIC || DECODE_DENON) - bool decodePanasonic(decode_results *results, + bool decodePanasonic(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kPanasonicBits, const bool strict = false, const uint32_t manufacturer = kPanasonicManufacturer); #endif #if DECODE_LG - bool decodeLG(decode_results *results, uint16_t nbits = kLgBits, - bool strict = false); + bool decodeLG(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kLgBits, + const bool strict = false); #endif #if DECODE_INAX - bool decodeInax(decode_results *results, const uint16_t nbits = kInaxBits, + bool decodeInax(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kInaxBits, const bool strict = true); #endif // DECODE_INAX #if DECODE_JVC - bool decodeJVC(decode_results *results, uint16_t nbits = kJvcBits, - bool strict = true); + bool decodeJVC(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kJvcBits, + const bool strict = true); #endif #if DECODE_SAMSUNG - bool decodeSAMSUNG(decode_results *results, + bool decodeSAMSUNG(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kSamsungBits, const bool strict = true); #endif #if DECODE_SAMSUNG - bool decodeSamsung36(decode_results *results, + bool decodeSamsung36(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kSamsung36Bits, const bool strict = true); #endif #if DECODE_SAMSUNG_AC - bool decodeSamsungAC(decode_results *results, + bool decodeSamsungAC(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kSamsungAcBits, const bool strict = true); #endif #if DECODE_WHYNTER - bool decodeWhynter(decode_results *results, uint16_t nbits = kWhynterBits, - bool strict = true); + bool decodeWhynter(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kWhynterBits, + const bool strict = true); #endif #if DECODE_COOLIX - bool decodeCOOLIX(decode_results *results, uint16_t nbits = kCoolixBits, - bool strict = true); + bool decodeCOOLIX(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kCoolixBits, + const bool strict = true); #endif #if DECODE_DENON - bool decodeDenon(decode_results *results, uint16_t nbits = kDenonBits, - bool strict = true); + bool decodeDenon(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kDenonBits, + const bool strict = true); #endif #if DECODE_DISH - bool decodeDISH(decode_results *results, uint16_t nbits = kDishBits, - bool strict = true); + bool decodeDISH(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kDishBits, + const bool strict = true); #endif #if (DECODE_SHARP || DECODE_DENON) - bool decodeSharp(decode_results *results, const uint16_t nbits = kSharpBits, + bool decodeSharp(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kSharpBits, const bool strict = true, const bool expansion = true); #endif #if DECODE_SHARP_AC - bool decodeSharpAc(decode_results *results, + bool decodeSharpAc(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kSharpAcBits, const bool strict = true); #endif #if DECODE_AIWA_RC_T501 - bool decodeAiwaRCT501(decode_results *results, - uint16_t nbits = kAiwaRcT501Bits, bool strict = true); + bool decodeAiwaRCT501(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kAiwaRcT501Bits, + const bool strict = true); #endif #if DECODE_NIKAI - bool decodeNikai(decode_results *results, uint16_t nbits = kNikaiBits, - bool strict = true); + bool decodeNikai(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kNikaiBits, + const bool strict = true); #endif #if DECODE_MAGIQUEST - bool decodeMagiQuest(decode_results *results, uint16_t nbits = kMagiquestBits, - bool strict = true); + bool decodeMagiQuest(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kMagiquestBits, + const bool strict = true); #endif #if DECODE_KELVINATOR - bool decodeKelvinator(decode_results *results, - uint16_t nbits = kKelvinatorBits, bool strict = true); + bool decodeKelvinator(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kKelvinatorBits, + const bool strict = true); #endif #if DECODE_DAIKIN - bool decodeDaikin(decode_results *results, const uint16_t nbits = kDaikinBits, + bool decodeDaikin(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kDaikinBits, const bool strict = true); #endif #if DECODE_DAIKIN128 - bool decodeDaikin128(decode_results *results, + bool decodeDaikin128(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kDaikin128Bits, const bool strict = true); #endif // DECODE_DAIKIN128 #if DECODE_DAIKIN152 - bool decodeDaikin152(decode_results *results, + bool decodeDaikin152(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kDaikin152Bits, const bool strict = true); #endif // DECODE_DAIKIN152 #if DECODE_DAIKIN160 - bool decodeDaikin160(decode_results *results, + bool decodeDaikin160(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kDaikin160Bits, const bool strict = true); #endif // DECODE_DAIKIN160 #if DECODE_DAIKIN176 - bool decodeDaikin176(decode_results *results, + bool decodeDaikin176(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kDaikin176Bits, const bool strict = true); #endif // DECODE_DAIKIN176 #if DECODE_DAIKIN2 - bool decodeDaikin2(decode_results *results, uint16_t nbits = kDaikin2Bits, - bool strict = true); + bool decodeDaikin2(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kDaikin2Bits, + const bool strict = true); #endif #if DECODE_DAIKIN216 - bool decodeDaikin216(decode_results *results, + bool decodeDaikin216(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kDaikin216Bits, const bool strict = true); #endif #if DECODE_TOSHIBA_AC - bool decodeToshibaAC(decode_results *results, + bool decodeToshibaAC(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbytes = kToshibaACBits, const bool strict = true); #endif #if DECODE_TROTEC - bool decodeTrotec(decode_results *results, const uint16_t nbits = kTrotecBits, + bool decodeTrotec(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kTrotecBits, const bool strict = true); #endif // DECODE_TROTEC #if DECODE_MIDEA - bool decodeMidea(decode_results *results, uint16_t nbits = kMideaBits, - bool strict = true); + bool decodeMidea(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kMideaBits, + const bool strict = true); #endif #if DECODE_FUJITSU_AC - bool decodeFujitsuAC(decode_results *results, uint16_t nbits = kFujitsuAcBits, - bool strict = false); + bool decodeFujitsuAC(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kFujitsuAcBits, + const bool strict = false); #endif #if DECODE_LASERTAG - bool decodeLasertag(decode_results *results, uint16_t nbits = kLasertagBits, - bool strict = true); + bool decodeLasertag(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kLasertagBits, + const bool strict = true); #endif #if DECODE_CARRIER_AC - bool decodeCarrierAC(decode_results *results, uint16_t nbits = kCarrierAcBits, - bool strict = true); + bool decodeCarrierAC(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kCarrierAcBits, + const bool strict = true); #endif #if DECODE_GOODWEATHER bool decodeGoodweather(decode_results *results, + uint16_t offset = kStartOffset, const uint16_t nbits = kGoodweatherBits, const bool strict = true); #endif // DECODE_GOODWEATHER #if DECODE_GREE - bool decodeGree(decode_results *results, uint16_t nbits = kGreeBits, - bool strict = true); + bool decodeGree(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kGreeBits, + const bool strict = true); #endif #if (DECODE_HAIER_AC | DECODE_HAIER_AC_YRW02) - bool decodeHaierAC(decode_results *results, uint16_t nbits = kHaierACBits, - bool strict = true); + bool decodeHaierAC(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kHaierACBits, + const bool strict = true); #endif #if DECODE_HAIER_AC_YRW02 bool decodeHaierACYRW02(decode_results *results, - uint16_t nbits = kHaierACYRW02Bits, - bool strict = true); + uint16_t offset = kStartOffset, + const uint16_t nbits = kHaierACYRW02Bits, + const bool strict = true); #endif #if (DECODE_HITACHI_AC || DECODE_HITACHI_AC2) - bool decodeHitachiAC(decode_results *results, + bool decodeHitachiAC(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kHitachiAcBits, const bool strict = true); #endif #if DECODE_HITACHI_AC1 - bool decodeHitachiAC1(decode_results *results, + bool decodeHitachiAC1(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kHitachiAc1Bits, const bool strict = true); #endif #if DECODE_HITACHI_AC424 bool decodeHitachiAc424(decode_results *results, + uint16_t offset = kStartOffset, const uint16_t nbits = kHitachiAc424Bits, const bool strict = true); #endif // DECODE_HITACHI_AC424 #if DECODE_GICABLE - bool decodeGICable(decode_results *results, uint16_t nbits = kGicableBits, - bool strict = true); + bool decodeGICable(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kGicableBits, + const bool strict = true); #endif #if DECODE_WHIRLPOOL_AC bool decodeWhirlpoolAC(decode_results *results, + uint16_t offset = kStartOffset, const uint16_t nbits = kWhirlpoolAcBits, const bool strict = true); #endif #if DECODE_LUTRON - bool decodeLutron(decode_results *results, uint16_t nbits = kLutronBits, - bool strict = true); + bool decodeLutron(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kLutronBits, + const bool strict = true); #endif #if DECODE_ELECTRA_AC - bool decodeElectraAC(decode_results *results, uint16_t nbits = kElectraAcBits, - bool strict = true); + bool decodeElectraAC(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kElectraAcBits, + const bool strict = true); #endif #if DECODE_PANASONIC_AC bool decodePanasonicAC(decode_results *results, + uint16_t offset = kStartOffset, const uint16_t nbits = kPanasonicAcBits, const bool strict = true); #endif #if DECODE_PIONEER - bool decodePioneer(decode_results *results, + bool decodePioneer(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kPioneerBits, const bool strict = true); #endif #if DECODE_MWM - bool decodeMWM(decode_results *results, uint16_t nbits = 24, - bool strict = true); + bool decodeMWM(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = 24, + const bool strict = true); #endif #if DECODE_VESTEL_AC - bool decodeVestelAc(decode_results *results, + bool decodeVestelAc(decode_results *results, uint16_t offset = kStartOffset, const uint16_t nbits = kVestelAcBits, const bool strict = true); #endif #if DECODE_TECO - bool decodeTeco(decode_results *results, const uint16_t nbits = kTecoBits, + bool decodeTeco(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kTecoBits, const bool strict = false); #endif #if DECODE_LEGOPF - bool decodeLegoPf(decode_results *results, const uint16_t nbits = kLegoPfBits, + bool decodeLegoPf(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kLegoPfBits, const bool strict = true); #endif #if DECODE_NEOCLIMA -bool decodeNeoclima(decode_results *results, - const uint16_t nbits = kNeoclimaBits, - const bool strict = true); + bool decodeNeoclima(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kNeoclimaBits, + const bool strict = true); #endif // DECODE_NEOCLIMA #if DECODE_AMCOR -bool decodeAmcor(decode_results *results, - const uint16_t nbits = kAmcorBits, - const bool strict = true); + bool decodeAmcor(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kAmcorBits, + const bool strict = true); #endif // DECODE_AMCOR +#if DECODE_EPSON + bool decodeEpson(decode_results *results, uint16_t offset = kStartOffset, + const uint16_t nbits = kEpsonBits, + const bool strict = true); +#endif // DECODE_EPSON }; #endif // IRRECV_H_ diff --git a/lib/IRremoteESP8266-2.7.3/src/IRremoteESP8266.h b/lib/IRremoteESP8266-2.7.4/src/IRremoteESP8266.h similarity index 96% rename from lib/IRremoteESP8266-2.7.3/src/IRremoteESP8266.h rename to lib/IRremoteESP8266-2.7.4/src/IRremoteESP8266.h index eb8a67f5c..a048e23fc 100644 --- a/lib/IRremoteESP8266-2.7.3/src/IRremoteESP8266.h +++ b/lib/IRremoteESP8266-2.7.4/src/IRremoteESP8266.h @@ -52,7 +52,7 @@ #endif // UNIT_TEST // Library Version -#define _IRREMOTEESP8266_VERSION_ "2.7.3" +#define _IRREMOTEESP8266_VERSION_ "2.7.4" // Set the language & locale for the library. See the `locale` dir for options. #ifndef _IR_LOCALE_ @@ -565,6 +565,13 @@ #define SEND_HITACHI_AC424 _IR_ENABLE_DEFAULT_ #endif // SEND_HITACHI_AC424 +#ifndef DECODE_EPSON +#define DECODE_EPSON _IR_ENABLE_DEFAULT_ +#endif // DECODE_EPSON +#ifndef SEND_EPSON +#define SEND_EPSON _IR_ENABLE_DEFAULT_ +#endif // SEND_EPSON + #if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \ DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \ DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \ @@ -589,6 +596,22 @@ #define ALLOW_DELAY_CALLS true #endif // ALLOW_DELAY_CALLS +// Enable a run-time settable high-pass filter on captured data **before** +// trying any protocol decoding. +// i.e. Try to remove/merge any really short pulses detected in the raw data. +// Note: Even when this option is enabled, it is _off_ by default, and requires +// a user who knows what they are doing to enable it. +// The option to disable this feature is here if your project is _really_ +// tight on resources. i.e. Saves a small handful of bytes and cpu time. +// WARNING: If you use this feature at runtime, you can no longer trust the +// **raw** data captured. It will now have been slightly **cooked**! +// DANGER: If you set the `noise_floor` value too high, it **WILL** break +// decoding of some protocols. You have been warned. Here Be Dragons! +// +// See: `irrecv::decode()` in IRrecv.cpp for more info. +#ifndef ENABLE_NOISE_FILTER_OPTION +#define ENABLE_NOISE_FILTER_OPTION true +#endif // ENABLE_NOISE_FILTER_OPTION /* * Always add to the end of the list and should never remove entries * or change order. Projects may save the type number for later usage @@ -671,8 +694,9 @@ enum decode_type_t { MITSUBISHI112, HITACHI_AC424, SONY_38K, + EPSON, // 75 // Add new entries before this one, and update it to point to the last entry. - kLastDecodeType = SONY_38K, + kLastDecodeType = EPSON, }; // Message lengths & required repeat values @@ -720,6 +744,8 @@ const uint16_t kDenon48Bits = 48; const uint16_t kDenonLegacyBits = 14; const uint16_t kDishBits = 16; const uint16_t kDishMinRepeat = 3; +const uint16_t kEpsonBits = 32; +const uint16_t kEpsonMinRepeat = 2; const uint16_t kElectraAcStateLength = 13; const uint16_t kElectraAcBits = kElectraAcStateLength * 8; const uint16_t kElectraAcMinRepeat = kNoRepeat; diff --git a/lib/IRremoteESP8266-2.7.3/src/IRsend.cpp b/lib/IRremoteESP8266-2.7.4/src/IRsend.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.3/src/IRsend.cpp rename to lib/IRremoteESP8266-2.7.4/src/IRsend.cpp index 4bc16a75c..8bc12949b 100644 --- a/lib/IRremoteESP8266-2.7.3/src/IRsend.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/IRsend.cpp @@ -477,7 +477,8 @@ void IRsend::sendGeneric(const uint16_t headermark, const uint32_t headerspace, // // Ref: // examples/IRrecvDumpV2/IRrecvDumpV2.ino -void IRsend::sendRaw(uint16_t buf[], uint16_t len, uint16_t hz) { +void IRsend::sendRaw(const uint16_t buf[], const uint16_t len, + const uint16_t hz) { // Set IR carrier frequency enableIROut(hz); for (uint16_t i = 0; i < len; i++) { @@ -517,6 +518,8 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) { return kSonyMinRepeat; case SONY_38K: return kSonyMinRepeat + 1; + case EPSON: + return kEpsonMinRepeat; default: return kNoRepeat; } @@ -558,6 +561,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) { case LG2: return 28; case CARRIER_AC: + case EPSON: case NEC: case NEC_LIKE: case SAMSUNG: @@ -687,6 +691,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data, sendDISH(data, nbits, min_repeat); break; #endif +#if SEND_EPSON + case EPSON: + sendEpson(data, nbits, min_repeat); + break; +#endif #if SEND_GICABLE case GICABLE: sendGICable(data, nbits, min_repeat); diff --git a/lib/IRremoteESP8266-2.7.3/src/IRsend.h b/lib/IRremoteESP8266-2.7.4/src/IRsend.h similarity index 99% rename from lib/IRremoteESP8266-2.7.3/src/IRsend.h rename to lib/IRremoteESP8266-2.7.4/src/IRsend.h index ff801210d..902f22010 100644 --- a/lib/IRremoteESP8266-2.7.3/src/IRsend.h +++ b/lib/IRremoteESP8266-2.7.4/src/IRsend.h @@ -158,7 +158,7 @@ class IRsend { VIRTUAL uint16_t mark(uint16_t usec); VIRTUAL void space(uint32_t usec); int8_t calibrate(uint16_t hz = 38000U); - void sendRaw(uint16_t buf[], uint16_t len, uint16_t hz); + void sendRaw(const uint16_t buf[], const uint16_t len, const uint16_t hz); void sendData(uint16_t onemark, uint32_t onespace, uint16_t zeromark, uint32_t zerospace, uint64_t data, uint16_t nbits, bool MSBfirst = true); @@ -535,7 +535,10 @@ class IRsend { const uint16_t nbytes = kAmcorStateLength, const uint16_t repeat = kAmcorDefaultRepeat); #endif // SEND_AMCOR - +#if SEND_EPSON + void sendEpson(uint64_t data, uint16_t nbits = kEpsonBits, + uint16_t repeat = kEpsonMinRepeat); +#endif protected: #ifdef UNIT_TEST diff --git a/lib/IRremoteESP8266-2.7.3/src/IRtext.cpp b/lib/IRremoteESP8266-2.7.4/src/IRtext.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/IRtext.cpp rename to lib/IRremoteESP8266-2.7.4/src/IRtext.cpp diff --git a/lib/IRremoteESP8266-2.7.3/src/IRtext.h b/lib/IRremoteESP8266-2.7.4/src/IRtext.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/IRtext.h rename to lib/IRremoteESP8266-2.7.4/src/IRtext.h diff --git a/lib/IRremoteESP8266-2.7.3/src/IRtimer.cpp b/lib/IRremoteESP8266-2.7.4/src/IRtimer.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/IRtimer.cpp rename to lib/IRremoteESP8266-2.7.4/src/IRtimer.cpp diff --git a/lib/IRremoteESP8266-2.7.3/src/IRtimer.h b/lib/IRremoteESP8266-2.7.4/src/IRtimer.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/IRtimer.h rename to lib/IRremoteESP8266-2.7.4/src/IRtimer.h diff --git a/lib/IRremoteESP8266-2.7.3/src/IRutils.cpp b/lib/IRremoteESP8266-2.7.4/src/IRutils.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.3/src/IRutils.cpp rename to lib/IRremoteESP8266-2.7.4/src/IRutils.cpp index bbb9ed491..230b24809 100644 --- a/lib/IRremoteESP8266-2.7.3/src/IRutils.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/IRutils.cpp @@ -125,6 +125,8 @@ decode_type_t strToDecodeType(const char * const str) { return decode_type_t::DISH; else if (!strcasecmp(str, "ELECTRA_AC")) return decode_type_t::ELECTRA_AC; + else if (!strcasecmp(str, "EPSON")) + return decode_type_t::EPSON; else if (!strcasecmp(str, "FUJITSU_AC")) return decode_type_t::FUJITSU_AC; else if (!strcasecmp(str, "GICABLE")) @@ -310,6 +312,9 @@ String typeToString(const decode_type_t protocol, const bool isRepeat) { case ELECTRA_AC: result = F("ELECTRA_AC"); break; + case EPSON: + result = F("EPSON"); + break; case FUJITSU_AC: result = F("FUJITSU_AC"); break; diff --git a/lib/IRremoteESP8266-2.7.3/src/IRutils.h b/lib/IRremoteESP8266-2.7.4/src/IRutils.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/IRutils.h rename to lib/IRremoteESP8266-2.7.4/src/IRutils.h diff --git a/lib/IRremoteESP8266-2.7.3/src/i18n.h b/lib/IRremoteESP8266-2.7.4/src/i18n.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/i18n.h rename to lib/IRremoteESP8266-2.7.4/src/i18n.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Aiwa.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Aiwa.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/src/ir_Aiwa.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Aiwa.cpp index 70dbc85b2..95dffe1aa 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Aiwa.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Aiwa.cpp @@ -53,6 +53,8 @@ void IRsend::sendAiwaRCT501(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kAiwaRcT501Bits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -69,8 +71,8 @@ void IRsend::sendAiwaRCT501(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Ref: // http://www.sbprojects.com/knowledge/ir/nec.php -bool IRrecv::decodeAiwaRCT501(decode_results *results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeAiwaRCT501(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { // Compliance if (strict && nbits != kAiwaRcT501Bits) return false; // Doesn't match our protocol defn. @@ -82,7 +84,7 @@ bool IRrecv::decodeAiwaRCT501(decode_results *results, uint16_t nbits, return false; // We can't possibly match something that big. // Decode it as a much bigger (non-standard) NEC message, so we have to turn // off strict mode checking for NEC. - if (!decodeNEC(results, expected_nbits, false)) + if (!decodeNEC(results, offset, expected_nbits, false)) return false; // The NEC decode had a problem, so we should too. uint16_t actual_bits = results->bits; new_data = results->value; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Amcor.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Amcor.cpp similarity index 96% rename from lib/IRremoteESP8266-2.7.3/src/ir_Amcor.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Amcor.cpp index b36c6d15a..b29933906 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Amcor.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Amcor.cpp @@ -56,6 +56,8 @@ void IRsend::sendAmcor(const unsigned char data[], const uint16_t nbytes, // Decode the supplied Amcor HVAC message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. // Typically kAmcorBits. // strict: Flag to indicate if we strictly adhere to the specification. @@ -64,15 +66,13 @@ void IRsend::sendAmcor(const unsigned char data[], const uint16_t nbytes, // // Status: STABLE / Reported as working. // -bool IRrecv::decodeAmcor(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + kHeader - 1) +bool IRrecv::decodeAmcor(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= 2 * nbits + kHeader - 1 + offset) return false; // Can't possibly be a valid Amcor message. if (strict && nbits != kAmcorBits) return false; // We expect Amcor to be 64 bits of message. - uint16_t offset = kStartOffset; - uint16_t used; // Header + Data Block (64 bits) + Footer used = matchGeneric(results->rawbuf + offset, results->state, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Amcor.h b/lib/IRremoteESP8266-2.7.4/src/ir_Amcor.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Amcor.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Amcor.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Argo.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Argo.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Argo.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Argo.cpp index f1806ebcd..11e8336e3 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Argo.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Argo.cpp @@ -378,6 +378,8 @@ String IRArgoAC::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kArgoBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -388,12 +390,11 @@ String IRArgoAC::toString(void) { // Note: // This decoder is based soley off sendArgo(). We have no actual captures // to test this against. If you have one of these units, please let us know. -bool IRrecv::decodeArgo(decode_results *results, const uint16_t nbits, +bool IRrecv::decodeArgo(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kArgoBits) return false; - uint16_t offset = kStartOffset; - // Match Header + Data if (!matchGeneric(results->rawbuf + offset, results->state, results->rawlen - offset, nbits, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Argo.h b/lib/IRremoteESP8266-2.7.4/src/ir_Argo.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Argo.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Argo.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Carrier.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Carrier.cpp similarity index 92% rename from lib/IRremoteESP8266-2.7.3/src/ir_Carrier.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Carrier.cpp index e31ddd55f..7b2b00d58 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Carrier.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Carrier.cpp @@ -53,6 +53,8 @@ void IRsend::sendCarrierAC(uint64_t data, uint16_t nbits, uint16_t repeat) { // i.e. normal + inverted + normal // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. // Typically kCarrierAcBits. // strict: Flag to indicate if we strictly adhere to the specification. @@ -61,16 +63,15 @@ void IRsend::sendCarrierAC(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Status: ALPHA / Untested. // -bool IRrecv::decodeCarrierAC(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < ((2 * nbits + kHeader + kFooter) * 3) - 1) +bool IRrecv::decodeCarrierAC(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < ((2 * nbits + kHeader + kFooter) * 3) - 1 + offset) return false; // Can't possibly be a valid Carrier message. if (strict && nbits != kCarrierAcBits) return false; // We expect Carrier to be 32 bits of message. uint64_t data = 0; uint64_t prev_data = 0; - uint16_t offset = kStartOffset; for (uint8_t i = 0; i < 3; i++) { prev_data = data; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Coolix.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Coolix.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_Coolix.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Coolix.cpp index 8b184bf9f..a8d98301c 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Coolix.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Coolix.cpp @@ -130,6 +130,7 @@ void IRCoolixAC::send(const uint16_t repeat) { uint32_t IRCoolixAC::getRaw() { return remote_state; } void IRCoolixAC::setRaw(const uint32_t new_code) { + powerFlag = true; // Everything that is not the special power off mesg is On. if (!handleSpecialState(new_code)) { // it isn`t special so might affect Temp|mode|Fan if (new_code == kCoolixCmdFan) { @@ -578,17 +579,19 @@ String IRCoolixAC::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kCoolixBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: BETA / Probably working. -bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { // The protocol sends the data normal + inverted, alternating on // each byte. Hence twice the number of expected data bits. - if (results->rawlen < 2 * 2 * nbits + kHeader + kFooter - 1) + if (results->rawlen <= 2 * 2 * nbits + kHeader + kFooter - 1 + offset) return false; // Can't possibly be a valid COOLIX message. if (strict && nbits != kCoolixBits) return false; // Not strictly a COOLIX message. @@ -597,7 +600,6 @@ bool IRrecv::decodeCOOLIX(decode_results *results, uint16_t nbits, uint64_t data = 0; uint64_t inverted = 0; - uint16_t offset = kStartOffset; if (nbits > sizeof(data) * 8) return false; // We can't possibly capture a Coolix packet that big. diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Coolix.h b/lib/IRremoteESP8266-2.7.4/src/ir_Coolix.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Coolix.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Coolix.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Daikin.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Daikin.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_Daikin.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Daikin.cpp index 678e43f88..4941fe977 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Daikin.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Daikin.cpp @@ -513,6 +513,8 @@ String IRDaikinESP::toString(void) { // Decode the supplied Daikin A/C message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. (kDaikinBits) // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -522,17 +524,17 @@ String IRDaikinESP::toString(void) { // // Ref: // https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -bool IRrecv::decodeDaikin(decode_results *results, const uint16_t nbits, - const bool strict) { +bool IRrecv::decodeDaikin(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { // Is there enough data to match successfully? if (results->rawlen < (2 * (nbits + kDaikinHeaderLength) + - kDaikinSections * (kHeader + kFooter) + kFooter - 1)) + kDaikinSections * (kHeader + kFooter) + kFooter - 1) + + offset) return false; // Compliance if (strict && nbits != kDaikinBits) return false; - uint16_t offset = kStartOffset; match_result_t data_result; // Header #1 - Doesn't count as data. @@ -1206,6 +1208,8 @@ String IRDaikin2::toString(void) { // Decode the supplied Daikin2 A/C message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. (kDaikin2Bits) // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -1219,15 +1223,14 @@ String IRDaikin2::toString(void) { // // Ref: // https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/tree/master/IRremote -bool IRrecv::decodeDaikin2(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * (nbits + kHeader + kFooter) + kHeader - 1) +bool IRrecv::decodeDaikin2(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) + kHeader - 1 + offset) return false; // Compliance if (strict && nbits != kDaikin2Bits) return false; - uint16_t offset = kStartOffset; const uint8_t ksectionSize[kDaikin2Sections] = {kDaikin2Section1Length, kDaikin2Section2Length}; @@ -1552,6 +1555,8 @@ String IRDaikin216::toString(void) { // Decode the supplied Daikin 216 bit A/C message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. (kDaikin216Bits) // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -1565,15 +1570,14 @@ String IRDaikin216::toString(void) { // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/689 // https://github.com/danny-source/Arduino_DY_IRDaikin -bool IRrecv::decodeDaikin216(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) +bool IRrecv::decodeDaikin216(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1 + offset) return false; // Compliance if (strict && nbits != kDaikin216Bits) return false; - uint16_t offset = kStartOffset; const uint8_t ksectionSize[kDaikin216Sections] = {kDaikin216Section1Length, kDaikin216Section2Length}; // Sections @@ -1905,6 +1909,8 @@ String IRDaikin160::toString(void) { // Decode the supplied Daikin 160 bit A/C message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. (kDaikin160Bits) // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -1917,15 +1923,14 @@ String IRDaikin160::toString(void) { // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/731 -bool IRrecv::decodeDaikin160(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) +bool IRrecv::decodeDaikin160(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1 + offset) return false; // Compliance if (strict && nbits != kDaikin160Bits) return false; - uint16_t offset = kStartOffset; const uint8_t ksectionSize[kDaikin160Sections] = {kDaikin160Section1Length, kDaikin160Section2Length}; @@ -2268,6 +2273,8 @@ String IRDaikin176::toString(void) { // Decode the supplied Daikin 176 bit A/C message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. (kDaikin176Bits) // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -2279,15 +2286,15 @@ String IRDaikin176::toString(void) { // Status: BETA / Probably works. // -bool IRrecv::decodeDaikin176(decode_results *results, const uint16_t nbits, +bool IRrecv::decodeDaikin176(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { - if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1 + offset) return false; // Compliance if (strict && nbits != kDaikin176Bits) return false; - uint16_t offset = kStartOffset; const uint8_t ksectionSize[kDaikin176Sections] = {kDaikin176Section1Length, kDaikin176Section2Length}; @@ -2762,6 +2769,8 @@ stdAc::state_t IRDaikin128::toCommon(const stdAc::state_t *prev) { // Decode the supplied Daikin 128 bit A/C message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. (kDaikin128Bits) // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -2773,17 +2782,15 @@ stdAc::state_t IRDaikin128::toCommon(const stdAc::state_t *prev) { // Status: STABLE / Known Working. // // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/827 -bool IRrecv::decodeDaikin128(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * (nbits + kHeader) + kFooter - 1) +bool IRrecv::decodeDaikin128(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader) + kFooter - 1 + offset) return false; if (nbits / 8 <= kDaikin128SectionLength) return false; // Compliance if (strict && nbits != kDaikin128Bits) return false; - uint16_t offset = kStartOffset; - // Leader for (uint8_t i = 0; i < 2; i++) { if (!matchMark(results->rawbuf[offset++], kDaikin128LeaderMark, @@ -2862,6 +2869,8 @@ void IRsend::sendDaikin152(const unsigned char data[], const uint16_t nbytes, // Decode the supplied Daikin 152 bit A/C message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. (kDaikin152Bits) // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -2873,16 +2882,15 @@ void IRsend::sendDaikin152(const unsigned char data[], const uint16_t nbytes, // Status: STABLE / Known working. // // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/873 -bool IRrecv::decodeDaikin152(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * (5 + nbits + kFooter) + kHeader - 1) +bool IRrecv::decodeDaikin152(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * (5 + nbits + kFooter) + kHeader - 1 + offset) return false; if (nbits / 8 < kDaikin152StateLength) return false; // Compliance if (strict && nbits != kDaikin152Bits) return false; - uint16_t offset = kStartOffset; uint16_t used; // Leader diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Daikin.h b/lib/IRremoteESP8266-2.7.4/src/ir_Daikin.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Daikin.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Daikin.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Denon.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Denon.cpp similarity index 89% rename from lib/IRremoteESP8266-2.7.3/src/ir_Denon.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Denon.cpp index 8a32ae261..bd4940714 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Denon.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Denon.cpp @@ -64,7 +64,10 @@ void IRsend::sendDenon(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Expected nr. of data bits. (Typically kDenonBits) +// strict: Flag to indicate if we strictly adhere to the specification. // Returns: // boolean: True if it can decode it, false if it can't. // @@ -72,7 +75,8 @@ void IRsend::sendDenon(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Denon.cpp -bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) { +bool IRrecv::decodeDenon(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { // Compliance if (strict) { switch (nbits) { @@ -92,15 +96,14 @@ bool IRrecv::decodeDenon(decode_results *results, uint16_t nbits, bool strict) { // Ditto for Panasonic, it's the same except for a different // manufacturer code. - if (!decodeSharp(results, nbits, true, false) && - !decodePanasonic(results, nbits, true, kDenonManufacturer)) { + if (!decodeSharp(results, offset, nbits, true, false) && + !decodePanasonic(results, offset, nbits, true, kDenonManufacturer)) { // We couldn't decode it as expected, so try the old legacy method. // NOTE: I don't think this following protocol actually exists. // Looks like a partial version of the Sharp protocol. if (strict && nbits != kDenonLegacyBits) return false; uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, &data, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Dish.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Dish.cpp similarity index 93% rename from lib/IRremoteESP8266-2.7.3/src/ir_Dish.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Dish.cpp index b217da763..834ceda04 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Dish.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Dish.cpp @@ -69,6 +69,8 @@ void IRsend::sendDISH(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. Typically kDishBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -84,13 +86,11 @@ void IRsend::sendDISH(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://www.hifi-remote.com/wiki/index.php?title=Dish // http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Dish.cpp -bool IRrecv::decodeDISH(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) - return false; // Not enough entries to be valid. +bool IRrecv::decodeDISH(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kDishBits) return false; // Not strictly compliant. uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, &data, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Electra.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Electra.cpp similarity index 88% rename from lib/IRremoteESP8266-2.7.3/src/ir_Electra.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Electra.cpp index e423bfa0a..16c753f35 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Electra.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Electra.cpp @@ -66,7 +66,7 @@ IRElectraAc::IRElectraAc(const uint16_t pin, const bool inverted, void IRElectraAc::stateReset(void) { for (uint8_t i = 1; i < kElectraAcStateLength - 2; i++) remote_state[i] = 0; remote_state[0] = 0xC3; - remote_state[11] = 0x08; + remote_state[11] = kElectraAcLightToggleOff; // [12] is the checksum. } @@ -233,6 +233,30 @@ bool IRElectraAc::getSwingH(void) { kElectraAcSwingSize); } +void IRElectraAc::setLightToggle(const bool on) { + remote_state[11] = on ? kElectraAcLightToggleOn : kElectraAcLightToggleOff; +} + +bool IRElectraAc::getLightToggle(void) { + return (remote_state[11] & kElectraAcLightToggleMask) == + kElectraAcLightToggleMask; +} + +void IRElectraAc::setClean(const bool on) { + setBit(&remote_state[9], kElectraAcCleanOffset, on); +} + +bool IRElectraAc::getClean(void) { + return GETBIT8(remote_state[9], kElectraAcCleanOffset); +} + +void IRElectraAc::setTurbo(const bool on) { + setBit(&remote_state[5], kElectraAcTurboOffset, on); +} + +bool IRElectraAc::getTurbo(void) { + return GETBIT8(remote_state[5], kElectraAcTurboOffset); +} // Convert the A/C state to it's common equivalent. stdAc::state_t IRElectraAc::toCommon(void) { stdAc::state_t result; @@ -246,13 +270,13 @@ stdAc::state_t IRElectraAc::toCommon(void) { : stdAc::swingv_t::kOff; result.swingh = this->getSwingH() ? stdAc::swingh_t::kAuto : stdAc::swingh_t::kOff; + result.light = this->getLightToggle(); + result.turbo = this->getTurbo(); + result.clean = this->getClean(); // Not supported. result.model = -1; // No models used. result.quiet = false; - result.turbo = false; result.econo = false; - result.clean = false; - result.light = false; result.filter = false; result.beep = false; result.sleep = -1; @@ -263,7 +287,7 @@ stdAc::state_t IRElectraAc::toCommon(void) { // Convert the internal state into a human readable string. String IRElectraAc::toString(void) { String result = ""; - result.reserve(80); // Reserve some heap for the string to reduce fragging. + result.reserve(130); // Reserve some heap for the string to reduce fragging. result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kElectraAcAuto, kElectraAcCool, kElectraAcHeat, kElectraAcDry, kElectraAcFan); @@ -273,6 +297,9 @@ String IRElectraAc::toString(void) { kElectraAcFanMed); result += addBoolToString(getSwingV(), kSwingVStr); result += addBoolToString(getSwingH(), kSwingHStr); + result += addLabeledString(getLightToggle() ? kToggleStr : "-", kLightStr); + result += addBoolToString(getClean(), kCleanStr); + result += addBoolToString(getTurbo(), kTurboStr); return result; } @@ -281,6 +308,8 @@ String IRElectraAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kElectraAcBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -288,14 +317,14 @@ String IRElectraAc::toString(void) { // // Status: STABLE / Known working. // -bool IRrecv::decodeElectraAC(decode_results *results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeElectraAC(decode_results *results, uint16_t offset, + const uint16_t nbits, + const bool strict) { if (strict) { if (nbits != kElectraAcBits) return false; // Not strictly a ELECTRA_AC message. } - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, results->state, results->rawlen - offset, nbits, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Electra.h b/lib/IRremoteESP8266-2.7.4/src/ir_Electra.h similarity index 81% rename from lib/IRremoteESP8266-2.7.3/src/ir_Electra.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Electra.h index a120bcd28..2d5fe09f5 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Electra.h +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Electra.h @@ -50,6 +50,10 @@ const uint8_t kElectraAcFanAuto = 0b101; const uint8_t kElectraAcFanLow = 0b011; const uint8_t kElectraAcFanMed = 0b010; const uint8_t kElectraAcFanHigh = 0b001; +// state[5] +// TurboMask = 0b01000000; +const uint8_t kElectraAcTurboOffset = 6; + // state[6] // Mode 0b11100000 const uint8_t kElectraAcModeOffset = 5; @@ -59,7 +63,18 @@ const uint8_t kElectraAcDry = 0b010; const uint8_t kElectraAcHeat = 0b100; const uint8_t kElectraAcFan = 0b110; // state[9] -const uint8_t kElectraAcPowerOffset = 5; +// +const uint8_t kElectraAcCleanOffset = 2; // Bit 0b00000100 +const uint8_t kElectraAcPowerOffset = 5; // Bit 0b00100000 +// state[11] +// +const uint8_t kElectraAcLightToggleOn = 0x15; +// Light has known ON values of 0x15 (0b00010101) or 0x19 (0b00011001) +// Thus common bits ON are: 0b00010001 (0x11) +// We will use this for the getLightToggle() test. +const uint8_t kElectraAcLightToggleMask = 0x11; +// and known OFF values of 0x08 (0b00001000) & 0x05 (0x00000101) +const uint8_t kElectraAcLightToggleOff = 0x08; // Classes @@ -88,6 +103,12 @@ class IRElectraAc { bool getSwingV(void); void setSwingH(const bool on); bool getSwingH(void); + void setClean(const bool on); + bool getClean(void); + void setLightToggle(const bool on); + bool getLightToggle(void); + void setTurbo(const bool on); + bool getTurbo(void); uint8_t* getRaw(void); void setRaw(const uint8_t new_code[], const uint16_t length = kElectraAcStateLength); diff --git a/lib/IRremoteESP8266-2.7.4/src/ir_Epson.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Epson.cpp new file mode 100644 index 000000000..40973a947 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Epson.cpp @@ -0,0 +1,114 @@ +// Copyright 2020 David Conran + +// Epson is an NEC-like protocol, except it doesn't use the NEC style repeat. + +#define __STDC_LIMIT_MACROS +#include +#include +#include "IRrecv.h" +#include "IRsend.h" +#include "IRutils.h" +#include "ir_NEC.h" + +#if SEND_EPSON +// Send an Epson formatted message. +// +// Args: +// data: The message to be sent. +// nbits: The number of bits of the message to be sent. Typically kEpsonBits. +// repeat: The number of times the command is to be repeated. +// +// Status: Beta / Probably works. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/1034 +void IRsend::sendEpson(uint64_t data, uint16_t nbits, uint16_t repeat) { + sendGeneric(kNecHdrMark, kNecHdrSpace, kNecBitMark, kNecOneSpace, kNecBitMark, + kNecZeroSpace, kNecBitMark, kNecMinGap, kNecMinCommandLength, + data, nbits, 38, true, repeat, 33); +} + +#endif // SEND_EPSON + +#if DECODE_EPSON +// Decode the supplied Epson message. +// +// Args: +// results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. +// nbits: The number of data bits to expect. Typically kNECBits. +// strict: Flag indicating if we should perform strict matching. +// Returns: +// boolean: True if it can decode it, false if it can't. +// +// Status: Beta / Probably works. +// +// Notes: +// Experimental data indicates there are at least three +// messages (first + 2 repeats). We only require the first + a single repeat +// to match. This helps us distinguish it from NEC messages which are near +// identical. +// +// Ref: +// https://github.com/crankyoldgit/IRremoteESP8266/issues/1034 +bool IRrecv::decodeEpson(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + const uint8_t kEpsonMinMesgsForDecode = 2; + + if (results->rawlen < kEpsonMinMesgsForDecode * (2 * nbits + kHeader + + kFooter) + offset - 1) + return false; // Can't possibly be a valid Epson message. + if (strict && nbits != kEpsonBits) + return false; // Not strictly an Epson message. + + uint64_t data = 0; + uint64_t first_data = 0; + bool first = true; + + for (uint8_t i = 0; i < kEpsonMinMesgsForDecode; i++) { + // Match Header + Data + Footer + uint16_t delta = matchGeneric(results->rawbuf + offset, &data, + results->rawlen - offset, nbits, + kNecHdrMark, kNecHdrSpace, + kNecBitMark, kNecOneSpace, + kNecBitMark, kNecZeroSpace, + kNecBitMark, kNecMinGap, true); + if (!delta) return false; + offset += delta; + if (first) + first_data = data; + else if (data != first_data) return false; + first = false; // No longer the first message. + } + // Compliance + // Calculate command and optionally enforce integrity checking. + uint8_t command = (data & 0xFF00) >> 8; + // Command is sent twice, once as plain and then inverted. + if ((command ^ 0xFF) != (data & 0xFF)) { + if (strict) return false; // Command integrity failed. + command = 0; // The command value isn't valid, so default to zero. + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = EPSON; + // Epson command and address are technically in LSB first order so the + // final versions have to be reversed. + results->command = reverseBits(command, 8); + // Normal Epson (NEC) protocol has an 8 bit address sent, + // followed by it inverted. + uint8_t address = (data & 0xFF000000) >> 24; + uint8_t address_inverted = (data & 0x00FF0000) >> 16; + if (address == (address_inverted ^ 0xFF)) + // Inverted, so it is normal Epson (NEC) protocol. + results->address = reverseBits(address, 8); + else + // Not inverted, so must be Extended Epson (NEC) protocol, + // thus 16 bit address. + results->address = reverseBits((data >> 16) & UINT16_MAX, 16); + results->repeat = !first; + return true; +} +#endif // DECODE_EPSON diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Fujitsu.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Fujitsu.cpp index 4b0095b1e..583a441ba 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Fujitsu.cpp @@ -684,22 +684,25 @@ String IRFujitsuAC::toString(void) { // Places successful decode information in the results pointer. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kFujitsuAcBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: ALPHA / Untested. +// Status: STABLE / Working. // // Ref: // -bool IRrecv::decodeFujitsuAC(decode_results* results, uint16_t nbits, - bool strict) { - uint16_t offset = kStartOffset; +bool IRrecv::decodeFujitsuAC(decode_results* results, uint16_t offset, + const uint16_t nbits, + const bool strict) { uint16_t dataBitsSoFar = 0; // Have we got enough data to successfully decode? - if (results->rawlen < (2 * kFujitsuAcMinBits) + kHeader + kFooter - 1) + if (results->rawlen < (2 * kFujitsuAcMinBits) + kHeader + kFooter - 1 + + offset) return false; // Can't possibly be a valid message. // Compliance diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.h b/lib/IRremoteESP8266-2.7.4/src/ir_Fujitsu.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Fujitsu.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Fujitsu.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_GICable.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_GICable.cpp similarity index 92% rename from lib/IRremoteESP8266-2.7.3/src/ir_GICable.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_GICable.cpp index 6b3849b4c..ef68199cb 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_GICable.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_GICable.cpp @@ -58,19 +58,20 @@ void IRsend::sendGICable(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kGicableBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: Alpha / Not tested against a real device. -bool IRrecv::decodeGICable(decode_results *results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeGICable(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kGicableBits) return false; // Not strictly an GICABLE message. uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer uint16_t used; used = matchGeneric(results->rawbuf + offset, &data, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_GlobalCache.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_GlobalCache.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_GlobalCache.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_GlobalCache.cpp diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Goodweather.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Goodweather.cpp index 4c5aa3513..8b7e0b76e 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Goodweather.cpp @@ -370,23 +370,24 @@ String IRGoodweatherAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kGoodweatherBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: ALPHA / Untested. -bool IRrecv::decodeGoodweather(decode_results* results, +bool IRrecv::decodeGoodweather(decode_results* results, uint16_t offset, const uint16_t nbits, const bool strict) { - if (results->rawlen < 2 * (2 * nbits) + kHeader + 2 * kFooter - 1) + if (results->rawlen < 2 * (2 * nbits) + kHeader + 2 * kFooter - 1 + offset) return false; // Can't possibly be a valid Goodweather message. if (strict && nbits != kGoodweatherBits) return false; // Not strictly a Goodweather message. uint64_t dataSoFar = 0; uint16_t dataBitsSoFar = 0; - uint16_t offset = kStartOffset; match_result_t data_result; // Header diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.h b/lib/IRremoteESP8266-2.7.4/src/ir_Goodweather.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Goodweather.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Goodweather.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Gree.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Gree.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Gree.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Gree.cpp index 2dbebe84b..735e3b88c 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Gree.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Gree.cpp @@ -513,21 +513,22 @@ String IRGreeAC::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kGreeBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: ALPHA / Untested. -bool IRrecv::decodeGree(decode_results* results, uint16_t nbits, bool strict) { - if (results->rawlen < - 2 * (nbits + kGreeBlockFooterBits) + (kHeader + kFooter + 1)) +// Status: STABLE / Working. +bool IRrecv::decodeGree(decode_results* results, uint16_t offset, + const uint16_t nbits, bool const strict) { + if (results->rawlen <= + 2 * (nbits + kGreeBlockFooterBits) + (kHeader + kFooter + 1) - 1 + offset) return false; // Can't possibly be a valid Gree message. if (strict && nbits != kGreeBits) return false; // Not strictly a Gree message. - uint16_t offset = kStartOffset; - // There are two blocks back-to-back in a full Gree IR message // sequence. diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Gree.h b/lib/IRremoteESP8266-2.7.4/src/ir_Gree.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Gree.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Gree.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Haier.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Haier.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_Haier.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Haier.cpp index ac8be71ac..cac4320cf 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Haier.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Haier.cpp @@ -853,6 +853,8 @@ String IRHaierACYRW02::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kHaierACBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -860,18 +862,16 @@ String IRHaierACYRW02::toString(void) { // // Status: STABLE / Known to be working. // -bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeHaierAC(decode_results* results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict) { if (nbits != kHaierACBits) return false; // Not strictly a HAIER_AC message. } - if (results->rawlen < (2 * nbits + kHeader) + kFooter - 1) + if (results->rawlen <= (2 * nbits + kHeader) + kFooter - 1 + offset) return false; // Can't possibly be a valid HAIER_AC message. - uint16_t offset = kStartOffset; - // Pre-Header if (!matchMark(results->rawbuf[offset++], kHaierAcHdr)) return false; if (!matchSpace(results->rawbuf[offset++], kHaierAcHdr)) return false; @@ -903,6 +903,8 @@ bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kHaierACYRW02Bits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -910,15 +912,15 @@ bool IRrecv::decodeHaierAC(decode_results* results, uint16_t nbits, // // Status: BETA / Appears to be working. // -bool IRrecv::decodeHaierACYRW02(decode_results* results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeHaierACYRW02(decode_results* results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict) { if (nbits != kHaierACYRW02Bits) return false; // Not strictly a HAIER_AC_YRW02 message. } // The protocol is almost exactly the same as HAIER_AC - if (!decodeHaierAC(results, nbits, false)) return false; + if (!decodeHaierAC(results, offset, nbits, false)) return false; // Compliance if (strict) { diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Haier.h b/lib/IRremoteESP8266-2.7.4/src/ir_Haier.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Haier.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Haier.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Hitachi.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Hitachi.cpp index fcbcb5fec..02489d010 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Hitachi.cpp @@ -359,13 +359,15 @@ String IRHitachiAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. // Typically kHitachiAcBits, kHitachiAc1Bits, kHitachiAc2Bits // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: ALPHA / Untested. +// Status: BETA / Probably works. // // Supported devices: // Hitachi A/C Series VI (Circa 2007) / Remote: LT0541-HTA @@ -373,11 +375,10 @@ String IRHitachiAc::toString(void) { // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/417 // https://github.com/crankyoldgit/IRremoteESP8266/issues/453 -bool IRrecv::decodeHitachiAC(decode_results *results, const uint16_t nbits, - const bool strict) { +bool IRrecv::decodeHitachiAC(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { const uint8_t k_tolerance = _tolerance + 5; - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) - return false; // Can't possibly be a valid HitachiAC message. + if (strict) { switch (nbits) { case kHitachiAcBits: @@ -388,7 +389,6 @@ bool IRrecv::decodeHitachiAC(decode_results *results, const uint16_t nbits, return false; // Not strictly a Hitachi message. } } - uint16_t offset = kStartOffset; uint16_t hmark; uint32_t hspace; if (nbits == kHitachiAc1Bits) { @@ -475,6 +475,8 @@ void IRsend::sendHitachiAc424(const uint8_t data[], const uint16_t nbytes, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kHitachiAc424Bits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -489,14 +491,14 @@ void IRsend::sendHitachiAc424(const uint8_t data[], const uint16_t nbytes, // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/973 -bool IRrecv::decodeHitachiAc424(decode_results *results, const uint16_t nbits, +bool IRrecv::decodeHitachiAc424(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { - if (results->rawlen < 2 * nbits + kHeader + kHeader + kFooter - 1) + if (results->rawlen < 2 * nbits + kHeader + kHeader + kFooter - 1 + offset) return false; // Too short a message to match. if (strict && nbits != kHitachiAc424Bits) return false; - uint16_t offset = kStartOffset; uint16_t used; // Leader diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.h b/lib/IRremoteESP8266-2.7.4/src/ir_Hitachi.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Hitachi.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Hitachi.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Inax.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Inax.cpp similarity index 90% rename from lib/IRremoteESP8266-2.7.3/src/ir_Inax.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Inax.cpp index 073580fae..9822e750b 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Inax.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Inax.cpp @@ -49,6 +49,8 @@ void IRsend::sendInax(const uint64_t data, const uint16_t nbits, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. // Typically kInaxBits. // strict: Flag to indicate if we strictly adhere to the specification. @@ -57,13 +59,12 @@ void IRsend::sendInax(const uint64_t data, const uint16_t nbits, // // Status: Stable / Known working. // -bool IRrecv::decodeInax(decode_results *results, const uint16_t nbits, - const bool strict) { +bool IRrecv::decodeInax(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kInaxBits) return false; // We expect Inax to be a certain sized message. uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, &data, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_JVC.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_JVC.cpp similarity index 93% rename from lib/IRremoteESP8266-2.7.3/src/ir_JVC.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_JVC.cpp index 7038e9d3e..128efdf08 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_JVC.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_JVC.cpp @@ -92,6 +92,8 @@ uint16_t IRsend::encodeJVC(uint8_t address, uint8_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits of data to expect. Typically kJvcBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -103,14 +105,14 @@ uint16_t IRsend::encodeJVC(uint8_t address, uint8_t command) { // JVC repeat codes don't have a header. // Ref: // http://www.sbprojects.com/knowledge/ir/jvc.php -bool IRrecv::decodeJVC(decode_results *results, uint16_t nbits, bool strict) { +bool IRrecv::decodeJVC(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kJvcBits) return false; // Must be called with the correct nr. of bits. - if (results->rawlen < 2 * nbits + kFooter - 1) + if (results->rawlen <= 2 * nbits + kFooter - 1 + offset) return false; // Can't possibly be a valid JVC message. uint64_t data = 0; - uint16_t offset = kStartOffset; bool isRepeat = true; // Header diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Kelvinator.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Kelvinator.cpp index 320458b30..4a4fac276 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Kelvinator.cpp @@ -414,22 +414,23 @@ String IRKelvinatorAC::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kKelvinatorBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: STABLE / Known working. -bool IRrecv::decodeKelvinator(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < - 2 * (nbits + kKelvinatorCmdFooterBits) + (kHeader + kFooter + 1) * 2 - 1) +bool IRrecv::decodeKelvinator(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= + 2 * (nbits + kKelvinatorCmdFooterBits) + (kHeader + kFooter + 1) * 2 - 1 + + offset) return false; // Can't possibly be a valid Kelvinator message. if (strict && nbits != kKelvinatorBits) return false; // Not strictly a Kelvinator message. - uint16_t offset = kStartOffset; - // There are two messages back-to-back in a full Kelvinator IR message // sequence. int8_t pos = 0; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.h b/lib/IRremoteESP8266-2.7.4/src/ir_Kelvinator.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Kelvinator.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Kelvinator.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_LG.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_LG.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_LG.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_LG.cpp index ce0a36d3d..b30dba082 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_LG.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_LG.cpp @@ -176,13 +176,15 @@ uint32_t IRsend::encodeLG(uint16_t address, uint16_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. // Typically kLgBits or kLg32Bits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: BETA / Should work. +// Status: STABLE / Working. // // Note: // LG 32bit protocol appears near identical to the Samsung protocol. @@ -193,19 +195,18 @@ uint32_t IRsend::encodeLG(uint16_t address, uint16_t command) { // Ref: // https://funembedded.wordpress.com/2014/11/08/ir-remote-control-for-lg-conditioner-using-stm32f302-mcu-on-mbed-platform/ -bool IRrecv::decodeLG(decode_results *results, uint16_t nbits, bool strict) { +bool IRrecv::decodeLG(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (nbits >= kLg32Bits) { - if (results->rawlen < 2 * nbits + 2 * (kHeader + kFooter) - 1) + if (results->rawlen <= 2 * nbits + 2 * (kHeader + kFooter) - 1 + offset) return false; // Can't possibly be a valid LG32 message. } else { - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) + if (results->rawlen <= 2 * nbits + kHeader - 1 + offset) return false; // Can't possibly be a valid LG message. } if (strict && nbits != kLgBits && nbits != kLg32Bits) return false; // Doesn't comply with expected LG protocol. - uint64_t data = 0; - uint16_t offset = kStartOffset; bool isLg2 = false; // Header @@ -280,7 +281,6 @@ bool IRrecv::decodeLG(decode_results *results, uint16_t nbits, bool strict) { if (strict && (data & 0xF) != calcLGChecksum(command)) return false; // The last 4 bits sent are the expected checksum. - // Success if (isLg2) results->decode_type = LG2; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_LG.h b/lib/IRremoteESP8266-2.7.4/src/ir_LG.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_LG.h rename to lib/IRremoteESP8266-2.7.4/src/ir_LG.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Lasertag.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Lasertag.cpp similarity index 90% rename from lib/IRremoteESP8266-2.7.3/src/ir_Lasertag.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Lasertag.cpp index f52b7477a..14a059084 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Lasertag.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Lasertag.cpp @@ -56,6 +56,8 @@ void IRsend::sendLasertag(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -67,14 +69,13 @@ void IRsend::sendLasertag(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://www.sbprojects.com/knowledge/ir/rc5.php // https://en.wikipedia.org/wiki/RC-5 // https://en.wikipedia.org/wiki/Manchester_code -bool IRrecv::decodeLasertag(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < kLasertagMinSamples) return false; +bool IRrecv::decodeLasertag(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= kLasertagMinSamples + offset) return false; // Compliance if (strict && nbits != kLasertagBits) return false; - uint16_t offset = kStartOffset; uint16_t used = 0; uint64_t data = 0; uint16_t actual_bits = 0; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Lego.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Lego.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/src/ir_Lego.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Lego.cpp index 932a568d0..502352218 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Lego.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Lego.cpp @@ -67,20 +67,20 @@ void IRsend::sendLegoPf(const uint64_t data, const uint16_t nbits, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kLegoPfBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // -// Status: Alpha / Untested. -bool IRrecv::decodeLegoPf(decode_results* results, +// Status: BETA / Appears to work. +bool IRrecv::decodeLegoPf(decode_results* results, uint16_t offset, const uint16_t nbits, const bool strict) { // Check if can possibly be a valid LEGO message. - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; if (strict && nbits != kLegoPfBits) return false; // Not what is expected uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, &data, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Lutron.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Lutron.cpp similarity index 93% rename from lib/IRremoteESP8266-2.7.3/src/ir_Lutron.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Lutron.cpp index 7c9835047..094932e5d 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Lutron.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Lutron.cpp @@ -58,6 +58,8 @@ void IRsend::sendLutron(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kLutronBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -69,8 +71,8 @@ void IRsend::sendLutron(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/515 -bool IRrecv::decodeLutron(decode_results *results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeLutron(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { // Technically the smallest number of entries for the smallest message is '1'. // i.e. All the bits set to 1, would produce a single huge mark signal. // So no minimum length check is required. @@ -81,8 +83,7 @@ bool IRrecv::decodeLutron(decode_results *results, uint16_t nbits, int16_t bitsSoFar = -1; if (nbits > sizeof(data) * 8) return false; // To large to store the data. - for (uint16_t offset = kStartOffset; - bitsSoFar < nbits && offset < results->rawlen; offset++) { + for (; bitsSoFar < nbits && offset < results->rawlen; offset++) { uint16_t entry = results->rawbuf[offset]; // It has to be large enough to qualify as a bit. if (!matchAtLeast(entry, kLutronTick, 0, kLutronDelta)) { diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_MWM.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_MWM.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/src/ir_MWM.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_MWM.cpp index b747b224b..eefc4a57e 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_MWM.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_MWM.cpp @@ -74,6 +74,8 @@ void IRsend::sendMWM(const uint8_t data[], const uint16_t nbytes, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -81,16 +83,16 @@ void IRsend::sendMWM(const uint8_t data[], const uint16_t nbytes, // // Status: Implemented. // -bool IRrecv::decodeMWM(decode_results *results, uint16_t nbits, bool strict) { +bool IRrecv::decodeMWM(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { DPRINTLN("DEBUG: decodeMWM"); // Compliance - if (results->rawlen < kMWMMinSamples) { + if (results->rawlen <= kMWMMinSamples + offset) { DPRINTLN("DEBUG: decodeMWM: too few samples"); return false; } - uint16_t offset = kStartOffset; uint16_t used = 0; uint64_t data = 0; uint16_t frame_bits = 0; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Magiquest.cpp similarity index 92% rename from lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Magiquest.cpp index 863aa0ec3..2c15612f4 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Magiquest.cpp @@ -67,6 +67,8 @@ uint64_t IRsend::encodeMagiQuest(uint32_t wand_id, uint16_t magnitude) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion, inc. the 8 bit header. // Typically kMagiquestBits. // strict: Flag to indicate if we strictly adhere to the specification. @@ -77,17 +79,16 @@ uint64_t IRsend::encodeMagiQuest(uint32_t wand_id, uint16_t magnitude) { // // Ref: // https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp -bool IRrecv::decodeMagiQuest(decode_results *results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeMagiQuest(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { uint16_t bits = 0; uint64_t data = 0; - uint16_t offset = kStartOffset; - if (results->rawlen < (2 * kMagiquestBits)) { + if (results->rawlen < (2 * kMagiquestBits) + offset - 1) { DPRINT("Not enough bits to be Magiquest - Rawlen: "); DPRINT(results->rawlen); DPRINT(" Expected: "); - DPRINTLN((2 * kMagiquestBits)); + DPRINTLN(2 * kMagiquestBits + offset - 1); return false; } diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.h b/lib/IRremoteESP8266-2.7.4/src/ir_Magiquest.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Magiquest.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Magiquest.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Midea.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Midea.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_Midea.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Midea.cpp index ce373ebfe..bbf9bedfa 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Midea.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Midea.cpp @@ -64,7 +64,7 @@ void IRsend::sendMidea(uint64_t data, uint16_t nbits, uint16_t repeat) { enableIROut(38); for (uint16_t r = 0; r <= repeat; r++) { - // The protcol sends the message, then follows up with an entirely + // The protocol sends the message, then follows up with an entirely // inverted payload. for (size_t inner_loop = 0; inner_loop < 2; inner_loop++) { // Header @@ -397,6 +397,8 @@ String IRMideaAC::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kMideaBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -404,7 +406,8 @@ String IRMideaAC::toString(void) { // // Status: Alpha / Needs testing against a real device. // -bool IRrecv::decodeMidea(decode_results *results, uint16_t nbits, bool strict) { +bool IRrecv::decodeMidea(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { uint8_t min_nr_of_messages = 1; if (strict) { if (nbits != kMideaBits) return false; // Not strictly a MIDEA message. @@ -414,12 +417,11 @@ bool IRrecv::decodeMidea(decode_results *results, uint16_t nbits, bool strict) { // The protocol sends the data normal + inverted, alternating on // each byte. Hence twice the number of expected data bits. if (results->rawlen < - min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1) + min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1 + offset) return false; // Can't possibly be a valid MIDEA message. uint64_t data = 0; uint64_t inverted = 0; - uint16_t offset = kStartOffset; if (nbits > sizeof(data) * 8) return false; // We can't possibly capture a Midea packet that big. diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Midea.h b/lib/IRremoteESP8266-2.7.4/src/ir_Midea.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Midea.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Midea.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Mitsubishi.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Mitsubishi.cpp index cf5c573fc..68098f40a 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Mitsubishi.cpp @@ -127,6 +127,8 @@ void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -139,12 +141,11 @@ void IRsend::sendMitsubishi(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Ref: // GlobalCache's Control Tower's Mitsubishi TV data. -bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeMitsubishi(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kMitsubishiBits) return false; // Request is out of spec. - uint16_t offset = kStartOffset; uint64_t data = 0; // Match Data + Footer @@ -206,6 +207,8 @@ void IRsend::sendMitsubishi2(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -219,14 +222,13 @@ void IRsend::sendMitsubishi2(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/441 -bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + kHeader + (kFooter * 2) - 1) +bool IRrecv::decodeMitsubishi2(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= 2 * nbits + kHeader + (kFooter * 2) - 1 + offset) return false; // Shorter than shortest possibly expected. if (strict && nbits != kMitsubishiBits) return false; // Request is out of spec. - uint16_t offset = kStartOffset; results->value = 0; // Header @@ -287,6 +289,8 @@ void IRsend::sendMitsubishiAC(const unsigned char data[], const uint16_t nbytes, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -296,9 +300,10 @@ void IRsend::sendMitsubishiAC(const unsigned char data[], const uint16_t nbytes, // // Ref: // https://www.analysir.com/blog/2015/01/06/reverse-engineering-mitsubishi-ac-infrared-protocol/ -bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < ((kMitsubishiACBits * 2) + 2)) { +bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t offset, + const uint16_t nbits, + const bool strict) { + if (results->rawlen <= ((kMitsubishiACBits * 2) + 2) + offset) { DPRINTLN("Shorter than shortest possibly expected."); return false; // Shorter than shortest possibly expected. } @@ -306,10 +311,7 @@ bool IRrecv::decodeMitsubishiAC(decode_results *results, uint16_t nbits, DPRINTLN("Request is out of spec."); return false; // Request is out of spec. } - uint16_t offset = kStartOffset; - for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) { - results->state[i] = 0; - } + for (uint8_t i = 0; i < kMitsubishiACStateLength; i++) results->state[i] = 0; bool failure = false; uint8_t rep = 0; do { @@ -825,6 +827,8 @@ void IRsend::sendMitsubishi136(const unsigned char data[], // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -834,16 +838,15 @@ void IRsend::sendMitsubishi136(const unsigned char data[], // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/888 -bool IRrecv::decodeMitsubishi136(decode_results *results, const uint16_t nbits, +bool IRrecv::decodeMitsubishi136(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { - // Too short to match? - if (results->rawlen < (2 * nbits) + kHeader + kFooter - 1) return false; if (nbits % 8 != 0) return false; // Not a multiple of an 8 bit byte. if (strict) { // Do checks to see if it matches the spec. if (nbits != kMitsubishi136Bits) return false; } - uint16_t used = matchGeneric(results->rawbuf + kStartOffset, results->state, - results->rawlen - kStartOffset, nbits, + uint16_t used = matchGeneric(results->rawbuf + offset, results->state, + results->rawlen - offset, nbits, kMitsubishi136HdrMark, kMitsubishi136HdrSpace, kMitsubishi136BitMark, kMitsubishi136OneSpace, kMitsubishi136BitMark, kMitsubishi136ZeroSpace, @@ -1174,6 +1177,8 @@ void IRsend::sendMitsubishi112(const unsigned char data[], // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -1191,14 +1196,14 @@ void IRsend::sendMitsubishi112(const unsigned char data[], // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/619 // https://github.com/crankyoldgit/IRremoteESP8266/issues/947 -bool IRrecv::decodeMitsubishi112(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < ((2 * nbits) + kHeader + kFooter - 1)) return false; +bool IRrecv::decodeMitsubishi112(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < (2 * nbits) + kHeader + kFooter - 1 + offset) + return false; if (nbits % 8 != 0) return false; // Not a multiple of an 8 bit byte. if (strict) { // Do checks to see if it matches the spec. if (nbits != kMitsubishi112Bits && nbits != kTcl112AcBits) return false; } - uint16_t offset = kStartOffset; decode_type_t typeguess = decode_type_t::UNKNOWN; uint16_t hdrspace; uint16_t bitmark; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.h b/lib/IRremoteESP8266-2.7.4/src/ir_Mitsubishi.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Mitsubishi.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Mitsubishi.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_MitsubishiHeavy.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_MitsubishiHeavy.cpp index cc6d066f3..39bd3d8d6 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_MitsubishiHeavy.cpp @@ -959,17 +959,17 @@ String IRMitsubishiHeavy88Ac::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. -// Typically kMitsubishiHeavy88Bits or kMitsubishiHeavy152Bits. +// Typically kMitsubishiHeavy88Bits or kMitsubishiHeavy152Bits (def). // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: BETA / Appears to be working. Needs testing against a real device. -bool IRrecv::decodeMitsubishiHeavy(decode_results* results, +bool IRrecv::decodeMitsubishiHeavy(decode_results* results, uint16_t offset, const uint16_t nbits, const bool strict) { - // Check if can possibly be a valid MitsubishiHeavy message. - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) return false; if (strict) { switch (nbits) { case kMitsubishiHeavy88Bits: @@ -980,7 +980,6 @@ bool IRrecv::decodeMitsubishiHeavy(decode_results* results, } } - uint16_t offset = kStartOffset; uint16_t used; used = matchGeneric(results->rawbuf + offset, results->state, results->rawlen - offset, nbits, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.h b/lib/IRremoteESP8266-2.7.4/src/ir_MitsubishiHeavy.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_MitsubishiHeavy.h rename to lib/IRremoteESP8266-2.7.4/src/ir_MitsubishiHeavy.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_NEC.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_NEC.cpp similarity index 89% rename from lib/IRremoteESP8266-2.7.3/src/ir_NEC.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_NEC.cpp index 03f68c1d9..2f870f58c 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_NEC.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_NEC.cpp @@ -68,6 +68,8 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kNECBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -85,22 +87,22 @@ uint32_t IRsend::encodeNEC(uint16_t address, uint16_t command) { // // Ref: // http://www.sbprojects.com/knowledge/ir/nec.php -bool IRrecv::decodeNEC(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1 && - results->rawlen != kNecRptLength) +bool IRrecv::decodeNEC(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < kNecRptLength + offset - 1) return false; // Can't possibly be a valid NEC message. if (strict && nbits != kNECBits) return false; // Not strictly an NEC message. uint64_t data = 0; - uint16_t offset = kStartOffset; - // Header + // Header - All NEC messages have this Header Mark. if (!matchMark(results->rawbuf[offset++], kNecHdrMark)) return false; // Check if it is a repeat code. - if (results->rawlen == kNecRptLength && - matchSpace(results->rawbuf[offset], kNecRptSpace) && - matchMark(results->rawbuf[offset + 1], kNecBitMark)) { + if (matchSpace(results->rawbuf[offset], kNecRptSpace) && + matchMark(results->rawbuf[offset + 1], kNecBitMark) && + (offset + 2 <= results->rawlen || + matchAtLeast(results->rawbuf[offset + 2], kNecMinGap))) { results->value = kRepeat; results->decode_type = NEC; results->bits = 0; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_NEC.h b/lib/IRremoteESP8266-2.7.4/src/ir_NEC.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_NEC.h rename to lib/IRremoteESP8266-2.7.4/src/ir_NEC.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Neoclima.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Neoclima.cpp index 8b944293e..0e410ca67 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Neoclima.cpp @@ -463,6 +463,8 @@ String IRNeoclimaAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. Typically kNeoclimaBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -472,13 +474,12 @@ String IRNeoclimaAc::toString(void) { // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/764 -bool IRrecv::decodeNeoclima(decode_results *results, const uint16_t nbits, - const bool strict) { +bool IRrecv::decodeNeoclima(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { // Compliance if (strict && nbits != kNeoclimaBits) return false; // Incorrect nr. of bits per spec. - uint16_t offset = kStartOffset; // Match Main Header + Data + Footer uint16_t used; used = matchGeneric(results->rawbuf + offset, results->state, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.h b/lib/IRremoteESP8266-2.7.4/src/ir_Neoclima.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Neoclima.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Neoclima.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Nikai.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Nikai.cpp similarity index 90% rename from lib/IRremoteESP8266-2.7.3/src/ir_Nikai.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Nikai.cpp index 12e99c278..5e6f9fbe5 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Nikai.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Nikai.cpp @@ -48,6 +48,8 @@ void IRsend::sendNikai(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. // Typically kNikaiBits. // strict: Flag to indicate if we strictly adhere to the specification. @@ -56,12 +58,12 @@ void IRsend::sendNikai(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Status: STABLE / Working. // -bool IRrecv::decodeNikai(decode_results *results, uint16_t nbits, bool strict) { +bool IRrecv::decodeNikai(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kNikaiBits) return false; // We expect Nikai to be a certain sized message. uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, &data, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Panasonic.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Panasonic.cpp index 511986a11..bf472de88 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Panasonic.cpp @@ -142,6 +142,8 @@ uint64_t IRsend::encodePanasonic(const uint16_t manufacturer, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -153,13 +155,13 @@ uint64_t IRsend::encodePanasonic(const uint16_t manufacturer, // Ref: // http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 // http://www.hifi-remote.com/wiki/index.php?title=Panasonic -bool IRrecv::decodePanasonic(decode_results *results, const uint16_t nbits, - const bool strict, const uint32_t manufacturer) { +bool IRrecv::decodePanasonic(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict, + const uint32_t manufacturer) { if (strict && nbits != kPanasonicBits) return false; // Request is out of spec. uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, &data, @@ -810,6 +812,8 @@ String IRPanasonicAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kPanasonicAcBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -825,20 +829,18 @@ String IRPanasonicAc::toString(void) { // A/C Remotes: // A75C3747 (Confirmed) // A75C3704 -bool IRrecv::decodePanasonicAC(decode_results *results, const uint16_t nbits, - const bool strict) { +bool IRrecv::decodePanasonicAC(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { uint8_t min_nr_of_messages = 1; if (strict) { if (nbits != kPanasonicAcBits && nbits != kPanasonicAcShortBits) return false; // Not strictly a PANASONIC_AC message. } - if (results->rawlen < - min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1) + if (results->rawlen <= + min_nr_of_messages * (2 * nbits + kHeader + kFooter) - 1 + offset) return false; // Can't possibly be a valid PANASONIC_AC message. - uint16_t offset = kStartOffset; - // Match Header + Data #1 + Footer uint16_t used; used = matchGeneric(results->rawbuf + offset, results->state, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.h b/lib/IRremoteESP8266-2.7.4/src/ir_Panasonic.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Panasonic.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Panasonic.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Pioneer.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Pioneer.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/src/ir_Pioneer.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Pioneer.cpp index 490ea9440..85343a117 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Pioneer.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Pioneer.cpp @@ -96,6 +96,8 @@ uint64_t IRsend::encodePioneer(const uint16_t address, const uint16_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kPioneerBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -103,15 +105,14 @@ uint64_t IRsend::encodePioneer(const uint16_t address, const uint16_t command) { // // Status: BETA / Should be working. (Self decodes & real examples) // -bool IRrecv::decodePioneer(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1) +bool IRrecv::decodePioneer(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * (nbits + kHeader + kFooter) - 1 + offset) return false; // Can't possibly be a valid Pioneer message. if (strict && nbits != kPioneerBits) return false; // Not strictly an Pioneer message. uint64_t data = 0; - uint16_t offset = kStartOffset; results->value = 0; for (uint16_t section = 0; section < 2; section++) { // Match Header + Data + Footer diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Pronto.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Pronto.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Pronto.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Pronto.cpp diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_RC5_RC6.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_RC5_RC6.cpp similarity index 95% rename from lib/IRremoteESP8266-2.7.3/src/ir_RC5_RC6.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_RC5_RC6.cpp index b79416692..ce69aaa3a 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_RC5_RC6.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_RC5_RC6.cpp @@ -347,6 +347,8 @@ int16_t IRrecv::getRClevel(decode_results *results, uint16_t *offset, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -363,14 +365,14 @@ int16_t IRrecv::getRClevel(decode_results *results, uint16_t *offset, // https://en.wikipedia.org/wiki/Manchester_code // TODO(anyone): // Serious testing of the RC-5X and strict aspects needs to be done. -bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < kRc5SamplesMin + kHeader - 1) return false; +bool IRrecv::decodeRC5(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= kRc5SamplesMin + kHeader - 1 + offset) return false; // Compliance if (strict && nbits != kRC5Bits && nbits != kRC5XBits) return false; // It's neither RC-5 or RC-5X. - uint16_t offset = kStartOffset; uint16_t used = 0; bool is_rc5x = false; uint64_t data = 0; @@ -432,6 +434,8 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -444,8 +448,10 @@ bool IRrecv::decodeRC5(decode_results *results, uint16_t nbits, bool strict) { // https://en.wikipedia.org/wiki/Manchester_code // TODO(anyone): // Testing of the strict compliance aspects. -bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < kHeader + 2 + 4) // Up to the double-wide T bit. +bool IRrecv::decodeRC6(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= kHeader + 2 + 4 + offset) + // Up to the double-wide T bit. return false; // Smaller than absolute smallest possible RC6 message. if (strict) { // Compliance @@ -455,7 +461,7 @@ bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { // Also due to potential melding with the start bit, we can only count // the start bit as 1, instead of a more typical 2 value. The header still // remains as normal. - if (results->rawlen < nbits + kHeader + 1) + if (results->rawlen <= nbits + kHeader + 1 + offset) return false; // Don't have enough entries/samples to be valid. switch (nbits) { case kRC6Mode0Bits: @@ -466,8 +472,6 @@ bool IRrecv::decodeRC6(decode_results *results, uint16_t nbits, bool strict) { } } - uint16_t offset = kStartOffset; - // Header if (!matchMark(results->rawbuf[offset], kRc6HdrMark)) return false; // Calculate how long the common tick time is based on the header mark. diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_RCMM.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_RCMM.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/src/ir_RCMM.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_RCMM.cpp index 4e8f43891..a2542e467 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_RCMM.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_RCMM.cpp @@ -95,6 +95,8 @@ void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { // Places successful decode information in the results pointer. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. Typically kRCMMBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -104,11 +106,11 @@ void IRsend::sendRCMM(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Ref: // http://www.sbprojects.com/knowledge/ir/rcmm.php -bool IRrecv::decodeRCMM(decode_results *results, uint16_t nbits, bool strict) { +bool IRrecv::decodeRCMM(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { uint64_t data = 0; - uint16_t offset = kStartOffset; - if (results->rawlen <= 4) + if (results->rawlen <= 4 + offset - 1) return false; // Not enough entries to ever be RCMM. // Calc the maximum size in bits, the message can be, or that we can accept. diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Samsung.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Samsung.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/src/ir_Samsung.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Samsung.cpp index 1ca7a2b4a..a31e76953 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Samsung.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Samsung.cpp @@ -109,6 +109,8 @@ uint32_t IRsend::encodeSAMSUNG(const uint8_t customer, const uint8_t command) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. Typically kSamsungBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -121,15 +123,12 @@ uint32_t IRsend::encodeSAMSUNG(const uint8_t customer, const uint8_t command) { // They differ on their compliance criteria and how they repeat. // Ref: // http://elektrolab.wz.cz/katalog/samsung_protocol.pdf -bool IRrecv::decodeSAMSUNG(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) - return false; // Can't possibly be a valid Samsung message. +bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kSamsungBits) return false; // We expect Samsung to be 32 bits of message. uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, &data, @@ -201,6 +200,8 @@ void IRsend::sendSamsung36(const uint64_t data, const uint16_t nbits, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. // Typically kSamsung36Bits. // strict: Flag to indicate if we strictly adhere to the specification. @@ -214,9 +215,9 @@ void IRsend::sendSamsung36(const uint64_t data, const uint16_t nbits, // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/621 -bool IRrecv::decodeSamsung36(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * nbits + kHeader + kFooter * 2 - 1) +bool IRrecv::decodeSamsung36(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * nbits + kHeader + kFooter * 2 - 1 + offset) return false; // Can't possibly be a valid Samsung message. // We need to be looking for > 16 bits to make sense. if (nbits <= 16) return false; @@ -224,7 +225,6 @@ bool IRrecv::decodeSamsung36(decode_results *results, const uint16_t nbits, return false; // We expect nbits to be 36 bits of message. uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer uint16_t used; @@ -570,6 +570,22 @@ void IRSamsungAc::setPowerful(const bool on) { } } +bool IRSamsungAc::getDisplay(void) { + return GETBIT8(remote_state[10], kSamsungAcDisplayOffset); +} + +void IRSamsungAc::setDisplay(const bool on) { + setBit(&remote_state[10], kSamsungAcDisplayOffset, on); +} + +bool IRSamsungAc::getIon(void) { + return GETBIT8(remote_state[11], kSamsungAcIonOffset); +} + +void IRSamsungAc::setIon(const bool on) { + setBit(&remote_state[11], kSamsungAcIonOffset, on); +} + // Convert a standard A/C mode into its native mode. uint8_t IRSamsungAc::convertMode(const stdAc::opmode_t mode) { switch (mode) { @@ -631,11 +647,11 @@ stdAc::state_t IRSamsungAc::toCommon(void) { result.turbo = this->getPowerful(); result.clean = this->getClean(); result.beep = this->getBeep(); + result.light = this->getDisplay(); + result.filter = this->getIon(); // Not supported. result.swingh = stdAc::swingh_t::kOff; result.econo = false; - result.filter = false; - result.light = false; result.sleep = -1; result.clock = -1; return result; @@ -644,7 +660,7 @@ stdAc::state_t IRSamsungAc::toCommon(void) { // Convert the internal state into a human readable string. String IRSamsungAc::toString(void) { String result = ""; - result.reserve(100); // Reserve some heap for the string to reduce fragging. + result.reserve(115); // Reserve some heap for the string to reduce fragging. result += addBoolToString(getPower(), kPowerStr, false); result += addModeToString(getMode(), kSamsungAcAuto, kSamsungAcCool, kSamsungAcHeat, kSamsungAcDry, @@ -679,6 +695,8 @@ String IRSamsungAc::toString(void) { result += addBoolToString(getClean(), kCleanStr); result += addBoolToString(getQuiet(), kQuietStr); result += addBoolToString(getPowerful(), kPowerfulStr); + result += addBoolToString(getDisplay(), kLightStr); + result += addBoolToString(getIon(), kIonStr); return result; } @@ -687,6 +705,8 @@ String IRSamsungAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kSamsungAcBits // strict: Flag indicating if we should perform strict matching. // Returns: @@ -696,14 +716,12 @@ String IRSamsungAc::toString(void) { // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/505 -bool IRrecv::decodeSamsungAC(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * nbits + kHeader * 3 + kFooter * 2 - 1) +bool IRrecv::decodeSamsungAC(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * nbits + kHeader * 3 + kFooter * 2 - 1 + offset) return false; // Can't possibly be a valid Samsung A/C message. if (nbits != kSamsungAcBits && nbits != kSamsungAcExtendedBits) return false; - uint16_t offset = kStartOffset; - // Message Header if (!matchMark(results->rawbuf[offset++], kSamsungAcBitMark)) return false; if (!matchSpace(results->rawbuf[offset++], kSamsungAcHdrSpace)) return false; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Samsung.h b/lib/IRremoteESP8266-2.7.4/src/ir_Samsung.h similarity index 93% rename from lib/IRremoteESP8266-2.7.3/src/ir_Samsung.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Samsung.h index de2172444..52a781b65 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Samsung.h +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Samsung.h @@ -18,7 +18,9 @@ // Supports: // Brand: Samsung, Model: UA55H6300 TV +// Brand: Samsung, Model: DB63-03556X003 remote // Brand: Samsung, Model: IEC-R03 remote +// Brand: Samsung, Model: AR09FSSDAWKNFA A/C // Brand: Samsung, Model: AR12KSFPEWQNET A/C // Brand: Samsung, Model: AR12HSSDBWKNEU A/C @@ -58,6 +60,8 @@ const uint8_t kSamsungAcQuiet5Offset = 5; const uint8_t kSamsungAcPowerfulMask8 = 0b01010000; const uint8_t kSamsungAcPowerful10Offset = 1; // Mask 0b00000110 const uint8_t kSamsungAcPowerful10Size = 1; // Mask 0b00000110 +const uint8_t kSamsungAcDisplayOffset = 4; // Mask 0b00010000 +const uint8_t kSamsungAcIonOffset = 0; // Mask 0b00000001 const uint16_t kSamsungACSectionLength = 7; const uint64_t kSamsungAcPowerSection = 0x1D20F00000000; @@ -99,6 +103,12 @@ class IRSamsungAc { bool getQuiet(void); void setPowerful(const bool on); bool getPowerful(void); + + void setDisplay(const bool on); + bool getDisplay(void); + void setIon(const bool on); + bool getIon(void); + uint8_t* getRaw(void); void setRaw(const uint8_t new_code[], const uint16_t length = kSamsungAcStateLength); diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Sanyo.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Sanyo.cpp similarity index 96% rename from lib/IRremoteESP8266-2.7.3/src/ir_Sanyo.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Sanyo.cpp index b05e76766..f797fb678 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Sanyo.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Sanyo.cpp @@ -96,7 +96,7 @@ uint64_t IRsend::encodeSanyoLC7461(uint16_t address, uint8_t command) { // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Sanyo.cpp // http://pdf.datasheetcatalog.com/datasheet/sanyo/LC7461.pdf void IRsend::sendSanyoLC7461(uint64_t data, uint16_t nbits, uint16_t repeat) { - // This protocol appears to be another 42-bit variant of the NEC protcol. + // This protocol appears to be another 42-bit variant of the NEC protocol. sendNEC(data, nbits, repeat); } #endif // SEND_SANYO @@ -106,6 +106,8 @@ void IRsend::sendSanyoLC7461(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -123,12 +125,12 @@ void IRsend::sendSanyoLC7461(uint64_t data, uint16_t nbits, uint16_t repeat) { // http://slydiman.narod.ru/scr/kb/sanyo.htm // https://github.com/marcosamarinho/IRremoteESP8266/blob/master/ir_Sanyo.cpp // http://pdf.datasheetcatalog.com/datasheet/sanyo/LC7461.pdf -bool IRrecv::decodeSanyoLC7461(decode_results *results, uint16_t nbits, - bool strict) { +bool IRrecv::decodeSanyoLC7461(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (strict && nbits != kSanyoLC7461Bits) return false; // Not strictly in spec. // This protocol is basically a 42-bit variant of the NEC protocol. - if (!decodeNEC(results, nbits, false)) + if (!decodeNEC(results, offset, nbits, false)) return false; // Didn't match a NEC format (without strict) // Bits 30 to 42+. diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Sharp.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Sharp.cpp similarity index 96% rename from lib/IRremoteESP8266-2.7.3/src/ir_Sharp.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Sharp.cpp index abd93ecf6..f28ca0f4d 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Sharp.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Sharp.cpp @@ -168,6 +168,8 @@ void IRsend::sendSharp(const uint16_t address, uint16_t const command, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. Typically kSharpBits. // strict: Flag indicating if we should perform strict matching. // expansion: Should we expect the expansion bit to be set. Default is true. @@ -185,9 +187,10 @@ void IRsend::sendSharp(const uint16_t address, uint16_t const command, // http://www.sbprojects.com/knowledge/ir/sharp.php // http://www.mwftr.com/ucF08/LEC14%20PIC%20IR.pdf // http://www.hifi-remote.com/johnsfine/DecodeIR.html#Sharp -bool IRrecv::decodeSharp(decode_results *results, const uint16_t nbits, - const bool strict, const bool expansion) { - if (results->rawlen < 2 * nbits + kFooter - 1) +bool IRrecv::decodeSharp(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict, + const bool expansion) { + if (results->rawlen <= 2 * nbits + kFooter - 1 + offset) return false; // Not enough entries to be a Sharp message. // Compliance if (strict) { @@ -196,12 +199,12 @@ bool IRrecv::decodeSharp(decode_results *results, const uint16_t nbits, #ifdef UNIT_TEST // An in spec message has the data sent normally, then inverted. So we // expect twice as many entries than to just get the results. - if (results->rawlen < 2 * (2 * nbits + kFooter)) return false; + if (results->rawlen <= (2 * (2 * nbits + kFooter)) - 1 + offset) + return false; #endif } uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Data + Footer uint16_t used; @@ -496,6 +499,8 @@ String IRSharpAc::toString(void) { // Decode the supplied Sharp A/C message. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of bits to expect in the data portion. (kSharpAcBits) // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -506,16 +511,11 @@ String IRSharpAc::toString(void) { // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/638 // https://github.com/ToniA/arduino-heatpumpir/blob/master/SharpHeatpumpIR.cpp -bool IRrecv::decodeSharpAc(decode_results *results, const uint16_t nbits, - const bool strict) { - // Is there enough data to match successfully? - if (results->rawlen < 2 * nbits + kHeader + kFooter - 1) - return false; - +bool IRrecv::decodeSharpAc(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { // Compliance if (strict && nbits != kSharpAcBits) return false; - uint16_t offset = kStartOffset; // Match Header + Data + Footer uint16_t used; used = matchGeneric(results->rawbuf + offset, results->state, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Sharp.h b/lib/IRremoteESP8266-2.7.4/src/ir_Sharp.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Sharp.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Sharp.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Sherwood.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Sherwood.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Sherwood.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Sherwood.cpp diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Sony.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Sony.cpp similarity index 95% rename from lib/IRremoteESP8266-2.7.3/src/ir_Sony.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Sony.cpp index d0f4b3c7a..c346eb293 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Sony.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Sony.cpp @@ -134,6 +134,8 @@ uint32_t IRsend::encodeSony(uint16_t nbits, uint16_t command, uint16_t address, // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -145,8 +147,9 @@ uint32_t IRsend::encodeSony(uint16_t nbits, uint16_t command, uint16_t address, // SONY protocol, SIRC (Serial Infra-Red Control) can be 12,15,20 bits long. // Ref: // http://www.sbprojects.com/knowledge/ir/sirc.php -bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { - if (results->rawlen < 2 * nbits + kHeader - 1) +bool IRrecv::decodeSony(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= 2 * nbits + kHeader - 1 + offset) return false; // Message is smaller than we expected. // Compliance @@ -162,7 +165,6 @@ bool IRrecv::decodeSony(decode_results *results, uint16_t nbits, bool strict) { } uint64_t data = 0; - uint16_t offset = kStartOffset; uint16_t actualBits; // Header diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Tcl.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Tcl.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Tcl.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Tcl.cpp diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Tcl.h b/lib/IRremoteESP8266-2.7.4/src/ir_Tcl.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Tcl.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Tcl.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Teco.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Teco.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Teco.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Teco.cpp index 200f1954d..8e33e04ec 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Teco.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Teco.cpp @@ -298,18 +298,19 @@ String IRTecoAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kTecoBits. // strict: Flag indicating if we should perform strict matching. // Returns: // boolean: True if it can decode it, false if it can't. // // Status: STABLE / Tested. -bool IRrecv::decodeTeco(decode_results* results, +bool IRrecv::decodeTeco(decode_results* results, uint16_t offset, const uint16_t nbits, const bool strict) { if (strict && nbits != kTecoBits) return false; // Not what is expected uint64_t data = 0; - uint16_t offset = kStartOffset; // Match Header + Data + Footer if (!matchGeneric(results->rawbuf + offset, &data, results->rawlen - offset, nbits, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Teco.h b/lib/IRremoteESP8266-2.7.4/src/ir_Teco.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Teco.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Teco.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Toshiba.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Toshiba.cpp index ba1ca5424..3113e1b09 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Toshiba.cpp @@ -316,6 +316,8 @@ String IRToshibaAC::toString(void) { // Places successful decode information in the results pointer. // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kToshibaACBits. // strict: Flag to indicate if we strictly adhere to the specification. // Returns: @@ -325,10 +327,8 @@ String IRToshibaAC::toString(void) { // // Ref: // -bool IRrecv::decodeToshibaAC(decode_results* results, const uint16_t nbits, - const bool strict) { - uint16_t offset = kStartOffset; - +bool IRrecv::decodeToshibaAC(decode_results* results, uint16_t offset, + const uint16_t nbits, const bool strict) { // Compliance if (strict && nbits != kToshibaACBits) return false; // Must be called with the correct nr. of bytes. diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.h b/lib/IRremoteESP8266-2.7.4/src/ir_Toshiba.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Toshiba.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Toshiba.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Trotec.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Trotec.cpp similarity index 96% rename from lib/IRremoteESP8266-2.7.3/src/ir_Trotec.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Trotec.cpp index cb923b5fc..563564d36 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Trotec.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Trotec.cpp @@ -238,6 +238,8 @@ String IRTrotecESP::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kTrotecBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -246,13 +248,12 @@ String IRTrotecESP::toString(void) { // Status: BETA / Probably works. Untested on real devices. // // Ref: -bool IRrecv::decodeTrotec(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * nbits + kHeader + 2 * kFooter - 1) +bool IRrecv::decodeTrotec(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= 2 * nbits + kHeader + 2 * kFooter - 1 + offset) return false; // Can't possibly be a valid Samsung A/C message. if (strict && nbits != kTrotecBits) return false; - uint16_t offset = kStartOffset; uint16_t used; // Header + Data + Footer #1 used = matchGeneric(results->rawbuf + offset, results->state, diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Trotec.h b/lib/IRremoteESP8266-2.7.4/src/ir_Trotec.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Trotec.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Trotec.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Vestel.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Vestel.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Vestel.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Vestel.cpp index c2a3a905b..4378497e0 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Vestel.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Vestel.cpp @@ -512,6 +512,8 @@ String IRVestelAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kVestelBits. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -519,8 +521,8 @@ String IRVestelAc::toString(void) { // // Status: Alpha / Needs testing against a real device. // -bool IRrecv::decodeVestelAc(decode_results* results, const uint16_t nbits, - const bool strict) { +bool IRrecv::decodeVestelAc(decode_results* results, uint16_t offset, + const uint16_t nbits, const bool strict) { if (nbits % 8 != 0) // nbits has to be a multiple of nr. of bits in a byte. return false; @@ -529,7 +531,6 @@ bool IRrecv::decodeVestelAc(decode_results* results, const uint16_t nbits, return false; // Not strictly a Vestel AC message. uint64_t data = 0; - uint16_t offset = kStartOffset; if (nbits > sizeof(data) * 8) return false; // We can't possibly capture a Vestel packet that big. diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Vestel.h b/lib/IRremoteESP8266-2.7.4/src/ir_Vestel.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Vestel.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Vestel.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Whirlpool.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Whirlpool.cpp index 9dbdf62e5..e1ca2e6db 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Whirlpool.cpp @@ -542,6 +542,8 @@ String IRWhirlpoolAc::toString(void) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: The number of data bits to expect. Typically kWhirlpoolAcBits // strict: Flag indicating if we should perform strict matching. // Returns: @@ -552,16 +554,15 @@ String IRWhirlpoolAc::toString(void) { // // Ref: // https://github.com/crankyoldgit/IRremoteESP8266/issues/509 -bool IRrecv::decodeWhirlpoolAC(decode_results *results, const uint16_t nbits, - const bool strict) { - if (results->rawlen < 2 * nbits + 4 + kHeader + kFooter - 1) +bool IRrecv::decodeWhirlpoolAC(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen < 2 * nbits + 4 + kHeader + kFooter - 1 + offset) return false; // Can't possibly be a valid Whirlpool A/C message. if (strict) { if (nbits != kWhirlpoolAcBits) return false; } - uint16_t offset = kStartOffset; - uint8_t sectionSize[kWhirlpoolAcSections] = {6, 8, 7}; + const uint8_t sectionSize[kWhirlpoolAcSections] = {6, 8, 7}; // Header if (!matchMark(results->rawbuf[offset++], kWhirlpoolAcHdrMark)) return false; diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.h b/lib/IRremoteESP8266-2.7.4/src/ir_Whirlpool.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/ir_Whirlpool.h rename to lib/IRremoteESP8266-2.7.4/src/ir_Whirlpool.h diff --git a/lib/IRremoteESP8266-2.7.3/src/ir_Whynter.cpp b/lib/IRremoteESP8266-2.7.4/src/ir_Whynter.cpp similarity index 91% rename from lib/IRremoteESP8266-2.7.3/src/ir_Whynter.cpp rename to lib/IRremoteESP8266-2.7.4/src/ir_Whynter.cpp index c5634f381..118eb7559 100644 --- a/lib/IRremoteESP8266-2.7.3/src/ir_Whynter.cpp +++ b/lib/IRremoteESP8266-2.7.4/src/ir_Whynter.cpp @@ -69,6 +69,8 @@ void IRsend::sendWhynter(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Args: // results: Ptr to the data to decode and where to store the decode result. +// offset: The starting index to use when attempting to decode the raw data. +// Typically/Defaults to kStartOffset. // nbits: Nr. of data bits to expect. // strict: Flag indicating if we should perform strict matching. // Returns: @@ -78,16 +80,15 @@ void IRsend::sendWhynter(uint64_t data, uint16_t nbits, uint16_t repeat) { // // Ref: // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp -bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits, - bool strict) { - if (results->rawlen < 2 * nbits + 2 * kHeader + kFooter - 1) +bool IRrecv::decodeWhynter(decode_results *results, uint16_t offset, + const uint16_t nbits, const bool strict) { + if (results->rawlen <= 2 * nbits + 2 * kHeader + kFooter - 1 + offset) return false; // We don't have enough entries to possibly match. // Compliance if (strict && nbits != kWhynterBits) return false; // Incorrect nr. of bits per spec. - uint16_t offset = kStartOffset; uint64_t data = 0; // Pre-Header // Sequence begins with a bit mark and a zero space. diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/README.md b/lib/IRremoteESP8266-2.7.4/src/locale/README.md similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/README.md rename to lib/IRremoteESP8266-2.7.4/src/locale/README.md diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/de-CH.h b/lib/IRremoteESP8266-2.7.4/src/locale/de-CH.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/de-CH.h rename to lib/IRremoteESP8266-2.7.4/src/locale/de-CH.h diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/de-DE.h b/lib/IRremoteESP8266-2.7.4/src/locale/de-DE.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/de-DE.h rename to lib/IRremoteESP8266-2.7.4/src/locale/de-DE.h diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/defaults.h b/lib/IRremoteESP8266-2.7.4/src/locale/defaults.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/defaults.h rename to lib/IRremoteESP8266-2.7.4/src/locale/defaults.h diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/en-AU.h b/lib/IRremoteESP8266-2.7.4/src/locale/en-AU.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/en-AU.h rename to lib/IRremoteESP8266-2.7.4/src/locale/en-AU.h diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/en-IE.h b/lib/IRremoteESP8266-2.7.4/src/locale/en-IE.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/en-IE.h rename to lib/IRremoteESP8266-2.7.4/src/locale/en-IE.h diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/en-UK.h b/lib/IRremoteESP8266-2.7.4/src/locale/en-UK.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/en-UK.h rename to lib/IRremoteESP8266-2.7.4/src/locale/en-UK.h diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/en-US.h b/lib/IRremoteESP8266-2.7.4/src/locale/en-US.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/en-US.h rename to lib/IRremoteESP8266-2.7.4/src/locale/en-US.h diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/es-ES.h b/lib/IRremoteESP8266-2.7.4/src/locale/es-ES.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/es-ES.h rename to lib/IRremoteESP8266-2.7.4/src/locale/es-ES.h diff --git a/lib/IRremoteESP8266-2.7.3/src/locale/fr-FR.h b/lib/IRremoteESP8266-2.7.4/src/locale/fr-FR.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/src/locale/fr-FR.h rename to lib/IRremoteESP8266-2.7.4/src/locale/fr-FR.h diff --git a/lib/IRremoteESP8266-2.7.4/src/locale/it-IT.h b/lib/IRremoteESP8266-2.7.4/src/locale/it-IT.h new file mode 100644 index 000000000..b078a7319 --- /dev/null +++ b/lib/IRremoteESP8266-2.7.4/src/locale/it-IT.h @@ -0,0 +1,157 @@ +// Copyright 2020 - Enrico Gueli (@egueli) +// Locale/language file for Italian. +// This file will override the default values located in `defaults.h`. + +#ifndef LOCALE_IT_IT_H_ +#define LOCALE_IT_IT_H_ + +#define D_STR_UNKNOWN "SCONOSCIUTO" +#define D_STR_PROTOCOL "Protocollo" +#define D_STR_POWER "Accensione" +#define D_STR_ON "Acceso" +#define D_STR_OFF "Spento" +#define D_STR_MODE "Modalità" +#define D_STR_TOGGLE "Alterna" +#define D_STR_SLEEP "Sonno" +#define D_STR_LIGHT "Leggero" +#define D_STR_POWERFUL "Forte" +#define D_STR_QUIET "Silenzioso" +#define D_STR_ECONO "Eco" +#define D_STR_SWING "Swing" +#define D_STR_SWINGH D_STR_SWING"(O)" // Set `D_STR_SWING` first! +#define D_STR_SWINGV D_STR_SWING"(V)" // Set `D_STR_SWING` first! +#define D_STR_MOULD "Muffa" +#define D_STR_CLEAN "Pulizia" +#define D_STR_PURIFY "Purifica" +#define D_STR_TIMER "Timer" +#define D_STR_ONTIMER D_STR_ON " " D_STR_TIMER // Set `D_STR_ON` first! +#define D_STR_OFFTIMER D_STR_OFF " " D_STR_TIMER // Set `D_STR_OFF` first! +#define D_STR_CLOCK "Orologio" +#define D_STR_COMMAND "Comando" +#define D_STR_MODEL "Modello" +#define D_STR_TEMP "Temp" +#define D_STR_HUMID "Umido" +#define D_STR_SAVE "Salva" +#define D_STR_EYE "Occhio" +#define D_STR_FOLLOW "Segui" +#define D_STR_ION "Ioni" +#define D_STR_FRESH "Fresco" +#define D_STR_HOLD "Mantieni" +#define D_STR_8C_HEAT "8C " D_STR_HEAT // Set `D_STR_HEAT` first! +#define D_STR_BUTTON "Pulsante" +#define D_STR_NIGHT "Notte" +#define D_STR_SILENT "Silenzioso" +#define D_STR_FILTER "Filtro" +#define D_STR_UP "Su" +#define D_STR_TEMPUP D_STR_TEMP " " D_STR_UP // Set `D_STR_TEMP` first! +#define D_STR_DOWN "Giù" +#define D_STR_TEMPDOWN D_STR_TEMP " " D_STR_DOWN // Set `D_STR_TEMP` first! +#define D_STR_CHANGE "Cambia" +#define D_STR_START "Avvia" +#define D_STR_STOP "Ferma" +#define D_STR_MOVE "Muovi" +#define D_STR_SET "Imposta" +#define D_STR_CANCEL "Annulla" +#define D_STR_SENSOR "Sensore" +#define D_STR_WEEKLY "Settimanale" +#define D_STR_WEEKLYTIMER D_STR_WEEKLY " " D_STR_TIMER // Needs `D_STR_WEEKLY`! +#define D_STR_LAST "Ultimo" +#define D_STR_FAST "Veloce" +#define D_STR_SLOW "Lento" +#define D_STR_AIRFLOW "Flusso d'aria" +#define D_STR_STEP "Passo" +#define D_STR_NA "N/D" +#define D_STR_OUTSIDE "Esterno" +#define D_STR_LOUD "Rumoroso" +#define D_STR_UPPER "Superiore" +#define D_STR_LOWER "Inferiore" +#define D_STR_CIRCULATE "Circolare" +#define D_STR_CEILING "Soffitto" +#define D_STR_WALL "Muro" +#define D_STR_ROOM "Camera" +#define D_STR_FIXED "Fisso" + +#define D_STR_AUTO "Auto" +#define D_STR_AUTOMATIC "Automatico" +#define D_STR_MANUAL "Manuale" +#define D_STR_COOL "Fresco" +#define D_STR_HEAT "Caldo" +#define D_STR_FAN "Ventola" +#define D_STR_FANONLY "solo_ventola" +#define D_STR_DRY "Secco" + +#define D_STR_MAX "Max" +#define D_STR_MAXIMUM "Massimo" +#define D_STR_MINIMUM "Minimo" +#define D_STR_MEDIUM "Medio" + +#define D_STR_HIGHEST "Molto alto" +#define D_STR_HIGH "Alto" +#define D_STR_MID "Med" +#define D_STR_MIDDLE "Medio" +#define D_STR_LOW "Basso" +#define D_STR_LOWEST "Bassissimo" +#define D_STR_RIGHT "Destra" +#define D_STR_MAXRIGHT D_STR_MAX " " D_STR_RIGHT // Set `D_STR_MAX` first! +#define D_STR_RIGHTMAX_NOSPACE D_STR_RIGHT D_STR_MAX // Set `D_STR_MAX` first! +#define D_STR_LEFT "Sinistra" +#define D_STR_MAXLEFT D_STR_MAX " " D_STR_LEFT // Set `D_STR_MAX` first! +#define D_STR_LEFTMAX_NOSPACE D_STR_LEFT D_STR_MAX // Set `D_STR_MAX` first! +#define D_STR_WIDE "Largo" +#define D_STR_CENTRE "Centro" +#define D_STR_TOP "Superiore" +#define D_STR_BOTTOM "Inferiore" +// Compound words/phrases/descriptions from pre-defined words. +// Note: Obviously these need to be defined *after* their component words. + +#define D_STR_EYEAUTO D_STR_EYE " " D_STR_AUTO +#define D_STR_LIGHTTOGGLE D_STR_LIGHT " " D_STR_TOGGLE +#define D_STR_OUTSIDEQUIET D_STR_OUTSIDE " " D_STR_QUIET +#define D_STR_POWERTOGGLE D_STR_POWER " " D_STR_TOGGLE +#define D_STR_SENSORTEMP D_STR_SENSOR " " D_STR_TEMP +#define D_STR_SLEEP_TIMER D_STR_SLEEP " " D_STR_TIMER +#define D_STR_SWINGVMODE D_STR_SWINGV " " D_STR_MODE +#define D_STR_SWINGVTOGGLE D_STR_SWINGV " " D_STR_TOGGLE +// Separators +#ifndef D_CHR_TIME_SEP +#define D_CHR_TIME_SEP '.' +#endif // D_CHR_TIME_SEP + +#define D_STR_SPACELBRACE " (" +#define D_STR_COMMASPACE ", " +#define D_STR_COLONSPACE ": " + +#define D_STR_DAY "Giorno" +#define D_STR_DAYS D_STR_DAY "s" +#define D_STR_HOUR "Ore" +#define D_STR_HOURS D_STR_HOUR "s" +#define D_STR_MINUTE "Minuti" +#define D_STR_MINUTES D_STR_MINUTE "s" +#define D_STR_SECOND "Secondi" +#define D_STR_SECONDS D_STR_SECOND "s" +#define D_STR_NOW "Adesso" +#define D_STR_THREELETTERDAYS "DomLunMarMerGioVenSab" + +#define D_STR_YES "Sì" +#define D_STR_TRUE "Vero" +#define D_STR_FALSE "Falso" + +#define D_STR_REPEAT "Ripeti" +#define D_STR_CODE "Codice" +#define D_STR_BITS "Bit" +// IRrecvDumpV2 + +#define D_STR_LIBRARY "Libreria" +#define D_STR_MESGDESC "Desc. Mess." +#define D_STR_IRRECVDUMP_STARTUP \ + "IRrecvDumpV2 è ora attivo e in attesa di segnali IR dal pin %d" + +#ifndef D_WARN_BUFFERFULL +#define D_WARN_BUFFERFULL \ + "ATTENZIONE: il codice IR è troppo grande per il buffer (>= %d). " \ + "Non fare affidamento a questi risultati finché questo problema " \ + "non è risolto." \ + "Modifica e aumenta `kCaptureBufferSize`." +#endif // D_WARN_BUFFERFULL + +#endif // LOCALE_IT_IT_H_ diff --git a/lib/IRremoteESP8266-2.7.3/test/IRac_test.cpp b/lib/IRremoteESP8266-2.7.4/test/IRac_test.cpp similarity index 95% rename from lib/IRremoteESP8266-2.7.3/test/IRac_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/IRac_test.cpp index 875485eee..c8c231621 100644 --- a/lib/IRremoteESP8266-2.7.3/test/IRac_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/IRac_test.cpp @@ -332,21 +332,24 @@ TEST(TestIRac, Daikin216) { } TEST(TestIRac, Electra) { - IRElectraAc ac(0); - IRac irac(0); - IRrecv capture(0); + IRElectraAc ac(kGpioUnused); + IRac irac(kGpioUnused); + IRrecv capture(kGpioUnused); char expected[] = "Power: On, Mode: 6 (Fan), Temp: 26C, Fan: 1 (High), " - "Swing(V): On, Swing(H): On"; + "Swing(V): On, Swing(H): On, Light: Toggle, Clean: On, Turbo: On"; ac.begin(); irac.electra(&ac, - true, // Power - stdAc::opmode_t::kFan, // Mode - 26, // Celsius - stdAc::fanspeed_t::kHigh, // Fan speed - stdAc::swingv_t::kAuto, // Veritcal swing - stdAc::swingh_t::kLeft); // Horizontal swing + true, // Power + stdAc::opmode_t::kFan, // Mode + 26, // Celsius + stdAc::fanspeed_t::kHigh, // Fan speed + stdAc::swingv_t::kAuto, // Veritcal swing + stdAc::swingh_t::kLeft, // Horizontal swing + true, // Turbo + true, // Light (toggle) + true); // Clean ASSERT_EQ(expected, ac.toString()); ac._irsend.makeDecodeResult(); EXPECT_TRUE(capture.decode(&ac._irsend.capture)); @@ -892,7 +895,7 @@ TEST(TestIRac, Samsung) { IRrecv capture(0); char expected[] = "Power: On, Mode: 0 (Auto), Temp: 28C, Fan: 6 (Auto), Swing: On, " - "Beep: On, Clean: On, Quiet: On, Powerful: Off"; + "Beep: On, Clean: On, Quiet: On, Powerful: Off, Light: On, Ion: Off"; ac.begin(); irac.samsung(&ac, @@ -903,6 +906,8 @@ TEST(TestIRac, Samsung) { stdAc::swingv_t::kAuto, // Veritcal swing true, // Quiet false, // Turbo + true, // Light (Display) + false, // Filter (Ion) true, // Clean true, // Beep true, // Previous power state @@ -923,6 +928,8 @@ TEST(TestIRac, Samsung) { stdAc::swingv_t::kAuto, // Veritcal swing true, // Quiet false, // Turbo + true, // Light (Display) + false, // Filter (Ion) true, // Clean true, // Beep true, // Previous power state @@ -936,7 +943,7 @@ TEST(TestIRac, Samsung) { // desired state. char expected_on[] = "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off"; + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off"; ASSERT_EQ(expected_on, IRAcUtils::resultAcToString(&ac._irsend.capture)); } @@ -1600,3 +1607,64 @@ TEST(TestIRac, Issue1001) { "Command: 1 (Power)", IRAcUtils::resultAcToString(&ac._irsend.capture)); } + +// Check power switching in Daikin2 common a/c handling when from an IR message. +TEST(TestIRac, Issue1035) { + stdAc::state_t prev; // Previously desired state + stdAc::state_t result; // State we need to send to get to `desired` + prev.protocol = decode_type_t::DAIKIN2; + prev.model = -1; + prev.power = false; + prev.mode = stdAc::opmode_t::kAuto; + prev.degrees = 24; + prev.celsius = true; + prev.fanspeed = stdAc::fanspeed_t::kAuto; + prev.swingv = stdAc::swingv_t::kOff; + prev.swingh = stdAc::swingh_t::kOff; + prev.quiet = false; + prev.turbo = false; + prev.econo = false; + prev.light = false; + prev.filter = false; + prev.clean = false; + prev.beep = false; + prev.sleep = -1; + + // https://github.com/crankyoldgit/IRremoteESP8266/issues/1035#issuecomment-580963572 + const uint8_t on_code[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x15, 0x43, 0x90, 0x29, 0x0C, 0x80, 0x04, + 0xC0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xC1, 0x2D, 0x11, 0xDA, 0x27, 0x00, + 0x00, 0x09, 0x2A, 0x00, 0xB0, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, + 0x90, 0x60, 0x0C}; + const uint8_t off_code[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x15, 0xC3, 0x90, 0x29, 0x0C, 0x80, 0x04, + 0xC0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xD1, 0xBD, 0x11, 0xDA, 0x27, 0x00, + 0x00, 0x08, 0x2A, 0x00, 0xB0, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, + 0x90, 0x60, 0x0B}; + + IRac irac(kGpioUnused); + IRrecv capture(kGpioUnused); + IRDaikin2 ac(kGpioUnused); + + ac.begin(); + ac.setRaw(on_code); + ac.send(); + ac._irsend.makeDecodeResult(); + ASSERT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(DAIKIN2, ac._irsend.capture.decode_type); + ASSERT_FALSE(prev.power); + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &result, &prev)); + ASSERT_TRUE(result.power); + + prev = result; + + ac._irsend.reset(); + ac.setRaw(off_code); + ac.send(); + ac._irsend.makeDecodeResult(); + ASSERT_TRUE(capture.decode(&ac._irsend.capture)); + ASSERT_EQ(DAIKIN2, ac._irsend.capture.decode_type); + ASSERT_TRUE(prev.power); + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &result, &prev)); + ASSERT_FALSE(result.power); +} diff --git a/lib/IRremoteESP8266-2.7.3/test/IRrecv_test.cpp b/lib/IRremoteESP8266-2.7.4/test/IRrecv_test.cpp similarity index 74% rename from lib/IRremoteESP8266-2.7.3/test/IRrecv_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/IRrecv_test.cpp index 9dff78c75..fa025a2cb 100644 --- a/lib/IRremoteESP8266-2.7.3/test/IRrecv_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/IRrecv_test.cpp @@ -168,7 +168,8 @@ TEST(TestDecode, DecodePanasonic) { irsend.reset(); irsend.sendPanasonic64(0x40040190ED7C); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x40040190ED7C, irsend.capture.value); @@ -1244,3 +1245,347 @@ TEST(TestIRrecv, Tolerance) { result = irrecv.matchData(irsend.capture.rawbuf + 1, 5, 1500, 500, 500, 1500); ASSERT_FALSE(result.success); } + +TEST(TestDecode, SkippingInDecode) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + // Normal (default) usage. + irsend.reset(); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + + // Explicitly use the default (no skipping) + irsend.reset(); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + // Enable the least amount of actual skipping. + // Should still decode normal data. + irsend.reset(); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 1)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + + // Crank up the amount of actual skipping. + // Should still decode normal data. + irsend.reset(); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 10)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + + // Introduce some noise before the actual message. + + // Should not match as NEC anymore. + irsend.reset(); + irsend.mark(60); + irsend.space(60); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_NE(NEC, irsend.capture.decode_type); + // Now with explicit default options set. + irsend.reset(); + irsend.mark(60); + irsend.space(60); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0)); + EXPECT_NE(NEC, irsend.capture.decode_type); + + // Now with 1 skip, which it should match as NEC as there is only one + // mark + space pair of noise. + irsend.reset(); + irsend.mark(60); + irsend.space(60); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 1)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + + // Now with more than 1 skip, which it should match as NEC as there is only + // one mark + space pair of noise. + irsend.reset(); + irsend.mark(60); + irsend.space(60); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 5)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + + // Test multiple noise pairs. + + irsend.reset(); + irsend.mark(160); + irsend.space(60); + irsend.mark(60); + irsend.space(160); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + // Default decode parameters should fail to detect as NEC. + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_NE(NEC, irsend.capture.decode_type); + // A single skip should fail to detect as NEC, as there are two pairs of noise + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 1)); + EXPECT_NE(NEC, irsend.capture.decode_type); + // However, two skips should match it correctly. + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 2)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + // And so should more than 2 skips. + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 10)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); +} + +TEST(TestCrudeNoiseFilter, General) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + // Normal (default) usage. + irsend.reset(); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); + + // Explicitly no filtering. + irsend.reset(); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 0)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); + + // Filter out anything less than 100usecs of which there should be none. + irsend.reset(); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 100)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); + + // Add small noise at the start, but don't filter it + irsend.reset(); + irsend.mark(60); + irsend.space(60); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 0)); + EXPECT_NE(NEC, irsend.capture.decode_type); + EXPECT_EQ(69 + 2, irsend.capture.rawlen); + + // Add small noise at the start, but filter it this time + irsend.reset(); + irsend.mark(60); + irsend.space(60); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 100)); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); + + irsend.reset(); + irsend.mark(60); // Less than the filter floor. + irsend.space(560); + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 100)); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); + + irsend.reset(); + irsend.mark(100); // Higher than the filter floor. + irsend.space(200); // Higher than the filter floor. + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 100)); + EXPECT_NE(kNECBits, irsend.capture.bits); + EXPECT_EQ(69 + 2, irsend.capture.rawlen); + + irsend.reset(); + irsend.mark(160); // Higher than the filter floor. + irsend.space(60); // Lower than the filter floor. + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 100)); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); + + // Multiple noise at the start + irsend.reset(); + irsend.mark(60); // Lower than the filter floor. + irsend.space(60); // Lower than the filter floor. + irsend.mark(60); // Lower than the filter floor. + irsend.space(60); // Lower than the filter floor. + irsend.mark(60); // Lower than the filter floor. + irsend.space(60); // Lower than the filter floor. + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 100)); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); + + // A mix of noise that should be removed. + irsend.reset(); + irsend.mark(60); // Lower than the filter floor. + irsend.space(160); // Higher than the filter floor. + irsend.mark(160); // Higher than the filter floor. + irsend.space(60); // Lower than the filter floor. + irsend.mark(160); // Higher than the filter floor. + irsend.space(60); // Lower than the filter floor. + irsend.sendNEC(0x4BB640BF); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 100)); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); + + // Add noise that should be removed to the end of a message. + irsend.reset(); + irsend.sendNEC(0x4BB640BF); + irsend.mark(60); // Lower than the filter floor. + irsend.space(160); // Higher than the filter floor. + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 100)); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x4BB640BF, irsend.capture.value); + EXPECT_EQ(69, irsend.capture.rawlen); +} + +TEST(TestCrudeNoiseFilter, NoiseMidSample) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1042#issuecomment-583895303 + uint16_t rawData[71] = { + 482, 1370, 9082, 1558, 342, 2514, 662, 470, 660, 468, 658, 1588, 662, 466, + 662, 466, 662, 466, 662, 466, 662, 466, 662, 1586, 660, 1588, 662, 466, + 662, 1588, 662, 1586, 662, 1586, 660, 1588, 662, 1586, 662, 468, 660, + 1588, 662, 468, 662, 466, 660, 466, 662, 464, 662, 466, 662, 466, 662, + 1588, 660, 466, 662, 1586, 662, 1588, 660, 1586, 662, 1586, 662, 1586, + 664, 1594, 662}; // UNKNOWN B0784C9E + + irsend.reset(); + irsend.sendRaw(rawData, 71, 38); + irsend.makeDecodeResult(); + // Try with no filter first. + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 1, 0)); + EXPECT_NE(NEC, irsend.capture.decode_type); + const uint16_t prev_length = irsend.capture.rawlen; + // Now with the filter set to 350, to remove the 342 mark at rawData[4]. + // Note: a mark of 350us is huge. + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 1, 350)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x20DF40BF, irsend.capture.value); + EXPECT_EQ(prev_length - 2, irsend.capture.rawlen); + EXPECT_EQ( + "uint16_t rawData[69] = {482, 1370, 9082, 4414, 662, 470, 660, 468, " + "658, 1588, 662, 466, 662, 466, 662, 466, 662, 466, 662, 466, 662, " + "1586, 660, 1588, 662, 466, 662, 1588, 662, 1586, 662, 1586, 660, " + "1588, 662, 1586, 662, 468, 660, 1588, 662, 468, 662, 466, 660, " + "466, 662, 464, 662, 466, 662, 466, 662, 1588, 660, 466, 662, " + "1586, 662, 1588, 660, 1586, 662, 1586, 662, 1586, 664, 1594, " + "662}; // NEC 20DF40BF\n" + "uint32_t address = 0x4;\n" + "uint32_t command = 0x2;\n" + "uint64_t data = 0x20DF40BF;\n", + resultToSourceCode(&irsend.capture)); + + // Data modified as rawData2[3] which was 882 is too far out of spec. for a + // NEC bit mark. + uint16_t rawData2[7] = { + 9066, 2026, 600, 13906, 222, 992, 734}; // UNKNOWN 8FDE36A7 + irsend.reset(); + irsend.sendRaw(rawData2, 7, 38); + irsend.makeDecodeResult(); + // Try with no filter first. + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 0)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(0, irsend.capture.bits); + EXPECT_TRUE(irsend.capture.repeat); + // Now with the filter set to 250, to remove the 222 mark at rawData2[4]. + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 350)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(0, irsend.capture.bits); + EXPECT_TRUE(irsend.capture.repeat); + EXPECT_EQ( + "uint16_t rawData[5] = {9066, 2026, 600, 15120, 734}; " + "// NEC (Repeat) FFFFFFFFFFFFFFFF\n" + "uint64_t data = 0xFFFFFFFFFFFFFFFF;\n", + resultToSourceCode(&irsend.capture)); +} + +TEST(TestCrudeNoiseFilter, NoiseAtEndOfSample) { + IRsendTest irsend(0); + IRrecv irrecv(1); + irsend.begin(); + + // Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1042#issuecomment-583895303 + uint16_t rawData[69] = { // UNKNOWN B52869E1 + 9078, 4386, 662, 468, 660, 466, 662, 1588, 660, 468, 660, 468, 662, 466, + 662, 466, 662, 466, 662, 1588, 660, 1588, 660, 466, 662, 1590, 660, 1586, + 662, 1586, 662, 1588, 662, 1584, 662, 1588, 662, 1588, 660, 466, 686, 442, + 662, 466, 662, 466, 662, 466, 662, 468, 662, 466, 662, 466, 662, 1586, + 662, 1588, 662, 1586, 644, 1600, 662, 1586, 688, 1566, 684, 2638, 146}; + irsend.reset(); + irsend.sendRaw(rawData, 69, 38); + irsend.makeDecodeResult(); + // Try with no filter first. + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 0)); + EXPECT_NE(NEC, irsend.capture.decode_type); + const uint16_t prev_length = irsend.capture.rawlen; + + // Now with the filter set to 200, to remove the 146 mark at at the end. + EXPECT_TRUE(irrecv.decode(&irsend.capture, NULL, 0, 200)); + EXPECT_EQ(NEC, irsend.capture.decode_type); + EXPECT_EQ(kNECBits, irsend.capture.bits); + EXPECT_EQ(0x20DFC03F, irsend.capture.value); + EXPECT_EQ(prev_length - 2, irsend.capture.rawlen); + EXPECT_EQ( + "uint16_t rawData[67] = {9078, 4386, 662, 468, 660, 466, 662, 1588, " + "660, 468, 660, 468, 662, 466, 662, 466, 662, 466, 662, 1588, 660, " + "1588, 660, 466, 662, 1590, 660, 1586, 662, 1586, 662, 1588, 662, " + "1584, 662, 1588, 662, 1588, 660, 466, 686, 442, 662, 466, 662, " + "466, 662, 466, 662, 468, 662, 466, 662, 466, 662, 1586, 662, 1588," + " 662, 1586, 644, 1600, 662, 1586, 688, 1566, 684}; " + "// NEC 20DFC03F\n" + "uint32_t address = 0x4;\n" + "uint32_t command = 0x3;\n" + "uint64_t data = 0x20DFC03F;\n", + resultToSourceCode(&irsend.capture)); +} diff --git a/lib/IRremoteESP8266-2.7.3/test/IRrecv_test.h b/lib/IRremoteESP8266-2.7.4/test/IRrecv_test.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/IRrecv_test.h rename to lib/IRremoteESP8266-2.7.4/test/IRrecv_test.h diff --git a/lib/IRremoteESP8266-2.7.3/test/IRsend_test.cpp b/lib/IRremoteESP8266-2.7.4/test/IRsend_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.3/test/IRsend_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/IRsend_test.cpp index fbf8ba229..f2e280504 100644 --- a/lib/IRremoteESP8266-2.7.3/test/IRsend_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/IRsend_test.cpp @@ -193,7 +193,7 @@ TEST(TestSendRaw, GeneralUse) { irsend.reset(); irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); + ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, kNECBits, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0xC3E0E0E8, irsend.capture.value); diff --git a/lib/IRremoteESP8266-2.7.3/test/IRsend_test.h b/lib/IRremoteESP8266-2.7.4/test/IRsend_test.h similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/IRsend_test.h rename to lib/IRremoteESP8266-2.7.4/test/IRsend_test.h diff --git a/lib/IRremoteESP8266-2.7.3/test/IRutils_test.cpp b/lib/IRremoteESP8266-2.7.4/test/IRutils_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/IRutils_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/IRutils_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/Makefile b/lib/IRremoteESP8266-2.7.4/test/Makefile similarity index 98% rename from lib/IRremoteESP8266-2.7.3/test/Makefile rename to lib/IRremoteESP8266-2.7.4/test/Makefile index cdf133913..7b1a4b379 100644 --- a/lib/IRremoteESP8266-2.7.3/test/Makefile +++ b/lib/IRremoteESP8266-2.7.4/test/Makefile @@ -39,7 +39,7 @@ TESTS = IRutils_test IRsend_test ir_NEC_test ir_GlobalCache_test \ ir_Whirlpool_test ir_Lutron_test ir_Electra_test ir_Pioneer_test \ ir_MWM_test ir_Vestel_test ir_Teco_test ir_Tcl_test ir_Lego_test IRac_test \ ir_MitsubishiHeavy_test ir_Trotec_test ir_Argo_test ir_Goodweather_test \ - ir_Inax_test ir_Neoclima_test ir_Amcor_test + ir_Inax_test ir_Neoclima_test ir_Amcor_test ir_Epson_test # All Google Test headers. Usually you shouldn't change this # definition. @@ -85,7 +85,7 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ ir_Hitachi.o ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o \ ir_Pioneer.o ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o ir_Lego.o ir_Argo.o \ ir_Trotec.o ir_MitsubishiHeavy.o ir_Goodweather.o ir_Inax.o ir_Neoclima.o \ - ir_Amcor.o + ir_Amcor.o ir_Epson.o # All the IR Protocol header files. PROTOCOLS_H = $(USER_DIR)/ir_Amcor.h \ @@ -623,3 +623,12 @@ ir_Amcor_test.o : ir_Amcor_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) ir_Amcor_test : $(COMMON_OBJ) ir_Amcor_test.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ + +ir_Epson.o : $(USER_DIR)/ir_Epson.cpp $(COMMON_DEPS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Epson.cpp + +ir_Epson_test.o : ir_Epson_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c ir_Epson_test.cpp + +ir_Epson_test : $(COMMON_OBJ) ir_Epson_test.o + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Aiwa_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Aiwa_test.cpp similarity index 83% rename from lib/IRremoteESP8266-2.7.3/test/ir_Aiwa_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Aiwa_test.cpp index 2fa63afe6..f87d5c5e2 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Aiwa_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Aiwa_test.cpp @@ -130,7 +130,8 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x7F); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); @@ -142,7 +143,8 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -154,7 +156,8 @@ TEST(TestDecodeAiwa, NormalDecodeWithStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x7FFF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7FFF, irsend.capture.value); @@ -173,7 +176,8 @@ TEST(TestDecodeAiwa, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendAiwaRCT501(0x7F, kAiwaRcT501Bits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); EXPECT_EQ(kAiwaRcT501Bits, irsend.capture.bits); EXPECT_EQ(0x7F, irsend.capture.value); @@ -193,7 +197,8 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictValues) { irsend.sendNEC(0x1D8113F00FF, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // MUST pass with strict on. - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); ASSERT_EQ(0x7F, irsend.capture.value); irsend.reset(); @@ -202,10 +207,12 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictValues) { irsend.sendNEC(0x1234567890A, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); // Should fail if strict off too. ASSERT_FALSE( - irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); + irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, kAiwaRcT501Bits, + false)); irsend.reset(); // Use sendNEC(data, 42) to make/send an illegal value Aiwa message. @@ -213,7 +220,8 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictValues) { irsend.sendNEC(0x1D8113F00FE, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); // Should fail if strict off too. ASSERT_FALSE( irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); @@ -224,10 +232,12 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictValues) { irsend.sendNEC(0x0D8113F00FF, 42, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); // Should fail if strict off too. ASSERT_FALSE( - irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); + irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, kAiwaRcT501Bits, + false)); } // Decode unsupported Aiwa messages. @@ -240,9 +250,10 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictSizes) { irsend.sendAiwaRCT501(0x0, 8); // Illegal size Aiwa 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -251,12 +262,15 @@ TEST(TestDecodeAiwa, DecodeWithNonStrictSizes) { irsend.sendAiwaRCT501(0x12345678, 32); // Illegal size Aiwa 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, + kAiwaRcT501Bits, true)); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, 32, + true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, 32, + false)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -273,7 +287,8 @@ TEST(TestDecodeAiwa, Decode64BitMessages) { irsend.sendAiwaRCT501(0x1FFFFFFFFF, 37); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 37, false)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, 37, + false)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); EXPECT_EQ(37, irsend.capture.bits); EXPECT_EQ(0x1FFFFFFFFF, irsend.capture.value); @@ -283,7 +298,8 @@ TEST(TestDecodeAiwa, Decode64BitMessages) { irsend.sendNEC(0x76044FFFFFFFFFFF, 64, kAiwaRcT501MinRepeats); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, 37, false)); + ASSERT_TRUE(irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, 37, + false)); EXPECT_EQ(AIWA_RC_T501, irsend.capture.decode_type); EXPECT_EQ(37, irsend.capture.bits); EXPECT_EQ(0x1FFFFFFFFF, irsend.capture.value); @@ -316,7 +332,7 @@ TEST(TestDecodeAiwa, DecodeGlobalCacheExample) { EXPECT_FALSE(irsend.capture.repeat); // Confirm what the 42-bit NEC decode is. - ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, 42, false)); + ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 42, false)); EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); } @@ -336,5 +352,6 @@ TEST(TestDecodeAiwa, FailToDecodeNonAiwaExample) { ASSERT_FALSE(irrecv.decodeAiwaRCT501(&irsend.capture)); ASSERT_FALSE( - irrecv.decodeAiwaRCT501(&irsend.capture, kAiwaRcT501Bits, false)); + irrecv.decodeAiwaRCT501(&irsend.capture, kStartOffset, kAiwaRcT501Bits, + false)); } diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Amcor_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Amcor_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Amcor_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Amcor_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Argo_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Argo_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Argo_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Argo_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Carrier_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Carrier_test.cpp similarity index 97% rename from lib/IRremoteESP8266-2.7.3/test/ir_Carrier_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Carrier_test.cpp index 053b31dd4..f62a9d0f5 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Carrier_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Carrier_test.cpp @@ -161,7 +161,8 @@ TEST(TestDecodeCarrierAC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCarrierAC(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCarrierAC(&irsend.capture, kCarrierAcBits, true)); + ASSERT_TRUE(irrecv.decodeCarrierAC(&irsend.capture, kStartOffset, + kCarrierAcBits, true)); EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -172,7 +173,8 @@ TEST(TestDecodeCarrierAC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCarrierAC(0xB335ABE2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCarrierAC(&irsend.capture, kCarrierAcBits, true)); + ASSERT_TRUE(irrecv.decodeCarrierAC(&irsend.capture, kStartOffset, + kCarrierAcBits, true)); EXPECT_EQ(CARRIER_AC, irsend.capture.decode_type); EXPECT_EQ(kCarrierAcBits, irsend.capture.bits); EXPECT_EQ(0xB335ABE2, irsend.capture.value); diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Coolix_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Coolix_test.cpp similarity index 91% rename from lib/IRremoteESP8266-2.7.3/test/ir_Coolix_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Coolix_test.cpp index 226e1aa68..20a46c7b4 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Coolix_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Coolix_test.cpp @@ -215,7 +215,8 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0x123456); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); @@ -227,7 +228,8 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -239,7 +241,8 @@ TEST(TestDecodeCoolix, NormalDecodeWithStrict) { irsend.reset(); irsend.sendCOOLIX(0xFFFFFF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0xFFFFFF, irsend.capture.value); @@ -258,20 +261,23 @@ TEST(TestDecodeCoolix, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendCOOLIX(0x123456, kCoolixBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); EXPECT_FALSE(irsend.capture.repeat); irsend.makeDecodeResult(4 * kCoolixBits + 4); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); irsend.makeDecodeResult(2 * (4 * kCoolixBits + 4)); - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + true)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(kCoolixBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); @@ -287,9 +293,10 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { irsend.sendCOOLIX(0x12, 8); // Illegal value Coolix 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x12, irsend.capture.value); @@ -298,13 +305,14 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { irsend.sendCOOLIX(0x12345678, 32); // Illegal value Coolix 32-bit message. irsend.makeDecodeResult(); // Shouldn't pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, true)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, 32, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -313,7 +321,7 @@ TEST(TestDecodeCoolix, DecodeWithNonStrictSizes) { irsend.reset(); irsend.sendCOOLIX(0x123456, kCoolixBits, 2); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, 9, false)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, 9, false)); } // Decode (non-standard) 64-bit messages. @@ -327,7 +335,7 @@ TEST(TestDecodeCoolix, Decode64BitMessages) { irsend.sendCOOLIX(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(COOLIX, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -349,7 +357,8 @@ TEST(TestDecodeCoolix, FailToDecodeNonCoolixExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kCoolixBits, false)); + ASSERT_FALSE(irrecv.decodeCOOLIX(&irsend.capture, kStartOffset, kCoolixBits, + false)); } // Tests for the IRCoolixAC class. @@ -800,3 +809,44 @@ TEST(TestCoolixACClass, Issue985) { EXPECT_EQ(kCoolixOff, ac._irsend.capture.value); EXPECT_EQ("Power: Off", IRAcUtils::resultAcToString(&ac._irsend.capture)); } + +TEST(TestCoolixACClass, PowerStateWithSetRaw) { + IRrecv irrecv(kGpioUnused); + IRCoolixAC ac(kGpioUnused); + + // Problem reported that power is always off via decodeToState() + // Ref: + // https://github.com/crankyoldgit/IRremoteESP8266/pull/1040 + // https://github.com/arendst/Tasmota/issues/7660 + + const uint32_t on_code = 0xB2BFCC; // A valid "on" message. + + // Check the off case. + ac.setRaw(kCoolixOff); + ASSERT_FALSE(ac.getPower()); + EXPECT_FALSE(ac.toCommon().power); + + // Check the "on" case. + ac.setRaw(on_code); + ASSERT_TRUE(ac.getPower()); + EXPECT_TRUE(ac.toCommon().power); + // Now check the reported decodeToState() is also fixed. + ac._irsend.reset(); + ac.send(); + ac._irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&ac._irsend.capture)); + EXPECT_EQ(COOLIX, ac._irsend.capture.decode_type); + EXPECT_EQ(kCoolixBits, ac._irsend.capture.bits); + EXPECT_EQ(on_code, ac._irsend.capture.value); + EXPECT_EQ( + "Power: On, Mode: 3 (Heat), Fan: 5 (Auto), Temp: 25C, Zone Follow: Off, " + "Sensor Temp: Off", IRAcUtils::resultAcToString(&ac._irsend.capture)); + stdAc::state_t result; + ASSERT_TRUE(IRAcUtils::decodeToState(&ac._irsend.capture, &result)); + EXPECT_TRUE(result.power); + + // Recheck the off case to ensure it changes. + ac.setRaw(kCoolixOff); + ASSERT_FALSE(ac.getPower()); + EXPECT_FALSE(ac.toCommon().power); +} diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Daikin_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Daikin_test.cpp similarity index 98% rename from lib/IRremoteESP8266-2.7.3/test/ir_Daikin_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Daikin_test.cpp index 9fcaabcb0..60d39d9a3 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Daikin_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Daikin_test.cpp @@ -3364,3 +3364,39 @@ TEST(TestDaikin152Class, BuildKnownState) { 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x6F}; EXPECT_STATE_EQ(expectedState, ac.getRaw(), kDaikin152Bits); } + +TEST(TestDaikin2Class, Issue1035) { + IRDaikin2 ac(kGpioUnused); + // https://github.com/crankyoldgit/IRremoteESP8266/issues/1035#issuecomment-580963572 + const uint8_t on_code[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x15, 0x43, 0x90, 0x29, 0x0C, 0x80, 0x04, + 0xC0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xC1, 0x2D, 0x11, 0xDA, 0x27, 0x00, + 0x00, 0x09, 0x2A, 0x00, 0xB0, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, + 0x90, 0x60, 0x0C}; + const uint8_t off_code[kDaikin2StateLength] = { + 0x11, 0xDA, 0x27, 0x00, 0x01, 0x15, 0xC3, 0x90, 0x29, 0x0C, 0x80, 0x04, + 0xC0, 0x16, 0x24, 0x00, 0x00, 0xBE, 0xD1, 0xBD, 0x11, 0xDA, 0x27, 0x00, + 0x00, 0x08, 0x2A, 0x00, 0xB0, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0xC1, + 0x90, 0x60, 0x0B}; + + ac.setRaw(on_code); + EXPECT_EQ( + "Power: On, Mode: 0 (Auto), Temp: 21C, Fan: 11 (Quiet), " + "Swing(V): 1 (Highest), Swing(H): 190 (Auto), Clock: 13:09, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 2 (Loud), " + "Light: 1 (High), Mould: On, Clean: On, Fresh: On, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", + ac.toString()); + ASSERT_TRUE(ac.toCommon().power); + ASSERT_NE(ac.toCommon().mode, stdAc::opmode_t::kOff); + + ac.setRaw(off_code); + EXPECT_EQ( + "Power: Off, Mode: 0 (Auto), Temp: 21C, Fan: 11 (Quiet), " + "Swing(V): 1 (Highest), Swing(H): 190 (Auto), Clock: 13:09, " + "On Timer: Off, Off Timer: Off, Sleep Timer: Off, Beep: 2 (Loud), " + "Light: 1 (High), Mould: On, Clean: On, Fresh: On, Eye: Off, " + "Eye Auto: Off, Quiet: Off, Powerful: Off, Purify: On, Econo: Off", + ac.toString()); + ASSERT_FALSE(ac.toCommon().power); +} diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Denon_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Denon_test.cpp similarity index 92% rename from lib/IRremoteESP8266-2.7.3/test/ir_Denon_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Denon_test.cpp index bfb554bb5..64be43f97 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Denon_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Denon_test.cpp @@ -185,7 +185,8 @@ TEST(TestDecodeDenon, NormalDecodeWithStrict) { irsend.sendDenon(0x2278); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenonBits, true)); + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kStartOffset, kDenonBits, + true)); EXPECT_EQ(DENON, irsend.capture.decode_type); EXPECT_EQ(kDenonBits, irsend.capture.bits); EXPECT_EQ(0x2278, irsend.capture.value); @@ -198,7 +199,8 @@ TEST(TestDecodeDenon, NormalDecodeWithStrict) { irsend.sendDenon(0x1278, kDenonLegacyBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenonLegacyBits, true)); + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kStartOffset, + kDenonLegacyBits, true)); EXPECT_EQ(DENON, irsend.capture.decode_type); EXPECT_EQ(kDenonLegacyBits, irsend.capture.bits); EXPECT_EQ(0x1278, irsend.capture.value); @@ -210,7 +212,8 @@ TEST(TestDecodeDenon, NormalDecodeWithStrict) { irsend.reset(); irsend.sendDenon(0x2A4C028D6CE3, kDenon48Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenon48Bits, true)); + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kStartOffset, + kDenon48Bits, true)); EXPECT_EQ(DENON, irsend.capture.decode_type); EXPECT_EQ(kDenon48Bits, irsend.capture.bits); EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value); @@ -235,7 +238,8 @@ TEST(TestDecodeDenon, DecodeGlobalCacheExample) { irsend.sendGC(gc_test_power, 67); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenonBits, true)); + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kStartOffset, kDenonBits, + true)); EXPECT_EQ(DENON, irsend.capture.decode_type); EXPECT_EQ(kDenonBits, irsend.capture.bits); EXPECT_EQ(0x2278, irsend.capture.value); @@ -256,7 +260,8 @@ TEST(TestDecodeDenon, DecodeGlobalCacheExample) { irsend.sendGC(gc_test_eco, 103); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kDenon48Bits, true)); + ASSERT_TRUE(irrecv.decodeDenon(&irsend.capture, kStartOffset, kDenon48Bits, + true)); EXPECT_EQ(DENON, irsend.capture.decode_type); EXPECT_EQ(kDenon48Bits, irsend.capture.bits); EXPECT_EQ(0x2A4C028D6CE3, irsend.capture.value); @@ -280,7 +285,10 @@ TEST(TestDecodeDenon, FailToDecodeNonDenonExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kDenonLegacyBits, false)); - ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kDenonBits, false)); - ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kDenon48Bits, false)); + ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kStartOffset, + kDenonLegacyBits, false)); + ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kStartOffset, kDenonBits, + false)); + ASSERT_FALSE(irrecv.decodeDenon(&irsend.capture, kStartOffset, kDenon48Bits, + false)); } diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Dish_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Dish_test.cpp similarity index 92% rename from lib/IRremoteESP8266-2.7.3/test/ir_Dish_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Dish_test.cpp index 21286b7ac..d74564811 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Dish_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Dish_test.cpp @@ -189,7 +189,8 @@ TEST(TestDecodeDish, NormalDecodeWithStrict) { irsend.reset(); irsend.sendDISH(0x9C00); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kStartOffset, kDishBits, + true)); EXPECT_EQ(DISH, irsend.capture.decode_type); EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); @@ -208,13 +209,14 @@ TEST(TestDecodeDish, DecodeWithNonStrictSize) { irsend.sendDISH(0x12, 8); // Illegal size Dish message. (smaller) irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kStartOffset, kDishBits, + true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, 8, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kStartOffset, 8, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(DISH, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x12, irsend.capture.value); @@ -225,13 +227,14 @@ TEST(TestDecodeDish, DecodeWithNonStrictSize) { irsend.sendDISH(0x12345678, 32); // Illegal size Dish message. (larger) irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kStartOffset, kDishBits, + true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kStartOffset, 32, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(DISH, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -249,9 +252,9 @@ TEST(TestDecodeDish, Decode64BitMessages) { // Illegal value & size Dish 64-bit message. irsend.sendDISH(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, 64, true)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kStartOffset, 64, true)); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(DISH, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -299,7 +302,8 @@ TEST(TestDecodeDish, DecodeGlobalCacheExample) { irsend.sendGC(gc_test_hopper, 73); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kDishBits, true)); + ASSERT_TRUE(irrecv.decodeDISH(&irsend.capture, kStartOffset, kDishBits, + true)); EXPECT_EQ(DISH, irsend.capture.decode_type); EXPECT_EQ(kDishBits, irsend.capture.bits); EXPECT_EQ(0x9C00, irsend.capture.value); @@ -332,5 +336,6 @@ TEST(TestDecodeDish, FailToDecodeNonDishExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kDishBits, false)); + ASSERT_FALSE(irrecv.decodeDISH(&irsend.capture, kStartOffset, kDishBits, + false)); } diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Electra_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Electra_test.cpp similarity index 69% rename from lib/IRremoteESP8266-2.7.3/test/ir_Electra_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Electra_test.cpp index 43ea456c6..b49482433 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Electra_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Electra_test.cpp @@ -101,7 +101,7 @@ TEST(TestDecodeElectraAC, RealExampleDecode) { EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " - "Swing(V): Off, Swing(H): Off", + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off", IRAcUtils::resultAcToString(&irsend.capture)); } @@ -199,24 +199,25 @@ TEST(TestIRElectraAcClass, toCommon) { ac.setFan(kElectraAcFanHigh); ac.setSwingV(true); ac.setSwingH(true); + ac.setClean(true); + ac.setLightToggle(true); // Now test it. ASSERT_EQ(decode_type_t::ELECTRA_AC, ac.toCommon().protocol); ASSERT_EQ(-1, ac.toCommon().model); ASSERT_TRUE(ac.toCommon().power); ASSERT_TRUE(ac.toCommon().celsius); ASSERT_EQ(20, ac.toCommon().degrees); - ASSERT_EQ(stdAc::opmode_t::kCool, ac.toCommon().mode); ASSERT_EQ(stdAc::fanspeed_t::kMax, ac.toCommon().fanspeed); ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv); ASSERT_EQ(stdAc::swingh_t::kAuto, ac.toCommon().swingh); + ASSERT_TRUE(ac.toCommon().clean); + ASSERT_TRUE(ac.toCommon().light); // Unsupported. ASSERT_FALSE(ac.toCommon().turbo); ASSERT_FALSE(ac.toCommon().filter); - ASSERT_FALSE(ac.toCommon().light); ASSERT_FALSE(ac.toCommon().quiet); ASSERT_FALSE(ac.toCommon().econo); - ASSERT_FALSE(ac.toCommon().clean); ASSERT_FALSE(ac.toCommon().beep); ASSERT_EQ(-1, ac.toCommon().sleep); ASSERT_EQ(-1, ac.toCommon().clock); @@ -232,19 +233,125 @@ TEST(TestIRElectraAcClass, HumanReadable) { ac.setRaw(on_cool_32C_auto_voff); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 32C, Fan: 5 (Auto), " - "Swing(V): Off, Swing(H): Off", ac.toString()); + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off", + ac.toString()); uint8_t on_cool_16C_auto_voff[13] = { 0xC3, 0x47, 0xE0, 0x00, 0xA0, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x41, 0x0B}; ac.setRaw(on_cool_16C_auto_voff); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 5 (Auto), " - "Swing(V): Off, Swing(H): Off", ac.toString()); + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off", + ac.toString()); uint8_t on_cool_16C_low_voff[13] = { 0xC3, 0x47, 0xE0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x41, 0xCB}; ac.setRaw(on_cool_16C_low_voff); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 3 (Low), " - "Swing(V): Off, Swing(H): Off", ac.toString()); + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: Off", + ac.toString()); +} + +TEST(TestIRElectraAcClass, Clean) { + IRElectraAc ac(kGpioUnused); + ac.begin(); + + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); + + ac.setClean(false); + EXPECT_FALSE(ac.getClean()); + + ac.setClean(true); + EXPECT_TRUE(ac.getClean()); + + ac.setClean(false); + // ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1033#issuecomment-581133127 + uint8_t on[13] = {0xC3, 0x87, 0xE0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x00, 0x24, + 0x00, 0x19, 0xE7}; + ac.setRaw(on); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " + "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off", + ac.toString()); +} + +TEST(TestIRElectraAcClass, Turbo) { + IRElectraAc ac(kGpioUnused); + ac.begin(); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + + ac.setTurbo(false); + EXPECT_FALSE(ac.getTurbo()); + + ac.setTurbo(true); + EXPECT_TRUE(ac.getTurbo()); + + ac.setTurbo(false); + // ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1033#issuecomment-583888046 + const uint8_t on[13] = { + 0xC3, 0x87, 0xE0, 0x00, 0x60, 0x40, 0x20, 0x00, 0x00, 0x20, 0x00, 0x08, + 0x12}; + + ac.setRaw(on); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " + "Swing(V): Off, Swing(H): Off, Light: -, Clean: Off, Turbo: On", + ac.toString()); +} + +TEST(TestIRElectraAcClass, LightToggle) { + IRElectraAc ac(kGpioUnused); + ac.begin(); + + ac.setLightToggle(true); + EXPECT_TRUE(ac.getLightToggle()); + + ac.setLightToggle(false); + EXPECT_FALSE(ac.getLightToggle()); + + ac.setLightToggle(true); + EXPECT_TRUE(ac.getLightToggle()); + + ac.setLightToggle(false); + // ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1033#issuecomment-581133127 + uint8_t on[13] = {0xC3, 0x87, 0xE0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x00, 0x24, + 0x00, 0x19, 0xE7}; + ac.setRaw(on); + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " + "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off", + ac.toString()); +} + +TEST(TestIRElectraAcClass, ConstructKnownState) { + IRElectraAc ac(kGpioUnused); + // Data from: + // https://github.com/crankyoldgit/IRremoteESP8266/issues/1033#issuecomment-581133127 + // A/C on - Cooling mode - 24° - Fan speed set to 1 - Light set to toggle + // - flaps off - turbo off - clean on + const uint8_t on_cool_24C_fan1_swing_off_turbo_off_clean_on[13] = { + 0xC3, 0x87, 0xE0, 0x00, 0x60, 0x00, 0x20, + // 0x00, 0x00, 0x24, 0x00, 0x19, 0xE7}; // Real captured data + // TODO(ShonP40): Explain `state[11]` difference. + 0x00, 0x00, 0x24, 0x00, 0x15, 0xE3}; // state[11] hacked to pass test. + ac.stateReset(); + ac.on(); + ac.setMode(kElectraAcCool); + ac.setTemp(24); + ac.setSwingH(false); + ac.setSwingV(false); + ac.setFan(kElectraAcFanLow); + ac.setLightToggle(true); + ac.setClean(true); + + EXPECT_EQ( + "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 3 (Low), " + "Swing(V): Off, Swing(H): Off, Light: Toggle, Clean: On, Turbo: Off", + ac.toString()); + EXPECT_STATE_EQ(on_cool_24C_fan1_swing_off_turbo_off_clean_on, + ac.getRaw(), kElectraAcBits); } diff --git a/lib/IRremoteESP8266-2.7.4/test/ir_Epson_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Epson_test.cpp new file mode 100644 index 000000000..d1df3f9ac --- /dev/null +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Epson_test.cpp @@ -0,0 +1,159 @@ +// Copyright 2020 David Conran + +#include "IRac.h" +#include "IRrecv.h" +#include "IRrecv_test.h" +#include "IRsend.h" +#include "IRsend_test.h" +#include "gtest/gtest.h" + +// Tests for sendEpson(). + +// Test sending typical data only. +TEST(TestSendEpson, SendDataOnly) { + IRsendTest irsend(kGpioUnused); + irsend.begin(); + irsend.sendEpson(0xC1AA09F6); + EXPECT_EQ( + "f38000d33" + "m8960s4480" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s41440" + "m8960s4480" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s41440" + "m8960s4480" + "m560s1680m560s1680m560s560m560s560m560s560m560s560m560s560m560s1680" + "m560s1680m560s560m560s1680m560s560m560s1680m560s560m560s1680m560s560" + "m560s560m560s560m560s560m560s560m560s1680m560s560m560s560m560s1680" + "m560s1680m560s1680m560s1680m560s1680m560s560m560s1680m560s1680m560s560" + "m560s41440", + irsend.outputStr()); +} + +// Tests for decodeEpson(). + +// Decode normal Epson messages. +TEST(TestDecodeEpson, SyntheticSelfDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + // Real-life Epson code from an actual capture/decode. + irsend.reset(); + irsend.sendEpson(0xC1AA09F6); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(EPSON, irsend.capture.decode_type); + EXPECT_EQ(kEpsonBits, irsend.capture.bits); + EXPECT_EQ(0xC1AA09F6, irsend.capture.value); + EXPECT_EQ(0x5583, irsend.capture.address); + EXPECT_EQ(0x90, irsend.capture.command); + EXPECT_TRUE(irsend.capture.repeat); +} + +// Decode a real Epson message. +TEST(TestDecodeEpson, RealMessageDecode) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + // Real-life Epson code from an actual capture/decode. + irsend.reset(); + const uint16_t rawData_0[203] = { + 8976, 4496, 542, 1690, 542, 1688, 542, 588, 518, 612, 542, 586, 518, 610, + 518, 610, 542, 1688, 516, 1714, 542, 614, 516, 1688, 542, 612, 516, 1690, + 540, 614, 514, 1690, 520, 638, 516, 584, 518, 612, 542, 586, 540, 588, + 542, 1688, 520, 610, 540, 586, 520, 1712, 540, 1692, 542, 1688, 542, 1690, + 520, 1710, 518, 610, 518, 1712, 518, 1716, 544, 584, 544, 40870, + 8978, 4496, 542, 1690, 542, 1688, 520, 610, 542, 584, 516, 638, 514, 588, + 540, 588, 540, 1690, 516, 1716, 516, 614, 542, 1688, 518, 612, 542, 1688, + 540, 614, 514, 1692, 542, 588, 538, 590, 542, 586, 542, 612, 516, 612, + 514, 1692, 516, 612, 540, 586, 520, 1712, 518, 1714, 542, 1688, 518, 1716, + 542, 1688, 516, 614, 542, 1686, 518, 1714, 516, 612, 532, 40882, + 8976, 4498, 516, 1716, 542, 1690, 540, 614, 516, 614, 516, 614, 514, 588, + 540, 588, 544, 1688, 522, 1710, 518, 638, 516, 1688, 520, 636, 492, 1714, + 542, 586, 542, 1690, 542, 588, 542, 584, 542, 612, 516, 612, 514, 614, + 516, 1690, 542, 586, 542, 586, 540, 1690, 518, 1712, 518, 1716, 518, 1714, + 542, 1690, 542, 586, 540, 1690, 542, 1690, 542, 588, 540}; + irsend.sendRaw(rawData_0, 203, 38000); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(EPSON, irsend.capture.decode_type); + EXPECT_EQ(kEpsonBits, irsend.capture.bits); + EXPECT_EQ(0xC1AA09F6, irsend.capture.value); + EXPECT_EQ(0x5583, irsend.capture.address); + EXPECT_EQ(0x90, irsend.capture.command); + EXPECT_TRUE(irsend.capture.repeat); +} + +TEST(TestDecodeEpson, RequiresARepeat) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + // Simulate sending only two messages (mesg + repeat) + irsend.reset(); + irsend.sendEpson(0xC1AA09F6, kEpsonBits, 1); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(EPSON, irsend.capture.decode_type); + EXPECT_EQ(kEpsonBits, irsend.capture.bits); + EXPECT_EQ(0xC1AA09F6, irsend.capture.value); + EXPECT_EQ(0x5583, irsend.capture.address); + EXPECT_EQ(0x90, irsend.capture.command); + EXPECT_TRUE(irsend.capture.repeat); + + // Simulate sending no repeats (just 1 message) which should fail to be + // detected as Epson. + irsend.reset(); + irsend.sendEpson(0xC1AA09F6, kEpsonBits, 0); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_NE(EPSON, irsend.capture.decode_type); +} + +TEST(TestDecodeEpson, DecodeOnlyIfRepeatIsTheSame) { + IRsendTest irsend(kGpioUnused); + IRrecv irrecv(kGpioUnused); + irsend.begin(); + + // Simulate sending only two identical messages. + // This should succeed. + irsend.reset(); + irsend.sendEpson(0xC1AA09F6, kEpsonBits, 0); + irsend.sendEpson(0xC1AA09F6, kEpsonBits, 0); + + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(EPSON, irsend.capture.decode_type); + EXPECT_EQ(kEpsonBits, irsend.capture.bits); + EXPECT_EQ(0xC1AA09F6, irsend.capture.value); + EXPECT_EQ(0x5583, irsend.capture.address); + EXPECT_EQ(0x90, irsend.capture.command); + EXPECT_TRUE(irsend.capture.repeat); + + // Simulate sending a repeat but with a different code. + // This should fail. + irsend.reset(); + irsend.sendEpson(0xC1AA09F6, kEpsonBits, 0); // Valid code. + irsend.sendEpson(0x4BB640BF, kEpsonBits, 0); // Valid code but different. + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + ASSERT_NE(EPSON, irsend.capture.decode_type); +} + +TEST(TestUtils, Housekeeping) { + ASSERT_EQ("EPSON", typeToString(decode_type_t::EPSON)); + ASSERT_EQ(decode_type_t::EPSON, strToDecodeType("EPSON")); + ASSERT_FALSE(hasACState(decode_type_t::EPSON)); + ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::EPSON)); + ASSERT_EQ(kEpsonBits, IRsendTest::defaultBits(decode_type_t::EPSON)); + ASSERT_EQ(kEpsonMinRepeat, IRsendTest::minRepeats(decode_type_t::EPSON)); +} diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Fujitsu_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Fujitsu_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Fujitsu_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Fujitsu_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_GICable_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_GICable_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_GICable_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_GICable_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_GlobalCache_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_GlobalCache_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_GlobalCache_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_GlobalCache_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Goodweather_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Goodweather_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Goodweather_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Goodweather_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Gree_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Gree_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Gree_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Gree_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Haier_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Haier_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.3/test/ir_Haier_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Haier_test.cpp index db824a28e..ee55d2866 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Haier_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Haier_test.cpp @@ -768,7 +768,8 @@ TEST(TestDecodeHaierAC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendHaierAC(expectedState); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeHaierAC(&irsend.capture, kHaierACBits, true)); + ASSERT_TRUE(irrecv.decodeHaierAC(&irsend.capture, kStartOffset, kHaierACBits, + true)); EXPECT_EQ(HAIER_AC, irsend.capture.decode_type); EXPECT_EQ(kHaierACBits, irsend.capture.bits); EXPECT_FALSE(irsend.capture.repeat); diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Hitachi_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Hitachi_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Hitachi_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Hitachi_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Inax_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Inax_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Inax_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Inax_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_JVC_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_JVC_test.cpp similarity index 88% rename from lib/IRremoteESP8266-2.7.3/test/ir_JVC_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_JVC_test.cpp index 3cd99c3aa..51b16b82c 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_JVC_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_JVC_test.cpp @@ -110,7 +110,7 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(0xC2B8); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); @@ -122,7 +122,7 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(irsend.encodeJVC(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xE099, irsend.capture.value); @@ -134,7 +134,7 @@ TEST(TestDecodeJVC, NormalDecodeWithStrict) { irsend.reset(); irsend.sendJVC(irsend.encodeJVC(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0x8080, irsend.capture.value); @@ -153,7 +153,7 @@ TEST(TestDecodeJVC, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendJVC(0xC2B8, kJvcBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); @@ -162,14 +162,14 @@ TEST(TestDecodeJVC, NormalDecodeWithRepeatAndStrict) { EXPECT_FALSE(irsend.capture.repeat); irsend.makeDecodeResult(2 * kJvcBits + 4); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); EXPECT_TRUE(irsend.capture.repeat); irsend.makeDecodeResult(2 * kJvcBits + 4 + 2 * kJvcBits + 2); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, true)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(kJvcBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); @@ -203,9 +203,9 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.sendJVC(0x0, 8); // Illegal value JVC 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -216,13 +216,13 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.sendJVC(0x12345678, 32); // Illegal value JVC 32-bit message. irsend.makeDecodeResult(); // Should not pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, true)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kStartOffset, 32, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -235,11 +235,12 @@ TEST(TestDecodeJVC, DecodeWithNonStrictValues) { irsend.makeDecodeResult(); // Shouldn't pass if strict off and the wrong expected bits. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, false)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, + false)); // Re-decode with correct bit size. - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, 36, true)); - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 36, false)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kStartOffset, 36, true)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, 36, false)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(36, irsend.capture.bits); EXPECT_EQ(0x40C0, irsend.capture.value); @@ -258,7 +259,7 @@ TEST(TestDecodeJVC, Decode64BitMessages) { irsend.sendJVC(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeJVC(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(JVC, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -307,5 +308,6 @@ TEST(TestDecodeJVC, FailToDecodeNonJVCExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kJvcBits, false)); + ASSERT_FALSE(irrecv.decodeJVC(&irsend.capture, kStartOffset, kJvcBits, + false)); } diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Kelvinator_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Kelvinator_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Kelvinator_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Kelvinator_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_LG_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_LG_test.cpp similarity index 92% rename from lib/IRremoteESP8266-2.7.3/test/ir_LG_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_LG_test.cpp index 1c2b2a856..703ea3c6c 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_LG_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_LG_test.cpp @@ -151,7 +151,7 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { irsend.reset(); irsend.sendLG(0x4B4AE51, kLgBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x4B4AE51, irsend.capture.value); @@ -163,7 +163,7 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { irsend.reset(); irsend.sendLG(0xB4B4AE51, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, false)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0xB4B4AE51, irsend.capture.value); @@ -175,7 +175,7 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { irsend.reset(); irsend.sendLG(irsend.encodeLG(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); @@ -187,7 +187,7 @@ TEST(TestDecodeLG, NormalDecodeWithStrict) { irsend.reset(); irsend.sendLG(irsend.encodeLG(0x800, 0x8000), kLg32Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x80080008, irsend.capture.value); @@ -206,7 +206,7 @@ TEST(TestDecodeLG, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendLG(irsend.encodeLG(0x07, 0x99), kLgBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(kLgBits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); @@ -218,7 +218,7 @@ TEST(TestDecodeLG, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendLG(irsend.encodeLG(0x07, 0x99), kLg32Bits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x700992, irsend.capture.value); @@ -238,19 +238,20 @@ TEST(TestDecodeLG, DecodeWithNonStrictValues) { irsend.reset(); irsend.sendLG(0x1); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, + false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, false)); // Illegal LG 32-bit message value. irsend.reset(); irsend.sendLG(0x1111111, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, true)); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, false)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0x1111111, irsend.capture.value); @@ -261,7 +262,7 @@ TEST(TestDecodeLG, DecodeWithNonStrictValues) { irsend.reset(); irsend.sendLG(0x1111111, kLg32Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, false)); } // Decode unsupported LG message sizes. @@ -276,13 +277,14 @@ TEST(TestDecodeLG, DecodeWithNonStrictSizes) { irsend.sendLG(irsend.encodeLG(0x07, 0x99), 16); irsend.makeDecodeResult(); // Should fail when unexpected against different bit sizes. - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, + false)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 16, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, 16, false)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(16, irsend.capture.bits); EXPECT_EQ(0x992, irsend.capture.value); @@ -294,12 +296,13 @@ TEST(TestDecodeLG, DecodeWithNonStrictSizes) { irsend.sendLG(0x123456789, 36); // Illegal value LG 36-bit message. irsend.makeDecodeResult(); // Should fail when unexpected against different bit sizes. - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLg32Bits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, + false)); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 36, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, 36, false)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(36, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); @@ -318,9 +321,9 @@ TEST(TestDecodeLG, Decode64BitMessages) { // Illegal value & size LG 64-bit message. irsend.sendLG(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, 64, true)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, 64, true)); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -346,7 +349,7 @@ TEST(TestDecodeLG, DecodeGlobalCacheExample) { irsend.sendGC(gc_test, 75); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kLg32Bits, true)); + ASSERT_TRUE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLg32Bits, true)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(kLg32Bits, irsend.capture.bits); EXPECT_EQ(0xB4B4AE51, irsend.capture.value); @@ -371,7 +374,7 @@ TEST(TestDecodeLG, FailToDecodeNonLGExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeLG(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kLgBits, false)); + ASSERT_FALSE(irrecv.decodeLG(&irsend.capture, kStartOffset, kLgBits, false)); } // Tests for sendLG2(). @@ -451,6 +454,7 @@ TEST(TestDecodeLG, Issue620) { 532, 512, 530, 484, 556, 1536, 532}; // LG 8808721 irsend.sendRaw(rawData, 59, 38000); irsend.makeDecodeResult(); + ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(LG, irsend.capture.decode_type); EXPECT_EQ(28, irsend.capture.bits); diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Lasertag_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Lasertag_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Lasertag_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Lasertag_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Lego_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Lego_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Lego_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Lego_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Lutron_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Lutron_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Lutron_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Lutron_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_MWM_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_MWM_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_MWM_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_MWM_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Magiquest_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Magiquest_test.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/test/ir_Magiquest_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Magiquest_test.cpp index bbc5f3366..1e5faf5c0 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Magiquest_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Magiquest_test.cpp @@ -93,7 +93,8 @@ TEST(TestDecodeMagiQuest, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMagiQuest(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kStartOffset, + kMagiquestBits, true)); EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); EXPECT_EQ(kMagiquestBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -104,7 +105,8 @@ TEST(TestDecodeMagiQuest, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMagiQuest(irsend.encodeMagiQuest(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kStartOffset, + kMagiquestBits, true)); EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); EXPECT_EQ(kMagiquestBits, irsend.capture.bits); EXPECT_EQ(0x10001, irsend.capture.value); @@ -115,7 +117,8 @@ TEST(TestDecodeMagiQuest, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMagiQuest(irsend.encodeMagiQuest(0x12345678, 0xABCD)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kMagiquestBits, true)); + ASSERT_TRUE(irrecv.decodeMagiQuest(&irsend.capture, kStartOffset, + kMagiquestBits, true)); EXPECT_EQ(MAGIQUEST, irsend.capture.decode_type); EXPECT_EQ(kMagiquestBits, irsend.capture.bits); EXPECT_EQ(0x12345678ABCD, irsend.capture.value); diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Midea_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Midea_test.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/test/ir_Midea_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Midea_test.cpp index ebe291048..a43076fea 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Midea_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Midea_test.cpp @@ -478,7 +478,8 @@ TEST(TestDecodeMidea, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMidea(0x1234567890DF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + true)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(kMideaBits, irsend.capture.bits); EXPECT_EQ(0x1234567890DF, irsend.capture.value); @@ -490,7 +491,8 @@ TEST(TestDecodeMidea, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMidea(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + true)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(kMideaBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -502,7 +504,8 @@ TEST(TestDecodeMidea, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMidea(0xFFFFFFFFFFA0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + true)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(kMideaBits, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFA0, irsend.capture.value); @@ -534,20 +537,23 @@ TEST(TestDecodeMidea, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendMidea(0xA18263FFFF6E, kMideaBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + true)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(kMideaBits, irsend.capture.bits); EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); EXPECT_FALSE(irsend.capture.repeat); irsend.makeDecodeResult(2 * (2 * kMideaBits + 4)); - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + true)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(kMideaBits, irsend.capture.bits); EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); irsend.makeDecodeResult(4 * (2 * kMideaBits + 4)); - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + true)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(kMideaBits, irsend.capture.bits); EXPECT_EQ(0xA18263FFFF6E, irsend.capture.value); @@ -563,9 +569,10 @@ TEST(TestDecodeMidea, DecodeWithNonStrictSizes) { irsend.sendMidea(0x12, 8); // Illegal value Midea 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x12, irsend.capture.value); @@ -574,13 +581,14 @@ TEST(TestDecodeMidea, DecodeWithNonStrictSizes) { irsend.sendMidea(0x12345678, 32); // Illegal value Midea 32-bit message. irsend.makeDecodeResult(); // Shouldn't pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, true)); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kStartOffset, 32, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -589,7 +597,7 @@ TEST(TestDecodeMidea, DecodeWithNonStrictSizes) { irsend.reset(); irsend.sendMidea(0x123456, kMideaBits, 2); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, 9, false)); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kStartOffset, 9, false)); } // Decode (non-standard) 64-bit messages. @@ -603,7 +611,7 @@ TEST(TestDecodeMidea, Decode64BitMessages) { irsend.sendMidea(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -625,7 +633,8 @@ TEST(TestDecodeMidea, FailToDecodeNonMideaExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kMideaBits, false)); + ASSERT_FALSE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + false)); } // Decode against a real capture reported by a user. See issue #354 @@ -768,7 +777,8 @@ TEST(TestDecodeMidea, Issue887) { irsend.reset(); irsend.sendMidea(hwaddr); irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeMidea(&irsend.capture, kMideaBits, false)); + EXPECT_TRUE(irrecv.decodeMidea(&irsend.capture, kStartOffset, kMideaBits, + false)); EXPECT_EQ(MIDEA, irsend.capture.decode_type); EXPECT_EQ(kMideaBits, irsend.capture.bits); EXPECT_EQ(hwaddr, irsend.capture.value); diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_MitsubishiHeavy_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_MitsubishiHeavy_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_MitsubishiHeavy_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_MitsubishiHeavy_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Mitsubishi_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Mitsubishi_test.cpp similarity index 96% rename from lib/IRremoteESP8266-2.7.3/test/ir_Mitsubishi_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Mitsubishi_test.cpp index 8236777b5..4f759c046 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Mitsubishi_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Mitsubishi_test.cpp @@ -143,7 +143,8 @@ TEST(TestDecodeMitsubishi, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMitsubishi(0xC2B8); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); @@ -154,7 +155,8 @@ TEST(TestDecodeMitsubishi, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMitsubishi(0x0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -165,7 +167,8 @@ TEST(TestDecodeMitsubishi, NormalDecodeWithStrict) { irsend.reset(); irsend.sendMitsubishi(0xFFFF); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); EXPECT_EQ(0xFFFF, irsend.capture.value); @@ -178,17 +181,24 @@ TEST(TestDecodeMitsubishi, NormalDecodeWithStrict) { // 12 bits. irsend.sendMitsubishi(0xFFF, 12); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 12, + true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 64, + true)); // 32 bits. irsend.sendMitsubishi(0xFFF, 32); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 12, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 32, true)); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 12, + true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 32, + true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 64, + true)); } // Decode normal repeated Mitsubishi messages. @@ -201,7 +211,8 @@ TEST(TestDecodeMitsubishi, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendMitsubishi(0xC2B8, kMitsubishiBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); @@ -213,7 +224,8 @@ TEST(TestDecodeMitsubishi, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendMitsubishi(0xC2B8, kMitsubishiBits, 0); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); EXPECT_EQ(kMitsubishiBits, irsend.capture.bits); EXPECT_EQ(0xC2B8, irsend.capture.value); @@ -232,31 +244,36 @@ TEST(TestDecodeMitsubishi, DecodeWithNonStrictValues) { irsend.sendMitsubishi(0x0, 8); // Illegal sized Mitsubishi 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 64, + false)); irsend.reset(); // Illegal sized Mitsubishi 64-bit message. irsend.sendMitsubishi(0xFEDCBA9876543210, 64); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, true)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, + kMitsubishiBits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 64, + false)); EXPECT_EQ(MITSUBISHI, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFEDCBA9876543210, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); // Should fail when we are after a shorter message than we got. - ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, 8, false)); + ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, 8, + false)); } // Decode a 'real' example via GlobalCache @@ -299,7 +316,8 @@ TEST(TestDecodeMitsubishi, FailToDecodeNonMitsubishiExample) { ASSERT_FALSE(irrecv.decodeMitsubishi(&irsend.capture)); ASSERT_FALSE( - irrecv.decodeMitsubishi(&irsend.capture, kMitsubishiBits, false)); + irrecv.decodeMitsubishi(&irsend.capture, kStartOffset, kMitsubishiBits, + false)); } // Tests for Mitsubishi A/C methods. diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_NEC_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_NEC_test.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/test/ir_NEC_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_NEC_test.cpp index c881b7b44..f7598c981 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_NEC_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_NEC_test.cpp @@ -162,7 +162,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithoutStrict) { irsend.reset(); irsend.sendNEC(0x0); irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 32, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0, irsend.capture.value); @@ -172,7 +172,7 @@ TEST(TestDecodeNEC, NormalNECDecodeWithoutStrict) { irsend.reset(); irsend.sendNEC(0x12345678); irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 32, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -189,7 +189,7 @@ TEST(TestDecodeNEC, ShortNECDecodeWithoutStrict) { irsend.reset(); irsend.sendNEC(0x0, 16); irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 16, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 16, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); EXPECT_EQ(16, irsend.capture.bits); EXPECT_EQ(0, irsend.capture.value); @@ -200,13 +200,13 @@ TEST(TestDecodeNEC, ShortNECDecodeWithoutStrict) { irsend.reset(); irsend.sendNEC(0x0, 32); irsend.makeDecodeResult(); - EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, 16, false)); + EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 16, false)); // Send 16 bits of data, but fail because we are expecting 17. irsend.reset(); irsend.sendNEC(0x0, 16); irsend.makeDecodeResult(); - EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, 17, false)); + EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 17, false)); } // Longer NEC-like messages (without strict naturally) @@ -218,7 +218,7 @@ TEST(TestDecodeNEC, LongerNECDecodeWithoutStrict) { irsend.reset(); irsend.sendNEC(0x1234567890ABCDEF, 64); irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, 64, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0x1234567890ABCDEF, irsend.capture.value); @@ -229,7 +229,7 @@ TEST(TestDecodeNEC, LongerNECDecodeWithoutStrict) { irsend.reset(); irsend.sendNEC(0x0, 63); irsend.makeDecodeResult(); - EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, 64, false)); + EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 64, false)); } // Incorrect decoding reported in Issue #243 @@ -299,7 +299,7 @@ TEST(TestDecodeNEC, NonStrictNECDecode_Issue264) { irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); EXPECT_FALSE(irrecv.decodeNEC(&irsend.capture)); // Not strictly NEC - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, kNECBits, false)); EXPECT_EQ(0x77E1A040, irsend.capture.value); // Do it all again, but with a normal decode. @@ -331,7 +331,7 @@ TEST(TestDecodeNEC, AutoReceiveCalibration) { irsend.sendRaw(rawData, 67, 38); irsend.makeDecodeResult(); - EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kNECBits, false)); + EXPECT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, kNECBits, false)); EXPECT_EQ(NEC, irsend.capture.decode_type); EXPECT_EQ(kNECBits, irsend.capture.bits); EXPECT_EQ(0x77E1A040, irsend.capture.value); diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Neoclima_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Neoclima_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Neoclima_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Neoclima_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Nikai_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Nikai_test.cpp similarity index 87% rename from lib/IRremoteESP8266-2.7.3/test/ir_Nikai_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Nikai_test.cpp index fff242326..98d6d806d 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Nikai_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Nikai_test.cpp @@ -77,7 +77,8 @@ TEST(TestDecodeNikai, NormalDecodeWithStrict) { irsend.reset(); irsend.sendNikai(0x123456); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kStartOffset, kNikaiBits, + true)); EXPECT_EQ(NIKAI, irsend.capture.decode_type); EXPECT_EQ(kNikaiBits, irsend.capture.bits); EXPECT_EQ(0x123456, irsend.capture.value); @@ -85,7 +86,8 @@ TEST(TestDecodeNikai, NormalDecodeWithStrict) { irsend.reset(); irsend.sendNikai(0x101); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kStartOffset, kNikaiBits, + true)); EXPECT_EQ(NIKAI, irsend.capture.decode_type); EXPECT_EQ(kNikaiBits, irsend.capture.bits); EXPECT_EQ(0x101, irsend.capture.value); @@ -101,7 +103,8 @@ TEST(TestDecodeNikai, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendNikai(0xD5F2A, kNikaiBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kStartOffset, kNikaiBits, + true)); EXPECT_EQ(NIKAI, irsend.capture.decode_type); EXPECT_EQ(kNikaiBits, irsend.capture.bits); EXPECT_EQ(0xD5F2A, irsend.capture.value); @@ -117,18 +120,20 @@ TEST(TestDecodeNikai, NormalDecodeWithNonStrict) { irsend.sendNikai(0x0, 16); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kStartOffset, kNikaiBits, + true)); // And it should fail when we expect more bits. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, false)); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kStartOffset, kNikaiBits, + false)); // Should pass if strict off if we ask for correct nr. of bits sent. - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 16, false)); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kStartOffset, 16, false)); EXPECT_EQ(NIKAI, irsend.capture.decode_type); EXPECT_EQ(16, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); // Should fail as we are expecting less bits than there are. - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, 12, false)); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kStartOffset, 12, false)); } // Decode (non-standard) 64-bit messages. @@ -142,9 +147,10 @@ TEST(TestDecodeNikai, Decode64BitMessages) { // Illegal size Nikai 64-bit message. irsend.sendNikai(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, true)); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kStartOffset, kNikaiBits, + true)); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeNikai(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(NIKAI, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -211,5 +217,6 @@ TEST(TestDecodeNikai, FailToDecodeNonNikaiExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kNikaiBits, false)); + ASSERT_FALSE(irrecv.decodeNikai(&irsend.capture, kStartOffset, kNikaiBits, + false)); } diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Panasonic_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Panasonic_test.cpp similarity index 95% rename from lib/IRremoteESP8266-2.7.3/test/ir_Panasonic_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Panasonic_test.cpp index 97f9bbb28..7f022ed17 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Panasonic_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Panasonic_test.cpp @@ -219,7 +219,8 @@ TEST(TestDecodePanasonic, NormalDecodeWithStrict) { irsend.reset(); irsend.sendPanasonic64(0x40040190ED7C); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x40040190ED7C, irsend.capture.value); @@ -231,7 +232,8 @@ TEST(TestDecodePanasonic, NormalDecodeWithStrict) { irsend.reset(); irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x12, 0x34, 0x56)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x400412345670, irsend.capture.value); @@ -243,7 +245,8 @@ TEST(TestDecodePanasonic, NormalDecodeWithStrict) { irsend.reset(); irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 0x1, 0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x400401010101, irsend.capture.value); @@ -262,7 +265,8 @@ TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendPanasonic64(0x40040190ED7C, kPanasonicBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x40040190ED7C, irsend.capture.value); @@ -271,13 +275,15 @@ TEST(TestDecodePanasonic, NormalDecodeWithRepeatAndStrict) { EXPECT_FALSE(irsend.capture.repeat); irsend.makeDecodeResult(2 * kPanasonicBits + 4); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x40040190ED7C, irsend.capture.value); irsend.makeDecodeResult(2 * (2 * kPanasonicBits + 4)); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x40040190ED7C, irsend.capture.value); @@ -293,9 +299,11 @@ TEST(TestDecodePanasonic, DecodeWithNonStrictValues) { irsend.sendPanasonic64(0x0); // Illegal value Panasonic 48-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, false)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -307,9 +315,11 @@ TEST(TestDecodePanasonic, DecodeWithNonStrictValues) { irsend.sendPanasonic64(irsend.encodePanasonic(0, 1, 2, 3)); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, false)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x1020300, irsend.capture.value); @@ -327,13 +337,14 @@ TEST(TestDecodePanasonic, DecodeWithNonStrictSize) { irsend.sendPanasonic64(0x12345678, 32); // Illegal size Panasonic message. irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 32, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -345,12 +356,14 @@ TEST(TestDecodePanasonic, DecodeWithNonStrictSize) { irsend.sendPanasonic64(irsend.encodePanasonic(0x4004, 1, 2, 3), 56); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); // Shouldn't pass if strict off and wrong bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, false)); // Re-decode with correct bit size. - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 56, true)); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 56, false)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 56, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 56, false)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(56, irsend.capture.bits); EXPECT_EQ(0x400401020300, irsend.capture.value); @@ -368,9 +381,9 @@ TEST(TestDecodePanasonic, Decode64BitMessages) { // Illegal value & size Panasonic 64-bit message. irsend.sendPanasonic64(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, 64, true)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 64, true)); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -397,7 +410,8 @@ TEST(TestDecodePanasonic, DecodeGlobalCacheExample) { irsend.sendGC(gc_test, 103); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, true)); + ASSERT_TRUE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, true)); EXPECT_EQ(PANASONIC, irsend.capture.decode_type); EXPECT_EQ(kPanasonicBits, irsend.capture.bits); EXPECT_EQ(0x40040190ED7C, irsend.capture.value); @@ -430,7 +444,8 @@ TEST(TestDecodePanasonic, FailToDecodeNonPanasonicExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture)); - ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kPanasonicBits, false)); + ASSERT_FALSE(irrecv.decodePanasonic(&irsend.capture, kStartOffset, + kPanasonicBits, false)); } // Failing to decode Panasonic in Issue #245 diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Pioneer_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Pioneer_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Pioneer_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Pioneer_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Pronto_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Pronto_test.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/test/ir_Pronto_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Pronto_test.cpp index 513f985da..b5020987f 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Pronto_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Pronto_test.cpp @@ -366,3 +366,28 @@ TEST(TestSendPronto, NormalPlusRepeatSequence) { "m8892s2210m546s95212", irsend.outputStr()); } + +// Tests for #1034 +TEST(TestSendPronto, Issue1034) { + IRsendTest irsend(0); + IRrecv irrecv(0); + irsend.begin(); + + // JVC code allegedly. + uint16_t pronto_test[40] = { + 0x0000, 0x006c, 0x0001, 0x0011, 0x0140, 0x00a0, 0x0014, 0x003c, 0x0014, + 0x003c, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x003c, + 0x0014, 0x0014, 0x0014, 0x003c, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, + 0x0014, 0x0014, 0x0014, 0x0014, 0x003c, 0x0014, 0x0014, 0x0014, 0x0014, + 0x0014, 0x0014, 0x0014, 0x0384}; + + irsend.reset(); + irsend.sendPronto(pronto_test, 40, 1); + irsend.makeDecodeResult(); + EXPECT_TRUE(irrecv.decode(&irsend.capture)); + EXPECT_EQ(JVC, irsend.capture.decode_type); + EXPECT_EQ(kJvcBits, irsend.capture.bits); + EXPECT_EQ(0xc508, irsend.capture.value); + EXPECT_EQ(0xa3, irsend.capture.address); + EXPECT_EQ(0x10, irsend.capture.command); +} diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_RC5_RC6_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_RC5_RC6_test.cpp similarity index 88% rename from lib/IRremoteESP8266-2.7.3/test/ir_RC5_RC6_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_RC5_RC6_test.cpp index da9fa027c..0b46bad7f 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_RC5_RC6_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_RC5_RC6_test.cpp @@ -202,7 +202,7 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); @@ -214,7 +214,7 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5XBits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); @@ -227,7 +227,7 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(0x175, kRC5XBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5XBits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); @@ -239,7 +239,7 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(irsend.encodeRC5(0x00, 0x0B, true)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x80B, irsend.capture.value); @@ -251,7 +251,7 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5XBits, true)); EXPECT_EQ(RC5X, irsend.capture.decode_type); EXPECT_EQ(kRC5XBits, irsend.capture.bits); EXPECT_EQ(0x1881, irsend.capture.value); @@ -264,7 +264,7 @@ TEST(TestDecodeRC5, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, true)); } // Decode normal repeated RC5 messages. @@ -277,7 +277,7 @@ TEST(TestDecodeRC5, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendRC5(0x174, kRC5Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); @@ -288,7 +288,7 @@ TEST(TestDecodeRC5, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendRC5(0x175, kRC5Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, true)); EXPECT_EQ(RC5, irsend.capture.decode_type); EXPECT_EQ(kRC5Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); @@ -299,7 +299,7 @@ TEST(TestDecodeRC5, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendRC5(irsend.encodeRC5X(0x02, 0x41, true), kRC5XBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5XBits, true)); EXPECT_EQ(RC5X, irsend.capture.decode_type); EXPECT_EQ(kRC5XBits, irsend.capture.bits); EXPECT_EQ(0x1881, irsend.capture.value); @@ -317,10 +317,11 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0xFA, 8); // Illegal value RC5 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5XBits, + true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(RC5, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0xFA, irsend.capture.value); @@ -331,14 +332,15 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0x12345678, 32); // Illegal size RC5 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5XBits, + true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, 32, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(RC5, irsend.capture.decode_type); EXPECT_EQ(31, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -347,14 +349,15 @@ TEST(TestDecodeRC5, DecodeWithNonStrictValues) { irsend.sendRC5(0x87654321, 32); // Illegal size RC5 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, true)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5XBits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5XBits, + true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, 32, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(RC5X, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x87654321, irsend.capture.value); @@ -371,7 +374,7 @@ TEST(TestDecodeRC5, Decode64BitMessages) { irsend.sendRC5(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeRC5(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(RC5X, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -392,7 +395,8 @@ TEST(TestDecodeRC5, FailToDecodeNonRC5Example) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kRC5Bits, false)); + ASSERT_FALSE(irrecv.decodeRC5(&irsend.capture, kStartOffset, kRC5Bits, + false)); } // RRRRRR CCCCC 666 @@ -688,7 +692,8 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { irsend.reset(); irsend.sendRC6(0x175); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); @@ -700,7 +705,8 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { irsend.reset(); irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, kRC6Mode0Bits)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x56789, irsend.capture.value); @@ -712,7 +718,8 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithStrict) { irsend.reset(); irsend.sendRC6(0x123456789, kRC6Mode0Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x56789, irsend.capture.value); @@ -731,7 +738,8 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithStrict) { irsend.reset(); irsend.sendRC6(0x175, kRC6_36Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6_36Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); @@ -743,7 +751,8 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithStrict) { irsend.reset(); irsend.sendRC6(irsend.encodeRC6(0x1234567, 0x89, kRC6_36Bits), kRC6_36Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6_36Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); @@ -762,7 +771,8 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendRC6(0x174, kRC6Mode0Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); @@ -773,7 +783,8 @@ TEST(TestDecodeRC6, NormalMode0DecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendRC6(0x175, kRC6Mode0Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6Mode0Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); @@ -791,7 +802,8 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendRC6(0x175, kRC6_36Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6_36Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x175, irsend.capture.value); @@ -802,7 +814,8 @@ TEST(TestDecodeRC6, Normal36BitDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendRC6(0x174, kRC6_36Bits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6_36Bits, + true)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0x174, irsend.capture.value); @@ -881,7 +894,7 @@ TEST(TestDecodeRC6, Decode36BitGlobalCacheExample) { irsend.sendGC(gc_test, 65); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits)); + ASSERT_TRUE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6_36Bits)); EXPECT_EQ(RC6, irsend.capture.decode_type); EXPECT_EQ(kRC6_36Bits, irsend.capture.bits); EXPECT_EQ(0xC800F742A, irsend.capture.value); @@ -905,18 +918,26 @@ TEST(TestDecodeRC5, FailToDecodeNonRC6Example) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, false)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6_36Bits, + true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, kStartOffset, + false)); irsend.reset(); irsend.sendRC5(0x0); irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6Mode0Bits, false)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, true)); - ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6Mode0Bits, + false)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kStartOffset, kRC6_36Bits, + true)); + ASSERT_FALSE(irrecv.decodeRC6(&irsend.capture, kRC6_36Bits, kStartOffset, + false)); } diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_RCMM_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_RCMM_test.cpp similarity index 86% rename from lib/IRremoteESP8266-2.7.3/test/ir_RCMM_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_RCMM_test.cpp index 22306a59b..ef37d87a6 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_RCMM_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_RCMM_test.cpp @@ -91,7 +91,8 @@ TEST(TestDecodeRCMM, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRCMM(0xe0a600); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kRCMMBits, true)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, kRCMMBits, + true)); EXPECT_EQ(RCMM, irsend.capture.decode_type); EXPECT_EQ(kRCMMBits, irsend.capture.bits); EXPECT_EQ(0xe0a600, irsend.capture.value); @@ -103,7 +104,7 @@ TEST(TestDecodeRCMM, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRCMM(0x600, 12); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 12, true)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 12, true)); EXPECT_EQ(RCMM, irsend.capture.decode_type); EXPECT_EQ(12, irsend.capture.bits); EXPECT_EQ(0x600, irsend.capture.value); @@ -115,7 +116,7 @@ TEST(TestDecodeRCMM, NormalDecodeWithStrict) { irsend.reset(); irsend.sendRCMM(0x28e0a600, 32); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 32, true)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 32, true)); EXPECT_EQ(RCMM, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x28e0a600, irsend.capture.value); @@ -134,15 +135,15 @@ TEST(TestDecodeRCMM, IllegalDecodeWithStrict) { irsend.reset(); irsend.sendRCMM(0x0, 8); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, 8, true)); - ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, 12, true)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 8, true)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 12, true)); // Illegal RCMM 36-bit message. irsend.reset(); irsend.sendRCMM(0x0, 36); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, 12, true)); - ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, 36, true)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 12, true)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 36, true)); } // Decodes without strict mode. @@ -155,13 +156,13 @@ TEST(TestDecodeRCMM, DecodeWithoutStrict) { irsend.reset(); irsend.sendRCMM(0x55, 8); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(RCMM, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x55, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 12, false)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 12, false)); EXPECT_EQ(RCMM, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x55, irsend.capture.value); @@ -172,18 +173,18 @@ TEST(TestDecodeRCMM, DecodeWithoutStrict) { irsend.reset(); irsend.sendRCMM(0x123456789, 36); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 12, false)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 12, false)); EXPECT_EQ(RCMM, irsend.capture.decode_type); EXPECT_EQ(36, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 24, false)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 24, false)); EXPECT_EQ(36, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); EXPECT_EQ(0x0, irsend.capture.address); EXPECT_EQ(0x0, irsend.capture.command); - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 36, false)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 36, false)); EXPECT_EQ(RCMM, irsend.capture.decode_type); EXPECT_EQ(36, irsend.capture.bits); EXPECT_EQ(0x123456789, irsend.capture.value); @@ -202,7 +203,7 @@ TEST(TestDecodeRCMM, Decode64BitMessages) { irsend.sendRCMM(0xFEDCBA9876543210, 64); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(RCMM, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFEDCBA9876543210, irsend.capture.value); @@ -226,7 +227,8 @@ TEST(TestDecodeRCMM, FailToDecodeNonRCMMExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, kRCMMBits, false)); + ASSERT_FALSE(irrecv.decodeRCMM(&irsend.capture, kStartOffset, kRCMMBits, + false)); } // Issue 281 Debugging diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Samsung_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Samsung_test.cpp similarity index 93% rename from lib/IRremoteESP8266-2.7.3/test/ir_Samsung_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Samsung_test.cpp index 9a572c631..c44572934 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Samsung_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Samsung_test.cpp @@ -107,7 +107,8 @@ TEST(TestDecodeSamsung, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSAMSUNG(0xE0E09966); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + true)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(kSamsungBits, irsend.capture.bits); EXPECT_EQ(0xE0E09966, irsend.capture.value); @@ -118,7 +119,8 @@ TEST(TestDecodeSamsung, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + true)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(kSamsungBits, irsend.capture.bits); EXPECT_EQ(0xE0E09966, irsend.capture.value); @@ -129,7 +131,8 @@ TEST(TestDecodeSamsung, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + true)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(kSamsungBits, irsend.capture.bits); EXPECT_EQ(0x8080807F, irsend.capture.value); @@ -147,7 +150,8 @@ TEST(TestDecodeSamsung, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendSAMSUNG(0xE0E09966, kSamsungBits, 2); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + true)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(kSamsungBits, irsend.capture.bits); EXPECT_EQ(0xE0E09966, irsend.capture.value); @@ -165,9 +169,11 @@ TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { irsend.sendSAMSUNG(0x0); // Illegal value Samsung 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + false)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(kSamsungBits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -178,9 +184,11 @@ TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { irsend.sendSAMSUNG(0x12345678); // Illegal value Samsung 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + false)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(kSamsungBits, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -192,12 +200,14 @@ TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { irsend.sendSAMSUNG(irsend.encodeSAMSUNG(0, 0), 36); irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + true)); // Shouldn't pass if strict off and wrong expected bit size. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + false)); // Re-decode with correct bit size. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 36, true)); - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 36, false)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, 36, true)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, 36, false)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(36, irsend.capture.bits); EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 8 bits less. @@ -214,7 +224,7 @@ TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); // Should pass if strict off if we ask for correct nr. of bits sent. - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 16, false)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, 16, false)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(16, irsend.capture.bits); EXPECT_EQ(0xFF, irsend.capture.value); // We told it to expect 4 bits less. @@ -222,7 +232,7 @@ TEST(TestDecodeSamsung, DecodeWithNonStrictValues) { EXPECT_EQ(0x00, irsend.capture.command); // Should fail as we are expecting less bits than there are. - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, 12, false)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, 12, false)); } // Decode (non-standard) 64-bit messages. @@ -236,9 +246,10 @@ TEST(TestDecodeSamsung, Decode64BitMessages) { // Illegal value & size Samsung 64-bit message. irsend.sendSAMSUNG(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, true)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + true)); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(SAMSUNG, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -289,7 +300,8 @@ TEST(TestDecodeSamsung, FailToDecodeNonSamsungExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kSamsungBits, false)); + ASSERT_FALSE(irrecv.decodeSAMSUNG(&irsend.capture, kStartOffset, kSamsungBits, + false)); } // General housekeeping @@ -451,6 +463,26 @@ TEST(TestIRSamsungAcClass, SetAndGetBeep) { EXPECT_TRUE(samsung.getBeep()); } +TEST(TestIRSamsungAcClass, SetAndGetDisplay) { + IRSamsungAc ac(0); + ac.setDisplay(true); + EXPECT_TRUE(ac.getDisplay()); + ac.setDisplay(false); + EXPECT_FALSE(ac.getDisplay()); + ac.setDisplay(true); + EXPECT_TRUE(ac.getDisplay()); +} + +TEST(TestIRSamsungAcClass, SetAndGetIon) { + IRSamsungAc ac(0); + ac.setIon(true); + EXPECT_TRUE(ac.getIon()); + ac.setIon(false); + EXPECT_FALSE(ac.getIon()); + ac.setIon(true); + EXPECT_TRUE(ac.getIon()); +} + TEST(TestIRSamsungAcClass, SetAndGetTemp) { IRSamsungAc samsung(0); samsung.setTemp(25); @@ -549,7 +581,8 @@ TEST(TestIRSamsungAcClass, SetAndGetPowerful) { EXPECT_EQ(kSamsungAcFanTurbo, ac.getFan()); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 7 (Turbo), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: On", ac.toString()); + "Beep: Off, Clean: Off, Quiet: Off, Powerful: On, Light: On, Ion: Off", + ac.toString()); uint8_t off[kSamsungAcStateLength] = { 0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, @@ -559,7 +592,8 @@ TEST(TestIRSamsungAcClass, SetAndGetPowerful) { EXPECT_NE(kSamsungAcFanTurbo, ac.getFan()); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", ac.toString()); + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", + ac.toString()); } TEST(TestIRSamsungAcClass, QuietAndPowerfulAreMutuallyExclusive) { @@ -624,7 +658,7 @@ TEST(TestIRSamsungAcClass, HumanReadable) { IRSamsungAc samsung(0); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 2 (Low), Swing: On, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); samsung.setTemp(kSamsungAcMaxTemp); samsung.setMode(kSamsungAcHeat); @@ -635,18 +669,24 @@ TEST(TestIRSamsungAcClass, HumanReadable) { samsung.setClean(true); EXPECT_EQ( "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 5 (High), Swing: Off, " - "Beep: On, Clean: On, Quiet: Off, Powerful: Off", + "Beep: On, Clean: On, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); samsung.setQuiet(true); EXPECT_EQ( "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 0 (Auto), Swing: Off, " - "Beep: On, Clean: On, Quiet: On, Powerful: Off", + "Beep: On, Clean: On, Quiet: On, Powerful: Off, Light: On, Ion: Off", samsung.toString()); samsung.setQuiet(false); samsung.setPowerful(true); EXPECT_EQ( "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 7 (Turbo), Swing: Off, " - "Beep: On, Clean: On, Quiet: Off, Powerful: On", + "Beep: On, Clean: On, Quiet: Off, Powerful: On, Light: On, Ion: Off", + samsung.toString()); + samsung.setIon(true); + samsung.setDisplay(false); + EXPECT_EQ( + "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 7 (Turbo), Swing: Off, " + "Beep: On, Clean: On, Quiet: Off, Powerful: On, Light: Off, Ion: On", samsung.toString()); } @@ -750,7 +790,7 @@ TEST(TestDecodeSamsungAC, DecodeRealExample) { samsung.setRaw(irsend.capture.state); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 2 (Low), Swing: On, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); } @@ -799,7 +839,7 @@ TEST(TestDecodeSamsungAC, DecodeRealExample2) { samsung.setRaw(irsend.capture.state); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); } @@ -858,7 +898,7 @@ TEST(TestDecodeSamsungAC, DecodePowerOnSample) { samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); } @@ -918,7 +958,7 @@ TEST(TestDecodeSamsungAC, DecodePowerOffSample) { samsung.setRaw(irsend.capture.state, kSamsungAcExtendedStateLength); EXPECT_EQ( "Power: Off, Mode: 1 (Cool), Temp: 24C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); } @@ -965,7 +1005,7 @@ TEST(TestDecodeSamsungAC, DecodeHeatSample) { samsung.setRaw(irsend.capture.state); EXPECT_EQ( "Power: On, Mode: 4 (Heat), Temp: 17C, Fan: 0 (Auto), Swing: On, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); } @@ -1012,7 +1052,7 @@ TEST(TestDecodeSamsungAC, DecodeCoolSample) { samsung.setRaw(irsend.capture.state); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 20C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); } @@ -1070,7 +1110,7 @@ TEST(TestDecodeSamsungAC, Issue604DecodeExtended) { samsung.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( "Power: Off, Mode: 4 (Heat), Temp: 30C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", samsung.toString()); } @@ -1267,7 +1307,7 @@ TEST(TestIRSamsungAcClass, Issue604SendPowerHack) { "m586s100000"; std::string text = "Power: On, Mode: 1 (Cool), Temp: 23C, Fan: 4 (Med), " "Swing: On, Beep: Off, Clean: Off, Quiet: Off, " - "Powerful: Off"; + "Powerful: Off, Light: On, Ion: Off"; // Don't do a setPower()/on()/off() as that will trigger the special message. // So it should only be the normal "settings" message. ac.setTemp(23); @@ -1328,6 +1368,8 @@ TEST(TestIRSamsungAcClass, toCommon) { ac.setBeep(true); ac.setClean(true); ac.setQuiet(true); + ac.setDisplay(true); + ac.setIon(true); // Now test it. ASSERT_EQ(decode_type_t::SAMSUNG_AC, ac.toCommon().protocol); ASSERT_EQ(-1, ac.toCommon().model); @@ -1339,13 +1381,13 @@ TEST(TestIRSamsungAcClass, toCommon) { ASSERT_EQ(stdAc::swingv_t::kAuto, ac.toCommon().swingv); ASSERT_FALSE(ac.toCommon().turbo); ASSERT_TRUE(ac.toCommon().quiet); + ASSERT_TRUE(ac.toCommon().light); + ASSERT_TRUE(ac.toCommon().filter); ASSERT_TRUE(ac.toCommon().clean); ASSERT_TRUE(ac.toCommon().beep); // Unsupported. ASSERT_EQ(stdAc::swingh_t::kOff, ac.toCommon().swingh); ASSERT_FALSE(ac.toCommon().econo); - ASSERT_FALSE(ac.toCommon().light); - ASSERT_FALSE(ac.toCommon().filter); ASSERT_EQ(-1, ac.toCommon().sleep); ASSERT_EQ(-1, ac.toCommon().clock); } @@ -1392,7 +1434,7 @@ TEST(TestDecodeSamsungAC, Issue734QuietSetting) { ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: On, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: On, Powerful: Off, Light: On, Ion: Off", ac.toString()); // Make sure the ac class state is in something wildly different first. @@ -1414,7 +1456,7 @@ TEST(TestDecodeSamsungAC, Issue734QuietSetting) { ac.setQuiet(true); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: On, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: On, Powerful: Off, Light: On, Ion: Off", ac.toString()); // Check it matches the known good/expected state. EXPECT_STATE_EQ(expectedState, ac.getRaw(), kSamsungAcBits); @@ -1464,6 +1506,6 @@ TEST(TestDecodeSamsungAC, Issue734PowerfulOff) { ac.setRaw(irsend.capture.state, irsend.capture.bits / 8); EXPECT_EQ( "Power: On, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Swing: Off, " - "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off", + "Beep: Off, Clean: Off, Quiet: Off, Powerful: Off, Light: On, Ion: Off", ac.toString()); } diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Sanyo_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Sanyo_test.cpp similarity index 81% rename from lib/IRremoteESP8266-2.7.3/test/ir_Sanyo_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Sanyo_test.cpp index 165e29f17..c59113cda 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Sanyo_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Sanyo_test.cpp @@ -71,7 +71,8 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.sendSanyoLC7461(0x1D8113F00FF); irsend.makeDecodeResult(); ASSERT_TRUE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); @@ -84,7 +85,8 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.sendSanyoLC7461(irsend.encodeSanyoLC7461(0x1234, 0x56)); irsend.makeDecodeResult(); ASSERT_TRUE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x2468DCB56A9, irsend.capture.value); @@ -97,7 +99,8 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithStrict) { irsend.sendSanyoLC7461(irsend.encodeSanyoLC7461(0x1, 0x1)); irsend.makeDecodeResult(); ASSERT_TRUE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x3FFE01FE, irsend.capture.value); @@ -117,7 +120,8 @@ TEST(TestDecodeSanyoLC7461, NormalDecodeWithRepeatAndStrict) { irsend.sendSanyoLC7461(0x3FFE01FE, kSanyoLC7461Bits, 1); irsend.makeDecodeResult(); ASSERT_TRUE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x3FFE01FE, irsend.capture.value); @@ -137,10 +141,12 @@ TEST(TestDecodeSanyoLC7461, DecodeWithNonStrictValues) { irsend.makeDecodeResult(); // Should fail with strict on. ASSERT_FALSE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + true)); // Should pass if strict off. ASSERT_TRUE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + false)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -152,17 +158,22 @@ TEST(TestDecodeSanyoLC7461, DecodeWithNonStrictValues) { irsend.sendSanyoLC7461(0x1234567890A); irsend.makeDecodeResult(); ASSERT_FALSE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + true)); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 32, true)); - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 64, true)); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, 32, + true)); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, 64, + true)); // And should fail for a bad value. ASSERT_FALSE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + true)); // Should pass if strict off. ASSERT_TRUE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + false)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x1234567890A, irsend.capture.value); @@ -170,7 +181,8 @@ TEST(TestDecodeSanyoLC7461, DecodeWithNonStrictValues) { EXPECT_EQ(0x89, irsend.capture.command); // Shouldn't pass if strict off and looking for a smaller size. - ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, 34, false)); + ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, 34, + false)); } // Decode (non-standard) 64-bit messages. @@ -184,7 +196,8 @@ TEST(TestDecodeSanyoLC7461, Decode64BitMessages) { irsend.sendSanyoLC7461(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, 64, + false)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -210,7 +223,8 @@ TEST(TestDecodeSanyoLC7461, DecodeGlobalCacheExample) { irsend.makeDecodeResult(); ASSERT_TRUE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, true)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + true)); EXPECT_EQ(SANYO_LC7461, irsend.capture.decode_type); EXPECT_EQ(kSanyoLC7461Bits, irsend.capture.bits); EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); @@ -219,7 +233,7 @@ TEST(TestDecodeSanyoLC7461, DecodeGlobalCacheExample) { EXPECT_FALSE(irsend.capture.repeat); // Confirm what the 42-bit NEC decode is. - ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, 42, false)); + ASSERT_TRUE(irrecv.decodeNEC(&irsend.capture, kStartOffset, 42, false)); EXPECT_EQ(0x1D8113F00FF, irsend.capture.value); } @@ -240,5 +254,6 @@ TEST(TestDecodeSanyoLC7461, FailToDecodeNonSanyoLC7461Example) { ASSERT_FALSE(irrecv.decodeSanyoLC7461(&irsend.capture)); ASSERT_FALSE( - irrecv.decodeSanyoLC7461(&irsend.capture, kSanyoLC7461Bits, false)); + irrecv.decodeSanyoLC7461(&irsend.capture, kStartOffset, kSanyoLC7461Bits, + false)); } diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Sharp_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Sharp_test.cpp similarity index 94% rename from lib/IRremoteESP8266-2.7.3/test/ir_Sharp_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Sharp_test.cpp index 571e59859..e605e0d05 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Sharp_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Sharp_test.cpp @@ -196,7 +196,8 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(0x454A); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); + EXPECT_TRUE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x454A, irsend.capture.value); @@ -208,7 +209,8 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(irsend.encodeSharp(0x07, 0x99)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); @@ -220,7 +222,8 @@ TEST(TestDecodeSharp, NormalDecodeWithStrict) { irsend.reset(); irsend.sendSharpRaw(irsend.encodeSharp(0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x4202, irsend.capture.value); @@ -239,7 +242,8 @@ TEST(TestDecodeSharp, NormalDecodeWithRepeatAndStrict) { irsend.reset(); irsend.sendSharpRaw(0x7266, kSharpBits, 1); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); @@ -247,7 +251,8 @@ TEST(TestDecodeSharp, NormalDecodeWithRepeatAndStrict) { EXPECT_EQ(0x99, irsend.capture.command); irsend.makeDecodeResult(2 * (2 * kSharpBits + kFooter)); - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + true)); EXPECT_EQ(SHARP, irsend.capture.decode_type); EXPECT_EQ(kSharpBits, irsend.capture.bits); EXPECT_EQ(0x7266, irsend.capture.value); @@ -263,9 +268,10 @@ TEST(TestDecodeSharp, DecodeWithNonStrict) { irsend.sendSharpRaw(0x0, 8); // Illegal length Sharp 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(SHARP, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x0, irsend.capture.value); @@ -276,12 +282,13 @@ TEST(TestDecodeSharp, DecodeWithNonStrict) { irsend.sendSharpRaw(0x12345678, 32); // Illegal length Sharp 32-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, true)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + true)); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, 32, true)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kStartOffset, 32, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, 32, false)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kStartOffset, 32, false)); EXPECT_EQ(SHARP, irsend.capture.decode_type); EXPECT_EQ(32, irsend.capture.bits); EXPECT_EQ(0x12345678, irsend.capture.value); @@ -300,7 +307,7 @@ TEST(TestDecodeSharp, Decode64BitMessages) { irsend.sendSharpRaw(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeSharp(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(SHARP, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -350,7 +357,8 @@ TEST(TestDecodeSharp, FailToDecodeNonSharpExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, false)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + false)); // Test only half of a good message, as it is sent (sort of) twice. uint16_t gc_half[35] = {38000, 1, 1, 10, 70, 10, 30, 10, 30, 10, 30, 10, @@ -361,7 +369,8 @@ TEST(TestDecodeSharp, FailToDecodeNonSharpExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kSharpBits, false)); + ASSERT_FALSE(irrecv.decodeSharp(&irsend.capture, kStartOffset, kSharpBits, + false)); } // https://github.com/crankyoldgit/IRremoteESP8266/issues/638#issue-421064165 diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Sherwood_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Sherwood_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Sherwood_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Sherwood_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Sony_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Sony_test.cpp similarity index 88% rename from lib/IRremoteESP8266-2.7.3/test/ir_Sony_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Sony_test.cpp index 18fc58334..c69d40e67 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Sony_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Sony_test.cpp @@ -193,7 +193,7 @@ TEST(TestDecodeSony, SonyDecodeWithUnexpectedLegalSize) { irsend.reset(); irsend.sendSony(irsend.encodeSony(kSony20Bits, 0x1, 0x1, 0x1)); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSonyMinBits)); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSonyMinBits)); EXPECT_EQ(SONY, irsend.capture.decode_type); EXPECT_EQ(kSony20Bits, irsend.capture.bits); EXPECT_EQ(0x81080, irsend.capture.value); @@ -204,7 +204,7 @@ TEST(TestDecodeSony, SonyDecodeWithUnexpectedLegalSize) { irsend.reset(); irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony20Bits)); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony20Bits)); EXPECT_EQ(SONY, irsend.capture.decode_type); EXPECT_EQ(kSony12Bits, irsend.capture.bits); EXPECT_EQ(0xA90, irsend.capture.value); @@ -215,22 +215,28 @@ TEST(TestDecodeSony, SonyDecodeWithUnexpectedLegalSize) { irsend.reset(); irsend.sendSony(irsend.encodeSony(kSony12Bits, 21, 1), kSony12Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony20Bits, + true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony15Bits, + true)); // 15-bit message should be regected when using strict and a different size. irsend.reset(); irsend.sendSony(irsend.encodeSony(kSony15Bits, 21, 1), kSony15Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony12Bits, + true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony20Bits, + true)); // 20-bit message should be regected when using strict and a different size. irsend.reset(); irsend.sendSony(irsend.encodeSony(kSony20Bits, 1, 1, 1), kSony20Bits); irsend.makeDecodeResult(); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); - ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony12Bits, + true)); + ASSERT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony15Bits, + true)); } // Decode unsupported Sony messages. i.e non-standard sizes. @@ -243,10 +249,14 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) { irsend.sendSony(0xFF, 8); // Illegal 8-bit Sony-like message. irsend.makeDecodeResult(); // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSonyMinBits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony12Bits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony15Bits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony20Bits, + true)); // Should work with a 'normal' match (not strict) ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); @@ -259,10 +269,14 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) { irsend.sendSony(0x1FFF, 13); // Illegal 13-bit Sony-like message. irsend.makeDecodeResult(); // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSonyMinBits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony12Bits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony15Bits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony20Bits, + true)); // Should work with a 'normal' match (not strict) ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); @@ -275,10 +289,14 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) { irsend.sendSony(0x1FFFF, 17); // Illegal 17-bit Sony-like message. irsend.makeDecodeResult(); // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSonyMinBits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony12Bits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony15Bits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony20Bits, + true)); // Should work with a 'normal' match (not strict) ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); @@ -291,10 +309,14 @@ TEST(TestDecodeSony, SonyDecodeWithIllegalSize) { irsend.sendSony(0x1FFFFF, 21); // Illegal 21-bit Sony-like message. irsend.makeDecodeResult(); // Should fail with strict on. - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSonyMinBits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony15Bits, true)); - EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kSony20Bits, true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSonyMinBits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony12Bits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony15Bits, + true)); + EXPECT_FALSE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony20Bits, + true)); // Should work with a 'normal' match (not strict) ASSERT_TRUE(irrecv.decode(&irsend.capture)); EXPECT_EQ(SONY, irsend.capture.decode_type); @@ -336,7 +358,8 @@ TEST(TestDecodeSony, DecodeGlobalCacheExample) { EXPECT_EQ(0x1, irsend.capture.address); EXPECT_EQ(0x2E, irsend.capture.command); // With strict and correct size. - ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kSony12Bits, true)); + ASSERT_TRUE(irrecv.decodeSony(&irsend.capture, kStartOffset, kSony12Bits, + true)); } // Encoding & Decode 20 bit Sony messages. Issue #476 diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Tcl_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Tcl_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Tcl_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Tcl_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Teco_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Teco_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.3/test/ir_Teco_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Teco_test.cpp index cb6c8bcd9..635e93a44 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Teco_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Teco_test.cpp @@ -353,7 +353,8 @@ TEST(TestDecodeTeco, NormalDecodeWithStrict) { irsend.reset(); irsend.sendTeco(expectedState); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeTeco(&irsend.capture, kTecoBits, true)); + ASSERT_TRUE(irrecv.decodeTeco(&irsend.capture, kStartOffset, kTecoBits, + true)); EXPECT_EQ(TECO, irsend.capture.decode_type); EXPECT_EQ(kTecoBits, irsend.capture.bits); EXPECT_FALSE(irsend.capture.repeat); diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Toshiba_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Toshiba_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Toshiba_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Toshiba_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Trotec_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Trotec_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Trotec_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Trotec_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Vestel_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Vestel_test.cpp similarity index 99% rename from lib/IRremoteESP8266-2.7.3/test/ir_Vestel_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Vestel_test.cpp index 4164386f7..d20a882a6 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Vestel_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Vestel_test.cpp @@ -407,7 +407,8 @@ TEST(TestDecodeVestelAc, NormalDecodeWithStrict) { irsend.reset(); irsend.sendVestelAc(expectedState); irsend.makeDecodeResult(); - ASSERT_TRUE(irrecv.decodeVestelAc(&irsend.capture, kVestelAcBits, true)); + ASSERT_TRUE(irrecv.decodeVestelAc(&irsend.capture, kStartOffset, + kVestelAcBits, true)); EXPECT_EQ(VESTEL_AC, irsend.capture.decode_type); EXPECT_EQ(kVestelAcBits, irsend.capture.bits); EXPECT_FALSE(irsend.capture.repeat); diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Whirlpool_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Whirlpool_test.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/test/ir_Whirlpool_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Whirlpool_test.cpp diff --git a/lib/IRremoteESP8266-2.7.3/test/ir_Whynter_test.cpp b/lib/IRremoteESP8266-2.7.4/test/ir_Whynter_test.cpp similarity index 92% rename from lib/IRremoteESP8266-2.7.3/test/ir_Whynter_test.cpp rename to lib/IRremoteESP8266-2.7.4/test/ir_Whynter_test.cpp index 0c45f2654..eaccf0ea1 100644 --- a/lib/IRremoteESP8266-2.7.3/test/ir_Whynter_test.cpp +++ b/lib/IRremoteESP8266-2.7.4/test/ir_Whynter_test.cpp @@ -199,10 +199,11 @@ TEST(TestDecodeWhynter, DecodeWithNonStrictSizes) { irsend.sendWhynter(0x12, 8); // Illegal sized Whynter 8-bit message. irsend.makeDecodeResult(); // Should fail with strict on. - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, 8, true)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kStartOffset, kWhynterBits, + true)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kStartOffset, 8, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, 8, false)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kStartOffset, 8, false)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); EXPECT_EQ(8, irsend.capture.bits); EXPECT_EQ(0x12, irsend.capture.value); @@ -213,13 +214,14 @@ TEST(TestDecodeWhynter, DecodeWithNonStrictSizes) { irsend.sendWhynter(0x1234567890, 40); // Illegal size Whynter 40-bit message. irsend.makeDecodeResult(); // Shouldn't pass with strict when we ask for less bits than we got. - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, true)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kStartOffset, kWhynterBits, + true)); irsend.makeDecodeResult(); // Should fail with strict when we ask for the wrong bit size. - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, 40, true)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kStartOffset, 40, true)); // Should pass if strict off. - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, 40, false)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kStartOffset, 40, false)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); EXPECT_EQ(40, irsend.capture.bits); EXPECT_EQ(0x1234567890, irsend.capture.value); @@ -238,7 +240,7 @@ TEST(TestDecodeWhynter, Decode64BitMessages) { irsend.sendWhynter(0xFFFFFFFFFFFFFFFF, 64); irsend.makeDecodeResult(); // Should work with a 'normal' match (not strict) - ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, 64, false)); + ASSERT_TRUE(irrecv.decodeWhynter(&irsend.capture, kStartOffset, 64, false)); EXPECT_EQ(WHYNTER, irsend.capture.decode_type); EXPECT_EQ(64, irsend.capture.bits); EXPECT_EQ(0xFFFFFFFFFFFFFFFF, irsend.capture.value); @@ -262,5 +264,6 @@ TEST(TestDecodeWhynter, FailToDecodeNonWhynterExample) { irsend.makeDecodeResult(); ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture)); - ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kWhynterBits, false)); + ASSERT_FALSE(irrecv.decodeWhynter(&irsend.capture, kStartOffset, kWhynterBits, + false)); } diff --git a/lib/IRremoteESP8266-2.7.3/tools/Makefile b/lib/IRremoteESP8266-2.7.4/tools/Makefile similarity index 98% rename from lib/IRremoteESP8266-2.7.3/tools/Makefile rename to lib/IRremoteESP8266-2.7.4/tools/Makefile index 6868f97db..0ee8cc563 100644 --- a/lib/IRremoteESP8266-2.7.3/tools/Makefile +++ b/lib/IRremoteESP8266-2.7.4/tools/Makefile @@ -51,7 +51,7 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \ ir_GICable.o ir_Whirlpool.o ir_Lutron.o ir_Electra.o ir_Pioneer.o \ ir_MWM.o ir_Vestel.o ir_Teco.o ir_Tcl.o ir_Lego.o \ ir_MitsubishiHeavy.o ir_Goodweather.o ir_Inax.o ir_Argo.o \ - ir_Trotec.o ir_Neoclima.o ir_Amcor.o + ir_Trotec.o ir_Neoclima.o ir_Amcor.o ir_Epson.o # Common object files COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o IRtext.o IRac.o $(PROTOCOLS) @@ -234,5 +234,8 @@ ir_Neoclima.o : $(USER_DIR)/ir_Neoclima.cpp $(USER_DIR)/ir_Neoclima.h $(COMMON_D ir_Amcor.o : $(USER_DIR)/ir_Amcor.cpp $(USER_DIR)/ir_Amcor.h $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Amcor.cpp +ir_Epson.o : $(USER_DIR)/ir_Epson.cpp $(GTEST_HEADERS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/ir_Epson.cpp + IRac.o : $(USER_DIR)/IRac.cpp $(USER_DIR)/IRac.h $(COMMON_DEPS) $(GTEST_HEADERS) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES) -c $(USER_DIR)/IRac.cpp diff --git a/lib/IRremoteESP8266-2.7.3/tools/RawToGlobalCache.sh b/lib/IRremoteESP8266-2.7.4/tools/RawToGlobalCache.sh similarity index 100% rename from lib/IRremoteESP8266-2.7.3/tools/RawToGlobalCache.sh rename to lib/IRremoteESP8266-2.7.4/tools/RawToGlobalCache.sh diff --git a/lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data.py b/lib/IRremoteESP8266-2.7.4/tools/auto_analyse_raw_data.py similarity index 100% rename from lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data.py rename to lib/IRremoteESP8266-2.7.4/tools/auto_analyse_raw_data.py diff --git a/lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data_test.py b/lib/IRremoteESP8266-2.7.4/tools/auto_analyse_raw_data_test.py similarity index 100% rename from lib/IRremoteESP8266-2.7.3/tools/auto_analyse_raw_data_test.py rename to lib/IRremoteESP8266-2.7.4/tools/auto_analyse_raw_data_test.py diff --git a/lib/IRremoteESP8266-2.7.3/tools/gc_decode.cpp b/lib/IRremoteESP8266-2.7.4/tools/gc_decode.cpp similarity index 84% rename from lib/IRremoteESP8266-2.7.3/tools/gc_decode.cpp rename to lib/IRremoteESP8266-2.7.4/tools/gc_decode.cpp index a1d828d1c..f1c374bbe 100644 --- a/lib/IRremoteESP8266-2.7.3/tools/gc_decode.cpp +++ b/lib/IRremoteESP8266-2.7.4/tools/gc_decode.cpp @@ -27,18 +27,20 @@ void str_to_uint16(char *str, uint16_t *res, uint8_t base) { void usage_error(char *name) { std::cerr << "Usage: " << name << " [-gc] [-rawdump] " << std::endl - << "Usage: " << name << " -prontohex [-rawdump] " + << "Usage: " << name + << " -prontohex [-rawdump] [-repeats num] " << std::endl << "Usage: " << name << " -raw [-rawdump] " << std::endl; } int main(int argc, char *argv[]) { int argv_offset = 1; + int repeats = 0; bool dumpraw = false; enum decode_type_t input_type = GLOBALCACHE; const uint16_t raw_freq = 38; // Check the invocation/calling usage. - if (argc < 2 || argc > 4) { + if (argc < 2 || argc > 6) { usage_error(argv[0]); return 1; } @@ -52,11 +54,24 @@ int main(int argc, char *argv[]) { argv_offset++; } - if (strncmp("-rawdump", argv[argv_offset], 7) == 0) { + if (strncmp("-rawdump", argv[argv_offset], 8) == 0) { dumpraw = true; argv_offset++; } + if (input_type == PRONTO && strncmp("-repeats", argv[argv_offset], 8) == 0) { + argv_offset++; + if (argc - argv_offset <= 1) { + usage_error(argv[0]); + return 1; + } + repeats = atoi(argv[argv_offset++]); + if (repeats < 0) { + usage_error(argv[0]); + return 1; + } + } + if (argc - argv_offset != 1) { usage_error(argv[0]); return 1; @@ -80,8 +95,8 @@ int main(int argc, char *argv[]) { index++; } - IRsendTest irsend(4); - IRrecv irrecv(4); + IRsendTest irsend(0); + IRrecv irrecv(0); irsend.begin(); irsend.reset(); @@ -90,7 +105,7 @@ int main(int argc, char *argv[]) { irsend.sendGC(gc_test, index); break; case PRONTO: - irsend.sendPronto(gc_test, index); + irsend.sendPronto(gc_test, index, repeats); break; case RAW: irsend.sendRaw(gc_test, index, raw_freq); diff --git a/lib/IRremoteESP8266-2.7.3/tools/generate_irtext_h.sh b/lib/IRremoteESP8266-2.7.4/tools/generate_irtext_h.sh similarity index 100% rename from lib/IRremoteESP8266-2.7.3/tools/generate_irtext_h.sh rename to lib/IRremoteESP8266-2.7.4/tools/generate_irtext_h.sh diff --git a/lib/IRremoteESP8266-2.7.3/tools/mkkeywords b/lib/IRremoteESP8266-2.7.4/tools/mkkeywords similarity index 100% rename from lib/IRremoteESP8266-2.7.3/tools/mkkeywords rename to lib/IRremoteESP8266-2.7.4/tools/mkkeywords diff --git a/lib/IRremoteESP8266-2.7.3/tools/mode2_decode.cpp b/lib/IRremoteESP8266-2.7.4/tools/mode2_decode.cpp similarity index 100% rename from lib/IRremoteESP8266-2.7.3/tools/mode2_decode.cpp rename to lib/IRremoteESP8266-2.7.4/tools/mode2_decode.cpp diff --git a/lib/IRremoteESP8266-2.7.3/tools/scrape_supported_devices.py b/lib/IRremoteESP8266-2.7.4/tools/scrape_supported_devices.py similarity index 100% rename from lib/IRremoteESP8266-2.7.3/tools/scrape_supported_devices.py rename to lib/IRremoteESP8266-2.7.4/tools/scrape_supported_devices.py diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index b304bf95b..ee767851a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -4,6 +4,7 @@ - Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers - Add support for Jarolift rollers by Keeloq algorithm +- Change IRremoteESP8266 library updated to v2.7.4 ### 8.1.0.9 20200220 From 6874dddf035fa28031d2b82158d38c816fdd4b68 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 29 Feb 2020 14:34:58 +0100 Subject: [PATCH 523/559] Delete eagle.flash.1m0.ld --- .../tools/sdk/ld/eagle.flash.1m0.ld | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 arduino/version 2.3.0/tools/sdk/ld/eagle.flash.1m0.ld diff --git a/arduino/version 2.3.0/tools/sdk/ld/eagle.flash.1m0.ld b/arduino/version 2.3.0/tools/sdk/ld/eagle.flash.1m0.ld deleted file mode 100644 index 250962962..000000000 --- a/arduino/version 2.3.0/tools/sdk/ld/eagle.flash.1m0.ld +++ /dev/null @@ -1,18 +0,0 @@ -/* Flash Split for 1M chips, no SPIFFS */ -/* sketch 999KB */ -/* eeprom 20KB */ - -MEMORY -{ - dport0_0_seg : org = 0x3FF00000, len = 0x10 - dram0_0_seg : org = 0x3FFE8000, len = 0x14000 - iram1_0_seg : org = 0x40100000, len = 0x8000 - irom0_0_seg : org = 0x40201010, len = 0xf9ff0 -} - -PROVIDE ( _SPIFFS_start = 0x402FB000 ); -PROVIDE ( _SPIFFS_end = 0x402FB000 ); -PROVIDE ( _SPIFFS_page = 0 ); -PROVIDE ( _SPIFFS_block = 0 ); - -INCLUDE "../ld/eagle.app.v6.common.ld" From 53a622ee3dcf052d19520ec3273d1bdf4a669d50 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 29 Feb 2020 14:35:56 +0100 Subject: [PATCH 524/559] Delete boards.txt --- arduino/version 2.3.0/boards.txt | 1897 ------------------------------ 1 file changed, 1897 deletions(-) delete mode 100644 arduino/version 2.3.0/boards.txt diff --git a/arduino/version 2.3.0/boards.txt b/arduino/version 2.3.0/boards.txt deleted file mode 100644 index 9b3f2db8d..000000000 --- a/arduino/version 2.3.0/boards.txt +++ /dev/null @@ -1,1897 +0,0 @@ -menu.UploadSpeed=Upload Speed -menu.CpuFrequency=CPU Frequency -menu.FlashSize=Flash Size -menu.FlashMode=Flash Mode -menu.FlashFreq=Flash Frequency -menu.UploadTool=Upload Using -menu.ResetMethod=Reset Method -menu.ESPModule=Module -menu.Debug=Debug port -menu.DebugLevel=Debug Level -menu.LwIPVariant=lwIP Variant - -############################################################## -generic.name=Generic ESP8266 Module - -generic.upload.tool=esptool -generic.upload.speed=115200 -generic.upload.resetmethod=ck -generic.upload.maximum_size=434160 -generic.upload.maximum_data_size=81920 -generic.upload.wait_for_upload_port=true -generic.serial.disableDTR=true -generic.serial.disableRTS=true - -generic.build.mcu=esp8266 -generic.build.f_cpu=80000000L -generic.build.board=ESP8266_ESP01 -generic.build.core=esp8266 -generic.build.variant=generic -generic.build.flash_mode=qio -generic.build.spiffs_pagesize=256 -generic.build.debug_port= -generic.build.debug_level= - -generic.menu.UploadTool.esptool=Serial -generic.menu.UploadTool.esptool.upload.tool=esptool -generic.menu.UploadTool.esptool.upload.verbose=-vv -generic.menu.UploadTool.espupload=OTA_upload -generic.menu.UploadTool.espupload.upload.tool=espupload - -generic.menu.CpuFrequency.80=80 MHz -generic.menu.CpuFrequency.80.build.f_cpu=80000000L -generic.menu.CpuFrequency.160=160 MHz -generic.menu.CpuFrequency.160.build.f_cpu=160000000L - -generic.menu.FlashFreq.40=40MHz -generic.menu.FlashFreq.40.build.flash_freq=40 -generic.menu.FlashFreq.80=80MHz -generic.menu.FlashFreq.80.build.flash_freq=80 - -generic.menu.FlashMode.dio=DIO -generic.menu.FlashMode.dio.build.flash_mode=dio -generic.menu.FlashMode.qio=QIO -generic.menu.FlashMode.qio.build.flash_mode=qio -generic.menu.FlashMode.dout=DOUT -generic.menu.FlashMode.dout.build.flash_mode=dout -generic.menu.FlashMode.qout=QOUT -generic.menu.FlashMode.qout.build.flash_mode=qout - -generic.menu.UploadSpeed.115200=115200 -generic.menu.UploadSpeed.115200.upload.speed=115200 -generic.menu.UploadSpeed.9600=9600 -generic.menu.UploadSpeed.9600.upload.speed=9600 -generic.menu.UploadSpeed.57600=57600 -generic.menu.UploadSpeed.57600.upload.speed=57600 -generic.menu.UploadSpeed.256000.windows=256000 -generic.menu.UploadSpeed.256000.upload.speed=256000 -generic.menu.UploadSpeed.230400.linux=230400 -generic.menu.UploadSpeed.230400.macosx=230400 -generic.menu.UploadSpeed.230400.upload.speed=230400 -generic.menu.UploadSpeed.460800.linux=460800 -generic.menu.UploadSpeed.460800.macosx=460800 -generic.menu.UploadSpeed.460800.upload.speed=460800 -generic.menu.UploadSpeed.512000.windows=512000 -generic.menu.UploadSpeed.512000.upload.speed=512000 -generic.menu.UploadSpeed.921600=921600 -generic.menu.UploadSpeed.921600.upload.speed=921600 - -generic.menu.FlashSize.512K64=512K (64K SPIFFS) -generic.menu.FlashSize.512K64.build.flash_size=512K -generic.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -generic.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -generic.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -generic.menu.FlashSize.512K64.upload.maximum_size=434160 - -generic.menu.FlashSize.512K128=512K (128K SPIFFS) -generic.menu.FlashSize.512K128.build.flash_size=512K -generic.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -generic.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -generic.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -generic.menu.FlashSize.512K128.upload.maximum_size=368624 - -generic.menu.FlashSize.512K0=512K (no SPIFFS) -generic.menu.FlashSize.512K0.build.flash_size=512K -generic.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -generic.menu.FlashSize.512K0.upload.maximum_size=499696 - -generic.menu.FlashSize.1M512=1M (512K SPIFFS) -generic.menu.FlashSize.1M512.build.flash_size=1M -generic.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -generic.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -generic.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -generic.menu.FlashSize.1M512.upload.maximum_size=499696 - -generic.menu.FlashSize.1M256=1M (256K SPIFFS) -generic.menu.FlashSize.1M256.build.flash_size=1M -generic.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -generic.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -generic.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M256.upload.maximum_size=761840 - -generic.menu.FlashSize.1M192=1M (192K SPIFFS) -generic.menu.FlashSize.1M192.build.flash_size=1M -generic.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -generic.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -generic.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M192.upload.maximum_size=827376 - -generic.menu.FlashSize.1M160=1M (160K SPIFFS) -generic.menu.FlashSize.1M160.build.flash_size=1M -generic.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -generic.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -generic.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M160.upload.maximum_size=860144 - -generic.menu.FlashSize.1M144=1M (144K SPIFFS) -generic.menu.FlashSize.1M144.build.flash_size=1M -generic.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -generic.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -generic.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M144.upload.maximum_size=876528 - -generic.menu.FlashSize.1M128=1M (128K SPIFFS) -generic.menu.FlashSize.1M128.build.flash_size=1M -generic.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -generic.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -generic.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M128.upload.maximum_size=892912 - -generic.menu.FlashSize.1M64=1M (64K SPIFFS) -generic.menu.FlashSize.1M64.build.flash_size=1M -generic.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -generic.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -generic.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M64.upload.maximum_size=958448 - -generic.menu.FlashSize.1M0=1M (no SPIFFS) -generic.menu.FlashSize.1M0.build.flash_size=1M -generic.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -generic.menu.FlashSize.1M0.upload.maximum_size=1023984 - -generic.menu.FlashSize.2M=2M (1M SPIFFS) -generic.menu.FlashSize.2M.build.flash_size=2M -generic.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -generic.menu.FlashSize.2M.build.spiffs_start=0x100000 -generic.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -generic.menu.FlashSize.2M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.2M.upload.maximum_size=1044464 - -generic.menu.FlashSize.4M1M=4M (1M SPIFFS) -generic.menu.FlashSize.4M1M.build.flash_size=4M -generic.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -generic.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -generic.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -generic.menu.FlashSize.4M1M.upload.maximum_size=1044464 - -generic.menu.FlashSize.4M3M=4M (3M SPIFFS) -generic.menu.FlashSize.4M3M.build.flash_size=4M -generic.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -generic.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -generic.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M3M.upload.maximum_size=1044464 - -generic.menu.ResetMethod.ck=ck -generic.menu.ResetMethod.ck.upload.resetmethod=ck -generic.menu.ResetMethod.nodemcu=nodemcu -generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu - -generic.menu.Debug.Disabled=Disabled -generic.menu.Debug.Disabled.build.debug_port= -generic.menu.Debug.Serial=Serial -generic.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -generic.menu.Debug.Serial1=Serial1 -generic.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 - -generic.menu.DebugLevel.None____=None -generic.menu.DebugLevel.None____.build.debug_level= -generic.menu.DebugLevel.Core____=Core -generic.menu.DebugLevel.Core____.build.debug_level=-DDEBUG_ESP_CORE -generic.menu.DebugLevel.SSL_____=Core + SSL -generic.menu.DebugLevel.SSL_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -generic.menu.DebugLevel.SSL_MEM_=Core + SSL + TLS Mem -generic.menu.DebugLevel.SSL_MEM_.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_TLS_MEM -generic.menu.DebugLevel.WiFic___=Core + WiFi -generic.menu.DebugLevel.WiFic___.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -generic.menu.DebugLevel.WiFi____=WiFi -generic.menu.DebugLevel.WiFi____.build.debug_level=-DDEBUG_ESP_WIFI -generic.menu.DebugLevel.HTTPClient=HTTPClient -generic.menu.DebugLevel.HTTPClient.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.HTTPClient2=HTTPClient + SSL -generic.menu.DebugLevel.HTTPClient2.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_SSL -generic.menu.DebugLevel.HTTPUpdate=HTTPUpdate -generic.menu.DebugLevel.HTTPUpdate.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -generic.menu.DebugLevel.HTTPUpdate2=HTTPClient + HTTPUpdate -generic.menu.DebugLevel.HTTPUpdate2.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -generic.menu.DebugLevel.HTTPUpdate3=HTTPClient + HTTPUpdate + Updater -generic.menu.DebugLevel.HTTPUpdate3.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -generic.menu.DebugLevel.HTTPServer=HTTPServer -generic.menu.DebugLevel.HTTPServer.build.debug_level=-DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.UPDATER=Updater -generic.menu.DebugLevel.UPDATER.build.debug_level=-DDEBUG_ESP_UPDATER -generic.menu.DebugLevel.OTA_____=OTA -generic.menu.DebugLevel.OTA_____.build.debug_level=-DDEBUG_ESP_OTA -generic.menu.DebugLevel.OTA2____=OTA + Updater -generic.menu.DebugLevel.OTA2____.build.debug_level=-DDEBUG_ESP_OTA -DDEBUG_ESP_UPDATER -generic.menu.DebugLevel.all_____=All -generic.menu.DebugLevel.all_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM - -# disabled because espressif's bootloader refuses to write above 4M -# generic.menu.FlashSize.8M=8M (7M SPIFFS) -# generic.menu.FlashSize.8M.build.flash_size=1M -# generic.menu.FlashSize.8M.build.flash_ld=eagle.flash.8m.ld -# generic.menu.FlashSize.8M.build.spiffs_start=0x100000 -# generic.menu.FlashSize.8M.build.spiffs_end=0x800000 -# generic.menu.FlashSize.8M.build.spiffs_blocksize=8192 -# generic.menu.FlashSize.16M=16M (15M SPIFFS) -# generic.menu.FlashSize.16M.build.flash_size=1M -# generic.menu.FlashSize.16M.build.flash_ld=eagle.flash.16m.ld -# generic.menu.FlashSize.16M.build.spiffs_start=0x100000 -# generic.menu.FlashSize.16M.build.spiffs_end=0x1000000 -# generic.menu.FlashSize.16M.build.spiffs_blocksize=8192 - -############################################################## -# ESP8285 chip has built-in 1MB flash - -esp8285.name=Generic ESP8285 Module - -esp8285.upload.tool=esptool -esp8285.upload.speed=115200 -esp8285.upload.resetmethod=ck -esp8285.upload.maximum_size=434160 -esp8285.upload.maximum_data_size=81920 -esp8285.upload.wait_for_upload_port=true -esp8285.serial.disableDTR=true -esp8285.serial.disableRTS=true - -esp8285.build.mcu=esp8266 -esp8285.build.f_cpu=80000000L -esp8285.build.board=ESP8266_ESP01 -esp8285.build.core=esp8266 -esp8285.build.variant=generic -esp8285.build.flash_mode=dout -esp8285.build.flash_freq=40 -esp8285.build.spiffs_pagesize=256 -esp8285.build.debug_port= -esp8285.build.debug_level= - -esp8285.menu.UploadTool.esptool=Serial -esp8285.menu.UploadTool.esptool.upload.tool=esptool -esp8285.menu.UploadTool.esptool.upload.verbose=-vv -esp8285.menu.UploadTool.espupload=OTA_upload -esp8285.menu.UploadTool.espupload.upload.tool=espupload - -esp8285.menu.CpuFrequency.80=80 MHz -esp8285.menu.CpuFrequency.80.build.f_cpu=80000000L -esp8285.menu.CpuFrequency.160=160 MHz -esp8285.menu.CpuFrequency.160.build.f_cpu=160000000L - -esp8285.menu.UploadSpeed.115200=115200 -esp8285.menu.UploadSpeed.115200.upload.speed=115200 -esp8285.menu.UploadSpeed.9600=9600 -esp8285.menu.UploadSpeed.9600.upload.speed=9600 -esp8285.menu.UploadSpeed.57600=57600 -esp8285.menu.UploadSpeed.57600.upload.speed=57600 -esp8285.menu.UploadSpeed.256000.windows=256000 -esp8285.menu.UploadSpeed.256000.upload.speed=256000 -esp8285.menu.UploadSpeed.230400.linux=230400 -esp8285.menu.UploadSpeed.230400.macosx=230400 -esp8285.menu.UploadSpeed.230400.upload.speed=230400 -esp8285.menu.UploadSpeed.460800.linux=460800 -esp8285.menu.UploadSpeed.460800.macosx=460800 -esp8285.menu.UploadSpeed.460800.upload.speed=460800 -esp8285.menu.UploadSpeed.512000.windows=512000 -esp8285.menu.UploadSpeed.512000.upload.speed=512000 -esp8285.menu.UploadSpeed.921600=921600 -esp8285.menu.UploadSpeed.921600.upload.speed=921600 - -esp8285.menu.FlashSize.1M512=1M (512K SPIFFS) -esp8285.menu.FlashSize.1M512.build.flash_size=1M -esp8285.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -esp8285.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -esp8285.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -esp8285.menu.FlashSize.1M512.upload.maximum_size=499696 - -esp8285.menu.FlashSize.1M256=1M (256K SPIFFS) -esp8285.menu.FlashSize.1M256.build.flash_size=1M -esp8285.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -esp8285.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -esp8285.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M256.upload.maximum_size=761840 - -esp8285.menu.FlashSize.1M192=1M (192K SPIFFS) -esp8285.menu.FlashSize.1M192.build.flash_size=1M -esp8285.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -esp8285.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -esp8285.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M192.upload.maximum_size=827376 - -esp8285.menu.FlashSize.1M160=1M (160K SPIFFS) -esp8285.menu.FlashSize.1M160.build.flash_size=1M -esp8285.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -esp8285.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -esp8285.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M160.upload.maximum_size=860144 - -esp8285.menu.FlashSize.1M144=1M (144K SPIFFS) -esp8285.menu.FlashSize.1M144.build.flash_size=1M -esp8285.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -esp8285.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -esp8285.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M144.upload.maximum_size=876528 - -esp8285.menu.FlashSize.1M128=1M (128K SPIFFS) -esp8285.menu.FlashSize.1M128.build.flash_size=1M -esp8285.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -esp8285.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -esp8285.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M128.upload.maximum_size=892912 - -esp8285.menu.FlashSize.1M64=1M (64K SPIFFS) -esp8285.menu.FlashSize.1M64.build.flash_size=1M -esp8285.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -esp8285.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -esp8285.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M64.upload.maximum_size=958448 - -esp8285.menu.FlashSize.1M0=1M (no SPIFFS) -esp8285.menu.FlashSize.1M0.build.flash_size=1M -esp8285.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -esp8285.menu.FlashSize.1M0.upload.maximum_size=1023984 - -############################################################## - -espduino.name=ESPDuino (ESP-13 Module) - -espduino.upload.tool=esptool -espduino.upload.speed=115200 -espduino.upload.resetmethod=ck -espduino.upload.maximum_size=1044464 -espduino.upload.maximum_data_size=81920 -espduino.upload.wait_for_upload_port=true -espduino.serial.disableDTR=true -espduino.serial.disableRTS=true - -espduino.build.mcu=esp8266 -espduino.build.f_cpu=80000000L -espduino.build.board=ESP8266_ESP13 -espduino.build.core=esp8266 -espduino.build.variant=ESPDuino -espduino.build.flash_mode=dio -espduino.build.flash_size=4M -espduino.build.flash_freq=40 -espduino.build.debug_port= -espduino.build.debug_level= - -espduino.menu.CpuFrequency.80=80 MHz -espduino.menu.CpuFrequency.80.build.f_cpu=80000000L -espduino.menu.CpuFrequency.160=160 MHz -espduino.menu.CpuFrequency.160.build.f_cpu=160000000L - -espduino.menu.UploadSpeed.115200=115200 -espduino.menu.UploadSpeed.115200.upload.speed=115200 -espduino.menu.UploadSpeed.9600=9600 -espduino.menu.UploadSpeed.9600.upload.speed=9600 -espduino.menu.UploadSpeed.57600=57600 -espduino.menu.UploadSpeed.57600.upload.speed=57600 -espduino.menu.UploadSpeed.256000.windows=256000 -espduino.menu.UploadSpeed.256000.upload.speed=256000 -espduino.menu.UploadSpeed.230400.linux=230400 -espduino.menu.UploadSpeed.230400.macosx=230400 -espduino.menu.UploadSpeed.230400.macosx=230400 -espduino.menu.UploadSpeed.230400.upload.speed=230400 -espduino.menu.UploadSpeed.460800.linux=460800 -espduino.menu.UploadSpeed.460800.macosx=460800 -espduino.menu.UploadSpeed.460800.upload.speed=460800 -espduino.menu.UploadSpeed.512000.windows=512000 -espduino.menu.UploadSpeed.512000.upload.speed=512000 -espduino.menu.UploadSpeed.921600=921600 -espduino.menu.UploadSpeed.921600.upload.speed=921600 - -espduino.menu.FlashSize.4M3M=4M (3M SPIFFS) -espduino.menu.FlashSize.4M3M.build.flash_size=4M -espduino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espduino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espduino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espduino.menu.FlashSize.4M3M.build.spiffs_pagesize=256 - -espduino.menu.FlashSize.4M1M=4M (1M SPIFFS) -espduino.menu.FlashSize.4M1M.build.flash_size=4M -espduino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espduino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espduino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espduino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -############################################################## -huzzah.name=Adafruit HUZZAH ESP8266 - -huzzah.upload.tool=esptool -huzzah.upload.speed=115200 -huzzah.upload.resetmethod=nodemcu -huzzah.upload.maximum_size=1044464 -huzzah.upload.maximum_data_size=81920 -huzzah.upload.wait_for_upload_port=true -huzzah.serial.disableDTR=true -huzzah.serial.disableRTS=true - -huzzah.build.mcu=esp8266 -huzzah.build.f_cpu=80000000L -huzzah.build.board=ESP8266_ESP12 -huzzah.build.core=esp8266 -huzzah.build.variant=adafruit -huzzah.build.flash_mode=qio -huzzah.build.flash_size=4M -huzzah.build.flash_freq=40 -huzzah.build.debug_port= -huzzah.build.debug_level= - -huzzah.menu.CpuFrequency.80=80 MHz -huzzah.menu.CpuFrequency.80.build.f_cpu=80000000L -huzzah.menu.CpuFrequency.160=160 MHz -huzzah.menu.CpuFrequency.160.build.f_cpu=160000000L - -huzzah.menu.UploadSpeed.115200=115200 -huzzah.menu.UploadSpeed.115200.upload.speed=115200 -huzzah.menu.UploadSpeed.9600=9600 -huzzah.menu.UploadSpeed.9600.upload.speed=9600 -huzzah.menu.UploadSpeed.57600=57600 -huzzah.menu.UploadSpeed.57600.upload.speed=57600 -huzzah.menu.UploadSpeed.256000=256000 -huzzah.menu.UploadSpeed.256000.upload.speed=256000 -huzzah.menu.UploadSpeed.921600=921600 -huzzah.menu.UploadSpeed.921600.upload.speed=921600 - -huzzah.menu.FlashSize.4M3M=4M (3M SPIFFS) -huzzah.menu.FlashSize.4M3M.build.flash_size=4M -huzzah.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -huzzah.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -huzzah.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -huzzah.menu.FlashSize.4M3M.build.spiffs_pagesize=256 - -huzzah.menu.FlashSize.4M1M=4M (1M SPIFFS) -huzzah.menu.FlashSize.4M1M.build.flash_size=4M -huzzah.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -huzzah.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -huzzah.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -huzzah.menu.FlashSize.4M1M.build.spiffs_pagesize=256 - -############################################################## -espresso_lite_v1.name=ESPresso Lite 1.0 -espresso_lite_v1.upload.tool=esptool -espresso_lite_v1.upload.speed=115200 -espresso_lite_v1.upload.maximum_size=1044464 -espresso_lite_v1.upload.maximum_data_size=81920 -espresso_lite_v1.upload.wait_for_upload_port=true - -espresso_lite_v1.build.mcu=esp8266 -espresso_lite_v1.build.f_cpu=80000000L -espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 -espresso_lite_v1.build.core=esp8266 -espresso_lite_v1.build.variant=espresso_lite_v1 -espresso_lite_v1.build.flash_mode=dio -espresso_lite_v1.build.flash_size=4M -espresso_lite_v1.build.flash_freq=40 - -espresso_lite_v1.menu.CpuFrequency.80=80 MHz -espresso_lite_v1.menu.CpuFrequency.80.build.f_cpu=80000000L -espresso_lite_v1.menu.CpuFrequency.160=160 MHz -espresso_lite_v1.menu.CpuFrequency.160.build.f_cpu=160000000L - -espresso_lite_v1.menu.UploadSpeed.115200=115200 -espresso_lite_v1.menu.UploadSpeed.115200.upload.speed=115200 -espresso_lite_v1.menu.UploadSpeed.57600=57600 -espresso_lite_v1.menu.UploadSpeed.57600.upload.speed=57600 -espresso_lite_v1.menu.UploadSpeed.256000.windows=256000 -espresso_lite_v1.menu.UploadSpeed.256000.upload.speed=256000 -espresso_lite_v1.menu.UploadSpeed.230400.linux=230400 -espresso_lite_v1.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v1.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v1.menu.UploadSpeed.230400.upload.speed=230400 -espresso_lite_v1.menu.UploadSpeed.460800.linux=460800 -espresso_lite_v1.menu.UploadSpeed.460800.macosx=460800 -espresso_lite_v1.menu.UploadSpeed.460800.upload.speed=460800 -espresso_lite_v1.menu.UploadSpeed.512000.windows=512000 -espresso_lite_v1.menu.UploadSpeed.512000.upload.speed=512000 -espresso_lite_v1.menu.UploadSpeed.921600=921600 -espresso_lite_v1.menu.UploadSpeed.921600.upload.speed=921600 - -espresso_lite_v1.menu.FlashSize.4M3M=4M (3M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.FlashSize.4M3M.upload.maximum_size=1044464 - -espresso_lite_v1.menu.FlashSize.4M1M=4M (1M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.FlashSize.4M1M.upload.maximum_size=1044464 - -espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v1.menu.ResetMethod.ck=ck -espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck - -espresso_lite_v1.menu.Debug.Disabled=Disabled -espresso_lite_v1.menu.Debug.Disabled.build.debug_port= -espresso_lite_v1.menu.Debug.Serial=Serial -espresso_lite_v1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v1.menu.Debug.Serial1=Serial1 -espresso_lite_v1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 - -espresso_lite_v1.menu.DebugLevel.None____=None -espresso_lite_v1.menu.DebugLevel.None____.build.debug_level= -espresso_lite_v1.menu.DebugLevel.Core____=Core -espresso_lite_v1.menu.DebugLevel.Core____.build.debug_level=-DDEBUG_ESP_CORE -espresso_lite_v1.menu.DebugLevel.SSL_____=Core + SSL -espresso_lite_v1.menu.DebugLevel.SSL_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -espresso_lite_v1.menu.DebugLevel.SSL_MEM_=Core + SSL + TLS Mem -espresso_lite_v1.menu.DebugLevel.SSL_MEM_.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_TLS_MEM -espresso_lite_v1.menu.DebugLevel.WiFic___=Core + WiFi -espresso_lite_v1.menu.DebugLevel.WiFic___.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -espresso_lite_v1.menu.DebugLevel.WiFi____=WiFi -espresso_lite_v1.menu.DebugLevel.WiFi____.build.debug_level=-DDEBUG_ESP_WIFI -espresso_lite_v1.menu.DebugLevel.HTTPClient=HTTPClient -espresso_lite_v1.menu.DebugLevel.HTTPClient.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.HTTPClient2=HTTPClient + SSL -espresso_lite_v1.menu.DebugLevel.HTTPClient2.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_SSL -espresso_lite_v1.menu.DebugLevel.HTTPUpdate=HTTPUpdate -espresso_lite_v1.menu.DebugLevel.HTTPUpdate.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v1.menu.DebugLevel.HTTPUpdate2=HTTPClient + HTTPUpdate -espresso_lite_v1.menu.DebugLevel.HTTPUpdate2.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v1.menu.DebugLevel.HTTPUpdate3=HTTPClient + HTTPUpdate + Updater -espresso_lite_v1.menu.DebugLevel.HTTPUpdate3.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.DebugLevel.HTTPServer=HTTPServer -espresso_lite_v1.menu.DebugLevel.HTTPServer.build.debug_level=-DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.UPDATER=Updater -espresso_lite_v1.menu.DebugLevel.UPDATER.build.debug_level=-DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.DebugLevel.OTA_____=OTA -espresso_lite_v1.menu.DebugLevel.OTA_____.build.debug_level=-DDEBUG_ESP_OTA -espresso_lite_v1.menu.DebugLevel.OTA2____=OTA + Updater -espresso_lite_v1.menu.DebugLevel.OTA2____.build.debug_level=-DDEBUG_ESP_OTA -DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.DebugLevel.all_____=All -espresso_lite_v1.menu.DebugLevel.all_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM - -espresso_lite_v1.build.debug_port= -espresso_lite_v1.build.debug_level= - -############################################################## -espresso_lite_v2.name=ESPresso Lite 2.0 -espresso_lite_v2.upload.tool=esptool -espresso_lite_v2.upload.speed=115200 -espresso_lite_v2.upload.maximum_size=1044464 -espresso_lite_v2.upload.maximum_data_size=81920 -espresso_lite_v2.upload.wait_for_upload_port=true - -espresso_lite_v2.build.mcu=esp8266 -espresso_lite_v2.build.f_cpu=80000000L -espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 -espresso_lite_v2.build.core=esp8266 -espresso_lite_v2.build.variant=espresso_lite_v2 -espresso_lite_v2.build.flash_mode=dio -espresso_lite_v2.build.flash_size=4M -espresso_lite_v2.build.flash_freq=40 - -espresso_lite_v2.menu.CpuFrequency.80=80 MHz -espresso_lite_v2.menu.CpuFrequency.80.build.f_cpu=80000000L -espresso_lite_v2.menu.CpuFrequency.160=160 MHz -espresso_lite_v2.menu.CpuFrequency.160.build.f_cpu=160000000L - -espresso_lite_v2.menu.UploadSpeed.115200=115200 -espresso_lite_v2.menu.UploadSpeed.115200.upload.speed=115200 -espresso_lite_v2.menu.UploadSpeed.57600=57600 -espresso_lite_v2.menu.UploadSpeed.57600.upload.speed=57600 -espresso_lite_v2.menu.UploadSpeed.256000.windows=256000 -espresso_lite_v2.menu.UploadSpeed.256000.upload.speed=256000 -espresso_lite_v2.menu.UploadSpeed.230400.linux=230400 -espresso_lite_v2.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v2.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v2.menu.UploadSpeed.230400.upload.speed=230400 -espresso_lite_v2.menu.UploadSpeed.460800.linux=460800 -espresso_lite_v2.menu.UploadSpeed.460800.macosx=460800 -espresso_lite_v2.menu.UploadSpeed.460800.upload.speed=460800 -espresso_lite_v2.menu.UploadSpeed.512000.windows=512000 -espresso_lite_v2.menu.UploadSpeed.512000.upload.speed=512000 -espresso_lite_v2.menu.UploadSpeed.921600=921600 -espresso_lite_v2.menu.UploadSpeed.921600.upload.speed=921600 - -espresso_lite_v2.menu.FlashSize.4M3M=4M (3M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.FlashSize.4M3M.upload.maximum_size=1044464 - -espresso_lite_v2.menu.FlashSize.4M1M=4M (1M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.FlashSize.4M1M.upload.maximum_size=1044464 - -espresso_lite_v2.menu.ResetMethod.ck=ck -espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu - -espresso_lite_v2.menu.Debug.Disabled=Disabled -espresso_lite_v2.menu.Debug.Disabled.build.debug_port= -espresso_lite_v2.menu.Debug.Serial=Serial -espresso_lite_v2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v2.menu.Debug.Serial1=Serial1 -espresso_lite_v2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 - -espresso_lite_v2.menu.DebugLevel.None____=None -espresso_lite_v2.menu.DebugLevel.None____.build.debug_level= -espresso_lite_v2.menu.DebugLevel.Core____=Core -espresso_lite_v2.menu.DebugLevel.Core____.build.debug_level=-DDEBUG_ESP_CORE -espresso_lite_v2.menu.DebugLevel.SSL_____=Core + SSL -espresso_lite_v2.menu.DebugLevel.SSL_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -espresso_lite_v2.menu.DebugLevel.SSL_MEM_=Core + SSL + TLS Mem -espresso_lite_v2.menu.DebugLevel.SSL_MEM_.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_TLS_MEM -espresso_lite_v2.menu.DebugLevel.WiFic___=Core + WiFi -espresso_lite_v2.menu.DebugLevel.WiFic___.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -espresso_lite_v2.menu.DebugLevel.WiFi____=WiFi -espresso_lite_v2.menu.DebugLevel.WiFi____.build.debug_level=-DDEBUG_ESP_WIFI -espresso_lite_v2.menu.DebugLevel.HTTPClient=HTTPClient -espresso_lite_v2.menu.DebugLevel.HTTPClient.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.HTTPClient2=HTTPClient + SSL -espresso_lite_v2.menu.DebugLevel.HTTPClient2.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_SSL -espresso_lite_v2.menu.DebugLevel.HTTPUpdate=HTTPUpdate -espresso_lite_v2.menu.DebugLevel.HTTPUpdate.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v2.menu.DebugLevel.HTTPUpdate2=HTTPClient + HTTPUpdate -espresso_lite_v2.menu.DebugLevel.HTTPUpdate2.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v2.menu.DebugLevel.HTTPUpdate3=HTTPClient + HTTPUpdate + Updater -espresso_lite_v2.menu.DebugLevel.HTTPUpdate3.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.DebugLevel.HTTPServer=HTTPServer -espresso_lite_v2.menu.DebugLevel.HTTPServer.build.debug_level=-DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.UPDATER=Updater -espresso_lite_v2.menu.DebugLevel.UPDATER.build.debug_level=-DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.DebugLevel.OTA_____=OTA -espresso_lite_v2.menu.DebugLevel.OTA_____.build.debug_level=-DDEBUG_ESP_OTA -espresso_lite_v2.menu.DebugLevel.OTA2____=OTA + Updater -espresso_lite_v2.menu.DebugLevel.OTA2____.build.debug_level=-DDEBUG_ESP_OTA -DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.DebugLevel.all_____=All -espresso_lite_v2.menu.DebugLevel.all_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM - -espresso_lite_v2.build.debug_port= -espresso_lite_v2.build.debug_level= - -############################################################## -phoenix_v1.name=Phoenix 1.0 -phoenix_v1.upload.tool=esptool -phoenix_v1.upload.speed=115200 -phoenix_v1.upload.maximum_size=1044464 -phoenix_v1.upload.maximum_data_size=81920 -phoenix_v1.upload.wait_for_upload_port=true - -phoenix_v1.build.mcu=esp8266 -phoenix_v1.build.f_cpu=80000000L -phoenix_v1.build.board=ESP8266_PHOENIX_V1 -phoenix_v1.build.core=esp8266 -phoenix_v1.build.variant=phoenix_v1 -phoenix_v1.build.flash_mode=dio -phoenix_v1.build.flash_size=4M -phoenix_v1.build.flash_freq=40 - -phoenix_v1.menu.CpuFrequency.80=80 MHz -phoenix_v1.menu.CpuFrequency.80.build.f_cpu=80000000L -phoenix_v1.menu.CpuFrequency.160=160 MHz -phoenix_v1.menu.CpuFrequency.160.build.f_cpu=160000000L - -phoenix_v1.menu.UploadSpeed.115200=115200 -phoenix_v1.menu.UploadSpeed.115200.upload.speed=115200 -phoenix_v1.menu.UploadSpeed.57600=57600 -phoenix_v1.menu.UploadSpeed.57600.upload.speed=57600 -phoenix_v1.menu.UploadSpeed.256000.windows=256000 -phoenix_v1.menu.UploadSpeed.256000.upload.speed=256000 -phoenix_v1.menu.UploadSpeed.230400.linux=230400 -phoenix_v1.menu.UploadSpeed.230400.macosx=230400 -phoenix_v1.menu.UploadSpeed.230400.macosx=230400 -phoenix_v1.menu.UploadSpeed.230400.upload.speed=230400 -phoenix_v1.menu.UploadSpeed.460800.linux=460800 -phoenix_v1.menu.UploadSpeed.460800.macosx=460800 -phoenix_v1.menu.UploadSpeed.460800.upload.speed=460800 -phoenix_v1.menu.UploadSpeed.512000.windows=512000 -phoenix_v1.menu.UploadSpeed.512000.upload.speed=512000 -phoenix_v1.menu.UploadSpeed.921600=921600 -phoenix_v1.menu.UploadSpeed.921600.upload.speed=921600 - -phoenix_v1.menu.FlashSize.4M3M=4M (3M SPIFFS) -phoenix_v1.menu.FlashSize.4M3M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -phoenix_v1.menu.FlashSize.4M3M.upload.maximum_size=1044464 - -phoenix_v1.menu.FlashSize.4M1M=4M (1M SPIFFS) -phoenix_v1.menu.FlashSize.4M1M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -phoenix_v1.menu.FlashSize.4M1M.upload.maximum_size=1044464 - -phoenix_v1.menu.ResetMethod.nodemcu=nodemcu -phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v1.menu.ResetMethod.ck=ck -phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck - -phoenix_v1.menu.Debug.Disabled=Disabled -phoenix_v1.menu.Debug.Disabled.build.debug_port= -phoenix_v1.menu.Debug.Serial=Serial -phoenix_v1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v1.menu.Debug.Serial1=Serial1 -phoenix_v1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 - -phoenix_v1.menu.DebugLevel.None____=None -phoenix_v1.menu.DebugLevel.None____.build.debug_level= -phoenix_v1.menu.DebugLevel.Core____=Core -phoenix_v1.menu.DebugLevel.Core____.build.debug_level=-DDEBUG_ESP_CORE -phoenix_v1.menu.DebugLevel.SSL_____=Core + SSL -phoenix_v1.menu.DebugLevel.SSL_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -phoenix_v1.menu.DebugLevel.SSL_MEM_=Core + SSL + TLS Mem -phoenix_v1.menu.DebugLevel.SSL_MEM_.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_TLS_MEM -phoenix_v1.menu.DebugLevel.WiFic___=Core + WiFi -phoenix_v1.menu.DebugLevel.WiFic___.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -phoenix_v1.menu.DebugLevel.WiFi____=WiFi -phoenix_v1.menu.DebugLevel.WiFi____.build.debug_level=-DDEBUG_ESP_WIFI -phoenix_v1.menu.DebugLevel.HTTPClient=HTTPClient -phoenix_v1.menu.DebugLevel.HTTPClient.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.HTTPClient2=HTTPClient + SSL -phoenix_v1.menu.DebugLevel.HTTPClient2.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_SSL -phoenix_v1.menu.DebugLevel.HTTPUpdate=HTTPUpdate -phoenix_v1.menu.DebugLevel.HTTPUpdate.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -phoenix_v1.menu.DebugLevel.HTTPUpdate2=HTTPClient + HTTPUpdate -phoenix_v1.menu.DebugLevel.HTTPUpdate2.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -phoenix_v1.menu.DebugLevel.HTTPUpdate3=HTTPClient + HTTPUpdate + Updater -phoenix_v1.menu.DebugLevel.HTTPUpdate3.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -phoenix_v1.menu.DebugLevel.HTTPServer=HTTPServer -phoenix_v1.menu.DebugLevel.HTTPServer.build.debug_level=-DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.UPDATER=Updater -phoenix_v1.menu.DebugLevel.UPDATER.build.debug_level=-DDEBUG_ESP_UPDATER -phoenix_v1.menu.DebugLevel.OTA_____=OTA -phoenix_v1.menu.DebugLevel.OTA_____.build.debug_level=-DDEBUG_ESP_OTA -phoenix_v1.menu.DebugLevel.OTA2____=OTA + Updater -phoenix_v1.menu.DebugLevel.OTA2____.build.debug_level=-DDEBUG_ESP_OTA -DDEBUG_ESP_UPDATER -phoenix_v1.menu.DebugLevel.all_____=All -phoenix_v1.menu.DebugLevel.all_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM - -phoenix_v1.build.debug_port= -phoenix_v1.build.debug_level= - -############################################################## -phoenix_v2.name=Phoenix 2.0 -phoenix_v2.upload.tool=esptool -phoenix_v2.upload.speed=115200 -phoenix_v2.upload.maximum_size=1044464 -phoenix_v2.upload.maximum_data_size=81920 -phoenix_v2.upload.wait_for_upload_port=true - -phoenix_v2.build.mcu=esp8266 -phoenix_v2.build.f_cpu=80000000L -phoenix_v2.build.board=ESP8266_PHOENIX_V2 -phoenix_v2.build.core=esp8266 -phoenix_v2.build.variant=phoenix_v2 -phoenix_v2.build.flash_mode=dio -phoenix_v2.build.flash_size=4M -phoenix_v2.build.flash_freq=40 - -phoenix_v2.menu.CpuFrequency.80=80 MHz -phoenix_v2.menu.CpuFrequency.80.build.f_cpu=80000000L -phoenix_v2.menu.CpuFrequency.160=160 MHz -phoenix_v2.menu.CpuFrequency.160.build.f_cpu=160000000L - -phoenix_v2.menu.UploadSpeed.115200=115200 -phoenix_v2.menu.UploadSpeed.115200.upload.speed=115200 -phoenix_v2.menu.UploadSpeed.57600=57600 -phoenix_v2.menu.UploadSpeed.57600.upload.speed=57600 -phoenix_v2.menu.UploadSpeed.256000.windows=256000 -phoenix_v2.menu.UploadSpeed.256000.upload.speed=256000 -phoenix_v2.menu.UploadSpeed.230400.linux=230400 -phoenix_v2.menu.UploadSpeed.230400.macosx=230400 -phoenix_v2.menu.UploadSpeed.230400.macosx=230400 -phoenix_v2.menu.UploadSpeed.230400.upload.speed=230400 -phoenix_v2.menu.UploadSpeed.460800.linux=460800 -phoenix_v2.menu.UploadSpeed.460800.macosx=460800 -phoenix_v2.menu.UploadSpeed.460800.upload.speed=460800 -phoenix_v2.menu.UploadSpeed.512000.windows=512000 -phoenix_v2.menu.UploadSpeed.512000.upload.speed=512000 -phoenix_v2.menu.UploadSpeed.921600=921600 -phoenix_v2.menu.UploadSpeed.921600.upload.speed=921600 - -phoenix_v2.menu.FlashSize.4M3M=4M (3M SPIFFS) -phoenix_v2.menu.FlashSize.4M3M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -phoenix_v2.menu.FlashSize.4M3M.upload.maximum_size=1044464 - -phoenix_v2.menu.FlashSize.4M1M=4M (1M SPIFFS) -phoenix_v2.menu.FlashSize.4M1M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -phoenix_v2.menu.FlashSize.4M1M.upload.maximum_size=1044464 - -phoenix_v2.menu.ResetMethod.ck=ck -phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v2.menu.ResetMethod.nodemcu=nodemcu -phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu - -phoenix_v2.menu.Debug.Disabled=Disabled -phoenix_v2.menu.Debug.Disabled.build.debug_port= -phoenix_v2.menu.Debug.Serial=Serial -phoenix_v2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v2.menu.Debug.Serial1=Serial1 -phoenix_v2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 - -phoenix_v2.menu.DebugLevel.None____=None -phoenix_v2.menu.DebugLevel.None____.build.debug_level= -phoenix_v2.menu.DebugLevel.Core____=Core -phoenix_v2.menu.DebugLevel.Core____.build.debug_level=-DDEBUG_ESP_CORE -phoenix_v2.menu.DebugLevel.SSL_____=Core + SSL -phoenix_v2.menu.DebugLevel.SSL_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -phoenix_v2.menu.DebugLevel.SSL_MEM_=Core + SSL + TLS Mem -phoenix_v2.menu.DebugLevel.SSL_MEM_.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_TLS_MEM -phoenix_v2.menu.DebugLevel.WiFic___=Core + WiFi -phoenix_v2.menu.DebugLevel.WiFic___.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -phoenix_v2.menu.DebugLevel.WiFi____=WiFi -phoenix_v2.menu.DebugLevel.WiFi____.build.debug_level=-DDEBUG_ESP_WIFI -phoenix_v2.menu.DebugLevel.HTTPClient=HTTPClient -phoenix_v2.menu.DebugLevel.HTTPClient.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.HTTPClient2=HTTPClient + SSL -phoenix_v2.menu.DebugLevel.HTTPClient2.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_SSL -phoenix_v2.menu.DebugLevel.HTTPUpdate=HTTPUpdate -phoenix_v2.menu.DebugLevel.HTTPUpdate.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -phoenix_v2.menu.DebugLevel.HTTPUpdate2=HTTPClient + HTTPUpdate -phoenix_v2.menu.DebugLevel.HTTPUpdate2.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -phoenix_v2.menu.DebugLevel.HTTPUpdate3=HTTPClient + HTTPUpdate + Updater -phoenix_v2.menu.DebugLevel.HTTPUpdate3.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -phoenix_v2.menu.DebugLevel.HTTPServer=HTTPServer -phoenix_v2.menu.DebugLevel.HTTPServer.build.debug_level=-DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.UPDATER=Updater -phoenix_v2.menu.DebugLevel.UPDATER.build.debug_level=-DDEBUG_ESP_UPDATER -phoenix_v2.menu.DebugLevel.OTA_____=OTA -phoenix_v2.menu.DebugLevel.OTA_____.build.debug_level=-DDEBUG_ESP_OTA -phoenix_v2.menu.DebugLevel.OTA2____=OTA + Updater -phoenix_v2.menu.DebugLevel.OTA2____.build.debug_level=-DDEBUG_ESP_OTA -DDEBUG_ESP_UPDATER -phoenix_v2.menu.DebugLevel.all_____=All -phoenix_v2.menu.DebugLevel.all_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM - -phoenix_v2.build.debug_port= -phoenix_v2.build.debug_level= - -############################################################## -nodemcu.name=NodeMCU 0.9 (ESP-12 Module) - -nodemcu.upload.tool=esptool -nodemcu.upload.speed=115200 -nodemcu.upload.resetmethod=nodemcu -nodemcu.upload.maximum_size=1044464 -nodemcu.upload.maximum_data_size=81920 -nodemcu.upload.wait_for_upload_port=true -nodemcu.serial.disableDTR=true -nodemcu.serial.disableRTS=true - -nodemcu.build.mcu=esp8266 -nodemcu.build.f_cpu=80000000L -nodemcu.build.board=ESP8266_NODEMCU -nodemcu.build.core=esp8266 -nodemcu.build.variant=nodemcu -nodemcu.build.flash_mode=qio -nodemcu.build.flash_size=4M -nodemcu.build.flash_freq=40 -nodemcu.build.debug_port= -nodemcu.build.debug_level= - -nodemcu.menu.CpuFrequency.80=80 MHz -nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L -nodemcu.menu.CpuFrequency.160=160 MHz -nodemcu.menu.CpuFrequency.160.build.f_cpu=160000000L - -nodemcu.menu.UploadSpeed.115200=115200 -nodemcu.menu.UploadSpeed.115200.upload.speed=115200 -nodemcu.menu.UploadSpeed.9600=9600 -nodemcu.menu.UploadSpeed.9600.upload.speed=9600 -nodemcu.menu.UploadSpeed.57600=57600 -nodemcu.menu.UploadSpeed.57600.upload.speed=57600 -nodemcu.menu.UploadSpeed.256000.windows=256000 -nodemcu.menu.UploadSpeed.256000.upload.speed=256000 -nodemcu.menu.UploadSpeed.230400.linux=230400 -nodemcu.menu.UploadSpeed.230400.macosx=230400 -nodemcu.menu.UploadSpeed.230400.macosx=230400 -nodemcu.menu.UploadSpeed.230400.upload.speed=230400 -nodemcu.menu.UploadSpeed.460800.linux=460800 -nodemcu.menu.UploadSpeed.460800.macosx=460800 -nodemcu.menu.UploadSpeed.460800.upload.speed=460800 -nodemcu.menu.UploadSpeed.512000.windows=512000 -nodemcu.menu.UploadSpeed.512000.upload.speed=512000 -nodemcu.menu.UploadSpeed.921600=921600 -nodemcu.menu.UploadSpeed.921600.upload.speed=921600 - -nodemcu.menu.FlashSize.4M3M=4M (3M SPIFFS) -nodemcu.menu.FlashSize.4M3M.build.flash_size=4M -nodemcu.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -nodemcu.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -nodemcu.menu.FlashSize.4M3M.build.spiffs_pagesize=256 - -nodemcu.menu.FlashSize.4M1M=4M (1M SPIFFS) -nodemcu.menu.FlashSize.4M1M.build.flash_size=4M -nodemcu.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcu.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -nodemcu.menu.FlashSize.4M1M.build.spiffs_pagesize=256 - -############################################################## -nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) - -nodemcuv2.upload.tool=esptool -nodemcuv2.upload.speed=115200 -nodemcuv2.upload.resetmethod=nodemcu -nodemcuv2.upload.maximum_size=1044464 -nodemcuv2.upload.maximum_data_size=81920 -nodemcuv2.upload.wait_for_upload_port=true -nodemcuv2.serial.disableDTR=true -nodemcuv2.serial.disableRTS=true - -nodemcuv2.build.mcu=esp8266 -nodemcuv2.build.f_cpu=80000000L -nodemcuv2.build.board=ESP8266_NODEMCU -nodemcuv2.build.core=esp8266 -nodemcuv2.build.variant=nodemcu -nodemcuv2.build.flash_mode=dio -nodemcuv2.build.flash_size=4M -nodemcuv2.build.flash_freq=40 -nodemcuv2.build.debug_port= -nodemcuv2.build.debug_level= - -nodemcuv2.menu.CpuFrequency.80=80 MHz -nodemcuv2.menu.CpuFrequency.80.build.f_cpu=80000000L -nodemcuv2.menu.CpuFrequency.160=160 MHz -nodemcuv2.menu.CpuFrequency.160.build.f_cpu=160000000L - -nodemcuv2.menu.UploadSpeed.115200=115200 -nodemcuv2.menu.UploadSpeed.115200.upload.speed=115200 -nodemcuv2.menu.UploadSpeed.9600=9600 -nodemcuv2.menu.UploadSpeed.9600.upload.speed=9600 -nodemcuv2.menu.UploadSpeed.57600=57600 -nodemcuv2.menu.UploadSpeed.57600.upload.speed=57600 -nodemcuv2.menu.UploadSpeed.256000.windows=256000 -nodemcuv2.menu.UploadSpeed.256000.upload.speed=256000 -nodemcuv2.menu.UploadSpeed.230400.linux=230400 -nodemcuv2.menu.UploadSpeed.230400.macosx=230400 -nodemcuv2.menu.UploadSpeed.230400.macosx=230400 -nodemcuv2.menu.UploadSpeed.230400.upload.speed=230400 -nodemcuv2.menu.UploadSpeed.460800.linux=460800 -nodemcuv2.menu.UploadSpeed.460800.macosx=460800 -nodemcuv2.menu.UploadSpeed.460800.upload.speed=460800 -nodemcuv2.menu.UploadSpeed.512000.windows=512000 -nodemcuv2.menu.UploadSpeed.512000.upload.speed=512000 -nodemcuv2.menu.UploadSpeed.921600=921600 -nodemcuv2.menu.UploadSpeed.921600.upload.speed=921600 - -nodemcuv2.menu.FlashSize.4M3M=4M (3M SPIFFS) -nodemcuv2.menu.FlashSize.4M3M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 - -nodemcuv2.menu.FlashSize.4M1M=4M (1M SPIFFS) -nodemcuv2.menu.FlashSize.4M1M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 - - -############################################################## -modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) - -modwifi.upload.tool=esptool -modwifi.upload.speed=115200 -modwifi.upload.resetmethod=ck -modwifi.upload.maximum_size=1044464 -modwifi.upload.maximum_data_size=81920 -modwifi.upload.wait_for_upload_port=true -modwifi.serial.disableDTR=true -modwifi.serial.disableRTS=true - -modwifi.build.mcu=esp8266 -modwifi.build.f_cpu=80000000L -modwifi.build.board=MOD_WIFI_ESP8266 -modwifi.build.core=esp8266 -modwifi.build.variant=generic -# Winbond W25Q16 flash -modwifi.build.flash_mode=qio -modwifi.build.flash_size=2M -modwifi.build.flash_freq=40 -modwifi.build.flash_ld=eagle.flash.2m.ld -modwifi.build.spiffs_start=0x100000 -modwifi.build.spiffs_end=0x1FB000 -modwifi.build.spiffs_pagesize=256 -modwifi.build.spiffs_blocksize=8192 -modwifi.build.debug_port= -modwifi.build.debug_level= - -modwifi.menu.CpuFrequency.80=80 MHz -modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L -modwifi.menu.CpuFrequency.160=160 MHz -modwifi.menu.CpuFrequency.160.build.f_cpu=160000000L - -modwifi.menu.UploadSpeed.115200=115200 -modwifi.menu.UploadSpeed.115200.upload.speed=115200 -modwifi.menu.UploadSpeed.9600=9600 -modwifi.menu.UploadSpeed.9600.upload.speed=9600 -modwifi.menu.UploadSpeed.57600=57600 -modwifi.menu.UploadSpeed.57600.upload.speed=57600 -modwifi.menu.UploadSpeed.256000.windows=256000 -modwifi.menu.UploadSpeed.256000.upload.speed=256000 -modwifi.menu.UploadSpeed.230400.linux=230400 -modwifi.menu.UploadSpeed.230400.macosx=230400 -modwifi.menu.UploadSpeed.230400.macosx=230400 -modwifi.menu.UploadSpeed.230400.upload.speed=230400 -modwifi.menu.UploadSpeed.460800.linux=460800 -modwifi.menu.UploadSpeed.460800.macosx=460800 -modwifi.menu.UploadSpeed.460800.upload.speed=460800 -modwifi.menu.UploadSpeed.512000.windows=512000 -modwifi.menu.UploadSpeed.512000.upload.speed=512000 -modwifi.menu.UploadSpeed.921600=921600 -modwifi.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -thing.name=SparkFun ESP8266 Thing - -thing.upload.tool=esptool -thing.upload.speed=921600 -thing.upload.resetmethod=ck -thing.upload.maximum_size=434160 -thing.upload.maximum_data_size=81920 -thing.upload.wait_for_upload_port=true -thing.serial.disableDTR=true -thing.serial.disableRTS=true - -thing.build.mcu=esp8266 -thing.build.f_cpu=80000000L -thing.build.board=ESP8266_THING -thing.build.core=esp8266 -thing.build.variant=thing -thing.build.flash_mode=qio -# flash chip: AT25SF041 (512 kbyte, 4Mbit) -thing.build.flash_size=512K -thing.build.flash_ld=eagle.flash.512k64.ld -thing.build.flash_freq=40 -thing.build.spiffs_start=0x6B000 -thing.build.spiffs_end=0x7B000 -thing.build.spiffs_blocksize=4096 -thing.build.spiffs_pagesize=256 -thing.build.debug_port= -thing.build.debug_level= - -thing.menu.CpuFrequency.80=80 MHz -thing.menu.CpuFrequency.80.build.f_cpu=80000000L -thing.menu.CpuFrequency.160=160 MHz -thing.menu.CpuFrequency.160.build.f_cpu=160000000L - -thing.menu.UploadSpeed.115200=115200 -thing.menu.UploadSpeed.115200.upload.speed=115200 -thing.menu.UploadSpeed.9600=9600 -thing.menu.UploadSpeed.9600.upload.speed=9600 -thing.menu.UploadSpeed.57600=57600 -thing.menu.UploadSpeed.57600.upload.speed=57600 -thing.menu.UploadSpeed.256000.windows=256000 -thing.menu.UploadSpeed.256000.upload.speed=256000 -thing.menu.UploadSpeed.230400.linux=230400 -thing.menu.UploadSpeed.230400.macosx=230400 -thing.menu.UploadSpeed.230400.upload.speed=230400 -thing.menu.UploadSpeed.460800.linux=460800 -thing.menu.UploadSpeed.460800.macosx=460800 -thing.menu.UploadSpeed.460800.upload.speed=460800 -thing.menu.UploadSpeed.512000.windows=512000 -thing.menu.UploadSpeed.512000.upload.speed=512000 -thing.menu.UploadSpeed.921600=921600 -thing.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -thingdev.name=SparkFun ESP8266 Thing Dev - -thingdev.upload.tool=esptool -thingdev.upload.speed=921600 -thingdev.upload.resetmethod=nodemcu -thingdev.upload.maximum_size=434160 -thingdev.upload.maximum_data_size=81920 -thingdev.upload.wait_for_upload_port=true -thingdev.serial.disableDTR=true -thingdev.serial.disableRTS=true - -thingdev.build.mcu=esp8266 -thingdev.build.f_cpu=80000000L -thingdev.build.board=ESP8266_THING_DEV -thingdev.build.core=esp8266 -thingdev.build.variant=thing -thingdev.build.flash_mode=dio -# flash chip: AT25SF041 (512 kbyte, 4Mbit) -thingdev.build.flash_size=512K -thingdev.build.flash_ld=eagle.flash.512k64.ld -thingdev.build.flash_freq=40 -thingdev.build.debug_port= -thingdev.build.debug_level= - -thingdev.menu.CpuFrequency.80=80 MHz -thingdev.menu.CpuFrequency.80.build.f_cpu=80000000L -thingdev.menu.CpuFrequency.160=160 MHz -thingdev.menu.CpuFrequency.160.build.f_cpu=160000000L - -thingdev.menu.UploadSpeed.115200=115200 -thingdev.menu.UploadSpeed.115200.upload.speed=115200 -thingdev.menu.UploadSpeed.9600=9600 -thingdev.menu.UploadSpeed.9600.upload.speed=9600 -thingdev.menu.UploadSpeed.57600=57600 -thingdev.menu.UploadSpeed.57600.upload.speed=57600 -thingdev.menu.UploadSpeed.256000.windows=256000 -thingdev.menu.UploadSpeed.256000.upload.speed=256000 -thingdev.menu.UploadSpeed.230400.linux=230400 -thingdev.menu.UploadSpeed.230400.macosx=230400 -thingdev.menu.UploadSpeed.230400.upload.speed=230400 -thingdev.menu.UploadSpeed.460800.linux=460800 -thingdev.menu.UploadSpeed.460800.macosx=460800 -thingdev.menu.UploadSpeed.460800.upload.speed=460800 -thingdev.menu.UploadSpeed.512000.windows=512000 -thingdev.menu.UploadSpeed.512000.upload.speed=512000 -thingdev.menu.UploadSpeed.921600=921600 -thingdev.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -esp210.name=SweetPea ESP-210 - -esp210.upload.tool=esptool -esp210.upload.speed=115200 -esp210.upload.resetmethod=ck -esp210.upload.maximum_size=1044464 -esp210.upload.maximum_data_size=81920 -esp210.upload.wait_for_upload_port=true -esp210.serial.disableDTR=true -esp210.serial.disableRTS=true - -esp210.build.mcu=esp8266 -esp210.build.f_cpu=80000000L -esp210.build.board=ESP8266_ESP210 -esp210.build.core=esp8266 -esp210.build.variant=generic -esp210.build.flash_mode=qio -esp210.build.flash_size=4M -esp210.build.flash_freq=40 -esp210.build.debug_port= -esp210.build.debug_level= - -esp210.menu.CpuFrequency.80=80 MHz -esp210.menu.CpuFrequency.80.build.f_cpu=80000000L -esp210.menu.CpuFrequency.160=160 MHz -esp210.menu.CpuFrequency.160.build.f_cpu=160000000L - -esp210.menu.UploadSpeed.57600=57600 -esp210.menu.UploadSpeed.57600.upload.speed=57600 -esp210.menu.UploadSpeed.115200=115200 -esp210.menu.UploadSpeed.115200.upload.speed=115200 -esp210.menu.UploadSpeed.256000.windows=256000 -esp210.menu.UploadSpeed.256000.upload.speed=256000 -esp210.menu.UploadSpeed.230400.linux=230400 -esp210.menu.UploadSpeed.230400.macosx=230400 -esp210.menu.UploadSpeed.230400.macosx=230400 -esp210.menu.UploadSpeed.230400.upload.speed=230400 -esp210.menu.UploadSpeed.460800.linux=460800 -esp210.menu.UploadSpeed.460800.macosx=460800 -esp210.menu.UploadSpeed.460800.upload.speed=460800 -esp210.menu.UploadSpeed.512000.windows=512000 -esp210.menu.UploadSpeed.512000.upload.speed=512000 -esp210.menu.UploadSpeed.921600=921600 -esp210.menu.UploadSpeed.921600.upload.speed=921600 - -esp210.menu.FlashSize.4M3M=4M (3M SPIFFS) -esp210.menu.FlashSize.4M3M.build.flash_size=4M -esp210.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -esp210.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -esp210.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -esp210.menu.FlashSize.4M3M.build.spiffs_pagesize=256 - -esp210.menu.FlashSize.4M1M=4M (1M SPIFFS) -esp210.menu.FlashSize.4M1M.build.flash_size=4M -esp210.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -esp210.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -esp210.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -esp210.menu.FlashSize.4M1M.build.spiffs_pagesize=256 - -############################################################## -# wifio.name=Wifio -# -# wifio.upload.tool=esptool -# wifio.upload.speed=115200 -# wifio.upload.resetmethod=wifio -# wifio.upload.maximum_size=524288 -# wifio.upload.wait_for_upload_port=true -# -# wifio.build.mcu=esp8266 -# wifio.build.f_cpu=80000000L -# wifio.build.board=ESP8266_WIFIO -# wifio.build.core=esp8266 -# wifio.build.variant=wifio -# wifio.build.flash_mode=qio -# wifio.build.flash_size=512K -# wifio.build.flash_freq=40 -# wifio.build.flash_ld=eagle.flash.512k64.ld -# wifio.build.spiffs_start=0x6B000 -# wifio.build.spiffs_end=0x7B000 -# -# wifio.menu.CpuFrequency.80=80MHz -# wifio.menu.CpuFrequency.80.build.f_cpu=80000000L -# wifio.menu.CpuFrequency.160=160MHz -# wifio.menu.CpuFrequency.160.build.f_cpu=160000000L -# -# wifio.upload.tool=esptool -# - -############################################################## -d1_mini.name=WeMos D1 R2 & mini - -d1_mini.upload.tool=esptool -d1_mini.upload.speed=460800 -d1_mini.upload.resetmethod=nodemcu -d1_mini.upload.maximum_size=1044464 -d1_mini.upload.maximum_data_size=81920 -d1_mini.upload.wait_for_upload_port=true -d1_mini.serial.disableDTR=true -d1_mini.serial.disableRTS=true - -d1_mini.build.mcu=esp8266 -d1_mini.build.f_cpu=80000000L -d1_mini.build.board=ESP8266_WEMOS_D1MINI -d1_mini.build.core=esp8266 -d1_mini.build.variant=d1_mini -d1_mini.build.flash_mode=dio -d1_mini.build.flash_size=4M -d1_mini.build.flash_freq=40 -d1_mini.build.debug_port= -d1_mini.build.debug_level= - -d1_mini.menu.CpuFrequency.80=80 MHz -d1_mini.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini.menu.CpuFrequency.160=160 MHz -d1_mini.menu.CpuFrequency.160.build.f_cpu=160000000L - -d1_mini.menu.UploadSpeed.921600=921600 -d1_mini.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini.menu.UploadSpeed.115200=115200 -d1_mini.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini.menu.UploadSpeed.9600=9600 -d1_mini.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini.menu.UploadSpeed.57600=57600 -d1_mini.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini.menu.UploadSpeed.256000.windows=256000 -d1_mini.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini.menu.UploadSpeed.230400.linux=230400 -d1_mini.menu.UploadSpeed.230400.macosx=230400 -d1_mini.menu.UploadSpeed.230400.macosx=230400 -d1_mini.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini.menu.UploadSpeed.460800.linux=460800 -d1_mini.menu.UploadSpeed.460800.macosx=460800 -d1_mini.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini.menu.UploadSpeed.512000.windows=512000 -d1_mini.menu.UploadSpeed.512000.upload.speed=512000 - - -d1_mini.menu.FlashSize.4M3M=4M (3M SPIFFS) -d1_mini.menu.FlashSize.4M3M.build.flash_size=4M -d1_mini.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -d1_mini.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -d1_mini.menu.FlashSize.4M3M.build.spiffs_pagesize=256 - -d1_mini.menu.FlashSize.4M1M=4M (1M SPIFFS) -d1_mini.menu.FlashSize.4M1M.build.flash_size=4M -d1_mini.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1_mini.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -d1_mini.menu.FlashSize.4M1M.build.spiffs_pagesize=256 - -############################################################## -d1.name=WeMos D1(Retired) - -d1.upload.tool=esptool -d1.upload.speed=460800 -d1.upload.resetmethod=nodemcu -d1.upload.maximum_size=1044464 -d1.upload.maximum_data_size=81920 -d1.upload.wait_for_upload_port=true -d1.serial.disableDTR=true -d1.serial.disableRTS=true - -d1.build.mcu=esp8266 -d1.build.f_cpu=80000000L -d1.build.board=ESP8266_WEMOS_D1MINI -d1.build.core=esp8266 -d1.build.variant=d1 -d1.build.flash_mode=dio -d1.build.flash_size=4M -d1.build.flash_freq=40 -d1.build.debug_port= -d1.build.debug_level= - -d1.menu.CpuFrequency.80=80 MHz -d1.menu.CpuFrequency.80.build.f_cpu=80000000L -d1.menu.CpuFrequency.160=160 MHz -d1.menu.CpuFrequency.160.build.f_cpu=160000000L - -d1.menu.UploadSpeed.921600=921600 -d1.menu.UploadSpeed.921600.upload.speed=921600 -d1.menu.UploadSpeed.115200=115200 -d1.menu.UploadSpeed.115200.upload.speed=115200 -d1.menu.UploadSpeed.9600=9600 -d1.menu.UploadSpeed.9600.upload.speed=9600 -d1.menu.UploadSpeed.57600=57600 -d1.menu.UploadSpeed.57600.upload.speed=57600 -d1.menu.UploadSpeed.256000.windows=256000 -d1.menu.UploadSpeed.256000.upload.speed=256000 -d1.menu.UploadSpeed.230400.linux=230400 -d1.menu.UploadSpeed.230400.macosx=230400 -d1.menu.UploadSpeed.230400.macosx=230400 -d1.menu.UploadSpeed.230400.upload.speed=230400 -d1.menu.UploadSpeed.460800.linux=460800 -d1.menu.UploadSpeed.460800.macosx=460800 -d1.menu.UploadSpeed.460800.upload.speed=460800 -d1.menu.UploadSpeed.512000.windows=512000 -d1.menu.UploadSpeed.512000.upload.speed=512000 - - -d1.menu.FlashSize.4M3M=4M (3M SPIFFS) -d1.menu.FlashSize.4M3M.build.flash_size=4M -d1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -d1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -d1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -d1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 - -d1.menu.FlashSize.4M1M=4M (1M SPIFFS) -d1.menu.FlashSize.4M1M.build.flash_size=4M -d1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -d1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -d1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 - - -############################################################## - -espino.name=ESPino (ESP-12 Module) - -espino.upload.tool=esptool -espino.upload.speed=115200 -espino.upload.resetmethod=ck -espino.upload.maximum_size=1044464 -espino.upload.maximum_data_size=81920 -espino.upload.wait_for_upload_port=true -espino.serial.disableDTR=true -espino.serial.disableRTS=true - -espino.build.mcu=esp8266 -espino.build.f_cpu=80000000L -espino.build.board=ESP8266_ESP12 -espino.build.core=esp8266 -espino.build.variant=espino -espino.build.flash_mode=qio -espino.build.flash_size=4M -espino.build.flash_freq=40 -espino.build.spiffs_pagesize=256 -espino.build.debug_port= -espino.build.debug_level= - -espino.menu.CpuFrequency.80=80 MHz -espino.menu.CpuFrequency.80.build.f_cpu=80000000L -espino.menu.CpuFrequency.160=160 MHz -espino.menu.CpuFrequency.160.build.f_cpu=160000000L - -espino.menu.FlashMode.dio=DIO -espino.menu.FlashMode.dio.build.flash_mode=dio -espino.menu.FlashMode.qio=QIO -espino.menu.FlashMode.qio.build.flash_mode=qio - -espino.menu.UploadSpeed.115200=115200 -espino.menu.UploadSpeed.115200.upload.speed=115200 -espino.menu.UploadSpeed.9600=9600 -espino.menu.UploadSpeed.9600.upload.speed=9600 -espino.menu.UploadSpeed.57600=57600 -espino.menu.UploadSpeed.57600.upload.speed=57600 -espino.menu.UploadSpeed.256000.windows=256000 -espino.menu.UploadSpeed.256000.upload.speed=256000 -espino.menu.UploadSpeed.230400.linux=230400 -espino.menu.UploadSpeed.230400.macosx=230400 -espino.menu.UploadSpeed.230400.upload.speed=230400 -espino.menu.UploadSpeed.460800.linux=460800 -espino.menu.UploadSpeed.460800.macosx=460800 -espino.menu.UploadSpeed.460800.upload.speed=460800 -espino.menu.UploadSpeed.512000.windows=512000 -espino.menu.UploadSpeed.512000.upload.speed=512000 -espino.menu.UploadSpeed.921600=921600 -espino.menu.UploadSpeed.921600.upload.speed=921600 - -espino.menu.FlashSize.4M1M=4M (1M SPIFFS) -espino.menu.FlashSize.4M1M.build.flash_size=4M -espino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espino.menu.FlashSize.4M1M.upload.maximum_size=1044464 - -espino.menu.FlashSize.4M3M=4M (3M SPIFFS) -espino.menu.FlashSize.4M3M.build.flash_size=4M -espino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espino.menu.FlashSize.4M3M.upload.maximum_size=1044464 - -espino.menu.ResetMethod.ck=ck -espino.menu.ResetMethod.ck.upload.resetmethod=ck -espino.menu.ResetMethod.nodemcu=nodemcu -espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu - -############################################################## -espinotee.name=ThaiEasyElec's ESPino - -espinotee.upload.tool=esptool -espinotee.upload.speed=115200 -espinotee.upload.resetmethod=nodemcu -espinotee.upload.maximum_size=1044464 -espinotee.upload.maximum_data_size=81920 -espinotee.upload.wait_for_upload_port=true -espinotee.serial.disableDTR=true -espinotee.serial.disableRTS=true - -espinotee.build.mcu=esp8266 -espinotee.build.f_cpu=80000000L -espinotee.build.board=ESP8266_ESP13 -espinotee.build.core=esp8266 -espinotee.build.variant=espinotee -espinotee.build.flash_mode=qio -espinotee.build.flash_size=4M -espinotee.build.flash_freq=40 -espinotee.build.debug_port= -espinotee.build.debug_level= - -espinotee.menu.CpuFrequency.80=80 MHz -espinotee.menu.CpuFrequency.80.build.f_cpu=80000000L -espinotee.menu.CpuFrequency.160=160 MHz -espinotee.menu.CpuFrequency.160.build.f_cpu=160000000L - -espinotee.menu.UploadSpeed.115200=115200 -espinotee.menu.UploadSpeed.115200.upload.speed=115200 -espinotee.menu.UploadSpeed.9600=9600 -espinotee.menu.UploadSpeed.9600.upload.speed=9600 -espinotee.menu.UploadSpeed.57600=57600 -espinotee.menu.UploadSpeed.57600.upload.speed=57600 -espinotee.menu.UploadSpeed.256000.windows=256000 -espinotee.menu.UploadSpeed.256000.upload.speed=256000 -espinotee.menu.UploadSpeed.230400.linux=230400 -espinotee.menu.UploadSpeed.230400.macosx=230400 -espinotee.menu.UploadSpeed.230400.macosx=230400 -espinotee.menu.UploadSpeed.230400.upload.speed=230400 -espinotee.menu.UploadSpeed.460800.linux=460800 -espinotee.menu.UploadSpeed.460800.macosx=460800 -espinotee.menu.UploadSpeed.460800.upload.speed=460800 -espinotee.menu.UploadSpeed.512000.windows=512000 -espinotee.menu.UploadSpeed.512000.upload.speed=512000 -espinotee.menu.UploadSpeed.921600=921600 -espinotee.menu.UploadSpeed.921600.upload.speed=921600 - -espinotee.menu.FlashSize.4M3M=4M (3M SPIFFS) -espinotee.menu.FlashSize.4M3M.build.flash_size=4M -espinotee.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espinotee.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espinotee.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espinotee.menu.FlashSize.4M3M.build.spiffs_pagesize=256 - -espinotee.menu.FlashSize.4M1M=4M (1M SPIFFS) -espinotee.menu.FlashSize.4M1M.build.flash_size=4M -espinotee.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espinotee.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espinotee.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espinotee.menu.FlashSize.4M1M.build.spiffs_pagesize=256 - -############################################################## -wifinfo.name=WifInfo - -wifinfo.upload.tool=esptool -wifinfo.upload.speed=115200 -wifinfo.upload.resetmethod=nodemcu -wifinfo.upload.maximum_size=434160 -wifinfo.upload.maximum_data_size=81920 -wifinfo.upload.wait_for_upload_port=true -wifinfo.serial.disableDTR=true -wifinfo.serial.disableRTS=true - -wifinfo.build.mcu=esp8266 -wifinfo.build.core=esp8266 -wifinfo.build.variant=wifinfo -wifinfo.build.board=WIFINFO -wifinfo.build.spiffs_pagesize=256 -wifinfo.build.debug_port=Serial1 -wifinfo.build.debug_level=Wifinfo - -wifinfo.menu.Debug.Disabled=Disabled -wifinfo.menu.Debug.Disabled.build.debug_port= -wifinfo.menu.Debug.Serial=Serial -wifinfo.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifinfo.menu.Debug.Serial1=Serial1 -wifinfo.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 - -wifinfo.menu.DebugLevel.None=None -wifinfo.menu.DebugLevel.None.build.debug_level= -wifinfo.menu.DebugLevel.Wifinfo=Wifinfo -wifinfo.menu.DebugLevel.Wifinfo.build.debug_level=-DDEBUG_ESP_WIFINFO - -#wifinfo.menu.ESPModule.ESP07512=ESP07 (1M/512K SPIFFS) -#wifinfo.menu.ESPModule.ESP07512.build.board=ESP8266_ESP07 -#wifinfo.menu.ESPModule.ESP07512.build.flash_size=1M -#wifinfo.menu.ESPModule.ESP07512.build.flash_ld=eagle.flash.1m512.ld -#wifinfo.menu.ESPModule.ESP07512.build.spiffs_start=0x7B000 -#wifinfo.menu.ESPModule.ESP07512.build.spiffs_end=0xFB000 -#wifinfo.menu.ESPModule.ESP07512.build.spiffs_blocksize=8192 -#wifinfo.menu.ESPModule.ESP07512.upload.maximum_size=499696 - -#wifinfo.menu.ESPModule.ESP07256=ESP07 (1M/256K SPIFFS) -#wifinfo.menu.ESPModule.ESP07256.build.board=ESP8266_ESP07 -#wifinfo.menu.ESPModule.ESP07256.build.flash_size=1M -#wifinfo.menu.ESPModule.ESP07256.build.flash_ld=eagle.flash.1m256.ld -#wifinfo.menu.ESPModule.ESP07256.build.spiffs_start=0xBB000 -#wifinfo.menu.ESPModule.ESP07256.build.spiffs_end=0xFB000 -##wifinfo.menu.ESPModule.ESP07256.build.spiffs_blocksize=4096 -#wifinfo.menu.ESPModule.ESP07256.upload.maximum_size=761840 - -wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) -wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 -wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M -wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 -wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 - -#wifinfo.menu.ESPModule.ESP07160=ESP07 (1M/160K SPIFFS) -#wifinfo.menu.ESPModule.ESP07160.build.board=ESP8266_ESP07 -#wifinfo.menu.ESPModule.ESP07160.build.flash_size=1M -#wifinfo.menu.ESPModule.ESP07160.build.flash_ld=eagle.flash.1m160.ld -#wifinfo.menu.ESPModule.ESP07160.build.spiffs_start=0xD3000 -#wifinfo.menu.ESPModule.ESP07160.build.spiffs_end=0xFB000 -#wifinfo.menu.ESPModule.ESP07160.build.spiffs_blocksize=4096 -#wifinfo.menu.ESPModule.ESP07160.upload.maximum_size=860144 -# -#wifinfo.menu.ESPModule.ESP07144=ESP07 (1M/144K SPIFFS) -#wifinfo.menu.ESPModule.ESP07144.build.board=ESP8266_ESP07 -#wifinfo.menu.ESPModule.ESP07144.build.flash_size=1M -#wifinfo.menu.ESPModule.ESP07144.build.flash_ld=eagle.flash.1m144.ld -#wifinfo.menu.ESPModule.ESP07144.build.spiffs_start=0xD7000 -#wifinfo.menu.ESPModule.ESP07144.build.spiffs_end=0xFB000 -#wifinfo.menu.ESPModule.ESP07144.build.spiffs_blocksize=4096 -#wifinfo.menu.ESPModule.ESP07144.upload.maximum_size=876528 -# -#wifinfo.menu.ESPModule.ESP07=ESP07 (1M/64K SPIFFS) -#wifinfo.menu.ESPModule.ESP07.build.board=ESP8266_ESP07 -#wifinfo.menu.ESPModule.ESP07.build.flash_size=1M -#wifinfo.menu.ESPModule.ESP07.build.flash_ld=eagle.flash.1m64.ld -#wifinfo.menu.ESPModule.ESP07.build.spiffs_start=0xEB000 -#wifinfo.menu.ESPModule.ESP07.build.spiffs_end=0xFB000 -#wifinfo.menu.ESPModule.ESP07.build.spiffs_blocksize=4096 -#wifinfo.menu.ESPModule.ESP07.upload.maximum_size=958448 - -wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) -wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 -wifinfo.menu.ESPModule.ESP12.build.flash_size=4M -wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld -wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 -wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 -wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 -wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 -wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 - -wifinfo.menu.CpuFrequency.160=160 MHz -wifinfo.menu.CpuFrequency.160.build.f_cpu=160000000L -wifinfo.menu.CpuFrequency.80=80 MHz -wifinfo.menu.CpuFrequency.80.build.f_cpu=80000000L - -wifinfo.menu.FlashFreq.40=40MHz -wifinfo.menu.FlashFreq.40.build.flash_freq=40 -wifinfo.menu.FlashFreq.80=80MHz -wifinfo.menu.FlashFreq.80.build.flash_freq=80 - -wifinfo.menu.FlashMode.qio=QIO -wifinfo.menu.FlashMode.qio.build.flash_mode=qio -wifinfo.menu.FlashMode.dio=DIO -wifinfo.menu.FlashMode.dio.build.flash_mode=dio - -wifinfo.menu.UploadSpeed.115200=115200 -wifinfo.menu.UploadSpeed.115200.upload.speed=115200 -wifinfo.menu.UploadSpeed.9600=9600 -wifinfo.menu.UploadSpeed.9600.upload.speed=9600 -wifinfo.menu.UploadSpeed.57600=57600 -wifinfo.menu.UploadSpeed.57600.upload.speed=57600 -wifinfo.menu.UploadSpeed.256000.windows=256000 -wifinfo.menu.UploadSpeed.256000.upload.speed=256000 -wifinfo.menu.UploadSpeed.230400.linux=230400 -wifinfo.menu.UploadSpeed.230400.macosx=230400 -wifinfo.menu.UploadSpeed.230400.upload.speed=230400 -wifinfo.menu.UploadSpeed.460800.linux=460800 -wifinfo.menu.UploadSpeed.460800.macosx=460800 -wifinfo.menu.UploadSpeed.460800.upload.speed=460800 -wifinfo.menu.UploadSpeed.512000.windows=512000 -wifinfo.menu.UploadSpeed.512000.upload.speed=512000 -wifinfo.menu.UploadSpeed.921600=921600 -wifinfo.menu.UploadSpeed.921600.upload.speed=921600 - - -############################################################## -coredev.name=Core Development Module - -coredev.upload.tool=esptool -coredev.upload.speed=115200 -coredev.upload.resetmethod=ck -coredev.upload.maximum_size=434160 -coredev.upload.maximum_data_size=81920 -coredev.upload.wait_for_upload_port=true -coredev.serial.disableDTR=true -coredev.serial.disableRTS=true - -coredev.build.mcu=esp8266 -coredev.build.f_cpu=80000000L -coredev.build.board=ESP8266_ESP01 -coredev.build.core=esp8266 -coredev.build.variant=generic -coredev.build.flash_mode=qio -coredev.build.spiffs_pagesize=256 -coredev.build.debug_port= -coredev.build.debug_level= -coredev.build.lwip_lib=-llwip -coredev.build.lwip_flags= - - -coredev.menu.LwIPVariant.Espressif=Espressif (xcc) -coredev.menu.LwIPVariant.Espressif.build.lwip_lib=-llwip -coredev.menu.LwIPVariant.Espressif.build.lwip_flags= -coredev.menu.LwIPVariant.Prebuilt=Prebuilt Source (gcc) -coredev.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -coredev.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -coredev.menu.LwIPVariant.OpenSource=Open Source (gcc) -coredev.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -coredev.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -coredev.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" - -coredev.menu.CpuFrequency.80=80 MHz -coredev.menu.CpuFrequency.80.build.f_cpu=80000000L -coredev.menu.CpuFrequency.160=160 MHz -coredev.menu.CpuFrequency.160.build.f_cpu=160000000L - -coredev.menu.FlashFreq.40=40MHz -coredev.menu.FlashFreq.40.build.flash_freq=40 -coredev.menu.FlashFreq.80=80MHz -coredev.menu.FlashFreq.80.build.flash_freq=80 - -coredev.menu.FlashMode.dio=DIO -coredev.menu.FlashMode.dio.build.flash_mode=dio -coredev.menu.FlashMode.qio=QIO -coredev.menu.FlashMode.qio.build.flash_mode=qio -coredev.menu.FlashMode.dout=DOUT -coredev.menu.FlashMode.dout.build.flash_mode=dout -coredev.menu.FlashMode.qout=QOUT -coredev.menu.FlashMode.qout.build.flash_mode=qout - -coredev.menu.UploadSpeed.115200=115200 -coredev.menu.UploadSpeed.115200.upload.speed=115200 -coredev.menu.UploadSpeed.9600=9600 -coredev.menu.UploadSpeed.9600.upload.speed=9600 -coredev.menu.UploadSpeed.57600=57600 -coredev.menu.UploadSpeed.57600.upload.speed=57600 -coredev.menu.UploadSpeed.256000.windows=256000 -coredev.menu.UploadSpeed.256000.upload.speed=256000 -coredev.menu.UploadSpeed.230400.linux=230400 -coredev.menu.UploadSpeed.230400.macosx=230400 -coredev.menu.UploadSpeed.230400.upload.speed=230400 -coredev.menu.UploadSpeed.460800.linux=460800 -coredev.menu.UploadSpeed.460800.macosx=460800 -coredev.menu.UploadSpeed.460800.upload.speed=460800 -coredev.menu.UploadSpeed.512000.windows=512000 -coredev.menu.UploadSpeed.512000.upload.speed=512000 -coredev.menu.UploadSpeed.921600=921600 -coredev.menu.UploadSpeed.921600.upload.speed=921600 - -coredev.menu.FlashSize.512K64=512K (64K SPIFFS) -coredev.menu.FlashSize.512K64.build.flash_size=512K -coredev.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -coredev.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -coredev.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -coredev.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -coredev.menu.FlashSize.512K64.upload.maximum_size=434160 - -coredev.menu.FlashSize.512K128=512K (128K SPIFFS) -coredev.menu.FlashSize.512K128.build.flash_size=512K -coredev.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -coredev.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -coredev.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -coredev.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -coredev.menu.FlashSize.512K128.upload.maximum_size=368624 - -coredev.menu.FlashSize.512K0=512K (no SPIFFS) -coredev.menu.FlashSize.512K0.build.flash_size=512K -coredev.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -coredev.menu.FlashSize.512K0.upload.maximum_size=499696 - -coredev.menu.FlashSize.1M512=1M (512K SPIFFS) -coredev.menu.FlashSize.1M512.build.flash_size=1M -coredev.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -coredev.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -coredev.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -coredev.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -coredev.menu.FlashSize.1M512.upload.maximum_size=499696 - -coredev.menu.FlashSize.1M256=1M (256K SPIFFS) -coredev.menu.FlashSize.1M256.build.flash_size=1M -coredev.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -coredev.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -coredev.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -coredev.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -coredev.menu.FlashSize.1M256.upload.maximum_size=761840 - -coredev.menu.FlashSize.1M192=1M (192K SPIFFS) -coredev.menu.FlashSize.1M192.build.flash_size=1M -coredev.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -coredev.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -coredev.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -coredev.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -coredev.menu.FlashSize.1M192.upload.maximum_size=827376 - -coredev.menu.FlashSize.1M160=1M (160K SPIFFS) -coredev.menu.FlashSize.1M160.build.flash_size=1M -coredev.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -coredev.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -coredev.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -coredev.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -coredev.menu.FlashSize.1M160.upload.maximum_size=860144 - -coredev.menu.FlashSize.1M144=1M (144K SPIFFS) -coredev.menu.FlashSize.1M144.build.flash_size=1M -coredev.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -coredev.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -coredev.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -coredev.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -coredev.menu.FlashSize.1M144.upload.maximum_size=876528 - -coredev.menu.FlashSize.1M128=1M (128K SPIFFS) -coredev.menu.FlashSize.1M128.build.flash_size=1M -coredev.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -coredev.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -coredev.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -coredev.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -coredev.menu.FlashSize.1M128.upload.maximum_size=892912 - -coredev.menu.FlashSize.1M64=1M (64K SPIFFS) -coredev.menu.FlashSize.1M64.build.flash_size=1M -coredev.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -coredev.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -coredev.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -coredev.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -coredev.menu.FlashSize.1M64.upload.maximum_size=958448 - -coredev.menu.FlashSize.2M=2M (1M SPIFFS) -coredev.menu.FlashSize.2M.build.flash_size=2M -coredev.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -coredev.menu.FlashSize.2M.build.spiffs_start=0x100000 -coredev.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -coredev.menu.FlashSize.2M.build.spiffs_blocksize=8192 -coredev.menu.FlashSize.2M.upload.maximum_size=1044464 - -coredev.menu.FlashSize.4M1M=4M (1M SPIFFS) -coredev.menu.FlashSize.4M1M.build.flash_size=4M -coredev.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -coredev.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -coredev.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -coredev.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -coredev.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -coredev.menu.FlashSize.4M1M.upload.maximum_size=1044464 - -coredev.menu.FlashSize.4M3M=4M (3M SPIFFS) -coredev.menu.FlashSize.4M3M.build.flash_size=4M -coredev.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -coredev.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -coredev.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -coredev.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -coredev.menu.FlashSize.4M3M.upload.maximum_size=1044464 - -coredev.menu.ResetMethod.ck=ck -coredev.menu.ResetMethod.ck.upload.resetmethod=ck -coredev.menu.ResetMethod.nodemcu=nodemcu -coredev.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu - -coredev.menu.Debug.Disabled=Disabled -coredev.menu.Debug.Disabled.build.debug_port= -coredev.menu.Debug.Serial=Serial -coredev.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -coredev.menu.Debug.Serial1=Serial1 -coredev.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 - -coredev.menu.DebugLevel.None____=None -coredev.menu.DebugLevel.None____.build.debug_level= -coredev.menu.DebugLevel.Core____=Core -coredev.menu.DebugLevel.Core____.build.debug_level=-DDEBUG_ESP_CORE -coredev.menu.DebugLevel.SSL_____=Core + SSL -coredev.menu.DebugLevel.SSL_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -coredev.menu.DebugLevel.SSL_MEM_=Core + SSL + TLS Mem -coredev.menu.DebugLevel.SSL_MEM_.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_TLS_MEM -coredev.menu.DebugLevel.WiFic___=Core + WiFi -coredev.menu.DebugLevel.WiFic___.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -coredev.menu.DebugLevel.WiFi____=WiFi -coredev.menu.DebugLevel.WiFi____.build.debug_level=-DDEBUG_ESP_WIFI -coredev.menu.DebugLevel.HTTPClient=HTTPClient -coredev.menu.DebugLevel.HTTPClient.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -coredev.menu.DebugLevel.HTTPClient2=HTTPClient + SSL -coredev.menu.DebugLevel.HTTPClient2.build.debug_level=-DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_SSL -coredev.menu.DebugLevel.HTTPUpdate=HTTPUpdate -coredev.menu.DebugLevel.HTTPUpdate.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -coredev.menu.DebugLevel.HTTPUpdate2=HTTPClient + HTTPUpdate -coredev.menu.DebugLevel.HTTPUpdate2.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -coredev.menu.DebugLevel.HTTPUpdate3=HTTPClient + HTTPUpdate + Updater -coredev.menu.DebugLevel.HTTPUpdate3.build.debug_level=-DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -coredev.menu.DebugLevel.HTTPServer=HTTPServer -coredev.menu.DebugLevel.HTTPServer.build.debug_level=-DDEBUG_ESP_HTTP_SERVER -coredev.menu.DebugLevel.UPDATER=Updater -coredev.menu.DebugLevel.UPDATER.build.debug_level=-DDEBUG_ESP_UPDATER -coredev.menu.DebugLevel.OTA_____=OTA -coredev.menu.DebugLevel.OTA_____.build.debug_level=-DDEBUG_ESP_OTA -coredev.menu.DebugLevel.OTA2____=OTA + Updater -coredev.menu.DebugLevel.OTA2____.build.debug_level=-DDEBUG_ESP_OTA -DDEBUG_ESP_UPDATER -coredev.menu.DebugLevel.all_____=All -coredev.menu.DebugLevel.all_____.build.debug_level=-DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM From 44cf79777848e42ce5b52a92d108cb7a710fe043 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 29 Feb 2020 14:36:07 +0100 Subject: [PATCH 525/559] Delete platform.txt --- arduino/version 2.3.0/platform.txt | 130 ----------------------------- 1 file changed, 130 deletions(-) delete mode 100644 arduino/version 2.3.0/platform.txt diff --git a/arduino/version 2.3.0/platform.txt b/arduino/version 2.3.0/platform.txt deleted file mode 100644 index d9c60b3f1..000000000 --- a/arduino/version 2.3.0/platform.txt +++ /dev/null @@ -1,130 +0,0 @@ - -# ESP8266 platform -# ------------------------------ - -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification - -name=ESP8266 Modules -version=2.2.0 - - - - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -compiler.warning_flags.more=-Wall -compiler.warning_flags.all=-Wall -Wextra - -build.lwip_lib=-llwip_gcc -build.lwip_flags=-DLWIP_OPEN_SRC - -compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ -compiler.sdk.path={runtime.platform.path}/tools/sdk -compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/lwip/include" "-I{build.path}/core" - -compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections - -compiler.S.cmd=xtensa-lx106-elf-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls - -compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,register_chipv6_phy - -compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lm -lgcc -lhal -lphy -lpp -lnet80211 -lwpa -lcrypto -lmain -lwps -laxtls -lsmartconfig -lmesh -lwpa2 {build.lwip_lib} -lstdc++ - -compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections - -compiler.as.cmd=xtensa-lx106-elf-as - -compiler.ar.cmd=xtensa-lx106-elf-ar -compiler.ar.flags=cru - -compiler.elf2hex.cmd=esptool -compiler.elf2hex.flags= - -compiler.size.cmd=xtensa-lx106-elf-size - -compiler.esptool.cmd=esptool -compiler.esptool.cmd.windows=esptool.exe - -# This can be overriden in boards.txt -build.extra_flags=-DESP8266 - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -## generate file with git version number -## needs bash, git, and echo - -## windows-compatible version may be added later - - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/arduino.ar" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/arduino.ar" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" - -## Create eeprom -recipe.objcopy.eep.pattern= - -## Create hex -#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" - -recipe.objcopy.hex.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec - -## Save hex -recipe.output.tmp_file={build.project_name}.bin -recipe.output.save_file={build.project_name}.{build.variant}.bin - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* -#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - -# ------------------------------ - -tools.esptool.cmd=esptool -tools.esptool.cmd.windows=esptool.exe -tools.esptool.path={runtime.tools.esptool.path} -tools.esptool.network_cmd=python -tools.esptool.network_cmd.windows=python.exe - -tools.esptool.upload.protocol=esp -tools.esptool.upload.params.verbose=-vv -tools.esptool.upload.params.quiet= -tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" -ca 0x00000 -cf "{build.path}/{build.project_name}.bin" -tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" - -tools.mkspiffs.cmd=mkspiffs -tools.mkspiffs.cmd.windows=mkspiffs.exe -tools.mkspiffs.path={runtime.tools.mkspiffs.path} - -tools.espupload.cmd=python -tools.espupload.cmd.windows=python.exe -tools.espupload.path={runtime.platform.path}/tools - -tools.espupload.upload.protocol=espupload -tools.espupload.upload.params.verbose= -tools.espupload.upload.params.quiet= -tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" From 6dde795e0cb18b949bd2736d6dc7ae6df7878cf6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 29 Feb 2020 14:36:21 +0100 Subject: [PATCH 526/559] Delete boards.txt --- arduino/version 2.4.2/boards.txt | 4829 ------------------------------ 1 file changed, 4829 deletions(-) delete mode 100644 arduino/version 2.4.2/boards.txt diff --git a/arduino/version 2.4.2/boards.txt b/arduino/version 2.4.2/boards.txt deleted file mode 100644 index ead81b6f0..000000000 --- a/arduino/version 2.4.2/boards.txt +++ /dev/null @@ -1,4829 +0,0 @@ -# -# Do not create pull-requests for this file only, CI will not accept them. -# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. -# All modified files after running with option "--allgen" must be included in the pull-request. -# - -menu.BoardModel=Model -menu.UploadSpeed=Upload Speed -menu.UploadTool=Upload Using -menu.CpuFrequency=CPU Frequency -menu.CrystalFreq=Crystal Frequency -menu.FlashSize=Flash Size -menu.FlashMode=Flash Mode -menu.FlashFreq=Flash Frequency -menu.ResetMethod=Reset Method -menu.ESPModule=Module -menu.Debug=Debug port -menu.DebugLevel=Debug Level -menu.LwIPVariant=lwIP Variant -menu.VTable=VTables -menu.led=Builtin Led -menu.FlashErase=Erase Flash - -############################################################## -generic.name=Generic ESP8266 Module -generic.build.board=ESP8266_GENERIC -generic.upload.tool=esptool -generic.upload.maximum_data_size=81920 -generic.upload.wait_for_upload_port=true -generic.upload.erase_cmd= -generic.serial.disableDTR=true -generic.serial.disableRTS=true -generic.build.mcu=esp8266 -generic.build.core=esp8266 -generic.build.variant=generic -generic.build.spiffs_pagesize=256 -generic.build.debug_port= -generic.build.debug_level= - -generic.menu.UploadTool.esptool=Serial -generic.menu.UploadTool.esptool.upload.tool=esptool -generic.menu.UploadTool.esptool.upload.verbose=-vv -generic.menu.UploadTool.espupload=OTA_upload -generic.menu.UploadTool.espupload.upload.tool=espupload - -generic.menu.CpuFrequency.80=80 MHz -generic.menu.CpuFrequency.80.build.f_cpu=80000000L -generic.menu.CpuFrequency.160=160 MHz -generic.menu.CpuFrequency.160.build.f_cpu=160000000L -generic.menu.VTable.flash=Flash -generic.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -generic.menu.VTable.heap=Heap -generic.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -generic.menu.VTable.iram=IRAM -generic.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -generic.menu.ResetMethod.ck=ck -generic.menu.ResetMethod.ck.upload.resetmethod=ck -generic.menu.ResetMethod.nodemcu=nodemcu -generic.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -generic.menu.ResetMethod.none=none -generic.menu.ResetMethod.none.upload.resetmethod=none -generic.menu.ResetMethod.dtrset=dtrset -generic.menu.ResetMethod.dtrset.upload.resetmethod=dtrset -generic.menu.CrystalFreq.26=26 MHz -generic.menu.CrystalFreq.40=40 MHz -generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -generic.menu.FlashFreq.40=40MHz -generic.menu.FlashFreq.40.build.flash_freq=40 -generic.menu.FlashFreq.80=80MHz -generic.menu.FlashFreq.80.build.flash_freq=80 -generic.menu.FlashMode.qio=QIO -generic.menu.FlashMode.qio.build.flash_mode=qio -generic.menu.FlashMode.qout=QOUT -generic.menu.FlashMode.qout.build.flash_mode=qout -generic.menu.FlashMode.dio=DIO -generic.menu.FlashMode.dio.build.flash_mode=dio -generic.menu.FlashMode.dout=DOUT -generic.menu.FlashMode.dout.build.flash_mode=dout -generic.menu.FlashSize.512K0=512K (no SPIFFS) -generic.menu.FlashSize.512K0.build.flash_size=512K -generic.menu.FlashSize.512K0.build.flash_size_bytes=0x80000 -generic.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -generic.menu.FlashSize.512K0.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K0.upload.maximum_size=499696 -generic.menu.FlashSize.512K0.build.rfcal_addr=0x7C000 -generic.menu.FlashSize.512K32=512K (32K SPIFFS) -generic.menu.FlashSize.512K32.build.flash_size=512K -generic.menu.FlashSize.512K32.build.flash_size_bytes=0x80000 -generic.menu.FlashSize.512K32.build.flash_ld=eagle.flash.512k32.ld -generic.menu.FlashSize.512K32.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K32.upload.maximum_size=466928 -generic.menu.FlashSize.512K32.build.rfcal_addr=0x7C000 -generic.menu.FlashSize.512K32.build.spiffs_start=0x73000 -generic.menu.FlashSize.512K32.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K32.build.spiffs_blocksize=4096 -generic.menu.FlashSize.512K64=512K (64K SPIFFS) -generic.menu.FlashSize.512K64.build.flash_size=512K -generic.menu.FlashSize.512K64.build.flash_size_bytes=0x80000 -generic.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -generic.menu.FlashSize.512K64.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K64.upload.maximum_size=434160 -generic.menu.FlashSize.512K64.build.rfcal_addr=0x7C000 -generic.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -generic.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -generic.menu.FlashSize.512K128=512K (128K SPIFFS) -generic.menu.FlashSize.512K128.build.flash_size=512K -generic.menu.FlashSize.512K128.build.flash_size_bytes=0x80000 -generic.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -generic.menu.FlashSize.512K128.build.spiffs_pagesize=256 -generic.menu.FlashSize.512K128.upload.maximum_size=368624 -generic.menu.FlashSize.512K128.build.rfcal_addr=0x7C000 -generic.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -generic.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -generic.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M0=1M (no SPIFFS) -generic.menu.FlashSize.1M0.build.flash_size=1M -generic.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -generic.menu.FlashSize.1M0.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M0.upload.maximum_size=1023984 -generic.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M64=1M (64K SPIFFS) -generic.menu.FlashSize.1M64.build.flash_size=1M -generic.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -generic.menu.FlashSize.1M64.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M64.upload.maximum_size=958448 -generic.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -generic.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M128=1M (128K SPIFFS) -generic.menu.FlashSize.1M128.build.flash_size=1M -generic.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -generic.menu.FlashSize.1M128.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M128.upload.maximum_size=892912 -generic.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -generic.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M144=1M (144K SPIFFS) -generic.menu.FlashSize.1M144.build.flash_size=1M -generic.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -generic.menu.FlashSize.1M144.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M144.upload.maximum_size=876528 -generic.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -generic.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M160=1M (160K SPIFFS) -generic.menu.FlashSize.1M160.build.flash_size=1M -generic.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -generic.menu.FlashSize.1M160.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M160.upload.maximum_size=860144 -generic.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -generic.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M192=1M (192K SPIFFS) -generic.menu.FlashSize.1M192.build.flash_size=1M -generic.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -generic.menu.FlashSize.1M192.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M192.upload.maximum_size=827376 -generic.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -generic.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M256=1M (256K SPIFFS) -generic.menu.FlashSize.1M256.build.flash_size=1M -generic.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -generic.menu.FlashSize.1M256.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M256.upload.maximum_size=761840 -generic.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -generic.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -generic.menu.FlashSize.1M512=1M (512K SPIFFS) -generic.menu.FlashSize.1M512.build.flash_size=1M -generic.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -generic.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -generic.menu.FlashSize.1M512.build.spiffs_pagesize=256 -generic.menu.FlashSize.1M512.upload.maximum_size=499696 -generic.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -generic.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -generic.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -generic.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -generic.menu.FlashSize.2M=2M (1M SPIFFS) -generic.menu.FlashSize.2M.build.flash_size=2M -generic.menu.FlashSize.2M.build.flash_size_bytes=0x200000 -generic.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -generic.menu.FlashSize.2M.build.spiffs_pagesize=256 -generic.menu.FlashSize.2M.upload.maximum_size=1044464 -generic.menu.FlashSize.2M.build.rfcal_addr=0x1FC000 -generic.menu.FlashSize.2M.build.spiffs_start=0x100000 -generic.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -generic.menu.FlashSize.2M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M1M=4M (1M SPIFFS) -generic.menu.FlashSize.4M1M.build.flash_size=4M -generic.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -generic.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -generic.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -generic.menu.FlashSize.4M1M.upload.maximum_size=1044464 -generic.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -generic.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -generic.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M2M=4M (2M SPIFFS) -generic.menu.FlashSize.4M2M.build.flash_size=4M -generic.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -generic.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -generic.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -generic.menu.FlashSize.4M2M.upload.maximum_size=1044464 -generic.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -generic.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -generic.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.4M3M=4M (3M SPIFFS) -generic.menu.FlashSize.4M3M.build.flash_size=4M -generic.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -generic.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -generic.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -generic.menu.FlashSize.4M3M.upload.maximum_size=1044464 -generic.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -generic.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -generic.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -generic.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.8M7M=8M (7M SPIFFS) -generic.menu.FlashSize.8M7M.build.flash_size=8M -generic.menu.FlashSize.8M7M.build.flash_size_bytes=0x800000 -generic.menu.FlashSize.8M7M.build.flash_ld=eagle.flash.8m.ld -generic.menu.FlashSize.8M7M.build.spiffs_pagesize=256 -generic.menu.FlashSize.8M7M.upload.maximum_size=1044464 -generic.menu.FlashSize.8M7M.build.rfcal_addr=0x7FC000 -generic.menu.FlashSize.8M7M.build.spiffs_start=0x100000 -generic.menu.FlashSize.8M7M.build.spiffs_end=0x7FB000 -generic.menu.FlashSize.8M7M.build.spiffs_blocksize=8192 -generic.menu.FlashSize.16M15M=16M (15M SPIFFS) -generic.menu.FlashSize.16M15M.build.flash_size=16M -generic.menu.FlashSize.16M15M.build.flash_size_bytes=0x1000000 -generic.menu.FlashSize.16M15M.build.flash_ld=eagle.flash.16m.ld -generic.menu.FlashSize.16M15M.build.spiffs_pagesize=256 -generic.menu.FlashSize.16M15M.upload.maximum_size=1044464 -generic.menu.FlashSize.16M15M.build.rfcal_addr=0xFFC000 -generic.menu.FlashSize.16M15M.build.spiffs_start=0x100000 -generic.menu.FlashSize.16M15M.build.spiffs_end=0xFFB000 -generic.menu.FlashSize.16M15M.build.spiffs_blocksize=8192 -generic.menu.led.2=2 -generic.menu.led.2.build.led=-DLED_BUILTIN=2 -generic.menu.led.0=0 -generic.menu.led.0.build.led=-DLED_BUILTIN=0 -generic.menu.led.1=1 -generic.menu.led.1.build.led=-DLED_BUILTIN=1 -generic.menu.led.3=3 -generic.menu.led.3.build.led=-DLED_BUILTIN=3 -generic.menu.led.4=4 -generic.menu.led.4.build.led=-DLED_BUILTIN=4 -generic.menu.led.5=5 -generic.menu.led.5.build.led=-DLED_BUILTIN=5 -generic.menu.led.6=6 -generic.menu.led.6.build.led=-DLED_BUILTIN=6 -generic.menu.led.7=7 -generic.menu.led.7.build.led=-DLED_BUILTIN=7 -generic.menu.led.8=8 -generic.menu.led.8.build.led=-DLED_BUILTIN=8 -generic.menu.led.9=9 -generic.menu.led.9.build.led=-DLED_BUILTIN=9 -generic.menu.led.10=10 -generic.menu.led.10.build.led=-DLED_BUILTIN=10 -generic.menu.led.11=11 -generic.menu.led.11.build.led=-DLED_BUILTIN=11 -generic.menu.led.12=12 -generic.menu.led.12.build.led=-DLED_BUILTIN=12 -generic.menu.led.13=13 -generic.menu.led.13.build.led=-DLED_BUILTIN=13 -generic.menu.led.14=14 -generic.menu.led.14.build.led=-DLED_BUILTIN=14 -generic.menu.led.15=15 -generic.menu.led.15.build.led=-DLED_BUILTIN=15 -generic.menu.LwIPVariant.v2mss536=v2 Lower Memory -generic.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -generic.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -generic.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -generic.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -generic.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -generic.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -generic.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -generic.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -generic.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -generic.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.LwIPVariant.OpenSource=v1.4 Compile from source -generic.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -generic.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -generic.menu.Debug.Disabled=Disabled -generic.menu.Debug.Disabled.build.debug_port= -generic.menu.Debug.Serial=Serial -generic.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -generic.menu.Debug.Serial1=Serial1 -generic.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -generic.menu.DebugLevel.None____=None -generic.menu.DebugLevel.None____.build.debug_level= -generic.menu.DebugLevel.SSL=SSL -generic.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -generic.menu.DebugLevel.TLS_MEM=TLS_MEM -generic.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -generic.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -generic.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -generic.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -generic.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -generic.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -generic.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.DebugLevel.CORE=CORE -generic.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -generic.menu.DebugLevel.WIFI=WIFI -generic.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -generic.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -generic.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -generic.menu.DebugLevel.UPDATER=UPDATER -generic.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -generic.menu.DebugLevel.OTA=OTA -generic.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -generic.menu.DebugLevel.OOM=OOM -generic.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -generic.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -generic.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -generic.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -generic.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -generic.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -generic.menu.FlashErase.none=Only Sketch -generic.menu.FlashErase.none.upload.erase_cmd= -generic.menu.FlashErase.sdk=Sketch + WiFi Settings -generic.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -generic.menu.FlashErase.all=All Flash Contents -generic.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -generic.menu.UploadSpeed.115200=115200 -generic.menu.UploadSpeed.115200.upload.speed=115200 -generic.menu.UploadSpeed.9600=9600 -generic.menu.UploadSpeed.9600.upload.speed=9600 -generic.menu.UploadSpeed.57600=57600 -generic.menu.UploadSpeed.57600.upload.speed=57600 -generic.menu.UploadSpeed.230400.linux=230400 -generic.menu.UploadSpeed.230400.macosx=230400 -generic.menu.UploadSpeed.230400.upload.speed=230400 -generic.menu.UploadSpeed.256000.windows=256000 -generic.menu.UploadSpeed.256000.upload.speed=256000 -generic.menu.UploadSpeed.460800.linux=460800 -generic.menu.UploadSpeed.460800.macosx=460800 -generic.menu.UploadSpeed.460800.upload.speed=460800 -generic.menu.UploadSpeed.512000.windows=512000 -generic.menu.UploadSpeed.512000.upload.speed=512000 -generic.menu.UploadSpeed.921600=921600 -generic.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -esp8285.name=Generic ESP8285 Module -esp8285.build.board=ESP8266_ESP01 -esp8285.upload.tool=esptool -esp8285.upload.maximum_data_size=81920 -esp8285.upload.wait_for_upload_port=true -esp8285.upload.erase_cmd= -esp8285.serial.disableDTR=true -esp8285.serial.disableRTS=true -esp8285.build.mcu=esp8266 -esp8285.build.core=esp8266 -esp8285.build.variant=generic -esp8285.build.spiffs_pagesize=256 -esp8285.build.debug_port= -esp8285.build.debug_level= -esp8285.menu.CpuFrequency.80=80 MHz -esp8285.menu.CpuFrequency.80.build.f_cpu=80000000L -esp8285.menu.CpuFrequency.160=160 MHz -esp8285.menu.CpuFrequency.160.build.f_cpu=160000000L -esp8285.menu.VTable.flash=Flash -esp8285.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -esp8285.menu.VTable.heap=Heap -esp8285.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -esp8285.menu.VTable.iram=IRAM -esp8285.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -esp8285.menu.ResetMethod.ck=ck -esp8285.menu.ResetMethod.ck.upload.resetmethod=ck -esp8285.menu.ResetMethod.nodemcu=nodemcu -esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -esp8285.menu.ResetMethod.none=none -esp8285.menu.ResetMethod.none.upload.resetmethod=none -esp8285.menu.ResetMethod.dtrset=dtrset -esp8285.menu.ResetMethod.dtrset.upload.resetmethod=dtrset -esp8285.menu.CrystalFreq.26=26 MHz -esp8285.menu.CrystalFreq.40=40 MHz -esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -esp8285.build.flash_mode=dout -esp8285.build.flash_freq=40 -esp8285.menu.FlashSize.1M0=1M (no SPIFFS) -esp8285.menu.FlashSize.1M0.build.flash_size=1M -esp8285.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -esp8285.menu.FlashSize.1M0.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M0.upload.maximum_size=1023984 -esp8285.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M64=1M (64K SPIFFS) -esp8285.menu.FlashSize.1M64.build.flash_size=1M -esp8285.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -esp8285.menu.FlashSize.1M64.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M64.upload.maximum_size=958448 -esp8285.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -esp8285.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M128=1M (128K SPIFFS) -esp8285.menu.FlashSize.1M128.build.flash_size=1M -esp8285.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -esp8285.menu.FlashSize.1M128.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M128.upload.maximum_size=892912 -esp8285.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -esp8285.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M144=1M (144K SPIFFS) -esp8285.menu.FlashSize.1M144.build.flash_size=1M -esp8285.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -esp8285.menu.FlashSize.1M144.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M144.upload.maximum_size=876528 -esp8285.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -esp8285.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M160=1M (160K SPIFFS) -esp8285.menu.FlashSize.1M160.build.flash_size=1M -esp8285.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -esp8285.menu.FlashSize.1M160.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M160.upload.maximum_size=860144 -esp8285.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -esp8285.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M192=1M (192K SPIFFS) -esp8285.menu.FlashSize.1M192.build.flash_size=1M -esp8285.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -esp8285.menu.FlashSize.1M192.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M192.upload.maximum_size=827376 -esp8285.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -esp8285.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M256=1M (256K SPIFFS) -esp8285.menu.FlashSize.1M256.build.flash_size=1M -esp8285.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -esp8285.menu.FlashSize.1M256.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M256.upload.maximum_size=761840 -esp8285.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -esp8285.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -esp8285.menu.FlashSize.1M512=1M (512K SPIFFS) -esp8285.menu.FlashSize.1M512.build.flash_size=1M -esp8285.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -esp8285.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -esp8285.menu.FlashSize.1M512.build.spiffs_pagesize=256 -esp8285.menu.FlashSize.1M512.upload.maximum_size=499696 -esp8285.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -esp8285.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -esp8285.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -esp8285.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -esp8285.menu.led.2=2 -esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 -esp8285.menu.led.0=0 -esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 -esp8285.menu.led.1=1 -esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 -esp8285.menu.led.3=3 -esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 -esp8285.menu.led.4=4 -esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 -esp8285.menu.led.5=5 -esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 -esp8285.menu.led.6=6 -esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 -esp8285.menu.led.7=7 -esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 -esp8285.menu.led.8=8 -esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 -esp8285.menu.led.9=9 -esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 -esp8285.menu.led.10=10 -esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 -esp8285.menu.led.11=11 -esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 -esp8285.menu.led.12=12 -esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 -esp8285.menu.led.13=13 -esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 -esp8285.menu.led.14=14 -esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 -esp8285.menu.led.15=15 -esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 -esp8285.menu.LwIPVariant.v2mss536=v2 Lower Memory -esp8285.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -esp8285.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -esp8285.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -esp8285.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -esp8285.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -esp8285.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -esp8285.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -esp8285.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.LwIPVariant.OpenSource=v1.4 Compile from source -esp8285.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -esp8285.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp8285.menu.Debug.Disabled=Disabled -esp8285.menu.Debug.Disabled.build.debug_port= -esp8285.menu.Debug.Serial=Serial -esp8285.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp8285.menu.Debug.Serial1=Serial1 -esp8285.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp8285.menu.DebugLevel.None____=None -esp8285.menu.DebugLevel.None____.build.debug_level= -esp8285.menu.DebugLevel.SSL=SSL -esp8285.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp8285.menu.DebugLevel.TLS_MEM=TLS_MEM -esp8285.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp8285.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -esp8285.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -esp8285.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp8285.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp8285.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.DebugLevel.CORE=CORE -esp8285.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp8285.menu.DebugLevel.WIFI=WIFI -esp8285.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp8285.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -esp8285.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp8285.menu.DebugLevel.UPDATER=UPDATER -esp8285.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp8285.menu.DebugLevel.OTA=OTA -esp8285.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp8285.menu.DebugLevel.OOM=OOM -esp8285.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -esp8285.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp8285.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp8285.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp8285.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -esp8285.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp8285.menu.FlashErase.none=Only Sketch -esp8285.menu.FlashErase.none.upload.erase_cmd= -esp8285.menu.FlashErase.sdk=Sketch + WiFi Settings -esp8285.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -esp8285.menu.FlashErase.all=All Flash Contents -esp8285.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -esp8285.menu.UploadSpeed.115200=115200 -esp8285.menu.UploadSpeed.115200.upload.speed=115200 -esp8285.menu.UploadSpeed.9600=9600 -esp8285.menu.UploadSpeed.9600.upload.speed=9600 -esp8285.menu.UploadSpeed.57600=57600 -esp8285.menu.UploadSpeed.57600.upload.speed=57600 -esp8285.menu.UploadSpeed.230400.linux=230400 -esp8285.menu.UploadSpeed.230400.macosx=230400 -esp8285.menu.UploadSpeed.230400.upload.speed=230400 -esp8285.menu.UploadSpeed.256000.windows=256000 -esp8285.menu.UploadSpeed.256000.upload.speed=256000 -esp8285.menu.UploadSpeed.460800.linux=460800 -esp8285.menu.UploadSpeed.460800.macosx=460800 -esp8285.menu.UploadSpeed.460800.upload.speed=460800 -esp8285.menu.UploadSpeed.512000.windows=512000 -esp8285.menu.UploadSpeed.512000.upload.speed=512000 -esp8285.menu.UploadSpeed.921600=921600 -esp8285.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espduino.name=ESPDuino (ESP-13 Module) -espduino.build.board=ESP8266_ESP13 -espduino.build.variant=ESPDuino -espduino.menu.ResetMethod.v2=ESPduino-V2 -espduino.menu.ResetMethod.v2.upload.resetmethod=nodemcu -espduino.menu.ResetMethod.v1=ESPduino-V1 -espduino.menu.ResetMethod.v1.upload.resetmethod=ck -espduino.menu.UploadTool.esptool=Serial -espduino.menu.UploadTool.esptool.upload.tool=esptool -espduino.menu.UploadTool.esptool.upload.verbose=-vv -espduino.menu.UploadTool.espota=OTA -espduino.menu.UploadTool.espota.upload.tool=espota -espduino.upload.tool=esptool -espduino.upload.maximum_data_size=81920 -espduino.upload.wait_for_upload_port=true -espduino.upload.erase_cmd= -espduino.serial.disableDTR=true -espduino.serial.disableRTS=true -espduino.build.mcu=esp8266 -espduino.build.core=esp8266 -espduino.build.spiffs_pagesize=256 -espduino.build.debug_port= -espduino.build.debug_level= -espduino.menu.CpuFrequency.80=80 MHz -espduino.menu.CpuFrequency.80.build.f_cpu=80000000L -espduino.menu.CpuFrequency.160=160 MHz -espduino.menu.CpuFrequency.160.build.f_cpu=160000000L -espduino.menu.VTable.flash=Flash -espduino.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espduino.menu.VTable.heap=Heap -espduino.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espduino.menu.VTable.iram=IRAM -espduino.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espduino.build.flash_mode=dio -espduino.build.flash_freq=40 -espduino.menu.FlashSize.4M1M=4M (1M SPIFFS) -espduino.menu.FlashSize.4M1M.build.flash_size=4M -espduino.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espduino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espduino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espduino.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espduino.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espduino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espduino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espduino.menu.FlashSize.4M2M=4M (2M SPIFFS) -espduino.menu.FlashSize.4M2M.build.flash_size=4M -espduino.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -espduino.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espduino.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -espduino.menu.FlashSize.4M2M.upload.maximum_size=1044464 -espduino.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -espduino.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -espduino.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -espduino.menu.FlashSize.4M3M=4M (3M SPIFFS) -espduino.menu.FlashSize.4M3M.build.flash_size=4M -espduino.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espduino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espduino.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espduino.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espduino.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espduino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espduino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espduino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espduino.menu.LwIPVariant.v2mss536=v2 Lower Memory -espduino.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espduino.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espduino.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espduino.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espduino.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espduino.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espduino.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espduino.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espduino.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espduino.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espduino.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espduino.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espduino.menu.Debug.Disabled=Disabled -espduino.menu.Debug.Disabled.build.debug_port= -espduino.menu.Debug.Serial=Serial -espduino.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espduino.menu.Debug.Serial1=Serial1 -espduino.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espduino.menu.DebugLevel.None____=None -espduino.menu.DebugLevel.None____.build.debug_level= -espduino.menu.DebugLevel.SSL=SSL -espduino.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espduino.menu.DebugLevel.TLS_MEM=TLS_MEM -espduino.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espduino.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espduino.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espduino.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espduino.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espduino.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espduino.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.DebugLevel.CORE=CORE -espduino.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espduino.menu.DebugLevel.WIFI=WIFI -espduino.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espduino.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espduino.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espduino.menu.DebugLevel.UPDATER=UPDATER -espduino.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espduino.menu.DebugLevel.OTA=OTA -espduino.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espduino.menu.DebugLevel.OOM=OOM -espduino.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -espduino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espduino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espduino.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espduino.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espduino.menu.FlashErase.none=Only Sketch -espduino.menu.FlashErase.none.upload.erase_cmd= -espduino.menu.FlashErase.sdk=Sketch + WiFi Settings -espduino.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espduino.menu.FlashErase.all=All Flash Contents -espduino.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espduino.menu.UploadSpeed.115200=115200 -espduino.menu.UploadSpeed.115200.upload.speed=115200 -espduino.menu.UploadSpeed.9600=9600 -espduino.menu.UploadSpeed.9600.upload.speed=9600 -espduino.menu.UploadSpeed.57600=57600 -espduino.menu.UploadSpeed.57600.upload.speed=57600 -espduino.menu.UploadSpeed.230400.linux=230400 -espduino.menu.UploadSpeed.230400.macosx=230400 -espduino.menu.UploadSpeed.230400.upload.speed=230400 -espduino.menu.UploadSpeed.256000.windows=256000 -espduino.menu.UploadSpeed.256000.upload.speed=256000 -espduino.menu.UploadSpeed.460800.linux=460800 -espduino.menu.UploadSpeed.460800.macosx=460800 -espduino.menu.UploadSpeed.460800.upload.speed=460800 -espduino.menu.UploadSpeed.512000.windows=512000 -espduino.menu.UploadSpeed.512000.upload.speed=512000 -espduino.menu.UploadSpeed.921600=921600 -espduino.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -huzzah.name=Adafruit Feather HUZZAH ESP8266 -huzzah.build.board=ESP8266_ESP12 -huzzah.build.variant=adafruit -huzzah.upload.tool=esptool -huzzah.upload.maximum_data_size=81920 -huzzah.upload.wait_for_upload_port=true -huzzah.upload.erase_cmd= -huzzah.serial.disableDTR=true -huzzah.serial.disableRTS=true -huzzah.build.mcu=esp8266 -huzzah.build.core=esp8266 -huzzah.build.spiffs_pagesize=256 -huzzah.build.debug_port= -huzzah.build.debug_level= -huzzah.menu.CpuFrequency.80=80 MHz -huzzah.menu.CpuFrequency.80.build.f_cpu=80000000L -huzzah.menu.CpuFrequency.160=160 MHz -huzzah.menu.CpuFrequency.160.build.f_cpu=160000000L -huzzah.menu.VTable.flash=Flash -huzzah.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -huzzah.menu.VTable.heap=Heap -huzzah.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -huzzah.menu.VTable.iram=IRAM -huzzah.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -huzzah.upload.resetmethod=nodemcu -huzzah.build.flash_mode=qio -huzzah.build.flash_freq=40 -huzzah.menu.FlashSize.4M1M=4M (1M SPIFFS) -huzzah.menu.FlashSize.4M1M.build.flash_size=4M -huzzah.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -huzzah.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -huzzah.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -huzzah.menu.FlashSize.4M1M.upload.maximum_size=1044464 -huzzah.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -huzzah.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -huzzah.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -huzzah.menu.FlashSize.4M2M=4M (2M SPIFFS) -huzzah.menu.FlashSize.4M2M.build.flash_size=4M -huzzah.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -huzzah.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -huzzah.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -huzzah.menu.FlashSize.4M2M.upload.maximum_size=1044464 -huzzah.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -huzzah.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -huzzah.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -huzzah.menu.FlashSize.4M3M=4M (3M SPIFFS) -huzzah.menu.FlashSize.4M3M.build.flash_size=4M -huzzah.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -huzzah.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -huzzah.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -huzzah.menu.FlashSize.4M3M.upload.maximum_size=1044464 -huzzah.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -huzzah.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -huzzah.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -huzzah.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -huzzah.menu.LwIPVariant.v2mss536=v2 Lower Memory -huzzah.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -huzzah.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -huzzah.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -huzzah.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -huzzah.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -huzzah.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -huzzah.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -huzzah.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.LwIPVariant.OpenSource=v1.4 Compile from source -huzzah.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -huzzah.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -huzzah.menu.Debug.Disabled=Disabled -huzzah.menu.Debug.Disabled.build.debug_port= -huzzah.menu.Debug.Serial=Serial -huzzah.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -huzzah.menu.Debug.Serial1=Serial1 -huzzah.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -huzzah.menu.DebugLevel.None____=None -huzzah.menu.DebugLevel.None____.build.debug_level= -huzzah.menu.DebugLevel.SSL=SSL -huzzah.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -huzzah.menu.DebugLevel.TLS_MEM=TLS_MEM -huzzah.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -huzzah.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -huzzah.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -huzzah.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -huzzah.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -huzzah.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.DebugLevel.CORE=CORE -huzzah.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -huzzah.menu.DebugLevel.WIFI=WIFI -huzzah.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -huzzah.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -huzzah.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -huzzah.menu.DebugLevel.UPDATER=UPDATER -huzzah.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -huzzah.menu.DebugLevel.OTA=OTA -huzzah.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -huzzah.menu.DebugLevel.OOM=OOM -huzzah.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -huzzah.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -huzzah.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -huzzah.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -huzzah.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -huzzah.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -huzzah.menu.FlashErase.none=Only Sketch -huzzah.menu.FlashErase.none.upload.erase_cmd= -huzzah.menu.FlashErase.sdk=Sketch + WiFi Settings -huzzah.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -huzzah.menu.FlashErase.all=All Flash Contents -huzzah.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -huzzah.menu.UploadSpeed.115200=115200 -huzzah.menu.UploadSpeed.115200.upload.speed=115200 -huzzah.menu.UploadSpeed.9600=9600 -huzzah.menu.UploadSpeed.9600.upload.speed=9600 -huzzah.menu.UploadSpeed.57600=57600 -huzzah.menu.UploadSpeed.57600.upload.speed=57600 -huzzah.menu.UploadSpeed.230400.linux=230400 -huzzah.menu.UploadSpeed.230400.macosx=230400 -huzzah.menu.UploadSpeed.230400.upload.speed=230400 -huzzah.menu.UploadSpeed.256000.windows=256000 -huzzah.menu.UploadSpeed.256000.upload.speed=256000 -huzzah.menu.UploadSpeed.460800.linux=460800 -huzzah.menu.UploadSpeed.460800.macosx=460800 -huzzah.menu.UploadSpeed.460800.upload.speed=460800 -huzzah.menu.UploadSpeed.512000.windows=512000 -huzzah.menu.UploadSpeed.512000.upload.speed=512000 -huzzah.menu.UploadSpeed.921600=921600 -huzzah.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -cw01.name=XinaBox CW01 -cw01.build.board=ESP8266_GENERIC -cw01.build.variant=xinabox -cw01.upload.tool=esptool -cw01.upload.maximum_data_size=81920 -cw01.upload.wait_for_upload_port=true -cw01.upload.erase_cmd= -cw01.serial.disableDTR=true -cw01.serial.disableRTS=true -cw01.build.mcu=esp8266 -cw01.build.core=esp8266 -cw01.build.spiffs_pagesize=256 -cw01.build.debug_port= -cw01.build.debug_level= -cw01.menu.CpuFrequency.80=80 MHz -cw01.menu.CpuFrequency.80.build.f_cpu=80000000L -cw01.menu.CpuFrequency.160=160 MHz -cw01.menu.CpuFrequency.160.build.f_cpu=160000000L -cw01.menu.VTable.flash=Flash -cw01.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -cw01.menu.VTable.heap=Heap -cw01.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -cw01.menu.VTable.iram=IRAM -cw01.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -cw01.upload.resetmethod=nodemcu -cw01.menu.CrystalFreq.26=26 MHz -cw01.menu.CrystalFreq.40=40 MHz -cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -cw01.build.flash_mode=qio -cw01.build.flash_freq=40 -cw01.menu.FlashSize.4M1M=4M (1M SPIFFS) -cw01.menu.FlashSize.4M1M.build.flash_size=4M -cw01.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -cw01.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -cw01.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -cw01.menu.FlashSize.4M1M.upload.maximum_size=1044464 -cw01.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -cw01.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -cw01.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -cw01.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -cw01.menu.FlashSize.4M2M=4M (2M SPIFFS) -cw01.menu.FlashSize.4M2M.build.flash_size=4M -cw01.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -cw01.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -cw01.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -cw01.menu.FlashSize.4M2M.upload.maximum_size=1044464 -cw01.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -cw01.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -cw01.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -cw01.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -cw01.menu.FlashSize.4M3M=4M (3M SPIFFS) -cw01.menu.FlashSize.4M3M.build.flash_size=4M -cw01.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -cw01.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -cw01.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -cw01.menu.FlashSize.4M3M.upload.maximum_size=1044464 -cw01.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -cw01.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -cw01.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -cw01.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -cw01.menu.LwIPVariant.v2mss536=v2 Lower Memory -cw01.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -cw01.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -cw01.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -cw01.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -cw01.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -cw01.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -cw01.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -cw01.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -cw01.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -cw01.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -cw01.menu.LwIPVariant.OpenSource=v1.4 Compile from source -cw01.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -cw01.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -cw01.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -cw01.menu.Debug.Disabled=Disabled -cw01.menu.Debug.Disabled.build.debug_port= -cw01.menu.Debug.Serial=Serial -cw01.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -cw01.menu.Debug.Serial1=Serial1 -cw01.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -cw01.menu.DebugLevel.None____=None -cw01.menu.DebugLevel.None____.build.debug_level= -cw01.menu.DebugLevel.SSL=SSL -cw01.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -cw01.menu.DebugLevel.TLS_MEM=TLS_MEM -cw01.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -cw01.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -cw01.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -cw01.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -cw01.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -cw01.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -cw01.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -cw01.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -cw01.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -cw01.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -cw01.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -cw01.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -cw01.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -cw01.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -cw01.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -cw01.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -cw01.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -cw01.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -cw01.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -cw01.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.DebugLevel.CORE=CORE -cw01.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -cw01.menu.DebugLevel.WIFI=WIFI -cw01.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -cw01.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -cw01.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -cw01.menu.DebugLevel.UPDATER=UPDATER -cw01.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -cw01.menu.DebugLevel.OTA=OTA -cw01.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -cw01.menu.DebugLevel.OOM=OOM -cw01.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -cw01.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -cw01.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -cw01.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -cw01.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -cw01.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -cw01.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -cw01.menu.FlashErase.none=Only Sketch -cw01.menu.FlashErase.none.upload.erase_cmd= -cw01.menu.FlashErase.sdk=Sketch + WiFi Settings -cw01.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -cw01.menu.FlashErase.all=All Flash Contents -cw01.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -cw01.menu.UploadSpeed.115200=115200 -cw01.menu.UploadSpeed.115200.upload.speed=115200 -cw01.menu.UploadSpeed.9600=9600 -cw01.menu.UploadSpeed.9600.upload.speed=9600 -cw01.menu.UploadSpeed.57600=57600 -cw01.menu.UploadSpeed.57600.upload.speed=57600 -cw01.menu.UploadSpeed.230400.linux=230400 -cw01.menu.UploadSpeed.230400.macosx=230400 -cw01.menu.UploadSpeed.230400.upload.speed=230400 -cw01.menu.UploadSpeed.256000.windows=256000 -cw01.menu.UploadSpeed.256000.upload.speed=256000 -cw01.menu.UploadSpeed.460800.linux=460800 -cw01.menu.UploadSpeed.460800.macosx=460800 -cw01.menu.UploadSpeed.460800.upload.speed=460800 -cw01.menu.UploadSpeed.512000.windows=512000 -cw01.menu.UploadSpeed.512000.upload.speed=512000 -cw01.menu.UploadSpeed.921600=921600 -cw01.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espresso_lite_v1.name=ESPresso Lite 1.0 -espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 -espresso_lite_v1.build.variant=espresso_lite_v1 -espresso_lite_v1.upload.tool=esptool -espresso_lite_v1.upload.maximum_data_size=81920 -espresso_lite_v1.upload.wait_for_upload_port=true -espresso_lite_v1.upload.erase_cmd= -espresso_lite_v1.serial.disableDTR=true -espresso_lite_v1.serial.disableRTS=true -espresso_lite_v1.build.mcu=esp8266 -espresso_lite_v1.build.core=esp8266 -espresso_lite_v1.build.spiffs_pagesize=256 -espresso_lite_v1.build.debug_port= -espresso_lite_v1.build.debug_level= -espresso_lite_v1.menu.CpuFrequency.80=80 MHz -espresso_lite_v1.menu.CpuFrequency.80.build.f_cpu=80000000L -espresso_lite_v1.menu.CpuFrequency.160=160 MHz -espresso_lite_v1.menu.CpuFrequency.160.build.f_cpu=160000000L -espresso_lite_v1.menu.VTable.flash=Flash -espresso_lite_v1.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espresso_lite_v1.menu.VTable.heap=Heap -espresso_lite_v1.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espresso_lite_v1.menu.VTable.iram=IRAM -espresso_lite_v1.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espresso_lite_v1.build.flash_mode=dio -espresso_lite_v1.build.flash_freq=40 -espresso_lite_v1.menu.FlashSize.4M1M=4M (1M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espresso_lite_v1.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.FlashSize.4M2M=4M (2M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M2M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espresso_lite_v1.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.FlashSize.4M2M.upload.maximum_size=1044464 -espresso_lite_v1.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -espresso_lite_v1.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.FlashSize.4M3M=4M (3M SPIFFS) -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_size=4M -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espresso_lite_v1.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.ResetMethod.ck=ck -espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v1.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v1.menu.LwIPVariant.v2mss536=v2 Lower Memory -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espresso_lite_v1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espresso_lite_v1.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espresso_lite_v1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espresso_lite_v1.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espresso_lite_v1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espresso_lite_v1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espresso_lite_v1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espresso_lite_v1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v1.menu.Debug.Disabled=Disabled -espresso_lite_v1.menu.Debug.Disabled.build.debug_port= -espresso_lite_v1.menu.Debug.Serial=Serial -espresso_lite_v1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v1.menu.Debug.Serial1=Serial1 -espresso_lite_v1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v1.menu.DebugLevel.None____=None -espresso_lite_v1.menu.DebugLevel.None____.build.debug_level= -espresso_lite_v1.menu.DebugLevel.SSL=SSL -espresso_lite_v1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v1.menu.DebugLevel.TLS_MEM=TLS_MEM -espresso_lite_v1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.DebugLevel.CORE=CORE -espresso_lite_v1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v1.menu.DebugLevel.WIFI=WIFI -espresso_lite_v1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v1.menu.DebugLevel.UPDATER=UPDATER -espresso_lite_v1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.DebugLevel.OTA=OTA -espresso_lite_v1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v1.menu.DebugLevel.OOM=OOM -espresso_lite_v1.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -espresso_lite_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v1.menu.FlashErase.none=Only Sketch -espresso_lite_v1.menu.FlashErase.none.upload.erase_cmd= -espresso_lite_v1.menu.FlashErase.sdk=Sketch + WiFi Settings -espresso_lite_v1.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espresso_lite_v1.menu.FlashErase.all=All Flash Contents -espresso_lite_v1.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espresso_lite_v1.menu.UploadSpeed.115200=115200 -espresso_lite_v1.menu.UploadSpeed.115200.upload.speed=115200 -espresso_lite_v1.menu.UploadSpeed.9600=9600 -espresso_lite_v1.menu.UploadSpeed.9600.upload.speed=9600 -espresso_lite_v1.menu.UploadSpeed.57600=57600 -espresso_lite_v1.menu.UploadSpeed.57600.upload.speed=57600 -espresso_lite_v1.menu.UploadSpeed.230400.linux=230400 -espresso_lite_v1.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v1.menu.UploadSpeed.230400.upload.speed=230400 -espresso_lite_v1.menu.UploadSpeed.256000.windows=256000 -espresso_lite_v1.menu.UploadSpeed.256000.upload.speed=256000 -espresso_lite_v1.menu.UploadSpeed.460800.linux=460800 -espresso_lite_v1.menu.UploadSpeed.460800.macosx=460800 -espresso_lite_v1.menu.UploadSpeed.460800.upload.speed=460800 -espresso_lite_v1.menu.UploadSpeed.512000.windows=512000 -espresso_lite_v1.menu.UploadSpeed.512000.upload.speed=512000 -espresso_lite_v1.menu.UploadSpeed.921600=921600 -espresso_lite_v1.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espresso_lite_v2.name=ESPresso Lite 2.0 -espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 -espresso_lite_v2.build.variant=espresso_lite_v2 -espresso_lite_v2.upload.tool=esptool -espresso_lite_v2.upload.maximum_data_size=81920 -espresso_lite_v2.upload.wait_for_upload_port=true -espresso_lite_v2.upload.erase_cmd= -espresso_lite_v2.serial.disableDTR=true -espresso_lite_v2.serial.disableRTS=true -espresso_lite_v2.build.mcu=esp8266 -espresso_lite_v2.build.core=esp8266 -espresso_lite_v2.build.spiffs_pagesize=256 -espresso_lite_v2.build.debug_port= -espresso_lite_v2.build.debug_level= -espresso_lite_v2.menu.CpuFrequency.80=80 MHz -espresso_lite_v2.menu.CpuFrequency.80.build.f_cpu=80000000L -espresso_lite_v2.menu.CpuFrequency.160=160 MHz -espresso_lite_v2.menu.CpuFrequency.160.build.f_cpu=160000000L -espresso_lite_v2.menu.VTable.flash=Flash -espresso_lite_v2.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espresso_lite_v2.menu.VTable.heap=Heap -espresso_lite_v2.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espresso_lite_v2.menu.VTable.iram=IRAM -espresso_lite_v2.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espresso_lite_v2.build.flash_mode=dio -espresso_lite_v2.build.flash_freq=40 -espresso_lite_v2.menu.FlashSize.4M1M=4M (1M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espresso_lite_v2.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.FlashSize.4M2M=4M (2M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M2M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espresso_lite_v2.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.FlashSize.4M2M.upload.maximum_size=1044464 -espresso_lite_v2.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -espresso_lite_v2.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.FlashSize.4M3M=4M (3M SPIFFS) -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_size=4M -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espresso_lite_v2.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espresso_lite_v2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.ResetMethod.ck=ck -espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=ck -espresso_lite_v2.menu.ResetMethod.nodemcu=nodemcu -espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espresso_lite_v2.menu.LwIPVariant.v2mss536=v2 Lower Memory -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espresso_lite_v2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espresso_lite_v2.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espresso_lite_v2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espresso_lite_v2.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espresso_lite_v2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espresso_lite_v2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espresso_lite_v2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espresso_lite_v2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v2.menu.Debug.Disabled=Disabled -espresso_lite_v2.menu.Debug.Disabled.build.debug_port= -espresso_lite_v2.menu.Debug.Serial=Serial -espresso_lite_v2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v2.menu.Debug.Serial1=Serial1 -espresso_lite_v2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v2.menu.DebugLevel.None____=None -espresso_lite_v2.menu.DebugLevel.None____.build.debug_level= -espresso_lite_v2.menu.DebugLevel.SSL=SSL -espresso_lite_v2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v2.menu.DebugLevel.TLS_MEM=TLS_MEM -espresso_lite_v2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.DebugLevel.CORE=CORE -espresso_lite_v2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v2.menu.DebugLevel.WIFI=WIFI -espresso_lite_v2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v2.menu.DebugLevel.UPDATER=UPDATER -espresso_lite_v2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.DebugLevel.OTA=OTA -espresso_lite_v2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v2.menu.DebugLevel.OOM=OOM -espresso_lite_v2.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -espresso_lite_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espresso_lite_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espresso_lite_v2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v2.menu.FlashErase.none=Only Sketch -espresso_lite_v2.menu.FlashErase.none.upload.erase_cmd= -espresso_lite_v2.menu.FlashErase.sdk=Sketch + WiFi Settings -espresso_lite_v2.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espresso_lite_v2.menu.FlashErase.all=All Flash Contents -espresso_lite_v2.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espresso_lite_v2.menu.UploadSpeed.115200=115200 -espresso_lite_v2.menu.UploadSpeed.115200.upload.speed=115200 -espresso_lite_v2.menu.UploadSpeed.9600=9600 -espresso_lite_v2.menu.UploadSpeed.9600.upload.speed=9600 -espresso_lite_v2.menu.UploadSpeed.57600=57600 -espresso_lite_v2.menu.UploadSpeed.57600.upload.speed=57600 -espresso_lite_v2.menu.UploadSpeed.230400.linux=230400 -espresso_lite_v2.menu.UploadSpeed.230400.macosx=230400 -espresso_lite_v2.menu.UploadSpeed.230400.upload.speed=230400 -espresso_lite_v2.menu.UploadSpeed.256000.windows=256000 -espresso_lite_v2.menu.UploadSpeed.256000.upload.speed=256000 -espresso_lite_v2.menu.UploadSpeed.460800.linux=460800 -espresso_lite_v2.menu.UploadSpeed.460800.macosx=460800 -espresso_lite_v2.menu.UploadSpeed.460800.upload.speed=460800 -espresso_lite_v2.menu.UploadSpeed.512000.windows=512000 -espresso_lite_v2.menu.UploadSpeed.512000.upload.speed=512000 -espresso_lite_v2.menu.UploadSpeed.921600=921600 -espresso_lite_v2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -phoenix_v1.name=Phoenix 1.0 -phoenix_v1.build.board=ESP8266_PHOENIX_V1 -phoenix_v1.build.variant=phoenix_v1 -phoenix_v1.upload.tool=esptool -phoenix_v1.upload.maximum_data_size=81920 -phoenix_v1.upload.wait_for_upload_port=true -phoenix_v1.upload.erase_cmd= -phoenix_v1.serial.disableDTR=true -phoenix_v1.serial.disableRTS=true -phoenix_v1.build.mcu=esp8266 -phoenix_v1.build.core=esp8266 -phoenix_v1.build.spiffs_pagesize=256 -phoenix_v1.build.debug_port= -phoenix_v1.build.debug_level= -phoenix_v1.menu.CpuFrequency.80=80 MHz -phoenix_v1.menu.CpuFrequency.80.build.f_cpu=80000000L -phoenix_v1.menu.CpuFrequency.160=160 MHz -phoenix_v1.menu.CpuFrequency.160.build.f_cpu=160000000L -phoenix_v1.menu.VTable.flash=Flash -phoenix_v1.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -phoenix_v1.menu.VTable.heap=Heap -phoenix_v1.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -phoenix_v1.menu.VTable.iram=IRAM -phoenix_v1.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -phoenix_v1.build.flash_mode=dio -phoenix_v1.build.flash_freq=40 -phoenix_v1.menu.FlashSize.4M1M=4M (1M SPIFFS) -phoenix_v1.menu.FlashSize.4M1M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -phoenix_v1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -phoenix_v1.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -phoenix_v1.menu.FlashSize.4M2M=4M (2M SPIFFS) -phoenix_v1.menu.FlashSize.4M2M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -phoenix_v1.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -phoenix_v1.menu.FlashSize.4M2M.upload.maximum_size=1044464 -phoenix_v1.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -phoenix_v1.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -phoenix_v1.menu.FlashSize.4M3M=4M (3M SPIFFS) -phoenix_v1.menu.FlashSize.4M3M.build.flash_size=4M -phoenix_v1.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -phoenix_v1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -phoenix_v1.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -phoenix_v1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -phoenix_v1.menu.ResetMethod.ck=ck -phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v1.menu.ResetMethod.nodemcu=nodemcu -phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v1.menu.LwIPVariant.v2mss536=v2 Lower Memory -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -phoenix_v1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -phoenix_v1.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -phoenix_v1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -phoenix_v1.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -phoenix_v1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -phoenix_v1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.LwIPVariant.OpenSource=v1.4 Compile from source -phoenix_v1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -phoenix_v1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v1.menu.Debug.Disabled=Disabled -phoenix_v1.menu.Debug.Disabled.build.debug_port= -phoenix_v1.menu.Debug.Serial=Serial -phoenix_v1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v1.menu.Debug.Serial1=Serial1 -phoenix_v1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v1.menu.DebugLevel.None____=None -phoenix_v1.menu.DebugLevel.None____.build.debug_level= -phoenix_v1.menu.DebugLevel.SSL=SSL -phoenix_v1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v1.menu.DebugLevel.TLS_MEM=TLS_MEM -phoenix_v1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -phoenix_v1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.DebugLevel.CORE=CORE -phoenix_v1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v1.menu.DebugLevel.WIFI=WIFI -phoenix_v1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -phoenix_v1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v1.menu.DebugLevel.UPDATER=UPDATER -phoenix_v1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v1.menu.DebugLevel.OTA=OTA -phoenix_v1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v1.menu.DebugLevel.OOM=OOM -phoenix_v1.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -phoenix_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v1.menu.FlashErase.none=Only Sketch -phoenix_v1.menu.FlashErase.none.upload.erase_cmd= -phoenix_v1.menu.FlashErase.sdk=Sketch + WiFi Settings -phoenix_v1.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -phoenix_v1.menu.FlashErase.all=All Flash Contents -phoenix_v1.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -phoenix_v1.menu.UploadSpeed.115200=115200 -phoenix_v1.menu.UploadSpeed.115200.upload.speed=115200 -phoenix_v1.menu.UploadSpeed.9600=9600 -phoenix_v1.menu.UploadSpeed.9600.upload.speed=9600 -phoenix_v1.menu.UploadSpeed.57600=57600 -phoenix_v1.menu.UploadSpeed.57600.upload.speed=57600 -phoenix_v1.menu.UploadSpeed.230400.linux=230400 -phoenix_v1.menu.UploadSpeed.230400.macosx=230400 -phoenix_v1.menu.UploadSpeed.230400.upload.speed=230400 -phoenix_v1.menu.UploadSpeed.256000.windows=256000 -phoenix_v1.menu.UploadSpeed.256000.upload.speed=256000 -phoenix_v1.menu.UploadSpeed.460800.linux=460800 -phoenix_v1.menu.UploadSpeed.460800.macosx=460800 -phoenix_v1.menu.UploadSpeed.460800.upload.speed=460800 -phoenix_v1.menu.UploadSpeed.512000.windows=512000 -phoenix_v1.menu.UploadSpeed.512000.upload.speed=512000 -phoenix_v1.menu.UploadSpeed.921600=921600 -phoenix_v1.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -phoenix_v2.name=Phoenix 2.0 -phoenix_v2.build.board=ESP8266_PHOENIX_V2 -phoenix_v2.build.variant=phoenix_v2 -phoenix_v2.upload.tool=esptool -phoenix_v2.upload.maximum_data_size=81920 -phoenix_v2.upload.wait_for_upload_port=true -phoenix_v2.upload.erase_cmd= -phoenix_v2.serial.disableDTR=true -phoenix_v2.serial.disableRTS=true -phoenix_v2.build.mcu=esp8266 -phoenix_v2.build.core=esp8266 -phoenix_v2.build.spiffs_pagesize=256 -phoenix_v2.build.debug_port= -phoenix_v2.build.debug_level= -phoenix_v2.menu.CpuFrequency.80=80 MHz -phoenix_v2.menu.CpuFrequency.80.build.f_cpu=80000000L -phoenix_v2.menu.CpuFrequency.160=160 MHz -phoenix_v2.menu.CpuFrequency.160.build.f_cpu=160000000L -phoenix_v2.menu.VTable.flash=Flash -phoenix_v2.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -phoenix_v2.menu.VTable.heap=Heap -phoenix_v2.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -phoenix_v2.menu.VTable.iram=IRAM -phoenix_v2.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -phoenix_v2.build.flash_mode=dio -phoenix_v2.build.flash_freq=40 -phoenix_v2.menu.FlashSize.4M1M=4M (1M SPIFFS) -phoenix_v2.menu.FlashSize.4M1M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -phoenix_v2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -phoenix_v2.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -phoenix_v2.menu.FlashSize.4M2M=4M (2M SPIFFS) -phoenix_v2.menu.FlashSize.4M2M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -phoenix_v2.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -phoenix_v2.menu.FlashSize.4M2M.upload.maximum_size=1044464 -phoenix_v2.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -phoenix_v2.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -phoenix_v2.menu.FlashSize.4M3M=4M (3M SPIFFS) -phoenix_v2.menu.FlashSize.4M3M.build.flash_size=4M -phoenix_v2.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -phoenix_v2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -phoenix_v2.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -phoenix_v2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -phoenix_v2.menu.ResetMethod.ck=ck -phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=ck -phoenix_v2.menu.ResetMethod.nodemcu=nodemcu -phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -phoenix_v2.menu.LwIPVariant.v2mss536=v2 Lower Memory -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -phoenix_v2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -phoenix_v2.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -phoenix_v2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -phoenix_v2.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -phoenix_v2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -phoenix_v2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.LwIPVariant.OpenSource=v1.4 Compile from source -phoenix_v2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -phoenix_v2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v2.menu.Debug.Disabled=Disabled -phoenix_v2.menu.Debug.Disabled.build.debug_port= -phoenix_v2.menu.Debug.Serial=Serial -phoenix_v2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v2.menu.Debug.Serial1=Serial1 -phoenix_v2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v2.menu.DebugLevel.None____=None -phoenix_v2.menu.DebugLevel.None____.build.debug_level= -phoenix_v2.menu.DebugLevel.SSL=SSL -phoenix_v2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v2.menu.DebugLevel.TLS_MEM=TLS_MEM -phoenix_v2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -phoenix_v2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.DebugLevel.CORE=CORE -phoenix_v2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v2.menu.DebugLevel.WIFI=WIFI -phoenix_v2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -phoenix_v2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v2.menu.DebugLevel.UPDATER=UPDATER -phoenix_v2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v2.menu.DebugLevel.OTA=OTA -phoenix_v2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v2.menu.DebugLevel.OOM=OOM -phoenix_v2.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -phoenix_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -phoenix_v2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -phoenix_v2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v2.menu.FlashErase.none=Only Sketch -phoenix_v2.menu.FlashErase.none.upload.erase_cmd= -phoenix_v2.menu.FlashErase.sdk=Sketch + WiFi Settings -phoenix_v2.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -phoenix_v2.menu.FlashErase.all=All Flash Contents -phoenix_v2.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -phoenix_v2.menu.UploadSpeed.115200=115200 -phoenix_v2.menu.UploadSpeed.115200.upload.speed=115200 -phoenix_v2.menu.UploadSpeed.9600=9600 -phoenix_v2.menu.UploadSpeed.9600.upload.speed=9600 -phoenix_v2.menu.UploadSpeed.57600=57600 -phoenix_v2.menu.UploadSpeed.57600.upload.speed=57600 -phoenix_v2.menu.UploadSpeed.230400.linux=230400 -phoenix_v2.menu.UploadSpeed.230400.macosx=230400 -phoenix_v2.menu.UploadSpeed.230400.upload.speed=230400 -phoenix_v2.menu.UploadSpeed.256000.windows=256000 -phoenix_v2.menu.UploadSpeed.256000.upload.speed=256000 -phoenix_v2.menu.UploadSpeed.460800.linux=460800 -phoenix_v2.menu.UploadSpeed.460800.macosx=460800 -phoenix_v2.menu.UploadSpeed.460800.upload.speed=460800 -phoenix_v2.menu.UploadSpeed.512000.windows=512000 -phoenix_v2.menu.UploadSpeed.512000.upload.speed=512000 -phoenix_v2.menu.UploadSpeed.921600=921600 -phoenix_v2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -nodemcu.name=NodeMCU 0.9 (ESP-12 Module) -nodemcu.build.board=ESP8266_NODEMCU -nodemcu.build.variant=nodemcu -nodemcu.upload.tool=esptool -nodemcu.upload.maximum_data_size=81920 -nodemcu.upload.wait_for_upload_port=true -nodemcu.upload.erase_cmd= -nodemcu.serial.disableDTR=true -nodemcu.serial.disableRTS=true -nodemcu.build.mcu=esp8266 -nodemcu.build.core=esp8266 -nodemcu.build.spiffs_pagesize=256 -nodemcu.build.debug_port= -nodemcu.build.debug_level= -nodemcu.menu.CpuFrequency.80=80 MHz -nodemcu.menu.CpuFrequency.80.build.f_cpu=80000000L -nodemcu.menu.CpuFrequency.160=160 MHz -nodemcu.menu.CpuFrequency.160.build.f_cpu=160000000L -nodemcu.menu.VTable.flash=Flash -nodemcu.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -nodemcu.menu.VTable.heap=Heap -nodemcu.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -nodemcu.menu.VTable.iram=IRAM -nodemcu.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -nodemcu.upload.resetmethod=nodemcu -nodemcu.build.flash_mode=qio -nodemcu.build.flash_freq=40 -nodemcu.menu.FlashSize.4M1M=4M (1M SPIFFS) -nodemcu.menu.FlashSize.4M1M.build.flash_size=4M -nodemcu.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -nodemcu.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcu.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -nodemcu.menu.FlashSize.4M1M.upload.maximum_size=1044464 -nodemcu.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -nodemcu.menu.FlashSize.4M2M=4M (2M SPIFFS) -nodemcu.menu.FlashSize.4M2M.build.flash_size=4M -nodemcu.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -nodemcu.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -nodemcu.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -nodemcu.menu.FlashSize.4M2M.upload.maximum_size=1044464 -nodemcu.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -nodemcu.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -nodemcu.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -nodemcu.menu.FlashSize.4M3M=4M (3M SPIFFS) -nodemcu.menu.FlashSize.4M3M.build.flash_size=4M -nodemcu.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -nodemcu.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -nodemcu.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -nodemcu.menu.FlashSize.4M3M.upload.maximum_size=1044464 -nodemcu.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -nodemcu.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -nodemcu.menu.LwIPVariant.v2mss536=v2 Lower Memory -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -nodemcu.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -nodemcu.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -nodemcu.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -nodemcu.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -nodemcu.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -nodemcu.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.LwIPVariant.OpenSource=v1.4 Compile from source -nodemcu.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -nodemcu.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcu.menu.Debug.Disabled=Disabled -nodemcu.menu.Debug.Disabled.build.debug_port= -nodemcu.menu.Debug.Serial=Serial -nodemcu.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcu.menu.Debug.Serial1=Serial1 -nodemcu.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcu.menu.DebugLevel.None____=None -nodemcu.menu.DebugLevel.None____.build.debug_level= -nodemcu.menu.DebugLevel.SSL=SSL -nodemcu.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcu.menu.DebugLevel.TLS_MEM=TLS_MEM -nodemcu.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcu.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -nodemcu.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -nodemcu.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcu.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.DebugLevel.CORE=CORE -nodemcu.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcu.menu.DebugLevel.WIFI=WIFI -nodemcu.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcu.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -nodemcu.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcu.menu.DebugLevel.UPDATER=UPDATER -nodemcu.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcu.menu.DebugLevel.OTA=OTA -nodemcu.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcu.menu.DebugLevel.OOM=OOM -nodemcu.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -nodemcu.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcu.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcu.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcu.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcu.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcu.menu.FlashErase.none=Only Sketch -nodemcu.menu.FlashErase.none.upload.erase_cmd= -nodemcu.menu.FlashErase.sdk=Sketch + WiFi Settings -nodemcu.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -nodemcu.menu.FlashErase.all=All Flash Contents -nodemcu.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -nodemcu.menu.UploadSpeed.115200=115200 -nodemcu.menu.UploadSpeed.115200.upload.speed=115200 -nodemcu.menu.UploadSpeed.9600=9600 -nodemcu.menu.UploadSpeed.9600.upload.speed=9600 -nodemcu.menu.UploadSpeed.57600=57600 -nodemcu.menu.UploadSpeed.57600.upload.speed=57600 -nodemcu.menu.UploadSpeed.230400.linux=230400 -nodemcu.menu.UploadSpeed.230400.macosx=230400 -nodemcu.menu.UploadSpeed.230400.upload.speed=230400 -nodemcu.menu.UploadSpeed.256000.windows=256000 -nodemcu.menu.UploadSpeed.256000.upload.speed=256000 -nodemcu.menu.UploadSpeed.460800.linux=460800 -nodemcu.menu.UploadSpeed.460800.macosx=460800 -nodemcu.menu.UploadSpeed.460800.upload.speed=460800 -nodemcu.menu.UploadSpeed.512000.windows=512000 -nodemcu.menu.UploadSpeed.512000.upload.speed=512000 -nodemcu.menu.UploadSpeed.921600=921600 -nodemcu.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) -nodemcuv2.build.board=ESP8266_NODEMCU -nodemcuv2.build.variant=nodemcu -nodemcuv2.upload.tool=esptool -nodemcuv2.upload.maximum_data_size=81920 -nodemcuv2.upload.wait_for_upload_port=true -nodemcuv2.upload.erase_cmd= -nodemcuv2.serial.disableDTR=true -nodemcuv2.serial.disableRTS=true -nodemcuv2.build.mcu=esp8266 -nodemcuv2.build.core=esp8266 -nodemcuv2.build.spiffs_pagesize=256 -nodemcuv2.build.debug_port= -nodemcuv2.build.debug_level= -nodemcuv2.menu.CpuFrequency.80=80 MHz -nodemcuv2.menu.CpuFrequency.80.build.f_cpu=80000000L -nodemcuv2.menu.CpuFrequency.160=160 MHz -nodemcuv2.menu.CpuFrequency.160.build.f_cpu=160000000L -nodemcuv2.menu.VTable.flash=Flash -nodemcuv2.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -nodemcuv2.menu.VTable.heap=Heap -nodemcuv2.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -nodemcuv2.menu.VTable.iram=IRAM -nodemcuv2.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -nodemcuv2.upload.resetmethod=nodemcu -nodemcuv2.build.flash_mode=dio -nodemcuv2.build.flash_freq=40 -nodemcuv2.menu.FlashSize.4M1M=4M (1M SPIFFS) -nodemcuv2.menu.FlashSize.4M1M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -nodemcuv2.menu.FlashSize.4M1M.upload.maximum_size=1044464 -nodemcuv2.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -nodemcuv2.menu.FlashSize.4M2M=4M (2M SPIFFS) -nodemcuv2.menu.FlashSize.4M2M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -nodemcuv2.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -nodemcuv2.menu.FlashSize.4M2M.upload.maximum_size=1044464 -nodemcuv2.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -nodemcuv2.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -nodemcuv2.menu.FlashSize.4M3M=4M (3M SPIFFS) -nodemcuv2.menu.FlashSize.4M3M.build.flash_size=4M -nodemcuv2.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -nodemcuv2.menu.FlashSize.4M3M.upload.maximum_size=1044464 -nodemcuv2.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -nodemcuv2.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -nodemcuv2.menu.LwIPVariant.v2mss536=v2 Lower Memory -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -nodemcuv2.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -nodemcuv2.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -nodemcuv2.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -nodemcuv2.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -nodemcuv2.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -nodemcuv2.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.LwIPVariant.OpenSource=v1.4 Compile from source -nodemcuv2.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -nodemcuv2.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcuv2.menu.Debug.Disabled=Disabled -nodemcuv2.menu.Debug.Disabled.build.debug_port= -nodemcuv2.menu.Debug.Serial=Serial -nodemcuv2.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcuv2.menu.Debug.Serial1=Serial1 -nodemcuv2.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcuv2.menu.DebugLevel.None____=None -nodemcuv2.menu.DebugLevel.None____.build.debug_level= -nodemcuv2.menu.DebugLevel.SSL=SSL -nodemcuv2.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcuv2.menu.DebugLevel.TLS_MEM=TLS_MEM -nodemcuv2.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -nodemcuv2.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -nodemcuv2.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.DebugLevel.CORE=CORE -nodemcuv2.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcuv2.menu.DebugLevel.WIFI=WIFI -nodemcuv2.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcuv2.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -nodemcuv2.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcuv2.menu.DebugLevel.UPDATER=UPDATER -nodemcuv2.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcuv2.menu.DebugLevel.OTA=OTA -nodemcuv2.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcuv2.menu.DebugLevel.OOM=OOM -nodemcuv2.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -nodemcuv2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcuv2.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -nodemcuv2.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -nodemcuv2.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcuv2.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcuv2.menu.FlashErase.none=Only Sketch -nodemcuv2.menu.FlashErase.none.upload.erase_cmd= -nodemcuv2.menu.FlashErase.sdk=Sketch + WiFi Settings -nodemcuv2.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -nodemcuv2.menu.FlashErase.all=All Flash Contents -nodemcuv2.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -nodemcuv2.menu.UploadSpeed.115200=115200 -nodemcuv2.menu.UploadSpeed.115200.upload.speed=115200 -nodemcuv2.menu.UploadSpeed.9600=9600 -nodemcuv2.menu.UploadSpeed.9600.upload.speed=9600 -nodemcuv2.menu.UploadSpeed.57600=57600 -nodemcuv2.menu.UploadSpeed.57600.upload.speed=57600 -nodemcuv2.menu.UploadSpeed.230400.linux=230400 -nodemcuv2.menu.UploadSpeed.230400.macosx=230400 -nodemcuv2.menu.UploadSpeed.230400.upload.speed=230400 -nodemcuv2.menu.UploadSpeed.256000.windows=256000 -nodemcuv2.menu.UploadSpeed.256000.upload.speed=256000 -nodemcuv2.menu.UploadSpeed.460800.linux=460800 -nodemcuv2.menu.UploadSpeed.460800.macosx=460800 -nodemcuv2.menu.UploadSpeed.460800.upload.speed=460800 -nodemcuv2.menu.UploadSpeed.512000.windows=512000 -nodemcuv2.menu.UploadSpeed.512000.upload.speed=512000 -nodemcuv2.menu.UploadSpeed.921600=921600 -nodemcuv2.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) -modwifi.build.board=MOD_WIFI_ESP8266 -modwifi.build.variant=modwifi -modwifi.upload.tool=esptool -modwifi.upload.maximum_data_size=81920 -modwifi.upload.wait_for_upload_port=true -modwifi.upload.erase_cmd= -modwifi.serial.disableDTR=true -modwifi.serial.disableRTS=true -modwifi.build.mcu=esp8266 -modwifi.build.core=esp8266 -modwifi.build.spiffs_pagesize=256 -modwifi.build.debug_port= -modwifi.build.debug_level= -modwifi.menu.CpuFrequency.80=80 MHz -modwifi.menu.CpuFrequency.80.build.f_cpu=80000000L -modwifi.menu.CpuFrequency.160=160 MHz -modwifi.menu.CpuFrequency.160.build.f_cpu=160000000L -modwifi.menu.VTable.flash=Flash -modwifi.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -modwifi.menu.VTable.heap=Heap -modwifi.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -modwifi.menu.VTable.iram=IRAM -modwifi.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -modwifi.upload.resetmethod=ck -modwifi.build.flash_mode=qio -modwifi.build.flash_freq=40 -modwifi.menu.FlashSize.2M=2M (1M SPIFFS) -modwifi.menu.FlashSize.2M.build.flash_size=2M -modwifi.menu.FlashSize.2M.build.flash_size_bytes=0x200000 -modwifi.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -modwifi.menu.FlashSize.2M.build.spiffs_pagesize=256 -modwifi.menu.FlashSize.2M.upload.maximum_size=1044464 -modwifi.menu.FlashSize.2M.build.rfcal_addr=0x1FC000 -modwifi.menu.FlashSize.2M.build.spiffs_start=0x100000 -modwifi.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -modwifi.menu.FlashSize.2M.build.spiffs_blocksize=8192 -modwifi.menu.LwIPVariant.v2mss536=v2 Lower Memory -modwifi.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -modwifi.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -modwifi.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -modwifi.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -modwifi.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -modwifi.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -modwifi.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -modwifi.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.LwIPVariant.OpenSource=v1.4 Compile from source -modwifi.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -modwifi.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -modwifi.menu.Debug.Disabled=Disabled -modwifi.menu.Debug.Disabled.build.debug_port= -modwifi.menu.Debug.Serial=Serial -modwifi.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -modwifi.menu.Debug.Serial1=Serial1 -modwifi.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -modwifi.menu.DebugLevel.None____=None -modwifi.menu.DebugLevel.None____.build.debug_level= -modwifi.menu.DebugLevel.SSL=SSL -modwifi.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -modwifi.menu.DebugLevel.TLS_MEM=TLS_MEM -modwifi.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -modwifi.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -modwifi.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -modwifi.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -modwifi.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -modwifi.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.DebugLevel.CORE=CORE -modwifi.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -modwifi.menu.DebugLevel.WIFI=WIFI -modwifi.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -modwifi.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -modwifi.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -modwifi.menu.DebugLevel.UPDATER=UPDATER -modwifi.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -modwifi.menu.DebugLevel.OTA=OTA -modwifi.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -modwifi.menu.DebugLevel.OOM=OOM -modwifi.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -modwifi.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -modwifi.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -modwifi.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -modwifi.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -modwifi.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -modwifi.menu.FlashErase.none=Only Sketch -modwifi.menu.FlashErase.none.upload.erase_cmd= -modwifi.menu.FlashErase.sdk=Sketch + WiFi Settings -modwifi.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -modwifi.menu.FlashErase.all=All Flash Contents -modwifi.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -modwifi.menu.UploadSpeed.115200=115200 -modwifi.menu.UploadSpeed.115200.upload.speed=115200 -modwifi.menu.UploadSpeed.9600=9600 -modwifi.menu.UploadSpeed.9600.upload.speed=9600 -modwifi.menu.UploadSpeed.57600=57600 -modwifi.menu.UploadSpeed.57600.upload.speed=57600 -modwifi.menu.UploadSpeed.230400.linux=230400 -modwifi.menu.UploadSpeed.230400.macosx=230400 -modwifi.menu.UploadSpeed.230400.upload.speed=230400 -modwifi.menu.UploadSpeed.256000.windows=256000 -modwifi.menu.UploadSpeed.256000.upload.speed=256000 -modwifi.menu.UploadSpeed.460800.linux=460800 -modwifi.menu.UploadSpeed.460800.macosx=460800 -modwifi.menu.UploadSpeed.460800.upload.speed=460800 -modwifi.menu.UploadSpeed.512000.windows=512000 -modwifi.menu.UploadSpeed.512000.upload.speed=512000 -modwifi.menu.UploadSpeed.921600=921600 -modwifi.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -thing.name=SparkFun ESP8266 Thing -thing.build.board=ESP8266_THING -thing.build.variant=thing -thing.upload.tool=esptool -thing.upload.maximum_data_size=81920 -thing.upload.wait_for_upload_port=true -thing.upload.erase_cmd= -thing.serial.disableDTR=true -thing.serial.disableRTS=true -thing.build.mcu=esp8266 -thing.build.core=esp8266 -thing.build.spiffs_pagesize=256 -thing.build.debug_port= -thing.build.debug_level= -thing.menu.CpuFrequency.80=80 MHz -thing.menu.CpuFrequency.80.build.f_cpu=80000000L -thing.menu.CpuFrequency.160=160 MHz -thing.menu.CpuFrequency.160.build.f_cpu=160000000L -thing.menu.VTable.flash=Flash -thing.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -thing.menu.VTable.heap=Heap -thing.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -thing.menu.VTable.iram=IRAM -thing.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -thing.upload.resetmethod=ck -thing.build.flash_mode=qio -thing.build.flash_freq=40 -thing.menu.FlashSize.512K0=512K (no SPIFFS) -thing.menu.FlashSize.512K0.build.flash_size=512K -thing.menu.FlashSize.512K0.build.flash_size_bytes=0x80000 -thing.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -thing.menu.FlashSize.512K0.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K0.upload.maximum_size=499696 -thing.menu.FlashSize.512K0.build.rfcal_addr=0x7C000 -thing.menu.FlashSize.512K32=512K (32K SPIFFS) -thing.menu.FlashSize.512K32.build.flash_size=512K -thing.menu.FlashSize.512K32.build.flash_size_bytes=0x80000 -thing.menu.FlashSize.512K32.build.flash_ld=eagle.flash.512k32.ld -thing.menu.FlashSize.512K32.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K32.upload.maximum_size=466928 -thing.menu.FlashSize.512K32.build.rfcal_addr=0x7C000 -thing.menu.FlashSize.512K32.build.spiffs_start=0x73000 -thing.menu.FlashSize.512K32.build.spiffs_end=0x7B000 -thing.menu.FlashSize.512K32.build.spiffs_blocksize=4096 -thing.menu.FlashSize.512K64=512K (64K SPIFFS) -thing.menu.FlashSize.512K64.build.flash_size=512K -thing.menu.FlashSize.512K64.build.flash_size_bytes=0x80000 -thing.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -thing.menu.FlashSize.512K64.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K64.upload.maximum_size=434160 -thing.menu.FlashSize.512K64.build.rfcal_addr=0x7C000 -thing.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -thing.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -thing.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -thing.menu.FlashSize.512K128=512K (128K SPIFFS) -thing.menu.FlashSize.512K128.build.flash_size=512K -thing.menu.FlashSize.512K128.build.flash_size_bytes=0x80000 -thing.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -thing.menu.FlashSize.512K128.build.spiffs_pagesize=256 -thing.menu.FlashSize.512K128.upload.maximum_size=368624 -thing.menu.FlashSize.512K128.build.rfcal_addr=0x7C000 -thing.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -thing.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -thing.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -thing.menu.LwIPVariant.v2mss536=v2 Lower Memory -thing.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -thing.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -thing.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -thing.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -thing.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -thing.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -thing.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -thing.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -thing.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -thing.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.LwIPVariant.OpenSource=v1.4 Compile from source -thing.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -thing.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thing.menu.Debug.Disabled=Disabled -thing.menu.Debug.Disabled.build.debug_port= -thing.menu.Debug.Serial=Serial -thing.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thing.menu.Debug.Serial1=Serial1 -thing.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thing.menu.DebugLevel.None____=None -thing.menu.DebugLevel.None____.build.debug_level= -thing.menu.DebugLevel.SSL=SSL -thing.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -thing.menu.DebugLevel.TLS_MEM=TLS_MEM -thing.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thing.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -thing.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -thing.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -thing.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thing.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thing.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.DebugLevel.CORE=CORE -thing.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -thing.menu.DebugLevel.WIFI=WIFI -thing.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thing.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -thing.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thing.menu.DebugLevel.UPDATER=UPDATER -thing.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thing.menu.DebugLevel.OTA=OTA -thing.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -thing.menu.DebugLevel.OOM=OOM -thing.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -thing.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thing.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thing.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thing.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -thing.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thing.menu.FlashErase.none=Only Sketch -thing.menu.FlashErase.none.upload.erase_cmd= -thing.menu.FlashErase.sdk=Sketch + WiFi Settings -thing.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -thing.menu.FlashErase.all=All Flash Contents -thing.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -thing.menu.UploadSpeed.115200=115200 -thing.menu.UploadSpeed.115200.upload.speed=115200 -thing.menu.UploadSpeed.9600=9600 -thing.menu.UploadSpeed.9600.upload.speed=9600 -thing.menu.UploadSpeed.57600=57600 -thing.menu.UploadSpeed.57600.upload.speed=57600 -thing.menu.UploadSpeed.230400.linux=230400 -thing.menu.UploadSpeed.230400.macosx=230400 -thing.menu.UploadSpeed.230400.upload.speed=230400 -thing.menu.UploadSpeed.256000.windows=256000 -thing.menu.UploadSpeed.256000.upload.speed=256000 -thing.menu.UploadSpeed.460800.linux=460800 -thing.menu.UploadSpeed.460800.macosx=460800 -thing.menu.UploadSpeed.460800.upload.speed=460800 -thing.menu.UploadSpeed.512000.windows=512000 -thing.menu.UploadSpeed.512000.upload.speed=512000 -thing.menu.UploadSpeed.921600=921600 -thing.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -thingdev.name=SparkFun ESP8266 Thing Dev -thingdev.build.board=ESP8266_THING_DEV -thingdev.build.variant=thing -thingdev.upload.tool=esptool -thingdev.upload.maximum_data_size=81920 -thingdev.upload.wait_for_upload_port=true -thingdev.upload.erase_cmd= -thingdev.serial.disableDTR=true -thingdev.serial.disableRTS=true -thingdev.build.mcu=esp8266 -thingdev.build.core=esp8266 -thingdev.build.spiffs_pagesize=256 -thingdev.build.debug_port= -thingdev.build.debug_level= -thingdev.menu.CpuFrequency.80=80 MHz -thingdev.menu.CpuFrequency.80.build.f_cpu=80000000L -thingdev.menu.CpuFrequency.160=160 MHz -thingdev.menu.CpuFrequency.160.build.f_cpu=160000000L -thingdev.menu.VTable.flash=Flash -thingdev.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -thingdev.menu.VTable.heap=Heap -thingdev.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -thingdev.menu.VTable.iram=IRAM -thingdev.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -thingdev.upload.resetmethod=nodemcu -thingdev.build.flash_mode=dio -thingdev.build.flash_freq=40 -thingdev.menu.FlashSize.512K0=512K (no SPIFFS) -thingdev.menu.FlashSize.512K0.build.flash_size=512K -thingdev.menu.FlashSize.512K0.build.flash_size_bytes=0x80000 -thingdev.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -thingdev.menu.FlashSize.512K0.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K0.upload.maximum_size=499696 -thingdev.menu.FlashSize.512K0.build.rfcal_addr=0x7C000 -thingdev.menu.FlashSize.512K32=512K (32K SPIFFS) -thingdev.menu.FlashSize.512K32.build.flash_size=512K -thingdev.menu.FlashSize.512K32.build.flash_size_bytes=0x80000 -thingdev.menu.FlashSize.512K32.build.flash_ld=eagle.flash.512k32.ld -thingdev.menu.FlashSize.512K32.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K32.upload.maximum_size=466928 -thingdev.menu.FlashSize.512K32.build.rfcal_addr=0x7C000 -thingdev.menu.FlashSize.512K32.build.spiffs_start=0x73000 -thingdev.menu.FlashSize.512K32.build.spiffs_end=0x7B000 -thingdev.menu.FlashSize.512K32.build.spiffs_blocksize=4096 -thingdev.menu.FlashSize.512K64=512K (64K SPIFFS) -thingdev.menu.FlashSize.512K64.build.flash_size=512K -thingdev.menu.FlashSize.512K64.build.flash_size_bytes=0x80000 -thingdev.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -thingdev.menu.FlashSize.512K64.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K64.upload.maximum_size=434160 -thingdev.menu.FlashSize.512K64.build.rfcal_addr=0x7C000 -thingdev.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -thingdev.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -thingdev.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -thingdev.menu.FlashSize.512K128=512K (128K SPIFFS) -thingdev.menu.FlashSize.512K128.build.flash_size=512K -thingdev.menu.FlashSize.512K128.build.flash_size_bytes=0x80000 -thingdev.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -thingdev.menu.FlashSize.512K128.build.spiffs_pagesize=256 -thingdev.menu.FlashSize.512K128.upload.maximum_size=368624 -thingdev.menu.FlashSize.512K128.build.rfcal_addr=0x7C000 -thingdev.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -thingdev.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -thingdev.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -thingdev.menu.LwIPVariant.v2mss536=v2 Lower Memory -thingdev.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -thingdev.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -thingdev.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -thingdev.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -thingdev.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -thingdev.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -thingdev.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -thingdev.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.LwIPVariant.OpenSource=v1.4 Compile from source -thingdev.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -thingdev.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thingdev.menu.Debug.Disabled=Disabled -thingdev.menu.Debug.Disabled.build.debug_port= -thingdev.menu.Debug.Serial=Serial -thingdev.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thingdev.menu.Debug.Serial1=Serial1 -thingdev.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thingdev.menu.DebugLevel.None____=None -thingdev.menu.DebugLevel.None____.build.debug_level= -thingdev.menu.DebugLevel.SSL=SSL -thingdev.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -thingdev.menu.DebugLevel.TLS_MEM=TLS_MEM -thingdev.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thingdev.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -thingdev.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -thingdev.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thingdev.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thingdev.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.DebugLevel.CORE=CORE -thingdev.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -thingdev.menu.DebugLevel.WIFI=WIFI -thingdev.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thingdev.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -thingdev.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thingdev.menu.DebugLevel.UPDATER=UPDATER -thingdev.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thingdev.menu.DebugLevel.OTA=OTA -thingdev.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -thingdev.menu.DebugLevel.OOM=OOM -thingdev.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -thingdev.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thingdev.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -thingdev.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -thingdev.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -thingdev.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thingdev.menu.FlashErase.none=Only Sketch -thingdev.menu.FlashErase.none.upload.erase_cmd= -thingdev.menu.FlashErase.sdk=Sketch + WiFi Settings -thingdev.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -thingdev.menu.FlashErase.all=All Flash Contents -thingdev.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -thingdev.menu.UploadSpeed.115200=115200 -thingdev.menu.UploadSpeed.115200.upload.speed=115200 -thingdev.menu.UploadSpeed.9600=9600 -thingdev.menu.UploadSpeed.9600.upload.speed=9600 -thingdev.menu.UploadSpeed.57600=57600 -thingdev.menu.UploadSpeed.57600.upload.speed=57600 -thingdev.menu.UploadSpeed.230400.linux=230400 -thingdev.menu.UploadSpeed.230400.macosx=230400 -thingdev.menu.UploadSpeed.230400.upload.speed=230400 -thingdev.menu.UploadSpeed.256000.windows=256000 -thingdev.menu.UploadSpeed.256000.upload.speed=256000 -thingdev.menu.UploadSpeed.460800.linux=460800 -thingdev.menu.UploadSpeed.460800.macosx=460800 -thingdev.menu.UploadSpeed.460800.upload.speed=460800 -thingdev.menu.UploadSpeed.512000.windows=512000 -thingdev.menu.UploadSpeed.512000.upload.speed=512000 -thingdev.menu.UploadSpeed.921600=921600 -thingdev.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -esp210.name=SweetPea ESP-210 -esp210.build.board=ESP8266_ESP210 -esp210.upload.tool=esptool -esp210.upload.maximum_data_size=81920 -esp210.upload.wait_for_upload_port=true -esp210.upload.erase_cmd= -esp210.serial.disableDTR=true -esp210.serial.disableRTS=true -esp210.build.mcu=esp8266 -esp210.build.core=esp8266 -esp210.build.variant=generic -esp210.build.spiffs_pagesize=256 -esp210.build.debug_port= -esp210.build.debug_level= -esp210.menu.CpuFrequency.80=80 MHz -esp210.menu.CpuFrequency.80.build.f_cpu=80000000L -esp210.menu.CpuFrequency.160=160 MHz -esp210.menu.CpuFrequency.160.build.f_cpu=160000000L -esp210.menu.VTable.flash=Flash -esp210.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -esp210.menu.VTable.heap=Heap -esp210.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -esp210.menu.VTable.iram=IRAM -esp210.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -esp210.upload.resetmethod=ck -esp210.build.flash_mode=qio -esp210.build.flash_freq=40 -esp210.menu.FlashSize.4M1M=4M (1M SPIFFS) -esp210.menu.FlashSize.4M1M.build.flash_size=4M -esp210.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -esp210.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -esp210.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -esp210.menu.FlashSize.4M1M.upload.maximum_size=1044464 -esp210.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -esp210.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -esp210.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -esp210.menu.FlashSize.4M2M=4M (2M SPIFFS) -esp210.menu.FlashSize.4M2M.build.flash_size=4M -esp210.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -esp210.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -esp210.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -esp210.menu.FlashSize.4M2M.upload.maximum_size=1044464 -esp210.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -esp210.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -esp210.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -esp210.menu.FlashSize.4M3M=4M (3M SPIFFS) -esp210.menu.FlashSize.4M3M.build.flash_size=4M -esp210.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -esp210.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -esp210.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -esp210.menu.FlashSize.4M3M.upload.maximum_size=1044464 -esp210.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -esp210.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -esp210.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -esp210.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -esp210.menu.LwIPVariant.v2mss536=v2 Lower Memory -esp210.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -esp210.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -esp210.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -esp210.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -esp210.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -esp210.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -esp210.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -esp210.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -esp210.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -esp210.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.LwIPVariant.OpenSource=v1.4 Compile from source -esp210.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -esp210.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp210.menu.Debug.Disabled=Disabled -esp210.menu.Debug.Disabled.build.debug_port= -esp210.menu.Debug.Serial=Serial -esp210.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp210.menu.Debug.Serial1=Serial1 -esp210.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp210.menu.DebugLevel.None____=None -esp210.menu.DebugLevel.None____.build.debug_level= -esp210.menu.DebugLevel.SSL=SSL -esp210.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp210.menu.DebugLevel.TLS_MEM=TLS_MEM -esp210.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp210.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -esp210.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -esp210.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -esp210.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp210.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp210.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.DebugLevel.CORE=CORE -esp210.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp210.menu.DebugLevel.WIFI=WIFI -esp210.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp210.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -esp210.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp210.menu.DebugLevel.UPDATER=UPDATER -esp210.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp210.menu.DebugLevel.OTA=OTA -esp210.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp210.menu.DebugLevel.OOM=OOM -esp210.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -esp210.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp210.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -esp210.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -esp210.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -esp210.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp210.menu.FlashErase.none=Only Sketch -esp210.menu.FlashErase.none.upload.erase_cmd= -esp210.menu.FlashErase.sdk=Sketch + WiFi Settings -esp210.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -esp210.menu.FlashErase.all=All Flash Contents -esp210.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -esp210.menu.UploadSpeed.57600=57600 -esp210.menu.UploadSpeed.57600.upload.speed=57600 -esp210.menu.UploadSpeed.9600=9600 -esp210.menu.UploadSpeed.9600.upload.speed=9600 -esp210.menu.UploadSpeed.115200=115200 -esp210.menu.UploadSpeed.115200.upload.speed=115200 -esp210.menu.UploadSpeed.230400.linux=230400 -esp210.menu.UploadSpeed.230400.macosx=230400 -esp210.menu.UploadSpeed.230400.upload.speed=230400 -esp210.menu.UploadSpeed.256000.windows=256000 -esp210.menu.UploadSpeed.256000.upload.speed=256000 -esp210.menu.UploadSpeed.460800.linux=460800 -esp210.menu.UploadSpeed.460800.macosx=460800 -esp210.menu.UploadSpeed.460800.upload.speed=460800 -esp210.menu.UploadSpeed.512000.windows=512000 -esp210.menu.UploadSpeed.512000.upload.speed=512000 -esp210.menu.UploadSpeed.921600=921600 -esp210.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -d1_mini.name=LOLIN(WEMOS) D1 R2 & mini -d1_mini.build.board=ESP8266_WEMOS_D1MINI -d1_mini.build.variant=d1_mini -d1_mini.upload.tool=esptool -d1_mini.upload.maximum_data_size=81920 -d1_mini.upload.wait_for_upload_port=true -d1_mini.upload.erase_cmd= -d1_mini.serial.disableDTR=true -d1_mini.serial.disableRTS=true -d1_mini.build.mcu=esp8266 -d1_mini.build.core=esp8266 -d1_mini.build.spiffs_pagesize=256 -d1_mini.build.debug_port= -d1_mini.build.debug_level= -d1_mini.menu.CpuFrequency.80=80 MHz -d1_mini.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini.menu.CpuFrequency.160=160 MHz -d1_mini.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini.menu.VTable.flash=Flash -d1_mini.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini.menu.VTable.heap=Heap -d1_mini.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini.menu.VTable.iram=IRAM -d1_mini.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini.upload.resetmethod=nodemcu -d1_mini.build.flash_mode=dio -d1_mini.build.flash_freq=40 -d1_mini.menu.FlashSize.4M1M=4M (1M SPIFFS) -d1_mini.menu.FlashSize.4M1M.build.flash_size=4M -d1_mini.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -d1_mini.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1_mini.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -d1_mini.menu.FlashSize.4M1M.upload.maximum_size=1044464 -d1_mini.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -d1_mini.menu.FlashSize.4M2M=4M (2M SPIFFS) -d1_mini.menu.FlashSize.4M2M.build.flash_size=4M -d1_mini.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -d1_mini.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -d1_mini.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -d1_mini.menu.FlashSize.4M2M.upload.maximum_size=1044464 -d1_mini.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -d1_mini.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -d1_mini.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -d1_mini.menu.FlashSize.4M3M=4M (3M SPIFFS) -d1_mini.menu.FlashSize.4M3M.build.flash_size=4M -d1_mini.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -d1_mini.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -d1_mini.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -d1_mini.menu.FlashSize.4M3M.upload.maximum_size=1044464 -d1_mini.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -d1_mini.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -d1_mini.menu.LwIPVariant.v2mss536=v2 Lower Memory -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -d1_mini.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.LwIPVariant.OpenSource=v1.4 Compile from source -d1_mini.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini.menu.Debug.Disabled=Disabled -d1_mini.menu.Debug.Disabled.build.debug_port= -d1_mini.menu.Debug.Serial=Serial -d1_mini.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini.menu.Debug.Serial1=Serial1 -d1_mini.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini.menu.DebugLevel.None____=None -d1_mini.menu.DebugLevel.None____.build.debug_level= -d1_mini.menu.DebugLevel.SSL=SSL -d1_mini.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.DebugLevel.CORE=CORE -d1_mini.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini.menu.DebugLevel.WIFI=WIFI -d1_mini.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini.menu.DebugLevel.UPDATER=UPDATER -d1_mini.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini.menu.DebugLevel.OTA=OTA -d1_mini.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini.menu.DebugLevel.OOM=OOM -d1_mini.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini.menu.FlashErase.none=Only Sketch -d1_mini.menu.FlashErase.none.upload.erase_cmd= -d1_mini.menu.FlashErase.sdk=Sketch + WiFi Settings -d1_mini.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini.menu.FlashErase.all=All Flash Contents -d1_mini.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini.menu.UploadSpeed.921600=921600 -d1_mini.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini.menu.UploadSpeed.9600=9600 -d1_mini.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini.menu.UploadSpeed.57600=57600 -d1_mini.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini.menu.UploadSpeed.115200=115200 -d1_mini.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini.menu.UploadSpeed.230400.linux=230400 -d1_mini.menu.UploadSpeed.230400.macosx=230400 -d1_mini.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini.menu.UploadSpeed.256000.windows=256000 -d1_mini.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini.menu.UploadSpeed.460800.linux=460800 -d1_mini.menu.UploadSpeed.460800.macosx=460800 -d1_mini.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini.menu.UploadSpeed.512000.windows=512000 -d1_mini.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro -d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO -d1_mini_pro.build.variant=d1_mini -d1_mini_pro.upload.tool=esptool -d1_mini_pro.upload.maximum_data_size=81920 -d1_mini_pro.upload.wait_for_upload_port=true -d1_mini_pro.upload.erase_cmd= -d1_mini_pro.serial.disableDTR=true -d1_mini_pro.serial.disableRTS=true -d1_mini_pro.build.mcu=esp8266 -d1_mini_pro.build.core=esp8266 -d1_mini_pro.build.spiffs_pagesize=256 -d1_mini_pro.build.debug_port= -d1_mini_pro.build.debug_level= -d1_mini_pro.menu.CpuFrequency.80=80 MHz -d1_mini_pro.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini_pro.menu.CpuFrequency.160=160 MHz -d1_mini_pro.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini_pro.menu.VTable.flash=Flash -d1_mini_pro.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini_pro.menu.VTable.heap=Heap -d1_mini_pro.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini_pro.menu.VTable.iram=IRAM -d1_mini_pro.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini_pro.upload.resetmethod=nodemcu -d1_mini_pro.build.flash_mode=dio -d1_mini_pro.build.flash_freq=40 -d1_mini_pro.menu.FlashSize.16M15M=16M (15M SPIFFS) -d1_mini_pro.menu.FlashSize.16M15M.build.flash_size=16M -d1_mini_pro.menu.FlashSize.16M15M.build.flash_size_bytes=0x1000000 -d1_mini_pro.menu.FlashSize.16M15M.build.flash_ld=eagle.flash.16m.ld -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_pagesize=256 -d1_mini_pro.menu.FlashSize.16M15M.upload.maximum_size=1044464 -d1_mini_pro.menu.FlashSize.16M15M.build.rfcal_addr=0xFFC000 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_start=0x100000 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_end=0xFFB000 -d1_mini_pro.menu.FlashSize.16M15M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.LwIPVariant.v2mss536=v2 Lower Memory -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini_pro.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini_pro.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini_pro.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini_pro.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -d1_mini_pro.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini_pro.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.LwIPVariant.OpenSource=v1.4 Compile from source -d1_mini_pro.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini_pro.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_pro.menu.Debug.Disabled=Disabled -d1_mini_pro.menu.Debug.Disabled.build.debug_port= -d1_mini_pro.menu.Debug.Serial=Serial -d1_mini_pro.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_pro.menu.Debug.Serial1=Serial1 -d1_mini_pro.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_pro.menu.DebugLevel.None____=None -d1_mini_pro.menu.DebugLevel.None____.build.debug_level= -d1_mini_pro.menu.DebugLevel.SSL=SSL -d1_mini_pro.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_pro.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini_pro.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_pro.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.DebugLevel.CORE=CORE -d1_mini_pro.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_pro.menu.DebugLevel.WIFI=WIFI -d1_mini_pro.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_pro.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini_pro.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_pro.menu.DebugLevel.UPDATER=UPDATER -d1_mini_pro.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_pro.menu.DebugLevel.OTA=OTA -d1_mini_pro.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_pro.menu.DebugLevel.OOM=OOM -d1_mini_pro.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini_pro.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_pro.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_pro.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_pro.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_pro.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_pro.menu.FlashErase.none=Only Sketch -d1_mini_pro.menu.FlashErase.none.upload.erase_cmd= -d1_mini_pro.menu.FlashErase.sdk=Sketch + WiFi Settings -d1_mini_pro.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini_pro.menu.FlashErase.all=All Flash Contents -d1_mini_pro.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini_pro.menu.UploadSpeed.921600=921600 -d1_mini_pro.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini_pro.menu.UploadSpeed.9600=9600 -d1_mini_pro.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini_pro.menu.UploadSpeed.57600=57600 -d1_mini_pro.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini_pro.menu.UploadSpeed.115200=115200 -d1_mini_pro.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini_pro.menu.UploadSpeed.230400.linux=230400 -d1_mini_pro.menu.UploadSpeed.230400.macosx=230400 -d1_mini_pro.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini_pro.menu.UploadSpeed.256000.windows=256000 -d1_mini_pro.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini_pro.menu.UploadSpeed.460800.linux=460800 -d1_mini_pro.menu.UploadSpeed.460800.macosx=460800 -d1_mini_pro.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini_pro.menu.UploadSpeed.512000.windows=512000 -d1_mini_pro.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite -d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE -d1_mini_lite.build.variant=d1_mini -d1_mini_lite.upload.tool=esptool -d1_mini_lite.upload.maximum_data_size=81920 -d1_mini_lite.upload.wait_for_upload_port=true -d1_mini_lite.upload.erase_cmd= -d1_mini_lite.serial.disableDTR=true -d1_mini_lite.serial.disableRTS=true -d1_mini_lite.build.mcu=esp8266 -d1_mini_lite.build.core=esp8266 -d1_mini_lite.build.spiffs_pagesize=256 -d1_mini_lite.build.debug_port= -d1_mini_lite.build.debug_level= -d1_mini_lite.menu.CpuFrequency.80=80 MHz -d1_mini_lite.menu.CpuFrequency.80.build.f_cpu=80000000L -d1_mini_lite.menu.CpuFrequency.160=160 MHz -d1_mini_lite.menu.CpuFrequency.160.build.f_cpu=160000000L -d1_mini_lite.menu.VTable.flash=Flash -d1_mini_lite.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini_lite.menu.VTable.heap=Heap -d1_mini_lite.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini_lite.menu.VTable.iram=IRAM -d1_mini_lite.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini_lite.upload.resetmethod=nodemcu -d1_mini_lite.build.flash_mode=dout -d1_mini_lite.build.flash_freq=40 -d1_mini_lite.menu.FlashSize.1M0=1M (no SPIFFS) -d1_mini_lite.menu.FlashSize.1M0.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -d1_mini_lite.menu.FlashSize.1M0.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M0.upload.maximum_size=1023984 -d1_mini_lite.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M64=1M (64K SPIFFS) -d1_mini_lite.menu.FlashSize.1M64.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M64.upload.maximum_size=958448 -d1_mini_lite.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M128=1M (128K SPIFFS) -d1_mini_lite.menu.FlashSize.1M128.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M128.upload.maximum_size=892912 -d1_mini_lite.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M144=1M (144K SPIFFS) -d1_mini_lite.menu.FlashSize.1M144.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M144.upload.maximum_size=876528 -d1_mini_lite.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M160=1M (160K SPIFFS) -d1_mini_lite.menu.FlashSize.1M160.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M160.upload.maximum_size=860144 -d1_mini_lite.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M192=1M (192K SPIFFS) -d1_mini_lite.menu.FlashSize.1M192.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M192.upload.maximum_size=827376 -d1_mini_lite.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M256=1M (256K SPIFFS) -d1_mini_lite.menu.FlashSize.1M256.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M256.upload.maximum_size=761840 -d1_mini_lite.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -d1_mini_lite.menu.FlashSize.1M512=1M (512K SPIFFS) -d1_mini_lite.menu.FlashSize.1M512.build.flash_size=1M -d1_mini_lite.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_pagesize=256 -d1_mini_lite.menu.FlashSize.1M512.upload.maximum_size=499696 -d1_mini_lite.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -d1_mini_lite.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -d1_mini_lite.menu.LwIPVariant.v2mss536=v2 Lower Memory -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1_mini_lite.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1_mini_lite.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1_mini_lite.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1_mini_lite.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -d1_mini_lite.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1_mini_lite.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.LwIPVariant.OpenSource=v1.4 Compile from source -d1_mini_lite.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1_mini_lite.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_lite.menu.Debug.Disabled=Disabled -d1_mini_lite.menu.Debug.Disabled.build.debug_port= -d1_mini_lite.menu.Debug.Serial=Serial -d1_mini_lite.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_lite.menu.Debug.Serial1=Serial1 -d1_mini_lite.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_lite.menu.DebugLevel.None____=None -d1_mini_lite.menu.DebugLevel.None____.build.debug_level= -d1_mini_lite.menu.DebugLevel.SSL=SSL -d1_mini_lite.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_lite.menu.DebugLevel.TLS_MEM=TLS_MEM -d1_mini_lite.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_lite.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.DebugLevel.CORE=CORE -d1_mini_lite.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_lite.menu.DebugLevel.WIFI=WIFI -d1_mini_lite.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_lite.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1_mini_lite.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_lite.menu.DebugLevel.UPDATER=UPDATER -d1_mini_lite.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_lite.menu.DebugLevel.OTA=OTA -d1_mini_lite.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_lite.menu.DebugLevel.OOM=OOM -d1_mini_lite.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini_lite.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_lite.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1_mini_lite.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1_mini_lite.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_lite.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_lite.menu.FlashErase.none=Only Sketch -d1_mini_lite.menu.FlashErase.none.upload.erase_cmd= -d1_mini_lite.menu.FlashErase.sdk=Sketch + WiFi Settings -d1_mini_lite.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1_mini_lite.menu.FlashErase.all=All Flash Contents -d1_mini_lite.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1_mini_lite.menu.UploadSpeed.921600=921600 -d1_mini_lite.menu.UploadSpeed.921600.upload.speed=921600 -d1_mini_lite.menu.UploadSpeed.9600=9600 -d1_mini_lite.menu.UploadSpeed.9600.upload.speed=9600 -d1_mini_lite.menu.UploadSpeed.57600=57600 -d1_mini_lite.menu.UploadSpeed.57600.upload.speed=57600 -d1_mini_lite.menu.UploadSpeed.115200=115200 -d1_mini_lite.menu.UploadSpeed.115200.upload.speed=115200 -d1_mini_lite.menu.UploadSpeed.230400.linux=230400 -d1_mini_lite.menu.UploadSpeed.230400.macosx=230400 -d1_mini_lite.menu.UploadSpeed.230400.upload.speed=230400 -d1_mini_lite.menu.UploadSpeed.256000.windows=256000 -d1_mini_lite.menu.UploadSpeed.256000.upload.speed=256000 -d1_mini_lite.menu.UploadSpeed.460800.linux=460800 -d1_mini_lite.menu.UploadSpeed.460800.macosx=460800 -d1_mini_lite.menu.UploadSpeed.460800.upload.speed=460800 -d1_mini_lite.menu.UploadSpeed.512000.windows=512000 -d1_mini_lite.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -d1.name=WeMos D1 R1 -d1.build.board=ESP8266_WEMOS_D1R1 -d1.build.variant=d1 -d1.upload.tool=esptool -d1.upload.maximum_data_size=81920 -d1.upload.wait_for_upload_port=true -d1.upload.erase_cmd= -d1.serial.disableDTR=true -d1.serial.disableRTS=true -d1.build.mcu=esp8266 -d1.build.core=esp8266 -d1.build.spiffs_pagesize=256 -d1.build.debug_port= -d1.build.debug_level= -d1.menu.CpuFrequency.80=80 MHz -d1.menu.CpuFrequency.80.build.f_cpu=80000000L -d1.menu.CpuFrequency.160=160 MHz -d1.menu.CpuFrequency.160.build.f_cpu=160000000L -d1.menu.VTable.flash=Flash -d1.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1.menu.VTable.heap=Heap -d1.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1.menu.VTable.iram=IRAM -d1.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1.upload.resetmethod=nodemcu -d1.build.flash_mode=dio -d1.build.flash_freq=40 -d1.menu.FlashSize.4M1M=4M (1M SPIFFS) -d1.menu.FlashSize.4M1M.build.flash_size=4M -d1.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -d1.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -d1.menu.FlashSize.4M1M.upload.maximum_size=1044464 -d1.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -d1.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -d1.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -d1.menu.FlashSize.4M2M=4M (2M SPIFFS) -d1.menu.FlashSize.4M2M.build.flash_size=4M -d1.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -d1.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -d1.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -d1.menu.FlashSize.4M2M.upload.maximum_size=1044464 -d1.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -d1.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -d1.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -d1.menu.FlashSize.4M3M=4M (3M SPIFFS) -d1.menu.FlashSize.4M3M.build.flash_size=4M -d1.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -d1.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -d1.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -d1.menu.FlashSize.4M3M.upload.maximum_size=1044464 -d1.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -d1.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -d1.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -d1.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -d1.menu.LwIPVariant.v2mss536=v2 Lower Memory -d1.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -d1.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -d1.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -d1.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -d1.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -d1.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -d1.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -d1.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -d1.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -d1.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.LwIPVariant.OpenSource=v1.4 Compile from source -d1.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -d1.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1.menu.Debug.Disabled=Disabled -d1.menu.Debug.Disabled.build.debug_port= -d1.menu.Debug.Serial=Serial -d1.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1.menu.Debug.Serial1=Serial1 -d1.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1.menu.DebugLevel.None____=None -d1.menu.DebugLevel.None____.build.debug_level= -d1.menu.DebugLevel.SSL=SSL -d1.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1.menu.DebugLevel.TLS_MEM=TLS_MEM -d1.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -d1.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -d1.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -d1.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.DebugLevel.CORE=CORE -d1.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1.menu.DebugLevel.WIFI=WIFI -d1.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -d1.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1.menu.DebugLevel.UPDATER=UPDATER -d1.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1.menu.DebugLevel.OTA=OTA -d1.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1.menu.DebugLevel.OOM=OOM -d1.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -d1.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -d1.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -d1.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1.menu.FlashErase.none=Only Sketch -d1.menu.FlashErase.none.upload.erase_cmd= -d1.menu.FlashErase.sdk=Sketch + WiFi Settings -d1.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -d1.menu.FlashErase.all=All Flash Contents -d1.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -d1.menu.UploadSpeed.921600=921600 -d1.menu.UploadSpeed.921600.upload.speed=921600 -d1.menu.UploadSpeed.9600=9600 -d1.menu.UploadSpeed.9600.upload.speed=9600 -d1.menu.UploadSpeed.57600=57600 -d1.menu.UploadSpeed.57600.upload.speed=57600 -d1.menu.UploadSpeed.115200=115200 -d1.menu.UploadSpeed.115200.upload.speed=115200 -d1.menu.UploadSpeed.230400.linux=230400 -d1.menu.UploadSpeed.230400.macosx=230400 -d1.menu.UploadSpeed.230400.upload.speed=230400 -d1.menu.UploadSpeed.256000.windows=256000 -d1.menu.UploadSpeed.256000.upload.speed=256000 -d1.menu.UploadSpeed.460800.linux=460800 -d1.menu.UploadSpeed.460800.macosx=460800 -d1.menu.UploadSpeed.460800.upload.speed=460800 -d1.menu.UploadSpeed.512000.windows=512000 -d1.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -espino.name=ESPino (ESP-12 Module) -espino.build.board=ESP8266_ESP12 -espino.build.variant=espino -espino.upload.tool=esptool -espino.upload.maximum_data_size=81920 -espino.upload.wait_for_upload_port=true -espino.upload.erase_cmd= -espino.serial.disableDTR=true -espino.serial.disableRTS=true -espino.build.mcu=esp8266 -espino.build.core=esp8266 -espino.build.spiffs_pagesize=256 -espino.build.debug_port= -espino.build.debug_level= -espino.menu.CpuFrequency.80=80 MHz -espino.menu.CpuFrequency.80.build.f_cpu=80000000L -espino.menu.CpuFrequency.160=160 MHz -espino.menu.CpuFrequency.160.build.f_cpu=160000000L -espino.menu.VTable.flash=Flash -espino.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espino.menu.VTable.heap=Heap -espino.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espino.menu.VTable.iram=IRAM -espino.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espino.menu.ResetMethod.ck=ck -espino.menu.ResetMethod.ck.upload.resetmethod=ck -espino.menu.ResetMethod.nodemcu=nodemcu -espino.menu.ResetMethod.nodemcu.upload.resetmethod=nodemcu -espino.build.flash_mode=qio -espino.build.flash_freq=40 -espino.menu.FlashSize.4M1M=4M (1M SPIFFS) -espino.menu.FlashSize.4M1M.build.flash_size=4M -espino.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espino.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espino.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espino.menu.FlashSize.4M2M=4M (2M SPIFFS) -espino.menu.FlashSize.4M2M.build.flash_size=4M -espino.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -espino.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espino.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -espino.menu.FlashSize.4M2M.upload.maximum_size=1044464 -espino.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -espino.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -espino.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -espino.menu.FlashSize.4M3M=4M (3M SPIFFS) -espino.menu.FlashSize.4M3M.build.flash_size=4M -espino.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espino.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espino.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espino.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espino.menu.LwIPVariant.v2mss536=v2 Lower Memory -espino.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espino.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espino.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espino.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espino.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espino.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espino.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espino.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espino.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espino.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espino.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espino.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espino.menu.Debug.Disabled=Disabled -espino.menu.Debug.Disabled.build.debug_port= -espino.menu.Debug.Serial=Serial -espino.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espino.menu.Debug.Serial1=Serial1 -espino.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espino.menu.DebugLevel.None____=None -espino.menu.DebugLevel.None____.build.debug_level= -espino.menu.DebugLevel.SSL=SSL -espino.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espino.menu.DebugLevel.TLS_MEM=TLS_MEM -espino.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espino.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espino.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espino.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espino.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espino.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espino.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.DebugLevel.CORE=CORE -espino.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espino.menu.DebugLevel.WIFI=WIFI -espino.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espino.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espino.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espino.menu.DebugLevel.UPDATER=UPDATER -espino.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espino.menu.DebugLevel.OTA=OTA -espino.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espino.menu.DebugLevel.OOM=OOM -espino.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -espino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espino.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espino.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espino.menu.FlashErase.none=Only Sketch -espino.menu.FlashErase.none.upload.erase_cmd= -espino.menu.FlashErase.sdk=Sketch + WiFi Settings -espino.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espino.menu.FlashErase.all=All Flash Contents -espino.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espino.menu.UploadSpeed.115200=115200 -espino.menu.UploadSpeed.115200.upload.speed=115200 -espino.menu.UploadSpeed.9600=9600 -espino.menu.UploadSpeed.9600.upload.speed=9600 -espino.menu.UploadSpeed.57600=57600 -espino.menu.UploadSpeed.57600.upload.speed=57600 -espino.menu.UploadSpeed.230400.linux=230400 -espino.menu.UploadSpeed.230400.macosx=230400 -espino.menu.UploadSpeed.230400.upload.speed=230400 -espino.menu.UploadSpeed.256000.windows=256000 -espino.menu.UploadSpeed.256000.upload.speed=256000 -espino.menu.UploadSpeed.460800.linux=460800 -espino.menu.UploadSpeed.460800.macosx=460800 -espino.menu.UploadSpeed.460800.upload.speed=460800 -espino.menu.UploadSpeed.512000.windows=512000 -espino.menu.UploadSpeed.512000.upload.speed=512000 -espino.menu.UploadSpeed.921600=921600 -espino.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -espinotee.name=ThaiEasyElec's ESPino -espinotee.build.board=ESP8266_ESP13 -espinotee.build.variant=espinotee -espinotee.upload.tool=esptool -espinotee.upload.maximum_data_size=81920 -espinotee.upload.wait_for_upload_port=true -espinotee.upload.erase_cmd= -espinotee.serial.disableDTR=true -espinotee.serial.disableRTS=true -espinotee.build.mcu=esp8266 -espinotee.build.core=esp8266 -espinotee.build.spiffs_pagesize=256 -espinotee.build.debug_port= -espinotee.build.debug_level= -espinotee.menu.CpuFrequency.80=80 MHz -espinotee.menu.CpuFrequency.80.build.f_cpu=80000000L -espinotee.menu.CpuFrequency.160=160 MHz -espinotee.menu.CpuFrequency.160.build.f_cpu=160000000L -espinotee.menu.VTable.flash=Flash -espinotee.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espinotee.menu.VTable.heap=Heap -espinotee.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espinotee.menu.VTable.iram=IRAM -espinotee.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espinotee.upload.resetmethod=nodemcu -espinotee.build.flash_mode=qio -espinotee.build.flash_freq=40 -espinotee.menu.FlashSize.4M1M=4M (1M SPIFFS) -espinotee.menu.FlashSize.4M1M.build.flash_size=4M -espinotee.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -espinotee.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espinotee.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -espinotee.menu.FlashSize.4M1M.upload.maximum_size=1044464 -espinotee.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -espinotee.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -espinotee.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -espinotee.menu.FlashSize.4M2M=4M (2M SPIFFS) -espinotee.menu.FlashSize.4M2M.build.flash_size=4M -espinotee.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -espinotee.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espinotee.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -espinotee.menu.FlashSize.4M2M.upload.maximum_size=1044464 -espinotee.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -espinotee.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -espinotee.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -espinotee.menu.FlashSize.4M3M=4M (3M SPIFFS) -espinotee.menu.FlashSize.4M3M.build.flash_size=4M -espinotee.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -espinotee.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -espinotee.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -espinotee.menu.FlashSize.4M3M.upload.maximum_size=1044464 -espinotee.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -espinotee.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -espinotee.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -espinotee.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -espinotee.menu.LwIPVariant.v2mss536=v2 Lower Memory -espinotee.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -espinotee.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -espinotee.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -espinotee.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -espinotee.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -espinotee.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -espinotee.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -espinotee.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.LwIPVariant.OpenSource=v1.4 Compile from source -espinotee.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -espinotee.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espinotee.menu.Debug.Disabled=Disabled -espinotee.menu.Debug.Disabled.build.debug_port= -espinotee.menu.Debug.Serial=Serial -espinotee.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espinotee.menu.Debug.Serial1=Serial1 -espinotee.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espinotee.menu.DebugLevel.None____=None -espinotee.menu.DebugLevel.None____.build.debug_level= -espinotee.menu.DebugLevel.SSL=SSL -espinotee.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -espinotee.menu.DebugLevel.TLS_MEM=TLS_MEM -espinotee.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espinotee.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -espinotee.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -espinotee.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espinotee.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espinotee.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.DebugLevel.CORE=CORE -espinotee.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -espinotee.menu.DebugLevel.WIFI=WIFI -espinotee.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espinotee.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -espinotee.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espinotee.menu.DebugLevel.UPDATER=UPDATER -espinotee.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espinotee.menu.DebugLevel.OTA=OTA -espinotee.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -espinotee.menu.DebugLevel.OOM=OOM -espinotee.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -espinotee.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espinotee.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -espinotee.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -espinotee.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -espinotee.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espinotee.menu.FlashErase.none=Only Sketch -espinotee.menu.FlashErase.none.upload.erase_cmd= -espinotee.menu.FlashErase.sdk=Sketch + WiFi Settings -espinotee.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -espinotee.menu.FlashErase.all=All Flash Contents -espinotee.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -espinotee.menu.UploadSpeed.115200=115200 -espinotee.menu.UploadSpeed.115200.upload.speed=115200 -espinotee.menu.UploadSpeed.9600=9600 -espinotee.menu.UploadSpeed.9600.upload.speed=9600 -espinotee.menu.UploadSpeed.57600=57600 -espinotee.menu.UploadSpeed.57600.upload.speed=57600 -espinotee.menu.UploadSpeed.230400.linux=230400 -espinotee.menu.UploadSpeed.230400.macosx=230400 -espinotee.menu.UploadSpeed.230400.upload.speed=230400 -espinotee.menu.UploadSpeed.256000.windows=256000 -espinotee.menu.UploadSpeed.256000.upload.speed=256000 -espinotee.menu.UploadSpeed.460800.linux=460800 -espinotee.menu.UploadSpeed.460800.macosx=460800 -espinotee.menu.UploadSpeed.460800.upload.speed=460800 -espinotee.menu.UploadSpeed.512000.windows=512000 -espinotee.menu.UploadSpeed.512000.upload.speed=512000 -espinotee.menu.UploadSpeed.921600=921600 -espinotee.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -wifinfo.name=WifInfo -wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 -wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 -wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 -wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld -wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 -wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) -wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 -wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 -wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 -wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 -wifinfo.menu.ESPModule.ESP12.build.flash_size=4M -wifinfo.build.board=WIFINFO -wifinfo.build.variant=wifinfo -wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M -wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) -wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 -wifinfo.upload.tool=esptool -wifinfo.upload.maximum_data_size=81920 -wifinfo.upload.wait_for_upload_port=true -wifinfo.upload.erase_cmd= -wifinfo.serial.disableDTR=true -wifinfo.serial.disableRTS=true -wifinfo.build.mcu=esp8266 -wifinfo.build.core=esp8266 -wifinfo.build.spiffs_pagesize=256 -wifinfo.build.debug_port= -wifinfo.build.debug_level= -wifinfo.menu.CpuFrequency.80=80 MHz -wifinfo.menu.CpuFrequency.80.build.f_cpu=80000000L -wifinfo.menu.CpuFrequency.160=160 MHz -wifinfo.menu.CpuFrequency.160.build.f_cpu=160000000L -wifinfo.menu.VTable.flash=Flash -wifinfo.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifinfo.menu.VTable.heap=Heap -wifinfo.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifinfo.menu.VTable.iram=IRAM -wifinfo.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifinfo.upload.resetmethod=nodemcu -wifinfo.build.flash_mode=qio -wifinfo.menu.FlashFreq.40=40MHz -wifinfo.menu.FlashFreq.40.build.flash_freq=40 -wifinfo.menu.FlashFreq.80=80MHz -wifinfo.menu.FlashFreq.80.build.flash_freq=80 -wifinfo.menu.FlashSize.1M0=1M (no SPIFFS) -wifinfo.menu.FlashSize.1M0.build.flash_size=1M -wifinfo.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -wifinfo.menu.FlashSize.1M0.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M0.upload.maximum_size=1023984 -wifinfo.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M64=1M (64K SPIFFS) -wifinfo.menu.FlashSize.1M64.build.flash_size=1M -wifinfo.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -wifinfo.menu.FlashSize.1M64.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M64.upload.maximum_size=958448 -wifinfo.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -wifinfo.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M128=1M (128K SPIFFS) -wifinfo.menu.FlashSize.1M128.build.flash_size=1M -wifinfo.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -wifinfo.menu.FlashSize.1M128.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M128.upload.maximum_size=892912 -wifinfo.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -wifinfo.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M144=1M (144K SPIFFS) -wifinfo.menu.FlashSize.1M144.build.flash_size=1M -wifinfo.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -wifinfo.menu.FlashSize.1M144.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M144.upload.maximum_size=876528 -wifinfo.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -wifinfo.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M160=1M (160K SPIFFS) -wifinfo.menu.FlashSize.1M160.build.flash_size=1M -wifinfo.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -wifinfo.menu.FlashSize.1M160.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M160.upload.maximum_size=860144 -wifinfo.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -wifinfo.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M192=1M (192K SPIFFS) -wifinfo.menu.FlashSize.1M192.build.flash_size=1M -wifinfo.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.FlashSize.1M192.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M192.upload.maximum_size=827376 -wifinfo.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -wifinfo.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M256=1M (256K SPIFFS) -wifinfo.menu.FlashSize.1M256.build.flash_size=1M -wifinfo.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -wifinfo.menu.FlashSize.1M256.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M256.upload.maximum_size=761840 -wifinfo.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -wifinfo.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -wifinfo.menu.FlashSize.1M512=1M (512K SPIFFS) -wifinfo.menu.FlashSize.1M512.build.flash_size=1M -wifinfo.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -wifinfo.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -wifinfo.menu.FlashSize.1M512.build.spiffs_pagesize=256 -wifinfo.menu.FlashSize.1M512.upload.maximum_size=499696 -wifinfo.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -wifinfo.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -wifinfo.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -wifinfo.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -wifinfo.menu.LwIPVariant.v2mss536=v2 Lower Memory -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -wifinfo.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -wifinfo.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -wifinfo.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -wifinfo.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -wifinfo.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -wifinfo.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.LwIPVariant.OpenSource=v1.4 Compile from source -wifinfo.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -wifinfo.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifinfo.menu.Debug.Disabled=Disabled -wifinfo.menu.Debug.Disabled.build.debug_port= -wifinfo.menu.Debug.Serial=Serial -wifinfo.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifinfo.menu.Debug.Serial1=Serial1 -wifinfo.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifinfo.menu.DebugLevel.None____=None -wifinfo.menu.DebugLevel.None____.build.debug_level= -wifinfo.menu.DebugLevel.SSL=SSL -wifinfo.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifinfo.menu.DebugLevel.TLS_MEM=TLS_MEM -wifinfo.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifinfo.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -wifinfo.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -wifinfo.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifinfo.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.DebugLevel.CORE=CORE -wifinfo.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifinfo.menu.DebugLevel.WIFI=WIFI -wifinfo.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifinfo.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -wifinfo.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifinfo.menu.DebugLevel.UPDATER=UPDATER -wifinfo.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifinfo.menu.DebugLevel.OTA=OTA -wifinfo.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifinfo.menu.DebugLevel.OOM=OOM -wifinfo.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifinfo.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifinfo.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifinfo.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifinfo.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -wifinfo.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifinfo.menu.FlashErase.none=Only Sketch -wifinfo.menu.FlashErase.none.upload.erase_cmd= -wifinfo.menu.FlashErase.sdk=Sketch + WiFi Settings -wifinfo.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifinfo.menu.FlashErase.all=All Flash Contents -wifinfo.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifinfo.menu.UploadSpeed.115200=115200 -wifinfo.menu.UploadSpeed.115200.upload.speed=115200 -wifinfo.menu.UploadSpeed.9600=9600 -wifinfo.menu.UploadSpeed.9600.upload.speed=9600 -wifinfo.menu.UploadSpeed.57600=57600 -wifinfo.menu.UploadSpeed.57600.upload.speed=57600 -wifinfo.menu.UploadSpeed.230400.linux=230400 -wifinfo.menu.UploadSpeed.230400.macosx=230400 -wifinfo.menu.UploadSpeed.230400.upload.speed=230400 -wifinfo.menu.UploadSpeed.256000.windows=256000 -wifinfo.menu.UploadSpeed.256000.upload.speed=256000 -wifinfo.menu.UploadSpeed.460800.linux=460800 -wifinfo.menu.UploadSpeed.460800.macosx=460800 -wifinfo.menu.UploadSpeed.460800.upload.speed=460800 -wifinfo.menu.UploadSpeed.512000.windows=512000 -wifinfo.menu.UploadSpeed.512000.upload.speed=512000 -wifinfo.menu.UploadSpeed.921600=921600 -wifinfo.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -arduino-esp8266.name=Arduino -arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO -arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI -arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.primo=Primo -arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi -arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO -arduino-esp8266.build.board=ESP8266_ARDUINO -arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO -arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi -arduino-esp8266.upload.tool=esptool -arduino-esp8266.upload.maximum_data_size=81920 -arduino-esp8266.upload.wait_for_upload_port=true -arduino-esp8266.upload.erase_cmd= -arduino-esp8266.serial.disableDTR=true -arduino-esp8266.serial.disableRTS=true -arduino-esp8266.build.mcu=esp8266 -arduino-esp8266.build.core=esp8266 -arduino-esp8266.build.variant=generic -arduino-esp8266.build.spiffs_pagesize=256 -arduino-esp8266.build.debug_port= -arduino-esp8266.build.debug_level= -arduino-esp8266.menu.CpuFrequency.80=80 MHz -arduino-esp8266.menu.CpuFrequency.80.build.f_cpu=80000000L -arduino-esp8266.menu.CpuFrequency.160=160 MHz -arduino-esp8266.menu.CpuFrequency.160.build.f_cpu=160000000L -arduino-esp8266.menu.VTable.flash=Flash -arduino-esp8266.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -arduino-esp8266.menu.VTable.heap=Heap -arduino-esp8266.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -arduino-esp8266.menu.VTable.iram=IRAM -arduino-esp8266.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -arduino-esp8266.upload.resetmethod=ck -arduino-esp8266.build.flash_mode=qio -arduino-esp8266.build.flash_freq=40 -arduino-esp8266.menu.FlashSize.4M1M=4M (1M SPIFFS) -arduino-esp8266.menu.FlashSize.4M1M.build.flash_size=4M -arduino-esp8266.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -arduino-esp8266.menu.FlashSize.4M1M.upload.maximum_size=1044464 -arduino-esp8266.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.FlashSize.4M2M=4M (2M SPIFFS) -arduino-esp8266.menu.FlashSize.4M2M.build.flash_size=4M -arduino-esp8266.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -arduino-esp8266.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -arduino-esp8266.menu.FlashSize.4M2M.upload.maximum_size=1044464 -arduino-esp8266.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -arduino-esp8266.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.FlashSize.4M3M=4M (3M SPIFFS) -arduino-esp8266.menu.FlashSize.4M3M.build.flash_size=4M -arduino-esp8266.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -arduino-esp8266.menu.FlashSize.4M3M.upload.maximum_size=1044464 -arduino-esp8266.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -arduino-esp8266.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.LwIPVariant.v2mss536=v2 Lower Memory -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -arduino-esp8266.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -arduino-esp8266.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -arduino-esp8266.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -arduino-esp8266.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -arduino-esp8266.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -arduino-esp8266.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.LwIPVariant.OpenSource=v1.4 Compile from source -arduino-esp8266.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -arduino-esp8266.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -arduino-esp8266.menu.Debug.Disabled=Disabled -arduino-esp8266.menu.Debug.Disabled.build.debug_port= -arduino-esp8266.menu.Debug.Serial=Serial -arduino-esp8266.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -arduino-esp8266.menu.Debug.Serial1=Serial1 -arduino-esp8266.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -arduino-esp8266.menu.DebugLevel.None____=None -arduino-esp8266.menu.DebugLevel.None____.build.debug_level= -arduino-esp8266.menu.DebugLevel.SSL=SSL -arduino-esp8266.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -arduino-esp8266.menu.DebugLevel.TLS_MEM=TLS_MEM -arduino-esp8266.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -arduino-esp8266.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.DebugLevel.CORE=CORE -arduino-esp8266.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -arduino-esp8266.menu.DebugLevel.WIFI=WIFI -arduino-esp8266.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -arduino-esp8266.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -arduino-esp8266.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -arduino-esp8266.menu.DebugLevel.UPDATER=UPDATER -arduino-esp8266.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -arduino-esp8266.menu.DebugLevel.OTA=OTA -arduino-esp8266.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -arduino-esp8266.menu.DebugLevel.OOM=OOM -arduino-esp8266.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -arduino-esp8266.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -arduino-esp8266.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -arduino-esp8266.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -arduino-esp8266.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -arduino-esp8266.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -arduino-esp8266.menu.FlashErase.none=Only Sketch -arduino-esp8266.menu.FlashErase.none.upload.erase_cmd= -arduino-esp8266.menu.FlashErase.sdk=Sketch + WiFi Settings -arduino-esp8266.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -arduino-esp8266.menu.FlashErase.all=All Flash Contents -arduino-esp8266.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -arduino-esp8266.menu.UploadSpeed.115200=115200 -arduino-esp8266.menu.UploadSpeed.115200.upload.speed=115200 -arduino-esp8266.menu.UploadSpeed.9600=9600 -arduino-esp8266.menu.UploadSpeed.9600.upload.speed=9600 -arduino-esp8266.menu.UploadSpeed.57600=57600 -arduino-esp8266.menu.UploadSpeed.57600.upload.speed=57600 -arduino-esp8266.menu.UploadSpeed.230400.linux=230400 -arduino-esp8266.menu.UploadSpeed.230400.macosx=230400 -arduino-esp8266.menu.UploadSpeed.230400.upload.speed=230400 -arduino-esp8266.menu.UploadSpeed.256000.windows=256000 -arduino-esp8266.menu.UploadSpeed.256000.upload.speed=256000 -arduino-esp8266.menu.UploadSpeed.460800.linux=460800 -arduino-esp8266.menu.UploadSpeed.460800.macosx=460800 -arduino-esp8266.menu.UploadSpeed.460800.upload.speed=460800 -arduino-esp8266.menu.UploadSpeed.512000.windows=512000 -arduino-esp8266.menu.UploadSpeed.512000.upload.speed=512000 -arduino-esp8266.menu.UploadSpeed.921600=921600 -arduino-esp8266.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -gen4iod.name=4D Systems gen4 IoD Range -gen4iod.build.board=GEN4_IOD -gen4iod.build.f_cpu=160000000L -gen4iod.build.variant=generic -gen4iod.upload.tool=esptool -gen4iod.upload.maximum_data_size=81920 -gen4iod.upload.wait_for_upload_port=true -gen4iod.upload.erase_cmd= -gen4iod.serial.disableDTR=true -gen4iod.serial.disableRTS=true -gen4iod.build.mcu=esp8266 -gen4iod.build.core=esp8266 -gen4iod.build.spiffs_pagesize=256 -gen4iod.build.debug_port= -gen4iod.build.debug_level= -gen4iod.menu.CpuFrequency.80=80 MHz -gen4iod.menu.CpuFrequency.80.build.f_cpu=80000000L -gen4iod.menu.CpuFrequency.160=160 MHz -gen4iod.menu.CpuFrequency.160.build.f_cpu=160000000L -gen4iod.menu.VTable.flash=Flash -gen4iod.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -gen4iod.menu.VTable.heap=Heap -gen4iod.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -gen4iod.menu.VTable.iram=IRAM -gen4iod.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -gen4iod.upload.resetmethod=nodemcu -gen4iod.build.flash_mode=dio -gen4iod.build.flash_freq=80 -gen4iod.menu.FlashSize.512K0=512K (no SPIFFS) -gen4iod.menu.FlashSize.512K0.build.flash_size=512K -gen4iod.menu.FlashSize.512K0.build.flash_size_bytes=0x80000 -gen4iod.menu.FlashSize.512K0.build.flash_ld=eagle.flash.512k0.ld -gen4iod.menu.FlashSize.512K0.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K0.upload.maximum_size=499696 -gen4iod.menu.FlashSize.512K0.build.rfcal_addr=0x7C000 -gen4iod.menu.FlashSize.512K32=512K (32K SPIFFS) -gen4iod.menu.FlashSize.512K32.build.flash_size=512K -gen4iod.menu.FlashSize.512K32.build.flash_size_bytes=0x80000 -gen4iod.menu.FlashSize.512K32.build.flash_ld=eagle.flash.512k32.ld -gen4iod.menu.FlashSize.512K32.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K32.upload.maximum_size=466928 -gen4iod.menu.FlashSize.512K32.build.rfcal_addr=0x7C000 -gen4iod.menu.FlashSize.512K32.build.spiffs_start=0x73000 -gen4iod.menu.FlashSize.512K32.build.spiffs_end=0x7B000 -gen4iod.menu.FlashSize.512K32.build.spiffs_blocksize=4096 -gen4iod.menu.FlashSize.512K64=512K (64K SPIFFS) -gen4iod.menu.FlashSize.512K64.build.flash_size=512K -gen4iod.menu.FlashSize.512K64.build.flash_size_bytes=0x80000 -gen4iod.menu.FlashSize.512K64.build.flash_ld=eagle.flash.512k64.ld -gen4iod.menu.FlashSize.512K64.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K64.upload.maximum_size=434160 -gen4iod.menu.FlashSize.512K64.build.rfcal_addr=0x7C000 -gen4iod.menu.FlashSize.512K64.build.spiffs_start=0x6B000 -gen4iod.menu.FlashSize.512K64.build.spiffs_end=0x7B000 -gen4iod.menu.FlashSize.512K64.build.spiffs_blocksize=4096 -gen4iod.menu.FlashSize.512K128=512K (128K SPIFFS) -gen4iod.menu.FlashSize.512K128.build.flash_size=512K -gen4iod.menu.FlashSize.512K128.build.flash_size_bytes=0x80000 -gen4iod.menu.FlashSize.512K128.build.flash_ld=eagle.flash.512k128.ld -gen4iod.menu.FlashSize.512K128.build.spiffs_pagesize=256 -gen4iod.menu.FlashSize.512K128.upload.maximum_size=368624 -gen4iod.menu.FlashSize.512K128.build.rfcal_addr=0x7C000 -gen4iod.menu.FlashSize.512K128.build.spiffs_start=0x5B000 -gen4iod.menu.FlashSize.512K128.build.spiffs_end=0x7B000 -gen4iod.menu.FlashSize.512K128.build.spiffs_blocksize=4096 -gen4iod.menu.LwIPVariant.v2mss536=v2 Lower Memory -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -gen4iod.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -gen4iod.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -gen4iod.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -gen4iod.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -gen4iod.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -gen4iod.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.LwIPVariant.OpenSource=v1.4 Compile from source -gen4iod.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -gen4iod.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -gen4iod.menu.Debug.Disabled=Disabled -gen4iod.menu.Debug.Disabled.build.debug_port= -gen4iod.menu.Debug.Serial=Serial -gen4iod.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -gen4iod.menu.Debug.Serial1=Serial1 -gen4iod.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -gen4iod.menu.DebugLevel.None____=None -gen4iod.menu.DebugLevel.None____.build.debug_level= -gen4iod.menu.DebugLevel.SSL=SSL -gen4iod.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -gen4iod.menu.DebugLevel.TLS_MEM=TLS_MEM -gen4iod.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -gen4iod.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -gen4iod.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -gen4iod.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -gen4iod.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.DebugLevel.CORE=CORE -gen4iod.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -gen4iod.menu.DebugLevel.WIFI=WIFI -gen4iod.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -gen4iod.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -gen4iod.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -gen4iod.menu.DebugLevel.UPDATER=UPDATER -gen4iod.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -gen4iod.menu.DebugLevel.OTA=OTA -gen4iod.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -gen4iod.menu.DebugLevel.OOM=OOM -gen4iod.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -gen4iod.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -gen4iod.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -gen4iod.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -gen4iod.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -gen4iod.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -gen4iod.menu.FlashErase.none=Only Sketch -gen4iod.menu.FlashErase.none.upload.erase_cmd= -gen4iod.menu.FlashErase.sdk=Sketch + WiFi Settings -gen4iod.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -gen4iod.menu.FlashErase.all=All Flash Contents -gen4iod.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -gen4iod.menu.UploadSpeed.115200=115200 -gen4iod.menu.UploadSpeed.115200.upload.speed=115200 -gen4iod.menu.UploadSpeed.9600=9600 -gen4iod.menu.UploadSpeed.9600.upload.speed=9600 -gen4iod.menu.UploadSpeed.57600=57600 -gen4iod.menu.UploadSpeed.57600.upload.speed=57600 -gen4iod.menu.UploadSpeed.230400.linux=230400 -gen4iod.menu.UploadSpeed.230400.macosx=230400 -gen4iod.menu.UploadSpeed.230400.upload.speed=230400 -gen4iod.menu.UploadSpeed.256000.windows=256000 -gen4iod.menu.UploadSpeed.256000.upload.speed=256000 -gen4iod.menu.UploadSpeed.460800.linux=460800 -gen4iod.menu.UploadSpeed.460800.macosx=460800 -gen4iod.menu.UploadSpeed.460800.upload.speed=460800 -gen4iod.menu.UploadSpeed.512000.windows=512000 -gen4iod.menu.UploadSpeed.512000.upload.speed=512000 -gen4iod.menu.UploadSpeed.921600=921600 -gen4iod.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -oak.name=Digistump Oak -oak.build.board=ESP8266_OAK -oak.build.variant=oak -oak.upload.maximum_size=1040368 -oak.upload.tool=esptool -oak.upload.maximum_data_size=81920 -oak.upload.wait_for_upload_port=true -oak.upload.erase_cmd= -oak.serial.disableDTR=true -oak.serial.disableRTS=true -oak.build.mcu=esp8266 -oak.build.core=esp8266 -oak.build.spiffs_pagesize=256 -oak.build.debug_port= -oak.build.debug_level= -oak.menu.CpuFrequency.80=80 MHz -oak.menu.CpuFrequency.80.build.f_cpu=80000000L -oak.menu.CpuFrequency.160=160 MHz -oak.menu.CpuFrequency.160.build.f_cpu=160000000L -oak.menu.VTable.flash=Flash -oak.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -oak.menu.VTable.heap=Heap -oak.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -oak.menu.VTable.iram=IRAM -oak.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -oak.upload.resetmethod=none -oak.build.flash_mode=dio -oak.build.flash_freq=40 -oak.menu.FlashSize.4M1M=4M (1M SPIFFS) -oak.menu.FlashSize.4M1M.build.flash_size=4M -oak.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -oak.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -oak.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -oak.menu.FlashSize.4M1M.upload.maximum_size=1044464 -oak.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -oak.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -oak.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -oak.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -oak.menu.FlashSize.4M2M=4M (2M SPIFFS) -oak.menu.FlashSize.4M2M.build.flash_size=4M -oak.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -oak.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -oak.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -oak.menu.FlashSize.4M2M.upload.maximum_size=1044464 -oak.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -oak.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -oak.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -oak.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -oak.menu.FlashSize.4M3M=4M (3M SPIFFS) -oak.menu.FlashSize.4M3M.build.flash_size=4M -oak.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -oak.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -oak.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -oak.menu.FlashSize.4M3M.upload.maximum_size=1044464 -oak.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -oak.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -oak.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -oak.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -oak.menu.LwIPVariant.v2mss536=v2 Lower Memory -oak.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -oak.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -oak.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -oak.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -oak.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -oak.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -oak.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -oak.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -oak.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -oak.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.LwIPVariant.OpenSource=v1.4 Compile from source -oak.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -oak.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -oak.menu.Debug.Disabled=Disabled -oak.menu.Debug.Disabled.build.debug_port= -oak.menu.Debug.Serial=Serial -oak.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -oak.menu.Debug.Serial1=Serial1 -oak.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -oak.menu.DebugLevel.None____=None -oak.menu.DebugLevel.None____.build.debug_level= -oak.menu.DebugLevel.SSL=SSL -oak.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -oak.menu.DebugLevel.TLS_MEM=TLS_MEM -oak.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -oak.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -oak.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -oak.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -oak.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -oak.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -oak.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.DebugLevel.CORE=CORE -oak.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -oak.menu.DebugLevel.WIFI=WIFI -oak.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -oak.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -oak.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -oak.menu.DebugLevel.UPDATER=UPDATER -oak.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -oak.menu.DebugLevel.OTA=OTA -oak.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -oak.menu.DebugLevel.OOM=OOM -oak.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -oak.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -oak.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -oak.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -oak.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -oak.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -oak.menu.FlashErase.none=Only Sketch -oak.menu.FlashErase.none.upload.erase_cmd= -oak.menu.FlashErase.sdk=Sketch + WiFi Settings -oak.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -oak.menu.FlashErase.all=All Flash Contents -oak.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -oak.menu.UploadSpeed.921600=921600 -oak.menu.UploadSpeed.921600.upload.speed=921600 -oak.menu.UploadSpeed.9600=9600 -oak.menu.UploadSpeed.9600.upload.speed=9600 -oak.menu.UploadSpeed.57600=57600 -oak.menu.UploadSpeed.57600.upload.speed=57600 -oak.menu.UploadSpeed.115200=115200 -oak.menu.UploadSpeed.115200.upload.speed=115200 -oak.menu.UploadSpeed.230400.linux=230400 -oak.menu.UploadSpeed.230400.macosx=230400 -oak.menu.UploadSpeed.230400.upload.speed=230400 -oak.menu.UploadSpeed.256000.windows=256000 -oak.menu.UploadSpeed.256000.upload.speed=256000 -oak.menu.UploadSpeed.460800.linux=460800 -oak.menu.UploadSpeed.460800.macosx=460800 -oak.menu.UploadSpeed.460800.upload.speed=460800 -oak.menu.UploadSpeed.512000.windows=512000 -oak.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -wifiduino.name=WiFiduino -wifiduino.build.board=WIFIDUINO_ESP8266 -wifiduino.build.variant=wifiduino -wifiduino.upload.tool=esptool -wifiduino.upload.maximum_data_size=81920 -wifiduino.upload.wait_for_upload_port=true -wifiduino.upload.erase_cmd= -wifiduino.serial.disableDTR=true -wifiduino.serial.disableRTS=true -wifiduino.build.mcu=esp8266 -wifiduino.build.core=esp8266 -wifiduino.build.spiffs_pagesize=256 -wifiduino.build.debug_port= -wifiduino.build.debug_level= -wifiduino.menu.CpuFrequency.80=80 MHz -wifiduino.menu.CpuFrequency.80.build.f_cpu=80000000L -wifiduino.menu.CpuFrequency.160=160 MHz -wifiduino.menu.CpuFrequency.160.build.f_cpu=160000000L -wifiduino.menu.VTable.flash=Flash -wifiduino.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifiduino.menu.VTable.heap=Heap -wifiduino.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifiduino.menu.VTable.iram=IRAM -wifiduino.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifiduino.upload.resetmethod=nodemcu -wifiduino.build.flash_mode=dio -wifiduino.build.flash_freq=40 -wifiduino.menu.FlashSize.4M1M=4M (1M SPIFFS) -wifiduino.menu.FlashSize.4M1M.build.flash_size=4M -wifiduino.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -wifiduino.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -wifiduino.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -wifiduino.menu.FlashSize.4M1M.upload.maximum_size=1044464 -wifiduino.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -wifiduino.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -wifiduino.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -wifiduino.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -wifiduino.menu.FlashSize.4M2M=4M (2M SPIFFS) -wifiduino.menu.FlashSize.4M2M.build.flash_size=4M -wifiduino.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -wifiduino.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -wifiduino.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -wifiduino.menu.FlashSize.4M2M.upload.maximum_size=1044464 -wifiduino.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -wifiduino.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -wifiduino.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -wifiduino.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -wifiduino.menu.FlashSize.4M3M=4M (3M SPIFFS) -wifiduino.menu.FlashSize.4M3M.build.flash_size=4M -wifiduino.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -wifiduino.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -wifiduino.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -wifiduino.menu.FlashSize.4M3M.upload.maximum_size=1044464 -wifiduino.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -wifiduino.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -wifiduino.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -wifiduino.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -wifiduino.menu.LwIPVariant.v2mss536=v2 Lower Memory -wifiduino.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -wifiduino.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -wifiduino.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -wifiduino.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -wifiduino.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -wifiduino.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -wifiduino.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -wifiduino.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -wifiduino.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -wifiduino.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -wifiduino.menu.LwIPVariant.OpenSource=v1.4 Compile from source -wifiduino.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -wifiduino.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -wifiduino.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifiduino.menu.Debug.Disabled=Disabled -wifiduino.menu.Debug.Disabled.build.debug_port= -wifiduino.menu.Debug.Serial=Serial -wifiduino.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifiduino.menu.Debug.Serial1=Serial1 -wifiduino.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifiduino.menu.DebugLevel.None____=None -wifiduino.menu.DebugLevel.None____.build.debug_level= -wifiduino.menu.DebugLevel.SSL=SSL -wifiduino.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifiduino.menu.DebugLevel.TLS_MEM=TLS_MEM -wifiduino.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifiduino.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -wifiduino.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -wifiduino.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -wifiduino.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifiduino.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifiduino.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifiduino.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifiduino.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifiduino.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifiduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifiduino.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.DebugLevel.CORE=CORE -wifiduino.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifiduino.menu.DebugLevel.WIFI=WIFI -wifiduino.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifiduino.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -wifiduino.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifiduino.menu.DebugLevel.UPDATER=UPDATER -wifiduino.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifiduino.menu.DebugLevel.OTA=OTA -wifiduino.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifiduino.menu.DebugLevel.OOM=OOM -wifiduino.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifiduino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifiduino.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifiduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifiduino.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifiduino.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -wifiduino.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifiduino.menu.FlashErase.none=Only Sketch -wifiduino.menu.FlashErase.none.upload.erase_cmd= -wifiduino.menu.FlashErase.sdk=Sketch + WiFi Settings -wifiduino.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifiduino.menu.FlashErase.all=All Flash Contents -wifiduino.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifiduino.menu.UploadSpeed.921600=921600 -wifiduino.menu.UploadSpeed.921600.upload.speed=921600 -wifiduino.menu.UploadSpeed.9600=9600 -wifiduino.menu.UploadSpeed.9600.upload.speed=9600 -wifiduino.menu.UploadSpeed.57600=57600 -wifiduino.menu.UploadSpeed.57600.upload.speed=57600 -wifiduino.menu.UploadSpeed.115200=115200 -wifiduino.menu.UploadSpeed.115200.upload.speed=115200 -wifiduino.menu.UploadSpeed.230400.linux=230400 -wifiduino.menu.UploadSpeed.230400.macosx=230400 -wifiduino.menu.UploadSpeed.230400.upload.speed=230400 -wifiduino.menu.UploadSpeed.256000.windows=256000 -wifiduino.menu.UploadSpeed.256000.upload.speed=256000 -wifiduino.menu.UploadSpeed.460800.linux=460800 -wifiduino.menu.UploadSpeed.460800.macosx=460800 -wifiduino.menu.UploadSpeed.460800.upload.speed=460800 -wifiduino.menu.UploadSpeed.512000.windows=512000 -wifiduino.menu.UploadSpeed.512000.upload.speed=512000 - -############################################################## -wifi_slot.name=Amperka WiFi Slot -wifi_slot.build.board=AMPERKA_WIFI_SLOT -wifi_slot.build.variant=wifi_slot -wifi_slot.upload.tool=esptool -wifi_slot.upload.maximum_data_size=81920 -wifi_slot.upload.wait_for_upload_port=true -wifi_slot.upload.erase_cmd= -wifi_slot.serial.disableDTR=true -wifi_slot.serial.disableRTS=true -wifi_slot.build.mcu=esp8266 -wifi_slot.build.core=esp8266 -wifi_slot.build.spiffs_pagesize=256 -wifi_slot.build.debug_port= -wifi_slot.build.debug_level= -wifi_slot.menu.CpuFrequency.80=80 MHz -wifi_slot.menu.CpuFrequency.80.build.f_cpu=80000000L -wifi_slot.menu.CpuFrequency.160=160 MHz -wifi_slot.menu.CpuFrequency.160.build.f_cpu=160000000L -wifi_slot.menu.VTable.flash=Flash -wifi_slot.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifi_slot.menu.VTable.heap=Heap -wifi_slot.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifi_slot.menu.VTable.iram=IRAM -wifi_slot.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifi_slot.upload.resetmethod=nodemcu -wifi_slot.menu.FlashFreq.40=40MHz -wifi_slot.menu.FlashFreq.40.build.flash_freq=40 -wifi_slot.menu.FlashFreq.80=80MHz -wifi_slot.menu.FlashFreq.80.build.flash_freq=80 -wifi_slot.menu.FlashMode.qio=QIO -wifi_slot.menu.FlashMode.qio.build.flash_mode=qio -wifi_slot.menu.FlashMode.qout=QOUT -wifi_slot.menu.FlashMode.qout.build.flash_mode=qout -wifi_slot.menu.FlashMode.dio=DIO -wifi_slot.menu.FlashMode.dio.build.flash_mode=dio -wifi_slot.menu.FlashMode.dout=DOUT -wifi_slot.menu.FlashMode.dout.build.flash_mode=dout -wifi_slot.menu.FlashSize.1M0=1M (no SPIFFS) -wifi_slot.menu.FlashSize.1M0.build.flash_size=1M -wifi_slot.menu.FlashSize.1M0.build.flash_size_bytes=0x100000 -wifi_slot.menu.FlashSize.1M0.build.flash_ld=eagle.flash.1m0.ld -wifi_slot.menu.FlashSize.1M0.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.1M0.upload.maximum_size=1023984 -wifi_slot.menu.FlashSize.1M0.build.rfcal_addr=0xFC000 -wifi_slot.menu.FlashSize.1M64=1M (64K SPIFFS) -wifi_slot.menu.FlashSize.1M64.build.flash_size=1M -wifi_slot.menu.FlashSize.1M64.build.flash_size_bytes=0x100000 -wifi_slot.menu.FlashSize.1M64.build.flash_ld=eagle.flash.1m64.ld -wifi_slot.menu.FlashSize.1M64.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.1M64.upload.maximum_size=958448 -wifi_slot.menu.FlashSize.1M64.build.rfcal_addr=0xFC000 -wifi_slot.menu.FlashSize.1M64.build.spiffs_start=0xEB000 -wifi_slot.menu.FlashSize.1M64.build.spiffs_end=0xFB000 -wifi_slot.menu.FlashSize.1M64.build.spiffs_blocksize=4096 -wifi_slot.menu.FlashSize.1M128=1M (128K SPIFFS) -wifi_slot.menu.FlashSize.1M128.build.flash_size=1M -wifi_slot.menu.FlashSize.1M128.build.flash_size_bytes=0x100000 -wifi_slot.menu.FlashSize.1M128.build.flash_ld=eagle.flash.1m128.ld -wifi_slot.menu.FlashSize.1M128.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.1M128.upload.maximum_size=892912 -wifi_slot.menu.FlashSize.1M128.build.rfcal_addr=0xFC000 -wifi_slot.menu.FlashSize.1M128.build.spiffs_start=0xDB000 -wifi_slot.menu.FlashSize.1M128.build.spiffs_end=0xFB000 -wifi_slot.menu.FlashSize.1M128.build.spiffs_blocksize=4096 -wifi_slot.menu.FlashSize.1M144=1M (144K SPIFFS) -wifi_slot.menu.FlashSize.1M144.build.flash_size=1M -wifi_slot.menu.FlashSize.1M144.build.flash_size_bytes=0x100000 -wifi_slot.menu.FlashSize.1M144.build.flash_ld=eagle.flash.1m144.ld -wifi_slot.menu.FlashSize.1M144.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.1M144.upload.maximum_size=876528 -wifi_slot.menu.FlashSize.1M144.build.rfcal_addr=0xFC000 -wifi_slot.menu.FlashSize.1M144.build.spiffs_start=0xD7000 -wifi_slot.menu.FlashSize.1M144.build.spiffs_end=0xFB000 -wifi_slot.menu.FlashSize.1M144.build.spiffs_blocksize=4096 -wifi_slot.menu.FlashSize.1M160=1M (160K SPIFFS) -wifi_slot.menu.FlashSize.1M160.build.flash_size=1M -wifi_slot.menu.FlashSize.1M160.build.flash_size_bytes=0x100000 -wifi_slot.menu.FlashSize.1M160.build.flash_ld=eagle.flash.1m160.ld -wifi_slot.menu.FlashSize.1M160.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.1M160.upload.maximum_size=860144 -wifi_slot.menu.FlashSize.1M160.build.rfcal_addr=0xFC000 -wifi_slot.menu.FlashSize.1M160.build.spiffs_start=0xD3000 -wifi_slot.menu.FlashSize.1M160.build.spiffs_end=0xFB000 -wifi_slot.menu.FlashSize.1M160.build.spiffs_blocksize=4096 -wifi_slot.menu.FlashSize.1M192=1M (192K SPIFFS) -wifi_slot.menu.FlashSize.1M192.build.flash_size=1M -wifi_slot.menu.FlashSize.1M192.build.flash_size_bytes=0x100000 -wifi_slot.menu.FlashSize.1M192.build.flash_ld=eagle.flash.1m192.ld -wifi_slot.menu.FlashSize.1M192.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.1M192.upload.maximum_size=827376 -wifi_slot.menu.FlashSize.1M192.build.rfcal_addr=0xFC000 -wifi_slot.menu.FlashSize.1M192.build.spiffs_start=0xCB000 -wifi_slot.menu.FlashSize.1M192.build.spiffs_end=0xFB000 -wifi_slot.menu.FlashSize.1M192.build.spiffs_blocksize=4096 -wifi_slot.menu.FlashSize.1M256=1M (256K SPIFFS) -wifi_slot.menu.FlashSize.1M256.build.flash_size=1M -wifi_slot.menu.FlashSize.1M256.build.flash_size_bytes=0x100000 -wifi_slot.menu.FlashSize.1M256.build.flash_ld=eagle.flash.1m256.ld -wifi_slot.menu.FlashSize.1M256.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.1M256.upload.maximum_size=761840 -wifi_slot.menu.FlashSize.1M256.build.rfcal_addr=0xFC000 -wifi_slot.menu.FlashSize.1M256.build.spiffs_start=0xBB000 -wifi_slot.menu.FlashSize.1M256.build.spiffs_end=0xFB000 -wifi_slot.menu.FlashSize.1M256.build.spiffs_blocksize=4096 -wifi_slot.menu.FlashSize.1M512=1M (512K SPIFFS) -wifi_slot.menu.FlashSize.1M512.build.flash_size=1M -wifi_slot.menu.FlashSize.1M512.build.flash_size_bytes=0x100000 -wifi_slot.menu.FlashSize.1M512.build.flash_ld=eagle.flash.1m512.ld -wifi_slot.menu.FlashSize.1M512.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.1M512.upload.maximum_size=499696 -wifi_slot.menu.FlashSize.1M512.build.rfcal_addr=0xFC000 -wifi_slot.menu.FlashSize.1M512.build.spiffs_start=0x7B000 -wifi_slot.menu.FlashSize.1M512.build.spiffs_end=0xFB000 -wifi_slot.menu.FlashSize.1M512.build.spiffs_blocksize=8192 -wifi_slot.menu.FlashSize.2M=2M (1M SPIFFS) -wifi_slot.menu.FlashSize.2M.build.flash_size=2M -wifi_slot.menu.FlashSize.2M.build.flash_size_bytes=0x200000 -wifi_slot.menu.FlashSize.2M.build.flash_ld=eagle.flash.2m.ld -wifi_slot.menu.FlashSize.2M.build.spiffs_pagesize=256 -wifi_slot.menu.FlashSize.2M.upload.maximum_size=1044464 -wifi_slot.menu.FlashSize.2M.build.rfcal_addr=0x1FC000 -wifi_slot.menu.FlashSize.2M.build.spiffs_start=0x100000 -wifi_slot.menu.FlashSize.2M.build.spiffs_end=0x1FB000 -wifi_slot.menu.FlashSize.2M.build.spiffs_blocksize=8192 -wifi_slot.menu.LwIPVariant.v2mss536=v2 Lower Memory -wifi_slot.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -wifi_slot.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -wifi_slot.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -wifi_slot.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -wifi_slot.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -wifi_slot.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -wifi_slot.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -wifi_slot.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -wifi_slot.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -wifi_slot.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -wifi_slot.menu.LwIPVariant.OpenSource=v1.4 Compile from source -wifi_slot.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -wifi_slot.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -wifi_slot.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifi_slot.menu.Debug.Disabled=Disabled -wifi_slot.menu.Debug.Disabled.build.debug_port= -wifi_slot.menu.Debug.Serial=Serial -wifi_slot.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifi_slot.menu.Debug.Serial1=Serial1 -wifi_slot.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifi_slot.menu.DebugLevel.None____=None -wifi_slot.menu.DebugLevel.None____.build.debug_level= -wifi_slot.menu.DebugLevel.SSL=SSL -wifi_slot.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifi_slot.menu.DebugLevel.TLS_MEM=TLS_MEM -wifi_slot.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifi_slot.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -wifi_slot.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -wifi_slot.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -wifi_slot.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifi_slot.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifi_slot.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifi_slot.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifi_slot.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifi_slot.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifi_slot.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifi_slot.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.DebugLevel.CORE=CORE -wifi_slot.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifi_slot.menu.DebugLevel.WIFI=WIFI -wifi_slot.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifi_slot.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -wifi_slot.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifi_slot.menu.DebugLevel.UPDATER=UPDATER -wifi_slot.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifi_slot.menu.DebugLevel.OTA=OTA -wifi_slot.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifi_slot.menu.DebugLevel.OOM=OOM -wifi_slot.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifi_slot.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifi_slot.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifi_slot.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wifi_slot.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wifi_slot.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -wifi_slot.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifi_slot.menu.FlashErase.none=Only Sketch -wifi_slot.menu.FlashErase.none.upload.erase_cmd= -wifi_slot.menu.FlashErase.sdk=Sketch + WiFi Settings -wifi_slot.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wifi_slot.menu.FlashErase.all=All Flash Contents -wifi_slot.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wifi_slot.menu.UploadSpeed.115200=115200 -wifi_slot.menu.UploadSpeed.115200.upload.speed=115200 -wifi_slot.menu.UploadSpeed.9600=9600 -wifi_slot.menu.UploadSpeed.9600.upload.speed=9600 -wifi_slot.menu.UploadSpeed.57600=57600 -wifi_slot.menu.UploadSpeed.57600.upload.speed=57600 -wifi_slot.menu.UploadSpeed.230400.linux=230400 -wifi_slot.menu.UploadSpeed.230400.macosx=230400 -wifi_slot.menu.UploadSpeed.230400.upload.speed=230400 -wifi_slot.menu.UploadSpeed.256000.windows=256000 -wifi_slot.menu.UploadSpeed.256000.upload.speed=256000 -wifi_slot.menu.UploadSpeed.460800.linux=460800 -wifi_slot.menu.UploadSpeed.460800.macosx=460800 -wifi_slot.menu.UploadSpeed.460800.upload.speed=460800 -wifi_slot.menu.UploadSpeed.512000.windows=512000 -wifi_slot.menu.UploadSpeed.512000.upload.speed=512000 -wifi_slot.menu.UploadSpeed.921600=921600 -wifi_slot.menu.UploadSpeed.921600.upload.speed=921600 - -############################################################## -wiolink.name=Seeed Wio Link -wiolink.build.board=ESP8266_WIO_LINK -wiolink.build.variant=wiolink -wiolink.upload.tool=esptool -wiolink.upload.maximum_data_size=81920 -wiolink.upload.wait_for_upload_port=true -wiolink.upload.erase_cmd= -wiolink.serial.disableDTR=true -wiolink.serial.disableRTS=true -wiolink.build.mcu=esp8266 -wiolink.build.core=esp8266 -wiolink.build.spiffs_pagesize=256 -wiolink.build.debug_port= -wiolink.build.debug_level= -wiolink.menu.CpuFrequency.80=80 MHz -wiolink.menu.CpuFrequency.80.build.f_cpu=80000000L -wiolink.menu.CpuFrequency.160=160 MHz -wiolink.menu.CpuFrequency.160.build.f_cpu=160000000L -wiolink.menu.VTable.flash=Flash -wiolink.menu.VTable.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wiolink.menu.VTable.heap=Heap -wiolink.menu.VTable.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wiolink.menu.VTable.iram=IRAM -wiolink.menu.VTable.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wiolink.upload.resetmethod=nodemcu -wiolink.build.flash_mode=qio -wiolink.build.flash_freq=40 -wiolink.menu.FlashSize.4M1M=4M (1M SPIFFS) -wiolink.menu.FlashSize.4M1M.build.flash_size=4M -wiolink.menu.FlashSize.4M1M.build.flash_size_bytes=0x400000 -wiolink.menu.FlashSize.4M1M.build.flash_ld=eagle.flash.4m1m.ld -wiolink.menu.FlashSize.4M1M.build.spiffs_pagesize=256 -wiolink.menu.FlashSize.4M1M.upload.maximum_size=1044464 -wiolink.menu.FlashSize.4M1M.build.rfcal_addr=0x3FC000 -wiolink.menu.FlashSize.4M1M.build.spiffs_start=0x300000 -wiolink.menu.FlashSize.4M1M.build.spiffs_end=0x3FB000 -wiolink.menu.FlashSize.4M1M.build.spiffs_blocksize=8192 -wiolink.menu.FlashSize.4M2M=4M (2M SPIFFS) -wiolink.menu.FlashSize.4M2M.build.flash_size=4M -wiolink.menu.FlashSize.4M2M.build.flash_size_bytes=0x400000 -wiolink.menu.FlashSize.4M2M.build.flash_ld=eagle.flash.4m2m.ld -wiolink.menu.FlashSize.4M2M.build.spiffs_pagesize=256 -wiolink.menu.FlashSize.4M2M.upload.maximum_size=1044464 -wiolink.menu.FlashSize.4M2M.build.rfcal_addr=0x3FC000 -wiolink.menu.FlashSize.4M2M.build.spiffs_start=0x200000 -wiolink.menu.FlashSize.4M2M.build.spiffs_end=0x3FB000 -wiolink.menu.FlashSize.4M2M.build.spiffs_blocksize=8192 -wiolink.menu.FlashSize.4M3M=4M (3M SPIFFS) -wiolink.menu.FlashSize.4M3M.build.flash_size=4M -wiolink.menu.FlashSize.4M3M.build.flash_size_bytes=0x400000 -wiolink.menu.FlashSize.4M3M.build.flash_ld=eagle.flash.4m.ld -wiolink.menu.FlashSize.4M3M.build.spiffs_pagesize=256 -wiolink.menu.FlashSize.4M3M.upload.maximum_size=1044464 -wiolink.menu.FlashSize.4M3M.build.rfcal_addr=0x3FC000 -wiolink.menu.FlashSize.4M3M.build.spiffs_start=0x100000 -wiolink.menu.FlashSize.4M3M.build.spiffs_end=0x3FB000 -wiolink.menu.FlashSize.4M3M.build.spiffs_blocksize=8192 -wiolink.menu.LwIPVariant.v2mss536=v2 Lower Memory -wiolink.menu.LwIPVariant.v2mss536.build.lwip_include=lwip2/include -wiolink.menu.LwIPVariant.v2mss536.build.lwip_lib=-llwip2 -wiolink.menu.LwIPVariant.v2mss536.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -wiolink.menu.LwIPVariant.v2mss1460=v2 Higher Bandwidth -wiolink.menu.LwIPVariant.v2mss1460.build.lwip_include=lwip2/include -wiolink.menu.LwIPVariant.v2mss1460.build.lwip_lib=-llwip2_1460 -wiolink.menu.LwIPVariant.v2mss1460.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -wiolink.menu.LwIPVariant.Prebuilt=v1.4 Higher Bandwidth -wiolink.menu.LwIPVariant.Prebuilt.build.lwip_lib=-llwip_gcc -wiolink.menu.LwIPVariant.Prebuilt.build.lwip_flags=-DLWIP_OPEN_SRC -wiolink.menu.LwIPVariant.OpenSource=v1.4 Compile from source -wiolink.menu.LwIPVariant.OpenSource.build.lwip_lib=-llwip_src -wiolink.menu.LwIPVariant.OpenSource.build.lwip_flags=-DLWIP_OPEN_SRC -wiolink.menu.LwIPVariant.OpenSource.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wiolink.menu.Debug.Disabled=Disabled -wiolink.menu.Debug.Disabled.build.debug_port= -wiolink.menu.Debug.Serial=Serial -wiolink.menu.Debug.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wiolink.menu.Debug.Serial1=Serial1 -wiolink.menu.Debug.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wiolink.menu.DebugLevel.None____=None -wiolink.menu.DebugLevel.None____.build.debug_level= -wiolink.menu.DebugLevel.SSL=SSL -wiolink.menu.DebugLevel.SSL.build.debug_level= -DDEBUG_ESP_SSL -wiolink.menu.DebugLevel.TLS_MEM=TLS_MEM -wiolink.menu.DebugLevel.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wiolink.menu.DebugLevel.HTTP_CLIENT=HTTP_CLIENT -wiolink.menu.DebugLevel.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.DebugLevel.HTTP_SERVER=HTTP_SERVER -wiolink.menu.DebugLevel.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.DebugLevel.SSLTLS_MEM=SSL+TLS_MEM -wiolink.menu.DebugLevel.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wiolink.menu.DebugLevel.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wiolink.menu.DebugLevel.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.DebugLevel.SSLHTTP_SERVER=SSL+HTTP_SERVER -wiolink.menu.DebugLevel.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.DebugLevel.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wiolink.menu.DebugLevel.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.DebugLevel.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wiolink.menu.DebugLevel.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wiolink.menu.DebugLevel.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wiolink.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wiolink.menu.DebugLevel.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.DebugLevel.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.DebugLevel.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.DebugLevel.CORE=CORE -wiolink.menu.DebugLevel.CORE.build.debug_level= -DDEBUG_ESP_CORE -wiolink.menu.DebugLevel.WIFI=WIFI -wiolink.menu.DebugLevel.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wiolink.menu.DebugLevel.HTTP_UPDATE=HTTP_UPDATE -wiolink.menu.DebugLevel.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wiolink.menu.DebugLevel.UPDATER=UPDATER -wiolink.menu.DebugLevel.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wiolink.menu.DebugLevel.OTA=OTA -wiolink.menu.DebugLevel.OTA.build.debug_level= -DDEBUG_ESP_OTA -wiolink.menu.DebugLevel.OOM=OOM -wiolink.menu.DebugLevel.OOM.build.debug_level= -DDEBUG_ESP_OOM -wiolink.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wiolink.menu.DebugLevel.COREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wiolink.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM -wiolink.menu.DebugLevel.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -wiolink.menu.DebugLevel.NoAssert-NDEBUG=NoAssert-NDEBUG -wiolink.menu.DebugLevel.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wiolink.menu.FlashErase.none=Only Sketch -wiolink.menu.FlashErase.none.upload.erase_cmd= -wiolink.menu.FlashErase.sdk=Sketch + WiFi Settings -wiolink.menu.FlashErase.sdk.upload.erase_cmd=-ca "{build.rfcal_addr}" -cz 0x4000 -wiolink.menu.FlashErase.all=All Flash Contents -wiolink.menu.FlashErase.all.upload.erase_cmd=-ca 0x0 -cz "{build.flash_size_bytes}" -wiolink.menu.UploadSpeed.115200=115200 -wiolink.menu.UploadSpeed.115200.upload.speed=115200 -wiolink.menu.UploadSpeed.9600=9600 -wiolink.menu.UploadSpeed.9600.upload.speed=9600 -wiolink.menu.UploadSpeed.57600=57600 -wiolink.menu.UploadSpeed.57600.upload.speed=57600 -wiolink.menu.UploadSpeed.230400.linux=230400 -wiolink.menu.UploadSpeed.230400.macosx=230400 -wiolink.menu.UploadSpeed.230400.upload.speed=230400 -wiolink.menu.UploadSpeed.256000.windows=256000 -wiolink.menu.UploadSpeed.256000.upload.speed=256000 -wiolink.menu.UploadSpeed.460800.linux=460800 -wiolink.menu.UploadSpeed.460800.macosx=460800 -wiolink.menu.UploadSpeed.460800.upload.speed=460800 -wiolink.menu.UploadSpeed.512000.windows=512000 -wiolink.menu.UploadSpeed.512000.upload.speed=512000 -wiolink.menu.UploadSpeed.921600=921600 -wiolink.menu.UploadSpeed.921600.upload.speed=921600 - From d8e43829bc5501c561be4ba47ffa91bf8a28780b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 29 Feb 2020 14:36:31 +0100 Subject: [PATCH 527/559] Delete platform.txt --- arduino/version 2.4.2/platform.txt | 143 ----------------------------- 1 file changed, 143 deletions(-) delete mode 100644 arduino/version 2.4.2/platform.txt diff --git a/arduino/version 2.4.2/platform.txt b/arduino/version 2.4.2/platform.txt deleted file mode 100644 index 097ec545c..000000000 --- a/arduino/version 2.4.2/platform.txt +++ /dev/null @@ -1,143 +0,0 @@ - -# ESP8266 platform -# ------------------------------ - -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification - -name=ESP8266 Modules -version=2.4.2 - - - - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -compiler.warning_flags.more=-Wall -compiler.warning_flags.all=-Wall -Wextra - -build.lwip_lib=-llwip_gcc -build.lwip_include=lwip/include -build.lwip_flags=-DLWIP_OPEN_SRC - -build.vtable_flags=-DVTABLES_IN_FLASH - -#build.float=-u _printf_float -u _scanf_float -build.float= -build.led= -build.noextra4kheap= - -compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ -compiler.sdk.path={runtime.platform.path}/tools/sdk -compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf -compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" - -compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} {build.noextra4kheap} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections - -compiler.S.cmd=xtensa-lx106-elf-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls - -compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read - -compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 -lstdc++ -lm -lc -lgcc - -compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} {build.noextra4kheap} -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections - -compiler.as.cmd=xtensa-lx106-elf-as - -compiler.ar.cmd=xtensa-lx106-elf-ar -compiler.ar.flags=cru - -compiler.elf2hex.cmd=esptool -compiler.elf2hex.flags= - -compiler.size.cmd=xtensa-lx106-elf-size - -compiler.esptool.cmd=esptool -compiler.esptool.cmd.windows=esptool.exe - -# This can be overriden in boards.txt -build.extra_flags=-DESP8266 - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -## generate file with git version number -## needs bash, git, and echo - - -## windows-compatible version without git - - - -## Build the app.ld linker file -recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld" - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/arduino.ar" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{build.path}/arduino.ar" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" - -## Create eeprom -recipe.objcopy.eep.pattern= - -## Create hex -#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" - -recipe.objcopy.hex.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec - -## Save hex -recipe.output.tmp_file={build.project_name}.bin -recipe.output.save_file={build.project_name}.{build.variant}.bin - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* -#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - -# ------------------------------ - -tools.esptool.cmd=esptool -tools.esptool.cmd.windows=esptool.exe -tools.esptool.path={runtime.tools.esptool.path} -tools.esptool.network_cmd=python -tools.esptool.network_cmd.windows=python.exe - -tools.esptool.upload.protocol=esp -tools.esptool.upload.params.verbose=-vv -tools.esptool.upload.params.quiet= -tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin" -tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" - -tools.mkspiffs.cmd=mkspiffs -tools.mkspiffs.cmd.windows=mkspiffs.exe -tools.mkspiffs.path={runtime.tools.mkspiffs.path} - -tools.espupload.cmd=python -tools.espupload.cmd.windows=python.exe -tools.espupload.path={runtime.platform.path}/tools -tools.espupload.upload.protocol=espupload -tools.espupload.upload.params.verbose= -tools.espupload.upload.params.quiet= -tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" From 9b8b8ca376d19963cb8160020665d2e21830a0fe Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 29 Feb 2020 14:39:23 +0100 Subject: [PATCH 528/559] Delete esp8266.flash.1m0.ld --- esp8266.flash.1m0.ld | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 esp8266.flash.1m0.ld diff --git a/esp8266.flash.1m0.ld b/esp8266.flash.1m0.ld deleted file mode 100644 index 1f9b56a87..000000000 --- a/esp8266.flash.1m0.ld +++ /dev/null @@ -1,18 +0,0 @@ -/* Flash Split for 1M chips */ -/* sketch 999KB */ -/* eeprom 20KB */ - -MEMORY -{ - dport0_0_seg : org = 0x3FF00000, len = 0x10 - dram0_0_seg : org = 0x3FFE8000, len = 0x14000 - iram1_0_seg : org = 0x40100000, len = 0x8000 - irom0_0_seg : org = 0x40201010, len = 0xf9ff0 -} - -PROVIDE ( _SPIFFS_start = 0x402FB000 ); -PROVIDE ( _SPIFFS_end = 0x402FB000 ); -PROVIDE ( _SPIFFS_page = 0 ); -PROVIDE ( _SPIFFS_block = 0 ); - -INCLUDE "esp8266.flash.common.ld" From 94dbc4d1a220489a5440aaf80ac279ae67deedbc Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sat, 29 Feb 2020 16:11:59 +0100 Subject: [PATCH 529/559] refactor TX2x sensor driver --- API.md | 2 +- BUILDS.md | 2 +- tasmota/language/bg-BG.h | 2 - tasmota/language/cs-CZ.h | 2 - tasmota/language/de-DE.h | 2 - tasmota/language/el-GR.h | 2 - tasmota/language/en-GB.h | 2 - tasmota/language/es-ES.h | 2 - tasmota/language/fr-FR.h | 2 - tasmota/language/he-HE.h | 2 - tasmota/language/hu-HU.h | 2 - tasmota/language/it-IT.h | 2 - tasmota/language/ko-KO.h | 2 - tasmota/language/nl-NL.h | 2 - tasmota/language/pl-PL.h | 2 - tasmota/language/pt-BR.h | 2 - tasmota/language/pt-PT.h | 2 - tasmota/language/ru-RU.h | 2 - tasmota/language/sk-SK.h | 2 - tasmota/language/sv-SE.h | 2 - tasmota/language/tr-TR.h | 2 - tasmota/language/uk-UA.h | 2 - tasmota/language/zh-CN.h | 2 - tasmota/language/zh-TW.h | 2 - tasmota/my_user_config.h | 4 +- tasmota/support_tasmota.ino | 1 + tasmota/tasmota_post.h | 4 +- tasmota/xsns_35_tx20.ino | 418 ++++++++++++++++++++++++++++-------- 28 files changed, 336 insertions(+), 139 deletions(-) diff --git a/API.md b/API.md index 354382cfc..f10ae2c93 100644 --- a/API.md +++ b/API.md @@ -25,7 +25,7 @@ FUNC_EVERY_250_MSECOND | | 1 | 3 | 2 | | FUNC_EVERY_SECOND | | 1 | 2 | | | FUNC_SAVE_AT_MIDNIGHT | | | x | | | At midnight FUNC_SAVE_BEFORE_RESTART | | 2 | 1 | | | Just before a planned restart -FUNC_AFTER_TELEPERIOD | | x | | | | At end of teleperiod +FUNC_AFTER_TELEPERIOD | | 2 | 1 | | | At end of teleperiod FUNC_JSON_APPEND | | 2 | 1 | 3 | | Extend teleperiod JSON text FUNC_WEB_SENSOR | | 2 | 1 | 3 | | Add sensor data to web GUI FUNC_COMMAND | x | 1 | 2 | 3 | 4 | When a command is not recognized diff --git a/BUILDS.md b/BUILDS.md index d2ca20438..f09de3125 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -142,7 +142,7 @@ | USE_SR04 | - | - | - | - | x | - | - | | USE_TM1638 | - | - | - | - | x | - | - | | USE_HX711 | - | - | - | - | x | - | - | -| USE_TX20_WIND_SENSOR | - | - | - | - | x | - | - | +| USE_TX2x_WIND_SENSOR | - | - | - | - | - | - | - | | USE_RC_SWITCH | - | - | - | - | x | - | - | | USE_RF_SENSOR | - | - | - | - | x | - | - | AlectoV2 only | USE_HRE | - | - | - | - | x | - | - | diff --git a/tasmota/language/bg-BG.h b/tasmota/language/bg-BG.h index 9a6ce8abc..b2b151644 100644 --- a/tasmota/language/bg-BG.h +++ b/tasmota/language/bg-BG.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Посока на вятъра" -#define D_TX20_WIND_DEGREES "Степени на вятъра" #define D_TX20_WIND_SPEED "Скорост на вятъра" -#define D_TX20_WIND_SPEED_AVG "Средна скорост на вятъра" #define D_TX20_WIND_SPEED_MIN "Мини. скорост на вятъра" #define D_TX20_WIND_SPEED_MAX "Макс. скорост на вятъра" #define D_TX20_NORTH "С" diff --git a/tasmota/language/cs-CZ.h b/tasmota/language/cs-CZ.h index d98361640..332a45920 100644 --- a/tasmota/language/cs-CZ.h +++ b/tasmota/language/cs-CZ.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Směr větru" -#define D_TX20_WIND_DEGREES "Úhel větru" #define D_TX20_WIND_SPEED "Rychlost větru" -#define D_TX20_WIND_SPEED_AVG "Průměrná rychlost větru" #define D_TX20_WIND_SPEED_MIN "Minimální rychlost větru" #define D_TX20_WIND_SPEED_MAX "Maximální rychlost větru" #define D_TX20_NORTH "S" diff --git a/tasmota/language/de-DE.h b/tasmota/language/de-DE.h index 05835a49c..1f534f27f 100644 --- a/tasmota/language/de-DE.h +++ b/tasmota/language/de-DE.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Windrichtung" -#define D_TX20_WIND_DEGREES "Windrichtung Grad" #define D_TX20_WIND_SPEED "Windgeschwindigkeit" -#define D_TX20_WIND_SPEED_AVG "Windgeschwindigkeit Ø" #define D_TX20_WIND_SPEED_MIN "Windgeschwindigkeit Min" #define D_TX20_WIND_SPEED_MAX "Windgeschwindigkeit Max" #define D_TX20_NORTH "N" diff --git a/tasmota/language/el-GR.h b/tasmota/language/el-GR.h index 0ddd43918..fc540043e 100644 --- a/tasmota/language/el-GR.h +++ b/tasmota/language/el-GR.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Κατεύθυνση ανέμου" -#define D_TX20_WIND_DEGREES "Βαθμός ανέμου" #define D_TX20_WIND_SPEED "Ταχύτητα ανέμου" -#define D_TX20_WIND_SPEED_AVG "Μέση ταχύτητα ανέμου" #define D_TX20_WIND_SPEED_MIN "Ελάχιστη ταχύτητα ανέμου" #define D_TX20_WIND_SPEED_MAX "Μέγιστη ταχύτητα ανέμου" #define D_TX20_NORTH "Β" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index b175cc193..e5a82f411 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_DEGREES "Wind Degrees" #define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" #define D_TX20_WIND_SPEED_MIN "Wind Speed Min" #define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_NORTH "N" diff --git a/tasmota/language/es-ES.h b/tasmota/language/es-ES.h index 12e732bc2..9331a3f62 100644 --- a/tasmota/language/es-ES.h +++ b/tasmota/language/es-ES.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Dirección del Viento" -#define D_TX20_WIND_DEGREES "Ángulo del Viento" #define D_TX20_WIND_SPEED "Vel. del Viento" -#define D_TX20_WIND_SPEED_AVG "Vel. Prom. del Viento" #define D_TX20_WIND_SPEED_MIN "Vel. Min. del Viento" #define D_TX20_WIND_SPEED_MAX "Vel. Max. del Viento" #define D_TX20_NORTH "N" diff --git a/tasmota/language/fr-FR.h b/tasmota/language/fr-FR.h index e9c31da46..1ca53402e 100644 --- a/tasmota/language/fr-FR.h +++ b/tasmota/language/fr-FR.h @@ -504,9 +504,7 @@ //xsns_35_TX20.ino #define D_TX20_WIND_DIRECTION "Direction du vent" -#define D_TX20_WIND_DEGREES "Degré de vent" #define D_TX20_WIND_SPEED "Vitesse du vent" -#define D_TX20_WIND_SPEED_AVG "Vitesse Moy." #define D_TX20_WIND_SPEED_MIN "Vitesse Min" #define D_TX20_WIND_SPEED_MAX "Vitesse Max" #define D_TX20_NORTH "N" diff --git a/tasmota/language/he-HE.h b/tasmota/language/he-HE.h index f836a92b9..a8f3ba572 100644 --- a/tasmota/language/he-HE.h +++ b/tasmota/language/he-HE.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "כיוון הרוח" -#define D_TX20_WIND_DEGREES "זווית הרוח" #define D_TX20_WIND_SPEED "מהירות הרוח" -#define D_TX20_WIND_SPEED_AVG "מהירות הרוח ממוצעת" #define D_TX20_WIND_SPEED_MIN "מהירות הרוח היא מינימלית" #define D_TX20_WIND_SPEED_MAX "מהירות הרוח מקסימלית" #define D_TX20_NORTH "N" diff --git a/tasmota/language/hu-HU.h b/tasmota/language/hu-HU.h index da313caaa..2d888bd81 100644 --- a/tasmota/language/hu-HU.h +++ b/tasmota/language/hu-HU.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Szélirány" -#define D_TX20_WIND_DEGREES "Szél mértéke" #define D_TX20_WIND_SPEED "Szélsebesség" -#define D_TX20_WIND_SPEED_AVG "Átlag szélsebesség" #define D_TX20_WIND_SPEED_MIN "Min. szélsebesség" #define D_TX20_WIND_SPEED_MAX "Max. szélsebesség" #define D_TX20_NORTH "É" diff --git a/tasmota/language/it-IT.h b/tasmota/language/it-IT.h index efaecc1a5..3ec7e9773 100644 --- a/tasmota/language/it-IT.h +++ b/tasmota/language/it-IT.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Direzione Vento" -#define D_TX20_WIND_DEGREES "Angolo Vento" #define D_TX20_WIND_SPEED "Velocità Vento" -#define D_TX20_WIND_SPEED_AVG "Velocità Media Vento" #define D_TX20_WIND_SPEED_MIN "Velocità Minima Vento" #define D_TX20_WIND_SPEED_MAX "Velocità Massima Vento" #define D_TX20_NORTH "N" diff --git a/tasmota/language/ko-KO.h b/tasmota/language/ko-KO.h index 794b97e84..2377fadb1 100644 --- a/tasmota/language/ko-KO.h +++ b/tasmota/language/ko-KO.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "풍향" -#define D_TX20_WIND_DEGREES "바람 정도" #define D_TX20_WIND_SPEED "풍속" -#define D_TX20_WIND_SPEED_AVG "평균 풍속" #define D_TX20_WIND_SPEED_MIN "풍속 최소" #define D_TX20_WIND_SPEED_MAX "풍속 최대" #define D_TX20_NORTH "N" diff --git a/tasmota/language/nl-NL.h b/tasmota/language/nl-NL.h index 288da67d5..24bdc17e6 100644 --- a/tasmota/language/nl-NL.h +++ b/tasmota/language/nl-NL.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Windrichting" -#define D_TX20_WIND_DEGREES "Wind graad" #define D_TX20_WIND_SPEED "Windsnelheid" -#define D_TX20_WIND_SPEED_AVG "Windsnelheid gemiddeld" #define D_TX20_WIND_SPEED_MIN "Windsnelhied minimum" #define D_TX20_WIND_SPEED_MAX "Windsnelhied maximaal" #define D_TX20_NORTH "N" diff --git a/tasmota/language/pl-PL.h b/tasmota/language/pl-PL.h index e15ccbbc2..c96df7c95 100644 --- a/tasmota/language/pl-PL.h +++ b/tasmota/language/pl-PL.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Kierunek" -#define D_TX20_WIND_DEGREES "Grad" #define D_TX20_WIND_SPEED "Prędkość" -#define D_TX20_WIND_SPEED_AVG "Średnia prędkość" #define D_TX20_WIND_SPEED_MIN "Minimalna prędkość" #define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość" #define D_TX20_NORTH "N" diff --git a/tasmota/language/pt-BR.h b/tasmota/language/pt-BR.h index 9b24d05c8..38c1e4b48 100644 --- a/tasmota/language/pt-BR.h +++ b/tasmota/language/pt-BR.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Direção do vento" -#define D_TX20_WIND_DEGREES "Ângulo do vento" #define D_TX20_WIND_SPEED "Velocidade do vento" -#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" #define D_TX20_WIND_SPEED_MIN "Velocidade do vento Mínima" #define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima" #define D_TX20_NORTH "N" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 9565fc7a5..4ed7d874d 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Direção do vento" -#define D_TX20_WIND_DEGREES "Ângulo do vento" #define D_TX20_WIND_SPEED "Velocidade do vento" -#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento" #define D_TX20_WIND_SPEED_MIN "Velocidade mínima do vento" #define D_TX20_WIND_SPEED_MAX "Velocidade máxima do vento" #define D_TX20_NORTH "N" diff --git a/tasmota/language/ru-RU.h b/tasmota/language/ru-RU.h index 700958875..92307ba89 100644 --- a/tasmota/language/ru-RU.h +++ b/tasmota/language/ru-RU.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_DEGREES "Wind Degrees" #define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" #define D_TX20_WIND_SPEED_MIN "Wind Speed Min" #define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_NORTH "N" diff --git a/tasmota/language/sk-SK.h b/tasmota/language/sk-SK.h index dbee001e9..327b4c11f 100644 --- a/tasmota/language/sk-SK.h +++ b/tasmota/language/sk-SK.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Smer vetra" -#define D_TX20_WIND_DEGREES "Uhol vetra" #define D_TX20_WIND_SPEED "Rýchlosť vetra" -#define D_TX20_WIND_SPEED_AVG "Priemerná rýchlosť vetra" #define D_TX20_WIND_SPEED_MIN "Minimálna rýchlosť vetra" #define D_TX20_WIND_SPEED_MAX "Maximálna rýchlosť vetra" #define D_TX20_NORTH "S" diff --git a/tasmota/language/sv-SE.h b/tasmota/language/sv-SE.h index a8e5aa6a8..30434d696 100644 --- a/tasmota/language/sv-SE.h +++ b/tasmota/language/sv-SE.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Vindriktning" -#define D_TX20_WIND_DEGREES "Vindvinkel" #define D_TX20_WIND_SPEED "Vindstyrka" -#define D_TX20_WIND_SPEED_AVG "Vindstyrka medel" #define D_TX20_WIND_SPEED_MIN "Vindstyrka min" #define D_TX20_WIND_SPEED_MAX "Vindstyrka max" #define D_TX20_NORTH "N" diff --git a/tasmota/language/tr-TR.h b/tasmota/language/tr-TR.h index 430289372..637899101 100644 --- a/tasmota/language/tr-TR.h +++ b/tasmota/language/tr-TR.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_DEGREES "Wind Degrees" #define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" #define D_TX20_WIND_SPEED_MIN "Wind Speed Min" #define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_NORTH "N" diff --git a/tasmota/language/uk-UA.h b/tasmota/language/uk-UA.h index 2b4873e7a..0bf4736cb 100644 --- a/tasmota/language/uk-UA.h +++ b/tasmota/language/uk-UA.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Напрям вітру" -#define D_TX20_WIND_DEGREES "Кут вітру" #define D_TX20_WIND_SPEED "Швидкість вітру" -#define D_TX20_WIND_SPEED_AVG "Середня швидкість вітру" #define D_TX20_WIND_SPEED_MIN "Мінімальна швидкість вітру" #define D_TX20_WIND_SPEED_MAX "Максимальна швидкість вітру" #define D_TX20_NORTH "Пн" diff --git a/tasmota/language/zh-CN.h b/tasmota/language/zh-CN.h index 5a71e95dc..6e2621b4e 100644 --- a/tasmota/language/zh-CN.h +++ b/tasmota/language/zh-CN.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "风向" -#define D_TX20_WIND_DEGREES "风度" #define D_TX20_WIND_SPEED "风速" -#define D_TX20_WIND_SPEED_AVG "平均风速" #define D_TX20_WIND_SPEED_MIN "最低风速" #define D_TX20_WIND_SPEED_MAX "最高风速" #define D_TX20_NORTH "北" diff --git a/tasmota/language/zh-TW.h b/tasmota/language/zh-TW.h index 9883972f1..b5445a3f6 100644 --- a/tasmota/language/zh-TW.h +++ b/tasmota/language/zh-TW.h @@ -504,9 +504,7 @@ //xsns_35_tx20.ino #define D_TX20_WIND_DIRECTION "Wind Direction" -#define D_TX20_WIND_DEGREES "Wind Degrees" #define D_TX20_WIND_SPEED "Wind Speed" -#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" #define D_TX20_WIND_SPEED_MIN "Wind Speed Min" #define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_NORTH "N" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 8fc58ac4d..06901fa12 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -627,8 +627,8 @@ // #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) // Select none or only one of the below defines -//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+1k3 code) -//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+1k4 code) +//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k6/0k8 code) +//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+2k7/1k code) //#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index ad9b38165..d7396267b 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -787,6 +787,7 @@ void PerformEverySecond(void) #endif // USE_RULES } + XsnsCall(FUNC_AFTER_TELEPERIOD); XdrvCall(FUNC_AFTER_TELEPERIOD); } } diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 8f5038387..2e3ed1e26 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -230,8 +230,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) #define USE_HX711 // Add support for HX711 load cell (+1k5 code) //#define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) -//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+1k3 code) -//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+1k4 code) +//#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k6/0k8 code) +//#define USE_TX23_WIND_SENSOR // Add support for La Crosse TX23 anemometer (+2k7/1k code) #define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code, 460 iram) #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) diff --git a/tasmota/xsns_35_tx20.ino b/tasmota/xsns_35_tx20.ino index 14fd5c9f9..69844fda4 100644 --- a/tasmota/xsns_35_tx20.ino +++ b/tasmota/xsns_35_tx20.ino @@ -18,10 +18,7 @@ */ #if defined(USE_TX20_WIND_SENSOR) || defined(USE_TX23_WIND_SENSOR) -#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR) -#undef USE_TX20_WIND_SENSOR -#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled **** -#endif + /*********************************************************************************************\ * La Crosse TX20/TX23 Anemometer * @@ -30,18 +27,39 @@ * https://www.john.geek.nz/2011/07/la-crosse-tx20-anemometer-communication-protocol/ * http://www.rd-1000.com/chpm78/lacrosse/Lacrosse_TX23_protocol.html * https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/ - * + * * TX23 RJ11 connection: * 1 yellow - GND * 2 green - NC * 3 red - Vcc 3.3V * 4 black/brown - TxD Signal (GPIOxx) + * + * Reads speed and direction + * + * Calculate statistics: + * speed avg/min/max + * direction avg/min/max/range + * + * avg values are updated continuously (using exponentially weighted average) + * min/max/range values are reset after TelePeriod time or TX2X_WEIGHT_AVG_SAMPLE seconds + * (if TelePeriod is disabled) + * + * Statistic calculation can be disabled by defining USE_TX2X_WIND_SENSOR_NOSTATISTICS + * (saves 1k8) \*********************************************************************************************/ #define XSNS_35 35 +#if defined(USE_TX20_WIND_SENSOR) && defined(USE_TX23_WIND_SENSOR) +#undef USE_TX20_WIND_SENSOR +#warning **** use USE_TX20_WIND_SENSOR or USE_TX23_WIND_SENSOR but not both together, TX20 disabled **** +#endif // USE_TX20_WIND_SENSOR && USE_TX23_WIND_SENSOR + +// #define USE_TX2X_WIND_SENSOR_NOSTATISTICS // suppress statistics (speed/dir avg/min/max/range) + #define TX2X_BIT_TIME 1220 // microseconds #define TX2X_WEIGHT_AVG_SAMPLE 150 // seconds +#define TX2X_TIMEOUT 10 // seconds #define TX23_READ_INTERVAL 4 // seconds (don't use less than 3) // The Arduino standard GPIO routines are not enough, @@ -51,20 +69,36 @@ extern "C" { } #ifdef USE_TX20_WIND_SENSOR - #define D_TX2x_NAME "TX20" -#else - #define D_TX2x_NAME "TX23" -#endif +#undef D_TX2x_NAME +#define D_TX2x_NAME "TX20" +#else // USE_TX20_WIND_SENSOR +#undef D_TX2x_NAME +#define D_TX2x_NAME "TX23" +#endif // USE_TX20_WIND_SENSOR #ifdef USE_WEBSERVER +#define D_TX20_WIND_AVG "∅" +#define D_TX20_WIND_ANGLE "∠" const char HTTP_SNS_TX2X[] PROGMEM = "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED " " D_TX20_WIND_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s %s°{e}"; +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s %s°{e}" +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_AVG "{m}%s %s°{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_ANGLE "{m}%s° (%s°,%s°)"; +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS + ; #endif // USE_WEBSERVER +// float saves 48 byte +float const ff_pi = 3.1415926535897932384626433; // Pi +float const ff_halfpi = ff_pi / 2.0; +float const ff_pi180 = ff_pi / 180.0; + const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" D_TX20_NORTH D_TX20_EAST "|" @@ -82,26 +116,38 @@ const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" D_TX20_NORTH D_TX20_WEST "|" D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; -uint8_t tx2x_sa = 0; -uint8_t tx2x_sb = 0; -uint8_t tx2x_sd = 0; -uint8_t tx2x_se = 0; -uint16_t tx2x_sc = 0; -uint16_t tx2x_sf = 0; - float tx2x_wind_speed_kmh = 0; +int32_t tx2x_wind_direction = 0; + +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS float tx2x_wind_speed_min = 200.0; float tx2x_wind_speed_max = 0; float tx2x_wind_speed_avg = 0; -uint8_t tx2x_wind_direction = 0; -int tx2x_count = 0; -uint16_t tx2x_avg_samples; +float tx2x_wind_direction_avg_x = 0; +float tx2x_wind_direction_avg_y = 0; +float tx2x_wind_direction_avg = 0; +int32_t tx2x_wind_direction_min = 0; +int32_t tx2x_wind_direction_max = 0; -bool tx2x_available = false; +uint32_t tx2x_count = 0; +uint32_t tx2x_avg_samples; +uint32_t last_uptime = 0; +bool tx2x_valuesread = false; +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS + +#ifdef DEBUG_TASMOTA_SENSOR +uint32_t tx2x_sa = 0; +uint32_t tx2x_sb = 0; +uint32_t tx2x_sc = 0; +uint32_t tx2x_sd = 0; +uint32_t tx2x_se = 0; +uint32_t tx2x_sf = 0; +#endif // DEBUG_TASMOTA_SENSOR +uint32_t last_available = 0; #ifdef USE_TX23_WIND_SENSOR -uint8_t tx23_stage = 0; -#endif +uint32_t tx23_stage = 0; +#endif // USE_TX23_WIND_SENSOR #ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception void TX2xStartRead(void) ICACHE_RAM_ATTR; // As iram is tight and it works this way too @@ -120,7 +166,7 @@ void TX2xStartRead(void) * sd - Checksum (invert) * se - Wind direction 0 - 15 * sf - Wind speed 0 - 511 - * + * * La Crosse TX23 Anemometer datagram after setting TxD to low/high * 1-1 0 1 0-0 11011 0011 111010101111 0101 1100 000101010000 1-1 - Received pin data at 1200 uSec per bit * t s c sa sb sc sd se sf @@ -139,23 +185,30 @@ void TX2xStartRead(void) { if ((2==tx23_stage) || (3==tx23_stage)) { -#endif - tx2x_available = false; - +#endif // USE_TX23_WIND_SENSOR +#ifdef DEBUG_TASMOTA_SENSOR tx2x_sa = 0; tx2x_sb = 0; + tx2x_sc = 0; tx2x_sd = 0; tx2x_se = 0; - tx2x_sc = 0; tx2x_sf = 0; +#else // DEBUG_TASMOTA_SENSOR + uint32_t tx2x_sa = 0; + uint32_t tx2x_sb = 0; + uint32_t tx2x_sc = 0; + uint32_t tx2x_sd = 0; + uint32_t tx2x_se = 0; + uint32_t tx2x_sf = 0; +#endif // DEBUG_TASMOTA_SENSOR delayMicroseconds(TX2X_BIT_TIME / 2); for (int32_t bitcount = 41; bitcount > 0; bitcount--) { - uint8_t dpin = (digitalRead(pin[GPIO_TX2X_TXD_BLACK])); + uint32_t dpin = (digitalRead(pin[GPIO_TX2X_TXD_BLACK])); #ifdef USE_TX23_WIND_SENSOR dpin ^= 1; -#endif +#endif // USE_TX23_WIND_SENSOR if (bitcount > 41 - 5) { // start frame (invert) tx2x_sa = (tx2x_sa << 1) | (dpin ^ 1); @@ -178,27 +231,64 @@ void TX2xStartRead(void) delayMicroseconds(TX2X_BIT_TIME); } - uint8_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); + uint32_t chk = (tx2x_sb + (tx2x_sc & 0xf) + ((tx2x_sc >> 4) & 0xf) + ((tx2x_sc >> 8) & 0xf)); chk &= 0xf; - // check checksum, non-inverted with inverted values and max. speed - tx2x_available = ((chk == tx2x_sd) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)); + // check checksum, start frame,non-inverted==inverted values and max. speed + ; + if ((chk == tx2x_sd) && (0x1b==tx2x_sa) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { + last_available = uptime; + // Wind speed spec: 0 to 180 km/h (0 to 50 m/s) + tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36; + tx2x_wind_direction = tx2x_sb; +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + if (!tx2x_valuesread) { + tx2x_wind_direction_min = tx2x_wind_direction; + tx2x_wind_direction_max = tx2x_wind_direction; + tx2x_valuesread = true; + } +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS + } + #ifdef USE_TX23_WIND_SENSOR } tx23_stage++; } -#endif +#endif // USE_TX23_WIND_SENSOR // Must clear this bit in the interrupt register, // it gets set even when interrupts are disabled GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX2X_TXD_BLACK]); } -void Tx2xResetStat(void) +bool Tx2xAvailable(void) { - tx2x_wind_speed_min = tx2x_wind_speed_kmh; - tx2x_wind_speed_max = tx2x_wind_speed_kmh; - uint16_t tx2x_prev_avg_samples = tx2x_avg_samples; + return ((uptime - last_available) < TX2X_TIMEOUT); +} + +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS +float atan2f(float a, float b) +{ + float atan2val; + if (b > 0) { + atan2val = atanf(a/b); + } else if ((b < 0) && (a >= 0)) { + atan2val = atanf(a/b) + ff_pi; + } else if ((b < 0) && (a < 0)) { + atan2val = atanf(a/b) - ff_pi; + } else if ((b == 0) && (a > 0)) { + atan2val = ff_halfpi; + } else if ((b == 0) && (a < 0)) { + atan2val = 0 - (ff_halfpi); + } else if ((b == 0) && (a == 0)) { + atan2val = 1000; //represents undefined + } + return atan2val; +} + +void Tx2xCheckSampleCount(void) +{ + uint32_t tx2x_prev_avg_samples = tx2x_avg_samples; if (Settings.tele_period) { // number for avg samples = teleperiod value if set tx2x_avg_samples = Settings.tele_period; @@ -212,6 +302,23 @@ void Tx2xResetStat(void) } } +void Tx2xResetStat(void) +{ + DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": reset statistics")); + last_uptime = uptime; + Tx2xResetStatData(); +} + +void Tx2xResetStatData(void) +{ + tx2x_wind_speed_min = tx2x_wind_speed_kmh; + tx2x_wind_speed_max = tx2x_wind_speed_kmh; + + tx2x_wind_direction_min = tx2x_wind_direction; + tx2x_wind_direction_max = tx2x_wind_direction; +} +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS + void Tx2xRead(void) { #ifdef USE_TX23_WIND_SENSOR @@ -220,7 +327,7 @@ void Tx2xRead(void) // |____| |___________| |_| |__XXXXXXXXXX // trigger start conv Startframe Data // - // note: TX23 speed calculation is unstable when conversion starts + // note: TX23 speed calculation is unstable when conversion starts // less than 2 seconds after last request if ((uptime % TX23_READ_INTERVAL)==0) { // TX23 start transmission by pulling down TxD line for at minimum 500ms @@ -234,22 +341,21 @@ void Tx2xRead(void) tx23_stage = 1; // first rising signal is invalid pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT_PULLUP); } -#endif - if (0!=Settings.tele_period && Settings.tele_period!=tx2x_avg_samples) { - // new teleperiod value - Tx2xResetStat(); - } - if (tx2x_available) { - // Wind speed spec: 0 to 180 km/h (0 to 50 m/s) - tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36; +#endif // USE_TX23_WIND_SENSOR + if (Tx2xAvailable()) { +#ifdef DEBUG_TASMOTA_SENSOR + DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": sa=0x%02lx sb=%ld (0x%02lx), sc=%ld (0x%03lx), sd=0x%02lx, se=%ld, sf=%ld"), tx2x_sa,tx2x_sb,tx2x_sb,tx2x_sc,tx2x_sc,tx2x_sd,tx2x_se,tx2x_sf); +#endif // DEBUG_TASMOTA_SENSOR +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS if (tx2x_wind_speed_kmh < tx2x_wind_speed_min) { tx2x_wind_speed_min = tx2x_wind_speed_kmh; } if (tx2x_wind_speed_kmh > tx2x_wind_speed_max) { tx2x_wind_speed_max = tx2x_wind_speed_kmh; } - // exponentially weighted average is not quite as smooth as the arithmetic average - // but close enough to the moving average and does not require the regular reset + + // exponentially weighted average is not quite as smooth as the arithmetic average + // but close enough to the moving average and does not require the regular reset // of the divider with the associated jump in avg values after period is over if (tx2x_count <= tx2x_avg_samples) { tx2x_count++; @@ -257,72 +363,200 @@ void Tx2xRead(void) tx2x_wind_speed_avg -= tx2x_wind_speed_avg / tx2x_count; tx2x_wind_speed_avg += tx2x_wind_speed_kmh / tx2x_count; - tx2x_wind_direction = tx2x_sb; - - if (!(uptime % tx2x_avg_samples)) { - tx2x_wind_speed_min = tx2x_wind_speed_kmh; - tx2x_wind_speed_max = tx2x_wind_speed_kmh; - + tx2x_wind_direction_avg_x -= tx2x_wind_direction_avg_x / tx2x_count; + tx2x_wind_direction_avg_x += cosf((tx2x_wind_direction*22.5) * ff_pi180) / tx2x_count; + tx2x_wind_direction_avg_y -= tx2x_wind_direction_avg_y / tx2x_count; + tx2x_wind_direction_avg_y += sinf((tx2x_wind_direction*22.5) * ff_pi180) / tx2x_count; + tx2x_wind_direction_avg = atan2f(tx2x_wind_direction_avg_y, tx2x_wind_direction_avg_x) * 180.0f / ff_pi; + if (tx2x_wind_direction_avg<0.0) { + tx2x_wind_direction_avg += 360.0; } + if (tx2x_wind_direction_avg>360.0) { + tx2x_wind_direction_avg -= 360.0; + } + + int32_t tx2x_wind_direction_avg_int = int((tx2x_wind_direction_avg/22.5)+0.5) % 16; + + // degrees min/max + if (tx2x_wind_direction > tx2x_wind_direction_avg_int) { + // clockwise or left-handed rotation + if ((tx2x_wind_direction-tx2x_wind_direction_avg_int)>8) { + // diff > 180° + if ((tx2x_wind_direction - 16) < tx2x_wind_direction_min) { + // new min (negative values < 0) + tx2x_wind_direction_min = tx2x_wind_direction - 16; + } + } else { + // diff <= 180° + if (tx2x_wind_direction > tx2x_wind_direction_max) { + // new max (origin max) + tx2x_wind_direction_max = tx2x_wind_direction; + } + } + } else { + // also clockwise or left-handed rotation but needs other tests + if ((tx2x_wind_direction_avg_int-tx2x_wind_direction)>8) { + // diff > 180° + if ((tx2x_wind_direction + 16) > tx2x_wind_direction_max) { + // new max (overflow values > 15) + tx2x_wind_direction_max = tx2x_wind_direction + 16; + } + } else { + // diff <= 180° + if (tx2x_wind_direction < tx2x_wind_direction_min) { + // new min (origin min) + tx2x_wind_direction_min = tx2x_wind_direction; + } + } + } + +#ifdef DEBUG_TASMOTA_SENSOR + char diravg[33]; + dtostrfd(tx2x_wind_direction_avg, 1, diravg); + char cosx[33]; + dtostrfd(tx2x_wind_direction_avg_x, 1, cosx); + char siny[33]; + dtostrfd(tx2x_wind_direction_avg_y, 1, siny); + DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": dir stat - counter=%ld, actint=%ld, avgint=%ld, avg=%s (cosx=%s, siny=%s), min %d, max %d"), + (uptime-last_uptime), + tx2x_wind_direction, + tx2x_wind_direction_avg_int, + diravg, + cosx, + siny, + tx2x_wind_direction_min, + tx2x_wind_direction_max + ); +#endif // DEBUG_TASMOTA_SENSOR +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS + } else { + DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": not available")); + tx2x_wind_speed_kmh = 0; + tx2x_wind_direction = 0; +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + tx2x_wind_speed_avg = 0; + tx2x_wind_direction_avg = 0; + Tx2xResetStatData(); +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS } + +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + Tx2xCheckSampleCount(); + if (0==Settings.tele_period && (uptime-last_uptime)>=tx2x_avg_samples) { + Tx2xResetStat(); + } +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS } -void Tx2xInit(void) +void Tx2xInit(void) { +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + tx2x_valuesread = false; Tx2xResetStat(); + Tx2xCheckSampleCount(); +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS #ifdef USE_TX23_WIND_SENSOR tx23_stage = 0; pinMode(pin[GPIO_TX2X_TXD_BLACK], OUTPUT); digitalWrite(pin[GPIO_TX2X_TXD_BLACK], LOW); -#else +#else // USE_TX23_WIND_SENSOR pinMode(pin[GPIO_TX2X_TXD_BLACK], INPUT); -#endif +#endif // USE_TX23_WIND_SENSOR attachInterrupt(pin[GPIO_TX2X_TXD_BLACK], TX2xStartRead, RISING); } +int32_t Tx2xNormalize(int32_t value) +{ + while (value>15) { + value -= 16; + } + while (value<0) { + value += 16; + } + return value; +} + void Tx2xShow(bool json) { - char wind_speed_string[33]; + char wind_speed_string[17]; dtostrfd(tx2x_wind_speed_kmh, 1, wind_speed_string); - char wind_speed_min_string[33]; + char wind_direction_string[17]; + dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_string); + char wind_direction_cardinal_string[4]; + GetTextIndexed(wind_direction_cardinal_string, sizeof(wind_direction_cardinal_string), tx2x_wind_direction, kTx2xDirections); +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + char wind_speed_min_string[17]; dtostrfd(tx2x_wind_speed_min, 1, wind_speed_min_string); - char wind_speed_max_string[33]; + char wind_speed_max_string[17]; dtostrfd(tx2x_wind_speed_max, 1, wind_speed_max_string); - char wind_speed_avg_string[33]; + char wind_speed_avg_string[17]; dtostrfd(tx2x_wind_speed_avg, 1, wind_speed_avg_string); - char wind_direction_degree_string[33]; - dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_degree_string); - char wind_direction_string[4]; - GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx2x_wind_direction, kTx2xDirections); + char wind_direction_avg_string[17]; + dtostrfd(tx2x_wind_direction_avg, 1, wind_direction_avg_string); + char wind_direction_avg_cardinal_string[4]; + GetTextIndexed(wind_direction_avg_cardinal_string, sizeof(wind_direction_avg_cardinal_string), int((tx2x_wind_direction_avg/22.5f)+0.5f) % 16, kTx2xDirections); + char wind_direction_range_string[17]; + dtostrfd(Tx2xNormalize(tx2x_wind_direction_max-tx2x_wind_direction_min)*22.5, 1, wind_direction_range_string); + char wind_direction_min_string[17]; + dtostrfd(Tx2xNormalize(tx2x_wind_direction_min)*22.5, 1, wind_direction_min_string); + char wind_direction_max_string[17]; + dtostrfd(Tx2xNormalize(tx2x_wind_direction_max)*22.5, 1, wind_direction_max_string); +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS if (json) { +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS #ifdef USE_TX2x_LEGACY_JSON - ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), - wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string, wind_direction_degree); -#else - // new format grouped by Speed and Dir(ection) - // Card = cardianal (N../O../S../W..) - // Deg = Degree - ResponseAppend_P( - PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s},\"Direction\":{\"Cardinal\":\"%s\",\"Degree\":%s}}"), - wind_speed_string, - wind_speed_avg_string, - wind_speed_min_string, - wind_speed_max_string, - wind_direction_string, - wind_direction_degree_string + ResponseAppend_P(Tx2xAvailable()?PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"):PSTR(""), + wind_speed_string, + wind_speed_avg_string, + wind_speed_max_string, + wind_direction_cardinal_string, + wind_direction_string ); -#endif +#else // USE_TX2x_LEGACY_JSON + ResponseAppend_P(Tx2xAvailable()?PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s,\"Avg\":%s,\"AvgCard\":\"%s\",\"Min\":%s,\"Max\":%s,\"Range\":%s}}"):PSTR(""), + wind_speed_string, + wind_speed_avg_string, + wind_speed_min_string, + wind_speed_max_string, + wind_direction_cardinal_string, + wind_direction_string, + wind_direction_avg_string, + wind_direction_avg_cardinal_string, + wind_direction_min_string, + wind_direction_max_string, + wind_direction_range_string + ); +#endif // USE_TX2x_LEGACY_JSON +#else // USE_TX2X_WIND_SENSOR_NOSTATISTICS +#ifdef USE_TX2x_LEGACY_JSON + ResponseAppend_P(Tx2xAvailable()?PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"Direction\":\"%s\",\"Degree\":%s}"):PSTR(""), + wind_speed_string, wind_direction_cardinal_string, wind_direction_string); +#else // USE_TX2x_LEGACY_JSON + ResponseAppend_P(Tx2xAvailable()?PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":{\"Act\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s}}"):PSTR(""), + wind_speed_string, wind_direction_cardinal_string, wind_direction_string); +#endif // USE_TX2x_LEGACY_JSON +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS + #ifdef USE_WEBSERVER } else { WSContentSend_PD( - HTTP_SNS_TX2X, - wind_speed_string, - wind_speed_avg_string, - wind_speed_min_string, - wind_speed_max_string, - wind_direction_string, - wind_direction_degree_string + Tx2xAvailable()?HTTP_SNS_TX2X:PSTR(""), + wind_speed_string, +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + wind_speed_avg_string, + wind_speed_min_string, + wind_speed_max_string, +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS + wind_direction_cardinal_string, + wind_direction_string +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + ,wind_direction_avg_cardinal_string, + wind_direction_avg_string, + wind_direction_range_string, + wind_direction_min_string, + wind_direction_max_string +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS ); #endif // USE_WEBSERVER } @@ -344,6 +578,11 @@ bool Xsns35(uint8_t function) case FUNC_EVERY_SECOND: Tx2xRead(); break; +#ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS + case FUNC_AFTER_TELEPERIOD: + Tx2xResetStat(); + break; +#endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS case FUNC_JSON_APPEND: Tx2xShow(true); break; @@ -352,6 +591,7 @@ bool Xsns35(uint8_t function) Tx2xShow(false); break; #endif // USE_WEBSERVER + } } return result; From 9498cde5e5a7ec1c833c3180af731f63178780cc Mon Sep 17 00:00:00 2001 From: Phonog Date: Sun, 1 Mar 2020 09:42:59 +0000 Subject: [PATCH 530/559] Fix switchmode 6 according to issue 7778 --- .theia/launch.json | 6 ++++++ tasmota/support_switch.ino | 16 ++++++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 .theia/launch.json diff --git a/.theia/launch.json b/.theia/launch.json new file mode 100644 index 000000000..a2ea02c46 --- /dev/null +++ b/.theia/launch.json @@ -0,0 +1,6 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + "version": "0.2.0", + "configurations": [] +} diff --git a/tasmota/support_switch.ino b/tasmota/support_switch.ino index 24470ff93..49b9428b0 100644 --- a/tasmota/support_switch.ino +++ b/tasmota/support_switch.ino @@ -214,20 +214,20 @@ void SwitchHandler(uint8_t mode) break; case PUSHBUTTONHOLD: if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; // Start timer on button press } if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd + Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer... + switchflag = POWER_TOGGLE; // ...and Toggle } break; case PUSHBUTTONHOLD_INV: - if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { - Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; + if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) { + Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; // Start timer on button press... + switchflag = POWER_TOGGLE; // ...and Toggle } - if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) { - Switch.hold_timer[i] = 0; - switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd + if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) { + Switch.hold_timer[i] = 0; // Button released : stop timer. } break; case TOGGLEMULTI: From 7cf8c1750f28c9113722f0c4cd3ae8dced7ceed9 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Sun, 1 Mar 2020 11:25:59 +0100 Subject: [PATCH 531/559] Add Zigbee features and improvements --- tasmota/CHANGELOG.md | 1 + tasmota/i18n.h | 12 +- tasmota/xdrv_23_zigbee_0_constants.ino | 112 ++++---- tasmota/xdrv_23_zigbee_3_devices.ino | 58 ++-- tasmota/xdrv_23_zigbee_5_converters.ino | 325 ++++++++++++++-------- tasmota/xdrv_23_zigbee_6_commands.ino | 93 +++++-- tasmota/xdrv_23_zigbee_7_statemachine.ino | 5 +- tasmota/xdrv_23_zigbee_8_parsers.ino | 113 +++++--- tasmota/xdrv_23_zigbee_9_impl.ino | 111 ++++++-- 9 files changed, 550 insertions(+), 280 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index ee767851a..579d19975 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -5,6 +5,7 @@ - Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers - Add support for Jarolift rollers by Keeloq algorithm - Change IRremoteESP8266 library updated to v2.7.4 +- Add Zigbee features and improvements ### 8.1.0.9 20200220 diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 903224c99..0f1988944 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -470,10 +470,10 @@ // Commands xdrv_23_zigbee.ino #define D_PRFX_ZB "Zb" -#define D_PRFX_ZIGBEE "Zigbee" #define D_ZIGBEE_NOT_STARTED "Zigbee not started (yet)" #define D_CMND_ZIGBEE_PERMITJOIN "PermitJoin" #define D_CMND_ZIGBEE_STATUS "Status" + #define D_JSON_ZIGBEE_Status "Status" #define D_CMND_ZIGBEE_RESET "Reset" #define D_JSON_ZIGBEE_CC2530 "CC2530" #define D_CMND_ZIGBEEZNPRECEIVE "ZNPReceive" // only for debug @@ -486,19 +486,27 @@ #define D_JSON_ZIGBEE_DEVICE "Device" #define D_JSON_ZIGBEE_NAME "Name" #define D_CMND_ZIGBEE_NAME "Name" +#define D_CMND_ZIGBEE_MODELID "ModelId" + #define D_JSON_ZIGBEE_MODELID "ModelId" #define D_CMND_ZIGBEE_PROBE "Probe" #define D_CMND_ZIGBEE_FORGET "Forget" #define D_CMND_ZIGBEE_SAVE "Save" #define D_CMND_ZIGBEE_LINKQUALITY "LinkQuality" #define D_CMND_ZIGBEE_ENDPOINT "Endpoint" + #define D_CMND_ZIGBEE_GROUP "Group" #define D_CMND_ZIGBEE_READ "Read" #define D_CMND_ZIGBEE_SEND "Send" #define D_JSON_ZIGBEE_ZCL_SENT "ZbZCLSent" #define D_JSON_ZIGBEE_RECEIVED "ZbReceived" -#define D_JSON_ZIGBEE_RECEIVED_LEGACY "ZigbeeReceived" #define D_CMND_ZIGBEE_BIND "Bind" + #define D_JSON_ZIGBEE_BIND "ZbBind" #define D_CMND_ZIGBEE_PING "Ping" #define D_JSON_ZIGBEE_PING "ZbPing" + #define D_JSON_ZIGBEE_IEEE "IEEEAddr" +#define D_JSON_ZIGBEE_RESPONSE "ZbResponse" + #define D_JSON_ZIGBEE_CMD "Command" + #define D_JSON_ZIGBEE_STATUS "Status" + #define D_JSON_ZIGBEE_STATUS_MSG "StatusMessage" // Commands xdrv_25_A4988_Stepper.ino #define D_CMND_MOTOR "MOTOR" diff --git a/tasmota/xdrv_23_zigbee_0_constants.ino b/tasmota/xdrv_23_zigbee_0_constants.ino index a37969f8b..cc88fadc2 100644 --- a/tasmota/xdrv_23_zigbee_0_constants.ino +++ b/tasmota/xdrv_23_zigbee_0_constants.ino @@ -169,43 +169,6 @@ enum Z_configuration { ZNP_HAS_CONFIGURED = 0xF00 }; -// enum Z_nvItemIds { -// SCENE_TABLE = 145, -// MIN_FREE_NWK_ADDR = 146, -// MAX_FREE_NWK_ADDR = 147, -// MIN_FREE_GRP_ID = 148, -// MAX_FREE_GRP_ID = 149, -// MIN_GRP_IDS = 150, -// MAX_GRP_IDS = 151, -// OTA_BLOCK_REQ_DELAY = 152, -// SAPI_ENDPOINT = 161, -// SAS_SHORT_ADDR = 177, -// SAS_EXT_PANID = 178, -// SAS_PANID = 179, -// SAS_CHANNEL_MASK = 180, -// SAS_PROTOCOL_VER = 181, -// SAS_STACK_PROFILE = 182, -// SAS_STARTUP_CTRL = 183, -// SAS_TC_ADDR = 193, -// SAS_TC_MASTER_KEY = 194, -// SAS_NWK_KEY = 195, -// SAS_USE_INSEC_JOIN = 196, -// SAS_PRECFG_LINK_KEY = 197, -// SAS_NWK_KEY_SEQ_NUM = 198, -// SAS_NWK_KEY_TYPE = 199, -// SAS_NWK_MGR_ADDR = 200, -// SAS_CURR_TC_MASTER_KEY = 209, -// SAS_CURR_NWK_KEY = 210, -// SAS_CURR_PRECFG_LINK_KEY = 211, -// TCLK_TABLE_START = 257, -// TCLK_TABLE_END = 511, -// APS_LINK_KEY_DATA_START = 513, -// APS_LINK_KEY_DATA_END = 767, -// DUPLICATE_BINDING_TABLE = 768, -// DUPLICATE_DEVICE_LIST = 769, -// DUPLICATE_DEVICE_LIST_KA_TIMEOUT = 770, -//}; - // enum Z_Status { Z_Success = 0x00, @@ -261,16 +224,14 @@ enum Z_Device_Ids { // 0x0403 IAS Warning Device }; -// enum class AddrMode : uint8_t { -// NotPresent = 0, -// Group = 1, -// ShortAddress = 2, -// IEEEAddress = 3, -// Broadcast = 0xFF -// }; -// -// -// + enum Z_AddrMode : uint8_t { + Z_Addr_NotPresent = 0, + Z_Addr_Group = 1, + Z_Addr_ShortAddress = 2, + Z_Addr_IEEEAddress = 3, + Z_Addr_Broadcast = 0xFF +}; + // Commands in the AF subsystem enum AfCommand : uint8_t { AF_REGISTER = 0x00, @@ -286,7 +247,7 @@ enum AfCommand : uint8_t { AF_INCOMING_MSG = 0x81, AF_INCOMING_MSG_EXT = 0x82 }; -// + // Commands in the ZDO subsystem enum : uint8_t { ZDO_NWK_ADDR_REQ = 0x00, @@ -371,7 +332,7 @@ enum ZdoStates { ZDO_DEV_ZB_COORD = 0x09, // Started as a a Zigbee Coordinator ZDO_DEV_NWK_ORPHAN = 0x0A, // Device has lost information about its parent. }; -// + // Commands in the UTIL subsystem enum Z_Util { Z_UTIL_GET_DEVICE_INFO = 0x00, @@ -427,4 +388,57 @@ enum ZCL_Global_Commands { const uint16_t Z_ProfileIds[] PROGMEM = { 0x0104, 0x0109, 0xA10E, 0xC05E }; const char Z_ProfileNames[] PROGMEM = "ZigBee Home Automation|ZigBee Smart Energy|ZigBee Green Power|ZigBee Light Link"; +typedef struct Z_StatusLine { + uint32_t status; // no need to use uint8_t since it uses 32 bits anyways + const char * status_msg; +} Z_StatusLine; + +const Z_StatusLine Z_Status[] PROGMEM = { + 0x00, "SUCCESS", + 0x01, "FAILURE", + 0x7E, "NOT_AUTHORIZED", + 0x7F, "RESERVED_FIELD_NOT_ZERO", + 0x80, "MALFORMED_COMMAND", + 0x81, "UNSUP_CLUSTER_COMMAND", + 0x82, "UNSUP_GENERAL_COMMAND", + 0x83, "UNSUP_MANUF_CLUSTER_COMMAND", + 0x84, "UNSUP_MANUF_GENERAL_COMMAND", + 0x85, "INVALID_FIELD", + 0x86, "UNSUPPORTED_ATTRIBUTE", + 0x87, "INVALID_VALUE", + 0x88, "READ_ONLY", + 0x89, "INSUFFICIENT_SPACE", + 0x8A, "DUPLICATE_EXISTS", + 0x8B, "NOT_FOUND", + 0x8C, "UNREPORTABLE_ATTRIBUTE", + 0x8D, "INVALID_DATA_TYPE", + 0x8E, "INVALID_SELECTOR", + 0x8F, "WRITE_ONLY", + 0x90, "INCONSISTENT_STARTUP_STATE", + 0x91, "DEFINED_OUT_OF_BAND", + 0x92, "INCONSISTENT", + 0x93, "ACTION_DENIED", + 0x94, "TIMEOUT", + 0x95, "ABORT", + 0x96, "INVALID_IMAGE", + 0x97, "WAIT_FOR_DATA", + 0x98, "NO_IMAGE_AVAILABLE", + 0x99, "REQUIRE_MORE_IMAGE", + 0x9A, "NOTIFICATION_PENDING", + 0xC0, "HARDWARE_FAILURE", + 0xC1, "SOFTWARE_FAILURE", + 0xC2, "CALIBRATION_ERROR", + 0xC3, "UNSUPPORTED_CLUSTER", +}; + +const __FlashStringHelper* getZigbeeStatusMessage(uint8_t status) { + for (uint32_t i = 0; i < sizeof(Z_Status) / sizeof(Z_Status[0]); i++) { + const Z_StatusLine *statl = &Z_Status[i]; + if (statl->status == status) { + return (const __FlashStringHelper*) statl->status_msg; + } + } + return nullptr; +} + #endif // USE_ZIGBEE diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index c7c1f2d11..d814a8c0c 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -19,10 +19,6 @@ #ifdef USE_ZIGBEE -#ifndef ZIGBEERECEIVED -#define ZIGBEERECEIVED 1 -#endif - #include #include @@ -97,7 +93,8 @@ public: void setManufId(uint16_t shortaddr, const char * str); void setModelId(uint16_t shortaddr, const char * str); void setFriendlyName(uint16_t shortaddr, const char * str); - const String * getFriendlyName(uint16_t) const; + const String * getFriendlyName(uint16_t shortaddr) const; + const String * getModelId(uint16_t shortaddr) const; // device just seen on the network, update the lastSeen field void updateLastSeen(uint16_t shortaddr); @@ -537,6 +534,17 @@ const String * Z_Devices::getFriendlyName(uint16_t shortaddr) const { return nullptr; } +const String * Z_Devices::getModelId(uint16_t shortaddr) const { + int32_t found = findShortAddr(shortaddr); + if (found >= 0) { + const Z_Device & device = devicesAt(found); + if (device.modelId.length() > 0) { + return &device.modelId; + } + } + return nullptr; +} + // device just seen on the network, update the lastSeen field void Z_Devices::updateLastSeen(uint16_t shortaddr) { Z_Device & device = getShortAddr(shortaddr); @@ -656,13 +664,31 @@ bool Z_Devices::jsonIsConflict(uint16_t shortaddr, const JsonObject &values) { return false; // if no previous value, no conflict } + // compare groups + uint16_t group1 = 0; + uint16_t group2 = 0; + if (device.json->containsKey(D_CMND_ZIGBEE_GROUP)) { + group1 = device.json->get(D_CMND_ZIGBEE_GROUP); + } + if (values.containsKey(D_CMND_ZIGBEE_GROUP)) { + group2 = values.get(D_CMND_ZIGBEE_GROUP); + } + if (group1 != group2) { + return true; // if group addresses differ, then conflict + } + + // parse all other parameters for (auto kv : values) { String key_string = kv.key; - if (0 == strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_ENDPOINT))) { - // attribute "Endpoint" - if (kv.value.as() != device.json->get(kv.key)) { - return true; + if (0 == strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_GROUP))) { + // ignore group, it was handled already + } else if (0 == strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_ENDPOINT))) { + // attribute "Endpoint" or "Group" + if (device.json->containsKey(kv.key)) { + if (kv.value.as() != device.json->get(kv.key)) { + return true; + } } } else if (strcasecmp_P(kv.key, PSTR(D_CMND_ZIGBEE_LINKQUALITY))) { // exception = ignore duplicates for LinkQuality if (device.json->containsKey(kv.key)) { @@ -734,25 +760,11 @@ void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); -#if ZIGBEERECEIVED - // DEPRECATED TODO - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); -#endif } else { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); XdrvRulesProcess(); -#if ZIGBEERECEIVED - // DEPRECATED TODO - Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED_LEGACY "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); -#endif } - // MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - // XdrvRulesProcess(); } void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { diff --git a/tasmota/xdrv_23_zigbee_5_converters.ino b/tasmota/xdrv_23_zigbee_5_converters.ino index 4debd73fd..6d71d5ccf 100644 --- a/tasmota/xdrv_23_zigbee_5_converters.ino +++ b/tasmota/xdrv_23_zigbee_5_converters.ino @@ -112,6 +112,7 @@ public: static void generateAttributeName(const JsonObject& json, uint16_t cluster, uint16_t attr, char *key, size_t key_len); void parseRawAttributes(JsonObject& json, uint8_t offset = 0); void parseReadAttributes(JsonObject& json, uint8_t offset = 0); + void parseResponse(void); void parseClusterSpecificCommand(JsonObject& json, uint8_t offset = 0); void postProcessAttributes(uint16_t shortaddr, JsonObject& json); @@ -484,6 +485,51 @@ void ZCLFrame::parseReadAttributes(JsonObject& json, uint8_t offset) { } } +// ZCL_DEFAULT_RESPONSE +void ZCLFrame::parseResponse(void) { + if (_payload.len() < 2) { return; } // wrong format + uint8_t cmd = _payload.get8(0); + uint8_t status = _payload.get8(1); + + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + + // "Device" + char s[12]; + snprintf_P(s, sizeof(s), PSTR("0x%04X"), _srcaddr); + json[F(D_JSON_ZIGBEE_DEVICE)] = s; + // "Name" + const String * friendlyName = zigbee_devices.getFriendlyName(_srcaddr); + if (friendlyName) { + json[F(D_JSON_ZIGBEE_NAME)] = *friendlyName; + } + // "Command" + snprintf_P(s, sizeof(s), PSTR("%04X!%02X"), _cluster_id, cmd); + json[F(D_JSON_ZIGBEE_CMD)] = s; + // "Status" + json[F(D_JSON_ZIGBEE_STATUS)] = status; + // "StatusMessage" + const __FlashStringHelper* statm = getZigbeeStatusMessage(status); + if (statm) { + json[F(D_JSON_ZIGBEE_STATUS_MSG)] = statm; + } + // Add Endpoint + json[F(D_CMND_ZIGBEE_ENDPOINT)] = _srcendpoint; + // Add Group if non-zero + if (_group_id) { + json[F(D_CMND_ZIGBEE_GROUP)] = _group_id; + } + // Add linkquality + json[F(D_CMND_ZIGBEE_LINKQUALITY)] = _linkquality; + + String msg(""); + msg.reserve(100); + json.printTo(msg); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_RESPONSE "\":%s}"), msg.c_str()); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); +} + // Parse non-normalized attributes void ZCLFrame::parseClusterSpecificCommand(JsonObject& json, uint8_t offset) { @@ -519,7 +565,7 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { // Power Configuration cluster { 0x0001, 0x0000, "MainsVoltage", &Z_Copy }, { 0x0001, 0x0001, "MainsFrequency", &Z_Copy }, - { 0x0001, 0x0020, "BatteryVoltage", &Z_Copy }, + { 0x0001, 0x0020, "BatteryVoltage", &Z_FloatDiv10 }, { 0x0001, 0x0021, "BatteryPercentageRemaining",&Z_Copy }, // Device Temperature Configuration cluster @@ -564,78 +610,112 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x000B, 0x0000, "QualityMeasure", &Z_Copy }, { 0x000B, 0x0000, "NumberOfDevices", &Z_Copy }, // Analog Input cluster - { 0x000C, 0x0004, "ActiveText", &Z_Copy }, - { 0x000C, 0x001C, "Description", &Z_Copy }, - { 0x000C, 0x002E, "InactiveText", &Z_Copy }, - { 0x000C, 0x0041, "MaxPresentValue", &Z_Copy }, - { 0x000C, 0x0045, "MinPresentValue", &Z_Copy }, - { 0x000C, 0x0051, "OutOfService", &Z_Copy }, + { 0x000C, 0x0004, "AnalogInActiveText", &Z_Copy }, + { 0x000C, 0x001C, "AnalogInDescription", &Z_Copy }, + { 0x000C, 0x002E, "AnalogInInactiveText", &Z_Copy }, + { 0x000C, 0x0041, "AnalogInMaxValue", &Z_Copy }, + { 0x000C, 0x0045, "AnalogInMinValue", &Z_Copy }, + { 0x000C, 0x0051, "AnalogInOutOfService", &Z_Copy }, { 0x000C, 0x0055, "AqaraRotate", &Z_Copy }, - { 0x000C, 0x0057, "PriorityArray", &Z_Copy }, - { 0x000C, 0x0067, "Reliability", &Z_Copy }, - { 0x000C, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x000C, 0x006A, "Resolution", &Z_Copy }, - { 0x000C, 0x006F, "StatusFlags", &Z_Copy }, - { 0x000C, 0x0075, "EngineeringUnits", &Z_Copy }, - { 0x000C, 0x0100, "ApplicationType", &Z_Copy }, + { 0x000C, 0x0057, "AnalogInPriorityArray",&Z_Copy }, + { 0x000C, 0x0067, "AnalogInReliability", &Z_Copy }, + { 0x000C, 0x0068, "AnalogInRelinquishDefault",&Z_Copy }, + { 0x000C, 0x006A, "AnalogInResolution", &Z_Copy }, + { 0x000C, 0x006F, "AnalogInStatusFlags", &Z_Copy }, + { 0x000C, 0x0075, "AnalogInEngineeringUnits",&Z_Copy }, + { 0x000C, 0x0100, "AnalogInApplicationType",&Z_Copy }, { 0x000C, 0xFF05, "Aqara_FF05", &Z_Copy }, + // Analog Output cluster + { 0x000D, 0x001C, "AnalogOutDescription", &Z_Copy }, + { 0x000D, 0x0041, "AnalogOutMaxValue", &Z_Copy }, + { 0x000D, 0x0045, "AnalogOutMinValue", &Z_Copy }, + { 0x000D, 0x0051, "AnalogOutOutOfService",&Z_Copy }, + { 0x000D, 0x0055, "AnalogOutValue", &Z_Copy }, + { 0x000D, 0x0057, "AnalogOutPriorityArray",&Z_Copy }, + { 0x000D, 0x0067, "AnalogOutReliability", &Z_Copy }, + { 0x000D, 0x0068, "AnalogOutRelinquishDefault",&Z_Copy }, + { 0x000D, 0x006A, "AnalogOutResolution", &Z_Copy }, + { 0x000D, 0x006F, "AnalogOutStatusFlags", &Z_Copy }, + { 0x000D, 0x0075, "AnalogOutEngineeringUnits",&Z_Copy }, + { 0x000D, 0x0100, "AnalogOutApplicationType",&Z_Copy }, + // Analog Value cluster + { 0x000E, 0x001C, "AnalogDescription", &Z_Copy }, + { 0x000E, 0x0051, "AnalogOutOfService", &Z_Copy }, + { 0x000E, 0x0055, "AnalogValue", &Z_Copy }, + { 0x000E, 0x0057, "AnalogPriorityArray", &Z_Copy }, + { 0x000E, 0x0067, "AnalogReliability", &Z_Copy }, + { 0x000E, 0x0068, "AnalogRelinquishDefault",&Z_Copy }, + { 0x000E, 0x006F, "AnalogStatusFlags", &Z_Copy }, + { 0x000E, 0x0075, "AnalogEngineeringUnits",&Z_Copy }, + { 0x000E, 0x0100, "AnalogApplicationType",&Z_Copy }, + // Binary Input cluster + { 0x000F, 0x0004, "BinaryInActiveText", &Z_Copy }, + { 0x000F, 0x001C, "BinaryInDescription", &Z_Copy }, + { 0x000F, 0x002E, "BinaryInInactiveText",&Z_Copy }, + { 0x000F, 0x0051, "BinaryInOutOfService",&Z_Copy }, + { 0x000F, 0x0054, "BinaryInPolarity", &Z_Copy }, + { 0x000F, 0x0055, "BinaryInValue", &Z_Copy }, + { 0x000F, 0x0057, "BinaryInPriorityArray",&Z_Copy }, + { 0x000F, 0x0067, "BinaryInReliability", &Z_Copy }, + { 0x000F, 0x006F, "BinaryInStatusFlags", &Z_Copy }, + { 0x000F, 0x0100, "BinaryInApplicationType",&Z_Copy }, // Binary Output cluster - { 0x0010, 0x0004, "ActiveText", &Z_Copy }, - { 0x0010, 0x001C, "Description", &Z_Copy }, - { 0x0010, 0x002E, "InactiveText", &Z_Copy }, - { 0x0010, 0x0042, "MinimumOffTime", &Z_Copy }, - { 0x0010, 0x0043, "MinimumOnTime", &Z_Copy }, - { 0x0010, 0x0051, "OutOfService", &Z_Copy }, - { 0x0010, 0x0054, "Polarity", &Z_Copy }, - { 0x0010, 0x0055, "PresentValue", &Z_Copy }, - { 0x0010, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0010, 0x0067, "Reliability", &Z_Copy }, - { 0x0010, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0010, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0010, 0x0100, "ApplicationType", &Z_Copy }, + { 0x0010, 0x0004, "BinaryOutActiveText", &Z_Copy }, + { 0x0010, 0x001C, "BinaryOutDescription", &Z_Copy }, + { 0x0010, 0x002E, "BinaryOutInactiveText",&Z_Copy }, + { 0x0010, 0x0042, "BinaryOutMinimumOffTime",&Z_Copy }, + { 0x0010, 0x0043, "BinaryOutMinimumOnTime",&Z_Copy }, + { 0x0010, 0x0051, "BinaryOutOutOfService",&Z_Copy }, + { 0x0010, 0x0054, "BinaryOutPolarity", &Z_Copy }, + { 0x0010, 0x0055, "BinaryOutValue", &Z_Copy }, + { 0x0010, 0x0057, "BinaryOutPriorityArray",&Z_Copy }, + { 0x0010, 0x0067, "BinaryOutReliability", &Z_Copy }, + { 0x0010, 0x0068, "BinaryOutRelinquishDefault",&Z_Copy }, + { 0x0010, 0x006F, "BinaryOutStatusFlags", &Z_Copy }, + { 0x0010, 0x0100, "BinaryOutApplicationType",&Z_Copy }, // Binary Value cluster - { 0x0011, 0x0004, "ActiveText", &Z_Copy }, - { 0x0011, 0x001C, "Description", &Z_Copy }, - { 0x0011, 0x002E, "InactiveText", &Z_Copy }, - { 0x0011, 0x0042, "MinimumOffTime", &Z_Copy }, - { 0x0011, 0x0043, "MinimumOnTime", &Z_Copy }, - { 0x0011, 0x0051, "OutOfService", &Z_Copy }, - { 0x0011, 0x0055, "PresentValue", &Z_Copy }, - { 0x0011, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0011, 0x0067, "Reliability", &Z_Copy }, - { 0x0011, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0011, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0011, 0x0100, "ApplicationType", &Z_Copy }, + { 0x0011, 0x0004, "BinaryActiveText", &Z_Copy }, + { 0x0011, 0x001C, "BinaryDescription", &Z_Copy }, + { 0x0011, 0x002E, "BinaryInactiveText", &Z_Copy }, + { 0x0011, 0x0042, "BinaryMinimumOffTime", &Z_Copy }, + { 0x0011, 0x0043, "BinaryMinimumOnTime", &Z_Copy }, + { 0x0011, 0x0051, "BinaryOutOfService", &Z_Copy }, + { 0x0011, 0x0055, "BinaryValue", &Z_Copy }, + { 0x0011, 0x0057, "BinaryPriorityArray", &Z_Copy }, + { 0x0011, 0x0067, "BinaryReliability", &Z_Copy }, + { 0x0011, 0x0068, "BinaryRelinquishDefault",&Z_Copy }, + { 0x0011, 0x006F, "BinaryStatusFlags", &Z_Copy }, + { 0x0011, 0x0100, "BinaryApplicationType",&Z_Copy }, // Multistate Input cluster - { 0x0012, 0x000E, "StateText", &Z_Copy }, - { 0x0012, 0x001C, "Description", &Z_Copy }, - { 0x0012, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0012, 0x0051, "OutOfService", &Z_Copy }, - { 0x0012, 0x0055, "PresentValue", &Z_AqaraCube }, - { 0x0012, 0x0067, "Reliability", &Z_Copy }, - { 0x0012, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0012, 0x0100, "ApplicationType", &Z_Copy }, + { 0x0012, 0x000E, "MultiInStateText", &Z_Copy }, + { 0x0012, 0x001C, "MultiInDescription", &Z_Copy }, + { 0x0012, 0x004A, "MultiInNumberOfStates",&Z_Copy }, + { 0x0012, 0x0051, "MultiInOutOfService", &Z_Copy }, + { 0x0012, 0x0055, "MultiInValue", &Z_AqaraCube }, + { 0x0012, 0x0067, "MultiInReliability", &Z_Copy }, + { 0x0012, 0x006F, "MultiInStatusFlags", &Z_Copy }, + { 0x0012, 0x0100, "MultiInApplicationType",&Z_Copy }, // Multistate output - { 0x0013, 0x000E, "StateText", &Z_Copy }, - { 0x0013, 0x001C, "Description", &Z_Copy }, - { 0x0013, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0013, 0x0051, "OutOfService", &Z_Copy }, - { 0x0013, 0x0055, "PresentValue", &Z_Copy }, - { 0x0013, 0x0057, "PriorityArray", &Z_Copy }, - { 0x0013, 0x0067, "Reliability", &Z_Copy }, - { 0x0013, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0013, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0013, 0x0100, "ApplicationType", &Z_Copy }, + { 0x0013, 0x000E, "MultiOutStateText", &Z_Copy }, + { 0x0013, 0x001C, "MultiOutDescription", &Z_Copy }, + { 0x0013, 0x004A, "MultiOutNumberOfStates",&Z_Copy }, + { 0x0013, 0x0051, "MultiOutOutOfService", &Z_Copy }, + { 0x0013, 0x0055, "MultiOutValue", &Z_Copy }, + { 0x0013, 0x0057, "MultiOutPriorityArray",&Z_Copy }, + { 0x0013, 0x0067, "MultiOutReliability", &Z_Copy }, + { 0x0013, 0x0068, "MultiOutRelinquishDefault",&Z_Copy }, + { 0x0013, 0x006F, "MultiOutStatusFlags", &Z_Copy }, + { 0x0013, 0x0100, "MultiOutApplicationType",&Z_Copy }, // Multistate Value cluster - { 0x0014, 0x000E, "StateText", &Z_Copy }, - { 0x0014, 0x001C, "Description", &Z_Copy }, - { 0x0014, 0x004A, "NumberOfStates", &Z_Copy }, - { 0x0014, 0x0051, "OutOfService", &Z_Copy }, - { 0x0014, 0x0055, "PresentValue", &Z_Copy }, - { 0x0014, 0x0067, "Reliability", &Z_Copy }, - { 0x0014, 0x0068, "RelinquishDefault", &Z_Copy }, - { 0x0014, 0x006F, "StatusFlags", &Z_Copy }, - { 0x0014, 0x0100, "ApplicationType", &Z_Copy }, + { 0x0014, 0x000E, "MultiStateText", &Z_Copy }, + { 0x0014, 0x001C, "MultiDescription", &Z_Copy }, + { 0x0014, 0x004A, "MultiNumberOfStates", &Z_Copy }, + { 0x0014, 0x0051, "MultiOutOfService", &Z_Copy }, + { 0x0014, 0x0055, "MultiValue", &Z_Copy }, + { 0x0014, 0x0067, "MultiReliability", &Z_Copy }, + { 0x0014, 0x0068, "MultiRelinquishDefault",&Z_Copy }, + { 0x0014, 0x006F, "MultiStatusFlags", &Z_Copy }, + { 0x0014, 0x0100, "MultiApplicationType", &Z_Copy }, // Power Profile cluster { 0x001A, 0x0000, "TotalProfileNum", &Z_Copy }, { 0x001A, 0x0001, "MultipleScheduling", &Z_Copy }, @@ -682,12 +762,12 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { { 0x0102, 0x0009, "CurrentPositionTiltPercentage",&Z_Copy }, { 0x0102, 0x0010, "InstalledOpenLimitLift",&Z_Copy }, { 0x0102, 0x0011, "InstalledClosedLimitLift",&Z_Copy }, - { 0x0102, 0x0012, "InstalledOpenLimitTilt", &Z_Copy }, - { 0x0102, 0x0013, "InstalledClosedLimitTilt", &Z_Copy }, - { 0x0102, 0x0014, "VelocityLift",&Z_Copy }, + { 0x0102, 0x0012, "InstalledOpenLimitTilt",&Z_Copy }, + { 0x0102, 0x0013, "InstalledClosedLimitTilt",&Z_Copy }, + { 0x0102, 0x0014, "VelocityLift", &Z_Copy }, { 0x0102, 0x0015, "AccelerationTimeLift",&Z_Copy }, - { 0x0102, 0x0016, "DecelerationTimeLift", &Z_Copy }, - { 0x0102, 0x0017, "Mode",&Z_Copy }, + { 0x0102, 0x0016, "DecelerationTimeLift", &Z_Copy }, + { 0x0102, 0x0017, "Mode", &Z_Copy }, { 0x0102, 0x0018, "IntermediateSetpointsLift",&Z_Copy }, { 0x0102, 0x0019, "IntermediateSetpointsTilt",&Z_Copy }, @@ -725,49 +805,49 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = { // Illuminance Measurement cluster { 0x0400, 0x0000, D_JSON_ILLUMINANCE, &Z_Copy }, // Illuminance (in Lux) - { 0x0400, 0x0001, "MinMeasuredValue", &Z_Copy }, // - { 0x0400, 0x0002, "MaxMeasuredValue", &Z_Copy }, // - { 0x0400, 0x0003, "Tolerance", &Z_Copy }, // - { 0x0400, 0x0004, "LightSensorType", &Z_Copy }, // + { 0x0400, 0x0001, "IlluminanceMinMeasuredValue", &Z_Copy }, // + { 0x0400, 0x0002, "IlluminanceMaxMeasuredValue", &Z_Copy }, // + { 0x0400, 0x0003, "IlluminanceTolerance", &Z_Copy }, // + { 0x0400, 0x0004, "IlluminanceLightSensorType", &Z_Copy }, // { 0x0400, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Illuminance Level Sensing cluster - { 0x0401, 0x0000, "LevelStatus", &Z_Copy }, // Illuminance (in Lux) - { 0x0401, 0x0001, "LightSensorType", &Z_Copy }, // LightSensorType + { 0x0401, 0x0000, "IlluminanceLevelStatus", &Z_Copy }, // Illuminance (in Lux) + { 0x0401, 0x0001, "IlluminanceLightSensorType", &Z_Copy }, // LightSensorType { 0x0401, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Temperature Measurement cluster { 0x0402, 0x0000, D_JSON_TEMPERATURE, &Z_FloatDiv100 }, // Temperature - { 0x0402, 0x0001, "MinMeasuredValue", &Z_FloatDiv100 }, // - { 0x0402, 0x0002, "MaxMeasuredValue", &Z_FloatDiv100 }, // - { 0x0402, 0x0003, "Tolerance", &Z_FloatDiv100 }, // + { 0x0402, 0x0001, "TemperatureMinMeasuredValue", &Z_FloatDiv100 }, // + { 0x0402, 0x0002, "TemperatureMaxMeasuredValue", &Z_FloatDiv100 }, // + { 0x0402, 0x0003, "TemperatureTolerance", &Z_FloatDiv100 }, // { 0x0402, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Pressure Measurement cluster { 0x0403, 0x0000, D_JSON_PRESSURE_UNIT, &Z_AddPressureUnit }, // Pressure Unit { 0x0403, 0x0000, D_JSON_PRESSURE, &Z_Copy }, // Pressure - { 0x0403, 0x0001, "MinMeasuredValue", &Z_Copy }, // - { 0x0403, 0x0002, "MaxMeasuredValue", &Z_Copy }, // - { 0x0403, 0x0003, "Tolerance", &Z_Copy }, // - { 0x0403, 0x0010, "ScaledValue", &Z_Copy }, // - { 0x0403, 0x0011, "MinScaledValue", &Z_Copy }, // - { 0x0403, 0x0012, "MaxScaledValue", &Z_Copy }, // - { 0x0403, 0x0013, "ScaledTolerance", &Z_Copy }, // - { 0x0403, 0x0014, "Scale", &Z_Copy }, // + { 0x0403, 0x0001, "PressureMinMeasuredValue", &Z_Copy }, // + { 0x0403, 0x0002, "PressureMaxMeasuredValue", &Z_Copy }, // + { 0x0403, 0x0003, "PressureTolerance", &Z_Copy }, // + { 0x0403, 0x0010, "PressureScaledValue", &Z_Copy }, // + { 0x0403, 0x0011, "PressureMinScaledValue", &Z_Copy }, // + { 0x0403, 0x0012, "PressureMaxScaledValue", &Z_Copy }, // + { 0x0403, 0x0013, "PressureScaledTolerance", &Z_Copy }, // + { 0x0403, 0x0014, "PressureScale", &Z_Copy }, // { 0x0403, 0xFFFF, nullptr, &Z_Remove }, // Remove all other Pressure values // Flow Measurement cluster { 0x0404, 0x0000, D_JSON_FLOWRATE, &Z_FloatDiv10 }, // Flow (in m3/h) - { 0x0404, 0x0001, "MinMeasuredValue", &Z_Copy }, // - { 0x0404, 0x0002, "MaxMeasuredValue", &Z_Copy }, // - { 0x0404, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0404, 0x0001, "FlowMinMeasuredValue", &Z_Copy }, // + { 0x0404, 0x0002, "FlowMaxMeasuredValue", &Z_Copy }, // + { 0x0404, 0x0003, "FlowTolerance", &Z_Copy }, // { 0x0404, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Relative Humidity Measurement cluster { 0x0405, 0x0000, D_JSON_HUMIDITY, &Z_FloatDiv100 }, // Humidity - { 0x0405, 0x0001, "MinMeasuredValue", &Z_Copy }, // - { 0x0405, 0x0002, "MaxMeasuredValue", &Z_Copy }, // - { 0x0405, 0x0003, "Tolerance", &Z_Copy }, // + { 0x0405, 0x0001, "HumidityMinMeasuredValue", &Z_Copy }, // + { 0x0405, 0x0002, "HumidityMaxMeasuredValue", &Z_Copy }, // + { 0x0405, 0x0003, "HumidityTolerance", &Z_Copy }, // { 0x0405, 0xFFFF, nullptr, &Z_Remove }, // Remove all other values // Occupancy Sensing cluster @@ -837,6 +917,11 @@ int32_t Z_FloatDiv10(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json[new_name] = ((float)value) / 10.0f; return 1; // remove original key } +// Convert int to float and divide by 10 +int32_t Z_FloatDiv2(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& json, const char *name, JsonVariant& value, const String &new_name, uint16_t cluster, uint16_t attr) { + json[new_name] = ((float)value) / 2.0f; + return 1; // remove original key +} // Publish a message for `"Occupancy":0` when the timer expired int32_t Z_OccupancyCallback(uint16_t shortaddr, uint16_t cluster, uint16_t endpoint, uint32_t value) { @@ -947,9 +1032,6 @@ int32_t Z_AqaraVibration(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObje int32_t Angle_X = 0.5f + atanf(X/sqrtf(z*z+y*y)) * f_180pi; int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(x*x+z*z)) * f_180pi; int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(x*x+y*y)) * f_180pi; - // int32_t Angle_X = 0.5f + atanf(X/sqrtf(Z*Z+Y*Y)) * f_180pi; - // int32_t Angle_Y = 0.5f + atanf(Y/sqrtf(X*X+Z*Z)) * f_180pi; - // int32_t Angle_Z = 0.5f + atanf(Z/sqrtf(X*X+Y*Y)) * f_180pi; JsonArray& angles = json.createNestedArray(F("AqaraAngles")); angles.add(Angle_X); angles.add(Angle_Y); @@ -968,6 +1050,7 @@ int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& char tmp[] = "tmp"; // for obscure reasons, it must be converted from const char* to char*, otherwise ArduinoJson gets confused JsonVariant sub_value; + const String * modelId = zigbee_devices.getModelId(shortaddr); // null if unknown while (len - i >= 2) { uint8_t attrid = buf2.get8(i++); @@ -975,25 +1058,43 @@ int32_t Z_AqaraSensor(const class ZCLFrame *zcl, uint16_t shortaddr, JsonObject& i += parseSingleAttribute(json, tmp, buf2, i, len); float val = json[tmp]; json.remove(tmp); + bool translated = false; // were we able to translate to a known format? if (0x01 == attrid) { json[F(D_JSON_VOLTAGE)] = val / 1000.0f; json[F("Battery")] = toPercentageCR2032(val); - } else if (0 == zcl->getManufCode()) { - // onla Aqara Temp/Humidity has manuf_code of zero. If non-zero we skip the parameters - if (0x64 == attrid) { - json[F(D_JSON_TEMPERATURE)] = val / 100.0f; - } else if (0x65 == attrid) { - json[F(D_JSON_HUMIDITY)] = val / 100.0f; - } else if (0x66 == attrid) { - json[F(D_JSON_PRESSURE)] = val / 100.0f; - json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa - } else if (0x01 == attrid) { - json[F(D_JSON_VOLTAGE)] = val / 1000.0f; - json[F("Battery")] = toPercentageCR2032(val); + } else if ((nullptr != modelId) && (0 == zcl->getManufCode())) { + translated = true; + if (modelId->startsWith(F("lumi.sensor_ht")) || + modelId->startsWith(F("lumi.weather"))) { // Temp sensor + // Filter according to prefix of model name + // onla Aqara Temp/Humidity has manuf_code of zero. If non-zero we skip the parameters + if (0x64 == attrid) { + json[F(D_JSON_TEMPERATURE)] = val / 100.0f; + } else if (0x65 == attrid) { + json[F(D_JSON_HUMIDITY)] = val / 100.0f; + } else if (0x66 == attrid) { + json[F(D_JSON_PRESSURE)] = val / 100.0f; + json[F(D_JSON_PRESSURE_UNIT)] = F(D_UNIT_PRESSURE); // hPa + } + } else if (modelId->startsWith(F("lumi.sensor_smoke"))) { // gas leak + if (0x64 == attrid) { + json[F("SmokeDensity")] = val; + } + } else if (modelId->startsWith(F("lumi.sensor_natgas"))) { // gas leak + if (0x64 == attrid) { + json[F("GasDensity")] = val; + } + } else { + translated = false; // we didn't find a match + } + // } else if (0x115F == zcl->getManufCode()) { // Aqara Motion Sensor, still unknown field + } + if (!translated) { + if (attrid >= 100) { // payload is always above 0x64 or 100 + char attr_name[12]; + snprintf_P(attr_name, sizeof(attr_name), PSTR("Xiaomi_%02X"), attrid); + json[attr_name] = val; } - } else if (0x115F == zcl->getManufCode()) { - // Aqara Motion Sensor, still unknown field - json[F("AqaraUnknown")] = val; } } return 1; // remove original key diff --git a/tasmota/xdrv_23_zigbee_6_commands.ino b/tasmota/xdrv_23_zigbee_6_commands.ino index 5c3e3fc1b..3d8d378b0 100644 --- a/tasmota/xdrv_23_zigbee_6_commands.ino +++ b/tasmota/xdrv_23_zigbee_6_commands.ino @@ -36,8 +36,14 @@ typedef struct Z_XYZ_Var { // Holds values for vairables X, Y and Z uint8_t z_type = 0; } Z_XYZ_Var; -// list of post-processing directives -const Z_CommandConverter Z_Commands[] = { +// Cluster specific commands +// Note: the table is both for sending commands, but also displaying received commands +// - tasmota_cmd: the human-readable name of the command as entered or displayed, use '|' to split into multiple commands when displayed +// - cluster: cluster number of the command +// - cmd: the command number, of 0xFF if it's actually a variable to be assigned from 'xx' +// - direction: the direction of the command (bit field). 0x01=from client to server (coord to device), 0x02= from server to client (response), 0x80=needs specific decoding +// - param: the paylod template, x/y/z are substituted with arguments, little endian. For command display, payload must match until x/y/z character or until the end of the paylod. '??' means ignore. +const Z_CommandConverter Z_Commands[] PROGMEM = { // Group adress commands { "AddGroup", 0x0004, 0x00, 0x01, "xxxx00" }, // Add group id, group name is not supported { "ViewGroup", 0x0004, 0x01, 0x01, "xxxx" }, // Ask for the group name @@ -65,7 +71,7 @@ const Z_CommandConverter Z_Commands[] = { { "ShutterTilt", 0x0102, 0x08, 0x01, "xx" }, // Tilt percentage { "Shutter", 0x0102, 0xFF, 0x01, "" }, // Blitzwolf PIR - { "Occupancy", 0xEF00, 0x01, 0x01, "xx"}, // Specific decoder for Blitzwolf PIR, empty name means special treatment + { "Occupancy", 0xEF00, 0x01, 0x82, ""}, // Specific decoder for Blitzwolf PIR, empty name means special treatment // Decoders only - normally not used to send, and names may be masked by previous definitions { "Dimmer", 0x0008, 0x00, 0x01, "xx" }, { "DimmerMove", 0x0008, 0x01, 0x01, "xx0A" }, @@ -85,15 +91,14 @@ const Z_CommandConverter Z_Commands[] = { { "ArrowHold", 0x0005, 0x08, 0x01, "xx" }, // xx == 0x01 = left, 0x00 = right { "ArrowRelease", 0x0005, 0x09, 0x01, "" }, // IAS - Intruder Alarm System + leak/fire detection - { "ZoneStatusChange",0x0500, 0x00, 0x02, "xxxxyyzz" }, // xxxx = zone status, yy = extended status, zz = zone id, Delay is ignored + { "ZoneStatusChange",0x0500, 0x00, 0x82, "xxxxyyzz" }, // xxxx = zone status, yy = extended status, zz = zone id, Delay is ignored // responses for Group cluster commands - { "AddGroupResp", 0x0004, 0x00, 0x02, "xxyyyy" }, // xx = status, yy = group id - { "ViewGroupResp", 0x0004, 0x01, 0x02, "xxyyyy" }, // xx = status, yy = group id, name ignored - { "GetGroupResp", 0x0004, 0x02, 0x02, "xxyyzzzz" }, // xx = capacity, yy = count, zzzz = first group id, following groups ignored - { "RemoveGroup", 0x0004, 0x03, 0x02, "xxyyyy" }, // xx = status, yy = group id + { "AddGroup", 0x0004, 0x00, 0x82, "xxyyyy" }, // xx = status, yy = group id + { "ViewGroup", 0x0004, 0x01, 0x82, "xxyyyy" }, // xx = status, yy = group id, name ignored + { "GetGroup", 0x0004, 0x02, 0x82, "xxyyzzzz" }, // xx = capacity, yy = count, zzzz = first group id, following groups ignored + { "RemoveGroup", 0x0004, 0x03, 0x82, "xxyyyy" }, // xx = status, yy = group id }; - #define ZLE(x) ((x) & 0xFF), ((x) >> 8) // Little Endian // Below are the attributes we wand to read from each cluster @@ -235,16 +240,20 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo ToHex_P((unsigned char*)payload.getBuffer(), payload.len(), hex_char, hex_char_len); const __FlashStringHelper* command_name = nullptr; + uint8_t conv_direction; Z_XYZ_Var xyz; //AddLog_P2(LOG_LEVEL_INFO, PSTR(">>> len = %d - %02X%02X%02X"), payload.len(), payload.get8(0), payload.get8(1), payload.get8(2)); for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { const Z_CommandConverter *conv = &Z_Commands[i]; - if (conv->cluster == cluster) { + uint16_t conv_cluster = pgm_read_word(&conv->cluster); + if (conv_cluster == cluster) { // cluster match - if ((0xFF == conv->cmd) || (cmd == conv->cmd)) { + uint8_t conv_cmd = pgm_read_byte(&conv->cmd); + conv_direction = pgm_read_byte(&conv->direction); + if ((0xFF == conv_cmd) || (cmd == conv_cmd)) { // cmd match - if ((direction && (conv->direction & 0x02)) || (!direction && (conv->direction & 0x01))) { + if ((direction && (conv_direction & 0x02)) || (!direction && (conv_direction & 0x01))) { // check if we have a match for params too // Match if: // - payload exactly matches conv->param (conv->param may be longer) @@ -271,7 +280,7 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo if (match) { command_name = (const __FlashStringHelper*) conv->tasmota_cmd; parseXYZ(conv->param, payload, &xyz); - if (0xFF == conv->cmd) { + if (0xFF == conv_cmd) { // shift all values xyz.z = xyz.y; xyz.z_type = xyz.y_type; @@ -296,31 +305,63 @@ void convertClusterSpecific(JsonObject& json, uint16_t cluster, uint8_t cmd, boo free(hex_char); if (command_name) { - if (0 == xyz.x_type) { - json[command_name] = true; // no parameter - } else if (0 == xyz.y_type) { - json[command_name] = xyz.x; // 1 parameter + // Now try to transform into a human readable format + // if (direction & 0x80) then specific transform + if (conv_direction & 0x80) { + // TODO need to create a specific command + // IAS + String command_name2 = String(command_name); + if ((cluster == 0x0500) && (cmd == 0x00)) { + // "ZoneStatusChange" + json[command_name] = xyz.x; + json[command_name2 + "Ext"] = xyz.y; + json[command_name2 + "Zone"] = xyz.z; + } else if ((cluster == 0x0004) && ((cmd == 0x00) || (cmd == 0x01) || (cmd == 0x03))) { + // AddGroupResp or ViewGroupResp (group name ignored) or RemoveGroup + json[command_name] = xyz.y; + json[command_name2 + "Status"] = xyz.x; + json[command_name2 + "StatusMsg"] = getZigbeeStatusMessage(xyz.x); + } else if ((cluster == 0x0004) && (cmd == 0x02)) { + // GetGroupResp + json[command_name2 + "Capacity"] = xyz.x; + json[command_name2 + "Count"] = xyz.y; + JsonArray &arr = json.createNestedArray(command_name); + for (uint32_t i = 0; i < xyz.y; i++) { + arr.add(payload.get16(2 + 2*i)); + } + //arr.add(xyz.z); + } } else { - // multiple answers, create an array - JsonArray &arr = json.createNestedArray(command_name); - arr.add(xyz.x); - arr.add(xyz.y); - if (xyz.z_type) { - arr.add(xyz.z); + if (0 == xyz.x_type) { + json[command_name] = true; // no parameter + } else if (0 == xyz.y_type) { + json[command_name] = xyz.x; // 1 parameter + } else { + // multiple answers, create an array + JsonArray &arr = json.createNestedArray(command_name); + arr.add(xyz.x); + arr.add(xyz.y); + if (xyz.z_type) { + arr.add(xyz.z); + } } } } } // Find the command details by command name +// Only take commands outgoing, i.e. direction == 0 // If not found: // - returns nullptr const __FlashStringHelper* zigbeeFindCommand(const char *command, uint16_t *cluster, uint16_t *cmd) { for (uint32_t i = 0; i < sizeof(Z_Commands) / sizeof(Z_Commands[0]); i++) { const Z_CommandConverter *conv = &Z_Commands[i]; - if (0 == strcasecmp_P(command, conv->tasmota_cmd)) { - *cluster = conv->cluster; - *cmd = conv->cmd; + uint8_t conv_direction = pgm_read_byte(&conv->direction); + uint8_t conv_cmd = pgm_read_byte(&conv->cmd); + uint16_t conv_cluster = pgm_read_word(&conv->cluster); + if ((conv_direction & 0x01) && (0 == strcasecmp_P(command, conv->tasmota_cmd))) { + *cluster = conv_cluster; + *cmd = conv_cmd; return (const __FlashStringHelper*) conv->param; } } diff --git a/tasmota/xdrv_23_zigbee_7_statemachine.ino b/tasmota/xdrv_23_zigbee_7_statemachine.ino index d0616a40b..015a07ab4 100644 --- a/tasmota/xdrv_23_zigbee_7_statemachine.ino +++ b/tasmota/xdrv_23_zigbee_7_statemachine.ino @@ -33,7 +33,7 @@ const uint8_t ZIGBEE_STATUS_NODE_DESC = 31; // Node descriptor const uint8_t ZIGBEE_STATUS_ACTIVE_EP = 32; // Endpoints descriptor const uint8_t ZIGBEE_STATUS_SIMPLE_DESC = 33; // Simple Descriptor (clusters) const uint8_t ZIGBEE_STATUS_DEVICE_INDICATION = 34; // Device announces its address -const uint8_t ZIGBEE_STATUS_DEVICE_IEEE = 35; // Request of device address +//const uint8_t ZIGBEE_STATUS_DEVICE_IEEE = 35; // Request of device address const uint8_t ZIGBEE_STATUS_CC_VERSION = 50; // Status: CC2530 ZNP Version const uint8_t ZIGBEE_STATUS_CC_INFO = 51; // Status: CC2530 Device Configuration const uint8_t ZIGBEE_STATUS_UNSUPPORTED_VERSION = 98; // Unsupported ZNP version @@ -49,9 +49,6 @@ typedef union Zigbee_Instruction { uint16_t d16; // 16 bits data } i; const void *p; // pointer - // const void *m; // for type checking only, message - // const ZB_Func f; - // const ZB_RecvMsgFunc fr; } Zigbee_Instruction; // // Zigbee_Instruction z1 = { .i = {1,2,3}}; diff --git a/tasmota/xdrv_23_zigbee_8_parsers.ino b/tasmota/xdrv_23_zigbee_8_parsers.ino index 9e336d0c1..859351438 100644 --- a/tasmota/xdrv_23_zigbee_8_parsers.ino +++ b/tasmota/xdrv_23_zigbee_8_parsers.ino @@ -39,7 +39,7 @@ int32_t Z_ReceiveDeviceInfo(int32_t res, class SBuffer &buf) { char hex[20]; Uint64toHex(long_adr, hex, 64); Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + "\"Status\":%d,\"IEEEAddr\":\"0x%s\",\"ShortAddr\":\"0x%04X\"" ",\"DeviceType\":%d,\"DeviceState\":%d" ",\"NumAssocDevices\":%d"), ZIGBEE_STATUS_CC_INFO, hex, short_adr, device_type, device_state, @@ -355,21 +355,24 @@ int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { zigbee_devices.updateDevice(nwkAddr, ieeeAddr); char hex[20]; Uint64toHex(ieeeAddr, hex, 64); - Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" - "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" - "}}"), - ZIGBEE_STATUS_DEVICE_IEEE, hex, nwkAddr - ); + // Response_P(PSTR("{\"" D_JSON_ZIGBEE_STATE "\":{" + // "\"Status\":%d,\"IEEEAddr\":\"%s\",\"ShortAddr\":\"0x%04X\"" + // "}}"), + // ZIGBEE_STATUS_DEVICE_IEEE, hex, nwkAddr + // ); - MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); - XdrvRulesProcess(); + // MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + // XdrvRulesProcess(); // Ping response const String * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); if (friendlyName) { Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" - ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), nwkAddr, friendlyName->c_str()); + ",\"" D_JSON_ZIGBEE_IEEE "\":\"0x%s\"" + ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"}}"), nwkAddr, hex, friendlyName->c_str()); } else { - Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"}}"), nwkAddr); + Response_P(PSTR("{\"" D_JSON_ZIGBEE_PING "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_IEEE "\":\"0x%s\"" + "}}"), nwkAddr, hex); } MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); @@ -378,6 +381,27 @@ int32_t Z_ReceiveIEEEAddr(int32_t res, const class SBuffer &buf) { return -1; } +int32_t Z_BindRsp(int32_t res, const class SBuffer &buf) { + Z_ShortAddress nwkAddr = buf.get16(2); + uint8_t status = buf.get8(4); + + const String * friendlyName = zigbee_devices.getFriendlyName(nwkAddr); + if (friendlyName) { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_NAME "\":\"%s\"" + ",\"" D_JSON_ZIGBEE_Status "\":%d" + "}}"), nwkAddr, friendlyName->c_str(), status); + } else { + Response_P(PSTR("{\"" D_JSON_ZIGBEE_BIND "\":{\"" D_JSON_ZIGBEE_DEVICE "\":\"0x%04X\"" + ",\"" D_JSON_ZIGBEE_Status "\":%d" + "}}"), nwkAddr, status); + } + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCL_RECEIVED)); + XdrvRulesProcess(); + + return -1; +} + int32_t Z_ReceiveEndDeviceAnnonce(int32_t res, const class SBuffer &buf) { Z_ShortAddress srcAddr = buf.get16(2); Z_ShortAddress nwkAddr = buf.get16(4); @@ -480,36 +504,45 @@ int32_t Z_ReceiveAfIncomingMessage(int32_t res, const class SBuffer &buf) { DynamicJsonBuffer jsonBuffer; JsonObject& json = jsonBuffer.createObject(); - if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { - zcl_received.parseRawAttributes(json); - if (clusterid) { defer_attributes = true; } // don't defer system Cluster=0 messages - } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { - zcl_received.parseReadAttributes(json); - } else if (zcl_received.isClusterSpecificCommand()) { - zcl_received.parseClusterSpecificCommand(json); - } - String msg(""); - msg.reserve(100); - json.printTo(msg); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); - - zcl_received.postProcessAttributes(srcaddr, json); - // Add Endpoint - json[F(D_CMND_ZIGBEE_ENDPOINT)] = srcendpoint; - // Add linkquality - json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; - - if (defer_attributes) { - // Prepare for publish - if (zigbee_devices.jsonIsConflict(srcaddr, json)) { - // there is conflicting values, force a publish of the previous message now and don't coalesce - zigbee_devices.jsonPublishFlush(srcaddr); + if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_DEFAULT_RESPONSE == zcl_received.getCmdId())) { + zcl_received.parseResponse(); + } else { + // Build the ZbReceive json + if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_REPORT_ATTRIBUTES == zcl_received.getCmdId())) { + zcl_received.parseRawAttributes(json); + if (clusterid) { defer_attributes = true; } // don't defer system Cluster=0 messages + } else if ( (!zcl_received.isClusterSpecificCommand()) && (ZCL_READ_ATTRIBUTES_RESPONSE == zcl_received.getCmdId())) { + zcl_received.parseReadAttributes(json); + } else if (zcl_received.isClusterSpecificCommand()) { + zcl_received.parseClusterSpecificCommand(json); + } + String msg(""); + msg.reserve(100); + json.printTo(msg); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZCL_RAW_RECEIVED ": {\"0x%04X\":%s}"), srcaddr, msg.c_str()); + + zcl_received.postProcessAttributes(srcaddr, json); + // Add Endpoint + json[F(D_CMND_ZIGBEE_ENDPOINT)] = srcendpoint; + // Add Group if non-zero + if (groupid) { + json[F(D_CMND_ZIGBEE_GROUP)] = groupid; + } + // Add linkquality + json[F(D_CMND_ZIGBEE_LINKQUALITY)] = linkquality; + + if (defer_attributes) { + // Prepare for publish + if (zigbee_devices.jsonIsConflict(srcaddr, json)) { + // there is conflicting values, force a publish of the previous message now and don't coalesce + zigbee_devices.jsonPublishFlush(srcaddr); + } + zigbee_devices.jsonAppend(srcaddr, json); + zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); + } else { + // Publish immediately + zigbee_devices.jsonPublishNow(srcaddr, json); } - zigbee_devices.jsonAppend(srcaddr, json); - zigbee_devices.setTimer(srcaddr, USE_ZIGBEE_COALESCE_ATTR_TIMER, clusterid, srcendpoint, 0, &Z_PublishAttributes); - } else { - // Publish immediately - zigbee_devices.jsonPublishNow(srcaddr, json); } return -1; } @@ -527,6 +560,7 @@ ZBM(AREQ_PERMITJOIN_OPEN_XX, Z_AREQ | Z_ZDO, ZDO_PERMIT_JOIN_IND ) // 45CB ZBM(AREQ_ZDO_ACTIVEEPRSP, Z_AREQ | Z_ZDO, ZDO_ACTIVE_EP_RSP) // 4585 ZBM(AREQ_ZDO_SIMPLEDESCRSP, Z_AREQ | Z_ZDO, ZDO_SIMPLE_DESC_RSP) // 4584 ZBM(AREQ_ZDO_IEEE_ADDR_RSP, Z_AREQ | Z_ZDO, ZDO_IEEE_ADDR_RSP) // 4581 +ZBM(AREQ_ZDO_BIND_RSP, Z_AREQ | Z_ZDO, ZDO_BIND_RSP) // 45A1 const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_AF_INCOMING_MESSAGE, &Z_ReceiveAfIncomingMessage }, @@ -537,6 +571,7 @@ const Z_Dispatcher Z_DispatchTable[] PROGMEM = { { AREQ_ZDO_ACTIVEEPRSP, &Z_ReceiveActiveEp }, { AREQ_ZDO_SIMPLEDESCRSP, &Z_ReceiveSimpleDesc }, { AREQ_ZDO_IEEE_ADDR_RSP, &Z_ReceiveIEEEAddr }, + { AREQ_ZDO_BIND_RSP, &Z_BindRsp }, }; int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) { diff --git a/tasmota/xdrv_23_zigbee_9_impl.ino b/tasmota/xdrv_23_zigbee_9_impl.ino index 08055ba9e..3ed971b0e 100644 --- a/tasmota/xdrv_23_zigbee_9_impl.ino +++ b/tasmota/xdrv_23_zigbee_9_impl.ino @@ -33,22 +33,16 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" - D_CMND_ZIGBEE_PING ; - -const char kZigbeeCommands[] PROGMEM = D_PRFX_ZIGBEE "|" // legacy prefix -- deprecated - D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" - D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" - D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEE_READ "|" D_CMND_ZIGBEEZNPRECEIVE "|" - D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_BIND "|" - D_CMND_ZIGBEE_PING ; + D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" + D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID + ; void (* const ZigbeeCommand[])(void) PROGMEM = { &CmndZbZNPSend, &CmndZbPermitJoin, &CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe, &CmndZbRead, &CmndZbZNPReceive, - &CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbBind, - &CmndZbPing, + &CmndZbForget, &CmndZbSave, &CmndZbName, + &CmndZbBind, &CmndZbPing, &CmndZbModelId, }; int32_t ZigbeeProcessInput(class SBuffer &buf) { @@ -547,35 +541,75 @@ void CmndZbBind(void) { // params // static char delim[] = ", "; // delimiters for parameters - uint16_t device = 0xFFFF; // 0xFFFF is broadcast, so considered valid - uint8_t endpoint = 0x00; // 0x00 is invalid for the dst endpoint + uint16_t srcDevice = 0xFFFF; // 0xFFFF is broadcast, so considered invalid + uint16_t dstDevice = 0xFFFF; // 0xFFFF is broadcast, so considered invalid + uint64_t dstLongAddr = 0; + uint8_t endpoint = 0x00; // 0x00 is invalid for the src endpoint + uint8_t toendpoint = 0x00; // 0x00 is invalid for the dst endpoint + uint16_t toGroup = 0x0000; // group address uint16_t cluster = 0; // 0xFFFF is invalid uint32_t group = 0xFFFFFFFF; // 16 bits values, otherwise 0xFFFFFFFF is unspecified + // Information about source device: "Device", "Endpoint", "Cluster" + // - the source endpoint must have a known IEEE address const JsonVariant &val_device = getCaseInsensitive(json, PSTR("Device")); if (nullptr != &val_device) { - device = zigbee_devices.parseDeviceParam(val_device.as()); - if (0xFFFF == device) { ResponseCmndChar("Invalid parameter"); return; } + srcDevice = zigbee_devices.parseDeviceParam(val_device.as()); + if (0xFFFF == srcDevice) { ResponseCmndChar("Invalid parameter"); return; } } - if ((nullptr == &val_device) || (0x000 == device)) { ResponseCmndChar("Unknown device"); return; } - + if ((nullptr == &val_device) || (0x0000 == srcDevice)) { ResponseCmndChar("Unknown source device"); return; } + // check if IEEE address is known + uint64_t srcLongAddr = zigbee_devices.getDeviceLongAddr(srcDevice); + if (0 == srcLongAddr) { ResponseCmndChar("Unknown source IEEE address"); return; } + // look for source endpoint const JsonVariant &val_endpoint = getCaseInsensitive(json, PSTR("Endpoint")); if (nullptr != &val_endpoint) { endpoint = strToUInt(val_endpoint); } + // look for source cluster const JsonVariant &val_cluster = getCaseInsensitive(json, PSTR("Cluster")); if (nullptr != &val_cluster) { cluster = strToUInt(val_cluster); } - // TODO compute endpoint from cluster + // Either Device address + // In this case the following parameters are mandatory + // - "ToDevice" and the device must have a known IEEE address + // - "ToEndpoint" + const JsonVariant &dst_device = getCaseInsensitive(json, PSTR("ToDevice")); + if (nullptr != &dst_device) { + dstDevice = zigbee_devices.parseDeviceParam(dst_device.as()); + if (0xFFFF == dstDevice) { ResponseCmndChar("Invalid parameter"); return; } + if (0x0000 == dstDevice) { + dstLongAddr = localIEEEAddr; + } else { + dstLongAddr = zigbee_devices.getDeviceLongAddr(dstDevice); + } + if (0 == dstLongAddr) { ResponseCmndChar("Unknown dest IEEE address"); return; } + + const JsonVariant &val_toendpoint = getCaseInsensitive(json, PSTR("ToEndpoint")); + if (nullptr != &val_toendpoint) { toendpoint = strToUInt(val_endpoint); } else { toendpoint = endpoint; } + } + + // Or Group Address - we don't need a dstEndpoint in this case + const JsonVariant &to_group = getCaseInsensitive(json, PSTR("ToGroup")); + if (nullptr != &to_group) { toGroup = strToUInt(to_group); } + + // make sure we don't have conflicting parameters + if (toGroup && dstLongAddr) { ResponseCmndChar("Cannot have both \"ToDevice\" and \"ToGroup\""); return; } + if (!toGroup && !dstLongAddr) { ResponseCmndChar("Missing \"ToDevice\" or \"ToGroup\""); return; } SBuffer buf(sizeof(ZBS_BIND_REQ)); buf.add8(Z_SREQ | Z_ZDO); buf.add8(ZDO_BIND_REQ); - buf.add16(device); - buf.add64(zigbee_devices.getDeviceLongAddr(device)); + buf.add16(srcDevice); + buf.add64(srcLongAddr); buf.add8(endpoint); buf.add16(cluster); - buf.add8(0x03); // DstAddrMode - 0x03 = ADDRESS_64_BIT - buf.add64(localIEEEAddr); // coordinatore IEEE address - buf.add8(0x01); // local endpoint = 1 + if (dstLongAddr) { + buf.add8(Z_Addr_IEEEAddress); // DstAddrMode - 0x03 = ADDRESS_64_BIT + buf.add64(dstLongAddr); + buf.add8(toendpoint); + } else { + buf.add8(Z_Addr_Group); // DstAddrMode - 0x01 = GROUP_ADDRESS + buf.add16(toGroup); + } ZigbeeZNPSend(buf.getBuffer(), buf.len()); @@ -635,6 +669,35 @@ void CmndZbName(void) { } } +// Specify, read or erase a ModelId, only for debug purposes +void CmndZbModelId(void) { + // Syntax is: + // ZigbeeName , - assign a friendly name + // ZigbeeName - display the current friendly name + // ZigbeeName , - remove friendly name + // + // Where can be: short_addr, long_addr, device_index, friendly_name + + if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } + + // check if parameters contain a comma ',' + char *p; + char *str = strtok_r(XdrvMailbox.data, ", ", &p); + + // parse first part, + uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data, true); // in case of short_addr, it must be already registered + if (0x0000 == shortaddr) { ResponseCmndChar("Unknown device"); return; } + if (0xFFFF == shortaddr) { ResponseCmndChar("Invalid parameter"); return; } + + if (p == nullptr) { + const String * modelId = zigbee_devices.getModelId(shortaddr); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, modelId ? modelId->c_str() : ""); + } else { + zigbee_devices.setModelId(shortaddr, p); + Response_P(PSTR("{\"0x%04X\":{\"" D_JSON_ZIGBEE_MODELID "\":\"%s\"}}"), shortaddr, p); + } +} + // Remove an old Zigbee device from the list of known devices, use ZigbeeStatus to know all registered devices void CmndZbForget(void) { if (zigbee.init_phase) { ResponseCmndChar(D_ZIGBEE_NOT_STARTED); return; } @@ -775,7 +838,6 @@ bool Xdrv23(uint8_t function) case FUNC_LOOP: if (ZigbeeSerial) { ZigbeeInput(); } if (zigbee.state_machine) { - //ZigbeeStateMachine(); ZigbeeStateMachine_Run(); } break; @@ -784,7 +846,6 @@ bool Xdrv23(uint8_t function) break; case FUNC_COMMAND: result = DecodeCommand(kZbCommands, ZigbeeCommand); - result = result || DecodeCommand(kZigbeeCommands, ZigbeeCommand); // deprecated break; } } From 82954e2928253a89edc8dfdd298abe4d78aa1263 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Mar 2020 13:52:01 +0100 Subject: [PATCH 532/559] Delete launch.json --- .theia/launch.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .theia/launch.json diff --git a/.theia/launch.json b/.theia/launch.json deleted file mode 100644 index a2ea02c46..000000000 --- a/.theia/launch.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - "version": "0.2.0", - "configurations": [] -} From 3343164da9a83f4ce432542d07e6c45c2237cbad Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Mar 2020 14:20:19 +0100 Subject: [PATCH 533/559] Add support for MaxBotix HRXL-MaxSonar Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) --- BUILDS.md | 1 + RELEASENOTES.md | 5 ++++- tasmota/CHANGELOG.md | 6 ++++-- tasmota/my_user_config.h | 1 + tasmota/support_features.ino | 6 ++++-- tasmota/tasmota_post.h | 4 ++++ tools/decode-status.py | 4 ++-- 7 files changed, 20 insertions(+), 7 deletions(-) diff --git a/BUILDS.md b/BUILDS.md index f09de3125..53ebba456 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -130,6 +130,7 @@ | USE_IBEACON | - | - | - | - | x | - | - | | USE_GPS | - | - | - | - | - | - | - | | USE_HM10 | - | - | - | - | x | - | - | +| USE_HRXL | - | - | - | - | x | - | - | | | | | | | | | | | USE_NRF24 | - | - | - | - | - | - | - | | USE_MIBLE | - | - | - | - | - | - | - | diff --git a/RELEASENOTES.md b/RELEASENOTES.md index d07bb254a..38ba097b4 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -57,10 +57,11 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers - Change Lights: simplified gamma correction and 10 bits internal computation - Change commands ``Prefix``, ``Ssid``, ``StateText``, ``NTPServer``, and ``FriendlyName`` displaying all items -- Change IRremoteESP8266 library updated to v2.7.3 +- Change IRremoteESP8266 library updated to v2.7.4 - Change Zigbee command prefix from ``Zigbee*`` to ``Zb*`` - Change MQTT message size with additional 200 characters - Change display of some date and time messages from "Wed Feb 19 10:45:12 2020" to "2020-02-19T10:45:12" +- Change switchmode 6 according to issue 7778 (#7831) - Fix Sonoff Bridge, Sc, L1, iFan03 and CSE7766 serial interface to forced speed, config and disable logging - Fix commands ``Display`` and ``Counter`` from overruling command processing (#7322) - Fix ``White`` added to light status (#7142) @@ -107,6 +108,8 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add initial support for Sensors AHT10 and AHT15 by Martin Wagner (#7596) - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) - Add Zigbee enhanced commands decoding, added ``ZbPing`` +- Add Zigbee features and improvements - Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) - Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) - Add support for Jarolift rollers by Keeloq algorithm +- Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 579d19975..4a30b6cad 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -3,9 +3,11 @@ ### 8.1.0.10 20200227 - Change default my_user_config.h driver and sensor support removing most sensors and adding most drivers -- Add support for Jarolift rollers by Keeloq algorithm - Change IRremoteESP8266 library updated to v2.7.4 -- Add Zigbee features and improvements +- Change switchmode 6 according to issue 7778 (#7831) +- Add support for Jarolift rollers by Keeloq algorithm +- Add Zigbee features and improvements and remove support for Zigbee commands starting with ``Zigbee...`` +- Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) ### 8.1.0.9 20200220 diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 06901fa12..b6300c9a4 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -554,6 +554,7 @@ //#define USE_GPS // Add support for GPS and NTP Server for becoming Stratus 1 Time Source (+3k1 code, +132 bytes RAM) // #define USE_FLOG // Add support for GPS logging in OTA's Flash (Experimental) (+2k9 code, +8 bytes RAM) //#define USE_HM10 // Add support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) +//#define USE_HRXL // Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) // -- Power monitoring sensors -------------------- #define USE_ENERGY_MARGIN_DETECTION // Add support for Energy Margin detection (+1k6 code) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 6a13573c1..c37216c14 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -531,9 +531,11 @@ void GetFeatures(void) feature6 = 0x00000000; #ifdef USE_KEELOQ - feature6 |= 0x00000001; // xdrv_36keeloq.ino + feature6 |= 0x00000001; // xdrv_36_keeloq.ino +#endif +#ifdef USE_HRXL + feature6 |= 0x00000002; // xsns_64_hrxl.ino #endif -// feature6 |= 0x00000002; // feature6 |= 0x00000004; // feature6 |= 0x00000008; diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index 2e3ed1e26..fd0183dc9 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -205,6 +205,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_IBEACON // Add support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) //#define USE_GPS // Add support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) #define USE_HM10 // Add support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) +#define USE_HRXL // Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) #define USE_ENERGY_SENSOR // Add energy sensors (-14k code) #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) @@ -424,6 +425,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) #undef USE_GPS // Disable support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) #undef USE_HM10 // Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) +#undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) //#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI @@ -521,6 +523,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) #undef USE_GPS // Disable support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) #undef USE_HM10 // Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) +#undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) //#undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_PZEM004T // Disable PZEM004T energy sensor @@ -640,6 +643,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module) #undef USE_GPS // Disable support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM) #undef USE_HM10 // Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) +#undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) #undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_PZEM004T // Disable PZEM004T energy sensor diff --git a/tools/decode-status.py b/tools/decode-status.py index 126b050aa..756f27dff 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -198,7 +198,7 @@ a_features = [[ "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", "USE_AHT1x","USE_WEMOS_MOTOR_V1","USE_DEVICE_GROUPS","USE_PWM_DIMMER" ],[ - "USE_KEELOQ","","","", + "USE_KEELOQ","USE_HRXL","","", "","","","", "","","","", "","","","", @@ -239,7 +239,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200228 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200301 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From 473892d5c925a0aef9975f299915d8f01b18391e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Mar 2020 15:31:08 +0100 Subject: [PATCH 534/559] Add updated experimental Sonoff D1 support Add updated experimental Sonoff D1 support (#7598) --- tasmota/my_user_config.h | 2 +- tasmota/support_features.ino | 4 +- tasmota/tasmota_post.h | 10 ++ tasmota/tasmota_template.h | 4 +- tasmota/xdrv_37_sonoff_d1.ino | 225 ++++++++++++++++++++++++++++++++++ tools/decode-status.py | 2 +- 6 files changed, 243 insertions(+), 4 deletions(-) create mode 100644 tasmota/xdrv_37_sonoff_d1.ino diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index b6300c9a4..77c0771ee 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -419,7 +419,7 @@ #define USE_PWM_DIMMER // Add support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #define USE_PWM_DIMMER_REMOTE // Add support for remote switches to PWM Dimmer, also adds device groups support (+0k7 code, also includes device groups) //#define USE_KEELOQ // Add support for Jarolift rollers by Keeloq algorithm (+4k5 code) -//#define USE_SONOFF_D1 // Add support for Sonoff D1 +#define USE_SONOFF_D1 // Add support for Sonoff D1 Dimmer (+0k7 code) // -- Optional light modules ---------------------- #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by // diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index c37216c14..4049d9cfe 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -536,7 +536,9 @@ void GetFeatures(void) #ifdef USE_HRXL feature6 |= 0x00000002; // xsns_64_hrxl.ino #endif -// feature6 |= 0x00000004; +#ifdef USE_SONOFF_D1 + feature6 |= 0x00000004; +#endif // feature6 |= 0x00000008; // feature6 |= 0x00000010; diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index fd0183dc9..7cf0fff75 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -117,6 +117,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #define USE_HOTPLUG // Add support for sensor HotPlug #undef USE_DEVICE_GROUPS // Disable support for device groups (+5k6 code) #undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) +#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code) +#define USE_SONOFF_D1 // Add support for Sonoff D1 Dimmer (+0k7 code) // -- Optional light modules ---------------------- #define USE_LIGHT // Add Dimmer/Light support @@ -305,6 +307,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) #undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer +#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code) +#undef USE_SONOFF_D1 // Disable support for Sonoff D1 Dimmer (+0k7 code) #undef USE_ENERGY_SENSOR // Disable energy sensors (-14k code) #undef USE_PZEM004T // Disable PZEM004T energy sensor @@ -384,6 +388,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) #undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer +#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code) +#undef USE_SONOFF_D1 // Disable support for Sonoff D1 Dimmer (+0k7 code) // -- Optional light modules ---------------------- //#undef USE_LIGHT // Also disable all Dimmer/Light support @@ -495,6 +501,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) #undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer +#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code) +//#undef USE_SONOFF_D1 // Disable support for Sonoff D1 Dimmer (+0k7 code) // -- Optional light modules ---------------------- //#undef USE_LIGHT // Also disable all Dimmer/Light support @@ -613,6 +621,8 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack #undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code) #undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code) #undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer +#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code) +#undef USE_SONOFF_D1 // Disable support for Sonoff D1 Dimmer (+0k7 code) // -- Optional light modules ---------------------- #undef USE_LIGHT // Disable support for lights diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index cdc976bb0..a45c456f8 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -2264,7 +2264,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0, // GPIO09 0, // GPIO10 // GPIO11 (SD_CMD Flash) - 0, 0, 0, 0, 0, 0 + 0, // GPIO12 + GPIO_LED1_INV, // GPIO13 WiFi Blue Led - Link and Power status + 0, 0, 0, 0 } }; diff --git a/tasmota/xdrv_37_sonoff_d1.ino b/tasmota/xdrv_37_sonoff_d1.ino new file mode 100644 index 000000000..b7f98c352 --- /dev/null +++ b/tasmota/xdrv_37_sonoff_d1.ino @@ -0,0 +1,225 @@ +/* + xdrv_37_sonoff_d1.ino - sonoff D1 dimmer support for Tasmota + + Copyright (C) 2020 Theo Arends and robbz23 (protocol analysis) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_SONOFF_D1 +/*********************************************************************************************\ + * Sonoff D1 dimmer 433 + * + * 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 + * AA 55 - Header + * 01 04 - Version? + * 00 0A - Following data length (10 bytes) + * 01 - Power state (00 = off, 01 = on, FF = ignore) + * 64 - Dimmer percentage (01 to 64 = 1 to 100%) + * FF FF FF FF FF FF FF FF - Not used + * 6C - CRC over bytes 2 to F (Addition) + * + * Based on Gravitate1: + * When I switch the light ON via the app, I get: + * AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C + * + * When I switch it OFF, I get: + * AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B + * + * When I set it to 1%, I get: + * AA 55 01 04 00 0A FF 01 FF FF FF FF FF FF FF FF 07 + * AB 55 FD F7 FF FF F5 01 FF FF FF FF FF FF FF FF 09 + * + * When I set it to 6%, I get: + * AA 55 01 04 00 0A FF 06 FF FF FF FF FF FF FF FF 0C + * AB 55 FD F7 FF FF F5 06 FF FF FF FF FF FF FF FF 0E + * + * When I set it to 100%, I get: + * AA 55 01 04 00 0A FF 64 FF FF FF FF FF FF FF FF 6A + * AB 55 FD F7 FF FF F5 64 FF FF FF FF FF FF FF FF 6C + * + * Based on robbz23: + * 00:17:59 CMD: Baudrate 9600 + * 00:17:59 SER: Set to 8N1 9600 bit/s + * 00:17:59 RSL: stat/tasmota_D9E56D/RESULT = {"Baudrate":9600} + * + * 00:25:32 CMD: SerialSend5 aa 55 01 04 00 0a 01 22 ffffffffffffffff 29 + * 00:25:32 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} + * + * 00:26:35 CMD: SerialSend5 aa 55 01 04 00 0a 01 22 ffffffffffffffff 2a + * 00:26:35 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} + * 00:26:35 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 00 05} + * + * 00:28:58 CMD: SerialSend5 aa 55 01 04 00 0a 01 01 ffffffffffffffff 09 + * 00:28:58 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} + * 00:28:58 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 00 05} + * + * 00:29:12 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 3C FF FF FF FF FF FF FF FF 44} + * 00:29:43 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 01 FF FF FF FF FF FF FF FF 09} + * 00:29:53 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C} + * + * 00:30:02 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A FF 1E FF FF FF FF FF FF FF FF 24} +\*********************************************************************************************/ + +#define XDRV_37 37 + +struct SONOFFD1 { + uint8_t receive_flag = 0; + uint8_t dimmer; +} SnfD1; + +/********************************************************************************************/ + +void SonoffD1Received(void) +{ + char svalue[32]; + + uint8_t action = serial_in_buffer[6]; + uint8_t dimmer = serial_in_buffer[7]; + + if (action < 2) { + // AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C - Power On, Dimmer 100% + // AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B - Power Off, Dimmer 100% + bool is_switch_change = (action != power); + if (is_switch_change) { + ExecuteCommandPower(1, action, SRC_SWITCH); + } + } + else if (0xFF == action) { + SnfD1.dimmer = dimmer; + bool is_brightness_change = SnfD1.dimmer != Settings.light_dimmer; + if (power && (SnfD1.dimmer > 0) && is_brightness_change) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), SnfD1.dimmer); + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + + // Send Acknowledge - Copy first 5 bytes, reset byte 6 and store crc in byte 7 + // AA 55 01 04 00 00 05 + serial_in_buffer[5] = 0; // Ack + serial_in_buffer[6] = 0; // Crc + for (uint32_t i = 0; i < 7; i++) { + if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } + Serial.write(serial_in_buffer[i]); + } +} + +bool SonoffD1SerialInput(void) +{ + uint8_t packet_length = 0; + + if (0xAA == serial_in_byte) { // 0xAA - Start of text + serial_in_byte_counter = 0; + SnfD1.receive_flag = true; + } + if (SnfD1.receive_flag) { + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + if (serial_in_byte_counter == 6) { + packet_length = 7 + serial_in_byte; // 8 or 17 + } + if (serial_in_byte_counter == packet_length) { + + // Sonoff D1 codes + // AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C - Power On, Dimmer 100% + // AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B - Power Off, Dimmer 100% + // AA 55 01 04 00 0A FF 01 FF FF FF FF FF FF FF FF 07 - Power ignore, Dimmer 1% + // AB 55 FD F7 FF FF F5 01 FF FF FF FF FF FF FF FF 09 - Response 2 + // AA 55 01 04 00 0A FF 06 FF FF FF FF FF FF FF FF 0C - Power ignore, Dimmer 6% + // AB 55 FD F7 FF FF F5 06 FF FF FF FF FF FF FF FF 0E - Response 2 + // AA 55 01 04 00 0A FF 64 FF FF FF FF FF FF FF FF 6A - Power ignore, Dimmer 100% + // AB 55 FD F7 FF FF F5 64 FF FF FF FF FF FF FF FF 6C - Response 2 + + AddLogSerial(LOG_LEVEL_DEBUG); + uint8_t crc = 0; + for (uint32_t i = 2; i < packet_length -1; i++) { + crc += serial_in_buffer[i]; + } + if (crc == serial_in_buffer[packet_length -1]) { + SonoffD1Received(); + SnfD1.receive_flag = false; + return true; + } + } + serial_in_byte = 0; + } + return false; +} + +/********************************************************************************************/ + +bool SonoffD1SendPower(void) +{ + uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; + + buffer[6] = XdrvMailbox.index; + + for (uint32_t i = 0; i < sizeof(buffer); i++) { + if ((i > 1) && (i < sizeof(buffer) -1)) { buffer[16] += buffer[i]; } + Serial.write(buffer[i]); + } + return true; +} + +bool SonoffD1SendDimmer(void) +{ + uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; + + buffer[7] = changeUIntScale(((uint16_t *)XdrvMailbox.data)[0], 0, 255, 0, 100); + + for (uint32_t i = 0; i < sizeof(buffer); i++) { + if ((i > 1) && (i < sizeof(buffer) -1)) { buffer[16] += buffer[i]; } + Serial.write(buffer[i]); + } + return true; +} + +bool SonoffD1ModuleSelected(void) +{ + SetSerial(9600, TS_SERIAL_8N1); + + devices_present++; + light_type = LT_SERIAL1; + + return true; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv37(uint8_t function) +{ + bool result = false; + + if (SONOFF_D1 == my_module_type) { + switch (function) { + case FUNC_SERIAL: + result = SonoffD1SerialInput(); + break; + case FUNC_SET_DEVICE_POWER: + result = SonoffD1SendPower(); + break; + case FUNC_SET_CHANNELS: + result = SonoffD1SendDimmer(); + break; + case FUNC_MODULE_INIT: + result = SonoffD1ModuleSelected(); + break; + } + } + return result; +} + +#endif // USE_SONOFF_D1 diff --git a/tools/decode-status.py b/tools/decode-status.py index 756f27dff..6c5dd6a5b 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -198,7 +198,7 @@ a_features = [[ "USE_NRF24","USE_MIBLE","USE_HM10","USE_LE01MR", "USE_AHT1x","USE_WEMOS_MOTOR_V1","USE_DEVICE_GROUPS","USE_PWM_DIMMER" ],[ - "USE_KEELOQ","USE_HRXL","","", + "USE_KEELOQ","USE_HRXL","USE_SONOFF_D1","", "","","","", "","","","", "","","","", From 2b438328ddaff4ef832b5aa741a9d8a7f3f667fc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Mar 2020 16:13:59 +0100 Subject: [PATCH 535/559] Add DimmerRange support to Sonoff D1 Add DimmerRange support to Sonoff D1 (#7598) --- tasmota/xdrv_37_sonoff_d1.ino | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tasmota/xdrv_37_sonoff_d1.ino b/tasmota/xdrv_37_sonoff_d1.ino index b7f98c352..d00d58162 100644 --- a/tasmota/xdrv_37_sonoff_d1.ino +++ b/tasmota/xdrv_37_sonoff_d1.ino @@ -159,29 +159,33 @@ bool SonoffD1SerialInput(void) /********************************************************************************************/ -bool SonoffD1SendPower(void) +void SonoffD1Send(uint8_t lpower, uint8_t dimmer) { - uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; - buffer[6] = XdrvMailbox.index; + buffer[6] = lpower; + buffer[7] = dimmer; for (uint32_t i = 0; i < sizeof(buffer); i++) { if ((i > 1) && (i < sizeof(buffer) -1)) { buffer[16] += buffer[i]; } Serial.write(buffer[i]); } +} + +bool SonoffD1SendPower(void) +{ + SonoffD1Send(XdrvMailbox.index &1, 0xFF); return true; } bool SonoffD1SendDimmer(void) { - uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; + uint8_t dimmer = changeUIntScale(((uint16_t *)XdrvMailbox.data)[0], 0, 255, 0, 100); + dimmer = (dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : dimmer; + dimmer = (dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : dimmer; - buffer[7] = changeUIntScale(((uint16_t *)XdrvMailbox.data)[0], 0, 255, 0, 100); - - for (uint32_t i = 0; i < sizeof(buffer); i++) { - if ((i > 1) && (i < sizeof(buffer) -1)) { buffer[16] += buffer[i]; } - Serial.write(buffer[i]); - } + SonoffD1Send(0xFF, dimmer); return true; } From a837a8ac7ce4d65b3d590a7a258e030448d7cec0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 1 Mar 2020 22:13:02 +0100 Subject: [PATCH 536/559] Fix compile error --- tasmota/xdrv_39_sonoff_d1.ino | 215 ---------------------------------- 1 file changed, 215 deletions(-) delete mode 100644 tasmota/xdrv_39_sonoff_d1.ino diff --git a/tasmota/xdrv_39_sonoff_d1.ino b/tasmota/xdrv_39_sonoff_d1.ino deleted file mode 100644 index 9d58f3782..000000000 --- a/tasmota/xdrv_39_sonoff_d1.ino +++ /dev/null @@ -1,215 +0,0 @@ -/* - xdrv_39_sonoff_d1.ino - sonoff D1 dimmer support for Tasmota - - Copyright (C) 2020 Theo Arends and robbz23 (protocol analysis) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_SONOFF_D1 -/*********************************************************************************************\ - * Sonoff D1 dimmer 433 - * - * 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 - * AA 55 - Header - * 01 04 - Version? - * 00 0A - Following data length (10 bytes) - * 01 - Power state (00 = off, 01 = on, FF = ignore) - * 64 - Dimmer percentage (01 to 64 = 1 to 100%) - * FF FF FF FF FF FF FF FF - Not used - * 6C - CRC over bytes 2 to F (Addition) - * - * Based on Gravitate1: - * When I switch the light ON via the app, I get: - * AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C - * - * When I switch it OFF, I get: - * AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B - * - * When I set it to 1%, I get: - * AA 55 01 04 00 0A FF 01 FF FF FF FF FF FF FF FF 07 - * AB 55 FD F7 FF FF F5 01 FF FF FF FF FF FF FF FF 09 - * - * When I set it to 6%, I get: - * AA 55 01 04 00 0A FF 06 FF FF FF FF FF FF FF FF 0C - * AB 55 FD F7 FF FF F5 06 FF FF FF FF FF FF FF FF 0E - * - * When I set it to 100%, I get: - * AA 55 01 04 00 0A FF 64 FF FF FF FF FF FF FF FF 6A - * AB 55 FD F7 FF FF F5 64 FF FF FF FF FF FF FF FF 6C - * - * Based on robbz23: - * 00:17:59 CMD: Baudrate 9600 - * 00:17:59 SER: Set to 8N1 9600 bit/s - * 00:17:59 RSL: stat/tasmota_D9E56D/RESULT = {"Baudrate":9600} - * - * 00:25:32 CMD: SerialSend5 aa 55 01 04 00 0a 01 22 ffffffffffffffff 29 - * 00:25:32 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} - * - * 00:26:35 CMD: SerialSend5 aa 55 01 04 00 0a 01 22 ffffffffffffffff 2a - * 00:26:35 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} - * 00:26:35 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 00 05} - * - * 00:28:58 CMD: SerialSend5 aa 55 01 04 00 0a 01 01 ffffffffffffffff 09 - * 00:28:58 RSL: stat/tasmota_D9E56D/RESULT = {"SerialSend":"Done"} - * 00:28:58 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 00 05} - * - * 00:29:12 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 3C FF FF FF FF FF FF FF FF 44} - * 00:29:43 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 01 FF FF FF FF FF FF FF FF 09} - * 00:29:53 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C} - * - * 00:30:02 RSL: tele/tasmota_D9E56D/RESULT = {"SerialReceived":AA 55 01 04 00 0A FF 1E FF FF FF FF FF FF FF FF 24} -\*********************************************************************************************/ - -#define XDRV_39 39 - -struct SONOFFD1 { - uint8_t receive_flag = 0; - uint8_t dimmer; -} SnfD1; - -/********************************************************************************************/ - -void SonoffD1Received(void) -{ - char svalue[32]; - - uint8_t action = serial_in_buffer[6]; - uint8_t dimmer = serial_in_buffer[7]; - - if (action < 2) { - // AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C - Power On, Dimmer 100% - // AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B - Power Off, Dimmer 100% - bool is_switch_change = (action != power); - if (is_switch_change) { - ExecuteCommandPower(1, action, SRC_SWITCH); - } - } - else if (0xFF == action) { - SnfD1.dimmer = dimmer; - bool is_brightness_change = SnfD1.dimmer != Settings.light_dimmer; - if (power && (SnfD1.dimmer > 0) && is_brightness_change) { - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), SnfD1.dimmer); - ExecuteCommand(scmnd, SRC_SWITCH); - } - } - - // Send Acknowledge - Copy first 5 bytes, reset byte 6 and store crc in byte 7 - // AA 55 01 04 00 00 05 - serial_in_buffer[5] = 0; // Ack - serial_in_buffer[6] = 0; // Crc - for (uint32_t i = 0; i < 7; i++) { - if ((i > 1) && (i < 6)) { serial_in_buffer[6] += serial_in_buffer[i]; } - Serial.write(serial_in_buffer[i]); - } -} - -bool SonoffD1SerialInput(void) -{ - uint8_t packet_length = 0; - - if (0xAA == serial_in_byte) { // 0xAA - Start of text - serial_in_byte_counter = 0; - SnfD1.receive_flag = true; - } - if (SnfD1.receive_flag) { - serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter == 5) { - packet_length = 7 + serial_in_byte; // 8 or 17 - } - if (serial_in_byte_counter == packet_length) { - - // Sonoff D1 codes - // AA 55 01 04 00 0A 01 64 FF FF FF FF FF FF FF FF 6C - Power On, Dimmer 100% - // AA 55 01 04 00 0A 00 64 FF FF FF FF FF FF FF FF 6B - Power Off, Dimmer 100% - // AA 55 01 04 00 0A FF 01 FF FF FF FF FF FF FF FF 07 - Power ignore, Dimmer 1% - // AB 55 FD F7 FF FF F5 01 FF FF FF FF FF FF FF FF 09 - Response 2 - // AA 55 01 04 00 0A FF 06 FF FF FF FF FF FF FF FF 0C - Power ignore, Dimmer 6% - // AB 55 FD F7 FF FF F5 06 FF FF FF FF FF FF FF FF 0E - Response 2 - // AA 55 01 04 00 0A FF 64 FF FF FF FF FF FF FF FF 6A - Power ignore, Dimmer 100% - // AB 55 FD F7 FF FF F5 64 FF FF FF FF FF FF FF FF 6C - Response 2 - - AddLogSerial(LOG_LEVEL_DEBUG); - uint8_t crc = 0; - for (uint32_t i = 2; i < packet_length -1; i++) { - crc += serial_in_buffer[i]; - } - if (crc == serial_in_buffer[packet_length -1]) { - SonoffD1Received(); - SnfD1.receive_flag = false; - return true; - } - } - serial_in_byte = 0; - } - return false; -} - -/********************************************************************************************/ - -bool SonoffD1SendPower(void) -{ - uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; - - buffer[6] = XdrvMailbox.payload; - - for (uint32_t i = 0; i < sizeof(buffer); i++) { - if ((i > 1) && (i < sizeof(buffer) -1)) { serial_in_buffer[16] += serial_in_buffer[i]; } - Serial.write(serial_in_buffer[i]); - } - return true; -} - -bool SonoffD1SendDimmer(void) -{ - uint8_t buffer[17] = { 0xAA,0x55,0x01,0x04,0x00,0x0A,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 }; - - buffer[7] = light_state.getDimmer(); - - for (uint32_t i = 0; i < sizeof(buffer); i++) { - if ((i > 1) && (i < sizeof(buffer) -1)) { serial_in_buffer[16] += serial_in_buffer[i]; } - Serial.write(serial_in_buffer[i]); - } - return true; -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xdrv39(uint8_t function) -{ - bool result = false; - - if (SONOFF_D1 == my_module_type) { - switch (function) { - case FUNC_SERIAL: - result = SonoffD1SerialInput(); - break; - case FUNC_SET_DEVICE_POWER: - result = SonoffD1SendPower(); - break; - case FUNC_SET_CHANNELS: - result = SonoffD1SendDimmer(); - break; - case FUNC_MODULE_INIT: - SetSerial(9600, TS_SERIAL_8N1); - break; - } - } - return result; -} - -#endif // USE_SONOFF_D1 From 669f88a5aab6b99e534bced6bbe80ec23d82a3bb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Mar 2020 14:00:57 +0100 Subject: [PATCH 537/559] Add Settings.flag2.speed_conversion --- tasmota/settings.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tasmota/settings.h b/tasmota/settings.h index be108ac33..37734b32a 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -140,10 +140,8 @@ typedef union { uint32_t data; // Allow bit manipulation struct { uint32_t spare00 : 1; - uint32_t spare01 : 1; - uint32_t spare02 : 1; - uint32_t spare03 : 1; - uint32_t time_format : 2; // (v6.6.0.9) - CMND_TIME + uint32_t speed_conversion : 3; // (v8.1.0.10) - Tx2x sensor + uint32_t time_format : 2; // (v6.6.0.9) - CMND_TIME uint32_t calc_resolution : 3; uint32_t weight_resolution : 2; uint32_t frequency_resolution : 2; From 71d810aac451f6f88591dbc69b51f081efcc5181 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Mar 2020 15:51:33 +0100 Subject: [PATCH 538/559] Update Tx2x Sensor Update Tx2x Sensor with command SpeedUnit (#7843) --- tasmota/i18n.h | 13 ++++ tasmota/support.ino | 12 ++++ tasmota/support_command.ino | 10 +++ tasmota/support_tasmota.ino | 3 + tasmota/xdrv_10_rules.ino | 9 ++- tasmota/xsns_35_tx20.ino | 132 +++++++++++++++++++----------------- 6 files changed, 115 insertions(+), 64 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 0f1988944..f36f37977 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -139,6 +139,8 @@ #define D_JSON_SERIALRECEIVED "SerialReceived" #define D_JSON_SET "Set" #define D_JSON_SIGNAL "Signal" +#define D_JSON_SPEED "Speed" +#define D_JSON_SPEED_UNIT "SpeedUnit" #define D_JSON_SSID "SSId" #define D_JSON_STARTDST "StartDST" // Start Daylight Savings Time #define D_JSON_STARTED "Started" @@ -287,6 +289,7 @@ #define D_CMND_LEDSTATE "LedState" #define D_CMND_LEDMASK "LedMask" #define D_CMND_WIFIPOWER "WifiPower" +#define D_CMND_SPEEDUNIT "SpeedUnit" #define D_CMND_I2CSCAN "I2CScan" #define D_CMND_I2CDRIVER "I2CDriver" #define D_CMND_DEVGROUP_SHARE "DevGroupShare" @@ -647,6 +650,16 @@ const char S_OFFLINE[] PROGMEM = D_OFFLINE; // support.ino static const char kMonthNames[] = D_MONTH3LIST; +const char kSpeedUnit[] PROGMEM = "|m/s|km/h|kn|mph|ft/s|yd/s"; +const float kSpeedConversionFactor[] = {1, // none + 1, // m/s + 3.6, // km/h + 1.943844492, // kn + 2.236936292, // mph + 3.280839895, // ft/s + 1.093613298 // yd/s + }; + // xdrv_02_webserver.ino #ifdef USE_WEBSERVER // {s} =
diff --git a/tasmota/support.ino b/tasmota/support.ino index ed2cea4c1..8587c034b 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -641,6 +641,18 @@ String PressureUnit(void) return (Settings.flag.pressure_conversion) ? String(D_UNIT_MILLIMETER_MERCURY) : String(D_UNIT_PRESSURE); } +float ConvertSpeed(float s) +{ + // Entry in m/s + return s * kSpeedConversionFactor[Settings.flag2.speed_conversion]; +} + +String SpeedUnit(void) +{ + char speed[8]; + return String(GetTextIndexed(speed, sizeof(speed), Settings.flag2.speed_conversion, kSpeedUnit)); +} + void ResetGlobalValues(void) { if ((uptime - global_update) > GLOBAL_VALUES_VALID) { // Reset after 5 minutes diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index ac44b9850..43db86430 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -27,6 +27,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" + D_CMND_SPEEDUNIT "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif @@ -45,6 +46,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, + &CmndSpeedUnit, #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif @@ -877,6 +879,14 @@ void CmndWeightResolution(void) ResponseCmndNumber(Settings.flag2.weight_resolution); } +void CmndSpeedUnit(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) { + Settings.flag2.speed_conversion = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings.flag2.speed_conversion); +} + void CmndModule(void) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAXMODULE)) { diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index d7396267b..43e73321d 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -696,6 +696,9 @@ bool MqttShowSensor(void) if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); } + if ((strstr_P(mqtt_data, PSTR(D_JSON_SPEED)) != nullptr) && Settings.flag2.speed_conversion) { + ResponseAppend_P(PSTR(",\"" D_JSON_SPEED_UNIT "\":\"%s\""), SpeedUnit().c_str()); + } ResponseJsonEnd(); if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 27c7787e0..2509d6f6f 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -289,8 +289,8 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) str_value = (*obj)[rule_name]; // "CURRENT" } -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), -// rule_task.c_str(), rule_name.c_str(), rule_svalue, Rules.trigger_count[rule_set], bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"), +// rule_task.c_str(), rule_name.c_str(), rule_svalue, Rules.trigger_count[rule_set], bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none"); Rules.event_value = str_value; // Prepare %value% @@ -330,6 +330,9 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } } else match = true; +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Match 1 %d"), match); + + if (bitRead(Settings.rule_once, rule_set)) { if (match) { // Only allow match state changes if (!bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set])) { @@ -342,6 +345,8 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule) } } +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Match 2 %d"), match); + return match; } diff --git a/tasmota/xsns_35_tx20.ino b/tasmota/xsns_35_tx20.ino index 69844fda4..c9c1fcee7 100644 --- a/tasmota/xsns_35_tx20.ino +++ b/tasmota/xsns_35_tx20.ino @@ -56,7 +56,6 @@ #endif // USE_TX20_WIND_SENSOR && USE_TX23_WIND_SENSOR // #define USE_TX2X_WIND_SENSOR_NOSTATISTICS // suppress statistics (speed/dir avg/min/max/range) - #define TX2X_BIT_TIME 1220 // microseconds #define TX2X_WEIGHT_AVG_SAMPLE 150 // seconds #define TX2X_TIMEOUT 10 // seconds @@ -79,26 +78,28 @@ extern "C" { #ifdef USE_WEBSERVER #define D_TX20_WIND_AVG "∅" #define D_TX20_WIND_ANGLE "∠" +#define D_TX20_WIND_DEGREE "°" const char HTTP_SNS_TX2X[] PROGMEM = - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED "{m}%s %s{e}" #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED " " D_TX20_WIND_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED " " D_TX20_WIND_AVG "{m}%s %s{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MIN "{m}%s %s{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_SPEED_MAX "{m}%s %s{e}" #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s %s°{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION "{m}%s %s" D_TX20_WIND_DEGREE "{e}" #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_AVG "{m}%s %s°{e}" - "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_ANGLE "{m}%s° (%s°,%s°)"; + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_AVG "{m}%s %s" D_TX20_WIND_DEGREE "{e}" + "{s}" D_TX2x_NAME " " D_TX20_WIND_DIRECTION " " D_TX20_WIND_ANGLE "{m}%s" D_TX20_WIND_DEGREE " (%s,%s)" D_TX20_WIND_DEGREE; #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS ; #endif // USE_WEBSERVER // float saves 48 byte -float const ff_pi = 3.1415926535897932384626433; // Pi -float const ff_halfpi = ff_pi / 2.0; -float const ff_pi180 = ff_pi / 180.0; +float const tx2x_f_pi = 3.1415926535897932384626433; // Pi +float const tx2x_f_halfpi = tx2x_f_pi / 2.0; +float const tx2x_f_pi180 = tx2x_f_pi / 180.0; +#define TX2X_DIRECTIONS_MAXSIZE 3 const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" D_TX20_NORTH D_TX20_EAST "|" @@ -116,12 +117,12 @@ const char kTx2xDirections[] PROGMEM = D_TX20_NORTH "|" D_TX20_NORTH D_TX20_WEST "|" D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; -float tx2x_wind_speed_kmh = 0; +int32_t tx2x_wind_speed = 0; int32_t tx2x_wind_direction = 0; #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS -float tx2x_wind_speed_min = 200.0; -float tx2x_wind_speed_max = 0; +int32_t tx2x_wind_speed_min = 0xfff; +int32_t tx2x_wind_speed_max = 0; float tx2x_wind_speed_avg = 0; float tx2x_wind_direction_avg_x = 0; float tx2x_wind_direction_avg_y = 0; @@ -131,7 +132,7 @@ int32_t tx2x_wind_direction_max = 0; uint32_t tx2x_count = 0; uint32_t tx2x_avg_samples; -uint32_t last_uptime = 0; +uint32_t tx2x_last_uptime = 0; bool tx2x_valuesread = false; #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS @@ -143,7 +144,7 @@ uint32_t tx2x_sd = 0; uint32_t tx2x_se = 0; uint32_t tx2x_sf = 0; #endif // DEBUG_TASMOTA_SENSOR -uint32_t last_available = 0; +uint32_t tx2x_last_available = 0; #ifdef USE_TX23_WIND_SENSOR uint32_t tx23_stage = 0; @@ -237,9 +238,9 @@ void TX2xStartRead(void) // check checksum, start frame,non-inverted==inverted values and max. speed ; if ((chk == tx2x_sd) && (0x1b==tx2x_sa) && (tx2x_sb==tx2x_se) && (tx2x_sc==tx2x_sf) && (tx2x_sc < 511)) { - last_available = uptime; + tx2x_last_available = uptime; // Wind speed spec: 0 to 180 km/h (0 to 50 m/s) - tx2x_wind_speed_kmh = float(tx2x_sc) * 0.36; + tx2x_wind_speed = tx2x_sc; tx2x_wind_direction = tx2x_sb; #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS if (!tx2x_valuesread) { @@ -263,7 +264,7 @@ void TX2xStartRead(void) bool Tx2xAvailable(void) { - return ((uptime - last_available) < TX2X_TIMEOUT); + return ((uptime - tx2x_last_available) < TX2X_TIMEOUT); } #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS @@ -273,13 +274,13 @@ float atan2f(float a, float b) if (b > 0) { atan2val = atanf(a/b); } else if ((b < 0) && (a >= 0)) { - atan2val = atanf(a/b) + ff_pi; + atan2val = atanf(a/b) + tx2x_f_pi; } else if ((b < 0) && (a < 0)) { - atan2val = atanf(a/b) - ff_pi; + atan2val = atanf(a/b) - tx2x_f_pi; } else if ((b == 0) && (a > 0)) { - atan2val = ff_halfpi; + atan2val = tx2x_f_halfpi; } else if ((b == 0) && (a < 0)) { - atan2val = 0 - (ff_halfpi); + atan2val = 0 - (tx2x_f_halfpi); } else if ((b == 0) && (a == 0)) { atan2val = 1000; //represents undefined } @@ -297,7 +298,7 @@ void Tx2xCheckSampleCount(void) tx2x_avg_samples = TX2X_WEIGHT_AVG_SAMPLE; } if (tx2x_prev_avg_samples != tx2x_avg_samples) { - tx2x_wind_speed_avg = tx2x_wind_speed_kmh; + tx2x_wind_speed_avg = tx2x_wind_speed; tx2x_count = 0; } } @@ -305,14 +306,14 @@ void Tx2xCheckSampleCount(void) void Tx2xResetStat(void) { DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": reset statistics")); - last_uptime = uptime; + tx2x_last_uptime = uptime; Tx2xResetStatData(); } void Tx2xResetStatData(void) { - tx2x_wind_speed_min = tx2x_wind_speed_kmh; - tx2x_wind_speed_max = tx2x_wind_speed_kmh; + tx2x_wind_speed_min = tx2x_wind_speed; + tx2x_wind_speed_max = tx2x_wind_speed; tx2x_wind_direction_min = tx2x_wind_direction; tx2x_wind_direction_max = tx2x_wind_direction; @@ -347,11 +348,11 @@ void Tx2xRead(void) DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": sa=0x%02lx sb=%ld (0x%02lx), sc=%ld (0x%03lx), sd=0x%02lx, se=%ld, sf=%ld"), tx2x_sa,tx2x_sb,tx2x_sb,tx2x_sc,tx2x_sc,tx2x_sd,tx2x_se,tx2x_sf); #endif // DEBUG_TASMOTA_SENSOR #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - if (tx2x_wind_speed_kmh < tx2x_wind_speed_min) { - tx2x_wind_speed_min = tx2x_wind_speed_kmh; + if (tx2x_wind_speed < tx2x_wind_speed_min) { + tx2x_wind_speed_min = tx2x_wind_speed; } - if (tx2x_wind_speed_kmh > tx2x_wind_speed_max) { - tx2x_wind_speed_max = tx2x_wind_speed_kmh; + if (tx2x_wind_speed > tx2x_wind_speed_max) { + tx2x_wind_speed_max = tx2x_wind_speed; } // exponentially weighted average is not quite as smooth as the arithmetic average @@ -361,13 +362,13 @@ void Tx2xRead(void) tx2x_count++; } tx2x_wind_speed_avg -= tx2x_wind_speed_avg / tx2x_count; - tx2x_wind_speed_avg += tx2x_wind_speed_kmh / tx2x_count; + tx2x_wind_speed_avg += float(tx2x_wind_speed) / tx2x_count; tx2x_wind_direction_avg_x -= tx2x_wind_direction_avg_x / tx2x_count; - tx2x_wind_direction_avg_x += cosf((tx2x_wind_direction*22.5) * ff_pi180) / tx2x_count; + tx2x_wind_direction_avg_x += cosf((tx2x_wind_direction*22.5) * tx2x_f_pi180) / tx2x_count; tx2x_wind_direction_avg_y -= tx2x_wind_direction_avg_y / tx2x_count; - tx2x_wind_direction_avg_y += sinf((tx2x_wind_direction*22.5) * ff_pi180) / tx2x_count; - tx2x_wind_direction_avg = atan2f(tx2x_wind_direction_avg_y, tx2x_wind_direction_avg_x) * 180.0f / ff_pi; + tx2x_wind_direction_avg_y += sinf((tx2x_wind_direction*22.5) * tx2x_f_pi180) / tx2x_count; + tx2x_wind_direction_avg = atan2f(tx2x_wind_direction_avg_y, tx2x_wind_direction_avg_x) * 180.0f / tx2x_f_pi; if (tx2x_wind_direction_avg<0.0) { tx2x_wind_direction_avg += 360.0; } @@ -411,14 +412,14 @@ void Tx2xRead(void) } #ifdef DEBUG_TASMOTA_SENSOR - char diravg[33]; + char diravg[FLOATSZ]; dtostrfd(tx2x_wind_direction_avg, 1, diravg); - char cosx[33]; + char cosx[FLOATSZ]; dtostrfd(tx2x_wind_direction_avg_x, 1, cosx); - char siny[33]; + char siny[FLOATSZ]; dtostrfd(tx2x_wind_direction_avg_y, 1, siny); DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": dir stat - counter=%ld, actint=%ld, avgint=%ld, avg=%s (cosx=%s, siny=%s), min %d, max %d"), - (uptime-last_uptime), + (uptime-tx2x_last_uptime), tx2x_wind_direction, tx2x_wind_direction_avg_int, diravg, @@ -431,7 +432,7 @@ void Tx2xRead(void) #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS } else { DEBUG_SENSOR_LOG(PSTR(D_TX2x_NAME ": not available")); - tx2x_wind_speed_kmh = 0; + tx2x_wind_speed = 0; tx2x_wind_direction = 0; #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS tx2x_wind_speed_avg = 0; @@ -442,7 +443,7 @@ void Tx2xRead(void) #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS Tx2xCheckSampleCount(); - if (0==Settings.tele_period && (uptime-last_uptime)>=tx2x_avg_samples) { + if (0==Settings.tele_period && (uptime-tx2x_last_uptime)>=tx2x_avg_samples) { Tx2xResetStat(); } #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS @@ -450,6 +451,9 @@ void Tx2xRead(void) void Tx2xInit(void) { + if (!Settings.flag2.speed_conversion) { + Settings.flag2.speed_conversion = 2; // 0 = none, 1 = m/s, 2 = km/h, 3 = kn, 4 = mph, 5 = ft/s, 6 = yd/s + } #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS tx2x_valuesread = false; Tx2xResetStat(); @@ -478,35 +482,37 @@ int32_t Tx2xNormalize(int32_t value) void Tx2xShow(bool json) { - char wind_speed_string[17]; - dtostrfd(tx2x_wind_speed_kmh, 1, wind_speed_string); - char wind_direction_string[17]; + if (!Tx2xAvailable()) { return; } + + char wind_speed_string[FLOATSZ]; + dtostrfd(ConvertSpeed(tx2x_wind_speed)/10, 1, wind_speed_string); + char wind_direction_string[FLOATSZ]; dtostrfd(tx2x_wind_direction*22.5, 1, wind_direction_string); - char wind_direction_cardinal_string[4]; + char wind_direction_cardinal_string[TX2X_DIRECTIONS_MAXSIZE+1]; GetTextIndexed(wind_direction_cardinal_string, sizeof(wind_direction_cardinal_string), tx2x_wind_direction, kTx2xDirections); #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS - char wind_speed_min_string[17]; - dtostrfd(tx2x_wind_speed_min, 1, wind_speed_min_string); - char wind_speed_max_string[17]; - dtostrfd(tx2x_wind_speed_max, 1, wind_speed_max_string); - char wind_speed_avg_string[17]; - dtostrfd(tx2x_wind_speed_avg, 1, wind_speed_avg_string); - char wind_direction_avg_string[17]; + char wind_speed_min_string[FLOATSZ]; + dtostrfd(ConvertSpeed(tx2x_wind_speed_min)/10, 1, wind_speed_min_string); + char wind_speed_max_string[FLOATSZ]; + dtostrfd(ConvertSpeed(tx2x_wind_speed_max)/10, 1, wind_speed_max_string); + char wind_speed_avg_string[FLOATSZ]; + dtostrfd(ConvertSpeed(tx2x_wind_speed_avg)/10, 1, wind_speed_avg_string); + char wind_direction_avg_string[FLOATSZ]; dtostrfd(tx2x_wind_direction_avg, 1, wind_direction_avg_string); char wind_direction_avg_cardinal_string[4]; GetTextIndexed(wind_direction_avg_cardinal_string, sizeof(wind_direction_avg_cardinal_string), int((tx2x_wind_direction_avg/22.5f)+0.5f) % 16, kTx2xDirections); - char wind_direction_range_string[17]; + char wind_direction_range_string[FLOATSZ]; dtostrfd(Tx2xNormalize(tx2x_wind_direction_max-tx2x_wind_direction_min)*22.5, 1, wind_direction_range_string); - char wind_direction_min_string[17]; + char wind_direction_min_string[FLOATSZ]; dtostrfd(Tx2xNormalize(tx2x_wind_direction_min)*22.5, 1, wind_direction_min_string); - char wind_direction_max_string[17]; + char wind_direction_max_string[FLOATSZ]; dtostrfd(Tx2xNormalize(tx2x_wind_direction_max)*22.5, 1, wind_direction_max_string); #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS if (json) { #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS #ifdef USE_TX2x_LEGACY_JSON - ResponseAppend_P(Tx2xAvailable()?PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"):PSTR(""), + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), wind_speed_string, wind_speed_avg_string, wind_speed_max_string, @@ -514,7 +520,7 @@ void Tx2xShow(bool json) wind_direction_string ); #else // USE_TX2x_LEGACY_JSON - ResponseAppend_P(Tx2xAvailable()?PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s,\"Avg\":%s,\"AvgCard\":\"%s\",\"Min\":%s,\"Max\":%s,\"Range\":%s}}"):PSTR(""), + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s,\"Avg\":%s,\"Min\":%s,\"Max\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s,\"Avg\":%s,\"AvgCard\":\"%s\",\"Min\":%s,\"Max\":%s,\"Range\":%s}}"), wind_speed_string, wind_speed_avg_string, wind_speed_min_string, @@ -530,23 +536,25 @@ void Tx2xShow(bool json) #endif // USE_TX2x_LEGACY_JSON #else // USE_TX2X_WIND_SENSOR_NOSTATISTICS #ifdef USE_TX2x_LEGACY_JSON - ResponseAppend_P(Tx2xAvailable()?PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":%s,\"Direction\":\"%s\",\"Degree\":%s}"):PSTR(""), + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":%s,\"Direction\":\"%s\",\"Degree\":%s}"), wind_speed_string, wind_direction_cardinal_string, wind_direction_string); #else // USE_TX2x_LEGACY_JSON - ResponseAppend_P(Tx2xAvailable()?PSTR(",\"" D_TX2x_NAME "\":{\"Speed\":{\"Act\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s}}"):PSTR(""), + ResponseAppend_P(PSTR(",\"" D_TX2x_NAME "\":{\"" D_JSON_SPEED "\":{\"Act\":%s},\"Dir\":{\"Card\":\"%s\",\"Deg\":%s}}"), wind_speed_string, wind_direction_cardinal_string, wind_direction_string); #endif // USE_TX2x_LEGACY_JSON #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS - #ifdef USE_WEBSERVER } else { - WSContentSend_PD( - Tx2xAvailable()?HTTP_SNS_TX2X:PSTR(""), + WSContentSend_PD(HTTP_SNS_TX2X, wind_speed_string, + SpeedUnit().c_str(), #ifndef USE_TX2X_WIND_SENSOR_NOSTATISTICS wind_speed_avg_string, + SpeedUnit().c_str(), wind_speed_min_string, + SpeedUnit().c_str(), wind_speed_max_string, + SpeedUnit().c_str(), #endif // USE_TX2X_WIND_SENSOR_NOSTATISTICS wind_direction_cardinal_string, wind_direction_string From 0ce89e53e3ffa25988f36ac1bd0d32e295d2586c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 2 Mar 2020 17:48:19 +0100 Subject: [PATCH 539/559] Fix Arduino IDE compile error --- arduino/version 2.6.3/boards.txt | 7124 ++++++++++++++++++++++++++++ arduino/version 2.6.3/platform.txt | 171 + tasmota/tasmota.ino | 9 +- tasmota/xdrv_01_webserver.ino | 2 + 4 files changed, 7304 insertions(+), 2 deletions(-) create mode 100644 arduino/version 2.6.3/boards.txt create mode 100644 arduino/version 2.6.3/platform.txt diff --git a/arduino/version 2.6.3/boards.txt b/arduino/version 2.6.3/boards.txt new file mode 100644 index 000000000..3fbb48f33 --- /dev/null +++ b/arduino/version 2.6.3/boards.txt @@ -0,0 +1,7124 @@ +# +# Do not create pull-requests for this file only, CI will not accept them. +# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. +# All modified files after running with option "--allgen" must be included in the pull-request. +# + +menu.BoardModel=Model +menu.ESPModule=Module + +menu.UploadTool=Upload Using + +menu.led=Builtin Led +menu.baud=Upload Speed +menu.xtal=CPU Frequency +menu.CrystalFreq=Crystal Frequency +menu.eesz=Flash Size +menu.FlashMode=Flash Mode +menu.FlashFreq=Flash Frequency +menu.ResetMethod=Reset Method +menu.dbg=Debug port +menu.lvl=Debug Level +menu.ip=lwIP Variant +menu.vt=VTables +menu.exception=Exceptions +menu.wipe=Erase Flash +menu.sdk=Espressif FW +menu.ssl=SSL Support + +############################################################## +generic.name=Generic ESP8266 Module +generic.build.board=ESP8266_GENERIC +generic.upload.tool=esptool +generic.upload.maximum_data_size=81920 +generic.upload.wait_for_upload_port=true +generic.upload.erase_cmd= +generic.serial.disableDTR=true +generic.serial.disableRTS=true +generic.build.mcu=esp8266 +generic.build.core=esp8266 +generic.build.variant=generic +generic.build.spiffs_pagesize=256 +generic.build.debug_port= +generic.build.debug_level= + +generic.menu.UploadTool.esptool=Serial +generic.menu.UploadTool.esptool.upload.tool=esptool +generic.menu.UploadTool.esptool.upload.verbose=-vv +generic.menu.UploadTool.espupload=OTA_upload +generic.menu.UploadTool.espupload.upload.tool=espupload + +generic.menu.xtal.80=80 MHz +generic.menu.xtal.80.build.f_cpu=80000000L +generic.menu.xtal.160=160 MHz +generic.menu.xtal.160.build.f_cpu=160000000L +generic.menu.vt.flash=Flash +generic.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +generic.menu.vt.heap=Heap +generic.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +generic.menu.vt.iram=IRAM +generic.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +generic.menu.exception.legacy=Legacy (new can return nullptr) +generic.menu.exception.legacy.build.exception_flags=-fno-exceptions +generic.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +generic.menu.exception.disabled=Disabled (new can abort) +generic.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +generic.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +generic.menu.exception.enabled=Enabled +generic.menu.exception.enabled.build.exception_flags=-fexceptions +generic.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +generic.menu.ssl.all=All SSL ciphers (most compatible) +generic.menu.ssl.all.build.sslflags= +generic.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +generic.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +generic.menu.ResetMethod.nodemcu=dtr (aka nodemcu) +generic.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset +generic.menu.ResetMethod.ck=no dtr (aka ck) +generic.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset +generic.menu.ResetMethod.nodtr_nosync=no dtr, no_sync +generic.menu.ResetMethod.nodtr_nosync.upload.resetmethod=--before no_reset_no_sync --after soft_reset +generic.menu.CrystalFreq.26=26 MHz +generic.menu.CrystalFreq.40=40 MHz +generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +generic.menu.FlashFreq.40=40MHz +generic.menu.FlashFreq.40.build.flash_freq=40 +generic.menu.FlashFreq.80=80MHz +generic.menu.FlashFreq.80.build.flash_freq=80 +generic.menu.FlashFreq.20=20MHz +generic.menu.FlashFreq.20.build.flash_freq=20 +generic.menu.FlashFreq.26=26MHz +generic.menu.FlashFreq.26.build.flash_freq=26 +generic.menu.FlashMode.dout=DOUT (compatible) +generic.menu.FlashMode.dout.build.flash_mode=dout +generic.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT +generic.menu.FlashMode.dio=DIO +generic.menu.FlashMode.dio.build.flash_mode=dio +generic.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO +generic.menu.FlashMode.qout=QOUT +generic.menu.FlashMode.qout.build.flash_mode=qout +generic.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT +generic.menu.FlashMode.qio=QIO (fast) +generic.menu.FlashMode.qio.build.flash_mode=qio +generic.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO +generic.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +generic.menu.eesz.1M64.build.flash_size=1M +generic.menu.eesz.1M64.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +generic.menu.eesz.1M64.build.spiffs_pagesize=256 +generic.menu.eesz.1M64.upload.maximum_size=958448 +generic.menu.eesz.1M64.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M64.build.spiffs_start=0xEB000 +generic.menu.eesz.1M64.build.spiffs_end=0xFB000 +generic.menu.eesz.1M64.build.spiffs_blocksize=4096 +generic.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +generic.menu.eesz.1M128.build.flash_size=1M +generic.menu.eesz.1M128.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +generic.menu.eesz.1M128.build.spiffs_pagesize=256 +generic.menu.eesz.1M128.upload.maximum_size=892912 +generic.menu.eesz.1M128.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M128.build.spiffs_start=0xDB000 +generic.menu.eesz.1M128.build.spiffs_end=0xFB000 +generic.menu.eesz.1M128.build.spiffs_blocksize=4096 +generic.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +generic.menu.eesz.1M144.build.flash_size=1M +generic.menu.eesz.1M144.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +generic.menu.eesz.1M144.build.spiffs_pagesize=256 +generic.menu.eesz.1M144.upload.maximum_size=876528 +generic.menu.eesz.1M144.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M144.build.spiffs_start=0xD7000 +generic.menu.eesz.1M144.build.spiffs_end=0xFB000 +generic.menu.eesz.1M144.build.spiffs_blocksize=4096 +generic.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +generic.menu.eesz.1M160.build.flash_size=1M +generic.menu.eesz.1M160.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +generic.menu.eesz.1M160.build.spiffs_pagesize=256 +generic.menu.eesz.1M160.upload.maximum_size=860144 +generic.menu.eesz.1M160.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M160.build.spiffs_start=0xD3000 +generic.menu.eesz.1M160.build.spiffs_end=0xFB000 +generic.menu.eesz.1M160.build.spiffs_blocksize=4096 +generic.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +generic.menu.eesz.1M192.build.flash_size=1M +generic.menu.eesz.1M192.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +generic.menu.eesz.1M192.build.spiffs_pagesize=256 +generic.menu.eesz.1M192.upload.maximum_size=827376 +generic.menu.eesz.1M192.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M192.build.spiffs_start=0xCB000 +generic.menu.eesz.1M192.build.spiffs_end=0xFB000 +generic.menu.eesz.1M192.build.spiffs_blocksize=4096 +generic.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +generic.menu.eesz.1M256.build.flash_size=1M +generic.menu.eesz.1M256.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +generic.menu.eesz.1M256.build.spiffs_pagesize=256 +generic.menu.eesz.1M256.upload.maximum_size=761840 +generic.menu.eesz.1M256.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M256.build.spiffs_start=0xBB000 +generic.menu.eesz.1M256.build.spiffs_end=0xFB000 +generic.menu.eesz.1M256.build.spiffs_blocksize=4096 +generic.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +generic.menu.eesz.1M512.build.flash_size=1M +generic.menu.eesz.1M512.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +generic.menu.eesz.1M512.build.spiffs_pagesize=256 +generic.menu.eesz.1M512.upload.maximum_size=499696 +generic.menu.eesz.1M512.build.rfcal_addr=0xFC000 +generic.menu.eesz.1M512.build.spiffs_start=0x7B000 +generic.menu.eesz.1M512.build.spiffs_end=0xFB000 +generic.menu.eesz.1M512.build.spiffs_blocksize=8192 +generic.menu.eesz.1M=1MB (FS:none OTA:~502KB) +generic.menu.eesz.1M.build.flash_size=1M +generic.menu.eesz.1M.build.flash_size_bytes=0x100000 +generic.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +generic.menu.eesz.1M.build.spiffs_pagesize=256 +generic.menu.eesz.1M.upload.maximum_size=1023984 +generic.menu.eesz.1M.build.rfcal_addr=0xFC000 +generic.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) +generic.menu.eesz.2M64.build.flash_size=2M +generic.menu.eesz.2M64.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld +generic.menu.eesz.2M64.build.spiffs_pagesize=256 +generic.menu.eesz.2M64.upload.maximum_size=1044464 +generic.menu.eesz.2M64.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M64.build.spiffs_start=0x1F0000 +generic.menu.eesz.2M64.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M64.build.spiffs_blocksize=4096 +generic.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) +generic.menu.eesz.2M128.build.flash_size=2M +generic.menu.eesz.2M128.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +generic.menu.eesz.2M128.build.spiffs_pagesize=256 +generic.menu.eesz.2M128.upload.maximum_size=1044464 +generic.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M128.build.spiffs_start=0x1E0000 +generic.menu.eesz.2M128.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M128.build.spiffs_blocksize=4096 +generic.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) +generic.menu.eesz.2M256.build.flash_size=2M +generic.menu.eesz.2M256.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +generic.menu.eesz.2M256.build.spiffs_pagesize=256 +generic.menu.eesz.2M256.upload.maximum_size=1044464 +generic.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M256.build.spiffs_start=0x1C0000 +generic.menu.eesz.2M256.build.spiffs_end=0x1FB000 +generic.menu.eesz.2M256.build.spiffs_blocksize=4096 +generic.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) +generic.menu.eesz.2M512.build.flash_size=2M +generic.menu.eesz.2M512.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +generic.menu.eesz.2M512.build.spiffs_pagesize=256 +generic.menu.eesz.2M512.upload.maximum_size=1044464 +generic.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M512.build.spiffs_start=0x180000 +generic.menu.eesz.2M512.build.spiffs_end=0x1FA000 +generic.menu.eesz.2M512.build.spiffs_blocksize=8192 +generic.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) +generic.menu.eesz.2M1M.build.flash_size=2M +generic.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +generic.menu.eesz.2M1M.build.spiffs_pagesize=256 +generic.menu.eesz.2M1M.upload.maximum_size=1044464 +generic.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +generic.menu.eesz.2M1M.build.spiffs_start=0x100000 +generic.menu.eesz.2M1M.build.spiffs_end=0x1FA000 +generic.menu.eesz.2M1M.build.spiffs_blocksize=8192 +generic.menu.eesz.2M=2MB (FS:none OTA:~1019KB) +generic.menu.eesz.2M.build.flash_size=2M +generic.menu.eesz.2M.build.flash_size_bytes=0x200000 +generic.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +generic.menu.eesz.2M.build.spiffs_pagesize=256 +generic.menu.eesz.2M.upload.maximum_size=1044464 +generic.menu.eesz.2M.build.rfcal_addr=0x1FC000 +generic.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +generic.menu.eesz.4M2M.build.flash_size=4M +generic.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +generic.menu.eesz.4M2M.build.spiffs_pagesize=256 +generic.menu.eesz.4M2M.upload.maximum_size=1044464 +generic.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M2M.build.spiffs_start=0x200000 +generic.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +generic.menu.eesz.4M2M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +generic.menu.eesz.4M3M.build.flash_size=4M +generic.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +generic.menu.eesz.4M3M.build.spiffs_pagesize=256 +generic.menu.eesz.4M3M.upload.maximum_size=1044464 +generic.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M3M.build.spiffs_start=0x100000 +generic.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +generic.menu.eesz.4M3M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +generic.menu.eesz.4M1M.build.flash_size=4M +generic.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +generic.menu.eesz.4M1M.build.spiffs_pagesize=256 +generic.menu.eesz.4M1M.upload.maximum_size=1044464 +generic.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.4M1M.build.spiffs_start=0x300000 +generic.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +generic.menu.eesz.4M1M.build.spiffs_blocksize=8192 +generic.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +generic.menu.eesz.4M.build.flash_size=4M +generic.menu.eesz.4M.build.flash_size_bytes=0x400000 +generic.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +generic.menu.eesz.4M.build.spiffs_pagesize=256 +generic.menu.eesz.4M.upload.maximum_size=1044464 +generic.menu.eesz.4M.build.rfcal_addr=0x3FC000 +generic.menu.eesz.8M6M=8MB (FS:6MB OTA:~1019KB) +generic.menu.eesz.8M6M.build.flash_size=8M +generic.menu.eesz.8M6M.build.flash_size_bytes=0x800000 +generic.menu.eesz.8M6M.build.flash_ld=eagle.flash.8m6m.ld +generic.menu.eesz.8M6M.build.spiffs_pagesize=256 +generic.menu.eesz.8M6M.upload.maximum_size=1044464 +generic.menu.eesz.8M6M.build.rfcal_addr=0x7FC000 +generic.menu.eesz.8M6M.build.spiffs_start=0x200000 +generic.menu.eesz.8M6M.build.spiffs_end=0x7FA000 +generic.menu.eesz.8M6M.build.spiffs_blocksize=8192 +generic.menu.eesz.8M7M=8MB (FS:7MB OTA:~512KB) +generic.menu.eesz.8M7M.build.flash_size=8M +generic.menu.eesz.8M7M.build.flash_size_bytes=0x800000 +generic.menu.eesz.8M7M.build.flash_ld=eagle.flash.8m7m.ld +generic.menu.eesz.8M7M.build.spiffs_pagesize=256 +generic.menu.eesz.8M7M.upload.maximum_size=1044464 +generic.menu.eesz.8M7M.build.rfcal_addr=0x7FC000 +generic.menu.eesz.8M7M.build.spiffs_start=0x100000 +generic.menu.eesz.8M7M.build.spiffs_end=0x7FA000 +generic.menu.eesz.8M7M.build.spiffs_blocksize=8192 +generic.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB) +generic.menu.eesz.16M14M.build.flash_size=16M +generic.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 +generic.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld +generic.menu.eesz.16M14M.build.spiffs_pagesize=256 +generic.menu.eesz.16M14M.upload.maximum_size=1044464 +generic.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 +generic.menu.eesz.16M14M.build.spiffs_start=0x200000 +generic.menu.eesz.16M14M.build.spiffs_end=0xFFA000 +generic.menu.eesz.16M14M.build.spiffs_blocksize=8192 +generic.menu.eesz.16M15M=16MB (FS:15MB OTA:~512KB) +generic.menu.eesz.16M15M.build.flash_size=16M +generic.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 +generic.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld +generic.menu.eesz.16M15M.build.spiffs_pagesize=256 +generic.menu.eesz.16M15M.upload.maximum_size=1044464 +generic.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 +generic.menu.eesz.16M15M.build.spiffs_start=0x100000 +generic.menu.eesz.16M15M.build.spiffs_end=0xFFA000 +generic.menu.eesz.16M15M.build.spiffs_blocksize=8192 +generic.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) +generic.menu.eesz.512K32.build.flash_size=512K +generic.menu.eesz.512K32.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +generic.menu.eesz.512K32.build.spiffs_pagesize=256 +generic.menu.eesz.512K32.upload.maximum_size=466928 +generic.menu.eesz.512K32.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K32.build.spiffs_start=0x73000 +generic.menu.eesz.512K32.build.spiffs_end=0x7B000 +generic.menu.eesz.512K32.build.spiffs_blocksize=4096 +generic.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) +generic.menu.eesz.512K64.build.flash_size=512K +generic.menu.eesz.512K64.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +generic.menu.eesz.512K64.build.spiffs_pagesize=256 +generic.menu.eesz.512K64.upload.maximum_size=434160 +generic.menu.eesz.512K64.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K64.build.spiffs_start=0x6B000 +generic.menu.eesz.512K64.build.spiffs_end=0x7B000 +generic.menu.eesz.512K64.build.spiffs_blocksize=4096 +generic.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) +generic.menu.eesz.512K128.build.flash_size=512K +generic.menu.eesz.512K128.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +generic.menu.eesz.512K128.build.spiffs_pagesize=256 +generic.menu.eesz.512K128.upload.maximum_size=368624 +generic.menu.eesz.512K128.build.rfcal_addr=0x7C000 +generic.menu.eesz.512K128.build.spiffs_start=0x5B000 +generic.menu.eesz.512K128.build.spiffs_end=0x7B000 +generic.menu.eesz.512K128.build.spiffs_blocksize=4096 +generic.menu.eesz.512K=512KB (FS:none OTA:~246KB) +generic.menu.eesz.512K.build.flash_size=512K +generic.menu.eesz.512K.build.flash_size_bytes=0x80000 +generic.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +generic.menu.eesz.512K.build.spiffs_pagesize=256 +generic.menu.eesz.512K.upload.maximum_size=499696 +generic.menu.eesz.512K.build.rfcal_addr=0x7C000 +generic.menu.led.2=2 +generic.menu.led.2.build.led=-DLED_BUILTIN=2 +generic.menu.led.0=0 +generic.menu.led.0.build.led=-DLED_BUILTIN=0 +generic.menu.led.1=1 +generic.menu.led.1.build.led=-DLED_BUILTIN=1 +generic.menu.led.3=3 +generic.menu.led.3.build.led=-DLED_BUILTIN=3 +generic.menu.led.4=4 +generic.menu.led.4.build.led=-DLED_BUILTIN=4 +generic.menu.led.5=5 +generic.menu.led.5.build.led=-DLED_BUILTIN=5 +generic.menu.led.6=6 +generic.menu.led.6.build.led=-DLED_BUILTIN=6 +generic.menu.led.7=7 +generic.menu.led.7.build.led=-DLED_BUILTIN=7 +generic.menu.led.8=8 +generic.menu.led.8.build.led=-DLED_BUILTIN=8 +generic.menu.led.9=9 +generic.menu.led.9.build.led=-DLED_BUILTIN=9 +generic.menu.led.10=10 +generic.menu.led.10.build.led=-DLED_BUILTIN=10 +generic.menu.led.11=11 +generic.menu.led.11.build.led=-DLED_BUILTIN=11 +generic.menu.led.12=12 +generic.menu.led.12.build.led=-DLED_BUILTIN=12 +generic.menu.led.13=13 +generic.menu.led.13.build.led=-DLED_BUILTIN=13 +generic.menu.led.14=14 +generic.menu.led.14.build.led=-DLED_BUILTIN=14 +generic.menu.led.15=15 +generic.menu.led.15.build.led=-DLED_BUILTIN=15 +generic.menu.led.16=16 +generic.menu.led.16.build.led=-DLED_BUILTIN=16 +generic.menu.sdk.nonosdk_190703=nonos-sdk 2.2.1+100 (190703) +generic.menu.sdk.nonosdk_190703.build.sdk=NONOSDK22x_190703 +generic.menu.sdk.nonosdk_191122=nonos-sdk 2.2.1+119 (191122) +generic.menu.sdk.nonosdk_191122.build.sdk=NONOSDK22x_191122 +generic.menu.sdk.nonosdk_191105=nonos-sdk 2.2.1+113 (191105) +generic.menu.sdk.nonosdk_191105.build.sdk=NONOSDK22x_191105 +generic.menu.sdk.nonosdk_191024=nonos-sdk 2.2.1+111 (191024) +generic.menu.sdk.nonosdk_191024.build.sdk=NONOSDK22x_191024 +generic.menu.sdk.nonosdk221=nonos-sdk 2.2.1 (legacy) +generic.menu.sdk.nonosdk221.build.sdk=NONOSDK221 +generic.menu.sdk.nonosdk3v0=nonos-sdk pre-3 (180626 known issues) +generic.menu.sdk.nonosdk3v0.build.sdk=NONOSDK3V0 +generic.menu.ip.lm2f=v2 Lower Memory +generic.menu.ip.lm2f.build.lwip_include=lwip2/include +generic.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +generic.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +generic.menu.ip.hb2f=v2 Higher Bandwidth +generic.menu.ip.hb2f.build.lwip_include=lwip2/include +generic.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +generic.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +generic.menu.ip.lm2n=v2 Lower Memory (no features) +generic.menu.ip.lm2n.build.lwip_include=lwip2/include +generic.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +generic.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +generic.menu.ip.hb2n=v2 Higher Bandwidth (no features) +generic.menu.ip.hb2n.build.lwip_include=lwip2/include +generic.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +generic.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +generic.menu.ip.lm6f=v2 IPv6 Lower Memory +generic.menu.ip.lm6f.build.lwip_include=lwip2/include +generic.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +generic.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +generic.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +generic.menu.ip.hb6f.build.lwip_include=lwip2/include +generic.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +generic.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +generic.menu.ip.hb1=v1.4 Higher Bandwidth +generic.menu.ip.hb1.build.lwip_lib=-llwip_gcc +generic.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +generic.menu.ip.src=v1.4 Compile from source +generic.menu.ip.src.build.lwip_lib=-llwip_src +generic.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +generic.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +generic.menu.dbg.Disabled=Disabled +generic.menu.dbg.Disabled.build.debug_port= +generic.menu.dbg.Serial=Serial +generic.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +generic.menu.dbg.Serial1=Serial1 +generic.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +generic.menu.lvl.None____=None +generic.menu.lvl.None____.build.debug_level= +generic.menu.lvl.SSL=SSL +generic.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +generic.menu.lvl.TLS_MEM=TLS_MEM +generic.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +generic.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +generic.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.HTTP_SERVER=HTTP_SERVER +generic.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +generic.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +generic.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +generic.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +generic.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +generic.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +generic.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +generic.menu.lvl.CORE=CORE +generic.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +generic.menu.lvl.WIFI=WIFI +generic.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +generic.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +generic.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +generic.menu.lvl.UPDATER=UPDATER +generic.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +generic.menu.lvl.OTA=OTA +generic.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +generic.menu.lvl.OOM=OOM +generic.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +generic.menu.lvl.MDNS=MDNS +generic.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +generic.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +generic.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +generic.menu.wipe.none=Only Sketch +generic.menu.wipe.none.upload.erase_cmd= +generic.menu.wipe.sdk=Sketch + WiFi Settings +generic.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +generic.menu.wipe.all=All Flash Contents +generic.menu.wipe.all.upload.erase_cmd=erase_flash +generic.menu.baud.115200=115200 +generic.menu.baud.115200.upload.speed=115200 +generic.menu.baud.57600=57600 +generic.menu.baud.57600.upload.speed=57600 +generic.menu.baud.230400.linux=230400 +generic.menu.baud.230400.macosx=230400 +generic.menu.baud.230400.upload.speed=230400 +generic.menu.baud.256000.windows=256000 +generic.menu.baud.256000.upload.speed=256000 +generic.menu.baud.460800.linux=460800 +generic.menu.baud.460800.macosx=460800 +generic.menu.baud.460800.upload.speed=460800 +generic.menu.baud.512000.windows=512000 +generic.menu.baud.512000.upload.speed=512000 +generic.menu.baud.921600=921600 +generic.menu.baud.921600.upload.speed=921600 +generic.menu.baud.3000000=3000000 +generic.menu.baud.3000000.upload.speed=3000000 + +############################################################## +esp8285.name=Generic ESP8285 Module +esp8285.build.board=ESP8266_ESP01 +esp8285.build.variant=esp8285 +esp8285.upload.tool=esptool +esp8285.upload.maximum_data_size=81920 +esp8285.upload.wait_for_upload_port=true +esp8285.upload.erase_cmd= +esp8285.serial.disableDTR=true +esp8285.serial.disableRTS=true +esp8285.build.mcu=esp8266 +esp8285.build.core=esp8266 +esp8285.build.spiffs_pagesize=256 +esp8285.build.debug_port= +esp8285.build.debug_level= +esp8285.menu.xtal.80=80 MHz +esp8285.menu.xtal.80.build.f_cpu=80000000L +esp8285.menu.xtal.160=160 MHz +esp8285.menu.xtal.160.build.f_cpu=160000000L +esp8285.menu.vt.flash=Flash +esp8285.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +esp8285.menu.vt.heap=Heap +esp8285.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +esp8285.menu.vt.iram=IRAM +esp8285.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +esp8285.menu.exception.legacy=Legacy (new can return nullptr) +esp8285.menu.exception.legacy.build.exception_flags=-fno-exceptions +esp8285.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +esp8285.menu.exception.disabled=Disabled (new can abort) +esp8285.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +esp8285.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +esp8285.menu.exception.enabled=Enabled +esp8285.menu.exception.enabled.build.exception_flags=-fexceptions +esp8285.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +esp8285.menu.ssl.all=All SSL ciphers (most compatible) +esp8285.menu.ssl.all.build.sslflags= +esp8285.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +esp8285.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +esp8285.menu.ResetMethod.nodemcu=dtr (aka nodemcu) +esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset +esp8285.menu.ResetMethod.ck=no dtr (aka ck) +esp8285.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset +esp8285.menu.ResetMethod.nodtr_nosync=no dtr, no_sync +esp8285.menu.ResetMethod.nodtr_nosync.upload.resetmethod=--before no_reset_no_sync --after soft_reset +esp8285.menu.CrystalFreq.26=26 MHz +esp8285.menu.CrystalFreq.40=40 MHz +esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +esp8285.build.flash_mode=dout +esp8285.build.flash_flags=-DFLASHMODE_DOUT +esp8285.build.flash_freq=40 +esp8285.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +esp8285.menu.eesz.1M64.build.flash_size=1M +esp8285.menu.eesz.1M64.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +esp8285.menu.eesz.1M64.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M64.upload.maximum_size=958448 +esp8285.menu.eesz.1M64.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M64.build.spiffs_start=0xEB000 +esp8285.menu.eesz.1M64.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M64.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +esp8285.menu.eesz.1M128.build.flash_size=1M +esp8285.menu.eesz.1M128.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +esp8285.menu.eesz.1M128.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M128.upload.maximum_size=892912 +esp8285.menu.eesz.1M128.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M128.build.spiffs_start=0xDB000 +esp8285.menu.eesz.1M128.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M128.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +esp8285.menu.eesz.1M144.build.flash_size=1M +esp8285.menu.eesz.1M144.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +esp8285.menu.eesz.1M144.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M144.upload.maximum_size=876528 +esp8285.menu.eesz.1M144.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M144.build.spiffs_start=0xD7000 +esp8285.menu.eesz.1M144.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M144.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +esp8285.menu.eesz.1M160.build.flash_size=1M +esp8285.menu.eesz.1M160.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +esp8285.menu.eesz.1M160.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M160.upload.maximum_size=860144 +esp8285.menu.eesz.1M160.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M160.build.spiffs_start=0xD3000 +esp8285.menu.eesz.1M160.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M160.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +esp8285.menu.eesz.1M192.build.flash_size=1M +esp8285.menu.eesz.1M192.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +esp8285.menu.eesz.1M192.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M192.upload.maximum_size=827376 +esp8285.menu.eesz.1M192.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M192.build.spiffs_start=0xCB000 +esp8285.menu.eesz.1M192.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M192.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +esp8285.menu.eesz.1M256.build.flash_size=1M +esp8285.menu.eesz.1M256.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +esp8285.menu.eesz.1M256.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M256.upload.maximum_size=761840 +esp8285.menu.eesz.1M256.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M256.build.spiffs_start=0xBB000 +esp8285.menu.eesz.1M256.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M256.build.spiffs_blocksize=4096 +esp8285.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +esp8285.menu.eesz.1M512.build.flash_size=1M +esp8285.menu.eesz.1M512.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +esp8285.menu.eesz.1M512.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M512.upload.maximum_size=499696 +esp8285.menu.eesz.1M512.build.rfcal_addr=0xFC000 +esp8285.menu.eesz.1M512.build.spiffs_start=0x7B000 +esp8285.menu.eesz.1M512.build.spiffs_end=0xFB000 +esp8285.menu.eesz.1M512.build.spiffs_blocksize=8192 +esp8285.menu.eesz.1M=1MB (FS:none OTA:~502KB) +esp8285.menu.eesz.1M.build.flash_size=1M +esp8285.menu.eesz.1M.build.flash_size_bytes=0x100000 +esp8285.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +esp8285.menu.eesz.1M.build.spiffs_pagesize=256 +esp8285.menu.eesz.1M.upload.maximum_size=1023984 +esp8285.menu.eesz.1M.build.rfcal_addr=0xFC000 +esp8285.menu.led.2=2 +esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 +esp8285.menu.led.0=0 +esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 +esp8285.menu.led.1=1 +esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 +esp8285.menu.led.3=3 +esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 +esp8285.menu.led.4=4 +esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 +esp8285.menu.led.5=5 +esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 +esp8285.menu.led.6=6 +esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 +esp8285.menu.led.7=7 +esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 +esp8285.menu.led.8=8 +esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 +esp8285.menu.led.9=9 +esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 +esp8285.menu.led.10=10 +esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 +esp8285.menu.led.11=11 +esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 +esp8285.menu.led.12=12 +esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 +esp8285.menu.led.13=13 +esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 +esp8285.menu.led.14=14 +esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 +esp8285.menu.led.15=15 +esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 +esp8285.menu.led.16=16 +esp8285.menu.led.16.build.led=-DLED_BUILTIN=16 +esp8285.menu.ip.lm2f=v2 Lower Memory +esp8285.menu.ip.lm2f.build.lwip_include=lwip2/include +esp8285.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +esp8285.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp8285.menu.ip.hb2f=v2 Higher Bandwidth +esp8285.menu.ip.hb2f.build.lwip_include=lwip2/include +esp8285.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +esp8285.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp8285.menu.ip.lm2n=v2 Lower Memory (no features) +esp8285.menu.ip.lm2n.build.lwip_include=lwip2/include +esp8285.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +esp8285.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp8285.menu.ip.hb2n=v2 Higher Bandwidth (no features) +esp8285.menu.ip.hb2n.build.lwip_include=lwip2/include +esp8285.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +esp8285.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp8285.menu.ip.lm6f=v2 IPv6 Lower Memory +esp8285.menu.ip.lm6f.build.lwip_include=lwip2/include +esp8285.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +esp8285.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp8285.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +esp8285.menu.ip.hb6f.build.lwip_include=lwip2/include +esp8285.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +esp8285.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp8285.menu.ip.hb1=v1.4 Higher Bandwidth +esp8285.menu.ip.hb1.build.lwip_lib=-llwip_gcc +esp8285.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +esp8285.menu.ip.src=v1.4 Compile from source +esp8285.menu.ip.src.build.lwip_lib=-llwip_src +esp8285.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +esp8285.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +esp8285.menu.dbg.Disabled=Disabled +esp8285.menu.dbg.Disabled.build.debug_port= +esp8285.menu.dbg.Serial=Serial +esp8285.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +esp8285.menu.dbg.Serial1=Serial1 +esp8285.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +esp8285.menu.lvl.None____=None +esp8285.menu.lvl.None____.build.debug_level= +esp8285.menu.lvl.SSL=SSL +esp8285.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +esp8285.menu.lvl.TLS_MEM=TLS_MEM +esp8285.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +esp8285.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +esp8285.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.HTTP_SERVER=HTTP_SERVER +esp8285.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +esp8285.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +esp8285.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +esp8285.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +esp8285.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp8285.menu.lvl.CORE=CORE +esp8285.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +esp8285.menu.lvl.WIFI=WIFI +esp8285.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +esp8285.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +esp8285.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +esp8285.menu.lvl.UPDATER=UPDATER +esp8285.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +esp8285.menu.lvl.OTA=OTA +esp8285.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +esp8285.menu.lvl.OOM=OOM +esp8285.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +esp8285.menu.lvl.MDNS=MDNS +esp8285.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +esp8285.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +esp8285.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +esp8285.menu.wipe.none=Only Sketch +esp8285.menu.wipe.none.upload.erase_cmd= +esp8285.menu.wipe.sdk=Sketch + WiFi Settings +esp8285.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +esp8285.menu.wipe.all=All Flash Contents +esp8285.menu.wipe.all.upload.erase_cmd=erase_flash +esp8285.menu.baud.115200=115200 +esp8285.menu.baud.115200.upload.speed=115200 +esp8285.menu.baud.57600=57600 +esp8285.menu.baud.57600.upload.speed=57600 +esp8285.menu.baud.230400.linux=230400 +esp8285.menu.baud.230400.macosx=230400 +esp8285.menu.baud.230400.upload.speed=230400 +esp8285.menu.baud.256000.windows=256000 +esp8285.menu.baud.256000.upload.speed=256000 +esp8285.menu.baud.460800.linux=460800 +esp8285.menu.baud.460800.macosx=460800 +esp8285.menu.baud.460800.upload.speed=460800 +esp8285.menu.baud.512000.windows=512000 +esp8285.menu.baud.512000.upload.speed=512000 +esp8285.menu.baud.921600=921600 +esp8285.menu.baud.921600.upload.speed=921600 +esp8285.menu.baud.3000000=3000000 +esp8285.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espduino.name=ESPDuino (ESP-13 Module) +espduino.build.board=ESP8266_ESP13 +espduino.build.variant=ESPDuino +espduino.menu.ResetMethod.v1=ESPduino-V1 +espduino.menu.ResetMethod.v1.upload.resetmethod=--before no_reset --after soft_reset +espduino.menu.ResetMethod.v2=ESPduino-V2 +espduino.menu.ResetMethod.v2.upload.resetmethod=--before default_reset --after hard_reset +espduino.menu.UploadTool.espota=OTA +espduino.menu.UploadTool.espota.upload.tool=espota +espduino.menu.UploadTool.esptool=Serial +espduino.menu.UploadTool.esptool.upload.tool=esptool +espduino.menu.UploadTool.esptool.upload.verbose=--trace +espduino.upload.tool=esptool +espduino.upload.maximum_data_size=81920 +espduino.upload.wait_for_upload_port=true +espduino.upload.erase_cmd= +espduino.serial.disableDTR=true +espduino.serial.disableRTS=true +espduino.build.mcu=esp8266 +espduino.build.core=esp8266 +espduino.build.spiffs_pagesize=256 +espduino.build.debug_port= +espduino.build.debug_level= +espduino.menu.xtal.80=80 MHz +espduino.menu.xtal.80.build.f_cpu=80000000L +espduino.menu.xtal.160=160 MHz +espduino.menu.xtal.160.build.f_cpu=160000000L +espduino.menu.vt.flash=Flash +espduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espduino.menu.vt.heap=Heap +espduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espduino.menu.vt.iram=IRAM +espduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espduino.menu.exception.legacy=Legacy (new can return nullptr) +espduino.menu.exception.legacy.build.exception_flags=-fno-exceptions +espduino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espduino.menu.exception.disabled=Disabled (new can abort) +espduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espduino.menu.exception.enabled=Enabled +espduino.menu.exception.enabled.build.exception_flags=-fexceptions +espduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espduino.menu.ssl.all=All SSL ciphers (most compatible) +espduino.menu.ssl.all.build.sslflags= +espduino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espduino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espduino.build.flash_mode=dio +espduino.build.flash_flags=-DFLASHMODE_DIO +espduino.build.flash_freq=40 +espduino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espduino.menu.eesz.4M2M.build.flash_size=4M +espduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espduino.menu.eesz.4M2M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M2M.upload.maximum_size=1044464 +espduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M2M.build.spiffs_start=0x200000 +espduino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espduino.menu.eesz.4M3M.build.flash_size=4M +espduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espduino.menu.eesz.4M3M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M3M.upload.maximum_size=1044464 +espduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M3M.build.spiffs_start=0x100000 +espduino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espduino.menu.eesz.4M1M.build.flash_size=4M +espduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espduino.menu.eesz.4M1M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M1M.upload.maximum_size=1044464 +espduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espduino.menu.eesz.4M1M.build.spiffs_start=0x300000 +espduino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espduino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espduino.menu.eesz.4M.build.flash_size=4M +espduino.menu.eesz.4M.build.flash_size_bytes=0x400000 +espduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espduino.menu.eesz.4M.build.spiffs_pagesize=256 +espduino.menu.eesz.4M.upload.maximum_size=1044464 +espduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espduino.menu.ip.lm2f=v2 Lower Memory +espduino.menu.ip.lm2f.build.lwip_include=lwip2/include +espduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espduino.menu.ip.hb2f=v2 Higher Bandwidth +espduino.menu.ip.hb2f.build.lwip_include=lwip2/include +espduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espduino.menu.ip.lm2n=v2 Lower Memory (no features) +espduino.menu.ip.lm2n.build.lwip_include=lwip2/include +espduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espduino.menu.ip.hb2n.build.lwip_include=lwip2/include +espduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espduino.menu.ip.lm6f=v2 IPv6 Lower Memory +espduino.menu.ip.lm6f.build.lwip_include=lwip2/include +espduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espduino.menu.ip.hb6f.build.lwip_include=lwip2/include +espduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espduino.menu.ip.hb1=v1.4 Higher Bandwidth +espduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espduino.menu.ip.src=v1.4 Compile from source +espduino.menu.ip.src.build.lwip_lib=-llwip_src +espduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espduino.menu.dbg.Disabled=Disabled +espduino.menu.dbg.Disabled.build.debug_port= +espduino.menu.dbg.Serial=Serial +espduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espduino.menu.dbg.Serial1=Serial1 +espduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espduino.menu.lvl.None____=None +espduino.menu.lvl.None____.build.debug_level= +espduino.menu.lvl.SSL=SSL +espduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espduino.menu.lvl.TLS_MEM=TLS_MEM +espduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.HTTP_SERVER=HTTP_SERVER +espduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espduino.menu.lvl.CORE=CORE +espduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espduino.menu.lvl.WIFI=WIFI +espduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espduino.menu.lvl.UPDATER=UPDATER +espduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espduino.menu.lvl.OTA=OTA +espduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espduino.menu.lvl.OOM=OOM +espduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espduino.menu.lvl.MDNS=MDNS +espduino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espduino.menu.wipe.none=Only Sketch +espduino.menu.wipe.none.upload.erase_cmd= +espduino.menu.wipe.sdk=Sketch + WiFi Settings +espduino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espduino.menu.wipe.all=All Flash Contents +espduino.menu.wipe.all.upload.erase_cmd=erase_flash +espduino.menu.baud.115200=115200 +espduino.menu.baud.115200.upload.speed=115200 +espduino.menu.baud.57600=57600 +espduino.menu.baud.57600.upload.speed=57600 +espduino.menu.baud.230400.linux=230400 +espduino.menu.baud.230400.macosx=230400 +espduino.menu.baud.230400.upload.speed=230400 +espduino.menu.baud.256000.windows=256000 +espduino.menu.baud.256000.upload.speed=256000 +espduino.menu.baud.460800.linux=460800 +espduino.menu.baud.460800.macosx=460800 +espduino.menu.baud.460800.upload.speed=460800 +espduino.menu.baud.512000.windows=512000 +espduino.menu.baud.512000.upload.speed=512000 +espduino.menu.baud.921600=921600 +espduino.menu.baud.921600.upload.speed=921600 +espduino.menu.baud.3000000=3000000 +espduino.menu.baud.3000000.upload.speed=3000000 + +############################################################## +huzzah.name=Adafruit Feather HUZZAH ESP8266 +huzzah.build.board=ESP8266_ESP12 +huzzah.build.variant=adafruit +huzzah.upload.tool=esptool +huzzah.upload.maximum_data_size=81920 +huzzah.upload.wait_for_upload_port=true +huzzah.upload.erase_cmd= +huzzah.serial.disableDTR=true +huzzah.serial.disableRTS=true +huzzah.build.mcu=esp8266 +huzzah.build.core=esp8266 +huzzah.build.spiffs_pagesize=256 +huzzah.build.debug_port= +huzzah.build.debug_level= +huzzah.menu.xtal.80=80 MHz +huzzah.menu.xtal.80.build.f_cpu=80000000L +huzzah.menu.xtal.160=160 MHz +huzzah.menu.xtal.160.build.f_cpu=160000000L +huzzah.menu.vt.flash=Flash +huzzah.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +huzzah.menu.vt.heap=Heap +huzzah.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +huzzah.menu.vt.iram=IRAM +huzzah.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +huzzah.menu.exception.legacy=Legacy (new can return nullptr) +huzzah.menu.exception.legacy.build.exception_flags=-fno-exceptions +huzzah.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +huzzah.menu.exception.disabled=Disabled (new can abort) +huzzah.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +huzzah.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +huzzah.menu.exception.enabled=Enabled +huzzah.menu.exception.enabled.build.exception_flags=-fexceptions +huzzah.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +huzzah.menu.ssl.all=All SSL ciphers (most compatible) +huzzah.menu.ssl.all.build.sslflags= +huzzah.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +huzzah.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +huzzah.upload.resetmethod=--before default_reset --after hard_reset +huzzah.build.flash_mode=qio +huzzah.build.flash_flags=-DFLASHMODE_QIO +huzzah.build.flash_freq=40 +huzzah.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +huzzah.menu.eesz.4M2M.build.flash_size=4M +huzzah.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +huzzah.menu.eesz.4M2M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M2M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M2M.build.spiffs_start=0x200000 +huzzah.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +huzzah.menu.eesz.4M2M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +huzzah.menu.eesz.4M3M.build.flash_size=4M +huzzah.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +huzzah.menu.eesz.4M3M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M3M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M3M.build.spiffs_start=0x100000 +huzzah.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +huzzah.menu.eesz.4M3M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +huzzah.menu.eesz.4M1M.build.flash_size=4M +huzzah.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +huzzah.menu.eesz.4M1M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M1M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +huzzah.menu.eesz.4M1M.build.spiffs_start=0x300000 +huzzah.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +huzzah.menu.eesz.4M1M.build.spiffs_blocksize=8192 +huzzah.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +huzzah.menu.eesz.4M.build.flash_size=4M +huzzah.menu.eesz.4M.build.flash_size_bytes=0x400000 +huzzah.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +huzzah.menu.eesz.4M.build.spiffs_pagesize=256 +huzzah.menu.eesz.4M.upload.maximum_size=1044464 +huzzah.menu.eesz.4M.build.rfcal_addr=0x3FC000 +huzzah.menu.ip.lm2f=v2 Lower Memory +huzzah.menu.ip.lm2f.build.lwip_include=lwip2/include +huzzah.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +huzzah.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +huzzah.menu.ip.hb2f=v2 Higher Bandwidth +huzzah.menu.ip.hb2f.build.lwip_include=lwip2/include +huzzah.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +huzzah.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +huzzah.menu.ip.lm2n=v2 Lower Memory (no features) +huzzah.menu.ip.lm2n.build.lwip_include=lwip2/include +huzzah.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +huzzah.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +huzzah.menu.ip.hb2n=v2 Higher Bandwidth (no features) +huzzah.menu.ip.hb2n.build.lwip_include=lwip2/include +huzzah.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +huzzah.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +huzzah.menu.ip.lm6f=v2 IPv6 Lower Memory +huzzah.menu.ip.lm6f.build.lwip_include=lwip2/include +huzzah.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +huzzah.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +huzzah.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +huzzah.menu.ip.hb6f.build.lwip_include=lwip2/include +huzzah.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +huzzah.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +huzzah.menu.ip.hb1=v1.4 Higher Bandwidth +huzzah.menu.ip.hb1.build.lwip_lib=-llwip_gcc +huzzah.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +huzzah.menu.ip.src=v1.4 Compile from source +huzzah.menu.ip.src.build.lwip_lib=-llwip_src +huzzah.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +huzzah.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +huzzah.menu.dbg.Disabled=Disabled +huzzah.menu.dbg.Disabled.build.debug_port= +huzzah.menu.dbg.Serial=Serial +huzzah.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +huzzah.menu.dbg.Serial1=Serial1 +huzzah.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +huzzah.menu.lvl.None____=None +huzzah.menu.lvl.None____.build.debug_level= +huzzah.menu.lvl.SSL=SSL +huzzah.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +huzzah.menu.lvl.TLS_MEM=TLS_MEM +huzzah.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +huzzah.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +huzzah.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.HTTP_SERVER=HTTP_SERVER +huzzah.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +huzzah.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +huzzah.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +huzzah.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +huzzah.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +huzzah.menu.lvl.CORE=CORE +huzzah.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +huzzah.menu.lvl.WIFI=WIFI +huzzah.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +huzzah.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +huzzah.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +huzzah.menu.lvl.UPDATER=UPDATER +huzzah.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +huzzah.menu.lvl.OTA=OTA +huzzah.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +huzzah.menu.lvl.OOM=OOM +huzzah.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +huzzah.menu.lvl.MDNS=MDNS +huzzah.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +huzzah.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +huzzah.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +huzzah.menu.wipe.none=Only Sketch +huzzah.menu.wipe.none.upload.erase_cmd= +huzzah.menu.wipe.sdk=Sketch + WiFi Settings +huzzah.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +huzzah.menu.wipe.all=All Flash Contents +huzzah.menu.wipe.all.upload.erase_cmd=erase_flash +huzzah.menu.baud.115200=115200 +huzzah.menu.baud.115200.upload.speed=115200 +huzzah.menu.baud.57600=57600 +huzzah.menu.baud.57600.upload.speed=57600 +huzzah.menu.baud.230400.linux=230400 +huzzah.menu.baud.230400.macosx=230400 +huzzah.menu.baud.230400.upload.speed=230400 +huzzah.menu.baud.256000.windows=256000 +huzzah.menu.baud.256000.upload.speed=256000 +huzzah.menu.baud.460800.linux=460800 +huzzah.menu.baud.460800.macosx=460800 +huzzah.menu.baud.460800.upload.speed=460800 +huzzah.menu.baud.512000.windows=512000 +huzzah.menu.baud.512000.upload.speed=512000 +huzzah.menu.baud.921600=921600 +huzzah.menu.baud.921600.upload.speed=921600 +huzzah.menu.baud.3000000=3000000 +huzzah.menu.baud.3000000.upload.speed=3000000 + +############################################################## +inventone.name=Invent One +inventone.build.board=ESP8266_GENERIC +inventone.build.variant=inventone +inventone.upload.tool=esptool +inventone.upload.maximum_data_size=81920 +inventone.upload.wait_for_upload_port=true +inventone.upload.erase_cmd= +inventone.serial.disableDTR=true +inventone.serial.disableRTS=true +inventone.build.mcu=esp8266 +inventone.build.core=esp8266 +inventone.build.spiffs_pagesize=256 +inventone.build.debug_port= +inventone.build.debug_level= +inventone.menu.xtal.80=80 MHz +inventone.menu.xtal.80.build.f_cpu=80000000L +inventone.menu.xtal.160=160 MHz +inventone.menu.xtal.160.build.f_cpu=160000000L +inventone.menu.vt.flash=Flash +inventone.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +inventone.menu.vt.heap=Heap +inventone.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +inventone.menu.vt.iram=IRAM +inventone.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +inventone.menu.exception.legacy=Legacy (new can return nullptr) +inventone.menu.exception.legacy.build.exception_flags=-fno-exceptions +inventone.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +inventone.menu.exception.disabled=Disabled (new can abort) +inventone.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +inventone.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +inventone.menu.exception.enabled=Enabled +inventone.menu.exception.enabled.build.exception_flags=-fexceptions +inventone.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +inventone.menu.ssl.all=All SSL ciphers (most compatible) +inventone.menu.ssl.all.build.sslflags= +inventone.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +inventone.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +inventone.upload.resetmethod=--before default_reset --after hard_reset +inventone.build.flash_mode=dio +inventone.build.flash_flags=-DFLASHMODE_DIO +inventone.build.flash_freq=40 +inventone.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +inventone.menu.eesz.4M2M.build.flash_size=4M +inventone.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +inventone.menu.eesz.4M2M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M2M.upload.maximum_size=1044464 +inventone.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M2M.build.spiffs_start=0x200000 +inventone.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +inventone.menu.eesz.4M2M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +inventone.menu.eesz.4M3M.build.flash_size=4M +inventone.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +inventone.menu.eesz.4M3M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M3M.upload.maximum_size=1044464 +inventone.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M3M.build.spiffs_start=0x100000 +inventone.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +inventone.menu.eesz.4M3M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +inventone.menu.eesz.4M1M.build.flash_size=4M +inventone.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +inventone.menu.eesz.4M1M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M1M.upload.maximum_size=1044464 +inventone.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +inventone.menu.eesz.4M1M.build.spiffs_start=0x300000 +inventone.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +inventone.menu.eesz.4M1M.build.spiffs_blocksize=8192 +inventone.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +inventone.menu.eesz.4M.build.flash_size=4M +inventone.menu.eesz.4M.build.flash_size_bytes=0x400000 +inventone.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +inventone.menu.eesz.4M.build.spiffs_pagesize=256 +inventone.menu.eesz.4M.upload.maximum_size=1044464 +inventone.menu.eesz.4M.build.rfcal_addr=0x3FC000 +inventone.menu.ip.lm2f=v2 Lower Memory +inventone.menu.ip.lm2f.build.lwip_include=lwip2/include +inventone.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +inventone.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +inventone.menu.ip.hb2f=v2 Higher Bandwidth +inventone.menu.ip.hb2f.build.lwip_include=lwip2/include +inventone.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +inventone.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +inventone.menu.ip.lm2n=v2 Lower Memory (no features) +inventone.menu.ip.lm2n.build.lwip_include=lwip2/include +inventone.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +inventone.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +inventone.menu.ip.hb2n=v2 Higher Bandwidth (no features) +inventone.menu.ip.hb2n.build.lwip_include=lwip2/include +inventone.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +inventone.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +inventone.menu.ip.lm6f=v2 IPv6 Lower Memory +inventone.menu.ip.lm6f.build.lwip_include=lwip2/include +inventone.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +inventone.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +inventone.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +inventone.menu.ip.hb6f.build.lwip_include=lwip2/include +inventone.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +inventone.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +inventone.menu.ip.hb1=v1.4 Higher Bandwidth +inventone.menu.ip.hb1.build.lwip_lib=-llwip_gcc +inventone.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +inventone.menu.ip.src=v1.4 Compile from source +inventone.menu.ip.src.build.lwip_lib=-llwip_src +inventone.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +inventone.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +inventone.menu.dbg.Disabled=Disabled +inventone.menu.dbg.Disabled.build.debug_port= +inventone.menu.dbg.Serial=Serial +inventone.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +inventone.menu.dbg.Serial1=Serial1 +inventone.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +inventone.menu.lvl.None____=None +inventone.menu.lvl.None____.build.debug_level= +inventone.menu.lvl.SSL=SSL +inventone.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +inventone.menu.lvl.TLS_MEM=TLS_MEM +inventone.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +inventone.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +inventone.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.HTTP_SERVER=HTTP_SERVER +inventone.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +inventone.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +inventone.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +inventone.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +inventone.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +inventone.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +inventone.menu.lvl.CORE=CORE +inventone.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +inventone.menu.lvl.WIFI=WIFI +inventone.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +inventone.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +inventone.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +inventone.menu.lvl.UPDATER=UPDATER +inventone.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +inventone.menu.lvl.OTA=OTA +inventone.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +inventone.menu.lvl.OOM=OOM +inventone.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +inventone.menu.lvl.MDNS=MDNS +inventone.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +inventone.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +inventone.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +inventone.menu.wipe.none=Only Sketch +inventone.menu.wipe.none.upload.erase_cmd= +inventone.menu.wipe.sdk=Sketch + WiFi Settings +inventone.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +inventone.menu.wipe.all=All Flash Contents +inventone.menu.wipe.all.upload.erase_cmd=erase_flash +inventone.menu.baud.115200=115200 +inventone.menu.baud.115200.upload.speed=115200 +inventone.menu.baud.57600=57600 +inventone.menu.baud.57600.upload.speed=57600 +inventone.menu.baud.230400.linux=230400 +inventone.menu.baud.230400.macosx=230400 +inventone.menu.baud.230400.upload.speed=230400 +inventone.menu.baud.256000.windows=256000 +inventone.menu.baud.256000.upload.speed=256000 +inventone.menu.baud.460800.linux=460800 +inventone.menu.baud.460800.macosx=460800 +inventone.menu.baud.460800.upload.speed=460800 +inventone.menu.baud.512000.windows=512000 +inventone.menu.baud.512000.upload.speed=512000 +inventone.menu.baud.921600=921600 +inventone.menu.baud.921600.upload.speed=921600 +inventone.menu.baud.3000000=3000000 +inventone.menu.baud.3000000.upload.speed=3000000 + +############################################################## +cw01.name=XinaBox CW01 +cw01.build.board=ESP8266_GENERIC +cw01.build.variant=xinabox +cw01.upload.tool=esptool +cw01.upload.maximum_data_size=81920 +cw01.upload.wait_for_upload_port=true +cw01.upload.erase_cmd= +cw01.serial.disableDTR=true +cw01.serial.disableRTS=true +cw01.build.mcu=esp8266 +cw01.build.core=esp8266 +cw01.build.spiffs_pagesize=256 +cw01.build.debug_port= +cw01.build.debug_level= +cw01.menu.xtal.80=80 MHz +cw01.menu.xtal.80.build.f_cpu=80000000L +cw01.menu.xtal.160=160 MHz +cw01.menu.xtal.160.build.f_cpu=160000000L +cw01.menu.vt.flash=Flash +cw01.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +cw01.menu.vt.heap=Heap +cw01.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +cw01.menu.vt.iram=IRAM +cw01.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +cw01.menu.exception.legacy=Legacy (new can return nullptr) +cw01.menu.exception.legacy.build.exception_flags=-fno-exceptions +cw01.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +cw01.menu.exception.disabled=Disabled (new can abort) +cw01.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +cw01.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +cw01.menu.exception.enabled=Enabled +cw01.menu.exception.enabled.build.exception_flags=-fexceptions +cw01.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +cw01.menu.ssl.all=All SSL ciphers (most compatible) +cw01.menu.ssl.all.build.sslflags= +cw01.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +cw01.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +cw01.upload.resetmethod=--before default_reset --after hard_reset +cw01.menu.CrystalFreq.26=26 MHz +cw01.menu.CrystalFreq.40=40 MHz +cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +cw01.build.flash_mode=dio +cw01.build.flash_flags=-DFLASHMODE_DIO +cw01.build.flash_freq=40 +cw01.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +cw01.menu.eesz.4M2M.build.flash_size=4M +cw01.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +cw01.menu.eesz.4M2M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M2M.upload.maximum_size=1044464 +cw01.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M2M.build.spiffs_start=0x200000 +cw01.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +cw01.menu.eesz.4M2M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +cw01.menu.eesz.4M3M.build.flash_size=4M +cw01.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +cw01.menu.eesz.4M3M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M3M.upload.maximum_size=1044464 +cw01.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M3M.build.spiffs_start=0x100000 +cw01.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +cw01.menu.eesz.4M3M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +cw01.menu.eesz.4M1M.build.flash_size=4M +cw01.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +cw01.menu.eesz.4M1M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M1M.upload.maximum_size=1044464 +cw01.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +cw01.menu.eesz.4M1M.build.spiffs_start=0x300000 +cw01.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +cw01.menu.eesz.4M1M.build.spiffs_blocksize=8192 +cw01.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +cw01.menu.eesz.4M.build.flash_size=4M +cw01.menu.eesz.4M.build.flash_size_bytes=0x400000 +cw01.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +cw01.menu.eesz.4M.build.spiffs_pagesize=256 +cw01.menu.eesz.4M.upload.maximum_size=1044464 +cw01.menu.eesz.4M.build.rfcal_addr=0x3FC000 +cw01.menu.ip.lm2f=v2 Lower Memory +cw01.menu.ip.lm2f.build.lwip_include=lwip2/include +cw01.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +cw01.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +cw01.menu.ip.hb2f=v2 Higher Bandwidth +cw01.menu.ip.hb2f.build.lwip_include=lwip2/include +cw01.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +cw01.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +cw01.menu.ip.lm2n=v2 Lower Memory (no features) +cw01.menu.ip.lm2n.build.lwip_include=lwip2/include +cw01.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +cw01.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +cw01.menu.ip.hb2n=v2 Higher Bandwidth (no features) +cw01.menu.ip.hb2n.build.lwip_include=lwip2/include +cw01.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +cw01.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +cw01.menu.ip.lm6f=v2 IPv6 Lower Memory +cw01.menu.ip.lm6f.build.lwip_include=lwip2/include +cw01.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +cw01.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +cw01.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +cw01.menu.ip.hb6f.build.lwip_include=lwip2/include +cw01.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +cw01.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +cw01.menu.ip.hb1=v1.4 Higher Bandwidth +cw01.menu.ip.hb1.build.lwip_lib=-llwip_gcc +cw01.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +cw01.menu.ip.src=v1.4 Compile from source +cw01.menu.ip.src.build.lwip_lib=-llwip_src +cw01.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +cw01.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +cw01.menu.dbg.Disabled=Disabled +cw01.menu.dbg.Disabled.build.debug_port= +cw01.menu.dbg.Serial=Serial +cw01.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +cw01.menu.dbg.Serial1=Serial1 +cw01.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +cw01.menu.lvl.None____=None +cw01.menu.lvl.None____.build.debug_level= +cw01.menu.lvl.SSL=SSL +cw01.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +cw01.menu.lvl.TLS_MEM=TLS_MEM +cw01.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +cw01.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +cw01.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.HTTP_SERVER=HTTP_SERVER +cw01.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +cw01.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +cw01.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +cw01.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +cw01.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +cw01.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +cw01.menu.lvl.CORE=CORE +cw01.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +cw01.menu.lvl.WIFI=WIFI +cw01.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +cw01.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +cw01.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +cw01.menu.lvl.UPDATER=UPDATER +cw01.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +cw01.menu.lvl.OTA=OTA +cw01.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +cw01.menu.lvl.OOM=OOM +cw01.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +cw01.menu.lvl.MDNS=MDNS +cw01.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +cw01.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +cw01.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +cw01.menu.wipe.none=Only Sketch +cw01.menu.wipe.none.upload.erase_cmd= +cw01.menu.wipe.sdk=Sketch + WiFi Settings +cw01.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +cw01.menu.wipe.all=All Flash Contents +cw01.menu.wipe.all.upload.erase_cmd=erase_flash +cw01.menu.baud.115200=115200 +cw01.menu.baud.115200.upload.speed=115200 +cw01.menu.baud.57600=57600 +cw01.menu.baud.57600.upload.speed=57600 +cw01.menu.baud.230400.linux=230400 +cw01.menu.baud.230400.macosx=230400 +cw01.menu.baud.230400.upload.speed=230400 +cw01.menu.baud.256000.windows=256000 +cw01.menu.baud.256000.upload.speed=256000 +cw01.menu.baud.460800.linux=460800 +cw01.menu.baud.460800.macosx=460800 +cw01.menu.baud.460800.upload.speed=460800 +cw01.menu.baud.512000.windows=512000 +cw01.menu.baud.512000.upload.speed=512000 +cw01.menu.baud.921600=921600 +cw01.menu.baud.921600.upload.speed=921600 +cw01.menu.baud.3000000=3000000 +cw01.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espresso_lite_v1.name=ESPresso Lite 1.0 +espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 +espresso_lite_v1.build.variant=espresso_lite_v1 +espresso_lite_v1.upload.tool=esptool +espresso_lite_v1.upload.maximum_data_size=81920 +espresso_lite_v1.upload.wait_for_upload_port=true +espresso_lite_v1.upload.erase_cmd= +espresso_lite_v1.serial.disableDTR=true +espresso_lite_v1.serial.disableRTS=true +espresso_lite_v1.build.mcu=esp8266 +espresso_lite_v1.build.core=esp8266 +espresso_lite_v1.build.spiffs_pagesize=256 +espresso_lite_v1.build.debug_port= +espresso_lite_v1.build.debug_level= +espresso_lite_v1.menu.xtal.80=80 MHz +espresso_lite_v1.menu.xtal.80.build.f_cpu=80000000L +espresso_lite_v1.menu.xtal.160=160 MHz +espresso_lite_v1.menu.xtal.160.build.f_cpu=160000000L +espresso_lite_v1.menu.vt.flash=Flash +espresso_lite_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espresso_lite_v1.menu.vt.heap=Heap +espresso_lite_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espresso_lite_v1.menu.vt.iram=IRAM +espresso_lite_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espresso_lite_v1.menu.exception.legacy=Legacy (new can return nullptr) +espresso_lite_v1.menu.exception.legacy.build.exception_flags=-fno-exceptions +espresso_lite_v1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espresso_lite_v1.menu.exception.disabled=Disabled (new can abort) +espresso_lite_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espresso_lite_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espresso_lite_v1.menu.exception.enabled=Enabled +espresso_lite_v1.menu.exception.enabled.build.exception_flags=-fexceptions +espresso_lite_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espresso_lite_v1.menu.ssl.all=All SSL ciphers (most compatible) +espresso_lite_v1.menu.ssl.all.build.sslflags= +espresso_lite_v1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espresso_lite_v1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espresso_lite_v1.build.flash_mode=dio +espresso_lite_v1.build.flash_flags=-DFLASHMODE_DIO +espresso_lite_v1.build.flash_freq=40 +espresso_lite_v1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espresso_lite_v1.menu.eesz.4M2M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M2M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espresso_lite_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espresso_lite_v1.menu.eesz.4M3M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M3M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espresso_lite_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espresso_lite_v1.menu.eesz.4M1M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M1M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espresso_lite_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espresso_lite_v1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espresso_lite_v1.menu.eesz.4M.build.flash_size=4M +espresso_lite_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 +espresso_lite_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espresso_lite_v1.menu.eesz.4M.build.spiffs_pagesize=256 +espresso_lite_v1.menu.eesz.4M.upload.maximum_size=1044464 +espresso_lite_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espresso_lite_v1.menu.ResetMethod.nodemcu=dtr (aka nodemcu) +espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset +espresso_lite_v1.menu.ResetMethod.ck=no dtr (aka ck) +espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset +espresso_lite_v1.menu.ip.lm2f=v2 Lower Memory +espresso_lite_v1.menu.ip.lm2f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espresso_lite_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.hb2f=v2 Higher Bandwidth +espresso_lite_v1.menu.ip.hb2f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espresso_lite_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.lm2n=v2 Lower Memory (no features) +espresso_lite_v1.menu.ip.lm2n.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espresso_lite_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espresso_lite_v1.menu.ip.hb2n.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espresso_lite_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v1.menu.ip.lm6f=v2 IPv6 Lower Memory +espresso_lite_v1.menu.ip.lm6f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espresso_lite_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espresso_lite_v1.menu.ip.hb6f.build.lwip_include=lwip2/include +espresso_lite_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espresso_lite_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v1.menu.ip.hb1=v1.4 Higher Bandwidth +espresso_lite_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espresso_lite_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v1.menu.ip.src=v1.4 Compile from source +espresso_lite_v1.menu.ip.src.build.lwip_lib=-llwip_src +espresso_lite_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espresso_lite_v1.menu.dbg.Disabled=Disabled +espresso_lite_v1.menu.dbg.Disabled.build.debug_port= +espresso_lite_v1.menu.dbg.Serial=Serial +espresso_lite_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espresso_lite_v1.menu.dbg.Serial1=Serial1 +espresso_lite_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espresso_lite_v1.menu.lvl.None____=None +espresso_lite_v1.menu.lvl.None____.build.debug_level= +espresso_lite_v1.menu.lvl.SSL=SSL +espresso_lite_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espresso_lite_v1.menu.lvl.TLS_MEM=TLS_MEM +espresso_lite_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espresso_lite_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espresso_lite_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espresso_lite_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v1.menu.lvl.CORE=CORE +espresso_lite_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espresso_lite_v1.menu.lvl.WIFI=WIFI +espresso_lite_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espresso_lite_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espresso_lite_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espresso_lite_v1.menu.lvl.UPDATER=UPDATER +espresso_lite_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espresso_lite_v1.menu.lvl.OTA=OTA +espresso_lite_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espresso_lite_v1.menu.lvl.OOM=OOM +espresso_lite_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espresso_lite_v1.menu.lvl.MDNS=MDNS +espresso_lite_v1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espresso_lite_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espresso_lite_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espresso_lite_v1.menu.wipe.none=Only Sketch +espresso_lite_v1.menu.wipe.none.upload.erase_cmd= +espresso_lite_v1.menu.wipe.sdk=Sketch + WiFi Settings +espresso_lite_v1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espresso_lite_v1.menu.wipe.all=All Flash Contents +espresso_lite_v1.menu.wipe.all.upload.erase_cmd=erase_flash +espresso_lite_v1.menu.baud.115200=115200 +espresso_lite_v1.menu.baud.115200.upload.speed=115200 +espresso_lite_v1.menu.baud.57600=57600 +espresso_lite_v1.menu.baud.57600.upload.speed=57600 +espresso_lite_v1.menu.baud.230400.linux=230400 +espresso_lite_v1.menu.baud.230400.macosx=230400 +espresso_lite_v1.menu.baud.230400.upload.speed=230400 +espresso_lite_v1.menu.baud.256000.windows=256000 +espresso_lite_v1.menu.baud.256000.upload.speed=256000 +espresso_lite_v1.menu.baud.460800.linux=460800 +espresso_lite_v1.menu.baud.460800.macosx=460800 +espresso_lite_v1.menu.baud.460800.upload.speed=460800 +espresso_lite_v1.menu.baud.512000.windows=512000 +espresso_lite_v1.menu.baud.512000.upload.speed=512000 +espresso_lite_v1.menu.baud.921600=921600 +espresso_lite_v1.menu.baud.921600.upload.speed=921600 +espresso_lite_v1.menu.baud.3000000=3000000 +espresso_lite_v1.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espresso_lite_v2.name=ESPresso Lite 2.0 +espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 +espresso_lite_v2.build.variant=espresso_lite_v2 +espresso_lite_v2.upload.tool=esptool +espresso_lite_v2.upload.maximum_data_size=81920 +espresso_lite_v2.upload.wait_for_upload_port=true +espresso_lite_v2.upload.erase_cmd= +espresso_lite_v2.serial.disableDTR=true +espresso_lite_v2.serial.disableRTS=true +espresso_lite_v2.build.mcu=esp8266 +espresso_lite_v2.build.core=esp8266 +espresso_lite_v2.build.spiffs_pagesize=256 +espresso_lite_v2.build.debug_port= +espresso_lite_v2.build.debug_level= +espresso_lite_v2.menu.xtal.80=80 MHz +espresso_lite_v2.menu.xtal.80.build.f_cpu=80000000L +espresso_lite_v2.menu.xtal.160=160 MHz +espresso_lite_v2.menu.xtal.160.build.f_cpu=160000000L +espresso_lite_v2.menu.vt.flash=Flash +espresso_lite_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espresso_lite_v2.menu.vt.heap=Heap +espresso_lite_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espresso_lite_v2.menu.vt.iram=IRAM +espresso_lite_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espresso_lite_v2.menu.exception.legacy=Legacy (new can return nullptr) +espresso_lite_v2.menu.exception.legacy.build.exception_flags=-fno-exceptions +espresso_lite_v2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espresso_lite_v2.menu.exception.disabled=Disabled (new can abort) +espresso_lite_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espresso_lite_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espresso_lite_v2.menu.exception.enabled=Enabled +espresso_lite_v2.menu.exception.enabled.build.exception_flags=-fexceptions +espresso_lite_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espresso_lite_v2.menu.ssl.all=All SSL ciphers (most compatible) +espresso_lite_v2.menu.ssl.all.build.sslflags= +espresso_lite_v2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espresso_lite_v2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espresso_lite_v2.build.flash_mode=dio +espresso_lite_v2.build.flash_flags=-DFLASHMODE_DIO +espresso_lite_v2.build.flash_freq=40 +espresso_lite_v2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espresso_lite_v2.menu.eesz.4M2M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M2M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espresso_lite_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espresso_lite_v2.menu.eesz.4M3M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M3M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espresso_lite_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espresso_lite_v2.menu.eesz.4M1M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M1M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espresso_lite_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espresso_lite_v2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espresso_lite_v2.menu.eesz.4M.build.flash_size=4M +espresso_lite_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 +espresso_lite_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espresso_lite_v2.menu.eesz.4M.build.spiffs_pagesize=256 +espresso_lite_v2.menu.eesz.4M.upload.maximum_size=1044464 +espresso_lite_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espresso_lite_v2.menu.ResetMethod.nodemcu=dtr (aka nodemcu) +espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset +espresso_lite_v2.menu.ResetMethod.ck=no dtr (aka ck) +espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset +espresso_lite_v2.menu.ip.lm2f=v2 Lower Memory +espresso_lite_v2.menu.ip.lm2f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espresso_lite_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.hb2f=v2 Higher Bandwidth +espresso_lite_v2.menu.ip.hb2f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espresso_lite_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.lm2n=v2 Lower Memory (no features) +espresso_lite_v2.menu.ip.lm2n.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espresso_lite_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espresso_lite_v2.menu.ip.hb2n.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espresso_lite_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espresso_lite_v2.menu.ip.lm6f=v2 IPv6 Lower Memory +espresso_lite_v2.menu.ip.lm6f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espresso_lite_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espresso_lite_v2.menu.ip.hb6f.build.lwip_include=lwip2/include +espresso_lite_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espresso_lite_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espresso_lite_v2.menu.ip.hb1=v1.4 Higher Bandwidth +espresso_lite_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espresso_lite_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v2.menu.ip.src=v1.4 Compile from source +espresso_lite_v2.menu.ip.src.build.lwip_lib=-llwip_src +espresso_lite_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espresso_lite_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espresso_lite_v2.menu.dbg.Disabled=Disabled +espresso_lite_v2.menu.dbg.Disabled.build.debug_port= +espresso_lite_v2.menu.dbg.Serial=Serial +espresso_lite_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espresso_lite_v2.menu.dbg.Serial1=Serial1 +espresso_lite_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espresso_lite_v2.menu.lvl.None____=None +espresso_lite_v2.menu.lvl.None____.build.debug_level= +espresso_lite_v2.menu.lvl.SSL=SSL +espresso_lite_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espresso_lite_v2.menu.lvl.TLS_MEM=TLS_MEM +espresso_lite_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espresso_lite_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espresso_lite_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espresso_lite_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espresso_lite_v2.menu.lvl.CORE=CORE +espresso_lite_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espresso_lite_v2.menu.lvl.WIFI=WIFI +espresso_lite_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espresso_lite_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espresso_lite_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espresso_lite_v2.menu.lvl.UPDATER=UPDATER +espresso_lite_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espresso_lite_v2.menu.lvl.OTA=OTA +espresso_lite_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espresso_lite_v2.menu.lvl.OOM=OOM +espresso_lite_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espresso_lite_v2.menu.lvl.MDNS=MDNS +espresso_lite_v2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espresso_lite_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espresso_lite_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espresso_lite_v2.menu.wipe.none=Only Sketch +espresso_lite_v2.menu.wipe.none.upload.erase_cmd= +espresso_lite_v2.menu.wipe.sdk=Sketch + WiFi Settings +espresso_lite_v2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espresso_lite_v2.menu.wipe.all=All Flash Contents +espresso_lite_v2.menu.wipe.all.upload.erase_cmd=erase_flash +espresso_lite_v2.menu.baud.115200=115200 +espresso_lite_v2.menu.baud.115200.upload.speed=115200 +espresso_lite_v2.menu.baud.57600=57600 +espresso_lite_v2.menu.baud.57600.upload.speed=57600 +espresso_lite_v2.menu.baud.230400.linux=230400 +espresso_lite_v2.menu.baud.230400.macosx=230400 +espresso_lite_v2.menu.baud.230400.upload.speed=230400 +espresso_lite_v2.menu.baud.256000.windows=256000 +espresso_lite_v2.menu.baud.256000.upload.speed=256000 +espresso_lite_v2.menu.baud.460800.linux=460800 +espresso_lite_v2.menu.baud.460800.macosx=460800 +espresso_lite_v2.menu.baud.460800.upload.speed=460800 +espresso_lite_v2.menu.baud.512000.windows=512000 +espresso_lite_v2.menu.baud.512000.upload.speed=512000 +espresso_lite_v2.menu.baud.921600=921600 +espresso_lite_v2.menu.baud.921600.upload.speed=921600 +espresso_lite_v2.menu.baud.3000000=3000000 +espresso_lite_v2.menu.baud.3000000.upload.speed=3000000 + +############################################################## +phoenix_v1.name=Phoenix 1.0 +phoenix_v1.build.board=ESP8266_PHOENIX_V1 +phoenix_v1.build.variant=phoenix_v1 +phoenix_v1.upload.tool=esptool +phoenix_v1.upload.maximum_data_size=81920 +phoenix_v1.upload.wait_for_upload_port=true +phoenix_v1.upload.erase_cmd= +phoenix_v1.serial.disableDTR=true +phoenix_v1.serial.disableRTS=true +phoenix_v1.build.mcu=esp8266 +phoenix_v1.build.core=esp8266 +phoenix_v1.build.spiffs_pagesize=256 +phoenix_v1.build.debug_port= +phoenix_v1.build.debug_level= +phoenix_v1.menu.xtal.80=80 MHz +phoenix_v1.menu.xtal.80.build.f_cpu=80000000L +phoenix_v1.menu.xtal.160=160 MHz +phoenix_v1.menu.xtal.160.build.f_cpu=160000000L +phoenix_v1.menu.vt.flash=Flash +phoenix_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +phoenix_v1.menu.vt.heap=Heap +phoenix_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +phoenix_v1.menu.vt.iram=IRAM +phoenix_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +phoenix_v1.menu.exception.legacy=Legacy (new can return nullptr) +phoenix_v1.menu.exception.legacy.build.exception_flags=-fno-exceptions +phoenix_v1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +phoenix_v1.menu.exception.disabled=Disabled (new can abort) +phoenix_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +phoenix_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +phoenix_v1.menu.exception.enabled=Enabled +phoenix_v1.menu.exception.enabled.build.exception_flags=-fexceptions +phoenix_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +phoenix_v1.menu.ssl.all=All SSL ciphers (most compatible) +phoenix_v1.menu.ssl.all.build.sslflags= +phoenix_v1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +phoenix_v1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +phoenix_v1.build.flash_mode=dio +phoenix_v1.build.flash_flags=-DFLASHMODE_DIO +phoenix_v1.build.flash_freq=40 +phoenix_v1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +phoenix_v1.menu.eesz.4M2M.build.flash_size=4M +phoenix_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +phoenix_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M2M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +phoenix_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +phoenix_v1.menu.eesz.4M3M.build.flash_size=4M +phoenix_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +phoenix_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M3M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +phoenix_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +phoenix_v1.menu.eesz.4M1M.build.flash_size=4M +phoenix_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +phoenix_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M1M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +phoenix_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +phoenix_v1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +phoenix_v1.menu.eesz.4M.build.flash_size=4M +phoenix_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 +phoenix_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +phoenix_v1.menu.eesz.4M.build.spiffs_pagesize=256 +phoenix_v1.menu.eesz.4M.upload.maximum_size=1044464 +phoenix_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +phoenix_v1.menu.ResetMethod.nodemcu=dtr (aka nodemcu) +phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset +phoenix_v1.menu.ResetMethod.ck=no dtr (aka ck) +phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset +phoenix_v1.menu.ip.lm2f=v2 Lower Memory +phoenix_v1.menu.ip.lm2f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +phoenix_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.hb2f=v2 Higher Bandwidth +phoenix_v1.menu.ip.hb2f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +phoenix_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.lm2n=v2 Lower Memory (no features) +phoenix_v1.menu.ip.lm2n.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +phoenix_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +phoenix_v1.menu.ip.hb2n.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +phoenix_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v1.menu.ip.lm6f=v2 IPv6 Lower Memory +phoenix_v1.menu.ip.lm6f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +phoenix_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +phoenix_v1.menu.ip.hb6f.build.lwip_include=lwip2/include +phoenix_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +phoenix_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v1.menu.ip.hb1=v1.4 Higher Bandwidth +phoenix_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +phoenix_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v1.menu.ip.src=v1.4 Compile from source +phoenix_v1.menu.ip.src.build.lwip_lib=-llwip_src +phoenix_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +phoenix_v1.menu.dbg.Disabled=Disabled +phoenix_v1.menu.dbg.Disabled.build.debug_port= +phoenix_v1.menu.dbg.Serial=Serial +phoenix_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +phoenix_v1.menu.dbg.Serial1=Serial1 +phoenix_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +phoenix_v1.menu.lvl.None____=None +phoenix_v1.menu.lvl.None____.build.debug_level= +phoenix_v1.menu.lvl.SSL=SSL +phoenix_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +phoenix_v1.menu.lvl.TLS_MEM=TLS_MEM +phoenix_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +phoenix_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +phoenix_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +phoenix_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +phoenix_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +phoenix_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v1.menu.lvl.CORE=CORE +phoenix_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +phoenix_v1.menu.lvl.WIFI=WIFI +phoenix_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +phoenix_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +phoenix_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +phoenix_v1.menu.lvl.UPDATER=UPDATER +phoenix_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +phoenix_v1.menu.lvl.OTA=OTA +phoenix_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +phoenix_v1.menu.lvl.OOM=OOM +phoenix_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +phoenix_v1.menu.lvl.MDNS=MDNS +phoenix_v1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +phoenix_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +phoenix_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +phoenix_v1.menu.wipe.none=Only Sketch +phoenix_v1.menu.wipe.none.upload.erase_cmd= +phoenix_v1.menu.wipe.sdk=Sketch + WiFi Settings +phoenix_v1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +phoenix_v1.menu.wipe.all=All Flash Contents +phoenix_v1.menu.wipe.all.upload.erase_cmd=erase_flash +phoenix_v1.menu.baud.115200=115200 +phoenix_v1.menu.baud.115200.upload.speed=115200 +phoenix_v1.menu.baud.57600=57600 +phoenix_v1.menu.baud.57600.upload.speed=57600 +phoenix_v1.menu.baud.230400.linux=230400 +phoenix_v1.menu.baud.230400.macosx=230400 +phoenix_v1.menu.baud.230400.upload.speed=230400 +phoenix_v1.menu.baud.256000.windows=256000 +phoenix_v1.menu.baud.256000.upload.speed=256000 +phoenix_v1.menu.baud.460800.linux=460800 +phoenix_v1.menu.baud.460800.macosx=460800 +phoenix_v1.menu.baud.460800.upload.speed=460800 +phoenix_v1.menu.baud.512000.windows=512000 +phoenix_v1.menu.baud.512000.upload.speed=512000 +phoenix_v1.menu.baud.921600=921600 +phoenix_v1.menu.baud.921600.upload.speed=921600 +phoenix_v1.menu.baud.3000000=3000000 +phoenix_v1.menu.baud.3000000.upload.speed=3000000 + +############################################################## +phoenix_v2.name=Phoenix 2.0 +phoenix_v2.build.board=ESP8266_PHOENIX_V2 +phoenix_v2.build.variant=phoenix_v2 +phoenix_v2.upload.tool=esptool +phoenix_v2.upload.maximum_data_size=81920 +phoenix_v2.upload.wait_for_upload_port=true +phoenix_v2.upload.erase_cmd= +phoenix_v2.serial.disableDTR=true +phoenix_v2.serial.disableRTS=true +phoenix_v2.build.mcu=esp8266 +phoenix_v2.build.core=esp8266 +phoenix_v2.build.spiffs_pagesize=256 +phoenix_v2.build.debug_port= +phoenix_v2.build.debug_level= +phoenix_v2.menu.xtal.80=80 MHz +phoenix_v2.menu.xtal.80.build.f_cpu=80000000L +phoenix_v2.menu.xtal.160=160 MHz +phoenix_v2.menu.xtal.160.build.f_cpu=160000000L +phoenix_v2.menu.vt.flash=Flash +phoenix_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +phoenix_v2.menu.vt.heap=Heap +phoenix_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +phoenix_v2.menu.vt.iram=IRAM +phoenix_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +phoenix_v2.menu.exception.legacy=Legacy (new can return nullptr) +phoenix_v2.menu.exception.legacy.build.exception_flags=-fno-exceptions +phoenix_v2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +phoenix_v2.menu.exception.disabled=Disabled (new can abort) +phoenix_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +phoenix_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +phoenix_v2.menu.exception.enabled=Enabled +phoenix_v2.menu.exception.enabled.build.exception_flags=-fexceptions +phoenix_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +phoenix_v2.menu.ssl.all=All SSL ciphers (most compatible) +phoenix_v2.menu.ssl.all.build.sslflags= +phoenix_v2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +phoenix_v2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +phoenix_v2.build.flash_mode=dio +phoenix_v2.build.flash_flags=-DFLASHMODE_DIO +phoenix_v2.build.flash_freq=40 +phoenix_v2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +phoenix_v2.menu.eesz.4M2M.build.flash_size=4M +phoenix_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +phoenix_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M2M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +phoenix_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +phoenix_v2.menu.eesz.4M3M.build.flash_size=4M +phoenix_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +phoenix_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M3M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +phoenix_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +phoenix_v2.menu.eesz.4M1M.build.flash_size=4M +phoenix_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +phoenix_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M1M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +phoenix_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +phoenix_v2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +phoenix_v2.menu.eesz.4M.build.flash_size=4M +phoenix_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 +phoenix_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +phoenix_v2.menu.eesz.4M.build.spiffs_pagesize=256 +phoenix_v2.menu.eesz.4M.upload.maximum_size=1044464 +phoenix_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +phoenix_v2.menu.ResetMethod.nodemcu=dtr (aka nodemcu) +phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset +phoenix_v2.menu.ResetMethod.ck=no dtr (aka ck) +phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset +phoenix_v2.menu.ip.lm2f=v2 Lower Memory +phoenix_v2.menu.ip.lm2f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +phoenix_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.hb2f=v2 Higher Bandwidth +phoenix_v2.menu.ip.hb2f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +phoenix_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.lm2n=v2 Lower Memory (no features) +phoenix_v2.menu.ip.lm2n.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +phoenix_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +phoenix_v2.menu.ip.hb2n.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +phoenix_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +phoenix_v2.menu.ip.lm6f=v2 IPv6 Lower Memory +phoenix_v2.menu.ip.lm6f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +phoenix_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +phoenix_v2.menu.ip.hb6f.build.lwip_include=lwip2/include +phoenix_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +phoenix_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +phoenix_v2.menu.ip.hb1=v1.4 Higher Bandwidth +phoenix_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +phoenix_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v2.menu.ip.src=v1.4 Compile from source +phoenix_v2.menu.ip.src.build.lwip_lib=-llwip_src +phoenix_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +phoenix_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +phoenix_v2.menu.dbg.Disabled=Disabled +phoenix_v2.menu.dbg.Disabled.build.debug_port= +phoenix_v2.menu.dbg.Serial=Serial +phoenix_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +phoenix_v2.menu.dbg.Serial1=Serial1 +phoenix_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +phoenix_v2.menu.lvl.None____=None +phoenix_v2.menu.lvl.None____.build.debug_level= +phoenix_v2.menu.lvl.SSL=SSL +phoenix_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +phoenix_v2.menu.lvl.TLS_MEM=TLS_MEM +phoenix_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +phoenix_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +phoenix_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +phoenix_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +phoenix_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +phoenix_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +phoenix_v2.menu.lvl.CORE=CORE +phoenix_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +phoenix_v2.menu.lvl.WIFI=WIFI +phoenix_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +phoenix_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +phoenix_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +phoenix_v2.menu.lvl.UPDATER=UPDATER +phoenix_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +phoenix_v2.menu.lvl.OTA=OTA +phoenix_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +phoenix_v2.menu.lvl.OOM=OOM +phoenix_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +phoenix_v2.menu.lvl.MDNS=MDNS +phoenix_v2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +phoenix_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +phoenix_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +phoenix_v2.menu.wipe.none=Only Sketch +phoenix_v2.menu.wipe.none.upload.erase_cmd= +phoenix_v2.menu.wipe.sdk=Sketch + WiFi Settings +phoenix_v2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +phoenix_v2.menu.wipe.all=All Flash Contents +phoenix_v2.menu.wipe.all.upload.erase_cmd=erase_flash +phoenix_v2.menu.baud.115200=115200 +phoenix_v2.menu.baud.115200.upload.speed=115200 +phoenix_v2.menu.baud.57600=57600 +phoenix_v2.menu.baud.57600.upload.speed=57600 +phoenix_v2.menu.baud.230400.linux=230400 +phoenix_v2.menu.baud.230400.macosx=230400 +phoenix_v2.menu.baud.230400.upload.speed=230400 +phoenix_v2.menu.baud.256000.windows=256000 +phoenix_v2.menu.baud.256000.upload.speed=256000 +phoenix_v2.menu.baud.460800.linux=460800 +phoenix_v2.menu.baud.460800.macosx=460800 +phoenix_v2.menu.baud.460800.upload.speed=460800 +phoenix_v2.menu.baud.512000.windows=512000 +phoenix_v2.menu.baud.512000.upload.speed=512000 +phoenix_v2.menu.baud.921600=921600 +phoenix_v2.menu.baud.921600.upload.speed=921600 +phoenix_v2.menu.baud.3000000=3000000 +phoenix_v2.menu.baud.3000000.upload.speed=3000000 + +############################################################## +nodemcu.name=NodeMCU 0.9 (ESP-12 Module) +nodemcu.build.board=ESP8266_NODEMCU +nodemcu.build.variant=nodemcu +nodemcu.upload.tool=esptool +nodemcu.upload.maximum_data_size=81920 +nodemcu.upload.wait_for_upload_port=true +nodemcu.upload.erase_cmd= +nodemcu.serial.disableDTR=true +nodemcu.serial.disableRTS=true +nodemcu.build.mcu=esp8266 +nodemcu.build.core=esp8266 +nodemcu.build.spiffs_pagesize=256 +nodemcu.build.debug_port= +nodemcu.build.debug_level= +nodemcu.menu.xtal.80=80 MHz +nodemcu.menu.xtal.80.build.f_cpu=80000000L +nodemcu.menu.xtal.160=160 MHz +nodemcu.menu.xtal.160.build.f_cpu=160000000L +nodemcu.menu.vt.flash=Flash +nodemcu.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +nodemcu.menu.vt.heap=Heap +nodemcu.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +nodemcu.menu.vt.iram=IRAM +nodemcu.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +nodemcu.menu.exception.legacy=Legacy (new can return nullptr) +nodemcu.menu.exception.legacy.build.exception_flags=-fno-exceptions +nodemcu.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +nodemcu.menu.exception.disabled=Disabled (new can abort) +nodemcu.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +nodemcu.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +nodemcu.menu.exception.enabled=Enabled +nodemcu.menu.exception.enabled.build.exception_flags=-fexceptions +nodemcu.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +nodemcu.menu.ssl.all=All SSL ciphers (most compatible) +nodemcu.menu.ssl.all.build.sslflags= +nodemcu.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +nodemcu.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +nodemcu.upload.resetmethod=--before default_reset --after hard_reset +nodemcu.build.flash_mode=qio +nodemcu.build.flash_flags=-DFLASHMODE_QIO +nodemcu.build.flash_freq=40 +nodemcu.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +nodemcu.menu.eesz.4M2M.build.flash_size=4M +nodemcu.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +nodemcu.menu.eesz.4M2M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M2M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M2M.build.spiffs_start=0x200000 +nodemcu.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +nodemcu.menu.eesz.4M2M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +nodemcu.menu.eesz.4M3M.build.flash_size=4M +nodemcu.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +nodemcu.menu.eesz.4M3M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M3M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M3M.build.spiffs_start=0x100000 +nodemcu.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +nodemcu.menu.eesz.4M3M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +nodemcu.menu.eesz.4M1M.build.flash_size=4M +nodemcu.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +nodemcu.menu.eesz.4M1M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M1M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +nodemcu.menu.eesz.4M1M.build.spiffs_start=0x300000 +nodemcu.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +nodemcu.menu.eesz.4M1M.build.spiffs_blocksize=8192 +nodemcu.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +nodemcu.menu.eesz.4M.build.flash_size=4M +nodemcu.menu.eesz.4M.build.flash_size_bytes=0x400000 +nodemcu.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +nodemcu.menu.eesz.4M.build.spiffs_pagesize=256 +nodemcu.menu.eesz.4M.upload.maximum_size=1044464 +nodemcu.menu.eesz.4M.build.rfcal_addr=0x3FC000 +nodemcu.menu.ip.lm2f=v2 Lower Memory +nodemcu.menu.ip.lm2f.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +nodemcu.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcu.menu.ip.hb2f=v2 Higher Bandwidth +nodemcu.menu.ip.hb2f.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +nodemcu.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcu.menu.ip.lm2n=v2 Lower Memory (no features) +nodemcu.menu.ip.lm2n.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +nodemcu.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcu.menu.ip.hb2n=v2 Higher Bandwidth (no features) +nodemcu.menu.ip.hb2n.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +nodemcu.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcu.menu.ip.lm6f=v2 IPv6 Lower Memory +nodemcu.menu.ip.lm6f.build.lwip_include=lwip2/include +nodemcu.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +nodemcu.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcu.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +nodemcu.menu.ip.hb6f.build.lwip_include=lwip2/include +nodemcu.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +nodemcu.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcu.menu.ip.hb1=v1.4 Higher Bandwidth +nodemcu.menu.ip.hb1.build.lwip_lib=-llwip_gcc +nodemcu.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcu.menu.ip.src=v1.4 Compile from source +nodemcu.menu.ip.src.build.lwip_lib=-llwip_src +nodemcu.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcu.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +nodemcu.menu.dbg.Disabled=Disabled +nodemcu.menu.dbg.Disabled.build.debug_port= +nodemcu.menu.dbg.Serial=Serial +nodemcu.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +nodemcu.menu.dbg.Serial1=Serial1 +nodemcu.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +nodemcu.menu.lvl.None____=None +nodemcu.menu.lvl.None____.build.debug_level= +nodemcu.menu.lvl.SSL=SSL +nodemcu.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +nodemcu.menu.lvl.TLS_MEM=TLS_MEM +nodemcu.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +nodemcu.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +nodemcu.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.HTTP_SERVER=HTTP_SERVER +nodemcu.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +nodemcu.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +nodemcu.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +nodemcu.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcu.menu.lvl.CORE=CORE +nodemcu.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +nodemcu.menu.lvl.WIFI=WIFI +nodemcu.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +nodemcu.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +nodemcu.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +nodemcu.menu.lvl.UPDATER=UPDATER +nodemcu.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +nodemcu.menu.lvl.OTA=OTA +nodemcu.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +nodemcu.menu.lvl.OOM=OOM +nodemcu.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +nodemcu.menu.lvl.MDNS=MDNS +nodemcu.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +nodemcu.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +nodemcu.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +nodemcu.menu.wipe.none=Only Sketch +nodemcu.menu.wipe.none.upload.erase_cmd= +nodemcu.menu.wipe.sdk=Sketch + WiFi Settings +nodemcu.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +nodemcu.menu.wipe.all=All Flash Contents +nodemcu.menu.wipe.all.upload.erase_cmd=erase_flash +nodemcu.menu.baud.115200=115200 +nodemcu.menu.baud.115200.upload.speed=115200 +nodemcu.menu.baud.57600=57600 +nodemcu.menu.baud.57600.upload.speed=57600 +nodemcu.menu.baud.230400.linux=230400 +nodemcu.menu.baud.230400.macosx=230400 +nodemcu.menu.baud.230400.upload.speed=230400 +nodemcu.menu.baud.256000.windows=256000 +nodemcu.menu.baud.256000.upload.speed=256000 +nodemcu.menu.baud.460800.linux=460800 +nodemcu.menu.baud.460800.macosx=460800 +nodemcu.menu.baud.460800.upload.speed=460800 +nodemcu.menu.baud.512000.windows=512000 +nodemcu.menu.baud.512000.upload.speed=512000 +nodemcu.menu.baud.921600=921600 +nodemcu.menu.baud.921600.upload.speed=921600 +nodemcu.menu.baud.3000000=3000000 +nodemcu.menu.baud.3000000.upload.speed=3000000 + +############################################################## +nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) +nodemcuv2.build.board=ESP8266_NODEMCU +nodemcuv2.build.variant=nodemcu +nodemcuv2.upload.tool=esptool +nodemcuv2.upload.maximum_data_size=81920 +nodemcuv2.upload.wait_for_upload_port=true +nodemcuv2.upload.erase_cmd= +nodemcuv2.serial.disableDTR=true +nodemcuv2.serial.disableRTS=true +nodemcuv2.build.mcu=esp8266 +nodemcuv2.build.core=esp8266 +nodemcuv2.build.spiffs_pagesize=256 +nodemcuv2.build.debug_port= +nodemcuv2.build.debug_level= +nodemcuv2.menu.xtal.80=80 MHz +nodemcuv2.menu.xtal.80.build.f_cpu=80000000L +nodemcuv2.menu.xtal.160=160 MHz +nodemcuv2.menu.xtal.160.build.f_cpu=160000000L +nodemcuv2.menu.vt.flash=Flash +nodemcuv2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +nodemcuv2.menu.vt.heap=Heap +nodemcuv2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +nodemcuv2.menu.vt.iram=IRAM +nodemcuv2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +nodemcuv2.menu.exception.legacy=Legacy (new can return nullptr) +nodemcuv2.menu.exception.legacy.build.exception_flags=-fno-exceptions +nodemcuv2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +nodemcuv2.menu.exception.disabled=Disabled (new can abort) +nodemcuv2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +nodemcuv2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +nodemcuv2.menu.exception.enabled=Enabled +nodemcuv2.menu.exception.enabled.build.exception_flags=-fexceptions +nodemcuv2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +nodemcuv2.menu.ssl.all=All SSL ciphers (most compatible) +nodemcuv2.menu.ssl.all.build.sslflags= +nodemcuv2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +nodemcuv2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +nodemcuv2.upload.resetmethod=--before default_reset --after hard_reset +nodemcuv2.build.flash_mode=dio +nodemcuv2.build.flash_flags=-DFLASHMODE_DIO +nodemcuv2.build.flash_freq=40 +nodemcuv2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +nodemcuv2.menu.eesz.4M2M.build.flash_size=4M +nodemcuv2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +nodemcuv2.menu.eesz.4M2M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M2M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_start=0x200000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +nodemcuv2.menu.eesz.4M2M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +nodemcuv2.menu.eesz.4M3M.build.flash_size=4M +nodemcuv2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +nodemcuv2.menu.eesz.4M3M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M3M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_start=0x100000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +nodemcuv2.menu.eesz.4M3M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +nodemcuv2.menu.eesz.4M1M.build.flash_size=4M +nodemcuv2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +nodemcuv2.menu.eesz.4M1M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M1M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_start=0x300000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +nodemcuv2.menu.eesz.4M1M.build.spiffs_blocksize=8192 +nodemcuv2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +nodemcuv2.menu.eesz.4M.build.flash_size=4M +nodemcuv2.menu.eesz.4M.build.flash_size_bytes=0x400000 +nodemcuv2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +nodemcuv2.menu.eesz.4M.build.spiffs_pagesize=256 +nodemcuv2.menu.eesz.4M.upload.maximum_size=1044464 +nodemcuv2.menu.eesz.4M.build.rfcal_addr=0x3FC000 +nodemcuv2.menu.led.2=2 +nodemcuv2.menu.led.2.build.led=-DLED_BUILTIN=2 +nodemcuv2.menu.led.16=16 +nodemcuv2.menu.led.16.build.led=-DLED_BUILTIN=16 +nodemcuv2.menu.ip.lm2f=v2 Lower Memory +nodemcuv2.menu.ip.lm2f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +nodemcuv2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.hb2f=v2 Higher Bandwidth +nodemcuv2.menu.ip.hb2f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +nodemcuv2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.lm2n=v2 Lower Memory (no features) +nodemcuv2.menu.ip.lm2n.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +nodemcuv2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.hb2n=v2 Higher Bandwidth (no features) +nodemcuv2.menu.ip.hb2n.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +nodemcuv2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +nodemcuv2.menu.ip.lm6f=v2 IPv6 Lower Memory +nodemcuv2.menu.ip.lm6f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +nodemcuv2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcuv2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +nodemcuv2.menu.ip.hb6f.build.lwip_include=lwip2/include +nodemcuv2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +nodemcuv2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +nodemcuv2.menu.ip.hb1=v1.4 Higher Bandwidth +nodemcuv2.menu.ip.hb1.build.lwip_lib=-llwip_gcc +nodemcuv2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcuv2.menu.ip.src=v1.4 Compile from source +nodemcuv2.menu.ip.src.build.lwip_lib=-llwip_src +nodemcuv2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +nodemcuv2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +nodemcuv2.menu.dbg.Disabled=Disabled +nodemcuv2.menu.dbg.Disabled.build.debug_port= +nodemcuv2.menu.dbg.Serial=Serial +nodemcuv2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +nodemcuv2.menu.dbg.Serial1=Serial1 +nodemcuv2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +nodemcuv2.menu.lvl.None____=None +nodemcuv2.menu.lvl.None____.build.debug_level= +nodemcuv2.menu.lvl.SSL=SSL +nodemcuv2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +nodemcuv2.menu.lvl.TLS_MEM=TLS_MEM +nodemcuv2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +nodemcuv2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +nodemcuv2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.HTTP_SERVER=HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +nodemcuv2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +nodemcuv2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +nodemcuv2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +nodemcuv2.menu.lvl.CORE=CORE +nodemcuv2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +nodemcuv2.menu.lvl.WIFI=WIFI +nodemcuv2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +nodemcuv2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +nodemcuv2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +nodemcuv2.menu.lvl.UPDATER=UPDATER +nodemcuv2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +nodemcuv2.menu.lvl.OTA=OTA +nodemcuv2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +nodemcuv2.menu.lvl.OOM=OOM +nodemcuv2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +nodemcuv2.menu.lvl.MDNS=MDNS +nodemcuv2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +nodemcuv2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +nodemcuv2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +nodemcuv2.menu.wipe.none=Only Sketch +nodemcuv2.menu.wipe.none.upload.erase_cmd= +nodemcuv2.menu.wipe.sdk=Sketch + WiFi Settings +nodemcuv2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +nodemcuv2.menu.wipe.all=All Flash Contents +nodemcuv2.menu.wipe.all.upload.erase_cmd=erase_flash +nodemcuv2.menu.baud.115200=115200 +nodemcuv2.menu.baud.115200.upload.speed=115200 +nodemcuv2.menu.baud.57600=57600 +nodemcuv2.menu.baud.57600.upload.speed=57600 +nodemcuv2.menu.baud.230400.linux=230400 +nodemcuv2.menu.baud.230400.macosx=230400 +nodemcuv2.menu.baud.230400.upload.speed=230400 +nodemcuv2.menu.baud.256000.windows=256000 +nodemcuv2.menu.baud.256000.upload.speed=256000 +nodemcuv2.menu.baud.460800.linux=460800 +nodemcuv2.menu.baud.460800.macosx=460800 +nodemcuv2.menu.baud.460800.upload.speed=460800 +nodemcuv2.menu.baud.512000.windows=512000 +nodemcuv2.menu.baud.512000.upload.speed=512000 +nodemcuv2.menu.baud.921600=921600 +nodemcuv2.menu.baud.921600.upload.speed=921600 +nodemcuv2.menu.baud.3000000=3000000 +nodemcuv2.menu.baud.3000000.upload.speed=3000000 + +############################################################## +modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) +modwifi.build.board=MOD_WIFI_ESP8266 +modwifi.build.variant=modwifi +modwifi.upload.tool=esptool +modwifi.upload.maximum_data_size=81920 +modwifi.upload.wait_for_upload_port=true +modwifi.upload.erase_cmd= +modwifi.serial.disableDTR=true +modwifi.serial.disableRTS=true +modwifi.build.mcu=esp8266 +modwifi.build.core=esp8266 +modwifi.build.spiffs_pagesize=256 +modwifi.build.debug_port= +modwifi.build.debug_level= +modwifi.menu.xtal.80=80 MHz +modwifi.menu.xtal.80.build.f_cpu=80000000L +modwifi.menu.xtal.160=160 MHz +modwifi.menu.xtal.160.build.f_cpu=160000000L +modwifi.menu.vt.flash=Flash +modwifi.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +modwifi.menu.vt.heap=Heap +modwifi.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +modwifi.menu.vt.iram=IRAM +modwifi.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +modwifi.menu.exception.legacy=Legacy (new can return nullptr) +modwifi.menu.exception.legacy.build.exception_flags=-fno-exceptions +modwifi.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +modwifi.menu.exception.disabled=Disabled (new can abort) +modwifi.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +modwifi.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +modwifi.menu.exception.enabled=Enabled +modwifi.menu.exception.enabled.build.exception_flags=-fexceptions +modwifi.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +modwifi.menu.ssl.all=All SSL ciphers (most compatible) +modwifi.menu.ssl.all.build.sslflags= +modwifi.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +modwifi.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +modwifi.upload.resetmethod=--before no_reset --after soft_reset +modwifi.build.flash_mode=qio +modwifi.build.flash_flags=-DFLASHMODE_QIO +modwifi.build.flash_freq=40 +modwifi.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) +modwifi.menu.eesz.2M64.build.flash_size=2M +modwifi.menu.eesz.2M64.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld +modwifi.menu.eesz.2M64.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M64.upload.maximum_size=1044464 +modwifi.menu.eesz.2M64.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M64.build.spiffs_start=0x1F0000 +modwifi.menu.eesz.2M64.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M64.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) +modwifi.menu.eesz.2M128.build.flash_size=2M +modwifi.menu.eesz.2M128.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +modwifi.menu.eesz.2M128.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M128.upload.maximum_size=1044464 +modwifi.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M128.build.spiffs_start=0x1E0000 +modwifi.menu.eesz.2M128.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M128.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) +modwifi.menu.eesz.2M256.build.flash_size=2M +modwifi.menu.eesz.2M256.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +modwifi.menu.eesz.2M256.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M256.upload.maximum_size=1044464 +modwifi.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M256.build.spiffs_start=0x1C0000 +modwifi.menu.eesz.2M256.build.spiffs_end=0x1FB000 +modwifi.menu.eesz.2M256.build.spiffs_blocksize=4096 +modwifi.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) +modwifi.menu.eesz.2M512.build.flash_size=2M +modwifi.menu.eesz.2M512.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +modwifi.menu.eesz.2M512.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M512.upload.maximum_size=1044464 +modwifi.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M512.build.spiffs_start=0x180000 +modwifi.menu.eesz.2M512.build.spiffs_end=0x1FA000 +modwifi.menu.eesz.2M512.build.spiffs_blocksize=8192 +modwifi.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) +modwifi.menu.eesz.2M1M.build.flash_size=2M +modwifi.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +modwifi.menu.eesz.2M1M.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M1M.upload.maximum_size=1044464 +modwifi.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +modwifi.menu.eesz.2M1M.build.spiffs_start=0x100000 +modwifi.menu.eesz.2M1M.build.spiffs_end=0x1FA000 +modwifi.menu.eesz.2M1M.build.spiffs_blocksize=8192 +modwifi.menu.eesz.2M=2MB (FS:none OTA:~1019KB) +modwifi.menu.eesz.2M.build.flash_size=2M +modwifi.menu.eesz.2M.build.flash_size_bytes=0x200000 +modwifi.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +modwifi.menu.eesz.2M.build.spiffs_pagesize=256 +modwifi.menu.eesz.2M.upload.maximum_size=1044464 +modwifi.menu.eesz.2M.build.rfcal_addr=0x1FC000 +modwifi.menu.ip.lm2f=v2 Lower Memory +modwifi.menu.ip.lm2f.build.lwip_include=lwip2/include +modwifi.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +modwifi.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +modwifi.menu.ip.hb2f=v2 Higher Bandwidth +modwifi.menu.ip.hb2f.build.lwip_include=lwip2/include +modwifi.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +modwifi.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +modwifi.menu.ip.lm2n=v2 Lower Memory (no features) +modwifi.menu.ip.lm2n.build.lwip_include=lwip2/include +modwifi.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +modwifi.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +modwifi.menu.ip.hb2n=v2 Higher Bandwidth (no features) +modwifi.menu.ip.hb2n.build.lwip_include=lwip2/include +modwifi.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +modwifi.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +modwifi.menu.ip.lm6f=v2 IPv6 Lower Memory +modwifi.menu.ip.lm6f.build.lwip_include=lwip2/include +modwifi.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +modwifi.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +modwifi.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +modwifi.menu.ip.hb6f.build.lwip_include=lwip2/include +modwifi.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +modwifi.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +modwifi.menu.ip.hb1=v1.4 Higher Bandwidth +modwifi.menu.ip.hb1.build.lwip_lib=-llwip_gcc +modwifi.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +modwifi.menu.ip.src=v1.4 Compile from source +modwifi.menu.ip.src.build.lwip_lib=-llwip_src +modwifi.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +modwifi.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +modwifi.menu.dbg.Disabled=Disabled +modwifi.menu.dbg.Disabled.build.debug_port= +modwifi.menu.dbg.Serial=Serial +modwifi.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +modwifi.menu.dbg.Serial1=Serial1 +modwifi.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +modwifi.menu.lvl.None____=None +modwifi.menu.lvl.None____.build.debug_level= +modwifi.menu.lvl.SSL=SSL +modwifi.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +modwifi.menu.lvl.TLS_MEM=TLS_MEM +modwifi.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +modwifi.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +modwifi.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.HTTP_SERVER=HTTP_SERVER +modwifi.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +modwifi.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +modwifi.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +modwifi.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +modwifi.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +modwifi.menu.lvl.CORE=CORE +modwifi.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +modwifi.menu.lvl.WIFI=WIFI +modwifi.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +modwifi.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +modwifi.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +modwifi.menu.lvl.UPDATER=UPDATER +modwifi.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +modwifi.menu.lvl.OTA=OTA +modwifi.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +modwifi.menu.lvl.OOM=OOM +modwifi.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +modwifi.menu.lvl.MDNS=MDNS +modwifi.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +modwifi.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +modwifi.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +modwifi.menu.wipe.none=Only Sketch +modwifi.menu.wipe.none.upload.erase_cmd= +modwifi.menu.wipe.sdk=Sketch + WiFi Settings +modwifi.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +modwifi.menu.wipe.all=All Flash Contents +modwifi.menu.wipe.all.upload.erase_cmd=erase_flash +modwifi.menu.baud.115200=115200 +modwifi.menu.baud.115200.upload.speed=115200 +modwifi.menu.baud.57600=57600 +modwifi.menu.baud.57600.upload.speed=57600 +modwifi.menu.baud.230400.linux=230400 +modwifi.menu.baud.230400.macosx=230400 +modwifi.menu.baud.230400.upload.speed=230400 +modwifi.menu.baud.256000.windows=256000 +modwifi.menu.baud.256000.upload.speed=256000 +modwifi.menu.baud.460800.linux=460800 +modwifi.menu.baud.460800.macosx=460800 +modwifi.menu.baud.460800.upload.speed=460800 +modwifi.menu.baud.512000.windows=512000 +modwifi.menu.baud.512000.upload.speed=512000 +modwifi.menu.baud.921600=921600 +modwifi.menu.baud.921600.upload.speed=921600 +modwifi.menu.baud.3000000=3000000 +modwifi.menu.baud.3000000.upload.speed=3000000 + +############################################################## +thing.name=SparkFun ESP8266 Thing +thing.build.board=ESP8266_THING +thing.build.variant=thing +thing.upload.tool=esptool +thing.upload.maximum_data_size=81920 +thing.upload.wait_for_upload_port=true +thing.upload.erase_cmd= +thing.serial.disableDTR=true +thing.serial.disableRTS=true +thing.build.mcu=esp8266 +thing.build.core=esp8266 +thing.build.spiffs_pagesize=256 +thing.build.debug_port= +thing.build.debug_level= +thing.menu.xtal.80=80 MHz +thing.menu.xtal.80.build.f_cpu=80000000L +thing.menu.xtal.160=160 MHz +thing.menu.xtal.160.build.f_cpu=160000000L +thing.menu.vt.flash=Flash +thing.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +thing.menu.vt.heap=Heap +thing.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +thing.menu.vt.iram=IRAM +thing.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +thing.menu.exception.legacy=Legacy (new can return nullptr) +thing.menu.exception.legacy.build.exception_flags=-fno-exceptions +thing.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +thing.menu.exception.disabled=Disabled (new can abort) +thing.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +thing.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +thing.menu.exception.enabled=Enabled +thing.menu.exception.enabled.build.exception_flags=-fexceptions +thing.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +thing.menu.ssl.all=All SSL ciphers (most compatible) +thing.menu.ssl.all.build.sslflags= +thing.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +thing.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +thing.upload.resetmethod=--before no_reset --after soft_reset +thing.build.flash_mode=qio +thing.build.flash_flags=-DFLASHMODE_QIO +thing.build.flash_freq=40 +thing.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) +thing.menu.eesz.512K32.build.flash_size=512K +thing.menu.eesz.512K32.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +thing.menu.eesz.512K32.build.spiffs_pagesize=256 +thing.menu.eesz.512K32.upload.maximum_size=466928 +thing.menu.eesz.512K32.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K32.build.spiffs_start=0x73000 +thing.menu.eesz.512K32.build.spiffs_end=0x7B000 +thing.menu.eesz.512K32.build.spiffs_blocksize=4096 +thing.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) +thing.menu.eesz.512K64.build.flash_size=512K +thing.menu.eesz.512K64.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +thing.menu.eesz.512K64.build.spiffs_pagesize=256 +thing.menu.eesz.512K64.upload.maximum_size=434160 +thing.menu.eesz.512K64.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K64.build.spiffs_start=0x6B000 +thing.menu.eesz.512K64.build.spiffs_end=0x7B000 +thing.menu.eesz.512K64.build.spiffs_blocksize=4096 +thing.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) +thing.menu.eesz.512K128.build.flash_size=512K +thing.menu.eesz.512K128.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +thing.menu.eesz.512K128.build.spiffs_pagesize=256 +thing.menu.eesz.512K128.upload.maximum_size=368624 +thing.menu.eesz.512K128.build.rfcal_addr=0x7C000 +thing.menu.eesz.512K128.build.spiffs_start=0x5B000 +thing.menu.eesz.512K128.build.spiffs_end=0x7B000 +thing.menu.eesz.512K128.build.spiffs_blocksize=4096 +thing.menu.eesz.512K=512KB (FS:none OTA:~246KB) +thing.menu.eesz.512K.build.flash_size=512K +thing.menu.eesz.512K.build.flash_size_bytes=0x80000 +thing.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +thing.menu.eesz.512K.build.spiffs_pagesize=256 +thing.menu.eesz.512K.upload.maximum_size=499696 +thing.menu.eesz.512K.build.rfcal_addr=0x7C000 +thing.menu.ip.lm2f=v2 Lower Memory +thing.menu.ip.lm2f.build.lwip_include=lwip2/include +thing.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +thing.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thing.menu.ip.hb2f=v2 Higher Bandwidth +thing.menu.ip.hb2f.build.lwip_include=lwip2/include +thing.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +thing.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thing.menu.ip.lm2n=v2 Lower Memory (no features) +thing.menu.ip.lm2n.build.lwip_include=lwip2/include +thing.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +thing.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thing.menu.ip.hb2n=v2 Higher Bandwidth (no features) +thing.menu.ip.hb2n.build.lwip_include=lwip2/include +thing.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +thing.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thing.menu.ip.lm6f=v2 IPv6 Lower Memory +thing.menu.ip.lm6f.build.lwip_include=lwip2/include +thing.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +thing.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thing.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +thing.menu.ip.hb6f.build.lwip_include=lwip2/include +thing.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +thing.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thing.menu.ip.hb1=v1.4 Higher Bandwidth +thing.menu.ip.hb1.build.lwip_lib=-llwip_gcc +thing.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +thing.menu.ip.src=v1.4 Compile from source +thing.menu.ip.src.build.lwip_lib=-llwip_src +thing.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +thing.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +thing.menu.dbg.Disabled=Disabled +thing.menu.dbg.Disabled.build.debug_port= +thing.menu.dbg.Serial=Serial +thing.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +thing.menu.dbg.Serial1=Serial1 +thing.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +thing.menu.lvl.None____=None +thing.menu.lvl.None____.build.debug_level= +thing.menu.lvl.SSL=SSL +thing.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +thing.menu.lvl.TLS_MEM=TLS_MEM +thing.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +thing.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +thing.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.HTTP_SERVER=HTTP_SERVER +thing.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +thing.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +thing.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +thing.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +thing.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +thing.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thing.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thing.menu.lvl.CORE=CORE +thing.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +thing.menu.lvl.WIFI=WIFI +thing.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +thing.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +thing.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +thing.menu.lvl.UPDATER=UPDATER +thing.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +thing.menu.lvl.OTA=OTA +thing.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +thing.menu.lvl.OOM=OOM +thing.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +thing.menu.lvl.MDNS=MDNS +thing.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +thing.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +thing.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +thing.menu.wipe.none=Only Sketch +thing.menu.wipe.none.upload.erase_cmd= +thing.menu.wipe.sdk=Sketch + WiFi Settings +thing.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +thing.menu.wipe.all=All Flash Contents +thing.menu.wipe.all.upload.erase_cmd=erase_flash +thing.menu.baud.115200=115200 +thing.menu.baud.115200.upload.speed=115200 +thing.menu.baud.57600=57600 +thing.menu.baud.57600.upload.speed=57600 +thing.menu.baud.230400.linux=230400 +thing.menu.baud.230400.macosx=230400 +thing.menu.baud.230400.upload.speed=230400 +thing.menu.baud.256000.windows=256000 +thing.menu.baud.256000.upload.speed=256000 +thing.menu.baud.460800.linux=460800 +thing.menu.baud.460800.macosx=460800 +thing.menu.baud.460800.upload.speed=460800 +thing.menu.baud.512000.windows=512000 +thing.menu.baud.512000.upload.speed=512000 +thing.menu.baud.921600=921600 +thing.menu.baud.921600.upload.speed=921600 +thing.menu.baud.3000000=3000000 +thing.menu.baud.3000000.upload.speed=3000000 + +############################################################## +thingdev.name=SparkFun ESP8266 Thing Dev +thingdev.build.board=ESP8266_THING_DEV +thingdev.build.variant=thing +thingdev.upload.tool=esptool +thingdev.upload.maximum_data_size=81920 +thingdev.upload.wait_for_upload_port=true +thingdev.upload.erase_cmd= +thingdev.serial.disableDTR=true +thingdev.serial.disableRTS=true +thingdev.build.mcu=esp8266 +thingdev.build.core=esp8266 +thingdev.build.spiffs_pagesize=256 +thingdev.build.debug_port= +thingdev.build.debug_level= +thingdev.menu.xtal.80=80 MHz +thingdev.menu.xtal.80.build.f_cpu=80000000L +thingdev.menu.xtal.160=160 MHz +thingdev.menu.xtal.160.build.f_cpu=160000000L +thingdev.menu.vt.flash=Flash +thingdev.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +thingdev.menu.vt.heap=Heap +thingdev.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +thingdev.menu.vt.iram=IRAM +thingdev.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +thingdev.menu.exception.legacy=Legacy (new can return nullptr) +thingdev.menu.exception.legacy.build.exception_flags=-fno-exceptions +thingdev.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +thingdev.menu.exception.disabled=Disabled (new can abort) +thingdev.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +thingdev.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +thingdev.menu.exception.enabled=Enabled +thingdev.menu.exception.enabled.build.exception_flags=-fexceptions +thingdev.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +thingdev.menu.ssl.all=All SSL ciphers (most compatible) +thingdev.menu.ssl.all.build.sslflags= +thingdev.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +thingdev.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +thingdev.upload.resetmethod=--before default_reset --after hard_reset +thingdev.build.flash_mode=dio +thingdev.build.flash_flags=-DFLASHMODE_DIO +thingdev.build.flash_freq=40 +thingdev.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) +thingdev.menu.eesz.512K32.build.flash_size=512K +thingdev.menu.eesz.512K32.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +thingdev.menu.eesz.512K32.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K32.upload.maximum_size=466928 +thingdev.menu.eesz.512K32.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K32.build.spiffs_start=0x73000 +thingdev.menu.eesz.512K32.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K32.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) +thingdev.menu.eesz.512K64.build.flash_size=512K +thingdev.menu.eesz.512K64.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +thingdev.menu.eesz.512K64.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K64.upload.maximum_size=434160 +thingdev.menu.eesz.512K64.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K64.build.spiffs_start=0x6B000 +thingdev.menu.eesz.512K64.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K64.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) +thingdev.menu.eesz.512K128.build.flash_size=512K +thingdev.menu.eesz.512K128.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +thingdev.menu.eesz.512K128.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K128.upload.maximum_size=368624 +thingdev.menu.eesz.512K128.build.rfcal_addr=0x7C000 +thingdev.menu.eesz.512K128.build.spiffs_start=0x5B000 +thingdev.menu.eesz.512K128.build.spiffs_end=0x7B000 +thingdev.menu.eesz.512K128.build.spiffs_blocksize=4096 +thingdev.menu.eesz.512K=512KB (FS:none OTA:~246KB) +thingdev.menu.eesz.512K.build.flash_size=512K +thingdev.menu.eesz.512K.build.flash_size_bytes=0x80000 +thingdev.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +thingdev.menu.eesz.512K.build.spiffs_pagesize=256 +thingdev.menu.eesz.512K.upload.maximum_size=499696 +thingdev.menu.eesz.512K.build.rfcal_addr=0x7C000 +thingdev.menu.ip.lm2f=v2 Lower Memory +thingdev.menu.ip.lm2f.build.lwip_include=lwip2/include +thingdev.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +thingdev.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thingdev.menu.ip.hb2f=v2 Higher Bandwidth +thingdev.menu.ip.hb2f.build.lwip_include=lwip2/include +thingdev.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +thingdev.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +thingdev.menu.ip.lm2n=v2 Lower Memory (no features) +thingdev.menu.ip.lm2n.build.lwip_include=lwip2/include +thingdev.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +thingdev.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thingdev.menu.ip.hb2n=v2 Higher Bandwidth (no features) +thingdev.menu.ip.hb2n.build.lwip_include=lwip2/include +thingdev.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +thingdev.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +thingdev.menu.ip.lm6f=v2 IPv6 Lower Memory +thingdev.menu.ip.lm6f.build.lwip_include=lwip2/include +thingdev.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +thingdev.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thingdev.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +thingdev.menu.ip.hb6f.build.lwip_include=lwip2/include +thingdev.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +thingdev.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +thingdev.menu.ip.hb1=v1.4 Higher Bandwidth +thingdev.menu.ip.hb1.build.lwip_lib=-llwip_gcc +thingdev.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +thingdev.menu.ip.src=v1.4 Compile from source +thingdev.menu.ip.src.build.lwip_lib=-llwip_src +thingdev.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +thingdev.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +thingdev.menu.dbg.Disabled=Disabled +thingdev.menu.dbg.Disabled.build.debug_port= +thingdev.menu.dbg.Serial=Serial +thingdev.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +thingdev.menu.dbg.Serial1=Serial1 +thingdev.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +thingdev.menu.lvl.None____=None +thingdev.menu.lvl.None____.build.debug_level= +thingdev.menu.lvl.SSL=SSL +thingdev.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +thingdev.menu.lvl.TLS_MEM=TLS_MEM +thingdev.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +thingdev.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +thingdev.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.HTTP_SERVER=HTTP_SERVER +thingdev.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +thingdev.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +thingdev.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +thingdev.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +thingdev.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +thingdev.menu.lvl.CORE=CORE +thingdev.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +thingdev.menu.lvl.WIFI=WIFI +thingdev.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +thingdev.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +thingdev.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +thingdev.menu.lvl.UPDATER=UPDATER +thingdev.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +thingdev.menu.lvl.OTA=OTA +thingdev.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +thingdev.menu.lvl.OOM=OOM +thingdev.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +thingdev.menu.lvl.MDNS=MDNS +thingdev.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +thingdev.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +thingdev.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +thingdev.menu.wipe.none=Only Sketch +thingdev.menu.wipe.none.upload.erase_cmd= +thingdev.menu.wipe.sdk=Sketch + WiFi Settings +thingdev.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +thingdev.menu.wipe.all=All Flash Contents +thingdev.menu.wipe.all.upload.erase_cmd=erase_flash +thingdev.menu.baud.115200=115200 +thingdev.menu.baud.115200.upload.speed=115200 +thingdev.menu.baud.57600=57600 +thingdev.menu.baud.57600.upload.speed=57600 +thingdev.menu.baud.230400.linux=230400 +thingdev.menu.baud.230400.macosx=230400 +thingdev.menu.baud.230400.upload.speed=230400 +thingdev.menu.baud.256000.windows=256000 +thingdev.menu.baud.256000.upload.speed=256000 +thingdev.menu.baud.460800.linux=460800 +thingdev.menu.baud.460800.macosx=460800 +thingdev.menu.baud.460800.upload.speed=460800 +thingdev.menu.baud.512000.windows=512000 +thingdev.menu.baud.512000.upload.speed=512000 +thingdev.menu.baud.921600=921600 +thingdev.menu.baud.921600.upload.speed=921600 +thingdev.menu.baud.3000000=3000000 +thingdev.menu.baud.3000000.upload.speed=3000000 + +############################################################## +blynk.name=SparkFun Blynk Board +blynk.build.board=ESP8266_THING +blynk.build.variant=thing +blynk.upload.tool=esptool +blynk.upload.maximum_data_size=81920 +blynk.upload.wait_for_upload_port=true +blynk.upload.erase_cmd= +blynk.serial.disableDTR=true +blynk.serial.disableRTS=true +blynk.build.mcu=esp8266 +blynk.build.core=esp8266 +blynk.build.spiffs_pagesize=256 +blynk.build.debug_port= +blynk.build.debug_level= +blynk.menu.xtal.80=80 MHz +blynk.menu.xtal.80.build.f_cpu=80000000L +blynk.menu.xtal.160=160 MHz +blynk.menu.xtal.160.build.f_cpu=160000000L +blynk.menu.vt.flash=Flash +blynk.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +blynk.menu.vt.heap=Heap +blynk.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +blynk.menu.vt.iram=IRAM +blynk.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +blynk.menu.exception.legacy=Legacy (new can return nullptr) +blynk.menu.exception.legacy.build.exception_flags=-fno-exceptions +blynk.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +blynk.menu.exception.disabled=Disabled (new can abort) +blynk.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +blynk.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +blynk.menu.exception.enabled=Enabled +blynk.menu.exception.enabled.build.exception_flags=-fexceptions +blynk.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +blynk.menu.ssl.all=All SSL ciphers (most compatible) +blynk.menu.ssl.all.build.sslflags= +blynk.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +blynk.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +blynk.upload.resetmethod=--before default_reset --after hard_reset +blynk.build.flash_mode=qio +blynk.build.flash_flags=-DFLASHMODE_QIO +blynk.build.flash_freq=40 +blynk.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +blynk.menu.eesz.4M2M.build.flash_size=4M +blynk.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +blynk.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +blynk.menu.eesz.4M2M.build.spiffs_pagesize=256 +blynk.menu.eesz.4M2M.upload.maximum_size=1044464 +blynk.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +blynk.menu.eesz.4M2M.build.spiffs_start=0x200000 +blynk.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +blynk.menu.eesz.4M2M.build.spiffs_blocksize=8192 +blynk.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +blynk.menu.eesz.4M3M.build.flash_size=4M +blynk.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +blynk.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +blynk.menu.eesz.4M3M.build.spiffs_pagesize=256 +blynk.menu.eesz.4M3M.upload.maximum_size=1044464 +blynk.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +blynk.menu.eesz.4M3M.build.spiffs_start=0x100000 +blynk.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +blynk.menu.eesz.4M3M.build.spiffs_blocksize=8192 +blynk.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +blynk.menu.eesz.4M1M.build.flash_size=4M +blynk.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +blynk.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +blynk.menu.eesz.4M1M.build.spiffs_pagesize=256 +blynk.menu.eesz.4M1M.upload.maximum_size=1044464 +blynk.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +blynk.menu.eesz.4M1M.build.spiffs_start=0x300000 +blynk.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +blynk.menu.eesz.4M1M.build.spiffs_blocksize=8192 +blynk.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +blynk.menu.eesz.4M.build.flash_size=4M +blynk.menu.eesz.4M.build.flash_size_bytes=0x400000 +blynk.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +blynk.menu.eesz.4M.build.spiffs_pagesize=256 +blynk.menu.eesz.4M.upload.maximum_size=1044464 +blynk.menu.eesz.4M.build.rfcal_addr=0x3FC000 +blynk.menu.ip.lm2f=v2 Lower Memory +blynk.menu.ip.lm2f.build.lwip_include=lwip2/include +blynk.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +blynk.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +blynk.menu.ip.hb2f=v2 Higher Bandwidth +blynk.menu.ip.hb2f.build.lwip_include=lwip2/include +blynk.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +blynk.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +blynk.menu.ip.lm2n=v2 Lower Memory (no features) +blynk.menu.ip.lm2n.build.lwip_include=lwip2/include +blynk.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +blynk.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +blynk.menu.ip.hb2n=v2 Higher Bandwidth (no features) +blynk.menu.ip.hb2n.build.lwip_include=lwip2/include +blynk.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +blynk.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +blynk.menu.ip.lm6f=v2 IPv6 Lower Memory +blynk.menu.ip.lm6f.build.lwip_include=lwip2/include +blynk.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +blynk.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +blynk.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +blynk.menu.ip.hb6f.build.lwip_include=lwip2/include +blynk.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +blynk.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +blynk.menu.ip.hb1=v1.4 Higher Bandwidth +blynk.menu.ip.hb1.build.lwip_lib=-llwip_gcc +blynk.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +blynk.menu.ip.src=v1.4 Compile from source +blynk.menu.ip.src.build.lwip_lib=-llwip_src +blynk.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +blynk.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +blynk.menu.dbg.Disabled=Disabled +blynk.menu.dbg.Disabled.build.debug_port= +blynk.menu.dbg.Serial=Serial +blynk.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +blynk.menu.dbg.Serial1=Serial1 +blynk.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +blynk.menu.lvl.None____=None +blynk.menu.lvl.None____.build.debug_level= +blynk.menu.lvl.SSL=SSL +blynk.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +blynk.menu.lvl.TLS_MEM=TLS_MEM +blynk.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +blynk.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +blynk.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +blynk.menu.lvl.HTTP_SERVER=HTTP_SERVER +blynk.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +blynk.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +blynk.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +blynk.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +blynk.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +blynk.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +blynk.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +blynk.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +blynk.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +blynk.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +blynk.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +blynk.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +blynk.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +blynk.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +blynk.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +blynk.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +blynk.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +blynk.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +blynk.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +blynk.menu.lvl.CORE=CORE +blynk.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +blynk.menu.lvl.WIFI=WIFI +blynk.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +blynk.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +blynk.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +blynk.menu.lvl.UPDATER=UPDATER +blynk.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +blynk.menu.lvl.OTA=OTA +blynk.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +blynk.menu.lvl.OOM=OOM +blynk.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +blynk.menu.lvl.MDNS=MDNS +blynk.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +blynk.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +blynk.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +blynk.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +blynk.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +blynk.menu.wipe.none=Only Sketch +blynk.menu.wipe.none.upload.erase_cmd= +blynk.menu.wipe.sdk=Sketch + WiFi Settings +blynk.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +blynk.menu.wipe.all=All Flash Contents +blynk.menu.wipe.all.upload.erase_cmd=erase_flash +blynk.menu.baud.115200=115200 +blynk.menu.baud.115200.upload.speed=115200 +blynk.menu.baud.57600=57600 +blynk.menu.baud.57600.upload.speed=57600 +blynk.menu.baud.230400.linux=230400 +blynk.menu.baud.230400.macosx=230400 +blynk.menu.baud.230400.upload.speed=230400 +blynk.menu.baud.256000.windows=256000 +blynk.menu.baud.256000.upload.speed=256000 +blynk.menu.baud.460800.linux=460800 +blynk.menu.baud.460800.macosx=460800 +blynk.menu.baud.460800.upload.speed=460800 +blynk.menu.baud.512000.windows=512000 +blynk.menu.baud.512000.upload.speed=512000 +blynk.menu.baud.921600=921600 +blynk.menu.baud.921600.upload.speed=921600 +blynk.menu.baud.3000000=3000000 +blynk.menu.baud.3000000.upload.speed=3000000 + +############################################################## +esp210.name=SweetPea ESP-210 +esp210.build.board=ESP8266_ESP210 +esp210.upload.tool=esptool +esp210.upload.maximum_data_size=81920 +esp210.upload.wait_for_upload_port=true +esp210.upload.erase_cmd= +esp210.serial.disableDTR=true +esp210.serial.disableRTS=true +esp210.build.mcu=esp8266 +esp210.build.core=esp8266 +esp210.build.variant=generic +esp210.build.spiffs_pagesize=256 +esp210.build.debug_port= +esp210.build.debug_level= +esp210.menu.xtal.80=80 MHz +esp210.menu.xtal.80.build.f_cpu=80000000L +esp210.menu.xtal.160=160 MHz +esp210.menu.xtal.160.build.f_cpu=160000000L +esp210.menu.vt.flash=Flash +esp210.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +esp210.menu.vt.heap=Heap +esp210.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +esp210.menu.vt.iram=IRAM +esp210.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +esp210.menu.exception.legacy=Legacy (new can return nullptr) +esp210.menu.exception.legacy.build.exception_flags=-fno-exceptions +esp210.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +esp210.menu.exception.disabled=Disabled (new can abort) +esp210.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +esp210.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +esp210.menu.exception.enabled=Enabled +esp210.menu.exception.enabled.build.exception_flags=-fexceptions +esp210.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +esp210.menu.ssl.all=All SSL ciphers (most compatible) +esp210.menu.ssl.all.build.sslflags= +esp210.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +esp210.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +esp210.upload.resetmethod=--before no_reset --after soft_reset +esp210.build.flash_mode=qio +esp210.build.flash_flags=-DFLASHMODE_QIO +esp210.build.flash_freq=40 +esp210.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +esp210.menu.eesz.4M2M.build.flash_size=4M +esp210.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +esp210.menu.eesz.4M2M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M2M.upload.maximum_size=1044464 +esp210.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M2M.build.spiffs_start=0x200000 +esp210.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +esp210.menu.eesz.4M2M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +esp210.menu.eesz.4M3M.build.flash_size=4M +esp210.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +esp210.menu.eesz.4M3M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M3M.upload.maximum_size=1044464 +esp210.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M3M.build.spiffs_start=0x100000 +esp210.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +esp210.menu.eesz.4M3M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +esp210.menu.eesz.4M1M.build.flash_size=4M +esp210.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +esp210.menu.eesz.4M1M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M1M.upload.maximum_size=1044464 +esp210.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +esp210.menu.eesz.4M1M.build.spiffs_start=0x300000 +esp210.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +esp210.menu.eesz.4M1M.build.spiffs_blocksize=8192 +esp210.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +esp210.menu.eesz.4M.build.flash_size=4M +esp210.menu.eesz.4M.build.flash_size_bytes=0x400000 +esp210.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +esp210.menu.eesz.4M.build.spiffs_pagesize=256 +esp210.menu.eesz.4M.upload.maximum_size=1044464 +esp210.menu.eesz.4M.build.rfcal_addr=0x3FC000 +esp210.menu.ip.lm2f=v2 Lower Memory +esp210.menu.ip.lm2f.build.lwip_include=lwip2/include +esp210.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +esp210.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp210.menu.ip.hb2f=v2 Higher Bandwidth +esp210.menu.ip.hb2f.build.lwip_include=lwip2/include +esp210.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +esp210.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +esp210.menu.ip.lm2n=v2 Lower Memory (no features) +esp210.menu.ip.lm2n.build.lwip_include=lwip2/include +esp210.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +esp210.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp210.menu.ip.hb2n=v2 Higher Bandwidth (no features) +esp210.menu.ip.hb2n.build.lwip_include=lwip2/include +esp210.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +esp210.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +esp210.menu.ip.lm6f=v2 IPv6 Lower Memory +esp210.menu.ip.lm6f.build.lwip_include=lwip2/include +esp210.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +esp210.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp210.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +esp210.menu.ip.hb6f.build.lwip_include=lwip2/include +esp210.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +esp210.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +esp210.menu.ip.hb1=v1.4 Higher Bandwidth +esp210.menu.ip.hb1.build.lwip_lib=-llwip_gcc +esp210.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +esp210.menu.ip.src=v1.4 Compile from source +esp210.menu.ip.src.build.lwip_lib=-llwip_src +esp210.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +esp210.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +esp210.menu.dbg.Disabled=Disabled +esp210.menu.dbg.Disabled.build.debug_port= +esp210.menu.dbg.Serial=Serial +esp210.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +esp210.menu.dbg.Serial1=Serial1 +esp210.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +esp210.menu.lvl.None____=None +esp210.menu.lvl.None____.build.debug_level= +esp210.menu.lvl.SSL=SSL +esp210.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +esp210.menu.lvl.TLS_MEM=TLS_MEM +esp210.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +esp210.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +esp210.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.HTTP_SERVER=HTTP_SERVER +esp210.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +esp210.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +esp210.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +esp210.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +esp210.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +esp210.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +esp210.menu.lvl.CORE=CORE +esp210.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +esp210.menu.lvl.WIFI=WIFI +esp210.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +esp210.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +esp210.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +esp210.menu.lvl.UPDATER=UPDATER +esp210.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +esp210.menu.lvl.OTA=OTA +esp210.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +esp210.menu.lvl.OOM=OOM +esp210.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +esp210.menu.lvl.MDNS=MDNS +esp210.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +esp210.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +esp210.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +esp210.menu.wipe.none=Only Sketch +esp210.menu.wipe.none.upload.erase_cmd= +esp210.menu.wipe.sdk=Sketch + WiFi Settings +esp210.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +esp210.menu.wipe.all=All Flash Contents +esp210.menu.wipe.all.upload.erase_cmd=erase_flash +esp210.menu.baud.57600=57600 +esp210.menu.baud.57600.upload.speed=57600 +esp210.menu.baud.115200=115200 +esp210.menu.baud.115200.upload.speed=115200 +esp210.menu.baud.230400.linux=230400 +esp210.menu.baud.230400.macosx=230400 +esp210.menu.baud.230400.upload.speed=230400 +esp210.menu.baud.256000.windows=256000 +esp210.menu.baud.256000.upload.speed=256000 +esp210.menu.baud.460800.linux=460800 +esp210.menu.baud.460800.macosx=460800 +esp210.menu.baud.460800.upload.speed=460800 +esp210.menu.baud.512000.windows=512000 +esp210.menu.baud.512000.upload.speed=512000 +esp210.menu.baud.921600=921600 +esp210.menu.baud.921600.upload.speed=921600 +esp210.menu.baud.3000000=3000000 +esp210.menu.baud.3000000.upload.speed=3000000 + +############################################################## +d1_mini.name=LOLIN(WEMOS) D1 R2 & mini +d1_mini.build.board=ESP8266_WEMOS_D1MINI +d1_mini.build.variant=d1_mini +d1_mini.upload.tool=esptool +d1_mini.upload.maximum_data_size=81920 +d1_mini.upload.wait_for_upload_port=true +d1_mini.upload.erase_cmd= +d1_mini.serial.disableDTR=true +d1_mini.serial.disableRTS=true +d1_mini.build.mcu=esp8266 +d1_mini.build.core=esp8266 +d1_mini.build.spiffs_pagesize=256 +d1_mini.build.debug_port= +d1_mini.build.debug_level= +d1_mini.menu.xtal.80=80 MHz +d1_mini.menu.xtal.80.build.f_cpu=80000000L +d1_mini.menu.xtal.160=160 MHz +d1_mini.menu.xtal.160.build.f_cpu=160000000L +d1_mini.menu.vt.flash=Flash +d1_mini.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini.menu.vt.heap=Heap +d1_mini.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini.menu.vt.iram=IRAM +d1_mini.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini.menu.exception.legacy=Legacy (new can return nullptr) +d1_mini.menu.exception.legacy.build.exception_flags=-fno-exceptions +d1_mini.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +d1_mini.menu.exception.disabled=Disabled (new can abort) +d1_mini.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +d1_mini.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini.menu.exception.enabled=Enabled +d1_mini.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini.menu.ssl.all=All SSL ciphers (most compatible) +d1_mini.menu.ssl.all.build.sslflags= +d1_mini.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +d1_mini.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +d1_mini.upload.resetmethod=--before default_reset --after hard_reset +d1_mini.build.flash_mode=dio +d1_mini.build.flash_flags=-DFLASHMODE_DIO +d1_mini.build.flash_freq=40 +d1_mini.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +d1_mini.menu.eesz.4M2M.build.flash_size=4M +d1_mini.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +d1_mini.menu.eesz.4M2M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M2M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M2M.build.spiffs_start=0x200000 +d1_mini.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +d1_mini.menu.eesz.4M2M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +d1_mini.menu.eesz.4M3M.build.flash_size=4M +d1_mini.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +d1_mini.menu.eesz.4M3M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M3M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M3M.build.spiffs_start=0x100000 +d1_mini.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +d1_mini.menu.eesz.4M3M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +d1_mini.menu.eesz.4M1M.build.flash_size=4M +d1_mini.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +d1_mini.menu.eesz.4M1M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M1M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +d1_mini.menu.eesz.4M1M.build.spiffs_start=0x300000 +d1_mini.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +d1_mini.menu.eesz.4M1M.build.spiffs_blocksize=8192 +d1_mini.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +d1_mini.menu.eesz.4M.build.flash_size=4M +d1_mini.menu.eesz.4M.build.flash_size_bytes=0x400000 +d1_mini.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +d1_mini.menu.eesz.4M.build.spiffs_pagesize=256 +d1_mini.menu.eesz.4M.upload.maximum_size=1044464 +d1_mini.menu.eesz.4M.build.rfcal_addr=0x3FC000 +d1_mini.menu.ip.lm2f=v2 Lower Memory +d1_mini.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini.menu.ip.src=v1.4 Compile from source +d1_mini.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini.menu.dbg.Disabled=Disabled +d1_mini.menu.dbg.Disabled.build.debug_port= +d1_mini.menu.dbg.Serial=Serial +d1_mini.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini.menu.dbg.Serial1=Serial1 +d1_mini.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini.menu.lvl.None____=None +d1_mini.menu.lvl.None____.build.debug_level= +d1_mini.menu.lvl.SSL=SSL +d1_mini.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini.menu.lvl.TLS_MEM=TLS_MEM +d1_mini.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini.menu.lvl.CORE=CORE +d1_mini.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini.menu.lvl.WIFI=WIFI +d1_mini.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini.menu.lvl.UPDATER=UPDATER +d1_mini.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini.menu.lvl.OTA=OTA +d1_mini.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini.menu.lvl.OOM=OOM +d1_mini.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini.menu.lvl.MDNS=MDNS +d1_mini.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini.menu.wipe.none=Only Sketch +d1_mini.menu.wipe.none.upload.erase_cmd= +d1_mini.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +d1_mini.menu.wipe.all=All Flash Contents +d1_mini.menu.wipe.all.upload.erase_cmd=erase_flash +d1_mini.menu.baud.921600=921600 +d1_mini.menu.baud.921600.upload.speed=921600 +d1_mini.menu.baud.57600=57600 +d1_mini.menu.baud.57600.upload.speed=57600 +d1_mini.menu.baud.115200=115200 +d1_mini.menu.baud.115200.upload.speed=115200 +d1_mini.menu.baud.230400.linux=230400 +d1_mini.menu.baud.230400.macosx=230400 +d1_mini.menu.baud.230400.upload.speed=230400 +d1_mini.menu.baud.256000.windows=256000 +d1_mini.menu.baud.256000.upload.speed=256000 +d1_mini.menu.baud.460800.linux=460800 +d1_mini.menu.baud.460800.macosx=460800 +d1_mini.menu.baud.460800.upload.speed=460800 +d1_mini.menu.baud.512000.windows=512000 +d1_mini.menu.baud.512000.upload.speed=512000 +d1_mini.menu.baud.3000000=3000000 +d1_mini.menu.baud.3000000.upload.speed=3000000 + +############################################################## +d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro +d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO +d1_mini_pro.build.variant=d1_mini +d1_mini_pro.upload.tool=esptool +d1_mini_pro.upload.maximum_data_size=81920 +d1_mini_pro.upload.wait_for_upload_port=true +d1_mini_pro.upload.erase_cmd= +d1_mini_pro.serial.disableDTR=true +d1_mini_pro.serial.disableRTS=true +d1_mini_pro.build.mcu=esp8266 +d1_mini_pro.build.core=esp8266 +d1_mini_pro.build.spiffs_pagesize=256 +d1_mini_pro.build.debug_port= +d1_mini_pro.build.debug_level= +d1_mini_pro.menu.xtal.80=80 MHz +d1_mini_pro.menu.xtal.80.build.f_cpu=80000000L +d1_mini_pro.menu.xtal.160=160 MHz +d1_mini_pro.menu.xtal.160.build.f_cpu=160000000L +d1_mini_pro.menu.vt.flash=Flash +d1_mini_pro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini_pro.menu.vt.heap=Heap +d1_mini_pro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini_pro.menu.vt.iram=IRAM +d1_mini_pro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini_pro.menu.exception.legacy=Legacy (new can return nullptr) +d1_mini_pro.menu.exception.legacy.build.exception_flags=-fno-exceptions +d1_mini_pro.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +d1_mini_pro.menu.exception.disabled=Disabled (new can abort) +d1_mini_pro.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +d1_mini_pro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini_pro.menu.exception.enabled=Enabled +d1_mini_pro.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini_pro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini_pro.menu.ssl.all=All SSL ciphers (most compatible) +d1_mini_pro.menu.ssl.all.build.sslflags= +d1_mini_pro.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +d1_mini_pro.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +d1_mini_pro.upload.resetmethod=--before default_reset --after hard_reset +d1_mini_pro.build.flash_mode=dio +d1_mini_pro.build.flash_flags=-DFLASHMODE_DIO +d1_mini_pro.build.flash_freq=40 +d1_mini_pro.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB) +d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M +d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 +d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld +d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256 +d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464 +d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFA000 +d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192 +d1_mini_pro.menu.eesz.16M15M=16MB (FS:15MB OTA:~512KB) +d1_mini_pro.menu.eesz.16M15M.build.flash_size=16M +d1_mini_pro.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 +d1_mini_pro.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld +d1_mini_pro.menu.eesz.16M15M.build.spiffs_pagesize=256 +d1_mini_pro.menu.eesz.16M15M.upload.maximum_size=1044464 +d1_mini_pro.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_start=0x100000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_end=0xFFA000 +d1_mini_pro.menu.eesz.16M15M.build.spiffs_blocksize=8192 +d1_mini_pro.menu.ip.lm2f=v2 Lower Memory +d1_mini_pro.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini_pro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini_pro.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini_pro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini_pro.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini_pro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini_pro.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini_pro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_pro.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini_pro.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini_pro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_pro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini_pro.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini_pro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini_pro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_pro.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini_pro.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini_pro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_pro.menu.ip.src=v1.4 Compile from source +d1_mini_pro.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini_pro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_pro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini_pro.menu.dbg.Disabled=Disabled +d1_mini_pro.menu.dbg.Disabled.build.debug_port= +d1_mini_pro.menu.dbg.Serial=Serial +d1_mini_pro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini_pro.menu.dbg.Serial1=Serial1 +d1_mini_pro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini_pro.menu.lvl.None____=None +d1_mini_pro.menu.lvl.None____.build.debug_level= +d1_mini_pro.menu.lvl.SSL=SSL +d1_mini_pro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini_pro.menu.lvl.TLS_MEM=TLS_MEM +d1_mini_pro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini_pro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini_pro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini_pro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini_pro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_pro.menu.lvl.CORE=CORE +d1_mini_pro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini_pro.menu.lvl.WIFI=WIFI +d1_mini_pro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini_pro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini_pro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini_pro.menu.lvl.UPDATER=UPDATER +d1_mini_pro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini_pro.menu.lvl.OTA=OTA +d1_mini_pro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini_pro.menu.lvl.OOM=OOM +d1_mini_pro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini_pro.menu.lvl.MDNS=MDNS +d1_mini_pro.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini_pro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini_pro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini_pro.menu.wipe.none=Only Sketch +d1_mini_pro.menu.wipe.none.upload.erase_cmd= +d1_mini_pro.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini_pro.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +d1_mini_pro.menu.wipe.all=All Flash Contents +d1_mini_pro.menu.wipe.all.upload.erase_cmd=erase_flash +d1_mini_pro.menu.baud.921600=921600 +d1_mini_pro.menu.baud.921600.upload.speed=921600 +d1_mini_pro.menu.baud.57600=57600 +d1_mini_pro.menu.baud.57600.upload.speed=57600 +d1_mini_pro.menu.baud.115200=115200 +d1_mini_pro.menu.baud.115200.upload.speed=115200 +d1_mini_pro.menu.baud.230400.linux=230400 +d1_mini_pro.menu.baud.230400.macosx=230400 +d1_mini_pro.menu.baud.230400.upload.speed=230400 +d1_mini_pro.menu.baud.256000.windows=256000 +d1_mini_pro.menu.baud.256000.upload.speed=256000 +d1_mini_pro.menu.baud.460800.linux=460800 +d1_mini_pro.menu.baud.460800.macosx=460800 +d1_mini_pro.menu.baud.460800.upload.speed=460800 +d1_mini_pro.menu.baud.512000.windows=512000 +d1_mini_pro.menu.baud.512000.upload.speed=512000 +d1_mini_pro.menu.baud.3000000=3000000 +d1_mini_pro.menu.baud.3000000.upload.speed=3000000 + +############################################################## +d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite +d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE +d1_mini_lite.build.variant=d1_mini +d1_mini_lite.upload.tool=esptool +d1_mini_lite.upload.maximum_data_size=81920 +d1_mini_lite.upload.wait_for_upload_port=true +d1_mini_lite.upload.erase_cmd= +d1_mini_lite.serial.disableDTR=true +d1_mini_lite.serial.disableRTS=true +d1_mini_lite.build.mcu=esp8266 +d1_mini_lite.build.core=esp8266 +d1_mini_lite.build.spiffs_pagesize=256 +d1_mini_lite.build.debug_port= +d1_mini_lite.build.debug_level= +d1_mini_lite.menu.xtal.80=80 MHz +d1_mini_lite.menu.xtal.80.build.f_cpu=80000000L +d1_mini_lite.menu.xtal.160=160 MHz +d1_mini_lite.menu.xtal.160.build.f_cpu=160000000L +d1_mini_lite.menu.vt.flash=Flash +d1_mini_lite.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1_mini_lite.menu.vt.heap=Heap +d1_mini_lite.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1_mini_lite.menu.vt.iram=IRAM +d1_mini_lite.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1_mini_lite.menu.exception.legacy=Legacy (new can return nullptr) +d1_mini_lite.menu.exception.legacy.build.exception_flags=-fno-exceptions +d1_mini_lite.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +d1_mini_lite.menu.exception.disabled=Disabled (new can abort) +d1_mini_lite.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +d1_mini_lite.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1_mini_lite.menu.exception.enabled=Enabled +d1_mini_lite.menu.exception.enabled.build.exception_flags=-fexceptions +d1_mini_lite.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1_mini_lite.menu.ssl.all=All SSL ciphers (most compatible) +d1_mini_lite.menu.ssl.all.build.sslflags= +d1_mini_lite.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +d1_mini_lite.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +d1_mini_lite.upload.resetmethod=--before default_reset --after hard_reset +d1_mini_lite.build.flash_mode=dout +d1_mini_lite.build.flash_flags=-DFLASHMODE_DOUT +d1_mini_lite.build.flash_freq=40 +d1_mini_lite.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +d1_mini_lite.menu.eesz.1M64.build.flash_size=1M +d1_mini_lite.menu.eesz.1M64.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +d1_mini_lite.menu.eesz.1M64.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M64.upload.maximum_size=958448 +d1_mini_lite.menu.eesz.1M64.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_start=0xEB000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M64.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +d1_mini_lite.menu.eesz.1M128.build.flash_size=1M +d1_mini_lite.menu.eesz.1M128.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +d1_mini_lite.menu.eesz.1M128.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M128.upload.maximum_size=892912 +d1_mini_lite.menu.eesz.1M128.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_start=0xDB000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M128.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +d1_mini_lite.menu.eesz.1M144.build.flash_size=1M +d1_mini_lite.menu.eesz.1M144.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +d1_mini_lite.menu.eesz.1M144.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M144.upload.maximum_size=876528 +d1_mini_lite.menu.eesz.1M144.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_start=0xD7000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M144.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +d1_mini_lite.menu.eesz.1M160.build.flash_size=1M +d1_mini_lite.menu.eesz.1M160.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +d1_mini_lite.menu.eesz.1M160.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M160.upload.maximum_size=860144 +d1_mini_lite.menu.eesz.1M160.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_start=0xD3000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M160.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +d1_mini_lite.menu.eesz.1M192.build.flash_size=1M +d1_mini_lite.menu.eesz.1M192.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +d1_mini_lite.menu.eesz.1M192.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M192.upload.maximum_size=827376 +d1_mini_lite.menu.eesz.1M192.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_start=0xCB000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M192.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +d1_mini_lite.menu.eesz.1M256.build.flash_size=1M +d1_mini_lite.menu.eesz.1M256.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +d1_mini_lite.menu.eesz.1M256.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M256.upload.maximum_size=761840 +d1_mini_lite.menu.eesz.1M256.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_start=0xBB000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M256.build.spiffs_blocksize=4096 +d1_mini_lite.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +d1_mini_lite.menu.eesz.1M512.build.flash_size=1M +d1_mini_lite.menu.eesz.1M512.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +d1_mini_lite.menu.eesz.1M512.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M512.upload.maximum_size=499696 +d1_mini_lite.menu.eesz.1M512.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_start=0x7B000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_end=0xFB000 +d1_mini_lite.menu.eesz.1M512.build.spiffs_blocksize=8192 +d1_mini_lite.menu.eesz.1M=1MB (FS:none OTA:~502KB) +d1_mini_lite.menu.eesz.1M.build.flash_size=1M +d1_mini_lite.menu.eesz.1M.build.flash_size_bytes=0x100000 +d1_mini_lite.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +d1_mini_lite.menu.eesz.1M.build.spiffs_pagesize=256 +d1_mini_lite.menu.eesz.1M.upload.maximum_size=1023984 +d1_mini_lite.menu.eesz.1M.build.rfcal_addr=0xFC000 +d1_mini_lite.menu.ip.lm2f=v2 Lower Memory +d1_mini_lite.menu.ip.lm2f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1_mini_lite.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.hb2f=v2 Higher Bandwidth +d1_mini_lite.menu.ip.hb2f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1_mini_lite.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.lm2n=v2 Lower Memory (no features) +d1_mini_lite.menu.ip.lm2n.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1_mini_lite.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1_mini_lite.menu.ip.hb2n.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1_mini_lite.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1_mini_lite.menu.ip.lm6f=v2 IPv6 Lower Memory +d1_mini_lite.menu.ip.lm6f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1_mini_lite.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_lite.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1_mini_lite.menu.ip.hb6f.build.lwip_include=lwip2/include +d1_mini_lite.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1_mini_lite.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1_mini_lite.menu.ip.hb1=v1.4 Higher Bandwidth +d1_mini_lite.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1_mini_lite.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_lite.menu.ip.src=v1.4 Compile from source +d1_mini_lite.menu.ip.src.build.lwip_lib=-llwip_src +d1_mini_lite.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1_mini_lite.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1_mini_lite.menu.dbg.Disabled=Disabled +d1_mini_lite.menu.dbg.Disabled.build.debug_port= +d1_mini_lite.menu.dbg.Serial=Serial +d1_mini_lite.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1_mini_lite.menu.dbg.Serial1=Serial1 +d1_mini_lite.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1_mini_lite.menu.lvl.None____=None +d1_mini_lite.menu.lvl.None____.build.debug_level= +d1_mini_lite.menu.lvl.SSL=SSL +d1_mini_lite.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1_mini_lite.menu.lvl.TLS_MEM=TLS_MEM +d1_mini_lite.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1_mini_lite.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1_mini_lite.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1_mini_lite.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1_mini_lite.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1_mini_lite.menu.lvl.CORE=CORE +d1_mini_lite.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1_mini_lite.menu.lvl.WIFI=WIFI +d1_mini_lite.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1_mini_lite.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1_mini_lite.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1_mini_lite.menu.lvl.UPDATER=UPDATER +d1_mini_lite.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1_mini_lite.menu.lvl.OTA=OTA +d1_mini_lite.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1_mini_lite.menu.lvl.OOM=OOM +d1_mini_lite.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1_mini_lite.menu.lvl.MDNS=MDNS +d1_mini_lite.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1_mini_lite.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1_mini_lite.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1_mini_lite.menu.wipe.none=Only Sketch +d1_mini_lite.menu.wipe.none.upload.erase_cmd= +d1_mini_lite.menu.wipe.sdk=Sketch + WiFi Settings +d1_mini_lite.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +d1_mini_lite.menu.wipe.all=All Flash Contents +d1_mini_lite.menu.wipe.all.upload.erase_cmd=erase_flash +d1_mini_lite.menu.baud.921600=921600 +d1_mini_lite.menu.baud.921600.upload.speed=921600 +d1_mini_lite.menu.baud.57600=57600 +d1_mini_lite.menu.baud.57600.upload.speed=57600 +d1_mini_lite.menu.baud.115200=115200 +d1_mini_lite.menu.baud.115200.upload.speed=115200 +d1_mini_lite.menu.baud.230400.linux=230400 +d1_mini_lite.menu.baud.230400.macosx=230400 +d1_mini_lite.menu.baud.230400.upload.speed=230400 +d1_mini_lite.menu.baud.256000.windows=256000 +d1_mini_lite.menu.baud.256000.upload.speed=256000 +d1_mini_lite.menu.baud.460800.linux=460800 +d1_mini_lite.menu.baud.460800.macosx=460800 +d1_mini_lite.menu.baud.460800.upload.speed=460800 +d1_mini_lite.menu.baud.512000.windows=512000 +d1_mini_lite.menu.baud.512000.upload.speed=512000 +d1_mini_lite.menu.baud.3000000=3000000 +d1_mini_lite.menu.baud.3000000.upload.speed=3000000 + +############################################################## +d1.name=WeMos D1 R1 +d1.build.board=ESP8266_WEMOS_D1R1 +d1.build.variant=d1 +d1.upload.tool=esptool +d1.upload.maximum_data_size=81920 +d1.upload.wait_for_upload_port=true +d1.upload.erase_cmd= +d1.serial.disableDTR=true +d1.serial.disableRTS=true +d1.build.mcu=esp8266 +d1.build.core=esp8266 +d1.build.spiffs_pagesize=256 +d1.build.debug_port= +d1.build.debug_level= +d1.menu.xtal.80=80 MHz +d1.menu.xtal.80.build.f_cpu=80000000L +d1.menu.xtal.160=160 MHz +d1.menu.xtal.160.build.f_cpu=160000000L +d1.menu.vt.flash=Flash +d1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +d1.menu.vt.heap=Heap +d1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +d1.menu.vt.iram=IRAM +d1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +d1.menu.exception.legacy=Legacy (new can return nullptr) +d1.menu.exception.legacy.build.exception_flags=-fno-exceptions +d1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +d1.menu.exception.disabled=Disabled (new can abort) +d1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +d1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +d1.menu.exception.enabled=Enabled +d1.menu.exception.enabled.build.exception_flags=-fexceptions +d1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +d1.menu.ssl.all=All SSL ciphers (most compatible) +d1.menu.ssl.all.build.sslflags= +d1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +d1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +d1.upload.resetmethod=--before default_reset --after hard_reset +d1.build.flash_mode=dio +d1.build.flash_flags=-DFLASHMODE_DIO +d1.build.flash_freq=40 +d1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +d1.menu.eesz.4M2M.build.flash_size=4M +d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +d1.menu.eesz.4M2M.build.spiffs_pagesize=256 +d1.menu.eesz.4M2M.upload.maximum_size=1044464 +d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M2M.build.spiffs_start=0x200000 +d1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +d1.menu.eesz.4M2M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +d1.menu.eesz.4M3M.build.flash_size=4M +d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +d1.menu.eesz.4M3M.build.spiffs_pagesize=256 +d1.menu.eesz.4M3M.upload.maximum_size=1044464 +d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M3M.build.spiffs_start=0x100000 +d1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +d1.menu.eesz.4M3M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +d1.menu.eesz.4M1M.build.flash_size=4M +d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +d1.menu.eesz.4M1M.build.spiffs_pagesize=256 +d1.menu.eesz.4M1M.upload.maximum_size=1044464 +d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +d1.menu.eesz.4M1M.build.spiffs_start=0x300000 +d1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +d1.menu.eesz.4M1M.build.spiffs_blocksize=8192 +d1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +d1.menu.eesz.4M.build.flash_size=4M +d1.menu.eesz.4M.build.flash_size_bytes=0x400000 +d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +d1.menu.eesz.4M.build.spiffs_pagesize=256 +d1.menu.eesz.4M.upload.maximum_size=1044464 +d1.menu.eesz.4M.build.rfcal_addr=0x3FC000 +d1.menu.ip.lm2f=v2 Lower Memory +d1.menu.ip.lm2f.build.lwip_include=lwip2/include +d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1.menu.ip.hb2f=v2 Higher Bandwidth +d1.menu.ip.hb2f.build.lwip_include=lwip2/include +d1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +d1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +d1.menu.ip.lm2n=v2 Lower Memory (no features) +d1.menu.ip.lm2n.build.lwip_include=lwip2/include +d1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +d1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1.menu.ip.hb2n=v2 Higher Bandwidth (no features) +d1.menu.ip.hb2n.build.lwip_include=lwip2/include +d1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +d1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +d1.menu.ip.lm6f=v2 IPv6 Lower Memory +d1.menu.ip.lm6f.build.lwip_include=lwip2/include +d1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +d1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +d1.menu.ip.hb6f.build.lwip_include=lwip2/include +d1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +d1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +d1.menu.ip.hb1=v1.4 Higher Bandwidth +d1.menu.ip.hb1.build.lwip_lib=-llwip_gcc +d1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +d1.menu.ip.src=v1.4 Compile from source +d1.menu.ip.src.build.lwip_lib=-llwip_src +d1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +d1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +d1.menu.dbg.Disabled=Disabled +d1.menu.dbg.Disabled.build.debug_port= +d1.menu.dbg.Serial=Serial +d1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +d1.menu.dbg.Serial1=Serial1 +d1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +d1.menu.lvl.None____=None +d1.menu.lvl.None____.build.debug_level= +d1.menu.lvl.SSL=SSL +d1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +d1.menu.lvl.TLS_MEM=TLS_MEM +d1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +d1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +d1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.HTTP_SERVER=HTTP_SERVER +d1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +d1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +d1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +d1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +d1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +d1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +d1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +d1.menu.lvl.CORE=CORE +d1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +d1.menu.lvl.WIFI=WIFI +d1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +d1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +d1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +d1.menu.lvl.UPDATER=UPDATER +d1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +d1.menu.lvl.OTA=OTA +d1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +d1.menu.lvl.OOM=OOM +d1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +d1.menu.lvl.MDNS=MDNS +d1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +d1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +d1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +d1.menu.wipe.none=Only Sketch +d1.menu.wipe.none.upload.erase_cmd= +d1.menu.wipe.sdk=Sketch + WiFi Settings +d1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +d1.menu.wipe.all=All Flash Contents +d1.menu.wipe.all.upload.erase_cmd=erase_flash +d1.menu.baud.921600=921600 +d1.menu.baud.921600.upload.speed=921600 +d1.menu.baud.57600=57600 +d1.menu.baud.57600.upload.speed=57600 +d1.menu.baud.115200=115200 +d1.menu.baud.115200.upload.speed=115200 +d1.menu.baud.230400.linux=230400 +d1.menu.baud.230400.macosx=230400 +d1.menu.baud.230400.upload.speed=230400 +d1.menu.baud.256000.windows=256000 +d1.menu.baud.256000.upload.speed=256000 +d1.menu.baud.460800.linux=460800 +d1.menu.baud.460800.macosx=460800 +d1.menu.baud.460800.upload.speed=460800 +d1.menu.baud.512000.windows=512000 +d1.menu.baud.512000.upload.speed=512000 +d1.menu.baud.3000000=3000000 +d1.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espino.name=ESPino (ESP-12 Module) +espino.build.board=ESP8266_ESP12 +espino.build.variant=espino +espino.upload.tool=esptool +espino.upload.maximum_data_size=81920 +espino.upload.wait_for_upload_port=true +espino.upload.erase_cmd= +espino.serial.disableDTR=true +espino.serial.disableRTS=true +espino.build.mcu=esp8266 +espino.build.core=esp8266 +espino.build.spiffs_pagesize=256 +espino.build.debug_port= +espino.build.debug_level= +espino.menu.xtal.80=80 MHz +espino.menu.xtal.80.build.f_cpu=80000000L +espino.menu.xtal.160=160 MHz +espino.menu.xtal.160.build.f_cpu=160000000L +espino.menu.vt.flash=Flash +espino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espino.menu.vt.heap=Heap +espino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espino.menu.vt.iram=IRAM +espino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espino.menu.exception.legacy=Legacy (new can return nullptr) +espino.menu.exception.legacy.build.exception_flags=-fno-exceptions +espino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espino.menu.exception.disabled=Disabled (new can abort) +espino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espino.menu.exception.enabled=Enabled +espino.menu.exception.enabled.build.exception_flags=-fexceptions +espino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espino.menu.ssl.all=All SSL ciphers (most compatible) +espino.menu.ssl.all.build.sslflags= +espino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espino.menu.ResetMethod.nodemcu=dtr (aka nodemcu) +espino.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset +espino.menu.ResetMethod.ck=no dtr (aka ck) +espino.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset +espino.build.flash_mode=qio +espino.build.flash_flags=-DFLASHMODE_QIO +espino.build.flash_freq=40 +espino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espino.menu.eesz.4M2M.build.flash_size=4M +espino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espino.menu.eesz.4M2M.build.spiffs_pagesize=256 +espino.menu.eesz.4M2M.upload.maximum_size=1044464 +espino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M2M.build.spiffs_start=0x200000 +espino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espino.menu.eesz.4M3M.build.flash_size=4M +espino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espino.menu.eesz.4M3M.build.spiffs_pagesize=256 +espino.menu.eesz.4M3M.upload.maximum_size=1044464 +espino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M3M.build.spiffs_start=0x100000 +espino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espino.menu.eesz.4M1M.build.flash_size=4M +espino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espino.menu.eesz.4M1M.build.spiffs_pagesize=256 +espino.menu.eesz.4M1M.upload.maximum_size=1044464 +espino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espino.menu.eesz.4M1M.build.spiffs_start=0x300000 +espino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espino.menu.eesz.4M.build.flash_size=4M +espino.menu.eesz.4M.build.flash_size_bytes=0x400000 +espino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espino.menu.eesz.4M.build.spiffs_pagesize=256 +espino.menu.eesz.4M.upload.maximum_size=1044464 +espino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espino.menu.ip.lm2f=v2 Lower Memory +espino.menu.ip.lm2f.build.lwip_include=lwip2/include +espino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espino.menu.ip.hb2f=v2 Higher Bandwidth +espino.menu.ip.hb2f.build.lwip_include=lwip2/include +espino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espino.menu.ip.lm2n=v2 Lower Memory (no features) +espino.menu.ip.lm2n.build.lwip_include=lwip2/include +espino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espino.menu.ip.hb2n.build.lwip_include=lwip2/include +espino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espino.menu.ip.lm6f=v2 IPv6 Lower Memory +espino.menu.ip.lm6f.build.lwip_include=lwip2/include +espino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espino.menu.ip.hb6f.build.lwip_include=lwip2/include +espino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espino.menu.ip.hb1=v1.4 Higher Bandwidth +espino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espino.menu.ip.src=v1.4 Compile from source +espino.menu.ip.src.build.lwip_lib=-llwip_src +espino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espino.menu.dbg.Disabled=Disabled +espino.menu.dbg.Disabled.build.debug_port= +espino.menu.dbg.Serial=Serial +espino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espino.menu.dbg.Serial1=Serial1 +espino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espino.menu.lvl.None____=None +espino.menu.lvl.None____.build.debug_level= +espino.menu.lvl.SSL=SSL +espino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espino.menu.lvl.TLS_MEM=TLS_MEM +espino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.HTTP_SERVER=HTTP_SERVER +espino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espino.menu.lvl.CORE=CORE +espino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espino.menu.lvl.WIFI=WIFI +espino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espino.menu.lvl.UPDATER=UPDATER +espino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espino.menu.lvl.OTA=OTA +espino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espino.menu.lvl.OOM=OOM +espino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espino.menu.lvl.MDNS=MDNS +espino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espino.menu.wipe.none=Only Sketch +espino.menu.wipe.none.upload.erase_cmd= +espino.menu.wipe.sdk=Sketch + WiFi Settings +espino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espino.menu.wipe.all=All Flash Contents +espino.menu.wipe.all.upload.erase_cmd=erase_flash +espino.menu.baud.115200=115200 +espino.menu.baud.115200.upload.speed=115200 +espino.menu.baud.57600=57600 +espino.menu.baud.57600.upload.speed=57600 +espino.menu.baud.230400.linux=230400 +espino.menu.baud.230400.macosx=230400 +espino.menu.baud.230400.upload.speed=230400 +espino.menu.baud.256000.windows=256000 +espino.menu.baud.256000.upload.speed=256000 +espino.menu.baud.460800.linux=460800 +espino.menu.baud.460800.macosx=460800 +espino.menu.baud.460800.upload.speed=460800 +espino.menu.baud.512000.windows=512000 +espino.menu.baud.512000.upload.speed=512000 +espino.menu.baud.921600=921600 +espino.menu.baud.921600.upload.speed=921600 +espino.menu.baud.3000000=3000000 +espino.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espinotee.name=ThaiEasyElec's ESPino +espinotee.build.board=ESP8266_ESP13 +espinotee.build.variant=espinotee +espinotee.upload.tool=esptool +espinotee.upload.maximum_data_size=81920 +espinotee.upload.wait_for_upload_port=true +espinotee.upload.erase_cmd= +espinotee.serial.disableDTR=true +espinotee.serial.disableRTS=true +espinotee.build.mcu=esp8266 +espinotee.build.core=esp8266 +espinotee.build.spiffs_pagesize=256 +espinotee.build.debug_port= +espinotee.build.debug_level= +espinotee.menu.xtal.80=80 MHz +espinotee.menu.xtal.80.build.f_cpu=80000000L +espinotee.menu.xtal.160=160 MHz +espinotee.menu.xtal.160.build.f_cpu=160000000L +espinotee.menu.vt.flash=Flash +espinotee.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espinotee.menu.vt.heap=Heap +espinotee.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espinotee.menu.vt.iram=IRAM +espinotee.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espinotee.menu.exception.legacy=Legacy (new can return nullptr) +espinotee.menu.exception.legacy.build.exception_flags=-fno-exceptions +espinotee.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espinotee.menu.exception.disabled=Disabled (new can abort) +espinotee.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espinotee.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espinotee.menu.exception.enabled=Enabled +espinotee.menu.exception.enabled.build.exception_flags=-fexceptions +espinotee.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espinotee.menu.ssl.all=All SSL ciphers (most compatible) +espinotee.menu.ssl.all.build.sslflags= +espinotee.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espinotee.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espinotee.upload.resetmethod=--before default_reset --after hard_reset +espinotee.build.flash_mode=qio +espinotee.build.flash_flags=-DFLASHMODE_QIO +espinotee.build.flash_freq=40 +espinotee.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espinotee.menu.eesz.4M2M.build.flash_size=4M +espinotee.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espinotee.menu.eesz.4M2M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M2M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M2M.build.spiffs_start=0x200000 +espinotee.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espinotee.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espinotee.menu.eesz.4M3M.build.flash_size=4M +espinotee.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espinotee.menu.eesz.4M3M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M3M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M3M.build.spiffs_start=0x100000 +espinotee.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espinotee.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espinotee.menu.eesz.4M1M.build.flash_size=4M +espinotee.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espinotee.menu.eesz.4M1M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M1M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espinotee.menu.eesz.4M1M.build.spiffs_start=0x300000 +espinotee.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espinotee.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espinotee.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espinotee.menu.eesz.4M.build.flash_size=4M +espinotee.menu.eesz.4M.build.flash_size_bytes=0x400000 +espinotee.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espinotee.menu.eesz.4M.build.spiffs_pagesize=256 +espinotee.menu.eesz.4M.upload.maximum_size=1044464 +espinotee.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espinotee.menu.ip.lm2f=v2 Lower Memory +espinotee.menu.ip.lm2f.build.lwip_include=lwip2/include +espinotee.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espinotee.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espinotee.menu.ip.hb2f=v2 Higher Bandwidth +espinotee.menu.ip.hb2f.build.lwip_include=lwip2/include +espinotee.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espinotee.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espinotee.menu.ip.lm2n=v2 Lower Memory (no features) +espinotee.menu.ip.lm2n.build.lwip_include=lwip2/include +espinotee.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espinotee.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espinotee.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espinotee.menu.ip.hb2n.build.lwip_include=lwip2/include +espinotee.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espinotee.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espinotee.menu.ip.lm6f=v2 IPv6 Lower Memory +espinotee.menu.ip.lm6f.build.lwip_include=lwip2/include +espinotee.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espinotee.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espinotee.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espinotee.menu.ip.hb6f.build.lwip_include=lwip2/include +espinotee.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espinotee.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espinotee.menu.ip.hb1=v1.4 Higher Bandwidth +espinotee.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espinotee.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espinotee.menu.ip.src=v1.4 Compile from source +espinotee.menu.ip.src.build.lwip_lib=-llwip_src +espinotee.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espinotee.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espinotee.menu.dbg.Disabled=Disabled +espinotee.menu.dbg.Disabled.build.debug_port= +espinotee.menu.dbg.Serial=Serial +espinotee.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espinotee.menu.dbg.Serial1=Serial1 +espinotee.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espinotee.menu.lvl.None____=None +espinotee.menu.lvl.None____.build.debug_level= +espinotee.menu.lvl.SSL=SSL +espinotee.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espinotee.menu.lvl.TLS_MEM=TLS_MEM +espinotee.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espinotee.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espinotee.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.HTTP_SERVER=HTTP_SERVER +espinotee.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espinotee.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espinotee.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espinotee.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espinotee.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espinotee.menu.lvl.CORE=CORE +espinotee.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espinotee.menu.lvl.WIFI=WIFI +espinotee.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espinotee.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espinotee.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espinotee.menu.lvl.UPDATER=UPDATER +espinotee.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espinotee.menu.lvl.OTA=OTA +espinotee.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espinotee.menu.lvl.OOM=OOM +espinotee.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espinotee.menu.lvl.MDNS=MDNS +espinotee.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espinotee.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espinotee.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espinotee.menu.wipe.none=Only Sketch +espinotee.menu.wipe.none.upload.erase_cmd= +espinotee.menu.wipe.sdk=Sketch + WiFi Settings +espinotee.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espinotee.menu.wipe.all=All Flash Contents +espinotee.menu.wipe.all.upload.erase_cmd=erase_flash +espinotee.menu.baud.115200=115200 +espinotee.menu.baud.115200.upload.speed=115200 +espinotee.menu.baud.57600=57600 +espinotee.menu.baud.57600.upload.speed=57600 +espinotee.menu.baud.230400.linux=230400 +espinotee.menu.baud.230400.macosx=230400 +espinotee.menu.baud.230400.upload.speed=230400 +espinotee.menu.baud.256000.windows=256000 +espinotee.menu.baud.256000.upload.speed=256000 +espinotee.menu.baud.460800.linux=460800 +espinotee.menu.baud.460800.macosx=460800 +espinotee.menu.baud.460800.upload.speed=460800 +espinotee.menu.baud.512000.windows=512000 +espinotee.menu.baud.512000.upload.speed=512000 +espinotee.menu.baud.921600=921600 +espinotee.menu.baud.921600.upload.speed=921600 +espinotee.menu.baud.3000000=3000000 +espinotee.menu.baud.3000000.upload.speed=3000000 + +############################################################## +wifinfo.name=WifInfo +wifinfo.build.board=WIFINFO +wifinfo.build.variant=wifinfo +wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) +wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 +wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld +wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M +wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 +wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 +wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 +wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 +wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) +wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 +wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld +wifinfo.menu.ESPModule.ESP12.build.flash_size=4M +wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 +wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 +wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 +wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 +wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 +wifinfo.upload.tool=esptool +wifinfo.upload.maximum_data_size=81920 +wifinfo.upload.wait_for_upload_port=true +wifinfo.upload.erase_cmd= +wifinfo.serial.disableDTR=true +wifinfo.serial.disableRTS=true +wifinfo.build.mcu=esp8266 +wifinfo.build.core=esp8266 +wifinfo.build.spiffs_pagesize=256 +wifinfo.build.debug_port= +wifinfo.build.debug_level= +wifinfo.menu.xtal.80=80 MHz +wifinfo.menu.xtal.80.build.f_cpu=80000000L +wifinfo.menu.xtal.160=160 MHz +wifinfo.menu.xtal.160.build.f_cpu=160000000L +wifinfo.menu.vt.flash=Flash +wifinfo.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifinfo.menu.vt.heap=Heap +wifinfo.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifinfo.menu.vt.iram=IRAM +wifinfo.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifinfo.menu.exception.legacy=Legacy (new can return nullptr) +wifinfo.menu.exception.legacy.build.exception_flags=-fno-exceptions +wifinfo.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +wifinfo.menu.exception.disabled=Disabled (new can abort) +wifinfo.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +wifinfo.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifinfo.menu.exception.enabled=Enabled +wifinfo.menu.exception.enabled.build.exception_flags=-fexceptions +wifinfo.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifinfo.menu.ssl.all=All SSL ciphers (most compatible) +wifinfo.menu.ssl.all.build.sslflags= +wifinfo.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +wifinfo.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +wifinfo.upload.resetmethod=--before default_reset --after hard_reset +wifinfo.build.flash_mode=qio +wifinfo.build.flash_flags=-DFLASHMODE_QIO +wifinfo.menu.FlashFreq.40=40MHz +wifinfo.menu.FlashFreq.40.build.flash_freq=40 +wifinfo.menu.FlashFreq.80=80MHz +wifinfo.menu.FlashFreq.80.build.flash_freq=80 +wifinfo.menu.FlashFreq.20=20MHz +wifinfo.menu.FlashFreq.20.build.flash_freq=20 +wifinfo.menu.FlashFreq.26=26MHz +wifinfo.menu.FlashFreq.26.build.flash_freq=26 +wifinfo.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +wifinfo.menu.eesz.1M64.build.flash_size=1M +wifinfo.menu.eesz.1M64.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +wifinfo.menu.eesz.1M64.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M64.upload.maximum_size=958448 +wifinfo.menu.eesz.1M64.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M64.build.spiffs_start=0xEB000 +wifinfo.menu.eesz.1M64.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M64.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +wifinfo.menu.eesz.1M128.build.flash_size=1M +wifinfo.menu.eesz.1M128.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +wifinfo.menu.eesz.1M128.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M128.upload.maximum_size=892912 +wifinfo.menu.eesz.1M128.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M128.build.spiffs_start=0xDB000 +wifinfo.menu.eesz.1M128.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M128.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +wifinfo.menu.eesz.1M144.build.flash_size=1M +wifinfo.menu.eesz.1M144.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +wifinfo.menu.eesz.1M144.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M144.upload.maximum_size=876528 +wifinfo.menu.eesz.1M144.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M144.build.spiffs_start=0xD7000 +wifinfo.menu.eesz.1M144.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M144.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +wifinfo.menu.eesz.1M160.build.flash_size=1M +wifinfo.menu.eesz.1M160.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +wifinfo.menu.eesz.1M160.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M160.upload.maximum_size=860144 +wifinfo.menu.eesz.1M160.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M160.build.spiffs_start=0xD3000 +wifinfo.menu.eesz.1M160.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M160.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +wifinfo.menu.eesz.1M192.build.flash_size=1M +wifinfo.menu.eesz.1M192.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +wifinfo.menu.eesz.1M192.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M192.upload.maximum_size=827376 +wifinfo.menu.eesz.1M192.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M192.build.spiffs_start=0xCB000 +wifinfo.menu.eesz.1M192.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M192.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +wifinfo.menu.eesz.1M256.build.flash_size=1M +wifinfo.menu.eesz.1M256.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +wifinfo.menu.eesz.1M256.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M256.upload.maximum_size=761840 +wifinfo.menu.eesz.1M256.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M256.build.spiffs_start=0xBB000 +wifinfo.menu.eesz.1M256.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M256.build.spiffs_blocksize=4096 +wifinfo.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +wifinfo.menu.eesz.1M512.build.flash_size=1M +wifinfo.menu.eesz.1M512.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +wifinfo.menu.eesz.1M512.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M512.upload.maximum_size=499696 +wifinfo.menu.eesz.1M512.build.rfcal_addr=0xFC000 +wifinfo.menu.eesz.1M512.build.spiffs_start=0x7B000 +wifinfo.menu.eesz.1M512.build.spiffs_end=0xFB000 +wifinfo.menu.eesz.1M512.build.spiffs_blocksize=8192 +wifinfo.menu.eesz.1M=1MB (FS:none OTA:~502KB) +wifinfo.menu.eesz.1M.build.flash_size=1M +wifinfo.menu.eesz.1M.build.flash_size_bytes=0x100000 +wifinfo.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +wifinfo.menu.eesz.1M.build.spiffs_pagesize=256 +wifinfo.menu.eesz.1M.upload.maximum_size=1023984 +wifinfo.menu.eesz.1M.build.rfcal_addr=0xFC000 +wifinfo.menu.ip.lm2f=v2 Lower Memory +wifinfo.menu.ip.lm2f.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifinfo.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifinfo.menu.ip.hb2f=v2 Higher Bandwidth +wifinfo.menu.ip.hb2f.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifinfo.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifinfo.menu.ip.lm2n=v2 Lower Memory (no features) +wifinfo.menu.ip.lm2n.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifinfo.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifinfo.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifinfo.menu.ip.hb2n.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifinfo.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifinfo.menu.ip.lm6f=v2 IPv6 Lower Memory +wifinfo.menu.ip.lm6f.build.lwip_include=lwip2/include +wifinfo.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifinfo.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifinfo.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifinfo.menu.ip.hb6f.build.lwip_include=lwip2/include +wifinfo.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifinfo.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifinfo.menu.ip.hb1=v1.4 Higher Bandwidth +wifinfo.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifinfo.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifinfo.menu.ip.src=v1.4 Compile from source +wifinfo.menu.ip.src.build.lwip_lib=-llwip_src +wifinfo.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifinfo.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifinfo.menu.dbg.Disabled=Disabled +wifinfo.menu.dbg.Disabled.build.debug_port= +wifinfo.menu.dbg.Serial=Serial +wifinfo.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifinfo.menu.dbg.Serial1=Serial1 +wifinfo.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifinfo.menu.lvl.None____=None +wifinfo.menu.lvl.None____.build.debug_level= +wifinfo.menu.lvl.SSL=SSL +wifinfo.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifinfo.menu.lvl.TLS_MEM=TLS_MEM +wifinfo.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifinfo.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifinfo.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifinfo.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifinfo.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifinfo.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifinfo.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifinfo.menu.lvl.CORE=CORE +wifinfo.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifinfo.menu.lvl.WIFI=WIFI +wifinfo.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifinfo.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifinfo.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifinfo.menu.lvl.UPDATER=UPDATER +wifinfo.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifinfo.menu.lvl.OTA=OTA +wifinfo.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifinfo.menu.lvl.OOM=OOM +wifinfo.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifinfo.menu.lvl.MDNS=MDNS +wifinfo.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifinfo.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifinfo.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifinfo.menu.wipe.none=Only Sketch +wifinfo.menu.wipe.none.upload.erase_cmd= +wifinfo.menu.wipe.sdk=Sketch + WiFi Settings +wifinfo.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +wifinfo.menu.wipe.all=All Flash Contents +wifinfo.menu.wipe.all.upload.erase_cmd=erase_flash +wifinfo.menu.baud.115200=115200 +wifinfo.menu.baud.115200.upload.speed=115200 +wifinfo.menu.baud.57600=57600 +wifinfo.menu.baud.57600.upload.speed=57600 +wifinfo.menu.baud.230400.linux=230400 +wifinfo.menu.baud.230400.macosx=230400 +wifinfo.menu.baud.230400.upload.speed=230400 +wifinfo.menu.baud.256000.windows=256000 +wifinfo.menu.baud.256000.upload.speed=256000 +wifinfo.menu.baud.460800.linux=460800 +wifinfo.menu.baud.460800.macosx=460800 +wifinfo.menu.baud.460800.upload.speed=460800 +wifinfo.menu.baud.512000.windows=512000 +wifinfo.menu.baud.512000.upload.speed=512000 +wifinfo.menu.baud.921600=921600 +wifinfo.menu.baud.921600.upload.speed=921600 +wifinfo.menu.baud.3000000=3000000 +wifinfo.menu.baud.3000000.upload.speed=3000000 + +############################################################## +arduino-esp8266.name=Arduino +arduino-esp8266.build.board=ESP8266_ARDUINO +arduino-esp8266.menu.BoardModel.primo=Primo +arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO +arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi +arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO +arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO +arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart +arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi +arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI +arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 +arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart +arduino-esp8266.upload.tool=esptool +arduino-esp8266.upload.maximum_data_size=81920 +arduino-esp8266.upload.wait_for_upload_port=true +arduino-esp8266.upload.erase_cmd= +arduino-esp8266.serial.disableDTR=true +arduino-esp8266.serial.disableRTS=true +arduino-esp8266.build.mcu=esp8266 +arduino-esp8266.build.core=esp8266 +arduino-esp8266.build.variant=generic +arduino-esp8266.build.spiffs_pagesize=256 +arduino-esp8266.build.debug_port= +arduino-esp8266.build.debug_level= +arduino-esp8266.menu.xtal.80=80 MHz +arduino-esp8266.menu.xtal.80.build.f_cpu=80000000L +arduino-esp8266.menu.xtal.160=160 MHz +arduino-esp8266.menu.xtal.160.build.f_cpu=160000000L +arduino-esp8266.menu.vt.flash=Flash +arduino-esp8266.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +arduino-esp8266.menu.vt.heap=Heap +arduino-esp8266.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +arduino-esp8266.menu.vt.iram=IRAM +arduino-esp8266.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +arduino-esp8266.menu.exception.legacy=Legacy (new can return nullptr) +arduino-esp8266.menu.exception.legacy.build.exception_flags=-fno-exceptions +arduino-esp8266.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +arduino-esp8266.menu.exception.disabled=Disabled (new can abort) +arduino-esp8266.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +arduino-esp8266.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +arduino-esp8266.menu.exception.enabled=Enabled +arduino-esp8266.menu.exception.enabled.build.exception_flags=-fexceptions +arduino-esp8266.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +arduino-esp8266.menu.ssl.all=All SSL ciphers (most compatible) +arduino-esp8266.menu.ssl.all.build.sslflags= +arduino-esp8266.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +arduino-esp8266.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +arduino-esp8266.upload.resetmethod=--before no_reset --after soft_reset +arduino-esp8266.build.flash_mode=qio +arduino-esp8266.build.flash_flags=-DFLASHMODE_QIO +arduino-esp8266.build.flash_freq=40 +arduino-esp8266.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +arduino-esp8266.menu.eesz.4M2M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +arduino-esp8266.menu.eesz.4M2M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M2M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_start=0x200000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +arduino-esp8266.menu.eesz.4M2M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +arduino-esp8266.menu.eesz.4M3M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +arduino-esp8266.menu.eesz.4M3M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M3M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_start=0x100000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +arduino-esp8266.menu.eesz.4M3M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +arduino-esp8266.menu.eesz.4M1M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +arduino-esp8266.menu.eesz.4M1M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M1M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_start=0x300000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +arduino-esp8266.menu.eesz.4M1M.build.spiffs_blocksize=8192 +arduino-esp8266.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +arduino-esp8266.menu.eesz.4M.build.flash_size=4M +arduino-esp8266.menu.eesz.4M.build.flash_size_bytes=0x400000 +arduino-esp8266.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +arduino-esp8266.menu.eesz.4M.build.spiffs_pagesize=256 +arduino-esp8266.menu.eesz.4M.upload.maximum_size=1044464 +arduino-esp8266.menu.eesz.4M.build.rfcal_addr=0x3FC000 +arduino-esp8266.menu.ip.lm2f=v2 Lower Memory +arduino-esp8266.menu.ip.lm2f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +arduino-esp8266.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.hb2f=v2 Higher Bandwidth +arduino-esp8266.menu.ip.hb2f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +arduino-esp8266.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.lm2n=v2 Lower Memory (no features) +arduino-esp8266.menu.ip.lm2n.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +arduino-esp8266.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.hb2n=v2 Higher Bandwidth (no features) +arduino-esp8266.menu.ip.hb2n.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +arduino-esp8266.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +arduino-esp8266.menu.ip.lm6f=v2 IPv6 Lower Memory +arduino-esp8266.menu.ip.lm6f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +arduino-esp8266.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +arduino-esp8266.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +arduino-esp8266.menu.ip.hb6f.build.lwip_include=lwip2/include +arduino-esp8266.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +arduino-esp8266.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +arduino-esp8266.menu.ip.hb1=v1.4 Higher Bandwidth +arduino-esp8266.menu.ip.hb1.build.lwip_lib=-llwip_gcc +arduino-esp8266.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +arduino-esp8266.menu.ip.src=v1.4 Compile from source +arduino-esp8266.menu.ip.src.build.lwip_lib=-llwip_src +arduino-esp8266.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +arduino-esp8266.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +arduino-esp8266.menu.dbg.Disabled=Disabled +arduino-esp8266.menu.dbg.Disabled.build.debug_port= +arduino-esp8266.menu.dbg.Serial=Serial +arduino-esp8266.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +arduino-esp8266.menu.dbg.Serial1=Serial1 +arduino-esp8266.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +arduino-esp8266.menu.lvl.None____=None +arduino-esp8266.menu.lvl.None____.build.debug_level= +arduino-esp8266.menu.lvl.SSL=SSL +arduino-esp8266.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +arduino-esp8266.menu.lvl.TLS_MEM=TLS_MEM +arduino-esp8266.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +arduino-esp8266.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +arduino-esp8266.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.HTTP_SERVER=HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +arduino-esp8266.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +arduino-esp8266.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +arduino-esp8266.menu.lvl.CORE=CORE +arduino-esp8266.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +arduino-esp8266.menu.lvl.WIFI=WIFI +arduino-esp8266.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +arduino-esp8266.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +arduino-esp8266.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +arduino-esp8266.menu.lvl.UPDATER=UPDATER +arduino-esp8266.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +arduino-esp8266.menu.lvl.OTA=OTA +arduino-esp8266.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +arduino-esp8266.menu.lvl.OOM=OOM +arduino-esp8266.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +arduino-esp8266.menu.lvl.MDNS=MDNS +arduino-esp8266.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +arduino-esp8266.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +arduino-esp8266.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +arduino-esp8266.menu.wipe.none=Only Sketch +arduino-esp8266.menu.wipe.none.upload.erase_cmd= +arduino-esp8266.menu.wipe.sdk=Sketch + WiFi Settings +arduino-esp8266.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +arduino-esp8266.menu.wipe.all=All Flash Contents +arduino-esp8266.menu.wipe.all.upload.erase_cmd=erase_flash +arduino-esp8266.menu.baud.115200=115200 +arduino-esp8266.menu.baud.115200.upload.speed=115200 +arduino-esp8266.menu.baud.57600=57600 +arduino-esp8266.menu.baud.57600.upload.speed=57600 +arduino-esp8266.menu.baud.230400.linux=230400 +arduino-esp8266.menu.baud.230400.macosx=230400 +arduino-esp8266.menu.baud.230400.upload.speed=230400 +arduino-esp8266.menu.baud.256000.windows=256000 +arduino-esp8266.menu.baud.256000.upload.speed=256000 +arduino-esp8266.menu.baud.460800.linux=460800 +arduino-esp8266.menu.baud.460800.macosx=460800 +arduino-esp8266.menu.baud.460800.upload.speed=460800 +arduino-esp8266.menu.baud.512000.windows=512000 +arduino-esp8266.menu.baud.512000.upload.speed=512000 +arduino-esp8266.menu.baud.921600=921600 +arduino-esp8266.menu.baud.921600.upload.speed=921600 +arduino-esp8266.menu.baud.3000000=3000000 +arduino-esp8266.menu.baud.3000000.upload.speed=3000000 + +############################################################## +gen4iod.name=4D Systems gen4 IoD Range +gen4iod.build.board=GEN4_IOD +gen4iod.build.f_cpu=160000000L +gen4iod.build.variant=generic +gen4iod.upload.tool=esptool +gen4iod.upload.maximum_data_size=81920 +gen4iod.upload.wait_for_upload_port=true +gen4iod.upload.erase_cmd= +gen4iod.serial.disableDTR=true +gen4iod.serial.disableRTS=true +gen4iod.build.mcu=esp8266 +gen4iod.build.core=esp8266 +gen4iod.build.spiffs_pagesize=256 +gen4iod.build.debug_port= +gen4iod.build.debug_level= +gen4iod.menu.xtal.80=80 MHz +gen4iod.menu.xtal.80.build.f_cpu=80000000L +gen4iod.menu.xtal.160=160 MHz +gen4iod.menu.xtal.160.build.f_cpu=160000000L +gen4iod.menu.vt.flash=Flash +gen4iod.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +gen4iod.menu.vt.heap=Heap +gen4iod.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +gen4iod.menu.vt.iram=IRAM +gen4iod.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +gen4iod.menu.exception.legacy=Legacy (new can return nullptr) +gen4iod.menu.exception.legacy.build.exception_flags=-fno-exceptions +gen4iod.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +gen4iod.menu.exception.disabled=Disabled (new can abort) +gen4iod.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +gen4iod.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +gen4iod.menu.exception.enabled=Enabled +gen4iod.menu.exception.enabled.build.exception_flags=-fexceptions +gen4iod.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +gen4iod.menu.ssl.all=All SSL ciphers (most compatible) +gen4iod.menu.ssl.all.build.sslflags= +gen4iod.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +gen4iod.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +gen4iod.upload.resetmethod=--before default_reset --after hard_reset +gen4iod.build.flash_mode=dio +gen4iod.build.flash_flags=-DFLASHMODE_DIO +gen4iod.build.flash_freq=80 +gen4iod.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) +gen4iod.menu.eesz.512K32.build.flash_size=512K +gen4iod.menu.eesz.512K32.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld +gen4iod.menu.eesz.512K32.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K32.upload.maximum_size=466928 +gen4iod.menu.eesz.512K32.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K32.build.spiffs_start=0x73000 +gen4iod.menu.eesz.512K32.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K32.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) +gen4iod.menu.eesz.512K64.build.flash_size=512K +gen4iod.menu.eesz.512K64.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld +gen4iod.menu.eesz.512K64.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K64.upload.maximum_size=434160 +gen4iod.menu.eesz.512K64.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K64.build.spiffs_start=0x6B000 +gen4iod.menu.eesz.512K64.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K64.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) +gen4iod.menu.eesz.512K128.build.flash_size=512K +gen4iod.menu.eesz.512K128.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld +gen4iod.menu.eesz.512K128.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K128.upload.maximum_size=368624 +gen4iod.menu.eesz.512K128.build.rfcal_addr=0x7C000 +gen4iod.menu.eesz.512K128.build.spiffs_start=0x5B000 +gen4iod.menu.eesz.512K128.build.spiffs_end=0x7B000 +gen4iod.menu.eesz.512K128.build.spiffs_blocksize=4096 +gen4iod.menu.eesz.512K=512KB (FS:none OTA:~246KB) +gen4iod.menu.eesz.512K.build.flash_size=512K +gen4iod.menu.eesz.512K.build.flash_size_bytes=0x80000 +gen4iod.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld +gen4iod.menu.eesz.512K.build.spiffs_pagesize=256 +gen4iod.menu.eesz.512K.upload.maximum_size=499696 +gen4iod.menu.eesz.512K.build.rfcal_addr=0x7C000 +gen4iod.menu.ip.lm2f=v2 Lower Memory +gen4iod.menu.ip.lm2f.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +gen4iod.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +gen4iod.menu.ip.hb2f=v2 Higher Bandwidth +gen4iod.menu.ip.hb2f.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +gen4iod.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +gen4iod.menu.ip.lm2n=v2 Lower Memory (no features) +gen4iod.menu.ip.lm2n.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +gen4iod.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +gen4iod.menu.ip.hb2n=v2 Higher Bandwidth (no features) +gen4iod.menu.ip.hb2n.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +gen4iod.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +gen4iod.menu.ip.lm6f=v2 IPv6 Lower Memory +gen4iod.menu.ip.lm6f.build.lwip_include=lwip2/include +gen4iod.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +gen4iod.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +gen4iod.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +gen4iod.menu.ip.hb6f.build.lwip_include=lwip2/include +gen4iod.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +gen4iod.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +gen4iod.menu.ip.hb1=v1.4 Higher Bandwidth +gen4iod.menu.ip.hb1.build.lwip_lib=-llwip_gcc +gen4iod.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +gen4iod.menu.ip.src=v1.4 Compile from source +gen4iod.menu.ip.src.build.lwip_lib=-llwip_src +gen4iod.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +gen4iod.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +gen4iod.menu.dbg.Disabled=Disabled +gen4iod.menu.dbg.Disabled.build.debug_port= +gen4iod.menu.dbg.Serial=Serial +gen4iod.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +gen4iod.menu.dbg.Serial1=Serial1 +gen4iod.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +gen4iod.menu.lvl.None____=None +gen4iod.menu.lvl.None____.build.debug_level= +gen4iod.menu.lvl.SSL=SSL +gen4iod.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +gen4iod.menu.lvl.TLS_MEM=TLS_MEM +gen4iod.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +gen4iod.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +gen4iod.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.HTTP_SERVER=HTTP_SERVER +gen4iod.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +gen4iod.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +gen4iod.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +gen4iod.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +gen4iod.menu.lvl.CORE=CORE +gen4iod.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +gen4iod.menu.lvl.WIFI=WIFI +gen4iod.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +gen4iod.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +gen4iod.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +gen4iod.menu.lvl.UPDATER=UPDATER +gen4iod.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +gen4iod.menu.lvl.OTA=OTA +gen4iod.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +gen4iod.menu.lvl.OOM=OOM +gen4iod.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +gen4iod.menu.lvl.MDNS=MDNS +gen4iod.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +gen4iod.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +gen4iod.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +gen4iod.menu.wipe.none=Only Sketch +gen4iod.menu.wipe.none.upload.erase_cmd= +gen4iod.menu.wipe.sdk=Sketch + WiFi Settings +gen4iod.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +gen4iod.menu.wipe.all=All Flash Contents +gen4iod.menu.wipe.all.upload.erase_cmd=erase_flash +gen4iod.menu.baud.115200=115200 +gen4iod.menu.baud.115200.upload.speed=115200 +gen4iod.menu.baud.57600=57600 +gen4iod.menu.baud.57600.upload.speed=57600 +gen4iod.menu.baud.230400.linux=230400 +gen4iod.menu.baud.230400.macosx=230400 +gen4iod.menu.baud.230400.upload.speed=230400 +gen4iod.menu.baud.256000.windows=256000 +gen4iod.menu.baud.256000.upload.speed=256000 +gen4iod.menu.baud.460800.linux=460800 +gen4iod.menu.baud.460800.macosx=460800 +gen4iod.menu.baud.460800.upload.speed=460800 +gen4iod.menu.baud.512000.windows=512000 +gen4iod.menu.baud.512000.upload.speed=512000 +gen4iod.menu.baud.921600=921600 +gen4iod.menu.baud.921600.upload.speed=921600 +gen4iod.menu.baud.3000000=3000000 +gen4iod.menu.baud.3000000.upload.speed=3000000 + +############################################################## +oak.name=Digistump Oak +oak.build.board=ESP8266_OAK +oak.build.variant=oak +oak.upload.maximum_size=1040368 +oak.upload.tool=esptool +oak.upload.maximum_data_size=81920 +oak.upload.wait_for_upload_port=true +oak.upload.erase_cmd= +oak.serial.disableDTR=true +oak.serial.disableRTS=true +oak.build.mcu=esp8266 +oak.build.core=esp8266 +oak.build.spiffs_pagesize=256 +oak.build.debug_port= +oak.build.debug_level= +oak.menu.xtal.80=80 MHz +oak.menu.xtal.80.build.f_cpu=80000000L +oak.menu.xtal.160=160 MHz +oak.menu.xtal.160.build.f_cpu=160000000L +oak.menu.vt.flash=Flash +oak.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +oak.menu.vt.heap=Heap +oak.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +oak.menu.vt.iram=IRAM +oak.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +oak.menu.exception.legacy=Legacy (new can return nullptr) +oak.menu.exception.legacy.build.exception_flags=-fno-exceptions +oak.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +oak.menu.exception.disabled=Disabled (new can abort) +oak.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +oak.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +oak.menu.exception.enabled=Enabled +oak.menu.exception.enabled.build.exception_flags=-fexceptions +oak.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +oak.menu.ssl.all=All SSL ciphers (most compatible) +oak.menu.ssl.all.build.sslflags= +oak.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +oak.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +oak.upload.resetmethod=--before no_reset --after soft_reset +oak.build.flash_mode=dio +oak.build.flash_flags=-DFLASHMODE_DIO +oak.build.flash_freq=40 +oak.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +oak.menu.eesz.4M2M.build.flash_size=4M +oak.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +oak.menu.eesz.4M2M.build.spiffs_pagesize=256 +oak.menu.eesz.4M2M.upload.maximum_size=1044464 +oak.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M2M.build.spiffs_start=0x200000 +oak.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +oak.menu.eesz.4M2M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +oak.menu.eesz.4M3M.build.flash_size=4M +oak.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +oak.menu.eesz.4M3M.build.spiffs_pagesize=256 +oak.menu.eesz.4M3M.upload.maximum_size=1044464 +oak.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M3M.build.spiffs_start=0x100000 +oak.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +oak.menu.eesz.4M3M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +oak.menu.eesz.4M1M.build.flash_size=4M +oak.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +oak.menu.eesz.4M1M.build.spiffs_pagesize=256 +oak.menu.eesz.4M1M.upload.maximum_size=1044464 +oak.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +oak.menu.eesz.4M1M.build.spiffs_start=0x300000 +oak.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +oak.menu.eesz.4M1M.build.spiffs_blocksize=8192 +oak.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +oak.menu.eesz.4M.build.flash_size=4M +oak.menu.eesz.4M.build.flash_size_bytes=0x400000 +oak.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +oak.menu.eesz.4M.build.spiffs_pagesize=256 +oak.menu.eesz.4M.upload.maximum_size=1044464 +oak.menu.eesz.4M.build.rfcal_addr=0x3FC000 +oak.menu.ip.lm2f=v2 Lower Memory +oak.menu.ip.lm2f.build.lwip_include=lwip2/include +oak.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +oak.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +oak.menu.ip.hb2f=v2 Higher Bandwidth +oak.menu.ip.hb2f.build.lwip_include=lwip2/include +oak.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +oak.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +oak.menu.ip.lm2n=v2 Lower Memory (no features) +oak.menu.ip.lm2n.build.lwip_include=lwip2/include +oak.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +oak.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +oak.menu.ip.hb2n=v2 Higher Bandwidth (no features) +oak.menu.ip.hb2n.build.lwip_include=lwip2/include +oak.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +oak.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +oak.menu.ip.lm6f=v2 IPv6 Lower Memory +oak.menu.ip.lm6f.build.lwip_include=lwip2/include +oak.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +oak.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +oak.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +oak.menu.ip.hb6f.build.lwip_include=lwip2/include +oak.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +oak.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +oak.menu.ip.hb1=v1.4 Higher Bandwidth +oak.menu.ip.hb1.build.lwip_lib=-llwip_gcc +oak.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +oak.menu.ip.src=v1.4 Compile from source +oak.menu.ip.src.build.lwip_lib=-llwip_src +oak.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +oak.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +oak.menu.dbg.Disabled=Disabled +oak.menu.dbg.Disabled.build.debug_port= +oak.menu.dbg.Serial=Serial +oak.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +oak.menu.dbg.Serial1=Serial1 +oak.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +oak.menu.lvl.None____=None +oak.menu.lvl.None____.build.debug_level= +oak.menu.lvl.SSL=SSL +oak.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +oak.menu.lvl.TLS_MEM=TLS_MEM +oak.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +oak.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +oak.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.HTTP_SERVER=HTTP_SERVER +oak.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +oak.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +oak.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +oak.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +oak.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +oak.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +oak.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +oak.menu.lvl.CORE=CORE +oak.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +oak.menu.lvl.WIFI=WIFI +oak.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +oak.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +oak.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +oak.menu.lvl.UPDATER=UPDATER +oak.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +oak.menu.lvl.OTA=OTA +oak.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +oak.menu.lvl.OOM=OOM +oak.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +oak.menu.lvl.MDNS=MDNS +oak.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +oak.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +oak.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +oak.menu.wipe.none=Only Sketch +oak.menu.wipe.none.upload.erase_cmd= +oak.menu.wipe.sdk=Sketch + WiFi Settings +oak.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +oak.menu.wipe.all=All Flash Contents +oak.menu.wipe.all.upload.erase_cmd=erase_flash +oak.menu.baud.921600=921600 +oak.menu.baud.921600.upload.speed=921600 +oak.menu.baud.57600=57600 +oak.menu.baud.57600.upload.speed=57600 +oak.menu.baud.115200=115200 +oak.menu.baud.115200.upload.speed=115200 +oak.menu.baud.230400.linux=230400 +oak.menu.baud.230400.macosx=230400 +oak.menu.baud.230400.upload.speed=230400 +oak.menu.baud.256000.windows=256000 +oak.menu.baud.256000.upload.speed=256000 +oak.menu.baud.460800.linux=460800 +oak.menu.baud.460800.macosx=460800 +oak.menu.baud.460800.upload.speed=460800 +oak.menu.baud.512000.windows=512000 +oak.menu.baud.512000.upload.speed=512000 +oak.menu.baud.3000000=3000000 +oak.menu.baud.3000000.upload.speed=3000000 + +############################################################## +wifiduino.name=WiFiduino +wifiduino.build.board=WIFIDUINO_ESP8266 +wifiduino.build.variant=wifiduino +wifiduino.upload.tool=esptool +wifiduino.upload.maximum_data_size=81920 +wifiduino.upload.wait_for_upload_port=true +wifiduino.upload.erase_cmd= +wifiduino.serial.disableDTR=true +wifiduino.serial.disableRTS=true +wifiduino.build.mcu=esp8266 +wifiduino.build.core=esp8266 +wifiduino.build.spiffs_pagesize=256 +wifiduino.build.debug_port= +wifiduino.build.debug_level= +wifiduino.menu.xtal.80=80 MHz +wifiduino.menu.xtal.80.build.f_cpu=80000000L +wifiduino.menu.xtal.160=160 MHz +wifiduino.menu.xtal.160.build.f_cpu=160000000L +wifiduino.menu.vt.flash=Flash +wifiduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifiduino.menu.vt.heap=Heap +wifiduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifiduino.menu.vt.iram=IRAM +wifiduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifiduino.menu.exception.legacy=Legacy (new can return nullptr) +wifiduino.menu.exception.legacy.build.exception_flags=-fno-exceptions +wifiduino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +wifiduino.menu.exception.disabled=Disabled (new can abort) +wifiduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +wifiduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifiduino.menu.exception.enabled=Enabled +wifiduino.menu.exception.enabled.build.exception_flags=-fexceptions +wifiduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifiduino.menu.ssl.all=All SSL ciphers (most compatible) +wifiduino.menu.ssl.all.build.sslflags= +wifiduino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +wifiduino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +wifiduino.upload.resetmethod=--before default_reset --after hard_reset +wifiduino.build.flash_mode=dio +wifiduino.build.flash_flags=-DFLASHMODE_DIO +wifiduino.build.flash_freq=40 +wifiduino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +wifiduino.menu.eesz.4M2M.build.flash_size=4M +wifiduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +wifiduino.menu.eesz.4M2M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M2M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M2M.build.spiffs_start=0x200000 +wifiduino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +wifiduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +wifiduino.menu.eesz.4M3M.build.flash_size=4M +wifiduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +wifiduino.menu.eesz.4M3M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M3M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M3M.build.spiffs_start=0x100000 +wifiduino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +wifiduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +wifiduino.menu.eesz.4M1M.build.flash_size=4M +wifiduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +wifiduino.menu.eesz.4M1M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M1M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +wifiduino.menu.eesz.4M1M.build.spiffs_start=0x300000 +wifiduino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +wifiduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 +wifiduino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +wifiduino.menu.eesz.4M.build.flash_size=4M +wifiduino.menu.eesz.4M.build.flash_size_bytes=0x400000 +wifiduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +wifiduino.menu.eesz.4M.build.spiffs_pagesize=256 +wifiduino.menu.eesz.4M.upload.maximum_size=1044464 +wifiduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 +wifiduino.menu.ip.lm2f=v2 Lower Memory +wifiduino.menu.ip.lm2f.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifiduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifiduino.menu.ip.hb2f=v2 Higher Bandwidth +wifiduino.menu.ip.hb2f.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifiduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifiduino.menu.ip.lm2n=v2 Lower Memory (no features) +wifiduino.menu.ip.lm2n.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifiduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifiduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifiduino.menu.ip.hb2n.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifiduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifiduino.menu.ip.lm6f=v2 IPv6 Lower Memory +wifiduino.menu.ip.lm6f.build.lwip_include=lwip2/include +wifiduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifiduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifiduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifiduino.menu.ip.hb6f.build.lwip_include=lwip2/include +wifiduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifiduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifiduino.menu.ip.hb1=v1.4 Higher Bandwidth +wifiduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifiduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifiduino.menu.ip.src=v1.4 Compile from source +wifiduino.menu.ip.src.build.lwip_lib=-llwip_src +wifiduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifiduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifiduino.menu.dbg.Disabled=Disabled +wifiduino.menu.dbg.Disabled.build.debug_port= +wifiduino.menu.dbg.Serial=Serial +wifiduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifiduino.menu.dbg.Serial1=Serial1 +wifiduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifiduino.menu.lvl.None____=None +wifiduino.menu.lvl.None____.build.debug_level= +wifiduino.menu.lvl.SSL=SSL +wifiduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifiduino.menu.lvl.TLS_MEM=TLS_MEM +wifiduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifiduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifiduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifiduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifiduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifiduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifiduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifiduino.menu.lvl.CORE=CORE +wifiduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifiduino.menu.lvl.WIFI=WIFI +wifiduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifiduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifiduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifiduino.menu.lvl.UPDATER=UPDATER +wifiduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifiduino.menu.lvl.OTA=OTA +wifiduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifiduino.menu.lvl.OOM=OOM +wifiduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifiduino.menu.lvl.MDNS=MDNS +wifiduino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifiduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifiduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifiduino.menu.wipe.none=Only Sketch +wifiduino.menu.wipe.none.upload.erase_cmd= +wifiduino.menu.wipe.sdk=Sketch + WiFi Settings +wifiduino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +wifiduino.menu.wipe.all=All Flash Contents +wifiduino.menu.wipe.all.upload.erase_cmd=erase_flash +wifiduino.menu.baud.921600=921600 +wifiduino.menu.baud.921600.upload.speed=921600 +wifiduino.menu.baud.57600=57600 +wifiduino.menu.baud.57600.upload.speed=57600 +wifiduino.menu.baud.115200=115200 +wifiduino.menu.baud.115200.upload.speed=115200 +wifiduino.menu.baud.230400.linux=230400 +wifiduino.menu.baud.230400.macosx=230400 +wifiduino.menu.baud.230400.upload.speed=230400 +wifiduino.menu.baud.256000.windows=256000 +wifiduino.menu.baud.256000.upload.speed=256000 +wifiduino.menu.baud.460800.linux=460800 +wifiduino.menu.baud.460800.macosx=460800 +wifiduino.menu.baud.460800.upload.speed=460800 +wifiduino.menu.baud.512000.windows=512000 +wifiduino.menu.baud.512000.upload.speed=512000 +wifiduino.menu.baud.3000000=3000000 +wifiduino.menu.baud.3000000.upload.speed=3000000 + +############################################################## +wifi_slot.name=Amperka WiFi Slot +wifi_slot.build.board=AMPERKA_WIFI_SLOT +wifi_slot.build.variant=wifi_slot +wifi_slot.upload.tool=esptool +wifi_slot.upload.maximum_data_size=81920 +wifi_slot.upload.wait_for_upload_port=true +wifi_slot.upload.erase_cmd= +wifi_slot.serial.disableDTR=true +wifi_slot.serial.disableRTS=true +wifi_slot.build.mcu=esp8266 +wifi_slot.build.core=esp8266 +wifi_slot.build.spiffs_pagesize=256 +wifi_slot.build.debug_port= +wifi_slot.build.debug_level= +wifi_slot.menu.xtal.80=80 MHz +wifi_slot.menu.xtal.80.build.f_cpu=80000000L +wifi_slot.menu.xtal.160=160 MHz +wifi_slot.menu.xtal.160.build.f_cpu=160000000L +wifi_slot.menu.vt.flash=Flash +wifi_slot.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wifi_slot.menu.vt.heap=Heap +wifi_slot.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wifi_slot.menu.vt.iram=IRAM +wifi_slot.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wifi_slot.menu.exception.legacy=Legacy (new can return nullptr) +wifi_slot.menu.exception.legacy.build.exception_flags=-fno-exceptions +wifi_slot.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +wifi_slot.menu.exception.disabled=Disabled (new can abort) +wifi_slot.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +wifi_slot.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wifi_slot.menu.exception.enabled=Enabled +wifi_slot.menu.exception.enabled.build.exception_flags=-fexceptions +wifi_slot.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wifi_slot.menu.ssl.all=All SSL ciphers (most compatible) +wifi_slot.menu.ssl.all.build.sslflags= +wifi_slot.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +wifi_slot.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +wifi_slot.upload.resetmethod=--before default_reset --after hard_reset +wifi_slot.menu.FlashFreq.40=40MHz +wifi_slot.menu.FlashFreq.40.build.flash_freq=40 +wifi_slot.menu.FlashFreq.80=80MHz +wifi_slot.menu.FlashFreq.80.build.flash_freq=80 +wifi_slot.menu.FlashFreq.20=20MHz +wifi_slot.menu.FlashFreq.20.build.flash_freq=20 +wifi_slot.menu.FlashFreq.26=26MHz +wifi_slot.menu.FlashFreq.26.build.flash_freq=26 +wifi_slot.menu.FlashMode.dout=DOUT (compatible) +wifi_slot.menu.FlashMode.dout.build.flash_mode=dout +wifi_slot.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT +wifi_slot.menu.FlashMode.dio=DIO +wifi_slot.menu.FlashMode.dio.build.flash_mode=dio +wifi_slot.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO +wifi_slot.menu.FlashMode.qout=QOUT +wifi_slot.menu.FlashMode.qout.build.flash_mode=qout +wifi_slot.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT +wifi_slot.menu.FlashMode.qio=QIO (fast) +wifi_slot.menu.FlashMode.qio.build.flash_mode=qio +wifi_slot.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO +wifi_slot.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +wifi_slot.menu.eesz.1M64.build.flash_size=1M +wifi_slot.menu.eesz.1M64.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +wifi_slot.menu.eesz.1M64.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M64.upload.maximum_size=958448 +wifi_slot.menu.eesz.1M64.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M64.build.spiffs_start=0xEB000 +wifi_slot.menu.eesz.1M64.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M64.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +wifi_slot.menu.eesz.1M128.build.flash_size=1M +wifi_slot.menu.eesz.1M128.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +wifi_slot.menu.eesz.1M128.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M128.upload.maximum_size=892912 +wifi_slot.menu.eesz.1M128.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M128.build.spiffs_start=0xDB000 +wifi_slot.menu.eesz.1M128.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M128.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +wifi_slot.menu.eesz.1M144.build.flash_size=1M +wifi_slot.menu.eesz.1M144.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +wifi_slot.menu.eesz.1M144.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M144.upload.maximum_size=876528 +wifi_slot.menu.eesz.1M144.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M144.build.spiffs_start=0xD7000 +wifi_slot.menu.eesz.1M144.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M144.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +wifi_slot.menu.eesz.1M160.build.flash_size=1M +wifi_slot.menu.eesz.1M160.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +wifi_slot.menu.eesz.1M160.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M160.upload.maximum_size=860144 +wifi_slot.menu.eesz.1M160.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M160.build.spiffs_start=0xD3000 +wifi_slot.menu.eesz.1M160.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M160.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +wifi_slot.menu.eesz.1M192.build.flash_size=1M +wifi_slot.menu.eesz.1M192.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +wifi_slot.menu.eesz.1M192.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M192.upload.maximum_size=827376 +wifi_slot.menu.eesz.1M192.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M192.build.spiffs_start=0xCB000 +wifi_slot.menu.eesz.1M192.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M192.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +wifi_slot.menu.eesz.1M256.build.flash_size=1M +wifi_slot.menu.eesz.1M256.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +wifi_slot.menu.eesz.1M256.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M256.upload.maximum_size=761840 +wifi_slot.menu.eesz.1M256.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M256.build.spiffs_start=0xBB000 +wifi_slot.menu.eesz.1M256.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M256.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +wifi_slot.menu.eesz.1M512.build.flash_size=1M +wifi_slot.menu.eesz.1M512.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +wifi_slot.menu.eesz.1M512.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M512.upload.maximum_size=499696 +wifi_slot.menu.eesz.1M512.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.1M512.build.spiffs_start=0x7B000 +wifi_slot.menu.eesz.1M512.build.spiffs_end=0xFB000 +wifi_slot.menu.eesz.1M512.build.spiffs_blocksize=8192 +wifi_slot.menu.eesz.1M=1MB (FS:none OTA:~502KB) +wifi_slot.menu.eesz.1M.build.flash_size=1M +wifi_slot.menu.eesz.1M.build.flash_size_bytes=0x100000 +wifi_slot.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +wifi_slot.menu.eesz.1M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.1M.upload.maximum_size=1023984 +wifi_slot.menu.eesz.1M.build.rfcal_addr=0xFC000 +wifi_slot.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) +wifi_slot.menu.eesz.2M64.build.flash_size=2M +wifi_slot.menu.eesz.2M64.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld +wifi_slot.menu.eesz.2M64.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M64.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M64.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M64.build.spiffs_start=0x1F0000 +wifi_slot.menu.eesz.2M64.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M64.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) +wifi_slot.menu.eesz.2M128.build.flash_size=2M +wifi_slot.menu.eesz.2M128.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld +wifi_slot.menu.eesz.2M128.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M128.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M128.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M128.build.spiffs_start=0x1E0000 +wifi_slot.menu.eesz.2M128.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M128.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) +wifi_slot.menu.eesz.2M256.build.flash_size=2M +wifi_slot.menu.eesz.2M256.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld +wifi_slot.menu.eesz.2M256.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M256.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M256.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M256.build.spiffs_start=0x1C0000 +wifi_slot.menu.eesz.2M256.build.spiffs_end=0x1FB000 +wifi_slot.menu.eesz.2M256.build.spiffs_blocksize=4096 +wifi_slot.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) +wifi_slot.menu.eesz.2M512.build.flash_size=2M +wifi_slot.menu.eesz.2M512.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld +wifi_slot.menu.eesz.2M512.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M512.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M512.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M512.build.spiffs_start=0x180000 +wifi_slot.menu.eesz.2M512.build.spiffs_end=0x1FA000 +wifi_slot.menu.eesz.2M512.build.spiffs_blocksize=8192 +wifi_slot.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) +wifi_slot.menu.eesz.2M1M.build.flash_size=2M +wifi_slot.menu.eesz.2M1M.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld +wifi_slot.menu.eesz.2M1M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M1M.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 +wifi_slot.menu.eesz.2M1M.build.spiffs_start=0x100000 +wifi_slot.menu.eesz.2M1M.build.spiffs_end=0x1FA000 +wifi_slot.menu.eesz.2M1M.build.spiffs_blocksize=8192 +wifi_slot.menu.eesz.2M=2MB (FS:none OTA:~1019KB) +wifi_slot.menu.eesz.2M.build.flash_size=2M +wifi_slot.menu.eesz.2M.build.flash_size_bytes=0x200000 +wifi_slot.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld +wifi_slot.menu.eesz.2M.build.spiffs_pagesize=256 +wifi_slot.menu.eesz.2M.upload.maximum_size=1044464 +wifi_slot.menu.eesz.2M.build.rfcal_addr=0x1FC000 +wifi_slot.menu.ip.lm2f=v2 Lower Memory +wifi_slot.menu.ip.lm2f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wifi_slot.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifi_slot.menu.ip.hb2f=v2 Higher Bandwidth +wifi_slot.menu.ip.hb2f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wifi_slot.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wifi_slot.menu.ip.lm2n=v2 Lower Memory (no features) +wifi_slot.menu.ip.lm2n.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wifi_slot.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifi_slot.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wifi_slot.menu.ip.hb2n.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wifi_slot.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wifi_slot.menu.ip.lm6f=v2 IPv6 Lower Memory +wifi_slot.menu.ip.lm6f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wifi_slot.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifi_slot.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wifi_slot.menu.ip.hb6f.build.lwip_include=lwip2/include +wifi_slot.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wifi_slot.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wifi_slot.menu.ip.hb1=v1.4 Higher Bandwidth +wifi_slot.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wifi_slot.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wifi_slot.menu.ip.src=v1.4 Compile from source +wifi_slot.menu.ip.src.build.lwip_lib=-llwip_src +wifi_slot.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wifi_slot.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wifi_slot.menu.dbg.Disabled=Disabled +wifi_slot.menu.dbg.Disabled.build.debug_port= +wifi_slot.menu.dbg.Serial=Serial +wifi_slot.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wifi_slot.menu.dbg.Serial1=Serial1 +wifi_slot.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wifi_slot.menu.lvl.None____=None +wifi_slot.menu.lvl.None____.build.debug_level= +wifi_slot.menu.lvl.SSL=SSL +wifi_slot.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wifi_slot.menu.lvl.TLS_MEM=TLS_MEM +wifi_slot.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wifi_slot.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wifi_slot.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.HTTP_SERVER=HTTP_SERVER +wifi_slot.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wifi_slot.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wifi_slot.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wifi_slot.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wifi_slot.menu.lvl.CORE=CORE +wifi_slot.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wifi_slot.menu.lvl.WIFI=WIFI +wifi_slot.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wifi_slot.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wifi_slot.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wifi_slot.menu.lvl.UPDATER=UPDATER +wifi_slot.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wifi_slot.menu.lvl.OTA=OTA +wifi_slot.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wifi_slot.menu.lvl.OOM=OOM +wifi_slot.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wifi_slot.menu.lvl.MDNS=MDNS +wifi_slot.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wifi_slot.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wifi_slot.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wifi_slot.menu.wipe.none=Only Sketch +wifi_slot.menu.wipe.none.upload.erase_cmd= +wifi_slot.menu.wipe.sdk=Sketch + WiFi Settings +wifi_slot.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +wifi_slot.menu.wipe.all=All Flash Contents +wifi_slot.menu.wipe.all.upload.erase_cmd=erase_flash +wifi_slot.menu.baud.115200=115200 +wifi_slot.menu.baud.115200.upload.speed=115200 +wifi_slot.menu.baud.57600=57600 +wifi_slot.menu.baud.57600.upload.speed=57600 +wifi_slot.menu.baud.230400.linux=230400 +wifi_slot.menu.baud.230400.macosx=230400 +wifi_slot.menu.baud.230400.upload.speed=230400 +wifi_slot.menu.baud.256000.windows=256000 +wifi_slot.menu.baud.256000.upload.speed=256000 +wifi_slot.menu.baud.460800.linux=460800 +wifi_slot.menu.baud.460800.macosx=460800 +wifi_slot.menu.baud.460800.upload.speed=460800 +wifi_slot.menu.baud.512000.windows=512000 +wifi_slot.menu.baud.512000.upload.speed=512000 +wifi_slot.menu.baud.921600=921600 +wifi_slot.menu.baud.921600.upload.speed=921600 +wifi_slot.menu.baud.3000000=3000000 +wifi_slot.menu.baud.3000000.upload.speed=3000000 + +############################################################## +wiolink.name=Seeed Wio Link +wiolink.build.board=ESP8266_WIO_LINK +wiolink.build.variant=wiolink +wiolink.upload.tool=esptool +wiolink.upload.maximum_data_size=81920 +wiolink.upload.wait_for_upload_port=true +wiolink.upload.erase_cmd= +wiolink.serial.disableDTR=true +wiolink.serial.disableRTS=true +wiolink.build.mcu=esp8266 +wiolink.build.core=esp8266 +wiolink.build.spiffs_pagesize=256 +wiolink.build.debug_port= +wiolink.build.debug_level= +wiolink.menu.xtal.80=80 MHz +wiolink.menu.xtal.80.build.f_cpu=80000000L +wiolink.menu.xtal.160=160 MHz +wiolink.menu.xtal.160.build.f_cpu=160000000L +wiolink.menu.vt.flash=Flash +wiolink.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +wiolink.menu.vt.heap=Heap +wiolink.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +wiolink.menu.vt.iram=IRAM +wiolink.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +wiolink.menu.exception.legacy=Legacy (new can return nullptr) +wiolink.menu.exception.legacy.build.exception_flags=-fno-exceptions +wiolink.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +wiolink.menu.exception.disabled=Disabled (new can abort) +wiolink.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +wiolink.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +wiolink.menu.exception.enabled=Enabled +wiolink.menu.exception.enabled.build.exception_flags=-fexceptions +wiolink.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +wiolink.menu.ssl.all=All SSL ciphers (most compatible) +wiolink.menu.ssl.all.build.sslflags= +wiolink.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +wiolink.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +wiolink.upload.resetmethod=--before default_reset --after hard_reset +wiolink.build.flash_mode=qio +wiolink.build.flash_flags=-DFLASHMODE_QIO +wiolink.build.flash_freq=40 +wiolink.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +wiolink.menu.eesz.4M2M.build.flash_size=4M +wiolink.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +wiolink.menu.eesz.4M2M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M2M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M2M.build.spiffs_start=0x200000 +wiolink.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +wiolink.menu.eesz.4M2M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +wiolink.menu.eesz.4M3M.build.flash_size=4M +wiolink.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +wiolink.menu.eesz.4M3M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M3M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M3M.build.spiffs_start=0x100000 +wiolink.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +wiolink.menu.eesz.4M3M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +wiolink.menu.eesz.4M1M.build.flash_size=4M +wiolink.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +wiolink.menu.eesz.4M1M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M1M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +wiolink.menu.eesz.4M1M.build.spiffs_start=0x300000 +wiolink.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +wiolink.menu.eesz.4M1M.build.spiffs_blocksize=8192 +wiolink.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +wiolink.menu.eesz.4M.build.flash_size=4M +wiolink.menu.eesz.4M.build.flash_size_bytes=0x400000 +wiolink.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +wiolink.menu.eesz.4M.build.spiffs_pagesize=256 +wiolink.menu.eesz.4M.upload.maximum_size=1044464 +wiolink.menu.eesz.4M.build.rfcal_addr=0x3FC000 +wiolink.menu.ip.lm2f=v2 Lower Memory +wiolink.menu.ip.lm2f.build.lwip_include=lwip2/include +wiolink.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +wiolink.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wiolink.menu.ip.hb2f=v2 Higher Bandwidth +wiolink.menu.ip.hb2f.build.lwip_include=lwip2/include +wiolink.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +wiolink.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +wiolink.menu.ip.lm2n=v2 Lower Memory (no features) +wiolink.menu.ip.lm2n.build.lwip_include=lwip2/include +wiolink.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +wiolink.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wiolink.menu.ip.hb2n=v2 Higher Bandwidth (no features) +wiolink.menu.ip.hb2n.build.lwip_include=lwip2/include +wiolink.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +wiolink.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +wiolink.menu.ip.lm6f=v2 IPv6 Lower Memory +wiolink.menu.ip.lm6f.build.lwip_include=lwip2/include +wiolink.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +wiolink.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wiolink.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +wiolink.menu.ip.hb6f.build.lwip_include=lwip2/include +wiolink.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +wiolink.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +wiolink.menu.ip.hb1=v1.4 Higher Bandwidth +wiolink.menu.ip.hb1.build.lwip_lib=-llwip_gcc +wiolink.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +wiolink.menu.ip.src=v1.4 Compile from source +wiolink.menu.ip.src.build.lwip_lib=-llwip_src +wiolink.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +wiolink.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +wiolink.menu.dbg.Disabled=Disabled +wiolink.menu.dbg.Disabled.build.debug_port= +wiolink.menu.dbg.Serial=Serial +wiolink.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +wiolink.menu.dbg.Serial1=Serial1 +wiolink.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +wiolink.menu.lvl.None____=None +wiolink.menu.lvl.None____.build.debug_level= +wiolink.menu.lvl.SSL=SSL +wiolink.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +wiolink.menu.lvl.TLS_MEM=TLS_MEM +wiolink.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +wiolink.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +wiolink.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.HTTP_SERVER=HTTP_SERVER +wiolink.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +wiolink.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +wiolink.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +wiolink.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +wiolink.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +wiolink.menu.lvl.CORE=CORE +wiolink.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +wiolink.menu.lvl.WIFI=WIFI +wiolink.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +wiolink.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +wiolink.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +wiolink.menu.lvl.UPDATER=UPDATER +wiolink.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +wiolink.menu.lvl.OTA=OTA +wiolink.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +wiolink.menu.lvl.OOM=OOM +wiolink.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +wiolink.menu.lvl.MDNS=MDNS +wiolink.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +wiolink.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +wiolink.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +wiolink.menu.wipe.none=Only Sketch +wiolink.menu.wipe.none.upload.erase_cmd= +wiolink.menu.wipe.sdk=Sketch + WiFi Settings +wiolink.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +wiolink.menu.wipe.all=All Flash Contents +wiolink.menu.wipe.all.upload.erase_cmd=erase_flash +wiolink.menu.baud.115200=115200 +wiolink.menu.baud.115200.upload.speed=115200 +wiolink.menu.baud.57600=57600 +wiolink.menu.baud.57600.upload.speed=57600 +wiolink.menu.baud.230400.linux=230400 +wiolink.menu.baud.230400.macosx=230400 +wiolink.menu.baud.230400.upload.speed=230400 +wiolink.menu.baud.256000.windows=256000 +wiolink.menu.baud.256000.upload.speed=256000 +wiolink.menu.baud.460800.linux=460800 +wiolink.menu.baud.460800.macosx=460800 +wiolink.menu.baud.460800.upload.speed=460800 +wiolink.menu.baud.512000.windows=512000 +wiolink.menu.baud.512000.upload.speed=512000 +wiolink.menu.baud.921600=921600 +wiolink.menu.baud.921600.upload.speed=921600 +wiolink.menu.baud.3000000=3000000 +wiolink.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espectro.name=ESPectro Core +espectro.build.board=ESP8266_ESPECTRO_CORE +espectro.build.variant=espectro +espectro.upload.tool=esptool +espectro.upload.maximum_data_size=81920 +espectro.upload.wait_for_upload_port=true +espectro.upload.erase_cmd= +espectro.serial.disableDTR=true +espectro.serial.disableRTS=true +espectro.build.mcu=esp8266 +espectro.build.core=esp8266 +espectro.build.spiffs_pagesize=256 +espectro.build.debug_port= +espectro.build.debug_level= +espectro.menu.xtal.80=80 MHz +espectro.menu.xtal.80.build.f_cpu=80000000L +espectro.menu.xtal.160=160 MHz +espectro.menu.xtal.160.build.f_cpu=160000000L +espectro.menu.vt.flash=Flash +espectro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espectro.menu.vt.heap=Heap +espectro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espectro.menu.vt.iram=IRAM +espectro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espectro.menu.exception.legacy=Legacy (new can return nullptr) +espectro.menu.exception.legacy.build.exception_flags=-fno-exceptions +espectro.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espectro.menu.exception.disabled=Disabled (new can abort) +espectro.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espectro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espectro.menu.exception.enabled=Enabled +espectro.menu.exception.enabled.build.exception_flags=-fexceptions +espectro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espectro.menu.ssl.all=All SSL ciphers (most compatible) +espectro.menu.ssl.all.build.sslflags= +espectro.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espectro.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espectro.upload.resetmethod=--before default_reset --after hard_reset +espectro.build.flash_mode=dio +espectro.build.flash_flags=-DFLASHMODE_DIO +espectro.build.flash_freq=40 +espectro.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) +espectro.menu.eesz.4M2M.build.flash_size=4M +espectro.menu.eesz.4M2M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld +espectro.menu.eesz.4M2M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M2M.upload.maximum_size=1044464 +espectro.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M2M.build.spiffs_start=0x200000 +espectro.menu.eesz.4M2M.build.spiffs_end=0x3FA000 +espectro.menu.eesz.4M2M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) +espectro.menu.eesz.4M3M.build.flash_size=4M +espectro.menu.eesz.4M3M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld +espectro.menu.eesz.4M3M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M3M.upload.maximum_size=1044464 +espectro.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M3M.build.spiffs_start=0x100000 +espectro.menu.eesz.4M3M.build.spiffs_end=0x3FA000 +espectro.menu.eesz.4M3M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) +espectro.menu.eesz.4M1M.build.flash_size=4M +espectro.menu.eesz.4M1M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld +espectro.menu.eesz.4M1M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M1M.upload.maximum_size=1044464 +espectro.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 +espectro.menu.eesz.4M1M.build.spiffs_start=0x300000 +espectro.menu.eesz.4M1M.build.spiffs_end=0x3FA000 +espectro.menu.eesz.4M1M.build.spiffs_blocksize=8192 +espectro.menu.eesz.4M=4MB (FS:none OTA:~1019KB) +espectro.menu.eesz.4M.build.flash_size=4M +espectro.menu.eesz.4M.build.flash_size_bytes=0x400000 +espectro.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld +espectro.menu.eesz.4M.build.spiffs_pagesize=256 +espectro.menu.eesz.4M.upload.maximum_size=1044464 +espectro.menu.eesz.4M.build.rfcal_addr=0x3FC000 +espectro.menu.ip.lm2f=v2 Lower Memory +espectro.menu.ip.lm2f.build.lwip_include=lwip2/include +espectro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espectro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espectro.menu.ip.hb2f=v2 Higher Bandwidth +espectro.menu.ip.hb2f.build.lwip_include=lwip2/include +espectro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espectro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espectro.menu.ip.lm2n=v2 Lower Memory (no features) +espectro.menu.ip.lm2n.build.lwip_include=lwip2/include +espectro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espectro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espectro.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espectro.menu.ip.hb2n.build.lwip_include=lwip2/include +espectro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espectro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espectro.menu.ip.lm6f=v2 IPv6 Lower Memory +espectro.menu.ip.lm6f.build.lwip_include=lwip2/include +espectro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espectro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espectro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espectro.menu.ip.hb6f.build.lwip_include=lwip2/include +espectro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espectro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espectro.menu.ip.hb1=v1.4 Higher Bandwidth +espectro.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espectro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espectro.menu.ip.src=v1.4 Compile from source +espectro.menu.ip.src.build.lwip_lib=-llwip_src +espectro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espectro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espectro.menu.dbg.Disabled=Disabled +espectro.menu.dbg.Disabled.build.debug_port= +espectro.menu.dbg.Serial=Serial +espectro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espectro.menu.dbg.Serial1=Serial1 +espectro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espectro.menu.lvl.None____=None +espectro.menu.lvl.None____.build.debug_level= +espectro.menu.lvl.SSL=SSL +espectro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espectro.menu.lvl.TLS_MEM=TLS_MEM +espectro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espectro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espectro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.HTTP_SERVER=HTTP_SERVER +espectro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espectro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espectro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espectro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espectro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espectro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espectro.menu.lvl.CORE=CORE +espectro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espectro.menu.lvl.WIFI=WIFI +espectro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espectro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espectro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espectro.menu.lvl.UPDATER=UPDATER +espectro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espectro.menu.lvl.OTA=OTA +espectro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espectro.menu.lvl.OOM=OOM +espectro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espectro.menu.lvl.MDNS=MDNS +espectro.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espectro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espectro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espectro.menu.wipe.none=Only Sketch +espectro.menu.wipe.none.upload.erase_cmd= +espectro.menu.wipe.sdk=Sketch + WiFi Settings +espectro.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espectro.menu.wipe.all=All Flash Contents +espectro.menu.wipe.all.upload.erase_cmd=erase_flash +espectro.menu.baud.115200=115200 +espectro.menu.baud.115200.upload.speed=115200 +espectro.menu.baud.57600=57600 +espectro.menu.baud.57600.upload.speed=57600 +espectro.menu.baud.230400.linux=230400 +espectro.menu.baud.230400.macosx=230400 +espectro.menu.baud.230400.upload.speed=230400 +espectro.menu.baud.256000.windows=256000 +espectro.menu.baud.256000.upload.speed=256000 +espectro.menu.baud.460800.linux=460800 +espectro.menu.baud.460800.macosx=460800 +espectro.menu.baud.460800.upload.speed=460800 +espectro.menu.baud.512000.windows=512000 +espectro.menu.baud.512000.upload.speed=512000 +espectro.menu.baud.921600=921600 +espectro.menu.baud.921600.upload.speed=921600 +espectro.menu.baud.3000000=3000000 +espectro.menu.baud.3000000.upload.speed=3000000 + +############################################################## +sonoff.name=ITEAD Sonoff +sonoff.build.board=SONOFF_SV +sonoff.build.extra_flags=-DESP8266 +sonoff.build.flash_size=1M +sonoff.build.variant=itead +sonoff.menu.BoardModel.sonoffBasic=ITEAD Sonoff Basic +sonoff.menu.BoardModel.sonoffBasic.build.board=SONOFF_BASIC +sonoff.menu.BoardModel.sonoffS20=ITEAD Sonoff S20 +sonoff.menu.BoardModel.sonoffS20.build.board=SONOFF_S20 +sonoff.menu.BoardModel.sonoffSV=ITEAD Sonoff SV +sonoff.menu.BoardModel.sonoffSV.build.board=SONOFF_SV +sonoff.menu.BoardModel.sonoffTH=ITEAD Sonoff TH +sonoff.menu.BoardModel.sonoffTH.build.board=SONOFF_TH +sonoff.upload.tool=esptool +sonoff.upload.maximum_data_size=81920 +sonoff.upload.wait_for_upload_port=true +sonoff.upload.erase_cmd= +sonoff.serial.disableDTR=true +sonoff.serial.disableRTS=true +sonoff.build.mcu=esp8266 +sonoff.build.core=esp8266 +sonoff.build.spiffs_pagesize=256 +sonoff.build.debug_port= +sonoff.build.debug_level= +sonoff.menu.xtal.80=80 MHz +sonoff.menu.xtal.80.build.f_cpu=80000000L +sonoff.menu.xtal.160=160 MHz +sonoff.menu.xtal.160.build.f_cpu=160000000L +sonoff.menu.vt.flash=Flash +sonoff.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +sonoff.menu.vt.heap=Heap +sonoff.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +sonoff.menu.vt.iram=IRAM +sonoff.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +sonoff.menu.exception.legacy=Legacy (new can return nullptr) +sonoff.menu.exception.legacy.build.exception_flags=-fno-exceptions +sonoff.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +sonoff.menu.exception.disabled=Disabled (new can abort) +sonoff.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +sonoff.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +sonoff.menu.exception.enabled=Enabled +sonoff.menu.exception.enabled.build.exception_flags=-fexceptions +sonoff.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +sonoff.menu.ssl.all=All SSL ciphers (most compatible) +sonoff.menu.ssl.all.build.sslflags= +sonoff.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +sonoff.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +sonoff.upload.resetmethod=--before no_reset --after soft_reset +sonoff.build.flash_mode=dout +sonoff.build.flash_flags=-DFLASHMODE_DOUT +sonoff.build.flash_freq=40 +sonoff.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +sonoff.menu.eesz.1M64.build.flash_size=1M +sonoff.menu.eesz.1M64.build.flash_size_bytes=0x100000 +sonoff.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +sonoff.menu.eesz.1M64.build.spiffs_pagesize=256 +sonoff.menu.eesz.1M64.upload.maximum_size=958448 +sonoff.menu.eesz.1M64.build.rfcal_addr=0xFC000 +sonoff.menu.eesz.1M64.build.spiffs_start=0xEB000 +sonoff.menu.eesz.1M64.build.spiffs_end=0xFB000 +sonoff.menu.eesz.1M64.build.spiffs_blocksize=4096 +sonoff.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +sonoff.menu.eesz.1M128.build.flash_size=1M +sonoff.menu.eesz.1M128.build.flash_size_bytes=0x100000 +sonoff.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +sonoff.menu.eesz.1M128.build.spiffs_pagesize=256 +sonoff.menu.eesz.1M128.upload.maximum_size=892912 +sonoff.menu.eesz.1M128.build.rfcal_addr=0xFC000 +sonoff.menu.eesz.1M128.build.spiffs_start=0xDB000 +sonoff.menu.eesz.1M128.build.spiffs_end=0xFB000 +sonoff.menu.eesz.1M128.build.spiffs_blocksize=4096 +sonoff.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +sonoff.menu.eesz.1M144.build.flash_size=1M +sonoff.menu.eesz.1M144.build.flash_size_bytes=0x100000 +sonoff.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +sonoff.menu.eesz.1M144.build.spiffs_pagesize=256 +sonoff.menu.eesz.1M144.upload.maximum_size=876528 +sonoff.menu.eesz.1M144.build.rfcal_addr=0xFC000 +sonoff.menu.eesz.1M144.build.spiffs_start=0xD7000 +sonoff.menu.eesz.1M144.build.spiffs_end=0xFB000 +sonoff.menu.eesz.1M144.build.spiffs_blocksize=4096 +sonoff.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +sonoff.menu.eesz.1M160.build.flash_size=1M +sonoff.menu.eesz.1M160.build.flash_size_bytes=0x100000 +sonoff.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +sonoff.menu.eesz.1M160.build.spiffs_pagesize=256 +sonoff.menu.eesz.1M160.upload.maximum_size=860144 +sonoff.menu.eesz.1M160.build.rfcal_addr=0xFC000 +sonoff.menu.eesz.1M160.build.spiffs_start=0xD3000 +sonoff.menu.eesz.1M160.build.spiffs_end=0xFB000 +sonoff.menu.eesz.1M160.build.spiffs_blocksize=4096 +sonoff.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +sonoff.menu.eesz.1M192.build.flash_size=1M +sonoff.menu.eesz.1M192.build.flash_size_bytes=0x100000 +sonoff.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +sonoff.menu.eesz.1M192.build.spiffs_pagesize=256 +sonoff.menu.eesz.1M192.upload.maximum_size=827376 +sonoff.menu.eesz.1M192.build.rfcal_addr=0xFC000 +sonoff.menu.eesz.1M192.build.spiffs_start=0xCB000 +sonoff.menu.eesz.1M192.build.spiffs_end=0xFB000 +sonoff.menu.eesz.1M192.build.spiffs_blocksize=4096 +sonoff.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +sonoff.menu.eesz.1M256.build.flash_size=1M +sonoff.menu.eesz.1M256.build.flash_size_bytes=0x100000 +sonoff.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +sonoff.menu.eesz.1M256.build.spiffs_pagesize=256 +sonoff.menu.eesz.1M256.upload.maximum_size=761840 +sonoff.menu.eesz.1M256.build.rfcal_addr=0xFC000 +sonoff.menu.eesz.1M256.build.spiffs_start=0xBB000 +sonoff.menu.eesz.1M256.build.spiffs_end=0xFB000 +sonoff.menu.eesz.1M256.build.spiffs_blocksize=4096 +sonoff.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +sonoff.menu.eesz.1M512.build.flash_size=1M +sonoff.menu.eesz.1M512.build.flash_size_bytes=0x100000 +sonoff.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +sonoff.menu.eesz.1M512.build.spiffs_pagesize=256 +sonoff.menu.eesz.1M512.upload.maximum_size=499696 +sonoff.menu.eesz.1M512.build.rfcal_addr=0xFC000 +sonoff.menu.eesz.1M512.build.spiffs_start=0x7B000 +sonoff.menu.eesz.1M512.build.spiffs_end=0xFB000 +sonoff.menu.eesz.1M512.build.spiffs_blocksize=8192 +sonoff.menu.eesz.1M=1MB (FS:none OTA:~502KB) +sonoff.menu.eesz.1M.build.flash_size=1M +sonoff.menu.eesz.1M.build.flash_size_bytes=0x100000 +sonoff.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +sonoff.menu.eesz.1M.build.spiffs_pagesize=256 +sonoff.menu.eesz.1M.upload.maximum_size=1023984 +sonoff.menu.eesz.1M.build.rfcal_addr=0xFC000 +sonoff.menu.ip.lm2f=v2 Lower Memory +sonoff.menu.ip.lm2f.build.lwip_include=lwip2/include +sonoff.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +sonoff.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +sonoff.menu.ip.hb2f=v2 Higher Bandwidth +sonoff.menu.ip.hb2f.build.lwip_include=lwip2/include +sonoff.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +sonoff.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +sonoff.menu.ip.lm2n=v2 Lower Memory (no features) +sonoff.menu.ip.lm2n.build.lwip_include=lwip2/include +sonoff.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +sonoff.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +sonoff.menu.ip.hb2n=v2 Higher Bandwidth (no features) +sonoff.menu.ip.hb2n.build.lwip_include=lwip2/include +sonoff.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +sonoff.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +sonoff.menu.ip.lm6f=v2 IPv6 Lower Memory +sonoff.menu.ip.lm6f.build.lwip_include=lwip2/include +sonoff.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +sonoff.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +sonoff.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +sonoff.menu.ip.hb6f.build.lwip_include=lwip2/include +sonoff.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +sonoff.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +sonoff.menu.ip.hb1=v1.4 Higher Bandwidth +sonoff.menu.ip.hb1.build.lwip_lib=-llwip_gcc +sonoff.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +sonoff.menu.ip.src=v1.4 Compile from source +sonoff.menu.ip.src.build.lwip_lib=-llwip_src +sonoff.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +sonoff.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +sonoff.menu.dbg.Disabled=Disabled +sonoff.menu.dbg.Disabled.build.debug_port= +sonoff.menu.dbg.Serial=Serial +sonoff.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +sonoff.menu.dbg.Serial1=Serial1 +sonoff.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +sonoff.menu.lvl.None____=None +sonoff.menu.lvl.None____.build.debug_level= +sonoff.menu.lvl.SSL=SSL +sonoff.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +sonoff.menu.lvl.TLS_MEM=TLS_MEM +sonoff.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +sonoff.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +sonoff.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +sonoff.menu.lvl.HTTP_SERVER=HTTP_SERVER +sonoff.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +sonoff.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +sonoff.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +sonoff.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +sonoff.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +sonoff.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +sonoff.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +sonoff.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +sonoff.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +sonoff.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +sonoff.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +sonoff.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +sonoff.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +sonoff.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +sonoff.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +sonoff.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +sonoff.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +sonoff.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +sonoff.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +sonoff.menu.lvl.CORE=CORE +sonoff.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +sonoff.menu.lvl.WIFI=WIFI +sonoff.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +sonoff.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +sonoff.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +sonoff.menu.lvl.UPDATER=UPDATER +sonoff.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +sonoff.menu.lvl.OTA=OTA +sonoff.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +sonoff.menu.lvl.OOM=OOM +sonoff.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +sonoff.menu.lvl.MDNS=MDNS +sonoff.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +sonoff.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +sonoff.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +sonoff.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +sonoff.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +sonoff.menu.wipe.none=Only Sketch +sonoff.menu.wipe.none.upload.erase_cmd= +sonoff.menu.wipe.sdk=Sketch + WiFi Settings +sonoff.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +sonoff.menu.wipe.all=All Flash Contents +sonoff.menu.wipe.all.upload.erase_cmd=erase_flash +sonoff.menu.baud.115200=115200 +sonoff.menu.baud.115200.upload.speed=115200 +sonoff.menu.baud.57600=57600 +sonoff.menu.baud.57600.upload.speed=57600 +sonoff.menu.baud.230400.linux=230400 +sonoff.menu.baud.230400.macosx=230400 +sonoff.menu.baud.230400.upload.speed=230400 +sonoff.menu.baud.256000.windows=256000 +sonoff.menu.baud.256000.upload.speed=256000 +sonoff.menu.baud.460800.linux=460800 +sonoff.menu.baud.460800.macosx=460800 +sonoff.menu.baud.460800.upload.speed=460800 +sonoff.menu.baud.512000.windows=512000 +sonoff.menu.baud.512000.upload.speed=512000 +sonoff.menu.baud.921600=921600 +sonoff.menu.baud.921600.upload.speed=921600 +sonoff.menu.baud.3000000=3000000 +sonoff.menu.baud.3000000.upload.speed=3000000 + +############################################################## +espmxdevkit.name=DOIT ESP-Mx DevKit (ESP8285) +espmxdevkit.build.board=ESP8266_ESP01 +espmxdevkit.build.led=-DLED_BUILTIN=16 +espmxdevkit.build.variant=esp8285 +espmxdevkit.upload.tool=esptool +espmxdevkit.upload.maximum_data_size=81920 +espmxdevkit.upload.wait_for_upload_port=true +espmxdevkit.upload.erase_cmd= +espmxdevkit.serial.disableDTR=true +espmxdevkit.serial.disableRTS=true +espmxdevkit.build.mcu=esp8266 +espmxdevkit.build.core=esp8266 +espmxdevkit.build.spiffs_pagesize=256 +espmxdevkit.build.debug_port= +espmxdevkit.build.debug_level= +espmxdevkit.menu.xtal.80=80 MHz +espmxdevkit.menu.xtal.80.build.f_cpu=80000000L +espmxdevkit.menu.xtal.160=160 MHz +espmxdevkit.menu.xtal.160.build.f_cpu=160000000L +espmxdevkit.menu.vt.flash=Flash +espmxdevkit.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH +espmxdevkit.menu.vt.heap=Heap +espmxdevkit.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM +espmxdevkit.menu.vt.iram=IRAM +espmxdevkit.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM +espmxdevkit.menu.exception.legacy=Legacy (new can return nullptr) +espmxdevkit.menu.exception.legacy.build.exception_flags=-fno-exceptions +espmxdevkit.menu.exception.legacy.build.stdcpp_lib=-lstdc++ +espmxdevkit.menu.exception.disabled=Disabled (new can abort) +espmxdevkit.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT +espmxdevkit.menu.exception.disabled.build.stdcpp_lib=-lstdc++ +espmxdevkit.menu.exception.enabled=Enabled +espmxdevkit.menu.exception.enabled.build.exception_flags=-fexceptions +espmxdevkit.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc +espmxdevkit.menu.ssl.all=All SSL ciphers (most compatible) +espmxdevkit.menu.ssl.all.build.sslflags= +espmxdevkit.menu.ssl.basic=Basic SSL ciphers (lower ROM use) +espmxdevkit.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC +espmxdevkit.upload.resetmethod=--before default_reset --after hard_reset +espmxdevkit.build.flash_mode=dout +espmxdevkit.build.flash_flags=-DFLASHMODE_DOUT +espmxdevkit.build.flash_freq=40 +espmxdevkit.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) +espmxdevkit.menu.eesz.1M64.build.flash_size=1M +espmxdevkit.menu.eesz.1M64.build.flash_size_bytes=0x100000 +espmxdevkit.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld +espmxdevkit.menu.eesz.1M64.build.spiffs_pagesize=256 +espmxdevkit.menu.eesz.1M64.upload.maximum_size=958448 +espmxdevkit.menu.eesz.1M64.build.rfcal_addr=0xFC000 +espmxdevkit.menu.eesz.1M64.build.spiffs_start=0xEB000 +espmxdevkit.menu.eesz.1M64.build.spiffs_end=0xFB000 +espmxdevkit.menu.eesz.1M64.build.spiffs_blocksize=4096 +espmxdevkit.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) +espmxdevkit.menu.eesz.1M128.build.flash_size=1M +espmxdevkit.menu.eesz.1M128.build.flash_size_bytes=0x100000 +espmxdevkit.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld +espmxdevkit.menu.eesz.1M128.build.spiffs_pagesize=256 +espmxdevkit.menu.eesz.1M128.upload.maximum_size=892912 +espmxdevkit.menu.eesz.1M128.build.rfcal_addr=0xFC000 +espmxdevkit.menu.eesz.1M128.build.spiffs_start=0xDB000 +espmxdevkit.menu.eesz.1M128.build.spiffs_end=0xFB000 +espmxdevkit.menu.eesz.1M128.build.spiffs_blocksize=4096 +espmxdevkit.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) +espmxdevkit.menu.eesz.1M144.build.flash_size=1M +espmxdevkit.menu.eesz.1M144.build.flash_size_bytes=0x100000 +espmxdevkit.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld +espmxdevkit.menu.eesz.1M144.build.spiffs_pagesize=256 +espmxdevkit.menu.eesz.1M144.upload.maximum_size=876528 +espmxdevkit.menu.eesz.1M144.build.rfcal_addr=0xFC000 +espmxdevkit.menu.eesz.1M144.build.spiffs_start=0xD7000 +espmxdevkit.menu.eesz.1M144.build.spiffs_end=0xFB000 +espmxdevkit.menu.eesz.1M144.build.spiffs_blocksize=4096 +espmxdevkit.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) +espmxdevkit.menu.eesz.1M160.build.flash_size=1M +espmxdevkit.menu.eesz.1M160.build.flash_size_bytes=0x100000 +espmxdevkit.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld +espmxdevkit.menu.eesz.1M160.build.spiffs_pagesize=256 +espmxdevkit.menu.eesz.1M160.upload.maximum_size=860144 +espmxdevkit.menu.eesz.1M160.build.rfcal_addr=0xFC000 +espmxdevkit.menu.eesz.1M160.build.spiffs_start=0xD3000 +espmxdevkit.menu.eesz.1M160.build.spiffs_end=0xFB000 +espmxdevkit.menu.eesz.1M160.build.spiffs_blocksize=4096 +espmxdevkit.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) +espmxdevkit.menu.eesz.1M192.build.flash_size=1M +espmxdevkit.menu.eesz.1M192.build.flash_size_bytes=0x100000 +espmxdevkit.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld +espmxdevkit.menu.eesz.1M192.build.spiffs_pagesize=256 +espmxdevkit.menu.eesz.1M192.upload.maximum_size=827376 +espmxdevkit.menu.eesz.1M192.build.rfcal_addr=0xFC000 +espmxdevkit.menu.eesz.1M192.build.spiffs_start=0xCB000 +espmxdevkit.menu.eesz.1M192.build.spiffs_end=0xFB000 +espmxdevkit.menu.eesz.1M192.build.spiffs_blocksize=4096 +espmxdevkit.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) +espmxdevkit.menu.eesz.1M256.build.flash_size=1M +espmxdevkit.menu.eesz.1M256.build.flash_size_bytes=0x100000 +espmxdevkit.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld +espmxdevkit.menu.eesz.1M256.build.spiffs_pagesize=256 +espmxdevkit.menu.eesz.1M256.upload.maximum_size=761840 +espmxdevkit.menu.eesz.1M256.build.rfcal_addr=0xFC000 +espmxdevkit.menu.eesz.1M256.build.spiffs_start=0xBB000 +espmxdevkit.menu.eesz.1M256.build.spiffs_end=0xFB000 +espmxdevkit.menu.eesz.1M256.build.spiffs_blocksize=4096 +espmxdevkit.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) +espmxdevkit.menu.eesz.1M512.build.flash_size=1M +espmxdevkit.menu.eesz.1M512.build.flash_size_bytes=0x100000 +espmxdevkit.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld +espmxdevkit.menu.eesz.1M512.build.spiffs_pagesize=256 +espmxdevkit.menu.eesz.1M512.upload.maximum_size=499696 +espmxdevkit.menu.eesz.1M512.build.rfcal_addr=0xFC000 +espmxdevkit.menu.eesz.1M512.build.spiffs_start=0x7B000 +espmxdevkit.menu.eesz.1M512.build.spiffs_end=0xFB000 +espmxdevkit.menu.eesz.1M512.build.spiffs_blocksize=8192 +espmxdevkit.menu.eesz.1M=1MB (FS:none OTA:~502KB) +espmxdevkit.menu.eesz.1M.build.flash_size=1M +espmxdevkit.menu.eesz.1M.build.flash_size_bytes=0x100000 +espmxdevkit.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld +espmxdevkit.menu.eesz.1M.build.spiffs_pagesize=256 +espmxdevkit.menu.eesz.1M.upload.maximum_size=1023984 +espmxdevkit.menu.eesz.1M.build.rfcal_addr=0xFC000 +espmxdevkit.menu.ip.lm2f=v2 Lower Memory +espmxdevkit.menu.ip.lm2f.build.lwip_include=lwip2/include +espmxdevkit.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat +espmxdevkit.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espmxdevkit.menu.ip.hb2f=v2 Higher Bandwidth +espmxdevkit.menu.ip.hb2f.build.lwip_include=lwip2/include +espmxdevkit.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat +espmxdevkit.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 +espmxdevkit.menu.ip.lm2n=v2 Lower Memory (no features) +espmxdevkit.menu.ip.lm2n.build.lwip_include=lwip2/include +espmxdevkit.menu.ip.lm2n.build.lwip_lib=-llwip2-536 +espmxdevkit.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espmxdevkit.menu.ip.hb2n=v2 Higher Bandwidth (no features) +espmxdevkit.menu.ip.hb2n.build.lwip_include=lwip2/include +espmxdevkit.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 +espmxdevkit.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 +espmxdevkit.menu.ip.lm6f=v2 IPv6 Lower Memory +espmxdevkit.menu.ip.lm6f.build.lwip_include=lwip2/include +espmxdevkit.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat +espmxdevkit.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espmxdevkit.menu.ip.hb6f=v2 IPv6 Higher Bandwidth +espmxdevkit.menu.ip.hb6f.build.lwip_include=lwip2/include +espmxdevkit.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat +espmxdevkit.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 +espmxdevkit.menu.ip.hb1=v1.4 Higher Bandwidth +espmxdevkit.menu.ip.hb1.build.lwip_lib=-llwip_gcc +espmxdevkit.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC +espmxdevkit.menu.ip.src=v1.4 Compile from source +espmxdevkit.menu.ip.src.build.lwip_lib=-llwip_src +espmxdevkit.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC +espmxdevkit.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" +espmxdevkit.menu.dbg.Disabled=Disabled +espmxdevkit.menu.dbg.Disabled.build.debug_port= +espmxdevkit.menu.dbg.Serial=Serial +espmxdevkit.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial +espmxdevkit.menu.dbg.Serial1=Serial1 +espmxdevkit.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 +espmxdevkit.menu.lvl.None____=None +espmxdevkit.menu.lvl.None____.build.debug_level= +espmxdevkit.menu.lvl.SSL=SSL +espmxdevkit.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL +espmxdevkit.menu.lvl.TLS_MEM=TLS_MEM +espmxdevkit.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM +espmxdevkit.menu.lvl.HTTP_CLIENT=HTTP_CLIENT +espmxdevkit.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT +espmxdevkit.menu.lvl.HTTP_SERVER=HTTP_SERVER +espmxdevkit.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER +espmxdevkit.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM +espmxdevkit.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM +espmxdevkit.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT +espmxdevkit.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT +espmxdevkit.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER +espmxdevkit.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER +espmxdevkit.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT +espmxdevkit.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espmxdevkit.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER +espmxdevkit.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espmxdevkit.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER +espmxdevkit.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT +espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT +espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER +espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER +espmxdevkit.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER +espmxdevkit.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espmxdevkit.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espmxdevkit.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER +espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER +espmxdevkit.menu.lvl.CORE=CORE +espmxdevkit.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE +espmxdevkit.menu.lvl.WIFI=WIFI +espmxdevkit.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI +espmxdevkit.menu.lvl.HTTP_UPDATE=HTTP_UPDATE +espmxdevkit.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE +espmxdevkit.menu.lvl.UPDATER=UPDATER +espmxdevkit.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER +espmxdevkit.menu.lvl.OTA=OTA +espmxdevkit.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA +espmxdevkit.menu.lvl.OOM=OOM +espmxdevkit.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM +espmxdevkit.menu.lvl.MDNS=MDNS +espmxdevkit.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS +espmxdevkit.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espmxdevkit.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS +espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS +espmxdevkit.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG +espmxdevkit.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG +espmxdevkit.menu.wipe.none=Only Sketch +espmxdevkit.menu.wipe.none.upload.erase_cmd= +espmxdevkit.menu.wipe.sdk=Sketch + WiFi Settings +espmxdevkit.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 +espmxdevkit.menu.wipe.all=All Flash Contents +espmxdevkit.menu.wipe.all.upload.erase_cmd=erase_flash +espmxdevkit.menu.baud.115200=115200 +espmxdevkit.menu.baud.115200.upload.speed=115200 +espmxdevkit.menu.baud.57600=57600 +espmxdevkit.menu.baud.57600.upload.speed=57600 +espmxdevkit.menu.baud.230400.linux=230400 +espmxdevkit.menu.baud.230400.macosx=230400 +espmxdevkit.menu.baud.230400.upload.speed=230400 +espmxdevkit.menu.baud.256000.windows=256000 +espmxdevkit.menu.baud.256000.upload.speed=256000 +espmxdevkit.menu.baud.460800.linux=460800 +espmxdevkit.menu.baud.460800.macosx=460800 +espmxdevkit.menu.baud.460800.upload.speed=460800 +espmxdevkit.menu.baud.512000.windows=512000 +espmxdevkit.menu.baud.512000.upload.speed=512000 +espmxdevkit.menu.baud.921600=921600 +espmxdevkit.menu.baud.921600.upload.speed=921600 +espmxdevkit.menu.baud.3000000=3000000 +espmxdevkit.menu.baud.3000000.upload.speed=3000000 + diff --git a/arduino/version 2.6.3/platform.txt b/arduino/version 2.6.3/platform.txt new file mode 100644 index 000000000..204b5793b --- /dev/null +++ b/arduino/version 2.6.3/platform.txt @@ -0,0 +1,171 @@ + +# ESP8266 platform +# ------------------------------ + +# For more info: +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification + +name=ESP8266 Boards (2.6.3) +version=2.6.3 + +# These will be removed by the packager script when doing a JSON release + + + + +runtime.tools.signing={runtime.platform.path}/tools/signing.py +runtime.tools.elf2bin={runtime.platform.path}/tools/elf2bin.py +runtime.tools.sizes={runtime.platform.path}/tools/sizes.py +runtime.tools.makecorever={runtime.platform.path}/tools/makecorever.py +runtime.tools.eboot={runtime.platform.path}/bootloaders/eboot/eboot.elf + +compiler.warning_flags=-w +compiler.warning_flags.none=-w +compiler.warning_flags.default= +compiler.warning_flags.more=-Wall +compiler.warning_flags.all=-Wall -Wextra + +build.lwip_lib=-llwip_gcc +build.lwip_include=lwip/include +build.lwip_flags=-DLWIP_OPEN_SRC + +build.vtable_flags=-DVTABLES_IN_FLASH + +build.sslflags= + +build.exception_flags=-fno-exceptions +build.stdcpp_lib=-lstdc++ +build.stdcpp_level=-std=gnu++11 + +#build.float=-u _printf_float -u _scanf_float +build.float= +build.led= + +# default SDK for all boards +# (generic board overrides this variable) +build.sdk=NONOSDK22x_190703 +#build.sdk=NONOSDK22x_191024 +#build.sdk=NONOSDK22x_191105 + +compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ +compiler.sdk.path={runtime.platform.path}/tools/sdk + +compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf +compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" + +compiler.c.cmd=xtensa-lx106-elf-gcc +compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} + +compiler.S.cmd=xtensa-lx106-elf-gcc +compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls + +compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/lib/{build.sdk}" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read + +compiler.c.elf.cmd=xtensa-lx106-elf-gcc +compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc + +compiler.cpp.cmd=xtensa-lx106-elf-g++ +compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} + +compiler.as.cmd=xtensa-lx106-elf-as + +compiler.ar.cmd=xtensa-lx106-elf-ar +compiler.ar.flags=cru + +compiler.elf2hex.cmd=esptool +compiler.elf2hex.flags= + +compiler.size.cmd=xtensa-lx106-elf-size + +# This can be overriden in boards.txt +build.extra_flags=-DESP8266 + +# These can be overridden in platform.local.txt +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= + +## generate file with git version number +## needs git +recipe.hooks.sketch.prebuild.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" +# This is quite a working hack. This form of prebuild hook, while intuitive, is not explicitly documented. + + +## Build the app.ld linker file +recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld" + +## Compile c files +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile c++ files +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Compile S files +recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" + +## Create archives +recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" + +## Create eeprom +recipe.objcopy.eep.pattern= + +## Create hex +recipe.objcopy.hex.1.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.elf2bin}" --eboot "{runtime.tools.eboot}" --app "{build.path}/{build.project_name}.elf" --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin" --out "{build.path}/{build.project_name}.bin" +recipe.objcopy.hex.2.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed" --legacy "{build.path}/{build.project_name}.bin.legacy_sig" +recipe.objcopy.hex.3.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.sizes}" --elf "{build.path}/{build.project_name}.elf" --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin" + +## Save hex +recipe.output.tmp_file={build.project_name}.bin +recipe.output.save_file={build.project_name}.{build.variant}.bin + +## Compute size +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.regex=^(?:\.irom0\.text|\.text|\.text1|\.data|\.rodata|)\s+([0-9]+).* +recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* +#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* + +# ------------------------------ + +tools.esptool.path= +# Because the variable expansion doesn't allow one tool to find another, the following lines +# will point to "{runtime.platform.path}/tools/python3/python3" in GIT and +# "{runtime.tools.python3.path}/python3" for JSON board manager releases. +tools.esptool.cmd={runtime.tools.python3.path}/python3 +tools.esptool.network_cmd={runtime.tools.python3.path}/python3 + + + +tools.esptool.upload.protocol=esp +# esptool.py --trace option is a debug option, not a verbose option +tools.esptool.upload.params.verbose= +tools.esptool.upload.params.quiet= + +# First, potentially perform an erase or nothing +# Next, do the binary upload +# Combined in one rule because Arduino doesn't suport upload.1.pattern/upload.3.pattern +tools.esptool.upload.pattern="{cmd}" "{runtime.platform.path}/tools/upload.py" --chip esp8266 --port "{serial.port}" --baud "{upload.speed}" "{upload.verbose}" {upload.erase_cmd} {upload.resetmethod} write_flash 0x0 "{build.path}/{build.project_name}.bin" + +tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" + +tools.mkspiffs.cmd=mkspiffs +tools.mkspiffs.cmd.windows=mkspiffs.exe +tools.mkspiffs.path={runtime.tools.mkspiffs.path} + +tools.mklittlefs.cmd=mklittlefs +tools.mklittlefs.cmd.windows=mklittlefs.exe +tools.mklittlefs.path={runtime.platform.path}/tools/mklittlefs + +tools.espupload.cmd=python +tools.espupload.cmd.windows=python.exe +tools.espupload.path={runtime.platform.path}/tools +tools.espupload.upload.protocol=espupload +tools.espupload.upload.params.verbose= +tools.espupload.upload.params.quiet= +tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 8e9546ed6..08d5fcd95 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -21,8 +21,13 @@ - Change libraries/PubSubClient/src/PubSubClient.h #define MQTT_MAX_PACKET_SIZE 1200 - - Select IDE Tools - Flash Mode: "DOUT" - - Select IDE Tools - Flash Size: "1M (no SPIFFS)" + Arduino IDE 1.8.12 and up parameters + - Select IDE Tools - Board: "Generic ESP8266 Module" + - Select IDE Tools - Flash Mode: "DOUT (compatible)" + - Select IDE Tools - Flash Size: "1M (FS:none OTA:~502KB)" + - Select IDE Tools - LwIP Variant: "v2 Higher Bandwidth (no feature)" + - Select IDE Tools - VTables: "Flash" + - Select IDE Tools - Espressif FW: "nonos-sdk-2.2.1+100 (190703)" ====================================================*/ // Location specific includes diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 7e7292a8c..6bc4d2b16 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -991,6 +991,7 @@ void HandleWifiLogin(void) WSContentStop(); } +#ifdef USE_LIGHT void WebSliderColdWarm(void) { WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Cold Warm @@ -1001,6 +1002,7 @@ void WebSliderColdWarm(void) LightGetColorTemp(), 't', 0); // t0 - Value id releated to lc("t0", value) and WebGetArg("t0", tmp, sizeof(tmp)); } +#endif // USE_LIGHT void HandleRoot(void) { From 02ba705ecae60a40a68d5078310e7486145477b7 Mon Sep 17 00:00:00 2001 From: to-scho Date: Mon, 2 Mar 2020 20:32:55 +0100 Subject: [PATCH 540/559] Shutterbutton does not work for 1 button, fixes #7793 --- tasmota/xdrv_27_shutter.ino | 64 +++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 96d9ccf5c..b157da933 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -34,7 +34,7 @@ uint16_t messwerte[5] = {30,50,70,90,100}; uint16_t last_execute_step; enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE, SHT_OFF_ON__OPEN_CLOSE_STEPPER,}; -enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; +enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_EXT_HOLD, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|" @@ -520,12 +520,12 @@ void ShutterRelayChanged(void) bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_index) { // check for simultaneous shutter button hold - uint32 min_shutterbutton_hold_timer = -1; + uint32 min_shutterbutton_hold_timer = -1; // -1 == max(uint32) for (uint32_t i = 0; i < MAX_KEYS; i++) { - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) + if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer)) min_shutterbutton_hold_timer = Button.hold_timer[i]; } - return (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1)); + return ((-1 != min_shutterbutton_hold_timer) && (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1))); } void ShutterButtonHandler(void) @@ -535,8 +535,8 @@ void ShutterButtonHandler(void) uint8_t press_index; uint32_t button_index = XdrvMailbox.index; uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03; - uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50) + if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) { if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action buttonState = SHT_PRESSED_MULTI; @@ -582,11 +582,13 @@ void ShutterButtonHandler(void) Button.press_counter[button_index] = 0; } if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer + press_index = -1; // check for simultaneous shutter button extend hold if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) { // simultaneous shutter button extend hold detected - press_index = 0; buttonState = SHT_PRESSED_EXT_HOLD_SIMULTANEOUS; + } else { + buttonState = SHT_PRESSED_EXT_HOLD; } } } @@ -599,14 +601,13 @@ void ShutterButtonHandler(void) if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0)) { if (Button.press_counter[button_index]<99) { // check for simultaneous shutter button press - uint32 min_shutterbutton_press_counter = -1; + uint32 min_shutterbutton_press_counter = -1; // -1 == max(uint32) for (uint32_t i = 0; i < MAX_KEYS; i++) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Settings.shutter_button[i] %ld, shutter_index %d, Button.press_counter[i] %d, min_shutterbutton_press_counter %d, i %d"), Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i); - if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { + if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) { min_shutterbutton_press_counter = Button.press_counter[i]; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: min_shutterbutton_press_counter %d"), min_shutterbutton_press_counter); } - } if (min_shutterbutton_press_counter == Button.press_counter[button_index]) { // simultaneous shutter button press detected @@ -628,23 +629,32 @@ void ShutterButtonHandler(void) } } - if (buttonState != SHT_NOT_PRESSED) { - if (buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) { - if ((press_index>=5) && (press_index<=7) && (!Settings.flag.button_restrict)) { // 5x..7x && no SetOption1 (0) - // simultaneous shutter button press 5x, 6x, 7x detected - char scmnd[20]; - GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } - } else if (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) { - if (!Settings.flag.button_restrict) { // no SetOption1 (0) - char scmnd[20]; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); - ExecuteCommand(scmnd, SRC_BUTTON); - return; - } - } else if (buttonState <= SHT_PRESSED_IMMEDIATE) { + if (buttonState != SHT_NOT_PRESSED) { + if ((!Settings.flag.button_restrict) && (((press_index>=5) && (press_index<=7)) || (buttonState == SHT_PRESSED_EXT_HOLD) || (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS))){ + // check number of buttons for this shutter + uint8_t shutter_index_num_buttons = 0; + for (uint32_t i = 0; i < MAX_KEYS; i++) { + if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) { + shutter_index_num_buttons++; + } + } + if ((buttonState == SHT_PRESSED_MULTI_SIMULTANEOUS) || ((shutter_index_num_buttons==1) && (buttonState == SHT_PRESSED_MULTI))){ + // 5x..7x && no SetOption1 (0) checked above + // simultaneous or stand alone button press 5x, 6x, 7x detected + char scmnd[20]; + GetTextIndexed(scmnd, sizeof(scmnd), press_index -3, kCommands); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } else if ((buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS) || ((shutter_index_num_buttons==1) && (buttonState == SHT_PRESSED_EXT_HOLD))){ + // no SetOption1 (0) checked above + // simultaneous or stand alone button extended hold detected + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1")); + ExecuteCommand(scmnd, SRC_BUTTON); + return; + } + } + if (buttonState <= SHT_PRESSED_IMMEDIATE) { if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) { uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1); if (pos_press_index>3) pos_press_index=3; @@ -686,7 +696,7 @@ void ShutterButtonHandler(void) } // if if (Settings.shutter_startrelay[shutter_index] } Response_P(PSTR("{")); - ResponseAppend_P(JSON_SHUTTER_BUTTON, shutter_index+1, (buttonState <= SHT_PRESSED_IMMEDIATE) ? (button_index+1) : 0, press_index); + ResponseAppend_P(JSON_SHUTTER_BUTTON, shutter_index+1, (buttonState <= SHT_PRESSED_EXT_HOLD) ? (button_index+1) : 0, press_index); ResponseJsonEnd(); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER)); XdrvRulesProcess(); From 543f83218eb5f5fb4798c6017888f33993404f5a Mon Sep 17 00:00:00 2001 From: to-scho Date: Mon, 2 Mar 2020 20:49:11 +0100 Subject: [PATCH 541/559] extended multipress window from 0.5s to 0.75s --- tasmota/xdrv_27_shutter.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasmota/xdrv_27_shutter.ino b/tasmota/xdrv_27_shutter.ino index 96d9ccf5c..f31c9dbc2 100644 --- a/tasmota/xdrv_27_shutter.ino +++ b/tasmota/xdrv_27_shutter.ino @@ -548,7 +548,8 @@ void ShutterButtonHandler(void) Button.press_counter[button_index] = 99; // Remember to discard further action for press & hold within button timings } else { Button.press_counter[button_index] = (Button.window_timer[button_index]) ? Button.press_counter[button_index] +1 : 1; - Button.window_timer[button_index] = loops_per_second / 2; // 0.5 second multi press window + // Button.window_timer[button_index] = (Button.press_counter[button_index]==1) ? loops_per_second / 2 : loops_per_second; // 0.5 second multi press window after 1st press, 1s afterwards + Button.window_timer[button_index] = (loops_per_second >> 2) * 3; // 0.75 second multi press window } } blinks = 201; From 3a2a3cde8892f44472c854ffa6245d180baacaeb Mon Sep 17 00:00:00 2001 From: Hadinger Date: Wed, 4 Mar 2020 08:59:45 +0100 Subject: [PATCH 542/559] Sync with https://github.com/esp8266/Arduino/pull/7057 --- tasmota/core_esp8266_waveform.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tasmota/core_esp8266_waveform.cpp b/tasmota/core_esp8266_waveform.cpp index 2a0e8415b..0e4beeef2 100644 --- a/tasmota/core_esp8266_waveform.cpp +++ b/tasmota/core_esp8266_waveform.cpp @@ -170,6 +170,13 @@ static inline ICACHE_RAM_ATTR uint32_t min_u32(uint32_t a, uint32_t b) { return b; } +static inline ICACHE_RAM_ATTR int32_t max_32(int32_t a, int32_t b) { + if (a < b) { + return b; + } + return a; +} + // Stops a waveform on a pin int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) { // Can't possibly need to stop anything if there is no timer active @@ -261,6 +268,13 @@ static ICACHE_RAM_ATTR void timer1Interrupt() { // Check for toggles int32_t cyclesToGo = wave->nextServiceCycle - now; if (cyclesToGo < 0) { + // See #7057 + // The following is a no-op unless we have overshot by an entire waveform cycle. + // As modulus is an expensive operation, this code is removed for now: + // cyclesToGo = -((-cyclesToGo) % (wave->nextTimeHighCycles + wave->nextTimeLowCycles)); + // + // Alternative version with lower CPU impact: + // while (-cyclesToGo > wave->nextTimeHighCycles + wave->nextTimeLowCycles) { cyclesToGo += wave->nextTimeHighCycles + wave->nextTimeLowCycles)}; waveformState ^= mask; if (waveformState & mask) { if (i == 16) { @@ -268,16 +282,16 @@ static ICACHE_RAM_ATTR void timer1Interrupt() { } else { SetGPIO(mask); } - wave->nextServiceCycle = now + wave->nextTimeHighCycles + cyclesToGo; - nextEventCycles = min_u32(nextEventCycles, min_u32(wave->nextTimeHighCycles + cyclesToGo, 1)); + wave->nextServiceCycle += wave->nextTimeHighCycles; + nextEventCycles = min_u32(nextEventCycles, max_32(wave->nextTimeHighCycles + cyclesToGo, microsecondsToClockCycles(1))); } else { if (i == 16) { GP16O &= ~1; // GPIO16 write slow as it's RMW } else { ClearGPIO(mask); } - wave->nextServiceCycle = now + wave->nextTimeLowCycles + cyclesToGo; - nextEventCycles = min_u32(nextEventCycles, min_u32(wave->nextTimeLowCycles + cyclesToGo, 1)); + wave->nextServiceCycle += wave->nextTimeLowCycles; + nextEventCycles = min_u32(nextEventCycles, max_32(wave->nextTimeLowCycles + cyclesToGo, microsecondsToClockCycles(1))); } } else { uint32_t deltaCycles = wave->nextServiceCycle - now; From f0a8305b136d96097090fc68405d8c00ddb8f99c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Mar 2020 11:56:35 +0100 Subject: [PATCH 543/559] Add localization for Romanian --- .travis.yml | 1 + platformio.ini | 1 + platformio_tasmota_env.ini | 3 + tasmota/language/ro-RO.h | 728 +++++++++++++++++++++++++++++++++++++ tasmota/my_user_config.h | 1 + 5 files changed, 734 insertions(+) create mode 100644 tasmota/language/ro-RO.h diff --git a/.travis.yml b/.travis.yml index 88e971a06..5e5885f65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ env: - ENV=tasmota-NL - ENV=tasmota-PL - ENV=tasmota-PT + - ENV=tasmota-RO - ENV=tasmota-RU - ENV=tasmota-SE - ENV=tasmota-SK diff --git a/platformio.ini b/platformio.ini index 552408790..198e47264 100755 --- a/platformio.ini +++ b/platformio.ini @@ -40,6 +40,7 @@ default_envs = ; tasmota-NL ; tasmota-PL ; tasmota-PT +; tasmota-RO ; tasmota-RU ; tasmota-SE ; tasmota-SK diff --git a/platformio_tasmota_env.ini b/platformio_tasmota_env.ini index cfcd53686..a09f01ecd 100644 --- a/platformio_tasmota_env.ini +++ b/platformio_tasmota_env.ini @@ -82,6 +82,9 @@ build_flags = ${common.build_flags} -DMY_LANGUAGE=pl-PL [env:tasmota-PT] build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-PT +[env:tasmota-RO] +build_flags = ${common.build_flags} -DMY_LANGUAGE=ro-RO + [env:tasmota-RU] build_flags = ${common.build_flags} -DMY_LANGUAGE=ru-RU diff --git a/tasmota/language/ro-RO.h b/tasmota/language/ro-RO.h new file mode 100644 index 000000000..cc75273af --- /dev/null +++ b/tasmota/language/ro-RO.h @@ -0,0 +1,728 @@ +/* + ro-RO.h - localization for Romanian - Romania and Moldova for Tasmota + + Copyright (C) 2020 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LANGUAGE_RO_RO_H_ +#define _LANGUAGE_RO_RO_H_ + +/*************************** ATTENTION *******************************\ + * + * Due to memory constraints only UTF-8 is supported. + * To save code space keep text as short as possible. + * Time and Date provided by SDK can not be localized (yet). + * Use online command StateText to translate ON, OFF, HOLD and TOGGLE. + * Use online command Prefix to translate cmnd, stat and tele. + * + * Updated until v8.1.0.10 +\*********************************************************************/ + +//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) +// https://www.science.co.il/language/Locale-codes.php +#define LANGUAGE_LCID 2072 +// HTML (ISO 639-1) Language Code +#define D_HTML_LANGUAGE "ro" + +// "2017-03-07T11:08:02" - ISO8601:2004 +#define D_YEAR_MONTH_SEPARATOR "-" +#define D_MONTH_DAY_SEPARATOR "-" +#define D_DATE_TIME_SEPARATOR "T" +#define D_HOUR_MINUTE_SEPARATOR ":" +#define D_MINUTE_SECOND_SEPARATOR ":" + +#define D_DAY3LIST "DumLunMarMieJoiVinSâm" +#define D_MONTH3LIST "IanFebMarAprMaiIunIulAugSepOctNoeDec" + +// Non JSON decimal separator +#define D_DECIMAL_SEPARATOR "." + +// Common +#define D_ADMIN "Admin" +#define D_AIR_QUALITY "Calitatea aerului" +#define D_AP "AP" // Access Point +#define D_AS "as" +#define D_AUTO "AUTO" +#define D_BLINK "Blink" +#define D_BLINKOFF "BlinkOff" +#define D_BOOT_COUNT "Boot Count" +#define D_BRIGHTLIGHT "Strălucire" +#define D_BSSID "BSSId" +#define D_BUTTON "Buton" +#define D_BY "de" // Written by me +#define D_BYTES "Bytes" +#define D_CELSIUS "Celsius" +#define D_CHANNEL "Canal" +#define D_CO2 "Dioxid de carbon" +#define D_CODE "cod" // Button code +#define D_COLDLIGHT "Rece" +#define D_COMMAND "Comandă" +#define D_CONNECTED "Conectat" +#define D_CORS_DOMAIN "Domeniu CORS" +#define D_COUNT "Numărătoare" +#define D_COUNTER "Contor" +#define D_CT_POWER "Putere Transformată" +#define D_CURRENT "Curent" // As in Voltage and Current +#define D_DA;TA "Date" +#define D_DARKLIGHT "Întunecat" +#define D_DEBUG "Depanare" +#define D_DISABLED "Dezactivat" +#define D_DISTANCE "Distanță" +#define D_DNS_SERVER "Server DNS" +#define D_DONE "Terminat" +#define D_DST_TIME "DST" +#define D_ECO2 "eCO₂" +#define D_EMULATION "Emulație" +#define D_ENABLED "Abilitat" +#define D_ERASE "Șterge" +#define D_ERROR "Eroare" +#define D_FAHRENHEIT "Fahrenheit" +#define D_FAILED "Eșuat" +#define D_FALLBACK "Rezervă" +#define D_FALLBACK_TOPIC "Listă de rezervă" +#define D_FALSE "Fals" +#define D_FILE "Fișier" +#define D_FLOW_RATE "Debit" +#define D_FREE_MEMORY "Memorie Liberă" +#define D_FREQUENCY "Frecvență" +#define D_GAS "Gaz" +#define D_GATEWAY "Gateway" +#define D_GROUP "Grup" +#define D_HOST "Gazdă" +#define D_HOSTNAME "Hostname" +#define D_HUMIDITY "Umiditate" +#define D_ILLUMINANCE "Iluminare" +#define D_IMMEDIATE "imediat" // Button immediate +#define D_INDEX "Index" +#define D_INFO "Info" +#define D_INFRARED "Infraroșu" +#define D_INITIALIZED "Inițializat" +#define D_IP_ADDRESS "Adresă IP" +#define D_LIGHT "Lumină" +#define D_LWT "LWT" +#define D_MODULE "Modul" +#define D_MOISTURE "Umezeală" +#define D_MQTT "MQTT" +#define D_MULTI_PRESS "selectare multiplă" +#define D_NOISE "Zgomot" +#define D_NONE "Lipsă" +#define D_OFF "Închis" +#define D_OFFLINE "Offline" +#define D_OK "Ok" +#define D_ON "Aprins" +#define D_ONLINE "Online" +#define D_PASSWORD "Parolă" +#define D_PORT "Port" +#define D_POWER_FACTOR "Factor de Putere" +#define D_POWERUSAGE "Putere" +#define D_POWERUSAGE_ACTIVE "Putere Activă" +#define D_POWERUSAGE_APPARENT "Putere Aparentă" +#define D_POWERUSAGE_REACTIVE "Putere Reactivă" +#define D_PRESSURE "Presiune" +#define D_PRESSUREATSEALEVEL "Presiune atmosferică" +#define D_PROGRAM_FLASH_SIZE "Mărimea Programului Flash" +#define D_PROGRAM_SIZE "Mărimea Programului" +#define D_PROJECT "Proiect" +#define D_RAIN "Ploaie" +#define D_RANGE "Distanță" +#define D_RECEIVED "Primit" +#define D_RESTART "Restart" +#define D_RESTARTING "Restartare" +#define D_RESTART_REASON "Motiv Restartare" +#define D_RESTORE "Restaurare" +#define D_RETAINED "Păstrare" +#define D_RULE "Regulă" +#define D_SAVE "Salvare" +#define D_SENSOR "Senzor" +#define D_SSID "SSId" +#define D_START "Start" +#define D_STD_TIME "STD" +#define D_STOP "Stop" +#define D_SUBNET_MASK "Subnet Mask" +#define D_SUBSCRIBE_TO "Înscriere la" +#define D_UNSUBSCRIBE_FROM "Renunțare de la" +#define D_SUCCESSFUL "Succes" +#define D_SUNRISE "Răsărit" +#define D_SUNSET "Apus" +#define D_TEMPERATURE "Temperatură" +#define D_TO "la" +#define D_TOGGLE "Comută" +#define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Folosință totală" +#define D_TRANSMIT "Transmitere" +#define D_TRUE "Adevărat" +#define D_TVOC "TVOC" +#define D_UPGRADE "actualizare" +#define D_UPLOAD "Încarcare" +#define D_UPTIME "Folosință" +#define D_USER "Utilizator" +#define D_UTC_TIME "UTC" +#define D_UV_INDEX "Index UV" +#define D_UV_INDEX_1 "Mic" +#define D_UV_INDEX_2 "Mediu" +#define D_UV_INDEX_3 "Mare" +#define D_UV_INDEX_4 "Pericol" +#define D_UV_INDEX_5 "ArdereL1/2" +#define D_UV_INDEX_6 "ArdereL3" +#define D_UV_INDEX_7 "În afara intervalului" // Out of Range +#define D_UV_LEVEL "Nivel UV" +#define D_UV_POWER "Putere UV" +#define D_VERSION "Versiune" +#define D_VOLTAGE "Voltaj" +#define D_WEIGHT "Greutate" +#define D_WARMLIGHT "Cald" +#define D_WEB_SERVER "Server Web" + +// tasmota.ino +#define D_WARNING_MINIMAL_VERSION "ATENȚIE Această versiune nu suportă setări permanente" +#define D_LEVEL_10 "nivel 1-0" +#define D_LEVEL_01 "nivel 0-1" +#define D_SERIAL_LOGGING_DISABLED "Logare serială dezactivată" +#define D_SYSLOG_LOGGING_REENABLED "Logare Syslog activată" + +#define D_SET_BAUDRATE_TO "Setare Baudrate la" +#define D_RECEIVED_TOPIC "Listă Primită" +#define D_DATA_SIZE "Mărime Date" +#define D_ANALOG_INPUT "Analog" + +// support.ino +#define D_OSWATCH "osWatch" +#define D_BLOCKED_LOOP "Circuit blocat" +#define D_WPS_FAILED_WITH_STATUS "status WPSconfig EȘUAT" +#define D_ACTIVE_FOR_3_MINUTES "activ pentru 3 minute" +#define D_FAILED_TO_START "start eșuat" +#define D_PATCH_ISSUE_2186 "emitere patch 2186" +#define D_CONNECTING_TO_AP "Conectare la AP" +#define D_IN_MODE "in mode" +#define D_CONNECT_FAILED_NO_IP_ADDRESS "Conexiune eșuată, lipsă primire adresă IP" +#define D_CONNECT_FAILED_AP_NOT_REACHED "Conexiune eșuată,nu s-a găsit AP" +#define D_CONNECT_FAILED_WRONG_PASSWORD "Conexiune eșuată,parolă greșită AP" +#define D_CONNECT_FAILED_AP_TIMEOUT "Conexiune eșuată,expirare timp AP" +#define D_ATTEMPTING_CONNECTION "Conectare in curs ..." +#define D_CHECKING_CONNECTION "Verificare conexiune..." +#define D_QUERY_DONE "Query terminat. Servicii MQTT găsite" +#define D_MQTT_SERVICE_FOUND "Servicii MQTT găsite" +#define D_FOUND_AT "Găsite la" +#define D_SYSLOG_HOST_NOT_FOUND "Lipsă gazdă Syslog" + +// settings.ino +#define D_SAVED_TO_FLASH_AT "Salvat pe flash la" +#define D_LOADED_FROM_FLASH_AT "Încărcat din flash la" +#define D_USE_DEFAULTS "Folosește setari fabrica" +#define D_ERASED_SECTOR "Sector șters" + +// xdrv_02_webserver.ino +#define D_NOSCRIPT "Pentru a folosi Tasmota, vă rugăm abilitați JavaScript" +#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "firmware MINIMAL
vă rugăm actualizați" +#define D_WEBSERVER_ACTIVE_ON "Server Web activ" +#define D_WITH_IP_ADDRESS "cu adresa IP " +#define D_WEBSERVER_STOPPED "Server Web oprit" +#define D_FILE_NOT_FOUND "Lipsă fișier" +#define D_REDIRECTED "Redirecționat la captive portal" +#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint cu păstrare Stație" +#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint" +#define D_TRYING_TO_CONNECT "Încercare conectare la rețea" + +#define D_RESTART_IN "Restart în" +#define D_SECONDS "secunde" +#define D_DEVICE_WILL_RESTART "echipamentul va reporni în cateva secunde" +#define D_BUTTON_TOGGLE "Comutare" +#define D_CONFIGURATION "Configurație" +#define D_INFORMATION "Informație" +#define D_FIRMWARE_UPGRADE "Actualizare Firmware" +#define D_CONSOLE "Consolă" +#define D_CONFIRM_RESTART "Confirmare Restart" + +#define D_CONFIGURE_MODULE "Configurare Modul" +#define D_CONFIGURE_WIFI "Configurare WiFi" +#define D_CONFIGURE_MQTT "Configurare MQTT" +#define D_CONFIGURE_DOMOTICZ "Configurare Domoticz" +#define D_CONFIGURE_LOGGING "Configurare Logging" +#define D_CONFIGURE_OTHER "Altă configurare" +#define D_CONFIRM_RESET_CONFIGURATION "Confirmă Reset Configurare" +#define D_RESET_CONFIGURATION "Reseteaza Configurare" +#define D_BACKUP_CONFIGURATION "Backup Configurare" +#define D_RESTORE_CONFIGURATION "Restaurează Configurație" +#define D_MAIN_MENU "Meniu Principal" + +#define D_MODULE_PARAMETERS "Parametri modul" +#define D_MODULE_TYPE "Tip modul" +#define D_PULLUP_ENABLE "Fără Buton/Întrerupător" +#define D_ADC "ADC" +#define D_GPIO "GPIO" +#define D_SERIAL_IN "Intrare Serială" +#define D_SERIAL_OUT "Ieșire Serială" + +#define D_WIFI_PARAMETERS "Parameteri Wifi" +#define D_SCAN_FOR_WIFI_NETWORKS "Scanare rețele wifi" +#define D_SCAN_DONE "Scanare terminată" +#define D_NO_NETWORKS_FOUND "Lipsă rețele găsite" +#define D_REFRESH_TO_SCAN_AGAIN "Refresh pentru o nouă scanare" +#define D_DUPLICATE_ACCESSPOINT "Clonează AccessPoint" +#define D_SKIPPING_LOW_QUALITY "Omite,joasă calitate" +#define D_RSSI "RSSI" +#define D_WEP "WEP" +#define D_WPA_PSK "WPA PSK" +#define D_WPA2_PSK "WPA2 PSK" +#define D_AP1_SSID "AP1 SSId" +#define D_AP1_PASSWORD "Parolă AP1" +#define D_AP2_SSID "AP2 SSId" +#define D_AP2_PASSWORD "Parolă AP2" + +#define D_MQTT_PARAMETERS "parametri MQTT" +#define D_CLIENT "Client" +#define D_FULL_TOPIC "Full Topic" + +#define D_LOGGING_PARAMETERS "parametri Logging" +#define D_SERIAL_LOG_LEVEL "Nivel Serial log" +#define D_MQTT_LOG_LEVEL "Nivel Mqtt log" +#define D_WEB_LOG_LEVEL "Nivel Web log" +#define D_SYS_LOG_LEVEL "Nivel Syslog" +#define D_MORE_DEBUG "Depanare detailată" +#define D_SYSLOG_HOST "Syslog Gazdă " +#define D_SYSLOG_PORT "Syslog port" +#define D_TELEMETRY_PERIOD "Perioadă Telemetrie" + +#define D_OTHER_PARAMETERS "Alți paramatri" +#define D_TEMPLATE "Template" +#define D_ACTIVATE "Activare" +#define D_WEB_ADMIN_PASSWORD "Parolă Web Admin" +#define D_MQTT_ENABLE "Abilitare MQTT" +#define D_FRIENDLY_NAME "Friendly Name" +#define D_BELKIN_WEMO "Belkin WeMo" +#define D_HUE_BRIDGE "Hue Bridge" +#define D_SINGLE_DEVICE "echipament unic" +#define D_MULTI_DEVICE "echipament multiplu" + +#define D_CONFIGURE_TEMPLATE "Configurare Template" +#define D_TEMPLATE_PARAMETERS "Parametri Template" +#define D_TEMPLATE_NAME "Nume" +#define D_BASE_TYPE "Bazat pe" +#define D_TEMPLATE_FLAGS "Opțiuni" + +#define D_SAVE_CONFIGURATION "Salvează configurația" +#define D_CONFIGURATION_SAVED "Configurația salvată" +#define D_CONFIGURATION_RESET "Configurația resetată" + +#define D_PROGRAM_VERSION "Versiunea Program" +#define D_BUILD_DATE_AND_TIME "Creare Data & Timp" +#define D_CORE_AND_SDK_VERSION "Versiunea Core/SDK" +#define D_FLASH_WRITE_COUNT "Spațiu Flash scris" +#define D_MAC_ADDRESS "Adresă MAC" +#define D_MQTT_HOST "Gazdă MQTT" +#define D_MQTT_PORT "Port MQTT" +#define D_MQTT_CLIENT "Client MQTT" +#define D_MQTT_USER "Uilizator MQTT" +#define D_MQTT_TOPIC "Listă MQTT" +#define D_MQTT_GROUP_TOPIC "Listă Grup MQTT" +#define D_MQTT_FULL_TOPIC "Listă Întreagă MQTT" +#define D_MDNS_DISCOVERY "Descoperă mDNS" +#define D_MDNS_ADVERTISE "Publică mDNS" +#define D_ESP_CHIP_ID "ESP Chip Id" +#define D_FLASH_CHIP_ID "Flash Chip Id" +#define D_FLASH_CHIP_SIZE "Mărime Flash" +#define D_FREE_PROGRAM_SPACE "Spațiu Disponibil Program" + +#define D_UPGRADE_BY_WEBSERVER "Actualizat de web server" +#define D_OTA_URL "OTA Url" +#define D_START_UPGRADE "Porneste actualizare" +#define D_UPGRADE_BY_FILE_UPLOAD "Actualizare cu încărcare fișier" +#define D_UPLOAD_STARTED "Încărcare începută" +#define D_UPGRADE_STARTED "Actualizare începută" +#define D_UPLOAD_DONE "Încărcare terminată" +#define D_UPLOAD_ERR_1 "Nici un fișier selectat" +#define D_UPLOAD_ERR_2 "Spațiu insuficient" +#define D_UPLOAD_ERR_3 "Magic byte nu este 0xE9" +#define D_UPLOAD_ERR_4 "Dimensiunea programului este mai mare decât mărimea memoriei" +#define D_UPLOAD_ERR_5 "Încărcare buffer necomparabil" +#define D_UPLOAD_ERR_6 "Încărcare eșuată. Abilitează logging 3" +#define D_UPLOAD_ERR_7 "Încărcare aulată" +#define D_UPLOAD_ERR_8 "Fișier invalid" +#define D_UPLOAD_ERR_9 "Fișier prea mare" +#define D_UPLOAD_ERR_10 "Inițiere chip RF eșuată" +#define D_UPLOAD_ERR_11 "Ștergere chip RF eșuată" +#define D_UPLOAD_ERR_12 "Scriere chip RF eșuată" +#define D_UPLOAD_ERR_13 "Decodare RF firmware eșuată" +#define D_UPLOAD_ERR_14 "Incompatibil" +#define D_UPLOAD_ERROR_CODE "Încărcare cod eroare" + +#define D_ENTER_COMMAND "Introdu comandă" +#define D_ENABLE_WEBLOG_FOR_RESPONSE "Abilitează weblog 2 dacă există răspunsul așteptat" +#define D_NEED_USER_AND_PASSWORD "Necesită utilizator=&parolă=" + +// xdrv_01_mqtt.ino +#define D_FINGERPRINT "Verifică amprenta TLS..." +#define D_TLS_CONNECT_FAILED_TO "Conexiune TLS eșuată" +#define D_RETRY_IN "Reâncearcă în" +#define D_VERIFIED "Verificat folosind amprenta" +#define D_INSECURE "Conexiune nesigură din cauza amprentei eșuate" +#define D_CONNECT_FAILED_TO "Eșuare conectare la" + +// xplg_wemohue.ino +#define D_MULTICAST_DISABLED "Multicast dezabilitat" +#define D_MULTICAST_REJOINED "Multicast (re)conectat" +#define D_MULTICAST_JOIN_FAILED "Multicast conectare eșuată" +#define D_FAILED_TO_SEND_RESPONSE "Trimitere răspuns eșuată" + +#define D_WEMO "WeMo" +#define D_WEMO_BASIC_EVENT "WeMo eveniment basic" +#define D_WEMO_EVENT_SERVICE "WeMo service eveniment" +#define D_WEMO_META_SERVICE "WeMo meta service" +#define D_WEMO_SETUP "Configurare WeMo" +#define D_RESPONSE_SENT "Răspuns trimis" + +#define D_HUE "Hue" +#define D_HUE_BRIDGE_SETUP "Configurare Hue" +#define D_HUE_API_NOT_IMPLEMENTED "Hue API neimplementat" +#define D_HUE_API "Hue API" +#define D_HUE_POST_ARGS "Hue POST args" +#define D_3_RESPONSE_PACKETS_SENT "3 pachete de răspuns trimise" + +// xdrv_07_domoticz.ino +#define D_DOMOTICZ_PARAMETERS "Parametri Domoticz" +#define D_DOMOTICZ_IDX "Idx" +#define D_DOMOTICZ_KEY_IDX "Key idx" +#define D_DOMOTICZ_SWITCH_IDX "Întrerupator idx" +#define D_DOMOTICZ_SENSOR_IDX "Senzor idx" + #define D_DOMOTICZ_TEMP "Temp" + #define D_DOMOTICZ_TEMP_HUM "Temp,U!mid" + #define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Umid,Baro" + #define D_DOMOTICZ_POWER_ENERGY "Putere,Energie" + #define D_DOMOTICZ_ILLUMINANCE "Iluminare" + #define D_DOMOTICZ_COUNT "Contor/PM1" + #define D_DOMOTICZ_VOLTAGE "Voltaj/PM2.5" + #define D_DOMOTICZ_CURRENT "Curent/PM10" + #define D_DOMOTICZ_AIRQUALITY "Calitatea Aerului" + #define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter" +#define D_DOMOTICZ_UPDATE_TIMER "Actualizare Cronometrare" + +// xdrv_09_timers.ino +#define D_CONFIGURE_TIMER "Configurare Cronometrare" +#define D_TIMER_PARAMETERS "Parameteri Cronometrare" +#define D_TIMER_ENABLE "Abilitează Cronometrare" +#define D_TIMER_ARM "Arm" +#define D_TIMER_TIME "Timp" +#define D_TIMER_DAYS "Zile" +#define D_TIMER_REPEAT "Repetă" +#define D_TIMER_OUTPUT "Ieșire" +#define D_TIMER_ACTION "Acțiune" + +// xdrv_10_knx.ino +#define D_CONFIGURE_KNX "Configurare KNX" +#define D_KNX_PARAMETERS "Parameteri KNX" +#define D_KNX_GENERAL_CONFIG "General" +#define D_KNX_PHYSICAL_ADDRESS "Adresă fizică" +#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Trebuie să fie unică în rețeaua KNX)" +#define D_KNX_ENABLE "Abilitează KNX" +#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data de trimis la adresele grupului" +#define D_ADD "Adaugă" +#define D_DELETE "Șterge" +#define D_REPLY "Răspunde" +#define D_KNX_GROUP_ADDRESS_TO_READ "Datele primite pentru adresele grupului" +#define D_RECEIVED_FROM "Primit de la" +#define D_KNX_COMMAND_WRITE "Scrie" +#define D_KNX_COMMAND_READ "Citește" +#define D_KNX_COMMAND_OTHER "Altele" +#define D_SENT_TO "trimite la" +#define D_KNX_WARNING "Adresa grupului ( 0 / 0 / 0 ) este rezervată și nu se poate folosi." +#define D_KNX_ENHANCEMENT "Îmbunătățire Communicație" +#define D_KNX_TX_SLOT "KNX TX" +#define D_KNX_RX_SLOT "KNX RX" + +// xdrv_03_energy.ino +#define D_ENERGY_TODAY "Energia de Azi" +#define D_ENERGY_YESTERDAY "Energia de Ieri" +#define D_ENERGY_TOTAL "Energia Totală" + +// xdrv_27_shutter.ino +#define D_OPEN "Deschide" +#define D_CLOSE "Inchide" +#define D_DOMOTICZ_SHUTTER "Shutter" + +// xdrv_28_pcf8574.ino +#define D_CONFIGURE_PCF8574 "Configurează PCF8574" +#define D_PCF8574_PARAMETERS "Parameteri PCF8574" +#define D_INVERT_PORTS "Inversează Porturile" +#define D_DEVICE "echipament" +#define D_DEVICE_INPUT "Intrare" +#define D_DEVICE_OUTPUT "Ieșire" + +// xsns_05_ds18b20.ino +#define D_SENSOR_BUSY "Senzor ocupat" +#define D_SENSOR_CRC_ERROR "Eroare senzor CRC" +#define D_SENSORS_FOUND "Descoperit senzor" + +// xsns_06_dht.ino +#define D_TIMEOUT_WAITING_FOR "Timp expirat așteptare pentru" +#define D_START_SIGNAL_LOW "Semnal inițiere mic" +#define D_START_SIGNAL_HIGH "Semnal inițiere mare" +#define D_PULSE "puls" +#define D_CHECKSUM_FAILURE "Eroare Checksum" + +// xsns_07_sht1x.ino +#define D_SENSOR_DID_NOT_ACK_COMMAND "Senzorul nu a primit comanda ACK" +#define D_SHT1X_FOUND " Descoperit SHT1X" + +// xsns_18_pms5003.ino +#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter +#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter +#define D_PARTICALS_BEYOND "Particule" + +// xsns_32_mpu6050.ino +#define D_AX_AXIS "Accel.Axa-X" +#define D_AY_AXIS "Accel.Axa-Y" +#define D_AZ_AXIS "Accel.Axa-Z" +#define D_GX_AXIS "Gyro Axa-X" +#define D_GY_AXIS "Gyro Axa-Y" +#define D_GZ_AXIS "Gyro Axa-Z" + +// xsns_34_hx711.ino +#define D_HX_CAL_REMOVE "Elimină greutatea" +#define D_HX_CAL_REFERENCE "Așează greutatea de referință" +#define D_HX_CAL_DONE "Calibrat" +#define D_HX_CAL_FAIL "Eroare Calibrare" +#define D_RESET_HX711 "Reset Balanța" +#define D_CONFIGURE_HX711 "Configurare Balanța" +#define D_HX711_PARAMETERS "Parametri Balanța" +#define D_ITEM_WEIGHT "Greutatea obiectului" +#define D_REFERENCE_WEIGHT "Greutatea de referință" +#define D_CALIBRATE "Calibrează" +#define D_CALIBRATION "Execută Calibrarea" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Direcția vântului" +#define D_TX20_WIND_SPEED "Viteza vântului" +#define D_TX20_WIND_SPEED_MIN "Viteza vântului Min" +#define D_TX20_WIND_SPEED_MAX "Viteza vântului Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "V" + +// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box +#define D_SENSOR_NONE "Fără" +#define D_SENSOR_USER "Utilizator" +#define D_SENSOR_DHT11 "DHT11" +#define D_SENSOR_AM2301 "AM2301" +#define D_SENSOR_SI7021 "SI7021" +#define D_SENSOR_DS18X20 "DS18x20" +#define D_SENSOR_I2C_SCL "I2C SCL" +#define D_SENSOR_I2C_SDA ; "I2C SDA" +#define D_SENSOR_WS2812 "WS2812" +#define D_SENSOR_DFR562 "MP3 Player" +#define D_SENSOR_IRSEND "IRsend" +#define D_SENSOR_SWITCH "Întrerupator" // Suffix "1" +#define D_SENSOR_BUTTON "Buton" // Suffix "1" +#define D_SENSOR_RELAY "Releu" // Suffix "1i" +#define D_SENSOR_LED "Led" // Suffix "1i" +#define D_SENSOR_LED_LINK "LedLink" // Suffix "i" +#define D_SENSOR_PWM "PWM" // Suffix "1" +#define D_SENSOR_COUNTER "Contor" // Suffix "1" +#define D_SENSOR_IRRECV "IRrecv" +#define D_SENSOR_MHZ_RX "MHZ Rx" +#define D_SENSOR_MHZ_TX "MHZ Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" +#define D_SENSOR_SAIR_RX "SAir Rx" +#define D_SENSOR_SAIR_TX "SAir Tx" +#define D_SENSOR_SPI_CS "SPI CS" +#define D_SENSOR_SPI_DC "SPI DC" +#define D_SENSOR_SPI_MISO "SPI MISO" +#define D_SENSOR_SPI_MOSI "SPI MOSI" +#define D_SENSOR_SPI_CLK "SPI CLK" +#define D_SENSOR_BACKLIGHT "Backlight" +#define D_SENSOR_PMS5003 "PMS5003" +#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx" +#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx" +#define D_SENSOR_HPMA_RX "HPMA Rx" +#define D_SENSOR_HPMA_TX "HPMA Tx" +#define D_SENSOR_SBR_RX "SerBr Rx" +#define D_SENSOR_SBR_TX "SerBr Tx" +#define D_SENSOR_SR04_TRIG "SR04 Tri/TX" +#define D_SENSOR_SR04_ECHO "SR04 Ech/RX" +#define D_SENSOR_SDM120_TX "SDMx20 Tx" +#define D_SENSOR_SDM120_RX "SDMx20 Rx" +#define D_SENSOR_SDM630_TX "SDM630 Tx" +#define D_SENSOR_SDM630_RX "SDM630 Rx" +#define D_SENSOR_TM1638_CLK "TM16 CLK" +#define D_SENSOR_TM1638_DIO "TM16 DIO" +#define D_SENSOR_TM1638_STB "TM16 STB" +#define D_SENSOR_HX711_SCK "HX711 SCK" +#define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX2X_TX "TX2x" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" +#define D_SENSOR_TUYA_TX "Tuya Tx" +#define D_SENSOR_TUYA_RX "Tuya Rx" +#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr" +#define D_SENSOR_MGC3130_RESET "MGC3130 Rst" +#define D_SENSOR_SSPI_MISO "SSPI MISO" +#define D_SENSOR_SSPI_MOSI "SSPI MOSI" +#define D_SENSOR_SSPI_SCLK "SSPI SCLK" +#define D_SENSOR_SSPI_CS "SSPI CS" +#define D_SENSOR_SSPI_DC "SSPI DC" +#define D_SENSOR_RF_SENSOR "RF Sensor" +#define D_SENSOR_AZ_RX "AZ Rx" +#define D_SENSOR_AZ_TX "AZ Tx" +#define D_SENSOR_MAX31855_CS "MX31855 CS" +#define D_SENSOR_MAX31855_CLK "MX31855 CLK" +#define D_SENSOR_MAX31855_DO "MX31855 DO" +#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i" +#define D_SENSOR_NRG_CF1 "HLWBL CF1" +#define D_SENSOR_HLW_CF "HLW8012 CF" +#define D_SENSOR_HJL_CF "BL0937 CF" +#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx" +#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx" +#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst" +#define D_SENSOR_CSE7766_TX "CSE7766 Tx" +#define D_SENSOR_CSE7766_RX "CSE7766 Rx" +#define D_SENSOR_PN532_TX "PN532 Tx" +#define D_SENSOR_PN532_RX "PN532 Rx" +#define D_SENSOR_SM16716_CLK "SM16716 CLK" +#define D_SENSOR_SM16716_DAT "SM16716 DAT" +#define D_SENSOR_SM16716_POWER "SM16716 PWR" +#define D_SENSOR_MY92X1_DI "MY92x1 DI" +#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI" +#define D_SENSOR_ARIRFRCV "ALux IrRcv" +#define D_SENSOR_ARIRFSEL "ALux IrSel" +#define D_SENSOR_TXD "Serial Tx" +#define D_SENSOR_RXD "Serial Rx" +#define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" +#define D_SENSOR_ADE7953_IRQ "ADE7953 IRQ" +#define D_SENSOR_BUZZER "Buzzer" +#define D_SENSOR_OLED_RESET "OLED Reset" +#define D_SENSOR_ZIGBEE_TXD "Zigbee Tx" +#define D_SENSOR_ZIGBEE_RXD "Zigbee Rx" +#define D_SENSOR_SOLAXX1_TX "SolaxX1 Tx" +#define D_SENSOR_SOLAXX1_RX "SolaxX1 Rx" +#define D_SENSOR_IBEACON_TX "iBeacon TX" +#define D_SENSOR_IBEACON_RX "iBeacon RX" +#define D_SENSOR_RDM6300_RX "RDM6300 RX" +#define D_SENSOR_CC1101_CS "CC1101 CS" +#define D_SENSOR_A4988_DIR "A4988 DIR" +#define D_SENSOR_A4988_STP "A4988 STP" +#define D_SENSOR_A4988_ENA "A4988 ENA" +#define D_SENSOR_A4988_MS1 "A4988 MS1" +#define D_SENSOR_A4988_MS2 "A4988 MS2" +#define D_SENSOR_A4988_MS3 "A4988 MS3" +#define D_SENSOR_DDS2382_TX "DDS238-2 Tx" +#define D_SENSOR_DDS2382_RX "DDS238-2 Rx" +#define D_SENSOR_DDSU666_TX "DDSU666 Tx" +#define D_SENSOR_DDSU666_RX "DDSU666 Rx" +#define D_SENSOR_SM2135_CLK "SM2135 Clk" +#define D_SENSOR_SM2135_DAT "SM2135 Dat" +#define D_SENSOR_DEEPSLEEP "DeepSleep" +#define D_SENSOR_EXS_ENABLE "EXS Enable" +#define D_SENSOR_SLAVE_TX "Slave TX" +#define D_SENSOR_SLAVE_RX "Slave RX" +#define D_SENSOR_SLAVE_RESET "Slave RST" +#define D_SENSOR_GPS_RX "GPS RX" +#define D_SENSOR_GPS_TX "GPS TX" +#define D_SENSOR_HM10_RX "HM10 RX" +#define D_SENSOR_HM10_TX "HM10 TX" +#define D_SENSOR_LE01MR_RX "LE-01MR Rx" +#define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" +#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" +#define D_SENSOR_HRXL_RX "HRXL Rx" + +// Units +#define D_UNIT_AMPERE "A" +#define D_UNIT_CENTIMETER "cm" +#define D_UNIT_HERTZ "Hz" +#define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" +#define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" +#define D_UNIT_KILOOHM "kΩ" +#define D_UNIT_KILOWATTHOUR "kWh" +#define D_UNIT_LUX "lx" +#define D_UNIT_MICROGRAM_PER_CUBIC_METER "µg/m³" +#define D_UNIT_MICROMETER "µm" +#define D_UNIT_MICROSECOND "µs" +#define D_UNIT_MILLIAMPERE "mA" +#define D_UNIT_MILLIMETER "mm" +#define D_UNIT_MILLIMETER_MERCURY "mmHg" +#define D_UNIT_MILLISECOND "ms" +#define D_UNIT_MINUTE "Min" +#define D_UNIT_PARTS_PER_BILLION "ppb" +#define D_UNIT_PARTS_PER_DECILITER "ppd" +#define D_UNIT_PARTS_PER_MILLION "ppm" +#define D_UNIT_PRESSURE "hPa" +#define D_UNIT_SECOND "sec" +#define D_UNIT_SECTORS "sectors" +#define D_UNIT_VA "VA" +#define D_UNIT_VAR "VAr" +#define D_UNIT_VOLT "V" +#define D_UNIT_WATT "W" +#define D_UNIT_WATTHOUR "Wh" +#define D_UNIT_WATT_METER_QUADRAT "W/m²" + +//SDM220, SDM120, LE01MR +#define D_PHASE_ANGLE "Unghi de fază" +#define D_IMPORT_ACTIVE "Import Activ" +#define D_EXPORT_ACTIVE "Export Activ" +#define D_IMPORT_REACTIVE "Import Reactiv" +#define D_EXPORT_REACTIVE "Export Reactiv" +#define D_TOTAL_REACTIVE "Total Reactiv" +#define D_UNIT_KWARH "kVArh" +#define D_UNIT_ANGLE "Deg" +#define D_TOTAL_ACTIVE "Total Activ" + +//SOLAXX1 +#define D_PV1_VOLTAGE "PV1 Voltaj" +#define D_PV1_CURRENT "PV1 Curent" +#define D_PV1_POWER "PV1 Putere" +#define D_PV2_VOLTAGE "PV2 Voltaj" +#define D_PV2_CURRENT "PV2 Curent" +#define D_PV2_POWER "PV2 Putere" +#define D_SOLAR_POWER "Putere Solară" +#define D_INVERTER_POWER "Invertor Putere" +#define D_STATUS "Status" +#define D_WAITING "Așteptare" +#define D_CHECKING "Verificare" +#define D_WORKING "Lucrează" +#define D_FAILURE "Eroare" +#define D_SOLAX_ERROR_0 "Fără cod de eroare" +#define D_SOLAX_ERROR_1 "Eroare zona" +#define D_SOLAX_ERROR_2 "Eroare zona voltaj" +#define D_SOLAX_ERROR_3 "Eroare zona frecvență" +#define D_SOLAX_ERROR_4 "Pv Eroare Voltaj" +#define D_SOLAX_ERROR_5 "Eroare Isolație" +#define D_SOLAX_ERROR_6 "Eroare temperatură ridicată" +#define D_SOLAX_ERROR_7 "Eroare ventilator" +#define D_SOLAX_ERROR_8 "Eroare alt echipament" + +//xdrv_10_scripter.ino +#define D_CONFIGURE_SCRIPT "Configurare script" +#define D_SCRIPT "editează script" +#define D_SDCARD_UPLOAD "Încarcă fișier" +#define D_SDCARD_DIR "director sd card" +#define D_UPL_DONE "Terminat" +#define D_SCRIPT_CHARS_LEFT "caractere rămase" +#define D_SCRIPT_CHARS_NO_MORE "caractere terminate" +#define D_SCRIPT_DOWNLOAD "Descarcă" +#define D_SCRIPT_ENABLE "abilitează script" +#define D_SCRIPT_UPLOAD "Încarcă" +#define D_SCRIPT_UPLOAD_FILES "Încarcă fișiere" + +#endif // _LANGUAGE_RO_RO_H_ diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 77c0771ee..a62c6d191 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -326,6 +326,7 @@ //#define MY_LANGUAGE pl-PL // Polish in Poland //#define MY_LANGUAGE pt-BR // Portuguese in Brazil //#define MY_LANGUAGE pt-PT // Portuguese in Portugal +//#define MY_LANGUAGE ro-RO // Romanian in Romania //#define MY_LANGUAGE ru-RU // Russian in Russia //#define MY_LANGUAGE sk-SK // Slovak in Slovakia //#define MY_LANGUAGE sv-SE // Swedish in Sweden From 46e6c3a7964d540c7c7b4a5db476e590e886c869 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Mar 2020 12:18:32 +0100 Subject: [PATCH 544/559] Fix RO compilation --- RELEASENOTES.md | 1 + tasmota/CHANGELOG.md | 1 + tasmota/language/ro-RO.h | 6 +++--- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 38ba097b4..ceec8285b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -113,3 +113,4 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) - Add support for Jarolift rollers by Keeloq algorithm - Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) +- Add support for Romanian language translations by Augustin Marti diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 4a30b6cad..f33d217bb 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -8,6 +8,7 @@ - Add support for Jarolift rollers by Keeloq algorithm - Add Zigbee features and improvements and remove support for Zigbee commands starting with ``Zigbee...`` - Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) +- Add support for Romanian language translations by Augustin Marti ### 8.1.0.9 20200220 diff --git a/tasmota/language/ro-RO.h b/tasmota/language/ro-RO.h index cc75273af..2db7cf4ba 100644 --- a/tasmota/language/ro-RO.h +++ b/tasmota/language/ro-RO.h @@ -1,7 +1,7 @@ /* ro-RO.h - localization for Romanian - Romania and Moldova for Tasmota - Copyright (C) 2020 Theo Arends + Copyright (C) 2020 Augustin Marti 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 @@ -76,7 +76,7 @@ #define D_COUNTER "Contor" #define D_CT_POWER "Putere Transformată" #define D_CURRENT "Curent" // As in Voltage and Current -#define D_DA;TA "Date" +#define D_DATA "Date" #define D_DARKLIGHT "Întunecat" #define D_DEBUG "Depanare" #define D_DISABLED "Dezactivat" @@ -520,7 +520,7 @@ #define D_SENSOR_SI7021 "SI7021" #define D_SENSOR_DS18X20 "DS18x20" #define D_SENSOR_I2C_SCL "I2C SCL" -#define D_SENSOR_I2C_SDA ; "I2C SDA" +#define D_SENSOR_I2C_SDA "I2C SDA" #define D_SENSOR_WS2812 "WS2812" #define D_SENSOR_DFR562 "MP3 Player" #define D_SENSOR_IRSEND "IRsend" From 71e702c6594eeab81308bdfbc8b14dda906bdc59 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Mar 2020 15:36:37 +0100 Subject: [PATCH 545/559] Change minimal filename construction --- tasmota/support_tasmota.ino | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 43e73321d..fe0153f78 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -921,14 +921,17 @@ void Every250mSeconds(void) // Replace tasmota.xyz with tasmota-minimal.xyz // Replace tasmota.bin.gz with tasmota-minimal.bin.gz // Replace tasmota.xyz.gz with tasmota-minimal.xyz.gz + // Replace tasmota.ino.bin with tasmota-minimal.ino.bin // Replace http://domus1:80/api/arduino/tasmota.bin with http://domus1:80/api/arduino/tasmota-minimal.bin // Replace http://domus1:80/api/arduino/tasmota.bin.gz with http://domus1:80/api/arduino/tasmota-minimal.bin.gz // Replace http://domus1:80/api/arduino/tasmota-DE.bin.gz with http://domus1:80/api/arduino/tasmota-minimal.bin.gz // Replace http://domus1:80/api/ard-uino/tasmota-DE.bin.gz with http://domus1:80/api/ard-uino/tasmota-minimal.bin.gz + // Replace http://192.168.2.17:80/api/arduino/tasmota.bin with http://192.168.2.17:80/api/arduino/tasmota-minimal.bin + // Replace http://192.168.2.17/api/arduino/tasmota.bin.gz with http://192.168.2.17/api/arduino/tasmota-minimal.bin.gz char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it if (bch == nullptr) { bch = mqtt_data; } // No path found so use filename only - +/* char *ech = strrchr(bch, '.'); // Find file type in filename (none, .bin or .gz) if ((ech != nullptr) && (0 == strncasecmp_P(ech, PSTR(".GZ"), 3))) { char *fch = ech; @@ -936,9 +939,14 @@ void Every250mSeconds(void) ech = strrchr(bch, '.'); // Find file type .bin.gz *fch = '.'; } +*/ + char *ech = strchr(bch, '.'); // Find file type in filename (none, .ino.bin, .ino.bin.gz, .bin, .bin.gz or .gz) if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } + +//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: File type [%s]"), ech); + char ota_url_type[strlen(ech) +1]; - strncpy(ota_url_type, ech, sizeof(ota_url_type)); // Either empty, .bin or .bin.gz + strncpy(ota_url_type, ech, sizeof(ota_url_type)); // Either empty, .ino.bin, .ino.bin.gz, .bin, .bin.gz or .gz char *pch = strrchr(bch, '-'); // Find last dash (-) and ignore remainder - handles tasmota-DE if (pch == nullptr) { pch = ech; } // No dash so ignore filetype From 50b19712ac04ff32d2118c929a74be7431c2baa9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Mar 2020 15:51:50 +0100 Subject: [PATCH 546/559] Fix DS1624 with KNX compilation error Fix DS1624 with KNX compilation error (#7853) --- tasmota/xsns_59_ds1624.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xsns_59_ds1624.ino b/tasmota/xsns_59_ds1624.ino index be0bcf9e5..f3ffcd1f1 100644 --- a/tasmota/xsns_59_ds1624.ino +++ b/tasmota/xsns_59_ds1624.ino @@ -190,7 +190,7 @@ void DS1624Show(bool json) DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ #ifdef USE_KNX - KnxSensor(KNX_TEMPERATURE, temperature); + KnxSensor(KNX_TEMPERATURE, ds1624_sns[i].value); #endif // USE_KNX once = false; } From 74f1ad8a1beeb34a47fac3b3dc2a93f22aa3629e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Mar 2020 16:34:06 +0100 Subject: [PATCH 547/559] Fix APDS9960 compile error --- tasmota/xsns_27_apds9960.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasmota/xsns_27_apds9960.ino b/tasmota/xsns_27_apds9960.ino index fe8f0ffec..c426d535a 100644 --- a/tasmota/xsns_27_apds9960.ino +++ b/tasmota/xsns_27_apds9960.ino @@ -240,7 +240,7 @@ const char HTTP_APDS_9960_SNS[] PROGMEM = #define DEFAULT_GCONF3 0 // All photodiodes active during gesture #define DEFAULT_GIEN 0 // Disable gesture interrupts -#define ERROR 0xFF +#define APDS9960_ERROR 0xFF /* Direction definitions */ enum { @@ -1530,7 +1530,7 @@ int16_t readGesture(void) (uint8_t*)fifo_data, (fifo_level * 4) ); if( bytes_read == -1 ) { - return ERROR; + return APDS9960_ERROR; } /* If at least 1 set of data, sort the data into U/D/L/R */ From 0006d44e6304dc28534c560a97de94f5eacf2003 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 4 Mar 2020 18:02:27 +0100 Subject: [PATCH 548/559] Fix HASS button discovery --- tasmota/support_tasmota.ino | 6 ++++-- tasmota/xdrv_02_mqtt.ino | 7 +++++++ tasmota/xdrv_12_home_assistant.ino | 20 ++++++++++++-------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index fe0153f78..19f592a18 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -424,6 +424,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) char scommand[CMDSZ]; char key_topic[TOPSZ]; bool result = false; + uint32_t device_save = device; char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_BUTTON_TOPIC); Format(key_topic, tmp, sizeof(key_topic)); @@ -459,7 +460,7 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state) result = XdrvRulesProcess(); } int32_t payload_save = XdrvMailbox.payload; - XdrvMailbox.payload = key << 16 | state << 8 | device; + XdrvMailbox.payload = device_save << 24 | key << 16 | state << 8 | device; XdrvCall(FUNC_ANY_KEY); XdrvMailbox.payload = payload_save; return result; @@ -922,6 +923,7 @@ void Every250mSeconds(void) // Replace tasmota.bin.gz with tasmota-minimal.bin.gz // Replace tasmota.xyz.gz with tasmota-minimal.xyz.gz // Replace tasmota.ino.bin with tasmota-minimal.ino.bin + // Replace tasmota.ino.bin.gz with tasmota-minimal.ino.bin.gz // Replace http://domus1:80/api/arduino/tasmota.bin with http://domus1:80/api/arduino/tasmota-minimal.bin // Replace http://domus1:80/api/arduino/tasmota.bin.gz with http://domus1:80/api/arduino/tasmota-minimal.bin.gz // Replace http://domus1:80/api/arduino/tasmota-DE.bin.gz with http://domus1:80/api/arduino/tasmota-minimal.bin.gz @@ -941,7 +943,7 @@ void Every250mSeconds(void) } */ char *ech = strchr(bch, '.'); // Find file type in filename (none, .ino.bin, .ino.bin.gz, .bin, .bin.gz or .gz) - if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } + if (ech == nullptr) { ech = mqtt_data + strlen(mqtt_data); } // Point to '/0' at end of mqtt_data becoming an empty string //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("OTA: File type [%s]"), ech); diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index b7bd00aa7..c766ab247 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -712,6 +712,13 @@ void MqttCheck(void) } } +bool ButtonTopicActive(void) +{ + char key_topic[TOPSZ]; + Format(key_topic, SettingsText(SET_MQTT_BUTTON_TOPIC), sizeof(key_topic)); + return ((strlen(key_topic) != 0) && strcmp(key_topic, "0")); +} + /*********************************************************************************************\ * Commands \*********************************************************************************************/ diff --git a/tasmota/xdrv_12_home_assistant.ino b/tasmota/xdrv_12_home_assistant.ino index fde47a623..7da0ad380 100644 --- a/tasmota/xdrv_12_home_assistant.ino +++ b/tasmota/xdrv_12_home_assistant.ino @@ -53,9 +53,9 @@ const char HASS_DISCOVER_BASE[] PROGMEM = "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_RELAY[] PROGMEM = - ",\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2 - "\"val_tpl\":\"{{value_json.%s}}\"," // POWER2 - "\"pl_off\":\"%s\"," // OFF + ",\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2 + "\"val_tpl\":\"{{value_json.%s}}\"," // POWER2 + "\"pl_off\":\"%s\"," // OFF "\"pl_on\":\"%s\""; // ON const char HASS_DISCOVER_BUTTON_TOGGLE[] PROGMEM = @@ -368,7 +368,7 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const char unique_id[30]; mqtt_data[0] = '\0'; // Clear retained message - // Clear or Set topic + // Clear or Set topic char subname[20]; NoAlNumToUnderscore(subname, MultiSubName); //Replace all non alphaumeric characters to '_' to avoid topic name issues snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subname); @@ -504,7 +504,7 @@ void HAssAnnounceStatusSensor(void) TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), WiFi.macAddress().c_str(), SettingsText(SET_FRIENDLYNAME1), ModuleName().c_str(), my_version, my_image); - + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); @@ -568,9 +568,13 @@ void HAssAnyKey(void) return; } // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59) - uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; - uint32_t device = XdrvMailbox.payload & 0xFF; - uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; + uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; // 0 = Button, 1 = Switch + uint32_t device = XdrvMailbox.payload & 0xFF; // Device number or 1 if more Buttons than Devices + uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // 0 = Off, 1 = On, 2 = Toggle + + if (!key && ButtonTopicActive()) { // Button and ButtonTopic is active + device = (XdrvMailbox.payload >> 24) & 0xFF; // Button number + } char scommand[CMDSZ]; snprintf_P(scommand, sizeof(scommand), PSTR("%s%d"), (key) ? "SWITCH" : "BUTTON", device); From 8855d2a2185ce507a58857d94f96eab29d636cf2 Mon Sep 17 00:00:00 2001 From: Hadinger Date: Wed, 4 Mar 2020 21:00:57 +0100 Subject: [PATCH 549/559] Add Zigbee use distinct MQTT topics per device for SENSOR, allowing retained messages (#7835) --- tasmota/CHANGELOG.md | 1 + tasmota/settings.h | 2 +- tasmota/xdrv_23_zigbee_3_devices.ino | 12 ++++++++---- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index f33d217bb..b1d84e701 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -9,6 +9,7 @@ - Add Zigbee features and improvements and remove support for Zigbee commands starting with ``Zigbee...`` - Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) - Add support for Romanian language translations by Augustin Marti +- Add Zigbee use distinct MQTT topics per device for SENSOR, allowing retained messages (#7835) ### 8.1.0.9 20200220 diff --git a/tasmota/settings.h b/tasmota/settings.h index 37734b32a..673758890 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -108,7 +108,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t led_timeout : 1; // bit 4 (v8.1.0.9) - SetOption86 - PWM Dimmer Turn brightness LED's off 5 seconds after last change uint32_t powered_off_led : 1; // bit 5 (v8.1.0.9) - SetOption87 - PWM Dimmer Turn red LED on when powered off uint32_t remote_device_mode : 1; // bit 6 (v8.1.0.9) - SetOption88 - PWM Dimmer Buttons control remote devices - uint32_t spare07 : 1; + uint32_t zigbee_distinct_topics : 1; // bit 7 (v8.1.0.10) - SetOption89 - Distinct MQTT topics per device for Zigbee (#7835) uint32_t spare08 : 1; uint32_t spare09 : 1; uint32_t spare10 : 1; diff --git a/tasmota/xdrv_23_zigbee_3_devices.ino b/tasmota/xdrv_23_zigbee_3_devices.ino index d814a8c0c..121961eda 100644 --- a/tasmota/xdrv_23_zigbee_3_devices.ino +++ b/tasmota/xdrv_23_zigbee_3_devices.ino @@ -758,13 +758,17 @@ void Z_Devices::jsonPublishFlush(uint16_t shortaddr) { if (use_fname) { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"%s\":%s}}"), fname->c_str(), msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); } else { Response_P(PSTR("{\"" D_JSON_ZIGBEE_RECEIVED "\":{\"0x%04X\":%s}}"), shortaddr, msg.c_str()); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR)); - XdrvRulesProcess(); } + if (Settings.flag4.zigbee_distinct_topics) { + char subtopic[16]; + snprintf_P(subtopic, sizeof(subtopic), PSTR("%04X/" D_RSLT_SENSOR), shortaddr); + MqttPublishPrefixTopic_P(TELE, subtopic, Settings.flag.mqtt_sensor_retain); + } else { + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + } + XdrvRulesProcess(); } void Z_Devices::jsonPublishNow(uint16_t shortaddr, JsonObject & values) { From a8e369e5cefd09847f01a3fac5be2356e8844a97 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Mar 2020 14:00:47 +0100 Subject: [PATCH 550/559] Update feature information --- RELEASENOTES.md | 8 ++++++-- tasmota/CHANGELOG.md | 7 +++++-- tasmota/support_features.ino | 2 +- tools/decode-status.py | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ceec8285b..da7f0cf31 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -78,7 +78,12 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Fix relation between RSSI and signal strength - Add command ``SetOption79 0/1`` to enable reset of counters at teleperiod time by Andre Thomas (#7355) - Add command ``SetOption82 0/1`` to limit the CT range for Alexa to 200..380 -- Add command ``SetOption84 1`` to send AWS IoT device shadow updates (alternative to retained) +- Add command ``SetOption84 0/1`` to send AWS IoT device shadow updates (alternative to retained) +- Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) +- Add command ``SetOption86 0/1`` for PWM dimmer to turn brightness LED's off 5 seconds after last change +- Add command ``SetOption87 0/1`` for PWM dimmer to turn red LED on when powered off +- Add command ``SetOption88 0/1`` for PWM dimmer to let buttons control remote devices +- Add command ``SetOption89 0/1`` for Zigbee distinct MQTT topics per device for SENSOR, allowing retained messages (#7835) - Add command ``ShutterButton `` to control shutter(s) by to-scho (#7403) - Add commands ``SwitchMode 8`` ToggleMulti, ``SwitchMode 9`` FollowMulti and ``SwitchMode 10`` FollowMultiInverted (#7522) - Add commands ``SwitchMode 11`` PushHoldMulti and ``SwitchMode 12`` PushHoldInverted (#7603) @@ -109,7 +114,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c - Add support for Wemos Motor Shield V1 by Denis Sborets (#7764) - Add Zigbee enhanced commands decoding, added ``ZbPing`` - Add Zigbee features and improvements -- Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) - Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) - Add support for Jarolift rollers by Keeloq algorithm - Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index b1d84e701..90f2a711a 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -9,7 +9,7 @@ - Add Zigbee features and improvements and remove support for Zigbee commands starting with ``Zigbee...`` - Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders by Jon Little (#7814) - Add support for Romanian language translations by Augustin Marti -- Add Zigbee use distinct MQTT topics per device for SENSOR, allowing retained messages (#7835) +- Add command ``SetOption89 0/1`` for Zigbee distinct MQTT topics per device for SENSOR, allowing retained messages (#7835) ### 8.1.0.9 20200220 @@ -20,6 +20,9 @@ - Add Zigbee enhanced commands decoding, added ``ZbPing`` - Add commands ``SetOption85 0/1`` and ``DevGroupShare`` supporting UDP Group command using ``GroupTopic`` without MQTT by Paul Diem (#7790) - Add support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches by Paul Diem (#7791) +- Add command ``SetOption86 0/1`` for PWM dimmer to turn brightness LED's off 5 seconds after last change +- Add command ``SetOption87 0/1`` for PWM dimmer to turn red LED on when powered off +- Add command ``SetOption88 0/1`` for PWM dimmer to let buttons control remote devices ### 8.1.0.8 20200212 @@ -52,7 +55,7 @@ - Change wifi connectivity stability (#7602) - Change IRremoteESP8266 library updated to v2.7.3 - Fix PWM flickering at low levels (#7415) -- Add ``SetOption84 1`` sends AWS IoT device shadow updates (alternative to retained) +- Add ``SetOption84 0/1`` sends AWS IoT device shadow updates (alternative to retained) - Add ``ZbBind`` (experimental) and bug fixes ### 8.1.0.4 20200116 diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 4049d9cfe..961dd1091 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -537,7 +537,7 @@ void GetFeatures(void) feature6 |= 0x00000002; // xsns_64_hrxl.ino #endif #ifdef USE_SONOFF_D1 - feature6 |= 0x00000004; + feature6 |= 0x00000004; // xdrv_37_sonoff_d1.ino #endif // feature6 |= 0x00000008; diff --git a/tools/decode-status.py b/tools/decode-status.py index 6c5dd6a5b..fe80630cc 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -143,7 +143,7 @@ a_setoption = [[ "PWM Dimmer Turn brightness LED's off 5 seconds after last change", "PWM Dimmer Turn red LED on when powered off", "PWM Dimmer Buttons control remote devices", - "", + "Distinct MQTT topics per device for Zigbee", "","","","", "","","","", "","","","", @@ -239,7 +239,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200301 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200305 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj)) From f4047b43379a290373a3fa08321ae8fe0e1b4772 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Mar 2020 14:53:51 +0100 Subject: [PATCH 551/559] Fix GUI channel offset Fix GUI channel offset when relays are present (#7855) --- tasmota/xdrv_01_webserver.ino | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 6bc4d2b16..31398f60d 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1274,12 +1274,13 @@ bool HandleRootStatusRefresh(void) snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_WHITE " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } + uint32_t light_device = LightDevice(); // Channel number offset uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7); - for (uint32_t j = 1; j <= pwm_channels; j++) { - snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j); + for (uint32_t j = 0; j < pwm_channels; j++) { + snprintf_P(webindex, sizeof(webindex), PSTR("e%d"), j +1); WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent if (strlen(tmp)) { - snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j, tmp); + snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_CHANNEL "%d %s"), j +light_device, tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } } From c52680f836c948c3dd42140076af13aace5c2f9e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 5 Mar 2020 18:45:43 +0100 Subject: [PATCH 552/559] Fix -minimal compile error --- tasmota/xdrv_01_webserver.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 31398f60d..2dff240ad 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -1264,6 +1264,7 @@ bool HandleRootStatusRefresh(void) } #endif // USE_SONOFF_IFAN } +#ifdef USE_LIGHT WebGetArg("d0", tmp, sizeof(tmp)); // 0 - 100 Dimmer value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); @@ -1299,6 +1300,7 @@ bool HandleRootStatusRefresh(void) snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } +#endif // USE_LIGHT #ifdef USE_SHUTTER for (uint32_t j = 1; j <= shutters_present; j++) { snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j); From d16f1a7a0fe44851bc7dd937b6d94f10979ef455 Mon Sep 17 00:00:00 2001 From: Paul C Diem Date: Thu, 5 Mar 2020 17:51:22 -0600 Subject: [PATCH 553/559] Add Light skip_light_fade flag and Dimmer3 command, Ignore MCU dimmer changes after sending dimmer command --- tasmota/support_device_groups.ino | 9 ++------- tasmota/tasmota.ino | 1 + tasmota/xdrv_04_light.ino | 19 +++++++++++++++++-- tasmota/xdrv_16_tuyamcu.ino | 17 +++++++++++------ 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino index 01404b1cb..b6df25606 100644 --- a/tasmota/support_device_groups.ino +++ b/tasmota/support_device_groups.ino @@ -511,9 +511,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) */ XdrvMailbox.command = nullptr; // Indicates the source is a device group update XdrvMailbox.index = flags | device_group_index << 16; - - light_fade = Settings.light_fade; - if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) Settings.light_fade = false; + if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true; for (;;) { if (packet_length - (message_ptr - packet) < 1) goto badmsg; // Malformed message @@ -549,9 +547,6 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length) value |= *message_ptr++ << 24; } } - else if (item == DGR_ITEM_LIGHT_FADE) { - light_fade = value; - } #ifdef DEVICE_GROUPS_DEBUG AddLog_P2(LOG_LEVEL_DEBUG, PSTR(" 0 && value <= 40) { Settings.light_speed = value; @@ -2488,10 +2494,17 @@ void CmndDimmer(void) // Dimmer0 0..100 - Change both RGB and W(W) Dimmers // Dimmer1 0..100 - Change RGB Dimmer // Dimmer2 0..100 - Change W(W) Dimmer + // Dimmer3 0..100 - Change both RGB and W(W) Dimmers with no fading // Dimmer + - Incerement Dimmer in steps of 10 // Dimmer - - Decrement Dimmer in steps of 10 uint32_t dimmer; - if (XdrvMailbox.index > 2) { XdrvMailbox.index = 1; } + if (XdrvMailbox.index == 3) { + skip_light_fade = true; + XdrvMailbox.index = 0; + } + else if (XdrvMailbox.index > 2) { + XdrvMailbox.index = 1; + } if ((light_controller.isCTRGBLinked()) || (0 == XdrvMailbox.index)) { dimmer = light_state.getDimmer(); @@ -2524,9 +2537,11 @@ void CmndDimmer(void) } } Light.update = true; + if (skip_light_fade) LightAnimate(); } else { ResponseCmndNumber(dimmer); } + skip_light_fade = false; } #endif // USE_LIGHT diff --git a/tasmota/xdrv_16_tuyamcu.ino b/tasmota/xdrv_16_tuyamcu.ino index f250f6409..466c3faf1 100644 --- a/tasmota/xdrv_16_tuyamcu.ino +++ b/tasmota/xdrv_16_tuyamcu.ino @@ -68,6 +68,7 @@ struct TUYA { int byte_counter = 0; // Index in serial receive buffer bool low_power_mode = false; // Normal or Low power mode protocol bool send_success_next_second = false; // Second command success in low power mode + uint32_t ignore_dimmer_cmd_timeout = 0;// Time until which received dimmer commands should be ignored } Tuya; @@ -366,6 +367,7 @@ bool TuyaSetPower(void) if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction TuyaSendBool(dpid, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1)); + delay(20); // Hack when power is off and dimmer is set then both commands go too soon to Serial out. status = true; } return status; @@ -374,7 +376,7 @@ bool TuyaSetPower(void) bool TuyaSetChannels(void) { LightSerialDuty(((uint8_t*)XdrvMailbox.data)[0]); - delay(20); // Hack when power is off and dimmer is set then both commands go too soon to Serial out. + //delay(20); // Hack when power is off and dimmer is set then both commands go too soon to Serial out. return true; } @@ -386,6 +388,7 @@ void LightSerialDuty(uint16_t duty) if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself if (Tuya.new_dim != duty) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid); + Tuya.ignore_dimmer_cmd_timeout = millis() + 250; // Ignore serial received dim commands for the next 250ms TuyaSendValue(dpid, duty); } } else if (dpid > 0) { @@ -456,12 +459,14 @@ void TuyaProcessStatePacket(void) { if (fnId == TUYA_MCU_FUNC_DIMMER) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), packetValue); Tuya.new_dim = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100); - if ((power || Settings.flag3.tuya_apply_o20) && // SetOption54 - Apply SetOption20 settings to Tuya device - (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { - Tuya.ignore_dim = true; + if (Tuya.ignore_dimmer_cmd_timeout < millis()) { + if ((power || Settings.flag3.tuya_apply_o20) && // SetOption54 - Apply SetOption20 settings to Tuya device + (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) { + Tuya.ignore_dim = true; - snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Tuya.new_dim ); - ExecuteCommand(scmnd, SRC_SWITCH); + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER "3 %d"), Tuya.new_dim ); + ExecuteCommand(scmnd, SRC_SWITCH); + } } } From 0b36bedace6410cf392ae523251f88a3476046a6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Fri, 6 Mar 2020 13:02:25 +0100 Subject: [PATCH 554/559] Use latest feature stage version for Tasmota... Core Stage. udp: fix again pbuf management --- platformio_override_sample.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini index 814c1e75c..fd5c86fdc 100644 --- a/platformio_override_sample.ini +++ b/platformio_override_sample.ini @@ -180,7 +180,7 @@ build_flags = ${esp82xx_defaults.build_flags} [tasmota_core_stage] ; *** Esp8266 core for Arduino version stable beta platform = espressif8266@2.3.3 -platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#abdd2bdbb6a5caf31807d82ebd7b447947a9c360 +platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#372a3ec297dfe8501bed1ec4552244695b5e8ced build_flags = ${esp82xx_defaults.build_flags} -DBEARSSL_SSL_BASIC ; NONOSDK221 From bd98c1816ccbe507f7a3a6a7ed67735db63abd91 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 6 Mar 2020 15:52:46 +0100 Subject: [PATCH 555/559] Update TEMPLATE and RELEASE info --- MODULES.md | 3 +- RELEASENOTES.md | 8 +- TEMPLATES.md | 1630 ++++--- arduino/version 2.6.1/boards.txt | 7122 ---------------------------- arduino/version 2.6.1/platform.txt | 171 - 5 files changed, 1103 insertions(+), 7831 deletions(-) delete mode 100644 arduino/version 2.6.1/boards.txt delete mode 100644 arduino/version 2.6.1/platform.txt diff --git a/MODULES.md b/MODULES.md index be1d5d110..b47769998 100644 --- a/MODULES.md +++ b/MODULES.md @@ -77,5 +77,6 @@ Module | Description 71 Sonoff iFan03 | Sonoff iFan03 Wifi Smart Ceiling Fan with Light 72 EXS Dimmer | EXS Wifi Dimmer v4 73 PWM Dimmer | Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM Dimmer Switches +74 Sonoff D1 | Sonoff D1 Wifi and RF Dimmer -Over 600 additional devices are supported using [templates](TEMPLATES.md). +Over 1000 additional devices are supported using [templates](TEMPLATES.md). diff --git a/RELEASENOTES.md b/RELEASENOTES.md index da7f0cf31..2fc828a40 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -21,7 +21,7 @@ While fallback or downgrading is common practice it was never supported due to S ## Supported Core versions -This release will be supported from ESP8266/Arduino library Core version **2.6.1** due to reported security and stability issues on previous Core version. +This release will be supported from ESP8266/Arduino library Core version **2.6.3 + 372a3ec** due to reported security and stability issues on previous Core version. This will also support gzipped binaries. Although it might still compile on previous Core versions all support will be removed in the near future. @@ -35,11 +35,11 @@ For initial configuration this release supports Webserver based **WifiManager** ## Provided Binary Downloads -The following binary downloads have been compiled with ESP8266/Arduino library core version **2.6.1**. +The following binary downloads have been compiled with ESP8266/Arduino library core version **2.6.3 + 372a3ec**. -- **tasmota.bin** = The Tasmota version with sensors. **RECOMMENDED RELEASE BINARY** +- **tasmota.bin** = The Tasmota version with most drivers. **RECOMMENDED RELEASE BINARY** - **tasmota-BG.bin** to **tasmota-TW.bin** = The Tasmota version in different languages. -- **tasmota-lite.bin** = The Lite version without most sensors. +- **tasmota-lite.bin** = The Lite version without most drivers and sensors. - **tasmota-knx.bin** = The Knx version without some features but adds KNX support. - **tasmota-sensors.bin** = The Sensors version adds more useful sensors. - **tasmota-ir** = The InfraRed Receiver and transmitter version allowing all available protocols provided by library IRremoteESP8266 but without most other features. diff --git a/TEMPLATES.md b/TEMPLATES.md index d922a4174..e34fb2ea5 100644 --- a/TEMPLATES.md +++ b/TEMPLATES.md @@ -2,613 +2,1177 @@ # Templates -Find below the available templates as of October 22nd, 2019. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) +Find below the available templates as of March 2020. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates) -## Bulb +## Aromatherapy Diffuser ``` -A19 RGBW 8W E26 {"NAME":"OOOLED 60W RGB","GPIO":[255,255,255,255,39,40,255,255,37,255,38,255,255],"FLAG":1,"BASE":18} -Aisirer 9W A19 E26 {"NAME":"AISIRER E26","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Anoopsyche CW/WW 60W {"NAME":"Anoop-CW-WW","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} -Aoycocr A19 {"NAME":"AoycocrA19","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} -Arlec GLD112HA {"NAME":"Arlec CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} -Arlec GLD122HA {"NAME":"Arlec RGBWW","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Ausein E14 7W White {"NAME":"Tuya RGBW","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18} -Avatar 5W E14 {"NAME":"AVATAR","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -BNeta A60 E27 {"NAME":"OM60/RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18} -BNeta GU10 RGB {"NAME":"BNeta","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18} -Bomcosy 7W E27 RGB CW {"NAME":"Generic","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18} -Brilliant 20741 {"NAME":"Brilliant RGB+","GPIO":[255,255,255,255,37,40,255,255,38,0,39,0,0],"FLAG":0,"BASE":18} -Brilliant HK17653S72 {"NAME":"Brilliant E14 ","GPIO":[255,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18} -Candle 6W E14/E27 RGBWW {"NAME":"E14_RGBWW_6W","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":20} -DGM L-WT9W1 {"NAME":"DGM L-WT9W1","GPIO":[0,0,0,0,140,142,0,0,38,37,141,0,0],"FLAG":0,"BASE":18} -electriQ RGBW B22 {"NAME":"ElectricQ B22","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} -EleLight 7W A19 E27 RGBW {"NAME":"EleLight 7wA19","GPIO":[255,255,255,255,140,37,255,255,255,142,141,255,255],"FLAG":0,"BASE":18} -Esicoo 9W E26 {"NAME":"Esicoo Bulb","GPIO":[0,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} -Fcmila 7W RGBW E27 {"NAME":"FCMILA 7W","GPIO":[255,255,255,255,39,40,255,255,37,255,38,255,255],"FLAG":0,"BASE":18} -Fcmila EQ723 {"NAME":"FCMILA LED E27","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18} -Fcmila FC-12W {"NAME":"SYF05","GPIO":[255,0,255,0,140,37,0,0,255,255,141,0,255],"FLAG":1,"BASE":69} -Feit Electric BPA800/RGBW/AG/2 {"NAME":" BPA800/RGBW","GPIO":[255,255,255,255,37,38,255,255,141,142,140,255,255],"FLAG":0,"BASE":48} -Feit Electric BR30/927CA/AG {"NAME":"Feit BR30 WW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Feit Electric BR30/950CA/AG {"NAME":"Feit BR30 CW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Feit Electric OM60/927CA/AG {"NAME":" Feit P_A800_2","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Feit Electric OM60/RGBW/CA/AG {"NAME":"OM60/RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18} -Geeni Lux A21 White {"NAME":"Geeni-1050-WW","GPIO":[0,0,0,0,37,37,0,0,38,0,0,0,0],"FLAG":1,"BASE":18} -Generic 10W E26/E27 RGBW {"NAME":"10W E27 RGBW","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} -Globe CW/WW {"NAME":"Globe CW/WW","GPIO":[0,0,0,0,38,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Globe RGBW {"NAME":"GlobeRGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} -Gosund E27 8W RGBW {"NAME":"Gosund RGB+W","GPIO":[255,255,255,255,40,255,255,255,37,38,39,255,255],"FLAG":0,"BASE":18} -Jomarto 9W B22 {"NAME":"Jomarto Wifi S","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":1,"BASE":18} -Kainsy 7W E27 RGBW {"NAME":"KAINSY","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} -Kogan SmarterHome™ White 10W B22 {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,37,40,0,0,41,38,39,0,0],"FLAG":0,"BASE":18} -Kohree A19 7W {"NAME":"Kohree VHP560","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} -LE A19 RGBCT 9W E26 {"NAME":"LE RGBWW 60W","GPIO":[255,0,255,0,140,37,0,0,38,142,141,0,255],"FLAG":1,"BASE":18} -Legelite E26 {"NAME":"Legelite E26","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Linganzh LWE3 6W RGBW {"NAME":"Linganzh LWE3 ","GPIO":[255,255,255,255,255,38,255,255,39,255,40,37,255],"FLAG":0,"BASE":18} -Lohas 5W E12 {"NAME":"LH-5W-ZN01204","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -Lohas 9W E26 RGBW {"NAME":"Lohas RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":18} -Lohas A19 RGBW E12 {"NAME":"Lohas","GPIO":[17,255,255,255,0,0,0,0,0,143,0,144,0],"FLAG":1,"BASE":26} -Lohas E14 R50 {"NAME":"Lohas E14 R50","GPIO":[17,255,255,255,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -Lohas ZN031 {"NAME":"Lohas ZN031","GPIO":[255,255,255,255,38,37,255,255,41,39,40,255,255],"FLAG":0,"BASE":18} -LSC Smart Connect Multicolor Spot GU10 {"NAME":"LSC RGBCW LED","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} -LSC Smart Connect Smart Filament LED {"NAME":"LSC-Filam-Big","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} -Lumiman E27 Multicolor {"NAME":"Lumiman RGB","GPIO":[255,255,255,255,37,40,255,255,38,41,39,52,255],"FLAG":1,"BASE":18} -Lumiman LM530 E26 {"NAME":"Lumiman LM530","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":1,"BASE":18} -Lumiman LM650 {"NAME":"Legelite E26","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Luminea ZX-2831 E27 CCT {"NAME":"Luminea CCT","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} -Luminea ZX-2832 E27 RGBW {"NAME":"Luminea RGBW","GPIO":[255,255,255,255,140,37,255,255,38,142,141,255,255],"FLAG":1,"BASE":18} -Lyasi PT-BW09 {"NAME":"Lyasi PT-BW09","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} -Maxcio YX-L01P-E7 {"NAME":"Maxcio YXL01P","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} -Merkury A19 60W {"NAME":"MI-BW902-999W","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Merkury A21 75W {"NAME":"MI-BW904-999W","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":1,"BASE":69} -Merkury BR30 65W {"NAME":"MI-BW905-999W","GPIO":[0,0,0,0,37,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} -Mirabella Genio CW {"NAME":"GenioBulbCW","GPIO":[0,0,0,0,38,37,0,0,0,40,39,0,0],"FLAG":0,"BASE":18} -Mirabella Genio Dimmable {"NAME":"GenioBulbCCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} -Mirabella Genio RGBW {"NAME":"GenioBulbRGB","GPIO":[255,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":1,"BASE":18} -Mixigoo 10W E27 RGBW {"NAME":"Mixigoo Bulb","GPIO":[255,255,255,255,41,38,255,255,39,255,37,40,255],"FLAG":0,"BASE":18} -MOKO YX-L01C-E27 {"NAME":"MOKO","GPIO":[17,255,255,255,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} -Nedis WIFILC10WTE27 {"NAME":"Nedis RGBW","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":1,"BASE":18} -Nedis WIFILW10WTE27 {"NAME":"WIFILW10WTE27","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} -NiteBird TT-WB4 {"NAME":"NiteBird TT-WB","GPIO":[255,255,255,255,40,255,255,255,37,38,39,255,255],"FLAG":0,"BASE":18} -Novostella 12W RGBCT E27 {"NAME":"Novostella","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Novostella B22 7W {"NAME":"Novostella B22","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} -Oobest RGBW E27 {"NAME":"WifiBulb","GPIO":[0,0,0,0,0,37,0,0,39,40,38,0,0],"FLAG":1,"BASE":18} -Oobest ZN93028 11W E27 RGB {"NAME":"RGB Bulb 11W","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":1,"BASE":18} -Reafoo 9W A26 {"NAME":"ReaFooE26","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} -RGBW 7W B22 {"NAME":"SM16716","GPIO":[255,255,255,255,140,37,255,255,255,255,141,255,255],"FLAG":0,"BASE":18} -RGBW 7W E14 {"NAME":"7W-E14-RGBW-La","GPIO":[255,255,255,255,38,37,255,255,39,255,40,255,255],"FLAG":0,"BASE":18} -Solimo 12W B22 RGBWW {"NAME":"Solimo RGBWW12","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Solimo 9W B22 RGBWW {"NAME":"Solimo RGBWW 9","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Sonoff B1 (R2) {"NAME":"Sonoff B1","GPIO":[17,255,255,255,0,0,0,0,143,0,144,0,0],"FLAG":0,"BASE":26} -TCP B22 RGBW {"NAME":"TCP Smart RGBW","GPIO":[255,255,255,255,140,37,0,0,38,142,141,255,255],"FLAG":0,"BASE":18} -Teckin SB50 {"NAME":"Teckin SB50","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18} -Teckin SB50 v2 {"NAME":"Teckin SB50","GPIO":[255,255,255,255,37,255,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} -Teckin SB50 V3 {"NAME":"Teckin SB50v3","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Teckin SB51 {"NAME":"Teckin SB51","GPIO":[255,255,255,255,40,255,255,255,38,39,37,255,255],"FLAG":0,"BASE":18} -Teckin SB53 {"NAME":"Teckin SB53","GPIO":[255,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -TikLOk 7.5W A19 E26 {"NAME":"TikLOk WW-CW-L","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} -Wipro Garnet B22 9W {"NAME":"WiproSmartBulb","GPIO":[255,255,255,255,37,41,255,255,38,40,39,255,255],"FLAG":0,"BASE":18} -Woopower RGBW E14 5W {"NAME":"Woopower E14","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -Xiaomi Phillips E14 {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48} -Xiaomi Phillips E27 {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48} -XMRJ {"NAME":"XMRJ","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -ZZHXON 6W E14/E27 {"NAME":"E27_RGB_Bulb","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Asakuki 500ml {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,0,0,255,255,255,21,22],"FLAG":0,"BASE":18} +Essential Oil 400ml {"NAME":"XD800W","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +GD-30W 300ml {"NAME":"GD-30W","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +Maxcio 400ml {"NAME":"MaxcioDiffuser","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +Mirabella Genio Glass Aroma Diffuser 250ml {"NAME":"Genio Diffuser","GPIO":[0,0,0,0,37,38,0,0,0,160,22,39,21],"FLAG":15,"BASE":18} +Wood Grain 550ML {"NAME":"MY-KCL01800FB","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +``` + +## Bulb CCT +``` +AICase 800lm {"NAME":"AICase Smart L","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Ajax Online 380lm {"NAME":"AjaxOnline","GPIO":[17,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":38} +Ajax Online 7W Vintage {"NAME":"AjaxOnline-7W","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Anoopsyche 9W 800lm {"NAME":"Anoop-CW-WW","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Arlec GLD112HA 806lm {"NAME":"Arlec CCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} +BrilliantSmart 20696 9W 900lm {"NAME":"Brilliant20696","GPIO":[0,0,0,0,0,0,0,0,37,0,38,0,0],"FLAG":0,"BASE":48} +BrilliantSmart 20697 9W 900lm {"NAME":"Brilliant20699","GPIO":[0,0,0,0,0,0,0,0,37,0,38,0,0],"FLAG":0,"BASE":48} +Bulbrite Solana A19 Edison Filament {"NAME":"BulbBrite01","GPIO":[0,0,0,0,0,0,0,0,37,0,38,0,0],"FLAG":0,"BASE":18} +Calex 429036 G125 1055lm {"NAME":"Calex G125 E27","GPIO":[0,0,0,0,0,140,0,0,38,0,37,142,141],"FLAG":0,"BASE":18} +Deltaco SH-LE14W 470lm {"NAME":"SH-LE14W","GPIO":[0,0,0,0,0,140,0,0,38,0,37,142,141],"FLAG":0,"BASE":18} +Deltaco SH-LE27W 810lm {"NAME":"SH-LE27W","GPIO":[0,0,0,0,0,140,0,0,38,0,37,142,141],"FLAG":0,"BASE":18} +DGM L-WT9W1 800lm {"NAME":"DGM L-WT9W1","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +DORESshop A60 720lm Filament {"NAME":"DORESshop-A60","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Energizer A19 10W {"NAME":"Energizer CCT ","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Geeni LUX 1050lm {"NAME":"Geeni-1050-WW","GPIO":[0,0,0,0,37,37,0,0,38,0,0,0,0],"FLAG":1,"BASE":18} +Globe 34919 ST19 Edison 500lm {"NAME":"Globe 34919","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Hama 176550 806lm {"NAME":"Hama Bulb xW","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Hykker SL-0392 650lm {"NAME":"Hykker 7W","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Iotton 9W 700lm {"NAME":"Iotton Light","GPIO":[0,0,0,0,37,38,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Kogan 10W Cool & Warm White 1050lm {"NAME":"Kogan White/Wa","GPIO":[0,0,0,0,37,40,0,0,41,38,39,0,0],"FLAG":0,"BASE":18} +LE LampUX 4.5W 410lm {"NAME":"LE LampUX","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":48} +ledscom.de 4.5W 430lm {"NAME":"GX53","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":0} +Lohas ZN070 720lm {"NAME":"Lohas ZN070","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Lumiman A19 7.5W 800lm {"NAME":"Lumiman LM520","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Luminea ZX-2831 {"NAME":"Luminea CCT","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Merkury MI-BW905-999W 700lm {"NAME":"MI-BW905-999W","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Mimoodz 1050lm {"NAME":"ID Components","GPIO":[0,0,0,0,21,22,0,0,23,24,25,26,27],"FLAG":0,"BASE":18} +Mirabella Genio 1002336 800lm {"NAME":"GenioBulbCCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Mirabella Genio 1002337 800lm {"NAME":"GenioBulbCCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Mirabella Genio 9W 800lm {"NAME":"GenioBulbCCT","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Mirabella Genio I002745 SES 470lm {"NAME":"Mirabella Candle","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Mirabella Genio I002746 500lm {"NAME":"GenioGU10","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Mirabella Genio I002747 G95 470lm {"NAME":"Genio Filament","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Nedis A60 800lm {"NAME":"WIFILW10WTE27","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Nedis C10 350lm {"NAME":"WIFILW10WTE14","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +Nedis PAR16 330lm {"NAME":"Nedis WIFILW30","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Philips Zhirui Candle 250lm {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48} +Phillips Zhirui 450lm {"NAME":"Xiaomi Philips","GPIO":[0,0,0,0,0,0,0,0,38,0,0,37,0],"FLAG":0,"BASE":48} +Swisstone SH 330 806lm {"NAME":"SwisstoneSH330","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Wipro Garnet NS9100 810lm {"NAME":"WiproSmartBulb","GPIO":[0,0,0,0,38,38,0,0,37,37,0,0,0],"FLAG":0,"BASE":18} +Wyze WLPA19 A19 800lm {"NAME":"Wyze Bulb","GPIO":[0,0,0,0,0,0,0,0,0,37,47,0,0],"FLAG":0,"BASE":48} +``` + +## Bulb Cold White +``` +Feit Electric BR30/950CA/AG 650lm {"NAME":"Feit BR30 CW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +KMC 70113 A19 7.5W {"NAME":"Generic","GPIO":[0,0,0,0,0,0,37,38,0,0,0,0,0],"FLAG":15,"BASE":18} +Lohas LZN127 G25 800lm {"NAME":"Lohas Globe","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Lohas ZN014 550lm {"NAME":"Lohas MR16","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Lohas ZN124 980lm {"NAME":"Lohas LH-ZN124","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Mirabella Genio 1002334 800lm {"NAME":"GenioBulbCW","GPIO":[0,0,0,0,38,37,0,0,0,40,39,0,0],"FLAG":0,"BASE":18} +Mirabella Genio A70 1400lm {"NAME":"GenioB_CW2744","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +``` + +## Bulb Red Green Blue +``` +Deltaco SH-LE27RGB 810lm {"NAME":"SH-LE27RGB","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Halonix Prime Prizm 12W {"NAME":"Halonix Prizm ","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Jomarto 9W {"NAME":"Jomarto Wifi S","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":1,"BASE":18} +Lyasi PT-BW09 {"NAME":"Lyasi PT-BW09","GPIO":[17,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +MoKo YX-L01C-E27 810lm {"NAME":"MOKO","GPIO":[17,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +muvit IO miobulb001 600lm {"NAME":"miobulb001","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":15,"BASE":18} +Oobest ZN93028 11W {"NAME":"RGB Bulb 11W","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":1,"BASE":18} +Wipro Garnet NS7001 480lm {"NAME":"WiproSmartBulb","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +``` + +## Bulb Red Green Blue CCT +``` +Aigital LE13 800lm {"NAME":"Aigital 9W RGB","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +Alfawise LE12 9W 900LM {"NAME":"Alfawise LE12 ","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +Aoycocr JL81 5W 400lm {"NAME":"AoycocrJLB1","GPIO":[0,0,0,0,39,0,0,0,38,41,37,40,0],"FLAG":0,"BASE":18} +Aoycocr Q0 750lm {"NAME":"AoycocrA19","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} +Aoycocr Q10CWM 720lm {"NAME":"AoycocrBR30","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} +Arlec GLD122HA 806lm {"NAME":"Arlec RGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Aunics 7W 600lm {"NAME":"Aunics RGBW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Avatar ALB201W 720lm {"NAME":"AVATAR ALB201W","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} +Avatar ALS18L A60 800lm {"NAME":"Avatar E14 7W","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":20} +B.K.Licht BKL1253 9W 806lm {"NAME":"BKL1253","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Bakibo TB95 9W 1000lm {"NAME":"Bakibo A19 9W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +BlitzWolf BW-LT27 w/ remote 850lm {"NAME":"BW-LT27","GPIO":[0,0,0,0,41,38,0,0,39,51,40,37,0],"FLAG":0,"BASE":18} +BNeta IO-WIFI60-E27P 800lm {"NAME":"OM60/RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Bomcosy 600lm {"NAME":"Generic","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18} +Calex 429002 Reflector 350lm {"NAME":"Calex RGBW","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +Calex 429004 A60 806lm {"NAME":"Calex E27 RGB ","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Cleverio 51395 806lm {"NAME":"CleverioE27RGB","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +CMARS 4W Reflector {"NAME":"RGBWW GU10","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":15,"BASE":18} +Dogain 320lm {"NAME":"DOGAIN","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Emuni TB95 9W 850Lm {"NAME":"TB95","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Ener-J SHA5262 800lm {"NAME":"ENER-J RGBWWW ","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Euri Lighting LIS-A1001 800lm {"NAME":"Euri Lighting ","GPIO":[0,0,0,0,37,40,0,0,38,41,39,37,0],"FLAG":0,"BASE":18} +EXUP C37 5W {"NAME":"EXUP","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":15,"BASE":18} +Feit Electric BPA800/RGBW/AG/2 800lm {"NAME":" BPA800/RGBW/AG/2","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Feit Electric BPA800/RGBW/AG/2(P) 800lm {"NAME":" BPA800/RGBW/AG/2P","GPIO":[0,0,0,0,37,38,0,0,141,142,140,0,0],"FLAG":0,"BASE":48} +Feit Electric OM100/RGBW/CA/AG 1600lm {"NAME":"OM100/RGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Feit Electric OM60/RGBW/15K/AG 800lm {"NAME":"FE-OM60-15K-AG","GPIO":[0,0,0,0,141,140,0,0,37,142,38,0,0],"FLAG":0,"BASE":18} +Feit Electric OM60/RGBW/CA/AG 800lm {"NAME":"OM60/RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Fulighture 9W 810lm {"NAME":"Fulighture 9W","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Geeni Prisma Plus 800lm {"NAME":"Geeni Prisma P","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Globe 34207 800lm {"NAME":"GlobeRGBWW","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Jeeo TF-QPZ13 800lm {"NAME":"Jeeo","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Julun JL-021 5W Candle {"NAME":"E14 RGBCCT","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Kohree 600lm {"NAME":"Kohree VHP560","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +LE lampUX A19 850lm {"NAME":"LE RGBWW 60W","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":1,"BASE":18} +Ledmundo 6W 600lm {"NAME":"LEDMUNDO 6W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Legelite 5W Candle {"NAME":"Legelite E12","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Legelite A60 7W {"NAME":"Legelite A60 7","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Legelite A60 7W 600lm {"NAME":"Legelite E26","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Lohas ZN031 650lm {"NAME":"Lohas ZN031","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Lohas ZN033 810lm {"NAME":"Lohas RGBWW","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Lohas ZN036 900 lm {"NAME":"Lohas RGBCCT","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Lohas ZN037 450lm {"NAME":"Lohas LH-ZN037","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":20} +Lumary 9W 800lm {"NAME":"Lumary / iLint","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +LVWIT A60 8.5W 806lm {"NAME":"LVWIT A60 8.5W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +LVWIT A70 12W 1521lm {"NAME":"LVWIT A70 12W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Novostella HM-LB09 13W 1300lm {"NAME":"Novostella 13W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Novostella NTB10 9W 900lm {"NAME":"NTB10","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +Novostella UT55505 7W 600lm {"NAME":"Novostella B22","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +Novostella UT55508 12W 1150lm {"NAME":"Novostella","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Novostella UT55509 13W 1300lm {"NAME":"Novostella 13W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Ohlux A19 7W 600lm {"NAME":"OHLUX","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Ohlux BR30 10W 900lm {"NAME":"OHLUX","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Powertech SL225X 800lm {"NAME":"Jaycar SL225X","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Qualitel ALS08L 1100lm {"NAME":"Qualitel ALS08","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Reafoo A26 9W {"NAME":"ReaFooE26","GPIO":[0,0,0,0,41,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +RYE 5W 450LM Candle {"NAME":"RYE Candlebra","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Saudio A19 7W 700lm {"NAME":"X002BU0DOL","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Slitinto TB95 9W 1000lm {"NAME":"Slitinto 9W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Sonoff B1 (R2) {"NAME":"Sonoff B1","GPIO":[17,0,0,0,0,0,0,0,143,0,144,0,0],"FLAG":0,"BASE":26} +Sunco G25 5W 450lm {"NAME":"Sunco G25","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Sunco PAR20 5W 400lm {"NAME":"Sunco PAR20","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Teckin SB50-2 800lm {"NAME":"Teckin SB50v3","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Teckin SB53 1300lm {"NAME":"Teckin SB53","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +V-Tac VT-5164 400lm {"NAME":"V-TAC VT5164","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +Wipro Garnet NS9001 810lm {"NAME":"WiproSmartBulb","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +ZZHXON 600lm {"NAME":"E27_RGB_Bulb","GPIO":[0,0,0,0,40,41,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +``` + +## Bulb Red Green Blue White +``` +3Stone EBE-QPW36 1050lm {"NAME":"3STONE","GPIO":[0,0,0,0,141,140,0,0,37,142,0,0,0],"FLAG":15,"BASE":18} +Accewit 7W 650lm {"NAME":"Accewit Bulb","GPIO":[0,0,0,0,0,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +Aisirer 7W 580lm {"NAME":"Aisirer RGBW","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Aisirer 7W 580lm {"NAME":"Aisirer RGBW","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +AL Above Lights 810lm {"NAME":"AL 810LM","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Aoycocr Q3CM 230lm {"NAME":"Aoycocr_GU10","GPIO":[0,0,0,0,0,0,0,0,143,0,144,0,0],"FLAG":0,"BASE":27} +Avatar ALS08L A19 910lm {"NAME":"Avatar E27 7W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":20} +Avatar ALS09L A60 900lm {"NAME":"Avatar E14 9W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":20} +Avatar ALS11L PAR16 500lm {"NAME":"Avatar_GU10","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +AWOW A60 9W 800lm {"NAME":"AWOW 9W RGBW","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Axtee AI-003 A19 700lm {"NAME":"Axtee E26 7W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":20} +Bawoo EUWL122130 925lm {"NAME":"Bawoo","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +BlitzWolf BW-LT21 900lm {"NAME":"BlitzWolf LT21","GPIO":[0,0,0,0,41,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} +BNeta IO-WIFI-GU10 380lm {"NAME":"BNeta","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +BriHome 6,5W 500lm {"NAME":"BRI E27 6,5W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":20} +Brilliant HK17653S72 350lm {"NAME":"HK17653S72","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +BrilliantSmart 20698 9W 800lm {"NAME":"Brilliant20698","GPIO":[0,0,0,0,141,140,0,0,37,142,0,0,0],"FLAG":0,"BASE":18} +BrilliantSmart 20699 9W 800lm {"NAME":"Brilliant20699","GPIO":[0,0,0,0,141,140,0,0,37,142,0,0,0],"FLAG":0,"BASE":18} +BrilliantSmart 20741 9W 750lm {"NAME":"Brilliant RGB+","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +BrizLabs A19 9W 806LM {"NAME":"TCP Smart RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +BrizLabs Candle 4,5W 350lm {"NAME":"BrizLabs RGBW","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Brizlabs EBE-LZW10 350Lm {"NAME":"Brizlabs E14","GPIO":[0,0,0,0,141,140,0,0,37,142,0,0,0],"FLAG":15,"BASE":18} +BrizLabs EBE-SHW03 380lm {"NAME":"BrizLabs","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +BTZ1 {"NAME":"WifiBulb","GPIO":[0,0,0,0,0,37,0,0,39,40,38,0,0],"FLAG":0,"BASE":18} +Calex 429008 B35 5W 470lm {"NAME":"Calex E14 RGBW","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +Cleverio 51398 370lm {"NAME":"CleverioGU10","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Cocoon DY180363-B 800lm {"NAME":"Cocoon RGBW","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +electriQ 600lm {"NAME":"ElectricQ B22","GPIO":[0,0,0,0,37,41,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +EleLight 350lm {"NAME":"EleLight 7wA19","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +Esicoo 810lm {"NAME":"Esicoo Bulb","GPIO":[0,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Fcmila 10W {"NAME":"FCMILA LED E27","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Fcmila 7W {"NAME":"FCMILA E27 0.1","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Fcmila Spotlight 460lm {"NAME":"Fcmila LED 6W","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Feit Electric BR30/RGBW/CA/AG 650lm {"NAME":"BR30/RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Fulighture A60 810lm {"NAME":"Fulighture A60","GPIO":[0,0,0,0,38,37,0,0,0,39,40,0,0],"FLAG":0,"BASE":18} +Geeni Prisma 1050lm {"NAME":"Geeni 1050 RGB","GPIO":[37,0,0,0,140,38,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +Generic 10W {"NAME":"10W E27 RGBW","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":0,"BASE":18} +Generic GU10 5W 450lm {"NAME":"RGBCW GU10","GPIO":[0,255,0,255,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":3} +Gosund WB3 8W 800lm {"NAME":"Gosund WB3","GPIO":[0,0,0,0,40,0,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +Hama 176531 1050lm {"NAME":"Hama Bulb RGBW","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +Hama 176547 806lm {"NAME":"hama_rgb","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Hykker SL-0492 810lm {"NAME":"Hykker RBGW 9W","GPIO":[0,0,0,0,0,40,0,0,37,0,39,38,0],"FLAG":0,"BASE":18} +iDigital Smart Home Wifi Globe 9W {"NAME":"iDigitalRGB+WW","GPIO":[0,0,0,0,0,40,0,0,37,0,39,38,0],"FLAG":0,"BASE":18} +Kainsy 600lm {"NAME":"KAINSY","GPIO":[17,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Koaanw 650lm {"NAME":"KOAANW Bulb","GPIO":[0,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Kogan 10W Ambient 1050lm {"NAME":"Kogan RGB","GPIO":[0,0,0,0,140,37,0,0,0,0,141,0,0],"FLAG":0,"BASE":18} +Kogan Ambient Candle {"NAME":"Kogan_E14","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Kogan Ambient Spotlight 330lm {"NAME":"Kogan_GU10","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":0,"BASE":18} +Kuled 800lm {"NAME":"KULED 60W RGB","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":1,"BASE":18} +Laideyi 7W {"NAME":"7W-E14-RGBW-La","GPIO":[0,0,0,0,38,37,0,0,39,0,40,0,0],"FLAG":0,"BASE":18} +LeCardio 10W 980lm {"NAME":"LeCardio RGBW","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Lohas ZN001 810lm {"NAME":"Lohas RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":18} +Lohas ZN001-E12 810lm {"NAME":"Lohas","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":26} +Lohas ZN005 420lm {"NAME":"Lohas E14 R50","GPIO":[17,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Lohas ZN006 1380lm {"NAME":"Lohas100 RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":18} +Lohas ZN012 450lm {"NAME":"LH-5W-ZN01204","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Lonsonho 900lm {"NAME":"RGB+W+C Bulb","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +LSC Smart Connect C45 400lm {"NAME":"LSC RGBCW E14","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +LSC Smart Connect MR16 380lm {"NAME":"LSC RGBCW GU10","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18} +Lumiman LM530 7.5W 800lm {"NAME":"Lumiman LM530","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18} +Lumiman LM530 7.5W 800lm {"NAME":"Lumiman LM530","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18} +Lumiman LM530 7.5W 800lm {"NAME":"LM530","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":1,"BASE":18} +Luminea ZX-2832 {"NAME":"Luminea RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":1,"BASE":18} +Luminea ZX-2986 1400lm {"NAME":"Luminea RGBW","GPIO":[0,0,0,0,37,41,0,0,0,38,39,40,0],"FLAG":0,"BASE":18} +LWE3 600lm {"NAME":"Linganzh LWE3 ","GPIO":[0,0,0,0,0,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +Manzoku XS-001 1050lm {"NAME":"Manzoku RGBW","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Maxcio YX-L01P-E27-2P 9W {"NAME":"Maxcio YXL01P","GPIO":[17,0,0,0,143,144,0,0,0,0,0,0,0],"FLAG":0,"BASE":27} +Merkury MI-BW210-999W 1050lm {"NAME":"MI-BW210-999W","GPIO":[0,0,0,0,140,37,0,0,142,38,141,0,0],"FLAG":0,"BASE":48} +Merkury MI-BW904-999W 1050lm {"NAME":"MI-BW904-999W","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +Merkury MI-BW904-999W v2 1050lm {"NAME":"MI-BW210-999W","GPIO":[0,0,0,0,38,37,0,0,141,142,140,0,0],"FLAG":0,"BASE":48} +Merkury MI-BW904-999W v3 {"NAME":"MI-BW904-999W","GPIO":[0,0,0,0,37,38,0,0,141,142,140,0,0],"FLAG":0,"BASE":69} +Merkury MI-BW906-999W BR30 750lm {"NAME":"MI-BW906-999W","GPIO":[0,0,0,0,38,37,0,0,141,142,140,0,0],"FLAG":0,"BASE":18} +Mirabella Genio 1002338 800lm {"NAME":"GenioBulbRGB","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":1,"BASE":18} +Mixigoo 950lm {"NAME":"Mixigoo Bulb","GPIO":[0,0,0,0,41,38,0,0,39,0,37,40,0],"FLAG":0,"BASE":18} +MoKo JL81 5W 400lm {"NAME":"MoKo E14","GPIO":[0,0,0,0,0,0,0,0,143,0,144,0,0],"FLAG":0,"BASE":27} +Nedis A60 800lm {"NAME":"Nedis RGBW","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":1,"BASE":18} +Nedis C10 350lm {"NAME":"Nedis WIFILC10","GPIO":[0,0,0,0,39,37,0,0,40,38,41,0,0],"FLAG":1,"BASE":18} +Nedis PAR16 330lm {"NAME":"Nedis GU10","GPIO":[0,0,0,0,39,37,0,0,40,38,41,0,0],"FLAG":0,"BASE":18} +NiteBird TT-WB4 800lm {"NAME":"NiteBird TT-WB","GPIO":[0,0,0,0,40,0,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +Orbecco 5W 400lm {"NAME":"Orbecco Bulb","GPIO":[0,0,0,0,0,0,0,0,143,0,144,0,0],"FLAG":0,"BASE":27} +Premier A19 10W {"NAME":"Premier Light","GPIO":[0,0,0,0,0,39,0,0,38,0,37,40,0],"FLAG":1,"BASE":18} +Riversong Juno 10W {"NAME":"Juno10","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":0,"BASE":18} +Rogoei EBE-QPZ04 6.5W 450lm {"NAME":"EBE-QPZ04","GPIO":[0,0,0,0,180,0,0,0,0,0,181,0,0],"FLAG":0,"BASE":18} +Smart 810lm {"NAME":"OOOLED 60W RGB","GPIO":[0,0,0,0,39,40,0,0,37,0,38,0,0],"FLAG":1,"BASE":18} +Smartyfi 600lm {"NAME":"SMARTYFI 9W","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Solimo 12W {"NAME":"Solimo RGBWW12","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Solimo 810lm {"NAME":"Solimo RGBWW 9","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Swisstone SH 340 806lm {"NAME":"SH 340","GPIO":[0,0,0,0,140,37,0,0,0,142,141,0,0],"FLAG":15,"BASE":18} +Syska 720lm {"NAME":"SyskaSmartBulb","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +TCP Smart 806lm {"NAME":"TCP Smart RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Teckin SB50 800lm {"NAME":"Teckin SB50","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +Teckin SB50 v2 800lm {"NAME":"Teckin SB50","GPIO":[0,0,0,0,37,0,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +Teckin SB51 800lm {"NAME":"Teckin SB51","GPIO":[0,0,0,0,40,0,0,0,38,39,37,0,0],"FLAG":0,"BASE":18} +TikLOk TL530 A19 7.5W 800lm {"NAME":"TikLOk WW-CW-L","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +Utorch LE7 600lm {"NAME":"Utorch LE7","GPIO":[0,0,0,0,0,38,0,0,39,0,40,37,0],"FLAG":0,"BASE":18} +V-Tac VT-5113 1055lm {"NAME":"V-TAC LED A60 ","GPIO":[0,0,0,0,180,0,0,0,0,0,181,0,0],"FLAG":0,"BASE":18} +Wallfire WF-05 {"NAME":"Wallfire E27","GPIO":[17,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Woopower 460lm {"NAME":"Woopower E14","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +WOOX R4553 650lm {"NAME":"WOOX R4553","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +WOOX R5076 4W 350lm {"NAME":"WOOX R4553","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Woox R5077 {"NAME":"WOOX R5077","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +Zemismart 5W {"NAME":"Zemismart_GU10","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Zilotek A19 800lm {"NAME":"Zilotek RGBW","GPIO":[0,0,0,0,140,37,0,0,38,142,141,0,0],"FLAG":0,"BASE":18} +``` + +## Bulb Warm White +``` +Aisirer 9W 806lm {"NAME":"Aisirer 9W","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Aisirer 9W 806lm {"NAME":"AISIRER E26","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Aisirer 9W 806lm {"NAME":"Aisirer 9W","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Avatar ALS15L Candle {"NAME":"AVATAR","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Cleverio 51396 800lm {"NAME":"Cleverio E27","GPIO":[0,0,0,0,0,0,0,0,0,0,46,0,0],"FLAG":0,"BASE":18} +Connect Smart 10W {"NAME":"CSH-B22WW10W","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":18} +DORESshop B11 600lm Filament {"NAME":"Doresshop-cand","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +DORESshop ST64 720lm Filament {"NAME":"DORESshop-ST64","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Feit Electric BR30/927CA/AG 650lm {"NAME":"Feit BR30 WW","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Feit Electric OM60/927CA/AG 800lm {"NAME":" Feit P_A800_2","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Geeni LUX Edison {"NAME":"Geeni-Edison","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Globe 34209 800lm {"NAME":"Globe WW 800lm","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Kogan ST-20 Filament {"NAME":"Kogan Filament","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":15,"BASE":18} +LeDesign 8W ST21 Filament {"NAME":"Edison Bulb","GPIO":[0,0,0,0,0,0,0,0,0,37,0,0,0],"FLAG":0,"BASE":18} +LSC Smart Connect Filament A60 {"NAME":"LSC Filam E27","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +LSC Smart Connect Filament C35 {"NAME":"LSC Filam E14","GPIO":[0,255,0,255,0,0,0,0,38,0,37,0,0],"FLAG":15,"BASE":18} +LSC Smart Connect Filament G125 {"NAME":"LSC Filam Huge","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +LSC Smart Connect Filament ST64 {"NAME":"LSC Filam Big","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":18} +Lumary 6W 700lm Edison {"NAME":"Lumary TS3Y","GPIO":[0,0,0,0,0,0,0,0,0,37,0,0,0],"FLAG":0,"BASE":18} +Luminea ZX-2982 ST64 Filament {"NAME":"Luminea ZX2982","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Merkury MI-BW902-999W 800lm {"NAME":"MI-BW902-999W","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Merkury MI-BW942-999W 800lm {"NAME":"MI-BW942-999W","GPIO":[0,0,0,0,37,0,0,0,0,52,0,0,0],"FLAG":0,"BASE":18} +Merkury MIC-BW902-999W {"NAME":"MI-BW902-999W","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Merkury Vintage Edison A19 {"NAME":"Merkury A19 Ed","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Nedis A60 Filament {"NAME":"WIFILF10WTA60","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Nedis G125 Filament {"NAME":"WIFILF10GDG125","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Nedis PAR16 330lm {"NAME":"Nedis WIFILW31","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Sealight Vintage Edison A19 {"NAME":"SealightEdison","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} ``` ## Bulb Socket ``` -Elegant Choice E27/E26 {"NAME":"Sm Lghtg Base","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Slampher {"NAME":"Slampher","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":9} -SmartBase E0260 {"NAME":"SmartBaseE0260","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Elegant Choice E27/E26 {"NAME":"name","GPIO":[0,0,0,0,0,0,0,0,0,0,0,21,0],"FLAG":0,"BASE":18} +Slampher {"NAME":"Slampher","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":9} +SmartBase E0260 {"NAME":"SmartBaseE0260","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +``` + +## Curtain Motor +``` +Zemismart BCM300D-TY {"NAME":"Zemistart_Curt","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} ``` ## Curtain Switch ``` -Teepao {"NAME":"Taopao","GPIO":[255,255,255,18,22,19,255,255,255,21,255,255,17],"FLAG":1,"BASE":18} -WF-CS01 {"NAME":"Tuya Shutter","GPIO":[157,0,54,10,22,19,0,0,17,21,53,23,52],"FLAG":0,"BASE":18} +Anccy Relax {"NAME":"Tuya Shutter","GPIO":[157,0,54,10,22,19,0,0,17,21,53,23,52],"FLAG":0,"BASE":18} +Homecube Blinds and Curtains {"NAME":"Jinvoo Curtain","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} +Jinvoo SM-SW101-C Curtain {"NAME":"Jinvoo Curtain","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} +LoraTap SC511WSC Roller Shutter {"NAME":"SC511WSC","GPIO":[0,255,0,56,17,18,0,0,21,19,22,0,0],"FLAG":0,"BASE":18} +Teekar SYS-CS 01 {"NAME":"Teekar-Tag","GPIO":[56,0,157,18,22,11,0,0,0,21,57,31,17],"FLAG":0,"BASE":18} +Teepao {"NAME":"Taopao","GPIO":[255,255,255,18,22,19,0,0,255,21,255,255,17],"FLAG":1,"BASE":18} +WF-CS01 {"NAME":"Tuya Shutter","GPIO":[157,0,54,10,22,19,0,0,17,21,53,23,52],"FLAG":0,"BASE":18} +WF-CS02 {"NAME":"WF-CS02 Tuya","GPIO":[157,0,53,11,23,18,0,0,17,21,54,22,52],"FLAG":0,"BASE":18} ``` -## DIY Project +## DIY ``` -LC-Tech 1Ch and PZEM-004T {"NAME":"HW-655 PZEM","GPIO":[0,63,0,62,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} -Luani HVIO {"NAME":"Luani HVIO","GPIO":[0,255,255,255,21,22,0,0,9,10,255,52,0],"FLAG":1,"BASE":35} -SUPLA inCan by Espablo {"NAME":"Supla Espablo","GPIO":[0,255,4,255,17,21,0,0,255,22,255,0,52],"FLAG":1,"BASE":31} -``` - -## Development Board -``` -Witty Cloud {"NAME":"Witty Cloud","GPIO":[255,255,56,255,17,255,0,0,38,39,255,37,255],"FLAG":1,"BASE":32} +Adafruit HUZZAH {"NAME":"Huzzah","GPIO":[17,0,56,0,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":18} +Heltec WiFi Kit 8 {"NAME":"HTIT-W8266","GPIO":[255,255,255,255,6,5,0,0,255,255,255,255,162],"FLAG":15,"BASE":18} +LC Tech relay and PZEM-004T {"NAME":"HW-655 PZEM","GPIO":[0,63,0,62,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Luani HVIO {"NAME":"Luani HVIO","GPIO":[0,255,255,255,21,22,0,0,9,10,255,52,0],"FLAG":1,"BASE":35} +Splatura USB Device Power Switch {"NAME":"Splatura USB","GPIO":[0,0,52,0,0,0,0,0,0,21,0,122,0],"FLAG":0,"BASE":18} +SUPLA inCan by Espablo {"NAME":"Supla Espablo","GPIO":[0,255,4,255,17,21,0,0,255,22,255,0,52],"FLAG":1,"BASE":31} +Witty Cloud {"NAME":"Witty Cloud","GPIO":[255,255,56,255,17,255,0,0,38,39,255,37,255],"FLAG":1,"BASE":32} ``` ## Dimmer ``` -Armtronix AC Dimmer One Triac Board {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56} -Armtronix AC Dimmer Two Triac Board {"NAME":"ARMTR Dimmer","GPIO":[255,148,255,149,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":56} -CE Smart Home WF500D {"NAME":"CE-WF500D","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} -EVA LOGIK WF31 {"NAME":"WF31 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} -EX-Store 2 Kanal RS232 V4 {"NAME":"EXS Dimmer","GPIO":[0,148,0,149,255,255,0,0,255,183,255,0,0],"FLAG":0,"BASE":72} -Kingart Touch {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58} -Moes DS01 {"NAME":"MOES - DS01","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} -Moes QS-WiFi-D01 Dimmer 150W {"NAME":"WiFi-Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,42,37,0,0],"FLAG":0,"BASE":18} -PS-16-DZ {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58} -PWM Dimmer {"NAME":"PWM Dimmer","GPIO":[19,18,0,59,158,58,0,0,57,37,56,122,29],"FLAG":0,"BASE":73} -Zemismart KS-7011 {"NAME":"KS-7011 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +Armtronix AC Dimmer One Triac Board {"NAME":"ARMTR Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":56} +Armtronix AC Dimmer Two Triac Board {"NAME":"ARMTR Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":56} +BrilliantSmart D350W {"NAME":"Generic","GPIO":[255,107,255,108,255,255,0,0,255,0,255,0,255],"FLAG":0,"BASE":54} +CE Smart Home CFW500D-3W 3 Way {"NAME":"CE-WF500D-3W","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} +CE Smart Home CWF500D-3W {"NAME":"CE-WF500D-3W","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} +CE Smart Home WF500D {"NAME":"CE-WF500D","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} +Eva Logik WF31 {"NAME":"WF31 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +EX-Store 2 Kanal RS232 V4 {"NAME":"EXS Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,183,0,0,0],"FLAG":0,"BASE":72} +Gosund SW2 {"NAME":"Gosund Dimmer","GPIO":[255,148,255,149,17,0,255,255,56,158,37,255,255],"FLAG":0,"BASE":18} +Martin Jerry MJ-SD02 {"NAME":"MJ-SD02","GPIO":[19,17,0,33,34,32,255,255,31,37,30,127,29],"FLAG":15,"BASE":18} +Moes DS01-1 {"NAME":"MOES DS01","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} +Moes MS-105-1 v2 {"NAME":"MS-105","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} +PS-16-DZ {"NAME":"PS-16-DZ","GPIO":[255,148,255,149,255,255,0,0,255,52,255,255,255],"FLAG":0,"BASE":58} +QS-WiFi-D01 150W {"NAME":"WiFi-Dimmer","GPIO":[0,148,0,149,0,0,0,0,0,42,37,0,0],"FLAG":0,"BASE":18} +RJWF-02A {"NAME":"RJWF-02A","GPIO":[17,107,0,108,0,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":54} +Sonoff D1 {"NAME":"Sonoff D1","GPIO":[255,148,0,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":74} +Teekar UIW001-1 {"NAME":"Teekar UIW001-","GPIO":[0,149,37,148,6,5,0,0,9,0,0,0,0],"FLAG":0,"BASE":18} +TreatLife DS01 {"NAME":"DS02S Dimmer","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} +TreatLife DS02S {"NAME":"DS02S Dimmer","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} +WF-DS01 {"NAME":"Dimmer WF-DS01","GPIO":[255,255,255,255,255,255,0,0,255,255,54,255,255],"FLAG":0,"BASE":54} +WiFi Dimmer Switch {"NAME":"PS-16-DZ","GPIO":[0,148,0,149,0,0,0,0,0,52,0,0,0],"FLAG":0,"BASE":58} +Zemismart KS-7011 {"NAME":"KS-7011 Dimmer","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} ``` -## Environment Monitor +## Fan ``` -Sonoff SC {"NAME":"Sonoff SC","GPIO":[17,148,255,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":21} +Anko HEGSM40 {"NAME":"Anko HEGSM40","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} +Arlec 45cm Smart DC Wall {"NAME":"Arlec 45cm Fan","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} +Goldair SleepSmart GCPF315 {"NAME":"Goldair Fan","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} ``` ## Fan Controller ``` -Sonoff iFan02 {"NAME":"Sonoff iFan02","GPIO":[17,255,0,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":44} -Sonoff iFan03 {"NAME":"SonoffiFan03","GPIO":[17,148,0,149,0,0,29,161,23,56,22,24,0],"FLAG":0,"BASE":71} +BrilliantSmart 99111 {"NAME":"Brilliant Fan","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} +Lucci Connect Remote Control {"NAME":"Lucci Fan","GPIO":[0,0,0,0,0,0,0,0,0,108,0,107,0],"FLAG":0,"BASE":54} +Sonoff iFan02 {"NAME":"Sonoff iFan02","GPIO":[17,255,0,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":44} +Sonoff iFan03 {"NAME":"SonoffiFan03","GPIO":[17,148,0,149,0,0,29,161,23,56,22,24,0],"FLAG":0,"BASE":71} ``` ## Humidifier ``` -Asakuki 500ml {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":0,"BASE":18} -Maxcio 400ml {"NAME":"MaxcioDiffuser","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} -Oil Diffuser 550ML {"NAME":"Oil Diffuser","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":0,"BASE":18} +Proscenic 807C {"NAME":"Generic","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":15,"BASE":54} ``` ## IR Bridge ``` -Alfawise KS1 {"NAME":"KS1","GPIO":[255,71,17,72,17,51,0,0,56,0,8,0,0],"FLAG":1,"BASE":62} -auvisio S06 {"NAME":"NX-4519-675","GPIO":[255,255,255,255,52,51,255,255,255,255,8,255,255],"FLAG":1,"BASE":18} -Eachen SANT-IR 01 {"NAME":"Eachen IR","GPIO":[0,0,0,0,56,51,255,255,255,17,8,0,0],"FLAG":0,"BASE":18} -Geeklink {"NAME":"GL IR Blaster","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} -Mirabella Genio HKWL-IR02W {"NAME":"Genio IR TxRx","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} -STITCH by Monoprice 35753 {"NAME":"Stitch 35753","GPIO":[0,0,0,0,52,51,0,0,0,90,8,0,0],"FLAG":0,"BASE":18} -YTF {"NAME":"YTF IR Bridge","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +A1 Universal Remote Control {"NAME":"A1 IR Bridge","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +Alfawise KS1 {"NAME":"KS1","GPIO":[255,71,17,72,17,51,0,0,56,0,8,0,0],"FLAG":1,"BASE":62} +auvisio S06 {"NAME":"NX-4519-675","GPIO":[255,255,255,255,52,51,0,0,255,255,8,255,255],"FLAG":1,"BASE":18} +BlitzWolf BW-RC1 Smart IR Controller {"NAME":"BW-RC1","GPIO":[0,0,0,0,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +Connect SmartHome Universal Smart IR Remote {"NAME":"CSH IR Bridge","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +Cusam CS-IRC-1 {"NAME":"YTF IR Bridge","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +Eachen IR DC6 {"NAME":"Eachen IR","GPIO":[0,0,0,0,56,51,0,0,255,17,8,0,0],"FLAG":0,"BASE":18} +Geeklink GK01 {"NAME":"GL IR Blaster","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +Mirabella Genio I002577 {"NAME":"Genio IR TxRx","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +NEO Coolcam NAS-IR03W0 {"NAME":"Neo Coolcam IR","GPIO":[0,0,0,0,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +STITCH by Monoprice 35753 {"NAME":"Stitch 35753","GPIO":[0,0,0,0,52,51,0,0,0,90,8,0,0],"FLAG":0,"BASE":18} +YTF Universal Remote {"NAME":"YTF IR Bridge","GPIO":[255,255,255,255,56,51,0,0,0,17,8,0,0],"FLAG":0,"BASE":62} +``` + +## Kettle +``` +Kogan 1.7L Smart Glass {"NAME":"Kogan Kettle","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +ProfiCook PC-WKS 1167 G 1.5 L {"NAME":"PC-WKS Kettle","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} ``` ## LED Controller ``` -Arilux AL-LC01 {"NAME":"Arilux LC01","GPIO":[17,255,59,255,147,37,0,0,38,39,255,0,0],"FLAG":0,"BASE":37} -Arilux AL-LC06 {"NAME":"Arilux LC06","GPIO":[17,255,255,255,255,255,255,255,38,39,37,41,40],"FLAG":0,"BASE":18} -Arilux AL-LC11 {"NAME":"Arilux LC11","GPIO":[17,255,59,255,38,37,0,0,41,40,39,147,0],"FLAG":0,"BASE":38} -Electrodragon Mosfet Drive {"NAME":"LEDBoard RGBW","GPIO":[255,0,0,0,255,255,0,0,39,38,40,37,52],"FLAG":0,"BASE":18} -H801 {"NAME":"H801","GPIO":[255,52,255,255,41,57,0,0,39,38,40,37,0],"FLAG":0,"BASE":20} -LEDEnet {"NAME":"LEDEnet","GPIO":[0,255,56,255,147,0,0,0,38,39,37,40,0],"FLAG":0,"BASE":34} -Luminea ZX-2844 {"NAME":"Luminea ZX-284","GPIO":[40,255,255,255,0,39,255,255,38,17,37,255,255],"FLAG":0,"BASE":18} -MagicHome RGB ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGB","GPIO":[0,0,0,0,0,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34} -MagicHome RGBW ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGBW","GPIO":[0,0,0,0,51,38,0,0,37,39,0,40,0],"FLAG":0,"BASE":34} -MagicHome ZJ-ESP-IR-F V1 {"NAME":"ZJ-ESP-IR-F V1","GPIO":[255,255,255,255,51,38,255,255,37,39,255,40,255],"FLAG":0,"BASE":18} -Nexlux {"NAME":"MagicHome V1.1","GPIO":[0,0,0,0,51,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34} -Shelly RGBW2 {"NAME":"RGBW2","GPIO":[255,255,33,255,24,91,255,255,21,17,23,22,255],"FLAG":0,"BASE":18} +Anncoe C350 RGB {"NAME":"TUYA LED","GPIO":[0,0,0,0,0,38,0,0,39,17,37,0,0],"FLAG":0,"BASE":18} +Arilux AL-LC01 {"NAME":"Arilux LC01","GPIO":[17,0,59,0,147,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":37} +Arilux AL-LC06 {"NAME":"Arilux LC06","GPIO":[17,0,0,0,0,0,0,0,38,39,37,41,40],"FLAG":0,"BASE":18} +Arilux AL-LC11 {"NAME":"Arilux LC11","GPIO":[17,0,59,0,38,37,0,0,41,40,39,147,0],"FLAG":0,"BASE":38} +Arilux SL-LC 09 {"NAME":"Arilux LC09","GPIO":[0,0,0,0,106,37,0,0,39,0,38,0,0],"FLAG":0,"BASE":18} +DD001-MINI(G)-IR-V08 {"NAME":"WIFI-RGB","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Electrodragon ESP LED Strip Board, Mosfet Drive {"NAME":"LEDBoard RGBW","GPIO":[0,0,0,0,0,0,0,0,39,38,40,37,52],"FLAG":0,"BASE":18} +H801 {"NAME":"H801","GPIO":[0,52,0,0,41,57,0,0,39,38,40,37,0],"FLAG":0,"BASE":20} +LEDEnet {"NAME":"LEDEnet","GPIO":[0,255,56,255,147,41,0,0,38,39,37,40,0],"FLAG":0,"BASE":34} +Luminea ZX-2844 {"NAME":"Luminea ZX-284","GPIO":[40,0,0,0,0,39,0,0,38,17,37,0,0],"FLAG":0,"BASE":18} +Luminea ZX-2844-675 {"NAME":"ZX-2844-675","GPIO":[17,0,0,0,38,40,0,0,37,0,39,0,0],"FLAG":0,"BASE":18} +Magic UFO RGBW {"NAME":"Magic UFO","GPIO":[17,0,157,0,0,37,0,0,39,40,38,56,0],"FLAG":0,"BASE":18} +MagicHome RGB ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGB","GPIO":[0,0,0,0,0,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34} +MagicHome RGBW ESP-IR-B-v2.3 {"NAME":"ESP-IR-B-v2.3","GPIO":[0,0,51,0,0,38,0,0,37,39,0,40,0],"FLAG":0,"BASE":18} +MagicHome RGBW ZJ-WFMN-A V1.1 {"NAME":"MagicHome RGBW","GPIO":[0,0,0,0,51,38,0,0,37,39,0,40,0],"FLAG":0,"BASE":34} +MagicHome RGBWW w/ RF {"NAME":"MagicHome RF","GPIO":[0,0,159,0,37,38,0,0,41,40,39,147,0],"FLAG":0,"BASE":38} +MagicHome RGBWW w/ RF {"NAME":"MagicHome RF","GPIO":[0,0,0,0,147,40,0,0,38,39,37,41,159],"FLAG":0,"BASE":18} +MagicHome ZJ-ESP-IR-F V1 {"NAME":"ZJ-ESP-IR-F V1","GPIO":[0,0,0,0,51,38,0,0,37,39,0,40,0],"FLAG":0,"BASE":18} +Maxonar Lightstrip Pro XS-SLD001 {"NAME":"Maxonar LED","GPIO":[0,0,0,0,0,37,0,0,39,17,38,0,0],"FLAG":0,"BASE":18} +Nexlux {"NAME":"MagicHome V1.1","GPIO":[0,0,0,0,51,37,0,0,38,39,0,0,0],"FLAG":0,"BASE":34} +Shelly RGBW2 {"NAME":"Shelly RGBW2","GPIO":[0,0,52,0,40,255,0,0,37,17,39,38,0],"FLAG":0,"BASE":18} +ZJ-WF-ESP-A v1.1 {"NAME":"RGB2","GPIO":[0,0,0,0,0,0,0,0,38,37,39,0,0],"FLAG":0,"BASE":18} ``` ## LED Strip ``` -BlitzWolf BW-LT11 {"NAME":"BW-LT11 Strip","GPIO":[17,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18} -LSC Smart Connect RGBW {"NAME":"LSC-RGBW-Strip","GPIO":[51,0,0,0,37,0,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} -Merkury Innovations MI-EW003-999W {"NAME":"MI-EW003-999W ","GPIO":[17,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Mirabella Genio 3 Metre {"NAME":"MirabellaStrip","GPIO":[17,255,255,255,37,40,255,255,38,255,39,255,255],"FLAG":0,"BASE":18} -Monster Smart IlluminEssence {"NAME":"MI-EW003-999W ","GPIO":[17,255,255,255,37,40,255,255,38,41,39,255,255],"FLAG":0,"BASE":18} -Sonoff L1 {"NAME":"SonoffL1","GPIO":[0,148,0,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":70} -Torchstar {"NAME":"Torchstar","GPIO":[255,255,255,255,52,255,255,255,255,255,255,37,53],"FLAG":1,"BASE":18} +Arlec 2m LED Colour Changing Strip Light {"NAME":"Arlec ALD233AH","GPIO":[0,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +B.K. Licht BKL1268 2m RGB {"NAME":"RGBW-Strip","GPIO":[0,0,0,0,37,17,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +BlitzWolf BW-LT11 {"NAME":"BW-LT11 Strip","GPIO":[17,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +BrilliantSmart 20743 RGB+W {"NAME":"BrilliantStrip","GPIO":[17,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Briloner 2256-150 RGB {"NAME":"Briloner2256-1","GPIO":[51,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Cocoon Smart {"NAME":"Cocoon Smart","GPIO":[17,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +LE LampUX 2m RGB TV Backlight {"NAME":"LE 904102","GPIO":[0,17,18,0,0,38,0,0,39,19,0,37,0],"FLAG":0,"BASE":18} +LE LampUX 5m RGB LED Strip {"NAME":"LampUX","GPIO":[17,0,0,0,0,38,0,0,39,0,0,37,0],"FLAG":0,"BASE":18} +LE lampUX 5m RGBW {"NAME":"LampUX","GPIO":[17,0,0,0,37,40,255,255,38,41,39,0,0],"FLAG":0,"BASE":18} +LSC Smart Connect RGBW {"NAME":"LSC RGBW Strip","GPIO":[51,0,0,0,37,0,0,0,38,40,39,0,0],"FLAG":0,"BASE":18} +Lumary RGBCCT {"NAME":"Lumary LED","GPIO":[17,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Lumary RGBCCT {"NAME":"Lumary LED","GPIO":[17,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Merkury Innovations MI-EW003-999W {"NAME":"MI-EW003-999W ","GPIO":[17,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Mirabella Genio I002579 {"NAME":"MirabellaStrip","GPIO":[17,0,0,0,37,40,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Monster Smart IlluminEssence {"NAME":"MI-EW003-999W ","GPIO":[17,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Sonoff L1 {"NAME":"SonoffL1","GPIO":[0,148,0,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":70} +Teckin SL02 {"NAME":"Teckin SL02","GPIO":[51,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":52} +Torchstar Safe Lighting Kit {"NAME":"Torchstar","GPIO":[0,0,0,0,52,0,0,0,0,0,0,37,53],"FLAG":1,"BASE":18} +Zemismart RGBW {"NAME":"Zemismart LED","GPIO":[0,0,0,0,38,37,0,0,0,39,40,0,0],"FLAG":0,"BASE":18} ``` ## Light ``` -Brilliant 20702/06 Garden {"NAME":"Brilliant Gard","GPIO":[0,0,0,0,37,0,255,255,38,0,39,0,0],"FLAG":0,"BASE":18} -Brilliant Smart WiFi Downlight CCT {"NAME":"SmartCCTDwnLgt","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} -Fcmila XDD-48W {"NAME":"XDD-48W","GPIO":[0,0,0,0,37,40,0,0,38,25,39,0,0],"FLAG":0,"BASE":18} -Mi LED Desk Lamp MJTD01YL {"NAME":"Mi Desk Lamp","GPIO":[0,0,17,0,37,38,0,0,150,151,0,0,0],"FLAG":0,"BASE":66} -Mirabella Genio Dimmable CCT Downlight {"NAME":"GenioDLightCCT","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":48} -Mirabella Genio Dimmable RGBCCT Downlight {"NAME":"GenioDLightRGB","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} -Sonoff BN-SZ01 {"NAME":"Sonoff BN-SZ","GPIO":[0,0,0,0,0,0,0,0,37,56,0,0,0],"FLAG":0,"BASE":22} -Spotlight 9cm RGB+W 7W {"NAME":"Spotlight RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} -Utorch PZE-911 {"NAME":"Utorch PZE-911","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":1} -Utorch UT40 {"NAME":"Utorch UT40","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":1} -Wipro Next 20W Smart LED Batten {"NAME":"WIPROBatten","GPIO":[255,255,255,255,255,37,255,255,255,47,255,255,255],"FLAG":1,"BASE":18} -Zemismart 14W RGB-CCT {"NAME":"ZemiDownLight6","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} -Zemismart 4" 10W RGBW {"NAME":"ZemiDownLight","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Arlec 15W Security Floodlight {"NAME":"ArlecFlood","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":15,"BASE":18} +Arlec 40W 4000lm LED Batten Light {"NAME":"Arlec Batten","GPIO":[0,0,0,0,0,37,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +BlitzWolf BW-LT20 {"NAME":"BW-LT20","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":15,"BASE":18} +Brilliant CORDIA Colour Temperature Changing LED Flush Ceiling Light {"NAME":"Brilliant Oyst","GPIO":[0,0,0,0,0,37,0,0,38,0,0,0,0],"FLAG":0,"BASE":18} +BrilliantSmart 20695 Downlight CCT {"NAME":"SmartCCTDwnLgt","GPIO":[0,0,0,0,0,37,0,0,0,38,0,0,0],"FLAG":0,"BASE":48} +BrilliantSmart Prism LED RGBCCT Downlight {"NAME":"Prism","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +BrilliantSmart RGB Garden Kit {"NAME":"Brilliant Gard","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Calex 429250 Ceiling {"NAME":"Calex_LED","GPIO":[0,0,0,0,0,0,0,0,52,37,38,54,0],"FLAG":0,"BASE":18} +Connect SmartHome CSH-240RGB10W {"NAME":"Connect1","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Connect SmartHome CSH-FSTN12 {"NAME":"CSH-FSTN12","GPIO":[0,0,0,0,37,0,0,0,38,0,39,0,0],"FLAG":0,"BASE":18} +Deta DET902HA 10W 940lm RGB+CCT {"NAME":"Deta DownLight","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Fcmila XDD-48W {"NAME":"XDD-48W","GPIO":[0,0,0,0,37,40,0,0,38,25,39,0,0],"FLAG":0,"BASE":18} +Hama 10W RGB+WW {"NAME":"Hama Smart WiF","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Hyperikon 14W 1000lm 6" Downlight {"NAME":"HyperikonDL6","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +iHomma Downlight {"NAME":"iHommaLEDDownl","GPIO":[0,0,0,0,0,40,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +Infray 9W 900LM {"NAME":"InfrayRGBCCT","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +LE lampUX 15W RGBCCT Ceiling {"NAME":"LE lampUX 15W","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Lohas ZN026CL10 RGBCCT {"NAME":"Lohas LED Lamp","GPIO":[0,0,0,0,38,37,0,0,40,39,41,0,0],"FLAG":0,"BASE":18} +Mi LED Desk Lamp MJTD01YL {"NAME":"Mi Desk Lamp","GPIO":[0,0,17,0,37,38,0,0,150,151,0,0,0],"FLAG":0,"BASE":66} +Mirabella Genio I002741 {"NAME":"GenioDLightRGB","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Mirabella Genio I002742 {"NAME":"GenioDLightCCT","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":48} +Mirabella Genio I002798 Warm White Filament Festoon {"NAME":"GenioFestoon","GPIO":[0,0,0,0,0,0,0,0,0,0,37,0,0],"FLAG":0,"BASE":18} +Novostella UT88835 20W Floodlight {"NAME":"Novo 20W Flood","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Sonoff BN-SZ01 {"NAME":"Sonoff BN-SZ","GPIO":[0,0,0,0,0,0,0,0,37,56,0,0,0],"FLAG":0,"BASE":22} +Spotlight 9cm RGB+W 7W {"NAME":"Spotlight RGBW","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Teckin FL41 {"NAME":"Teckin FL41","GPIO":[0,0,0,0,0,17,0,0,0,0,21,0,0],"FLAG":0,"BASE":18} +Utorch PZE-911 {"NAME":"Utorch PZE-911","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":1} +Utorch UT40 {"NAME":"Utorch UT40","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":1} +Verve Design Angie 18W Ceiling Light With RGB Ring {"NAME":"ACL12HA Light","GPIO":[0,0,0,0,38,37,0,0,41,39,40,0,0],"FLAG":0,"BASE":18} +Verve Design Hana 24W CCT Ceiling {"NAME":"Verve ACL03HA","GPIO":[0,0,0,0,0,0,0,0,38,0,37,0,0],"FLAG":0,"BASE":48} +Wipro Next 20W Smart LED Batten {"NAME":"WIPROBatten","GPIO":[0,0,0,0,0,37,0,0,0,47,0,0,0],"FLAG":1,"BASE":18} +Zemismart 4" 10W RGBCCT {"NAME":"ZemiDownLight4","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} +Zemismart 4" 10W RGBW {"NAME":"ZemiDownLight","GPIO":[0,0,0,0,0,0,0,0,0,143,0,144,0],"FLAG":0,"BASE":27} +Zemismart 6" 14W RGBCCT {"NAME":"ZemiDownLight6","GPIO":[0,0,0,0,37,40,0,0,38,41,39,0,0],"FLAG":0,"BASE":18} ``` ## Outdoor Plug ``` -Acenx SOP04-US Dual {"NAME":"SOP04-US Dual","GPIO":[255,255,255,255,56,57,255,255,21,17,22,255,255],"FLAG":0,"BASE":18} -Albohes PC-1606 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} -ECF-SOP03 {"NAME":"Outdoor3Outlet","GPIO":[0,0,0,23,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} -Feit Electric Dual {"NAME":"Prime Smart ou","GPIO":[255,255,255,255,157,56,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -Geeni GN-OW101-101 {"NAME":"Geeni Outdoor","GPIO":[17,0,0,0,0,57,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} -LEPOWER {"NAME":"LEPOWER Outdoo","GPIO":[255,255,255,255,56,57,255,255,21,17,22,255,255],"FLAG":0,"BASE":18} -Oittm Outdoor {"NAME":"Oittm Outdoor","GPIO":[17,0,0,0,0,0,0,0,0,0,56,21,255],"FLAG":0,"BASE":18} -SK03 {"NAME":"SK03 Outdoor","GPIO":[17,0,0,0,133,132,0,0,131,57,56,21,0],"FLAG":0,"BASE":57} -Top-Max PS-1602 {"NAME":"PS-1602","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +Acenx SOP04-US Dual {"NAME":"SOP04-US Dual","GPIO":[255,255,255,255,56,57,0,0,21,17,22,255,255],"FLAG":0,"BASE":18} +Aicliv SOP03-US {"NAME":"AICLIV SOP03US","GPIO":[0,0,0,23,57,0,0,0,21,18,22,0,0],"FLAG":15,"BASE":18} +Albohes PC-1606 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} +Albohes PS-1602 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} +Aoycocr X13 {"NAME":"Aoycocr X13","GPIO":[0,0,56,0,0,0,0,0,21,17,0,22,0],"FLAG":0,"BASE":18} +Brennenstuhl WA 3000 XS02 {"NAME":"WA 3000 XS02","GPIO":[0,0,0,0,21,17,0,0,158,52,0,0,0],"FLAG":0,"BASE":61} +C137 IP55 {"NAME":"C137 Outdoor","GPIO":[0,17,0,56,134,132,0,0,21,131,22,0,0],"FLAG":15,"BASE":18} +C168 IP64 {"NAME":"C188","GPIO":[56,0,57,0,18,0,0,0,21,17,157,22,0],"FLAG":0,"BASE":18} +ECF-SOP03 {"NAME":"Outdoor3Outlet","GPIO":[0,0,0,23,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Ecoolbuy 4 socket {"NAME":"ECCOLBUY 4","GPIO":[0,0,0,0,22,23,0,0,21,57,17,0,24],"FLAG":0,"BASE":18} +Feit Electric PLUG/WIFI/WP {"NAME":"Prime Smart ou","GPIO":[0,255,0,255,157,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Geeni Outdoor {"NAME":"Geeni Outdoor","GPIO":[17,0,0,0,0,57,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} +Geeni Outdoor DUO Dual Outlet {"NAME":"Geeni Dual Out","GPIO":[17,0,0,0,0,57,0,0,0,56,21,0,22],"FLAG":0,"BASE":18} +HA109US {"NAME":"HA109US","GPIO":[17,0,0,0,52,53,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} +iClever IC-BS06 {"NAME":"iClever Switch","GPIO":[0,0,0,0,157,56,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +King-Link C128 {"NAME":"King-Link C128","GPIO":[0,0,58,0,22,56,0,0,23,157,17,21,57],"FLAG":0,"BASE":18} +LEPOWER {"NAME":"LEPOWER Outdoo","GPIO":[255,255,255,255,56,57,0,0,21,17,22,255,255],"FLAG":0,"BASE":18} +Luminea NX-4458 {"NAME":"Luminea NX4458","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":65} +Maxcio EOP03-EU {"NAME":"Maxcio EOP03-EU","GPIO":[0,0,0,0,22,57,0,0,21,52,17,0,58],"FLAG":0,"BASE":18} +Maxcio SOP02-US {"NAME":"Maxcio SOP02US","GPIO":[0,0,0,0,0,157,0,0,21,17,22,0,0],"FLAG":15,"BASE":18} +Merkury MI-OW101-101W {"NAME":"Merkury Switch","GPIO":[17,255,255,255,0,56,0,0,0,54,21,255,255],"FLAG":1,"BASE":18} +Minoston MP22W {"NAME":"Minoston MP22W","GPIO":[0,0,0,0,56,0,0,0,21,90,0,0,0],"FLAG":0,"BASE":18} +Nedis IP44 PO120 {"NAME":"WIFIPO120FWT","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} +Obi Stecker IP44 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61} +Oittm Outdoor {"NAME":"Oittm Outdoor","GPIO":[17,0,0,0,0,0,0,0,0,0,56,21,255],"FLAG":0,"BASE":18} +Peteme PS-1602 {"NAME":"Peteme Outdoor","GPIO":[17,0,0,0,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":18} +Prime CCRCWFIO2PK {"NAME":"Prime Outdoor","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Signstek EOP03-EU {"NAME":"Signstek EOP03","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":15,"BASE":18} +SK03 {"NAME":"SK03 Outdoor","GPIO":[17,0,0,0,133,132,0,0,131,57,56,21,0],"FLAG":0,"BASE":57} +STITCH by Monoprice 35556 {"NAME":"STITCH 35556","GPIO":[255,255,255,255,22,57,0,0,21,56,17,255,255],"FLAG":0,"BASE":18} +Teckin SS31 {"NAME":"Teckin SS31","GPIO":[255,255,255,255,56,57,255,255,21,17,22,255,255],"FLAG":15,"BASE":18} +Teckin SS33 {"NAME":"Teckin SS31","GPIO":[0,0,0,23,56,57,0,0,21,17,22,0,0],"FLAG":15,"BASE":18} +Teckin SS42 {"NAME":"Teckin SS42","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Top-Max PS-1602 {"NAME":"PS-1602","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +Torchstar LITEdge 2-in-1 {"NAME":"LITEdge Plug","GPIO":[0,0,0,0,56,57,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Ucomen PA-GEBA-01SWP {"NAME":"PA-GEBA-01SWP","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} ``` ## Plug ``` -3Stone Mini {"NAME":"3Stone Smart P","GPIO":[0,17,0,0,0,0,0,0,0,57,21,0,0],"FLAG":0,"BASE":18} -Acashna HS108 {"NAME":"HS108","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} -Aisirer UK1 {"NAME":"AISIRER","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} -Albohes PS-1602 {"NAME":"Albohes PC1606","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":1,"BASE":39} -Aldi Medion Life+ S85225 {"NAME":"Medion","GPIO":[0,0,0,17,134,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":52} -Alexfirst TV-ASP801EU {"NAME":"Alexfirst","GPIO":[17,0,0,0,54,56,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} -Alfawise PE1004T {"NAME":"PE1004T","GPIO":[255,255,255,255,56,57,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -Amysen YX-WS01 {"NAME":"Amyse YX WS01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18} -ANBES ABS-CZ004 {"NAME":"ANBES ABS-CZ00","GPIO":[0,0,0,0,21,133,0,0,131,17,132,22,18],"FLAG":0,"BASE":18} -Anoopsyche AWP07L {"NAME":"Anoopsyche AWP","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} -Anoopsyche JH-G01B1 {"NAME":"JH-G01B1","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} -Anoopsyche UK1D {"NAME":"UK1D","GPIO":[0,17,0,0,133,132,0,0,130,52,21,0,0],"FLAG":0,"BASE":6} -Aoycocr EU5-16A {"NAME":"Aoycocr","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} -Aoycocr Smart Plug {"NAME":"Aoycocr Smart ","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} -Arlec Grid Connect PC189HA {"NAME":"Arlec","GPIO":[0,0,0,0,123,0,0,0,21,56,17,0,0],"FLAG":0,"BASE":18} -Arlec Twin PC288HA {"NAME":"Arlec Twin","GPIO":[0,17,0,22,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} -Aukey SH-PA1 {"NAME":"AUKEY SH-PA1","GPIO":[0,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} -Avatar 10A {"NAME":"AWP07L","GPIO":[56,255,255,255,255,134,255,255,130,17,132,21,255],"FLAG":1,"BASE":18} -Avatar AWP07L 10A {"NAME":"Avatar AWP07L","GPIO":[56,255,255,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Avatto JH-G01E {"NAME":"AVATTO JH-G01E","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} -AWP02L-N {"NAME":"AWP02L-N","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} -AWP04L {"NAME":"AWP04L","GPIO":[57,255,255,131,255,134,0,0,21,17,132,56,255],"FLAG":0,"BASE":18} -AWP07L {"NAME":"AISIRER AWP07L","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} -AWP08L {"NAME":"AWP08L","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} -AzpenHome Smart {"NAME":"Socket2Me","GPIO":[52,255,255,255,22,255,0,0,21,255,17,255,255],"FLAG":0,"BASE":18} -Bestek MRJ1011 {"NAME":"BestekMRJ1011","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} -Bilikay SP10 {"NAME":"Bilikay SP10","GPIO":[255,37,255,17,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} -Blitzwolf BW-SHP2 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Blitzwolf BW-SHP3 {"NAME":"Blitzwolf SHP3","GPIO":[56,0,57,0,22,134,0,0,131,18,132,21,17],"FLAG":0,"BASE":45} -Blitzwolf BW-SHP3 alt {"NAME":"Blitzwolf SHP3","GPIO":[18,56,0,131,134,132,0,0,17,0,22,21,0],"FLAG":0,"BASE":18} -Blitzwolf BW-SHP4 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Blitzwolf BW-SHP5 {"NAME":"SHP5","GPIO":[57,145,56,146,0,22,0,0,0,0,21,0,17],"FLAG":0,"BASE":18} -Blitzwolf BW-SHP6 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Blitzwolf BW-SHP8 {"NAME":"SHP8","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} -BN-LINK BNC-60/U133TJ-2P {"NAME":"BNC-60/U133TJ","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":18} -Brilliant USB Charger {"NAME":"Brilliant","GPIO":[0,0,0,0,0,21,0,0,0,52,90,0,0],"FLAG":0,"BASE":18} -BSD15 {"NAME":"TuyaPlugBSD15","GPIO":[255,255,255,255,255,255,255,255,21,17,56,255,255],"FLAG":1,"BASE":18} -BSD25 {"NAME":"Tuya Wifi Plug","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -BSD29 {"NAME":"BSD29","GPIO":[0,0,0,131,134,132,0,0,21,17,56,0,0],"FLAG":0,"BASE":52} -BSD33 {"NAME":"Generic","GPIO":[255,255,255,131,134,132,255,255,21,17,56,255,255],"FLAG":0,"BASE":18} -BSD34 {"NAME":"BSD34 Plug","GPIO":[255,255,255,255,255,255,255,255,21,17,56,255,255],"FLAG":0,"BASE":18} -CE Smart Home - LA-WF3 {"NAME":"CE LA-WF3","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Conico SM-PW70 {"NAME":"Conico SM-PW70","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} -Coosa {"NAME":"COOSA","GPIO":[0,0,0,0,57,52,0,0,21,17,255,0,0],"FLAG":0,"BASE":1} -Coosa SP1 {"NAME":"COOSA SP1","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -CrazyLynX WiFi {"NAME":"CrazyLynX","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} -CYYLTF BIFANS J23 {"NAME":"CYYLTD BIFANS J23","GPIO":[56,0,0,0,0,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} -Delock 11826 {"NAME":"Delock 11826","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} -Digoo DG-SP01 {"NAME":"DG-SP01","GPIO":[255,17,255,21,56,37,255,255,38,39,40,255,255],"FLAG":0,"BASE":18} -Digoo NX-SP202 {"NAME":"Generic_SP202","GPIO":[52,0,0,131,91,134,0,0,22,17,132,21,0],"FLAG":0,"BASE":63} -DILISENS SP201 {"NAME":"Dilisens SP201","GPIO":[0,0,131,0,133,132,52,21,18,22,17,0,0],"FLAG":0,"BASE":18} -DWFeng AWP02L-N {"NAME":"AWP02L-N","GPIO":[255,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} -ECO Plugs CT-065W {"NAME":"ECO/CT-065W","GPIO":[255,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} -EFUN SH331W {"NAME":"Efun-Plug","GPIO":[56,0,158,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} -EletecPro 2 {"NAME":"EletecPro-2","GPIO":[255,255,255,255,17,255,255,255,53,52,21,255,255],"FLAG":1,"BASE":18} -ENJOWI SP111-EU-W {"NAME":"Enjowi SP111-E","GPIO":[17,56,0,0,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} -Epicka {"NAME":"Epicka","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} -Esicoo YX-WS01 {"NAME":"Esicoo Plug","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} -Estink C178 {"NAME":"Estink C178","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -ESW01-US {"NAME":"ESW01-US","GPIO":[0,0,0,0,21,56,0,0,0,0,9,0,0],"FLAG":1,"BASE":18} -ET RGB {"NAME":"RGB Smart Plug","GPIO":[37,0,39,0,38,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -EVA LOGIK NWF001 {"NAME":"EVA LOGIK Plug","GPIO":[255,17,255,255,255,255,255,255,255,52,21,255,255],"FLAG":0,"BASE":18} -EVO-Smart JH-G01U {"NAME":"EVO JH-G01U","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":0,"BASE":18} -FK-PW901U {"NAME":"FK-PW901U","GPIO":[56,255,255,255,255,23,255,255,21,17,24,22,255],"FLAG":0,"BASE":18} -FLHS-ZN04 {"NAME":"FLHS-ZN04","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Fontastic SH01 {"NAME":"Fontastic","GPIO":[255,0,255,0,56,0,255,255,21,17,0,0,0],"FLAG":1,"BASE":18} -FrankEver FLHS-ZN04 {"NAME":"Israel plug","GPIO":[57,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45} -GDTech W-US001 {"NAME":"GDTech W-US001","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18} -GDTech W-US003 {"NAME":"W-US003","GPIO":[0,17,255,255,255,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} -Geeni Charge {"NAME":"Geeni Charge","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Geeni Glo {"NAME":"Geeni Glo","GPIO":[0,0,0,0,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} -Geeni Spot {"NAME":"Geeni Spot","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Geeni Switch Duo {"NAME":"Geeni Duo","GPIO":[0,0,0,0,18,22,0,0,17,52,21,0,53],"FLAG":0,"BASE":18} -Globe Smart {"NAME":"GlobeSmartPlug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} -Gosund SP1 {"NAME":"Gosund SP1 v23","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} -Gosund SP111 {"NAME":"Gosund SP111","GPIO":[56,0,57,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} -Gosund SP112 {"NAME":"SHP5","GPIO":[56,145,57,146,255,22,0,0,255,255,21,255,18],"FLAG":0,"BASE":18} -Gosund WP1-1 {"NAME":"Gosund WP1-1","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Gosund WP211 {"NAME":"Gosund wp211","GPIO":[0,0,0,0,21,0,0,0,0,17,0,22,18],"FLAG":0,"BASE":18} -Gosund WP212 {"NAME":"Gosund_WP212","GPIO":[17,0,0,0,18,0,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} -Gosund WP3 {"NAME":"Gosund WP3","GPIO":[0,0,0,0,17,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} -Gosund WP5 {"NAME":"Gosund-WP5","GPIO":[255,255,255,255,17,255,255,255,53,52,21,255,255],"FLAG":1,"BASE":18} -Gosund WP6 {"NAME":"Gosund WP6","GPIO":[0,0,0,17,0,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} -Grefic TE101 {"NAME":"Grefic TE101","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} -Gyman SM-PW701U {"NAME":"Gyman","GPIO":[255,255,157,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -Hauppauge SL-1642 {"NAME":"SL-1642","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -HiHome WPP-16T {"NAME":"HiHome WPP-16T","GPIO":[17,56,255,255,134,132,255,255,18,255,22,130,21],"FLAG":1,"BASE":18} -hiwild W-US002 {"NAME":"W-US002","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,158],"FLAG":0,"BASE":18} -Houzetek AWP07L {"NAME":"AWP07L","GPIO":[56,255,255,130,255,134,255,255,0,17,132,21,255],"FLAG":0,"BASE":18} -HuaFan QinLu {"NAME":"Huafan SS","GPIO":[56,0,0,57,17,29,0,0,132,130,133,0,0],"FLAG":0,"BASE":24} -Hyleton 313 {"NAME":"Hyleton 313","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} -Hyleton 317 {"NAME":"hyleton-317","GPIO":[56,0,57,0,58,0,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} -Innens BSD29 {"NAME":"BSD29","GPIO":[0,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":52} -iSwitch {"NAME":"Smart Plug XSA","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} -Jeeo TF-SH330 {"NAME":"Jeeo TF-SH330","GPIO":[56,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":1,"BASE":18} -Jinvoo SM-PW701U {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Jinvoo SM-PW762U {"NAME":"SM-PW762U","GPIO":[0,0,0,0,158,56,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} -Jules V (Upgrade Version) {"NAME":"Jules-V_UV","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} -Jules.V NX-SM300 {"NAME":"NX-SM300","GPIO":[52,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6} -Kimire S12 {"NAME":"Kimire S12","GPIO":[255,255,255,17,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} -King-Link C128 {"NAME":"King-Link C128","GPIO":[0,0,55,0,22,53,0,0,23,52,17,21,54],"FLAG":0,"BASE":18} -KMC 4 30608 {"NAME":"KMC 4 Outlet","GPIO":[0,56,0,0,133,132,0,0,130,22,23,21,17],"FLAG":0,"BASE":36} -KMC 70011 {"NAME":"KMC 70011","GPIO":[17,0,0,0,133,132,0,0,130,56,21,0,0],"FLAG":0,"BASE":36} -Kogan SmarterHome™ Energy Meter {"NAME":"Kogan Smart Sw","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} -Koogeek KLSP1 {"NAME":"Koogeek-KLSP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} -Koogeek KLUP1 {"NAME":"Koogeek-KLUP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} -LA-WF3 {"NAME":"CE Smart Plug","GPIO":[255,255,255,255,56,57,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -Laduo YX-DE01 {"NAME":"YX-DE01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} -LESHP KS-501 {"NAME":"LESHP KS-501","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} -LINGANZH 16A {"NAME":"Linganzh Smart","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} -Lonsonho 10A Type E {"NAME":"Lonsonho10ALed","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Lonsonho RGB {"NAME":"RGB Smart Plug","GPIO":[37,0,38,0,0,39,0,0,0,17,0,21,0],"FLAG":0,"BASE":45} -LSC Smart Connect {"NAME":"LSC Smart Plug","GPIO":[255,255,255,255,56,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18} -Luminea ZX-2820-675 {"NAME":"ZX2820-675","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Luminea ZX-2820-919 {"NAME":"Luminea ZX2820","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":65} -Martin Jerry {"NAME":"MJ V01","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -Martin Jerry XS-SSA01 {"NAME":"MJ_XS-SSA01","GPIO":[0,0,0,0,0,0,0,0,56,17,0,21,0],"FLAG":0,"BASE":18} -Maxcio W-DE004 {"NAME":"Maxcio W-DE004","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} -Maxcio W-UK007 {"NAME":"Maxcio","GPIO":[0,17,0,0,0,0,255,255,0,56,21,0,0],"FLAG":0,"BASE":18} -Maxcio W-UK007S {"NAME":"Maxcio","GPIO":[56,0,255,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Maxcio W-US002S {"NAME":"W-US002S","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Maxcio W-US003 {"NAME":"W-US003","GPIO":[255,17,255,255,255,255,255,255,255,22,21,255,255],"FLAG":0,"BASE":18} -Maxcio YX-DE02 {"NAME":"Generic","GPIO":[255,17,255,21,56,37,255,255,38,39,40,255,255],"FLAG":1,"BASE":18} -Merisny P2 {"NAME":"Generic","GPIO":[0,0,52,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} -Merkury 70011 MIC-WW102 {"NAME":"MIC-WW102","GPIO":[17,0,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":36} -Merkury Innovations {"NAME":"Merkury Switch","GPIO":[255,255,255,255,53,56,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} -Merkury MI-OW101-101W {"NAME":"Merkury Switch","GPIO":[17,255,255,255,255,56,255,255,255,255,21,255,255],"FLAG":1,"BASE":18} -Mirabella Genio {"NAME":"Genio 1","GPIO":[0,0,56,0,0,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} -Nanxin NX-SM200 16A {"NAME":"NX-SM200","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} -NEO Coolcam 16A {"NAME":"Neo Coolcam 16","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} -Obi Stecker {"NAME":"OBI Socket","GPIO":[255,255,0,255,52,21,0,0,54,255,17,0,255],"FLAG":1,"BASE":51} -Obi Stecker 2 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61} -Obi Stecker IP44 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61} -Oittm Smart {"NAME":"Oittm","GPIO":[0,0,0,0,21,56,0,0,17,0,0,0,0],"FLAG":0,"BASE":1} -Oukitel P1 {"NAME":"Oukitel P1Dual","GPIO":[52,255,255,255,255,255,255,255,22,17,255,21,255],"FLAG":0,"BASE":18} -Oukitel X6P {"NAME":"OUKITEL X6P","GPIO":[255,255,57,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} -OxaOxe NX-SM200 {"NAME":"NX-SM200","GPIO":[17,0,0,0,133,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":18} -Oxaoxe NX-SM800 {"NAME":"NX-SM800","GPIO":[0,0,0,131,0,134,0,0,21,17,132,0,0],"FLAG":0,"BASE":45} -OxaOxe NX-SP202 {"NAME":"oxaoxe-dual","GPIO":[18,0,0,0,134,132,0,0,131,56,21,22,17],"FLAG":0,"BASE":18} -OxaOxe NX-SP202 v2 {"NAME":"oxaoxe-dold","GPIO":[56,0,0,131,17,134,0,0,21,18,132,22,0],"FLAG":0,"BASE":18} -Panamalar NX-SM200 16A {"NAME":"NX-SM200","GPIO":[0,0,0,0,56,134,0,0,131,17,132,21,0],"FLAG":1,"BASE":18} -Powertech {"NAME":"Jaycar","GPIO":[56,0,0,0,0,0,0,0,0,9,0,21,0],"FLAG":0,"BASE":6} -Powrui AW-08 {"NAME":"POWRUI AW-08","GPIO":[0,0,0,0,9,21,0,0,0,52,57,0,0],"FLAG":1,"BASE":18} -Prime CCRCWFII113PK {"NAME":"Prime","GPIO":[0,0,0,0,57,56,0,0,21,122,0,0,0],"FLAG":0,"BASE":18} -RGB Light {"NAME":"RGB Light","GPIO":[37,0,38,0,0,39,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} -RSH-WS007 {"NAME":"RSH-WS007","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} -Shelly Plug S {"NAME":"Shelly Plug S","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":2,"BASE":45} -Slitinto NX-SM110 {"NAME":"Slitinto SM110","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Slitinto NX-SM112 {"NAME":"NX-SM112","GPIO":[158,0,0,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45} -Slitinto NX-SP202 {"NAME":"Slitinto SP202","GPIO":[17,0,0,0,134,132,0,0,131,52,22,21,91],"FLAG":0,"BASE":64} -SM-PW702 {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -SmartDGM PP-W162 {"NAME":"SmartDGM Plug","GPIO":[0,0,0,17,134,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":18} -Sonoff S20 {"NAME":"Sonoff S20","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":8} -Sonoff S22 TH {"NAME":"Sonoff S22","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":4} -Sonoff S26 {"NAME":"Sonoff S26","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":8} -Sonoff S31 {"NAME":"Sonoff S31","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":41} -SP201 Dual {"NAME":"SP-201","GPIO":[31,0,0,131,17,134,0,0,21,18,132,22,0],"FLAG":0,"BASE":45} -SS01 {"NAME":"Smart Plug SS0","GPIO":[255,255,255,255,255,255,255,255,21,17,255,255,255],"FLAG":1,"BASE":18} -STITCH by Monoprice 27937 {"NAME":"Stitch 27937","GPIO":[17,0,56,0,133,132,0,0,131,0,21,0,57],"FLAG":0,"BASE":18} -STITCH by Monoprice 35511 {"NAME":"Stitch 35511","GPIO":[56,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} -SuperNight Dual {"NAME":"SuperNight Dua","GPIO":[255,17,255,21,132,133,255,255,22,130,58,255,255],"FLAG":1,"BASE":18} -SWA1 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} -SWA1 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} -SWA11 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} -SWA9 {"NAME":"SWA9","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} -TanTan WP3 {"NAME":"TanTan WP3","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} -Teckin SP10 {"NAME":"Teckin SP10","GPIO":[255,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} -Teckin SP20 {"NAME":"TECKIN SP20","GPIO":[56,255,57,255,21,134,0,0,131,17,132,0,0],"FLAG":0,"BASE":45} -Teckin SP21 {"NAME":"Teckin SP21","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":45} -Teckin SP22 {"NAME":"Teckin","GPIO":[0,17,0,57,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52} -Teckin SP23 {"NAME":"Teckin SP23","GPIO":[56,255,57,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} -Teckin SP25 {"NAME":"Teckin SP25","GPIO":[56,255,255,255,255,255,255,255,22,17,255,21,255],"FLAG":1,"BASE":18} -Teckin SP27 {"NAME":"Teckin SP27","GPIO":[56,255,255,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} -Tflag NX-SM100 {"NAME":"NX-SM100","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} -THRUMM XS-A11 {"NAME":"THRUMM XS-A11 ","GPIO":[255,17,255,255,255,255,255,255,255,56,29,255,255],"FLAG":0,"BASE":18} -Timethinker TK04 {"NAME":"TimethinkerEU","GPIO":[255,255,255,255,17,255,0,0,255,52,21,255,0],"FLAG":0,"BASE":18} -TimeThinker WS2 {"NAME":"TimeThinkerWS2","GPIO":[0,0,0,0,17,0,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} -TomaxUSA HKWL-SO07W {"NAME":"HKWL-SO07W","GPIO":[17,255,255,255,255,255,255,255,255,255,21,255,56],"FLAG":0,"BASE":18} -WAGA life CHCZ02MB {"NAME":"WAGA CHCZ02MB","GPIO":[57,0,0,131,0,134,0,0,21,17,132,56,0],"FLAG":0,"BASE":68} -WAZA 10A {"NAME":"WAZA","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":1,"BASE":18} -WAZA JH-G01B {"NAME":"Teckin SP27","GPIO":[255,255,255,255,53,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -WAZA JH-G01E {"NAME":"Waza JH-G01E","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} -WiOn 50055 {"NAME":"WiOn","GPIO":[255,0,52,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} -WL-SC01 {"NAME":"WL-SC01","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":1} -Woox R4026 {"NAME":"WOOX R4026","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} -XS-SSA01 {"NAME":"XS-SSA01","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":0,"BASE":18} -XS-SSA01 Alternate {"NAME":"XS-SSA01","GPIO":[255,17,255,255,255,255,255,255,56,255,255,21,255],"FLAG":0,"BASE":18} -XS-SSA05 {"NAME":"XS-SSA05","GPIO":[30,255,255,131,255,133,255,255,21,17,132,31,255],"FLAG":1,"BASE":18} -XS-SSA06 {"NAME":"RGB Light","GPIO":[37,0,38,0,0,39,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} -Yelomin JH-G01E {"NAME":"Yelomin","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":18} -YERON US101 {"NAME":"YERON_US101","GPIO":[255,255,255,17,133,132,255,255,131,56,21,255,255],"FLAG":0,"BASE":18} -YT-E003 {"NAME":"YT-E003-SP202","GPIO":[17,0,0,0,134,132,0,0,131,52,22,21,91],"FLAG":0,"BASE":64} -YX-WS02 {"NAME":"Amysen YX-WS02","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18} -ZBR-001 {"NAME":"ZBR-001","GPIO":[17,255,255,255,133,132,255,255,130,56,21,255,57],"FLAG":1,"BASE":18} -ZooZee {"NAME":"ZooZee","GPIO":[57,255,56,255,255,255,255,255,255,17,255,21,255],"FLAG":0,"BASE":18} -ZooZee SA102 {"NAME":"ZooZee","GPIO":[57,255,56,255,21,133,255,255,131,17,132,255,255],"FLAG":0,"BASE":18} -ZooZee SE131 {"NAME":"ZooZee SE131","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} -ZSP-001 {"NAME":"ZSP-001","GPIO":[17,255,255,255,133,132,255,255,130,57,21,255,56],"FLAG":1,"BASE":18} +2nice SP111 {"NAME":"2NICE SP111","GPIO":[56,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":2,"BASE":18} +2nice UP111 {"NAME":"2NICE UP111","GPIO":[0,52,0,17,134,132,0,0,131,157,21,0,0],"FLAG":0,"BASE":18} +3Stone Mini {"NAME":"3Stone Smart P","GPIO":[0,17,0,0,0,0,0,0,0,57,21,0,0],"FLAG":0,"BASE":18} +Ablue WP1 {"NAME":"Ablue","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +Aigoss 16A Mini {"NAME":"Aigoss Plug","GPIO":[255,255,0,255,52,21,0,0,54,255,17,0,255],"FLAG":15,"BASE":51} +Aisirer AWP07L {"NAME":"AISIRER AWP07L","GPIO":[56,0,57,0,0,133,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} +Aisirer AWP07L v2 {"NAME":"AWP07L v2","GPIO":[0,17,57,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Aisirer AWP08L {"NAME":"AISIRER AWP08L","GPIO":[0,0,56,0,0,0,0,0,0,0,0,21,0],"FLAG":0,"BASE":18} +Aisirer AWP08L v2 {"NAME":"AISIRER AWP08L","GPIO":[0,0,0,0,17,57,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Aisirer JH-G018 v2 {"NAME":"AISIRER JH-G01","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Aisirer JH-G01B {"NAME":"AISIRER","GPIO":[0,0,0,0,21,0,0,0,56,17,0,0,0],"FLAG":1,"BASE":18} +Aisirer SWA11 {"NAME":"SWA11","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +Aisirer UK-1 {"NAME":"AISIRER","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,0],"FLAG":1,"BASE":18} +Alexfirst TV-ASP801EU {"NAME":"Alexfirst","GPIO":[17,0,0,0,54,56,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Alfawise PE1004T {"NAME":"PE1004T","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Alfawise PME1606 {"NAME":"PME1606","GPIO":[0,0,0,17,133,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":18} +Amysen JSM-WF02 {"NAME":"Amysen JSMWF02","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Amysen YX-WS01 {"NAME":"Amysen YX-WS01","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +ANBES ABS-CZ004 {"NAME":"ANBES ABS-CZ00","GPIO":[0,0,0,0,21,133,0,0,131,17,132,22,18],"FLAG":0,"BASE":18} +Anncoe C318 {"NAME":"Anncoe C318","GPIO":[90,145,255,146,0,0,0,0,21,53,0,0,0],"FLAG":0,"BASE":18} +Anoopsyche AWP08L {"NAME":"AWP08L-Annopsy","GPIO":[0,0,0,0,17,56,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Anoopsyche SP-G01 {"NAME":"SP-G01","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} +Anoopsyche SP15 {"NAME":"Anoop SP15","GPIO":[0,0,0,0,56,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +Anoopsyche UK1D {"NAME":"UK1D","GPIO":[0,17,0,0,133,132,0,0,130,52,21,0,0],"FLAG":0,"BASE":6} +Aoycocr EU5 16A {"NAME":"Aoycocr","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} +Aoycocr EU6S {"NAME":"Aoycocr EU6S","GPIO":[255,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":17} +Aoycocr U2S {"NAME":"Aoycocr U2S","GPIO":[56,0,57,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Aoycocr U3S {"NAME":"Aoycocr U3S","GPIO":[56,255,57,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Aoycocr X10S {"NAME":"Aoycocr X10S","GPIO":[56,0,57,0,21,134,0,0,131,17,132,0,0],"FLAG":0,"BASE":45} +Aoycocr X5P {"NAME":"Aoycocr X5P","GPIO":[56,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Aoycocr X6 {"NAME":"Aoycocr X6","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Arlec PC189HA {"NAME":"Arlec Single","GPIO":[0,0,0,0,57,0,0,0,21,0,90,0,0],"FLAG":0,"BASE":18} +Arlec PC190HA {"NAME":"Arlec-PC190HA","GPIO":[0,0,0,0,0,0,0,0,21,56,17,0,0],"FLAG":0,"BASE":18} +Arlec Twin PC288HA {"NAME":"Arlec Twin","GPIO":[0,17,0,22,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Atomi AT1217 {"NAME":"AT1217","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Aukey SH-PA1 {"NAME":"AUKEY SH-PA1","GPIO":[0,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Aunics Smart EU {"NAME":"AUNICS","GPIO":[0,0,0,17,134,132,0,0,131,157,21,0,0],"FLAG":0,"BASE":18} +Aunics Smart IT {"NAME":"AUNICS","GPIO":[0,0,0,17,134,132,0,0,131,157,21,0,0],"FLAG":0,"BASE":18} +Avatar AWP01L {"NAME":"AWP01L","GPIO":[0,0,0,0,0,56,0,0,0,17,21,0,0],"FLAG":0,"BASE":18} +Avatar AWP02L-N {"NAME":"AWP02L-N","GPIO":[158,0,0,0,56,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Avatar AWP04L {"NAME":"AWP04L","GPIO":[57,255,255,131,255,134,0,0,21,17,132,56,255],"FLAG":0,"BASE":18} +Avatar AWP07L {"NAME":"AWP07L","GPIO":[56,255,255,255,255,134,0,0,130,17,132,21,255],"FLAG":1,"BASE":18} +Avatar AWP07L v2 {"NAME":"AWP07L","GPIO":[56,255,255,255,255,134,255,255,131,17,132,21,255],"FLAG":0,"BASE":18} +Avatar AWP08L {"NAME":"AWP08L","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Avatar AWP12L Capsule 2-in-1 {"NAME":"Dual Plug","GPIO":[0,0,0,0,0,0,0,0,21,17,0,22,0],"FLAG":0,"BASE":18} +Avatar AWP14H {"NAME":"Avatar UK 10A","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Avatto JH-G01E {"NAME":"AVATTO JH-G01E","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":41} +Avatto NAS-WR01W 10A {"NAME":"AvattoNAS-WR01W","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Avatto OT06 16A {"NAME":"Avatto OT06","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} +AWP02L-N {"NAME":"AWP02L-N","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +AzpenHome Smart {"NAME":"Socket2Me","GPIO":[52,255,255,255,22,255,0,0,21,255,17,255,255],"FLAG":0,"BASE":18} +Bakibo TP22Y {"NAME":"Bakibo TP22Y","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52} +Bauhn ASPU-1019 {"NAME":"Buahn Smart Pl","GPIO":[0,0,0,0,21,22,0,0,0,56,17,0,0],"FLAG":0,"BASE":18} +Bestek MRJ1011 {"NAME":"BestekMRJ1011","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +BlitzWolf BW-SHP2 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +BlitzWolf BW-SHP3 {"NAME":"BlitzWolf SHP3","GPIO":[56,0,57,0,22,134,0,0,131,18,132,21,17],"FLAG":0,"BASE":45} +BlitzWolf BW-SHP3 alt {"NAME":"BlitzWolf SHP3","GPIO":[18,56,0,131,134,132,0,0,17,0,22,21,0],"FLAG":0,"BASE":18} +BlitzWolf BW-SHP4 {"NAME":"BlitzWolf SHP","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +BlitzWolf BW-SHP5 {"NAME":"SHP5","GPIO":[57,145,56,146,0,22,0,0,0,0,21,0,17],"FLAG":0,"BASE":18} +BlitzWolf BW-SHP6 10A {"NAME":"BW-SHP6 10A","GPIO":[158,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Blitzwolf BW-SHP6 15A {"NAME":"Blitzwolf SHP6","GPIO":[56,255,158,255,132,134,0,0,131,17,0,21,0],"FLAG":0,"BASE":45} +BlitzWolf BW-SHP7 {"NAME":"SHP7","GPIO":[17,158,57,131,134,132,0,0,18,56,21,0,22],"FLAG":0,"BASE":45} +BN-LINK BNC-60/U133TJ-2P {"NAME":"BNC-60/U133TJ","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":18} +Brennenstuhl WA 3000 XS01 {"NAME":"WA 3000 XS01","GPIO":[0,0,0,0,21,17,0,0,158,52,0,0,0],"FLAG":0,"BASE":61} +Brilliant HK17654S05 {"NAME":"HK17654S05","GPIO":[17,255,255,255,133,132,255,255,131,56,21,255,255],"FLAG":0,"BASE":18} +Brilliant Lighting BL20925 {"NAME":"BL20925","GPIO":[0,0,0,17,133,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":52} +BrilliantSmart 20676 USB Charger {"NAME":"Brilliant","GPIO":[0,0,0,0,0,21,0,0,0,52,90,0,0],"FLAG":0,"BASE":18} +BSD13 {"NAME":"TuyaPlugBSD13","GPIO":[0,57,0,0,0,0,0,0,21,17,52,0,0],"FLAG":0,"BASE":18} +BSD15 {"NAME":"TuyaPlugBSD15","GPIO":[255,255,255,255,255,255,0,0,21,17,56,255,255],"FLAG":1,"BASE":18} +BSD25 {"NAME":"Tuya Wifi Plug","GPIO":[255,255,255,255,56,255,0,0,21,17,255,255,255],"FLAG":0,"BASE":18} +BSD29 {"NAME":"BSD29","GPIO":[0,0,0,131,134,132,0,0,21,17,56,0,0],"FLAG":0,"BASE":52} +BSD33 10A {"NAME":"BSD33 type 2","GPIO":[0,0,56,0,0,0,0,0,255,17,255,21,255],"FLAG":0,"BASE":18} +BSD33 16A {"NAME":"Generic","GPIO":[0,255,0,131,134,132,0,0,21,17,56,0,0],"FLAG":0,"BASE":18} +BSD34 {"NAME":"BSD34 Plug","GPIO":[0,0,0,0,0,0,0,0,21,17,56,0,0],"FLAG":0,"BASE":18} +BSD48 16A {"NAME":"BSD48 Plug","GPIO":[0,52,0,0,0,0,0,0,21,17,57,0,0],"FLAG":0,"BASE":18} +CE Smart Home LA-WF3 {"NAME":"CE LA-WF3","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +CE Smart Home LA-WF7 {"NAME":"LITESUN LA-WF7","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":18} +Conico SM-PW70 {"NAME":"Conico SM-PW70","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +Connex CC-P1000 {"NAME":"Connex Smart T","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Coosa {"NAME":"COOSA","GPIO":[0,0,0,0,57,52,0,0,21,17,255,0,0],"FLAG":0,"BASE":1} +Coosa SP1 {"NAME":"COOSA SP1","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +CrazyLynX WiFi {"NAME":"CrazyLynX","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +CYYLTF BIFANS J23 {"NAME":"CYYLTD BIFANS J23","GPIO":[56,0,0,0,0,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +DE-1 16A {"NAME":"DE-1","GPIO":[0,17,0,0,133,0,0,0,0,52,21,0,0],"FLAG":1,"BASE":18} +DeLock 11826 {"NAME":"DeLock 11826","GPIO":[17,0,0,0,0,0,0,0,21,158,0,0,0],"FLAG":0,"BASE":1} +Deltaco SH-P01 {"NAME":"DELTACO SH-P01","GPIO":[0,0,0,0,0,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Deltaco SH-P01E {"NAME":"DELTACO SH-P01E","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} +Deltaco SH-P02 {"NAME":"Deltaco SH-P02","GPIO":[18,0,0,0,134,132,0,0,131,56,21,22,17],"FLAG":0,"BASE":18} +Deta 6930HA {"NAME":"DetaSmartPlug","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Digoo DG-SP01 {"NAME":"DG-SP01","GPIO":[255,17,255,21,56,37,0,0,38,39,40,255,255],"FLAG":0,"BASE":18} +Digoo NX-SP202 {"NAME":"Generic_SP202","GPIO":[52,0,0,131,91,134,0,0,22,17,132,21,0],"FLAG":0,"BASE":63} +Dilisens NX-SP201 Mini 2 in 1 {"NAME":"NX-SP201","GPIO":[0,0,131,0,134,132,52,21,18,22,17,0,0],"FLAG":0,"BASE":18} +DILISENS SP201 {"NAME":"Dilisens SP201","GPIO":[0,0,131,0,133,132,52,21,18,22,17,0,0],"FLAG":0,"BASE":18} +Dunnes Stores {"NAME":"SmartLifePlug","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +DWFeng AWP02L-N {"NAME":"AWP02L-N","GPIO":[255,255,56,255,255,255,0,0,255,17,255,21,255],"FLAG":0,"BASE":18} +DWFeng BSD01 {"NAME":"DWFeng BSD01","GPIO":[255,255,255,255,255,255,255,255,21,17,56,255,255],"FLAG":15,"BASE":18} +ECO Plugs CT-065W {"NAME":"ECO/CT-065W","GPIO":[255,255,255,255,255,255,0,0,255,17,255,21,255],"FLAG":0,"BASE":18} +eco4life DPS1101S {"NAME":"Eco4Life Plug","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +ednet 84334 {"NAME":"84334","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +eFamilyCloud ASDFEE174 {"NAME":"eFamily Plug","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +EFUN SH331W {"NAME":"Efun-Plug","GPIO":[56,0,158,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} +EletecPro 2 {"NAME":"EletecPro-2","GPIO":[255,255,255,255,17,255,0,0,53,52,21,255,255],"FLAG":1,"BASE":18} +Enjowi SP111-EU-W {"NAME":"Enjowi SP111-E","GPIO":[17,56,0,0,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} +Epicka {"NAME":"Epicka","GPIO":[255,255,255,255,57,56,0,0,21,17,255,255,255],"FLAG":1,"BASE":18} +Esicoo JSM-WF02 {"NAME":"Esicoo Plug","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Esicoo YX-WS01 {"NAME":"Esicoo Plug","GPIO":[255,17,255,255,255,255,0,0,255,56,21,255,255],"FLAG":0,"BASE":18} +Estink C178 {"NAME":"Estink C178","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Etekcity ESW01-USA {"NAME":"ESW01-USA","GPIO":[0,0,0,0,21,157,0,0,132,133,17,130,52],"FLAG":0,"BASE":55} +Eva Logik NWF001 {"NAME":"EVA LOGIK Plug","GPIO":[255,17,255,255,255,255,0,0,255,52,21,255,255],"FLAG":0,"BASE":18} +EVO-Smart JH-G01U {"NAME":"EVO JH-G01U","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":0,"BASE":18} +Feit Electric PLUG/WIFI {"NAME":"Feit Wifi Plug","GPIO":[0,0,0,56,0,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +FK-PW901U {"NAME":"FK-PW901U","GPIO":[56,255,255,255,255,23,0,0,21,17,24,22,255],"FLAG":0,"BASE":18} +FLHS-ZN04 {"NAME":"FLHS-ZN04","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Fontastic SH01 {"NAME":"Fontastic","GPIO":[255,0,255,0,56,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +FrankEver FLHS-ZN04 {"NAME":"Israel plug","GPIO":[57,0,56,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45} +GDTech W-US001 {"NAME":"GDTech W-US001","GPIO":[255,17,255,255,255,255,0,0,255,56,21,255,255],"FLAG":1,"BASE":18} +GDTech W-US003 {"NAME":"W-US003","GPIO":[0,17,255,255,255,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Geeni Spot {"NAME":"Geeni Spot","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Geeni Spot Glo {"NAME":"Geeni Glo","GPIO":[0,0,0,0,56,0,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Geeni Switch {"NAME":"Geeni Switch","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Geeni Switch Duo {"NAME":"Geeni Duo","GPIO":[0,0,0,0,18,22,0,0,17,52,21,0,53],"FLAG":0,"BASE":18} +Globe 50020 2 Outlet {"NAME":"Globe 50020","GPIO":[0,158,0,57,18,17,0,0,21,56,22,0,0],"FLAG":0,"BASE":18} +Globe Smart {"NAME":"GlobeSmartPlug","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +GoldenDot Mini {"NAME":"GoldenDot Mini","GPIO":[0,17,0,0,0,0,0,0,0,57,21,0,0],"FLAG":0,"BASE":52} +Gosund SP1 {"NAME":"Gosund SP1 v23","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} +Gosund SP111 {"NAME":"Gosund SP111","GPIO":[56,0,57,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} +Gosund SP111 v1.1 {"NAME":"SP111 v1.1","GPIO":[56,0,158,0,132,134,0,0,131,17,0,21,0],"FLAG":0,"BASE":45} +Gosund SP111 v1.4 {"NAME":"Gosund SP111","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Gosund SP112 {"NAME":"SHP5","GPIO":[57,145,56,146,255,22,0,0,255,255,21,255,18],"FLAG":0,"BASE":18} +Gosund UP111 {"NAME":"Gosund UP111","GPIO":[0,52,0,17,134,132,0,0,131,157,21,0,0],"FLAG":0,"BASE":18} +Gosund WP1 {"NAME":"Gosund WP1-1","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Gosund WP2 {"NAME":"Gosund WP2","GPIO":[17,158,57,0,18,0,0,0,22,56,21,0,0],"FLAG":0,"BASE":18} +Gosund WP211 {"NAME":"Gosund wp211","GPIO":[0,0,0,0,21,0,0,0,0,17,0,22,18],"FLAG":0,"BASE":18} +Gosund WP212 {"NAME":"Gosund_WP212","GPIO":[17,0,0,0,18,0,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} +Gosund WP3 {"NAME":"Gosund WP3","GPIO":[0,0,0,0,17,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} +Gosund WP5 {"NAME":"Gosund-WP5","GPIO":[255,255,255,255,17,255,0,0,56,158,21,255,255],"FLAG":0,"BASE":18} +Gosund WP6 {"NAME":"Gosund WP6","GPIO":[0,0,0,17,0,0,0,0,56,57,21,0,0],"FLAG":0,"BASE":18} +Grefic TE101 {"NAME":"Grefic TE101","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +Gyman SM-PW701U {"NAME":"Gyman","GPIO":[255,255,157,255,56,255,0,0,21,17,255,255,255],"FLAG":0,"BASE":18} +Hama 176565 {"NAME":"hama","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52} +Hauppauge 01647 {"NAME":"SL-1642","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +HiHome WPP-10S1 {"NAME":"HIhome WPP-10S","GPIO":[56,0,158,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":49} +HiHome WPP-10S2 {"NAME":"HiHome WPP-10S","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} +HiHome WPP-16S {"NAME":"HIhome WPP-16S","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} +HiHome WPP-16T {"NAME":"HiHome WPP-16T","GPIO":[17,56,255,255,134,132,0,0,18,255,22,130,21],"FLAG":1,"BASE":18} +HIPER IoT P01 {"NAME":"HIPER IoT P01","GPIO":[0,0,0,0,0,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +hiwild W-US002 {"NAME":"W-US002","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,158],"FLAG":0,"BASE":18} +Houzetek AWP07L {"NAME":"AWP07L","GPIO":[56,255,255,130,255,134,0,0,0,17,132,21,255],"FLAG":0,"BASE":18} +HS108 {"NAME":"HS108","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} +HS108A {"NAME":"HS108A","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +HuaFan QinLu {"NAME":"Huafan SS","GPIO":[56,0,0,57,17,29,0,0,132,130,133,0,0],"FLAG":0,"BASE":24} +Hykker SE-0792 {"NAME":"Hykker SE-0792","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Hyleton 312 {"NAME":"MANZOKU HLT312","GPIO":[0,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Hyleton 313 {"NAME":"Hyleton 313","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Hyleton 314 {"NAME":"hyleton-314","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Hyleton 315 {"NAME":"hyleton-315","GPIO":[0,0,0,0,57,56,0,0,21,90,0,0,0],"FLAG":0,"BASE":18} +Hyleton 317 {"NAME":"hyleton-317","GPIO":[56,0,57,0,58,0,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} +Ihommate ZCH-02 {"NAME":"ZCH-02","GPIO":[0,0,0,17,133,132,0,0,130,56,21,0,0],"FLAG":1,"BASE":18} +iSwitch {"NAME":"Smart Plug XSA","GPIO":[255,17,255,255,255,255,0,0,255,56,21,255,255],"FLAG":0,"BASE":18} +Jeeo TF-SH330 {"NAME":"Jeeo TF-SH330","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":1,"BASE":18} +Jeeo TF-SH331W {"NAME":"Jeeo SH331W","GPIO":[56,0,158,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} +Jinvoo SM-PW701U {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Jinvoo SM-PW712UA 10A {"NAME":"SM-PW712UA","GPIO":[0,0,0,158,56,57,0,0,22,17,21,0,0],"FLAG":15,"BASE":18} +Jinvoo SM-PW762U {"NAME":"SM-PW762U","GPIO":[0,0,0,0,158,56,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Jomarto SH1123 {"NAME":"SH1123","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Jules V (Upgrade Version) {"NAME":"Jules-V_UV","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} +Jules.V NX-SM300 {"NAME":"NX-SM300","GPIO":[52,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6} +Jules.V NX-SP203 {"NAME":"NX-SP203","GPIO":[52,0,0,0,17,134,255,255,21,18,0,22,0],"FLAG":0,"BASE":18} +JVMAC-EU01 {"NAME":"JVMAC","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Kimire S12 {"NAME":"Kimire S12","GPIO":[255,255,255,17,255,255,0,0,255,56,21,255,255],"FLAG":0,"BASE":18} +King-Link KL-US-WF002 {"NAME":"Kinglink-plug","GPIO":[0,0,0,0,0,21,0,0,52,17,0,0,0],"FLAG":0,"BASE":18} +Kisslink SP200 {"NAME":"Kisslink SP200","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +KMC 30137 {"NAME":"KMC 30137","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +KMC 4 {"NAME":"KMC 4 Outlet","GPIO":[0,56,0,0,133,132,0,0,130,22,23,21,17],"FLAG":0,"BASE":36} +KMC 70011 {"NAME":"KMC 70011","GPIO":[17,0,0,0,133,132,0,0,130,56,21,0,0],"FLAG":0,"BASE":36} +Kogan Energy Meter {"NAME":"Kogan Smart Sw","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Kogan Energy Meter & USB {"NAME":"KoganPOW","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52} +Koogeek KLSP1 {"NAME":"Koogeek-KLSP1","GPIO":[0,56,0,17,134,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":18} +Koogeek KLSP2 {"NAME":"KOOGEEK KLSP2","GPIO":[57,145,56,146,0,22,0,0,0,0,21,0,17],"FLAG":0,"BASE":45} +Koogeek KLUP1 {"NAME":"Koogeek-KLUP1","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +Koogeek W-DEXI {"NAME":"W-DEXI","GPIO":[0,90,0,0,134,132,0,0,130,52,21,0,0],"FLAG":0,"BASE":18} +Laduo YX-DE01 {"NAME":"YX-DE01","GPIO":[255,17,255,255,255,255,0,0,255,56,21,255,255],"FLAG":0,"BASE":18} +LESHP KS-501 {"NAME":"LESHP KS-501","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Loetad EU3S 16A {"NAME":"Loetad EU3S 16","GPIO":[0,255,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":18} +Lonsonho 10A Type E {"NAME":"Lonsonho10ALed","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +LoraTap SP400W-IT {"NAME":"LoraTap SP400W","GPIO":[0,0,0,0,157,56,0,0,21,17,0,0,0],"FLAG":15,"BASE":18} +LSC Smart Connect Power {"NAME":"LSC Smart Plug","GPIO":[255,255,255,255,56,255,0,0,21,255,17,255,255],"FLAG":0,"BASE":18} +LSC Smart Connect Power Plug v2 {"NAME":"LSC Smart Plug","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Lumiman LM650 {"NAME":"Lumiman LM650","GPIO":[0,0,0,0,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Luminea NX-4491 {"NAME":"Luminea NX-449","GPIO":[56,0,158,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Luminea ZX-2820 {"NAME":"ZX2820-675","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Luminea ZX-2820 v2 {"NAME":"ZX2820-675","GPIO":[0,0,0,17,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":65} +Luminea ZX-2858 {"NAME":"Luminea SF-200","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Martin Jerry XS-SSA01 {"NAME":"MJ_XS-SSA01","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Maxcio W-DE004 {"NAME":"Maxcio W-DE004","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} +Maxcio W-UK007 {"NAME":"Maxcio","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Maxcio W-UK007S {"NAME":"Maxcio","GPIO":[56,0,255,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Maxcio W-US002S {"NAME":"W-US002S","GPIO":[57,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Maxcio W-US003 {"NAME":"W-US003","GPIO":[255,17,255,255,255,255,0,0,255,22,21,255,255],"FLAG":0,"BASE":18} +Maxcio YX-DE02 {"NAME":"Maxcio DE02","GPIO":[0,17,0,21,56,22,0,0,37,38,39,0,0],"FLAG":0,"BASE":18} +Maxcio YX-DE04 {"NAME":"Maxcio YX-DE04","GPIO":[255,17,255,21,56,40,0,0,37,38,39,255,255],"FLAG":1,"BASE":18} +MaxKare XKJJ-0218 {"NAME":"MaxKare XKJJ-0","GPIO":[0,0,0,0,18,133,0,0,21,17,132,22,130],"FLAG":0,"BASE":18} +Medion Life+ S85225 {"NAME":"Medion","GPIO":[0,0,0,17,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52} +Merkury MI-WW101-199 {"NAME":"merkury WW101","GPIO":[0,0,0,0,0,0,0,0,56,90,0,21,0],"FLAG":0,"BASE":18} +Merkury MI-WW102-199L {"NAME":"MIC-WW102","GPIO":[17,0,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":36} +Merkury MI-WW105-199W {"NAME":"Merkury Switch","GPIO":[255,255,255,255,53,56,0,0,21,17,255,255,255],"FLAG":1,"BASE":18} +Minleaf W-DEXI {"NAME":"W-DEXI","GPIO":[0,17,0,0,134,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":18} +Mirabella Genio 1002341 {"NAME":"Genio 1","GPIO":[0,0,56,0,0,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +Moes NX-SP203 {"NAME":"Moes NX-SP203","GPIO":[52,0,0,0,17,134,0,0,21,18,0,22,0],"FLAG":0,"BASE":18} +Moes WS-UEU {"NAME":"MoesHouse","GPIO":[0,0,0,21,17,0,0,0,57,0,0,0,0],"FLAG":0,"BASE":18} +Nanxin NX-SM400 {"NAME":"NX-SM400","GPIO":[0,0,0,17,134,132,0,0,130,52,21,0,0],"FLAG":0,"BASE":18} +Nedis P110 {"NAME":"Nedis WIFIP110","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} +Nedis P130 {"NAME":"WIFIP130FWT","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +NEO Coolcam 16A {"NAME":"Neo Coolcam 16","GPIO":[17,0,0,0,133,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} +NEO Coolcam 16A v2 {"NAME":"Neo Coolcam 16","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":49} +NEO Coolcam NAS-WR01W {"NAME":"NAS-WR01W","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Nishica SM-PW701I {"NAME":"SM-PW701I","GPIO":[255,255,255,255,255,255,255,255,21,52,17,255,255],"FLAG":15,"BASE":18} +NX-SM112 {"NAME":"NX-SM112v3","GPIO":[0,0,0,0,134,132,0,0,158,17,130,21,0],"FLAG":0,"BASE":45} +NX-SM200 {"NAME":"NX-SM200","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} +Obi Stecker {"NAME":"OBI Socket","GPIO":[255,255,0,255,52,21,0,0,54,255,17,0,255],"FLAG":1,"BASE":51} +Obi Stecker 2 {"NAME":"OBI Socket 2","GPIO":[0,0,0,0,21,17,0,0,56,53,0,0,0],"FLAG":0,"BASE":61} +Oittm Smart {"NAME":"Oittm","GPIO":[0,0,0,0,21,56,0,0,17,0,0,0,0],"FLAG":0,"BASE":1} +Oukitel P1 {"NAME":"Oukitel P1Dual","GPIO":[52,255,0,255,0,0,0,0,22,17,0,21,0],"FLAG":0,"BASE":18} +Oukitel P2 {"NAME":"Oukitel P2","GPIO":[0,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Oukitel X6P {"NAME":"OUKITEL X6P","GPIO":[0,0,57,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +OxaOxe NX-SM200 {"NAME":"NX-SM200","GPIO":[17,0,0,0,133,132,0,0,131,158,21,0,0],"FLAG":0,"BASE":18} +Oxaoxe NX-SM800 {"NAME":"NX-SM800","GPIO":[0,0,0,131,0,134,0,0,21,17,132,0,0],"FLAG":0,"BASE":45} +OxaOxe NX-SP202 {"NAME":"oxaoxe-dual","GPIO":[18,0,0,0,134,132,0,0,131,56,21,22,17],"FLAG":0,"BASE":18} +OxaOxe NX-SP202 v2 {"NAME":"oxaoxe-dold","GPIO":[56,0,0,131,17,134,0,0,21,18,132,22,0],"FLAG":0,"BASE":18} +Panamalar NX-SM200 {"NAME":"NX-SM200","GPIO":[0,0,0,0,56,134,0,0,131,17,132,21,0],"FLAG":1,"BASE":18} +Positivo PPW1000 {"NAME":"PPW1000","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Powertech {"NAME":"Jaycar","GPIO":[56,0,0,0,0,0,0,0,0,9,0,21,0],"FLAG":0,"BASE":6} +Powrui AW-08 {"NAME":"POWRUI AW-08","GPIO":[0,0,0,0,9,21,0,0,0,52,57,0,0],"FLAG":1,"BASE":18} +Powrui Surge Protector 4USB+3AC {"NAME":"POWRUI AHR-077","GPIO":[0,0,0,0,19,18,0,0,22,23,17,21,157],"FLAG":0,"BASE":18} +Premier PWIFPLG {"NAME":"Premier Plug","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":1,"BASE":18} +Prime CCRCWFII113PK {"NAME":"Prime","GPIO":[0,0,0,0,57,56,0,0,21,122,0,0,0],"FLAG":0,"BASE":18} +RenPho RF-SM004 {"NAME":"RenPho RFSM004","GPIO":[0,0,0,0,157,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +RSH-WS007-EU {"NAME":"RSH-WS007","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":1,"BASE":18} +Shelly Plug S {"NAME":"Shelly Plug S","GPIO":[57,255,56,255,0,134,0,0,131,17,132,21,0],"FLAG":2,"BASE":45} +Slitinto NX-SM110 {"NAME":"Slitinto SM110","GPIO":[0,0,56,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Slitinto NX-SM112 {"NAME":"NX-SM112","GPIO":[158,0,0,131,0,134,0,0,0,17,132,21,0],"FLAG":0,"BASE":45} +Slitinto NX-SM112 v2 {"NAME":"Slitinto NX SM","GPIO":[56,255,158,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Slitinto NX-SM200 {"NAME":"NX-SM200","GPIO":[0,0,0,17,134,132,0,0,0,52,21,130,0],"FLAG":0,"BASE":45} +Slitinto NX-SM2001 {"NAME":"NX-SM2001","GPIO":[0,0,0,17,134,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":45} +Slitinto NX-SP201 Mini 2 in 1 {"NAME":"Slitinto Dual ","GPIO":[158,0,0,131,90,134,0,0,21,91,132,22,0],"FLAG":0,"BASE":18} +Slitinto NX-SP202 {"NAME":"Slitinto SP202","GPIO":[17,0,0,0,134,132,0,0,131,52,22,21,91],"FLAG":0,"BASE":64} +Smaho {"NAME":"SMAHO WiFi P.","GPIO":[17,0,0,0,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":18} +SmartDGM PP-W162 {"NAME":"SmartDGM Plug","GPIO":[0,0,0,17,134,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":18} +Sonoff S20 {"NAME":"Sonoff S20","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":8} +Sonoff S22 TH {"NAME":"Sonoff S22","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":4} +Sonoff S26 {"NAME":"Sonoff S26","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":8} +Sonoff S31 {"NAME":"Sonoff S31","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":41} +Sonoff S31 Lite {"NAME":"Sonoff S31","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":41} +SP10 {"NAME":"Bilikay SP10","GPIO":[0,37,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +SP201 Dual {"NAME":"SP-201","GPIO":[31,0,0,131,17,134,0,0,21,18,132,22,0],"FLAG":0,"BASE":45} +SPARKE JH-G01E 10A {"NAME":"SPARKE JH-G01E","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +SPC Clever 6201B {"NAME":"SPC Clever Plu","GPIO":[17,0,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +SS01 {"NAME":"Smart Plug SS0","GPIO":[255,255,255,255,255,255,0,0,21,17,255,255,255],"FLAG":1,"BASE":18} +STITCH by Monoprice 27937 {"NAME":"Stitch 27937","GPIO":[17,0,56,0,133,132,0,0,131,0,21,0,57],"FLAG":0,"BASE":18} +STITCH by Monoprice 35511 {"NAME":"Stitch 35511","GPIO":[56,0,57,0,0,133,0,0,0,17,132,21,131],"FLAG":0,"BASE":18} +SuperNight Dual {"NAME":"SuperNight Dua","GPIO":[255,17,255,21,132,133,0,0,22,130,58,255,255],"FLAG":1,"BASE":18} +SWA1 {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +SWA1 FR {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +SWA1 UK {"NAME":"SWA1","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +SWA11 {"NAME":"SWA11","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +SWA5 {"NAME":"Lingan SWA5","GPIO":[56,0,0,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +SWA9 {"NAME":"SWA9","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +SwissTone SH 100 {"NAME":"SwissTone","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Sygonix SY-4276902 {"NAME":"SYGONIX","GPIO":[0,0,0,17,133,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":18} +TanTan WP3 {"NAME":"TanTan WP3","GPIO":[57,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +TCP WISSINWUK {"NAME":"TCP_Plug","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":45} +Teckin SP10 {"NAME":"Teckin SP10","GPIO":[255,255,56,255,255,255,0,0,255,17,255,21,255],"FLAG":0,"BASE":18} +Teckin SP20 {"NAME":"TECKIN SP20","GPIO":[56,255,57,255,21,134,0,0,131,17,132,0,0],"FLAG":0,"BASE":45} +Teckin SP21 {"NAME":"Teckin SP21","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":45} +Teckin SP22 {"NAME":"Teckin","GPIO":[0,17,0,57,134,132,0,0,131,56,21,0,0],"FLAG":0,"BASE":52} +Teckin SP23 {"NAME":"Teckin SP23","GPIO":[56,255,57,255,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Teckin SP25 {"NAME":"Teckin SP25","GPIO":[56,255,255,255,255,255,0,0,22,17,255,21,255],"FLAG":1,"BASE":18} +Teckin SP27 {"NAME":"Teckin SP27","GPIO":[56,255,255,255,255,255,0,0,255,17,255,21,255],"FLAG":0,"BASE":18} +Tflag NX-SM100 {"NAME":"NX-SM100","GPIO":[56,0,0,0,0,134,0,0,21,17,132,57,131],"FLAG":0,"BASE":18} +TikLok TL650 {"NAME":"TikLok Mini","GPIO":[0,0,0,0,57,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Timethinker TK04 {"NAME":"TimethinkerEU","GPIO":[255,255,255,255,17,255,0,0,255,52,21,255,0],"FLAG":0,"BASE":18} +TimeThinker WS2 {"NAME":"TimeThinkerWS2","GPIO":[0,0,0,0,17,0,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} +TomaxUSA HKWL-SO07W {"NAME":"HKWL-SO07W","GPIO":[17,255,255,255,255,255,0,0,255,255,21,255,56],"FLAG":0,"BASE":18} +Topersun WL-SC01 {"NAME":"Topersun ","GPIO":[0,0,0,0,52,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +TopGreener TGWF115APM {"NAME":"TGWF115APM","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":18} +Torchstar LITEdge Smart {"NAME":"LITEdge Plug","GPIO":[0,17,0,0,0,0,0,0,0,52,21,0,0],"FLAG":0,"BASE":18} +TP20 {"NAME":"TP20","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +TP24 {"NAME":"TP24","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +U10 Series {"NAME":"WIFI-Socket","GPIO":[255,17,255,255,255,255,255,255,255,56,21,255,255],"FLAG":1,"BASE":18} +Ultralink UL-P01W {"NAME":"UL-P01W","GPIO":[0,52,0,17,134,132,0,0,131,157,21,0,0],"FLAG":0,"BASE":18} +Varna Crafts 16A {"NAME":"VC Plug","GPIO":[157,0,0,0,0,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +Vaupan X6P {"NAME":"Vaupan 10a X6P","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +Vingo {"NAME":"Karpal-01","GPIO":[0,0,0,0,0,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Vivanco 39625 Smart Home Power Adapter {"NAME":"Vivianco","GPIO":[0,0,0,17,133,132,0,0,131,52,21,0,0],"FLAG":0,"BASE":18} +Vivitar HA-1006 {"NAME":"HA-1006","GPIO":[0,0,0,0,56,0,0,0,21,90,0,0,0],"FLAG":0,"BASE":18} +Vivitar HA-1006-AU {"NAME":"HA-1006-AU","GPIO":[0,0,0,0,56,0,0,0,21,90,0,0,0],"FLAG":0,"BASE":18} +WAGA life CHCZ02MB {"NAME":"WAGA CHCZ02MB","GPIO":[57,0,0,131,0,134,0,0,21,17,132,56,0],"FLAG":0,"BASE":68} +WAZA 10A {"NAME":"WAZA","GPIO":[0,0,0,0,21,17,0,0,56,0,0,0,0],"FLAG":1,"BASE":18} +WAZA JH-G01B {"NAME":"Teckin SP27","GPIO":[255,255,255,255,53,255,0,0,21,17,255,255,255],"FLAG":0,"BASE":18} +WAZA JH-G01E 10A {"NAME":"Waza JH-G01E","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":1,"BASE":18} +Waza JH-G01E 16A {"NAME":"Waza JH-G01E 2","GPIO":[0,0,0,0,0,0,0,0,17,52,21,0,0],"FLAG":1,"BASE":18} +WiOn 50055 {"NAME":"WiOn","GPIO":[255,0,52,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} +Wisdom ZY_ACU02 {"NAME":"ZY-ACU02","GPIO":[255,255,255,52,22,21,0,0,31,17,32,255,255],"FLAG":15,"BASE":18} +WL-SC01 {"NAME":"WL-SC01","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":1} +Woox R4026 {"NAME":"WOOX R4026","GPIO":[0,0,0,17,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +Woox R4785 {"NAME":"WooxR4785","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +WOOX R5024 {"NAME":"Woox5024","GPIO":[0,0,56,0,0,0,0,0,0,17,0,21,0],"FLAG":0,"BASE":18} +WP211 {"NAME":"YUNTAB WP211","GPIO":[56,0,158,0,22,0,0,0,0,18,0,21,17],"FLAG":0,"BASE":18} +Wsiiroon {"NAME":"WSIIROON","GPIO":[0,0,0,0,17,56,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Wsiiroon {"NAME":"Wsiiroon/Wsky","GPIO":[0,0,0,0,17,56,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Wyze WLPP1 {"NAME":"WyzePlugWLPP1","GPIO":[0,0,0,0,0,56,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +Xenon SM-PW702-U {"NAME":"SM-PW702","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +XS-A11 {"NAME":"THRUMM XS-A11","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +XS-A12 {"NAME":"XS-A12","GPIO":[37,0,39,0,38,134,0,0,131,17,132,21,0],"FLAG":0,"BASE":45} +XS-A14 {"NAME":"NETVIP XS-A14","GPIO":[37,0,38,0,0,17,0,0,39,21,0,0,0],"FLAG":0,"BASE":18} +XS-A17 {"NAME":"XS-A18","GPIO":[37,0,38,0,0,39,0,0,0,17,0,21,0],"FLAG":0,"BASE":45} +XS-A18 {"NAME":"XS-A18","GPIO":[37,0,38,0,0,39,0,0,0,17,0,21,0],"FLAG":0,"BASE":45} +XS-A23 {"NAME":"XS-A23","GPIO":[56,255,0,131,17,134,0,0,0,18,132,21,22],"FLAG":0,"BASE":45} +XS-SSA01 {"NAME":"XS-SSA01","GPIO":[255,17,255,255,255,255,0,0,255,56,21,255,255],"FLAG":0,"BASE":18} +XS-SSA01 v2 {"NAME":"XS-SSA01","GPIO":[255,17,255,255,255,255,0,0,56,255,255,21,255],"FLAG":0,"BASE":18} +XS-SSA05 {"NAME":"XS-SSA05","GPIO":[30,255,255,131,255,133,0,0,21,17,132,31,255],"FLAG":1,"BASE":18} +XS-SSA06 {"NAME":"XS-SSA06","GPIO":[37,0,38,0,0,39,0,0,0,90,0,21,0],"FLAG":0,"BASE":18} +Yagala SWA9 {"NAME":"SWA9","GPIO":[0,0,0,0,52,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} +Yelomin JH-G01E {"NAME":"Yelomin","GPIO":[0,145,0,146,0,0,0,0,17,56,21,0,0],"FLAG":0,"BASE":18} +YERON US101 {"NAME":"YERON_US101","GPIO":[255,255,255,17,133,132,0,0,131,56,21,255,255],"FLAG":0,"BASE":18} +YT-E003 {"NAME":"YT-E003-SP202","GPIO":[17,0,0,0,134,132,0,0,131,52,22,21,91],"FLAG":0,"BASE":64} +YX-WS02 {"NAME":"Amysen YX-WS02","GPIO":[255,17,255,255,255,255,0,0,255,56,21,255,255],"FLAG":1,"BASE":18} +ZBR-001 {"NAME":"ZBR-001","GPIO":[17,255,255,255,133,132,0,0,130,56,21,255,57],"FLAG":1,"BASE":18} +ZooZee SA101 {"NAME":"ZooZee","GPIO":[57,255,56,255,255,255,0,0,255,17,255,21,255],"FLAG":0,"BASE":18} +ZooZee SA102 {"NAME":"ZooZee","GPIO":[57,255,56,255,21,133,0,0,131,17,132,255,255],"FLAG":0,"BASE":18} +ZooZee SE131 {"NAME":"ZooZee SE131","GPIO":[255,0,56,0,0,0,0,0,255,17,0,21,0],"FLAG":0,"BASE":17} +ZSP-001 {"NAME":"ZSP-001","GPIO":[17,255,255,255,133,132,0,0,130,57,21,255,56],"FLAG":1,"BASE":18} ``` ## Power Strip ``` -3Stone (2019 Model) {"NAME":"3Stone-2019","GPIO":[0,0,56,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} -ACENX 3AC+3USB {"NAME":"ACENX 3-Outlet","GPIO":[56,55,54,53,0,21,0,0,23,24,22,0,17],"FLAG":0,"BASE":18} -Annhome 3AC + 2USB {"NAME":"1200W WiFi SPS","GPIO":[32,0,0,0,57,52,0,0,21,17,22,23,33],"FLAG":0,"BASE":18} -AOFO 3AC+4USB {"NAME":"AOFO","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} -AOFO 4AC+4USB {"NAME":"AOFO4AC4USB","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} -CE Garden Power Stake {"NAME":"CE Power Stake","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -CE Smart Home LTS-6A-W5 {"NAME":"CE Power Strip","GPIO":[52,0,0,0,22,21,0,0,24,23,25,26,17],"FLAG":0,"BASE":18} -CRST LTS-4G-W {"NAME":"CRST LTS-4G-W","GPIO":[0,0,0,0,24,0,255,255,22,23,21,0,0],"FLAG":0,"BASE":18} -Digoo DG-PS01 {"NAME":"Digoo DG-PS01","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18} -Geekbes 4AC+4USB {"NAME":"Geekbes 4xStri","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} -Geeni GN-SW003 {"NAME":"Geeni GNCSW003","GPIO":[52,0,0,0,22,21,0,0,24,25,23,26,17],"FLAG":0,"BASE":18} -Hyleton 330 {"NAME":"Hyleton-330","GPIO":[57,0,0,56,29,17,0,0,31,30,32,0,25],"FLAG":0,"BASE":18} -Hyleton 331 {"NAME":"HLT-331","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,58],"FLAG":0,"BASE":18} -Hyleton 336 {"NAME":"HLT-336","GPIO":[52,0,0,57,29,17,0,0,31,30,0,0,32],"FLAG":0,"BASE":18} -KMC 5 {"NAME":"KMC 5-Outlet","GPIO":[56,0,0,0,25,9,0,0,22,21,23,0,24],"FLAG":0,"BASE":18} -Koogeek KLOE4 {"NAME":"Koogeek KLOE4","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} -LeFun SK2 {"NAME":"LeFun SK2","GPIO":[0,0,0,17,22,21,0,0,23,24,25,0,0],"FLAG":0,"BASE":18} -Meross MSS425 {"NAME":"Meross MSS425","GPIO":[33,0,0,0,56,0,0,0,21,17,22,23,32],"FLAG":0,"BASE":18} -Monoprice 34082 {"NAME":"Stitch 34082","GPIO":[255,255,255,255,21,20,255,255,23,22,24,255,255],"FLAG":0,"BASE":18} -Nedis WIFIP310FWT {"NAME":"Nedis WIFIP310","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} -Powrui AW-39 {"NAME":"Porui AW-39","GPIO":[56,0,0,0,21,255,0,0,23,24,22,0,9],"FLAG":0,"BASE":18} -S2199EU {"NAME":"S2199EU","GPIO":[0,17,0,52,23,25,0,0,21,24,22,0,0],"FLAG":1,"BASE":18} -SM-S0301 {"NAME":"SM-SO301","GPIO":[56,0,0,0,30,17,0,0,32,31,33,0,21],"FLAG":0,"BASE":18} -SM-S0301 {"NAME":"SM-SO301","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,25],"FLAG":0,"BASE":18} -SWB1 {"NAME":"SWB1","GPIO":[52,0,0,0,0,24,0,0,21,17,22,23,0],"FLAG":0,"BASE":18} -Teckin SS30 {"NAME":"Teckin SS30","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,58],"FLAG":0,"BASE":18} -Tellur TLL331031 {"NAME":"Tellur","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} -TESSAN A4L-BK {"NAME":"TESSAN A4L-BK","GPIO":[0,0,0,24,23,0,255,255,21,0,22,0,0],"FLAG":0,"BASE":18} -Viflykoo 3AC+4USB {"NAME":"Viflykoo 3xStr","GPIO":[0,0,53,0,0,23,0,0,21,56,17,24,22],"FLAG":1,"BASE":18} -Woox R4028 {"NAME":"Woox R4028","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18} -Xenon SM-S0301 {"NAME":"SM-SO301","GPIO":[52,255,255,57,29,17,255,255,31,30,32,255,25],"FLAG":0,"BASE":18} -XS-A25 {"NAME":"XS-A25","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} -XSA26-EU {"NAME":"XSA26-EU","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} -Yagala {"NAME":"Yagala","GPIO":[0,0,0,17,22,24,0,0,23,25,21,0,0],"FLAG":0,"BASE":18} -Yagala SWB3 {"NAME":"YAGALA SWB3","GPIO":[0,0,53,0,0,23,0,0,21,0,22,24,0],"FLAG":1,"BASE":18} -Yagala SWB3 v2 {"NAME":"YAGALA SWB3","GPIO":[157,0,53,0,0,23,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} -Yuanguo 4AC + 2 USB {"NAME":"YUANGUO","GPIO":[0,20,0,24,19,18,0,0,17,22,21,23,0],"FLAG":0,"BASE":1} -Zeoota PS022 {"NAME":"ZEOOTA 3x plus","GPIO":[0,57,0,56,22,21,0,0,17,23,24,0,0],"FLAG":1,"BASE":18} -ZLD-44EU-W {"NAME":"ZLD-44EU-W","GPIO":[17,255,255,255,22,21,18,19,23,24,25,0,0],"FLAG":0,"BASE":23} -ZLD-44USA-W {"NAME":"ZLD-44USA-W","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} -ZLD64-EU-W {"NAME":"ZLD64-EU-W","GPIO":[0,56,0,17,22,21,0,0,0,0,23,0,0],"FLAG":0,"BASE":18} +A0F0 ZLD-44EU-W {"NAME":"AOFO-4AC-4USB","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +ACENX 3AC+3USB {"NAME":"ACENX 3-Outlet","GPIO":[56,55,54,53,0,21,0,0,23,24,22,0,17],"FLAG":0,"BASE":18} +Annhome 3AC + 2USB {"NAME":"1200W WiFi SPS","GPIO":[32,0,0,0,57,52,0,0,21,17,22,23,33],"FLAG":0,"BASE":18} +AOFO 3AC+4USB {"NAME":"AOFO","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} +AOFO 4AC+4USB {"NAME":"AOFO4AC4USB","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":0,"BASE":18} +AOFO 4AC+4USB Tuya {"NAME":"AOFO-4AC-4USB","GPIO":[255,255,255,255,255,255,0,0,255,255,255,255,255],"FLAG":1,"BASE":54} +AOFO 4AC+4USB UK {"NAME":"AOFO4AC4USB-UK","GPIO":[0,56,0,17,23,24,0,0,22,21,33,0,0],"FLAG":0,"BASE":18} +Arlec PB88UHA {"NAME":"ArlecPowerStri","GPIO":[0,0,0,255,22,21,0,0,24,23,0,0,0],"FLAG":0,"BASE":18} +Arlec PB89HA {"NAME":"Arlec PB89HA","GPIO":[255,255,255,255,22,21,0,0,24,23,255,255,255],"FLAG":15,"BASE":18} +Bauhn ASPBU-1019 {"NAME":"Bauhn 3AC+3USB","GPIO":[0,157,0,0,22,21,0,0,0,23,17,0,0],"FLAG":0,"BASE":18} +BlitzWolf BW-SHP9 {"NAME":"BlitzWolf SHP9","GPIO":[158,255,0,255,0,23,0,0,21,17,22,24,0],"FLAG":0,"BASE":45} +BrilliantSmart 20691 Powerboard with USB Chargers {"NAME":"B_WiFi-4","GPIO":[56,0,0,57,29,17,0,0,31,30,32,0,25],"FLAG":1,"BASE":18} +CE Smart Home LTS-6A-W5 {"NAME":"CE Power Strip","GPIO":[52,0,0,0,22,21,0,0,24,23,25,26,17],"FLAG":0,"BASE":18} +CE Smart Home Garden Stake LH-7-1 {"NAME":"CE Power Stake","GPIO":[0,0,0,0,56,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +CRST LTS-4G-W {"NAME":"CRST LTS-4G-W","GPIO":[0,0,0,0,24,0,0,0,22,23,21,0,0],"FLAG":0,"BASE":18} +Deltaco SH-P03USB {"NAME":"Deltaco SH-P03","GPIO":[0,56,0,0,0,21,0,0,23,17,22,24,0],"FLAG":1,"BASE":18} +Digoo DG-PS01 {"NAME":"Digoo DG-PS01","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18} +Geekbes 4AC+4USB {"NAME":"Geekbes 4xStri","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +Geeni Surge {"NAME":"Geeni GNCSW003","GPIO":[52,0,0,0,22,21,0,0,24,25,23,26,17],"FLAG":0,"BASE":18} +Geeni Surge Mini {"NAME":"Geeni-GN-SW004","GPIO":[56,0,0,17,0,0,0,0,22,21,23,0,0],"FLAG":15,"BASE":18} +Gousund WP9 {"NAME":"Gosund WP9","GPIO":[56,55,54,53,0,21,0,0,23,24,22,0,17],"FLAG":0,"BASE":18} +Hyleton 330 {"NAME":"Hyleton-330","GPIO":[57,0,0,56,29,17,0,0,31,30,32,0,25],"FLAG":0,"BASE":18} +Hyleton 331 {"NAME":"HLT-331","GPIO":[52,255,255,57,29,17,0,0,31,30,32,255,58],"FLAG":0,"BASE":18} +Hyleton 333 {"NAME":"HLT-333","GPIO":[52,0,0,57,29,17,0,0,31,30,0,0,24],"FLAG":0,"BASE":18} +Hyleton 336 {"NAME":"HLT-336","GPIO":[52,0,0,57,29,17,0,0,31,30,0,0,32],"FLAG":0,"BASE":18} +KMC 5 {"NAME":"KMC 5-Outlet","GPIO":[56,0,0,0,25,9,0,0,22,21,23,0,24],"FLAG":0,"BASE":18} +Kogan Power Strip USB Ports & Energy Meter {"NAME":"Generic","GPIO":[90,56,0,24,134,132,0,0,131,22,23,21,0],"FLAG":0,"BASE":18} +Koogeek KLOE4 {"NAME":"Koogeek KLOE4","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +LeFun SK2 {"NAME":"LeFun SK2","GPIO":[0,0,0,17,22,21,0,0,23,24,25,0,0],"FLAG":0,"BASE":18} +Maxcio ZLD-34EU-W {"NAME":"MAXCIO","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} +Meross MSS425 {"NAME":"Meross MSS425","GPIO":[33,0,0,0,56,0,0,0,21,17,22,23,32],"FLAG":0,"BASE":18} +Mirabella Genio Powerboard I002578 {"NAME":"Genio Powerboa","GPIO":[21,52,0,0,23,22,0,0,25,17,26,24,0],"FLAG":0,"BASE":18} +Nedis P310 {"NAME":"Nedis WIFIP310","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} +Powrui AHR-079 {"NAME":"Powrui Power S","GPIO":[56,0,0,17,19,21,0,0,23,20,22,24,18],"FLAG":0,"BASE":18} +Powrui AW-39 {"NAME":"Powrui AW-39","GPIO":[56,0,0,0,21,255,0,0,23,24,22,0,9],"FLAG":0,"BASE":18} +S2199EU {"NAME":"S2199EU","GPIO":[0,17,0,52,23,25,0,0,21,24,22,0,0],"FLAG":1,"BASE":18} +SA-P402A {"NAME":"SA-P402A","GPIO":[0,17,0,56,23,25,21,24,22,0,0,1,0],"FLAG":1,"BASE":18} +STITCH by Monoprice 34082 {"NAME":"Stitch 34082","GPIO":[255,255,255,255,21,20,0,0,23,22,24,255,255],"FLAG":0,"BASE":18} +SWB1 {"NAME":"SWB1","GPIO":[52,0,0,0,0,24,0,0,21,17,22,23,0],"FLAG":0,"BASE":18} +Teckin SS30 {"NAME":"Teckin SS30","GPIO":[52,255,255,57,29,17,0,0,31,30,32,255,25],"FLAG":0,"BASE":18} +Tellur TLL331031 {"NAME":"Tellur","GPIO":[0,56,0,17,22,21,0,0,0,23,24,0,0],"FLAG":1,"BASE":18} +TESSAN A4L-BK {"NAME":"TESSAN A4L-BK","GPIO":[0,0,0,24,23,0,0,0,21,0,22,0,0],"FLAG":0,"BASE":18} +Tonbux SM-SO301-U {"NAME":"Tonbux SM-SO30","GPIO":[56,0,0,0,29,0,0,0,31,30,32,0,25],"FLAG":0,"BASE":18} +Vivitar HA-1007 {"NAME":"Vivitar HA1007","GPIO":[56,0,0,0,30,17,0,0,32,31,33,0,21],"FLAG":15,"BASE":18} +Vivitar HA-1007-AU {"NAME":"HA-1007-AU","GPIO":[56,17,0,58,29,57,0,0,31,30,32,0,25],"FLAG":0,"BASE":18} +wesmartify essentials 4AC+4USB {"NAME":"essential_4_po","GPIO":[56,0,0,0,24,25,0,0,22,21,23,0,17],"FLAG":0,"BASE":18} +Woox R4028 {"NAME":"Woox R4028","GPIO":[0,56,0,17,23,22,0,0,0,24,21,0,0],"FLAG":1,"BASE":18} +Xenon SM-S0301 {"NAME":"SM-SO301","GPIO":[52,255,255,57,29,17,0,0,31,30,32,255,25],"FLAG":0,"BASE":18} +Xenon SM-S0301-U {"NAME":"SM-SO301-U","GPIO":[52,255,255,57,29,17,0,0,31,30,32,255,25],"FLAG":0,"BASE":18} +Xenon SM-SO301 v2 {"NAME":"SM-SO301","GPIO":[56,0,0,0,30,17,0,0,32,31,33,0,21],"FLAG":0,"BASE":18} +XS-A25 {"NAME":"XS-A25","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} +XS-A26 {"NAME":"XS-A26","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} +XS-A34 {"NAME":"XS-A24","GPIO":[52,0,53,0,25,22,0,0,24,17,23,21,0],"FLAG":0,"BASE":18} +Yagala {"NAME":"Yagala","GPIO":[0,0,0,17,22,24,0,0,23,25,21,0,0],"FLAG":0,"BASE":18} +Yagala SWB3 {"NAME":"YAGALA SWB3","GPIO":[0,0,53,0,0,23,0,0,21,0,22,24,0],"FLAG":1,"BASE":18} +Yagala SWB3 v2 {"NAME":"YAGALA SWB3","GPIO":[157,0,53,0,0,23,0,0,21,17,22,24,0],"FLAG":0,"BASE":18} +Yuanguo 4AC + 2 USB {"NAME":"YUANGUO","GPIO":[0,20,0,24,19,18,0,0,17,22,21,23,0],"FLAG":0,"BASE":1} +Yuanguo 4AC+2USB {"NAME":"YUANGUO","GPIO":[13,20,0,24,19,18,0,0,17,22,21,23,157],"FLAG":0,"BASE":1} +Zeoota PS022 {"NAME":"ZEOOTA 3x plus","GPIO":[0,57,0,56,22,21,0,0,17,23,24,0,0],"FLAG":1,"BASE":18} +Zeoota ZLD-44EU-W {"NAME":"ZEOOTA-ZLD-44E","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +ZLD-44EU-W {"NAME":"ZLD-44EU-W","GPIO":[17,255,255,255,22,21,18,19,23,24,25,0,0],"FLAG":0,"BASE":23} +ZLD-44USA-W {"NAME":"ZLD-44USA-W","GPIO":[0,56,0,17,22,21,0,0,23,24,25,0,0],"FLAG":1,"BASE":18} +ZLD64-EU-W {"NAME":"ZLD64-EU-W","GPIO":[0,56,0,17,22,21,0,0,0,0,23,0,0],"FLAG":0,"BASE":18} ``` ## RF Bridge ``` -Sonoff RF Bridge 433 {"NAME":"Sonoff Bridge","GPIO":[17,148,255,149,255,255,0,0,255,56,255,0,0],"FLAG":0,"BASE":25} +Sonoff RF Bridge 433 {"NAME":"Sonoff Bridge","GPIO":[17,148,255,149,255,255,0,0,255,56,255,0,0],"FLAG":0,"BASE":25} ``` ## Relay ``` -1 Channel Inching/Self-Locking {"NAME":"1 Channel","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":12} -Blitzwolf BW-SS1 {"NAME":"BW-SS1","GPIO":[255,255,255,255,157,21,0,0,255,17,255,255,0],"FLAG":0,"BASE":18} -Canwing CW-001 {"NAME":"Canwing CW-001","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} -EACHEN ST-DC2 {"NAME":"Garage Control","GPIO":[11,0,0,0,23,22,18,0,21,52,12,24,0],"FLAG":1,"BASE":18} -Electrodragon Board SPDT {"NAME":"ED Relay Board","GPIO":[255,255,255,255,255,255,255,255,21,22,255,255,52],"FLAG":1,"BASE":18} -Electrodragon ESP8266 {"NAME":"ElectroDragon","GPIO":[18,255,17,255,255,255,0,0,22,21,255,255,52],"FLAG":1,"BASE":15} -eMylo SS-8839-03 {"NAME":"eMylo","GPIO":[0,0,0,0,56,0,0,0,21,0,17,0,0],"FLAG":1,"BASE":18} -eMylo XL9251WI {"NAME":"XL9251WI","GPIO":[255,255,255,255,56,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18} -eMylo YSA111A1N-FBA {"NAME":"Emylo","GPIO":[255,255,255,255,52,255,255,255,21,255,17,255,255],"FLAG":0,"BASE":18} -ESP-01 Relay V4.0 {"NAME":"ESP01v4","GPIO":[29,52,0,255,255,255,255,255,255,255,255,255,255],"FLAG":0,"BASE":18} -EX Store 2 Kanal V5 {"NAME":"EXS Relay V5","GPIO":[255,255,255,255,255,255,0,0,21,22,31,52,32],"FLAG":0,"BASE":16} -Geekcreit 2 Channel {"NAME":"Geekcreit 2ch","GPIO":[17,0,0,0,0,22,18,0,21,52,0,0,0],"FLAG":1,"BASE":18} -Gocomma Wi-Fi Smart Switch {"NAME":"GoCommaSmartSw","GPIO":[17,255,255,255,21,255,255,255,255,56,255,255,255],"FLAG":0,"BASE":18} -LC Technology 4CH {"NAME":"LC-Tech_4CH ","GPIO":[52,255,17,255,255,255,255,255,21,22,23,24,255],"FLAG":0,"BASE":18} -LinkNode R4 {"NAME":"LinkNode R4","GPIO":[0,0,0,0,0,0,0,0,21,22,23,0,24],"FLAG":0,"BASE":18} -LinkNode R8 {"NAME":"LinkNode R8","GPIO":[0,0,0,0,25,26,0,28,23,24,22,27,21],"FLAG":0,"BASE":18} -MHCOZY {"NAME":"Portail","GPIO":[9,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":1,"BASE":18} -Moeshouse 2 way 2 gang MS-104B {"NAME":"moeshouse2gang","GPIO":[0,0,17,0,160,0,0,0,43,42,21,22,0],"FLAG":0,"BASE":18} -Nova Digital Basic 1 MS101 {"NAME":"NovaDigBasic1","GPIO":[255,255,255,255,56,255,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -QS-WIFI-S03 {"NAME":"Generic","GPIO":[17,255,255,255,255,0,0,0,82,21,0,0,0],"FLAG":0,"BASE":1} -Shelly 1 {"NAME":"Shelly 1","GPIO":[0,0,0,0,21,82,0,0,0,0,0,0,0],"FLAG":0,"BASE":46} -Shelly 1PM {"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18} -Shelly 2 {"NAME":"Shelly 2","GPIO":[0,135,0,136,21,22,0,0,9,0,10,137,0],"FLAG":0,"BASE":47} -Shelly 2.5 {"NAME":"Shelly 2.5","GPIO":[56,255,17,255,21,83,0,0,6,82,5,22,156],"FLAG":2,"BASE":18} -SmartHome Smart Breaker {"NAME":"SmartHome Swit","GPIO":[255,255,255,255,21,255,255,255,17,57,255,56,255],"FLAG":0,"BASE":18} -Sonoff 4CH (R2) {"NAME":"Sonoff 4CH","GPIO":[17,255,255,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":7} -Sonoff 4CH Pro (R2) {"NAME":"Sonoff 4CH Pro","GPIO":[17,255,255,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":23} -Sonoff 5V Inching/Selflock Module RE5V1C {"NAME":"Sonoff RE5V1C","GPIO":[17,255,255,255,255,255,0,0,21,56,0,0,0],"FLAG":0,"BASE":18} -Sonoff Basic {"NAME":"Sonoff Basic","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1} -Sonoff Basic R3 {"NAME":"Basic R3","GPIO":[17,255,0,255,255,0,255,255,21,56,255,0,255],"FLAG":0,"BASE":1} -Sonoff Dual {"NAME":"Sonoff Dual","GPIO":[0,148,0,149,255,0,0,0,0,56,255,0,0],"FLAG":0,"BASE":5} -Sonoff Dual R2 {"NAME":"Sonoff Dual R2","GPIO":[255,255,0,255,0,22,255,17,21,56,0,0,0],"FLAG":0,"BASE":39} -Sonoff Mini {"NAME":"Sonoff Mini","GPIO":[17,0,0,0,9,0,0,0,21,56,0,0,255],"FLAG":0,"BASE":1} -Sonoff Pow {"NAME":"Sonoff Pow","GPIO":[17,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6} -Sonoff Pow R2 {"NAME":"Sonoff Pow R2","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":43} -Sonoff RF {"NAME":"Sonoff RF","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":2} -Sonoff SV {"NAME":"Sonoff SV","GPIO":[17,255,0,255,255,255,0,0,21,56,255,0,0],"FLAG":1,"BASE":3} -Sonoff TH10/TH16 {"NAME":"Sonoff TH","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":4} -Tuya Kinetic Switch {"NAME":"Kinetic Switch","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Wemos Module 10A {"NAME":"WeMos Relay","GPIO":[17,255,52,255,21,255,255,255,255,255,255,255,255],"FLAG":0,"BASE":18} -WL-SW01_10 {"NAME":"WL-SW01_10","GPIO":[17,149,0,148,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} -Yunshan 10A 7-30VDC {"NAME":"Yunshan Relay","GPIO":[0,255,56,255,21,17,0,0,0,0,0,0,0],"FLAG":0,"BASE":33} -Zemismart ERC309 Kinetic {"NAME":"Kinetic Switch","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} +1 Channel Inching/Self-Locking {"NAME":"1 Channel","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":12} +BlitzWolf BW-SS1 {"NAME":"BW-SS1","GPIO":[255,255,255,255,157,21,0,0,255,17,255,255,0],"FLAG":0,"BASE":18} +Canwing CW-001 {"NAME":"Canwing CW-001","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Century Aoke Smart Switch {"NAME":"CenturyAoke","GPIO":[0,255,0,255,21,0,0,0,17,56,255,0,0],"FLAG":0,"BASE":18} +Deta 6000HA Smart Inline Switch {"NAME":"DETA-6000HA","GPIO":[0,17,0,0,0,0,0,0,0,56,21,0,0],"FLAG":0,"BASE":18} +DoHome HomeKit DIY Switch {"NAME":"DoHome DIY","GPIO":[255,255,0,255,255,157,0,0,21,0,0,0,0],"FLAG":0,"BASE":1} +Eachen ST-DC2 {"NAME":"Garage Control","GPIO":[11,0,0,0,23,22,18,0,21,52,12,24,0],"FLAG":1,"BASE":18} +Eachen ST-UDC1 {"NAME":"ST-UDC1","GPIO":[9,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":1,"BASE":18} +Electrodragon Board SPDT {"NAME":"ED Relay Board","GPIO":[255,255,255,255,255,255,0,0,21,22,255,255,52],"FLAG":1,"BASE":18} +Electrodragon ESP8266 {"NAME":"ElectroDragon","GPIO":[18,255,17,255,255,255,0,0,22,21,255,255,52],"FLAG":1,"BASE":15} +eMylo SS-8839-02 {"NAME":"SS-8839-02","GPIO":[0,255,0,255,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +eMylo SS-8839-03 {"NAME":"SS-8839-03","GPIO":[0,255,0,255,52,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +ESP-01 Relay V4.0 {"NAME":"ESP01v4","GPIO":[29,52,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +ESP-01S 5V Relay Module V1.0 {"NAME":"ESP-01S Relay","GPIO":[29,52,255,255,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +ESP12F 220V 10A 7V-30V DC {"NAME":"Yunshan 10A","GPIO":[17,255,52,255,21,10,0,0,22,0,0,0,0],"FLAG":0,"BASE":18} +EX Store 2 Kanal V5 {"NAME":"EXS Relay V5","GPIO":[255,255,255,255,255,255,0,0,21,22,31,52,32],"FLAG":0,"BASE":16} +Garage Door Controller {"NAME":"Garage Opener","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} +Geekcreit 2 Channel AC 85V-250V {"NAME":"Geekcreit 2ch","GPIO":[17,0,0,0,0,22,18,0,21,52,0,0,0],"FLAG":1,"BASE":18} +Geekcreit 5V DIY 4 Channel Jog Inching Self-Locking {"NAME":"Geekcreit-4ch","GPIO":[9,0,0,0,23,22,10,11,21,52,12,24,0],"FLAG":0,"BASE":18} +Geekcreit Module 220V 10A {"NAME":"WeMos Relay","GPIO":[17,255,52,255,21,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Gocomma Wi-Fi Smart Switch {"NAME":"GoCommaSmartSw","GPIO":[17,255,255,255,21,0,0,0,255,56,0,0,0],"FLAG":0,"BASE":18} +Hoch Circuit Breaker 1P {"NAME":"HOCH ZJSB9","GPIO":[17,255,255,255,255,255,0,0,21,56,0,0,0],"FLAG":0,"BASE":18} +L-5A01 {"NAME":"L-5A01","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +LC Technology 5V 2 Channel {"NAME":"LC-ESP01-2R-5V","GPIO":[0,148,0,149,0,0,0,0,21,22,0,0,0],"FLAG":0,"BASE":18} +LC Technology 5V 4 Channel {"NAME":"LC-Tech_4CH ","GPIO":[52,255,17,255,0,0,0,0,21,22,23,24,0],"FLAG":0,"BASE":18} +LC Technology AC/DC 1 Channel ESP-12F Dev Board {"NAME":"LC-ESP12-1R-MV","GPIO":[255,255,157,255,255,21,255,255,255,255,255,255,57],"FLAG":15,"BASE":18} +LinkNode R4 {"NAME":"LinkNode R4","GPIO":[0,0,0,0,0,0,0,0,21,22,23,0,24],"FLAG":0,"BASE":18} +LinkNode R8 {"NAME":"LinkNode R8","GPIO":[0,0,0,0,25,26,0,28,23,24,22,27,21],"FLAG":0,"BASE":18} +LoraTap RR500W {"NAME":"LoraTap RR500W","GPIO":[157,255,255,255,9,255,255,255,255,21,255,255,56],"FLAG":15,"BASE":18} +LoraTap SC500W Roller Shutter {"NAME":"SC500W","GPIO":[0,0,0,158,9,10,0,0,21,17,22,0,0],"FLAG":0,"BASE":18} +Mhcozy 5V {"NAME":"Portail","GPIO":[9,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":1,"BASE":18} +Moes MS-104B-1 {"NAME":"Moes MS-104B","GPIO":[0,0,17,0,160,0,0,0,43,42,21,22,0],"FLAG":0,"BASE":18} +Nova Digital Basic 1 MS101 {"NAME":"NovaDigBasic1","GPIO":[0,255,0,255,56,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Protium PS-1604 {"NAME":"Protium16A","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1} +QS-WIFI-S03 {"NAME":"QS-WIFI-S03","GPIO":[17,255,255,255,255,0,0,0,82,21,0,0,0],"FLAG":0,"BASE":1} +Shelly 1 {"NAME":"Shelly 1","GPIO":[0,0,0,0,21,82,0,0,0,0,0,0,0],"FLAG":0,"BASE":46} +Shelly 1PM {"NAME":"Shelly 1PM","GPIO":[56,0,0,0,82,134,0,0,0,0,0,21,0],"FLAG":2,"BASE":18} +Shelly 2 {"NAME":"Shelly 2","GPIO":[0,135,0,136,21,22,0,0,9,0,10,137,0],"FLAG":0,"BASE":47} +Shelly 2.5 {"NAME":"Shelly 2.5","GPIO":[56,255,17,255,21,83,0,0,6,82,5,22,156],"FLAG":2,"BASE":18} +Sinilink XY-WF36V DC6V-36V Switch Module {"NAME":"Sinilink XY-WF5V","GPIO":[0,0,0,0,21,255,0,0,17,52,0,0,255],"FLAG":0,"BASE":18} +Sinilink XY-WFMS MOS Switch Module {"NAME":"Sinilink MOS","GPIO":[0,0,0,0,21,255,0,0,17,52,0,0,255],"FLAG":0,"BASE":18} +Sinilink XY-WFUSB USB Switch {"NAME":"XY-WFUSB","GPIO":[255,255,0,255,17,21,0,0,0,0,56,0,157],"FLAG":0,"BASE":18} +Smart Home SS-8839-01 {"NAME":"SS-8839-01","GPIO":[0,255,0,255,21,0,0,0,17,57,0,56,0],"FLAG":0,"BASE":18} +Sonoff 4CH (R2) {"NAME":"Sonoff 4CH","GPIO":[17,255,255,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":7} +Sonoff 4CH Pro (R2) {"NAME":"Sonoff 4CH Pro","GPIO":[17,255,255,255,23,22,18,19,21,56,20,24,0],"FLAG":0,"BASE":23} +Sonoff 5V Inching/Selflock Module RE5V1C {"NAME":"Sonoff RE5V1C","GPIO":[17,255,255,255,255,255,0,0,21,56,0,0,0],"FLAG":0,"BASE":18} +Sonoff Basic {"NAME":"Sonoff Basic","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1} +Sonoff Basic R3 {"NAME":"Basic R3","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,255],"FLAG":0,"BASE":1} +Sonoff Dual {"NAME":"Sonoff Dual","GPIO":[0,148,0,149,255,0,0,0,0,56,255,0,0],"FLAG":0,"BASE":5} +Sonoff Dual R2 {"NAME":"Sonoff Dual R2","GPIO":[255,255,0,255,0,22,255,17,21,56,0,0,0],"FLAG":0,"BASE":39} +Sonoff Mini {"NAME":"Sonoff Mini","GPIO":[17,0,0,0,9,0,0,0,21,56,0,0,255],"FLAG":0,"BASE":1} +Sonoff Pow {"NAME":"Sonoff Pow","GPIO":[17,0,0,0,0,130,0,0,21,132,133,52,0],"FLAG":0,"BASE":6} +Sonoff Pow R2 {"NAME":"Sonoff Pow R2","GPIO":[17,145,0,146,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":43} +Sonoff RF {"NAME":"Sonoff RF","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":2} +Sonoff SV {"NAME":"Sonoff SV","GPIO":[17,255,0,255,255,255,0,0,21,56,255,0,0],"FLAG":1,"BASE":3} +Sonoff TH10/TH16 {"NAME":"Sonoff TH","GPIO":[17,255,0,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":4} +SS-8839-02 {"NAME":"SS-8839-02","GPIO":[0,255,0,255,56,0,0,0,21,0,17,0,0],"FLAG":0,"BASE":18} +SS311KWS RF Kinetic Switch and WiFi {"NAME":"SS311KWS","GPIO":[0,0,0,0,52,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +SW-R03 {"NAME":"SW-R03","GPIO":[0,0,0,0,0,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +WL-SW01_10 {"NAME":"WL-SW01_10","GPIO":[17,149,0,148,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Zemismart ERC309 Kinetic Switch {"NAME":"Kinetic Switch","GPIO":[255,255,255,255,255,255,0,0,255,108,255,107,255],"FLAG":0,"BASE":54} +``` + +## Sensor +``` +DP-WP001 PIR {"NAME":"TUYA PIR","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} +DS18B20 ESP01 Module Temperature {"NAME":"ESP01S ds18b20","GPIO":[255,255,4,255,255,255,0,0,255,255,255,255,255],"FLAG":15,"BASE":18} +Earykong TYMC-1 Door Window {"NAME":"TYMC-1","GPIO":[0,107,0,108,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54} +IOT4SH01DS Temperature {"NAME":"IOT4SH01DS","GPIO":[255,255,255,255,255,255,0,0,255,4,255,255,255],"FLAG":15,"BASE":18} +Mirabella Genio I002576 Motion {"NAME":"GenioPir","GPIO":[17,107,0,108,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":54} +Sonoff SC {"NAME":"Sonoff SC","GPIO":[17,148,255,149,0,0,0,0,0,56,0,0,0],"FLAG":0,"BASE":21} +Zemismart Door Window {"NAME":"Zemismart","GPIO":[255,107,255,108,255,255,0,0,255,255,255,255,255],"FLAG":0,"BASE":54} ``` ## Switch ``` -3A Smart Home HGZB-043 {"NAME":"3A Smart Home ","GPIO":[52,0,55,18,22,19,0,0,17,21,54,23,53],"FLAG":0,"BASE":18} -Deta 6912HA {"NAME":"DETA 2G Switch","GPIO":[0,0,0,0,157,0,0,0,91,21,22,0,90],"FLAG":0,"BASE":18} -DS-102 1 Gang {"NAME":"DS-102 1 Gang","GPIO":[57,0,0,17,0,0,0,0,0,21,56,0,0],"FLAG":1,"BASE":18} -DS-102 2 Gang {"NAME":"DS-102 2 Gang","GPIO":[56,58,0,17,22,18,0,0,0,21,57,255,0],"FLAG":0,"BASE":18} -DS-102 3 Gang {"NAME":"DS-102 3 Gang","GPIO":[158,58,0,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18} -Enjowi WF-SK301 {"NAME":"Tuya 3 Channel","GPIO":[0,0,0,0,23,18,0,0,17,21,19,22,157],"FLAG":0,"BASE":18} -Etekcity 3-way {"NAME":"Etekcity 3Way","GPIO":[255,255,0,255,23,29,0,0,82,22,10,0,0],"FLAG":0,"BASE":18} -EtekCity ESWL01 {"NAME":"EtekCityESWL01","GPIO":[255,255,255,255,52,53,255,255,255,21,122,255,255],"FLAG":1,"BASE":18} -Gosund KS-602S {"NAME":"Gosund KS-602S","GPIO":[17,56,0,0,0,0,0,0,0,0,21,0,158],"FLAG":0,"BASE":18} -Jinvoo SM-SW101-1 {"NAME":"SM-SW101-1","GPIO":[52,0,0,18,0,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} -Jinvoo SM-SW101-2 {"NAME":"SM-SW101-2","GPIO":[52,0,0,18,22,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} -Jinvoo SM-SW101-3 {"NAME":"Jinvoo Wall Sw","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} -Jinvoo SM-SW101-C Curtain {"NAME":"Jinvoo Curtain","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} -KMC 70008 {"NAME":"KMC 70008","GPIO":[17,255,255,0,0,255,255,255,0,56,21,255,255],"FLAG":0,"BASE":18} -KOAANW DS302 {"NAME":"DS302","GPIO":[0,0,0,19,23,18,0,0,17,21,0,22,52],"FLAG":1,"BASE":18} -KS-601 2-way {"NAME":"2way Switch","GPIO":[255,255,158,255,255,83,255,255,22,21,255,82,255],"FLAG":0,"BASE":18} -Kuled K36 {"NAME":"KULED-B","GPIO":[9,255,255,255,255,255,21,52,29,56,255,255,255],"FLAG":0,"BASE":18} -Kuled KS602S {"NAME":"KULED","GPIO":[9,255,255,255,255,255,255,255,21,56,255,255,255],"FLAG":0,"BASE":18} -KYGNE CD-301 {"NAME":"KYGNE Touch","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":10} -Lonsonho SK3-01 {"NAME":"Tuya 1 Channel","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,52],"FLAG":0,"BASE":18} -Lonsonho SK3-02 {"NAME":"Tuya 2 Channel","GPIO":[0,0,0,0,22,0,0,0,17,21,18,0,52],"FLAG":0,"BASE":18} -Luminea LHC-101.on {"NAME":"LHC-101.on","GPIO":[157,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} -Luminea LHC-102.on {"NAME":"LHC-102.on","GPIO":[157,0,53,0,0,18,0,0,17,21,0,22,52],"FLAG":0,"BASE":18} -LX-WIFI-00M 4 Gang {"NAME":"LX-WIFI-00M","GPIO":[17,25,255,255,23,22,18,19,21,0,20,24,0],"FLAG":0,"BASE":7} -LYASI B07PYMG3WD {"NAME":"LYASI Touch Sw","GPIO":[0,0,0,0,56,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -Martin Jerry 15A {"NAME":"MJ Switch","GPIO":[255,255,255,255,57,56,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -Martin Jerry 3 Way {"NAME":"MJ 3Way Switch","GPIO":[255,255,255,255,52,53,0,0,21,9,157,255,0],"FLAG":0,"BASE":18} -Merkury MI-WW107-199W {"NAME":"MI-WW107-199W","GPIO":[52,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} -Minitiger 1 Gang {"NAME":"minitiger 1 Gang","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} -Minitiger 2 Gang {"NAME":"minitiger 2 Gang","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":28} -Moes 1 Gang Touch {"NAME":"B07C8FJY3G","GPIO":[54,0,0,17,21,0,0,0,0,0,52,0,55],"FLAG":0,"BASE":18} -Moes 2 Gang Touch {"NAME":"B07BLZFQZZ ","GPIO":[52,0,53,0,0,18,0,0,17,21,0,22,54],"FLAG":0,"BASE":18} -Moes 2 Gang Touch {"NAME":"Tuya Moes 2 Ch","GPIO":[25,255,24,0,0,18,0,0,17,21,0,22,23],"FLAG":0,"BASE":18} -Moes 3 Gang Touch {"NAME":"Tuya Moes 3 Ch","GPIO":[27,255,26,18,22,19,0,0,17,21,25,23,24],"FLAG":0,"BASE":18} -Moes 3-Way {"NAME":"Moes 3-Way","GPIO":[255,255,255,255,21,57,0,0,30,10,9,255,255],"FLAG":0,"BASE":18} -Moko {"NAME":"Moko Switch","GPIO":[0,0,0,17,21,134,0,0,0,0,0,0,0],"FLAG":0,"BASE":59} -Nexete DS-123 {"NAME":"DS-123","GPIO":[157,57,255,17,21,18,0,0,255,22,56,255,255],"FLAG":0,"BASE":18} -Sainko 1-Way {"NAME":"SAINKO 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} -SANA {"NAME":"SW02-03","GPIO":[56,255,255,19,23,18,255,255,17,21,255,22,255],"FLAG":0,"BASE":18} -SANA SASW-03 {"NAME":"SANA SASW-03","GPIO":[54,0,0,19,23,18,0,0,17,21,0,22,0],"FLAG":0,"BASE":18} -Sesoo SK3-04 {"NAME":"Tuya 4 Channel","GPIO":[52,255,255,19,23,17,0,0,20,24,22,21,18],"FLAG":0,"BASE":18} -Sesoo WIFI-US-SK3-04 {"NAME":"WIFI-US-SK3-04","GPIO":[255,255,255,19,23,17,0,0,20,24,22,21,18],"FLAG":0,"BASE":18} -SmartPlex 3 Gang {"NAME":"Tuya 3 Channel","GPIO":[255,255,255,255,21,18,0,0,19,23,17,22,255],"FLAG":0,"BASE":18} -Sonoff T1 EU 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} -Sonoff T1 EU 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} -Sonoff T1 UK 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} -Sonoff T1 UK 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} -Sonoff T1 UK 3 Gang {"NAME":"Sonoff T1 3CH","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} -Sonoff T1 US 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} -Sonoff T1 US 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} -Sonoff T1 US 3 Gang {"NAME":"Sonoff T1 3CH","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} -Sonoff Touch EU {"NAME":"Sonoff Touch","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":10} -Sonoff Touch US {"NAME":"Sonoff Touch","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":10} -SS118-01K1 {"NAME":"SS118-01K1","GPIO":[255,255,255,17,21,255,255,255,255,255,56,255,255],"FLAG":0,"BASE":18} -STITCH by Monoprice 35557 {"NAME":"Tuya WF15S ","GPIO":[255,255,0,0,255,255,0,0,255,108,255,107,0],"FLAG":0,"BASE":54} -Teepao Smart-Rollladen-Schalter {"NAME":"Teepao","GPIO":[158,58,23,18,22,19,0,0,56,21,57,0,17],"FLAG":0,"BASE":18} -Tonbux AMZ180648-2 {"NAME":"Tonbux","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1} -Touch 2 Gang {"NAME":"tuya_2_gang","GPIO":[52,0,0,0,18,0,0,0,17,21,255,22,29],"FLAG":0,"BASE":18} -TreatLife SS01S {"NAME":"TL SS01S Swtch","GPIO":[0,0,0,0,52,158,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} -WS-US-03 {"NAME":"WS-US-03","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} -Xenon SM-SW102-2 {"NAME":"SM SW102","GPIO":[255,255,255,18,22,255,255,255,17,21,255,255,255],"FLAG":0,"BASE":18} -Youngzuth SW02 2-way {"NAME":"SW02 2W","GPIO":[52,255,255,9,21,255,255,255,10,22,255,255,255],"FLAG":0,"BASE":18} -Zemismart KS-611 3 Gang {"NAME":"Zemismart 3 Ga","GPIO":[0,0,56,0,19,18,0,0,22,21,23,0,17],"FLAG":0,"BASE":18} -Zemismart KS-811 1 gang {"NAME":"KS-811 Single","GPIO":[17,255,255,255,255,255,255,255,21,56,255,255,255],"FLAG":0,"BASE":18} -Zemismart KS-811 2 Gang {"NAME":"KS-811 Dual","GPIO":[255,255,52,255,255,18,255,255,22,21,255,255,17],"FLAG":0,"BASE":18} -Zemismart KS-811 3 Gang {"NAME":"KS-811 Triple","GPIO":[255,255,56,255,19,18,255,255,22,21,23,255,17],"FLAG":0,"BASE":18} -Zemismart WF-BS01 {"NAME":"WF-BS01","GPIO":[53,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} -Zemismart ZM-L02E {"NAME":"ZSmart ZM-L02E","GPIO":[255,255,255,255,255,17,255,255,18,21,22,255,255],"FLAG":0,"BASE":18} +3A Smart Home HGZB-043 {"NAME":"3A Smart Home ","GPIO":[52,0,55,18,22,19,0,0,17,21,54,23,53],"FLAG":0,"BASE":18} +Aoycocr SW1 {"NAME":"Aoycocr SW1","GPIO":[158,255,57,255,255,255,255,255,56,17,255,21,255],"FLAG":15,"BASE":18} +Bardi Smart Wallswitch 2 {"NAME":"BARDI 2 Gang","GPIO":[56,0,157,18,22,0,0,0,52,21,57,0,17],"FLAG":0,"BASE":18} +Bardi Smart Wallswitch 3 {"NAME":"BARDI 3 Gang","GPIO":[56,57,157,19,23,18,0,0,52,21,58,22,17],"FLAG":0,"BASE":18} +BlitzWolf BW-SS3 2 Gang {"NAME":"BW-SS3-2G-EU","GPIO":[157,255,255,255,22,18,255,255,17,21,255,255,255],"FLAG":15,"BASE":18} +BlitzWolf BW-SS3 3 Gang {"NAME":"BlitzWolf SS3","GPIO":[158,0,0,10,22,11,0,0,9,21,0,23,0],"FLAG":0,"BASE":18} +CD303 3 Gang Touch {"NAME":"Touch Switch 3","GPIO":[54,57,255,19,23,18,255,255,17,21,255,22,52],"FLAG":15,"BASE":18} +Deta 6911HA {"NAME":"Deta 1G Switch","GPIO":[0,0,0,0,157,0,0,0,0,21,0,0,90],"FLAG":0,"BASE":18} +Deta 6912HA {"NAME":"DETA 2G Switch","GPIO":[0,0,0,0,157,0,0,0,91,21,22,0,90],"FLAG":0,"BASE":18} +Digoo DG-S811 3 Gang {"NAME":"DIGOO Switch","GPIO":[0,0,0,0,19,18,0,0,22,21,23,0,17],"FLAG":0,"BASE":18} +DS-102 1 Gang {"NAME":"DS-102 1 Gang","GPIO":[57,0,0,17,0,0,0,0,0,21,56,0,0],"FLAG":1,"BASE":18} +DS-102 2 Gang {"NAME":"DS-102 2 Gang","GPIO":[158,57,0,17,22,18,0,0,0,21,56,255,0],"FLAG":0,"BASE":18} +DS-102 3 Gang {"NAME":"DS-102 3 Gang","GPIO":[158,58,0,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18} +Eachen CD303 3 Gang {"NAME":"ID Components","GPIO":[157,53,0,11,21,10,0,0,9,22,54,23,52],"FLAG":15,"BASE":18} +Eachen SWT-2Gang {"NAME":"ID Components","GPIO":[157,255,255,255,255,10,255,255,9,21,53,22,52],"FLAG":15,"BASE":18} +Enjowi WF-SK301 {"NAME":"Tuya 3 Channel","GPIO":[0,0,0,0,23,18,0,0,17,21,19,22,157],"FLAG":0,"BASE":18} +Etekcity ESWL01 {"NAME":"EtekCityESWL01","GPIO":[0,255,0,255,52,53,0,0,0,21,122,0,0],"FLAG":1,"BASE":18} +Etekcity ESWL03 3-way {"NAME":"Etekcity 3Way","GPIO":[0,0,0,0,23,29,0,0,82,22,10,0,0],"FLAG":0,"BASE":18} +Eva Logik WF30 3-Way {"NAME":"WF30 Switch","GPIO":[0,0,0,0,18,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Geeni TAP 3-Way {"NAME":"Geeni 3-Way","GPIO":[157,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} +Girier JRSWR-SEU01 1 Gang {"NAME":"W601","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,157],"FLAG":15,"BASE":18} +Girier JRSWR-SEU01 2 Gang {"NAME":"W602","GPIO":[0,0,0,0,22,0,0,0,17,21,18,0,157],"FLAG":15,"BASE":18} +Girier JRSWR-US01 No Neutral {"NAME":"Tuya 1 Channel","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,157],"FLAG":0,"BASE":18} +GoKlug Glass Touch 1 Gang {"NAME":"GoKlug 1x","GPIO":[56,57,0,0,0,9,0,0,0,0,0,21,0],"FLAG":0,"BASE":18} +Gosund KS-602S {"NAME":"Gosund KS-602S","GPIO":[17,56,0,0,0,0,0,0,0,0,21,0,158],"FLAG":0,"BASE":18} +Gosund SW1 {"NAME":"Gosund SW1","GPIO":[17,56,0,0,0,0,0,0,0,0,21,0,158],"FLAG":0,"BASE":18} +Gosund SW1 v2 {"NAME":"Gosund SW1","GPIO":[17,0,56,0,0,0,0,0,0,0,21,0,57],"FLAG":0,"BASE":18} +HBN Wall-Mounted Timer {"NAME":"HBN Time Switc","GPIO":[0,0,0,0,54,57,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Jinvoo SM-SW101-1 {"NAME":"SM-SW101-1","GPIO":[52,0,0,18,0,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} +Jinvoo SM-SW101-2 {"NAME":"SM-SW101-2","GPIO":[52,0,0,18,22,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} +Jinvoo SM-SW101-3 {"NAME":"Jinvoo Wall Sw","GPIO":[52,0,0,18,22,19,0,0,17,21,0,23,0],"FLAG":1,"BASE":18} +KMC 70008 {"NAME":"KMC 70008","GPIO":[17,255,255,0,0,255,0,0,0,56,21,255,255],"FLAG":0,"BASE":18} +Koaanw CD302-EU-1 {"NAME":"CD302-EU-1","GPIO":[0,0,0,0,157,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Koaanw CD302-EU-2 {"NAME":"CD302-EU-2","GPIO":[157,0,0,0,0,18,0,0,17,21,57,22,56],"FLAG":0,"BASE":18} +Koaanw CD302-EU-3 {"NAME":"CD302-EU-3","GPIO":[158,53,0,19,23,18,0,0,17,21,54,22,52],"FLAG":0,"BASE":18} +KS-601 2-way {"NAME":"2way Switch","GPIO":[255,255,158,255,255,83,0,0,22,21,255,82,255],"FLAG":0,"BASE":18} +KS-605 {"NAME":"KS-605","GPIO":[17,0,0,0,0,0,0,0,21,158,0,0,0],"FLAG":0,"BASE":18} +Kuled K36 {"NAME":"KULED-B","GPIO":[9,255,255,255,255,255,21,52,29,56,255,255,255],"FLAG":0,"BASE":18} +Kuled KS602S {"NAME":"KULED","GPIO":[17,255,255,255,255,255,0,0,21,56,255,255,255],"FLAG":0,"BASE":18} +Kygne CD-301 {"NAME":"KYGNE Touch","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":10} +Laghten SS02S {"NAME":"Laghten SS02S","GPIO":[0,0,0,0,52,57,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +LerLink X801A-L No Neutral {"NAME":"LerLink X801-L","GPIO":[0,0,0,0,17,0,0,0,21,56,0,0,0],"FLAG":15,"BASE":18} +Lerlink X802A 2 Gang {"NAME":"Lerlink X802A","GPIO":[0,0,0,18,17,0,0,0,21,23,22,0,0],"FLAG":15,"BASE":18} +LerLink X802A-L No Neutral {"NAME":"LerLink X802-L","GPIO":[0,0,0,18,17,0,0,0,21,158,22,0,0],"FLAG":15,"BASE":18} +Lightstory WT02S {"NAME":"WT02S","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":50} +Lonsonho SK3-01 {"NAME":"Tuya 1 Channel","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,52],"FLAG":0,"BASE":18} +Lonsonho SK3-02 {"NAME":"Tuya 2 Channel","GPIO":[0,0,0,0,22,0,0,0,17,21,18,0,52],"FLAG":0,"BASE":18} +Lonsonho SK3-03 {"NAME":"ID Components","GPIO":[0,0,0,0,21,18,0,0,19,23,17,22,157],"FLAG":0,"BASE":18} +LoraTap WH100W-US 20A {"NAME":"LoraTap Boiler","GPIO":[0,0,0,0,0,0,0,0,17,21,0,0,56],"FLAG":0,"BASE":18} +Luminea LHC-101.on {"NAME":"LHC-101.on","GPIO":[157,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} +Luminea LHC-102.on {"NAME":"LHC-102.on","GPIO":[157,0,53,0,0,18,0,0,17,21,0,22,52],"FLAG":0,"BASE":18} +LX-WIFI-00M 4 Gang {"NAME":"LX-WIFI-00M","GPIO":[17,25,255,255,23,22,18,19,21,0,20,24,0],"FLAG":0,"BASE":7} +Markevina KS-602S {"NAME":"Markevina KS-6","GPIO":[17,255,0,255,0,0,0,0,21,52,0,0,0],"FLAG":0,"BASE":18} +Martin Jerry MJ-S01 15A {"NAME":"MJ Switch","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Martin Jerry ST01 3 Way {"NAME":"MJ 3Way Switch","GPIO":[255,255,255,255,52,53,0,0,21,9,157,255,0],"FLAG":0,"BASE":18} +Merkury MI-WW107-199W {"NAME":"MI-WW107-199W","GPIO":[52,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} +Micmi K38 {"NAME":"KS-605","GPIO":[17,0,0,0,0,0,0,0,21,158,0,0,0],"FLAG":0,"BASE":18} +Minitiger 1 Gang {"NAME":"minitiger 1 Gang","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Minitiger 1 Gang v2 {"NAME":"MiniTiger1Band","GPIO":[0,56,0,0,0,17,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Minitiger 2 Gang {"NAME":"minitiger 2 Gang","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Minitiger 2 Gang v2 {"NAME":"Minitiger2Band","GPIO":[0,0,0,17,18,0,0,0,0,21,22,0,0],"FLAG":0,"BASE":18} +Moes BS-US-W Boiler {"NAME":"BS-US-W","GPIO":[54,0,0,17,21,0,0,0,0,0,52,0,55],"FLAG":0,"BASE":18} +Moes SS01-1 3-Way {"NAME":"Moes 3-Way","GPIO":[255,255,255,255,21,57,0,0,30,10,9,255,255],"FLAG":0,"BASE":18} +Moes SS01S-1 {"NAME":"Moes Switch","GPIO":[255,255,255,255,56,0,0,0,21,17,255,255,255],"FLAG":0,"BASE":18} +Moes SS86-01 AI {"NAME":"SS86-AI 1 Gang","GPIO":[157,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} +Moes WS-EU1-LB 1 Gang No Neutral {"NAME":"Moes WS-EU1-LB","GPIO":[0,0,0,0,0,17,0,0,0,0,0,21,157],"FLAG":0,"BASE":18} +Moes WS-EU2-LW 2 Gang No Neutral {"NAME":"Tuya 2 Channel","GPIO":[0,0,0,0,22,0,0,0,17,21,18,0,157],"FLAG":0,"BASE":18} +Moes WS-EU3-LW 3 Gang No Neutral {"NAME":"Tuya 3 Channel","GPIO":[0,0,0,0,21,19,0,0,18,22,17,23,157],"FLAG":0,"BASE":18} +Moes WS-EUY3-W {"NAME":"WS-EUY3-W","GPIO":[157,0,58,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18} +Moes WS-US1-W 1 Gang {"NAME":"WS-US1-W","GPIO":[54,0,0,17,21,0,0,0,0,0,52,0,55],"FLAG":0,"BASE":18} +Moes WS-US2-W 2 Gang {"NAME":"WS-US2-W ","GPIO":[52,0,53,0,0,18,0,0,17,21,0,22,54],"FLAG":0,"BASE":18} +Moes WS-US3-W 3 Gang {"NAME":"Tuya Moes 3 Ch","GPIO":[27,255,26,18,22,19,0,0,17,21,25,23,24],"FLAG":0,"BASE":18} +Moes WT02S {"NAME":"Moes WT02S","GPIO":[0,0,0,0,56,158,0,0,21,9,0,0,0],"FLAG":15,"BASE":18} +MoKo Smart Life {"NAME":"Moko Switch","GPIO":[0,0,0,17,21,134,0,0,0,0,0,0,0],"FLAG":0,"BASE":59} +NaamaSmart KS602 {"NAME":"KS-602","GPIO":[17,0,0,0,0,0,0,0,21,158,0,0,0],"FLAG":0,"BASE":18} +Nexete DS-123 {"NAME":"DS-123","GPIO":[157,57,255,17,21,18,0,0,255,22,56,255,255],"FLAG":0,"BASE":18} +Nexete DS-123 Single {"NAME":"DS-123","GPIO":[157,0,255,18,0,17,0,0,255,21,56,255,255],"FLAG":0,"BASE":18} +Sainko 1-Way {"NAME":"SAINKO 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +SANA SASW-03 {"NAME":"SANA SASW-03","GPIO":[54,0,0,19,23,18,0,0,17,21,0,22,0],"FLAG":0,"BASE":18} +SANA SW02-02 {"NAME":"SW02-02","GPIO":[31,255,255,18,22,0,0,0,17,21,255,0,255],"FLAG":0,"BASE":18} +SANA SW02-03 {"NAME":"SW02-03","GPIO":[56,255,255,19,23,18,0,0,17,21,255,22,255],"FLAG":0,"BASE":18} +SavEnergy 3 Gang {"NAME":"SavEnergy 3-sw","GPIO":[55,157,54,18,23,19,255,255,17,22,53,21,52],"FLAG":15,"BASE":18} +Semicom LM-HP/GEVD-W {"NAME":"WaterHeater","GPIO":[158,56,0,0,0,17,0,0,0,0,0,21,0],"FLAG":0,"BASE":18} +Sesoo WIFI-EU-SK3-01 {"NAME":"Sensoo SK3-01","GPIO":[255,255,57,255,255,17,0,0,255,255,255,21,52],"FLAG":0,"BASE":18} +Sesoo WIFI-EU-SK3-02 {"NAME":"Sesoo SK3-02","GPIO":[0,0,57,0,22,0,0,0,17,21,18,0,52],"FLAG":0,"BASE":18} +Sesoo WIFI-US-SK3-04 {"NAME":"Tuya 4 Channel","GPIO":[52,255,255,19,23,17,0,0,20,24,22,21,18],"FLAG":0,"BASE":18} +Smartlife Opard CD302 {"NAME":"CD302","GPIO":[0,0,0,0,52,57,0,0,29,17,0,0,0],"FLAG":0,"BASE":18} +SmartPlex 3 Gang {"NAME":"Tuya 3 Channel","GPIO":[255,255,255,255,21,18,0,0,19,23,17,22,255],"FLAG":0,"BASE":18} +Sonoff T1 EU 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Sonoff T1 EU 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +Sonoff T1 UK 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Sonoff T1 UK 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +Sonoff T1 UK 3 Gang {"NAME":"Sonoff T1 3CH","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} +Sonoff T1 US 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Sonoff T1 US 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[17,255,255,255,0,22,18,0,21,56,0,0,0],"FLAG":0,"BASE":29} +Sonoff T1 US 3 Gang {"NAME":"Sonoff T1 3CH","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} +Sonoff Touch EU {"NAME":"Sonoff Touch","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":10} +Sonoff Touch US {"NAME":"Sonoff Touch","GPIO":[17,255,0,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":10} +Sonoff TX T3 3 Gang {"NAME":"TX T3EU3C","GPIO":[17,255,0,255,23,22,18,19,21,158,0,0,0],"FLAG":0,"BASE":30} +SS118-01K1 {"NAME":"SS118-01K1","GPIO":[255,255,255,17,21,255,0,0,255,255,56,255,255],"FLAG":0,"BASE":18} +SS86-AI 3-Gang {"NAME":"SS86-AI 3 Gang","GPIO":[157,0,58,18,22,19,0,0,17,21,57,23,56],"FLAG":0,"BASE":18} +SSMS118-01A1 Scene Light Smart {"NAME":"RGB Switch","GPIO":[30,0,32,10,39,38,0,0,31,9,37,21,0],"FLAG":0,"BASE":18} +STITCH by Monoprice 35557 {"NAME":"Tuya WF15S ","GPIO":[255,255,0,0,255,255,0,0,255,108,255,107,0],"FLAG":0,"BASE":54} +Teekar 10 Way 1 Gang {"NAME":"Teekar 10way","GPIO":[9,10,11,20,13,14,0,0,15,16,0,0,0],"FLAG":0,"BASE":18} +Teekar Wi-Fi Light 1 Gang {"NAME":"TeeKar Touch","GPIO":[0,0,255,0,255,21,0,0,0,255,17,0,255],"FLAG":0,"BASE":18} +Teepao Smart-Rollladen-Schalter {"NAME":"Teepao","GPIO":[158,58,23,18,22,19,0,0,56,21,57,0,17],"FLAG":0,"BASE":18} +Tonbux AMZ180648-2 {"NAME":"Tonbux","GPIO":[17,255,255,255,255,0,0,0,21,56,255,0,0],"FLAG":0,"BASE":1} +Touch 2 Gang {"NAME":"tuya_2_gang","GPIO":[52,0,0,0,18,0,0,0,17,21,255,22,29],"FLAG":0,"BASE":18} +TreatLife SS01S {"NAME":"TL SS01S Swtch","GPIO":[0,0,0,0,52,158,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +TreatLife SS02 3-Way {"NAME":"TreatLife 3Way","GPIO":[0,0,0,0,53,29,0,0,30,18,9,0,0],"FLAG":0,"BASE":18} +TreatLife SS02S {"NAME":"Treatlife SS02","GPIO":[0,0,0,0,53,0,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Vaticas 1 {"NAME":"Vaticas","GPIO":[0,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} +WiFi Smart Switch 2 Gang {"NAME":"Kingart N2","GPIO":[17,255,0,255,0,22,18,0,21,0,0,0,0],"FLAG":15,"BASE":18} +WiFi Smart Switch 3 Gang {"NAME":"KingArt-3CH","GPIO":[17,255,0,255,23,22,18,19,21,52,0,0,0],"FLAG":15,"BASE":18} +WS-US-03 {"NAME":"WS-US-03","GPIO":[17,255,255,255,23,22,18,19,21,56,0,0,0],"FLAG":0,"BASE":30} +Xenon SM-SW102U 2 Gang {"NAME":"SM-SW102U-2","GPIO":[52,0,0,18,22,0,0,0,17,21,0,0,0],"FLAG":1,"BASE":18} +Xenon SM-SW202 {"NAME":"SM-SW202","GPIO":[0,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} +Yapmor 1-gang {"NAME":"YAPMOR 1CH","GPIO":[17,255,255,255,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":28} +Youngzuth 3in1 {"NAME":"SW02 3W","GPIO":[52,0,255,19,23,18,0,0,17,21,255,22,255],"FLAG":0,"BASE":18} +Youngzuth SW02 2-way {"NAME":"SW02 2W","GPIO":[52,255,255,9,21,255,0,0,10,22,255,255,255],"FLAG":0,"BASE":18} +Zemismart KS-611 3 Gang {"NAME":"Zemismart 3 Ga","GPIO":[0,0,56,0,19,18,0,0,22,21,23,0,17],"FLAG":0,"BASE":18} +Zemismart KS-811 1 Gang {"NAME":"KS-811 Single","GPIO":[17,0,0,0,0,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":18} +Zemismart KS-811 2 Gang {"NAME":"KS-811 Dual","GPIO":[0,0,52,0,0,18,0,0,22,21,0,0,17],"FLAG":0,"BASE":18} +Zemismart KS-811 3 Gang {"NAME":"KS-811 Triple","GPIO":[0,0,56,0,19,18,0,0,22,21,23,0,17],"FLAG":0,"BASE":18} +ZemiSmart SS118-01K2 {"NAME":"SS118-01K2","GPIO":[0,0,0,17,21,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":18} +Zemismart WF-BS01 {"NAME":"WF-BS01","GPIO":[53,0,0,17,21,0,0,0,0,0,52,0,0],"FLAG":0,"BASE":18} +Zemismart ZM-L01E {"NAME":"ZSmart ZM-L01E","GPIO":[255,255,255,255,255,255,0,0,255,21,255,255,17],"FLAG":0,"BASE":18} +Zemismart ZM-L02E {"NAME":"ZSmart ZM-L02E","GPIO":[255,255,255,255,255,17,0,0,18,21,22,255,255],"FLAG":0,"BASE":18} +Zemismart ZM-L03E {"NAME":"ZSmart ZM-L03E","GPIO":[52,53,0,0,23,17,0,0,19,21,22,0,18],"FLAG":0,"BASE":18} ``` ## Valve ``` -Hoenyzy DN20 3/4 {"NAME":"Unbranded TYWE3S DN20 WIFI Valve","GPIO":[0,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} -Jinvoo SM-PW713 {"NAME":"Jinvoo Valve","GPIO":[0,0,0,0,21,52,0,0,17,53,0,0,0],"FLAG":1,"BASE":18} -TopKitchen Irrigation Timer {"NAME":"HoseController","GPIO":[255,255,255,255,255,255,255,255,255,255,255,21,22],"FLAG":1,"BASE":18} +Garden Water Timer BQ05 {"NAME":"BQ05","GPIO":[255,255,255,255,255,255,0,0,255,255,255,21,22],"FLAG":1,"BASE":18} +Hoenyzy DN20 3/4 {"NAME":"DN20 Valve","GPIO":[0,0,0,0,0,0,0,0,17,21,0,0,0],"FLAG":0,"BASE":18} +Jinvoo SM-AW713 {"NAME":"Jinvoo Valve","GPIO":[0,0,0,0,0,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +Jinvoo SM-AW713 v2 {"NAME":"Jinvoo Valve v2","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":1} +Jinvoo SM-PW713 {"NAME":"Jinvoo Valve","GPIO":[0,0,0,0,21,52,0,0,17,53,0,0,0],"FLAG":1,"BASE":18} ``` ## Wall Outlet ``` -Bestten LO-2-W2 {"NAME":"BESTTEN LO-2-W","GPIO":[17,0,0,0,57,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} -Charging Essentials WiFi Smart {"NAME":"CESmart-Wall","GPIO":[255,255,255,255,255,17,255,255,21,255,255,255,255],"FLAG":0,"BASE":18} -Kesen KS-604 {"NAME":"KS-604","GPIO":[255,255,52,255,255,18,255,255,22,21,255,255,17],"FLAG":0,"BASE":18} -Kesen KS-604S {"NAME":"KS-604S","GPIO":[255,255,31,255,255,18,255,255,22,21,255,255,17],"FLAG":1,"BASE":18} -MakeGood MG-AUWF01 {"NAME":"MG-AUWF01","GPIO":[56,10,157,59,134,132,255,255,131,22,57,21,9],"FLAG":0,"BASE":18} -MoesHouse Smart Socket {"NAME":"Smart Socket","GPIO":[255,255,255,255,52,53,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} -Smanergy KA10 {"NAME":"KA10","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} -Sonoff S55 {"NAME":"Sonoff S55","GPIO":[17,255,0,255,255,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} -Topgreener TGWF15RM {"NAME":"TGWF15RM","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} -Vigica VGSPK00815 {"NAME":"VIGICA outlet","GPIO":[17,255,255,255,255,22,18,255,21,255,255,255,255],"FLAG":1,"BASE":18} -WWK-UN-W Glass Panel {"NAME":"tuya wall sock","GPIO":[255,255,255,255,52,53,255,255,21,17,255,255,255],"FLAG":0,"BASE":18} +Bestten LO-2-W v2 {"NAME":"BESTTEN LO-2-W","GPIO":[0,0,0,0,158,17,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Bestten LO-2-W2 {"NAME":"BESTTEN LO-2-W","GPIO":[17,0,0,0,57,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +BlitzWolf BW-SHP8 {"NAME":"SHP8","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} +BSEED Smart Socket / WIFI {"NAME":"BSEED Socket","GPIO":[0,0,0,0,157,52,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +CE Smart Home LA-2-W3 {"NAME":"CE Smart Wall","GPIO":[255,255,255,255,157,17,0,0,21,255,255,255,255],"FLAG":15,"BASE":18} +CE Smart Home LQ-2-W3 {"NAME":"CE LQ-2-W3","GPIO":[255,255,255,255,255,17,255,255,21,255,255,255,255],"FLAG":15,"BASE":18} +CE Smart Home LQ-2-W3 {"NAME":"LITESUN","GPIO":[0,0,0,0,157,17,0,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Deta 6922HA {"NAME":"DETA 2G GPO","GPIO":[0,0,0,17,157,0,0,0,91,21,22,0,90],"FLAG":0,"BASE":18} +Ener-J 13A Twin Wall Sockets with USB {"NAME":"Ener-J 2-Gang ","GPIO":[17,0,0,0,0,21,18,0,22,56,0,0,0],"FLAG":0,"BASE":18} +Kapok T16 {"NAME":"tiltech-t16","GPIO":[0,56,0,17,82,0,0,0,21,22,0,0,0],"FLAG":0,"BASE":18} +Kesen KS-604 {"NAME":"KS-604","GPIO":[255,255,52,255,255,18,0,0,22,21,255,255,17],"FLAG":0,"BASE":18} +Kesen KS-604S {"NAME":"KS-604S","GPIO":[255,255,31,255,255,18,0,0,22,21,255,255,17],"FLAG":1,"BASE":18} +Keygma KS-15TW {"NAME":"Keygma KS-15T","GPIO":[0,0,0,0,0,56,0,0,21,9,0,0,0],"FLAG":0,"BASE":18} +KS-621 {"NAME":"KS-621","GPIO":[17,0,0,0,133,132,0,0,130,52,0,21,91],"FLAG":15,"BASE":18} +Makegood MG-AUWF01 {"NAME":"MG-AUWF01","GPIO":[56,10,157,59,134,132,0,0,131,22,57,21,9],"FLAG":0,"BASE":18} +Makegood MG-UKWSG01 {"NAME":"Aseer 2-Gang","GPIO":[57,9,157,59,134,132,0,0,131,21,56,22,10],"FLAG":0,"BASE":18} +Makegood MG-UKWSW/B {"NAME":"Aseer 1-Gang","GPIO":[56,0,157,57,134,132,0,0,131,0,0,21,9],"FLAG":0,"BASE":18} +Moes WWK Glass Panel {"NAME":"Smart Socket","GPIO":[0,0,0,0,52,53,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +PS-1607 {"NAME":"PS-1607","GPIO":[17,0,0,0,0,22,18,0,21,0,0,0,0],"FLAG":0,"BASE":18} +Smanergy KA10 {"NAME":"KA10","GPIO":[0,56,0,17,134,132,0,0,131,53,21,0,0],"FLAG":0,"BASE":64} +Sonoff IW100 {"NAME":"Sonoff IW100","GPIO":[17,145,0,146,0,0,0,0,21,157,0,0,0],"FLAG":0,"BASE":41} +Sonoff S55 {"NAME":"Sonoff S55","GPIO":[17,255,0,255,255,0,0,0,21,56,0,0,0],"FLAG":0,"BASE":1} +Teckin RF-SR40-US {"NAME":"RF-SR40-US","GPIO":[0,0,0,0,57,56,0,0,21,17,0,0,0],"FLAG":0,"BASE":18} +TopGreener TGWF15RM {"NAME":"TGWF15RM","GPIO":[0,56,0,17,134,132,0,0,131,57,21,0,0],"FLAG":0,"BASE":55} +Vigica VGSPK00815 {"NAME":"VIGICA outlet","GPIO":[17,255,255,255,255,22,18,255,21,255,255,255,255],"FLAG":1,"BASE":18} ``` \ No newline at end of file diff --git a/arduino/version 2.6.1/boards.txt b/arduino/version 2.6.1/boards.txt deleted file mode 100644 index e0eab55a7..000000000 --- a/arduino/version 2.6.1/boards.txt +++ /dev/null @@ -1,7122 +0,0 @@ -# -# Do not create pull-requests for this file only, CI will not accept them. -# You *must* edit/modify/run boards.txt.py to regenerate boards.txt. -# All modified files after running with option "--allgen" must be included in the pull-request. -# - -menu.BoardModel=Model -menu.ESPModule=Module - -menu.UploadTool=Upload Using - -menu.led=Builtin Led -menu.baud=Upload Speed -menu.xtal=CPU Frequency -menu.CrystalFreq=Crystal Frequency -menu.eesz=Flash Size -menu.FlashMode=Flash Mode -menu.FlashFreq=Flash Frequency -menu.ResetMethod=Reset Method -menu.dbg=Debug port -menu.lvl=Debug Level -menu.ip=lwIP Variant -menu.vt=VTables -menu.exception=Exceptions -menu.wipe=Erase Flash -menu.sdk=Espressif FW -menu.ssl=SSL Support - -############################################################## -generic.name=Generic ESP8266 Module -generic.build.board=ESP8266_GENERIC -generic.upload.tool=esptool -generic.upload.maximum_data_size=81920 -generic.upload.wait_for_upload_port=true -generic.upload.erase_cmd= -generic.serial.disableDTR=true -generic.serial.disableRTS=true -generic.build.mcu=esp8266 -generic.build.core=esp8266 -generic.build.variant=generic -generic.build.spiffs_pagesize=256 -generic.build.debug_port= -generic.build.debug_level= - -generic.menu.UploadTool.esptool=Serial -generic.menu.UploadTool.esptool.upload.tool=esptool -generic.menu.UploadTool.esptool.upload.verbose=-vv -generic.menu.UploadTool.espupload=OTA_upload -generic.menu.UploadTool.espupload.upload.tool=espupload - -generic.menu.xtal.80=80 MHz -generic.menu.xtal.80.build.f_cpu=80000000L -generic.menu.xtal.160=160 MHz -generic.menu.xtal.160.build.f_cpu=160000000L -generic.menu.vt.flash=Flash -generic.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -generic.menu.vt.heap=Heap -generic.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -generic.menu.vt.iram=IRAM -generic.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -generic.menu.exception.legacy=Legacy (new can return nullptr) -generic.menu.exception.legacy.build.exception_flags=-fno-exceptions -generic.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -generic.menu.exception.disabled=Disabled (new can abort) -generic.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -generic.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -generic.menu.exception.enabled=Enabled -generic.menu.exception.enabled.build.exception_flags=-fexceptions -generic.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -generic.menu.ssl.all=All SSL ciphers (most compatible) -generic.menu.ssl.all.build.sslflags= -generic.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -generic.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -generic.menu.ResetMethod.nodemcu=dtr (aka nodemcu) -generic.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset -generic.menu.ResetMethod.ck=no dtr (aka ck) -generic.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset -generic.menu.ResetMethod.nodtr_nosync=no dtr, no_sync -generic.menu.ResetMethod.nodtr_nosync.upload.resetmethod=--before no_reset_no_sync --after soft_reset -generic.menu.CrystalFreq.26=26 MHz -generic.menu.CrystalFreq.40=40 MHz -generic.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -generic.menu.FlashFreq.40=40MHz -generic.menu.FlashFreq.40.build.flash_freq=40 -generic.menu.FlashFreq.80=80MHz -generic.menu.FlashFreq.80.build.flash_freq=80 -generic.menu.FlashFreq.20=20MHz -generic.menu.FlashFreq.20.build.flash_freq=20 -generic.menu.FlashFreq.26=26MHz -generic.menu.FlashFreq.26.build.flash_freq=26 -generic.menu.FlashMode.dout=DOUT (compatible) -generic.menu.FlashMode.dout.build.flash_mode=dout -generic.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT -generic.menu.FlashMode.dio=DIO -generic.menu.FlashMode.dio.build.flash_mode=dio -generic.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO -generic.menu.FlashMode.qout=QOUT -generic.menu.FlashMode.qout.build.flash_mode=qout -generic.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT -generic.menu.FlashMode.qio=QIO (fast) -generic.menu.FlashMode.qio.build.flash_mode=qio -generic.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO -generic.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) -generic.menu.eesz.1M64.build.flash_size=1M -generic.menu.eesz.1M64.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -generic.menu.eesz.1M64.build.spiffs_pagesize=256 -generic.menu.eesz.1M64.upload.maximum_size=958448 -generic.menu.eesz.1M64.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M64.build.spiffs_start=0xEB000 -generic.menu.eesz.1M64.build.spiffs_end=0xFB000 -generic.menu.eesz.1M64.build.spiffs_blocksize=4096 -generic.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) -generic.menu.eesz.1M128.build.flash_size=1M -generic.menu.eesz.1M128.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -generic.menu.eesz.1M128.build.spiffs_pagesize=256 -generic.menu.eesz.1M128.upload.maximum_size=892912 -generic.menu.eesz.1M128.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M128.build.spiffs_start=0xDB000 -generic.menu.eesz.1M128.build.spiffs_end=0xFB000 -generic.menu.eesz.1M128.build.spiffs_blocksize=4096 -generic.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) -generic.menu.eesz.1M144.build.flash_size=1M -generic.menu.eesz.1M144.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -generic.menu.eesz.1M144.build.spiffs_pagesize=256 -generic.menu.eesz.1M144.upload.maximum_size=876528 -generic.menu.eesz.1M144.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M144.build.spiffs_start=0xD7000 -generic.menu.eesz.1M144.build.spiffs_end=0xFB000 -generic.menu.eesz.1M144.build.spiffs_blocksize=4096 -generic.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) -generic.menu.eesz.1M160.build.flash_size=1M -generic.menu.eesz.1M160.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -generic.menu.eesz.1M160.build.spiffs_pagesize=256 -generic.menu.eesz.1M160.upload.maximum_size=860144 -generic.menu.eesz.1M160.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M160.build.spiffs_start=0xD3000 -generic.menu.eesz.1M160.build.spiffs_end=0xFB000 -generic.menu.eesz.1M160.build.spiffs_blocksize=4096 -generic.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) -generic.menu.eesz.1M192.build.flash_size=1M -generic.menu.eesz.1M192.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -generic.menu.eesz.1M192.build.spiffs_pagesize=256 -generic.menu.eesz.1M192.upload.maximum_size=827376 -generic.menu.eesz.1M192.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M192.build.spiffs_start=0xCB000 -generic.menu.eesz.1M192.build.spiffs_end=0xFB000 -generic.menu.eesz.1M192.build.spiffs_blocksize=4096 -generic.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) -generic.menu.eesz.1M256.build.flash_size=1M -generic.menu.eesz.1M256.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -generic.menu.eesz.1M256.build.spiffs_pagesize=256 -generic.menu.eesz.1M256.upload.maximum_size=761840 -generic.menu.eesz.1M256.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M256.build.spiffs_start=0xBB000 -generic.menu.eesz.1M256.build.spiffs_end=0xFB000 -generic.menu.eesz.1M256.build.spiffs_blocksize=4096 -generic.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) -generic.menu.eesz.1M512.build.flash_size=1M -generic.menu.eesz.1M512.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -generic.menu.eesz.1M512.build.spiffs_pagesize=256 -generic.menu.eesz.1M512.upload.maximum_size=499696 -generic.menu.eesz.1M512.build.rfcal_addr=0xFC000 -generic.menu.eesz.1M512.build.spiffs_start=0x7B000 -generic.menu.eesz.1M512.build.spiffs_end=0xFB000 -generic.menu.eesz.1M512.build.spiffs_blocksize=8192 -generic.menu.eesz.1M=1MB (FS:none OTA:~502KB) -generic.menu.eesz.1M.build.flash_size=1M -generic.menu.eesz.1M.build.flash_size_bytes=0x100000 -generic.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -generic.menu.eesz.1M.build.spiffs_pagesize=256 -generic.menu.eesz.1M.upload.maximum_size=1023984 -generic.menu.eesz.1M.build.rfcal_addr=0xFC000 -generic.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) -generic.menu.eesz.2M64.build.flash_size=2M -generic.menu.eesz.2M64.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld -generic.menu.eesz.2M64.build.spiffs_pagesize=256 -generic.menu.eesz.2M64.upload.maximum_size=1044464 -generic.menu.eesz.2M64.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M64.build.spiffs_start=0x1F0000 -generic.menu.eesz.2M64.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M64.build.spiffs_blocksize=4096 -generic.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) -generic.menu.eesz.2M128.build.flash_size=2M -generic.menu.eesz.2M128.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -generic.menu.eesz.2M128.build.spiffs_pagesize=256 -generic.menu.eesz.2M128.upload.maximum_size=1044464 -generic.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M128.build.spiffs_start=0x1E0000 -generic.menu.eesz.2M128.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M128.build.spiffs_blocksize=4096 -generic.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) -generic.menu.eesz.2M256.build.flash_size=2M -generic.menu.eesz.2M256.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -generic.menu.eesz.2M256.build.spiffs_pagesize=256 -generic.menu.eesz.2M256.upload.maximum_size=1044464 -generic.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M256.build.spiffs_start=0x1C0000 -generic.menu.eesz.2M256.build.spiffs_end=0x1FB000 -generic.menu.eesz.2M256.build.spiffs_blocksize=4096 -generic.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) -generic.menu.eesz.2M512.build.flash_size=2M -generic.menu.eesz.2M512.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -generic.menu.eesz.2M512.build.spiffs_pagesize=256 -generic.menu.eesz.2M512.upload.maximum_size=1044464 -generic.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M512.build.spiffs_start=0x180000 -generic.menu.eesz.2M512.build.spiffs_end=0x1FA000 -generic.menu.eesz.2M512.build.spiffs_blocksize=8192 -generic.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) -generic.menu.eesz.2M1M.build.flash_size=2M -generic.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -generic.menu.eesz.2M1M.build.spiffs_pagesize=256 -generic.menu.eesz.2M1M.upload.maximum_size=1044464 -generic.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -generic.menu.eesz.2M1M.build.spiffs_start=0x100000 -generic.menu.eesz.2M1M.build.spiffs_end=0x1FA000 -generic.menu.eesz.2M1M.build.spiffs_blocksize=8192 -generic.menu.eesz.2M=2MB (FS:none OTA:~1019KB) -generic.menu.eesz.2M.build.flash_size=2M -generic.menu.eesz.2M.build.flash_size_bytes=0x200000 -generic.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -generic.menu.eesz.2M.build.spiffs_pagesize=256 -generic.menu.eesz.2M.upload.maximum_size=1044464 -generic.menu.eesz.2M.build.rfcal_addr=0x1FC000 -generic.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -generic.menu.eesz.4M2M.build.flash_size=4M -generic.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -generic.menu.eesz.4M2M.build.spiffs_pagesize=256 -generic.menu.eesz.4M2M.upload.maximum_size=1044464 -generic.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M2M.build.spiffs_start=0x200000 -generic.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -generic.menu.eesz.4M2M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -generic.menu.eesz.4M3M.build.flash_size=4M -generic.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -generic.menu.eesz.4M3M.build.spiffs_pagesize=256 -generic.menu.eesz.4M3M.upload.maximum_size=1044464 -generic.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M3M.build.spiffs_start=0x100000 -generic.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -generic.menu.eesz.4M3M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -generic.menu.eesz.4M1M.build.flash_size=4M -generic.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -generic.menu.eesz.4M1M.build.spiffs_pagesize=256 -generic.menu.eesz.4M1M.upload.maximum_size=1044464 -generic.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.4M1M.build.spiffs_start=0x300000 -generic.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -generic.menu.eesz.4M1M.build.spiffs_blocksize=8192 -generic.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -generic.menu.eesz.4M.build.flash_size=4M -generic.menu.eesz.4M.build.flash_size_bytes=0x400000 -generic.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -generic.menu.eesz.4M.build.spiffs_pagesize=256 -generic.menu.eesz.4M.upload.maximum_size=1044464 -generic.menu.eesz.4M.build.rfcal_addr=0x3FC000 -generic.menu.eesz.8M6M=8MB (FS:6MB OTA:~1019KB) -generic.menu.eesz.8M6M.build.flash_size=8M -generic.menu.eesz.8M6M.build.flash_size_bytes=0x800000 -generic.menu.eesz.8M6M.build.flash_ld=eagle.flash.8m6m.ld -generic.menu.eesz.8M6M.build.spiffs_pagesize=256 -generic.menu.eesz.8M6M.upload.maximum_size=1044464 -generic.menu.eesz.8M6M.build.rfcal_addr=0x7FC000 -generic.menu.eesz.8M6M.build.spiffs_start=0x200000 -generic.menu.eesz.8M6M.build.spiffs_end=0x7FA000 -generic.menu.eesz.8M6M.build.spiffs_blocksize=8192 -generic.menu.eesz.8M7M=8MB (FS:7MB OTA:~512KB) -generic.menu.eesz.8M7M.build.flash_size=8M -generic.menu.eesz.8M7M.build.flash_size_bytes=0x800000 -generic.menu.eesz.8M7M.build.flash_ld=eagle.flash.8m7m.ld -generic.menu.eesz.8M7M.build.spiffs_pagesize=256 -generic.menu.eesz.8M7M.upload.maximum_size=1044464 -generic.menu.eesz.8M7M.build.rfcal_addr=0x7FC000 -generic.menu.eesz.8M7M.build.spiffs_start=0x100000 -generic.menu.eesz.8M7M.build.spiffs_end=0x7FA000 -generic.menu.eesz.8M7M.build.spiffs_blocksize=8192 -generic.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB) -generic.menu.eesz.16M14M.build.flash_size=16M -generic.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 -generic.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld -generic.menu.eesz.16M14M.build.spiffs_pagesize=256 -generic.menu.eesz.16M14M.upload.maximum_size=1044464 -generic.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 -generic.menu.eesz.16M14M.build.spiffs_start=0x200000 -generic.menu.eesz.16M14M.build.spiffs_end=0xFFA000 -generic.menu.eesz.16M14M.build.spiffs_blocksize=8192 -generic.menu.eesz.16M15M=16MB (FS:15MB OTA:~512KB) -generic.menu.eesz.16M15M.build.flash_size=16M -generic.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 -generic.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld -generic.menu.eesz.16M15M.build.spiffs_pagesize=256 -generic.menu.eesz.16M15M.upload.maximum_size=1044464 -generic.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 -generic.menu.eesz.16M15M.build.spiffs_start=0x100000 -generic.menu.eesz.16M15M.build.spiffs_end=0xFFA000 -generic.menu.eesz.16M15M.build.spiffs_blocksize=8192 -generic.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) -generic.menu.eesz.512K32.build.flash_size=512K -generic.menu.eesz.512K32.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -generic.menu.eesz.512K32.build.spiffs_pagesize=256 -generic.menu.eesz.512K32.upload.maximum_size=466928 -generic.menu.eesz.512K32.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K32.build.spiffs_start=0x73000 -generic.menu.eesz.512K32.build.spiffs_end=0x7B000 -generic.menu.eesz.512K32.build.spiffs_blocksize=4096 -generic.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) -generic.menu.eesz.512K64.build.flash_size=512K -generic.menu.eesz.512K64.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -generic.menu.eesz.512K64.build.spiffs_pagesize=256 -generic.menu.eesz.512K64.upload.maximum_size=434160 -generic.menu.eesz.512K64.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K64.build.spiffs_start=0x6B000 -generic.menu.eesz.512K64.build.spiffs_end=0x7B000 -generic.menu.eesz.512K64.build.spiffs_blocksize=4096 -generic.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) -generic.menu.eesz.512K128.build.flash_size=512K -generic.menu.eesz.512K128.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -generic.menu.eesz.512K128.build.spiffs_pagesize=256 -generic.menu.eesz.512K128.upload.maximum_size=368624 -generic.menu.eesz.512K128.build.rfcal_addr=0x7C000 -generic.menu.eesz.512K128.build.spiffs_start=0x5B000 -generic.menu.eesz.512K128.build.spiffs_end=0x7B000 -generic.menu.eesz.512K128.build.spiffs_blocksize=4096 -generic.menu.eesz.512K=512KB (FS:none OTA:~246KB) -generic.menu.eesz.512K.build.flash_size=512K -generic.menu.eesz.512K.build.flash_size_bytes=0x80000 -generic.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -generic.menu.eesz.512K.build.spiffs_pagesize=256 -generic.menu.eesz.512K.upload.maximum_size=499696 -generic.menu.eesz.512K.build.rfcal_addr=0x7C000 -generic.menu.led.2=2 -generic.menu.led.2.build.led=-DLED_BUILTIN=2 -generic.menu.led.0=0 -generic.menu.led.0.build.led=-DLED_BUILTIN=0 -generic.menu.led.1=1 -generic.menu.led.1.build.led=-DLED_BUILTIN=1 -generic.menu.led.3=3 -generic.menu.led.3.build.led=-DLED_BUILTIN=3 -generic.menu.led.4=4 -generic.menu.led.4.build.led=-DLED_BUILTIN=4 -generic.menu.led.5=5 -generic.menu.led.5.build.led=-DLED_BUILTIN=5 -generic.menu.led.6=6 -generic.menu.led.6.build.led=-DLED_BUILTIN=6 -generic.menu.led.7=7 -generic.menu.led.7.build.led=-DLED_BUILTIN=7 -generic.menu.led.8=8 -generic.menu.led.8.build.led=-DLED_BUILTIN=8 -generic.menu.led.9=9 -generic.menu.led.9.build.led=-DLED_BUILTIN=9 -generic.menu.led.10=10 -generic.menu.led.10.build.led=-DLED_BUILTIN=10 -generic.menu.led.11=11 -generic.menu.led.11.build.led=-DLED_BUILTIN=11 -generic.menu.led.12=12 -generic.menu.led.12.build.led=-DLED_BUILTIN=12 -generic.menu.led.13=13 -generic.menu.led.13.build.led=-DLED_BUILTIN=13 -generic.menu.led.14=14 -generic.menu.led.14.build.led=-DLED_BUILTIN=14 -generic.menu.led.15=15 -generic.menu.led.15.build.led=-DLED_BUILTIN=15 -generic.menu.led.16=16 -generic.menu.led.16.build.led=-DLED_BUILTIN=16 -generic.menu.sdk.nonosdk_191024=nonos-sdk 2.2.1+111 (191024) -generic.menu.sdk.nonosdk_191024.build.sdk=NONOSDK22x_191024 -generic.menu.sdk.nonosdk_191105=nonos-sdk 2.2.1+113 (191105) -generic.menu.sdk.nonosdk_191105.build.sdk=NONOSDK22x_191105 -generic.menu.sdk.nonosdk_190703=nonos-sdk 2.2.1+100 (190703) -generic.menu.sdk.nonosdk_190703.build.sdk=NONOSDK22x_190703 -generic.menu.sdk.nonosdk221=nonos-sdk 2.2.1 (legacy) -generic.menu.sdk.nonosdk221.build.sdk=NONOSDK221 -generic.menu.sdk.nonosdk3v0=nonos-sdk pre-3 (180626 known issues) -generic.menu.sdk.nonosdk3v0.build.sdk=NONOSDK3V0 -generic.menu.ip.lm2f=v2 Lower Memory -generic.menu.ip.lm2f.build.lwip_include=lwip2/include -generic.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -generic.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -generic.menu.ip.hb2f=v2 Higher Bandwidth -generic.menu.ip.hb2f.build.lwip_include=lwip2/include -generic.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -generic.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -generic.menu.ip.lm2n=v2 Lower Memory (no features) -generic.menu.ip.lm2n.build.lwip_include=lwip2/include -generic.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -generic.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -generic.menu.ip.hb2n=v2 Higher Bandwidth (no features) -generic.menu.ip.hb2n.build.lwip_include=lwip2/include -generic.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -generic.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -generic.menu.ip.lm6f=v2 IPv6 Lower Memory -generic.menu.ip.lm6f.build.lwip_include=lwip2/include -generic.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -generic.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -generic.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -generic.menu.ip.hb6f.build.lwip_include=lwip2/include -generic.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -generic.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -generic.menu.ip.hb1=v1.4 Higher Bandwidth -generic.menu.ip.hb1.build.lwip_lib=-llwip_gcc -generic.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.ip.src=v1.4 Compile from source -generic.menu.ip.src.build.lwip_lib=-llwip_src -generic.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -generic.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -generic.menu.dbg.Disabled=Disabled -generic.menu.dbg.Disabled.build.debug_port= -generic.menu.dbg.Serial=Serial -generic.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -generic.menu.dbg.Serial1=Serial1 -generic.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -generic.menu.lvl.None____=None -generic.menu.lvl.None____.build.debug_level= -generic.menu.lvl.SSL=SSL -generic.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -generic.menu.lvl.TLS_MEM=TLS_MEM -generic.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -generic.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -generic.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.HTTP_SERVER=HTTP_SERVER -generic.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -generic.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -generic.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -generic.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -generic.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -generic.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -generic.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -generic.menu.lvl.CORE=CORE -generic.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -generic.menu.lvl.WIFI=WIFI -generic.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -generic.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -generic.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -generic.menu.lvl.UPDATER=UPDATER -generic.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -generic.menu.lvl.OTA=OTA -generic.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -generic.menu.lvl.OOM=OOM -generic.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -generic.menu.lvl.MDNS=MDNS -generic.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -generic.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -generic.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -generic.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -generic.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -generic.menu.wipe.none=Only Sketch -generic.menu.wipe.none.upload.erase_cmd= -generic.menu.wipe.sdk=Sketch + WiFi Settings -generic.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -generic.menu.wipe.all=All Flash Contents -generic.menu.wipe.all.upload.erase_cmd=erase_flash -generic.menu.baud.115200=115200 -generic.menu.baud.115200.upload.speed=115200 -generic.menu.baud.57600=57600 -generic.menu.baud.57600.upload.speed=57600 -generic.menu.baud.230400.linux=230400 -generic.menu.baud.230400.macosx=230400 -generic.menu.baud.230400.upload.speed=230400 -generic.menu.baud.256000.windows=256000 -generic.menu.baud.256000.upload.speed=256000 -generic.menu.baud.460800.linux=460800 -generic.menu.baud.460800.macosx=460800 -generic.menu.baud.460800.upload.speed=460800 -generic.menu.baud.512000.windows=512000 -generic.menu.baud.512000.upload.speed=512000 -generic.menu.baud.921600=921600 -generic.menu.baud.921600.upload.speed=921600 -generic.menu.baud.3000000=3000000 -generic.menu.baud.3000000.upload.speed=3000000 - -############################################################## -esp8285.name=Generic ESP8285 Module -esp8285.build.board=ESP8266_ESP01 -esp8285.build.variant=esp8285 -esp8285.upload.tool=esptool -esp8285.upload.maximum_data_size=81920 -esp8285.upload.wait_for_upload_port=true -esp8285.upload.erase_cmd= -esp8285.serial.disableDTR=true -esp8285.serial.disableRTS=true -esp8285.build.mcu=esp8266 -esp8285.build.core=esp8266 -esp8285.build.spiffs_pagesize=256 -esp8285.build.debug_port= -esp8285.build.debug_level= -esp8285.menu.xtal.80=80 MHz -esp8285.menu.xtal.80.build.f_cpu=80000000L -esp8285.menu.xtal.160=160 MHz -esp8285.menu.xtal.160.build.f_cpu=160000000L -esp8285.menu.vt.flash=Flash -esp8285.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -esp8285.menu.vt.heap=Heap -esp8285.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -esp8285.menu.vt.iram=IRAM -esp8285.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -esp8285.menu.exception.legacy=Legacy (new can return nullptr) -esp8285.menu.exception.legacy.build.exception_flags=-fno-exceptions -esp8285.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -esp8285.menu.exception.disabled=Disabled (new can abort) -esp8285.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -esp8285.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -esp8285.menu.exception.enabled=Enabled -esp8285.menu.exception.enabled.build.exception_flags=-fexceptions -esp8285.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -esp8285.menu.ssl.all=All SSL ciphers (most compatible) -esp8285.menu.ssl.all.build.sslflags= -esp8285.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -esp8285.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -esp8285.menu.ResetMethod.nodemcu=dtr (aka nodemcu) -esp8285.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset -esp8285.menu.ResetMethod.ck=no dtr (aka ck) -esp8285.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset -esp8285.menu.ResetMethod.nodtr_nosync=no dtr, no_sync -esp8285.menu.ResetMethod.nodtr_nosync.upload.resetmethod=--before no_reset_no_sync --after soft_reset -esp8285.menu.CrystalFreq.26=26 MHz -esp8285.menu.CrystalFreq.40=40 MHz -esp8285.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -esp8285.build.flash_mode=dout -esp8285.build.flash_flags=-DFLASHMODE_DOUT -esp8285.build.flash_freq=40 -esp8285.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) -esp8285.menu.eesz.1M64.build.flash_size=1M -esp8285.menu.eesz.1M64.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -esp8285.menu.eesz.1M64.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M64.upload.maximum_size=958448 -esp8285.menu.eesz.1M64.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M64.build.spiffs_start=0xEB000 -esp8285.menu.eesz.1M64.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M64.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) -esp8285.menu.eesz.1M128.build.flash_size=1M -esp8285.menu.eesz.1M128.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -esp8285.menu.eesz.1M128.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M128.upload.maximum_size=892912 -esp8285.menu.eesz.1M128.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M128.build.spiffs_start=0xDB000 -esp8285.menu.eesz.1M128.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M128.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) -esp8285.menu.eesz.1M144.build.flash_size=1M -esp8285.menu.eesz.1M144.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -esp8285.menu.eesz.1M144.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M144.upload.maximum_size=876528 -esp8285.menu.eesz.1M144.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M144.build.spiffs_start=0xD7000 -esp8285.menu.eesz.1M144.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M144.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) -esp8285.menu.eesz.1M160.build.flash_size=1M -esp8285.menu.eesz.1M160.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -esp8285.menu.eesz.1M160.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M160.upload.maximum_size=860144 -esp8285.menu.eesz.1M160.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M160.build.spiffs_start=0xD3000 -esp8285.menu.eesz.1M160.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M160.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) -esp8285.menu.eesz.1M192.build.flash_size=1M -esp8285.menu.eesz.1M192.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -esp8285.menu.eesz.1M192.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M192.upload.maximum_size=827376 -esp8285.menu.eesz.1M192.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M192.build.spiffs_start=0xCB000 -esp8285.menu.eesz.1M192.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M192.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) -esp8285.menu.eesz.1M256.build.flash_size=1M -esp8285.menu.eesz.1M256.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -esp8285.menu.eesz.1M256.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M256.upload.maximum_size=761840 -esp8285.menu.eesz.1M256.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M256.build.spiffs_start=0xBB000 -esp8285.menu.eesz.1M256.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M256.build.spiffs_blocksize=4096 -esp8285.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) -esp8285.menu.eesz.1M512.build.flash_size=1M -esp8285.menu.eesz.1M512.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -esp8285.menu.eesz.1M512.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M512.upload.maximum_size=499696 -esp8285.menu.eesz.1M512.build.rfcal_addr=0xFC000 -esp8285.menu.eesz.1M512.build.spiffs_start=0x7B000 -esp8285.menu.eesz.1M512.build.spiffs_end=0xFB000 -esp8285.menu.eesz.1M512.build.spiffs_blocksize=8192 -esp8285.menu.eesz.1M=1MB (FS:none OTA:~502KB) -esp8285.menu.eesz.1M.build.flash_size=1M -esp8285.menu.eesz.1M.build.flash_size_bytes=0x100000 -esp8285.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -esp8285.menu.eesz.1M.build.spiffs_pagesize=256 -esp8285.menu.eesz.1M.upload.maximum_size=1023984 -esp8285.menu.eesz.1M.build.rfcal_addr=0xFC000 -esp8285.menu.led.2=2 -esp8285.menu.led.2.build.led=-DLED_BUILTIN=2 -esp8285.menu.led.0=0 -esp8285.menu.led.0.build.led=-DLED_BUILTIN=0 -esp8285.menu.led.1=1 -esp8285.menu.led.1.build.led=-DLED_BUILTIN=1 -esp8285.menu.led.3=3 -esp8285.menu.led.3.build.led=-DLED_BUILTIN=3 -esp8285.menu.led.4=4 -esp8285.menu.led.4.build.led=-DLED_BUILTIN=4 -esp8285.menu.led.5=5 -esp8285.menu.led.5.build.led=-DLED_BUILTIN=5 -esp8285.menu.led.6=6 -esp8285.menu.led.6.build.led=-DLED_BUILTIN=6 -esp8285.menu.led.7=7 -esp8285.menu.led.7.build.led=-DLED_BUILTIN=7 -esp8285.menu.led.8=8 -esp8285.menu.led.8.build.led=-DLED_BUILTIN=8 -esp8285.menu.led.9=9 -esp8285.menu.led.9.build.led=-DLED_BUILTIN=9 -esp8285.menu.led.10=10 -esp8285.menu.led.10.build.led=-DLED_BUILTIN=10 -esp8285.menu.led.11=11 -esp8285.menu.led.11.build.led=-DLED_BUILTIN=11 -esp8285.menu.led.12=12 -esp8285.menu.led.12.build.led=-DLED_BUILTIN=12 -esp8285.menu.led.13=13 -esp8285.menu.led.13.build.led=-DLED_BUILTIN=13 -esp8285.menu.led.14=14 -esp8285.menu.led.14.build.led=-DLED_BUILTIN=14 -esp8285.menu.led.15=15 -esp8285.menu.led.15.build.led=-DLED_BUILTIN=15 -esp8285.menu.led.16=16 -esp8285.menu.led.16.build.led=-DLED_BUILTIN=16 -esp8285.menu.ip.lm2f=v2 Lower Memory -esp8285.menu.ip.lm2f.build.lwip_include=lwip2/include -esp8285.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -esp8285.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp8285.menu.ip.hb2f=v2 Higher Bandwidth -esp8285.menu.ip.hb2f.build.lwip_include=lwip2/include -esp8285.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -esp8285.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp8285.menu.ip.lm2n=v2 Lower Memory (no features) -esp8285.menu.ip.lm2n.build.lwip_include=lwip2/include -esp8285.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -esp8285.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp8285.menu.ip.hb2n=v2 Higher Bandwidth (no features) -esp8285.menu.ip.hb2n.build.lwip_include=lwip2/include -esp8285.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -esp8285.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp8285.menu.ip.lm6f=v2 IPv6 Lower Memory -esp8285.menu.ip.lm6f.build.lwip_include=lwip2/include -esp8285.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -esp8285.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp8285.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -esp8285.menu.ip.hb6f.build.lwip_include=lwip2/include -esp8285.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -esp8285.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp8285.menu.ip.hb1=v1.4 Higher Bandwidth -esp8285.menu.ip.hb1.build.lwip_lib=-llwip_gcc -esp8285.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.ip.src=v1.4 Compile from source -esp8285.menu.ip.src.build.lwip_lib=-llwip_src -esp8285.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -esp8285.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp8285.menu.dbg.Disabled=Disabled -esp8285.menu.dbg.Disabled.build.debug_port= -esp8285.menu.dbg.Serial=Serial -esp8285.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp8285.menu.dbg.Serial1=Serial1 -esp8285.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp8285.menu.lvl.None____=None -esp8285.menu.lvl.None____.build.debug_level= -esp8285.menu.lvl.SSL=SSL -esp8285.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp8285.menu.lvl.TLS_MEM=TLS_MEM -esp8285.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp8285.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -esp8285.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.HTTP_SERVER=HTTP_SERVER -esp8285.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -esp8285.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp8285.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp8285.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp8285.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp8285.menu.lvl.CORE=CORE -esp8285.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp8285.menu.lvl.WIFI=WIFI -esp8285.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp8285.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -esp8285.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp8285.menu.lvl.UPDATER=UPDATER -esp8285.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp8285.menu.lvl.OTA=OTA -esp8285.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp8285.menu.lvl.OOM=OOM -esp8285.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -esp8285.menu.lvl.MDNS=MDNS -esp8285.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -esp8285.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -esp8285.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -esp8285.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -esp8285.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp8285.menu.wipe.none=Only Sketch -esp8285.menu.wipe.none.upload.erase_cmd= -esp8285.menu.wipe.sdk=Sketch + WiFi Settings -esp8285.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -esp8285.menu.wipe.all=All Flash Contents -esp8285.menu.wipe.all.upload.erase_cmd=erase_flash -esp8285.menu.baud.115200=115200 -esp8285.menu.baud.115200.upload.speed=115200 -esp8285.menu.baud.57600=57600 -esp8285.menu.baud.57600.upload.speed=57600 -esp8285.menu.baud.230400.linux=230400 -esp8285.menu.baud.230400.macosx=230400 -esp8285.menu.baud.230400.upload.speed=230400 -esp8285.menu.baud.256000.windows=256000 -esp8285.menu.baud.256000.upload.speed=256000 -esp8285.menu.baud.460800.linux=460800 -esp8285.menu.baud.460800.macosx=460800 -esp8285.menu.baud.460800.upload.speed=460800 -esp8285.menu.baud.512000.windows=512000 -esp8285.menu.baud.512000.upload.speed=512000 -esp8285.menu.baud.921600=921600 -esp8285.menu.baud.921600.upload.speed=921600 -esp8285.menu.baud.3000000=3000000 -esp8285.menu.baud.3000000.upload.speed=3000000 - -############################################################## -espduino.name=ESPDuino (ESP-13 Module) -espduino.build.board=ESP8266_ESP13 -espduino.build.variant=ESPDuino -espduino.menu.ResetMethod.v1=ESPduino-V1 -espduino.menu.ResetMethod.v1.upload.resetmethod=--before no_reset --after soft_reset -espduino.menu.ResetMethod.v2=ESPduino-V2 -espduino.menu.ResetMethod.v2.upload.resetmethod=--before default_reset --after hard_reset -espduino.menu.UploadTool.espota=OTA -espduino.menu.UploadTool.espota.upload.tool=espota -espduino.menu.UploadTool.esptool=Serial -espduino.menu.UploadTool.esptool.upload.tool=esptool -espduino.menu.UploadTool.esptool.upload.verbose=--trace -espduino.upload.tool=esptool -espduino.upload.maximum_data_size=81920 -espduino.upload.wait_for_upload_port=true -espduino.upload.erase_cmd= -espduino.serial.disableDTR=true -espduino.serial.disableRTS=true -espduino.build.mcu=esp8266 -espduino.build.core=esp8266 -espduino.build.spiffs_pagesize=256 -espduino.build.debug_port= -espduino.build.debug_level= -espduino.menu.xtal.80=80 MHz -espduino.menu.xtal.80.build.f_cpu=80000000L -espduino.menu.xtal.160=160 MHz -espduino.menu.xtal.160.build.f_cpu=160000000L -espduino.menu.vt.flash=Flash -espduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espduino.menu.vt.heap=Heap -espduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espduino.menu.vt.iram=IRAM -espduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espduino.menu.exception.legacy=Legacy (new can return nullptr) -espduino.menu.exception.legacy.build.exception_flags=-fno-exceptions -espduino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -espduino.menu.exception.disabled=Disabled (new can abort) -espduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -espduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espduino.menu.exception.enabled=Enabled -espduino.menu.exception.enabled.build.exception_flags=-fexceptions -espduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espduino.menu.ssl.all=All SSL ciphers (most compatible) -espduino.menu.ssl.all.build.sslflags= -espduino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -espduino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -espduino.build.flash_mode=dio -espduino.build.flash_flags=-DFLASHMODE_DIO -espduino.build.flash_freq=40 -espduino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -espduino.menu.eesz.4M2M.build.flash_size=4M -espduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espduino.menu.eesz.4M2M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M2M.upload.maximum_size=1044464 -espduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M2M.build.spiffs_start=0x200000 -espduino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -espduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espduino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -espduino.menu.eesz.4M3M.build.flash_size=4M -espduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espduino.menu.eesz.4M3M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M3M.upload.maximum_size=1044464 -espduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M3M.build.spiffs_start=0x100000 -espduino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -espduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espduino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -espduino.menu.eesz.4M1M.build.flash_size=4M -espduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espduino.menu.eesz.4M1M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M1M.upload.maximum_size=1044464 -espduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espduino.menu.eesz.4M1M.build.spiffs_start=0x300000 -espduino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -espduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espduino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -espduino.menu.eesz.4M.build.flash_size=4M -espduino.menu.eesz.4M.build.flash_size_bytes=0x400000 -espduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espduino.menu.eesz.4M.build.spiffs_pagesize=256 -espduino.menu.eesz.4M.upload.maximum_size=1044464 -espduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espduino.menu.ip.lm2f=v2 Lower Memory -espduino.menu.ip.lm2f.build.lwip_include=lwip2/include -espduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espduino.menu.ip.hb2f=v2 Higher Bandwidth -espduino.menu.ip.hb2f.build.lwip_include=lwip2/include -espduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espduino.menu.ip.lm2n=v2 Lower Memory (no features) -espduino.menu.ip.lm2n.build.lwip_include=lwip2/include -espduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espduino.menu.ip.hb2n.build.lwip_include=lwip2/include -espduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espduino.menu.ip.lm6f=v2 IPv6 Lower Memory -espduino.menu.ip.lm6f.build.lwip_include=lwip2/include -espduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espduino.menu.ip.hb6f.build.lwip_include=lwip2/include -espduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espduino.menu.ip.hb1=v1.4 Higher Bandwidth -espduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.ip.src=v1.4 Compile from source -espduino.menu.ip.src.build.lwip_lib=-llwip_src -espduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espduino.menu.dbg.Disabled=Disabled -espduino.menu.dbg.Disabled.build.debug_port= -espduino.menu.dbg.Serial=Serial -espduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espduino.menu.dbg.Serial1=Serial1 -espduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espduino.menu.lvl.None____=None -espduino.menu.lvl.None____.build.debug_level= -espduino.menu.lvl.SSL=SSL -espduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espduino.menu.lvl.TLS_MEM=TLS_MEM -espduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.HTTP_SERVER=HTTP_SERVER -espduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espduino.menu.lvl.CORE=CORE -espduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espduino.menu.lvl.WIFI=WIFI -espduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espduino.menu.lvl.UPDATER=UPDATER -espduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espduino.menu.lvl.OTA=OTA -espduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espduino.menu.lvl.OOM=OOM -espduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espduino.menu.lvl.MDNS=MDNS -espduino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espduino.menu.wipe.none=Only Sketch -espduino.menu.wipe.none.upload.erase_cmd= -espduino.menu.wipe.sdk=Sketch + WiFi Settings -espduino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -espduino.menu.wipe.all=All Flash Contents -espduino.menu.wipe.all.upload.erase_cmd=erase_flash -espduino.menu.baud.115200=115200 -espduino.menu.baud.115200.upload.speed=115200 -espduino.menu.baud.57600=57600 -espduino.menu.baud.57600.upload.speed=57600 -espduino.menu.baud.230400.linux=230400 -espduino.menu.baud.230400.macosx=230400 -espduino.menu.baud.230400.upload.speed=230400 -espduino.menu.baud.256000.windows=256000 -espduino.menu.baud.256000.upload.speed=256000 -espduino.menu.baud.460800.linux=460800 -espduino.menu.baud.460800.macosx=460800 -espduino.menu.baud.460800.upload.speed=460800 -espduino.menu.baud.512000.windows=512000 -espduino.menu.baud.512000.upload.speed=512000 -espduino.menu.baud.921600=921600 -espduino.menu.baud.921600.upload.speed=921600 -espduino.menu.baud.3000000=3000000 -espduino.menu.baud.3000000.upload.speed=3000000 - -############################################################## -huzzah.name=Adafruit Feather HUZZAH ESP8266 -huzzah.build.board=ESP8266_ESP12 -huzzah.build.variant=adafruit -huzzah.upload.tool=esptool -huzzah.upload.maximum_data_size=81920 -huzzah.upload.wait_for_upload_port=true -huzzah.upload.erase_cmd= -huzzah.serial.disableDTR=true -huzzah.serial.disableRTS=true -huzzah.build.mcu=esp8266 -huzzah.build.core=esp8266 -huzzah.build.spiffs_pagesize=256 -huzzah.build.debug_port= -huzzah.build.debug_level= -huzzah.menu.xtal.80=80 MHz -huzzah.menu.xtal.80.build.f_cpu=80000000L -huzzah.menu.xtal.160=160 MHz -huzzah.menu.xtal.160.build.f_cpu=160000000L -huzzah.menu.vt.flash=Flash -huzzah.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -huzzah.menu.vt.heap=Heap -huzzah.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -huzzah.menu.vt.iram=IRAM -huzzah.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -huzzah.menu.exception.legacy=Legacy (new can return nullptr) -huzzah.menu.exception.legacy.build.exception_flags=-fno-exceptions -huzzah.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -huzzah.menu.exception.disabled=Disabled (new can abort) -huzzah.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -huzzah.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -huzzah.menu.exception.enabled=Enabled -huzzah.menu.exception.enabled.build.exception_flags=-fexceptions -huzzah.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -huzzah.menu.ssl.all=All SSL ciphers (most compatible) -huzzah.menu.ssl.all.build.sslflags= -huzzah.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -huzzah.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -huzzah.upload.resetmethod=--before default_reset --after hard_reset -huzzah.build.flash_mode=qio -huzzah.build.flash_flags=-DFLASHMODE_QIO -huzzah.build.flash_freq=40 -huzzah.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -huzzah.menu.eesz.4M2M.build.flash_size=4M -huzzah.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -huzzah.menu.eesz.4M2M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M2M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M2M.build.spiffs_start=0x200000 -huzzah.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -huzzah.menu.eesz.4M2M.build.spiffs_blocksize=8192 -huzzah.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -huzzah.menu.eesz.4M3M.build.flash_size=4M -huzzah.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -huzzah.menu.eesz.4M3M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M3M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M3M.build.spiffs_start=0x100000 -huzzah.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -huzzah.menu.eesz.4M3M.build.spiffs_blocksize=8192 -huzzah.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -huzzah.menu.eesz.4M1M.build.flash_size=4M -huzzah.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -huzzah.menu.eesz.4M1M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M1M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -huzzah.menu.eesz.4M1M.build.spiffs_start=0x300000 -huzzah.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -huzzah.menu.eesz.4M1M.build.spiffs_blocksize=8192 -huzzah.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -huzzah.menu.eesz.4M.build.flash_size=4M -huzzah.menu.eesz.4M.build.flash_size_bytes=0x400000 -huzzah.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -huzzah.menu.eesz.4M.build.spiffs_pagesize=256 -huzzah.menu.eesz.4M.upload.maximum_size=1044464 -huzzah.menu.eesz.4M.build.rfcal_addr=0x3FC000 -huzzah.menu.ip.lm2f=v2 Lower Memory -huzzah.menu.ip.lm2f.build.lwip_include=lwip2/include -huzzah.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -huzzah.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -huzzah.menu.ip.hb2f=v2 Higher Bandwidth -huzzah.menu.ip.hb2f.build.lwip_include=lwip2/include -huzzah.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -huzzah.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -huzzah.menu.ip.lm2n=v2 Lower Memory (no features) -huzzah.menu.ip.lm2n.build.lwip_include=lwip2/include -huzzah.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -huzzah.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -huzzah.menu.ip.hb2n=v2 Higher Bandwidth (no features) -huzzah.menu.ip.hb2n.build.lwip_include=lwip2/include -huzzah.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -huzzah.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -huzzah.menu.ip.lm6f=v2 IPv6 Lower Memory -huzzah.menu.ip.lm6f.build.lwip_include=lwip2/include -huzzah.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -huzzah.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -huzzah.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -huzzah.menu.ip.hb6f.build.lwip_include=lwip2/include -huzzah.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -huzzah.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -huzzah.menu.ip.hb1=v1.4 Higher Bandwidth -huzzah.menu.ip.hb1.build.lwip_lib=-llwip_gcc -huzzah.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.ip.src=v1.4 Compile from source -huzzah.menu.ip.src.build.lwip_lib=-llwip_src -huzzah.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -huzzah.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -huzzah.menu.dbg.Disabled=Disabled -huzzah.menu.dbg.Disabled.build.debug_port= -huzzah.menu.dbg.Serial=Serial -huzzah.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -huzzah.menu.dbg.Serial1=Serial1 -huzzah.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -huzzah.menu.lvl.None____=None -huzzah.menu.lvl.None____.build.debug_level= -huzzah.menu.lvl.SSL=SSL -huzzah.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -huzzah.menu.lvl.TLS_MEM=TLS_MEM -huzzah.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -huzzah.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -huzzah.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.HTTP_SERVER=HTTP_SERVER -huzzah.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -huzzah.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -huzzah.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -huzzah.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -huzzah.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -huzzah.menu.lvl.CORE=CORE -huzzah.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -huzzah.menu.lvl.WIFI=WIFI -huzzah.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -huzzah.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -huzzah.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -huzzah.menu.lvl.UPDATER=UPDATER -huzzah.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -huzzah.menu.lvl.OTA=OTA -huzzah.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -huzzah.menu.lvl.OOM=OOM -huzzah.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -huzzah.menu.lvl.MDNS=MDNS -huzzah.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -huzzah.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -huzzah.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -huzzah.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -huzzah.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -huzzah.menu.wipe.none=Only Sketch -huzzah.menu.wipe.none.upload.erase_cmd= -huzzah.menu.wipe.sdk=Sketch + WiFi Settings -huzzah.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -huzzah.menu.wipe.all=All Flash Contents -huzzah.menu.wipe.all.upload.erase_cmd=erase_flash -huzzah.menu.baud.115200=115200 -huzzah.menu.baud.115200.upload.speed=115200 -huzzah.menu.baud.57600=57600 -huzzah.menu.baud.57600.upload.speed=57600 -huzzah.menu.baud.230400.linux=230400 -huzzah.menu.baud.230400.macosx=230400 -huzzah.menu.baud.230400.upload.speed=230400 -huzzah.menu.baud.256000.windows=256000 -huzzah.menu.baud.256000.upload.speed=256000 -huzzah.menu.baud.460800.linux=460800 -huzzah.menu.baud.460800.macosx=460800 -huzzah.menu.baud.460800.upload.speed=460800 -huzzah.menu.baud.512000.windows=512000 -huzzah.menu.baud.512000.upload.speed=512000 -huzzah.menu.baud.921600=921600 -huzzah.menu.baud.921600.upload.speed=921600 -huzzah.menu.baud.3000000=3000000 -huzzah.menu.baud.3000000.upload.speed=3000000 - -############################################################## -inventone.name=Invent One -inventone.build.board=ESP8266_GENERIC -inventone.build.variant=inventone -inventone.upload.tool=esptool -inventone.upload.maximum_data_size=81920 -inventone.upload.wait_for_upload_port=true -inventone.upload.erase_cmd= -inventone.serial.disableDTR=true -inventone.serial.disableRTS=true -inventone.build.mcu=esp8266 -inventone.build.core=esp8266 -inventone.build.spiffs_pagesize=256 -inventone.build.debug_port= -inventone.build.debug_level= -inventone.menu.xtal.80=80 MHz -inventone.menu.xtal.80.build.f_cpu=80000000L -inventone.menu.xtal.160=160 MHz -inventone.menu.xtal.160.build.f_cpu=160000000L -inventone.menu.vt.flash=Flash -inventone.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -inventone.menu.vt.heap=Heap -inventone.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -inventone.menu.vt.iram=IRAM -inventone.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -inventone.menu.exception.legacy=Legacy (new can return nullptr) -inventone.menu.exception.legacy.build.exception_flags=-fno-exceptions -inventone.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -inventone.menu.exception.disabled=Disabled (new can abort) -inventone.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -inventone.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -inventone.menu.exception.enabled=Enabled -inventone.menu.exception.enabled.build.exception_flags=-fexceptions -inventone.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -inventone.menu.ssl.all=All SSL ciphers (most compatible) -inventone.menu.ssl.all.build.sslflags= -inventone.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -inventone.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -inventone.upload.resetmethod=--before default_reset --after hard_reset -inventone.build.flash_mode=dio -inventone.build.flash_flags=-DFLASHMODE_DIO -inventone.build.flash_freq=40 -inventone.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -inventone.menu.eesz.4M2M.build.flash_size=4M -inventone.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -inventone.menu.eesz.4M2M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M2M.upload.maximum_size=1044464 -inventone.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M2M.build.spiffs_start=0x200000 -inventone.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -inventone.menu.eesz.4M2M.build.spiffs_blocksize=8192 -inventone.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -inventone.menu.eesz.4M3M.build.flash_size=4M -inventone.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -inventone.menu.eesz.4M3M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M3M.upload.maximum_size=1044464 -inventone.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M3M.build.spiffs_start=0x100000 -inventone.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -inventone.menu.eesz.4M3M.build.spiffs_blocksize=8192 -inventone.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -inventone.menu.eesz.4M1M.build.flash_size=4M -inventone.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -inventone.menu.eesz.4M1M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M1M.upload.maximum_size=1044464 -inventone.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -inventone.menu.eesz.4M1M.build.spiffs_start=0x300000 -inventone.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -inventone.menu.eesz.4M1M.build.spiffs_blocksize=8192 -inventone.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -inventone.menu.eesz.4M.build.flash_size=4M -inventone.menu.eesz.4M.build.flash_size_bytes=0x400000 -inventone.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -inventone.menu.eesz.4M.build.spiffs_pagesize=256 -inventone.menu.eesz.4M.upload.maximum_size=1044464 -inventone.menu.eesz.4M.build.rfcal_addr=0x3FC000 -inventone.menu.ip.lm2f=v2 Lower Memory -inventone.menu.ip.lm2f.build.lwip_include=lwip2/include -inventone.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -inventone.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -inventone.menu.ip.hb2f=v2 Higher Bandwidth -inventone.menu.ip.hb2f.build.lwip_include=lwip2/include -inventone.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -inventone.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -inventone.menu.ip.lm2n=v2 Lower Memory (no features) -inventone.menu.ip.lm2n.build.lwip_include=lwip2/include -inventone.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -inventone.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -inventone.menu.ip.hb2n=v2 Higher Bandwidth (no features) -inventone.menu.ip.hb2n.build.lwip_include=lwip2/include -inventone.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -inventone.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -inventone.menu.ip.lm6f=v2 IPv6 Lower Memory -inventone.menu.ip.lm6f.build.lwip_include=lwip2/include -inventone.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -inventone.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -inventone.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -inventone.menu.ip.hb6f.build.lwip_include=lwip2/include -inventone.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -inventone.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -inventone.menu.ip.hb1=v1.4 Higher Bandwidth -inventone.menu.ip.hb1.build.lwip_lib=-llwip_gcc -inventone.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -inventone.menu.ip.src=v1.4 Compile from source -inventone.menu.ip.src.build.lwip_lib=-llwip_src -inventone.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -inventone.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -inventone.menu.dbg.Disabled=Disabled -inventone.menu.dbg.Disabled.build.debug_port= -inventone.menu.dbg.Serial=Serial -inventone.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -inventone.menu.dbg.Serial1=Serial1 -inventone.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -inventone.menu.lvl.None____=None -inventone.menu.lvl.None____.build.debug_level= -inventone.menu.lvl.SSL=SSL -inventone.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -inventone.menu.lvl.TLS_MEM=TLS_MEM -inventone.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -inventone.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -inventone.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.HTTP_SERVER=HTTP_SERVER -inventone.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -inventone.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -inventone.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -inventone.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -inventone.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -inventone.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -inventone.menu.lvl.CORE=CORE -inventone.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -inventone.menu.lvl.WIFI=WIFI -inventone.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -inventone.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -inventone.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -inventone.menu.lvl.UPDATER=UPDATER -inventone.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -inventone.menu.lvl.OTA=OTA -inventone.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -inventone.menu.lvl.OOM=OOM -inventone.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -inventone.menu.lvl.MDNS=MDNS -inventone.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -inventone.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -inventone.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -inventone.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -inventone.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -inventone.menu.wipe.none=Only Sketch -inventone.menu.wipe.none.upload.erase_cmd= -inventone.menu.wipe.sdk=Sketch + WiFi Settings -inventone.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -inventone.menu.wipe.all=All Flash Contents -inventone.menu.wipe.all.upload.erase_cmd=erase_flash -inventone.menu.baud.115200=115200 -inventone.menu.baud.115200.upload.speed=115200 -inventone.menu.baud.57600=57600 -inventone.menu.baud.57600.upload.speed=57600 -inventone.menu.baud.230400.linux=230400 -inventone.menu.baud.230400.macosx=230400 -inventone.menu.baud.230400.upload.speed=230400 -inventone.menu.baud.256000.windows=256000 -inventone.menu.baud.256000.upload.speed=256000 -inventone.menu.baud.460800.linux=460800 -inventone.menu.baud.460800.macosx=460800 -inventone.menu.baud.460800.upload.speed=460800 -inventone.menu.baud.512000.windows=512000 -inventone.menu.baud.512000.upload.speed=512000 -inventone.menu.baud.921600=921600 -inventone.menu.baud.921600.upload.speed=921600 -inventone.menu.baud.3000000=3000000 -inventone.menu.baud.3000000.upload.speed=3000000 - -############################################################## -cw01.name=XinaBox CW01 -cw01.build.board=ESP8266_GENERIC -cw01.build.variant=xinabox -cw01.upload.tool=esptool -cw01.upload.maximum_data_size=81920 -cw01.upload.wait_for_upload_port=true -cw01.upload.erase_cmd= -cw01.serial.disableDTR=true -cw01.serial.disableRTS=true -cw01.build.mcu=esp8266 -cw01.build.core=esp8266 -cw01.build.spiffs_pagesize=256 -cw01.build.debug_port= -cw01.build.debug_level= -cw01.menu.xtal.80=80 MHz -cw01.menu.xtal.80.build.f_cpu=80000000L -cw01.menu.xtal.160=160 MHz -cw01.menu.xtal.160.build.f_cpu=160000000L -cw01.menu.vt.flash=Flash -cw01.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -cw01.menu.vt.heap=Heap -cw01.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -cw01.menu.vt.iram=IRAM -cw01.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -cw01.menu.exception.legacy=Legacy (new can return nullptr) -cw01.menu.exception.legacy.build.exception_flags=-fno-exceptions -cw01.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -cw01.menu.exception.disabled=Disabled (new can abort) -cw01.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -cw01.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -cw01.menu.exception.enabled=Enabled -cw01.menu.exception.enabled.build.exception_flags=-fexceptions -cw01.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -cw01.menu.ssl.all=All SSL ciphers (most compatible) -cw01.menu.ssl.all.build.sslflags= -cw01.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -cw01.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -cw01.upload.resetmethod=--before default_reset --after hard_reset -cw01.menu.CrystalFreq.26=26 MHz -cw01.menu.CrystalFreq.40=40 MHz -cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -cw01.build.flash_mode=dio -cw01.build.flash_flags=-DFLASHMODE_DIO -cw01.build.flash_freq=40 -cw01.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -cw01.menu.eesz.4M2M.build.flash_size=4M -cw01.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -cw01.menu.eesz.4M2M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M2M.upload.maximum_size=1044464 -cw01.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M2M.build.spiffs_start=0x200000 -cw01.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -cw01.menu.eesz.4M2M.build.spiffs_blocksize=8192 -cw01.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -cw01.menu.eesz.4M3M.build.flash_size=4M -cw01.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -cw01.menu.eesz.4M3M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M3M.upload.maximum_size=1044464 -cw01.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M3M.build.spiffs_start=0x100000 -cw01.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -cw01.menu.eesz.4M3M.build.spiffs_blocksize=8192 -cw01.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -cw01.menu.eesz.4M1M.build.flash_size=4M -cw01.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -cw01.menu.eesz.4M1M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M1M.upload.maximum_size=1044464 -cw01.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -cw01.menu.eesz.4M1M.build.spiffs_start=0x300000 -cw01.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -cw01.menu.eesz.4M1M.build.spiffs_blocksize=8192 -cw01.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -cw01.menu.eesz.4M.build.flash_size=4M -cw01.menu.eesz.4M.build.flash_size_bytes=0x400000 -cw01.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -cw01.menu.eesz.4M.build.spiffs_pagesize=256 -cw01.menu.eesz.4M.upload.maximum_size=1044464 -cw01.menu.eesz.4M.build.rfcal_addr=0x3FC000 -cw01.menu.ip.lm2f=v2 Lower Memory -cw01.menu.ip.lm2f.build.lwip_include=lwip2/include -cw01.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -cw01.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -cw01.menu.ip.hb2f=v2 Higher Bandwidth -cw01.menu.ip.hb2f.build.lwip_include=lwip2/include -cw01.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -cw01.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -cw01.menu.ip.lm2n=v2 Lower Memory (no features) -cw01.menu.ip.lm2n.build.lwip_include=lwip2/include -cw01.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -cw01.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -cw01.menu.ip.hb2n=v2 Higher Bandwidth (no features) -cw01.menu.ip.hb2n.build.lwip_include=lwip2/include -cw01.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -cw01.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -cw01.menu.ip.lm6f=v2 IPv6 Lower Memory -cw01.menu.ip.lm6f.build.lwip_include=lwip2/include -cw01.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -cw01.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -cw01.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -cw01.menu.ip.hb6f.build.lwip_include=lwip2/include -cw01.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -cw01.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -cw01.menu.ip.hb1=v1.4 Higher Bandwidth -cw01.menu.ip.hb1.build.lwip_lib=-llwip_gcc -cw01.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -cw01.menu.ip.src=v1.4 Compile from source -cw01.menu.ip.src.build.lwip_lib=-llwip_src -cw01.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -cw01.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -cw01.menu.dbg.Disabled=Disabled -cw01.menu.dbg.Disabled.build.debug_port= -cw01.menu.dbg.Serial=Serial -cw01.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -cw01.menu.dbg.Serial1=Serial1 -cw01.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -cw01.menu.lvl.None____=None -cw01.menu.lvl.None____.build.debug_level= -cw01.menu.lvl.SSL=SSL -cw01.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -cw01.menu.lvl.TLS_MEM=TLS_MEM -cw01.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -cw01.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -cw01.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.HTTP_SERVER=HTTP_SERVER -cw01.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -cw01.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -cw01.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -cw01.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -cw01.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -cw01.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -cw01.menu.lvl.CORE=CORE -cw01.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -cw01.menu.lvl.WIFI=WIFI -cw01.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -cw01.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -cw01.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -cw01.menu.lvl.UPDATER=UPDATER -cw01.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -cw01.menu.lvl.OTA=OTA -cw01.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -cw01.menu.lvl.OOM=OOM -cw01.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -cw01.menu.lvl.MDNS=MDNS -cw01.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -cw01.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -cw01.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -cw01.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -cw01.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -cw01.menu.wipe.none=Only Sketch -cw01.menu.wipe.none.upload.erase_cmd= -cw01.menu.wipe.sdk=Sketch + WiFi Settings -cw01.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -cw01.menu.wipe.all=All Flash Contents -cw01.menu.wipe.all.upload.erase_cmd=erase_flash -cw01.menu.baud.115200=115200 -cw01.menu.baud.115200.upload.speed=115200 -cw01.menu.baud.57600=57600 -cw01.menu.baud.57600.upload.speed=57600 -cw01.menu.baud.230400.linux=230400 -cw01.menu.baud.230400.macosx=230400 -cw01.menu.baud.230400.upload.speed=230400 -cw01.menu.baud.256000.windows=256000 -cw01.menu.baud.256000.upload.speed=256000 -cw01.menu.baud.460800.linux=460800 -cw01.menu.baud.460800.macosx=460800 -cw01.menu.baud.460800.upload.speed=460800 -cw01.menu.baud.512000.windows=512000 -cw01.menu.baud.512000.upload.speed=512000 -cw01.menu.baud.921600=921600 -cw01.menu.baud.921600.upload.speed=921600 -cw01.menu.baud.3000000=3000000 -cw01.menu.baud.3000000.upload.speed=3000000 - -############################################################## -espresso_lite_v1.name=ESPresso Lite 1.0 -espresso_lite_v1.build.board=ESP8266_ESPRESSO_LITE_V1 -espresso_lite_v1.build.variant=espresso_lite_v1 -espresso_lite_v1.upload.tool=esptool -espresso_lite_v1.upload.maximum_data_size=81920 -espresso_lite_v1.upload.wait_for_upload_port=true -espresso_lite_v1.upload.erase_cmd= -espresso_lite_v1.serial.disableDTR=true -espresso_lite_v1.serial.disableRTS=true -espresso_lite_v1.build.mcu=esp8266 -espresso_lite_v1.build.core=esp8266 -espresso_lite_v1.build.spiffs_pagesize=256 -espresso_lite_v1.build.debug_port= -espresso_lite_v1.build.debug_level= -espresso_lite_v1.menu.xtal.80=80 MHz -espresso_lite_v1.menu.xtal.80.build.f_cpu=80000000L -espresso_lite_v1.menu.xtal.160=160 MHz -espresso_lite_v1.menu.xtal.160.build.f_cpu=160000000L -espresso_lite_v1.menu.vt.flash=Flash -espresso_lite_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espresso_lite_v1.menu.vt.heap=Heap -espresso_lite_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espresso_lite_v1.menu.vt.iram=IRAM -espresso_lite_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espresso_lite_v1.menu.exception.legacy=Legacy (new can return nullptr) -espresso_lite_v1.menu.exception.legacy.build.exception_flags=-fno-exceptions -espresso_lite_v1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -espresso_lite_v1.menu.exception.disabled=Disabled (new can abort) -espresso_lite_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -espresso_lite_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espresso_lite_v1.menu.exception.enabled=Enabled -espresso_lite_v1.menu.exception.enabled.build.exception_flags=-fexceptions -espresso_lite_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espresso_lite_v1.menu.ssl.all=All SSL ciphers (most compatible) -espresso_lite_v1.menu.ssl.all.build.sslflags= -espresso_lite_v1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -espresso_lite_v1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -espresso_lite_v1.build.flash_mode=dio -espresso_lite_v1.build.flash_flags=-DFLASHMODE_DIO -espresso_lite_v1.build.flash_freq=40 -espresso_lite_v1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -espresso_lite_v1.menu.eesz.4M2M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M2M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -espresso_lite_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -espresso_lite_v1.menu.eesz.4M3M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M3M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -espresso_lite_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -espresso_lite_v1.menu.eesz.4M1M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M1M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -espresso_lite_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -espresso_lite_v1.menu.eesz.4M.build.flash_size=4M -espresso_lite_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 -espresso_lite_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v1.menu.eesz.4M.build.spiffs_pagesize=256 -espresso_lite_v1.menu.eesz.4M.upload.maximum_size=1044464 -espresso_lite_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espresso_lite_v1.menu.ResetMethod.nodemcu=dtr (aka nodemcu) -espresso_lite_v1.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset -espresso_lite_v1.menu.ResetMethod.ck=no dtr (aka ck) -espresso_lite_v1.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset -espresso_lite_v1.menu.ip.lm2f=v2 Lower Memory -espresso_lite_v1.menu.ip.lm2f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espresso_lite_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.hb2f=v2 Higher Bandwidth -espresso_lite_v1.menu.ip.hb2f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espresso_lite_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.lm2n=v2 Lower Memory (no features) -espresso_lite_v1.menu.ip.lm2n.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espresso_lite_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espresso_lite_v1.menu.ip.hb2n.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espresso_lite_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v1.menu.ip.lm6f=v2 IPv6 Lower Memory -espresso_lite_v1.menu.ip.lm6f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espresso_lite_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espresso_lite_v1.menu.ip.hb6f.build.lwip_include=lwip2/include -espresso_lite_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espresso_lite_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v1.menu.ip.hb1=v1.4 Higher Bandwidth -espresso_lite_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espresso_lite_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.ip.src=v1.4 Compile from source -espresso_lite_v1.menu.ip.src.build.lwip_lib=-llwip_src -espresso_lite_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v1.menu.dbg.Disabled=Disabled -espresso_lite_v1.menu.dbg.Disabled.build.debug_port= -espresso_lite_v1.menu.dbg.Serial=Serial -espresso_lite_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v1.menu.dbg.Serial1=Serial1 -espresso_lite_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v1.menu.lvl.None____=None -espresso_lite_v1.menu.lvl.None____.build.debug_level= -espresso_lite_v1.menu.lvl.SSL=SSL -espresso_lite_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v1.menu.lvl.TLS_MEM=TLS_MEM -espresso_lite_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v1.menu.lvl.CORE=CORE -espresso_lite_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v1.menu.lvl.WIFI=WIFI -espresso_lite_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v1.menu.lvl.UPDATER=UPDATER -espresso_lite_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v1.menu.lvl.OTA=OTA -espresso_lite_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v1.menu.lvl.OOM=OOM -espresso_lite_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espresso_lite_v1.menu.lvl.MDNS=MDNS -espresso_lite_v1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espresso_lite_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espresso_lite_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espresso_lite_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v1.menu.wipe.none=Only Sketch -espresso_lite_v1.menu.wipe.none.upload.erase_cmd= -espresso_lite_v1.menu.wipe.sdk=Sketch + WiFi Settings -espresso_lite_v1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -espresso_lite_v1.menu.wipe.all=All Flash Contents -espresso_lite_v1.menu.wipe.all.upload.erase_cmd=erase_flash -espresso_lite_v1.menu.baud.115200=115200 -espresso_lite_v1.menu.baud.115200.upload.speed=115200 -espresso_lite_v1.menu.baud.57600=57600 -espresso_lite_v1.menu.baud.57600.upload.speed=57600 -espresso_lite_v1.menu.baud.230400.linux=230400 -espresso_lite_v1.menu.baud.230400.macosx=230400 -espresso_lite_v1.menu.baud.230400.upload.speed=230400 -espresso_lite_v1.menu.baud.256000.windows=256000 -espresso_lite_v1.menu.baud.256000.upload.speed=256000 -espresso_lite_v1.menu.baud.460800.linux=460800 -espresso_lite_v1.menu.baud.460800.macosx=460800 -espresso_lite_v1.menu.baud.460800.upload.speed=460800 -espresso_lite_v1.menu.baud.512000.windows=512000 -espresso_lite_v1.menu.baud.512000.upload.speed=512000 -espresso_lite_v1.menu.baud.921600=921600 -espresso_lite_v1.menu.baud.921600.upload.speed=921600 -espresso_lite_v1.menu.baud.3000000=3000000 -espresso_lite_v1.menu.baud.3000000.upload.speed=3000000 - -############################################################## -espresso_lite_v2.name=ESPresso Lite 2.0 -espresso_lite_v2.build.board=ESP8266_ESPRESSO_LITE_V2 -espresso_lite_v2.build.variant=espresso_lite_v2 -espresso_lite_v2.upload.tool=esptool -espresso_lite_v2.upload.maximum_data_size=81920 -espresso_lite_v2.upload.wait_for_upload_port=true -espresso_lite_v2.upload.erase_cmd= -espresso_lite_v2.serial.disableDTR=true -espresso_lite_v2.serial.disableRTS=true -espresso_lite_v2.build.mcu=esp8266 -espresso_lite_v2.build.core=esp8266 -espresso_lite_v2.build.spiffs_pagesize=256 -espresso_lite_v2.build.debug_port= -espresso_lite_v2.build.debug_level= -espresso_lite_v2.menu.xtal.80=80 MHz -espresso_lite_v2.menu.xtal.80.build.f_cpu=80000000L -espresso_lite_v2.menu.xtal.160=160 MHz -espresso_lite_v2.menu.xtal.160.build.f_cpu=160000000L -espresso_lite_v2.menu.vt.flash=Flash -espresso_lite_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espresso_lite_v2.menu.vt.heap=Heap -espresso_lite_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espresso_lite_v2.menu.vt.iram=IRAM -espresso_lite_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espresso_lite_v2.menu.exception.legacy=Legacy (new can return nullptr) -espresso_lite_v2.menu.exception.legacy.build.exception_flags=-fno-exceptions -espresso_lite_v2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -espresso_lite_v2.menu.exception.disabled=Disabled (new can abort) -espresso_lite_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -espresso_lite_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espresso_lite_v2.menu.exception.enabled=Enabled -espresso_lite_v2.menu.exception.enabled.build.exception_flags=-fexceptions -espresso_lite_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espresso_lite_v2.menu.ssl.all=All SSL ciphers (most compatible) -espresso_lite_v2.menu.ssl.all.build.sslflags= -espresso_lite_v2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -espresso_lite_v2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -espresso_lite_v2.build.flash_mode=dio -espresso_lite_v2.build.flash_flags=-DFLASHMODE_DIO -espresso_lite_v2.build.flash_freq=40 -espresso_lite_v2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -espresso_lite_v2.menu.eesz.4M2M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M2M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -espresso_lite_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -espresso_lite_v2.menu.eesz.4M3M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M3M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -espresso_lite_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -espresso_lite_v2.menu.eesz.4M1M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M1M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -espresso_lite_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espresso_lite_v2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -espresso_lite_v2.menu.eesz.4M.build.flash_size=4M -espresso_lite_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 -espresso_lite_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espresso_lite_v2.menu.eesz.4M.build.spiffs_pagesize=256 -espresso_lite_v2.menu.eesz.4M.upload.maximum_size=1044464 -espresso_lite_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espresso_lite_v2.menu.ResetMethod.nodemcu=dtr (aka nodemcu) -espresso_lite_v2.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset -espresso_lite_v2.menu.ResetMethod.ck=no dtr (aka ck) -espresso_lite_v2.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset -espresso_lite_v2.menu.ip.lm2f=v2 Lower Memory -espresso_lite_v2.menu.ip.lm2f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espresso_lite_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.hb2f=v2 Higher Bandwidth -espresso_lite_v2.menu.ip.hb2f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espresso_lite_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.lm2n=v2 Lower Memory (no features) -espresso_lite_v2.menu.ip.lm2n.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espresso_lite_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espresso_lite_v2.menu.ip.hb2n.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espresso_lite_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espresso_lite_v2.menu.ip.lm6f=v2 IPv6 Lower Memory -espresso_lite_v2.menu.ip.lm6f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espresso_lite_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espresso_lite_v2.menu.ip.hb6f.build.lwip_include=lwip2/include -espresso_lite_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espresso_lite_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espresso_lite_v2.menu.ip.hb1=v1.4 Higher Bandwidth -espresso_lite_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espresso_lite_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.ip.src=v1.4 Compile from source -espresso_lite_v2.menu.ip.src.build.lwip_lib=-llwip_src -espresso_lite_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espresso_lite_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espresso_lite_v2.menu.dbg.Disabled=Disabled -espresso_lite_v2.menu.dbg.Disabled.build.debug_port= -espresso_lite_v2.menu.dbg.Serial=Serial -espresso_lite_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espresso_lite_v2.menu.dbg.Serial1=Serial1 -espresso_lite_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espresso_lite_v2.menu.lvl.None____=None -espresso_lite_v2.menu.lvl.None____.build.debug_level= -espresso_lite_v2.menu.lvl.SSL=SSL -espresso_lite_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espresso_lite_v2.menu.lvl.TLS_MEM=TLS_MEM -espresso_lite_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espresso_lite_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espresso_lite_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espresso_lite_v2.menu.lvl.CORE=CORE -espresso_lite_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espresso_lite_v2.menu.lvl.WIFI=WIFI -espresso_lite_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espresso_lite_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espresso_lite_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espresso_lite_v2.menu.lvl.UPDATER=UPDATER -espresso_lite_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espresso_lite_v2.menu.lvl.OTA=OTA -espresso_lite_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espresso_lite_v2.menu.lvl.OOM=OOM -espresso_lite_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espresso_lite_v2.menu.lvl.MDNS=MDNS -espresso_lite_v2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espresso_lite_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espresso_lite_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espresso_lite_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espresso_lite_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espresso_lite_v2.menu.wipe.none=Only Sketch -espresso_lite_v2.menu.wipe.none.upload.erase_cmd= -espresso_lite_v2.menu.wipe.sdk=Sketch + WiFi Settings -espresso_lite_v2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -espresso_lite_v2.menu.wipe.all=All Flash Contents -espresso_lite_v2.menu.wipe.all.upload.erase_cmd=erase_flash -espresso_lite_v2.menu.baud.115200=115200 -espresso_lite_v2.menu.baud.115200.upload.speed=115200 -espresso_lite_v2.menu.baud.57600=57600 -espresso_lite_v2.menu.baud.57600.upload.speed=57600 -espresso_lite_v2.menu.baud.230400.linux=230400 -espresso_lite_v2.menu.baud.230400.macosx=230400 -espresso_lite_v2.menu.baud.230400.upload.speed=230400 -espresso_lite_v2.menu.baud.256000.windows=256000 -espresso_lite_v2.menu.baud.256000.upload.speed=256000 -espresso_lite_v2.menu.baud.460800.linux=460800 -espresso_lite_v2.menu.baud.460800.macosx=460800 -espresso_lite_v2.menu.baud.460800.upload.speed=460800 -espresso_lite_v2.menu.baud.512000.windows=512000 -espresso_lite_v2.menu.baud.512000.upload.speed=512000 -espresso_lite_v2.menu.baud.921600=921600 -espresso_lite_v2.menu.baud.921600.upload.speed=921600 -espresso_lite_v2.menu.baud.3000000=3000000 -espresso_lite_v2.menu.baud.3000000.upload.speed=3000000 - -############################################################## -phoenix_v1.name=Phoenix 1.0 -phoenix_v1.build.board=ESP8266_PHOENIX_V1 -phoenix_v1.build.variant=phoenix_v1 -phoenix_v1.upload.tool=esptool -phoenix_v1.upload.maximum_data_size=81920 -phoenix_v1.upload.wait_for_upload_port=true -phoenix_v1.upload.erase_cmd= -phoenix_v1.serial.disableDTR=true -phoenix_v1.serial.disableRTS=true -phoenix_v1.build.mcu=esp8266 -phoenix_v1.build.core=esp8266 -phoenix_v1.build.spiffs_pagesize=256 -phoenix_v1.build.debug_port= -phoenix_v1.build.debug_level= -phoenix_v1.menu.xtal.80=80 MHz -phoenix_v1.menu.xtal.80.build.f_cpu=80000000L -phoenix_v1.menu.xtal.160=160 MHz -phoenix_v1.menu.xtal.160.build.f_cpu=160000000L -phoenix_v1.menu.vt.flash=Flash -phoenix_v1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -phoenix_v1.menu.vt.heap=Heap -phoenix_v1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -phoenix_v1.menu.vt.iram=IRAM -phoenix_v1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -phoenix_v1.menu.exception.legacy=Legacy (new can return nullptr) -phoenix_v1.menu.exception.legacy.build.exception_flags=-fno-exceptions -phoenix_v1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -phoenix_v1.menu.exception.disabled=Disabled (new can abort) -phoenix_v1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -phoenix_v1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -phoenix_v1.menu.exception.enabled=Enabled -phoenix_v1.menu.exception.enabled.build.exception_flags=-fexceptions -phoenix_v1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -phoenix_v1.menu.ssl.all=All SSL ciphers (most compatible) -phoenix_v1.menu.ssl.all.build.sslflags= -phoenix_v1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -phoenix_v1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -phoenix_v1.build.flash_mode=dio -phoenix_v1.build.flash_flags=-DFLASHMODE_DIO -phoenix_v1.build.flash_freq=40 -phoenix_v1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -phoenix_v1.menu.eesz.4M2M.build.flash_size=4M -phoenix_v1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -phoenix_v1.menu.eesz.4M2M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M2M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_start=0x200000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -phoenix_v1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -phoenix_v1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -phoenix_v1.menu.eesz.4M3M.build.flash_size=4M -phoenix_v1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -phoenix_v1.menu.eesz.4M3M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M3M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_start=0x100000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -phoenix_v1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -phoenix_v1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -phoenix_v1.menu.eesz.4M1M.build.flash_size=4M -phoenix_v1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v1.menu.eesz.4M1M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M1M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_start=0x300000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -phoenix_v1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -phoenix_v1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -phoenix_v1.menu.eesz.4M.build.flash_size=4M -phoenix_v1.menu.eesz.4M.build.flash_size_bytes=0x400000 -phoenix_v1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -phoenix_v1.menu.eesz.4M.build.spiffs_pagesize=256 -phoenix_v1.menu.eesz.4M.upload.maximum_size=1044464 -phoenix_v1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -phoenix_v1.menu.ResetMethod.nodemcu=dtr (aka nodemcu) -phoenix_v1.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset -phoenix_v1.menu.ResetMethod.ck=no dtr (aka ck) -phoenix_v1.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset -phoenix_v1.menu.ip.lm2f=v2 Lower Memory -phoenix_v1.menu.ip.lm2f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -phoenix_v1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.hb2f=v2 Higher Bandwidth -phoenix_v1.menu.ip.hb2f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -phoenix_v1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.lm2n=v2 Lower Memory (no features) -phoenix_v1.menu.ip.lm2n.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -phoenix_v1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -phoenix_v1.menu.ip.hb2n.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -phoenix_v1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v1.menu.ip.lm6f=v2 IPv6 Lower Memory -phoenix_v1.menu.ip.lm6f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -phoenix_v1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -phoenix_v1.menu.ip.hb6f.build.lwip_include=lwip2/include -phoenix_v1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -phoenix_v1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v1.menu.ip.hb1=v1.4 Higher Bandwidth -phoenix_v1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -phoenix_v1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.ip.src=v1.4 Compile from source -phoenix_v1.menu.ip.src.build.lwip_lib=-llwip_src -phoenix_v1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v1.menu.dbg.Disabled=Disabled -phoenix_v1.menu.dbg.Disabled.build.debug_port= -phoenix_v1.menu.dbg.Serial=Serial -phoenix_v1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v1.menu.dbg.Serial1=Serial1 -phoenix_v1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v1.menu.lvl.None____=None -phoenix_v1.menu.lvl.None____.build.debug_level= -phoenix_v1.menu.lvl.SSL=SSL -phoenix_v1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v1.menu.lvl.TLS_MEM=TLS_MEM -phoenix_v1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -phoenix_v1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.HTTP_SERVER=HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v1.menu.lvl.CORE=CORE -phoenix_v1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v1.menu.lvl.WIFI=WIFI -phoenix_v1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -phoenix_v1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v1.menu.lvl.UPDATER=UPDATER -phoenix_v1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v1.menu.lvl.OTA=OTA -phoenix_v1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v1.menu.lvl.OOM=OOM -phoenix_v1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -phoenix_v1.menu.lvl.MDNS=MDNS -phoenix_v1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -phoenix_v1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -phoenix_v1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -phoenix_v1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v1.menu.wipe.none=Only Sketch -phoenix_v1.menu.wipe.none.upload.erase_cmd= -phoenix_v1.menu.wipe.sdk=Sketch + WiFi Settings -phoenix_v1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -phoenix_v1.menu.wipe.all=All Flash Contents -phoenix_v1.menu.wipe.all.upload.erase_cmd=erase_flash -phoenix_v1.menu.baud.115200=115200 -phoenix_v1.menu.baud.115200.upload.speed=115200 -phoenix_v1.menu.baud.57600=57600 -phoenix_v1.menu.baud.57600.upload.speed=57600 -phoenix_v1.menu.baud.230400.linux=230400 -phoenix_v1.menu.baud.230400.macosx=230400 -phoenix_v1.menu.baud.230400.upload.speed=230400 -phoenix_v1.menu.baud.256000.windows=256000 -phoenix_v1.menu.baud.256000.upload.speed=256000 -phoenix_v1.menu.baud.460800.linux=460800 -phoenix_v1.menu.baud.460800.macosx=460800 -phoenix_v1.menu.baud.460800.upload.speed=460800 -phoenix_v1.menu.baud.512000.windows=512000 -phoenix_v1.menu.baud.512000.upload.speed=512000 -phoenix_v1.menu.baud.921600=921600 -phoenix_v1.menu.baud.921600.upload.speed=921600 -phoenix_v1.menu.baud.3000000=3000000 -phoenix_v1.menu.baud.3000000.upload.speed=3000000 - -############################################################## -phoenix_v2.name=Phoenix 2.0 -phoenix_v2.build.board=ESP8266_PHOENIX_V2 -phoenix_v2.build.variant=phoenix_v2 -phoenix_v2.upload.tool=esptool -phoenix_v2.upload.maximum_data_size=81920 -phoenix_v2.upload.wait_for_upload_port=true -phoenix_v2.upload.erase_cmd= -phoenix_v2.serial.disableDTR=true -phoenix_v2.serial.disableRTS=true -phoenix_v2.build.mcu=esp8266 -phoenix_v2.build.core=esp8266 -phoenix_v2.build.spiffs_pagesize=256 -phoenix_v2.build.debug_port= -phoenix_v2.build.debug_level= -phoenix_v2.menu.xtal.80=80 MHz -phoenix_v2.menu.xtal.80.build.f_cpu=80000000L -phoenix_v2.menu.xtal.160=160 MHz -phoenix_v2.menu.xtal.160.build.f_cpu=160000000L -phoenix_v2.menu.vt.flash=Flash -phoenix_v2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -phoenix_v2.menu.vt.heap=Heap -phoenix_v2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -phoenix_v2.menu.vt.iram=IRAM -phoenix_v2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -phoenix_v2.menu.exception.legacy=Legacy (new can return nullptr) -phoenix_v2.menu.exception.legacy.build.exception_flags=-fno-exceptions -phoenix_v2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -phoenix_v2.menu.exception.disabled=Disabled (new can abort) -phoenix_v2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -phoenix_v2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -phoenix_v2.menu.exception.enabled=Enabled -phoenix_v2.menu.exception.enabled.build.exception_flags=-fexceptions -phoenix_v2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -phoenix_v2.menu.ssl.all=All SSL ciphers (most compatible) -phoenix_v2.menu.ssl.all.build.sslflags= -phoenix_v2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -phoenix_v2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -phoenix_v2.build.flash_mode=dio -phoenix_v2.build.flash_flags=-DFLASHMODE_DIO -phoenix_v2.build.flash_freq=40 -phoenix_v2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -phoenix_v2.menu.eesz.4M2M.build.flash_size=4M -phoenix_v2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -phoenix_v2.menu.eesz.4M2M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M2M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_start=0x200000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -phoenix_v2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -phoenix_v2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -phoenix_v2.menu.eesz.4M3M.build.flash_size=4M -phoenix_v2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -phoenix_v2.menu.eesz.4M3M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M3M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_start=0x100000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -phoenix_v2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -phoenix_v2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -phoenix_v2.menu.eesz.4M1M.build.flash_size=4M -phoenix_v2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -phoenix_v2.menu.eesz.4M1M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M1M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_start=0x300000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -phoenix_v2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -phoenix_v2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -phoenix_v2.menu.eesz.4M.build.flash_size=4M -phoenix_v2.menu.eesz.4M.build.flash_size_bytes=0x400000 -phoenix_v2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -phoenix_v2.menu.eesz.4M.build.spiffs_pagesize=256 -phoenix_v2.menu.eesz.4M.upload.maximum_size=1044464 -phoenix_v2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -phoenix_v2.menu.ResetMethod.nodemcu=dtr (aka nodemcu) -phoenix_v2.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset -phoenix_v2.menu.ResetMethod.ck=no dtr (aka ck) -phoenix_v2.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset -phoenix_v2.menu.ip.lm2f=v2 Lower Memory -phoenix_v2.menu.ip.lm2f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -phoenix_v2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.hb2f=v2 Higher Bandwidth -phoenix_v2.menu.ip.hb2f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -phoenix_v2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.lm2n=v2 Lower Memory (no features) -phoenix_v2.menu.ip.lm2n.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -phoenix_v2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -phoenix_v2.menu.ip.hb2n.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -phoenix_v2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -phoenix_v2.menu.ip.lm6f=v2 IPv6 Lower Memory -phoenix_v2.menu.ip.lm6f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -phoenix_v2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -phoenix_v2.menu.ip.hb6f.build.lwip_include=lwip2/include -phoenix_v2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -phoenix_v2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -phoenix_v2.menu.ip.hb1=v1.4 Higher Bandwidth -phoenix_v2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -phoenix_v2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.ip.src=v1.4 Compile from source -phoenix_v2.menu.ip.src.build.lwip_lib=-llwip_src -phoenix_v2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -phoenix_v2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -phoenix_v2.menu.dbg.Disabled=Disabled -phoenix_v2.menu.dbg.Disabled.build.debug_port= -phoenix_v2.menu.dbg.Serial=Serial -phoenix_v2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -phoenix_v2.menu.dbg.Serial1=Serial1 -phoenix_v2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -phoenix_v2.menu.lvl.None____=None -phoenix_v2.menu.lvl.None____.build.debug_level= -phoenix_v2.menu.lvl.SSL=SSL -phoenix_v2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -phoenix_v2.menu.lvl.TLS_MEM=TLS_MEM -phoenix_v2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -phoenix_v2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.HTTP_SERVER=HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -phoenix_v2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -phoenix_v2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -phoenix_v2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -phoenix_v2.menu.lvl.CORE=CORE -phoenix_v2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -phoenix_v2.menu.lvl.WIFI=WIFI -phoenix_v2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -phoenix_v2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -phoenix_v2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -phoenix_v2.menu.lvl.UPDATER=UPDATER -phoenix_v2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -phoenix_v2.menu.lvl.OTA=OTA -phoenix_v2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -phoenix_v2.menu.lvl.OOM=OOM -phoenix_v2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -phoenix_v2.menu.lvl.MDNS=MDNS -phoenix_v2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -phoenix_v2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -phoenix_v2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -phoenix_v2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -phoenix_v2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -phoenix_v2.menu.wipe.none=Only Sketch -phoenix_v2.menu.wipe.none.upload.erase_cmd= -phoenix_v2.menu.wipe.sdk=Sketch + WiFi Settings -phoenix_v2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -phoenix_v2.menu.wipe.all=All Flash Contents -phoenix_v2.menu.wipe.all.upload.erase_cmd=erase_flash -phoenix_v2.menu.baud.115200=115200 -phoenix_v2.menu.baud.115200.upload.speed=115200 -phoenix_v2.menu.baud.57600=57600 -phoenix_v2.menu.baud.57600.upload.speed=57600 -phoenix_v2.menu.baud.230400.linux=230400 -phoenix_v2.menu.baud.230400.macosx=230400 -phoenix_v2.menu.baud.230400.upload.speed=230400 -phoenix_v2.menu.baud.256000.windows=256000 -phoenix_v2.menu.baud.256000.upload.speed=256000 -phoenix_v2.menu.baud.460800.linux=460800 -phoenix_v2.menu.baud.460800.macosx=460800 -phoenix_v2.menu.baud.460800.upload.speed=460800 -phoenix_v2.menu.baud.512000.windows=512000 -phoenix_v2.menu.baud.512000.upload.speed=512000 -phoenix_v2.menu.baud.921600=921600 -phoenix_v2.menu.baud.921600.upload.speed=921600 -phoenix_v2.menu.baud.3000000=3000000 -phoenix_v2.menu.baud.3000000.upload.speed=3000000 - -############################################################## -nodemcu.name=NodeMCU 0.9 (ESP-12 Module) -nodemcu.build.board=ESP8266_NODEMCU -nodemcu.build.variant=nodemcu -nodemcu.upload.tool=esptool -nodemcu.upload.maximum_data_size=81920 -nodemcu.upload.wait_for_upload_port=true -nodemcu.upload.erase_cmd= -nodemcu.serial.disableDTR=true -nodemcu.serial.disableRTS=true -nodemcu.build.mcu=esp8266 -nodemcu.build.core=esp8266 -nodemcu.build.spiffs_pagesize=256 -nodemcu.build.debug_port= -nodemcu.build.debug_level= -nodemcu.menu.xtal.80=80 MHz -nodemcu.menu.xtal.80.build.f_cpu=80000000L -nodemcu.menu.xtal.160=160 MHz -nodemcu.menu.xtal.160.build.f_cpu=160000000L -nodemcu.menu.vt.flash=Flash -nodemcu.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -nodemcu.menu.vt.heap=Heap -nodemcu.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -nodemcu.menu.vt.iram=IRAM -nodemcu.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -nodemcu.menu.exception.legacy=Legacy (new can return nullptr) -nodemcu.menu.exception.legacy.build.exception_flags=-fno-exceptions -nodemcu.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -nodemcu.menu.exception.disabled=Disabled (new can abort) -nodemcu.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -nodemcu.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -nodemcu.menu.exception.enabled=Enabled -nodemcu.menu.exception.enabled.build.exception_flags=-fexceptions -nodemcu.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -nodemcu.menu.ssl.all=All SSL ciphers (most compatible) -nodemcu.menu.ssl.all.build.sslflags= -nodemcu.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -nodemcu.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -nodemcu.upload.resetmethod=--before default_reset --after hard_reset -nodemcu.build.flash_mode=qio -nodemcu.build.flash_flags=-DFLASHMODE_QIO -nodemcu.build.flash_freq=40 -nodemcu.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -nodemcu.menu.eesz.4M2M.build.flash_size=4M -nodemcu.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -nodemcu.menu.eesz.4M2M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M2M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M2M.build.spiffs_start=0x200000 -nodemcu.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -nodemcu.menu.eesz.4M2M.build.spiffs_blocksize=8192 -nodemcu.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -nodemcu.menu.eesz.4M3M.build.flash_size=4M -nodemcu.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -nodemcu.menu.eesz.4M3M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M3M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M3M.build.spiffs_start=0x100000 -nodemcu.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -nodemcu.menu.eesz.4M3M.build.spiffs_blocksize=8192 -nodemcu.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -nodemcu.menu.eesz.4M1M.build.flash_size=4M -nodemcu.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcu.menu.eesz.4M1M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M1M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -nodemcu.menu.eesz.4M1M.build.spiffs_start=0x300000 -nodemcu.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -nodemcu.menu.eesz.4M1M.build.spiffs_blocksize=8192 -nodemcu.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -nodemcu.menu.eesz.4M.build.flash_size=4M -nodemcu.menu.eesz.4M.build.flash_size_bytes=0x400000 -nodemcu.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -nodemcu.menu.eesz.4M.build.spiffs_pagesize=256 -nodemcu.menu.eesz.4M.upload.maximum_size=1044464 -nodemcu.menu.eesz.4M.build.rfcal_addr=0x3FC000 -nodemcu.menu.ip.lm2f=v2 Lower Memory -nodemcu.menu.ip.lm2f.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -nodemcu.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcu.menu.ip.hb2f=v2 Higher Bandwidth -nodemcu.menu.ip.hb2f.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -nodemcu.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcu.menu.ip.lm2n=v2 Lower Memory (no features) -nodemcu.menu.ip.lm2n.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -nodemcu.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcu.menu.ip.hb2n=v2 Higher Bandwidth (no features) -nodemcu.menu.ip.hb2n.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -nodemcu.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcu.menu.ip.lm6f=v2 IPv6 Lower Memory -nodemcu.menu.ip.lm6f.build.lwip_include=lwip2/include -nodemcu.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -nodemcu.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcu.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -nodemcu.menu.ip.hb6f.build.lwip_include=lwip2/include -nodemcu.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -nodemcu.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcu.menu.ip.hb1=v1.4 Higher Bandwidth -nodemcu.menu.ip.hb1.build.lwip_lib=-llwip_gcc -nodemcu.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.ip.src=v1.4 Compile from source -nodemcu.menu.ip.src.build.lwip_lib=-llwip_src -nodemcu.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcu.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcu.menu.dbg.Disabled=Disabled -nodemcu.menu.dbg.Disabled.build.debug_port= -nodemcu.menu.dbg.Serial=Serial -nodemcu.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcu.menu.dbg.Serial1=Serial1 -nodemcu.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcu.menu.lvl.None____=None -nodemcu.menu.lvl.None____.build.debug_level= -nodemcu.menu.lvl.SSL=SSL -nodemcu.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcu.menu.lvl.TLS_MEM=TLS_MEM -nodemcu.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcu.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -nodemcu.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.HTTP_SERVER=HTTP_SERVER -nodemcu.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -nodemcu.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcu.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcu.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcu.menu.lvl.CORE=CORE -nodemcu.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcu.menu.lvl.WIFI=WIFI -nodemcu.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcu.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -nodemcu.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcu.menu.lvl.UPDATER=UPDATER -nodemcu.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcu.menu.lvl.OTA=OTA -nodemcu.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcu.menu.lvl.OOM=OOM -nodemcu.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -nodemcu.menu.lvl.MDNS=MDNS -nodemcu.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -nodemcu.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -nodemcu.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -nodemcu.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcu.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcu.menu.wipe.none=Only Sketch -nodemcu.menu.wipe.none.upload.erase_cmd= -nodemcu.menu.wipe.sdk=Sketch + WiFi Settings -nodemcu.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -nodemcu.menu.wipe.all=All Flash Contents -nodemcu.menu.wipe.all.upload.erase_cmd=erase_flash -nodemcu.menu.baud.115200=115200 -nodemcu.menu.baud.115200.upload.speed=115200 -nodemcu.menu.baud.57600=57600 -nodemcu.menu.baud.57600.upload.speed=57600 -nodemcu.menu.baud.230400.linux=230400 -nodemcu.menu.baud.230400.macosx=230400 -nodemcu.menu.baud.230400.upload.speed=230400 -nodemcu.menu.baud.256000.windows=256000 -nodemcu.menu.baud.256000.upload.speed=256000 -nodemcu.menu.baud.460800.linux=460800 -nodemcu.menu.baud.460800.macosx=460800 -nodemcu.menu.baud.460800.upload.speed=460800 -nodemcu.menu.baud.512000.windows=512000 -nodemcu.menu.baud.512000.upload.speed=512000 -nodemcu.menu.baud.921600=921600 -nodemcu.menu.baud.921600.upload.speed=921600 -nodemcu.menu.baud.3000000=3000000 -nodemcu.menu.baud.3000000.upload.speed=3000000 - -############################################################## -nodemcuv2.name=NodeMCU 1.0 (ESP-12E Module) -nodemcuv2.build.board=ESP8266_NODEMCU -nodemcuv2.build.variant=nodemcu -nodemcuv2.upload.tool=esptool -nodemcuv2.upload.maximum_data_size=81920 -nodemcuv2.upload.wait_for_upload_port=true -nodemcuv2.upload.erase_cmd= -nodemcuv2.serial.disableDTR=true -nodemcuv2.serial.disableRTS=true -nodemcuv2.build.mcu=esp8266 -nodemcuv2.build.core=esp8266 -nodemcuv2.build.spiffs_pagesize=256 -nodemcuv2.build.debug_port= -nodemcuv2.build.debug_level= -nodemcuv2.menu.xtal.80=80 MHz -nodemcuv2.menu.xtal.80.build.f_cpu=80000000L -nodemcuv2.menu.xtal.160=160 MHz -nodemcuv2.menu.xtal.160.build.f_cpu=160000000L -nodemcuv2.menu.vt.flash=Flash -nodemcuv2.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -nodemcuv2.menu.vt.heap=Heap -nodemcuv2.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -nodemcuv2.menu.vt.iram=IRAM -nodemcuv2.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -nodemcuv2.menu.exception.legacy=Legacy (new can return nullptr) -nodemcuv2.menu.exception.legacy.build.exception_flags=-fno-exceptions -nodemcuv2.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -nodemcuv2.menu.exception.disabled=Disabled (new can abort) -nodemcuv2.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -nodemcuv2.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -nodemcuv2.menu.exception.enabled=Enabled -nodemcuv2.menu.exception.enabled.build.exception_flags=-fexceptions -nodemcuv2.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -nodemcuv2.menu.ssl.all=All SSL ciphers (most compatible) -nodemcuv2.menu.ssl.all.build.sslflags= -nodemcuv2.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -nodemcuv2.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -nodemcuv2.upload.resetmethod=--before default_reset --after hard_reset -nodemcuv2.build.flash_mode=dio -nodemcuv2.build.flash_flags=-DFLASHMODE_DIO -nodemcuv2.build.flash_freq=40 -nodemcuv2.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -nodemcuv2.menu.eesz.4M2M.build.flash_size=4M -nodemcuv2.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -nodemcuv2.menu.eesz.4M2M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M2M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_start=0x200000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -nodemcuv2.menu.eesz.4M2M.build.spiffs_blocksize=8192 -nodemcuv2.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -nodemcuv2.menu.eesz.4M3M.build.flash_size=4M -nodemcuv2.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -nodemcuv2.menu.eesz.4M3M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M3M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_start=0x100000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -nodemcuv2.menu.eesz.4M3M.build.spiffs_blocksize=8192 -nodemcuv2.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -nodemcuv2.menu.eesz.4M1M.build.flash_size=4M -nodemcuv2.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -nodemcuv2.menu.eesz.4M1M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M1M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_start=0x300000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -nodemcuv2.menu.eesz.4M1M.build.spiffs_blocksize=8192 -nodemcuv2.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -nodemcuv2.menu.eesz.4M.build.flash_size=4M -nodemcuv2.menu.eesz.4M.build.flash_size_bytes=0x400000 -nodemcuv2.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -nodemcuv2.menu.eesz.4M.build.spiffs_pagesize=256 -nodemcuv2.menu.eesz.4M.upload.maximum_size=1044464 -nodemcuv2.menu.eesz.4M.build.rfcal_addr=0x3FC000 -nodemcuv2.menu.led.2=2 -nodemcuv2.menu.led.2.build.led=-DLED_BUILTIN=2 -nodemcuv2.menu.led.16=16 -nodemcuv2.menu.led.16.build.led=-DLED_BUILTIN=16 -nodemcuv2.menu.ip.lm2f=v2 Lower Memory -nodemcuv2.menu.ip.lm2f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -nodemcuv2.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.hb2f=v2 Higher Bandwidth -nodemcuv2.menu.ip.hb2f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -nodemcuv2.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.lm2n=v2 Lower Memory (no features) -nodemcuv2.menu.ip.lm2n.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -nodemcuv2.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.hb2n=v2 Higher Bandwidth (no features) -nodemcuv2.menu.ip.hb2n.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -nodemcuv2.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -nodemcuv2.menu.ip.lm6f=v2 IPv6 Lower Memory -nodemcuv2.menu.ip.lm6f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -nodemcuv2.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcuv2.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -nodemcuv2.menu.ip.hb6f.build.lwip_include=lwip2/include -nodemcuv2.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -nodemcuv2.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -nodemcuv2.menu.ip.hb1=v1.4 Higher Bandwidth -nodemcuv2.menu.ip.hb1.build.lwip_lib=-llwip_gcc -nodemcuv2.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.ip.src=v1.4 Compile from source -nodemcuv2.menu.ip.src.build.lwip_lib=-llwip_src -nodemcuv2.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -nodemcuv2.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -nodemcuv2.menu.dbg.Disabled=Disabled -nodemcuv2.menu.dbg.Disabled.build.debug_port= -nodemcuv2.menu.dbg.Serial=Serial -nodemcuv2.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -nodemcuv2.menu.dbg.Serial1=Serial1 -nodemcuv2.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -nodemcuv2.menu.lvl.None____=None -nodemcuv2.menu.lvl.None____.build.debug_level= -nodemcuv2.menu.lvl.SSL=SSL -nodemcuv2.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -nodemcuv2.menu.lvl.TLS_MEM=TLS_MEM -nodemcuv2.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -nodemcuv2.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.HTTP_SERVER=HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -nodemcuv2.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -nodemcuv2.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -nodemcuv2.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -nodemcuv2.menu.lvl.CORE=CORE -nodemcuv2.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -nodemcuv2.menu.lvl.WIFI=WIFI -nodemcuv2.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -nodemcuv2.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -nodemcuv2.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -nodemcuv2.menu.lvl.UPDATER=UPDATER -nodemcuv2.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -nodemcuv2.menu.lvl.OTA=OTA -nodemcuv2.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -nodemcuv2.menu.lvl.OOM=OOM -nodemcuv2.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -nodemcuv2.menu.lvl.MDNS=MDNS -nodemcuv2.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -nodemcuv2.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -nodemcuv2.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -nodemcuv2.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -nodemcuv2.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -nodemcuv2.menu.wipe.none=Only Sketch -nodemcuv2.menu.wipe.none.upload.erase_cmd= -nodemcuv2.menu.wipe.sdk=Sketch + WiFi Settings -nodemcuv2.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -nodemcuv2.menu.wipe.all=All Flash Contents -nodemcuv2.menu.wipe.all.upload.erase_cmd=erase_flash -nodemcuv2.menu.baud.115200=115200 -nodemcuv2.menu.baud.115200.upload.speed=115200 -nodemcuv2.menu.baud.57600=57600 -nodemcuv2.menu.baud.57600.upload.speed=57600 -nodemcuv2.menu.baud.230400.linux=230400 -nodemcuv2.menu.baud.230400.macosx=230400 -nodemcuv2.menu.baud.230400.upload.speed=230400 -nodemcuv2.menu.baud.256000.windows=256000 -nodemcuv2.menu.baud.256000.upload.speed=256000 -nodemcuv2.menu.baud.460800.linux=460800 -nodemcuv2.menu.baud.460800.macosx=460800 -nodemcuv2.menu.baud.460800.upload.speed=460800 -nodemcuv2.menu.baud.512000.windows=512000 -nodemcuv2.menu.baud.512000.upload.speed=512000 -nodemcuv2.menu.baud.921600=921600 -nodemcuv2.menu.baud.921600.upload.speed=921600 -nodemcuv2.menu.baud.3000000=3000000 -nodemcuv2.menu.baud.3000000.upload.speed=3000000 - -############################################################## -modwifi.name=Olimex MOD-WIFI-ESP8266(-DEV) -modwifi.build.board=MOD_WIFI_ESP8266 -modwifi.build.variant=modwifi -modwifi.upload.tool=esptool -modwifi.upload.maximum_data_size=81920 -modwifi.upload.wait_for_upload_port=true -modwifi.upload.erase_cmd= -modwifi.serial.disableDTR=true -modwifi.serial.disableRTS=true -modwifi.build.mcu=esp8266 -modwifi.build.core=esp8266 -modwifi.build.spiffs_pagesize=256 -modwifi.build.debug_port= -modwifi.build.debug_level= -modwifi.menu.xtal.80=80 MHz -modwifi.menu.xtal.80.build.f_cpu=80000000L -modwifi.menu.xtal.160=160 MHz -modwifi.menu.xtal.160.build.f_cpu=160000000L -modwifi.menu.vt.flash=Flash -modwifi.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -modwifi.menu.vt.heap=Heap -modwifi.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -modwifi.menu.vt.iram=IRAM -modwifi.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -modwifi.menu.exception.legacy=Legacy (new can return nullptr) -modwifi.menu.exception.legacy.build.exception_flags=-fno-exceptions -modwifi.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -modwifi.menu.exception.disabled=Disabled (new can abort) -modwifi.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -modwifi.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -modwifi.menu.exception.enabled=Enabled -modwifi.menu.exception.enabled.build.exception_flags=-fexceptions -modwifi.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -modwifi.menu.ssl.all=All SSL ciphers (most compatible) -modwifi.menu.ssl.all.build.sslflags= -modwifi.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -modwifi.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -modwifi.upload.resetmethod=--before no_reset --after soft_reset -modwifi.build.flash_mode=qio -modwifi.build.flash_flags=-DFLASHMODE_QIO -modwifi.build.flash_freq=40 -modwifi.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) -modwifi.menu.eesz.2M64.build.flash_size=2M -modwifi.menu.eesz.2M64.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld -modwifi.menu.eesz.2M64.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M64.upload.maximum_size=1044464 -modwifi.menu.eesz.2M64.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M64.build.spiffs_start=0x1F0000 -modwifi.menu.eesz.2M64.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M64.build.spiffs_blocksize=4096 -modwifi.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) -modwifi.menu.eesz.2M128.build.flash_size=2M -modwifi.menu.eesz.2M128.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -modwifi.menu.eesz.2M128.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M128.upload.maximum_size=1044464 -modwifi.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M128.build.spiffs_start=0x1E0000 -modwifi.menu.eesz.2M128.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M128.build.spiffs_blocksize=4096 -modwifi.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) -modwifi.menu.eesz.2M256.build.flash_size=2M -modwifi.menu.eesz.2M256.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -modwifi.menu.eesz.2M256.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M256.upload.maximum_size=1044464 -modwifi.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M256.build.spiffs_start=0x1C0000 -modwifi.menu.eesz.2M256.build.spiffs_end=0x1FB000 -modwifi.menu.eesz.2M256.build.spiffs_blocksize=4096 -modwifi.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) -modwifi.menu.eesz.2M512.build.flash_size=2M -modwifi.menu.eesz.2M512.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -modwifi.menu.eesz.2M512.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M512.upload.maximum_size=1044464 -modwifi.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M512.build.spiffs_start=0x180000 -modwifi.menu.eesz.2M512.build.spiffs_end=0x1FA000 -modwifi.menu.eesz.2M512.build.spiffs_blocksize=8192 -modwifi.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) -modwifi.menu.eesz.2M1M.build.flash_size=2M -modwifi.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -modwifi.menu.eesz.2M1M.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M1M.upload.maximum_size=1044464 -modwifi.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -modwifi.menu.eesz.2M1M.build.spiffs_start=0x100000 -modwifi.menu.eesz.2M1M.build.spiffs_end=0x1FA000 -modwifi.menu.eesz.2M1M.build.spiffs_blocksize=8192 -modwifi.menu.eesz.2M=2MB (FS:none OTA:~1019KB) -modwifi.menu.eesz.2M.build.flash_size=2M -modwifi.menu.eesz.2M.build.flash_size_bytes=0x200000 -modwifi.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -modwifi.menu.eesz.2M.build.spiffs_pagesize=256 -modwifi.menu.eesz.2M.upload.maximum_size=1044464 -modwifi.menu.eesz.2M.build.rfcal_addr=0x1FC000 -modwifi.menu.ip.lm2f=v2 Lower Memory -modwifi.menu.ip.lm2f.build.lwip_include=lwip2/include -modwifi.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -modwifi.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -modwifi.menu.ip.hb2f=v2 Higher Bandwidth -modwifi.menu.ip.hb2f.build.lwip_include=lwip2/include -modwifi.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -modwifi.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -modwifi.menu.ip.lm2n=v2 Lower Memory (no features) -modwifi.menu.ip.lm2n.build.lwip_include=lwip2/include -modwifi.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -modwifi.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -modwifi.menu.ip.hb2n=v2 Higher Bandwidth (no features) -modwifi.menu.ip.hb2n.build.lwip_include=lwip2/include -modwifi.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -modwifi.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -modwifi.menu.ip.lm6f=v2 IPv6 Lower Memory -modwifi.menu.ip.lm6f.build.lwip_include=lwip2/include -modwifi.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -modwifi.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -modwifi.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -modwifi.menu.ip.hb6f.build.lwip_include=lwip2/include -modwifi.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -modwifi.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -modwifi.menu.ip.hb1=v1.4 Higher Bandwidth -modwifi.menu.ip.hb1.build.lwip_lib=-llwip_gcc -modwifi.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.ip.src=v1.4 Compile from source -modwifi.menu.ip.src.build.lwip_lib=-llwip_src -modwifi.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -modwifi.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -modwifi.menu.dbg.Disabled=Disabled -modwifi.menu.dbg.Disabled.build.debug_port= -modwifi.menu.dbg.Serial=Serial -modwifi.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -modwifi.menu.dbg.Serial1=Serial1 -modwifi.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -modwifi.menu.lvl.None____=None -modwifi.menu.lvl.None____.build.debug_level= -modwifi.menu.lvl.SSL=SSL -modwifi.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -modwifi.menu.lvl.TLS_MEM=TLS_MEM -modwifi.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -modwifi.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -modwifi.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.HTTP_SERVER=HTTP_SERVER -modwifi.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -modwifi.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -modwifi.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -modwifi.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -modwifi.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -modwifi.menu.lvl.CORE=CORE -modwifi.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -modwifi.menu.lvl.WIFI=WIFI -modwifi.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -modwifi.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -modwifi.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -modwifi.menu.lvl.UPDATER=UPDATER -modwifi.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -modwifi.menu.lvl.OTA=OTA -modwifi.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -modwifi.menu.lvl.OOM=OOM -modwifi.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -modwifi.menu.lvl.MDNS=MDNS -modwifi.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -modwifi.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -modwifi.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -modwifi.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -modwifi.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -modwifi.menu.wipe.none=Only Sketch -modwifi.menu.wipe.none.upload.erase_cmd= -modwifi.menu.wipe.sdk=Sketch + WiFi Settings -modwifi.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -modwifi.menu.wipe.all=All Flash Contents -modwifi.menu.wipe.all.upload.erase_cmd=erase_flash -modwifi.menu.baud.115200=115200 -modwifi.menu.baud.115200.upload.speed=115200 -modwifi.menu.baud.57600=57600 -modwifi.menu.baud.57600.upload.speed=57600 -modwifi.menu.baud.230400.linux=230400 -modwifi.menu.baud.230400.macosx=230400 -modwifi.menu.baud.230400.upload.speed=230400 -modwifi.menu.baud.256000.windows=256000 -modwifi.menu.baud.256000.upload.speed=256000 -modwifi.menu.baud.460800.linux=460800 -modwifi.menu.baud.460800.macosx=460800 -modwifi.menu.baud.460800.upload.speed=460800 -modwifi.menu.baud.512000.windows=512000 -modwifi.menu.baud.512000.upload.speed=512000 -modwifi.menu.baud.921600=921600 -modwifi.menu.baud.921600.upload.speed=921600 -modwifi.menu.baud.3000000=3000000 -modwifi.menu.baud.3000000.upload.speed=3000000 - -############################################################## -thing.name=SparkFun ESP8266 Thing -thing.build.board=ESP8266_THING -thing.build.variant=thing -thing.upload.tool=esptool -thing.upload.maximum_data_size=81920 -thing.upload.wait_for_upload_port=true -thing.upload.erase_cmd= -thing.serial.disableDTR=true -thing.serial.disableRTS=true -thing.build.mcu=esp8266 -thing.build.core=esp8266 -thing.build.spiffs_pagesize=256 -thing.build.debug_port= -thing.build.debug_level= -thing.menu.xtal.80=80 MHz -thing.menu.xtal.80.build.f_cpu=80000000L -thing.menu.xtal.160=160 MHz -thing.menu.xtal.160.build.f_cpu=160000000L -thing.menu.vt.flash=Flash -thing.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -thing.menu.vt.heap=Heap -thing.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -thing.menu.vt.iram=IRAM -thing.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -thing.menu.exception.legacy=Legacy (new can return nullptr) -thing.menu.exception.legacy.build.exception_flags=-fno-exceptions -thing.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -thing.menu.exception.disabled=Disabled (new can abort) -thing.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -thing.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -thing.menu.exception.enabled=Enabled -thing.menu.exception.enabled.build.exception_flags=-fexceptions -thing.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -thing.menu.ssl.all=All SSL ciphers (most compatible) -thing.menu.ssl.all.build.sslflags= -thing.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -thing.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -thing.upload.resetmethod=--before no_reset --after soft_reset -thing.build.flash_mode=qio -thing.build.flash_flags=-DFLASHMODE_QIO -thing.build.flash_freq=40 -thing.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) -thing.menu.eesz.512K32.build.flash_size=512K -thing.menu.eesz.512K32.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -thing.menu.eesz.512K32.build.spiffs_pagesize=256 -thing.menu.eesz.512K32.upload.maximum_size=466928 -thing.menu.eesz.512K32.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K32.build.spiffs_start=0x73000 -thing.menu.eesz.512K32.build.spiffs_end=0x7B000 -thing.menu.eesz.512K32.build.spiffs_blocksize=4096 -thing.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) -thing.menu.eesz.512K64.build.flash_size=512K -thing.menu.eesz.512K64.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -thing.menu.eesz.512K64.build.spiffs_pagesize=256 -thing.menu.eesz.512K64.upload.maximum_size=434160 -thing.menu.eesz.512K64.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K64.build.spiffs_start=0x6B000 -thing.menu.eesz.512K64.build.spiffs_end=0x7B000 -thing.menu.eesz.512K64.build.spiffs_blocksize=4096 -thing.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) -thing.menu.eesz.512K128.build.flash_size=512K -thing.menu.eesz.512K128.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -thing.menu.eesz.512K128.build.spiffs_pagesize=256 -thing.menu.eesz.512K128.upload.maximum_size=368624 -thing.menu.eesz.512K128.build.rfcal_addr=0x7C000 -thing.menu.eesz.512K128.build.spiffs_start=0x5B000 -thing.menu.eesz.512K128.build.spiffs_end=0x7B000 -thing.menu.eesz.512K128.build.spiffs_blocksize=4096 -thing.menu.eesz.512K=512KB (FS:none OTA:~246KB) -thing.menu.eesz.512K.build.flash_size=512K -thing.menu.eesz.512K.build.flash_size_bytes=0x80000 -thing.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -thing.menu.eesz.512K.build.spiffs_pagesize=256 -thing.menu.eesz.512K.upload.maximum_size=499696 -thing.menu.eesz.512K.build.rfcal_addr=0x7C000 -thing.menu.ip.lm2f=v2 Lower Memory -thing.menu.ip.lm2f.build.lwip_include=lwip2/include -thing.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -thing.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thing.menu.ip.hb2f=v2 Higher Bandwidth -thing.menu.ip.hb2f.build.lwip_include=lwip2/include -thing.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -thing.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thing.menu.ip.lm2n=v2 Lower Memory (no features) -thing.menu.ip.lm2n.build.lwip_include=lwip2/include -thing.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -thing.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thing.menu.ip.hb2n=v2 Higher Bandwidth (no features) -thing.menu.ip.hb2n.build.lwip_include=lwip2/include -thing.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -thing.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thing.menu.ip.lm6f=v2 IPv6 Lower Memory -thing.menu.ip.lm6f.build.lwip_include=lwip2/include -thing.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -thing.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thing.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -thing.menu.ip.hb6f.build.lwip_include=lwip2/include -thing.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -thing.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thing.menu.ip.hb1=v1.4 Higher Bandwidth -thing.menu.ip.hb1.build.lwip_lib=-llwip_gcc -thing.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.ip.src=v1.4 Compile from source -thing.menu.ip.src.build.lwip_lib=-llwip_src -thing.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -thing.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thing.menu.dbg.Disabled=Disabled -thing.menu.dbg.Disabled.build.debug_port= -thing.menu.dbg.Serial=Serial -thing.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thing.menu.dbg.Serial1=Serial1 -thing.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thing.menu.lvl.None____=None -thing.menu.lvl.None____.build.debug_level= -thing.menu.lvl.SSL=SSL -thing.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -thing.menu.lvl.TLS_MEM=TLS_MEM -thing.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thing.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -thing.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.HTTP_SERVER=HTTP_SERVER -thing.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -thing.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thing.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thing.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -thing.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thing.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thing.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thing.menu.lvl.CORE=CORE -thing.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -thing.menu.lvl.WIFI=WIFI -thing.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thing.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -thing.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thing.menu.lvl.UPDATER=UPDATER -thing.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thing.menu.lvl.OTA=OTA -thing.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -thing.menu.lvl.OOM=OOM -thing.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -thing.menu.lvl.MDNS=MDNS -thing.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -thing.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -thing.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -thing.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -thing.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thing.menu.wipe.none=Only Sketch -thing.menu.wipe.none.upload.erase_cmd= -thing.menu.wipe.sdk=Sketch + WiFi Settings -thing.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -thing.menu.wipe.all=All Flash Contents -thing.menu.wipe.all.upload.erase_cmd=erase_flash -thing.menu.baud.115200=115200 -thing.menu.baud.115200.upload.speed=115200 -thing.menu.baud.57600=57600 -thing.menu.baud.57600.upload.speed=57600 -thing.menu.baud.230400.linux=230400 -thing.menu.baud.230400.macosx=230400 -thing.menu.baud.230400.upload.speed=230400 -thing.menu.baud.256000.windows=256000 -thing.menu.baud.256000.upload.speed=256000 -thing.menu.baud.460800.linux=460800 -thing.menu.baud.460800.macosx=460800 -thing.menu.baud.460800.upload.speed=460800 -thing.menu.baud.512000.windows=512000 -thing.menu.baud.512000.upload.speed=512000 -thing.menu.baud.921600=921600 -thing.menu.baud.921600.upload.speed=921600 -thing.menu.baud.3000000=3000000 -thing.menu.baud.3000000.upload.speed=3000000 - -############################################################## -thingdev.name=SparkFun ESP8266 Thing Dev -thingdev.build.board=ESP8266_THING_DEV -thingdev.build.variant=thing -thingdev.upload.tool=esptool -thingdev.upload.maximum_data_size=81920 -thingdev.upload.wait_for_upload_port=true -thingdev.upload.erase_cmd= -thingdev.serial.disableDTR=true -thingdev.serial.disableRTS=true -thingdev.build.mcu=esp8266 -thingdev.build.core=esp8266 -thingdev.build.spiffs_pagesize=256 -thingdev.build.debug_port= -thingdev.build.debug_level= -thingdev.menu.xtal.80=80 MHz -thingdev.menu.xtal.80.build.f_cpu=80000000L -thingdev.menu.xtal.160=160 MHz -thingdev.menu.xtal.160.build.f_cpu=160000000L -thingdev.menu.vt.flash=Flash -thingdev.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -thingdev.menu.vt.heap=Heap -thingdev.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -thingdev.menu.vt.iram=IRAM -thingdev.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -thingdev.menu.exception.legacy=Legacy (new can return nullptr) -thingdev.menu.exception.legacy.build.exception_flags=-fno-exceptions -thingdev.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -thingdev.menu.exception.disabled=Disabled (new can abort) -thingdev.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -thingdev.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -thingdev.menu.exception.enabled=Enabled -thingdev.menu.exception.enabled.build.exception_flags=-fexceptions -thingdev.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -thingdev.menu.ssl.all=All SSL ciphers (most compatible) -thingdev.menu.ssl.all.build.sslflags= -thingdev.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -thingdev.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -thingdev.upload.resetmethod=--before default_reset --after hard_reset -thingdev.build.flash_mode=dio -thingdev.build.flash_flags=-DFLASHMODE_DIO -thingdev.build.flash_freq=40 -thingdev.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) -thingdev.menu.eesz.512K32.build.flash_size=512K -thingdev.menu.eesz.512K32.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -thingdev.menu.eesz.512K32.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K32.upload.maximum_size=466928 -thingdev.menu.eesz.512K32.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K32.build.spiffs_start=0x73000 -thingdev.menu.eesz.512K32.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K32.build.spiffs_blocksize=4096 -thingdev.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) -thingdev.menu.eesz.512K64.build.flash_size=512K -thingdev.menu.eesz.512K64.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -thingdev.menu.eesz.512K64.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K64.upload.maximum_size=434160 -thingdev.menu.eesz.512K64.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K64.build.spiffs_start=0x6B000 -thingdev.menu.eesz.512K64.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K64.build.spiffs_blocksize=4096 -thingdev.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) -thingdev.menu.eesz.512K128.build.flash_size=512K -thingdev.menu.eesz.512K128.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -thingdev.menu.eesz.512K128.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K128.upload.maximum_size=368624 -thingdev.menu.eesz.512K128.build.rfcal_addr=0x7C000 -thingdev.menu.eesz.512K128.build.spiffs_start=0x5B000 -thingdev.menu.eesz.512K128.build.spiffs_end=0x7B000 -thingdev.menu.eesz.512K128.build.spiffs_blocksize=4096 -thingdev.menu.eesz.512K=512KB (FS:none OTA:~246KB) -thingdev.menu.eesz.512K.build.flash_size=512K -thingdev.menu.eesz.512K.build.flash_size_bytes=0x80000 -thingdev.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -thingdev.menu.eesz.512K.build.spiffs_pagesize=256 -thingdev.menu.eesz.512K.upload.maximum_size=499696 -thingdev.menu.eesz.512K.build.rfcal_addr=0x7C000 -thingdev.menu.ip.lm2f=v2 Lower Memory -thingdev.menu.ip.lm2f.build.lwip_include=lwip2/include -thingdev.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -thingdev.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thingdev.menu.ip.hb2f=v2 Higher Bandwidth -thingdev.menu.ip.hb2f.build.lwip_include=lwip2/include -thingdev.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -thingdev.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -thingdev.menu.ip.lm2n=v2 Lower Memory (no features) -thingdev.menu.ip.lm2n.build.lwip_include=lwip2/include -thingdev.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -thingdev.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thingdev.menu.ip.hb2n=v2 Higher Bandwidth (no features) -thingdev.menu.ip.hb2n.build.lwip_include=lwip2/include -thingdev.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -thingdev.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -thingdev.menu.ip.lm6f=v2 IPv6 Lower Memory -thingdev.menu.ip.lm6f.build.lwip_include=lwip2/include -thingdev.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -thingdev.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thingdev.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -thingdev.menu.ip.hb6f.build.lwip_include=lwip2/include -thingdev.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -thingdev.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -thingdev.menu.ip.hb1=v1.4 Higher Bandwidth -thingdev.menu.ip.hb1.build.lwip_lib=-llwip_gcc -thingdev.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.ip.src=v1.4 Compile from source -thingdev.menu.ip.src.build.lwip_lib=-llwip_src -thingdev.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -thingdev.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -thingdev.menu.dbg.Disabled=Disabled -thingdev.menu.dbg.Disabled.build.debug_port= -thingdev.menu.dbg.Serial=Serial -thingdev.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -thingdev.menu.dbg.Serial1=Serial1 -thingdev.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -thingdev.menu.lvl.None____=None -thingdev.menu.lvl.None____.build.debug_level= -thingdev.menu.lvl.SSL=SSL -thingdev.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -thingdev.menu.lvl.TLS_MEM=TLS_MEM -thingdev.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -thingdev.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -thingdev.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.HTTP_SERVER=HTTP_SERVER -thingdev.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -thingdev.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -thingdev.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -thingdev.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -thingdev.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -thingdev.menu.lvl.CORE=CORE -thingdev.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -thingdev.menu.lvl.WIFI=WIFI -thingdev.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -thingdev.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -thingdev.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -thingdev.menu.lvl.UPDATER=UPDATER -thingdev.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -thingdev.menu.lvl.OTA=OTA -thingdev.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -thingdev.menu.lvl.OOM=OOM -thingdev.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -thingdev.menu.lvl.MDNS=MDNS -thingdev.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -thingdev.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -thingdev.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -thingdev.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -thingdev.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -thingdev.menu.wipe.none=Only Sketch -thingdev.menu.wipe.none.upload.erase_cmd= -thingdev.menu.wipe.sdk=Sketch + WiFi Settings -thingdev.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -thingdev.menu.wipe.all=All Flash Contents -thingdev.menu.wipe.all.upload.erase_cmd=erase_flash -thingdev.menu.baud.115200=115200 -thingdev.menu.baud.115200.upload.speed=115200 -thingdev.menu.baud.57600=57600 -thingdev.menu.baud.57600.upload.speed=57600 -thingdev.menu.baud.230400.linux=230400 -thingdev.menu.baud.230400.macosx=230400 -thingdev.menu.baud.230400.upload.speed=230400 -thingdev.menu.baud.256000.windows=256000 -thingdev.menu.baud.256000.upload.speed=256000 -thingdev.menu.baud.460800.linux=460800 -thingdev.menu.baud.460800.macosx=460800 -thingdev.menu.baud.460800.upload.speed=460800 -thingdev.menu.baud.512000.windows=512000 -thingdev.menu.baud.512000.upload.speed=512000 -thingdev.menu.baud.921600=921600 -thingdev.menu.baud.921600.upload.speed=921600 -thingdev.menu.baud.3000000=3000000 -thingdev.menu.baud.3000000.upload.speed=3000000 - -############################################################## -blynk.name=SparkFun Blynk Board -blynk.build.board=ESP8266_THING -blynk.build.variant=thing -blynk.upload.tool=esptool -blynk.upload.maximum_data_size=81920 -blynk.upload.wait_for_upload_port=true -blynk.upload.erase_cmd= -blynk.serial.disableDTR=true -blynk.serial.disableRTS=true -blynk.build.mcu=esp8266 -blynk.build.core=esp8266 -blynk.build.spiffs_pagesize=256 -blynk.build.debug_port= -blynk.build.debug_level= -blynk.menu.xtal.80=80 MHz -blynk.menu.xtal.80.build.f_cpu=80000000L -blynk.menu.xtal.160=160 MHz -blynk.menu.xtal.160.build.f_cpu=160000000L -blynk.menu.vt.flash=Flash -blynk.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -blynk.menu.vt.heap=Heap -blynk.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -blynk.menu.vt.iram=IRAM -blynk.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -blynk.menu.exception.legacy=Legacy (new can return nullptr) -blynk.menu.exception.legacy.build.exception_flags=-fno-exceptions -blynk.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -blynk.menu.exception.disabled=Disabled (new can abort) -blynk.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -blynk.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -blynk.menu.exception.enabled=Enabled -blynk.menu.exception.enabled.build.exception_flags=-fexceptions -blynk.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -blynk.menu.ssl.all=All SSL ciphers (most compatible) -blynk.menu.ssl.all.build.sslflags= -blynk.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -blynk.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -blynk.upload.resetmethod=--before default_reset --after hard_reset -blynk.build.flash_mode=qio -blynk.build.flash_flags=-DFLASHMODE_QIO -blynk.build.flash_freq=40 -blynk.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -blynk.menu.eesz.4M2M.build.flash_size=4M -blynk.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -blynk.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -blynk.menu.eesz.4M2M.build.spiffs_pagesize=256 -blynk.menu.eesz.4M2M.upload.maximum_size=1044464 -blynk.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -blynk.menu.eesz.4M2M.build.spiffs_start=0x200000 -blynk.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -blynk.menu.eesz.4M2M.build.spiffs_blocksize=8192 -blynk.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -blynk.menu.eesz.4M3M.build.flash_size=4M -blynk.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -blynk.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -blynk.menu.eesz.4M3M.build.spiffs_pagesize=256 -blynk.menu.eesz.4M3M.upload.maximum_size=1044464 -blynk.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -blynk.menu.eesz.4M3M.build.spiffs_start=0x100000 -blynk.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -blynk.menu.eesz.4M3M.build.spiffs_blocksize=8192 -blynk.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -blynk.menu.eesz.4M1M.build.flash_size=4M -blynk.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -blynk.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -blynk.menu.eesz.4M1M.build.spiffs_pagesize=256 -blynk.menu.eesz.4M1M.upload.maximum_size=1044464 -blynk.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -blynk.menu.eesz.4M1M.build.spiffs_start=0x300000 -blynk.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -blynk.menu.eesz.4M1M.build.spiffs_blocksize=8192 -blynk.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -blynk.menu.eesz.4M.build.flash_size=4M -blynk.menu.eesz.4M.build.flash_size_bytes=0x400000 -blynk.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -blynk.menu.eesz.4M.build.spiffs_pagesize=256 -blynk.menu.eesz.4M.upload.maximum_size=1044464 -blynk.menu.eesz.4M.build.rfcal_addr=0x3FC000 -blynk.menu.ip.lm2f=v2 Lower Memory -blynk.menu.ip.lm2f.build.lwip_include=lwip2/include -blynk.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -blynk.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -blynk.menu.ip.hb2f=v2 Higher Bandwidth -blynk.menu.ip.hb2f.build.lwip_include=lwip2/include -blynk.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -blynk.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -blynk.menu.ip.lm2n=v2 Lower Memory (no features) -blynk.menu.ip.lm2n.build.lwip_include=lwip2/include -blynk.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -blynk.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -blynk.menu.ip.hb2n=v2 Higher Bandwidth (no features) -blynk.menu.ip.hb2n.build.lwip_include=lwip2/include -blynk.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -blynk.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -blynk.menu.ip.lm6f=v2 IPv6 Lower Memory -blynk.menu.ip.lm6f.build.lwip_include=lwip2/include -blynk.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -blynk.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -blynk.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -blynk.menu.ip.hb6f.build.lwip_include=lwip2/include -blynk.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -blynk.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -blynk.menu.ip.hb1=v1.4 Higher Bandwidth -blynk.menu.ip.hb1.build.lwip_lib=-llwip_gcc -blynk.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -blynk.menu.ip.src=v1.4 Compile from source -blynk.menu.ip.src.build.lwip_lib=-llwip_src -blynk.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -blynk.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -blynk.menu.dbg.Disabled=Disabled -blynk.menu.dbg.Disabled.build.debug_port= -blynk.menu.dbg.Serial=Serial -blynk.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -blynk.menu.dbg.Serial1=Serial1 -blynk.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -blynk.menu.lvl.None____=None -blynk.menu.lvl.None____.build.debug_level= -blynk.menu.lvl.SSL=SSL -blynk.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -blynk.menu.lvl.TLS_MEM=TLS_MEM -blynk.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -blynk.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -blynk.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -blynk.menu.lvl.HTTP_SERVER=HTTP_SERVER -blynk.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -blynk.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -blynk.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -blynk.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -blynk.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -blynk.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -blynk.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -blynk.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -blynk.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -blynk.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -blynk.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -blynk.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -blynk.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -blynk.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -blynk.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -blynk.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -blynk.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -blynk.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -blynk.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -blynk.menu.lvl.CORE=CORE -blynk.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -blynk.menu.lvl.WIFI=WIFI -blynk.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -blynk.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -blynk.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -blynk.menu.lvl.UPDATER=UPDATER -blynk.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -blynk.menu.lvl.OTA=OTA -blynk.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -blynk.menu.lvl.OOM=OOM -blynk.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -blynk.menu.lvl.MDNS=MDNS -blynk.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -blynk.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -blynk.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -blynk.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -blynk.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -blynk.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -blynk.menu.wipe.none=Only Sketch -blynk.menu.wipe.none.upload.erase_cmd= -blynk.menu.wipe.sdk=Sketch + WiFi Settings -blynk.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -blynk.menu.wipe.all=All Flash Contents -blynk.menu.wipe.all.upload.erase_cmd=erase_flash -blynk.menu.baud.115200=115200 -blynk.menu.baud.115200.upload.speed=115200 -blynk.menu.baud.57600=57600 -blynk.menu.baud.57600.upload.speed=57600 -blynk.menu.baud.230400.linux=230400 -blynk.menu.baud.230400.macosx=230400 -blynk.menu.baud.230400.upload.speed=230400 -blynk.menu.baud.256000.windows=256000 -blynk.menu.baud.256000.upload.speed=256000 -blynk.menu.baud.460800.linux=460800 -blynk.menu.baud.460800.macosx=460800 -blynk.menu.baud.460800.upload.speed=460800 -blynk.menu.baud.512000.windows=512000 -blynk.menu.baud.512000.upload.speed=512000 -blynk.menu.baud.921600=921600 -blynk.menu.baud.921600.upload.speed=921600 -blynk.menu.baud.3000000=3000000 -blynk.menu.baud.3000000.upload.speed=3000000 - -############################################################## -esp210.name=SweetPea ESP-210 -esp210.build.board=ESP8266_ESP210 -esp210.upload.tool=esptool -esp210.upload.maximum_data_size=81920 -esp210.upload.wait_for_upload_port=true -esp210.upload.erase_cmd= -esp210.serial.disableDTR=true -esp210.serial.disableRTS=true -esp210.build.mcu=esp8266 -esp210.build.core=esp8266 -esp210.build.variant=generic -esp210.build.spiffs_pagesize=256 -esp210.build.debug_port= -esp210.build.debug_level= -esp210.menu.xtal.80=80 MHz -esp210.menu.xtal.80.build.f_cpu=80000000L -esp210.menu.xtal.160=160 MHz -esp210.menu.xtal.160.build.f_cpu=160000000L -esp210.menu.vt.flash=Flash -esp210.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -esp210.menu.vt.heap=Heap -esp210.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -esp210.menu.vt.iram=IRAM -esp210.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -esp210.menu.exception.legacy=Legacy (new can return nullptr) -esp210.menu.exception.legacy.build.exception_flags=-fno-exceptions -esp210.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -esp210.menu.exception.disabled=Disabled (new can abort) -esp210.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -esp210.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -esp210.menu.exception.enabled=Enabled -esp210.menu.exception.enabled.build.exception_flags=-fexceptions -esp210.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -esp210.menu.ssl.all=All SSL ciphers (most compatible) -esp210.menu.ssl.all.build.sslflags= -esp210.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -esp210.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -esp210.upload.resetmethod=--before no_reset --after soft_reset -esp210.build.flash_mode=qio -esp210.build.flash_flags=-DFLASHMODE_QIO -esp210.build.flash_freq=40 -esp210.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -esp210.menu.eesz.4M2M.build.flash_size=4M -esp210.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -esp210.menu.eesz.4M2M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M2M.upload.maximum_size=1044464 -esp210.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M2M.build.spiffs_start=0x200000 -esp210.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -esp210.menu.eesz.4M2M.build.spiffs_blocksize=8192 -esp210.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -esp210.menu.eesz.4M3M.build.flash_size=4M -esp210.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -esp210.menu.eesz.4M3M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M3M.upload.maximum_size=1044464 -esp210.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M3M.build.spiffs_start=0x100000 -esp210.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -esp210.menu.eesz.4M3M.build.spiffs_blocksize=8192 -esp210.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -esp210.menu.eesz.4M1M.build.flash_size=4M -esp210.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -esp210.menu.eesz.4M1M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M1M.upload.maximum_size=1044464 -esp210.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -esp210.menu.eesz.4M1M.build.spiffs_start=0x300000 -esp210.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -esp210.menu.eesz.4M1M.build.spiffs_blocksize=8192 -esp210.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -esp210.menu.eesz.4M.build.flash_size=4M -esp210.menu.eesz.4M.build.flash_size_bytes=0x400000 -esp210.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -esp210.menu.eesz.4M.build.spiffs_pagesize=256 -esp210.menu.eesz.4M.upload.maximum_size=1044464 -esp210.menu.eesz.4M.build.rfcal_addr=0x3FC000 -esp210.menu.ip.lm2f=v2 Lower Memory -esp210.menu.ip.lm2f.build.lwip_include=lwip2/include -esp210.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -esp210.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp210.menu.ip.hb2f=v2 Higher Bandwidth -esp210.menu.ip.hb2f.build.lwip_include=lwip2/include -esp210.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -esp210.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -esp210.menu.ip.lm2n=v2 Lower Memory (no features) -esp210.menu.ip.lm2n.build.lwip_include=lwip2/include -esp210.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -esp210.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp210.menu.ip.hb2n=v2 Higher Bandwidth (no features) -esp210.menu.ip.hb2n.build.lwip_include=lwip2/include -esp210.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -esp210.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -esp210.menu.ip.lm6f=v2 IPv6 Lower Memory -esp210.menu.ip.lm6f.build.lwip_include=lwip2/include -esp210.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -esp210.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp210.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -esp210.menu.ip.hb6f.build.lwip_include=lwip2/include -esp210.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -esp210.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -esp210.menu.ip.hb1=v1.4 Higher Bandwidth -esp210.menu.ip.hb1.build.lwip_lib=-llwip_gcc -esp210.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.ip.src=v1.4 Compile from source -esp210.menu.ip.src.build.lwip_lib=-llwip_src -esp210.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -esp210.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -esp210.menu.dbg.Disabled=Disabled -esp210.menu.dbg.Disabled.build.debug_port= -esp210.menu.dbg.Serial=Serial -esp210.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -esp210.menu.dbg.Serial1=Serial1 -esp210.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -esp210.menu.lvl.None____=None -esp210.menu.lvl.None____.build.debug_level= -esp210.menu.lvl.SSL=SSL -esp210.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -esp210.menu.lvl.TLS_MEM=TLS_MEM -esp210.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -esp210.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -esp210.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.HTTP_SERVER=HTTP_SERVER -esp210.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -esp210.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -esp210.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -esp210.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -esp210.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -esp210.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -esp210.menu.lvl.CORE=CORE -esp210.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -esp210.menu.lvl.WIFI=WIFI -esp210.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -esp210.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -esp210.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -esp210.menu.lvl.UPDATER=UPDATER -esp210.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -esp210.menu.lvl.OTA=OTA -esp210.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -esp210.menu.lvl.OOM=OOM -esp210.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -esp210.menu.lvl.MDNS=MDNS -esp210.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -esp210.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -esp210.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -esp210.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -esp210.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -esp210.menu.wipe.none=Only Sketch -esp210.menu.wipe.none.upload.erase_cmd= -esp210.menu.wipe.sdk=Sketch + WiFi Settings -esp210.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -esp210.menu.wipe.all=All Flash Contents -esp210.menu.wipe.all.upload.erase_cmd=erase_flash -esp210.menu.baud.57600=57600 -esp210.menu.baud.57600.upload.speed=57600 -esp210.menu.baud.115200=115200 -esp210.menu.baud.115200.upload.speed=115200 -esp210.menu.baud.230400.linux=230400 -esp210.menu.baud.230400.macosx=230400 -esp210.menu.baud.230400.upload.speed=230400 -esp210.menu.baud.256000.windows=256000 -esp210.menu.baud.256000.upload.speed=256000 -esp210.menu.baud.460800.linux=460800 -esp210.menu.baud.460800.macosx=460800 -esp210.menu.baud.460800.upload.speed=460800 -esp210.menu.baud.512000.windows=512000 -esp210.menu.baud.512000.upload.speed=512000 -esp210.menu.baud.921600=921600 -esp210.menu.baud.921600.upload.speed=921600 -esp210.menu.baud.3000000=3000000 -esp210.menu.baud.3000000.upload.speed=3000000 - -############################################################## -d1_mini.name=LOLIN(WEMOS) D1 R2 & mini -d1_mini.build.board=ESP8266_WEMOS_D1MINI -d1_mini.build.variant=d1_mini -d1_mini.upload.tool=esptool -d1_mini.upload.maximum_data_size=81920 -d1_mini.upload.wait_for_upload_port=true -d1_mini.upload.erase_cmd= -d1_mini.serial.disableDTR=true -d1_mini.serial.disableRTS=true -d1_mini.build.mcu=esp8266 -d1_mini.build.core=esp8266 -d1_mini.build.spiffs_pagesize=256 -d1_mini.build.debug_port= -d1_mini.build.debug_level= -d1_mini.menu.xtal.80=80 MHz -d1_mini.menu.xtal.80.build.f_cpu=80000000L -d1_mini.menu.xtal.160=160 MHz -d1_mini.menu.xtal.160.build.f_cpu=160000000L -d1_mini.menu.vt.flash=Flash -d1_mini.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini.menu.vt.heap=Heap -d1_mini.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini.menu.vt.iram=IRAM -d1_mini.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini.menu.exception.legacy=Legacy (new can return nullptr) -d1_mini.menu.exception.legacy.build.exception_flags=-fno-exceptions -d1_mini.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -d1_mini.menu.exception.disabled=Disabled (new can abort) -d1_mini.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -d1_mini.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -d1_mini.menu.exception.enabled=Enabled -d1_mini.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -d1_mini.menu.ssl.all=All SSL ciphers (most compatible) -d1_mini.menu.ssl.all.build.sslflags= -d1_mini.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -d1_mini.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -d1_mini.upload.resetmethod=--before default_reset --after hard_reset -d1_mini.build.flash_mode=dio -d1_mini.build.flash_flags=-DFLASHMODE_DIO -d1_mini.build.flash_freq=40 -d1_mini.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -d1_mini.menu.eesz.4M2M.build.flash_size=4M -d1_mini.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -d1_mini.menu.eesz.4M2M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M2M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M2M.build.spiffs_start=0x200000 -d1_mini.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -d1_mini.menu.eesz.4M2M.build.spiffs_blocksize=8192 -d1_mini.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -d1_mini.menu.eesz.4M3M.build.flash_size=4M -d1_mini.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -d1_mini.menu.eesz.4M3M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M3M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M3M.build.spiffs_start=0x100000 -d1_mini.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -d1_mini.menu.eesz.4M3M.build.spiffs_blocksize=8192 -d1_mini.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -d1_mini.menu.eesz.4M1M.build.flash_size=4M -d1_mini.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1_mini.menu.eesz.4M1M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M1M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -d1_mini.menu.eesz.4M1M.build.spiffs_start=0x300000 -d1_mini.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -d1_mini.menu.eesz.4M1M.build.spiffs_blocksize=8192 -d1_mini.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -d1_mini.menu.eesz.4M.build.flash_size=4M -d1_mini.menu.eesz.4M.build.flash_size_bytes=0x400000 -d1_mini.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -d1_mini.menu.eesz.4M.build.spiffs_pagesize=256 -d1_mini.menu.eesz.4M.upload.maximum_size=1044464 -d1_mini.menu.eesz.4M.build.rfcal_addr=0x3FC000 -d1_mini.menu.ip.lm2f=v2 Lower Memory -d1_mini.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.ip.src=v1.4 Compile from source -d1_mini.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini.menu.dbg.Disabled=Disabled -d1_mini.menu.dbg.Disabled.build.debug_port= -d1_mini.menu.dbg.Serial=Serial -d1_mini.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini.menu.dbg.Serial1=Serial1 -d1_mini.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini.menu.lvl.None____=None -d1_mini.menu.lvl.None____.build.debug_level= -d1_mini.menu.lvl.SSL=SSL -d1_mini.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini.menu.lvl.TLS_MEM=TLS_MEM -d1_mini.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini.menu.lvl.CORE=CORE -d1_mini.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini.menu.lvl.WIFI=WIFI -d1_mini.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini.menu.lvl.UPDATER=UPDATER -d1_mini.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini.menu.lvl.OTA=OTA -d1_mini.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini.menu.lvl.OOM=OOM -d1_mini.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini.menu.lvl.MDNS=MDNS -d1_mini.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -d1_mini.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -d1_mini.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -d1_mini.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini.menu.wipe.none=Only Sketch -d1_mini.menu.wipe.none.upload.erase_cmd= -d1_mini.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -d1_mini.menu.wipe.all=All Flash Contents -d1_mini.menu.wipe.all.upload.erase_cmd=erase_flash -d1_mini.menu.baud.921600=921600 -d1_mini.menu.baud.921600.upload.speed=921600 -d1_mini.menu.baud.57600=57600 -d1_mini.menu.baud.57600.upload.speed=57600 -d1_mini.menu.baud.115200=115200 -d1_mini.menu.baud.115200.upload.speed=115200 -d1_mini.menu.baud.230400.linux=230400 -d1_mini.menu.baud.230400.macosx=230400 -d1_mini.menu.baud.230400.upload.speed=230400 -d1_mini.menu.baud.256000.windows=256000 -d1_mini.menu.baud.256000.upload.speed=256000 -d1_mini.menu.baud.460800.linux=460800 -d1_mini.menu.baud.460800.macosx=460800 -d1_mini.menu.baud.460800.upload.speed=460800 -d1_mini.menu.baud.512000.windows=512000 -d1_mini.menu.baud.512000.upload.speed=512000 -d1_mini.menu.baud.3000000=3000000 -d1_mini.menu.baud.3000000.upload.speed=3000000 - -############################################################## -d1_mini_pro.name=LOLIN(WEMOS) D1 mini Pro -d1_mini_pro.build.board=ESP8266_WEMOS_D1MINIPRO -d1_mini_pro.build.variant=d1_mini -d1_mini_pro.upload.tool=esptool -d1_mini_pro.upload.maximum_data_size=81920 -d1_mini_pro.upload.wait_for_upload_port=true -d1_mini_pro.upload.erase_cmd= -d1_mini_pro.serial.disableDTR=true -d1_mini_pro.serial.disableRTS=true -d1_mini_pro.build.mcu=esp8266 -d1_mini_pro.build.core=esp8266 -d1_mini_pro.build.spiffs_pagesize=256 -d1_mini_pro.build.debug_port= -d1_mini_pro.build.debug_level= -d1_mini_pro.menu.xtal.80=80 MHz -d1_mini_pro.menu.xtal.80.build.f_cpu=80000000L -d1_mini_pro.menu.xtal.160=160 MHz -d1_mini_pro.menu.xtal.160.build.f_cpu=160000000L -d1_mini_pro.menu.vt.flash=Flash -d1_mini_pro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini_pro.menu.vt.heap=Heap -d1_mini_pro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini_pro.menu.vt.iram=IRAM -d1_mini_pro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini_pro.menu.exception.legacy=Legacy (new can return nullptr) -d1_mini_pro.menu.exception.legacy.build.exception_flags=-fno-exceptions -d1_mini_pro.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -d1_mini_pro.menu.exception.disabled=Disabled (new can abort) -d1_mini_pro.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -d1_mini_pro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -d1_mini_pro.menu.exception.enabled=Enabled -d1_mini_pro.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini_pro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -d1_mini_pro.menu.ssl.all=All SSL ciphers (most compatible) -d1_mini_pro.menu.ssl.all.build.sslflags= -d1_mini_pro.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -d1_mini_pro.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -d1_mini_pro.upload.resetmethod=--before default_reset --after hard_reset -d1_mini_pro.build.flash_mode=dio -d1_mini_pro.build.flash_flags=-DFLASHMODE_DIO -d1_mini_pro.build.flash_freq=40 -d1_mini_pro.menu.eesz.16M14M=16MB (FS:14MB OTA:~1019KB) -d1_mini_pro.menu.eesz.16M14M.build.flash_size=16M -d1_mini_pro.menu.eesz.16M14M.build.flash_size_bytes=0x1000000 -d1_mini_pro.menu.eesz.16M14M.build.flash_ld=eagle.flash.16m14m.ld -d1_mini_pro.menu.eesz.16M14M.build.spiffs_pagesize=256 -d1_mini_pro.menu.eesz.16M14M.upload.maximum_size=1044464 -d1_mini_pro.menu.eesz.16M14M.build.rfcal_addr=0xFFC000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_start=0x200000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_end=0xFFA000 -d1_mini_pro.menu.eesz.16M14M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.eesz.16M15M=16MB (FS:15MB OTA:~512KB) -d1_mini_pro.menu.eesz.16M15M.build.flash_size=16M -d1_mini_pro.menu.eesz.16M15M.build.flash_size_bytes=0x1000000 -d1_mini_pro.menu.eesz.16M15M.build.flash_ld=eagle.flash.16m15m.ld -d1_mini_pro.menu.eesz.16M15M.build.spiffs_pagesize=256 -d1_mini_pro.menu.eesz.16M15M.upload.maximum_size=1044464 -d1_mini_pro.menu.eesz.16M15M.build.rfcal_addr=0xFFC000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_start=0x100000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_end=0xFFA000 -d1_mini_pro.menu.eesz.16M15M.build.spiffs_blocksize=8192 -d1_mini_pro.menu.ip.lm2f=v2 Lower Memory -d1_mini_pro.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini_pro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini_pro.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini_pro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini_pro.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini_pro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini_pro.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini_pro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_pro.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini_pro.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini_pro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_pro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini_pro.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini_pro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini_pro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_pro.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini_pro.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini_pro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.ip.src=v1.4 Compile from source -d1_mini_pro.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini_pro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_pro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_pro.menu.dbg.Disabled=Disabled -d1_mini_pro.menu.dbg.Disabled.build.debug_port= -d1_mini_pro.menu.dbg.Serial=Serial -d1_mini_pro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_pro.menu.dbg.Serial1=Serial1 -d1_mini_pro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_pro.menu.lvl.None____=None -d1_mini_pro.menu.lvl.None____.build.debug_level= -d1_mini_pro.menu.lvl.SSL=SSL -d1_mini_pro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_pro.menu.lvl.TLS_MEM=TLS_MEM -d1_mini_pro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini_pro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_pro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_pro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_pro.menu.lvl.CORE=CORE -d1_mini_pro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_pro.menu.lvl.WIFI=WIFI -d1_mini_pro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_pro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini_pro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_pro.menu.lvl.UPDATER=UPDATER -d1_mini_pro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_pro.menu.lvl.OTA=OTA -d1_mini_pro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_pro.menu.lvl.OOM=OOM -d1_mini_pro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini_pro.menu.lvl.MDNS=MDNS -d1_mini_pro.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -d1_mini_pro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -d1_mini_pro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -d1_mini_pro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_pro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_pro.menu.wipe.none=Only Sketch -d1_mini_pro.menu.wipe.none.upload.erase_cmd= -d1_mini_pro.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini_pro.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -d1_mini_pro.menu.wipe.all=All Flash Contents -d1_mini_pro.menu.wipe.all.upload.erase_cmd=erase_flash -d1_mini_pro.menu.baud.921600=921600 -d1_mini_pro.menu.baud.921600.upload.speed=921600 -d1_mini_pro.menu.baud.57600=57600 -d1_mini_pro.menu.baud.57600.upload.speed=57600 -d1_mini_pro.menu.baud.115200=115200 -d1_mini_pro.menu.baud.115200.upload.speed=115200 -d1_mini_pro.menu.baud.230400.linux=230400 -d1_mini_pro.menu.baud.230400.macosx=230400 -d1_mini_pro.menu.baud.230400.upload.speed=230400 -d1_mini_pro.menu.baud.256000.windows=256000 -d1_mini_pro.menu.baud.256000.upload.speed=256000 -d1_mini_pro.menu.baud.460800.linux=460800 -d1_mini_pro.menu.baud.460800.macosx=460800 -d1_mini_pro.menu.baud.460800.upload.speed=460800 -d1_mini_pro.menu.baud.512000.windows=512000 -d1_mini_pro.menu.baud.512000.upload.speed=512000 -d1_mini_pro.menu.baud.3000000=3000000 -d1_mini_pro.menu.baud.3000000.upload.speed=3000000 - -############################################################## -d1_mini_lite.name=LOLIN(WEMOS) D1 mini Lite -d1_mini_lite.build.board=ESP8266_WEMOS_D1MINILITE -d1_mini_lite.build.variant=d1_mini -d1_mini_lite.upload.tool=esptool -d1_mini_lite.upload.maximum_data_size=81920 -d1_mini_lite.upload.wait_for_upload_port=true -d1_mini_lite.upload.erase_cmd= -d1_mini_lite.serial.disableDTR=true -d1_mini_lite.serial.disableRTS=true -d1_mini_lite.build.mcu=esp8266 -d1_mini_lite.build.core=esp8266 -d1_mini_lite.build.spiffs_pagesize=256 -d1_mini_lite.build.debug_port= -d1_mini_lite.build.debug_level= -d1_mini_lite.menu.xtal.80=80 MHz -d1_mini_lite.menu.xtal.80.build.f_cpu=80000000L -d1_mini_lite.menu.xtal.160=160 MHz -d1_mini_lite.menu.xtal.160.build.f_cpu=160000000L -d1_mini_lite.menu.vt.flash=Flash -d1_mini_lite.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1_mini_lite.menu.vt.heap=Heap -d1_mini_lite.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1_mini_lite.menu.vt.iram=IRAM -d1_mini_lite.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1_mini_lite.menu.exception.legacy=Legacy (new can return nullptr) -d1_mini_lite.menu.exception.legacy.build.exception_flags=-fno-exceptions -d1_mini_lite.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -d1_mini_lite.menu.exception.disabled=Disabled (new can abort) -d1_mini_lite.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -d1_mini_lite.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -d1_mini_lite.menu.exception.enabled=Enabled -d1_mini_lite.menu.exception.enabled.build.exception_flags=-fexceptions -d1_mini_lite.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -d1_mini_lite.menu.ssl.all=All SSL ciphers (most compatible) -d1_mini_lite.menu.ssl.all.build.sslflags= -d1_mini_lite.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -d1_mini_lite.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -d1_mini_lite.upload.resetmethod=--before default_reset --after hard_reset -d1_mini_lite.build.flash_mode=dout -d1_mini_lite.build.flash_flags=-DFLASHMODE_DOUT -d1_mini_lite.build.flash_freq=40 -d1_mini_lite.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) -d1_mini_lite.menu.eesz.1M64.build.flash_size=1M -d1_mini_lite.menu.eesz.1M64.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -d1_mini_lite.menu.eesz.1M64.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M64.upload.maximum_size=958448 -d1_mini_lite.menu.eesz.1M64.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_start=0xEB000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M64.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) -d1_mini_lite.menu.eesz.1M128.build.flash_size=1M -d1_mini_lite.menu.eesz.1M128.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -d1_mini_lite.menu.eesz.1M128.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M128.upload.maximum_size=892912 -d1_mini_lite.menu.eesz.1M128.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_start=0xDB000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M128.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) -d1_mini_lite.menu.eesz.1M144.build.flash_size=1M -d1_mini_lite.menu.eesz.1M144.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -d1_mini_lite.menu.eesz.1M144.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M144.upload.maximum_size=876528 -d1_mini_lite.menu.eesz.1M144.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_start=0xD7000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M144.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) -d1_mini_lite.menu.eesz.1M160.build.flash_size=1M -d1_mini_lite.menu.eesz.1M160.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -d1_mini_lite.menu.eesz.1M160.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M160.upload.maximum_size=860144 -d1_mini_lite.menu.eesz.1M160.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_start=0xD3000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M160.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) -d1_mini_lite.menu.eesz.1M192.build.flash_size=1M -d1_mini_lite.menu.eesz.1M192.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -d1_mini_lite.menu.eesz.1M192.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M192.upload.maximum_size=827376 -d1_mini_lite.menu.eesz.1M192.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_start=0xCB000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M192.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) -d1_mini_lite.menu.eesz.1M256.build.flash_size=1M -d1_mini_lite.menu.eesz.1M256.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -d1_mini_lite.menu.eesz.1M256.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M256.upload.maximum_size=761840 -d1_mini_lite.menu.eesz.1M256.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_start=0xBB000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M256.build.spiffs_blocksize=4096 -d1_mini_lite.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) -d1_mini_lite.menu.eesz.1M512.build.flash_size=1M -d1_mini_lite.menu.eesz.1M512.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -d1_mini_lite.menu.eesz.1M512.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M512.upload.maximum_size=499696 -d1_mini_lite.menu.eesz.1M512.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_start=0x7B000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_end=0xFB000 -d1_mini_lite.menu.eesz.1M512.build.spiffs_blocksize=8192 -d1_mini_lite.menu.eesz.1M=1MB (FS:none OTA:~502KB) -d1_mini_lite.menu.eesz.1M.build.flash_size=1M -d1_mini_lite.menu.eesz.1M.build.flash_size_bytes=0x100000 -d1_mini_lite.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -d1_mini_lite.menu.eesz.1M.build.spiffs_pagesize=256 -d1_mini_lite.menu.eesz.1M.upload.maximum_size=1023984 -d1_mini_lite.menu.eesz.1M.build.rfcal_addr=0xFC000 -d1_mini_lite.menu.ip.lm2f=v2 Lower Memory -d1_mini_lite.menu.ip.lm2f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1_mini_lite.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.hb2f=v2 Higher Bandwidth -d1_mini_lite.menu.ip.hb2f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1_mini_lite.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.lm2n=v2 Lower Memory (no features) -d1_mini_lite.menu.ip.lm2n.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1_mini_lite.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1_mini_lite.menu.ip.hb2n.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1_mini_lite.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1_mini_lite.menu.ip.lm6f=v2 IPv6 Lower Memory -d1_mini_lite.menu.ip.lm6f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1_mini_lite.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_lite.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1_mini_lite.menu.ip.hb6f.build.lwip_include=lwip2/include -d1_mini_lite.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1_mini_lite.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1_mini_lite.menu.ip.hb1=v1.4 Higher Bandwidth -d1_mini_lite.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1_mini_lite.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.ip.src=v1.4 Compile from source -d1_mini_lite.menu.ip.src.build.lwip_lib=-llwip_src -d1_mini_lite.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1_mini_lite.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1_mini_lite.menu.dbg.Disabled=Disabled -d1_mini_lite.menu.dbg.Disabled.build.debug_port= -d1_mini_lite.menu.dbg.Serial=Serial -d1_mini_lite.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1_mini_lite.menu.dbg.Serial1=Serial1 -d1_mini_lite.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1_mini_lite.menu.lvl.None____=None -d1_mini_lite.menu.lvl.None____.build.debug_level= -d1_mini_lite.menu.lvl.SSL=SSL -d1_mini_lite.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1_mini_lite.menu.lvl.TLS_MEM=TLS_MEM -d1_mini_lite.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1_mini_lite.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1_mini_lite.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1_mini_lite.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1_mini_lite.menu.lvl.CORE=CORE -d1_mini_lite.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1_mini_lite.menu.lvl.WIFI=WIFI -d1_mini_lite.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1_mini_lite.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1_mini_lite.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1_mini_lite.menu.lvl.UPDATER=UPDATER -d1_mini_lite.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1_mini_lite.menu.lvl.OTA=OTA -d1_mini_lite.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1_mini_lite.menu.lvl.OOM=OOM -d1_mini_lite.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1_mini_lite.menu.lvl.MDNS=MDNS -d1_mini_lite.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -d1_mini_lite.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -d1_mini_lite.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -d1_mini_lite.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1_mini_lite.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1_mini_lite.menu.wipe.none=Only Sketch -d1_mini_lite.menu.wipe.none.upload.erase_cmd= -d1_mini_lite.menu.wipe.sdk=Sketch + WiFi Settings -d1_mini_lite.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -d1_mini_lite.menu.wipe.all=All Flash Contents -d1_mini_lite.menu.wipe.all.upload.erase_cmd=erase_flash -d1_mini_lite.menu.baud.921600=921600 -d1_mini_lite.menu.baud.921600.upload.speed=921600 -d1_mini_lite.menu.baud.57600=57600 -d1_mini_lite.menu.baud.57600.upload.speed=57600 -d1_mini_lite.menu.baud.115200=115200 -d1_mini_lite.menu.baud.115200.upload.speed=115200 -d1_mini_lite.menu.baud.230400.linux=230400 -d1_mini_lite.menu.baud.230400.macosx=230400 -d1_mini_lite.menu.baud.230400.upload.speed=230400 -d1_mini_lite.menu.baud.256000.windows=256000 -d1_mini_lite.menu.baud.256000.upload.speed=256000 -d1_mini_lite.menu.baud.460800.linux=460800 -d1_mini_lite.menu.baud.460800.macosx=460800 -d1_mini_lite.menu.baud.460800.upload.speed=460800 -d1_mini_lite.menu.baud.512000.windows=512000 -d1_mini_lite.menu.baud.512000.upload.speed=512000 -d1_mini_lite.menu.baud.3000000=3000000 -d1_mini_lite.menu.baud.3000000.upload.speed=3000000 - -############################################################## -d1.name=WeMos D1 R1 -d1.build.board=ESP8266_WEMOS_D1R1 -d1.build.variant=d1 -d1.upload.tool=esptool -d1.upload.maximum_data_size=81920 -d1.upload.wait_for_upload_port=true -d1.upload.erase_cmd= -d1.serial.disableDTR=true -d1.serial.disableRTS=true -d1.build.mcu=esp8266 -d1.build.core=esp8266 -d1.build.spiffs_pagesize=256 -d1.build.debug_port= -d1.build.debug_level= -d1.menu.xtal.80=80 MHz -d1.menu.xtal.80.build.f_cpu=80000000L -d1.menu.xtal.160=160 MHz -d1.menu.xtal.160.build.f_cpu=160000000L -d1.menu.vt.flash=Flash -d1.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -d1.menu.vt.heap=Heap -d1.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -d1.menu.vt.iram=IRAM -d1.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -d1.menu.exception.legacy=Legacy (new can return nullptr) -d1.menu.exception.legacy.build.exception_flags=-fno-exceptions -d1.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -d1.menu.exception.disabled=Disabled (new can abort) -d1.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -d1.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -d1.menu.exception.enabled=Enabled -d1.menu.exception.enabled.build.exception_flags=-fexceptions -d1.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -d1.menu.ssl.all=All SSL ciphers (most compatible) -d1.menu.ssl.all.build.sslflags= -d1.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -d1.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -d1.upload.resetmethod=--before default_reset --after hard_reset -d1.build.flash_mode=dio -d1.build.flash_flags=-DFLASHMODE_DIO -d1.build.flash_freq=40 -d1.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -d1.menu.eesz.4M2M.build.flash_size=4M -d1.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -d1.menu.eesz.4M2M.build.spiffs_pagesize=256 -d1.menu.eesz.4M2M.upload.maximum_size=1044464 -d1.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M2M.build.spiffs_start=0x200000 -d1.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -d1.menu.eesz.4M2M.build.spiffs_blocksize=8192 -d1.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -d1.menu.eesz.4M3M.build.flash_size=4M -d1.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -d1.menu.eesz.4M3M.build.spiffs_pagesize=256 -d1.menu.eesz.4M3M.upload.maximum_size=1044464 -d1.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M3M.build.spiffs_start=0x100000 -d1.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -d1.menu.eesz.4M3M.build.spiffs_blocksize=8192 -d1.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -d1.menu.eesz.4M1M.build.flash_size=4M -d1.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -d1.menu.eesz.4M1M.build.spiffs_pagesize=256 -d1.menu.eesz.4M1M.upload.maximum_size=1044464 -d1.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -d1.menu.eesz.4M1M.build.spiffs_start=0x300000 -d1.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -d1.menu.eesz.4M1M.build.spiffs_blocksize=8192 -d1.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -d1.menu.eesz.4M.build.flash_size=4M -d1.menu.eesz.4M.build.flash_size_bytes=0x400000 -d1.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -d1.menu.eesz.4M.build.spiffs_pagesize=256 -d1.menu.eesz.4M.upload.maximum_size=1044464 -d1.menu.eesz.4M.build.rfcal_addr=0x3FC000 -d1.menu.ip.lm2f=v2 Lower Memory -d1.menu.ip.lm2f.build.lwip_include=lwip2/include -d1.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -d1.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1.menu.ip.hb2f=v2 Higher Bandwidth -d1.menu.ip.hb2f.build.lwip_include=lwip2/include -d1.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -d1.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -d1.menu.ip.lm2n=v2 Lower Memory (no features) -d1.menu.ip.lm2n.build.lwip_include=lwip2/include -d1.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -d1.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1.menu.ip.hb2n=v2 Higher Bandwidth (no features) -d1.menu.ip.hb2n.build.lwip_include=lwip2/include -d1.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -d1.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -d1.menu.ip.lm6f=v2 IPv6 Lower Memory -d1.menu.ip.lm6f.build.lwip_include=lwip2/include -d1.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -d1.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -d1.menu.ip.hb6f.build.lwip_include=lwip2/include -d1.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -d1.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -d1.menu.ip.hb1=v1.4 Higher Bandwidth -d1.menu.ip.hb1.build.lwip_lib=-llwip_gcc -d1.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.ip.src=v1.4 Compile from source -d1.menu.ip.src.build.lwip_lib=-llwip_src -d1.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -d1.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -d1.menu.dbg.Disabled=Disabled -d1.menu.dbg.Disabled.build.debug_port= -d1.menu.dbg.Serial=Serial -d1.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -d1.menu.dbg.Serial1=Serial1 -d1.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -d1.menu.lvl.None____=None -d1.menu.lvl.None____.build.debug_level= -d1.menu.lvl.SSL=SSL -d1.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -d1.menu.lvl.TLS_MEM=TLS_MEM -d1.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -d1.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -d1.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.HTTP_SERVER=HTTP_SERVER -d1.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -d1.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -d1.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -d1.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -d1.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -d1.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -d1.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -d1.menu.lvl.CORE=CORE -d1.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -d1.menu.lvl.WIFI=WIFI -d1.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -d1.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -d1.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -d1.menu.lvl.UPDATER=UPDATER -d1.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -d1.menu.lvl.OTA=OTA -d1.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -d1.menu.lvl.OOM=OOM -d1.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -d1.menu.lvl.MDNS=MDNS -d1.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -d1.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -d1.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -d1.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -d1.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -d1.menu.wipe.none=Only Sketch -d1.menu.wipe.none.upload.erase_cmd= -d1.menu.wipe.sdk=Sketch + WiFi Settings -d1.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -d1.menu.wipe.all=All Flash Contents -d1.menu.wipe.all.upload.erase_cmd=erase_flash -d1.menu.baud.921600=921600 -d1.menu.baud.921600.upload.speed=921600 -d1.menu.baud.57600=57600 -d1.menu.baud.57600.upload.speed=57600 -d1.menu.baud.115200=115200 -d1.menu.baud.115200.upload.speed=115200 -d1.menu.baud.230400.linux=230400 -d1.menu.baud.230400.macosx=230400 -d1.menu.baud.230400.upload.speed=230400 -d1.menu.baud.256000.windows=256000 -d1.menu.baud.256000.upload.speed=256000 -d1.menu.baud.460800.linux=460800 -d1.menu.baud.460800.macosx=460800 -d1.menu.baud.460800.upload.speed=460800 -d1.menu.baud.512000.windows=512000 -d1.menu.baud.512000.upload.speed=512000 -d1.menu.baud.3000000=3000000 -d1.menu.baud.3000000.upload.speed=3000000 - -############################################################## -espino.name=ESPino (ESP-12 Module) -espino.build.board=ESP8266_ESP12 -espino.build.variant=espino -espino.upload.tool=esptool -espino.upload.maximum_data_size=81920 -espino.upload.wait_for_upload_port=true -espino.upload.erase_cmd= -espino.serial.disableDTR=true -espino.serial.disableRTS=true -espino.build.mcu=esp8266 -espino.build.core=esp8266 -espino.build.spiffs_pagesize=256 -espino.build.debug_port= -espino.build.debug_level= -espino.menu.xtal.80=80 MHz -espino.menu.xtal.80.build.f_cpu=80000000L -espino.menu.xtal.160=160 MHz -espino.menu.xtal.160.build.f_cpu=160000000L -espino.menu.vt.flash=Flash -espino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espino.menu.vt.heap=Heap -espino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espino.menu.vt.iram=IRAM -espino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espino.menu.exception.legacy=Legacy (new can return nullptr) -espino.menu.exception.legacy.build.exception_flags=-fno-exceptions -espino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -espino.menu.exception.disabled=Disabled (new can abort) -espino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -espino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espino.menu.exception.enabled=Enabled -espino.menu.exception.enabled.build.exception_flags=-fexceptions -espino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espino.menu.ssl.all=All SSL ciphers (most compatible) -espino.menu.ssl.all.build.sslflags= -espino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -espino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -espino.menu.ResetMethod.nodemcu=dtr (aka nodemcu) -espino.menu.ResetMethod.nodemcu.upload.resetmethod=--before default_reset --after hard_reset -espino.menu.ResetMethod.ck=no dtr (aka ck) -espino.menu.ResetMethod.ck.upload.resetmethod=--before no_reset --after soft_reset -espino.build.flash_mode=qio -espino.build.flash_flags=-DFLASHMODE_QIO -espino.build.flash_freq=40 -espino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -espino.menu.eesz.4M2M.build.flash_size=4M -espino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espino.menu.eesz.4M2M.build.spiffs_pagesize=256 -espino.menu.eesz.4M2M.upload.maximum_size=1044464 -espino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M2M.build.spiffs_start=0x200000 -espino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -espino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -espino.menu.eesz.4M3M.build.flash_size=4M -espino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espino.menu.eesz.4M3M.build.spiffs_pagesize=256 -espino.menu.eesz.4M3M.upload.maximum_size=1044464 -espino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M3M.build.spiffs_start=0x100000 -espino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -espino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -espino.menu.eesz.4M1M.build.flash_size=4M -espino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espino.menu.eesz.4M1M.build.spiffs_pagesize=256 -espino.menu.eesz.4M1M.upload.maximum_size=1044464 -espino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espino.menu.eesz.4M1M.build.spiffs_start=0x300000 -espino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -espino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -espino.menu.eesz.4M.build.flash_size=4M -espino.menu.eesz.4M.build.flash_size_bytes=0x400000 -espino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espino.menu.eesz.4M.build.spiffs_pagesize=256 -espino.menu.eesz.4M.upload.maximum_size=1044464 -espino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espino.menu.ip.lm2f=v2 Lower Memory -espino.menu.ip.lm2f.build.lwip_include=lwip2/include -espino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espino.menu.ip.hb2f=v2 Higher Bandwidth -espino.menu.ip.hb2f.build.lwip_include=lwip2/include -espino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espino.menu.ip.lm2n=v2 Lower Memory (no features) -espino.menu.ip.lm2n.build.lwip_include=lwip2/include -espino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espino.menu.ip.hb2n.build.lwip_include=lwip2/include -espino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espino.menu.ip.lm6f=v2 IPv6 Lower Memory -espino.menu.ip.lm6f.build.lwip_include=lwip2/include -espino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espino.menu.ip.hb6f.build.lwip_include=lwip2/include -espino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espino.menu.ip.hb1=v1.4 Higher Bandwidth -espino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.ip.src=v1.4 Compile from source -espino.menu.ip.src.build.lwip_lib=-llwip_src -espino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espino.menu.dbg.Disabled=Disabled -espino.menu.dbg.Disabled.build.debug_port= -espino.menu.dbg.Serial=Serial -espino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espino.menu.dbg.Serial1=Serial1 -espino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espino.menu.lvl.None____=None -espino.menu.lvl.None____.build.debug_level= -espino.menu.lvl.SSL=SSL -espino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espino.menu.lvl.TLS_MEM=TLS_MEM -espino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.HTTP_SERVER=HTTP_SERVER -espino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espino.menu.lvl.CORE=CORE -espino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espino.menu.lvl.WIFI=WIFI -espino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espino.menu.lvl.UPDATER=UPDATER -espino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espino.menu.lvl.OTA=OTA -espino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espino.menu.lvl.OOM=OOM -espino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espino.menu.lvl.MDNS=MDNS -espino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espino.menu.wipe.none=Only Sketch -espino.menu.wipe.none.upload.erase_cmd= -espino.menu.wipe.sdk=Sketch + WiFi Settings -espino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -espino.menu.wipe.all=All Flash Contents -espino.menu.wipe.all.upload.erase_cmd=erase_flash -espino.menu.baud.115200=115200 -espino.menu.baud.115200.upload.speed=115200 -espino.menu.baud.57600=57600 -espino.menu.baud.57600.upload.speed=57600 -espino.menu.baud.230400.linux=230400 -espino.menu.baud.230400.macosx=230400 -espino.menu.baud.230400.upload.speed=230400 -espino.menu.baud.256000.windows=256000 -espino.menu.baud.256000.upload.speed=256000 -espino.menu.baud.460800.linux=460800 -espino.menu.baud.460800.macosx=460800 -espino.menu.baud.460800.upload.speed=460800 -espino.menu.baud.512000.windows=512000 -espino.menu.baud.512000.upload.speed=512000 -espino.menu.baud.921600=921600 -espino.menu.baud.921600.upload.speed=921600 -espino.menu.baud.3000000=3000000 -espino.menu.baud.3000000.upload.speed=3000000 - -############################################################## -espinotee.name=ThaiEasyElec's ESPino -espinotee.build.board=ESP8266_ESP13 -espinotee.build.variant=espinotee -espinotee.upload.tool=esptool -espinotee.upload.maximum_data_size=81920 -espinotee.upload.wait_for_upload_port=true -espinotee.upload.erase_cmd= -espinotee.serial.disableDTR=true -espinotee.serial.disableRTS=true -espinotee.build.mcu=esp8266 -espinotee.build.core=esp8266 -espinotee.build.spiffs_pagesize=256 -espinotee.build.debug_port= -espinotee.build.debug_level= -espinotee.menu.xtal.80=80 MHz -espinotee.menu.xtal.80.build.f_cpu=80000000L -espinotee.menu.xtal.160=160 MHz -espinotee.menu.xtal.160.build.f_cpu=160000000L -espinotee.menu.vt.flash=Flash -espinotee.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espinotee.menu.vt.heap=Heap -espinotee.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espinotee.menu.vt.iram=IRAM -espinotee.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espinotee.menu.exception.legacy=Legacy (new can return nullptr) -espinotee.menu.exception.legacy.build.exception_flags=-fno-exceptions -espinotee.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -espinotee.menu.exception.disabled=Disabled (new can abort) -espinotee.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -espinotee.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espinotee.menu.exception.enabled=Enabled -espinotee.menu.exception.enabled.build.exception_flags=-fexceptions -espinotee.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espinotee.menu.ssl.all=All SSL ciphers (most compatible) -espinotee.menu.ssl.all.build.sslflags= -espinotee.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -espinotee.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -espinotee.upload.resetmethod=--before default_reset --after hard_reset -espinotee.build.flash_mode=qio -espinotee.build.flash_flags=-DFLASHMODE_QIO -espinotee.build.flash_freq=40 -espinotee.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -espinotee.menu.eesz.4M2M.build.flash_size=4M -espinotee.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espinotee.menu.eesz.4M2M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M2M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M2M.build.spiffs_start=0x200000 -espinotee.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -espinotee.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espinotee.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -espinotee.menu.eesz.4M3M.build.flash_size=4M -espinotee.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espinotee.menu.eesz.4M3M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M3M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M3M.build.spiffs_start=0x100000 -espinotee.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -espinotee.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espinotee.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -espinotee.menu.eesz.4M1M.build.flash_size=4M -espinotee.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espinotee.menu.eesz.4M1M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M1M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espinotee.menu.eesz.4M1M.build.spiffs_start=0x300000 -espinotee.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -espinotee.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espinotee.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -espinotee.menu.eesz.4M.build.flash_size=4M -espinotee.menu.eesz.4M.build.flash_size_bytes=0x400000 -espinotee.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espinotee.menu.eesz.4M.build.spiffs_pagesize=256 -espinotee.menu.eesz.4M.upload.maximum_size=1044464 -espinotee.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espinotee.menu.ip.lm2f=v2 Lower Memory -espinotee.menu.ip.lm2f.build.lwip_include=lwip2/include -espinotee.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espinotee.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espinotee.menu.ip.hb2f=v2 Higher Bandwidth -espinotee.menu.ip.hb2f.build.lwip_include=lwip2/include -espinotee.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espinotee.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espinotee.menu.ip.lm2n=v2 Lower Memory (no features) -espinotee.menu.ip.lm2n.build.lwip_include=lwip2/include -espinotee.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espinotee.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espinotee.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espinotee.menu.ip.hb2n.build.lwip_include=lwip2/include -espinotee.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espinotee.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espinotee.menu.ip.lm6f=v2 IPv6 Lower Memory -espinotee.menu.ip.lm6f.build.lwip_include=lwip2/include -espinotee.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espinotee.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espinotee.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espinotee.menu.ip.hb6f.build.lwip_include=lwip2/include -espinotee.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espinotee.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espinotee.menu.ip.hb1=v1.4 Higher Bandwidth -espinotee.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espinotee.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.ip.src=v1.4 Compile from source -espinotee.menu.ip.src.build.lwip_lib=-llwip_src -espinotee.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espinotee.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espinotee.menu.dbg.Disabled=Disabled -espinotee.menu.dbg.Disabled.build.debug_port= -espinotee.menu.dbg.Serial=Serial -espinotee.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espinotee.menu.dbg.Serial1=Serial1 -espinotee.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espinotee.menu.lvl.None____=None -espinotee.menu.lvl.None____.build.debug_level= -espinotee.menu.lvl.SSL=SSL -espinotee.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espinotee.menu.lvl.TLS_MEM=TLS_MEM -espinotee.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espinotee.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espinotee.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.HTTP_SERVER=HTTP_SERVER -espinotee.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espinotee.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espinotee.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espinotee.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espinotee.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espinotee.menu.lvl.CORE=CORE -espinotee.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espinotee.menu.lvl.WIFI=WIFI -espinotee.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espinotee.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espinotee.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espinotee.menu.lvl.UPDATER=UPDATER -espinotee.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espinotee.menu.lvl.OTA=OTA -espinotee.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espinotee.menu.lvl.OOM=OOM -espinotee.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espinotee.menu.lvl.MDNS=MDNS -espinotee.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espinotee.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espinotee.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espinotee.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espinotee.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espinotee.menu.wipe.none=Only Sketch -espinotee.menu.wipe.none.upload.erase_cmd= -espinotee.menu.wipe.sdk=Sketch + WiFi Settings -espinotee.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -espinotee.menu.wipe.all=All Flash Contents -espinotee.menu.wipe.all.upload.erase_cmd=erase_flash -espinotee.menu.baud.115200=115200 -espinotee.menu.baud.115200.upload.speed=115200 -espinotee.menu.baud.57600=57600 -espinotee.menu.baud.57600.upload.speed=57600 -espinotee.menu.baud.230400.linux=230400 -espinotee.menu.baud.230400.macosx=230400 -espinotee.menu.baud.230400.upload.speed=230400 -espinotee.menu.baud.256000.windows=256000 -espinotee.menu.baud.256000.upload.speed=256000 -espinotee.menu.baud.460800.linux=460800 -espinotee.menu.baud.460800.macosx=460800 -espinotee.menu.baud.460800.upload.speed=460800 -espinotee.menu.baud.512000.windows=512000 -espinotee.menu.baud.512000.upload.speed=512000 -espinotee.menu.baud.921600=921600 -espinotee.menu.baud.921600.upload.speed=921600 -espinotee.menu.baud.3000000=3000000 -espinotee.menu.baud.3000000.upload.speed=3000000 - -############################################################## -wifinfo.name=WifInfo -wifinfo.build.board=WIFINFO -wifinfo.build.variant=wifinfo -wifinfo.menu.ESPModule.ESP07192=ESP07 (1M/192K SPIFFS) -wifinfo.menu.ESPModule.ESP07192.build.board=ESP8266_ESP07 -wifinfo.menu.ESPModule.ESP07192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.ESPModule.ESP07192.build.flash_size=1M -wifinfo.menu.ESPModule.ESP07192.build.spiffs_blocksize=4096 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_end=0xFB000 -wifinfo.menu.ESPModule.ESP07192.build.spiffs_start=0xCB000 -wifinfo.menu.ESPModule.ESP07192.upload.maximum_size=827376 -wifinfo.menu.ESPModule.ESP12=ESP12 (4M/1M SPIFFS) -wifinfo.menu.ESPModule.ESP12.build.board=ESP8266_ESP12 -wifinfo.menu.ESPModule.ESP12.build.flash_ld=eagle.flash.4m1m.ld -wifinfo.menu.ESPModule.ESP12.build.flash_size=4M -wifinfo.menu.ESPModule.ESP12.build.spiffs_blocksize=8192 -wifinfo.menu.ESPModule.ESP12.build.spiffs_end=0x3FB000 -wifinfo.menu.ESPModule.ESP12.build.spiffs_pagesize=256 -wifinfo.menu.ESPModule.ESP12.build.spiffs_start=0x300000 -wifinfo.menu.ESPModule.ESP12.upload.maximum_size=1044464 -wifinfo.upload.tool=esptool -wifinfo.upload.maximum_data_size=81920 -wifinfo.upload.wait_for_upload_port=true -wifinfo.upload.erase_cmd= -wifinfo.serial.disableDTR=true -wifinfo.serial.disableRTS=true -wifinfo.build.mcu=esp8266 -wifinfo.build.core=esp8266 -wifinfo.build.spiffs_pagesize=256 -wifinfo.build.debug_port= -wifinfo.build.debug_level= -wifinfo.menu.xtal.80=80 MHz -wifinfo.menu.xtal.80.build.f_cpu=80000000L -wifinfo.menu.xtal.160=160 MHz -wifinfo.menu.xtal.160.build.f_cpu=160000000L -wifinfo.menu.vt.flash=Flash -wifinfo.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifinfo.menu.vt.heap=Heap -wifinfo.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifinfo.menu.vt.iram=IRAM -wifinfo.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifinfo.menu.exception.legacy=Legacy (new can return nullptr) -wifinfo.menu.exception.legacy.build.exception_flags=-fno-exceptions -wifinfo.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -wifinfo.menu.exception.disabled=Disabled (new can abort) -wifinfo.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -wifinfo.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -wifinfo.menu.exception.enabled=Enabled -wifinfo.menu.exception.enabled.build.exception_flags=-fexceptions -wifinfo.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -wifinfo.menu.ssl.all=All SSL ciphers (most compatible) -wifinfo.menu.ssl.all.build.sslflags= -wifinfo.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -wifinfo.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -wifinfo.upload.resetmethod=--before default_reset --after hard_reset -wifinfo.build.flash_mode=qio -wifinfo.build.flash_flags=-DFLASHMODE_QIO -wifinfo.menu.FlashFreq.40=40MHz -wifinfo.menu.FlashFreq.40.build.flash_freq=40 -wifinfo.menu.FlashFreq.80=80MHz -wifinfo.menu.FlashFreq.80.build.flash_freq=80 -wifinfo.menu.FlashFreq.20=20MHz -wifinfo.menu.FlashFreq.20.build.flash_freq=20 -wifinfo.menu.FlashFreq.26=26MHz -wifinfo.menu.FlashFreq.26.build.flash_freq=26 -wifinfo.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) -wifinfo.menu.eesz.1M64.build.flash_size=1M -wifinfo.menu.eesz.1M64.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -wifinfo.menu.eesz.1M64.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M64.upload.maximum_size=958448 -wifinfo.menu.eesz.1M64.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M64.build.spiffs_start=0xEB000 -wifinfo.menu.eesz.1M64.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M64.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) -wifinfo.menu.eesz.1M128.build.flash_size=1M -wifinfo.menu.eesz.1M128.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -wifinfo.menu.eesz.1M128.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M128.upload.maximum_size=892912 -wifinfo.menu.eesz.1M128.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M128.build.spiffs_start=0xDB000 -wifinfo.menu.eesz.1M128.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M128.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) -wifinfo.menu.eesz.1M144.build.flash_size=1M -wifinfo.menu.eesz.1M144.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -wifinfo.menu.eesz.1M144.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M144.upload.maximum_size=876528 -wifinfo.menu.eesz.1M144.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M144.build.spiffs_start=0xD7000 -wifinfo.menu.eesz.1M144.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M144.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) -wifinfo.menu.eesz.1M160.build.flash_size=1M -wifinfo.menu.eesz.1M160.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -wifinfo.menu.eesz.1M160.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M160.upload.maximum_size=860144 -wifinfo.menu.eesz.1M160.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M160.build.spiffs_start=0xD3000 -wifinfo.menu.eesz.1M160.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M160.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) -wifinfo.menu.eesz.1M192.build.flash_size=1M -wifinfo.menu.eesz.1M192.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -wifinfo.menu.eesz.1M192.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M192.upload.maximum_size=827376 -wifinfo.menu.eesz.1M192.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M192.build.spiffs_start=0xCB000 -wifinfo.menu.eesz.1M192.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M192.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) -wifinfo.menu.eesz.1M256.build.flash_size=1M -wifinfo.menu.eesz.1M256.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -wifinfo.menu.eesz.1M256.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M256.upload.maximum_size=761840 -wifinfo.menu.eesz.1M256.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M256.build.spiffs_start=0xBB000 -wifinfo.menu.eesz.1M256.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M256.build.spiffs_blocksize=4096 -wifinfo.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) -wifinfo.menu.eesz.1M512.build.flash_size=1M -wifinfo.menu.eesz.1M512.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -wifinfo.menu.eesz.1M512.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M512.upload.maximum_size=499696 -wifinfo.menu.eesz.1M512.build.rfcal_addr=0xFC000 -wifinfo.menu.eesz.1M512.build.spiffs_start=0x7B000 -wifinfo.menu.eesz.1M512.build.spiffs_end=0xFB000 -wifinfo.menu.eesz.1M512.build.spiffs_blocksize=8192 -wifinfo.menu.eesz.1M=1MB (FS:none OTA:~502KB) -wifinfo.menu.eesz.1M.build.flash_size=1M -wifinfo.menu.eesz.1M.build.flash_size_bytes=0x100000 -wifinfo.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -wifinfo.menu.eesz.1M.build.spiffs_pagesize=256 -wifinfo.menu.eesz.1M.upload.maximum_size=1023984 -wifinfo.menu.eesz.1M.build.rfcal_addr=0xFC000 -wifinfo.menu.ip.lm2f=v2 Lower Memory -wifinfo.menu.ip.lm2f.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifinfo.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifinfo.menu.ip.hb2f=v2 Higher Bandwidth -wifinfo.menu.ip.hb2f.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifinfo.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifinfo.menu.ip.lm2n=v2 Lower Memory (no features) -wifinfo.menu.ip.lm2n.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifinfo.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifinfo.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifinfo.menu.ip.hb2n.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifinfo.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifinfo.menu.ip.lm6f=v2 IPv6 Lower Memory -wifinfo.menu.ip.lm6f.build.lwip_include=lwip2/include -wifinfo.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifinfo.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifinfo.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifinfo.menu.ip.hb6f.build.lwip_include=lwip2/include -wifinfo.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifinfo.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifinfo.menu.ip.hb1=v1.4 Higher Bandwidth -wifinfo.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifinfo.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.ip.src=v1.4 Compile from source -wifinfo.menu.ip.src.build.lwip_lib=-llwip_src -wifinfo.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifinfo.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifinfo.menu.dbg.Disabled=Disabled -wifinfo.menu.dbg.Disabled.build.debug_port= -wifinfo.menu.dbg.Serial=Serial -wifinfo.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifinfo.menu.dbg.Serial1=Serial1 -wifinfo.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifinfo.menu.lvl.None____=None -wifinfo.menu.lvl.None____.build.debug_level= -wifinfo.menu.lvl.SSL=SSL -wifinfo.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifinfo.menu.lvl.TLS_MEM=TLS_MEM -wifinfo.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifinfo.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifinfo.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifinfo.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifinfo.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifinfo.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifinfo.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifinfo.menu.lvl.CORE=CORE -wifinfo.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifinfo.menu.lvl.WIFI=WIFI -wifinfo.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifinfo.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifinfo.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifinfo.menu.lvl.UPDATER=UPDATER -wifinfo.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifinfo.menu.lvl.OTA=OTA -wifinfo.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifinfo.menu.lvl.OOM=OOM -wifinfo.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifinfo.menu.lvl.MDNS=MDNS -wifinfo.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -wifinfo.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -wifinfo.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -wifinfo.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifinfo.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifinfo.menu.wipe.none=Only Sketch -wifinfo.menu.wipe.none.upload.erase_cmd= -wifinfo.menu.wipe.sdk=Sketch + WiFi Settings -wifinfo.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -wifinfo.menu.wipe.all=All Flash Contents -wifinfo.menu.wipe.all.upload.erase_cmd=erase_flash -wifinfo.menu.baud.115200=115200 -wifinfo.menu.baud.115200.upload.speed=115200 -wifinfo.menu.baud.57600=57600 -wifinfo.menu.baud.57600.upload.speed=57600 -wifinfo.menu.baud.230400.linux=230400 -wifinfo.menu.baud.230400.macosx=230400 -wifinfo.menu.baud.230400.upload.speed=230400 -wifinfo.menu.baud.256000.windows=256000 -wifinfo.menu.baud.256000.upload.speed=256000 -wifinfo.menu.baud.460800.linux=460800 -wifinfo.menu.baud.460800.macosx=460800 -wifinfo.menu.baud.460800.upload.speed=460800 -wifinfo.menu.baud.512000.windows=512000 -wifinfo.menu.baud.512000.upload.speed=512000 -wifinfo.menu.baud.921600=921600 -wifinfo.menu.baud.921600.upload.speed=921600 -wifinfo.menu.baud.3000000=3000000 -wifinfo.menu.baud.3000000.upload.speed=3000000 - -############################################################## -arduino-esp8266.name=Arduino -arduino-esp8266.build.board=ESP8266_ARDUINO -arduino-esp8266.menu.BoardModel.primo=Primo -arduino-esp8266.menu.BoardModel.primo.build.board=ESP8266_ARDUINO_PRIMO -arduino-esp8266.menu.BoardModel.primo.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.primo.build.variant=arduino_spi -arduino-esp8266.menu.BoardModel.starottodeved=Star OTTO -arduino-esp8266.menu.BoardModel.starottodeved.build.board=ESP8266_ARDUINO_STAR_OTTO -arduino-esp8266.menu.BoardModel.starottodeved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.starottodeved.build.variant=arduino_uart -arduino-esp8266.menu.BoardModel.unowifideved=Uno WiFi -arduino-esp8266.menu.BoardModel.unowifideved.build.board=ESP8266_ARDUINO_UNOWIFI -arduino-esp8266.menu.BoardModel.unowifideved.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266 -arduino-esp8266.menu.BoardModel.unowifideved.build.variant=arduino_uart -arduino-esp8266.upload.tool=esptool -arduino-esp8266.upload.maximum_data_size=81920 -arduino-esp8266.upload.wait_for_upload_port=true -arduino-esp8266.upload.erase_cmd= -arduino-esp8266.serial.disableDTR=true -arduino-esp8266.serial.disableRTS=true -arduino-esp8266.build.mcu=esp8266 -arduino-esp8266.build.core=esp8266 -arduino-esp8266.build.variant=generic -arduino-esp8266.build.spiffs_pagesize=256 -arduino-esp8266.build.debug_port= -arduino-esp8266.build.debug_level= -arduino-esp8266.menu.xtal.80=80 MHz -arduino-esp8266.menu.xtal.80.build.f_cpu=80000000L -arduino-esp8266.menu.xtal.160=160 MHz -arduino-esp8266.menu.xtal.160.build.f_cpu=160000000L -arduino-esp8266.menu.vt.flash=Flash -arduino-esp8266.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -arduino-esp8266.menu.vt.heap=Heap -arduino-esp8266.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -arduino-esp8266.menu.vt.iram=IRAM -arduino-esp8266.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -arduino-esp8266.menu.exception.legacy=Legacy (new can return nullptr) -arduino-esp8266.menu.exception.legacy.build.exception_flags=-fno-exceptions -arduino-esp8266.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -arduino-esp8266.menu.exception.disabled=Disabled (new can abort) -arduino-esp8266.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -arduino-esp8266.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -arduino-esp8266.menu.exception.enabled=Enabled -arduino-esp8266.menu.exception.enabled.build.exception_flags=-fexceptions -arduino-esp8266.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -arduino-esp8266.menu.ssl.all=All SSL ciphers (most compatible) -arduino-esp8266.menu.ssl.all.build.sslflags= -arduino-esp8266.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -arduino-esp8266.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -arduino-esp8266.upload.resetmethod=--before no_reset --after soft_reset -arduino-esp8266.build.flash_mode=qio -arduino-esp8266.build.flash_flags=-DFLASHMODE_QIO -arduino-esp8266.build.flash_freq=40 -arduino-esp8266.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -arduino-esp8266.menu.eesz.4M2M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -arduino-esp8266.menu.eesz.4M2M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M2M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_start=0x200000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -arduino-esp8266.menu.eesz.4M2M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -arduino-esp8266.menu.eesz.4M3M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -arduino-esp8266.menu.eesz.4M3M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M3M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_start=0x100000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -arduino-esp8266.menu.eesz.4M3M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -arduino-esp8266.menu.eesz.4M1M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -arduino-esp8266.menu.eesz.4M1M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M1M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_start=0x300000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -arduino-esp8266.menu.eesz.4M1M.build.spiffs_blocksize=8192 -arduino-esp8266.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -arduino-esp8266.menu.eesz.4M.build.flash_size=4M -arduino-esp8266.menu.eesz.4M.build.flash_size_bytes=0x400000 -arduino-esp8266.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -arduino-esp8266.menu.eesz.4M.build.spiffs_pagesize=256 -arduino-esp8266.menu.eesz.4M.upload.maximum_size=1044464 -arduino-esp8266.menu.eesz.4M.build.rfcal_addr=0x3FC000 -arduino-esp8266.menu.ip.lm2f=v2 Lower Memory -arduino-esp8266.menu.ip.lm2f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -arduino-esp8266.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.hb2f=v2 Higher Bandwidth -arduino-esp8266.menu.ip.hb2f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -arduino-esp8266.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.lm2n=v2 Lower Memory (no features) -arduino-esp8266.menu.ip.lm2n.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -arduino-esp8266.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.hb2n=v2 Higher Bandwidth (no features) -arduino-esp8266.menu.ip.hb2n.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -arduino-esp8266.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -arduino-esp8266.menu.ip.lm6f=v2 IPv6 Lower Memory -arduino-esp8266.menu.ip.lm6f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -arduino-esp8266.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -arduino-esp8266.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -arduino-esp8266.menu.ip.hb6f.build.lwip_include=lwip2/include -arduino-esp8266.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -arduino-esp8266.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -arduino-esp8266.menu.ip.hb1=v1.4 Higher Bandwidth -arduino-esp8266.menu.ip.hb1.build.lwip_lib=-llwip_gcc -arduino-esp8266.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.ip.src=v1.4 Compile from source -arduino-esp8266.menu.ip.src.build.lwip_lib=-llwip_src -arduino-esp8266.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -arduino-esp8266.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -arduino-esp8266.menu.dbg.Disabled=Disabled -arduino-esp8266.menu.dbg.Disabled.build.debug_port= -arduino-esp8266.menu.dbg.Serial=Serial -arduino-esp8266.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -arduino-esp8266.menu.dbg.Serial1=Serial1 -arduino-esp8266.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -arduino-esp8266.menu.lvl.None____=None -arduino-esp8266.menu.lvl.None____.build.debug_level= -arduino-esp8266.menu.lvl.SSL=SSL -arduino-esp8266.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -arduino-esp8266.menu.lvl.TLS_MEM=TLS_MEM -arduino-esp8266.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -arduino-esp8266.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.HTTP_SERVER=HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -arduino-esp8266.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -arduino-esp8266.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -arduino-esp8266.menu.lvl.CORE=CORE -arduino-esp8266.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -arduino-esp8266.menu.lvl.WIFI=WIFI -arduino-esp8266.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -arduino-esp8266.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -arduino-esp8266.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -arduino-esp8266.menu.lvl.UPDATER=UPDATER -arduino-esp8266.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -arduino-esp8266.menu.lvl.OTA=OTA -arduino-esp8266.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -arduino-esp8266.menu.lvl.OOM=OOM -arduino-esp8266.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -arduino-esp8266.menu.lvl.MDNS=MDNS -arduino-esp8266.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -arduino-esp8266.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -arduino-esp8266.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -arduino-esp8266.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -arduino-esp8266.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -arduino-esp8266.menu.wipe.none=Only Sketch -arduino-esp8266.menu.wipe.none.upload.erase_cmd= -arduino-esp8266.menu.wipe.sdk=Sketch + WiFi Settings -arduino-esp8266.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -arduino-esp8266.menu.wipe.all=All Flash Contents -arduino-esp8266.menu.wipe.all.upload.erase_cmd=erase_flash -arduino-esp8266.menu.baud.115200=115200 -arduino-esp8266.menu.baud.115200.upload.speed=115200 -arduino-esp8266.menu.baud.57600=57600 -arduino-esp8266.menu.baud.57600.upload.speed=57600 -arduino-esp8266.menu.baud.230400.linux=230400 -arduino-esp8266.menu.baud.230400.macosx=230400 -arduino-esp8266.menu.baud.230400.upload.speed=230400 -arduino-esp8266.menu.baud.256000.windows=256000 -arduino-esp8266.menu.baud.256000.upload.speed=256000 -arduino-esp8266.menu.baud.460800.linux=460800 -arduino-esp8266.menu.baud.460800.macosx=460800 -arduino-esp8266.menu.baud.460800.upload.speed=460800 -arduino-esp8266.menu.baud.512000.windows=512000 -arduino-esp8266.menu.baud.512000.upload.speed=512000 -arduino-esp8266.menu.baud.921600=921600 -arduino-esp8266.menu.baud.921600.upload.speed=921600 -arduino-esp8266.menu.baud.3000000=3000000 -arduino-esp8266.menu.baud.3000000.upload.speed=3000000 - -############################################################## -gen4iod.name=4D Systems gen4 IoD Range -gen4iod.build.board=GEN4_IOD -gen4iod.build.f_cpu=160000000L -gen4iod.build.variant=generic -gen4iod.upload.tool=esptool -gen4iod.upload.maximum_data_size=81920 -gen4iod.upload.wait_for_upload_port=true -gen4iod.upload.erase_cmd= -gen4iod.serial.disableDTR=true -gen4iod.serial.disableRTS=true -gen4iod.build.mcu=esp8266 -gen4iod.build.core=esp8266 -gen4iod.build.spiffs_pagesize=256 -gen4iod.build.debug_port= -gen4iod.build.debug_level= -gen4iod.menu.xtal.80=80 MHz -gen4iod.menu.xtal.80.build.f_cpu=80000000L -gen4iod.menu.xtal.160=160 MHz -gen4iod.menu.xtal.160.build.f_cpu=160000000L -gen4iod.menu.vt.flash=Flash -gen4iod.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -gen4iod.menu.vt.heap=Heap -gen4iod.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -gen4iod.menu.vt.iram=IRAM -gen4iod.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -gen4iod.menu.exception.legacy=Legacy (new can return nullptr) -gen4iod.menu.exception.legacy.build.exception_flags=-fno-exceptions -gen4iod.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -gen4iod.menu.exception.disabled=Disabled (new can abort) -gen4iod.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -gen4iod.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -gen4iod.menu.exception.enabled=Enabled -gen4iod.menu.exception.enabled.build.exception_flags=-fexceptions -gen4iod.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -gen4iod.menu.ssl.all=All SSL ciphers (most compatible) -gen4iod.menu.ssl.all.build.sslflags= -gen4iod.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -gen4iod.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -gen4iod.upload.resetmethod=--before default_reset --after hard_reset -gen4iod.build.flash_mode=dio -gen4iod.build.flash_flags=-DFLASHMODE_DIO -gen4iod.build.flash_freq=80 -gen4iod.menu.eesz.512K32=512KB (FS:32KB OTA:~230KB) -gen4iod.menu.eesz.512K32.build.flash_size=512K -gen4iod.menu.eesz.512K32.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K32.build.flash_ld=eagle.flash.512k32.ld -gen4iod.menu.eesz.512K32.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K32.upload.maximum_size=466928 -gen4iod.menu.eesz.512K32.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K32.build.spiffs_start=0x73000 -gen4iod.menu.eesz.512K32.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K32.build.spiffs_blocksize=4096 -gen4iod.menu.eesz.512K64=512KB (FS:64KB OTA:~214KB) -gen4iod.menu.eesz.512K64.build.flash_size=512K -gen4iod.menu.eesz.512K64.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K64.build.flash_ld=eagle.flash.512k64.ld -gen4iod.menu.eesz.512K64.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K64.upload.maximum_size=434160 -gen4iod.menu.eesz.512K64.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K64.build.spiffs_start=0x6B000 -gen4iod.menu.eesz.512K64.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K64.build.spiffs_blocksize=4096 -gen4iod.menu.eesz.512K128=512KB (FS:128KB OTA:~182KB) -gen4iod.menu.eesz.512K128.build.flash_size=512K -gen4iod.menu.eesz.512K128.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K128.build.flash_ld=eagle.flash.512k128.ld -gen4iod.menu.eesz.512K128.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K128.upload.maximum_size=368624 -gen4iod.menu.eesz.512K128.build.rfcal_addr=0x7C000 -gen4iod.menu.eesz.512K128.build.spiffs_start=0x5B000 -gen4iod.menu.eesz.512K128.build.spiffs_end=0x7B000 -gen4iod.menu.eesz.512K128.build.spiffs_blocksize=4096 -gen4iod.menu.eesz.512K=512KB (FS:none OTA:~246KB) -gen4iod.menu.eesz.512K.build.flash_size=512K -gen4iod.menu.eesz.512K.build.flash_size_bytes=0x80000 -gen4iod.menu.eesz.512K.build.flash_ld=eagle.flash.512k.ld -gen4iod.menu.eesz.512K.build.spiffs_pagesize=256 -gen4iod.menu.eesz.512K.upload.maximum_size=499696 -gen4iod.menu.eesz.512K.build.rfcal_addr=0x7C000 -gen4iod.menu.ip.lm2f=v2 Lower Memory -gen4iod.menu.ip.lm2f.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -gen4iod.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -gen4iod.menu.ip.hb2f=v2 Higher Bandwidth -gen4iod.menu.ip.hb2f.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -gen4iod.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -gen4iod.menu.ip.lm2n=v2 Lower Memory (no features) -gen4iod.menu.ip.lm2n.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -gen4iod.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -gen4iod.menu.ip.hb2n=v2 Higher Bandwidth (no features) -gen4iod.menu.ip.hb2n.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -gen4iod.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -gen4iod.menu.ip.lm6f=v2 IPv6 Lower Memory -gen4iod.menu.ip.lm6f.build.lwip_include=lwip2/include -gen4iod.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -gen4iod.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -gen4iod.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -gen4iod.menu.ip.hb6f.build.lwip_include=lwip2/include -gen4iod.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -gen4iod.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -gen4iod.menu.ip.hb1=v1.4 Higher Bandwidth -gen4iod.menu.ip.hb1.build.lwip_lib=-llwip_gcc -gen4iod.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.ip.src=v1.4 Compile from source -gen4iod.menu.ip.src.build.lwip_lib=-llwip_src -gen4iod.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -gen4iod.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -gen4iod.menu.dbg.Disabled=Disabled -gen4iod.menu.dbg.Disabled.build.debug_port= -gen4iod.menu.dbg.Serial=Serial -gen4iod.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -gen4iod.menu.dbg.Serial1=Serial1 -gen4iod.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -gen4iod.menu.lvl.None____=None -gen4iod.menu.lvl.None____.build.debug_level= -gen4iod.menu.lvl.SSL=SSL -gen4iod.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -gen4iod.menu.lvl.TLS_MEM=TLS_MEM -gen4iod.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -gen4iod.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -gen4iod.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.HTTP_SERVER=HTTP_SERVER -gen4iod.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -gen4iod.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -gen4iod.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -gen4iod.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -gen4iod.menu.lvl.CORE=CORE -gen4iod.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -gen4iod.menu.lvl.WIFI=WIFI -gen4iod.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -gen4iod.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -gen4iod.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -gen4iod.menu.lvl.UPDATER=UPDATER -gen4iod.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -gen4iod.menu.lvl.OTA=OTA -gen4iod.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -gen4iod.menu.lvl.OOM=OOM -gen4iod.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -gen4iod.menu.lvl.MDNS=MDNS -gen4iod.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -gen4iod.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -gen4iod.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -gen4iod.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -gen4iod.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -gen4iod.menu.wipe.none=Only Sketch -gen4iod.menu.wipe.none.upload.erase_cmd= -gen4iod.menu.wipe.sdk=Sketch + WiFi Settings -gen4iod.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -gen4iod.menu.wipe.all=All Flash Contents -gen4iod.menu.wipe.all.upload.erase_cmd=erase_flash -gen4iod.menu.baud.115200=115200 -gen4iod.menu.baud.115200.upload.speed=115200 -gen4iod.menu.baud.57600=57600 -gen4iod.menu.baud.57600.upload.speed=57600 -gen4iod.menu.baud.230400.linux=230400 -gen4iod.menu.baud.230400.macosx=230400 -gen4iod.menu.baud.230400.upload.speed=230400 -gen4iod.menu.baud.256000.windows=256000 -gen4iod.menu.baud.256000.upload.speed=256000 -gen4iod.menu.baud.460800.linux=460800 -gen4iod.menu.baud.460800.macosx=460800 -gen4iod.menu.baud.460800.upload.speed=460800 -gen4iod.menu.baud.512000.windows=512000 -gen4iod.menu.baud.512000.upload.speed=512000 -gen4iod.menu.baud.921600=921600 -gen4iod.menu.baud.921600.upload.speed=921600 -gen4iod.menu.baud.3000000=3000000 -gen4iod.menu.baud.3000000.upload.speed=3000000 - -############################################################## -oak.name=Digistump Oak -oak.build.board=ESP8266_OAK -oak.build.variant=oak -oak.upload.maximum_size=1040368 -oak.upload.tool=esptool -oak.upload.maximum_data_size=81920 -oak.upload.wait_for_upload_port=true -oak.upload.erase_cmd= -oak.serial.disableDTR=true -oak.serial.disableRTS=true -oak.build.mcu=esp8266 -oak.build.core=esp8266 -oak.build.spiffs_pagesize=256 -oak.build.debug_port= -oak.build.debug_level= -oak.menu.xtal.80=80 MHz -oak.menu.xtal.80.build.f_cpu=80000000L -oak.menu.xtal.160=160 MHz -oak.menu.xtal.160.build.f_cpu=160000000L -oak.menu.vt.flash=Flash -oak.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -oak.menu.vt.heap=Heap -oak.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -oak.menu.vt.iram=IRAM -oak.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -oak.menu.exception.legacy=Legacy (new can return nullptr) -oak.menu.exception.legacy.build.exception_flags=-fno-exceptions -oak.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -oak.menu.exception.disabled=Disabled (new can abort) -oak.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -oak.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -oak.menu.exception.enabled=Enabled -oak.menu.exception.enabled.build.exception_flags=-fexceptions -oak.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -oak.menu.ssl.all=All SSL ciphers (most compatible) -oak.menu.ssl.all.build.sslflags= -oak.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -oak.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -oak.upload.resetmethod=--before no_reset --after soft_reset -oak.build.flash_mode=dio -oak.build.flash_flags=-DFLASHMODE_DIO -oak.build.flash_freq=40 -oak.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -oak.menu.eesz.4M2M.build.flash_size=4M -oak.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -oak.menu.eesz.4M2M.build.spiffs_pagesize=256 -oak.menu.eesz.4M2M.upload.maximum_size=1044464 -oak.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M2M.build.spiffs_start=0x200000 -oak.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -oak.menu.eesz.4M2M.build.spiffs_blocksize=8192 -oak.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -oak.menu.eesz.4M3M.build.flash_size=4M -oak.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -oak.menu.eesz.4M3M.build.spiffs_pagesize=256 -oak.menu.eesz.4M3M.upload.maximum_size=1044464 -oak.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M3M.build.spiffs_start=0x100000 -oak.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -oak.menu.eesz.4M3M.build.spiffs_blocksize=8192 -oak.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -oak.menu.eesz.4M1M.build.flash_size=4M -oak.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -oak.menu.eesz.4M1M.build.spiffs_pagesize=256 -oak.menu.eesz.4M1M.upload.maximum_size=1044464 -oak.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -oak.menu.eesz.4M1M.build.spiffs_start=0x300000 -oak.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -oak.menu.eesz.4M1M.build.spiffs_blocksize=8192 -oak.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -oak.menu.eesz.4M.build.flash_size=4M -oak.menu.eesz.4M.build.flash_size_bytes=0x400000 -oak.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -oak.menu.eesz.4M.build.spiffs_pagesize=256 -oak.menu.eesz.4M.upload.maximum_size=1044464 -oak.menu.eesz.4M.build.rfcal_addr=0x3FC000 -oak.menu.ip.lm2f=v2 Lower Memory -oak.menu.ip.lm2f.build.lwip_include=lwip2/include -oak.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -oak.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -oak.menu.ip.hb2f=v2 Higher Bandwidth -oak.menu.ip.hb2f.build.lwip_include=lwip2/include -oak.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -oak.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -oak.menu.ip.lm2n=v2 Lower Memory (no features) -oak.menu.ip.lm2n.build.lwip_include=lwip2/include -oak.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -oak.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -oak.menu.ip.hb2n=v2 Higher Bandwidth (no features) -oak.menu.ip.hb2n.build.lwip_include=lwip2/include -oak.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -oak.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -oak.menu.ip.lm6f=v2 IPv6 Lower Memory -oak.menu.ip.lm6f.build.lwip_include=lwip2/include -oak.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -oak.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -oak.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -oak.menu.ip.hb6f.build.lwip_include=lwip2/include -oak.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -oak.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -oak.menu.ip.hb1=v1.4 Higher Bandwidth -oak.menu.ip.hb1.build.lwip_lib=-llwip_gcc -oak.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.ip.src=v1.4 Compile from source -oak.menu.ip.src.build.lwip_lib=-llwip_src -oak.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -oak.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -oak.menu.dbg.Disabled=Disabled -oak.menu.dbg.Disabled.build.debug_port= -oak.menu.dbg.Serial=Serial -oak.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -oak.menu.dbg.Serial1=Serial1 -oak.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -oak.menu.lvl.None____=None -oak.menu.lvl.None____.build.debug_level= -oak.menu.lvl.SSL=SSL -oak.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -oak.menu.lvl.TLS_MEM=TLS_MEM -oak.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -oak.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -oak.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.HTTP_SERVER=HTTP_SERVER -oak.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -oak.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -oak.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -oak.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -oak.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -oak.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -oak.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -oak.menu.lvl.CORE=CORE -oak.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -oak.menu.lvl.WIFI=WIFI -oak.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -oak.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -oak.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -oak.menu.lvl.UPDATER=UPDATER -oak.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -oak.menu.lvl.OTA=OTA -oak.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -oak.menu.lvl.OOM=OOM -oak.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -oak.menu.lvl.MDNS=MDNS -oak.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -oak.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -oak.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -oak.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -oak.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -oak.menu.wipe.none=Only Sketch -oak.menu.wipe.none.upload.erase_cmd= -oak.menu.wipe.sdk=Sketch + WiFi Settings -oak.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -oak.menu.wipe.all=All Flash Contents -oak.menu.wipe.all.upload.erase_cmd=erase_flash -oak.menu.baud.921600=921600 -oak.menu.baud.921600.upload.speed=921600 -oak.menu.baud.57600=57600 -oak.menu.baud.57600.upload.speed=57600 -oak.menu.baud.115200=115200 -oak.menu.baud.115200.upload.speed=115200 -oak.menu.baud.230400.linux=230400 -oak.menu.baud.230400.macosx=230400 -oak.menu.baud.230400.upload.speed=230400 -oak.menu.baud.256000.windows=256000 -oak.menu.baud.256000.upload.speed=256000 -oak.menu.baud.460800.linux=460800 -oak.menu.baud.460800.macosx=460800 -oak.menu.baud.460800.upload.speed=460800 -oak.menu.baud.512000.windows=512000 -oak.menu.baud.512000.upload.speed=512000 -oak.menu.baud.3000000=3000000 -oak.menu.baud.3000000.upload.speed=3000000 - -############################################################## -wifiduino.name=WiFiduino -wifiduino.build.board=WIFIDUINO_ESP8266 -wifiduino.build.variant=wifiduino -wifiduino.upload.tool=esptool -wifiduino.upload.maximum_data_size=81920 -wifiduino.upload.wait_for_upload_port=true -wifiduino.upload.erase_cmd= -wifiduino.serial.disableDTR=true -wifiduino.serial.disableRTS=true -wifiduino.build.mcu=esp8266 -wifiduino.build.core=esp8266 -wifiduino.build.spiffs_pagesize=256 -wifiduino.build.debug_port= -wifiduino.build.debug_level= -wifiduino.menu.xtal.80=80 MHz -wifiduino.menu.xtal.80.build.f_cpu=80000000L -wifiduino.menu.xtal.160=160 MHz -wifiduino.menu.xtal.160.build.f_cpu=160000000L -wifiduino.menu.vt.flash=Flash -wifiduino.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifiduino.menu.vt.heap=Heap -wifiduino.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifiduino.menu.vt.iram=IRAM -wifiduino.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifiduino.menu.exception.legacy=Legacy (new can return nullptr) -wifiduino.menu.exception.legacy.build.exception_flags=-fno-exceptions -wifiduino.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -wifiduino.menu.exception.disabled=Disabled (new can abort) -wifiduino.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -wifiduino.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -wifiduino.menu.exception.enabled=Enabled -wifiduino.menu.exception.enabled.build.exception_flags=-fexceptions -wifiduino.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -wifiduino.menu.ssl.all=All SSL ciphers (most compatible) -wifiduino.menu.ssl.all.build.sslflags= -wifiduino.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -wifiduino.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -wifiduino.upload.resetmethod=--before default_reset --after hard_reset -wifiduino.build.flash_mode=dio -wifiduino.build.flash_flags=-DFLASHMODE_DIO -wifiduino.build.flash_freq=40 -wifiduino.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -wifiduino.menu.eesz.4M2M.build.flash_size=4M -wifiduino.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -wifiduino.menu.eesz.4M2M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M2M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M2M.build.spiffs_start=0x200000 -wifiduino.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -wifiduino.menu.eesz.4M2M.build.spiffs_blocksize=8192 -wifiduino.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -wifiduino.menu.eesz.4M3M.build.flash_size=4M -wifiduino.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -wifiduino.menu.eesz.4M3M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M3M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M3M.build.spiffs_start=0x100000 -wifiduino.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -wifiduino.menu.eesz.4M3M.build.spiffs_blocksize=8192 -wifiduino.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -wifiduino.menu.eesz.4M1M.build.flash_size=4M -wifiduino.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -wifiduino.menu.eesz.4M1M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M1M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -wifiduino.menu.eesz.4M1M.build.spiffs_start=0x300000 -wifiduino.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -wifiduino.menu.eesz.4M1M.build.spiffs_blocksize=8192 -wifiduino.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -wifiduino.menu.eesz.4M.build.flash_size=4M -wifiduino.menu.eesz.4M.build.flash_size_bytes=0x400000 -wifiduino.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -wifiduino.menu.eesz.4M.build.spiffs_pagesize=256 -wifiduino.menu.eesz.4M.upload.maximum_size=1044464 -wifiduino.menu.eesz.4M.build.rfcal_addr=0x3FC000 -wifiduino.menu.ip.lm2f=v2 Lower Memory -wifiduino.menu.ip.lm2f.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifiduino.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifiduino.menu.ip.hb2f=v2 Higher Bandwidth -wifiduino.menu.ip.hb2f.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifiduino.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifiduino.menu.ip.lm2n=v2 Lower Memory (no features) -wifiduino.menu.ip.lm2n.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifiduino.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifiduino.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifiduino.menu.ip.hb2n.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifiduino.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifiduino.menu.ip.lm6f=v2 IPv6 Lower Memory -wifiduino.menu.ip.lm6f.build.lwip_include=lwip2/include -wifiduino.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifiduino.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifiduino.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifiduino.menu.ip.hb6f.build.lwip_include=lwip2/include -wifiduino.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifiduino.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifiduino.menu.ip.hb1=v1.4 Higher Bandwidth -wifiduino.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifiduino.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifiduino.menu.ip.src=v1.4 Compile from source -wifiduino.menu.ip.src.build.lwip_lib=-llwip_src -wifiduino.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifiduino.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifiduino.menu.dbg.Disabled=Disabled -wifiduino.menu.dbg.Disabled.build.debug_port= -wifiduino.menu.dbg.Serial=Serial -wifiduino.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifiduino.menu.dbg.Serial1=Serial1 -wifiduino.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifiduino.menu.lvl.None____=None -wifiduino.menu.lvl.None____.build.debug_level= -wifiduino.menu.lvl.SSL=SSL -wifiduino.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifiduino.menu.lvl.TLS_MEM=TLS_MEM -wifiduino.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifiduino.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifiduino.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifiduino.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifiduino.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifiduino.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifiduino.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifiduino.menu.lvl.CORE=CORE -wifiduino.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifiduino.menu.lvl.WIFI=WIFI -wifiduino.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifiduino.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifiduino.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifiduino.menu.lvl.UPDATER=UPDATER -wifiduino.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifiduino.menu.lvl.OTA=OTA -wifiduino.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifiduino.menu.lvl.OOM=OOM -wifiduino.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifiduino.menu.lvl.MDNS=MDNS -wifiduino.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -wifiduino.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -wifiduino.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -wifiduino.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifiduino.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifiduino.menu.wipe.none=Only Sketch -wifiduino.menu.wipe.none.upload.erase_cmd= -wifiduino.menu.wipe.sdk=Sketch + WiFi Settings -wifiduino.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -wifiduino.menu.wipe.all=All Flash Contents -wifiduino.menu.wipe.all.upload.erase_cmd=erase_flash -wifiduino.menu.baud.921600=921600 -wifiduino.menu.baud.921600.upload.speed=921600 -wifiduino.menu.baud.57600=57600 -wifiduino.menu.baud.57600.upload.speed=57600 -wifiduino.menu.baud.115200=115200 -wifiduino.menu.baud.115200.upload.speed=115200 -wifiduino.menu.baud.230400.linux=230400 -wifiduino.menu.baud.230400.macosx=230400 -wifiduino.menu.baud.230400.upload.speed=230400 -wifiduino.menu.baud.256000.windows=256000 -wifiduino.menu.baud.256000.upload.speed=256000 -wifiduino.menu.baud.460800.linux=460800 -wifiduino.menu.baud.460800.macosx=460800 -wifiduino.menu.baud.460800.upload.speed=460800 -wifiduino.menu.baud.512000.windows=512000 -wifiduino.menu.baud.512000.upload.speed=512000 -wifiduino.menu.baud.3000000=3000000 -wifiduino.menu.baud.3000000.upload.speed=3000000 - -############################################################## -wifi_slot.name=Amperka WiFi Slot -wifi_slot.build.board=AMPERKA_WIFI_SLOT -wifi_slot.build.variant=wifi_slot -wifi_slot.upload.tool=esptool -wifi_slot.upload.maximum_data_size=81920 -wifi_slot.upload.wait_for_upload_port=true -wifi_slot.upload.erase_cmd= -wifi_slot.serial.disableDTR=true -wifi_slot.serial.disableRTS=true -wifi_slot.build.mcu=esp8266 -wifi_slot.build.core=esp8266 -wifi_slot.build.spiffs_pagesize=256 -wifi_slot.build.debug_port= -wifi_slot.build.debug_level= -wifi_slot.menu.xtal.80=80 MHz -wifi_slot.menu.xtal.80.build.f_cpu=80000000L -wifi_slot.menu.xtal.160=160 MHz -wifi_slot.menu.xtal.160.build.f_cpu=160000000L -wifi_slot.menu.vt.flash=Flash -wifi_slot.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wifi_slot.menu.vt.heap=Heap -wifi_slot.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wifi_slot.menu.vt.iram=IRAM -wifi_slot.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wifi_slot.menu.exception.legacy=Legacy (new can return nullptr) -wifi_slot.menu.exception.legacy.build.exception_flags=-fno-exceptions -wifi_slot.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -wifi_slot.menu.exception.disabled=Disabled (new can abort) -wifi_slot.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -wifi_slot.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -wifi_slot.menu.exception.enabled=Enabled -wifi_slot.menu.exception.enabled.build.exception_flags=-fexceptions -wifi_slot.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -wifi_slot.menu.ssl.all=All SSL ciphers (most compatible) -wifi_slot.menu.ssl.all.build.sslflags= -wifi_slot.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -wifi_slot.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -wifi_slot.upload.resetmethod=--before default_reset --after hard_reset -wifi_slot.menu.FlashFreq.40=40MHz -wifi_slot.menu.FlashFreq.40.build.flash_freq=40 -wifi_slot.menu.FlashFreq.80=80MHz -wifi_slot.menu.FlashFreq.80.build.flash_freq=80 -wifi_slot.menu.FlashFreq.20=20MHz -wifi_slot.menu.FlashFreq.20.build.flash_freq=20 -wifi_slot.menu.FlashFreq.26=26MHz -wifi_slot.menu.FlashFreq.26.build.flash_freq=26 -wifi_slot.menu.FlashMode.dout=DOUT (compatible) -wifi_slot.menu.FlashMode.dout.build.flash_mode=dout -wifi_slot.menu.FlashMode.dout.build.flash_flags=-DFLASHMODE_DOUT -wifi_slot.menu.FlashMode.dio=DIO -wifi_slot.menu.FlashMode.dio.build.flash_mode=dio -wifi_slot.menu.FlashMode.dio.build.flash_flags=-DFLASHMODE_DIO -wifi_slot.menu.FlashMode.qout=QOUT -wifi_slot.menu.FlashMode.qout.build.flash_mode=qout -wifi_slot.menu.FlashMode.qout.build.flash_flags=-DFLASHMODE_QOUT -wifi_slot.menu.FlashMode.qio=QIO (fast) -wifi_slot.menu.FlashMode.qio.build.flash_mode=qio -wifi_slot.menu.FlashMode.qio.build.flash_flags=-DFLASHMODE_QIO -wifi_slot.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) -wifi_slot.menu.eesz.1M64.build.flash_size=1M -wifi_slot.menu.eesz.1M64.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -wifi_slot.menu.eesz.1M64.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M64.upload.maximum_size=958448 -wifi_slot.menu.eesz.1M64.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M64.build.spiffs_start=0xEB000 -wifi_slot.menu.eesz.1M64.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M64.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) -wifi_slot.menu.eesz.1M128.build.flash_size=1M -wifi_slot.menu.eesz.1M128.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -wifi_slot.menu.eesz.1M128.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M128.upload.maximum_size=892912 -wifi_slot.menu.eesz.1M128.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M128.build.spiffs_start=0xDB000 -wifi_slot.menu.eesz.1M128.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M128.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) -wifi_slot.menu.eesz.1M144.build.flash_size=1M -wifi_slot.menu.eesz.1M144.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -wifi_slot.menu.eesz.1M144.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M144.upload.maximum_size=876528 -wifi_slot.menu.eesz.1M144.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M144.build.spiffs_start=0xD7000 -wifi_slot.menu.eesz.1M144.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M144.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) -wifi_slot.menu.eesz.1M160.build.flash_size=1M -wifi_slot.menu.eesz.1M160.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -wifi_slot.menu.eesz.1M160.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M160.upload.maximum_size=860144 -wifi_slot.menu.eesz.1M160.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M160.build.spiffs_start=0xD3000 -wifi_slot.menu.eesz.1M160.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M160.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) -wifi_slot.menu.eesz.1M192.build.flash_size=1M -wifi_slot.menu.eesz.1M192.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -wifi_slot.menu.eesz.1M192.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M192.upload.maximum_size=827376 -wifi_slot.menu.eesz.1M192.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M192.build.spiffs_start=0xCB000 -wifi_slot.menu.eesz.1M192.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M192.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) -wifi_slot.menu.eesz.1M256.build.flash_size=1M -wifi_slot.menu.eesz.1M256.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -wifi_slot.menu.eesz.1M256.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M256.upload.maximum_size=761840 -wifi_slot.menu.eesz.1M256.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M256.build.spiffs_start=0xBB000 -wifi_slot.menu.eesz.1M256.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M256.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) -wifi_slot.menu.eesz.1M512.build.flash_size=1M -wifi_slot.menu.eesz.1M512.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -wifi_slot.menu.eesz.1M512.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M512.upload.maximum_size=499696 -wifi_slot.menu.eesz.1M512.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.1M512.build.spiffs_start=0x7B000 -wifi_slot.menu.eesz.1M512.build.spiffs_end=0xFB000 -wifi_slot.menu.eesz.1M512.build.spiffs_blocksize=8192 -wifi_slot.menu.eesz.1M=1MB (FS:none OTA:~502KB) -wifi_slot.menu.eesz.1M.build.flash_size=1M -wifi_slot.menu.eesz.1M.build.flash_size_bytes=0x100000 -wifi_slot.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -wifi_slot.menu.eesz.1M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.1M.upload.maximum_size=1023984 -wifi_slot.menu.eesz.1M.build.rfcal_addr=0xFC000 -wifi_slot.menu.eesz.2M64=2MB (FS:64KB OTA:~992KB) -wifi_slot.menu.eesz.2M64.build.flash_size=2M -wifi_slot.menu.eesz.2M64.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M64.build.flash_ld=eagle.flash.2m64.ld -wifi_slot.menu.eesz.2M64.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M64.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M64.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M64.build.spiffs_start=0x1F0000 -wifi_slot.menu.eesz.2M64.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M64.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M128=2MB (FS:128KB OTA:~960KB) -wifi_slot.menu.eesz.2M128.build.flash_size=2M -wifi_slot.menu.eesz.2M128.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M128.build.flash_ld=eagle.flash.2m128.ld -wifi_slot.menu.eesz.2M128.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M128.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M128.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M128.build.spiffs_start=0x1E0000 -wifi_slot.menu.eesz.2M128.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M128.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M256=2MB (FS:256KB OTA:~896KB) -wifi_slot.menu.eesz.2M256.build.flash_size=2M -wifi_slot.menu.eesz.2M256.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M256.build.flash_ld=eagle.flash.2m256.ld -wifi_slot.menu.eesz.2M256.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M256.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M256.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M256.build.spiffs_start=0x1C0000 -wifi_slot.menu.eesz.2M256.build.spiffs_end=0x1FB000 -wifi_slot.menu.eesz.2M256.build.spiffs_blocksize=4096 -wifi_slot.menu.eesz.2M512=2MB (FS:512KB OTA:~768KB) -wifi_slot.menu.eesz.2M512.build.flash_size=2M -wifi_slot.menu.eesz.2M512.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M512.build.flash_ld=eagle.flash.2m512.ld -wifi_slot.menu.eesz.2M512.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M512.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M512.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M512.build.spiffs_start=0x180000 -wifi_slot.menu.eesz.2M512.build.spiffs_end=0x1FA000 -wifi_slot.menu.eesz.2M512.build.spiffs_blocksize=8192 -wifi_slot.menu.eesz.2M1M=2MB (FS:1MB OTA:~512KB) -wifi_slot.menu.eesz.2M1M.build.flash_size=2M -wifi_slot.menu.eesz.2M1M.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M1M.build.flash_ld=eagle.flash.2m1m.ld -wifi_slot.menu.eesz.2M1M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M1M.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M1M.build.rfcal_addr=0x1FC000 -wifi_slot.menu.eesz.2M1M.build.spiffs_start=0x100000 -wifi_slot.menu.eesz.2M1M.build.spiffs_end=0x1FA000 -wifi_slot.menu.eesz.2M1M.build.spiffs_blocksize=8192 -wifi_slot.menu.eesz.2M=2MB (FS:none OTA:~1019KB) -wifi_slot.menu.eesz.2M.build.flash_size=2M -wifi_slot.menu.eesz.2M.build.flash_size_bytes=0x200000 -wifi_slot.menu.eesz.2M.build.flash_ld=eagle.flash.2m.ld -wifi_slot.menu.eesz.2M.build.spiffs_pagesize=256 -wifi_slot.menu.eesz.2M.upload.maximum_size=1044464 -wifi_slot.menu.eesz.2M.build.rfcal_addr=0x1FC000 -wifi_slot.menu.ip.lm2f=v2 Lower Memory -wifi_slot.menu.ip.lm2f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wifi_slot.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifi_slot.menu.ip.hb2f=v2 Higher Bandwidth -wifi_slot.menu.ip.hb2f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wifi_slot.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wifi_slot.menu.ip.lm2n=v2 Lower Memory (no features) -wifi_slot.menu.ip.lm2n.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wifi_slot.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifi_slot.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wifi_slot.menu.ip.hb2n.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wifi_slot.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wifi_slot.menu.ip.lm6f=v2 IPv6 Lower Memory -wifi_slot.menu.ip.lm6f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wifi_slot.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifi_slot.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wifi_slot.menu.ip.hb6f.build.lwip_include=lwip2/include -wifi_slot.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wifi_slot.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wifi_slot.menu.ip.hb1=v1.4 Higher Bandwidth -wifi_slot.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wifi_slot.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wifi_slot.menu.ip.src=v1.4 Compile from source -wifi_slot.menu.ip.src.build.lwip_lib=-llwip_src -wifi_slot.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wifi_slot.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wifi_slot.menu.dbg.Disabled=Disabled -wifi_slot.menu.dbg.Disabled.build.debug_port= -wifi_slot.menu.dbg.Serial=Serial -wifi_slot.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wifi_slot.menu.dbg.Serial1=Serial1 -wifi_slot.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wifi_slot.menu.lvl.None____=None -wifi_slot.menu.lvl.None____.build.debug_level= -wifi_slot.menu.lvl.SSL=SSL -wifi_slot.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wifi_slot.menu.lvl.TLS_MEM=TLS_MEM -wifi_slot.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wifi_slot.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wifi_slot.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.HTTP_SERVER=HTTP_SERVER -wifi_slot.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wifi_slot.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wifi_slot.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wifi_slot.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wifi_slot.menu.lvl.CORE=CORE -wifi_slot.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wifi_slot.menu.lvl.WIFI=WIFI -wifi_slot.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wifi_slot.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wifi_slot.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wifi_slot.menu.lvl.UPDATER=UPDATER -wifi_slot.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wifi_slot.menu.lvl.OTA=OTA -wifi_slot.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wifi_slot.menu.lvl.OOM=OOM -wifi_slot.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wifi_slot.menu.lvl.MDNS=MDNS -wifi_slot.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -wifi_slot.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -wifi_slot.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -wifi_slot.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wifi_slot.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wifi_slot.menu.wipe.none=Only Sketch -wifi_slot.menu.wipe.none.upload.erase_cmd= -wifi_slot.menu.wipe.sdk=Sketch + WiFi Settings -wifi_slot.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -wifi_slot.menu.wipe.all=All Flash Contents -wifi_slot.menu.wipe.all.upload.erase_cmd=erase_flash -wifi_slot.menu.baud.115200=115200 -wifi_slot.menu.baud.115200.upload.speed=115200 -wifi_slot.menu.baud.57600=57600 -wifi_slot.menu.baud.57600.upload.speed=57600 -wifi_slot.menu.baud.230400.linux=230400 -wifi_slot.menu.baud.230400.macosx=230400 -wifi_slot.menu.baud.230400.upload.speed=230400 -wifi_slot.menu.baud.256000.windows=256000 -wifi_slot.menu.baud.256000.upload.speed=256000 -wifi_slot.menu.baud.460800.linux=460800 -wifi_slot.menu.baud.460800.macosx=460800 -wifi_slot.menu.baud.460800.upload.speed=460800 -wifi_slot.menu.baud.512000.windows=512000 -wifi_slot.menu.baud.512000.upload.speed=512000 -wifi_slot.menu.baud.921600=921600 -wifi_slot.menu.baud.921600.upload.speed=921600 -wifi_slot.menu.baud.3000000=3000000 -wifi_slot.menu.baud.3000000.upload.speed=3000000 - -############################################################## -wiolink.name=Seeed Wio Link -wiolink.build.board=ESP8266_WIO_LINK -wiolink.build.variant=wiolink -wiolink.upload.tool=esptool -wiolink.upload.maximum_data_size=81920 -wiolink.upload.wait_for_upload_port=true -wiolink.upload.erase_cmd= -wiolink.serial.disableDTR=true -wiolink.serial.disableRTS=true -wiolink.build.mcu=esp8266 -wiolink.build.core=esp8266 -wiolink.build.spiffs_pagesize=256 -wiolink.build.debug_port= -wiolink.build.debug_level= -wiolink.menu.xtal.80=80 MHz -wiolink.menu.xtal.80.build.f_cpu=80000000L -wiolink.menu.xtal.160=160 MHz -wiolink.menu.xtal.160.build.f_cpu=160000000L -wiolink.menu.vt.flash=Flash -wiolink.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -wiolink.menu.vt.heap=Heap -wiolink.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -wiolink.menu.vt.iram=IRAM -wiolink.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -wiolink.menu.exception.legacy=Legacy (new can return nullptr) -wiolink.menu.exception.legacy.build.exception_flags=-fno-exceptions -wiolink.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -wiolink.menu.exception.disabled=Disabled (new can abort) -wiolink.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -wiolink.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -wiolink.menu.exception.enabled=Enabled -wiolink.menu.exception.enabled.build.exception_flags=-fexceptions -wiolink.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -wiolink.menu.ssl.all=All SSL ciphers (most compatible) -wiolink.menu.ssl.all.build.sslflags= -wiolink.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -wiolink.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -wiolink.upload.resetmethod=--before default_reset --after hard_reset -wiolink.build.flash_mode=qio -wiolink.build.flash_flags=-DFLASHMODE_QIO -wiolink.build.flash_freq=40 -wiolink.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -wiolink.menu.eesz.4M2M.build.flash_size=4M -wiolink.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -wiolink.menu.eesz.4M2M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M2M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M2M.build.spiffs_start=0x200000 -wiolink.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -wiolink.menu.eesz.4M2M.build.spiffs_blocksize=8192 -wiolink.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -wiolink.menu.eesz.4M3M.build.flash_size=4M -wiolink.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -wiolink.menu.eesz.4M3M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M3M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M3M.build.spiffs_start=0x100000 -wiolink.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -wiolink.menu.eesz.4M3M.build.spiffs_blocksize=8192 -wiolink.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -wiolink.menu.eesz.4M1M.build.flash_size=4M -wiolink.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -wiolink.menu.eesz.4M1M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M1M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -wiolink.menu.eesz.4M1M.build.spiffs_start=0x300000 -wiolink.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -wiolink.menu.eesz.4M1M.build.spiffs_blocksize=8192 -wiolink.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -wiolink.menu.eesz.4M.build.flash_size=4M -wiolink.menu.eesz.4M.build.flash_size_bytes=0x400000 -wiolink.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -wiolink.menu.eesz.4M.build.spiffs_pagesize=256 -wiolink.menu.eesz.4M.upload.maximum_size=1044464 -wiolink.menu.eesz.4M.build.rfcal_addr=0x3FC000 -wiolink.menu.ip.lm2f=v2 Lower Memory -wiolink.menu.ip.lm2f.build.lwip_include=lwip2/include -wiolink.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -wiolink.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wiolink.menu.ip.hb2f=v2 Higher Bandwidth -wiolink.menu.ip.hb2f.build.lwip_include=lwip2/include -wiolink.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -wiolink.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -wiolink.menu.ip.lm2n=v2 Lower Memory (no features) -wiolink.menu.ip.lm2n.build.lwip_include=lwip2/include -wiolink.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -wiolink.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wiolink.menu.ip.hb2n=v2 Higher Bandwidth (no features) -wiolink.menu.ip.hb2n.build.lwip_include=lwip2/include -wiolink.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -wiolink.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -wiolink.menu.ip.lm6f=v2 IPv6 Lower Memory -wiolink.menu.ip.lm6f.build.lwip_include=lwip2/include -wiolink.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -wiolink.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wiolink.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -wiolink.menu.ip.hb6f.build.lwip_include=lwip2/include -wiolink.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -wiolink.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -wiolink.menu.ip.hb1=v1.4 Higher Bandwidth -wiolink.menu.ip.hb1.build.lwip_lib=-llwip_gcc -wiolink.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -wiolink.menu.ip.src=v1.4 Compile from source -wiolink.menu.ip.src.build.lwip_lib=-llwip_src -wiolink.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -wiolink.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -wiolink.menu.dbg.Disabled=Disabled -wiolink.menu.dbg.Disabled.build.debug_port= -wiolink.menu.dbg.Serial=Serial -wiolink.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -wiolink.menu.dbg.Serial1=Serial1 -wiolink.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -wiolink.menu.lvl.None____=None -wiolink.menu.lvl.None____.build.debug_level= -wiolink.menu.lvl.SSL=SSL -wiolink.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -wiolink.menu.lvl.TLS_MEM=TLS_MEM -wiolink.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -wiolink.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -wiolink.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.HTTP_SERVER=HTTP_SERVER -wiolink.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -wiolink.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -wiolink.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -wiolink.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -wiolink.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -wiolink.menu.lvl.CORE=CORE -wiolink.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -wiolink.menu.lvl.WIFI=WIFI -wiolink.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -wiolink.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -wiolink.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -wiolink.menu.lvl.UPDATER=UPDATER -wiolink.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -wiolink.menu.lvl.OTA=OTA -wiolink.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -wiolink.menu.lvl.OOM=OOM -wiolink.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -wiolink.menu.lvl.MDNS=MDNS -wiolink.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -wiolink.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -wiolink.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -wiolink.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -wiolink.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -wiolink.menu.wipe.none=Only Sketch -wiolink.menu.wipe.none.upload.erase_cmd= -wiolink.menu.wipe.sdk=Sketch + WiFi Settings -wiolink.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -wiolink.menu.wipe.all=All Flash Contents -wiolink.menu.wipe.all.upload.erase_cmd=erase_flash -wiolink.menu.baud.115200=115200 -wiolink.menu.baud.115200.upload.speed=115200 -wiolink.menu.baud.57600=57600 -wiolink.menu.baud.57600.upload.speed=57600 -wiolink.menu.baud.230400.linux=230400 -wiolink.menu.baud.230400.macosx=230400 -wiolink.menu.baud.230400.upload.speed=230400 -wiolink.menu.baud.256000.windows=256000 -wiolink.menu.baud.256000.upload.speed=256000 -wiolink.menu.baud.460800.linux=460800 -wiolink.menu.baud.460800.macosx=460800 -wiolink.menu.baud.460800.upload.speed=460800 -wiolink.menu.baud.512000.windows=512000 -wiolink.menu.baud.512000.upload.speed=512000 -wiolink.menu.baud.921600=921600 -wiolink.menu.baud.921600.upload.speed=921600 -wiolink.menu.baud.3000000=3000000 -wiolink.menu.baud.3000000.upload.speed=3000000 - -############################################################## -espectro.name=ESPectro Core -espectro.build.board=ESP8266_ESPECTRO_CORE -espectro.build.variant=espectro -espectro.upload.tool=esptool -espectro.upload.maximum_data_size=81920 -espectro.upload.wait_for_upload_port=true -espectro.upload.erase_cmd= -espectro.serial.disableDTR=true -espectro.serial.disableRTS=true -espectro.build.mcu=esp8266 -espectro.build.core=esp8266 -espectro.build.spiffs_pagesize=256 -espectro.build.debug_port= -espectro.build.debug_level= -espectro.menu.xtal.80=80 MHz -espectro.menu.xtal.80.build.f_cpu=80000000L -espectro.menu.xtal.160=160 MHz -espectro.menu.xtal.160.build.f_cpu=160000000L -espectro.menu.vt.flash=Flash -espectro.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espectro.menu.vt.heap=Heap -espectro.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espectro.menu.vt.iram=IRAM -espectro.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espectro.menu.exception.legacy=Legacy (new can return nullptr) -espectro.menu.exception.legacy.build.exception_flags=-fno-exceptions -espectro.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -espectro.menu.exception.disabled=Disabled (new can abort) -espectro.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -espectro.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espectro.menu.exception.enabled=Enabled -espectro.menu.exception.enabled.build.exception_flags=-fexceptions -espectro.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espectro.menu.ssl.all=All SSL ciphers (most compatible) -espectro.menu.ssl.all.build.sslflags= -espectro.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -espectro.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -espectro.upload.resetmethod=--before default_reset --after hard_reset -espectro.build.flash_mode=dio -espectro.build.flash_flags=-DFLASHMODE_DIO -espectro.build.flash_freq=40 -espectro.menu.eesz.4M2M=4MB (FS:2MB OTA:~1019KB) -espectro.menu.eesz.4M2M.build.flash_size=4M -espectro.menu.eesz.4M2M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M2M.build.flash_ld=eagle.flash.4m2m.ld -espectro.menu.eesz.4M2M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M2M.upload.maximum_size=1044464 -espectro.menu.eesz.4M2M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M2M.build.spiffs_start=0x200000 -espectro.menu.eesz.4M2M.build.spiffs_end=0x3FA000 -espectro.menu.eesz.4M2M.build.spiffs_blocksize=8192 -espectro.menu.eesz.4M3M=4MB (FS:3MB OTA:~512KB) -espectro.menu.eesz.4M3M.build.flash_size=4M -espectro.menu.eesz.4M3M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M3M.build.flash_ld=eagle.flash.4m3m.ld -espectro.menu.eesz.4M3M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M3M.upload.maximum_size=1044464 -espectro.menu.eesz.4M3M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M3M.build.spiffs_start=0x100000 -espectro.menu.eesz.4M3M.build.spiffs_end=0x3FA000 -espectro.menu.eesz.4M3M.build.spiffs_blocksize=8192 -espectro.menu.eesz.4M1M=4MB (FS:1MB OTA:~1019KB) -espectro.menu.eesz.4M1M.build.flash_size=4M -espectro.menu.eesz.4M1M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M1M.build.flash_ld=eagle.flash.4m1m.ld -espectro.menu.eesz.4M1M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M1M.upload.maximum_size=1044464 -espectro.menu.eesz.4M1M.build.rfcal_addr=0x3FC000 -espectro.menu.eesz.4M1M.build.spiffs_start=0x300000 -espectro.menu.eesz.4M1M.build.spiffs_end=0x3FA000 -espectro.menu.eesz.4M1M.build.spiffs_blocksize=8192 -espectro.menu.eesz.4M=4MB (FS:none OTA:~1019KB) -espectro.menu.eesz.4M.build.flash_size=4M -espectro.menu.eesz.4M.build.flash_size_bytes=0x400000 -espectro.menu.eesz.4M.build.flash_ld=eagle.flash.4m.ld -espectro.menu.eesz.4M.build.spiffs_pagesize=256 -espectro.menu.eesz.4M.upload.maximum_size=1044464 -espectro.menu.eesz.4M.build.rfcal_addr=0x3FC000 -espectro.menu.ip.lm2f=v2 Lower Memory -espectro.menu.ip.lm2f.build.lwip_include=lwip2/include -espectro.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espectro.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espectro.menu.ip.hb2f=v2 Higher Bandwidth -espectro.menu.ip.hb2f.build.lwip_include=lwip2/include -espectro.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espectro.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espectro.menu.ip.lm2n=v2 Lower Memory (no features) -espectro.menu.ip.lm2n.build.lwip_include=lwip2/include -espectro.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espectro.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espectro.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espectro.menu.ip.hb2n.build.lwip_include=lwip2/include -espectro.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espectro.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espectro.menu.ip.lm6f=v2 IPv6 Lower Memory -espectro.menu.ip.lm6f.build.lwip_include=lwip2/include -espectro.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espectro.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espectro.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espectro.menu.ip.hb6f.build.lwip_include=lwip2/include -espectro.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espectro.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espectro.menu.ip.hb1=v1.4 Higher Bandwidth -espectro.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espectro.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espectro.menu.ip.src=v1.4 Compile from source -espectro.menu.ip.src.build.lwip_lib=-llwip_src -espectro.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espectro.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espectro.menu.dbg.Disabled=Disabled -espectro.menu.dbg.Disabled.build.debug_port= -espectro.menu.dbg.Serial=Serial -espectro.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espectro.menu.dbg.Serial1=Serial1 -espectro.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espectro.menu.lvl.None____=None -espectro.menu.lvl.None____.build.debug_level= -espectro.menu.lvl.SSL=SSL -espectro.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espectro.menu.lvl.TLS_MEM=TLS_MEM -espectro.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espectro.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espectro.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.HTTP_SERVER=HTTP_SERVER -espectro.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espectro.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espectro.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espectro.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espectro.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espectro.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espectro.menu.lvl.CORE=CORE -espectro.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espectro.menu.lvl.WIFI=WIFI -espectro.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espectro.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espectro.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espectro.menu.lvl.UPDATER=UPDATER -espectro.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espectro.menu.lvl.OTA=OTA -espectro.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espectro.menu.lvl.OOM=OOM -espectro.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espectro.menu.lvl.MDNS=MDNS -espectro.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espectro.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espectro.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espectro.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espectro.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espectro.menu.wipe.none=Only Sketch -espectro.menu.wipe.none.upload.erase_cmd= -espectro.menu.wipe.sdk=Sketch + WiFi Settings -espectro.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -espectro.menu.wipe.all=All Flash Contents -espectro.menu.wipe.all.upload.erase_cmd=erase_flash -espectro.menu.baud.115200=115200 -espectro.menu.baud.115200.upload.speed=115200 -espectro.menu.baud.57600=57600 -espectro.menu.baud.57600.upload.speed=57600 -espectro.menu.baud.230400.linux=230400 -espectro.menu.baud.230400.macosx=230400 -espectro.menu.baud.230400.upload.speed=230400 -espectro.menu.baud.256000.windows=256000 -espectro.menu.baud.256000.upload.speed=256000 -espectro.menu.baud.460800.linux=460800 -espectro.menu.baud.460800.macosx=460800 -espectro.menu.baud.460800.upload.speed=460800 -espectro.menu.baud.512000.windows=512000 -espectro.menu.baud.512000.upload.speed=512000 -espectro.menu.baud.921600=921600 -espectro.menu.baud.921600.upload.speed=921600 -espectro.menu.baud.3000000=3000000 -espectro.menu.baud.3000000.upload.speed=3000000 - -############################################################## -sonoff.name=ITEAD Sonoff -sonoff.build.board=SONOFF_SV -sonoff.build.extra_flags=-DESP8266 -sonoff.build.flash_size=1M -sonoff.build.variant=itead -sonoff.menu.BoardModel.sonoffBasic=ITEAD Sonoff Basic -sonoff.menu.BoardModel.sonoffBasic.build.board=SONOFF_BASIC -sonoff.menu.BoardModel.sonoffS20=ITEAD Sonoff S20 -sonoff.menu.BoardModel.sonoffS20.build.board=SONOFF_S20 -sonoff.menu.BoardModel.sonoffSV=ITEAD Sonoff SV -sonoff.menu.BoardModel.sonoffSV.build.board=SONOFF_SV -sonoff.menu.BoardModel.sonoffTH=ITEAD Sonoff TH -sonoff.menu.BoardModel.sonoffTH.build.board=SONOFF_TH -sonoff.upload.tool=esptool -sonoff.upload.maximum_data_size=81920 -sonoff.upload.wait_for_upload_port=true -sonoff.upload.erase_cmd= -sonoff.serial.disableDTR=true -sonoff.serial.disableRTS=true -sonoff.build.mcu=esp8266 -sonoff.build.core=esp8266 -sonoff.build.spiffs_pagesize=256 -sonoff.build.debug_port= -sonoff.build.debug_level= -sonoff.menu.xtal.80=80 MHz -sonoff.menu.xtal.80.build.f_cpu=80000000L -sonoff.menu.xtal.160=160 MHz -sonoff.menu.xtal.160.build.f_cpu=160000000L -sonoff.menu.vt.flash=Flash -sonoff.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -sonoff.menu.vt.heap=Heap -sonoff.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -sonoff.menu.vt.iram=IRAM -sonoff.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -sonoff.menu.exception.legacy=Legacy (new can return nullptr) -sonoff.menu.exception.legacy.build.exception_flags=-fno-exceptions -sonoff.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -sonoff.menu.exception.disabled=Disabled (new can abort) -sonoff.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -sonoff.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -sonoff.menu.exception.enabled=Enabled -sonoff.menu.exception.enabled.build.exception_flags=-fexceptions -sonoff.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -sonoff.menu.ssl.all=All SSL ciphers (most compatible) -sonoff.menu.ssl.all.build.sslflags= -sonoff.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -sonoff.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -sonoff.upload.resetmethod=--before no_reset --after soft_reset -sonoff.build.flash_mode=dout -sonoff.build.flash_flags=-DFLASHMODE_DOUT -sonoff.build.flash_freq=40 -sonoff.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) -sonoff.menu.eesz.1M64.build.flash_size=1M -sonoff.menu.eesz.1M64.build.flash_size_bytes=0x100000 -sonoff.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -sonoff.menu.eesz.1M64.build.spiffs_pagesize=256 -sonoff.menu.eesz.1M64.upload.maximum_size=958448 -sonoff.menu.eesz.1M64.build.rfcal_addr=0xFC000 -sonoff.menu.eesz.1M64.build.spiffs_start=0xEB000 -sonoff.menu.eesz.1M64.build.spiffs_end=0xFB000 -sonoff.menu.eesz.1M64.build.spiffs_blocksize=4096 -sonoff.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) -sonoff.menu.eesz.1M128.build.flash_size=1M -sonoff.menu.eesz.1M128.build.flash_size_bytes=0x100000 -sonoff.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -sonoff.menu.eesz.1M128.build.spiffs_pagesize=256 -sonoff.menu.eesz.1M128.upload.maximum_size=892912 -sonoff.menu.eesz.1M128.build.rfcal_addr=0xFC000 -sonoff.menu.eesz.1M128.build.spiffs_start=0xDB000 -sonoff.menu.eesz.1M128.build.spiffs_end=0xFB000 -sonoff.menu.eesz.1M128.build.spiffs_blocksize=4096 -sonoff.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) -sonoff.menu.eesz.1M144.build.flash_size=1M -sonoff.menu.eesz.1M144.build.flash_size_bytes=0x100000 -sonoff.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -sonoff.menu.eesz.1M144.build.spiffs_pagesize=256 -sonoff.menu.eesz.1M144.upload.maximum_size=876528 -sonoff.menu.eesz.1M144.build.rfcal_addr=0xFC000 -sonoff.menu.eesz.1M144.build.spiffs_start=0xD7000 -sonoff.menu.eesz.1M144.build.spiffs_end=0xFB000 -sonoff.menu.eesz.1M144.build.spiffs_blocksize=4096 -sonoff.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) -sonoff.menu.eesz.1M160.build.flash_size=1M -sonoff.menu.eesz.1M160.build.flash_size_bytes=0x100000 -sonoff.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -sonoff.menu.eesz.1M160.build.spiffs_pagesize=256 -sonoff.menu.eesz.1M160.upload.maximum_size=860144 -sonoff.menu.eesz.1M160.build.rfcal_addr=0xFC000 -sonoff.menu.eesz.1M160.build.spiffs_start=0xD3000 -sonoff.menu.eesz.1M160.build.spiffs_end=0xFB000 -sonoff.menu.eesz.1M160.build.spiffs_blocksize=4096 -sonoff.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) -sonoff.menu.eesz.1M192.build.flash_size=1M -sonoff.menu.eesz.1M192.build.flash_size_bytes=0x100000 -sonoff.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -sonoff.menu.eesz.1M192.build.spiffs_pagesize=256 -sonoff.menu.eesz.1M192.upload.maximum_size=827376 -sonoff.menu.eesz.1M192.build.rfcal_addr=0xFC000 -sonoff.menu.eesz.1M192.build.spiffs_start=0xCB000 -sonoff.menu.eesz.1M192.build.spiffs_end=0xFB000 -sonoff.menu.eesz.1M192.build.spiffs_blocksize=4096 -sonoff.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) -sonoff.menu.eesz.1M256.build.flash_size=1M -sonoff.menu.eesz.1M256.build.flash_size_bytes=0x100000 -sonoff.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -sonoff.menu.eesz.1M256.build.spiffs_pagesize=256 -sonoff.menu.eesz.1M256.upload.maximum_size=761840 -sonoff.menu.eesz.1M256.build.rfcal_addr=0xFC000 -sonoff.menu.eesz.1M256.build.spiffs_start=0xBB000 -sonoff.menu.eesz.1M256.build.spiffs_end=0xFB000 -sonoff.menu.eesz.1M256.build.spiffs_blocksize=4096 -sonoff.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) -sonoff.menu.eesz.1M512.build.flash_size=1M -sonoff.menu.eesz.1M512.build.flash_size_bytes=0x100000 -sonoff.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -sonoff.menu.eesz.1M512.build.spiffs_pagesize=256 -sonoff.menu.eesz.1M512.upload.maximum_size=499696 -sonoff.menu.eesz.1M512.build.rfcal_addr=0xFC000 -sonoff.menu.eesz.1M512.build.spiffs_start=0x7B000 -sonoff.menu.eesz.1M512.build.spiffs_end=0xFB000 -sonoff.menu.eesz.1M512.build.spiffs_blocksize=8192 -sonoff.menu.eesz.1M=1MB (FS:none OTA:~502KB) -sonoff.menu.eesz.1M.build.flash_size=1M -sonoff.menu.eesz.1M.build.flash_size_bytes=0x100000 -sonoff.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -sonoff.menu.eesz.1M.build.spiffs_pagesize=256 -sonoff.menu.eesz.1M.upload.maximum_size=1023984 -sonoff.menu.eesz.1M.build.rfcal_addr=0xFC000 -sonoff.menu.ip.lm2f=v2 Lower Memory -sonoff.menu.ip.lm2f.build.lwip_include=lwip2/include -sonoff.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -sonoff.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -sonoff.menu.ip.hb2f=v2 Higher Bandwidth -sonoff.menu.ip.hb2f.build.lwip_include=lwip2/include -sonoff.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -sonoff.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -sonoff.menu.ip.lm2n=v2 Lower Memory (no features) -sonoff.menu.ip.lm2n.build.lwip_include=lwip2/include -sonoff.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -sonoff.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -sonoff.menu.ip.hb2n=v2 Higher Bandwidth (no features) -sonoff.menu.ip.hb2n.build.lwip_include=lwip2/include -sonoff.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -sonoff.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -sonoff.menu.ip.lm6f=v2 IPv6 Lower Memory -sonoff.menu.ip.lm6f.build.lwip_include=lwip2/include -sonoff.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -sonoff.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -sonoff.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -sonoff.menu.ip.hb6f.build.lwip_include=lwip2/include -sonoff.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -sonoff.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -sonoff.menu.ip.hb1=v1.4 Higher Bandwidth -sonoff.menu.ip.hb1.build.lwip_lib=-llwip_gcc -sonoff.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -sonoff.menu.ip.src=v1.4 Compile from source -sonoff.menu.ip.src.build.lwip_lib=-llwip_src -sonoff.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -sonoff.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -sonoff.menu.dbg.Disabled=Disabled -sonoff.menu.dbg.Disabled.build.debug_port= -sonoff.menu.dbg.Serial=Serial -sonoff.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -sonoff.menu.dbg.Serial1=Serial1 -sonoff.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -sonoff.menu.lvl.None____=None -sonoff.menu.lvl.None____.build.debug_level= -sonoff.menu.lvl.SSL=SSL -sonoff.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -sonoff.menu.lvl.TLS_MEM=TLS_MEM -sonoff.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -sonoff.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -sonoff.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -sonoff.menu.lvl.HTTP_SERVER=HTTP_SERVER -sonoff.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -sonoff.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -sonoff.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -sonoff.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -sonoff.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -sonoff.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -sonoff.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -sonoff.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -sonoff.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -sonoff.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -sonoff.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -sonoff.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -sonoff.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -sonoff.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -sonoff.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -sonoff.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -sonoff.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -sonoff.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -sonoff.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -sonoff.menu.lvl.CORE=CORE -sonoff.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -sonoff.menu.lvl.WIFI=WIFI -sonoff.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -sonoff.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -sonoff.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -sonoff.menu.lvl.UPDATER=UPDATER -sonoff.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -sonoff.menu.lvl.OTA=OTA -sonoff.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -sonoff.menu.lvl.OOM=OOM -sonoff.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -sonoff.menu.lvl.MDNS=MDNS -sonoff.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -sonoff.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -sonoff.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -sonoff.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -sonoff.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -sonoff.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -sonoff.menu.wipe.none=Only Sketch -sonoff.menu.wipe.none.upload.erase_cmd= -sonoff.menu.wipe.sdk=Sketch + WiFi Settings -sonoff.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -sonoff.menu.wipe.all=All Flash Contents -sonoff.menu.wipe.all.upload.erase_cmd=erase_flash -sonoff.menu.baud.115200=115200 -sonoff.menu.baud.115200.upload.speed=115200 -sonoff.menu.baud.57600=57600 -sonoff.menu.baud.57600.upload.speed=57600 -sonoff.menu.baud.230400.linux=230400 -sonoff.menu.baud.230400.macosx=230400 -sonoff.menu.baud.230400.upload.speed=230400 -sonoff.menu.baud.256000.windows=256000 -sonoff.menu.baud.256000.upload.speed=256000 -sonoff.menu.baud.460800.linux=460800 -sonoff.menu.baud.460800.macosx=460800 -sonoff.menu.baud.460800.upload.speed=460800 -sonoff.menu.baud.512000.windows=512000 -sonoff.menu.baud.512000.upload.speed=512000 -sonoff.menu.baud.921600=921600 -sonoff.menu.baud.921600.upload.speed=921600 -sonoff.menu.baud.3000000=3000000 -sonoff.menu.baud.3000000.upload.speed=3000000 - -############################################################## -espmxdevkit.name=DOIT ESP-Mx DevKit (ESP8285) -espmxdevkit.build.board=ESP8266_ESP01 -espmxdevkit.build.led=-DLED_BUILTIN=16 -espmxdevkit.build.variant=esp8285 -espmxdevkit.upload.tool=esptool -espmxdevkit.upload.maximum_data_size=81920 -espmxdevkit.upload.wait_for_upload_port=true -espmxdevkit.upload.erase_cmd= -espmxdevkit.serial.disableDTR=true -espmxdevkit.serial.disableRTS=true -espmxdevkit.build.mcu=esp8266 -espmxdevkit.build.core=esp8266 -espmxdevkit.build.spiffs_pagesize=256 -espmxdevkit.build.debug_port= -espmxdevkit.build.debug_level= -espmxdevkit.menu.xtal.80=80 MHz -espmxdevkit.menu.xtal.80.build.f_cpu=80000000L -espmxdevkit.menu.xtal.160=160 MHz -espmxdevkit.menu.xtal.160.build.f_cpu=160000000L -espmxdevkit.menu.vt.flash=Flash -espmxdevkit.menu.vt.flash.build.vtable_flags=-DVTABLES_IN_FLASH -espmxdevkit.menu.vt.heap=Heap -espmxdevkit.menu.vt.heap.build.vtable_flags=-DVTABLES_IN_DRAM -espmxdevkit.menu.vt.iram=IRAM -espmxdevkit.menu.vt.iram.build.vtable_flags=-DVTABLES_IN_IRAM -espmxdevkit.menu.exception.legacy=Legacy (new can return nullptr) -espmxdevkit.menu.exception.legacy.build.exception_flags=-fno-exceptions -espmxdevkit.menu.exception.legacy.build.stdcpp_lib=-lstdc++ -espmxdevkit.menu.exception.disabled=Disabled (new can abort) -espmxdevkit.menu.exception.disabled.build.exception_flags=-fno-exceptions -DNEW_OOM_ABORT -espmxdevkit.menu.exception.disabled.build.stdcpp_lib=-lstdc++ -espmxdevkit.menu.exception.enabled=Enabled -espmxdevkit.menu.exception.enabled.build.exception_flags=-fexceptions -espmxdevkit.menu.exception.enabled.build.stdcpp_lib=-lstdc++-exc -espmxdevkit.menu.ssl.all=All SSL ciphers (most compatible) -espmxdevkit.menu.ssl.all.build.sslflags= -espmxdevkit.menu.ssl.basic=Basic SSL ciphers (lower ROM use) -espmxdevkit.menu.ssl.basic.build.sslflags=-DBEARSSL_SSL_BASIC -espmxdevkit.upload.resetmethod=--before default_reset --after hard_reset -espmxdevkit.build.flash_mode=dout -espmxdevkit.build.flash_flags=-DFLASHMODE_DOUT -espmxdevkit.build.flash_freq=40 -espmxdevkit.menu.eesz.1M64=1MB (FS:64KB OTA:~470KB) -espmxdevkit.menu.eesz.1M64.build.flash_size=1M -espmxdevkit.menu.eesz.1M64.build.flash_size_bytes=0x100000 -espmxdevkit.menu.eesz.1M64.build.flash_ld=eagle.flash.1m64.ld -espmxdevkit.menu.eesz.1M64.build.spiffs_pagesize=256 -espmxdevkit.menu.eesz.1M64.upload.maximum_size=958448 -espmxdevkit.menu.eesz.1M64.build.rfcal_addr=0xFC000 -espmxdevkit.menu.eesz.1M64.build.spiffs_start=0xEB000 -espmxdevkit.menu.eesz.1M64.build.spiffs_end=0xFB000 -espmxdevkit.menu.eesz.1M64.build.spiffs_blocksize=4096 -espmxdevkit.menu.eesz.1M128=1MB (FS:128KB OTA:~438KB) -espmxdevkit.menu.eesz.1M128.build.flash_size=1M -espmxdevkit.menu.eesz.1M128.build.flash_size_bytes=0x100000 -espmxdevkit.menu.eesz.1M128.build.flash_ld=eagle.flash.1m128.ld -espmxdevkit.menu.eesz.1M128.build.spiffs_pagesize=256 -espmxdevkit.menu.eesz.1M128.upload.maximum_size=892912 -espmxdevkit.menu.eesz.1M128.build.rfcal_addr=0xFC000 -espmxdevkit.menu.eesz.1M128.build.spiffs_start=0xDB000 -espmxdevkit.menu.eesz.1M128.build.spiffs_end=0xFB000 -espmxdevkit.menu.eesz.1M128.build.spiffs_blocksize=4096 -espmxdevkit.menu.eesz.1M144=1MB (FS:144KB OTA:~430KB) -espmxdevkit.menu.eesz.1M144.build.flash_size=1M -espmxdevkit.menu.eesz.1M144.build.flash_size_bytes=0x100000 -espmxdevkit.menu.eesz.1M144.build.flash_ld=eagle.flash.1m144.ld -espmxdevkit.menu.eesz.1M144.build.spiffs_pagesize=256 -espmxdevkit.menu.eesz.1M144.upload.maximum_size=876528 -espmxdevkit.menu.eesz.1M144.build.rfcal_addr=0xFC000 -espmxdevkit.menu.eesz.1M144.build.spiffs_start=0xD7000 -espmxdevkit.menu.eesz.1M144.build.spiffs_end=0xFB000 -espmxdevkit.menu.eesz.1M144.build.spiffs_blocksize=4096 -espmxdevkit.menu.eesz.1M160=1MB (FS:160KB OTA:~422KB) -espmxdevkit.menu.eesz.1M160.build.flash_size=1M -espmxdevkit.menu.eesz.1M160.build.flash_size_bytes=0x100000 -espmxdevkit.menu.eesz.1M160.build.flash_ld=eagle.flash.1m160.ld -espmxdevkit.menu.eesz.1M160.build.spiffs_pagesize=256 -espmxdevkit.menu.eesz.1M160.upload.maximum_size=860144 -espmxdevkit.menu.eesz.1M160.build.rfcal_addr=0xFC000 -espmxdevkit.menu.eesz.1M160.build.spiffs_start=0xD3000 -espmxdevkit.menu.eesz.1M160.build.spiffs_end=0xFB000 -espmxdevkit.menu.eesz.1M160.build.spiffs_blocksize=4096 -espmxdevkit.menu.eesz.1M192=1MB (FS:192KB OTA:~406KB) -espmxdevkit.menu.eesz.1M192.build.flash_size=1M -espmxdevkit.menu.eesz.1M192.build.flash_size_bytes=0x100000 -espmxdevkit.menu.eesz.1M192.build.flash_ld=eagle.flash.1m192.ld -espmxdevkit.menu.eesz.1M192.build.spiffs_pagesize=256 -espmxdevkit.menu.eesz.1M192.upload.maximum_size=827376 -espmxdevkit.menu.eesz.1M192.build.rfcal_addr=0xFC000 -espmxdevkit.menu.eesz.1M192.build.spiffs_start=0xCB000 -espmxdevkit.menu.eesz.1M192.build.spiffs_end=0xFB000 -espmxdevkit.menu.eesz.1M192.build.spiffs_blocksize=4096 -espmxdevkit.menu.eesz.1M256=1MB (FS:256KB OTA:~374KB) -espmxdevkit.menu.eesz.1M256.build.flash_size=1M -espmxdevkit.menu.eesz.1M256.build.flash_size_bytes=0x100000 -espmxdevkit.menu.eesz.1M256.build.flash_ld=eagle.flash.1m256.ld -espmxdevkit.menu.eesz.1M256.build.spiffs_pagesize=256 -espmxdevkit.menu.eesz.1M256.upload.maximum_size=761840 -espmxdevkit.menu.eesz.1M256.build.rfcal_addr=0xFC000 -espmxdevkit.menu.eesz.1M256.build.spiffs_start=0xBB000 -espmxdevkit.menu.eesz.1M256.build.spiffs_end=0xFB000 -espmxdevkit.menu.eesz.1M256.build.spiffs_blocksize=4096 -espmxdevkit.menu.eesz.1M512=1MB (FS:512KB OTA:~246KB) -espmxdevkit.menu.eesz.1M512.build.flash_size=1M -espmxdevkit.menu.eesz.1M512.build.flash_size_bytes=0x100000 -espmxdevkit.menu.eesz.1M512.build.flash_ld=eagle.flash.1m512.ld -espmxdevkit.menu.eesz.1M512.build.spiffs_pagesize=256 -espmxdevkit.menu.eesz.1M512.upload.maximum_size=499696 -espmxdevkit.menu.eesz.1M512.build.rfcal_addr=0xFC000 -espmxdevkit.menu.eesz.1M512.build.spiffs_start=0x7B000 -espmxdevkit.menu.eesz.1M512.build.spiffs_end=0xFB000 -espmxdevkit.menu.eesz.1M512.build.spiffs_blocksize=8192 -espmxdevkit.menu.eesz.1M=1MB (FS:none OTA:~502KB) -espmxdevkit.menu.eesz.1M.build.flash_size=1M -espmxdevkit.menu.eesz.1M.build.flash_size_bytes=0x100000 -espmxdevkit.menu.eesz.1M.build.flash_ld=eagle.flash.1m.ld -espmxdevkit.menu.eesz.1M.build.spiffs_pagesize=256 -espmxdevkit.menu.eesz.1M.upload.maximum_size=1023984 -espmxdevkit.menu.eesz.1M.build.rfcal_addr=0xFC000 -espmxdevkit.menu.ip.lm2f=v2 Lower Memory -espmxdevkit.menu.ip.lm2f.build.lwip_include=lwip2/include -espmxdevkit.menu.ip.lm2f.build.lwip_lib=-llwip2-536-feat -espmxdevkit.menu.ip.lm2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espmxdevkit.menu.ip.hb2f=v2 Higher Bandwidth -espmxdevkit.menu.ip.hb2f.build.lwip_include=lwip2/include -espmxdevkit.menu.ip.hb2f.build.lwip_lib=-llwip2-1460-feat -espmxdevkit.menu.ip.hb2f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=0 -espmxdevkit.menu.ip.lm2n=v2 Lower Memory (no features) -espmxdevkit.menu.ip.lm2n.build.lwip_include=lwip2/include -espmxdevkit.menu.ip.lm2n.build.lwip_lib=-llwip2-536 -espmxdevkit.menu.ip.lm2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espmxdevkit.menu.ip.hb2n=v2 Higher Bandwidth (no features) -espmxdevkit.menu.ip.hb2n.build.lwip_include=lwip2/include -espmxdevkit.menu.ip.hb2n.build.lwip_lib=-llwip2-1460 -espmxdevkit.menu.ip.hb2n.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=0 -DLWIP_IPV6=0 -espmxdevkit.menu.ip.lm6f=v2 IPv6 Lower Memory -espmxdevkit.menu.ip.lm6f.build.lwip_include=lwip2/include -espmxdevkit.menu.ip.lm6f.build.lwip_lib=-llwip6-536-feat -espmxdevkit.menu.ip.lm6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espmxdevkit.menu.ip.hb6f=v2 IPv6 Higher Bandwidth -espmxdevkit.menu.ip.hb6f.build.lwip_include=lwip2/include -espmxdevkit.menu.ip.hb6f.build.lwip_lib=-llwip6-1460-feat -espmxdevkit.menu.ip.hb6f.build.lwip_flags=-DLWIP_OPEN_SRC -DTCP_MSS=1460 -DLWIP_FEATURES=1 -DLWIP_IPV6=1 -espmxdevkit.menu.ip.hb1=v1.4 Higher Bandwidth -espmxdevkit.menu.ip.hb1.build.lwip_lib=-llwip_gcc -espmxdevkit.menu.ip.hb1.build.lwip_flags=-DLWIP_OPEN_SRC -espmxdevkit.menu.ip.src=v1.4 Compile from source -espmxdevkit.menu.ip.src.build.lwip_lib=-llwip_src -espmxdevkit.menu.ip.src.build.lwip_flags=-DLWIP_OPEN_SRC -espmxdevkit.menu.ip.src.recipe.hooks.sketch.prebuild.1.pattern=make -C "{runtime.platform.path}/tools/sdk/lwip/src" install TOOLS_PATH="{runtime.tools.xtensa-lx106-elf-gcc.path}/bin/xtensa-lx106-elf-" -espmxdevkit.menu.dbg.Disabled=Disabled -espmxdevkit.menu.dbg.Disabled.build.debug_port= -espmxdevkit.menu.dbg.Serial=Serial -espmxdevkit.menu.dbg.Serial.build.debug_port=-DDEBUG_ESP_PORT=Serial -espmxdevkit.menu.dbg.Serial1=Serial1 -espmxdevkit.menu.dbg.Serial1.build.debug_port=-DDEBUG_ESP_PORT=Serial1 -espmxdevkit.menu.lvl.None____=None -espmxdevkit.menu.lvl.None____.build.debug_level= -espmxdevkit.menu.lvl.SSL=SSL -espmxdevkit.menu.lvl.SSL.build.debug_level= -DDEBUG_ESP_SSL -espmxdevkit.menu.lvl.TLS_MEM=TLS_MEM -espmxdevkit.menu.lvl.TLS_MEM.build.debug_level= -DDEBUG_ESP_TLS_MEM -espmxdevkit.menu.lvl.HTTP_CLIENT=HTTP_CLIENT -espmxdevkit.menu.lvl.HTTP_CLIENT.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -espmxdevkit.menu.lvl.HTTP_SERVER=HTTP_SERVER -espmxdevkit.menu.lvl.HTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_SERVER -espmxdevkit.menu.lvl.SSLTLS_MEM=SSL+TLS_MEM -espmxdevkit.menu.lvl.SSLTLS_MEM.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -espmxdevkit.menu.lvl.SSLHTTP_CLIENT=SSL+HTTP_CLIENT -espmxdevkit.menu.lvl.SSLHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -espmxdevkit.menu.lvl.SSLHTTP_SERVER=SSL+HTTP_SERVER -espmxdevkit.menu.lvl.SSLHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_SERVER -espmxdevkit.menu.lvl.TLS_MEMHTTP_CLIENT=TLS_MEM+HTTP_CLIENT -espmxdevkit.menu.lvl.TLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espmxdevkit.menu.lvl.TLS_MEMHTTP_SERVER=TLS_MEM+HTTP_SERVER -espmxdevkit.menu.lvl.TLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espmxdevkit.menu.lvl.HTTP_CLIENTHTTP_SERVER=HTTP_CLIENT+HTTP_SERVER -espmxdevkit.menu.lvl.HTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENT=SSL+TLS_MEM+HTTP_CLIENT -espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENT.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_SERVER=SSL+TLS_MEM+HTTP_SERVER -espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_SERVER -espmxdevkit.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER=SSL+HTTP_CLIENT+HTTP_SERVER -espmxdevkit.menu.lvl.SSLHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espmxdevkit.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER=TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espmxdevkit.menu.lvl.TLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER -espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVER.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -espmxdevkit.menu.lvl.CORE=CORE -espmxdevkit.menu.lvl.CORE.build.debug_level= -DDEBUG_ESP_CORE -espmxdevkit.menu.lvl.WIFI=WIFI -espmxdevkit.menu.lvl.WIFI.build.debug_level= -DDEBUG_ESP_WIFI -espmxdevkit.menu.lvl.HTTP_UPDATE=HTTP_UPDATE -espmxdevkit.menu.lvl.HTTP_UPDATE.build.debug_level= -DDEBUG_ESP_HTTP_UPDATE -espmxdevkit.menu.lvl.UPDATER=UPDATER -espmxdevkit.menu.lvl.UPDATER.build.debug_level= -DDEBUG_ESP_UPDATER -espmxdevkit.menu.lvl.OTA=OTA -espmxdevkit.menu.lvl.OTA.build.debug_level= -DDEBUG_ESP_OTA -espmxdevkit.menu.lvl.OOM=OOM -espmxdevkit.menu.lvl.OOM.build.debug_level= -DDEBUG_ESP_OOM -espmxdevkit.menu.lvl.MDNS=MDNS -espmxdevkit.menu.lvl.MDNS.build.debug_level= -DDEBUG_ESP_MDNS -espmxdevkit.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espmxdevkit.menu.lvl.COREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS=SSL+TLS_MEM+HTTP_CLIENT+HTTP_SERVER+CORE+WIFI+HTTP_UPDATE+UPDATER+OTA+OOM+MDNS -espmxdevkit.menu.lvl.SSLTLS_MEMHTTP_CLIENTHTTP_SERVERCOREWIFIHTTP_UPDATEUPDATEROTAOOMMDNS.build.debug_level= -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_OOM -DDEBUG_ESP_MDNS -espmxdevkit.menu.lvl.NoAssert-NDEBUG=NoAssert-NDEBUG -espmxdevkit.menu.lvl.NoAssert-NDEBUG.build.debug_level= -DNDEBUG -espmxdevkit.menu.wipe.none=Only Sketch -espmxdevkit.menu.wipe.none.upload.erase_cmd= -espmxdevkit.menu.wipe.sdk=Sketch + WiFi Settings -espmxdevkit.menu.wipe.sdk.upload.erase_cmd=erase_region "{build.rfcal_addr}" 0x4000 -espmxdevkit.menu.wipe.all=All Flash Contents -espmxdevkit.menu.wipe.all.upload.erase_cmd=erase_flash -espmxdevkit.menu.baud.115200=115200 -espmxdevkit.menu.baud.115200.upload.speed=115200 -espmxdevkit.menu.baud.57600=57600 -espmxdevkit.menu.baud.57600.upload.speed=57600 -espmxdevkit.menu.baud.230400.linux=230400 -espmxdevkit.menu.baud.230400.macosx=230400 -espmxdevkit.menu.baud.230400.upload.speed=230400 -espmxdevkit.menu.baud.256000.windows=256000 -espmxdevkit.menu.baud.256000.upload.speed=256000 -espmxdevkit.menu.baud.460800.linux=460800 -espmxdevkit.menu.baud.460800.macosx=460800 -espmxdevkit.menu.baud.460800.upload.speed=460800 -espmxdevkit.menu.baud.512000.windows=512000 -espmxdevkit.menu.baud.512000.upload.speed=512000 -espmxdevkit.menu.baud.921600=921600 -espmxdevkit.menu.baud.921600.upload.speed=921600 -espmxdevkit.menu.baud.3000000=3000000 -espmxdevkit.menu.baud.3000000.upload.speed=3000000 - diff --git a/arduino/version 2.6.1/platform.txt b/arduino/version 2.6.1/platform.txt deleted file mode 100644 index 76c8aba60..000000000 --- a/arduino/version 2.6.1/platform.txt +++ /dev/null @@ -1,171 +0,0 @@ - -# ESP8266 platform -# ------------------------------ - -# For more info: -# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification - -name=ESP8266 Boards (2.6.1) -version=2.6.1 - -# These will be removed by the packager script when doing a JSON release - - - - -runtime.tools.signing={runtime.platform.path}/tools/signing.py -runtime.tools.elf2bin={runtime.platform.path}/tools/elf2bin.py -runtime.tools.sizes={runtime.platform.path}/tools/sizes.py -runtime.tools.makecorever={runtime.platform.path}/tools/makecorever.py -runtime.tools.eboot={runtime.platform.path}/bootloaders/eboot/eboot.elf - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -compiler.warning_flags.more=-Wall -compiler.warning_flags.all=-Wall -Wextra - -build.lwip_lib=-llwip_gcc -build.lwip_include=lwip/include -build.lwip_flags=-DLWIP_OPEN_SRC - -build.vtable_flags=-DVTABLES_IN_FLASH - -build.sslflags= - -build.exception_flags=-fno-exceptions -build.stdcpp_lib=-lstdc++ -build.stdcpp_level=-std=gnu++11 - -#build.float=-u _printf_float -u _scanf_float -build.float= -build.led= - -# default SDK for all boards -# (generic board overrides this variable) -build.sdk=NONOSDK22x_190703 -#build.sdk=NONOSDK22x_191024 -#build.sdk=NONOSDK22x_191105 - -compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/ -compiler.sdk.path={runtime.platform.path}/tools/sdk - -compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf -compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" - -compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} - -compiler.S.cmd=xtensa-lx106-elf-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls - -compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/lib/{build.sdk}" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read - -compiler.c.elf.cmd=xtensa-lx106-elf-gcc -compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc - -compiler.cpp.cmd=xtensa-lx106-elf-g++ -compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} - -compiler.as.cmd=xtensa-lx106-elf-as - -compiler.ar.cmd=xtensa-lx106-elf-ar -compiler.ar.flags=cru - -compiler.elf2hex.cmd=esptool -compiler.elf2hex.flags= - -compiler.size.cmd=xtensa-lx106-elf-size - -# This can be overriden in boards.txt -build.extra_flags=-DESP8266 - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -## generate file with git version number -## needs git -recipe.hooks.sketch.prebuild.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h" -# This is quite a working hack. This form of prebuild hook, while intuitive, is not explicitly documented. - - -## Build the app.ld linker file -recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld" - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -D{build.sdk}=1 -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}" - -## Create eeprom -recipe.objcopy.eep.pattern= - -## Create hex -recipe.objcopy.hex.1.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.elf2bin}" --eboot "{runtime.tools.eboot}" --app "{build.path}/{build.project_name}.elf" --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin" --out "{build.path}/{build.project_name}.bin" -recipe.objcopy.hex.2.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed" --legacy "{build.path}/{build.project_name}.bin.legacy_sig" -recipe.objcopy.hex.3.pattern="{runtime.tools.python3.path}/python3" "{runtime.tools.sizes}" --elf "{build.path}/{build.project_name}.elf" --path "{runtime.tools.xtensa-lx106-elf-gcc.path}/bin" - -## Save hex -recipe.output.tmp_file={build.project_name}.bin -recipe.output.save_file={build.project_name}.{build.variant}.bin - -## Compute size -recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.irom0\.text|\.text|\.text1|\.data|\.rodata|)\s+([0-9]+).* -recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* -#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - -# ------------------------------ - -tools.esptool.path= -# Because the variable expansion doesn't allow one tool to find another, the following lines -# will point to "{runtime.platform.path}/tools/python3/python3" in GIT and -# "{runtime.tools.python3.path}/python3" for JSON board manager releases. -tools.esptool.cmd={runtime.tools.python3.path}/python3 -tools.esptool.network_cmd={runtime.tools.python3.path}/python3 - - - -tools.esptool.upload.protocol=esp -# esptool.py --trace option is a debug option, not a verbose option -tools.esptool.upload.params.verbose= -tools.esptool.upload.params.quiet= - -# First, potentially perform an erase or nothing -# Next, do the binary upload -# Combined in one rule because Arduino doesn't suport upload.1.pattern/upload.3.pattern -tools.esptool.upload.pattern="{cmd}" "{runtime.platform.path}/tools/upload.py" --chip esp8266 --port "{serial.port}" --baud "{upload.speed}" "{upload.verbose}" {upload.erase_cmd} {upload.resetmethod} "{build.path}/{build.project_name}.bin" - -tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin" - -tools.mkspiffs.cmd=mkspiffs -tools.mkspiffs.cmd.windows=mkspiffs.exe -tools.mkspiffs.path={runtime.tools.mkspiffs.path} - -tools.mklittlefs.cmd=mklittlefs -tools.mklittlefs.cmd.windows=mklittlefs.exe -tools.mklittlefs.path={runtime.platform.path}/tools/mklittlefs - -tools.espupload.cmd=python -tools.espupload.cmd.windows=python.exe -tools.espupload.path={runtime.platform.path}/tools -tools.espupload.upload.protocol=espupload -tools.espupload.upload.params.verbose= -tools.espupload.upload.params.quiet= -tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin" From 048474f7ac2534f6edb2c86a92ce895cecdf01d0 Mon Sep 17 00:00:00 2001 From: Staars Date: Fri, 6 Mar 2020 19:22:30 +0100 Subject: [PATCH 556/559] add missing PDU-type, small refactoring --- tasmota/xsns_61_MI_NRF24.ino | 124 ++++++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 25 deletions(-) diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/xsns_61_MI_NRF24.ino index f1db19d74..69a99cb08 100644 --- a/tasmota/xsns_61_MI_NRF24.ino +++ b/tasmota/xsns_61_MI_NRF24.ino @@ -21,6 +21,9 @@ Version yyyymmdd Action Description -------------------------------------------------------------------------------------------- + 0.9.4.0 20200304 integrate - sensor types can be ignored (default for LYWSD03), + add CGD1 (Alarm clock), correct PDU-types for LYWSD02 + --- 0.9.3.0 20200222 integrate - use now the correct id-word instead of MAC-OUI, add CGG1 --- @@ -48,7 +51,7 @@ /*********************************************************************************************\ * MINRF -* BLE-Sniffer/Bridge for MIJIA/XIAOMI Temperatur/Humidity-Sensor, Mi Flora, LYWSD02 +* BLE-Sniffer/Bridge for MIJIA/XIAOMI Temperatur/Humidity-Sensor, Mi Flora, LYWSD02, GCx * * Usage: Configure NRF24 \*********************************************************************************************/ @@ -62,12 +65,19 @@ #define LYWSD02 3 #define LYWSD03 4 #define CGG1 5 +#define CGD1 6 -const uint16_t kMINRFSlaveID[5]={ 0x0098, // Flora +/* define sensors to ignore, which can improve performance + pattern: #define IGNORE_sensorname +*/ +#define IGNORE_LYWSD03 + +const uint16_t kMINRFSlaveID[6]={ 0x0098, // Flora 0x01aa, // MJ_HT_V1 0x045b, // LYWSD02 0x055b, // LYWSD03 - 0x0347 // CGG1 + 0x0347, // CGG1 + 0x0576 // CGD1 }; const char kMINRFSlaveType1[] PROGMEM = "Flora"; @@ -75,19 +85,21 @@ const char kMINRFSlaveType2[] PROGMEM = "MJ_HT_V1"; const char kMINRFSlaveType3[] PROGMEM = "LYWSD02"; const char kMINRFSlaveType4[] PROGMEM = "LYWSD03"; const char kMINRFSlaveType5[] PROGMEM = "CGG1"; -const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4,kMINRFSlaveType5}; +const char kMINRFSlaveType6[] PROGMEM = "CGD1"; +const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMINRFSlaveType3,kMINRFSlaveType4,kMINRFSlaveType5,kMINRFSlaveType6}; // PDU's or different channels 37-39 const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; -const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71da7646}; // 1 and 3 unsure +const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71dafb46}; // const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0xffffffff}; //encrypted - 58 58 const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; //unencrypted - 30 58 -const uint32_t kMINRFCGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; +const uint32_t kMINRFCGGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; +const uint32_t kMINRFCGDPDU[3] = {0x5da0d752,0xc10c16e7,0x29c497c1}; // start-LSFR for different channels 37-39 const uint8_t kMINRFlsfrList_A[3] = {0x4b,0x17,0x23}; // Flora, LYWSD02 -const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03, CGG1 +const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03, CGx #pragma pack(1) // important!! @@ -196,6 +208,15 @@ union LYWSD02Packet_t { // related to the whole 32-byte-packet/buffer } TH; // mode 04 or 06 }; +union CGDPacket_t { // related to the whole 32-byte-packet/buffer + struct { + uint8_t serial[6]; + uint16_t mode; + int16_t temp; // -9 - 59 °C + uint16_t hum; + } TH; // This is no MiBeacon +}; + struct bleAdvPacket_t { // for nRF24L01 max 32 bytes = 2+6+24 uint8_t pduType; uint8_t payloadSize; @@ -254,6 +275,7 @@ union FIFO_t{ floraPacket_t floraPacket; MJ_HT_V1Packet_t MJ_HT_V1Packet; LYWSD02Packet_t LYWSD02Packet; + CGDPacket_t CGDPacket; uint8_t raw[32]; }; @@ -266,7 +288,7 @@ struct { uint16_t timer; uint8_t currentChan=0; FIFO_t buffer; - uint8_t packetMode; // 0 - normal BLE-advertisements, 1 - special "flora"-packet, 2 - special "MJ_HT_V1"-packet + uint8_t packetMode; // 0 - normal BLE-advertisements, 1 - 6 "special" sensor packets #ifdef DEBUG_TASMOTA_SENSOR uint8_t streamBuffer[sizeof(buffer)]; // raw data stream bytes @@ -276,10 +298,10 @@ struct { } MINRF; struct mi_sensor_t{ - uint8_t type; //Flora = 1; MJ_HT_V1=2; LYWSD02=3; LYWSD03=4; ; CGG1=5 + uint8_t type; //Flora = 1; MJ_HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6 uint8_t serial[6]; uint8_t showedUp; - float temp; //Flora, MJ_HT_V1, LYWSD0x + float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx union { struct { float moisture; @@ -289,7 +311,7 @@ struct mi_sensor_t{ struct { float hum; uint8_t bat; - }; // MJ_HT_V1, LYWSD0x + }; // MJ_HT_V1, LYWSD0x, CGx }; }; @@ -372,6 +394,9 @@ bool MINRFreceivePacket(void) case 5: MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); // "CGG1" mode break; + case 6: + MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), kMINRFlsfrList_B[MINRF.currentChan]); // "CGD1" mode + break; } // DEBUG_SENSOR_LOG(PSTR("MINRF: LSFR:%x"),_lsfr); // if (_lsfr>254) _lsfr=0; @@ -481,7 +506,10 @@ void MINRFchangePacketModeTo(uint8_t _mode) { NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]);// 95 fe 58 30 -> LYWSD03 (= no data message) break; case 5: // special CGG1 packet - NRF24radio.openReadingPipe(0,kMINRFCGPDU[_nextchannel]); // 95 fe 50 30 -> CGG1 + NRF24radio.openReadingPipe(0,kMINRFCGGPDU[_nextchannel]); // 95 fe 50 30 -> CGG1 + break; + case 6: // special CGD1 packet + NRF24radio.openReadingPipe(0,kMINRFCGDPDU[_nextchannel]); // cd fd 08 0c -> CGD1 break; } // DEBUG_SENSOR_LOG(PSTR("MINRF: Change Mode to %u"),_mode); @@ -499,7 +527,7 @@ uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ DEBUG_SENSOR_LOG(PSTR("MINRF: will test ID-type: %x"), _type); bool _success = false; - for (uint32_t i=0;i<5;i++){ + for (uint32_t i=0;i<6;i++){ // i < sizeof(kMINRFSlaveID) gives compiler warning if(_type == kMINRFSlaveID[i]){ DEBUG_SENSOR_LOG(PSTR("MINRF: ID is type %u"), i); _type = i+1; @@ -536,9 +564,9 @@ uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){ _newSensor.fertility =-1000.0f; _newSensor.lux = 0x00ffffff; break; - case 2: case 3: case 4: + case 2: case 3: case 4: case 5: case 6: _newSensor.hum=-1.0f; - _newSensor.bat=0xff; + _newSensor.bat=0x00; break; default: break; @@ -574,7 +602,7 @@ void MINRFhandleFloraPacket(void){ DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot); if(_slot==0xff) return; - static float _tempFloat; + float _tempFloat; switch(MINRF.buffer.floraPacket.L.mode) { // we can use any struct with a mode, they are all same at this point case 4: _tempFloat=(float)(MINRF.buffer.floraPacket.T.data)/10.0f; @@ -617,7 +645,7 @@ void MINRFhandleMJ_HT_V1Packet(void){ DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot); if(_slot==0xff) return; - static float _tempFloat; + float _tempFloat; switch(MINRF.buffer.MJ_HT_V1Packet.TH.mode) { // we can use any struct with a mode, they are all same at this point case 0x0d: _tempFloat=(float)(MINRF.buffer.MJ_HT_V1Packet.TH.temp)/10.0f; @@ -653,7 +681,7 @@ void MINRFhandleLYWSD02Packet(void){ DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot); if(_slot==0xff) return; - static float _tempFloat; + float _tempFloat; switch(MINRF.buffer.LYWSD02Packet.TH.mode) { // we can use any struct with a mode, they are all same at this point case 4: _tempFloat=(float)(MINRF.buffer.LYWSD02Packet.TH.data)/10.0f; @@ -695,7 +723,7 @@ void MINRFhandleCGG1Packet(void){ // we assume, that the packet structure is equ DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot); if(_slot==0xff) return; - static float _tempFloat; + float _tempFloat; switch(MINRF.buffer.MJ_HT_V1Packet.TH.mode) { // we can use any struct with a mode, they are all same at this point case 0x0d: _tempFloat=(float)(MINRF.buffer.MJ_HT_V1Packet.TH.temp)/10.0f; @@ -720,6 +748,31 @@ void MINRFhandleCGG1Packet(void){ // we assume, that the packet structure is equ } } +void MINRFhandleCGD1Packet(void){ // + if(MINRF.buffer.CGDPacket.TH.mode!=0x0401){ // not really a mode + DEBUG_SENSOR_LOG(PSTR("MINRF: unexpected CGD1-packet")); + MINRF_LOG_BUFFER(MINRF.buffer.raw); + return; + } + MINRFreverseMAC(MINRF.buffer.CGDPacket.TH.serial); + uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.CGDPacket.TH.serial, 0x0576); // This must be hard-coded, no object-id in Cleargrass-packet + DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot); + if(_slot==0xff) return; + + float _tempFloat; + _tempFloat=(float)(MINRF.buffer.CGDPacket.TH.temp)/10.0f; + if(_tempFloat<60){ + MIBLEsensors.at(_slot).temp = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated")); + } + _tempFloat=(float)(MINRF.buffer.CGDPacket.TH.hum)/10.0f; + if(_tempFloat<100){ + MIBLEsensors.at(_slot).hum = _tempFloat; + DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated")); + } + DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), MINRF.buffer.CGDPacket.TH.temp, MINRF.buffer.CGDPacket.TH.hum); +} + /*********************************************************************************************\ * Main loop of the driver \*********************************************************************************************/ @@ -769,11 +822,32 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds else if (MINRF.packetMode == CGG1){ MINRFhandleCGG1Packet(); } - if (MINRF.packetMode == CGG1){ - MINRFinitBLE(1); // no real ble packets in release mode, otherwise for developing use 0 + else if (MINRF.packetMode == CGD1){ + MINRFhandleCGD1Packet(); } - else { - MINRFinitBLE(++MINRF.packetMode); + +#ifdef IGNORE_FLORA + if (MINRF.packetMode+1 == FLORA) MINRF.packetMode++; +#endif // IGNORE_LYWSD03 +#ifdef IGNORE_MJ_HT_V1 + if (MINRF.packetMode+1 == MJ_HT_V1) MINRF.packetMode++; +#endif //IGNORE_MJ_HT_V1 +#ifdef IGNORE_LYWSD02 + if (MINRF.packetMode+1 == LYWSD02) MINRF.packetMode++; +#endif // IGNORE_LYWSD02 +#ifdef IGNORE_LYWSD03 + if (MINRF.packetMode+1 == LYWSD03) MINRF.packetMode++; +#endif // IGNORE_LYWSD03 +#ifdef IGNORE_CGG1 + if (MINRF.packetMode+1 == CGG1) MINRF.packetMode++; +#endif // IGNORE_CGG1 +#ifdef IGNORE_CGD1 + if (MINRF.packetMode+1 == CGD1) MINRF.packetMode=0; +#endif // IGNORE_CGD1 + MINRFinitBLE(++MINRF.packetMode); + +if (MINRF.packetMode > CGD1){ + MINRFinitBLE(1); // no real ble packets in release mode, otherwise for developing use 0 } MINRFhopChannel(); @@ -828,7 +902,7 @@ void MINRFShow(bool json) if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity); } - if(MIBLEsensors.at(i).bat!=0xff){ // this is the error code -> no battery + if(MIBLEsensors.at(i).bat!=0x00){ // this is the error code -> no battery ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat); } } @@ -868,7 +942,7 @@ void MINRFShow(bool json) dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity); WSContentSend_PD(HTTP_SNS_HUM, kMINRFSlaveType[MIBLEsensors.at(i).type-1], humidity); } - if(MIBLEsensors.at(i).bat!=0xff){ + if(MIBLEsensors.at(i).bat!=0x00){ // without "juice" nothing can be done WSContentSend_PD(HTTP_BATTERY, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat); } } From cd14bde1f709224802ab18f25e32f8381dfc48f7 Mon Sep 17 00:00:00 2001 From: Alexander Schliebner Date: Fri, 6 Mar 2020 21:13:12 +0100 Subject: [PATCH 557/559] Update xdrv_10_scripter.ino MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added mapping function `mp` ´´´ mp(x str1 str2 ... str) ´´´ It addresses a standard task with less code and much flexibility: mapping an arbitrary incoming numeric value into the allowed range. The numeric value `x` passed as the first parameter is compared to the rules in the order they are provided as subsequent sting parameters. If the value matches the criteria, the defined value is returned. Subsequent rules are skipped. If `x` matches none of the rules, `x` is returned unchanged. Rules consist of one of the comparison operators `< > =` followed by a numeric value `v1`, optionally followed by a colon and another numeric value `v2`. ``` <|>|=v1[:v2] ``` Example 1: `"<8:0"` - this rule reads: If x is less than 8, return 0. Example 2: `">100"` - this rule reads: If x is greater than 100, return 100. Example 3: ``` y=mp(x "<8:0" ">100") ``` Assigns 0 to y if x is less than 8. Assigns 100 to y if x is greater than 100. Assigns x to y for all values of x that do not meet the above criteria (8 to 100). The above code of example 3 does the same as the following code - with just one line of code and 15 characters less: ``` y=x if x<8 { y=0 } if x>100 { y=100 } ``` --- tasmota/xdrv_10_scripter.ino | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index d850dfaea..074e32baa 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1496,6 +1496,40 @@ chknext: fvar=!global_state.mqtt_down; goto exit; } + if (!strncmp(vname,"mp(",3)) { + lp+=3; + float fvar1; + lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); + SCRIPT_SKIP_SPACES + while (*lp!=')') { + char str[SCRIPT_MAXSSIZE]; + lp=GetStringResult(lp,OPER_EQU,str,0); + SCRIPT_SKIP_SPACES + char *pstr=str; + pstr++; + float fvar2; + pstr=GetNumericResult(pstr,OPER_EQU,&fvar2,0); + while (*pstr==' ') pstr++; + fvar=fvar1; + if ((str[0]=='<' && fvar1' && fvar1>fvar2) || + (str[0]=='=' && fvar1==fvar2)) + { + if (*pstr==':') { + pstr++; + while (*pstr==' ') pstr++; + float fvar3; + pstr=GetNumericResult(pstr,OPER_EQU,&fvar3,0); + fvar=fvar3; + } else { + fvar=fvar2; + } + break; + } + } + len=0; + goto exit; + } break; case 'p': if (!strncmp(vname,"pin[",4)) { From 7df46f051d58fe64148d5c97d0677178a37b57fe Mon Sep 17 00:00:00 2001 From: Alexander Schliebner Date: Sat, 7 Mar 2020 16:53:49 +0100 Subject: [PATCH 558/559] Optimized function 'mp' Leaner syntax of function `mp` and simplified implementation. New documentation: Mapping function `mp` It addresses a standard task with less code and much flexibility: mapping an arbitrary incoming numeric value into a defined schema of allowed/reasonable ranges. The numeric value `x` passed as the first parameter is compared to the mprules in the order they are provided as subsequent parameters. If the value matches the criteria, the defined value is returned. Subsequent mprules are skipped. If `x` matches none of the mprules, `x` is returned unchanged. ``` mp(x mprule1 mprule2 ... mprule) ``` An mprule starts with one of the comparison operators `<`, `>` or `=`, followed by a numeric value `v1`, optionally followed by a second numeric value `v2`: ``` <|>|=v1[ v2] ``` Example 1: `<8 0` - this rule reads: If x is less than 8, return 0. Example 2: `>100` - this rule reads: If x is greater than 100, return 100. Example 3: ``` y=mp(x <8 0 >100) ``` Assigns 0 to y if x is less than 8. Assigns 100 to y if x is greater than 100. Assigns x to y for all values of x that do not meet the above criteria (8 to 100). The above code of example 3 does the same as the following code - with just one line of code and 19 characters less: ``` y=x if x<8 { y=0 } if x>100 { y=100 } ``` Every of the above mentioned numeric values `x`, `v1` and `v2` can be a literal, an expression or a variable. --- tasmota/xdrv_10_scripter.ino | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 074e32baa..be65a3e37 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1502,30 +1502,27 @@ chknext: lp=GetNumericResult(lp,OPER_EQU,&fvar1,0); SCRIPT_SKIP_SPACES while (*lp!=')') { - char str[SCRIPT_MAXSSIZE]; - lp=GetStringResult(lp,OPER_EQU,str,0); - SCRIPT_SKIP_SPACES - char *pstr=str; - pstr++; + char *opp=lp; + lp++; float fvar2; - pstr=GetNumericResult(pstr,OPER_EQU,&fvar2,0); - while (*pstr==' ') pstr++; + lp=GetNumericResult(lp,OPER_EQU,&fvar2,0); + SCRIPT_SKIP_SPACES fvar=fvar1; - if ((str[0]=='<' && fvar1' && fvar1>fvar2) || - (str[0]=='=' && fvar1==fvar2)) + if ((*opp=='<' && fvar1' && fvar1>fvar2) || + (*opp=='=' && fvar1==fvar2)) { - if (*pstr==':') { - pstr++; - while (*pstr==' ') pstr++; + if (*lp!='<' && *lp!='>' && *lp!='=') { float fvar3; - pstr=GetNumericResult(pstr,OPER_EQU,&fvar3,0); + lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); + SCRIPT_SKIP_SPACES fvar=fvar3; } else { fvar=fvar2; } break; } + while (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) lp++; } len=0; goto exit; From 2335f2fedd0b592bdbb4fb2e23a0ad56ca3730c0 Mon Sep 17 00:00:00 2001 From: Alexander Schliebner Date: Sat, 7 Mar 2020 18:52:24 +0100 Subject: [PATCH 559/559] Bugfix in function 'mp' If optional parameter v2 was omitted, evaluation failed. --- tasmota/xdrv_10_scripter.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index be65a3e37..30ed26598 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -1512,7 +1512,7 @@ chknext: (*opp=='>' && fvar1>fvar2) || (*opp=='=' && fvar1==fvar2)) { - if (*lp!='<' && *lp!='>' && *lp!='=') { + if (*lp!='<' && *lp!='>' && *lp!='=' && *lp!=')' && *lp!=SCRIPT_EOL) { float fvar3; lp=GetNumericResult(lp,OPER_EQU,&fvar3,0); SCRIPT_SKIP_SPACES
, {m} = , {e} =